summaryrefslogtreecommitdiff
path: root/chromium/net
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net')
-rw-r--r--chromium/net/BUILD.gn534
-rw-r--r--chromium/net/DEPS6
-rw-r--r--chromium/net/android/BUILD.gn41
-rw-r--r--chromium/net/android/http_auth_negotiate_android.cc1
-rw-r--r--chromium/net/android/http_auth_negotiate_android.h1
-rw-r--r--chromium/net/android/http_auth_negotiate_android_unittest.cc5
-rw-r--r--chromium/net/android/keystore_openssl.cc1
-rw-r--r--chromium/net/android/keystore_unittest.cc20
-rw-r--r--chromium/net/android/legacy_openssl.h5
-rw-r--r--chromium/net/android/network_change_notifier_android.cc18
-rw-r--r--chromium/net/android/network_change_notifier_android.h3
-rw-r--r--chromium/net/android/network_change_notifier_delegate_android.cc9
-rw-r--r--chromium/net/android/network_change_notifier_delegate_android.h5
-rw-r--r--chromium/net/android/network_library.h13
-rw-r--r--chromium/net/android/traffic_stats_unittest.cc8
-rw-r--r--chromium/net/base/OWNERS1
-rw-r--r--chromium/net/base/address_family.cc5
-rw-r--r--chromium/net/base/address_family.h5
-rw-r--r--chromium/net/base/address_list.cc7
-rw-r--r--chromium/net/base/address_list.h5
-rw-r--r--chromium/net/base/address_list_unittest.cc11
-rw-r--r--chromium/net/base/address_tracker_linux.cc26
-rw-r--r--chromium/net/base/address_tracker_linux.h4
-rw-r--r--chromium/net/base/address_tracker_linux_unittest.cc70
-rw-r--r--chromium/net/base/chunked_upload_data_stream.cc24
-rw-r--r--chromium/net/base/chunked_upload_data_stream.h44
-rw-r--r--chromium/net/base/chunked_upload_data_stream_unittest.cc22
-rw-r--r--chromium/net/base/data_url.cc17
-rw-r--r--chromium/net/base/dir_header.html84
-rw-r--r--chromium/net/base/directory_lister.cc21
-rw-r--r--chromium/net/base/directory_lister.h6
-rw-r--r--chromium/net/base/directory_lister_unittest.cc5
-rw-r--r--chromium/net/base/directory_listing.cc21
-rw-r--r--chromium/net/base/directory_listing_unittest.cc56
-rw-r--r--chromium/net/base/escape.cc5
-rw-r--r--chromium/net/base/escape.h26
-rw-r--r--chromium/net/base/escape_unittest.cc335
-rw-r--r--chromium/net/base/file_stream.h1
-rw-r--r--chromium/net/base/file_stream_context_win.cc3
-rw-r--r--chromium/net/base/filename_util.cc3
-rw-r--r--chromium/net/base/filename_util_internal.cc7
-rw-r--r--chromium/net/base/filename_util_unittest.cc9
-rw-r--r--chromium/net/base/fuzzer_test_support.cc25
-rw-r--r--chromium/net/base/hash_value.cc2
-rw-r--r--chromium/net/base/host_mapping_rules.cc2
-rw-r--r--chromium/net/base/host_port_pair.cc3
-rw-r--r--chromium/net/base/host_port_pair_unittest.cc7
-rw-r--r--chromium/net/base/io_buffer.h1
-rw-r--r--chromium/net/base/ip_address.cc160
-rw-r--r--chromium/net/base/ip_address.h133
-rw-r--r--chromium/net/base/ip_address_number.cc63
-rw-r--r--chromium/net/base/ip_address_number.h26
-rw-r--r--chromium/net/base/ip_address_number_unittest.cc154
-rw-r--r--chromium/net/base/ip_address_unittest.cc269
-rw-r--r--chromium/net/base/ip_endpoint.cc15
-rw-r--r--chromium/net/base/ip_endpoint.h15
-rw-r--r--chromium/net/base/ip_endpoint_unittest.cc12
-rw-r--r--chromium/net/base/ip_pattern.cc10
-rw-r--r--chromium/net/base/ip_pattern.h5
-rw-r--r--chromium/net/base/ip_pattern_unittest.cc14
-rw-r--r--chromium/net/base/keygen_handler_mac.cc14
-rw-r--r--chromium/net/base/keygen_handler_openssl.cc106
-rw-r--r--chromium/net/base/keygen_handler_unittest.cc115
-rw-r--r--chromium/net/base/keygen_handler_win.cc3
-rw-r--r--chromium/net/base/layered_network_delegate.cc27
-rw-r--r--chromium/net/base/layered_network_delegate.h15
-rw-r--r--chromium/net/base/layered_network_delegate_unittest.cc30
-rw-r--r--chromium/net/base/linked_hash_map.h6
-rw-r--r--chromium/net/base/load_flags_list.h4
-rw-r--r--chromium/net/base/load_timing_info.cc2
-rw-r--r--chromium/net/base/load_timing_info.h1
-rw-r--r--chromium/net/base/mime_sniffer_fuzzer.cc52
-rw-r--r--chromium/net/base/net_error_details.h17
-rw-r--r--chromium/net/base/net_error_list.h6
-rw-r--r--chromium/net/base/net_info_source_list.h2
-rw-r--r--chromium/net/base/net_util.cc375
-rw-r--r--chromium/net/base/net_util.h110
-rw-r--r--chromium/net/base/net_util_unittest.cc492
-rw-r--r--chromium/net/base/network_change_notifier.cc19
-rw-r--r--chromium/net/base/network_change_notifier.h27
-rw-r--r--chromium/net/base/network_change_notifier_linux.cc19
-rw-r--r--chromium/net/base/network_change_notifier_linux.h1
-rw-r--r--chromium/net/base/network_change_notifier_win.cc2
-rw-r--r--chromium/net/base/network_delegate.cc34
-rw-r--r--chromium/net/base/network_delegate.h38
-rw-r--r--chromium/net/base/network_delegate_impl.cc10
-rw-r--r--chromium/net/base/network_delegate_impl.h26
-rw-r--r--chromium/net/base/network_interfaces.cc38
-rw-r--r--chromium/net/base/network_interfaces.h10
-rw-r--r--chromium/net/base/network_interfaces_linux.cc5
-rw-r--r--chromium/net/base/network_interfaces_mac.cc1
-rw-r--r--chromium/net/base/network_interfaces_unittest.cc67
-rw-r--r--chromium/net/base/network_interfaces_win.cc22
-rw-r--r--chromium/net/base/network_quality_estimator.cc281
-rw-r--r--chromium/net/base/network_quality_estimator.h165
-rw-r--r--chromium/net/base/network_quality_estimator_unittest.cc268
-rw-r--r--chromium/net/base/openssl_private_key_store_android.cc54
-rw-r--r--chromium/net/base/parse_data_url_fuzzer.cc19
-rw-r--r--chromium/net/base/parse_ip_pattern_fuzzer.cc16
-rw-r--r--chromium/net/base/parse_number.cc23
-rw-r--r--chromium/net/base/parse_number.h68
-rw-r--r--chromium/net/base/parse_number_unittest.cc71
-rw-r--r--chromium/net/base/port_util.cc1
-rw-r--r--chromium/net/base/prioritized_dispatcher.cc2
-rw-r--r--chromium/net/base/prioritized_dispatcher.h1
-rw-r--r--chromium/net/base/proxy_delegate.h15
-rw-r--r--chromium/net/base/registry_controlled_domains/effective_tld_names.dat625
-rw-r--r--chromium/net/base/registry_controlled_domains/effective_tld_names.gperf43
-rw-r--r--chromium/net/base/registry_controlled_domains/get_domain_and_registry_fuzzer.cc25
-rw-r--r--chromium/net/base/registry_controlled_domains/registry_controlled_domain.cc53
-rw-r--r--chromium/net/base/registry_controlled_domains/registry_controlled_domain.h16
-rw-r--r--chromium/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc18
-rw-r--r--chromium/net/base/sdch_manager.cc5
-rw-r--r--chromium/net/base/socket_performance_watcher.cc34
-rw-r--r--chromium/net/base/socket_performance_watcher.h46
-rw-r--r--chromium/net/base/socket_performance_watcher_factory.h12
-rw-r--r--chromium/net/base/test_proxy_delegate.cc87
-rw-r--r--chromium/net/base/test_proxy_delegate.h87
-rw-r--r--chromium/net/base/unescape_url_component_fuzzer.cc22
-rw-r--r--chromium/net/base/unescape_url_component_fuzzer.dict63
-rw-r--r--chromium/net/base/unescape_url_component_fuzzer.options2
-rw-r--r--chromium/net/base/url_util.cc303
-rw-r--r--chromium/net/base/url_util.h85
-rw-r--r--chromium/net/base/url_util_unittest.cc348
-rw-r--r--chromium/net/cert/asn1_util.cc2
-rw-r--r--chromium/net/cert/cert_database.cc6
-rw-r--r--chromium/net/cert/cert_database_android.cc3
-rw-r--r--chromium/net/cert/cert_database_win.cc2
-rw-r--r--chromium/net/cert/cert_verify_proc.cc219
-rw-r--r--chromium/net/cert/cert_verify_proc_blacklist.inc154
-rw-r--r--chromium/net/cert/cert_verify_proc_ios.cc239
-rw-r--r--chromium/net/cert/cert_verify_proc_ios.h36
-rw-r--r--chromium/net/cert/cert_verify_proc_mac.cc7
-rw-r--r--chromium/net/cert/cert_verify_proc_nss.cc119
-rw-r--r--chromium/net/cert/cert_verify_proc_unittest.cc232
-rw-r--r--chromium/net/cert/cert_verify_proc_whitelist.cc744
-rw-r--r--chromium/net/cert/cert_verify_proc_win.cc492
-rw-r--r--chromium/net/cert/cert_verify_result.cc2
-rw-r--r--chromium/net/cert/cert_verify_result.h3
-rw-r--r--chromium/net/cert/client_cert_verifier.h42
-rw-r--r--chromium/net/cert/crl_set_storage.cc5
-rw-r--r--chromium/net/cert/ct_known_logs_static.h15
-rw-r--r--chromium/net/cert/ct_log_response_parser.cc4
-rw-r--r--chromium/net/cert/ct_log_response_parser_unittest.cc18
-rw-r--r--chromium/net/cert/ct_log_verifier.cc16
-rw-r--r--chromium/net/cert/ct_log_verifier_openssl.cc11
-rw-r--r--chromium/net/cert/ct_log_verifier_unittest.cc16
-rw-r--r--chromium/net/cert/ct_objects_extractor_openssl.cc2
-rw-r--r--chromium/net/cert/ct_policy_enforcer.cc244
-rw-r--r--chromium/net/cert/ct_policy_enforcer.h85
-rw-r--r--chromium/net/cert/ct_policy_enforcer_unittest.cc219
-rw-r--r--chromium/net/cert/ct_policy_status.h57
-rw-r--r--chromium/net/cert/ct_serialization.cc101
-rw-r--r--chromium/net/cert/ct_verify_result.cc10
-rw-r--r--chromium/net/cert/ct_verify_result.h20
-rw-r--r--chromium/net/cert/ev_root_ca_metadata.cc991
-rw-r--r--chromium/net/cert/ev_root_ca_metadata.h8
-rw-r--r--chromium/net/cert/internal/certificate_policies.cc7
-rw-r--r--chromium/net/cert/internal/extended_key_usage_unittest.cc4
-rw-r--r--chromium/net/cert/internal/name_constraints.cc299
-rw-r--r--chromium/net/cert/internal/name_constraints.h80
-rw-r--r--chromium/net/cert/internal/name_constraints_unittest.cc608
-rw-r--r--chromium/net/cert/internal/nist_pkits_unittest.h54
-rw-r--r--chromium/net/cert/internal/parse_certificate.cc49
-rw-r--r--chromium/net/cert/internal/parse_certificate.h27
-rw-r--r--chromium/net/cert/internal/parse_name.cc332
-rw-r--r--chromium/net/cert/internal/parse_name.h102
-rw-r--r--chromium/net/cert/internal/parse_name_unittest.cc248
-rw-r--r--chromium/net/cert/internal/parse_ocsp.cc532
-rw-r--r--chromium/net/cert/internal/parse_ocsp.h282
-rw-r--r--chromium/net/cert/internal/parse_ocsp_unittest.cc177
-rw-r--r--chromium/net/cert/internal/signature_algorithm.cc102
-rw-r--r--chromium/net/cert/internal/signature_algorithm.h15
-rw-r--r--chromium/net/cert/internal/signature_algorithm_unittest.cc27
-rw-r--r--chromium/net/cert/internal/signature_policy.h3
-rw-r--r--chromium/net/cert/internal/test_helpers.cc4
-rw-r--r--chromium/net/cert/internal/test_helpers.h4
-rw-r--r--chromium/net/cert/internal/verify_certificate_chain.cc106
-rw-r--r--chromium/net/cert/internal/verify_certificate_chain.h1
-rw-r--r--chromium/net/cert/internal/verify_certificate_chain_pkits_unittest.cc223
-rw-r--r--chromium/net/cert/internal/verify_name_match.cc241
-rw-r--r--chromium/net/cert/internal/verify_signed_data.cc9
-rw-r--r--chromium/net/cert/internal/verify_signed_data_unittest.cc16
-rw-r--r--chromium/net/cert/jwk_serializer_nss.cc1
-rw-r--r--chromium/net/cert/jwk_serializer_openssl.cc11
-rw-r--r--chromium/net/cert/mock_client_cert_verifier.cc40
-rw-r--r--chromium/net/cert/mock_client_cert_verifier.h52
-rw-r--r--chromium/net/cert/multi_log_ct_verifier_unittest.cc51
-rw-r--r--chromium/net/cert/multi_threaded_cert_verifier.cc27
-rw-r--r--chromium/net/cert/multi_threaded_cert_verifier.h1
-rw-r--r--chromium/net/cert/nss_cert_database.cc9
-rw-r--r--chromium/net/cert/nss_cert_database.h2
-rw-r--r--chromium/net/cert/nss_profile_filter_chromeos.cc3
-rw-r--r--chromium/net/cert/sha256_legacy_support_win.cc217
-rw-r--r--chromium/net/cert/sha256_legacy_support_win.h49
-rw-r--r--chromium/net/cert/sha256_legacy_support_win_unittest.cc52
-rw-r--r--chromium/net/cert/signed_tree_head.cc49
-rw-r--r--chromium/net/cert/signed_tree_head.h17
-rw-r--r--chromium/net/cert/sth_distributor.cc49
-rw-r--r--chromium/net/cert/sth_distributor.h42
-rw-r--r--chromium/net/cert/sth_observer.h31
-rw-r--r--chromium/net/cert/sth_reporter.h31
-rw-r--r--chromium/net/cert/test_root_certs.h6
-rw-r--r--chromium/net/cert/test_root_certs_mac.cc33
-rw-r--r--chromium/net/cert/test_root_certs_unittest.cc4
-rw-r--r--chromium/net/cert/x509_cert_types.cc5
-rw-r--r--chromium/net/cert/x509_cert_types_mac.cc7
-rw-r--r--chromium/net/cert/x509_cert_types_unittest.cc78
-rw-r--r--chromium/net/cert/x509_cert_types_win.cc3
-rw-r--r--chromium/net/cert/x509_certificate.cc23
-rw-r--r--chromium/net/cert/x509_certificate.h35
-rw-r--r--chromium/net/cert/x509_certificate_known_roots_win.h28
-rw-r--r--chromium/net/cert/x509_certificate_mac.cc7
-rw-r--r--chromium/net/cert/x509_certificate_nss.cc5
-rw-r--r--chromium/net/cert/x509_certificate_openssl_ios.cc474
-rw-r--r--chromium/net/cert/x509_certificate_unittest.cc24
-rw-r--r--chromium/net/cert/x509_certificate_win.cc3
-rw-r--r--chromium/net/cert/x509_util.cc3
-rw-r--r--chromium/net/cert/x509_util.h6
-rw-r--r--chromium/net/cert/x509_util_ios.cc9
-rw-r--r--chromium/net/cert/x509_util_ios.h3
-rw-r--r--chromium/net/cert/x509_util_mac.cc7
-rw-r--r--chromium/net/cert/x509_util_mac.h7
-rw-r--r--chromium/net/cert/x509_util_nss.cc6
-rw-r--r--chromium/net/cert/x509_util_nss.h39
-rw-r--r--chromium/net/cert/x509_util_nss_certs.cc72
-rw-r--r--chromium/net/cert/x509_util_openssl.cc56
-rw-r--r--chromium/net/cert/x509_util_unittest.cc512
-rw-r--r--chromium/net/cookies/canonical_cookie.cc139
-rw-r--r--chromium/net/cookies/canonical_cookie.h44
-rw-r--r--chromium/net/cookies/canonical_cookie_unittest.cc388
-rw-r--r--chromium/net/cookies/cookie_constants.cc17
-rw-r--r--chromium/net/cookies/cookie_constants.h16
-rw-r--r--chromium/net/cookies/cookie_monster.cc1181
-rw-r--r--chromium/net/cookies/cookie_monster.h288
-rw-r--r--chromium/net/cookies/cookie_monster_perftest.cc21
-rw-r--r--chromium/net/cookies/cookie_monster_store_test.cc68
-rw-r--r--chromium/net/cookies/cookie_monster_store_test.h62
-rw-r--r--chromium/net/cookies/cookie_monster_unittest.cc1586
-rw-r--r--chromium/net/cookies/cookie_options.cc3
-rw-r--r--chromium/net/cookies/cookie_options.h30
-rw-r--r--chromium/net/cookies/cookie_store.cc64
-rw-r--r--chromium/net/cookies/cookie_store.h119
-rw-r--r--chromium/net/cookies/cookie_store_test_callbacks.cc33
-rw-r--r--chromium/net/cookies/cookie_store_test_callbacks.h30
-rw-r--r--chromium/net/cookies/cookie_store_test_helpers.cc71
-rw-r--r--chromium/net/cookies/cookie_store_test_helpers.h40
-rw-r--r--chromium/net/cookies/cookie_store_unittest.cc65
-rw-r--r--chromium/net/cookies/cookie_store_unittest.h1445
-rw-r--r--chromium/net/cookies/cookie_util.cc2
-rw-r--r--chromium/net/cookies/parse_cookie_line_fuzzer.cc15
-rw-r--r--chromium/net/cookies/parsed_cookie.cc39
-rw-r--r--chromium/net/cookies/parsed_cookie.h10
-rw-r--r--chromium/net/cookies/parsed_cookie_unittest.cc74
-rw-r--r--chromium/net/data/name_constraints_unittest/directoryname-excludeall.pem26
-rw-r--r--chromium/net/data/name_constraints_unittest/directoryname-excluded.pem27
-rw-r--r--chromium/net/data/name_constraints_unittest/directoryname.pem111
-rw-r--r--chromium/net/data/name_constraints_unittest/directoryname_and_dnsname.pem147
-rw-r--r--chromium/net/data/name_constraints_unittest/directoryname_and_dnsname_and_ipaddress.pem195
-rwxr-xr-xchromium/net/data/name_constraints_unittest/generate_name_constraints.py4
-rw-r--r--chromium/net/data/name_constraints_unittest/san-edipartyname.pem6
-rw-r--r--chromium/net/data/name_constraints_unittest/san-excluded-directoryname.pem34
-rw-r--r--chromium/net/data/name_constraints_unittest/san-excluded-dnsname.pem17
-rw-r--r--chromium/net/data/name_constraints_unittest/san-excluded-ipaddress.pem17
-rw-r--r--chromium/net/data/name_constraints_unittest/san-invalid-empty.pem4
-rw-r--r--chromium/net/data/name_constraints_unittest/san-invalid-ipaddress.pem5
-rw-r--r--chromium/net/data/name_constraints_unittest/san-othername.pem7
-rw-r--r--chromium/net/data/name_constraints_unittest/san-permitted.pem16
-rw-r--r--chromium/net/data/name_constraints_unittest/san-registeredid.pem5
-rw-r--r--chromium/net/data/name_constraints_unittest/san-rfc822name.pem5
-rw-r--r--chromium/net/data/name_constraints_unittest/san-uri.pem5
-rw-r--r--chromium/net/data/name_constraints_unittest/san-x400address.pem8
-rw-r--r--chromium/net/data/parse_certificate_unittest/basic_constraints_ca_false.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/basic_constraints_ca_no_path.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/basic_constraints_ca_path_9.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/basic_constraints_negative_path.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/basic_constraints_not_ca.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/basic_constraints_path_too_large.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_255.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_256.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_not_ca.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/basic_constraints_unconsumed_data.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/cert_algorithm_not_sequence.pem8
-rw-r--r--chromium/net/data/parse_certificate_unittest/cert_data_after_signature.pem8
-rw-r--r--chromium/net/data/parse_certificate_unittest/cert_empty_sequence.pem6
-rw-r--r--chromium/net/data/parse_certificate_unittest/cert_missing_signature.pem8
-rw-r--r--chromium/net/data/parse_certificate_unittest/cert_not_sequence.pem6
-rw-r--r--chromium/net/data/parse_certificate_unittest/cert_signature_not_bit_string.pem8
-rw-r--r--chromium/net/data/parse_certificate_unittest/cert_skeleton.pem28
-rw-r--r--chromium/net/data/parse_certificate_unittest/cert_version3.pem114
-rw-r--r--chromium/net/data/parse_certificate_unittest/extension_critical.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extension_critical_0.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extension_critical_3.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extension_not_critical.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extensions_basic_constraints.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extensions_data_after_sequence.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extensions_duplicate_key_usage.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extensions_empty_sequence.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extensions_extended_key_usage.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extensions_key_usage.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extensions_not_sequence.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extensions_policies.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extensions_real.pem2
-rw-r--r--chromium/net/data/parse_certificate_unittest/extensions_subject_alt_name.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extensions_unknown_critical.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/extensions_unknown_non_critical.pem1
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_explicit_v1.pem10
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_negative_serial_number.pem54
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_serial_number_21_octets_leading_0.pem10
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_serial_number_26_octets.pem10
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v1.pem54
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v1_extensions.pem10
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v2_extensions.pem10
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v2_issuer_and_subject_unique_id.pem58
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v2_issuer_unique_id.pem56
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v2_no_optionals.pem54
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v3_all_optionals.pem67
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v3_data_after_extensions.pem10
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v3_extensions.pem60
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v3_extensions_not_sequence.pem10
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v3_no_optionals.pem54
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v3_real.pem131
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_v4.pem10
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_validity_both_generalized_time.pem54
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_validity_both_utc_time.pem54
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_validity_generalized_time_and_utc_time.pem54
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_validity_relaxed.pem52
-rw-r--r--chromium/net/data/parse_certificate_unittest/tbs_validity_utc_time_and_generalized_time.pem54
-rwxr-xr-xchromium/net/data/parse_ocsp_unittest/annotate_test_data.py173
-rw-r--r--chromium/net/data/parse_ocsp_unittest/bad_ocsp_type.pem123
-rw-r--r--chromium/net/data/parse_ocsp_unittest/bad_signature.pem121
-rw-r--r--chromium/net/data/parse_ocsp_unittest/bad_status.pem91
-rw-r--r--chromium/net/data/parse_ocsp_unittest/good_response.pem123
-rw-r--r--chromium/net/data/parse_ocsp_unittest/good_response_next_update.pem125
-rw-r--r--chromium/net/data/parse_ocsp_unittest/has_extension.pem124
-rw-r--r--chromium/net/data/parse_ocsp_unittest/has_single_extension.pem124
-rw-r--r--chromium/net/data/parse_ocsp_unittest/has_version.pem123
-rw-r--r--chromium/net/data/parse_ocsp_unittest/malformed_status.pem91
-rw-r--r--chromium/net/data/parse_ocsp_unittest/missing_response.pem112
-rw-r--r--chromium/net/data/parse_ocsp_unittest/multiple_response.pem133
-rw-r--r--chromium/net/data/parse_ocsp_unittest/no_response.pem112
-rw-r--r--chromium/net/data/parse_ocsp_unittest/ocsp_extra_certs.pem205
-rw-r--r--chromium/net/data/parse_ocsp_unittest/ocsp_sign_bad_indirect.pem163
-rw-r--r--chromium/net/data/parse_ocsp_unittest/ocsp_sign_direct.pem123
-rw-r--r--chromium/net/data/parse_ocsp_unittest/ocsp_sign_indirect.pem168
-rw-r--r--chromium/net/data/parse_ocsp_unittest/ocsp_sign_indirect_missing.pem123
-rw-r--r--chromium/net/data/parse_ocsp_unittest/other_response.pem135
-rw-r--r--chromium/net/data/parse_ocsp_unittest/responder_id.pem119
-rw-r--r--chromium/net/data/parse_ocsp_unittest/responder_name.pem123
-rw-r--r--chromium/net/data/parse_ocsp_unittest/revoke_response.pem124
-rw-r--r--chromium/net/data/parse_ocsp_unittest/revoke_response_reason.pem126
-rw-r--r--chromium/net/data/parse_ocsp_unittest/unknown_response.pem123
-rw-r--r--chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/favicon.icobin0 -> 1036 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/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index2.html16
-rw-r--r--chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/kitten-1.jpgbin0 -> 144862 bytes
-rw-r--r--chromium/net/data/ssl/blacklist/0d136e439f0ab6e97f3a02a540da9f0641aa554e1d66ea51ae2920d51b2f7217.pem120
-rw-r--r--chromium/net/data/ssl/blacklist/0f912fd7be760be25afbc56bdc09cd9e5dcc9c6f6a55a778aefcb6aa30e31554.pem120
-rw-r--r--chromium/net/data/ssl/blacklist/159ca03a88897c8f13817a212629df84ce824709492b8c9adb8e5437d2fc72be.pem26
-rw-r--r--chromium/net/data/ssl/blacklist/1af56c98ff043ef92bebff54cebb4dd67a25ba956c817f3e6dd3c1e52eb584c1.key9
-rw-r--r--chromium/net/data/ssl/blacklist/1f17f2cbb109f01c885c94d9e74a48625ae9659665d6d7e7bc5a10332976370f.pem104
-rw-r--r--chromium/net/data/ssl/blacklist/294f55ef3bd7244c6ff8a68ab797e9186ec27582751a791515e3292e48372d61.pem120
-rw-r--r--chromium/net/data/ssl/blacklist/2a3699deca1e9fd099ba45de8489e205977c9f2a5e29d5dd747381eec0744d71.pem114
-rw-r--r--chromium/net/data/ssl/blacklist/31c8fd37db9b56e708b03d1f01848b068c6da66f36fb5d82c008c6040fa3e133.pem96
-rw-r--r--chromium/net/data/ssl/blacklist/32ecc96f912f96d889e73088cd031c7ded2c651c805016157a23b6f32f798a3b.key9
-rw-r--r--chromium/net/data/ssl/blacklist/372447c43185c38edd2ce0e9c853f9ac1576ddd1704c2f54d96076c089cb4227.pem78
-rw-r--r--chromium/net/data/ssl/blacklist/3946901f46b0071e90d78279e82fababca177231a704be72c5b0e8918566ea66.pem97
-rw-r--r--chromium/net/data/ssl/blacklist/3e26492e20b52de79e15766e6cb4251a1d566b0dbfb225aa7d08dda1dcebbf0a.pem104
-rw-r--r--chromium/net/data/ssl/blacklist/42187727be39faf667aeb92bf0cc4e268f6e2ead2cefbec575bdc90430024f69.pem103
-rw-r--r--chromium/net/data/ssl/blacklist/450f1b421bb05c8609854884559c323319619e8b06b001ea2dcbb74a23aa3be2.pem82
-rw-r--r--chromium/net/data/ssl/blacklist/4bf6bb839b03b72839329b4ea70bb1b2f0d07e014d9d24aa9cc596114702bee3.pem114
-rw-r--r--chromium/net/data/ssl/blacklist/4fee0163686ecbd65db968e7494f55d84b25486d438e9de558d629d28cd4d176.pem116
-rw-r--r--chromium/net/data/ssl/blacklist/67ed4b703d15dc555f8c444b3a05a32579cb7599bd19c9babe10c584ea327ae0.pem96
-rw-r--r--chromium/net/data/ssl/blacklist/79f69a47cfd6c4b4ceae8030d04b49f6171d3b5d6c812f58d040e586f1cb3f14.pem114
-rw-r--r--chromium/net/data/ssl/blacklist/7abd72a323c9d179c722564f4e27a51dd4afd24006b38a40ce918b94960bcf18.pem104
-rw-r--r--chromium/net/data/ssl/blacklist/817d4e05063d5942869c47d8504dc56a5208f7569c3d6d67f3457cfe921b3e29.pem94
-rw-r--r--chromium/net/data/ssl/blacklist/8290cc3fc1c3aac3239782c141ace8f88aeef4e9576a43d01867cf19d025be66.pem114
-rw-r--r--chromium/net/data/ssl/blacklist/83618f932d6947744d5ecca299d4b2820c01483947bd16be814e683f7436be24.pem131
-rw-r--r--chromium/net/data/ssl/blacklist/8a1bd21661c60015065212cc98b1abb50dfd14c872a208e66bae890f25c448af.pem116
-rw-r--r--chromium/net/data/ssl/blacklist/933f7d8cda9f0d7c8bfd3c22bf4653f4161fd38ccdcf66b22e95a2f49c2650f8.pem114
-rw-r--r--chromium/net/data/ssl/blacklist/9532e8b504964331c271f3f5f10070131a08bf8ba438978ce394c34feeae246f.pem114
-rw-r--r--chromium/net/data/ssl/blacklist/9ed8f9b0e8e42a1656b8e1dd18f42ba42dc06fe52686173ba2fc70e756f207dc.pem111
-rw-r--r--chromium/net/data/ssl/blacklist/README.md195
-rw-r--r--chromium/net/data/ssl/blacklist/a686fee577c88ab664d0787ecdfff035f4806f3de418dc9e4d516324fff02083.pem110
-rw-r--r--chromium/net/data/ssl/blacklist/a8e1dfd9cd8e470aa2f443914f931cfd61c323e94d75827affee985241c35ce5.pem96
-rw-r--r--chromium/net/data/ssl/blacklist/b8686723e415534bc0dbd16326f9486f85b0b0799bf6639334e61daae67f36cd.pem139
-rw-r--r--chromium/net/data/ssl/blacklist/b8c1b957c077ea76e00b0f45bff5ae3acb696f221d2e062164fe37125e5a8d25.pem25
-rw-r--r--chromium/net/data/ssl/blacklist/be144b56fb1163c49c9a0e6b5a458df6b29f7e6449985960c178a4744624b7bc.pem136
-rw-r--r--chromium/net/data/ssl/blacklist/c4387d45364a313fbfe79812b35b815d42852ab03b06f11589638021c8f2cb44.key6
-rw-r--r--chromium/net/data/ssl/blacklist/c67d722c1495be02cbf9ef1159f5ca4aa782dc832dc6aa60c9aa076a0ad1e69d.pem108
-rw-r--r--chromium/net/data/ssl/blacklist/e4f9a3235df7330255f36412bc849fb630f8519961ec3538301deb896c953da5.pem89
-rw-r--r--chromium/net/data/ssl/blacklist/ea08c8d45d52ca593de524f0513ca6418da9859f7b08ef13ff9dd7bf612d6a37.key9
-rw-r--r--chromium/net/data/ssl/blacklist/ead610e6e90b439f2ecb51628b0932620f6ef340bd843fca38d3181b8f4ba197.pem114
-rw-r--r--chromium/net/data/ssl/blacklist/ec30c9c3065a06bb07dc5b1c6b497f370c1ca65c0f30c08e042ba6bcecc78f2c.pem71
-rw-r--r--chromium/net/data/ssl/blacklist/f3bae5e9c0adbfbfb6dbf7e04e74be6ead3ca98a5604ffe591cea86c241848ec.pem131
-rw-r--r--chromium/net/data/ssl/blacklist/f4a5984324de98bd979ef181a100cf940f2166173319a86a0d9d7c8fac3b0a8f.pem98
-rw-r--r--chromium/net/data/ssl/blacklist/f8a5ff189fedbfe34e21103389a68340174439ad12974a4e8d4d784d1f3a0faa.pem114
-rw-r--r--chromium/net/data/ssl/blacklist/fdedb5bdfcb67411513a61aee5cb5b5d7c52af06028efc996cc1b05b1d6cea2b.pem110
-rw-r--r--chromium/net/data/ssl/certificates/README10
-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.pk8bin1219 -> 1218 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.pk8bin1218 -> 1216 bytes
-rw-r--r--chromium/net/data/ssl/certificates/client_2_ca.pem98
-rw-r--r--chromium/net/data/ssl/certificates/client_3.key27
-rw-r--r--chromium/net/data/ssl/certificates/client_3.pem70
-rw-r--r--chromium/net/data/ssl/certificates/client_3.pk8bin0 -> 1220 bytes
-rw-r--r--chromium/net/data/ssl/certificates/client_3_ca.pem71
-rw-r--r--chromium/net/data/ssl/certificates/globalsign_ev_sha256_ca_cert.pem25
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-A-by-B.pem107
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-B-by-C.pem74
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-B-by-F.pem74
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-C-by-D.pem74
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-C-by-E.pem74
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-D-by-D.pem75
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-E-by-E.pem75
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-F-by-E.pem74
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-chain1.pem475
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-chain2.pem475
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-crlset-C.rawbin0 -> 155 bytes
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-crlset-CD-and-FE.rawbin0 -> 187 bytes
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-crlset-D-and-E.rawbin0 -> 203 bytes
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-crlset-E.rawbin0 -> 155 bytes
-rw-r--r--chromium/net/data/ssl/certificates/multi-root-crlset-unrelated.rawbin0 -> 148 bytes
-rw-r--r--chromium/net/data/ssl/certificates/sha256.pem70
-rw-r--r--chromium/net/data/ssl/scripts/client-certs.cnf3
-rwxr-xr-xchromium/net/data/ssl/scripts/generate-client-certificates.sh27
-rwxr-xr-xchromium/net/data/ssl/scripts/generate-multi-root-test-chains.sh363
-rwxr-xr-xchromium/net/data/ssl/scripts/generate-test-certs.sh6
-rw-r--r--chromium/net/data/ssl/scripts/redundant-ca.cnf9
-rw-r--r--chromium/net/data/url_request_unittest/expect-ct-header.html0
-rw-r--r--chromium/net/data/url_request_unittest/expect-ct-header.html.mock-http-headers4
-rwxr-xr-xchromium/net/data/verify_signed_data_unittest/annotate_test_data.py31
-rw-r--r--chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-spki-params-null.pem28
-rw-r--r--chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-unused-bits-signature.pem28
-rw-r--r--chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecdh-key.pem28
-rw-r--r--chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecmqv-key.pem28
-rw-r--r--chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-rsa-algorithm.pem28
-rw-r--r--chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-wrong-signature-format.pem28
-rw-r--r--chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512.pem28
-rw-r--r--chromium/net/data/verify_signed_data_unittest/ecdsa-secp384r1-sha256-corrupted-data.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/ecdsa-secp384r1-sha256.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/ecdsa-using-rsa-key.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-length.pem24
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-null.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-key-params-absent.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-using-pss-key-no-params.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-wrong-algorithm.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-key-encoded-ber.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-spki-non-null-params.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-using-ecdsa-algorithm.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-using-id-ea-rsa.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20-using-pss-key-no-params.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20-using-pss-key-with-null-params.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-wrong-salt.pem30
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-mgf1-sha512-salt33.pem32
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10-using-pss-key-with-params.pem34
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10-using-pss-key-with-wrong-params.pem34
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10.pem32
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa-using-ec-key.pem28
-rw-r--r--chromium/net/data/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem32
-rw-r--r--chromium/net/der/input.cc16
-rw-r--r--chromium/net/der/input.h9
-rw-r--r--chromium/net/der/input_unittest.cc10
-rw-r--r--chromium/net/der/parser.cc14
-rw-r--r--chromium/net/der/parser.h18
-rw-r--r--chromium/net/der/tag.cc8
-rw-r--r--chromium/net/der/tag.h5
-rw-r--r--chromium/net/disk_cache/backend_unittest.cc120
-rw-r--r--chromium/net/disk_cache/blockfile/file_win.cc6
-rw-r--r--chromium/net/disk_cache/blockfile/in_flight_io.cc2
-rw-r--r--chromium/net/disk_cache/blockfile/index_table_v3.cc2
-rw-r--r--chromium/net/disk_cache/blockfile/index_table_v3.h1
-rw-r--r--chromium/net/disk_cache/entry_unittest.cc2
-rw-r--r--chromium/net/disk_cache/memory/mem_backend_impl.cc312
-rw-r--r--chromium/net/disk_cache/memory/mem_backend_impl.h66
-rw-r--r--chromium/net/disk_cache/memory/mem_entry_impl.cc356
-rw-r--r--chromium/net/disk_cache/memory/mem_entry_impl.h126
-rw-r--r--chromium/net/disk_cache/memory/mem_rankings.cc67
-rw-r--r--chromium/net/disk_cache/memory/mem_rankings.h44
-rw-r--r--chromium/net/disk_cache/simple/simple_backend_impl.cc4
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_impl.cc81
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_impl.h6
-rw-r--r--chromium/net/disk_cache/simple/simple_index.cc2
-rw-r--r--chromium/net/disk_cache/simple/simple_index.h11
-rw-r--r--chromium/net/disk_cache/simple/simple_index_file.cc29
-rw-r--r--chromium/net/disk_cache/simple/simple_index_file.h1
-rw-r--r--chromium/net/disk_cache/simple/simple_synchronous_entry.cc36
-rw-r--r--chromium/net/disk_cache/simple/simple_synchronous_entry.h9
-rw-r--r--chromium/net/dns/address_sorter_posix.cc64
-rw-r--r--chromium/net/dns/address_sorter_posix.h7
-rw-r--r--chromium/net/dns/address_sorter_posix_unittest.cc19
-rw-r--r--chromium/net/dns/address_sorter_unittest.cc6
-rw-r--r--chromium/net/dns/address_sorter_win.cc9
-rw-r--r--chromium/net/dns/dns_config_service.cc91
-rw-r--r--chromium/net/dns/dns_config_service.h39
-rw-r--r--chromium/net/dns/dns_config_service_posix.cc17
-rw-r--r--chromium/net/dns/dns_config_service_posix_unittest.cc15
-rw-r--r--chromium/net/dns/dns_config_service_unittest.cc94
-rw-r--r--chromium/net/dns/dns_config_service_win.cc29
-rw-r--r--chromium/net/dns/dns_config_service_win.h1
-rw-r--r--chromium/net/dns/dns_config_service_win_unittest.cc12
-rw-r--r--chromium/net/dns/dns_hosts.cc12
-rw-r--r--chromium/net/dns/dns_hosts.h9
-rw-r--r--chromium/net/dns/dns_hosts_unittest.cc5
-rw-r--r--chromium/net/dns/dns_query.cc28
-rw-r--r--chromium/net/dns/dns_query.h6
-rw-r--r--chromium/net/dns/dns_record_fuzzer.cc20
-rw-r--r--chromium/net/dns/dns_response.cc9
-rw-r--r--chromium/net/dns/dns_response_unittest.cc1
-rw-r--r--chromium/net/dns/dns_session.cc60
-rw-r--r--chromium/net/dns/dns_session.h16
-rw-r--r--chromium/net/dns/dns_session_unittest.cc24
-rw-r--r--chromium/net/dns/dns_transaction.cc5
-rw-r--r--chromium/net/dns/dns_transaction.h1
-rw-r--r--chromium/net/dns/dns_transaction_unittest.cc11
-rw-r--r--chromium/net/dns/dns_util.cc40
-rw-r--r--chromium/net/dns/dns_util.h10
-rw-r--r--chromium/net/dns/host_cache.cc2
-rw-r--r--chromium/net/dns/host_resolver_impl.cc122
-rw-r--r--chromium/net/dns/host_resolver_impl.h29
-rw-r--r--chromium/net/dns/host_resolver_impl_unittest.cc125
-rw-r--r--chromium/net/dns/host_resolver_mojo_unittest.cc50
-rw-r--r--chromium/net/dns/mapped_host_resolver.cc1
-rw-r--r--chromium/net/dns/mapped_host_resolver_unittest.cc1
-rw-r--r--chromium/net/dns/mdns_client.cc9
-rw-r--r--chromium/net/dns/mdns_client_unittest.cc7
-rw-r--r--chromium/net/dns/mock_host_resolver.cc20
-rw-r--r--chromium/net/dns/mock_mdns_socket_factory.h6
-rw-r--r--chromium/net/dns/mojo_host_resolver_impl_unittest.cc3
-rw-r--r--chromium/net/dns/mojo_host_type_converters.cc17
-rw-r--r--chromium/net/dns/record_rdata.cc20
-rw-r--r--chromium/net/dns/record_rdata.h10
-rw-r--r--chromium/net/dns/record_rdata_unittest.cc6
-rw-r--r--chromium/net/docs/README.txt20
-rw-r--r--chromium/net/docs/bug-triage-labels.md94
-rw-r--r--chromium/net/docs/bug-triage-suggested-workflow.md228
-rw-r--r--chromium/net/docs/bug-triage.md143
-rw-r--r--chromium/net/docs/crash-course-in-net-internals.md20
-rw-r--r--chromium/net/docs/life-of-a-url-request.md45
-rw-r--r--chromium/net/docs/pools.dot101
-rw-r--r--chromium/net/docs/pools.svg335
-rw-r--r--chromium/net/docs/url_request.dot186
-rw-r--r--chromium/net/docs/url_request.svg594
-rw-r--r--chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc69
-rw-r--r--chromium/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc3
-rw-r--r--chromium/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc102
-rw-r--r--chromium/net/filter/filter.cc2
-rw-r--r--chromium/net/filter/filter.h7
-rw-r--r--chromium/net/ftp/ftp_ctrl_response_buffer.cc5
-rw-r--r--chromium/net/ftp/ftp_ctrl_response_buffer.h2
-rw-r--r--chromium/net/ftp/ftp_ctrl_response_fuzzer.cc22
-rw-r--r--chromium/net/ftp/ftp_directory_listing_fuzzer.cc20
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser_vms.cc4
-rw-r--r--chromium/net/ftp/ftp_network_transaction.cc9
-rw-r--r--chromium/net/ftp/ftp_network_transaction_unittest.cc41
-rw-r--r--chromium/net/ftp/ftp_util.cc4
-rw-r--r--chromium/net/http/OWNERS2
-rw-r--r--chromium/net/http/bidirectional_stream.cc55
-rw-r--r--chromium/net/http/bidirectional_stream.h34
-rw-r--r--chromium/net/http/bidirectional_stream_impl.cc17
-rw-r--r--chromium/net/http/bidirectional_stream_impl.h (renamed from chromium/net/http/bidirectional_stream_job.h)53
-rw-r--r--chromium/net/http/bidirectional_stream_job.cc17
-rw-r--r--chromium/net/http/bidirectional_stream_unittest.cc220
-rw-r--r--chromium/net/http/disk_based_cert_cache.cc598
-rw-r--r--chromium/net/http/disk_based_cert_cache.h106
-rw-r--r--chromium/net/http/disk_based_cert_cache_unittest.cc535
-rw-r--r--chromium/net/http/disk_cache_based_quic_server_info_unittest.cc56
-rw-r--r--chromium/net/http/http_auth.cc16
-rw-r--r--chromium/net/http/http_auth.h21
-rw-r--r--chromium/net/http/http_auth_cache.cc2
-rw-r--r--chromium/net/http/http_auth_cache.h1
-rw-r--r--chromium/net/http/http_auth_cache_unittest.cc3
-rw-r--r--chromium/net/http/http_auth_controller.cc56
-rw-r--r--chromium/net/http/http_auth_controller.h4
-rw-r--r--chromium/net/http/http_auth_controller_unittest.cc20
-rw-r--r--chromium/net/http/http_auth_gssapi_posix.cc36
-rw-r--r--chromium/net/http/http_auth_gssapi_posix.h2
-rw-r--r--chromium/net/http/http_auth_gssapi_posix_unittest.cc6
-rw-r--r--chromium/net/http/http_auth_handler.cc12
-rw-r--r--chromium/net/http/http_auth_handler.h9
-rw-r--r--chromium/net/http/http_auth_handler_basic.cc7
-rw-r--r--chromium/net/http/http_auth_handler_basic.h4
-rw-r--r--chromium/net/http/http_auth_handler_basic_unittest.cc14
-rw-r--r--chromium/net/http/http_auth_handler_digest.cc9
-rw-r--r--chromium/net/http/http_auth_handler_digest.h4
-rw-r--r--chromium/net/http/http_auth_handler_digest_unittest.cc28
-rw-r--r--chromium/net/http/http_auth_handler_factory.cc18
-rw-r--r--chromium/net/http/http_auth_handler_factory.h6
-rw-r--r--chromium/net/http/http_auth_handler_factory_unittest.cc78
-rw-r--r--chromium/net/http/http_auth_handler_mock.cc7
-rw-r--r--chromium/net/http/http_auth_handler_mock.h4
-rw-r--r--chromium/net/http/http_auth_handler_negotiate.cc46
-rw-r--r--chromium/net/http/http_auth_handler_negotiate.h5
-rw-r--r--chromium/net/http/http_auth_handler_negotiate_unittest.cc24
-rw-r--r--chromium/net/http/http_auth_handler_ntlm.cc13
-rw-r--r--chromium/net/http/http_auth_handler_ntlm.h4
-rw-r--r--chromium/net/http/http_auth_handler_ntlm_portable.cc6
-rw-r--r--chromium/net/http/http_auth_handler_ntlm_win.cc7
-rw-r--r--chromium/net/http/http_auth_handler_unittest.cc4
-rw-r--r--chromium/net/http/http_auth_preferences.h3
-rw-r--r--chromium/net/http/http_auth_preferences_unittest.cc2
-rw-r--r--chromium/net/http/http_auth_sspi_win.cc91
-rw-r--r--chromium/net/http/http_auth_sspi_win.h13
-rw-r--r--chromium/net/http/http_auth_sspi_win_unittest.cc6
-rw-r--r--chromium/net/http/http_auth_unittest.cc28
-rw-r--r--chromium/net/http/http_basic_stream.cc8
-rw-r--r--chromium/net/http/http_basic_stream.h3
-rw-r--r--chromium/net/http/http_cache.cc13
-rw-r--r--chromium/net/http/http_cache.h5
-rw-r--r--chromium/net/http/http_cache_transaction.cc204
-rw-r--r--chromium/net/http/http_cache_transaction.h5
-rw-r--r--chromium/net/http/http_chunked_decoder_fuzzer.cc45
-rw-r--r--chromium/net/http/http_chunked_decoder_fuzzer.dict34
-rw-r--r--chromium/net/http/http_content_disposition.cc4
-rw-r--r--chromium/net/http/http_network_session.cc100
-rw-r--r--chromium/net/http/http_network_session.h59
-rw-r--r--chromium/net/http/http_network_transaction.cc285
-rw-r--r--chromium/net/http/http_network_transaction.h35
-rw-r--r--chromium/net/http/http_network_transaction_ssl_unittest.cc123
-rw-r--r--chromium/net/http/http_network_transaction_unittest.cc859
-rw-r--r--chromium/net/http/http_proxy_client_socket.cc9
-rw-r--r--chromium/net/http/http_proxy_client_socket.h1
-rw-r--r--chromium/net/http/http_proxy_client_socket_pool.cc33
-rw-r--r--chromium/net/http/http_proxy_client_socket_pool.h4
-rw-r--r--chromium/net/http/http_proxy_client_socket_pool_unittest.cc161
-rw-r--r--chromium/net/http/http_proxy_client_socket_wrapper.cc19
-rw-r--r--chromium/net/http/http_proxy_client_socket_wrapper.h3
-rw-r--r--chromium/net/http/http_request_headers.cc5
-rw-r--r--chromium/net/http/http_request_headers.h4
-rw-r--r--chromium/net/http/http_request_info.cc2
-rw-r--r--chromium/net/http/http_request_info.h5
-rw-r--r--chromium/net/http/http_response_body_drainer_unittest.cc5
-rw-r--r--chromium/net/http/http_response_headers.cc49
-rw-r--r--chromium/net/http/http_response_headers.h36
-rw-r--r--chromium/net/http/http_response_headers_unittest.cc40
-rw-r--r--chromium/net/http/http_security_headers.cc31
-rw-r--r--chromium/net/http/http_security_headers.h4
-rw-r--r--chromium/net/http/http_security_headers_unittest.cc8
-rw-r--r--chromium/net/http/http_server_properties.cc9
-rw-r--r--chromium/net/http/http_server_properties.h26
-rw-r--r--chromium/net/http/http_server_properties_impl.cc48
-rw-r--r--chromium/net/http/http_server_properties_impl.h29
-rw-r--r--chromium/net/http/http_server_properties_impl_unittest.cc201
-rw-r--r--chromium/net/http/http_server_properties_manager.cc80
-rw-r--r--chromium/net/http/http_server_properties_manager.h57
-rw-r--r--chromium/net/http/http_server_properties_manager_unittest.cc237
-rw-r--r--chromium/net/http/http_stream.h12
-rw-r--r--chromium/net/http/http_stream_factory.cc88
-rw-r--r--chromium/net/http/http_stream_factory.h45
-rw-r--r--chromium/net/http/http_stream_factory_impl.cc107
-rw-r--r--chromium/net/http/http_stream_factory_impl.h10
-rw-r--r--chromium/net/http/http_stream_factory_impl_job.cc288
-rw-r--r--chromium/net/http/http_stream_factory_impl_job.h40
-rw-r--r--chromium/net/http/http_stream_factory_impl_request.cc41
-rw-r--r--chromium/net/http/http_stream_factory_impl_request.h32
-rw-r--r--chromium/net/http/http_stream_factory_impl_request_unittest.cc66
-rw-r--r--chromium/net/http/http_stream_factory_impl_unittest.cc428
-rw-r--r--chromium/net/http/http_stream_parser.cc25
-rw-r--r--chromium/net/http/http_stream_parser.h5
-rw-r--r--chromium/net/http/http_stream_parser_fuzzer.cc152
-rw-r--r--chromium/net/http/http_stream_parser_unittest.cc10
-rw-r--r--chromium/net/http/http_transaction_test_util.cc7
-rw-r--r--chromium/net/http/http_transaction_test_util.h1
-rw-r--r--chromium/net/http/http_util.cc35
-rw-r--r--chromium/net/http/http_util.h12
-rw-r--r--chromium/net/http/http_util_icu.cc23
-rw-r--r--chromium/net/http/http_util_unittest.cc59
-rw-r--r--chromium/net/http/http_vary_data.cc2
-rw-r--r--chromium/net/http/mock_gssapi_library_posix.cc3
-rw-r--r--chromium/net/http/mock_gssapi_library_posix.h1
-rw-r--r--chromium/net/http/proxy_client_socket.cc6
-rw-r--r--chromium/net/http/proxy_connect_redirect_http_stream.cc7
-rw-r--r--chromium/net/http/proxy_connect_redirect_http_stream.h2
-rw-r--r--chromium/net/http/transport_security_persister.cc1
-rw-r--r--chromium/net/http/transport_security_persister_unittest.cc1
-rw-r--r--chromium/net/http/transport_security_state.cc98
-rw-r--r--chromium/net/http/transport_security_state.h49
-rw-r--r--chromium/net/http/transport_security_state_static.h12772
-rw-r--r--chromium/net/http/transport_security_state_static.json6017
-rw-r--r--chromium/net/http/transport_security_state_unittest.cc262
-rw-r--r--chromium/net/http/url_security_manager_win.cc1
-rw-r--r--chromium/net/log/net_log.h6
-rw-r--r--chromium/net/log/net_log_event_type_list.h100
-rw-r--r--chromium/net/log/net_log_util.cc28
-rw-r--r--chromium/net/log/trace_net_log_observer.cc6
-rw-r--r--chromium/net/net.gyp159
-rw-r--r--chromium/net/net.gypi211
-rw-r--r--chromium/net/net_common.gypi99
-rw-r--r--chromium/net/net_unittests.isolate2
-rw-r--r--chromium/net/net_unittests_apk.isolate1
-rw-r--r--chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.cc2
-rw-r--r--chromium/net/proxy/dhcp_proxy_script_fetcher_factory.h1
-rw-r--r--chromium/net/proxy/dhcp_proxy_script_fetcher_win.cc2
-rw-r--r--chromium/net/proxy/mojo_proxy_type_converters.cc34
-rw-r--r--chromium/net/proxy/multi_threaded_proxy_resolver_unittest.cc8
-rw-r--r--chromium/net/proxy/parse_proxy_bypass_rules_fuzzer.cc16
-rw-r--r--chromium/net/proxy/parse_proxy_list_fuzzer.cc16
-rw-r--r--chromium/net/proxy/parse_proxy_list_pac_fuzzer.cc16
-rw-r--r--chromium/net/proxy/parse_proxy_rules_fuzzer.cc16
-rw-r--r--chromium/net/proxy/proxy_bypass_rules.cc36
-rw-r--r--chromium/net/proxy/proxy_bypass_rules_unittest.cc9
-rw-r--r--chromium/net/proxy/proxy_config.cc2
-rw-r--r--chromium/net/proxy/proxy_config.h1
-rw-r--r--chromium/net/proxy/proxy_config_service_linux.cc4
-rw-r--r--chromium/net/proxy/proxy_config_service_win.cc2
-rw-r--r--chromium/net/proxy/proxy_info.cc2
-rw-r--r--chromium/net/proxy/proxy_info.h1
-rw-r--r--chromium/net/proxy/proxy_list.cc2
-rw-r--r--chromium/net/proxy/proxy_list.h1
-rw-r--r--chromium/net/proxy/proxy_resolver_factory_mojo.cc10
-rw-r--r--chromium/net/proxy/proxy_resolver_v8.cc55
-rw-r--r--chromium/net/proxy/proxy_resolver_v8_tracing.cc4
-rw-r--r--chromium/net/proxy/proxy_resolver_winhttp.cc2
-rw-r--r--chromium/net/proxy/proxy_server.cc2
-rw-r--r--chromium/net/proxy/proxy_service.cc100
-rw-r--r--chromium/net/proxy/proxy_service.h27
-rw-r--r--chromium/net/proxy/proxy_service_mojo_unittest.cc24
-rw-r--r--chromium/net/proxy/proxy_service_unittest.cc714
-rw-r--r--chromium/net/quic/bidirectional_stream_quic_impl.cc264
-rw-r--r--chromium/net/quic/bidirectional_stream_quic_impl.h114
-rw-r--r--chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc1154
-rw-r--r--chromium/net/quic/congestion_control/general_loss_algorithm.cc24
-rw-r--r--chromium/net/quic/congestion_control/general_loss_algorithm.h8
-rw-r--r--chromium/net/quic/congestion_control/general_loss_algorithm_test.cc20
-rw-r--r--chromium/net/quic/congestion_control/hybrid_slow_start.cc5
-rw-r--r--chromium/net/quic/congestion_control/hybrid_slow_start.h2
-rw-r--r--chromium/net/quic/congestion_control/loss_detection_interface.cc15
-rw-r--r--chromium/net/quic/congestion_control/loss_detection_interface.h8
-rw-r--r--chromium/net/quic/congestion_control/pacing_sender.cc17
-rw-r--r--chromium/net/quic/congestion_control/pacing_sender.h8
-rw-r--r--chromium/net/quic/congestion_control/pacing_sender_test.cc97
-rw-r--r--chromium/net/quic/congestion_control/rtt_stats.h3
-rw-r--r--chromium/net/quic/congestion_control/send_algorithm_interface.cc21
-rw-r--r--chromium/net/quic/congestion_control/send_algorithm_interface.h3
-rw-r--r--chromium/net/quic/congestion_control/send_algorithm_simulator.cc2
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_bytes_sender.cc388
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_bytes_sender.h151
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_sender.cc399
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_sender_base.cc261
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_sender_base.h (renamed from chromium/net/quic/congestion_control/tcp_cubic_sender.h)105
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_sender_bytes.cc209
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_sender_bytes.h99
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc (renamed from chromium/net/quic/congestion_control/tcp_cubic_bytes_sender_test.cc)163
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_sender_packets.cc217
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_sender_packets.h101
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc (renamed from chromium/net/quic/congestion_control/tcp_cubic_sender_test.cc)207
-rw-r--r--chromium/net/quic/congestion_control/tcp_loss_algorithm.cc104
-rw-r--r--chromium/net/quic/congestion_control/tcp_loss_algorithm.h54
-rw-r--r--chromium/net/quic/congestion_control/tcp_loss_algorithm_test.cc216
-rw-r--r--chromium/net/quic/congestion_control/time_loss_algorithm.cc81
-rw-r--r--chromium/net/quic/congestion_control/time_loss_algorithm.h58
-rw-r--r--chromium/net/quic/congestion_control/time_loss_algorithm_test.cc148
-rw-r--r--chromium/net/quic/crypto/aead_base_decrypter.h9
-rw-r--r--chromium/net/quic/crypto/aead_base_decrypter_nss.cc14
-rw-r--r--chromium/net/quic/crypto/aead_base_decrypter_openssl.cc14
-rw-r--r--chromium/net/quic/crypto/aead_base_encrypter.h3
-rw-r--r--chromium/net/quic/crypto/aead_base_encrypter_nss.cc11
-rw-r--r--chromium/net/quic/crypto/aead_base_encrypter_openssl.cc12
-rw-r--r--chromium/net/quic/crypto/aes_128_gcm_12_decrypter.h2
-rw-r--r--chromium/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc2
-rw-r--r--chromium/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc9
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_decrypter.h2
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc62
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_decrypter_openssl.cc41
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_decrypter_test.cc133
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_encrypter_nss.cc47
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_encrypter_openssl.cc32
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_encrypter_test.cc102
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h2
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc2
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_openssl.cc2
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_test.cc9
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_openssl.cc2
-rw-r--r--chromium/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_test.cc8
-rw-r--r--chromium/net/quic/crypto/channel_id_chromium.cc7
-rw-r--r--chromium/net/quic/crypto/common_cert_set.cc2
-rw-r--r--chromium/net/quic/crypto/common_cert_set.h2
-rw-r--r--chromium/net/quic/crypto/crypto_handshake.cc3
-rw-r--r--chromium/net/quic/crypto/crypto_handshake.h19
-rw-r--r--chromium/net/quic/crypto/crypto_handshake_message.cc9
-rw-r--r--chromium/net/quic/crypto/crypto_handshake_message_test.cc7
-rw-r--r--chromium/net/quic/crypto/crypto_protocol.h24
-rw-r--r--chromium/net/quic/crypto/crypto_secret_boxer.cc52
-rw-r--r--chromium/net/quic/crypto/crypto_secret_boxer.h28
-rw-r--r--chromium/net/quic/crypto/crypto_secret_boxer_test.cc46
-rw-r--r--chromium/net/quic/crypto/crypto_server_test.cc189
-rw-r--r--chromium/net/quic/crypto/crypto_utils.cc15
-rw-r--r--chromium/net/quic/crypto/crypto_utils.h4
-rw-r--r--chromium/net/quic/crypto/curve25519_key_exchange.cc8
-rw-r--r--chromium/net/quic/crypto/curve25519_key_exchange.h4
-rw-r--r--chromium/net/quic/crypto/key_exchange.h2
-rw-r--r--chromium/net/quic/crypto/null_decrypter.cc10
-rw-r--r--chromium/net/quic/crypto/null_decrypter.h10
-rw-r--r--chromium/net/quic/crypto/null_decrypter_test.cc15
-rw-r--r--chromium/net/quic/crypto/null_encrypter.cc3
-rw-r--r--chromium/net/quic/crypto/null_encrypter.h3
-rw-r--r--chromium/net/quic/crypto/null_encrypter_test.cc5
-rw-r--r--chromium/net/quic/crypto/p256_key_exchange.h2
-rw-r--r--chromium/net/quic/crypto/p256_key_exchange_nss.cc2
-rw-r--r--chromium/net/quic/crypto/p256_key_exchange_openssl.cc2
-rw-r--r--chromium/net/quic/crypto/proof_source.cc14
-rw-r--r--chromium/net/quic/crypto/proof_source.h41
-rw-r--r--chromium/net/quic/crypto/proof_source_chromium.h8
-rw-r--r--chromium/net/quic/crypto/proof_source_chromium_nss.cc6
-rw-r--r--chromium/net/quic/crypto/proof_source_chromium_openssl.cc59
-rw-r--r--chromium/net/quic/crypto/proof_test.cc173
-rw-r--r--chromium/net/quic/crypto/proof_verifier.h4
-rw-r--r--chromium/net/quic/crypto/proof_verifier_chromium.cc108
-rw-r--r--chromium/net/quic/crypto/proof_verifier_chromium.h3
-rw-r--r--chromium/net/quic/crypto/proof_verifier_chromium_test.cc97
-rw-r--r--chromium/net/quic/crypto/properties_based_quic_server_info_test.cc6
-rw-r--r--chromium/net/quic/crypto/quic_compressed_certs_cache.cc124
-rw-r--r--chromium/net/quic/crypto/quic_compressed_certs_cache.h108
-rw-r--r--chromium/net/quic/crypto/quic_compressed_certs_cache_test.cc91
-rw-r--r--chromium/net/quic/crypto/quic_crypto_client_config.cc62
-rw-r--r--chromium/net/quic/crypto/quic_crypto_client_config.h18
-rw-r--r--chromium/net/quic/crypto/quic_crypto_client_config_test.cc58
-rw-r--r--chromium/net/quic/crypto/quic_crypto_server_config.cc271
-rw-r--r--chromium/net/quic/crypto/quic_crypto_server_config.h69
-rw-r--r--chromium/net/quic/crypto/quic_crypto_server_config_test.cc182
-rw-r--r--chromium/net/quic/crypto/quic_decrypter.cc3
-rw-r--r--chromium/net/quic/crypto/quic_decrypter.h7
-rw-r--r--chromium/net/quic/crypto/quic_encrypter.cc3
-rw-r--r--chromium/net/quic/crypto/quic_encrypter.h3
-rw-r--r--chromium/net/quic/crypto/quic_random.cc1
-rw-r--r--chromium/net/quic/crypto/quic_server_info.cc28
-rw-r--r--chromium/net/quic/crypto/quic_server_info.h2
-rw-r--r--chromium/net/quic/iovector.cc2
-rw-r--r--chromium/net/quic/iovector.h1
-rw-r--r--chromium/net/quic/p2p/quic_p2p_session.cc26
-rw-r--r--chromium/net/quic/p2p/quic_p2p_session.h8
-rw-r--r--chromium/net/quic/p2p/quic_p2p_session_test.cc28
-rw-r--r--chromium/net/quic/p2p/quic_p2p_stream.cc4
-rw-r--r--chromium/net/quic/p2p/quic_p2p_stream.h3
-rw-r--r--chromium/net/quic/quic_ack_listener_interface.h38
-rw-r--r--chromium/net/quic/quic_address_mismatch.cc18
-rw-r--r--chromium/net/quic/quic_address_mismatch_test.cc25
-rw-r--r--chromium/net/quic/quic_alarm.cc32
-rw-r--r--chromium/net/quic/quic_alarm.h16
-rw-r--r--chromium/net/quic/quic_alarm_test.cc56
-rw-r--r--chromium/net/quic/quic_arena_scoped_ptr.h210
-rw-r--r--chromium/net/quic/quic_arena_scoped_ptr_test.cc102
-rw-r--r--chromium/net/quic/quic_bandwidth.cc12
-rw-r--r--chromium/net/quic/quic_bandwidth.h4
-rw-r--r--chromium/net/quic/quic_blocked_writer_interface.h11
-rw-r--r--chromium/net/quic/quic_bug_tracker.h7
-rw-r--r--chromium/net/quic/quic_chromium_client_session.cc231
-rw-r--r--chromium/net/quic/quic_chromium_client_session.h58
-rw-r--r--chromium/net/quic/quic_chromium_client_session_test.cc46
-rw-r--r--chromium/net/quic/quic_chromium_client_stream.cc124
-rw-r--r--chromium/net/quic/quic_chromium_client_stream.h33
-rw-r--r--chromium/net/quic/quic_chromium_client_stream_test.cc266
-rw-r--r--chromium/net/quic/quic_chromium_connection_helper.cc19
-rw-r--r--chromium/net/quic/quic_chromium_connection_helper.h3
-rw-r--r--chromium/net/quic/quic_chromium_connection_helper_test.cc5
-rw-r--r--chromium/net/quic/quic_chromium_packet_reader.cc (renamed from chromium/net/quic/quic_packet_reader.cc)27
-rw-r--r--chromium/net/quic/quic_chromium_packet_reader.h (renamed from chromium/net/quic/quic_packet_reader.h)26
-rw-r--r--chromium/net/quic/quic_chromium_packet_writer.cc (renamed from chromium/net/quic/quic_default_packet_writer.cc)27
-rw-r--r--chromium/net/quic/quic_chromium_packet_writer.h (renamed from chromium/net/quic/quic_default_packet_writer.h)17
-rw-r--r--chromium/net/quic/quic_client_promised_info.cc123
-rw-r--r--chromium/net/quic/quic_client_promised_info.h113
-rw-r--r--chromium/net/quic/quic_client_promised_info_test.cc376
-rw-r--r--chromium/net/quic/quic_client_push_promise_index.cc49
-rw-r--r--chromium/net/quic/quic_client_push_promise_index.h98
-rw-r--r--chromium/net/quic/quic_client_push_promise_index_test.cc107
-rw-r--r--chromium/net/quic/quic_client_session_base.cc148
-rw-r--r--chromium/net/quic/quic_client_session_base.h102
-rw-r--r--chromium/net/quic/quic_config.cc50
-rw-r--r--chromium/net/quic/quic_config.h9
-rw-r--r--chromium/net/quic/quic_config_test.cc11
-rw-r--r--chromium/net/quic/quic_connection.cc1026
-rw-r--r--chromium/net/quic/quic_connection.h310
-rw-r--r--chromium/net/quic/quic_connection_logger.cc42
-rw-r--r--chromium/net/quic/quic_connection_logger.h12
-rw-r--r--chromium/net/quic/quic_connection_stats.cc5
-rw-r--r--chromium/net/quic/quic_connection_stats.h8
-rw-r--r--chromium/net/quic/quic_connection_test.cc2219
-rw-r--r--chromium/net/quic/quic_crypto_client_stream.cc70
-rw-r--r--chromium/net/quic/quic_crypto_client_stream.h48
-rw-r--r--chromium/net/quic/quic_crypto_client_stream_factory.cc5
-rw-r--r--chromium/net/quic/quic_crypto_client_stream_test.cc32
-rw-r--r--chromium/net/quic/quic_crypto_framer_parse_message_fuzzer.cc18
-rw-r--r--chromium/net/quic/quic_crypto_server_stream.cc22
-rw-r--r--chromium/net/quic/quic_crypto_server_stream.h11
-rw-r--r--chromium/net/quic/quic_crypto_server_stream_test.cc44
-rw-r--r--chromium/net/quic/quic_crypto_stream.cc15
-rw-r--r--chromium/net/quic/quic_crypto_stream.h11
-rw-r--r--chromium/net/quic/quic_crypto_stream_test.cc4
-rw-r--r--chromium/net/quic/quic_end_to_end_unittest.cc89
-rw-r--r--chromium/net/quic/quic_flags.cc121
-rw-r--r--chromium/net/quic/quic_flags.h39
-rw-r--r--chromium/net/quic/quic_flow_controller.cc11
-rw-r--r--chromium/net/quic/quic_flow_controller_test.cc4
-rw-r--r--chromium/net/quic/quic_frame_list.cc9
-rw-r--r--chromium/net/quic/quic_frame_list.h25
-rw-r--r--chromium/net/quic/quic_framer.cc291
-rw-r--r--chromium/net/quic/quic_framer.h65
-rw-r--r--chromium/net/quic/quic_framer_test.cc1297
-rw-r--r--chromium/net/quic/quic_headers_stream.cc28
-rw-r--r--chromium/net/quic/quic_headers_stream.h1
-rw-r--r--chromium/net/quic/quic_headers_stream_test.cc274
-rw-r--r--chromium/net/quic/quic_http_stream.cc265
-rw-r--r--chromium/net/quic/quic_http_stream.h36
-rw-r--r--chromium/net/quic/quic_http_stream_test.cc889
-rw-r--r--chromium/net/quic/quic_multipath_received_packet_manager.cc50
-rw-r--r--chromium/net/quic/quic_multipath_received_packet_manager.h6
-rw-r--r--chromium/net/quic/quic_multipath_received_packet_manager_test.cc28
-rw-r--r--chromium/net/quic/quic_multipath_transmissions_map.cc4
-rw-r--r--chromium/net/quic/quic_multipath_transmissions_map.h20
-rw-r--r--chromium/net/quic/quic_multipath_transmissions_map_test.cc4
-rw-r--r--chromium/net/quic/quic_network_transaction_unittest.cc677
-rw-r--r--chromium/net/quic/quic_one_block_arena.h77
-rw-r--r--chromium/net/quic/quic_one_block_arena_test.cc58
-rw-r--r--chromium/net/quic/quic_packet_creator.cc567
-rw-r--r--chromium/net/quic/quic_packet_creator.h257
-rw-r--r--chromium/net/quic/quic_packet_creator_test.cc873
-rw-r--r--chromium/net/quic/quic_packet_generator.cc161
-rw-r--r--chromium/net/quic/quic_packet_generator.h72
-rw-r--r--chromium/net/quic/quic_packet_generator_test.cc1067
-rw-r--r--chromium/net/quic/quic_packet_writer.h31
-rw-r--r--chromium/net/quic/quic_protocol.cc287
-rw-r--r--chromium/net/quic/quic_protocol.h346
-rw-r--r--chromium/net/quic/quic_protocol_test.cc9
-rw-r--r--chromium/net/quic/quic_received_packet_manager.cc52
-rw-r--r--chromium/net/quic/quic_received_packet_manager.h17
-rw-r--r--chromium/net/quic/quic_received_packet_manager_test.cc76
-rw-r--r--chromium/net/quic/quic_sent_packet_manager.cc298
-rw-r--r--chromium/net/quic/quic_sent_packet_manager.h104
-rw-r--r--chromium/net/quic/quic_sent_packet_manager_test.cc337
-rw-r--r--chromium/net/quic/quic_session.cc346
-rw-r--r--chromium/net/quic/quic_session.h91
-rw-r--r--chromium/net/quic/quic_session_test.cc273
-rw-r--r--chromium/net/quic/quic_simple_buffer_allocator.cc4
-rw-r--r--chromium/net/quic/quic_simple_buffer_allocator.h1
-rw-r--r--chromium/net/quic/quic_socket_address_coder.cc5
-rw-r--r--chromium/net/quic/quic_socket_address_coder.h4
-rw-r--r--chromium/net/quic/quic_socket_address_coder_test.cc12
-rw-r--r--chromium/net/quic/quic_spdy_session.cc14
-rw-r--r--chromium/net/quic/quic_spdy_session.h6
-rw-r--r--chromium/net/quic/quic_spdy_stream.cc84
-rw-r--r--chromium/net/quic/quic_spdy_stream.h27
-rw-r--r--chromium/net/quic/quic_spdy_stream_test.cc163
-rw-r--r--chromium/net/quic/quic_stream_factory.cc422
-rw-r--r--chromium/net/quic/quic_stream_factory.h76
-rw-r--r--chromium/net/quic/quic_stream_factory_test.cc1418
-rw-r--r--chromium/net/quic/quic_stream_sequencer.cc78
-rw-r--r--chromium/net/quic/quic_stream_sequencer.h5
-rw-r--r--chromium/net/quic/quic_stream_sequencer_buffer.cc (renamed from chromium/net/quic/stream_sequencer_buffer.cc)129
-rw-r--r--chromium/net/quic/quic_stream_sequencer_buffer.h (renamed from chromium/net/quic/stream_sequencer_buffer.h)99
-rw-r--r--chromium/net/quic/quic_stream_sequencer_buffer_test.cc (renamed from chromium/net/quic/stream_sequencer_buffer_test.cc)429
-rw-r--r--chromium/net/quic/quic_stream_sequencer_test.cc202
-rw-r--r--chromium/net/quic/quic_unacked_packet_map.cc170
-rw-r--r--chromium/net/quic/quic_unacked_packet_map.h16
-rw-r--r--chromium/net/quic/quic_unacked_packet_map_test.cc91
-rw-r--r--chromium/net/quic/quic_utils.cc152
-rw-r--r--chromium/net/quic/quic_utils.h35
-rw-r--r--chromium/net/quic/quic_utils_test.cc73
-rw-r--r--chromium/net/quic/quic_write_blocked_list.h101
-rw-r--r--chromium/net/quic/quic_write_blocked_list_test.cc92
-rw-r--r--chromium/net/quic/reliable_quic_stream.cc40
-rw-r--r--chromium/net/quic/reliable_quic_stream.h19
-rw-r--r--chromium/net/quic/reliable_quic_stream_test.cc170
-rw-r--r--chromium/net/quic/spdy_utils.cc23
-rw-r--r--chromium/net/quic/spdy_utils.h5
-rw-r--r--chromium/net/quic/spdy_utils_test.cc24
-rw-r--r--chromium/net/quic/test_tools/crypto_test_utils.cc16
-rw-r--r--chromium/net/quic/test_tools/crypto_test_utils_chromium.cc17
-rw-r--r--chromium/net/quic/test_tools/mock_crypto_client_stream.cc32
-rw-r--r--chromium/net/quic/test_tools/mock_crypto_client_stream.h19
-rw-r--r--chromium/net/quic/test_tools/mock_crypto_client_stream_factory.cc2
-rw-r--r--chromium/net/quic/test_tools/mock_crypto_client_stream_factory.h6
-rw-r--r--chromium/net/quic/test_tools/mock_quic_client_promised_info.cc21
-rw-r--r--chromium/net/quic/test_tools/mock_quic_client_promised_info.h33
-rw-r--r--chromium/net/quic/test_tools/mock_quic_dispatcher.cc5
-rw-r--r--chromium/net/quic/test_tools/mock_quic_dispatcher.h4
-rw-r--r--chromium/net/quic/test_tools/mock_quic_spdy_client_stream.cc19
-rw-r--r--chromium/net/quic/test_tools/mock_quic_spdy_client_stream.h34
-rw-r--r--chromium/net/quic/test_tools/quic_config_peer.cc5
-rw-r--r--chromium/net/quic/test_tools/quic_config_peer.h1
-rw-r--r--chromium/net/quic/test_tools/quic_connection_peer.cc30
-rw-r--r--chromium/net/quic/test_tools/quic_connection_peer.h14
-rw-r--r--chromium/net/quic/test_tools/quic_framer_peer.cc6
-rw-r--r--chromium/net/quic/test_tools/quic_framer_peer.h2
-rw-r--r--chromium/net/quic/test_tools/quic_packet_creator_peer.cc85
-rw-r--r--chromium/net/quic/test_tools/quic_packet_creator_peer.h20
-rw-r--r--chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc38
-rw-r--r--chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h8
-rw-r--r--chromium/net/quic/test_tools/quic_session_peer.cc14
-rw-r--r--chromium/net/quic/test_tools/quic_session_peer.h9
-rw-r--r--chromium/net/quic/test_tools/quic_stream_factory_peer.cc14
-rw-r--r--chromium/net/quic/test_tools/quic_stream_factory_peer.h6
-rw-r--r--chromium/net/quic/test_tools/quic_stream_sequencer_peer.cc12
-rw-r--r--chromium/net/quic/test_tools/quic_stream_sequencer_peer.h4
-rw-r--r--chromium/net/quic/test_tools/quic_test_packet_maker.cc159
-rw-r--r--chromium/net/quic/test_tools/quic_test_packet_maker.h62
-rw-r--r--chromium/net/quic/test_tools/quic_test_utils.cc154
-rw-r--r--chromium/net/quic/test_tools/quic_test_utils.h133
-rw-r--r--chromium/net/quic/test_tools/reliable_quic_stream_peer.cc6
-rw-r--r--chromium/net/quic/test_tools/reliable_quic_stream_peer.h2
-rw-r--r--chromium/net/quic/test_tools/simple_quic_framer.cc19
-rw-r--r--chromium/net/quic/test_tools/simple_quic_framer.h1
-rw-r--r--chromium/net/sdch/sdch_owner.cc176
-rw-r--r--chromium/net/sdch/sdch_owner.h102
-rw-r--r--chromium/net/sdch/sdch_owner_unittest.cc184
-rw-r--r--chromium/net/server/http_server_request_info.cc3
-rw-r--r--chromium/net/server/http_server_request_info.h1
-rw-r--r--chromium/net/server/http_server_response_info.cc3
-rw-r--r--chromium/net/server/http_server_response_info.h1
-rw-r--r--chromium/net/server/http_server_unittest.cc2
-rw-r--r--chromium/net/server/web_socket_encoder.cc1
-rw-r--r--chromium/net/server/web_socket_encoder.h2
-rw-r--r--chromium/net/socket/client_socket_handle.cc2
-rw-r--r--chromium/net/socket/client_socket_handle.h8
-rw-r--r--chromium/net/socket/client_socket_pool.h13
-rw-r--r--chromium/net/socket/client_socket_pool_base.cc22
-rw-r--r--chromium/net/socket/client_socket_pool_base.h42
-rw-r--r--chromium/net/socket/client_socket_pool_base_unittest.cc1133
-rw-r--r--chromium/net/socket/client_socket_pool_manager.cc29
-rw-r--r--chromium/net/socket/client_socket_pool_manager_impl.h5
-rw-r--r--chromium/net/socket/next_proto.cc29
-rw-r--r--chromium/net/socket/next_proto.h10
-rw-r--r--chromium/net/socket/nss_ssl_util.cc5
-rw-r--r--chromium/net/socket/sequenced_socket_data_unittest.cc4
-rw-r--r--chromium/net/socket/server_socket.cc8
-rw-r--r--chromium/net/socket/server_socket.h2
-rw-r--r--chromium/net/socket/socket_net_log_params.cc1
-rw-r--r--chromium/net/socket/socket_posix.cc2
-rw-r--r--chromium/net/socket/socket_test_util.cc139
-rw-r--r--chromium/net/socket/socket_test_util.h40
-rw-r--r--chromium/net/socket/socks5_client_socket.cc9
-rw-r--r--chromium/net/socket/socks5_client_socket.h1
-rw-r--r--chromium/net/socket/socks_client_socket.cc12
-rw-r--r--chromium/net/socket/socks_client_socket.h1
-rw-r--r--chromium/net/socket/socks_client_socket_pool.cc50
-rw-r--r--chromium/net/socket/socks_client_socket_pool.h4
-rw-r--r--chromium/net/socket/socks_client_socket_pool_unittest.cc42
-rw-r--r--chromium/net/socket/ssl_client_socket.h14
-rw-r--r--chromium/net/socket/ssl_client_socket_nss.cc153
-rw-r--r--chromium/net/socket/ssl_client_socket_nss.h7
-rw-r--r--chromium/net/socket/ssl_client_socket_openssl.cc281
-rw-r--r--chromium/net/socket/ssl_client_socket_openssl.h15
-rw-r--r--chromium/net/socket/ssl_client_socket_openssl_unittest.cc267
-rw-r--r--chromium/net/socket/ssl_client_socket_pool.cc55
-rw-r--r--chromium/net/socket/ssl_client_socket_pool.h4
-rw-r--r--chromium/net/socket/ssl_client_socket_pool_unittest.cc113
-rw-r--r--chromium/net/socket/ssl_client_socket_unittest.cc149
-rw-r--r--chromium/net/socket/ssl_server_socket.h26
-rw-r--r--chromium/net/socket/ssl_server_socket_nss.cc240
-rw-r--r--chromium/net/socket/ssl_server_socket_nss.h126
-rw-r--r--chromium/net/socket/ssl_server_socket_openssl.cc397
-rw-r--r--chromium/net/socket/ssl_server_socket_openssl.h126
-rw-r--r--chromium/net/socket/ssl_server_socket_unittest.cc617
-rw-r--r--chromium/net/socket/ssl_socket.h3
-rw-r--r--chromium/net/socket/stream_socket.h5
-rw-r--r--chromium/net/socket/tcp_client_socket.cc5
-rw-r--r--chromium/net/socket/tcp_client_socket.h1
-rw-r--r--chromium/net/socket/tcp_client_socket_unittest.cc21
-rw-r--r--chromium/net/socket/tcp_server_socket.h3
-rw-r--r--chromium/net/socket/tcp_server_socket_unittest.cc17
-rw-r--r--chromium/net/socket/tcp_socket.cc29
-rw-r--r--chromium/net/socket/tcp_socket.h34
-rw-r--r--chromium/net/socket/tcp_socket_posix.cc16
-rw-r--r--chromium/net/socket/tcp_socket_posix.h2
-rw-r--r--chromium/net/socket/tcp_socket_unittest.cc23
-rw-r--r--chromium/net/socket/tcp_socket_win.cc55
-rw-r--r--chromium/net/socket/tcp_socket_win.h4
-rw-r--r--chromium/net/socket/transport_client_socket_pool.cc37
-rw-r--r--chromium/net/socket/transport_client_socket_pool.h5
-rw-r--r--chromium/net/socket/transport_client_socket_pool_test_util.cc29
-rw-r--r--chromium/net/socket/transport_client_socket_pool_unittest.cc224
-rw-r--r--chromium/net/socket/transport_client_socket_unittest.cc5
-rw-r--r--chromium/net/socket/unix_domain_client_socket_posix.cc17
-rw-r--r--chromium/net/socket/unix_domain_client_socket_posix.h1
-rw-r--r--chromium/net/socket/unix_domain_client_socket_posix_unittest.cc14
-rw-r--r--chromium/net/socket/unix_domain_server_socket_posix.cc14
-rw-r--r--chromium/net/socket/unix_domain_server_socket_posix.h10
-rw-r--r--chromium/net/socket/unix_domain_server_socket_posix_unittest.cc28
-rw-r--r--chromium/net/socket/websocket_endpoint_lock_manager_unittest.cc7
-rw-r--r--chromium/net/socket/websocket_transport_client_socket_pool.cc35
-rw-r--r--chromium/net/socket/websocket_transport_client_socket_pool.h3
-rw-r--r--chromium/net/socket/websocket_transport_client_socket_pool_unittest.cc142
-rw-r--r--chromium/net/spdy/bidirectional_stream_spdy_impl.cc (renamed from chromium/net/spdy/bidirectional_stream_spdy_job.cc)57
-rw-r--r--chromium/net/spdy/bidirectional_stream_spdy_impl.h (renamed from chromium/net/spdy/bidirectional_stream_spdy_job.h)26
-rw-r--r--chromium/net/spdy/buffered_spdy_framer.cc60
-rw-r--r--chromium/net/spdy/buffered_spdy_framer.h64
-rw-r--r--chromium/net/spdy/buffered_spdy_framer_unittest.cc54
-rw-r--r--chromium/net/spdy/hpack/hpack_decoder.cc5
-rw-r--r--chromium/net/spdy/hpack/hpack_decoder.h2
-rw-r--r--chromium/net/spdy/hpack/hpack_decoder_test.cc32
-rw-r--r--chromium/net/spdy/hpack/hpack_header_table.cc122
-rw-r--r--chromium/net/spdy/hpack/hpack_header_table.h35
-rw-r--r--chromium/net/spdy/hpack/hpack_header_table_test.cc47
-rw-r--r--chromium/net/spdy/hpack/hpack_static_table.cc5
-rw-r--r--chromium/net/spdy/hpack/hpack_static_table.h8
-rw-r--r--chromium/net/spdy/hpack/hpack_static_table_test.cc11
-rw-r--r--chromium/net/spdy/http2_priority_dependencies.cc51
-rw-r--r--chromium/net/spdy/http2_priority_dependencies.h60
-rw-r--r--chromium/net/spdy/http2_priority_dependencies_unittest.cc144
-rw-r--r--chromium/net/spdy/http2_write_scheduler.h739
-rw-r--r--chromium/net/spdy/http2_write_scheduler_test.cc675
-rw-r--r--chromium/net/spdy/mock_spdy_framer_visitor.h1
-rw-r--r--chromium/net/spdy/priority_write_scheduler.h31
-rw-r--r--chromium/net/spdy/priority_write_scheduler_test.cc27
-rw-r--r--chromium/net/spdy/spdy_alt_svc_wire_format.cc4
-rw-r--r--chromium/net/spdy/spdy_alt_svc_wire_format.h1
-rw-r--r--chromium/net/spdy/spdy_buffer.cc18
-rw-r--r--chromium/net/spdy/spdy_buffer.h8
-rw-r--r--chromium/net/spdy/spdy_buffer_unittest.cc8
-rw-r--r--chromium/net/spdy/spdy_frame_builder.cc15
-rw-r--r--chromium/net/spdy/spdy_frame_builder.h6
-rw-r--r--chromium/net/spdy/spdy_frame_builder_test.cc28
-rw-r--r--chromium/net/spdy/spdy_framer.cc619
-rw-r--r--chromium/net/spdy/spdy_framer.h76
-rw-r--r--chromium/net/spdy/spdy_framer_test.cc1889
-rw-r--r--chromium/net/spdy/spdy_header_block.cc3
-rw-r--r--chromium/net/spdy/spdy_header_block.h5
-rw-r--r--chromium/net/spdy/spdy_headers_handler_interface.h9
-rw-r--r--chromium/net/spdy/spdy_http_stream.cc13
-rw-r--r--chromium/net/spdy/spdy_http_stream.h2
-rw-r--r--chromium/net/spdy/spdy_http_stream_unittest.cc103
-rw-r--r--chromium/net/spdy/spdy_http_utils.cc25
-rw-r--r--chromium/net/spdy/spdy_http_utils.h8
-rw-r--r--chromium/net/spdy/spdy_network_transaction_unittest.cc2169
-rw-r--r--chromium/net/spdy/spdy_priority_tree.h563
-rw-r--r--chromium/net/spdy/spdy_priority_tree_test.cc607
-rw-r--r--chromium/net/spdy/spdy_protocol.cc34
-rw-r--r--chromium/net/spdy/spdy_protocol.h69
-rw-r--r--chromium/net/spdy/spdy_proxy_client_socket.cc7
-rw-r--r--chromium/net/spdy/spdy_proxy_client_socket.h1
-rw-r--r--chromium/net/spdy/spdy_proxy_client_socket_unittest.cc253
-rw-r--r--chromium/net/spdy/spdy_session.cc383
-rw-r--r--chromium/net/spdy/spdy_session.h132
-rw-r--r--chromium/net/spdy/spdy_session_key.cc2
-rw-r--r--chromium/net/spdy/spdy_session_key.h2
-rw-r--r--chromium/net/spdy/spdy_session_pool.cc95
-rw-r--r--chromium/net/spdy/spdy_session_pool.h36
-rw-r--r--chromium/net/spdy/spdy_session_pool_unittest.cc48
-rw-r--r--chromium/net/spdy/spdy_session_unittest.cc667
-rw-r--r--chromium/net/spdy/spdy_stream.cc7
-rw-r--r--chromium/net/spdy/spdy_stream.h4
-rw-r--r--chromium/net/spdy/spdy_stream_unittest.cc192
-rw-r--r--chromium/net/spdy/spdy_test_util_common.cc456
-rw-r--r--chromium/net/spdy/spdy_test_util_common.h320
-rw-r--r--chromium/net/spdy/spdy_test_utils.cc64
-rw-r--r--chromium/net/spdy/spdy_test_utils.h28
-rw-r--r--chromium/net/spdy/spdy_write_queue.cc2
-rw-r--r--chromium/net/spdy/spdy_write_queue.h1
-rw-r--r--chromium/net/spdy/spdy_write_queue_unittest.cc9
-rw-r--r--chromium/net/ssl/channel_id_service.cc7
-rw-r--r--chromium/net/ssl/channel_id_service.h5
-rw-r--r--chromium/net/ssl/channel_id_store.h4
-rw-r--r--chromium/net/ssl/client_cert_store_mac.cc7
-rw-r--r--chromium/net/ssl/client_cert_store_nss.cc18
-rw-r--r--chromium/net/ssl/client_cert_store_nss.h3
-rw-r--r--chromium/net/ssl/client_cert_store_nss_unittest.cc2
-rw-r--r--chromium/net/ssl/default_channel_id_store.cc4
-rw-r--r--chromium/net/ssl/default_channel_id_store.h1
-rw-r--r--chromium/net/ssl/openssl_ssl_util.cc39
-rw-r--r--chromium/net/ssl/openssl_ssl_util.h13
-rw-r--r--chromium/net/ssl/scoped_openssl_types.h15
-rw-r--r--chromium/net/ssl/signed_certificate_timestamp_and_status.cc3
-rw-r--r--chromium/net/ssl/signed_certificate_timestamp_and_status.h3
-rw-r--r--chromium/net/ssl/ssl_cert_request_info.h2
-rw-r--r--chromium/net/ssl/ssl_client_session_cache_openssl.cc8
-rw-r--r--chromium/net/ssl/ssl_client_session_cache_openssl.h5
-rw-r--r--chromium/net/ssl/ssl_config.cc4
-rw-r--r--chromium/net/ssl/ssl_config.h14
-rw-r--r--chromium/net/ssl/ssl_info.cc18
-rw-r--r--chromium/net/ssl/ssl_info.h38
-rw-r--r--chromium/net/ssl/ssl_platform_key_chromecast.cc136
-rw-r--r--chromium/net/ssl/ssl_platform_key_mac.cc7
-rw-r--r--chromium/net/ssl/ssl_platform_key_win.cc3
-rw-r--r--chromium/net/ssl/ssl_server_config.cc5
-rw-r--r--chromium/net/ssl/ssl_server_config.h27
-rw-r--r--chromium/net/ssl/test_ssl_private_key.cc128
-rw-r--r--chromium/net/ssl/test_ssl_private_key.h25
-rw-r--r--chromium/net/ssl/threaded_ssl_private_key.h1
-rw-r--r--chromium/net/ssl/token_binding.h117
-rw-r--r--chromium/net/ssl/token_binding_nss.cc51
-rw-r--r--chromium/net/ssl/token_binding_openssl.cc166
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/IEmbeddedTestServerImpl.aidl8
-rw-r--r--chromium/net/test/cert_test_util_nss.cc2
-rw-r--r--chromium/net/test/ct_test_util.cc34
-rw-r--r--chromium/net/test/ct_test_util.h20
-rw-r--r--chromium/net/test/embedded_test_server/android/embedded_test_server_android.cc9
-rw-r--r--chromium/net/test/embedded_test_server/android/embedded_test_server_android.h5
-rw-r--r--chromium/net/test/embedded_test_server/default_handlers.cc3
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server.cc42
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server.h8
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server_unittest.cc10
-rw-r--r--chromium/net/test/embedded_test_server/http_request.cc4
-rw-r--r--chromium/net/test/embedded_test_server/http_request.h2
-rw-r--r--chromium/net/test/embedded_test_server/request_handler_util.cc7
-rw-r--r--chromium/net/test/net_test_suite.cc4
-rw-r--r--chromium/net/test/run_all_unittests.cc6
-rw-r--r--chromium/net/test/spawned_test_server/base_test_server.cc2
-rw-r--r--chromium/net/test/spawned_test_server/base_test_server.h1
-rw-r--r--chromium/net/test/url_request/url_request_failed_job.cc1
-rw-r--r--chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp6
-rw-r--r--chromium/net/third_party/nist-pkits/BUILD.gn12
-rw-r--r--chromium/net/third_party/nist-pkits/README.chromium19
-rw-r--r--chromium/net/third_party/nist-pkits/certs/AllCertificatesNoPoliciesTest2EE.crtbin0 -> 898 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/AllCertificatesSamePoliciesTest10EE.crtbin0 -> 941 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/AllCertificatesSamePoliciesTest13EE.crtbin0 -> 958 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/AllCertificatesanyPolicyTest11EE.crtbin0 -> 914 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/AnyPolicyTest14EE.crtbin0 -> 903 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/BadCRLIssuerNameCACert.crtbin0 -> 911 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/BadCRLSignatureCACert.crtbin0 -> 909 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/BadSignedCACert.crtbin0 -> 902 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/BadnotAfterDateCACert.crtbin0 -> 909 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/BadnotBeforeDateCACert.crtbin0 -> 910 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCACert.crtbin0 -> 925 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crtbin0 -> 1074 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedNewKeyCACert.crtbin0 -> 917 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crtbin0 -> 933 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedOldKeyCACert.crtbin0 -> 917 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crtbin0 -> 1067 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/CPSPointerQualifierTest20EE.crtbin0 -> 1011 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/DSACACert.crtbin0 -> 1045 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/DSAParametersInheritedCACert.crtbin0 -> 546 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest12EE.crtbin0 -> 914 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest3EE.crtbin0 -> 916 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest4EE.crtbin0 -> 909 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest5EE.crtbin0 -> 917 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest7EE.crtbin0 -> 943 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest8EE.crtbin0 -> 941 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest9EE.crtbin0 -> 931 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/GeneralizedTimeCRLnextUpdateCACert.crtbin0 -> 920 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/GoodCACert.crtbin0 -> 896 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/GoodsubCACert.crtbin0 -> 910 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/GoodsubCAPanyPolicyMapping1to2CACert.crtbin0 -> 968 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidBadCRLIssuerNameTest5EE.crtbin0 -> 930 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidBadCRLSignatureTest4EE.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crtbin0 -> 958 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crtbin0 -> 958 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crtbin0 -> 947 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crtbin0 -> 947 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidCASignatureTest2EE.crtbin0 -> 899 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidCAnotAfterDateTest5EE.crtbin0 -> 925 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidCAnotBeforeDateTest1EE.crtbin0 -> 927 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNSnameConstraintsTest31EE.crtbin0 -> 981 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNSnameConstraintsTest33EE.crtbin0 -> 970 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNSnameConstraintsTest38EE.crtbin0 -> 969 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest28EE.crtbin0 -> 1049 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest29EE.crtbin0 -> 1051 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest10EE.crtbin0 -> 986 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest12EE.crtbin0 -> 991 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest13EE.crtbin0 -> 991 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest15EE.crtbin0 -> 962 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest16EE.crtbin0 -> 962 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest17EE.crtbin0 -> 962 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest20EE.crtbin0 -> 904 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest2EE.crtbin0 -> 957 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest3EE.crtbin0 -> 1113 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest7EE.crtbin0 -> 957 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest8EE.crtbin0 -> 957 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest9EE.crtbin0 -> 957 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidDSASignatureTest6EE.crtbin0 -> 851 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidEESignatureTest3EE.crtbin0 -> 893 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidEEnotAfterDateTest6EE.crtbin0 -> 912 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidEEnotBeforeDateTest2EE.crtbin0 -> 913 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidIDPwithindirectCRLTest23EE.crtbin0 -> 925 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidIDPwithindirectCRLTest26EE.crtbin0 -> 1019 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidLongSerialNumberTest18EE.crtbin0 -> 948 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidMappingFromanyPolicyTest7EE.crtbin0 -> 936 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidMappingToanyPolicyTest8EE.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidMissingCRLTest1EE.crtbin0 -> 909 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidMissingbasicConstraintsTest1EE.crtbin0 -> 940 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidNameChainingOrderTest2EE.crtbin0 -> 999 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidNameChainingTest1EE.crtbin0 -> 914 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidNegativeSerialNumberTest15EE.crtbin0 -> 937 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidOldCRLnextUpdateTest11EE.crtbin0 -> 929 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidPolicyMappingTest10EE.crtbin0 -> 938 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidPolicyMappingTest2EE.crtbin0 -> 918 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidPolicyMappingTest4EE.crtbin0 -> 928 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidRFC822nameConstraintsTest22EE.crtbin0 -> 982 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidRFC822nameConstraintsTest24EE.crtbin0 -> 993 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidRFC822nameConstraintsTest26EE.crtbin0 -> 982 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidRevokedCATest2EE.crtbin0 -> 909 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidRevokedEETest3EE.crtbin0 -> 903 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crtbin0 -> 919 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crtbin0 -> 944 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crtbin0 -> 952 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crtbin0 -> 952 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crtbin0 -> 954 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crtbin0 -> 954 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crtbin0 -> 944 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crtbin0 -> 925 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crtbin0 -> 925 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crtbin0 -> 960 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crtbin0 -> 960 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidURInameConstraintsTest35EE.crtbin0 -> 987 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidURInameConstraintsTest37EE.crtbin0 -> 987 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidUnknownCRLEntryExtensionTest8EE.crtbin0 -> 946 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidUnknownCRLExtensionTest10EE.crtbin0 -> 935 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidUnknownCRLExtensionTest9EE.crtbin0 -> 934 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crtbin0 -> 954 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidWrongCRLTest6EE.crtbin0 -> 910 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidcAFalseTest2EE.crtbin0 -> 934 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidcAFalseTest3EE.crtbin0 -> 938 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest27EE.crtbin0 -> 999 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest31EE.crtbin0 -> 1136 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest32EE.crtbin0 -> 1136 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest34EE.crtbin0 -> 1044 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest35EE.crtbin0 -> 1128 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crtbin0 -> 942 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest10EE.crtbin0 -> 1094 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest3EE.crtbin0 -> 1093 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest4EE.crtbin0 -> 1093 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest6EE.crtbin0 -> 1093 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest9EE.crtbin0 -> 1093 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest2EE.crtbin0 -> 1071 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest3EE.crtbin0 -> 1071 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest6EE.crtbin0 -> 984 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest8EE.crtbin0 -> 1028 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest9EE.crtbin0 -> 927 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest1EE.crtbin0 -> 919 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest4EE.crtbin0 -> 923 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest5EE.crtbin0 -> 925 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest6EE.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest1EE.crtbin0 -> 950 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest3EE.crtbin0 -> 943 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest5EE.crtbin0 -> 942 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest6EE.crtbin0 -> 947 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crtbin0 -> 954 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crtbin0 -> 962 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crtbin0 -> 962 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crtbin0 -> 963 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidonlyContainsAttributeCertsTest14EE.crtbin0 -> 945 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidonlyContainsCACertsTest12EE.crtbin0 -> 931 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidonlyContainsUserCertsTest11EE.crtbin0 -> 952 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest15EE.crtbin0 -> 924 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest16EE.crtbin0 -> 924 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest17EE.crtbin0 -> 924 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest20EE.crtbin0 -> 1153 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest21EE.crtbin0 -> 1153 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest10EE.crtbin0 -> 953 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest11EE.crtbin0 -> 940 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest12EE.crtbin0 -> 957 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest5EE.crtbin0 -> 930 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest6EE.crtbin0 -> 947 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest9EE.crtbin0 -> 935 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/Invalidpre2000CRLnextUpdateTest12EE.crtbin0 -> 937 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidrequireExplicitPolicyTest3EE.crtbin0 -> 919 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/InvalidrequireExplicitPolicyTest5EE.crtbin0 -> 925 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/LongSerialNumberCACert.crtbin0 -> 910 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/Mapping1to2CACert.crtbin0 -> 960 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/MappingFromanyPolicyCACert.crtbin0 -> 961 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/MappingToanyPolicyCACert.crtbin0 -> 965 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/MissingbasicConstraintsCACert.crtbin0 -> 899 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/NameOrderingCACert.crtbin0 -> 980 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/NegativeSerialNumberCACert.crtbin0 -> 914 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/NoCRLCACert.crtbin0 -> 898 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/NoPoliciesCACert.crtbin0 -> 878 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/NoissuingDistributionPointCACert.crtbin0 -> 919 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/OldCRLnextUpdateCACert.crtbin0 -> 910 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/OverlappingPoliciesTest6EE.crtbin0 -> 948 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/P12Mapping1to3CACert.crtbin0 -> 978 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/P12Mapping1to3subCACert.crtbin0 -> 1000 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/P12Mapping1to3subsubCACert.crtbin0 -> 980 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/P1Mapping1to234CACert.crtbin0 -> 1017 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/P1Mapping1to234subCACert.crtbin0 -> 1002 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/P1anyPolicyMapping1to2CACert.crtbin0 -> 1329 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PanyPolicyMapping1to2CACert.crtbin0 -> 965 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP1234CACert.crtbin0 -> 964 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP1234subCAP123Cert.crtbin0 -> 948 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP1234subsubCAP123P12Cert.crtbin0 -> 947 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP123CACert.crtbin0 -> 949 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP123subCAP12Cert.crtbin0 -> 931 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP123subsubCAP12P1Cert.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP123subsubCAP12P2Cert.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP123subsubsubCAP12P2P1Cert.crtbin0 -> 936 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP12CACert.crtbin0 -> 934 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP12subCAP1Cert.crtbin0 -> 912 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP12subsubCAP1P2Cert.crtbin0 -> 922 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP2subCA2Cert.crtbin0 -> 918 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP2subCACert.crtbin0 -> 901 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/PoliciesP3CACert.crtbin0 -> 919 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/RFC3280MandatoryAttributeTypesCACert.crtbin0 -> 980 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/RFC3280OptionalAttributeTypesCACert.crtbin0 -> 992 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/RevokedsubCACert.crtbin0 -> 897 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/RolloverfromPrintableStringtoUTF8StringCACert.crtbin0 -> 935 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crtbin0 -> 909 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCRLSigningCert.crtbin0 -> 909 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/TrustAnchorRootCertificate.crtbin0 -> 843 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/TwoCRLsCACert.crtbin0 -> 900 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/UIDCACert.crtbin0 -> 900 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/UTF8StringCaseInsensitiveMatchCACert.crtbin0 -> 925 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/UTF8StringEncodedNamesCACert.crtbin0 -> 902 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/UnknownCRLEntryExtensionCACert.crtbin0 -> 919 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/UnknownCRLExtensionCACert.crtbin0 -> 913 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest15EE.crtbin0 -> 1026 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest16EE.crtbin0 -> 1145 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest17EE.crtbin0 -> 1014 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest18EE.crtbin0 -> 1240 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest19EE.crtbin0 -> 1263 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crtbin0 -> 956 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crtbin0 -> 945 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crtbin0 -> 945 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crtbin0 -> 945 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidCertificatePathTest1EE.crtbin0 -> 893 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDNSnameConstraintsTest30EE.crtbin0 -> 976 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDNSnameConstraintsTest32EE.crtbin0 -> 976 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDNandRFC822nameConstraintsTest27EE.crtbin0 -> 1044 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest11EE.crtbin0 -> 985 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest14EE.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest18EE.crtbin0 -> 932 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest19EE.crtbin0 -> 957 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest1EE.crtbin0 -> 956 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest4EE.crtbin0 -> 1016 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest5EE.crtbin0 -> 1109 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest6EE.crtbin0 -> 956 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDSAParameterInheritanceTest5EE.crtbin0 -> 574 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidDSASignaturesTest4EE.crtbin0 -> 835 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crtbin0 -> 949 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidGeneralizedTimenotAfterDateTest8EE.crtbin0 -> 925 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidIDPwithindirectCRLTest22EE.crtbin0 -> 923 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidIDPwithindirectCRLTest24EE.crtbin0 -> 1016 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidIDPwithindirectCRLTest25EE.crtbin0 -> 1016 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidLongSerialNumberTest16EE.crtbin0 -> 946 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidLongSerialNumberTest17EE.crtbin0 -> 946 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidNameChainingCapitalizationTest5EE.crtbin0 -> 922 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidNameChainingWhitespaceTest3EE.crtbin0 -> 923 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidNameChainingWhitespaceTest4EE.crtbin0 -> 924 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidNameUIDsTest6EE.crtbin0 -> 901 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidNegativeSerialNumberTest14EE.crtbin0 -> 936 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidNoissuingDistributionPointTest10EE.crtbin0 -> 1069 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest11EE.crtbin0 -> 936 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest12EE.crtbin0 -> 1339 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest13EE.crtbin0 -> 929 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest14EE.crtbin0 -> 929 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest1EE.crtbin0 -> 916 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest3EE.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest5EE.crtbin0 -> 924 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest6EE.crtbin0 -> 924 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest9EE.crtbin0 -> 927 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crtbin0 -> 1011 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crtbin0 -> 1022 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidRFC822nameConstraintsTest21EE.crtbin0 -> 991 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidRFC822nameConstraintsTest23EE.crtbin0 -> 980 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidRFC822nameConstraintsTest25EE.crtbin0 -> 991 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crtbin0 -> 965 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crtbin0 -> 939 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crtbin0 -> 939 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crtbin0 -> 949 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest15EE.crtbin0 -> 938 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest17EE.crtbin0 -> 941 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crtbin0 -> 920 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidSeparateCertificateandCRLKeysTest19EE.crtbin0 -> 958 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidTwoCRLsTest7EE.crtbin0 -> 906 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidURInameConstraintsTest34EE.crtbin0 -> 994 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidURInameConstraintsTest36EE.crtbin0 -> 997 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crtbin0 -> 962 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidUTF8StringEncodedNamesTest9EE.crtbin0 -> 924 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crtbin0 -> 952 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidbasicConstraintsNotCriticalTest4EE.crtbin0 -> 948 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest28EE.crtbin0 -> 1156 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest29EE.crtbin0 -> 1065 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest30EE.crtbin0 -> 1156 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest33EE.crtbin0 -> 1134 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest2EE.crtbin0 -> 1091 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest5EE.crtbin0 -> 1091 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest7EE.crtbin0 -> 1091 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest8EE.crtbin0 -> 1091 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest1EE.crtbin0 -> 1069 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest4EE.crtbin0 -> 982 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest5EE.crtbin0 -> 982 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest7EE.crtbin0 -> 1069 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidinhibitAnyPolicyTest2EE.crtbin0 -> 931 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidinhibitPolicyMappingTest2EE.crtbin0 -> 938 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidinhibitPolicyMappingTest4EE.crtbin0 -> 941 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidkeyUsageNotCriticalTest3EE.crtbin0 -> 932 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidonlyContainsCACertsTest13EE.crtbin0 -> 946 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidonlySomeReasonsTest18EE.crtbin0 -> 1035 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidonlySomeReasonsTest19EE.crtbin0 -> 1151 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest13EE.crtbin0 -> 938 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest14EE.crtbin0 -> 955 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest7EE.crtbin0 -> 925 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest8EE.crtbin0 -> 942 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/Validpre2000UTCnotBeforeDateTest3EE.crtbin0 -> 920 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidrequireExplicitPolicyTest1EE.crtbin0 -> 918 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidrequireExplicitPolicyTest2EE.crtbin0 -> 917 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/ValidrequireExplicitPolicyTest4EE.crtbin0 -> 942 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/WrongCRLCACert.crtbin0 -> 901 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/anyPolicyCACert.crtbin0 -> 911 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/basicConstraintsCriticalcAFalseCACert.crtbin0 -> 923 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/basicConstraintsNotCriticalCACert.crtbin0 -> 918 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/basicConstraintsNotCriticalcAFalseCACert.crtbin0 -> 924 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/deltaCRLCA1Cert.crtbin0 -> 901 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/deltaCRLCA2Cert.crtbin0 -> 901 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/deltaCRLCA3Cert.crtbin0 -> 901 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/deltaCRLIndicatorNoBaseCACert.crtbin0 -> 917 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/distributionPoint1CACert.crtbin0 -> 910 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/distributionPoint2CACert.crtbin0 -> 910 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/indirectCRLCA1Cert.crtbin0 -> 904 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/indirectCRLCA2Cert.crtbin0 -> 904 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/indirectCRLCA3Cert.crtbin0 -> 904 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/indirectCRLCA3cRLIssuerCert.crtbin0 -> 1010 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/indirectCRLCA4Cert.crtbin0 -> 904 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/indirectCRLCA4cRLIssuerCert.crtbin0 -> 1144 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/indirectCRLCA5Cert.crtbin0 -> 904 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/indirectCRLCA6Cert.crtbin0 -> 904 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy0CACert.crtbin0 -> 940 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1CACert.crtbin0 -> 940 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedCACert.crtbin0 -> 917 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crtbin0 -> 919 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subCA1Cert.crtbin0 -> 915 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subCA2Cert.crtbin0 -> 915 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subCAIAP5Cert.crtbin0 -> 941 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subsubCA2Cert.crtbin0 -> 922 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy5CACert.crtbin0 -> 940 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy5subCACert.crtbin0 -> 937 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy5subsubCACert.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicyTest3EE.crtbin0 -> 921 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping0CACert.crtbin0 -> 935 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping0subCACert.crtbin0 -> 970 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12CACert.crtbin0 -> 953 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subCACert.crtbin0 -> 1018 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crtbin0 -> 973 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subsubCACert.crtbin0 -> 998 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crtbin0 -> 1006 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1CACert.crtbin0 -> 938 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crtbin0 -> 931 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crtbin0 -> 979 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1subCACert.crtbin0 -> 976 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1subsubCACert.crtbin0 -> 982 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5CACert.crtbin0 -> 935 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5subCACert.crtbin0 -> 947 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5subsubCACert.crtbin0 -> 934 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5subsubsubCACert.crtbin0 -> 982 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/keyUsageCriticalcRLSignFalseCACert.crtbin0 -> 923 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/keyUsageCriticalkeyCertSignFalseCACert.crtbin0 -> 927 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/keyUsageNotCriticalCACert.crtbin0 -> 910 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/keyUsageNotCriticalcRLSignFalseCACert.crtbin0 -> 924 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crtbin0 -> 928 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1CACert.crtbin0 -> 1009 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1SelfIssuedCACert.crtbin0 -> 921 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1subCA1Cert.crtbin0 -> 1079 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1subCA2Cert.crtbin0 -> 1051 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1subCA3Cert.crtbin0 -> 995 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDN2CACert.crtbin0 -> 1095 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDN3CACert.crtbin0 -> 1008 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDN3subCA1Cert.crtbin0 -> 1022 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDN3subCA2Cert.crtbin0 -> 995 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDN4CACert.crtbin0 -> 1093 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDN5CACert.crtbin0 -> 1123 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDNS1CACert.crtbin0 -> 954 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsDNS2CACert.crtbin0 -> 957 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsRFC822CA1Cert.crtbin0 -> 958 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsRFC822CA2Cert.crtbin0 -> 957 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsRFC822CA3Cert.crtbin0 -> 957 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsURI1CACert.crtbin0 -> 955 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/nameConstraintsURI2CACert.crtbin0 -> 957 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/onlyContainsAttributeCertsCACert.crtbin0 -> 918 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/onlyContainsCACertsCACert.crtbin0 -> 911 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/onlyContainsUserCertsCACert.crtbin0 -> 913 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA1Cert.crtbin0 -> 908 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA2Cert.crtbin0 -> 908 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA3Cert.crtbin0 -> 908 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA4Cert.crtbin0 -> 908 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint0CACert.crtbin0 -> 913 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint0SelfIssuedCACert.crtbin0 -> 919 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint0subCA2Cert.crtbin0 -> 923 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint0subCACert.crtbin0 -> 922 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint1CACert.crtbin0 -> 913 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint1SelfIssuedCACert.crtbin0 -> 919 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint1SelfIssuedsubCACert.crtbin0 -> 925 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint1subCACert.crtbin0 -> 922 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint6CACert.crtbin0 -> 913 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subCA0Cert.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subCA1Cert.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subCA4Cert.crtbin0 -> 926 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubCA00Cert.crtbin0 -> 934 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubCA11Cert.crtbin0 -> 934 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubCA41Cert.crtbin0 -> 934 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubsubCA11XCert.crtbin0 -> 939 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubsubCA41XCert.crtbin0 -> 939 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/pre2000CRLnextUpdateCACert.crtbin0 -> 914 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0CACert.crtbin0 -> 933 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0subCACert.crtbin0 -> 930 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0subsubCACert.crtbin0 -> 936 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0subsubsubCACert.crtbin0 -> 942 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10CACert.crtbin0 -> 934 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10subCACert.crtbin0 -> 932 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10subsubCACert.crtbin0 -> 938 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10subsubsubCACert.crtbin0 -> 944 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2CACert.crtbin0 -> 933 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2SelfIssuedCACert.crtbin0 -> 927 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2SelfIssuedsubCACert.crtbin0 -> 933 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2subCACert.crtbin0 -> 930 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4CACert.crtbin0 -> 933 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4subCACert.crtbin0 -> 930 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4subsubCACert.crtbin0 -> 936 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4subsubsubCACert.crtbin0 -> 942 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5CACert.crtbin0 -> 933 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5subCACert.crtbin0 -> 930 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5subsubCACert.crtbin0 -> 936 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5subsubsubCACert.crtbin0 -> 942 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7CACert.crtbin0 -> 933 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7subCARE2Cert.crtbin0 -> 952 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crtbin0 -> 964 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crtbin0 -> 954 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/BadCRLIssuerNameCACRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/BadCRLSignatureCACRL.crlbin0 -> 459 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/BadSignedCACRL.crlbin0 -> 452 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/BadnotAfterDateCACRL.crlbin0 -> 459 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/BadnotBeforeDateCACRL.crlbin0 -> 460 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.crlbin0 -> 511 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crlbin0 -> 618 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedNewKeyCACRL.crlbin0 -> 503 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedOldKeyCACRL.crlbin0 -> 503 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crlbin0 -> 602 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/DSACACRL.crlbin0 -> 225 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/DSAParametersInheritedCACRL.crlbin0 -> 245 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.crlbin0 -> 472 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/GoodCACRL.crlbin0 -> 516 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/GoodsubCACRL.crlbin0 -> 449 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crlbin0 -> 473 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/LongSerialNumberCACRL.crlbin0 -> 515 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/Mapping1to2CACRL.crlbin0 -> 454 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/MappingFromanyPolicyCACRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/MappingToanyPolicyCACRL.crlbin0 -> 462 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/MissingbasicConstraintsCACRL.crlbin0 -> 466 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/NameOrderCACRL.crlbin0 -> 530 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/NegativeSerialNumberCACRL.crlbin0 -> 500 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/NoPoliciesCACRL.crlbin0 -> 453 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/NoissuingDistributionPointCACRL.crlbin0 -> 469 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/OldCRLnextUpdateCACRL.crlbin0 -> 460 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/P12Mapping1to3CACRL.crlbin0 -> 458 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/P12Mapping1to3subCACRL.crlbin0 -> 461 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/P12Mapping1to3subsubCACRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/P1Mapping1to234CACRL.crlbin0 -> 459 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/P1Mapping1to234subCACRL.crlbin0 -> 462 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/P1anyPolicyMapping1to2CACRL.crlbin0 -> 466 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PanyPolicyMapping1to2CACRL.crlbin0 -> 465 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP1234CACRL.crlbin0 -> 456 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP1234subCAP123CRL.crlbin0 -> 463 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP1234subsubCAP123P12CRL.crlbin0 -> 469 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP123CACRL.crlbin0 -> 455 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP123subCAP12CRL.crlbin0 -> 461 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP123subsubCAP12P1CRL.crlbin0 -> 466 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP123subsubCAP2P2CRL.crlbin0 -> 466 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.crlbin0 -> 471 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP12CACRL.crlbin0 -> 454 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP12subCAP1CRL.crlbin0 -> 459 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP12subsubCAP1P2CRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP2subCA2CRL.crlbin0 -> 457 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP2subCACRL.crlbin0 -> 456 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/PoliciesP3CACRL.crlbin0 -> 453 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/RFC3280MandatoryAttributeTypesCACRL.crlbin0 -> 530 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/RFC3280OptionalAttributeTypesCACRL.crlbin0 -> 543 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/RevokedsubCACRL.crlbin0 -> 452 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crlbin0 -> 485 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/SeparateCertificateandCRLKeysCA2CRL.crlbin0 -> 476 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/SeparateCertificateandCRLKeysCRL.crlbin0 -> 512 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/TrustAnchorRootCRL.crlbin0 -> 487 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/TwoCRLsCABadCRL.crlbin0 -> 498 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/TwoCRLsCAGoodCRL.crlbin0 -> 450 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/UIDCACRL.crlbin0 -> 445 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.crlbin0 -> 475 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/UTF8StringEncodedNamesCACRL.crlbin0 -> 452 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/UnknownCRLEntryExtensionCACRL.crlbin0 -> 526 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/UnknownCRLExtensionCACRL.crlbin0 -> 520 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/WrongCRLCACRL.crlbin0 -> 487 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/anyPolicyCACRL.crlbin0 -> 451 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/basicConstraintsCriticalcAFalseCACRL.crlbin0 -> 476 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/basicConstraintsNotCriticalCACRL.crlbin0 -> 471 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.crlbin0 -> 480 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/deltaCRLCA1CRL.crlbin0 -> 648 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/deltaCRLCA1deltaCRL.crlbin0 -> 606 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/deltaCRLCA2CRL.crlbin0 -> 580 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/deltaCRLCA2deltaCRL.crlbin0 -> 502 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/deltaCRLCA3CRL.crlbin0 -> 544 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/deltaCRLCA3deltaCRL.crlbin0 -> 466 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/deltaCRLIndicatorNoBaseCACRL.crlbin0 -> 482 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/distributionPoint1CACRL.crlbin0 -> 641 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/distributionPoint2CACRL.crlbin0 -> 553 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/indirectCRLCA1CRL.crlbin0 -> 507 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/indirectCRLCA3CRL.crlbin0 -> 566 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/indirectCRLCA3cRLIssuerCRL.crlbin0 -> 622 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/indirectCRLCA4cRLIssuerCRL.crlbin0 -> 622 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/indirectCRLCA5CRL.crlbin0 -> 1577 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy0CACRL.crlbin0 -> 459 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1CACRL.crlbin0 -> 459 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subCA1CRL.crlbin0 -> 463 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subCA2CRL.crlbin0 -> 463 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.crlbin0 -> 466 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subsubCA2CRL.crlbin0 -> 466 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy5CACRL.crlbin0 -> 459 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy5subCACRL.crlbin0 -> 462 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy5subsubCACRL.crlbin0 -> 465 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping0CACRL.crlbin0 -> 463 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping0subCACRL.crlbin0 -> 466 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12CACRL.crlbin0 -> 467 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subCACRL.crlbin0 -> 470 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crlbin0 -> 474 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subsubCACRL.crlbin0 -> 473 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crlbin0 -> 477 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P1CACRL.crlbin0 -> 466 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P1subCACRL.crlbin0 -> 469 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P1subsubCACRL.crlbin0 -> 472 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5CACRL.crlbin0 -> 463 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5subCACRL.crlbin0 -> 466 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5subsubCACRL.crlbin0 -> 469 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5subsubsubCACRL.crlbin0 -> 472 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/keyUsageCriticalcRLSignFalseCACRL.crlbin0 -> 473 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.crlbin0 -> 477 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/keyUsageNotCriticalCACRL.crlbin0 -> 463 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.crlbin0 -> 477 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crlbin0 -> 481 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1CACRL.crlbin0 -> 461 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1subCA1CRL.crlbin0 -> 493 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1subCA2CRL.crlbin0 -> 493 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1subCA3CRL.crlbin0 -> 493 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsDN2CACRL.crlbin0 -> 461 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsDN3CACRL.crlbin0 -> 461 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsDN3subCA1CRL.crlbin0 -> 465 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsDN3subCA2CRL.crlbin0 -> 465 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsDN4CACRL.crlbin0 -> 461 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsDN5CACRL.crlbin0 -> 461 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsDNS1CACRL.crlbin0 -> 462 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsDNS2CACRL.crlbin0 -> 462 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsRFC822CA1CRL.crlbin0 -> 465 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsRFC822CA2CRL.crlbin0 -> 465 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsRFC822CA3CRL.crlbin0 -> 465 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsURI1CACRL.crlbin0 -> 462 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/nameConstraintsURI2CACRL.crlbin0 -> 462 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/onlyContainsAttributeCertsCACRL.crlbin0 -> 485 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/onlyContainsCACertsCACRL.crlbin0 -> 478 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/onlyContainsUserCertsCACRL.crlbin0 -> 480 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA1compromiseCRL.crlbin0 -> 512 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA1otherreasonsCRL.crlbin0 -> 513 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA2CRL1.crlbin0 -> 476 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA2CRL2.crlbin0 -> 476 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA3compromiseCRL.crlbin0 -> 577 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA3otherreasonsCRL.crlbin0 -> 578 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA4compromiseCRL.crlbin0 -> 614 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA4otherreasonsCRL.crlbin0 -> 615 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint0CACRL.crlbin0 -> 460 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint0subCA2CRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint0subCACRL.crlbin0 -> 463 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint1CACRL.crlbin0 -> 460 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint1subCACRL.crlbin0 -> 463 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint6CACRL.crlbin0 -> 460 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subCA0CRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subCA1CRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subCA4CRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubCA00CRL.crlbin0 -> 468 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubCA11CRL.crlbin0 -> 468 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubCA41CRL.crlbin0 -> 468 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubsubCA11XCRL.crlbin0 -> 472 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubsubCA41XCRL.crlbin0 -> 472 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/pre2000CRLnextUpdateCACRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0CACRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0subCACRL.crlbin0 -> 467 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0subsubCACRL.crlbin0 -> 470 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0subsubsubCACRL.crlbin0 -> 473 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10CACRL.crlbin0 -> 465 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10subCACRL.crlbin0 -> 468 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10subsubCACRL.crlbin0 -> 471 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10subsubsubCACRL.crlbin0 -> 474 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy2CACRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy2subCACRL.crlbin0 -> 467 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4CACRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4subCACRL.crlbin0 -> 467 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4subsubCACRL.crlbin0 -> 470 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4subsubsubCACRL.crlbin0 -> 473 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5CACRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5subCACRL.crlbin0 -> 467 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5subsubCACRL.crlbin0 -> 470 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5subsubsubCACRL.crlbin0 -> 473 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7CACRL.crlbin0 -> 464 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7subCARE2CRL.crlbin0 -> 470 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crlbin0 -> 476 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crlbin0 -> 479 bytes
-rw-r--r--chromium/net/third_party/nist-pkits/generate_tests.py196
-rw-r--r--chromium/net/third_party/nist-pkits/pkits_testcases-inl.h2035
-rw-r--r--chromium/net/third_party/nss/README.chromium47
-rw-r--r--chromium/net/third_party/nss/patches/aesgcmchromium.patch121
-rwxr-xr-xchromium/net/third_party/nss/patches/applypatches.sh18
-rw-r--r--chromium/net/third_party/nss/patches/cachecerts.patch100
-rw-r--r--chromium/net/third_party/nss/patches/cachelocks.patch84
-rw-r--r--chromium/net/third_party/nss/patches/chacha20poly1305.patch285
-rw-r--r--chromium/net/third_party/nss/patches/channelid.patch547
-rw-r--r--chromium/net/third_party/nss/patches/cipherorder.patch64
-rw-r--r--chromium/net/third_party/nss/patches/clientauth.patch457
-rw-r--r--chromium/net/third_party/nss/patches/didhandshakeresume.patch17
-rw-r--r--chromium/net/third_party/nss/patches/getrequestedclientcerttypes.patch64
-rw-r--r--chromium/net/third_party/nss/patches/nobypass.patch20
-rw-r--r--chromium/net/third_party/nss/patches/nssrwlock.patch238
-rw-r--r--chromium/net/third_party/nss/patches/reorderextensions.patch31
-rw-r--r--chromium/net/third_party/nss/patches/restartclientauth.patch140
-rw-r--r--chromium/net/third_party/nss/patches/secitemarray.patch44
-rw-r--r--chromium/net/third_party/nss/patches/secretexporterlocks.patch35
-rw-r--r--chromium/net/third_party/nss/patches/sessioncache.patch46
-rw-r--r--chromium/net/third_party/nss/patches/signedcertificatetimestamps.patch355
-rw-r--r--chromium/net/third_party/nss/patches/suitebonly.patch22
-rw-r--r--chromium/net/third_party/nss/patches/tls12chromium.patch104
-rw-r--r--chromium/net/third_party/nss/patches/tlsunique.patch84
-rw-r--r--chromium/net/third_party/nss/ssl.gyp85
-rw-r--r--chromium/net/third_party/nss/ssl/BUILD.gn44
-rw-r--r--chromium/net/third_party/nss/ssl/SSLerrs.h553
-rw-r--r--chromium/net/third_party/nss/ssl/authcert.c124
-rw-r--r--chromium/net/third_party/nss/ssl/bodge/nssrenam.h47
-rw-r--r--chromium/net/third_party/nss/ssl/bodge/secitem_array.c151
-rw-r--r--chromium/net/third_party/nss/ssl/cmpcert.c121
-rw-r--r--chromium/net/third_party/nss/ssl/derive.c1288
-rw-r--r--chromium/net/third_party/nss/ssl/dtlscon.c191
-rw-r--r--chromium/net/third_party/nss/ssl/exports_win.def66
-rw-r--r--chromium/net/third_party/nss/ssl/manifest.mn2
-rw-r--r--chromium/net/third_party/nss/ssl/notes.txt134
-rw-r--r--chromium/net/third_party/nss/ssl/os2_err.c200
-rw-r--r--chromium/net/third_party/nss/ssl/os2_err.h4
-rw-r--r--chromium/net/third_party/nss/ssl/preenc.h112
-rw-r--r--chromium/net/third_party/nss/ssl/prelib.c12
-rw-r--r--chromium/net/third_party/nss/ssl/ssl.h490
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3con.c14617
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3ecc.c819
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3ext.c1561
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3gthr.c533
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3prot.h223
-rw-r--r--chromium/net/third_party/nss/ssl/sslauth.c279
-rw-r--r--chromium/net/third_party/nss/ssl/sslcon.c3707
-rw-r--r--chromium/net/third_party/nss/ssl/ssldef.c146
-rw-r--r--chromium/net/third_party/nss/ssl/sslenum.c21
-rw-r--r--chromium/net/third_party/nss/ssl/sslerr.c32
-rw-r--r--chromium/net/third_party/nss/ssl/sslerr.h409
-rw-r--r--chromium/net/third_party/nss/ssl/sslerrstrs.c12
-rw-r--r--chromium/net/third_party/nss/ssl/sslgathr.c600
-rw-r--r--chromium/net/third_party/nss/ssl/sslimpl.h2133
-rw-r--r--chromium/net/third_party/nss/ssl/sslinfo.c466
-rw-r--r--chromium/net/third_party/nss/ssl/sslinit.c46
-rw-r--r--chromium/net/third_party/nss/ssl/sslmutex.c333
-rw-r--r--chromium/net/third_party/nss/ssl/sslmutex.h58
-rw-r--r--chromium/net/third_party/nss/ssl/sslnonce.c311
-rw-r--r--chromium/net/third_party/nss/ssl/sslplatf.c766
-rw-r--r--chromium/net/third_party/nss/ssl/sslproto.h9
-rw-r--r--chromium/net/third_party/nss/ssl/sslreveal.c146
-rw-r--r--chromium/net/third_party/nss/ssl/sslsecur.c1280
-rw-r--r--chromium/net/third_party/nss/ssl/sslsnce.c1926
-rw-r--r--chromium/net/third_party/nss/ssl/sslsock.c2249
-rw-r--r--chromium/net/third_party/nss/ssl/sslt.h204
-rw-r--r--chromium/net/third_party/nss/ssl/ssltrace.c317
-rw-r--r--chromium/net/third_party/nss/ssl/tls13con.c2059
-rw-r--r--chromium/net/third_party/nss/ssl/tls13con.h62
-rw-r--r--chromium/net/third_party/nss/ssl/tls13hkdf.c212
-rw-r--r--chromium/net/third_party/nss/ssl/tls13hkdf.h38
-rw-r--r--chromium/net/third_party/nss/ssl/unix_err.c716
-rw-r--r--chromium/net/third_party/nss/ssl/unix_err.h4
-rw-r--r--chromium/net/third_party/nss/ssl/win32err.c465
-rw-r--r--chromium/net/third_party/nss/ssl/win32err.h4
-rw-r--r--chromium/net/tools/balsa/balsa_frame.cc5
-rw-r--r--chromium/net/tools/balsa/split.cc72
-rw-r--r--chromium/net/tools/balsa/split.h23
-rw-r--r--chromium/net/tools/cachetool/cachetool.cc203
-rw-r--r--chromium/net/tools/content_decoder_tool/content_decoder_tool.cc83
-rwxr-xr-xchromium/net/tools/dafsa/make_dafsa.py8
-rwxr-xr-xchromium/net/tools/dafsa/make_dafsa_unittest.py20
-rw-r--r--chromium/net/tools/flip_server/acceptor_thread.cc13
-rw-r--r--chromium/net/tools/flip_server/flip_config.cc10
-rw-r--r--chromium/net/tools/flip_server/flip_in_mem_edsm_server.cc91
-rw-r--r--chromium/net/tools/flip_server/output_ordering.cc3
-rw-r--r--chromium/net/tools/flip_server/output_ordering.h1
-rw-r--r--chromium/net/tools/flip_server/sm_connection.cc6
-rw-r--r--chromium/net/tools/flip_server/spdy_interface.cc20
-rw-r--r--chromium/net/tools/flip_server/spdy_interface_test.cc5
-rw-r--r--chromium/net/tools/flip_server/tcp_socket_util.cc (renamed from chromium/net/tools/flip_server/create_listener.cc)60
-rw-r--r--chromium/net/tools/flip_server/tcp_socket_util.h (renamed from chromium/net/tools/flip_server/create_listener.h)18
-rw-r--r--chromium/net/tools/flip_server/url_to_filename_encoder.cc1
-rw-r--r--chromium/net/tools/flip_server/url_to_filename_encoder.h2
-rw-r--r--chromium/net/tools/gdig/gdig.cc11
-rw-r--r--chromium/net/tools/get_server_time/get_server_time.cc2
-rw-r--r--chromium/net/tools/quic/end_to_end_test.cc806
-rw-r--r--chromium/net/tools/quic/quic_client.cc243
-rw-r--r--chromium/net/tools/quic/quic_client.h94
-rw-r--r--chromium/net/tools/quic/quic_client_base.cc17
-rw-r--r--chromium/net/tools/quic/quic_client_base.h25
-rw-r--r--chromium/net/tools/quic/quic_client_bin.cc15
-rw-r--r--chromium/net/tools/quic/quic_client_session.cc69
-rw-r--r--chromium/net/tools/quic/quic_client_session.h21
-rw-r--r--chromium/net/tools/quic/quic_client_session_test.cc367
-rw-r--r--chromium/net/tools/quic/quic_client_test.cc27
-rw-r--r--chromium/net/tools/quic/quic_default_packet_writer.cc14
-rw-r--r--chromium/net/tools/quic/quic_default_packet_writer.h7
-rw-r--r--chromium/net/tools/quic/quic_dispatcher.cc287
-rw-r--r--chromium/net/tools/quic/quic_dispatcher.h95
-rw-r--r--chromium/net/tools/quic/quic_dispatcher_test.cc233
-rw-r--r--chromium/net/tools/quic/quic_epoll_clock.cc2
-rw-r--r--chromium/net/tools/quic/quic_epoll_clock.h2
-rw-r--r--chromium/net/tools/quic/quic_epoll_clock_test.cc2
-rw-r--r--chromium/net/tools/quic/quic_epoll_connection_helper.cc34
-rw-r--r--chromium/net/tools/quic/quic_epoll_connection_helper.h17
-rw-r--r--chromium/net/tools/quic/quic_epoll_connection_helper_test.cc74
-rw-r--r--chromium/net/tools/quic/quic_in_memory_cache.cc191
-rw-r--r--chromium/net/tools/quic/quic_in_memory_cache.h100
-rw-r--r--chromium/net/tools/quic/quic_in_memory_cache_test.cc27
-rw-r--r--chromium/net/tools/quic/quic_packet_reader.cc99
-rw-r--r--chromium/net/tools/quic/quic_packet_reader.h60
-rw-r--r--chromium/net/tools/quic/quic_packet_writer_wrapper.cc15
-rw-r--r--chromium/net/tools/quic/quic_packet_writer_wrapper.h8
-rw-r--r--chromium/net/tools/quic/quic_per_connection_packet_writer.cc11
-rw-r--r--chromium/net/tools/quic/quic_per_connection_packet_writer.h9
-rw-r--r--chromium/net/tools/quic/quic_process_packet_interface.h25
-rw-r--r--chromium/net/tools/quic/quic_server.cc85
-rw-r--r--chromium/net/tools/quic/quic_server.h15
-rw-r--r--chromium/net/tools/quic/quic_server_bin.cc13
-rw-r--r--chromium/net/tools/quic/quic_server_session_base.cc94
-rw-r--r--chromium/net/tools/quic/quic_server_session_base.h34
-rw-r--r--chromium/net/tools/quic/quic_server_session_base_test.cc94
-rw-r--r--chromium/net/tools/quic/quic_server_test.cc16
-rw-r--r--chromium/net/tools/quic/quic_simple_client.cc35
-rw-r--r--chromium/net/tools/quic/quic_simple_client.h24
-rw-r--r--chromium/net/tools/quic/quic_simple_client_bin.cc13
-rw-r--r--chromium/net/tools/quic/quic_simple_client_test.cc2
-rw-r--r--chromium/net/tools/quic/quic_simple_per_connection_packet_writer.cc9
-rw-r--r--chromium/net/tools/quic/quic_simple_per_connection_packet_writer.h7
-rw-r--r--chromium/net/tools/quic/quic_simple_server.cc5
-rw-r--r--chromium/net/tools/quic/quic_simple_server.h2
-rw-r--r--chromium/net/tools/quic/quic_simple_server_bin.cc8
-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.h20
-rw-r--r--chromium/net/tools/quic/quic_simple_server_session.cc34
-rw-r--r--chromium/net/tools/quic/quic_simple_server_session.h18
-rw-r--r--chromium/net/tools/quic/quic_simple_server_session_test.cc241
-rw-r--r--chromium/net/tools/quic/quic_simple_server_stream.cc41
-rw-r--r--chromium/net/tools/quic/quic_simple_server_stream.h11
-rw-r--r--chromium/net/tools/quic/quic_simple_server_stream_test.cc98
-rw-r--r--chromium/net/tools/quic/quic_simple_server_test.cc9
-rw-r--r--chromium/net/tools/quic/quic_socket_utils.cc128
-rw-r--r--chromium/net/tools/quic/quic_socket_utils.h60
-rw-r--r--chromium/net/tools/quic/quic_spdy_client_stream.cc68
-rw-r--r--chromium/net/tools/quic/quic_spdy_client_stream.h26
-rw-r--r--chromium/net/tools/quic/quic_spdy_client_stream_test.cc51
-rw-r--r--chromium/net/tools/quic/quic_time_wait_list_manager.cc22
-rw-r--r--chromium/net/tools/quic/quic_time_wait_list_manager.h12
-rw-r--r--chromium/net/tools/quic/quic_time_wait_list_manager_test.cc63
-rw-r--r--chromium/net/tools/quic/spdy_balsa_utils.cc17
-rw-r--r--chromium/net/tools/quic/spdy_balsa_utils.h2
-rw-r--r--chromium/net/tools/quic/spdy_balsa_utils_test.cc2
-rw-r--r--chromium/net/tools/quic/synchronous_host_resolver.cc2
-rw-r--r--chromium/net/tools/quic/synchronous_host_resolver.h2
-rw-r--r--chromium/net/tools/quic/test_tools/http_message.cc2
-rw-r--r--chromium/net/tools/quic/test_tools/http_message.h2
-rw-r--r--chromium/net/tools/quic/test_tools/limited_mtu_test_writer.cc14
-rw-r--r--chromium/net/tools/quic/test_tools/limited_mtu_test_writer.h7
-rw-r--r--chromium/net/tools/quic/test_tools/mock_epoll_server.cc2
-rw-r--r--chromium/net/tools/quic/test_tools/mock_epoll_server.h2
-rw-r--r--chromium/net/tools/quic/test_tools/mock_quic_server_session_visitor.cc2
-rw-r--r--chromium/net/tools/quic/test_tools/mock_quic_server_session_visitor.h10
-rw-r--r--chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.cc2
-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.cc53
-rw-r--r--chromium/net/tools/quic/test_tools/packet_dropping_test_writer.h24
-rw-r--r--chromium/net/tools/quic/test_tools/quic_client_peer.cc14
-rw-r--r--chromium/net/tools/quic/test_tools/quic_client_peer.h5
-rw-r--r--chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc8
-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.cc2
-rw-r--r--chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.h2
-rw-r--r--chromium/net/tools/quic/test_tools/quic_server_peer.cc7
-rw-r--r--chromium/net/tools/quic/test_tools/quic_server_peer.h3
-rw-r--r--chromium/net/tools/quic/test_tools/quic_test_client.cc94
-rw-r--r--chromium/net/tools/quic/test_tools/quic_test_client.h44
-rw-r--r--chromium/net/tools/quic/test_tools/quic_test_server.cc49
-rw-r--r--chromium/net/tools/quic/test_tools/quic_test_server.h8
-rw-r--r--chromium/net/tools/quic/test_tools/server_thread.cc4
-rw-r--r--chromium/net/tools/quic/test_tools/server_thread.h2
-rw-r--r--chromium/net/tools/quic/test_tools/simple_client.cc2
-rw-r--r--chromium/net/tools/quic/test_tools/simple_client.h9
-rwxr-xr-xchromium/net/tools/testserver/testserver.py37
-rw-r--r--chromium/net/udp/datagram_client_socket.h31
-rw-r--r--chromium/net/udp/datagram_server_socket.h17
-rw-r--r--chromium/net/udp/udp_client_socket.cc55
-rw-r--r--chromium/net/udp/udp_client_socket.h7
-rw-r--r--chromium/net/udp/udp_server_socket.cc4
-rw-r--r--chromium/net/udp/udp_server_socket.h6
-rw-r--r--chromium/net/udp/udp_socket_perftest.cc8
-rw-r--r--chromium/net/udp/udp_socket_posix.cc42
-rw-r--r--chromium/net/udp/udp_socket_posix.h20
-rw-r--r--chromium/net/udp/udp_socket_unittest.cc23
-rw-r--r--chromium/net/udp/udp_socket_win.cc39
-rw-r--r--chromium/net/udp/udp_socket_win.h20
-rw-r--r--chromium/net/url_request/certificate_report_sender.cc25
-rw-r--r--chromium/net/url_request/certificate_report_sender.h17
-rw-r--r--chromium/net/url_request/certificate_report_sender_unittest.cc32
-rw-r--r--chromium/net/url_request/redirect_info.cc2
-rw-r--r--chromium/net/url_request/redirect_info.h6
-rw-r--r--chromium/net/url_request/url_fetcher.h23
-rw-r--r--chromium/net/url_request/url_fetcher_core.cc27
-rw-r--r--chromium/net/url_request/url_fetcher_core.h9
-rw-r--r--chromium/net/url_request/url_fetcher_impl_unittest.cc101
-rw-r--r--chromium/net/url_request/url_request.cc64
-rw-r--r--chromium/net/url_request/url_request.h32
-rw-r--r--chromium/net/url_request/url_request_backoff_manager.cc2
-rw-r--r--chromium/net/url_request/url_request_context.cc7
-rw-r--r--chromium/net/url_request/url_request_context.h20
-rw-r--r--chromium/net/url_request/url_request_context_builder.cc94
-rw-r--r--chromium/net/url_request/url_request_context_builder.h77
-rw-r--r--chromium/net/url_request/url_request_context_builder_unittest.cc20
-rw-r--r--chromium/net/url_request/url_request_context_getter.cc3
-rw-r--r--chromium/net/url_request/url_request_context_getter.h3
-rw-r--r--chromium/net/url_request/url_request_context_storage.cc14
-rw-r--r--chromium/net/url_request/url_request_context_storage.h7
-rw-r--r--chromium/net/url_request/url_request_file_dir_job.cc73
-rw-r--r--chromium/net/url_request/url_request_file_dir_job.h29
-rw-r--r--chromium/net/url_request/url_request_file_dir_job_unittest.cc252
-rw-r--r--chromium/net/url_request/url_request_file_job_unittest.cc1
-rw-r--r--chromium/net/url_request/url_request_filter.h8
-rw-r--r--chromium/net/url_request/url_request_ftp_job.cc19
-rw-r--r--chromium/net/url_request/url_request_http_job.cc354
-rw-r--r--chromium/net/url_request/url_request_http_job.h20
-rw-r--r--chromium/net/url_request/url_request_http_job_unittest.cc166
-rw-r--r--chromium/net/url_request/url_request_job.cc76
-rw-r--r--chromium/net/url_request/url_request_job.h7
-rw-r--r--chromium/net/url_request/url_request_job_factory_impl_unittest.cc15
-rw-r--r--chromium/net/url_request/url_request_job_unittest.cc37
-rw-r--r--chromium/net/url_request/url_request_test_util.cc27
-rw-r--r--chromium/net/url_request/url_request_test_util.h15
-rw-r--r--chromium/net/url_request/url_request_throttler_manager.cc2
-rw-r--r--chromium/net/url_request/url_request_unittest.cc812
-rw-r--r--chromium/net/url_request/view_cache_helper.cc2
-rw-r--r--chromium/net/websockets/websocket_basic_handshake_stream.cc21
-rw-r--r--chromium/net/websockets/websocket_basic_handshake_stream.h2
-rw-r--r--chromium/net/websockets/websocket_basic_stream_test.cc9
-rw-r--r--chromium/net/websockets/websocket_channel.cc3
-rw-r--r--chromium/net/websockets/websocket_channel.h1
-rw-r--r--chromium/net/websockets/websocket_end_to_end_test.cc37
-rw-r--r--chromium/net/websockets/websocket_extension.cc3
-rw-r--r--chromium/net/websockets/websocket_extension.h1
-rw-r--r--chromium/net/websockets/websocket_frame_parser_fuzzer.cc19
-rw-r--r--chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc10
-rw-r--r--chromium/net/websockets/websocket_stream_create_test_base.cc2
2043 files changed, 102906 insertions, 64980 deletions
diff --git a/chromium/net/BUILD.gn b/chromium/net/BUILD.gn
index 129003a5935..fdfe0b69078 100644
--- a/chromium/net/BUILD.gn
+++ b/chromium/net/BUILD.gn
@@ -9,6 +9,7 @@ import("//build/config/crypto.gni")
import("//build/config/features.gni")
import("//build/config/ui.gni")
import("//build_overrides/v8.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
import("//testing/test.gni")
import("//third_party/icu/config.gni")
import("//third_party/protobuf/proto_library.gni")
@@ -27,10 +28,6 @@ gypi_values = exec_script("//build/gypi_to_gn.py",
"scope",
[ "net.gypi" ])
-# Disable Kerberos on ChromeOS, iOS, Chromecast and headless, at least for now.
-# It needs configuration (krb5.conf and so on).
-use_kerberos = !is_chromeos && !is_ios && !is_chromecast && !is_headless
-
# The way the cache uses mmap() is inefficient on some Android devices. If
# this flag is set, we hackily avoid using mmap() in the disk cache. We are
# pretty confident that mmap-ing the index would not hurt any existing x86
@@ -45,13 +42,15 @@ declare_args() {
# Disables support for file URLs. File URL support requires use of icu.
disable_file_support = false
- # Enables BidirectionalStream; Used in cronet, disabled by default.
- enable_bidirectional_stream = false
-
# WebSockets and socket stream code are not used on iOS and are optional in
# cronet.
enable_websockets = !is_ios
disable_ftp_support = is_ios
+
+ # Enable Kerberos authentication. It is disabled by default on ChromeOS, iOS,
+ # Chromecast, at least for now. This feature needs configuration (krb5.conf
+ # and so on).
+ use_kerberos = !is_chromeos && !is_ios && !is_chromecast
}
config("net_config") {
@@ -105,7 +104,6 @@ net_shared_configs = [
]
net_shared_public_deps = [
- ":features",
":net_quic_proto",
"//crypto",
"//crypto:platform",
@@ -122,16 +120,14 @@ if (!is_nacl) {
net_shared_sources += gypi_values.net_non_nacl_sources
net_shared_deps += [
- "//base:prefs",
"//base/third_party/dynamic_annotations",
+ "//components/prefs",
"//sdch",
"//third_party/zlib",
]
if (!use_kerberos) {
net_shared_sources -= [
- "http/http_auth_gssapi_posix.cc",
- "http/http_auth_gssapi_posix.h",
"http/http_auth_handler_negotiate.cc",
"http/http_auth_handler_negotiate.h",
]
@@ -167,8 +163,6 @@ if (!is_nacl) {
"quic/crypto/aead_base_encrypter_nss.cc",
"quic/crypto/aes_128_gcm_12_decrypter_nss.cc",
"quic/crypto/aes_128_gcm_12_encrypter_nss.cc",
- "quic/crypto/chacha20_poly1305_decrypter_nss.cc",
- "quic/crypto/chacha20_poly1305_encrypter_nss.cc",
"quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc",
"quic/crypto/chacha20_poly1305_rfc7539_encrypter_nss.cc",
"quic/crypto/channel_id_nss.cc",
@@ -180,17 +174,14 @@ if (!is_nacl) {
"socket/ssl_client_socket_nss.h",
"socket/ssl_server_socket_nss.cc",
"socket/ssl_server_socket_nss.h",
+ "ssl/token_binding_nss.cc",
]
if (is_ios) {
- # Always removed for !ios below.
net_shared_sources -= [
- "cert/cert_verify_proc_nss.cc",
- "cert/cert_verify_proc_nss.h",
+ "cert/x509_util_ios.cc",
+ "cert/x509_util_ios.h",
]
}
- if (!use_nss_certs && !is_ios) {
- net_shared_sources -= [ "cert/x509_util_nss.h" ]
- }
} else {
net_shared_sources -= [
"cert/ct_log_verifier_openssl.cc",
@@ -202,8 +193,6 @@ if (!is_nacl) {
"quic/crypto/aead_base_encrypter_openssl.cc",
"quic/crypto/aes_128_gcm_12_decrypter_openssl.cc",
"quic/crypto/aes_128_gcm_12_encrypter_openssl.cc",
- "quic/crypto/chacha20_poly1305_decrypter_openssl.cc",
- "quic/crypto/chacha20_poly1305_encrypter_openssl.cc",
"quic/crypto/chacha20_poly1305_rfc7539_decrypter_openssl.cc",
"quic/crypto/chacha20_poly1305_rfc7539_encrypter_openssl.cc",
"quic/crypto/channel_id_openssl.cc",
@@ -224,8 +213,11 @@ if (!is_nacl) {
"ssl/ssl_platform_key.h",
"ssl/ssl_platform_key_task_runner.cc",
"ssl/ssl_platform_key_task_runner.h",
+ "ssl/test_ssl_private_key.cc",
+ "ssl/test_ssl_private_key.h",
"ssl/threaded_ssl_private_key.cc",
"ssl/threaded_ssl_private_key.h",
+ "ssl/token_binding_openssl.cc",
]
}
@@ -254,12 +246,17 @@ if (!is_nacl) {
"cert/cert_database_openssl.cc",
"cert/cert_verify_proc_openssl.cc",
"cert/test_root_certs_openssl.cc",
- "http/http_auth_gssapi_posix.cc",
- "http/http_auth_gssapi_posix.h",
]
}
}
+ if (!use_kerberos || is_android) {
+ net_shared_sources -= [
+ "http/http_auth_gssapi_posix.cc",
+ "http/http_auth_gssapi_posix.h",
+ ]
+ }
+
if (use_glib && use_gconf && !is_chromeos) {
net_shared_configs += [ "//build/config/linux:gconf" ]
net_shared_deps += [ "//build/linux:gio" ]
@@ -286,18 +283,6 @@ if (!is_nacl) {
"third_party/mozilla_security_manager/nsPKCS12Blob.cpp",
"third_party/mozilla_security_manager/nsPKCS12Blob.h",
]
- if (!is_ios) {
- # These files are part of the partial implementation of NSS on iOS so
- # keep them in that case (even though use_nss_certs is not set).
- net_shared_sources -= [
- "cert/cert_verify_proc_nss.cc",
- "cert/cert_verify_proc_nss.h",
- "cert/test_root_certs_nss.cc",
- "cert/x509_util_nss_certs.cc",
- "cert_net/nss_ocsp.cc",
- "cert_net/nss_ocsp.h",
- ]
- }
if (is_chromeos) {
# These were already removed on non-ChromeOS.
net_shared_sources -= [
@@ -319,6 +304,32 @@ if (!is_nacl) {
net_shared_sources += [ "third_party/nss/ssl/cmpcert.c" ]
}
+ if (!use_nss_verifier) {
+ # These files are part of the partial implementation of NSS for
+ # cert verification, so keep them in that case.
+ net_shared_sources -= [
+ "cert/cert_verify_proc_nss.cc",
+ "cert/cert_verify_proc_nss.h",
+ "cert/test_root_certs_nss.cc",
+ "cert/x509_util_nss_certs.cc",
+ "cert_net/nss_ocsp.cc",
+ "cert_net/nss_ocsp.h",
+ ]
+ }
+
+ if (is_ios && use_nss_verifier) {
+ net_shared_sources -= [
+ "cert/cert_verify_proc_ios.cc",
+ "cert/cert_verify_proc_ios.h",
+ "cert/x509_certificate_openssl_ios.cc",
+ ]
+ }
+
+ if (is_chromecast && use_nss_certs) {
+ net_shared_sources += [ "ssl/ssl_platform_key_chromecast.cc" ]
+ net_shared_sources -= [ "ssl/ssl_platform_key_nss.cc" ]
+ }
+
if (!enable_mdns) {
net_shared_sources -= [
"dns/mdns_cache.cc",
@@ -370,6 +381,10 @@ if (!is_nacl) {
]
}
+ if (is_ios && !use_nss_verifier) {
+ net_shared_sources += [ "cert/test_root_certs_mac.cc" ]
+ }
+
if (is_ios || is_mac) {
net_shared_sources += gypi_values.net_base_mac_ios_sources
}
@@ -425,6 +440,18 @@ component("net") {
]
}
+ if (is_win) {
+ libs = [
+ "crypt32.lib",
+ "dhcpcsvc.lib",
+ "iphlpapi.lib",
+ "rpcrt4.lib",
+ "secur32.lib",
+ "urlmon.lib",
+ "winhttp.lib",
+ ]
+ }
+
if (!is_nacl) {
if (!disable_file_support) {
sources += gypi_values.net_file_support_sources
@@ -434,10 +461,6 @@ component("net") {
sources += gypi_values.net_ftp_support_sources
}
- if (enable_bidirectional_stream) {
- sources += gypi_values.net_bidirectional_stream_sources
- }
-
if (enable_websockets) {
sources += gypi_values.net_websockets_sources
}
@@ -492,10 +515,6 @@ if (is_android) {
# Disable Brotli support.
sources += [ "filter/brotli_filter_disabled.cc" ]
-
- if (enable_bidirectional_stream) {
- sources += gypi_values.net_bidirectional_stream_sources
- }
}
}
@@ -561,22 +580,35 @@ static_library("http_server") {
]
}
-executable("dump_cache") {
+if (!is_ios) {
+ executable("dump_cache") {
+ testonly = true
+ sources = [
+ "tools/dump_cache/dump_cache.cc",
+ "tools/dump_cache/dump_files.cc",
+ "tools/dump_cache/dump_files.h",
+ ]
+
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+
+ deps = [
+ ":net",
+ ":test_support",
+ "//base",
+ "//build/config/sanitizers:deps",
+ ]
+ }
+}
+
+bundle_data("test_support_bundle_data") {
testonly = true
sources = [
- "tools/dump_cache/dump_cache.cc",
- "tools/dump_cache/dump_files.cc",
- "tools/dump_cache/dump_files.h",
+ "data/ssl/certificates",
]
-
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
-
- deps = [
- ":net",
- ":test_support",
- "//base",
- "//build/config/sanitizers:deps",
+ outputs = [
+ "{{bundle_resources_dir}}/" +
+ "{{source_root_relative_dir}}/{{source_file_part}}",
]
}
@@ -593,6 +625,8 @@ source_set("test_support") {
"base/test_data_directory.h",
"cert/mock_cert_verifier.cc",
"cert/mock_cert_verifier.h",
+ "cert/mock_client_cert_verifier.cc",
+ "cert/mock_client_cert_verifier.h",
"cookies/cookie_monster_store_test.cc",
"cookies/cookie_monster_store_test.h",
"cookies/cookie_store_test_callbacks.cc",
@@ -683,6 +717,10 @@ source_set("test_support") {
"//build/config/compiler:no_size_t_to_int_warning",
]
+ deps = [
+ ":test_support_bundle_data",
+ ]
+
public_deps = [
"//base",
"//base/test:test_support",
@@ -698,7 +736,7 @@ source_set("test_support") {
public_deps += [ "//third_party/protobuf:py_proto" ]
}
- if (use_nss_certs || is_ios) {
+ if (use_nss_verifier) {
public_deps += [ "//crypto:platform" ]
}
@@ -751,8 +789,6 @@ source_set("balsa") {
"tools/balsa/noop_balsa_visitor.h",
"tools/balsa/simple_buffer.cc",
"tools/balsa/simple_buffer.h",
- "tools/balsa/split.cc",
- "tools/balsa/split.h",
"tools/balsa/string_piece_utils.h",
"tools/quic/spdy_balsa_utils.cc",
"tools/quic/spdy_balsa_utils.h",
@@ -1061,6 +1097,33 @@ if (!is_ios && !is_android) {
}
if (is_linux) {
+ executable("cachetool") {
+ testonly = true
+ sources = [
+ "tools/cachetool/cachetool.cc",
+ ]
+ deps = [
+ ":net",
+ ":test_support",
+ "//base",
+ ]
+ }
+
+ executable("content_decoder_tool") {
+ testonly = true
+ sources = [
+ "filter/mock_filter_context.cc",
+ "filter/mock_filter_context.h",
+ "tools/content_decoder_tool/content_decoder_tool.cc",
+ ]
+ deps = [
+ ":net",
+ ":test_support",
+ "//base",
+ "//url",
+ ]
+ }
+
static_library("epoll_server") {
sources = [
"tools/epoll_server/epoll_server.cc",
@@ -1078,8 +1141,6 @@ if (is_linux) {
"tools/flip_server/acceptor_thread.cc",
"tools/flip_server/acceptor_thread.h",
"tools/flip_server/constants.h",
- "tools/flip_server/create_listener.cc",
- "tools/flip_server/create_listener.h",
"tools/flip_server/flip_config.cc",
"tools/flip_server/flip_config.h",
"tools/flip_server/http_interface.cc",
@@ -1101,6 +1162,8 @@ if (is_linux) {
"tools/flip_server/spdy_util.h",
"tools/flip_server/streamer_interface.cc",
"tools/flip_server/streamer_interface.h",
+ "tools/flip_server/tcp_socket_util.cc",
+ "tools/flip_server/tcp_socket_util.h",
"tools/flip_server/url_to_filename_encoder.cc",
"tools/flip_server/url_to_filename_encoder.h",
"tools/flip_server/url_utilities.cc",
@@ -1270,6 +1333,7 @@ source_set("simple_quic_tools") {
"tools/quic/quic_in_memory_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",
"tools/quic/quic_server_session_base.cc",
"tools/quic/quic_server_session_base.h",
"tools/quic/quic_simple_client.cc",
@@ -1356,26 +1420,27 @@ if (!is_ios) {
}
}
-# TODO(GYP): Delete this after we've converted everything to GN.
-# The _run targets exist only for compatibility w/ GYP.
-group("net_unittests_run") {
+bundle_data("net_unittests_bundle_data") {
testonly = true
- deps = [
- ":net_unittests",
+ sources = [
+ "data/certificate_policies_unittest",
+ "data/name_constraints_unittest",
+ "data/parse_certificate_unittest",
+ "data/parse_ocsp_unittest",
+ "data/test.html",
+ "data/url_request_unittest",
+ "data/verify_certificate_chain_unittest",
+ "data/verify_name_match_unittest/names",
+ ]
+ outputs = [
+ "{{bundle_resources_dir}}/" +
+ "{{source_root_relative_dir}}/{{source_file_part}}",
]
}
test("net_unittests") {
sources = gypi_values.net_test_sources
- if (is_ios) {
- sources -= [
- "websockets/websocket_stream_cookie_test.cc",
- "websockets/websocket_stream_create_test_base.cc",
- "websockets/websocket_stream_create_test_base.h",
- ]
- }
-
configs += [
"//build/config:precompiled_headers",
@@ -1387,15 +1452,13 @@ test("net_unittests") {
deps = [
":balsa",
":extras",
- ":http_server",
":net",
+ ":net_unittests_bundle_data",
":simple_quic_tools",
":stale_while_revalidate_experiment_domains",
":test_support",
"//base",
"//base:i18n",
- "//base:prefs_test_support",
- "//base/allocator",
"//base/third_party/dynamic_annotations",
"//crypto",
"//crypto:platform",
@@ -1411,6 +1474,11 @@ test("net_unittests") {
data = [
"data/",
]
+ data_deps = []
+
+ if (!is_ios) {
+ data_deps += [ "third_party/nist-pkits/" ]
+ }
if (is_linux || is_mac || is_win) {
deps += [
@@ -1418,7 +1486,7 @@ test("net_unittests") {
"//third_party/pywebsocket/",
"//third_party/tlslite/",
]
- data_deps = [
+ data_deps += [
"//third_party/pyftpdlib/",
"//third_party/pywebsocket/",
"//third_party/tlslite/",
@@ -1474,7 +1542,6 @@ test("net_unittests") {
} else {
sources -= [
"quic/test_tools/crypto_test_utils_openssl.cc",
- "socket/ssl_client_socket_openssl_unittest.cc",
"ssl/ssl_client_session_cache_openssl_unittest.cc",
]
}
@@ -1496,9 +1563,8 @@ test("net_unittests") {
sources -= [ "http/http_auth_handler_negotiate_unittest.cc" ]
}
- if (!use_nss_certs && !is_ios) {
- # Only include this test when on Posix and using NSS for
- # cert verification or on iOS (which also uses NSS for certs).
+ if (!use_nss_verifier) {
+ # Only include this test when using NSS for cert verification.
sources -= [ "cert_net/nss_ocsp_unittest.cc" ]
}
@@ -1506,38 +1572,16 @@ test("net_unittests") {
sources -= [ "ssl/openssl_client_key_store_unittest.cc" ]
}
- if (!enable_websockets) {
- sources -= [
- "server/http_connection_unittest.cc",
- "server/http_server_response_info_unittest.cc",
- "server/http_server_unittest.cc",
- "server/web_socket_encoder_unittest.cc",
- "websockets/websocket_basic_stream_test.cc",
- "websockets/websocket_channel_test.cc",
- "websockets/websocket_deflate_parameters_test.cc",
- "websockets/websocket_deflate_predictor_impl_test.cc",
- "websockets/websocket_deflate_stream_test.cc",
- "websockets/websocket_deflater_test.cc",
- "websockets/websocket_end_to_end_test.cc",
- "websockets/websocket_errors_test.cc",
- "websockets/websocket_extension_parser_test.cc",
- "websockets/websocket_extension_test.cc",
- "websockets/websocket_frame_parser_test.cc",
- "websockets/websocket_frame_test.cc",
- "websockets/websocket_handshake_challenge_test.cc",
- "websockets/websocket_handshake_stream_create_helper_test.cc",
- "websockets/websocket_inflater_test.cc",
- "websockets/websocket_stream_test.cc",
- "websockets/websocket_test_util.cc",
- "websockets/websocket_test_util.h",
- ]
- deps -= [ ":http_server" ]
+ if (enable_websockets) {
+ sources += gypi_values.net_websockets_test_sources
+ deps += [ ":http_server" ]
}
if (disable_file_support) {
sources -= [
"base/directory_lister_unittest.cc",
"base/directory_listing_unittest.cc",
+ "url_request/url_request_file_dir_job_unittest.cc",
"url_request/url_request_file_job_unittest.cc",
]
}
@@ -1557,9 +1601,6 @@ test("net_unittests") {
]
}
- if (!enable_bidirectional_stream) {
- sources -= [ "http/bidirectional_stream_unittest.cc" ]
- }
if (!enable_built_in_dns) {
sources -= [
"dns/address_sorter_posix_unittest.cc",
@@ -1581,8 +1622,7 @@ test("net_unittests") {
deps += [
":net_browser_services",
":net_utility_services",
- "//mojo/environment:chromium",
- "//third_party/mojo/src/mojo/edk/system",
+ "//mojo/edk/system",
]
} else {
sources -= [
@@ -1606,26 +1646,6 @@ test("net_unittests") {
}
if (is_ios) {
- # TODO(GYP)
- # 'actions': [
- # {
- # 'action_name': 'copy_test_data',
- # 'variables': {
- # 'test_data_files': [
- # 'data/certificate_policies_unittest/',
- # 'data/name_constraints_unittest/',
- # 'data/parse_certificate_unittest/',
- # 'data/ssl/certificates/',
- # 'data/test.html',
- # 'data/url_request_unittest/',
- # 'data/verify_certificate_chain_unittest/',
- # 'data/verify_name_match_unittest/names/',
- # ],
- # 'test_data_prefix': 'net',
- # },
- # 'includes': [ '../build/copy_test_data_ios.gypi' ],
- # },
- # ],
sources -= [
# TODO(droger): The following tests are disabled because the
# implementation is missing or incomplete.
@@ -1697,45 +1717,239 @@ test("net_unittests") {
}
# !is_android && !is_win && !is_mac
+if (!is_ios) {
+ # TODO(crbug.com/594965): this should be converted to "app" template and
+ # enabled on iOS too.
+ executable("net_perftests") {
+ testonly = true
+ sources = [
+ "base/mime_sniffer_perftest.cc",
+ "cookies/cookie_monster_perftest.cc",
+ "disk_cache/blockfile/disk_cache_perftest.cc",
+ "extras/sqlite/sqlite_persistent_cookie_store_perftest.cc",
+ "proxy/proxy_resolver_perftest.cc",
+ "udp/udp_socket_perftest.cc",
+ ]
+
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+ deps = [
+ ":extras",
+ ":net",
+ ":test_support",
+ "//base",
+ "//base:i18n",
+ "//base/test:test_support_perf",
+ "//build/config/sanitizers:deps",
+ "//testing/gtest",
+ "//url",
+ ]
+
+ if (enable_websockets) {
+ sources += [ "websockets/websocket_frame_perftest.cc" ]
+ }
+
+ if (use_v8_in_net) {
+ deps += [ ":net_with_v8" ]
+ } else {
+ sources -= [ "proxy/proxy_resolver_perftest.cc" ]
+ }
+ }
+}
-executable("net_perftests") {
+# Fuzzers
+
+source_set("net_fuzzer_test_support") {
testonly = true
+
+ sources = [
+ "base/fuzzer_test_support.cc",
+ ]
+ deps = [
+ "//base",
+ "//base:i18n",
+ ]
+}
+
+fuzzer_test("net_mime_sniffer_fuzzer") {
sources = [
- "base/mime_sniffer_perftest.cc",
- "cookies/cookie_monster_perftest.cc",
- "disk_cache/blockfile/disk_cache_perftest.cc",
- "extras/sqlite/sqlite_persistent_cookie_store_perftest.cc",
- "proxy/proxy_resolver_perftest.cc",
- "udp/udp_socket_perftest.cc",
+ "base/mime_sniffer_fuzzer.cc",
]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//base",
+ "//net",
+ ]
+}
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+fuzzer_test("net_parse_proxy_list_pac_fuzzer") {
+ sources = [
+ "proxy/parse_proxy_list_pac_fuzzer.cc",
+ ]
deps = [
- ":extras",
- ":net",
+ ":net_fuzzer_test_support",
+ "//net",
+ ]
+}
+
+fuzzer_test("net_parse_proxy_list_fuzzer") {
+ sources = [
+ "proxy/parse_proxy_list_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//net",
+ ]
+}
+
+fuzzer_test("net_parse_proxy_bypass_rules_fuzzer") {
+ sources = [
+ "proxy/parse_proxy_bypass_rules_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//net",
+ ]
+}
+
+fuzzer_test("net_parse_proxy_rules_fuzzer") {
+ sources = [
+ "proxy/parse_proxy_rules_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//net",
+ ]
+}
+
+fuzzer_test("net_parse_data_url_fuzzer") {
+ sources = [
+ "base/parse_data_url_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//base",
+ "//net",
+ ]
+}
+
+fuzzer_test("net_parse_ip_pattern_fuzzer") {
+ sources = [
+ "base/parse_ip_pattern_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//net",
+ ]
+}
+
+fuzzer_test("net_get_domain_and_registry_fuzzer") {
+ sources = [
+ "base/registry_controlled_domains/get_domain_and_registry_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//base",
+ "//net",
+ ]
+}
+
+fuzzer_test("net_parse_cookie_line_fuzzer") {
+ sources = [
+ "cookies/parse_cookie_line_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//net",
+ ]
+}
+
+fuzzer_test("net_dns_record_fuzzer") {
+ sources = [
+ "dns/dns_record_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//base",
+ "//net",
+ ]
+}
+
+fuzzer_test("net_http_stream_parser_fuzzer") {
+ sources = [
+ "http/http_stream_parser_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
":test_support",
"//base",
- "//base:i18n",
- "//base/test:test_support_perf",
- "//build/config/sanitizers:deps",
- "//testing/gtest",
- "//url",
+ "//net",
]
+}
- if (enable_websockets) {
- sources += [ "websockets/websocket_frame_perftest.cc" ]
- }
+fuzzer_test("net_ftp_ctrl_response_fuzzer") {
+ sources = [
+ "ftp/ftp_ctrl_response_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//base",
+ "//net",
+ ]
+}
- if (use_v8_in_net) {
- deps += [ ":net_with_v8" ]
- } else {
- sources -= [ "proxy/proxy_resolver_perftest.cc" ]
- }
+fuzzer_test("net_ftp_directory_listing_fuzzer") {
+ sources = [
+ "ftp/ftp_directory_listing_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//base",
+ "//net",
+ ]
+}
+
+fuzzer_test("net_unescape_url_component_fuzzer") {
+ sources = [
+ "base/unescape_url_component_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//base",
+ "//net",
+ ]
+ dict = "base/unescape_url_component_fuzzer.dict"
+ libfuzzer_options = "base/unescape_url_component_fuzzer.options"
+}
+
+fuzzer_test("net_websocket_frame_parser_fuzzer") {
+ sources = [
+ "websockets/websocket_frame_parser_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//net",
+ ]
}
-buildflag_header("features") {
- header = "net_features.h"
+fuzzer_test("net_http_chunked_decoder_fuzzer") {
+ sources = [
+ "http/http_chunked_decoder_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//net",
+ ]
+ dict = "http/http_chunked_decoder_fuzzer.dict"
+}
- flags = [ "ENABLE_BIDIRECTIONAL_STREAM=$enable_bidirectional_stream" ]
+fuzzer_test("net_quic_crypto_framer_parse_message_fuzzer") {
+ sources = [
+ "quic/quic_crypto_framer_parse_message_fuzzer.cc",
+ ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//base",
+ "//net",
+ ]
}
diff --git a/chromium/net/DEPS b/chromium/net/DEPS
index 6f3c3d3c972..88c82c8eb03 100644
--- a/chromium/net/DEPS
+++ b/chromium/net/DEPS
@@ -54,12 +54,16 @@ specific_include_rules = {
],
"run_all_unittests\.cc": [
- "+third_party/mojo/src/mojo/edk",
+ "+mojo/edk",
],
"brotli_filter\.cc": [
"+third_party/brotli",
],
+
+ "fuzzer_test_support.cc": [
+ "+base/i18n",
+ ],
}
skip_child_includes = [
diff --git a/chromium/net/android/BUILD.gn b/chromium/net/android/BUILD.gn
index a1c23f4e320..241d9553e15 100644
--- a/chromium/net/android/BUILD.gn
+++ b/chromium/net/android/BUILD.gn
@@ -6,7 +6,22 @@ import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
android_library("net_java") {
- DEPRECATED_java_in_dir = "java/src"
+ java_files = [
+ "java/src/org/chromium/net/AndroidCertVerifyResult.java",
+ "java/src/org/chromium/net/AndroidKeyStore.java",
+ "java/src/org/chromium/net/AndroidNetworkLibrary.java",
+ "java/src/org/chromium/net/AndroidTrafficStats.java",
+ "java/src/org/chromium/net/GURLUtils.java",
+ "java/src/org/chromium/net/HttpNegotiateAuthenticator.java",
+ "java/src/org/chromium/net/HttpNegotiateConstants.java",
+ "java/src/org/chromium/net/NetStringUtil.java",
+ "java/src/org/chromium/net/NetworkChangeNotifier.java",
+ "java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java",
+ "java/src/org/chromium/net/ProxyChangeListener.java",
+ "java/src/org/chromium/net/RegistrationPolicyAlwaysRegister.java",
+ "java/src/org/chromium/net/RegistrationPolicyApplicationStatus.java",
+ "java/src/org/chromium/net/X509Util.java",
+ ]
deps = [
"//base:base_java",
]
@@ -25,7 +40,21 @@ android_aidl("embedded_test_server_aidl") {
android_library("net_java_test_support") {
testonly = true
- DEPRECATED_java_in_dir = "../test/android/javatests/src"
+ java_files = [
+ "../test/android/javatests/src/org/chromium/net/test/BaseHttpTestServer.java",
+ "../test/android/javatests/src/org/chromium/net/test/BaseTcpTestServer.java",
+ "../test/android/javatests/src/org/chromium/net/test/BaseTestServer.java",
+ "../test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticator.java",
+ "../test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticatorService.java",
+ "../test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java",
+ "../test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerImpl.java",
+ "../test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerService.java",
+ "../test/android/javatests/src/org/chromium/net/test/TestServerBuilder.java",
+ "../test/android/javatests/src/org/chromium/net/test/TestServerSpawner.java",
+ "../test/android/javatests/src/org/chromium/net/test/util/CertTestUtil.java",
+ "../test/android/javatests/src/org/chromium/net/test/util/NetworkChangeNotifierTestUtil.java",
+ "../test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java",
+ ]
deps = [
":net_java",
"//base:base_java",
@@ -83,7 +112,13 @@ android_resources("net_unittests_apk_resources") {
android_library("net_javatests") {
testonly = true
- DEPRECATED_java_in_dir = "javatests/src"
+ java_files = [
+ "javatests/src/org/chromium/net/AndroidKeyStoreTestUtil.java",
+ "javatests/src/org/chromium/net/AndroidProxySelectorTest.java",
+ "javatests/src/org/chromium/net/NetErrorsTest.java",
+ "javatests/src/org/chromium/net/NetworkChangeNotifierTest.java",
+ "javatests/src/org/chromium/net/X509UtilTest.java",
+ ]
deps = [
":net_java",
":net_java_test_support",
diff --git a/chromium/net/android/http_auth_negotiate_android.cc b/chromium/net/android/http_auth_negotiate_android.cc
index 907cff3aec8..764eb4c0356 100644
--- a/chromium/net/android/http_auth_negotiate_android.cc
+++ b/chromium/net/android/http_auth_negotiate_android.cc
@@ -101,6 +101,7 @@ HttpAuth::AuthorizationResult HttpAuthNegotiateAndroid::ParseChallenge(
int HttpAuthNegotiateAndroid::GenerateAuthToken(
const AuthCredentials* credentials,
const std::string& spn,
+ const std::string& channel_bindings,
std::string* auth_token,
const net::CompletionCallback& callback) {
if (prefs_->AuthAndroidNegotiateAccountType().empty()) {
diff --git a/chromium/net/android/http_auth_negotiate_android.h b/chromium/net/android/http_auth_negotiate_android.h
index 1b337261fcd..af8163c9fb2 100644
--- a/chromium/net/android/http_auth_negotiate_android.h
+++ b/chromium/net/android/http_auth_negotiate_android.h
@@ -107,6 +107,7 @@ class NET_EXPORT_PRIVATE HttpAuthNegotiateAndroid {
// credentials are used instead.
int GenerateAuthToken(const AuthCredentials* credentials,
const std::string& spn,
+ const std::string& channel_bindings,
std::string* auth_token,
const net::CompletionCallback& callback);
diff --git a/chromium/net/android/http_auth_negotiate_android_unittest.cc b/chromium/net/android/http_auth_negotiate_android_unittest.cc
index 8e3de79485c..b44547d1b16 100644
--- a/chromium/net/android/http_auth_negotiate_android_unittest.cc
+++ b/chromium/net/android/http_auth_negotiate_android_unittest.cc
@@ -31,8 +31,9 @@ TEST(HttpAuthNegotiateAndroidTest, GenerateAuthToken) {
EXPECT_TRUE(auth.Init());
TestCompletionCallback callback;
- EXPECT_EQ(OK, callback.GetResult(auth.GenerateAuthToken(
- nullptr, "Dummy", &auth_token, callback.callback())));
+ EXPECT_EQ(OK, callback.GetResult(
+ auth.GenerateAuthToken(nullptr, "Dummy", std::string(),
+ &auth_token, callback.callback())));
EXPECT_EQ("Negotiate DummyToken", auth_token);
diff --git a/chromium/net/android/keystore_openssl.cc b/chromium/net/android/keystore_openssl.cc
index 611b926cfd8..f60842cfda9 100644
--- a/chromium/net/android/keystore_openssl.cc
+++ b/chromium/net/android/keystore_openssl.cc
@@ -17,6 +17,7 @@
#include "base/android/scoped_java_ref.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
#include "crypto/openssl_util.h"
#include "net/android/keystore.h"
#include "net/android/legacy_openssl.h"
diff --git a/chromium/net/android/keystore_unittest.cc b/chromium/net/android/keystore_unittest.cc
index 4faa2458cec..26d49c28afa 100644
--- a/chromium/net/android/keystore_unittest.cc
+++ b/chromium/net/android/keystore_unittest.cc
@@ -9,7 +9,6 @@
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
-#include <openssl/x509.h>
#include "base/android/build_info.h"
#include "base/android/jni_android.h"
@@ -23,6 +22,7 @@
#include "base/files/scoped_file.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "crypto/auto_cbb.h"
#include "crypto/openssl_util.h"
#include "net/android/keystore.h"
#include "net/android/keystore_openssl.h"
@@ -128,18 +128,16 @@ EVP_PKEY* ImportPrivateKeyFile(const char* filename) {
// Returns true on success, false otherwise.
bool GetPrivateKeyPkcs8Bytes(const crypto::ScopedEVP_PKEY& pkey,
std::string* pkcs8) {
- // Convert to PKCS#8 object.
- ScopedPKCS8_PRIV_KEY_INFO p8_info(EVP_PKEY2PKCS8(pkey.get()));
- if (!p8_info.get()) {
- LOG(ERROR) << "Can't get PKCS#8 private key from EVP_PKEY: "
- << GetOpenSSLErrorString();
+ uint8_t* der;
+ size_t der_len;
+ crypto::AutoCBB cbb;
+ if (!CBB_init(cbb.get(), 0) ||
+ !EVP_marshal_private_key(cbb.get(), pkey.get()) ||
+ !CBB_finish(cbb.get(), &der, &der_len)) {
return false;
}
-
- // Then convert it
- int len = i2d_PKCS8_PRIV_KEY_INFO(p8_info.get(), NULL);
- unsigned char* p = OpenSSLWriteInto(pkcs8, static_cast<size_t>(len));
- i2d_PKCS8_PRIV_KEY_INFO(p8_info.get(), &p);
+ pkcs8->assign(reinterpret_cast<const char*>(der), der_len);
+ OPENSSL_free(der);
return true;
}
diff --git a/chromium/net/android/legacy_openssl.h b/chromium/net/android/legacy_openssl.h
index e87413570ee..75c77b8a06f 100644
--- a/chromium/net/android/legacy_openssl.h
+++ b/chromium/net/android/legacy_openssl.h
@@ -78,9 +78,8 @@ struct AndroidRSA_METHOD {
struct AndroidEVP_PKEY {
int type;
int save_type;
- // Note: this value must NOT be modified using Chromium's CRYPTO_add
- // function. That may not necessarily use the same locking implementation as
- // system OpenSSL.
+ // Note: this value is protected by threading functions in the Android system
+ // OpenSSL. It should not be accessed or modified directly.
int references;
const AndroidEVP_PKEY_ASN1_METHOD* ameth;
AndroidENGINE* engine;
diff --git a/chromium/net/android/network_change_notifier_android.cc b/chromium/net/android/network_change_notifier_android.cc
index a7655adbe8c..74d47936e70 100644
--- a/chromium/net/android/network_change_notifier_android.cc
+++ b/chromium/net/android/network_change_notifier_android.cc
@@ -61,6 +61,7 @@
#include "base/android/build_info.h"
#include "base/macros.h"
+#include "base/metrics/histogram_macros.h"
#include "base/threading/thread.h"
#include "net/base/address_tracker_linux.h"
#include "net/dns/dns_config_service_posix.h"
@@ -84,7 +85,7 @@ class NetworkChangeNotifierAndroid::DnsConfigServiceThread
: public base::Thread,
public NetworkChangeNotifier::NetworkChangeObserver {
public:
- DnsConfigServiceThread(const DnsConfig* dns_config_for_testing)
+ explicit DnsConfigServiceThread(const DnsConfig* dns_config_for_testing)
: base::Thread("DnsConfigService"),
dns_config_for_testing_(dns_config_for_testing),
creation_time_(base::Time::Now()),
@@ -263,4 +264,19 @@ NetworkChangeNotifierAndroid::NetworkChangeCalculatorParamsAndroid() {
return params;
}
+void NetworkChangeNotifierAndroid::OnFinalizingMetricsLogRecord() {
+ // Metrics logged here will be included in every metrics log record. It's not
+ // yet clear if these metrics are generally useful enough to warrant being
+ // added to the SystemProfile proto, so they are logged here as histograms for
+ // now.
+ const NetworkChangeNotifier::ConnectionType type =
+ NetworkChangeNotifier::GetConnectionType();
+ NetworkChangeNotifier::LogOperatorCodeHistogram(type);
+ if (NetworkChangeNotifier::IsConnectionCellular(type)) {
+ UMA_HISTOGRAM_ENUMERATION("NCN.CellularConnectionSubtype",
+ delegate_->GetCurrentConnectionSubtype(),
+ SUBTYPE_LAST + 1);
+ }
+}
+
} // namespace net
diff --git a/chromium/net/android/network_change_notifier_android.h b/chromium/net/android/network_change_notifier_android.h
index 89e7f19ee95..203daf3f4f4 100644
--- a/chromium/net/android/network_change_notifier_android.h
+++ b/chromium/net/android/network_change_notifier_android.h
@@ -73,6 +73,9 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierAndroid
// delegate class.
using NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype;
+ protected:
+ void OnFinalizingMetricsLogRecord() override;
+
private:
friend class NetworkChangeNotifierAndroidTest;
friend class NetworkChangeNotifierFactoryAndroid;
diff --git a/chromium/net/android/network_change_notifier_delegate_android.cc b/chromium/net/android/network_change_notifier_delegate_android.cc
index ff072979606..429a576693a 100644
--- a/chromium/net/android/network_change_notifier_delegate_android.cc
+++ b/chromium/net/android/network_change_notifier_delegate_android.cc
@@ -109,6 +109,15 @@ NetworkChangeNotifierDelegateAndroid::GetCurrentConnectionType() const {
return connection_type_;
}
+NetworkChangeNotifier::ConnectionSubtype
+NetworkChangeNotifierDelegateAndroid::GetCurrentConnectionSubtype() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return ConvertConnectionSubtype(
+ Java_NetworkChangeNotifier_getCurrentConnectionSubtype(
+ base::android::AttachCurrentThread(),
+ java_network_change_notifier_.obj()));
+}
+
void NetworkChangeNotifierDelegateAndroid::
GetCurrentMaxBandwidthAndConnectionType(
double* max_bandwidth_mbps,
diff --git a/chromium/net/android/network_change_notifier_delegate_android.h b/chromium/net/android/network_change_notifier_delegate_android.h
index a9f18d51d7c..719be5b2958 100644
--- a/chromium/net/android/network_change_notifier_delegate_android.h
+++ b/chromium/net/android/network_change_notifier_delegate_android.h
@@ -107,6 +107,9 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierDelegateAndroid {
NetworkHandle GetCurrentDefaultNetwork() const;
void GetCurrentlyConnectedNetworks(NetworkList* network_list) const;
+ // Can only be called from the main (Java) thread.
+ NetworkChangeNotifier::ConnectionSubtype GetCurrentConnectionSubtype() const;
+
// Initializes JNI bindings.
static bool Register(JNIEnv* env);
@@ -153,4 +156,4 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierDelegateAndroid {
} // namespace net
-#endif // NET_ANDROID_NETWORK_CHANGE_NOTIFIER_DELEGATE_H_
+#endif // NET_ANDROID_NETWORK_CHANGE_NOTIFIER_DELEGATE_ANDROID_H_
diff --git a/chromium/net/android/network_library.h b/chromium/net/android/network_library.h
index ddfb5e92eee..827548ac590 100644
--- a/chromium/net/android/network_library.h
+++ b/chromium/net/android/network_library.h
@@ -36,15 +36,10 @@ 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. Note that the public key must be a DER
-// encoded SubjectPublicKeyInfo (X.509), as returned by i2d_PUBKEY()
-// (and *not* i2d_PublicKey(), which returns a PKCS#1 key).
-//
-// Also, the private key must be in PKCS#8 format, as returned by
-// i2d_PKCS8_PRIV_KEY_INFO(EVP_PKEY2PKCS8(pkey)), which is a different
-// format than what i2d_PrivateKey() returns, so don't use it either.
-//
+// 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,
diff --git a/chromium/net/android/traffic_stats_unittest.cc b/chromium/net/android/traffic_stats_unittest.cc
index de49ec53d2b..29abbe70e39 100644
--- a/chromium/net/android/traffic_stats_unittest.cc
+++ b/chromium/net/android/traffic_stats_unittest.cc
@@ -42,9 +42,9 @@ TEST(TrafficStatsAndroidTest, BasicsTest) {
int64_t tx_bytes_after_request = -1;
int64_t rx_bytes_after_request = -1;
EXPECT_TRUE(android::traffic_stats::GetTotalTxBytes(&tx_bytes_after_request));
- DCHECK_GT(tx_bytes_after_request, tx_bytes_before_request);
+ EXPECT_GT(tx_bytes_after_request, tx_bytes_before_request);
EXPECT_TRUE(android::traffic_stats::GetTotalRxBytes(&rx_bytes_after_request));
- DCHECK_GT(rx_bytes_after_request, rx_bytes_before_request);
+ EXPECT_GT(rx_bytes_after_request, rx_bytes_before_request);
}
TEST(TrafficStatsAndroidTest, UIDBasicsTest) {
@@ -76,10 +76,10 @@ TEST(TrafficStatsAndroidTest, UIDBasicsTest) {
int64_t rx_bytes_after_request = -1;
EXPECT_TRUE(
android::traffic_stats::GetCurrentUidTxBytes(&tx_bytes_after_request));
- DCHECK_GT(tx_bytes_after_request, tx_bytes_before_request);
+ EXPECT_GT(tx_bytes_after_request, tx_bytes_before_request);
EXPECT_TRUE(
android::traffic_stats::GetCurrentUidRxBytes(&rx_bytes_after_request));
- DCHECK_GT(rx_bytes_after_request, rx_bytes_before_request);
+ EXPECT_GT(rx_bytes_after_request, rx_bytes_before_request);
}
} // namespace
diff --git a/chromium/net/base/OWNERS b/chromium/net/base/OWNERS
index 8c9c4c27d46..8532b8c7edd 100644
--- a/chromium/net/base/OWNERS
+++ b/chromium/net/base/OWNERS
@@ -6,3 +6,4 @@ per-file mime_sniffer*=mmenke@chromium.org
# For all files relating to the network quality estimator.
per-file network_quality*=bengr@chromium.org
+per-file socket_performance_watcher*=bengr@chromium.org
diff --git a/chromium/net/base/address_family.cc b/chromium/net/base/address_family.cc
index 1af5e001065..8fc2bf02a66 100644
--- a/chromium/net/base/address_family.cc
+++ b/chromium/net/base/address_family.cc
@@ -5,6 +5,7 @@
#include "net/base/address_family.h"
#include "base/logging.h"
+#include "net/base/ip_address.h"
#include "net/base/sys_addrinfo.h"
namespace net {
@@ -20,6 +21,10 @@ AddressFamily GetAddressFamily(const IPAddressNumber& address) {
}
}
+AddressFamily GetAddressFamily(const IPAddress& address) {
+ return GetAddressFamily(address.bytes());
+}
+
int ConvertAddressFamily(AddressFamily address_family) {
switch (address_family) {
case ADDRESS_FAMILY_UNSPECIFIED:
diff --git a/chromium/net/base/address_family.h b/chromium/net/base/address_family.h
index 57ec48db839..748090e2a48 100644
--- a/chromium/net/base/address_family.h
+++ b/chromium/net/base/address_family.h
@@ -10,6 +10,8 @@
namespace net {
+class IPAddress;
+
// Enum wrapper around the address family types supported by host resolver
// procedures.
enum AddressFamily {
@@ -36,6 +38,9 @@ typedef int HostResolverFlags;
// Returns AddressFamily for |address|.
NET_EXPORT AddressFamily GetAddressFamily(const IPAddressNumber& address);
+// GetAddressFamily for net::IPAddress.
+NET_EXPORT AddressFamily GetAddressFamily(const IPAddress& address);
+
// Maps the given AddressFamily to either AF_INET, AF_INET6 or AF_UNSPEC.
NET_EXPORT int ConvertAddressFamily(AddressFamily address_family);
diff --git a/chromium/net/base/address_list.cc b/chromium/net/base/address_list.cc
index 5b4fe34ac03..2a0cbfc47fb 100644
--- a/chromium/net/base/address_list.cc
+++ b/chromium/net/base/address_list.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/values.h"
-#include "net/base/net_util.h"
#include "net/base/sys_addrinfo.h"
namespace net {
@@ -42,12 +41,6 @@ AddressList::AddressList(const IPEndPoint& endpoint) {
}
// static
-AddressList AddressList::CreateFromIPAddress(const IPAddressNumber& address,
- uint16_t port) {
- return AddressList(IPEndPoint(address, port));
-}
-
-// static
AddressList AddressList::CreateFromIPAddress(const IPAddress& address,
uint16_t port) {
return AddressList(IPEndPoint(address, port));
diff --git a/chromium/net/base/address_list.h b/chromium/net/base/address_list.h
index 72e0a43d5d8..93255e78985 100644
--- a/chromium/net/base/address_list.h
+++ b/chromium/net/base/address_list.h
@@ -11,7 +11,6 @@
#include <vector>
#include "base/compiler_specific.h"
-#include "net/base/ip_address_number.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_export.h"
#include "net/log/net_log.h"
@@ -31,10 +30,6 @@ class NET_EXPORT AddressList
// Creates an address list for a single IP literal.
explicit AddressList(const IPEndPoint& endpoint);
- // DEPRECATED(crbug.com/496258): Use the method below that takes IPAddress.
- static AddressList CreateFromIPAddress(const IPAddressNumber& address,
- uint16_t port);
-
static AddressList CreateFromIPAddress(const IPAddress& address,
uint16_t port);
diff --git a/chromium/net/base/address_list_unittest.cc b/chromium/net/base/address_list_unittest.cc
index 44955a96736..1e2fa427015 100644
--- a/chromium/net/base/address_list_unittest.cc
+++ b/chromium/net/base/address_list_unittest.cc
@@ -6,6 +6,7 @@
#include "base/strings/string_util.h"
#include "base/sys_byteorder.h"
+#include "net/base/ip_address.h"
#include "net/base/sockaddr_storage.h"
#include "net/base/sys_addrinfo.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -70,7 +71,7 @@ TEST(AddressListTest, CreateFromAddrinfo) {
for (size_t i = 0; i < list.size(); ++i) {
EXPECT_EQ(ADDRESS_FAMILY_IPV4, list[i].GetFamily());
// Only check the first byte of the address.
- EXPECT_EQ(i, list[i].address()[0]);
+ EXPECT_EQ(i, list[i].address().bytes()[0]);
EXPECT_EQ(static_cast<int>(i << 2), list[i].port());
}
@@ -82,7 +83,7 @@ TEST(AddressListTest, CreateFromAddrinfo) {
// Check if copy is independent.
copy[1] = IPEndPoint(copy[2].address(), 0xBEEF);
// Original should be unchanged.
- EXPECT_EQ(1u, list[1].address()[0]);
+ EXPECT_EQ(1u, list[1].address().bytes()[0]);
EXPECT_EQ(1 << 2, list[1].port());
}
@@ -122,9 +123,9 @@ TEST(AddressListTest, CreateFromIPAddressList) {
// Construct a list of ip addresses.
IPAddressList ip_list;
for (size_t i = 0; i < arraysize(tests); ++i) {
- IPAddressNumber ip_number;
- ASSERT_TRUE(ParseIPLiteralToNumber(tests[i].ip_address, &ip_number));
- ip_list.push_back(ip_number);
+ IPAddress ip_address;
+ ASSERT_TRUE(ip_address.AssignFromIPLiteral(tests[i].ip_address));
+ ip_list.push_back(ip_address);
}
AddressList test_list = AddressList::CreateFromIPAddressList(ip_list,
diff --git a/chromium/net/base/address_tracker_linux.cc b/chromium/net/base/address_tracker_linux.cc
index a9983f49d6e..59d732c90d7 100644
--- a/chromium/net/base/address_tracker_linux.cc
+++ b/chromium/net/base/address_tracker_linux.cc
@@ -6,6 +6,7 @@
#include <errno.h>
#include <linux/if.h>
+#include <stdint.h>
#include <sys/ioctl.h>
#include "base/files/scoped_file.h"
@@ -13,7 +14,6 @@
#include "base/posix/eintr_wrapper.h"
#include "base/threading/thread_restrictions.h"
#include "net/base/network_interfaces_linux.h"
-#include "net/base/ip_address_number.h"
namespace net {
namespace internal {
@@ -37,7 +37,7 @@ bool IgnoreWirelessChange(const struct nlmsghdr* header,
// Retrieves address from NETLINK address message.
// Sets |really_deprecated| for IPv6 addresses with preferred lifetimes of 0.
bool GetAddress(const struct nlmsghdr* header,
- IPAddressNumber* out,
+ IPAddress* out,
bool* really_deprecated) {
if (really_deprecated)
*really_deprecated = false;
@@ -46,10 +46,10 @@ bool GetAddress(const struct nlmsghdr* header,
size_t address_length = 0;
switch (msg->ifa_family) {
case AF_INET:
- address_length = kIPv4AddressSize;
+ address_length = IPAddress::kIPv4AddressSize;
break;
case AF_INET6:
- address_length = kIPv6AddressSize;
+ address_length = IPAddress::kIPv6AddressSize;
break;
default:
// Unknown family.
@@ -59,8 +59,8 @@ bool GetAddress(const struct nlmsghdr* header,
// getaddrinfo in glibc (check_pf.c). Judging from kernel implementation of
// NETLINK, IPv4 addresses have only the IFA_ADDRESS attribute, while IPv6
// have the IFA_LOCAL attribute.
- unsigned char* address = NULL;
- unsigned char* local = NULL;
+ uint8_t* address = NULL;
+ uint8_t* local = NULL;
size_t length = IFA_PAYLOAD(header);
for (const struct rtattr* attr =
reinterpret_cast<const struct rtattr*>(IFA_RTA(msg));
@@ -69,11 +69,11 @@ bool GetAddress(const struct nlmsghdr* header,
switch (attr->rta_type) {
case IFA_ADDRESS:
DCHECK_GE(RTA_PAYLOAD(attr), address_length);
- address = reinterpret_cast<unsigned char*>(RTA_DATA(attr));
+ address = reinterpret_cast<uint8_t*>(RTA_DATA(attr));
break;
case IFA_LOCAL:
DCHECK_GE(RTA_PAYLOAD(attr), address_length);
- local = reinterpret_cast<unsigned char*>(RTA_DATA(attr));
+ local = reinterpret_cast<uint8_t*>(RTA_DATA(attr));
break;
case IFA_CACHEINFO: {
const struct ifa_cacheinfo *cache_info =
@@ -89,7 +89,7 @@ bool GetAddress(const struct nlmsghdr* header,
address = local;
if (!address)
return false;
- out->assign(address, address + address_length);
+ *out = IPAddress(address, address_length);
return true;
}
@@ -116,12 +116,12 @@ AddressTrackerLinux::AddressTrackerLinux()
link_callback_(base::Bind(&base::DoNothing)),
tunnel_callback_(base::Bind(&base::DoNothing)),
netlink_fd_(-1),
+ ignored_interfaces_(),
connection_type_initialized_(false),
connection_type_initialized_cv_(&connection_type_lock_),
current_connection_type_(NetworkChangeNotifier::CONNECTION_NONE),
tracking_(false),
- threads_waiting_for_connection_type_initialization_(0) {
-}
+ threads_waiting_for_connection_type_initialization_(0) {}
AddressTrackerLinux::AddressTrackerLinux(
const base::Closure& address_callback,
@@ -327,7 +327,7 @@ void AddressTrackerLinux::HandleMessage(char* buffer,
LOG(ERROR) << "Unexpected netlink error " << msg->error << ".";
} return;
case RTM_NEWADDR: {
- IPAddressNumber address;
+ IPAddress address;
bool really_deprecated;
struct ifaddrmsg* msg =
reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header));
@@ -357,7 +357,7 @@ void AddressTrackerLinux::HandleMessage(char* buffer,
}
} break;
case RTM_DELADDR: {
- IPAddressNumber address;
+ IPAddress address;
const struct ifaddrmsg* msg =
reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header));
if (IsInterfaceIgnored(msg->ifa_index))
diff --git a/chromium/net/base/address_tracker_linux.h b/chromium/net/base/address_tracker_linux.h
index da5c8934e0d..80767f6195b 100644
--- a/chromium/net/base/address_tracker_linux.h
+++ b/chromium/net/base/address_tracker_linux.h
@@ -22,7 +22,7 @@
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "net/base/network_change_notifier.h"
namespace net {
@@ -33,7 +33,7 @@ namespace internal {
class NET_EXPORT_PRIVATE AddressTrackerLinux :
public base::MessageLoopForIO::Watcher {
public:
- typedef std::map<IPAddressNumber, struct ifaddrmsg> AddressMap;
+ typedef std::map<IPAddress, struct ifaddrmsg> AddressMap;
// Non-tracking version constructor: it takes a snapshot of the
// current system configuration. Once Init() returns, the
diff --git a/chromium/net/base/address_tracker_linux_unittest.cc b/chromium/net/base/address_tracker_linux_unittest.cc
index 53c478d7eec..1b349e53dfa 100644
--- a/chromium/net/base/address_tracker_linux_unittest.cc
+++ b/chromium/net/base/address_tracker_linux_unittest.cc
@@ -2,19 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <vector>
+
+#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/spin_wait.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/simple_thread.h"
#include "net/base/address_tracker_linux.h"
+#include "net/base/ip_address.h"
+#include "testing/gtest/include/gtest/gtest.h"
#include <linux/if.h>
-#include <vector>
-
-#include "base/bind.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
#ifndef IFA_F_HOMEADDRESS
#define IFA_F_HOMEADDRESS 0x10
#endif
@@ -175,8 +175,8 @@ void MakeAddrMessageWithCacheInfo(uint16_t type,
uint8_t flags,
uint8_t family,
int index,
- const IPAddressNumber& address,
- const IPAddressNumber& local,
+ const IPAddress& address,
+ const IPAddress& local,
uint32_t preferred_lifetime,
Buffer* output) {
NetlinkMessage nlmsg(type);
@@ -186,9 +186,9 @@ void MakeAddrMessageWithCacheInfo(uint16_t type,
msg.ifa_index = index;
nlmsg.AddPayload(&msg, sizeof(msg));
if (address.size())
- nlmsg.AddAttribute(IFA_ADDRESS, &address[0], address.size());
+ nlmsg.AddAttribute(IFA_ADDRESS, address.bytes().data(), address.size());
if (local.size())
- nlmsg.AddAttribute(IFA_LOCAL, &local[0], local.size());
+ nlmsg.AddAttribute(IFA_LOCAL, local.bytes().data(), local.size());
struct ifa_cacheinfo cache_info = {};
cache_info.ifa_prefered = preferred_lifetime;
cache_info.ifa_valid = INFINITY_LIFE_TIME;
@@ -200,8 +200,8 @@ void MakeAddrMessage(uint16_t type,
uint8_t flags,
uint8_t family,
int index,
- const IPAddressNumber& address,
- const IPAddressNumber& local,
+ const IPAddress& address,
+ const IPAddress& local,
Buffer* output) {
MakeAddrMessageWithCacheInfo(type, flags, family, index, address, local,
INFINITY_LIFE_TIME, output);
@@ -247,11 +247,11 @@ const unsigned char kAddress3[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
TEST_F(AddressTrackerLinuxTest, NewAddress) {
InitializeAddressTracker(true);
- const IPAddressNumber kEmpty;
- const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
- const IPAddressNumber kAddr1(kAddress1, kAddress1 + arraysize(kAddress1));
- const IPAddressNumber kAddr2(kAddress2, kAddress2 + arraysize(kAddress2));
- const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3));
+ const IPAddress kEmpty;
+ const IPAddress kAddr0(kAddress0);
+ const IPAddress kAddr1(kAddress1);
+ const IPAddress kAddr2(kAddress2);
+ const IPAddress kAddr3(kAddress3);
Buffer buffer;
MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
@@ -284,8 +284,8 @@ TEST_F(AddressTrackerLinuxTest, NewAddress) {
TEST_F(AddressTrackerLinuxTest, NewAddressChange) {
InitializeAddressTracker(true);
- const IPAddressNumber kEmpty;
- const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
+ const IPAddress kEmpty;
+ const IPAddress kAddr0(kAddress0);
Buffer buffer;
MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
@@ -320,7 +320,7 @@ TEST_F(AddressTrackerLinuxTest, NewAddressChange) {
TEST_F(AddressTrackerLinuxTest, NewAddressDuplicate) {
InitializeAddressTracker(true);
- const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
+ const IPAddress kAddr0(kAddress0);
Buffer buffer;
MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
@@ -340,10 +340,10 @@ TEST_F(AddressTrackerLinuxTest, NewAddressDuplicate) {
TEST_F(AddressTrackerLinuxTest, DeleteAddress) {
InitializeAddressTracker(true);
- const IPAddressNumber kEmpty;
- const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
- const IPAddressNumber kAddr1(kAddress1, kAddress1 + arraysize(kAddress1));
- const IPAddressNumber kAddr2(kAddress2, kAddress2 + arraysize(kAddress2));
+ const IPAddress kEmpty;
+ const IPAddress kAddr0(kAddress0);
+ const IPAddress kAddr1(kAddress1);
+ const IPAddress kAddr2(kAddress2);
Buffer buffer;
MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kTestInterfaceEth, kAddr0, kEmpty,
@@ -382,8 +382,8 @@ TEST_F(AddressTrackerLinuxTest, DeleteAddress) {
TEST_F(AddressTrackerLinuxTest, DeprecatedLifetime) {
InitializeAddressTracker(true);
- const IPAddressNumber kEmpty;
- const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3));
+ const IPAddress kEmpty;
+ const IPAddress kAddr3(kAddress3);
Buffer buffer;
MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth, kEmpty, kAddr3,
@@ -425,9 +425,9 @@ TEST_F(AddressTrackerLinuxTest, DeprecatedLifetime) {
TEST_F(AddressTrackerLinuxTest, IgnoredMessage) {
InitializeAddressTracker(true);
- const IPAddressNumber kEmpty;
- const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
- const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3));
+ const IPAddress kEmpty;
+ const IPAddress kAddr0(kAddress0);
+ const IPAddress kAddr3(kAddress3);
Buffer buffer;
// Ignored family.
@@ -450,7 +450,7 @@ TEST_F(AddressTrackerLinuxTest, IgnoredMessage) {
// Ignored attribute.
struct ifa_cacheinfo cache_info = {};
nlmsg.AddAttribute(IFA_CACHEINFO, &cache_info, sizeof(cache_info));
- nlmsg.AddAttribute(IFA_ADDRESS, &kAddr0[0], kAddr0.size());
+ nlmsg.AddAttribute(IFA_ADDRESS, kAddr0.bytes().data(), kAddr0.size());
nlmsg.AppendTo(&buffer);
EXPECT_TRUE(HandleAddressMessage(buffer));
@@ -567,8 +567,8 @@ TEST_F(AddressTrackerLinuxTest, IgnoreInterface) {
InitializeAddressTracker(true);
Buffer buffer;
- const IPAddressNumber kEmpty;
- const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
+ const IPAddress kEmpty;
+ const IPAddress kAddr0(kAddress0);
// Verify online links and address map has been not been updated
MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceAp,
@@ -589,8 +589,8 @@ TEST_F(AddressTrackerLinuxTest, IgnoreInterface_NonIgnoredInterface) {
InitializeAddressTracker(true);
Buffer buffer;
- const IPAddressNumber kEmpty;
- const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
+ const IPAddress kEmpty;
+ const IPAddress kAddr0(kAddress0);
// Verify eth0 is not ignored when only uap0 is ignored
MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
@@ -662,8 +662,8 @@ TEST_F(AddressTrackerLinuxTest, GetInterfaceName) {
TEST_F(AddressTrackerLinuxTest, NonTrackingMode) {
InitializeAddressTracker(false);
- const IPAddressNumber kEmpty;
- const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
+ const IPAddress kEmpty;
+ const IPAddress kAddr0(kAddress0);
Buffer buffer;
MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
diff --git a/chromium/net/base/chunked_upload_data_stream.cc b/chromium/net/base/chunked_upload_data_stream.cc
index 2b9c4807c7a..7ddd9418dbc 100644
--- a/chromium/net/base/chunked_upload_data_stream.cc
+++ b/chromium/net/base/chunked_upload_data_stream.cc
@@ -10,17 +10,37 @@
namespace net {
+ChunkedUploadDataStream::Writer::~Writer() {}
+
+bool ChunkedUploadDataStream::Writer::AppendData(const char* data,
+ int data_len,
+ bool is_done) {
+ if (!upload_data_stream_)
+ return false;
+ upload_data_stream_->AppendData(data, data_len, is_done);
+ return true;
+}
+
+ChunkedUploadDataStream::Writer::Writer(
+ base::WeakPtr<ChunkedUploadDataStream> upload_data_stream)
+ : upload_data_stream_(upload_data_stream) {}
+
ChunkedUploadDataStream::ChunkedUploadDataStream(int64_t identifier)
: UploadDataStream(true, identifier),
read_index_(0),
read_offset_(0),
all_data_appended_(false),
- read_buffer_len_(0) {
-}
+ read_buffer_len_(0),
+ weak_factory_(this) {}
ChunkedUploadDataStream::~ChunkedUploadDataStream() {
}
+scoped_ptr<ChunkedUploadDataStream::Writer>
+ChunkedUploadDataStream::CreateWriter() {
+ return make_scoped_ptr(new Writer(weak_factory_.GetWeakPtr()));
+}
+
void ChunkedUploadDataStream::AppendData(
const char* data, int data_len, bool is_done) {
DCHECK(!all_data_appended_);
diff --git a/chromium/net/base/chunked_upload_data_stream.h b/chromium/net/base/chunked_upload_data_stream.h
index 7b5e2dfecb6..e8b9cd34f07 100644
--- a/chromium/net/base/chunked_upload_data_stream.h
+++ b/chromium/net/base/chunked_upload_data_stream.h
@@ -12,6 +12,8 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
#include "net/base/upload_data_stream.h"
@@ -25,14 +27,54 @@ class IOBuffer;
// seekable data, due to this buffering behavior.
class NET_EXPORT ChunkedUploadDataStream : public UploadDataStream {
public:
+ // Utility class that allows writing data to a particular
+ // ChunkedUploadDataStream. It can outlive the associated
+ // ChunkedUploadDataStream, and the URLRequest it is associated with, and
+ // still be safely used. This allows the consumer to not have to worry about
+ // the lifetime of the ChunkedUploadDataStream, which the owning URLRequest
+ // may delete without warning.
+ //
+ // The writer may only be used on the ChunkedUploadDataStream's thread.
+ class NET_EXPORT Writer {
+ public:
+ ~Writer();
+
+ // Adds data to the stream. |is_done| should be true if this is the last
+ // data to be appended. |data_len| must not be 0 unless |is_done| is true.
+ // Once called with |is_done| being true, must never be called again.
+ // Returns true if write was passed successfully on to the next layer,
+ // though the data may not actually have been written to the underlying
+ // URLRequest. Returns false if unable to write the data failed because the
+ // underlying ChunkedUploadDataStream was destroyed.
+ bool AppendData(const char* data, int data_len, bool is_done);
+
+ private:
+ friend class ChunkedUploadDataStream;
+
+ explicit Writer(base::WeakPtr<ChunkedUploadDataStream> upload_data_stream);
+
+ const base::WeakPtr<ChunkedUploadDataStream> upload_data_stream_;
+
+ DISALLOW_COPY_AND_ASSIGN(Writer);
+ };
+
explicit ChunkedUploadDataStream(int64_t identifier);
~ChunkedUploadDataStream() override;
+ // Creates a Writer for appending data to |this|. It's generally expected
+ // that only one writer is created per stream, though multiple writers are
+ // allowed. All writers write to the same stream, and once one of them
+ // appends data with |is_done| being true, no other writers may be used to
+ // append data.
+ scoped_ptr<Writer> CreateWriter();
+
// Adds data to the stream. |is_done| should be true if this is the last
// data to be appended. |data_len| must not be 0 unless |is_done| is true.
// Once called with |is_done| being true, must never be called again.
// TODO(mmenke): Consider using IOBuffers instead, to reduce data copies.
+ // TODO(mmenke): Consider making private, and having all consumers use
+ // Writers.
void AppendData(const char* data, int data_len, bool is_done);
private:
@@ -57,6 +99,8 @@ class NET_EXPORT ChunkedUploadDataStream : public UploadDataStream {
scoped_refptr<IOBuffer> read_buffer_;
int read_buffer_len_;
+ base::WeakPtrFactory<ChunkedUploadDataStream> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ChunkedUploadDataStream);
};
diff --git a/chromium/net/base/chunked_upload_data_stream_unittest.cc b/chromium/net/base/chunked_upload_data_stream_unittest.cc
index 334e9a39428..283465106fc 100644
--- a/chromium/net/base/chunked_upload_data_stream_unittest.cc
+++ b/chromium/net/base/chunked_upload_data_stream_unittest.cc
@@ -305,4 +305,26 @@ TEST(ChunkedUploadDataStreamTest, RewindWhileReading) {
EXPECT_FALSE(callback.have_result());
}
+// Check the behavior of ChunkedUploadDataStream::Writer.
+TEST(ChunkedUploadDataStreamTest, ChunkedUploadDataStreamWriter) {
+ scoped_ptr<ChunkedUploadDataStream> stream(new ChunkedUploadDataStream(0));
+ scoped_ptr<ChunkedUploadDataStream::Writer> writer(stream->CreateWriter());
+
+ // Write before Init.
+ ASSERT_TRUE(writer->AppendData(kTestData, 1, false));
+ ASSERT_EQ(OK, stream->Init(TestCompletionCallback().callback()));
+
+ // Write after Init.
+ ASSERT_TRUE(writer->AppendData(kTestData + 1, kTestDataSize - 1, false));
+
+ TestCompletionCallback callback;
+ std::string data = ReadSync(stream.get(), kTestBufferSize);
+ EXPECT_EQ(kTestData, data);
+
+ // Writing data should gracefully fail if the stream is deleted while still
+ // appending data to it.
+ stream.reset();
+ EXPECT_FALSE(writer->AppendData(kTestData, kTestDataSize, true));
+}
+
} // namespace net
diff --git a/chromium/net/base/data_url.cc b/chromium/net/base/data_url.cc
index 07b8fb00bb5..40911850ff3 100644
--- a/chromium/net/base/data_url.cc
+++ b/chromium/net/base/data_url.cc
@@ -21,6 +21,9 @@ namespace net {
// static
bool DataURL::Parse(const GURL& url, std::string* mime_type,
std::string* charset, std::string* data) {
+ if (!url.is_valid())
+ return false;
+
DCHECK(mime_type->empty());
DCHECK(charset->empty());
std::string::const_iterator begin = url.spec().begin();
@@ -96,9 +99,10 @@ bool DataURL::Parse(const GURL& url, std::string* mime_type,
// of the data, and should be stripped. Otherwise, the escaped whitespace
// could be part of the payload, so don't strip it.
if (base64_encoded) {
- temp_data = UnescapeURLComponent(temp_data,
- UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS |
- UnescapeRule::SPOOFING_AND_CONTROL_CHARS);
+ temp_data = UnescapeURLComponent(
+ temp_data, UnescapeRule::SPACES | UnescapeRule::PATH_SEPARATORS |
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS |
+ UnescapeRule::SPOOFING_AND_CONTROL_CHARS);
}
// Strip whitespace.
@@ -110,9 +114,10 @@ bool DataURL::Parse(const GURL& url, std::string* mime_type,
}
if (!base64_encoded) {
- temp_data = UnescapeURLComponent(temp_data,
- UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS |
- UnescapeRule::SPOOFING_AND_CONTROL_CHARS);
+ temp_data = UnescapeURLComponent(
+ temp_data, UnescapeRule::SPACES | UnescapeRule::PATH_SEPARATORS |
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS |
+ UnescapeRule::SPOOFING_AND_CONTROL_CHARS);
}
if (base64_encoded) {
diff --git a/chromium/net/base/dir_header.html b/chromium/net/base/dir_header.html
index c75637bfff0..8bb1f1ef7af 100644
--- a/chromium/net/base/dir_header.html
+++ b/chromium/net/base/dir_header.html
@@ -7,7 +7,8 @@
<meta name="google" value="notranslate">
<script>
-function addRow(name, url, isdir, size, date_modified) {
+function addRow(name, url, isdir,
+ size, size_string, date_modified, date_modified_string) {
if (name == ".")
return;
@@ -15,7 +16,7 @@ function addRow(name, url, isdir, size, date_modified) {
if (root.substr(-1) !== "/")
root += "/";
- var table = document.getElementById("table");
+ var tbody = document.getElementById("tbody");
var row = document.createElement("tr");
var file_cell = document.createElement("td");
var link = document.createElement("a");
@@ -26,13 +27,16 @@ function addRow(name, url, isdir, size, date_modified) {
link.href = root + "..";
link.innerText = document.getElementById("parentDirText").innerText;
link.className = "icon up";
- size = "";
- date_modified = "";
+ size = 0;
+ size_string = "";
+ date_modified = 0;
+ date_modified_string = "";
} else {
if (isdir) {
name = name + "/";
url = url + "/";
- size = "";
+ size = 0;
+ size_string = "";
} else {
link.draggable = "true";
link.addEventListener("dragstart", onDragStart, false);
@@ -40,13 +44,14 @@ function addRow(name, url, isdir, size, date_modified) {
link.innerText = name;
link.href = root + url;
}
+ file_cell.dataset.value = name;
file_cell.appendChild(link);
row.appendChild(file_cell);
- row.appendChild(createCell(size));
- row.appendChild(createCell(date_modified));
+ row.appendChild(createCell(size, size_string));
+ row.appendChild(createCell(date_modified, date_modified_string));
- table.appendChild(row);
+ tbody.appendChild(row);
}
function onDragStart(e) {
@@ -57,9 +62,10 @@ function onDragStart(e) {
e.dataTransfer.effectAllowed = "copy";
}
-function createCell(text) {
+function createCell(value, text) {
var cell = document.createElement("td");
cell.setAttribute("class", "detailsColumn");
+ cell.dataset.value = value;
cell.innerText = text;
return cell;
}
@@ -77,6 +83,46 @@ function onListingParsingError() {
+ "?raw");
box.style.display = "block";
}
+
+function sortTable(column) {
+ var theader = document.getElementById("theader");
+ var oldOrder = theader.cells[column].dataset.order || '1';
+ oldOrder = parseInt(oldOrder, 10)
+ var newOrder = 0 - oldOrder;
+ theader.cells[column].dataset.order = newOrder;
+
+ var tbody = document.getElementById("tbody");
+ var rows = tbody.rows;
+ var list = [], i;
+ for (i = 0; i < rows.length; i++) {
+ list.push(rows[i]);
+ }
+
+ list.sort(function(row1, row2) {
+ var a = row1.cells[column].dataset.value;
+ var b = row2.cells[column].dataset.value;
+ if (column) {
+ a = parseInt(a, 10);
+ b = parseInt(b, 10);
+ return a > b ? newOrder : a < b ? oldOrder : 0;
+ }
+
+ // Column 0 is text.
+ // Also the parent directory should always be sorted at one of the ends.
+ if (b == ".." | a > b) {
+ return newOrder;
+ } else if (a == ".." | a < b) {
+ return oldOrder;
+ } else {
+ return 0;
+ }
+ });
+
+ // Appending an existing child again just moves it.
+ for (i = 0; i < list.length; i++) {
+ tbody.appendChild(list[i]);
+ }
+}
</script>
<style>
@@ -92,8 +138,8 @@ function onListingParsingError() {
border-collapse: collapse;
}
- tr.header {
- font-weight: bold;
+ th {
+ cursor: pointer;
}
td.detailsColumn {
@@ -147,12 +193,16 @@ function onListingParsingError() {
<h1 id="header" i18n-content="header"></h1>
-<table id="table">
- <tr class="header">
- <td i18n-content="headerName"></td>
- <td class="detailsColumn" i18n-content="headerSize"></td>
- <td class="detailsColumn" i18n-content="headerDateModified"></td>
- </tr>
+<table>
+ <thead>
+ <tr class="header" id="theader">
+ <th i18n-content="headerName" onclick="javascript:sortTable(0);"></th>
+ <th class="detailsColumn" i18n-content="headerSize" onclick="javascript:sortTable(1);"></th>
+ <th class="detailsColumn" i18n-content="headerDateModified" onclick="javascript:sortTable(2);"></th>
+ </tr>
+ </thead>
+ <tbody id="tbody">
+ </tbody>
</table>
</body>
diff --git a/chromium/net/base/directory_lister.cc b/chromium/net/base/directory_lister.cc
index 6b06ca62e11..352deeb4b74 100644
--- a/chromium/net/base/directory_lister.cc
+++ b/chromium/net/base/directory_lister.cc
@@ -13,7 +13,7 @@
#include "base/i18n/file_util_icu.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/worker_pool.h"
@@ -64,11 +64,7 @@ void SortData(std::vector<DirectoryLister::DirectoryListerData>* data,
DirectoryLister::DirectoryLister(const base::FilePath& dir,
DirectoryListerDelegate* delegate)
- : delegate_(delegate) {
- core_ = new Core(dir, ALPHA_DIRS_FIRST, this);
- DCHECK(delegate_);
- DCHECK(!dir.value().empty());
-}
+ : DirectoryLister(dir, ALPHA_DIRS_FIRST, delegate) {}
DirectoryLister::DirectoryLister(const base::FilePath& dir,
ListingType type,
@@ -83,11 +79,8 @@ DirectoryLister::~DirectoryLister() {
Cancel();
}
-bool DirectoryLister::Start() {
- return base::WorkerPool::PostTask(
- FROM_HERE,
- base::Bind(&Core::Start, core_),
- true);
+bool DirectoryLister::Start(base::TaskRunner* dir_task_runner) {
+ return dir_task_runner->PostTask(FROM_HERE, base::Bind(&Core::Start, core_));
}
void DirectoryLister::Cancel() {
@@ -99,7 +92,7 @@ DirectoryLister::Core::Core(const base::FilePath& dir,
DirectoryLister* lister)
: dir_(dir),
type_(type),
- origin_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ origin_task_runner_(base::ThreadTaskRunnerHandle::Get().get()),
lister_(lister),
cancelled_(0) {
DCHECK(lister_);
@@ -108,7 +101,7 @@ DirectoryLister::Core::Core(const base::FilePath& dir,
DirectoryLister::Core::~Core() {}
void DirectoryLister::Core::CancelOnOriginThread() {
- DCHECK(origin_task_runner_->BelongsToCurrentThread());
+ DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
base::subtle::NoBarrier_Store(&cancelled_, 1);
// Core must not call into |lister_| after cancellation, as the |lister_| may
@@ -179,7 +172,7 @@ bool DirectoryLister::Core::IsCancelled() const {
void DirectoryLister::Core::DoneOnOriginThread(
scoped_ptr<DirectoryList> directory_list, int error) const {
- DCHECK(origin_task_runner_->BelongsToCurrentThread());
+ DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
// Need to check if the operation was before first callback.
if (IsCancelled())
diff --git a/chromium/net/base/directory_lister.h b/chromium/net/base/directory_lister.h
index a29ff53287a..5a397e465ca 100644
--- a/chromium/net/base/directory_lister.h
+++ b/chromium/net/base/directory_lister.h
@@ -16,7 +16,7 @@
#include "net/base/net_export.h"
namespace base {
-class SingleThreadTaskRunner;
+class TaskRunner;
}
namespace net {
@@ -69,7 +69,7 @@ class NET_EXPORT DirectoryLister {
~DirectoryLister();
// Call this method to start the directory enumeration thread.
- bool Start();
+ bool Start(base::TaskRunner* dir_task_runner);
// Call this method to asynchronously stop directory enumeration. The
// delegate will not be called back.
@@ -110,7 +110,7 @@ class NET_EXPORT DirectoryLister {
const base::FilePath dir_;
const ListingType type_;
- const scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
+ const scoped_refptr<base::TaskRunner> origin_task_runner_;
// Only used on the origin thread.
DirectoryLister* lister_;
diff --git a/chromium/net/base/directory_lister_unittest.cc b/chromium/net/base/directory_lister_unittest.cc
index 1e80718bb70..41cdb7af42c 100644
--- a/chromium/net/base/directory_lister_unittest.cc
+++ b/chromium/net/base/directory_lister_unittest.cc
@@ -13,6 +13,7 @@
#include "base/i18n/file_util_icu.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
+#include "base/thread_task_runner_handle.h"
#include "net/base/directory_lister.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -96,7 +97,7 @@ class ListerDelegate : public DirectoryLister::DirectoryListerDelegate {
void Run(DirectoryLister* lister) {
lister_ = lister;
- lister_->Start();
+ lister_->Start(base::ThreadTaskRunnerHandle::Get().get());
run_loop.Run();
}
@@ -235,7 +236,7 @@ TEST_F(DirectoryListerTest, BasicCancelTest) {
ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST);
scoped_ptr<DirectoryLister> lister(new DirectoryLister(
root_path(), &delegate));
- lister->Start();
+ lister->Start(base::ThreadTaskRunnerHandle::Get().get());
lister->Cancel();
base::RunLoop().RunUntilIdle();
diff --git a/chromium/net/base/directory_listing.cc b/chromium/net/base/directory_listing.cc
index 25d98bc6811..e5635472dd6 100644
--- a/chromium/net/base/directory_listing.cc
+++ b/chromium/net/base/directory_listing.cc
@@ -57,6 +57,10 @@ std::string GetDirectoryListingEntry(const base::string16& name,
}
// Negative size means unknown or not applicable (e.g. directory).
+ std::stringstream raw_size_string_stream;
+ raw_size_string_stream << size << ",";
+ result.append(raw_size_string_stream.str());
+
base::string16 size_string;
if (size >= 0)
size_string = base::FormatBytesUnlocalized(size);
@@ -64,12 +68,23 @@ std::string GetDirectoryListingEntry(const base::string16& name,
result.append(",");
- base::string16 modified_str;
// |modified| can be NULL in FTP listings.
- if (!modified.is_null())
+ base::string16 modified_str;
+ if (modified.is_null()) {
+ result.append("0,");
+ } else {
+ std::stringstream raw_time_string_stream;
+ // Certain access paths can only get up to seconds resolution, so here we
+ // output the raw time value in seconds for consistency.
+ raw_time_string_stream << modified.ToJavaTime() /
+ base::Time::kMillisecondsPerSecond
+ << ",";
+ result.append(raw_time_string_stream.str());
+
modified_str = base::TimeFormatShortDateAndTime(modified);
- base::EscapeJSONString(modified_str, true, &result);
+ }
+ base::EscapeJSONString(modified_str, true, &result);
result.append(");</script>\n");
return result;
diff --git a/chromium/net/base/directory_listing_unittest.cc b/chromium/net/base/directory_listing_unittest.cc
index 7470c2ab9e1..4f888c0fd31 100644
--- a/chromium/net/base/directory_listing_unittest.cc
+++ b/chromium/net/base/directory_listing_unittest.cc
@@ -23,44 +23,24 @@ struct GetDirectoryListingEntryCase {
TEST(DirectoryListingTest, GetDirectoryListingEntry) {
const GetDirectoryListingEntryCase test_cases[] = {
- {L"Foo",
- "",
- false,
- 10000,
- base::Time(),
- "<script>addRow(\"Foo\",\"Foo\",0,\"9.8 kB\",\"\");</script>\n"},
- {L"quo\"tes",
- "",
- false,
- 10000,
- base::Time(),
- "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>"
- "\n"},
- {L"quo\"tes",
- "quo\"tes",
- false,
- 10000,
- base::Time(),
- "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>"
- "\n"},
- // U+D55C0 U+AE00. raw_bytes is empty (either a local file with
- // UTF-8/UTF-16 encoding or a remote file on an ftp server using UTF-8
- {L"\xD55C\xAE00.txt",
- "",
- false,
- 10000,
- base::Time(),
- "<script>addRow(\"\xED\x95\x9C\xEA\xB8\x80.txt\","
- "\"%ED%95%9C%EA%B8%80.txt\",0,\"9.8 kB\",\"\");</script>\n"},
- // U+D55C0 U+AE00. raw_bytes is the corresponding EUC-KR sequence:
- // a local or remote file in EUC-KR.
- {L"\xD55C\xAE00.txt",
- "\xC7\xD1\xB1\xDB.txt",
- false,
- 10000,
- base::Time(),
- "<script>addRow(\"\xED\x95\x9C\xEA\xB8\x80.txt\",\"%C7%D1%B1%DB.txt\""
- ",0,\"9.8 kB\",\"\");</script>\n"},
+ {L"Foo", "", false, 10000, base::Time(),
+ "<script>addRow(\"Foo\",\"Foo\",0,10000,\"9.8 kB\",0,\"\");</script>\n"},
+ {L"quo\"tes", "", false, 10000, base::Time(),
+ "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,10000,\"9.8 kB\",0,\"\""
+ ");</script>\n"},
+ {L"quo\"tes", "quo\"tes", false, 10000, base::Time(),
+ "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,10000,\"9.8 kB\",0,\"\""
+ ");</script>\n"},
+ // U+D55C0 U+AE00. raw_bytes is empty (either a local file with
+ // UTF-8/UTF-16 encoding or a remote file on an ftp server using UTF-8
+ {L"\xD55C\xAE00.txt", "", false, 10000, base::Time(),
+ "<script>addRow(\"\xED\x95\x9C\xEA\xB8\x80.txt\","
+ "\"%ED%95%9C%EA%B8%80.txt\",0,10000,\"9.8 kB\",0,\"\");</script>\n"},
+ // U+D55C0 U+AE00. raw_bytes is the corresponding EUC-KR sequence:
+ // a local or remote file in EUC-KR.
+ {L"\xD55C\xAE00.txt", "\xC7\xD1\xB1\xDB.txt", false, 10000, base::Time(),
+ "<script>addRow(\"\xED\x95\x9C\xEA\xB8\x80.txt\",\"%C7%D1%B1%DB.txt\""
+ ",0,10000,\"9.8 kB\",0,\"\");</script>\n"},
};
for (size_t i = 0; i < arraysize(test_cases); ++i) {
diff --git a/chromium/net/base/escape.cc b/chromium/net/base/escape.cc
index 15de5e1dbd3..fc7d5cf0fc8 100644
--- a/chromium/net/base/escape.cc
+++ b/chromium/net/base/escape.cc
@@ -290,7 +290,10 @@ STR UnescapeURLWithAdjustmentsImpl(
(first_byte == ' ' && (rules & UnescapeRule::SPACES)) ||
// Allow any of the prohibited but non-control characters when
// we're doing "special" chars.
- (first_byte > ' ' && (rules & UnescapeRule::URL_SPECIAL_CHARS)) ||
+ ((first_byte == '/' || first_byte == '\\') &&
+ (rules & UnescapeRule::PATH_SEPARATORS)) ||
+ (first_byte > ' ' && first_byte != '/' && first_byte != '\\' &&
+ (rules & UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS)) ||
// Additionally allow non-display characters if requested.
(first_byte < ' ' &&
(rules & UnescapeRule::SPOOFING_AND_CONTROL_CHARS)))) {
diff --git a/chromium/net/base/escape.h b/chromium/net/base/escape.h
index c31dcf9aa22..8637a70a5e7 100644
--- a/chromium/net/base/escape.h
+++ b/chromium/net/base/escape.h
@@ -78,20 +78,28 @@ class UnescapeRule {
// just the absence of them). All other unescape rules imply "normal" in
// addition to their special meaning. Things like escaped letters, digits,
// and most symbols will get unescaped with this mode.
- NORMAL = 1,
+ NORMAL = 1 << 0,
// Convert %20 to spaces. In some places where we're showing URLs, we may
// want this. In places where the URL may be copied and pasted out, then
// you wouldn't want this since it might not be interpreted in one piece
// by other applications.
- SPACES = 2,
+ SPACES = 1 << 1,
+
+ // Unescapes '/' and '\\'. If these characters were unescaped, the resulting
+ // URL won't be the same as the source one. Moreover, they are dangerous to
+ // unescape in strings that will be used as file paths or names. This value
+ // should only be used when slashes don't have special meaning, like data
+ // URLs.
+ PATH_SEPARATORS = 1 << 2,
// Unescapes various characters that will change the meaning of URLs,
- // including '%', '+', '&', '/', '#'. If we unescaped these characters, the
- // resulting URL won't be the same as the source one. This flag is used when
- // generating final output like filenames for URLs where we won't be
- // interpreting as a URL and want to do as much unescaping as possible.
- URL_SPECIAL_CHARS = 4,
+ // including '%', '+', '&', '#'. Does not unescape path separators.
+ // If these characters were unescaped, the resulting URL won't be the same
+ // as the source one. This flag is used when generating final output like
+ // filenames for URLs where we won't be interpreting as a URL and want to do
+ // as much unescaping as possible.
+ URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS = 1 << 3,
// Unescapes characters that can be used in spoofing attempts (such as LOCK)
// and control characters (such as BiDi control characters and %01). This
@@ -100,10 +108,10 @@ class UnescapeRule {
//
// DO NOT use SPOOFING_AND_CONTROL_CHARS if the URL is going to be displayed
// in the UI for security reasons.
- SPOOFING_AND_CONTROL_CHARS = 8,
+ SPOOFING_AND_CONTROL_CHARS = 1 << 4,
// URL queries use "+" for space. This flag controls that replacement.
- REPLACE_PLUS_WITH_SPACE = 16,
+ REPLACE_PLUS_WITH_SPACE = 1 << 5,
};
};
diff --git a/chromium/net/base/escape_unittest.cc b/chromium/net/base/escape_unittest.cc
index cec7f32d1e5..b828d80b5fe 100644
--- a/chromium/net/base/escape_unittest.cc
+++ b/chromium/net/base/escape_unittest.cc
@@ -150,43 +150,55 @@ TEST(EscapeTest, EscapeUrlEncodedDataSpace) {
TEST(EscapeTest, UnescapeURLComponentASCII) {
const UnescapeURLCaseASCII unescape_cases[] = {
- {"", UnescapeRule::NORMAL, ""},
- {"%2", UnescapeRule::NORMAL, "%2"},
- {"%%%%%%", UnescapeRule::NORMAL, "%%%%%%"},
- {"Don't escape anything", UnescapeRule::NORMAL, "Don't escape anything"},
- {"Invalid %escape %2", UnescapeRule::NORMAL, "Invalid %escape %2"},
- {"Some%20random text %25%2dOK", UnescapeRule::NONE,
- "Some%20random text %25%2dOK"},
- {"Some%20random text %25%2dOK", UnescapeRule::NORMAL,
- "Some%20random text %25-OK"},
- {"Some%20random text %25%2dOK", UnescapeRule::SPACES,
- "Some random text %25-OK"},
- {"Some%20random text %25%2dOK", UnescapeRule::URL_SPECIAL_CHARS,
- "Some%20random text %-OK"},
- {"Some%20random text %25%2dOK",
- UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS,
- "Some random text %-OK"},
- {"%A0%B1%C2%D3%E4%F5", UnescapeRule::NORMAL, "\xA0\xB1\xC2\xD3\xE4\xF5"},
- {"%Aa%Bb%Cc%Dd%Ee%Ff", UnescapeRule::NORMAL, "\xAa\xBb\xCc\xDd\xEe\xFf"},
- // Certain URL-sensitive characters should not be unescaped unless asked.
- {"Hello%20%13%10world %23# %3F? %3D= %26& %25% %2B+", UnescapeRule::SPACES,
- "Hello %13%10world %23# %3F? %3D= %26& %25% %2B+"},
- {"Hello%20%13%10world %23# %3F? %3D= %26& %25% %2B+",
- UnescapeRule::URL_SPECIAL_CHARS,
- "Hello%20%13%10world ## ?? == && %% ++"},
- // We can neither escape nor unescape '@' since some websites expect it to
- // be preserved as either '@' or "%40".
- // See http://b/996720 and http://crbug.com/23933 .
- {"me@my%40example", UnescapeRule::NORMAL, "me@my%40example"},
- // Control characters.
- {"%01%02%03%04%05%06%07%08%09 %25", UnescapeRule::URL_SPECIAL_CHARS,
- "%01%02%03%04%05%06%07%08%09 %"},
- {"%01%02%03%04%05%06%07%08%09 %25",
- UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- "\x01\x02\x03\x04\x05\x06\x07\x08\x09 %25"},
- {"Hello%20%13%10%02", UnescapeRule::SPACES, "Hello %13%10%02"},
- {"Hello%20%13%10%02", UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- "Hello%20\x13\x10\x02"},
+ {"", UnescapeRule::NORMAL, ""},
+ {"%2", UnescapeRule::NORMAL, "%2"},
+ {"%%%%%%", UnescapeRule::NORMAL, "%%%%%%"},
+ {"Don't escape anything", UnescapeRule::NORMAL, "Don't escape anything"},
+ {"Invalid %escape %2", UnescapeRule::NORMAL, "Invalid %escape %2"},
+ {"Some%20random text %25%2dOK", UnescapeRule::NONE,
+ "Some%20random text %25%2dOK"},
+ {"Some%20random text %25%2dOK", UnescapeRule::NORMAL,
+ "Some%20random text %25-OK"},
+ {"Some%20random text %25%2dOK", UnescapeRule::SPACES,
+ "Some random text %25-OK"},
+ {"Some%20random text %25%2dOK", UnescapeRule::PATH_SEPARATORS,
+ "Some%20random text %25-OK"},
+ {"Some%20random text %25%2dOK",
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS,
+ "Some%20random text %-OK"},
+ {"Some%20random text %25%2dOK",
+ UnescapeRule::SPACES |
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS,
+ "Some random text %-OK"},
+ {"%A0%B1%C2%D3%E4%F5", UnescapeRule::NORMAL, "\xA0\xB1\xC2\xD3\xE4\xF5"},
+ {"%Aa%Bb%Cc%Dd%Ee%Ff", UnescapeRule::NORMAL, "\xAa\xBb\xCc\xDd\xEe\xFf"},
+ // Certain URL-sensitive characters should not be unescaped unless asked.
+ {"Hello%20%13%10world %23# %3F? %3D= %26& %25% %2B+",
+ UnescapeRule::SPACES, "Hello %13%10world %23# %3F? %3D= %26& %25% %2B+"},
+ {"Hello%20%13%10world %23# %3F? %3D= %26& %25% %2B+",
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS,
+ "Hello%20%13%10world ## ?? == && %% ++"},
+ // We can neither escape nor unescape '@' since some websites expect it to
+ // be preserved as either '@' or "%40".
+ // See http://b/996720 and http://crbug.com/23933 .
+ {"me@my%40example", UnescapeRule::NORMAL, "me@my%40example"},
+ // Control characters.
+ {"%01%02%03%04%05%06%07%08%09 %25",
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS,
+ "%01%02%03%04%05%06%07%08%09 %"},
+ {"%01%02%03%04%05%06%07%08%09 %25",
+ UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ "\x01\x02\x03\x04\x05\x06\x07\x08\x09 %25"},
+ {"Hello%20%13%10%02", UnescapeRule::SPACES, "Hello %13%10%02"},
+ {"Hello%20%13%10%02", UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ "Hello%20\x13\x10\x02"},
+
+ // '/' and '\\' should only be unescaped by PATH_SEPARATORS.
+ {"%2F%5C", UnescapeRule::PATH_SEPARATORS, "/\\"},
+ {"%2F%5C", UnescapeRule::SPACES |
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS |
+ UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ "%2F%5C"},
};
for (size_t i = 0; i < arraysize(unescape_cases); i++) {
@@ -218,126 +230,135 @@ TEST(EscapeTest, UnescapeURLComponentASCII) {
TEST(EscapeTest, UnescapeURLComponent) {
const UnescapeURLCase unescape_cases[] = {
- {L"", UnescapeRule::NORMAL, L""},
- {L"%2", UnescapeRule::NORMAL, L"%2"},
- {L"%%%%%%", UnescapeRule::NORMAL, L"%%%%%%"},
- {L"Don't escape anything", UnescapeRule::NORMAL, L"Don't escape anything"},
- {L"Invalid %escape %2", UnescapeRule::NORMAL, L"Invalid %escape %2"},
- {L"Some%20random text %25%2dOK", UnescapeRule::NONE,
- L"Some%20random text %25%2dOK"},
- {L"Some%20random text %25%2dOK", UnescapeRule::NORMAL,
- L"Some%20random text %25-OK"},
- {L"Some%20random text %25%E2%80", UnescapeRule::NORMAL,
- L"Some%20random text %25\xE2\x80"},
- {L"Some%20random text %25%E2%80OK", UnescapeRule::NORMAL,
- L"Some%20random text %25\xE2\x80OK"},
- {L"Some%20random text %25%E2%80%84OK", UnescapeRule::NORMAL,
- L"Some%20random text %25\xE2\x80\x84OK"},
-
- // BiDi Control characters should not be unescaped unless explicity told to
- // do so with UnescapeRule::SPOOFING_AND_CONTROL_CHARS
- {L"Some%20random text %25%D8%9COK", UnescapeRule::NORMAL,
- L"Some%20random text %25%D8%9COK"},
- {L"Some%20random text %25%E2%80%8EOK", UnescapeRule::NORMAL,
- L"Some%20random text %25%E2%80%8EOK"},
- {L"Some%20random text %25%E2%80%8FOK", UnescapeRule::NORMAL,
- L"Some%20random text %25%E2%80%8FOK"},
- {L"Some%20random text %25%E2%80%AAOK", UnescapeRule::NORMAL,
- L"Some%20random text %25%E2%80%AAOK"},
- {L"Some%20random text %25%E2%80%ABOK", UnescapeRule::NORMAL,
- L"Some%20random text %25%E2%80%ABOK"},
- {L"Some%20random text %25%E2%80%AEOK", UnescapeRule::NORMAL,
- L"Some%20random text %25%E2%80%AEOK"},
- {L"Some%20random text %25%E2%81%A6OK", UnescapeRule::NORMAL,
- L"Some%20random text %25%E2%81%A6OK"},
- {L"Some%20random text %25%E2%81%A9OK", UnescapeRule::NORMAL,
- L"Some%20random text %25%E2%81%A9OK"},
- // UnescapeRule::SPOOFING_AND_CONTROL_CHARS should unescape BiDi Control
- // characters.
- {L"Some%20random text %25%D8%9COK",
- UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Some%20random text %25\xD8\x9COK"},
- {L"Some%20random text %25%E2%80%8EOK",
- UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Some%20random text %25\xE2\x80\x8EOK"},
- {L"Some%20random text %25%E2%80%8FOK",
- UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Some%20random text %25\xE2\x80\x8FOK"},
- {L"Some%20random text %25%E2%80%AAOK",
- UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Some%20random text %25\xE2\x80\xAAOK"},
- {L"Some%20random text %25%E2%80%ABOK",
- UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Some%20random text %25\xE2\x80\xABOK"},
- {L"Some%20random text %25%E2%80%AEOK",
- UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Some%20random text %25\xE2\x80\xAEOK"},
- {L"Some%20random text %25%E2%81%A6OK",
- UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Some%20random text %25\xE2\x81\xA6OK"},
- {L"Some%20random text %25%E2%81%A9OK",
- UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Some%20random text %25\xE2\x81\xA9OK"},
-
- // Certain banned characters should not be unescaped unless explicitly told
- // to do so with UnescapeRule::SPOOFING_AND_CONTROL_CHARS.
- // U+1F50F LOCK WITH INK PEN
- {L"Some%20random text %25%F0%9F%94%8FOK", UnescapeRule::NORMAL,
- L"Some%20random text %25%F0%9F%94%8FOK"},
- // U+1F510 CLOSED LOCK WITH KEY
- {L"Some%20random text %25%F0%9F%94%90OK", UnescapeRule::NORMAL,
- L"Some%20random text %25%F0%9F%94%90OK"},
- // U+1F512 LOCK
- {L"Some%20random text %25%F0%9F%94%92OK", UnescapeRule::NORMAL,
- L"Some%20random text %25%F0%9F%94%92OK"},
- // U+1F513 OPEN LOCK
- {L"Some%20random text %25%F0%9F%94%93OK", UnescapeRule::NORMAL,
- L"Some%20random text %25%F0%9F%94%93OK"},
- // UnescapeRule::SPOOFING_AND_CONTROL_CHARS should unescape banned
- // characters.
- {L"Some%20random text %25%F0%9F%94%8FOK",
- UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Some%20random text %25\xF0\x9F\x94\x8FOK"},
- {L"Some%20random text %25%F0%9F%94%90OK",
- UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Some%20random text %25\xF0\x9F\x94\x90OK"},
- {L"Some%20random text %25%F0%9F%94%92OK",
- UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Some%20random text %25\xF0\x9F\x94\x92OK"},
- {L"Some%20random text %25%F0%9F%94%93OK",
- UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Some%20random text %25\xF0\x9F\x94\x93OK"},
-
- {L"Some%20random text %25%2dOK", UnescapeRule::SPACES,
- L"Some random text %25-OK"},
- {L"Some%20random text %25%2dOK", UnescapeRule::URL_SPECIAL_CHARS,
- L"Some%20random text %-OK"},
- {L"Some%20random text %25%2dOK",
- UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS,
- L"Some random text %-OK"},
- {L"%A0%B1%C2%D3%E4%F5", UnescapeRule::NORMAL, L"\xA0\xB1\xC2\xD3\xE4\xF5"},
- {L"%Aa%Bb%Cc%Dd%Ee%Ff", UnescapeRule::NORMAL, L"\xAa\xBb\xCc\xDd\xEe\xFf"},
- // Certain URL-sensitive characters should not be unescaped unless asked.
- {L"Hello%20%13%10world %23# %3F? %3D= %26& %25% %2B+", UnescapeRule::SPACES,
- L"Hello %13%10world %23# %3F? %3D= %26& %25% %2B+"},
- {L"Hello%20%13%10world %23# %3F? %3D= %26& %25% %2B+",
- UnescapeRule::URL_SPECIAL_CHARS,
- L"Hello%20%13%10world ## ?? == && %% ++"},
- // We can neither escape nor unescape '@' since some websites expect it to
- // be preserved as either '@' or "%40".
- // See http://b/996720 and http://crbug.com/23933 .
- {L"me@my%40example", UnescapeRule::NORMAL, L"me@my%40example"},
- // Control characters.
- {L"%01%02%03%04%05%06%07%08%09 %25", UnescapeRule::URL_SPECIAL_CHARS,
- L"%01%02%03%04%05%06%07%08%09 %"},
- {L"%01%02%03%04%05%06%07%08%09 %25",
- UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"\x01\x02\x03\x04\x05\x06\x07\x08\x09 %25"},
- {L"Hello%20%13%10%02", UnescapeRule::SPACES, L"Hello %13%10%02"},
- {L"Hello%20%13%10%02", UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Hello%20\x13\x10\x02"},
- {L"Hello\x9824\x9827", UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
- L"Hello\x9824\x9827"},
+ {L"", UnescapeRule::NORMAL, L""},
+ {L"%2", UnescapeRule::NORMAL, L"%2"},
+ {L"%%%%%%", UnescapeRule::NORMAL, L"%%%%%%"},
+ {L"Don't escape anything", UnescapeRule::NORMAL,
+ L"Don't escape anything"},
+ {L"Invalid %escape %2", UnescapeRule::NORMAL, L"Invalid %escape %2"},
+ {L"Some%20random text %25%2dOK", UnescapeRule::NONE,
+ L"Some%20random text %25%2dOK"},
+ {L"Some%20random text %25%2dOK", UnescapeRule::NORMAL,
+ L"Some%20random text %25-OK"},
+ {L"Some%20random text %25%E2%80", UnescapeRule::NORMAL,
+ L"Some%20random text %25\xE2\x80"},
+ {L"Some%20random text %25%E2%80OK", UnescapeRule::NORMAL,
+ L"Some%20random text %25\xE2\x80OK"},
+ {L"Some%20random text %25%E2%80%84OK", UnescapeRule::NORMAL,
+ L"Some%20random text %25\xE2\x80\x84OK"},
+
+ // BiDi Control characters should not be unescaped unless explicity told
+ // to
+ // do so with UnescapeRule::SPOOFING_AND_CONTROL_CHARS
+ {L"Some%20random text %25%D8%9COK", UnescapeRule::NORMAL,
+ L"Some%20random text %25%D8%9COK"},
+ {L"Some%20random text %25%E2%80%8EOK", UnescapeRule::NORMAL,
+ L"Some%20random text %25%E2%80%8EOK"},
+ {L"Some%20random text %25%E2%80%8FOK", UnescapeRule::NORMAL,
+ L"Some%20random text %25%E2%80%8FOK"},
+ {L"Some%20random text %25%E2%80%AAOK", UnescapeRule::NORMAL,
+ L"Some%20random text %25%E2%80%AAOK"},
+ {L"Some%20random text %25%E2%80%ABOK", UnescapeRule::NORMAL,
+ L"Some%20random text %25%E2%80%ABOK"},
+ {L"Some%20random text %25%E2%80%AEOK", UnescapeRule::NORMAL,
+ L"Some%20random text %25%E2%80%AEOK"},
+ {L"Some%20random text %25%E2%81%A6OK", UnescapeRule::NORMAL,
+ L"Some%20random text %25%E2%81%A6OK"},
+ {L"Some%20random text %25%E2%81%A9OK", UnescapeRule::NORMAL,
+ L"Some%20random text %25%E2%81%A9OK"},
+ // UnescapeRule::SPOOFING_AND_CONTROL_CHARS should unescape BiDi Control
+ // characters.
+ {L"Some%20random text %25%D8%9COK",
+ UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Some%20random text %25\xD8\x9COK"},
+ {L"Some%20random text %25%E2%80%8EOK",
+ UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Some%20random text %25\xE2\x80\x8EOK"},
+ {L"Some%20random text %25%E2%80%8FOK",
+ UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Some%20random text %25\xE2\x80\x8FOK"},
+ {L"Some%20random text %25%E2%80%AAOK",
+ UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Some%20random text %25\xE2\x80\xAAOK"},
+ {L"Some%20random text %25%E2%80%ABOK",
+ UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Some%20random text %25\xE2\x80\xABOK"},
+ {L"Some%20random text %25%E2%80%AEOK",
+ UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Some%20random text %25\xE2\x80\xAEOK"},
+ {L"Some%20random text %25%E2%81%A6OK",
+ UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Some%20random text %25\xE2\x81\xA6OK"},
+ {L"Some%20random text %25%E2%81%A9OK",
+ UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Some%20random text %25\xE2\x81\xA9OK"},
+
+ // Certain banned characters should not be unescaped unless explicitly
+ // told
+ // to do so with UnescapeRule::SPOOFING_AND_CONTROL_CHARS.
+ // U+1F50F LOCK WITH INK PEN
+ {L"Some%20random text %25%F0%9F%94%8FOK", UnescapeRule::NORMAL,
+ L"Some%20random text %25%F0%9F%94%8FOK"},
+ // U+1F510 CLOSED LOCK WITH KEY
+ {L"Some%20random text %25%F0%9F%94%90OK", UnescapeRule::NORMAL,
+ L"Some%20random text %25%F0%9F%94%90OK"},
+ // U+1F512 LOCK
+ {L"Some%20random text %25%F0%9F%94%92OK", UnescapeRule::NORMAL,
+ L"Some%20random text %25%F0%9F%94%92OK"},
+ // U+1F513 OPEN LOCK
+ {L"Some%20random text %25%F0%9F%94%93OK", UnescapeRule::NORMAL,
+ L"Some%20random text %25%F0%9F%94%93OK"},
+ // UnescapeRule::SPOOFING_AND_CONTROL_CHARS should unescape banned
+ // characters.
+ {L"Some%20random text %25%F0%9F%94%8FOK",
+ UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Some%20random text %25\xF0\x9F\x94\x8FOK"},
+ {L"Some%20random text %25%F0%9F%94%90OK",
+ UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Some%20random text %25\xF0\x9F\x94\x90OK"},
+ {L"Some%20random text %25%F0%9F%94%92OK",
+ UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Some%20random text %25\xF0\x9F\x94\x92OK"},
+ {L"Some%20random text %25%F0%9F%94%93OK",
+ UnescapeRule::NORMAL | UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Some%20random text %25\xF0\x9F\x94\x93OK"},
+
+ {L"Some%20random text %25%2dOK", UnescapeRule::SPACES,
+ L"Some random text %25-OK"},
+ {L"Some%20random text %25%2dOK",
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS,
+ L"Some%20random text %-OK"},
+ {L"Some%20random text %25%2dOK",
+ UnescapeRule::SPACES |
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS,
+ L"Some random text %-OK"},
+ {L"%A0%B1%C2%D3%E4%F5", UnescapeRule::NORMAL,
+ L"\xA0\xB1\xC2\xD3\xE4\xF5"},
+ {L"%Aa%Bb%Cc%Dd%Ee%Ff", UnescapeRule::NORMAL,
+ L"\xAa\xBb\xCc\xDd\xEe\xFf"},
+ // Certain URL-sensitive characters should not be unescaped unless asked.
+ {L"Hello%20%13%10world %23# %3F? %3D= %26& %25% %2B+",
+ UnescapeRule::SPACES,
+ L"Hello %13%10world %23# %3F? %3D= %26& %25% %2B+"},
+ {L"Hello%20%13%10world %23# %3F? %3D= %26& %25% %2B+",
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS,
+ L"Hello%20%13%10world ## ?? == && %% ++"},
+ // We can neither escape nor unescape '@' since some websites expect it to
+ // be preserved as either '@' or "%40".
+ // See http://b/996720 and http://crbug.com/23933 .
+ {L"me@my%40example", UnescapeRule::NORMAL, L"me@my%40example"},
+ // Control characters.
+ {L"%01%02%03%04%05%06%07%08%09 %25",
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS,
+ L"%01%02%03%04%05%06%07%08%09 %"},
+ {L"%01%02%03%04%05%06%07%08%09 %25",
+ UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"\x01\x02\x03\x04\x05\x06\x07\x08\x09 %25"},
+ {L"Hello%20%13%10%02", UnescapeRule::SPACES, L"Hello %13%10%02"},
+ {L"Hello%20%13%10%02", UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Hello%20\x13\x10\x02"},
+ {L"Hello\x9824\x9827", UnescapeRule::SPOOFING_AND_CONTROL_CHARS,
+ L"Hello\x9824\x9827"},
};
for (size_t i = 0; i < arraysize(unescape_cases); i++) {
diff --git a/chromium/net/base/file_stream.h b/chromium/net/base/file_stream.h
index 64a34354808..fc4b1a4bfa1 100644
--- a/chromium/net/base/file_stream.h
+++ b/chromium/net/base/file_stream.h
@@ -14,6 +14,7 @@
#include "base/files/file.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
diff --git a/chromium/net/base/file_stream_context_win.cc b/chromium/net/base/file_stream_context_win.cc
index 907d863b8e4..0294a1aa486 100644
--- a/chromium/net/base/file_stream_context_win.cc
+++ b/chromium/net/base/file_stream_context_win.cc
@@ -5,6 +5,7 @@
#include "net/base/file_stream_context.h"
#include <windows.h>
+#include <utility>
#include "base/files/file_path.h"
#include "base/location.h"
@@ -50,7 +51,7 @@ FileStream::Context::Context(const scoped_refptr<base::TaskRunner>& task_runner)
FileStream::Context::Context(base::File file,
const scoped_refptr<base::TaskRunner>& task_runner)
- : file_(file.Pass()),
+ : file_(std::move(file)),
async_in_progress_(false),
orphaned_(false),
task_runner_(task_runner),
diff --git a/chromium/net/base/filename_util.cc b/chromium/net/base/filename_util.cc
index 0969f715521..153ce43d024 100644
--- a/chromium/net/base/filename_util.cc
+++ b/chromium/net/base/filename_util.cc
@@ -98,7 +98,8 @@ bool FileURLToFilePath(const GURL& url, base::FilePath* file_path) {
// GURL stores strings as percent-encoded 8-bit, this will undo if possible.
path = UnescapeURLComponent(
- path, UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS);
+ path, UnescapeRule::SPACES |
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS);
#if defined(OS_WIN)
if (base::IsStringUTF8(path)) {
diff --git a/chromium/net/base/filename_util_internal.cc b/chromium/net/base/filename_util_internal.cc
index 2f038ad4028..6eb3f55ed44 100644
--- a/chromium/net/base/filename_util_internal.cc
+++ b/chromium/net/base/filename_util_internal.cc
@@ -124,7 +124,8 @@ std::string GetFileNameFromURL(const GURL& url,
const std::string unescaped_url_filename = UnescapeURLComponent(
url.ExtractFileName(),
- UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS);
+ UnescapeRule::SPACES |
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS);
// The URL's path should be escaped UTF-8, but may not be.
std::string decoded_filename = unescaped_url_filename;
@@ -162,8 +163,8 @@ bool IsShellIntegratedExtension(const base::FilePath::StringType& extension) {
// http://www.juniper.net/security/auto/vulnerabilities/vuln2612.html
// Files become magical if they end in a CLSID, so block such extensions.
if (!extension_lower.empty() &&
- (extension_lower[0] == FILE_PATH_LITERAL('{')) &&
- (extension_lower[extension_lower.length() - 1] == FILE_PATH_LITERAL('}')))
+ (extension_lower.front() == FILE_PATH_LITERAL('{')) &&
+ (extension_lower.back() == FILE_PATH_LITERAL('}')))
return true;
return false;
}
diff --git a/chromium/net/base/filename_util_unittest.cc b/chromium/net/base/filename_util_unittest.cc
index 5e3fb7e1c9f..16a6ec0c73d 100644
--- a/chromium/net/base/filename_util_unittest.cc
+++ b/chromium/net/base/filename_util_unittest.cc
@@ -239,6 +239,9 @@ TEST(FilenameUtilTest, FileURLConversion) {
{L"\\\\foo\\bar.txt", "file:/foo/bar.txt"},
{L"\\\\foo\\bar.txt", "file://foo\\bar.txt"},
{L"C:\\foo\\bar.txt", "file:\\\\\\c:/foo/bar.txt"},
+ // %2f ('/') and %5c ('\\') are left alone by both GURL and
+ // FileURLToFilePath.
+ {L"C:\\foo%2f..%5cbar", "file:///C:\\foo%2f..%5cbar"},
#elif defined(OS_POSIX)
{L"/c:/foo/bar.txt", "file:/c:/foo/bar.txt"},
{L"/c:/foo/bar.txt", "file:///c:/foo/bar.txt"},
@@ -253,6 +256,9 @@ TEST(FilenameUtilTest, FileURLConversion) {
{L"/foo/bar.txt", "file:////foo////bar.txt"},
{L"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"},
{L"/c:/foo/bar.txt", "file:c:/foo/bar.txt"},
+ // %2f ('/') and %5c ('\\') are left alone by both GURL and
+ // FileURLToFilePath.
+ {L"/foo%2f..%5cbar", "file:///foo%2f..%5cbar"},
// We get these wrong because GURL turns back slashes into forward
// slashes.
// {L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
@@ -822,6 +828,9 @@ TEST(FilenameUtilTest, GenerateFileName) {
{// A normal avi should get .avi and not .avi.avi
__LINE__, "https://blah.google.com/misc/2.avi", "", "", "",
"video/x-msvideo", L"download", L"2.avi"},
+ {// Shouldn't unescape slashes.
+ __LINE__, "http://www.example.com/foo%2f..%2fbar.jpg", "", "", "",
+ "text/plain", L"download", L"foo%2f..%2fbar.jpg"},
{// Extension generation
__LINE__, "http://www.example.com/my-cat", "filename=my-cat", "", "",
"image/jpeg", L"download", L"my-cat"},
diff --git a/chromium/net/base/fuzzer_test_support.cc b/chromium/net/base/fuzzer_test_support.cc
new file mode 100644
index 00000000000..1c185c6d82c
--- /dev/null
+++ b/chromium/net/base/fuzzer_test_support.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 "base/at_exit.h"
+#include "base/i18n/icu_util.h"
+
+namespace {
+
+// This translation unit provides a static initializer to set up ICU.
+//
+// ICU is used internally by GURL, which is used throughout the //net code.
+// Initializing ICU is important to prevent fuzztests from asserting when
+// handling non-ASCII urls.
+//
+// Note that in general static initializers are not allowed, however this is
+// just being used by test code.
+struct InitICU {
+ InitICU() { CHECK(base::i18n::InitializeICU()); }
+ base::AtExitManager at_exit_manager;
+};
+
+InitICU* init_icu = new InitICU();
+
+} // namespace
diff --git a/chromium/net/base/hash_value.cc b/chromium/net/base/hash_value.cc
index 9a91a93b4be..f72aa454df6 100644
--- a/chromium/net/base/hash_value.cc
+++ b/chromium/net/base/hash_value.cc
@@ -4,6 +4,8 @@
#include "net/base/hash_value.h"
+#include <stdlib.h>
+
#include "base/base64.h"
#include "base/logging.h"
#include "base/sha1.h"
diff --git a/chromium/net/base/host_mapping_rules.cc b/chromium/net/base/host_mapping_rules.cc
index 5e604250c27..3c24b245942 100644
--- a/chromium/net/base/host_mapping_rules.cc
+++ b/chromium/net/base/host_mapping_rules.cc
@@ -10,7 +10,7 @@
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "net/base/host_port_pair.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
namespace net {
diff --git a/chromium/net/base/host_port_pair.cc b/chromium/net/base/host_port_pair.cc
index a0dd2d50752..441a35965d8 100644
--- a/chromium/net/base/host_port_pair.cc
+++ b/chromium/net/base/host_port_pair.cc
@@ -10,6 +10,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/base/ip_endpoint.h"
+#include "net/base/parse_number.h"
#include "net/base/port_util.h"
#include "url/gurl.h"
@@ -37,7 +38,7 @@ HostPortPair HostPortPair::FromString(const std::string& str) {
if (key_port.size() != 2)
return HostPortPair();
int port;
- if (!base::StringToInt(key_port[1], &port))
+ if (!ParseNonNegativeDecimalInt(key_port[1], &port))
return HostPortPair();
if (!IsPortValid(port))
return HostPortPair();
diff --git a/chromium/net/base/host_port_pair_unittest.cc b/chromium/net/base/host_port_pair_unittest.cc
index 8047cc31814..72704a0f5c9 100644
--- a/chromium/net/base/host_port_pair_unittest.cc
+++ b/chromium/net/base/host_port_pair_unittest.cc
@@ -38,11 +38,8 @@ TEST(HostPortPairTest, Parsing) {
TEST(HostPortPairTest, BadString) {
const char* kBadStrings[] = {
- "foo.com:2:3",
- "bar.com:two",
- "www.google.com:-1",
- "127.0.0.1:65536",
- "[2001:db8::42]:65536",
+ "foo.com:2:3", "bar.com:two", "www.google.com:-1",
+ "www.google.com:+1", "127.0.0.1:65536", "[2001:db8::42]:65536",
};
for (size_t index = 0; index < arraysize(kBadStrings); ++index) {
diff --git a/chromium/net/base/io_buffer.h b/chromium/net/base/io_buffer.h
index 5e9ff21d6b8..9285791adeb 100644
--- a/chromium/net/base/io_buffer.h
+++ b/chromium/net/base/io_buffer.h
@@ -9,6 +9,7 @@
#include <string>
+#include "base/memory/free_deleter.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/pickle.h"
diff --git a/chromium/net/base/ip_address.cc b/chromium/net/base/ip_address.cc
index 060477ea7d4..722e3703f35 100644
--- a/chromium/net/base/ip_address.cc
+++ b/chromium/net/base/ip_address.cc
@@ -4,22 +4,53 @@
#include "net/base/ip_address.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
#include "net/base/ip_address_number.h"
+#include "net/base/parse_number.h"
#include "url/gurl.h"
#include "url/url_canon_ip.h"
namespace net {
-const size_t IPAddress::kIPv4AddressSize = 4;
-const size_t IPAddress::kIPv6AddressSize = 16;
-
IPAddress::IPAddress() {}
IPAddress::IPAddress(const IPAddressNumber& address) : ip_address_(address) {}
+IPAddress::IPAddress(const IPAddress& other) = default;
+
IPAddress::IPAddress(const uint8_t* address, size_t address_len)
: ip_address_(address, address + address_len) {}
+IPAddress::IPAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) {
+ ip_address_.reserve(4);
+ ip_address_.push_back(b0);
+ ip_address_.push_back(b1);
+ ip_address_.push_back(b2);
+ ip_address_.push_back(b3);
+}
+
+IPAddress::IPAddress(uint8_t b0,
+ uint8_t b1,
+ uint8_t b2,
+ uint8_t b3,
+ uint8_t b4,
+ uint8_t b5,
+ uint8_t b6,
+ uint8_t b7,
+ uint8_t b8,
+ uint8_t b9,
+ uint8_t b10,
+ uint8_t b11,
+ uint8_t b12,
+ uint8_t b13,
+ uint8_t b14,
+ uint8_t b15) {
+ const uint8_t address[] = {b0, b1, b2, b3, b4, b5, b6, b7,
+ b8, b9, b10, b11, b12, b13, b14, b15};
+ ip_address_ = std::vector<uint8_t>(std::begin(address), std::end(address));
+}
+
IPAddress::~IPAddress() {}
bool IPAddress::IsIPv4() const {
@@ -38,7 +69,16 @@ bool IPAddress::IsReserved() const {
return IsIPAddressReserved(ip_address_);
}
-bool IPAddress::IsIPv4Mapped() const {
+bool IPAddress::IsZero() const {
+ for (auto x : ip_address_) {
+ if (x != 0)
+ return false;
+ }
+
+ return !empty();
+}
+
+bool IPAddress::IsIPv4MappedIPv6() const {
return net::IsIPv4Mapped(ip_address_);
}
@@ -46,21 +86,51 @@ std::string IPAddress::ToString() const {
return IPAddressToString(ip_address_);
}
-// static
-bool IPAddress::FromIPLiteral(const base::StringPiece& ip_literal,
- IPAddress* ip_address) {
+bool IPAddress::AssignFromIPLiteral(const base::StringPiece& ip_literal) {
std::vector<uint8_t> number;
if (!ParseIPLiteralToNumber(ip_literal, &number))
return false;
- std::swap(number, ip_address->ip_address_);
+ std::swap(number, ip_address_);
return true;
}
+// static
+IPAddress IPAddress::IPv4Localhost() {
+ static const uint8_t kLocalhostIPv4[] = {127, 0, 0, 1};
+ return IPAddress(kLocalhostIPv4);
+}
+
+// static
+IPAddress IPAddress::IPv6Localhost() {
+ static const uint8_t kLocalhostIPv6[] = {0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1};
+ return IPAddress(kLocalhostIPv6);
+}
+
+// static
+IPAddress IPAddress::AllZeros(size_t num_zero_bytes) {
+ return IPAddress(std::vector<uint8_t>(num_zero_bytes));
+}
+
+// static
+IPAddress IPAddress::IPv4AllZeros() {
+ return AllZeros(kIPv4AddressSize);
+}
+
+// static
+IPAddress IPAddress::IPv6AllZeros() {
+ return AllZeros(kIPv6AddressSize);
+}
+
bool IPAddress::operator==(const IPAddress& that) const {
return ip_address_ == that.ip_address_;
}
+bool IPAddress::operator!=(const IPAddress& that) const {
+ return ip_address_ != that.ip_address_;
+}
+
bool IPAddress::operator<(const IPAddress& that) const {
// Sort IPv4 before IPv6.
if (ip_address_.size() != that.ip_address_.size()) {
@@ -70,4 +140,78 @@ bool IPAddress::operator<(const IPAddress& that) const {
return ip_address_ < that.ip_address_;
}
+std::string IPAddressToStringWithPort(const IPAddress& address, uint16_t port) {
+ return IPAddressToStringWithPort(address.bytes(), port);
+}
+
+std::string IPAddressToPackedString(const IPAddress& address) {
+ return IPAddressToPackedString(address.bytes());
+}
+
+IPAddress ConvertIPv4ToIPv4MappedIPv6(const IPAddress& address) {
+ return IPAddress(ConvertIPv4NumberToIPv6Number(address.bytes()));
+}
+
+IPAddress ConvertIPv4MappedIPv6ToIPv4(const IPAddress& address) {
+ return IPAddress(ConvertIPv4MappedToIPv4(address.bytes()));
+}
+
+bool IPAddressMatchesPrefix(const IPAddress& ip_address,
+ const IPAddress& ip_prefix,
+ size_t prefix_length_in_bits) {
+ return IPNumberMatchesPrefix(ip_address.bytes(), ip_prefix.bytes(),
+ prefix_length_in_bits);
+}
+
+bool ParseCIDRBlock(const std::string& cidr_literal,
+ IPAddress* ip_address,
+ size_t* prefix_length_in_bits) {
+ // We expect CIDR notation to match one of these two templates:
+ // <IPv4-literal> "/" <number of bits>
+ // <IPv6-literal> "/" <number of bits>
+
+ std::vector<base::StringPiece> parts = base::SplitStringPiece(
+ cidr_literal, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ if (parts.size() != 2)
+ return false;
+
+ // Parse the IP address.
+ if (!ip_address->AssignFromIPLiteral(parts[0]))
+ return false;
+
+ // Parse the prefix length.
+ int number_of_bits = -1;
+ if (!ParseNonNegativeDecimalInt(parts[1], &number_of_bits))
+ return false;
+
+ // Make sure the prefix length is in a valid range.
+ if (number_of_bits < 0 ||
+ number_of_bits > static_cast<int>(ip_address->size() * 8))
+ return false;
+
+ *prefix_length_in_bits = static_cast<size_t>(number_of_bits);
+ return true;
+}
+
+bool ParseURLHostnameToAddress(const std::string& hostname,
+ IPAddress* ip_address) {
+ if (hostname.size() >= 2 && hostname.front() == '[' &&
+ hostname.back() == ']') {
+ // Strip the square brackets that surround IPv6 literals.
+ auto ip_literal =
+ base::StringPiece(hostname).substr(1, hostname.size() - 2);
+ return ip_address->AssignFromIPLiteral(ip_literal) && ip_address->IsIPv6();
+ }
+
+ return ip_address->AssignFromIPLiteral(hostname) && ip_address->IsIPv4();
+}
+
+unsigned CommonPrefixLength(const IPAddress& a1, const IPAddress& a2) {
+ return CommonPrefixLength(a1.bytes(), a2.bytes());
+}
+
+unsigned MaskPrefixLength(const IPAddress& mask) {
+ return MaskPrefixLength(mask.bytes());
+}
+
} // namespace net
diff --git a/chromium/net/base/ip_address.h b/chromium/net/base/ip_address.h
index 69e6696fd6d..2f9d7aba90c 100644
--- a/chromium/net/base/ip_address.h
+++ b/chromium/net/base/ip_address.h
@@ -20,8 +20,7 @@ namespace net {
class NET_EXPORT IPAddress {
public:
- static const size_t kIPv4AddressSize;
- static const size_t kIPv6AddressSize;
+ enum : size_t { kIPv4AddressSize = 4, kIPv6AddressSize = 16 };
// Creates a zero-sized, invalid address.
IPAddress();
@@ -29,6 +28,8 @@ class NET_EXPORT IPAddress {
// Creates an IP address from a deprecated IPAddressNumber.
explicit IPAddress(const IPAddressNumber& address);
+ IPAddress(const IPAddress& other);
+
// Copies the input address to |ip_address_|. The input is expected to be in
// network byte order.
template <size_t N>
@@ -39,6 +40,29 @@ class NET_EXPORT IPAddress {
// parameter. The input is expected to be in network byte order.
IPAddress(const uint8_t* address, size_t address_len);
+ // Initializes |ip_address_| from the 4 bX bytes to form an IPv4 address.
+ // The bytes are expected to be in network byte order.
+ IPAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3);
+
+ // Initializes |ip_address_| from the 16 bX bytes to form an IPv6 address.
+ // The bytes are expected to be in network byte order.
+ IPAddress(uint8_t b0,
+ uint8_t b1,
+ uint8_t b2,
+ uint8_t b3,
+ uint8_t b4,
+ uint8_t b5,
+ uint8_t b6,
+ uint8_t b7,
+ uint8_t b8,
+ uint8_t b9,
+ uint8_t b10,
+ uint8_t b11,
+ uint8_t b12,
+ uint8_t b13,
+ uint8_t b14,
+ uint8_t b15);
+
~IPAddress();
// Returns true if the IP has |kIPv4AddressSize| elements.
@@ -56,8 +80,11 @@ class NET_EXPORT IPAddress {
// protocols's reserved ranges.
bool IsReserved() const;
+ // Returns true if the IP is "zero" (e.g. the 0.0.0.0 IPv4 address).
+ bool IsZero() const;
+
// Returns true if |ip_address_| is an IPv4-mapped IPv6 address.
- bool IsIPv4Mapped() const;
+ bool IsIPv4MappedIPv6() const;
// The size in bytes of |ip_address_|.
size_t size() const { return ip_address_.size(); }
@@ -66,19 +93,35 @@ class NET_EXPORT IPAddress {
bool empty() const { return ip_address_.empty(); }
// Returns the canonical string representation of an IP address.
- // For example: "192.168.0.1" or "::1". The IP address must be
- // valid, calling this on an invalid address will result in a crash.
+ // For example: "192.168.0.1" or "::1". Returns the empty string when
+ // |ip_address_| is invalid.
std::string ToString() const;
// Parses an IP address literal (either IPv4 or IPv6) to its numeric value.
- // Returns true on success and fills |ip_address| with the numeric value.
- static bool FromIPLiteral(const base::StringPiece& ip_literal,
- IPAddress* ip_address) WARN_UNUSED_RESULT;
+ // Returns true on success and fills |ip_address_| with the numeric value.
+ bool AssignFromIPLiteral(const base::StringPiece& ip_literal)
+ WARN_UNUSED_RESULT;
// Returns the underlying byte vector.
const std::vector<uint8_t>& bytes() const { return ip_address_; };
+ // Returns an IPAddress instance representing the 127.0.0.1 address.
+ static IPAddress IPv4Localhost();
+
+ // Returns an IPAddress instance representing the ::1 address.
+ static IPAddress IPv6Localhost();
+
+ // Returns an IPAddress made up of |num_zero_bytes| zeros.
+ static IPAddress AllZeros(size_t num_zero_bytes);
+
+ // Returns an IPAddress instance representing the 0.0.0.0 address.
+ static IPAddress IPv4AllZeros();
+
+ // Returns an IPAddress instance representing the :: address.
+ static IPAddress IPv6AllZeros();
+
bool operator==(const IPAddress& that) const;
+ bool operator!=(const IPAddress& that) const;
bool operator<(const IPAddress& that) const;
private:
@@ -89,6 +132,80 @@ class NET_EXPORT IPAddress {
// This class is copyable and assignable.
};
+using IPAddressList = std::vector<IPAddress>;
+
+// TODO(Martijnc): These utility functions currently forward the calls to
+// the IPAddressNumber implementations. Move the implementations over when
+// the IPAddressNumber migration is complete. https://crbug.com/496258.
+
+// Returns the canonical string representation of an IP address along with its
+// port. For example: "192.168.0.1:99" or "[::1]:80".
+NET_EXPORT std::string IPAddressToStringWithPort(const IPAddress& address,
+ uint16_t port);
+
+// Returns the address as a sequence of bytes in network-byte-order.
+NET_EXPORT std::string IPAddressToPackedString(const IPAddress& address);
+
+// Converts an IPv4 address to an IPv4-mapped IPv6 address.
+// For example 192.168.0.1 would be converted to ::ffff:192.168.0.1.
+NET_EXPORT IPAddress ConvertIPv4ToIPv4MappedIPv6(const IPAddress& address);
+
+// Converts an IPv4-mapped IPv6 address to IPv4 address. Should only be called
+// on IPv4-mapped IPv6 addresses.
+NET_EXPORT IPAddress ConvertIPv4MappedIPv6ToIPv4(const IPAddress& address);
+
+// Compares an IP address to see if it falls within the specified IP block.
+// Returns true if it does, false otherwise.
+//
+// The IP block is given by (|ip_prefix|, |prefix_length_in_bits|) -- any
+// IP address whose |prefix_length_in_bits| most significant bits match
+// |ip_prefix| will be matched.
+//
+// In cases when an IPv4 address is being compared to an IPv6 address prefix
+// and vice versa, the IPv4 addresses will be converted to IPv4-mapped
+// (IPv6) addresses.
+NET_EXPORT bool IPAddressMatchesPrefix(const IPAddress& ip_address,
+ const IPAddress& ip_prefix,
+ size_t prefix_length_in_bits);
+
+// Parses an IP block specifier from CIDR notation to an
+// (IP address, prefix length) pair. Returns true on success and fills
+// |*ip_address| with the numeric value of the IP address and sets
+// |*prefix_length_in_bits| with the length of the prefix.
+//
+// CIDR notation literals can use either IPv4 or IPv6 literals. Some examples:
+//
+// 10.10.3.1/20
+// a:b:c::/46
+// ::1/128
+NET_EXPORT bool ParseCIDRBlock(const std::string& cidr_literal,
+ IPAddress* ip_address,
+ size_t* prefix_length_in_bits);
+
+// Parses a URL-safe IP literal (see RFC 3986, Sec 3.2.2) to its numeric value.
+// Returns true on success, and fills |ip_address| with the numeric value.
+// In other words, |hostname| must be an IPv4 literal, or an IPv6 literal
+// surrounded by brackets as in [::1].
+NET_EXPORT bool ParseURLHostnameToAddress(const std::string& hostname,
+ IPAddress* ip_address)
+ WARN_UNUSED_RESULT;
+
+// Returns number of matching initial bits between the addresses |a1| and |a2|.
+unsigned CommonPrefixLength(const IPAddress& a1, const IPAddress& a2);
+
+// Computes the number of leading 1-bits in |mask|.
+unsigned MaskPrefixLength(const IPAddress& mask);
+
+// Checks whether |address| starts with |prefix|. This provides similar
+// functionality as IPAddressMatchesPrefix() but doesn't perform automatic IPv4
+// to IPv4MappedIPv6 conversions and only checks against full bytes.
+template <size_t N>
+bool IPAddressStartsWith(const IPAddress& address, const uint8_t (&prefix)[N]) {
+ if (address.size() < N)
+ return false;
+ return std::equal(prefix, prefix + N, address.bytes().begin());
+}
+
} // namespace net
#endif // NET_BASE_IP_ADDRESS_NET_H_
diff --git a/chromium/net/base/ip_address_number.cc b/chromium/net/base/ip_address_number.cc
index 1e44b7d3b1e..e9913140ae3 100644
--- a/chromium/net/base/ip_address_number.cc
+++ b/chromium/net/base/ip_address_number.cc
@@ -102,8 +102,6 @@ std::string IPAddressToString(const uint8_t* address, size_t address_len) {
url::AppendIPv4Address(address, &output);
} else if (address_len == kIPv6AddressSize) {
url::AppendIPv6Address(address, &output);
- } else {
- CHECK(false) << "Invalid IP address with length: " << address_len;
}
output.Complete();
@@ -114,6 +112,8 @@ std::string IPAddressToStringWithPort(const uint8_t* address,
size_t address_len,
uint16_t port) {
std::string address_str = IPAddressToString(address, address_len);
+ if (address_str.empty())
+ return address_str;
if (address_len == kIPv6AddressSize) {
// Need to bracket IPv6 addresses since they contain colons.
@@ -123,39 +123,16 @@ std::string IPAddressToStringWithPort(const uint8_t* address,
}
std::string IPAddressToString(const IPAddressNumber& addr) {
- return IPAddressToString(&addr.front(), addr.size());
+ return IPAddressToString(addr.data(), addr.size());
}
std::string IPAddressToStringWithPort(const IPAddressNumber& addr,
uint16_t port) {
- return IPAddressToStringWithPort(&addr.front(), addr.size(), port);
+ return IPAddressToStringWithPort(addr.data(), addr.size(), port);
}
std::string IPAddressToPackedString(const IPAddressNumber& addr) {
- return std::string(reinterpret_cast<const char *>(&addr.front()),
- addr.size());
-}
-
-bool ParseURLHostnameToNumber(const std::string& hostname,
- IPAddressNumber* ip_number) {
- // |hostname| is an already canoncalized hostname, conforming to RFC 3986.
- // For an IP address, this is defined in Section 3.2.2 of RFC 3986, with
- // the canonical form for IPv6 addresses defined in Section 4 of RFC 5952.
- url::Component host_comp(0, hostname.size());
-
- // If it has a bracket, try parsing it as an IPv6 address.
- if (hostname[0] == '[') {
- ip_number->resize(16); // 128 bits.
- return url::IPv6AddressToNumber(
- hostname.data(), host_comp, &(*ip_number)[0]);
- }
-
- // Otherwise, try IPv4.
- ip_number->resize(4); // 32 bits.
- int num_components;
- url::CanonHostInfo::Family family = url::IPv4AddressToNumber(
- hostname.data(), host_comp, &(*ip_number)[0], &num_components);
- return family == url::CanonHostInfo::IPV4;
+ return std::string(reinterpret_cast<const char*>(addr.data()), addr.size());
}
bool ParseIPLiteralToNumber(const base::StringPiece& ip_literal,
@@ -219,36 +196,6 @@ IPAddressNumber ConvertIPv4MappedToIPv4(const IPAddressNumber& address) {
address.end());
}
-bool ParseCIDRBlock(const std::string& cidr_literal,
- IPAddressNumber* ip_number,
- size_t* prefix_length_in_bits) {
- // We expect CIDR notation to match one of these two templates:
- // <IPv4-literal> "/" <number of bits>
- // <IPv6-literal> "/" <number of bits>
-
- std::vector<base::StringPiece> parts = base::SplitStringPiece(
- cidr_literal, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- if (parts.size() != 2)
- return false;
-
- // Parse the IP address.
- if (!ParseIPLiteralToNumber(parts[0], ip_number))
- return false;
-
- // Parse the prefix length.
- int number_of_bits = -1;
- if (!base::StringToInt(parts[1], &number_of_bits))
- return false;
-
- // Make sure the prefix length is in a valid range.
- if (number_of_bits < 0 ||
- number_of_bits > static_cast<int>(ip_number->size() * 8))
- return false;
-
- *prefix_length_in_bits = static_cast<size_t>(number_of_bits);
- return true;
-}
-
bool IPNumberMatchesPrefix(const IPAddressNumber& ip_number,
const IPAddressNumber& ip_prefix,
size_t prefix_length_in_bits) {
diff --git a/chromium/net/base/ip_address_number.h b/chromium/net/base/ip_address_number.h
index 2671a24d653..8c997e4efc8 100644
--- a/chromium/net/base/ip_address_number.h
+++ b/chromium/net/base/ip_address_number.h
@@ -26,7 +26,6 @@ namespace net {
// IPAddress instead and existing code should be switched over.
// https://crbug.com/496258
typedef std::vector<unsigned char> IPAddressNumber;
-typedef std::vector<IPAddressNumber> IPAddressList;
static const size_t kIPv4AddressSize = 4;
static const size_t kIPv6AddressSize = 16;
@@ -37,12 +36,14 @@ static const size_t kIPv6AddressSize = 16;
NET_EXPORT bool IsIPAddressReserved(const IPAddressNumber& address);
// Returns the string representation of an IP address.
-// For example: "192.168.0.1" or "::1".
+// For example: "192.168.0.1" or "::1". Returns the empty string when |address|
+// is invalid.
NET_EXPORT std::string IPAddressToString(const uint8_t* address,
size_t address_len);
// Returns the string representation of an IP address along with its port.
-// For example: "192.168.0.1:99" or "[::1]:80".
+// For example: "192.168.0.1:99" or "[::1]:80". Returns the empty string when
+// |address| is invalid (the port will be ignored).
NET_EXPORT std::string IPAddressToStringWithPort(const uint8_t* address,
size_t address_len,
uint16_t port);
@@ -57,11 +58,6 @@ NET_EXPORT std::string IPAddressToStringWithPort(const IPAddressNumber& addr,
// Returns the address as a sequence of bytes in network-byte-order.
NET_EXPORT std::string IPAddressToPackedString(const IPAddressNumber& addr);
-// Parses a URL-safe IP literal (see RFC 3986, Sec 3.2.2) to its numeric value.
-// Returns true on success, and fills |ip_number| with the numeric value
-NET_EXPORT bool ParseURLHostnameToNumber(const std::string& hostname,
- IPAddressNumber* ip_number);
-
// Parses an IP address literal (either IPv4 or IPv6) to its numeric value.
// Returns true on success and fills |ip_number| with the numeric value.
NET_EXPORT bool ParseIPLiteralToNumber(const base::StringPiece& ip_literal,
@@ -80,20 +76,6 @@ NET_EXPORT_PRIVATE bool IsIPv4Mapped(const IPAddressNumber& address);
NET_EXPORT_PRIVATE IPAddressNumber ConvertIPv4MappedToIPv4(
const IPAddressNumber& address);
-// Parses an IP block specifier from CIDR notation to an
-// (IP address, prefix length) pair. Returns true on success and fills
-// |*ip_number| with the numeric value of the IP address and sets
-// |*prefix_length_in_bits| with the length of the prefix.
-//
-// CIDR notation literals can use either IPv4 or IPv6 literals. Some examples:
-//
-// 10.10.3.1/20
-// a:b:c::/46
-// ::1/128
-NET_EXPORT bool ParseCIDRBlock(const std::string& cidr_literal,
- IPAddressNumber* ip_number,
- size_t* prefix_length_in_bits);
-
// Compares an IP address to see if it falls within the specified IP block.
// Returns true if it does, false otherwise.
//
diff --git a/chromium/net/base/ip_address_number_unittest.cc b/chromium/net/base/ip_address_number_unittest.cc
index 0b37bfac39f..f7975d6d9bd 100644
--- a/chromium/net/base/ip_address_number_unittest.cc
+++ b/chromium/net/base/ip_address_number_unittest.cc
@@ -7,7 +7,6 @@
#include "base/format_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
-#include "net/base/net_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -34,6 +33,10 @@ TEST(IpAddressNumberTest, IPAddressToString) {
uint8_t addr3[16] = {0xFE, 0xDC, 0xBA, 0x98};
EXPECT_EQ("fedc:ba98::", IPAddressToString(addr3, sizeof(addr3)));
+
+ // IPAddressToString() shouldn't crash on invalid addresses.
+ uint8_t addr4[2];
+ EXPECT_EQ("", IPAddressToString(addr4, sizeof(addr4)));
}
TEST(IpAddressNumberTest, IPAddressToStringWithPort) {
@@ -47,6 +50,10 @@ TEST(IpAddressNumberTest, IPAddressToStringWithPort) {
uint8_t addr3[16] = {0xFE, 0xDC, 0xBA, 0x98};
EXPECT_EQ("[fedc:ba98::]:8080",
IPAddressToStringWithPort(addr3, sizeof(addr3), 8080));
+
+ // IPAddressToStringWithPort() shouldn't crash on invalid addresses.
+ uint8_t addr4[2];
+ EXPECT_EQ("", IPAddressToStringWithPort(addr4, sizeof(addr4), 8080));
}
// Test that invalid IP literals fail to parse.
@@ -91,31 +98,6 @@ TEST(IpAddressNumberTest, ConvertIPv4NumberToIPv6Number) {
EXPECT_EQ("::ffff:c0a8:1", IPAddressToString(ipv6_number));
}
-TEST(IpAddressNumberTest, ParseURLHostnameToNumber_FailParse) {
- IPAddressNumber number;
-
- EXPECT_FALSE(ParseURLHostnameToNumber("bad value", &number));
- EXPECT_FALSE(ParseURLHostnameToNumber("bad:value", &number));
- EXPECT_FALSE(ParseURLHostnameToNumber(std::string(), &number));
- EXPECT_FALSE(ParseURLHostnameToNumber("192.168.0.1:30", &number));
- EXPECT_FALSE(ParseURLHostnameToNumber(" 192.168.0.1 ", &number));
- EXPECT_FALSE(ParseURLHostnameToNumber("::1", &number));
-}
-
-TEST(IpAddressNumberTest, ParseURLHostnameToNumber_IPv4) {
- IPAddressNumber number;
- EXPECT_TRUE(ParseURLHostnameToNumber("192.168.0.1", &number));
- EXPECT_EQ("192,168,0,1", DumpIPNumber(number));
- EXPECT_EQ("192.168.0.1", IPAddressToString(number));
-}
-
-TEST(IpAddressNumberTest, ParseURLHostnameToNumber_IPv6) {
- IPAddressNumber number;
- EXPECT_TRUE(ParseURLHostnameToNumber("[1:abcd::3:4:ff]", &number));
- EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPNumber(number));
- EXPECT_EQ("1:abcd::3:4:ff", IPAddressToString(number));
-}
-
TEST(IpAddressNumberTest, IsIPv4Mapped) {
IPAddressNumber ipv4_number;
EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number));
@@ -139,105 +121,29 @@ TEST(IpAddressNumberTest, ConvertIPv4MappedToIPv4) {
EXPECT_EQ(expected, result);
}
-// Test parsing invalid CIDR notation literals.
-TEST(IpAddressNumberTest, ParseCIDRBlock_Invalid) {
- const char* const bad_literals[] = {
- "foobar",
- "",
- "192.168.0.1",
- "::1",
- "/",
- "/1",
- "1",
- "192.168.1.1/-1",
- "192.168.1.1/33",
- "::1/-3",
- "a::3/129",
- "::1/x",
- "192.168.0.1//11"
- };
-
- for (size_t i = 0; i < arraysize(bad_literals); ++i) {
- IPAddressNumber ip_number;
- size_t prefix_length_in_bits;
-
- EXPECT_FALSE(ParseCIDRBlock(bad_literals[i],
- &ip_number,
- &prefix_length_in_bits));
- }
-}
-
-// Test parsing a valid CIDR notation literal.
-TEST(IpAddressNumberTest, ParseCIDRBlock_Valid) {
- IPAddressNumber ip_number;
- size_t prefix_length_in_bits;
-
- EXPECT_TRUE(ParseCIDRBlock("192.168.0.1/11",
- &ip_number,
- &prefix_length_in_bits));
-
- EXPECT_EQ("192,168,0,1", DumpIPNumber(ip_number));
- EXPECT_EQ(11u, prefix_length_in_bits);
-}
-
TEST(IpAddressNumberTest, IPNumberMatchesPrefix) {
struct {
const char* const cidr_literal;
+ size_t prefix_length_in_bits;
const char* const ip_literal;
bool expected_to_match;
} tests[] = {
- // IPv4 prefix with IPv4 inputs.
- {
- "10.10.1.32/27",
- "10.10.1.44",
- true
- },
- {
- "10.10.1.32/27",
- "10.10.1.90",
- false
- },
- {
- "10.10.1.32/27",
- "10.10.1.90",
- false
- },
-
- // IPv6 prefix with IPv6 inputs.
- {
- "2001:db8::/32",
- "2001:DB8:3:4::5",
- true
- },
- {
- "2001:db8::/32",
- "2001:c8::",
- false
- },
-
- // IPv6 prefix with IPv4 inputs.
- {
- "2001:db8::/33",
- "192.168.0.1",
- false
- },
- {
- "::ffff:192.168.0.1/112",
- "192.168.33.77",
- true
- },
-
- // IPv4 prefix with IPv6 inputs.
- {
- "10.11.33.44/16",
- "::ffff:0a0b:89",
- true
- },
- {
- "10.11.33.44/16",
- "::ffff:10.12.33.44",
- false
- },
+ // IPv4 prefix with IPv4 inputs.
+ {"10.10.1.32", 27, "10.10.1.44", true},
+ {"10.10.1.32", 27, "10.10.1.90", false},
+ {"10.10.1.32", 27, "10.10.1.90", false},
+
+ // IPv6 prefix with IPv6 inputs.
+ {"2001:db8::", 32, "2001:DB8:3:4::5", true},
+ {"2001:db8::", 32, "2001:c8::", false},
+
+ // IPv6 prefix with IPv4 inputs.
+ {"2001:db8::", 33, "192.168.0.1", false},
+ {"::ffff:192.168.0.1", 112, "192.168.33.77", true},
+
+ // IPv4 prefix with IPv6 inputs.
+ {"10.11.33.44", 16, "::ffff:0a0b:89", true},
+ {"10.11.33.44", 16, "::ffff:10.12.33.44", false},
};
for (size_t i = 0; i < arraysize(tests); ++i) {
SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s, %s", i,
@@ -248,16 +154,12 @@ TEST(IpAddressNumberTest, IPNumberMatchesPrefix) {
EXPECT_TRUE(ParseIPLiteralToNumber(tests[i].ip_literal, &ip_number));
IPAddressNumber ip_prefix;
- size_t prefix_length_in_bits;
- EXPECT_TRUE(ParseCIDRBlock(tests[i].cidr_literal,
- &ip_prefix,
- &prefix_length_in_bits));
+ EXPECT_TRUE(ParseIPLiteralToNumber(tests[i].cidr_literal, &ip_prefix));
EXPECT_EQ(tests[i].expected_to_match,
- IPNumberMatchesPrefix(ip_number,
- ip_prefix,
- prefix_length_in_bits));
+ IPNumberMatchesPrefix(ip_number, ip_prefix,
+ tests[i].prefix_length_in_bits));
}
}
diff --git a/chromium/net/base/ip_address_unittest.cc b/chromium/net/base/ip_address_unittest.cc
index 35c9cc93e98..3b9f3dfc183 100644
--- a/chromium/net/base/ip_address_unittest.cc
+++ b/chromium/net/base/ip_address_unittest.cc
@@ -13,7 +13,7 @@ namespace net {
namespace {
-// Helper to stringize an IP number (used to define expectations).
+// Helper to stringize an IP address (used to define expectations).
std::string DumpIPAddress(const IPAddress& v) {
std::string out;
for (size_t i = 0; i < v.bytes().size(); ++i) {
@@ -24,6 +24,20 @@ std::string DumpIPAddress(const IPAddress& v) {
return out;
}
+TEST(IPAddressTest, ConstructIPv4) {
+ EXPECT_EQ("127.0.0.1", IPAddress::IPv4Localhost().ToString());
+
+ IPAddress ipv4_ctor(192, 168, 1, 1);
+ EXPECT_EQ("192.168.1.1", ipv4_ctor.ToString());
+}
+
+TEST(IPAddressTest, ConstructIPv6) {
+ EXPECT_EQ("::1", IPAddress::IPv6Localhost().ToString());
+
+ IPAddress ipv6_ctor(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+ EXPECT_EQ("102:304:506:708:90a:b0c:d0e:f10", ipv6_ctor.ToString());
+}
+
TEST(IPAddressTest, IsIPVersion) {
uint8_t addr1[4] = {192, 168, 0, 1};
IPAddress ip_address1(addr1);
@@ -61,6 +75,37 @@ TEST(IPAddressTest, IsValid) {
EXPECT_TRUE(ip_address4.empty());
}
+TEST(IPAddressTest, IsZero) {
+ uint8_t address1[4] = {};
+ IPAddress zero_ipv4_address(address1);
+ EXPECT_TRUE(zero_ipv4_address.IsZero());
+
+ uint8_t address2[4] = {10};
+ IPAddress non_zero_ipv4_address(address2);
+ EXPECT_FALSE(non_zero_ipv4_address.IsZero());
+
+ uint8_t address3[16] = {};
+ IPAddress zero_ipv6_address(address3);
+ EXPECT_TRUE(zero_ipv6_address.IsZero());
+
+ uint8_t address4[16] = {10};
+ IPAddress non_zero_ipv6_address(address4);
+ EXPECT_FALSE(non_zero_ipv6_address.IsZero());
+
+ IPAddress empty_address;
+ EXPECT_FALSE(empty_address.IsZero());
+}
+
+TEST(IPAddressTest, AllZeros) {
+ EXPECT_TRUE(IPAddress::AllZeros(0).empty());
+
+ EXPECT_EQ(3u, IPAddress::AllZeros(3).size());
+ EXPECT_TRUE(IPAddress::AllZeros(3).IsZero());
+
+ EXPECT_EQ("0.0.0.0", IPAddress::IPv4AllZeros().ToString());
+ EXPECT_EQ("::", IPAddress::IPv6AllZeros().ToString());
+}
+
TEST(IPAddressTest, ToString) {
uint8_t addr1[4] = {0, 0, 0, 0};
IPAddress ip_address1(addr1);
@@ -73,57 +118,65 @@ TEST(IPAddressTest, ToString) {
uint8_t addr3[16] = {0xFE, 0xDC, 0xBA, 0x98};
IPAddress ip_address3(addr3);
EXPECT_EQ("fedc:ba98::", ip_address3.ToString());
+
+ // ToString() shouldn't crash on invalid addresses.
+ uint8_t addr4[2];
+ IPAddress ip_address4(addr4);
+ EXPECT_EQ("", ip_address4.ToString());
+
+ IPAddress ip_address5;
+ EXPECT_EQ("", ip_address5.ToString());
}
// Test that invalid IP literals fail to parse.
-TEST(IPAddressTest, FromIPLiteral_FailParse) {
+TEST(IPAddressTest, AssignFromIPLiteral_FailParse) {
IPAddress address;
- EXPECT_FALSE(IPAddress::FromIPLiteral("bad value", &address));
- EXPECT_FALSE(IPAddress::FromIPLiteral("bad:value", &address));
- EXPECT_FALSE(IPAddress::FromIPLiteral(std::string(), &address));
- EXPECT_FALSE(IPAddress::FromIPLiteral("192.168.0.1:30", &address));
- EXPECT_FALSE(IPAddress::FromIPLiteral(" 192.168.0.1 ", &address));
- EXPECT_FALSE(IPAddress::FromIPLiteral("[::1]", &address));
+ EXPECT_FALSE(address.AssignFromIPLiteral("bad value"));
+ EXPECT_FALSE(address.AssignFromIPLiteral("bad:value"));
+ EXPECT_FALSE(address.AssignFromIPLiteral(std::string()));
+ EXPECT_FALSE(address.AssignFromIPLiteral("192.168.0.1:30"));
+ EXPECT_FALSE(address.AssignFromIPLiteral(" 192.168.0.1 "));
+ EXPECT_FALSE(address.AssignFromIPLiteral("[::1]"));
}
// Test parsing an IPv4 literal.
-TEST(IPAddressTest, FromIPLiteral_IPv4) {
+TEST(IPAddressTest, AssignFromIPLiteral_IPv4) {
IPAddress address;
- EXPECT_TRUE(IPAddress::FromIPLiteral("192.168.0.1", &address));
+ EXPECT_TRUE(address.AssignFromIPLiteral("192.168.0.1"));
EXPECT_EQ("192,168,0,1", DumpIPAddress(address));
EXPECT_EQ("192.168.0.1", address.ToString());
}
// Test parsing an IPv6 literal.
-TEST(IPAddressTest, FromIPLiteral_IPv6) {
+TEST(IPAddressTest, AssignFromIPLiteral_IPv6) {
IPAddress address;
- EXPECT_TRUE(IPAddress::FromIPLiteral("1:abcd::3:4:ff", &address));
+ EXPECT_TRUE(address.AssignFromIPLiteral("1:abcd::3:4:ff"));
EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPAddress(address));
EXPECT_EQ("1:abcd::3:4:ff", address.ToString());
}
-TEST(IPAddressTest, IsIPv4Mapped) {
+TEST(IPAddressTest, IsIPv4MappedIPv6) {
IPAddress ipv4_address;
- EXPECT_TRUE(IPAddress::FromIPLiteral("192.168.0.1", &ipv4_address));
- EXPECT_FALSE(ipv4_address.IsIPv4Mapped());
+ EXPECT_TRUE(ipv4_address.AssignFromIPLiteral("192.168.0.1"));
+ EXPECT_FALSE(ipv4_address.IsIPv4MappedIPv6());
IPAddress ipv6_address;
- EXPECT_TRUE(IPAddress::FromIPLiteral("::1", &ipv4_address));
- EXPECT_FALSE(ipv6_address.IsIPv4Mapped());
+ EXPECT_TRUE(ipv6_address.AssignFromIPLiteral("::1"));
+ EXPECT_FALSE(ipv6_address.IsIPv4MappedIPv6());
IPAddress ipv4mapped_address;
- EXPECT_TRUE(IPAddress::FromIPLiteral("::ffff:0101:1", &ipv4mapped_address));
- EXPECT_TRUE(ipv4mapped_address.IsIPv4Mapped());
+ EXPECT_TRUE(ipv4mapped_address.AssignFromIPLiteral("::ffff:0101:1"));
+ EXPECT_TRUE(ipv4mapped_address.IsIPv4MappedIPv6());
}
TEST(IPAddressTest, IsEqual) {
IPAddress ip_address1;
- EXPECT_TRUE(IPAddress::FromIPLiteral("127.0.0.1", &ip_address1));
+ EXPECT_TRUE(ip_address1.AssignFromIPLiteral("127.0.0.1"));
IPAddress ip_address2;
- EXPECT_TRUE(IPAddress::FromIPLiteral("2001:db8:0::42", &ip_address2));
+ EXPECT_TRUE(ip_address2.AssignFromIPLiteral("2001:db8:0::42"));
IPAddress ip_address3;
- EXPECT_TRUE(IPAddress::FromIPLiteral("127.0.0.1", &ip_address3));
+ EXPECT_TRUE(ip_address3.AssignFromIPLiteral("127.0.0.1"));
EXPECT_FALSE(ip_address1 == ip_address2);
EXPECT_TRUE(ip_address1 == ip_address3);
@@ -132,19 +185,185 @@ TEST(IPAddressTest, IsEqual) {
TEST(IPAddressTest, LessThan) {
// IPv4 vs IPv6
IPAddress ip_address1;
- EXPECT_TRUE(IPAddress::FromIPLiteral("127.0.0.1", &ip_address1));
+ EXPECT_TRUE(ip_address1.AssignFromIPLiteral("127.0.0.1"));
IPAddress ip_address2;
- EXPECT_TRUE(IPAddress::FromIPLiteral("2001:db8:0::42", &ip_address2));
+ EXPECT_TRUE(ip_address2.AssignFromIPLiteral("2001:db8:0::42"));
EXPECT_TRUE(ip_address1 < ip_address2);
EXPECT_FALSE(ip_address2 < ip_address1);
// Compare equivalent addresses.
IPAddress ip_address3;
- EXPECT_TRUE(IPAddress::FromIPLiteral("127.0.0.1", &ip_address3));
+ EXPECT_TRUE(ip_address3.AssignFromIPLiteral("127.0.0.1"));
EXPECT_FALSE(ip_address1 < ip_address3);
EXPECT_FALSE(ip_address3 < ip_address1);
}
+TEST(IPAddressTest, IPAddressToStringWithPort) {
+ IPAddress address1;
+ EXPECT_TRUE(address1.AssignFromIPLiteral("0.0.0.0"));
+ EXPECT_EQ("0.0.0.0:3", IPAddressToStringWithPort(address1, 3));
+
+ IPAddress address2;
+ EXPECT_TRUE(address2.AssignFromIPLiteral("192.168.0.1"));
+ EXPECT_EQ("192.168.0.1:99", IPAddressToStringWithPort(address2, 99));
+
+ IPAddress address3;
+ EXPECT_TRUE(address3.AssignFromIPLiteral("fedc:ba98::"));
+ EXPECT_EQ("[fedc:ba98::]:8080", IPAddressToStringWithPort(address3, 8080));
+
+ // ToString() shouldn't crash on invalid addresses.
+ IPAddress address4;
+ EXPECT_EQ("", IPAddressToStringWithPort(address4, 8080));
+}
+
+TEST(IPAddressTest, IPAddressToPackedString) {
+ IPAddress ipv4_address;
+ EXPECT_TRUE(ipv4_address.AssignFromIPLiteral("4.31.198.44"));
+ std::string expected_ipv4_address("\x04\x1f\xc6\x2c", 4);
+ EXPECT_EQ(expected_ipv4_address, IPAddressToPackedString(ipv4_address));
+
+ IPAddress ipv6_address;
+ EXPECT_TRUE(ipv6_address.AssignFromIPLiteral("2001:0700:0300:1800::000f"));
+ std::string expected_ipv6_address(
+ "\x20\x01\x07\x00\x03\x00\x18\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x0f",
+ 16);
+ EXPECT_EQ(expected_ipv6_address, IPAddressToPackedString(ipv6_address));
+}
+
+TEST(IPAddressTest, ConvertIPv4ToIPv4MappedIPv6) {
+ IPAddress ipv4_address;
+ EXPECT_TRUE(ipv4_address.AssignFromIPLiteral("192.168.0.1"));
+
+ IPAddress ipv6_address = ConvertIPv4ToIPv4MappedIPv6(ipv4_address);
+
+ // ::ffff:192.168.0.1
+ EXPECT_EQ("::ffff:c0a8:1", ipv6_address.ToString());
+}
+
+TEST(IPAddressTest, ConvertIPv4MappedIPv6ToIPv4) {
+ IPAddress ipv4mapped_address;
+ EXPECT_TRUE(ipv4mapped_address.AssignFromIPLiteral("::ffff:c0a8:1"));
+
+ IPAddress expected;
+ EXPECT_TRUE(expected.AssignFromIPLiteral("192.168.0.1"));
+
+ IPAddress result = ConvertIPv4MappedIPv6ToIPv4(ipv4mapped_address);
+ EXPECT_EQ(expected, result);
+}
+
+// Test parsing invalid CIDR notation literals.
+TEST(IPAddressTest, ParseCIDRBlock_Invalid) {
+ const char* const bad_literals[] = {"foobar",
+ "",
+ "192.168.0.1",
+ "::1",
+ "/",
+ "/1",
+ "1",
+ "192.168.1.1/-1",
+ "192.168.1.1/33",
+ "::1/-3",
+ "a::3/129",
+ "::1/x",
+ "192.168.0.1//11",
+ "192.168.1.1/+1",
+ "192.168.1.1/ +1",
+ "192.168.1.1/"};
+
+ for (const auto& bad_literal : bad_literals) {
+ IPAddress ip_address;
+ size_t prefix_length_in_bits;
+
+ EXPECT_FALSE(
+ ParseCIDRBlock(bad_literal, &ip_address, &prefix_length_in_bits));
+ }
+}
+
+// Test parsing a valid CIDR notation literal.
+TEST(IPAddressTest, ParseCIDRBlock_Valid) {
+ IPAddress ip_address;
+ size_t prefix_length_in_bits;
+
+ EXPECT_TRUE(
+ ParseCIDRBlock("192.168.0.1/11", &ip_address, &prefix_length_in_bits));
+
+ EXPECT_EQ("192,168,0,1", DumpIPAddress(ip_address));
+ EXPECT_EQ(11u, prefix_length_in_bits);
+
+ EXPECT_TRUE(ParseCIDRBlock("::ffff:192.168.0.1/112", &ip_address,
+ &prefix_length_in_bits));
+
+ EXPECT_EQ("0,0,0,0,0,0,0,0,0,0,255,255,192,168,0,1",
+ DumpIPAddress(ip_address));
+ EXPECT_EQ(112u, prefix_length_in_bits);
+}
+
+TEST(IPAddressTest, ParseURLHostnameToAddress_FailParse) {
+ IPAddress address;
+ EXPECT_FALSE(ParseURLHostnameToAddress("bad value", &address));
+ EXPECT_FALSE(ParseURLHostnameToAddress("bad:value", &address));
+ EXPECT_FALSE(ParseURLHostnameToAddress(std::string(), &address));
+ EXPECT_FALSE(ParseURLHostnameToAddress("192.168.0.1:30", &address));
+ EXPECT_FALSE(ParseURLHostnameToAddress(" 192.168.0.1 ", &address));
+ EXPECT_FALSE(ParseURLHostnameToAddress("::1", &address));
+ EXPECT_FALSE(ParseURLHostnameToAddress("[192.169.0.1]", &address));
+}
+
+TEST(IPAddressTest, ParseURLHostnameToAddress_IPv4) {
+ IPAddress address;
+ EXPECT_TRUE(ParseURLHostnameToAddress("192.168.0.1", &address));
+ EXPECT_EQ("192,168,0,1", DumpIPAddress(address));
+ EXPECT_EQ("192.168.0.1", address.ToString());
+}
+
+TEST(IPAddressTest, ParseURLHostnameToAddress_IPv6) {
+ IPAddress address;
+ EXPECT_TRUE(ParseURLHostnameToAddress("[1:abcd::3:4:ff]", &address));
+ EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPAddress(address));
+ EXPECT_EQ("1:abcd::3:4:ff", address.ToString());
+}
+
+TEST(IPAddressTest, IPAddressStartsWith) {
+ IPAddress ipv4_address(192, 168, 10, 5);
+
+ uint8_t ipv4_prefix1[] = {192, 168, 10};
+ EXPECT_TRUE(IPAddressStartsWith(ipv4_address, ipv4_prefix1));
+
+ uint8_t ipv4_prefix3[] = {192, 168, 10, 5};
+ EXPECT_TRUE(IPAddressStartsWith(ipv4_address, ipv4_prefix3));
+
+ uint8_t ipv4_prefix2[] = {192, 168, 10, 10};
+ EXPECT_FALSE(IPAddressStartsWith(ipv4_address, ipv4_prefix2));
+
+ // Prefix is longer than the address.
+ uint8_t ipv4_prefix4[] = {192, 168, 10, 10, 0};
+ EXPECT_FALSE(IPAddressStartsWith(ipv4_address, ipv4_prefix4));
+
+ IPAddress ipv6_address;
+ EXPECT_TRUE(ipv6_address.AssignFromIPLiteral("2a00:1450:400c:c09::64"));
+
+ uint8_t ipv6_prefix1[] = {42, 0, 20, 80, 64, 12, 12, 9};
+ EXPECT_TRUE(IPAddressStartsWith(ipv6_address, ipv6_prefix1));
+
+ uint8_t ipv6_prefix2[] = {41, 0, 20, 80, 64, 12, 12, 9,
+ 0, 0, 0, 0, 0, 0, 100};
+ EXPECT_FALSE(IPAddressStartsWith(ipv6_address, ipv6_prefix2));
+
+ uint8_t ipv6_prefix3[] = {42, 0, 20, 80, 64, 12, 12, 9,
+ 0, 0, 0, 0, 0, 0, 0, 100};
+ EXPECT_TRUE(IPAddressStartsWith(ipv6_address, ipv6_prefix3));
+
+ uint8_t ipv6_prefix4[] = {42, 0, 20, 80, 64, 12, 12, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+ EXPECT_FALSE(IPAddressStartsWith(ipv6_address, ipv6_prefix4));
+
+ // Prefix is longer than the address.
+ uint8_t ipv6_prefix5[] = {42, 0, 20, 80, 64, 12, 12, 9, 0,
+ 0, 0, 0, 0, 0, 0, 0, 10};
+ EXPECT_FALSE(IPAddressStartsWith(ipv6_address, ipv6_prefix5));
+}
+
} // anonymous namespace
} // namespace net
diff --git a/chromium/net/base/ip_endpoint.cc b/chromium/net/base/ip_endpoint.cc
index c88ae2ec723..df0cb56947f 100644
--- a/chromium/net/base/ip_endpoint.cc
+++ b/chromium/net/base/ip_endpoint.cc
@@ -89,8 +89,7 @@ IPEndPoint::IPEndPoint(const IPAddressNumber& address, uint16_t port)
}
IPEndPoint::IPEndPoint(const IPAddress& address, uint16_t port)
- : address_(address.bytes()), port_(port) {
-}
+ : address_(address), port_(port) {}
IPEndPoint::IPEndPoint(const IPEndPoint& endpoint) {
address_ = endpoint.address_;
@@ -98,7 +97,7 @@ IPEndPoint::IPEndPoint(const IPEndPoint& endpoint) {
}
AddressFamily IPEndPoint::GetFamily() const {
- return GetAddressFamily(address_);
+ return GetAddressFamily(address_.bytes());
}
int IPEndPoint::GetSockAddrFamily() const {
@@ -126,7 +125,7 @@ bool IPEndPoint::ToSockAddr(struct sockaddr* address,
memset(addr, 0, sizeof(struct sockaddr_in));
addr->sin_family = AF_INET;
addr->sin_port = base::HostToNet16(port_);
- memcpy(&addr->sin_addr, &address_[0], kIPv4AddressSize);
+ memcpy(&addr->sin_addr, &address_.bytes()[0], kIPv4AddressSize);
break;
}
case kIPv6AddressSize: {
@@ -138,7 +137,7 @@ bool IPEndPoint::ToSockAddr(struct sockaddr* address,
memset(addr6, 0, sizeof(struct sockaddr_in6));
addr6->sin6_family = AF_INET6;
addr6->sin6_port = base::HostToNet16(port_);
- memcpy(&addr6->sin6_addr, &address_[0], kIPv6AddressSize);
+ memcpy(&addr6->sin6_addr, &address_.bytes()[0], kIPv6AddressSize);
break;
}
default:
@@ -159,17 +158,17 @@ bool IPEndPoint::FromSockAddr(const struct sockaddr* sock_addr,
return false;
}
- address_.assign(address, address + address_len);
+ address_ = net::IPAddress(address, address_len);
port_ = port;
return true;
}
std::string IPEndPoint::ToString() const {
- return IPAddressToStringWithPort(address_, port_);
+ return IPAddressToStringWithPort(address_.bytes(), port_);
}
std::string IPEndPoint::ToStringWithoutPort() const {
- return IPAddressToString(address_);
+ return address_.ToString();
}
bool IPEndPoint::operator<(const IPEndPoint& other) const {
diff --git a/chromium/net/base/ip_endpoint.h b/chromium/net/base/ip_endpoint.h
index 07ef3841d1e..a1c12296b3d 100644
--- a/chromium/net/base/ip_endpoint.h
+++ b/chromium/net/base/ip_endpoint.h
@@ -11,7 +11,7 @@
#include "base/compiler_specific.h"
#include "net/base/address_family.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "net/base/net_export.h"
#include "net/base/sys_addrinfo.h"
@@ -19,8 +19,6 @@ struct sockaddr;
namespace net {
-class IPAddress;
-
// An IPEndPoint represents the address of a transport endpoint:
// * IP address (either v4 or v6)
// * Port
@@ -33,7 +31,7 @@ class NET_EXPORT IPEndPoint {
IPEndPoint(const IPAddress& address, uint16_t port);
IPEndPoint(const IPEndPoint& endpoint);
- const IPAddressNumber& address() const { return address_; }
+ const IPAddress& address() const { return address_; }
uint16_t port() const { return port_; }
// Returns AddressFamily of the address.
@@ -59,18 +57,19 @@ class NET_EXPORT IPEndPoint {
bool FromSockAddr(const struct sockaddr* address, socklen_t address_length)
WARN_UNUSED_RESULT;
- // Returns value as a string (e.g. "127.0.0.1:80"). The IP address must be
- // valid.
+ // Returns value as a string (e.g. "127.0.0.1:80"). Returns the empty string
+ // when |address_| is invalid (the port will be ignored).
std::string ToString() const;
- // As above, but without port.
+ // As above, but without port. Returns the empty string when address_ is
+ // invalid.
std::string ToStringWithoutPort() const;
bool operator<(const IPEndPoint& that) const;
bool operator==(const IPEndPoint& that) const;
private:
- IPAddressNumber address_;
+ IPAddress address_;
uint16_t port_;
};
diff --git a/chromium/net/base/ip_endpoint_unittest.cc b/chromium/net/base/ip_endpoint_unittest.cc
index a2b647c8723..b3aa5b190de 100644
--- a/chromium/net/base/ip_endpoint_unittest.cc
+++ b/chromium/net/base/ip_endpoint_unittest.cc
@@ -54,7 +54,7 @@ struct TestData {
std::string host;
std::string host_normalized;
bool ipv6;
- IPAddressNumber ip_address;
+ IPAddress ip_address;
} tests[] = {
{ "127.0.00.1", "127.0.0.1", false},
{ "192.168.1.1", "192.168.1.1", false },
@@ -68,8 +68,8 @@ class IPEndPointTest : public PlatformTest {
void SetUp() override {
// This is where we populate the TestData.
for (int index = 0; index < test_count; ++index) {
- EXPECT_TRUE(ParseIPLiteralToNumber(tests[index].host,
- &tests[index].ip_address));
+ EXPECT_TRUE(
+ tests[index].ip_address.AssignFromIPLiteral(tests[index].host));
}
}
};
@@ -198,6 +198,12 @@ TEST_F(IPEndPointTest, ToString) {
EXPECT_EQ(tests[index].host_normalized + ":" + base::UintToString(port),
result);
}
+
+ // ToString() shouldn't crash on invalid addresses.
+ IPAddress invalid_address;
+ IPEndPoint invalid_endpoint(invalid_address, 8080);
+ EXPECT_EQ("", invalid_endpoint.ToString());
+ EXPECT_EQ("", invalid_endpoint.ToStringWithoutPort());
}
} // namespace
diff --git a/chromium/net/base/ip_pattern.cc b/chromium/net/base/ip_pattern.cc
index 0dbbe13d78d..6d58b5fb0fe 100644
--- a/chromium/net/base/ip_pattern.cc
+++ b/chromium/net/base/ip_pattern.cc
@@ -13,6 +13,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
+#include "net/base/ip_address.h"
namespace net {
@@ -57,11 +58,10 @@ IPPattern::IPPattern() : is_ipv4_(true) {}
IPPattern::~IPPattern() {}
-bool IPPattern::Match(const IPAddressNumber& address) const {
+bool IPPattern::Match(const IPAddress& address) const {
if (ip_mask_.empty())
return false;
- bool address_is_ipv4 = address.size() == kIPv4AddressSize;
- if (address_is_ipv4 != is_ipv4_)
+ if (address.IsIPv4() != is_ipv4_)
return false;
ComponentPatternList::const_iterator pattern_it(component_patterns_.begin());
@@ -70,9 +70,9 @@ bool IPPattern::Match(const IPAddressNumber& address) const {
// 8, so it is easier to count separately.
int address_index = 0;
for (size_t i = 0; i < ip_mask_.size(); ++i) {
- uint32_t value_to_test = address[address_index++];
+ uint32_t value_to_test = address.bytes()[address_index++];
if (!is_ipv4_) {
- value_to_test = (value_to_test << 8) + address[address_index++];
+ value_to_test = (value_to_test << 8) + address.bytes()[address_index++];
}
if (ip_mask_[i]) {
if (component_values_[fixed_value_index++] != value_to_test)
diff --git a/chromium/net/base/ip_pattern.h b/chromium/net/base/ip_pattern.h
index c30fd4c449a..92daa28f13a 100644
--- a/chromium/net/base/ip_pattern.h
+++ b/chromium/net/base/ip_pattern.h
@@ -13,11 +13,12 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
-#include "net/base/ip_address_number.h"
#include "net/base/net_export.h"
namespace net {
+class IPAddress;
+
// IPPatterns are used to match IP address resolutions for possible augmentation
// by a MappedIPResolver, which uses IPMappingRules.
class NET_EXPORT IPPattern {
@@ -30,7 +31,7 @@ class NET_EXPORT IPPattern {
bool ParsePattern(const std::string& ip_pattern);
// Test to see if the current pattern in |this| matches the given |address|
// and return true if it matches.
- bool Match(const IPAddressNumber& address) const;
+ bool Match(const IPAddress& address) const;
bool is_ipv4() const { return is_ipv4_; }
diff --git a/chromium/net/base/ip_pattern_unittest.cc b/chromium/net/base/ip_pattern_unittest.cc
index feec18dd505..7141e7f6620 100644
--- a/chromium/net/base/ip_pattern_unittest.cc
+++ b/chromium/net/base/ip_pattern_unittest.cc
@@ -4,7 +4,7 @@
#include "net/base/ip_pattern.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -17,17 +17,17 @@ bool IsValidPattern(const std::string& pattern_text) {
}
bool CheckForMatch(const IPPattern& pattern, const std::string& address_text) {
- IPAddressNumber address;
- EXPECT_TRUE(ParseIPLiteralToNumber(address_text, &address));
+ IPAddress address;
+ EXPECT_TRUE(address.AssignFromIPLiteral(address_text));
return pattern.Match(address);
}
TEST(IPPatternTest, EmptyPattern) {
IPPattern pattern;
- IPAddressNumber ipv4_address1;
- EXPECT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &ipv4_address1));
- IPAddressNumber ipv6_address1;
- EXPECT_TRUE(ParseIPLiteralToNumber("1:2:3:4:5:6:7:8", &ipv6_address1));
+ IPAddress ipv4_address1;
+ EXPECT_TRUE(ipv4_address1.AssignFromIPLiteral("1.2.3.4"));
+ IPAddress ipv6_address1;
+ EXPECT_TRUE(ipv6_address1.AssignFromIPLiteral("1:2:3:4:5:6:7:8"));
EXPECT_FALSE(pattern.Match(ipv4_address1));
EXPECT_FALSE(pattern.Match(ipv6_address1));
diff --git a/chromium/net/base/keygen_handler_mac.cc b/chromium/net/base/keygen_handler_mac.cc
index 63ea84751aa..13814fea820 100644
--- a/chromium/net/base/keygen_handler_mac.cc
+++ b/chromium/net/base/keygen_handler_mac.cc
@@ -18,6 +18,11 @@
#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[];
@@ -148,10 +153,15 @@ std::string KeygenHandler::GenKeyAndSignChallenge() {
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 =
@@ -175,6 +185,8 @@ std::string KeygenHandler::GenKeyAndSignChallenge() {
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>
@@ -323,3 +335,5 @@ static OSStatus SignData(CSSM_DATA data,
}
} // namespace net
+
+#pragma clang diagnostic pop // "-Wdeprecated-declarations"
diff --git a/chromium/net/base/keygen_handler_openssl.cc b/chromium/net/base/keygen_handler_openssl.cc
index bc34012c1e8..f72ca0e0eeb 100644
--- a/chromium/net/base/keygen_handler_openssl.cc
+++ b/chromium/net/base/keygen_handler_openssl.cc
@@ -4,11 +4,18 @@
#include "net/base/keygen_handler.h"
+#include <openssl/bytestring.h>
+#include <openssl/digest.h>
+#include <openssl/evp.h>
#include <openssl/mem.h>
-#include <openssl/ssl.h>
+#include <stdint.h>
+#include "base/base64.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "crypto/auto_cbb.h"
#include "crypto/openssl_util.h"
#include "crypto/rsa_private_key.h"
#include "crypto/scoped_openssl_types.h"
@@ -24,21 +31,94 @@ std::string KeygenHandler::GenKeyAndSignChallenge() {
if (stores_key_)
OpenSSLPrivateKeyStore::StoreKeyPair(url_, pkey);
- crypto::ScopedOpenSSL<NETSCAPE_SPKI, NETSCAPE_SPKI_free> spki(
- NETSCAPE_SPKI_new());
- ASN1_STRING_set(spki.get()->spkac->challenge,
- challenge_.data(), challenge_.size());
- NETSCAPE_SPKI_set_pubkey(spki.get(), pkey);
- // Using MD5 as this is what is required in HTML5, even though the SPKI
- // structure does allow the use of a SHA-1 signature.
- NETSCAPE_SPKI_sign(spki.get(), pkey, EVP_md5());
- char* spkistr = NETSCAPE_SPKI_b64_encode(spki.get());
+ // 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.
- std::string result(spkistr);
- OPENSSL_free(spkistr);
+ // 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.
+ crypto::AutoCBB 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.
+ crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
+ 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
index c1b5fe44e00..b045ababacd 100644
--- a/chromium/net/base/keygen_handler_unittest.cc
+++ b/chromium/net/base/keygen_handler_unittest.cc
@@ -4,6 +4,10 @@
#include "net/base/keygen_handler.h"
+#include <openssl/bytestring.h>
+#include <openssl/evp.h>
+#include <stdint.h>
+
#include <string>
#include <utility>
@@ -11,10 +15,12 @@
#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 "crypto/scoped_openssl_types.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(USE_NSS_CERTS)
@@ -48,14 +54,16 @@ class StubCryptoModuleDelegate : public crypto::NSSCryptoModuleDelegate {
};
#endif
+const char kChallenge[] = "some challenge";
+
class KeygenHandlerTest : public ::testing::Test {
public:
KeygenHandlerTest() {}
~KeygenHandlerTest() override {}
scoped_ptr<KeygenHandler> CreateKeygenHandler() {
- scoped_ptr<KeygenHandler> handler(new KeygenHandler(
- 768, "some challenge", GURL("http://www.example.com")));
+ scoped_ptr<KeygenHandler> handler(
+ new KeygenHandler(768, kChallenge, GURL("http://www.example.com")));
#if defined(USE_NSS_CERTS)
handler->set_crypto_module_delegate(
scoped_ptr<crypto::NSSCryptoModuleDelegate>(
@@ -71,40 +79,89 @@ class KeygenHandlerTest : public ::testing::Test {
#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) {
- ASSERT_GT(result.length(), 0U);
-
// Verify it's valid base64:
std::string spkac;
ASSERT_TRUE(base::Base64Decode(result, &spkac));
- // In lieu of actually parsing and validating the DER data,
- // just check that it exists and has a reasonable length.
- // (It's almost always 590 bytes, but the DER encoding of the random key
- // and signature could sometimes be a few bytes different.)
- ASSERT_GE(spkac.length(), 200U);
- ASSERT_LE(spkac.length(), 300U);
-
- // NOTE:
- // The value of |result| can be validated by prefixing 'SPKAC=' to it
- // and piping it through
- // openssl spkac -verify
- // whose output should look like:
- // Netscape SPKI:
- // Public Key Algorithm: rsaEncryption
- // RSA Public Key: (2048 bit)
- // Modulus (2048 bit):
- // 00:b6:cc:14:c9:43:b5:2d:51:65:7e:11:8b:80:9e: .....
- // Exponent: 65537 (0x10001)
- // Challenge String: some challenge
- // Signature Algorithm: md5WithRSAEncryption
- // 92:f3:cc:ff:0b:d3:d0:4a:3a:4c:ba:ff:d6:38:7f:a5:4b:b5: .....
- // Signature OK
+
+ // Parse the following structure:
//
- // The value of |spkac| can be ASN.1-parsed with:
- // openssl asn1parse -inform DER
+ // 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));
+ crypto::ScopedEVP_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.
+ crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
+ 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) {
@@ -112,7 +169,7 @@ TEST_F(KeygenHandlerTest, SmokeTest) {
handler->set_stores_key(false); // Don't leave the key-pair behind
std::string result = handler->GenKeyAndSignChallenge();
VLOG(1) << "KeygenHandler produced: " << result;
- AssertValidSignedPublicKeyAndChallenge(result, "some challenge");
+ AssertValidSignedPublicKeyAndChallenge(result, kChallenge);
}
void ConcurrencyTestCallback(const std::string& challenge,
diff --git a/chromium/net/base/keygen_handler_win.cc b/chromium/net/base/keygen_handler_win.cc
index d7eacd852db..f88e7e12579 100644
--- a/chromium/net/base/keygen_handler_win.cc
+++ b/chromium/net/base/keygen_handler_win.cc
@@ -20,9 +20,6 @@
#include "crypto/scoped_capi_types.h"
#include "crypto/wincrypt_shim.h"
-#pragma comment(lib, "crypt32.lib")
-#pragma comment(lib, "rpcrt4.lib")
-
namespace net {
// Assigns the contents of a CERT_PUBLIC_KEY_INFO structure for the signing
diff --git a/chromium/net/base/layered_network_delegate.cc b/chromium/net/base/layered_network_delegate.cc
index 9fe37196ccd..d97496205f9 100644
--- a/chromium/net/base/layered_network_delegate.cc
+++ b/chromium/net/base/layered_network_delegate.cc
@@ -30,33 +30,6 @@ void LayeredNetworkDelegate::OnBeforeURLRequestInternal(
GURL* new_url) {
}
-void LayeredNetworkDelegate::OnResolveProxy(const GURL& url,
- int load_flags,
- const ProxyService& proxy_service,
- ProxyInfo* result) {
- OnResolveProxyInternal(url, load_flags, proxy_service, result);
- nested_network_delegate_->NotifyResolveProxy(url, load_flags, proxy_service,
- result);
-}
-
-void LayeredNetworkDelegate::OnResolveProxyInternal(
- const GURL& url,
- int load_flags,
- const ProxyService& proxy_service,
- ProxyInfo* result) {
-}
-
-void LayeredNetworkDelegate::OnProxyFallback(const ProxyServer& bad_proxy,
- int net_error) {
- OnProxyFallbackInternal(bad_proxy, net_error);
- nested_network_delegate_->NotifyProxyFallback(bad_proxy, net_error);
-}
-
-void LayeredNetworkDelegate::OnProxyFallbackInternal(
- const ProxyServer& bad_proxy,
- int net_error) {
-}
-
int LayeredNetworkDelegate::OnBeforeSendHeaders(
URLRequest* request,
const CompletionCallback& callback,
diff --git a/chromium/net/base/layered_network_delegate.h b/chromium/net/base/layered_network_delegate.h
index 9f0928e7d1b..577f4b70b9a 100644
--- a/chromium/net/base/layered_network_delegate.h
+++ b/chromium/net/base/layered_network_delegate.h
@@ -25,8 +25,6 @@ class CookieOptions;
class HttpRequestHeaders;
class HttpResponseHeaders;
class ProxyInfo;
-class ProxyServer;
-class ProxyService;
class URLRequest;
// WrappingNetworkDelegate takes a |network_delegate| and extends it. When
@@ -43,11 +41,6 @@ class NET_EXPORT LayeredNetworkDelegate : public NetworkDelegate {
int OnBeforeURLRequest(URLRequest* request,
const CompletionCallback& callback,
GURL* new_url) final;
- void OnResolveProxy(const GURL& url,
- int load_flags,
- const ProxyService& proxy_service,
- ProxyInfo* result) final;
- void OnProxyFallback(const ProxyServer& bad_proxy, int net_error) final;
int OnBeforeSendHeaders(URLRequest* request,
const CompletionCallback& callback,
HttpRequestHeaders* headers) final;
@@ -95,14 +88,6 @@ class NET_EXPORT LayeredNetworkDelegate : public NetworkDelegate {
const CompletionCallback& callback,
GURL* new_url);
- virtual void OnResolveProxyInternal(const GURL& url,
- int load_flags,
- const ProxyService& proxy_service,
- ProxyInfo* result);
-
- virtual void OnProxyFallbackInternal(const ProxyServer& bad_proxy,
- int net_error);
-
virtual void OnBeforeSendHeadersInternal(URLRequest* request,
const CompletionCallback& callback,
HttpRequestHeaders* headers);
diff --git a/chromium/net/base/layered_network_delegate_unittest.cc b/chromium/net/base/layered_network_delegate_unittest.cc
index 6ca77a5015d..5b9e6107dbf 100644
--- a/chromium/net/base/layered_network_delegate_unittest.cc
+++ b/chromium/net/base/layered_network_delegate_unittest.cc
@@ -20,7 +20,6 @@
#include "net/http/http_response_headers.h"
#include "net/proxy/proxy_config_service.h"
#include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_service.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -46,17 +45,6 @@ class TestNetworkDelegateImpl : public NetworkDelegateImpl {
return OK;
}
- void OnResolveProxy(const GURL& url,
- int load_flags,
- const ProxyService& proxy_service,
- ProxyInfo* result) override {
- IncrementAndCompareCounter("on_resolve_proxy_count");
- }
-
- void OnProxyFallback(const ProxyServer& bad_proxy, int net_error) override {
- IncrementAndCompareCounter("on_proxy_fallback_count");
- }
-
int OnBeforeSendHeaders(URLRequest* request,
const CompletionCallback& callback,
HttpRequestHeaders* headers) override {
@@ -191,13 +179,9 @@ class TestLayeredNetworkDelegate : public LayeredNetworkDelegate {
scoped_refptr<HttpResponseHeaders> response_headers(
new HttpResponseHeaders(""));
TestCompletionCallback completion_callback;
- scoped_ptr<ProxyService> proxy_service(ProxyService::CreateDirect());
- scoped_ptr<ProxyInfo> proxy_info(new ProxyInfo());
EXPECT_EQ(OK, OnBeforeURLRequest(request.get(),
completion_callback.callback(), NULL));
- OnResolveProxy(GURL(), 0, *proxy_service, proxy_info.get());
- OnProxyFallback(ProxyServer(), 0);
EXPECT_EQ(OK, OnBeforeSendHeaders(NULL, completion_callback.callback(),
request_headers.get()));
OnBeforeSendProxyHeaders(NULL, ProxyInfo(), request_headers.get());
@@ -229,20 +213,6 @@ class TestLayeredNetworkDelegate : public LayeredNetworkDelegate {
EXPECT_EQ(1, (*counters_)["on_before_url_request_count"]);
}
- void OnResolveProxyInternal(const GURL& url,
- int load_flags,
- const ProxyService& proxy_service,
- ProxyInfo* result) override {
- ++(*counters_)["on_resolve_proxy_count"];
- EXPECT_EQ(1, (*counters_)["on_resolve_proxy_count"]);
- }
-
- void OnProxyFallbackInternal(const ProxyServer& bad_proxy,
- int net_error) override {
- ++(*counters_)["on_proxy_fallback_count"];
- EXPECT_EQ(1, (*counters_)["on_proxy_fallback_count"]);
- }
-
void OnBeforeSendHeadersInternal(URLRequest* request,
const CompletionCallback& callback,
HttpRequestHeaders* headers) override {
diff --git a/chromium/net/base/linked_hash_map.h b/chromium/net/base/linked_hash_map.h
index b86654bdeeb..e3d12d63413 100644
--- a/chromium/net/base/linked_hash_map.h
+++ b/chromium/net/base/linked_hash_map.h
@@ -18,9 +18,9 @@
#include <stddef.h>
#include <list>
+#include <unordered_map>
#include <utility>
-#include "base/containers/hash_tables.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -30,11 +30,11 @@
//
// We also keep a map<Key, list::iterator> for find. Since std::list is a
// doubly-linked list, the iterators should remain stable.
-template<class Key, class Value>
+template <class Key, class Value, class Hash = std::hash<Key>>
class linked_hash_map {
private:
typedef std::list<std::pair<Key, Value> > ListType;
- typedef base::hash_map<Key, typename ListType::iterator> MapType;
+ typedef std::unordered_map<Key, typename ListType::iterator, Hash> MapType;
public:
typedef typename ListType::iterator iterator;
diff --git a/chromium/net/base/load_flags_list.h b/chromium/net/base/load_flags_list.h
index 6ace1323254..28cbcba8db6 100644
--- a/chromium/net/base/load_flags_list.h
+++ b/chromium/net/base/load_flags_list.h
@@ -80,3 +80,7 @@ LOAD_FLAG(DO_NOT_USE_EMBEDDED_IDENTITY, 1 << 16)
// by the "Cache-Control: stale-while-revalidate" directive and is able to issue
// an async revalidation to update the cache.
LOAD_FLAG(SUPPORT_ASYNC_REVALIDATION, 1 << 17)
+
+// Indicates that this request is not to be migrated to a new network when QUIC
+// connection migration is enabled.
+LOAD_FLAG(DISABLE_CONNECTION_MIGRATION, 1 << 18)
diff --git a/chromium/net/base/load_timing_info.cc b/chromium/net/base/load_timing_info.cc
index ce4df2df045..309e7b33b51 100644
--- a/chromium/net/base/load_timing_info.cc
+++ b/chromium/net/base/load_timing_info.cc
@@ -16,6 +16,8 @@ LoadTimingInfo::LoadTimingInfo() : socket_reused(false),
socket_log_id(NetLog::Source::kInvalidId) {
}
+LoadTimingInfo::LoadTimingInfo(const LoadTimingInfo& other) = default;
+
LoadTimingInfo::~LoadTimingInfo() {}
} // namespace net
diff --git a/chromium/net/base/load_timing_info.h b/chromium/net/base/load_timing_info.h
index 22a59082f54..8ee5a22ec14 100644
--- a/chromium/net/base/load_timing_info.h
+++ b/chromium/net/base/load_timing_info.h
@@ -93,6 +93,7 @@ struct NET_EXPORT LoadTimingInfo {
};
LoadTimingInfo();
+ LoadTimingInfo(const LoadTimingInfo& other);
~LoadTimingInfo();
// True if the socket was reused. When true, DNS, connect, and SSL times
diff --git a/chromium/net/base/mime_sniffer_fuzzer.cc b/chromium/net/base/mime_sniffer_fuzzer.cc
new file mode 100644
index 00000000000..fec7feaf677
--- /dev/null
+++ b/chromium/net/base/mime_sniffer_fuzzer.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/base/mime_sniffer.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "url/gurl.h"
+
+namespace {
+
+// Finds the line break in |input|, removes every thing up to and including the
+// line break from |input|, and returns everything up to the line break as a
+// string.
+std::string GetNextArgument(base::StringPiece* input) {
+ base::StringPiece::size_type argument_end = input->find('\n');
+ if (argument_end == base::StringPiece::npos)
+ argument_end = input->size();
+ base::StringPiece argument = input->substr(0, argument_end);
+ *input = input->substr(argument_end + 1);
+ return argument.as_string();
+}
+
+} // namespace
+
+// Fuzzer for the two main mime sniffing functions:
+// SniffMimeType and SniffMimeTypeFromLocalData.
+//
+// Breaks |data| up into 3 substrings: URL, MIME type hint, and content, and
+// passes them to the MIME sniffing functions (SniffMimeTypeFromLocalData
+// does not take all 3 arguments). The first two substrings are each on their
+// own line, and content is everything after them. Since neither URLs nor
+// content-encoding headers can have line breaks, this doesn't reduce coverage.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ base::StringPiece input(reinterpret_cast<const char*>(data), size);
+ GURL url(GetNextArgument(&input));
+
+ std::string mime_type_hint = GetNextArgument(&input);
+
+ std::string result;
+ net::SniffMimeType(input.data(), input.length(), url, mime_type_hint,
+ &result);
+
+ net::SniffMimeTypeFromLocalData(input.data(), input.length(), &result);
+
+ return 0;
+}
diff --git a/chromium/net/base/net_error_details.h b/chromium/net/base/net_error_details.h
index 940394efbee..7bd5baad67d 100644
--- a/chromium/net/base/net_error_details.h
+++ b/chromium/net/base/net_error_details.h
@@ -5,6 +5,7 @@
#ifndef NET_BASE_NET_ERROR_DETAILS_H_
#define NET_BASE_NET_ERROR_DETAILS_H_
+#include "net/http/http_response_info.h"
#include "net/quic/quic_protocol.h"
namespace net {
@@ -13,16 +14,28 @@ namespace net {
// net stack.
struct NET_EXPORT NetErrorDetails {
NetErrorDetails()
- : quic_broken(false), quic_connection_error(QUIC_NO_ERROR) {}
+ : quic_broken(false),
+ quic_connection_error(QUIC_NO_ERROR),
+ connection_info(HttpResponseInfo::CONNECTION_INFO_UNKNOWN),
+ quic_port_migration_detected(false) {}
NetErrorDetails(bool quic_broken, QuicErrorCode quic_connection_error)
: quic_broken(quic_broken),
- quic_connection_error(quic_connection_error) {}
+ quic_connection_error(quic_connection_error),
+ connection_info(HttpResponseInfo::CONNECTION_INFO_UNKNOWN),
+ quic_port_migration_detected(false) {}
// True if all QUIC alternative services are marked broken for the origin.
bool quic_broken;
// QUIC granular error info.
QuicErrorCode quic_connection_error;
+ // Early prediction of the connection type that this request attempts to use.
+ // Will be discarded by upper layers if the connection type can be fetched
+ // from response header from the server.
+ HttpResponseInfo::ConnectionInfo connection_info;
+ // True if receives a GoAway frame from the server due to connection
+ // migration with port change.
+ bool quic_port_migration_detected;
};
} // namespace net
diff --git a/chromium/net/base/net_error_list.h b/chromium/net/base/net_error_list.h
index 296024b2b94..be1b712cc7e 100644
--- a/chromium/net/base/net_error_list.h
+++ b/chromium/net/base/net_error_list.h
@@ -363,6 +363,9 @@ NET_ERROR(CT_STH_INCOMPLETE, -169)
// internally by the network stack.
NET_ERROR(UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH, -170)
+// Certificate Transparency: Failed to parse the received consistency proof.
+NET_ERROR(CT_CONSISTENCY_PROOF_PARSING_FAILED, -171)
+
// Certificate error codes
//
// The values of certificate error codes must be consecutive.
@@ -791,8 +794,7 @@ NET_ERROR(SELF_SIGNED_CERT_GENERATION_FAILED, -713)
// The certificate database changed in some way.
NET_ERROR(CERT_DATABASE_CHANGED, -714)
-// Failure to import Channel ID.
-NET_ERROR(CHANNEL_ID_IMPORT_FAILED, -715)
+// Error -715 was removed (CHANNEL_ID_IMPORT_FAILED)
// DNS error codes.
diff --git a/chromium/net/base/net_info_source_list.h b/chromium/net/base/net_info_source_list.h
index 7b3b65b42fa..d89cd60f2e4 100644
--- a/chromium/net/base/net_info_source_list.h
+++ b/chromium/net/base/net_info_source_list.h
@@ -17,6 +17,6 @@ NET_INFO_SOURCE(SOCKET_POOL, "socketPoolInfo", 1 << 3)
NET_INFO_SOURCE(QUIC, "quicInfo", 1 << 4)
NET_INFO_SOURCE(SPDY_SESSIONS, "spdySessionInfo", 1 << 5)
NET_INFO_SOURCE(SPDY_STATUS, "spdyStatus", 1 << 6)
-NET_INFO_SOURCE(SPDY_ALT_SVC_MAPPINGS, "spdyAlternateProtocolMappings", 1 << 7)
+NET_INFO_SOURCE(ALT_SVC_MAPPINGS, "altSvcMappings", 1 << 7)
NET_INFO_SOURCE(HTTP_CACHE, "httpCacheInfo", 1 << 8)
NET_INFO_SOURCE(SDCH, "sdchInfo", 1 << 9)
diff --git a/chromium/net/base/net_util.cc b/chromium/net/base/net_util.cc
deleted file mode 100644
index f89cc991b6d..00000000000
--- a/chromium/net/base/net_util.cc
+++ /dev/null
@@ -1,375 +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/net_util.h"
-
-#include <algorithm>
-#include <string>
-
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#include <iphlpapi.h>
-#include <winsock2.h>
-#pragma comment(lib, "iphlpapi.lib")
-#elif defined(OS_POSIX)
-#include <fcntl.h>
-#include <netdb.h>
-#include <unistd.h>
-#endif // defined(OS_POSIX)
-
-#include "base/logging.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 "net/base/address_list.h"
-#include "net/base/ip_address_number.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-#include "net/base/url_util.h"
-#include "url/gurl.h"
-#include "url/third_party/mozilla/url_parse.h"
-#include "url/url_canon.h"
-#include "url/url_canon_ip.h"
-
-#if defined(OS_WIN)
-#include "net/base/winsock_init.h"
-#endif
-
-namespace net {
-
-namespace {
-
-std::string NormalizeHostname(base::StringPiece host) {
- std::string result = base::ToLowerASCII(host);
- if (!result.empty() && *result.rbegin() == '.')
- result.resize(result.size() - 1);
- return result;
-}
-
-bool IsNormalizedLocalhostTLD(const std::string& host) {
- return base::EndsWith(host, ".localhost", base::CompareCase::SENSITIVE);
-}
-
-// |host| should be normalized.
-bool IsLocalHostname(const std::string& host) {
- return host == "localhost" || host == "localhost.localdomain" ||
- IsNormalizedLocalhostTLD(host);
-}
-
-// |host| should be normalized.
-bool IsLocal6Hostname(const std::string& host) {
- return host == "localhost6" || host == "localhost6.localdomain6";
-}
-
-} // namespace
-
-std::string CanonicalizeHost(const std::string& host,
- url::CanonHostInfo* host_info) {
- // Try to canonicalize the host.
- const url::Component raw_host_component(0, static_cast<int>(host.length()));
- std::string canon_host;
- url::StdStringCanonOutput canon_host_output(&canon_host);
- url::CanonicalizeHostVerbose(host.c_str(), raw_host_component,
- &canon_host_output, host_info);
-
- if (host_info->out_host.is_nonempty() &&
- host_info->family != url::CanonHostInfo::BROKEN) {
- // Success! Assert that there's no extra garbage.
- canon_host_output.Complete();
- DCHECK_EQ(host_info->out_host.len, static_cast<int>(canon_host.length()));
- } else {
- // Empty host, or canonicalization failed. We'll return empty.
- canon_host.clear();
- }
-
- return canon_host;
-}
-
-inline bool IsHostCharAlphanumeric(char c) {
- // We can just check lowercase because uppercase characters have already been
- // normalized.
- return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'));
-}
-
-bool IsCanonicalizedHostCompliant(const std::string& host) {
- if (host.empty())
- return false;
-
- bool in_component = false;
- bool most_recent_component_started_alphanumeric = false;
-
- for (std::string::const_iterator i(host.begin()); i != host.end(); ++i) {
- const char c = *i;
- if (!in_component) {
- most_recent_component_started_alphanumeric = IsHostCharAlphanumeric(c);
- if (!most_recent_component_started_alphanumeric && (c != '-') &&
- (c != '_')) {
- return false;
- }
- in_component = true;
- } else if (c == '.') {
- in_component = false;
- } else if (!IsHostCharAlphanumeric(c) && (c != '-') && (c != '_')) {
- return false;
- }
- }
-
- return most_recent_component_started_alphanumeric;
-}
-
-bool ParseHostAndPort(std::string::const_iterator host_and_port_begin,
- std::string::const_iterator host_and_port_end,
- std::string* host,
- int* port) {
- if (host_and_port_begin >= host_and_port_end)
- return false;
-
- // When using url, we use char*.
- const char* auth_begin = &(*host_and_port_begin);
- int auth_len = host_and_port_end - host_and_port_begin;
-
- url::Component auth_component(0, auth_len);
- url::Component username_component;
- url::Component password_component;
- url::Component hostname_component;
- url::Component port_component;
-
- url::ParseAuthority(auth_begin, auth_component, &username_component,
- &password_component, &hostname_component, &port_component);
-
- // There shouldn't be a username/password.
- if (username_component.is_valid() || password_component.is_valid())
- return false;
-
- if (!hostname_component.is_nonempty())
- return false; // Failed parsing.
-
- int parsed_port_number = -1;
- if (port_component.is_nonempty()) {
- parsed_port_number = url::ParsePort(auth_begin, port_component);
-
- // If parsing failed, port_number will be either PORT_INVALID or
- // PORT_UNSPECIFIED, both of which are negative.
- if (parsed_port_number < 0)
- return false; // Failed parsing the port number.
- }
-
- if (port_component.len == 0)
- return false; // Reject inputs like "foo:"
-
- unsigned char tmp_ipv6_addr[16];
-
- // If the hostname starts with a bracket, it is either an IPv6 literal or
- // invalid. If it is an IPv6 literal then strip the brackets.
- if (hostname_component.len > 0 &&
- auth_begin[hostname_component.begin] == '[') {
- if (auth_begin[hostname_component.end() - 1] == ']' &&
- url::IPv6AddressToNumber(
- auth_begin, hostname_component, tmp_ipv6_addr)) {
- // Strip the brackets.
- hostname_component.begin++;
- hostname_component.len -= 2;
- } else {
- return false;
- }
- }
-
- // Pass results back to caller.
- host->assign(auth_begin + hostname_component.begin, hostname_component.len);
- *port = parsed_port_number;
-
- return true; // Success.
-}
-
-bool ParseHostAndPort(const std::string& host_and_port,
- std::string* host,
- int* port) {
- return ParseHostAndPort(
- host_and_port.begin(), host_and_port.end(), host, port);
-}
-
-std::string GetHostAndPort(const GURL& url) {
- // For IPv6 literals, GURL::host() already includes the brackets so it is
- // safe to just append a colon.
- return base::StringPrintf("%s:%d", url.host().c_str(),
- url.EffectiveIntPort());
-}
-
-std::string GetHostAndOptionalPort(const GURL& url) {
- // For IPv6 literals, GURL::host() already includes the brackets
- // so it is safe to just append a colon.
- if (url.has_port())
- return base::StringPrintf("%s:%s", url.host().c_str(), url.port().c_str());
- return url.host();
-}
-
-bool IsHostnameNonUnique(const std::string& hostname) {
- // CanonicalizeHost requires surrounding brackets to parse an IPv6 address.
- const std::string host_or_ip = hostname.find(':') != std::string::npos ?
- "[" + hostname + "]" : hostname;
- url::CanonHostInfo host_info;
- std::string canonical_name = CanonicalizeHost(host_or_ip, &host_info);
-
- // If canonicalization fails, then the input is truly malformed. However,
- // to avoid mis-reporting bad inputs as "non-unique", treat them as unique.
- if (canonical_name.empty())
- return false;
-
- // If |hostname| is an IP address, check to see if it's in an IANA-reserved
- // range.
- if (host_info.IsIPAddress()) {
- IPAddressNumber host_addr;
- if (!ParseIPLiteralToNumber(hostname.substr(host_info.out_host.begin,
- host_info.out_host.len),
- &host_addr)) {
- return false;
- }
- switch (host_info.family) {
- case url::CanonHostInfo::IPV4:
- case url::CanonHostInfo::IPV6:
- return IsIPAddressReserved(host_addr);
- case url::CanonHostInfo::NEUTRAL:
- case url::CanonHostInfo::BROKEN:
- return false;
- }
- }
-
- // Check for a registry controlled portion of |hostname|, ignoring private
- // registries, as they already chain to ICANN-administered registries,
- // and explicitly ignoring unknown registries.
- //
- // Note: This means that as new gTLDs are introduced on the Internet, they
- // will be treated as non-unique until the registry controlled domain list
- // is updated. However, because gTLDs are expected to provide significant
- // advance notice to deprecate older versions of this code, this an
- // acceptable tradeoff.
- return 0 == registry_controlled_domains::GetRegistryLength(
- canonical_name,
- registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
- registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
-}
-
-std::string GetHostName() {
-#if defined(OS_NACL)
- NOTIMPLEMENTED();
- return std::string();
-#else // defined(OS_NACL)
-#if defined(OS_WIN)
- EnsureWinsockInit();
-#endif
-
- // Host names are limited to 255 bytes.
- char buffer[256];
- int result = gethostname(buffer, sizeof(buffer));
- if (result != 0) {
- DVLOG(1) << "gethostname() failed with " << result;
- buffer[0] = '\0';
- }
- return std::string(buffer);
-#endif // !defined(OS_NACL)
-}
-
-std::string GetHostOrSpecFromURL(const GURL& url) {
- return url.has_host() ? TrimEndingDot(url.host_piece()) : url.spec();
-}
-
-GURL SimplifyUrlForRequest(const GURL& url) {
- DCHECK(url.is_valid());
- GURL::Replacements replacements;
- replacements.ClearUsername();
- replacements.ClearPassword();
- replacements.ClearRef();
- return url.ReplaceComponents(replacements);
-}
-
-bool ResolveLocalHostname(base::StringPiece host,
- uint16_t port,
- AddressList* address_list) {
- static const unsigned char kLocalhostIPv4[] = {127, 0, 0, 1};
- static const unsigned char kLocalhostIPv6[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
-
- std::string normalized_host = NormalizeHostname(host);
-
- address_list->clear();
-
- bool is_local6 = IsLocal6Hostname(normalized_host);
- if (!is_local6 && !IsLocalHostname(normalized_host))
- return false;
-
- address_list->push_back(
- IPEndPoint(IPAddressNumber(kLocalhostIPv6,
- kLocalhostIPv6 + arraysize(kLocalhostIPv6)),
- port));
- if (!is_local6) {
- address_list->push_back(
- IPEndPoint(IPAddressNumber(kLocalhostIPv4,
- kLocalhostIPv4 + arraysize(kLocalhostIPv4)),
- port));
- }
-
- return true;
-}
-
-bool IsLocalhost(base::StringPiece host) {
- std::string normalized_host = NormalizeHostname(host);
- if (IsLocalHostname(normalized_host) || IsLocal6Hostname(normalized_host))
- return true;
-
- IPAddressNumber ip_number;
- if (ParseIPLiteralToNumber(host, &ip_number)) {
- size_t size = ip_number.size();
- switch (size) {
- case kIPv4AddressSize: {
- IPAddressNumber localhost_prefix;
- localhost_prefix.push_back(127);
- for (int i = 0; i < 3; ++i) {
- localhost_prefix.push_back(0);
- }
- return IPNumberMatchesPrefix(ip_number, localhost_prefix, 8);
- }
-
- case kIPv6AddressSize: {
- struct in6_addr sin6_addr;
- memcpy(&sin6_addr, &ip_number[0], kIPv6AddressSize);
- return !!IN6_IS_ADDR_LOOPBACK(&sin6_addr);
- }
-
- default:
- NOTREACHED();
- }
- }
-
- return false;
-}
-
-bool HasGoogleHost(const GURL& url) {
- static const char* kGoogleHostSuffixes[] = {
- ".google.com",
- ".youtube.com",
- ".gmail.com",
- ".doubleclick.net",
- ".gstatic.com",
- ".googlevideo.com",
- ".googleusercontent.com",
- ".googlesyndication.com",
- ".google-analytics.com",
- ".googleadservices.com",
- ".googleapis.com",
- ".ytimg.com",
- };
- base::StringPiece host = url.host_piece();
- for (const char* suffix : kGoogleHostSuffixes) {
- // Here it's possible to get away with faster case-sensitive comparisons
- // because the list above is all lowercase, and a GURL's host name will
- // always be canonicalized to lowercase as well.
- if (base::EndsWith(host, suffix, base::CompareCase::SENSITIVE))
- return true;
- }
- return false;
-}
-
-} // namespace net
diff --git a/chromium/net/base/net_util.h b/chromium/net/base/net_util.h
deleted file mode 100644
index 1bf6510122c..00000000000
--- a/chromium/net/base/net_util.h
+++ /dev/null
@@ -1,110 +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_BASE_NET_UTIL_H_
-#define NET_BASE_NET_UTIL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
-
-class GURL;
-
-namespace url {
-struct CanonHostInfo;
-}
-
-namespace net {
-
-class AddressList;
-
-// Splits an input of the form <host>[":"<port>] into its consitituent parts.
-// Saves the result into |*host| and |*port|. If the input did not have
-// the optional port, sets |*port| to -1.
-// Returns true if the parsing was successful, false otherwise.
-// The returned host is NOT canonicalized, and may be invalid.
-//
-// IPv6 literals must be specified in a bracketed form, for instance:
-// [::1]:90 and [::1]
-//
-// The resultant |*host| in both cases will be "::1" (not bracketed).
-NET_EXPORT bool ParseHostAndPort(
- std::string::const_iterator host_and_port_begin,
- std::string::const_iterator host_and_port_end,
- std::string* host,
- int* port);
-NET_EXPORT bool ParseHostAndPort(
- const std::string& host_and_port,
- std::string* host,
- int* port);
-
-// Returns a host:port string for the given URL.
-NET_EXPORT std::string GetHostAndPort(const GURL& url);
-
-// Returns a host[:port] string for the given URL, where the port is omitted
-// if it is the default for the URL's scheme.
-NET_EXPORT std::string GetHostAndOptionalPort(const GURL& url);
-
-// Returns true if |hostname| contains a non-registerable or non-assignable
-// domain name (eg: a gTLD that has not been assigned by IANA) or an IP address
-// that falls in an IANA-reserved range.
-NET_EXPORT bool IsHostnameNonUnique(const std::string& hostname);
-
-// Returns the hostname of the current system. Returns empty string on failure.
-NET_EXPORT std::string GetHostName();
-
-// Returns either the host from |url|, or, if the host is empty, the full spec.
-NET_EXPORT std::string GetHostOrSpecFromURL(const GURL& url);
-
-// Canonicalizes |host| and returns it. Also fills |host_info| with
-// IP address information. |host_info| must not be NULL.
-NET_EXPORT std::string CanonicalizeHost(const std::string& host,
- url::CanonHostInfo* host_info);
-
-// Returns true if |host| is not an IP address and is compliant with a set of
-// rules based on RFC 1738 and tweaked to be compatible with the real world.
-// The rules are:
-// * One or more components separated by '.'
-// * Each component contains only alphanumeric characters and '-' or '_'
-// * The last component begins with an alphanumeric character
-// * Optional trailing dot after last component (means "treat as FQDN")
-//
-// NOTE: You should only pass in hosts that have been returned from
-// CanonicalizeHost(), or you may not get accurate results.
-NET_EXPORT bool IsCanonicalizedHostCompliant(const std::string& host);
-
-// Strip the portions of |url| that aren't core to the network request.
-// - user name / password
-// - reference section
-NET_EXPORT GURL SimplifyUrlForRequest(const GURL& url);
-
-// Resolves a local hostname (such as "localhost" or "localhost6") into
-// IP endpoints with the given port. Returns true if |host| is a local
-// hostname and false otherwise. Special IPv6 names (e.g. "localhost6")
-// will resolve to an IPv6 address only, whereas other names will
-// resolve to both IPv4 and IPv6.
-NET_EXPORT_PRIVATE bool ResolveLocalHostname(base::StringPiece host,
- uint16_t port,
- AddressList* address_list);
-
-// Returns true if |host| is one of the local hostnames
-// (e.g. "localhost") or IP addresses (IPv4 127.0.0.0/8 or IPv6 ::1).
-//
-// Note that this function does not check for IP addresses other than
-// the above, although other IP addresses may point to the local
-// machine.
-NET_EXPORT bool IsLocalhost(base::StringPiece host);
-
-// Returns true if the url's host is a Google server. This should only be used
-// for histograms and shouldn't be used to affect behavior.
-NET_EXPORT_PRIVATE bool HasGoogleHost(const GURL& url);
-
-} // namespace net
-
-#endif // NET_BASE_NET_UTIL_H_
diff --git a/chromium/net/base/net_util_unittest.cc b/chromium/net/base/net_util_unittest.cc
deleted file mode 100644
index b92244a74c6..00000000000
--- a/chromium/net/base/net_util_unittest.cc
+++ /dev/null
@@ -1,492 +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/net_util.h"
-
-#include <ostream>
-
-#include "base/format_macros.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "net/base/address_list.h"
-#include "net/base/ip_endpoint.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-#if !defined(OS_NACL) && !defined(OS_WIN)
-#include <net/if.h>
-#include <netinet/in.h>
-#if defined(OS_MACOSX)
-#include <ifaddrs.h>
-#if !defined(OS_IOS)
-#include <netinet/in_var.h>
-#endif // !OS_IOS
-#endif // OS_MACOSX
-#endif // !OS_NACL && !OS_WIN
-
-#if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_WIN)
-#include "net/base/address_tracker_linux.h"
-#endif // !OS_MACOSX && !OS_NACL && !OS_WIN
-
-namespace net {
-
-namespace {
-
-const unsigned char kLocalhostIPv4[] = {127, 0, 0, 1};
-const unsigned char kLocalhostIPv6[] =
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
-const uint16_t kLocalhostLookupPort = 80;
-
-bool HasEndpoint(const IPEndPoint& endpoint, const AddressList& addresses) {
- for (const auto& address : addresses) {
- if (endpoint == address)
- return true;
- }
- return false;
-}
-
-void TestBothLoopbackIPs(const std::string& host) {
- IPEndPoint localhost_ipv4(
- IPAddressNumber(kLocalhostIPv4,
- kLocalhostIPv4 + arraysize(kLocalhostIPv4)),
- kLocalhostLookupPort);
- IPEndPoint localhost_ipv6(
- IPAddressNumber(kLocalhostIPv6,
- kLocalhostIPv6 + arraysize(kLocalhostIPv6)),
- kLocalhostLookupPort);
-
- AddressList addresses;
- EXPECT_TRUE(ResolveLocalHostname(host, kLocalhostLookupPort, &addresses));
- EXPECT_EQ(2u, addresses.size());
- EXPECT_TRUE(HasEndpoint(localhost_ipv4, addresses));
- EXPECT_TRUE(HasEndpoint(localhost_ipv6, addresses));
-}
-
-void TestIPv6LoopbackOnly(const std::string& host) {
- IPEndPoint localhost_ipv6(
- IPAddressNumber(kLocalhostIPv6,
- kLocalhostIPv6 + arraysize(kLocalhostIPv6)),
- kLocalhostLookupPort);
-
- AddressList addresses;
- EXPECT_TRUE(ResolveLocalHostname(host, kLocalhostLookupPort, &addresses));
- EXPECT_EQ(1u, addresses.size());
- EXPECT_TRUE(HasEndpoint(localhost_ipv6, addresses));
-}
-
-} // anonymous namespace
-
-TEST(NetUtilTest, CompliantHost) {
- struct {
- const char* const host;
- bool expected_output;
- } compliant_host_cases[] = {
- {"", false},
- {"a", true},
- {"-", false},
- {"_", false},
- {".", false},
- {"9", true},
- {"9a", true},
- {"9_", true},
- {"a.", true},
- {"a.a", true},
- {"9.a", true},
- {"a.9", true},
- {"_9a", false},
- {"-9a", false},
- {"a.a9", true},
- {"_.9a", true},
- {"a.-a9", false},
- {"a+9a", false},
- {"-a.a9", true},
- {"a_.a9", true},
- {"1-.a-b", true},
- {"1_.a-b", true},
- {"1-2.a_b", true},
- {"a.b.c.d.e", true},
- {"1.2.3.4.5", true},
- {"1.2.3.4.5.", true},
- };
-
- for (size_t i = 0; i < arraysize(compliant_host_cases); ++i) {
- EXPECT_EQ(compliant_host_cases[i].expected_output,
- IsCanonicalizedHostCompliant(compliant_host_cases[i].host));
- }
-}
-
-TEST(NetUtilTest, ParseHostAndPort) {
- const struct {
- const char* const input;
- bool success;
- const char* const expected_host;
- int expected_port;
- } tests[] = {
- // Valid inputs:
- {"foo:10", true, "foo", 10},
- {"foo", true, "foo", -1},
- {
- "[1080:0:0:0:8:800:200C:4171]:11",
- true,
- "1080:0:0:0:8:800:200C:4171",
- 11
- },
- {
- "[1080:0:0:0:8:800:200C:4171]",
- true,
- "1080:0:0:0:8:800:200C:4171",
- -1
- },
-
- // Because no validation is done on the host, the following are accepted,
- // even though they are invalid names.
- {"]", true, "]", -1},
- {"::1", true, ":", 1},
- // Invalid inputs:
- {"foo:bar", false, "", -1},
- {"foo:", false, "", -1},
- {":", false, "", -1},
- {":80", false, "", -1},
- {"", false, "", -1},
- {"porttoolong:300000", false, "", -1},
- {"usrname@host", false, "", -1},
- {"usrname:password@host", false, "", -1},
- {":password@host", false, "", -1},
- {":password@host:80", false, "", -1},
- {":password@host", false, "", -1},
- {"@host", false, "", -1},
- {"[", false, "", -1},
- {"[]", false, "", -1},
- };
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- std::string host;
- int port;
- bool ok = ParseHostAndPort(tests[i].input, &host, &port);
-
- EXPECT_EQ(tests[i].success, ok);
-
- if (tests[i].success) {
- EXPECT_EQ(tests[i].expected_host, host);
- EXPECT_EQ(tests[i].expected_port, port);
- }
- }
-}
-
-TEST(NetUtilTest, GetHostAndPort) {
- const struct {
- GURL url;
- const char* const expected_host_and_port;
- } tests[] = {
- { GURL("http://www.foo.com/x"), "www.foo.com:80"},
- { GURL("http://www.foo.com:21/x"), "www.foo.com:21"},
-
- // For IPv6 literals should always include the brackets.
- { GURL("http://[1::2]/x"), "[1::2]:80"},
- { GURL("http://[::a]:33/x"), "[::a]:33"},
- };
- for (size_t i = 0; i < arraysize(tests); ++i) {
- std::string host_and_port = GetHostAndPort(tests[i].url);
- EXPECT_EQ(std::string(tests[i].expected_host_and_port), host_and_port);
- }
-}
-
-TEST(NetUtilTest, GetHostAndOptionalPort) {
- const struct {
- GURL url;
- const char* const expected_host_and_port;
- } tests[] = {
- { GURL("http://www.foo.com/x"), "www.foo.com"},
- { GURL("http://www.foo.com:21/x"), "www.foo.com:21"},
-
- // For IPv6 literals should always include the brackets.
- { GURL("http://[1::2]/x"), "[1::2]"},
- { GURL("http://[::a]:33/x"), "[::a]:33"},
- };
- for (size_t i = 0; i < arraysize(tests); ++i) {
- std::string host_and_port = GetHostAndOptionalPort(tests[i].url);
- EXPECT_EQ(std::string(tests[i].expected_host_and_port), host_and_port);
- }
-}
-
-TEST(NetUtilTest, GetHostName) {
- // We can't check the result of GetHostName() directly, since the result
- // will differ across machines. Our goal here is to simply exercise the
- // code path, and check that things "look about right".
- std::string hostname = GetHostName();
- EXPECT_FALSE(hostname.empty());
-}
-
-TEST(NetUtilTest, SimplifyUrlForRequest) {
- struct {
- const char* const input_url;
- const char* const expected_simplified_url;
- } tests[] = {
- {
- // Reference section should be stripped.
- "http://www.google.com:78/foobar?query=1#hash",
- "http://www.google.com:78/foobar?query=1",
- },
- {
- // Reference section can itself contain #.
- "http://192.168.0.1?query=1#hash#10#11#13#14",
- "http://192.168.0.1?query=1",
- },
- { // Strip username/password.
- "http://user:pass@google.com",
- "http://google.com/",
- },
- { // Strip both the reference and the username/password.
- "http://user:pass@google.com:80/sup?yo#X#X",
- "http://google.com/sup?yo",
- },
- { // Try an HTTPS URL -- strip both the reference and the username/password.
- "https://user:pass@google.com:80/sup?yo#X#X",
- "https://google.com:80/sup?yo",
- },
- { // Try an FTP URL -- strip both the reference and the username/password.
- "ftp://user:pass@google.com:80/sup?yo#X#X",
- "ftp://google.com:80/sup?yo",
- },
- { // Try a nonstandard URL
- "foobar://user:pass@google.com:80/sup?yo#X#X",
- "foobar://user:pass@google.com:80/sup?yo",
- },
- };
- for (size_t i = 0; i < arraysize(tests); ++i) {
- SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i,
- tests[i].input_url));
- GURL input_url(GURL(tests[i].input_url));
- GURL expected_url(GURL(tests[i].expected_simplified_url));
- EXPECT_EQ(expected_url, SimplifyUrlForRequest(input_url));
- }
-}
-
-TEST(NetUtilTest, GetHostOrSpecFromURL) {
- EXPECT_EQ("example.com",
- GetHostOrSpecFromURL(GURL("http://example.com/test")));
- EXPECT_EQ("example.com",
- GetHostOrSpecFromURL(GURL("http://example.com./test")));
- EXPECT_EQ("file:///tmp/test.html",
- GetHostOrSpecFromURL(GURL("file:///tmp/test.html")));
-}
-
-TEST(NetUtilTest, IsLocalhost) {
- EXPECT_TRUE(IsLocalhost("localhost"));
- EXPECT_TRUE(IsLocalhost("localHosT"));
- EXPECT_TRUE(IsLocalhost("localhost."));
- EXPECT_TRUE(IsLocalhost("localHost."));
- EXPECT_TRUE(IsLocalhost("localhost.localdomain"));
- EXPECT_TRUE(IsLocalhost("localhost.localDOMain"));
- EXPECT_TRUE(IsLocalhost("localhost.localdomain."));
- EXPECT_TRUE(IsLocalhost("localhost6"));
- EXPECT_TRUE(IsLocalhost("localhost6."));
- EXPECT_TRUE(IsLocalhost("localhost6.localdomain6"));
- EXPECT_TRUE(IsLocalhost("localhost6.localdomain6."));
- EXPECT_TRUE(IsLocalhost("127.0.0.1"));
- EXPECT_TRUE(IsLocalhost("127.0.1.0"));
- EXPECT_TRUE(IsLocalhost("127.1.0.0"));
- EXPECT_TRUE(IsLocalhost("127.0.0.255"));
- EXPECT_TRUE(IsLocalhost("127.0.255.0"));
- EXPECT_TRUE(IsLocalhost("127.255.0.0"));
- EXPECT_TRUE(IsLocalhost("::1"));
- EXPECT_TRUE(IsLocalhost("0:0:0:0:0:0:0:1"));
- EXPECT_TRUE(IsLocalhost("foo.localhost"));
- EXPECT_TRUE(IsLocalhost("foo.localhost."));
- EXPECT_TRUE(IsLocalhost("foo.localhoST"));
- EXPECT_TRUE(IsLocalhost("foo.localhoST."));
-
- EXPECT_FALSE(IsLocalhost("localhostx"));
- EXPECT_FALSE(IsLocalhost("localhost.x"));
- EXPECT_FALSE(IsLocalhost("foo.localdomain"));
- EXPECT_FALSE(IsLocalhost("foo.localdomain.x"));
- EXPECT_FALSE(IsLocalhost("localhost6x"));
- EXPECT_FALSE(IsLocalhost("localhost.localdomain6"));
- EXPECT_FALSE(IsLocalhost("localhost6.localdomain"));
- EXPECT_FALSE(IsLocalhost("127.0.0.1.1"));
- EXPECT_FALSE(IsLocalhost(".127.0.0.255"));
- EXPECT_FALSE(IsLocalhost("::2"));
- EXPECT_FALSE(IsLocalhost("::1:1"));
- EXPECT_FALSE(IsLocalhost("0:0:0:0:1:0:0:1"));
- EXPECT_FALSE(IsLocalhost("::1:1"));
- EXPECT_FALSE(IsLocalhost("0:0:0:0:0:0:0:0:1"));
- EXPECT_FALSE(IsLocalhost("foo.localhost.com"));
- EXPECT_FALSE(IsLocalhost("foo.localhoste"));
- EXPECT_FALSE(IsLocalhost("foo.localhos"));
-}
-
-TEST(NetUtilTest, ResolveLocalHostname) {
- AddressList addresses;
-
- TestBothLoopbackIPs("localhost");
- TestBothLoopbackIPs("localhoST");
- TestBothLoopbackIPs("localhost.");
- TestBothLoopbackIPs("localhoST.");
- TestBothLoopbackIPs("localhost.localdomain");
- TestBothLoopbackIPs("localhost.localdomAIn");
- TestBothLoopbackIPs("localhost.localdomain.");
- TestBothLoopbackIPs("localhost.localdomAIn.");
- TestBothLoopbackIPs("foo.localhost");
- TestBothLoopbackIPs("foo.localhOSt");
- TestBothLoopbackIPs("foo.localhost.");
- TestBothLoopbackIPs("foo.localhOSt.");
-
- TestIPv6LoopbackOnly("localhost6");
- TestIPv6LoopbackOnly("localhoST6");
- TestIPv6LoopbackOnly("localhost6.");
- TestIPv6LoopbackOnly("localhost6.localdomain6");
- TestIPv6LoopbackOnly("localhost6.localdomain6.");
-
- EXPECT_FALSE(
- ResolveLocalHostname("127.0.0.1", kLocalhostLookupPort, &addresses));
- EXPECT_FALSE(ResolveLocalHostname("::1", kLocalhostLookupPort, &addresses));
- EXPECT_FALSE(ResolveLocalHostname("0:0:0:0:0:0:0:1", kLocalhostLookupPort,
- &addresses));
- EXPECT_FALSE(
- ResolveLocalHostname("localhostx", kLocalhostLookupPort, &addresses));
- EXPECT_FALSE(
- ResolveLocalHostname("localhost.x", kLocalhostLookupPort, &addresses));
- EXPECT_FALSE(ResolveLocalHostname("foo.localdomain", kLocalhostLookupPort,
- &addresses));
- EXPECT_FALSE(ResolveLocalHostname("foo.localdomain.x", kLocalhostLookupPort,
- &addresses));
- EXPECT_FALSE(
- ResolveLocalHostname("localhost6x", kLocalhostLookupPort, &addresses));
- EXPECT_FALSE(ResolveLocalHostname("localhost.localdomain6",
- kLocalhostLookupPort, &addresses));
- EXPECT_FALSE(ResolveLocalHostname("localhost6.localdomain",
- kLocalhostLookupPort, &addresses));
- EXPECT_FALSE(
- ResolveLocalHostname("127.0.0.1.1", kLocalhostLookupPort, &addresses));
- EXPECT_FALSE(
- ResolveLocalHostname(".127.0.0.255", kLocalhostLookupPort, &addresses));
- EXPECT_FALSE(ResolveLocalHostname("::2", kLocalhostLookupPort, &addresses));
- EXPECT_FALSE(ResolveLocalHostname("::1:1", kLocalhostLookupPort, &addresses));
- EXPECT_FALSE(ResolveLocalHostname("0:0:0:0:1:0:0:1", kLocalhostLookupPort,
- &addresses));
- EXPECT_FALSE(ResolveLocalHostname("::1:1", kLocalhostLookupPort, &addresses));
- EXPECT_FALSE(ResolveLocalHostname("0:0:0:0:0:0:0:0:1", kLocalhostLookupPort,
- &addresses));
- EXPECT_FALSE(ResolveLocalHostname("foo.localhost.com", kLocalhostLookupPort,
- &addresses));
- EXPECT_FALSE(
- ResolveLocalHostname("foo.localhoste", kLocalhostLookupPort, &addresses));
-}
-
-TEST(NetUtilTest, GoogleHost) {
- struct {
- GURL url;
- bool expected_output;
- } google_host_cases[] = {
- {GURL("http://.google.com"), true},
- {GURL("http://.youtube.com"), true},
- {GURL("http://.gmail.com"), true},
- {GURL("http://.doubleclick.net"), true},
- {GURL("http://.gstatic.com"), true},
- {GURL("http://.googlevideo.com"), true},
- {GURL("http://.googleusercontent.com"), true},
- {GURL("http://.googlesyndication.com"), true},
- {GURL("http://.google-analytics.com"), true},
- {GURL("http://.googleadservices.com"), true},
- {GURL("http://.googleapis.com"), true},
- {GURL("http://a.google.com"), true},
- {GURL("http://b.youtube.com"), true},
- {GURL("http://c.gmail.com"), true},
- {GURL("http://google.com"), false},
- {GURL("http://youtube.com"), false},
- {GURL("http://gmail.com"), false},
- {GURL("http://google.coma"), false},
- {GURL("http://agoogle.com"), false},
- {GURL("http://oogle.com"), false},
- {GURL("http://google.co"), false},
- {GURL("http://oggole.com"), false},
- };
-
- for (size_t i = 0; i < arraysize(google_host_cases); ++i) {
- EXPECT_EQ(google_host_cases[i].expected_output,
- HasGoogleHost(google_host_cases[i].url));
- }
-}
-
-struct NonUniqueNameTestData {
- bool is_unique;
- const char* const hostname;
-};
-
-// Google Test pretty-printer.
-void PrintTo(const NonUniqueNameTestData& data, std::ostream* os) {
- ASSERT_TRUE(data.hostname);
- *os << " hostname: " << testing::PrintToString(data.hostname)
- << "; is_unique: " << testing::PrintToString(data.is_unique);
-}
-
-const NonUniqueNameTestData kNonUniqueNameTestData[] = {
- // Domains under ICANN-assigned domains.
- { true, "google.com" },
- { true, "google.co.uk" },
- // Domains under private registries.
- { true, "appspot.com" },
- { true, "test.appspot.com" },
- // Unreserved IPv4 addresses (in various forms).
- { true, "8.8.8.8" },
- { true, "99.64.0.0" },
- { true, "212.15.0.0" },
- { true, "212.15" },
- { true, "212.15.0" },
- { true, "3557752832" },
- // Reserved IPv4 addresses (in various forms).
- { false, "192.168.0.0" },
- { false, "192.168.0.6" },
- { false, "10.0.0.5" },
- { false, "10.0" },
- { false, "10.0.0" },
- { false, "3232235526" },
- // Unreserved IPv6 addresses.
- { true, "FFC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
- { true, "2000:ba98:7654:2301:EFCD:BA98:7654:3210" },
- // Reserved IPv6 addresses.
- { false, "::192.9.5.5" },
- { false, "FEED::BEEF" },
- { false, "FEC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
- // 'internal'/non-IANA assigned domains.
- { false, "intranet" },
- { false, "intranet." },
- { false, "intranet.example" },
- { false, "host.intranet.example" },
- // gTLDs under discussion, but not yet assigned.
- { false, "intranet.corp" },
- { false, "intranet.internal" },
- // Invalid host names are treated as unique - but expected to be
- // filtered out before then.
- { true, "junk)(£)$*!@~#" },
- { true, "w$w.example.com" },
- { true, "nocolonsallowed:example" },
- { true, "[::4.5.6.9]" },
-};
-
-class NetUtilNonUniqueNameTest
- : public testing::TestWithParam<NonUniqueNameTestData> {
- public:
- virtual ~NetUtilNonUniqueNameTest() {}
-
- protected:
- bool IsUnique(const std::string& hostname) {
- return !IsHostnameNonUnique(hostname);
- }
-};
-
-// Test that internal/non-unique names are properly identified as such, but
-// that IP addresses and hosts beneath registry-controlled domains are flagged
-// as unique names.
-TEST_P(NetUtilNonUniqueNameTest, IsHostnameNonUnique) {
- const NonUniqueNameTestData& test_data = GetParam();
-
- EXPECT_EQ(test_data.is_unique, IsUnique(test_data.hostname));
-}
-
-INSTANTIATE_TEST_CASE_P(, NetUtilNonUniqueNameTest,
- testing::ValuesIn(kNonUniqueNameTestData));
-
-} // namespace net
diff --git a/chromium/net/base/network_change_notifier.cc b/chromium/net/base/network_change_notifier.cc
index 52e5ce34c21..93ca8ba2490 100644
--- a/chromium/net/base/network_change_notifier.cc
+++ b/chromium/net/base/network_change_notifier.cc
@@ -12,9 +12,9 @@
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "build/build_config.h"
-#include "net/base/net_util.h"
#include "net/base/network_change_notifier_factory.h"
#include "net/base/network_interfaces.h"
+#include "net/base/url_util.h"
#include "net/dns/dns_config_service.h"
#include "net/url_request/url_request.h"
#include "url/gurl.h"
@@ -420,7 +420,7 @@ class NetworkChangeNotifier::NetworkChangeCalculator
: public ConnectionTypeObserver,
public IPAddressObserver {
public:
- NetworkChangeCalculator(const NetworkChangeCalculatorParams& params)
+ explicit NetworkChangeCalculator(const NetworkChangeCalculatorParams& params)
: params_(params),
have_announced_(false),
last_announced_connection_type_(CONNECTION_NONE),
@@ -730,14 +730,19 @@ void NetworkChangeNotifier::ShutdownHistogramWatcher() {
}
// static
+void NetworkChangeNotifier::FinalizingMetricsLogRecord() {
+ if (!g_network_change_notifier)
+ return;
+ g_network_change_notifier->OnFinalizingMetricsLogRecord();
+}
+
+// static
void NetworkChangeNotifier::LogOperatorCodeHistogram(ConnectionType type) {
#if defined(OS_ANDROID)
- // On a connection type change to 2/3/4G, log the network operator MCC/MNC.
+ // On a connection type change to cellular, log the network operator MCC/MNC.
// Log zero in other cases.
unsigned mcc_mnc = 0;
- if (type == NetworkChangeNotifier::CONNECTION_2G ||
- type == NetworkChangeNotifier::CONNECTION_3G ||
- type == NetworkChangeNotifier::CONNECTION_4G) {
+ if (NetworkChangeNotifier::IsConnectionCellular(type)) {
// Log zero if not perfectly converted.
if (!base::StringToUint(android::GetTelephonyNetworkOperator(), &mcc_mnc)) {
mcc_mnc = 0;
@@ -758,7 +763,7 @@ NetworkChangeNotifier::GetAddressTracker() {
// static
bool NetworkChangeNotifier::IsOffline() {
- return GetConnectionType() == CONNECTION_NONE;
+ return GetConnectionType() == CONNECTION_NONE;
}
// static
diff --git a/chromium/net/base/network_change_notifier.h b/chromium/net/base/network_change_notifier.h
index f532889b0af..0d3c0dc73b2 100644
--- a/chromium/net/base/network_change_notifier.h
+++ b/chromium/net/base/network_change_notifier.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/observer_list_threadsafe.h"
#include "base/time/time.h"
#include "net/base/net_export.h"
@@ -60,13 +61,18 @@ class NET_EXPORT NetworkChangeNotifier {
};
// This is the NetInfo v3 set of connection technologies as seen in
- // http://w3c.github.io/netinfo/. This enum is copied in
- // NetworkChangeNotifier.java so be sure to change both at once.
+ // http://w3c.github.io/netinfo/. This enum is duplicated in histograms.xml
+ // so be sure to change both at once. Additionally, since this enum is used in
+ // a UMA histogram, it should not be re-ordered and any new values should be
+ // added to the end.
//
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net
enum ConnectionSubtype {
- SUBTYPE_GSM = 0,
+ SUBTYPE_UNKNOWN = 0,
+ SUBTYPE_NONE,
+ SUBTYPE_OTHER,
+ SUBTYPE_GSM,
SUBTYPE_IDEN,
SUBTYPE_CDMA,
SUBTYPE_1XRTT,
@@ -96,10 +102,7 @@ class NET_EXPORT NetworkChangeNotifier {
SUBTYPE_WIFI_N,
SUBTYPE_WIFI_AC,
SUBTYPE_WIFI_AD,
- SUBTYPE_UNKNOWN,
- SUBTYPE_NONE,
- SUBTYPE_OTHER,
- SUBTYPE_LAST = SUBTYPE_OTHER
+ SUBTYPE_LAST = SUBTYPE_WIFI_AD
};
class NET_EXPORT IPAddressObserver {
@@ -420,6 +423,12 @@ class NET_EXPORT NetworkChangeNotifier {
// should be called from the network thread to avoid race conditions.
static void ShutdownHistogramWatcher();
+ // Invoked at the time a new user metrics log record is being finalized, on
+ // the main thread. NCN Histograms that want to be logged once per record
+ // should be logged in this method. Platform-specific histograms should be
+ // logged in an overridden implementaton of OnFinalizingMetricsLogRecord.
+ static void FinalizingMetricsLogRecord();
+
// Log the |NCN.NetworkOperatorMCCMNC| histogram.
static void LogOperatorCodeHistogram(ConnectionType type);
@@ -497,6 +506,10 @@ class NET_EXPORT NetworkChangeNotifier {
NetworkHandle network) const;
virtual NetworkHandle GetCurrentDefaultNetwork() const;
+ // Hook that allows derived implementations to log histograms at the time a
+ // new histogram record is being finalized.
+ virtual void OnFinalizingMetricsLogRecord() {}
+
// Broadcasts a notification to all registered observers. Note that this
// happens asynchronously, even for observers on the current thread, even in
// tests.
diff --git a/chromium/net/base/network_change_notifier_linux.cc b/chromium/net/base/network_change_notifier_linux.cc
index e1e7de02508..b18b6c21c24 100644
--- a/chromium/net/base/network_change_notifier_linux.cc
+++ b/chromium/net/base/network_change_notifier_linux.cc
@@ -21,11 +21,11 @@ class NetworkChangeNotifierLinux::Thread : public base::Thread {
// Plumbing for NetworkChangeNotifier::GetCurrentConnectionType.
// Safe to call from any thread.
NetworkChangeNotifier::ConnectionType GetCurrentConnectionType() {
- return address_tracker_.GetCurrentConnectionType();
+ return address_tracker_->GetCurrentConnectionType();
}
const internal::AddressTrackerLinux* address_tracker() const {
- return &address_tracker_;
+ return address_tracker_.get();
}
protected:
@@ -38,7 +38,7 @@ class NetworkChangeNotifierLinux::Thread : public base::Thread {
void OnLinkChanged();
scoped_ptr<DnsConfigService> dns_config_service_;
// Used to detect online/offline state and IP address changes.
- internal::AddressTrackerLinux address_tracker_;
+ scoped_ptr<internal::AddressTrackerLinux> address_tracker_;
NetworkChangeNotifier::ConnectionType last_type_;
DISALLOW_COPY_AND_ASSIGN(Thread);
@@ -47,28 +47,31 @@ class NetworkChangeNotifierLinux::Thread : public base::Thread {
NetworkChangeNotifierLinux::Thread::Thread(
const base::hash_set<std::string>& ignored_interfaces)
: base::Thread("NetworkChangeNotifier"),
- address_tracker_(
+ address_tracker_(new internal::AddressTrackerLinux(
base::Bind(&NetworkChangeNotifierLinux::Thread::OnIPAddressChanged,
base::Unretained(this)),
base::Bind(&NetworkChangeNotifierLinux::Thread::OnLinkChanged,
base::Unretained(this)),
base::Bind(base::DoNothing),
- ignored_interfaces),
- last_type_(NetworkChangeNotifier::CONNECTION_NONE) {
-}
+ ignored_interfaces)),
+ last_type_(NetworkChangeNotifier::CONNECTION_NONE) {}
NetworkChangeNotifierLinux::Thread::~Thread() {
DCHECK(!Thread::IsRunning());
}
void NetworkChangeNotifierLinux::Thread::Init() {
- address_tracker_.Init();
+ address_tracker_->Init();
dns_config_service_ = DnsConfigService::CreateSystemService();
dns_config_service_->WatchConfig(
base::Bind(&NetworkChangeNotifier::SetDnsConfig));
}
void NetworkChangeNotifierLinux::Thread::CleanUp() {
+ // Delete AddressTrackerLinux before MessageLoop gets deleted as
+ // AddressTrackerLinux's FileDescriptorWatcher holds a pointer to the
+ // MessageLoop.
+ address_tracker_.reset();
dns_config_service_.reset();
}
diff --git a/chromium/net/base/network_change_notifier_linux.h b/chromium/net/base/network_change_notifier_linux.h
index 85238cf9688..48bda6bdd4a 100644
--- a/chromium/net/base/network_change_notifier_linux.h
+++ b/chromium/net/base/network_change_notifier_linux.h
@@ -6,6 +6,7 @@
#define NET_BASE_NETWORK_CHANGE_NOTIFIER_LINUX_H_
#include "base/compiler_specific.h"
+#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/net_export.h"
diff --git a/chromium/net/base/network_change_notifier_win.cc b/chromium/net/base/network_change_notifier_win.cc
index 1c4052246cc..f0f5206c0c5 100644
--- a/chromium/net/base/network_change_notifier_win.cc
+++ b/chromium/net/base/network_change_notifier_win.cc
@@ -17,8 +17,6 @@
#include "net/base/winsock_util.h"
#include "net/dns/dns_config_service.h"
-#pragma comment(lib, "iphlpapi.lib")
-
namespace net {
namespace {
diff --git a/chromium/net/base/network_delegate.cc b/chromium/net/base/network_delegate.cc
index ff4ee88fa0b..113b7481478 100644
--- a/chromium/net/base/network_delegate.cc
+++ b/chromium/net/base/network_delegate.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/profiler/scoped_tracker.h"
+#include "base/trace_event/trace_event.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/proxy/proxy_info.h"
@@ -16,6 +17,8 @@ namespace net {
int NetworkDelegate::NotifyBeforeURLRequest(
URLRequest* request, const CompletionCallback& callback,
GURL* new_url) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "NetworkDelegate::NotifyBeforeURLRequest");
DCHECK(CalledOnValidThread());
DCHECK(request);
DCHECK(!callback.is_null());
@@ -26,26 +29,11 @@ int NetworkDelegate::NotifyBeforeURLRequest(
return OnBeforeURLRequest(request, callback, new_url);
}
-void NetworkDelegate::NotifyResolveProxy(
- const GURL& url,
- int load_flags,
- const ProxyService& proxy_service,
- ProxyInfo* result) {
- DCHECK(CalledOnValidThread());
- DCHECK(result);
- OnResolveProxy(url, load_flags, proxy_service, result);
-}
-
-void NetworkDelegate::NotifyProxyFallback(
- const ProxyServer& bad_proxy,
- int net_error) {
- DCHECK(CalledOnValidThread());
- OnProxyFallback(bad_proxy, net_error);
-}
-
int NetworkDelegate::NotifyBeforeSendHeaders(
URLRequest* request, const CompletionCallback& callback,
HttpRequestHeaders* headers) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "NetworkDelegate::NotifyBeforeSendHeaders");
DCHECK(CalledOnValidThread());
DCHECK(headers);
DCHECK(!callback.is_null());
@@ -63,6 +51,8 @@ void NetworkDelegate::NotifyBeforeSendProxyHeaders(
void NetworkDelegate::NotifySendHeaders(URLRequest* request,
const HttpRequestHeaders& headers) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "NetworkDelegate::NotifySendHeaders");
DCHECK(CalledOnValidThread());
OnSendHeaders(request, headers);
}
@@ -73,6 +63,8 @@ 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");
DCHECK(CalledOnValidThread());
DCHECK(original_response_headers);
DCHECK(!callback.is_null());
@@ -91,6 +83,8 @@ void NetworkDelegate::NotifyResponseStarted(URLRequest* request) {
void NetworkDelegate::NotifyNetworkBytesReceived(URLRequest* request,
int64_t bytes_received) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "NetworkDelegate::NotifyNetworkBytesReceived");
DCHECK(CalledOnValidThread());
DCHECK_GT(bytes_received, 0);
OnNetworkBytesReceived(request, bytes_received);
@@ -111,6 +105,8 @@ void NetworkDelegate::NotifyBeforeRedirect(URLRequest* request,
}
void NetworkDelegate::NotifyCompleted(URLRequest* request, bool started) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "NetworkDelegate::NotifyCompleted");
DCHECK(CalledOnValidThread());
DCHECK(request);
// TODO(cbentzel): Remove ScopedTracker below once crbug.com/475753 is fixed.
@@ -120,6 +116,8 @@ void NetworkDelegate::NotifyCompleted(URLRequest* request, bool started) {
}
void NetworkDelegate::NotifyURLRequestDestroyed(URLRequest* request) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "NetworkDelegate::NotifyURLRequestDestroyed");
DCHECK(CalledOnValidThread());
DCHECK(request);
OnURLRequestDestroyed(request);
@@ -164,6 +162,8 @@ 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");
DCHECK(CalledOnValidThread());
return OnCanEnablePrivacyMode(url, first_party_for_cookies);
}
diff --git a/chromium/net/base/network_delegate.h b/chromium/net/base/network_delegate.h
index 07371371054..81d81902412 100644
--- a/chromium/net/base/network_delegate.h
+++ b/chromium/net/base/network_delegate.h
@@ -38,8 +38,6 @@ class CookieOptions;
class HttpRequestHeaders;
class HttpResponseHeaders;
class ProxyInfo;
-class ProxyServer;
-class ProxyService;
class URLRequest;
class NET_EXPORT NetworkDelegate : public base::NonThreadSafe {
@@ -64,12 +62,6 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe {
int NotifyBeforeURLRequest(URLRequest* request,
const CompletionCallback& callback,
GURL* new_url);
- void NotifyResolveProxy(const GURL& url,
- int load_flags,
- const ProxyService& proxy_service,
- ProxyInfo* result);
- void NotifyProxyFallback(const ProxyServer& bad_proxy,
- int net_error);
int NotifyBeforeSendHeaders(URLRequest* request,
const CompletionCallback& callback,
HttpRequestHeaders* headers);
@@ -106,12 +98,10 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe {
bool CanEnablePrivacyMode(const GURL& url,
const GURL& first_party_for_cookies) const;
- // TODO(mkwst): Remove this once we decide whether or not we wish to ship
- // first-party cookies and setting secure cookies require
- // secure scheme. https://crbug.com/459154, https://crbug.com/541511,
- // https://crbug.com/546820
bool AreExperimentalCookieFeaturesEnabled() const;
- // TODO(jww): Remove this once we ship strict secure cookies.
+
+ // TODO(jww): Remove this once we ship strict secure cookies:
+ // https://crbug.com/546820
bool AreStrictSecureCookiesEnabled() const;
bool CancelURLRequestWithPolicyViolatingReferrerHeader(
@@ -140,20 +130,6 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe {
const CompletionCallback& callback,
GURL* new_url) = 0;
- // Called as the proxy is being resolved for |url|. Allows the delegate to
- // override the proxy resolution decision made by ProxyService. The delegate
- // may override the decision by modifying the ProxyInfo |result|.
- virtual void OnResolveProxy(const GURL& url,
- int load_flags,
- const ProxyService& proxy_service,
- ProxyInfo* result) = 0;
-
- // Called when use of |bad_proxy| fails due to |net_error|. |net_error| is
- // the network error encountered, if any, and OK if the fallback was
- // for a reason other than a network error (e.g. the proxy service was
- // explicitly directed to skip a proxy).
- virtual void OnProxyFallback(const ProxyServer& bad_proxy, int net_error) = 0;
-
// Called right before the HTTP headers are sent. Allows the delegate to
// read/write |headers| before they get sent out. |callback| and |headers| are
// valid only until OnCompleted or OnURLRequestDestroyed is called for this
@@ -290,17 +266,13 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe {
// Returns true if the embedder has enabled the experimental features, and
// false otherwise.
- //
- // TODO(mkwst): Remove this once we decide whether or not we wish to ship
- // first-party cookies, cookie prefixes, and setting secure cookies require
- // secure scheme. https://crbug.com/459154, https://crbug.com/541511,
- // https://crbug.com/546820
virtual bool OnAreExperimentalCookieFeaturesEnabled() const = 0;
// Returns true if the embedder has enabled experimental features or
// specifically strict secure cookies, and false otherwise.
//
- // TODO(jww): Remove this once we ship strict secure cookies.
+ // TODO(jww): Remove this once we ship strict secure cookies:
+ // https://crbug.com/546820.
virtual bool OnAreStrictSecureCookiesEnabled() const = 0;
// Called when the |referrer_url| for requesting |target_url| during handling
diff --git a/chromium/net/base/network_delegate_impl.cc b/chromium/net/base/network_delegate_impl.cc
index 5e94543b303..43f94af8f16 100644
--- a/chromium/net/base/network_delegate_impl.cc
+++ b/chromium/net/base/network_delegate_impl.cc
@@ -14,16 +14,6 @@ int NetworkDelegateImpl::OnBeforeURLRequest(URLRequest* request,
return OK;
}
-void NetworkDelegateImpl::OnResolveProxy(const GURL& url,
- int load_flags,
- const ProxyService& proxy_service,
- ProxyInfo* result) {
-}
-
-void NetworkDelegateImpl::OnProxyFallback(const ProxyServer& bad_proxy,
- int net_error) {
-}
-
int NetworkDelegateImpl::OnBeforeSendHeaders(URLRequest* request,
const CompletionCallback& callback,
HttpRequestHeaders* headers) {
diff --git a/chromium/net/base/network_delegate_impl.h b/chromium/net/base/network_delegate_impl.h
index 8a0b007f3d8..e0685d65f20 100644
--- a/chromium/net/base/network_delegate_impl.h
+++ b/chromium/net/base/network_delegate_impl.h
@@ -24,8 +24,6 @@ class CookieOptions;
class HttpRequestHeaders;
class HttpResponseHeaders;
class ProxyInfo;
-class ProxyServer;
-class ProxyService;
class URLRequest;
class NET_EXPORT NetworkDelegateImpl : public NetworkDelegate {
@@ -53,20 +51,6 @@ class NET_EXPORT NetworkDelegateImpl : public NetworkDelegate {
const CompletionCallback& callback,
GURL* new_url) override;
- // Called as the proxy is being resolved for |url|. Allows the delegate to
- // override the proxy resolution decision made by ProxyService. The delegate
- // may override the decision by modifying the ProxyInfo |result|.
- void OnResolveProxy(const GURL& url,
- int load_flags,
- const ProxyService& proxy_service,
- ProxyInfo* result) override;
-
- // Called when use of |bad_proxy| fails due to |net_error|. |net_error| is
- // the network error encountered, if any, and OK if the fallback was
- // for a reason other than a network error (e.g. the proxy service was
- // explicitly directed to skip a proxy).
- void OnProxyFallback(const ProxyServer& bad_proxy, int net_error) override;
-
// Called right before the HTTP headers are sent. Allows the delegate to
// read/write |headers| before they get sent out. |callback| and |headers| are
// valid only until OnCompleted or OnURLRequestDestroyed is called for this
@@ -198,13 +182,11 @@ class NET_EXPORT NetworkDelegateImpl : public NetworkDelegate {
const GURL& url,
const GURL& first_party_for_cookies) const override;
- // Returns true if the embedder has enabled the "first-party" cookie
- // experiment, and false otherwise.
- //
- // TODO(mkwst): Remove this once we decide whether or not we wish to ship
- // first-party cookies and cookie prefixes. https://crbug.com/459154,
- // https://crbug.com/541511
+ // Returns true if the embedder has enabled experimental cookie features.
bool OnAreExperimentalCookieFeaturesEnabled() const override;
+
+ // TODO(jww): Remove this once we ship strict secure cookies:
+ // https://crbug.com/546820
bool OnAreStrictSecureCookiesEnabled() const override;
// Called when the |referrer_url| for requesting |target_url| during handling
diff --git a/chromium/net/base/network_interfaces.cc b/chromium/net/base/network_interfaces.cc
index a49bce600c4..ccbd66ac68d 100644
--- a/chromium/net/base/network_interfaces.cc
+++ b/chromium/net/base/network_interfaces.cc
@@ -4,6 +4,17 @@
#include "net/base/network_interfaces.h"
+#include "build/build_config.h"
+
+#if defined(OS_POSIX)
+#include <unistd.h>
+#endif
+
+#if defined(OS_WIN)
+#include <winsock2.h>
+#include "net/base/winsock_init.h"
+#endif
+
namespace net {
NetworkInterface::NetworkInterface()
@@ -14,7 +25,7 @@ NetworkInterface::NetworkInterface(const std::string& name,
const std::string& friendly_name,
uint32_t interface_index,
NetworkChangeNotifier::ConnectionType type,
- const IPAddressNumber& address,
+ const IPAddress& address,
uint32_t prefix_length,
int ip_address_attributes)
: name(name),
@@ -23,8 +34,9 @@ NetworkInterface::NetworkInterface(const std::string& name,
type(type),
address(address),
prefix_length(prefix_length),
- ip_address_attributes(ip_address_attributes) {
-}
+ ip_address_attributes(ip_address_attributes) {}
+
+NetworkInterface::NetworkInterface(const NetworkInterface& other) = default;
NetworkInterface::~NetworkInterface() {
}
@@ -32,4 +44,24 @@ NetworkInterface::~NetworkInterface() {
ScopedWifiOptions::~ScopedWifiOptions() {
}
+std::string GetHostName() {
+#if defined(OS_NACL)
+ NOTIMPLEMENTED();
+ return std::string();
+#else // defined(OS_NACL)
+#if defined(OS_WIN)
+ EnsureWinsockInit();
+#endif
+
+ // Host names are limited to 255 bytes.
+ char buffer[256];
+ int result = gethostname(buffer, sizeof(buffer));
+ if (result != 0) {
+ DVLOG(1) << "gethostname() failed with " << result;
+ buffer[0] = '\0';
+ }
+ return std::string(buffer);
+#endif // !defined(OS_NACL)
+}
+
} // namespace net
diff --git a/chromium/net/base/network_interfaces.h b/chromium/net/base/network_interfaces.h
index ed98abb5d84..84edcfb8241 100644
--- a/chromium/net/base/network_interfaces.h
+++ b/chromium/net/base/network_interfaces.h
@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "net/base/net_export.h"
#include "net/base/network_change_notifier.h"
@@ -44,16 +44,17 @@ struct NET_EXPORT NetworkInterface {
const std::string& friendly_name,
uint32_t interface_index,
NetworkChangeNotifier::ConnectionType type,
- const IPAddressNumber& address,
+ const IPAddress& address,
uint32_t prefix_length,
int ip_address_attributes);
+ NetworkInterface(const NetworkInterface& other);
~NetworkInterface();
std::string name;
std::string friendly_name; // Same as |name| on non-Windows.
uint32_t interface_index; // Always 0 on Android.
NetworkChangeNotifier::ConnectionType type;
- IPAddressNumber address;
+ IPAddress address;
uint32_t prefix_length;
int ip_address_attributes; // Combination of |IPAddressAttributes|.
};
@@ -122,6 +123,9 @@ class NET_EXPORT ScopedWifiOptions {
// is freed. Currently only available on Windows.
NET_EXPORT scoped_ptr<ScopedWifiOptions> SetWifiOptions(int options);
+// Returns the hostname of the current system. Returns empty string on failure.
+NET_EXPORT std::string GetHostName();
+
} // namespace net
#endif // NET_BASE_NETWORK_INTERFACES_H_
diff --git a/chromium/net/base/network_interfaces_linux.cc b/chromium/net/base/network_interfaces_linux.cc
index 8aea321fd13..121e0e0284e 100644
--- a/chromium/net/base/network_interfaces_linux.cc
+++ b/chromium/net/base/network_interfaces_linux.cc
@@ -26,7 +26,6 @@
#include "net/base/escape.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/network_interfaces_posix.h"
#include "url/gurl.h"
@@ -68,10 +67,6 @@ bool TryConvertNativeToNetIPAttributes(int native_attributes,
namespace internal {
-inline const unsigned char* GetIPAddressData(const IPAddressNumber& ip) {
- return ip.data();
-}
-
// Gets the connection type for interface |ifname| by checking for wireless
// or ethtool extensions.
NetworkChangeNotifier::ConnectionType GetInterfaceConnectionType(
diff --git a/chromium/net/base/network_interfaces_mac.cc b/chromium/net/base/network_interfaces_mac.cc
index 8176c6c3775..2fa66fbc77b 100644
--- a/chromium/net/base/network_interfaces_mac.cc
+++ b/chromium/net/base/network_interfaces_mac.cc
@@ -20,7 +20,6 @@
#include "net/base/escape.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/network_interfaces_posix.h"
#include "url/gurl.h"
diff --git a/chromium/net/base/network_interfaces_unittest.cc b/chromium/net/base/network_interfaces_unittest.cc
index 470295f0218..2017ab7de7f 100644
--- a/chromium/net/base/network_interfaces_unittest.cc
+++ b/chromium/net/base/network_interfaces_unittest.cc
@@ -19,7 +19,6 @@
#include "base/sys_byteorder.h"
#include "base/time/time.h"
#include "net/base/ip_endpoint.h"
-#include "net/base/net_util.h"
#if !defined(OS_NACL) && !defined(OS_WIN)
#include <net/if.h>
@@ -91,8 +90,8 @@ class IPAttributesGetterTest : public internal::IPAttributesGetterMac {
bool FillIfaddrs(ifaddrs* interfaces,
const char* ifname,
uint flags,
- const IPAddressNumber& ip_address,
- const IPAddressNumber& ip_netmask,
+ const IPAddress& ip_address,
+ const IPAddress& ip_netmask,
sockaddr_storage sock_addrs[2]) {
interfaces->ifa_next = NULL;
interfaces->ifa_name = const_cast<char*>(ifname);
@@ -119,8 +118,9 @@ bool FillIfaddrs(ifaddrs* interfaces,
return true;
}
#endif // OS_MACOSX
+
// Verify GetNetworkList().
-TEST(NetUtilTest, GetNetworkList) {
+TEST(NetworkInterfacesTest, GetNetworkList) {
NetworkInterfaceList list;
ASSERT_TRUE(GetNetworkList(&list, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES));
for (NetworkInterfaceList::iterator it = list.begin();
@@ -130,17 +130,9 @@ TEST(NetUtilTest, GetNetworkList) {
EXPECT_FALSE(it->friendly_name.empty());
// Verify that the address is correct.
- EXPECT_TRUE(it->address.size() == kIPv4AddressSize ||
- it->address.size() == kIPv6AddressSize)
- << "Invalid address of size " << it->address.size();
- bool all_zeroes = true;
- for (size_t i = 0; i < it->address.size(); ++i) {
- if (it->address[i] != 0) {
- all_zeroes = false;
- break;
- }
- }
- EXPECT_FALSE(all_zeroes);
+ EXPECT_TRUE(it->address.IsValid()) << "Invalid address of size "
+ << it->address.size();
+ EXPECT_FALSE(it->address.IsZero());
EXPECT_GT(it->prefix_length, 1u);
EXPECT_LE(it->prefix_length, it->address.size() * 8);
@@ -232,10 +224,9 @@ char* GetInterfaceNameVM(int interface_index, char* ifname) {
return CopyInterfaceName(ifname_vm, arraysize(ifname_vm), ifname);
}
-TEST(NetUtilTest, GetNetworkListTrimming) {
- IPAddressNumber ipv6_local_address(
- kIPv6LocalAddr, kIPv6LocalAddr + arraysize(kIPv6LocalAddr));
- IPAddressNumber ipv6_address(kIPv6Addr, kIPv6Addr + arraysize(kIPv6Addr));
+TEST(NetworkInterfacesTest, GetNetworkListTrimming) {
+ IPAddress ipv6_local_address(kIPv6LocalAddr);
+ IPAddress ipv6_address(kIPv6Addr);
NetworkInterfaceList results;
::base::hash_set<int> online_links;
@@ -333,12 +324,10 @@ TEST(NetUtilTest, GetNetworkListTrimming) {
#elif defined(OS_MACOSX)
-TEST(NetUtilTest, GetNetworkListTrimming) {
- IPAddressNumber ipv6_local_address(
- kIPv6LocalAddr, kIPv6LocalAddr + arraysize(kIPv6LocalAddr));
- IPAddressNumber ipv6_address(kIPv6Addr, kIPv6Addr + arraysize(kIPv6Addr));
- IPAddressNumber ipv6_netmask(kIPv6Netmask,
- kIPv6Netmask + arraysize(kIPv6Netmask));
+TEST(NetworkInterfacesTest, GetNetworkListTrimming) {
+ IPAddress ipv6_local_address(kIPv6LocalAddr);
+ IPAddress ipv6_address(kIPv6Addr);
+ IPAddress ipv6_netmask(kIPv6Netmask);
NetworkInterfaceList results;
IPAttributesGetterTest ip_attributes_getter;
@@ -432,8 +421,8 @@ TEST(NetUtilTest, GetNetworkListTrimming) {
// |adapter_address| once the function is returned.
bool FillAdapterAddress(IP_ADAPTER_ADDRESSES* adapter_address,
const char* ifname,
- const IPAddressNumber& ip_address,
- const IPAddressNumber& ip_netmask,
+ const IPAddress& ip_address,
+ const IPAddress& ip_netmask,
sockaddr_storage sock_addrs[2]) {
adapter_address->AdapterName = const_cast<char*>(ifname);
adapter_address->FriendlyName = const_cast<PWCHAR>(L"interface");
@@ -480,12 +469,10 @@ bool FillAdapterAddress(IP_ADAPTER_ADDRESSES* adapter_address,
return true;
}
-TEST(NetUtilTest, GetNetworkListTrimming) {
- IPAddressNumber ipv6_local_address(
- kIPv6LocalAddr, kIPv6LocalAddr + arraysize(kIPv6LocalAddr));
- IPAddressNumber ipv6_address(kIPv6Addr, kIPv6Addr + arraysize(kIPv6Addr));
- IPAddressNumber ipv6_prefix(kIPv6AddrPrefix,
- kIPv6AddrPrefix + arraysize(kIPv6AddrPrefix));
+TEST(NetworkInterfacesTest, GetNetworkListTrimming) {
+ IPAddress ipv6_local_address(kIPv6LocalAddr);
+ IPAddress ipv6_address(kIPv6Addr);
+ IPAddress ipv6_prefix(kIPv6AddrPrefix);
NetworkInterfaceList results;
sockaddr_storage addresses[2];
@@ -596,7 +583,7 @@ TEST(NetUtilTest, GetNetworkListTrimming) {
#endif // !OS_MACOSX && !OS_WIN && !OS_NACL
-TEST(NetUtilTest, GetWifiSSID) {
+TEST(NetworkInterfacesTest, GetWifiSSID) {
// We can't check the result of GetWifiSSID() directly, since the result
// will differ across machines. Simply exercise the code path and hope that it
// doesn't crash.
@@ -604,7 +591,7 @@ TEST(NetUtilTest, GetWifiSSID) {
}
#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS)
-TEST(NetUtilTest, GetWifiSSIDFromInterfaceList) {
+TEST(NetworkInterfacesTest, GetWifiSSIDFromInterfaceList) {
NetworkInterfaceList list;
EXPECT_EQ(std::string(), internal::GetWifiSSIDFromInterfaceListInternal(
list, TestGetInterfaceSSID));
@@ -743,7 +730,7 @@ void TryChangeWifiOptions(int options) {
}
// Test SetWifiOptions().
-TEST(NetUtilTest, SetWifiOptionsTest) {
+TEST(NetworkInterfacesTest, SetWifiOptionsTest) {
TryChangeWifiOptions(0);
TryChangeWifiOptions(WIFI_OPTIONS_DISABLE_SCAN);
TryChangeWifiOptions(WIFI_OPTIONS_MEDIA_STREAMING_MODE);
@@ -751,6 +738,14 @@ TEST(NetUtilTest, SetWifiOptionsTest) {
WIFI_OPTIONS_MEDIA_STREAMING_MODE);
}
+TEST(NetworkInterfacesTest, GetHostName) {
+ // We can't check the result of GetHostName() directly, since the result
+ // will differ across machines. Our goal here is to simply exercise the
+ // code path, and check that things "look about right".
+ std::string hostname = GetHostName();
+ EXPECT_FALSE(hostname.empty());
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/base/network_interfaces_win.cc b/chromium/net/base/network_interfaces_win.cc
index e451211161e..e00606ce7bf 100644
--- a/chromium/net/base/network_interfaces_win.cc
+++ b/chromium/net/base/network_interfaces_win.cc
@@ -4,8 +4,6 @@
#include "net/base/network_interfaces_win.h"
-#pragma comment(lib, "iphlpapi.lib")
-
#include <algorithm>
#include "base/files/file_path.h"
@@ -21,7 +19,6 @@
#include "net/base/escape.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "url/gurl.h"
namespace net {
@@ -55,20 +52,20 @@ GetConnectionAttributes() {
scoped_ptr<WLAN_CONNECTION_ATTRIBUTES, internal::WlanApiDeleter>
wlan_connection_attributes;
if (!wlanapi.initialized)
- return wlan_connection_attributes.Pass();
+ return wlan_connection_attributes;
internal::WlanHandle client;
DWORD cur_version = 0;
const DWORD kMaxClientVersion = 2;
DWORD result = wlanapi.OpenHandle(kMaxClientVersion, &cur_version, &client);
if (result != ERROR_SUCCESS)
- return wlan_connection_attributes.Pass();
+ return wlan_connection_attributes;
WLAN_INTERFACE_INFO_LIST* interface_list_ptr = NULL;
result =
wlanapi.enum_interfaces_func(client.Get(), NULL, &interface_list_ptr);
if (result != ERROR_SUCCESS)
- return wlan_connection_attributes.Pass();
+ return wlan_connection_attributes;
scoped_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter> interface_list(
interface_list_ptr);
@@ -83,7 +80,7 @@ GetConnectionAttributes() {
}
if (info == NULL)
- return wlan_connection_attributes.Pass();
+ return wlan_connection_attributes;
WLAN_CONNECTION_ATTRIBUTES* conn_info_ptr = nullptr;
DWORD conn_info_size = 0;
@@ -97,7 +94,7 @@ GetConnectionAttributes() {
DCHECK(conn_info_ptr);
else
wlan_connection_attributes.reset();
- return wlan_connection_attributes.Pass();
+ return wlan_connection_attributes;
}
} // namespace
@@ -180,11 +177,12 @@ bool GetNetworkListImpl(NetworkInterfaceList* networks,
int prefix_family = prefix->Address.lpSockaddr->sa_family;
IPEndPoint network_endpoint;
if (prefix_family == family &&
- network_endpoint.FromSockAddr(prefix->Address.lpSockaddr,
+ network_endpoint.FromSockAddr(
+ prefix->Address.lpSockaddr,
prefix->Address.iSockaddrLength) &&
- IPNumberMatchesPrefix(endpoint.address(),
- network_endpoint.address(),
- prefix->PrefixLength)) {
+ IPAddressMatchesPrefix(endpoint.address(),
+ network_endpoint.address(),
+ prefix->PrefixLength)) {
prefix_length =
std::max<size_t>(prefix_length, prefix->PrefixLength);
}
diff --git a/chromium/net/base/network_quality_estimator.cc b/chromium/net/base/network_quality_estimator.cc
index c67b641101a..9a6d8d60f06 100644
--- a/chromium/net/base/network_quality_estimator.cc
+++ b/chromium/net/base/network_quality_estimator.cc
@@ -15,11 +15,14 @@
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_base.h"
#include "base/strings/string_number_conversions.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "net/base/load_flags.h"
#include "net/base/load_timing_info.h"
-#include "net/base/net_util.h"
#include "net/base/network_interfaces.h"
+#include "net/base/socket_performance_watcher.h"
+#include "net/base/url_util.h"
#include "net/url_request/url_request.h"
#include "url/gurl.h"
@@ -117,6 +120,81 @@ base::HistogramBase* GetHistogram(
namespace net {
+// SocketWatcher implements SocketPerformanceWatcher, and notifies
+// NetworkQualityEstimator of various socket performance events. SocketWatcher
+// is not thread-safe.
+class NetworkQualityEstimator::SocketWatcher : public SocketPerformanceWatcher {
+ public:
+ SocketWatcher(
+ SocketPerformanceWatcherFactory::Protocol protocol,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const base::WeakPtr<NetworkQualityEstimator>& network_quality_estimator)
+ : protocol_(protocol),
+ task_runner_(std::move(task_runner)),
+ network_quality_estimator_(network_quality_estimator) {}
+
+ ~SocketWatcher() override {}
+
+ // SocketPerformanceWatcher implementation:
+ bool ShouldNotifyUpdatedRTT() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ return true;
+ }
+
+ void OnUpdatedRTTAvailable(const base::TimeDelta& rtt) override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ task_runner_->PostTask(
+ FROM_HERE, base::Bind(&NetworkQualityEstimator::OnUpdatedRTTAvailable,
+ network_quality_estimator_, protocol_, rtt));
+ }
+
+ void OnConnectionChanged() override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ }
+
+ private:
+ // Transport layer protocol used by the socket that |this| is watching.
+ const SocketPerformanceWatcherFactory::Protocol protocol_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ base::WeakPtr<NetworkQualityEstimator> network_quality_estimator_;
+
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(SocketWatcher);
+};
+
+// SocketWatcherFactory implements SocketPerformanceWatcherFactory, and is
+// owned by NetworkQualityEstimator. SocketWatcherFactory is thread safe.
+class NetworkQualityEstimator::SocketWatcherFactory
+ : public SocketPerformanceWatcherFactory {
+ public:
+ SocketWatcherFactory(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const base::WeakPtr<NetworkQualityEstimator>& network_quality_estimator)
+ : task_runner_(std::move(task_runner)),
+ network_quality_estimator_(network_quality_estimator) {}
+
+ ~SocketWatcherFactory() override {}
+
+ // SocketPerformanceWatcherFactory implementation:
+ scoped_ptr<SocketPerformanceWatcher> CreateSocketPerformanceWatcher(
+ const Protocol protocol) override {
+ return scoped_ptr<SocketPerformanceWatcher>(
+ new SocketWatcher(protocol, task_runner_, network_quality_estimator_));
+ }
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ base::WeakPtr<NetworkQualityEstimator> network_quality_estimator_;
+
+ DISALLOW_COPY_AND_ASSIGN(SocketWatcherFactory);
+};
+
const int32_t NetworkQualityEstimator::kInvalidThroughput = 0;
NetworkQualityEstimator::NetworkQualityEstimator(
@@ -140,8 +218,9 @@ NetworkQualityEstimator::NetworkQualityEstimator(
std::string())),
downstream_throughput_kbps_observations_(
GetWeightMultiplierPerSecond(variation_params)),
- rtt_msec_observations_(GetWeightMultiplierPerSecond(variation_params)),
- external_estimate_provider_(std::move(external_estimates_provider)) {
+ rtt_observations_(GetWeightMultiplierPerSecond(variation_params)),
+ external_estimate_provider_(std::move(external_estimates_provider)),
+ weak_ptr_factory_(this) {
static_assert(kMinRequestDurationMicroseconds > 0,
"Minimum request duration must be > 0");
static_assert(kDefaultHalfLifeSeconds > 0,
@@ -166,6 +245,9 @@ NetworkQualityEstimator::NetworkQualityEstimator(
}
current_network_id_ = GetCurrentNetworkID();
AddDefaultEstimates();
+
+ watcher_factory_.reset(new SocketWatcherFactory(
+ base::ThreadTaskRunnerHandle::Get(), weak_ptr_factory_.GetWeakPtr()));
}
// static
@@ -216,15 +298,15 @@ void NetworkQualityEstimator::ObtainOperatingParams(
void NetworkQualityEstimator::AddDefaultEstimates() {
DCHECK(thread_checker_.CalledOnValidThread());
if (default_observations_[current_network_id_.type].rtt() != InvalidRTT()) {
- Observation rtt_observation(
- default_observations_[current_network_id_.type].rtt().InMilliseconds(),
+ RttObservation rtt_observation(
+ default_observations_[current_network_id_.type].rtt(),
base::TimeTicks::Now(), DEFAULT_FROM_PLATFORM);
- rtt_msec_observations_.AddObservation(rtt_observation);
+ rtt_observations_.AddObservation(rtt_observation);
NotifyObserversOfRTT(rtt_observation);
}
if (default_observations_[current_network_id_.type]
.downstream_throughput_kbps() != kInvalidThroughput) {
- Observation throughput_observation(
+ ThroughputObservation throughput_observation(
default_observations_[current_network_id_.type]
.downstream_throughput_kbps(),
base::TimeTicks::Now(), DEFAULT_FROM_PLATFORM);
@@ -240,6 +322,8 @@ NetworkQualityEstimator::~NetworkQualityEstimator() {
}
void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "NetworkQualityEstimator::NotifyHeadersReceived");
DCHECK(thread_checker_.CalledOnValidThread());
if (!RequestProvidesUsefulObservations(request))
@@ -248,7 +332,7 @@ void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) {
// Update |estimated_median_network_quality_| if this is a main frame request.
if (request.load_flags() & LOAD_MAIN_FRAME) {
estimated_median_network_quality_ = NetworkQuality(
- GetRTTEstimateInternal(base::TimeTicks(), 50),
+ GetURLRequestRTTEstimateInternal(base::TimeTicks(), 50),
GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50));
}
@@ -278,9 +362,8 @@ void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) {
observed_rtt, peak_network_quality_.downstream_throughput_kbps());
}
- Observation rtt_observation(observed_rtt.InMilliseconds(), now,
- URL_REQUEST);
- rtt_msec_observations_.AddObservation(rtt_observation);
+ RttObservation rtt_observation(observed_rtt, now, URL_REQUEST);
+ rtt_observations_.AddObservation(rtt_observation);
NotifyObserversOfRTT(rtt_observation);
// Compare the RTT observation with the estimated value and record it.
@@ -292,6 +375,8 @@ void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) {
void NetworkQualityEstimator::NotifyRequestCompleted(
const URLRequest& request) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "NetworkQualityEstimator::NotifyRequestCompleted");
DCHECK(thread_checker_.CalledOnValidThread());
if (!RequestProvidesUsefulObservations(request))
@@ -348,8 +433,8 @@ void NetworkQualityEstimator::NotifyRequestCompleted(
peak_network_quality_ =
NetworkQuality(peak_network_quality_.rtt(), downstream_kbps_as_integer);
- Observation throughput_observation(downstream_kbps_as_integer, now,
- URL_REQUEST);
+ ThroughputObservation throughput_observation(downstream_kbps_as_integer, now,
+ URL_REQUEST);
downstream_throughput_kbps_observations_.AddObservation(
throughput_observation);
NotifyObserversOfThroughput(throughput_observation);
@@ -377,6 +462,13 @@ void NetworkQualityEstimator::RemoveThroughputObserver(
throughput_observer_list_.RemoveObserver(throughput_observer);
}
+SocketPerformanceWatcherFactory*
+NetworkQualityEstimator::GetSocketPerformanceWatcherFactory() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ return watcher_factory_.get();
+}
+
void NetworkQualityEstimator::RecordRTTUMA(int32_t estimated_value_msec,
int32_t actual_value_msec) const {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -519,7 +611,7 @@ void NetworkQualityEstimator::OnConnectionTypeChanged(
}
}
- base::TimeDelta rtt = GetRTTEstimateInternal(base::TimeTicks(), 50);
+ base::TimeDelta rtt = GetURLRequestRTTEstimateInternal(base::TimeTicks(), 50);
if (rtt != InvalidRTT()) {
// Add the 50th percentile value.
base::HistogramBase* rtt_percentile =
@@ -530,7 +622,8 @@ void NetworkQualityEstimator::OnConnectionTypeChanged(
// Add the remaining percentile values.
static const int kPercentiles[] = {0, 10, 90, 100};
for (size_t i = 0; i < arraysize(kPercentiles); ++i) {
- rtt = GetRTTEstimateInternal(base::TimeTicks(), kPercentiles[i]);
+ rtt =
+ GetURLRequestRTTEstimateInternal(base::TimeTicks(), kPercentiles[i]);
rtt_percentile = GetHistogram(
"RTT.Percentile" + base::IntToString(kPercentiles[i]) + ".",
@@ -546,7 +639,7 @@ void NetworkQualityEstimator::OnConnectionTypeChanged(
last_connection_change_ = base::TimeTicks::Now();
peak_network_quality_ = NetworkQuality();
downstream_throughput_kbps_observations_.Clear();
- rtt_msec_observations_.Clear();
+ rtt_observations_.Clear();
current_network_id_ = GetCurrentNetworkID();
QueryExternalEstimateProvider();
@@ -558,14 +651,15 @@ void NetworkQualityEstimator::OnConnectionTypeChanged(
estimated_median_network_quality_ = NetworkQuality();
}
-bool NetworkQualityEstimator::GetRTTEstimate(base::TimeDelta* rtt) const {
+bool NetworkQualityEstimator::GetURLRequestRTTEstimate(
+ base::TimeDelta* rtt) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(rtt);
- if (rtt_msec_observations_.Size() == 0) {
+ if (rtt_observations_.Size() == 0) {
*rtt = InvalidRTT();
return false;
}
- *rtt = GetRTTEstimateInternal(base::TimeTicks(), 50);
+ *rtt = GetURLRequestRTTEstimateInternal(base::TimeTicks(), 50);
return (*rtt != InvalidRTT());
}
@@ -581,12 +675,12 @@ bool NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate(
return (*kbps != kInvalidThroughput);
}
-bool NetworkQualityEstimator::GetRecentMedianRTT(
+bool NetworkQualityEstimator::GetRecentURLRequestRTTMedian(
const base::TimeTicks& begin_timestamp,
base::TimeDelta* rtt) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(rtt);
- *rtt = GetRTTEstimateInternal(begin_timestamp, 50);
+ *rtt = GetURLRequestRTTEstimateInternal(begin_timestamp, 50);
return (*rtt != InvalidRTT());
}
@@ -599,18 +693,8 @@ bool NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps(
return (*kbps != kInvalidThroughput);
}
-NetworkQualityEstimator::Observation::Observation(int32_t value,
- base::TimeTicks timestamp,
- ObservationSource source)
- : value(value), timestamp(timestamp), source(source) {
- DCHECK_GE(value, 0);
- DCHECK(!timestamp.is_null());
-}
-
-NetworkQualityEstimator::Observation::~Observation() {
-}
-
-NetworkQualityEstimator::ObservationBuffer::ObservationBuffer(
+template <typename ValueType>
+NetworkQualityEstimator::ObservationBuffer<ValueType>::ObservationBuffer(
double weight_multiplier_per_second)
: weight_multiplier_per_second_(weight_multiplier_per_second) {
static_assert(kMaximumObservationsBufferSize > 0U,
@@ -619,48 +703,26 @@ NetworkQualityEstimator::ObservationBuffer::ObservationBuffer(
DCHECK_LE(weight_multiplier_per_second_, 1.0);
}
-NetworkQualityEstimator::ObservationBuffer::~ObservationBuffer() {
-}
-
-void NetworkQualityEstimator::ObservationBuffer::AddObservation(
- const Observation& observation) {
- DCHECK_LE(observations_.size(),
- static_cast<size_t>(kMaximumObservationsBufferSize));
- // Evict the oldest element if the buffer is already full.
- if (observations_.size() == kMaximumObservationsBufferSize)
- observations_.pop_front();
-
- observations_.push_back(observation);
- DCHECK_LE(observations_.size(),
- static_cast<size_t>(kMaximumObservationsBufferSize));
-}
-
-size_t NetworkQualityEstimator::ObservationBuffer::Size() const {
- return observations_.size();
-}
-
-void NetworkQualityEstimator::ObservationBuffer::Clear() {
- observations_.clear();
- DCHECK(observations_.empty());
-}
+template <typename ValueType>
+NetworkQualityEstimator::ObservationBuffer<ValueType>::~ObservationBuffer() {}
-base::TimeDelta NetworkQualityEstimator::GetRTTEstimateInternal(
+base::TimeDelta NetworkQualityEstimator::GetURLRequestRTTEstimateInternal(
const base::TimeTicks& begin_timestamp,
int percentile) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_GE(percentile, 0);
DCHECK_LE(percentile, 100);
- if (rtt_msec_observations_.Size() == 0)
+ if (rtt_observations_.Size() == 0)
return InvalidRTT();
// 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 = InvalidRTT();
- int32_t rtt_result = -1;
- if (rtt_msec_observations_.GetPercentile(begin_timestamp, &rtt_result,
- percentile)) {
- rtt = base::TimeDelta::FromMilliseconds(rtt_result);
- }
+ std::vector<ObservationSource> disallowed_observation_sources;
+ disallowed_observation_sources.push_back(TCP);
+ disallowed_observation_sources.push_back(QUIC);
+ rtt_observations_.GetPercentile(begin_timestamp, &rtt, percentile,
+ disallowed_observation_sources);
return rtt;
}
@@ -676,15 +738,20 @@ int32_t NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimateInternal(
// Throughput observations are sorted by kbps from slowest to fastest,
// thus a higher percentile throughput will be faster than a lower one.
int32_t kbps = kInvalidThroughput;
- downstream_throughput_kbps_observations_.GetPercentile(begin_timestamp, &kbps,
- 100 - percentile);
+ downstream_throughput_kbps_observations_.GetPercentile(
+ begin_timestamp, &kbps, 100 - percentile,
+ std::vector<ObservationSource>());
return kbps;
}
-void NetworkQualityEstimator::ObservationBuffer::ComputeWeightedObservations(
- const base::TimeTicks& begin_timestamp,
- std::vector<WeightedObservation>& weighted_observations,
- double* total_weight) const {
+template <typename ValueType>
+void NetworkQualityEstimator::ObservationBuffer<ValueType>::
+ ComputeWeightedObservations(
+ const base::TimeTicks& begin_timestamp,
+ std::vector<WeightedObservation<ValueType>>& weighted_observations,
+ double* total_weight,
+ const std::vector<ObservationSource>& disallowed_observation_sources)
+ const {
weighted_observations.clear();
double total_weight_observations = 0.0;
base::TimeTicks now = base::TimeTicks::Now();
@@ -692,13 +759,20 @@ void NetworkQualityEstimator::ObservationBuffer::ComputeWeightedObservations(
for (const auto& observation : observations_) {
if (observation.timestamp < begin_timestamp)
continue;
+ bool disallowed = false;
+ for (const auto& disallowed_source : disallowed_observation_sources) {
+ if (disallowed_source == observation.source)
+ disallowed = true;
+ }
+ if (disallowed)
+ continue;
base::TimeDelta time_since_sample_taken = now - observation.timestamp;
double weight =
pow(weight_multiplier_per_second_, time_since_sample_taken.InSeconds());
weight = std::max(DBL_MIN, std::min(1.0, weight));
weighted_observations.push_back(
- WeightedObservation(observation.value, weight));
+ WeightedObservation<ValueType>(observation.value, weight));
total_weight_observations += weight;
}
@@ -707,19 +781,22 @@ void NetworkQualityEstimator::ObservationBuffer::ComputeWeightedObservations(
*total_weight = total_weight_observations;
}
-bool NetworkQualityEstimator::ObservationBuffer::GetPercentile(
+template <typename ValueType>
+bool NetworkQualityEstimator::ObservationBuffer<ValueType>::GetPercentile(
const base::TimeTicks& begin_timestamp,
- int32_t* result,
- int percentile) const {
+ ValueType* result,
+ int percentile,
+ const std::vector<ObservationSource>& disallowed_observation_sources)
+ const {
DCHECK(result);
// Stores WeightedObservation in increasing order of value.
- std::vector<WeightedObservation> weighted_observations;
+ std::vector<WeightedObservation<ValueType>> weighted_observations;
// Total weight of all observations in |weighted_observations|.
double total_weight = 0.0;
ComputeWeightedObservations(begin_timestamp, weighted_observations,
- &total_weight);
+ &total_weight, disallowed_observation_sources);
if (weighted_observations.empty())
return false;
@@ -736,7 +813,6 @@ bool NetworkQualityEstimator::ObservationBuffer::GetPercentile(
for (const auto& weighted_observation : weighted_observations) {
cumulative_weight_seen_so_far += weighted_observation.weight;
- // TODO(tbansal): Consider interpolating between observations.
if (cumulative_weight_seen_so_far >= desired_weight) {
*result = weighted_observation.value;
return true;
@@ -817,16 +893,16 @@ bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() {
DCHECK_NE(InvalidRTT(), network_quality.rtt());
DCHECK_NE(kInvalidThroughput, network_quality.downstream_throughput_kbps());
- Observation througphput_observation(
+ ThroughputObservation througphput_observation(
network_quality.downstream_throughput_kbps(), base::TimeTicks::Now(),
CACHED_ESTIMATE);
downstream_throughput_kbps_observations_.AddObservation(
througphput_observation);
NotifyObserversOfThroughput(througphput_observation);
- Observation rtt_observation(network_quality.rtt().InMilliseconds(),
- base::TimeTicks::Now(), CACHED_ESTIMATE);
- rtt_msec_observations_.AddObservation(rtt_observation);
+ RttObservation rtt_observation(network_quality.rtt(), base::TimeTicks::Now(),
+ CACHED_ESTIMATE);
+ rtt_observations_.AddObservation(rtt_observation);
NotifyObserversOfRTT(rtt_observation);
return true;
@@ -869,15 +945,16 @@ void NetworkQualityEstimator::QueryExternalEstimateProvider() {
EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL);
base::TimeDelta rtt;
if (external_estimate_provider_->GetRTT(&rtt)) {
- rtt_msec_observations_.AddObservation(Observation(
- rtt.InMilliseconds(), base::TimeTicks::Now(), EXTERNAL_ESTIMATE));
+ rtt_observations_.AddObservation(
+ RttObservation(rtt, base::TimeTicks::Now(), EXTERNAL_ESTIMATE));
}
int32_t downstream_throughput_kbps;
if (external_estimate_provider_->GetDownstreamThroughputKbps(
&downstream_throughput_kbps)) {
- downstream_throughput_kbps_observations_.AddObservation(Observation(
- downstream_throughput_kbps, base::TimeTicks::Now(), EXTERNAL_ESTIMATE));
+ downstream_throughput_kbps_observations_.AddObservation(
+ ThroughputObservation(downstream_throughput_kbps,
+ base::TimeTicks::Now(), EXTERNAL_ESTIMATE));
}
}
@@ -891,7 +968,7 @@ void NetworkQualityEstimator::CacheNetworkQualityEstimate() {
return;
NetworkQuality network_quality = NetworkQuality(
- GetRTTEstimateInternal(base::TimeTicks(), 50),
+ GetURLRequestRTTEstimateInternal(base::TimeTicks(), 50),
GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50));
if (network_quality.rtt() == InvalidRTT() ||
network_quality.downstream_throughput_kbps() == kInvalidThroughput) {
@@ -920,28 +997,17 @@ void NetworkQualityEstimator::CacheNetworkQualityEstimate() {
static_cast<size_t>(kMaximumNetworkQualityCacheSize));
}
-scoped_ptr<SocketPerformanceWatcher>
-NetworkQualityEstimator::CreateSocketPerformanceWatcher(
- const Protocol protocol) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- return scoped_ptr<SocketPerformanceWatcher>(
- new SocketPerformanceWatcher(protocol, this));
-}
-
void NetworkQualityEstimator::OnUpdatedRTTAvailable(
- const Protocol protocol,
+ SocketPerformanceWatcherFactory::Protocol protocol,
const base::TimeDelta& rtt) {
DCHECK(thread_checker_.CalledOnValidThread());
switch (protocol) {
- case PROTOCOL_TCP:
- NotifyObserversOfRTT(
- Observation(rtt.InMilliseconds(), base::TimeTicks::Now(), TCP));
+ case SocketPerformanceWatcherFactory::PROTOCOL_TCP:
+ NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), TCP));
return;
- case PROTOCOL_QUIC:
- NotifyObserversOfRTT(
- Observation(rtt.InMilliseconds(), base::TimeTicks::Now(), QUIC));
+ case SocketPerformanceWatcherFactory::PROTOCOL_QUIC:
+ NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), QUIC));
return;
default:
NOTREACHED();
@@ -949,14 +1015,15 @@ void NetworkQualityEstimator::OnUpdatedRTTAvailable(
}
void NetworkQualityEstimator::NotifyObserversOfRTT(
- const Observation& observation) {
- FOR_EACH_OBSERVER(RTTObserver, rtt_observer_list_,
- OnRTTObservation(observation.value, observation.timestamp,
- observation.source));
+ const RttObservation& observation) {
+ FOR_EACH_OBSERVER(
+ RTTObserver, rtt_observer_list_,
+ OnRTTObservation(observation.value.InMilliseconds(),
+ observation.timestamp, observation.source));
}
void NetworkQualityEstimator::NotifyObserversOfThroughput(
- const Observation& observation) {
+ const ThroughputObservation& observation) {
FOR_EACH_OBSERVER(
ThroughputObserver, throughput_observer_list_,
OnThroughputObservation(observation.value, observation.timestamp,
diff --git a/chromium/net/base/network_quality_estimator.h b/chromium/net/base/network_quality_estimator.h
index ad10d3249b2..5ff9bd73540 100644
--- a/chromium/net/base/network_quality_estimator.h
+++ b/chromium/net/base/network_quality_estimator.h
@@ -17,15 +17,19 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "net/base/external_estimate_provider.h"
#include "net/base/net_export.h"
#include "net/base/network_change_notifier.h"
-#include "net/base/socket_performance_watcher.h"
#include "net/base/socket_performance_watcher_factory.h"
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
namespace net {
class URLRequest;
@@ -40,8 +44,7 @@ class URLRequest;
// observed traffic characteristics.
class NET_EXPORT_PRIVATE NetworkQualityEstimator
: public NetworkChangeNotifier::ConnectionTypeObserver,
- public ExternalEstimateProvider::UpdatedEstimateDelegate,
- public SocketPerformanceWatcherFactory {
+ public ExternalEstimateProvider::UpdatedEstimateDelegate {
public:
// On Android, a Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net
@@ -130,12 +133,15 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
~NetworkQualityEstimator() override;
- // Returns true if RTT is available and sets |rtt| to estimated RTT.
- // Virtualized for testing. |rtt| should not be null.
- virtual bool GetRTTEstimate(base::TimeDelta* rtt) const;
+ // Returns true if RTT is available and sets |rtt| to estimated RTT at the
+ // HTTP layer. Virtualized for testing. |rtt| should not be null. The RTT at
+ // the HTTP layer measures the time from when the request was sent (this
+ // happens after the connection is established) to the time when the response
+ // headers were received.
+ virtual bool GetURLRequestRTTEstimate(base::TimeDelta* rtt) const;
// Returns true if downlink throughput is available and sets |kbps| to
- // estimated downlink throughput (in Kilobits per second).
+ // estimated downlink throughput (in kilobits per second).
// Virtualized for testing. |kbps| should not be null.
virtual bool GetDownlinkThroughputKbpsEstimate(int32_t* kbps) const;
@@ -147,25 +153,24 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// been received.
void NotifyRequestCompleted(const URLRequest& request);
- // Returns true if median RTT is available and sets |rtt| to the median of
- // RTT observations since |begin_timestamp|.
- // Virtualized for testing. |rtt| should not be null.
- virtual bool GetRecentMedianRTT(const base::TimeTicks& begin_timestamp,
- base::TimeDelta* rtt) const;
+ // Returns true if median RTT at the HTTP layer is available and sets |rtt|
+ // to the median of RTT observations since |begin_timestamp|.
+ // Virtualized for testing. |rtt| should not be null. The RTT at the HTTP
+ // layer measures the time from when the request was sent (this happens after
+ // the connection is established) to the time when the response headers were
+ // received.
+ virtual bool GetRecentURLRequestRTTMedian(
+ const base::TimeTicks& begin_timestamp,
+ base::TimeDelta* rtt) const;
// Returns true if median downstream throughput is available and sets |kbps|
- // to the median of downstream Kbps observations since |begin_timestamp|.
- // Virtualized for testing. |kbps| should not be null.
+ // to the median of downstream throughput (in kilobits per second)
+ // observations since |begin_timestamp|. Virtualized for testing. |kbps|
+ // should not be null.
virtual bool GetRecentMedianDownlinkThroughputKbps(
const base::TimeTicks& begin_timestamp,
int32_t* kbps) const;
- // SocketPerformanceWatcherFactory implementation:
- scoped_ptr<SocketPerformanceWatcher> CreateSocketPerformanceWatcher(
- const Protocol protocol) override;
- void OnUpdatedRTTAvailable(const Protocol protocol,
- const base::TimeDelta& rtt) override;
-
// Adds |rtt_observer| to the list of round trip time observers. Must be
// called on the IO thread.
void AddRTTObserver(RTTObserver* rtt_observer);
@@ -182,6 +187,8 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// is on the list of observers. Must be called on the IO thread.
void RemoveThroughputObserver(ThroughputObserver* throughput_observer);
+ SocketPerformanceWatcherFactory* GetSocketPerformanceWatcherFactory();
+
protected:
// NetworkID is used to uniquely identify a network.
// For the purpose of network quality estimation and caching, a network is
@@ -250,7 +257,9 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
TestExternalEstimateProvider);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
TestExternalEstimateProviderMergeEstimates);
- FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestObservers);
+
+ class SocketWatcher;
+ class SocketWatcherFactory;
// NetworkQuality is used to cache the quality of a network connection.
class NET_EXPORT_PRIVATE NetworkQuality {
@@ -258,7 +267,7 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
NetworkQuality();
// |rtt| is the estimate of the round trip time.
// |downstream_throughput_kbps| is the estimate of the downstream
- // throughput.
+ // throughput in kilobits per second.
NetworkQuality(const base::TimeDelta& rtt,
int32_t downstream_throughput_kbps);
NetworkQuality(const NetworkQuality& other);
@@ -269,7 +278,7 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// Returns the estimate of the round trip time.
const base::TimeDelta& rtt() const { return rtt_; }
- // Returns the estimate of the downstream throughput in Kbps (Kilo bits per
+ // Returns the estimate of the downstream throughput in Kbps (Kilobits per
// second).
int32_t downstream_throughput_kbps() const {
return downstream_throughput_kbps_;
@@ -279,7 +288,7 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// Estimated round trip time.
base::TimeDelta rtt_;
- // Estimated downstream throughput in Kbps.
+ // Estimated downstream throughput in kilobits per second.
int32_t downstream_throughput_kbps_;
};
@@ -307,20 +316,23 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
DISALLOW_ASSIGN(CachedNetworkQuality);
};
- // Records the round trip time or throughput observation, along with the time
- // the observation was made. The units of value are type specific. For round
- // trip time observations, the value is in milliseconds. For throughput,
- // the value is in kilobits per second. Observations can be made at several
- // places in the network stack, thus the observation source is provided as
- // well.
+ // Records observations of network quality metrics (such as round trip time
+ // or throughput), along with the time the observation was made. Observations
+ // can be made at several places in the network stack, thus the observation
+ // source is provided as well. ValueType must be numerical so that statistics
+ // such as median, average can be computed.
+ template <typename ValueType>
struct NET_EXPORT_PRIVATE Observation {
- Observation(int32_t value,
+ Observation(const ValueType& value,
base::TimeTicks timestamp,
- ObservationSource source);
- ~Observation();
+ ObservationSource source)
+ : value(value), timestamp(timestamp), source(source) {
+ DCHECK(!timestamp.is_null());
+ }
+ ~Observation() {}
// Value of the observation.
- const int32_t value;
+ const ValueType value;
// Time when the observation was taken.
const base::TimeTicks timestamp;
@@ -330,8 +342,9 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
};
// Holds an observation and its weight.
+ template <typename ValueType>
struct NET_EXPORT_PRIVATE WeightedObservation {
- WeightedObservation(int32_t value, double weight)
+ WeightedObservation(ValueType value, double weight)
: value(value), weight(weight) {}
WeightedObservation(const WeightedObservation& other)
: WeightedObservation(other.value, other.weight) {}
@@ -348,7 +361,7 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
}
// Value of the sample.
- int32_t value;
+ ValueType value;
// Weight of the sample. This is computed based on how much time has passed
// since the sample was taken.
@@ -356,6 +369,7 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
};
// Stores observations sorted by time.
+ template <typename ValueType>
class NET_EXPORT_PRIVATE ObservationBuffer {
public:
explicit ObservationBuffer(double weight_multiplier_per_second);
@@ -363,24 +377,37 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// Adds |observation| to the buffer. The oldest observation in the buffer
// will be evicted to make room if the buffer is already full.
- void AddObservation(const Observation& observation);
+ void AddObservation(const Observation<ValueType>& observation) {
+ DCHECK_LE(observations_.size(),
+ static_cast<size_t>(kMaximumObservationsBufferSize));
+ // Evict the oldest element if the buffer is already full.
+ if (observations_.size() == kMaximumObservationsBufferSize)
+ observations_.pop_front();
+
+ observations_.push_back(observation);
+ DCHECK_LE(observations_.size(),
+ static_cast<size_t>(kMaximumObservationsBufferSize));
+ }
// Returns the number of observations in this buffer.
- size_t Size() const;
+ size_t Size() const { return observations_.size(); }
// Clears the observations stored in this buffer.
- void Clear();
+ void Clear() { observations_.clear(); }
// Returns true iff the |percentile| value of the observations in this
// buffer is available. Sets |result| to the computed |percentile|
// value among all observations since |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|.
- // |result| must not be null.
+ // than |begin_timestamp|. |result| must not be null.
+ // |disallowed_observation_sources| is the list of observation sources that
+ // should be excluded when computing the percentile.
bool GetPercentile(const base::TimeTicks& begin_timestamp,
- int32_t* result,
- int percentile) const;
+ ValueType* result,
+ int percentile,
+ const std::vector<ObservationSource>&
+ disallowed_observation_sources) const;
private:
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations);
@@ -393,15 +420,19 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// 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.
+ // observation in the buffer. |disallowed_observation_sources| is the list
+ // of observation sources that should be excluded when computing the
+ // weighted observations.
void ComputeWeightedObservations(
const base::TimeTicks& begin_timestamp,
- std::vector<WeightedObservation>& weighted_observations,
- double* total_weight) const;
+ std::vector<WeightedObservation<ValueType>>& weighted_observations,
+ double* total_weight,
+ const std::vector<ObservationSource>& disallowed_observation_sources)
+ const;
// Holds observations sorted by time, with the oldest observation at the
// front of the queue.
- std::deque<Observation> observations_;
+ std::deque<Observation<ValueType>> observations_;
// The factor by which the weight of an observation reduces every second.
// For example, if an observation is 6 seconds old, its weight would be:
@@ -413,6 +444,18 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
DISALLOW_COPY_AND_ASSIGN(ObservationBuffer);
};
+ // Value of round trip time observations is in base::TimeDelta.
+ typedef net::NetworkQualityEstimator::Observation<base::TimeDelta>
+ RttObservation;
+ typedef net::NetworkQualityEstimator::ObservationBuffer<base::TimeDelta>
+ RttObservationBuffer;
+
+ // Value of throughput observations is in kilobits per second.
+ typedef net::NetworkQualityEstimator::Observation<int32_t>
+ ThroughputObservation;
+ typedef net::NetworkQualityEstimator::ObservationBuffer<int32_t>
+ ThroughputObservationBuffer;
+
// This does not use a unordered_map or hash_map for code simplicity (key just
// implements operator<, rather than hash and equality) and because the map is
// tiny.
@@ -436,7 +479,7 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
static const int kMinimumRTTVariationParameterMsec = 1;
// Minimum valid value of the variation parameter that holds throughput (in
- // kbps) values.
+ // kilobits per second) values.
static const int kMinimumThroughputVariationParameterKbps = 1;
// Maximum size of the cache that holds network quality estimates.
@@ -456,6 +499,10 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// should discard RTT if it is set to the value returned by |InvalidRTT()|.
static const base::TimeDelta InvalidRTT();
+ // Notifies |this| of a new transport layer RTT.
+ void OnUpdatedRTTAvailable(SocketPerformanceWatcherFactory::Protocol protocol,
+ const base::TimeDelta& rtt);
+
// Queries the external estimate provider for the latest network quality
// estimates, and adds those estimates to the current observation buffer.
void QueryExternalEstimateProvider();
@@ -475,8 +522,9 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// |percentile| is 90, then the network is expected to be faster than the
// returned estimate with 0.9 probability. Similarly, network is expected to
// be slower than the returned estimate with 0.1 probability.
- base::TimeDelta GetRTTEstimateInternal(const base::TimeTicks& begin_timestamp,
- int percentile) const;
+ base::TimeDelta GetURLRequestRTTEstimateInternal(
+ const base::TimeTicks& begin_timestamp,
+ int percentile) const;
int32_t GetDownlinkThroughputKbpsEstimateInternal(
const base::TimeTicks& begin_timestamp,
int percentile) const;
@@ -488,9 +536,9 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// Writes the estimated quality of the current network to the cache.
void CacheNetworkQualityEstimate();
- void NotifyObserversOfRTT(const Observation& observation);
+ void NotifyObserversOfRTT(const RttObservation& observation);
- void NotifyObserversOfThroughput(const Observation& observation);
+ void NotifyObserversOfThroughput(const ThroughputObservation& observation);
// Records the UMA related to RTT.
void RecordRTTUMA(int32_t estimated_value_msec,
@@ -543,11 +591,12 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// Cache that stores quality of previously seen networks.
CachedNetworkQualities cached_network_qualities_;
- // Buffer that holds Kbps observations sorted by timestamp.
- ObservationBuffer downstream_throughput_kbps_observations_;
+ // Buffer that holds throughput observations (in kilobits per second) sorted
+ // by timestamp.
+ ThroughputObservationBuffer downstream_throughput_kbps_observations_;
- // Buffer that holds RTT (in milliseconds) observations sorted by timestamp.
- ObservationBuffer rtt_msec_observations_;
+ // Buffer that holds RTT observations sorted by timestamp.
+ RttObservationBuffer rtt_observations_;
// Default network quality observations obtained from the network quality
// estimator field trial parameters. The observations are indexed by
@@ -566,8 +615,12 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
base::ObserverList<RTTObserver> rtt_observer_list_;
base::ObserverList<ThroughputObserver> throughput_observer_list_;
+ scoped_ptr<SocketPerformanceWatcherFactory> watcher_factory_;
+
base::ThreadChecker thread_checker_;
+ base::WeakPtrFactory<NetworkQualityEstimator> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(NetworkQualityEstimator);
};
diff --git a/chromium/net/base/network_quality_estimator_unittest.cc b/chromium/net/base/network_quality_estimator_unittest.cc
index cf1197f501a..13d35b1b1a0 100644
--- a/chromium/net/base/network_quality_estimator_unittest.cc
+++ b/chromium/net/base/network_quality_estimator_unittest.cc
@@ -5,8 +5,10 @@
#include "net/base/network_quality_estimator.h"
#include <stdint.h>
+
#include <limits>
#include <map>
+#include <string>
#include <utility>
#include <vector>
@@ -23,10 +25,13 @@
#include "net/base/external_estimate_provider.h"
#include "net/base/load_flags.h"
#include "net/base/network_change_notifier.h"
+#include "net/base/socket_performance_watcher.h"
+#include "net/base/socket_performance_watcher_factory.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
+#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -168,7 +173,7 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) {
TestNetworkQualityEstimator estimator(variation_params);
EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(),
- estimator.GetRTTEstimateInternal(base::TimeTicks(), 100));
+ estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 100));
EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput,
estimator.GetDownlinkThroughputKbpsEstimateInternal(
base::TimeTicks(), 100));
@@ -186,22 +191,22 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) {
// Both RTT and downstream throughput should be updated.
EXPECT_NE(NetworkQualityEstimator::InvalidRTT(),
- estimator.GetRTTEstimateInternal(base::TimeTicks(), 100));
+ estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 100));
EXPECT_NE(NetworkQualityEstimator::kInvalidThroughput,
estimator.GetDownlinkThroughputKbpsEstimateInternal(
base::TimeTicks(), 100));
base::TimeDelta rtt = NetworkQualityEstimator::InvalidRTT();
int32_t kbps = NetworkQualityEstimator::kInvalidThroughput;
- EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
EXPECT_NE(NetworkQualityEstimator::InvalidRTT(), rtt);
EXPECT_NE(NetworkQualityEstimator::kInvalidThroughput, kbps);
- EXPECT_NEAR(
- rtt.InMilliseconds(),
- estimator.GetRTTEstimateInternal(base::TimeTicks(), 100).InMilliseconds(),
- 1);
+ EXPECT_NEAR(rtt.InMilliseconds(),
+ estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 100)
+ .InMilliseconds(),
+ 1);
// Check UMA histograms.
histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 0);
@@ -230,12 +235,12 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) {
histogram_tester.ExpectTotalCount("NQE.RTT.Percentile100.Unknown", 1);
EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(),
- estimator.GetRTTEstimateInternal(base::TimeTicks(), 100));
+ estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 100));
EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput,
estimator.GetDownlinkThroughputKbpsEstimateInternal(
base::TimeTicks(), 100));
- EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(), rtt);
EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput, kbps);
@@ -246,12 +251,12 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) {
histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 1);
EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(),
- estimator.GetRTTEstimateInternal(base::TimeTicks(), 100));
+ estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 100));
EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput,
estimator.GetDownlinkThroughputKbpsEstimateInternal(
base::TimeTicks(), 100));
- EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
}
@@ -277,13 +282,13 @@ TEST(NetworkQualityEstimatorTest, StoreObservations) {
estimator.downstream_throughput_kbps_observations_.Size());
EXPECT_EQ(static_cast<size_t>(
NetworkQualityEstimator::kMaximumObservationsBufferSize),
- estimator.rtt_msec_observations_.Size());
+ estimator.rtt_observations_.Size());
// Verify that the stored observations are cleared on network change.
estimator.SimulateNetworkChangeTo(
NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-2");
EXPECT_EQ(0U, estimator.downstream_throughput_kbps_observations_.Size());
- EXPECT_EQ(0U, estimator.rtt_msec_observations_.Size());
+ EXPECT_EQ(0U, estimator.rtt_observations_.Size());
}
// Verifies that the percentiles are correctly computed. All observations have
@@ -296,7 +301,7 @@ TEST(NetworkQualityEstimatorTest, PercentileSameTimestamps) {
// Network quality should be unavailable when no observations are available.
base::TimeDelta rtt;
- EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt));
int32_t kbps;
EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
@@ -304,23 +309,41 @@ TEST(NetworkQualityEstimatorTest, PercentileSameTimestamps) {
// samples. This helps in verifying that the order of samples does not matter.
for (int i = 1; i <= 99; i += 2) {
estimator.downstream_throughput_kbps_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
- i, now, NetworkQualityEstimator::URL_REQUEST));
- estimator.rtt_msec_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
+ NetworkQualityEstimator::ThroughputObservation(
i, now, NetworkQualityEstimator::URL_REQUEST));
- EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(i), now,
+ NetworkQualityEstimator::URL_REQUEST));
+ EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
}
+ for (int i = 1; i <= 99; i += 2) {
+ // Insert TCP observation which should not be taken into account when
+ // computing median RTT at HTTP layer.
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(10000), now,
+ NetworkQualityEstimator::TCP));
+
+ // Insert QUIC observation which should not be taken into account when
+ // computing median RTT at HTTP layer.
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(10000), now,
+ NetworkQualityEstimator::QUIC));
+ }
+
for (int i = 2; i <= 100; i += 2) {
estimator.downstream_throughput_kbps_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
- i, now, NetworkQualityEstimator::URL_REQUEST));
- estimator.rtt_msec_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
+ NetworkQualityEstimator::ThroughputObservation(
i, now, NetworkQualityEstimator::URL_REQUEST));
- EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(i), now,
+ NetworkQualityEstimator::URL_REQUEST));
+ EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
}
@@ -332,18 +355,19 @@ TEST(NetworkQualityEstimatorTest, PercentileSameTimestamps) {
EXPECT_NEAR(estimator.GetDownlinkThroughputKbpsEstimateInternal(
base::TimeTicks(), i),
100 - i, 1);
- EXPECT_NEAR(
- estimator.GetRTTEstimateInternal(base::TimeTicks(), i).InMilliseconds(),
- i, 1);
+ EXPECT_NEAR(estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), i)
+ .InMilliseconds(),
+ i, 1);
}
- EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
// |network_quality| should be equal to the 50 percentile value.
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimateInternal(
base::TimeTicks(), 50) > 0);
- EXPECT_TRUE(estimator.GetRTTEstimateInternal(base::TimeTicks(), 50) !=
- NetworkQualityEstimator::InvalidRTT());
+ EXPECT_TRUE(
+ estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 50) !=
+ NetworkQualityEstimator::InvalidRTT());
}
// Verifies that the percentiles are correctly computed. Observations have
@@ -355,26 +379,28 @@ TEST(NetworkQualityEstimatorTest, PercentileDifferentTimestamps) {
std::map<std::string, std::string> variation_params;
TestNetworkQualityEstimator estimator(variation_params);
base::TimeTicks now = base::TimeTicks::Now();
- base::TimeTicks very_old = base::TimeTicks::UnixEpoch();
+ base::TimeTicks very_old = now - base::TimeDelta::FromDays(365);
// First 50 samples have very old timestamp.
for (int i = 1; i <= 50; ++i) {
estimator.downstream_throughput_kbps_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
- i, very_old, NetworkQualityEstimator::URL_REQUEST));
- estimator.rtt_msec_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
+ NetworkQualityEstimator::ThroughputObservation(
i, very_old, NetworkQualityEstimator::URL_REQUEST));
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(i), very_old,
+ NetworkQualityEstimator::URL_REQUEST));
}
// Next 50 (i.e., from 51 to 100) have recent timestamp.
for (int i = 51; i <= 100; ++i) {
estimator.downstream_throughput_kbps_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
- i, now, NetworkQualityEstimator::URL_REQUEST));
- estimator.rtt_msec_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
+ NetworkQualityEstimator::ThroughputObservation(
i, now, NetworkQualityEstimator::URL_REQUEST));
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(i), now,
+ NetworkQualityEstimator::URL_REQUEST));
}
// Older samples have very little weight. So, all percentiles are >= 51
@@ -387,13 +413,13 @@ TEST(NetworkQualityEstimatorTest, PercentileDifferentTimestamps) {
EXPECT_NEAR(estimator.GetDownlinkThroughputKbpsEstimateInternal(
base::TimeTicks(), i),
51 + 0.49 * (100 - i), 1);
- EXPECT_NEAR(
- estimator.GetRTTEstimateInternal(base::TimeTicks(), i).InMilliseconds(),
- 51 + 0.49 * i, 1);
+ EXPECT_NEAR(estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), i)
+ .InMilliseconds(),
+ 51 + 0.49 * i, 1);
}
EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(),
- estimator.GetRTTEstimateInternal(
+ estimator.GetURLRequestRTTEstimateInternal(
base::TimeTicks::Now() + base::TimeDelta::FromMinutes(10), 50));
EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput,
estimator.GetDownlinkThroughputKbpsEstimateInternal(
@@ -408,7 +434,7 @@ TEST(NetworkQualityEstimatorTest, ComputedPercentiles) {
TestNetworkQualityEstimator estimator(variation_params);
EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(),
- estimator.GetRTTEstimateInternal(base::TimeTicks(), 100));
+ estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 100));
EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput,
estimator.GetDownlinkThroughputKbpsEstimateInternal(
base::TimeTicks(), 100));
@@ -431,7 +457,7 @@ TEST(NetworkQualityEstimatorTest, ComputedPercentiles) {
EXPECT_GT(estimator.GetDownlinkThroughputKbpsEstimateInternal(
base::TimeTicks(), i),
0);
- EXPECT_LT(estimator.GetRTTEstimateInternal(base::TimeTicks(), i),
+ EXPECT_LT(estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), i),
base::TimeDelta::Max());
if (i != 0) {
@@ -442,8 +468,9 @@ TEST(NetworkQualityEstimatorTest, ComputedPercentiles) {
base::TimeTicks(), i - 1));
// RTT percentiles are in increasing order.
- EXPECT_GE(estimator.GetRTTEstimateInternal(base::TimeTicks(), i),
- estimator.GetRTTEstimateInternal(base::TimeTicks(), i - 1));
+ EXPECT_GE(
+ estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), i),
+ estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), i - 1));
}
}
}
@@ -461,36 +488,37 @@ TEST(NetworkQualityEstimatorTest, ObtainOperatingParams) {
TestNetworkQualityEstimator estimator(variation_params);
EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size());
- EXPECT_EQ(1U, estimator.rtt_msec_observations_.Size());
+ EXPECT_EQ(1U, estimator.rtt_observations_.Size());
base::TimeDelta rtt;
- EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt));
int32_t kbps;
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
EXPECT_EQ(100, kbps);
EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), rtt);
- auto it =
+ auto throughput_iterator =
estimator.downstream_throughput_kbps_observations_.observations_.begin();
- EXPECT_EQ(100, (*it).value);
- it = estimator.rtt_msec_observations_.observations_.begin();
- EXPECT_EQ(1000, (*it).value);
+ EXPECT_EQ(100, (*throughput_iterator).value);
+ auto rtt_iterator = estimator.rtt_observations_.observations_.begin();
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), (*rtt_iterator).value);
// Simulate network change to Wi-Fi.
estimator.SimulateNetworkChangeTo(
NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size());
- EXPECT_EQ(1U, estimator.rtt_msec_observations_.Size());
+ EXPECT_EQ(1U, estimator.rtt_observations_.Size());
- EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
EXPECT_EQ(200, kbps);
EXPECT_EQ(base::TimeDelta::FromMilliseconds(2000), rtt);
- it = estimator.downstream_throughput_kbps_observations_.observations_.begin();
- EXPECT_EQ(200, (*it).value);
- it = estimator.rtt_msec_observations_.observations_.begin();
- EXPECT_EQ(2000, (*it).value);
+ throughput_iterator =
+ estimator.downstream_throughput_kbps_observations_.observations_.begin();
+ EXPECT_EQ(200, (*throughput_iterator).value);
+ rtt_iterator = estimator.rtt_observations_.observations_.begin();
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(2000), (*rtt_iterator).value);
// Peak network quality should not be affected by the network quality
// estimator field trial.
@@ -504,22 +532,23 @@ TEST(NetworkQualityEstimatorTest, ObtainOperatingParams) {
estimator.SimulateNetworkChangeTo(
NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-2");
EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size());
- EXPECT_EQ(0U, estimator.rtt_msec_observations_.Size());
+ EXPECT_EQ(0U, estimator.rtt_observations_.Size());
- EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
- it = estimator.downstream_throughput_kbps_observations_.observations_.begin();
- EXPECT_EQ(300, (*it).value);
+ throughput_iterator =
+ estimator.downstream_throughput_kbps_observations_.observations_.begin();
+ EXPECT_EQ(300, (*throughput_iterator).value);
// Simulate network change to 3G. Default estimates should be unavailable.
estimator.SimulateNetworkChangeTo(
NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-3");
- EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
EXPECT_EQ(0U, estimator.downstream_throughput_kbps_observations_.Size());
- EXPECT_EQ(0U, estimator.rtt_msec_observations_.Size());
+ EXPECT_EQ(0U, estimator.rtt_observations_.Size());
}
TEST(NetworkQualityEstimatorTest, HalfLifeParam) {
@@ -575,11 +604,12 @@ TEST(NetworkQualityEstimatorTest, TestCaching) {
// Cache entry will not be added for (NONE, "").
estimator.downstream_throughput_kbps_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
+ NetworkQualityEstimator::ThroughputObservation(
1, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST));
- estimator.rtt_msec_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
- 1000, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST));
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(1000), base::TimeTicks::Now(),
+ NetworkQualityEstimator::URL_REQUEST));
estimator.SimulateNetworkChangeTo(
NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-1");
EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size());
@@ -588,11 +618,12 @@ TEST(NetworkQualityEstimatorTest, TestCaching) {
// Also, set the network quality for (2G, "test1") so that it is stored in
// the cache.
estimator.downstream_throughput_kbps_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
+ NetworkQualityEstimator::ThroughputObservation(
1, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST));
- estimator.rtt_msec_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
- 1000, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST));
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(1000), base::TimeTicks::Now(),
+ NetworkQualityEstimator::URL_REQUEST));
estimator.SimulateNetworkChangeTo(
NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-1");
@@ -603,11 +634,12 @@ TEST(NetworkQualityEstimatorTest, TestCaching) {
// Also, set the network quality for (3G, "test1") so that it is stored in
// the cache.
estimator.downstream_throughput_kbps_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
+ NetworkQualityEstimator::ThroughputObservation(
2, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST));
- estimator.rtt_msec_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
- 500, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST));
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(500), base::TimeTicks::Now(),
+ NetworkQualityEstimator::URL_REQUEST));
estimator.SimulateNetworkChangeTo(
NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-2");
++expected_cache_size;
@@ -623,7 +655,7 @@ TEST(NetworkQualityEstimatorTest, TestCaching) {
base::TimeDelta rtt;
int32_t kbps;
- EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
EXPECT_EQ(1, kbps);
EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), rtt);
@@ -635,7 +667,7 @@ TEST(NetworkQualityEstimatorTest, TestCaching) {
// Read the network quality for (3G, "test-1").
EXPECT_TRUE(estimator.ReadCachedNetworkQualityEstimate());
- EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
EXPECT_EQ(2, kbps);
EXPECT_EQ(base::TimeDelta::FromMilliseconds(500), rtt);
@@ -671,11 +703,12 @@ TEST(NetworkQualityEstimatorTest, TestLRUCacheMaximumSize) {
base::TimeTicks update_time_of_network_100;
for (size_t i = 0; i < network_count; ++i) {
estimator.downstream_throughput_kbps_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
+ NetworkQualityEstimator::ThroughputObservation(
2, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST));
- estimator.rtt_msec_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
- 500, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST));
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(500), base::TimeTicks::Now(),
+ NetworkQualityEstimator::URL_REQUEST));
if (i == 100)
update_time_of_network_100 = base::TimeTicks::Now();
@@ -691,11 +724,12 @@ TEST(NetworkQualityEstimatorTest, TestLRUCacheMaximumSize) {
}
// One more call so that the last network is also written to cache.
estimator.downstream_throughput_kbps_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
+ NetworkQualityEstimator::ThroughputObservation(
2, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST));
- estimator.rtt_msec_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
- 500, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST));
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(500), base::TimeTicks::Now(),
+ NetworkQualityEstimator::URL_REQUEST));
estimator.SimulateNetworkChangeTo(
net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
base::SizeTToString(network_count - 1));
@@ -721,23 +755,25 @@ TEST(NetworkQualityEstimatorTest, TestGetMedianRTTSince) {
// First sample has very old timestamp.
estimator.downstream_throughput_kbps_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
- 1, old, NetworkQualityEstimator::URL_REQUEST));
- estimator.rtt_msec_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
+ NetworkQualityEstimator::ThroughputObservation(
1, old, NetworkQualityEstimator::URL_REQUEST));
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(1), old,
+ NetworkQualityEstimator::URL_REQUEST));
estimator.downstream_throughput_kbps_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
- 100, now, NetworkQualityEstimator::URL_REQUEST));
- estimator.rtt_msec_observations_.AddObservation(
- NetworkQualityEstimator::Observation(
+ NetworkQualityEstimator::ThroughputObservation(
100, now, NetworkQualityEstimator::URL_REQUEST));
+ estimator.rtt_observations_.AddObservation(
+ NetworkQualityEstimator::RttObservation(
+ base::TimeDelta::FromMilliseconds(100), now,
+ NetworkQualityEstimator::URL_REQUEST));
base::TimeDelta rtt;
- EXPECT_FALSE(estimator.GetRecentMedianRTT(
+ EXPECT_FALSE(estimator.GetRecentURLRequestRTTMedian(
now + base::TimeDelta::FromSeconds(10), &rtt));
- EXPECT_TRUE(estimator.GetRecentMedianRTT(now, &rtt));
+ EXPECT_TRUE(estimator.GetRecentURLRequestRTTMedian(now, &rtt));
EXPECT_EQ(100, rtt.InMilliseconds());
int32_t downstream_throughput_kbps;
@@ -813,7 +849,7 @@ TEST(NetworkQualityEstimatorTest, InvalidExternalEstimateProvider) {
base::TimeDelta rtt;
int32_t kbps;
EXPECT_EQ(1U, invalid_external_estimate_provider->get_rtt_count());
- EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
}
@@ -910,7 +946,7 @@ TEST(NetworkQualityEstimatorTest, TestExternalEstimateProvider) {
base::TimeDelta rtt;
int32_t kbps;
- EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
EXPECT_EQ(
@@ -924,7 +960,7 @@ TEST(NetworkQualityEstimatorTest, TestExternalEstimateProvider) {
// provider must increment.
estimator.SimulateNetworkChangeTo(
NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
- EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
EXPECT_EQ(
2U, test_external_estimate_provider->get_time_since_last_update_count());
@@ -962,7 +998,7 @@ TEST(NetworkQualityEstimatorTest, TestExternalEstimateProvider) {
// Estimates are unavailable because external estimate provider never
// notifies network quality estimator of the updated estimates.
- EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
}
@@ -986,14 +1022,14 @@ TEST(NetworkQualityEstimatorTest, TestExternalEstimateProviderMergeEstimates) {
base::TimeDelta rtt;
// Estimate provided by network quality estimator should match the estimate
// provided by external estimate provider.
- EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt));
EXPECT_EQ(external_estimate_provider_rtt, rtt);
int32_t kbps;
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
EXPECT_EQ(external_estimate_provider_downstream_throughput, kbps);
- EXPECT_EQ(1U, estimator.rtt_msec_observations_.Size());
+ EXPECT_EQ(1U, estimator.rtt_observations_.Size());
EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size());
TestDelegate test_delegate;
@@ -1006,7 +1042,7 @@ TEST(NetworkQualityEstimatorTest, TestExternalEstimateProviderMergeEstimates) {
request->Start();
base::RunLoop().Run();
- EXPECT_EQ(2U, estimator.rtt_msec_observations_.Size());
+ EXPECT_EQ(2U, estimator.rtt_observations_.Size());
EXPECT_EQ(2U, estimator.downstream_throughput_kbps_observations_.Size());
}
@@ -1040,11 +1076,11 @@ TEST(NetworkQualityEstimatorTest, TestObservers) {
base::RunLoop().Run();
// Both RTT and downstream throughput should be updated.
- EXPECT_NE(NetworkQualityEstimator::InvalidRTT(),
- estimator.GetRTTEstimateInternal(base::TimeTicks(), 100));
- EXPECT_NE(NetworkQualityEstimator::kInvalidThroughput,
- estimator.GetDownlinkThroughputKbpsEstimateInternal(
- base::TimeTicks(), 100));
+ base::TimeDelta rtt;
+ EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt));
+
+ int32_t throughput;
+ EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&throughput));
EXPECT_EQ(2U, rtt_observer.observations().size());
EXPECT_EQ(2U, throughput_observer.observations().size());
@@ -1064,14 +1100,20 @@ TEST(NetworkQualityEstimatorTest, TestObservers) {
base::TimeDelta quic_rtt(base::TimeDelta::FromMilliseconds(2));
scoped_ptr<SocketPerformanceWatcher> tcp_watcher =
- estimator.CreateSocketPerformanceWatcher(
- SocketPerformanceWatcherFactory::PROTOCOL_TCP);
+ estimator.GetSocketPerformanceWatcherFactory()
+ ->CreateSocketPerformanceWatcher(
+ SocketPerformanceWatcherFactory::PROTOCOL_TCP);
+
scoped_ptr<SocketPerformanceWatcher> quic_watcher =
- estimator.CreateSocketPerformanceWatcher(
- SocketPerformanceWatcherFactory::PROTOCOL_QUIC);
+ estimator.GetSocketPerformanceWatcherFactory()
+ ->CreateSocketPerformanceWatcher(
+ SocketPerformanceWatcherFactory::PROTOCOL_QUIC);
+
tcp_watcher->OnUpdatedRTTAvailable(tcp_rtt);
quic_watcher->OnUpdatedRTTAvailable(quic_rtt);
+ base::RunLoop().RunUntilIdle();
+
EXPECT_EQ(4U, rtt_observer.observations().size());
EXPECT_EQ(2U, throughput_observer.observations().size());
diff --git a/chromium/net/base/openssl_private_key_store_android.cc b/chromium/net/base/openssl_private_key_store_android.cc
index 538b4746501..424f72f477e 100644
--- a/chromium/net/base/openssl_private_key_store_android.cc
+++ b/chromium/net/base/openssl_private_key_store_android.cc
@@ -4,47 +4,47 @@
#include "net/base/openssl_private_key_store.h"
+#include <openssl/bytestring.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
-#include <openssl/x509.h>
#include "base/logging.h"
#include "base/memory/singleton.h"
+#include "crypto/auto_cbb.h"
#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
#include "net/android/network_library.h"
-#include "net/ssl/scoped_openssl_types.h"
namespace net {
-bool OpenSSLPrivateKeyStore::StoreKeyPair(const GURL& url,
- EVP_PKEY* pkey) {
+bool OpenSSLPrivateKeyStore::StoreKeyPair(const GURL& url, EVP_PKEY* pkey) {
// Always clear openssl errors on exit.
crypto::OpenSSLErrStackTracer err_trace(FROM_HERE);
- // Important: Do not use i2d_PublicKey() here, which returns data in
- // PKCS#1 format, use i2d_PUBKEY() which returns it as DER-encoded
- // SubjectPublicKeyInfo (X.509), as expected by the platform.
- unsigned char* public_key = NULL;
- int public_len = i2d_PUBKEY(pkey, &public_key);
-
- // Important: Do not use i2d_PrivateKey() here, it returns data
- // in a format that is incompatible with what the platform expects.
- unsigned char* private_key = NULL;
- int private_len = 0;
- ScopedPKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(pkey));
- if (pkcs8)
- private_len = i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), &private_key);
- bool ret = false;
- if (public_len > 0 && private_len > 0) {
- ret = android::StoreKeyPair(
- static_cast<const uint8_t*>(public_key), public_len,
- static_cast<const uint8_t*>(private_key), private_len);
+ uint8_t* public_key;
+ size_t public_len;
+ crypto::AutoCBB cbb;
+ if (!CBB_init(cbb.get(), 0) || !EVP_marshal_public_key(cbb.get(), pkey) ||
+ !CBB_finish(cbb.get(), &public_key, &public_len)) {
+ return false;
}
- LOG_IF(ERROR, !ret) << "StoreKeyPair failed. pub len = " << public_len
- << " priv len = " << private_len;
- OPENSSL_free(public_key);
- OPENSSL_free(private_key);
- return ret;
+ crypto::ScopedOpenSSLBytes 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;
+ }
+ crypto::ScopedOpenSSLBytes 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/parse_data_url_fuzzer.cc b/chromium/net/base/parse_data_url_fuzzer.cc
new file mode 100644
index 00000000000..f91b691df8c
--- /dev/null
+++ b/chromium/net/base/parse_data_url_fuzzer.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 <stddef.h>
+#include <stdint.h>
+
+#include "net/base/data_url.h"
+#include "url/gurl.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::string input(data, data + size);
+ std::string mime_type;
+ std::string charset;
+ std::string urldata;
+ net::DataURL::Parse(GURL(input), &mime_type, &charset, &urldata);
+ return 0;
+}
diff --git a/chromium/net/base/parse_ip_pattern_fuzzer.cc b/chromium/net/base/parse_ip_pattern_fuzzer.cc
new file mode 100644
index 00000000000..67044e1d9c8
--- /dev/null
+++ b/chromium/net/base/parse_ip_pattern_fuzzer.cc
@@ -0,0 +1,16 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include "net/base/ip_pattern.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::string input(data, data + size);
+ net::IPPattern pattern;
+ pattern.ParsePattern(input);
+ return 0;
+}
diff --git a/chromium/net/base/parse_number.cc b/chromium/net/base/parse_number.cc
new file mode 100644
index 00000000000..d315bec63a9
--- /dev/null
+++ b/chromium/net/base/parse_number.cc
@@ -0,0 +1,23 @@
+// 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/parse_number.h"
+
+#include "base/strings/string_number_conversions.h"
+
+namespace net {
+
+bool ParseNonNegativeDecimalInt(const base::StringPiece& input, int* output) {
+ if (input.empty() || input[0] > '9' || input[0] < '0')
+ return false;
+
+ int result;
+ if (!base::StringToInt(input, &result))
+ return false;
+
+ *output = result;
+ return true;
+}
+
+} // namespace net
diff --git a/chromium/net/base/parse_number.h b/chromium/net/base/parse_number.h
new file mode 100644
index 00000000000..0b88cf0435b
--- /dev/null
+++ b/chromium/net/base/parse_number.h
@@ -0,0 +1,68 @@
+// 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_PARSE_NUMBER_H_
+#define NET_BASE_PARSE_NUMBER_H_
+
+#include "base/compiler_specific.h"
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+
+// This file contains utility functions for parsing numbers, in the context of
+// network protocols.
+//
+// Q: Doesn't //base already provide these in string_number_conversions.h, with
+// functions like base::StringToInt()?
+//
+// A: Yes, and those functions are used under the hood by these
+// implementations.
+//
+// However using the number parsing functions from //base directly in network
+// code can lead to subtle bugs, as the //base versions are more permissive.
+// For instance "+99" is successfully parsed by base::StringToInt().
+//
+// However in the majority of places in //net, a leading plus on a number
+// should be considered invalid. For instance when parsing a host:port pair
+// you wouldn't want to recognize "foo:+99" as having a port of 99. The same
+// issue applies when parsing a content-length header.
+//
+// To reduce the risk of such problems, use of these functions over the
+// //base versions.
+
+class GURL;
+
+namespace net {
+
+// Parses a string representing a decimal number to an |int|. Returns true on
+// success, and fills |*output| with the result. Note that |*output| is not
+// modified on failure.
+//
+// Recognized inputs take the form:
+// 1*DIGIT
+//
+// Where DIGIT is an ASCII number in the range '0' - '9'
+//
+// Note that:
+// * Parsing is locale independent
+// * Leading zeros are allowed (numbers needn't be in minimal encoding)
+// * Inputs that would overflow the output are rejected.
+// * Only accepts integers
+//
+// Examples of recognized inputs are:
+// "13"
+// "0"
+// "00013"
+//
+// Examples of rejected inputs are:
+// " 13"
+// "-13"
+// "+13"
+// "0x15"
+// "13.3"
+NET_EXPORT bool ParseNonNegativeDecimalInt(const base::StringPiece& input,
+ int* output) WARN_UNUSED_RESULT;
+
+} // namespace net
+
+#endif // NET_BASE_PARSE_NUMBER_H_
diff --git a/chromium/net/base/parse_number_unittest.cc b/chromium/net/base/parse_number_unittest.cc
new file mode 100644
index 00000000000..79cac9f43ba
--- /dev/null
+++ b/chromium/net/base/parse_number_unittest.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/base/parse_number.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace {
+
+TEST(ParseNumberTest, IntValidInputs) {
+ const struct {
+ const char* input;
+ int output;
+ } kTests[] = {
+ {"0", 0}, {"00000", 0}, {"003", 3}, {"003", 3}, {"1234566", 1234566},
+ {"987", 987}, {"010", 10},
+ };
+
+ for (const auto& test : kTests) {
+ int result;
+ ASSERT_TRUE(ParseNonNegativeDecimalInt(test.input, &result))
+ << "Failed to parse: " << test.input;
+ EXPECT_EQ(result, test.output) << "Failed to parse: " << test.input;
+ }
+}
+
+TEST(ParseNumberTest, IntInvalidInputs) {
+ const char* kTests[] = {
+ "",
+ "-23",
+ "+42",
+ " 123",
+ "123 ",
+ "123\n",
+ "0xFF",
+ "0x11",
+ "x11",
+ "F11",
+ "AF",
+ "0AF",
+ "0.0",
+ "13.",
+ "13,000",
+ "13.000",
+ "13/5",
+ "9999999999999999999999999999999999999999999999999999999999999999",
+ "Inf",
+ "NaN",
+ "null",
+ "dog",
+ };
+
+ for (const auto& input : kTests) {
+ int result = 0xDEAD;
+ ASSERT_FALSE(ParseNonNegativeDecimalInt(input, &result))
+ << "Succeeded to parse: " << input;
+ EXPECT_EQ(0xDEAD, result) << "Modified output for failed parsing";
+ }
+}
+
+TEST(ParseNumberTest, IntInvalidInputsContainsNul) {
+ int result = 0xDEAD;
+ ASSERT_FALSE(
+ ParseNonNegativeDecimalInt(base::StringPiece("123\0", 4), &result));
+ EXPECT_EQ(0xDEAD, result);
+}
+
+} // namespace
+} // namespace net
diff --git a/chromium/net/base/port_util.cc b/chromium/net/base/port_util.cc
index 1867dc36496..7328b5e842f 100644
--- a/chromium/net/base/port_util.cc
+++ b/chromium/net/base/port_util.cc
@@ -4,6 +4,7 @@
#include "net/base/port_util.h"
+#include <limits>
#include <set>
#include "base/lazy_instance.h"
diff --git a/chromium/net/base/prioritized_dispatcher.cc b/chromium/net/base/prioritized_dispatcher.cc
index b72f7a5018d..a6125a0db44 100644
--- a/chromium/net/base/prioritized_dispatcher.cc
+++ b/chromium/net/base/prioritized_dispatcher.cc
@@ -12,6 +12,8 @@ PrioritizedDispatcher::Limits::Limits(Priority num_priorities,
size_t total_jobs)
: total_jobs(total_jobs), reserved_slots(num_priorities) {}
+PrioritizedDispatcher::Limits::Limits(const Limits& other) = default;
+
PrioritizedDispatcher::Limits::~Limits() {}
PrioritizedDispatcher::PrioritizedDispatcher(const Limits& limits)
diff --git a/chromium/net/base/prioritized_dispatcher.h b/chromium/net/base/prioritized_dispatcher.h
index 8da8a1a668a..a0716ccf054 100644
--- a/chromium/net/base/prioritized_dispatcher.h
+++ b/chromium/net/base/prioritized_dispatcher.h
@@ -40,6 +40,7 @@ class NET_EXPORT_PRIVATE PrioritizedDispatcher {
// for priority 3 or above.
struct NET_EXPORT_PRIVATE Limits {
Limits(Priority num_priorities, size_t total_jobs);
+ Limits(const Limits& other);
~Limits();
// Total allowed running jobs.
diff --git a/chromium/net/base/proxy_delegate.h b/chromium/net/base/proxy_delegate.h
index 7e00d0ca8c7..f2e6120c20e 100644
--- a/chromium/net/base/proxy_delegate.h
+++ b/chromium/net/base/proxy_delegate.h
@@ -5,6 +5,8 @@
#ifndef NET_BASE_PROXY_DELEGATE_H_
#define NET_BASE_PROXY_DELEGATE_H_
+#include <string>
+
#include "base/macros.h"
#include "net/base/net_export.h"
@@ -29,10 +31,13 @@ class NET_EXPORT ProxyDelegate {
virtual ~ProxyDelegate() {
}
- // Called as the proxy is being resolved for |url|. Allows the delegate to
- // override the proxy resolution decision made by ProxyService. The delegate
- // may override the decision by modifying the ProxyInfo |result|.
+ // Called as the proxy is being resolved for |url| for a |method| request.
+ // The caller may pass an empty string to get method agnostic resoulution.
+ // Allows the delegate to override the proxy resolution decision made by
+ // ProxyService. The delegate may override the decision by modifying the
+ // ProxyInfo |result|.
virtual void OnResolveProxy(const GURL& url,
+ const std::string& method,
int load_flags,
const ProxyService& proxy_service,
ProxyInfo* result) = 0;
@@ -67,6 +72,10 @@ class NET_EXPORT ProxyDelegate {
const HostPortPair& proxy_server,
const HttpResponseHeaders& response_headers) = 0;
+ // Returns true if |proxy_server| is a trusted SPDY/HTTP2 proxy that is
+ // allowed to push cross-origin resources.
+ virtual bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(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 3f8c10bbac1..257e750d29f 100644
--- a/chromium/net/base/registry_controlled_domains/effective_tld_names.dat
+++ b/chromium/net/base/registry_controlled_domains/effective_tld_names.dat
@@ -7,7 +7,7 @@
// ===BEGIN ICANN DOMAINS===
-// ac : http://en.wikipedia.org/wiki/.ac
+// ac : https://en.wikipedia.org/wiki/.ac
ac
com.ac
edu.ac
@@ -16,11 +16,11 @@ net.ac
mil.ac
org.ac
-// ad : http://en.wikipedia.org/wiki/.ad
+// ad : https://en.wikipedia.org/wiki/.ad
ad
nom.ad
-// ae : http://en.wikipedia.org/wiki/.ae
+// ae : https://en.wikipedia.org/wiki/.ae
// see also: "Domain Name Eligibility Policy" at http://www.aeda.ae/eng/aepolicy.php
ae
co.ae
@@ -31,7 +31,7 @@ ac.ae
gov.ae
mil.ae
-// aero : see http://www.information.aero/index.php?id=66
+// aero : see https://www.information.aero/index.php?id=66
aero
accident-investigation.aero
accident-prevention.aero
@@ -153,10 +153,10 @@ mil.al
net.al
org.al
-// am : http://en.wikipedia.org/wiki/.am
+// am : https://en.wikipedia.org/wiki/.am
am
-// ao : http://en.wikipedia.org/wiki/.ao
+// ao : https://en.wikipedia.org/wiki/.ao
// http://www.dns.ao/REGISTR.DOC
ao
ed.ao
@@ -166,7 +166,7 @@ co.ao
pb.ao
it.ao
-// aq : http://en.wikipedia.org/wiki/.aq
+// aq : https://en.wikipedia.org/wiki/.aq
aq
// ar : https://nic.ar/normativa-vigente.xhtml
@@ -181,7 +181,7 @@ net.ar
org.ar
tur.ar
-// arpa : http://en.wikipedia.org/wiki/.arpa
+// arpa : https://en.wikipedia.org/wiki/.arpa
// Confirmed by registry <iana-questions@icann.org> 2008-06-18
arpa
e164.arpa
@@ -191,14 +191,14 @@ iris.arpa
uri.arpa
urn.arpa
-// as : http://en.wikipedia.org/wiki/.as
+// as : https://en.wikipedia.org/wiki/.as
as
gov.as
-// asia : http://en.wikipedia.org/wiki/.asia
+// asia : https://en.wikipedia.org/wiki/.asia
asia
-// at : http://en.wikipedia.org/wiki/.at
+// at : https://en.wikipedia.org/wiki/.at
// Confirmed by registry <it@nic.at> 2008-06-17
at
ac.at
@@ -206,7 +206,7 @@ co.at
gv.at
or.at
-// au : http://en.wikipedia.org/wiki/.au
+// au : https://en.wikipedia.org/wiki/.au
// http://www.auda.org.au/
au
// 2LDs
@@ -248,14 +248,14 @@ tas.gov.au
vic.gov.au
wa.gov.au
-// aw : http://en.wikipedia.org/wiki/.aw
+// aw : https://en.wikipedia.org/wiki/.aw
aw
com.aw
-// ax : http://en.wikipedia.org/wiki/.ax
+// ax : https://en.wikipedia.org/wiki/.ax
ax
-// az : http://en.wikipedia.org/wiki/.az
+// az : https://en.wikipedia.org/wiki/.az
az
com.az
net.az
@@ -270,7 +270,7 @@ name.az
pro.az
biz.az
-// ba : http://en.wikipedia.org/wiki/.ba
+// ba : https://en.wikipedia.org/wiki/.ba
ba
org.ba
net.ba
@@ -283,7 +283,7 @@ co.ba
com.ba
rs.ba
-// bb : http://en.wikipedia.org/wiki/.bb
+// bb : https://en.wikipedia.org/wiki/.bb
bb
biz.bb
co.bb
@@ -296,19 +296,19 @@ org.bb
store.bb
tv.bb
-// bd : http://en.wikipedia.org/wiki/.bd
+// bd : https://en.wikipedia.org/wiki/.bd
*.bd
-// be : http://en.wikipedia.org/wiki/.be
+// be : https://en.wikipedia.org/wiki/.be
// Confirmed by registry <tech@dns.be> 2008-06-08
be
ac.be
-// bf : http://en.wikipedia.org/wiki/.bf
+// bf : https://en.wikipedia.org/wiki/.bf
bf
gov.bf
-// bg : http://en.wikipedia.org/wiki/.bg
+// bg : https://en.wikipedia.org/wiki/.bg
// https://www.register.bg/user/static/rules/en/index.html
bg
a.bg
@@ -348,7 +348,7 @@ z.bg
8.bg
9.bg
-// bh : http://en.wikipedia.org/wiki/.bh
+// bh : https://en.wikipedia.org/wiki/.bh
bh
com.bh
edu.bh
@@ -356,7 +356,7 @@ net.bh
org.bh
gov.bh
-// bi : http://en.wikipedia.org/wiki/.bi
+// bi : https://en.wikipedia.org/wiki/.bi
// http://whois.nic.bi/
bi
co.bi
@@ -365,10 +365,10 @@ edu.bi
or.bi
org.bi
-// biz : http://en.wikipedia.org/wiki/.biz
+// biz : https://en.wikipedia.org/wiki/.biz
biz
-// bj : http://en.wikipedia.org/wiki/.bj
+// bj : https://en.wikipedia.org/wiki/.bj
bj
asso.bj
barreau.bj
@@ -382,7 +382,7 @@ gov.bm
net.bm
org.bm
-// bn : http://en.wikipedia.org/wiki/.bn
+// bn : https://en.wikipedia.org/wiki/.bn
*.bn
// bo : http://www.nic.bo/
@@ -398,7 +398,7 @@ mil.bo
tv.bo
// br : http://registro.br/dominio/categoria.html
-// Submitted by registry <fneves@registro.br> 2014-08-11
+// Submitted by registry <fneves@registro.br>
br
adm.br
adv.br
@@ -479,7 +479,7 @@ org.bs
edu.bs
gov.bs
-// bt : http://en.wikipedia.org/wiki/.bt
+// bt : https://en.wikipedia.org/wiki/.bt
bt
com.bt
edu.bt
@@ -488,17 +488,17 @@ net.bt
org.bt
// bv : No registrations at this time.
-// Submitted by registry <jarle@uninett.no> 2006-06-16
+// Submitted by registry <jarle@uninett.no>
bv
-// bw : http://en.wikipedia.org/wiki/.bw
+// bw : https://en.wikipedia.org/wiki/.bw
// http://www.gobin.info/domainname/bw.doc
// list of other 2nd level tlds ?
bw
co.bw
org.bw
-// by : http://en.wikipedia.org/wiki/.by
+// by : https://en.wikipedia.org/wiki/.by
// http://tld.by/rules_2006_en.html
// list of other 2nd level tlds ?
by
@@ -512,7 +512,7 @@ com.by
// http://hoster.by/
of.by
-// bz : http://en.wikipedia.org/wiki/.bz
+// bz : https://en.wikipedia.org/wiki/.bz
// http://www.belizenic.bz/
bz
com.bz
@@ -521,7 +521,7 @@ org.bz
edu.bz
gov.bz
-// ca : http://en.wikipedia.org/wiki/.ca
+// ca : https://en.wikipedia.org/wiki/.ca
ca
// ca geographical names
ab.ca
@@ -538,31 +538,31 @@ pe.ca
qc.ca
sk.ca
yk.ca
-// gc.ca: http://en.wikipedia.org/wiki/.gc.ca
+// gc.ca: https://en.wikipedia.org/wiki/.gc.ca
// see also: http://registry.gc.ca/en/SubdomainFAQ
gc.ca
-// cat : http://en.wikipedia.org/wiki/.cat
+// cat : https://en.wikipedia.org/wiki/.cat
cat
-// cc : http://en.wikipedia.org/wiki/.cc
+// cc : https://en.wikipedia.org/wiki/.cc
cc
-// cd : http://en.wikipedia.org/wiki/.cd
+// cd : https://en.wikipedia.org/wiki/.cd
// see also: https://www.nic.cd/domain/insertDomain_2.jsp?act=1
cd
gov.cd
-// cf : http://en.wikipedia.org/wiki/.cf
+// cf : https://en.wikipedia.org/wiki/.cf
cf
-// cg : http://en.wikipedia.org/wiki/.cg
+// cg : https://en.wikipedia.org/wiki/.cg
cg
-// ch : http://en.wikipedia.org/wiki/.ch
+// ch : https://en.wikipedia.org/wiki/.ch
ch
-// ci : http://en.wikipedia.org/wiki/.ci
+// ci : https://en.wikipedia.org/wiki/.ci
// http://www.nic.ci/index.php?page=charte
ci
org.ci
@@ -581,26 +581,26 @@ presse.ci
md.ci
gouv.ci
-// ck : http://en.wikipedia.org/wiki/.ck
+// ck : https://en.wikipedia.org/wiki/.ck
*.ck
!www.ck
-// cl : http://en.wikipedia.org/wiki/.cl
+// cl : https://en.wikipedia.org/wiki/.cl
cl
gov.cl
gob.cl
co.cl
mil.cl
-// cm : http://en.wikipedia.org/wiki/.cm plus bug 981927
+// cm : https://en.wikipedia.org/wiki/.cm plus bug 981927
cm
co.cm
com.cm
gov.cm
net.cm
-// cn : http://en.wikipedia.org/wiki/.cn
-// Submitted by registry <tanyaling@cnnic.cn> 2008-06-11
+// cn : https://en.wikipedia.org/wiki/.cn
+// Submitted by registry <tanyaling@cnnic.cn>
cn
ac.cn
com.cn
@@ -648,8 +648,8 @@ hk.cn
mo.cn
tw.cn
-// co : http://en.wikipedia.org/wiki/.co
-// Submitted by registry <tecnico@uniandes.edu.co> 2008-06-11
+// co : https://en.wikipedia.org/wiki/.co
+// Submitted by registry <tecnico@uniandes.edu.co>
co
arts.co
com.co
@@ -665,10 +665,10 @@ org.co
rec.co
web.co
-// com : http://en.wikipedia.org/wiki/.com
+// com : https://en.wikipedia.org/wiki/.com
com
-// coop : http://en.wikipedia.org/wiki/.coop
+// coop : https://en.wikipedia.org/wiki/.coop
coop
// cr : http://www.nic.cr/niccr_publico/showRegistroDominiosScreen.do
@@ -681,7 +681,7 @@ go.cr
or.cr
sa.cr
-// cu : http://en.wikipedia.org/wiki/.cu
+// cu : https://en.wikipedia.org/wiki/.cu
cu
com.cu
edu.cu
@@ -690,7 +690,7 @@ net.cu
gov.cu
inf.cu
-// cv : http://en.wikipedia.org/wiki/.cv
+// cv : https://en.wikipedia.org/wiki/.cv
cv
// cw : http://www.una.cw/cw_registry/
@@ -701,12 +701,12 @@ edu.cw
net.cw
org.cw
-// cx : http://en.wikipedia.org/wiki/.cx
+// cx : https://en.wikipedia.org/wiki/.cx
// list of other 2nd level tlds ?
cx
gov.cx
-// cy : http://en.wikipedia.org/wiki/.cy
+// cy : https://en.wikipedia.org/wiki/.cy
ac.cy
biz.cy
com.cy
@@ -721,22 +721,22 @@ press.cy
pro.cy
tm.cy
-// cz : http://en.wikipedia.org/wiki/.cz
+// cz : https://en.wikipedia.org/wiki/.cz
cz
-// de : http://en.wikipedia.org/wiki/.de
+// de : https://en.wikipedia.org/wiki/.de
// Confirmed by registry <ops@denic.de> (with technical
// reservations) 2008-07-01
de
-// dj : http://en.wikipedia.org/wiki/.dj
+// dj : https://en.wikipedia.org/wiki/.dj
dj
-// dk : http://en.wikipedia.org/wiki/.dk
+// dk : https://en.wikipedia.org/wiki/.dk
// Confirmed by registry <robert@dk-hostmaster.dk> 2008-06-17
dk
-// dm : http://en.wikipedia.org/wiki/.dm
+// dm : https://en.wikipedia.org/wiki/.dm
dm
com.dm
net.dm
@@ -744,7 +744,7 @@ org.dm
edu.dm
gov.dm
-// do : http://en.wikipedia.org/wiki/.do
+// do : https://en.wikipedia.org/wiki/.do
do
art.do
com.do
@@ -757,7 +757,7 @@ org.do
sld.do
web.do
-// dz : http://en.wikipedia.org/wiki/.dz
+// dz : https://en.wikipedia.org/wiki/.dz
dz
com.dz
org.dz
@@ -769,7 +769,7 @@ pol.dz
art.dz
// ec : http://www.nic.ec/reg/paso1.asp
-// Submitted by registry <vabboud@nic.ec> 2008-07-04
+// Submitted by registry <vabboud@nic.ec>
ec
com.ec
info.ec
@@ -784,7 +784,7 @@ gov.ec
gob.ec
mil.ec
-// edu : http://en.wikipedia.org/wiki/.edu
+// edu : https://en.wikipedia.org/wiki/.edu
edu
// ee : http://www.eenet.ee/EENet/dom_reeglid.html#lisa_B
@@ -800,7 +800,7 @@ aip.ee
org.ee
fie.ee
-// eg : http://en.wikipedia.org/wiki/.eg
+// eg : https://en.wikipedia.org/wiki/.eg
eg
com.eg
edu.eg
@@ -812,7 +812,7 @@ net.eg
org.eg
sci.eg
-// er : http://en.wikipedia.org/wiki/.er
+// er : https://en.wikipedia.org/wiki/.er
*.er
// es : https://www.nic.es/site_ingles/ingles/dominios/index.html
@@ -823,7 +823,7 @@ org.es
gob.es
edu.es
-// et : http://en.wikipedia.org/wiki/.et
+// et : https://en.wikipedia.org/wiki/.et
et
com.et
gov.et
@@ -834,28 +834,28 @@ name.et
info.et
net.et
-// eu : http://en.wikipedia.org/wiki/.eu
+// eu : https://en.wikipedia.org/wiki/.eu
eu
-// fi : http://en.wikipedia.org/wiki/.fi
+// fi : https://en.wikipedia.org/wiki/.fi
fi
-// aland.fi : http://en.wikipedia.org/wiki/.ax
+// aland.fi : https://en.wikipedia.org/wiki/.ax
// This domain is being phased out in favor of .ax. As there are still many
// domains under aland.fi, we still keep it on the list until aland.fi is
// completely removed.
// TODO: Check for updates (expected to be phased out around Q1/2009)
aland.fi
-// fj : http://en.wikipedia.org/wiki/.fj
+// fj : https://en.wikipedia.org/wiki/.fj
*.fj
-// fk : http://en.wikipedia.org/wiki/.fk
+// fk : https://en.wikipedia.org/wiki/.fk
*.fk
-// fm : http://en.wikipedia.org/wiki/.fm
+// fm : https://en.wikipedia.org/wiki/.fm
fm
-// fo : http://en.wikipedia.org/wiki/.fo
+// fo : https://en.wikipedia.org/wiki/.fo
fo
// fr : http://www.afnic.fr/
@@ -886,14 +886,14 @@ pharmacien.fr
port.fr
veterinaire.fr
-// ga : http://en.wikipedia.org/wiki/.ga
+// ga : https://en.wikipedia.org/wiki/.ga
ga
// gb : This registry is effectively dormant
-// Submitted by registry <Damien.Shaw@ja.net> 2008-06-12
+// Submitted by registry <Damien.Shaw@ja.net>
gb
-// gd : http://en.wikipedia.org/wiki/.gd
+// gd : https://en.wikipedia.org/wiki/.gd
gd
// ge : http://www.nic.net.ge/policy_en.pdf
@@ -906,7 +906,7 @@ mil.ge
net.ge
pvt.ge
-// gf : http://en.wikipedia.org/wiki/.gf
+// gf : https://en.wikipedia.org/wiki/.gf
gf
// gg : http://www.channelisles.net/register-domains/
@@ -916,7 +916,7 @@ co.gg
net.gg
org.gg
-// gh : http://en.wikipedia.org/wiki/.gh
+// gh : https://en.wikipedia.org/wiki/.gh
// see also: http://www.nic.gh/reg_now.php
// Although domains directly at second level are not possible at the moment,
// they have been possible for some time and may come back.
@@ -936,7 +936,7 @@ mod.gi
edu.gi
org.gi
-// gl : http://en.wikipedia.org/wiki/.gl
+// gl : https://en.wikipedia.org/wiki/.gl
// http://nic.gl
gl
co.gl
@@ -949,7 +949,7 @@ org.gl
gm
// gn : http://psg.com/dns/gn/gn.txt
-// Submitted by registry <randy@psg.com> 2008-06-17
+// Submitted by registry <randy@psg.com>
gn
ac.gn
com.gn
@@ -958,7 +958,7 @@ gov.gn
org.gn
net.gn
-// gov : http://en.wikipedia.org/wiki/.gov
+// gov : https://en.wikipedia.org/wiki/.gov
gov
// gp : http://www.nic.gp/index.php?lang=en
@@ -970,11 +970,11 @@ edu.gp
org.gp
asso.gp
-// gq : http://en.wikipedia.org/wiki/.gq
+// gq : https://en.wikipedia.org/wiki/.gq
gq
// gr : https://grweb.ics.forth.gr/english/1617-B-2005.html
-// Submitted by registry <segred@ics.forth.gr> 2008-06-09
+// Submitted by registry <segred@ics.forth.gr>
gr
com.gr
edu.gr
@@ -982,7 +982,7 @@ net.gr
org.gr
gov.gr
-// gs : http://en.wikipedia.org/wiki/.gs
+// gs : https://en.wikipedia.org/wiki/.gs
gs
// gt : http://www.gt/politicas_de_registro.html
@@ -998,18 +998,21 @@ org.gt
// gu : http://gadao.gov.gu/registration.txt
*.gu
-// gw : http://en.wikipedia.org/wiki/.gw
+// gw : https://en.wikipedia.org/wiki/.gw
gw
-// gy : http://en.wikipedia.org/wiki/.gy
+// gy : https://en.wikipedia.org/wiki/.gy
// http://registry.gy/
gy
co.gy
com.gy
+edu.gy
+gov.gy
net.gy
+org.gy
// hk : https://www.hkdnr.hk
-// Submitted by registry <hk.tech@hkirc.hk> 2008-06-11
+// Submitted by registry <hk.tech@hkirc.hk>
hk
com.hk
edu.hk
@@ -1033,7 +1036,7 @@ org.hk
組織.hk
組织.hk
-// hm : http://en.wikipedia.org/wiki/.hm
+// hm : https://en.wikipedia.org/wiki/.hm
hm
// hn : http://www.nic.hn/politicas/ps02,,05.html
@@ -1121,7 +1124,7 @@ or.id
sch.id
web.id
-// ie : http://en.wikipedia.org/wiki/.ie
+// ie : https://en.wikipedia.org/wiki/.ie
ie
gov.ie
@@ -1137,7 +1140,7 @@ net.il
org.il
// im : https://www.nic.im/
-// Submitted by registry <info@nic.im> 2013-11-15
+// Submitted by registry <info@nic.im>
im
ac.im
co.im
@@ -1149,7 +1152,7 @@ plc.co.im
tt.im
tv.im
-// in : http://en.wikipedia.org/wiki/.in
+// in : https://en.wikipedia.org/wiki/.in
// see also: https://registry.in/Policies
// Please note, that nic.in is not an official eTLD, but used by most
// government institutions.
@@ -1167,10 +1170,10 @@ res.in
gov.in
mil.in
-// info : http://en.wikipedia.org/wiki/.info
+// info : https://en.wikipedia.org/wiki/.info
info
-// int : http://en.wikipedia.org/wiki/.int
+// int : https://en.wikipedia.org/wiki/.int
// Confirmed by registry <iana-questions@icann.org> 2008-06-18
int
eu.int
@@ -1215,7 +1218,7 @@ gov.is
org.is
int.is
-// it : http://en.wikipedia.org/wiki/.it
+// it : https://en.wikipedia.org/wiki/.it
it
gov.it
edu.it
@@ -1613,12 +1616,12 @@ gov.jo
mil.jo
name.jo
-// jobs : http://en.wikipedia.org/wiki/.jobs
+// jobs : https://en.wikipedia.org/wiki/.jobs
jobs
-// jp : http://en.wikipedia.org/wiki/.jp
+// jp : https://en.wikipedia.org/wiki/.jp
// http://jprs.co.jp/en/jpdomain.html
-// Submitted by registry <info@jprs.jp> 2014-10-30
+// Submitted by registry <info@jprs.jp>
jp
// jp organizational type names
ac.jp
@@ -3445,7 +3448,7 @@ gov.ki
info.ki
com.ki
-// km : http://en.wikipedia.org/wiki/.km
+// km : https://en.wikipedia.org/wiki/.km
// http://www.domaine.km/documents/charte.doc
km
org.km
@@ -3458,7 +3461,7 @@ mil.km
ass.km
com.km
// These are only mentioned as proposed suggestions at domaine.km, but
-// http://en.wikipedia.org/wiki/.km says they're available for registration:
+// https://en.wikipedia.org/wiki/.km says they're available for registration:
coop.km
asso.km
presse.km
@@ -3468,7 +3471,7 @@ pharmaciens.km
veterinaire.km
gouv.km
-// kn : http://en.wikipedia.org/wiki/.kn
+// kn : https://en.wikipedia.org/wiki/.kn
// http://www.dot.kn/domainRules.html
kn
net.kn
@@ -3485,7 +3488,7 @@ org.kp
rep.kp
tra.kp
-// kr : http://en.wikipedia.org/wiki/.kr
+// kr : https://en.wikipedia.org/wiki/.kr
// see also: http://domain.nida.or.kr/eng/registration.jsp
kr
ac.kr
@@ -3519,7 +3522,7 @@ jeonnam.kr
seoul.kr
ulsan.kr
-// kw : http://en.wikipedia.org/wiki/.kw
+// kw : https://en.wikipedia.org/wiki/.kw
*.kw
// ky : http://www.icta.ky/da_ky_reg_dom.php
@@ -3531,7 +3534,7 @@ com.ky
org.ky
net.ky
-// kz : http://en.wikipedia.org/wiki/.kz
+// kz : https://en.wikipedia.org/wiki/.kz
// see also: http://www.nic.kz/rules/index.jsp
kz
org.kz
@@ -3541,8 +3544,8 @@ gov.kz
mil.kz
com.kz
-// la : http://en.wikipedia.org/wiki/.la
-// Submitted by registry <gavin.brown@nic.la> 2008-06-10
+// la : https://en.wikipedia.org/wiki/.la
+// Submitted by registry <gavin.brown@nic.la>
la
int.la
net.la
@@ -3553,8 +3556,8 @@ per.la
com.la
org.la
-// lb : http://en.wikipedia.org/wiki/.lb
-// Submitted by registry <randy@psg.com> 2008-06-17
+// lb : https://en.wikipedia.org/wiki/.lb
+// Submitted by registry <randy@psg.com>
lb
com.lb
edu.lb
@@ -3562,7 +3565,7 @@ gov.lb
net.lb
org.lb
-// lc : http://en.wikipedia.org/wiki/.lc
+// lc : https://en.wikipedia.org/wiki/.lc
// see also: http://www.nic.lc/rules.htm
lc
com.lc
@@ -3572,7 +3575,7 @@ org.lc
edu.lc
gov.lc
-// li : http://en.wikipedia.org/wiki/.li
+// li : https://en.wikipedia.org/wiki/.li
li
// lk : http://www.nic.lk/seclevpr.html
@@ -3594,7 +3597,7 @@ hotel.lk
ac.lk
// lr : http://psg.com/dns/lr/lr.txt
-// Submitted by registry <randy@psg.com> 2008-06-17
+// Submitted by registry <randy@psg.com>
lr
com.lr
edu.lr
@@ -3602,12 +3605,12 @@ gov.lr
org.lr
net.lr
-// ls : http://en.wikipedia.org/wiki/.ls
+// ls : https://en.wikipedia.org/wiki/.ls
ls
co.ls
org.ls
-// lt : http://en.wikipedia.org/wiki/.lt
+// lt : https://en.wikipedia.org/wiki/.lt
lt
// gov.lt : http://www.gov.lt/index_en.php
gov.lt
@@ -3639,7 +3642,7 @@ med.ly
org.ly
id.ly
-// ma : http://en.wikipedia.org/wiki/.ma
+// ma : https://en.wikipedia.org/wiki/.ma
// http://www.anrt.ma/fr/admin/download/upload/file_fr782.pdf
ma
co.ma
@@ -3654,10 +3657,10 @@ mc
tm.mc
asso.mc
-// md : http://en.wikipedia.org/wiki/.md
+// md : https://en.wikipedia.org/wiki/.md
md
-// me : http://en.wikipedia.org/wiki/.me
+// me : https://en.wikipedia.org/wiki/.me
me
co.me
net.me
@@ -3680,13 +3683,13 @@ mil.mg
com.mg
co.mg
-// mh : http://en.wikipedia.org/wiki/.mh
+// mh : https://en.wikipedia.org/wiki/.mh
mh
-// mil : http://en.wikipedia.org/wiki/.mil
+// mil : https://en.wikipedia.org/wiki/.mil
mil
-// mk : http://en.wikipedia.org/wiki/.mk
+// mk : https://en.wikipedia.org/wiki/.mk
// see also: http://dns.marnet.net.mk/postapka.php
mk
com.mk
@@ -3698,7 +3701,7 @@ inf.mk
name.mk
// ml : http://www.gobin.info/domainname/ml-template.doc
-// see also: http://en.wikipedia.org/wiki/.ml
+// see also: https://en.wikipedia.org/wiki/.ml
ml
com.ml
edu.ml
@@ -3708,10 +3711,10 @@ net.ml
org.ml
presse.ml
-// mm : http://en.wikipedia.org/wiki/.mm
+// mm : https://en.wikipedia.org/wiki/.mm
*.mm
-// mn : http://en.wikipedia.org/wiki/.mn
+// mn : https://en.wikipedia.org/wiki/.mn
mn
gov.mn
edu.mn
@@ -3725,17 +3728,17 @@ org.mo
edu.mo
gov.mo
-// mobi : http://en.wikipedia.org/wiki/.mobi
+// mobi : https://en.wikipedia.org/wiki/.mobi
mobi
// mp : http://www.dot.mp/
// Confirmed by registry <dcamacho@saipan.com> 2008-06-17
mp
-// mq : http://en.wikipedia.org/wiki/.mq
+// mq : https://en.wikipedia.org/wiki/.mq
mq
-// mr : http://en.wikipedia.org/wiki/.mr
+// mr : https://en.wikipedia.org/wiki/.mr
mr
gov.mr
@@ -3748,14 +3751,14 @@ net.ms
org.ms
// mt : https://www.nic.org.mt/go/policy
-// Submitted by registry <help@nic.org.mt> 2013-11-19
+// Submitted by registry <help@nic.org.mt>
mt
com.mt
edu.mt
net.mt
org.mt
-// mu : http://en.wikipedia.org/wiki/.mu
+// mu : https://en.wikipedia.org/wiki/.mu
mu
com.mu
net.mu
@@ -4317,7 +4320,7 @@ zoology.museum
ירושלים.museum
иком.museum
-// mv : http://en.wikipedia.org/wiki/.mv
+// mv : https://en.wikipedia.org/wiki/.mv
// "mv" included because, contra Wikipedia, google.mv exists.
mv
aero.mv
@@ -4350,7 +4353,7 @@ net.mw
org.mw
// mx : http://www.nic.mx/
-// Submitted by registry <farias@nic.mx> 2008-06-19
+// Submitted by registry <farias@nic.mx>
mx
com.mx
org.mx
@@ -4400,13 +4403,13 @@ name
nc
asso.nc
-// ne : http://en.wikipedia.org/wiki/.ne
+// ne : https://en.wikipedia.org/wiki/.ne
ne
-// net : http://en.wikipedia.org/wiki/.net
+// net : https://en.wikipedia.org/wiki/.net
net
-// nf : http://en.wikipedia.org/wiki/.nf
+// nf : https://en.wikipedia.org/wiki/.nf
nf
com.nf
net.nf
@@ -4419,17 +4422,18 @@ info.nf
other.nf
store.nf
-// ng : http://psg.com/dns/ng/
+// ng : http://www.nira.org.ng/index.php/join-us/register-ng-domain/189-nira-slds
ng
com.ng
edu.ng
+gov.ng
+i.ng
+mil.ng
+mobi.ng
name.ng
net.ng
org.ng
sch.ng
-gov.ng
-mil.ng
-mobi.ng
// ni : http://www.nic.ni/
com.ni
@@ -4447,7 +4451,7 @@ ac.ni
in.ni
info.ni
-// nl : http://en.wikipedia.org/wiki/.nl
+// nl : https://en.wikipedia.org/wiki/.nl
// https://www.sidn.nl/
// ccTLD for the Netherlands
nl
@@ -5226,7 +5230,7 @@ våler.hedmark.no
*.np
// nr : http://cenpac.net.nr/dns/index.html
-// Confirmed by registry <technician@cenpac.net.nr> 2008-06-17
+// Submitted by registry <technician@cenpac.net.nr>
nr
biz.nr
info.nr
@@ -5236,11 +5240,11 @@ org.nr
net.nr
com.nr
-// nu : http://en.wikipedia.org/wiki/.nu
+// nu : https://en.wikipedia.org/wiki/.nu
nu
-// nz : http://en.wikipedia.org/wiki/.nz
-// Confirmed by registry <jay@nzrs.net.nz> 2014-05-19
+// nz : https://en.wikipedia.org/wiki/.nz
+// Submitted by registry <jay@nzrs.net.nz>
nz
ac.nz
co.nz
@@ -5259,7 +5263,7 @@ org.nz
parliament.nz
school.nz
-// om : http://en.wikipedia.org/wiki/.om
+// om : https://en.wikipedia.org/wiki/.om
om
co.om
com.om
@@ -5271,7 +5275,7 @@ net.om
org.om
pro.om
-// org : http://en.wikipedia.org/wiki/.org
+// org : https://en.wikipedia.org/wiki/.org
org
// pa : http://www.nic.pa/
@@ -5306,11 +5310,11 @@ com.pf
org.pf
edu.pf
-// pg : http://en.wikipedia.org/wiki/.pg
+// pg : https://en.wikipedia.org/wiki/.pg
*.pg
// ph : http://www.domains.ph/FAQ2.asp
-// Submitted by registry <jed@email.com.ph> 2008-06-13
+// Submitted by registry <jed@email.com.ph>
ph
com.ph
net.ph
@@ -5339,7 +5343,7 @@ gos.pk
info.pk
// pl http://www.dns.pl/english/index.html
-// updated by .PL registry on 2015-04-28
+// Submitted by registry
pl
com.pl
net.pl
@@ -5556,7 +5560,7 @@ org.pn
edu.pn
net.pn
-// post : http://en.wikipedia.org/wiki/.post
+// post : https://en.wikipedia.org/wiki/.post
post
// pr : http://www.nic.pr/index.asp?f=1
@@ -5571,22 +5575,26 @@ pro.pr
biz.pr
info.pr
name.pr
-// these aren't mentioned on nic.pr, but on http://en.wikipedia.org/wiki/.pr
+// these aren't mentioned on nic.pr, but on https://en.wikipedia.org/wiki/.pr
est.pr
prof.pr
ac.pr
-// pro : http://www.nic.pro/support_faq.htm
+// pro : http://registry.pro/get-pro
pro
+aaa.pro
aca.pro
+acct.pro
+avocat.pro
bar.pro
cpa.pro
+eng.pro
jur.pro
law.pro
med.pro
-eng.pro
+recht.pro
-// ps : http://en.wikipedia.org/wiki/.ps
+// ps : https://en.wikipedia.org/wiki/.ps
// http://www.nic.ps/registration/policy.html#reg
ps
edu.ps
@@ -5608,7 +5616,7 @@ publ.pt
com.pt
nome.pt
-// pw : http://en.wikipedia.org/wiki/.pw
+// pw : https://en.wikipedia.org/wiki/.pw
pw
co.pw
ne.pw
@@ -5618,7 +5626,7 @@ go.pw
belau.pw
// py : http://www.nic.py/pautas.html#seccion_9
-// Confirmed by registry 2012-10-03
+// Submitted by registry
py
com.py
coop.py
@@ -5641,32 +5649,32 @@ sch.qa
// re : http://www.afnic.re/obtenir/chartes/nommage-re/annexe-descriptifs
re
-com.re
asso.re
+com.re
nom.re
// ro : http://www.rotld.ro/
ro
+arts.ro
com.ro
-org.ro
-tm.ro
-nt.ro
-nom.ro
+firm.ro
info.ro
+nom.ro
+nt.ro
+org.ro
rec.ro
-arts.ro
-firm.ro
store.ro
+tm.ro
www.ro
-// rs : http://en.wikipedia.org/wiki/.rs
+// rs : https://www.rnids.rs/en/domains/national-domains
rs
+ac.rs
co.rs
-org.rs
edu.rs
-ac.rs
gov.rs
in.rs
+org.rs
// ru : http://www.cctld.ru/ru/docs/aktiv_8.php
// Industry domains
@@ -5831,7 +5839,7 @@ edu.sa
sch.sa
// sb : http://www.sbnic.net.sb/
-// Submitted by registry <lee.humphries@telekom.com.sb> 2008-06-08
+// Submitted by registry <lee.humphries@telekom.com.sb>
sb
com.sb
edu.sb
@@ -5848,7 +5856,7 @@ org.sc
edu.sc
// sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm
-// Submitted by registry <admin@isoc.sd> 2008-06-17
+// Submitted by registry <admin@isoc.sd>
sd
com.sd
net.sd
@@ -5859,8 +5867,8 @@ tv.sd
gov.sd
info.sd
-// se : http://en.wikipedia.org/wiki/.se
-// Submitted by registry <patrik.wallstrom@iis.se> 2014-03-18
+// se : https://en.wikipedia.org/wiki/.se
+// Submitted by registry <patrik.wallstrom@iis.se>
se
a.se
ac.se
@@ -5919,19 +5927,19 @@ gov.sh
org.sh
mil.sh
-// si : http://en.wikipedia.org/wiki/.si
+// si : https://en.wikipedia.org/wiki/.si
si
// sj : No registrations at this time.
-// Submitted by registry <jarle@uninett.no> 2008-06-16
+// Submitted by registry <jarle@uninett.no>
sj
-// sk : http://en.wikipedia.org/wiki/.sk
+// sk : https://en.wikipedia.org/wiki/.sk
// list of 2nd level domains ?
sk
// sl : http://www.nic.sl
-// Submitted by registry <adam@neoip.com> 2008-06-12
+// Submitted by registry <adam@neoip.com>
sl
com.sl
net.sl
@@ -5939,10 +5947,10 @@ edu.sl
gov.sl
org.sl
-// sm : http://en.wikipedia.org/wiki/.sm
+// sm : https://en.wikipedia.org/wiki/.sm
sm
-// sn : http://en.wikipedia.org/wiki/.sn
+// sn : https://en.wikipedia.org/wiki/.sn
sn
art.sn
com.sn
@@ -5958,7 +5966,7 @@ com.so
net.so
org.so
-// sr : http://en.wikipedia.org/wiki/.sr
+// sr : https://en.wikipedia.org/wiki/.sr
sr
// st : http://www.nic.st/html/policyrules/
@@ -5976,7 +5984,7 @@ principe.st
saotome.st
store.st
-// su : http://en.wikipedia.org/wiki/.su
+// su : https://en.wikipedia.org/wiki/.su
su
adygeya.su
arkhangelsk.su
@@ -6019,12 +6027,12 @@ gob.sv
org.sv
red.sv
-// sx : http://en.wikipedia.org/wiki/.sx
-// Confirmed by registry <jcvignes@openregistry.com> 2012-05-31
+// sx : https://en.wikipedia.org/wiki/.sx
+// Submitted by registry <jcvignes@openregistry.com>
sx
gov.sx
-// sy : http://en.wikipedia.org/wiki/.sy
+// sy : https://en.wikipedia.org/wiki/.sy
// see also: http://www.gobin.info/domainname/sy.doc
sy
edu.sy
@@ -6034,32 +6042,32 @@ mil.sy
com.sy
org.sy
-// sz : http://en.wikipedia.org/wiki/.sz
+// sz : https://en.wikipedia.org/wiki/.sz
// http://www.sispa.org.sz/
sz
co.sz
ac.sz
org.sz
-// tc : http://en.wikipedia.org/wiki/.tc
+// tc : https://en.wikipedia.org/wiki/.tc
tc
-// td : http://en.wikipedia.org/wiki/.td
+// td : https://en.wikipedia.org/wiki/.td
td
-// tel: http://en.wikipedia.org/wiki/.tel
+// tel: https://en.wikipedia.org/wiki/.tel
// http://www.telnic.org/
tel
-// tf : http://en.wikipedia.org/wiki/.tf
+// tf : https://en.wikipedia.org/wiki/.tf
tf
-// tg : http://en.wikipedia.org/wiki/.tg
+// tg : https://en.wikipedia.org/wiki/.tg
// http://www.nic.tg/
tg
-// th : http://en.wikipedia.org/wiki/.th
-// Submitted by registry <krit@thains.co.th> 2008-06-17
+// th : https://en.wikipedia.org/wiki/.th
+// Submitted by registry <krit@thains.co.th>
th
ac.th
co.th
@@ -6087,10 +6095,10 @@ org.tj
test.tj
web.tj
-// tk : http://en.wikipedia.org/wiki/.tk
+// tk : https://en.wikipedia.org/wiki/.tk
tk
-// tl : http://en.wikipedia.org/wiki/.tl
+// tl : https://en.wikipedia.org/wiki/.tl
tl
gov.tl
@@ -6105,7 +6113,7 @@ gov.tm
mil.tm
edu.tm
-// tn : http://en.wikipedia.org/wiki/.tn
+// tn : https://en.wikipedia.org/wiki/.tn
// http://whois.ati.tn/
tn
com.tn
@@ -6129,8 +6137,8 @@ agrinet.tn
defense.tn
turen.tn
-// to : http://en.wikipedia.org/wiki/.to
-// Submitted by registry <egullich@colo.to> 2008-06-17
+// to : https://en.wikipedia.org/wiki/.to
+// Submitted by registry <egullich@colo.to>
to
com.to
gov.to
@@ -6139,13 +6147,9 @@ org.to
edu.to
mil.to
-// tp : No registrations at this time.
-// Submitted by Ryan Sleevi <ryan.sleevi@gmail.com> 2014-01-03
-tp
-
// subTLDs: https://www.nic.tr/forms/eng/policies.pdf
// and: https://www.nic.tr/forms/politikalar.pdf
-// Submitted by <mehmetgurevin@gmail.com> 2014-07-19
+// Submitted by <mehmetgurevin@gmail.com>
tr
com.tr
info.tr
@@ -6174,7 +6178,7 @@ nc.tr
// Used by government agencies of Northern Cyprus
gov.nc.tr
-// travel : http://en.wikipedia.org/wiki/.travel
+// travel : https://en.wikipedia.org/wiki/.travel
travel
// tt : http://www.nic.tt/
@@ -6197,12 +6201,12 @@ name.tt
gov.tt
edu.tt
-// tv : http://en.wikipedia.org/wiki/.tv
+// tv : https://en.wikipedia.org/wiki/.tv
// Not listing any 2LDs as reserved since none seem to exist in practice,
// Wikipedia notwithstanding.
tv
-// tw : http://en.wikipedia.org/wiki/.tw
+// tw : https://en.wikipedia.org/wiki/.tw
tw
edu.tw
gov.tw
@@ -6219,7 +6223,7 @@ club.tw
商業.tw
// tz : http://www.tznic.or.tz/index.php/domains
-// Confirmed by registry <manager@tznic.or.tz> 2013-01-22
+// Submitted by registry <manager@tznic.or.tz>
tz
ac.tz
co.tz
@@ -6235,7 +6239,7 @@ sc.tz
tv.tz
// ua : https://hostmaster.ua/policy/?ua
-// Submitted by registry <dk@cctld.ua> 2012-04-27
+// Submitted by registry <dk@cctld.ua>
ua
// ua 2LD
com.ua
@@ -6328,7 +6332,7 @@ ne.ug
com.ug
org.ug
-// uk : http://en.wikipedia.org/wiki/.uk
+// uk : https://en.wikipedia.org/wiki/.uk
// Submitted by registry <Michael.Daly@nominet.org.uk>
uk
ac.uk
@@ -6343,7 +6347,7 @@ plc.uk
police.uk
*.sch.uk
-// us : http://en.wikipedia.org/wiki/.us
+// us : https://en.wikipedia.org/wiki/.us
us
dni.us
fed.us
@@ -6601,11 +6605,11 @@ com.uz
net.uz
org.uz
-// va : http://en.wikipedia.org/wiki/.va
+// va : https://en.wikipedia.org/wiki/.va
va
-// vc : http://en.wikipedia.org/wiki/.vc
-// Submitted by registry <kshah@ca.afilias.info> 2008-06-13
+// vc : https://en.wikipedia.org/wiki/.vc
+// Submitted by registry <kshah@ca.afilias.info>
vc
com.vc
net.vc
@@ -6615,8 +6619,7 @@ mil.vc
edu.vc
// ve : https://registro.nic.ve/
-// Confirmed by registry 2012-10-04
-// Updated 2014-05-20 - Bug 940478
+// Submitted by registry
ve
arts.ve
co.ve
@@ -6636,7 +6639,7 @@ store.ve
tec.ve
web.ve
-// vg : http://en.wikipedia.org/wiki/.vg
+// vg : https://en.wikipedia.org/wiki/.vg
vg
// vi : http://www.nic.vi/newdomainform.htm
@@ -6665,7 +6668,7 @@ name.vn
pro.vn
health.vn
-// vu : http://en.wikipedia.org/wiki/.vu
+// vu : https://en.wikipedia.org/wiki/.vu
// http://www.vunic.vu/
vu
com.vu
@@ -6676,7 +6679,7 @@ org.vu
// wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
wf
-// ws : http://en.wikipedia.org/wiki/.ws
+// ws : https://en.wikipedia.org/wiki/.ws
// http://samoanic.ws/index.dhtml
ws
com.ws
@@ -6727,6 +6730,9 @@ yt
// http://www.dotmasr.eg/
مصر
+// xn--e1a4c ("eu", Cyrillic) : EU
+ею
+
// xn--node ("ge", Georgian Mkhedruli) : GE
გე
@@ -6830,7 +6836,7 @@ yt
فلسطين
// xn--90a3ac ("srb", Cyrillic) : RS
-// http://www.rnids.rs/en/the-.срб-domain
+// https://www.rnids.rs/en/domains/national-domains
срб
пр.срб
орг.срб
@@ -6909,7 +6915,7 @@ xxx
// za : http://www.zadna.org.za/content/page/domain-information
ac.za
-agrica.za
+agric.za
alt.za
co.za
edu.za
@@ -6926,14 +6932,14 @@ school.za
tm.za
web.za
-// zm : http://en.wikipedia.org/wiki/.zm
+// zm : https://en.wikipedia.org/wiki/.zm
*.zm
-// zw : http://en.wikipedia.org/wiki/.zw
+// zw : https://en.wikipedia.org/wiki/.zw
*.zw
-// List of new gTLDs imported from https://newgtlds.icann.org/newgtlds.csv on 2016-01-04T22:39:54Z
+// List of new gTLDs imported from https://newgtlds.icann.org/newgtlds.csv on 2016-04-04T20:12:16Z
// aaa : 2015-02-26 American Automobile Association, Inc.
aaa
@@ -7118,6 +7124,9 @@ archi
// army : 2014-03-06 United TLD Holdco Ltd.
army
+// art : 2016-03-24 UK Creative Ideas Limited
+art
+
// arte : 2014-12-11 Association Relative à la Télévision Européenne G.E.I.E.
arte
@@ -7820,9 +7829,6 @@ doha
// domains : 2013-10-17 Sugar Cross, LLC
domains
-// doosan : 2014-04-03 Doosan Corporation
-doosan
-
// dot : 2015-05-21 Dish DBS Corporation
dot
@@ -8111,6 +8117,9 @@ fujitsu
// fujixerox : 2015-07-23 Xerox DNHC LLC
fujixerox
+// fun : 2016-01-14 Oriental Trading Company, Inc.
+fun
+
// fund : 2014-03-20 John Castle, LLC
fund
@@ -8198,6 +8207,9 @@ globo
// gmail : 2014-05-01 Charleston Road Registry Inc.
gmail
+// gmbh : 2016-01-29 Extra Dynamite, LLC
+gmbh
+
// gmo : 2014-01-09 GMO Internet, Inc.
gmo
@@ -9653,6 +9665,9 @@ shiksha
// shoes : 2013-10-02 Binky Galley, LLC
shoes
+// shopping : 2016-03-31 Uniregistry, Corp.
+shopping
+
// shouji : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD.
shouji
@@ -9785,6 +9800,9 @@ storage
// store : 2015-04-09 DotStore Inc.
store
+// stream : 2016-01-08 dot Stream Limited
+stream
+
// studio : 2015-02-11
studio
@@ -10595,20 +10613,21 @@ zuerich
// (Note: these are in alphabetical order by company name)
// Amazon CloudFront : https://aws.amazon.com/cloudfront/
-// Submitted by Donavan Miller <donavanm@amazon.com> 2013-03-22
+// Submitted by Donavan Miller <donavanm@amazon.com>
cloudfront.net
// Amazon Elastic Compute Cloud: https://aws.amazon.com/ec2/
-// Submitted by Osman Surkatty <osmans@amazon.com> 2014-12-16
+// Submitted by Luke Wells <lawells@amazon.com>
ap-northeast-1.compute.amazonaws.com
+ap-northeast-2.compute.amazonaws.com
ap-southeast-1.compute.amazonaws.com
ap-southeast-2.compute.amazonaws.com
cn-north-1.compute.amazonaws.cn
+compute-1.amazonaws.com
compute.amazonaws.cn
compute.amazonaws.com
-compute-1.amazonaws.com
-eu-west-1.compute.amazonaws.com
eu-central-1.compute.amazonaws.com
+eu-west-1.compute.amazonaws.com
sa-east-1.compute.amazonaws.com
us-east-1.amazonaws.com
us-gov-west-1.compute.amazonaws.com
@@ -10618,37 +10637,39 @@ z-1.compute-1.amazonaws.com
z-2.compute-1.amazonaws.com
// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/
-// Submitted by Adam Stein <astein@amazon.com> 2013-04-02
+// Submitted by Adam Stein <astein@amazon.com>
elasticbeanstalk.com
// Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/
-// Submitted by Scott Vidmar <svidmar@amazon.com> 2013-03-27
+// Submitted by Scott Vidmar <svidmar@amazon.com>
elb.amazonaws.com
// Amazon S3 : https://aws.amazon.com/s3/
-// Submitted by Eric Kinolik <kilo@amazon.com> 2015-04-08
+// Submitted by Luke Wells <lawells@amazon.com>
s3.amazonaws.com
s3-ap-northeast-1.amazonaws.com
+s3-ap-northeast-2.amazonaws.com
s3-ap-southeast-1.amazonaws.com
s3-ap-southeast-2.amazonaws.com
+s3-eu-central-1.amazonaws.com
+s3-eu-west-1.amazonaws.com
s3-external-1.amazonaws.com
s3-external-2.amazonaws.com
s3-fips-us-gov-west-1.amazonaws.com
-s3-eu-central-1.amazonaws.com
-s3-eu-west-1.amazonaws.com
s3-sa-east-1.amazonaws.com
s3-us-gov-west-1.amazonaws.com
s3-us-west-1.amazonaws.com
s3-us-west-2.amazonaws.com
+s3.ap-northeast-2.amazonaws.com
s3.cn-north-1.amazonaws.com.cn
s3.eu-central-1.amazonaws.com
// BetaInABox
-// Submitted by adrian@betainabox.com 2012-09-13
+// Submitted by Adrian <adrian@betainabox.com>
betainabox.com
// CentralNic : http://www.centralnic.com/names/domains
-// Submitted by registry <gavin.brown@centralnic.com> 2012-09-27
+// Submitted by registry <gavin.brown@centralnic.com>
ae.org
ar.com
br.com
@@ -10679,38 +10700,46 @@ za.bz
za.com
// Africa.com Web Solutions Ltd : https://registry.africa.com
-// Submitted by Gavin Brown <gavin.brown@centralnic.com> 2014-02-04
+// Submitted by Gavin Brown <gavin.brown@centralnic.com>
africa.com
// iDOT Services Limited : http://www.domain.gr.com
-// Submitted by Gavin Brown <gavin.brown@centralnic.com> 2014-02-04
+// Submitted by Gavin Brown <gavin.brown@centralnic.com>
gr.com
// Radix FZC : http://domains.in.net
-// Submitted by Gavin Brown <gavin.brown@centralnic.com> 2014-02-04
+// Submitted by Gavin Brown <gavin.brown@centralnic.com>
in.net
// US REGISTRY LLC : http://us.org
-// Submitted by Gavin Brown <gavin.brown@centralnic.com> 2014-02-04
+// Submitted by Gavin Brown <gavin.brown@centralnic.com>
us.org
// co.com Registry, LLC : https://registry.co.com
-// Submitted by Gavin Brown <gavin.brown@centralnic.com> 2014-02-04
+// Submitted by Gavin Brown <gavin.brown@centralnic.com>
co.com
// c.la : http://www.c.la/
c.la
+// Citrix : https://citrix.com
+// Submitted by Alex Stoddard <alex.stoddard@citrix.com>
+xenapponazure.com
+
// cloudControl : https://www.cloudcontrol.com/
-// Submitted by Tobias Wilken <tw@cloudcontrol.com> 2013-07-23
+// Submitted by Tobias Wilken <tw@cloudcontrol.com>
cloudcontrolled.com
cloudcontrolapp.com
// co.ca : http://registry.co.ca/
co.ca
+// i-registry s.r.o. : http://www.i-registry.cz/
+// Submitted by Martin Semrad <semrad@i-registry.cz>
+co.cz
+
// CDN77.com : http://www.cdn77.com
-// Submitted by Jan Krpes <jan.krpes@cdn77.com> 2015-07-13
+// Submitted by Jan Krpes <jan.krpes@cdn77.com>
c.cdn77.org
cdn77-ssl.net
r.cdn77.net
@@ -10722,20 +10751,37 @@ co.nl
co.no
// Commerce Guys, SAS
-// Submitted by Damien Tournoud <damien@commerceguys.com> 2015-01-22
+// Submitted by Damien Tournoud <damien@commerceguys.com>
// CHROMIUM - Disabled as per https://code.google.com/p/chromium/issues/detail?id=459802
// *.platform.sh
// Cupcake : https://cupcake.io/
-// Submitted by Jonathan Rudenberg <jonathan@cupcake.io> 2013-10-08
+// Submitted by Jonathan Rudenberg <jonathan@cupcake.io>
cupcake.is
+// cyon GmbH : https://www.cyon.ch/
+// Submitted by Dominic Luechinger <dol@cyon.ch>
+cyon.link
+cyon.site
+
+// Dansk.net : http://www.dansk.net/
+// Submitted by Anani Voule <digital@digital.co.dk>
+biz.dk
+co.dk
+firm.dk
+reg.dk
+store.dk
+
// DreamHost : http://www.dreamhost.com/
-// Submitted by Andrew Farmer <andrew.farmer@dreamhost.com> 2012-10-02
+// Submitted by Andrew Farmer <andrew.farmer@dreamhost.com>
dreamhosters.com
+// Drobo : http://www.drobo.com/
+// Submitted by Ricardo Padilha <rpadilha@drobo.com>
+mydrobo.com
+
// DuckDNS : http://www.duckdns.org/
-// Submitted by Richard Harper <richard@duckdns.org> 2015-05-17
+// Submitted by Richard Harper <richard@duckdns.org>
duckdns.org
// DynDNS.com : http://www.dyndns.com/services/dns/dyndns/
@@ -11019,9 +11065,12 @@ webhop.org
worse-than.tv
writesthisblog.com
-// EU.org https://eu.org/
-// Submitted by Pierre Beyssac <hostmaster@eu.org> 2015-04-17
+// dynv6 : https://dynv6.com
+// Submitted by Dominik Menke <dom@digineo.de> 2016-01-18
+dynv6.net
+// EU.org https://eu.org/
+// Submitted by Pierre Beyssac <hostmaster@eu.org>
eu.org
al.eu.org
asso.eu.org
@@ -11079,8 +11128,12 @@ tr.eu.org
uk.eu.org
us.eu.org
+// Facebook, Inc.
+// Submitted by Peter Ruibal <public-suffix@fb.com>
+apps.fbsbx.com
+
// Fastly Inc. http://www.fastly.com/
-// Submitted by Vladimir Vuksan <vladimir@fastly.com> 2013-05-31
+// Submitted by Vladimir Vuksan <vladimir@fastly.com>
a.ssl.fastly.net
b.ssl.fastly.net
global.ssl.fastly.net
@@ -11088,28 +11141,33 @@ a.prod.fastly.net
global.prod.fastly.net
// Firebase, Inc.
-// Submitted by Chris Raynor <chris@firebase.com> 2014-01-21
+// Submitted by Chris Raynor <chris@firebase.com>
firebaseapp.com
// Flynn : https://flynn.io
-// Submitted by Jonathan Rudenberg <jonathan@flynn.io> 2014-07-12
+// Submitted by Jonathan Rudenberg <jonathan@flynn.io>
flynnhub.com
// GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains
-// Submitted by David Illsley <david.illsley@digital.cabinet-office.gov.uk> 2014-08-28
+// Submitted by David Illsley <david.illsley@digital.cabinet-office.gov.uk>
service.gov.uk
// GitHub, Inc.
-// Submitted by Ben Toews <btoews@github.com> 2014-02-06
+// Submitted by Patrick Toomey <security@github.com>
github.io
githubusercontent.com
+githubcloud.com
+*.api.githubcloud.com
+*.ext.githubcloud.com
+gist.githubcloud.com
+*.githubcloudusercontent.com
// GlobeHosting, Inc.
-// Submitted by Zoltan Egresi <egresi@globehosting.com> 2013-07-12
+// Submitted by Zoltan Egresi <egresi@globehosting.com>
ro.com
// Google, Inc.
-// Submitted by Eduardo Vela <evn@google.com> 2014-12-19
+// Submitted by Eduardo Vela <evn@google.com>
appspot.com
blogspot.ae
blogspot.al
@@ -11194,16 +11252,15 @@ withgoogle.com
withyoutube.com
// Hashbang : https://hashbang.sh
-// Hashbang is a non-profit that provides shells and various other services.
hashbang.sh
// Heroku : https://www.heroku.com/
-// Submitted by Tom Maher <tmaher@heroku.com> 2013-05-02
+// Submitted by Tom Maher <tmaher@heroku.com>
herokuapp.com
herokussl.com
// iki.fi
-// Submitted by Hannu Aronsson <haa@iki.fi> 2009-11-05
+// Submitted by Hannu Aronsson <haa@iki.fi>
iki.fi
// info.at : http://www.info.at/
@@ -11214,45 +11271,49 @@ info.at
co.pl
// Microsoft : http://microsoft.com
-// Submitted by Barry Dorrans <bdorrans@microsoft.com> 2014-01-24
+// Submitted by Barry Dorrans <bdorrans@microsoft.com>
azurewebsites.net
azure-mobile.net
cloudapp.net
// Mozilla Foundation : https://mozilla.org/
-// Submited by glob <glob@mozilla.com> 2015-07-06
+// Submitted by glob <glob@mozilla.com>
bmoattachments.org
// Neustar Inc.
-// Submitted by Trung Tran <Trung.Tran@neustar.biz> 2015-04-23
+// Submitted by Trung Tran <Trung.Tran@neustar.biz>
4u.com
// ngrok : https://ngrok.com/
-// Submitted by Alan Shreve <alan@ngrok.com> 2015-11-10
+// Submitted by Alan Shreve <alan@ngrok.com>
ngrok.io
// NFSN, Inc. : https://www.NearlyFreeSpeech.NET/
-// Submitted by Jeff Wheelhouse <support@nearlyfreespeech.net> 2014-02-02
+// Submitted by Jeff Wheelhouse <support@nearlyfreespeech.net>
nfshost.com
// NYC.mn : http://www.information.nyc.mn
-// Submitted by Matthew Brown <mattbrown@nyc.mn> 2013-03-11
+// Submitted by Matthew Brown <mattbrown@nyc.mn>
nyc.mn
// One Fold Media : http://www.onefoldmedia.com/
-// Submitted by Eddie Jones <eddie@onefoldmedia.com> 2014-06-10
+// Submitted by Eddie Jones <eddie@onefoldmedia.com>
nid.io
// Opera Software, A.S.A.
-// Submitted by Yngve Pettersen <yngve@opera.com> 2009-11-26
+// Submitted by Yngve Pettersen <yngve@opera.com>
operaunite.com
// OutSystems
-// Submitted by Duarte Santos <domain-admin@outsystemscloud.com> 2014-03-11
+// Submitted by Duarte Santos <domain-admin@outsystemscloud.com>
outsystemscloud.com
+// oy.lc
+// Submitted by Charly Coste <changaco@changaco.oy.lc>
+oy.lc
+
// Pagefront : https://www.pagefronthq.com/
-// Submitted by Jason Kriss <jason@pagefronthq.com> 2015-12-02
+// Submitted by Jason Kriss <jason@pagefronthq.com>
pagefrontapp.com
// .pl domains (grandfathered)
@@ -11264,49 +11325,54 @@ wroc.pl
zakopane.pl
// Pantheon Systems, Inc. : https://pantheon.io/
-// Submitted by Gary Dylina <gary@pantheon.io> 2015-09-14
-pantheon.io
+// Submitted by Gary Dylina <gary@pantheon.io>
+pantheonsite.io
gotpantheon.com
+// Peplink | Pepwave : http://peplink.com/
+// Submitted by Steve Leung <steveleung@peplink.com>
+mypep.link
+
+// prgmr.com : https://prgmr.com/
+// Submitted by Sarah Newman <owner@prgmr.com>
+xen.prgmr.com
+
// priv.at : http://www.nic.priv.at/
-// Submitted by registry <lendl@nic.at> 2008-06-09
+// Submitted by registry <lendl@nic.at>
priv.at
// QA2
-// Submitted by Daniel Dent (https://www.danieldent.com/) 2015-07-16
+// Submitted by Daniel Dent (https://www.danieldent.com/)
qa2.com
// Rackmaze LLC : https://www.rackmaze.com
-// Submitted by Kirill Pertsev <kika@rackmaze.com> 2015-12-02
+// Submitted by Kirill Pertsev <kika@rackmaze.com>
rackmaze.com
rackmaze.net
// Red Hat, Inc. OpenShift : https://openshift.redhat.com/
-// Submitted by Tim Kramer <tkramer@rhcloud.com> 2012-10-24
+// Submitted by Tim Kramer <tkramer@rhcloud.com>
rhcloud.com
// Sandstorm Development Group, Inc. : https://sandcats.io/
-// Submitted by Asheesh Laroia <asheesh@sandstorm.io> 2015-07-21
+// Submitted by Asheesh Laroia <asheesh@sandstorm.io>
sandcats.io
// Service Online LLC : http://drs.ua/
-// Submitted by Serhii Bulakh <support@drs.ua> 2015-07-30
+// Submitted by Serhii Bulakh <support@drs.ua>
biz.ua
co.ua
pp.ua
// SinaAppEngine : http://sae.sina.com.cn/
-// Submitted by SinaAppEngine <saesupport@sinacloud.com> 2015-02-02
+// Submitted by SinaAppEngine <saesupport@sinacloud.com>
sinaapp.com
vipsinaapp.com
1kapp.com
// Synology, Inc. : https://www.synology.com/
-// Submitted by Rony Weng <ronyweng@synology.com> 2015-12-02
-synology.me
+// Submitted by Rony Weng <ronyweng@synology.com>
diskstation.me
-i234.me
-myds.me
dscloud.biz
dscloud.me
dscloud.mobi
@@ -11316,6 +11382,9 @@ dsmynas.org
familyds.com
familyds.net
familyds.org
+i234.me
+myds.me
+synology.me
// TASK geographical domains (www.task.gda.pl/uslugi/dns)
gda.pl
@@ -11325,18 +11394,18 @@ med.pl
sopot.pl
// UDR Limited : http://www.udr.hk.com
-// Submitted by registry <hostmaster@udr.hk.com> 2014-11-07
+// Submitted by registry <hostmaster@udr.hk.com>
hk.com
hk.org
ltd.hk
inc.hk
// Yola : https://www.yola.com/
-// Submitted by Stefano Rivera <stefano@yola.com> 2014-07-09
+// Submitted by Stefano Rivera <stefano@yola.com>
yolasite.com
// ZaNiC : http://www.za.net/
-// Submitted by registry <hostmaster@nic.za.net> 2009-10-03
+// Submitted by registry <hostmaster@nic.za.net>
za.net
za.org
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 793479d3f54..7a60e300488 100644
--- a/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf
+++ b/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf
@@ -30,6 +30,7 @@ a.se, 0
a.ssl.fastly.net, 4
aa.no, 0
aaa, 0
+aaa.pro, 0
aarborte.no, 0
aarp, 0
ab.ca, 0
@@ -94,6 +95,7 @@ accident-investigation.aero, 0
accident-prevention.aero, 0
accountant, 0
accountants, 0
+acct.pro, 0
achi.nagano.jp, 0
aco, 0
act.au, 0
@@ -141,7 +143,7 @@ agency, 0
agents.aero, 0
agr.br, 0
agrar.hu, 0
-agrica.za, 0
+agric.za, 0
agriculture.museum, 0
agrigento.it, 0
agrinet.tn, 0
@@ -284,13 +286,16 @@ aosta.it, 0
aostavalley.it, 0
aoste.it, 0
ap-northeast-1.compute.amazonaws.com, 4
+ap-northeast-2.compute.amazonaws.com, 4
ap-southeast-1.compute.amazonaws.com, 4
ap-southeast-2.compute.amazonaws.com, 4
ap.gov.pl, 0
ap.it, 0
apartments, 0
+api.githubcloud.com, 6
app, 0
apple, 0
+apps.fbsbx.com, 4
appspot.com, 4
aq, 0
aq.it, 0
@@ -326,6 +331,7 @@ army, 0
arna.no, 0
arpa, 0
arq.br, 0
+art, 0
art.br, 0
art.do, 0
art.dz, 0
@@ -445,6 +451,7 @@ averoy.no, 0
avianca, 0
aviation.museum, 0
avocat.fr, 0
+avocat.pro, 0
avoues.fr, 0
aw, 0
awaji.hyogo.jp, 0
@@ -609,6 +616,7 @@ biz.at, 4
biz.az, 0
biz.bb, 0
biz.cy, 0
+biz.dk, 4
biz.et, 0
biz.id, 0
biz.ki, 0
@@ -1125,6 +1133,8 @@ co.cl, 0
co.cm, 0
co.com, 4
co.cr, 0
+co.cz, 4
+co.dk, 4
co.gg, 0
co.gl, 0
co.gy, 0
@@ -1413,6 +1423,8 @@ cy.eu.org, 4
cyber.museum, 0
cymru, 0
cymru.museum, 0
+cyon.link, 4
+cyon.site, 4
cyou, 0
cz, 0
cz.eu.org, 4
@@ -1532,7 +1544,6 @@ dontexist.net, 4
dontexist.org, 4
doomdns.com, 4
doomdns.org, 4
-doosan, 0
doshi.yamanashi.jp, 0
dot, 0
dovre.no, 0
@@ -1589,6 +1600,7 @@ dyndns.info, 4
dyndns.org, 4
dyndns.tv, 4
dyndns.ws, 4
+dynv6.net, 4
dyroy.no, 0
dz, 0
e-burg.ru, 0
@@ -1654,6 +1666,7 @@ edu.gn, 0
edu.gp, 0
edu.gr, 0
edu.gt, 0
+edu.gy, 0
edu.hk, 0
edu.hn, 0
edu.ht, 0
@@ -1851,6 +1864,7 @@ experts-comptables.fr, 0
exposed, 0
express, 0
express.aero, 0
+ext.githubcloud.com, 6
extraspace, 0
f.bg, 0
f.se, 0
@@ -1924,6 +1938,7 @@ firebaseapp.com, 4
firenze.it, 0
firestone, 0
firm.co, 0
+firm.dk, 4
firm.ht, 0
firm.in, 0
firm.nf, 0
@@ -2130,6 +2145,7 @@ fukushima.fukushima.jp, 0
fukushima.hokkaido.jp, 0
fukushima.jp, 0
fukuyama.hiroshima.jp, 0
+fun, 0
funabashi.chiba.jp, 0
funagata.yamagata.jp, 0
funahashi.toyama.jp, 0
@@ -2232,7 +2248,10 @@ ginan.gifu.jp, 0
ginowan.okinawa.jp, 0
ginoza.okinawa.jp, 0
giske.no, 0
+gist.githubcloud.com, 4
github.io, 4
+githubcloud.com, 4
+githubcloudusercontent.com, 6
githubusercontent.com, 4
gives, 0
giving, 0
@@ -2257,6 +2276,7 @@ glogow.pl, 0
gloppen.no, 0
gm, 0
gmail, 0
+gmbh, 0
gmina.pl, 0
gmo, 0
gmx, 0
@@ -2373,6 +2393,7 @@ gov.gh, 0
gov.gi, 0
gov.gn, 0
gov.gr, 0
+gov.gy, 0
gov.hk, 0
gov.ie, 0
gov.il, 0
@@ -2825,6 +2846,7 @@ hyogo.jp, 0
hyuga.miyazaki.jp, 0
hyundai, 0
i.bg, 0
+i.ng, 0
i.ph, 0
i.se, 0
i234.me, 4
@@ -4480,9 +4502,11 @@ mx.na, 0
my, 0
my.eu.org, 4
my.id, 0
+mydrobo.com, 4
myds.me, 4
mykolaiv.ua, 0
myoko.niigata.jp, 0
+mypep.link, 4
mypets.ws, 4
myphotos.cc, 4
mytis.ru, 0
@@ -5181,6 +5205,7 @@ org.gn, 0
org.gp, 0
org.gr, 0
org.gt, 0
+org.gy, 0
org.hk, 0
org.hn, 0
org.ht, 0
@@ -5342,6 +5367,7 @@ ovre-eiker.no, 0
owani.aomori.jp, 0
owariasahi.aichi.jp, 0
oxford.museum, 0
+oy.lc, 4
oyabe.toyama.jp, 0
oyama.tochigi.jp, 0
oyamazaki.kyoto.jp, 0
@@ -5375,7 +5401,7 @@ pamperedchef, 0
panama.museum, 0
panasonic, 0
panerai, 0
-pantheon.io, 4
+pantheonsite.io, 4
parachuting.aero, 0
paragliding.aero, 0
paris, 0
@@ -5664,12 +5690,14 @@ rec.co, 0
rec.nf, 0
rec.ro, 0
rec.ve, 0
+recht.pro, 0
recipes, 0
recreation.aero, 0
red, 0
red.sv, 0
redstone, 0
redumbrella, 0
+reg.dk, 4
reggio-calabria.it, 0
reggio-emilia.it, 0
reggiocalabria.it, 0
@@ -5793,6 +5821,7 @@ rzgw.gov.pl, 0
s.bg, 0
s.se, 0
s3-ap-northeast-1.amazonaws.com, 4
+s3-ap-northeast-2.amazonaws.com, 4
s3-ap-southeast-1.amazonaws.com, 4
s3-ap-southeast-2.amazonaws.com, 4
s3-eu-central-1.amazonaws.com, 4
@@ -5805,6 +5834,7 @@ s3-us-gov-west-1.amazonaws.com, 4
s3-us-west-1.amazonaws.com, 4
s3-us-west-2.amazonaws.com, 4
s3.amazonaws.com, 4
+s3.ap-northeast-2.amazonaws.com, 4
s3.cn-north-1.amazonaws.com.cn, 4
s3.eu-central-1.amazonaws.com, 4
sa, 0
@@ -6158,6 +6188,7 @@ shoo.okayama.jp, 0
shop.ht, 0
shop.hu, 0
shop.pl, 0
+shopping, 0
shouji, 0
show, 0
show.aero, 0
@@ -6352,6 +6383,7 @@ stord.no, 0
stordal.no, 0
store, 0
store.bb, 0
+store.dk, 4
store.nf, 0
store.ro, 0
store.st, 0
@@ -6360,6 +6392,7 @@ storfjord.no, 0
stpetersburg.museum, 0
strand.no, 0
stranda.no, 0
+stream, 0
stryn.no, 0
student.aero, 0
studio, 0
@@ -6738,7 +6771,6 @@ toyoura.hokkaido.jp, 0
toys, 0
tozawa.yamagata.jp, 0
tozsde.hu, 0
-tp, 0
tp.it, 0
tr, 0
tr.eu.org, 4
@@ -7266,6 +7298,8 @@ wzmiuw.gov.pl, 0
x.bg, 0
x.se, 0
xbox, 0
+xen.prgmr.com, 4
+xenapponazure.com, 4
xerox, 0
xfinity, 0
xihuan, 0
@@ -7374,6 +7408,7 @@ xn--djty4k.jp, 0
xn--dnna-gra.no, 0
xn--drbak-wua.no, 0
xn--dyry-ira.no, 0
+xn--e1a4c, 0
xn--eckvdtc9d, 0
xn--efvn9s.jp, 0
xn--efvy88h, 0
diff --git a/chromium/net/base/registry_controlled_domains/get_domain_and_registry_fuzzer.cc b/chromium/net/base/registry_controlled_domains/get_domain_and_registry_fuzzer.cc
new file mode 100644
index 00000000000..e71c7dc26a7
--- /dev/null
+++ b/chromium/net/base/registry_controlled_domains/get_domain_and_registry_fuzzer.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 <stddef.h>
+#include <stdint.h>
+
+#include "base/strings/string_piece.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "url/gurl.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ // Call GetDomainAndRegistry() twice - once with each filter type to ensure
+ // both code paths are exercised.
+ net::registry_controlled_domains::GetDomainAndRegistry(
+ base::StringPiece(reinterpret_cast<const char*>(data), size),
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+
+ net::registry_controlled_domains::GetDomainAndRegistry(
+ base::StringPiece(reinterpret_cast<const char*>(data), size),
+ net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
+
+ return 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 7e6231663dc..8d379ba91b7 100644
--- a/chromium/net/base/registry_controlled_domains/registry_controlled_domain.cc
+++ b/chromium/net/base/registry_controlled_domains/registry_controlled_domain.cc
@@ -50,8 +50,9 @@
#include "base/strings/utf_string_conversions.h"
#include "net/base/lookup_string_in_fixed_set.h"
#include "net/base/net_module.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "url/gurl.h"
+#include "url/origin.h"
#include "url/third_party/mozilla/url_parse.h"
namespace net {
@@ -65,10 +66,9 @@ namespace {
const unsigned char* g_graph = kDafsa;
size_t g_graph_length = sizeof(kDafsa);
-size_t GetRegistryLengthImpl(
- const std::string& host,
- UnknownRegistryFilter unknown_filter,
- PrivateRegistryFilter private_filter) {
+size_t GetRegistryLengthImpl(base::StringPiece host,
+ UnknownRegistryFilter unknown_filter,
+ PrivateRegistryFilter private_filter) {
DCHECK(!host.empty());
// Skip leading dots.
@@ -148,8 +148,8 @@ size_t GetRegistryLengthImpl(
(host.length() - curr_start) : 0;
}
-std::string GetDomainAndRegistryImpl(
- const std::string& host, PrivateRegistryFilter private_filter) {
+std::string GetDomainAndRegistryImpl(base::StringPiece host,
+ PrivateRegistryFilter private_filter) {
DCHECK(!host.empty());
// Find the length of the registry for this host.
@@ -171,8 +171,8 @@ std::string GetDomainAndRegistryImpl(
// no dot.
const size_t dot = host.rfind('.', host.length() - registry_length - 2);
if (dot == std::string::npos)
- return host;
- return host.substr(dot + 1);
+ return host.as_string();
+ return host.substr(dot + 1).as_string();
}
} // namespace
@@ -180,16 +180,14 @@ std::string GetDomainAndRegistryImpl(
std::string GetDomainAndRegistry(
const GURL& gurl,
PrivateRegistryFilter filter) {
- const url::Component host = gurl.parsed_for_possibly_invalid_spec().host;
- if ((host.len <= 0) || gurl.HostIsIPAddress())
+ base::StringPiece host = gurl.host_piece();
+ if (host.empty() || gurl.HostIsIPAddress())
return std::string();
- return GetDomainAndRegistryImpl(std::string(
- gurl.possibly_invalid_spec().data() + host.begin, host.len), filter);
+ return GetDomainAndRegistryImpl(host, filter);
}
-std::string GetDomainAndRegistry(
- const std::string& host,
- PrivateRegistryFilter filter) {
+std::string GetDomainAndRegistry(base::StringPiece host,
+ PrivateRegistryFilter filter) {
url::CanonHostInfo host_info;
const std::string canon_host(CanonicalizeHost(host, &host_info));
if (canon_host.empty() || host_info.IsIPAddress())
@@ -218,25 +216,28 @@ bool SameDomainOrHost(
host1.len);
}
+bool SameDomainOrHost(const url::Origin& origin1,
+ const url::Origin& origin2,
+ PrivateRegistryFilter filter) {
+ return SameDomainOrHost(GURL(origin1.Serialize()), GURL(origin2.Serialize()),
+ filter);
+}
+
size_t GetRegistryLength(
const GURL& gurl,
UnknownRegistryFilter unknown_filter,
PrivateRegistryFilter private_filter) {
- const url::Component host = gurl.parsed_for_possibly_invalid_spec().host;
- if (host.len <= 0)
+ base::StringPiece host = gurl.host_piece();
+ if (host.empty())
return std::string::npos;
if (gurl.HostIsIPAddress())
return 0;
- return GetRegistryLengthImpl(
- std::string(gurl.possibly_invalid_spec().data() + host.begin, host.len),
- unknown_filter,
- private_filter);
+ return GetRegistryLengthImpl(host, unknown_filter, private_filter);
}
-size_t GetRegistryLength(
- const std::string& host,
- UnknownRegistryFilter unknown_filter,
- PrivateRegistryFilter private_filter) {
+size_t GetRegistryLength(base::StringPiece host,
+ UnknownRegistryFilter unknown_filter,
+ PrivateRegistryFilter private_filter) {
url::CanonHostInfo host_info;
const std::string canon_host(CanonicalizeHost(host, &host_info));
if (canon_host.empty())
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 67f5e3805c2..24ffb707a50 100644
--- a/chromium/net/base/registry_controlled_domains/registry_controlled_domain.h
+++ b/chromium/net/base/registry_controlled_domains/registry_controlled_domain.h
@@ -117,10 +117,15 @@
#include <string>
+#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
class GURL;
+namespace url {
+class Origin;
+};
+
struct DomainRule;
namespace net {
@@ -179,11 +184,11 @@ NET_EXPORT std::string GetDomainAndRegistry(const GURL& gurl,
// Like the GURL version, but takes a host (which is canonicalized internally)
// instead of a full GURL.
-NET_EXPORT std::string GetDomainAndRegistry(const std::string& host,
+NET_EXPORT std::string GetDomainAndRegistry(base::StringPiece host,
PrivateRegistryFilter filter);
-// This convenience function returns true if the two GURLs both have hosts
-// and one of the following is true:
+// These convenience functions return true if the two GURLs or Origins both have
+// hosts and one of the following is true:
// * They each have a known domain and registry, and it is the same for both
// URLs. Note that this means the trailing dot, if any, must match too.
// * They don't have known domains/registries, but the hosts are identical.
@@ -191,6 +196,9 @@ NET_EXPORT std::string GetDomainAndRegistry(const std::string& host,
// represent hosts "on the same site".
NET_EXPORT bool SameDomainOrHost(const GURL& gurl1, const GURL& gurl2,
PrivateRegistryFilter filter);
+NET_EXPORT bool SameDomainOrHost(const url::Origin& origin1,
+ const url::Origin& origin2,
+ 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
@@ -221,7 +229,7 @@ NET_EXPORT size_t GetRegistryLength(const GURL& gurl,
// Like the GURL version, but takes a host (which is canonicalized internally)
// instead of a full GURL.
-NET_EXPORT size_t GetRegistryLength(const std::string& host,
+NET_EXPORT size_t GetRegistryLength(base::StringPiece host,
UnknownRegistryFilter unknown_filter,
PrivateRegistryFilter private_filter);
diff --git a/chromium/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc b/chromium/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc
index 42af173b584..0d553cb255b 100644
--- a/chromium/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc
+++ b/chromium/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc
@@ -5,6 +5,7 @@
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+#include "url/origin.h"
namespace {
namespace test1 {
@@ -67,12 +68,6 @@ size_t GetRegistryLengthFromHostIncludingPrivate(
return GetRegistryLength(host, unknown_filter, INCLUDE_PRIVATE_REGISTRIES);
}
-bool CompareDomains(const std::string& url1, const std::string& url2) {
- GURL g1 = GURL(url1);
- GURL g2 = GURL(url2);
- return SameDomainOrHost(g1, g2, EXCLUDE_PRIVATE_REGISTRIES);
-}
-
} // namespace
class RegistryControlledDomainTest : public testing::Test {
@@ -82,6 +77,17 @@ class RegistryControlledDomainTest : public testing::Test {
SetFindDomainGraph(graph, sizeof(Graph));
}
+ bool CompareDomains(const std::string& url1, const std::string& url2) {
+ SCOPED_TRACE(url1 + " " + url2);
+ GURL g1 = GURL(url1);
+ GURL g2 = GURL(url2);
+ url::Origin o1 = url::Origin(g1);
+ url::Origin o2 = url::Origin(g2);
+ EXPECT_EQ(SameDomainOrHost(o1, o2, EXCLUDE_PRIVATE_REGISTRIES),
+ SameDomainOrHost(g1, g2, EXCLUDE_PRIVATE_REGISTRIES));
+ return SameDomainOrHost(g1, g2, EXCLUDE_PRIVATE_REGISTRIES);
+ }
+
void TearDown() override { SetFindDomainGraph(); }
};
diff --git a/chromium/net/base/sdch_manager.cc b/chromium/net/base/sdch_manager.cc
index a8272700d95..435977237d8 100644
--- a/chromium/net/base/sdch_manager.cc
+++ b/chromium/net/base/sdch_manager.cc
@@ -16,6 +16,7 @@
#include "base/time/default_clock.h"
#include "base/values.h"
#include "crypto/sha2.h"
+#include "net/base/parse_number.h"
#include "net/base/sdch_observer.h"
#include "net/url_request/url_request_http_job.h"
@@ -376,12 +377,12 @@ SdchProblemCode SdchManager::AddSdchDictionary(
return SDCH_DICTIONARY_UNSUPPORTED_VERSION;
} else if (name == "max-age") {
int64_t seconds;
+ // TODO(eroman): crbug.com/596541 -- should not accept a leading +.
base::StringToInt64(value, &seconds);
expiration = base::Time::Now() + base::TimeDelta::FromSeconds(seconds);
} else if (name == "port") {
int port;
- base::StringToInt(value, &port);
- if (port >= 0)
+ if (ParseNonNegativeDecimalInt(value, &port))
ports.insert(port);
}
}
diff --git a/chromium/net/base/socket_performance_watcher.cc b/chromium/net/base/socket_performance_watcher.cc
deleted file mode 100644
index aa0dab3b03c..00000000000
--- a/chromium/net/base/socket_performance_watcher.cc
+++ /dev/null
@@ -1,34 +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/base/socket_performance_watcher.h"
-
-#include "base/logging.h"
-
-namespace net {
-
-SocketPerformanceWatcher::SocketPerformanceWatcher(
- const SocketPerformanceWatcherFactory::Protocol protocol,
- SocketPerformanceWatcherFactory* socket_performance_watcher_factory)
- : protocol_(protocol),
- socket_performance_watcher_factory_(socket_performance_watcher_factory) {
- DCHECK(socket_performance_watcher_factory_);
-
- switch (protocol) {
- case SocketPerformanceWatcherFactory::PROTOCOL_TCP:
- case SocketPerformanceWatcherFactory::PROTOCOL_QUIC:
- return;
- default:
- NOTREACHED();
- }
-}
-
-SocketPerformanceWatcher::~SocketPerformanceWatcher() {}
-
-void SocketPerformanceWatcher::OnUpdatedRTTAvailable(
- const base::TimeDelta& rtt) const {
- socket_performance_watcher_factory_->OnUpdatedRTTAvailable(protocol_, rtt);
-}
-
-} // namespace net
diff --git a/chromium/net/base/socket_performance_watcher.h b/chromium/net/base/socket_performance_watcher.h
index e0e76327ce6..74413679890 100644
--- a/chromium/net/base/socket_performance_watcher.h
+++ b/chromium/net/base/socket_performance_watcher.h
@@ -5,9 +5,7 @@
#ifndef NET_BASE_SOCKET_PERFORMANCE_WATCHER_H_
#define NET_BASE_SOCKET_PERFORMANCE_WATCHER_H_
-#include "base/macros.h"
#include "net/base/net_export.h"
-#include "net/base/socket_performance_watcher_factory.h"
namespace base {
class TimeDelta;
@@ -16,32 +14,28 @@ class TimeDelta;
namespace net {
// SocketPerformanceWatcher is the base class for recording and aggregating
-// socket statistics.
+// per-socket statistics. SocketPerformanceWatcher must be used on a single
+// thread.
class NET_EXPORT_PRIVATE SocketPerformanceWatcher {
public:
- // |socket_performance_watcher_factory| is the factory that constructed
- // |this| watcher.
- SocketPerformanceWatcher(
- const SocketPerformanceWatcherFactory::Protocol protocol,
- SocketPerformanceWatcherFactory* socket_performance_watcher_factory);
-
- virtual ~SocketPerformanceWatcher();
-
- // Called when updated transport layer RTT information is available. This
- // must be the transport layer RTT from this device to the remote transport
- // layer endpoint. This method is called immediately after the observation is
- // made, hence no timestamp.
- void OnUpdatedRTTAvailable(const base::TimeDelta& rtt) const;
-
- private:
- // Transport layer protocol used by the socket that |this| is watching.
- const SocketPerformanceWatcherFactory::Protocol protocol_;
-
- // |socket_performance_watcher_factory_| is the factory that created
- // |this| watcher.
- SocketPerformanceWatcherFactory* socket_performance_watcher_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(SocketPerformanceWatcher);
+ virtual ~SocketPerformanceWatcher() {}
+
+ // Returns true if |this| SocketPerformanceWatcher is interested in receiving
+ // an updated RTT estimate (via OnUpdatedRTTAvailable).
+ virtual bool ShouldNotifyUpdatedRTT() const = 0;
+
+ // Notifies |this| SocketPerformanceWatcher of updated transport layer RTT
+ // from this device to the remote transport layer endpoint. This method is
+ // called immediately after the observation is made, hence no timestamp.
+ // There is no guarantee that OnUpdatedRTTAvailable will be called every time
+ // an updated RTT is available as the socket may throttle the
+ // OnUpdatedRTTAvailable call for various reasons, including performance.
+ virtual void OnUpdatedRTTAvailable(const base::TimeDelta& rtt) = 0;
+
+ // Notifies that |this| watcher will be reused to watch a socket that belongs
+ // to a different transport layer connection. Note: The new connection shares
+ // the same protocol as the previously watched socket.
+ virtual void OnConnectionChanged() = 0;
};
} // namespace net
diff --git a/chromium/net/base/socket_performance_watcher_factory.h b/chromium/net/base/socket_performance_watcher_factory.h
index cbd607ab336..df54e597efe 100644
--- a/chromium/net/base/socket_performance_watcher_factory.h
+++ b/chromium/net/base/socket_performance_watcher_factory.h
@@ -9,10 +9,6 @@
#include "base/memory/scoped_ptr.h"
#include "net/base/net_export.h"
-namespace base {
-class TimeDelta;
-} // namespace base
-
namespace net {
class SocketPerformanceWatcher;
@@ -34,14 +30,6 @@ class NET_EXPORT_PRIVATE SocketPerformanceWatcherFactory {
virtual scoped_ptr<SocketPerformanceWatcher> CreateSocketPerformanceWatcher(
const Protocol protocol) = 0;
- // Called when updated transport layer RTT information is available from one
- // of the watchers created by |this|. |protocol| is the protocol that was used
- // by the watcher. |rtt| must be the transport layer RTT from this device to
- // the remote transport layer endpoint. These methods are called immediately
- // after the observation is made, hence no timestamp.
- virtual void OnUpdatedRTTAvailable(const Protocol protocol,
- const base::TimeDelta& rtt) = 0;
-
protected:
SocketPerformanceWatcherFactory() {}
diff --git a/chromium/net/base/test_proxy_delegate.cc b/chromium/net/base/test_proxy_delegate.cc
new file mode 100644
index 00000000000..da7693bd2a8
--- /dev/null
+++ b/chromium/net/base/test_proxy_delegate.cc
@@ -0,0 +1,87 @@
+// 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/test_proxy_delegate.h"
+
+#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+TestProxyDelegate::TestProxyDelegate()
+ : on_before_tunnel_request_called_(false),
+ on_tunnel_request_completed_called_(false),
+ on_tunnel_headers_received_called_(false) {}
+
+TestProxyDelegate::~TestProxyDelegate() {}
+
+void TestProxyDelegate::VerifyOnTunnelRequestCompleted(
+ const std::string& endpoint,
+ const std::string& proxy_server) const {
+ EXPECT_TRUE(on_tunnel_request_completed_called_);
+ EXPECT_TRUE(HostPortPair::FromString(endpoint).Equals(
+ on_tunnel_request_completed_endpoint_));
+ EXPECT_TRUE(HostPortPair::FromString(proxy_server)
+ .Equals(on_tunnel_request_completed_proxy_server_));
+}
+
+void TestProxyDelegate::VerifyOnTunnelHeadersReceived(
+ const std::string& origin,
+ const std::string& proxy_server,
+ const std::string& status_line) const {
+ EXPECT_TRUE(on_tunnel_headers_received_called_);
+ EXPECT_TRUE(HostPortPair::FromString(origin).Equals(
+ on_tunnel_headers_received_origin_));
+ EXPECT_TRUE(HostPortPair::FromString(proxy_server)
+ .Equals(on_tunnel_headers_received_proxy_server_));
+ EXPECT_EQ(status_line, on_tunnel_headers_received_status_line_);
+}
+
+void TestProxyDelegate::OnResolveProxy(const GURL& url,
+ const std::string& method,
+ int load_flags,
+ const ProxyService& proxy_service,
+ ProxyInfo* result) {}
+
+void TestProxyDelegate::OnTunnelConnectCompleted(
+ const HostPortPair& endpoint,
+ const HostPortPair& proxy_server,
+ int net_error) {
+ on_tunnel_request_completed_called_ = true;
+ on_tunnel_request_completed_endpoint_ = endpoint;
+ on_tunnel_request_completed_proxy_server_ = proxy_server;
+}
+
+void TestProxyDelegate::OnFallback(const ProxyServer& bad_proxy,
+ int net_error) {}
+
+void TestProxyDelegate::OnBeforeSendHeaders(URLRequest* request,
+ const ProxyInfo& proxy_info,
+ HttpRequestHeaders* headers) {}
+
+void TestProxyDelegate::OnBeforeTunnelRequest(
+ const HostPortPair& proxy_server,
+ HttpRequestHeaders* extra_headers) {
+ on_before_tunnel_request_called_ = true;
+ if (extra_headers)
+ extra_headers->SetHeader("Foo", proxy_server.ToString());
+}
+
+void TestProxyDelegate::OnTunnelHeadersReceived(
+ const HostPortPair& origin,
+ const HostPortPair& proxy_server,
+ const HttpResponseHeaders& response_headers) {
+ on_tunnel_headers_received_called_ = true;
+ on_tunnel_headers_received_origin_ = origin;
+ on_tunnel_headers_received_proxy_server_ = proxy_server;
+ on_tunnel_headers_received_status_line_ = response_headers.GetStatusLine();
+}
+
+bool TestProxyDelegate::IsTrustedSpdyProxy(
+ const net::ProxyServer& proxy_server) {
+ return proxy_server.is_valid() && trusted_spdy_proxy_ == proxy_server;
+}
+
+} // namespace net \ No newline at end of file
diff --git a/chromium/net/base/test_proxy_delegate.h b/chromium/net/base/test_proxy_delegate.h
new file mode 100644
index 00000000000..0a40d996cdb
--- /dev/null
+++ b/chromium/net/base/test_proxy_delegate.h
@@ -0,0 +1,87 @@
+// 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_TEST_PROXY_DELEGATE_H_
+#define NET_BASE_TEST_PROXY_DELEGATE_H_
+
+#include <string>
+
+#include "net/base/host_port_pair.h"
+#include "net/base/proxy_delegate.h"
+#include "net/proxy/proxy_server.h"
+
+class GURL;
+
+namespace net {
+
+class HttpRequestHeaders;
+class HttpResponseHeaders;
+class ProxyInfo;
+class ProxyService;
+class URLRequest;
+
+class TestProxyDelegate : public ProxyDelegate {
+ public:
+ TestProxyDelegate();
+ ~TestProxyDelegate() override;
+
+ bool on_before_tunnel_request_called() const {
+ return on_before_tunnel_request_called_;
+ }
+
+ bool on_tunnel_request_completed_called() const {
+ return on_tunnel_request_completed_called_;
+ }
+
+ bool on_tunnel_headers_received_called() const {
+ return on_tunnel_headers_received_called_;
+ }
+
+ void set_trusted_spdy_proxy(const net::ProxyServer& proxy_server) {
+ trusted_spdy_proxy_ = proxy_server;
+ }
+
+ void VerifyOnTunnelRequestCompleted(const std::string& endpoint,
+ const std::string& proxy_server) const;
+
+ void VerifyOnTunnelHeadersReceived(const std::string& origin,
+ const std::string& proxy_server,
+ const std::string& status_line) const;
+
+ // ProxyDelegate implementation:
+ void OnResolveProxy(const GURL& url,
+ const std::string& method,
+ int load_flags,
+ const ProxyService& proxy_service,
+ ProxyInfo* result) override;
+ void OnTunnelConnectCompleted(const HostPortPair& endpoint,
+ const HostPortPair& proxy_server,
+ int net_error) override;
+ void OnFallback(const ProxyServer& bad_proxy, int net_error) override;
+ void OnBeforeSendHeaders(URLRequest* request,
+ const ProxyInfo& proxy_info,
+ HttpRequestHeaders* headers) override;
+ void OnBeforeTunnelRequest(const HostPortPair& proxy_server,
+ HttpRequestHeaders* extra_headers) override;
+ void OnTunnelHeadersReceived(
+ const HostPortPair& origin,
+ const HostPortPair& proxy_server,
+ const HttpResponseHeaders& response_headers) override;
+ bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override;
+
+ private:
+ bool on_before_tunnel_request_called_;
+ bool on_tunnel_request_completed_called_;
+ bool on_tunnel_headers_received_called_;
+ net::ProxyServer trusted_spdy_proxy_;
+ HostPortPair on_tunnel_request_completed_endpoint_;
+ HostPortPair on_tunnel_request_completed_proxy_server_;
+ HostPortPair on_tunnel_headers_received_origin_;
+ HostPortPair on_tunnel_headers_received_proxy_server_;
+ std::string on_tunnel_headers_received_status_line_;
+};
+
+} // namespace net
+
+#endif // NET_BASE_TEST_PROXY_DELEGATE_H_ \ No newline at end of file
diff --git a/chromium/net/base/unescape_url_component_fuzzer.cc b/chromium/net/base/unescape_url_component_fuzzer.cc
new file mode 100644
index 00000000000..0053011c1f5
--- /dev/null
+++ b/chromium/net/base/unescape_url_component_fuzzer.cc
@@ -0,0 +1,22 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include <string>
+
+#include "net/base/escape.h"
+
+static const int kMaxUnescapeRule = 31;
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::string path(reinterpret_cast<const char*>(data), size);
+ for (int i = 0; i <= kMaxUnescapeRule; i++) {
+ (void)net::UnescapeURLComponent(path,
+ static_cast<net::UnescapeRule::Type>(i));
+ }
+ return 0;
+}
diff --git a/chromium/net/base/unescape_url_component_fuzzer.dict b/chromium/net/base/unescape_url_component_fuzzer.dict
new file mode 100644
index 00000000000..4569ca15816
--- /dev/null
+++ b/chromium/net/base/unescape_url_component_fuzzer.dict
@@ -0,0 +1,63 @@
+"%2F"
+"%2f"
+"%"
+"%0"
+"%00"
+"%1"
+"%2"
+"%3"
+"%4"
+"%5"
+"%6"
+"%7"
+"%8"
+"%9"
+"%10"
+"%A"
+"%a"
+"%B"
+"%b"
+"%C"
+"%c"
+"%D"
+"%d"
+"%E"
+"%e"
+"%F"
+"%f"
+"\x00"
+"#"
+"%D8"
+"%d8"
+"%9c"
+"%9C"
+"%E2"
+"%e2"
+"%80"
+"%81"
+"%8E"
+"%8F"
+"%AA"
+"%aa"
+"%Aa"
+"%aA"
+"%AE"
+"%ae"
+"%Ae"
+"%aE"
+"%AA"
+"%a6"
+"%A9"
+"%a9"
+"%9F"
+"%9f"
+"%90"
+"%92"
+"%93"
+"/"
+"\\"
+" "
+"x09"
+"\x13"
+"\x10"
+"+" \ No newline at end of file
diff --git a/chromium/net/base/unescape_url_component_fuzzer.options b/chromium/net/base/unescape_url_component_fuzzer.options
new file mode 100644
index 00000000000..0428c8efba2
--- /dev/null
+++ b/chromium/net/base/unescape_url_component_fuzzer.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = random(1, 2048) \ No newline at end of file
diff --git a/chromium/net/base/url_util.cc b/chromium/net/base/url_util.cc
index a5818075ca5..879c746c9b3 100644
--- a/chromium/net/base/url_util.cc
+++ b/chromium/net/base/url_util.cc
@@ -4,12 +4,40 @@
#include "net/base/url_util.h"
+#include "build/build_config.h"
+
+#if defined(OS_POSIX)
+#include <netinet/in.h>
+#elif defined(OS_WIN)
+#include <ws2tcpip.h>
+#endif
+
#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "net/base/escape.h"
+#include "net/base/ip_address.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "url/gurl.h"
+#include "url/url_canon.h"
+#include "url/url_canon_ip.h"
namespace net {
+namespace {
+
+bool IsHostCharAlphanumeric(char c) {
+ // We can just check lowercase because uppercase characters have already been
+ // normalized.
+ return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'));
+}
+
+bool IsNormalizedLocalhostTLD(const std::string& host) {
+ return base::EndsWith(host, ".localhost", base::CompareCase::SENSITIVE);
+}
+
+} // namespace
+
GURL AppendQueryParameter(const GURL& url,
const std::string& name,
const std::string& value) {
@@ -96,10 +124,9 @@ const std::string& QueryIterator::GetUnescapedValue() {
DCHECK(!at_end_);
if (value_.is_nonempty() && unescaped_value_.empty()) {
unescaped_value_ = UnescapeURLComponent(
- GetValue(),
- UnescapeRule::SPACES |
- UnescapeRule::URL_SPECIAL_CHARS |
- UnescapeRule::REPLACE_PLUS_WITH_SPACE);
+ GetValue(), UnescapeRule::SPACES | UnescapeRule::PATH_SEPARATORS |
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS |
+ UnescapeRule::REPLACE_PLUS_WITH_SPACE);
}
return unescaped_value_;
}
@@ -129,7 +156,94 @@ bool GetValueForKeyInQuery(const GURL& url,
return false;
}
-std::string TrimEndingDot(const base::StringPiece& host) {
+bool ParseHostAndPort(std::string::const_iterator host_and_port_begin,
+ std::string::const_iterator host_and_port_end,
+ std::string* host,
+ int* port) {
+ if (host_and_port_begin >= host_and_port_end)
+ return false;
+
+ // When using url, we use char*.
+ const char* auth_begin = &(*host_and_port_begin);
+ int auth_len = host_and_port_end - host_and_port_begin;
+
+ url::Component auth_component(0, auth_len);
+ url::Component username_component;
+ url::Component password_component;
+ url::Component hostname_component;
+ url::Component port_component;
+
+ url::ParseAuthority(auth_begin, auth_component, &username_component,
+ &password_component, &hostname_component, &port_component);
+
+ // There shouldn't be a username/password.
+ if (username_component.is_valid() || password_component.is_valid())
+ return false;
+
+ if (!hostname_component.is_nonempty())
+ return false; // Failed parsing.
+
+ int parsed_port_number = -1;
+ if (port_component.is_nonempty()) {
+ parsed_port_number = url::ParsePort(auth_begin, port_component);
+
+ // If parsing failed, port_number will be either PORT_INVALID or
+ // PORT_UNSPECIFIED, both of which are negative.
+ if (parsed_port_number < 0)
+ return false; // Failed parsing the port number.
+ }
+
+ if (port_component.len == 0)
+ return false; // Reject inputs like "foo:"
+
+ unsigned char tmp_ipv6_addr[16];
+
+ // If the hostname starts with a bracket, it is either an IPv6 literal or
+ // invalid. If it is an IPv6 literal then strip the brackets.
+ if (hostname_component.len > 0 &&
+ auth_begin[hostname_component.begin] == '[') {
+ if (auth_begin[hostname_component.end() - 1] == ']' &&
+ url::IPv6AddressToNumber(
+ auth_begin, hostname_component, tmp_ipv6_addr)) {
+ // Strip the brackets.
+ hostname_component.begin++;
+ hostname_component.len -= 2;
+ } else {
+ return false;
+ }
+ }
+
+ // Pass results back to caller.
+ host->assign(auth_begin + hostname_component.begin, hostname_component.len);
+ *port = parsed_port_number;
+
+ return true; // Success.
+}
+
+bool ParseHostAndPort(const std::string& host_and_port,
+ std::string* host,
+ int* port) {
+ return ParseHostAndPort(
+ host_and_port.begin(), host_and_port.end(), host, port);
+}
+
+
+std::string GetHostAndPort(const GURL& url) {
+ // For IPv6 literals, GURL::host() already includes the brackets so it is
+ // safe to just append a colon.
+ return base::StringPrintf("%s:%d", url.host().c_str(),
+ url.EffectiveIntPort());
+}
+
+std::string GetHostAndOptionalPort(const GURL& url) {
+ // For IPv6 literals, GURL::host() already includes the brackets
+ // so it is safe to just append a colon.
+ if (url.has_port())
+ return base::StringPrintf("%s:%s", url.host().c_str(), url.port().c_str());
+ return url.host();
+}
+
+std::string TrimEndingDot(base::StringPiece host) {
base::StringPiece host_trimmed = host;
size_t len = host_trimmed.length();
if (len > 1 && host_trimmed[len - 1] == '.') {
@@ -138,13 +252,190 @@ std::string TrimEndingDot(const base::StringPiece& host) {
return host_trimmed.as_string();
}
+std::string GetHostOrSpecFromURL(const GURL& url) {
+ return url.has_host() ? TrimEndingDot(url.host_piece()) : url.spec();
+}
+
+std::string CanonicalizeHost(base::StringPiece host,
+ url::CanonHostInfo* host_info) {
+ // Try to canonicalize the host.
+ const url::Component raw_host_component(0, static_cast<int>(host.length()));
+ std::string canon_host;
+ url::StdStringCanonOutput canon_host_output(&canon_host);
+ url::CanonicalizeHostVerbose(host.data(), raw_host_component,
+ &canon_host_output, host_info);
+
+ if (host_info->out_host.is_nonempty() &&
+ host_info->family != url::CanonHostInfo::BROKEN) {
+ // Success! Assert that there's no extra garbage.
+ canon_host_output.Complete();
+ DCHECK_EQ(host_info->out_host.len, static_cast<int>(canon_host.length()));
+ } else {
+ // Empty host, or canonicalization failed. We'll return empty.
+ canon_host.clear();
+ }
+
+ return canon_host;
+}
+
+bool IsCanonicalizedHostCompliant(const std::string& host) {
+ if (host.empty())
+ return false;
+
+ bool in_component = false;
+ bool most_recent_component_started_alphanumeric = false;
+
+ for (std::string::const_iterator i(host.begin()); i != host.end(); ++i) {
+ const char c = *i;
+ if (!in_component) {
+ most_recent_component_started_alphanumeric = IsHostCharAlphanumeric(c);
+ if (!most_recent_component_started_alphanumeric && (c != '-') &&
+ (c != '_')) {
+ return false;
+ }
+ in_component = true;
+ } else if (c == '.') {
+ in_component = false;
+ } else if (!IsHostCharAlphanumeric(c) && (c != '-') && (c != '_')) {
+ return false;
+ }
+ }
+
+ return most_recent_component_started_alphanumeric;
+}
+
+bool IsHostnameNonUnique(const std::string& hostname) {
+ // CanonicalizeHost requires surrounding brackets to parse an IPv6 address.
+ const std::string host_or_ip = hostname.find(':') != std::string::npos ?
+ "[" + hostname + "]" : hostname;
+ url::CanonHostInfo host_info;
+ std::string canonical_name = CanonicalizeHost(host_or_ip, &host_info);
+
+ // If canonicalization fails, then the input is truly malformed. However,
+ // to avoid mis-reporting bad inputs as "non-unique", treat them as unique.
+ if (canonical_name.empty())
+ return false;
+
+ // If |hostname| is an IP address, check to see if it's in an IANA-reserved
+ // range.
+ if (host_info.IsIPAddress()) {
+ IPAddress host_addr;
+ if (!host_addr.AssignFromIPLiteral(hostname.substr(
+ host_info.out_host.begin, host_info.out_host.len))) {
+ return false;
+ }
+ switch (host_info.family) {
+ case url::CanonHostInfo::IPV4:
+ case url::CanonHostInfo::IPV6:
+ return host_addr.IsReserved();
+ case url::CanonHostInfo::NEUTRAL:
+ case url::CanonHostInfo::BROKEN:
+ return false;
+ }
+ }
+
+ // Check for a registry controlled portion of |hostname|, ignoring private
+ // registries, as they already chain to ICANN-administered registries,
+ // and explicitly ignoring unknown registries.
+ //
+ // Note: This means that as new gTLDs are introduced on the Internet, they
+ // will be treated as non-unique until the registry controlled domain list
+ // is updated. However, because gTLDs are expected to provide significant
+ // advance notice to deprecate older versions of this code, this an
+ // acceptable tradeoff.
+ return 0 == registry_controlled_domains::GetRegistryLength(
+ canonical_name,
+ registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
+ registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
+}
+
+bool IsLocalhost(base::StringPiece host) {
+ if (IsLocalHostname(host, nullptr))
+ return true;
+
+ IPAddress ip_address;
+ if (ip_address.AssignFromIPLiteral(host)) {
+ size_t size = ip_address.size();
+ switch (size) {
+ case IPAddress::kIPv4AddressSize: {
+ const uint8_t prefix[] = {127};
+ return IPAddressStartsWith(ip_address, prefix);
+ }
+
+ case IPAddress::kIPv6AddressSize:
+ return ip_address == IPAddress::IPv6Localhost();
+
+ default:
+ NOTREACHED();
+ }
+ }
+
+ return false;
+}
+
+GURL SimplifyUrlForRequest(const GURL& url) {
+ DCHECK(url.is_valid());
+ GURL::Replacements replacements;
+ replacements.ClearUsername();
+ replacements.ClearPassword();
+ replacements.ClearRef();
+ return url.ReplaceComponents(replacements);
+}
+
void GetIdentityFromURL(const GURL& url,
base::string16* username,
base::string16* password) {
UnescapeRule::Type flags =
- UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS;
+ UnescapeRule::SPACES | UnescapeRule::PATH_SEPARATORS |
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS;
*username = UnescapeAndDecodeUTF8URLComponent(url.username(), flags);
*password = UnescapeAndDecodeUTF8URLComponent(url.password(), flags);
}
+bool HasGoogleHost(const GURL& url) {
+ static const char* kGoogleHostSuffixes[] = {
+ ".google.com",
+ ".youtube.com",
+ ".gmail.com",
+ ".doubleclick.net",
+ ".gstatic.com",
+ ".googlevideo.com",
+ ".googleusercontent.com",
+ ".googlesyndication.com",
+ ".google-analytics.com",
+ ".googleadservices.com",
+ ".googleapis.com",
+ ".ytimg.com",
+ };
+ base::StringPiece host = url.host_piece();
+ for (const char* suffix : kGoogleHostSuffixes) {
+ // Here it's possible to get away with faster case-sensitive comparisons
+ // because the list above is all lowercase, and a GURL's host name will
+ // always be canonicalized to lowercase as well.
+ if (base::EndsWith(host, suffix, base::CompareCase::SENSITIVE))
+ return true;
+ }
+ return false;
+}
+
+bool IsLocalHostname(base::StringPiece host, bool* is_local6) {
+ std::string normalized_host = base::ToLowerASCII(host);
+ // Remove any trailing '.'.
+ if (!normalized_host.empty() && *normalized_host.rbegin() == '.')
+ normalized_host.resize(normalized_host.size() - 1);
+
+ if (normalized_host == "localhost6" ||
+ normalized_host == "localhost6.localdomain6") {
+ if (is_local6)
+ *is_local6 = true;
+ return true;
+ }
+
+ if (is_local6)
+ *is_local6 = false;
+ return normalized_host == "localhost" ||
+ normalized_host == "localhost.localdomain" ||
+ IsNormalizedLocalhostTLD(normalized_host);
+}
+
} // namespace net
diff --git a/chromium/net/base/url_util.h b/chromium/net/base/url_util.h
index 239a93cd4d7..75f7b620be0 100644
--- a/chromium/net/base/url_util.h
+++ b/chromium/net/base/url_util.h
@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// This file contains a set of utility functions related to parsing,
+// manipulating, and interacting with URLs and hostnames. These functions are
+// intended to be of a text-processing nature, and should not attempt to use any
+// networking or blocking services.
+
#ifndef NET_BASE_URL_UTIL_H_
#define NET_BASE_URL_UTIL_H_
@@ -15,6 +20,10 @@
class GURL;
+namespace url {
+struct CanonHostInfo;
+}
+
namespace net {
// Returns a new GURL by appending the given query parameter name and the
@@ -79,9 +88,72 @@ NET_EXPORT bool GetValueForKeyInQuery(const GURL& url,
const std::string& search_key,
std::string* out_value);
+// Splits an input of the form <host>[":"<port>] into its consitituent parts.
+// Saves the result into |*host| and |*port|. If the input did not have
+// the optional port, sets |*port| to -1.
+// Returns true if the parsing was successful, false otherwise.
+// The returned host is NOT canonicalized, and may be invalid.
+//
+// IPv6 literals must be specified in a bracketed form, for instance:
+// [::1]:90 and [::1]
+//
+// The resultant |*host| in both cases will be "::1" (not bracketed).
+NET_EXPORT bool ParseHostAndPort(
+ std::string::const_iterator host_and_port_begin,
+ std::string::const_iterator host_and_port_end,
+ std::string* host,
+ int* port);
+NET_EXPORT bool ParseHostAndPort(const std::string& host_and_port,
+ std::string* host,
+ int* port);
+
+// Returns a host:port string for the given URL.
+NET_EXPORT std::string GetHostAndPort(const GURL& url);
+
+// Returns a host[:port] string for the given URL, where the port is omitted
+// if it is the default for the URL's scheme.
+NET_EXPORT std::string GetHostAndOptionalPort(const GURL& url);
// Returns the hostname by trimming the ending dot, if one exists.
-NET_EXPORT std::string TrimEndingDot(const base::StringPiece& host);
+NET_EXPORT std::string TrimEndingDot(base::StringPiece host);
+
+// Returns either the host from |url|, or, if the host is empty, the full spec.
+NET_EXPORT std::string GetHostOrSpecFromURL(const GURL& url);
+
+// Canonicalizes |host| and returns it. Also fills |host_info| with
+// IP address information. |host_info| must not be NULL.
+NET_EXPORT std::string CanonicalizeHost(base::StringPiece host,
+ url::CanonHostInfo* host_info);
+
+// Returns true if |host| is not an IP address and is compliant with a set of
+// rules based on RFC 1738 and tweaked to be compatible with the real world.
+// The rules are:
+// * One or more components separated by '.'
+// * Each component contains only alphanumeric characters and '-' or '_'
+// * The last component begins with an alphanumeric character
+// * Optional trailing dot after last component (means "treat as FQDN")
+//
+// NOTE: You should only pass in hosts that have been returned from
+// CanonicalizeHost(), or you may not get accurate results.
+NET_EXPORT bool IsCanonicalizedHostCompliant(const std::string& host);
+
+// Returns true if |hostname| contains a non-registerable or non-assignable
+// domain name (eg: a gTLD that has not been assigned by IANA) or an IP address
+// that falls in an IANA-reserved range.
+NET_EXPORT bool IsHostnameNonUnique(const std::string& hostname);
+
+// Returns true if |host| is one of the local hostnames
+// (e.g. "localhost") or IP addresses (IPv4 127.0.0.0/8 or IPv6 ::1).
+//
+// Note that this function does not check for IP addresses other than
+// the above, although other IP addresses may point to the local
+// machine.
+NET_EXPORT bool IsLocalhost(base::StringPiece host);
+
+// Strip the portions of |url| that aren't core to the network request.
+// - user name / password
+// - reference section
+NET_EXPORT GURL SimplifyUrlForRequest(const GURL& url);
// Extracts the unescaped username/password from |url|, saving the results
// into |*username| and |*password|.
@@ -89,6 +161,17 @@ NET_EXPORT_PRIVATE void GetIdentityFromURL(const GURL& url,
base::string16* username,
base::string16* password);
+// Returns true if the url's host is a Google server. This should only be used
+// for histograms and shouldn't be used to affect behavior.
+NET_EXPORT_PRIVATE bool HasGoogleHost(const GURL& url);
+
+// This function tests |host| to see if it is of any local hostname form.
+// |host| is normalized before being tested and if |is_local6| is not NULL then
+// it it will be set to true if the localhost name implies an IPv6 interface (
+// for instance localhost6.localdomain6).
+NET_EXPORT_PRIVATE bool IsLocalHostname(base::StringPiece host,
+ bool* is_local6);
+
} // namespace net
#endif // NET_BASE_URL_UTIL_H_
diff --git a/chromium/net/base/url_util_unittest.cc b/chromium/net/base/url_util_unittest.cc
index 863e5528721..3a7a1b4240c 100644
--- a/chromium/net/base/url_util_unittest.cc
+++ b/chromium/net/base/url_util_unittest.cc
@@ -4,6 +4,8 @@
#include "net/base/url_util.h"
+#include <ostream>
+
#include "base/format_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/strings/stringprintf.h"
@@ -165,7 +167,316 @@ TEST(UrlUtilTest, ParseQueryInvalidURL) {
EXPECT_TRUE(it.IsAtEnd());
}
-TEST(NetUtilTest, GetIdentityFromURL) {
+TEST(UrlUtilTest, ParseHostAndPort) {
+ const struct {
+ const char* const input;
+ bool success;
+ const char* const expected_host;
+ int expected_port;
+ } tests[] = {
+ // Valid inputs:
+ {"foo:10", true, "foo", 10},
+ {"foo", true, "foo", -1},
+ {
+ "[1080:0:0:0:8:800:200C:4171]:11",
+ true,
+ "1080:0:0:0:8:800:200C:4171",
+ 11
+ },
+ {
+ "[1080:0:0:0:8:800:200C:4171]",
+ true,
+ "1080:0:0:0:8:800:200C:4171",
+ -1
+ },
+
+ // Because no validation is done on the host, the following are accepted,
+ // even though they are invalid names.
+ {"]", true, "]", -1},
+ {"::1", true, ":", 1},
+ // Invalid inputs:
+ {"foo:bar", false, "", -1},
+ {"foo:", false, "", -1},
+ {":", false, "", -1},
+ {":80", false, "", -1},
+ {"", false, "", -1},
+ {"porttoolong:300000", false, "", -1},
+ {"usrname@host", false, "", -1},
+ {"usrname:password@host", false, "", -1},
+ {":password@host", false, "", -1},
+ {":password@host:80", false, "", -1},
+ {":password@host", false, "", -1},
+ {"@host", false, "", -1},
+ {"[", false, "", -1},
+ {"[]", false, "", -1},
+ };
+
+ for (size_t i = 0; i < arraysize(tests); ++i) {
+ std::string host;
+ int port;
+ bool ok = ParseHostAndPort(tests[i].input, &host, &port);
+
+ EXPECT_EQ(tests[i].success, ok);
+
+ if (tests[i].success) {
+ EXPECT_EQ(tests[i].expected_host, host);
+ EXPECT_EQ(tests[i].expected_port, port);
+ }
+ }
+}
+TEST(UrlUtilTest, GetHostAndPort) {
+ const struct {
+ GURL url;
+ const char* const expected_host_and_port;
+ } tests[] = {
+ { GURL("http://www.foo.com/x"), "www.foo.com:80"},
+ { GURL("http://www.foo.com:21/x"), "www.foo.com:21"},
+
+ // For IPv6 literals should always include the brackets.
+ { GURL("http://[1::2]/x"), "[1::2]:80"},
+ { GURL("http://[::a]:33/x"), "[::a]:33"},
+ };
+ for (size_t i = 0; i < arraysize(tests); ++i) {
+ std::string host_and_port = GetHostAndPort(tests[i].url);
+ EXPECT_EQ(std::string(tests[i].expected_host_and_port), host_and_port);
+ }
+}
+
+TEST(UrlUtilTest, GetHostAndOptionalPort) {
+ const struct {
+ GURL url;
+ const char* const expected_host_and_port;
+ } tests[] = {
+ { GURL("http://www.foo.com/x"), "www.foo.com"},
+ { GURL("http://www.foo.com:21/x"), "www.foo.com:21"},
+
+ // For IPv6 literals should always include the brackets.
+ { GURL("http://[1::2]/x"), "[1::2]"},
+ { GURL("http://[::a]:33/x"), "[::a]:33"},
+ };
+ for (size_t i = 0; i < arraysize(tests); ++i) {
+ std::string host_and_port = GetHostAndOptionalPort(tests[i].url);
+ EXPECT_EQ(std::string(tests[i].expected_host_and_port), host_and_port);
+ }
+}
+
+TEST(UrlUtilTest, GetHostOrSpecFromURL) {
+ EXPECT_EQ("example.com",
+ GetHostOrSpecFromURL(GURL("http://example.com/test")));
+ EXPECT_EQ("example.com",
+ GetHostOrSpecFromURL(GURL("http://example.com./test")));
+ EXPECT_EQ("file:///tmp/test.html",
+ GetHostOrSpecFromURL(GURL("file:///tmp/test.html")));
+}
+
+TEST(UrlUtilTest, CompliantHost) {
+ struct {
+ const char* const host;
+ bool expected_output;
+ } compliant_host_cases[] = {
+ {"", false},
+ {"a", true},
+ {"-", false},
+ {"_", false},
+ {".", false},
+ {"9", true},
+ {"9a", true},
+ {"9_", true},
+ {"a.", true},
+ {"a.a", true},
+ {"9.a", true},
+ {"a.9", true},
+ {"_9a", false},
+ {"-9a", false},
+ {"a.a9", true},
+ {"_.9a", true},
+ {"a.-a9", false},
+ {"a+9a", false},
+ {"-a.a9", true},
+ {"a_.a9", true},
+ {"1-.a-b", true},
+ {"1_.a-b", true},
+ {"1-2.a_b", true},
+ {"a.b.c.d.e", true},
+ {"1.2.3.4.5", true},
+ {"1.2.3.4.5.", true},
+ };
+
+ for (size_t i = 0; i < arraysize(compliant_host_cases); ++i) {
+ EXPECT_EQ(compliant_host_cases[i].expected_output,
+ IsCanonicalizedHostCompliant(compliant_host_cases[i].host));
+ }
+}
+
+struct NonUniqueNameTestData {
+ bool is_unique;
+ const char* const hostname;
+};
+
+// Google Test pretty-printer.
+void PrintTo(const NonUniqueNameTestData& data, std::ostream* os) {
+ ASSERT_TRUE(data.hostname);
+ *os << " hostname: " << testing::PrintToString(data.hostname)
+ << "; is_unique: " << testing::PrintToString(data.is_unique);
+}
+
+const NonUniqueNameTestData kNonUniqueNameTestData[] = {
+ // Domains under ICANN-assigned domains.
+ { true, "google.com" },
+ { true, "google.co.uk" },
+ // Domains under private registries.
+ { true, "appspot.com" },
+ { true, "test.appspot.com" },
+ // Unreserved IPv4 addresses (in various forms).
+ { true, "8.8.8.8" },
+ { true, "99.64.0.0" },
+ { true, "212.15.0.0" },
+ { true, "212.15" },
+ { true, "212.15.0" },
+ { true, "3557752832" },
+ // Reserved IPv4 addresses (in various forms).
+ { false, "192.168.0.0" },
+ { false, "192.168.0.6" },
+ { false, "10.0.0.5" },
+ { false, "10.0" },
+ { false, "10.0.0" },
+ { false, "3232235526" },
+ // Unreserved IPv6 addresses.
+ { true, "FFC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
+ { true, "2000:ba98:7654:2301:EFCD:BA98:7654:3210" },
+ // Reserved IPv6 addresses.
+ { false, "::192.9.5.5" },
+ { false, "FEED::BEEF" },
+ { false, "FEC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
+ // 'internal'/non-IANA assigned domains.
+ { false, "intranet" },
+ { false, "intranet." },
+ { false, "intranet.example" },
+ { false, "host.intranet.example" },
+ // gTLDs under discussion, but not yet assigned.
+ { false, "intranet.corp" },
+ { false, "intranet.internal" },
+ // Invalid host names are treated as unique - but expected to be
+ // filtered out before then.
+ { true, "junk)(£)$*!@~#" },
+ { true, "w$w.example.com" },
+ { true, "nocolonsallowed:example" },
+ { true, "[::4.5.6.9]" },
+};
+
+class UrlUtilNonUniqueNameTest
+ : public testing::TestWithParam<NonUniqueNameTestData> {
+ public:
+ virtual ~UrlUtilNonUniqueNameTest() {}
+
+ protected:
+ bool IsUnique(const std::string& hostname) {
+ return !IsHostnameNonUnique(hostname);
+ }
+};
+
+// Test that internal/non-unique names are properly identified as such, but
+// that IP addresses and hosts beneath registry-controlled domains are flagged
+// as unique names.
+TEST_P(UrlUtilNonUniqueNameTest, IsHostnameNonUnique) {
+ const NonUniqueNameTestData& test_data = GetParam();
+
+ EXPECT_EQ(test_data.is_unique, IsUnique(test_data.hostname));
+}
+
+INSTANTIATE_TEST_CASE_P(, UrlUtilNonUniqueNameTest,
+ testing::ValuesIn(kNonUniqueNameTestData));
+
+TEST(UrlUtilTest, IsLocalhost) {
+ EXPECT_TRUE(IsLocalhost("localhost"));
+ EXPECT_TRUE(IsLocalhost("localHosT"));
+ EXPECT_TRUE(IsLocalhost("localhost."));
+ EXPECT_TRUE(IsLocalhost("localHost."));
+ EXPECT_TRUE(IsLocalhost("localhost.localdomain"));
+ EXPECT_TRUE(IsLocalhost("localhost.localDOMain"));
+ EXPECT_TRUE(IsLocalhost("localhost.localdomain."));
+ EXPECT_TRUE(IsLocalhost("localhost6"));
+ EXPECT_TRUE(IsLocalhost("localhost6."));
+ EXPECT_TRUE(IsLocalhost("localhost6.localdomain6"));
+ EXPECT_TRUE(IsLocalhost("localhost6.localdomain6."));
+ EXPECT_TRUE(IsLocalhost("127.0.0.1"));
+ EXPECT_TRUE(IsLocalhost("127.0.1.0"));
+ EXPECT_TRUE(IsLocalhost("127.1.0.0"));
+ EXPECT_TRUE(IsLocalhost("127.0.0.255"));
+ EXPECT_TRUE(IsLocalhost("127.0.255.0"));
+ EXPECT_TRUE(IsLocalhost("127.255.0.0"));
+ EXPECT_TRUE(IsLocalhost("::1"));
+ EXPECT_TRUE(IsLocalhost("0:0:0:0:0:0:0:1"));
+ EXPECT_TRUE(IsLocalhost("foo.localhost"));
+ EXPECT_TRUE(IsLocalhost("foo.localhost."));
+ EXPECT_TRUE(IsLocalhost("foo.localhoST"));
+ EXPECT_TRUE(IsLocalhost("foo.localhoST."));
+
+ EXPECT_FALSE(IsLocalhost("localhostx"));
+ EXPECT_FALSE(IsLocalhost("localhost.x"));
+ EXPECT_FALSE(IsLocalhost("foo.localdomain"));
+ EXPECT_FALSE(IsLocalhost("foo.localdomain.x"));
+ EXPECT_FALSE(IsLocalhost("localhost6x"));
+ EXPECT_FALSE(IsLocalhost("localhost.localdomain6"));
+ EXPECT_FALSE(IsLocalhost("localhost6.localdomain"));
+ EXPECT_FALSE(IsLocalhost("127.0.0.1.1"));
+ EXPECT_FALSE(IsLocalhost(".127.0.0.255"));
+ EXPECT_FALSE(IsLocalhost("::2"));
+ EXPECT_FALSE(IsLocalhost("::1:1"));
+ EXPECT_FALSE(IsLocalhost("0:0:0:0:1:0:0:1"));
+ EXPECT_FALSE(IsLocalhost("::1:1"));
+ EXPECT_FALSE(IsLocalhost("0:0:0:0:0:0:0:0:1"));
+ EXPECT_FALSE(IsLocalhost("foo.localhost.com"));
+ EXPECT_FALSE(IsLocalhost("foo.localhoste"));
+ EXPECT_FALSE(IsLocalhost("foo.localhos"));
+}
+
+TEST(UrlUtilTest, SimplifyUrlForRequest) {
+ struct {
+ const char* const input_url;
+ const char* const expected_simplified_url;
+ } tests[] = {
+ {
+ // Reference section should be stripped.
+ "http://www.google.com:78/foobar?query=1#hash",
+ "http://www.google.com:78/foobar?query=1",
+ },
+ {
+ // Reference section can itself contain #.
+ "http://192.168.0.1?query=1#hash#10#11#13#14",
+ "http://192.168.0.1?query=1",
+ },
+ { // Strip username/password.
+ "http://user:pass@google.com",
+ "http://google.com/",
+ },
+ { // Strip both the reference and the username/password.
+ "http://user:pass@google.com:80/sup?yo#X#X",
+ "http://google.com/sup?yo",
+ },
+ { // Try an HTTPS URL -- strip both the reference and the username/password.
+ "https://user:pass@google.com:80/sup?yo#X#X",
+ "https://google.com:80/sup?yo",
+ },
+ { // Try an FTP URL -- strip both the reference and the username/password.
+ "ftp://user:pass@google.com:80/sup?yo#X#X",
+ "ftp://google.com:80/sup?yo",
+ },
+ { // Try a nonstandard URL
+ "foobar://user:pass@google.com:80/sup?yo#X#X",
+ "foobar://user:pass@google.com:80/sup?yo",
+ },
+ };
+ for (size_t i = 0; i < arraysize(tests); ++i) {
+ SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i,
+ tests[i].input_url));
+ GURL input_url(GURL(tests[i].input_url));
+ GURL expected_url(GURL(tests[i].expected_simplified_url));
+ EXPECT_EQ(expected_url, SimplifyUrlForRequest(input_url));
+ }
+}
+
+TEST(UrlUtilTest, GetIdentityFromURL) {
struct {
const char* const input_url;
const char* const expected_username;
@@ -236,5 +547,40 @@ TEST(UrlUtilTest, GetIdentityFromURL_UTF8) {
EXPECT_EQ(WideToUTF16(L"\x4f60\x597d"), password);
}
+TEST(UrlUtilTest, GoogleHost) {
+ struct {
+ GURL url;
+ bool expected_output;
+ } google_host_cases[] = {
+ {GURL("http://.google.com"), true},
+ {GURL("http://.youtube.com"), true},
+ {GURL("http://.gmail.com"), true},
+ {GURL("http://.doubleclick.net"), true},
+ {GURL("http://.gstatic.com"), true},
+ {GURL("http://.googlevideo.com"), true},
+ {GURL("http://.googleusercontent.com"), true},
+ {GURL("http://.googlesyndication.com"), true},
+ {GURL("http://.google-analytics.com"), true},
+ {GURL("http://.googleadservices.com"), true},
+ {GURL("http://.googleapis.com"), true},
+ {GURL("http://a.google.com"), true},
+ {GURL("http://b.youtube.com"), true},
+ {GURL("http://c.gmail.com"), true},
+ {GURL("http://google.com"), false},
+ {GURL("http://youtube.com"), false},
+ {GURL("http://gmail.com"), false},
+ {GURL("http://google.coma"), false},
+ {GURL("http://agoogle.com"), false},
+ {GURL("http://oogle.com"), false},
+ {GURL("http://google.co"), false},
+ {GURL("http://oggole.com"), false},
+ };
+
+ for (size_t i = 0; i < arraysize(google_host_cases); ++i) {
+ EXPECT_EQ(google_host_cases[i].expected_output,
+ HasGoogleHost(google_host_cases[i].url));
+ }
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/cert/asn1_util.cc b/chromium/net/cert/asn1_util.cc
index 315ca75e648..6b0b71d9024 100644
--- a/chromium/net/cert/asn1_util.cc
+++ b/chromium/net/cert/asn1_util.cc
@@ -185,7 +185,7 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert,
// CRL Distribution Points extension.
static const uint8_t kCRLDistributionPointsOID[] = {0x55, 0x1d, 0x1f};
- if (!oid.Equals(der::Input(kCRLDistributionPointsOID)))
+ if (oid != der::Input(kCRLDistributionPointsOID))
continue;
// critical
diff --git a/chromium/net/cert/cert_database.cc b/chromium/net/cert/cert_database.cc
index 7b85fc74d9d..3d423b0c4f4 100644
--- a/chromium/net/cert/cert_database.cc
+++ b/chromium/net/cert/cert_database.cc
@@ -27,18 +27,18 @@ void CertDatabase::RemoveObserver(Observer* observer) {
void CertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) {
observer_list_->Notify(FROM_HERE, &Observer::OnCertAdded,
- make_scoped_refptr(cert));
+ base::RetainedRef(cert));
}
void CertDatabase::NotifyObserversOfCertRemoved(const X509Certificate* cert) {
observer_list_->Notify(FROM_HERE, &Observer::OnCertRemoved,
- make_scoped_refptr(cert));
+ base::RetainedRef(cert));
}
void CertDatabase::NotifyObserversOfCACertChanged(
const X509Certificate* cert) {
observer_list_->Notify(FROM_HERE, &Observer::OnCACertChanged,
- make_scoped_refptr(cert));
+ base::RetainedRef(cert));
}
} // namespace net
diff --git a/chromium/net/cert/cert_database_android.cc b/chromium/net/cert/cert_database_android.cc
index d9b0dfcd024..89a1a44a54b 100644
--- a/chromium/net/cert/cert_database_android.cc
+++ b/chromium/net/cert/cert_database_android.cc
@@ -48,8 +48,7 @@ void CertDatabase::OnAndroidKeyStoreChanged() {
}
void CertDatabase::OnAndroidKeyChainChanged() {
- observer_list_->Notify(FROM_HERE, &Observer::OnCACertChanged,
- scoped_refptr<X509Certificate>());
+ observer_list_->Notify(FROM_HERE, &Observer::OnCACertChanged, nullptr);
}
} // namespace net
diff --git a/chromium/net/cert/cert_database_win.cc b/chromium/net/cert/cert_database_win.cc
index ef8147bdab5..bda2ef02a49 100644
--- a/chromium/net/cert/cert_database_win.cc
+++ b/chromium/net/cert/cert_database_win.cc
@@ -11,8 +11,6 @@
#include "net/base/net_errors.h"
#include "net/cert/x509_certificate.h"
-#pragma comment(lib, "crypt32.lib")
-
namespace net {
CertDatabase::CertDatabase()
diff --git a/chromium/net/cert/cert_verify_proc.cc b/chromium/net/cert/cert_verify_proc.cc
index bdb4b871b4d..9c8267de69e 100644
--- a/chromium/net/cert/cert_verify_proc.cc
+++ b/chromium/net/cert/cert_verify_proc.cc
@@ -6,6 +6,8 @@
#include <stdint.h>
+#include <algorithm>
+
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_macros.h"
#include "base/sha1.h"
@@ -14,8 +16,8 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/base/url_util.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/cert_verify_proc_whitelist.h"
@@ -24,12 +26,14 @@
#include "net/cert/x509_certificate.h"
#include "url/url_canon.h"
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
#include "net/cert/cert_verify_proc_nss.h"
#elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
#include "net/cert/cert_verify_proc_openssl.h"
#elif defined(OS_ANDROID)
#include "net/cert/cert_verify_proc_android.h"
+#elif defined(OS_IOS)
+#include "net/cert/cert_verify_proc_ios.h"
#elif defined(OS_MACOSX)
#include "net/cert/cert_verify_proc_mac.h"
#elif defined(OS_WIN)
@@ -178,16 +182,37 @@ bool IsPastSHA1DeprecationDate(const X509Certificate& cert) {
return start >= kSHA1DeprecationDate;
}
+// Comparison functor used for binary searching whether a given HashValue,
+// which MUST be a SHA-256 hash, is contained with an array of SHA-256
+// hashes.
+struct HashToArrayComparator {
+ template <size_t N>
+ bool operator()(const uint8_t(&lhs)[N], const HashValue& rhs) const {
+ static_assert(N == crypto::kSHA256Length,
+ "Only SHA-256 hashes are supported");
+ return memcmp(lhs, rhs.data(), crypto::kSHA256Length) < 0;
+ }
+
+ template <size_t N>
+ bool operator()(const HashValue& lhs, const uint8_t(&rhs)[N]) const {
+ static_assert(N == crypto::kSHA256Length,
+ "Only SHA-256 hashes are supported");
+ return memcmp(lhs.data(), rhs, crypto::kSHA256Length) < 0;
+ }
+};
+
} // namespace
// static
CertVerifyProc* CertVerifyProc::CreateDefault() {
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
return new CertVerifyProcNSS();
#elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
return new CertVerifyProcOpenSSL();
#elif defined(OS_ANDROID)
return new CertVerifyProcAndroid();
+#elif defined(OS_IOS)
+ return new CertVerifyProcIOS();
#elif defined(OS_MACOSX)
return new CertVerifyProcMac();
#elif defined(OS_WIN)
@@ -319,70 +344,6 @@ int CertVerifyProc::Verify(X509Certificate* cert,
// static
bool CertVerifyProc::IsBlacklisted(X509Certificate* cert) {
- static const unsigned kComodoSerialBytes = 16;
- static const uint8_t kComodoSerials[][kComodoSerialBytes] = {
- // Not a real certificate. For testing only.
- {0x07,0x7a,0x59,0xbc,0xd5,0x34,0x59,0x60,0x1c,0xa6,0x90,0x72,0x67,0xa6,0xdd,0x1c},
-
- // The next nine certificates all expire on Fri Mar 14 23:59:59 2014.
- // Some serial numbers actually have a leading 0x00 byte required to
- // encode a positive integer in DER if the most significant bit is 0.
- // We omit the leading 0x00 bytes to make all serial numbers 16 bytes.
-
- // Subject: CN=mail.google.com
- // subjectAltName dNSName: mail.google.com, www.mail.google.com
- {0x04,0x7e,0xcb,0xe9,0xfc,0xa5,0x5f,0x7b,0xd0,0x9e,0xae,0x36,0xe1,0x0c,0xae,0x1e},
- // Subject: CN=global trustee
- // subjectAltName dNSName: global trustee
- // Note: not a CA certificate.
- {0xd8,0xf3,0x5f,0x4e,0xb7,0x87,0x2b,0x2d,0xab,0x06,0x92,0xe3,0x15,0x38,0x2f,0xb0},
- // Subject: CN=login.live.com
- // subjectAltName dNSName: login.live.com, www.login.live.com
- {0xb0,0xb7,0x13,0x3e,0xd0,0x96,0xf9,0xb5,0x6f,0xae,0x91,0xc8,0x74,0xbd,0x3a,0xc0},
- // Subject: CN=addons.mozilla.org
- // subjectAltName dNSName: addons.mozilla.org, www.addons.mozilla.org
- {0x92,0x39,0xd5,0x34,0x8f,0x40,0xd1,0x69,0x5a,0x74,0x54,0x70,0xe1,0xf2,0x3f,0x43},
- // Subject: CN=login.skype.com
- // subjectAltName dNSName: login.skype.com, www.login.skype.com
- {0xe9,0x02,0x8b,0x95,0x78,0xe4,0x15,0xdc,0x1a,0x71,0x0a,0x2b,0x88,0x15,0x44,0x47},
- // Subject: CN=login.yahoo.com
- // subjectAltName dNSName: login.yahoo.com, www.login.yahoo.com
- {0xd7,0x55,0x8f,0xda,0xf5,0xf1,0x10,0x5b,0xb2,0x13,0x28,0x2b,0x70,0x77,0x29,0xa3},
- // Subject: CN=www.google.com
- // subjectAltName dNSName: www.google.com, google.com
- {0xf5,0xc8,0x6a,0xf3,0x61,0x62,0xf1,0x3a,0x64,0xf5,0x4f,0x6d,0xc9,0x58,0x7c,0x06},
- // Subject: CN=login.yahoo.com
- // subjectAltName dNSName: login.yahoo.com
- {0x39,0x2a,0x43,0x4f,0x0e,0x07,0xdf,0x1f,0x8a,0xa3,0x05,0xde,0x34,0xe0,0xc2,0x29},
- // Subject: CN=login.yahoo.com
- // subjectAltName dNSName: login.yahoo.com
- {0x3e,0x75,0xce,0xd4,0x6b,0x69,0x30,0x21,0x21,0x88,0x30,0xae,0x86,0xa8,0x2a,0x71},
- };
-
- const std::string& serial_number = cert->serial_number();
- if (!serial_number.empty() && (serial_number[0] & 0x80) != 0) {
- // This is a negative serial number, which isn't technically allowed but
- // which probably happens. In order to avoid confusing a negative serial
- // number with a positive one once the leading zeros have been removed, we
- // disregard it.
- return false;
- }
-
- base::StringPiece serial(serial_number);
- // Remove leading zeros.
- while (serial.size() > 1 && serial[0] == 0)
- serial.remove_prefix(1);
-
- if (serial.size() == kComodoSerialBytes) {
- for (unsigned i = 0; i < arraysize(kComodoSerials); i++) {
- if (memcmp(kComodoSerials[i], serial.data(), kComodoSerialBytes) == 0) {
- UMA_HISTOGRAM_ENUMERATION("Net.SSLCertBlacklisted", i,
- arraysize(kComodoSerials) + 1);
- return true;
- }
- }
- }
-
// CloudFlare revoked all certificates issued prior to April 2nd, 2014. Thus
// all certificates where the CN ends with ".cloudflare.com" with a prior
// issuance date are rejected.
@@ -406,125 +367,19 @@ bool CertVerifyProc::IsBlacklisted(X509Certificate* cert) {
}
// static
-// NOTE: This implementation assumes and enforces that the hashes are SHA1.
bool CertVerifyProc::IsPublicKeyBlacklisted(
const HashValueVector& public_key_hashes) {
- static const unsigned kNumSHA1Hashes = 14;
- static const uint8_t kSHA1Hashes[kNumSHA1Hashes][base::kSHA1Length] = {
- // Subject: CN=DigiNotar Root CA
- // Issuer: CN=Entrust.net x2 and self-signed
- {0x41, 0x0f, 0x36, 0x36, 0x32, 0x58, 0xf3, 0x0b, 0x34, 0x7d,
- 0x12, 0xce, 0x48, 0x63, 0xe4, 0x33, 0x43, 0x78, 0x06, 0xa8},
- // Subject: CN=DigiNotar Cyber CA
- // Issuer: CN=GTE CyberTrust Global Root
- {0xc4, 0xf9, 0x66, 0x37, 0x16, 0xcd, 0x5e, 0x71, 0xd6, 0x95,
- 0x0b, 0x5f, 0x33, 0xce, 0x04, 0x1c, 0x95, 0xb4, 0x35, 0xd1},
- // Subject: CN=DigiNotar Services 1024 CA
- // Issuer: CN=Entrust.net
- {0xe2, 0x3b, 0x8d, 0x10, 0x5f, 0x87, 0x71, 0x0a, 0x68, 0xd9,
- 0x24, 0x80, 0x50, 0xeb, 0xef, 0xc6, 0x27, 0xbe, 0x4c, 0xa6},
- // Subject: CN=DigiNotar PKIoverheid CA Organisatie - G2
- // Issuer: CN=Staat der Nederlanden Organisatie CA - G2
- {0x7b, 0x2e, 0x16, 0xbc, 0x39, 0xbc, 0xd7, 0x2b, 0x45, 0x6e,
- 0x9f, 0x05, 0x5d, 0x1d, 0xe6, 0x15, 0xb7, 0x49, 0x45, 0xdb},
- // Subject: CN=DigiNotar PKIoverheid CA Overheid en Bedrijven
- // Issuer: CN=Staat der Nederlanden Overheid CA
- {0xe8, 0xf9, 0x12, 0x00, 0xc6, 0x5c, 0xee, 0x16, 0xe0, 0x39,
- 0xb9, 0xf8, 0x83, 0x84, 0x16, 0x61, 0x63, 0x5f, 0x81, 0xc5},
- // Issuer: CN=Trustwave Organization Issuing CA, Level 2
- // Covers two certificates, the latter of which expires Apr 15 21:09:30
- // 2021 GMT.
- {0xe1, 0x2d, 0x89, 0xf5, 0x6d, 0x22, 0x76, 0xf8, 0x30, 0xe6,
- 0xce, 0xaf, 0xa6, 0x6c, 0x72, 0x5c, 0x0b, 0x41, 0xa9, 0x32},
- // Cyberoam CA certificate. Private key leaked, but this certificate would
- // only have been installed by Cyberoam customers. The certificate expires
- // in 2036, but we can probably remove in a couple of years (2014).
- {0xd9, 0xf5, 0xc6, 0xce, 0x57, 0xff, 0xaa, 0x39, 0xcc, 0x7e,
- 0xd1, 0x72, 0xbd, 0x53, 0xe0, 0xd3, 0x07, 0x83, 0x4b, 0xd1},
- // Win32/Sirefef.gen!C generates fake certificates with this public key.
- {0xa4, 0xf5, 0x6e, 0x9e, 0x1d, 0x9a, 0x3b, 0x7b, 0x1a, 0xc3,
- 0x31, 0xcf, 0x64, 0xfc, 0x76, 0x2c, 0xd0, 0x51, 0xfb, 0xa4},
- // Three retired intermediate certificates from Symantec. No compromise;
- // just for robustness. All expire May 17 23:59:59 2018.
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=966060
- {0x68, 0x5e, 0xec, 0x0a, 0x39, 0xf6, 0x68, 0xae, 0x8f, 0xd8,
- 0x96, 0x4f, 0x98, 0x74, 0x76, 0xb4, 0x50, 0x4f, 0xd2, 0xbe},
- {0x0e, 0x50, 0x2d, 0x4d, 0xd1, 0xe1, 0x60, 0x36, 0x8a, 0x31,
- 0xf0, 0x6a, 0x81, 0x04, 0x31, 0xba, 0x6f, 0x72, 0xc0, 0x41},
- {0x93, 0xd1, 0x53, 0x22, 0x29, 0xcc, 0x2a, 0xbd, 0x21, 0xdf,
- 0xf5, 0x97, 0xee, 0x32, 0x0f, 0xe4, 0x24, 0x6f, 0x3d, 0x0c},
- // C=IN, O=National Informatics Centre, CN=NIC CA 2011. Issued by
- // C=IN, O=India PKI, CN=CCA India 2011.
- // Expires March 11th 2016.
- {0x07, 0x7a, 0xc7, 0xde, 0x8d, 0xa5, 0x58, 0x64, 0x3a, 0x06,
- 0xc5, 0x36, 0x9e, 0x55, 0x4f, 0xae, 0xb3, 0xdf, 0xa1, 0x66},
- // C=IN, O=National Informatics Centre, CN=NIC CA 2014. Issued by
- // C=IN, O=India PKI, CN=CCA India 2014.
- // Expires: March 5th, 2024.
- {0xe5, 0x8e, 0x31, 0x5b, 0xaa, 0xee, 0xaa, 0xc6, 0xe7, 0x2e,
- 0xc9, 0x57, 0x36, 0x70, 0xca, 0x2f, 0x25, 0x4e, 0xc3, 0x47},
- // C=DE, O=Fraunhofer, OU=Fraunhofer Corporate PKI,
- // CN=Fraunhofer Service CA 2007.
- // Expires: Jun 30 2019.
- // No compromise, just for robustness. See
- // https://bugzilla.mozilla.org/show_bug.cgi?id=1076940
- {0x38, 0x4d, 0x0c, 0x1d, 0xc4, 0x77, 0xa7, 0xb3, 0xf8, 0x67,
- 0x86, 0xd0, 0x18, 0x51, 0x9f, 0x58, 0x9f, 0x1e, 0x9e, 0x25},
- };
-
- static const unsigned kNumSHA256Hashes = 4;
- static const uint8_t kSHA256Hashes[kNumSHA256Hashes][crypto::kSHA256Length] =
- {
- // Two intermediates issued by TurkTrust to *.ego.gov.tr and
- // e-islem.kktcmerkezbankasi.org. Expires July 6 2021 and August 5 2021,
- // respectively.
- // See http://googleonlinesecurity.blogspot.com/2013/01/enhancing-digital-certificate-security.html
- {0x3e, 0xdb, 0xd9, 0xac, 0xe6, 0x39, 0xba, 0x1a,
- 0x2d, 0x4a, 0xd0, 0x47, 0x18, 0x71, 0x1f, 0xda,
- 0x23, 0xe8, 0x59, 0xb2, 0xfb, 0xf5, 0xd1, 0x37,
- 0xd4, 0x24, 0x04, 0x5e, 0x79, 0x19, 0xdf, 0xb9},
- {0xc1, 0x73, 0xf0, 0x62, 0x64, 0x56, 0xca, 0x85,
- 0x4f, 0xf2, 0xa7, 0xf0, 0xb1, 0x33, 0xa7, 0xcf,
- 0x4d, 0x02, 0x11, 0xe5, 0x52, 0xf2, 0x4b, 0x3e,
- 0x33, 0xad, 0xe8, 0xc5, 0x9f, 0x0a, 0x42, 0x4c},
-
- // xs4all certificate. Expires March 19 2016.
- // https://raymii.org/s/blog/How_I_got_a_valid_SSL_certificate_for_my_ISPs_main_website.html
- {0xf2, 0xbb, 0xe0, 0x4c, 0x5d, 0xc7, 0x0d, 0x76,
- 0x3e, 0x89, 0xc5, 0xa0, 0x52, 0x70, 0x48, 0xcd,
- 0x9e, 0xcd, 0x39, 0xeb, 0x62, 0x1e, 0x20, 0x72,
- 0xff, 0x9a, 0x5f, 0x84, 0x32, 0x57, 0x1a, 0xa0},
-
- // Japanese National Institute of Informatics intermediate. No suggestion
- // of compromise, it's just being discontinued.
- // Expires March 27th 2019
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=1188582
- {0x5c, 0x72, 0x2c, 0xb7, 0x0f, 0xb3, 0x11, 0xf2,
- 0x1e, 0x0d, 0xa0, 0xe7, 0xd1, 0x2e, 0xbc, 0x8e,
- 0x05, 0xf6, 0x07, 0x96, 0xbc, 0x49, 0xcf, 0x51,
- 0x18, 0x49, 0xd5, 0xbc, 0x62, 0x03, 0x03, 0x82},
- };
-
- for (unsigned i = 0; i < kNumSHA1Hashes; i++) {
- for (HashValueVector::const_iterator j = public_key_hashes.begin();
- j != public_key_hashes.end(); ++j) {
- if (j->tag == HASH_VALUE_SHA1 &&
- memcmp(j->data(), kSHA1Hashes[i], base::kSHA1Length) == 0) {
- return true;
- }
- }
- }
-
- for (unsigned i = 0; i < kNumSHA256Hashes; i++) {
- for (HashValueVector::const_iterator j = public_key_hashes.begin();
- j != public_key_hashes.end(); ++j) {
- if (j->tag == HASH_VALUE_SHA256 &&
- memcmp(j->data(), kSHA256Hashes[i], crypto::kSHA256Length) == 0) {
- return true;
- }
+// Defines kBlacklistedSPKIs.
+#include "net/cert/cert_verify_proc_blacklist.inc"
+ for (const auto& hash : public_key_hashes) {
+ if (hash.tag != HASH_VALUE_SHA256)
+ continue;
+ if (std::binary_search(std::begin(kBlacklistedSPKIs),
+ std::end(kBlacklistedSPKIs), hash,
+ HashToArrayComparator())) {
+ return true;
}
}
-
return false;
}
diff --git a/chromium/net/cert/cert_verify_proc_blacklist.inc b/chromium/net/cert/cert_verify_proc_blacklist.inc
new file mode 100644
index 00000000000..b2bb55464a3
--- /dev/null
+++ b/chromium/net/cert/cert_verify_proc_blacklist.inc
@@ -0,0 +1,154 @@
+// 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.
+
+// 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 uint8_t
+ kBlacklistedSPKIs[kNumBlacklistedSPKIs][crypto::kSHA256Length] = {
+ // ead610e6e90b439f2ecb51628b0932620f6ef340bd843fca38d3181b8f4ba197.pem
+ {0x12, 0x13, 0x23, 0x60, 0xa3, 0x3b, 0xfd, 0xc6, 0xc3, 0xbf, 0x7b,
+ 0x7f, 0xab, 0x26, 0xa1, 0x68, 0x48, 0x74, 0xe7, 0x2c, 0x12, 0x63,
+ 0xc1, 0xf5, 0xde, 0x56, 0x5b, 0xb4, 0x9e, 0xf0, 0x37, 0x53},
+ // 4bf6bb839b03b72839329b4ea70bb1b2f0d07e014d9d24aa9cc596114702bee3.pem
+ {0x12, 0x7d, 0xa2, 0x7a, 0x9e, 0x45, 0xf0, 0x82, 0x28, 0x0b, 0x31,
+ 0xbf, 0x1e, 0x56, 0x15, 0x20, 0x38, 0x9f, 0x96, 0x65, 0x90, 0x93,
+ 0xb2, 0x69, 0x7c, 0x40, 0xfe, 0x86, 0x00, 0x23, 0x6c, 0x8c},
+ // 0f912fd7be760be25afbc56bdc09cd9e5dcc9c6f6a55a778aefcb6aa30e31554.pem
+ {0x13, 0x0a, 0xd4, 0xe0, 0x63, 0x35, 0x21, 0x29, 0x05, 0x31, 0xb6,
+ 0x65, 0x1f, 0x57, 0x59, 0xb0, 0xbc, 0x7b, 0xc6, 0x56, 0x70, 0x9f,
+ 0xf8, 0xf3, 0x65, 0xc2, 0x14, 0x3b, 0x03, 0x89, 0xb6, 0xf6},
+ // 1af56c98ff043ef92bebff54cebb4dd67a25ba956c817f3e6dd3c1e52eb584c1.key
+ {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},
+ // 2c998e761160c3b06d82faa9fdc7545d9bda9eb60310f992aa510a6280b74245.pem
+ {0x2c, 0x99, 0x8e, 0x76, 0x11, 0x60, 0xc3, 0xb0, 0x6d, 0x82, 0xfa,
+ 0xa9, 0xfd, 0xc7, 0x54, 0x5d, 0x9b, 0xda, 0x9e, 0xb6, 0x03, 0x10,
+ 0xf9, 0x92, 0xaa, 0x51, 0x0a, 0x62, 0x80, 0xb7, 0x42, 0x45},
+ // 32ecc96f912f96d889e73088cd031c7ded2c651c805016157a23b6f32f798a3b.key
+ {0x32, 0xec, 0xc9, 0x6f, 0x91, 0x2f, 0x96, 0xd8, 0x89, 0xe7, 0x30,
+ 0x88, 0xcd, 0x03, 0x1c, 0x7d, 0xed, 0x2c, 0x65, 0x1c, 0x80, 0x50,
+ 0x16, 0x15, 0x7a, 0x23, 0xb6, 0xf3, 0x2f, 0x79, 0x8a, 0x3b},
+ // 42187727be39faf667aeb92bf0cc4e268f6e2ead2cefbec575bdc90430024f69.pem
+ {0x3e, 0xdb, 0xd9, 0xac, 0xe6, 0x39, 0xba, 0x1a, 0x2d, 0x4a, 0xd0,
+ 0x47, 0x18, 0x71, 0x1f, 0xda, 0x23, 0xe8, 0x59, 0xb2, 0xfb, 0xf5,
+ 0xd1, 0x37, 0xd4, 0x24, 0x04, 0x5e, 0x79, 0x19, 0xdf, 0xb9},
+ // 294f55ef3bd7244c6ff8a68ab797e9186ec27582751a791515e3292e48372d61.pem
+ {0x45, 0x5b, 0x87, 0xe9, 0x6f, 0x1c, 0xea, 0x2f, 0x8b, 0x6d, 0xae,
+ 0x08, 0x08, 0xec, 0x24, 0x73, 0x8f, 0xd9, 0x2b, 0x7f, 0xd3, 0x06,
+ 0x75, 0x71, 0x98, 0xbf, 0x38, 0x9d, 0x75, 0x5c, 0x0b, 0x6c},
+ // 7abd72a323c9d179c722564f4e27a51dd4afd24006b38a40ce918b94960bcf18.pem
+ {0x57, 0x80, 0x94, 0x46, 0xea, 0xf1, 0x14, 0x84, 0x38, 0x54, 0xfe,
+ 0x63, 0x6e, 0xd9, 0xbc, 0xb5, 0x52, 0xe3, 0xc6, 0x16, 0x66, 0x3b,
+ 0xc4, 0x4c, 0xc9, 0x5a, 0xcf, 0x56, 0x50, 0x01, 0x6d, 0x3e},
+ // 817d4e05063d5942869c47d8504dc56a5208f7569c3d6d67f3457cfe921b3e29.pem
+ {0x5c, 0x72, 0x2c, 0xb7, 0x0f, 0xb3, 0x11, 0xf2, 0x1e, 0x0d, 0xa0,
+ 0xe7, 0xd1, 0x2e, 0xbc, 0x8e, 0x05, 0xf6, 0x07, 0x96, 0xbc, 0x49,
+ 0xcf, 0x51, 0x18, 0x49, 0xd5, 0xbc, 0x62, 0x03, 0x03, 0x82},
+ // 79f69a47cfd6c4b4ceae8030d04b49f6171d3b5d6c812f58d040e586f1cb3f14.pem
+ // 933f7d8cda9f0d7c8bfd3c22bf4653f4161fd38ccdcf66b22e95a2f49c2650f8.pem
+ // f8a5ff189fedbfe34e21103389a68340174439ad12974a4e8d4d784d1f3a0faa.pem
+ {0x5e, 0x53, 0xf2, 0x64, 0x67, 0xf8, 0x94, 0xfd, 0xe5, 0x3b, 0x3f,
+ 0xa4, 0x06, 0xa4, 0x40, 0xcb, 0xb3, 0xb0, 0x76, 0xbb, 0x5b, 0x75,
+ 0x8f, 0xe4, 0x83, 0x4a, 0xd6, 0x65, 0x00, 0x20, 0x89, 0x07},
+ // f4a5984324de98bd979ef181a100cf940f2166173319a86a0d9d7c8fac3b0a8f.pem
+ {0x71, 0x65, 0xe9, 0x91, 0xad, 0xe7, 0x91, 0x6d, 0x86, 0xb4, 0x66,
+ 0xab, 0xeb, 0xb6, 0xe4, 0x57, 0xca, 0x93, 0x1c, 0x80, 0x4e, 0x58,
+ 0xce, 0x1f, 0xba, 0xba, 0xe5, 0x09, 0x15, 0x6f, 0xfb, 0x43},
+ // f3bae5e9c0adbfbfb6dbf7e04e74be6ead3ca98a5604ffe591cea86c241848ec.pem
+ {0x7d, 0x5e, 0x3f, 0x50, 0x50, 0x81, 0x97, 0xb9, 0xa4, 0x78, 0xb1,
+ 0x13, 0x40, 0xb7, 0xdc, 0xe2, 0x0a, 0x3c, 0x4d, 0xe4, 0x9c, 0x48,
+ 0xc9, 0xa2, 0x94, 0x15, 0x8a, 0x89, 0x5c, 0x44, 0xa2, 0x1b},
+ // b8686723e415534bc0dbd16326f9486f85b0b0799bf6639334e61daae67f36cd.pem
+ {0x7e, 0x70, 0x58, 0xea, 0x35, 0xad, 0x43, 0x59, 0x65, 0x41, 0x59,
+ 0x97, 0x3f, 0x56, 0x01, 0x87, 0xf1, 0x6d, 0x19, 0xc5, 0x14, 0xb9,
+ 0x39, 0xc5, 0x05, 0x56, 0x72, 0xd1, 0xd2, 0xa5, 0x18, 0xac},
+ // 450f1b421bb05c8609854884559c323319619e8b06b001ea2dcbb74a23aa3be2.pem
+ {0x93, 0xca, 0x2d, 0x43, 0x6c, 0xae, 0x7f, 0x68, 0xd2, 0xb4, 0x25,
+ 0x6c, 0xa1, 0x75, 0xc9, 0x85, 0xce, 0x39, 0x92, 0x6d, 0xc9, 0xf7,
+ 0xee, 0xae, 0xec, 0xf2, 0xf8, 0x97, 0x0f, 0xb9, 0x78, 0x02},
+ // 1f17f2cbb109f01c885c94d9e74a48625ae9659665d6d7e7bc5a10332976370f.pem
+ {0x99, 0xba, 0x47, 0x84, 0xf9, 0xb0, 0x85, 0x12, 0x90, 0x2e, 0xb0,
+ 0xc3, 0xc8, 0x6d, 0xf0, 0xec, 0x04, 0x9e, 0xac, 0x9b, 0x65, 0xf7,
+ 0x7a, 0x9b, 0xa4, 0x2b, 0xe9, 0xd6, 0xeb, 0xce, 0x32, 0x0f},
+ // a8e1dfd9cd8e470aa2f443914f931cfd61c323e94d75827affee985241c35ce5.pem
+ {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},
+ // 0d136e439f0ab6e97f3a02a540da9f0641aa554e1d66ea51ae2920d51b2f7217.pem
+ // 4fee0163686ecbd65db968e7494f55d84b25486d438e9de558d629d28cd4d176.pem
+ // 8a1bd21661c60015065212cc98b1abb50dfd14c872a208e66bae890f25c448af.pem
+ {0xa9, 0x03, 0xaf, 0x8c, 0x07, 0xbb, 0x91, 0xb0, 0xd9, 0xe3, 0xf3,
+ 0xa3, 0x0c, 0x6d, 0x53, 0x33, 0x9f, 0xc5, 0xbd, 0x47, 0xe5, 0xd6,
+ 0xbd, 0xb4, 0x76, 0x59, 0x88, 0x60, 0xc0, 0x68, 0xa0, 0x24},
+ // b8c1b957c077ea76e00b0f45bff5ae3acb696f221d2e062164fe37125e5a8d25.pem
+ {0xb3, 0x18, 0x2e, 0x28, 0x9a, 0xe3, 0x4d, 0xdf, 0x2b, 0xe6, 0x43,
+ 0xab, 0x79, 0xc2, 0x44, 0x30, 0x16, 0x05, 0xfa, 0x0f, 0x1e, 0xaa,
+ 0xe6, 0xd1, 0x0f, 0xb9, 0x29, 0x60, 0x0a, 0xf8, 0x4d, 0xf0},
+ // be144b56fb1163c49c9a0e6b5a458df6b29f7e6449985960c178a4744624b7bc.pem
+ {0xb4, 0xd5, 0xc9, 0x20, 0x41, 0x5e, 0xd0, 0xcc, 0x4f, 0x5d, 0xbc,
+ 0x7f, 0x54, 0x26, 0x36, 0x76, 0x2e, 0x80, 0xda, 0x66, 0x25, 0xf3,
+ 0x3f, 0x2b, 0x6a, 0xd6, 0xdb, 0x68, 0xbd, 0xba, 0xb2, 0x9a},
+ // 372447c43185c38edd2ce0e9c853f9ac1576ddd1704c2f54d96076c089cb4227.pem
+ {0xc1, 0x73, 0xf0, 0x62, 0x64, 0x56, 0xca, 0x85, 0x4f, 0xf2, 0xa7,
+ 0xf0, 0xb1, 0x33, 0xa7, 0xcf, 0x4d, 0x02, 0x11, 0xe5, 0x52, 0xf2,
+ 0x4b, 0x3e, 0x33, 0xad, 0xe8, 0xc5, 0x9f, 0x0a, 0x42, 0x4c},
+ // c4387d45364a313fbfe79812b35b815d42852ab03b06f11589638021c8f2cb44.key
+ {0xc4, 0x38, 0x7d, 0x45, 0x36, 0x4a, 0x31, 0x3f, 0xbf, 0xe7, 0x98,
+ 0x12, 0xb3, 0x5b, 0x81, 0x5d, 0x42, 0x85, 0x2a, 0xb0, 0x3b, 0x06,
+ 0xf1, 0x15, 0x89, 0x63, 0x80, 0x21, 0xc8, 0xf2, 0xcb, 0x44},
+ // 8290cc3fc1c3aac3239782c141ace8f88aeef4e9576a43d01867cf19d025be66.pem
+ // 9532e8b504964331c271f3f5f10070131a08bf8ba438978ce394c34feeae246f.pem
+ {0xc6, 0x01, 0x23, 0x4e, 0x2b, 0x93, 0x25, 0xdc, 0x92, 0xe3, 0xea,
+ 0xba, 0xc1, 0x96, 0x00, 0xb0, 0xb4, 0x99, 0x47, 0xd4, 0xd0, 0x4d,
+ 0x8c, 0x99, 0xd3, 0x21, 0x27, 0x49, 0x3e, 0xa0, 0x28, 0xf8},
+ // ec30c9c3065a06bb07dc5b1c6b497f370c1ca65c0f30c08e042ba6bcecc78f2c.pem
+ {0xcd, 0xee, 0x9f, 0x33, 0x05, 0x57, 0x2a, 0x67, 0x7e, 0x1a, 0x6c,
+ 0x82, 0xdc, 0x1e, 0x02, 0xa3, 0x5b, 0x11, 0xca, 0xe6, 0xa6, 0x84,
+ 0x33, 0x8c, 0x9f, 0x37, 0xfe, 0x1a, 0xc8, 0xda, 0xec, 0x23},
+ // 9ed8f9b0e8e42a1656b8e1dd18f42ba42dc06fe52686173ba2fc70e756f207dc.pem
+ // a686fee577c88ab664d0787ecdfff035f4806f3de418dc9e4d516324fff02083.pem
+ // fdedb5bdfcb67411513a61aee5cb5b5d7c52af06028efc996cc1b05b1d6cea2b.pem
+ {0xd3, 0x4b, 0x25, 0x5b, 0x2f, 0xe7, 0xd1, 0xa0, 0x96, 0x56, 0xcb,
+ 0xab, 0x64, 0x09, 0xf7, 0x3c, 0x79, 0x6e, 0xc7, 0xd6, 0x6a, 0xf7,
+ 0x36, 0x53, 0xec, 0xc3, 0x9a, 0xf9, 0x78, 0x29, 0x73, 0x10},
+ // 3946901f46b0071e90d78279e82fababca177231a704be72c5b0e8918566ea66.pem
+ {0xdd, 0x3e, 0xeb, 0x77, 0x9b, 0xee, 0x07, 0xf9, 0xef, 0xda, 0xc3,
+ 0x82, 0x40, 0x8b, 0x28, 0xd1, 0x42, 0xfa, 0x84, 0x2c, 0x78, 0xe8,
+ 0xbc, 0x0e, 0x33, 0x34, 0x8d, 0x57, 0xb9, 0x2f, 0x05, 0x83},
+ // c67d722c1495be02cbf9ef1159f5ca4aa782dc832dc6aa60c9aa076a0ad1e69d.pem
+ {0xde, 0x8f, 0x05, 0x07, 0x4e, 0xc0, 0x31, 0x8e, 0x7e, 0x7e, 0x8d,
+ 0x31, 0x90, 0xda, 0xe8, 0xb0, 0x08, 0x94, 0xf0, 0xe8, 0xdd, 0xdf,
+ 0xd3, 0x91, 0x3d, 0x01, 0x75, 0x9b, 0x4f, 0x79, 0xb0, 0x5d},
+ // e4f9a3235df7330255f36412bc849fb630f8519961ec3538301deb896c953da5.pem
+ {0xe6, 0xe1, 0x36, 0xc8, 0x61, 0x54, 0xf3, 0x2c, 0x3e, 0x49, 0xf4,
+ 0x7c, 0xfc, 0x6b, 0x33, 0x8f, 0xf2, 0xdc, 0x61, 0xce, 0x14, 0xfc,
+ 0x75, 0x89, 0xb3, 0xb5, 0x6a, 0x14, 0x50, 0x13, 0x27, 0x01},
+ // 3e26492e20b52de79e15766e6cb4251a1d566b0dbfb225aa7d08dda1dcebbf0a.pem
+ {0xe7, 0xb9, 0x32, 0xae, 0x7e, 0x9b, 0xdc, 0x70, 0x1d, 0x77, 0x1d,
+ 0x6f, 0x39, 0xe8, 0xa6, 0x53, 0x44, 0x9e, 0xea, 0x43, 0xbd, 0xb4,
+ 0x7b, 0xd9, 0x10, 0x22, 0x95, 0x0d, 0x91, 0x79, 0xd8, 0x7e},
+ // ea08c8d45d52ca593de524f0513ca6418da9859f7b08ef13ff9dd7bf612d6a37.key
+ {0xea, 0x08, 0xc8, 0xd4, 0x5d, 0x52, 0xca, 0x59, 0x3d, 0xe5, 0x24,
+ 0xf0, 0x51, 0x3c, 0xa6, 0x41, 0x8d, 0xa9, 0x85, 0x9f, 0x7b, 0x08,
+ 0xef, 0x13, 0xff, 0x9d, 0xd7, 0xbf, 0x61, 0x2d, 0x6a, 0x37},
+ // 31c8fd37db9b56e708b03d1f01848b068c6da66f36fb5d82c008c6040fa3e133.pem
+ {0xf0, 0x34, 0xf6, 0x42, 0xca, 0x1d, 0x9e, 0x88, 0xe9, 0xef, 0xea,
+ 0xfc, 0xb1, 0x5c, 0x7c, 0x93, 0x7a, 0xa1, 0x9e, 0x04, 0xb0, 0x80,
+ 0xf2, 0x73, 0x35, 0xe1, 0xda, 0x70, 0xd1, 0xca, 0x12, 0x01},
+ // 83618f932d6947744d5ecca299d4b2820c01483947bd16be814e683f7436be24.pem
+ {0xf2, 0xbb, 0xe0, 0x4c, 0x5d, 0xc7, 0x0d, 0x76, 0x3e, 0x89, 0xc5,
+ 0xa0, 0x52, 0x70, 0x48, 0xcd, 0x9e, 0xcd, 0x39, 0xeb, 0x62, 0x1e,
+ 0x20, 0x72, 0xff, 0x9a, 0x5f, 0x84, 0x32, 0x57, 0x1a, 0xa0},
+ // 2a3699deca1e9fd099ba45de8489e205977c9f2a5e29d5dd747381eec0744d71.pem
+ {0xf3, 0x0e, 0x8f, 0x61, 0x01, 0x1d, 0x65, 0x87, 0x3c, 0xcb, 0x81,
+ 0xb4, 0x0f, 0xa6, 0x21, 0x97, 0x49, 0xb9, 0x94, 0xf0, 0x1f, 0xa2,
+ 0x4d, 0x02, 0x01, 0xd5, 0x21, 0xc2, 0x43, 0x56, 0x03, 0xca},
+ // 67ed4b703d15dc555f8c444b3a05a32579cb7599bd19c9babe10c584ea327ae0.pem
+ {0xfa, 0x00, 0xbe, 0xc7, 0x3d, 0xd9, 0x97, 0x95, 0xdf, 0x11, 0x62,
+ 0xc7, 0x89, 0x98, 0x70, 0x04, 0xc2, 0x6c, 0xbf, 0x90, 0xaf, 0x4d,
+ 0xb4, 0x42, 0xf6, 0x62, 0x20, 0xde, 0x41, 0x35, 0x4a, 0xc9},
+};
diff --git a/chromium/net/cert/cert_verify_proc_ios.cc b/chromium/net/cert/cert_verify_proc_ios.cc
new file mode 100644
index 00000000000..5f2884f8a84
--- /dev/null
+++ b/chromium/net/cert/cert_verify_proc_ios.cc
@@ -0,0 +1,239 @@
+// 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/cert/cert_verify_proc_ios.h"
+
+#include <CommonCrypto/CommonDigest.h>
+#include <Security/Security.h>
+
+#include "base/logging.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "crypto/sha2.h"
+#include "net/base/net_errors.h"
+#include "net/cert/asn1_util.h"
+#include "net/cert/cert_verify_result.h"
+#include "net/cert/test_root_certs.h"
+#include "net/cert/x509_certificate.h"
+#include "net/ssl/openssl_ssl_util.h"
+
+using base::ScopedCFTypeRef;
+
+namespace net {
+
+namespace {
+
+int NetErrorFromOSStatus(OSStatus status) {
+ switch (status) {
+ case noErr:
+ return OK;
+ case errSecNotAvailable:
+ return ERR_NOT_IMPLEMENTED;
+ case errSecAuthFailed:
+ return ERR_ACCESS_DENIED;
+ default:
+ return ERR_FAILED;
+ }
+}
+
+// Creates a series of SecPolicyRefs to be added to a SecTrustRef used to
+// validate a certificate for an SSL server. |hostname| contains the name of
+// the SSL server that the certificate should be verified against. If
+// successful, returns noErr, and stores the resultant array of SecPolicyRefs
+// in |policies|.
+OSStatus CreateTrustPolicies(ScopedCFTypeRef<CFArrayRef>* policies) {
+ ScopedCFTypeRef<CFMutableArrayRef> local_policies(
+ CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
+ if (!local_policies)
+ return errSecAllocate;
+
+ SecPolicyRef ssl_policy = SecPolicyCreateBasicX509();
+ CFArrayAppendValue(local_policies, ssl_policy);
+ CFRelease(ssl_policy);
+ ssl_policy = SecPolicyCreateSSL(true, nullptr);
+ CFArrayAppendValue(local_policies, ssl_policy);
+ CFRelease(ssl_policy);
+
+ policies->reset(local_policies.release());
+ return noErr;
+}
+
+// Builds and evaluates a SecTrustRef for the certificate chain contained
+// in |cert_array|, using the verification policies in |trust_policies|. On
+// success, returns OK, and updates |trust_ref| and |trust_result|. On failure,
+// no output parameters are modified.
+//
+// Note: An OK return does not mean that |cert_array| is trusted, merely that
+// verification was performed successfully.
+int BuildAndEvaluateSecTrustRef(CFArrayRef cert_array,
+ CFArrayRef trust_policies,
+ ScopedCFTypeRef<SecTrustRef>* trust_ref,
+ ScopedCFTypeRef<CFArrayRef>* verified_chain,
+ SecTrustResultType* trust_result) {
+ SecTrustRef tmp_trust = nullptr;
+ OSStatus status =
+ SecTrustCreateWithCertificates(cert_array, trust_policies, &tmp_trust);
+ if (status)
+ return NetErrorFromOSStatus(status);
+ ScopedCFTypeRef<SecTrustRef> scoped_tmp_trust(tmp_trust);
+
+ if (TestRootCerts::HasInstance()) {
+ status = TestRootCerts::GetInstance()->FixupSecTrustRef(tmp_trust);
+ if (status)
+ return NetErrorFromOSStatus(status);
+ }
+
+ SecTrustResultType tmp_trust_result;
+ status = SecTrustEvaluate(tmp_trust, &tmp_trust_result);
+ if (status)
+ return NetErrorFromOSStatus(status);
+
+ ScopedCFTypeRef<CFMutableArrayRef> tmp_verified_chain(
+ CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
+ const CFIndex chain_length = SecTrustGetCertificateCount(tmp_trust);
+ for (CFIndex i = 0; i < chain_length; ++i) {
+ SecCertificateRef chain_cert = SecTrustGetCertificateAtIndex(tmp_trust, i);
+ CFArrayAppendValue(tmp_verified_chain, chain_cert);
+ }
+
+ trust_ref->swap(scoped_tmp_trust);
+ *trust_result = tmp_trust_result;
+ verified_chain->reset(tmp_verified_chain.release());
+ return OK;
+}
+
+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) {
+ SecCertificateRef chain_cert = reinterpret_cast<SecCertificateRef>(
+ const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
+ if (i == 0) {
+ verified_cert = chain_cert;
+ } else {
+ verified_chain.push_back(chain_cert);
+ }
+
+ std::string der_bytes;
+ if (!X509Certificate::GetDEREncoded(chain_cert, &der_bytes))
+ return;
+ const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_bytes.data());
+ ScopedX509 x509_cert(d2i_X509(NULL, &bytes, der_bytes.size()));
+
+ base::StringPiece spki_bytes;
+ if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes))
+ continue;
+
+ HashValue sha1(HASH_VALUE_SHA1);
+ CC_SHA1(spki_bytes.data(), spki_bytes.size(), sha1.data());
+ verify_result->public_key_hashes.push_back(sha1);
+
+ HashValue sha256(HASH_VALUE_SHA256);
+ CC_SHA256(spki_bytes.data(), spki_bytes.size(), sha256.data());
+ verify_result->public_key_hashes.push_back(sha256);
+
+ 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();
+ return;
+ }
+
+ verify_result->verified_cert =
+ X509Certificate::CreateFromHandle(verified_cert, verified_chain);
+}
+
+} // namespace
+
+CertVerifyProcIOS::CertVerifyProcIOS() {}
+
+CertVerifyProcIOS::~CertVerifyProcIOS() {}
+
+bool CertVerifyProcIOS::SupportsAdditionalTrustAnchors() const {
+ return false;
+}
+
+bool CertVerifyProcIOS::SupportsOCSPStapling() const {
+ return false;
+}
+
+int CertVerifyProcIOS::VerifyInternal(
+ X509Certificate* cert,
+ const std::string& hostname,
+ const std::string& ocsp_response,
+ int flags,
+ CRLSet* crl_set,
+ const CertificateList& additional_trust_anchors,
+ CertVerifyResult* verify_result) {
+ ScopedCFTypeRef<CFArrayRef> trust_policies;
+ OSStatus status = CreateTrustPolicies(&trust_policies);
+ if (status)
+ return NetErrorFromOSStatus(status);
+
+ ScopedCFTypeRef<CFMutableArrayRef> cert_array(
+ cert->CreateOSCertChainForCert());
+ ScopedCFTypeRef<SecTrustRef> trust_ref;
+ SecTrustResultType trust_result = kSecTrustResultDeny;
+ ScopedCFTypeRef<CFArrayRef> final_chain;
+
+ status = BuildAndEvaluateSecTrustRef(cert_array, trust_policies, &trust_ref,
+ &final_chain, &trust_result);
+ if (status)
+ return NetErrorFromOSStatus(status);
+
+ if (CFArrayGetCount(final_chain) == 0)
+ return ERR_FAILED;
+
+ GetCertChainInfo(final_chain, verify_result);
+
+ // TODO(sleevi): Support CRLSet revocation.
+ // TODO(svaldez): Add specific error codes for trust errors resulting from
+ // expired/not-yet-valid certs.
+ switch (trust_result) {
+ case kSecTrustResultUnspecified:
+ case kSecTrustResultProceed:
+ break;
+ case kSecTrustResultDeny:
+ verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
+ default:
+ verify_result->cert_status |= CERT_STATUS_INVALID;
+ }
+
+ // Perform hostname verification independent of SecTrustEvaluate.
+ if (!verify_result->verified_cert->VerifyNameMatch(
+ hostname, &verify_result->common_name_fallback_used)) {
+ verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
+ }
+
+ verify_result->is_issued_by_known_root = false;
+
+ if (IsCertStatusError(verify_result->cert_status))
+ return MapCertStatusToNetError(verify_result->cert_status);
+
+ return OK;
+}
+
+} // namespace net
diff --git a/chromium/net/cert/cert_verify_proc_ios.h b/chromium/net/cert/cert_verify_proc_ios.h
new file mode 100644
index 00000000000..e965a486e03
--- /dev/null
+++ b/chromium/net/cert/cert_verify_proc_ios.h
@@ -0,0 +1,36 @@
+// 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_CERT_CERT_VERIFY_PROC_IOS_H_
+#define NET_CERT_CERT_VERIFY_PROC_IOS_H_
+
+#include "net/cert/cert_verify_proc.h"
+
+namespace net {
+
+// Performs certificate path construction and validation using iOS's
+// Security.framework.
+class CertVerifyProcIOS : public CertVerifyProc {
+ public:
+ CertVerifyProcIOS();
+
+ bool SupportsAdditionalTrustAnchors() const override;
+ bool SupportsOCSPStapling() const override;
+
+ protected:
+ ~CertVerifyProcIOS() override;
+
+ private:
+ int VerifyInternal(X509Certificate* cert,
+ const std::string& hostname,
+ const std::string& ocsp_response,
+ int flags,
+ CRLSet* crl_set,
+ const CertificateList& additional_trust_anchors,
+ CertVerifyResult* verify_result) override;
+};
+
+} // namespace net
+
+#endif // NET_CERT_CERT_VERIFY_PROC_IOS_H_
diff --git a/chromium/net/cert/cert_verify_proc_mac.cc b/chromium/net/cert/cert_verify_proc_mac.cc
index c4e0c41ba92..07a49a234b0 100644
--- a/chromium/net/cert/cert_verify_proc_mac.cc
+++ b/chromium/net/cert/cert_verify_proc_mac.cc
@@ -32,6 +32,11 @@
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util_mac.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"
+
// From 10.7.2 libsecurity_keychain-55035/lib/SecTrustPriv.h, for use with
// SecTrustCopyExtendedResult.
#ifndef kSecEVOrganizationName
@@ -835,3 +840,5 @@ int CertVerifyProcMac::VerifyInternal(
}
} // namespace net
+
+#pragma clang diagnostic pop // "-Wdeprecated-declarations"
diff --git a/chromium/net/cert/cert_verify_proc_nss.cc b/chromium/net/cert/cert_verify_proc_nss.cc
index ca8e8116f0e..cad20b9fa95 100644
--- a/chromium/net/cert/cert_verify_proc_nss.cc
+++ b/chromium/net/cert/cert_verify_proc_nss.cc
@@ -279,7 +279,7 @@ enum CRLSetResult {
// that some EV sites would otherwise take the hit of an OCSP lookup for
// no reason.
// kCRLSetOk: otherwise.
-CRLSetResult CheckRevocationWithCRLSet(CERTCertList* cert_list,
+CRLSetResult CheckRevocationWithCRLSet(const CERTCertList* cert_list,
CERTCertificate* root,
CRLSet* crl_set) {
std::vector<CERTCertificate*> certs;
@@ -352,6 +352,50 @@ CRLSetResult CheckRevocationWithCRLSet(CERTCertList* cert_list,
return kCRLSetOk;
}
+// Arguments for CheckChainRevocationWithCRLSet that are curried within the
+// CERTChainVerifyCallback's isChainValidArg.
+struct CheckChainRevocationArgs {
+ // The CRLSet to evaluate against.
+ CRLSet* crl_set = nullptr;
+
+ // The next callback to invoke, if the CRLSet does not report any errors.
+ CERTChainVerifyCallback* next_callback = nullptr;
+
+ // Indicates that the application callback failure was due to a CRLSet
+ // revocation, rather than due to |next_callback| rejecting it. This is
+ // used to map the error back to the proper caller-visible error code.
+ bool was_revoked = false;
+};
+
+SECStatus CheckChainRevocationWithCRLSet(void* is_chain_valid_arg,
+ const CERTCertList* current_chain,
+ PRBool* chain_ok) {
+ CHECK(is_chain_valid_arg);
+
+ CheckChainRevocationArgs* args =
+ static_cast<CheckChainRevocationArgs*>(is_chain_valid_arg);
+
+ CRLSetResult crlset_result = kCRLSetUnknown;
+ if (args->crl_set) {
+ crlset_result =
+ CheckRevocationWithCRLSet(current_chain, nullptr, args->crl_set);
+ }
+
+ if (crlset_result == kCRLSetRevoked) {
+ args->was_revoked = true;
+ *chain_ok = PR_FALSE;
+ return SECSuccess;
+ }
+ args->was_revoked = false;
+
+ *chain_ok = PR_TRUE;
+ if (!args->next_callback || !args->next_callback->isChainValid)
+ return SECSuccess;
+
+ return (*args->next_callback->isChainValid)(
+ args->next_callback->isChainValidArg, current_chain, chain_ok);
+}
+
// Forward declarations.
SECStatus RetryPKIXVerifyCertWithWorkarounds(
CERTCertificate* cert_handle, int num_policy_oids,
@@ -825,6 +869,22 @@ int CertVerifyProcNSS::VerifyInternalImpl(
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
}
+ // Setup a callback to call into CheckChainRevocationWithCRLSet with the
+ // current CRLSet. If the CRLSet revokes a given chain, |was_revoked|
+ // will be set to true.
+ // The same callback and args are used for every invocation of
+ // PKIXVerifyCert, as CheckChainRevocationWithCRLSet handles resetting
+ // |was_revoked| as necessary.
+ CheckChainRevocationArgs check_chain_revocation_args;
+ check_chain_revocation_args.crl_set = crl_set;
+ check_chain_revocation_args.next_callback = chain_verify_callback;
+
+ CERTChainVerifyCallback crlset_callback;
+ memset(&crlset_callback, 0, sizeof(crlset_callback));
+ crlset_callback.isChainValid = &CheckChainRevocationWithCRLSet;
+ crlset_callback.isChainValidArg =
+ static_cast<void*>(&check_chain_revocation_args);
+
// Make sure that the cert is valid now.
SECCertTimeValidity validity = CERT_CheckCertValidTimes(
cert_handle, PR_Now(), PR_TRUE);
@@ -862,15 +922,9 @@ int CertVerifyProcNSS::VerifyInternalImpl(
CertificateListToCERTCertList(additional_trust_anchors));
}
- SECStatus status = PKIXVerifyCert(cert_handle,
- check_revocation,
- false,
- cert_io_enabled,
- NULL,
- 0,
- trust_anchors.get(),
- chain_verify_callback,
- cvout);
+ SECStatus status =
+ PKIXVerifyCert(cert_handle, check_revocation, false, cert_io_enabled,
+ NULL, 0, trust_anchors.get(), &crlset_callback, cvout);
if (status == SECSuccess &&
(flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) &&
@@ -880,15 +934,8 @@ int CertVerifyProcNSS::VerifyInternalImpl(
// NSS tests for that feature.
scoped_cvout.Clear();
verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
- status = PKIXVerifyCert(cert_handle,
- true,
- true,
- cert_io_enabled,
- NULL,
- 0,
- trust_anchors.get(),
- chain_verify_callback,
- cvout);
+ status = PKIXVerifyCert(cert_handle, true, true, cert_io_enabled, NULL, 0,
+ trust_anchors.get(), &crlset_callback, cvout);
}
if (status == SECSuccess) {
@@ -910,13 +957,25 @@ int CertVerifyProcNSS::VerifyInternalImpl(
CRLSetResult crl_set_result = kCRLSetUnknown;
if (crl_set) {
- crl_set_result = CheckRevocationWithCRLSet(
- cvout[cvout_cert_list_index].value.pointer.chain,
- cvout[cvout_trust_anchor_index].value.pointer.cert,
- crl_set);
- if (crl_set_result == kCRLSetRevoked) {
+ if (status == SECSuccess) {
+ // Reverify the returned chain; NSS should have already called
+ // CheckChainRevocationWithCRLSet prior to returning, but given the
+ // edge cases (self-signed certs that are trusted; cached chains;
+ // unreadable code), this is more about defense in depth than
+ // functional necessity.
+ crl_set_result = CheckRevocationWithCRLSet(
+ cvout[cvout_cert_list_index].value.pointer.chain,
+ cvout[cvout_trust_anchor_index].value.pointer.cert, crl_set);
+ if (crl_set_result == kCRLSetRevoked) {
+ PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
+ status = SECFailure;
+ }
+ } else if (PORT_GetError() == SEC_ERROR_APPLICATION_CALLBACK_ERROR &&
+ check_chain_revocation_args.was_revoked) {
+ // If a CRLSet was supplied, and the error was an application callback
+ // error, then it was directed through the CRLSet code and that
+ // particular chain was revoked.
PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
- status = SECFailure;
}
}
@@ -949,14 +1008,8 @@ int CertVerifyProcNSS::VerifyInternalImpl(
if (check_revocation)
verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
- if (VerifyEV(cert_handle,
- flags,
- crl_set,
- check_revocation,
- metadata,
- ev_policy_oid,
- trust_anchors.get(),
- chain_verify_callback)) {
+ if (VerifyEV(cert_handle, flags, crl_set, check_revocation, metadata,
+ ev_policy_oid, trust_anchors.get(), &crlset_callback)) {
verify_result->cert_status |= CERT_STATUS_IS_EV;
}
}
diff --git a/chromium/net/cert/cert_verify_proc_unittest.cc b/chromium/net/cert/cert_verify_proc_unittest.cc
index 0b6788e47ca..07ef5615812 100644
--- a/chromium/net/cert/cert_verify_proc_unittest.cc
+++ b/chromium/net/cert/cert_verify_proc_unittest.cc
@@ -107,6 +107,22 @@ bool SupportsDetectingKnownRoots() {
return true;
}
+// 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).
+template <size_t N>
+void LoadCertificateFiles(const char* const (&cert_files)[N],
+ CertificateList* certs) {
+ certs->clear();
+ for (size_t i = 0; i < N; ++i) {
+ SCOPED_TRACE(cert_files[i]);
+ scoped_refptr<X509Certificate> cert = CreateCertificateChainFromFile(
+ GetTestCertsDirectory(), cert_files[i], X509Certificate::FORMAT_AUTO);
+ ASSERT_TRUE(cert);
+ certs->push_back(cert);
+ }
+}
+
} // namespace
class CertVerifyProcTest : public testing::Test {
@@ -121,6 +137,19 @@ class CertVerifyProcTest : public testing::Test {
return verify_proc_->SupportsAdditionalTrustAnchors();
}
+ // Returns true if the underlying CertVerifyProc supports integrating CRLSets
+ // into path building logic, such as allowing the selection of alternatively
+ // valid paths when one or more are revoked. As the goal is to integrate this
+ // into all platforms, this is a temporary, test-only flag to centralize the
+ // conditionals in tests.
+ bool SupportsCRLSetsInPathBuilding() {
+#if defined(OS_WIN) || defined(USE_NSS_CERTS)
+ return true;
+#else
+ return false;
+#endif
+ }
+
int Verify(X509Certificate* cert,
const std::string& hostname,
int flags,
@@ -135,30 +164,6 @@ class CertVerifyProcTest : public testing::Test {
scoped_refptr<CertVerifyProc> verify_proc_;
};
-TEST_F(CertVerifyProcTest, DISABLED_WithoutRevocationChecking) {
- // Check that verification without revocation checking works.
- CertificateList certs = CreateCertificateListFromFile(
- GetTestCertsDirectory(),
- "googlenew.chain.pem",
- X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
-
- X509Certificate::OSCertHandles intermediates;
- intermediates.push_back(certs[1]->os_cert_handle());
-
- scoped_refptr<X509Certificate> google_full_chain =
- X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(),
- intermediates);
-
- CertVerifyResult verify_result;
- EXPECT_EQ(OK,
- Verify(google_full_chain.get(),
- "www.google.com",
- 0 /* flags */,
- NULL,
- empty_cert_list_,
- &verify_result));
-}
-
#if defined(OS_ANDROID) || defined(USE_OPENSSL_CERTS)
// TODO(jnd): http://crbug.com/117478 - EV verification is not yet supported.
#define MAYBE_EVVerification DISABLED_EVVerification
@@ -216,7 +221,7 @@ TEST_F(CertVerifyProcTest, PaypalNullCertParsing) {
NULL,
empty_cert_list_,
&verify_result);
-#if defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_ANDROID)
+#if defined(USE_NSS_VERIFIER) || defined(OS_ANDROID)
EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, error);
#else
// TOOD(bulach): investigate why macosx and win aren't returning
@@ -226,7 +231,7 @@ TEST_F(CertVerifyProcTest, PaypalNullCertParsing) {
// Either the system crypto library should correctly report a certificate
// name mismatch, or our certificate blacklist should cause us to report an
// invalid certificate.
-#if defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER) || defined(OS_WIN)
EXPECT_TRUE(verify_result.cert_status &
(CERT_STATUS_COMMON_NAME_INVALID | CERT_STATUS_INVALID));
#endif
@@ -272,47 +277,6 @@ TEST_F(CertVerifyProcTest, MAYBE_IntermediateCARequireExplicitPolicy) {
EXPECT_EQ(0u, verify_result.cert_status);
}
-// Test for bug 58437.
-// This certificate will expire on 2011-12-21. The test will still
-// pass if error == ERR_CERT_DATE_INVALID.
-// This test is DISABLED because it appears that we cannot do
-// certificate revocation checking when running all of the net unit tests.
-// This test passes when run individually, but when run with all of the net
-// unit tests, the call to PKIXVerifyCert returns the NSS error -8180, which is
-// SEC_ERROR_REVOKED_CERTIFICATE. This indicates a lack of revocation
-// status, i.e. that the revocation check is failing for some reason.
-TEST_F(CertVerifyProcTest, DISABLED_GlobalSignR3EVTest) {
- base::FilePath certs_dir = GetTestCertsDirectory();
-
- scoped_refptr<X509Certificate> server_cert =
- ImportCertFromFile(certs_dir, "2029_globalsign_com_cert.pem");
- ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get());
-
- scoped_refptr<X509Certificate> intermediate_cert =
- ImportCertFromFile(certs_dir, "globalsign_ev_sha256_ca_cert.pem");
- ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert.get());
-
- X509Certificate::OSCertHandles intermediates;
- intermediates.push_back(intermediate_cert->os_cert_handle());
- scoped_refptr<X509Certificate> cert_chain =
- X509Certificate::CreateFromHandle(server_cert->os_cert_handle(),
- intermediates);
-
- CertVerifyResult verify_result;
- int flags = CertVerifier::VERIFY_REV_CHECKING_ENABLED |
- CertVerifier::VERIFY_EV_CERT;
- int error = Verify(cert_chain.get(),
- "2029.globalsign.com",
- flags,
- NULL,
- empty_cert_list_,
- &verify_result);
- if (error == OK)
- EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV);
- else
- EXPECT_EQ(ERR_CERT_DATE_INVALID, error);
-}
-
// Test that verifying an ECDSA certificate doesn't crash on XP. (See
// crbug.com/144466).
TEST_F(CertVerifyProcTest, ECDSA_RSA) {
@@ -516,6 +480,18 @@ TEST_F(CertVerifyProcTest, GoogleDigiNotarTest) {
EXPECT_NE(OK, error);
}
+// Ensures the CertVerifyProc blacklist remains in sorted order, so that it
+// can be binary-searched.
+TEST_F(CertVerifyProcTest, BlacklistIsSorted) {
+// Defines kBlacklistedSPKIs.
+#include "net/cert/cert_verify_proc_blacklist.inc"
+ for (size_t i = 0; i < arraysize(kBlacklistedSPKIs) - 1; ++i) {
+ EXPECT_GT(0, memcmp(kBlacklistedSPKIs[i], kBlacklistedSPKIs[i + 1],
+ crypto::kSHA256Length))
+ << " at index " << i;
+ }
+}
+
TEST_F(CertVerifyProcTest, DigiNotarCerts) {
static const char* const kDigiNotarFilenames[] = {
"diginotar_root_ca.pem",
@@ -538,12 +514,12 @@ TEST_F(CertVerifyProcTest, DigiNotarCerts) {
base::StringPiece spki;
ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(der_bytes, &spki));
- std::string spki_sha1 = base::SHA1HashString(spki.as_string());
+ std::string spki_sha256 = crypto::SHA256HashString(spki.as_string());
HashValueVector public_keys;
- HashValue hash(HASH_VALUE_SHA1);
- ASSERT_EQ(hash.size(), spki_sha1.size());
- memcpy(hash.data(), spki_sha1.data(), spki_sha1.size());
+ HashValue hash(HASH_VALUE_SHA256);
+ ASSERT_EQ(hash.size(), spki_sha256.size());
+ memcpy(hash.data(), spki_sha256.data(), spki_sha256.size());
public_keys.push_back(hash);
EXPECT_TRUE(CertVerifyProc::IsPublicKeyBlacklisted(public_keys)) <<
@@ -1237,6 +1213,120 @@ TEST_F(CertVerifyProcTest, CRLSetLeafSerial) {
&verify_result);
EXPECT_EQ(ERR_CERT_REVOKED, error);
}
+
+// Tests that CRLSets participate in path building functions, and that as
+// long as a valid path exists within the verification graph, verification
+// succeeds.
+//
+// In this test, there are two roots (D and E), and three possible paths
+// to validate a leaf (A):
+// 1. A(B) -> B(C) -> C(D) -> D(D)
+// 2. A(B) -> B(C) -> C(E) -> E(E)
+// 3. A(B) -> B(F) -> F(E) -> E(E)
+//
+// Each permutation of revocation is tried:
+// 1. Revoking E by SPKI, so that only Path 1 is valid (as E is in Paths 2 & 3)
+// 2. Revoking C(D) and F(E) by serial, so that only Path 2 is valid.
+// 3. Revoking C by SPKI, so that only Path 3 is valid (as C is in Paths 1 & 2)
+TEST_F(CertVerifyProcTest, CRLSetDuringPathBuilding) {
+ if (!SupportsCRLSetsInPathBuilding()) {
+ LOG(INFO) << "Skipping this test on this platform.";
+ return;
+ }
+
+ const char* const kPath1Files[] = {
+ "multi-root-A-by-B.pem", "multi-root-B-by-C.pem", "multi-root-C-by-D.pem",
+ "multi-root-D-by-D.pem"};
+ 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"};
+ const char* const kPath3Files[] = {
+ "multi-root-A-by-B.pem", "multi-root-B-by-F.pem", "multi-root-F-by-E.pem",
+ "multi-root-E-by-E.pem"};
+
+ CertificateList path_1_certs;
+ ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath1Files, &path_1_certs));
+
+ CertificateList path_2_certs;
+ ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath2Files, &path_2_certs));
+
+ CertificateList path_3_certs;
+ ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath3Files, &path_3_certs));
+
+ // Add D and E as trust anchors.
+ ScopedTestRoot test_root_D(path_1_certs[3].get()); // D-by-D
+ ScopedTestRoot test_root_E(path_2_certs[3].get()); // E-by-E
+
+ // Create a chain that contains all the certificate paths possible.
+ // CertVerifyProcTest.VerifyReturnChainFiltersUnrelatedCerts already
+ // ensures that it's safe to send additional certificates as inputs, and
+ // that they're ignored if not necessary.
+ // This is to avoid relying on AIA or internal object caches when
+ // interacting with the underlying library.
+ X509Certificate::OSCertHandles intermediates;
+ intermediates.push_back(path_1_certs[1]->os_cert_handle()); // B-by-C
+ intermediates.push_back(path_1_certs[2]->os_cert_handle()); // C-by-D
+ intermediates.push_back(path_2_certs[2]->os_cert_handle()); // C-by-E
+ intermediates.push_back(path_3_certs[1]->os_cert_handle()); // B-by-F
+ intermediates.push_back(path_3_certs[2]->os_cert_handle()); // F-by-E
+ scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
+ path_1_certs[0]->os_cert_handle(), intermediates);
+ ASSERT_TRUE(cert);
+
+ struct TestPermutations {
+ const char* crlset;
+ bool expect_valid;
+ scoped_refptr<X509Certificate> expected_intermediate;
+ } kTests[] = {
+ {"multi-root-crlset-D-and-E.raw", false, nullptr},
+ {"multi-root-crlset-E.raw", true, path_1_certs[2].get()},
+ {"multi-root-crlset-CD-and-FE.raw", true, path_2_certs[2].get()},
+ {"multi-root-crlset-C.raw", true, path_3_certs[2].get()},
+ {"multi-root-crlset-unrelated.raw", true, nullptr}};
+
+ for (const auto& testcase : kTests) {
+ SCOPED_TRACE(testcase.crlset);
+ scoped_refptr<CRLSet> crl_set;
+ std::string crl_set_bytes;
+ EXPECT_TRUE(base::ReadFileToString(
+ GetTestCertsDirectory().AppendASCII(testcase.crlset), &crl_set_bytes));
+ ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set));
+
+ int flags = 0;
+ CertVerifyResult verify_result;
+ int error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(),
+ empty_cert_list_, &verify_result);
+
+ if (!testcase.expect_valid) {
+ EXPECT_NE(OK, error);
+ EXPECT_NE(0U, verify_result.cert_status);
+ continue;
+ }
+
+ ASSERT_EQ(OK, error);
+ ASSERT_EQ(0U, verify_result.cert_status);
+ ASSERT_TRUE(verify_result.verified_cert.get());
+
+ if (!testcase.expected_intermediate)
+ continue;
+
+ const X509Certificate::OSCertHandles& verified_intermediates =
+ verify_result.verified_cert->GetIntermediateCertificates();
+ ASSERT_EQ(3U, verified_intermediates.size());
+
+ scoped_refptr<X509Certificate> intermediate =
+ X509Certificate::CreateFromHandle(verified_intermediates[1],
+ X509Certificate::OSCertHandles());
+ ASSERT_TRUE(intermediate);
+
+ EXPECT_TRUE(testcase.expected_intermediate->Equals(intermediate.get()))
+ << "Expected: " << testcase.expected_intermediate->subject().common_name
+ << " issued by " << testcase.expected_intermediate->issuer().common_name
+ << "; Got: " << intermediate->subject().common_name << " issued by "
+ << intermediate->issuer().common_name;
+ }
+}
+
#endif
enum ExpectedAlgorithms {
diff --git a/chromium/net/cert/cert_verify_proc_whitelist.cc b/chromium/net/cert/cert_verify_proc_whitelist.cc
index c2437f8c4de..3560f102d0e 100644
--- a/chromium/net/cert/cert_verify_proc_whitelist.cc
+++ b/chromium/net/cert/cert_verify_proc_whitelist.cc
@@ -22,18 +22,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xa0, 0xa8, 0xbb, 0xa5, 0x0a, 0x72, 0xd4, 0xe1,
0x83, 0x9a, 0x94, 0xfb, 0x1a, 0x58, 0x5a, 0xd7,
0x2a, 0x7a, 0xac, 0x3c, 0x72, 0x56, 0x1f, 0xc0 },
- { 0x00, 0xde, 0xff, 0x68, 0x2e, 0x35, 0x10, 0x22,
- 0xcc, 0x3b, 0xbb, 0x4e, 0xb5, 0x88, 0x0a, 0x97,
- 0x27, 0x88, 0x0a, 0xf3, 0x52, 0xfb, 0xbe, 0x2f,
- 0x91, 0x24, 0xbe, 0x92, 0x88, 0x4b, 0x18, 0xfd },
- { 0x00, 0xf8, 0x4a, 0x82, 0x67, 0xb3, 0xda, 0xee,
- 0x1e, 0x16, 0x90, 0x75, 0x1c, 0x86, 0xbd, 0x78,
- 0x94, 0x08, 0x65, 0x94, 0x3e, 0xee, 0x52, 0xe9,
- 0x7d, 0x98, 0x50, 0x1a, 0xc8, 0xe1, 0x58, 0x94 },
- { 0x01, 0x5f, 0x9b, 0x68, 0xd6, 0x4b, 0x86, 0x0d,
- 0x5e, 0xd0, 0x40, 0x50, 0x66, 0xa3, 0xf2, 0xfd,
- 0x9d, 0x6d, 0xde, 0x3a, 0x9b, 0x35, 0x73, 0x17,
- 0x34, 0x10, 0xe6, 0xce, 0x63, 0x9b, 0x77, 0x91 },
{ 0x01, 0x84, 0xb8, 0x58, 0xc0, 0x22, 0x4a, 0x51,
0x52, 0x41, 0x5c, 0x77, 0x68, 0x30, 0xa4, 0x42,
0x29, 0xf6, 0x44, 0xa3, 0x9e, 0xe5, 0x3e, 0x76,
@@ -46,34 +34,14 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x08, 0x22, 0xab, 0x1b, 0x8c, 0xc0, 0xd8,
- 0x22, 0x03, 0x60, 0xa1, 0xaf, 0x8b, 0xb4, 0xd9,
- 0xbe, 0x60, 0xe8, 0x43, 0x9e, 0x2b, 0xa3, 0x07,
- 0x8d, 0x61, 0xf4, 0x01, 0xe1, 0x5b, 0x41, 0xbc },
{ 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, 0xc4, 0x8c, 0x3a, 0xdc, 0xf9, 0x9f, 0x28,
- 0xf4, 0x79, 0xb8, 0xf6, 0x79, 0x88, 0x77, 0x78,
- 0xb9, 0x3a, 0x06, 0xaf, 0xf1, 0x6e, 0x35, 0x8f,
- 0x40, 0x9b, 0xc6, 0xfe, 0x54, 0x03, 0x04, 0xc6 },
{ 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, 0x2a, 0x7e, 0x55, 0xfe, 0xc3, 0x74, 0xc6,
- 0xd7, 0x9c, 0xff, 0xdb, 0x46, 0x7c, 0x5c, 0xcd,
- 0x56, 0xf5, 0x49, 0x0a, 0xae, 0x9a, 0xf1, 0xbc,
- 0xcc, 0x7e, 0x54, 0xda, 0xfa, 0x6d, 0x8a, 0x3f },
- { 0x03, 0x83, 0xf9, 0xc1, 0xf5, 0xc8, 0x4c, 0x02,
- 0x64, 0xe6, 0x3b, 0x2a, 0x96, 0x21, 0x21, 0x37,
- 0x58, 0x70, 0x0d, 0x1a, 0xfb, 0x61, 0xf8, 0x00,
- 0x1f, 0x3e, 0xff, 0x81, 0x44, 0xe6, 0xfe, 0x73 },
- { 0x03, 0xd9, 0x9f, 0x24, 0xf8, 0x64, 0x4b, 0x80,
- 0x4d, 0x8e, 0x3b, 0xc9, 0xc8, 0x7c, 0x02, 0x4e,
- 0x4b, 0xb7, 0x0d, 0xc6, 0x30, 0x1b, 0xcd, 0xe3,
- 0x24, 0x12, 0xb4, 0xce, 0x8c, 0x0c, 0x14, 0x58 },
{ 0x03, 0xe0, 0x6e, 0x0b, 0x7a, 0x2c, 0xba, 0xe4,
0xb6, 0x8b, 0xce, 0x5f, 0x83, 0xe7, 0xa9, 0x31,
0x6e, 0xd7, 0x82, 0x3e, 0x8d, 0x94, 0x85, 0x38,
@@ -186,10 +154,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x18, 0x68, 0x8e, 0xc6, 0x2f, 0x1c, 0x17, 0x30,
0xdc, 0xa2, 0x20, 0x48, 0x57, 0xce, 0x5f, 0xad,
0xb6, 0x6c, 0xe6, 0x6b, 0xda, 0xb1, 0x70, 0x3d },
- { 0x0b, 0x3d, 0x17, 0x8d, 0x8a, 0x68, 0x43, 0x73,
- 0x19, 0x35, 0x9f, 0xa3, 0x54, 0x28, 0x65, 0xad,
- 0xe1, 0x20, 0x02, 0x9a, 0xbe, 0x5b, 0x02, 0xba,
- 0xff, 0xbe, 0x98, 0x8b, 0x2a, 0x14, 0x46, 0x3d },
{ 0x0b, 0x48, 0xd5, 0x5c, 0xac, 0x84, 0xfd, 0xee,
0x15, 0xd8, 0x1a, 0xff, 0x99, 0x07, 0xbb, 0x9a,
0x57, 0x11, 0xa9, 0x5c, 0xe2, 0x3a, 0x8d, 0x4d,
@@ -226,14 +190,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xaf, 0x69, 0x65, 0x29, 0x28, 0x9a, 0xae, 0x25,
0xd9, 0xc4, 0x2a, 0x1b, 0xbb, 0x03, 0x5a, 0x2b,
0x8c, 0x61, 0x14, 0x7e, 0x1b, 0x8b, 0x90, 0x52 },
- { 0x0d, 0xab, 0xae, 0xcb, 0x0d, 0x12, 0x9b, 0xc6,
- 0x36, 0xe8, 0x4a, 0x4b, 0x23, 0x93, 0x46, 0x03,
- 0x06, 0xab, 0x49, 0xbd, 0x03, 0xe2, 0x22, 0xee,
- 0x79, 0x2a, 0x36, 0x9e, 0x6e, 0x4f, 0x70, 0x72 },
- { 0x0e, 0x4f, 0xd8, 0x53, 0xd6, 0x0f, 0xd7, 0x69,
- 0x90, 0xd7, 0x77, 0xaf, 0x09, 0x79, 0xd4, 0x65,
- 0x16, 0xbd, 0xc9, 0x09, 0xa8, 0xd9, 0xd5, 0xef,
- 0x70, 0x15, 0x59, 0xbf, 0x74, 0x62, 0xc4, 0xaf },
{ 0x0e, 0xfd, 0x68, 0x73, 0xd6, 0x0e, 0x77, 0x96,
0x2d, 0xf6, 0x00, 0x16, 0xdc, 0x3b, 0xaf, 0x9c,
0xa7, 0x1e, 0x7d, 0x86, 0x19, 0xe7, 0xeb, 0xaa,
@@ -242,26 +198,14 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x23, 0x4a, 0x86, 0xc7, 0x0d, 0x49, 0x8c, 0x62,
0x60, 0x7f, 0x37, 0x44, 0xea, 0x71, 0xf1, 0x83,
0x1d, 0xcf, 0xca, 0xf3, 0xaf, 0x15, 0x56, 0x9c },
- { 0x0f, 0x57, 0xed, 0x67, 0x2b, 0xac, 0x50, 0x14,
- 0x89, 0xe4, 0xf4, 0xab, 0x4b, 0x1d, 0xb1, 0x75,
- 0x81, 0xfe, 0xb8, 0x76, 0x0f, 0xfb, 0xc0, 0x8a,
- 0x82, 0x83, 0xe0, 0xf8, 0x41, 0xae, 0x01, 0x3c },
{ 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, 0x65, 0x97, 0x60, 0x44, 0x7f, 0xb6, 0x8d,
- 0x4f, 0xbb, 0x37, 0x6e, 0x3b, 0x66, 0xb1, 0x94,
- 0xda, 0x3e, 0xe0, 0x42, 0x5a, 0x0b, 0xc2, 0x13,
- 0x88, 0x06, 0xb2, 0x78, 0x43, 0x79, 0xd3, 0xb8 },
{ 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 },
- { 0x11, 0xb7, 0x69, 0xde, 0xde, 0x8b, 0xd6, 0x15,
- 0xfc, 0x71, 0x20, 0x0b, 0x20, 0xb9, 0xa3, 0x1d,
- 0x70, 0x93, 0x15, 0x16, 0xec, 0x54, 0x42, 0xc3,
- 0xdd, 0xc9, 0xc8, 0xd1, 0x90, 0x21, 0x9d, 0xe1 },
{ 0x11, 0xde, 0x20, 0x2a, 0x3e, 0x34, 0x13, 0xa2,
0x33, 0x3e, 0xc1, 0x67, 0x8e, 0xbb, 0x50, 0x6d,
0xd9, 0x55, 0x7c, 0x06, 0x81, 0xce, 0x5f, 0xed,
@@ -314,10 +258,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x06, 0x78, 0xdc, 0x5b, 0xa8, 0x03, 0x84, 0x7a,
0xbd, 0xb5, 0xea, 0x64, 0x31, 0x65, 0x3e, 0xc2,
0x5f, 0xdc, 0x8d, 0x2b, 0xb3, 0x3d, 0x12, 0x23 },
- { 0x15, 0xea, 0x55, 0xf0, 0x2c, 0x49, 0x02, 0xec,
- 0x77, 0x72, 0x64, 0xe0, 0x81, 0x71, 0x41, 0x24,
- 0x7c, 0x52, 0x00, 0xe1, 0x16, 0x56, 0xfd, 0xc2,
- 0x72, 0x9d, 0x59, 0x5c, 0x37, 0x79, 0x95, 0x6c },
{ 0x16, 0x21, 0xec, 0x14, 0xe0, 0xb4, 0x13, 0xfa,
0xb7, 0xd0, 0x27, 0x5a, 0x9a, 0xc3, 0xc3, 0xc9,
0x85, 0x13, 0xfe, 0x18, 0xa2, 0x02, 0x86, 0xf6,
@@ -326,22 +266,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x1d, 0xb5, 0x84, 0x6c, 0xca, 0x8e, 0xb7, 0x19,
0x12, 0x3d, 0x4b, 0x06, 0xb3, 0xff, 0x98, 0x66,
0xd7, 0x4d, 0x6e, 0x18, 0x7c, 0x1e, 0xf9, 0x70 },
- { 0x16, 0xe7, 0x66, 0x47, 0xb3, 0x97, 0xeb, 0x4e,
- 0xfd, 0x9a, 0x79, 0xf2, 0xfb, 0xba, 0x9a, 0xca,
- 0x46, 0xce, 0xad, 0x95, 0x43, 0x05, 0xfe, 0xe5,
- 0xb1, 0x3b, 0x5d, 0x53, 0xdb, 0x7c, 0x1d, 0xb1 },
{ 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 },
- { 0x17, 0x59, 0x7e, 0x00, 0x45, 0x6c, 0x38, 0x32,
- 0xe1, 0x85, 0x1c, 0x30, 0x0c, 0xd5, 0x52, 0xc2,
- 0xe7, 0x73, 0x35, 0x8c, 0xf0, 0xf6, 0x88, 0x58,
- 0xf3, 0x4f, 0xca, 0x34, 0x45, 0xc6, 0x4d, 0xb7 },
- { 0x17, 0xd1, 0xf6, 0xe5, 0x1c, 0xb3, 0xaf, 0x91,
- 0x23, 0xd4, 0xfc, 0xb3, 0x84, 0x18, 0x39, 0x4d,
- 0xe3, 0xe6, 0xc3, 0x33, 0x3f, 0x80, 0x20, 0xd5,
- 0x13, 0x48, 0xde, 0xba, 0xcc, 0x74, 0x70, 0x14 },
{ 0x17, 0xf7, 0x25, 0xac, 0x12, 0xce, 0xa5, 0xe0,
0x86, 0x6f, 0xcc, 0x3e, 0x83, 0x4e, 0x9c, 0xb6,
0x34, 0x14, 0x5c, 0xed, 0xc5, 0x6b, 0x61, 0x3d,
@@ -370,10 +298,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x0c, 0x95, 0x34, 0xe6, 0x84, 0xbb, 0x04, 0x9f,
0xf1, 0xe2, 0x3b, 0x66, 0xa1, 0x33, 0x01, 0x2f,
0xc3, 0x99, 0xeb, 0x4f, 0xb5, 0xd3, 0xaa, 0x35 },
- { 0x1a, 0xfa, 0xb3, 0x15, 0x5b, 0x57, 0x17, 0xc0,
- 0x89, 0x82, 0xf9, 0x0c, 0x88, 0xa7, 0xaa, 0xc3,
- 0x6b, 0xeb, 0x00, 0x03, 0xfa, 0xc4, 0x9b, 0xca,
- 0x74, 0xa1, 0xcc, 0x52, 0x09, 0xb7, 0x04, 0x39 },
{ 0x1b, 0x56, 0xba, 0x1e, 0xff, 0xac, 0x97, 0x36,
0x60, 0x74, 0xce, 0x07, 0x24, 0xe7, 0x04, 0x59,
0xdf, 0x99, 0x82, 0x1c, 0x3f, 0xaf, 0x20, 0xde,
@@ -402,10 +326,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x38, 0x5d, 0xe1, 0xde, 0x16, 0xb2, 0x22, 0x6e,
0x88, 0x3d, 0x9c, 0x34, 0x66, 0x3e, 0x1b, 0x64,
0xe8, 0x5b, 0x98, 0x0e, 0xaf, 0xf0, 0xb9, 0xd3 },
- { 0x1c, 0x76, 0xbb, 0xca, 0x37, 0x71, 0x77, 0x5b,
- 0xb9, 0xb0, 0xc3, 0x33, 0x71, 0x70, 0x32, 0x69,
- 0x06, 0x16, 0x77, 0xca, 0x7b, 0x18, 0x99, 0xef,
- 0x8c, 0x77, 0xe4, 0x15, 0x22, 0x2b, 0x56, 0xb6 },
{ 0x1d, 0x9e, 0xc0, 0x06, 0xa5, 0x26, 0xfa, 0xb5,
0xce, 0x2e, 0x71, 0xfd, 0xfc, 0x07, 0xc0, 0x11,
0xf7, 0x65, 0x7b, 0xf8, 0x5f, 0x5d, 0x03, 0x52,
@@ -414,10 +334,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x00, 0x4b, 0x82, 0x0c, 0xf6, 0x8b, 0x00,
- 0x7b, 0xb5, 0x72, 0xa0, 0xed, 0x42, 0x9c, 0x79,
- 0x8f, 0x79, 0x44, 0x4f, 0x6f, 0x13, 0x29, 0x32,
- 0xee, 0x5f, 0x8e, 0x28, 0xa4, 0x0a, 0xb9, 0x86 },
{ 0x1f, 0x11, 0x85, 0xa5, 0x21, 0xe2, 0x8e, 0x95,
0x17, 0x1c, 0xf3, 0x86, 0x07, 0x8a, 0x76, 0x4a,
0x9a, 0x3e, 0x71, 0xc2, 0x59, 0xbc, 0xdc, 0x5f,
@@ -426,10 +342,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x68, 0x40, 0x10, 0xc1, 0x92, 0xab, 0xfa,
- 0x85, 0xa7, 0x9b, 0xba, 0x45, 0xce, 0x76, 0x4b,
- 0x2d, 0xa8, 0x1f, 0x99, 0x1f, 0x5f, 0x01, 0xd9,
- 0xeb, 0x7e, 0x3c, 0x99, 0x9b, 0x78, 0x75, 0x0e },
{ 0x1f, 0xc7, 0xf8, 0x10, 0x4e, 0x27, 0xff, 0x2a,
0x45, 0x56, 0xf9, 0x1e, 0x05, 0x42, 0x17, 0xc5,
0x8f, 0x69, 0x3f, 0x70, 0x36, 0x25, 0x9e, 0x39,
@@ -442,22 +354,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x6e, 0xa3, 0xa9, 0x98, 0x8f, 0xb1, 0x0b, 0x24,
0xc7, 0x01, 0xef, 0xdd, 0xab, 0xe4, 0x74, 0x05,
0x63, 0x43, 0xa1, 0x36, 0x11, 0xd5, 0x4d, 0x7d },
- { 0x21, 0x03, 0x9f, 0x99, 0x3d, 0xae, 0x79, 0x03,
- 0xa0, 0xa7, 0xaa, 0x93, 0x5b, 0x96, 0x70, 0x1a,
- 0xdd, 0x7e, 0xc5, 0xca, 0x99, 0xe1, 0x7e, 0x65,
- 0x1c, 0x21, 0x29, 0x5b, 0x3b, 0x65, 0x70, 0x49 },
{ 0x21, 0x09, 0xf3, 0x10, 0x7d, 0x97, 0xf8, 0x70,
0x48, 0x70, 0x8e, 0xc8, 0x7c, 0xa2, 0xdc, 0x31,
0x8b, 0x2f, 0x2b, 0x57, 0x47, 0xc3, 0x38, 0xbd,
0x9c, 0x6d, 0xbc, 0xd6, 0x0f, 0xd6, 0xbe, 0xa2 },
- { 0x21, 0x4a, 0xbc, 0x84, 0x5d, 0x66, 0x68, 0x76,
- 0xc4, 0x78, 0x12, 0x84, 0x14, 0x16, 0xc6, 0xfb,
- 0xff, 0x4a, 0x38, 0x32, 0x20, 0x61, 0xb6, 0x5d,
- 0x9c, 0x5f, 0x6b, 0x74, 0x98, 0x2b, 0xc6, 0xea },
- { 0x21, 0x62, 0xab, 0xc2, 0x7d, 0x0c, 0x3d, 0xa0,
- 0xf6, 0xaf, 0xf9, 0x76, 0x95, 0xfb, 0x3d, 0x47,
- 0x7f, 0x4c, 0x63, 0x34, 0xff, 0xb3, 0xe5, 0xbc,
- 0xd0, 0xe3, 0x05, 0x49, 0xd5, 0xfe, 0xeb, 0x47 },
{ 0x21, 0x78, 0xe8, 0x28, 0x3a, 0x73, 0x39, 0x6e,
0x08, 0xc0, 0xa1, 0x1a, 0x88, 0x72, 0xfa, 0x4a,
0x9f, 0xcc, 0x05, 0x67, 0x0c, 0xee, 0xff, 0xb8,
@@ -474,10 +374,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x3f, 0xc6, 0xf9, 0x15, 0x1f, 0x05, 0x00,
- 0xbb, 0x38, 0xad, 0x20, 0x7a, 0xf2, 0x42, 0x21,
- 0x3a, 0x6a, 0x51, 0xce, 0xb3, 0x8c, 0x73, 0x0f,
- 0xf1, 0xbf, 0xa1, 0x0a, 0x82, 0x4a, 0x71, 0xc7 },
{ 0x23, 0x8a, 0x80, 0xcc, 0x9b, 0x58, 0x9a, 0xdc,
0x89, 0xb7, 0xa8, 0xf3, 0x4d, 0xdf, 0x12, 0x48,
0x73, 0x4b, 0x9f, 0x7f, 0x78, 0x20, 0xb6, 0x04,
@@ -486,10 +382,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x16, 0x2a, 0x9c, 0xa0, 0x6e, 0x88, 0x01, 0xe1,
0x19, 0xbd, 0xff, 0x54, 0x35, 0x4a, 0x3f, 0x68,
0x43, 0xcf, 0x2a, 0x2f, 0xa6, 0x01, 0x75, 0x8e },
- { 0x23, 0xf7, 0xe4, 0xa3, 0x5b, 0xcc, 0xe7, 0x40,
- 0x36, 0xd9, 0xc8, 0x6f, 0x7f, 0x61, 0x1d, 0x85,
- 0xf3, 0x7c, 0xb6, 0x2c, 0x43, 0x24, 0x7d, 0x13,
- 0x52, 0x22, 0x4e, 0xc3, 0xdc, 0x89, 0xed, 0x37 },
{ 0x24, 0x62, 0x52, 0x48, 0x32, 0xc1, 0x54, 0xd8,
0x4d, 0xf5, 0x8e, 0xd7, 0x75, 0x22, 0x3b, 0xbe,
0x25, 0x7d, 0xea, 0xf7, 0x0e, 0xf9, 0xd2, 0x08,
@@ -518,14 +410,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x3b, 0xd3, 0x7c, 0x2b, 0xc8, 0x23, 0xee, 0x27,
0x1a, 0x23, 0xf8, 0xf5, 0xc0, 0x9e, 0x1b, 0x71,
0x68, 0x7a, 0xec, 0x17, 0xe3, 0x8e, 0x46, 0x91 },
- { 0x26, 0xb2, 0x11, 0xcc, 0x34, 0x6d, 0x60, 0x37,
- 0x1b, 0x24, 0xbd, 0x0d, 0xba, 0xb3, 0xf4, 0x3d,
- 0x5d, 0xe3, 0xf2, 0x05, 0x47, 0xc1, 0x4c, 0x0b,
- 0xa1, 0xe0, 0xb2, 0xed, 0xdd, 0x73, 0x02, 0x64 },
- { 0x26, 0xb9, 0x4c, 0xa0, 0x1e, 0x63, 0x4e, 0xd0,
- 0xcb, 0x4f, 0xf3, 0xc9, 0xbc, 0xc2, 0x8a, 0x5e,
- 0x8f, 0x49, 0xca, 0xcd, 0xe7, 0xeb, 0xa2, 0x63,
- 0x2d, 0x3d, 0x30, 0x3f, 0xb2, 0xed, 0xe8, 0x63 },
{ 0x27, 0x50, 0x11, 0x93, 0xe4, 0x61, 0xca, 0xce,
0x55, 0x32, 0xfa, 0xd5, 0xd5, 0xb2, 0x7e, 0x01,
0x16, 0x57, 0x92, 0xe0, 0x4f, 0x24, 0x21, 0x93,
@@ -546,10 +430,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x36, 0x15, 0xdf, 0x12, 0x2e, 0x95, 0x21, 0x17,
0x42, 0x15, 0xee, 0x68, 0xf7, 0x44, 0xb2, 0xfa,
0x35, 0xd2, 0x9c, 0x5d, 0xf1, 0x08, 0xf5, 0x5b },
- { 0x29, 0x4a, 0x2b, 0xf8, 0x7b, 0x50, 0x1d, 0x28,
- 0x4f, 0x37, 0x80, 0x96, 0x0e, 0x8e, 0x72, 0xa1,
- 0x8a, 0xf1, 0xc6, 0x3b, 0xd7, 0xde, 0x4c, 0x4d,
- 0xde, 0xa3, 0x7b, 0xf0, 0x27, 0xd4, 0x2c, 0xb8 },
{ 0x29, 0x74, 0x8a, 0x69, 0xe9, 0x42, 0xa0, 0x67,
0xe6, 0xa6, 0xa3, 0x5a, 0x9d, 0x40, 0x00, 0x0a,
0x31, 0x8d, 0x7d, 0xdf, 0x5f, 0x5a, 0x2f, 0x4d,
@@ -582,10 +462,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xe9, 0xaa, 0x52, 0x1e, 0xaa, 0x76, 0xac, 0x7e,
0x55, 0x73, 0x7b, 0xf4, 0x3e, 0x2b, 0x0c, 0x30,
0xdd, 0xcf, 0x59, 0x87, 0x2e, 0xab, 0xe7, 0x7b },
- { 0x2c, 0xf2, 0x6d, 0xa5, 0x76, 0x7e, 0xde, 0x07,
- 0xc3, 0x73, 0x58, 0xcd, 0x5f, 0x71, 0xd1, 0x23,
- 0xbb, 0x19, 0x77, 0x28, 0x85, 0x87, 0xc7, 0x3f,
- 0x84, 0xb0, 0x8f, 0xf8, 0xaa, 0x01, 0x9a, 0x69 },
{ 0x2d, 0xd5, 0xe6, 0xd3, 0x73, 0x36, 0x34, 0x2f,
0x01, 0x1e, 0xb9, 0x7a, 0x2b, 0x77, 0x38, 0x9d,
0xe6, 0xd2, 0x23, 0x8d, 0x87, 0x69, 0x65, 0x08,
@@ -602,10 +478,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xb3, 0xd7, 0xdf, 0x24, 0xca, 0x74, 0xa7, 0x7d,
0xdc, 0x12, 0x06, 0x01, 0x52, 0x7b, 0x0f, 0x51,
0x06, 0x91, 0x05, 0xca, 0x88, 0x37, 0x6e, 0x20 },
- { 0x2f, 0x39, 0xbb, 0x30, 0xaa, 0x5c, 0xbb, 0x62,
- 0x01, 0x7c, 0x6c, 0x79, 0x90, 0xe3, 0xf9, 0xa4,
- 0x0d, 0x46, 0x9f, 0x76, 0x50, 0x59, 0x81, 0xc8,
- 0x6f, 0x95, 0x55, 0x4f, 0x48, 0x7a, 0x52, 0x76 },
{ 0x2f, 0xef, 0xa7, 0xcb, 0x12, 0x6b, 0x81, 0xc9,
0x47, 0x4d, 0x3e, 0x2c, 0x9b, 0x97, 0x3a, 0x83,
0x69, 0xbb, 0x08, 0x43, 0x41, 0xd3, 0x82, 0xd3,
@@ -630,10 +502,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x36, 0x98, 0x50, 0x9d, 0x8f, 0x8b, 0xfb,
- 0xd4, 0xf9, 0x04, 0xbd, 0x1d, 0x84, 0x64, 0x12,
- 0xc5, 0x27, 0xb7, 0x70, 0x06, 0x2a, 0xad, 0xdf,
- 0x9e, 0x91, 0x9d, 0x84, 0x10, 0xea, 0xa4, 0x9f },
{ 0x32, 0x8b, 0x9a, 0x45, 0xef, 0xef, 0x20, 0xb5,
0xd1, 0x57, 0x39, 0xdd, 0xfa, 0xc1, 0x0c, 0x7e,
0xfe, 0x5f, 0xa7, 0x96, 0xbf, 0xe0, 0x1e, 0xd1,
@@ -670,10 +538,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xc8, 0x68, 0x5e, 0xea, 0xac, 0x57, 0x87, 0x2d,
0x3b, 0x47, 0xe6, 0x02, 0xf4, 0x97, 0xe9, 0xf0,
0x28, 0x54, 0x12, 0x32, 0x59, 0xfb, 0xe1, 0x69 },
- { 0x34, 0xe6, 0xf1, 0x7a, 0x14, 0xd3, 0xd2, 0x8a,
- 0xfd, 0x51, 0xcf, 0x40, 0x49, 0x3a, 0xb2, 0xcf,
- 0xe0, 0x18, 0xef, 0x98, 0x1e, 0x23, 0xf1, 0xfc,
- 0x91, 0x60, 0xfb, 0x91, 0x2c, 0xdc, 0x5c, 0xb9 },
{ 0x35, 0x49, 0xb6, 0xec, 0xbd, 0x8d, 0x25, 0x2b,
0xe7, 0x17, 0xb9, 0x22, 0x73, 0x27, 0x38, 0x08,
0x0b, 0xaf, 0xd5, 0x60, 0xb4, 0x5a, 0x05, 0x40,
@@ -730,10 +594,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x43, 0x61, 0xa6, 0xc9, 0x72, 0xf0, 0xc5, 0x7c,
0xc0, 0x87, 0x74, 0x01, 0x06, 0x12, 0x78, 0x3f,
0xba, 0xbc, 0xb8, 0xd6, 0xf6, 0x03, 0x9e, 0x2c },
- { 0x39, 0xd7, 0x44, 0x77, 0x31, 0x72, 0x8b, 0xba,
- 0x92, 0x36, 0x72, 0x7d, 0xbd, 0x7c, 0x7e, 0xe1,
- 0x70, 0xe5, 0x9f, 0x3b, 0x53, 0x73, 0x79, 0x6d,
- 0x7d, 0xe1, 0xc6, 0xa2, 0xbe, 0x31, 0x22, 0x18 },
{ 0x39, 0xff, 0x6e, 0x31, 0x69, 0x9f, 0x5d, 0x68,
0x92, 0x97, 0x6d, 0x11, 0xdd, 0xbb, 0x14, 0x24,
0xed, 0x0c, 0xec, 0x48, 0x36, 0x3e, 0x94, 0xea,
@@ -754,10 +614,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xc9, 0x69, 0xa7, 0xfb, 0xd5, 0x11, 0x33, 0xa2,
0xb3, 0xc4, 0xdf, 0xb6, 0xba, 0x38, 0x5d, 0xce,
0x3f, 0xb8, 0x4d, 0x73, 0x6b, 0xea, 0xb1, 0xd9 },
- { 0x3b, 0x93, 0xac, 0x19, 0x6e, 0xc6, 0x7b, 0xf2,
- 0x78, 0x7f, 0x42, 0x40, 0xc0, 0xd1, 0x11, 0x37,
- 0xef, 0x79, 0xa4, 0xed, 0x1f, 0x5d, 0x1f, 0x3d,
- 0x04, 0x24, 0x1f, 0x03, 0xdc, 0x2d, 0xa3, 0x70 },
{ 0x3b, 0xaa, 0x31, 0x31, 0x70, 0x68, 0xac, 0xe0,
0x89, 0xae, 0xb4, 0xa8, 0x8d, 0x7e, 0xde, 0xbe,
0x94, 0xab, 0x4a, 0xce, 0x46, 0xbb, 0xd2, 0x68,
@@ -774,10 +630,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x27, 0x6c, 0x81, 0x47, 0x97, 0xc7, 0xbc, 0x7a,
0x6c, 0x14, 0xf7, 0x95, 0x3e, 0x7e, 0x9f, 0xea,
0x69, 0x51, 0x04, 0x0f, 0x2d, 0xaf, 0xbe, 0x9a },
- { 0x3d, 0x45, 0xbf, 0x0f, 0x64, 0x9b, 0xf5, 0xd1,
- 0xf8, 0x91, 0x85, 0x31, 0xa7, 0x7c, 0xf9, 0xbf,
- 0x5c, 0xa1, 0x85, 0x0c, 0x82, 0x02, 0x69, 0xd7,
- 0xb2, 0xc8, 0xec, 0xd0, 0x54, 0x3a, 0x61, 0x65 },
{ 0x3e, 0x8e, 0x9b, 0xad, 0x8e, 0xd9, 0xb5, 0x72,
0x38, 0x2e, 0x59, 0x8d, 0x2d, 0x73, 0x67, 0xe1,
0xfd, 0x6a, 0xf6, 0x95, 0x25, 0x00, 0x9d, 0x67,
@@ -790,18 +642,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x3f, 0x08, 0x2f, 0xab, 0x0c, 0xbd, 0x83,
- 0x16, 0xea, 0x9d, 0xc1, 0xc7, 0x7e, 0xc6, 0x4c,
- 0x32, 0x4d, 0x9c, 0x3d, 0x86, 0x08, 0xc7, 0x79,
- 0x56, 0xf1, 0x27, 0xa9, 0xb8, 0xf4, 0x9c, 0x46 },
{ 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, 0x5c, 0xfc, 0xab, 0x44, 0x1a, 0x30, 0xd8,
- 0xf0, 0x1a, 0xc1, 0xae, 0x9e, 0x08, 0xa2, 0xdb,
- 0x70, 0xc4, 0xc1, 0x6d, 0xed, 0x03, 0xa4, 0x21,
- 0xd4, 0x1b, 0x8f, 0x42, 0xd5, 0xc1, 0x89, 0x6e },
{ 0x3f, 0x92, 0x54, 0x89, 0x64, 0xcc, 0xde, 0xfb,
0x29, 0x96, 0x5a, 0x27, 0xc1, 0x6c, 0x2f, 0xed,
0x28, 0xd9, 0xb9, 0x14, 0x0e, 0x4f, 0xb5, 0x5b,
@@ -826,10 +670,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x09, 0x84, 0x85, 0xbf, 0x6f, 0x87, 0x24, 0x5f,
0x4e, 0xc0, 0x54, 0x71, 0xda, 0x59, 0xd0, 0x81,
0x06, 0x01, 0x53, 0xa2, 0x22, 0x25, 0x23, 0x7f },
- { 0x41, 0xab, 0x57, 0x74, 0x49, 0xa7, 0x50, 0xef,
- 0x45, 0x0d, 0x86, 0x4d, 0xb0, 0x6b, 0x7c, 0xba,
- 0x1f, 0x63, 0xe1, 0x1d, 0x1d, 0x86, 0xb7, 0x8c,
- 0x70, 0x5b, 0xb4, 0x27, 0x34, 0xf5, 0x05, 0x2d },
{ 0x42, 0x08, 0x71, 0xd8, 0xac, 0x49, 0x3c, 0xf9,
0x46, 0x8b, 0xb3, 0x76, 0x97, 0x6d, 0x65, 0x5e,
0xf0, 0xaf, 0xaa, 0xc2, 0x3d, 0x77, 0x00, 0x92,
@@ -910,10 +750,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xd4, 0x53, 0xbc, 0x68, 0x9c, 0x2c, 0x63, 0x10,
0x6f, 0xff, 0xc2, 0xb1, 0x86, 0x23, 0xaa, 0x0b,
0xde, 0xaa, 0xb4, 0xf9, 0xeb, 0x7c, 0x0e, 0x42 },
- { 0x4a, 0xa7, 0xd5, 0xcd, 0xb1, 0x8e, 0x5e, 0xae,
- 0x05, 0x9d, 0x54, 0x10, 0xfd, 0x5b, 0x44, 0xa5,
- 0x9e, 0xba, 0x0d, 0xe9, 0x66, 0x3c, 0x42, 0x2f,
- 0x42, 0x35, 0x87, 0x04, 0xc3, 0x2c, 0x90, 0x2d },
{ 0x4a, 0xcf, 0x9d, 0xa9, 0x05, 0x2f, 0x0b, 0x8c,
0xff, 0xf7, 0x37, 0xcd, 0xa3, 0x39, 0x11, 0xc2,
0x9e, 0xfc, 0xbf, 0xfd, 0x4b, 0xf4, 0xb7, 0x24,
@@ -922,10 +758,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xc5, 0xde, 0xb8, 0x6a, 0xff, 0x27, 0x63, 0x55,
0x23, 0x59, 0xda, 0x5b, 0x59, 0x82, 0xe5, 0x38,
0xba, 0xb7, 0xc9, 0x2a, 0x15, 0x9c, 0xb8, 0x3c },
- { 0x4a, 0xe5, 0xe5, 0x1e, 0x7f, 0xf1, 0x67, 0x47,
- 0x77, 0x5e, 0x2b, 0x2c, 0x05, 0x72, 0x1d, 0x95,
- 0xeb, 0xeb, 0x8c, 0x46, 0x01, 0xfd, 0xdc, 0xdc,
- 0x90, 0xfb, 0xce, 0x69, 0x7e, 0x35, 0x01, 0x2c },
{ 0x4b, 0x1f, 0xc8, 0x2d, 0x24, 0x72, 0x92, 0x7a,
0xc1, 0x7c, 0x58, 0x43, 0x07, 0xcb, 0x96, 0xd6,
0xfd, 0xdb, 0x8d, 0x50, 0xa5, 0x29, 0x53, 0x07,
@@ -954,14 +786,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x1b, 0x02, 0x04, 0xba, 0x9f, 0x27, 0xc0, 0xda,
0xcb, 0x2e, 0x47, 0x37, 0x72, 0x64, 0xcd, 0x31,
0xc4, 0xfe, 0xa4, 0xa4, 0x58, 0x5a, 0x99, 0x60 },
- { 0x4c, 0x3c, 0x7c, 0xbc, 0x42, 0x1c, 0xe0, 0xd1,
- 0x84, 0x4e, 0xa7, 0xb4, 0x6f, 0x61, 0xd7, 0x87,
- 0xe0, 0x4f, 0x94, 0x01, 0x71, 0x49, 0xbe, 0xa3,
- 0x28, 0xed, 0xc3, 0x6c, 0x20, 0xe3, 0x2f, 0xaa },
- { 0x4c, 0x4b, 0xb6, 0x05, 0x65, 0xb5, 0xca, 0x7f,
- 0x02, 0xf8, 0xf5, 0x9b, 0xfa, 0x1d, 0x1d, 0x62,
- 0x71, 0xb2, 0xf1, 0x4d, 0x5c, 0xd3, 0xa0, 0x43,
- 0x51, 0xc3, 0xc4, 0x9d, 0x3f, 0xa0, 0x43, 0xb4 },
{ 0x4c, 0x8a, 0x29, 0xb5, 0x81, 0x7d, 0x90, 0x99,
0xa4, 0xfe, 0xd1, 0xe7, 0x93, 0xb2, 0x8e, 0x2f,
0xaf, 0x6e, 0x87, 0x14, 0xee, 0x77, 0x60, 0xa7,
@@ -970,14 +794,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xc2, 0x63, 0x4e, 0x7a, 0x73, 0x76, 0x12, 0xf6,
0x3a, 0x17, 0xff, 0x51, 0x0a, 0x77, 0xa8, 0x04,
0xbb, 0x33, 0x1b, 0x2b, 0xe5, 0x8d, 0xfe, 0x0c },
- { 0x4c, 0xd8, 0x6a, 0xa6, 0x0c, 0xb3, 0x69, 0x00,
- 0xa9, 0xaa, 0x3b, 0x7b, 0x02, 0x7d, 0x71, 0x4c,
- 0x0f, 0x76, 0x07, 0xc3, 0x56, 0x73, 0x3b, 0xa2,
- 0x21, 0xaa, 0xe4, 0x09, 0x47, 0xf7, 0xfa, 0xcb },
- { 0x4d, 0x54, 0x4d, 0x4e, 0x41, 0xc0, 0xfb, 0x15,
- 0x5f, 0x04, 0x7d, 0x7f, 0xb1, 0xef, 0x29, 0xd1,
- 0x1b, 0xdf, 0xec, 0xa9, 0xd4, 0x11, 0xaf, 0x8b,
- 0x12, 0x54, 0x1f, 0x11, 0x50, 0xc0, 0xb4, 0x44 },
{ 0x4d, 0xcf, 0xeb, 0xdc, 0x15, 0x4b, 0x0c, 0x85,
0x46, 0x7f, 0x6f, 0x52, 0xad, 0x80, 0x4e, 0x19,
0x1d, 0x5b, 0xc8, 0x13, 0x51, 0x72, 0x0e, 0xc0,
@@ -994,22 +810,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x23, 0xc6, 0x87, 0x0c, 0x7c, 0xfa, 0x6d,
- 0x31, 0x92, 0x70, 0x3d, 0xca, 0xfd, 0x8f, 0x46,
- 0xb7, 0xbc, 0xc3, 0x72, 0xdc, 0x6d, 0x1c, 0x61,
- 0x00, 0x9a, 0x01, 0x75, 0x20, 0xe9, 0xf3, 0xdf },
- { 0x4f, 0x54, 0x31, 0xa9, 0xa1, 0x5e, 0x08, 0x9b,
- 0x70, 0x53, 0xb6, 0x61, 0x47, 0xe2, 0xb6, 0x23,
- 0xd5, 0x87, 0x6f, 0x9a, 0x04, 0x56, 0x44, 0x67,
- 0xae, 0x16, 0x13, 0xf6, 0xa8, 0x15, 0x98, 0x38 },
- { 0x4f, 0x9a, 0xcc, 0x0b, 0x75, 0xce, 0xaa, 0x7c,
- 0xb3, 0x88, 0x47, 0x09, 0x52, 0xc9, 0x98, 0x08,
- 0xe4, 0xf3, 0xcb, 0x99, 0xa7, 0x73, 0xa6, 0x00,
- 0xcd, 0xdf, 0x2c, 0xf3, 0x1a, 0xe7, 0xec, 0x72 },
- { 0x4f, 0xaf, 0xae, 0xbc, 0x7e, 0x20, 0x21, 0xc8,
- 0x43, 0x86, 0xec, 0x9d, 0x82, 0xa4, 0x9c, 0x24,
- 0xdb, 0xef, 0xeb, 0x71, 0x2e, 0xa7, 0x2c, 0x0d,
- 0x64, 0x73, 0x51, 0x86, 0x13, 0x53, 0xcd, 0x69 },
{ 0x4f, 0xe9, 0xf1, 0x68, 0x70, 0x6a, 0x07, 0x5d,
0xa9, 0x6c, 0x71, 0x3d, 0xa4, 0x32, 0x61, 0xe3,
0x39, 0xa9, 0x93, 0x6e, 0xdd, 0xd5, 0x88, 0x8b,
@@ -1022,10 +822,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x4c, 0x99, 0x15, 0x38, 0xdd, 0xd5, 0x1d, 0x01,
0x49, 0xcd, 0x9f, 0xf3, 0x60, 0x49, 0xf3, 0xd8,
0xa0, 0xb2, 0xd2, 0x92, 0x23, 0xf7, 0x91, 0x38 },
- { 0x50, 0x81, 0x1d, 0x6e, 0x9d, 0xaf, 0x31, 0x2a,
- 0x6a, 0xc2, 0xaf, 0x6b, 0x52, 0x13, 0xc9, 0x56,
- 0x20, 0xe0, 0x24, 0xe0, 0x87, 0xae, 0x5e, 0xb0,
- 0xcc, 0x8a, 0xa2, 0x6f, 0xbe, 0xd9, 0xd9, 0x85 },
{ 0x50, 0xf4, 0x78, 0x1e, 0xb1, 0xc1, 0x46, 0x70,
0xd9, 0xa5, 0x52, 0xc3, 0x49, 0x5f, 0xb9, 0xf6,
0xae, 0x86, 0x8a, 0xb1, 0xc9, 0xd9, 0x83, 0xe0,
@@ -1074,18 +870,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xe0, 0x3b, 0x48, 0x2f, 0x51, 0x95, 0x1c, 0x7e,
0xf0, 0x73, 0x45, 0x53, 0xce, 0xc7, 0x80, 0xfb,
0xdc, 0xfa, 0x30, 0x0c, 0xc1, 0x79, 0x0d, 0x66 },
- { 0x54, 0xa5, 0x1f, 0x64, 0xd6, 0x28, 0x61, 0x49,
- 0xf2, 0x3a, 0x43, 0xcc, 0x73, 0x67, 0x00, 0x0e,
- 0xf0, 0x16, 0x03, 0x89, 0x9c, 0xbc, 0x94, 0xa1,
- 0xa4, 0xe3, 0xbe, 0xec, 0xfe, 0xe8, 0x40, 0x66 },
{ 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, 0x54, 0xec, 0x61, 0xf2, 0x57, 0x6e, 0x34,
- 0xe7, 0x21, 0x56, 0xa6, 0xf6, 0xfd, 0x5e, 0xe8,
- 0xf4, 0x26, 0x2a, 0xb5, 0x3f, 0x7b, 0xc9, 0xf1,
- 0x8b, 0xb6, 0xd7, 0xeb, 0x3e, 0x16, 0x28, 0xde },
{ 0x55, 0xb2, 0x84, 0x5f, 0x48, 0x44, 0xa7, 0x72,
0x46, 0x36, 0x41, 0x78, 0xa1, 0x71, 0xc2, 0x26,
0xfc, 0xfd, 0x75, 0xc7, 0x63, 0xba, 0xd0, 0x87,
@@ -1094,14 +882,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x58, 0x4d, 0x9e, 0x7b, 0x57, 0x92, 0xa4, 0x03,
0xc2, 0x1d, 0x39, 0xd6, 0xe1, 0xf5, 0xe8, 0xed,
0x37, 0xb9, 0x3f, 0xa6, 0x1d, 0x88, 0x35, 0x16 },
- { 0x56, 0x96, 0x18, 0xd5, 0x4e, 0x3c, 0x61, 0x1b,
- 0x79, 0x7e, 0xeb, 0x01, 0xdf, 0x9c, 0x1c, 0x5c,
- 0x14, 0x6d, 0x87, 0xb3, 0xb1, 0x29, 0xba, 0x42,
- 0x29, 0x88, 0x88, 0x82, 0x10, 0x04, 0xfd, 0xcb },
- { 0x57, 0xc1, 0x4c, 0x78, 0x2c, 0xf5, 0x8c, 0x3b,
- 0x72, 0x28, 0x0f, 0xef, 0x7d, 0xa9, 0xe2, 0xd9,
- 0x71, 0xe5, 0x25, 0x03, 0xc4, 0x15, 0x99, 0x59,
- 0x68, 0xb6, 0x04, 0x37, 0x2a, 0x18, 0x96, 0xbf },
{ 0x58, 0x0c, 0x45, 0xd6, 0xe2, 0x55, 0x8e, 0x7c,
0x7d, 0xa8, 0x19, 0xa5, 0x99, 0xd5, 0xb1, 0x6f,
0x0e, 0x18, 0x79, 0xf0, 0xcb, 0x58, 0x31, 0xdf,
@@ -1110,10 +890,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x43, 0x09, 0x51, 0x02, 0x8b, 0x87, 0x78,
- 0x01, 0x67, 0xc9, 0x56, 0x47, 0x9a, 0x81, 0x5f,
- 0x91, 0xbc, 0x6c, 0x00, 0xc2, 0xe5, 0x0c, 0x35,
- 0xf0, 0x5f, 0xcf, 0xf5, 0x27, 0x68, 0xc7, 0x37 },
{ 0x59, 0xc9, 0xe8, 0xdf, 0x03, 0x0b, 0x1c, 0xd5,
0x89, 0xa8, 0xb3, 0x4f, 0xe7, 0x42, 0x51, 0xea,
0xd5, 0xa5, 0xfb, 0xe9, 0xe6, 0x13, 0x67, 0xca,
@@ -1126,10 +902,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x2c, 0xb6, 0x0c, 0x80, 0xe7, 0x37,
- 0x33, 0x72, 0x1c, 0xa6, 0xcd, 0x0c, 0x88, 0x63,
- 0xdd, 0x9a, 0xf6, 0xb8, 0x2f, 0x35, 0x0c, 0xe9,
- 0x88, 0x72, 0xf2, 0x2e, 0x23, 0x89, 0x5a, 0x55 },
{ 0x59, 0xee, 0x9b, 0x36, 0x80, 0xae, 0x20, 0x56,
0x83, 0x9c, 0x0b, 0xf6, 0x9e, 0xe6, 0x63, 0x26,
0x57, 0x16, 0xa8, 0xe2, 0x4c, 0xc6, 0x49, 0x95,
@@ -1138,10 +910,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x13, 0xb1, 0xb6, 0xae, 0xdf, 0xd3, 0xae, 0x8f,
0xe5, 0xfc, 0x42, 0x2f, 0xdb, 0x3b, 0xa7, 0x9e,
0xf7, 0x17, 0xa9, 0xbe, 0x19, 0xfa, 0x89, 0xdc },
- { 0x5a, 0x6b, 0xb1, 0x1f, 0x2e, 0xfd, 0x5e, 0x60,
- 0x25, 0xc6, 0x06, 0xf5, 0x58, 0x81, 0x30, 0xe1,
- 0x7c, 0x88, 0xed, 0xae, 0xdc, 0x2a, 0xa9, 0x41,
- 0xe2, 0x54, 0x3a, 0xdd, 0x77, 0x25, 0x31, 0xbe },
{ 0x5a, 0x84, 0xaf, 0xe6, 0x74, 0x05, 0xab, 0xe8,
0x4a, 0x0c, 0xd4, 0x2c, 0x2b, 0xa2, 0xe4, 0xc8,
0x8f, 0x35, 0xe0, 0xa5, 0x95, 0xe5, 0x69, 0xa3,
@@ -1154,18 +922,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xa9, 0x38, 0x1a, 0x5c, 0xd8, 0x7b, 0x80, 0xd1,
0x10, 0xf2, 0x6e, 0xe8, 0x39, 0x27, 0x1b, 0xc2,
0x70, 0x60, 0x8f, 0xd1, 0x43, 0x7f, 0x55, 0xb0 },
- { 0x5b, 0x1f, 0x32, 0x78, 0x8d, 0xd9, 0xd7, 0xe9,
- 0x06, 0x80, 0x7d, 0x03, 0x01, 0x45, 0xc8, 0xad,
- 0x20, 0x11, 0x03, 0x0c, 0xdb, 0xf0, 0xa6, 0x03,
- 0x08, 0x14, 0x93, 0x7e, 0x54, 0xd1, 0x54, 0x68 },
{ 0x5b, 0x29, 0x3d, 0x30, 0x9f, 0x64, 0x24, 0xbc,
0x26, 0x4f, 0x4b, 0xb0, 0x18, 0xae, 0xf5, 0x0e,
0x63, 0xe3, 0x37, 0xd1, 0x4d, 0xf0, 0x64, 0xc5,
0x7a, 0x23, 0x52, 0x83, 0x42, 0x16, 0x1c, 0x68 },
- { 0x5c, 0x06, 0x2f, 0x0d, 0x7e, 0x21, 0x91, 0xdf,
- 0xc1, 0x60, 0xe4, 0xc0, 0x59, 0xae, 0xd4, 0xd1,
- 0x83, 0xbd, 0x2d, 0x0f, 0x40, 0x98, 0x3d, 0x03,
- 0xb4, 0xe8, 0xda, 0xa1, 0x1f, 0xf5, 0xe8, 0x95 },
{ 0x5c, 0x7f, 0xf0, 0x55, 0xc2, 0xfd, 0x03, 0x3f,
0x34, 0xc4, 0xc4, 0xf7, 0xc4, 0xfb, 0x7d, 0xda,
0xaa, 0xfb, 0x43, 0x56, 0xc5, 0x60, 0xc9, 0x9e,
@@ -1182,10 +942,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x5f, 0x61, 0x6a, 0x95, 0x17, 0xa1, 0x30, 0xd8,
0x66, 0xa8, 0xcb, 0x0b, 0x18, 0x96, 0x3d, 0x54,
0xe7, 0xed, 0xae, 0xe2, 0x61, 0xcb, 0x1c, 0x19 },
- { 0x5e, 0xae, 0xd7, 0x13, 0x5c, 0x21, 0x69, 0x76,
- 0xad, 0x4e, 0xdc, 0x4d, 0xbb, 0x3f, 0x1f, 0xa1,
- 0xf7, 0xc2, 0x85, 0x54, 0xf1, 0x4f, 0x1a, 0xd1,
- 0xc6, 0x2a, 0xba, 0xbb, 0x00, 0xcf, 0x7b, 0x66 },
{ 0x5f, 0x5c, 0xca, 0x19, 0x1e, 0xc9, 0x2f, 0x4d,
0xad, 0x96, 0x6d, 0xaa, 0xfd, 0x6d, 0xe7, 0x56,
0x34, 0x44, 0x18, 0x60, 0x4d, 0x8a, 0xd5, 0x0a,
@@ -1198,10 +954,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x5a, 0x91, 0x72, 0x90, 0xac, 0xa6, 0x5a, 0xfd,
0x6e, 0xbd, 0xae, 0x05, 0xa0, 0x2a, 0xaf, 0x04,
0x29, 0xe9, 0x72, 0xec, 0x01, 0x90, 0xec, 0xfc },
- { 0x60, 0x1a, 0xf7, 0x2f, 0xb0, 0x6f, 0xe6, 0x68,
- 0x79, 0x92, 0xc5, 0x8f, 0xac, 0x32, 0xe3, 0x0c,
- 0x01, 0x9e, 0xaf, 0x41, 0xe0, 0xb3, 0x85, 0x7e,
- 0xa9, 0x00, 0xa1, 0x61, 0x08, 0xeb, 0x34, 0xde },
{ 0x60, 0xca, 0x81, 0xe3, 0x5b, 0x9a, 0x6f, 0x07,
0xe1, 0x3c, 0x02, 0xae, 0x41, 0x15, 0xb0, 0x00,
0x54, 0x30, 0xcf, 0x46, 0x0e, 0xfc, 0x7d, 0xba,
@@ -1218,18 +970,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x35, 0x8c, 0x6d, 0xeb, 0xdf, 0x48, 0x2b,
- 0xb2, 0xd3, 0x21, 0x13, 0xd3, 0xf0, 0xb1, 0x73,
- 0x77, 0xe2, 0xf7, 0xc9, 0x25, 0xb9, 0xfe, 0xb3,
- 0x47, 0x8b, 0xd9, 0x94, 0x56, 0x31, 0x3e, 0x78 },
{ 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 },
- { 0x63, 0x6a, 0x25, 0xbd, 0xdb, 0xb6, 0x5e, 0x7c,
- 0xc0, 0xe6, 0x1f, 0x91, 0xca, 0xfe, 0xb1, 0xfe,
- 0x5d, 0xd2, 0x67, 0xac, 0x67, 0x32, 0x25, 0xcc,
- 0x81, 0x8e, 0xa0, 0x2b, 0x9c, 0xc9, 0x4b, 0xe2 },
{ 0x64, 0xd4, 0x92, 0x41, 0x6e, 0xe0, 0x55, 0x57,
0x9c, 0x46, 0x3b, 0x21, 0x1a, 0xfe, 0xf7, 0x46,
0xc3, 0x30, 0xca, 0x05, 0xf4, 0x4d, 0x85, 0x90,
@@ -1290,18 +1034,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xe6, 0xfa, 0x4a, 0x4e, 0x46, 0xfa, 0x51, 0x74,
0x05, 0xf3, 0x77, 0xc0, 0xde, 0xe3, 0xd4, 0x29,
0x91, 0x4e, 0x6b, 0x7e, 0xa0, 0x8c, 0xb1, 0xa6 },
- { 0x69, 0xd3, 0x38, 0xe5, 0xd8, 0xc0, 0x69, 0xe7,
- 0xdc, 0x10, 0xd3, 0x82, 0x1f, 0x7a, 0x83, 0x0d,
- 0xeb, 0x5d, 0x95, 0x7c, 0x8e, 0xc6, 0xec, 0xd2,
- 0x5a, 0xf7, 0x24, 0x3e, 0xd0, 0xe4, 0xdc, 0x26 },
{ 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 },
- { 0x6a, 0xc3, 0x2d, 0xa9, 0x16, 0x8f, 0x70, 0xd0,
- 0x9f, 0xe9, 0xf7, 0x55, 0x3e, 0x67, 0x0f, 0xa4,
- 0xaa, 0xac, 0xe8, 0x7b, 0x5a, 0x0b, 0x9a, 0x3f,
- 0x22, 0x2d, 0x7a, 0x8b, 0xba, 0x76, 0xd2, 0xf2 },
{ 0x6a, 0xe7, 0x98, 0xd7, 0xde, 0x07, 0x84, 0x90,
0xa5, 0x0f, 0x73, 0x89, 0x86, 0xd4, 0x03, 0x39,
0x42, 0x97, 0x9d, 0xe2, 0x42, 0x6a, 0xfa, 0x95,
@@ -1330,10 +1066,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x86, 0x70, 0xd1, 0xc2, 0x01, 0x76, 0x57, 0xb0,
0xc5, 0xd6, 0x1a, 0x26, 0xc9, 0xcb, 0xd1, 0xea,
0x75, 0x5c, 0x68, 0x20, 0xb5, 0xf6, 0xd6, 0x7d },
- { 0x6c, 0xc8, 0x0f, 0x47, 0x96, 0x4e, 0x0d, 0xcb,
- 0x39, 0xe4, 0xd0, 0x1b, 0x3b, 0x3e, 0xbc, 0x8b,
- 0x9c, 0x77, 0xb4, 0x08, 0x59, 0xbb, 0x5d, 0x5c,
- 0x31, 0x27, 0x4d, 0xa5, 0x39, 0xfa, 0xca, 0x8d },
{ 0x6d, 0x32, 0xf4, 0x93, 0x40, 0x56, 0xee, 0x17,
0x14, 0xca, 0x72, 0x70, 0x3f, 0x64, 0x46, 0x9b,
0x98, 0x58, 0xfc, 0x39, 0x96, 0x4b, 0x4c, 0x03,
@@ -1342,10 +1074,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x3c, 0x6b, 0x7c, 0xb7, 0xe4, 0xe4, 0x25, 0xc8,
0xe2, 0x1f, 0x79, 0xff, 0x4d, 0x40, 0x00, 0xb9,
0x65, 0x3f, 0xa1, 0x27, 0xe1, 0x41, 0xd3, 0x50 },
- { 0x6d, 0x4e, 0xe5, 0x3b, 0xf9, 0x9f, 0xfa, 0xbb,
- 0x1c, 0x9b, 0x77, 0x96, 0x66, 0xef, 0xc4, 0x5e,
- 0x6a, 0xb3, 0xfa, 0x74, 0xab, 0x37, 0x30, 0x9f,
- 0x8c, 0xde, 0xf7, 0x2c, 0x94, 0x39, 0x23, 0xee },
{ 0x6d, 0xc9, 0x87, 0x5c, 0xd3, 0x46, 0xa2, 0x2b,
0x47, 0xb2, 0x80, 0xb1, 0xb1, 0x45, 0x0d, 0x87,
0x8e, 0x09, 0x8b, 0xb2, 0xe2, 0xa9, 0xe3, 0xc2,
@@ -1366,10 +1094,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xfb, 0x06, 0x04, 0x56, 0xee, 0xe8, 0x74, 0xed,
0xd9, 0xfa, 0x71, 0x3f, 0x26, 0x95, 0xee, 0x5e,
0xe8, 0x59, 0x84, 0x83, 0xe3, 0x02, 0x8f, 0x0b },
- { 0x6e, 0x8d, 0x55, 0xee, 0x2f, 0x72, 0x5a, 0x0b,
- 0xa5, 0xdf, 0x43, 0x43, 0xa0, 0x6f, 0xd3, 0x71,
- 0x54, 0x25, 0x6b, 0xcf, 0xf7, 0xce, 0xe0, 0xb7,
- 0x00, 0xac, 0xdd, 0x91, 0x56, 0x49, 0x79, 0x99 },
{ 0x6e, 0x99, 0x8d, 0xdd, 0xf2, 0x93, 0x9b, 0xfe,
0x8c, 0xc5, 0x2a, 0x48, 0x0a, 0xc0, 0x6d, 0x69,
0x71, 0xc5, 0xa3, 0xda, 0x97, 0xcf, 0x3e, 0xf0,
@@ -1414,18 +1138,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x29, 0x62, 0x43, 0xc0, 0xdd, 0x61, 0xb1,
- 0x7f, 0x5c, 0x58, 0x89, 0x4c, 0x31, 0x3e, 0xf7,
- 0xa8, 0x48, 0xae, 0xe3, 0x1b, 0x08, 0x96, 0xe0,
- 0xb3, 0xe1, 0x51, 0x7f, 0x6e, 0x6d, 0x9f, 0x2f },
{ 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 },
- { 0x73, 0x9d, 0x17, 0x23, 0x23, 0xf2, 0xb2, 0x84,
- 0x07, 0x0a, 0xce, 0x43, 0x09, 0x8c, 0x8b, 0x21,
- 0xc4, 0x7a, 0x53, 0xf9, 0x98, 0x5f, 0x2f, 0xad,
- 0x5f, 0x8b, 0x2e, 0xb7, 0x03, 0x4f, 0xdb, 0x21 },
{ 0x74, 0x54, 0x0f, 0xa5, 0x0a, 0x36, 0x2e, 0x68,
0x6d, 0x99, 0x17, 0x98, 0x18, 0x35, 0x09, 0x83,
0x6c, 0x95, 0xa3, 0xfb, 0x04, 0x58, 0x00, 0x22,
@@ -1434,18 +1150,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0xa9, 0x27, 0xe7, 0xb2, 0xf1, 0xf6, 0x48,
- 0x3d, 0xc2, 0x59, 0x21, 0xab, 0xbe, 0x2f, 0x97,
- 0x74, 0xa2, 0x0c, 0xb8, 0x96, 0xba, 0xb5, 0x64,
- 0x8c, 0x2a, 0xb0, 0xf9, 0xdb, 0xda, 0x3d, 0xa6 },
{ 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 },
- { 0x75, 0xe9, 0xa1, 0x5d, 0x94, 0x88, 0x0c, 0x66,
- 0x14, 0x82, 0xcf, 0xc1, 0x96, 0x4c, 0xbc, 0xe2,
- 0xb1, 0xca, 0x7a, 0x9f, 0x81, 0xd4, 0x07, 0x30,
- 0x12, 0x47, 0x1f, 0x27, 0x23, 0xcb, 0x72, 0x8a },
{ 0x76, 0x73, 0x18, 0x0f, 0x9d, 0x9a, 0x85, 0x48,
0x4b, 0x5c, 0x16, 0x99, 0xa2, 0xdc, 0x17, 0xfc,
0x61, 0x13, 0xa3, 0xed, 0x5b, 0xc9, 0xc0, 0x55,
@@ -1458,10 +1166,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x83, 0x98, 0x71, 0x0f, 0x02, 0x20, 0xfa, 0xf3,
0x30, 0x1d, 0x54, 0x49, 0x38, 0xfb, 0x24, 0x19,
0x2d, 0xec, 0x32, 0xf7, 0x44, 0xe4, 0x22, 0x10 },
- { 0x77, 0x95, 0x6b, 0x48, 0xcd, 0xd9, 0x15, 0x0b,
- 0xd8, 0x7d, 0x8d, 0x81, 0x50, 0x60, 0xac, 0x8c,
- 0x84, 0x81, 0x3a, 0x53, 0x87, 0x1a, 0x58, 0x6a,
- 0x69, 0x8b, 0x18, 0x79, 0x89, 0x13, 0xd3, 0xb8 },
{ 0x77, 0xac, 0x72, 0x54, 0x6a, 0x39, 0xca, 0x2f,
0x24, 0xe2, 0xd1, 0x3c, 0x0d, 0x74, 0x91, 0x5f,
0x67, 0xbc, 0xd4, 0x37, 0x09, 0xa9, 0xe5, 0xdb,
@@ -1478,10 +1182,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x41, 0x36, 0x37, 0x9b, 0xa0, 0xdb, 0xd7,
- 0xb3, 0xba, 0xdc, 0x52, 0xdc, 0xe6, 0xbb, 0x81,
- 0x07, 0xa3, 0x56, 0xc8, 0x48, 0x3f, 0x13, 0xe1,
- 0x69, 0x75, 0x0b, 0xc2, 0x07, 0x0a, 0x67, 0xd9 },
{ 0x78, 0xc9, 0x30, 0x40, 0x5a, 0x72, 0x0d, 0x9f,
0x00, 0x66, 0xdd, 0x88, 0xa2, 0xa8, 0xda, 0xfb,
0xbe, 0x6c, 0xd6, 0x5d, 0x54, 0xb7, 0x76, 0x06,
@@ -1502,18 +1202,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x8a, 0xda, 0x2d, 0xdf, 0xbd, 0x06, 0x8a, 0xc3,
0x5d, 0x0f, 0x9d, 0xfa, 0xe6, 0x70, 0xf3, 0xe3,
0x95, 0xd4, 0x03, 0x7c, 0x3f, 0x8c, 0x4d, 0xd0 },
- { 0x7a, 0x31, 0xb7, 0x14, 0x7a, 0x27, 0x75, 0x33,
- 0x8b, 0xfa, 0x3d, 0x0b, 0xbb, 0x68, 0x56, 0x33,
- 0xfe, 0xb8, 0x5e, 0x2a, 0xf9, 0x4d, 0x71, 0xbf,
- 0x2b, 0x64, 0x0b, 0xe1, 0xe7, 0x1c, 0xe8, 0x34 },
{ 0x7a, 0x42, 0xd5, 0x7b, 0x05, 0x32, 0x4e, 0x85,
0x83, 0x55, 0x05, 0x58, 0x26, 0xb1, 0x55, 0x17,
0x42, 0x5b, 0x5a, 0x18, 0x9c, 0x17, 0xb4, 0x7c,
0x18, 0x4c, 0xac, 0xe7, 0xac, 0x63, 0x18, 0xd0 },
- { 0x7a, 0x5b, 0x68, 0x1e, 0x54, 0x45, 0x1d, 0xcb,
- 0x0a, 0xa6, 0x0d, 0x9f, 0x02, 0xfd, 0x13, 0x7f,
- 0xa5, 0xc1, 0x9e, 0x2b, 0xf7, 0x30, 0xc8, 0x9f,
- 0x36, 0xc9, 0x1c, 0xc6, 0xe7, 0x8c, 0xc6, 0xfb },
{ 0x7b, 0x2c, 0x84, 0x1f, 0x5a, 0x96, 0x35, 0x28,
0xc8, 0x79, 0x9f, 0x4b, 0x71, 0x48, 0xf9, 0xf2,
0xa5, 0x05, 0x15, 0x76, 0x06, 0x9d, 0xef, 0xd9,
@@ -1526,14 +1218,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x94, 0x5a, 0x88, 0xd8, 0xef, 0x18, 0x91, 0xc9,
0x89, 0x97, 0x8a, 0xbf, 0x12, 0x2e, 0xc5, 0xe0,
0x51, 0x4b, 0xe3, 0x6c, 0x3a, 0x7f, 0x22, 0x9b },
- { 0x7c, 0x30, 0xff, 0x35, 0xe7, 0x8a, 0xba, 0x08,
- 0xf8, 0xa9, 0xb4, 0xd9, 0x8e, 0xa2, 0x9a, 0xe4,
- 0xa5, 0xa4, 0x24, 0x72, 0xf5, 0x91, 0xca, 0x11,
- 0xfb, 0x5e, 0x11, 0x21, 0x06, 0x28, 0x63, 0x96 },
- { 0x7c, 0xf9, 0x2f, 0x75, 0xbb, 0xe7, 0xa1, 0x4d,
- 0x86, 0x93, 0xf9, 0x93, 0xc3, 0xd1, 0xa6, 0x08,
- 0xdb, 0xe0, 0xd1, 0x8f, 0x80, 0x8e, 0x21, 0x2d,
- 0xc8, 0xe1, 0xf5, 0xda, 0x58, 0x04, 0xb3, 0x07 },
{ 0x7d, 0x20, 0xc7, 0xa9, 0x27, 0x26, 0x2b, 0xe7,
0x38, 0xd2, 0x58, 0xd0, 0xfd, 0x97, 0x6e, 0x9a,
0xf3, 0x6e, 0xf7, 0x99, 0x5f, 0x05, 0xe2, 0x87,
@@ -1586,10 +1270,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x2e, 0xbe, 0x7b, 0x2e, 0x8a, 0xf1, 0x78,
- 0x8a, 0x36, 0x08, 0x83, 0x84, 0xf4, 0xc0, 0x6a,
- 0x6d, 0x65, 0x9d, 0x95, 0x56, 0x83, 0xf0, 0x99,
- 0xe2, 0x54, 0x2d, 0x97, 0x58, 0xe1, 0xa6, 0x21 },
{ 0x82, 0x56, 0x8b, 0x3b, 0xb3, 0xc6, 0x55, 0xd7,
0xf2, 0x2d, 0x8c, 0x97, 0xa5, 0x66, 0x9c, 0xc8,
0x34, 0xa2, 0xdd, 0x7c, 0xda, 0xe7, 0x5a, 0x26,
@@ -1602,14 +1282,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x18, 0x02, 0x3a, 0xb7, 0x85, 0xfa, 0x3c, 0xde,
0xd6, 0x6f, 0x42, 0x5d, 0xe1, 0xf3, 0x2f, 0xcd,
0x72, 0x1b, 0x49, 0x46, 0x3a, 0x5a, 0x5f, 0x5b },
- { 0x82, 0xc0, 0x7b, 0x94, 0x4b, 0xba, 0xc1, 0xb2,
- 0x95, 0xe2, 0x5f, 0x91, 0xa5, 0xfb, 0x0f, 0x2a,
- 0xfc, 0xba, 0x7e, 0x09, 0xb2, 0x17, 0x27, 0xee,
- 0xd8, 0x13, 0x0c, 0xde, 0x8f, 0x08, 0x0f, 0xca },
- { 0x82, 0xe1, 0xbd, 0xb3, 0xdc, 0x4f, 0x02, 0x36,
- 0x3a, 0x79, 0x6b, 0x60, 0xa8, 0x8e, 0x4e, 0x71,
- 0xbd, 0x33, 0xb0, 0xbe, 0x4c, 0xc5, 0xb8, 0x33,
- 0x25, 0x2b, 0x83, 0x27, 0xb8, 0x0b, 0xd7, 0xe2 },
{ 0x83, 0x25, 0x41, 0x78, 0xae, 0x2c, 0x8b, 0xaa,
0x1a, 0xcb, 0xb9, 0x99, 0x82, 0x63, 0x8c, 0x79,
0x9b, 0x9b, 0x37, 0x9d, 0xa4, 0xd0, 0x2b, 0x28,
@@ -1626,10 +1298,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x2d, 0x39, 0xa8, 0xcf, 0xb7, 0x87, 0xe7, 0x72,
0x77, 0xd5, 0xcf, 0xa3, 0xe3, 0x6f, 0xda, 0xcb,
0xab, 0x4d, 0x18, 0xb2, 0xb0, 0x4e, 0x32, 0x94 },
- { 0x83, 0xf8, 0x00, 0xb3, 0xe5, 0x28, 0x52, 0xde,
- 0xbc, 0xc5, 0x04, 0xc2, 0x5b, 0x63, 0x58, 0x34,
- 0x30, 0x7b, 0x14, 0x5e, 0x38, 0x87, 0x50, 0xaa,
- 0xc1, 0x63, 0x90, 0x9d, 0x30, 0x4b, 0xe3, 0xd2 },
{ 0x84, 0x23, 0xb3, 0xf1, 0xcc, 0x85, 0x2b, 0x49,
0xcf, 0x81, 0xb7, 0xd5, 0xff, 0x51, 0xa7, 0xa5,
0x6a, 0x84, 0x78, 0x3a, 0x2d, 0xf7, 0x43, 0x61,
@@ -1642,10 +1310,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x6f, 0xff, 0x73, 0xf8, 0x2e, 0x6c, 0x75, 0x7c,
0x43, 0x35, 0xae, 0x5d, 0x3a, 0x1f, 0x52, 0xc4,
0xb6, 0x24, 0x08, 0xdb, 0x51, 0xdf, 0x9e, 0xb2 },
- { 0x85, 0x04, 0x81, 0x97, 0xf0, 0x2b, 0xf1, 0xa0,
- 0x38, 0x81, 0x27, 0xe3, 0x2b, 0x5f, 0x0a, 0xd5,
- 0xbc, 0xd9, 0x39, 0x89, 0x14, 0x1e, 0x2c, 0xf3,
- 0x2b, 0x04, 0x6f, 0x19, 0x01, 0x50, 0x59, 0xc8 },
{ 0x85, 0x31, 0xb2, 0xbf, 0xc5, 0x45, 0x79, 0xe8,
0xf1, 0x8f, 0x27, 0xb2, 0xe6, 0xec, 0xc0, 0xf8,
0x90, 0x64, 0xee, 0x86, 0x87, 0x0e, 0xcc, 0x8b,
@@ -1690,10 +1354,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x9f, 0xd1, 0xb8, 0x1d, 0x5d, 0x5d, 0xc4, 0x99,
0xd3, 0x97, 0x65, 0x62, 0x1f, 0x7f, 0x43, 0x0c,
0x73, 0x46, 0xa7, 0x7b, 0x23, 0x39, 0x43, 0x82 },
- { 0x89, 0x76, 0xb5, 0x94, 0xac, 0xdd, 0xc1, 0xb2,
- 0xab, 0xd7, 0x5f, 0xa1, 0xa1, 0xea, 0x24, 0x59,
- 0x92, 0x9a, 0x7e, 0x81, 0x4c, 0x9e, 0xe3, 0xf7,
- 0xba, 0x21, 0xb3, 0x80, 0x82, 0x88, 0xbe, 0xbb },
{ 0x89, 0xaf, 0x0e, 0x54, 0xc7, 0x62, 0x77, 0x86,
0x93, 0x52, 0x9d, 0x0a, 0x95, 0x0b, 0x78, 0x33,
0xf5, 0xea, 0xba, 0xf3, 0x42, 0x79, 0x72, 0x60,
@@ -1734,10 +1394,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x57, 0x0e, 0x5d, 0xe7, 0x04, 0x29, 0x38, 0x70,
0x8a, 0x1b, 0x0f, 0xce, 0xb4, 0x59, 0x86, 0x2a,
0x38, 0x67, 0xb7, 0x34, 0xcd, 0xcb, 0x97, 0x94 },
- { 0x8b, 0x59, 0x74, 0x2d, 0xff, 0xf2, 0xd5, 0xbf,
- 0x70, 0x92, 0x6d, 0x1f, 0xe8, 0x00, 0x7d, 0x35,
- 0x57, 0x91, 0x63, 0xfa, 0x4e, 0xee, 0x1d, 0x03,
- 0x38, 0xf4, 0x4e, 0xd8, 0xd9, 0xfb, 0x67, 0x28 },
{ 0x8c, 0x3e, 0x7c, 0x1d, 0xcc, 0x7d, 0xd8, 0xe7,
0xd8, 0xbf, 0x7b, 0x5b, 0x3a, 0xe5, 0xe0, 0x27,
0x2e, 0x81, 0x1a, 0xb9, 0xf3, 0xc3, 0xc5, 0x38,
@@ -1754,10 +1410,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x5d, 0x6a, 0xe9, 0x75, 0x3e, 0x4d, 0x48, 0xb1,
0x79, 0x23, 0xb9, 0x36, 0x5a, 0x6b, 0x4b, 0x97,
0xc4, 0xec, 0xac, 0x4a, 0x4b, 0x37, 0x03, 0x4b },
- { 0x8c, 0xfa, 0x92, 0x51, 0xb4, 0xda, 0xef, 0x50,
- 0x81, 0x0d, 0x6e, 0x19, 0xf5, 0xf8, 0x8e, 0xa2,
- 0xc6, 0x5d, 0xb7, 0xa2, 0xe8, 0xa5, 0x06, 0xf7,
- 0xdf, 0x99, 0x55, 0x81, 0x7d, 0xdd, 0xeb, 0xc8 },
{ 0x8d, 0x85, 0xda, 0x44, 0x6f, 0x5c, 0x79, 0x54,
0xbd, 0xf7, 0x6c, 0x09, 0x0c, 0xd2, 0x46, 0x68,
0xff, 0x23, 0x3c, 0xcd, 0xf6, 0x6b, 0x94, 0xda,
@@ -1766,10 +1418,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x35, 0xfa, 0xf5, 0x01, 0x5b, 0xe7, 0xda, 0xf4,
0x63, 0xb5, 0xc4, 0x14, 0xea, 0xbc, 0x8b, 0x89,
0xf3, 0xdb, 0xa2, 0x05, 0xab, 0x09, 0xa6, 0x43 },
- { 0x8e, 0x38, 0x31, 0x6e, 0x38, 0x8b, 0x56, 0x17,
- 0x8e, 0x60, 0x10, 0xad, 0xc2, 0xca, 0xbb, 0x40,
- 0x24, 0x92, 0x64, 0xb3, 0x34, 0x42, 0x20, 0xce,
- 0xd9, 0xf6, 0xec, 0xbc, 0xf0, 0x71, 0x1c, 0x34 },
{ 0x8e, 0x57, 0x12, 0xc7, 0x5e, 0xc1, 0xe0, 0x31,
0x73, 0x15, 0x96, 0x35, 0x60, 0xf2, 0x6c, 0x8e,
0xcb, 0x29, 0xa7, 0xa0, 0x28, 0x7f, 0x84, 0xe7,
@@ -1786,10 +1434,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x93, 0xc5, 0xa7, 0xc0, 0x96, 0x66, 0x8b,
- 0xd4, 0x51, 0x56, 0xba, 0xd5, 0x6f, 0x06, 0x12,
- 0x04, 0x5d, 0x63, 0x65, 0xb6, 0xbb, 0xaa, 0x63,
- 0xba, 0xcb, 0xf2, 0xbe, 0x01, 0xb5, 0x2c, 0xd3 },
{ 0x8f, 0x94, 0x15, 0x92, 0x6f, 0x40, 0x49, 0xea,
0x41, 0x8a, 0x30, 0x7c, 0x76, 0x36, 0xe4, 0x9b,
0x14, 0x4f, 0xa5, 0x3e, 0x52, 0xe1, 0x04, 0x15,
@@ -1814,10 +1458,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xea, 0x1f, 0x0f, 0x4f, 0x31, 0xc9, 0x48, 0x9d,
0x38, 0x45, 0x0f, 0x08, 0xca, 0x8b, 0xcc, 0x21,
0x87, 0xf6, 0x90, 0xb4, 0x4f, 0x37, 0x30, 0x17 },
- { 0x91, 0x31, 0x4f, 0xf3, 0xfb, 0x23, 0xd3, 0x41,
- 0x44, 0x63, 0x17, 0xf1, 0xc6, 0xca, 0x9d, 0x6c,
- 0x6d, 0xcb, 0x7a, 0x95, 0x65, 0x1d, 0xa7, 0xe3,
- 0xf1, 0x56, 0x00, 0xf4, 0x3a, 0x25, 0x8a, 0xf3 },
{ 0x91, 0x6b, 0x1a, 0x6b, 0x61, 0x6c, 0x6d, 0x8a,
0xc1, 0x49, 0xa3, 0x31, 0x04, 0x83, 0x51, 0x1a,
0xf7, 0xa7, 0xd5, 0x3c, 0x60, 0x17, 0x9e, 0x7f,
@@ -1838,10 +1478,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x07, 0xe9, 0x40, 0x7f, 0x7f, 0xff, 0x6a, 0x64,
0x63, 0x5d, 0x7c, 0xe9, 0x06, 0x66, 0xd4, 0x29,
0x94, 0x09, 0x7a, 0xf4, 0x0c, 0x31, 0x36, 0xfb },
- { 0x92, 0x83, 0x70, 0x07, 0x63, 0x1b, 0x8f, 0xfa,
- 0x02, 0x91, 0xd9, 0xe9, 0xc4, 0xb0, 0x8a, 0x5b,
- 0xfa, 0x84, 0x5b, 0xa1, 0x7e, 0x79, 0xa2, 0x2d,
- 0x9d, 0x9d, 0x44, 0xb9, 0x02, 0x23, 0x3d, 0x16 },
{ 0x93, 0x03, 0x43, 0xb5, 0xe8, 0xc1, 0x5d, 0x6d,
0x93, 0x9d, 0x0f, 0x39, 0xf0, 0x53, 0x7a, 0xa6,
0x23, 0x3f, 0x61, 0x17, 0x93, 0x79, 0xce, 0xbc,
@@ -1906,18 +1542,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xc0, 0xa8, 0x3e, 0xd4, 0x9e, 0x65, 0x0a, 0xdf,
0xd9, 0xbc, 0x0b, 0x3c, 0x50, 0x04, 0x9d, 0x7b,
0x93, 0x24, 0x5a, 0xcc, 0x3a, 0x0c, 0x16, 0xaf },
- { 0x98, 0x57, 0x02, 0xc0, 0x55, 0x05, 0xd9, 0xba,
- 0xe0, 0xce, 0x23, 0xab, 0x2c, 0xb8, 0x65, 0xa1,
- 0xd1, 0x3f, 0x7b, 0xe0, 0x4f, 0xab, 0xc1, 0x19,
- 0x49, 0x4b, 0x4c, 0xc1, 0x0a, 0x7d, 0x9a, 0xdb },
- { 0x98, 0x76, 0x8d, 0x66, 0x7e, 0x4d, 0xfc, 0x1d,
- 0x99, 0x5e, 0x42, 0xc7, 0x1e, 0x31, 0x93, 0x31,
- 0x6c, 0xef, 0x8c, 0x2a, 0xf5, 0x9a, 0x0e, 0xa6,
- 0x19, 0x81, 0xfb, 0x42, 0x00, 0x72, 0x57, 0xc7 },
- { 0x98, 0x7a, 0xd4, 0x70, 0x5f, 0x65, 0x65, 0xaf,
- 0x64, 0x53, 0x0d, 0x09, 0x60, 0xb8, 0x82, 0x74,
- 0x0a, 0xfb, 0x8a, 0x74, 0xd5, 0xcc, 0x3c, 0x68,
- 0x19, 0x34, 0x69, 0x83, 0xf2, 0x51, 0x33, 0x37 },
{ 0x98, 0xaa, 0xb4, 0xed, 0x43, 0x89, 0xf3, 0x5e,
0x74, 0x23, 0x74, 0x90, 0x68, 0x01, 0x15, 0x3d,
0xc7, 0xc8, 0xe3, 0x2d, 0x18, 0xb4, 0xd7, 0x81,
@@ -1998,14 +1622,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x39, 0xcd, 0x01, 0xec, 0x4b, 0x33, 0xa1, 0x2f,
0x47, 0x51, 0x2f, 0x54, 0x09, 0xff, 0x09, 0x5d,
0x40, 0xaa, 0xd6, 0x20, 0x84, 0xef, 0x15, 0xbe },
- { 0x9d, 0xac, 0x9d, 0x66, 0xde, 0xd0, 0xc1, 0x5d,
- 0x23, 0x24, 0x1a, 0x90, 0x78, 0xa9, 0x1e, 0xc1,
- 0xe9, 0x40, 0x70, 0xa1, 0x5c, 0x70, 0x29, 0x45,
- 0x02, 0xfe, 0x73, 0x8d, 0x12, 0x1c, 0xca, 0xac },
- { 0x9e, 0x80, 0xd0, 0x33, 0xe6, 0x10, 0x90, 0x7b,
- 0xfe, 0x1f, 0xd8, 0xdf, 0x2d, 0x36, 0xdd, 0xef,
- 0x00, 0xc8, 0xfc, 0x7b, 0xf7, 0xb7, 0xfd, 0x7e,
- 0x8d, 0x45, 0x92, 0xab, 0xf3, 0xc4, 0x21, 0xde },
{ 0x9e, 0x98, 0xf7, 0xda, 0x04, 0x74, 0xd4, 0x86,
0x5a, 0xc7, 0x05, 0xd4, 0xd7, 0xab, 0xbe, 0xb7,
0x1a, 0xef, 0xba, 0x2c, 0xf2, 0xe0, 0x82, 0xf0,
@@ -2030,10 +1646,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x06, 0x76, 0x2e, 0x02, 0xe4, 0x20, 0xf1, 0xa9,
0xc4, 0xab, 0x73, 0x29, 0xae, 0x29, 0x5f, 0x01,
0x5f, 0x74, 0x7d, 0xa1, 0x82, 0xa9, 0xc3, 0x9c },
- { 0xa0, 0xab, 0x9f, 0x42, 0xd0, 0x9d, 0x06, 0x44,
- 0x23, 0x8c, 0x63, 0xf2, 0x19, 0x26, 0x52, 0x8f,
- 0xa5, 0x3e, 0x56, 0x6d, 0x83, 0x3e, 0xf1, 0xb0,
- 0x8d, 0x9e, 0xe7, 0xf3, 0x4d, 0x2b, 0x6d, 0x8e },
{ 0xa0, 0xc2, 0xd2, 0x07, 0xa4, 0x7e, 0x18, 0xd0,
0x37, 0x14, 0xd5, 0xb3, 0x44, 0x5d, 0x88, 0xbe,
0x81, 0xff, 0x5e, 0x1d, 0x16, 0x07, 0x3d, 0xc1,
@@ -2070,26 +1682,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x12, 0x0b, 0xd2, 0x57, 0x94, 0xf8, 0xca, 0x20,
0xb0, 0x94, 0x3f, 0xbd, 0x13, 0x6e, 0x4b, 0x36,
0x77, 0x30, 0xf0, 0x5e, 0x71, 0x21, 0xf8, 0x97 },
- { 0xa5, 0x60, 0x81, 0x15, 0x27, 0xb1, 0xfc, 0x3e,
- 0x25, 0xaf, 0x12, 0xc6, 0x10, 0xd3, 0x58, 0x18,
- 0x43, 0x32, 0x10, 0xd3, 0x15, 0x27, 0x56, 0x45,
- 0x67, 0xdb, 0x9f, 0xf1, 0xa2, 0xed, 0x66, 0x90 },
- { 0xa5, 0x61, 0x59, 0x83, 0x9a, 0x9e, 0x88, 0xa6,
- 0x18, 0xed, 0xb3, 0xce, 0x3b, 0x8f, 0x16, 0x52,
- 0x35, 0x22, 0xaf, 0x8b, 0x0c, 0x53, 0xee, 0x1e,
- 0xa0, 0x85, 0x38, 0xb8, 0x88, 0x29, 0xc9, 0x2d },
{ 0xa5, 0x67, 0x98, 0x6c, 0xe0, 0xe3, 0x36, 0xf8,
0x4f, 0xdc, 0x08, 0x15, 0xb8, 0x6e, 0xa3, 0x03,
0x34, 0x3c, 0xf8, 0xc1, 0x0f, 0x37, 0x27, 0x83,
0x27, 0x14, 0x86, 0xb9, 0xc9, 0x3b, 0x63, 0x67 },
- { 0xa6, 0x21, 0xae, 0x36, 0x54, 0xac, 0xfd, 0x17,
- 0x23, 0x30, 0x70, 0xe9, 0xb1, 0x8d, 0xfd, 0x91,
- 0x6a, 0x55, 0x2e, 0x6a, 0x8b, 0x82, 0x42, 0xbd,
- 0x57, 0xbb, 0xcd, 0xf4, 0xe6, 0x5e, 0x99, 0x76 },
- { 0xa6, 0x33, 0x5d, 0xf3, 0xab, 0xa5, 0xea, 0xdf,
- 0xbd, 0xc9, 0xc2, 0xdc, 0x9d, 0x6b, 0xe6, 0x0b,
- 0xb6, 0x2d, 0xf2, 0xfe, 0x24, 0xec, 0x7b, 0xa7,
- 0x67, 0xbe, 0x65, 0xd3, 0x7f, 0x3c, 0x90, 0xf8 },
{ 0xa6, 0x62, 0xfc, 0x81, 0xc9, 0x09, 0x34, 0xb9,
0xb4, 0xd6, 0x30, 0xb5, 0xd8, 0x2e, 0x86, 0xf2,
0x36, 0x3e, 0xc1, 0x5c, 0xcf, 0xcd, 0xaf, 0xa7,
@@ -2098,10 +1694,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0xb6, 0xda, 0xd4, 0x51, 0x5b, 0x1c, 0xfc,
- 0x70, 0x37, 0x1c, 0xfc, 0xfc, 0x32, 0x30, 0x71,
- 0x0e, 0x30, 0xef, 0xe4, 0x0f, 0x95, 0xd5, 0x20,
- 0xaf, 0xc8, 0x65, 0x31, 0xe8, 0xc8, 0xf8, 0x41 },
{ 0xa6, 0xde, 0x6c, 0x3b, 0x8c, 0x14, 0x05, 0xcb,
0xe1, 0x2d, 0xb4, 0x09, 0x97, 0x61, 0x71, 0xac,
0xb5, 0x1f, 0xb3, 0xdc, 0xfb, 0xb7, 0x6e, 0xe3,
@@ -2118,10 +1710,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x6a, 0x7a, 0x48, 0x94, 0x3c, 0xbd, 0x2d, 0x99,
0x0e, 0x40, 0xfa, 0xa6, 0xd8, 0x56, 0x87, 0x7f,
0x45, 0x5b, 0xf0, 0x15, 0xf5, 0x45, 0x11, 0x3c },
- { 0xa7, 0x36, 0xb1, 0x97, 0xe6, 0xfb, 0x3b, 0x62,
- 0x32, 0xed, 0xb3, 0xc8, 0xd6, 0x8c, 0xe1, 0x35,
- 0x1a, 0x48, 0xb5, 0x6f, 0x70, 0x11, 0xbb, 0x99,
- 0x20, 0xcf, 0xca, 0x75, 0x7e, 0x57, 0xc6, 0xc4 },
{ 0xa8, 0x53, 0xad, 0xc1, 0xc2, 0x18, 0x59, 0xaf,
0x7c, 0x46, 0x2b, 0x4a, 0xa0, 0xa5, 0x74, 0xca,
0x9f, 0xee, 0xfb, 0x18, 0x5a, 0x1f, 0xdb, 0xb6,
@@ -2146,10 +1734,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xa5, 0x7d, 0xc1, 0xf0, 0xf8, 0x6d, 0xe1, 0x07,
0xb5, 0xe2, 0xf0, 0x36, 0x09, 0x53, 0xf1, 0xed,
0x12, 0x5e, 0x37, 0x07, 0x59, 0x47, 0x1d, 0x09 },
- { 0xa9, 0x94, 0xc9, 0x09, 0x10, 0x60, 0x9a, 0xf5,
- 0x0a, 0x4c, 0x09, 0x22, 0x97, 0xc9, 0xb4, 0xc7,
- 0xf1, 0x03, 0x96, 0xaf, 0x73, 0x95, 0xe9, 0xe1,
- 0xbf, 0xb8, 0x99, 0x53, 0xfa, 0x15, 0x25, 0x9b },
{ 0xaa, 0x0e, 0x12, 0x52, 0x43, 0x6d, 0xef, 0x79,
0x07, 0xfb, 0x99, 0xf7, 0x64, 0x15, 0x50, 0xd8,
0x0f, 0xaf, 0xfb, 0xf3, 0x01, 0x71, 0x1c, 0x7b,
@@ -2186,10 +1770,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xc1, 0x40, 0x30, 0xdb, 0xce, 0xdd, 0x63, 0xd1,
0xd1, 0x7c, 0x33, 0x8e, 0xbd, 0x1d, 0x7d, 0xe5,
0x6c, 0x79, 0xd2, 0x1a, 0x6f, 0x2e, 0x47, 0xa7 },
- { 0xad, 0x4b, 0x2f, 0x8e, 0xf2, 0xde, 0xfb, 0x01,
- 0x92, 0x3c, 0x9c, 0x0f, 0xe2, 0x5a, 0x9a, 0xce,
- 0x41, 0xfa, 0x9e, 0x69, 0x75, 0x85, 0xfc, 0x3d,
- 0xdf, 0x8d, 0x34, 0xe7, 0x45, 0xff, 0x0f, 0x12 },
{ 0xad, 0x69, 0x54, 0x5f, 0x9f, 0x85, 0x25, 0x5f,
0xe4, 0x16, 0x51, 0x3d, 0x94, 0xdb, 0x31, 0x50,
0x5f, 0x38, 0x4b, 0x52, 0x3c, 0x2c, 0xa2, 0x6e,
@@ -2198,10 +1778,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xe8, 0x54, 0xb5, 0x15, 0x50, 0xea, 0x44, 0x4f,
0xa3, 0xb8, 0xbb, 0x50, 0xae, 0x93, 0x74, 0x01,
0x3c, 0xfe, 0xf3, 0x88, 0x73, 0x5d, 0x0b, 0xd3 },
- { 0xae, 0x2f, 0x15, 0xea, 0x4a, 0xa5, 0x39, 0x81,
- 0x41, 0x0f, 0x98, 0x93, 0x81, 0xa4, 0x41, 0x5a,
- 0xf1, 0x84, 0x3d, 0x19, 0xe4, 0x39, 0x07, 0xaf,
- 0x53, 0xb2, 0x0f, 0x7f, 0xa7, 0x73, 0x2a, 0x93 },
{ 0xae, 0x4d, 0xf3, 0x97, 0x9b, 0x74, 0x27, 0x34,
0xa3, 0x39, 0xc4, 0x70, 0x1d, 0x5e, 0x13, 0x21,
0x26, 0x3f, 0xf4, 0x4e, 0x67, 0x56, 0x49, 0x05,
@@ -2218,10 +1794,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x41, 0x81, 0xd8, 0x6a, 0x7e, 0x8f, 0x07, 0x69,
0xb6, 0x1d, 0x46, 0xd7, 0xb6, 0xfa, 0xc6, 0xe6,
0xf9, 0x59, 0x6d, 0xe9, 0x4a, 0xa8, 0xe2, 0xe8 },
- { 0xaf, 0xe7, 0xb8, 0xee, 0xfd, 0xf5, 0x4e, 0x7f,
- 0x1c, 0x5a, 0x6b, 0xed, 0xf7, 0x54, 0xce, 0x97,
- 0x0f, 0xa1, 0x19, 0x59, 0xe7, 0x80, 0x38, 0xcc,
- 0x36, 0x8a, 0xc7, 0x78, 0xb7, 0x5c, 0x92, 0x4b },
{ 0xb0, 0x1e, 0xb1, 0x82, 0x68, 0x1a, 0xa9, 0x5d,
0x7b, 0xea, 0xaf, 0x53, 0xba, 0x75, 0x5b, 0x7f,
0x3d, 0x0f, 0xb7, 0x97, 0x76, 0xd5, 0x62, 0xb9,
@@ -2230,38 +1802,14 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x62, 0x43, 0x51, 0xfd, 0x68, 0x51, 0x23,
- 0x01, 0x38, 0x56, 0xec, 0x40, 0x63, 0x25, 0xfc,
- 0xcb, 0x16, 0x45, 0x76, 0x50, 0xa8, 0x71, 0xf5,
- 0xfb, 0x91, 0x5d, 0xdd, 0x75, 0x4a, 0x3b, 0xc9 },
- { 0xb0, 0xb6, 0x32, 0x1c, 0x45, 0x9b, 0xdb, 0x78,
- 0x91, 0x8e, 0xc3, 0x16, 0xbd, 0x36, 0xec, 0x5f,
- 0x30, 0x55, 0x8e, 0xe0, 0x2e, 0xcc, 0x51, 0xe3,
- 0x77, 0xc5, 0xf8, 0xab, 0xa4, 0x1d, 0xba, 0x6d },
{ 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 },
- { 0xb1, 0x61, 0xd6, 0x09, 0x5b, 0x6e, 0x9b, 0x1d,
- 0xb5, 0x16, 0xda, 0x1c, 0x2d, 0xef, 0x9c, 0xe9,
- 0x11, 0xc7, 0xa5, 0xbb, 0x55, 0xef, 0xf5, 0x05,
- 0x66, 0xd5, 0xd1, 0xe0, 0xdc, 0x4f, 0x45, 0xcd },
- { 0xb1, 0x91, 0x9d, 0x6c, 0xfa, 0xc2, 0x0d, 0x03,
- 0x47, 0x76, 0x87, 0x1a, 0xb0, 0xa2, 0x57, 0x8a,
- 0xc0, 0xb2, 0xdd, 0xb6, 0x8b, 0xe1, 0xdc, 0x75,
- 0x91, 0x80, 0x44, 0x1f, 0x05, 0x3a, 0x27, 0x2c },
{ 0xb1, 0x92, 0x30, 0x7c, 0xfa, 0xee, 0x42, 0x7b,
0x76, 0x7b, 0xc2, 0xf9, 0x9b, 0xc2, 0x26, 0x74,
0x26, 0x0a, 0x4e, 0x8e, 0x1e, 0x6b, 0x36, 0x19,
0x8c, 0x2f, 0x4e, 0xea, 0x67, 0xca, 0x85, 0xef },
- { 0xb1, 0xa5, 0x89, 0x8e, 0x3b, 0x0d, 0x0a, 0x7a,
- 0x80, 0x76, 0x79, 0x3d, 0x6c, 0x63, 0xa3, 0x22,
- 0xea, 0xb7, 0x1f, 0x7e, 0x28, 0x74, 0x5d, 0xef,
- 0xf5, 0xa0, 0xc3, 0x3a, 0x8e, 0xec, 0xe4, 0xfa },
- { 0xb2, 0xc6, 0xf7, 0xc6, 0x2f, 0xa5, 0x6a, 0x4e,
- 0x57, 0xb7, 0x62, 0xa8, 0x9c, 0x3c, 0x55, 0xdd,
- 0x81, 0xc1, 0x82, 0x7e, 0xdf, 0xb0, 0xd4, 0x41,
- 0x80, 0xe4, 0xfa, 0xdc, 0xeb, 0x23, 0x72, 0x73 },
{ 0xb2, 0xdc, 0x86, 0x25, 0x6c, 0xcf, 0xf4, 0xbb,
0x14, 0xfd, 0x70, 0x27, 0x9f, 0xcc, 0x3c, 0xe9,
0x25, 0xc5, 0x1f, 0xb7, 0x17, 0xe5, 0x87, 0x6f,
@@ -2274,10 +1822,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x19, 0xaf, 0x08, 0x28, 0x68, 0x1f, 0x97,
- 0x35, 0xa4, 0x8d, 0x11, 0x17, 0x39, 0xb8, 0x62,
- 0x89, 0xae, 0xf7, 0xfb, 0x81, 0x7c, 0x04, 0x7f,
- 0x12, 0x75, 0xa5, 0x87, 0xa7, 0x32, 0x2c, 0x0b },
{ 0xb3, 0x1a, 0xf0, 0xc2, 0xe5, 0x1e, 0xa2, 0x1c,
0x91, 0x04, 0xf9, 0x4f, 0xaa, 0x66, 0xe0, 0xcc,
0xc0, 0x41, 0x34, 0xd5, 0x80, 0x9a, 0x2a, 0x26,
@@ -2314,38 +1858,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x17, 0xf0, 0x6f, 0xe1, 0xd7, 0xac, 0x9c, 0x62,
0x33, 0xd4, 0x38, 0x22, 0xe9, 0xfd, 0x14, 0xdb,
0x98, 0xf7, 0xf8, 0x4e, 0x32, 0x79, 0x6d, 0x08 },
- { 0xb4, 0xf1, 0xef, 0x4a, 0xa5, 0x1f, 0x02, 0x1e,
- 0xd2, 0x66, 0x26, 0x44, 0xce, 0xda, 0x31, 0x1d,
- 0x86, 0xf5, 0x64, 0x0d, 0xaf, 0xe9, 0xa4, 0x39,
- 0x18, 0x89, 0x37, 0xd8, 0x09, 0x13, 0x90, 0x75 },
- { 0xb5, 0x25, 0x36, 0x2f, 0x68, 0x54, 0x4a, 0xc1,
- 0x8c, 0x2f, 0x5c, 0x19, 0x51, 0x47, 0x94, 0x40,
- 0x45, 0x8c, 0x59, 0xd7, 0xbb, 0x00, 0x5f, 0x19,
- 0x91, 0x17, 0x51, 0xb4, 0xd3, 0x97, 0x1d, 0x5c },
- { 0xb5, 0xb8, 0xd0, 0x08, 0x69, 0xdd, 0x78, 0x64,
- 0x9d, 0xab, 0xd4, 0x41, 0x14, 0x08, 0xa8, 0xff,
- 0x1a, 0xc5, 0x43, 0xec, 0xa8, 0x80, 0xae, 0xed,
- 0xb5, 0x83, 0x28, 0xed, 0xda, 0x47, 0x1b, 0xfc },
- { 0xb5, 0xe2, 0xaa, 0x4c, 0x7f, 0xa4, 0x65, 0xa9,
- 0x72, 0xaf, 0x17, 0x0e, 0x21, 0x76, 0xd1, 0x83,
- 0x51, 0xe6, 0x8d, 0x94, 0x95, 0x0d, 0x87, 0x55,
- 0x9c, 0x65, 0x20, 0x43, 0xfe, 0xcb, 0x05, 0x2d },
{ 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 },
- { 0xb6, 0x60, 0x21, 0xde, 0x5d, 0xe8, 0x81, 0x36,
- 0xbb, 0x09, 0x49, 0x1a, 0x46, 0xe0, 0xfc, 0x6b,
- 0x69, 0x33, 0x9b, 0xd9, 0xac, 0xc9, 0xa4, 0xea,
- 0x84, 0xcc, 0x76, 0x4c, 0x39, 0xf5, 0x70, 0xa3 },
- { 0xb6, 0x8d, 0x56, 0xb6, 0x8c, 0xc0, 0x99, 0xff,
- 0xde, 0xe7, 0xd5, 0x70, 0x1f, 0x1e, 0x1e, 0x97,
- 0x26, 0xdc, 0x75, 0x7c, 0x22, 0x22, 0xb0, 0xa0,
- 0x1e, 0x4a, 0x32, 0x72, 0xf8, 0xb3, 0x84, 0xf2 },
- { 0xb6, 0x90, 0x8f, 0xab, 0x0c, 0xa2, 0xd7, 0xd6,
- 0x5d, 0xca, 0x8b, 0x10, 0xd0, 0x1f, 0x08, 0x48,
- 0x13, 0x1c, 0x1c, 0x32, 0x10, 0xa2, 0x5b, 0x47,
- 0xc7, 0x9e, 0x33, 0xc4, 0xac, 0x09, 0x5f, 0x7e },
{ 0xb7, 0x06, 0xde, 0x1b, 0xd1, 0xee, 0x2f, 0x4c,
0xec, 0x6c, 0xe0, 0x92, 0x02, 0x2b, 0x49, 0x32,
0x81, 0xe2, 0x9a, 0x21, 0x73, 0x50, 0x8c, 0x9b,
@@ -2366,10 +1882,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x71, 0x0f, 0x38, 0xd0, 0xca, 0x3e, 0x01, 0xff,
0xab, 0xde, 0x0f, 0xc2, 0x48, 0x3e, 0x21, 0xb8,
0xf1, 0xa5, 0xff, 0x48, 0x3b, 0x2d, 0x60, 0xce },
- { 0xb9, 0x42, 0x94, 0x19, 0xf2, 0x9f, 0xe3, 0x5c,
- 0xd8, 0xcf, 0x94, 0x92, 0xd5, 0xa9, 0xb5, 0xd2,
- 0x24, 0x1d, 0xda, 0x4e, 0x12, 0x15, 0x6f, 0x37,
- 0x4c, 0xec, 0x78, 0x4f, 0x44, 0x5b, 0x43, 0xf2 },
{ 0xb9, 0x8d, 0x83, 0x38, 0x55, 0xc3, 0x67, 0x88,
0x62, 0xb6, 0x2f, 0x36, 0x50, 0xdb, 0x00, 0xa3,
0x45, 0xf4, 0x6a, 0x0e, 0x8e, 0x01, 0x1a, 0x20,
@@ -2386,10 +1898,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x0b, 0xd1, 0xe6, 0x9f, 0xf4, 0xa3, 0x89,
- 0x51, 0x61, 0x13, 0x55, 0x2c, 0x17, 0xab, 0x77,
- 0x82, 0xa7, 0xeb, 0xba, 0xea, 0x0b, 0xe3, 0x9f,
- 0x58, 0x92, 0x84, 0x1f, 0x1f, 0x74, 0xd2, 0x98 },
{ 0xbb, 0x5c, 0xb3, 0x78, 0xb7, 0xb9, 0x48, 0x7f,
0xa6, 0x1b, 0xc0, 0x91, 0x3d, 0xa1, 0xdf, 0x26,
0xa1, 0xcf, 0xef, 0xf7, 0x45, 0x2d, 0x9b, 0xa3,
@@ -2414,10 +1922,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x2a, 0xa7, 0xa7, 0x5f, 0x77, 0x63, 0xa8, 0x38,
0xcf, 0x4b, 0xa1, 0x7f, 0xb3, 0x64, 0x72, 0xba,
0x12, 0x69, 0x8c, 0x45, 0xdf, 0x88, 0xe8, 0x46 },
- { 0xbe, 0x41, 0x0a, 0x51, 0xd3, 0x44, 0x17, 0x76,
- 0x91, 0xb3, 0x42, 0x64, 0x10, 0xa4, 0x41, 0xaf,
- 0xd1, 0xc9, 0x40, 0xb1, 0xb2, 0x7c, 0xf5, 0x29,
- 0xee, 0x87, 0xa1, 0x40, 0x3b, 0xb0, 0x16, 0xf4 },
{ 0xbe, 0x68, 0x35, 0x4f, 0x7c, 0x36, 0x24, 0x2d,
0xb6, 0x20, 0x4f, 0x20, 0x13, 0x1b, 0x01, 0xff,
0x28, 0xb7, 0xdd, 0xff, 0x36, 0x2e, 0x42, 0x9b,
@@ -2426,10 +1930,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x5a, 0xf3, 0x91, 0x5a, 0x39, 0xcc, 0x2a, 0xfa,
0x9f, 0x6a, 0x8a, 0x6f, 0xbe, 0xd4, 0xfe, 0x54,
0xd9, 0xde, 0x32, 0x49, 0x23, 0xb3, 0x93, 0x5a },
- { 0xbe, 0xd5, 0xb6, 0xad, 0xe6, 0xc9, 0xc2, 0x15,
- 0xe4, 0x14, 0x53, 0x21, 0x9a, 0xf2, 0x9a, 0x8b,
- 0x8d, 0x76, 0x9d, 0x36, 0x43, 0x8c, 0x3f, 0x96,
- 0x61, 0x76, 0xe3, 0xbc, 0xc9, 0x1f, 0x2e, 0xe8 },
{ 0xbe, 0xd6, 0xf8, 0x1a, 0xd8, 0x5e, 0x71, 0x6b,
0x60, 0xd3, 0xe9, 0x7d, 0x8b, 0x90, 0x81, 0xe9,
0xc1, 0xb9, 0xec, 0x3b, 0xe8, 0xf3, 0xfd, 0x5b,
@@ -2510,10 +2010,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xbd, 0x47, 0x59, 0x1d, 0x93, 0x04, 0x71, 0xe6,
0x17, 0x4c, 0x93, 0x85, 0xf5, 0xdc, 0x32, 0xb7,
0x62, 0x31, 0x65, 0x5f, 0xc8, 0x5e, 0x22, 0xe2 },
- { 0xc2, 0xe8, 0x7a, 0xf9, 0xfe, 0x26, 0x55, 0x64,
- 0xe1, 0x09, 0xa3, 0x9d, 0x73, 0xbc, 0xd4, 0x7a,
- 0x4e, 0x98, 0x75, 0x6f, 0x76, 0xeb, 0xdf, 0xb7,
- 0xa6, 0x57, 0x0a, 0xda, 0xb9, 0xdd, 0xdd, 0xfb },
{ 0xc3, 0x79, 0x03, 0xc5, 0x3a, 0xe6, 0x02, 0xec,
0x96, 0x9e, 0xc3, 0x3f, 0x63, 0xfe, 0x9a, 0xb2,
0x0c, 0x39, 0x5f, 0x83, 0x0d, 0x30, 0xe4, 0xee,
@@ -2542,10 +2038,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x33, 0x8c, 0xef, 0x77, 0x73, 0xc6, 0xdf, 0xca,
0x6c, 0xe4, 0xfa, 0x96, 0x41, 0xbe, 0xab, 0x38,
0x05, 0xa8, 0xef, 0xb6, 0xcd, 0xc3, 0xcf, 0x0a },
- { 0xc4, 0xf4, 0x79, 0x81, 0xf4, 0x5d, 0x90, 0x3b,
- 0x56, 0x2f, 0x39, 0xf6, 0x17, 0x45, 0xf4, 0xe1,
- 0x90, 0x48, 0x1c, 0x4b, 0x56, 0xa4, 0xbd, 0xf5,
- 0xa0, 0xe1, 0x61, 0xe3, 0xe9, 0x42, 0x83, 0x89 },
{ 0xc5, 0x00, 0xb8, 0x3f, 0x3e, 0x06, 0x6c, 0xd1,
0xdd, 0x0e, 0xbc, 0xd7, 0x3d, 0xd4, 0x01, 0x61,
0xb9, 0x25, 0x9a, 0xa7, 0x7a, 0xb8, 0xa6, 0x47,
@@ -2562,14 +2054,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x41, 0x82, 0xd6, 0x05, 0xc1, 0xcb, 0xe1,
- 0x9b, 0xd3, 0xb7, 0xfe, 0x55, 0x7f, 0x58, 0xcd,
- 0x52, 0x10, 0x30, 0x97, 0xa3, 0x3b, 0xf8, 0x4a,
- 0xf2, 0x22, 0xc8, 0xce, 0x72, 0x52, 0x61, 0x15 },
- { 0xc6, 0x67, 0x05, 0xfc, 0xa8, 0x55, 0x10, 0xfd,
- 0x14, 0x58, 0xe2, 0xf4, 0x51, 0xd4, 0x54, 0x43,
- 0x55, 0xd0, 0xb1, 0x03, 0xfe, 0x6d, 0xb4, 0x73,
- 0x78, 0xe7, 0x28, 0x37, 0xed, 0x9a, 0x2e, 0x6f },
{ 0xc6, 0x89, 0xb9, 0x95, 0x6c, 0x73, 0x11, 0xd7,
0x34, 0x6a, 0x7f, 0xa3, 0x8b, 0x2c, 0xcd, 0xe3,
0xef, 0xee, 0x85, 0x3d, 0x7c, 0x2c, 0x41, 0x4f,
@@ -2582,10 +2066,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x2d, 0x31, 0xfb, 0xc1, 0x06, 0x16, 0xbf, 0x1c,
0xa2, 0xfb, 0x5b, 0x02, 0xe8, 0x46, 0xb5, 0x9e,
0x63, 0x34, 0x6b, 0x31, 0x92, 0xa7, 0x52, 0x92 },
- { 0xc6, 0xc6, 0xb0, 0x9a, 0xfa, 0x64, 0x6e, 0x4e,
- 0x1d, 0x75, 0xc9, 0x23, 0xae, 0xb0, 0x2b, 0x39,
- 0xf8, 0xf0, 0x7a, 0x74, 0x33, 0x59, 0xdd, 0x22,
- 0xb4, 0xb5, 0x32, 0x41, 0xb7, 0xb0, 0x3d, 0x63 },
{ 0xc7, 0x01, 0x83, 0x64, 0x38, 0xf3, 0x7b, 0xea,
0x8a, 0x88, 0x16, 0x10, 0x63, 0x70, 0x86, 0xf8,
0x8d, 0x9a, 0x11, 0x5e, 0x00, 0x92, 0x46, 0xd2,
@@ -2606,10 +2086,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x42, 0xed, 0x3c, 0x79, 0xbe, 0xd9, 0x44, 0x1e,
0x92, 0x50, 0xbd, 0x05, 0x20, 0x25, 0xad, 0x8a,
0xf4, 0x40, 0x41, 0xac, 0x19, 0xef, 0xbb, 0x4c },
- { 0xc8, 0xc6, 0x92, 0x81, 0xbe, 0x05, 0xc4, 0x14,
- 0xea, 0xa3, 0x1c, 0x61, 0xb6, 0x52, 0x93, 0xbe,
- 0x72, 0xb5, 0x89, 0xd1, 0xd5, 0xe4, 0xb7, 0x59,
- 0xd5, 0xed, 0xaf, 0x54, 0x63, 0x99, 0xa2, 0xef },
{ 0xc9, 0x43, 0x10, 0x03, 0xbb, 0xea, 0xb5, 0x8e,
0x35, 0x2f, 0xde, 0xb4, 0x5b, 0x7f, 0xcf, 0x15,
0xc7, 0x3f, 0x07, 0x34, 0xa0, 0x7d, 0x6c, 0xbd,
@@ -2626,18 +2102,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x6c, 0xc4, 0xba, 0x92, 0x04, 0x14, 0x20,
- 0x7a, 0xa0, 0xe0, 0xf3, 0x3f, 0x27, 0x44, 0xc3,
- 0x1a, 0x37, 0x78, 0x27, 0x50, 0x89, 0x24, 0x6e,
- 0x9e, 0x98, 0x4c, 0xb7, 0x2c, 0x58, 0x72, 0xfc },
{ 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, 0xc4, 0xbb, 0x2c, 0x3d, 0x5f, 0xc7, 0xcb,
- 0x19, 0xc5, 0x41, 0x06, 0x79, 0x59, 0xd7, 0x20,
- 0xef, 0x4c, 0xbf, 0x52, 0x98, 0x01, 0xbe, 0xe1,
- 0xc8, 0xde, 0xbf, 0x42, 0x75, 0xfc, 0x08, 0x3b },
{ 0xca, 0xdc, 0xd5, 0xae, 0x1b, 0x75, 0x6a, 0xb7,
0x41, 0xb3, 0x56, 0x9c, 0x42, 0xa5, 0x41, 0x1f,
0x09, 0x3e, 0x4e, 0x1f, 0x01, 0x2e, 0xc5, 0x79,
@@ -2674,10 +2142,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x2c, 0xf2, 0x55, 0x72, 0x57, 0x21, 0x30,
- 0x71, 0x73, 0x68, 0x19, 0xb7, 0xd2, 0x88, 0xa9,
- 0x30, 0x77, 0x2b, 0x9b, 0x78, 0x2e, 0x61, 0x60,
- 0x03, 0x8f, 0xc6, 0x7a, 0x76, 0x0d, 0x7c, 0xdc },
{ 0xce, 0x4c, 0x2f, 0x8f, 0x16, 0x46, 0x8a, 0x58,
0x88, 0xe9, 0x0f, 0x73, 0x4e, 0x4d, 0x22, 0x02,
0xdf, 0xad, 0xbf, 0xa6, 0x6f, 0x5b, 0x35, 0x75,
@@ -2694,22 +2158,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x85, 0xf5, 0xb6, 0x4e, 0x65, 0x22, 0x8d, 0x03,
0xfc, 0x77, 0x93, 0xd9, 0x49, 0x42, 0xf8, 0x8a,
0x1c, 0x72, 0xbb, 0x7b, 0x61, 0x14, 0x51, 0xd5 },
- { 0xcf, 0x92, 0x77, 0xce, 0xea, 0x50, 0x1a, 0x49,
- 0x66, 0x04, 0x3e, 0xf2, 0xb0, 0xf8, 0x86, 0x2a,
- 0xc9, 0x00, 0x93, 0x89, 0x78, 0x08, 0x26, 0x22,
- 0xc5, 0x7a, 0x50, 0x07, 0xc9, 0xc6, 0x53, 0x9d },
{ 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, 0x71, 0x14, 0xb2, 0x97, 0xb2, 0x9f, 0xa2,
- 0xe0, 0xec, 0xcd, 0xf1, 0x58, 0x7c, 0x0f, 0x03,
- 0xf8, 0x81, 0x63, 0x95, 0x46, 0x1d, 0x01, 0x1c,
- 0x47, 0x7b, 0xd7, 0xfe, 0x83, 0x8a, 0x3d, 0x0b },
- { 0xd0, 0xc4, 0x74, 0xe4, 0x47, 0xe3, 0x38, 0xa5,
- 0x4d, 0x31, 0xb3, 0xa0, 0xf4, 0x47, 0x43, 0x75,
- 0x1e, 0x45, 0xcb, 0x92, 0x87, 0xa0, 0x1f, 0x2b,
- 0x0a, 0x51, 0xe6, 0x4f, 0x16, 0xc9, 0xa7, 0x5c },
{ 0xd0, 0xf5, 0x93, 0xc1, 0xa8, 0x1b, 0x1e, 0xf8,
0x51, 0x69, 0x81, 0xee, 0x56, 0xf1, 0xd5, 0x98,
0xa2, 0xa6, 0x03, 0x48, 0x8c, 0x67, 0x8c, 0x1b,
@@ -2726,10 +2178,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0xc7, 0x0a, 0x4c, 0x52, 0xfb, 0xfc, 0x7b,
- 0x4c, 0x2d, 0xfe, 0x94, 0xcb, 0x44, 0x50, 0x37,
- 0x1e, 0x72, 0x36, 0xbd, 0xbd, 0x1c, 0x81, 0x13,
- 0xff, 0x36, 0x0f, 0xa4, 0xa1, 0x58, 0x1e, 0xfc },
{ 0xd2, 0xe8, 0xa1, 0x23, 0x7a, 0x93, 0xf5, 0x78,
0xd1, 0xba, 0x8f, 0x09, 0xe4, 0xff, 0x10, 0x7b,
0x62, 0x35, 0x78, 0x85, 0x42, 0xaa, 0x61, 0x83,
@@ -2738,14 +2186,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x00, 0x13, 0x01, 0xa6, 0x32, 0xa1, 0x1d, 0x50,
0x6e, 0xa9, 0x17, 0xde, 0xed, 0xca, 0x8e, 0xd0,
0x5f, 0x9e, 0x7a, 0xf0, 0xb6, 0x08, 0x55, 0x8b },
- { 0xd3, 0xff, 0x14, 0xad, 0xd8, 0x86, 0x5f, 0xaa,
- 0x9c, 0x30, 0x3a, 0xed, 0xf9, 0x34, 0x53, 0x85,
- 0x49, 0x8d, 0x44, 0xe1, 0xcd, 0xe0, 0x45, 0x6f,
- 0x1f, 0x33, 0xb4, 0x54, 0xc3, 0x95, 0x04, 0x58 },
- { 0xd4, 0xc3, 0xfd, 0x99, 0x41, 0x39, 0x82, 0x2a,
- 0xf3, 0x4d, 0xed, 0xf2, 0xc0, 0xe6, 0x2a, 0xe5,
- 0xec, 0x67, 0x28, 0xaa, 0x6e, 0xae, 0x4b, 0x65,
- 0x8d, 0x93, 0xbd, 0xaf, 0x3e, 0x4a, 0x7c, 0x0c },
{ 0xd5, 0x04, 0x88, 0x96, 0x86, 0x07, 0x29, 0xa8,
0xfa, 0x5d, 0x23, 0x57, 0x81, 0x2b, 0xa5, 0x6c,
0xbe, 0x84, 0xc9, 0xab, 0x7d, 0x14, 0xdf, 0x47,
@@ -2770,18 +2210,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x83, 0xd0, 0x6e, 0xb9, 0x28, 0x74, 0x43,
- 0xe5, 0x01, 0xec, 0xf7, 0x1d, 0xad, 0xa6, 0x80,
- 0x35, 0x88, 0x71, 0xd1, 0x2a, 0x53, 0xfb, 0xcc,
- 0x44, 0x09, 0x2e, 0x76, 0x4e, 0xe5, 0xba, 0x08 },
{ 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, 0x0e, 0xb9, 0xb3, 0xfe, 0xad, 0xd3, 0x05,
- 0x3f, 0x5b, 0xbc, 0xd5, 0xbb, 0xde, 0x27, 0x48,
- 0xcc, 0xcf, 0xb3, 0xe4, 0x41, 0x36, 0x7c, 0xe9,
- 0x3b, 0x76, 0xcc, 0x46, 0xcc, 0xe3, 0x76, 0xc8 },
{ 0xd7, 0x2c, 0x0e, 0x02, 0xa8, 0x71, 0xa9, 0xc2,
0x86, 0x7d, 0xb5, 0x13, 0x63, 0x62, 0x56, 0x98,
0x32, 0xdc, 0x3b, 0x85, 0xaa, 0x05, 0x4a, 0x6c,
@@ -2794,30 +2226,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x4c, 0x8c, 0xef, 0xbc, 0x28, 0xf7, 0x6d, 0x93,
0x0b, 0x6c, 0x0d, 0xae, 0x09, 0xd9, 0x3d, 0x24,
0x20, 0xeb, 0x7c, 0xde, 0x20, 0x59, 0xad, 0xba },
- { 0xd8, 0x29, 0xd3, 0x8a, 0xf1, 0xc4, 0x45, 0x73,
- 0x8b, 0xd8, 0x12, 0xe2, 0x8e, 0x38, 0x26, 0xb3,
- 0x32, 0x27, 0x32, 0xab, 0xe0, 0x02, 0x32, 0x89,
- 0xfe, 0x5a, 0x9e, 0xa6, 0x15, 0xf4, 0xf8, 0x97 },
- { 0xd8, 0x32, 0x8d, 0x2f, 0xf8, 0x7e, 0xc3, 0xe9,
- 0x0b, 0x84, 0xd9, 0xa1, 0x7b, 0x1e, 0x90, 0x24,
- 0xf6, 0x27, 0xc1, 0xec, 0xc3, 0x5e, 0xc7, 0xe6,
- 0x71, 0xc1, 0x42, 0x92, 0xa7, 0xb8, 0x8b, 0x43 },
- { 0xd8, 0x7a, 0x9d, 0xf7, 0x19, 0x1e, 0x29, 0xc8,
- 0x04, 0x1e, 0x4c, 0x19, 0x3c, 0x03, 0xa8, 0xa7,
- 0x12, 0x5f, 0x16, 0x6e, 0xa6, 0xcb, 0x21, 0x1f,
- 0xff, 0x4b, 0xee, 0x45, 0x0d, 0x72, 0x58, 0x09 },
- { 0xd8, 0x83, 0xdd, 0x00, 0x1c, 0x4e, 0x5c, 0x22,
- 0x6e, 0xe2, 0xc1, 0xf1, 0x0a, 0x66, 0x6f, 0xa1,
- 0x6e, 0x5a, 0xa9, 0x12, 0x30, 0x58, 0x38, 0xed,
- 0x9c, 0xdd, 0xc1, 0x56, 0x4d, 0xc6, 0x49, 0x64 },
{ 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, 0x41, 0x01, 0xb0, 0xdf, 0x02, 0xcd, 0xfe,
- 0xea, 0xd5, 0x21, 0xd0, 0xe2, 0xcf, 0x3a, 0x69,
- 0x46, 0x1f, 0x82, 0x6b, 0xb7, 0xa4, 0xab, 0x50,
- 0xba, 0x36, 0xa3, 0xc1, 0xf8, 0x3a, 0x52, 0xc4 },
{ 0xd9, 0x65, 0xf7, 0x41, 0x62, 0x04, 0xda, 0x83,
0x1a, 0xf6, 0x6b, 0xfa, 0x8f, 0x90, 0xd1, 0x41,
0xe9, 0x93, 0xf0, 0x00, 0x21, 0x33, 0xf2, 0x8d,
@@ -2842,18 +2254,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x8e, 0x3c, 0x4d, 0x3d, 0x11, 0x84, 0x99, 0x42,
0x26, 0x17, 0x93, 0x49, 0xda, 0xf1, 0x79, 0x5b,
0x77, 0x39, 0x3e, 0x2d, 0xd9, 0x87, 0xbb, 0x43 },
- { 0xdb, 0x57, 0x78, 0x2a, 0x14, 0xe1, 0x3c, 0x3b,
- 0xe5, 0x38, 0x9a, 0x26, 0x08, 0x1c, 0x99, 0x8b,
- 0x5f, 0xfa, 0x67, 0xdd, 0x45, 0x97, 0xf8, 0xca,
- 0x67, 0xef, 0x10, 0x6a, 0xd7, 0x5f, 0x34, 0x9f },
{ 0xdb, 0xa2, 0x21, 0xc2, 0xab, 0x44, 0xb5, 0x2c,
0x0b, 0x83, 0x36, 0xc4, 0x69, 0xfa, 0xa8, 0x56,
0xd6, 0xc3, 0xec, 0xdc, 0x6c, 0x24, 0x6b, 0xe3,
0xca, 0xc7, 0xe0, 0xf6, 0x28, 0x4b, 0x5b, 0xda },
- { 0xdc, 0x90, 0x90, 0x55, 0x0c, 0x93, 0x42, 0xe2,
- 0xfa, 0xe2, 0x42, 0x26, 0xa4, 0xf9, 0xb3, 0xf6,
- 0x93, 0xf4, 0xd1, 0x46, 0x52, 0x79, 0xc3, 0x7b,
- 0x46, 0x14, 0x38, 0xf4, 0xf5, 0x3c, 0x0e, 0x0b },
{ 0xdc, 0xb2, 0x1d, 0xef, 0x3c, 0x26, 0x0b, 0x20,
0x50, 0xf3, 0x4c, 0x5f, 0x51, 0xbe, 0x30, 0x9c,
0x3c, 0x76, 0x36, 0x30, 0x6d, 0x51, 0xb9, 0xbe,
@@ -2882,22 +2286,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x12, 0x39, 0x4e, 0x73, 0xcb, 0x8c, 0x95,
- 0xc5, 0x7e, 0x49, 0x8b, 0x96, 0xff, 0x65, 0x2c,
- 0x06, 0xac, 0x62, 0xa9, 0xa8, 0xed, 0x83, 0x85,
- 0x39, 0x93, 0xdc, 0xbd, 0xeb, 0xc0, 0x16, 0xaa },
{ 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 },
- { 0xdf, 0x51, 0x6d, 0xa3, 0xc8, 0x2d, 0x2d, 0x71,
- 0x17, 0x77, 0x76, 0x59, 0xcc, 0x9d, 0xbe, 0x7c,
- 0xec, 0x22, 0x70, 0x8f, 0x22, 0x59, 0x47, 0x6f,
- 0xfc, 0x48, 0x60, 0x34, 0x94, 0xfc, 0x87, 0xd3 },
- { 0xdf, 0xfb, 0x15, 0x21, 0xaa, 0x2d, 0x83, 0x65,
- 0x9a, 0x85, 0x8e, 0x14, 0x62, 0x82, 0x43, 0xd7,
- 0x23, 0x14, 0x5e, 0xa8, 0x13, 0x77, 0xde, 0xd7,
- 0x99, 0x1a, 0x3c, 0x00, 0xa3, 0x88, 0x9b, 0xf5 },
{ 0xe0, 0x0b, 0xd7, 0x86, 0xd1, 0xf2, 0xf4, 0x46,
0xc4, 0xba, 0x83, 0x99, 0xd4, 0xd8, 0xd5, 0xa0,
0xd1, 0x98, 0x57, 0x8f, 0x42, 0x99, 0xfd, 0xfd,
@@ -2906,10 +2298,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x1a, 0x33, 0x01, 0x7a, 0x9a, 0xc2, 0x5d, 0xda,
0xfb, 0x5e, 0xa1, 0x12, 0xc9, 0x56, 0xb0, 0x02,
0xfe, 0x6c, 0x79, 0x80, 0x14, 0xaa, 0x90, 0x65 },
- { 0xe0, 0xa9, 0xd9, 0x63, 0x6e, 0xfa, 0x36, 0xa7,
- 0x72, 0xac, 0xb5, 0xd0, 0x22, 0xfc, 0xa9, 0x73,
- 0x71, 0xb4, 0x4f, 0x7b, 0x80, 0x4b, 0x03, 0x97,
- 0xfb, 0x6c, 0x37, 0x1a, 0x22, 0x5b, 0xda, 0x78 },
{ 0xe0, 0xdd, 0xe1, 0x29, 0xd2, 0x60, 0xc3, 0xda,
0xb6, 0x91, 0xd8, 0x1d, 0xab, 0xad, 0x73, 0x4c,
0x9a, 0xdc, 0x61, 0xd2, 0x0c, 0x1a, 0xe1, 0xb6,
@@ -2938,10 +2326,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xd7, 0xb0, 0xca, 0x1f, 0x89, 0xf0, 0x8e, 0x25,
0xa7, 0x95, 0xe8, 0xb6, 0x04, 0x36, 0x8b, 0xa0,
0x78, 0x69, 0x68, 0x46, 0x8c, 0x18, 0xc3, 0xf0 },
- { 0xe2, 0xde, 0x18, 0x3e, 0xae, 0x35, 0x4c, 0xcf,
- 0x68, 0xf2, 0x52, 0x56, 0x76, 0xd7, 0x26, 0x46,
- 0x06, 0x01, 0x38, 0x43, 0xac, 0xb1, 0xfb, 0xff,
- 0xa0, 0x22, 0x99, 0xa7, 0x4e, 0xa0, 0xdf, 0x62 },
{ 0xe2, 0xf3, 0x9a, 0x9d, 0x48, 0xa3, 0x22, 0x10,
0x55, 0xb3, 0xc8, 0xa3, 0xeb, 0x14, 0x39, 0xd6,
0xb8, 0x73, 0x01, 0x3e, 0xe4, 0xd0, 0x97, 0x12,
@@ -2958,18 +2342,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xb1, 0xaa, 0xfd, 0x10, 0x81, 0x27, 0xa2, 0xf0,
0xa8, 0xfb, 0x6d, 0xa8, 0x5a, 0x04, 0x14, 0xad,
0x24, 0x99, 0x47, 0xc4, 0x8d, 0x24, 0x92, 0xc5 },
- { 0xe5, 0x3c, 0x7e, 0xa6, 0xb1, 0x2d, 0x3e, 0xca,
- 0xbf, 0xb0, 0x2f, 0xe4, 0x88, 0x56, 0xe6, 0x38,
- 0xbd, 0x0c, 0x6f, 0xeb, 0x35, 0x75, 0x7c, 0x19,
- 0xae, 0xfa, 0x3d, 0x51, 0x92, 0x17, 0xe2, 0x9e },
{ 0xe5, 0xf1, 0x20, 0xb8, 0x78, 0x63, 0x43, 0x1a,
0xd8, 0x34, 0xd8, 0x47, 0x94, 0x86, 0x4a, 0x90,
0x0e, 0x39, 0x30, 0xe0, 0xce, 0xce, 0xa1, 0x4b,
0x0d, 0x31, 0x33, 0xa9, 0x87, 0x74, 0x48, 0x89 },
- { 0xe6, 0x17, 0x7c, 0x86, 0xb8, 0x35, 0x58, 0x0a,
- 0x7a, 0x09, 0x50, 0x34, 0x78, 0x98, 0xab, 0x63,
- 0xaf, 0x11, 0xec, 0x99, 0x60, 0x64, 0x45, 0x4c,
- 0x04, 0x62, 0xbe, 0x5d, 0x4e, 0xd5, 0x22, 0x48 },
{ 0xe6, 0x44, 0xd1, 0x1c, 0x37, 0x07, 0x0f, 0x89,
0x69, 0x33, 0x08, 0x17, 0x8d, 0x6b, 0xe4, 0x95,
0x94, 0x96, 0x92, 0xc1, 0xfb, 0xeb, 0x30, 0xed,
@@ -2978,10 +2354,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0xc9, 0x32, 0x43, 0x98, 0x7b, 0x3b, 0xb2,
- 0x8a, 0xb8, 0x6f, 0xdd, 0x6b, 0xf4, 0xd9, 0xa5,
- 0x94, 0xf8, 0xd5, 0xbc, 0xe3, 0xb2, 0xf6, 0xaf,
- 0x51, 0x97, 0x15, 0x53, 0x08, 0xc6, 0x03, 0x2d },
{ 0xe6, 0xe5, 0x4d, 0xe7, 0xb4, 0x97, 0x54, 0xd3,
0x57, 0xb0, 0xa8, 0xd9, 0x4a, 0x4d, 0x4f, 0x80,
0xac, 0xd1, 0x99, 0x4c, 0xcc, 0x1c, 0x99, 0x08,
@@ -3002,10 +2374,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x36, 0x37, 0x3d, 0xcd, 0x2d, 0x4b, 0x21, 0xb7,
0x6a, 0x7c, 0x06, 0x6d, 0xf5, 0x52, 0x6e, 0x88,
0x8b, 0x6e, 0xed, 0x09, 0xa9, 0xee, 0xd0, 0x62 },
- { 0xe8, 0xa6, 0x09, 0xec, 0x44, 0xf9, 0x3c, 0x12,
- 0xe0, 0x81, 0xe5, 0x94, 0x3b, 0x5e, 0xa0, 0x48,
- 0x68, 0x14, 0x48, 0x33, 0x32, 0x5d, 0xaa, 0x64,
- 0x4f, 0x3f, 0x9f, 0xb7, 0x6a, 0xa2, 0x77, 0xc8 },
{ 0xe9, 0xd4, 0x98, 0x51, 0xbf, 0x78, 0x37, 0x6d,
0x54, 0x08, 0x2d, 0x1e, 0xb8, 0x2b, 0xd2, 0xdc,
0x96, 0x82, 0x07, 0x09, 0xb7, 0x77, 0x2d, 0x3f,
@@ -3082,18 +2450,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x5f, 0x7f, 0x0f, 0x5b, 0xf8, 0x72, 0xb1, 0xac,
0x56, 0x5e, 0xc6, 0xf1, 0x9d, 0xb5, 0x17, 0xba,
0x4e, 0xd7, 0x55, 0xc4, 0x18, 0x5f, 0x69, 0xe8 },
- { 0xee, 0x35, 0x71, 0x37, 0x61, 0x52, 0x7a, 0xe4,
- 0x8e, 0x7e, 0x40, 0x94, 0xb2, 0xb9, 0x1d, 0x3d,
- 0xd2, 0x64, 0x3f, 0x38, 0xe2, 0x6d, 0x34, 0x36,
- 0x36, 0x52, 0xfe, 0x5c, 0x2b, 0xbc, 0x41, 0x6b },
{ 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, 0x6d, 0xe0, 0xc4, 0x85, 0x70, 0xbd, 0x71,
- 0x51, 0x6b, 0xf6, 0x39, 0x5d, 0xbd, 0x29, 0x33,
- 0x7c, 0xfc, 0xb7, 0xd4, 0x26, 0x64, 0x10, 0xa1,
- 0xf5, 0xda, 0x08, 0x08, 0xe0, 0x96, 0xf4, 0x55 },
{ 0xef, 0xaf, 0xca, 0x84, 0x90, 0x30, 0x7b, 0x0f,
0x62, 0x2b, 0xf4, 0x3a, 0x0e, 0xb3, 0xc5, 0x1a,
0xcb, 0xdd, 0xde, 0xdc, 0x23, 0x92, 0xf1, 0x61,
@@ -3126,22 +2486,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x97, 0xe1, 0x84, 0xea, 0x7d, 0x22, 0xf8, 0xee,
0x4a, 0x81, 0xd0, 0x56, 0x95, 0xab, 0x08, 0xd2,
0x5d, 0x4a, 0x73, 0x3b, 0x60, 0xb4, 0x70, 0xdf },
- { 0xf1, 0x4b, 0xf7, 0x41, 0x19, 0x15, 0xef, 0x83,
- 0x96, 0xcc, 0x04, 0x0a, 0x6f, 0x30, 0x12, 0xbd,
- 0x81, 0x8c, 0x11, 0x9d, 0x03, 0x98, 0xce, 0xd6,
- 0x1d, 0x80, 0x9e, 0xf9, 0x4b, 0xd8, 0x62, 0xd8 },
{ 0xf1, 0x9a, 0xe4, 0x7d, 0x93, 0x67, 0x16, 0x52,
0x78, 0xe1, 0x66, 0xed, 0x44, 0xff, 0xc3, 0x7e,
0x5b, 0x28, 0x19, 0x6c, 0x01, 0x4b, 0xf1, 0x18,
0xcf, 0xc6, 0x4e, 0xd5, 0xfa, 0x18, 0x19, 0x4d },
- { 0xf1, 0xb5, 0xf4, 0xb2, 0x1e, 0xa3, 0x2d, 0x06,
- 0x26, 0xaa, 0x5a, 0x6b, 0xf5, 0xc4, 0xde, 0x59,
- 0x1c, 0xf1, 0x65, 0x0f, 0xa8, 0x22, 0xf1, 0x34,
- 0xd9, 0x2d, 0x54, 0x8f, 0x15, 0x77, 0x73, 0xd6 },
- { 0xf2, 0x54, 0x76, 0xf3, 0xab, 0x8e, 0x5e, 0x0b,
- 0x9b, 0xb6, 0x1d, 0x4c, 0xe4, 0x50, 0x7f, 0xa3,
- 0x52, 0x93, 0xc6, 0x64, 0x15, 0xd7, 0xd1, 0x91,
- 0x9b, 0x29, 0xbb, 0x8c, 0xbf, 0xfd, 0xa5, 0x00 },
{ 0xf2, 0xb1, 0x95, 0x84, 0x6e, 0xe2, 0xb9, 0xab,
0x5f, 0x18, 0xe6, 0x80, 0x21, 0xf8, 0xdf, 0x7c,
0x0b, 0x60, 0x58, 0xde, 0xde, 0x86, 0xc5, 0xd5,
@@ -3158,22 +2506,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0x5f, 0x07, 0x09, 0x6a, 0xf4, 0xb8, 0xbe, 0xdc,
0x16, 0x3c, 0x0f, 0x6e, 0xd5, 0x34, 0x6e, 0xfc,
0x28, 0xe8, 0xcf, 0xaf, 0x84, 0x2f, 0xa5, 0xd9 },
- { 0xf3, 0x25, 0x58, 0x52, 0x53, 0xd2, 0x8e, 0x72,
- 0x02, 0x3f, 0x04, 0xda, 0x0a, 0x2c, 0xb5, 0x0f,
- 0xbd, 0x4b, 0x75, 0xc2, 0x5a, 0x3a, 0x80, 0x25,
- 0x3f, 0x70, 0x36, 0xce, 0x71, 0x74, 0x1b, 0x9b },
- { 0xf3, 0x5f, 0xe6, 0x61, 0xd1, 0x88, 0x65, 0x29,
- 0x35, 0xe2, 0xc0, 0xe5, 0x19, 0x11, 0x8f, 0x7c,
- 0x4e, 0x45, 0x7b, 0x0c, 0x65, 0xc8, 0xe1, 0x4b,
- 0xce, 0xdc, 0x7d, 0x4c, 0xc5, 0x1e, 0x81, 0xd0 },
{ 0xf4, 0x2a, 0x12, 0xa1, 0x43, 0x57, 0xc0, 0xcf,
0x12, 0x2b, 0xbd, 0x82, 0x77, 0x69, 0xfb, 0x56,
0xdb, 0xf5, 0xb6, 0xee, 0x89, 0x4f, 0x02, 0x5b,
0x9a, 0xde, 0x25, 0x88, 0xa9, 0xb5, 0x5d, 0x9b },
- { 0xf4, 0x91, 0x32, 0x07, 0xad, 0xc7, 0x68, 0xec,
- 0x7c, 0xa6, 0xb1, 0xfe, 0x03, 0xef, 0x9c, 0xf1,
- 0x0b, 0x7d, 0xb6, 0x01, 0xd7, 0xf6, 0x6c, 0x10,
- 0x2c, 0x84, 0xe4, 0x70, 0x92, 0x9e, 0xe4, 0xa1 },
{ 0xf5, 0x82, 0xf1, 0x66, 0xb8, 0x2b, 0xed, 0x47,
0xef, 0xe3, 0x66, 0x1a, 0xa8, 0x02, 0x32, 0xfa,
0x81, 0x67, 0xd2, 0xe8, 0x97, 0x96, 0xa3, 0x66,
@@ -3190,18 +2526,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xf5, 0xbf, 0x9f, 0xe7, 0x84, 0xe6, 0x31, 0xf7,
0x9a, 0xf3, 0x9c, 0xb1, 0x4f, 0x3a, 0xc5, 0x16,
0x11, 0xf6, 0xfe, 0x1d, 0x9d, 0x1e, 0x1c, 0xe9 },
- { 0xf6, 0x93, 0x79, 0x9b, 0xbd, 0xf1, 0xff, 0x89,
- 0xba, 0x48, 0xf2, 0xbf, 0xe2, 0x8f, 0x89, 0x36,
- 0x6a, 0xc3, 0xb4, 0x13, 0x54, 0x7d, 0xb8, 0x06,
- 0x0d, 0xb5, 0x07, 0xab, 0xc9, 0x42, 0x0b, 0xa8 },
- { 0xf6, 0x9d, 0x95, 0x42, 0xdb, 0x97, 0xec, 0x65,
- 0xbf, 0xf8, 0x45, 0x23, 0x0a, 0xdc, 0x76, 0xb0,
- 0x3c, 0x15, 0x91, 0x2f, 0x6f, 0x09, 0x97, 0x32,
- 0x9d, 0x5c, 0x2d, 0x14, 0xf6, 0xb2, 0x5e, 0xdf },
- { 0xf6, 0xa8, 0x1f, 0x59, 0xb1, 0x13, 0xba, 0xb9,
- 0x52, 0xd6, 0x2b, 0xda, 0xb9, 0x70, 0xc8, 0xee,
- 0xd9, 0xf7, 0x26, 0x22, 0xfa, 0x8a, 0xc6, 0xd8,
- 0x48, 0xc3, 0xe2, 0xc6, 0x14, 0x62, 0xef, 0x95 },
{ 0xf6, 0xaa, 0xef, 0x12, 0xfc, 0x25, 0x2d, 0xd9,
0xe7, 0xf7, 0x75, 0x2c, 0x2f, 0x74, 0x5d, 0x59,
0xd6, 0x37, 0x57, 0xc6, 0xcc, 0x14, 0xd2, 0x25,
@@ -3210,18 +2534,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xa5, 0xbf, 0xd9, 0x4b, 0xb5, 0x77, 0x12, 0xa4,
0x14, 0x1e, 0xb8, 0xd0, 0x92, 0xbb, 0x2d, 0x5d,
0xd1, 0x64, 0xf6, 0x74, 0xa2, 0xe5, 0xb0, 0x64 },
- { 0xf7, 0x76, 0x3b, 0xe8, 0x7e, 0x67, 0x8b, 0x31,
- 0x18, 0x66, 0x11, 0x9a, 0xd5, 0xac, 0xdf, 0x8f,
- 0xdb, 0x3b, 0xbb, 0x46, 0x5b, 0x83, 0x40, 0x61,
- 0x64, 0xac, 0x21, 0x30, 0x34, 0xe8, 0xad, 0x0e },
- { 0xf7, 0xd9, 0x10, 0xbc, 0xe2, 0xab, 0x1a, 0xca,
- 0xa6, 0x7b, 0x66, 0x3a, 0x8a, 0xdd, 0xbd, 0xa2,
- 0x93, 0xb5, 0x1c, 0xed, 0xe7, 0x86, 0x8b, 0x69,
- 0xa3, 0xce, 0xa7, 0xff, 0xd0, 0x10, 0xb3, 0xa8 },
- { 0xf8, 0x0c, 0x71, 0x5b, 0x84, 0x49, 0x5d, 0xbe,
- 0xda, 0xbf, 0xeb, 0x1b, 0x05, 0x7f, 0xa0, 0x80,
- 0x93, 0x10, 0x5d, 0x74, 0x6f, 0x8d, 0x4f, 0x10,
- 0x35, 0xd4, 0xe1, 0xd8, 0x6b, 0xe2, 0xb4, 0x80 },
{ 0xf8, 0x64, 0x44, 0x3e, 0x2f, 0x63, 0x9e, 0x7c,
0xff, 0xd2, 0x42, 0x21, 0xf6, 0x1b, 0xbf, 0xf0,
0x7c, 0xce, 0x5c, 0x61, 0xdd, 0xb1, 0x68, 0xb3,
@@ -3242,22 +2554,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xad, 0x25, 0x74, 0x25, 0xaa, 0xe7, 0x20, 0x01,
0x40, 0x05, 0xb4, 0x15, 0x91, 0x2d, 0xbb, 0x8c,
0x0b, 0xc9, 0x99, 0xaf, 0x48, 0x48, 0xcf, 0xe5 },
- { 0xf9, 0xa7, 0xdd, 0xd3, 0xff, 0x51, 0xaf, 0x30,
- 0x7f, 0x95, 0x4f, 0x7b, 0x44, 0xdb, 0xd2, 0x42,
- 0x83, 0xcf, 0x97, 0xb6, 0x25, 0xbe, 0x76, 0x6b,
- 0x43, 0x5e, 0x6c, 0x26, 0xd9, 0xcc, 0xac, 0xc3 },
{ 0xfa, 0x2a, 0x2f, 0x77, 0x8c, 0xbe, 0xf9, 0xf1,
0xb4, 0xa8, 0xfc, 0x57, 0xbf, 0x79, 0x5f, 0x1f,
0x8c, 0xf6, 0x23, 0xdb, 0x15, 0xbe, 0x65, 0x81,
0xeb, 0xa3, 0x6b, 0x2a, 0x86, 0x49, 0xd2, 0x1e },
- { 0xfa, 0x95, 0xb3, 0xf9, 0x6f, 0xc9, 0xc2, 0xd3,
- 0xa7, 0x9b, 0x05, 0x48, 0x67, 0x6c, 0x18, 0x48,
- 0x5a, 0xf1, 0x10, 0x4c, 0xca, 0x9b, 0xb6, 0xb8,
- 0xdd, 0x9b, 0x5a, 0x54, 0x3c, 0xb6, 0xc6, 0x2e },
- { 0xfb, 0x44, 0x15, 0x70, 0x4c, 0x1d, 0x61, 0x55,
- 0x10, 0x6d, 0x88, 0xf3, 0xb2, 0x0f, 0xec, 0x9f,
- 0x6e, 0x82, 0x0c, 0x82, 0x24, 0xfe, 0xe3, 0x5e,
- 0x45, 0x22, 0x85, 0x19, 0x05, 0xf3, 0x28, 0xd7 },
{ 0xfb, 0x9a, 0xf7, 0x9d, 0xea, 0x18, 0xaf, 0x62,
0x99, 0x85, 0x0e, 0x25, 0x15, 0x9b, 0x4f, 0xb2,
0x24, 0xcb, 0xb0, 0xf1, 0x4e, 0xad, 0x7e, 0x85,
@@ -3278,10 +2578,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0x2f, 0x1e, 0x84, 0x29, 0x82, 0xc9, 0x3b,
- 0x85, 0xd2, 0x79, 0xa8, 0x3d, 0xf2, 0x13, 0xc1,
- 0xa3, 0x33, 0x29, 0x7d, 0x42, 0xa3, 0x1a, 0x8c,
- 0xc7, 0x8a, 0x3f, 0x73, 0xcd, 0xf8, 0xaf, 0x9a },
{ 0xfc, 0x4d, 0x9a, 0x37, 0xe5, 0xf7, 0x32, 0x72,
0xd0, 0xa9, 0xdf, 0xcc, 0xe9, 0x03, 0x12, 0xc7,
0x52, 0xe1, 0xb5, 0x2e, 0xb6, 0x54, 0xc4, 0x2c,
@@ -3298,10 +2594,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
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, 0xe5, 0x47, 0xe1, 0x43, 0x54, 0x87, 0x7f,
- 0xed, 0x93, 0x0b, 0x19, 0xfd, 0xe7, 0xc6, 0xf9,
- 0xcb, 0xf5, 0xd4, 0xb5, 0x7b, 0xa5, 0x34, 0x4a,
- 0x0d, 0x40, 0x10, 0xff, 0x70, 0x5a, 0x03, 0xde },
{ 0xfc, 0xe7, 0x34, 0xe1, 0x2b, 0x8e, 0xfb, 0x43,
0x12, 0x71, 0xbf, 0xf6, 0x7a, 0x7a, 0x0a, 0x93,
0xb2, 0x19, 0xdd, 0x5e, 0x5d, 0xcc, 0x12, 0x58,
@@ -3310,14 +2602,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xa4, 0x86, 0x15, 0xe4, 0x44, 0xce, 0xd6, 0x90,
0xfa, 0x60, 0xeb, 0xfd, 0x0a, 0x06, 0x0a, 0x49,
0x93, 0x89, 0x98, 0x8a, 0x2c, 0x2c, 0x05, 0xce },
- { 0xfd, 0x44, 0x89, 0xf0, 0x27, 0x27, 0xdb, 0x36,
- 0xc1, 0x84, 0x35, 0xe5, 0xc4, 0xa9, 0xf8, 0x63,
- 0xac, 0xd8, 0x04, 0xae, 0x1b, 0x39, 0x7f, 0xbb,
- 0x83, 0xd4, 0x27, 0x5a, 0xf5, 0x6d, 0xf8, 0x9f },
- { 0xfd, 0x85, 0xcc, 0x72, 0x1b, 0x77, 0xc4, 0x41,
- 0xc8, 0xb1, 0xf1, 0x4a, 0xde, 0x34, 0x8a, 0x3e,
- 0xc9, 0xfa, 0xa6, 0x26, 0x4a, 0x91, 0x3f, 0xb8,
- 0xd3, 0x4c, 0x98, 0x3b, 0x43, 0x60, 0xe9, 0x7b },
{ 0xfd, 0x9c, 0xfe, 0x14, 0xda, 0xd8, 0x97, 0x8c,
0x5b, 0xc8, 0x88, 0x93, 0x8f, 0x16, 0xf3, 0xb3,
0x98, 0xf7, 0x63, 0xa3, 0xad, 0xaf, 0xaa, 0x4a,
@@ -3364,34 +2648,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
0xaf, 0x3f, 0x5c, 0xf4, 0x22, 0x5a, 0x8e, 0xaf },
};
const uint8_t kCNNICEVWhitelist[][crypto::kSHA256Length] = {
- { 0x23, 0x86, 0x51, 0xab, 0x70, 0xb7, 0x11, 0xa0,
- 0x65, 0x55, 0x4e, 0x5d, 0x63, 0x6a, 0x34, 0x2c,
- 0x8a, 0x6b, 0xfe, 0x46, 0x0e, 0x4e, 0x7b, 0x4c,
- 0x9e, 0xaf, 0xb4, 0x75, 0xd5, 0x68, 0x51, 0xd8 },
- { 0x29, 0x0c, 0x79, 0x6f, 0x6d, 0x23, 0xde, 0x2a,
- 0xae, 0x80, 0x77, 0xab, 0xcc, 0xfc, 0x52, 0xee,
- 0x5c, 0x71, 0x35, 0x3f, 0x9a, 0xb6, 0xbd, 0x56,
- 0x5c, 0x6a, 0xbd, 0x26, 0x9f, 0xf5, 0xe9, 0xba },
- { 0x34, 0x9b, 0x72, 0x1d, 0x0b, 0xb9, 0xa4, 0xc4,
- 0xaa, 0x33, 0x43, 0x60, 0xa6, 0x6a, 0xc3, 0xa7,
- 0x3f, 0xa8, 0xd8, 0xd3, 0x60, 0x0d, 0x89, 0x4e,
- 0xb0, 0xc7, 0xd2, 0x84, 0x23, 0xc6, 0x78, 0x57 },
- { 0x63, 0x80, 0x65, 0xec, 0x95, 0xf1, 0xea, 0x81,
- 0xd9, 0x5b, 0xa4, 0xdb, 0x9e, 0xa9, 0xa2, 0xef,
- 0xe2, 0xd6, 0xcd, 0x78, 0x75, 0x88, 0x67, 0x04,
- 0x5c, 0x06, 0xb6, 0x48, 0xa5, 0xda, 0x89, 0xb2 },
- { 0x80, 0xf3, 0xeb, 0x58, 0xea, 0x6a, 0xa2, 0x85,
- 0x11, 0xb0, 0x9b, 0x68, 0xf2, 0xde, 0xf9, 0xb4,
- 0xaf, 0xa9, 0x9c, 0x97, 0x44, 0xc0, 0xbe, 0x4e,
- 0x23, 0x94, 0x89, 0xf0, 0x4f, 0x75, 0xa3, 0xa5 },
- { 0x82, 0x33, 0xde, 0x42, 0x18, 0xe4, 0xef, 0x19,
- 0x38, 0xe6, 0xa8, 0xa3, 0x8a, 0xb0, 0xbc, 0x1a,
- 0x96, 0x4b, 0xa5, 0x76, 0x1a, 0x52, 0x99, 0x50,
- 0x22, 0x15, 0x0c, 0x86, 0x02, 0x6b, 0x90, 0xc9 },
- { 0x8c, 0xcd, 0x79, 0x41, 0x63, 0x00, 0xca, 0x61,
- 0xee, 0x56, 0xa6, 0x0d, 0xa1, 0xc8, 0x09, 0x35,
- 0xb8, 0x6e, 0x27, 0x91, 0x93, 0xad, 0x3d, 0x05,
- 0x65, 0x72, 0x9d, 0x69, 0xe0, 0x8c, 0x86, 0x96 },
{ 0x9f, 0xfa, 0x4e, 0xf4, 0xfc, 0xf2, 0xcf, 0xd1,
0xb2, 0x7c, 0x6a, 0x62, 0xe3, 0xc4, 0x23, 0x5b,
0xd8, 0x3c, 0xc5, 0xe0, 0x06, 0xe9, 0x2a, 0x55,
diff --git a/chromium/net/cert/cert_verify_proc_win.cc b/chromium/net/cert/cert_verify_proc_win.cc
index cb1db7d9b84..e485e3d2cf2 100644
--- a/chromium/net/cert/cert_verify_proc_win.cc
+++ b/chromium/net/cert/cert_verify_proc_win.cc
@@ -7,10 +7,12 @@
#include <string>
#include <vector>
+#include "base/memory/free_deleter.h"
#include "base/memory/scoped_ptr.h"
#include "base/sha1.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_local.h"
#include "crypto/capi_util.h"
#include "crypto/scoped_capi_types.h"
#include "crypto/sha2.h"
@@ -25,8 +27,6 @@
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_certificate_known_roots_win.h"
-#pragma comment(lib, "crypt32.lib")
-
#if !defined(CERT_TRUST_HAS_WEAK_SIGNATURE)
// This was introduced in Windows 8 / Windows Server 2012, but retroactively
// ported as far back as Windows XP via system update.
@@ -385,13 +385,129 @@ void GetCertPoliciesInfo(
output->reset(policies_info);
}
+// Computes the SHA-256 hash of the SPKI of |cert| and stores it in |hash|,
+// returning true. If an error occurs, returns false and leaves |hash|
+// unmodified.
+bool HashSPKI(PCCERT_CONTEXT cert, std::string* hash) {
+ base::StringPiece der_bytes(
+ reinterpret_cast<const char*>(cert->pbCertEncoded), cert->cbCertEncoded);
+
+ base::StringPiece spki;
+ if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki))
+ return false;
+
+ *hash = crypto::SHA256HashString(spki);
+ return true;
+}
+
enum CRLSetResult {
- kCRLSetOk,
+ // Indicates an error happened while attempting to determine CRLSet status.
+ // For example, if the certificate's SPKI could not be extracted.
+ kCRLSetError,
+
+ // Indicates there is no fresh information about the certificate, or if the
+ // CRLSet has expired.
+ // In the case of certificate chains, this is only returned if the leaf
+ // certificate is not covered by the CRLSet; this is because some
+ // intermediates are fully covered, but after filtering, the issuer's CRL
+ // is empty and thus omitted from the CRLSet. Since online checking is
+ // performed for EV certificates when this status is returned, this would
+ // result in needless online lookups for certificates known not-revoked.
kCRLSetUnknown,
+
+ // Indicates that the certificate (or a certificate in the chain) has been
+ // revoked.
kCRLSetRevoked,
+
+ // The certificate (or certificate chain) has no revocations.
+ kCRLSetOk,
};
-// CheckRevocationWithCRLSet attempts to check each element of |chain|
+// Determines if |subject_cert| is revoked within |crl_set|,
+// storing the SubjectPublicKeyInfo hash of |subject_cert| in
+// |*previous_hash|.
+//
+// CRLSets store revocations by both SPKI and by the tuple of Issuer SPKI
+// Hash & Serial. While |subject_cert| contains enough information to check
+// for SPKI revocations, to determine the issuer's SPKI, either |issuer_cert|
+// must be supplied, or the hash of the issuer's SPKI provided in
+// |*previous_hash|. If |issuer_cert| is omitted, and |*previous_hash| is empty,
+// only SPKI checks are performed.
+//
+// To avoid recomputing SPKI hashes, the hash of |subject_cert| is stored in
+// |*previous_hash|. This allows chaining revocation checking, by starting
+// at the root and iterating to the leaf, supplying |previous_hash| each time.
+//
+// In the event of a parsing error, |*previous_hash| is cleared, to prevent the
+// wrong Issuer&Serial tuple from being used.
+CRLSetResult CheckRevocationWithCRLSet(CRLSet* crl_set,
+ PCCERT_CONTEXT subject_cert,
+ PCCERT_CONTEXT issuer_cert,
+ std::string* previous_hash) {
+ DCHECK(crl_set);
+ DCHECK(subject_cert);
+
+ // Check to see if |subject_cert|'s SPKI is revoked. The actual revocation
+ // is handled by the SHA-256 hash of the SPKI, so compute that.
+ std::string subject_hash;
+ if (!HashSPKI(subject_cert, &subject_hash)) {
+ NOTREACHED(); // Indicates Windows accepted something irrecoverably bad.
+ previous_hash->clear();
+ return kCRLSetError;
+ }
+
+ CRLSet::Result result = crl_set->CheckSPKI(subject_hash);
+ if (result == CRLSet::REVOKED)
+ return kCRLSetRevoked;
+
+ // If no issuer cert is provided, nor a hash of the issuer's SPKI, no
+ // further checks can be done.
+ if (!issuer_cert && previous_hash->empty()) {
+ previous_hash->swap(subject_hash);
+ return kCRLSetUnknown;
+ }
+
+ // Compute the subject's serial.
+ const CRYPT_INTEGER_BLOB* serial_blob =
+ &subject_cert->pCertInfo->SerialNumber;
+ scoped_ptr<uint8_t[]> serial_bytes(new uint8_t[serial_blob->cbData]);
+ // The bytes of the serial number are stored little-endian.
+ // Note: While MSDN implies that bytes are stripped from this serial,
+ // they are not - only CertCompareIntegerBlob actually removes bytes.
+ for (DWORD j = 0; j < serial_blob->cbData; j++)
+ serial_bytes[j] = serial_blob->pbData[serial_blob->cbData - j - 1];
+ base::StringPiece serial(reinterpret_cast<const char*>(serial_bytes.get()),
+ serial_blob->cbData);
+
+ // Compute the issuer's hash. If it was provided (via previous_hash),
+ // use that; otherwise, compute it based on |issuer_cert|.
+ std::string issuer_hash_local;
+ std::string* issuer_hash = previous_hash;
+ if (issuer_hash->empty()) {
+ if (!HashSPKI(issuer_cert, &issuer_hash_local)) {
+ NOTREACHED(); // Indicates Windows accepted something irrecoverably bad.
+ previous_hash->clear();
+ return kCRLSetError;
+ }
+ issuer_hash = &issuer_hash_local;
+ }
+
+ // Look up by serial & issuer SPKI.
+ result = crl_set->CheckSerial(serial, *issuer_hash);
+ if (result == CRLSet::REVOKED)
+ return kCRLSetRevoked;
+
+ previous_hash->swap(subject_hash);
+ if (result == CRLSet::GOOD)
+ return kCRLSetOk;
+ if (result == CRLSet::UNKNOWN)
+ return kCRLSetUnknown;
+
+ NOTREACHED();
+ return kCRLSetError;
+}
+
+// CheckChainRevocationWithCRLSet attempts to check each element of |chain|
// against |crl_set|. It returns:
// kCRLSetRevoked: if any element of the chain is known to have been revoked.
// kCRLSetUnknown: if there is no fresh information about the leaf
@@ -403,79 +519,29 @@ enum CRLSetResult {
// that some EV sites would otherwise take the hit of an OCSP lookup for
// no reason.
// kCRLSetOk: otherwise.
-CRLSetResult CheckRevocationWithCRLSet(PCCERT_CHAIN_CONTEXT chain,
- CRLSet* crl_set) {
- if (chain->cChain == 0)
- return kCRLSetOk;
-
- const PCERT_SIMPLE_CHAIN first_chain = chain->rgpChain[0];
- const PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement;
-
- const int num_elements = first_chain->cElement;
- if (num_elements == 0)
+CRLSetResult CheckChainRevocationWithCRLSet(PCCERT_CHAIN_CONTEXT chain,
+ CRLSet* crl_set) {
+ if (chain->cChain == 0 || chain->rgpChain[0]->cElement == 0)
return kCRLSetOk;
- // error is set to true if any errors are found. It causes such chains to be
- // considered as not covered.
- bool error = false;
- // last_covered is set to the coverage state of the previous certificate. The
- // certificates are iterated over backwards thus, after the iteration,
- // |last_covered| contains the coverage state of the leaf certificate.
- bool last_covered = false;
+ PCERT_CHAIN_ELEMENT* elements = chain->rgpChain[0]->rgpElement;
+ DWORD num_elements = chain->rgpChain[0]->cElement;
- // We iterate from the root certificate down to the leaf, keeping track of
- // the issuer's SPKI at each step.
+ bool had_error = false;
+ CRLSetResult result = kCRLSetError;
std::string issuer_spki_hash;
- for (int i = num_elements - 1; i >= 0; i--) {
- PCCERT_CONTEXT cert = element[i]->pCertContext;
-
- base::StringPiece der_bytes(
- reinterpret_cast<const char*>(cert->pbCertEncoded),
- cert->cbCertEncoded);
-
- base::StringPiece spki;
- if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki)) {
- NOTREACHED();
- error = true;
- continue;
- }
-
- const std::string spki_hash = crypto::SHA256HashString(spki);
-
- const CRYPT_INTEGER_BLOB* serial_blob = &cert->pCertInfo->SerialNumber;
- scoped_ptr<uint8_t[]> serial_bytes(new uint8_t[serial_blob->cbData]);
- // The bytes of the serial number are stored little-endian.
- for (unsigned j = 0; j < serial_blob->cbData; j++)
- serial_bytes[j] = serial_blob->pbData[serial_blob->cbData - j - 1];
- base::StringPiece serial(reinterpret_cast<const char*>(serial_bytes.get()),
- serial_blob->cbData);
-
- CRLSet::Result result = crl_set->CheckSPKI(spki_hash);
-
- if (result != CRLSet::REVOKED && !issuer_spki_hash.empty())
- result = crl_set->CheckSerial(serial, issuer_spki_hash);
-
- issuer_spki_hash = spki_hash;
-
- switch (result) {
- case CRLSet::REVOKED:
- return kCRLSetRevoked;
- case CRLSet::UNKNOWN:
- last_covered = false;
- continue;
- case CRLSet::GOOD:
- last_covered = true;
- continue;
- default:
- NOTREACHED();
- error = true;
- continue;
- }
+ for (DWORD i = 0; i < num_elements; ++i) {
+ PCCERT_CONTEXT subject = elements[num_elements - i - 1]->pCertContext;
+ result =
+ CheckRevocationWithCRLSet(crl_set, subject, nullptr, &issuer_spki_hash);
+ if (result == kCRLSetRevoked)
+ return result;
+ if (result == kCRLSetError)
+ had_error = true;
}
-
- if (error || !last_covered || crl_set->IsExpired())
+ if (had_error || crl_set->IsExpired())
return kCRLSetUnknown;
- return kCRLSetOk;
+ return result;
}
void AppendPublicKeyHashes(PCCERT_CHAIN_CONTEXT chain,
@@ -551,6 +617,243 @@ bool CheckEV(PCCERT_CHAIN_CONTEXT chain_context,
return metadata->HasEVPolicyOID(fingerprint, policy_oid);
}
+// Custom revocation provider function that compares incoming certificates with
+// those in CRLSets. This is called BEFORE the default CRL & OCSP handling
+// is invoked (which is handled by the revocation provider function
+// "CertDllVerifyRevocation" in cryptnet.dll)
+BOOL WINAPI
+CertDllVerifyRevocationWithCRLSet(DWORD encoding_type,
+ DWORD revocation_type,
+ DWORD num_contexts,
+ void* rgpvContext[],
+ DWORD flags,
+ PCERT_REVOCATION_PARA revocation_params,
+ PCERT_REVOCATION_STATUS revocation_status);
+
+// Helper class that installs the CRLSet-based Revocation Provider as the
+// default revocation provider. Because it is installed as a function address
+// (meaning only scoped to the process, and not stored in the registry), it
+// will be used before any registry-based providers, including Microsoft's
+// default provider.
+class RevocationInjector {
+ public:
+ CRLSet* GetCRLSet() { return thread_local_crlset.Get(); }
+
+ void SetCRLSet(CRLSet* crl_set) { thread_local_crlset.Set(crl_set); }
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<RevocationInjector>;
+
+ RevocationInjector() {
+ const CRYPT_OID_FUNC_ENTRY kInterceptFunction[] = {
+ {CRYPT_DEFAULT_OID, &CertDllVerifyRevocationWithCRLSet},
+ };
+ BOOL ok = CryptInstallOIDFunctionAddress(
+ NULL, X509_ASN_ENCODING, CRYPT_OID_VERIFY_REVOCATION_FUNC,
+ arraysize(kInterceptFunction), kInterceptFunction,
+ CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG);
+ DCHECK(ok);
+ }
+
+ ~RevocationInjector() {}
+
+ // As the revocation parameters passed to CertVerifyProc::VerifyInternal
+ // cannot be officially smuggled to the Revocation Provider
+ base::ThreadLocalPointer<CRLSet> thread_local_crlset;
+};
+
+// Leaky, as CertVerifyProc workers are themselves leaky.
+base::LazyInstance<RevocationInjector>::Leaky g_revocation_injector =
+ LAZY_INSTANCE_INITIALIZER;
+
+BOOL WINAPI
+CertDllVerifyRevocationWithCRLSet(DWORD encoding_type,
+ DWORD revocation_type,
+ DWORD num_contexts,
+ void* rgpvContext[],
+ DWORD flags,
+ PCERT_REVOCATION_PARA revocation_params,
+ PCERT_REVOCATION_STATUS revocation_status) {
+ PCERT_CONTEXT* cert_contexts = reinterpret_cast<PCERT_CONTEXT*>(rgpvContext);
+ // The dummy CRLSet provider never returns that something is affirmatively
+ // *un*revoked, as this would disable other revocation providers from being
+ // checked for this certificate (much like an OCSP "Good" status would).
+ // Instead, it merely indicates that insufficient information existed to
+ // determine if the certificate was revoked (in the good case), or that a cert
+ // is affirmatively revoked in the event it appears within the CRLSet.
+ // Because of this, set up some basic bookkeeping for the results.
+ CHECK(revocation_status);
+ revocation_status->dwIndex = 0;
+ revocation_status->dwError = static_cast<DWORD>(CRYPT_E_NO_REVOCATION_CHECK);
+ revocation_status->dwReason = 0;
+
+ if (num_contexts == 0 || !cert_contexts[0]) {
+ SetLastError(static_cast<DWORD>(E_INVALIDARG));
+ return FALSE;
+ }
+
+ if ((GET_CERT_ENCODING_TYPE(encoding_type) != X509_ASN_ENCODING) ||
+ revocation_type != CERT_CONTEXT_REVOCATION_TYPE) {
+ SetLastError(static_cast<DWORD>(CRYPT_E_NO_REVOCATION_CHECK));
+ return FALSE;
+ }
+
+ // No revocation checking possible if there is no associated
+ // CRLSet.
+ CRLSet* crl_set = g_revocation_injector.Get().GetCRLSet();
+ if (!crl_set)
+ return FALSE;
+
+ // |revocation_params| is an optional structure; to make life simple and avoid
+ // the need to constantly check whether or not it was supplied, create a local
+ // copy. If the caller didn't supply anything, it will be empty; otherwise,
+ // it will be (non-owning) copies of the caller's original params.
+ CERT_REVOCATION_PARA local_params;
+ memset(&local_params, 0, sizeof(local_params));
+ if (revocation_params) {
+ DWORD bytes_to_copy = std::min(revocation_params->cbSize,
+ static_cast<DWORD>(sizeof(local_params)));
+ memcpy(&local_params, revocation_params, bytes_to_copy);
+ }
+ local_params.cbSize = sizeof(local_params);
+
+ PCERT_CONTEXT subject_cert = cert_contexts[0];
+
+ if ((flags & CERT_VERIFY_REV_CHAIN_FLAG) && num_contexts > 1) {
+ // Verifying a chain; first verify from the last certificate in the
+ // chain to the first, and then leave the last certificate (which
+ // is presumably self-issued, although it may simply be a trust
+ // anchor) as the |subject_cert| in order to scan for more
+ // revocations.
+ std::string issuer_hash;
+ PCCERT_CONTEXT issuer_cert = nullptr;
+ for (DWORD i = num_contexts; i > 0; --i) {
+ subject_cert = cert_contexts[i - 1];
+ if (!subject_cert) {
+ SetLastError(static_cast<DWORD>(E_INVALIDARG));
+ return FALSE;
+ }
+ CRLSetResult result = CheckRevocationWithCRLSet(
+ crl_set, subject_cert, issuer_cert, &issuer_hash);
+ if (result == kCRLSetRevoked) {
+ revocation_status->dwIndex = i - 1;
+ revocation_status->dwError = static_cast<DWORD>(CRYPT_E_REVOKED);
+ revocation_status->dwReason = CRL_REASON_UNSPECIFIED;
+ SetLastError(revocation_status->dwError);
+ return FALSE;
+ }
+ issuer_cert = subject_cert;
+ }
+ // Verified all certificates from the trust anchor to the leaf, and none
+ // were explicitly revoked. Now do a second pass to attempt to determine
+ // the issuer for cert_contexts[num_contexts - 1], so that the
+ // Issuer SPKI+Serial can be checked for that certificate.
+ //
+ // This code intentionally ignores the flag
+ subject_cert = cert_contexts[num_contexts - 1];
+ // Reset local_params.pIssuerCert, since it would contain the issuer
+ // for cert_contexts[0].
+ local_params.pIssuerCert = nullptr;
+ // Fixup the revocation index to point to this cert (in the event it is
+ // revoked). If it isn't revoked, this will be done undone later.
+ revocation_status->dwIndex = num_contexts - 1;
+ }
+
+ // Determine the issuer cert for the incoming cert
+ ScopedPCCERT_CONTEXT issuer_cert;
+ if (local_params.pIssuerCert &&
+ CryptVerifyCertificateSignatureEx(
+ NULL, subject_cert->dwCertEncodingType,
+ CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, subject_cert,
+ CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT,
+ const_cast<PCERT_CONTEXT>(local_params.pIssuerCert), 0, nullptr)) {
+ // Caller has already supplied the issuer cert via the revocation params;
+ // just use that.
+ issuer_cert.reset(
+ CertDuplicateCertificateContext(local_params.pIssuerCert));
+ } else if (CertCompareCertificateName(subject_cert->dwCertEncodingType,
+ &subject_cert->pCertInfo->Subject,
+ &subject_cert->pCertInfo->Issuer) &&
+ CryptVerifyCertificateSignatureEx(
+ NULL, subject_cert->dwCertEncodingType,
+ CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, subject_cert,
+ CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, subject_cert, 0,
+ nullptr)) {
+ // Certificate is self-signed; use it as its own issuer.
+ issuer_cert.reset(CertDuplicateCertificateContext(subject_cert));
+ } else {
+ // Scan the caller-supplied stores first, to try and find the issuer cert.
+ for (DWORD i = 0; i < local_params.cCertStore && !issuer_cert; ++i) {
+ PCCERT_CONTEXT previous_cert = nullptr;
+ for (;;) {
+ DWORD store_search_flags = CERT_STORE_SIGNATURE_FLAG;
+ previous_cert = CertGetIssuerCertificateFromStore(
+ local_params.rgCertStore[i], subject_cert, previous_cert,
+ &store_search_flags);
+ if (!previous_cert)
+ break;
+ // If a cert is found and meets the criteria, the flag will be reset to
+ // zero. Thus NOT having the bit set is equivalent to having found a
+ // matching certificate.
+ if (!(store_search_flags & CERT_STORE_SIGNATURE_FLAG)) {
+ // No need to dupe; reference is held.
+ issuer_cert.reset(previous_cert);
+ break;
+ }
+ }
+ if (issuer_cert)
+ break;
+ if (GetLastError() == static_cast<DWORD>(CRYPT_E_SELF_SIGNED)) {
+ issuer_cert.reset(CertDuplicateCertificateContext(subject_cert));
+ break;
+ }
+ }
+
+ // At this point, the Microsoft provider opens up the "CA", "Root", and
+ // "SPC" stores to search for the issuer certificate, if not found in the
+ // caller-supplied stores. It is unclear whether that is necessary here.
+ }
+
+ if (!issuer_cert) {
+ // Rather than return CRYPT_E_NO_REVOCATION_CHECK (indicating everything
+ // is fine to try the next provider), return CRYPT_E_REVOCATION_OFFLINE.
+ // This propogates up to the caller as an error while checking revocation,
+ // which is the desired intent if there are certificates that cannot
+ // be checked.
+ revocation_status->dwIndex = 0;
+ revocation_status->dwError = static_cast<DWORD>(CRYPT_E_REVOCATION_OFFLINE);
+ SetLastError(revocation_status->dwError);
+ return FALSE;
+ }
+
+ std::string unused;
+ CRLSetResult result = CheckRevocationWithCRLSet(crl_set, subject_cert,
+ issuer_cert.get(), &unused);
+ if (result == kCRLSetRevoked) {
+ revocation_status->dwError = static_cast<DWORD>(CRYPT_E_REVOKED);
+ revocation_status->dwReason = CRL_REASON_UNSPECIFIED;
+ SetLastError(revocation_status->dwError);
+ return FALSE;
+ }
+
+ // The result is ALWAYS FALSE in order to allow the next revocation provider
+ // a chance to examine. The only difference is whether or not an error is
+ // indicated via dwError (and SetLastError()).
+ // Reset the error index so that Windows does not believe this code has
+ // examined the entire chain and found no issues until the last cert (thus
+ // skipping other revocation providers).
+ revocation_status->dwIndex = 0;
+ return FALSE;
+}
+
+class ScopedThreadLocalCRLSet {
+ public:
+ explicit ScopedThreadLocalCRLSet(CRLSet* crl_set) {
+ g_revocation_injector.Get().SetCRLSet(crl_set);
+ }
+ ~ScopedThreadLocalCRLSet() { g_revocation_injector.Get().SetCRLSet(nullptr); }
+};
+
} // namespace
CertVerifyProcWin::CertVerifyProcWin() {}
@@ -578,6 +881,10 @@ int CertVerifyProcWin::VerifyInternal(
CRLSet* crl_set,
const CertificateList& additional_trust_anchors,
CertVerifyResult* verify_result) {
+ // Ensure the Revocation Provider has been installed and configured for this
+ // CRLSet.
+ ScopedThreadLocalCRLSet thread_local_crlset(crl_set);
+
PCCERT_CONTEXT cert_handle = cert->os_cert_handle();
if (!cert_handle)
return ERR_UNEXPECTED;
@@ -621,33 +928,41 @@ int CertVerifyProcWin::VerifyInternal(
}
}
- // We can set CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS to get more chains.
- DWORD chain_flags = CERT_CHAIN_CACHE_END_CERT |
- CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
+ // Revocation checking is always enabled, in order to enable CRLSets to be
+ // evaluated as part of a revocation provider. However, when the caller did
+ // not explicitly request revocation checking (which is to say, online
+ // revocation checking), then only enable cached results. This disables OCSP
+ // and CRL fetching, but still allows the revocation provider to be called.
+ // Note: The root cert is also checked for revocation status, so that CRLSets
+ // will cover revoked SPKIs.
+ DWORD chain_flags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
bool rev_checking_enabled =
(flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED);
-
if (rev_checking_enabled) {
verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
} else {
chain_flags |= CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
}
- // For non-test scenarios, use the default HCERTCHAINENGINE, NULL, which
- // corresponds to HCCE_CURRENT_USER and is is initialized as needed by
- // crypt32. However, when testing, it is necessary to create a new
- // HCERTCHAINENGINE and use that instead. This is because each
- // HCERTCHAINENGINE maintains a cache of information about certificates
- // encountered, and each test run may modify the trust status of a
- // certificate.
+ // By default, use the default HCERTCHAINENGINE (aka HCCE_CURRENT_USER). When
+ // running tests, use a dynamic HCERTCHAINENGINE. All of the status and cache
+ // of verified certificates and chains is tied to the HCERTCHAINENGINE. As
+ // each invocation may have changed the set of known roots, invalid the cache
+ // between runs.
+ //
+ // This is not the most efficient means of doing so; it's possible to mark the
+ // Root store used by TestRootCerts as changed, via CertControlStore with the
+ // CERT_STORE_CTRL_NOTIFY_CHANGE / CERT_STORE_CTRL_RESYNC, but that's more
+ // complexity for what is test-only code.
ScopedHCERTCHAINENGINE chain_engine(NULL);
if (TestRootCerts::HasInstance())
chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine());
ScopedPCCERT_CONTEXT cert_list(cert->CreateOSCertChainForCert());
+ // Add stapled OCSP response data, which will be preferred over online checks
+ // and used when in cache-only mode.
if (!ocsp_response.empty()) {
- // Attach the OCSP response to the chain.
CRYPT_DATA_BLOB ocsp_response_blob;
ocsp_response_blob.cbData = ocsp_response.size();
ocsp_response_blob.pbData =
@@ -657,10 +972,7 @@ int CertVerifyProcWin::VerifyInternal(
CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, &ocsp_response_blob);
}
- PCCERT_CHAIN_CONTEXT chain_context;
- // IE passes a non-NULL pTime argument that specifies the current system
- // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the
- // chain_flags argument.
+ PCCERT_CHAIN_CONTEXT chain_context = nullptr;
if (!CertGetCertificateChain(
chain_engine,
cert_list.get(),
@@ -674,9 +986,13 @@ int CertVerifyProcWin::VerifyInternal(
return MapSecurityError(GetLastError());
}
+ // Perform a second check with CRLSets. Although the Revocation Provider
+ // should have prevented invalid paths from being built, the behaviour and
+ // timing of how a Revocation Provider is invoked is not well documented. This
+ // is just defense in depth.
CRLSetResult crl_set_result = kCRLSetUnknown;
if (crl_set)
- crl_set_result = CheckRevocationWithCRLSet(chain_context, crl_set);
+ crl_set_result = CheckChainRevocationWithCRLSet(chain_context, crl_set);
if (crl_set_result == kCRLSetRevoked) {
verify_result->cert_status |= CERT_STATUS_REVOKED;
diff --git a/chromium/net/cert/cert_verify_result.cc b/chromium/net/cert/cert_verify_result.cc
index 2a418938e71..7a1082e9f44 100644
--- a/chromium/net/cert/cert_verify_result.cc
+++ b/chromium/net/cert/cert_verify_result.cc
@@ -12,6 +12,8 @@ CertVerifyResult::CertVerifyResult() {
Reset();
}
+CertVerifyResult::CertVerifyResult(const CertVerifyResult& other) = default;
+
CertVerifyResult::~CertVerifyResult() {
}
diff --git a/chromium/net/cert/cert_verify_result.h b/chromium/net/cert/cert_verify_result.h
index 104fc6eec46..1cfb8fa51b3 100644
--- a/chromium/net/cert/cert_verify_result.h
+++ b/chromium/net/cert/cert_verify_result.h
@@ -20,6 +20,7 @@ class X509Certificate;
class NET_EXPORT CertVerifyResult {
public:
CertVerifyResult();
+ CertVerifyResult(const CertVerifyResult& other);
~CertVerifyResult();
void Reset();
@@ -37,7 +38,7 @@ class NET_EXPORT CertVerifyResult {
// running within the sandbox.
scoped_refptr<X509Certificate> verified_cert;
- // Bitmask of CERT_STATUS_* from net/base/cert_status_flags.h. Note that
+ // Bitmask of CERT_STATUS_* from net/cert/cert_status_flags.h. Note that
// these status flags apply to the certificate chain returned in
// |verified_cert|, rather than the originally supplied certificate
// chain.
diff --git a/chromium/net/cert/client_cert_verifier.h b/chromium/net/cert/client_cert_verifier.h
new file mode 100644
index 00000000000..8060a028ecb
--- /dev/null
+++ b/chromium/net/cert/client_cert_verifier.h
@@ -0,0 +1,42 @@
+// 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_CERT_CLIENT_CERT_VERIFIER_H_
+#define NET_CERT_CLIENT_CERT_VERIFIER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/completion_callback.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+class X509Certificate;
+
+// ClientCertVerifier represents a service for verifying certificates.
+class NET_EXPORT ClientCertVerifier {
+ public:
+ class Request {
+ public:
+ Request() {}
+
+ // Destruction of the Request cancels it.
+ virtual ~Request() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Request);
+ };
+
+ virtual ~ClientCertVerifier() {}
+
+ // Verifies the given certificate as a client certificate.
+ // Returns OK if successful or an error code upon failure.
+ virtual int Verify(X509Certificate* cert,
+ const CompletionCallback& callback,
+ scoped_ptr<Request>* out_req) = 0;
+};
+
+} // namespace net
+
+#endif // NET_CERT_CLIENT_CERT_VERIFIER_H_
diff --git a/chromium/net/cert/crl_set_storage.cc b/chromium/net/cert/crl_set_storage.cc
index 0fdbadd9a40..fe3e70abd8c 100644
--- a/chromium/net/cert/crl_set_storage.cc
+++ b/chromium/net/cert/crl_set_storage.cc
@@ -7,6 +7,7 @@
#include "base/base64.h"
#include "base/format_macros.h"
#include "base/json/json_reader.h"
+#include "base/memory/scoped_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
@@ -132,7 +133,7 @@ static base::DictionaryValue* ReadHeader(base::StringPiece* data) {
if (!header->IsType(base::Value::TYPE_DICTIONARY))
return NULL;
- return reinterpret_cast<base::DictionaryValue*>(header.release());
+ return static_cast<base::DictionaryValue*>(header.release());
}
// kCurrentFileVersion is the version of the CRLSet file format that we
@@ -292,7 +293,7 @@ static bool ReadDeltaCRL(base::StringPiece* data,
// static
bool CRLSetStorage::Parse(base::StringPiece data,
scoped_refptr<CRLSet>* out_crl_set) {
- TRACE_EVENT0("CRLSet", "Parse");
+ TRACE_EVENT0("net", "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_static.h b/chromium/net/cert/ct_known_logs_static.h
index a1e30f1fc6d..8452ece5c37 100644
--- a/chromium/net/cert/ct_known_logs_static.h
+++ b/chromium/net/cert/ct_known_logs_static.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// 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.
@@ -99,9 +99,18 @@ const CTLogInfo kCTLogList[] = {
"\x02\x03\x01\x00\x01",
294,
"Venafi log",
- "https://ctlog.api.venafi.com/"}};
+ "https://ctlog.api.venafi.com/"},
+ {"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86"
+ "\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xea\x95\x9e\x02\xff\xee\xf1"
+ "\x33\x6d\x4b\x87\xbc\xcd\xfd\x19\x17\x62\xff\x94\xd3\xd0\x59\x07\x3f"
+ "\x02\x2d\x1c\x90\xfe\xc8\x47\x30\x3b\xf1\xdd\x0d\xb8\x11\x0c\x5d\x1d"
+ "\x86\xdd\xab\xd3\x2b\x46\x66\xfb\x6e\x65\xb7\x3b\xfd\x59\x68\xac\xdf"
+ "\xa6\xf8\xce\xd2\x18\x4d",
+ 91,
+ "Symantec 'Vega' log",
+ "https://vega.ws.symantec.com/"}};
-const size_t kNumKnownCTLogs = 8;
+const size_t kNumKnownCTLogs = 9;
// The list is sorted.
const char kGoogleLogIDs[][33] = {
diff --git a/chromium/net/cert/ct_log_response_parser.cc b/chromium/net/cert/ct_log_response_parser.cc
index 628eef286be..5baf1b33534 100644
--- a/chromium/net/cert/ct_log_response_parser.cc
+++ b/chromium/net/cert/ct_log_response_parser.cc
@@ -145,9 +145,7 @@ bool FillSignedTreeHead(const base::Value& json_signed_tree_head,
signed_tree_head->version = SignedTreeHead::V1;
signed_tree_head->tree_size = parsed_sth.tree_size;
- signed_tree_head->timestamp =
- base::Time::UnixEpoch() + base::TimeDelta::FromMilliseconds(
- static_cast<int64_t>(parsed_sth.timestamp));
+ signed_tree_head->timestamp = base::Time::FromJsTime(parsed_sth.timestamp);
signed_tree_head->signature = parsed_sth.signature;
memcpy(signed_tree_head->sha256_root_hash,
parsed_sth.sha256_root_hash.c_str(),
diff --git a/chromium/net/cert/ct_log_response_parser_unittest.cc b/chromium/net/cert/ct_log_response_parser_unittest.cc
index fad759019ac..8084a283e64 100644
--- a/chromium/net/cert/ct_log_response_parser_unittest.cc
+++ b/chromium/net/cert/ct_log_response_parser_unittest.cc
@@ -8,6 +8,7 @@
#include "base/base64.h"
#include "base/json/json_reader.h"
+#include "base/memory/scoped_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/values.h"
@@ -95,6 +96,23 @@ TEST(CTLogResponseParserTest, FailsToParseIncorrectLengthRootHash) {
ASSERT_FALSE(FillSignedTreeHead(*too_short_hash_json.get(), &tree_head));
}
+TEST(CTLogResponseParserTest, ParsesJsonSTHWithLargeTimestamp) {
+ SignedTreeHead tree_head;
+
+ scoped_ptr<base::Value> large_timestamp_json =
+ ParseJson(CreateSignedTreeHeadJsonString(
+ 100, INT64_C(1) << 34, GetSampleSTHSHA256RootHash(),
+ GetSampleSTHTreeHeadSignature()));
+
+ ASSERT_TRUE(FillSignedTreeHead(*large_timestamp_json.get(), &tree_head));
+
+ base::Time expected_time =
+ base::Time::UnixEpoch() +
+ base::TimeDelta::FromMilliseconds(INT64_C(1) << 34);
+
+ EXPECT_EQ(tree_head.timestamp, expected_time);
+}
+
TEST(CTLogResponseParserTest, ParsesConsistencyProofSuccessfully) {
std::string first(32, 'a');
std::string second(32, 'b');
diff --git a/chromium/net/cert/ct_log_verifier.cc b/chromium/net/cert/ct_log_verifier.cc
index 0f70678add0..05f1b049057 100644
--- a/chromium/net/cert/ct_log_verifier.cc
+++ b/chromium/net/cert/ct_log_verifier.cc
@@ -137,7 +137,7 @@ bool CTLogVerifier::VerifyConsistencyProof(
return proof.nodes.empty();
// Implement the algorithm described in
- // https://tools.ietf.org/html/draft-ietf-trans-rfc6962-bis-11#section-9.4.2
+ // https://tools.ietf.org/html/draft-ietf-trans-rfc6962-bis-12#section-9.4.2
//
// It maintains a pair of hashes |fr| and |sr|, initialized to the same
// value. Each node in |proof| will be hashed to the left of both |fr| and
@@ -179,10 +179,7 @@ bool CTLogVerifier::VerifyConsistencyProof(
// 5. For each subsequent value "c" in the "consistency_path" array:
for (; iter != proof.nodes.end(); ++iter) {
- // The proof should end exactly when |sn| becomes zero. This check is
- // missing from the draft specification. It and the additional check below
- // ensure the proof is consistent with the tree sizes but is not necessary
- // to ensure |old_tree_hash| is a prefix of |new_tree_hash|.
+ // If "sn" is 0, stop the iteration and fail the proof verification.
if (sn == 0)
return false;
// If "LSB(fn)" is set, or if "fn" is equal to "sn", then:
@@ -210,13 +207,8 @@ bool CTLogVerifier::VerifyConsistencyProof(
// 6. After completing iterating through the "consistency_path" array as
// described above, verify that the "fr" calculated is equal to the
- // "first_hash" supplied and that the "sr" calculated is equal to the
- // "second_hash" supplied.
- //
- // The proof should also end exactly when |sn| becomes zero. This check is
- // missing from the draft specification. It and the additional check above
- // ensure the proof is consistent with the tree sizes but is not necessary to
- // ensure |old_tree_hash| is a prefix of |new_tree_hash|.
+ // "first_hash" supplied, that the "sr" calculated is equal to the
+ // "second_hash" supplied and that "sn" is 0.
return fr == old_tree_hash && sr == new_tree_hash && sn == 0;
}
diff --git a/chromium/net/cert/ct_log_verifier_openssl.cc b/chromium/net/cert/ct_log_verifier_openssl.cc
index 5fe41fd7769..88f9027cd03 100644
--- a/chromium/net/cert/ct_log_verifier_openssl.cc
+++ b/chromium/net/cert/ct_log_verifier_openssl.cc
@@ -4,8 +4,8 @@
#include "net/cert/ct_log_verifier.h"
+#include <openssl/bytestring.h>
#include <openssl/evp.h>
-#include <openssl/x509.h>
#include "base/logging.h"
#include "crypto/openssl_util.h"
@@ -50,10 +50,11 @@ CTLogVerifier::~CTLogVerifier() {
bool CTLogVerifier::Init(const base::StringPiece& public_key) {
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(public_key.data());
- const uint8_t* end = ptr + public_key.size();
- public_key_ = d2i_PUBKEY(nullptr, &ptr, public_key.size());
- if (!public_key_ || ptr != end)
+ CBS cbs;
+ CBS_init(&cbs, reinterpret_cast<const uint8_t*>(public_key.data()),
+ public_key.size());
+ public_key_ = EVP_parse_public_key(&cbs);
+ if (!public_key_ || CBS_len(&cbs) != 0)
return false;
key_id_ = crypto::SHA256HashString(public_key);
diff --git a/chromium/net/cert/ct_log_verifier_unittest.cc b/chromium/net/cert/ct_log_verifier_unittest.cc
index 3ee926353af..9221f066327 100644
--- a/chromium/net/cert/ct_log_verifier_unittest.cc
+++ b/chromium/net/cert/ct_log_verifier_unittest.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include <memory>
#include <string>
#include "base/strings/string_number_conversions.h"
@@ -409,7 +410,7 @@ class TreeHasher {
SHA256HashValue sha256;
memset(sha256.data, 0, sizeof(sha256.data));
- scoped_ptr<crypto::SecureHash> hash(
+ std::unique_ptr<crypto::SecureHash> hash(
crypto::SecureHash::Create(crypto::SecureHash::SHA256));
hash->Update(kLeafPrefix, 1);
hash->Update(leaf.data(), leaf.size());
@@ -483,11 +484,16 @@ std::vector<std::string> ReferenceSnapshotConsistency(std::string* inputs,
return proof;
}
-// "brute-force" test generating a tree of 256 entries, generating
-// a consistency proof for each snapshot of each sub-tree up to that
-// size and making sure it verifies.
+// Times out on Win7 test bot. http://crbug.com/598406
+#if defined(OS_WIN)
+#define MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator \
+ DISABLED_VerifiesValidConsistencyProofsFromReferenceGenerator
+#else
+#define MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator \
+ VerifiesValidConsistencyProofsFromReferenceGenerator
+#endif
TEST_F(CTLogVerifierTest,
- VerifiesValidConsistencyProofsFromReferenceGenerator) {
+ MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator) {
std::vector<std::string> data;
for (int i = 0; i < 256; ++i)
data.push_back(std::string(1, i));
diff --git a/chromium/net/cert/ct_objects_extractor_openssl.cc b/chromium/net/cert/ct_objects_extractor_openssl.cc
index 6fcc3b8e93b..7c878d3a8aa 100644
--- a/chromium/net/cert/ct_objects_extractor_openssl.cc
+++ b/chromium/net/cert/ct_objects_extractor_openssl.cc
@@ -232,7 +232,7 @@ bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf,
// Extract the issuer's public key.
std::string issuer_der;
if (!X509Certificate::GetDEREncoded(issuer, &issuer_der))
- return ScopedX509();
+ return false;
base::StringPiece issuer_key;
if (!asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_key))
return false;
diff --git a/chromium/net/cert/ct_policy_enforcer.cc b/chromium/net/cert/ct_policy_enforcer.cc
index d9c92421bf8..e036087c5ca 100644
--- a/chromium/net/cert/ct_policy_enforcer.cc
+++ b/chromium/net/cert/ct_policy_enforcer.cc
@@ -19,6 +19,7 @@
#include "base/version.h"
#include "net/cert/ct_ev_whitelist.h"
#include "net/cert/ct_known_logs.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verify_result.h"
#include "net/cert/signed_certificate_timestamp.h"
#include "net/cert/x509_certificate.h"
@@ -37,13 +38,9 @@ bool IsEmbeddedSCT(const scoped_refptr<ct::SignedCertificateTimestamp>& sct) {
// built-in security information (e.g. CT Logs) is fresh enough.
// TODO(eranm): Move to base or net/base
bool IsBuildTimely() {
-#if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD)
- return true;
-#else
const base::Time build_time = base::GetBuildTime();
// We consider built-in information to be timely for 10 weeks.
return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
-#endif
}
bool IsGoogleIssuedSCT(
@@ -82,11 +79,10 @@ void RoundedDownMonthDifference(const base::Time& start,
}
bool HasRequiredNumberOfSCTs(const X509Certificate& cert,
- const ct::CTVerifyResult& ct_result) {
- size_t num_valid_scts = ct_result.verified_scts.size();
+ const ct::SCTList& verified_scts) {
+ size_t num_valid_scts = verified_scts.size();
size_t num_embedded_scts = base::checked_cast<size_t>(
- std::count_if(ct_result.verified_scts.begin(),
- ct_result.verified_scts.end(), IsEmbeddedSCT));
+ std::count_if(verified_scts.begin(), verified_scts.end(), IsEmbeddedSCT));
size_t num_non_embedded_scts = num_valid_scts - num_embedded_scts;
// If at least two valid SCTs were delivered by means other than embedding
@@ -134,30 +130,37 @@ bool HasEnoughDiverseSCTs(const ct::SCTList& verified_scts) {
(verified_scts.size() != num_google_issued_scts);
}
-enum CTComplianceStatus {
- CT_NOT_COMPLIANT = 0,
- CT_IN_WHITELIST = 1,
- CT_ENOUGH_SCTS = 2,
- CT_NOT_ENOUGH_DIVERSE_SCTS = 3,
- CT_COMPLIANCE_MAX,
-};
-
-const char* ComplianceStatusToString(CTComplianceStatus status) {
+const char* EVPolicyComplianceToString(ct::EVPolicyCompliance status) {
switch (status) {
- case CT_NOT_COMPLIANT:
- return "NOT_COMPLIANT";
- break;
- case CT_IN_WHITELIST:
+ case ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY:
+ return "POLICY_DOES_NOT_APPLY";
+ case ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST:
return "WHITELISTED";
+ case ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS:
+ return "COMPLIES_VIA_SCTS";
+ case ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS:
+ return "NOT_ENOUGH_SCTS";
+ case ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS:
+ return "SCTS_NOT_DIVERSE";
+ case ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY:
+ return "BUILD_NOT_TIMELY";
+ case ct::EVPolicyCompliance::EV_POLICY_MAX:
break;
- case CT_ENOUGH_SCTS:
- return "ENOUGH_SCTS";
- break;
- case CT_NOT_ENOUGH_DIVERSE_SCTS:
- return "NOT_ENOUGH_DIVERSE_SCTS";
- break;
- case CT_COMPLIANCE_MAX:
- break;
+ }
+
+ return "unknown";
+}
+
+const char* CertPolicyComplianceToString(ct::CertPolicyCompliance status) {
+ switch (status) {
+ case ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS:
+ return "COMPLIES_VIA_SCTS";
+ case ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS:
+ return "NOT_ENOUGH_SCTS";
+ case ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS:
+ return "NOT_DIVERSE_SCTS";
+ case ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY:
+ return "BUILD_NOT_TIMELY";
}
return "unknown";
@@ -170,11 +173,13 @@ enum EVWhitelistStatus {
EV_WHITELIST_MAX,
};
-void LogCTComplianceStatusToUMA(CTComplianceStatus status,
+void LogEVPolicyComplianceToUMA(ct::EVPolicyCompliance status,
const ct::EVCertsWhitelist* ev_whitelist) {
- UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVCertificateCTCompliance", status,
- CT_COMPLIANCE_MAX);
- if (status == CT_NOT_COMPLIANT) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Net.SSL_EVCTCompliance", static_cast<int>(status),
+ static_cast<int>(ct::EVPolicyCompliance::EV_POLICY_MAX));
+ if (status == ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS ||
+ status == ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS) {
EVWhitelistStatus ev_whitelist_status = EV_WHITELIST_NOT_PRESENT;
if (ev_whitelist != NULL) {
if (ev_whitelist->IsValid())
@@ -188,45 +193,50 @@ void LogCTComplianceStatusToUMA(CTComplianceStatus status,
}
}
-struct ComplianceDetails {
- ComplianceDetails()
- : ct_presence_required(false),
- build_timely(false),
- status(CT_NOT_COMPLIANT) {}
+struct EVComplianceDetails {
+ EVComplianceDetails()
+ : build_timely(false),
+ status(ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY) {}
- // Whether enforcement of the policy was required or not.
- bool ct_presence_required;
- // Whether the build is not older than 10 weeks. The value is meaningful only
- // if |ct_presence_required| is true.
+ // Whether the build is not older than 10 weeks.
bool build_timely;
- // Compliance status - meaningful only if |ct_presence_required| and
- // |build_timely| are true.
- CTComplianceStatus status;
+ // Compliance status - meaningful only if |build_timely| is true.
+ ct::EVPolicyCompliance status;
// EV whitelist version.
base::Version whitelist_version;
};
-scoped_ptr<base::Value> NetLogComplianceCheckResultCallback(
+scoped_ptr<base::Value> NetLogEVComplianceCheckResultCallback(
X509Certificate* cert,
- ComplianceDetails* details,
+ EVComplianceDetails* details,
NetLogCaptureMode capture_mode) {
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->Set("certificate", NetLogX509CertificateCallback(cert, capture_mode));
- dict->SetBoolean("policy_enforcement_required",
- details->ct_presence_required);
- if (details->ct_presence_required) {
- dict->SetBoolean("build_timely", details->build_timely);
- if (details->build_timely) {
- dict->SetString("ct_compliance_status",
- ComplianceStatusToString(details->status));
- if (details->whitelist_version.IsValid())
- dict->SetString("ev_whitelist_version",
- details->whitelist_version.GetString());
- }
+ dict->SetBoolean("policy_enforcement_required", true);
+ dict->SetBoolean("build_timely", details->build_timely);
+ if (details->build_timely) {
+ dict->SetString("ct_compliance_status",
+ EVPolicyComplianceToString(details->status));
+ if (details->whitelist_version.IsValid())
+ dict->SetString("ev_whitelist_version",
+ details->whitelist_version.GetString());
}
return std::move(dict);
}
+scoped_ptr<base::Value> NetLogCertComplianceCheckResultCallback(
+ X509Certificate* cert,
+ bool build_timely,
+ ct::CertPolicyCompliance compliance,
+ NetLogCaptureMode capture_mode) {
+ scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ dict->Set("certificate", NetLogX509CertificateCallback(cert, capture_mode));
+ dict->SetBoolean("build_timely", build_timely);
+ dict->SetString("ct_compliance_status",
+ CertPolicyComplianceToString(compliance));
+ return std::move(dict);
+}
+
// Returns true if all SCTs in |verified_scts| were issued on, or after, the
// date specified in kDiverseSCTRequirementStartDate
bool AllSCTsPastDistinctSCTRequirementEnforcementDate(
@@ -261,69 +271,111 @@ bool IsCertificateInWhitelist(const X509Certificate& cert,
return cert_in_ev_whitelist;
}
-void CheckCTEVPolicyCompliance(X509Certificate* cert,
- const ct::EVCertsWhitelist* ev_whitelist,
- const ct::CTVerifyResult& ct_result,
- ComplianceDetails* result) {
- result->ct_presence_required = true;
+ct::CertPolicyCompliance CheckCertPolicyCompliance(
+ X509Certificate* cert,
+ const ct::SCTList& verified_scts,
+ const BoundNetLog& net_log) {
+ if (!HasRequiredNumberOfSCTs(*cert, verified_scts))
+ return ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS;
+ if (AllSCTsPastDistinctSCTRequirementEnforcementDate(verified_scts) &&
+ !HasEnoughDiverseSCTs(verified_scts)) {
+ return ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS;
+ }
- if (!IsBuildTimely())
- return;
- result->build_timely = true;
+ return ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS;
+}
+
+ct::EVPolicyCompliance CertPolicyComplianceToEVPolicyCompliance(
+ ct::CertPolicyCompliance cert_policy_compliance) {
+ switch (cert_policy_compliance) {
+ case ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS:
+ return ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS;
+ case ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS:
+ return ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS;
+ case ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS:
+ return ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS;
+ case ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY:
+ return ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY;
+ }
+ return ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
+}
+void CheckCTEVPolicyCompliance(X509Certificate* cert,
+ const ct::EVCertsWhitelist* ev_whitelist,
+ const ct::SCTList& verified_scts,
+ const BoundNetLog& net_log,
+ EVComplianceDetails* result) {
+ result->status = CertPolicyComplianceToEVPolicyCompliance(
+ CheckCertPolicyCompliance(cert, verified_scts, net_log));
if (ev_whitelist && ev_whitelist->IsValid())
result->whitelist_version = ev_whitelist->Version();
- if (IsCertificateInWhitelist(*cert, ev_whitelist)) {
- result->status = CT_IN_WHITELIST;
- return;
+ if (result->status != ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS &&
+ IsCertificateInWhitelist(*cert, ev_whitelist)) {
+ result->status = ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST;
}
+}
- if (!HasRequiredNumberOfSCTs(*cert, ct_result)) {
- result->status = CT_NOT_COMPLIANT;
- return;
- }
+} // namespace
- if (AllSCTsPastDistinctSCTRequirementEnforcementDate(
- ct_result.verified_scts) &&
- !HasEnoughDiverseSCTs(ct_result.verified_scts)) {
- result->status = CT_NOT_ENOUGH_DIVERSE_SCTS;
- return;
+ct::CertPolicyCompliance CTPolicyEnforcer::DoesConformToCertPolicy(
+ X509Certificate* cert,
+ const ct::SCTList& verified_scts,
+ const BoundNetLog& net_log) {
+ // If the build is not timely, no certificate is considered compliant
+ // with CT policy. The reasoning is that, for example, a log might
+ // have been pulled and is no longer considered valid; thus, a client
+ // needs up-to-date information about logs to consider certificates to
+ // be compliant with policy.
+ bool build_timely = IsBuildTimely();
+ ct::CertPolicyCompliance compliance;
+ if (!build_timely) {
+ compliance = ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY;
+ } else {
+ compliance = CheckCertPolicyCompliance(cert, verified_scts, net_log);
}
- result->status = CT_ENOUGH_SCTS;
-}
+ NetLog::ParametersCallback net_log_callback =
+ base::Bind(&NetLogCertComplianceCheckResultCallback,
+ base::Unretained(cert), build_timely, compliance);
-} // namespace
+ net_log.AddEvent(NetLog::TYPE_CERT_CT_COMPLIANCE_CHECKED, net_log_callback);
+
+ return compliance;
+}
-bool CTPolicyEnforcer::DoesConformToCTEVPolicy(
+ct::EVPolicyCompliance CTPolicyEnforcer::DoesConformToCTEVPolicy(
X509Certificate* cert,
const ct::EVCertsWhitelist* ev_whitelist,
- const ct::CTVerifyResult& ct_result,
+ const ct::SCTList& verified_scts,
const BoundNetLog& net_log) {
- ComplianceDetails details;
-
- CheckCTEVPolicyCompliance(cert, ev_whitelist, ct_result, &details);
+ EVComplianceDetails details;
+ // If the build is not timely, no certificate is considered compliant
+ // with EV policy. The reasoning is that, for example, a log might
+ // have been pulled and is no longer considered valid; thus, a client
+ // needs up-to-date information about logs to consider certificates to
+ // be compliant with policy.
+ details.build_timely = IsBuildTimely();
+ if (!details.build_timely) {
+ details.status = ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY;
+ } else {
+ CheckCTEVPolicyCompliance(cert, ev_whitelist, verified_scts, net_log,
+ &details);
+ }
NetLog::ParametersCallback net_log_callback =
- base::Bind(&NetLogComplianceCheckResultCallback, base::Unretained(cert),
+ base::Bind(&NetLogEVComplianceCheckResultCallback, base::Unretained(cert),
base::Unretained(&details));
net_log.AddEvent(NetLog::TYPE_EV_CERT_CT_COMPLIANCE_CHECKED,
net_log_callback);
- if (!details.ct_presence_required)
- return true;
-
if (!details.build_timely)
- return false;
-
- LogCTComplianceStatusToUMA(details.status, ev_whitelist);
+ return ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY;
- if (details.status == CT_IN_WHITELIST || details.status == CT_ENOUGH_SCTS)
- return true;
+ LogEVPolicyComplianceToUMA(details.status, ev_whitelist);
- return false;
+ return details.status;
}
} // namespace net
diff --git a/chromium/net/cert/ct_policy_enforcer.h b/chromium/net/cert/ct_policy_enforcer.h
index 8c29da5ecb3..110c208ee49 100644
--- a/chromium/net/cert/ct_policy_enforcer.h
+++ b/chromium/net/cert/ct_policy_enforcer.h
@@ -1,42 +1,103 @@
// Copyright 2014 The Chromium 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_CT_POLICY_ENFORCER_H
#define NET_CERT_CT_POLICY_ENFORCER_H
#include <stddef.h>
+#include <vector>
#include "net/base/net_export.h"
+#include "net/cert/signed_certificate_timestamp.h"
#include "net/log/net_log.h"
namespace net {
namespace ct {
-struct CTVerifyResult;
class EVCertsWhitelist;
+enum class CertPolicyCompliance;
+enum class EVPolicyCompliance;
} // namespace ct
class X509Certificate;
-// Class for checking that a given certificate conforms to security-related
+using SCTList = std::vector<scoped_refptr<ct::SignedCertificateTimestamp>>;
+
+// Class for checking that a given certificate conforms to
+// Certificate Transparency-related policies.
+//
+// Each method can be called independently, to determine whether
+// or not it complies with a given policy.
+//
+// For example, to determine if a certificate complies with the
+// EV certificate policy, callers need only to call
+// DoesConformToEVPolicy() - it is not necessary to first check
+// whether or not DoesConformToCertPolicy().
+//
+// However, consider the case where a given certificate is desired
+// to be EV, but, if it does not conform to the EV policy, will
+// be downgraded to DV. In this case, it's necessary to check if
+// it complies with either policy. This can be done one of two
+// ways, reflected in pseudo-code below:
+//
+// Recommended:
+// // Checks EV certificates against the EV policy. If the
+// // certificate fails, it will be downgraded to DV, in which
+// // case, the DV policy will apply.
+// bool is_valid_cert_policy = DoesConformToCertPolicy(...);
+// bool is_valid_ev_policy = is_ev && DoesConformToEVPolicy(...);
+// if (!is_valid_ev_policy)
+// is_ev = false;
+// is_valid_ct = is_valid_ev_policy || is_valid_cert_policy;
+//
+// NOT recommended:
+// // Checks all certificates against the basic policy, and only
+// // if they meet the baseline policy, check EV.
+// bool conforms_to_cert_policy = DoesConformToCertPolicy(...);
+// if (conforms_to_cert_policy && is_ev) {
+// conforms_to_cert_policy = DoesConformToEVPolicy(...);
+// }
+//
+// The reason the second form is NOT recommended is that the EV and Cert
+// policies may be completely independent: a certificate might fail the
+// cert policy but pass the EV policy (because, for example, the EV
+// policy supports whitelisting certificates). Or, conversely, the EV
+// policy might have stricter SCT requirements, so that a certificate
+// passes the certificate policy but fails the EV policy. For this
+// reason, callers are encouraged to check the policy specific to the
+// certificate type being validated, and only call other methods if they
+// are changing the type of certificate because it failed one or more
// policies.
class NET_EXPORT CTPolicyEnforcer {
public:
CTPolicyEnforcer() {}
virtual ~CTPolicyEnforcer() {}
- // Returns true if the collection of SCTs for the given certificate
- // conforms with the CT/EV policy. Conformance details are logged to
- // |net_log|.
- // |cert| is the certificate for which the SCTs apply.
- // |ct_result| must contain the result of verifying any SCTs associated with
- // |cert| prior to invoking this method.
- virtual bool DoesConformToCTEVPolicy(X509Certificate* cert,
- const ct::EVCertsWhitelist* ev_whitelist,
- const ct::CTVerifyResult& ct_result,
- const BoundNetLog& net_log);
+ // Returns the CT certificate policy compliance status for a given
+ // certificate and collection of SCTs.
+ // |cert| is the certificate for which to check compliance, and
+ // ||verified_scts| contains any/all SCTs associated with |cert| that
+ // |have been verified (well-formed, issued by known logs, and
+ // |applying to |cert|).
+ virtual ct::CertPolicyCompliance DoesConformToCertPolicy(
+ X509Certificate* cert,
+ const SCTList& verified_scts,
+ const BoundNetLog& net_log);
+
+ // Returns the CT/EV policy compliance status for a given certificate
+ // and collection of SCTs.
+ // |cert| is the certificate for which to check compliance, and
+ // ||verified_scts| contains any/all SCTs associated with |cert| that
+ // |have been verified (well-formed, issued by known logs, and
+ // |applying to |cert|).
+ virtual ct::EVPolicyCompliance DoesConformToCTEVPolicy(
+ X509Certificate* cert,
+ const ct::EVCertsWhitelist* ev_whitelist,
+ const SCTList& verified_scts,
+ const BoundNetLog& net_log);
};
} // namespace net
diff --git a/chromium/net/cert/ct_policy_enforcer_unittest.cc b/chromium/net/cert/ct_policy_enforcer_unittest.cc
index 43552529333..a2cfb048ba4 100644
--- a/chromium/net/cert/ct_policy_enforcer_unittest.cc
+++ b/chromium/net/cert/ct_policy_enforcer_unittest.cc
@@ -12,6 +12,7 @@
#include "crypto/sha2.h"
#include "net/base/test_data_directory.h"
#include "net/cert/ct_ev_whitelist.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verify_result.h"
#include "net/cert/x509_certificate.h"
#include "net/test/cert_test_util.h"
@@ -65,12 +66,12 @@ class CTPolicyEnforcerTest : public ::testing::Test {
non_google_log_id_.assign(crypto::kSHA256Length, 'A');
}
- void FillResultWithSCTsOfOrigin(
+ void FillListWithSCTsOfOrigin(
ct::SignedCertificateTimestamp::Origin desired_origin,
size_t num_scts,
const std::vector<std::string>& desired_log_keys,
bool timestamp_past_enforcement_date,
- ct::CTVerifyResult* result) {
+ ct::SCTList* verified_scts) {
for (size_t i = 0; i < num_scts; ++i) {
scoped_refptr<ct::SignedCertificateTimestamp> sct(
new ct::SignedCertificateTimestamp());
@@ -87,29 +88,29 @@ class CTPolicyEnforcerTest : public ::testing::Test {
sct->timestamp =
base::Time::FromUTCExploded({2015, 6, 0, 15, 0, 0, 0, 0});
- result->verified_scts.push_back(sct);
+ verified_scts->push_back(sct);
}
}
- void FillResultWithSCTsOfOrigin(
+ void FillListWithSCTsOfOrigin(
ct::SignedCertificateTimestamp::Origin desired_origin,
size_t num_scts,
- ct::CTVerifyResult* result) {
+ ct::SCTList* verified_scts) {
std::vector<std::string> desired_log_ids;
desired_log_ids.push_back(google_log_id_);
- FillResultWithSCTsOfOrigin(desired_origin, num_scts, desired_log_ids, true,
- result);
+ FillListWithSCTsOfOrigin(desired_origin, num_scts, desired_log_ids, true,
+ verified_scts);
}
- void FillResultWithRepeatedLogID(const std::string& desired_id,
- size_t num_scts,
- bool timestamp_past_enforcement_date,
- ct::CTVerifyResult* result) {
+ void FillSCTListWithRepeatedLogID(const std::string& desired_id,
+ size_t num_scts,
+ bool timestamp_past_enforcement_date,
+ ct::SCTList* verified_scts) {
std::vector<std::string> desired_log_ids(num_scts, desired_id);
- FillResultWithSCTsOfOrigin(
+ FillListWithSCTsOfOrigin(
ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, num_scts,
- desired_log_ids, timestamp_past_enforcement_date, result);
+ desired_log_ids, timestamp_past_enforcement_date, verified_scts);
}
void CheckCertificateCompliesWithExactNumberOfEmbeddedSCTs(
@@ -118,22 +119,34 @@ class CTPolicyEnforcerTest : public ::testing::Test {
size_t required_scts) {
scoped_refptr<X509Certificate> cert(
new X509Certificate("subject", "issuer", start, end));
- ct::CTVerifyResult result;
+ ct::SCTList scts;
for (size_t i = 0; i < required_scts - 1; ++i) {
- FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED,
- 1, std::vector<std::string>(), false, &result);
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- cert.get(), nullptr, result, BoundNetLog()))
+ FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
+ std::vector<std::string>(), false, &scts);
+ EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCertPolicy(cert.get(), scts,
+ BoundNetLog()))
<< " for: " << (end - start).InDays() << " and " << required_scts
- << " scts=" << result.verified_scts.size() << " i=" << i;
+ << " scts=" << scts.size() << " i=" << i;
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(cert.get(), nullptr,
+ scts, BoundNetLog()))
+ << " for: " << (end - start).InDays() << " and " << required_scts
+ << " scts=" << scts.size() << " i=" << i;
}
- FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
- std::vector<std::string>(), false, &result);
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(
- cert.get(), nullptr, result, BoundNetLog()))
+ FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
+ std::vector<std::string>(), false, &scts);
+ EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS,
+ policy_enforcer_->DoesConformToCertPolicy(cert.get(), scts,
+ BoundNetLog()))
+ << " for: " << (end - start).InDays() << " and " << required_scts
+ << " scts=" << scts.size();
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(cert.get(), nullptr,
+ scts, BoundNetLog()))
<< " for: " << (end - start).InDays() << " and " << required_scts
- << " scts=" << result.verified_scts.size();
+ << " scts=" << scts.size();
}
protected:
@@ -145,47 +158,67 @@ class CTPolicyEnforcerTest : public ::testing::Test {
TEST_F(CTPolicyEnforcerTest,
DoesNotConformToCTEVPolicyNotEnoughDiverseSCTsAllGoogle) {
- ct::CTVerifyResult result;
- FillResultWithRepeatedLogID(google_log_id_, 2, true, &result);
-
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), nullptr, result, BoundNetLog()));
+ ct::SCTList scts;
+ FillSCTListWithRepeatedLogID(google_log_id_, 2, true, &scts);
+
+ EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS,
+ policy_enforcer_->DoesConformToCertPolicy(chain_.get(), scts,
+ BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr,
+ scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest,
DoesNotConformToCTEVPolicyNotEnoughDiverseSCTsAllNonGoogle) {
- ct::CTVerifyResult result;
- FillResultWithRepeatedLogID(non_google_log_id_, 2, true, &result);
-
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), nullptr, result, BoundNetLog()));
+ ct::SCTList scts;
+ FillSCTListWithRepeatedLogID(non_google_log_id_, 2, true, &scts);
+
+ EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS,
+ policy_enforcer_->DoesConformToCertPolicy(chain_.get(), scts,
+ BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr,
+ scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, ConformsToCTEVPolicyIfSCTBeforeEnforcementDate) {
- ct::CTVerifyResult result;
- FillResultWithRepeatedLogID(non_google_log_id_, 2, false, &result);
-
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr,
- result, BoundNetLog()));
+ ct::SCTList scts;
+ FillSCTListWithRepeatedLogID(non_google_log_id_, 2, false, &scts);
+
+ EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS,
+ policy_enforcer_->DoesConformToCertPolicy(chain_.get(), scts,
+ BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr,
+ scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, ConformsToCTEVPolicyWithNonEmbeddedSCTs) {
- ct::CTVerifyResult result;
- FillResultWithSCTsOfOrigin(
- ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 2, &result);
-
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr,
- result, BoundNetLog()));
+ ct::SCTList scts;
+ FillListWithSCTsOfOrigin(
+ ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 2, &scts);
+
+ EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS,
+ policy_enforcer_->DoesConformToCertPolicy(chain_.get(), scts,
+ BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr,
+ scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, ConformsToCTEVPolicyWithEmbeddedSCTs) {
// This chain_ is valid for 10 years - over 121 months - so requires 5 SCTs.
- ct::CTVerifyResult result;
- FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 5,
- &result);
-
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr,
- result, BoundNetLog()));
+ ct::SCTList scts;
+ FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 5,
+ &scts);
+
+ EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS,
+ policy_enforcer_->DoesConformToCertPolicy(chain_.get(), scts,
+ BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr,
+ scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, DoesNotConformToCTEVPolicyNotEnoughSCTs) {
@@ -194,33 +227,49 @@ TEST_F(CTPolicyEnforcerTest, DoesNotConformToCTEVPolicyNotEnoughSCTs) {
// This chain_ is valid for 10 years - over 121 months - so requires 5 SCTs.
// However, as there are only two logs, two SCTs will be required - supply one
// to guarantee the test fails.
- ct::CTVerifyResult result;
- FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
- &result);
-
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), non_including_whitelist.get(), result, BoundNetLog()));
+ ct::SCTList scts;
+ FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
+ &scts);
+
+ EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCertPolicy(chain_.get(), scts,
+ BoundNetLog()));
+ EXPECT_EQ(
+ ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), non_including_whitelist.get(), scts, BoundNetLog()));
// ... but should be OK if whitelisted.
scoped_refptr<ct::EVCertsWhitelist> whitelist(
new DummyEVCertsWhitelist(true, true));
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), whitelist.get(), result, BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), whitelist.get(), scts, BoundNetLog()));
}
-TEST_F(CTPolicyEnforcerTest, DoesNotConformToPolicyInvalidDates) {
+// TODO(estark): fix this test so that it can check if
+// |no_valid_dates_cert| is on the whitelist without
+// crashing. https://crbug.com/582740
+TEST_F(CTPolicyEnforcerTest, DISABLED_DoesNotConformToPolicyInvalidDates) {
scoped_refptr<X509Certificate> no_valid_dates_cert(new X509Certificate(
"subject", "issuer", base::Time(), base::Time::Now()));
- ct::CTVerifyResult result;
- FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 5,
- &result);
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- no_valid_dates_cert.get(), nullptr, result, BoundNetLog()));
+ ct::SCTList scts;
+ FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 5,
+ &scts);
+ ASSERT_TRUE(no_valid_dates_cert);
+ EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCertPolicy(no_valid_dates_cert.get(),
+ scts, BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ no_valid_dates_cert.get(), nullptr, scts, BoundNetLog()));
// ... but should be OK if whitelisted.
scoped_refptr<ct::EVCertsWhitelist> whitelist(
new DummyEVCertsWhitelist(true, true));
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), whitelist.get(), result, BoundNetLog()));
+ EXPECT_EQ(
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ no_valid_dates_cert.get(), whitelist.get(), scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest,
@@ -271,30 +320,36 @@ TEST_F(CTPolicyEnforcerTest, ConformsToPolicyByEVWhitelistPresence) {
scoped_refptr<ct::EVCertsWhitelist> whitelist(
new DummyEVCertsWhitelist(true, true));
- ct::CTVerifyResult result;
- FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
- &result);
- EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), whitelist.get(), result, BoundNetLog()));
+ ct::SCTList scts;
+ FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
+ &scts);
+ EXPECT_EQ(ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCertPolicy(chain_.get(), scts,
+ BoundNetLog()));
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), whitelist.get(), scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, IgnoresInvalidEVWhitelist) {
scoped_refptr<ct::EVCertsWhitelist> whitelist(
new DummyEVCertsWhitelist(false, true));
- ct::CTVerifyResult result;
- FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
- &result);
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), whitelist.get(), result, BoundNetLog()));
+ ct::SCTList scts;
+ FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
+ &scts);
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ chain_.get(), whitelist.get(), scts, BoundNetLog()));
}
TEST_F(CTPolicyEnforcerTest, IgnoresNullEVWhitelist) {
- ct::CTVerifyResult result;
- FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
- &result);
- EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy(
- chain_.get(), nullptr, result, BoundNetLog()));
+ ct::SCTList scts;
+ FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1,
+ &scts);
+ EXPECT_EQ(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS,
+ policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr,
+ scts, BoundNetLog()));
}
} // namespace
diff --git a/chromium/net/cert/ct_policy_status.h b/chromium/net/cert/ct_policy_status.h
new file mode 100644
index 00000000000..cc38585d6fa
--- /dev/null
+++ b/chromium/net/cert/ct_policy_status.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_CERT_CT_POLICY_STATUS_H
+#define NET_CERT_CT_POLICY_STATUS_H
+
+namespace net {
+
+namespace ct {
+
+// Information about the connection's compliance with the CT
+// certificate policy.
+enum class CertPolicyCompliance {
+ // The connection complied with the certificate policy by
+ // including SCTs that satisfy the policy.
+ CERT_POLICY_COMPLIES_VIA_SCTS = 0,
+ // The connection did not have enough SCTs to comply.
+ CERT_POLICY_NOT_ENOUGH_SCTS,
+ // The connection did not have diverse enough SCTs to comply.
+ CERT_POLICY_NOT_DIVERSE_SCTS,
+ // The connection cannot be considered compliant because the build
+ // isn't timely and therefore log information might be out of date
+ // (for example a log might no longer be considered trustworthy).
+ CERT_POLICY_BUILD_NOT_TIMELY,
+};
+
+// Information about a connection's compliance with the CT EV
+// certificate policy.
+// This enum is histogrammed, so do not remove or reorder values.
+enum class EVPolicyCompliance {
+ // The certificate was not EV, so the EV policy doesn't apply.
+ EV_POLICY_DOES_NOT_APPLY = 0,
+ // The connection complied with the EV certificate policy by being
+ // included on the EV whitelist.
+ EV_POLICY_COMPLIES_VIA_WHITELIST,
+ // The connection complied with the EV certificate policy by
+ // including SCTs that satisfy the policy.
+ EV_POLICY_COMPLIES_VIA_SCTS,
+ // The connection did not have enough SCTs to retain its EV
+ // status.
+ EV_POLICY_NOT_ENOUGH_SCTS,
+ // The connection did not have diverse enough SCTs to retain its
+ // EV status.
+ EV_POLICY_NOT_DIVERSE_SCTS,
+ // The connection cannot be considered compliant because the build
+ // isn't timely and therefore log information might be out of date
+ // (for example a log might no longer be considered trustworthy).
+ EV_POLICY_BUILD_NOT_TIMELY,
+ EV_POLICY_MAX,
+};
+
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_CT_POLICY_STATUS_H
diff --git a/chromium/net/cert/ct_serialization.cc b/chromium/net/cert/ct_serialization.cc
index 235d37e65ad..2de83087260 100644
--- a/chromium/net/cert/ct_serialization.cc
+++ b/chromium/net/cert/ct_serialization.cc
@@ -6,9 +6,11 @@
#include <stdint.h>
+#include <algorithm>
#include <limits>
#include "base/logging.h"
+#include "base/numerics/safe_math.h"
namespace net {
@@ -54,11 +56,15 @@ template <typename T>
bool ReadUint(size_t length, base::StringPiece* in, T* out) {
if (in->size() < length)
return false;
+ DCHECK_NE(length, 0u);
DCHECK_LE(length, sizeof(T));
- T result = 0;
- for (size_t i = 0; i < length; ++i) {
- result = (result << 8) | static_cast<unsigned char>((*in)[i]);
+ T result = static_cast<uint8_t>((*in)[0]);
+ // This loop only executes if sizeof(T) > 1, because the first operation is
+ // to shift left by 1 byte, which is undefined behaviour if T is a 1 byte
+ // integer.
+ for (size_t i = 1; i < length; ++i) {
+ result = (result << 8) | static_cast<uint8_t>((*in)[i]);
}
in->remove_prefix(length);
*out = result;
@@ -66,14 +72,18 @@ bool ReadUint(size_t length, base::StringPiece* in, T* out) {
}
// Reads a TLS-encoded field length from |in|.
-// The bytes read from |in| are discarded (i.e. |in|'s prefix removed)
-// |prefix_length| indicates the bytes needed to represent the length (e.g. 3)
+// The bytes read from |in| are discarded (i.e. |in|'s prefix removed).
+// |prefix_length| indicates the bytes needed to represent the length (e.g. 3).
+// Max |prefix_length| is 8.
// success, returns true and stores the result in |*out|.
bool ReadLength(size_t prefix_length, base::StringPiece* in, size_t* out) {
- size_t length;
+ uint64_t length = 0;
if (!ReadUint(prefix_length, in, &length))
return false;
- *out = length;
+ base::CheckedNumeric<size_t> checked_length = length;
+ if (!checked_length.IsValid())
+ return false;
+ *out = checked_length.ValueOrDie();
return true;
}
@@ -96,7 +106,7 @@ bool ReadFixedBytes(size_t length,
bool ReadVariableBytes(size_t prefix_length,
base::StringPiece* in,
base::StringPiece* out) {
- size_t length;
+ size_t length = 0;
if (!ReadLength(prefix_length, in, &length))
return false;
return ReadFixedBytes(length, in, out);
@@ -176,15 +186,15 @@ bool ConvertSignatureAlgorithm(
}
// Writes a TLS-encoded variable length unsigned integer to |output|.
-// |length| indicates the size (in bytes) of the integer.
+// |length| indicates the size (in bytes) of the integer. This must be able to
+// accomodate |value|.
// |value| the value itself to be written.
-template <typename T>
-void WriteUint(size_t length, T value, std::string* output) {
- DCHECK_LE(length, sizeof(T));
- DCHECK(length == sizeof(T) || value >> (length * 8) == 0);
+void WriteUint(size_t length, uint64_t value, std::string* output) {
+ // Check that |value| fits into |length| bytes.
+ DCHECK(length >= sizeof(value) || value >> (length * 8) == 0);
for (; length > 0; --length) {
- output->push_back((value >> ((length - 1)* 8)) & 0xFF);
+ output->push_back((value >> ((length - 1) * 8)) & 0xFF);
}
}
@@ -195,25 +205,33 @@ void WriteUint(size_t length, T value, std::string* output) {
// length when reading.
// If the length of |input| is dynamic and data is expected to follow it,
// WriteVariableBytes must be used.
-void WriteEncodedBytes(const base::StringPiece& input, std::string* output) {
+// Returns the number of bytes written (the length of |input|).
+size_t WriteEncodedBytes(const base::StringPiece& input, std::string* output) {
input.AppendToString(output);
+ return input.size();
}
// Writes a variable-length array to |output|.
-// |prefix_length| indicates the number of bytes needed to represnt the length.
+// |prefix_length| indicates the number of bytes needed to represent the length.
// |input| is the array itself.
-// If the size of |input| is less than 2^|prefix_length| - 1, encode the
-// length and data and return true. Otherwise, return false.
+// If 1 <= |prefix_length| <= 8 and the size of |input| is less than
+// 2^|prefix_length| - 1, encode the length and data and return true.
+// Otherwise, return false.
bool WriteVariableBytes(size_t prefix_length,
const base::StringPiece& input,
std::string* output) {
- size_t input_size = input.size();
- size_t max_allowed_input_size =
- static_cast<size_t>(((1 << (prefix_length * 8)) - 1));
- if (input_size > max_allowed_input_size)
+ DCHECK_GE(prefix_length, 1u);
+ DCHECK_LE(prefix_length, 8u);
+
+ uint64_t input_size = input.size();
+ uint64_t max_input_size = (prefix_length == 8)
+ ? UINT64_MAX
+ : ((UINT64_C(1) << (prefix_length * 8)) - 1);
+
+ if (input_size > max_input_size)
return false;
- WriteUint(prefix_length, input.size(), output);
+ WriteUint(prefix_length, input_size, output);
WriteEncodedBytes(input, output);
return true;
@@ -291,6 +309,26 @@ bool EncodeLogEntry(const LogEntry& input, std::string* output) {
return false;
}
+static bool ReadTimeSinceEpoch(base::StringPiece* input, base::Time* output) {
+ uint64_t time_since_epoch = 0;
+ if (!ReadUint(kTimestampLength, input, &time_since_epoch))
+ return false;
+
+ base::CheckedNumeric<int64_t> time_since_epoch_signed = time_since_epoch;
+
+ if (!time_since_epoch_signed.IsValid()) {
+ DVLOG(1) << "Timestamp value too big to cast to int64_t: "
+ << time_since_epoch;
+ return false;
+ }
+
+ *output =
+ base::Time::UnixEpoch() +
+ base::TimeDelta::FromMilliseconds(time_since_epoch_signed.ValueOrDie());
+
+ return true;
+}
+
static void WriteTimeSinceEpoch(const base::Time& timestamp,
std::string* output) {
base::TimeDelta time_since_epoch = timestamp - base::Time::UnixEpoch();
@@ -351,28 +389,17 @@ bool DecodeSignedCertificateTimestamp(
}
result->version = SignedCertificateTimestamp::SCT_VERSION_1;
- uint64_t timestamp;
base::StringPiece log_id;
base::StringPiece extensions;
if (!ReadFixedBytes(kLogIdLength, input, &log_id) ||
- !ReadUint(kTimestampLength, input, &timestamp) ||
- !ReadVariableBytes(kExtensionsLengthBytes, input,
- &extensions) ||
+ !ReadTimeSinceEpoch(input, &result->timestamp) ||
+ !ReadVariableBytes(kExtensionsLengthBytes, input, &extensions) ||
!DecodeDigitallySigned(input, &result->signature)) {
return false;
}
- if (timestamp > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
- DVLOG(1) << "Timestamp value too big to cast to int64_t: " << timestamp;
- return false;
- }
-
log_id.CopyToString(&result->log_id);
extensions.CopyToString(&result->extensions);
- result->timestamp =
- base::Time::UnixEpoch() +
- base::TimeDelta::FromMilliseconds(static_cast<int64_t>(timestamp));
-
output->swap(result);
return true;
}
@@ -381,7 +408,7 @@ bool EncodeSCTListForTesting(const base::StringPiece& sct,
std::string* output) {
std::string encoded_sct;
return WriteVariableBytes(kSerializedSCTLengthBytes, sct, &encoded_sct) &&
- WriteVariableBytes(kSCTListLengthBytes, encoded_sct, output);
+ WriteVariableBytes(kSCTListLengthBytes, encoded_sct, output);
}
} // namespace ct
diff --git a/chromium/net/cert/ct_verify_result.cc b/chromium/net/cert/ct_verify_result.cc
index c62a18a7c2d..de5bea0deed 100644
--- a/chromium/net/cert/ct_verify_result.cc
+++ b/chromium/net/cert/ct_verify_result.cc
@@ -4,11 +4,19 @@
#include "net/cert/ct_verify_result.h"
+#include "net/cert/ct_policy_status.h"
+
namespace net {
namespace ct {
-CTVerifyResult::CTVerifyResult() {}
+CTVerifyResult::CTVerifyResult()
+ : ct_policies_applied(false),
+ cert_policy_compliance(
+ ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS),
+ ev_policy_compliance(ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY) {}
+
+CTVerifyResult::CTVerifyResult(const CTVerifyResult& other) = default;
CTVerifyResult::~CTVerifyResult() {}
diff --git a/chromium/net/cert/ct_verify_result.h b/chromium/net/cert/ct_verify_result.h
index aa90164193b..ca163580d73 100644
--- a/chromium/net/cert/ct_verify_result.h
+++ b/chromium/net/cert/ct_verify_result.h
@@ -7,19 +7,24 @@
#include <vector>
+#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/signed_certificate_timestamp.h"
namespace net {
namespace ct {
+enum class CertPolicyCompliance;
+enum class EVPolicyCompliance;
+
typedef std::vector<scoped_refptr<SignedCertificateTimestamp> > SCTList;
-// Holds Signed Certificate Timestamps, depending on their verification results.
-// More information could be tracked here about SCTs, but for the current UI
-// this categorization is enough.
+// Holds Signed Certificate Timestamps, depending on their verification
+// results, and information about CT policies that were applied on the
+// connection.
struct NET_EXPORT CTVerifyResult {
CTVerifyResult();
+ CTVerifyResult(const CTVerifyResult& other);
~CTVerifyResult();
// SCTs from known logs where the signature verified correctly.
@@ -28,6 +33,15 @@ struct NET_EXPORT CTVerifyResult {
SCTList invalid_scts;
// SCTs from unknown logs and as such are unverifiable.
SCTList unknown_logs_scts;
+
+ // True if any CT policies were applied on this connection.
+ bool ct_policies_applied;
+ // The result of evaluating whether the connection complies with the
+ // CT certificate policy.
+ CertPolicyCompliance cert_policy_compliance;
+ // The result of evaluating whether the connection complies with the
+ // EV CT policy.
+ EVPolicyCompliance ev_policy_compliance;
};
} // namespace ct
diff --git a/chromium/net/cert/ev_root_ca_metadata.cc b/chromium/net/cert/ev_root_ca_metadata.cc
index a5ac6e2231e..a46e50a6f71 100644
--- a/chromium/net/cert/ev_root_ca_metadata.cc
+++ b/chromium/net/cert/ev_root_ca_metadata.cc
@@ -4,7 +4,7 @@
#include "net/cert/ev_root_ca_metadata.h"
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
#include <cert.h>
#include <pkcs11n.h>
#include <secerr.h>
@@ -15,13 +15,13 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
#include "crypto/nss_util.h"
#endif
namespace net {
-#if defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_WIN)
+#if defined(USE_NSS_VERIFIER) || defined(OS_WIN)
// Raw metadata.
struct EVMetadata {
// kMaxOIDsPerCA is the number of OIDs that we can support per root CA. At
@@ -41,457 +41,536 @@ struct EVMetadata {
};
static const EVMetadata ev_root_ca_metadata[] = {
- // AC Camerfirma S.A. Chambers of Commerce Root - 2008
- // https://www.camerfirma.com
- { { { 0x78, 0x6a, 0x74, 0xac, 0x76, 0xab, 0x14, 0x7f, 0x9c, 0x6a,
- 0x30, 0x50, 0xba, 0x9e, 0xa8, 0x7e, 0xfe, 0x9a, 0xce, 0x3c } },
- { // AC Camerfirma uses the last two arcs to track how the private key is
- // managed - the effective verification policy is the same.
- "1.3.6.1.4.1.17326.10.14.2.1.2",
- "1.3.6.1.4.1.17326.10.14.2.2.2", },
- },
- // AC Camerfirma S.A. Global Chambersign Root - 2008
- // https://server2.camerfirma.com:8082
- { { { 0x4a, 0xbd, 0xee, 0xec, 0x95, 0x0d, 0x35, 0x9c, 0x89, 0xae,
- 0xc7, 0x52, 0xa1, 0x2c, 0x5b, 0x29, 0xf6, 0xd6, 0xaa, 0x0c } },
- { // AC Camerfirma uses the last two arcs to track how the private key is
- // managed - the effective verification policy is the same.
- "1.3.6.1.4.1.17326.10.8.12.1.2",
- "1.3.6.1.4.1.17326.10.8.12.2.2", },
- },
- // AddTrust External CA Root
- // https://addtrustexternalcaroot-ev.comodoca.com
- { { { 0x02, 0xfa, 0xf3, 0xe2, 0x91, 0x43, 0x54, 0x68, 0x60, 0x78,
- 0x57, 0x69, 0x4d, 0xf5, 0xe4, 0x5b, 0x68, 0x85, 0x18, 0x68 } },
- {
- "1.3.6.1.4.1.6449.1.2.1.5.1",
- // This is the Network Solutions EV OID. However, this root
- // cross-certifies NetSol and so we need it here too.
- "1.3.6.1.4.1.782.1.2.1.8.1",
- },
- },
- // Actalis Authentication Root CA
- // https://ssltest-a.actalis.it:8443
- { { { 0xf3, 0x73, 0xb3, 0x87, 0x06, 0x5a, 0x28, 0x84, 0x8a, 0xf2,
- 0xf3, 0x4a, 0xce, 0x19, 0x2b, 0xdd, 0xc7, 0x8e, 0x9c, 0xac } },
- {"1.3.159.1.17.1", ""},
- },
- // AffirmTrust Commercial
- // https://commercial.affirmtrust.com/
- { { { 0xf9, 0xb5, 0xb6, 0x32, 0x45, 0x5f, 0x9c, 0xbe, 0xec, 0x57,
- 0x5f, 0x80, 0xdc, 0xe9, 0x6e, 0x2c, 0xc7, 0xb2, 0x78, 0xb7 } },
- {"1.3.6.1.4.1.34697.2.1", ""},
- },
- // AffirmTrust Networking
- // https://networking.affirmtrust.com:4431
- { { { 0x29, 0x36, 0x21, 0x02, 0x8b, 0x20, 0xed, 0x02, 0xf5, 0x66,
- 0xc5, 0x32, 0xd1, 0xd6, 0xed, 0x90, 0x9f, 0x45, 0x00, 0x2f } },
- {"1.3.6.1.4.1.34697.2.2", ""},
- },
- // AffirmTrust Premium
- // https://premium.affirmtrust.com:4432/
- { { { 0xd8, 0xa6, 0x33, 0x2c, 0xe0, 0x03, 0x6f, 0xb1, 0x85, 0xf6,
- 0x63, 0x4f, 0x7d, 0x6a, 0x06, 0x65, 0x26, 0x32, 0x28, 0x27 } },
- {"1.3.6.1.4.1.34697.2.3", ""},
- },
- // AffirmTrust Premium ECC
- // https://premiumecc.affirmtrust.com:4433/
- { { { 0xb8, 0x23, 0x6b, 0x00, 0x2f, 0x1d, 0x16, 0x86, 0x53, 0x01,
- 0x55, 0x6c, 0x11, 0xa4, 0x37, 0xca, 0xeb, 0xff, 0xc3, 0xbb } },
- {"1.3.6.1.4.1.34697.2.4", ""},
- },
- // Autoridad de Certificacion Firmaprofesional CIF A62634068
- // https://publifirma.firmaprofesional.com/
- { { { 0xae, 0xc5, 0xfb, 0x3f, 0xc8, 0xe1, 0xbf, 0xc4, 0xe5, 0x4f,
- 0x03, 0x07, 0x5a, 0x9a, 0xe8, 0x00, 0xb7, 0xf7, 0xb6, 0xfa } },
- {"1.3.6.1.4.1.13177.10.1.3.10", "" }
- },
- // Baltimore CyberTrust Root
- // https://secure.omniroot.com/repository/
- { { { 0xd4, 0xde, 0x20, 0xd0, 0x5e, 0x66, 0xfc, 0x53, 0xfe, 0x1a,
- 0x50, 0x88, 0x2c, 0x78, 0xdb, 0x28, 0x52, 0xca, 0xe4, 0x74 } },
- {"1.3.6.1.4.1.6334.1.100.1", ""},
- },
- // Buypass Class 3 CA 1
- // https://valid.evident.ca13.ssl.buypass.no/
- { { { 0x61, 0x57, 0x3A, 0x11, 0xDF, 0x0E, 0xD8, 0x7E, 0xD5, 0x92,
- 0x65, 0x22, 0xEA, 0xD0, 0x56, 0xD7, 0x44, 0xB3, 0x23, 0x71 } },
- {"2.16.578.1.26.1.3.3", ""},
- },
- // Buypass Class 3 Root CA
- // https://valid.evident.ca23.ssl.buypass.no/
- { { { 0xDA, 0xFA, 0xF7, 0xFA, 0x66, 0x84, 0xEC, 0x06, 0x8F, 0x14,
- 0x50, 0xBD, 0xC7, 0xC2, 0x81, 0xA5, 0xBC, 0xA9, 0x64, 0x57 } },
- {"2.16.578.1.26.1.3.3", ""},
- },
- // CA 沃通根证书
- // https://root2evtest.wosign.com/
- { { { 0x16, 0x32, 0x47, 0x8d, 0x89, 0xf9, 0x21, 0x3a, 0x92, 0x00,
- 0x85, 0x63, 0xf5, 0xa4, 0xa7, 0xd3, 0x12, 0x40, 0x8a, 0xd6 } },
- {"1.3.6.1.4.1.36305.2", ""},
- },
- // Certification Authority of WoSign
- // https://root1evtest.wosign.com/
- { { { 0xb9, 0x42, 0x94, 0xbf, 0x91, 0xea, 0x8f, 0xb6, 0x4b, 0xe6,
- 0x10, 0x97, 0xc7, 0xfb, 0x00, 0x13, 0x59, 0xb6, 0x76, 0xcb } },
- {"1.3.6.1.4.1.36305.2", ""},
- },
- // CertPlus Class 2 Primary CA (KEYNECTIS)
- // https://www.keynectis.com/
- { { { 0x74, 0x20, 0x74, 0x41, 0x72, 0x9c, 0xdd, 0x92, 0xec, 0x79,
- 0x31, 0xd8, 0x23, 0x10, 0x8d, 0xc2, 0x81, 0x92, 0xe2, 0xbb } },
- {"1.3.6.1.4.1.22234.2.5.2.3.1", ""},
- },
- // Certum Trusted Network CA
- // https://juice.certum.pl/
- { { { 0x07, 0xe0, 0x32, 0xe0, 0x20, 0xb7, 0x2c, 0x3f, 0x19, 0x2f,
- 0x06, 0x28, 0xa2, 0x59, 0x3a, 0x19, 0xa7, 0x0f, 0x06, 0x9e } },
- {"1.2.616.1.113527.2.5.1.1", ""},
- },
- // China Internet Network Information Center EV Certificates Root
- // https://evdemo.cnnic.cn/
- { { { 0x4F, 0x99, 0xAA, 0x93, 0xFB, 0x2B, 0xD1, 0x37, 0x26, 0xA1,
- 0x99, 0x4A, 0xCE, 0x7F, 0xF0, 0x05, 0xF2, 0x93, 0x5D, 0x1E } },
- {"1.3.6.1.4.1.29836.1.10", ""},
- },
- // COMODO Certification Authority
- // https://secure.comodo.com/
- { { { 0x66, 0x31, 0xbf, 0x9e, 0xf7, 0x4f, 0x9e, 0xb6, 0xc9, 0xd5,
- 0xa6, 0x0c, 0xba, 0x6a, 0xbe, 0xd1, 0xf7, 0xbd, 0xef, 0x7b } },
- {"1.3.6.1.4.1.6449.1.2.1.5.1", ""},
- },
- // COMODO Certification Authority (reissued certificate with NotBefore of Jan
- // 1 00:00:00 2011 GMT)
- // https://secure.comodo.com/
- { { { 0xee, 0x86, 0x93, 0x87, 0xff, 0xfd, 0x83, 0x49, 0xab, 0x5a,
- 0xd1, 0x43, 0x22, 0x58, 0x87, 0x89, 0xa4, 0x57, 0xb0, 0x12 } },
- {"1.3.6.1.4.1.6449.1.2.1.5.1", ""},
- },
- // COMODO ECC Certification Authority
- // https://comodoecccertificationauthority-ev.comodoca.com/
- { { { 0x9f, 0x74, 0x4e, 0x9f, 0x2b, 0x4d, 0xba, 0xec, 0x0f, 0x31,
- 0x2c, 0x50, 0xb6, 0x56, 0x3b, 0x8e, 0x2d, 0x93, 0xc3, 0x11 } },
- {"1.3.6.1.4.1.6449.1.2.1.5.1", ""},
- },
- // COMODO RSA Certification Authority
- // https://comodorsacertificationauthority-ev.comodoca.com/
- { { { 0xaf, 0xe5, 0xd2, 0x44, 0xa8, 0xd1, 0x19, 0x42, 0x30, 0xff,
- 0x47, 0x9f, 0xe2, 0xf8, 0x97, 0xbb, 0xcd, 0x7a, 0x8c, 0xb4 } },
- {"1.3.6.1.4.1.6449.1.2.1.5.1", ""},
- },
- // Cybertrust Global Root
- // https://evup.cybertrust.ne.jp/ctj-ev-upgrader/evseal.gif
- { { { 0x5f, 0x43, 0xe5, 0xb1, 0xbf, 0xf8, 0x78, 0x8c, 0xac, 0x1c,
- 0xc7, 0xca, 0x4a, 0x9a, 0xc6, 0x22, 0x2b, 0xcc, 0x34, 0xc6 } },
- {"1.3.6.1.4.1.6334.1.100.1", ""},
- },
- // DigiCert High Assurance EV Root CA
- // https://www.digicert.com
- { { { 0x5f, 0xb7, 0xee, 0x06, 0x33, 0xe2, 0x59, 0xdb, 0xad, 0x0c,
- 0x4c, 0x9a, 0xe6, 0xd3, 0x8f, 0x1a, 0x61, 0xc7, 0xdc, 0x25 } },
- {"2.16.840.1.114412.2.1", ""},
- },
- // D-TRUST Root Class 3 CA 2 EV 2009
- // https://certdemo-ev-valid.ssl.d-trust.net/
- { { { 0x96, 0xc9, 0x1b, 0x0b, 0x95, 0xb4, 0x10, 0x98, 0x42, 0xfa,
- 0xd0, 0xd8, 0x22, 0x79, 0xfe, 0x60, 0xfa, 0xb9, 0x16, 0x83 } },
- {"1.3.6.1.4.1.4788.2.202.1", ""},
- },
- // Entrust.net Secure Server Certification Authority
- // https://www.entrust.net/
- { { { 0x99, 0xa6, 0x9b, 0xe6, 0x1a, 0xfe, 0x88, 0x6b, 0x4d, 0x2b,
- 0x82, 0x00, 0x7c, 0xb8, 0x54, 0xfc, 0x31, 0x7e, 0x15, 0x39 } },
- {"2.16.840.1.114028.10.1.2", ""},
- },
- // Entrust Root Certification Authority
- // https://www.entrust.net/
- { { { 0xb3, 0x1e, 0xb1, 0xb7, 0x40, 0xe3, 0x6c, 0x84, 0x02, 0xda,
- 0xdc, 0x37, 0xd4, 0x4d, 0xf5, 0xd4, 0x67, 0x49, 0x52, 0xf9 } },
- {"2.16.840.1.114028.10.1.2", ""},
- },
- // Equifax Secure Certificate Authority (GeoTrust)
- // https://www.geotrust.com/
- { { { 0xd2, 0x32, 0x09, 0xad, 0x23, 0xd3, 0x14, 0x23, 0x21, 0x74,
- 0xe4, 0x0d, 0x7f, 0x9d, 0x62, 0x13, 0x97, 0x86, 0x63, 0x3a } },
- {"1.3.6.1.4.1.14370.1.6", ""},
- },
- // E-Tugra Certification Authority
- // https://sslev.e-tugra.com.tr
- { { { 0x51, 0xC6, 0xE7, 0x08, 0x49, 0x06, 0x6E, 0xF3, 0x92, 0xD4,
- 0x5C, 0xA0, 0x0D, 0x6D, 0xA3, 0x62, 0x8F, 0xC3, 0x52, 0x39 } },
- {"2.16.792.3.0.4.1.1.4", ""},
- },
- // GeoTrust Primary Certification Authority
- // https://www.geotrust.com/
- { { { 0x32, 0x3c, 0x11, 0x8e, 0x1b, 0xf7, 0xb8, 0xb6, 0x52, 0x54,
- 0xe2, 0xe2, 0x10, 0x0d, 0xd6, 0x02, 0x90, 0x37, 0xf0, 0x96 } },
- {"1.3.6.1.4.1.14370.1.6", ""},
- },
- // GeoTrust Primary Certification Authority - G2
- { { { 0x8d, 0x17, 0x84, 0xd5, 0x37, 0xf3, 0x03, 0x7d, 0xec, 0x70,
- 0xfe, 0x57, 0x8b, 0x51, 0x9a, 0x99, 0xe6, 0x10, 0xd7, 0xb0 } },
- {"1.3.6.1.4.1.14370.1.6", ""},
- },
- // GeoTrust Primary Certification Authority - G3
- { { { 0x03, 0x9e, 0xed, 0xb8, 0x0b, 0xe7, 0xa0, 0x3c, 0x69, 0x53,
- 0x89, 0x3b, 0x20, 0xd2, 0xd9, 0x32, 0x3a, 0x4c, 0x2a, 0xfd } },
- {"1.3.6.1.4.1.14370.1.6", ""},
- },
- // GlobalSign Root CA - R2
- // https://www.globalsign.com/
- { { { 0x75, 0xe0, 0xab, 0xb6, 0x13, 0x85, 0x12, 0x27, 0x1c, 0x04,
- 0xf8, 0x5f, 0xdd, 0xde, 0x38, 0xe4, 0xb7, 0x24, 0x2e, 0xfe } },
- {"1.3.6.1.4.1.4146.1.1", ""},
- },
- // GlobalSign Root CA
- { { { 0xb1, 0xbc, 0x96, 0x8b, 0xd4, 0xf4, 0x9d, 0x62, 0x2a, 0xa8,
- 0x9a, 0x81, 0xf2, 0x15, 0x01, 0x52, 0xa4, 0x1d, 0x82, 0x9c } },
- {"1.3.6.1.4.1.4146.1.1", ""},
- },
- // GlobalSign Root CA - R3
- // https://2029.globalsign.com/
- { { { 0xd6, 0x9b, 0x56, 0x11, 0x48, 0xf0, 0x1c, 0x77, 0xc5, 0x45,
- 0x78, 0xc1, 0x09, 0x26, 0xdf, 0x5b, 0x85, 0x69, 0x76, 0xad } },
- {"1.3.6.1.4.1.4146.1.1", ""},
- },
- // GlobalSign ECC Root CA - R4
- // https://2038r4.globalsign.com
- { { { 0x69, 0x69, 0x56, 0x2e, 0x40, 0x80, 0xf4, 0x24, 0xa1, 0xe7,
- 0x19, 0x9f, 0x14, 0xba, 0xf3, 0xee, 0x58, 0xab, 0x6a, 0xbb } },
- {"1.3.6.1.4.1.4146.1.1", ""},
- },
- // GlobalSign ECC Root CA - R5
- // https://2038r5.globalsign.com/
- { { { 0x1f, 0x24, 0xc6, 0x30, 0xcd, 0xa4, 0x18, 0xef, 0x20, 0x69,
- 0xff, 0xad, 0x4f, 0xdd, 0x5f, 0x46, 0x3a, 0x1b, 0x69, 0xaa } },
- {"1.3.6.1.4.1.4146.1.1", ""}
- },
- // Go Daddy Class 2 Certification Authority
- // https://www.godaddy.com/
- { { { 0x27, 0x96, 0xba, 0xe6, 0x3f, 0x18, 0x01, 0xe2, 0x77, 0x26,
- 0x1b, 0xa0, 0xd7, 0x77, 0x70, 0x02, 0x8f, 0x20, 0xee, 0xe4 } },
- {"2.16.840.1.114413.1.7.23.3", ""},
- },
- // Go Daddy Root Certificate Authority - G2
- // https://valid.gdig2.catest.godaddy.com/
- { { { 0x47, 0xbe, 0xab, 0xc9, 0x22, 0xea, 0xe8, 0x0e, 0x78, 0x78,
- 0x34, 0x62, 0xa7, 0x9f, 0x45, 0xc2, 0x54, 0xfd, 0xe6, 0x8b } },
- {"2.16.840.1.114413.1.7.23.3", ""},
- },
- // GTE CyberTrust Global Root
- // https://www.cybertrust.ne.jp/
- { { { 0x97, 0x81, 0x79, 0x50, 0xd8, 0x1c, 0x96, 0x70, 0xcc, 0x34,
- 0xd8, 0x09, 0xcf, 0x79, 0x44, 0x31, 0x36, 0x7e, 0xf4, 0x74 } },
- {"1.3.6.1.4.1.6334.1.100.1", ""},
- },
- // Izenpe.com - SHA256 root
- // The first OID is for businesses and the second for government entities.
- // These are the test sites, respectively:
- // https://servicios.izenpe.com
- // https://servicios1.izenpe.com
- { { { 0x2f, 0x78, 0x3d, 0x25, 0x52, 0x18, 0xa7, 0x4a, 0x65, 0x39,
- 0x71, 0xb5, 0x2c, 0xa2, 0x9c, 0x45, 0x15, 0x6f, 0xe9, 0x19} },
- {"1.3.6.1.4.1.14777.6.1.1", "1.3.6.1.4.1.14777.6.1.2"},
- },
- // Izenpe.com - SHA1 root
- // Windows XP finds this, SHA1, root instead. The policy OIDs are the same as
- // for the SHA256 root, above.
- { { { 0x30, 0x77, 0x9e, 0x93, 0x15, 0x02, 0x2e, 0x94, 0x85, 0x6a,
- 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"},
- },
- // Network Solutions Certificate Authority
- // https://www.networksolutions.com/website-packages/index.jsp
- { { { 0x74, 0xf8, 0xa3, 0xc3, 0xef, 0xe7, 0xb3, 0x90, 0x06, 0x4b,
- 0x83, 0x90, 0x3c, 0x21, 0x64, 0x60, 0x20, 0xe5, 0xdf, 0xce } },
- {"1.3.6.1.4.1.782.1.2.1.8.1", ""},
- },
- // Network Solutions Certificate Authority (reissued certificate with
- // NotBefore of Jan 1 00:00:00 2011 GMT).
- // https://www.networksolutions.com/website-packages/index.jsp
- { { { 0x71, 0x89, 0x9a, 0x67, 0xbf, 0x33, 0xaf, 0x31, 0xbe, 0xfd,
- 0xc0, 0x71, 0xf8, 0xf7, 0x33, 0xb1, 0x83, 0x85, 0x63, 0x32 } },
- {"1.3.6.1.4.1.782.1.2.1.8.1", ""},
- },
- // QuoVadis Root CA 2
- // https://www.quovadis.bm/
- { { { 0xca, 0x3a, 0xfb, 0xcf, 0x12, 0x40, 0x36, 0x4b, 0x44, 0xb2,
- 0x16, 0x20, 0x88, 0x80, 0x48, 0x39, 0x19, 0x93, 0x7c, 0xf7 } },
- {"1.3.6.1.4.1.8024.0.2.100.1.2", ""},
- },
- // QuoVadis Root CA 2 G3
- // https://evsslicag3-v.quovadisglobal.com/
- { { { 0x09, 0x3c, 0x61, 0xf3, 0x8b, 0x8b, 0xdc, 0x7d, 0x55, 0xdf,
- 0x75, 0x38, 0x02, 0x05, 0x00, 0xe1, 0x25, 0xf5, 0xc8, 0x36 } },
- {"1.3.6.1.4.1.8024.0.2.100.1.2", ""},
- },
- // SecureTrust CA, SecureTrust Corporation
- // https://www.securetrust.com
- // https://www.trustwave.com/
- { { { 0x87, 0x82, 0xc6, 0xc3, 0x04, 0x35, 0x3b, 0xcf, 0xd2, 0x96,
- 0x92, 0xd2, 0x59, 0x3e, 0x7d, 0x44, 0xd9, 0x34, 0xff, 0x11 } },
- {"2.16.840.1.114404.1.1.2.4.1", ""},
- },
- // Secure Global CA, SecureTrust Corporation
- { { { 0x3a, 0x44, 0x73, 0x5a, 0xe5, 0x81, 0x90, 0x1f, 0x24, 0x86,
- 0x61, 0x46, 0x1e, 0x3b, 0x9c, 0xc4, 0x5f, 0xf5, 0x3a, 0x1b } },
- {"2.16.840.1.114404.1.1.2.4.1", ""},
- },
- // Security Communication RootCA1
- // https://www.secomtrust.net/contact/form.html
- { { { 0x36, 0xb1, 0x2b, 0x49, 0xf9, 0x81, 0x9e, 0xd7, 0x4c, 0x9e,
- 0xbc, 0x38, 0x0f, 0xc6, 0x56, 0x8f, 0x5d, 0xac, 0xb2, 0xf7 } },
- {"1.2.392.200091.100.721.1", ""},
- },
- // Security Communication EV RootCA1
- // https://www.secomtrust.net/contact/form.html
- { { { 0xfe, 0xb8, 0xc4, 0x32, 0xdc, 0xf9, 0x76, 0x9a, 0xce, 0xae,
- 0x3d, 0xd8, 0x90, 0x8f, 0xfd, 0x28, 0x86, 0x65, 0x64, 0x7d } },
- {"1.2.392.200091.100.721.1", ""},
- },
- // Staat der Nederlanden EV Root CA
- // https://pkioevssl-v.quovadisglobal.com/
- { { { 0x76, 0xe2, 0x7e, 0xc1, 0x4f, 0xdb, 0x82, 0xc1, 0xc0, 0xa6,
- 0x75, 0xb5, 0x05, 0xbe, 0x3d, 0x29, 0xb4, 0xed, 0xdb, 0xbb } },
- {"2.16.528.1.1003.1.2.7", ""},
- },
- // StartCom Certification Authority
- // https://www.startssl.com/
- { { { 0x3e, 0x2b, 0xf7, 0xf2, 0x03, 0x1b, 0x96, 0xf3, 0x8c, 0xe6,
- 0xc4, 0xd8, 0xa8, 0x5d, 0x3e, 0x2d, 0x58, 0x47, 0x6a, 0x0f } },
- {"1.3.6.1.4.1.23223.1.1.1", ""},
- },
- // Starfield Class 2 Certification Authority
- // https://www.starfieldtech.com/
- { { { 0xad, 0x7e, 0x1c, 0x28, 0xb0, 0x64, 0xef, 0x8f, 0x60, 0x03,
- 0x40, 0x20, 0x14, 0xc3, 0xd0, 0xe3, 0x37, 0x0e, 0xb5, 0x8a } },
- {"2.16.840.1.114414.1.7.23.3", ""},
- },
- // Starfield Root Certificate Authority - G2
- // https://valid.sfig2.catest.starfieldtech.com/
- { { { 0xb5, 0x1c, 0x06, 0x7c, 0xee, 0x2b, 0x0c, 0x3d, 0xf8, 0x55,
- 0xab, 0x2d, 0x92, 0xf4, 0xfe, 0x39, 0xd4, 0xe7, 0x0f, 0x0e } },
- {"2.16.840.1.114414.1.7.23.3", ""},
- },
- // Starfield Services Root Certificate Authority - G2
- // https://valid.sfsg2.catest.starfieldtech.com/
- { { { 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", ""},
- },
- // SwissSign Gold CA - G2
- // https://testevg2.swisssign.net/
- { { { 0xd8, 0xc5, 0x38, 0x8a, 0xb7, 0x30, 0x1b, 0x1b, 0x6e, 0xd4,
- 0x7a, 0xe6, 0x45, 0x25, 0x3a, 0x6f, 0x9f, 0x1a, 0x27, 0x61 } },
- {"2.16.756.1.89.1.2.1.1", ""},
- },
- // Swisscom Root EV CA 2
- // https://test-quarz-ev-ca-2.pre.swissdigicert.ch
- { { { 0xe7, 0xa1, 0x90, 0x29, 0xd3, 0xd5, 0x52, 0xdc, 0x0d, 0x0f,
- 0xc6, 0x92, 0xd3, 0xea, 0x88, 0x0d, 0x15, 0x2e, 0x1a, 0x6b } },
- {"2.16.756.1.83.21.0", ""},
- },
- // Thawte Premium Server CA
- // https://www.thawte.com/
- { { { 0x62, 0x7f, 0x8d, 0x78, 0x27, 0x65, 0x63, 0x99, 0xd2, 0x7d,
- 0x7f, 0x90, 0x44, 0xc9, 0xfe, 0xb3, 0xf3, 0x3e, 0xfa, 0x9a } },
- {"2.16.840.1.113733.1.7.48.1", ""},
- },
- // thawte Primary Root CA
- // https://www.thawte.com/
- { { { 0x91, 0xc6, 0xd6, 0xee, 0x3e, 0x8a, 0xc8, 0x63, 0x84, 0xe5,
- 0x48, 0xc2, 0x99, 0x29, 0x5c, 0x75, 0x6c, 0x81, 0x7b, 0x81 } },
- {"2.16.840.1.113733.1.7.48.1", ""},
- },
- // thawte Primary Root CA - G2
- { { { 0xaa, 0xdb, 0xbc, 0x22, 0x23, 0x8f, 0xc4, 0x01, 0xa1, 0x27,
- 0xbb, 0x38, 0xdd, 0xf4, 0x1d, 0xdb, 0x08, 0x9e, 0xf0, 0x12 } },
- {"2.16.840.1.113733.1.7.48.1", ""},
- },
- // thawte Primary Root CA - G3
- { { { 0xf1, 0x8b, 0x53, 0x8d, 0x1b, 0xe9, 0x03, 0xb6, 0xa6, 0xf0,
- 0x56, 0x43, 0x5b, 0x17, 0x15, 0x89, 0xca, 0xf3, 0x6b, 0xf2 } },
- {"2.16.840.1.113733.1.7.48.1", ""},
- },
- // TWCA Global Root CA
- // https://evssldemo3.twca.com.tw/index.html
- { { { 0x9C, 0xBB, 0x48, 0x53, 0xF6, 0xA4, 0xF6, 0xD3, 0x52, 0xA4,
- 0xE8, 0x32, 0x52, 0x55, 0x60, 0x13, 0xF5, 0xAD, 0xAF, 0x65 } },
- {"1.3.6.1.4.1.40869.1.1.22.3", ""},
- },
- // TWCA Root Certification Authority
- // https://evssldemo.twca.com.tw/index.html
- { { { 0xcf, 0x9e, 0x87, 0x6d, 0xd3, 0xeb, 0xfc, 0x42, 0x26, 0x97,
- 0xa3, 0xb5, 0xa3, 0x7a, 0xa0, 0x76, 0xa9, 0x06, 0x23, 0x48 } },
- {"1.3.6.1.4.1.40869.1.1.22.3", ""},
- },
- // T-TeleSec GlobalRoot Class 3
- // http://www.telesec.de/ / https://root-class3.test.telesec.de/
- { { { 0x55, 0xa6, 0x72, 0x3e, 0xcb, 0xf2, 0xec, 0xcd, 0xc3, 0x23,
- 0x74, 0x70, 0x19, 0x9d, 0x2a, 0xbe, 0x11, 0xe3, 0x81, 0xd1 } },
- {"1.3.6.1.4.1.7879.13.24.1", "" },
- },
- // USERTrust ECC Certification Authority
- // https://usertrustecccertificationauthority-ev.comodoca.com/
- { { { 0xd1, 0xcb, 0xca, 0x5d, 0xb2, 0xd5, 0x2a, 0x7f, 0x69, 0x3b,
- 0x67, 0x4d, 0xe5, 0xf0, 0x5a, 0x1d, 0x0c, 0x95, 0x7d, 0xf0 } },
- {"1.3.6.1.4.1.6449.1.2.1.5.1", ""},
- },
- // USERTrust RSA Certification Authority
- // https://usertrustrsacertificationauthority-ev.comodoca.com/
- { { { 0x2b, 0x8f, 0x1b, 0x57, 0x33, 0x0d, 0xbb, 0xa2, 0xd0, 0x7a,
- 0x6c, 0x51, 0xf7, 0x0e, 0xe9, 0x0d, 0xda, 0xb9, 0xad, 0x8e } },
- {"1.3.6.1.4.1.6449.1.2.1.5.1", ""},
- },
- // UTN-USERFirst-Hardware
- { { { 0x04, 0x83, 0xed, 0x33, 0x99, 0xac, 0x36, 0x08, 0x05, 0x87,
- 0x22, 0xed, 0xbc, 0x5e, 0x46, 0x00, 0xe3, 0xbe, 0xf9, 0xd7 } },
- {
- "1.3.6.1.4.1.6449.1.2.1.5.1",
- // This is the Network Solutions EV OID. However, this root
- // cross-certifies NetSol and so we need it here too.
- "1.3.6.1.4.1.782.1.2.1.8.1",
- },
- },
- // ValiCert Class 2 Policy Validation Authority
- { { { 0x31, 0x7a, 0x2a, 0xd0, 0x7f, 0x2b, 0x33, 0x5e, 0xf5, 0xa1,
- 0xc3, 0x4e, 0x4b, 0x57, 0xe8, 0xb7, 0xd8, 0xf1, 0xfc, 0xa6 } },
- {"2.16.840.1.114413.1.7.23.3", "2.16.840.1.114414.1.7.23.3"},
- },
- // VeriSign Class 3 Public Primary Certification Authority
- // https://www.verisign.com/
- { { { 0x74, 0x2c, 0x31, 0x92, 0xe6, 0x07, 0xe4, 0x24, 0xeb, 0x45,
- 0x49, 0x54, 0x2b, 0xe1, 0xbb, 0xc5, 0x3e, 0x61, 0x74, 0xe2 } },
- {"2.16.840.1.113733.1.7.23.6", ""},
- },
- // VeriSign Class 3 Public Primary Certification Authority - G4
- { { { 0x22, 0xD5, 0xD8, 0xDF, 0x8F, 0x02, 0x31, 0xD1, 0x8D, 0xF7,
- 0x9D, 0xB7, 0xCF, 0x8A, 0x2D, 0x64, 0xC9, 0x3F, 0x6C, 0x3A } },
- {"2.16.840.1.113733.1.7.23.6", ""},
- },
- // VeriSign Class 3 Public Primary Certification Authority - G5
- // https://www.verisign.com/
- { { { 0x4e, 0xb6, 0xd5, 0x78, 0x49, 0x9b, 0x1c, 0xcf, 0x5f, 0x58,
- 0x1e, 0xad, 0x56, 0xbe, 0x3d, 0x9b, 0x67, 0x44, 0xa5, 0xe5 } },
- {"2.16.840.1.113733.1.7.23.6", ""},
- },
- // VeriSign Universal Root Certification Authority
- { { { 0x36, 0x79, 0xca, 0x35, 0x66, 0x87, 0x72, 0x30, 0x4d, 0x30,
- 0xa5, 0xfb, 0x87, 0x3b, 0x0f, 0xa7, 0x7b, 0xb7, 0x0d, 0x54 } },
- {"2.16.840.1.113733.1.7.23.6", ""},
- },
- // Wells Fargo WellsSecure Public Root Certificate Authority
- // https://nerys.wellsfargo.com/test.html
- { { { 0xe7, 0xb4, 0xf6, 0x9d, 0x61, 0xec, 0x90, 0x69, 0xdb, 0x7e,
- 0x90, 0xa7, 0x40, 0x1a, 0x3c, 0xf4, 0x7d, 0x4f, 0xe8, 0xee } },
- {"2.16.840.1.114171.500.9", ""},
- },
- // XRamp Global Certification Authority
- { { { 0xb8, 0x01, 0x86, 0xd1, 0xeb, 0x9c, 0x86, 0xa5, 0x41, 0x04,
- 0xcf, 0x30, 0x54, 0xf3, 0x4c, 0x52, 0xb7, 0xe5, 0x58, 0xc6 } },
- {"2.16.840.1.114404.1.1.2.4.1", ""},
- }
-};
+ // AC Camerfirma S.A. Chambers of Commerce Root - 2008
+ // https://www.camerfirma.com
+ {
+ {{0x78, 0x6a, 0x74, 0xac, 0x76, 0xab, 0x14, 0x7f, 0x9c, 0x6a,
+ 0x30, 0x50, 0xba, 0x9e, 0xa8, 0x7e, 0xfe, 0x9a, 0xce, 0x3c}},
+ {
+ // AC Camerfirma uses the last two arcs to track how the private key
+ // is
+ // managed - the effective verification policy is the same.
+ "1.3.6.1.4.1.17326.10.14.2.1.2", "1.3.6.1.4.1.17326.10.14.2.2.2",
+ },
+ },
+ // AC Camerfirma S.A. Global Chambersign Root - 2008
+ // https://server2.camerfirma.com:8082
+ {
+ {{0x4a, 0xbd, 0xee, 0xec, 0x95, 0x0d, 0x35, 0x9c, 0x89, 0xae,
+ 0xc7, 0x52, 0xa1, 0x2c, 0x5b, 0x29, 0xf6, 0xd6, 0xaa, 0x0c}},
+ {
+ // AC Camerfirma uses the last two arcs to track how the private key
+ // is
+ // managed - the effective verification policy is the same.
+ "1.3.6.1.4.1.17326.10.8.12.1.2", "1.3.6.1.4.1.17326.10.8.12.2.2",
+ },
+ },
+ // AddTrust External CA Root
+ // https://addtrustexternalcaroot-ev.comodoca.com
+ {
+ {{0x02, 0xfa, 0xf3, 0xe2, 0x91, 0x43, 0x54, 0x68, 0x60, 0x78,
+ 0x57, 0x69, 0x4d, 0xf5, 0xe4, 0x5b, 0x68, 0x85, 0x18, 0x68}},
+ {
+ "1.3.6.1.4.1.6449.1.2.1.5.1",
+ // This is the Network Solutions EV OID. However, this root
+ // cross-certifies NetSol and so we need it here too.
+ "1.3.6.1.4.1.782.1.2.1.8.1",
+ },
+ },
+ // Actalis Authentication Root CA
+ // https://ssltest-a.actalis.it:8443
+ {
+ {{0xf3, 0x73, 0xb3, 0x87, 0x06, 0x5a, 0x28, 0x84, 0x8a, 0xf2,
+ 0xf3, 0x4a, 0xce, 0x19, 0x2b, 0xdd, 0xc7, 0x8e, 0x9c, 0xac}},
+ {"1.3.159.1.17.1", ""},
+ },
+ // AffirmTrust Commercial
+ // https://commercial.affirmtrust.com/
+ {
+ {{0xf9, 0xb5, 0xb6, 0x32, 0x45, 0x5f, 0x9c, 0xbe, 0xec, 0x57,
+ 0x5f, 0x80, 0xdc, 0xe9, 0x6e, 0x2c, 0xc7, 0xb2, 0x78, 0xb7}},
+ {"1.3.6.1.4.1.34697.2.1", ""},
+ },
+ // AffirmTrust Networking
+ // https://networking.affirmtrust.com:4431
+ {
+ {{0x29, 0x36, 0x21, 0x02, 0x8b, 0x20, 0xed, 0x02, 0xf5, 0x66,
+ 0xc5, 0x32, 0xd1, 0xd6, 0xed, 0x90, 0x9f, 0x45, 0x00, 0x2f}},
+ {"1.3.6.1.4.1.34697.2.2", ""},
+ },
+ // AffirmTrust Premium
+ // https://premium.affirmtrust.com:4432/
+ {
+ {{0xd8, 0xa6, 0x33, 0x2c, 0xe0, 0x03, 0x6f, 0xb1, 0x85, 0xf6,
+ 0x63, 0x4f, 0x7d, 0x6a, 0x06, 0x65, 0x26, 0x32, 0x28, 0x27}},
+ {"1.3.6.1.4.1.34697.2.3", ""},
+ },
+ // AffirmTrust Premium ECC
+ // https://premiumecc.affirmtrust.com:4433/
+ {
+ {{0xb8, 0x23, 0x6b, 0x00, 0x2f, 0x1d, 0x16, 0x86, 0x53, 0x01,
+ 0x55, 0x6c, 0x11, 0xa4, 0x37, 0xca, 0xeb, 0xff, 0xc3, 0xbb}},
+ {"1.3.6.1.4.1.34697.2.4", ""},
+ },
+ // Autoridad de Certificacion Firmaprofesional CIF A62634068
+ // https://publifirma.firmaprofesional.com/
+ {{{0xae, 0xc5, 0xfb, 0x3f, 0xc8, 0xe1, 0xbf, 0xc4, 0xe5, 0x4f,
+ 0x03, 0x07, 0x5a, 0x9a, 0xe8, 0x00, 0xb7, 0xf7, 0xb6, 0xfa}},
+ {"1.3.6.1.4.1.13177.10.1.3.10", ""}},
+ // Baltimore CyberTrust Root
+ // https://secure.omniroot.com/repository/
+ {
+ {{0xd4, 0xde, 0x20, 0xd0, 0x5e, 0x66, 0xfc, 0x53, 0xfe, 0x1a,
+ 0x50, 0x88, 0x2c, 0x78, 0xdb, 0x28, 0x52, 0xca, 0xe4, 0x74}},
+ {"1.3.6.1.4.1.6334.1.100.1", ""},
+ },
+ // Buypass Class 3 CA 1
+ // https://valid.evident.ca13.ssl.buypass.no/
+ {
+ {{0x61, 0x57, 0x3A, 0x11, 0xDF, 0x0E, 0xD8, 0x7E, 0xD5, 0x92,
+ 0x65, 0x22, 0xEA, 0xD0, 0x56, 0xD7, 0x44, 0xB3, 0x23, 0x71}},
+ {"2.16.578.1.26.1.3.3", ""},
+ },
+ // Buypass Class 3 Root CA
+ // https://valid.evident.ca23.ssl.buypass.no/
+ {
+ {{0xDA, 0xFA, 0xF7, 0xFA, 0x66, 0x84, 0xEC, 0x06, 0x8F, 0x14,
+ 0x50, 0xBD, 0xC7, 0xC2, 0x81, 0xA5, 0xBC, 0xA9, 0x64, 0x57}},
+ {"2.16.578.1.26.1.3.3", ""},
+ },
+ // CA 沃通根证书
+ // https://root2evtest.wosign.com/
+ {
+ {{0x16, 0x32, 0x47, 0x8d, 0x89, 0xf9, 0x21, 0x3a, 0x92, 0x00,
+ 0x85, 0x63, 0xf5, 0xa4, 0xa7, 0xd3, 0x12, 0x40, 0x8a, 0xd6}},
+ {"1.3.6.1.4.1.36305.2", ""},
+ },
+ // Certification Authority of WoSign
+ // https://root1evtest.wosign.com/
+ {
+ {{0xb9, 0x42, 0x94, 0xbf, 0x91, 0xea, 0x8f, 0xb6, 0x4b, 0xe6,
+ 0x10, 0x97, 0xc7, 0xfb, 0x00, 0x13, 0x59, 0xb6, 0x76, 0xcb}},
+ {"1.3.6.1.4.1.36305.2", ""},
+ },
+ // CertPlus Class 2 Primary CA (KEYNECTIS)
+ // https://www.keynectis.com/
+ {
+ {{0x74, 0x20, 0x74, 0x41, 0x72, 0x9c, 0xdd, 0x92, 0xec, 0x79,
+ 0x31, 0xd8, 0x23, 0x10, 0x8d, 0xc2, 0x81, 0x92, 0xe2, 0xbb}},
+ {"1.3.6.1.4.1.22234.2.5.2.3.1", ""},
+ },
+ // Certum Trusted Network CA
+ // https://juice.certum.pl/
+ {
+ {{0x07, 0xe0, 0x32, 0xe0, 0x20, 0xb7, 0x2c, 0x3f, 0x19, 0x2f,
+ 0x06, 0x28, 0xa2, 0x59, 0x3a, 0x19, 0xa7, 0x0f, 0x06, 0x9e}},
+ {"1.2.616.1.113527.2.5.1.1", ""},
+ },
+ // China Internet Network Information Center EV Certificates Root
+ // https://evdemo.cnnic.cn/
+ {
+ {{0x4F, 0x99, 0xAA, 0x93, 0xFB, 0x2B, 0xD1, 0x37, 0x26, 0xA1,
+ 0x99, 0x4A, 0xCE, 0x7F, 0xF0, 0x05, 0xF2, 0x93, 0x5D, 0x1E}},
+ {"1.3.6.1.4.1.29836.1.10", ""},
+ },
+ // COMODO Certification Authority
+ // https://secure.comodo.com/
+ {
+ {{0x66, 0x31, 0xbf, 0x9e, 0xf7, 0x4f, 0x9e, 0xb6, 0xc9, 0xd5,
+ 0xa6, 0x0c, 0xba, 0x6a, 0xbe, 0xd1, 0xf7, 0xbd, 0xef, 0x7b}},
+ {"1.3.6.1.4.1.6449.1.2.1.5.1", ""},
+ },
+ // COMODO Certification Authority (reissued certificate with NotBefore of
+ // Jan 1 00:00:00 2011 GMT)
+ // https://secure.comodo.com/
+ {
+ {{0xee, 0x86, 0x93, 0x87, 0xff, 0xfd, 0x83, 0x49, 0xab, 0x5a,
+ 0xd1, 0x43, 0x22, 0x58, 0x87, 0x89, 0xa4, 0x57, 0xb0, 0x12}},
+ {"1.3.6.1.4.1.6449.1.2.1.5.1", ""},
+ },
+ // COMODO ECC Certification Authority
+ // https://comodoecccertificationauthority-ev.comodoca.com/
+ {
+ {{0x9f, 0x74, 0x4e, 0x9f, 0x2b, 0x4d, 0xba, 0xec, 0x0f, 0x31,
+ 0x2c, 0x50, 0xb6, 0x56, 0x3b, 0x8e, 0x2d, 0x93, 0xc3, 0x11}},
+ {"1.3.6.1.4.1.6449.1.2.1.5.1", ""},
+ },
+ // COMODO RSA Certification Authority
+ // https://comodorsacertificationauthority-ev.comodoca.com/
+ {
+ {{0xaf, 0xe5, 0xd2, 0x44, 0xa8, 0xd1, 0x19, 0x42, 0x30, 0xff,
+ 0x47, 0x9f, 0xe2, 0xf8, 0x97, 0xbb, 0xcd, 0x7a, 0x8c, 0xb4}},
+ {"1.3.6.1.4.1.6449.1.2.1.5.1", ""},
+ },
+ // Cybertrust Global Root
+ // https://evup.cybertrust.ne.jp/ctj-ev-upgrader/evseal.gif
+ {
+ {{0x5f, 0x43, 0xe5, 0xb1, 0xbf, 0xf8, 0x78, 0x8c, 0xac, 0x1c,
+ 0xc7, 0xca, 0x4a, 0x9a, 0xc6, 0x22, 0x2b, 0xcc, 0x34, 0xc6}},
+ {"1.3.6.1.4.1.6334.1.100.1", ""},
+ },
+ // DigiCert High Assurance EV Root CA
+ // https://www.digicert.com
+ {
+ {{0x5f, 0xb7, 0xee, 0x06, 0x33, 0xe2, 0x59, 0xdb, 0xad, 0x0c,
+ 0x4c, 0x9a, 0xe6, 0xd3, 0x8f, 0x1a, 0x61, 0xc7, 0xdc, 0x25}},
+ {"2.16.840.1.114412.2.1", ""},
+ },
+ // D-TRUST Root Class 3 CA 2 EV 2009
+ // https://certdemo-ev-valid.ssl.d-trust.net/
+ {
+ {{0x96, 0xc9, 0x1b, 0x0b, 0x95, 0xb4, 0x10, 0x98, 0x42, 0xfa,
+ 0xd0, 0xd8, 0x22, 0x79, 0xfe, 0x60, 0xfa, 0xb9, 0x16, 0x83}},
+ {"1.3.6.1.4.1.4788.2.202.1", ""},
+ },
+ // Entrust.net Secure Server Certification Authority
+ // https://www.entrust.net/
+ {
+ {{0x99, 0xa6, 0x9b, 0xe6, 0x1a, 0xfe, 0x88, 0x6b, 0x4d, 0x2b,
+ 0x82, 0x00, 0x7c, 0xb8, 0x54, 0xfc, 0x31, 0x7e, 0x15, 0x39}},
+ {"2.16.840.1.114028.10.1.2", ""},
+ },
+ // Entrust Root Certification Authority
+ // https://www.entrust.net/
+ {
+ {{0xb3, 0x1e, 0xb1, 0xb7, 0x40, 0xe3, 0x6c, 0x84, 0x02, 0xda,
+ 0xdc, 0x37, 0xd4, 0x4d, 0xf5, 0xd4, 0x67, 0x49, 0x52, 0xf9}},
+ {"2.16.840.1.114028.10.1.2", ""},
+ },
+ // Equifax Secure Certificate Authority (GeoTrust)
+ // https://www.geotrust.com/
+ {
+ {{0xd2, 0x32, 0x09, 0xad, 0x23, 0xd3, 0x14, 0x23, 0x21, 0x74,
+ 0xe4, 0x0d, 0x7f, 0x9d, 0x62, 0x13, 0x97, 0x86, 0x63, 0x3a}},
+ {"1.3.6.1.4.1.14370.1.6", ""},
+ },
+ // E-Tugra Certification Authority
+ // https://sslev.e-tugra.com.tr
+ {
+ {{0x51, 0xC6, 0xE7, 0x08, 0x49, 0x06, 0x6E, 0xF3, 0x92, 0xD4,
+ 0x5C, 0xA0, 0x0D, 0x6D, 0xA3, 0x62, 0x8F, 0xC3, 0x52, 0x39}},
+ {"2.16.792.3.0.4.1.1.4", ""},
+ },
+ // GeoTrust Primary Certification Authority
+ // https://www.geotrust.com/
+ {
+ {{0x32, 0x3c, 0x11, 0x8e, 0x1b, 0xf7, 0xb8, 0xb6, 0x52, 0x54,
+ 0xe2, 0xe2, 0x10, 0x0d, 0xd6, 0x02, 0x90, 0x37, 0xf0, 0x96}},
+ {"1.3.6.1.4.1.14370.1.6", ""},
+ },
+ // GeoTrust Primary Certification Authority - G2
+ {
+ {{0x8d, 0x17, 0x84, 0xd5, 0x37, 0xf3, 0x03, 0x7d, 0xec, 0x70,
+ 0xfe, 0x57, 0x8b, 0x51, 0x9a, 0x99, 0xe6, 0x10, 0xd7, 0xb0}},
+ {"1.3.6.1.4.1.14370.1.6", ""},
+ },
+ // GeoTrust Primary Certification Authority - G3
+ {
+ {{0x03, 0x9e, 0xed, 0xb8, 0x0b, 0xe7, 0xa0, 0x3c, 0x69, 0x53,
+ 0x89, 0x3b, 0x20, 0xd2, 0xd9, 0x32, 0x3a, 0x4c, 0x2a, 0xfd}},
+ {"1.3.6.1.4.1.14370.1.6", ""},
+ },
+ // GlobalSign Root CA - R2
+ // https://www.globalsign.com/
+ {
+ {{0x75, 0xe0, 0xab, 0xb6, 0x13, 0x85, 0x12, 0x27, 0x1c, 0x04,
+ 0xf8, 0x5f, 0xdd, 0xde, 0x38, 0xe4, 0xb7, 0x24, 0x2e, 0xfe}},
+ {"1.3.6.1.4.1.4146.1.1", ""},
+ },
+ // GlobalSign Root CA
+ {
+ {{0xb1, 0xbc, 0x96, 0x8b, 0xd4, 0xf4, 0x9d, 0x62, 0x2a, 0xa8,
+ 0x9a, 0x81, 0xf2, 0x15, 0x01, 0x52, 0xa4, 0x1d, 0x82, 0x9c}},
+ {"1.3.6.1.4.1.4146.1.1", ""},
+ },
+ // GlobalSign Root CA - R3
+ // https://2029.globalsign.com/
+ {
+ {{0xd6, 0x9b, 0x56, 0x11, 0x48, 0xf0, 0x1c, 0x77, 0xc5, 0x45,
+ 0x78, 0xc1, 0x09, 0x26, 0xdf, 0x5b, 0x85, 0x69, 0x76, 0xad}},
+ {"1.3.6.1.4.1.4146.1.1", ""},
+ },
+ // GlobalSign ECC Root CA - R4
+ // https://2038r4.globalsign.com
+ {
+ {{0x69, 0x69, 0x56, 0x2e, 0x40, 0x80, 0xf4, 0x24, 0xa1, 0xe7,
+ 0x19, 0x9f, 0x14, 0xba, 0xf3, 0xee, 0x58, 0xab, 0x6a, 0xbb}},
+ {"1.3.6.1.4.1.4146.1.1", ""},
+ },
+ // GlobalSign ECC Root CA - R5
+ // https://2038r5.globalsign.com/
+ {{{0x1f, 0x24, 0xc6, 0x30, 0xcd, 0xa4, 0x18, 0xef, 0x20, 0x69,
+ 0xff, 0xad, 0x4f, 0xdd, 0x5f, 0x46, 0x3a, 0x1b, 0x69, 0xaa}},
+ {"1.3.6.1.4.1.4146.1.1", ""}},
+ // Go Daddy Class 2 Certification Authority
+ // https://www.godaddy.com/
+ {
+ {{0x27, 0x96, 0xba, 0xe6, 0x3f, 0x18, 0x01, 0xe2, 0x77, 0x26,
+ 0x1b, 0xa0, 0xd7, 0x77, 0x70, 0x02, 0x8f, 0x20, 0xee, 0xe4}},
+ {"2.16.840.1.114413.1.7.23.3", ""},
+ },
+ // Go Daddy Root Certificate Authority - G2
+ // https://valid.gdig2.catest.godaddy.com/
+ {
+ {{0x47, 0xbe, 0xab, 0xc9, 0x22, 0xea, 0xe8, 0x0e, 0x78, 0x78,
+ 0x34, 0x62, 0xa7, 0x9f, 0x45, 0xc2, 0x54, 0xfd, 0xe6, 0x8b}},
+ {"2.16.840.1.114413.1.7.23.3", ""},
+ },
+ // GTE CyberTrust Global Root
+ // https://www.cybertrust.ne.jp/
+ {
+ {{0x97, 0x81, 0x79, 0x50, 0xd8, 0x1c, 0x96, 0x70, 0xcc, 0x34,
+ 0xd8, 0x09, 0xcf, 0x79, 0x44, 0x31, 0x36, 0x7e, 0xf4, 0x74}},
+ {"1.3.6.1.4.1.6334.1.100.1", ""},
+ },
+ // Izenpe.com - SHA256 root
+ // The first OID is for businesses and the second for government entities.
+ // These are the test sites, respectively:
+ // https://servicios.izenpe.com
+ // https://servicios1.izenpe.com
+ {
+ {{0x2f, 0x78, 0x3d, 0x25, 0x52, 0x18, 0xa7, 0x4a, 0x65, 0x39,
+ 0x71, 0xb5, 0x2c, 0xa2, 0x9c, 0x45, 0x15, 0x6f, 0xe9, 0x19}},
+ {"1.3.6.1.4.1.14777.6.1.1", "1.3.6.1.4.1.14777.6.1.2"},
+ },
+ // Izenpe.com - SHA1 root
+ // Windows XP finds this, SHA1, root instead. The policy OIDs are the same
+ // as for the SHA256 root, above.
+ {
+ {{0x30, 0x77, 0x9e, 0x93, 0x15, 0x02, 0x2e, 0x94, 0x85, 0x6a,
+ 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"},
+ },
+ // Network Solutions Certificate Authority
+ // https://www.networksolutions.com/website-packages/index.jsp
+ {
+ {{0x74, 0xf8, 0xa3, 0xc3, 0xef, 0xe7, 0xb3, 0x90, 0x06, 0x4b,
+ 0x83, 0x90, 0x3c, 0x21, 0x64, 0x60, 0x20, 0xe5, 0xdf, 0xce}},
+ {"1.3.6.1.4.1.782.1.2.1.8.1", ""},
+ },
+ // Network Solutions Certificate Authority (reissued certificate with
+ // NotBefore of Jan 1 00:00:00 2011 GMT).
+ // https://www.networksolutions.com/website-packages/index.jsp
+ {
+ {{0x71, 0x89, 0x9a, 0x67, 0xbf, 0x33, 0xaf, 0x31, 0xbe, 0xfd,
+ 0xc0, 0x71, 0xf8, 0xf7, 0x33, 0xb1, 0x83, 0x85, 0x63, 0x32}},
+ {"1.3.6.1.4.1.782.1.2.1.8.1", ""},
+ },
+ // QuoVadis Root CA 2
+ // https://www.quovadis.bm/
+ {
+ {{0xca, 0x3a, 0xfb, 0xcf, 0x12, 0x40, 0x36, 0x4b, 0x44, 0xb2,
+ 0x16, 0x20, 0x88, 0x80, 0x48, 0x39, 0x19, 0x93, 0x7c, 0xf7}},
+ {"1.3.6.1.4.1.8024.0.2.100.1.2", ""},
+ },
+ // QuoVadis Root CA 2 G3
+ // https://evsslicag3-v.quovadisglobal.com/
+ {
+ {{0x09, 0x3c, 0x61, 0xf3, 0x8b, 0x8b, 0xdc, 0x7d, 0x55, 0xdf,
+ 0x75, 0x38, 0x02, 0x05, 0x00, 0xe1, 0x25, 0xf5, 0xc8, 0x36}},
+ {"1.3.6.1.4.1.8024.0.2.100.1.2", ""},
+ },
+ // SecureTrust CA, SecureTrust Corporation
+ // https://www.securetrust.com
+ // https://www.trustwave.com/
+ {
+ {{0x87, 0x82, 0xc6, 0xc3, 0x04, 0x35, 0x3b, 0xcf, 0xd2, 0x96,
+ 0x92, 0xd2, 0x59, 0x3e, 0x7d, 0x44, 0xd9, 0x34, 0xff, 0x11}},
+ {"2.16.840.1.114404.1.1.2.4.1", ""},
+ },
+ // Secure Global CA, SecureTrust Corporation
+ {
+ {{0x3a, 0x44, 0x73, 0x5a, 0xe5, 0x81, 0x90, 0x1f, 0x24, 0x86,
+ 0x61, 0x46, 0x1e, 0x3b, 0x9c, 0xc4, 0x5f, 0xf5, 0x3a, 0x1b}},
+ {"2.16.840.1.114404.1.1.2.4.1", ""},
+ },
+ // Security Communication RootCA1
+ // https://www.secomtrust.net/contact/form.html
+ {
+ {{0x36, 0xb1, 0x2b, 0x49, 0xf9, 0x81, 0x9e, 0xd7, 0x4c, 0x9e,
+ 0xbc, 0x38, 0x0f, 0xc6, 0x56, 0x8f, 0x5d, 0xac, 0xb2, 0xf7}},
+ {"1.2.392.200091.100.721.1", ""},
+ },
+ // Security Communication EV RootCA1
+ // https://www.secomtrust.net/contact/form.html
+ {
+ {{0xfe, 0xb8, 0xc4, 0x32, 0xdc, 0xf9, 0x76, 0x9a, 0xce, 0xae,
+ 0x3d, 0xd8, 0x90, 0x8f, 0xfd, 0x28, 0x86, 0x65, 0x64, 0x7d}},
+ {"1.2.392.200091.100.721.1", ""},
+ },
+ // Security Communication EV RootCA2
+ // https://www.secomtrust.net/contact/form.html
+ {
+ {{0x5F, 0x3B, 0x8C, 0xF2, 0xF8, 0x10, 0xB3, 0x7D, 0x78, 0xB4,
+ 0xCE, 0xEC, 0x19, 0x19, 0xC3, 0x73, 0x34, 0xB9, 0xC7, 0x74}},
+ {"1.2.392.200091.100.721.1", ""},
+ },
+ // Staat der Nederlanden EV Root CA
+ // https://pkioevssl-v.quovadisglobal.com/
+ {
+ {{0x76, 0xe2, 0x7e, 0xc1, 0x4f, 0xdb, 0x82, 0xc1, 0xc0, 0xa6,
+ 0x75, 0xb5, 0x05, 0xbe, 0x3d, 0x29, 0xb4, 0xed, 0xdb, 0xbb}},
+ {"2.16.528.1.1003.1.2.7", ""},
+ },
+ // StartCom Certification Authority
+ // https://www.startssl.com/
+ {
+ {{0x3e, 0x2b, 0xf7, 0xf2, 0x03, 0x1b, 0x96, 0xf3, 0x8c, 0xe6,
+ 0xc4, 0xd8, 0xa8, 0x5d, 0x3e, 0x2d, 0x58, 0x47, 0x6a, 0x0f}},
+ {"1.3.6.1.4.1.23223.1.1.1", ""},
+ },
+ // Starfield Class 2 Certification Authority
+ // https://www.starfieldtech.com/
+ {
+ {{0xad, 0x7e, 0x1c, 0x28, 0xb0, 0x64, 0xef, 0x8f, 0x60, 0x03,
+ 0x40, 0x20, 0x14, 0xc3, 0xd0, 0xe3, 0x37, 0x0e, 0xb5, 0x8a}},
+ {"2.16.840.1.114414.1.7.23.3", ""},
+ },
+ // Starfield Root Certificate Authority - G2
+ // https://valid.sfig2.catest.starfieldtech.com/
+ {
+ {{0xb5, 0x1c, 0x06, 0x7c, 0xee, 0x2b, 0x0c, 0x3d, 0xf8, 0x55,
+ 0xab, 0x2d, 0x92, 0xf4, 0xfe, 0x39, 0xd4, 0xe7, 0x0f, 0x0e}},
+ {"2.16.840.1.114414.1.7.23.3", ""},
+ },
+ // Starfield Services Root Certificate Authority - G2
+ // https://valid.sfsg2.catest.starfieldtech.com/
+ {
+ {{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", ""},
+ },
+ // SwissSign Gold CA - G2
+ // https://testevg2.swisssign.net/
+ {
+ {{0xd8, 0xc5, 0x38, 0x8a, 0xb7, 0x30, 0x1b, 0x1b, 0x6e, 0xd4,
+ 0x7a, 0xe6, 0x45, 0x25, 0x3a, 0x6f, 0x9f, 0x1a, 0x27, 0x61}},
+ {"2.16.756.1.89.1.2.1.1", ""},
+ },
+ // Swisscom Root EV CA 2
+ // https://test-quarz-ev-ca-2.pre.swissdigicert.ch
+ {
+ {{0xe7, 0xa1, 0x90, 0x29, 0xd3, 0xd5, 0x52, 0xdc, 0x0d, 0x0f,
+ 0xc6, 0x92, 0xd3, 0xea, 0x88, 0x0d, 0x15, 0x2e, 0x1a, 0x6b}},
+ {"2.16.756.1.83.21.0", ""},
+ },
+ // Thawte Premium Server CA
+ // https://www.thawte.com/
+ {
+ {{0x62, 0x7f, 0x8d, 0x78, 0x27, 0x65, 0x63, 0x99, 0xd2, 0x7d,
+ 0x7f, 0x90, 0x44, 0xc9, 0xfe, 0xb3, 0xf3, 0x3e, 0xfa, 0x9a}},
+ {"2.16.840.1.113733.1.7.48.1", ""},
+ },
+ // thawte Primary Root CA
+ // https://www.thawte.com/
+ {
+ {{0x91, 0xc6, 0xd6, 0xee, 0x3e, 0x8a, 0xc8, 0x63, 0x84, 0xe5,
+ 0x48, 0xc2, 0x99, 0x29, 0x5c, 0x75, 0x6c, 0x81, 0x7b, 0x81}},
+ {"2.16.840.1.113733.1.7.48.1", ""},
+ },
+ // thawte Primary Root CA - G2
+ {
+ {{0xaa, 0xdb, 0xbc, 0x22, 0x23, 0x8f, 0xc4, 0x01, 0xa1, 0x27,
+ 0xbb, 0x38, 0xdd, 0xf4, 0x1d, 0xdb, 0x08, 0x9e, 0xf0, 0x12}},
+ {"2.16.840.1.113733.1.7.48.1", ""},
+ },
+ // thawte Primary Root CA - G3
+ {
+ {{0xf1, 0x8b, 0x53, 0x8d, 0x1b, 0xe9, 0x03, 0xb6, 0xa6, 0xf0,
+ 0x56, 0x43, 0x5b, 0x17, 0x15, 0x89, 0xca, 0xf3, 0x6b, 0xf2}},
+ {"2.16.840.1.113733.1.7.48.1", ""},
+ },
+ // TWCA Global Root CA
+ // https://evssldemo3.twca.com.tw/index.html
+ {
+ {{0x9C, 0xBB, 0x48, 0x53, 0xF6, 0xA4, 0xF6, 0xD3, 0x52, 0xA4,
+ 0xE8, 0x32, 0x52, 0x55, 0x60, 0x13, 0xF5, 0xAD, 0xAF, 0x65}},
+ {"1.3.6.1.4.1.40869.1.1.22.3", ""},
+ },
+ // TWCA Root Certification Authority
+ // https://evssldemo.twca.com.tw/index.html
+ {
+ {{0xcf, 0x9e, 0x87, 0x6d, 0xd3, 0xeb, 0xfc, 0x42, 0x26, 0x97,
+ 0xa3, 0xb5, 0xa3, 0x7a, 0xa0, 0x76, 0xa9, 0x06, 0x23, 0x48}},
+ {"1.3.6.1.4.1.40869.1.1.22.3", ""},
+ },
+ // T-TeleSec GlobalRoot Class 3
+ // http://www.telesec.de/ / https://root-class3.test.telesec.de/
+ {
+ {{0x55, 0xa6, 0x72, 0x3e, 0xcb, 0xf2, 0xec, 0xcd, 0xc3, 0x23,
+ 0x74, 0x70, 0x19, 0x9d, 0x2a, 0xbe, 0x11, 0xe3, 0x81, 0xd1}},
+ {"1.3.6.1.4.1.7879.13.24.1", ""},
+ },
+ // USERTrust ECC Certification Authority
+ // https://usertrustecccertificationauthority-ev.comodoca.com/
+ {
+ {{0xd1, 0xcb, 0xca, 0x5d, 0xb2, 0xd5, 0x2a, 0x7f, 0x69, 0x3b,
+ 0x67, 0x4d, 0xe5, 0xf0, 0x5a, 0x1d, 0x0c, 0x95, 0x7d, 0xf0}},
+ {"1.3.6.1.4.1.6449.1.2.1.5.1", ""},
+ },
+ // USERTrust RSA Certification Authority
+ // https://usertrustrsacertificationauthority-ev.comodoca.com/
+ {
+ {{0x2b, 0x8f, 0x1b, 0x57, 0x33, 0x0d, 0xbb, 0xa2, 0xd0, 0x7a,
+ 0x6c, 0x51, 0xf7, 0x0e, 0xe9, 0x0d, 0xda, 0xb9, 0xad, 0x8e}},
+ {"1.3.6.1.4.1.6449.1.2.1.5.1", ""},
+ },
+ // UTN-USERFirst-Hardware
+ {
+ {{0x04, 0x83, 0xed, 0x33, 0x99, 0xac, 0x36, 0x08, 0x05, 0x87,
+ 0x22, 0xed, 0xbc, 0x5e, 0x46, 0x00, 0xe3, 0xbe, 0xf9, 0xd7}},
+ {
+ "1.3.6.1.4.1.6449.1.2.1.5.1",
+ // This is the Network Solutions EV OID. However, this root
+ // cross-certifies NetSol and so we need it here too.
+ "1.3.6.1.4.1.782.1.2.1.8.1",
+ },
+ },
+ // ValiCert Class 2 Policy Validation Authority
+ {
+ {{0x31, 0x7a, 0x2a, 0xd0, 0x7f, 0x2b, 0x33, 0x5e, 0xf5, 0xa1,
+ 0xc3, 0x4e, 0x4b, 0x57, 0xe8, 0xb7, 0xd8, 0xf1, 0xfc, 0xa6}},
+ {"2.16.840.1.114413.1.7.23.3", "2.16.840.1.114414.1.7.23.3"},
+ },
+ // VeriSign Class 3 Public Primary Certification Authority
+ // https://www.verisign.com/
+ {
+ {{0x74, 0x2c, 0x31, 0x92, 0xe6, 0x07, 0xe4, 0x24, 0xeb, 0x45,
+ 0x49, 0x54, 0x2b, 0xe1, 0xbb, 0xc5, 0x3e, 0x61, 0x74, 0xe2}},
+ {"2.16.840.1.113733.1.7.23.6", ""},
+ },
+ // VeriSign Class 3 Public Primary Certification Authority - G4
+ {
+ {{0x22, 0xD5, 0xD8, 0xDF, 0x8F, 0x02, 0x31, 0xD1, 0x8D, 0xF7,
+ 0x9D, 0xB7, 0xCF, 0x8A, 0x2D, 0x64, 0xC9, 0x3F, 0x6C, 0x3A}},
+ {"2.16.840.1.113733.1.7.23.6", ""},
+ },
+ // VeriSign Class 3 Public Primary Certification Authority - G5
+ // https://www.verisign.com/
+ {
+ {{0x4e, 0xb6, 0xd5, 0x78, 0x49, 0x9b, 0x1c, 0xcf, 0x5f, 0x58,
+ 0x1e, 0xad, 0x56, 0xbe, 0x3d, 0x9b, 0x67, 0x44, 0xa5, 0xe5}},
+ {"2.16.840.1.113733.1.7.23.6", ""},
+ },
+ // VeriSign Universal Root Certification Authority
+ {
+ {{0x36, 0x79, 0xca, 0x35, 0x66, 0x87, 0x72, 0x30, 0x4d, 0x30,
+ 0xa5, 0xfb, 0x87, 0x3b, 0x0f, 0xa7, 0x7b, 0xb7, 0x0d, 0x54}},
+ {"2.16.840.1.113733.1.7.23.6", ""},
+ },
+ // Wells Fargo WellsSecure Public Root Certificate Authority
+ // https://nerys.wellsfargo.com/test.html
+ {
+ {{0xe7, 0xb4, 0xf6, 0x9d, 0x61, 0xec, 0x90, 0x69, 0xdb, 0x7e,
+ 0x90, 0xa7, 0x40, 0x1a, 0x3c, 0xf4, 0x7d, 0x4f, 0xe8, 0xee}},
+ {"2.16.840.1.114171.500.9", ""},
+ },
+ // XRamp Global Certification Authority
+ {
+ {{0xb8, 0x01, 0x86, 0xd1, 0xeb, 0x9c, 0x86, 0xa5, 0x41, 0x04,
+ 0xcf, 0x30, 0x54, 0xf3, 0x4c, 0x52, 0xb7, 0xe5, 0x58, 0xc6}},
+ {"2.16.840.1.114404.1.1.2.4.1", ""},
+ }};
#endif // defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_WIN)
@@ -503,7 +582,7 @@ EVRootCAMetadata* EVRootCAMetadata::GetInstance() {
return g_ev_root_ca_metadata.Pointer();
}
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
bool EVRootCAMetadata::IsEVPolicyOID(PolicyOID policy_oid) const {
return policy_oids_.find(policy_oid) != policy_oids_.end();
}
@@ -649,7 +728,7 @@ bool EVRootCAMetadata::RemoveEVCA(const SHA1HashValue& fingerprint) {
EVRootCAMetadata::EVRootCAMetadata() {
// Constructs the object from the raw metadata in ev_root_ca_metadata.
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
crypto::EnsureNSSInit();
for (size_t i = 0; i < arraysize(ev_root_ca_metadata); i++) {
diff --git a/chromium/net/cert/ev_root_ca_metadata.h b/chromium/net/cert/ev_root_ca_metadata.h
index 508e188b132..967dcbbdd48 100644
--- a/chromium/net/cert/ev_root_ca_metadata.h
+++ b/chromium/net/cert/ev_root_ca_metadata.h
@@ -7,7 +7,7 @@
#include "build/build_config.h"
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
#include <secoidt.h>
#endif
@@ -31,7 +31,7 @@ namespace net {
// extended-validation (EV) certificates.
class NET_EXPORT_PRIVATE EVRootCAMetadata {
public:
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
typedef SECOidTag PolicyOID;
#elif defined(OS_WIN)
typedef const char* PolicyOID;
@@ -39,7 +39,7 @@ class NET_EXPORT_PRIVATE EVRootCAMetadata {
static EVRootCAMetadata* GetInstance();
-#if defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER) || defined(OS_WIN)
// Returns true if policy_oid is an EV policy OID of some root CA.
bool IsEVPolicyOID(PolicyOID policy_oid) const;
@@ -64,7 +64,7 @@ class NET_EXPORT_PRIVATE EVRootCAMetadata {
EVRootCAMetadata();
~EVRootCAMetadata();
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
typedef std::map<SHA1HashValue, std::vector<PolicyOID>,
SHA1HashValueLessThan> PolicyOIDMap;
diff --git a/chromium/net/cert/internal/certificate_policies.cc b/chromium/net/cert/internal/certificate_policies.cc
index 4ff3a3a6595..7fa5dacf060 100644
--- a/chromium/net/cert/internal/certificate_policies.cc
+++ b/chromium/net/cert/internal/certificate_policies.cc
@@ -56,9 +56,8 @@ bool ParsePolicyQualifiers(const der::Input& policy_oid,
// RFC 5280 section 4.2.1.4: When qualifiers are used with the special
// policy anyPolicy, they MUST be limited to the qualifiers identified in
// this section.
- if (policy_oid.Equals(AnyPolicy()) &&
- !qualifier_oid.Equals(CpsPointerId()) &&
- !qualifier_oid.Equals(UserNoticeId())) {
+ if (policy_oid == AnyPolicy() && qualifier_oid != CpsPointerId() &&
+ qualifier_oid != UserNoticeId()) {
return false;
}
der::Tag tag;
@@ -152,7 +151,7 @@ bool ParseCertificatePoliciesExtension(const der::Input& extension_value,
std::lower_bound(policies->begin(), policies->end(), policy_oid);
// RFC 5280 section 4.2.1.4: A certificate policy OID MUST NOT appear more
// than once in a certificate policies extension.
- if (i != policies->end() && i->Equals(policy_oid))
+ if (i != policies->end() && *i == policy_oid)
return false;
policies->insert(i, policy_oid);
diff --git a/chromium/net/cert/internal/extended_key_usage_unittest.cc b/chromium/net/cert/internal/extended_key_usage_unittest.cc
index fd6ad5a1ff4..525698d3069 100644
--- a/chromium/net/cert/internal/extended_key_usage_unittest.cc
+++ b/chromium/net/cert/internal/extended_key_usage_unittest.cc
@@ -16,7 +16,7 @@ namespace {
// Helper method to check if an EKU is present in a std::vector of EKUs.
bool HasEKU(const std::vector<der::Input>& list, const der::Input& eku) {
for (const auto& oid : list) {
- if (oid.Equals(eku))
+ if (oid == eku)
return true;
}
return false;
@@ -62,7 +62,7 @@ TEST(ExtendedKeyUsageTest, RepeatedOid) {
EXPECT_TRUE(ParseEKUExtension(extension, &ekus));
EXPECT_EQ(2u, ekus.size());
for (const auto& eku : ekus) {
- EXPECT_TRUE(eku.Equals(ServerAuth()));
+ EXPECT_EQ(ServerAuth(), eku);
}
}
diff --git a/chromium/net/cert/internal/name_constraints.cc b/chromium/net/cert/internal/name_constraints.cc
index ade43a776ee..9141a02ddea 100644
--- a/chromium/net/cert/internal/name_constraints.cc
+++ b/chromium/net/cert/internal/name_constraints.cc
@@ -138,121 +138,96 @@ WARN_UNUSED_RESULT bool ParseGeneralName(
const der::Input& input,
ParseGeneralNameUnsupportedTypeBehavior unsupported_type_behavior,
ParseGeneralNameIPAddressType ip_address_type,
- NameConstraints::GeneralNames* subtrees) {
+ GeneralNames* subtrees) {
der::Parser parser(input);
der::Tag tag;
der::Input value;
if (!parser.ReadTagAndValue(&tag, &value))
return false;
- if (!der::IsContextSpecific(tag))
- return false;
GeneralNameTypes name_type = GENERAL_NAME_NONE;
- // GeneralName ::= CHOICE {
- switch (der::GetTagNumber(tag)) {
+ if (tag == der::ContextSpecificConstructed(0)) {
// otherName [0] OtherName,
- case 0:
- if (!der::IsConstructed(tag))
- return false;
- name_type = GENERAL_NAME_OTHER_NAME;
- break;
+ name_type = GENERAL_NAME_OTHER_NAME;
+ } else if (tag == der::ContextSpecificPrimitive(1)) {
// rfc822Name [1] IA5String,
- case 1:
- if (der::IsConstructed(tag))
- return false;
- name_type = GENERAL_NAME_RFC822_NAME;
- break;
+ name_type = GENERAL_NAME_RFC822_NAME;
+ } else if (tag == der::ContextSpecificPrimitive(2)) {
// dNSName [2] IA5String,
- case 2: {
- if (der::IsConstructed(tag))
- return false;
- name_type = GENERAL_NAME_DNS_NAME;
- const std::string s = value.AsString();
- if (!base::IsStringASCII(s))
- return false;
- subtrees->dns_names.push_back(s);
- break;
- }
+ name_type = GENERAL_NAME_DNS_NAME;
+ const std::string s = value.AsString();
+ if (!base::IsStringASCII(s))
+ return false;
+ subtrees->dns_names.push_back(s);
+ } else if (tag == der::ContextSpecificConstructed(3)) {
// x400Address [3] ORAddress,
- case 3:
- if (!der::IsConstructed(tag))
- return false;
- name_type = GENERAL_NAME_X400_ADDRESS;
- break;
+ name_type = GENERAL_NAME_X400_ADDRESS;
+ } else if (tag == der::ContextSpecificConstructed(4)) {
// directoryName [4] Name,
- case 4:
- if (!der::IsConstructed(tag))
- return false;
- name_type = GENERAL_NAME_DIRECTORY_NAME;
- subtrees->directory_names.push_back(std::vector<uint8_t>(
- value.UnsafeData(), value.UnsafeData() + value.Length()));
- break;
+ name_type = GENERAL_NAME_DIRECTORY_NAME;
+ // Name is a CHOICE { rdnSequence RDNSequence }, therefore the SEQUENCE
+ // tag is explicit. Remove it, since the name matching functions expect
+ // only the value portion.
+ der::Parser name_parser(value);
+ der::Input name_value;
+ if (!name_parser.ReadTag(der::kSequence, &name_value) || parser.HasMore())
+ return false;
+ subtrees->directory_names.push_back(
+ std::vector<uint8_t>(name_value.UnsafeData(),
+ name_value.UnsafeData() + name_value.Length()));
+ } else if (tag == der::ContextSpecificConstructed(5)) {
// ediPartyName [5] EDIPartyName,
- case 5:
- if (!der::IsConstructed(tag))
- return false;
- name_type = GENERAL_NAME_EDI_PARTY_NAME;
- break;
+ name_type = GENERAL_NAME_EDI_PARTY_NAME;
+ } else if (tag == der::ContextSpecificPrimitive(6)) {
// uniformResourceIdentifier [6] IA5String,
- case 6:
- if (der::IsConstructed(tag))
- return false;
- name_type = GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER;
- break;
+ name_type = GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER;
+ } else if (tag == der::ContextSpecificPrimitive(7)) {
// iPAddress [7] OCTET STRING,
- case 7:
- if (der::IsConstructed(tag))
+ name_type = GENERAL_NAME_IP_ADDRESS;
+ if (ip_address_type == IP_ADDRESS_ONLY) {
+ // RFC 5280 section 4.2.1.6:
+ // When the subjectAltName extension contains an iPAddress, the address
+ // MUST be stored in the octet string in "network byte order", as
+ // specified in [RFC791]. The least significant bit (LSB) of each octet
+ // is the LSB of the corresponding byte in the network address. For IP
+ // version 4, as specified in [RFC791], the octet string MUST contain
+ // exactly four octets. For IP version 6, as specified in [RFC2460],
+ // the octet string MUST contain exactly sixteen octets.
+ if ((value.Length() != IPAddress::kIPv4AddressSize &&
+ value.Length() != IPAddress::kIPv6AddressSize)) {
return false;
- name_type = GENERAL_NAME_IP_ADDRESS;
- if (ip_address_type == IP_ADDRESS_ONLY) {
- // RFC 5280 section 4.2.1.6:
- // When the subjectAltName extension contains an iPAddress, the address
- // MUST be stored in the octet string in "network byte order", as
- // specified in [RFC791]. The least significant bit (LSB) of each octet
- // is the LSB of the corresponding byte in the network address. For IP
- // version 4, as specified in [RFC791], the octet string MUST contain
- // exactly four octets. For IP version 6, as specified in [RFC2460],
- // the octet string MUST contain exactly sixteen octets.
- if ((value.Length() != kIPv4AddressSize &&
- value.Length() != kIPv6AddressSize)) {
- return false;
- }
- subtrees->ip_addresses.push_back(std::vector<uint8_t>(
- value.UnsafeData(), value.UnsafeData() + value.Length()));
- } else {
- DCHECK_EQ(ip_address_type, IP_ADDRESS_AND_NETMASK);
- // RFC 5280 section 4.2.1.10:
- // The syntax of iPAddress MUST be as described in Section 4.2.1.6 with
- // the following additions specifically for name constraints. For IPv4
- // addresses, the iPAddress field of GeneralName MUST contain eight (8)
- // octets, encoded in the style of RFC 4632 (CIDR) to represent an
- // address range [RFC4632]. For IPv6 addresses, the iPAddress field
- // MUST contain 32 octets similarly encoded. For example, a name
- // constraint for "class C" subnet 192.0.2.0 is represented as the
- // octets C0 00 02 00 FF FF FF 00, representing the CIDR notation
- // 192.0.2.0/24 (mask 255.255.255.0).
- if (value.Length() != kIPv4AddressSize * 2 &&
- value.Length() != kIPv6AddressSize * 2) {
- return false;
- }
- const std::vector<uint8_t> mask(value.UnsafeData() + value.Length() / 2,
- value.UnsafeData() + value.Length());
- const unsigned mask_prefix_length = MaskPrefixLength(mask);
- if (!IsSuffixZero(mask, mask_prefix_length))
- return false;
- subtrees->ip_address_ranges.push_back(std::make_pair(
- std::vector<uint8_t>(value.UnsafeData(),
- value.UnsafeData() + value.Length() / 2),
- mask_prefix_length));
}
- break;
- // registeredID [8] OBJECT IDENTIFIER }
- case 8:
- if (der::IsConstructed(tag))
+ subtrees->ip_addresses.push_back(
+ IPAddress(value.UnsafeData(), value.Length()));
+ } else {
+ DCHECK_EQ(ip_address_type, IP_ADDRESS_AND_NETMASK);
+ // RFC 5280 section 4.2.1.10:
+ // The syntax of iPAddress MUST be as described in Section 4.2.1.6 with
+ // the following additions specifically for name constraints. For IPv4
+ // addresses, the iPAddress field of GeneralName MUST contain eight (8)
+ // octets, encoded in the style of RFC 4632 (CIDR) to represent an
+ // address range [RFC4632]. For IPv6 addresses, the iPAddress field
+ // MUST contain 32 octets similarly encoded. For example, a name
+ // constraint for "class C" subnet 192.0.2.0 is represented as the
+ // octets C0 00 02 00 FF FF FF 00, representing the CIDR notation
+ // 192.0.2.0/24 (mask 255.255.255.0).
+ if (value.Length() != IPAddress::kIPv4AddressSize * 2 &&
+ value.Length() != IPAddress::kIPv6AddressSize * 2) {
return false;
- name_type = GENERAL_NAME_REGISTERED_ID;
- break;
- default:
- return false;
+ }
+ const IPAddress mask(value.UnsafeData() + value.Length() / 2,
+ value.Length() / 2);
+ const unsigned mask_prefix_length = MaskPrefixLength(mask);
+ if (!IsSuffixZero(mask.bytes(), mask_prefix_length))
+ return false;
+ subtrees->ip_address_ranges.push_back(
+ std::make_pair(IPAddress(value.UnsafeData(), value.Length() / 2),
+ mask_prefix_length));
+ }
+ } else if (tag == der::ContextSpecificPrimitive(8)) {
+ // registeredID [8] OBJECT IDENTIFIER }
+ name_type = GENERAL_NAME_REGISTERED_ID;
+ } else {
+ return false;
}
DCHECK_NE(GENERAL_NAME_NONE, name_type);
if ((name_type & kSupportedNameTypes) ||
@@ -265,11 +240,12 @@ WARN_UNUSED_RESULT bool ParseGeneralName(
// Parses a GeneralSubtrees |value| and store the contents in |subtrees|.
// The individual values stored into |subtrees| are not validated by this
// function.
-// NOTE: |subtrees| will be modified regardless of the return.
-WARN_UNUSED_RESULT bool ParseGeneralSubtrees(
- const der::Input& value,
- bool is_critical,
- NameConstraints::GeneralNames* subtrees) {
+// NOTE: |subtrees| is not pre-initialized by the function(it is expected to be
+// a default initialized object), and it will be modified regardless of the
+// return value.
+WARN_UNUSED_RESULT bool ParseGeneralSubtrees(const der::Input& value,
+ bool is_critical,
+ GeneralNames* subtrees) {
// GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
//
// GeneralSubtree ::= SEQUENCE {
@@ -317,9 +293,39 @@ WARN_UNUSED_RESULT bool ParseGeneralSubtrees(
} // namespace
-NameConstraints::GeneralNames::GeneralNames() {}
+GeneralNames::GeneralNames() {}
+
+GeneralNames::~GeneralNames() {}
+
+// static
+scoped_ptr<GeneralNames> GeneralNames::CreateFromDer(
+ const der::Input& general_names_tlv) {
+ // RFC 5280 section 4.2.1.6:
+ // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+ scoped_ptr<GeneralNames> general_names(new GeneralNames());
+ der::Parser parser(general_names_tlv);
+ der::Parser sequence_parser;
+ if (!parser.ReadSequence(&sequence_parser))
+ return nullptr;
+ // Should not have trailing data after GeneralNames sequence.
+ if (parser.HasMore())
+ return nullptr;
+ // The GeneralNames sequence should have at least 1 element.
+ if (!sequence_parser.HasMore())
+ return nullptr;
+
+ while (sequence_parser.HasMore()) {
+ der::Input raw_general_name;
+ if (!sequence_parser.ReadRawTLV(&raw_general_name))
+ return nullptr;
+
+ if (!ParseGeneralName(raw_general_name, RECORD_UNSUPPORTED, IP_ADDRESS_ONLY,
+ general_names.get()))
+ return nullptr;
+ }
-NameConstraints::GeneralNames::~GeneralNames() {}
+ return general_names;
+}
NameConstraints::~NameConstraints() {}
@@ -387,7 +393,7 @@ bool NameConstraints::Parse(const der::Input& extension_value,
bool NameConstraints::IsPermittedCert(
const der::Input& subject_rdn_sequence,
- const der::Input& subject_alt_name_extnvalue_tlv) const {
+ const GeneralNames* subject_alt_names) const {
// Subject Alternative Name handling:
//
// RFC 5280 section 4.2.1.6:
@@ -397,34 +403,7 @@ bool NameConstraints::IsPermittedCert(
//
// GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
- GeneralNames san_names;
- if (subject_alt_name_extnvalue_tlv.Length()) {
- der::Parser extnvalue_parser(subject_alt_name_extnvalue_tlv);
- der::Input subject_alt_name_tlv;
- if (!extnvalue_parser.ReadTag(der::kOctetString, &subject_alt_name_tlv))
- return false;
-
- der::Parser subject_alt_name_parser(subject_alt_name_tlv);
- der::Parser san_sequence_parser;
- if (!subject_alt_name_parser.ReadSequence(&san_sequence_parser))
- return false;
- // Should not have trailing data after subjectAltName sequence.
- if (subject_alt_name_parser.HasMore())
- return false;
- // The subjectAltName sequence should have at least 1 element.
- if (!san_sequence_parser.HasMore())
- return false;
-
- while (san_sequence_parser.HasMore()) {
- der::Input raw_general_name;
- if (!san_sequence_parser.ReadRawTLV(&raw_general_name))
- return false;
-
- if (!ParseGeneralName(raw_general_name, RECORD_UNSUPPORTED,
- IP_ADDRESS_ONLY, &san_names))
- return false;
- }
-
+ if (subject_alt_names) {
// Check unsupported name types:
// ConstrainedNameTypes for the unsupported types will only be true if that
// type of name was present in a name constraint that was marked critical.
@@ -435,25 +414,25 @@ bool NameConstraints::IsPermittedCert(
// that name form appears in the subject field or subjectAltName
// extension of a subsequent certificate, then the application MUST
// either process the constraint or reject the certificate.
- if (ConstrainedNameTypes() & san_names.present_name_types &
+ if (ConstrainedNameTypes() & subject_alt_names->present_name_types &
~kSupportedNameTypes) {
return false;
}
// Check supported name types:
- for (const auto& dns_name : san_names.dns_names) {
+ for (const auto& dns_name : subject_alt_names->dns_names) {
if (!IsPermittedDNSName(dns_name))
return false;
}
- for (const auto& directory_name : san_names.directory_names) {
+ for (const auto& directory_name : subject_alt_names->directory_names) {
if (!IsPermittedDirectoryName(
der::Input(directory_name.data(), directory_name.size()))) {
return false;
}
}
- for (const auto& ip_address : san_names.ip_addresses) {
+ for (const auto& ip_address : subject_alt_names->ip_addresses) {
if (!IsPermittedIP(ip_address))
return false;
}
@@ -468,7 +447,7 @@ bool NameConstraints::IsPermittedCert(
// form, but the certificate does not include a subject alternative name, the
// rfc822Name constraint MUST be applied to the attribute of type emailAddress
// in the subject distinguished name.
- if (!subject_alt_name_extnvalue_tlv.Length() &&
+ if (!subject_alt_names &&
(ConstrainedNameTypes() & GENERAL_NAME_RFC822_NAME)) {
bool contained_email_address = false;
if (!NameContainsEmailAddress(subject_rdn_sequence,
@@ -487,19 +466,13 @@ bool NameConstraints::IsPermittedCert(
// This code assumes that criticality condition is checked by the caller, and
// therefore only needs to avoid the IsPermittedDirectoryName check against an
// empty subject in such a case.
- if (subject_alt_name_extnvalue_tlv.Length() &&
- subject_rdn_sequence.Length() == 0) {
+ if (subject_alt_names && subject_rdn_sequence.Length() == 0)
return true;
- }
return IsPermittedDirectoryName(subject_rdn_sequence);
}
bool NameConstraints::IsPermittedDNSName(const std::string& name) const {
- // If there are no name constraints for DNS names, all names are accepted.
- if (!(ConstrainedNameTypes() & GENERAL_NAME_DNS_NAME))
- return true;
-
for (const std::string& excluded_name : excluded_subtrees_.dns_names) {
// When matching wildcard hosts against excluded subtrees, consider it a
// match if the constraint would match any expansion of the wildcard. Eg,
@@ -507,6 +480,12 @@ bool NameConstraints::IsPermittedDNSName(const std::string& name) const {
if (DNSNameMatches(name, excluded_name, WILDCARD_PARTIAL_MATCH))
return false;
}
+
+ // If permitted subtrees are not constrained, any name that is not excluded is
+ // allowed.
+ if (!(permitted_subtrees_.present_name_types & GENERAL_NAME_DNS_NAME))
+ return true;
+
for (const std::string& permitted_name : permitted_subtrees_.dns_names) {
// When matching wildcard hosts against permitted subtrees, consider it a
// match only if the constraint would match all expansions of the wildcard.
@@ -520,11 +499,6 @@ bool NameConstraints::IsPermittedDNSName(const std::string& name) const {
bool NameConstraints::IsPermittedDirectoryName(
const der::Input& name_rdn_sequence) const {
- // If there are no name constraints for directory names, all names are
- // accepted.
- if (!(ConstrainedNameTypes() & GENERAL_NAME_DIRECTORY_NAME))
- return true;
-
for (const auto& excluded_name : excluded_subtrees_.directory_names) {
if (VerifyNameInSubtree(
name_rdn_sequence,
@@ -532,6 +506,12 @@ bool NameConstraints::IsPermittedDirectoryName(
return false;
}
}
+
+ // If permitted subtrees are not constrained, any name that is not excluded is
+ // allowed.
+ if (!(permitted_subtrees_.present_name_types & GENERAL_NAME_DIRECTORY_NAME))
+ return true;
+
for (const auto& permitted_name : permitted_subtrees_.directory_names) {
if (VerifyNameInSubtree(
name_rdn_sequence,
@@ -543,18 +523,19 @@ bool NameConstraints::IsPermittedDirectoryName(
return false;
}
-bool NameConstraints::IsPermittedIP(const IPAddressNumber& ip) const {
- // If there are no name constraints for IP Address names, all names are
- // accepted.
- if (!(ConstrainedNameTypes() & GENERAL_NAME_IP_ADDRESS))
- return true;
-
+bool NameConstraints::IsPermittedIP(const IPAddress& ip) const {
for (const auto& excluded_ip : excluded_subtrees_.ip_address_ranges) {
- if (IPNumberMatchesPrefix(ip, excluded_ip.first, excluded_ip.second))
+ if (IPAddressMatchesPrefix(ip, excluded_ip.first, excluded_ip.second))
return false;
}
+
+ // If permitted subtrees are not constrained, any name that is not excluded is
+ // allowed.
+ if (!(permitted_subtrees_.present_name_types & GENERAL_NAME_IP_ADDRESS))
+ return true;
+
for (const auto& permitted_ip : permitted_subtrees_.ip_address_ranges) {
- if (IPNumberMatchesPrefix(ip, permitted_ip.first, permitted_ip.second))
+ if (IPAddressMatchesPrefix(ip, permitted_ip.first, permitted_ip.second))
return true;
}
diff --git a/chromium/net/cert/internal/name_constraints.h b/chromium/net/cert/internal/name_constraints.h
index 46cb0dade74..35ff91359bf 100644
--- a/chromium/net/cert/internal/name_constraints.h
+++ b/chromium/net/cert/internal/name_constraints.h
@@ -11,7 +11,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
namespace net {
@@ -35,42 +35,47 @@ enum GeneralNameTypes {
GENERAL_NAME_REGISTERED_ID = 1 << 8,
};
+// Represents a GeneralNames structure. When processing GeneralNames, it is
+// often necessary to know which types of names were present, and to check
+// all the names of a certain type. Therefore, a bitfield of all the name
+// types is kept, and the names are split into members for each type. Only
+// name types that are handled by this code are stored (though all types are
+// recorded in the bitfield.)
+// TODO(mattm): move this to some other file?
+struct NET_EXPORT GeneralNames {
+ GeneralNames();
+ ~GeneralNames();
+
+ // Create a GeneralNames object representing the DER-encoded
+ // |general_names_tlv|.
+ static scoped_ptr<GeneralNames> CreateFromDer(
+ const der::Input& general_names_tlv);
+
+ // ASCII hostnames.
+ std::vector<std::string> dns_names;
+
+ // DER-encoded Name values (not including the Sequence tag).
+ std::vector<std::vector<uint8_t>> directory_names;
+
+ // iPAddresses as sequences of octets in network byte order. This will be
+ // populated if the GeneralNames represents a Subject Alternative Name.
+ std::vector<IPAddress> ip_addresses;
+
+ // iPAddress ranges, as <IP, prefix length> pairs. This will be populated
+ // if the GeneralNames represents a Name Constraints.
+ std::vector<std::pair<IPAddress, unsigned>> ip_address_ranges;
+
+ // Which name types were present, as a bitfield of GeneralNameTypes.
+ // Includes both the supported and unsupported types (although unsupported
+ // ones may not be recorded depending on the context, like non-critical name
+ // constraints.)
+ int present_name_types = GENERAL_NAME_NONE;
+};
+
// Parses a NameConstraints extension value and allows testing whether names are
// allowed under those constraints as defined by RFC 5280 section 4.2.1.10.
class NET_EXPORT NameConstraints {
public:
- // Represents a GeneralNames structure. When processing GeneralNames, it is
- // often necessary to know which types of names were present, and to check
- // all the names of a certain type. Therefore, a bitfield of all the name
- // types is kept, and the names are split into members for each type. Only
- // name types that are handled by this code are stored (though all types are
- // recorded in the bitfield.)
- // TODO(mattm): This may need to be split out into a public class, since
- // GeneralNames is used other places in a certificate also...
- struct GeneralNames {
- GeneralNames();
- ~GeneralNames();
-
- // ASCII hostnames.
- std::vector<std::string> dns_names;
-
- // DER-encoded Name values (not including the Sequence tag).
- std::vector<std::vector<uint8_t>> directory_names;
-
- // iPAddresses as sequences of octets in network byte order. This will be
- // populated if the GeneralNames represents a Subject Alternative Name.
- std::vector<std::vector<uint8_t>> ip_addresses;
-
- // iPAddress ranges, as <IP, prefix length> pairs. This will be populated
- // if the GeneralNames represents a Name Constraints.
- std::vector<std::pair<std::vector<uint8_t>, unsigned>> ip_address_ranges;
-
- // Which name types were present, as a bitfield of GeneralNameTypes.
- // Includes both the supported and unsupported types (although unsupported
- // ones may not be recorded depending on the context, like non-critical name
- // constraints.)
- int present_name_types = GENERAL_NAME_NONE;
- };
~NameConstraints();
@@ -86,13 +91,12 @@ class NET_EXPORT NameConstraints {
// Tests if a certificate is allowed by the name constraints.
// |subject_rdn_sequence| should be the DER-encoded value of the subject's
// RDNSequence (not including Sequence tag), and may be an empty ASN.1
- // sequence. |subject_alt_name_extnvalue_tlv| should be the extnValue of the
- // subjectAltName extension (including the OCTET STRING tag & length), or
- // empty if the cert did not have a subjectAltName extension.
+ // sequence. |subject_alt_names| should be the parsed representation of the
+ // subjectAltName extension or nullptr if the extension was not present.
// Note that this method does not check hostname or IP address in commonName,
// which is deprecated (crbug.com/308330).
bool IsPermittedCert(const der::Input& subject_rdn_sequence,
- const der::Input& subject_alt_name_extnvalue_tlv) const;
+ const GeneralNames* subject_alt_names) const;
// Returns true if the ASCII hostname |name| is permitted.
// |name| may be a wildcard hostname (starts with "*."). Eg, "*.bar.com"
@@ -107,7 +111,7 @@ class NET_EXPORT NameConstraints {
bool IsPermittedDirectoryName(const der::Input& name_rdn_sequence) const;
// Returns true if the iPAddress |ip| is permitted.
- bool IsPermittedIP(const IPAddressNumber& ip) const;
+ bool IsPermittedIP(const IPAddress& ip) const;
// Returns a bitfield of GeneralNameTypes of all the types constrained by this
// NameConstraints. Name types that aren't supported will only be present if
diff --git a/chromium/net/cert/internal/name_constraints_unittest.cc b/chromium/net/cert/internal/name_constraints_unittest.cc
index 8b550f7fc94..693597da3aa 100644
--- a/chromium/net/cert/internal/name_constraints_unittest.cc
+++ b/chromium/net/cert/internal/name_constraints_unittest.cc
@@ -4,6 +4,7 @@
#include "net/cert/internal/name_constraints.h"
+#include "net/base/ip_address.h"
#include "net/cert/internal/test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -32,11 +33,26 @@ namespace {
return LoadTestData("NAME CONSTRAINTS", basename, result);
}
-::testing::AssertionResult LoadTestSubjectAltName(const std::string& basename,
- std::string* result) {
+::testing::AssertionResult LoadTestSubjectAltNameData(
+ const std::string& basename,
+ std::string* result) {
return LoadTestData("SUBJECT ALTERNATIVE NAME", basename, result);
}
+::testing::AssertionResult LoadTestSubjectAltName(
+ const std::string& basename,
+ scoped_ptr<GeneralNames>* result) {
+ std::string san_der;
+ ::testing::AssertionResult load_result =
+ LoadTestSubjectAltNameData(basename, &san_der);
+ if (!load_result)
+ return load_result;
+ *result = GeneralNames::CreateFromDer(der::Input(&san_der));
+ if (!*result)
+ return ::testing::AssertionFailure() << "CreateFromDer failed";
+ return ::testing::AssertionSuccess();
+}
+
} // namespace
class ParseNameConstraints
@@ -120,22 +136,18 @@ TEST_P(ParseNameConstraints, DNSNames) {
EXPECT_EQ(GENERAL_NAME_DNS_NAME, name_constraints->ConstrainedNameTypes());
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-permitted.pem", &san));
- EXPECT_TRUE(
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ EXPECT_TRUE(name_constraints->IsPermittedCert(der::Input(), san.get()));
ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-dnsname.pem", &san));
- EXPECT_FALSE(
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ EXPECT_FALSE(name_constraints->IsPermittedCert(der::Input(), san.get()));
ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-directoryname.pem", &san));
- EXPECT_TRUE(
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ EXPECT_TRUE(name_constraints->IsPermittedCert(der::Input(), san.get()));
ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-ipaddress.pem", &san));
- EXPECT_TRUE(
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ EXPECT_TRUE(name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints,
@@ -193,11 +205,11 @@ TEST_P(ParseNameConstraints, DNSNamesExcludeOnly) {
NameConstraints::CreateFromDer(der::Input(&a), is_critical()));
ASSERT_TRUE(name_constraints);
- // Only "excluded.permitted.example.com" is excluded, but since no dNSNames
- // are permitted, everything is excluded.
- EXPECT_FALSE(name_constraints->IsPermittedDNSName(""));
- EXPECT_FALSE(name_constraints->IsPermittedDNSName("foo.com"));
- EXPECT_FALSE(name_constraints->IsPermittedDNSName("permitted.example.com"));
+ // Only "excluded.permitted.example.com" is excluded, and since permitted is
+ // empty, any dNSName outside that is allowed.
+ EXPECT_TRUE(name_constraints->IsPermittedDNSName(""));
+ EXPECT_TRUE(name_constraints->IsPermittedDNSName("foo.com"));
+ EXPECT_TRUE(name_constraints->IsPermittedDNSName("permitted.example.com"));
EXPECT_FALSE(
name_constraints->IsPermittedDNSName("excluded.permitted.example.com"));
EXPECT_FALSE(
@@ -307,28 +319,24 @@ TEST_P(ParseNameConstraints, DirectoryNames) {
// Within the permitted C=US subtree.
EXPECT_TRUE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us), der::Input()));
+ SequenceValueFromString(&name_us), nullptr /* subject_alt_names */));
// Within the permitted C=US subtree, however the excluded C=US,ST=California
// subtree takes priority.
EXPECT_FALSE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_ca), der::Input()));
+ SequenceValueFromString(&name_us_ca), nullptr /* subject_alt_names */));
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-permitted.pem", &san));
- EXPECT_TRUE(
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ EXPECT_TRUE(name_constraints->IsPermittedCert(der::Input(), san.get()));
ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-dnsname.pem", &san));
- EXPECT_TRUE(
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ EXPECT_TRUE(name_constraints->IsPermittedCert(der::Input(), san.get()));
ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-directoryname.pem", &san));
- EXPECT_FALSE(
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ EXPECT_FALSE(name_constraints->IsPermittedCert(der::Input(), san.get()));
ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-ipaddress.pem", &san));
- EXPECT_TRUE(
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ EXPECT_TRUE(name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, DirectoryNamesExcludeOnly) {
@@ -349,11 +357,11 @@ TEST_P(ParseNameConstraints, DirectoryNamesExcludeOnly) {
ASSERT_TRUE(LoadTestName("name-us-california-mountain_view.pem",
&name_us_ca_mountain_view));
- // Only "C=US,ST=California" is excluded, but since no directoryNames are
- // permitted, everything is excluded.
- EXPECT_FALSE(name_constraints->IsPermittedDirectoryName(
+ // Only "C=US,ST=California" is excluded, and since permitted is empty,
+ // any directoryName outside that is allowed.
+ EXPECT_TRUE(name_constraints->IsPermittedDirectoryName(
SequenceValueFromString(&name_empty)));
- EXPECT_FALSE(name_constraints->IsPermittedDirectoryName(
+ EXPECT_TRUE(name_constraints->IsPermittedDirectoryName(
SequenceValueFromString(&name_us)));
EXPECT_FALSE(name_constraints->IsPermittedDirectoryName(
SequenceValueFromString(&name_us_ca)));
@@ -364,7 +372,7 @@ TEST_P(ParseNameConstraints, DirectoryNamesExcludeOnly) {
TEST_P(ParseNameConstraints, DirectoryNamesExcludeAll) {
std::string constraints_der;
ASSERT_TRUE(
- LoadTestNameConstraint("directoryname-excluded.pem", &constraints_der));
+ LoadTestNameConstraint("directoryname-excludeall.pem", &constraints_der));
scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer(
der::Input(&constraints_der), is_critical()));
ASSERT_TRUE(name_constraints);
@@ -402,161 +410,110 @@ TEST_P(ParseNameConstraints, IPAdresses) {
ASSERT_TRUE(name_constraints);
// IPv4 tests:
- {
- // Not in any permitted range.
- const uint8_t ip4[] = {192, 169, 0, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- // Within the permitted 192.168.0.0/255.255.0.0 range.
- const uint8_t ip4[] = {192, 168, 0, 1};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- // Within the permitted 192.168.0.0/255.255.0.0 range, however the
- // excluded 192.168.5.0/255.255.255.0 takes priority.
- const uint8_t ip4[] = {192, 168, 5, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- // Within the permitted 192.168.0.0/255.255.0.0 range as well as the
- // permitted 192.168.5.32/255.255.255.224 range, however the excluded
- // 192.168.5.0/255.255.255.0 still takes priority.
- const uint8_t ip4[] = {192, 168, 5, 33};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- // Not in any permitted range. (Just outside the
- // 192.167.5.32/255.255.255.224 range.)
- const uint8_t ip4[] = {192, 167, 5, 31};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- // Within the permitted 192.167.5.32/255.255.255.224 range.
- const uint8_t ip4[] = {192, 167, 5, 32};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- // Within the permitted 192.167.5.32/255.255.255.224 range.
- const uint8_t ip4[] = {192, 167, 5, 63};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- // Not in any permitted range. (Just outside the
- // 192.167.5.32/255.255.255.224 range.)
- const uint8_t ip4[] = {192, 167, 5, 64};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- // Not in any permitted range, and also inside the extraneous excluded
- // 192.166.5.32/255.255.255.224 range.
- const uint8_t ip4[] = {192, 166, 5, 32};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
+
+ // Not in any permitted range.
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 169, 0, 1)));
+
+ // Within the permitted 192.168.0.0/255.255.0.0 range.
+ EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 168, 0, 1)));
+
+ // Within the permitted 192.168.0.0/255.255.0.0 range, however the
+ // excluded 192.168.5.0/255.255.255.0 takes priority.
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 5, 1)));
+
+ // Within the permitted 192.168.0.0/255.255.0.0 range as well as the
+ // permitted 192.168.5.32/255.255.255.224 range, however the excluded
+ // 192.168.5.0/255.255.255.0 still takes priority.
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 5, 33)));
+
+ // Not in any permitted range. (Just outside the
+ // 192.167.5.32/255.255.255.224 range.)
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 167, 5, 31)));
+
+ // Within the permitted 192.167.5.32/255.255.255.224 range.
+ EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 167, 5, 32)));
+
+ // Within the permitted 192.167.5.32/255.255.255.224 range.
+ EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 167, 5, 63)));
+
+ // Not in any permitted range. (Just outside the
+ // 192.167.5.32/255.255.255.224 range.)
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 167, 5, 64)));
+
+ // Not in any permitted range, and also inside the extraneous excluded
+ // 192.166.5.32/255.255.255.224 range.
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 166, 5, 32)));
// IPv6 tests:
- {
- // Not in any permitted range.
- const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip6, ip6 + arraysize(ip6))));
- }
- {
- // Within the permitted
- // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range.
- const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 1};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip6, ip6 + arraysize(ip6))));
- }
- {
- // Within the permitted
- // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range, however
- // the excluded
- // 102:304:506:708:90a:b0c:500:0/ffff:ffff:ffff:ffff:ffff:ffff:ff00:0 takes
- // priority.
- const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 0, 0, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip6, ip6 + arraysize(ip6))));
- }
- {
- // Within the permitted
- // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range as well
- // as the permitted
- // 102:304:506:708:90a:b0c:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0,
- // however the excluded
- // 102:304:506:708:90a:b0c:500:0/ffff:ffff:ffff:ffff:ffff:ffff:ff00:0 takes
- // priority.
- const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 33, 0, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip6, ip6 + arraysize(ip6))));
- }
- {
- // Not in any permitted range. (Just outside the
- // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0
- // range.)
- const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8,
- 9, 10, 11, 11, 5, 31, 255, 255};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip6, ip6 + arraysize(ip6))));
- }
- {
- // Within the permitted
- // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
- const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 32, 0, 0};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip6, ip6 + arraysize(ip6))));
- }
- {
- // Within the permitted
- // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
- const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8,
- 9, 10, 11, 11, 5, 63, 255, 255};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip6, ip6 + arraysize(ip6))));
- }
- {
- // Not in any permitted range. (Just outside the
- // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0
- // range.)
- const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 64, 0, 0};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip6, ip6 + arraysize(ip6))));
- }
- {
- // Not in any permitted range, and also inside the extraneous excluded
- // 102:304:506:708:90a:b0a:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
- const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 10, 5, 33, 0, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip6, ip6 + arraysize(ip6))));
- }
+
+ // Not in any permitted range.
+ EXPECT_FALSE(name_constraints->IsPermittedIP(
+ IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1)));
+
+ // Within the permitted
+ // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range.
+ EXPECT_TRUE(name_constraints->IsPermittedIP(
+ IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 1)));
+
+ // Within the permitted
+ // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range, however
+ // the excluded
+ // 102:304:506:708:90a:b0c:500:0/ffff:ffff:ffff:ffff:ffff:ffff:ff00:0 takes
+ // priority.
+ EXPECT_FALSE(name_constraints->IsPermittedIP(
+ IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 0, 0, 1)));
+
+ // Within the permitted
+ // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range as well
+ // as the permitted
+ // 102:304:506:708:90a:b0c:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0,
+ // however the excluded
+ // 102:304:506:708:90a:b0c:500:0/ffff:ffff:ffff:ffff:ffff:ffff:ff00:0 takes
+ // priority.
+ EXPECT_FALSE(name_constraints->IsPermittedIP(
+ IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 33, 0, 1)));
+
+ // Not in any permitted range. (Just outside the
+ // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0
+ // range.)
+ EXPECT_FALSE(name_constraints->IsPermittedIP(
+ IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 31, 255, 255)));
+
+ // Within the permitted
+ // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
+ EXPECT_TRUE(name_constraints->IsPermittedIP(
+ IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 32, 0, 0)));
+
+ // Within the permitted
+ // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
+ EXPECT_TRUE(name_constraints->IsPermittedIP(
+ IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 63, 255, 255)));
+
+ // Not in any permitted range. (Just outside the
+ // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0
+ // range.)
+ EXPECT_FALSE(name_constraints->IsPermittedIP(
+ IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 64, 0, 0)));
+
+ // Not in any permitted range, and also inside the extraneous excluded
+ // 102:304:506:708:90a:b0a:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
+ EXPECT_FALSE(name_constraints->IsPermittedIP(
+ IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 10, 5, 33, 0, 1)));
EXPECT_EQ(GENERAL_NAME_IP_ADDRESS, name_constraints->ConstrainedNameTypes());
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-permitted.pem", &san));
- EXPECT_TRUE(
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ EXPECT_TRUE(name_constraints->IsPermittedCert(der::Input(), san.get()));
ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-dnsname.pem", &san));
- EXPECT_TRUE(
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ EXPECT_TRUE(name_constraints->IsPermittedCert(der::Input(), san.get()));
ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-directoryname.pem", &san));
- EXPECT_TRUE(
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ EXPECT_TRUE(name_constraints->IsPermittedCert(der::Input(), san.get()));
ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-ipaddress.pem", &san));
- EXPECT_FALSE(
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ EXPECT_FALSE(name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, IPAdressesExcludeOnly) {
@@ -567,23 +524,12 @@ TEST_P(ParseNameConstraints, IPAdressesExcludeOnly) {
NameConstraints::CreateFromDer(der::Input(&a), is_critical()));
ASSERT_TRUE(name_constraints);
- // Only 192.168.5.0/255.255.255.0 is excluded, but since no iPAddresses
- // are permitted, everything is excluded.
- {
- const uint8_t ip4[] = {192, 168, 0, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {192, 168, 5, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip6, ip6 + arraysize(ip6))));
- }
+ // Only 192.168.5.0/255.255.255.0 is excluded, and since permitted is empty,
+ // any iPAddress outside that is allowed.
+ EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 168, 0, 1)));
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 5, 1)));
+ EXPECT_TRUE(name_constraints->IsPermittedIP(
+ IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1)));
}
TEST_P(ParseNameConstraints, IPAdressesExcludeAll) {
@@ -597,26 +543,12 @@ TEST_P(ParseNameConstraints, IPAdressesExcludeAll) {
// 192.168.0.0/255.255.0.0 and
// 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: are permitted,
// but since 0.0.0.0/0 and ::/0 are excluded nothing is permitted.
- {
- const uint8_t ip4[] = {192, 168, 0, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {1, 1, 1, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip6[] = {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip6, ip6 + arraysize(ip6))));
- }
- {
- const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip6, ip6 + arraysize(ip6))));
- }
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 0, 1)));
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(1, 1, 1, 1)));
+ EXPECT_FALSE(name_constraints->IsPermittedIP(
+ IPAddress(2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)));
+ EXPECT_FALSE(name_constraints->IsPermittedIP(
+ IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1)));
}
TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitSingleHost) {
@@ -627,36 +559,12 @@ TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitSingleHost) {
NameConstraints::CreateFromDer(der::Input(&a), is_critical()));
ASSERT_TRUE(name_constraints);
- {
- const uint8_t ip4[] = {0, 0, 0, 0};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {192, 168, 1, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {192, 168, 1, 2};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {192, 168, 1, 3};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {192, 168, 1, 4};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {255, 255, 255, 255};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress::IPv4AllZeros()));
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 1)));
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 2)));
+ EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 3)));
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 4)));
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(255, 255, 255, 255)));
}
TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitPrefixLen31) {
@@ -667,41 +575,13 @@ TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitPrefixLen31) {
NameConstraints::CreateFromDer(der::Input(&a), is_critical()));
ASSERT_TRUE(name_constraints);
- {
- const uint8_t ip4[] = {0, 0, 0, 0};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {192, 168, 1, 1};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {192, 168, 1, 2};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {192, 168, 1, 3};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {192, 168, 1, 4};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {192, 168, 1, 5};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {255, 255, 255, 255};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress::IPv4AllZeros()));
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 1)));
+ EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 2)));
+ EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 3)));
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 4)));
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 5)));
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(255, 255, 255, 255)));
}
TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitPrefixLen1) {
@@ -712,26 +592,12 @@ TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitPrefixLen1) {
NameConstraints::CreateFromDer(der::Input(&a), is_critical()));
ASSERT_TRUE(name_constraints);
- {
- const uint8_t ip4[] = {0, 0, 0, 0};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {0x7F, 0xFF, 0xFF, 0xFF};
- EXPECT_FALSE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {0x80, 0, 0, 0};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {0xFF, 0xFF, 0xFF, 0xFF};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
+ EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress::IPv4AllZeros()));
+ EXPECT_FALSE(
+ name_constraints->IsPermittedIP(IPAddress(0x7F, 0xFF, 0xFF, 0xFF)));
+ EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(0x80, 0, 0, 0)));
+ EXPECT_TRUE(
+ name_constraints->IsPermittedIP(IPAddress(0xFF, 0xFF, 0xFF, 0xFF)));
}
TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitAll) {
@@ -742,21 +608,9 @@ TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitAll) {
NameConstraints::CreateFromDer(der::Input(&a), is_critical()));
ASSERT_TRUE(name_constraints);
- {
- const uint8_t ip4[] = {0, 0, 0, 0};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {192, 168, 1, 1};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
- {
- const uint8_t ip4[] = {255, 255, 255, 255};
- EXPECT_TRUE(name_constraints->IsPermittedIP(
- IPAddressNumber(ip4, ip4 + arraysize(ip4))));
- }
+ EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress::IPv4AllZeros()));
+ EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 1)));
+ EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(255, 255, 255, 255)));
}
TEST_P(ParseNameConstraints, IPAdressesFailOnInvalidAddr) {
@@ -800,10 +654,10 @@ TEST_P(ParseNameConstraints, OtherNamesInPermitted) {
EXPECT_EQ(0, name_constraints->ConstrainedNameTypes());
}
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-othername.pem", &san));
EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, OtherNamesInExcluded) {
@@ -821,10 +675,10 @@ TEST_P(ParseNameConstraints, OtherNamesInExcluded) {
EXPECT_EQ(0, name_constraints->ConstrainedNameTypes());
}
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-othername.pem", &san));
EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, Rfc822NamesInPermitted) {
@@ -842,10 +696,10 @@ TEST_P(ParseNameConstraints, Rfc822NamesInPermitted) {
EXPECT_EQ(0, name_constraints->ConstrainedNameTypes());
}
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-rfc822name.pem", &san));
EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, Rfc822NamesInExcluded) {
@@ -863,10 +717,10 @@ TEST_P(ParseNameConstraints, Rfc822NamesInExcluded) {
EXPECT_EQ(0, name_constraints->ConstrainedNameTypes());
}
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-rfc822name.pem", &san));
EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, X400AddresssInPermitted) {
@@ -884,10 +738,10 @@ TEST_P(ParseNameConstraints, X400AddresssInPermitted) {
EXPECT_EQ(0, name_constraints->ConstrainedNameTypes());
}
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-x400address.pem", &san));
EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, X400AddresssInExcluded) {
@@ -905,10 +759,10 @@ TEST_P(ParseNameConstraints, X400AddresssInExcluded) {
EXPECT_EQ(0, name_constraints->ConstrainedNameTypes());
}
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-x400address.pem", &san));
EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, EdiPartyNamesInPermitted) {
@@ -926,10 +780,10 @@ TEST_P(ParseNameConstraints, EdiPartyNamesInPermitted) {
EXPECT_EQ(0, name_constraints->ConstrainedNameTypes());
}
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-edipartyname.pem", &san));
EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, EdiPartyNamesInExcluded) {
@@ -947,10 +801,10 @@ TEST_P(ParseNameConstraints, EdiPartyNamesInExcluded) {
EXPECT_EQ(0, name_constraints->ConstrainedNameTypes());
}
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-edipartyname.pem", &san));
EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, URIsInPermitted) {
@@ -967,10 +821,10 @@ TEST_P(ParseNameConstraints, URIsInPermitted) {
EXPECT_EQ(0, name_constraints->ConstrainedNameTypes());
}
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-uri.pem", &san));
EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, URIsInExcluded) {
@@ -987,10 +841,10 @@ TEST_P(ParseNameConstraints, URIsInExcluded) {
EXPECT_EQ(0, name_constraints->ConstrainedNameTypes());
}
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-uri.pem", &san));
EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, RegisteredIDsInPermitted) {
@@ -1008,10 +862,10 @@ TEST_P(ParseNameConstraints, RegisteredIDsInPermitted) {
EXPECT_EQ(0, name_constraints->ConstrainedNameTypes());
}
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-registeredid.pem", &san));
EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints, RegisteredIDsInExcluded) {
@@ -1029,10 +883,10 @@ TEST_P(ParseNameConstraints, RegisteredIDsInExcluded) {
EXPECT_EQ(0, name_constraints->ConstrainedNameTypes());
}
- std::string san;
+ scoped_ptr<GeneralNames> san;
ASSERT_TRUE(LoadTestSubjectAltName("san-registeredid.pem", &san));
EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(der::Input(), der::Input(&san)));
+ name_constraints->IsPermittedCert(der::Input(), san.get()));
}
TEST_P(ParseNameConstraints,
@@ -1123,7 +977,8 @@ TEST_P(ParseNameConstraints, IsPermittedCertSubjectEmailAddressIsOk) {
// Name constraints don't contain rfc822Name, so emailAddress in subject is
// allowed regardless.
EXPECT_TRUE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_arizona_email), der::Input()));
+ SequenceValueFromString(&name_us_arizona_email),
+ nullptr /* subject_alt_names */));
}
TEST_P(ParseNameConstraints, IsPermittedCertSubjectEmailAddressIsNotOk) {
@@ -1140,9 +995,9 @@ TEST_P(ParseNameConstraints, IsPermittedCertSubjectEmailAddressIsNotOk) {
// Name constraints contain rfc822Name, so emailAddress in subject is not
// allowed if the constraints were critical.
- EXPECT_EQ(!is_critical(),
- name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_arizona_email), der::Input()));
+ EXPECT_EQ(!is_critical(), name_constraints->IsPermittedCert(
+ SequenceValueFromString(&name_us_arizona_email),
+ nullptr /* subject_alt_names */));
}
// Hostname in commonName is not allowed (crbug.com/308330), so these are tests
@@ -1162,7 +1017,8 @@ TEST_P(ParseNameConstraints, IsPermittedCertSubjectDnsNames) {
// (The commonName hostname is not within permitted dNSName constraints, so
// this would not be permitted if hostnames in commonName were checked.)
EXPECT_TRUE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_az_foocom), der::Input()));
+ SequenceValueFromString(&name_us_az_foocom),
+ nullptr /* subject_alt_names */));
std::string name_us_az_permitted;
ASSERT_TRUE(LoadTestName("name-us-arizona-permitted.example.com.pem",
@@ -1171,7 +1027,8 @@ TEST_P(ParseNameConstraints, IsPermittedCertSubjectDnsNames) {
// permitted dNSName constraints, so this should be permitted regardless if
// hostnames in commonName are checked or not.
EXPECT_TRUE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_az_permitted), der::Input()));
+ SequenceValueFromString(&name_us_az_permitted),
+ nullptr /* subject_alt_names */));
std::string name_us_ca_permitted;
ASSERT_TRUE(LoadTestName("name-us-california-permitted.example.com.pem",
@@ -1180,7 +1037,8 @@ TEST_P(ParseNameConstraints, IsPermittedCertSubjectDnsNames) {
// this should not be allowed, regardless of checking the
// permitted.example.com in commonName.
EXPECT_FALSE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_ca_permitted), der::Input()));
+ SequenceValueFromString(&name_us_ca_permitted),
+ nullptr /* subject_alt_names */));
}
// IP addresses in commonName are not allowed (crbug.com/308330), so these are
@@ -1200,7 +1058,8 @@ TEST_P(ParseNameConstraints, IsPermittedCertSubjectIpAddresses) {
// (The commonName IP address is not within permitted iPAddresses constraints,
// so this would not be permitted if IP addresses in commonName were checked.)
EXPECT_TRUE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_az_1_1_1_1), der::Input()));
+ SequenceValueFromString(&name_us_az_1_1_1_1),
+ nullptr /* subject_alt_names */));
std::string name_us_az_192_168_1_1;
ASSERT_TRUE(
@@ -1209,7 +1068,8 @@ TEST_P(ParseNameConstraints, IsPermittedCertSubjectIpAddresses) {
// permitted iPAddress constraints, so this should be permitted regardless if
// IP addresses in commonName are checked or not.
EXPECT_TRUE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_az_192_168_1_1), der::Input()));
+ SequenceValueFromString(&name_us_az_192_168_1_1),
+ nullptr /* subject_alt_names */));
std::string name_us_ca_192_168_1_1;
ASSERT_TRUE(LoadTestName("name-us-california-192.168.1.1.pem",
@@ -1218,7 +1078,8 @@ TEST_P(ParseNameConstraints, IsPermittedCertSubjectIpAddresses) {
// this should not be allowed, regardless of checking the
// IP address in commonName.
EXPECT_FALSE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_ca_192_168_1_1), der::Input()));
+ SequenceValueFromString(&name_us_ca_192_168_1_1),
+ nullptr /* subject_alt_names */));
std::string name_us_az_ipv6;
ASSERT_TRUE(LoadTestName("name-us-arizona-ipv6.pem", &name_us_az_ipv6));
@@ -1226,51 +1087,24 @@ TEST_P(ParseNameConstraints, IsPermittedCertSubjectIpAddresses) {
// (The commonName is an ipv6 address which wasn't supported in the past, but
// since commonName checking is ignored entirely, this is permitted.)
EXPECT_TRUE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_az_ipv6), der::Input()));
-}
-
-TEST_P(ParseNameConstraints, IsPermittedCertFailsOnEmptySubjectAltName) {
- std::string constraints_der;
- ASSERT_TRUE(LoadTestNameConstraint("dnsname.pem", &constraints_der));
- scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer(
- der::Input(&constraints_der), is_critical()));
- ASSERT_TRUE(name_constraints);
-
- std::string name_us_az;
- ASSERT_TRUE(LoadTestName("name-us-arizona.pem", &name_us_az));
-
- // No constraints on directoryName type, so name_us_az should be allowed when
- // subjectAltName is not present.
- EXPECT_TRUE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_az), der::Input()));
-
- std::string san;
- ASSERT_TRUE(LoadTestSubjectAltName("san-invalid-empty.pem", &san));
- // Should fail if subjectAltName is present but empty.
- EXPECT_FALSE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_az), der::Input(&san)));
+ SequenceValueFromString(&name_us_az_ipv6),
+ nullptr /* subject_alt_names */));
}
-TEST_P(ParseNameConstraints, IsPermittedCertFailsOnInvalidIpInSubjectAltName) {
- std::string constraints_der;
- ASSERT_TRUE(LoadTestNameConstraint("ipaddress.pem", &constraints_der));
- scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer(
- der::Input(&constraints_der), is_critical()));
- ASSERT_TRUE(name_constraints);
-
- std::string name_us_az_192_168_1_1;
+TEST_P(ParseNameConstraints,
+ GeneralNamesCreateFromDerFailsOnEmptySubjectAltName) {
+ std::string invalid_san_der;
ASSERT_TRUE(
- LoadTestName("name-us-arizona-192.168.1.1.pem", &name_us_az_192_168_1_1));
-
- // Without the invalid subjectAltName, it passes.
- EXPECT_TRUE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_az_192_168_1_1), der::Input()));
+ LoadTestSubjectAltNameData("san-invalid-empty.pem", &invalid_san_der));
+ EXPECT_FALSE(GeneralNames::CreateFromDer(der::Input(&invalid_san_der)));
+}
- std::string san;
- ASSERT_TRUE(LoadTestSubjectAltName("san-invalid-ipaddress.pem", &san));
- // Should fail if subjectAltName contains an invalid ip address.
- EXPECT_FALSE(name_constraints->IsPermittedCert(
- SequenceValueFromString(&name_us_az_192_168_1_1), der::Input(&san)));
+TEST_P(ParseNameConstraints,
+ GeneralNamesCreateFromDerFailsOnInvalidIpInSubjectAltName) {
+ std::string invalid_san_der;
+ ASSERT_TRUE(LoadTestSubjectAltNameData("san-invalid-ipaddress.pem",
+ &invalid_san_der));
+ EXPECT_FALSE(GeneralNames::CreateFromDer(der::Input(&invalid_san_der)));
}
} // namespace net
diff --git a/chromium/net/cert/internal/nist_pkits_unittest.h b/chromium/net/cert/internal/nist_pkits_unittest.h
new file mode 100644
index 00000000000..aaf3992b645
--- /dev/null
+++ b/chromium/net/cert/internal/nist_pkits_unittest.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_CERT_INTERNAL_NIST_PKITS_UNITTEST_H
+#define NET_CERT_INTERNAL_NIST_PKITS_UNITTEST_H
+
+#include "base/base_paths.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Parameterized test class for PKITS tests.
+// The instantiating code should define a PkitsTestDelegate with an appropriate
+// static Verify method, and then INSTANTIATE_TYPED_TEST_CASE_P for each
+// testcase (each TYPED_TEST_CASE_P in pkits_testcases-inl.h).
+template <typename PkitsTestDelegate>
+class PkitsTest : public ::testing::Test {
+ public:
+ template <size_t num_certs, size_t num_crls>
+ bool Verify(const char* const (&cert_names)[num_certs],
+ const char* const (&crl_names)[num_crls]) {
+ std::vector<std::string> cert_ders;
+ for (const std::string& s : cert_names)
+ cert_ders.push_back(ReadTestFileToString("certs/" + s + ".crt"));
+ std::vector<std::string> crl_ders;
+ for (const std::string& s : crl_names)
+ crl_ders.push_back(ReadTestFileToString("crls/" + s + ".crl"));
+ return PkitsTestDelegate::Verify(cert_ders, crl_ders);
+ }
+
+ private:
+ std::string ReadTestFileToString(const std::string& file_name) {
+ // Compute the full path, relative to the src/ directory.
+ base::FilePath src_root;
+ PathService::Get(base::DIR_SOURCE_ROOT, &src_root);
+ base::FilePath filepath = src_root.AppendASCII(
+ std::string("net/third_party/nist-pkits/") + file_name);
+
+ // Read the full contents of the file.
+ std::string file_data;
+ if (!base::ReadFileToString(filepath, &file_data)) {
+ ADD_FAILURE() << "Couldn't read file: " << filepath.value();
+ return std::string();
+ }
+
+ return file_data;
+ }
+};
+
+// Inline the generated test code:
+#include "net/third_party/nist-pkits/pkits_testcases-inl.h"
+
+#endif // NET_CERT_INTERNAL_NIST_PKITS_UNITTEST_H
diff --git a/chromium/net/cert/internal/parse_certificate.cc b/chromium/net/cert/internal/parse_certificate.cc
index 74222e8fde0..74538080c16 100644
--- a/chromium/net/cert/internal/parse_certificate.cc
+++ b/chromium/net/cert/internal/parse_certificate.cc
@@ -68,43 +68,6 @@ WARN_UNUSED_RESULT bool ParseVersion(const der::Input& in,
return !parser.HasMore();
}
-// Returns true if the given serial number (CertificateSerialNumber in RFC 5280)
-// is valid:
-//
-// CertificateSerialNumber ::= INTEGER
-//
-// The input to this function is the (unverified) value octets of the INTEGER.
-// This function will verify that:
-//
-// * The octets are a valid DER-encoding of an INTEGER (for instance, minimal
-// encoding length).
-//
-// * No more than 20 octets are used.
-//
-// Note that it DOES NOT reject non-positive values (zero or negative).
-//
-// For reference, here is what RFC 5280 section 4.1.2.2 says:
-//
-// Given the uniqueness requirements above, serial numbers can be
-// expected to contain long integers. Certificate users MUST be able to
-// handle serialNumber values up to 20 octets. Conforming CAs MUST NOT
-// use serialNumber values longer than 20 octets.
-//
-// Note: Non-conforming CAs may issue certificates with serial numbers
-// that are negative or zero. Certificate users SHOULD be prepared to
-// gracefully handle such certificates.
-WARN_UNUSED_RESULT bool VerifySerialNumber(const der::Input& value) {
- bool unused_negative;
- if (!der::IsValidInteger(value, &unused_negative))
- return false;
-
- // Check if the serial number is too long per RFC 5280.
- if (value.Length() > 20)
- return false;
-
- return true;
-}
-
// Consumes a "Time" value (as defined by RFC 5280) from |parser|. On success
// writes the result to |*out| and returns true. On failure no guarantees are
// made about the state of |parser|.
@@ -191,6 +154,18 @@ ParsedTbsCertificate::ParsedTbsCertificate() {}
ParsedTbsCertificate::~ParsedTbsCertificate() {}
+bool VerifySerialNumber(const der::Input& value) {
+ bool unused_negative;
+ if (!der::IsValidInteger(value, &unused_negative))
+ return false;
+
+ // Check if the serial number is too long per RFC 5280.
+ if (value.Length() > 20)
+ return false;
+
+ return true;
+}
+
bool ParseCertificate(const der::Input& certificate_tlv,
ParsedCertificate* out) {
der::Parser parser(certificate_tlv);
diff --git a/chromium/net/cert/internal/parse_certificate.h b/chromium/net/cert/internal/parse_certificate.h
index e7a1670af1b..eca692dd044 100644
--- a/chromium/net/cert/internal/parse_certificate.h
+++ b/chromium/net/cert/internal/parse_certificate.h
@@ -19,6 +19,33 @@ namespace net {
struct ParsedCertificate;
struct ParsedTbsCertificate;
+// Returns true if the given serial number (CertificateSerialNumber in RFC 5280)
+// is valid:
+//
+// CertificateSerialNumber ::= INTEGER
+//
+// The input to this function is the (unverified) value octets of the INTEGER.
+// This function will verify that:
+//
+// * The octets are a valid DER-encoding of an INTEGER (for instance, minimal
+// encoding length).
+//
+// * No more than 20 octets are used.
+//
+// Note that it DOES NOT reject non-positive values (zero or negative).
+//
+// For reference, here is what RFC 5280 section 4.1.2.2 says:
+//
+// Given the uniqueness requirements above, serial numbers can be
+// expected to contain long integers. Certificate users MUST be able to
+// handle serialNumber values up to 20 octets. Conforming CAs MUST NOT
+// use serialNumber values longer than 20 octets.
+//
+// Note: Non-conforming CAs may issue certificates with serial numbers
+// that are negative or zero. Certificate users SHOULD be prepared to
+// gracefully handle such certificates.
+bool VerifySerialNumber(const der::Input& value) WARN_UNUSED_RESULT;
+
// Parses a DER-encoded "Certificate" as specified by RFC 5280. Returns true on
// success and sets the results in |out|.
//
diff --git a/chromium/net/cert/internal/parse_name.cc b/chromium/net/cert/internal/parse_name.cc
new file mode 100644
index 00000000000..dc491ae1920
--- /dev/null
+++ b/chromium/net/cert/internal/parse_name.cc
@@ -0,0 +1,332 @@
+// 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/parse_name.h"
+
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversion_utils.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/sys_byteorder.h"
+#include "base/third_party/icu/icu_utf.h"
+
+namespace net {
+
+namespace {
+
+// Converts a BMPString value in Input |in| to UTF-8.
+//
+// If the conversion is successful, returns true and stores the result in
+// |out|. Otherwise it returns false and leaves |out| unmodified.
+bool ConvertBmpStringValue(const der::Input& in, std::string* out) {
+ if (in.Length() % 2 != 0)
+ return false;
+
+ base::string16 in_16bit;
+ if (in.Length()) {
+ memcpy(base::WriteInto(&in_16bit, in.Length() / 2 + 1), in.UnsafeData(),
+ in.Length());
+ }
+ for (base::char16& c : in_16bit) {
+ // BMPString is UCS-2 in big-endian order.
+ c = base::NetToHost16(c);
+
+ // BMPString only supports codepoints in the Basic Multilingual Plane;
+ // surrogates are not allowed.
+ if (CBU_IS_SURROGATE(c))
+ return false;
+ }
+ return base::UTF16ToUTF8(in_16bit.data(), in_16bit.size(), out);
+}
+
+// Converts a UniversalString value in Input |in| to UTF-8.
+//
+// If the conversion is successful, returns true and stores the result in
+// |out|. Otherwise it returns false and leaves |out| unmodified.
+bool ConvertUniversalStringValue(const der::Input& in, std::string* out) {
+ if (in.Length() % 4 != 0)
+ return false;
+
+ std::vector<uint32_t> in_32bit(in.Length() / 4);
+ if (in.Length())
+ memcpy(in_32bit.data(), in.UnsafeData(), in.Length());
+ for (const uint32_t c : in_32bit) {
+ // UniversalString is UCS-4 in big-endian order.
+ uint32_t codepoint = base::NetToHost32(c);
+ if (!CBU_IS_UNICODE_CHAR(codepoint))
+ return false;
+
+ base::WriteUnicodeCharacter(codepoint, out);
+ }
+ return true;
+}
+
+std::string OidToString(const uint8_t* data, size_t len) {
+ std::string out;
+ size_t index = 0;
+ while (index < len) {
+ uint64_t value = 0;
+ while ((data[index] & 0x80) == 0x80 && index < len) {
+ value = value << 7 | (data[index] & 0x7F);
+ index += 1;
+ }
+ if (index >= len)
+ return std::string();
+ value = value << 7 | (data[index] & 0x7F);
+ index += 1;
+
+ if (out.empty()) {
+ uint8_t first = 0;
+ if (value < 40) {
+ first = 0;
+ } else if (value < 80) {
+ first = 1;
+ value -= 40;
+ } else {
+ first = 2;
+ value -= 80;
+ }
+ out = base::UintToString(first);
+ }
+ out += "." + base::UintToString(value);
+ }
+
+ return out;
+}
+
+} // namespace
+
+der::Input TypeCommonNameOid() {
+ // id-at-commonName: 2.5.4.3 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x03};
+ return der::Input(oid);
+}
+
+der::Input TypeSurnameOid() {
+ // id-at-surname: 2.5.4.4 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x04};
+ return der::Input(oid);
+}
+
+der::Input TypeSerialNumberOid() {
+ // id-at-serialNumber: 2.5.4.5 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x05};
+ return der::Input(oid);
+}
+
+der::Input TypeCountryNameOid() {
+ // id-at-countryName: 2.5.4.6 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x06};
+ return der::Input(oid);
+}
+
+der::Input TypeLocalityNameOid() {
+ // id-at-localityName: 2.5.4.7 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x07};
+ return der::Input(oid);
+}
+
+der::Input TypeStateOrProvinceNameOid() {
+ // id-at-stateOrProvinceName: 2.5.4.8 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x08};
+ return der::Input(oid);
+}
+
+der::Input TypeOrganizationNameOid() {
+ // id-at-organizationName: 2.5.4.10 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x0a};
+ return der::Input(oid);
+}
+
+der::Input TypeOrganizationUnitNameOid() {
+ // id-at-organizationalUnitName: 2.5.4.11 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x0b};
+ return der::Input(oid);
+}
+
+der::Input TypeTitleOid() {
+ // id-at-title: 2.5.4.12 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x0c};
+ return der::Input(oid);
+}
+
+der::Input TypeNameOid() {
+ // id-at-name: 2.5.4.41 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x29};
+ return der::Input(oid);
+}
+
+der::Input TypeGivenNameOid() {
+ // id-at-givenName: 2.5.4.42 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x2a};
+ return der::Input(oid);
+}
+
+der::Input TypeInitialsOid() {
+ // id-at-initials: 2.5.4.43 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x2b};
+ return der::Input(oid);
+}
+
+der::Input TypeGenerationQualifierOid() {
+ // id-at-generationQualifier: 2.5.4.44 (RFC 5280)
+ static const uint8_t oid[] = {0x55, 0x04, 0x2c};
+ return der::Input(oid);
+}
+
+bool X509NameAttribute::ValueAsStringUnsafe(std::string* out) const {
+ switch (value_tag) {
+ case der::kIA5String:
+ case der::kPrintableString:
+ case der::kTeletexString:
+ case der::kUtf8String:
+ *out = value.AsString();
+ return true;
+ case der::kUniversalString:
+ return ConvertUniversalStringValue(value, out);
+ case der::kBmpString:
+ return ConvertBmpStringValue(value, out);
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
+
+bool X509NameAttribute::AsRFC2253String(std::string* out) const {
+ std::string type_string;
+ std::string value_string;
+ if (type == TypeCommonNameOid()) {
+ type_string = "CN";
+ } else if (type == TypeSurnameOid()) {
+ type_string = "SN";
+ } else if (type == TypeCountryNameOid()) {
+ type_string = "C";
+ } else if (type == TypeLocalityNameOid()) {
+ type_string = "L";
+ } else if (type == TypeStateOrProvinceNameOid()) {
+ type_string = "ST";
+ } else if (type == TypeOrganizationNameOid()) {
+ type_string = "O";
+ } else if (type == TypeOrganizationUnitNameOid()) {
+ type_string = "OU";
+ } else if (type == TypeGivenNameOid()) {
+ type_string = "GN";
+ } else {
+ type_string = OidToString(type.UnsafeData(), type.Length());
+ if (type_string.empty())
+ return false;
+ value_string = "#" + base::HexEncode(value.UnsafeData(), value.Length());
+ }
+
+ if (value_string.empty()) {
+ std::string unescaped;
+ if (!ValueAsStringUnsafe(&unescaped))
+ return false;
+
+ bool nonprintable = false;
+ for (unsigned int i = 0; i < unescaped.length(); ++i) {
+ unsigned char c = static_cast<unsigned char>(unescaped[i]);
+ if (i == 0 && c == '#') {
+ value_string += "\\#";
+ } else if (i == 0 && c == ' ') {
+ value_string += "\\ ";
+ } else if (i == unescaped.length() - 1 && c == ' ') {
+ value_string += "\\ ";
+ } else if (c == ',' || c == '+' || c == '"' || c == '\\' || c == '<' ||
+ c == '>' || c == ';') {
+ value_string += "\\";
+ value_string += c;
+ } else if (c < 32 || c > 126) {
+ nonprintable = true;
+ std::string h;
+ h += c;
+ value_string += "\\" + base::HexEncode(h.data(), h.length());
+ } else {
+ value_string += c;
+ }
+ }
+
+ // If we have non-printable characters in a TeletexString, we hex encode
+ // since we don't handle Teletex control codes.
+ if (nonprintable && value_tag == der::kTeletexString)
+ value_string = "#" + base::HexEncode(value.UnsafeData(), value.Length());
+ }
+
+ *out = type_string + "=" + value_string;
+ return true;
+}
+
+bool ReadRdn(der::Parser* parser, RelativeDistinguishedName* out) {
+ while (parser->HasMore()) {
+ der::Parser attr_type_and_value;
+ if (!parser->ReadSequence(&attr_type_and_value))
+ return false;
+ // Read the attribute type, which must be an OBJECT IDENTIFIER.
+ der::Input type;
+ if (!attr_type_and_value.ReadTag(der::kOid, &type))
+ return false;
+
+ // Read the attribute value.
+ der::Tag tag;
+ der::Input value;
+ if (!attr_type_and_value.ReadTagAndValue(&tag, &value))
+ return false;
+
+ // There should be no more elements in the sequence after reading the
+ // attribute type and value.
+ if (attr_type_and_value.HasMore())
+ return false;
+
+ out->push_back(X509NameAttribute(type, tag, value));
+ }
+
+ // RFC 5280 section 4.1.2.4
+ // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
+ return out->size() != 0;
+}
+
+bool ParseName(const der::Input& name_tlv, RDNSequence* out) {
+ der::Parser name_parser(name_tlv);
+ der::Parser rdn_sequence_parser;
+ if (!name_parser.ReadSequence(&rdn_sequence_parser))
+ return false;
+
+ while (rdn_sequence_parser.HasMore()) {
+ der::Parser rdn_parser;
+ if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser))
+ return false;
+ RelativeDistinguishedName type_and_values;
+ if (!ReadRdn(&rdn_parser, &type_and_values))
+ return false;
+ out->push_back(type_and_values);
+ }
+
+ return true;
+}
+
+bool ConvertToRFC2253(const RDNSequence& rdn_sequence, std::string* out) {
+ std::string rdns_string;
+ size_t size = rdn_sequence.size();
+ for (size_t i = 0; i < size; ++i) {
+ RelativeDistinguishedName rdn = rdn_sequence[size - i - 1];
+ std::string rdn_string;
+ for (const auto& atv : rdn) {
+ if (!rdn_string.empty())
+ rdn_string += "+";
+ std::string atv_string;
+ if (!atv.AsRFC2253String(&atv_string))
+ return false;
+ rdn_string += atv_string;
+ }
+ if (!rdns_string.empty())
+ rdns_string += ",";
+ rdns_string += rdn_string;
+ }
+
+ *out = rdns_string;
+ return true;
+}
+
+} // namespace net
diff --git a/chromium/net/cert/internal/parse_name.h b/chromium/net/cert/internal/parse_name.h
new file mode 100644
index 00000000000..00d2bbb7ef1
--- /dev/null
+++ b/chromium/net/cert/internal/parse_name.h
@@ -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.
+
+#ifndef NET_CERT_INTERNAL_PARSE_NAME_H_
+#define NET_CERT_INTERNAL_PARSE_NAME_H_
+
+#include <vector>
+
+#include "net/base/net_export.h"
+#include "net/der/input.h"
+#include "net/der/parser.h"
+#include "net/der/tag.h"
+
+namespace net {
+
+NET_EXPORT der::Input TypeCommonNameOid();
+NET_EXPORT der::Input TypeSurnameOid();
+NET_EXPORT der::Input TypeSerialNumberOid();
+NET_EXPORT der::Input TypeCountryNameOid();
+NET_EXPORT der::Input TypeLocalityNameOid();
+NET_EXPORT der::Input TypeStateOrProvinceNameOid();
+NET_EXPORT der::Input TypeOrganizationNameOid();
+NET_EXPORT der::Input TypeOrganizationUnitNameOid();
+NET_EXPORT der::Input TypeTitleOid();
+NET_EXPORT der::Input TypeNameOid();
+NET_EXPORT der::Input TypeGivenNameOid();
+NET_EXPORT der::Input TypeInitialsOid();
+NET_EXPORT der::Input TypeGenerationQualifierOid();
+
+// X509NameAttribute contains a representation of a DER-encoded RFC 2253
+// "AttributeTypeAndValue".
+//
+// AttributeTypeAndValue ::= SEQUENCE {
+// type AttributeType,
+// value AttributeValue
+// }
+struct NET_EXPORT X509NameAttribute {
+ X509NameAttribute(der::Input in_type,
+ der::Tag in_value_tag,
+ der::Input in_value)
+ : type(in_type), value_tag(in_value_tag), value(in_value) {}
+
+ // Attempts to convert the value represented by this struct into a
+ // std::string and store it in |out|, returning whether the conversion was
+ // successful. Due to some encodings being incompatible, the caller must
+ // verify the attribute |type|.
+ //
+ // Note: The conversion doesn't verify that the value corresponds to the
+ // ASN.1 definition of the value type.
+ bool ValueAsStringUnsafe(std::string* out) const WARN_UNUSED_RESULT;
+
+ // Formats the NameAttribute per RFC2253 into an ASCII string and stores
+ // the result in |out|, returning whether the conversion was successful.
+ bool AsRFC2253String(std::string* out) const WARN_UNUSED_RESULT;
+
+ der::Input type;
+ der::Tag value_tag;
+ der::Input value;
+};
+
+typedef std::vector<X509NameAttribute> RelativeDistinguishedName;
+typedef std::vector<RelativeDistinguishedName> RDNSequence;
+
+// Parses all the ASN.1 AttributeTypeAndValue elements in |parser| and stores
+// each as an AttributeTypeAndValue object in |out|.
+//
+// AttributeTypeAndValue is defined in RFC 5280 section 4.1.2.4:
+//
+// AttributeTypeAndValue ::= SEQUENCE {
+// type AttributeType,
+// value AttributeValue }
+//
+// AttributeType ::= OBJECT IDENTIFIER
+//
+// AttributeValue ::= ANY -- DEFINED BY AttributeType
+//
+// DirectoryString ::= CHOICE {
+// teletexString TeletexString (SIZE (1..MAX)),
+// printableString PrintableString (SIZE (1..MAX)),
+// universalString UniversalString (SIZE (1..MAX)),
+// utf8String UTF8String (SIZE (1..MAX)),
+// bmpString BMPString (SIZE (1..MAX)) }
+//
+// The type of the component AttributeValue is determined by the AttributeType;
+// in general it will be a DirectoryString.
+NET_EXPORT bool ReadRdn(der::Parser* parser,
+ RelativeDistinguishedName* out) WARN_UNUSED_RESULT;
+
+// Parses a DER-encoded "Name" as specified by 5280. Returns true on success
+// and sets the results in |out|.
+NET_EXPORT bool ParseName(const der::Input& name_tlv,
+ RDNSequence* out) WARN_UNUSED_RESULT;
+
+// Formats a RDNSequence |rdn_sequence| per RFC2253 as an ASCII string and
+// stores the result into |out|, and returns whether the conversion was
+// successful.
+NET_EXPORT bool ConvertToRFC2253(const RDNSequence& rdn_sequence,
+ std::string* out) WARN_UNUSED_RESULT;
+} // namespace net
+
+#endif // NET_CERT_INTERNAL_PARSE_NAME_H_
diff --git a/chromium/net/cert/internal/parse_name_unittest.cc b/chromium/net/cert/internal/parse_name_unittest.cc
new file mode 100644
index 00000000000..b1d768fda61
--- /dev/null
+++ b/chromium/net/cert/internal/parse_name_unittest.cc
@@ -0,0 +1,248 @@
+// 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/parse_name.h"
+
+#include "net/cert/internal/test_helpers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+// Loads test data from file. The filename is constructed from the parameters:
+// |prefix| describes the type of data being tested, e.g. "ascii",
+// "unicode_bmp", "unicode_supplementary", and "invalid".
+// |value_type| indicates what ASN.1 type is used to encode the data.
+// |suffix| indicates any additional modifications, such as caseswapping,
+// whitespace adding, etc.
+::testing::AssertionResult LoadTestData(const std::string& prefix,
+ const std::string& value_type,
+ const std::string& suffix,
+ std::string* result) {
+ std::string path = "net/data/verify_name_match_unittest/names/" + prefix +
+ "-" + value_type + "-" + suffix + ".pem";
+
+ const PemBlockMapping mappings[] = {
+ {"NAME", result},
+ };
+
+ return ReadTestDataFromPemFile(path, mappings);
+}
+}
+
+TEST(ParseNameTest, ConvertBmpString) {
+ const uint8_t der[] = {
+ 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x61, 0x00, 0x72,
+ };
+ X509NameAttribute value(der::Input(), der::kBmpString, der::Input(der));
+ std::string result;
+ ASSERT_TRUE(value.ValueAsStringUnsafe(&result));
+ ASSERT_EQ("foobar", result);
+}
+
+// BmpString must encode characters in pairs of 2 bytes.
+TEST(ParseNameTest, ConvertInvalidBmpString) {
+ const uint8_t der[] = {0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x72};
+ X509NameAttribute value(der::Input(), der::kBmpString, der::Input(der));
+ std::string result;
+ ASSERT_FALSE(value.ValueAsStringUnsafe(&result));
+}
+
+TEST(ParseNameTest, ConvertUniversalString) {
+ const uint8_t der[] = {0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x6f,
+ 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x62,
+ 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x72};
+ X509NameAttribute value(der::Input(), der::kUniversalString, der::Input(der));
+ std::string result;
+ ASSERT_TRUE(value.ValueAsStringUnsafe(&result));
+}
+
+// UniversalString must encode characters in pairs of 4 bytes.
+TEST(ParseNameTest, ConvertInvalidUniversalString) {
+ const uint8_t der[] = {0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72};
+ X509NameAttribute value(der::Input(), der::kUniversalString, der::Input(der));
+ std::string result;
+ ASSERT_FALSE(value.ValueAsStringUnsafe(&result));
+}
+
+TEST(ParseNameTest, EmptyName) {
+ const uint8_t der[] = {0x30, 0x00};
+ der::Input rdn(der);
+ RDNSequence atv;
+ ASSERT_TRUE(ParseName(rdn, &atv));
+ ASSERT_EQ(0u, atv.size());
+}
+
+TEST(ParseNameTest, ValidName) {
+ const uint8_t der[] = {0x30, 0x3c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30,
+ 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63,
+ 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x0e, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41};
+ der::Input rdn(der);
+ RDNSequence atv;
+ ASSERT_TRUE(ParseName(rdn, &atv));
+ ASSERT_EQ(3u, atv.size());
+ ASSERT_EQ(1u, atv[0].size());
+ ASSERT_EQ(TypeCountryNameOid(), atv[0][0].type);
+ ASSERT_EQ("US", atv[0][0].value.AsString());
+ ASSERT_EQ(1u, atv[1].size());
+ ASSERT_EQ(TypeOrganizationNameOid(), atv[1][0].type);
+ ASSERT_EQ("Google Inc.", atv[1][0].value.AsString());
+ ASSERT_EQ(1u, atv[2].size());
+ ASSERT_EQ(TypeCommonNameOid(), atv[2][0].type);
+ ASSERT_EQ("Google Test CA", atv[2][0].value.AsString());
+}
+
+TEST(ParseNameTest, InvalidNameExtraData) {
+ std::string invalid;
+ ASSERT_TRUE(
+ LoadTestData("invalid", "AttributeTypeAndValue", "extradata", &invalid));
+ RDNSequence atv;
+ ASSERT_FALSE(ParseName(SequenceValueFromString(&invalid), &atv));
+}
+
+TEST(ParseNameTest, InvalidNameEmpty) {
+ std::string invalid;
+ ASSERT_TRUE(
+ LoadTestData("invalid", "AttributeTypeAndValue", "empty", &invalid));
+ RDNSequence atv;
+ ASSERT_FALSE(ParseName(SequenceValueFromString(&invalid), &atv));
+}
+
+TEST(ParseNameTest, InvalidNameBadType) {
+ std::string invalid;
+ ASSERT_TRUE(LoadTestData("invalid", "AttributeTypeAndValue",
+ "badAttributeType", &invalid));
+ RDNSequence atv;
+ ASSERT_FALSE(ParseName(SequenceValueFromString(&invalid), &atv));
+}
+
+TEST(ParseNameTest, InvalidNameNotSequence) {
+ std::string invalid;
+ ASSERT_TRUE(LoadTestData("invalid", "AttributeTypeAndValue", "setNotSequence",
+ &invalid));
+ RDNSequence atv;
+ ASSERT_FALSE(ParseName(SequenceValueFromString(&invalid), &atv));
+}
+
+TEST(ParseNameTest, InvalidNameNotSet) {
+ std::string invalid;
+ ASSERT_TRUE(LoadTestData("invalid", "RDN", "sequenceInsteadOfSet", &invalid));
+ RDNSequence atv;
+ ASSERT_FALSE(ParseName(SequenceValueFromString(&invalid), &atv));
+}
+
+TEST(ParseNameTest, InvalidNameEmptyRdn) {
+ std::string invalid;
+ ASSERT_TRUE(LoadTestData("invalid", "RDN", "empty", &invalid));
+ RDNSequence atv;
+ ASSERT_FALSE(ParseName(SequenceValueFromString(&invalid), &atv));
+}
+
+TEST(ParseNameTest, RFC2253FormatBasic) {
+ const uint8_t der[] = {0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x16, 0x30,
+ 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x49,
+ 0x73, 0x6f, 0x64, 0x65, 0x20, 0x4c, 0x69, 0x6d, 0x69,
+ 0x74, 0x65, 0x64, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x13, 0x0b, 0x53, 0x74, 0x65, 0x76,
+ 0x65, 0x20, 0x4b, 0x69, 0x6c, 0x6c, 0x65};
+ der::Input rdn_input(der);
+ RDNSequence rdn;
+ ASSERT_TRUE(ParseName(rdn_input, &rdn));
+ std::string output;
+ ASSERT_TRUE(ConvertToRFC2253(rdn, &output));
+ ASSERT_EQ("CN=Steve Kille,O=Isode Limited,C=GB", output);
+}
+
+TEST(ParseNameTest, RFC2253FormatMultiRDN) {
+ const uint8_t der[] = {
+ 0x30, 0x44, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x0b, 0x57, 0x69, 0x64, 0x67, 0x65, 0x74, 0x20, 0x49, 0x6e, 0x63,
+ 0x2e, 0x31, 0x1f, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x05,
+ 0x53, 0x61, 0x6c, 0x65, 0x73, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x13, 0x08, 0x4a, 0x2e, 0x20, 0x53, 0x6d, 0x69, 0x74, 0x68};
+ der::Input rdn_input(der);
+ RDNSequence rdn;
+ ASSERT_TRUE(ParseName(rdn_input, &rdn));
+ std::string output;
+ ASSERT_TRUE(ConvertToRFC2253(rdn, &output));
+ ASSERT_EQ("OU=Sales+CN=J. Smith,O=Widget Inc.,C=US", output);
+}
+
+TEST(ParseNameTest, RFC2253FormatQuoted) {
+ const uint8_t der[] = {
+ 0x30, 0x40, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x47, 0x42, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x15, 0x53, 0x75, 0x65, 0x2c, 0x20, 0x47, 0x72,
+ 0x61, 0x62, 0x62, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52,
+ 0x75, 0x6e, 0x6e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x08, 0x4c, 0x2e, 0x20, 0x45, 0x61, 0x67, 0x6c, 0x65};
+ der::Input rdn_input(der);
+ RDNSequence rdn;
+ ASSERT_TRUE(ParseName(rdn_input, &rdn));
+ std::string output;
+ ASSERT_TRUE(ConvertToRFC2253(rdn, &output));
+ ASSERT_EQ("CN=L. Eagle,O=Sue\\, Grabbit and Runn,C=GB", output);
+}
+
+TEST(ParseNameTest, RFC2253FormatNonPrintable) {
+ const uint8_t der[] = {0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x0d, 0x30,
+ 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x04, 0x54,
+ 0x65, 0x73, 0x74, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x13, 0x0c, 0x42, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x0d, 0x41, 0x66, 0x74, 0x65, 0x72};
+ der::Input rdn_input(der);
+ RDNSequence rdn;
+ ASSERT_TRUE(ParseName(rdn_input, &rdn));
+ std::string output;
+ ASSERT_TRUE(ConvertToRFC2253(rdn, &output));
+ ASSERT_EQ("CN=Before\\0DAfter,O=Test,C=GB", output);
+}
+
+TEST(ParseNameTest, RFC2253FormatUnknownOid) {
+ const uint8_t der[] = {0x30, 0x30, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x0d, 0x30,
+ 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x04, 0x54,
+ 0x65, 0x73, 0x74, 0x31, 0x12, 0x30, 0x10, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x04, 0x01, 0x8b, 0x3a, 0x00, 0x13,
+ 0x04, 0x04, 0x02, 0x48, 0x69};
+ der::Input rdn_input(der);
+ RDNSequence rdn;
+ ASSERT_TRUE(ParseName(rdn_input, &rdn));
+ std::string output;
+ ASSERT_TRUE(ConvertToRFC2253(rdn, &output));
+ ASSERT_EQ("1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB", output);
+}
+
+TEST(ParseNameTest, RFC2253FormatLargeOid) {
+ const uint8_t der[] = {0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x0a,
+ 0x81, 0x0d, 0x06, 0x01, 0x99, 0x21, 0x01, 0x8b,
+ 0x3a, 0x00, 0x13, 0x04, 0x74, 0x65, 0x73, 0x74};
+ der::Input rdn_input(der);
+ RDNSequence rdn;
+ ASSERT_TRUE(ParseName(rdn_input, &rdn));
+ std::string output;
+ ASSERT_TRUE(ConvertToRFC2253(rdn, &output));
+ ASSERT_EQ("2.61.6.1.3233.1.1466.0=#74657374", output);
+}
+
+TEST(ParseNameTest, RFC2253FormatUTF8) {
+ const uint8_t der[] = {0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06,
+ 0x03, 0x55, 0x04, 0x04, 0x13, 0x07, 0x4c,
+ 0x75, 0xc4, 0x8d, 0x69, 0xc4, 0x87};
+ der::Input rdn_input(der);
+ RDNSequence rdn;
+ ASSERT_TRUE(ParseName(rdn_input, &rdn));
+ std::string output;
+ ASSERT_TRUE(ConvertToRFC2253(rdn, &output));
+ ASSERT_EQ("SN=Lu\\C4\\8Di\\C4\\87", output);
+}
+
+} // namespace net
diff --git a/chromium/net/cert/internal/parse_ocsp.cc b/chromium/net/cert/internal/parse_ocsp.cc
new file mode 100644
index 00000000000..e06b29abe61
--- /dev/null
+++ b/chromium/net/cert/internal/parse_ocsp.cc
@@ -0,0 +1,532 @@
+// 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 <algorithm>
+
+#include "base/sha1.h"
+#include "crypto/sha2.h"
+#include "net/cert/internal/parse_ocsp.h"
+
+namespace net {
+
+OCSPCertID::OCSPCertID() {}
+OCSPCertID::~OCSPCertID() {}
+
+OCSPSingleResponse::OCSPSingleResponse() {}
+OCSPSingleResponse::~OCSPSingleResponse() {}
+
+OCSPResponseData::OCSPResponseData() {}
+OCSPResponseData::~OCSPResponseData() {}
+
+OCSPResponse::OCSPResponse() {}
+OCSPResponse::~OCSPResponse() {}
+
+der::Input BasicOCSPResponseOid() {
+ // From RFC 6960:
+ //
+ // id-pkix-ocsp OBJECT IDENTIFIER ::= { id-ad-ocsp }
+ // id-pkix-ocsp-basic OBJECT IDENTIFIER ::= { id-pkix-ocsp 1 }
+ //
+ // In dotted notation: 1.3.6.1.5.5.7.48.1.1
+ static const uint8_t oid[] = {0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x01, 0x01};
+ return der::Input(oid);
+}
+
+// CertID ::= SEQUENCE {
+// hashAlgorithm AlgorithmIdentifier,
+// issuerNameHash OCTET STRING, -- Hash of issuer's DN
+// issuerKeyHash OCTET STRING, -- Hash of issuer's public key
+// serialNumber CertificateSerialNumber
+// }
+bool ParseOCSPCertID(const der::Input& raw_tlv, OCSPCertID* out) {
+ der::Parser outer_parser(raw_tlv);
+ der::Parser parser;
+ if (!outer_parser.ReadSequence(&parser))
+ return false;
+ if (outer_parser.HasMore())
+ return false;
+
+ der::Input sigalg_tlv;
+ if (!parser.ReadRawTLV(&sigalg_tlv))
+ return false;
+ if (!ParseHashAlgorithm(sigalg_tlv, &(out->hash_algorithm)))
+ return false;
+ if (!parser.ReadTag(der::kOctetString, &(out->issuer_name_hash)))
+ return false;
+ if (!parser.ReadTag(der::kOctetString, &(out->issuer_key_hash)))
+ return false;
+ if (!parser.ReadTag(der::kInteger, &(out->serial_number)))
+ return false;
+ if (!VerifySerialNumber(out->serial_number))
+ return false;
+
+ return !parser.HasMore();
+}
+
+namespace {
+
+// Parses |raw_tlv| to extract an OCSP RevokedInfo (RFC 6960) and stores the
+// result in the OCSPCertStatus |out|. Returns whether the parsing was
+// successful.
+//
+// RevokedInfo ::= SEQUENCE {
+// revocationTime GeneralizedTime,
+// revocationReason [0] EXPLICIT CRLReason OPTIONAL
+// }
+bool ParseRevokedInfo(const der::Input& raw_tlv, OCSPCertStatus* out) {
+ der::Parser parser(raw_tlv);
+ if (!parser.ReadGeneralizedTime(&(out->revocation_time)))
+ return false;
+
+ der::Input reason_input;
+ if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &reason_input,
+ &(out->has_reason))) {
+ return false;
+ }
+ if (out->has_reason) {
+ der::Parser reason_parser(reason_input);
+ der::Input reason_value_input;
+ uint8_t reason_value;
+ if (!reason_parser.ReadTag(der::kEnumerated, &reason_value_input))
+ return false;
+ if (!der::ParseUint8(reason_value_input, &reason_value))
+ return false;
+ if (reason_value >
+ static_cast<uint8_t>(OCSPCertStatus::RevocationReason::LAST)) {
+ return false;
+ }
+ out->revocation_reason =
+ static_cast<OCSPCertStatus::RevocationReason>(reason_value);
+ if (out->revocation_reason == OCSPCertStatus::RevocationReason::UNUSED)
+ return false;
+ if (reason_parser.HasMore())
+ return false;
+ }
+ return !parser.HasMore();
+}
+
+// Parses |raw_tlv| to extract an OCSP CertStatus (RFC 6960) and stores the
+// result in the OCSPCertStatus |out|. Returns whether the parsing was
+// successful.
+//
+// CertStatus ::= CHOICE {
+// good [0] IMPLICIT NULL,
+// revoked [1] IMPLICIT RevokedInfo,
+// unknown [2] IMPLICIT UnknownInfo
+// }
+//
+// UnknownInfo ::= NULL
+bool ParseCertStatus(const der::Input& raw_tlv, OCSPCertStatus* out) {
+ der::Parser parser(raw_tlv);
+ der::Tag status_tag;
+ der::Input status;
+ if (!parser.ReadTagAndValue(&status_tag, &status))
+ return false;
+
+ out->has_reason = false;
+ if (status_tag == der::ContextSpecificPrimitive(0)) {
+ out->status = OCSPCertStatus::Status::GOOD;
+ } else if (status_tag == der::ContextSpecificConstructed(1)) {
+ out->status = OCSPCertStatus::Status::REVOKED;
+ if (!ParseRevokedInfo(status, out))
+ return false;
+ } else if (status_tag == der::ContextSpecificPrimitive(2)) {
+ out->status = OCSPCertStatus::Status::UNKNOWN;
+ } else {
+ return false;
+ }
+
+ return !parser.HasMore();
+}
+
+} // namespace
+
+// SingleResponse ::= SEQUENCE {
+// certID CertID,
+// certStatus CertStatus,
+// thisUpdate GeneralizedTime,
+// nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+// singleExtensions [1] EXPLICIT Extensions OPTIONAL
+// }
+bool ParseOCSPSingleResponse(const der::Input& raw_tlv,
+ OCSPSingleResponse* out) {
+ der::Parser outer_parser(raw_tlv);
+ der::Parser parser;
+ if (!outer_parser.ReadSequence(&parser))
+ return false;
+ if (outer_parser.HasMore())
+ return false;
+
+ if (!parser.ReadRawTLV(&(out->cert_id_tlv)))
+ return false;
+ der::Input status_tlv;
+ if (!parser.ReadRawTLV(&status_tlv))
+ return false;
+ if (!ParseCertStatus(status_tlv, &(out->cert_status)))
+ return false;
+ if (!parser.ReadGeneralizedTime(&(out->this_update)))
+ return false;
+
+ der::Input next_update_input;
+ if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
+ &next_update_input, &(out->has_next_update))) {
+ return false;
+ }
+ if (out->has_next_update) {
+ der::Parser next_update_parser(next_update_input);
+ if (!next_update_parser.ReadGeneralizedTime(&(out->next_update)))
+ return false;
+ if (next_update_parser.HasMore())
+ return false;
+ }
+
+ if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(1),
+ &(out->extensions), &(out->has_extensions))) {
+ return false;
+ }
+
+ return !parser.HasMore();
+}
+
+namespace {
+
+// Parses |raw_tlv| to extract a ResponderID (RFC 6960) and stores the
+// result in the ResponderID |out|. Returns whether the parsing was successful.
+//
+// ResponderID ::= CHOICE {
+// byName [1] Name,
+// byKey [2] KeyHash
+// }
+bool ParseResponderID(const der::Input& raw_tlv,
+ OCSPResponseData::ResponderID* out) {
+ der::Parser parser(raw_tlv);
+ der::Tag id_tag;
+ der::Input id_input;
+ if (!parser.ReadTagAndValue(&id_tag, &id_input))
+ return false;
+
+ if (id_tag == der::ContextSpecificConstructed(1)) {
+ out->type = OCSPResponseData::ResponderType::NAME;
+ out->name = id_input;
+ } else if (id_tag == der::ContextSpecificConstructed(2)) {
+ der::Parser key_parser(id_input);
+ der::Input responder_key;
+ if (!key_parser.ReadTag(der::kOctetString, &responder_key))
+ return false;
+ if (key_parser.HasMore())
+ return false;
+
+ SHA1HashValue key_hash;
+ if (responder_key.Length() != sizeof(key_hash.data))
+ return false;
+ memcpy(key_hash.data, responder_key.UnsafeData(), sizeof(key_hash.data));
+ out->type = OCSPResponseData::ResponderType::KEY_HASH;
+ out->key_hash = HashValue(key_hash);
+ } else {
+ return false;
+ }
+ return !parser.HasMore();
+}
+
+} // namespace
+
+// ResponseData ::= SEQUENCE {
+// version [0] EXPLICIT Version DEFAULT v1,
+// responderID ResponderID,
+// producedAt GeneralizedTime,
+// responses SEQUENCE OF SingleResponse,
+// responseExtensions [1] EXPLICIT Extensions OPTIONAL
+// }
+bool ParseOCSPResponseData(const der::Input& raw_tlv, OCSPResponseData* out) {
+ der::Parser outer_parser(raw_tlv);
+ der::Parser parser;
+ if (!outer_parser.ReadSequence(&parser))
+ return false;
+ if (outer_parser.HasMore())
+ return false;
+
+ der::Input version_input;
+ bool version_present;
+ if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
+ &version_input, &version_present)) {
+ return false;
+ }
+
+ // For compatibilty, we ignore the restriction from X.690 Section 11.5 that
+ // DEFAULT values should be omitted for values equal to the default value.
+ // TODO: Add warning about non-strict parsing.
+ if (version_present) {
+ der::Parser version_parser(version_input);
+ if (!version_parser.ReadUint8(&(out->version)))
+ return false;
+ if (version_parser.HasMore())
+ return false;
+ } else {
+ out->version = 0;
+ }
+
+ if (out->version != 0)
+ return false;
+
+ der::Input responder_input;
+ if (!parser.ReadRawTLV(&responder_input))
+ return false;
+ if (!ParseResponderID(responder_input, &(out->responder_id)))
+ return false;
+ if (!parser.ReadGeneralizedTime(&(out->produced_at)))
+ return false;
+
+ der::Parser responses_parser;
+ if (!parser.ReadSequence(&responses_parser))
+ return false;
+ out->responses.clear();
+ while (responses_parser.HasMore()) {
+ der::Input single_response;
+ if (!responses_parser.ReadRawTLV(&single_response))
+ return false;
+ out->responses.push_back(single_response);
+ }
+
+ if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(1),
+ &(out->extensions), &(out->has_extensions))) {
+ return false;
+ }
+
+ return !parser.HasMore();
+}
+
+namespace {
+
+// Parses |raw_tlv| to extract a BasicOCSPResponse (RFC 6960) and stores the
+// result in the OCSPResponse |out|. Returns whether the parsing was
+// successful.
+//
+// BasicOCSPResponse ::= SEQUENCE {
+// tbsResponseData ResponseData,
+// signatureAlgorithm AlgorithmIdentifier,
+// signature BIT STRING,
+// certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
+// }
+bool ParseBasicOCSPResponse(const der::Input& raw_tlv, OCSPResponse* out) {
+ der::Parser outer_parser(raw_tlv);
+ der::Parser parser;
+ if (!outer_parser.ReadSequence(&parser))
+ return false;
+ if (outer_parser.HasMore())
+ return false;
+
+ if (!parser.ReadRawTLV(&(out->data)))
+ return false;
+ der::Input sigalg_tlv;
+ if (!parser.ReadRawTLV(&sigalg_tlv))
+ return false;
+ out->signature_algorithm = SignatureAlgorithm::CreateFromDer(sigalg_tlv);
+ if (!out->signature_algorithm)
+ return false;
+ if (!parser.ReadBitString(&(out->signature)))
+ return false;
+ der::Input certs_input;
+ if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &certs_input,
+ &(out->has_certs))) {
+ return false;
+ }
+
+ out->certs.clear();
+ if (out->has_certs) {
+ der::Parser certs_seq_parser(certs_input);
+ der::Parser certs_parser;
+ if (!certs_seq_parser.ReadSequence(&certs_parser))
+ return false;
+ if (certs_seq_parser.HasMore())
+ return false;
+ while (certs_parser.HasMore()) {
+ der::Input cert_tlv;
+ if (!certs_parser.ReadRawTLV(&cert_tlv))
+ return false;
+ out->certs.push_back(cert_tlv);
+ }
+ }
+
+ return !parser.HasMore();
+}
+
+} // namespace
+
+// OCSPResponse ::= SEQUENCE {
+// responseStatus OCSPResponseStatus,
+// responseBytes [0] EXPLICIT ResponseBytes OPTIONAL
+// }
+//
+// ResponseBytes ::= SEQUENCE {
+// responseType OBJECT IDENTIFIER,
+// response OCTET STRING
+// }
+bool ParseOCSPResponse(const der::Input& raw_tlv, OCSPResponse* out) {
+ der::Parser outer_parser(raw_tlv);
+ der::Parser parser;
+ if (!outer_parser.ReadSequence(&parser))
+ return false;
+ if (outer_parser.HasMore())
+ return false;
+
+ der::Input response_status_input;
+ uint8_t response_status;
+ if (!parser.ReadTag(der::kEnumerated, &response_status_input))
+ return false;
+ if (!der::ParseUint8(response_status_input, &response_status))
+ return false;
+ if (response_status >
+ static_cast<uint8_t>(OCSPResponse::ResponseStatus::LAST)) {
+ return false;
+ }
+ out->status = static_cast<OCSPResponse::ResponseStatus>(response_status);
+ if (out->status == OCSPResponse::ResponseStatus::UNUSED)
+ return false;
+
+ if (out->status == OCSPResponse::ResponseStatus::SUCCESSFUL) {
+ der::Parser outer_bytes_parser;
+ der::Parser bytes_parser;
+ if (!parser.ReadConstructed(der::ContextSpecificConstructed(0),
+ &outer_bytes_parser)) {
+ return false;
+ }
+ if (!outer_bytes_parser.ReadSequence(&bytes_parser))
+ return false;
+ if (outer_bytes_parser.HasMore())
+ return false;
+
+ der::Input type_oid;
+ if (!bytes_parser.ReadTag(der::kOid, &type_oid))
+ return false;
+ if (type_oid != BasicOCSPResponseOid())
+ return false;
+
+ // As per RFC 6960 Section 4.2.1, the value of |response| SHALL be the DER
+ // encoding of BasicOCSPResponse.
+ der::Input response;
+ if (!bytes_parser.ReadTag(der::kOctetString, &response))
+ return false;
+ if (!ParseBasicOCSPResponse(response, out))
+ return false;
+ if (bytes_parser.HasMore())
+ return false;
+ }
+
+ return !parser.HasMore();
+}
+
+namespace {
+
+// Checks that the |type| hash of |value| is equal to |hash|
+bool VerifyHash(HashValueTag type,
+ const der::Input& hash,
+ const der::Input& value) {
+ HashValue target(type);
+ if (target.size() != hash.Length())
+ return false;
+ memcpy(target.data(), hash.UnsafeData(), target.size());
+
+ HashValue value_hash(type);
+ if (type == HASH_VALUE_SHA1) {
+ base::SHA1HashBytes(value.UnsafeData(), value.Length(), value_hash.data());
+ } else if (type == HASH_VALUE_SHA256) {
+ std::string hash_string = crypto::SHA256HashString(value.AsString());
+ memcpy(value_hash.data(), hash_string.data(), value_hash.size());
+ } else {
+ return false;
+ }
+
+ return target.Equals(value_hash);
+}
+
+// Checks that the input |id_tlv| parses to a valid CertID and matches the
+// issuer |issuer| name and key, as well as the serial number |serial_number|.
+bool CheckCertID(const der::Input& id_tlv,
+ const ParsedTbsCertificate& certificate,
+ const ParsedTbsCertificate& issuer,
+ const der::Input& serial_number) {
+ OCSPCertID id;
+ if (!ParseOCSPCertID(id_tlv, &id))
+ return false;
+
+ HashValueTag type = HASH_VALUE_SHA1;
+ switch (id.hash_algorithm) {
+ case DigestAlgorithm::Sha1:
+ type = HASH_VALUE_SHA1;
+ break;
+ case DigestAlgorithm::Sha256:
+ type = HASH_VALUE_SHA256;
+ break;
+ case DigestAlgorithm::Sha384:
+ case DigestAlgorithm::Sha512:
+ NOTIMPLEMENTED();
+ return false;
+ }
+
+ if (!VerifyHash(type, id.issuer_name_hash, certificate.issuer_tlv))
+ return false;
+
+ // SubjectPublicKeyInfo ::= SEQUENCE {
+ // algorithm AlgorithmIdentifier,
+ // subjectPublicKey BIT STRING
+ // }
+ der::Parser outer_parser(issuer.spki_tlv);
+ der::Parser spki_parser;
+ der::BitString key_bits;
+ if (!outer_parser.ReadSequence(&spki_parser))
+ return false;
+ if (outer_parser.HasMore())
+ return false;
+ if (!spki_parser.SkipTag(der::kSequence))
+ return false;
+ if (!spki_parser.ReadBitString(&key_bits))
+ return false;
+ der::Input key_tlv = key_bits.bytes();
+ if (!VerifyHash(type, id.issuer_key_hash, key_tlv))
+ return false;
+
+ return id.serial_number == serial_number;
+}
+
+} // namespace
+
+bool GetOCSPCertStatus(const OCSPResponseData& response_data,
+ const ParsedCertificate& issuer,
+ const ParsedCertificate& cert,
+ OCSPCertStatus* out) {
+ out->status = OCSPCertStatus::Status::GOOD;
+
+ ParsedTbsCertificate tbs_cert;
+ if (!ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs_cert))
+ return false;
+ ParsedTbsCertificate issuer_tbs_cert;
+ if (!ParseTbsCertificate(issuer.tbs_certificate_tlv, &issuer_tbs_cert))
+ return false;
+
+ bool found = false;
+ for (const auto& response : response_data.responses) {
+ OCSPSingleResponse single_response;
+ if (!ParseOCSPSingleResponse(response, &single_response))
+ return false;
+ if (CheckCertID(single_response.cert_id_tlv, tbs_cert, issuer_tbs_cert,
+ tbs_cert.serial_number)) {
+ OCSPCertStatus new_status = single_response.cert_status;
+ found = true;
+ // In the case that we receive multiple responses, we keep only the
+ // strictest status (REVOKED > UNKNOWN > GOOD).
+ if (out->status == OCSPCertStatus::Status::GOOD ||
+ new_status.status == OCSPCertStatus::Status::REVOKED) {
+ *out = new_status;
+ }
+ }
+ }
+
+ if (!found)
+ out->status = OCSPCertStatus::Status::UNKNOWN;
+
+ return found;
+}
+
+} // namespace net
diff --git a/chromium/net/cert/internal/parse_ocsp.h b/chromium/net/cert/internal/parse_ocsp.h
new file mode 100644
index 00000000000..63ee3e8e2a5
--- /dev/null
+++ b/chromium/net/cert/internal/parse_ocsp.h
@@ -0,0 +1,282 @@
+// 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_PARSE_OCSP_H_
+#define NET_CERT_INTERNAL_PARSE_OCSP_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "net/base/hash_value.h"
+#include "net/cert/internal/parse_certificate.h"
+#include "net/cert/internal/signature_algorithm.h"
+#include "net/der/input.h"
+#include "net/der/parse_values.h"
+#include "net/der/parser.h"
+#include "net/der/tag.h"
+
+namespace net {
+
+// OCSPCertID contains a representation of a DER-encoded RFC 6960 "CertID".
+//
+// CertID ::= SEQUENCE {
+// hashAlgorithm AlgorithmIdentifier,
+// issuerNameHash OCTET STRING, -- Hash of issuer's DN
+// issuerKeyHash OCTET STRING, -- Hash of issuer's public key
+// serialNumber CertificateSerialNumber
+// }
+struct OCSPCertID {
+ OCSPCertID();
+ ~OCSPCertID();
+
+ DigestAlgorithm hash_algorithm;
+ der::Input issuer_name_hash;
+ der::Input issuer_key_hash;
+ der::Input serial_number;
+};
+
+// OCSPCertStatus contains a representation of a DER-encoded RFC 6960
+// "CertStatus". |revocation_time| and |has_reason| are only valid when
+// |status| is REVOKED. |revocation_reason| is only valid when |has_reason| is
+// true.
+//
+// CertStatus ::= CHOICE {
+// good [0] IMPLICIT NULL,
+// revoked [1] IMPLICIT RevokedInfo,
+// unknown [2] IMPLICIT UnknownInfo
+// }
+//
+// RevokedInfo ::= SEQUENCE {
+// revocationTime GeneralizedTime,
+// revocationReason [0] EXPLICIT CRLReason OPTIONAL
+// }
+//
+// UnknownInfo ::= NULL
+//
+// CRLReason ::= ENUMERATED {
+// unspecified (0),
+// keyCompromise (1),
+// cACompromise (2),
+// affiliationChanged (3),
+// superseded (4),
+// cessationOfOperation (5),
+// certificateHold (6),
+// -- value 7 is not used
+// removeFromCRL (8),
+// privilegeWithdrawn (9),
+// aACompromise (10)
+// }
+// (from RFC 5280)
+struct OCSPCertStatus {
+ enum class Status {
+ GOOD,
+ REVOKED,
+ UNKNOWN,
+ };
+
+ // Correspond to the values of CRLReason
+ enum class RevocationReason {
+ UNSPECIFIED = 0,
+ KEY_COMPROMISE = 1,
+ CA_COMPROMISE = 2,
+ AFFILIATION_CHANGED = 3,
+ SUPERSEDED = 4,
+ CESSATION_OF_OPERATION = 5,
+ CERTIFICATE_HOLD = 6,
+ UNUSED = 7,
+ REMOVE_FROM_CRL = 8,
+ PRIVILEGE_WITHDRAWN = 9,
+ AA_COMPROMISE = 10,
+
+ LAST = AA_COMPROMISE,
+ };
+
+ Status status;
+ der::GeneralizedTime revocation_time;
+ bool has_reason;
+ RevocationReason revocation_reason;
+};
+
+// OCSPSingleResponse contains a representation of a DER-encoded RFC 6960
+// "SingleResponse". The |cert_id_tlv| and |extensions| fields are pointers to
+// the original object and are only valid as long as it is alive. They also
+// aren't verified until they are parsed. |next_update| is only valid if
+// |has_next_update| is true and |extensions| is only valid if |has_extensions|
+// is true.
+//
+// SingleResponse ::= SEQUENCE {
+// certID CertID,
+// certStatus CertStatus,
+// thisUpdate GeneralizedTime,
+// nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+// singleExtensions [1] EXPLICIT Extensions OPTIONAL
+// }
+struct NET_EXPORT OCSPSingleResponse {
+ OCSPSingleResponse();
+ ~OCSPSingleResponse();
+
+ der::Input cert_id_tlv;
+ OCSPCertStatus cert_status;
+ der::GeneralizedTime this_update;
+ bool has_next_update;
+ der::GeneralizedTime next_update;
+ bool has_extensions;
+ der::Input extensions;
+};
+
+// OCSPResponseData contains a representation of a DER-encoded RFC 6960
+// "ResponseData". The |responses| and |extensions| fields are pointers to the
+// original object and are only valid as long as it is alive. They also aren't
+// verified until they are parsed into OCSPSingleResponse and ParsedExtensions.
+// |extensions| is only valid if |has_extensions| is true.
+//
+// ResponseData ::= SEQUENCE {
+// version [0] EXPLICIT Version DEFAULT v1,
+// responderID ResponderID,
+// producedAt GeneralizedTime,
+// responses SEQUENCE OF SingleResponse,
+// responseExtensions [1] EXPLICIT Extensions OPTIONAL
+// }
+struct NET_EXPORT OCSPResponseData {
+ enum class ResponderType { NAME, KEY_HASH };
+
+ struct ResponderID {
+ ResponderType type;
+ der::Input name;
+ HashValue key_hash;
+ };
+
+ OCSPResponseData();
+ ~OCSPResponseData();
+
+ uint8_t version;
+ OCSPResponseData::ResponderID responder_id;
+ der::GeneralizedTime produced_at;
+ std::vector<der::Input> responses;
+ bool has_extensions;
+ der::Input extensions;
+};
+
+// OCSPResponse contains a representation of a DER-encoded RFC 6960
+// "OCSPResponse" and the corresponding "BasicOCSPResponse". The |data| field
+// is a pointer to the original object and are only valid as long is it is
+// alive. The |data| field isn't verified until it is parsed into an
+// OCSPResponseData. |data|, |signature_algorithm|, |signature|, and
+// |has_certs| is only valid if |status| is SUCCESSFUL. |certs| is only valid
+// if |has_certs| is true.
+//
+// OCSPResponse ::= SEQUENCE {
+// responseStatus OCSPResponseStatus,
+// responseBytes [0] EXPLICIT ResponseBytes OPTIONAL
+// }
+//
+// ResponseBytes ::= SEQUENCE {
+// responseType OBJECT IDENTIFIER,
+// response OCTET STRING
+// }
+//
+// BasicOCSPResponse ::= SEQUENCE {
+// tbsResponseData ResponseData,
+// signatureAlgorithm AlgorithmIdentifier,
+// signature BIT STRING,
+// certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
+// }
+//
+// OCSPResponseStatus ::= ENUMERATED {
+// successful (0), -- Response has valid confirmations
+// malformedRequest (1), -- Illegal confirmation request
+// internalError (2), -- Internal error in issuer
+// tryLater (3), -- Try again later
+// -- (4) is not used
+// sigRequired (5), -- Must sign the request
+// unauthorized (6) -- Request unauthorized
+// }
+struct NET_EXPORT OCSPResponse {
+ // Correspond to the values of OCSPResponseStatus
+ enum class ResponseStatus {
+ SUCCESSFUL = 0,
+ MALFORMED_REQUEST = 1,
+ INTERNAL_ERROR = 2,
+ TRY_LATER = 3,
+ UNUSED = 4,
+ SIG_REQUIRED = 5,
+ UNAUTHORIZED = 6,
+
+ LAST = UNAUTHORIZED,
+ };
+
+ OCSPResponse();
+ ~OCSPResponse();
+
+ ResponseStatus status;
+ der::Input data;
+ scoped_ptr<SignatureAlgorithm> signature_algorithm;
+ der::BitString signature;
+ bool has_certs;
+ std::vector<der::Input> certs;
+};
+
+// From RFC 6960:
+//
+// id-pkix-ocsp OBJECT IDENTIFIER ::= { id-ad-ocsp }
+// id-pkix-ocsp-basic OBJECT IDENTIFIER ::= { id-pkix-ocsp 1 }
+//
+// In dotted notation: 1.3.6.1.5.5.7.48.1.1
+NET_EXPORT der::Input BasicOCSPResponseOid();
+
+// Parses a DER-encoded OCSP "CertID" as specified by RFC 6960. Returns true on
+// success and sets the results in |out|.
+//
+// On failure |out| has an undefined state. Some of its fields may have been
+// updated during parsing, whereas others may not have been changed.
+NET_EXPORT_PRIVATE bool ParseOCSPCertID(const der::Input& raw_tlv,
+ OCSPCertID* out);
+
+// Parses a DER-encoded OCSP "SingleResponse" as specified by RFC 6960. Returns
+// true on success and sets the results in |out|. The resulting |out|
+// references data from |raw_tlv| and is only valid for the lifetime of
+// |raw_tlv|.
+//
+// On failure |out| has an undefined state. Some of its fields may have been
+// updated during parsing, whereas others may not have been changed.
+NET_EXPORT_PRIVATE bool ParseOCSPSingleResponse(const der::Input& raw_tlv,
+ OCSPSingleResponse* out);
+
+// Parses a DER-encoded OCSP "ResponseData" as specified by RFC 6960. Returns
+// true on success and sets the results in |out|. The resulting |out|
+// references data from |raw_tlv| and is only valid for the lifetime of
+// |raw_tlv|.
+//
+// On failure |out| has an undefined state. Some of its fields may have been
+// updated during parsing, whereas others may not have been changed.
+NET_EXPORT_PRIVATE bool ParseOCSPResponseData(const der::Input& raw_tlv,
+ OCSPResponseData* out);
+
+// Parses a DER-encoded "OCSPResponse" as specified by RFC 6960. Returns true
+// on success and sets the results in |out|. The resulting |out|
+// references data from |raw_tlv| and is only valid for the lifetime of
+// |raw_tlv|.
+//
+// On failure |out| has an undefined state. Some of its fields may have been
+// updated during parsing, whereas others may not have been changed.
+NET_EXPORT_PRIVATE bool ParseOCSPResponse(const der::Input& raw_tlv,
+ OCSPResponse* out);
+
+// Checks the certificate status of |cert| based on the OCSPResponseData
+// |response_data| and issuer |issuer| and sets the results in |out|. In the
+// case that there are multiple responses for a given certificate, as a result
+// of caching or performance (RFC 6960, 4.2.2.3), the strictest response is
+// returned (REVOKED > UNKNOWN > GOOD).
+//
+// On failure |out| has an undefined state. Some of its fields may have been
+// updated during parsing, whereas others may not have been changed.
+NET_EXPORT_PRIVATE bool GetOCSPCertStatus(const OCSPResponseData& response_data,
+ const ParsedCertificate& issuer,
+ const ParsedCertificate& cert,
+ OCSPCertStatus* out);
+
+} // namespace net
+
+#endif // NET_CERT_INTERNAL_PARSE_OCSP_H_
diff --git a/chromium/net/cert/internal/parse_ocsp_unittest.cc b/chromium/net/cert/internal/parse_ocsp_unittest.cc
new file mode 100644
index 00000000000..12657e62695
--- /dev/null
+++ b/chromium/net/cert/internal/parse_ocsp_unittest.cc
@@ -0,0 +1,177 @@
+// 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/parse_ocsp.h"
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "net/base/test_data_directory.h"
+#include "net/cert/internal/test_helpers.h"
+#include "net/cert/x509_certificate.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_ocsp_unittest/") + file_name;
+}
+
+enum OCSPFailure {
+ OCSP_SUCCESS,
+ PARSE_CERT,
+ PARSE_OCSP,
+ OCSP_NOT_SUCCESSFUL,
+ PARSE_OCSP_DATA,
+ PARSE_OCSP_SINGLE_RESPONSE,
+ VERIFY_OCSP,
+ OCSP_SUCCESS_REVOKED,
+ OCSP_SUCCESS_UNKNOWN,
+};
+
+OCSPFailure ParseOCSP(const std::string& file_name) {
+ std::string ocsp_data;
+ std::string ca_data;
+ std::string cert_data;
+ const PemBlockMapping mappings[] = {
+ {"OCSP RESPONSE", &ocsp_data},
+ {"CA CERTIFICATE", &ca_data},
+ {"CERTIFICATE", &cert_data},
+ };
+
+ if (!ReadTestDataFromPemFile(GetFilePath(file_name), mappings))
+ return PARSE_CERT;
+
+ der::Input ocsp_input(&ocsp_data);
+ der::Input ca_input(&ca_data);
+ der::Input cert_input(&cert_data);
+
+ ParsedCertificate issuer;
+ ParsedCertificate cert;
+ if (!ParseCertificate(ca_input, &issuer))
+ return PARSE_CERT;
+ if (!ParseCertificate(cert_input, &cert))
+ return PARSE_CERT;
+ OCSPResponse parsed_ocsp;
+ OCSPResponseData parsed_ocsp_data;
+ if (!ParseOCSPResponse(ocsp_input, &parsed_ocsp))
+ return PARSE_OCSP;
+ if (parsed_ocsp.status != OCSPResponse::ResponseStatus::SUCCESSFUL)
+ return OCSP_NOT_SUCCESSFUL;
+ if (!ParseOCSPResponseData(parsed_ocsp.data, &parsed_ocsp_data))
+ return PARSE_OCSP_DATA;
+
+ OCSPCertStatus status;
+
+ if (!GetOCSPCertStatus(parsed_ocsp_data, issuer, cert, &status))
+ return PARSE_OCSP_SINGLE_RESPONSE;
+
+ switch (status.status) {
+ case OCSPCertStatus::Status::GOOD:
+ return OCSP_SUCCESS;
+ case OCSPCertStatus::Status::REVOKED:
+ return OCSP_SUCCESS_REVOKED;
+ case OCSPCertStatus::Status::UNKNOWN:
+ return OCSP_SUCCESS_UNKNOWN;
+ }
+
+ return OCSP_SUCCESS_UNKNOWN;
+}
+
+} // namespace
+
+TEST(ParseOCSPTest, OCSPGoodResponse) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("good_response.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPNoResponse) {
+ ASSERT_EQ(PARSE_OCSP_SINGLE_RESPONSE, ParseOCSP("no_response.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPMalformedStatus) {
+ ASSERT_EQ(OCSP_NOT_SUCCESSFUL, ParseOCSP("malformed_status.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPBadStatus) {
+ ASSERT_EQ(PARSE_OCSP, ParseOCSP("bad_status.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPInvalidOCSPOid) {
+ ASSERT_EQ(PARSE_OCSP, ParseOCSP("bad_ocsp_type.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPBadSignature) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("bad_signature.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPDirectSignature) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("ocsp_sign_direct.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPIndirectSignature) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("ocsp_sign_indirect.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPMissingIndirectSignature) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("ocsp_sign_indirect_missing.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPInvalidSignature) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("ocsp_sign_bad_indirect.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPExtraCerts) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("ocsp_extra_certs.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPIncludesVersion) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("has_version.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPResponderName) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("responder_name.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPResponderKeyHash) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("responder_id.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPOCSPExtension) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("has_extension.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPIncludeNextUpdate) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("good_response_next_update.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPRevokedResponse) {
+ ASSERT_EQ(OCSP_SUCCESS_REVOKED, ParseOCSP("revoke_response.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPRevokedResponseWithReason) {
+ ASSERT_EQ(OCSP_SUCCESS_REVOKED, ParseOCSP("revoke_response_reason.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPUnknownCertStatus) {
+ ASSERT_EQ(OCSP_SUCCESS_UNKNOWN, ParseOCSP("unknown_response.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPMultipleCertStatus) {
+ ASSERT_EQ(OCSP_SUCCESS_UNKNOWN, ParseOCSP("multiple_response.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPWrongCertResponse) {
+ ASSERT_EQ(PARSE_OCSP_SINGLE_RESPONSE, ParseOCSP("other_response.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPOCSPSingleExtension) {
+ ASSERT_EQ(OCSP_SUCCESS, ParseOCSP("has_single_extension.pem"));
+}
+
+TEST(ParseOCSPTest, OCSPMissingResponse) {
+ ASSERT_EQ(PARSE_OCSP_SINGLE_RESPONSE, ParseOCSP("missing_response.pem"));
+}
+
+} // namespace net
diff --git a/chromium/net/cert/internal/signature_algorithm.cc b/chromium/net/cert/internal/signature_algorithm.cc
index 38158fce771..315243f3968 100644
--- a/chromium/net/cert/internal/signature_algorithm.cc
+++ b/chromium/net/cert/internal/signature_algorithm.cc
@@ -226,7 +226,8 @@ WARN_UNUSED_RESULT bool IsNull(const der::Input& input) {
// Returns a nullptr on failure.
//
// RFC 5912 requires that the parameters for RSA PKCS#1 v1.5 algorithms be NULL
-// ("PARAMS TYPE NULL ARE required"):
+// ("PARAMS TYPE NULL ARE required"), however an empty parameter is also
+// allowed for compatibility with non-compliant OCSP responders:
//
// sa-rsaWithSHA1 SIGNATURE-ALGORITHM ::= {
// IDENTIFIER sha1WithRSAEncryption
@@ -261,7 +262,8 @@ WARN_UNUSED_RESULT bool IsNull(const der::Input& input) {
// }
scoped_ptr<SignatureAlgorithm> ParseRsaPkcs1(DigestAlgorithm digest,
const der::Input& params) {
- if (!IsNull(params))
+ // TODO(svaldez): Add warning about non-strict parsing.
+ if (!IsNull(params) && !IsEmpty(params))
return nullptr;
return SignatureAlgorithm::CreateRsaPkcs1(digest);
@@ -319,49 +321,6 @@ scoped_ptr<SignatureAlgorithm> ParseEcdsa(DigestAlgorithm digest,
return SignatureAlgorithm::CreateEcdsa(digest);
}
-// Parses a HashAlgorithm as defined by RFC 5912:
-//
-// HashAlgorithm ::= AlgorithmIdentifier{DIGEST-ALGORITHM,
-// {HashAlgorithms}}
-//
-// HashAlgorithms DIGEST-ALGORITHM ::= {
-// { IDENTIFIER id-sha1 PARAMS TYPE NULL ARE preferredPresent } |
-// { IDENTIFIER id-sha224 PARAMS TYPE NULL ARE preferredPresent } |
-// { IDENTIFIER id-sha256 PARAMS TYPE NULL ARE preferredPresent } |
-// { IDENTIFIER id-sha384 PARAMS TYPE NULL ARE preferredPresent } |
-// { IDENTIFIER id-sha512 PARAMS TYPE NULL ARE preferredPresent }
-// }
-WARN_UNUSED_RESULT bool ParseHashAlgorithm(const der::Input input,
- DigestAlgorithm* out) {
- der::Input oid;
- der::Input params;
- if (!ParseAlgorithmIdentifier(input, &oid, &params))
- return false;
-
- DigestAlgorithm hash;
-
- if (oid.Equals(der::Input(kOidSha1))) {
- hash = DigestAlgorithm::Sha1;
- } else if (oid.Equals(der::Input(kOidSha256))) {
- hash = DigestAlgorithm::Sha256;
- } else if (oid.Equals(der::Input(kOidSha384))) {
- hash = DigestAlgorithm::Sha384;
- } else if (oid.Equals(der::Input(kOidSha512))) {
- hash = DigestAlgorithm::Sha512;
- } else {
- // Unsupported digest algorithm.
- return false;
- }
-
- // From RFC 5912: "PARAMS TYPE NULL ARE preferredPresent". Which is to say
- // the can either be absent, or NULL.
- if (!IsEmpty(params) && !IsNull(params))
- return false;
-
- *out = hash;
- return true;
-}
-
// Parses a MaskGenAlgorithm as defined by RFC 5912:
//
// MaskGenAlgorithm ::= AlgorithmIdentifier{ALGORITHM,
@@ -395,7 +354,7 @@ WARN_UNUSED_RESULT bool ParseMaskGenAlgorithm(const der::Input input,
return false;
// MGF1 is the only supported mask generation algorithm.
- if (!oid.Equals(der::Input(kOidMgf1)))
+ if (oid != der::Input(kOidMgf1))
return false;
return ParseHashAlgorithm(params, mgf1_hash);
@@ -537,6 +496,37 @@ scoped_ptr<SignatureAlgorithm> ParseRsaPss(const der::Input& params) {
} // namespace
+WARN_UNUSED_RESULT bool ParseHashAlgorithm(const der::Input input,
+ DigestAlgorithm* out) {
+ der::Input oid;
+ der::Input params;
+ if (!ParseAlgorithmIdentifier(input, &oid, &params))
+ return false;
+
+ DigestAlgorithm hash;
+
+ if (oid == der::Input(kOidSha1)) {
+ hash = DigestAlgorithm::Sha1;
+ } else if (oid == der::Input(kOidSha256)) {
+ hash = DigestAlgorithm::Sha256;
+ } else if (oid == der::Input(kOidSha384)) {
+ hash = DigestAlgorithm::Sha384;
+ } else if (oid == der::Input(kOidSha512)) {
+ hash = DigestAlgorithm::Sha512;
+ } else {
+ // Unsupported digest algorithm.
+ return false;
+ }
+
+ // From RFC 5912: "PARAMS TYPE NULL ARE preferredPresent". Which is to say
+ // the can either be absent, or NULL.
+ if (!IsEmpty(params) && !IsNull(params))
+ return false;
+
+ *out = hash;
+ return true;
+}
+
RsaPssParameters::RsaPssParameters(DigestAlgorithm mgf1_hash,
uint32_t salt_length)
: mgf1_hash_(mgf1_hash), salt_length_(salt_length) {
@@ -555,34 +545,34 @@ scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateFromDer(
// TODO(eroman): Each OID is tested for equality in order, which is not
// particularly efficient.
- if (oid.Equals(der::Input(kOidSha1WithRsaEncryption)))
+ if (oid == der::Input(kOidSha1WithRsaEncryption))
return ParseRsaPkcs1(DigestAlgorithm::Sha1, params);
- if (oid.Equals(der::Input(kOidSha256WithRsaEncryption)))
+ if (oid == der::Input(kOidSha256WithRsaEncryption))
return ParseRsaPkcs1(DigestAlgorithm::Sha256, params);
- if (oid.Equals(der::Input(kOidSha384WithRsaEncryption)))
+ if (oid == der::Input(kOidSha384WithRsaEncryption))
return ParseRsaPkcs1(DigestAlgorithm::Sha384, params);
- if (oid.Equals(der::Input(kOidSha512WithRsaEncryption)))
+ if (oid == der::Input(kOidSha512WithRsaEncryption))
return ParseRsaPkcs1(DigestAlgorithm::Sha512, params);
- if (oid.Equals(der::Input(kOidEcdsaWithSha1)))
+ if (oid == der::Input(kOidEcdsaWithSha1))
return ParseEcdsa(DigestAlgorithm::Sha1, params);
- if (oid.Equals(der::Input(kOidEcdsaWithSha256)))
+ if (oid == der::Input(kOidEcdsaWithSha256))
return ParseEcdsa(DigestAlgorithm::Sha256, params);
- if (oid.Equals(der::Input(kOidEcdsaWithSha384)))
+ if (oid == der::Input(kOidEcdsaWithSha384))
return ParseEcdsa(DigestAlgorithm::Sha384, params);
- if (oid.Equals(der::Input(kOidEcdsaWithSha512)))
+ if (oid == der::Input(kOidEcdsaWithSha512))
return ParseEcdsa(DigestAlgorithm::Sha512, params);
- if (oid.Equals(der::Input(kOidRsaSsaPss)))
+ if (oid == der::Input(kOidRsaSsaPss))
return ParseRsaPss(params);
- if (oid.Equals(der::Input(kOidSha1WithRsaSignature)))
+ if (oid == der::Input(kOidSha1WithRsaSignature))
return ParseRsaPkcs1(DigestAlgorithm::Sha1, params);
return nullptr; // Unsupported OID.
diff --git a/chromium/net/cert/internal/signature_algorithm.h b/chromium/net/cert/internal/signature_algorithm.h
index de35a297473..d1400bec266 100644
--- a/chromium/net/cert/internal/signature_algorithm.h
+++ b/chromium/net/cert/internal/signature_algorithm.h
@@ -34,6 +34,21 @@ enum class SignatureAlgorithmId {
Ecdsa, // ECDSA
};
+// Parses a HashAlgorithm as defined by RFC 5912:
+//
+// HashAlgorithm ::= AlgorithmIdentifier{DIGEST-ALGORITHM,
+// {HashAlgorithms}}
+//
+// HashAlgorithms DIGEST-ALGORITHM ::= {
+// { IDENTIFIER id-sha1 PARAMS TYPE NULL ARE preferredPresent } |
+// { IDENTIFIER id-sha224 PARAMS TYPE NULL ARE preferredPresent } |
+// { IDENTIFIER id-sha256 PARAMS TYPE NULL ARE preferredPresent } |
+// { IDENTIFIER id-sha384 PARAMS TYPE NULL ARE preferredPresent } |
+// { IDENTIFIER id-sha512 PARAMS TYPE NULL ARE preferredPresent }
+// }
+WARN_UNUSED_RESULT bool ParseHashAlgorithm(const der::Input input,
+ DigestAlgorithm* out);
+
// Base class for describing algorithm parameters.
class NET_EXPORT SignatureAlgorithmParameters {
public:
diff --git a/chromium/net/cert/internal/signature_algorithm_unittest.cc b/chromium/net/cert/internal/signature_algorithm_unittest.cc
index 32f5a0fc629..fe5dc2fab8a 100644
--- a/chromium/net/cert/internal/signature_algorithm_unittest.cc
+++ b/chromium/net/cert/internal/signature_algorithm_unittest.cc
@@ -21,7 +21,7 @@ namespace {
template <size_t N>
bool ParseDer(const uint8_t(&data)[N], scoped_ptr<SignatureAlgorithm>* out) {
*out = SignatureAlgorithm::CreateFromDer(der::Input(data, N));
- return *out;
+ return !!*out;
}
// Parses a SignatureAlgorithm given an empty DER input.
@@ -72,7 +72,10 @@ TEST(SignatureAlgorithmTest, ParseDerSha1WithRSAEncryptionNoParams) {
};
// clang-format on
scoped_ptr<SignatureAlgorithm> algorithm;
- ASSERT_FALSE(ParseDer(kData, &algorithm));
+ ASSERT_TRUE(ParseDer(kData, &algorithm));
+
+ EXPECT_EQ(SignatureAlgorithmId::RsaPkcs1, algorithm->algorithm());
+ EXPECT_EQ(DigestAlgorithm::Sha1, algorithm->digest());
}
// Parses a sha1WithRSAEncryption which contains an unexpected parameters
@@ -128,7 +131,10 @@ TEST(SignatureAlgorithmTest, ParseDerSha1WithRSASignatureNoParams) {
};
// clang-format on
scoped_ptr<SignatureAlgorithm> algorithm;
- ASSERT_FALSE(ParseDer(kData, &algorithm));
+ ASSERT_TRUE(ParseDer(kData, &algorithm));
+
+ EXPECT_EQ(SignatureAlgorithmId::RsaPkcs1, algorithm->algorithm());
+ EXPECT_EQ(DigestAlgorithm::Sha1, algorithm->digest());
}
// Parses a sha1WithRSAEncryption which contains values after the sequence.
@@ -240,7 +246,10 @@ TEST(SignatureAlgorithmTest, ParseDerSha256WithRSAEncryptionNoParams) {
};
// clang-format on
scoped_ptr<SignatureAlgorithm> algorithm;
- ASSERT_FALSE(ParseDer(kData, &algorithm));
+ ASSERT_TRUE(ParseDer(kData, &algorithm));
+
+ EXPECT_EQ(SignatureAlgorithmId::RsaPkcs1, algorithm->algorithm());
+ EXPECT_EQ(DigestAlgorithm::Sha256, algorithm->digest());
}
// Parses a sha384WithRSAEncryption which contains a NULL parameters field.
@@ -277,7 +286,10 @@ TEST(SignatureAlgorithmTest, ParseDerSha384WithRSAEncryptionNoParams) {
};
// clang-format on
scoped_ptr<SignatureAlgorithm> algorithm;
- ASSERT_FALSE(ParseDer(kData, &algorithm));
+ ASSERT_TRUE(ParseDer(kData, &algorithm));
+
+ EXPECT_EQ(SignatureAlgorithmId::RsaPkcs1, algorithm->algorithm());
+ EXPECT_EQ(DigestAlgorithm::Sha384, algorithm->digest());
}
// Parses a sha512WithRSAEncryption which contains a NULL parameters field.
@@ -314,7 +326,10 @@ TEST(SignatureAlgorithmTest, ParseDerSha512WithRSAEncryptionNoParams) {
};
// clang-format on
scoped_ptr<SignatureAlgorithm> algorithm;
- ASSERT_FALSE(ParseDer(kData, &algorithm));
+ ASSERT_TRUE(ParseDer(kData, &algorithm));
+
+ EXPECT_EQ(SignatureAlgorithmId::RsaPkcs1, algorithm->algorithm());
+ EXPECT_EQ(DigestAlgorithm::Sha512, algorithm->digest());
}
// Parses a sha224WithRSAEncryption which contains a NULL parameters field.
diff --git a/chromium/net/cert/internal/signature_policy.h b/chromium/net/cert/internal/signature_policy.h
index 3acf17b9ea6..749862377d8 100644
--- a/chromium/net/cert/internal/signature_policy.h
+++ b/chromium/net/cert/internal/signature_policy.h
@@ -47,9 +47,6 @@ class NET_EXPORT SignaturePolicy {
// SimpleSignaturePolicy modifies the base SignaturePolicy by allowing the
// minimum RSA key length to be specified (rather than hard coded to 2048).
-//
-// TODO(eroman): This is currently just used by a test. If it ends up being
-// only useful for the unit-test then move it directly to that test file.
class NET_EXPORT SimpleSignaturePolicy : public SignaturePolicy {
public:
explicit SimpleSignaturePolicy(size_t min_rsa_modulus_length_bits);
diff --git a/chromium/net/cert/internal/test_helpers.cc b/chromium/net/cert/internal/test_helpers.cc
index 4194ae3e6a4..71b9a26e90a 100644
--- a/chromium/net/cert/internal/test_helpers.cc
+++ b/chromium/net/cert/internal/test_helpers.cc
@@ -26,10 +26,6 @@ void PrintTo(const Input& data, ::std::ostream* os) {
*os << "[" << b64 << "]";
}
-bool operator==(const Input& a, const Input& b) {
- return a.Equals(b);
-}
-
} // namespace der
der::Input SequenceValueFromString(const std::string* s) {
diff --git a/chromium/net/cert/internal/test_helpers.h b/chromium/net/cert/internal/test_helpers.h
index a1b3d8045ee..999c37b5569 100644
--- a/chromium/net/cert/internal/test_helpers.h
+++ b/chromium/net/cert/internal/test_helpers.h
@@ -18,10 +18,8 @@ namespace net {
namespace der {
-// These functions are used by GTest to support EXPECT_EQ() for
-// der::Input.
+// This function is used by GTest to support EXPECT_EQ() for der::Input.
void PrintTo(const Input& data, ::std::ostream* os);
-bool operator==(const Input& a, const Input& b);
} // namespace der
diff --git a/chromium/net/cert/internal/verify_certificate_chain.cc b/chromium/net/cert/internal/verify_certificate_chain.cc
index 524de925d3e..20fafc5303f 100644
--- a/chromium/net/cert/internal/verify_certificate_chain.cc
+++ b/chromium/net/cert/internal/verify_certificate_chain.cc
@@ -5,6 +5,7 @@
#include "net/cert/internal/verify_certificate_chain.h"
#include "base/logging.h"
+#include "net/cert/internal/name_constraints.h"
#include "net/cert/internal/parse_certificate.h"
#include "net/cert/internal/signature_algorithm.h"
#include "net/cert/internal/signature_policy.h"
@@ -35,6 +36,11 @@ struct FullyParsedCert {
bool has_key_usage = false;
der::BitString key_usage;
+ scoped_ptr<GeneralNames> subject_alt_names;
+
+ bool has_name_constraints = false;
+ ParsedExtension name_constraints_extension;
+
// The remaining extensions (excludes the standard ones above).
ExtensionsMap unconsumed_extensions;
};
@@ -65,6 +71,12 @@ WARN_UNUSED_RESULT bool VerifyNoUnconsumedCriticalExtensions(
return true;
}
+WARN_UNUSED_RESULT bool GetSequenceValue(const der::Input& tlv,
+ der::Input* value) {
+ der::Parser parser(tlv);
+ return parser.ReadTag(der::kSequence, value) && !parser.HasMore();
+}
+
// Parses an X.509 Certificate fully (including the TBSCertificate and
// standard extensions), saving all the properties to |out_|.
WARN_UNUSED_RESULT bool FullyParseCertificate(const der::Input& cert_tlv,
@@ -91,6 +103,8 @@ WARN_UNUSED_RESULT bool FullyParseCertificate(const der::Input& cert_tlv,
out->has_basic_constraints = false;
out->has_key_usage = false;
out->unconsumed_extensions.clear();
+ out->subject_alt_names.reset();
+ out->has_name_constraints = false;
// Parse the standard X.509 extensions and remove them from
// |unconsumed_extensions|.
@@ -117,17 +131,39 @@ WARN_UNUSED_RESULT bool FullyParseCertificate(const der::Input& cert_tlv,
if (!ParseKeyUsage(extension.value, &out->key_usage))
return false;
}
+
+ // Subject alternative name.
+ if (ConsumeExtension(SubjectAltNameOid(), &out->unconsumed_extensions,
+ &extension)) {
+ // RFC 5280 section 4.2.1.6:
+ // SubjectAltName ::= GeneralNames
+ out->subject_alt_names = GeneralNames::CreateFromDer(extension.value);
+ if (!out->subject_alt_names)
+ return false;
+ // RFC 5280 section 4.1.2.6:
+ // If subject naming information is present only in the subjectAltName
+ // extension (e.g., a key bound only to an email address or URI), then the
+ // subject name MUST be an empty sequence and the subjectAltName extension
+ // MUST be critical.
+ if (!extension.critical) {
+ der::Input subject_value;
+ if (!GetSequenceValue(out->tbs.subject_tlv, &subject_value))
+ return false;
+ if (subject_value.Length() == 0)
+ return false;
+ }
+ }
+
+ // Name constraints.
+ if (ConsumeExtension(NameConstraintsOid(), &out->unconsumed_extensions,
+ &out->name_constraints_extension)) {
+ out->has_name_constraints = true;
+ }
}
return true;
}
-WARN_UNUSED_RESULT bool GetSequenceValue(const der::Input& tlv,
- der::Input* value) {
- der::Parser parser(tlv);
- return parser.ReadTag(der::kSequence, value) && !parser.HasMore();
-}
-
// Returns true if |name1_tlv| matches |name2_tlv|. The two inputs must be
// tag-length-value for RFC 5280's Name.
WARN_UNUSED_RESULT bool NameMatches(const der::Input& name1_tlv,
@@ -229,19 +265,20 @@ WARN_UNUSED_RESULT bool VerifySignatureAlgorithmsMatch(
// Ensure that the two DER-encoded signature algorithms are byte-for-byte
// equal, but make a compatibility concession for RSA with SHA1.
- return alg1_tlv.Equals(alg2_tlv) ||
- (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) &&
- IsRsaWithSha1SignatureAlgorithm(alg2_tlv));
+ return alg1_tlv == alg2_tlv || (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) &&
+ IsRsaWithSha1SignatureAlgorithm(alg2_tlv));
}
// This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate
// Processing" procedure.
WARN_UNUSED_RESULT bool BasicCertificateProcessing(
const FullyParsedCert& cert,
+ bool is_target_cert,
const SignaturePolicy* signature_policy,
const der::GeneralizedTime& time,
const der::Input& working_spki,
- const der::Input& working_issuer_name) {
+ const der::Input& working_issuer_name,
+ const std::vector<scoped_ptr<NameConstraints>>& name_constraints_list) {
// Check that the signature algorithms in Certificate vs TBSCertificate
// match. This isn't part of RFC 5280 section 6.1.3, but is mandated by
// sections 4.1.1.2 and 4.1.2.3.
@@ -269,7 +306,21 @@ WARN_UNUSED_RESULT bool BasicCertificateProcessing(
if (!NameMatches(cert.tbs.issuer_tlv, working_issuer_name))
return false;
- // TODO(eroman): Steps b-f are omitted, as policy/name constraints are not yet
+ // Name constraints (RFC 5280 section 6.1.3 step b & c)
+ // If certificate i is self-issued and it is not the final certificate in the
+ // path, skip this step for certificate i.
+ if (!name_constraints_list.empty() &&
+ (!IsSelfIssued(cert) || is_target_cert)) {
+ der::Input subject_value;
+ if (!GetSequenceValue(cert.tbs.subject_tlv, &subject_value))
+ return false;
+ for (const auto& nc : name_constraints_list) {
+ if (!nc->IsPermittedCert(subject_value, cert.subject_alt_names.get()))
+ return false;
+ }
+ }
+
+ // TODO(eroman): Steps d-f are omitted, as policy constraints are not yet
// implemented.
return true;
@@ -281,8 +332,9 @@ WARN_UNUSED_RESULT bool PrepareForNextCertificate(
const FullyParsedCert& cert,
size_t* max_path_length_ptr,
der::Input* working_spki,
- der::Input* working_issuer_name) {
- // TODO(eroman): Steps a-b are omitted, as policy/name constraints are not yet
+ der::Input* working_issuer_name,
+ std::vector<scoped_ptr<NameConstraints>>* name_constraints_list) {
+ // TODO(eroman): Steps a-b are omitted, as policy constraints are not yet
// implemented.
// From RFC 5280 section 6.1.4 step c:
@@ -299,7 +351,17 @@ WARN_UNUSED_RESULT bool PrepareForNextCertificate(
// the assignment to |working_spki| above. See the definition
// of |working_spki|.
- // TODO(eroman): Steps g-j are omitted as policy/name constraints are not yet
+ // From RFC 5280 section 6.1.4 step g:
+ if (cert.has_name_constraints) {
+ scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer(
+ cert.name_constraints_extension.value,
+ cert.name_constraints_extension.critical));
+ if (!name_constraints)
+ return false;
+ name_constraints_list->push_back(std::move(name_constraints));
+ }
+
+ // TODO(eroman): Steps h-j are omitted as policy constraints are not yet
// implemented.
// From RFC 5280 section 6.1.4 step k:
@@ -405,7 +467,7 @@ WARN_UNUSED_RESULT bool VerifyTargetCertHasConsistentCaBits(
// This function corresponds with RFC 5280 section 6.1.5's "Wrap-Up Procedure".
// It does processing for the final certificate (the target cert).
WARN_UNUSED_RESULT bool WrapUp(const FullyParsedCert& cert) {
- // TODO(eroman): Steps a-c are omitted as policy/name constraints are not yet
+ // TODO(eroman): Steps a-b are omitted as policy constraints are not yet
// implemented.
// Note step c-e are omitted the verification function does
@@ -439,6 +501,7 @@ WARN_UNUSED_RESULT bool WrapUp(const FullyParsedCert& cert) {
TrustAnchor::~TrustAnchor() {}
TrustStore::TrustStore() {}
+TrustStore::TrustStore(const TrustStore& other) = default;
TrustStore::~TrustStore() {}
// This implementation is structured to mimic the description of certificate
@@ -451,6 +514,11 @@ bool VerifyCertificateChain(const std::vector<der::Input>& certs_der,
if (certs_der.empty())
return false;
+ // Will contain a NameConstraints for each previous cert in the chain which
+ // had nameConstraints. This corresponds to the permitted_subtrees and
+ // excluded_subtrees state variables from RFC 5280.
+ std::vector<scoped_ptr<NameConstraints>> name_constraints_list;
+
// |working_spki| is an amalgamation of 3 separate variables from RFC 5280:
// * working_public_key
// * working_public_key_algorithm
@@ -523,13 +591,15 @@ bool VerifyCertificateChain(const std::vector<der::Input>& certs_der,
// * If it is the last certificate in the path (target certificate)
// - Then run "Wrap up"
// - Otherwise run "Prepare for Next cert"
- if (!BasicCertificateProcessing(cert, signature_policy, time, working_spki,
- working_issuer_name)) {
+ if (!BasicCertificateProcessing(cert, is_target_cert, signature_policy,
+ time, working_spki, working_issuer_name,
+ name_constraints_list)) {
return false;
}
if (!is_target_cert) {
if (!PrepareForNextCertificate(cert, &max_path_length, &working_spki,
- &working_issuer_name)) {
+ &working_issuer_name,
+ &name_constraints_list)) {
return false;
}
} else {
diff --git a/chromium/net/cert/internal/verify_certificate_chain.h b/chromium/net/cert/internal/verify_certificate_chain.h
index 8f7e21f8ad6..35a3ebaea89 100644
--- a/chromium/net/cert/internal/verify_certificate_chain.h
+++ b/chromium/net/cert/internal/verify_certificate_chain.h
@@ -37,6 +37,7 @@ struct NET_EXPORT TrustAnchor {
// names to trusted public keys.
struct NET_EXPORT TrustStore {
TrustStore();
+ TrustStore(const TrustStore& other);
~TrustStore();
std::vector<TrustAnchor> anchors;
diff --git a/chromium/net/cert/internal/verify_certificate_chain_pkits_unittest.cc b/chromium/net/cert/internal/verify_certificate_chain_pkits_unittest.cc
new file mode 100644
index 00000000000..98b0e7b800a
--- /dev/null
+++ b/chromium/net/cert/internal/verify_certificate_chain_pkits_unittest.cc
@@ -0,0 +1,223 @@
+// 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.
+
+// TODO(eroman): Because VerifySignedData() is only implemented for BoringSSL
+// these tests also depend on BoringSSL.
+#if defined(USE_OPENSSL)
+
+#include "net/cert/internal/verify_certificate_chain.h"
+
+#include "net/cert/internal/parse_certificate.h"
+#include "net/cert/internal/signature_policy.h"
+#include "net/der/input.h"
+
+// Disable tests that require DSA signatures (DSA signatures are intentionally
+// unsupported). Custom versions of the DSA tests are defined below which expect
+// verification to fail.
+#define Section1ValidDSASignaturesTest4 DISABLED_Section1ValidDSASignaturesTest4
+#define Section1ValidDSAParameterInheritanceTest5 \
+ DISABLED_Section1ValidDSAParameterInheritanceTest5
+
+// Disable tests that require name constraints with name types that are
+// intentionally unsupported. Custom versions of the tests are defined below
+// which expect verification to fail.
+#define Section13ValidRFC822nameConstraintsTest21 \
+ DISABLED_Section13ValidRFC822nameConstraintsTest21
+#define Section13ValidRFC822nameConstraintsTest23 \
+ DISABLED_Section13ValidRFC822nameConstraintsTest23
+#define Section13ValidRFC822nameConstraintsTest25 \
+ DISABLED_Section13ValidRFC822nameConstraintsTest25
+#define Section13ValidDNandRFC822nameConstraintsTest27 \
+ DISABLED_Section13ValidDNandRFC822nameConstraintsTest27
+#define Section13ValidURInameConstraintsTest34 \
+ DISABLED_Section13ValidURInameConstraintsTest34
+#define Section13ValidURInameConstraintsTest36 \
+ DISABLED_Section13ValidURInameConstraintsTest36
+
+// TODO(mattm): these require CRL support:
+#define Section7InvalidkeyUsageCriticalcRLSignFalseTest4 \
+ DISABLED_Section7InvalidkeyUsageCriticalcRLSignFalseTest4
+#define Section7InvalidkeyUsageNotCriticalcRLSignFalseTest5 \
+ DISABLED_Section7InvalidkeyUsageNotCriticalcRLSignFalseTest5
+
+#include "net/cert/internal/nist_pkits_unittest.h"
+
+namespace net {
+
+namespace {
+
+// Adds the certificate |cert_der| as a trust anchor to |trust_store|.
+void AddCertificateToTrustStore(const std::string& cert_der,
+ TrustStore* trust_store) {
+ ParsedCertificate cert;
+ ASSERT_TRUE(ParseCertificate(der::Input(&cert_der), &cert));
+
+ ParsedTbsCertificate tbs;
+ ASSERT_TRUE(ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs));
+ TrustAnchor anchor = {tbs.spki_tlv.AsString(), tbs.subject_tlv.AsString()};
+ trust_store->anchors.push_back(anchor);
+}
+
+class VerifyCertificateChainPkitsTestDelegate {
+ public:
+ static bool Verify(std::vector<std::string> cert_ders,
+ std::vector<std::string> crl_ders) {
+ if (cert_ders.empty()) {
+ ADD_FAILURE() << "cert_ders is empty";
+ return false;
+ }
+ // First entry in the PKITS chain is the trust anchor.
+ TrustStore trust_store;
+ AddCertificateToTrustStore(cert_ders[0], &trust_store);
+
+ // PKITS lists chains from trust anchor to target, VerifyCertificateChain
+ // takes them starting with the target and not including the trust anchor.
+ std::vector<der::Input> input_chain;
+ for (size_t i = cert_ders.size() - 1; i > 0; --i)
+ input_chain.push_back(der::Input(&cert_ders[i]));
+
+ SimpleSignaturePolicy signature_policy(1024);
+
+ // Run all tests at the time the PKITS was published.
+ der::GeneralizedTime time = {2011, 4, 15, 0, 0, 0};
+
+ return VerifyCertificateChain(input_chain, trust_store, &signature_policy,
+ time);
+ }
+};
+
+} // namespace
+
+class PkitsTest01SignatureVerificationCustom
+ : public PkitsTest<VerifyCertificateChainPkitsTestDelegate> {};
+
+// Modified version of 4.1.4 Valid DSA Signatures Test4
+TEST_F(PkitsTest01SignatureVerificationCustom,
+ Section1ValidDSASignaturesTest4Custom) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "DSACACert",
+ "ValidDSASignaturesTest4EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "DSACACRL"};
+ // DSA signatures are intentionally unsupported.
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// Modified version of 4.1.5 Valid DSA Parameter Inheritance Test5
+TEST_F(PkitsTest01SignatureVerificationCustom,
+ Section1ValidDSAParameterInheritanceTest5Custom) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "DSACACert",
+ "DSAParametersInheritedCACert",
+ "ValidDSAParameterInheritanceTest5EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "DSACACRL",
+ "DSAParametersInheritedCACRL"};
+ // DSA signatures are intentionally unsupported.
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+class PkitsTest13SignatureVerificationCustom
+ : public PkitsTest<VerifyCertificateChainPkitsTestDelegate> {};
+
+// Modified version of 4.13.21 Valid RFC822 nameConstraints Test21
+TEST_F(PkitsTest13SignatureVerificationCustom,
+ Section13ValidRFC822nameConstraintsTest21Custom) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsRFC822CA1Cert",
+ "ValidRFC822nameConstraintsTest21EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "nameConstraintsRFC822CA1CRL"};
+ // Name constraints on rfc822Names are not supported.
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// Modified version of 4.13.23 Valid RFC822 nameConstraints Test23
+TEST_F(PkitsTest13SignatureVerificationCustom,
+ Section13ValidRFC822nameConstraintsTest23Custom) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsRFC822CA2Cert",
+ "ValidRFC822nameConstraintsTest23EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "nameConstraintsRFC822CA2CRL"};
+ // Name constraints on rfc822Names are not supported.
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// Modified version of 4.13.25 Valid RFC822 nameConstraints Test25
+TEST_F(PkitsTest13SignatureVerificationCustom,
+ Section13ValidRFC822nameConstraintsTest25Custom) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsRFC822CA3Cert",
+ "ValidRFC822nameConstraintsTest25EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "nameConstraintsRFC822CA3CRL"};
+ // Name constraints on rfc822Names are not supported.
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// Modified version of 4.13.27 Valid DN and RFC822 nameConstraints Test27
+TEST_F(PkitsTest13SignatureVerificationCustom,
+ Section13ValidDNandRFC822nameConstraintsTest27Custom) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN1CACert",
+ "nameConstraintsDN1subCA3Cert",
+ "ValidDNandRFC822nameConstraintsTest27EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL",
+ "nameConstraintsDN1subCA3CRL"};
+ // Name constraints on rfc822Names are not supported.
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// Modified version of 4.13.34 Valid URI nameConstraints Test34
+TEST_F(PkitsTest13SignatureVerificationCustom,
+ Section13ValidURInameConstraintsTest34Custom) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsURI1CACert",
+ "ValidURInameConstraintsTest34EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsURI1CACRL"};
+ // Name constraints on uniformResourceIdentifiers are not supported.
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// Modified version of 4.13.36 Valid URI nameConstraints Test36
+TEST_F(PkitsTest13SignatureVerificationCustom,
+ Section13ValidURInameConstraintsTest36Custom) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsURI2CACert",
+ "ValidURInameConstraintsTest36EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsURI2CACRL"};
+ // Name constraints on uniformResourceIdentifiers are not supported.
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+INSTANTIATE_TYPED_TEST_CASE_P(VerifyCertificateChain,
+ PkitsTest01SignatureVerification,
+ VerifyCertificateChainPkitsTestDelegate);
+INSTANTIATE_TYPED_TEST_CASE_P(VerifyCertificateChain,
+ PkitsTest02ValidityPeriods,
+ VerifyCertificateChainPkitsTestDelegate);
+INSTANTIATE_TYPED_TEST_CASE_P(VerifyCertificateChain,
+ PkitsTest03VerifyingNameChaining,
+ VerifyCertificateChainPkitsTestDelegate);
+INSTANTIATE_TYPED_TEST_CASE_P(VerifyCertificateChain,
+ PkitsTest06VerifyingBasicConstraints,
+ VerifyCertificateChainPkitsTestDelegate);
+INSTANTIATE_TYPED_TEST_CASE_P(VerifyCertificateChain,
+ PkitsTest07KeyUsage,
+ VerifyCertificateChainPkitsTestDelegate);
+INSTANTIATE_TYPED_TEST_CASE_P(VerifyCertificateChain,
+ PkitsTest13NameConstraints,
+ VerifyCertificateChainPkitsTestDelegate);
+INSTANTIATE_TYPED_TEST_CASE_P(VerifyCertificateChain,
+ PkitsTest16PrivateCertificateExtensions,
+ VerifyCertificateChainPkitsTestDelegate);
+
+// TODO(mattm): CRL support: PkitsTest04BasicCertificateRevocationTests,
+// PkitsTest05VerifyingPathswithSelfIssuedCertificates,
+// PkitsTest14DistributionPoints, PkitsTest15DeltaCRLs
+
+// TODO(mattm): Certificate Policies support: PkitsTest08CertificatePolicies,
+// PkitsTest09RequireExplicitPolicy PkitsTest10PolicyMappings,
+// PkitsTest11InhibitPolicyMapping, PkitsTest12InhibitAnyPolicy
+
+} // namespace net
+
+#endif // USE_OPENSSL
diff --git a/chromium/net/cert/internal/verify_name_match.cc b/chromium/net/cert/internal/verify_name_match.cc
index 00d1fb5c113..444f3c97f30 100644
--- a/chromium/net/cert/internal/verify_name_match.cc
+++ b/chromium/net/cert/internal/verify_name_match.cc
@@ -4,15 +4,8 @@
#include "net/cert/internal/verify_name_match.h"
-#include <string.h>
-
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversion_utils.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/sys_byteorder.h"
-#include "base/third_party/icu/icu_utf.h"
#include "base/tuple.h"
+#include "net/cert/internal/parse_name.h"
#include "net/der/input.h"
#include "net/der/parser.h"
#include "net/der/tag.h"
@@ -115,135 +108,28 @@ WARN_UNUSED_RESULT bool NormalizeDirectoryString(
return true;
}
-// Normalizes the DER-encoded PrintableString value |in| according to
-// RFC 2459, Section 4.1.2.4
+// Converts the value of X509NameAttribute |attribute| to UTF-8, normalizes it,
+// and stores in |output|. The type of |attribute| must be one of the types for
+// which IsNormalizableDirectoryString is true.
//
-// Briefly, normalization involves removing leading and trailing
-// whitespace, folding multiple whitespace characters into a single
-// whitespace character, and normalizing on case (this function
-// normalizes to lowercase).
-//
-// During normalization, this function also validates that |in|
-// is properly encoded - that is, that it restricts to the character
-// set defined in X.680 (2008), Section 41.4, Table 10. X.680 defines
-// the valid characters as
-// a-z A-Z 0-9 (space) ' ( ) + , - . / : = ?
-//
-// However, due to an old OpenSSL encoding bug, a number of
-// certificates have also included '*', which has historically been
-// allowed by implementations, and so is also allowed here.
-//
-// If |in| can be normalized, returns true and sets |output| to the
-// case folded, normalized value. If |in| is invalid, returns false.
-// NOTE: |output| will be modified regardless of the return.
-WARN_UNUSED_RESULT bool NormalizePrintableStringValue(const der::Input& in,
- std::string* output) {
- in.AsString().swap(*output);
- return NormalizeDirectoryString(ENFORCE_PRINTABLE_STRING, output);
-}
-
-// Normalized a UTF8String value. See the comment for NormalizeDirectoryString
-// for details.
-//
-// If |in| can be normalized, returns true and sets |output| to the
-// case folded, normalized value. If |in| is invalid, returns false.
-// NOTE: |output| will be modified regardless of the return.
-WARN_UNUSED_RESULT bool NormalizeUtf8StringValue(const der::Input& in,
- std::string* output) {
- in.AsString().swap(*output);
- return NormalizeDirectoryString(NO_ENFORCEMENT, output);
-}
-
-// IA5String is ISO/IEC Registrations 1 and 6 from the ISO
-// "International Register of Coded Character Sets to be used
-// with Escape Sequences", plus space and delete. That's just the
-// polite way of saying 0x00 - 0x7F, aka ASCII (or, more formally,
-// ISO/IEC 646)
-//
-// If |in| can be normalized, returns true and sets |output| to the case folded,
-// normalized value. If |in| is invalid, returns false.
-// NOTE: |output| will be modified regardless of the return.
-WARN_UNUSED_RESULT bool NormalizeIA5StringValue(const der::Input& in,
- std::string* output) {
- in.AsString().swap(*output);
- return NormalizeDirectoryString(ENFORCE_ASCII, output);
-}
-
-// Converts BMPString value to UTF-8 and then normalizes it. See the comment for
-// NormalizeDirectoryString for details.
-//
-// If |in| can be normalized, returns true and sets |output| to the case folded,
-// normalized value. If |in| is invalid, returns false.
+// If the value of |attribute| can be normalized, returns true and sets
+// |output| to the case folded, normalized value. If the value of |attribute|
+// is invalid, returns false.
// NOTE: |output| will be modified regardless of the return.
-WARN_UNUSED_RESULT bool NormalizeBmpStringValue(const der::Input& in,
- std::string* output) {
- if (in.Length() % 2 != 0)
- return false;
-
- base::string16 in_16bit;
- if (in.Length()) {
- memcpy(base::WriteInto(&in_16bit, in.Length() / 2 + 1), in.UnsafeData(),
- in.Length());
- }
- for (base::char16& c : in_16bit) {
- // BMPString is UCS-2 in big-endian order.
- c = base::NetToHost16(c);
-
- // BMPString only supports codepoints in the Basic Multilingual Plane;
- // surrogates are not allowed.
- if (CBU_IS_SURROGATE(c))
- return false;
- }
- if (!base::UTF16ToUTF8(in_16bit.data(), in_16bit.size(), output))
- return false;
- return NormalizeDirectoryString(NO_ENFORCEMENT, output);
-}
-
-// Converts UniversalString value to UTF-8 and then normalizes it. See the
-// comment for NormalizeDirectoryString for details.
-//
-// If |in| can be normalized, returns true and sets |output| to the case folded,
-// normalized value. If |in| is invalid, returns false.
-// NOTE: |output| will be modified regardless of the return.
-WARN_UNUSED_RESULT bool NormalizeUniversalStringValue(const der::Input& in,
- std::string* output) {
- if (in.Length() % 4 != 0)
+WARN_UNUSED_RESULT bool NormalizeValue(X509NameAttribute attribute,
+ std::string* output) {
+ if (!attribute.ValueAsStringUnsafe(output))
return false;
- std::vector<uint32_t> in_32bit(in.Length() / 4);
- if (in.Length())
- memcpy(in_32bit.data(), in.UnsafeData(), in.Length());
- for (const uint32_t c : in_32bit) {
- // UniversalString is UCS-4 in big-endian order.
- uint32_t codepoint = base::NetToHost32(c);
- if (!CBU_IS_UNICODE_CHAR(codepoint))
- return false;
-
- base::WriteUnicodeCharacter(codepoint, output);
- }
- return NormalizeDirectoryString(NO_ENFORCEMENT, output);
-}
-
-// Converts the string |value| to UTF-8, normalizes it, and stores in |output|.
-// |tag| must one of the types for which IsNormalizableDirectoryString is true.
-//
-// If |value| can be normalized, returns true and sets |output| to the case
-// folded, normalized value. If |value| is invalid, returns false.
-// NOTE: |output| will be modified regardless of the return.
-WARN_UNUSED_RESULT bool NormalizeValue(const der::Tag tag,
- const der::Input& value,
- std::string* output) {
- switch (tag) {
+ switch (attribute.value_tag) {
case der::kPrintableString:
- return NormalizePrintableStringValue(value, output);
+ return NormalizeDirectoryString(ENFORCE_PRINTABLE_STRING, output);
+ case der::kBmpString:
+ case der::kUniversalString:
case der::kUtf8String:
- return NormalizeUtf8StringValue(value, output);
+ return NormalizeDirectoryString(NO_ENFORCEMENT, output);
case der::kIA5String:
- return NormalizeIA5StringValue(value, output);
- case der::kUniversalString:
- return NormalizeUniversalStringValue(value, output);
- case der::kBmpString:
- return NormalizeBmpStringValue(value, output);
+ return NormalizeDirectoryString(ENFORCE_ASCII, output);
default:
NOTREACHED();
return false;
@@ -271,100 +157,31 @@ bool IsNormalizableDirectoryString(der::Tag tag) {
}
}
-// Returns true if the AttributeValue (|a_tag|, |a_value|) matches (|b_tag|,
-// |b_value|).
-bool VerifyValueMatch(const der::Tag a_tag,
- const der::Input& a_value,
- const der::Tag b_tag,
- const der::Input& b_value) {
- if (IsNormalizableDirectoryString(a_tag) &&
- IsNormalizableDirectoryString(b_tag)) {
+// Returns true if the value of X509NameAttribute |a| matches |b|.
+bool VerifyValueMatch(X509NameAttribute a, X509NameAttribute b) {
+ if (IsNormalizableDirectoryString(a.value_tag) &&
+ IsNormalizableDirectoryString(b.value_tag)) {
std::string a_normalized, b_normalized;
- if (!NormalizeValue(a_tag, a_value, &a_normalized) ||
- !NormalizeValue(b_tag, b_value, &b_normalized))
+ if (!NormalizeValue(a, &a_normalized) || !NormalizeValue(b, &b_normalized))
return false;
return a_normalized == b_normalized;
}
// Attributes encoded with different types may be assumed to be unequal.
- if (a_tag != b_tag)
+ if (a.value_tag != b.value_tag)
return false;
// All other types use binary comparison.
- return a_value.Equals(b_value);
-}
-
-struct AttributeTypeAndValue {
- AttributeTypeAndValue(der::Input in_type,
- der::Tag in_value_tag,
- der::Input in_value)
- : type(in_type), value_tag(in_value_tag), value(in_value) {}
- der::Input type;
- der::Tag value_tag;
- der::Input value;
-};
-
-// Parses all the ASN.1 AttributeTypeAndValue elements in |parser| and stores
-// each as an AttributeTypeAndValue object in |out|.
-//
-// AttributeTypeAndValue is defined in RFC 5280 section 4.1.2.4:
-//
-// AttributeTypeAndValue ::= SEQUENCE {
-// type AttributeType,
-// value AttributeValue }
-//
-// AttributeType ::= OBJECT IDENTIFIER
-//
-// AttributeValue ::= ANY -- DEFINED BY AttributeType
-//
-// DirectoryString ::= CHOICE {
-// teletexString TeletexString (SIZE (1..MAX)),
-// printableString PrintableString (SIZE (1..MAX)),
-// universalString UniversalString (SIZE (1..MAX)),
-// utf8String UTF8String (SIZE (1..MAX)),
-// bmpString BMPString (SIZE (1..MAX)) }
-//
-// The type of the component AttributeValue is determined by the AttributeType;
-// in general it will be a DirectoryString.
-WARN_UNUSED_RESULT bool ReadRdn(der::Parser* parser,
- std::vector<AttributeTypeAndValue>* out) {
- while (parser->HasMore()) {
- der::Parser attr_type_and_value;
- if (!parser->ReadSequence(&attr_type_and_value))
- return false;
- // Read the attribute type, which must be an OBJECT IDENTIFIER.
- der::Input type;
- if (!attr_type_and_value.ReadTag(der::kOid, &type))
- return false;
-
- // Read the attribute value.
- der::Tag tag;
- der::Input value;
- if (!attr_type_and_value.ReadTagAndValue(&tag, &value))
- return false;
-
- // There should be no more elements in the sequence after reading the
- // attribute type and value.
- if (attr_type_and_value.HasMore())
- return false;
-
- out->push_back(AttributeTypeAndValue(type, tag, value));
- }
- return true;
+ return a.value == b.value;
}
// Verifies that |a_parser| and |b_parser| are the same length and that every
// AttributeTypeAndValue in |a_parser| has a matching AttributeTypeAndValue in
// |b_parser|.
bool VerifyRdnMatch(der::Parser* a_parser, der::Parser* b_parser) {
- std::vector<AttributeTypeAndValue> a_type_and_values, b_type_and_values;
+ RelativeDistinguishedName a_type_and_values, b_type_and_values;
if (!ReadRdn(a_parser, &a_type_and_values) ||
!ReadRdn(b_parser, &b_type_and_values))
return false;
- // RFC 5280 section 4.1.2.4
- // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
- if (a_type_and_values.empty() || b_type_and_values.empty())
- return false;
-
// RFC 5280 section 7.1:
// Two relative distinguished names RDN1 and RDN2 match if they have the same
// number of naming attributes and for each naming attribute in RDN1 there is
@@ -377,12 +194,10 @@ bool VerifyRdnMatch(der::Parser* a_parser, der::Parser* b_parser) {
// small, a naive linear search for each element should be fine. (Hostile
// certificates already have ways to provoke pathological behavior.)
for (const auto& a : a_type_and_values) {
- std::vector<AttributeTypeAndValue>::iterator b_iter =
- b_type_and_values.begin();
+ RelativeDistinguishedName::iterator b_iter = b_type_and_values.begin();
for (; b_iter != b_type_and_values.end(); ++b_iter) {
const auto& b = *b_iter;
- if (a.type.Equals(b.type) &&
- VerifyValueMatch(a.value_tag, a.value, b.value_tag, b.value)) {
+ if (a.type == b.type && VerifyValueMatch(a, b)) {
break;
}
}
@@ -487,12 +302,12 @@ bool NameContainsEmailAddress(const der::Input& name_rdn_sequence,
if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser))
return false;
- std::vector<AttributeTypeAndValue> type_and_values;
+ RelativeDistinguishedName type_and_values;
if (!ReadRdn(&rdn_parser, &type_and_values))
return false;
for (const auto& type_and_value : type_and_values) {
- if (type_and_value.type.Equals(der::Input(kOidEmailAddress))) {
+ if (type_and_value.type == der::Input(kOidEmailAddress)) {
*contained_email_address = true;
return true;
}
diff --git a/chromium/net/cert/internal/verify_signed_data.cc b/chromium/net/cert/internal/verify_signed_data.cc
index 9b0ebd45817..eb0fd3ff2b6 100644
--- a/chromium/net/cert/internal/verify_signed_data.cc
+++ b/chromium/net/cert/internal/verify_signed_data.cc
@@ -29,12 +29,12 @@ bool VerifySignedData(const SignatureAlgorithm& signature_algorithm,
#else
+#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/ec.h>
#include <openssl/ec_key.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
-#include <openssl/x509.h>
#include "base/compiler_specific.h"
#include "crypto/openssl_util.h"
@@ -97,9 +97,10 @@ WARN_UNUSED_RESULT bool ImportPkeyFromSpki(const der::Input& spki,
crypto::ScopedEVP_PKEY* pkey) {
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
- const uint8_t* ptr = spki.UnsafeData();
- pkey->reset(d2i_PUBKEY(nullptr, &ptr, spki.Length()));
- if (!pkey->get() || ptr != spki.UnsafeData() + spki.Length() ||
+ CBS cbs;
+ CBS_init(&cbs, spki.UnsafeData(), spki.Length());
+ pkey->reset(EVP_parse_public_key(&cbs));
+ if (!*pkey || CBS_len(&cbs) != 0 ||
EVP_PKEY_id(pkey->get()) != expected_pkey_id) {
pkey->reset();
return false;
diff --git a/chromium/net/cert/internal/verify_signed_data_unittest.cc b/chromium/net/cert/internal/verify_signed_data_unittest.cc
index d7e822869cd..43a4856b312 100644
--- a/chromium/net/cert/internal/verify_signed_data_unittest.cc
+++ b/chromium/net/cert/internal/verify_signed_data_unittest.cc
@@ -101,9 +101,7 @@ TEST(VerifySignedDataTest, Rsa2048Pkcs1Sha512) {
}
TEST(VerifySignedDataTest, RsaPkcs1Sha256KeyEncodedBer) {
- // TODO(eroman): This should fail! (SPKI should be DER-encoded). See
- // https://crbug.com/522228
- RunTestCase(SUCCESS, "rsa-pkcs1-sha256-key-encoded-ber.pem");
+ RunTestCase(FAILURE, "rsa-pkcs1-sha256-key-encoded-ber.pem");
}
TEST(VerifySignedDataTest, EcdsaSecp384r1Sha256) {
@@ -175,9 +173,7 @@ TEST(VerifySignedDataTest, EcdsaPrime256v1Sha512UsingEcmqvKey) {
}
TEST(VerifySignedDataTest, RsaPkcs1Sha1KeyParamsAbsent) {
- // TODO(eroman): This should fail! (key algoritm parsing is too permissive)
- // See https://crbug.com/522228
- RunTestCase(SUCCESS, "rsa-pkcs1-sha1-key-params-absent.pem");
+ RunTestCase(FAILURE, "rsa-pkcs1-sha1-key-params-absent.pem");
}
TEST(VerifySignedDataTest, RsaPssSha1Salt20UsingPssKeyNoParams) {
@@ -211,15 +207,11 @@ TEST(VerifySignedDataTest, EcdsaPrime256v1Sha512SpkiParamsNull) {
}
TEST(VerifySignedDataTest, RsaPkcs1Sha256UsingIdEaRsa) {
- // TODO(eroman): This should fail! (shouldn't recognize this weird OID).
- // See https://crbug.com/522228
- RunTestCase(SUCCESS, "rsa-pkcs1-sha256-using-id-ea-rsa.pem");
+ RunTestCase(FAILURE, "rsa-pkcs1-sha256-using-id-ea-rsa.pem");
}
TEST(VerifySignedDataTest, RsaPkcs1Sha256SpkiNonNullParams) {
- // TODO(eroman): This should fail! (shouldn't recognize bogus params in rsa
- // SPKI). See https://crbug.com/522228
- RunTestCase(SUCCESS, "rsa-pkcs1-sha256-spki-non-null-params.pem");
+ RunTestCase(FAILURE, "rsa-pkcs1-sha256-spki-non-null-params.pem");
}
TEST(VerifySignedDataTest, EcdsaPrime256v1Sha512UnusedBitsSignature) {
diff --git a/chromium/net/cert/jwk_serializer_nss.cc b/chromium/net/cert/jwk_serializer_nss.cc
index 441a98ff4f9..426a207a854 100644
--- a/chromium/net/cert/jwk_serializer_nss.cc
+++ b/chromium/net/cert/jwk_serializer_nss.cc
@@ -9,6 +9,7 @@
#include <nss.h>
#include "base/base64url.h"
+#include "base/memory/scoped_ptr.h"
#include "base/values.h"
#include "crypto/nss_util.h"
#include "crypto/scoped_nss_types.h"
diff --git a/chromium/net/cert/jwk_serializer_openssl.cc b/chromium/net/cert/jwk_serializer_openssl.cc
index f5afd4fb734..12c8e4dae89 100644
--- a/chromium/net/cert/jwk_serializer_openssl.cc
+++ b/chromium/net/cert/jwk_serializer_openssl.cc
@@ -5,10 +5,10 @@
#include "net/cert/jwk_serializer.h"
#include <openssl/bn.h>
+#include <openssl/bytestring.h>
#include <openssl/ec.h>
#include <openssl/ec_key.h>
#include <openssl/evp.h>
-#include <openssl/x509.h>
#include "base/base64url.h"
#include "base/logging.h"
@@ -96,10 +96,11 @@ bool ConvertSpkiFromDerToJwk(
crypto::EnsureOpenSSLInit();
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
- const uint8_t *data = reinterpret_cast<const uint8_t*>(spki_der.data());
- const uint8_t *ptr = data;
- crypto::ScopedEVP_PKEY pubkey(d2i_PUBKEY(NULL, &ptr, spki_der.size()));
- if (!pubkey || ptr != data + spki_der.size())
+ CBS cbs;
+ CBS_init(&cbs, reinterpret_cast<const uint8_t*>(spki_der.data()),
+ spki_der.size());
+ crypto::ScopedEVP_PKEY pubkey(EVP_parse_public_key(&cbs));
+ if (!pubkey || CBS_len(&cbs) != 0)
return false;
if (pubkey->type == EVP_PKEY_EC) {
diff --git a/chromium/net/cert/mock_client_cert_verifier.cc b/chromium/net/cert/mock_client_cert_verifier.cc
new file mode 100644
index 00000000000..96e3a0a6aaa
--- /dev/null
+++ b/chromium/net/cert/mock_client_cert_verifier.cc
@@ -0,0 +1,40 @@
+// 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/cert/mock_client_cert_verifier.h"
+
+#include "net/base/net_errors.h"
+#include "net/cert/x509_certificate.h"
+
+namespace net {
+
+struct MockClientCertVerifier::Rule {
+ Rule(X509Certificate* cert, int rv) : cert(cert), rv(rv) { DCHECK(cert); }
+
+ scoped_refptr<X509Certificate> cert;
+ int rv;
+};
+
+MockClientCertVerifier::MockClientCertVerifier()
+ : default_result_(ERR_CERT_INVALID) {}
+
+MockClientCertVerifier::~MockClientCertVerifier() {}
+
+int MockClientCertVerifier::Verify(X509Certificate* cert,
+ const CompletionCallback& callback,
+ scoped_ptr<Request>* out_req) {
+ for (const Rule& rule : rules_) {
+ // Check just the server cert. Intermediates will be ignored.
+ if (rule.cert->Equals(cert))
+ return rule.rv;
+ }
+ return default_result_;
+}
+
+void MockClientCertVerifier::AddResultForCert(X509Certificate* cert, int rv) {
+ Rule rule(cert, rv);
+ rules_.push_back(rule);
+}
+
+} // namespace net
diff --git a/chromium/net/cert/mock_client_cert_verifier.h b/chromium/net/cert/mock_client_cert_verifier.h
new file mode 100644
index 00000000000..455df12ccc7
--- /dev/null
+++ b/chromium/net/cert/mock_client_cert_verifier.h
@@ -0,0 +1,52 @@
+// 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_CERT_MOCK_CLIENT_CERT_VERIFIER_H_
+#define NET_CERT_MOCK_CLIENT_CERT_VERIFIER_H_
+
+#include <list>
+
+#include "net/cert/client_cert_verifier.h"
+
+namespace net {
+
+class MockClientCertVerifier : public ClientCertVerifier {
+ public:
+ // Creates a new MockClientCertVerifier. By default, any call to Verify() will
+ // result in the cert status being flagged as CERT_STATUS_INVALID and return
+ // an ERR_CERT_INVALID network error code. This behaviour can be overridden
+ // by calling set_default_result() to change the default return value for
+ // Verify() or by calling one of the AddResult*() methods to specifically
+ // handle a certificate or certificate and host.
+ MockClientCertVerifier();
+
+ ~MockClientCertVerifier() override;
+
+ // ClientCertVerifier implementation
+ int Verify(X509Certificate* cert,
+ const CompletionCallback& callback,
+ scoped_ptr<Request>* out_req) override;
+
+ // Sets the default return value for Verify() for certificates/hosts that do
+ // not have explicit results added via the AddResult*() methods.
+ void set_default_result(int default_result) {
+ default_result_ = default_result;
+ }
+
+ // Adds a rule that will cause any call to Verify() for |cert| to return rv.
+ // Note: Only the primary certificate of |cert| is checked. Any intermediate
+ // certificates will be ignored.
+ void AddResultForCert(X509Certificate* cert, int rv);
+
+ private:
+ struct Rule;
+ typedef std::list<Rule> RuleList;
+
+ int default_result_;
+ RuleList rules_;
+};
+
+} // namespace net
+
+#endif // NET_CERT_MOCK_CLIENT_CERT_VERIFIER_H_
diff --git a/chromium/net/cert/multi_log_ct_verifier_unittest.cc b/chromium/net/cert/multi_log_ct_verifier_unittest.cc
index d5d609a8ec4..e9505d73c05 100644
--- a/chromium/net/cert/multi_log_ct_verifier_unittest.cc
+++ b/chromium/net/cert/multi_log_ct_verifier_unittest.cc
@@ -70,20 +70,6 @@ class MultiLogCTVerifierTest : public ::testing::Test {
ASSERT_TRUE(embedded_sct_chain_.get());
}
- bool CheckForSingleVerifiedSCTInResult(const ct::CTVerifyResult& result) {
- return (result.verified_scts.size() == 1U) &&
- result.invalid_scts.empty() &&
- result.unknown_logs_scts.empty() &&
- result.verified_scts[0]->log_description == kLogDescription;
- }
-
- bool CheckForSCTOrigin(
- const ct::CTVerifyResult& result,
- ct::SignedCertificateTimestamp::Origin origin) {
- return (result.verified_scts.size() > 0) &&
- (result.verified_scts[0]->origin == origin);
- }
-
bool CheckForEmbeddedSCTInNetLog(TestNetLog& net_log) {
TestNetLogEntry::List entries;
net_log.GetEntries(&entries);
@@ -128,18 +114,6 @@ class MultiLogCTVerifierTest : public ::testing::Test {
return true;
}
- std::string GetSCTListWithInvalidSCT() {
- std::string sct(ct::GetTestSignedCertificateTimestamp());
-
- // Change a byte inside the Log ID part of the SCT so it does
- // not match the log used in the tests
- sct[15] = 't';
-
- std::string sct_list;
- ct::EncodeSCTListForTesting(sct, &sct_list);
- return sct_list;
- }
-
bool VerifySinglePrecertificateChain(scoped_refptr<X509Certificate> chain,
const BoundNetLog& bound_net_log,
ct::CTVerifyResult* result) {
@@ -169,9 +143,9 @@ class MultiLogCTVerifierTest : public ::testing::Test {
BoundNetLog bound_net_log =
BoundNetLog::Make(&net_log, NetLog::SOURCE_CONNECT_JOB);
return (VerifySinglePrecertificateChain(chain, bound_net_log, &result) &&
- CheckForSingleVerifiedSCTInResult(result) &&
- CheckForSCTOrigin(result,
- ct::SignedCertificateTimestamp::SCT_EMBEDDED) &&
+ ct::CheckForSingleVerifiedSCTInResult(result, kLogDescription) &&
+ ct::CheckForSCTOrigin(
+ result, ct::SignedCertificateTimestamp::SCT_EMBEDDED) &&
CheckForEmbeddedSCTInNetLog(net_log));
}
@@ -241,25 +215,20 @@ TEST_F(MultiLogCTVerifierTest,
ASSERT_TRUE(CheckPrecertificateVerification(chain));
}
-TEST_F(MultiLogCTVerifierTest,
- VerifiesSCTOverX509Cert) {
- std::string sct(ct::GetTestSignedCertificateTimestamp());
-
- std::string sct_list;
- ASSERT_TRUE(ct::EncodeSCTListForTesting(sct, &sct_list));
+TEST_F(MultiLogCTVerifierTest, VerifiesSCTOverX509Cert) {
+ std::string sct_list = ct::GetSCTListForTesting();
ct::CTVerifyResult result;
EXPECT_EQ(OK,
verifier_->Verify(
chain_.get(), std::string(), sct_list, &result, BoundNetLog()));
- ASSERT_TRUE(CheckForSingleVerifiedSCTInResult(result));
- ASSERT_TRUE(CheckForSCTOrigin(
+ ASSERT_TRUE(ct::CheckForSingleVerifiedSCTInResult(result, kLogDescription));
+ ASSERT_TRUE(ct::CheckForSCTOrigin(
result, ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION));
}
-TEST_F(MultiLogCTVerifierTest,
- IdentifiesSCTFromUnknownLog) {
- std::string sct_list = GetSCTListWithInvalidSCT();
+TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromUnknownLog) {
+ std::string sct_list = ct::GetSCTListWithInvalidSCT();
ct::CTVerifyResult result;
EXPECT_NE(OK,
@@ -278,7 +247,7 @@ TEST_F(MultiLogCTVerifierTest, CountsValidSCTsInStatusHistogram) {
}
TEST_F(MultiLogCTVerifierTest, CountsInvalidSCTsInStatusHistogram) {
- std::string sct_list = GetSCTListWithInvalidSCT();
+ std::string sct_list = ct::GetSCTListWithInvalidSCT();
ct::CTVerifyResult result;
int num_valid_scts = NumValidSCTsInStatusHistogram();
int num_invalid_scts = GetValueFromHistogram(
diff --git a/chromium/net/cert/multi_threaded_cert_verifier.cc b/chromium/net/cert/multi_threaded_cert_verifier.cc
index 23f1d874ec8..35afe371c67 100644
--- a/chromium/net/cert/multi_threaded_cert_verifier.cc
+++ b/chromium/net/cert/multi_threaded_cert_verifier.cc
@@ -19,6 +19,7 @@
#include "base/stl_util.h"
#include "base/threading/worker_pool.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/hash_value.h"
#include "net/base/net_errors.h"
@@ -29,7 +30,7 @@
#include "net/cert/x509_certificate_net_log_param.h"
#include "net/log/net_log.h"
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
#include <private/pprthred.h> // PR_DetachThread
#endif
@@ -234,18 +235,19 @@ void DoVerifyOnWorkerThread(const scoped_refptr<CertVerifyProc>& verify_proc,
const CertificateList& additional_trust_anchors,
int* error,
CertVerifyResult* result) {
+ TRACE_EVENT0("net", "DoVerifyOnWorkerThread");
*error = verify_proc->Verify(cert.get(), hostname, ocsp_response, flags,
crl_set.get(), additional_trust_anchors, result);
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
- // 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();
+#if defined(USE_NSS_VERIFIER)
+ // 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
}
@@ -359,6 +361,7 @@ class CertVerifierJob {
void OnJobCompleted(
scoped_ptr<MultiThreadedCertVerifier::CachedResult> verify_result) {
+ TRACE_EVENT0("net", "CertVerifierJob::OnJobCompleted");
scoped_ptr<CertVerifierJob> keep_alive = cert_verifier_->RemoveJob(this);
LogMetrics(*verify_result);
@@ -497,6 +500,9 @@ MultiThreadedCertVerifier::RequestParams::RequestParams(
hash_values.push_back(additional_trust_anchors[i]->fingerprint());
}
+MultiThreadedCertVerifier::RequestParams::RequestParams(
+ const RequestParams& other) = default;
+
MultiThreadedCertVerifier::RequestParams::~RequestParams() {}
bool MultiThreadedCertVerifier::RequestParams::operator<(
@@ -588,4 +594,3 @@ CertVerifierJob* MultiThreadedCertVerifier::FindJob(const RequestParams& key) {
}
} // namespace net
-
diff --git a/chromium/net/cert/multi_threaded_cert_verifier.h b/chromium/net/cert/multi_threaded_cert_verifier.h
index 30234ff9bc2..83d00dd583e 100644
--- a/chromium/net/cert/multi_threaded_cert_verifier.h
+++ b/chromium/net/cert/multi_threaded_cert_verifier.h
@@ -92,6 +92,7 @@ class NET_EXPORT_PRIVATE MultiThreadedCertVerifier
const std::string& ocsp_response_arg,
int flags_arg,
const CertificateList& additional_trust_anchors);
+ RequestParams(const RequestParams& other);
~RequestParams();
bool operator<(const RequestParams& other) const;
diff --git a/chromium/net/cert/nss_cert_database.cc b/chromium/net/cert/nss_cert_database.cc
index 53ea7c79fc5..896d1d3517b 100644
--- a/chromium/net/cert/nss_cert_database.cc
+++ b/chromium/net/cert/nss_cert_database.cc
@@ -78,6 +78,9 @@ NSSCertDatabase::ImportCertFailure::ImportCertFailure(
int err)
: certificate(cert), net_error(err) {}
+NSSCertDatabase::ImportCertFailure::ImportCertFailure(
+ const ImportCertFailure& other) = default;
+
NSSCertDatabase::ImportCertFailure::~ImportCertFailure() {}
NSSCertDatabase::NSSCertDatabase(crypto::ScopedPK11Slot public_slot,
@@ -452,19 +455,19 @@ void NSSCertDatabase::NotifyCertRemovalAndCallBack(
void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) {
observer_list_->Notify(FROM_HERE, &Observer::OnCertAdded,
- make_scoped_refptr(cert));
+ base::RetainedRef(cert));
}
void NSSCertDatabase::NotifyObserversOfCertRemoved(
const X509Certificate* cert) {
observer_list_->Notify(FROM_HERE, &Observer::OnCertRemoved,
- make_scoped_refptr(cert));
+ base::RetainedRef(cert));
}
void NSSCertDatabase::NotifyObserversOfCACertChanged(
const X509Certificate* cert) {
observer_list_->Notify(FROM_HERE, &Observer::OnCACertChanged,
- make_scoped_refptr(cert));
+ base::RetainedRef(cert));
}
// static
diff --git a/chromium/net/cert/nss_cert_database.h b/chromium/net/cert/nss_cert_database.h
index ff96af029d4..fe267f92af7 100644
--- a/chromium/net/cert/nss_cert_database.h
+++ b/chromium/net/cert/nss_cert_database.h
@@ -13,6 +13,7 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "crypto/scoped_nss_types.h"
@@ -65,6 +66,7 @@ class NET_EXPORT NSSCertDatabase {
struct NET_EXPORT ImportCertFailure {
public:
ImportCertFailure(const scoped_refptr<X509Certificate>& cert, int err);
+ ImportCertFailure(const ImportCertFailure& other);
~ImportCertFailure();
scoped_refptr<X509Certificate> certificate;
diff --git a/chromium/net/cert/nss_profile_filter_chromeos.cc b/chromium/net/cert/nss_profile_filter_chromeos.cc
index 40502e350f2..3523931ce70 100644
--- a/chromium/net/cert/nss_profile_filter_chromeos.cc
+++ b/chromium/net/cert/nss_profile_filter_chromeos.cc
@@ -69,9 +69,10 @@ void NSSProfileFilterChromeOS::Init(crypto::ScopedPK11Slot public_slot,
crypto::ScopedPK11Slot system_slot) {
// crypto::ScopedPK11Slot actually holds a reference counted object.
// Because scoped_ptr<T> assignment is a no-op if it already points to
- // the same pointer, a reference would be leaked because .Pass() does
+ // the same pointer, a reference would be leaked because std::move() does
// not release its reference, and the receiving object won't free
// its copy.
+ // TODO(dcheng): This comment doesn't seem quite right.
if (public_slot_.get() != public_slot.get())
public_slot_ = std::move(public_slot);
if (private_slot_.get() != private_slot.get())
diff --git a/chromium/net/cert/sha256_legacy_support_win.cc b/chromium/net/cert/sha256_legacy_support_win.cc
deleted file mode 100644
index a936637e520..00000000000
--- a/chromium/net/cert/sha256_legacy_support_win.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright 2014 The Chromium 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/sha256_legacy_support_win.h"
-
-#include <openssl/asn1.h>
-#include <openssl/bytestring.h>
-#include <openssl/evp.h>
-#include <openssl/obj.h>
-#include <openssl/x509.h>
-
-#include "base/logging.h"
-#include "crypto/scoped_openssl_types.h"
-
-namespace net {
-
-namespace sha256_interception {
-
-namespace {
-
-using ScopedX509_ALGOR = crypto::ScopedOpenSSL<X509_ALGOR, X509_ALGOR_free>;
-
-bool IsSupportedSubjectType(DWORD subject_type) {
- switch (subject_type) {
- case CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB:
- case CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT:
- case CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL:
- return true;
- }
- return false;
-}
-
-bool IsSupportedIssuerType(DWORD issuer_type) {
- switch (issuer_type) {
- case CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY:
- case CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT:
- case CRYPT_VERIFY_CERT_SIGN_ISSUER_CHAIN:
- return true;
- }
- return false;
-}
-
-base::StringPiece GetSubjectSignature(DWORD subject_type,
- void* subject_data) {
- switch (subject_type) {
- case CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB: {
- CRYPT_DATA_BLOB* data_blob =
- reinterpret_cast<CRYPT_DATA_BLOB*>(subject_data);
- return base::StringPiece(reinterpret_cast<char*>(data_blob->pbData),
- data_blob->cbData);
- }
- case CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT: {
- PCCERT_CONTEXT subject_cert =
- reinterpret_cast<PCCERT_CONTEXT>(subject_data);
- return base::StringPiece(
- reinterpret_cast<char*>(subject_cert->pbCertEncoded),
- subject_cert->cbCertEncoded);
- }
- case CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL: {
- PCCRL_CONTEXT subject_crl =
- reinterpret_cast<PCCRL_CONTEXT>(subject_data);
- return base::StringPiece(
- reinterpret_cast<char*>(subject_crl->pbCrlEncoded),
- subject_crl->cbCrlEncoded);
- }
- }
- return base::StringPiece();
-}
-
-PCERT_PUBLIC_KEY_INFO GetIssuerPublicKey(DWORD issuer_type,
- void* issuer_data) {
- switch (issuer_type) {
- case CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY:
- return reinterpret_cast<PCERT_PUBLIC_KEY_INFO>(issuer_data);
- case CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT: {
- PCCERT_CONTEXT cert = reinterpret_cast<PCCERT_CONTEXT>(issuer_data);
- return &cert->pCertInfo->SubjectPublicKeyInfo;
- }
- case CRYPT_VERIFY_CERT_SIGN_ISSUER_CHAIN: {
- PCCERT_CHAIN_CONTEXT chain =
- reinterpret_cast<PCCERT_CHAIN_CONTEXT>(issuer_data);
- PCCERT_CONTEXT cert = chain->rgpChain[0]->rgpElement[0]->pCertContext;
- return &cert->pCertInfo->SubjectPublicKeyInfo;
- }
- }
- return NULL;
-}
-
-// Parses |subject_signature| and writes the components into |*out_tbs_data|,
-// |*out_algor|, and |*out_signature|. The BIT STRING in the signature must be
-// a multiple of 8 bits. |*out_signature| will have the padding byte removed.
-// It returns true on success and false on failure.
-bool ParseSubjectSignature(const base::StringPiece& subject_signature,
- CBS* out_tbs_data,
- ScopedX509_ALGOR* out_algor,
- CBS* out_signature) {
- CBS cbs, sequence, tbs_data, algorithm, signature;
- CBS_init(&cbs, reinterpret_cast<const uint8_t*>(subject_signature.data()),
- subject_signature.size());
- if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE) || CBS_len(&cbs) != 0 ||
- !CBS_get_any_asn1_element(&sequence, &tbs_data, nullptr, nullptr) ||
- !CBS_get_asn1_element(&sequence, &algorithm, CBS_ASN1_SEQUENCE) ||
- !CBS_get_asn1(&sequence, &signature, CBS_ASN1_BITSTRING) ||
- CBS_len(&sequence) != 0) {
- return false;
- }
-
- // Decode the algorithm.
- const uint8_t* ptr = CBS_data(&algorithm);
- ScopedX509_ALGOR algor(d2i_X509_ALGOR(NULL, &ptr, CBS_len(&algorithm)));
- if (!algor || ptr != CBS_data(&algorithm) + CBS_len(&algorithm))
- return false;
-
- // An ASN.1 BIT STRING is encoded with a leading byte denoting the number of
- // padding bits. All supported signature algorithms output octets, so the
- // leading byte must be zero.
- uint8_t padding;
- if (!CBS_get_u8(&signature, &padding) || padding != 0)
- return false;
-
- *out_tbs_data = tbs_data;
- *out_algor = algor.Pass();
- *out_signature = signature;
- return true;
-}
-
-} // namespace
-
-BOOL CryptVerifyCertificateSignatureExHook(
- CryptVerifyCertificateSignatureExFunc original_func,
- HCRYPTPROV_LEGACY provider,
- DWORD encoding_type,
- DWORD subject_type,
- void* subject_data,
- DWORD issuer_type,
- void* issuer_data,
- DWORD flags,
- void* extra) {
- CHECK(original_func);
-
- // Only intercept if the arguments are supported.
- if (provider != NULL || (encoding_type != X509_ASN_ENCODING) ||
- !IsSupportedSubjectType(subject_type) || subject_data == NULL ||
- !IsSupportedIssuerType(issuer_type) || issuer_data == NULL) {
- return original_func(provider, encoding_type, subject_type, subject_data,
- issuer_type, issuer_data, flags, extra);
- }
-
- base::StringPiece subject_signature =
- GetSubjectSignature(subject_type, subject_data);
- bool should_intercept = false;
-
- // Parse out the data, AlgorithmIdentifier, and signature.
- CBS tbs_data, signature;
- ScopedX509_ALGOR algor;
- if (ParseSubjectSignature(subject_signature, &tbs_data, &algor, &signature)) {
- // If the signature algorithm is RSA with one of the SHA-2 algorithms
- // supported by BoringSSL (excluding SHA-224, which is pointless), then
- // defer to the BoringSSL implementation. Otherwise, fall back and let the
- // OS handle it (e.g. in case there are any algorithm policies in effect).
- int nid = OBJ_obj2nid(algor->algorithm);
- if (nid == NID_sha256WithRSAEncryption ||
- nid == NID_sha384WithRSAEncryption ||
- nid == NID_sha512WithRSAEncryption) {
- should_intercept = true;
- }
- }
-
- if (!should_intercept) {
- return original_func(provider, encoding_type, subject_type, subject_data,
- issuer_type, issuer_data, flags, extra);
- }
-
- // Rather than attempting to synthesize an EVP_PKEY by hand, just force the
- // OS to do an ASN.1 encoding and then decode it back into BoringSSL. This
- // is silly for performance, but safest for consistency.
- PCERT_PUBLIC_KEY_INFO issuer_public_key =
- GetIssuerPublicKey(issuer_type, issuer_data);
- if (!issuer_public_key) {
- SetLastError(static_cast<DWORD>(NTE_BAD_ALGID));
- return FALSE;
- }
-
- uint8_t* issuer_spki_data = NULL;
- DWORD issuer_spki_len = 0;
- if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
- issuer_public_key, CRYPT_ENCODE_ALLOC_FLAG, NULL,
- &issuer_spki_data, &issuer_spki_len)) {
- return FALSE;
- }
-
- const uint8_t* ptr = issuer_spki_data;
- crypto::ScopedEVP_PKEY pubkey(d2i_PUBKEY(NULL, &ptr, issuer_spki_len));
- if (!pubkey.get() || ptr != issuer_spki_data + issuer_spki_len) {
- ::LocalFree(issuer_spki_data);
- SetLastError(static_cast<DWORD>(NTE_BAD_ALGID));
- return FALSE;
- }
- ::LocalFree(issuer_spki_data);
-
- crypto::ScopedEVP_MD_CTX md_ctx(EVP_MD_CTX_create());
- if (!EVP_DigestVerifyInitFromAlgorithm(md_ctx.get(), algor.get(),
- pubkey.get()) ||
- !EVP_DigestVerifyUpdate(md_ctx.get(), CBS_data(&tbs_data),
- CBS_len(&tbs_data)) ||
- !EVP_DigestVerifyFinal(md_ctx.get(), CBS_data(&signature),
- CBS_len(&signature))) {
- SetLastError(static_cast<DWORD>(NTE_BAD_SIGNATURE));
- return FALSE;
- }
- return TRUE;
-}
-
-} // namespace sha256_interception
-
-} // namespace net
diff --git a/chromium/net/cert/sha256_legacy_support_win.h b/chromium/net/cert/sha256_legacy_support_win.h
deleted file mode 100644
index 472ff602ef8..00000000000
--- a/chromium/net/cert/sha256_legacy_support_win.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2014 The Chromium 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_SHA256_LEGACY_SUPPORT_WIN_H_
-#define NET_CERT_SHA256_LEGACY_SUPPORT_WIN_H_
-
-#include <windows.h>
-
-#include "base/strings/string_piece.h"
-#include "crypto/wincrypt_shim.h"
-#include "net/base/net_export.h"
-
-namespace net {
-
-namespace sha256_interception {
-
-typedef BOOL (WINAPI* CryptVerifyCertificateSignatureExFunc)(
- HCRYPTPROV_LEGACY provider,
- DWORD encoding_type,
- DWORD subject_type,
- void* subject_data,
- DWORD issuer_type,
- void* issuer_data,
- DWORD flags,
- void* extra);
-
-// Interception function meant to be called whenever
-// CryptVerifyCertificateSignatureEx is called. Note that the calling
-// conventions do not match, as the caller is expected to ensure that their
-// interposed function handles the calling conventions and provides a pointer
-// to the original CryptVerifyCertificateSignatureEx (e.g. to handle parameters
-// and keys that are not supported).
-NET_EXPORT BOOL CryptVerifyCertificateSignatureExHook(
- CryptVerifyCertificateSignatureExFunc original_func,
- HCRYPTPROV_LEGACY provider,
- DWORD encoding_type,
- DWORD subject_type,
- void* subject_data,
- DWORD issuer_type,
- void* issuer_data,
- DWORD flags,
- void* extra);
-
-} // namespace sha256_interception
-
-} // namespace net
-
-#endif // NET_CERT_SHA256_LEGACY_SUPPORT_WIN_H_
diff --git a/chromium/net/cert/sha256_legacy_support_win_unittest.cc b/chromium/net/cert/sha256_legacy_support_win_unittest.cc
deleted file mode 100644
index 0496ca3070f..00000000000
--- a/chromium/net/cert/sha256_legacy_support_win_unittest.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2014 The Chromium 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/sha256_legacy_support_win.h"
-
-#include "base/memory/ref_counted.h"
-#include "net/base/test_data_directory.h"
-#include "net/cert/x509_certificate.h"
-#include "net/test/cert_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-
-namespace sha256_interception {
-
-namespace {
-
-// Verifies that SHA-256 signatures can be validated through the interception.
-// Although this is only needed on legacy platforms, the test is run on all
-// Windows platforms to make sure that the CryptoAPI<->NSS integration does not
-// regress.
-TEST(Sha256Interception, HandlesSHA2) {
- base::FilePath certs_dir = GetTestCertsDirectory();
-
- scoped_refptr<X509Certificate> server_cert =
- ImportCertFromFile(certs_dir, "sha256.pem");
- ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get());
-
- CryptVerifyCertificateSignatureExFunc cert_verify_signature_ptr =
- reinterpret_cast<CryptVerifyCertificateSignatureExFunc>(
- ::GetProcAddress(::GetModuleHandle(L"crypt32.dll"),
- "CryptVerifyCertificateSignatureEx"));
- ASSERT_TRUE(cert_verify_signature_ptr);
-
- BOOL rv = CryptVerifyCertificateSignatureExHook(
- cert_verify_signature_ptr, NULL, X509_ASN_ENCODING,
- CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT,
- const_cast<void*>(reinterpret_cast<const void*>(
- server_cert->os_cert_handle())),
- CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT,
- const_cast<void*>(reinterpret_cast<const void*>(
- server_cert->os_cert_handle())),
- 0, NULL);
- EXPECT_EQ(TRUE, rv);
-}
-
-} // namespace
-
-} // namespace sha256_interception
-
-} // namespace net \ No newline at end of file
diff --git a/chromium/net/cert/signed_tree_head.cc b/chromium/net/cert/signed_tree_head.cc
new file mode 100644
index 00000000000..8bf2b9f3ff7
--- /dev/null
+++ b/chromium/net/cert/signed_tree_head.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 "net/cert/signed_tree_head.h"
+
+#include <string.h>
+
+#include <ostream>
+
+#include "base/strings/string_number_conversions.h"
+
+namespace net {
+namespace ct {
+
+SignedTreeHead::SignedTreeHead() {}
+
+SignedTreeHead::SignedTreeHead(Version version,
+ const base::Time& timestamp,
+ uint64_t tree_size,
+ const char sha256_root_hash[kSthRootHashLength],
+ const DigitallySigned& signature,
+ const std::string& log_id)
+ : version(version),
+ timestamp(timestamp),
+ tree_size(tree_size),
+ signature(signature),
+ log_id(log_id) {
+ memcpy(this->sha256_root_hash, sha256_root_hash, kSthRootHashLength);
+}
+
+SignedTreeHead::SignedTreeHead(const SignedTreeHead& other) = default;
+
+SignedTreeHead::~SignedTreeHead() {}
+
+void PrintTo(const SignedTreeHead& sth, std::ostream* os) {
+ (*os) << "{\n"
+ << "\t\"version\": " << sth.version << ",\n"
+ << "\t\"timestamp\": " << sth.timestamp << ",\n"
+ << "\t\"tree_size\": " << sth.tree_size << ",\n"
+ << "\t\"sha256_root_hash\": \""
+ << base::HexEncode(sth.sha256_root_hash, kSthRootHashLength)
+ << "\",\n\t\"log_id\": \""
+ << base::HexEncode(sth.log_id.data(), sth.log_id.size()) << "\"\n"
+ << "}";
+}
+
+} // namespace ct
+} // namespace net
diff --git a/chromium/net/cert/signed_tree_head.h b/chromium/net/cert/signed_tree_head.h
index 161373607b2..154c7a9d08d 100644
--- a/chromium/net/cert/signed_tree_head.h
+++ b/chromium/net/cert/signed_tree_head.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <iosfwd>
#include <string>
#include <vector>
@@ -28,13 +29,29 @@ struct NET_EXPORT SignedTreeHead {
// RFC6962-bis to use separate versions, so using a separate scheme here.
enum Version { V1 = 0, };
+ SignedTreeHead();
+ SignedTreeHead(Version version,
+ const base::Time& timestamp,
+ uint64_t tree_size,
+ const char sha256_root_hash[kSthRootHashLength],
+ const DigitallySigned& signature,
+ const std::string& log_id);
+ SignedTreeHead(const SignedTreeHead& other);
+ ~SignedTreeHead();
+
Version version;
base::Time timestamp;
uint64_t tree_size;
char sha256_root_hash[kSthRootHashLength];
DigitallySigned signature;
+
+ // Added in RFC6962-bis, Appendix A. Needed to identify which log
+ // this STH belongs to.
+ std::string log_id;
};
+NET_EXPORT void PrintTo(const SignedTreeHead& sth, std::ostream* os);
+
} // namespace ct
} // namespace net
diff --git a/chromium/net/cert/sth_distributor.cc b/chromium/net/cert/sth_distributor.cc
new file mode 100644
index 00000000000..65a471f584d
--- /dev/null
+++ b/chromium/net/cert/sth_distributor.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 "net/cert/sth_distributor.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "base/time/time.h"
+#include "net/cert/signed_tree_head.h"
+
+namespace {
+const char kPilotLogID[33] =
+ "\xa4\xb9\x09\x90\xb4\x18\x58\x14\x87\xbb\x13\xa2\xcc\x67\x70\x0a\x3c\x35"
+ "\x98\x04\xf9\x1b\xdf\xb8\xe3\x77\xcd\x0e\xc8\x0d\xdc\x10";
+}
+
+namespace net {
+
+namespace ct {
+
+STHDistributor::STHDistributor()
+ : observer_list_(base::ObserverList<STHObserver>::NOTIFY_EXISTING_ONLY) {}
+
+STHDistributor::~STHDistributor() {}
+
+void STHDistributor::NewSTHObserved(const SignedTreeHead& sth) {
+ FOR_EACH_OBSERVER(STHObserver, observer_list_, NewSTHObserved(sth));
+
+ if (sth.log_id.compare(0, sth.log_id.size(), kPilotLogID,
+ arraysize(kPilotLogID)) != 0)
+ return;
+
+ const base::TimeDelta sth_age = base::Time::Now() - sth.timestamp;
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.CertificateTransparency.PilotSTHAge", sth_age,
+ base::TimeDelta::FromHours(1),
+ base::TimeDelta::FromDays(4), 100);
+}
+
+void STHDistributor::RegisterObserver(STHObserver* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void STHDistributor::UnregisterObserver(STHObserver* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
+} // namespace ct
+
+} // namespace net
diff --git a/chromium/net/cert/sth_distributor.h b/chromium/net/cert/sth_distributor.h
new file mode 100644
index 00000000000..3d9691cc56c
--- /dev/null
+++ b/chromium/net/cert/sth_distributor.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_CERT_STH_DISTRIBUTOR_H_
+#define NET_CERT_STH_DISTRIBUTOR_H_
+
+#include "base/observer_list.h"
+#include "net/base/net_export.h"
+#include "net/cert/sth_observer.h"
+#include "net/cert/sth_reporter.h"
+
+namespace net {
+
+namespace ct {
+
+// A proxy for delegating new STH notifications to all registered
+// observers.
+// For each |observer| registered with RegisterObserver, the
+// NewSTHObserved method will be called whenever the STHDistributor's
+// NewSTHObserved method is invoked.
+class NET_EXPORT STHDistributor : public STHObserver, public STHReporter {
+ public:
+ STHDistributor();
+ ~STHDistributor() override;
+
+ // STHObserver implementation.
+ void NewSTHObserved(const SignedTreeHead& sth) override;
+
+ // STHReporter implementation
+ void RegisterObserver(STHObserver* observer) override;
+ void UnregisterObserver(STHObserver* observer) override;
+
+ private:
+ base::ObserverList<STHObserver> observer_list_;
+};
+
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_STH_DISTRIBUTOR_H_
diff --git a/chromium/net/cert/sth_observer.h b/chromium/net/cert/sth_observer.h
new file mode 100644
index 00000000000..ad65a6bd162
--- /dev/null
+++ b/chromium/net/cert/sth_observer.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_CERT_STH_OBSERVER_H_
+#define NET_CERT_STH_OBSERVER_H_
+
+#include <set>
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+namespace ct {
+
+struct SignedTreeHead;
+
+// Interface for receiving notifications of new STHs observed.
+class NET_EXPORT STHObserver {
+ public:
+ virtual ~STHObserver() {}
+
+ // Called with a new |sth| when one is observed.
+ virtual void NewSTHObserved(const SignedTreeHead& sth) = 0;
+};
+
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_STH_OBSERVER_H_
diff --git a/chromium/net/cert/sth_reporter.h b/chromium/net/cert/sth_reporter.h
new file mode 100644
index 00000000000..a62ad659bf9
--- /dev/null
+++ b/chromium/net/cert/sth_reporter.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_CERT_STH_REPORTER_H_
+#define NET_CERT_STH_REPORTER_H_
+
+#include <set>
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+namespace ct {
+
+class STHObserver;
+
+// Interface for registering/unregistering observers.
+class NET_EXPORT STHReporter {
+ public:
+ virtual ~STHReporter() {}
+
+ virtual void RegisterObserver(STHObserver* observer) = 0;
+ virtual void UnregisterObserver(STHObserver* observer) = 0;
+};
+
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_STH_REPORTER_H_
diff --git a/chromium/net/cert/test_root_certs.h b/chromium/net/cert/test_root_certs.h
index a7d0fd212de..412bbe8a3be 100644
--- a/chromium/net/cert/test_root_certs.h
+++ b/chromium/net/cert/test_root_certs.h
@@ -11,7 +11,7 @@
#include "build/build_config.h"
#include "net/base/net_export.h"
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
#include <list>
#elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
#include <vector>
@@ -67,7 +67,7 @@ class NET_EXPORT TestRootCerts {
#if defined(USE_NSS_CERTS)
bool Contains(CERTCertificate* cert) const;
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
+#elif defined(OS_MACOSX) && !defined(USE_NSS_VERIFIER)
CFArrayRef temporary_roots() const { return temporary_roots_; }
// Modifies the root certificates of |trust_ref| to include the
@@ -102,7 +102,7 @@ class NET_EXPORT TestRootCerts {
// Performs platform-dependent initialization.
void Init();
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
// It is necessary to maintain a cache of the original certificate trust
// settings, in order to restore them when Clear() is called.
class TrustEntry;
diff --git a/chromium/net/cert/test_root_certs_mac.cc b/chromium/net/cert/test_root_certs_mac.cc
index 87824d4c9ed..af1e9c18dbe 100644
--- a/chromium/net/cert/test_root_certs_mac.cc
+++ b/chromium/net/cert/test_root_certs_mac.cc
@@ -7,8 +7,6 @@
#include <Security/Security.h>
#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/scoped_cftyperef.h"
#include "net/cert/x509_certificate.h"
namespace net {
@@ -69,37 +67,10 @@ OSStatus TestRootCerts::FixupSecTrustRef(SecTrustRef trust_ref) const {
if (IsEmpty())
return noErr;
- // Despite SecTrustSetAnchorCertificatesOnly existing in OS X 10.6, and
- // being documented as available, it is not actually implemented. On 10.7+,
- // however, it always works.
- if (base::mac::IsOSLionOrLater()) {
- OSStatus status = SecTrustSetAnchorCertificates(trust_ref,
- temporary_roots_);
- if (status)
- return status;
- return SecTrustSetAnchorCertificatesOnly(trust_ref, !allow_system_trust_);
- }
-
- if (!allow_system_trust_) {
- // Avoid any copying if system roots are not to be trusted. This acts as
- // an exclusive list on 10.6, replacing the built-ins.
- return SecTrustSetAnchorCertificates(trust_ref, temporary_roots_);
- }
-
- // Otherwise, both system trust and temporary_roots_ must be trusted.
- // Emulate the functionality of SecTrustSetAnchorCertificatesOnly by
- // creating a copy of the system roots and merging with temporary_roots_.
- CFArrayRef system_roots = NULL;
- OSStatus status = SecTrustCopyAnchorCertificates(&system_roots);
+ OSStatus status = SecTrustSetAnchorCertificates(trust_ref, temporary_roots_);
if (status)
return status;
-
- base::ScopedCFTypeRef<CFArrayRef> scoped_system_roots(system_roots);
- base::ScopedCFTypeRef<CFMutableArrayRef> scoped_roots(
- CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, scoped_system_roots));
- CFArrayAppendArray(scoped_roots, temporary_roots_,
- CFRangeMake(0, CFArrayGetCount(temporary_roots_)));
- return SecTrustSetAnchorCertificates(trust_ref, scoped_roots);
+ return SecTrustSetAnchorCertificatesOnly(trust_ref, !allow_system_trust_);
}
void TestRootCerts::SetAllowSystemTrust(bool allow_system_trust) {
diff --git a/chromium/net/cert/test_root_certs_unittest.cc b/chromium/net/cert/test_root_certs_unittest.cc
index e55c147c346..2f449e7651e 100644
--- a/chromium/net/cert/test_root_certs_unittest.cc
+++ b/chromium/net/cert/test_root_certs_unittest.cc
@@ -14,7 +14,7 @@
#include "net/test/cert_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
#include <nss.h>
#endif
@@ -68,7 +68,7 @@ TEST(TestRootCertsTest, AddFromFile) {
// the results of the rest of net_unittests, ensuring that the trust status
// is properly being set and cleared.
TEST(TestRootCertsTest, OverrideTrust) {
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
if (NSS_VersionCheck("3.14.2") && !NSS_VersionCheck("3.15")) {
// See http://bugzil.la/863947 for details
LOG(INFO) << "Skipping test for NSS 3.14.2 - NSS 3.15";
diff --git a/chromium/net/cert/x509_cert_types.cc b/chromium/net/cert/x509_cert_types.cc
index bfb875cf56c..766a1f0429b 100644
--- a/chromium/net/cert/x509_cert_types.cc
+++ b/chromium/net/cert/x509_cert_types.cc
@@ -8,9 +8,9 @@
#include <cstring>
#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/time/time.h"
+#include "net/base/parse_number.h"
#include "net/cert/x509_certificate.h"
namespace net {
@@ -23,7 +23,8 @@ namespace {
// untouched otherwise. Returns the parsed integer.
int ParseIntAndAdvance(const char** field, size_t field_len, bool* ok) {
int result = 0;
- *ok &= base::StringToInt(base::StringPiece(*field, field_len), &result);
+ *ok &=
+ ParseNonNegativeDecimalInt(base::StringPiece(*field, field_len), &result);
*field += field_len;
return result;
}
diff --git a/chromium/net/cert/x509_cert_types_mac.cc b/chromium/net/cert/x509_cert_types_mac.cc
index c8ed4fe00f5..4a7a968fa27 100644
--- a/chromium/net/cert/x509_cert_types_mac.cc
+++ b/chromium/net/cert/x509_cert_types_mac.cc
@@ -19,6 +19,11 @@ namespace net {
namespace {
+// 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"
+
// The BER encoding of 0.9.2342.19200300.100.1.25.
// On 10.6 and later this is available as CSSMOID_DomainComponent, which is an
// external symbol from Security.framework. However, it appears that Apple's
@@ -289,4 +294,6 @@ bool CertPrincipal::Matches(const CertPrincipal& against) const {
match(domain_components, against.domain_components);
}
+#pragma clang diagnostic pop // "-Wdeprecated-declarations"
+
} // namespace net
diff --git a/chromium/net/cert/x509_cert_types_unittest.cc b/chromium/net/cert/x509_cert_types_unittest.cc
index f3bf8fccb11..50275f0eb01 100644
--- a/chromium/net/cert/x509_cert_types_unittest.cc
+++ b/chromium/net/cert/x509_cert_types_unittest.cc
@@ -148,50 +148,40 @@ const struct CertDateTestData {
bool is_valid;
base::Time::Exploded expected_result;
} kCertDateTimeData[] = {
- { CERT_DATE_FORMAT_UTC_TIME,
- "120101000000Z",
- true,
- { 2012, 1, 0, 1, 0, 0, 0 } },
- { CERT_DATE_FORMAT_GENERALIZED_TIME,
- "20120101000000Z",
- true,
- { 2012, 1, 0, 1, 0, 0, 0 } },
- { CERT_DATE_FORMAT_UTC_TIME,
- "490101000000Z",
- true,
- { 2049, 1, 0, 1, 0, 0, 0 } },
- { CERT_DATE_FORMAT_UTC_TIME,
- "500101000000Z",
- true,
- { 1950, 1, 0, 1, 0, 0, 0 } },
- { CERT_DATE_FORMAT_GENERALIZED_TIME,
- "19500101000000Z",
- true,
- { 1950, 1, 0, 1, 0, 0, 0 } },
- { CERT_DATE_FORMAT_UTC_TIME,
- "AB0101000000Z",
- false,
- { 0 } },
- { CERT_DATE_FORMAT_GENERALIZED_TIME,
- "19AB0101000000Z",
- false,
- { 0 } },
- { CERT_DATE_FORMAT_UTC_TIME,
- "",
- false,
- { 0 } },
- { CERT_DATE_FORMAT_UTC_TIME,
- "A",
- false,
- { 0 } },
- { CERT_DATE_FORMAT_GENERALIZED_TIME,
- "20121301000000Z",
- false,
- { 0 } },
- { CERT_DATE_FORMAT_GENERALIZED_TIME,
- "20120101123000Z",
- true,
- { 2012, 1, 0, 1, 12, 30, 0 } },
+ {CERT_DATE_FORMAT_UTC_TIME,
+ "120101000000Z",
+ true,
+ {2012, 1, 0, 1, 0, 0, 0}},
+ {CERT_DATE_FORMAT_UTC_TIME, "-90101000000Z", false, {0}},
+ {CERT_DATE_FORMAT_UTC_TIME, "+90101000000Z", false, {0}},
+ {CERT_DATE_FORMAT_GENERALIZED_TIME, "2012+1+1000000Z", false, {0}},
+ {CERT_DATE_FORMAT_GENERALIZED_TIME, "2012-101000000Z", false, {0}},
+ {CERT_DATE_FORMAT_GENERALIZED_TIME, "2012 101000000Z", false, {0}},
+ {CERT_DATE_FORMAT_GENERALIZED_TIME,
+ "20120101000000Z",
+ true,
+ {2012, 1, 0, 1, 0, 0, 0}},
+ {CERT_DATE_FORMAT_UTC_TIME,
+ "490101000000Z",
+ true,
+ {2049, 1, 0, 1, 0, 0, 0}},
+ {CERT_DATE_FORMAT_UTC_TIME,
+ "500101000000Z",
+ true,
+ {1950, 1, 0, 1, 0, 0, 0}},
+ {CERT_DATE_FORMAT_GENERALIZED_TIME,
+ "19500101000000Z",
+ true,
+ {1950, 1, 0, 1, 0, 0, 0}},
+ {CERT_DATE_FORMAT_UTC_TIME, "AB0101000000Z", false, {0}},
+ {CERT_DATE_FORMAT_GENERALIZED_TIME, "19AB0101000000Z", false, {0}},
+ {CERT_DATE_FORMAT_UTC_TIME, "", false, {0}},
+ {CERT_DATE_FORMAT_UTC_TIME, "A", false, {0}},
+ {CERT_DATE_FORMAT_GENERALIZED_TIME, "20121301000000Z", false, {0}},
+ {CERT_DATE_FORMAT_GENERALIZED_TIME,
+ "20120101123000Z",
+ true,
+ {2012, 1, 0, 1, 12, 30, 0}},
};
// GTest pretty printer.
diff --git a/chromium/net/cert/x509_cert_types_win.cc b/chromium/net/cert/x509_cert_types_win.cc
index 1ec64c02f96..032c2480940 100644
--- a/chromium/net/cert/x509_cert_types_win.cc
+++ b/chromium/net/cert/x509_cert_types_win.cc
@@ -7,14 +7,13 @@
#include <windows.h>
#include "base/logging.h"
+#include "base/memory/free_deleter.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "crypto/capi_util.h"
#include "crypto/wincrypt_shim.h"
-#pragma comment(lib, "crypt32.lib")
-
namespace net {
namespace {
diff --git a/chromium/net/cert/x509_certificate.cc b/chromium/net/cert/x509_certificate.cc
index d925ce6b490..797793fa634 100644
--- a/chromium/net/cert/x509_certificate.cc
+++ b/chromium/net/cert/x509_certificate.cc
@@ -27,8 +27,8 @@
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "crypto/secure_hash.h"
-#include "net/base/net_util.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/base/url_util.h"
#include "net/cert/pem_tokenizer.h"
#include "url/url_canon.h"
@@ -255,7 +255,7 @@ X509Certificate::X509Certificate(const std::string& subject,
}
// static
-X509Certificate* X509Certificate::CreateFromHandle(
+scoped_refptr<X509Certificate> X509Certificate::CreateFromHandle(
OSCertHandle cert_handle,
const OSCertHandles& intermediates) {
DCHECK(cert_handle);
@@ -263,7 +263,7 @@ X509Certificate* X509Certificate::CreateFromHandle(
}
// static
-X509Certificate* X509Certificate::CreateFromDERCertChain(
+scoped_refptr<X509Certificate> X509Certificate::CreateFromDERCertChain(
const std::vector<base::StringPiece>& der_certs) {
// TODO(cbentzel): Remove ScopedTracker below once crbug.com/424386 is fixed.
tracked_objects::ScopedTracker tracking_profile(
@@ -289,7 +289,7 @@ X509Certificate* X509Certificate::CreateFromDERCertChain(
const_cast<char*>(der_certs[0].data()), der_certs[0].size());
}
- X509Certificate* cert = NULL;
+ scoped_refptr<X509Certificate> cert = nullptr;
if (handle) {
cert = CreateFromHandle(handle, intermediate_ca_certs);
FreeOSCertHandle(handle);
@@ -302,19 +302,21 @@ X509Certificate* X509Certificate::CreateFromDERCertChain(
}
// static
-X509Certificate* X509Certificate::CreateFromBytes(const char* data,
- size_t length) {
+scoped_refptr<X509Certificate> X509Certificate::CreateFromBytes(
+ const char* data,
+ size_t length) {
OSCertHandle cert_handle = CreateOSCertHandleFromBytes(data, length);
if (!cert_handle)
return NULL;
- X509Certificate* cert = CreateFromHandle(cert_handle, OSCertHandles());
+ scoped_refptr<X509Certificate> cert =
+ CreateFromHandle(cert_handle, OSCertHandles());
FreeOSCertHandle(cert_handle);
return cert;
}
// static
-X509Certificate* X509Certificate::CreateFromPickle(
+scoped_refptr<X509Certificate> X509Certificate::CreateFromPickle(
base::PickleIterator* pickle_iter,
PickleType type) {
if (type == PICKLETYPE_CERTIFICATE_CHAIN_V3) {
@@ -389,7 +391,7 @@ X509Certificate* X509Certificate::CreateFromPickle(
}
}
- X509Certificate* cert = NULL;
+ scoped_refptr<X509Certificate> cert = nullptr;
if (intermediates.size() == num_intermediates)
cert = CreateFromHandle(cert_handle, intermediates);
FreeOSCertHandle(cert_handle);
@@ -470,8 +472,7 @@ CertificateList X509Certificate::CreateCertificateListFromBytes(
for (OSCertHandles::iterator it = certificates.begin();
it != certificates.end(); ++it) {
- X509Certificate* result = CreateFromHandle(*it, OSCertHandles());
- results.push_back(scoped_refptr<X509Certificate>(result));
+ results.push_back(CreateFromHandle(*it, OSCertHandles()));
FreeOSCertHandle(*it);
}
diff --git a/chromium/net/cert/x509_certificate.h b/chromium/net/cert/x509_certificate.h
index c22a0d50d24..d70e6292258 100644
--- a/chromium/net/cert/x509_certificate.h
+++ b/chromium/net/cert/x509_certificate.h
@@ -140,36 +140,34 @@ class NET_EXPORT X509Certificate
base::Time start_date, base::Time expiration_date);
// Create an X509Certificate from a handle to the certificate object in the
- // underlying crypto library. The returned pointer must be stored in a
- // scoped_refptr<X509Certificate>.
- static X509Certificate* CreateFromHandle(OSCertHandle cert_handle,
- const OSCertHandles& intermediates);
+ // underlying crypto library.
+ static scoped_refptr<X509Certificate> CreateFromHandle(
+ OSCertHandle cert_handle,
+ const OSCertHandles& intermediates);
// Create an X509Certificate from a chain of DER encoded certificates. The
// first certificate in the chain is the end-entity certificate to which a
// handle is returned. The other certificates in the chain are intermediate
- // certificates. The returned pointer must be stored in a
- // scoped_refptr<X509Certificate>.
- static X509Certificate* CreateFromDERCertChain(
+ // certificates.
+ static scoped_refptr<X509Certificate> CreateFromDERCertChain(
const std::vector<base::StringPiece>& der_certs);
// Create an X509Certificate from the DER-encoded representation.
// Returns NULL on failure.
- //
- // The returned pointer must be stored in a scoped_refptr<X509Certificate>.
- static X509Certificate* CreateFromBytes(const char* data, size_t length);
+ static scoped_refptr<X509Certificate> CreateFromBytes(const char* data,
+ 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. The returned pointer must be stored in a
- // scoped_refptr<X509Certificate>.
+ // 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 X509Certificate* CreateFromBytesWithNickname(const char* data,
- size_t length,
- const char* nickname);
+ 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,
@@ -181,10 +179,9 @@ class NET_EXPORT X509Certificate
// pickle. The data for this object is found relative to the given
// pickle_iter, which should be passed to the pickle's various Read* methods.
// Returns NULL on failure.
- //
- // The returned pointer must be stored in a scoped_refptr<X509Certificate>.
- static X509Certificate* CreateFromPickle(base::PickleIterator* pickle_iter,
- PickleType type);
+ static scoped_refptr<X509Certificate> CreateFromPickle(
+ base::PickleIterator* pickle_iter,
+ PickleType type);
// Parses all of the certificates possible from |data|. |format| is a
// bit-wise OR of Format, indicating the possible formats the
diff --git a/chromium/net/cert/x509_certificate_known_roots_win.h b/chromium/net/cert/x509_certificate_known_roots_win.h
index f914ec865d7..eea3a6875ff 100644
--- a/chromium/net/cert/x509_certificate_known_roots_win.h
+++ b/chromium/net/cert/x509_certificate_known_roots_win.h
@@ -8,7 +8,7 @@
#include <stdint.h>
// This is a union of Microsoft trust roots over time, from 01 January
-// 2007 through 24 November 2015.
+// 2007 through 22 January 2016.
//
// Extracted from
// http://www.download.windowsupdate.com/msdownload/update/v3/
@@ -193,6 +193,10 @@ static uint8_t kKnownRootCertSHA256Hashes[][32] = {
{0x17, 0x9F, 0xBC, 0x14, 0x8A, 0x3D, 0xD0, 0x0F, 0xD2, 0x4E, 0xA1, 0x34,
0x58, 0xCC, 0x43, 0xBF, 0xA7, 0xF5, 0x9C, 0x81, 0x82, 0xD7, 0x83, 0xA5,
0x13, 0xF6, 0xEB, 0xEC, 0x10, 0x0C, 0x89, 0x24},
+ // C=US, O=Amazon, CN=Amazon Root CA 3
+ {0x18, 0xCE, 0x6C, 0xFE, 0x7B, 0xF1, 0x4E, 0x60, 0xB2, 0xE3, 0x47, 0xB8,
+ 0xDF, 0xE8, 0x68, 0xCB, 0x31, 0xD0, 0x2E, 0xBB, 0x3A, 0xDA, 0x27, 0x15,
+ 0x69, 0xF5, 0x03, 0x43, 0xB4, 0x6D, 0xB3, 0xA4},
// C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 3
{0x18, 0xF1, 0xFC, 0x7F, 0x20, 0x5D, 0xF8, 0xAD, 0xDD, 0xEB, 0x7F, 0xE0,
0x07, 0xDD, 0x57, 0xE3, 0xAF, 0x37, 0x5A, 0x9C, 0x4D, 0x8D, 0x73, 0x54,
@@ -208,6 +212,10 @@ static uint8_t kKnownRootCertSHA256Hashes[][32] = {
{0x1A, 0x25, 0x12, 0xCD, 0xA6, 0x74, 0x4A, 0xBE, 0xA1, 0x14, 0x32, 0xA2,
0xFD, 0xC9, 0xF8, 0xC0, 0x88, 0xDB, 0x5A, 0x98, 0xC8, 0x9E, 0x13, 0x35,
0x25, 0x74, 0xCD, 0xE4, 0xD9, 0xE8, 0x0C, 0xDD},
+ // C=US, O=Amazon, CN=Amazon Root CA 2
+ {0x1B, 0xA5, 0xB2, 0xAA, 0x8C, 0x65, 0x40, 0x1A, 0x82, 0x96, 0x01, 0x18,
+ 0xF8, 0x0B, 0xEC, 0x4F, 0x62, 0x30, 0x4D, 0x83, 0xCE, 0xC4, 0x71, 0x3A,
+ 0x19, 0xC3, 0x9C, 0x01, 0x1E, 0xA4, 0x6D, 0xB4},
// C=CN, O=China Internet Network Information Center, CN=China Internet
// Network Information Center EV Certificates Root
{0x1C, 0x01, 0xC6, 0xF4, 0xDB, 0xB2, 0xFE, 0xFC, 0x22, 0x55, 0x8B, 0x2B,
@@ -755,6 +763,11 @@ static uint8_t kKnownRootCertSHA256Hashes[][32] = {
{0x69, 0xFA, 0xC9, 0xBD, 0x55, 0xFB, 0x0A, 0xC7, 0x8D, 0x53, 0xBB, 0xEE,
0x5C, 0xF1, 0xD5, 0x97, 0x98, 0x9F, 0xD0, 0xAA, 0xAB, 0x20, 0xA2, 0x51,
0x51, 0xBD, 0xF1, 0x73, 0x3E, 0xE7, 0xD1, 0x22},
+ // C=CH, O=WISeKey, OU=OISTE Foundation Endorsed, CN=OISTE WISeKey Global
+ // Root GB CA
+ {0x6B, 0x9C, 0x08, 0xE8, 0x6E, 0xB0, 0xF7, 0x67, 0xCF, 0xAD, 0x65, 0xCD,
+ 0x98, 0xB6, 0x21, 0x49, 0xE5, 0x49, 0x4A, 0x67, 0xF5, 0x84, 0x5E, 0x7B,
+ 0xD1, 0xED, 0x01, 0x9F, 0x27, 0xB8, 0x6B, 0xD6},
// C=AT, O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,
// OU=A-Trust-Qual-03, CN=A-Trust-Qual-03
{0x6B, 0xAF, 0x50, 0xAE, 0x34, 0x67, 0xEF, 0xF3, 0xC3, 0x5F, 0xEF, 0xDC,
@@ -1064,6 +1077,10 @@ static uint8_t kKnownRootCertSHA256Hashes[][32] = {
{0x8E, 0x8C, 0x6E, 0xBF, 0x77, 0xDC, 0x73, 0xDB, 0x3E, 0x38, 0xE9, 0x3F,
0x48, 0x03, 0xE6, 0x2B, 0x6B, 0x59, 0x33, 0xBE, 0xB5, 0x1E, 0xE4, 0x15,
0x2F, 0x68, 0xD7, 0xAA, 0x14, 0x42, 0x6B, 0x31},
+ // C=US, O=Amazon, CN=Amazon Root CA 1
+ {0x8E, 0xCD, 0xE6, 0x88, 0x4F, 0x3D, 0x87, 0xB1, 0x12, 0x5B, 0xA3, 0x1A,
+ 0xC3, 0xFC, 0xB1, 0x3D, 0x70, 0x16, 0xDE, 0x7F, 0x57, 0xCC, 0x90, 0x4F,
+ 0xE1, 0xCB, 0x97, 0xC6, 0xAE, 0x98, 0x19, 0x6E},
// CN=SG TRUST SERVICES RACINE, OU=0002 43525289500022, O=SG TRUST SERVICES,
// C=FR
{0x8F, 0x1E, 0xCD, 0xAF, 0x29, 0xBC, 0xD5, 0x6E, 0xDD, 0xD6, 0xB5, 0xD5,
@@ -1078,6 +1095,11 @@ static uint8_t kKnownRootCertSHA256Hashes[][32] = {
{0x8F, 0x63, 0x3D, 0xF0, 0x19, 0x1A, 0x41, 0x7D, 0xCD, 0x4F, 0x63, 0x31,
0xF0, 0xE9, 0x0E, 0xB9, 0x47, 0x15, 0x8C, 0x8A, 0x3E, 0xA5, 0x9B, 0xFE,
0x81, 0x42, 0x00, 0x41, 0x31, 0x5E, 0xAC, 0x6C},
+ // C=SE, O=Swedish Social Insurance Agency, CN=Swedish Government Root
+ // Authority v3
+ {0x8F, 0x9A, 0xDB, 0x6D, 0x89, 0x5D, 0xAB, 0x5A, 0xDF, 0x5C, 0x3D, 0x3F,
+ 0xAB, 0x83, 0x92, 0x7B, 0xE0, 0xFB, 0x64, 0xEF, 0x82, 0x48, 0x5C, 0x62,
+ 0x28, 0x0D, 0x58, 0x4E, 0x8B, 0xD5, 0x5D, 0x22},
// C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data
// Networks GmbH, OU=TC TrustCenter Class 2
// CA/emailAddress=certificate@trustcenter.de
@@ -1633,6 +1655,10 @@ static uint8_t kKnownRootCertSHA256Hashes[][32] = {
{0xE2, 0x83, 0x93, 0x77, 0x3D, 0xA8, 0x45, 0xA6, 0x79, 0xF2, 0x08, 0x0C,
0xC7, 0xFB, 0x44, 0xA3, 0xB7, 0xA1, 0xC3, 0x79, 0x2C, 0xB7, 0xEB, 0x77,
0x29, 0xFD, 0xCB, 0x6A, 0x8D, 0x99, 0xAE, 0xA7},
+ // C=US, O=Amazon, CN=Amazon Root CA 4
+ {0xE3, 0x5D, 0x28, 0x41, 0x9E, 0xD0, 0x20, 0x25, 0xCF, 0xA6, 0x90, 0x38,
+ 0xCD, 0x62, 0x39, 0x62, 0x45, 0x8D, 0xA5, 0xC6, 0x95, 0xFB, 0xDE, 0xA3,
+ 0xC2, 0x2B, 0x0B, 0xFB, 0x25, 0x89, 0x70, 0x92},
// C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign,
// Inc. - For authorized use only, CN=VeriSign Class 4 Public Primary
// Certification Authority - G3
diff --git a/chromium/net/cert/x509_certificate_mac.cc b/chromium/net/cert/x509_certificate_mac.cc
index e27576ab265..83f8993dabd 100644
--- a/chromium/net/cert/x509_certificate_mac.cc
+++ b/chromium/net/cert/x509_certificate_mac.cc
@@ -29,6 +29,11 @@ using base::Time;
namespace net {
+// 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"
+
namespace {
void GetCertDistinguishedName(
@@ -573,4 +578,6 @@ bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) {
return true;
}
+#pragma clang diagnostic pop // "-Wdeprecated-declarations"
+
} // namespace net
diff --git a/chromium/net/cert/x509_certificate_nss.cc b/chromium/net/cert/x509_certificate_nss.cc
index 1c5359198bc..14c8889eb20 100644
--- a/chromium/net/cert/x509_certificate_nss.cc
+++ b/chromium/net/cert/x509_certificate_nss.cc
@@ -40,7 +40,7 @@ void X509Certificate::Initialize() {
}
// static
-X509Certificate* X509Certificate::CreateFromBytesWithNickname(
+scoped_refptr<X509Certificate> X509Certificate::CreateFromBytesWithNickname(
const char* data,
size_t length,
const char* nickname) {
@@ -50,7 +50,8 @@ X509Certificate* X509Certificate::CreateFromBytesWithNickname(
if (!cert_handle)
return NULL;
- X509Certificate* cert = CreateFromHandle(cert_handle, OSCertHandles());
+ scoped_refptr<X509Certificate> cert =
+ CreateFromHandle(cert_handle, OSCertHandles());
FreeOSCertHandle(cert_handle);
if (nickname)
diff --git a/chromium/net/cert/x509_certificate_openssl_ios.cc b/chromium/net/cert/x509_certificate_openssl_ios.cc
new file mode 100644
index 00000000000..96ed1dea510
--- /dev/null
+++ b/chromium/net/cert/x509_certificate_openssl_ios.cc
@@ -0,0 +1,474 @@
+// 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/cert/x509_certificate.h"
+
+#include <CommonCrypto/CommonDigest.h>
+#include <Security/Security.h>
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "base/mac/scoped_cftyperef.h"
+#include "base/pickle.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+#include "net/base/ip_address_number.h"
+#include "net/cert/x509_util_openssl.h"
+#include "net/ssl/openssl_ssl_util.h"
+
+using base::ScopedCFTypeRef;
+
+namespace net {
+
+namespace {
+
+using ScopedGENERAL_NAMES =
+ crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free>;
+
+// Returns true if a given |cert_handle| is actually a valid X.509 certificate
+// handle.
+//
+// SecCertificateCreateFromData() does not always force the immediate parsing of
+// the certificate, and as such, may return a SecCertificateRef for an
+// invalid/unparsable certificate. Force parsing to occur to ensure that the
+// SecCertificateRef is correct. On later versions where
+// SecCertificateCreateFromData() immediately parses, rather than lazily, this
+// call is cheap, as the subject is cached.
+bool IsValidOSCertHandle(SecCertificateRef cert_handle) {
+ ScopedCFTypeRef<CFStringRef> sanity_check(
+ SecCertificateCopySubjectSummary(cert_handle));
+ return sanity_check != nullptr;
+}
+
+void CreateOSCertHandlesFromPKCS7Bytes(
+ const char* data,
+ size_t length,
+ X509Certificate::OSCertHandles* handles) {
+ crypto::EnsureOpenSSLInit();
+ crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE);
+
+ CBS der_data;
+ CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length);
+ STACK_OF(X509)* certs = sk_X509_new_null();
+
+ if (PKCS7_get_certificates(certs, &der_data)) {
+ for (size_t i = 0; i < sk_X509_num(certs); ++i) {
+ X509* x509_cert = sk_X509_value(certs, i);
+ base::StringPiece der;
+ if (!x509_util::GetDER(x509_cert, &der))
+ return;
+ handles->push_back(X509Certificate::CreateOSCertHandleFromBytes(
+ der.data(), der.length()));
+ }
+ }
+ sk_X509_pop_free(certs, X509_free);
+}
+
+void ParsePrincipalValues(X509_NAME* name,
+ int nid,
+ std::vector<std::string>* fields) {
+ for (int index = -1;
+ (index = X509_NAME_get_index_by_NID(name, nid, index)) != -1;) {
+ std::string field;
+ if (!x509_util::ParsePrincipalValueByIndex(name, index, &field))
+ break;
+ fields->push_back(field);
+ }
+}
+
+void ParsePrincipal(X509Certificate::OSCertHandle os_cert,
+ X509_NAME* x509_name,
+ CertPrincipal* principal) {
+ if (!x509_name)
+ return;
+
+ ParsePrincipalValues(x509_name, NID_streetAddress,
+ &principal->street_addresses);
+ ParsePrincipalValues(x509_name, NID_organizationName,
+ &principal->organization_names);
+ ParsePrincipalValues(x509_name, NID_organizationalUnitName,
+ &principal->organization_unit_names);
+ ParsePrincipalValues(x509_name, NID_domainComponent,
+ &principal->domain_components);
+
+ x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName,
+ &principal->common_name);
+ x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName,
+ &principal->locality_name);
+ x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName,
+ &principal->state_or_province_name);
+ x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName,
+ &principal->country_name);
+}
+
+void ParseSubjectAltName(X509Certificate::OSCertHandle os_cert,
+ std::vector<std::string>* dns_names,
+ std::vector<std::string>* ip_addresses) {
+ DCHECK(dns_names || ip_addresses);
+ ScopedX509 cert = OSCertHandleToOpenSSL(os_cert);
+ if (!cert.get())
+ return;
+ int index = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1);
+ X509_EXTENSION* alt_name_ext = X509_get_ext(cert.get(), index);
+ if (!alt_name_ext)
+ return;
+
+ ScopedGENERAL_NAMES alt_names(
+ reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext)));
+ if (!alt_names.get())
+ return;
+
+ for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) {
+ const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i);
+ if (name->type == GEN_DNS && dns_names) {
+ const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName);
+ if (!dns_name)
+ continue;
+ int dns_name_len = ASN1_STRING_length(name->d.dNSName);
+ dns_names->push_back(
+ std::string(reinterpret_cast<const char*>(dns_name), dns_name_len));
+ } else if (name->type == GEN_IPADD && ip_addresses) {
+ const unsigned char* ip_addr = name->d.iPAddress->data;
+ if (!ip_addr)
+ continue;
+ int ip_addr_len = name->d.iPAddress->length;
+ if (ip_addr_len != static_cast<int>(kIPv4AddressSize) &&
+ ip_addr_len != static_cast<int>(kIPv6AddressSize)) {
+ // http://www.ietf.org/rfc/rfc3280.txt requires subjectAltName iPAddress
+ // to have 4 or 16 bytes, whereas in a name constraint it includes a
+ // net mask hence 8 or 32 bytes. Logging to help diagnose any mixup.
+ LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len;
+ continue;
+ }
+ ip_addresses->push_back(
+ std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len));
+ }
+ }
+}
+
+// Used to free a list of X509_NAMEs and the objects it points to.
+void sk_X509_NAME_free_all(STACK_OF(X509_NAME) * sk) {
+ sk_X509_NAME_pop_free(sk, X509_NAME_free);
+}
+
+} // namespace
+
+// static
+X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
+ OSCertHandle handle) {
+ if (!handle)
+ return nullptr;
+ return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle)));
+}
+
+// static
+void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
+ if (cert_handle)
+ CFRelease(cert_handle);
+}
+
+void X509Certificate::Initialize() {
+ crypto::EnsureOpenSSLInit();
+ fingerprint_ = CalculateFingerprint(cert_handle_);
+ ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_);
+ ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_);
+ if (!x509_cert)
+ return;
+ ASN1_INTEGER* serial_num = X509_get_serialNumber(x509_cert.get());
+ if (serial_num) {
+ // ASN1_INTEGERS represent the decoded number, in a format internal to
+ // OpenSSL. Most notably, this may have leading zeroes stripped off for
+ // numbers whose first byte is >= 0x80. Thus, it is necessary to
+ // re-encoded the integer back into DER, which is what the interface
+ // of X509Certificate exposes, to ensure callers get the proper (DER)
+ // value.
+ int bytes_required = i2c_ASN1_INTEGER(serial_num, nullptr);
+ unsigned char* buffer = reinterpret_cast<unsigned char*>(
+ base::WriteInto(&serial_number_, bytes_required + 1));
+ int bytes_written = i2c_ASN1_INTEGER(serial_num, &buffer);
+ DCHECK_EQ(static_cast<size_t>(bytes_written), serial_number_.size());
+ }
+
+ ParsePrincipal(cert_handle_, X509_get_subject_name(x509_cert.get()),
+ &subject_);
+ ParsePrincipal(cert_handle_, X509_get_issuer_name(x509_cert.get()), &issuer_);
+ x509_util::ParseDate(X509_get_notBefore(x509_cert.get()), &valid_start_);
+ x509_util::ParseDate(X509_get_notAfter(x509_cert.get()), &valid_expiry_);
+}
+
+// static
+SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) {
+ SHA1HashValue sha1;
+ memset(sha1.data, 0, sizeof(sha1.data));
+
+ ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert));
+ if (!cert_data)
+ return sha1;
+ DCHECK(CFDataGetBytePtr(cert_data));
+ DCHECK_NE(0, CFDataGetLength(cert_data));
+ CC_SHA1(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), sha1.data);
+
+ return sha1;
+}
+
+// static
+SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
+ SHA256HashValue sha256;
+ memset(sha256.data, 0, sizeof(sha256.data));
+
+ ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert));
+ if (!cert_data)
+ return sha256;
+ DCHECK(CFDataGetBytePtr(cert_data));
+ DCHECK_NE(0, CFDataGetLength(cert_data));
+ CC_SHA256(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data),
+ sha256.data);
+
+ return sha256;
+}
+
+// static
+SHA1HashValue X509Certificate::CalculateCAFingerprint(
+ const OSCertHandles& intermediates) {
+ SHA1HashValue sha1;
+ memset(sha1.data, 0, sizeof(sha1.data));
+
+ CC_SHA1_CTX sha1_ctx;
+ CC_SHA1_Init(&sha1_ctx);
+ for (size_t i = 0; i < intermediates.size(); ++i) {
+ ScopedCFTypeRef<CFDataRef> cert_data(
+ SecCertificateCopyData(intermediates[i]));
+ if (!cert_data)
+ return sha1;
+ CC_SHA1_Update(&sha1_ctx, CFDataGetBytePtr(cert_data),
+ CFDataGetLength(cert_data));
+ }
+ CC_SHA1_Final(sha1.data, &sha1_ctx);
+ return sha1;
+}
+
+// static
+X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
+ const char* data,
+ size_t length) {
+ ScopedCFTypeRef<CFDataRef> cert_data(CFDataCreateWithBytesNoCopy(
+ kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data),
+ base::checked_cast<CFIndex>(length), kCFAllocatorNull));
+ if (!cert_data)
+ return nullptr;
+ OSCertHandle cert_handle = SecCertificateCreateWithData(nullptr, cert_data);
+ if (!cert_handle)
+ return nullptr;
+ if (!IsValidOSCertHandle(cert_handle)) {
+ CFRelease(cert_handle);
+ return nullptr;
+ }
+ return cert_handle;
+}
+
+// static
+X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
+ const char* data,
+ size_t length,
+ Format format) {
+ OSCertHandles results;
+
+ switch (format) {
+ case FORMAT_SINGLE_CERTIFICATE: {
+ OSCertHandle handle =
+ X509Certificate::CreateOSCertHandleFromBytes(data, length);
+ if (handle)
+ results.push_back(handle);
+ break;
+ }
+ case FORMAT_PKCS7: {
+ CreateOSCertHandlesFromPKCS7Bytes(data, length, &results);
+ break;
+ }
+ default: {
+ NOTREACHED() << "Certificate format " << format << " unimplemented";
+ break;
+ }
+ }
+
+ return results;
+}
+
+void X509Certificate::GetSubjectAltName(
+ std::vector<std::string>* dns_names,
+ std::vector<std::string>* ip_addrs) const {
+ if (dns_names)
+ dns_names->clear();
+ if (ip_addrs)
+ ip_addrs->clear();
+
+ ParseSubjectAltName(cert_handle_, dns_names, ip_addrs);
+}
+
+// static
+bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle,
+ std::string* encoded) {
+ base::StringPiece der;
+ if (!cert_handle)
+ return false;
+ ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle));
+ if (!der_data)
+ return false;
+ encoded->assign(reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)),
+ CFDataGetLength(der_data));
+ return true;
+}
+
+// static
+bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
+ X509Certificate::OSCertHandle b) {
+ DCHECK(a && b);
+ return CFEqual(a, b);
+}
+
+// static
+X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle(
+ base::PickleIterator* pickle_iter) {
+ const char* data;
+ int length;
+ if (!pickle_iter->ReadData(&data, &length))
+ return nullptr;
+
+ return X509Certificate::CreateOSCertHandleFromBytes(data, length);
+}
+
+// static
+bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle,
+ base::Pickle* pickle) {
+ ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle));
+ if (!cert_data)
+ return false;
+
+ return pickle->WriteData(
+ reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)),
+ CFDataGetLength(cert_data));
+}
+
+// static
+void X509Certificate::GetPublicKeyInfo(OSCertHandle os_cert,
+ size_t* size_bits,
+ PublicKeyType* type) {
+ *type = kPublicKeyTypeUnknown;
+ *size_bits = 0;
+ ScopedX509 cert = OSCertHandleToOpenSSL(os_cert);
+ if (!cert)
+ return;
+ crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get()));
+ if (!scoped_key)
+ return;
+
+ EVP_PKEY* key = scoped_key.get();
+
+ switch (key->type) {
+ case EVP_PKEY_RSA:
+ *type = kPublicKeyTypeRSA;
+ break;
+ case EVP_PKEY_DSA:
+ *type = kPublicKeyTypeDSA;
+ break;
+ case EVP_PKEY_EC:
+ *type = kPublicKeyTypeECDSA;
+ break;
+ case EVP_PKEY_DH:
+ *type = kPublicKeyTypeDH;
+ break;
+ }
+ *size_bits = EVP_PKEY_bits(key);
+}
+
+bool X509Certificate::SupportsSSLClientAuth() const {
+ return false;
+}
+
+CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const {
+ CFMutableArrayRef cert_list =
+ CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+ if (!cert_list)
+ return nullptr;
+
+ CFArrayAppendValue(cert_list, os_cert_handle());
+ for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i)
+ CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]);
+
+ return cert_list;
+}
+
+bool X509Certificate::IsIssuedByEncoded(
+ const std::vector<std::string>& valid_issuers) {
+ if (valid_issuers.empty())
+ return false;
+
+ // Convert to a temporary list of X509_NAME objects.
+ // It will own the objects it points to.
+ crypto::ScopedOpenSSL<STACK_OF(X509_NAME), sk_X509_NAME_free_all>
+ issuer_names(sk_X509_NAME_new_null());
+ if (!issuer_names)
+ return false;
+
+ for (std::vector<std::string>::const_iterator it = valid_issuers.begin();
+ it != valid_issuers.end(); ++it) {
+ const unsigned char* p = reinterpret_cast<const unsigned char*>(it->data());
+ long len = static_cast<long>(it->length());
+ X509_NAME* ca_name = d2i_X509_NAME(nullptr, &p, len);
+ if (ca_name == nullptr)
+ return false;
+ sk_X509_NAME_push(issuer_names.get(), ca_name);
+ }
+
+ ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_);
+ if (!x509_cert)
+ return false;
+ X509_NAME* cert_issuer = X509_get_issuer_name(x509_cert.get());
+ if (cert_issuer == nullptr)
+ return false;
+
+ for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) {
+ X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m);
+ if (X509_NAME_cmp(issuer, cert_issuer) == 0) {
+ return true;
+ }
+ }
+
+ for (OSCertHandles::iterator it = intermediate_ca_certs_.begin();
+ it != intermediate_ca_certs_.end(); ++it) {
+ ScopedX509 intermediate_cert = OSCertHandleToOpenSSL(*it);
+ if (!intermediate_cert)
+ return false;
+ cert_issuer = X509_get_issuer_name(intermediate_cert.get());
+ if (cert_issuer == nullptr)
+ return false;
+
+ for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) {
+ X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m);
+ if (X509_NAME_cmp(issuer, cert_issuer) == 0) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// static
+bool X509Certificate::IsSelfSigned(OSCertHandle os_cert) {
+ ScopedX509 cert = OSCertHandleToOpenSSL(os_cert);
+ if (!cert)
+ return false;
+ crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get()));
+ if (!scoped_key)
+ return false;
+
+ // NOTE: X509_verify() returns 1 in case of success, 0 or -1 on error.
+ return X509_verify(cert.get(), scoped_key.get()) == 1;
+}
+
+} // namespace net
diff --git a/chromium/net/cert/x509_certificate_unittest.cc b/chromium/net/cert/x509_certificate_unittest.cc
index 362f7ff0991..0c543078ea4 100644
--- a/chromium/net/cert/x509_certificate_unittest.cc
+++ b/chromium/net/cert/x509_certificate_unittest.cc
@@ -17,6 +17,7 @@
#include "net/base/net_errors.h"
#include "net/base/test_data_directory.h"
#include "net/cert/asn1_util.h"
+#include "net/cert/x509_util_nss.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_certificate_data.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -507,6 +508,29 @@ TEST(X509CertificateTest, ParseSubjectAltNames) {
EXPECT_EQ("127.0.0.1", san_cert->subject().common_name);
}
+#if defined(USE_NSS_CERTS)
+TEST(X509CertificateTest, ParseClientSubjectAltNames) {
+ base::FilePath certs_dir = GetTestCertsDirectory();
+
+ // This cert contains one rfc822Name field, and one Microsoft UPN
+ // otherName field.
+ scoped_refptr<X509Certificate> san_cert =
+ ImportCertFromFile(certs_dir, "client_3.pem");
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), san_cert.get());
+
+ std::vector<std::string> rfc822_names;
+ net::x509_util::GetRFC822SubjectAltNames(san_cert->os_cert_handle(),
+ &rfc822_names);
+ ASSERT_EQ(1U, rfc822_names.size());
+ EXPECT_EQ("santest@example.com", rfc822_names[0]);
+
+ std::vector<std::string> upn_names;
+ net::x509_util::GetUPNSubjectAltNames(san_cert->os_cert_handle(), &upn_names);
+ ASSERT_EQ(1U, upn_names.size());
+ EXPECT_EQ("santest@ad.corp.example.com", upn_names[0]);
+}
+#endif // defined(USE_NSS_CERTS)
+
TEST(X509CertificateTest, ExtractSPKIFromDERCert) {
base::FilePath certs_dir = GetTestCertsDirectory();
scoped_refptr<X509Certificate> cert =
diff --git a/chromium/net/cert/x509_certificate_win.cc b/chromium/net/cert/x509_certificate_win.cc
index d2077821b8c..4c4addaf7a4 100644
--- a/chromium/net/cert/x509_certificate_win.cc
+++ b/chromium/net/cert/x509_certificate_win.cc
@@ -5,6 +5,7 @@
#include "net/cert/x509_certificate.h"
#include "base/logging.h"
+#include "base/memory/free_deleter.h"
#include "base/memory/scoped_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/pickle.h"
@@ -23,8 +24,6 @@
#include <blapi.h>
#endif
-#pragma comment(lib, "crypt32.lib")
-
using base::Time;
namespace net {
diff --git a/chromium/net/cert/x509_util.cc b/chromium/net/cert/x509_util.cc
index bbdc194a9aa..b0e343acd91 100644
--- a/chromium/net/cert/x509_util.cc
+++ b/chromium/net/cert/x509_util.cc
@@ -8,6 +8,9 @@
#include "base/time/time.h"
#include "crypto/ec_private_key.h"
#include "crypto/rsa_private_key.h"
+#include "net/base/hash_value.h"
+#include "net/cert/internal/parse_certificate.h"
+#include "net/cert/internal/signature_algorithm.h"
#include "net/cert/x509_certificate.h"
namespace net {
diff --git a/chromium/net/cert/x509_util.h b/chromium/net/cert/x509_util.h
index fb8c20f080d..bd254563717 100644
--- a/chromium/net/cert/x509_util.h
+++ b/chromium/net/cert/x509_util.h
@@ -31,6 +31,12 @@ enum DigestAlgorithm {
DIGEST_SHA256
};
+// Generate a 'tls-server-end-point' channel binding based on the specified
+// certificate. Channel bindings are based on RFC 5929.
+NET_EXPORT_PRIVATE bool GetTLSServerEndPointChannelBinding(
+ const X509Certificate& certificate,
+ std::string* token);
+
// Creates a public-private keypair and a self-signed certificate.
// Subject, serial number and validity period are given as parameters.
// The certificate is signed by the private key in |key|. The key length and
diff --git a/chromium/net/cert/x509_util_ios.cc b/chromium/net/cert/x509_util_ios.cc
index 736c26e0438..0c644a8a25a 100644
--- a/chromium/net/cert/x509_util_ios.cc
+++ b/chromium/net/cert/x509_util_ios.cc
@@ -10,6 +10,7 @@
#include <prtypes.h>
#include "base/mac/scoped_cftyperef.h"
+#include "base/memory/ref_counted.h"
#include "crypto/nss_util.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util_nss.h"
@@ -60,13 +61,13 @@ SecCertificateRef CreateOSCertHandleFromNSSHandle(
nss_cert_handle->derCert.len);
}
-X509Certificate* CreateCertFromNSSHandles(
+scoped_refptr<X509Certificate> CreateCertFromNSSHandles(
CERTCertificate* cert_handle,
const std::vector<CERTCertificate*>& intermediates) {
ScopedCFTypeRef<SecCertificateRef> os_server_cert(
CreateOSCertHandleFromNSSHandle(cert_handle));
if (!os_server_cert)
- return NULL;
+ return nullptr;
std::vector<SecCertificateRef> os_intermediates;
for (size_t i = 0; i < intermediates.size(); ++i) {
SecCertificateRef intermediate =
@@ -76,7 +77,7 @@ X509Certificate* CreateCertFromNSSHandles(
os_intermediates.push_back(intermediate);
}
- X509Certificate* cert = NULL;
+ scoped_refptr<X509Certificate> cert = nullptr;
if (intermediates.size() == os_intermediates.size()) {
cert = X509Certificate::CreateFromHandle(os_server_cert,
os_intermediates);
@@ -100,7 +101,7 @@ SHA1HashValue CalculateFingerprintNSS(CERTCertificate* cert) {
NSSCertificate::NSSCertificate(SecCertificateRef cert_handle) {
nss_cert_handle_ = CreateNSSCertHandleFromOSHandle(cert_handle);
- DLOG_IF(INFO, cert_handle && !nss_cert_handle_)
+ DLOG_IF(ERROR, cert_handle && !nss_cert_handle_)
<< "Could not convert SecCertificateRef to CERTCertificate*";
}
diff --git a/chromium/net/cert/x509_util_ios.h b/chromium/net/cert/x509_util_ios.h
index 5a8a57601ca..eb937552900 100644
--- a/chromium/net/cert/x509_util_ios.h
+++ b/chromium/net/cert/x509_util_ios.h
@@ -11,6 +11,7 @@
#include <Security/Security.h>
#include <vector>
+#include "base/memory/ref_counted.h"
#include "net/cert/x509_cert_types.h"
// Forward declaration; real one in <cert.h>
@@ -35,7 +36,7 @@ SecCertificateRef CreateOSCertHandleFromNSSHandle(
// intermediates. This is functionally equivalent to
// X509Certificate::CreateFromHandle(), except it supports receiving
// NSS CERTCertificate*s rather than iOS SecCertificateRefs.
-X509Certificate* CreateCertFromNSSHandles(
+scoped_refptr<X509Certificate> CreateCertFromNSSHandles(
CERTCertificate* cert_handle,
const std::vector<CERTCertificate*>& intermediates);
diff --git a/chromium/net/cert/x509_util_mac.cc b/chromium/net/cert/x509_util_mac.cc
index 3959b80eb48..7971a733af0 100644
--- a/chromium/net/cert/x509_util_mac.cc
+++ b/chromium/net/cert/x509_util_mac.cc
@@ -9,6 +9,11 @@
namespace net {
+// 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"
+
namespace x509_util {
namespace {
@@ -228,4 +233,6 @@ OSStatus CSSMCachedCertificate::GetField(const CSSM_OID* field_oid,
} // namespace x509_util
+#pragma clang diagnostic pop // "-Wdeprecated-declarations"
+
} // namespace net
diff --git a/chromium/net/cert/x509_util_mac.h b/chromium/net/cert/x509_util_mac.h
index a35266b2724..08c158921d4 100644
--- a/chromium/net/cert/x509_util_mac.h
+++ b/chromium/net/cert/x509_util_mac.h
@@ -57,6 +57,11 @@ OSStatus NET_EXPORT CreateRevocationPolicies(bool enable_revocation_checking,
bool enable_ev_checking,
CFMutableArrayRef policies);
+// 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"
+
// Wrapper for a CSSM_DATA_PTR that was obtained via one of the CSSM field
// accessors (such as CSSM_CL_CertGet[First/Next]Value or
// CSSM_CL_CertGet[First/Next]CachedValue).
@@ -132,6 +137,8 @@ class CSSMCachedCertificate {
CSSM_HANDLE cached_cert_handle_;
};
+#pragma clang diagnostic pop // "-Wdeprecated-declarations"
+
} // namespace x509_util
} // namespace net
diff --git a/chromium/net/cert/x509_util_nss.cc b/chromium/net/cert/x509_util_nss.cc
index 2dbff2c76fc..db6a97ae2ae 100644
--- a/chromium/net/cert/x509_util_nss.cc
+++ b/chromium/net/cert/x509_util_nss.cc
@@ -180,6 +180,12 @@ bool CreateSelfSignedCert(crypto::RSAPrivateKey* key,
return true;
}
+bool GetTLSServerEndPointChannelBinding(const X509Certificate& certificate,
+ std::string* token) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
} // namespace x509_util
} // namespace net
diff --git a/chromium/net/cert/x509_util_nss.h b/chromium/net/cert/x509_util_nss.h
index 55e562effba..c656264169e 100644
--- a/chromium/net/cert/x509_util_nss.h
+++ b/chromium/net/cert/x509_util_nss.h
@@ -28,7 +28,7 @@ namespace net {
namespace x509_util {
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
// Parses the Principal attribute from |name| and outputs the result in
// |principal|.
void ParsePrincipal(CERTName* name,
@@ -40,11 +40,44 @@ void ParseDate(const SECItem* der_date, base::Time* result);
// Parses the serial number from |certificate|.
std::string ParseSerialNumber(const CERTCertificate* certificate);
-// Gets the subjectAltName extension field from the certificate, if any.
+// Gets the dNSName and iPAddress name types from the subjectAltName
+// extension of |cert_handle|, storing them in |dns_names| and
+// |ip_addrs|, respectively.
+// If no subjectAltName is present, or no names of that type are
+// present, the relevant vectors are cleared.
void GetSubjectAltName(CERTCertificate* cert_handle,
std::vector<std::string>* dns_names,
std::vector<std::string>* ip_addrs);
+// Stores the values of all rfc822Name subjectAltNames from |cert_handle|
+// into |names|. If no names are present, clears |names|.
+// WARNING: This method does not validate that the rfc822Name is
+// properly encoded; it MAY contain embedded NULs or other illegal
+// characters; care should be taken to validate the well-formedness
+// before using.
+NET_EXPORT void GetRFC822SubjectAltNames(CERTCertificate* cert_handle,
+ std::vector<std::string>* names);
+
+// Stores the values of all Microsoft UPN subjectAltNames from |cert_handle|
+// into |names|. If no names are present, clears |names|.
+//
+// A "Microsoft UPN subjectAltName" is an OtherName value whose type-id
+// is equal to 1.3.6.1.4.1.311.20.2.3 (known as either id-ms-san-sc-logon-upn,
+// as described in RFC 4556, or as szOID_NT_PRINCIPAL_NAME, as
+// documented in Microsoft KB287547).
+// The value field is a UTF8String literal.
+// For more information:
+// https://www.ietf.org/mail-archive/web/pkix/current/msg03145.html
+// https://www.ietf.org/proceedings/65/slides/pkix-4/sld1.htm
+// https://tools.ietf.org/html/rfc4556
+//
+// WARNING: This method does not validate that the name is
+// properly encoded; it MAY contain embedded NULs or other illegal
+// characters; care should be taken to validate the well-formedness
+// before using.
+NET_EXPORT void GetUPNSubjectAltNames(CERTCertificate* cert_handle,
+ std::vector<std::string>* names);
+
// Creates all possible OS certificate handles from |data| encoded in a specific
// |format|. Returns an empty collection on failure.
X509Certificate::OSCertHandles CreateOSCertHandlesFromBytes(
@@ -94,7 +127,7 @@ bool IsCertificateIssuedBy(const std::vector<CERTCertificate*>& cert_chain,
std::string GetUniqueNicknameForSlot(const std::string& nickname,
const SECItem* subject,
PK11SlotInfo* slot);
-#endif // defined(USE_NSS_CERTS) || defined(OS_IOS)
+#endif // defined(USE_NSS_VERIFIER)
} // namespace x509_util
diff --git a/chromium/net/cert/x509_util_nss_certs.cc b/chromium/net/cert/x509_util_nss_certs.cc
index 1ec360d31e6..b0058895def 100644
--- a/chromium/net/cert/x509_util_nss_certs.cc
+++ b/chromium/net/cert/x509_util_nss_certs.cc
@@ -33,6 +33,10 @@ namespace net {
namespace {
+// Microsoft User Principal Name: 1.3.6.1.4.1.311.20.2.3
+const uint8_t kUpnOid[] = {0x2b, 0x6, 0x1, 0x4, 0x1,
+ 0x82, 0x37, 0x14, 0x2, 0x3};
+
// Callback for CERT_DecodeCertPackage(), used in
// CreateOSCertHandlesFromBytes().
SECStatus PR_CALLBACK
@@ -200,6 +204,74 @@ void GetSubjectAltName(CERTCertificate* cert_handle,
PORT_FreeArena(arena, PR_FALSE);
}
+void GetRFC822SubjectAltNames(CERTCertificate* cert_handle,
+ std::vector<std::string>* names) {
+ crypto::ScopedSECItem alt_name(SECITEM_AllocItem(NULL, NULL, 0));
+ DCHECK(alt_name.get());
+
+ names->clear();
+ SECStatus rv = CERT_FindCertExtension(
+ cert_handle, SEC_OID_X509_SUBJECT_ALT_NAME, alt_name.get());
+ if (rv != SECSuccess)
+ return;
+
+ crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+ DCHECK(arena.get());
+
+ CERTGeneralName* alt_name_list;
+ alt_name_list = CERT_DecodeAltNameExtension(arena.get(), alt_name.get());
+
+ CERTGeneralName* name = alt_name_list;
+ while (name) {
+ if (name->type == certRFC822Name) {
+ names->push_back(
+ std::string(reinterpret_cast<char*>(name->name.other.data),
+ name->name.other.len));
+ }
+ name = CERT_GetNextGeneralName(name);
+ if (name == alt_name_list)
+ break;
+ }
+}
+
+void GetUPNSubjectAltNames(CERTCertificate* cert_handle,
+ std::vector<std::string>* names) {
+ crypto::ScopedSECItem alt_name(SECITEM_AllocItem(NULL, NULL, 0));
+ DCHECK(alt_name.get());
+
+ names->clear();
+ SECStatus rv = CERT_FindCertExtension(
+ cert_handle, SEC_OID_X509_SUBJECT_ALT_NAME, alt_name.get());
+ if (rv != SECSuccess)
+ return;
+
+ crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+ DCHECK(arena.get());
+
+ CERTGeneralName* alt_name_list;
+ alt_name_list = CERT_DecodeAltNameExtension(arena.get(), alt_name.get());
+
+ CERTGeneralName* name = alt_name_list;
+ while (name) {
+ if (name->type == certOtherName) {
+ OtherName* on = &name->name.OthName;
+ if (on->oid.len == sizeof(kUpnOid) &&
+ memcmp(on->oid.data, kUpnOid, sizeof(kUpnOid)) == 0) {
+ SECItem decoded;
+ if (SEC_QuickDERDecodeItem(arena.get(), &decoded,
+ SEC_ASN1_GET(SEC_UTF8StringTemplate),
+ &name->name.OthName.name) == SECSuccess) {
+ names->push_back(
+ std::string(reinterpret_cast<char*>(decoded.data), decoded.len));
+ }
+ }
+ }
+ name = CERT_GetNextGeneralName(name);
+ if (name == alt_name_list)
+ break;
+ }
+}
+
X509Certificate::OSCertHandles CreateOSCertHandlesFromBytes(
const char* data,
size_t length,
diff --git a/chromium/net/cert/x509_util_openssl.cc b/chromium/net/cert/x509_util_openssl.cc
index c81a3a49b39..2e8ef2e6c7a 100644
--- a/chromium/net/cert/x509_util_openssl.cc
+++ b/chromium/net/cert/x509_util_openssl.cc
@@ -6,6 +6,7 @@
#include <limits.h>
#include <openssl/asn1.h>
+#include <openssl/digest.h>
#include <openssl/mem.h>
#include <algorithm>
@@ -19,7 +20,10 @@
#include "crypto/openssl_util.h"
#include "crypto/rsa_private_key.h"
#include "crypto/scoped_openssl_types.h"
+#include "net/cert/internal/parse_certificate.h"
+#include "net/cert/internal/signature_algorithm.h"
#include "net/cert/x509_cert_types.h"
+#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
#include "net/ssl/scoped_openssl_types.h"
@@ -35,7 +39,6 @@ using ScopedASN1_STRING = crypto::ScopedOpenSSL<ASN1_STRING, ASN1_STRING_free>;
using ScopedASN1_TIME = crypto::ScopedOpenSSL<ASN1_TIME, ASN1_TIME_free>;
using ScopedX509_EXTENSION =
crypto::ScopedOpenSSL<X509_EXTENSION, X509_EXTENSION_free>;
-using ScopedX509_NAME = crypto::ScopedOpenSSL<X509_NAME, X509_NAME_free>;
const EVP_MD* ToEVP(x509_util::DigestAlgorithm alg) {
switch (alg) {
@@ -304,6 +307,57 @@ bool GetDER(X509* x509, base::StringPiece* der_cache) {
return true;
}
+bool GetTLSServerEndPointChannelBinding(const X509Certificate& certificate,
+ std::string* token) {
+ static const char kChannelBindingPrefix[] = "tls-server-end-point:";
+
+ std::string der_encoded_certificate;
+ if (!X509Certificate::GetDEREncoded(certificate.os_cert_handle(),
+ &der_encoded_certificate))
+ return false;
+
+ ParsedCertificate parsed_certificate;
+ if (!ParseCertificate(der::Input(base::StringPiece(der_encoded_certificate)),
+ &parsed_certificate))
+ return false;
+
+ scoped_ptr<SignatureAlgorithm> signature_algorithm =
+ SignatureAlgorithm::CreateFromDer(
+ parsed_certificate.signature_algorithm_tlv);
+ if (!signature_algorithm)
+ return false;
+
+ const EVP_MD* digest_evp_md = nullptr;
+ switch (signature_algorithm->digest()) {
+ case net::DigestAlgorithm::Sha1:
+ case net::DigestAlgorithm::Sha256:
+ digest_evp_md = EVP_sha256();
+ break;
+
+ case net::DigestAlgorithm::Sha384:
+ digest_evp_md = EVP_sha384();
+ break;
+
+ case net::DigestAlgorithm::Sha512:
+ digest_evp_md = EVP_sha512();
+ break;
+ }
+ if (!digest_evp_md)
+ return false;
+
+ std::vector<uint8_t> digest(EVP_MAX_MD_SIZE);
+ unsigned int out_size = digest.size();
+ if (!EVP_Digest(der_encoded_certificate.data(),
+ der_encoded_certificate.size(), digest.data(), &out_size,
+ digest_evp_md, nullptr))
+ return false;
+
+ digest.resize(out_size);
+ token->assign(kChannelBindingPrefix);
+ token->append(digest.begin(), digest.end());
+ return true;
+}
+
} // namespace x509_util
} // namespace net
diff --git a/chromium/net/cert/x509_util_unittest.cc b/chromium/net/cert/x509_util_unittest.cc
index abce23a869c..6fabe000cfa 100644
--- a/chromium/net/cert/x509_util_unittest.cc
+++ b/chromium/net/cert/x509_util_unittest.cc
@@ -188,6 +188,518 @@ TEST(X509UtilTest, CreateSelfSigned) {
EXPECT_FALSE(cert->HasExpired());
}
+#if defined(USE_OPENSSL)
+// This is a test case based on
+// http://blogs.msdn.com/b/openspecification/archive/2013/03/26/ntlm-and-channel-binding-hash-aka-exteneded-protection-for-authentication.aspx
+// There doesn't seem to be too many public test vectors for channel bindings.
+TEST(X509UtilTest, CreateChannelBindings_SHA1) {
+ // Certificate:
+ // Data:
+ // Version: 3 (0x2)
+ // Serial Number:
+ // (Negative)34:96:86:32:ae:8a:3a:48:b4:98:cf:7c:93:87:bb:d9
+ // Signature Algorithm: sha1WithRSA
+ // ...
+ const uint8_t kCertificateDataDER[] = {
+ 0x30, 0x82, 0x02, 0x09, 0x30, 0x82, 0x01, 0x76, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x10, 0xcb, 0x69, 0x79, 0xcd, 0x51, 0x75, 0xc5, 0xb7, 0x4b,
+ 0x67, 0x30, 0x83, 0x6c, 0x78, 0x44, 0x27, 0x30, 0x09, 0x06, 0x05, 0x2b,
+ 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0b, 0x44, 0x43, 0x2d, 0x57, 0x53,
+ 0x32, 0x30, 0x30, 0x38, 0x52, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32,
+ 0x31, 0x31, 0x31, 0x37, 0x30, 0x30, 0x35, 0x39, 0x32, 0x31, 0x5a, 0x17,
+ 0x0d, 0x33, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35,
+ 0x39, 0x5a, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x0b, 0x44, 0x43, 0x2d, 0x57, 0x53, 0x32, 0x30, 0x30, 0x38,
+ 0x52, 0x32, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
+ 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0x9b, 0x00, 0xf8, 0x1a, 0x2d,
+ 0x37, 0xc6, 0x8d, 0xa1, 0x39, 0x91, 0x46, 0xf3, 0x6a, 0x1b, 0xf9, 0x60,
+ 0x6c, 0xb3, 0x6c, 0xa0, 0xac, 0xed, 0x85, 0xe0, 0x3f, 0xdc, 0x92, 0x86,
+ 0x36, 0xbd, 0x64, 0xbf, 0x36, 0x51, 0xdb, 0x57, 0x3a, 0x8a, 0x82, 0x6b,
+ 0xd8, 0x94, 0x17, 0x7b, 0xd3, 0x91, 0x11, 0x98, 0xef, 0x19, 0x06, 0x52,
+ 0x30, 0x03, 0x73, 0x67, 0xc8, 0xed, 0x8e, 0xfa, 0x0b, 0x3d, 0x4c, 0xc9,
+ 0x10, 0x63, 0x9f, 0xcf, 0xb4, 0xcf, 0x39, 0xd8, 0xfe, 0x99, 0xeb, 0x5b,
+ 0x11, 0xf2, 0xfc, 0xfa, 0x86, 0x24, 0xd9, 0xff, 0xd9, 0x19, 0xf5, 0x69,
+ 0xb4, 0xdf, 0x5a, 0x5a, 0xc4, 0x94, 0xb4, 0xb0, 0x07, 0x25, 0x97, 0x13,
+ 0xad, 0x7e, 0x38, 0x14, 0xfb, 0xd6, 0x33, 0x65, 0x6f, 0xe6, 0xf7, 0x48,
+ 0x4b, 0x2d, 0xb3, 0x51, 0x2e, 0x6d, 0xc7, 0xea, 0x11, 0x76, 0x9a, 0x2b,
+ 0xf0, 0x00, 0x4d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x60, 0x30, 0x5e,
+ 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06,
+ 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x47, 0x06,
+ 0x03, 0x55, 0x1d, 0x01, 0x04, 0x40, 0x30, 0x3e, 0x80, 0x10, 0xeb, 0x65,
+ 0x26, 0x03, 0x95, 0x4b, 0xd6, 0xc0, 0x54, 0x75, 0x78, 0x7c, 0xb6, 0x2a,
+ 0xa1, 0xbb, 0xa1, 0x18, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x13, 0x0b, 0x44, 0x43, 0x2d, 0x57, 0x53, 0x32, 0x30,
+ 0x30, 0x38, 0x52, 0x32, 0x82, 0x10, 0xcb, 0x69, 0x79, 0xcd, 0x51, 0x75,
+ 0xc5, 0xb7, 0x4b, 0x67, 0x30, 0x83, 0x6c, 0x78, 0x44, 0x27, 0x30, 0x09,
+ 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x03, 0x81, 0x81,
+ 0x00, 0x7b, 0xfa, 0xfe, 0xee, 0x74, 0x05, 0xac, 0xbb, 0x79, 0xe9, 0xda,
+ 0xca, 0x00, 0x44, 0x96, 0x94, 0x71, 0x92, 0xb1, 0xdb, 0xc9, 0x9b, 0x71,
+ 0x29, 0xc0, 0xe4, 0x28, 0x5e, 0x6a, 0x50, 0x99, 0xcd, 0xa8, 0x17, 0xe4,
+ 0x56, 0xb9, 0xef, 0x7f, 0x02, 0x7d, 0x96, 0xa3, 0x48, 0x14, 0x72, 0x75,
+ 0x2f, 0xb0, 0xb5, 0x87, 0xee, 0x55, 0xe9, 0x6a, 0x6d, 0x28, 0x3c, 0xc1,
+ 0xfd, 0x00, 0xe4, 0x76, 0xe3, 0x80, 0x88, 0x78, 0x26, 0x0d, 0x6c, 0x8c,
+ 0xb8, 0x64, 0x61, 0x63, 0xb7, 0x13, 0x3a, 0xab, 0xc7, 0xdd, 0x1d, 0x0a,
+ 0xd7, 0x15, 0x45, 0xa1, 0xd6, 0xd9, 0x34, 0xc7, 0x21, 0x48, 0xfb, 0x43,
+ 0x87, 0x38, 0xda, 0x1f, 0x50, 0x47, 0xb1, 0xa5, 0x5c, 0x47, 0xed, 0x04,
+ 0x44, 0x97, 0xd3, 0xac, 0x74, 0x2d, 0xeb, 0x09, 0x77, 0x59, 0xbf, 0xa3,
+ 0x54, 0x5b, 0xde, 0x42, 0xd5, 0x23, 0x5a, 0x71, 0x9f};
+
+ const unsigned char kExpectedServerEndPointToken[] = {
+ 0x74, 0x6c, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2d,
+ 0x65, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x3a, 0xea,
+ 0x05, 0xfe, 0xfe, 0xcc, 0x6b, 0x0b, 0xd5, 0x71, 0xdb, 0xbc, 0x5b,
+ 0xaa, 0x3e, 0xd4, 0x53, 0x86, 0xd0, 0x44, 0x68, 0x35, 0xf7, 0xb7,
+ 0x4c, 0x85, 0x62, 0x1b, 0x99, 0x83, 0x47, 0x5f, 0x95,
+ };
+
+ scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(kCertificateDataDER),
+ sizeof(kCertificateDataDER));
+
+ std::string channel_bindings;
+ ASSERT_TRUE(
+ x509_util::GetTLSServerEndPointChannelBinding(*cert, &channel_bindings));
+
+ std::string expected_channel_bindings(
+ std::begin(kExpectedServerEndPointToken),
+ std::end(kExpectedServerEndPointToken));
+ EXPECT_EQ(expected_channel_bindings, channel_bindings);
+}
+
+TEST(X509UtilTest, CreateChannelBindings_SHA256) {
+ // Certificate:
+ // Data:
+ // Version: 3 (0x2)
+ // Serial Number: 14673274151129443507 (0xcba1f1191dfdecb3)
+ // Signature Algorithm: sha256WithRSAEncryption
+ // ...
+ const uint8_t kCertificateDataDER[] = {
+ 0x30, 0x82, 0x03, 0x8f, 0x30, 0x82, 0x02, 0x77, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0xcb, 0xa1, 0xf1, 0x19, 0x1d, 0xfd, 0xec, 0xb3,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x0b, 0x05, 0x00, 0x30, 0x5e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06,
+ 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x0b, 0x4d, 0x6d, 0x6d, 0x6b, 0x61, 0x79, 0x20, 0x49, 0x6e, 0x63,
+ 0x2e, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f,
+ 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31,
+ 0x37, 0x31, 0x39, 0x33, 0x39, 0x34, 0x34, 0x5a, 0x17, 0x0d, 0x31, 0x36,
+ 0x30, 0x34, 0x31, 0x36, 0x31, 0x39, 0x33, 0x39, 0x34, 0x34, 0x5a, 0x30,
+ 0x5e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
+ 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07,
+ 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31,
+ 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x4d, 0x6d,
+ 0x6d, 0x6b, 0x61, 0x79, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e,
+ 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30,
+ 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
+ 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc6, 0x31, 0xfe, 0x13,
+ 0x0a, 0xb2, 0x87, 0xc0, 0xb9, 0xa4, 0xb9, 0x86, 0x98, 0x92, 0xc1, 0x48,
+ 0x41, 0x89, 0xd9, 0xe6, 0xe9, 0x36, 0x1a, 0xd6, 0x1c, 0xcb, 0x86, 0x3a,
+ 0xec, 0x34, 0x3a, 0xbf, 0x2a, 0xe7, 0x91, 0x33, 0xf4, 0x3e, 0xa4, 0x1b,
+ 0x9a, 0xc3, 0xa4, 0x66, 0xa0, 0x6d, 0xbf, 0x75, 0x44, 0x1a, 0x79, 0xda,
+ 0x23, 0x06, 0x5c, 0x07, 0x5c, 0x52, 0x84, 0x46, 0x40, 0xcf, 0x26, 0xa1,
+ 0x65, 0x65, 0x4e, 0x36, 0x1a, 0xd2, 0xc9, 0x40, 0x28, 0x1e, 0x6f, 0x4f,
+ 0x7e, 0xb7, 0x10, 0xcd, 0x55, 0x6c, 0xca, 0xf1, 0xfa, 0x66, 0xfb, 0x3e,
+ 0xb0, 0xf4, 0xc1, 0x92, 0xec, 0xec, 0x0c, 0x1c, 0x79, 0x23, 0x5d, 0xf6,
+ 0xc0, 0xed, 0xb7, 0x39, 0xa7, 0x59, 0x98, 0xa7, 0x9d, 0x9e, 0x3b, 0xe1,
+ 0x77, 0x8b, 0x2d, 0x2b, 0x02, 0x5f, 0x30, 0x46, 0xa9, 0x78, 0x47, 0x6f,
+ 0x05, 0x7d, 0xbc, 0x84, 0x37, 0x09, 0x40, 0x20, 0xba, 0x16, 0x96, 0x4c,
+ 0xfd, 0xea, 0x83, 0x3e, 0x50, 0xda, 0x24, 0xf4, 0x61, 0x52, 0xfe, 0x9b,
+ 0xd5, 0x71, 0x37, 0x18, 0x11, 0xe0, 0x7c, 0xbe, 0x98, 0x95, 0x6c, 0x61,
+ 0xab, 0x9b, 0xdc, 0x5c, 0x59, 0x7d, 0x85, 0x0c, 0xc5, 0x32, 0x07, 0x65,
+ 0x1e, 0x6a, 0x15, 0xe6, 0xbd, 0xc6, 0xbd, 0xd5, 0x91, 0xea, 0x9d, 0x2f,
+ 0x0f, 0xdf, 0xef, 0xff, 0x1e, 0x2d, 0x50, 0x44, 0xca, 0x38, 0x27, 0xe3,
+ 0x20, 0x79, 0x44, 0x47, 0x7a, 0xe3, 0xea, 0x7a, 0x70, 0x41, 0x26, 0x87,
+ 0xe0, 0x1a, 0x49, 0x1d, 0x62, 0x34, 0xe5, 0xde, 0xc3, 0xb3, 0x12, 0xb8,
+ 0xa2, 0xf9, 0xad, 0x1b, 0x6a, 0x0f, 0x04, 0xa8, 0xfb, 0xca, 0xe4, 0x01,
+ 0x6d, 0x77, 0x1f, 0x72, 0xff, 0x58, 0x49, 0x05, 0x1c, 0x1a, 0xb7, 0x76,
+ 0x29, 0x77, 0x93, 0xcc, 0x09, 0xe8, 0xb7, 0x03, 0x2f, 0x1b, 0xe2, 0xcd,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb7, 0x64, 0x60, 0xe7,
+ 0x6e, 0xb6, 0xaa, 0x25, 0x46, 0xe2, 0x8e, 0x98, 0xac, 0x81, 0xb0, 0xe7,
+ 0x10, 0x14, 0x85, 0x6d, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x18, 0x30, 0x16, 0x80, 0x14, 0xb7, 0x64, 0x60, 0xe7, 0x6e, 0xb6, 0xaa,
+ 0x25, 0x46, 0xe2, 0x8e, 0x98, 0xac, 0x81, 0xb0, 0xe7, 0x10, 0x14, 0x85,
+ 0x6d, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03,
+ 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x44,
+ 0xc4, 0x46, 0x89, 0x69, 0x21, 0xd0, 0x81, 0x30, 0xe3, 0x38, 0xb8, 0x80,
+ 0xa5, 0x23, 0xd4, 0xfc, 0xe5, 0x12, 0x0f, 0xab, 0x01, 0x44, 0x67, 0xe4,
+ 0x59, 0x86, 0xd0, 0xa1, 0x8c, 0x2b, 0x36, 0xf0, 0x63, 0x51, 0xbe, 0x24,
+ 0xfa, 0xf3, 0x1d, 0xc9, 0xfd, 0x40, 0x99, 0x48, 0xea, 0x95, 0x6e, 0xab,
+ 0xcf, 0xeb, 0x2b, 0x2d, 0x4e, 0xd2, 0xdf, 0xb2, 0xb9, 0x18, 0x27, 0xe3,
+ 0xc9, 0x17, 0xde, 0x25, 0x6c, 0xcc, 0x80, 0x5a, 0xd5, 0x3b, 0xc5, 0xc8,
+ 0x3a, 0xc6, 0xcb, 0xa0, 0x33, 0xd3, 0x80, 0x20, 0x4e, 0x3f, 0x61, 0x67,
+ 0x16, 0x0e, 0xbc, 0xf3, 0x25, 0xe9, 0x62, 0xfa, 0x7f, 0x0e, 0x75, 0x11,
+ 0xcb, 0x68, 0x24, 0x34, 0x96, 0x1d, 0xb2, 0x88, 0xb7, 0xeb, 0x5e, 0x9c,
+ 0xc7, 0xa0, 0x3b, 0xcf, 0x4e, 0x3c, 0x7c, 0x6c, 0x29, 0x1b, 0xa5, 0x74,
+ 0x4d, 0x90, 0xe1, 0xd9, 0x6a, 0x6c, 0x54, 0x6b, 0xce, 0x3d, 0x70, 0x99,
+ 0xf0, 0x11, 0xc3, 0xda, 0xce, 0xe9, 0xba, 0xc4, 0x91, 0x97, 0xe7, 0x44,
+ 0x09, 0xa4, 0x39, 0x36, 0xb5, 0xff, 0x3a, 0xce, 0x5d, 0xf1, 0x0b, 0x03,
+ 0xab, 0xea, 0x0c, 0xe6, 0xbd, 0xd4, 0x43, 0xed, 0x8d, 0x9c, 0xcd, 0x8e,
+ 0x14, 0xf9, 0xa7, 0xc7, 0xdc, 0xe0, 0xd8, 0xe7, 0x37, 0xf5, 0x48, 0xe8,
+ 0x84, 0x4c, 0xcd, 0x70, 0x1b, 0xe5, 0x71, 0xa7, 0x4d, 0xc3, 0x03, 0x5e,
+ 0x50, 0x8a, 0xc4, 0x7c, 0x9c, 0xa4, 0x6f, 0x91, 0xfa, 0x9f, 0xdc, 0xef,
+ 0x2b, 0x42, 0xe7, 0xd0, 0x0d, 0x60, 0x72, 0x71, 0xe7, 0x13, 0xff, 0x43,
+ 0xcb, 0x64, 0x33, 0x37, 0x2e, 0xe9, 0x09, 0xeb, 0x7e, 0x8f, 0x15, 0x99,
+ 0xc9, 0x0d, 0xb0, 0xcb, 0xf0, 0x1f, 0x02, 0xf7, 0xb7, 0x3a, 0xa0, 0x6b,
+ 0x57, 0xb3, 0x33, 0x14, 0xdb, 0x06, 0x7f, 0x98, 0x6f, 0xc4, 0x32, 0xd5,
+ 0x14, 0x83, 0x7a};
+
+ const unsigned char kExpectedServerEndPointToken[] = {
+ 0x74, 0x6c, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2d,
+ 0x65, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x3a, 0x96,
+ 0x4c, 0xd0, 0x44, 0x53, 0x81, 0x0b, 0x35, 0x01, 0x05, 0x54, 0x02,
+ 0x15, 0x79, 0xac, 0x74, 0x3c, 0xa4, 0x91, 0xa2, 0xb7, 0x60, 0xbe,
+ 0x75, 0x57, 0x0e, 0xaf, 0xa3, 0x10, 0xbf, 0xf1, 0xbb,
+ };
+
+ scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(kCertificateDataDER),
+ sizeof(kCertificateDataDER));
+
+ std::string channel_bindings;
+ ASSERT_TRUE(
+ x509_util::GetTLSServerEndPointChannelBinding(*cert, &channel_bindings));
+
+ std::string expected_channel_bindings(
+ std::begin(kExpectedServerEndPointToken),
+ std::end(kExpectedServerEndPointToken));
+ EXPECT_EQ(expected_channel_bindings, channel_bindings);
+}
+
+TEST(X509UtilTest, CreateChannelBindings_SHA384) {
+ // Certificate:
+ // Data:
+ // Version: 3 (0x2)
+ // Serial Number: 10071585730232401378 (0x8bc575dc2f653de2)
+ // Signature Algorithm: sha384WithRSAEncryption
+ // ...
+ const uint8_t kCertificateDataDER[] = {
+ 0x30, 0x82, 0x03, 0xe1, 0x30, 0x82, 0x02, 0xc9, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0x8b, 0xc5, 0x75, 0xdc, 0x2f, 0x65, 0x3d, 0xe2,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x0c, 0x05, 0x00, 0x30, 0x81, 0x86, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, 0x10,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72,
+ 0x69, 0x64, 0x67, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x0c, 0x0b, 0x4d, 0x6d, 0x6d, 0x6b, 0x61, 0x79, 0x20, 0x49, 0x6e,
+ 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
+ 0x1d, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x74,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x47, 0x65, 0x6e, 0x65,
+ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61,
+ 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x36, 0x30, 0x33, 0x31, 0x37, 0x31, 0x39, 0x35, 0x36, 0x34, 0x39,
+ 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x36, 0x31, 0x39, 0x35,
+ 0x36, 0x34, 0x39, 0x5a, 0x30, 0x81, 0x86, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62,
+ 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x0c, 0x0b, 0x4d, 0x6d, 0x6d, 0x6b, 0x61, 0x79, 0x20, 0x49,
+ 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b,
+ 0x0c, 0x1d, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x43, 0x65, 0x72,
+ 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x47, 0x65, 0x6e,
+ 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x18, 0x30, 0x16, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01,
+ 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01,
+ 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb4, 0xfa, 0x6c, 0xe7, 0xac, 0x91,
+ 0xa4, 0x00, 0xe1, 0xe8, 0xed, 0x5b, 0xe5, 0x86, 0x6b, 0x3d, 0x1d, 0x87,
+ 0xf7, 0x49, 0x5a, 0xda, 0x67, 0x65, 0x34, 0x57, 0x7b, 0x70, 0x71, 0x11,
+ 0xbd, 0xee, 0xfe, 0x01, 0x91, 0xb6, 0x43, 0x11, 0x0f, 0xec, 0x3f, 0x2f,
+ 0x05, 0xdb, 0x28, 0x44, 0x7e, 0x9c, 0x2b, 0xbb, 0xe9, 0x49, 0x2b, 0x62,
+ 0x1e, 0x8b, 0x4c, 0xf9, 0xa8, 0x2f, 0xfb, 0x24, 0x83, 0x13, 0xeb, 0x7f,
+ 0x52, 0x4c, 0xbb, 0xc5, 0x89, 0x6c, 0xe4, 0x22, 0xc0, 0x0c, 0x71, 0xda,
+ 0xb2, 0x36, 0xae, 0xc8, 0xe5, 0x10, 0x8f, 0x4a, 0x68, 0x65, 0xc3, 0x07,
+ 0xb5, 0xcf, 0xec, 0x08, 0xd9, 0x4b, 0x13, 0x4a, 0x25, 0x56, 0xec, 0x74,
+ 0x4d, 0xb3, 0xb5, 0x77, 0x3f, 0xf9, 0xa5, 0x0b, 0x15, 0x80, 0xf9, 0xe7,
+ 0x01, 0x4b, 0x73, 0x6a, 0x1e, 0xc8, 0xb0, 0x7a, 0x58, 0x13, 0x25, 0x50,
+ 0x40, 0x7e, 0x5c, 0x5d, 0xff, 0x2b, 0x9d, 0xf5, 0x43, 0xd2, 0xed, 0xca,
+ 0x87, 0xe3, 0x4e, 0x9f, 0x25, 0xa7, 0x75, 0xe9, 0x48, 0x7e, 0xb9, 0x38,
+ 0x74, 0x3f, 0x30, 0x6b, 0xec, 0x94, 0xb8, 0x0f, 0x00, 0x41, 0x60, 0xaa,
+ 0x48, 0x7d, 0x17, 0x65, 0x1a, 0x9a, 0x0d, 0x49, 0x18, 0xe8, 0x72, 0xbb,
+ 0x16, 0x37, 0xa0, 0x65, 0x0c, 0xe4, 0x69, 0x0f, 0x93, 0xca, 0x80, 0x7e,
+ 0xf6, 0x90, 0xbd, 0xf2, 0x86, 0xa3, 0xb6, 0x81, 0x7c, 0xe3, 0x40, 0x7a,
+ 0x65, 0x33, 0x71, 0xfd, 0x8c, 0xe6, 0xf6, 0x63, 0xcf, 0x40, 0xdd, 0x29,
+ 0xf2, 0x15, 0x25, 0x96, 0x1a, 0xa5, 0x14, 0x1e, 0xa2, 0xfd, 0x53, 0xb8,
+ 0xbc, 0x20, 0x10, 0x87, 0xcb, 0x8e, 0x24, 0xa9, 0x47, 0x60, 0x47, 0xcc,
+ 0xb2, 0x2e, 0xe5, 0x0f, 0x3e, 0x2c, 0x22, 0x9a, 0x1b, 0x46, 0x5a, 0xe4,
+ 0x2b, 0x7f, 0x4a, 0xab, 0x33, 0x49, 0xea, 0xd8, 0x6a, 0xd5, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x0f, 0x62, 0xc9, 0x94, 0xc0, 0x00,
+ 0x55, 0x51, 0x60, 0x36, 0xce, 0xd6, 0x4d, 0x6b, 0x5e, 0x20, 0x02, 0x6c,
+ 0x2e, 0xed, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
+ 0x16, 0x80, 0x14, 0x0f, 0x62, 0xc9, 0x94, 0xc0, 0x00, 0x55, 0x51, 0x60,
+ 0x36, 0xce, 0xd6, 0x4d, 0x6b, 0x5e, 0x20, 0x02, 0x6c, 0x2e, 0xed, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01,
+ 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x31, 0x7f, 0xcd,
+ 0x8b, 0xf1, 0x9c, 0x87, 0x59, 0xed, 0xe2, 0x36, 0x18, 0x84, 0x1c, 0x54,
+ 0x4e, 0x92, 0x45, 0xaf, 0xe9, 0xa1, 0x78, 0x89, 0x6e, 0xad, 0xec, 0x51,
+ 0xf9, 0x81, 0x70, 0xd9, 0x94, 0x01, 0xa9, 0x2a, 0x0d, 0x5f, 0xda, 0x83,
+ 0x49, 0x32, 0x24, 0x7e, 0xfd, 0x73, 0x97, 0xa2, 0x05, 0xd4, 0xf1, 0xb7,
+ 0x3f, 0xa0, 0x49, 0xbc, 0x0c, 0x85, 0x3e, 0xd3, 0x15, 0x67, 0xef, 0x5f,
+ 0xfb, 0xbe, 0x0d, 0x2a, 0x97, 0xcd, 0xaa, 0x24, 0x1e, 0x5a, 0xdd, 0x47,
+ 0xcf, 0x70, 0xe4, 0x93, 0xe6, 0xc3, 0xad, 0x78, 0x84, 0x60, 0xfa, 0x16,
+ 0x2e, 0xcc, 0x98, 0x88, 0xde, 0x80, 0xbb, 0x8f, 0x46, 0xfd, 0x59, 0x95,
+ 0xb4, 0x0b, 0x07, 0x8a, 0x67, 0x04, 0x10, 0xbd, 0x32, 0xb0, 0xa2, 0xfe,
+ 0x0f, 0xe0, 0x3e, 0x49, 0x84, 0x89, 0xc6, 0x18, 0xd9, 0xca, 0xdd, 0x63,
+ 0x0d, 0x55, 0x46, 0x56, 0xd1, 0x83, 0xcb, 0x0d, 0x23, 0x21, 0xb3, 0x59,
+ 0xa9, 0xd5, 0x56, 0x83, 0x4f, 0xf0, 0x92, 0x0b, 0xcc, 0xed, 0x93, 0x02,
+ 0xe7, 0x07, 0x92, 0x15, 0x90, 0x18, 0x78, 0xc9, 0xf4, 0x59, 0x0e, 0xbe,
+ 0xaa, 0x3e, 0x91, 0xb7, 0x81, 0xa2, 0x0c, 0x28, 0x04, 0xde, 0x78, 0xb0,
+ 0xd1, 0x54, 0x90, 0x8f, 0x3c, 0xfd, 0x2e, 0x36, 0x6e, 0xfe, 0x7b, 0xf6,
+ 0xce, 0x65, 0xae, 0x99, 0xa5, 0x38, 0x29, 0x4b, 0x13, 0x2f, 0x01, 0xa8,
+ 0xb0, 0xd0, 0x43, 0x22, 0x01, 0xd1, 0x71, 0x35, 0x93, 0xcf, 0x1e, 0x9e,
+ 0x05, 0x03, 0x05, 0xff, 0xfc, 0x35, 0x34, 0x6f, 0x49, 0x04, 0xe6, 0x58,
+ 0xa6, 0x0a, 0xb6, 0x13, 0x67, 0xd8, 0x1e, 0xe7, 0x33, 0x0f, 0x51, 0xb1,
+ 0x5c, 0x75, 0x1c, 0xea, 0x2b, 0x94, 0xec, 0x32, 0x7e, 0xb0, 0x8c, 0xb7,
+ 0x63, 0xf4, 0x83, 0x58, 0x3e, 0x47, 0xb7, 0x92, 0x67, 0x2c, 0xd5, 0xdb,
+ 0x48};
+
+ const unsigned char kExpectedServerEndPointToken[] = {
+ 0x74, 0x6c, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2d, 0x65,
+ 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x3a, 0x9c, 0xd9, 0x91,
+ 0xd4, 0x57, 0x1b, 0x64, 0x9d, 0x84, 0x31, 0xfd, 0xda, 0x3d, 0xaa, 0x2e,
+ 0x26, 0xab, 0xee, 0x40, 0x6b, 0x95, 0x36, 0x82, 0xc4, 0x5f, 0xad, 0xc1,
+ 0x26, 0x29, 0x72, 0xda, 0xe6, 0xfd, 0xa6, 0xd8, 0x0e, 0xab, 0xa2, 0xca,
+ 0x7d, 0x7d, 0x18, 0xa8, 0xee, 0x80, 0x26, 0xb2, 0x1f,
+ };
+
+ scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(kCertificateDataDER),
+ sizeof(kCertificateDataDER));
+
+ std::string channel_bindings;
+ ASSERT_TRUE(
+ x509_util::GetTLSServerEndPointChannelBinding(*cert, &channel_bindings));
+
+ std::string expected_channel_bindings(
+ std::begin(kExpectedServerEndPointToken),
+ std::end(kExpectedServerEndPointToken));
+ EXPECT_EQ(expected_channel_bindings, channel_bindings);
+}
+
+TEST(X509UtilTest, CreateChannelBindings_SHA512) {
+ // Certificate:
+ // Data:
+ // Version: 3 (0x2)
+ // Serial Number: 15197703563697605045 (0xd2e916decbe249b5)
+ // Signature Algorithm: sha512WithRSAEncryption
+ // ...
+ const uint8_t kCertificateDataDER[] = {
+ 0x30, 0x82, 0x03, 0x81, 0x30, 0x82, 0x02, 0x69, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0xd2, 0xe9, 0x16, 0xde, 0xcb, 0xe2, 0x49, 0xb5,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x0d, 0x05, 0x00, 0x30, 0x57, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06,
+ 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x04, 0x42, 0x6c, 0x61, 0x68, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61,
+ 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x36, 0x30, 0x33, 0x31, 0x37, 0x32, 0x30, 0x31, 0x33, 0x31, 0x30,
+ 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x36, 0x32, 0x30, 0x31,
+ 0x33, 0x31, 0x30, 0x5a, 0x30, 0x57, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, 0x10,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72,
+ 0x69, 0x64, 0x67, 0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x0c, 0x04, 0x42, 0x6c, 0x61, 0x68, 0x31, 0x18, 0x30, 0x16, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01,
+ 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01,
+ 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd3, 0xec, 0x61, 0x08, 0xbd, 0x91,
+ 0x94, 0x07, 0xaf, 0xf1, 0xf5, 0xeb, 0x84, 0x6d, 0x4b, 0x42, 0x0b, 0x40,
+ 0xb6, 0x6a, 0x51, 0x4d, 0x41, 0xde, 0x1c, 0xad, 0xf2, 0xcb, 0x73, 0xdb,
+ 0x41, 0x54, 0xd2, 0x13, 0xd6, 0xe9, 0x9b, 0xbe, 0x49, 0x3c, 0x6a, 0xeb,
+ 0x16, 0xa1, 0xee, 0x88, 0xbf, 0x58, 0xe6, 0x25, 0x52, 0x84, 0xdd, 0x3d,
+ 0x62, 0x34, 0x22, 0x81, 0x98, 0x55, 0x0d, 0xce, 0x6e, 0xf1, 0x72, 0xae,
+ 0x70, 0x34, 0x51, 0x4b, 0x54, 0xc8, 0x79, 0xe3, 0x57, 0xab, 0x24, 0xc0,
+ 0x29, 0x67, 0x38, 0xb1, 0x7f, 0x71, 0x32, 0x60, 0x08, 0x34, 0xa1, 0x92,
+ 0x6d, 0x78, 0xd6, 0x16, 0x73, 0x68, 0x32, 0x8b, 0xf8, 0x95, 0xa5, 0x79,
+ 0xfb, 0xa5, 0xd3, 0x8d, 0xb2, 0xa4, 0x4d, 0xc3, 0x22, 0xff, 0x2f, 0xae,
+ 0x6f, 0x12, 0xc9, 0xa6, 0xad, 0xe3, 0x6d, 0xc7, 0x40, 0x9b, 0x6a, 0xba,
+ 0x3c, 0x8c, 0xf3, 0x85, 0xa6, 0xc0, 0xbd, 0x49, 0xb6, 0x4f, 0xed, 0xaf,
+ 0x10, 0xb4, 0x17, 0x26, 0x40, 0x21, 0x01, 0xb7, 0xa9, 0xf0, 0x06, 0x98,
+ 0xfa, 0x03, 0x09, 0xe1, 0xfc, 0x7e, 0xcd, 0x70, 0x09, 0xcb, 0x19, 0x00,
+ 0x0a, 0x3c, 0x3a, 0xd8, 0x95, 0xfc, 0xd7, 0x2e, 0x92, 0x06, 0x25, 0x03,
+ 0xbd, 0x3f, 0x05, 0xf4, 0x89, 0x23, 0x41, 0x08, 0xc8, 0x3c, 0x62, 0xdc,
+ 0x25, 0xed, 0x01, 0x68, 0xf3, 0x75, 0x4d, 0xc5, 0xc2, 0xb0, 0x36, 0xb3,
+ 0x0f, 0x78, 0x4a, 0x2c, 0xa7, 0xbb, 0x13, 0x38, 0x09, 0xfd, 0x49, 0x95,
+ 0x99, 0x4c, 0x23, 0x36, 0x0a, 0x0f, 0x70, 0xbe, 0x02, 0xc3, 0x50, 0x30,
+ 0xb4, 0xaa, 0x7d, 0x47, 0x42, 0xbe, 0x62, 0x59, 0xbe, 0x88, 0xc4, 0x96,
+ 0x42, 0x63, 0xf3, 0x27, 0x09, 0x30, 0x9e, 0x58, 0xe6, 0xbe, 0x12, 0x2b,
+ 0x22, 0x11, 0x72, 0x65, 0x6c, 0x47, 0x50, 0x8c, 0x69, 0x0b, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x40, 0x1f, 0x60, 0x96, 0x13, 0x3e,
+ 0xb4, 0x93, 0x65, 0x71, 0x0e, 0x1b, 0xa3, 0xe6, 0x25, 0x21, 0xd6, 0x90,
+ 0x69, 0xed, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
+ 0x16, 0x80, 0x14, 0x40, 0x1f, 0x60, 0x96, 0x13, 0x3e, 0xb4, 0x93, 0x65,
+ 0x71, 0x0e, 0x1b, 0xa3, 0xe6, 0x25, 0x21, 0xd6, 0x90, 0x69, 0xed, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01,
+ 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x03, 0x4e, 0x0b,
+ 0xdd, 0x81, 0xe9, 0xf9, 0x91, 0x92, 0xa2, 0x77, 0xd0, 0x8f, 0x73, 0xb6,
+ 0x28, 0x7d, 0x3e, 0x2f, 0x36, 0x25, 0x01, 0x0f, 0x66, 0x14, 0x4d, 0x98,
+ 0x9d, 0x90, 0x08, 0x41, 0xfa, 0xe0, 0x8e, 0x15, 0xb6, 0xf9, 0x2c, 0x67,
+ 0x02, 0x31, 0x79, 0xa4, 0x2f, 0xb7, 0xf0, 0xf2, 0xfa, 0x28, 0xcf, 0xe5,
+ 0x71, 0x57, 0xd2, 0x18, 0xd5, 0xbd, 0x2b, 0xa8, 0x88, 0x10, 0xaf, 0xe9,
+ 0x68, 0x97, 0xb0, 0x04, 0x3f, 0x07, 0x5d, 0xb0, 0xc6, 0xfd, 0x34, 0xf0,
+ 0x14, 0xea, 0x81, 0xf5, 0x00, 0xd7, 0xe5, 0x0b, 0xde, 0x9a, 0x78, 0x93,
+ 0xe9, 0x64, 0x38, 0x93, 0x53, 0x57, 0x5c, 0x22, 0x1d, 0xec, 0xec, 0x77,
+ 0xc9, 0xed, 0x79, 0x8b, 0x85, 0xe6, 0xf2, 0xb0, 0x11, 0x34, 0x25, 0x20,
+ 0xdb, 0x3a, 0x82, 0x72, 0x15, 0x6e, 0xbb, 0x2b, 0x6c, 0xad, 0x26, 0x4d,
+ 0xb4, 0x2b, 0xd4, 0xd5, 0x45, 0x19, 0x6f, 0x3c, 0xd3, 0x42, 0x53, 0xdb,
+ 0x70, 0x6b, 0xd1, 0x9f, 0x24, 0x40, 0x55, 0xad, 0x64, 0x7e, 0x66, 0x80,
+ 0x45, 0xfb, 0x30, 0x97, 0x20, 0x3d, 0x3e, 0x14, 0xfe, 0x88, 0x0d, 0xd9,
+ 0x3a, 0x7e, 0x30, 0x5c, 0x75, 0x87, 0x59, 0x37, 0xe7, 0xb9, 0xff, 0x3d,
+ 0xf8, 0x47, 0xe4, 0xb7, 0xa6, 0xcc, 0x62, 0xc8, 0xfa, 0x55, 0x93, 0xe8,
+ 0xe4, 0x33, 0x29, 0x33, 0x91, 0xeb, 0x16, 0x95, 0xdc, 0x63, 0xaf, 0x5e,
+ 0x9b, 0x0c, 0xa4, 0x99, 0x20, 0x90, 0x80, 0x1c, 0xbe, 0x9f, 0x22, 0x93,
+ 0x21, 0xe1, 0x1c, 0x16, 0x92, 0x42, 0x42, 0x67, 0xfb, 0xf3, 0x31, 0x8c,
+ 0x78, 0x41, 0x43, 0xed, 0x5f, 0x09, 0x0b, 0x21, 0x72, 0x40, 0x95, 0xdb,
+ 0xd7, 0x8d, 0x2a, 0xe1, 0x52, 0x03, 0x57, 0xc8, 0x7b, 0x15, 0x90, 0x92,
+ 0xdf, 0x07, 0x11, 0xfb, 0xf7, 0x25, 0xbe, 0xcb, 0x0b, 0xfa, 0xa6, 0x34,
+ 0x61,
+ };
+
+ const unsigned char kExpectedServerEndPointToken[] = {
+ 0x74, 0x6c, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2d,
+ 0x65, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x3a, 0x2c,
+ 0x33, 0xc9, 0xee, 0x30, 0xa1, 0x99, 0xdc, 0x19, 0x48, 0x0a, 0xec,
+ 0xc5, 0x1d, 0x94, 0xc7, 0x84, 0x3d, 0xc7, 0x9e, 0x51, 0xee, 0xbc,
+ 0x23, 0x33, 0xfd, 0xeb, 0x20, 0x78, 0x3b, 0x93, 0xe8, 0xe6, 0x78,
+ 0x10, 0xd7, 0x5e, 0x37, 0x48, 0x04, 0x07, 0x5f, 0x57, 0xe6, 0x16,
+ 0xe2, 0x45, 0x44, 0xa3, 0x71, 0x8c, 0xef, 0x95, 0x08, 0x6b, 0x0c,
+ 0xaa, 0x65, 0x51, 0x51, 0x60, 0x4f, 0x58, 0x28,
+ };
+
+ scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(kCertificateDataDER),
+ sizeof(kCertificateDataDER));
+
+ std::string channel_bindings;
+ ASSERT_TRUE(
+ x509_util::GetTLSServerEndPointChannelBinding(*cert, &channel_bindings));
+
+ std::string expected_channel_bindings(
+ std::begin(kExpectedServerEndPointToken),
+ std::end(kExpectedServerEndPointToken));
+ EXPECT_EQ(expected_channel_bindings, channel_bindings);
+}
+
+TEST(X509UtilTest, CreateChannelBindings_Unsupported_MD4) {
+ // Certificate:
+ // Data:
+ // Version: 3 (0x2)
+ // Serial Number: 12629177056471137087 (0xaf43d99ee079bb3f)
+ // Signature Algorithm: md4WithRSAEncryption
+ // ...
+ const uint8_t kCertificateDataDER[] = {
+ 0x30, 0x82, 0x03, 0x87, 0x30, 0x82, 0x02, 0x6f, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0xaf, 0x43, 0xd9, 0x9e, 0xe0, 0x79, 0xbb, 0x3f,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x03, 0x05, 0x00, 0x30, 0x5a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06,
+ 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69,
+ 0x64, 0x67, 0x65, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x31, 0x18, 0x30,
+ 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e,
+ 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30,
+ 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x37, 0x32, 0x30, 0x31,
+ 0x39, 0x35, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x36,
+ 0x32, 0x30, 0x31, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x5a, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31,
+ 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61,
+ 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x10, 0x30, 0x0e, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c,
+ 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f,
+ 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xaf, 0xf8, 0xa5, 0xba, 0x20, 0x40, 0xcd, 0x60, 0x88, 0x1f, 0x27, 0x34,
+ 0x57, 0x2f, 0x1b, 0xc9, 0xfc, 0xf3, 0x0b, 0x9f, 0xb3, 0xb8, 0x26, 0x67,
+ 0x78, 0x79, 0x2b, 0xfe, 0x68, 0xa3, 0x95, 0x8c, 0x40, 0x6f, 0x80, 0x8b,
+ 0x15, 0x8f, 0x0b, 0x4c, 0x66, 0x8d, 0x17, 0x32, 0x6a, 0xa0, 0x57, 0x74,
+ 0x2d, 0x31, 0xc4, 0x8e, 0xa4, 0x76, 0x6b, 0xff, 0x93, 0x05, 0x44, 0x9b,
+ 0xe9, 0xf2, 0x81, 0x1e, 0x3b, 0x2e, 0x05, 0x67, 0x01, 0x85, 0x5a, 0xed,
+ 0xad, 0xc8, 0x55, 0x4b, 0x8e, 0x80, 0x1e, 0x7a, 0x5a, 0xbd, 0xc2, 0x8e,
+ 0x5f, 0x4f, 0x3a, 0x52, 0xda, 0x2d, 0x86, 0x0d, 0x6b, 0xaf, 0xe2, 0x12,
+ 0xd1, 0x6e, 0x15, 0x78, 0xb5, 0x06, 0x1c, 0xa2, 0xb4, 0xda, 0x3c, 0xfe,
+ 0x8b, 0x4c, 0x70, 0x5c, 0xc5, 0x5c, 0x86, 0xf6, 0x95, 0x01, 0x88, 0x44,
+ 0x99, 0xd2, 0x97, 0x47, 0xdb, 0xdb, 0x4f, 0x6d, 0x1a, 0xd1, 0x1d, 0x74,
+ 0x0b, 0x89, 0x5c, 0x05, 0x19, 0xe7, 0xe7, 0x17, 0xee, 0xb5, 0xf8, 0x75,
+ 0x96, 0x95, 0x5a, 0xfd, 0x37, 0x4d, 0xa1, 0xda, 0x5c, 0xf6, 0x5c, 0x60,
+ 0xa1, 0x04, 0x92, 0xa5, 0x42, 0x02, 0xbd, 0x40, 0xb3, 0x1e, 0xab, 0x28,
+ 0x0b, 0x28, 0x79, 0x92, 0xdc, 0x23, 0xde, 0xad, 0x28, 0x06, 0xba, 0x93,
+ 0x28, 0x3f, 0xf4, 0x6a, 0x10, 0x11, 0xf1, 0xe4, 0x92, 0x5b, 0x65, 0xce,
+ 0x0f, 0x13, 0x34, 0x87, 0xb6, 0xa4, 0x1d, 0xe3, 0x4a, 0xea, 0xc8, 0xcf,
+ 0x4e, 0x21, 0xf2, 0x70, 0x18, 0x9f, 0x3a, 0x62, 0x43, 0x70, 0x89, 0xb9,
+ 0xca, 0xab, 0xa6, 0xb1, 0x55, 0x42, 0x3d, 0x25, 0x35, 0xd6, 0xa2, 0x77,
+ 0x0f, 0x66, 0x88, 0xd2, 0x43, 0x6b, 0xfa, 0x3c, 0xa3, 0xcf, 0xa1, 0x56,
+ 0x84, 0xe5, 0x9b, 0x25, 0xff, 0x02, 0xb6, 0x9d, 0xaf, 0x6a, 0x4d, 0x8c,
+ 0xf8, 0x3e, 0xf7, 0xe5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30,
+ 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14,
+ 0x62, 0xf2, 0x1f, 0xd6, 0x29, 0xfa, 0x61, 0x88, 0x4c, 0x36, 0x39, 0xed,
+ 0x9f, 0x8e, 0xcf, 0x3b, 0xdc, 0x90, 0x04, 0xa5, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x62, 0xf2, 0x1f,
+ 0xd6, 0x29, 0xfa, 0x61, 0x88, 0x4c, 0x36, 0x39, 0xed, 0x9f, 0x8e, 0xcf,
+ 0x3b, 0xdc, 0x90, 0x04, 0xa5, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x03, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x01, 0x00, 0x9e, 0x36, 0xff, 0xf5, 0x77, 0x46, 0x80, 0x22, 0xc4,
+ 0x01, 0x05, 0x69, 0x84, 0xd1, 0xdc, 0x0c, 0xce, 0xda, 0x2f, 0x21, 0x11,
+ 0x9a, 0x80, 0x24, 0x81, 0xea, 0x1b, 0x1a, 0xb9, 0x5d, 0x70, 0x60, 0xaf,
+ 0xbc, 0xca, 0xdb, 0xc4, 0x10, 0x6e, 0x17, 0xdb, 0x58, 0x11, 0x0c, 0xec,
+ 0x0e, 0xdd, 0xf8, 0xbf, 0x42, 0x27, 0x2d, 0x06, 0x75, 0x25, 0xc0, 0xdb,
+ 0xb0, 0x35, 0x0c, 0x66, 0xfb, 0xfd, 0x0e, 0xb9, 0x16, 0x9e, 0x34, 0xaf,
+ 0xdb, 0x72, 0x6e, 0xb3, 0x6d, 0x5e, 0xb2, 0xf0, 0x6d, 0x46, 0x32, 0xba,
+ 0x35, 0xb5, 0x3b, 0xc5, 0x72, 0xb7, 0x1c, 0x88, 0x6a, 0x84, 0xc2, 0xde,
+ 0x1d, 0x45, 0x30, 0x41, 0x3d, 0xc5, 0xbb, 0x0a, 0x78, 0xe9, 0xef, 0x59,
+ 0xc6, 0xbc, 0x0c, 0x9d, 0x36, 0x1f, 0xc8, 0xb1, 0x1b, 0xd3, 0x1c, 0xec,
+ 0x57, 0x69, 0x8b, 0xcb, 0x1b, 0x93, 0x99, 0x2e, 0xab, 0x8d, 0xd7, 0x63,
+ 0xc5, 0x1f, 0x58, 0x9d, 0x06, 0x8e, 0xf1, 0x47, 0x64, 0xc5, 0xf3, 0x03,
+ 0x8d, 0x2c, 0x8a, 0x99, 0x2c, 0xe6, 0x89, 0x87, 0xb2, 0x42, 0xdd, 0x18,
+ 0xf0, 0xc9, 0xdb, 0x6c, 0xee, 0x3e, 0x5e, 0xc5, 0x75, 0xc7, 0x45, 0xd3,
+ 0xd0, 0xaa, 0xf7, 0x0d, 0xac, 0xaa, 0x4c, 0xb4, 0xa4, 0xa2, 0xb7, 0xfc,
+ 0x65, 0xb0, 0x2e, 0x83, 0xbd, 0x7a, 0x65, 0xfb, 0x1b, 0x92, 0x3f, 0x8d,
+ 0x47, 0x0c, 0xbb, 0x4a, 0x38, 0xc5, 0x67, 0x87, 0x8e, 0x79, 0xd6, 0x48,
+ 0xc7, 0xf2, 0x92, 0xdb, 0x6e, 0xf9, 0x54, 0x01, 0xed, 0xdb, 0xbd, 0xe0,
+ 0x12, 0x18, 0xd9, 0xcf, 0x36, 0x5d, 0x7e, 0xe9, 0xb9, 0x27, 0x09, 0x80,
+ 0x1a, 0x2f, 0xb9, 0x58, 0xc6, 0x6f, 0xa2, 0x42, 0x7a, 0x7b, 0x20, 0xf2,
+ 0xc9, 0x85, 0x54, 0x11, 0xa2, 0xe3, 0x31, 0x0f, 0x71, 0x6a, 0xea, 0x0e,
+ 0xef, 0xba, 0x6d, 0x5e, 0x88, 0x01, 0xaf,
+ };
+
+ scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(kCertificateDataDER),
+ sizeof(kCertificateDataDER));
+
+ std::string channel_bindings;
+ ASSERT_FALSE(
+ x509_util::GetTLSServerEndPointChannelBinding(*cert, &channel_bindings));
+ EXPECT_TRUE(channel_bindings.empty());
+}
+#endif
+
} // namespace x509_util
} // namespace net
diff --git a/chromium/net/cookies/canonical_cookie.cc b/chromium/net/cookies/canonical_cookie.cc
index 15287e0b8b5..bce2b5477fa 100644
--- a/chromium/net/cookies/canonical_cookie.cc
+++ b/chromium/net/cookies/canonical_cookie.cc
@@ -47,6 +47,7 @@
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/cookies/cookie_util.h"
#include "net/cookies/parsed_cookie.h"
@@ -133,7 +134,7 @@ CanonicalCookie::CanonicalCookie(const GURL& url,
const base::Time& last_access,
bool secure,
bool httponly,
- bool firstpartyonly,
+ CookieSameSite same_site,
CookiePriority priority)
: source_(url.SchemeIsFile() ? url : url.GetOrigin()),
name_(name),
@@ -145,36 +146,10 @@ CanonicalCookie::CanonicalCookie(const GURL& url,
last_access_date_(last_access),
secure_(secure),
httponly_(httponly),
- first_party_only_(firstpartyonly),
+ same_site_(same_site),
priority_(priority) {}
-CanonicalCookie::CanonicalCookie(const GURL& url, const ParsedCookie& pc)
- : source_(url.SchemeIsFile() ? url : url.GetOrigin()),
- name_(pc.Name()),
- value_(pc.Value()),
- path_(CanonPath(url, pc)),
- creation_date_(Time::Now()),
- last_access_date_(Time()),
- secure_(pc.IsSecure()),
- httponly_(pc.IsHttpOnly()),
- first_party_only_(pc.IsFirstPartyOnly()),
- priority_(pc.Priority()) {
- if (pc.HasExpires())
- expiry_date_ = CanonExpiration(pc, creation_date_, creation_date_);
-
- // Do the best we can with the domain.
- std::string cookie_domain;
- std::string domain_string;
- if (pc.HasDomain()) {
- domain_string = pc.Domain();
- }
- bool result
- = cookie_util::GetCookieDomainWithString(url, domain_string,
- &cookie_domain);
- // Caller is responsible for passing in good arguments.
- DCHECK(result);
- domain_ = cookie_domain;
-}
+CanonicalCookie::CanonicalCookie(const CanonicalCookie& other) = default;
CanonicalCookie::~CanonicalCookie() {
}
@@ -217,26 +192,27 @@ Time CanonicalCookie::CanonExpiration(const ParsedCookie& pc,
}
// static
-CanonicalCookie* CanonicalCookie::Create(const GURL& url,
- const std::string& cookie_line,
- const base::Time& creation_time,
- const CookieOptions& options) {
+scoped_ptr<CanonicalCookie> CanonicalCookie::Create(
+ const GURL& url,
+ const std::string& cookie_line,
+ const base::Time& creation_time,
+ const CookieOptions& options) {
ParsedCookie parsed_cookie(cookie_line);
if (!parsed_cookie.IsValid()) {
VLOG(kVlogSetCookies) << "WARNING: Couldn't parse cookie";
- return NULL;
+ return nullptr;
}
if (options.exclude_httponly() && parsed_cookie.IsHttpOnly()) {
VLOG(kVlogSetCookies) << "Create() is not creating a httponly cookie";
- return NULL;
+ return nullptr;
}
std::string cookie_domain;
if (!GetCookieDomain(url, parsed_cookie, &cookie_domain)) {
VLOG(kVlogSetCookies) << "Create() failed to get a cookie domain";
- return NULL;
+ return nullptr;
}
// Per 3.2.1 of "Deprecate modification of 'secure' cookies from non-secure
@@ -247,7 +223,7 @@ CanonicalCookie* CanonicalCookie::Create(const GURL& url,
!url.SchemeIsCryptographic()) {
VLOG(kVlogSetCookies)
<< "Create() is trying to create a secure cookie from an insecure URL";
- return NULL;
+ return nullptr;
}
std::string cookie_path = CanonicalCookie::CanonPath(url, parsed_cookie);
@@ -269,54 +245,56 @@ CanonicalCookie* CanonicalCookie::Create(const GURL& url,
return nullptr;
}
- return new CanonicalCookie(
+ return make_scoped_ptr(new CanonicalCookie(
url, parsed_cookie.Name(), parsed_cookie.Value(), cookie_domain,
cookie_path, creation_time, cookie_expires, creation_time,
parsed_cookie.IsSecure(), parsed_cookie.IsHttpOnly(),
- parsed_cookie.IsFirstPartyOnly(), parsed_cookie.Priority());
+ parsed_cookie.SameSite(), parsed_cookie.Priority()));
}
-CanonicalCookie* CanonicalCookie::Create(const GURL& url,
- const std::string& name,
- const std::string& value,
- const std::string& domain,
- const std::string& path,
- const base::Time& creation,
- const base::Time& expiration,
- bool secure,
- bool http_only,
- bool first_party_only,
- bool enforce_strict_secure,
- CookiePriority priority) {
+// static
+scoped_ptr<CanonicalCookie> CanonicalCookie::Create(
+ const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ const base::Time& creation,
+ const base::Time& expiration,
+ bool secure,
+ bool http_only,
+ CookieSameSite same_site,
+ bool enforce_strict_secure,
+ CookiePriority priority) {
// Expect valid attribute tokens and values, as defined by the ParsedCookie
// logic, otherwise don't create the cookie.
std::string parsed_name = ParsedCookie::ParseTokenString(name);
if (parsed_name != name)
- return NULL;
+ return nullptr;
std::string parsed_value = ParsedCookie::ParseValueString(value);
if (parsed_value != value)
- return NULL;
+ return nullptr;
std::string parsed_domain = ParsedCookie::ParseValueString(domain);
if (parsed_domain != domain)
- return NULL;
+ return nullptr;
std::string cookie_domain;
if (!cookie_util::GetCookieDomainWithString(url, parsed_domain,
&cookie_domain)) {
- return NULL;
+ return nullptr;
}
if (enforce_strict_secure && secure && !url.SchemeIsCryptographic())
- return NULL;
+ return nullptr;
std::string parsed_path = ParsedCookie::ParseValueString(path);
if (parsed_path != path)
- return NULL;
+ return nullptr;
std::string cookie_path = CanonPathWithString(url, parsed_path);
// Expect that the path was either not specified (empty), or is valid.
if (!parsed_path.empty() && cookie_path != parsed_path)
- return NULL;
+ return nullptr;
// Canonicalize path again to make sure it escapes characters as needed.
url::Component path_component(0, cookie_path.length());
url::RawCanonOutputT<char> canon_path;
@@ -326,9 +304,9 @@ CanonicalCookie* CanonicalCookie::Create(const GURL& url,
cookie_path = std::string(canon_path.data() + canon_path_component.begin,
canon_path_component.len);
- return new CanonicalCookie(url, parsed_name, parsed_value, cookie_domain,
- cookie_path, creation, expiration, creation,
- secure, http_only, first_party_only, priority);
+ return make_scoped_ptr(new CanonicalCookie(
+ url, parsed_name, parsed_value, cookie_domain, cookie_path, creation,
+ expiration, creation, secure, http_only, same_site, priority));
}
bool CanonicalCookie::IsOnPath(const std::string& url_path) const {
@@ -344,25 +322,24 @@ bool CanonicalCookie::IsOnPath(const std::string& url_path) const {
// was longer, the same length, or shorter than the length of the url path.
// I think the approach below is simpler.
- // Make sure the cookie path is a prefix of the url path. If the
- // url path is shorter than the cookie path, then the cookie path
- // can't be a prefix.
- if (url_path.find(path_) != 0)
+ // Make sure the cookie path is a prefix of the url path. If the url path is
+ // shorter than the cookie path, then the cookie path can't be a prefix.
+ if (!base::StartsWith(url_path, path_, base::CompareCase::SENSITIVE))
return false;
- // Now we know that url_path is >= cookie_path, and that cookie_path
- // is a prefix of url_path. If they are the are the same length then
- // they are identical, otherwise we need an additional check:
+ // |url_path| is >= |path_|, and |path_| is a prefix of |url_path|. If they
+ // are the are the same length then they are identical, otherwise need an
+ // additional check:
// In order to avoid in correctly matching a cookie path of /blah
// with a request path of '/blahblah/', we need to make sure that either
// the cookie path ends in a trailing '/', or that we prefix up to a '/'
// in the url path. Since we know that the url path length is greater
// than the cookie path length, it's safe to index one byte past.
- if (path_.length() != url_path.length() &&
- path_[path_.length() - 1] != '/' &&
- url_path[path_.length()] != '/')
+ if (path_.length() != url_path.length() && path_.back() != '/' &&
+ url_path[path_.length()] != '/') {
return false;
+ }
return true;
}
@@ -416,9 +393,23 @@ bool CanonicalCookie::IncludeForRequestURL(const GURL& url,
// match the cookie-path.
if (!IsOnPath(url.path()))
return false;
- // Don't include first-party-only cookies for non-first-party requests.
- if (IsFirstPartyOnly() && !options.include_first_party_only_cookies())
- return false;
+ // Don't include same-site cookies for cross-site requests.
+ switch (SameSite()) {
+ case CookieSameSite::STRICT_MODE:
+ if (options.same_site_cookie_mode() !=
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX) {
+ return false;
+ }
+ break;
+ case CookieSameSite::LAX_MODE:
+ if (options.same_site_cookie_mode() ==
+ CookieOptions::SameSiteCookieMode::DO_NOT_INCLUDE) {
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
return true;
}
diff --git a/chromium/net/cookies/canonical_cookie.h b/chromium/net/cookies/canonical_cookie.h
index 9c3a1c9c04b..f95501c7627 100644
--- a/chromium/net/cookies/canonical_cookie.h
+++ b/chromium/net/cookies/canonical_cookie.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/gtest_prod_util.h"
+#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "net/base/net_export.h"
#include "net/cookies/cookie_constants.h"
@@ -37,13 +38,10 @@ class NET_EXPORT CanonicalCookie {
const base::Time& last_access,
bool secure,
bool httponly,
- bool firstpartyonly,
+ CookieSameSite same_site,
CookiePriority priority);
- // This constructor does canonicalization but not validation.
- // The result of this constructor should not be relied on in contexts
- // in which pre-validation of the ParsedCookie has not been done.
- CanonicalCookie(const GURL& url, const ParsedCookie& pc);
+ CanonicalCookie(const CanonicalCookie& other);
~CanonicalCookie();
@@ -52,26 +50,26 @@ class NET_EXPORT CanonicalCookie {
// Creates a new |CanonicalCookie| from the |cookie_line| and the
// |creation_time|. Canonicalizes and validates inputs. May return NULL if
// an attribute value is invalid.
- static CanonicalCookie* Create(const GURL& url,
- const std::string& cookie_line,
- const base::Time& creation_time,
- const CookieOptions& options);
+ static scoped_ptr<CanonicalCookie> Create(const GURL& url,
+ const std::string& cookie_line,
+ const base::Time& creation_time,
+ const CookieOptions& options);
// Creates a canonical cookie from unparsed attribute values.
// Canonicalizes and validates inputs. May return NULL if an attribute
// value is invalid.
- static CanonicalCookie* Create(const GURL& url,
- const std::string& name,
- const std::string& value,
- const std::string& domain,
- const std::string& path,
- const base::Time& creation,
- const base::Time& expiration,
- bool secure,
- bool http_only,
- bool first_party_only,
- bool enforce_strict_secure,
- CookiePriority priority);
+ static scoped_ptr<CanonicalCookie> Create(const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ const base::Time& creation,
+ const base::Time& expiration,
+ bool secure,
+ bool http_only,
+ CookieSameSite same_site,
+ bool enforce_strict_secure,
+ CookiePriority priority);
const GURL& Source() const { return source_; }
const std::string& Name() const { return name_; }
@@ -84,7 +82,7 @@ class NET_EXPORT CanonicalCookie {
const base::Time& ExpiryDate() const { return expiry_date_; }
bool IsSecure() const { return secure_; }
bool IsHttpOnly() const { return httponly_; }
- bool IsFirstPartyOnly() const { return first_party_only_; }
+ CookieSameSite SameSite() const { return same_site_; }
CookiePriority Priority() const { return priority_; }
bool IsDomainCookie() const {
return !domain_.empty() && domain_[0] == '.'; }
@@ -203,7 +201,7 @@ class NET_EXPORT CanonicalCookie {
base::Time last_access_date_;
bool secure_;
bool httponly_;
- bool first_party_only_;
+ CookieSameSite same_site_;
CookiePriority priority_;
};
diff --git a/chromium/net/cookies/canonical_cookie_unittest.cc b/chromium/net/cookies/canonical_cookie_unittest.cc
index 2a01d9742a2..80b772e9b2f 100644
--- a/chromium/net/cookies/canonical_cookie_unittest.cc
+++ b/chromium/net/cookies/canonical_cookie_unittest.cc
@@ -19,7 +19,7 @@ TEST(CanonicalCookieTest, Constructor) {
CanonicalCookie cookie(url, "A", "2", "www.example.com", "/test",
current_time, base::Time(), current_time, false, false,
- false, COOKIE_PRIORITY_DEFAULT);
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT);
EXPECT_EQ(url.GetOrigin(), cookie.Source());
EXPECT_EQ("A", cookie.Name());
EXPECT_EQ("2", cookie.Value());
@@ -27,11 +27,12 @@ TEST(CanonicalCookieTest, Constructor) {
EXPECT_EQ("/test", cookie.Path());
EXPECT_FALSE(cookie.IsSecure());
EXPECT_FALSE(cookie.IsHttpOnly());
- EXPECT_FALSE(cookie.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie.SameSite());
CanonicalCookie cookie2(url, "A", "2", std::string(), std::string(),
current_time, base::Time(), current_time, false,
- false, false, COOKIE_PRIORITY_DEFAULT);
+ false, CookieSameSite::DEFAULT_MODE,
+ COOKIE_PRIORITY_DEFAULT);
EXPECT_EQ(url.GetOrigin(), cookie.Source());
EXPECT_EQ("A", cookie2.Name());
EXPECT_EQ("2", cookie2.Value());
@@ -39,7 +40,7 @@ TEST(CanonicalCookieTest, Constructor) {
EXPECT_EQ("", cookie2.Path());
EXPECT_FALSE(cookie2.IsSecure());
EXPECT_FALSE(cookie2.IsHttpOnly());
- EXPECT_FALSE(cookie2.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie2.SameSite());
}
TEST(CanonicalCookieTest, Create) {
@@ -58,7 +59,7 @@ TEST(CanonicalCookieTest, Create) {
EXPECT_FALSE(cookie->IsSecure());
GURL url2("http://www.foo.com");
- cookie.reset(CanonicalCookie::Create(url2, "B=1", creation_time, options));
+ cookie = CanonicalCookie::Create(url2, "B=1", creation_time, options);
EXPECT_EQ(url2.GetOrigin(), cookie->Source());
EXPECT_EQ("B", cookie->Name());
EXPECT_EQ("1", cookie->Value());
@@ -68,34 +69,37 @@ TEST(CanonicalCookieTest, Create) {
// Test creating secure cookies. RFC 6265 allows insecure urls to set secure
// cookies.
- cookie.reset(
- CanonicalCookie::Create(url, "A=2; Secure", creation_time, options));
+ cookie = CanonicalCookie::Create(url, "A=2; Secure", creation_time, options);
EXPECT_TRUE(cookie.get());
EXPECT_TRUE(cookie->IsSecure());
// Test creating http only cookies.
- cookie.reset(
- CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options));
+ cookie =
+ CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options);
EXPECT_FALSE(cookie.get());
CookieOptions httponly_options;
httponly_options.set_include_httponly();
- cookie.reset(CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time,
- httponly_options));
+ cookie = CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time,
+ httponly_options);
EXPECT_TRUE(cookie->IsHttpOnly());
- // Test creating http only cookies.
- CookieOptions first_party_options;
- first_party_options.set_include_first_party_only_cookies();
- cookie.reset(CanonicalCookie::Create(url, "A=2; First-Party-Only",
- creation_time, httponly_options));
+ // Test creating SameSite cookies.
+ CookieOptions same_site_options;
+ same_site_options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite=Strict", creation_time,
+ same_site_options);
EXPECT_TRUE(cookie.get());
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::STRICT_MODE, cookie->SameSite());
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", creation_time,
+ same_site_options);
// Test the creating cookies using specific parameter instead of a cookie
// string.
- cookie.reset(CanonicalCookie::Create(
- url, "A", "2", "www.example.com", "/test", creation_time, base::Time(),
- false, false, false, false, COOKIE_PRIORITY_DEFAULT));
+ cookie = CanonicalCookie::Create(url, "A", "2", "www.example.com", "/test",
+ creation_time, base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, false,
+ COOKIE_PRIORITY_DEFAULT);
EXPECT_EQ(url.GetOrigin(), cookie->Source());
EXPECT_EQ("A", cookie->Name());
EXPECT_EQ("2", cookie->Value());
@@ -103,11 +107,12 @@ TEST(CanonicalCookieTest, Create) {
EXPECT_EQ("/test", cookie->Path());
EXPECT_FALSE(cookie->IsSecure());
EXPECT_FALSE(cookie->IsHttpOnly());
- EXPECT_FALSE(cookie->IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
- cookie.reset(CanonicalCookie::Create(
- url, "A", "2", ".www.example.com", "/test", creation_time, base::Time(),
- false, false, false, false, COOKIE_PRIORITY_DEFAULT));
+ cookie = CanonicalCookie::Create(url, "A", "2", ".www.example.com", "/test",
+ creation_time, base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, false,
+ COOKIE_PRIORITY_DEFAULT);
EXPECT_EQ(url.GetOrigin(), cookie->Source());
EXPECT_EQ("A", cookie->Name());
EXPECT_EQ("2", cookie->Value());
@@ -115,7 +120,24 @@ TEST(CanonicalCookieTest, Create) {
EXPECT_EQ("/test", cookie->Path());
EXPECT_FALSE(cookie->IsSecure());
EXPECT_FALSE(cookie->IsHttpOnly());
- EXPECT_FALSE(cookie->IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
+}
+
+TEST(CanonicalCookieTest, CreateInvalidSameSite) {
+ GURL url("http://www.example.com/test/foo.html");
+ base::Time now = base::Time::Now();
+ scoped_ptr<CanonicalCookie> cookie;
+ CookieOptions options;
+
+ // Invalid 'SameSite' attribute values.
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite=Invalid", now, options);
+ EXPECT_EQ(nullptr, cookie.get());
+
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite", now, options);
+ EXPECT_EQ(nullptr, cookie.get());
}
TEST(CanonicalCookieTest, EmptyExpiry) {
@@ -134,8 +156,7 @@ TEST(CanonicalCookieTest, EmptyExpiry) {
// With a stale server time
options.set_server_time(creation_time - base::TimeDelta::FromHours(1));
- cookie.reset(
- CanonicalCookie::Create(url, cookie_line, creation_time, options));
+ cookie = CanonicalCookie::Create(url, cookie_line, creation_time, options);
EXPECT_TRUE(cookie.get());
EXPECT_FALSE(cookie->IsPersistent());
EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -143,8 +164,7 @@ TEST(CanonicalCookieTest, EmptyExpiry) {
// With a future server time
options.set_server_time(creation_time + base::TimeDelta::FromHours(1));
- cookie.reset(
- CanonicalCookie::Create(url, cookie_line, creation_time, options));
+ cookie = CanonicalCookie::Create(url, cookie_line, creation_time, options);
EXPECT_TRUE(cookie.get());
EXPECT_FALSE(cookie->IsPersistent());
EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -162,19 +182,19 @@ TEST(CanonicalCookieTest, IsEquivalent) {
base::Time expiration_time = creation_time + base::TimeDelta::FromDays(2);
bool secure(false);
bool httponly(false);
- bool firstparty(false);
+ CookieSameSite same_site(CookieSameSite::NO_RESTRICTION);
// Test that a cookie is equivalent to itself.
scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(
url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalent(*cookie));
// Test that two identical cookies are equivalent.
scoped_ptr<CanonicalCookie> other_cookie(new CanonicalCookie(
url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
@@ -183,47 +203,47 @@ TEST(CanonicalCookieTest, IsEquivalent) {
other_cookie.reset(
new CanonicalCookie(url, cookie_name, "2", cookie_domain, cookie_path,
creation_time, expiration_time, last_access_time,
- secure, httponly, firstparty, COOKIE_PRIORITY_HIGH));
+ secure, httponly, same_site, COOKIE_PRIORITY_HIGH));
EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
base::Time other_creation_time =
creation_time + base::TimeDelta::FromMinutes(2);
other_cookie.reset(new CanonicalCookie(
url, cookie_name, "2", cookie_domain, cookie_path, other_creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, true, httponly, firstparty,
+ expiration_time, last_access_time, true, httponly, same_site,
COOKIE_PRIORITY_LOW));
EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, true, firstparty,
+ expiration_time, last_access_time, secure, true, same_site,
COOKIE_PRIORITY_LOW));
EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, true,
- COOKIE_PRIORITY_LOW));
+ expiration_time, last_access_time, secure, httponly,
+ CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_LOW));
EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
// Tests that use different variations of attribute values that
// DO affect cookie equivalence.
- other_cookie.reset(new CanonicalCookie(
- url, "B", cookie_value, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
- COOKIE_PRIORITY_MEDIUM));
+ other_cookie.reset(
+ new CanonicalCookie(url, "B", cookie_value, cookie_domain, cookie_path,
+ creation_time, expiration_time, last_access_time,
+ secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM));
EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_value, "www.example.com", cookie_path,
creation_time, expiration_time, last_access_time, secure, httponly,
- firstparty, COOKIE_PRIORITY_MEDIUM));
+ same_site, COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsDomainCookie());
EXPECT_FALSE(other_cookie->IsDomainCookie());
EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
@@ -231,12 +251,12 @@ TEST(CanonicalCookieTest, IsEquivalent) {
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_value, ".example.com", cookie_path,
creation_time, expiration_time, last_access_time, secure, httponly,
- firstparty, COOKIE_PRIORITY_MEDIUM));
+ same_site, COOKIE_PRIORITY_MEDIUM));
EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_value, cookie_domain, "/test/0", creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
}
@@ -252,19 +272,19 @@ TEST(CanonicalCookieTest, IsEquivalentForSecureCookieMatching) {
base::Time expiration_time = creation_time + base::TimeDelta::FromDays(2);
bool secure(false);
bool httponly(false);
- bool firstparty(false);
+ CookieSameSite same_site(CookieSameSite::NO_RESTRICTION);
// Test that a cookie is equivalent to itself.
scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(
url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*cookie));
// Test that two identical cookies are equivalent.
scoped_ptr<CanonicalCookie> other_cookie(new CanonicalCookie(
url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
@@ -277,47 +297,47 @@ TEST(CanonicalCookieTest, IsEquivalentForSecureCookieMatching) {
other_cookie.reset(
new CanonicalCookie(url, cookie_name, "2", cookie_domain, cookie_path,
creation_time, expiration_time, last_access_time,
- secure, httponly, firstparty, COOKIE_PRIORITY_HIGH));
+ secure, httponly, same_site, COOKIE_PRIORITY_HIGH));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
base::Time other_creation_time =
creation_time + base::TimeDelta::FromMinutes(2);
other_cookie.reset(new CanonicalCookie(
url, cookie_name, "2", cookie_domain, cookie_path, other_creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, true, httponly, firstparty,
+ expiration_time, last_access_time, true, httponly, same_site,
COOKIE_PRIORITY_LOW));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, true, firstparty,
+ expiration_time, last_access_time, secure, true, same_site,
COOKIE_PRIORITY_LOW));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, true,
- COOKIE_PRIORITY_LOW));
+ expiration_time, last_access_time, secure, httponly,
+ CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_LOW));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
// The following 3 tests' expected results differ from their IsEquivalent
// counterparts above.
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_value, cookie_domain, "/test/0", creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_value, "www.example.com", cookie_path,
creation_time, expiration_time, last_access_time, secure, httponly,
- firstparty, COOKIE_PRIORITY_MEDIUM));
+ same_site, COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsDomainCookie());
EXPECT_FALSE(other_cookie->IsDomainCookie());
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
@@ -325,17 +345,17 @@ TEST(CanonicalCookieTest, IsEquivalentForSecureCookieMatching) {
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_value, ".example.com", cookie_path,
creation_time, expiration_time, last_access_time, secure, httponly,
- firstparty, COOKIE_PRIORITY_MEDIUM));
+ same_site, COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
// Tests that use different variations of attribute values that
// DO affect cookie equivalence. Note that unlike the IsEquivalent tests
// above, this does *not* include tests for differing paths or domains that
// "domain-match".
- other_cookie.reset(new CanonicalCookie(
- url, "B", cookie_value, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
- COOKIE_PRIORITY_MEDIUM));
+ other_cookie.reset(
+ new CanonicalCookie(url, "B", cookie_value, cookie_domain, cookie_path,
+ creation_time, expiration_time, last_access_time,
+ secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM));
EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
}
@@ -353,8 +373,8 @@ TEST(CanonicalCookieTest, IsDomainMatch) {
EXPECT_FALSE(cookie->IsDomainMatch("www0.example.com"));
EXPECT_FALSE(cookie->IsDomainMatch("example.com"));
- cookie.reset(CanonicalCookie::Create(url, "A=2; Domain=www.example.com",
- creation_time, options));
+ cookie = CanonicalCookie::Create(url, "A=2; Domain=www.example.com",
+ creation_time, options);
EXPECT_TRUE(cookie->IsDomainCookie());
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
@@ -362,8 +382,8 @@ TEST(CanonicalCookieTest, IsDomainMatch) {
EXPECT_FALSE(cookie->IsDomainMatch("www0.example.com"));
EXPECT_FALSE(cookie->IsDomainMatch("example.com"));
- cookie.reset(CanonicalCookie::Create(url, "A=2; Domain=.www.example.com",
- creation_time, options));
+ cookie = CanonicalCookie::Create(url, "A=2; Domain=.www.example.com",
+ creation_time, options);
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
EXPECT_TRUE(cookie->IsDomainMatch("foo.www.example.com"));
@@ -384,9 +404,8 @@ TEST(CanonicalCookieTest, IsOnPath) {
// Test the empty string edge case.
EXPECT_FALSE(cookie->IsOnPath(std::string()));
- cookie.reset(
- CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
- "A=2", creation_time, options));
+ cookie = CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
+ "A=2", creation_time, options);
EXPECT_FALSE(cookie->IsOnPath("/"));
EXPECT_TRUE(cookie->IsOnPath("/test"));
EXPECT_TRUE(cookie->IsOnPath("/test/bar.html"));
@@ -412,16 +431,16 @@ TEST(CanonicalCookieTest, IncludeForRequestURL) {
// Test that cookie with a cookie path that does not match the url path are
// not included.
- cookie.reset(CanonicalCookie::Create(url, "A=2; Path=/foo/bar", creation_time,
- options));
+ cookie = CanonicalCookie::Create(url, "A=2; Path=/foo/bar", creation_time,
+ options);
EXPECT_FALSE(cookie->IncludeForRequestURL(url, options));
EXPECT_TRUE(cookie->IncludeForRequestURL(
GURL("http://www.example.com/foo/bar/index.html"), options));
// Test that a secure cookie is not included for a non secure URL.
GURL secure_url("https://www.example.com");
- cookie.reset(CanonicalCookie::Create(secure_url, "A=2; Secure", creation_time,
- options));
+ cookie = CanonicalCookie::Create(secure_url, "A=2; Secure", creation_time,
+ options);
EXPECT_TRUE(cookie->IsSecure());
EXPECT_TRUE(cookie->IncludeForRequestURL(secure_url, options));
EXPECT_FALSE(cookie->IncludeForRequestURL(url, options));
@@ -429,54 +448,49 @@ TEST(CanonicalCookieTest, IncludeForRequestURL) {
// Test that http only cookies are only included if the include httponly flag
// is set on the cookie options.
options.set_include_httponly();
- cookie.reset(
- CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options));
+ cookie =
+ CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options);
EXPECT_TRUE(cookie->IsHttpOnly());
EXPECT_TRUE(cookie->IncludeForRequestURL(url, options));
options.set_exclude_httponly();
EXPECT_FALSE(cookie->IncludeForRequestURL(url, options));
}
-TEST(CanonicalCookieTest, IncludeFirstPartyForFirstPartyURL) {
- GURL insecure_url("http://example.test");
- GURL secure_url("https://example.test");
- GURL secure_url_with_path("https://example.test/foo/bar/index.html");
- GURL third_party_url("https://not-example.test");
+TEST(CanonicalCookieTest, IncludeSameSiteForSameSiteURL) {
+ GURL url("https://example.test");
base::Time creation_time = base::Time::Now();
CookieOptions options;
scoped_ptr<CanonicalCookie> cookie;
- // First-party-only cookies are not included for non-first-party requests,
- // even if other properties match:
- cookie.reset(CanonicalCookie::Create(secure_url, "A=2; First-Party-Only",
- creation_time, options));
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
- EXPECT_FALSE(cookie->IncludeForRequestURL(secure_url, options));
- cookie.reset(CanonicalCookie::Create(
- secure_url, "A=2; Secure; First-Party-Only", creation_time, options));
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
- EXPECT_FALSE(cookie->IncludeForRequestURL(secure_url, options));
- cookie.reset(CanonicalCookie::Create(secure_url_with_path,
- "A=2; First-Party-Only; path=/foo/bar",
- creation_time, options));
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
- EXPECT_FALSE(cookie->IncludeForRequestURL(secure_url, options));
+ // `SameSite=Strict` cookies are included for a URL only if the options'
+ // SameSiteCookieMode is INCLUDE_STRICT_AND_LAX.
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite=Strict", creation_time,
+ options);
+ EXPECT_EQ(CookieSameSite::STRICT_MODE, cookie->SameSite());
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::DO_NOT_INCLUDE);
+ EXPECT_FALSE(cookie->IncludeForRequestURL(url, options));
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_LAX);
+ EXPECT_FALSE(cookie->IncludeForRequestURL(url, options));
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ EXPECT_TRUE(cookie->IncludeForRequestURL(url, options));
- // First-party-only cookies are included for first-party requests:
- options.set_include_first_party_only_cookies();
- cookie.reset(CanonicalCookie::Create(secure_url, "A=2; First-Party-Only",
- creation_time, options));
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
- EXPECT_TRUE(cookie->IncludeForRequestURL(secure_url, options));
- cookie.reset(CanonicalCookie::Create(
- secure_url, "A=2; Secure; First-Party-Only", creation_time, options));
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
- EXPECT_TRUE(cookie->IncludeForRequestURL(secure_url, options));
- cookie.reset(CanonicalCookie::Create(secure_url_with_path,
- "A=2; First-Party-Only; path=/foo/bar",
- creation_time, options));
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
- EXPECT_TRUE(cookie->IncludeForRequestURL(secure_url_with_path, options));
+ // `SameSite=Lax` cookies are included for a URL only if the options'
+ // SameSiteCookieMode is INCLUDE_STRICT_AND_LAX.
+ cookie =
+ CanonicalCookie::Create(url, "A=2; SameSite=Lax", creation_time, options);
+ EXPECT_EQ(CookieSameSite::LAX_MODE, cookie->SameSite());
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::DO_NOT_INCLUDE);
+ EXPECT_FALSE(cookie->IncludeForRequestURL(url, options));
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_LAX);
+ EXPECT_TRUE(cookie->IncludeForRequestURL(url, options));
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ EXPECT_TRUE(cookie->IncludeForRequestURL(url, options));
}
TEST(CanonicalCookieTest, PartialCompare) {
@@ -549,28 +563,24 @@ TEST(CanonicalCookieTest, SecureCookiePrefix) {
CookieOptions options;
// A __Secure- cookie must be Secure.
- EXPECT_EQ(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Secure-A=B", creation_time, options)));
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Secure-A=B; httponly", creation_time, options)));
+ EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B", creation_time,
+ options));
+ EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B; httponly",
+ creation_time, options));
// A typoed prefix does not have to be Secure.
- EXPECT_NE(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__secure-A=B; Secure", creation_time, options)));
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__secure-A=C;", creation_time, options)));
- EXPECT_NE(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__SecureA=B; Secure", creation_time, options)));
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__SecureA=C;", creation_time, options)));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__secure-A=B; Secure",
+ creation_time, options));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__secure-A=C;", creation_time,
+ options));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__SecureA=B; Secure",
+ creation_time, options));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__SecureA=C;", creation_time,
+ options));
// A __Secure- cookie can't be set on a non-secure origin.
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- http_url, "__Secure-A=B; Secure", creation_time, options)));
+ EXPECT_FALSE(CanonicalCookie::Create(http_url, "__Secure-A=B; Secure",
+ creation_time, options));
}
TEST(CanonicalCookieTest, HostCookiePrefix) {
@@ -581,54 +591,44 @@ TEST(CanonicalCookieTest, HostCookiePrefix) {
std::string domain = https_url.host();
// A __Host- cookie must be Secure.
- EXPECT_EQ(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B;", creation_time, options)));
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Domain=" + domain + "; Path=/;",
- creation_time, options)));
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Path=/; Secure;",
- creation_time, options)));
+ EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B;", creation_time,
+ options));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Domain=" + domain + "; Path=/;", creation_time,
+ options));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure;",
+ creation_time, options));
// A __Host- cookie must be set from a secure scheme.
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- http_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
- creation_time, options)));
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Path=/; Secure;",
- creation_time, options)));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ http_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
+ creation_time, options));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure;",
+ creation_time, options));
// A __Host- cookie can't have a Domain.
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
- creation_time, options)));
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Domain=" + domain + "; Secure;",
- creation_time, options)));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
+ creation_time, options));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Domain=" + domain + "; Secure;", creation_time,
+ options));
// A __Host- cookie must have a Path of "/".
- EXPECT_EQ(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Path=/foo; Secure;",
- creation_time, options)));
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Secure;", creation_time, options)));
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Secure; Path=/;",
- creation_time, options)));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Path=/foo; Secure;", creation_time, options));
+ EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B; Secure;",
+ creation_time, options));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Secure; Path=/;",
+ creation_time, options));
// Rules don't apply for a typoed prefix.
- EXPECT_NE(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- http_url, "__host-A=B; Domain=" + domain + "; Path=/; Secure;",
- creation_time, options)));
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__HostA=B; Domain=" + domain + "; Secure;",
- creation_time, options)));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ http_url, "__host-A=B; Domain=" + domain + "; Path=/; Secure;",
+ creation_time, options));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__HostA=B; Domain=" + domain + "; Secure;", creation_time,
+ options));
}
TEST(CanonicalCookieTest, EnforceSecureCookiesRequireSecureScheme) {
@@ -653,21 +653,21 @@ TEST(CanonicalCookieTest, EnforceSecureCookiesRequireSecureScheme) {
EXPECT_TRUE(https_cookie_secure.get());
scoped_ptr<CanonicalCookie> http_cookie_no_secure_extended(
- CanonicalCookie::Create(http_url, "a", "b", "", "", creation_time,
- creation_time, false, false, false, true,
- COOKIE_PRIORITY_DEFAULT));
+ CanonicalCookie::Create(
+ http_url, "a", "b", "", "", creation_time, creation_time, false,
+ false, CookieSameSite::STRICT_MODE, true, COOKIE_PRIORITY_DEFAULT));
scoped_ptr<CanonicalCookie> http_cookie_secure_extended(
- CanonicalCookie::Create(http_url, "a", "b", "", "", creation_time,
- creation_time, true, false, false, true,
- COOKIE_PRIORITY_DEFAULT));
+ CanonicalCookie::Create(
+ http_url, "a", "b", "", "", creation_time, creation_time, true, false,
+ CookieSameSite::STRICT_MODE, true, COOKIE_PRIORITY_DEFAULT));
scoped_ptr<CanonicalCookie> https_cookie_no_secure_extended(
- CanonicalCookie::Create(https_url, "a", "b", "", "", creation_time,
- creation_time, false, false, false, true,
- COOKIE_PRIORITY_DEFAULT));
+ CanonicalCookie::Create(
+ https_url, "a", "b", "", "", creation_time, creation_time, false,
+ false, CookieSameSite::STRICT_MODE, true, COOKIE_PRIORITY_DEFAULT));
scoped_ptr<CanonicalCookie> https_cookie_secure_extended(
- CanonicalCookie::Create(https_url, "a", "b", "", "", creation_time,
- creation_time, true, false, false, true,
- COOKIE_PRIORITY_DEFAULT));
+ CanonicalCookie::Create(
+ https_url, "a", "b", "", "", creation_time, creation_time, true,
+ false, CookieSameSite::STRICT_MODE, true, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(http_cookie_no_secure_extended.get());
EXPECT_FALSE(http_cookie_secure_extended.get());
@@ -683,48 +683,42 @@ TEST(CanonicalCookieTest, TestPrefixHistograms) {
base::Time creation_time = base::Time::Now();
CookieOptions options;
- scoped_ptr<CanonicalCookie> cookie1 = make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B;", creation_time, options));
- EXPECT_EQ(nullptr, cookie1);
+ EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B;", creation_time,
+ options));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 1);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 1);
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Path=/; Secure", creation_time,
- options)));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure",
+ creation_time, options));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 2);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 1);
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__HostA=B; Path=/; Secure", creation_time,
- options)));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__HostA=B; Path=/; Secure",
+ creation_time, options));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 2);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 1);
- scoped_ptr<CanonicalCookie> cookie2 = make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Secure-A=B;", creation_time, options));
- EXPECT_EQ(nullptr, cookie2);
+ EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B;",
+ creation_time, options));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Secure-A=B; Path=/; Secure",
- creation_time, options)));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Secure-A=B; Path=/; Secure",
+ creation_time, options));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 2);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__SecureA=B; Path=/; Secure",
- creation_time, options)));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__SecureA=B; Path=/; Secure",
+ creation_time, options));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 2);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
diff --git a/chromium/net/cookies/cookie_constants.cc b/chromium/net/cookies/cookie_constants.cc
index 05fe22ea437..b618261f8b2 100644
--- a/chromium/net/cookies/cookie_constants.cc
+++ b/chromium/net/cookies/cookie_constants.cc
@@ -10,12 +10,17 @@
namespace net {
namespace {
+
const char kPriorityLow[] = "low";
const char kPriorityMedium[] = "medium";
const char kPriorityHigh[] = "high";
+
+const char kSameSiteLax[] = "lax";
+const char kSameSiteStrict[] = "strict";
+
} // namespace
-NET_EXPORT const std::string CookiePriorityToString(CookiePriority priority) {
+std::string CookiePriorityToString(CookiePriority priority) {
switch(priority) {
case COOKIE_PRIORITY_HIGH:
return kPriorityHigh;
@@ -29,7 +34,7 @@ NET_EXPORT const std::string CookiePriorityToString(CookiePriority priority) {
return std::string();
}
-NET_EXPORT CookiePriority StringToCookiePriority(const std::string& priority) {
+CookiePriority StringToCookiePriority(const std::string& priority) {
std::string priority_comp = base::ToLowerASCII(priority);
if (priority_comp == kPriorityHigh)
@@ -42,4 +47,12 @@ NET_EXPORT CookiePriority StringToCookiePriority(const std::string& priority) {
return COOKIE_PRIORITY_DEFAULT;
}
+CookieSameSite StringToCookieSameSite(const std::string& same_site) {
+ if (base::EqualsCaseInsensitiveASCII(same_site, kSameSiteLax))
+ return CookieSameSite::LAX_MODE;
+ if (base::EqualsCaseInsensitiveASCII(same_site, kSameSiteStrict))
+ return CookieSameSite::STRICT_MODE;
+ return CookieSameSite::DEFAULT_MODE;
+}
+
} // namespace net
diff --git a/chromium/net/cookies/cookie_constants.h b/chromium/net/cookies/cookie_constants.h
index 7e27e14657d..49dafbdb3a1 100644
--- a/chromium/net/cookies/cookie_constants.h
+++ b/chromium/net/cookies/cookie_constants.h
@@ -18,13 +18,27 @@ enum CookiePriority {
COOKIE_PRIORITY_DEFAULT = COOKIE_PRIORITY_MEDIUM
};
+enum class CookieSameSite {
+ NO_RESTRICTION = 0,
+ LAX_MODE = 1,
+ STRICT_MODE = 2,
+ DEFAULT_MODE = NO_RESTRICTION
+};
+
// Returns the Set-Cookie header priority token corresponding to |priority|.
-NET_EXPORT const std::string CookiePriorityToString(CookiePriority priority);
+//
+// TODO(mkwst): Remove this once its callsites are refactored.
+NET_EXPORT std::string CookiePriorityToString(CookiePriority priority);
// Converts the Set-Cookie header priority token |priority| to a CookiePriority.
// Defaults to COOKIE_PRIORITY_DEFAULT for empty or unrecognized strings.
NET_EXPORT CookiePriority StringToCookiePriority(const std::string& priority);
+// Converst the Set-Cookie header SameSite token |same_site| to a
+// CookieSameSite. Defaults to CookieSameSite::DEFAULT_MODE for empty or
+// unrecognized strings.
+NET_EXPORT CookieSameSite StringToCookieSameSite(const std::string& same_site);
+
} // namespace net
#endif // NET_COOKIES_COOKIE_CONSTANTS_H_
diff --git a/chromium/net/cookies/cookie_monster.cc b/chromium/net/cookies/cookie_monster.cc
index 15e4f7ee8e1..aaecaf9a265 100644
--- a/chromium/net/cookies/cookie_monster.cc
+++ b/chromium/net/cookies/cookie_monster.cc
@@ -162,13 +162,10 @@ bool CookieSorter(CanonicalCookie* cc1, CanonicalCookie* cc2) {
bool LRACookieSorter(const CookieMonster::CookieMap::iterator& it1,
const CookieMonster::CookieMap::iterator& it2) {
- // Cookies accessed less recently should be deleted first.
if (it1->second->LastAccessDate() != it2->second->LastAccessDate())
return it1->second->LastAccessDate() < it2->second->LastAccessDate();
- // In rare cases we might have two cookies with identical last access times.
- // To preserve the stability of the sort, in these cases prefer to delete
- // older cookies over newer ones. CreationDate() is guaranteed to be unique.
+ // Ensure stability for == last access times by falling back to creation.
return it1->second->CreationDate() < it2->second->CreationDate();
}
@@ -250,30 +247,6 @@ void SplitCookieVectorIntoSecureAndNonSecure(
}
}
-// Predicate to support PartitionCookieByPriority().
-struct CookiePriorityEqualsTo
- : std::unary_function<const CookieMonster::CookieMap::iterator, bool> {
- explicit CookiePriorityEqualsTo(CookiePriority priority)
- : priority_(priority) {}
-
- bool operator()(const CookieMonster::CookieMap::iterator it) const {
- return it->second->Priority() == priority_;
- }
-
- const CookiePriority priority_;
-};
-
-// For a CookieItVector iterator range [|it_begin|, |it_end|),
-// moves all cookies with a given |priority| to the beginning of the list.
-// Returns: An iterator in [it_begin, it_end) to the first element with
-// priority != |priority|, or |it_end| if all have priority == |priority|.
-CookieMonster::CookieItVector::iterator PartitionCookieByPriority(
- CookieMonster::CookieItVector::iterator it_begin,
- CookieMonster::CookieItVector::iterator it_end,
- CookiePriority priority) {
- return std::partition(it_begin, it_end, CookiePriorityEqualsTo(priority));
-}
-
bool LowerBoundAccessDateComparator(const CookieMonster::CookieMap::iterator it,
const Time& access_date) {
return it->second->LastAccessDate() < access_date;
@@ -328,22 +301,6 @@ ChangeCausePair ChangeCauseMapping[] = {
// DELETE_COOKIE_LAST_ENTRY
{CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT, false}};
-std::string BuildCookieLine(const CanonicalCookieVector& cookies) {
- std::string cookie_line;
- for (CanonicalCookieVector::const_iterator it = cookies.begin();
- it != cookies.end(); ++it) {
- if (it != cookies.begin())
- cookie_line += "; ";
- // In Mozilla if you set a cookie like AAAA, it will have an empty token
- // and a value of AAAA. When it sends the cookie back, it will send AAAA,
- // so we need to avoid sending =AAAA for a blank token value.
- if (!(*it)->Name().empty())
- cookie_line += (*it)->Name() + "=";
- cookie_line += (*it)->Value();
- }
- return cookie_line;
-}
-
void RunAsync(scoped_refptr<base::TaskRunner> proxy,
const CookieStore::CookieChangedCallback& callback,
const CanonicalCookie& cookie,
@@ -355,19 +312,7 @@ void RunAsync(scoped_refptr<base::TaskRunner> proxy,
CookieMonster::CookieMonster(PersistentCookieStore* store,
CookieMonsterDelegate* delegate)
- : initialized_(false),
- started_fetching_all_cookies_(false),
- finished_fetching_all_cookies_(false),
- fetch_strategy_(kUnknownFetch),
- store_(store),
- last_access_threshold_(
- TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)),
- delegate_(delegate),
- last_statistic_record_time_(Time::Now()),
- keep_expired_cookies_(false),
- persist_session_cookies_(false) {
- InitializeHistograms();
- SetDefaultCookieableSchemes();
+ : CookieMonster(store, delegate, kDefaultAccessUpdateThresholdSeconds) {
}
CookieMonster::CookieMonster(PersistentCookieStore* store,
@@ -377,15 +322,18 @@ CookieMonster::CookieMonster(PersistentCookieStore* store,
started_fetching_all_cookies_(false),
finished_fetching_all_cookies_(false),
fetch_strategy_(kUnknownFetch),
+ seen_global_task_(false),
store_(store),
last_access_threshold_(base::TimeDelta::FromMilliseconds(
last_access_threshold_milliseconds)),
delegate_(delegate),
last_statistic_record_time_(base::Time::Now()),
- keep_expired_cookies_(false),
- persist_session_cookies_(false) {
+ persist_session_cookies_(false),
+ weak_ptr_factory_(this) {
InitializeHistograms();
- SetDefaultCookieableSchemes();
+ cookieable_schemes_.insert(
+ cookieable_schemes_.begin(), kDefaultCookieableSchemes,
+ kDefaultCookieableSchemes + kDefaultCookieableSchemesCount);
}
// Task classes for queueing the coming request.
@@ -401,51 +349,23 @@ class CookieMonster::CookieMonsterTask
explicit CookieMonsterTask(CookieMonster* cookie_monster);
virtual ~CookieMonsterTask();
- // Invokes the callback immediately, if the current thread is the one
- // that originated the task, or queues the callback for execution on the
- // appropriate thread. Maintains a reference to this CookieMonsterTask
- // instance until the callback completes.
- void InvokeCallback(base::Closure callback);
-
CookieMonster* cookie_monster() { return cookie_monster_; }
private:
friend class base::RefCountedThreadSafe<CookieMonsterTask>;
CookieMonster* cookie_monster_;
- scoped_refptr<base::SingleThreadTaskRunner> thread_;
DISALLOW_COPY_AND_ASSIGN(CookieMonsterTask);
};
CookieMonster::CookieMonsterTask::CookieMonsterTask(
CookieMonster* cookie_monster)
- : cookie_monster_(cookie_monster),
- thread_(base::ThreadTaskRunnerHandle::Get()) {
-}
+ : cookie_monster_(cookie_monster) {}
CookieMonster::CookieMonsterTask::~CookieMonsterTask() {
}
-// Unfortunately, one cannot re-bind a Callback with parameters into a closure.
-// Therefore, the closure passed to InvokeCallback is a clumsy binding of
-// Callback::Run on a wrapped Callback instance. Since Callback is not
-// reference counted, we bind to an instance that is a member of the
-// CookieMonsterTask subclass. Then, we cannot simply post the callback to a
-// message loop because the underlying instance may be destroyed (along with the
-// CookieMonsterTask instance) in the interim. Therefore, we post a callback
-// bound to the CookieMonsterTask, which *is* reference counted (thus preventing
-// destruction of the original callback), and which invokes the closure (which
-// invokes the original callback with the returned data).
-void CookieMonster::CookieMonsterTask::InvokeCallback(base::Closure callback) {
- if (thread_->BelongsToCurrentThread()) {
- callback.Run();
- } else {
- thread_->PostTask(FROM_HERE, base::Bind(&CookieMonsterTask::InvokeCallback,
- this, callback));
- }
-}
-
// Task class for SetCookieWithDetails call.
class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
public:
@@ -455,11 +375,12 @@ class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
const std::string& value,
const std::string& domain,
const std::string& path,
- const base::Time& expiration_time,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
bool secure,
bool http_only,
- bool first_party_only,
- bool enforce_prefixes,
+ CookieSameSite same_site,
bool enforce_strict_secure,
CookiePriority priority,
const SetCookiesCallback& callback)
@@ -469,11 +390,12 @@ class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
value_(value),
domain_(domain),
path_(path),
+ creation_time_(creation_time),
expiration_time_(expiration_time),
+ last_access_time_(last_access_time),
secure_(secure),
http_only_(http_only),
- first_party_only_(first_party_only),
- enforce_prefixes_(enforce_prefixes),
+ same_site_(same_site),
enforce_strict_secure_(enforce_strict_secure),
priority_(priority),
callback_(callback) {}
@@ -490,11 +412,12 @@ class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
std::string value_;
std::string domain_;
std::string path_;
+ base::Time creation_time_;
base::Time expiration_time_;
+ base::Time last_access_time_;
bool secure_;
bool http_only_;
- bool first_party_only_;
- bool enforce_prefixes_;
+ CookieSameSite same_site_;
bool enforce_strict_secure_;
CookiePriority priority_;
SetCookiesCallback callback_;
@@ -504,13 +427,11 @@ class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
void CookieMonster::SetCookieWithDetailsTask::Run() {
bool success = this->cookie_monster()->SetCookieWithDetails(
- url_, name_, value_, domain_, path_, expiration_time_, secure_,
- http_only_, first_party_only_, enforce_prefixes_, enforce_strict_secure_,
- priority_);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&SetCookiesCallback::Run,
- base::Unretained(&callback_), success));
- }
+ url_, name_, value_, domain_, path_, creation_time_, expiration_time_,
+ last_access_time_, secure_, http_only_, same_site_,
+ enforce_strict_secure_, priority_);
+ if (!callback_.is_null())
+ callback_.Run(success);
}
// Task class for GetAllCookies call.
@@ -535,19 +456,17 @@ class CookieMonster::GetAllCookiesTask : public CookieMonsterTask {
void CookieMonster::GetAllCookiesTask::Run() {
if (!callback_.is_null()) {
CookieList cookies = this->cookie_monster()->GetAllCookies();
- this->InvokeCallback(base::Bind(&GetCookieListCallback::Run,
- base::Unretained(&callback_), cookies));
+ callback_.Run(cookies);
}
}
-// Task class for GetAllCookiesForURLWithOptions call.
-class CookieMonster::GetAllCookiesForURLWithOptionsTask
- : public CookieMonsterTask {
+// Task class for GetCookieListWithOptionsAsync call.
+class CookieMonster::GetCookieListWithOptionsTask : public CookieMonsterTask {
public:
- GetAllCookiesForURLWithOptionsTask(CookieMonster* cookie_monster,
- const GURL& url,
- const CookieOptions& options,
- const GetCookieListCallback& callback)
+ GetCookieListWithOptionsTask(CookieMonster* cookie_monster,
+ const GURL& url,
+ const CookieOptions& options,
+ const GetCookieListCallback& callback)
: CookieMonsterTask(cookie_monster),
url_(url),
options_(options),
@@ -557,22 +476,21 @@ class CookieMonster::GetAllCookiesForURLWithOptionsTask
void Run() override;
protected:
- ~GetAllCookiesForURLWithOptionsTask() override {}
+ ~GetCookieListWithOptionsTask() override {}
private:
GURL url_;
CookieOptions options_;
GetCookieListCallback callback_;
- DISALLOW_COPY_AND_ASSIGN(GetAllCookiesForURLWithOptionsTask);
+ DISALLOW_COPY_AND_ASSIGN(GetCookieListWithOptionsTask);
};
-void CookieMonster::GetAllCookiesForURLWithOptionsTask::Run() {
+void CookieMonster::GetCookieListWithOptionsTask::Run() {
if (!callback_.is_null()) {
CookieList cookies =
- this->cookie_monster()->GetAllCookiesForURLWithOptions(url_, options_);
- this->InvokeCallback(base::Bind(&GetCookieListCallback::Run,
- base::Unretained(&callback_), cookies));
+ this->cookie_monster()->GetCookieListWithOptions(url_, options_);
+ callback_.Run(cookies);
}
}
@@ -603,8 +521,11 @@ class CookieMonster::DeleteTask : public CookieMonsterTask {
private:
// Runs the delete task and returns a result.
virtual Result RunDeleteTask() = 0;
+ // Runs the delete task and then returns a callback to be called after
+ // flushing the persistent store.
+ // TODO(mmenke): This seems like a pretty ugly and needlessly confusing API.
+ // Simplify it?
base::Closure RunDeleteTaskAndBindCallback();
- void FlushDone(const base::Closure& callback);
typename CallbackType<Result>::Type callback_;
@@ -632,36 +553,13 @@ base::Closure CookieMonster::DeleteTask<void>::RunDeleteTaskAndBindCallback() {
template <typename Result>
void CookieMonster::DeleteTask<Result>::Run() {
- this->cookie_monster()->FlushStore(base::Bind(
- &DeleteTask<Result>::FlushDone, this, RunDeleteTaskAndBindCallback()));
-}
-
-template <typename Result>
-void CookieMonster::DeleteTask<Result>::FlushDone(
- const base::Closure& callback) {
+ base::Closure callback = RunDeleteTaskAndBindCallback();
if (!callback.is_null()) {
- this->InvokeCallback(callback);
+ callback = base::Bind(
+ &CookieMonster::RunCallback,
+ this->cookie_monster()->weak_ptr_factory_.GetWeakPtr(), callback);
}
-}
-
-// Task class for DeleteAll call.
-class CookieMonster::DeleteAllTask : public DeleteTask<int> {
- public:
- DeleteAllTask(CookieMonster* cookie_monster, const DeleteCallback& callback)
- : DeleteTask<int>(cookie_monster, callback) {}
-
- // DeleteTask:
- int RunDeleteTask() override;
-
- protected:
- ~DeleteAllTask() override {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DeleteAllTask);
-};
-
-int CookieMonster::DeleteAllTask::RunDeleteTask() {
- return this->cookie_monster()->DeleteAll(true);
+ this->cookie_monster()->FlushStore(callback);
}
// Task class for DeleteAllCreatedBetween call.
@@ -693,30 +591,6 @@ int CookieMonster::DeleteAllCreatedBetweenTask::RunDeleteTask() {
delete_end_);
}
-// Task class for DeleteAllForHost call.
-class CookieMonster::DeleteAllForHostTask : public DeleteTask<int> {
- public:
- DeleteAllForHostTask(CookieMonster* cookie_monster,
- const GURL& url,
- const DeleteCallback& callback)
- : DeleteTask<int>(cookie_monster, callback), url_(url) {}
-
- // DeleteTask:
- int RunDeleteTask() override;
-
- protected:
- ~DeleteAllForHostTask() override {}
-
- private:
- GURL url_;
-
- DISALLOW_COPY_AND_ASSIGN(DeleteAllForHostTask);
-};
-
-int CookieMonster::DeleteAllForHostTask::RunDeleteTask() {
- return this->cookie_monster()->DeleteAllForHost(url_);
-}
-
// Task class for DeleteAllCreatedBetweenForHost call.
class CookieMonster::DeleteAllCreatedBetweenForHostTask
: public DeleteTask<int> {
@@ -751,15 +625,15 @@ int CookieMonster::DeleteAllCreatedBetweenForHostTask::RunDeleteTask() {
}
// Task class for DeleteCanonicalCookie call.
-class CookieMonster::DeleteCanonicalCookieTask : public DeleteTask<bool> {
+class CookieMonster::DeleteCanonicalCookieTask : public DeleteTask<int> {
public:
DeleteCanonicalCookieTask(CookieMonster* cookie_monster,
const CanonicalCookie& cookie,
- const DeleteCookieCallback& callback)
- : DeleteTask<bool>(cookie_monster, callback), cookie_(cookie) {}
+ const DeleteCallback& callback)
+ : DeleteTask<int>(cookie_monster, callback), cookie_(cookie) {}
// DeleteTask:
- bool RunDeleteTask() override;
+ int RunDeleteTask() override;
protected:
~DeleteCanonicalCookieTask() override {}
@@ -770,7 +644,7 @@ class CookieMonster::DeleteCanonicalCookieTask : public DeleteTask<bool> {
DISALLOW_COPY_AND_ASSIGN(DeleteCanonicalCookieTask);
};
-bool CookieMonster::DeleteCanonicalCookieTask::RunDeleteTask() {
+int CookieMonster::DeleteCanonicalCookieTask::RunDeleteTask() {
return this->cookie_monster()->DeleteCanonicalCookie(cookie_);
}
@@ -806,10 +680,8 @@ class CookieMonster::SetCookieWithOptionsTask : public CookieMonsterTask {
void CookieMonster::SetCookieWithOptionsTask::Run() {
bool result = this->cookie_monster()->SetCookieWithOptions(url_, cookie_line_,
options_);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&SetCookiesCallback::Run,
- base::Unretained(&callback_), result));
- }
+ if (!callback_.is_null())
+ callback_.Run(result);
}
// Task class for SetAllCookies call.
@@ -849,10 +721,8 @@ void CookieMonster::SetAllCookiesTask::Run() {
if (positive_diff.size() > 0)
result = this->cookie_monster()->SetCanonicalCookies(list_);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&SetCookiesCallback::Run,
- base::Unretained(&callback_), result));
- }
+ if (!callback_.is_null())
+ callback_.Run(result);
}
// Task class for GetCookiesWithOptions call.
@@ -888,10 +758,8 @@ void CookieMonster::GetCookiesWithOptionsTask::Run() {
"456373 CookieMonster::GetCookiesWithOptionsTask::Run"));
std::string cookie =
this->cookie_monster()->GetCookiesWithOptions(url_, options_);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&GetCookiesCallback::Run,
- base::Unretained(&callback_), cookie));
- }
+ if (!callback_.is_null())
+ callback_.Run(cookie);
}
// Task class for DeleteCookie call.
@@ -951,51 +819,95 @@ void CookieMonster::SetCookieWithDetailsAsync(
const std::string& value,
const std::string& domain,
const std::string& path,
- const Time& expiration_time,
+ Time creation_time,
+ Time expiration_time,
+ Time last_access_time,
bool secure,
bool http_only,
- bool first_party_only,
- bool enforce_prefixes,
+ CookieSameSite same_site,
bool enforce_strict_secure,
CookiePriority priority,
const SetCookiesCallback& callback) {
scoped_refptr<SetCookieWithDetailsTask> task = new SetCookieWithDetailsTask(
- this, url, name, value, domain, path, expiration_time, secure, http_only,
- first_party_only, enforce_prefixes, enforce_strict_secure, priority,
- callback);
+ this, url, name, value, domain, path, creation_time, expiration_time,
+ last_access_time, secure, http_only, same_site, enforce_strict_secure,
+ priority, callback);
DoCookieTaskForURL(task, url);
}
-void CookieMonster::GetAllCookiesAsync(const GetCookieListCallback& callback) {
- scoped_refptr<GetAllCookiesTask> task = new GetAllCookiesTask(this, callback);
+void CookieMonster::FlushStore(const base::Closure& callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (initialized_ && store_.get())
+ store_->Flush(callback);
+ else if (!callback.is_null())
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
+}
+
+void CookieMonster::SetForceKeepSessionState() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (store_)
+ store_->SetForceKeepSessionState();
+}
+void CookieMonster::SetAllCookiesAsync(const CookieList& list,
+ const SetCookiesCallback& callback) {
+ scoped_refptr<SetAllCookiesTask> task =
+ new SetAllCookiesTask(this, list, callback);
DoCookieTask(task);
}
-void CookieMonster::GetAllCookiesForURLWithOptionsAsync(
+void CookieMonster::SetCookieWithOptionsAsync(
const GURL& url,
+ const std::string& cookie_line,
const CookieOptions& options,
- const GetCookieListCallback& callback) {
- scoped_refptr<GetAllCookiesForURLWithOptionsTask> task =
- new GetAllCookiesForURLWithOptionsTask(this, url, options, callback);
+ const SetCookiesCallback& callback) {
+ scoped_refptr<SetCookieWithOptionsTask> task =
+ new SetCookieWithOptionsTask(this, url, cookie_line, options, callback);
DoCookieTaskForURL(task, url);
}
-void CookieMonster::GetAllCookiesForURLAsync(
+void CookieMonster::GetCookiesWithOptionsAsync(
const GURL& url,
+ const CookieOptions& options,
+ const GetCookiesCallback& callback) {
+ scoped_refptr<GetCookiesWithOptionsTask> task =
+ new GetCookiesWithOptionsTask(this, url, options, callback);
+
+ DoCookieTaskForURL(task, url);
+}
+
+void CookieMonster::GetCookieListWithOptionsAsync(
+ const GURL& url,
+ const CookieOptions& options,
const GetCookieListCallback& callback) {
- CookieOptions options;
- options.set_include_httponly();
- options.set_include_first_party_only_cookies();
- scoped_refptr<GetAllCookiesForURLWithOptionsTask> task =
- new GetAllCookiesForURLWithOptionsTask(this, url, options, callback);
+ scoped_refptr<GetCookieListWithOptionsTask> task =
+ new GetCookieListWithOptionsTask(this, url, options, callback);
DoCookieTaskForURL(task, url);
}
-void CookieMonster::DeleteAllAsync(const DeleteCallback& callback) {
- scoped_refptr<DeleteAllTask> task = new DeleteAllTask(this, callback);
+void CookieMonster::GetAllCookiesAsync(const GetCookieListCallback& callback) {
+ scoped_refptr<GetAllCookiesTask> task = new GetAllCookiesTask(this, callback);
+
+ DoCookieTask(task);
+}
+
+void CookieMonster::DeleteCookieAsync(const GURL& url,
+ const std::string& cookie_name,
+ const base::Closure& callback) {
+ scoped_refptr<DeleteCookieTask> task =
+ new DeleteCookieTask(this, url, cookie_name, callback);
+
+ DoCookieTaskForURL(task, url);
+}
+
+void CookieMonster::DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
+ const DeleteCallback& callback) {
+ scoped_refptr<DeleteCanonicalCookieTask> task =
+ new DeleteCanonicalCookieTask(this, cookie, callback);
DoCookieTask(task);
}
@@ -1022,115 +934,74 @@ void CookieMonster::DeleteAllCreatedBetweenForHostAsync(
DoCookieTaskForURL(task, url);
}
-void CookieMonster::DeleteAllForHostAsync(const GURL& url,
- const DeleteCallback& callback) {
- scoped_refptr<DeleteAllForHostTask> task =
- new DeleteAllForHostTask(this, url, callback);
-
- DoCookieTaskForURL(task, url);
-}
-
-void CookieMonster::DeleteCanonicalCookieAsync(
- const CanonicalCookie& cookie,
- const DeleteCookieCallback& callback) {
- scoped_refptr<DeleteCanonicalCookieTask> task =
- new DeleteCanonicalCookieTask(this, cookie, callback);
+void CookieMonster::DeleteSessionCookiesAsync(
+ const CookieStore::DeleteCallback& callback) {
+ scoped_refptr<DeleteSessionCookiesTask> task =
+ new DeleteSessionCookiesTask(this, callback);
DoCookieTask(task);
}
-void CookieMonster::SetAllCookiesAsync(const CookieList& list,
- const SetCookiesCallback& callback) {
- scoped_refptr<SetAllCookiesTask> task =
- new SetAllCookiesTask(this, list, callback);
- DoCookieTask(task);
-}
+void CookieMonster::SetCookieableSchemes(
+ const std::vector<std::string>& schemes) {
+ DCHECK(thread_checker_.CalledOnValidThread());
-void CookieMonster::SetCookieWithOptionsAsync(
- const GURL& url,
- const std::string& cookie_line,
- const CookieOptions& options,
- const SetCookiesCallback& callback) {
- scoped_refptr<SetCookieWithOptionsTask> task =
- new SetCookieWithOptionsTask(this, url, cookie_line, options, callback);
+ // Calls to this method will have no effect if made after a WebView or
+ // CookieManager instance has been created.
+ if (initialized_)
+ return;
- DoCookieTaskForURL(task, url);
+ cookieable_schemes_ = schemes;
}
-void CookieMonster::GetCookiesWithOptionsAsync(
- const GURL& url,
- const CookieOptions& options,
- const GetCookiesCallback& callback) {
- scoped_refptr<GetCookiesWithOptionsTask> task =
- new GetCookiesWithOptionsTask(this, url, options, callback);
-
- DoCookieTaskForURL(task, url);
+// This function must be called before the CookieMonster is used.
+void CookieMonster::SetPersistSessionCookies(bool persist_session_cookies) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!initialized_);
+ persist_session_cookies_ = persist_session_cookies;
}
-void CookieMonster::DeleteCookieAsync(const GURL& url,
- const std::string& cookie_name,
- const base::Closure& callback) {
- scoped_refptr<DeleteCookieTask> task =
- new DeleteCookieTask(this, url, cookie_name, callback);
+bool CookieMonster::IsCookieableScheme(const std::string& scheme) {
+ DCHECK(thread_checker_.CalledOnValidThread());
- DoCookieTaskForURL(task, url);
+ return std::find(cookieable_schemes_.begin(), cookieable_schemes_.end(),
+ scheme) != cookieable_schemes_.end();
}
-void CookieMonster::DeleteSessionCookiesAsync(
- const CookieStore::DeleteCallback& callback) {
- scoped_refptr<DeleteSessionCookiesTask> task =
- new DeleteSessionCookiesTask(this, callback);
+const char* const CookieMonster::kDefaultCookieableSchemes[] = {"http", "https",
+ "ws", "wss"};
+const int CookieMonster::kDefaultCookieableSchemesCount =
+ arraysize(kDefaultCookieableSchemes);
- DoCookieTask(task);
-}
+scoped_ptr<CookieStore::CookieChangedSubscription>
+CookieMonster::AddCallbackForCookie(const GURL& gurl,
+ const std::string& name,
+ const CookieChangedCallback& callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
-void CookieMonster::DoCookieTask(
- const scoped_refptr<CookieMonsterTask>& task_item) {
- {
- base::AutoLock autolock(lock_);
- MarkCookieStoreAsInitialized();
- FetchAllCookiesIfNecessary();
- if (!finished_fetching_all_cookies_ && store_.get()) {
- tasks_pending_.push(task_item);
- return;
- }
- }
+ std::pair<GURL, std::string> key(gurl, name);
+ if (hook_map_.count(key) == 0)
+ hook_map_[key] = make_linked_ptr(new CookieChangedCallbackList());
+ return hook_map_[key]->Add(
+ base::Bind(&RunAsync, base::ThreadTaskRunnerHandle::Get(), callback));
+}
- task_item->Run();
+bool CookieMonster::IsEphemeral() {
+ return store_.get() == nullptr;
}
-void CookieMonster::DoCookieTaskForURL(
- const scoped_refptr<CookieMonsterTask>& task_item,
- const GURL& url) {
- {
- base::AutoLock autolock(lock_);
- MarkCookieStoreAsInitialized();
- if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
- FetchAllCookiesIfNecessary();
- // If cookies for the requested domain key (eTLD+1) have been loaded from DB
- // then run the task, otherwise load from DB.
- if (!finished_fetching_all_cookies_ && store_.get()) {
- // Checks if the domain key has been loaded.
- std::string key(
- cookie_util::GetEffectiveDomain(url.scheme(), url.host()));
- if (keys_loaded_.find(key) == keys_loaded_.end()) {
- std::map<std::string,
- std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it =
- tasks_pending_for_key_.find(key);
- if (it == tasks_pending_for_key_.end()) {
- store_->LoadCookiesForKey(
- key, base::Bind(&CookieMonster::OnKeyLoaded, this, key));
- it = tasks_pending_for_key_
- .insert(std::make_pair(
- key, std::deque<scoped_refptr<CookieMonsterTask>>()))
- .first;
- }
- it->second.push_back(task_item);
- return;
- }
- }
+CookieMonster::~CookieMonster() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // TODO(mmenke): Does it really make sense to run |delegate_| and
+ // CookieChanged callbacks when the CookieStore is destroyed?
+ for (CookieMap::iterator cookie_it = cookies_.begin();
+ cookie_it != cookies_.end();) {
+ CookieMap::iterator current_cookie_it = cookie_it;
+ ++cookie_it;
+ InternalDeleteCookie(current_cookie_it, false /* sync_to_store */,
+ DELETE_COOKIE_DONT_RECORD);
}
- task_item->Run();
}
bool CookieMonster::SetCookieWithDetails(const GURL& url,
@@ -1138,56 +1009,50 @@ bool CookieMonster::SetCookieWithDetails(const GURL& url,
const std::string& value,
const std::string& domain,
const std::string& path,
- const base::Time& expiration_time,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
bool secure,
bool http_only,
- bool first_party_only,
- bool enforce_prefixes,
+ CookieSameSite same_site,
bool enforce_strict_secure,
CookiePriority priority) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!HasCookieableScheme(url))
return false;
- Time creation_time = CurrentTime();
- last_time_seen_ = creation_time;
+ // TODO(mmenke): This class assumes each cookie to have a unique creation
+ // time. Allowing the caller to set the creation time violates that
+ // assumption. Worth fixing? Worth noting that time changes between browser
+ // restarts can cause the same issue.
+ base::Time actual_creation_time = creation_time;
+ if (creation_time.is_null()) {
+ actual_creation_time = CurrentTime();
+ last_time_seen_ = actual_creation_time;
+ }
- scoped_ptr<CanonicalCookie> cc;
- cc.reset(CanonicalCookie::Create(
- url, name, value, domain, path, creation_time, expiration_time, secure,
- http_only, first_party_only, enforce_strict_secure, priority));
+ scoped_ptr<CanonicalCookie> cc(CanonicalCookie::Create(
+ url, name, value, domain, path, actual_creation_time, expiration_time,
+ secure, http_only, same_site, enforce_strict_secure, priority));
if (!cc.get())
return false;
+ if (!last_access_time.is_null())
+ cc->SetLastAccessDate(last_access_time);
+
CookieOptions options;
options.set_include_httponly();
- options.set_include_first_party_only_cookies();
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
if (enforce_strict_secure)
options.set_enforce_strict_secure();
- return SetCanonicalCookie(&cc, creation_time, options);
-}
-
-bool CookieMonster::ImportCookies(const CookieList& list) {
- base::AutoLock autolock(lock_);
- MarkCookieStoreAsInitialized();
- if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
- FetchAllCookiesIfNecessary();
- for (CookieList::const_iterator iter = list.begin(); iter != list.end();
- ++iter) {
- scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(*iter));
- CookieOptions options;
- options.set_include_httponly();
- options.set_include_first_party_only_cookies();
- if (!SetCanonicalCookie(&cookie, cookie->CreationDate(), options))
- return false;
- }
- return true;
+ return SetCanonicalCookie(std::move(cc), options);
}
CookieList CookieMonster::GetAllCookies() {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
// This function is being called to scrape the cookie list for management UI
// or similar. We shouldn't show expired cookies in this list since it will
@@ -1217,16 +1082,19 @@ CookieList CookieMonster::GetAllCookies() {
return cookie_list;
}
-CookieList CookieMonster::GetAllCookiesForURLWithOptions(
+CookieList CookieMonster::GetCookieListWithOptions(
const GURL& url,
const CookieOptions& options) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ CookieList cookies;
+ if (!HasCookieableScheme(url))
+ return cookies;
std::vector<CanonicalCookie*> cookie_ptrs;
- FindCookiesForHostAndDomain(url, options, false, &cookie_ptrs);
+ FindCookiesForHostAndDomain(url, options, &cookie_ptrs);
std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
- CookieList cookies;
cookies.reserve(cookie_ptrs.size());
for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin();
it != cookie_ptrs.end(); it++)
@@ -1235,26 +1103,9 @@ CookieList CookieMonster::GetAllCookiesForURLWithOptions(
return cookies;
}
-int CookieMonster::DeleteAll(bool sync_to_store) {
- base::AutoLock autolock(lock_);
-
- int num_deleted = 0;
- for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
- CookieMap::iterator curit = it;
- ++it;
- InternalDeleteCookie(curit, sync_to_store,
- sync_to_store
- ? DELETE_COOKIE_EXPLICIT
- : DELETE_COOKIE_DONT_RECORD /* Destruction. */);
- ++num_deleted;
- }
-
- return num_deleted;
-}
-
int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin,
const Time& delete_end) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
int num_deleted = 0;
for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
@@ -1276,7 +1127,7 @@ int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin,
int CookieMonster::DeleteAllCreatedBetweenForHost(const Time delete_begin,
const Time delete_end,
const GURL& url) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!HasCookieableScheme(url))
return 0;
@@ -1308,55 +1159,11 @@ int CookieMonster::DeleteAllCreatedBetweenForHost(const Time delete_begin,
return num_deleted;
}
-int CookieMonster::DeleteAllForHost(const GURL& url) {
- return DeleteAllCreatedBetweenForHost(Time(), Time::Max(), url);
-}
-
-bool CookieMonster::DeleteCanonicalCookie(const CanonicalCookie& cookie) {
- base::AutoLock autolock(lock_);
-
- for (CookieMapItPair its = cookies_.equal_range(GetKey(cookie.Domain()));
- its.first != its.second; ++its.first) {
- // The creation date acts as our unique index...
- if (its.first->second->CreationDate() == cookie.CreationDate()) {
- InternalDeleteCookie(its.first, true, DELETE_COOKIE_EXPLICIT);
- return true;
- }
- }
- return false;
-}
-
-void CookieMonster::SetCookieableSchemes(const char* const schemes[],
- size_t num_schemes) {
- base::AutoLock autolock(lock_);
-
- // Calls to this method will have no effect if made after a WebView or
- // CookieManager instance has been created.
- if (initialized_) {
- return;
- }
-
- cookieable_schemes_.clear();
- cookieable_schemes_.insert(cookieable_schemes_.end(), schemes,
- schemes + num_schemes);
-}
-
-void CookieMonster::SetKeepExpiredCookies() {
- keep_expired_cookies_ = true;
-}
-
-void CookieMonster::FlushStore(const base::Closure& callback) {
- base::AutoLock autolock(lock_);
- if (initialized_ && store_.get())
- store_->Flush(callback);
- else if (!callback.is_null())
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
-}
bool CookieMonster::SetCookieWithOptions(const GURL& url,
const std::string& cookie_line,
const CookieOptions& options) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!HasCookieableScheme(url)) {
return false;
@@ -1367,13 +1174,13 @@ bool CookieMonster::SetCookieWithOptions(const GURL& url,
std::string CookieMonster::GetCookiesWithOptions(const GURL& url,
const CookieOptions& options) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!HasCookieableScheme(url))
return std::string();
std::vector<CanonicalCookie*> cookies;
- FindCookiesForHostAndDomain(url, options, true, &cookies);
+ FindCookiesForHostAndDomain(url, options, &cookies);
std::sort(cookies.begin(), cookies.end(), CookieSorter);
std::string cookie_line = BuildCookieLine(cookies);
@@ -1385,26 +1192,26 @@ std::string CookieMonster::GetCookiesWithOptions(const GURL& url,
void CookieMonster::DeleteCookie(const GURL& url,
const std::string& cookie_name) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!HasCookieableScheme(url))
return;
CookieOptions options;
options.set_include_httponly();
- options.set_include_first_party_only_cookies();
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
// Get the cookies for this host and its domain(s).
std::vector<CanonicalCookie*> cookies;
- FindCookiesForHostAndDomain(url, options, true, &cookies);
+ FindCookiesForHostAndDomain(url, options, &cookies);
std::set<CanonicalCookie*> matching_cookies;
- for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
- it != cookies.end(); ++it) {
- if ((*it)->Name() != cookie_name)
+ for (const auto& cookie : cookies) {
+ if (cookie->Name() != cookie_name)
continue;
- if (url.path().find((*it)->Path()))
+ if (!cookie->IsOnPath(url.path()))
continue;
- matching_cookies.insert(*it);
+ matching_cookies.insert(cookie);
}
for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
@@ -1416,50 +1223,25 @@ void CookieMonster::DeleteCookie(const GURL& url,
}
}
-int CookieMonster::DeleteSessionCookies() {
- base::AutoLock autolock(lock_);
+int CookieMonster::DeleteCanonicalCookie(const CanonicalCookie& cookie) {
+ DCHECK(thread_checker_.CalledOnValidThread());
- int num_deleted = 0;
- for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
- CookieMap::iterator curit = it;
- CanonicalCookie* cc = curit->second;
- ++it;
-
- if (!cc->IsPersistent()) {
- InternalDeleteCookie(curit, true, /*sync_to_store*/
- DELETE_COOKIE_EXPIRED);
- ++num_deleted;
+ for (CookieMapItPair its = cookies_.equal_range(GetKey(cookie.Domain()));
+ its.first != its.second; ++its.first) {
+ // The creation date acts as the unique index...
+ if (its.first->second->CreationDate() == cookie.CreationDate()) {
+ InternalDeleteCookie(its.first, true, DELETE_COOKIE_EXPLICIT);
+ return 1;
}
}
-
- return num_deleted;
-}
-
-CookieMonster* CookieMonster::GetCookieMonster() {
- return this;
-}
-
-// This function must be called before the CookieMonster is used.
-void CookieMonster::SetPersistSessionCookies(bool persist_session_cookies) {
- DCHECK(!initialized_);
- persist_session_cookies_ = persist_session_cookies;
-}
-
-void CookieMonster::SetForceKeepSessionState() {
- if (store_.get()) {
- store_->SetForceKeepSessionState();
- }
-}
-
-CookieMonster::~CookieMonster() {
- DeleteAll(false);
+ return 0;
}
bool CookieMonster::SetCookieWithCreationTime(const GURL& url,
const std::string& cookie_line,
const base::Time& creation_time) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!store_.get()) << "This method is only to be used by unit-tests.";
- base::AutoLock autolock(lock_);
if (!HasCookieableScheme(url)) {
return false;
@@ -1473,18 +1255,53 @@ bool CookieMonster::SetCookieWithCreationTime(const GURL& url,
CookieOptions());
}
+int CookieMonster::DeleteSessionCookies() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ int num_deleted = 0;
+ for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
+ CookieMap::iterator curit = it;
+ CanonicalCookie* cc = curit->second;
+ ++it;
+
+ if (!cc->IsPersistent()) {
+ InternalDeleteCookie(curit, true, /*sync_to_store*/
+ DELETE_COOKIE_EXPIRED);
+ ++num_deleted;
+ }
+ }
+
+ return num_deleted;
+}
+
void CookieMonster::MarkCookieStoreAsInitialized() {
+ DCHECK(thread_checker_.CalledOnValidThread());
initialized_ = true;
}
void CookieMonster::FetchAllCookiesIfNecessary() {
+ DCHECK(thread_checker_.CalledOnValidThread());
if (store_.get() && !started_fetching_all_cookies_) {
started_fetching_all_cookies_ = true;
FetchAllCookies();
}
}
+void CookieMonster::FetchAllCookies() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(store_.get()) << "Store must exist to initialize";
+ DCHECK(!finished_fetching_all_cookies_)
+ << "All cookies have already been fetched.";
+
+ // We bind in the current time so that we can report the wall-clock time for
+ // loading cookies.
+ store_->Load(base::Bind(&CookieMonster::OnLoaded,
+ weak_ptr_factory_.GetWeakPtr(), TimeTicks::Now()));
+}
+
bool CookieMonster::ShouldFetchAllCookiesWhenFetchingAnyCookie() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
if (fetch_strategy_ == kUnknownFetch) {
const std::string group_name =
base::FieldTrialList::FindFullName(kCookieMonsterFetchStrategyName);
@@ -1502,18 +1319,9 @@ bool CookieMonster::ShouldFetchAllCookiesWhenFetchingAnyCookie() {
return fetch_strategy_ == kAlwaysFetch;
}
-void CookieMonster::FetchAllCookies() {
- DCHECK(store_.get()) << "Store must exist to initialize";
- DCHECK(!finished_fetching_all_cookies_)
- << "All cookies have already been fetched.";
-
- // We bind in the current time so that we can report the wall-clock time for
- // loading cookies.
- store_->Load(base::Bind(&CookieMonster::OnLoaded, this, TimeTicks::Now()));
-}
-
void CookieMonster::OnLoaded(TimeTicks beginning_time,
const std::vector<CanonicalCookie*>& cookies) {
+ DCHECK(thread_checker_.CalledOnValidThread());
StoreLoadedCookies(cookies);
histogram_time_blocked_on_load_->AddTime(TimeTicks::Now() - beginning_time);
@@ -1523,52 +1331,45 @@ void CookieMonster::OnLoaded(TimeTicks beginning_time,
void CookieMonster::OnKeyLoaded(const std::string& key,
const std::vector<CanonicalCookie*>& cookies) {
- // This function does its own separate locking.
+ DCHECK(thread_checker_.CalledOnValidThread());
+
StoreLoadedCookies(cookies);
- std::deque<scoped_refptr<CookieMonsterTask>> tasks_pending_for_key;
+ auto tasks_pending_for_key = tasks_pending_for_key_.find(key);
- // We need to do this repeatedly until no more tasks were added to the queue
- // during the period where we release the lock.
- while (true) {
- {
- base::AutoLock autolock(lock_);
- std::map<std::string,
- std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it =
- tasks_pending_for_key_.find(key);
- if (it == tasks_pending_for_key_.end()) {
- keys_loaded_.insert(key);
- return;
- }
- if (it->second.empty()) {
- keys_loaded_.insert(key);
- tasks_pending_for_key_.erase(it);
- return;
- }
- it->second.swap(tasks_pending_for_key);
- }
+ // TODO(mmenke): Can this be turned into a DCHECK?
+ if (tasks_pending_for_key == tasks_pending_for_key_.end())
+ return;
- while (!tasks_pending_for_key.empty()) {
- scoped_refptr<CookieMonsterTask> task = tasks_pending_for_key.front();
- task->Run();
- tasks_pending_for_key.pop_front();
- }
+ // Run all tasks for the key. Note that running a task can result in multiple
+ // tasks being added to the back of the deque.
+ while (!tasks_pending_for_key->second.empty()) {
+ scoped_refptr<CookieMonsterTask> task =
+ tasks_pending_for_key->second.front();
+ tasks_pending_for_key->second.pop_front();
+
+ task->Run();
}
+
+ tasks_pending_for_key_.erase(tasks_pending_for_key);
+
+ // This has to be done last, in case running a task queues a new task for the
+ // key, to ensure tasks are run in the correct order.
+ keys_loaded_.insert(key);
}
void CookieMonster::StoreLoadedCookies(
const std::vector<CanonicalCookie*>& cookies) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
// TODO(erikwright): Remove ScopedTracker below once crbug.com/457528 is
// fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"457528 CookieMonster::StoreLoadedCookies"));
- // Initialize the store and sync in any saved persistent cookies. We don't
- // care if it's expired, insert it so it can be garbage collected, removed,
- // and sync'd.
- base::AutoLock autolock(lock_);
-
+ // Even if a key is expired, insert it so it can be garbage collected,
+ // removed, and sync'd.
CookieItVector cookies_with_control_chars;
for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
@@ -1621,25 +1422,36 @@ void CookieMonster::StoreLoadedCookies(
}
void CookieMonster::InvokeQueue() {
- while (true) {
- scoped_refptr<CookieMonsterTask> request_task;
- {
- base::AutoLock autolock(lock_);
- if (tasks_pending_.empty()) {
- finished_fetching_all_cookies_ = true;
- creation_times_.clear();
- keys_loaded_.clear();
- break;
- }
- request_task = tasks_pending_.front();
- tasks_pending_.pop();
- }
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Move all per-key tasks into the global queue, if there are any. This is
+ // protection about a race where the store learns about all cookies loading
+ // before it learned about the cookies for a key loading.
+
+ // Needed to prevent any recursively queued tasks from going back into the
+ // per-key queues.
+ seen_global_task_ = true;
+ for (const auto& tasks_for_key : tasks_pending_for_key_) {
+ tasks_pending_.insert(tasks_pending_.begin(), tasks_for_key.second.begin(),
+ tasks_for_key.second.end());
+ }
+ tasks_pending_for_key_.clear();
+
+ while (!tasks_pending_.empty()) {
+ scoped_refptr<CookieMonsterTask> request_task = tasks_pending_.front();
+ tasks_pending_.pop_front();
request_task->Run();
}
+
+ DCHECK(tasks_pending_for_key_.empty());
+
+ finished_fetching_all_cookies_ = true;
+ creation_times_.clear();
+ keys_loaded_.clear();
}
void CookieMonster::EnsureCookiesMapIsValid() {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
// Iterate through all the of the cookies, grouped by host.
CookieMap::iterator prev_range_end = cookies_.begin();
@@ -1657,7 +1469,7 @@ void CookieMonster::EnsureCookiesMapIsValid() {
void CookieMonster::TrimDuplicateCookiesForKey(const std::string& key,
CookieMap::iterator begin,
CookieMap::iterator end) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
// Set of cookies ordered by creation time.
typedef std::set<CookieMap::iterator, OrderByCreationTimeDesc> CookieSet;
@@ -1729,27 +1541,11 @@ void CookieMonster::TrimDuplicateCookiesForKey(const std::string& key,
DCHECK_EQ(num_duplicates, num_duplicates_found);
}
-// Note: file must be the last scheme.
-const char* const CookieMonster::kDefaultCookieableSchemes[] = {"http",
- "https",
- "ws",
- "wss",
- "file"};
-const int CookieMonster::kDefaultCookieableSchemesCount =
- arraysize(kDefaultCookieableSchemes);
-
-void CookieMonster::SetDefaultCookieableSchemes() {
- // Always disable file scheme unless SetEnableFileScheme(true) is called.
- SetCookieableSchemes(kDefaultCookieableSchemes,
- kDefaultCookieableSchemesCount - 1);
-}
-
void CookieMonster::FindCookiesForHostAndDomain(
const GURL& url,
const CookieOptions& options,
- bool update_access_time,
std::vector<CanonicalCookie*>* cookies) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
const Time current_time(CurrentTime());
@@ -1760,17 +1556,15 @@ void CookieMonster::FindCookiesForHostAndDomain(
// Can just dispatch to FindCookiesForKey
const std::string key(GetKey(url.host()));
- FindCookiesForKey(key, url, options, current_time, update_access_time,
- cookies);
+ FindCookiesForKey(key, url, options, current_time, cookies);
}
void CookieMonster::FindCookiesForKey(const std::string& key,
const GURL& url,
const CookieOptions& options,
const Time& current,
- bool update_access_time,
std::vector<CanonicalCookie*>* cookies) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
for (CookieMapItPair its = cookies_.equal_range(key);
its.first != its.second;) {
@@ -1779,7 +1573,7 @@ void CookieMonster::FindCookiesForKey(const std::string& key,
++its.first;
// If the cookie is expired, delete it.
- if (cc->IsExpired(current) && !keep_expired_cookies_) {
+ if (cc->IsExpired(current)) {
InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
continue;
}
@@ -1792,7 +1586,7 @@ void CookieMonster::FindCookiesForKey(const std::string& key,
// Add this cookie to the set of matching cookies. Update the access
// time if we've been requested to do so.
- if (update_access_time) {
+ if (options.update_access_time()) {
InternalUpdateCookieAccessTime(cc, current);
}
cookies->push_back(cc);
@@ -1804,7 +1598,7 @@ bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key,
bool skip_httponly,
bool already_expired,
bool enforce_strict_secure) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
bool found_equivalent_cookie = false;
bool skipped_httponly = false;
@@ -1867,11 +1661,12 @@ CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
const std::string& key,
CanonicalCookie* cc,
bool sync_to_store) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
// TODO(mkwst): Remove ScopedTracker below once crbug.com/456373 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"456373 CookieMonster::InternalInsertCookie"));
- lock_.AssertAcquired();
if ((cc->IsPersistent() || persist_session_cookies_) && store_.get() &&
sync_to_store)
@@ -1884,11 +1679,12 @@ CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
}
// See InitializeHistograms() for details.
- int32_t cookie_type_sample =
- cc->IsFirstPartyOnly() ? 1 << COOKIE_TYPE_FIRSTPARTYONLY : 0;
- cookie_type_sample |= cc->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0;
- cookie_type_sample |= cc->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0;
- histogram_cookie_type_->Add(cookie_type_sample);
+ int32_t type_sample = cc->SameSite() != CookieSameSite::NO_RESTRICTION
+ ? 1 << COOKIE_TYPE_SAME_SITE
+ : 0;
+ type_sample |= cc->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0;
+ type_sample |= cc->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0;
+ histogram_cookie_type_->Add(type_sample);
// Histogram the type of scheme used on URLs that set cookies. This
// intentionally includes cookies that are set or overwritten by
@@ -1910,7 +1706,7 @@ CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
histogram_cookie_source_scheme_->Add(cookie_source_sample);
}
- RunCallbacks(*cc, false);
+ RunCookieChangedCallbacks(*cc, false);
return inserted;
}
@@ -1920,7 +1716,7 @@ bool CookieMonster::SetCookieWithCreationTimeAndOptions(
const std::string& cookie_line,
const Time& creation_time_or_null,
const CookieOptions& options) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
VLOG(kVlogSetCookies) << "SetCookie() line: " << cookie_line;
@@ -1937,16 +1733,18 @@ bool CookieMonster::SetCookieWithCreationTimeAndOptions(
VLOG(kVlogSetCookies) << "WARNING: Failed to allocate CanonicalCookie";
return false;
}
- return SetCanonicalCookie(&cc, creation_time, options);
+ return SetCanonicalCookie(std::move(cc), options);
}
-bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc,
- const Time& creation_time,
+bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie> cc,
const CookieOptions& options) {
- const std::string key(GetKey((*cc)->Domain()));
- bool already_expired = (*cc)->IsExpired(creation_time);
+ DCHECK(thread_checker_.CalledOnValidThread());
- if (DeleteAnyEquivalentCookie(key, **cc, options.exclude_httponly(),
+ Time creation_time = cc->CreationDate();
+ const std::string key(GetKey(cc->Domain()));
+ bool already_expired = cc->IsExpired(creation_time);
+
+ if (DeleteAnyEquivalentCookie(key, *cc, options.exclude_httponly(),
already_expired,
options.enforce_strict_secure())) {
std::string error;
@@ -1963,21 +1761,18 @@ bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc,
}
VLOG(kVlogSetCookies) << "SetCookie() key: " << key
- << " cc: " << (*cc)->DebugString();
+ << " cc: " << cc->DebugString();
// Realize that we might be setting an expired cookie, and the only point
// was to delete the cookie which we've already done.
- if (!already_expired || keep_expired_cookies_) {
+ if (!already_expired) {
// See InitializeHistograms() for details.
- if ((*cc)->IsPersistent()) {
+ if (cc->IsPersistent()) {
histogram_expiration_duration_minutes_->Add(
- ((*cc)->ExpiryDate() - creation_time).InMinutes());
+ (cc->ExpiryDate() - creation_time).InMinutes());
}
- {
- CanonicalCookie cookie = *(cc->get());
- InternalInsertCookie(key, cc->release(), true);
- }
+ InternalInsertCookie(key, cc.release(), true);
} else {
VLOG(kVlogSetCookies) << "SetCookie() not storing already expired cookie.";
}
@@ -1993,15 +1788,16 @@ bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc,
}
bool CookieMonster::SetCanonicalCookies(const CookieList& list) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
CookieOptions options;
options.set_include_httponly();
- for (CookieList::const_iterator it = list.begin(); it != list.end(); ++it) {
- scoped_ptr<CanonicalCookie> canonical_cookie(new CanonicalCookie(*it));
- if (!SetCanonicalCookie(&canonical_cookie, it->CreationDate(), options))
+ for (const auto& cookie : list) {
+ if (!SetCanonicalCookie(make_scoped_ptr(new CanonicalCookie(cookie)),
+ options)) {
return false;
+ }
}
return true;
@@ -2009,7 +1805,7 @@ bool CookieMonster::SetCanonicalCookies(const CookieList& list) {
void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc,
const Time& current) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
// Based off the Mozilla code. When a cookie has been accessed recently,
// don't bother updating its access time again. This reduces the number of
@@ -2028,7 +1824,7 @@ void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc,
void CookieMonster::InternalDeleteCookie(CookieMap::iterator it,
bool sync_to_store,
DeletionCause deletion_cause) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
// Ideally, this would be asserted up where we define ChangeCauseMapping,
// but DeletionCause's visibility (or lack thereof) forces us to make
@@ -2054,39 +1850,17 @@ void CookieMonster::InternalDeleteCookie(CookieMap::iterator it,
if (mapping.notify)
delegate_->OnCookieChanged(*cc, true, mapping.cause);
}
- RunCallbacks(*cc, true);
+ RunCookieChangedCallbacks(*cc, true);
cookies_.erase(it);
delete cc;
}
-size_t CookieMonster::GarbageCollectLeastRecentlyAccessed(
- const base::Time& current,
- const base::Time& safe_date,
- size_t purge_goal,
- CookieItVector cookie_its) {
- // Sorts up to *and including* |cookie_its[purge_goal]|, so
- // |earliest_access_time| will be properly assigned even if
- // |global_purge_it| == |cookie_its.begin() + purge_goal|.
- SortLeastRecentlyAccessed(cookie_its.begin(), cookie_its.end(), purge_goal);
- // Find boundary to cookies older than safe_date.
- CookieItVector::iterator global_purge_it = LowerBoundAccessDate(
- cookie_its.begin(), cookie_its.begin() + purge_goal, safe_date);
- // Only delete the old cookies, and if strict secure is enabled, delete
- // non-secure ones first.
- size_t num_deleted =
- GarbageCollectDeleteRange(current, DELETE_COOKIE_EVICTED_GLOBAL,
- cookie_its.begin(), global_purge_it);
- // Set access day to the oldest cookie that wasn't deleted.
- earliest_access_time_ = (*global_purge_it)->second->LastAccessDate();
- return num_deleted;
-}
-
// Domain expiry behavior is unchanged by key/expiry scheme (the
// meaning of the key is different, but that's not visible to this routine).
size_t CookieMonster::GarbageCollect(const Time& current,
const std::string& key,
bool enforce_strict_secure) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
size_t num_deleted = 0;
Time safe_date(Time::Now() - TimeDelta::FromDays(kSafeFromGlobalPurgeDays));
@@ -2102,6 +1876,7 @@ size_t CookieMonster::GarbageCollect(const Time& current,
num_deleted +=
GarbageCollectExpired(current, cookies_.equal_range(key), cookie_its);
+ // TODO(mkwst): Soften this.
CookieItVector secure_cookie_its;
if (enforce_strict_secure && cookie_its->size() > kDomainMaxCookies) {
VLOG(kVlogGarbageCollection) << "Garbage collecting non-Secure cookies.";
@@ -2116,56 +1891,27 @@ size_t CookieMonster::GarbageCollect(const Time& current,
cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies);
DCHECK(purge_goal > kDomainPurgeCookies);
- // Boundary iterators into |cookie_its| for different priorities.
- CookieItVector::iterator it_bdd[4];
- // Intialize |it_bdd| while sorting |cookie_its| by priorities.
- // Schematic: [MLLHMHHLMM] => [LLL|MMMM|HHH], with 4 boundaries.
- it_bdd[0] = cookie_its->begin();
- it_bdd[3] = cookie_its->end();
- it_bdd[1] =
- PartitionCookieByPriority(it_bdd[0], it_bdd[3], COOKIE_PRIORITY_LOW);
- it_bdd[2] = PartitionCookieByPriority(it_bdd[1], it_bdd[3],
- COOKIE_PRIORITY_MEDIUM);
- size_t quota[3] = {kDomainCookiesQuotaLow,
- kDomainCookiesQuotaMedium,
- kDomainCookiesQuotaHigh};
-
- // Purge domain cookies in 3 rounds.
- // Round 1: consider low-priority cookies only: evict least-recently
- // accessed, while protecting quota[0] of these from deletion.
- // Round 2: consider {low, medium}-priority cookies, evict least-recently
- // accessed, while protecting quota[0] + quota[1].
- // Round 3: consider all cookies, evict least-recently accessed.
- size_t accumulated_quota = 0;
- CookieItVector::iterator it_purge_begin = it_bdd[0];
- for (int i = 0; i < 3 && purge_goal > 0; ++i) {
- accumulated_quota += quota[i];
-
- size_t num_considered = it_bdd[i + 1] - it_purge_begin;
- if (num_considered <= accumulated_quota)
- continue;
-
- // Number of cookies that will be purged in this round.
- size_t round_goal =
- std::min(purge_goal, num_considered - accumulated_quota);
- purge_goal -= round_goal;
-
- SortLeastRecentlyAccessed(it_purge_begin, it_bdd[i + 1], round_goal);
- // Cookies accessed on or after |safe_date| would have been safe from
- // global purge, and we want to keep track of this.
- CookieItVector::iterator it_purge_end = it_purge_begin + round_goal;
- CookieItVector::iterator it_purge_middle =
- LowerBoundAccessDate(it_purge_begin, it_purge_end, safe_date);
- // Delete cookies accessed before |safe_date|.
- num_deleted += GarbageCollectDeleteRange(
- current, DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE, it_purge_begin,
- it_purge_middle);
- // Delete cookies accessed on or after |safe_date|.
- num_deleted += GarbageCollectDeleteRange(
- current, DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE, it_purge_middle,
- it_purge_end);
- it_purge_begin = it_purge_end;
+ // Sort the cookies by access date, from least-recent to most-recent.
+ std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter);
+
+ // Remove all but the kDomainCookiesQuotaLow most-recently accessed
+ // cookies with low-priority. Then, if cookies still need to be removed,
+ // bump the quota and remove low- and medium-priority. Then, if cookies
+ // _still_ need to be removed, bump the quota and remove cookies with
+ // any priority.
+ const size_t kQuotas[3] = {kDomainCookiesQuotaLow,
+ kDomainCookiesQuotaMedium,
+ kDomainCookiesQuotaHigh};
+ size_t quota = 0;
+ for (size_t i = 0; i < arraysize(kQuotas) && purge_goal > 0; i++) {
+ quota += kQuotas[i];
+ size_t just_deleted = PurgeLeastRecentMatches(
+ cookie_its, static_cast<CookiePriority>(i), quota, purge_goal);
+ DCHECK_LE(just_deleted, purge_goal);
+ purge_goal -= just_deleted;
+ num_deleted += just_deleted;
}
+
DCHECK_EQ(0U, purge_goal);
}
}
@@ -2213,13 +1959,49 @@ size_t CookieMonster::GarbageCollect(const Time& current,
return num_deleted;
}
+size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies,
+ CookiePriority priority,
+ size_t to_protect,
+ size_t purge_goal) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Find the first protected cookie by walking down from the end of the list
+ // cookie list (most-recently accessed) until |to_protect| cookies that match
+ // |priority| are found.
+ size_t protection_boundary = cookies->size();
+ while (to_protect > 0 && protection_boundary > 0) {
+ protection_boundary--;
+ if (cookies->at(protection_boundary)->second->Priority() <= priority)
+ to_protect--;
+ }
+
+ // Now, walk up from the beginning of the list (least-recently accessed) until
+ // |purge_goal| cookies are removed, or the iterator hits
+ // |protection_boundary|.
+ size_t removed = 0;
+ size_t current = 0;
+ while (removed < purge_goal && current < protection_boundary) {
+ if (cookies->at(current)->second->Priority() <= priority) {
+ InternalDeleteCookie(cookies->at(current), true,
+ DELETE_COOKIE_EVICTED_DOMAIN);
+ cookies->erase(cookies->begin() + current);
+ removed++;
+
+ // The call to 'erase' above shifts the contents of the vector, but
+ // doesn't shift |protection_boundary|. Decrement that here to ensure that
+ // the correct set of cookies is protected.
+ protection_boundary--;
+ } else {
+ current++;
+ }
+ }
+ return removed;
+}
+
size_t CookieMonster::GarbageCollectExpired(const Time& current,
const CookieMapItPair& itpair,
CookieItVector* cookie_its) {
- if (keep_expired_cookies_)
- return 0;
-
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
int num_deleted = 0;
for (CookieMap::iterator it = itpair.first, end = itpair.second; it != end;) {
@@ -2240,7 +2022,7 @@ size_t CookieMonster::GarbageCollectExpired(const Time& current,
size_t CookieMonster::GarbageCollectNonSecure(
const CookieItVector& valid_cookies,
CookieItVector* cookie_its) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
size_t num_deleted = 0;
for (const auto& curr_cookie_it : valid_cookies) {
@@ -2260,6 +2042,8 @@ size_t CookieMonster::GarbageCollectDeleteRange(
DeletionCause cause,
CookieItVector::iterator it_begin,
CookieItVector::iterator it_end) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
for (CookieItVector::iterator it = it_begin; it != it_end; it++) {
histogram_evicted_last_access_minutes_->Add(
(current - (*it)->second->LastAccessDate()).InMinutes());
@@ -2268,6 +2052,30 @@ size_t CookieMonster::GarbageCollectDeleteRange(
return it_end - it_begin;
}
+size_t CookieMonster::GarbageCollectLeastRecentlyAccessed(
+ const base::Time& current,
+ const base::Time& safe_date,
+ size_t purge_goal,
+ CookieItVector cookie_its) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Sorts up to *and including* |cookie_its[purge_goal]|, so
+ // |earliest_access_time| will be properly assigned even if
+ // |global_purge_it| == |cookie_its.begin() + purge_goal|.
+ SortLeastRecentlyAccessed(cookie_its.begin(), cookie_its.end(), purge_goal);
+ // Find boundary to cookies older than safe_date.
+ CookieItVector::iterator global_purge_it = LowerBoundAccessDate(
+ cookie_its.begin(), cookie_its.begin() + purge_goal, safe_date);
+ // Only delete the old cookies, and if strict secure is enabled, delete
+ // non-secure ones first.
+ size_t num_deleted =
+ GarbageCollectDeleteRange(current, DELETE_COOKIE_EVICTED_GLOBAL,
+ cookie_its.begin(), global_purge_it);
+ // Set access day to the oldest cookie that wasn't deleted.
+ earliest_access_time_ = (*global_purge_it)->second->LastAccessDate();
+ return num_deleted;
+}
+
// A wrapper around registry_controlled_domains::GetDomainAndRegistry
// to make clear we're creating a key for our local map. Here and
// in FindCookiesForHostAndDomain() are the only two places where
@@ -2292,6 +2100,8 @@ size_t CookieMonster::GarbageCollectDeleteRange(
// be worth it, but is still too much trouble to solve what is currently a
// non-problem).
std::string CookieMonster::GetKey(const std::string& domain) const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
std::string effective_domain(
registry_controlled_domains::GetDomainAndRegistry(
domain, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
@@ -2303,15 +2113,8 @@ std::string CookieMonster::GetKey(const std::string& domain) const {
return effective_domain;
}
-bool CookieMonster::IsCookieableScheme(const std::string& scheme) {
- base::AutoLock autolock(lock_);
-
- return std::find(cookieable_schemes_.begin(), cookieable_schemes_.end(),
- scheme) != cookieable_schemes_.end();
-}
-
bool CookieMonster::HasCookieableScheme(const GURL& url) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
// Make sure the request is on a cookie-able url scheme.
for (size_t i = 0; i < cookieable_schemes_.size(); ++i) {
@@ -2337,6 +2140,8 @@ bool CookieMonster::HasCookieableScheme(const GURL& url) {
// in the constructor so that we won't take statistics right after
// startup, to avoid bias from browsers that are started but not used.
void CookieMonster::RecordPeriodicStats(const base::Time& current_time) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
const base::TimeDelta kRecordStatisticsIntervalTime(
base::TimeDelta::FromSeconds(kRecordStatisticsIntervalSeconds));
@@ -2377,6 +2182,8 @@ void CookieMonster::RecordPeriodicStats(const base::Time& current_time) {
// methods where needed. The specific histogram macro calls on which the
// initialization is based are included in comments below.
void CookieMonster::InitializeHistograms() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
// From UMA_HISTOGRAM_CUSTOM_COUNTS
histogram_expiration_duration_minutes_ = base::Histogram::FactoryGet(
"Cookie.ExpirationDurationMinutes", 1, kMinutesInTenYears, 50,
@@ -2418,10 +2225,70 @@ Time CookieMonster::CurrentTime() {
last_time_seen_.ToInternalValue() + 1));
}
+void CookieMonster::DoCookieTask(
+ const scoped_refptr<CookieMonsterTask>& task_item) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ MarkCookieStoreAsInitialized();
+ FetchAllCookiesIfNecessary();
+ seen_global_task_ = true;
+
+ if (!finished_fetching_all_cookies_ && store_.get()) {
+ tasks_pending_.push_back(task_item);
+ return;
+ }
+
+ task_item->Run();
+}
+
+void CookieMonster::DoCookieTaskForURL(
+ const scoped_refptr<CookieMonsterTask>& task_item,
+ const GURL& url) {
+ MarkCookieStoreAsInitialized();
+ if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
+ FetchAllCookiesIfNecessary();
+
+ // If cookies for the requested domain key (eTLD+1) have been loaded from DB
+ // then run the task, otherwise load from DB.
+ if (!finished_fetching_all_cookies_ && store_.get()) {
+ // If a global task has been previously seen, queue the task as a global
+ // task. Note that the CookieMonster may be in the middle of executing
+ // the global queue, |tasks_pending_| may be empty, which is why another
+ // bool is needed.
+ if (seen_global_task_) {
+ tasks_pending_.push_back(task_item);
+ return;
+ }
+
+ // Checks if the domain key has been loaded.
+ std::string key(cookie_util::GetEffectiveDomain(url.scheme(), url.host()));
+ if (keys_loaded_.find(key) == keys_loaded_.end()) {
+ std::map<std::string,
+ std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it =
+ tasks_pending_for_key_.find(key);
+ if (it == tasks_pending_for_key_.end()) {
+ store_->LoadCookiesForKey(
+ key, base::Bind(&CookieMonster::OnKeyLoaded,
+ weak_ptr_factory_.GetWeakPtr(), key));
+ it = tasks_pending_for_key_
+ .insert(std::make_pair(
+ key, std::deque<scoped_refptr<CookieMonsterTask>>()))
+ .first;
+ }
+ it->second.push_back(task_item);
+ return;
+ }
+ }
+
+ task_item->Run();
+}
+
void CookieMonster::ComputeCookieDiff(CookieList* old_cookies,
CookieList* new_cookies,
CookieList* cookies_to_add,
CookieList* cookies_to_delete) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
DCHECK(old_cookies);
DCHECK(new_cookies);
DCHECK(cookies_to_add);
@@ -2451,45 +2318,23 @@ void CookieMonster::ComputeCookieDiff(CookieList* old_cookies,
FullDiffCookieSorter);
}
-scoped_ptr<CookieStore::CookieChangedSubscription>
-CookieMonster::AddCallbackForCookie(const GURL& gurl,
- const std::string& name,
- const CookieChangedCallback& callback) {
- base::AutoLock autolock(lock_);
- std::pair<GURL, std::string> key(gurl, name);
- if (hook_map_.count(key) == 0)
- hook_map_[key] = make_linked_ptr(new CookieChangedCallbackList());
- return hook_map_[key]->Add(
- base::Bind(&RunAsync, base::ThreadTaskRunnerHandle::Get(), callback));
+void CookieMonster::RunCallback(const base::Closure& callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ callback.Run();
}
-#if defined(OS_ANDROID)
-void CookieMonster::SetEnableFileScheme(bool accept) {
- // This assumes "file" is always at the end of the array. See the comment
- // above kDefaultCookieableSchemes.
- //
- // TODO(mkwst): We're keeping this method around to support the
- // 'CookieManager::setAcceptFileSchemeCookies' method on Android's WebView;
- // if/when we can deprecate and remove that method, we can remove this one
- // as well. Until then, we'll just ensure that the method has no effect on
- // non-android systems.
- int num_schemes = accept ? kDefaultCookieableSchemesCount
- : kDefaultCookieableSchemesCount - 1;
-
- SetCookieableSchemes(kDefaultCookieableSchemes, num_schemes);
-}
-#endif
+void CookieMonster::RunCookieChangedCallbacks(const CanonicalCookie& cookie,
+ bool removed) {
+ DCHECK(thread_checker_.CalledOnValidThread());
-void CookieMonster::RunCallbacks(const CanonicalCookie& cookie, bool removed) {
- lock_.AssertAcquired();
CookieOptions opts;
opts.set_include_httponly();
- opts.set_include_first_party_only_cookies();
- // Note that the callbacks in hook_map_ are wrapped with MakeAsync(), so they
+ opts.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ // Note that the callbacks in hook_map_ are wrapped with RunAsync(), so they
// are guaranteed to not take long - they just post a RunAsync task back to
- // the appropriate thread's message loop and return. It is important that this
- // method not run user-supplied callbacks directly, since the CookieMonster
- // lock is held and it is easy to accidentally introduce deadlocks.
+ // the appropriate thread's message loop and return.
+ // TODO(mmenke): Consider running these synchronously?
for (CookieChangedHookMap::iterator it = hook_map_.begin();
it != hook_map_.end(); ++it) {
std::pair<GURL, std::string> key = it->first;
diff --git a/chromium/net/cookies/cookie_monster.h b/chromium/net/cookies/cookie_monster.h
index 94c3813b4a2..12e04942c8c 100644
--- a/chromium/net/cookies/cookie_monster.h
+++ b/chromium/net/cookies/cookie_monster.h
@@ -24,7 +24,8 @@
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.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/cookies/canonical_cookie.h"
@@ -48,13 +49,8 @@ class ParsedCookie;
// optional permanent storage that implements the PersistentCookieStore
// interface.
//
-// This class IS thread-safe. Normally, it is only used on the I/O thread, but
-// is also accessed directly through Automation for UI testing.
-//
-// All cookie tasks are handled asynchronously. Tasks may be deferred if
-// all affected cookies are not yet loaded from the backing store. Otherwise,
-// the callback may be invoked immediately (prior to return of the asynchronous
-// function).
+// Tasks may be deferred if all affected cookies are not yet loaded from the
+// backing store. Otherwise, callbacks may be invoked immediately.
//
// A cookie task is either pending loading of the entire cookie store, or
// loading of cookies for a specfic domain key(eTLD+1). In the former case, the
@@ -63,8 +59,6 @@ class ParsedCookie;
// task will be queued in tasks_pending_for_key_ while PermanentCookieStore
// loads cookies for the specified domain key(eTLD+1) on DB thread.
//
-// Callbacks are guaranteed to be invoked on the calling thread.
-//
// TODO(deanm) Implement CookieMonster, the cookie database.
// - Verify that our domain enforcement and non-dotted handling is correct
class NET_EXPORT CookieMonster : public CookieStore {
@@ -148,148 +142,66 @@ class NET_EXPORT CookieMonster : public CookieStore {
CookieMonsterDelegate* delegate,
int last_access_threshold_milliseconds);
- // Helper function that adds all cookies from |list| into this instance,
- // overwriting any equivalent cookies.
- bool ImportCookies(const CookieList& list);
+ ~CookieMonster() override;
- typedef base::Callback<void(const CookieList& cookies)> GetCookieListCallback;
- typedef base::Callback<void(bool success)> DeleteCookieCallback;
+ // Replaces all the cookies by |list|. This method does not flush the backend.
+ void SetAllCookiesAsync(const CookieList& list,
+ const SetCookiesCallback& callback);
- // Sets a cookie given explicit user-provided cookie attributes. The cookie
- // name, value, domain, etc. are each provided as separate strings. This
- // function expects each attribute to be well-formed. It will check for
- // disallowed characters (e.g. the ';' character is disallowed within the
- // cookie value attribute) and will return false without setting the cookie
- // if such characters are found.
+ // CookieStore implementation.
+ void SetCookieWithOptionsAsync(const GURL& url,
+ const std::string& cookie_line,
+ const CookieOptions& options,
+ const SetCookiesCallback& callback) override;
void SetCookieWithDetailsAsync(const GURL& url,
const std::string& name,
const std::string& value,
const std::string& domain,
const std::string& path,
- const base::Time& expiration_time,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
bool secure,
bool http_only,
- bool first_party,
- bool enforce_prefixes,
+ CookieSameSite same_site,
bool enforce_strict_secure,
CookiePriority priority,
- const SetCookiesCallback& callback);
-
- // Returns all the cookies, for use in management UI, etc. This does not mark
- // the cookies as having been accessed.
- // The returned cookies are ordered by longest path, then by earliest
- // creation date.
- void GetAllCookiesAsync(const GetCookieListCallback& callback);
-
- // Returns all the cookies, for use in management UI, etc. Filters results
- // using given url scheme, host / domain and path and options. This does not
- // mark the cookies as having been accessed.
- // The returned cookies are ordered by longest path, then earliest
- // creation date.
- void GetAllCookiesForURLWithOptionsAsync(
- const GURL& url,
- const CookieOptions& options,
- const GetCookieListCallback& callback);
-
- // Deletes all of the cookies.
- void DeleteAllAsync(const DeleteCallback& callback);
-
- // Deletes all cookies that match the host of the given URL
- // regardless of path. This includes all http_only and secure cookies,
- // but does not include any domain cookies that may apply to this host.
- // Returns the number of cookies deleted.
- void DeleteAllForHostAsync(const GURL& url, const DeleteCallback& callback);
-
- // Deletes one specific cookie.
- void DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
- const DeleteCookieCallback& callback);
-
- // Resets the list of cookieable schemes to the supplied schemes. Does
- // nothing if called after first use of the instance (i.e. after the
- // instance initialization process).
- void SetCookieableSchemes(const char* const schemes[], size_t num_schemes);
-
- // Instructs the cookie monster to not delete expired cookies. This is used
- // in cases where the cookie monster is used as a data structure to keep
- // arbitrary cookies.
- void SetKeepExpiredCookies();
-
- // Protects session cookies from deletion on shutdown.
- void SetForceKeepSessionState();
-
- // Flush the backing store (if any) to disk and post the given callback when
- // done.
- // WARNING: THE CALLBACK WILL RUN ON A RANDOM THREAD. IT MUST BE THREAD SAFE.
- // It may be posted to the current thread, or it may run on the thread that
- // actually does the flushing. Your Task should generally post a notification
- // to the thread you actually want to be notified on.
- void FlushStore(const base::Closure& callback);
-
- // Replaces all the cookies by |list|. This method does not flush the backend.
- void SetAllCookiesAsync(const CookieList& list,
- const SetCookiesCallback& callback);
-
- // CookieStore implementation.
-
- // Sets the cookies specified by |cookie_list| returned from |url|
- // with options |options| in effect.
- void SetCookieWithOptionsAsync(const GURL& url,
- const std::string& cookie_line,
- const CookieOptions& options,
const SetCookiesCallback& callback) override;
-
- // Gets all cookies that apply to |url| given |options|.
- // The returned cookies are ordered by longest path, then earliest
- // creation date.
void GetCookiesWithOptionsAsync(const GURL& url,
const CookieOptions& options,
const GetCookiesCallback& callback) override;
-
- // Invokes GetAllCookiesForURLWithOptions with options set to include HTTP
- // only cookies.
- void GetAllCookiesForURLAsync(const GURL& url,
- const GetCookieListCallback& callback) override;
-
- // Deletes all cookies with that might apply to |url| that has |cookie_name|.
+ void GetCookieListWithOptionsAsync(
+ const GURL& url,
+ const CookieOptions& options,
+ const GetCookieListCallback& callback) override;
+ void GetAllCookiesAsync(const GetCookieListCallback& callback) override;
void DeleteCookieAsync(const GURL& url,
const std::string& cookie_name,
const base::Closure& callback) override;
-
- // Deletes all of the cookies that have a creation_date greater than or equal
- // to |delete_begin| and less than |delete_end|.
- // Returns the number of cookies that have been deleted.
+ void DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
+ const DeleteCallback& callback) override;
void DeleteAllCreatedBetweenAsync(const base::Time& delete_begin,
const base::Time& delete_end,
const DeleteCallback& callback) override;
-
- // Deletes all of the cookies that match the host of the given URL
- // regardless of path and that have a creation_date greater than or
- // equal to |delete_begin| and less then |delete_end|. This includes
- // all http_only and secure cookies, but does not include any domain
- // cookies that may apply to this host.
- // Returns the number of cookies deleted.
void DeleteAllCreatedBetweenForHostAsync(
const base::Time delete_begin,
const base::Time delete_end,
const GURL& url,
const DeleteCallback& callback) override;
-
void DeleteSessionCookiesAsync(const DeleteCallback&) override;
+ void FlushStore(const base::Closure& callback) override;
+ void SetForceKeepSessionState() override;
- CookieMonster* GetCookieMonster() override;
+ // Resets the list of cookieable schemes to the supplied schemes. Does
+ // nothing if called after first use of the instance (i.e. after the
+ // instance initialization process).
+ void SetCookieableSchemes(const std::vector<std::string>& schemes);
// Enables writing session cookies into the cookie database. If this this
// method is called, it must be called before first use of the instance
// (i.e. as part of the instance initialization process).
void SetPersistSessionCookies(bool persist_session_cookies);
- // Debugging method to perform various validation checks on the map.
- // Currently just checking that there are no null CanonicalCookie pointers
- // in the map.
- // Argument |arg| is to allow retaining of arbitrary data if the CHECKs
- // in the function trip. TODO(rdsmith):Remove hack.
- void ValidateMap(int arg);
-
// Determines if the scheme of the URL is a scheme that cookies will be
// stored for.
bool IsCookieableScheme(const std::string& scheme);
@@ -303,21 +215,7 @@ class NET_EXPORT CookieMonster : public CookieStore {
const std::string& name,
const CookieChangedCallback& callback) override;
-#if defined(OS_ANDROID)
- // Resets the list of cookieable schemes to kDefaultCookieableSchemes with or
- // without 'file' being included.
- //
- // There are some unknowns about how to correctly handle file:// cookies,
- // and our implementation for this is not robust enough (Bug 1157243).
- // This allows you to enable support, and is exposed as a public WebView
- // API ('CookieManager::setAcceptFileSchemeCookies').
- //
- // TODO(mkwst): This method will be removed once we can deprecate and remove
- // the Android WebView 'CookieManager::setAcceptFileSchemeCookies' method.
- // Until then, this method only has effect on Android, and must not be used
- // outside a WebView context.
- void SetEnableFileScheme(bool accept);
-#endif
+ bool IsEphemeral() override;
private:
// For queueing the cookie monster calls.
@@ -326,13 +224,12 @@ class NET_EXPORT CookieMonster : public CookieStore {
class DeleteTask;
class DeleteAllCreatedBetweenTask;
class DeleteAllCreatedBetweenForHostTask;
- class DeleteAllForHostTask;
- class DeleteAllTask;
class DeleteCookieTask;
class DeleteCanonicalCookieTask;
- class GetAllCookiesForURLWithOptionsTask;
+ class GetCookieListForURLWithOptionsTask;
class GetAllCookiesTask;
class GetCookiesWithOptionsTask;
+ class GetCookieListWithOptionsTask;
class SetAllCookiesTask;
class SetCookieWithDetailsTask;
class SetCookieWithOptionsTask;
@@ -342,9 +239,6 @@ class NET_EXPORT CookieMonster : public CookieStore {
// For SetCookieWithCreationTime.
FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest,
TestCookieDeleteAllCreatedBetweenTimestamps);
- // For SetCookieWithCreationTime.
- FRIEND_TEST_ALL_PREFIXES(MultiThreadedCookieMonsterTest,
- ThreadCheckDeleteAllCreatedBetweenForHost);
// For gargage collection constants.
FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestHostGarbageCollection);
@@ -386,37 +280,37 @@ class NET_EXPORT CookieMonster : public CookieStore {
// at the end of the list, just before DELETE_COOKIE_LAST_ENTRY.
enum DeletionCause {
DELETE_COOKIE_EXPLICIT = 0,
- DELETE_COOKIE_OVERWRITE,
- DELETE_COOKIE_EXPIRED,
- DELETE_COOKIE_EVICTED,
- DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE,
- DELETE_COOKIE_DONT_RECORD, // e.g. For final cleanup after flush to store.
- DELETE_COOKIE_EVICTED_DOMAIN,
- DELETE_COOKIE_EVICTED_GLOBAL,
-
- // Cookies evicted during domain level garbage collection that
- // were accessed longer ago than kSafeFromGlobalPurgeDays
- DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE,
-
- // Cookies evicted during domain level garbage collection that
- // were accessed more recently than kSafeFromGlobalPurgeDays
- // (and thus would have been preserved by global garbage collection).
- DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE,
+ DELETE_COOKIE_OVERWRITE = 1,
+ DELETE_COOKIE_EXPIRED = 2,
+ DELETE_COOKIE_EVICTED = 3,
+ DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE = 4,
+ DELETE_COOKIE_DONT_RECORD = 5, // For final cleanup after flush to store.
+
+ // Cookies evicted during domain-level garbage collection.
+ DELETE_COOKIE_EVICTED_DOMAIN = 6,
+
+ // Cookies evicted during global garbage collection (which takes place after
+ // domain-level garbage collection fails to bring the cookie store under
+ // the overall quota.
+ DELETE_COOKIE_EVICTED_GLOBAL = 7,
+
+ // #8 was DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE
+ // #9 was DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE
// A common idiom is to remove a cookie by overwriting it with an
// already-expired expiration date. This captures that case.
- DELETE_COOKIE_EXPIRED_OVERWRITE,
+ DELETE_COOKIE_EXPIRED_OVERWRITE = 10,
// Cookies are not allowed to contain control characters in the name or
// value. However, we used to allow them, so we are now evicting any such
// cookies as we load them. See http://crbug.com/238041.
- DELETE_COOKIE_CONTROL_CHAR,
+ DELETE_COOKIE_CONTROL_CHAR = 11,
// When strict secure cookies is enabled, non-secure cookies are evicted
// right after expired cookies.
- DELETE_COOKIE_NON_SECURE,
+ DELETE_COOKIE_NON_SECURE = 12,
- DELETE_COOKIE_LAST_ENTRY
+ DELETE_COOKIE_LAST_ENTRY = 13
};
// This enum is used to generate a histogramed bitmask measureing the types
@@ -424,7 +318,7 @@ class NET_EXPORT CookieMonster : public CookieStore {
// New items MUST be added at the end of the list, just before
// COOKIE_TYPE_LAST_ENTRY;
enum CookieType {
- COOKIE_TYPE_FIRSTPARTYONLY = 0,
+ COOKIE_TYPE_SAME_SITE = 0,
COOKIE_TYPE_HTTPONLY,
COOKIE_TYPE_SECURE,
COOKIE_TYPE_LAST_ENTRY
@@ -487,8 +381,6 @@ class NET_EXPORT CookieMonster : public CookieStore {
// Record statistics every kRecordStatisticsIntervalSeconds of uptime.
static const int kRecordStatisticsIntervalSeconds = 10 * 60;
- ~CookieMonster() override;
-
// The following are synchronous calls to which the asynchronous methods
// delegate either immediately (if the store is loaded) or through a deferred
// task (if the store is not yet loaded).
@@ -497,31 +389,27 @@ class NET_EXPORT CookieMonster : public CookieStore {
const std::string& value,
const std::string& domain,
const std::string& path,
- const base::Time& expiration_time,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
bool secure,
bool http_only,
- bool first_party,
- bool enforce_prefixes,
+ CookieSameSite same_site,
bool enforce_strict_secure,
CookiePriority priority);
CookieList GetAllCookies();
- CookieList GetAllCookiesForURLWithOptions(const GURL& url,
- const CookieOptions& options);
-
- int DeleteAll(bool sync_to_store);
+ CookieList GetCookieListWithOptions(const GURL& url,
+ const CookieOptions& options);
int DeleteAllCreatedBetween(const base::Time& delete_begin,
const base::Time& delete_end);
- int DeleteAllForHost(const GURL& url);
int DeleteAllCreatedBetweenForHost(const base::Time delete_begin,
const base::Time delete_end,
const GURL& url);
- bool DeleteCanonicalCookie(const CanonicalCookie& cookie);
-
bool SetCookieWithOptions(const GURL& url,
const std::string& cookie_line,
const CookieOptions& options);
@@ -531,6 +419,8 @@ class NET_EXPORT CookieMonster : public CookieStore {
void DeleteCookie(const GURL& url, const std::string& cookie_name);
+ int DeleteCanonicalCookie(const CanonicalCookie& cookie);
+
bool SetCookieWithCreationTime(const GURL& url,
const std::string& cookie_line,
const base::Time& creation_time);
@@ -543,11 +433,9 @@ class NET_EXPORT CookieMonster : public CookieStore {
// Fetches all cookies if the backing store exists and they're not already
// being fetched.
- // Note: this method should always be called with lock_ held.
void FetchAllCookiesIfNecessary();
// Fetches all cookies from the backing store.
- // Note: this method should always be called with lock_ held.
void FetchAllCookies();
// Whether all cookies should be fetched as soon as any is requested.
@@ -588,14 +476,12 @@ class NET_EXPORT CookieMonster : public CookieStore {
void FindCookiesForHostAndDomain(const GURL& url,
const CookieOptions& options,
- bool update_access_time,
std::vector<CanonicalCookie*>* cookies);
void FindCookiesForKey(const std::string& key,
const GURL& url,
const CookieOptions& options,
const base::Time& current,
- bool update_access_time,
std::vector<CanonicalCookie*>* cookies);
// Delete any cookies that are equivalent to |ecc| (same path, domain, etc).
@@ -628,8 +514,7 @@ class NET_EXPORT CookieMonster : public CookieStore {
// Helper function that sets a canonical cookie, deleting equivalents and
// performing garbage collection.
- bool SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc,
- const base::Time& creation_time,
+ bool SetCanonicalCookie(scoped_ptr<CanonicalCookie> cc,
const CookieOptions& options);
// Helper function calling SetCanonicalCookie() for all cookies in |list|.
@@ -656,6 +541,18 @@ class NET_EXPORT CookieMonster : public CookieStore {
const std::string& key,
bool enforce_strict_secure);
+ // Helper for GarbageCollect(). Deletes up to |purge_goal| cookies with a
+ // priority less than or equal to |priority| from |cookies|, while ensuring
+ // that at least the |to_protect| most-recent cookies are retained.
+ //
+ // |cookies| must be sorted from least-recent to most-recent.
+ //
+ // Returns the number of cookies deleted.
+ size_t PurgeLeastRecentMatches(CookieItVector* cookies,
+ CookiePriority priority,
+ size_t to_protect,
+ size_t purge_goal);
+
// Helper for GarbageCollect(); can be called directly as well. Deletes all
// expired cookies in |itpair|. If |cookie_its| is non-NULL, all the
// non-expired cookies from |itpair| are appended to |cookie_its|.
@@ -727,9 +624,13 @@ class NET_EXPORT CookieMonster : public CookieStore {
CookieList* cookies_to_add,
CookieList* cookies_to_delete);
+ // Runs the given callback. Used to avoid running callbacks after the store
+ // has been destroyed.
+ void RunCallback(const base::Closure& callback);
+
// Run all cookie changed callbacks that are monitoring |cookie|.
// |removed| is true if the cookie was deleted.
- void RunCallbacks(const CanonicalCookie& cookie, bool removed);
+ void RunCookieChangedCallbacks(const CanonicalCookie& cookie, bool removed);
// Histogram variables; see CookieMonster::InitializeHistograms() in
// cookie_monster.cc for details.
@@ -765,7 +666,14 @@ class NET_EXPORT CookieMonster : public CookieStore {
// Queues tasks that are blocked until all cookies are loaded from the backend
// store.
- std::queue<scoped_refptr<CookieMonsterTask>> tasks_pending_;
+ std::deque<scoped_refptr<CookieMonsterTask>> tasks_pending_;
+
+ // Once a global cookie task has been seen, all per-key tasks must be put in
+ // |tasks_pending_| instead of |tasks_pending_for_key_| to ensure a reasonable
+ // view of the cookie store. This more to ensure fancy cookie export/import
+ // code has a consistent view of the CookieStore, rather than out of concern
+ // for typical use.
+ bool seen_global_task_;
scoped_refptr<PersistentCookieStore> store_;
@@ -796,23 +704,18 @@ class NET_EXPORT CookieMonster : public CookieStore {
scoped_refptr<CookieMonsterDelegate> delegate_;
- // Lock for thread-safety
- base::Lock lock_;
-
base::Time last_statistic_record_time_;
- bool keep_expired_cookies_;
bool persist_session_cookies_;
- // Static setting for whether or not file scheme cookies are allows when
- // a new CookieMonster is created, or the accepted schemes on a CookieMonster
- // instance are reset back to defaults.
- static bool default_enable_file_scheme_;
-
typedef std::map<std::pair<GURL, std::string>,
linked_ptr<CookieChangedCallbackList>> CookieChangedHookMap;
CookieChangedHookMap hook_map_;
+ base::ThreadChecker thread_checker_;
+
+ base::WeakPtrFactory<CookieMonster> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(CookieMonster);
};
@@ -869,6 +772,8 @@ class NET_EXPORT CookieMonster::PersistentCookieStore
// Initializes the store and retrieves the existing cookies. This will be
// called only once at startup. The callback will return all the cookies
// that are not yet returned to CookieMonster by previous priority loads.
+ //
+ // |loaded_callback| may not be NULL.
virtual void Load(const LoadedCallback& loaded_callback) = 0;
// Does a priority load of all cookies for the domain key (eTLD+1). The
@@ -876,6 +781,8 @@ class NET_EXPORT CookieMonster::PersistentCookieStore
// loads, which includes cookies for the requested domain key if they are not
// already returned, plus all cookies that are chain-loaded and not yet
// returned to CookieMonster.
+ //
+ // |loaded_callback| may not be NULL.
virtual void LoadCookiesForKey(const std::string& key,
const LoadedCallback& loaded_callback) = 0;
@@ -886,7 +793,8 @@ class NET_EXPORT CookieMonster::PersistentCookieStore
// Instructs the store to not discard session only cookies on shutdown.
virtual void SetForceKeepSessionState() = 0;
- // Flushes the store and posts |callback| when complete.
+ // Flushes the store and posts |callback| when complete. |callback| may be
+ // NULL.
virtual void Flush(const base::Closure& callback) = 0;
protected:
diff --git a/chromium/net/cookies/cookie_monster_perftest.cc b/chromium/net/cookies/cookie_monster_perftest.cc
index dd35638ead3..1dcb2769733 100644
--- a/chromium/net/cookies/cookie_monster_perftest.cc
+++ b/chromium/net/cookies/cookie_monster_perftest.cc
@@ -5,6 +5,8 @@
#include <algorithm>
#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -119,7 +121,7 @@ TEST(ParsedCookieTest, TestParseBigCookies) {
}
TEST_F(CookieMonsterTest, TestAddCookiesOnSingleHost) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
std::vector<std::string> cookies;
for (int i = 0; i < kNumCookies; i++) {
cookies.push_back(base::StringPrintf("a%03d=b", i));
@@ -152,7 +154,7 @@ TEST_F(CookieMonsterTest, TestAddCookiesOnSingleHost) {
}
TEST_F(CookieMonsterTest, TestAddCookieOnManyHosts) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
std::string cookie(kCookieLine);
std::vector<GURL> gurls; // just wanna have ffffuunnn
for (int i = 0; i < kNumCookies; ++i) {
@@ -185,7 +187,7 @@ TEST_F(CookieMonsterTest, TestAddCookieOnManyHosts) {
}
TEST_F(CookieMonsterTest, TestDomainTree) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
GetCookiesCallback getCookiesCallback;
SetCookieCallback setCookieCallback;
const char domain_cookie_format_tree[] = "a=b; domain=%s";
@@ -238,7 +240,7 @@ TEST_F(CookieMonsterTest, TestDomainTree) {
}
TEST_F(CookieMonsterTest, TestDomainLine) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
SetCookieCallback setCookieCallback;
GetCookiesCallback getCookiesCallback;
std::vector<std::string> domain_list;
@@ -287,8 +289,7 @@ TEST_F(CookieMonsterTest, TestImport) {
int64_t time_tick(base::Time::Now().ToInternalValue());
for (int domain_num = 0; domain_num < 300; domain_num++) {
- std::string domain_name(base::StringPrintf(".Domain_%d.com", domain_num));
- std::string gurl("www" + domain_name);
+ GURL gurl(base::StringPrintf("http://www.Domain_%d.com", domain_num));
for (int cookie_num = 0; cookie_num < 50; cookie_num++) {
std::string cookie_line(
base::StringPrintf("Cookie_%d=1; Path=/", cookie_num));
@@ -300,7 +301,7 @@ TEST_F(CookieMonsterTest, TestImport) {
store->SetLoadExpectation(true, initial_cookies);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
// Import will happen on first access.
GURL gurl("www.google.com");
@@ -314,7 +315,7 @@ TEST_F(CookieMonsterTest, TestImport) {
}
TEST_F(CookieMonsterTest, TestGetKey) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
base::PerfTimeLogger timer("Cookie_monster_get_key");
for (int i = 0; i < kNumCookies; i++)
cm->GetKey("www.google.com");
@@ -370,9 +371,9 @@ TEST_F(CookieMonsterTest, TestGCTimes) {
};
for (int ci = 0; ci < static_cast<int>(arraysize(test_cases)); ++ci) {
const TestCase& test_case(test_cases[ci]);
- scoped_refptr<CookieMonster> cm(CreateMonsterFromStoreForGC(
+ scoped_ptr<CookieMonster> cm = CreateMonsterFromStoreForGC(
test_case.num_cookies, test_case.num_old_cookies, 0, 0,
- CookieMonster::kSafeFromGlobalPurgeDays * 2));
+ CookieMonster::kSafeFromGlobalPurgeDays * 2);
GURL gurl("http://google.com");
std::string cookie_line("z=3");
diff --git a/chromium/net/cookies/cookie_monster_store_test.cc b/chromium/net/cookies/cookie_monster_store_test.cc
index 8c004ef6140..4573d4ad881 100644
--- a/chromium/net/cookies/cookie_monster_store_test.cc
+++ b/chromium/net/cookies/cookie_monster_store_test.cc
@@ -17,6 +17,7 @@
#include "url/gurl.h"
namespace net {
+
LoadedCallbackTask::LoadedCallbackTask(LoadedCallback loaded_callback,
std::vector<CanonicalCookie*> cookies)
: loaded_callback_(loaded_callback), cookies_(cookies) {
@@ -25,9 +26,22 @@ LoadedCallbackTask::LoadedCallbackTask(LoadedCallback loaded_callback,
LoadedCallbackTask::~LoadedCallbackTask() {
}
+CookieStoreCommand::CookieStoreCommand(
+ Type type,
+ const CookieMonster::PersistentCookieStore::LoadedCallback& loaded_callback,
+ const std::string& key)
+ : type(type), loaded_callback(loaded_callback), key(key) {}
+
+CookieStoreCommand::CookieStoreCommand(Type type, const CanonicalCookie& cookie)
+ : type(type), cookie(cookie) {}
+
+CookieStoreCommand::CookieStoreCommand(const CookieStoreCommand& other) =
+ default;
+
+CookieStoreCommand::~CookieStoreCommand() {}
+
MockPersistentCookieStore::MockPersistentCookieStore()
- : load_return_value_(true), loaded_(false) {
-}
+ : store_load_commands_(false), load_return_value_(true), loaded_(false) {}
void MockPersistentCookieStore::SetLoadExpectation(
bool return_value,
@@ -37,6 +51,11 @@ void MockPersistentCookieStore::SetLoadExpectation(
}
void MockPersistentCookieStore::Load(const LoadedCallback& loaded_callback) {
+ if (store_load_commands_) {
+ commands_.push_back(
+ CookieStoreCommand(CookieStoreCommand::LOAD, loaded_callback, ""));
+ return;
+ }
std::vector<CanonicalCookie*> out_cookies;
if (load_return_value_) {
out_cookies = load_result_;
@@ -51,6 +70,11 @@ void MockPersistentCookieStore::Load(const LoadedCallback& loaded_callback) {
void MockPersistentCookieStore::LoadCookiesForKey(
const std::string& key,
const LoadedCallback& loaded_callback) {
+ if (store_load_commands_) {
+ commands_.push_back(CookieStoreCommand(
+ CookieStoreCommand::LOAD_COOKIES_FOR_KEY, loaded_callback, key));
+ return;
+ }
if (!loaded_) {
Load(loaded_callback);
} else {
@@ -68,8 +92,6 @@ void MockPersistentCookieStore::AddCookie(const CanonicalCookie& cookie) {
void MockPersistentCookieStore::UpdateCookieAccessTime(
const CanonicalCookie& cookie) {
- commands_.push_back(
- CookieStoreCommand(CookieStoreCommand::UPDATE_ACCESS_TIME, cookie));
}
void MockPersistentCookieStore::DeleteCookie(const CanonicalCookie& cookie) {
@@ -101,9 +123,10 @@ void MockCookieMonsterDelegate::OnCookieChanged(
MockCookieMonsterDelegate::~MockCookieMonsterDelegate() {
}
-CanonicalCookie BuildCanonicalCookie(const std::string& key,
- const std::string& cookie_line,
- const base::Time& creation_time) {
+scoped_ptr<CanonicalCookie> BuildCanonicalCookie(
+ const GURL& url,
+ const std::string& cookie_line,
+ const base::Time& creation_time) {
// Parse the cookie line.
ParsedCookie pc(cookie_line);
EXPECT_TRUE(pc.IsValid());
@@ -118,18 +141,18 @@ CanonicalCookie BuildCanonicalCookie(const std::string& key,
: base::Time();
std::string cookie_path = pc.Path();
- return CanonicalCookie(GURL(), pc.Name(), pc.Value(), key, cookie_path,
- creation_time, cookie_expires, creation_time,
- pc.IsSecure(), pc.IsHttpOnly(), pc.IsFirstPartyOnly(),
- pc.Priority());
+ return CanonicalCookie::Create(url, pc.Name(), pc.Value(), url.host(),
+ cookie_path, creation_time, cookie_expires,
+ pc.IsSecure(), pc.IsHttpOnly(), pc.SameSite(),
+ false, pc.Priority());
}
-void AddCookieToList(const std::string& key,
+void AddCookieToList(const GURL& url,
const std::string& cookie_line,
const base::Time& creation_time,
std::vector<CanonicalCookie*>* out_list) {
- scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(
- BuildCanonicalCookie(key, cookie_line, creation_time)));
+ scoped_ptr<CanonicalCookie> cookie(
+ BuildCanonicalCookie(url, cookie_line, creation_time));
out_list->push_back(cookie.release());
}
@@ -196,11 +219,12 @@ void MockSimplePersistentCookieStore::Flush(const base::Closure& callback) {
void MockSimplePersistentCookieStore::SetForceKeepSessionState() {
}
-CookieMonster* CreateMonsterFromStoreForGC(int num_secure_cookies,
- int num_old_secure_cookies,
- int num_non_secure_cookies,
- int num_old_non_secure_cookies,
- int days_old) {
+scoped_ptr<CookieMonster> CreateMonsterFromStoreForGC(
+ int num_secure_cookies,
+ int num_old_secure_cookies,
+ int num_non_secure_cookies,
+ int num_old_non_secure_cookies,
+ int days_old) {
base::Time current(base::Time::Now());
base::Time past_creation(base::Time::Now() - base::TimeDelta::FromDays(1000));
scoped_refptr<MockSimplePersistentCookieStore> store(
@@ -229,12 +253,12 @@ CookieMonster* CreateMonsterFromStoreForGC(int num_secure_cookies,
CanonicalCookie cc(GURL(), "a", "1", base::StringPrintf("h%05d.izzle", i),
"/path", creation_time, expiration_time,
- last_access_time, secure, false, false,
- COOKIE_PRIORITY_DEFAULT);
+ last_access_time, secure, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT);
store->AddCookie(cc);
}
- return new CookieMonster(store.get(), NULL);
+ return make_scoped_ptr(new CookieMonster(store.get(), nullptr));
}
MockSimplePersistentCookieStore::~MockSimplePersistentCookieStore() {
diff --git a/chromium/net/cookies/cookie_monster_store_test.h b/chromium/net/cookies/cookie_monster_store_test.h
index 686bb07afdb..aac83f82992 100644
--- a/chromium/net/cookies/cookie_monster_store_test.h
+++ b/chromium/net/cookies/cookie_monster_store_test.h
@@ -18,9 +18,12 @@
#include <vector>
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_monster.h"
+class GURL;
+
namespace base {
class Time;
}
@@ -50,18 +53,41 @@ class LoadedCallbackTask
DISALLOW_COPY_AND_ASSIGN(LoadedCallbackTask);
}; // Wrapper class LoadedCallbackTask
-// Describes a call to one of the 3 functions of PersistentCookieStore.
+// Describes a call to one of the 5 functions of PersistentCookieStore.
struct CookieStoreCommand {
enum Type {
+ LOAD,
+ LOAD_COOKIES_FOR_KEY,
+ // UPDATE_ACCESS_TIME is not included in this list, because get cookie
+ // commands may or may not end updating the access time, unless they have
+ // the option set not to do so.
ADD,
- UPDATE_ACCESS_TIME,
REMOVE,
};
- CookieStoreCommand(Type type, const CanonicalCookie& cookie)
- : type(type), cookie(cookie) {}
+ // Constructor for LOAD and LOAD_COOKIES_FOR_KEY calls. |key| should be empty
+ // for LOAD_COOKIES_FOR_KEY.
+ CookieStoreCommand(Type type,
+ const CookieMonster::PersistentCookieStore::LoadedCallback&
+ loaded_callback,
+ const std::string& key);
+
+ // Constructor for ADD, UPDATE_ACCESS_TIME, and REMOVE calls.
+ CookieStoreCommand(Type type, const CanonicalCookie& cookie);
+
+ CookieStoreCommand(const CookieStoreCommand& other);
+
+ ~CookieStoreCommand();
Type type;
+
+ // Only non-null for LOAD and LOAD_COOKIES_FOR_KEY.
+ CookieMonster::PersistentCookieStore::LoadedCallback loaded_callback;
+
+ // Only non-empty for LOAD_COOKIES_FOR_KEY.
+ std::string key;
+
+ // Only non-null for ADD, UPDATE_ACCESS_TIME, and REMOVE.
CanonicalCookie cookie;
};
@@ -74,6 +100,12 @@ class MockPersistentCookieStore : public CookieMonster::PersistentCookieStore {
MockPersistentCookieStore();
+ // When set, Load() and LoadCookiesForKey() calls are store in the command
+ // list, rather than being automatically executed. Defaults to false.
+ void set_store_load_commands(bool store_load_commands) {
+ store_load_commands_ = store_load_commands;
+ }
+
void SetLoadExpectation(bool return_value,
const std::vector<CanonicalCookie*>& result);
@@ -100,6 +132,8 @@ class MockPersistentCookieStore : public CookieMonster::PersistentCookieStore {
private:
CommandList commands_;
+ bool store_load_commands_;
+
// Deferred result to use when Load() is called.
bool load_return_value_;
std::vector<CanonicalCookie*> load_result_;
@@ -134,12 +168,13 @@ class MockCookieMonsterDelegate : public CookieMonsterDelegate {
};
// Helper to build a single CanonicalCookie.
-CanonicalCookie BuildCanonicalCookie(const std::string& key,
- const std::string& cookie_line,
- const base::Time& creation_time);
+scoped_ptr<CanonicalCookie> BuildCanonicalCookie(
+ const GURL& url,
+ const std::string& cookie_line,
+ const base::Time& creation_time);
// Helper to build a list of CanonicalCookie*s.
-void AddCookieToList(const std::string& key,
+void AddCookieToList(const GURL& url,
const std::string& cookie_line,
const base::Time& creation_time,
std::vector<CanonicalCookie*>* out_list);
@@ -188,11 +223,12 @@ class MockSimplePersistentCookieStore
// will be marked secure and non-secure, respectively. Do two SetCookies().
// Return whether each of the two SetCookies() took longer than |gc_perf_micros|
// to complete, and how many cookie were left in the store afterwards.
-CookieMonster* CreateMonsterFromStoreForGC(int num_secure_cookies,
- int num_old_secure_cookies,
- int num_non_secure_cookies,
- int num_old_non_secure_cookies,
- int days_old);
+scoped_ptr<CookieMonster> CreateMonsterFromStoreForGC(
+ int num_secure_cookies,
+ int num_old_secure_cookies,
+ int num_non_secure_cookies,
+ int num_old_non_secure_cookies,
+ int days_old);
} // namespace net
diff --git a/chromium/net/cookies/cookie_monster_unittest.cc b/chromium/net/cookies/cookie_monster_unittest.cc
index efeadd96d58..45c3063b70c 100644
--- a/chromium/net/cookies/cookie_monster_unittest.cc
+++ b/chromium/net/cookies/cookie_monster_unittest.cc
@@ -70,29 +70,11 @@ const char kTopLevelDomainPlus2Secure[] = "https://www.math.harvard.edu";
const char kTopLevelDomainPlus3[] = "http://www.bourbaki.math.harvard.edu";
const char kOtherDomain[] = "http://www.mit.edu";
-class GetCookieListCallback : public CookieCallback {
- public:
- GetCookieListCallback() {}
- explicit GetCookieListCallback(Thread* run_in_thread)
- : CookieCallback(run_in_thread) {}
-
- void Run(const CookieList& cookies) {
- cookies_ = cookies;
- CallbackEpilogue();
- }
-
- const CookieList& cookies() { return cookies_; }
-
- private:
- CookieList cookies_;
-};
-
struct CookieMonsterTestTraits {
- static scoped_refptr<CookieStore> Create() {
- return new CookieMonster(NULL, NULL);
+ static scoped_ptr<CookieStore> Create() {
+ return make_scoped_ptr(new CookieMonster(nullptr, nullptr));
}
- static const bool is_cookie_monster = true;
static const bool supports_http_only = true;
static const bool supports_non_dotted_domains = true;
static const bool preserves_trailing_dots = true;
@@ -103,11 +85,10 @@ struct CookieMonsterTestTraits {
};
struct CookieMonsterEnforcingStrictSecure {
- static scoped_refptr<CookieStore> Create() {
- return new CookieMonster(NULL, NULL);
+ static scoped_ptr<CookieStore> Create() {
+ return make_scoped_ptr(new CookieMonster(nullptr, nullptr));
}
- static const bool is_cookie_monster = true;
static const bool supports_http_only = true;
static const bool supports_non_dotted_domains = true;
static const bool preserves_trailing_dots = true;
@@ -121,10 +102,6 @@ INSTANTIATE_TYPED_TEST_CASE_P(CookieMonster,
CookieStoreTest,
CookieMonsterTestTraits);
-INSTANTIATE_TYPED_TEST_CASE_P(CookieMonster,
- MultiThreadedCookieStoreTest,
- CookieMonsterTestTraits);
-
INSTANTIATE_TYPED_TEST_CASE_P(CookieMonsterStrictSecure,
CookieStoreTest,
CookieMonsterEnforcingStrictSecure);
@@ -132,88 +109,31 @@ INSTANTIATE_TYPED_TEST_CASE_P(CookieMonsterStrictSecure,
template <typename T>
class CookieMonsterTestBase : public CookieStoreTest<T> {
public:
- using CookieStoreTest<T>::RunFor;
using CookieStoreTest<T>::SetCookie;
protected:
using CookieStoreTest<T>::http_www_google_;
using CookieStoreTest<T>::https_www_google_;
- CookieList GetAllCookies(CookieMonster* cm) {
- DCHECK(cm);
- GetCookieListCallback callback;
- cm->GetAllCookiesAsync(
- base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.cookies();
- }
-
- CookieList GetAllCookiesForURL(CookieMonster* cm, const GURL& url) {
- DCHECK(cm);
- GetCookieListCallback callback;
- cm->GetAllCookiesForURLAsync(url, base::Bind(&GetCookieListCallback::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.cookies();
- }
-
CookieList GetAllCookiesForURLWithOptions(CookieMonster* cm,
const GURL& url,
const CookieOptions& options) {
DCHECK(cm);
GetCookieListCallback callback;
- cm->GetAllCookiesForURLWithOptionsAsync(
+ cm->GetCookieListWithOptionsAsync(
url, options,
base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.cookies();
}
- bool SetCookieWithDetails(CookieMonster* cm,
- const GURL& url,
- const std::string& name,
- const std::string& value,
- const std::string& domain,
- const std::string& path,
- const base::Time& expiration_time,
- bool secure,
- bool http_only,
- bool first_party_only,
- CookiePriority priority) {
- DCHECK(cm);
- ResultSavingCookieCallback<bool> callback;
- cm->SetCookieWithDetailsAsync(
- url, name, value, domain, path, expiration_time, secure, http_only,
- first_party_only, false /* enforce prefixes */,
- false /* enforces strict secure cookies */, priority,
- base::Bind(&ResultSavingCookieCallback<bool>::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.result();
- }
-
bool SetAllCookies(CookieMonster* cm, const CookieList& list) {
DCHECK(cm);
ResultSavingCookieCallback<bool> callback;
cm->SetAllCookiesAsync(list,
base::Bind(&ResultSavingCookieCallback<bool>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.result();
- }
-
- int DeleteAll(CookieMonster* cm) {
- DCHECK(cm);
- ResultSavingCookieCallback<int> callback;
- cm->DeleteAllAsync(base::Bind(&ResultSavingCookieCallback<int>::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.result();
}
@@ -226,8 +146,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
delete_begin, delete_end,
base::Bind(&ResultSavingCookieCallback<int>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.result();
}
@@ -241,120 +160,102 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
delete_begin, delete_end, url,
base::Bind(&ResultSavingCookieCallback<int>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.result();
- }
-
- int DeleteAllForHost(CookieMonster* cm, const GURL& url) {
- DCHECK(cm);
- ResultSavingCookieCallback<int> callback;
- cm->DeleteAllForHostAsync(url,
- base::Bind(&ResultSavingCookieCallback<int>::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.result();
- }
-
- bool DeleteCanonicalCookie(CookieMonster* cm, const CanonicalCookie& cookie) {
- DCHECK(cm);
- ResultSavingCookieCallback<bool> callback;
- cm->DeleteCanonicalCookieAsync(
- cookie, base::Bind(&ResultSavingCookieCallback<bool>::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.result();
}
// Helper for DeleteAllForHost test; repopulates CM with same layout
// each time.
- void PopulateCmForDeleteAllForHost(scoped_refptr<CookieMonster> cm) {
+ void PopulateCmForDeleteAllForHost(CookieMonster* cm) {
GURL url_top_level_domain_plus_1(kTopLevelDomainPlus1);
GURL url_top_level_domain_plus_2(kTopLevelDomainPlus2);
GURL url_top_level_domain_plus_2_secure(kTopLevelDomainPlus2Secure);
GURL url_top_level_domain_plus_3(kTopLevelDomainPlus3);
GURL url_other(kOtherDomain);
- DeleteAll(cm.get());
+ this->DeleteAll(cm);
// Static population for probe:
// * Three levels of domain cookie (.b.a, .c.b.a, .d.c.b.a)
// * Three levels of host cookie (w.b.a, w.c.b.a, w.d.c.b.a)
// * http_only cookie (w.c.b.a)
- // * first-party cookie (w.c.b.a)
+ // * same_site cookie (w.c.b.a)
// * Two secure cookies (.c.b.a, w.c.b.a)
// * Two domain path cookies (.c.b.a/dir1, .c.b.a/dir1/dir2)
// * Two host path cookies (w.c.b.a/dir1, w.c.b.a/dir1/dir2)
// Domain cookies
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_1, "dom_1", "X", ".harvard.edu",
- "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_1, "dom_1", "X", ".harvard.edu", "/",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "dom_2", "X",
- ".math.harvard.edu", "/", base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "dom_2", "X", ".math.harvard.edu", "/",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_3, "dom_3", "X",
- ".bourbaki.math.harvard.edu", "/", base::Time(), false, false, false,
+ cm, url_top_level_domain_plus_3, "dom_3", "X",
+ ".bourbaki.math.harvard.edu", "/", base::Time(), base::Time(),
+ base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
COOKIE_PRIORITY_DEFAULT));
// Host cookies
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_1, "host_1", "X", std::string(),
- "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_1, "host_1", "X", std::string(), "/",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "host_2", "X", std::string(),
- "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "host_2", "X", std::string(), "/",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_3, "host_3", "X", std::string(),
- "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_3, "host_3", "X", std::string(), "/",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
// http_only cookie
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "httpo_check", "x",
- std::string(), "/", base::Time(), false, true, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "httpo_check", "x", std::string(), "/",
+ base::Time(), base::Time(), base::Time(), false, true,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
- // first-party cookie
+ // same-site cookie
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "firstp_check", "x",
- std::string(), "/", base::Time(), false, false, true,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "firstp_check", "x", std::string(),
+ "/", base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT));
// Secure cookies
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2_secure, "sec_dom", "X",
- ".math.harvard.edu", "/", base::Time(), true, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2_secure, "sec_dom", "X",
+ ".math.harvard.edu", "/", base::Time(), base::Time(), base::Time(),
+ true, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2_secure, "sec_host", "X",
- std::string(), "/", base::Time(), true, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2_secure, "sec_host", "X", std::string(),
+ "/", base::Time(), base::Time(), base::Time(), true, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
// Domain path cookies
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "dom_path_1", "X",
- ".math.harvard.edu", "/dir1", base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "dom_path_1", "X", ".math.harvard.edu",
+ "/dir1", base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "dom_path_2", "X",
- ".math.harvard.edu", "/dir1/dir2", base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "dom_path_2", "X", ".math.harvard.edu",
+ "/dir1/dir2", base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
// Host path cookies
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "host_path_1", "X",
- std::string(), "/dir1", base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "host_path_1", "X", std::string(),
+ "/dir1", base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "host_path_2", "X",
- std::string(), "/dir1/dir2", base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "host_path_2", "X", std::string(),
+ "/dir1/dir2", base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
- EXPECT_EQ(14U, this->GetAllCookies(cm.get()).size());
+ EXPECT_EQ(14U, this->GetAllCookies(cm).size());
}
Time GetFirstCookieAccessDate(CookieMonster* cm) {
@@ -383,7 +284,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
(domain_max_cookies + domain_purge_cookies) * 2;
// Add a bunch of cookies on a single host, should purge them.
{
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
for (int i = 0; i < more_than_enough_cookies; ++i) {
std::string cookie = base::StringPrintf("a%03d=b", i);
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), cookie));
@@ -401,7 +302,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
// between them. We shouldn't go above kDomainMaxCookies for both together.
GURL url_google_specific(http_www_google_.Format("http://www.gmail.%D"));
{
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
for (int i = 0; i < more_than_enough_cookies; ++i) {
std::string cookie_general = base::StringPrintf("a%03d=b", i);
EXPECT_TRUE(
@@ -461,7 +362,8 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
size_t expected_low_count,
size_t expected_medium_count,
size_t expected_high_count) {
- DeleteAll(cm);
+ SCOPED_TRACE(coded_priority_str);
+ this->DeleteAll(cm);
int next_cookie_id = 0;
std::vector<CookiePriority> priority_list;
std::vector<int> id_list[3]; // Indexed by CookiePriority.
@@ -472,7 +374,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
base::SPLIT_WANT_ALL)) {
DCHECK(!token.empty());
// Take last character as priority.
- CookiePriority priority = CharToPriority(token[token.length() - 1]);
+ CookiePriority priority = CharToPriority(token.back());
std::string priority_str = CookiePriorityToString(priority);
// The rest of the string (possibly empty) specifies repetition.
int rep = 1;
@@ -544,10 +446,10 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
size_t expected_secure_cookies,
size_t expected_non_secure_cookies,
const AltHosts* alt_host_entries) {
- scoped_refptr<CookieMonster> cm;
+ scoped_ptr<CookieMonster> cm;
if (alt_host_entries == nullptr) {
- cm = new CookieMonster(nullptr, nullptr);
+ cm.reset(new CookieMonster(nullptr, nullptr));
} else {
// When generating all of these cookies on alternate hosts, they need to
// be all older than the max "safe" date for GC, which is currently 30
@@ -595,7 +497,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
DCHECK_EQ(50U, CookieMonster::kDomainCookiesQuotaMedium);
DCHECK_EQ(70U, CookieMonster::kDomainCookiesQuotaHigh);
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
// Each test case adds 181 cookies, so 31 cookies are evicted.
// Cookie same priority, repeated for each priority.
@@ -712,13 +614,6 @@ class MockDeleteCallback
MOCK_METHOD1(Invoke, void(int num_deleted));
};
-class MockDeleteCookieCallback
- : public MockCookieCallback<MockDeleteCookieCallback,
- CookieMonster::DeleteCookieCallback> {
- public:
- MOCK_METHOD1(Invoke, void(bool success));
-};
-
struct CookiesInputInfo {
const GURL url;
const std::string name;
@@ -728,13 +623,12 @@ struct CookiesInputInfo {
const base::Time expiration_time;
bool secure;
bool http_only;
- bool first_party_only;
+ CookieSameSite same_site;
CookiePriority priority;
};
-ACTION(QuitCurrentMessageLoop) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
+ACTION_P(QuitRunLoop, run_loop) {
+ run_loop->Quit();
}
// TODO(erikwright): When the synchronous helpers 'GetCookies' etc. are removed,
@@ -763,18 +657,24 @@ ACTION_P4(DeleteAllCreatedBetweenAction,
}
ACTION_P3(SetCookieWithDetailsAction, cookie_monster, cc, callback) {
cookie_monster->SetCookieWithDetailsAsync(
- cc.url, cc.name, cc.value, cc.domain, cc.path, cc.expiration_time,
- cc.secure, cc.http_only, cc.first_party_only,
- false /* enforce prefixes */, false /* enforces strict secure cookies */,
- cc.priority, callback->AsCallback());
+ 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());
}
ACTION_P2(GetAllCookiesAction, cookie_monster, callback) {
cookie_monster->GetAllCookiesAsync(callback->AsCallback());
}
-ACTION_P3(DeleteAllForHostAction, cookie_monster, url, callback) {
- cookie_monster->DeleteAllForHostAsync(url, callback->AsCallback());
+ACTION_P5(DeleteAllCreatedBetweenForHostAction,
+ cookie_monster,
+ delete_begin,
+ delete_end,
+ url,
+ callback) {
+ cookie_monster->DeleteAllCreatedBetweenForHostAsync(
+ delete_begin, delete_end, url, callback->AsCallback());
}
ACTION_P3(DeleteCanonicalCookieAction, cookie_monster, cookie, callback) {
@@ -785,9 +685,9 @@ ACTION_P2(DeleteAllAction, cookie_monster, callback) {
cookie_monster->DeleteAllAsync(callback->AsCallback());
}
-ACTION_P3(GetAllCookiesForUrlWithOptionsAction, cookie_monster, url, callback) {
- cookie_monster->GetAllCookiesForURLWithOptionsAsync(url, CookieOptions(),
- callback->AsCallback());
+ACTION_P3(GetCookieListForUrlWithOptionsAction, cookie_monster, url, callback) {
+ cookie_monster->GetCookieListWithOptionsAsync(url, CookieOptions(),
+ callback->AsCallback());
}
ACTION_P3(GetAllCookiesForUrlAction, cookie_monster, url, callback) {
@@ -813,39 +713,36 @@ ACTION_P2(DeleteSessionCookiesAction, cookie_monster, callback) {
// 3. Invocations after the loading has completed complete immediately.
class DeferredCookieTaskTest : public CookieMonsterTest {
protected:
- DeferredCookieTaskTest() {
+ DeferredCookieTaskTest() : expect_load_called_(false) {
persistent_store_ = new NewMockPersistentCookieStore();
- cookie_monster_ = new CookieMonster(persistent_store_.get(), NULL);
+ cookie_monster_.reset(new CookieMonster(persistent_store_.get(), nullptr));
}
// Defines a cookie to be returned from PersistentCookieStore::Load
- void DeclareLoadedCookie(const std::string& key,
+ void DeclareLoadedCookie(const GURL& url,
const std::string& cookie_line,
const base::Time& creation_time) {
- AddCookieToList(key, cookie_line, creation_time, &loaded_cookies_);
+ AddCookieToList(url, cookie_line, creation_time, &loaded_cookies_);
}
// Runs the message loop, waiting until PersistentCookieStore::Load is called.
- // Call CompleteLoadingAndWait to cause the load to complete.
+ // Call CompleteLoading to cause the load to complete.
void WaitForLoadCall() {
- RunFor(kTimeout);
+ load_run_loop_.Run();
// Verify that PeristentStore::Load was called.
testing::Mock::VerifyAndClear(persistent_store_.get());
}
// Invokes the PersistentCookieStore::LoadCookiesForKey completion callbacks
- // and PersistentCookieStore::Load completion callback and waits
- // until the message loop is quit.
- void CompleteLoadingAndWait() {
+ // and PersistentCookieStore::Load completion callback.
+ void CompleteLoading() {
while (!loaded_for_key_callbacks_.empty()) {
loaded_for_key_callbacks_.front().Run(loaded_cookies_);
loaded_cookies_.clear();
loaded_for_key_callbacks_.pop();
}
-
loaded_callback_.Run(loaded_cookies_);
- RunFor(kTimeout);
}
// Performs the provided action, expecting it to cause a call to
@@ -861,30 +758,26 @@ class DeferredCookieTaskTest : public CookieMonsterTest {
testing::Action<void(void)> action) {
EXPECT_CALL(*this, Begin()).WillOnce(action);
ExpectLoadCall();
- ExpectLoadForKeyCall(key, false);
+ ExpectLoadForKeyCall(key);
Begin();
}
// Declares an expectation that PersistentCookieStore::Load will be called,
- // saving the provided callback and sending a quit to the message loop.
+ // saving the provided callback and sending a quit to |load_run_loop_|.
void ExpectLoadCall() {
+ // Make sure the |load_run_loop_| is not reused.
+ CHECK(!expect_load_called_);
+ expect_load_called_ = true;
EXPECT_CALL(*persistent_store_.get(), Load(testing::_))
.WillOnce(testing::DoAll(testing::SaveArg<0>(&loaded_callback_),
- QuitCurrentMessageLoop()));
+ QuitRunLoop(&load_run_loop_)));
}
// Declares an expectation that PersistentCookieStore::LoadCookiesForKey
- // will be called, saving the provided callback and sending a quit to the
- // message loop.
- void ExpectLoadForKeyCall(const std::string& key, bool quit_queue) {
- if (quit_queue)
- EXPECT_CALL(*persistent_store_.get(), LoadCookiesForKey(key, testing::_))
- .WillOnce(
- testing::DoAll(PushCallbackAction(&loaded_for_key_callbacks_),
- QuitCurrentMessageLoop()));
- else
- EXPECT_CALL(*persistent_store_.get(), LoadCookiesForKey(key, testing::_))
- .WillOnce(PushCallbackAction(&loaded_for_key_callbacks_));
+ // will be called, saving the provided callback.
+ void ExpectLoadForKeyCall(const std::string& key) {
+ EXPECT_CALL(*persistent_store_.get(), LoadCookiesForKey(key, testing::_))
+ .WillOnce(PushCallbackAction(&loaded_for_key_callbacks_));
}
// Invokes the initial action.
@@ -906,15 +799,18 @@ class DeferredCookieTaskTest : public CookieMonsterTest {
// PersistentCookieStore::LoadCookiesForKey
std::queue<CookieMonster::PersistentCookieStore::LoadedCallback>
loaded_for_key_callbacks_;
-
+ // base::RunLoop used to wait for PersistentCookieStore::Load to be called.
+ base::RunLoop load_run_loop_;
+ // Indicates whether ExpectLoadCall() has been called.
+ bool expect_load_called_;
// Stores the CookieMonster under test.
- scoped_refptr<CookieMonster> cookie_monster_;
+ scoped_ptr<CookieMonster> cookie_monster_;
// Stores the mock PersistentCookieStore.
scoped_refptr<NewMockPersistentCookieStore> persistent_store_;
};
TEST_F(DeferredCookieTaskTest, DeferredGetCookies) {
- DeclareLoadedCookie(http_www_google_.host(),
+ DeclareLoadedCookie(http_www_google_.url(),
"X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(3));
@@ -930,10 +826,11 @@ TEST_F(DeferredCookieTaskTest, DeferredGetCookies) {
EXPECT_CALL(get_cookies_callback, Invoke("X=1"))
.WillOnce(GetCookiesAction(&cookie_monster(), http_www_google_.url(),
&get_cookies_callback));
- EXPECT_CALL(get_cookies_callback, Invoke("X=1"))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(get_cookies_callback, Invoke("X=1")).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredSetCookie) {
@@ -949,23 +846,24 @@ TEST_F(DeferredCookieTaskTest, DeferredSetCookie) {
EXPECT_CALL(set_cookies_callback, Invoke(true))
.WillOnce(SetCookieAction(&cookie_monster(), http_www_google_.url(),
"X=Y", &set_cookies_callback));
- EXPECT_CALL(set_cookies_callback, Invoke(true))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredSetAllCookies) {
MockSetCookiesCallback set_cookies_callback;
CookieList list;
- list.push_back(CanonicalCookie(http_www_google_.url(), "A", "B",
- http_www_google_.domain(), "/",
- base::Time::Now(), base::Time(), base::Time(),
- false, true, false, COOKIE_PRIORITY_DEFAULT));
- list.push_back(CanonicalCookie(http_www_google_.url(), "C", "D",
- http_www_google_.domain(), "/",
- base::Time::Now(), base::Time(), base::Time(),
- false, true, false, COOKIE_PRIORITY_DEFAULT));
+ list.push_back(*CanonicalCookie::Create(
+ http_www_google_.url(), "A", "B", http_www_google_.domain(), "/",
+ base::Time::Now(), base::Time(), false, true,
+ CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT));
+ list.push_back(*CanonicalCookie::Create(
+ http_www_google_.url(), "C", "D", http_www_google_.domain(), "/",
+ base::Time::Now(), base::Time(), false, true,
+ CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT));
BeginWith(
SetAllCookiesAction(&cookie_monster(), list, &set_cookies_callback));
@@ -975,10 +873,11 @@ TEST_F(DeferredCookieTaskTest, DeferredSetAllCookies) {
EXPECT_CALL(set_cookies_callback, Invoke(true))
.WillOnce(
SetAllCookiesAction(&cookie_monster(), list, &set_cookies_callback));
- EXPECT_CALL(set_cookies_callback, Invoke(true))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredDeleteCookie) {
@@ -994,10 +893,11 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteCookie) {
EXPECT_CALL(delete_cookie_callback, Invoke())
.WillOnce(DeleteCookieAction(&cookie_monster(), http_www_google_.url(),
"X", &delete_cookie_callback));
- EXPECT_CALL(delete_cookie_callback, Invoke())
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(delete_cookie_callback, Invoke()).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredSetCookieWithDetails) {
@@ -1011,7 +911,7 @@ TEST_F(DeferredCookieTaskTest, DeferredSetCookieWithDetails) {
base::Time(),
false,
false,
- false,
+ CookieSameSite::DEFAULT_MODE,
COOKIE_PRIORITY_DEFAULT};
BeginWithForDomainKey(
http_www_google_.domain(),
@@ -1028,19 +928,20 @@ TEST_F(DeferredCookieTaskTest, DeferredSetCookieWithDetails) {
base::Time(),
false,
false,
- false,
+ CookieSameSite::DEFAULT_MODE,
COOKIE_PRIORITY_DEFAULT};
EXPECT_CALL(set_cookies_callback, Invoke(true))
.WillOnce(SetCookieWithDetailsAction(&cookie_monster(), cookie_info_exp,
&set_cookies_callback));
- EXPECT_CALL(set_cookies_callback, Invoke(true))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredGetAllCookies) {
- DeclareLoadedCookie(http_www_google_.host(),
+ DeclareLoadedCookie(http_www_google_.url(),
"X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(3));
@@ -1053,14 +954,16 @@ TEST_F(DeferredCookieTaskTest, DeferredGetAllCookies) {
EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
.WillOnce(
GetAllCookiesAction(&cookie_monster(), &get_cookie_list_callback));
+ base::RunLoop loop;
EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
- .WillOnce(QuitCurrentMessageLoop());
+ .WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlCookies) {
- DeclareLoadedCookie(http_www_google_.host(),
+ DeclareLoadedCookie(http_www_google_.url(),
"X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(3));
@@ -1077,34 +980,38 @@ TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlCookies) {
.WillOnce(GetAllCookiesForUrlAction(&cookie_monster(),
http_www_google_.url(),
&get_cookie_list_callback));
+ base::RunLoop loop;
EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
- .WillOnce(QuitCurrentMessageLoop());
+ .WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlWithOptionsCookies) {
- DeclareLoadedCookie(http_www_google_.host(),
+ DeclareLoadedCookie(http_www_google_.url(),
"X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(3));
MockGetCookieListCallback get_cookie_list_callback;
BeginWithForDomainKey(http_www_google_.domain(),
- GetAllCookiesForUrlWithOptionsAction(
+ GetCookieListForUrlWithOptionsAction(
&cookie_monster(), http_www_google_.url(),
&get_cookie_list_callback));
WaitForLoadCall();
EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
- .WillOnce(GetAllCookiesForUrlWithOptionsAction(
+ .WillOnce(GetCookieListForUrlWithOptionsAction(
&cookie_monster(), http_www_google_.url(),
&get_cookie_list_callback));
+ base::RunLoop loop;
EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
- .WillOnce(QuitCurrentMessageLoop());
+ .WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCookies) {
@@ -1116,10 +1023,12 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCookies) {
EXPECT_CALL(delete_callback, Invoke(false))
.WillOnce(DeleteAllAction(&cookie_monster(), &delete_callback));
- EXPECT_CALL(delete_callback, Invoke(false))
- .WillOnce(QuitCurrentMessageLoop());
- CompleteLoadingAndWait();
+ base::RunLoop loop;
+ EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop));
+
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCreatedBetweenCookies) {
@@ -1134,50 +1043,54 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCreatedBetweenCookies) {
.WillOnce(DeleteAllCreatedBetweenAction(&cookie_monster(), base::Time(),
base::Time::Now(),
&delete_callback));
- EXPECT_CALL(delete_callback, Invoke(false))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
-TEST_F(DeferredCookieTaskTest, DeferredDeleteAllForHostCookies) {
+TEST_F(DeferredCookieTaskTest, DeferredDeleteAllForHostCreatedBetweenCookies) {
MockDeleteCallback delete_callback;
- BeginWithForDomainKey(
- http_www_google_.domain(),
- DeleteAllForHostAction(&cookie_monster(), http_www_google_.url(),
- &delete_callback));
+ BeginWithForDomainKey(http_www_google_.domain(),
+ DeleteAllCreatedBetweenForHostAction(
+ &cookie_monster(), base::Time(), base::Time::Now(),
+ http_www_google_.url(), &delete_callback));
WaitForLoadCall();
EXPECT_CALL(delete_callback, Invoke(false))
- .WillOnce(DeleteAllForHostAction(
- &cookie_monster(), http_www_google_.url(), &delete_callback));
- EXPECT_CALL(delete_callback, Invoke(false))
- .WillOnce(QuitCurrentMessageLoop());
+ .WillOnce(DeleteAllCreatedBetweenForHostAction(
+ &cookie_monster(), base::Time(), base::Time::Now(),
+ http_www_google_.url(), &delete_callback));
+ base::RunLoop loop;
+ EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredDeleteCanonicalCookie) {
std::vector<CanonicalCookie*> cookies;
- CanonicalCookie cookie = BuildCanonicalCookie(
- http_www_google_.host(), "X=1; path=/", base::Time::Now());
+ scoped_ptr<CanonicalCookie> cookie = BuildCanonicalCookie(
+ http_www_google_.url(), "X=1; path=/", base::Time::Now());
- MockDeleteCookieCallback delete_cookie_callback;
+ MockDeleteCallback delete_cookie_callback;
- BeginWith(DeleteCanonicalCookieAction(&cookie_monster(), cookie,
+ BeginWith(DeleteCanonicalCookieAction(&cookie_monster(), *cookie,
&delete_cookie_callback));
WaitForLoadCall();
- EXPECT_CALL(delete_cookie_callback, Invoke(false))
- .WillOnce(DeleteCanonicalCookieAction(&cookie_monster(), cookie,
+ EXPECT_CALL(delete_cookie_callback, Invoke(0))
+ .WillOnce(DeleteCanonicalCookieAction(&cookie_monster(), *cookie,
&delete_cookie_callback));
- EXPECT_CALL(delete_cookie_callback, Invoke(false))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(delete_cookie_callback, Invoke(0)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredDeleteSessionCookies) {
@@ -1190,17 +1103,18 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteSessionCookies) {
EXPECT_CALL(delete_callback, Invoke(false))
.WillOnce(
DeleteSessionCookiesAction(&cookie_monster(), &delete_callback));
- EXPECT_CALL(delete_callback, Invoke(false))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
// Verify that a series of queued tasks are executed in order upon loading of
// the backing store and that new tasks received while the queued tasks are
// being dispatched go to the end of the queue.
TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
- DeclareLoadedCookie(http_www_google_.host(),
+ DeclareLoadedCookie(http_www_google_.url(),
"X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(3));
@@ -1215,7 +1129,7 @@ TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
SetCookieAction(&cookie_monster(), http_www_google_.url(), "A=B",
&set_cookies_callback)));
ExpectLoadCall();
- ExpectLoadForKeyCall(http_www_google_.domain(), false);
+ ExpectLoadForKeyCall(http_www_google_.domain());
Begin();
WaitForLoadCall();
@@ -1223,15 +1137,17 @@ TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
.WillOnce(GetCookiesAction(&cookie_monster(), http_www_google_.url(),
&get_cookies_callback_deferred));
EXPECT_CALL(set_cookies_callback, Invoke(true));
+ base::RunLoop loop;
EXPECT_CALL(get_cookies_callback_deferred, Invoke("A=B; X=1"))
- .WillOnce(QuitCurrentMessageLoop());
+ .WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(CookieMonsterTest, TestCookieDeleteAll) {
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
CookieOptions options;
options.set_include_httponly();
@@ -1264,7 +1180,7 @@ TEST_F(CookieMonsterTest, TestCookieDeleteAll) {
}
TEST_F(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
Time now = Time::Now();
// Nothing has been added so nothing should be deleted.
@@ -1306,8 +1222,8 @@ TEST_F(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) {
static const int kAccessDelayMs = kLastAccessThresholdMilliseconds + 20;
TEST_F(CookieMonsterTest, TestLastAccess) {
- scoped_refptr<CookieMonster> cm(
- new CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds));
+ scoped_ptr<CookieMonster> cm(
+ new CookieMonster(nullptr, nullptr, kLastAccessThresholdMilliseconds));
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
const Time last_access_date(GetFirstCookieAccessDate(cm.get()));
@@ -1315,12 +1231,33 @@ TEST_F(CookieMonsterTest, TestLastAccess) {
// Reading the cookie again immediately shouldn't update the access date,
// since we're inside the threshold.
EXPECT_EQ("A=B", GetCookies(cm.get(), http_www_google_.url()));
- EXPECT_TRUE(last_access_date == GetFirstCookieAccessDate(cm.get()));
+ EXPECT_EQ(last_access_date, GetFirstCookieAccessDate(cm.get()));
- // Reading after a short wait should update the access date.
+ // Reading after a short wait will update the access date, if the cookie
+ // is requested with options that would update the access date. First, test
+ // that the flag's behavior is respected.
base::PlatformThread::Sleep(
base::TimeDelta::FromMilliseconds(kAccessDelayMs));
- EXPECT_EQ("A=B", GetCookies(cm.get(), http_www_google_.url()));
+ CookieOptions options;
+ options.set_do_not_update_access_time();
+ EXPECT_EQ("A=B",
+ GetCookiesWithOptions(cm.get(), http_www_google_.url(), options));
+ EXPECT_EQ(last_access_date, GetFirstCookieAccessDate(cm.get()));
+
+ // Getting all cookies for a URL doesn't update the accessed time either.
+ CookieList cookies = GetAllCookiesForURL(cm.get(), http_www_google_.url());
+ CookieList::iterator it = cookies.begin();
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ(http_www_google_.host(), it->Domain());
+ EXPECT_EQ("A", it->Name());
+ EXPECT_EQ("B", it->Value());
+ EXPECT_EQ(last_access_date, GetFirstCookieAccessDate(cm.get()));
+ EXPECT_TRUE(++it == cookies.end());
+
+ // If the flag isn't set, the last accessed time should be updated.
+ options = CookieOptions();
+ EXPECT_EQ("A=B",
+ GetCookiesWithOptions(cm.get(), http_www_google_.url(), options));
EXPECT_FALSE(last_access_date == GetFirstCookieAccessDate(cm.get()));
}
@@ -1332,29 +1269,14 @@ TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollection) {
TestPriorityAwareGarbageCollectHelper();
}
-TEST_F(CookieMonsterTest, TestDeleteSingleCookie) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
-
- EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "C=D"));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "E=F"));
- EXPECT_EQ("A=B; C=D; E=F", GetCookies(cm.get(), http_www_google_.url()));
-
- EXPECT_TRUE(
- FindAndDeleteCookie(cm.get(), http_www_google_.url().host(), "C"));
- EXPECT_EQ("A=B; E=F", GetCookies(cm.get(), http_www_google_.url()));
-
- EXPECT_FALSE(FindAndDeleteCookie(cm.get(), "random.host", "E"));
- EXPECT_EQ("A=B; E=F", GetCookies(cm.get(), http_www_google_.url()));
-}
-
TEST_F(CookieMonsterTest, SetCookieableSchemes) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- scoped_refptr<CookieMonster> cm_foo(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
+ scoped_ptr<CookieMonster> cm_foo(new CookieMonster(nullptr, nullptr));
// Only cm_foo should allow foo:// cookies.
- const char* const kSchemes[] = {"foo"};
- cm_foo->SetCookieableSchemes(kSchemes, 1);
+ std::vector<std::string> schemes;
+ schemes.push_back("foo");
+ cm_foo->SetCookieableSchemes(schemes);
GURL foo_url("foo://host/path");
GURL http_url("http://host/path");
@@ -1366,8 +1288,8 @@ TEST_F(CookieMonsterTest, SetCookieableSchemes) {
}
TEST_F(CookieMonsterTest, GetAllCookiesForURL) {
- scoped_refptr<CookieMonster> cm(
- new CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds));
+ scoped_ptr<CookieMonster> cm(
+ new CookieMonster(nullptr, nullptr, kLastAccessThresholdMilliseconds));
// Create an httponly cookie.
CookieOptions options;
@@ -1431,11 +1353,11 @@ TEST_F(CookieMonsterTest, GetAllCookiesForURL) {
ASSERT_TRUE(++it == cookies.end());
// Reading after a short wait should not update the access date.
- EXPECT_TRUE(last_access_date == GetFirstCookieAccessDate(cm.get()));
+ EXPECT_EQ(last_access_date, GetFirstCookieAccessDate(cm.get()));
}
TEST_F(CookieMonsterTest, GetAllCookiesForURLPathMatching) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
CookieOptions options;
EXPECT_TRUE(SetCookieWithOptions(cm.get(), www_google_foo_.url(),
@@ -1473,7 +1395,7 @@ TEST_F(CookieMonsterTest, GetAllCookiesForURLPathMatching) {
}
TEST_F(CookieMonsterTest, CookieSorting) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "B=B1; path=/"));
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "B=B2; path=/foo"));
@@ -1503,7 +1425,7 @@ TEST_F(CookieMonsterTest, CookieSorting) {
}
TEST_F(CookieMonsterTest, DeleteCookieByName) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=A1; path=/"));
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=A2; path=/foo"));
@@ -1523,40 +1445,6 @@ TEST_F(CookieMonsterTest, DeleteCookieByName) {
}
}
-TEST_F(CookieMonsterTest, ImportCookiesFromCookieMonster) {
- scoped_refptr<CookieMonster> cm_1(new CookieMonster(NULL, NULL));
- CookieOptions options;
-
- EXPECT_TRUE(SetCookieWithOptions(cm_1.get(), www_google_foo_.url(),
- "A1=B; path=/foo;", options));
- EXPECT_TRUE(SetCookieWithOptions(cm_1.get(), www_google_bar_.url(),
- "A2=D; path=/bar;", options));
- EXPECT_TRUE(SetCookieWithOptions(cm_1.get(), http_www_google_.url(), "A3=F;",
- options));
-
- CookieList cookies_1 = GetAllCookies(cm_1.get());
- scoped_refptr<CookieMonster> cm_2(new CookieMonster(NULL, NULL));
- ASSERT_TRUE(cm_2->ImportCookies(cookies_1));
- CookieList cookies_2 = GetAllCookies(cm_2.get());
-
- size_t expected_size = 3;
- EXPECT_EQ(expected_size, cookies_2.size());
-
- CookieList::iterator it = cookies_2.begin();
-
- ASSERT_TRUE(it != cookies_2.end());
- EXPECT_EQ("A1", it->Name());
- EXPECT_EQ("/foo", it->Path());
-
- ASSERT_TRUE(++it != cookies_2.end());
- EXPECT_EQ("A2", it->Name());
- EXPECT_EQ("/bar", it->Path());
-
- ASSERT_TRUE(++it != cookies_2.end());
- EXPECT_EQ("A3", it->Name());
- EXPECT_EQ("/", it->Path());
-}
-
// Tests importing from a persistent cookie store that contains duplicate
// equivalent cookies. This situation should be handled by removing the
// duplicate cookie (both from the in-memory cache, and from the backing store).
@@ -1576,20 +1464,20 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCookies) {
// dates. We expect only the most recent one to be preserved following
// the import.
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(3), &initial_cookies);
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"X=2; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(1), &initial_cookies);
// ===> This one is the WINNER (biggest creation time). <====
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"X=3; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(4), &initial_cookies);
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"X=4; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now(), &initial_cookies);
@@ -1597,23 +1485,23 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCookies) {
// dates. We expect only the most recent one to be preserved the import.
// ===> This one is the WINNER (biggest creation time). <====
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"X=a1; path=/2; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(9), &initial_cookies);
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"X=a2; path=/2; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(2), &initial_cookies);
// Insert 1 cookie with name "Y" on path "/".
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"Y=a; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(10), &initial_cookies);
// Inject our initial cookies into the mock PersistentCookieStore.
store->SetLoadExpectation(true, initial_cookies);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
// Verify that duplicates were not imported for path "/".
// (If this had failed, GetCookies() would have also returned X=1, X=2, X=4).
@@ -1648,20 +1536,28 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCreationTimes) {
// two cookies remaining, but which two (other than that there should
// be one from each set) will be random.
std::vector<CanonicalCookie*> initial_cookies;
- AddCookieToList("www.google.com", "X=1; path=/", now, &initial_cookies);
- AddCookieToList("www.google.com", "X=2; path=/", now, &initial_cookies);
- AddCookieToList("www.google.com", "X=3; path=/", now, &initial_cookies);
- AddCookieToList("www.google.com", "X=4; path=/", now, &initial_cookies);
-
- AddCookieToList("www.google.com", "Y=1; path=/", earlier, &initial_cookies);
- AddCookieToList("www.google.com", "Y=2; path=/", earlier, &initial_cookies);
- AddCookieToList("www.google.com", "Y=3; path=/", earlier, &initial_cookies);
- AddCookieToList("www.google.com", "Y=4; path=/", earlier, &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "X=1; path=/", now,
+ &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "X=2; path=/", now,
+ &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "X=3; path=/", now,
+ &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "X=4; path=/", now,
+ &initial_cookies);
+
+ AddCookieToList(GURL("http://www.google.com"), "Y=1; path=/", earlier,
+ &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "Y=2; path=/", earlier,
+ &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "Y=3; path=/", earlier,
+ &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "Y=4; path=/", earlier,
+ &initial_cookies);
// Inject our initial cookies into the mock PersistentCookieStore.
store->SetLoadExpectation(true, initial_cookies);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
CookieList list(GetAllCookies(cm.get()));
EXPECT_EQ(2U, list.size());
@@ -1677,8 +1573,7 @@ TEST_F(CookieMonsterTest, CookieMonsterDelegate) {
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
scoped_refptr<MockCookieMonsterDelegate> delegate(
new MockCookieMonsterDelegate);
- scoped_refptr<CookieMonster> cm(
- new CookieMonster(store.get(), delegate.get()));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), delegate.get()));
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "C=D"));
@@ -1756,79 +1651,8 @@ TEST_F(CookieMonsterTest, CookieMonsterDelegate) {
delegate->reset();
}
-TEST_F(CookieMonsterTest, SetCookieWithDetails) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
-
- EXPECT_TRUE(SetCookieWithDetails(cm.get(), www_google_foo_.url(), "A", "B",
- std::string(), "/foo", base::Time(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
- EXPECT_TRUE(SetCookieWithDetails(
- cm.get(), www_google_bar_.url(), "C", "D", www_google_bar_.domain(),
- "/bar", base::Time(), false, true, false, COOKIE_PRIORITY_DEFAULT));
- EXPECT_TRUE(SetCookieWithDetails(
- cm.get(), http_www_google_.url(), "E", "F", std::string(), std::string(),
- base::Time(), true, false, false, COOKIE_PRIORITY_DEFAULT));
-
- // Test that malformed attributes fail to set the cookie.
- EXPECT_FALSE(SetCookieWithDetails(cm.get(), www_google_foo_.url(), " A", "B",
- std::string(), "/foo", base::Time(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
- EXPECT_FALSE(SetCookieWithDetails(cm.get(), www_google_foo_.url(), "A;", "B",
- std::string(), "/foo", base::Time(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
- EXPECT_FALSE(SetCookieWithDetails(cm.get(), www_google_foo_.url(), "A=", "B",
- std::string(), "/foo", base::Time(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
- EXPECT_FALSE(SetCookieWithDetails(
- cm.get(), www_google_foo_.url(), "A", "B", "google.ozzzzzzle", "foo",
- base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
- EXPECT_FALSE(SetCookieWithDetails(cm.get(), www_google_foo_.url(), "A=", "B",
- std::string(), "foo", base::Time(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
-
- CookieList cookies = GetAllCookiesForURL(cm.get(), www_google_foo_.url());
- CookieList::iterator it = cookies.begin();
-
- ASSERT_TRUE(it != cookies.end());
- EXPECT_EQ("A", it->Name());
- EXPECT_EQ("B", it->Value());
- EXPECT_EQ(www_google_foo_.host(), it->Domain());
- EXPECT_EQ("/foo", it->Path());
- EXPECT_FALSE(it->IsPersistent());
- EXPECT_FALSE(it->IsSecure());
- EXPECT_FALSE(it->IsHttpOnly());
-
- ASSERT_TRUE(++it == cookies.end());
-
- cookies = GetAllCookiesForURL(cm.get(), www_google_bar_.url());
- it = cookies.begin();
-
- ASSERT_TRUE(it != cookies.end());
- EXPECT_EQ("C", it->Name());
- EXPECT_EQ("D", it->Value());
- EXPECT_EQ(www_google_bar_.Format(".%D"), it->Domain());
- EXPECT_EQ("/bar", it->Path());
- EXPECT_FALSE(it->IsSecure());
- EXPECT_TRUE(it->IsHttpOnly());
-
- ASSERT_TRUE(++it == cookies.end());
-
- cookies = GetAllCookiesForURL(cm.get(), https_www_google_.url());
- it = cookies.begin();
-
- ASSERT_TRUE(it != cookies.end());
- EXPECT_EQ("E", it->Name());
- EXPECT_EQ("F", it->Value());
- EXPECT_EQ("/", it->Path());
- EXPECT_EQ(https_www_google_.host(), it->Domain());
- EXPECT_TRUE(it->IsSecure());
- EXPECT_FALSE(it->IsHttpOnly());
-
- ASSERT_TRUE(++it == cookies.end());
-}
-
TEST_F(CookieMonsterTest, DeleteAllForHost) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
// Test probes:
// * Non-secure URL, mid-level (http://w.c.b.a)
@@ -1838,7 +1662,7 @@ TEST_F(CookieMonsterTest, DeleteAllForHost) {
// the http_only cookie, the host secure cookie, and the two host
// path cookies. http_only, secure, and paths are ignored by
// this call, and domain cookies arent touched.
- PopulateCmForDeleteAllForHost(cm);
+ PopulateCmForDeleteAllForHost(cm.get());
EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
GetCookies(cm.get(), GURL(kTopLevelDomainPlus3)));
EXPECT_EQ("dom_1=X; dom_2=X; host_2=X; sec_dom=X; sec_host=X",
@@ -1851,7 +1675,9 @@ TEST_F(CookieMonsterTest, DeleteAllForHost) {
GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure +
std::string("/dir1/dir2/xxx"))));
- EXPECT_EQ(6, DeleteAllForHost(cm.get(), GURL(kTopLevelDomainPlus2)));
+ EXPECT_EQ(6, DeleteAllCreatedBetweenForHost(cm.get(), base::Time(),
+ base::Time::Now(),
+ GURL(kTopLevelDomainPlus2)));
EXPECT_EQ(8U, GetAllCookies(cm.get()).size());
EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
@@ -1864,8 +1690,10 @@ TEST_F(CookieMonsterTest, DeleteAllForHost) {
GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure +
std::string("/dir1/dir2/xxx"))));
- PopulateCmForDeleteAllForHost(cm);
- EXPECT_EQ(6, DeleteAllForHost(cm.get(), GURL(kTopLevelDomainPlus2Secure)));
+ PopulateCmForDeleteAllForHost(cm.get());
+ EXPECT_EQ(6, DeleteAllCreatedBetweenForHost(
+ cm.get(), base::Time(), base::Time::Now(),
+ GURL(kTopLevelDomainPlus2Secure)));
EXPECT_EQ(8U, GetAllCookies(cm.get()).size());
EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
@@ -1878,9 +1706,11 @@ TEST_F(CookieMonsterTest, DeleteAllForHost) {
GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure +
std::string("/dir1/dir2/xxx"))));
- PopulateCmForDeleteAllForHost(cm);
- EXPECT_EQ(6, DeleteAllForHost(cm.get(), GURL(kTopLevelDomainPlus2Secure +
- std::string("/dir1/xxx"))));
+ PopulateCmForDeleteAllForHost(cm.get());
+ EXPECT_EQ(6,
+ DeleteAllCreatedBetweenForHost(
+ cm.get(), base::Time(), base::Time::Now(),
+ GURL(kTopLevelDomainPlus2Secure + std::string("/dir1/xxx"))));
EXPECT_EQ(8U, GetAllCookies(cm.get()).size());
EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
@@ -1895,7 +1725,7 @@ TEST_F(CookieMonsterTest, DeleteAllForHost) {
}
TEST_F(CookieMonsterTest, UniqueCreationTime) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
CookieOptions options;
// Add in three cookies through every public interface to the
@@ -1921,16 +1751,16 @@ TEST_F(CookieMonsterTest, UniqueCreationTime) {
EXPECT_TRUE(SetCookieWithDetails(
cm.get(), http_www_google_.url(), "setCookieWithDetails1", "A",
- http_www_google_.Format(".%D"), "/", Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ http_www_google_.Format(".%D"), "/", Time(), Time(), Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(SetCookieWithDetails(
cm.get(), http_www_google_.url(), "setCookieWithDetails2", "A",
- http_www_google_.Format(".%D"), "/", Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ http_www_google_.Format(".%D"), "/", Time(), Time(), Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(SetCookieWithDetails(
cm.get(), http_www_google_.url(), "setCookieWithDetails3", "A",
- http_www_google_.Format(".%D"), "/", Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ http_www_google_.Format(".%D"), "/", Time(), Time(), Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
// Now we check
CookieList cookie_list(GetAllCookies(cm.get()));
@@ -1958,7 +1788,7 @@ TEST_F(CookieMonsterTest, UniqueCreationTime) {
// Mainly a test of GetEffectiveDomain, or more specifically, of the
// expected behavior of GetEffectiveDomain within the CookieMonster.
TEST_F(CookieMonsterTest, GetKey) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
// This test is really only interesting if GetKey() actually does something.
EXPECT_EQ("google.com", cm->GetKey("www.google.com"));
@@ -1990,47 +1820,25 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) {
base::Time expires(base::Time::Now() + base::TimeDelta::FromSeconds(100));
const CookiesInputInfo input_info[] = {
- {GURL("http://a.b.google.com"),
- "a",
- "1",
- "",
- "/path/to/cookie",
- expires,
- false,
- false,
- false,
- COOKIE_PRIORITY_DEFAULT},
- {GURL("https://www.google.com"),
- "b",
- "2",
- ".google.com",
- "/path/from/cookie",
- expires + TimeDelta::FromSeconds(10),
- true,
- true,
- false,
- COOKIE_PRIORITY_DEFAULT},
- {GURL("https://google.com"),
- "c",
- "3",
- "",
- "/another/path/to/cookie",
- base::Time::Now() + base::TimeDelta::FromSeconds(100),
- true,
- false,
- true,
- COOKIE_PRIORITY_DEFAULT}};
+ {GURL("http://a.b.google.com"), "a", "1", "", "/path/to/cookie", expires,
+ false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT},
+ {GURL("https://www.google.com"), "b", "2", ".google.com",
+ "/path/from/cookie", expires + TimeDelta::FromSeconds(10), true, true,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT},
+ {GURL("https://google.com"), "c", "3", "", "/another/path/to/cookie",
+ base::Time::Now() + base::TimeDelta::FromSeconds(100), true, false,
+ CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT}};
const int INPUT_DELETE = 1;
// Create new cookies and flush them to the store.
{
- scoped_refptr<CookieMonster> cmout(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cmout(new CookieMonster(store.get(), nullptr));
for (const CookiesInputInfo* p = input_info;
p < &input_info[arraysize(input_info)]; p++) {
- EXPECT_TRUE(SetCookieWithDetails(cmout.get(), p->url, p->name, p->value,
- p->domain, p->path, p->expiration_time,
- p->secure, p->http_only,
- p->first_party_only, p->priority));
+ EXPECT_TRUE(SetCookieWithDetails(
+ cmout.get(), p->url, p->name, p->value, p->domain, p->path,
+ base::Time(), p->expiration_time, base::Time(), p->secure,
+ p->http_only, p->same_site, p->priority));
}
GURL del_url(input_info[INPUT_DELETE]
.url.Resolve(input_info[INPUT_DELETE].path)
@@ -2040,7 +1848,7 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) {
// Create a new cookie monster and make sure that everything is correct
{
- scoped_refptr<CookieMonster> cmin(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cmin(new CookieMonster(store.get(), nullptr));
CookieList cookies(GetAllCookies(cmin.get()));
ASSERT_EQ(2u, cookies.size());
// Ordering is path length, then creation time. So second cookie
@@ -2059,7 +1867,7 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) {
output->CreationDate().ToInternalValue());
EXPECT_EQ(input->secure, output->IsSecure());
EXPECT_EQ(input->http_only, output->IsHttpOnly());
- EXPECT_EQ(input->first_party_only, output->IsFirstPartyOnly());
+ EXPECT_EQ(input->same_site, output->SameSite());
EXPECT_TRUE(output->IsPersistent());
EXPECT_EQ(input->expiration_time.ToInternalValue(),
output->ExpiryDate().ToInternalValue());
@@ -2070,7 +1878,7 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) {
TEST_F(CookieMonsterTest, CookieListOrdering) {
// Put a random set of cookies into a monster and make sure
// they're returned in the right order.
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
EXPECT_TRUE(
SetCookie(cm.get(), GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
EXPECT_TRUE(SetCookie(cm.get(), GURL("http://b.a.google.com/aa/bb/cc/x.html"),
@@ -2127,7 +1935,7 @@ TEST_F(CookieMonsterTest, MAYBE_GarbageCollectionTriggers) {
// First we check to make sure that a whole lot of recent cookies
// doesn't get rid of anything after garbage collection is checked for.
{
- scoped_refptr<CookieMonster> cm(
+ scoped_ptr<CookieMonster> cm(
CreateMonsterForGC(CookieMonster::kMaxCookies * 2));
EXPECT_EQ(CookieMonster::kMaxCookies * 2, GetAllCookies(cm.get()).size());
SetCookie(cm.get(), GURL("http://newdomain.com"), "b=2");
@@ -2169,9 +1977,9 @@ TEST_F(CookieMonsterTest, MAYBE_GarbageCollectionTriggers) {
for (int ci = 0; ci < static_cast<int>(arraysize(test_cases)); ++ci) {
const TestCase* test_case = &test_cases[ci];
- scoped_refptr<CookieMonster> cm(CreateMonsterFromStoreForGC(
+ scoped_ptr<CookieMonster> cm = CreateMonsterFromStoreForGC(
test_case->num_cookies, test_case->num_old_cookies, 0, 0,
- CookieMonster::kSafeFromGlobalPurgeDays * 2));
+ CookieMonster::kSafeFromGlobalPurgeDays * 2);
EXPECT_EQ(test_case->expected_initial_cookies,
GetAllCookies(cm.get()).size())
<< "For test case " << ci;
@@ -2183,33 +1991,197 @@ TEST_F(CookieMonsterTest, MAYBE_GarbageCollectionTriggers) {
}
}
-// This test checks that keep expired cookies flag is working.
-TEST_F(CookieMonsterTest, KeepExpiredCookies) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- cm->SetKeepExpiredCookies();
- CookieOptions options;
+// Tests that if the main load event happens before the loaded event for a
+// particular key, the tasks for that key run first.
+TEST_F(CookieMonsterTest, WhileLoadingLoadCompletesBeforeKeyLoadCompletes) {
+ const GURL kUrl = GURL(kTopLevelDomainPlus1);
- // Set a persistent cookie.
- ASSERT_TRUE(SetCookieWithOptions(
- cm.get(), http_www_google_.url(),
- std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT",
- options));
+ scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+ store->set_store_load_commands(true);
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
+
+ // Get all cookies task that queues a task to set a cookie when executed.
+ ResultSavingCookieCallback<bool> set_cookie_callback;
+ cm->SetCookieWithOptionsAsync(
+ kUrl, "a=b", CookieOptions(),
+ base::Bind(&ResultSavingCookieCallback<bool>::Run,
+ base::Unretained(&set_cookie_callback)));
+
+ GetCookieListCallback get_cookie_list_callback1;
+ cm->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback1)));
+
+ // Two load events should have been queued.
+ ASSERT_EQ(2u, store->commands().size());
+ ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
+ ASSERT_EQ(CookieStoreCommand::LOAD_COOKIES_FOR_KEY,
+ store->commands()[1].type);
- // Get the canonical cookie.
- CookieList cookie_list = GetAllCookies(cm.get());
- ASSERT_EQ(1U, cookie_list.size());
+ // The main load completes first (With no cookies).
+ store->commands()[0].loaded_callback.Run(std::vector<CanonicalCookie*>());
- // Use a past expiry date to delete the cookie.
- ASSERT_TRUE(SetCookieWithOptions(
- cm.get(), http_www_google_.url(),
- std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
- options));
+ // The tasks should run in order, and the get should see the cookies.
+
+ set_cookie_callback.WaitUntilDone();
+ EXPECT_TRUE(set_cookie_callback.result());
+
+ get_cookie_list_callback1.WaitUntilDone();
+ EXPECT_EQ(1u, get_cookie_list_callback1.cookies().size());
+
+ // The loaded for key event completes late, with not cookies (Since they
+ // were already loaded).
+ store->commands()[1].loaded_callback.Run(std::vector<CanonicalCookie*>());
+
+ // The just set cookie should still be in the store.
+ GetCookieListCallback get_cookie_list_callback2;
+ cm->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback2)));
+ get_cookie_list_callback2.WaitUntilDone();
+ EXPECT_EQ(1u, get_cookie_list_callback2.cookies().size());
+}
+
+// Tests that case that DeleteAll is waiting for load to complete, and then a
+// get is queued. The get should wait to run until after all the cookies are
+// retrieved, and should return nothing, since all cookies were just deleted.
+TEST_F(CookieMonsterTest, WhileLoadingDeleteAllGetForURL) {
+ const GURL kUrl = GURL(kTopLevelDomainPlus1);
+
+ scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+ store->set_store_load_commands(true);
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
+
+ ResultSavingCookieCallback<int> delete_callback;
+ cm->DeleteAllAsync(base::Bind(&ResultSavingCookieCallback<int>::Run,
+ base::Unretained(&delete_callback)));
+
+ GetCookieListCallback get_cookie_list_callback;
+ cm->GetCookieListWithOptionsAsync(
+ kUrl, CookieOptions(),
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback)));
+
+ // Only the main load should have been queued.
+ ASSERT_EQ(1u, store->commands().size());
+ ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
+
+ std::vector<CanonicalCookie*> cookies;
+ // When passed to the CookieMonster, it takes ownership of the pointed to
+ // cookies.
+ cookies.push_back(
+ CanonicalCookie::Create(kUrl, "a=b", base::Time(), CookieOptions())
+ .release());
+ ASSERT_TRUE(cookies[0]);
+ store->commands()[0].loaded_callback.Run(cookies);
+
+ delete_callback.WaitUntilDone();
+ EXPECT_EQ(1, delete_callback.result());
+
+ get_cookie_list_callback.WaitUntilDone();
+ EXPECT_EQ(0u, get_cookie_list_callback.cookies().size());
+}
+
+// Tests that a set cookie call sandwiched between two get all cookies, all
+// before load completes, affects the first but not the second. The set should
+// also not trigger a LoadCookiesForKey (As that could complete only after the
+// main load for the store).
+TEST_F(CookieMonsterTest, WhileLoadingGetAllSetGetAll) {
+ const GURL kUrl = GURL(kTopLevelDomainPlus1);
+
+ scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+ store->set_store_load_commands(true);
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
+
+ GetCookieListCallback get_cookie_list_callback1;
+ cm->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback1)));
+
+ ResultSavingCookieCallback<bool> set_cookie_callback;
+ cm->SetCookieWithOptionsAsync(
+ kUrl, "a=b", CookieOptions(),
+ base::Bind(&ResultSavingCookieCallback<bool>::Run,
+ base::Unretained(&set_cookie_callback)));
+
+ GetCookieListCallback get_cookie_list_callback2;
+ cm->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback2)));
+
+ // Only the main load should have been queued.
+ ASSERT_EQ(1u, store->commands().size());
+ ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
+
+ // The load completes (With no cookies).
+ store->commands()[0].loaded_callback.Run(std::vector<CanonicalCookie*>());
+
+ get_cookie_list_callback1.WaitUntilDone();
+ EXPECT_EQ(0u, get_cookie_list_callback1.cookies().size());
+
+ set_cookie_callback.WaitUntilDone();
+ EXPECT_TRUE(set_cookie_callback.result());
+
+ get_cookie_list_callback2.WaitUntilDone();
+ EXPECT_EQ(1u, get_cookie_list_callback2.cookies().size());
+}
+
+namespace {
+
+void RunClosureOnCookieListReceived(const base::Closure& closure,
+ const CookieList& cookie_list) {
+ closure.Run();
+}
+
+} // namespace
- // Check that the cookie with the past expiry date is still there.
- // GetAllCookies() also triggers garbage collection.
- cookie_list = GetAllCookies(cm.get());
- ASSERT_EQ(1U, cookie_list.size());
- ASSERT_TRUE(cookie_list[0].IsExpired(Time::Now()));
+// Tests that if a single cookie task is queued as a result of a task performed
+// on all cookies when loading completes, it will be run after any already
+// queued tasks.
+TEST_F(CookieMonsterTest, CheckOrderOfCookieTaskQueueWhenLoadingCompletes) {
+ const GURL kUrl = GURL(kTopLevelDomainPlus1);
+
+ scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+ store->set_store_load_commands(true);
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
+
+ // Get all cookies task that queues a task to set a cookie when executed.
+ ResultSavingCookieCallback<bool> set_cookie_callback;
+ cm->GetAllCookiesAsync(base::Bind(
+ &RunClosureOnCookieListReceived,
+ base::Bind(&CookieStore::SetCookieWithOptionsAsync,
+ base::Unretained(cm.get()), kUrl, "a=b", CookieOptions(),
+ base::Bind(&ResultSavingCookieCallback<bool>::Run,
+ base::Unretained(&set_cookie_callback)))));
+
+ // Get cookie task. Queued before the delete task is executed, so should not
+ // see the set cookie.
+ GetCookieListCallback get_cookie_list_callback1;
+ cm->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback1)));
+
+ // Only the main load should have been queued.
+ ASSERT_EQ(1u, store->commands().size());
+ ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
+
+ // The load completes.
+ store->commands()[0].loaded_callback.Run(std::vector<CanonicalCookie*>());
+
+ // The get cookies call should see no cookies set.
+ get_cookie_list_callback1.WaitUntilDone();
+ EXPECT_EQ(0u, get_cookie_list_callback1.cookies().size());
+
+ set_cookie_callback.WaitUntilDone();
+ EXPECT_TRUE(set_cookie_callback.result());
+
+ // A subsequent get cookies call should see the new cookie.
+ GetCookieListCallback get_cookie_list_callback2;
+ cm->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback2)));
+ get_cookie_list_callback2.WaitUntilDone();
+ EXPECT_EQ(1u, get_cookie_list_callback2.cookies().size());
}
namespace {
@@ -2273,7 +2245,7 @@ class CallbackCounter : public base::RefCountedThreadSafe<CallbackCounter> {
TEST_F(CookieMonsterTest, FlushStore) {
scoped_refptr<CallbackCounter> counter(new CallbackCounter());
scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
ASSERT_EQ(0, store->flush_count());
ASSERT_EQ(0, counter->callback_count());
@@ -2308,7 +2280,7 @@ TEST_F(CookieMonsterTest, FlushStore) {
ASSERT_EQ(2, counter->callback_count());
// If there's no backing store, FlushStore() is always a safe no-op.
- cm = new CookieMonster(NULL, NULL);
+ cm.reset(new CookieMonster(nullptr, nullptr));
GetAllCookies(cm.get()); // Force init.
cm->FlushStore(base::Closure());
base::MessageLoop::current()->RunUntilIdle();
@@ -2323,7 +2295,7 @@ TEST_F(CookieMonsterTest, FlushStore) {
TEST_F(CookieMonsterTest, SetAllCookies) {
scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
cm->SetPersistSessionCookies(true);
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "U=V; path=/"));
@@ -2331,18 +2303,18 @@ TEST_F(CookieMonsterTest, SetAllCookies) {
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "Y=Z; path=/"));
CookieList list;
- list.push_back(CanonicalCookie(http_www_google_.url(), "A", "B",
- http_www_google_.url().host(), "/",
- base::Time::Now(), base::Time(), base::Time(),
- false, false, false, COOKIE_PRIORITY_DEFAULT));
- list.push_back(CanonicalCookie(http_www_google_.url(), "W", "X",
- http_www_google_.url().host(), "/bar",
- base::Time::Now(), base::Time(), base::Time(),
- false, false, false, COOKIE_PRIORITY_DEFAULT));
- list.push_back(CanonicalCookie(http_www_google_.url(), "Y", "Z",
- http_www_google_.url().host(), "/",
- base::Time::Now(), base::Time(), base::Time(),
- false, false, false, COOKIE_PRIORITY_DEFAULT));
+ list.push_back(*CanonicalCookie::Create(
+ http_www_google_.url(), "A", "B", http_www_google_.url().host(), "/",
+ base::Time::Now(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT));
+ list.push_back(*CanonicalCookie::Create(
+ http_www_google_.url(), "W", "X", http_www_google_.url().host(), "/bar",
+ base::Time::Now(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT));
+ list.push_back(*CanonicalCookie::Create(
+ http_www_google_.url(), "Y", "Z", http_www_google_.url().host(), "/",
+ base::Time::Now(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT));
// SetAllCookies must not flush.
ASSERT_EQ(0, store->flush_count());
@@ -2369,71 +2341,73 @@ TEST_F(CookieMonsterTest, SetAllCookies) {
}
TEST_F(CookieMonsterTest, ComputeCookieDiff) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
base::Time now = base::Time::Now();
base::Time creation_time = now - base::TimeDelta::FromSeconds(1);
- CanonicalCookie cookie1(http_www_google_.url(), "A", "B",
- http_www_google_.url().host(), "/", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie2(http_www_google_.url(), "C", "D",
- http_www_google_.url().host(), "/", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie3(http_www_google_.url(), "E", "F",
- http_www_google_.url().host(), "/", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie4(http_www_google_.url(), "G", "H",
- http_www_google_.url().host(), "/", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie4_with_new_value(
+ scoped_ptr<CanonicalCookie> cookie1(CanonicalCookie::Create(
+ http_www_google_.url(), "A", "B", http_www_google_.url().host(), "/",
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
+ scoped_ptr<CanonicalCookie> cookie2(CanonicalCookie::Create(
+ http_www_google_.url(), "C", "D", http_www_google_.url().host(), "/",
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
+ scoped_ptr<CanonicalCookie> cookie3(CanonicalCookie::Create(
+ http_www_google_.url(), "E", "F", http_www_google_.url().host(), "/",
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
+ scoped_ptr<CanonicalCookie> cookie4(CanonicalCookie::Create(
+ http_www_google_.url(), "G", "H", http_www_google_.url().host(), "/",
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
+ scoped_ptr<CanonicalCookie> cookie4_with_new_value(CanonicalCookie::Create(
http_www_google_.url(), "G", "iamnew", http_www_google_.url().host(), "/",
- creation_time, base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie5(http_www_google_.url(), "I", "J",
- http_www_google_.url().host(), "/", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie5_with_new_creation_time(
- http_www_google_.url(), "I", "J", http_www_google_.url().host(), "/", now,
- base::Time(), base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie6(http_www_google_.url(), "K", "L",
- http_www_google_.url().host(), "/foo", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie6_with_new_path(
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
+ scoped_ptr<CanonicalCookie> cookie5(CanonicalCookie::Create(
+ http_www_google_.url(), "I", "J", http_www_google_.url().host(), "/",
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
+ scoped_ptr<CanonicalCookie> cookie5_with_new_creation_time(
+ CanonicalCookie::Create(
+ http_www_google_.url(), "I", "J", http_www_google_.url().host(), "/",
+ now, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, false,
+ COOKIE_PRIORITY_DEFAULT));
+ scoped_ptr<CanonicalCookie> cookie6(CanonicalCookie::Create(
+ http_www_google_.url(), "K", "L", http_www_google_.url().host(), "/foo",
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
+ scoped_ptr<CanonicalCookie> cookie6_with_new_path(CanonicalCookie::Create(
http_www_google_.url(), "K", "L", http_www_google_.url().host(), "/bar",
- creation_time, base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie7(http_www_google_.url(), "M", "N",
- http_www_google_.url().host(), "/foo", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie7_with_new_path(
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
+ scoped_ptr<CanonicalCookie> cookie7(CanonicalCookie::Create(
+ http_www_google_.url(), "M", "N", http_www_google_.url().host(), "/foo",
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
+ scoped_ptr<CanonicalCookie> cookie7_with_new_path(CanonicalCookie::Create(
http_www_google_.url(), "M", "N", http_www_google_.url().host(), "/bar",
- creation_time, base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
CookieList old_cookies;
- old_cookies.push_back(cookie1);
- old_cookies.push_back(cookie2);
- old_cookies.push_back(cookie4);
- old_cookies.push_back(cookie5);
- old_cookies.push_back(cookie6);
- old_cookies.push_back(cookie7);
+ old_cookies.push_back(*cookie1);
+ old_cookies.push_back(*cookie2);
+ old_cookies.push_back(*cookie4);
+ old_cookies.push_back(*cookie5);
+ old_cookies.push_back(*cookie6);
+ old_cookies.push_back(*cookie7);
CookieList new_cookies;
- new_cookies.push_back(cookie1);
- new_cookies.push_back(cookie3);
- new_cookies.push_back(cookie4_with_new_value);
- new_cookies.push_back(cookie5_with_new_creation_time);
- new_cookies.push_back(cookie6_with_new_path);
- new_cookies.push_back(cookie7);
- new_cookies.push_back(cookie7_with_new_path);
+ new_cookies.push_back(*cookie1);
+ new_cookies.push_back(*cookie3);
+ new_cookies.push_back(*cookie4_with_new_value);
+ new_cookies.push_back(*cookie5_with_new_creation_time);
+ new_cookies.push_back(*cookie6_with_new_path);
+ new_cookies.push_back(*cookie7);
+ new_cookies.push_back(*cookie7_with_new_path);
CookieList cookies_to_add;
CookieList cookies_to_delete;
@@ -2442,51 +2416,51 @@ TEST_F(CookieMonsterTest, ComputeCookieDiff) {
&cookies_to_delete);
// |cookie1| has not changed.
- EXPECT_FALSE(IsCookieInList(cookie1, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie1, cookies_to_delete));
+ EXPECT_FALSE(IsCookieInList(*cookie1, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie1, cookies_to_delete));
// |cookie2| has been deleted.
- EXPECT_FALSE(IsCookieInList(cookie2, cookies_to_add));
- EXPECT_TRUE(IsCookieInList(cookie2, cookies_to_delete));
+ EXPECT_FALSE(IsCookieInList(*cookie2, cookies_to_add));
+ EXPECT_TRUE(IsCookieInList(*cookie2, cookies_to_delete));
// |cookie3| has been added.
- EXPECT_TRUE(IsCookieInList(cookie3, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie3, cookies_to_delete));
+ EXPECT_TRUE(IsCookieInList(*cookie3, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie3, cookies_to_delete));
// |cookie4| has a new value: new cookie overrides the old one (which does not
// need to be explicitly removed).
- EXPECT_FALSE(IsCookieInList(cookie4, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie4, cookies_to_delete));
- EXPECT_TRUE(IsCookieInList(cookie4_with_new_value, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie4_with_new_value, cookies_to_delete));
+ EXPECT_FALSE(IsCookieInList(*cookie4, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie4, cookies_to_delete));
+ EXPECT_TRUE(IsCookieInList(*cookie4_with_new_value, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie4_with_new_value, cookies_to_delete));
// |cookie5| has a new creation time: new cookie overrides the old one (which
// does not need to be explicitly removed).
- EXPECT_FALSE(IsCookieInList(cookie5, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie5, cookies_to_delete));
- EXPECT_TRUE(IsCookieInList(cookie5_with_new_creation_time, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie5, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie5, cookies_to_delete));
+ EXPECT_TRUE(IsCookieInList(*cookie5_with_new_creation_time, cookies_to_add));
EXPECT_FALSE(
- IsCookieInList(cookie5_with_new_creation_time, cookies_to_delete));
+ IsCookieInList(*cookie5_with_new_creation_time, cookies_to_delete));
// |cookie6| has a new path: the new cookie does not overrides the old one,
// which needs to be explicitly removed.
- EXPECT_FALSE(IsCookieInList(cookie6, cookies_to_add));
- EXPECT_TRUE(IsCookieInList(cookie6, cookies_to_delete));
- EXPECT_TRUE(IsCookieInList(cookie6_with_new_path, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie6_with_new_path, cookies_to_delete));
+ EXPECT_FALSE(IsCookieInList(*cookie6, cookies_to_add));
+ EXPECT_TRUE(IsCookieInList(*cookie6, cookies_to_delete));
+ EXPECT_TRUE(IsCookieInList(*cookie6_with_new_path, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie6_with_new_path, cookies_to_delete));
// |cookie7| is kept and |cookie7_with_new_path| is added as a new cookie.
- EXPECT_FALSE(IsCookieInList(cookie7, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie7, cookies_to_delete));
- EXPECT_TRUE(IsCookieInList(cookie7_with_new_path, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie7_with_new_path, cookies_to_delete));
+ EXPECT_FALSE(IsCookieInList(*cookie7, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie7, cookies_to_delete));
+ EXPECT_TRUE(IsCookieInList(*cookie7_with_new_path, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie7_with_new_path, cookies_to_delete));
}
// Check that DeleteAll does flush (as a sanity check that flush_count()
// works).
TEST_F(CookieMonsterTest, DeleteAll) {
scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
cm->SetPersistSessionCookies(true);
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "X=Y; path=/"));
@@ -2497,7 +2471,7 @@ TEST_F(CookieMonsterTest, DeleteAll) {
}
TEST_F(CookieMonsterTest, HistogramCheck) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
// Should match call in InitializeHistograms, but doesn't really matter
// since the histogram should have been initialized by the CM construction
// above.
@@ -2508,9 +2482,9 @@ TEST_F(CookieMonsterTest, HistogramCheck) {
scoped_ptr<base::HistogramSamples> samples1(
expired_histogram->SnapshotSamples());
ASSERT_TRUE(SetCookieWithDetails(
- cm.get(), GURL("http://fake.a.url"), "a", "b", "a.url", "/",
- base::Time::Now() + base::TimeDelta::FromMinutes(59), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm.get(), GURL("http://fake.a.url"), "a", "b", "a.url", "/", base::Time(),
+ base::Time::Now() + base::TimeDelta::FromMinutes(59), base::Time(), false,
+ false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
scoped_ptr<base::HistogramSamples> samples2(
expired_histogram->SnapshotSamples());
@@ -2524,356 +2498,6 @@ TEST_F(CookieMonsterTest, HistogramCheck) {
EXPECT_EQ(samples2->TotalCount(), samples3->TotalCount());
}
-namespace {
-
-class MultiThreadedCookieMonsterTest : public CookieMonsterTest {
- public:
- MultiThreadedCookieMonsterTest() : other_thread_("CMTthread") {}
-
- // Helper methods for calling the asynchronous CookieMonster methods
- // from a different thread.
-
- void GetAllCookiesTask(CookieMonster* cm, GetCookieListCallback* callback) {
- cm->GetAllCookiesAsync(
- base::Bind(&GetCookieListCallback::Run, base::Unretained(callback)));
- }
-
- void GetAllCookiesForURLTask(CookieMonster* cm,
- const GURL& url,
- GetCookieListCallback* callback) {
- cm->GetAllCookiesForURLAsync(url, base::Bind(&GetCookieListCallback::Run,
- base::Unretained(callback)));
- }
-
- void GetAllCookiesForURLWithOptionsTask(CookieMonster* cm,
- const GURL& url,
- const CookieOptions& options,
- GetCookieListCallback* callback) {
- cm->GetAllCookiesForURLWithOptionsAsync(
- url, options,
- base::Bind(&GetCookieListCallback::Run, base::Unretained(callback)));
- }
-
- void SetCookieWithDetailsTask(CookieMonster* cm,
- const GURL& url,
- ResultSavingCookieCallback<bool>* callback) {
- // Define the parameters here instead of in the calling fucntion.
- // The maximum number of parameters for Bind function is 6.
- std::string name = "A";
- std::string value = "B";
- std::string domain = std::string();
- std::string path = "/foo";
- base::Time expiration_time = base::Time();
- bool secure = false;
- bool http_only = false;
- bool first_party_only = false;
- CookiePriority priority = COOKIE_PRIORITY_DEFAULT;
- cm->SetCookieWithDetailsAsync(
- url, name, value, domain, path, expiration_time, secure, http_only,
- first_party_only, false /* enforce prefixes */,
- false /* enforces strict secure cookies */, priority,
- base::Bind(&ResultSavingCookieCallback<bool>::Run,
- base::Unretained(callback)));
- }
-
- void DeleteAllCreatedBetweenTask(CookieMonster* cm,
- const base::Time& delete_begin,
- const base::Time& delete_end,
- ResultSavingCookieCallback<int>* callback) {
- cm->DeleteAllCreatedBetweenAsync(
- delete_begin, delete_end,
- base::Bind(&ResultSavingCookieCallback<int>::Run,
- base::Unretained(callback)));
- }
-
- void DeleteAllForHostTask(CookieMonster* cm,
- const GURL& url,
- ResultSavingCookieCallback<int>* callback) {
- cm->DeleteAllForHostAsync(url,
- base::Bind(&ResultSavingCookieCallback<int>::Run,
- base::Unretained(callback)));
- }
-
- void DeleteAllCreatedBetweenForHostTask(
- CookieMonster* cm,
- const base::Time delete_begin,
- const base::Time delete_end,
- const GURL& url,
- ResultSavingCookieCallback<int>* callback) {
- cm->DeleteAllCreatedBetweenForHostAsync(
- delete_begin, delete_end, url,
- base::Bind(&ResultSavingCookieCallback<int>::Run,
- base::Unretained(callback)));
- }
-
- void DeleteCanonicalCookieTask(CookieMonster* cm,
- const CanonicalCookie& cookie,
- ResultSavingCookieCallback<bool>* callback) {
- cm->DeleteCanonicalCookieAsync(
- cookie, base::Bind(&ResultSavingCookieCallback<bool>::Run,
- base::Unretained(callback)));
- }
-
- protected:
- void RunOnOtherThread(const base::Closure& task) {
- other_thread_.Start();
- other_thread_.task_runner()->PostTask(FROM_HERE, task);
- RunFor(kTimeout);
- other_thread_.Stop();
- }
-
- Thread other_thread_;
-};
-
-} // namespace
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookies) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
- CookieList cookies = GetAllCookies(cm.get());
- CookieList::const_iterator it = cookies.begin();
- ASSERT_TRUE(it != cookies.end());
- EXPECT_EQ(http_www_google_.host(), it->Domain());
- EXPECT_EQ("A", it->Name());
- ASSERT_TRUE(++it == cookies.end());
- GetCookieListCallback callback(&other_thread_);
- base::Closure task =
- base::Bind(&MultiThreadedCookieMonsterTest::GetAllCookiesTask,
- base::Unretained(this), cm, &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- it = callback.cookies().begin();
- ASSERT_TRUE(it != callback.cookies().end());
- EXPECT_EQ(http_www_google_.host(), it->Domain());
- EXPECT_EQ("A", it->Name());
- ASSERT_TRUE(++it == callback.cookies().end());
-}
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookiesForURL) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
- CookieList cookies = GetAllCookiesForURL(cm.get(), http_www_google_.url());
- CookieList::const_iterator it = cookies.begin();
- ASSERT_TRUE(it != cookies.end());
- EXPECT_EQ(http_www_google_.host(), it->Domain());
- EXPECT_EQ("A", it->Name());
- ASSERT_TRUE(++it == cookies.end());
- GetCookieListCallback callback(&other_thread_);
- base::Closure task =
- base::Bind(&MultiThreadedCookieMonsterTest::GetAllCookiesForURLTask,
- base::Unretained(this), cm, http_www_google_.url(), &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- it = callback.cookies().begin();
- ASSERT_TRUE(it != callback.cookies().end());
- EXPECT_EQ(http_www_google_.host(), it->Domain());
- EXPECT_EQ("A", it->Name());
- ASSERT_TRUE(++it == callback.cookies().end());
-}
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookiesForURLWithOpt) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
- CookieOptions options;
- CookieList cookies =
- GetAllCookiesForURLWithOptions(cm.get(), http_www_google_.url(), options);
- CookieList::const_iterator it = cookies.begin();
- ASSERT_TRUE(it != cookies.end());
- EXPECT_EQ(http_www_google_.host(), it->Domain());
- EXPECT_EQ("A", it->Name());
- ASSERT_TRUE(++it == cookies.end());
- GetCookieListCallback callback(&other_thread_);
- base::Closure task = base::Bind(
- &MultiThreadedCookieMonsterTest::GetAllCookiesForURLWithOptionsTask,
- base::Unretained(this), cm, http_www_google_.url(), options, &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- it = callback.cookies().begin();
- ASSERT_TRUE(it != callback.cookies().end());
- EXPECT_EQ(http_www_google_.host(), it->Domain());
- EXPECT_EQ("A", it->Name());
- ASSERT_TRUE(++it == callback.cookies().end());
-}
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckSetCookieWithDetails) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- EXPECT_TRUE(SetCookieWithDetails(cm.get(), www_google_foo_.url(), "A", "B",
- std::string(), "/foo", base::Time(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
- ResultSavingCookieCallback<bool> callback(&other_thread_);
- base::Closure task =
- base::Bind(&MultiThreadedCookieMonsterTest::SetCookieWithDetailsTask,
- base::Unretained(this), cm, www_google_foo_.url(), &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_TRUE(callback.result());
-}
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteAllCreatedBetween) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- CookieOptions options;
- Time now = Time::Now();
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- EXPECT_EQ(1, DeleteAllCreatedBetween(cm.get(), now - TimeDelta::FromDays(99),
- Time()));
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- ResultSavingCookieCallback<int> callback(&other_thread_);
- base::Closure task =
- base::Bind(&MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenTask,
- base::Unretained(this), cm, now - TimeDelta::FromDays(99),
- Time(), &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_EQ(1, callback.result());
-}
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteAllForHost) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- CookieOptions options;
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- EXPECT_EQ(1, DeleteAllForHost(cm.get(), http_www_google_.url()));
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- ResultSavingCookieCallback<int> callback(&other_thread_);
- base::Closure task =
- base::Bind(&MultiThreadedCookieMonsterTest::DeleteAllForHostTask,
- base::Unretained(this), cm, http_www_google_.url(), &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_EQ(1, callback.result());
-}
-
-TEST_F(MultiThreadedCookieMonsterTest,
- ThreadCheckDeleteAllCreatedBetweenForHost) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- GURL url_not_google("http://www.notgoogle.com");
-
- CookieOptions options;
- Time now = Time::Now();
- // ago1 < ago2 < ago3 < now.
- Time ago1 = now - TimeDelta::FromDays(101);
- Time ago2 = now - TimeDelta::FromDays(100);
- Time ago3 = now - TimeDelta::FromDays(99);
-
- // These 3 cookies match the first deletion.
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "C=D", options));
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "Y=Z", options));
-
- // This cookie does not match host.
- EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_not_google, "E=F", options));
-
- // This cookie does not match time range: [ago3, inf], for first deletion, but
- // matches for the second deletion.
- EXPECT_TRUE(
- cm->SetCookieWithCreationTime(http_www_google_.url(), "G=H", ago2));
-
- // 1. First set of deletions.
- EXPECT_EQ(3, // Deletes A=B, C=D, Y=Z
- DeleteAllCreatedBetweenForHost(cm.get(), ago3, Time::Max(),
- http_www_google_.url()));
-
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- ResultSavingCookieCallback<int> callback(&other_thread_);
-
- // 2. Second set of deletions.
- base::Closure task = base::Bind(
- &MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenForHostTask,
- base::Unretained(this), cm, ago1, Time(), http_www_google_.url(),
- &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_EQ(2, callback.result()); // Deletes A=B, G=H.
-}
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteCanonicalCookie) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- CookieOptions options;
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- CookieList cookies = GetAllCookies(cm.get());
- CookieList::iterator it = cookies.begin();
- EXPECT_TRUE(DeleteCanonicalCookie(cm.get(), *it));
-
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- ResultSavingCookieCallback<bool> callback(&other_thread_);
- cookies = GetAllCookies(cm.get());
- it = cookies.begin();
- base::Closure task =
- base::Bind(&MultiThreadedCookieMonsterTest::DeleteCanonicalCookieTask,
- base::Unretained(this), cm, *it, &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_TRUE(callback.result());
-}
-
-// Ensure that cookies for http, https, ws, and wss all share the same storage
-// and policies when GetAllCookiesForURLAsync is used. This test is part of
-// MultiThreadedCookieMonsterTest in order to test and use
-// GetAllCookiesForURLAsync, but it does not use any additional threads.
-TEST_F(MultiThreadedCookieMonsterTest, GetAllCookiesForURLEffectiveDomain) {
- std::vector<CanonicalCookie*> cookies;
- // This cookie will be freed by the CookieMonster.
- cookies.push_back(CanonicalCookie::Create(
- http_www_google_.url(), kValidCookieLine, Time::Now(), CookieOptions()));
- CanonicalCookie cookie = *cookies[0];
- scoped_refptr<NewMockPersistentCookieStore> store(
- new NewMockPersistentCookieStore);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
-
- CookieMonster::PersistentCookieStore::LoadedCallback loaded_callback;
- ::testing::StrictMock<::testing::MockFunction<void(int)>> checkpoint;
- const std::string key = cookie_util::GetEffectiveDomain(
- http_www_google_.url().scheme(), http_www_google_.url().host());
-
- ::testing::InSequence s;
- EXPECT_CALL(checkpoint, Call(0));
- EXPECT_CALL(*store, Load(::testing::_));
- EXPECT_CALL(*store, LoadCookiesForKey(key, ::testing::_))
- .WillOnce(::testing::SaveArg<1>(&loaded_callback));
- EXPECT_CALL(checkpoint, Call(1));
- // LoadCookiesForKey will never be called after checkpoint.Call(1) although
- // we will call GetAllCookiesForURLAsync again, because all URLs below share
- // the same key.
- EXPECT_CALL(*store, LoadCookiesForKey(::testing::_, ::testing::_)).Times(0);
-
- GetCookieListCallback callback;
- checkpoint.Call(0);
- GetAllCookiesForURLTask(cm.get(), http_www_google_.url(), &callback);
- checkpoint.Call(1);
- ASSERT_FALSE(callback.did_run());
- // Pass the cookies to the CookieMonster.
- loaded_callback.Run(cookies);
- // Now GetAllCookiesForURLTask is done.
- ASSERT_TRUE(callback.did_run());
- // See that the callback was called with the cookies.
- ASSERT_EQ(1u, callback.cookies().size());
- EXPECT_TRUE(cookie.IsEquivalent(callback.cookies()[0]));
-
- // All urls in |urls| should share the same cookie domain.
- const GURL kUrls[] = {
- http_www_google_.url(), https_www_google_.url(), ws_www_google_.url(),
- wss_www_google_.url(),
- };
- for (const GURL& url : kUrls) {
- // Call the function with |url| and verify it is done synchronously without
- // calling LoadCookiesForKey.
- GetCookieListCallback callback;
- GetAllCookiesForURLTask(cm.get(), url, &callback);
- ASSERT_TRUE(callback.did_run());
- ASSERT_EQ(1u, callback.cookies().size());
- EXPECT_TRUE(cookie.IsEquivalent(callback.cookies()[0]));
- }
-}
-
TEST_F(CookieMonsterTest, InvalidExpiryTime) {
std::string cookie_line =
std::string(kValidCookieLine) + "; expires=Blarg arg arg";
@@ -2886,7 +2510,7 @@ TEST_F(CookieMonsterTest, InvalidExpiryTime) {
// CookieStore if the "persist session cookies" option is on.
TEST_F(CookieMonsterTest, PersistSessionCookies) {
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
cm->SetPersistSessionCookies(true);
// All cookies set with SetCookie are session cookies.
@@ -2922,7 +2546,7 @@ TEST_F(CookieMonsterTest, PersistSessionCookies) {
// Test the commands sent to the persistent cookie store.
TEST_F(CookieMonsterTest, PersisentCookieStorageTest) {
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
// Add a cookie.
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(),
@@ -2974,24 +2598,24 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) {
std::vector<CanonicalCookie*> initial_cookies;
- AddCookieToList(domain, "foo=bar; path=" + path, now1, &initial_cookies);
+ AddCookieToList(url, "foo=bar; path=" + path, now1, &initial_cookies);
// We have to manually build this cookie because it contains a control
// character, and our cookie line parser rejects control characters.
- CanonicalCookie* cc =
- new CanonicalCookie(url, "baz",
- "\x05"
- "boo",
- domain, path, now2, later, now2, false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- initial_cookies.push_back(cc);
+ scoped_ptr<CanonicalCookie> cc = CanonicalCookie::Create(
+ url, "baz",
+ "\x05"
+ "boo",
+ domain, path, now2, later, false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT);
+ initial_cookies.push_back(cc.release());
- AddCookieToList(domain, "hello=world; path=" + path, now3, &initial_cookies);
+ AddCookieToList(url, "hello=world; path=" + path, now3, &initial_cookies);
// Inject our initial cookies into the mock PersistentCookieStore.
store->SetLoadExpectation(true, initial_cookies);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
EXPECT_EQ("foo=bar; hello=world", GetCookies(cm.get(), url));
}
@@ -3002,7 +2626,7 @@ TEST_F(CookieMonsterTest, CookieSourceHistogram) {
const std::string cookie_source_histogram = "Cookie.CookieSourceScheme";
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
histograms.ExpectTotalCount(cookie_source_histogram, 0);
@@ -3069,7 +2693,7 @@ TEST_F(CookieMonsterTest, CookieDeleteEquivalentHistogramTest) {
const std::string cookie_source_histogram = "Cookie.CookieDeleteEquivalent";
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
// Set a secure cookie from a secure origin
EXPECT_TRUE(SetCookie(cm.get(), https_www_google_.url(), "A=B; Secure"));
@@ -3134,7 +2758,7 @@ TEST_F(CookieMonsterTest, CookieDeleteEquivalentHistogramTest) {
}
TEST_F(CookieMonsterStrictSecureTest, SetSecureCookies) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
GURL http_url("http://www.google.com");
GURL http_superdomain_url("http://google.com");
GURL https_url("https://www.google.com");
@@ -3327,7 +2951,7 @@ TEST_F(CookieMonsterStrictSecureTest, EvictSecureCookies) {
// Tests that strict secure cookies doesn't trip equivalent cookie checks
// accidentally. Regression test for https://crbug.com/569943.
TEST_F(CookieMonsterStrictSecureTest, EquivalentCookies) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
GURL http_url("http://www.google.com");
GURL http_superdomain_url("http://google.com");
GURL https_url("https://www.google.com");
@@ -3352,7 +2976,7 @@ TEST_F(CookieMonsterStrictSecureTest, CookieDeleteEquivalentHistogramTest) {
const std::string cookie_source_histogram = "Cookie.CookieDeleteEquivalent";
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
// Set a secure cookie from a secure origin
EXPECT_TRUE(SetCookie(cm.get(), https_www_google_.url(), "A=B; Secure"));
@@ -3427,7 +3051,7 @@ class CookieMonsterNotificationTest : public CookieMonsterTest {
CookieMonsterNotificationTest()
: test_url_("http://www.google.com/foo"),
store_(new MockPersistentCookieStore),
- monster_(new CookieMonster(store_.get(), NULL)) {}
+ monster_(new CookieMonster(store_.get(), nullptr)) {}
~CookieMonsterNotificationTest() override {}
@@ -3438,7 +3062,7 @@ class CookieMonsterNotificationTest : public CookieMonsterTest {
private:
scoped_refptr<MockPersistentCookieStore> store_;
- scoped_refptr<CookieMonster> monster_;
+ scoped_ptr<CookieMonster> monster_;
};
void RecordCookieChanges(std::vector<CanonicalCookie>* out_cookies,
diff --git a/chromium/net/cookies/cookie_options.cc b/chromium/net/cookies/cookie_options.cc
index d29d51186f1..8698afdbd7b 100644
--- a/chromium/net/cookies/cookie_options.cc
+++ b/chromium/net/cookies/cookie_options.cc
@@ -10,8 +10,9 @@ namespace net {
CookieOptions::CookieOptions()
: exclude_httponly_(true),
- include_first_party_only_cookies_(false),
+ same_site_cookie_mode_(SameSiteCookieMode::DO_NOT_INCLUDE),
enforce_strict_secure_(false),
+ update_access_time_(true),
server_time_() {}
} // namespace net
diff --git a/chromium/net/cookies/cookie_options.h b/chromium/net/cookies/cookie_options.h
index 4d2a774c1bc..d1c6afc6371 100644
--- a/chromium/net/cookies/cookie_options.h
+++ b/chromium/net/cookies/cookie_options.h
@@ -9,35 +9,45 @@
#include "base/time/time.h"
#include "net/base/net_export.h"
+#include "net/cookies/cookie_constants.h"
#include "url/gurl.h"
namespace net {
class NET_EXPORT CookieOptions {
public:
+ enum class SameSiteCookieMode {
+ INCLUDE_STRICT_AND_LAX,
+ INCLUDE_LAX,
+ DO_NOT_INCLUDE
+ };
+
// Creates a CookieOptions object which:
//
// * Excludes HttpOnly cookies
- // * Excludes First-Party-Only cookies
+ // * Excludes SameSite cookies
// * Does not enforce prefix restrictions (e.g. "$Secure-*")
+ // * Updates last-accessed time.
//
// These settings can be altered by calling:
//
// * |set_{include,exclude}_httponly()|
- // * |set_include_first_party_only_cookies()|
+ // * |set_same_site_cookie_mode(
+ // CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX)|
// * |set_enforce_prefixes()|
+ // * |set_do_not_update_access_time()|
CookieOptions();
void set_exclude_httponly() { exclude_httponly_ = true; }
void set_include_httponly() { exclude_httponly_ = false; }
bool exclude_httponly() const { return exclude_httponly_; }
- // Default is to exclude 'first-party-only' cookies.
- void set_include_first_party_only_cookies() {
- include_first_party_only_cookies_ = true;
+ // Default is to exclude 'same_site' cookies.
+ void set_same_site_cookie_mode(SameSiteCookieMode mode) {
+ same_site_cookie_mode_ = mode;
}
- bool include_first_party_only_cookies() const {
- return include_first_party_only_cookies_;
+ SameSiteCookieMode same_site_cookie_mode() const {
+ return same_site_cookie_mode_;
}
// TODO(jww): Remove once we decide whether to ship modifying 'secure' cookies
@@ -54,10 +64,14 @@ class NET_EXPORT CookieOptions {
bool has_server_time() const { return !server_time_.is_null(); }
base::Time server_time() const { return server_time_; }
+ void set_do_not_update_access_time() { update_access_time_ = false; }
+ bool update_access_time() const { return update_access_time_; }
+
private:
bool exclude_httponly_;
- bool include_first_party_only_cookies_;
+ SameSiteCookieMode same_site_cookie_mode_;
bool enforce_strict_secure_;
+ bool update_access_time_;
base::Time server_time_;
};
diff --git a/chromium/net/cookies/cookie_store.cc b/chromium/net/cookies/cookie_store.cc
index e1b2e091001..f1dff9ada43 100644
--- a/chromium/net/cookies/cookie_store.cc
+++ b/chromium/net/cookies/cookie_store.cc
@@ -8,8 +8,68 @@
namespace net {
-CookieStore::CookieStore() {}
-
CookieStore::~CookieStore() {}
+std::string CookieStore::BuildCookieLine(
+ const std::vector<CanonicalCookie>& cookies) {
+ std::string cookie_line;
+ for (const auto& cookie : cookies) {
+ if (!cookie_line.empty())
+ cookie_line += "; ";
+ // In Mozilla, if you set a cookie like "AAA", it will have an empty token
+ // and a value of "AAA". When it sends the cookie back, it will send "AAA",
+ // so we need to avoid sending "=AAA" for a blank token value.
+ if (!cookie.Name().empty())
+ cookie_line += cookie.Name() + "=";
+ cookie_line += cookie.Value();
+ }
+ return cookie_line;
+}
+
+std::string CookieStore::BuildCookieLine(
+ const std::vector<CanonicalCookie*>& cookies) {
+ std::string cookie_line;
+ for (const auto& cookie : cookies) {
+ if (!cookie_line.empty())
+ cookie_line += "; ";
+ // In Mozilla, if you set a cookie like "AAA", it will have an empty token
+ // and a value of "AAA". When it sends the cookie back, it will send "AAA",
+ // so we need to avoid sending "=AAA" for a blank token value.
+ if (!cookie->Name().empty())
+ cookie_line += cookie->Name() + "=";
+ cookie_line += cookie->Value();
+ }
+ return cookie_line;
+}
+
+void CookieStore::DeleteAllAsync(const DeleteCallback& callback) {
+ DeleteAllCreatedBetweenAsync(base::Time(), base::Time::Max(), callback);
+}
+
+void CookieStore::SetForceKeepSessionState() {
+ // By default, do nothing.
+}
+
+void CookieStore::GetAllCookiesForURLAsync(
+ const GURL& url,
+ const GetCookieListCallback& callback) {
+ CookieOptions options;
+ options.set_include_httponly();
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ options.set_do_not_update_access_time();
+ GetCookieListWithOptionsAsync(url, options, callback);
+}
+
+void CookieStore::SetChannelIDServiceID(int id) {
+ DCHECK_EQ(-1, channel_id_service_id_);
+ channel_id_service_id_ = id;
+}
+
+int CookieStore::GetChannelIDServiceID() {
+ return channel_id_service_id_;
+}
+
+CookieStore::CookieStore() : channel_id_service_id_(-1) {}
+
} // namespace net
diff --git a/chromium/net/cookies/cookie_store.h b/chromium/net/cookies/cookie_store.h
index e2e24406365..f6426c5d695 100644
--- a/chromium/net/cookies/cookie_store.h
+++ b/chromium/net/cookies/cookie_store.h
@@ -12,7 +12,7 @@
#include "base/callback.h"
#include "base/callback_list.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "net/base/net_export.h"
#include "net/cookies/canonical_cookie.h"
@@ -24,9 +24,14 @@ namespace net {
class CookieMonster;
-// An interface for storing and retrieving cookies. Implementations need to
-// be thread safe as its methods can be accessed from IO as well as UI threads.
-class NET_EXPORT CookieStore : public base::RefCountedThreadSafe<CookieStore> {
+// 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.
+//
+// All async functions may either invoke the callback asynchronously, or they
+// may be invoked immediately (prior to return of the asynchronous function).
+// Destroying the CookieStore will cancel pending async callbacks.
+class NET_EXPORT CookieStore {
public:
// Callback definitions.
typedef base::Callback<void(const CookieList& cookies)> GetCookieListCallback;
@@ -39,7 +44,21 @@ class NET_EXPORT CookieStore : public base::RefCountedThreadSafe<CookieStore> {
CookieChangedCallbackList;
typedef CookieChangedCallbackList::Subscription CookieChangedSubscription;
- // Sets a single cookie. Expects a cookie line, like "a=1; domain=b.com".
+ virtual ~CookieStore();
+
+ // Returns the cookie line (e.g. "cookie1=value1; cookie2=value2") represented
+ // by |cookies|. The string is built in the same order as the given list.
+ //
+ // TODO(mkwst): We really should standardize on either
+ // 'std::vector<CanonicalCookie>' or 'std::vector<CanonicalCookie*>'.
+ static std::string BuildCookieLine(
+ const std::vector<CanonicalCookie>& cookies);
+ static std::string BuildCookieLine(
+ const std::vector<CanonicalCookie*>& cookies);
+
+ // Sets the cookies specified by |cookie_list| returned from |url|
+ // with options |options| in effect. Expects a cookie line, like
+ // "a=1; domain=b.com".
//
// Fails either if the cookie is invalid or if this is a non-HTTPONLY cookie
// and it would overwrite an existing HTTPONLY cookie.
@@ -50,28 +69,85 @@ class NET_EXPORT CookieStore : public base::RefCountedThreadSafe<CookieStore> {
const CookieOptions& options,
const SetCookiesCallback& callback) = 0;
+ // Sets a cookie given explicit user-provided cookie attributes. The cookie
+ // name, value, domain, etc. are each provided as separate strings. This
+ // function expects each attribute to be well-formed. It will check for
+ // disallowed characters (e.g. the ';' character is disallowed within the
+ // cookie value attribute) and will return false without setting the cookie
+ // if such characters are found.
+ //
+ // If |creation_time| is null, it will be set to the time the cookie is set.
+ // If |last_access_time| is null, it be set to |creation_time|.
+ //
+ // If unable to set a cookie, will invoke |callback| with false.
+ virtual void SetCookieWithDetailsAsync(
+ const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
+ bool secure,
+ bool http_only,
+ CookieSameSite same_site,
+ bool enforce_strict_secure,
+ CookiePriority priority,
+ const SetCookiesCallback& callback) = 0;
+
// TODO(???): what if the total size of all the cookies >4k, can we have a
// header that big or do we need multiple Cookie: headers?
// Note: Some sites, such as Facebook, occasionally use Cookie headers >4k.
//
// Simple interface, gets a cookie string "a=b; c=d" for the given URL.
- // Use options to access httponly cookies.
+ // Gets all cookies that apply to |url| given |options|. Use options to
+ // access httponly cookies.
+ //
+ // The returned cookies are ordered by longest path, then earliest
+ // creation date.
+ //
+ // TODO(mkwst): This method is deprecated; callsites should be updated to
+ // use 'GetCookieListWithOptionsAsync'.
virtual void GetCookiesWithOptionsAsync(
const GURL& url,
const CookieOptions& options,
const GetCookiesCallback& callback) = 0;
- // Returns all matching cookies without marking them as accessed,
- // including HTTP only cookies.
- virtual void GetAllCookiesForURLAsync(
+ // Obtains a CookieList for the given |url| and |options|. The returned
+ // cookies are passed into |callback|, ordered by longest path, then earliest
+ // creation date.
+ virtual void GetCookieListWithOptionsAsync(
const GURL& url,
+ const CookieOptions& options,
const GetCookieListCallback& callback) = 0;
- // Deletes the passed in cookie for the specified URL.
+ // Returns all cookies associated with |url|, including http-only, and
+ // same-site cookies. The returned cookies are ordered by longest path, then
+ // by earliest creation date, and are not marked as having been accessed.
+ //
+ // TODO(mkwst): This method is deprecated, and should be removed, either by
+ // updating callsites to use 'GetCookieListWithOptionsAsync' with an explicit
+ // CookieOptions, or by changing CookieOptions' defaults.
+ void GetAllCookiesForURLAsync(const GURL& url,
+ const GetCookieListCallback& callback);
+
+ // Returns all the cookies, for use in management UI, etc. This does not mark
+ // the cookies as having been accessed. The returned cookies are ordered by
+ // longest path, then by earliest creation date.
+ virtual void GetAllCookiesAsync(const GetCookieListCallback& callback) = 0;
+
+ // Deletes all cookies that might apply to |url| that have |cookie_name|.
virtual void DeleteCookieAsync(const GURL& url,
const std::string& cookie_name,
const base::Closure& callback) = 0;
+ // Deletes one specific cookie. |cookie| must have been returned by a previous
+ // query on this CookieStore. Invokes |callback| with 1 if a cookie was
+ // deleted, 0 otherwise.
+ virtual void DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
+ const DeleteCallback& callback) = 0;
+
// Deletes all of the cookies that have a creation_date greater than or equal
// to |delete_begin| and less than |delete_end|
// Returns the number of cookies that have been deleted.
@@ -93,8 +169,17 @@ class NET_EXPORT CookieStore : public base::RefCountedThreadSafe<CookieStore> {
virtual void DeleteSessionCookiesAsync(const DeleteCallback&) = 0;
- // Returns the underlying CookieMonster.
- virtual CookieMonster* GetCookieMonster() = 0;
+ // Deletes all cookies in the store.
+ void DeleteAllAsync(const DeleteCallback& callback);
+
+ // Flush the backing store (if any) to disk and post the given callback when
+ // done.
+ virtual void FlushStore(const base::Closure& callback) = 0;
+
+ // Protects session cookies from deletion on shutdown, if the underlying
+ // CookieStore implemention is currently configured to store them to disk.
+ // Otherwise, does nothing.
+ virtual void SetForceKeepSessionState();
// Add a callback to be notified when the set of cookies named |name| that
// would be sent for a request to |url| changes. The returned handle is
@@ -117,10 +202,16 @@ class NET_EXPORT CookieStore : public base::RefCountedThreadSafe<CookieStore> {
const std::string& name,
const CookieChangedCallback& callback) = 0;
+ // Returns true if this cookie store is ephemeral, and false if it is backed
+ // by some sort of persistence layer.
+ // TODO(nharper): Remove this method once crbug.com/548423 has been closed.
+ virtual bool IsEphemeral() = 0;
+ void SetChannelIDServiceID(int id);
+ int GetChannelIDServiceID();
+
protected:
- friend class base::RefCountedThreadSafe<CookieStore>;
CookieStore();
- virtual ~CookieStore();
+ int channel_id_service_id_;
};
} // namespace net
diff --git a/chromium/net/cookies/cookie_store_test_callbacks.cc b/chromium/net/cookies/cookie_store_test_callbacks.cc
index 491fe0e8bf9..9e36e706201 100644
--- a/chromium/net/cookies/cookie_store_test_callbacks.cc
+++ b/chromium/net/cookies/cookie_store_test_callbacks.cc
@@ -13,18 +13,12 @@
namespace net {
CookieCallback::CookieCallback(base::Thread* run_in_thread)
- : did_run_(false),
- run_in_thread_(run_in_thread),
- run_in_loop_(NULL),
- parent_loop_(base::MessageLoop::current()),
- loop_to_quit_(base::MessageLoop::current()) {}
+ : run_in_thread_(run_in_thread), run_in_loop_(NULL) {}
CookieCallback::CookieCallback()
- : did_run_(false),
- run_in_thread_(NULL),
- run_in_loop_(base::MessageLoop::current()),
- parent_loop_(NULL),
- loop_to_quit_(base::MessageLoop::current()) {}
+ : run_in_thread_(NULL), run_in_loop_(base::MessageLoop::current()) {}
+
+CookieCallback::~CookieCallback() {}
void CookieCallback::CallbackEpilogue() {
base::MessageLoop* expected_loop = NULL;
@@ -36,10 +30,12 @@ void CookieCallback::CallbackEpilogue() {
}
ASSERT_TRUE(expected_loop != NULL);
- did_run_ = true;
EXPECT_EQ(expected_loop, base::MessageLoop::current());
- loop_to_quit_->task_runner()->PostTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
+ loop_to_quit_.Quit();
+}
+
+void CookieCallback::WaitUntilDone() {
+ loop_to_quit_.Run();
}
StringResultCookieCallback::StringResultCookieCallback() {}
@@ -51,4 +47,15 @@ NoResultCookieCallback::NoResultCookieCallback() {}
NoResultCookieCallback::NoResultCookieCallback(base::Thread* run_in_thread)
: CookieCallback(run_in_thread) {}
+GetCookieListCallback::GetCookieListCallback() {}
+GetCookieListCallback::GetCookieListCallback(base::Thread* run_in_thread)
+ : CookieCallback(run_in_thread) {}
+
+GetCookieListCallback::~GetCookieListCallback() {}
+
+void GetCookieListCallback::Run(const CookieList& cookies) {
+ cookies_ = cookies;
+ CallbackEpilogue();
+}
+
} // namespace net
diff --git a/chromium/net/cookies/cookie_store_test_callbacks.h b/chromium/net/cookies/cookie_store_test_callbacks.h
index eccdf1bff26..207eb02f28b 100644
--- a/chromium/net/cookies/cookie_store_test_callbacks.h
+++ b/chromium/net/cookies/cookie_store_test_callbacks.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include "base/run_loop.h"
+#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_store.h"
namespace base {
@@ -22,28 +24,27 @@ namespace net {
// quit to the thread in which it was constructed.
class CookieCallback {
public:
- // Indicates whether the callback has been called.
- bool did_run() { return did_run_; }
+ // Waits until the callback is invoked.
+ void WaitUntilDone();
protected:
- // Constructs a callback that expects to be called in the given thread and
- // will, upon execution, send a QUIT to the constructing thread.
+ // Constructs a callback that expects to be called in the given thread.
explicit CookieCallback(base::Thread* run_in_thread);
// Constructs a callback that expects to be called in current thread and will
// send a QUIT to the constructing thread.
CookieCallback();
+ ~CookieCallback();
+
// Tests whether the current thread was the caller's thread.
// Sends a QUIT to the constructing thread.
void CallbackEpilogue();
private:
- bool did_run_;
base::Thread* run_in_thread_;
base::MessageLoop* run_in_loop_;
- base::MessageLoop* parent_loop_;
- base::MessageLoop* loop_to_quit_;
+ base::RunLoop loop_to_quit_;
};
// Callback implementations for the asynchronous CookieStore methods.
@@ -94,6 +95,21 @@ class NoResultCookieCallback : public CookieCallback {
}
};
+class GetCookieListCallback : public CookieCallback {
+ public:
+ GetCookieListCallback();
+ explicit GetCookieListCallback(base::Thread* run_in_thread);
+
+ ~GetCookieListCallback();
+
+ void Run(const CookieList& cookies);
+
+ const CookieList& cookies() { return cookies_; }
+
+ private:
+ CookieList cookies_;
+};
+
} // namespace net
#endif // NET_COOKIES_COOKIE_STORE_TEST_CALLBACKS_H_
diff --git a/chromium/net/cookies/cookie_store_test_helpers.cc b/chromium/net/cookies/cookie_store_test_helpers.cc
index e75039c1484..d2dc2106192 100644
--- a/chromium/net/cookies/cookie_store_test_helpers.cc
+++ b/chromium/net/cookies/cookie_store_test_helpers.cc
@@ -34,10 +34,9 @@ namespace net {
const int kDelayedTime = 0;
DelayedCookieMonster::DelayedCookieMonster()
- : cookie_monster_(new CookieMonster(NULL, NULL)),
- did_run_(false),
- result_(false) {
-}
+ : cookie_monster_(new CookieMonster(nullptr, nullptr)),
+ did_run_(false),
+ result_(false) {}
DelayedCookieMonster::~DelayedCookieMonster() {
}
@@ -53,6 +52,12 @@ void DelayedCookieMonster::GetCookiesWithOptionsInternalCallback(
did_run_ = true;
}
+void DelayedCookieMonster::GetCookieListWithOptionsInternalCallback(
+ const CookieList& cookie_list) {
+ cookie_list_ = cookie_list;
+ did_run_ = true;
+}
+
void DelayedCookieMonster::SetCookieWithOptionsAsync(
const GURL& url,
const std::string& cookie_line,
@@ -70,6 +75,24 @@ void DelayedCookieMonster::SetCookieWithOptionsAsync(
base::TimeDelta::FromMilliseconds(kDelayedTime));
}
+void DelayedCookieMonster::SetCookieWithDetailsAsync(
+ const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
+ bool secure,
+ bool http_only,
+ CookieSameSite same_site,
+ bool enforce_strict_secure,
+ CookiePriority priority,
+ const SetCookiesCallback& callback) {
+ NOTREACHED();
+}
+
void DelayedCookieMonster::GetCookiesWithOptionsAsync(
const GURL& url,
const CookieOptions& options,
@@ -87,10 +110,26 @@ void DelayedCookieMonster::GetCookiesWithOptionsAsync(
base::TimeDelta::FromMilliseconds(kDelayedTime));
}
-void DelayedCookieMonster::GetAllCookiesForURLAsync(
+void DelayedCookieMonster::GetCookieListWithOptionsAsync(
const GURL& url,
+ const CookieOptions& options,
+ const CookieMonster::GetCookieListCallback& callback) {
+ did_run_ = false;
+ cookie_monster_->GetCookieListWithOptionsAsync(
+ url, options,
+ base::Bind(
+ &DelayedCookieMonster::GetCookieListWithOptionsInternalCallback,
+ base::Unretained(this)));
+ DCHECK_EQ(did_run_, true);
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::Bind(&DelayedCookieMonster::InvokeGetCookieListCallback,
+ base::Unretained(this), callback),
+ base::TimeDelta::FromMilliseconds(kDelayedTime));
+}
+
+void DelayedCookieMonster::GetAllCookiesAsync(
const GetCookieListCallback& callback) {
- cookie_monster_->GetAllCookiesForURLAsync(url, callback);
+ cookie_monster_->GetAllCookiesAsync(callback);
}
void DelayedCookieMonster::InvokeSetCookiesCallback(
@@ -105,6 +144,12 @@ void DelayedCookieMonster::InvokeGetCookieStringCallback(
callback.Run(cookie_);
}
+void DelayedCookieMonster::InvokeGetCookieListCallback(
+ const CookieMonster::GetCookieListCallback& callback) {
+ if (!callback.is_null())
+ callback.Run(cookie_list_);
+}
+
bool DelayedCookieMonster::SetCookieWithOptions(
const GURL& url,
const std::string& cookie_line,
@@ -131,6 +176,12 @@ void DelayedCookieMonster::DeleteCookieAsync(const GURL& url,
ADD_FAILURE();
}
+void DelayedCookieMonster::DeleteCanonicalCookieAsync(
+ const CanonicalCookie& cookie,
+ const DeleteCallback& callback) {
+ ADD_FAILURE();
+}
+
void DelayedCookieMonster::DeleteAllCreatedBetweenAsync(
const base::Time& delete_begin,
const base::Time& delete_end,
@@ -150,8 +201,8 @@ void DelayedCookieMonster::DeleteSessionCookiesAsync(const DeleteCallback&) {
ADD_FAILURE();
}
-CookieMonster* DelayedCookieMonster::GetCookieMonster() {
- return cookie_monster_.get();
+void DelayedCookieMonster::FlushStore(const base::Closure& callback) {
+ ADD_FAILURE();
}
scoped_ptr<CookieStore::CookieChangedSubscription>
@@ -163,6 +214,10 @@ DelayedCookieMonster::AddCallbackForCookie(
return scoped_ptr<CookieStore::CookieChangedSubscription>();
}
+bool DelayedCookieMonster::IsEphemeral() {
+ return true;
+}
+
//
// CookieURLHelper
//
diff --git a/chromium/net/cookies/cookie_store_test_helpers.h b/chromium/net/cookies/cookie_store_test_helpers.h
index 1750c7f07bd..0ebae5bb9e2 100644
--- a/chromium/net/cookies/cookie_store_test_helpers.h
+++ b/chromium/net/cookies/cookie_store_test_helpers.h
@@ -19,6 +19,8 @@ class DelayedCookieMonster : public CookieStore {
public:
DelayedCookieMonster();
+ ~DelayedCookieMonster() override;
+
// Call the asynchronous CookieMonster function, expect it to immediately
// invoke the internal callback.
// Post a delayed task to invoke the original callback with the results.
@@ -29,13 +31,32 @@ class DelayedCookieMonster : public CookieStore {
const CookieOptions& options,
const CookieMonster::SetCookiesCallback& callback) override;
+ void SetCookieWithDetailsAsync(const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
+ bool secure,
+ bool http_only,
+ CookieSameSite same_site,
+ bool enforce_strict_secure,
+ CookiePriority priority,
+ const SetCookiesCallback& callback) override;
+
void GetCookiesWithOptionsAsync(
const GURL& url,
const CookieOptions& options,
const CookieMonster::GetCookiesCallback& callback) override;
- void GetAllCookiesForURLAsync(const GURL& url,
- const GetCookieListCallback& callback) override;
+ void GetCookieListWithOptionsAsync(
+ const GURL& url,
+ const CookieOptions& options,
+ const GetCookieListCallback& callback) override;
+
+ void GetAllCookiesAsync(const GetCookieListCallback& callback) override;
virtual bool SetCookieWithOptions(const GURL& url,
const std::string& cookie_line,
@@ -51,6 +72,9 @@ class DelayedCookieMonster : public CookieStore {
const std::string& cookie_name,
const base::Closure& callback) override;
+ void DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
+ const DeleteCallback& callback) override;
+
void DeleteAllCreatedBetweenAsync(const base::Time& delete_begin,
const base::Time& delete_end,
const DeleteCallback& callback) override;
@@ -63,18 +87,21 @@ class DelayedCookieMonster : public CookieStore {
void DeleteSessionCookiesAsync(const DeleteCallback&) override;
- CookieMonster* GetCookieMonster() override;
+ void FlushStore(const base::Closure& callback) override;
scoped_ptr<CookieStore::CookieChangedSubscription>
AddCallbackForCookie(const GURL& url, const std::string& name,
const CookieChangedCallback& callback) override;
+ bool IsEphemeral() override;
+
private:
// Be called immediately from CookieMonster.
void SetCookiesInternalCallback(bool result);
void GetCookiesWithOptionsInternalCallback(const std::string& cookie);
+ void GetCookieListWithOptionsInternalCallback(const CookieList& cookie);
// Invoke the original callbacks.
@@ -84,15 +111,18 @@ class DelayedCookieMonster : public CookieStore {
void InvokeGetCookieStringCallback(
const CookieMonster::GetCookiesCallback& callback);
+ void InvokeGetCookieListCallback(
+ const CookieMonster::GetCookieListCallback& callback);
+
friend class base::RefCountedThreadSafe<DelayedCookieMonster>;
- ~DelayedCookieMonster() override;
- scoped_refptr<CookieMonster> cookie_monster_;
+ scoped_ptr<CookieMonster> cookie_monster_;
bool did_run_;
bool result_;
std::string cookie_;
std::string cookie_line_;
+ CookieList cookie_list_;
};
class CookieURLHelper {
diff --git a/chromium/net/cookies/cookie_store_unittest.cc b/chromium/net/cookies/cookie_store_unittest.cc
new file mode 100644
index 00000000000..739336594a7
--- /dev/null
+++ b/chromium/net/cookies/cookie_store_unittest.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 <vector>
+
+#include "base/time/time.h"
+#include "net/cookies/cookie_store.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_options.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace net {
+
+namespace {
+
+// Helper for testing BuildCookieLine
+void MatchCookieLineToVector(
+ const std::string& line,
+ const std::vector<scoped_ptr<CanonicalCookie>>& cookies) {
+ // Test the std::vector<CanonicalCookie> variant
+ // ('CookieMonster::CookieList'):
+ std::vector<CanonicalCookie> list;
+ for (const auto& cookie : cookies)
+ list.push_back(*cookie);
+ EXPECT_EQ(line, CookieStore::BuildCookieLine(list));
+
+ // Test the std::vector<CanonicalCookie*> variant
+ // ('CookieMonster::CanonicalCookieVector' (yes, this is absurd)):
+ std::vector<CanonicalCookie*> ptr_list;
+ for (const auto& cookie : cookies)
+ ptr_list.push_back(cookie.get());
+ EXPECT_EQ(line, CookieStore::BuildCookieLine(ptr_list));
+}
+
+} // namespace
+
+TEST(CookieStoreBaseTest, BuildCookieLine) {
+ std::vector<scoped_ptr<CanonicalCookie>> cookies;
+ GURL url("https://example.com/");
+ CookieOptions options;
+ base::Time now = base::Time::Now();
+ MatchCookieLineToVector("", cookies);
+
+ cookies.push_back(CanonicalCookie::Create(url, "A=B", now, options));
+ MatchCookieLineToVector("A=B", cookies);
+ // Nameless cookies are sent back without a prefixed '='.
+ cookies.push_back(CanonicalCookie::Create(url, "C", now, options));
+ MatchCookieLineToVector("A=B; C", cookies);
+ // Cookies separated by ';'.
+ cookies.push_back(CanonicalCookie::Create(url, "D=E", now, options));
+ MatchCookieLineToVector("A=B; C; D=E", cookies);
+ // BuildCookieLine doesn't reorder the list, it relies on the caller to do so.
+ cookies.push_back(CanonicalCookie::Create(
+ url, "F=G", now - base::TimeDelta::FromSeconds(1), options));
+ MatchCookieLineToVector("A=B; C; D=E; F=G", cookies);
+ // BuildCookieLine doesn't deduplicate.
+ cookies.push_back(CanonicalCookie::Create(
+ url, "D=E", now - base::TimeDelta::FromSeconds(2), options));
+ MatchCookieLineToVector("A=B; C; D=E; F=G; D=E", cookies);
+}
+
+} // namespace net
diff --git a/chromium/net/cookies/cookie_store_unittest.h b/chromium/net/cookies/cookie_store_unittest.h
index fb78d89bbbc..ce8008f21b5 100644
--- a/chromium/net/cookies/cookie_store_unittest.h
+++ b/chromium/net/cookies/cookie_store_unittest.h
@@ -41,12 +41,8 @@ const char kValidCookieLine[] = "A=B; path=/";
// The CookieStoreTestTraits must have the following members:
// struct CookieStoreTestTraits {
-// // Factory function.
-// static scoped_refptr<CookieStore> Create();
-//
-// // The cookie store is a CookieMonster. Only used to test
-// // GetCookieMonster().
-// static const bool is_cookie_monster;
+// // Factory function. Will be called at most once per test.
+// static scoped_ptr<CookieStore> Create();
//
// // The cookie store supports cookies with the exclude_httponly() option.
// static const bool supports_http_only;
@@ -84,7 +80,9 @@ class CookieStoreTest : public testing::Test {
ws_www_google_("ws://www.google.izzle"),
wss_www_google_("wss://www.google.izzle"),
www_google_foo_("http://www.google.izzle/foo"),
- www_google_bar_("http://www.google.izzle/bar") {
+ www_google_bar_("http://www.google.izzle/bar"),
+ http_foo_com_("http://foo.com"),
+ http_bar_com_("http://bar.com") {
// This test may be used outside of the net test suite, and thus may not
// have a message loop.
if (!base::MessageLoop::current())
@@ -102,27 +100,49 @@ class CookieStoreTest : public testing::Test {
CookieOptions options;
if (!CookieStoreTestTraits::supports_http_only)
options.set_include_httponly();
- StringResultCookieCallback callback;
- cs->GetCookiesWithOptionsAsync(
- url, options,
- base::Bind(&StringResultCookieCallback::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.result();
+ return GetCookiesWithOptions(cs, url, options);
}
std::string GetCookiesWithOptions(CookieStore* cs,
const GURL& url,
const CookieOptions& options) {
DCHECK(cs);
- StringResultCookieCallback callback;
- cs->GetCookiesWithOptionsAsync(
- url, options, base::Bind(&StringResultCookieCallback::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.result();
+ GetCookieListCallback callback;
+ cs->GetCookieListWithOptionsAsync(
+ url, options,
+ base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return CookieStore::BuildCookieLine(callback.cookies());
+ }
+
+ CookieList GetCookieListWithOptions(CookieStore* cs,
+ const GURL& url,
+ const CookieOptions& options) {
+ DCHECK(cs);
+ GetCookieListCallback callback;
+ cs->GetCookieListWithOptionsAsync(
+ url, options,
+ base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return callback.cookies();
+ }
+
+ CookieList GetAllCookiesForURL(CookieStore* cs, const GURL& url) {
+ DCHECK(cs);
+ GetCookieListCallback callback;
+ cs->GetAllCookiesForURLAsync(url, base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return callback.cookies();
+ }
+
+ CookieList GetAllCookies(CookieStore* cs) {
+ DCHECK(cs);
+ GetCookieListCallback callback;
+ cs->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return callback.cookies();
}
bool SetCookieWithOptions(CookieStore* cs,
@@ -136,8 +156,32 @@ class CookieStoreTest : public testing::Test {
base::Bind(
&ResultSavingCookieCallback<bool>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
+ return callback.result();
+ }
+
+ bool SetCookieWithDetails(CookieStore* cs,
+ const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ const base::Time creation_time,
+ const base::Time expiration_time,
+ const base::Time last_access_time,
+ bool secure,
+ bool http_only,
+ CookieSameSite same_site,
+ CookiePriority priority) {
+ DCHECK(cs);
+ ResultSavingCookieCallback<bool> callback;
+ cs->SetCookieWithDetailsAsync(
+ url, name, value, domain, path, creation_time, expiration_time,
+ last_access_time, secure, http_only, same_site,
+ false /* enforces strict secure cookies */, priority,
+ base::Bind(&ResultSavingCookieCallback<bool>::Run,
+ base::Unretained(&callback)));
+ callback.WaitUntilDone();
return callback.result();
}
@@ -171,8 +215,17 @@ class CookieStoreTest : public testing::Test {
cs->DeleteCookieAsync(
url, cookie_name,
base::Bind(&NoResultCookieCallback::Run, base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
+ }
+
+ int DeleteCanonicalCookie(CookieStore* cs, const CanonicalCookie& cookie) {
+ DCHECK(cs);
+ ResultSavingCookieCallback<int> callback;
+ cs->DeleteCanonicalCookieAsync(
+ cookie, base::Bind(&ResultSavingCookieCallback<int>::Run,
+ base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return callback.result();
}
int DeleteCreatedBetween(CookieStore* cs,
@@ -185,8 +238,7 @@ class CookieStoreTest : public testing::Test {
base::Bind(
&ResultSavingCookieCallback<int>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.result();
}
@@ -201,8 +253,7 @@ class CookieStoreTest : public testing::Test {
base::Bind(
&ResultSavingCookieCallback<int>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.result();
}
@@ -213,23 +264,24 @@ class CookieStoreTest : public testing::Test {
base::Bind(
&ResultSavingCookieCallback<int>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.result();
}
- void RunFor(int ms) {
- // Runs the test thread message loop for up to |ms| milliseconds.
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&base::MessageLoop::QuitWhenIdle,
- weak_factory_->GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(ms));
- base::MessageLoop::current()->Run();
- weak_factory_->InvalidateWeakPtrs();
+ int DeleteAll(CookieStore* cs) {
+ DCHECK(cs);
+ ResultSavingCookieCallback<int> callback;
+ cs->DeleteAllAsync(base::Bind(&ResultSavingCookieCallback<int>::Run,
+ base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return callback.result();
}
- scoped_refptr<CookieStore> GetCookieStore() {
- return CookieStoreTestTraits::Create();
+ // Returns the CookieStore for the test - each test only uses one CookieStore.
+ CookieStore* GetCookieStore() {
+ if (!cookie_store_)
+ cookie_store_ = CookieStoreTestTraits::Create();
+ return cookie_store_.get();
}
// Compares two cookie lines.
@@ -264,6 +316,8 @@ class CookieStoreTest : public testing::Test {
const CookieURLHelper wss_www_google_;
const CookieURLHelper www_google_foo_;
const CookieURLHelper www_google_bar_;
+ const CookieURLHelper http_foo_com_;
+ const CookieURLHelper http_bar_com_;
scoped_ptr<base::WeakPtrFactory<base::MessageLoop> > weak_factory_;
scoped_ptr<base::MessageLoop> message_loop_;
@@ -277,383 +331,467 @@ class CookieStoreTest : public testing::Test {
EXPECT_TRUE(tokens.insert(tokenizer.token()).second);
return tokens;
}
+
+ scoped_ptr<CookieStore> cookie_store_;
};
TYPED_TEST_CASE_P(CookieStoreTest);
-TYPED_TEST_P(CookieStoreTest, TypeTest) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_EQ(cs->GetCookieMonster(),
- (TypeParam::is_cookie_monster) ?
- static_cast<CookieMonster*>(cs.get()) : NULL);
+TYPED_TEST_P(CookieStoreTest, SetCookieWithDetailsAsync) {
+ CookieStore* cs = this->GetCookieStore();
+
+ base::Time two_hours_ago = base::Time::Now() - base::TimeDelta::FromHours(2);
+ base::Time one_hour_ago = base::Time::Now() - base::TimeDelta::FromHours(1);
+ base::Time one_hour_from_now =
+ base::Time::Now() + base::TimeDelta::FromHours(1);
+
+ EXPECT_TRUE(this->SetCookieWithDetails(
+ cs, this->www_google_foo_.url(), "A", "B", std::string(), "/foo",
+ one_hour_ago, one_hour_from_now, base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+ // Note that for the creation time to be set exactly, without modification,
+ // it must be different from the one set by the line above.
+ EXPECT_TRUE(this->SetCookieWithDetails(
+ cs, this->www_google_bar_.url(), "C", "D", this->www_google_bar_.domain(),
+ "/bar", two_hours_ago, base::Time(), one_hour_ago, false, true,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+ EXPECT_TRUE(this->SetCookieWithDetails(
+ cs, this->http_www_google_.url(), "E", "F", std::string(), std::string(),
+ base::Time(), base::Time(), base::Time(), true, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+
+ // Test that malformed attributes fail to set the cookie.
+ EXPECT_FALSE(this->SetCookieWithDetails(
+ cs, this->www_google_foo_.url(), " A", "B", std::string(), "/foo",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+ EXPECT_FALSE(this->SetCookieWithDetails(
+ cs, this->www_google_foo_.url(), "A;", "B", std::string(), "/foo",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+ EXPECT_FALSE(this->SetCookieWithDetails(
+ cs, this->www_google_foo_.url(), "A=", "B", std::string(), "/foo",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+ EXPECT_FALSE(this->SetCookieWithDetails(
+ cs, this->www_google_foo_.url(), "A", "B", "google.ozzzzzzle", "foo",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+ EXPECT_FALSE(this->SetCookieWithDetails(
+ cs, this->www_google_foo_.url(), "A=", "B", std::string(), "foo",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+
+ // Get all the cookies for a given URL, regardless of properties. This 'get()'
+ // operation shouldn't update the access time, as the test checks that the
+ // access time is set properly upon creation. Updating the access time would
+ // make that difficult.
+ CookieOptions options;
+ options.set_include_httponly();
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ options.set_do_not_update_access_time();
+
+ CookieList cookies =
+ this->GetCookieListWithOptions(cs, this->www_google_foo_.url(), options);
+ CookieList::iterator it = cookies.begin();
+
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ("A", it->Name());
+ EXPECT_EQ("B", it->Value());
+ EXPECT_EQ(this->www_google_foo_.host(), it->Domain());
+ EXPECT_EQ("/foo", it->Path());
+ EXPECT_EQ(one_hour_ago, it->CreationDate());
+ EXPECT_TRUE(it->IsPersistent());
+ // Expect expiration date is in the right range. Some cookie implementations
+ // may not record it with millisecond accuracy.
+ EXPECT_LE((one_hour_from_now - it->ExpiryDate()).magnitude().InSeconds(), 5);
+ // Some CookieStores don't store last access date.
+ if (!it->LastAccessDate().is_null())
+ EXPECT_EQ(one_hour_ago, it->LastAccessDate());
+ EXPECT_FALSE(it->IsSecure());
+ EXPECT_FALSE(it->IsHttpOnly());
+
+ ASSERT_TRUE(++it == cookies.end());
+
+ // Verify that the cookie was set as 'httponly' by passing in a CookieOptions
+ // that excludes them and getting an empty result.
+ if (TypeParam::supports_http_only) {
+ cookies = this->GetCookieListWithOptions(cs, this->www_google_bar_.url(),
+ CookieOptions());
+ it = cookies.begin();
+ ASSERT_TRUE(it == cookies.end());
+ }
+
+ // Get the cookie using the wide open |options|:
+ cookies =
+ this->GetCookieListWithOptions(cs, this->www_google_bar_.url(), options);
+ it = cookies.begin();
+
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ("C", it->Name());
+ EXPECT_EQ("D", it->Value());
+ EXPECT_EQ(this->www_google_bar_.Format(".%D"), it->Domain());
+ EXPECT_EQ("/bar", it->Path());
+ EXPECT_EQ(two_hours_ago, it->CreationDate());
+ EXPECT_FALSE(it->IsPersistent());
+ // Some CookieStores don't store last access date.
+ if (!it->LastAccessDate().is_null())
+ EXPECT_EQ(one_hour_ago, it->LastAccessDate());
+ EXPECT_FALSE(it->IsSecure());
+ EXPECT_TRUE(it->IsHttpOnly());
+
+ EXPECT_TRUE(++it == cookies.end());
+
+ cookies = this->GetCookieListWithOptions(cs, this->https_www_google_.url(),
+ options);
+ it = cookies.begin();
+
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ("E", it->Name());
+ EXPECT_EQ("F", it->Value());
+ EXPECT_EQ("/", it->Path());
+ EXPECT_EQ(this->https_www_google_.host(), it->Domain());
+ // Cookie should have its creation time set, and be in a reasonable range.
+ EXPECT_LE((base::Time::Now() - it->CreationDate()).magnitude().InMinutes(),
+ 2);
+ EXPECT_FALSE(it->IsPersistent());
+ // Some CookieStores don't store last access date.
+ if (!it->LastAccessDate().is_null())
+ EXPECT_EQ(it->CreationDate(), it->LastAccessDate());
+ EXPECT_TRUE(it->IsSecure());
+ EXPECT_FALSE(it->IsHttpOnly());
+
+ EXPECT_TRUE(++it == cookies.end());
}
TYPED_TEST_P(CookieStoreTest, DomainTest) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=B"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "A=B"));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
EXPECT_TRUE(
- this->SetCookie(cs.get(), this->http_www_google_.url(),
+ this->SetCookie(cs, this->http_www_google_.url(),
this->http_www_google_.Format("C=D; domain=.%D")));
- this->MatchCookieLines(
- "A=B; C=D", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B; C=D",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Verify that A=B was set as a host cookie rather than a domain
// cookie -- should not be accessible from a sub sub-domain.
this->MatchCookieLines(
- "C=D",
- this->GetCookies(
- cs.get(), GURL(this->http_www_google_.Format("http://foo.www.%D"))));
+ "C=D", this->GetCookies(
+ cs, GURL(this->http_www_google_.Format("http://foo.www.%D"))));
// Test and make sure we find domain cookies on the same domain.
EXPECT_TRUE(
- this->SetCookie(cs.get(), this->http_www_google_.url(),
+ this->SetCookie(cs, this->http_www_google_.url(),
this->http_www_google_.Format("E=F; domain=.www.%D")));
- this->MatchCookieLines(
- "A=B; C=D; E=F",
- this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B; C=D; E=F",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Test setting a domain= that doesn't start w/ a dot, should
// treat it as a domain cookie, as if there was a pre-pended dot.
EXPECT_TRUE(
- this->SetCookie(cs.get(), this->http_www_google_.url(),
+ this->SetCookie(cs, this->http_www_google_.url(),
this->http_www_google_.Format("G=H; domain=www.%D")));
- this->MatchCookieLines(
- "A=B; C=D; E=F; G=H",
- this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B; C=D; E=F; G=H",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Test domain enforcement, should fail on a sub-domain or something too deep.
EXPECT_FALSE(
- this->SetCookie(cs.get(), this->http_www_google_.url(),
+ this->SetCookie(cs, this->http_www_google_.url(),
this->http_www_google_.Format("I=J; domain=.%R")));
this->MatchCookieLines(
std::string(),
- this->GetCookies(cs.get(),
- GURL(this->http_www_google_.Format("http://a.%R"))));
+ this->GetCookies(cs, GURL(this->http_www_google_.Format("http://a.%R"))));
EXPECT_FALSE(this->SetCookie(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
this->http_www_google_.Format("K=L; domain=.bla.www.%D")));
this->MatchCookieLines(
"C=D; E=F; G=H",
this->GetCookies(
- cs.get(), GURL(this->http_www_google_.Format("http://bla.www.%D"))));
- this->MatchCookieLines(
- "A=B; C=D; E=F; G=H",
- this->GetCookies(cs.get(), this->http_www_google_.url()));
+ cs, GURL(this->http_www_google_.Format("http://bla.www.%D"))));
+ this->MatchCookieLines("A=B; C=D; E=F; G=H",
+ this->GetCookies(cs, this->http_www_google_.url()));
}
// FireFox recognizes domains containing trailing periods as valid.
// IE and Safari do not. Assert the expected policy here.
TYPED_TEST_P(CookieStoreTest, DomainWithTrailingDotTest) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_FALSE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_FALSE(this->SetCookie(cs, this->http_www_google_.url(),
"a=1; domain=.www.google.com."));
- EXPECT_FALSE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_FALSE(this->SetCookie(cs, this->http_www_google_.url(),
"b=2; domain=.www.google.com.."));
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
}
// Test that cookies can bet set on higher level domains.
-// http://b/issue?id=896491
TYPED_TEST_P(CookieStoreTest, ValidSubdomainTest) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
GURL url_abcd("http://a.b.c.d.com");
GURL url_bcd("http://b.c.d.com");
GURL url_cd("http://c.d.com");
GURL url_d("http://d.com");
- EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "a=1; domain=.a.b.c.d.com"));
- EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "b=2; domain=.b.c.d.com"));
- EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "c=3; domain=.c.d.com"));
- EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "d=4; domain=.d.com"));
+ EXPECT_TRUE(this->SetCookie(cs, url_abcd, "a=1; domain=.a.b.c.d.com"));
+ EXPECT_TRUE(this->SetCookie(cs, url_abcd, "b=2; domain=.b.c.d.com"));
+ EXPECT_TRUE(this->SetCookie(cs, url_abcd, "c=3; domain=.c.d.com"));
+ EXPECT_TRUE(this->SetCookie(cs, url_abcd, "d=4; domain=.d.com"));
- this->MatchCookieLines("a=1; b=2; c=3; d=4",
- this->GetCookies(cs.get(), url_abcd));
- this->MatchCookieLines("b=2; c=3; d=4", this->GetCookies(cs.get(), url_bcd));
- this->MatchCookieLines("c=3; d=4", this->GetCookies(cs.get(), url_cd));
- this->MatchCookieLines("d=4", this->GetCookies(cs.get(), url_d));
+ this->MatchCookieLines("a=1; b=2; c=3; d=4", this->GetCookies(cs, url_abcd));
+ this->MatchCookieLines("b=2; c=3; d=4", this->GetCookies(cs, url_bcd));
+ this->MatchCookieLines("c=3; d=4", this->GetCookies(cs, url_cd));
+ this->MatchCookieLines("d=4", this->GetCookies(cs, url_d));
// Check that the same cookie can exist on different sub-domains.
- EXPECT_TRUE(this->SetCookie(cs.get(), url_bcd, "X=bcd; domain=.b.c.d.com"));
- EXPECT_TRUE(this->SetCookie(cs.get(), url_bcd, "X=cd; domain=.c.d.com"));
+ EXPECT_TRUE(this->SetCookie(cs, url_bcd, "X=bcd; domain=.b.c.d.com"));
+ EXPECT_TRUE(this->SetCookie(cs, url_bcd, "X=cd; domain=.c.d.com"));
this->MatchCookieLines("b=2; c=3; d=4; X=bcd; X=cd",
- this->GetCookies(cs.get(), url_bcd));
- this->MatchCookieLines("c=3; d=4; X=cd", this->GetCookies(cs.get(), url_cd));
+ this->GetCookies(cs, url_bcd));
+ this->MatchCookieLines("c=3; d=4; X=cd", this->GetCookies(cs, url_cd));
}
// Test that setting a cookie which specifies an invalid domain has
// no side-effect. An invalid domain in this context is one which does
// not match the originating domain.
-// http://b/issue?id=896472
TYPED_TEST_P(CookieStoreTest, InvalidDomainTest) {
- {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url_foobar("http://foo.bar.com");
-
- // More specific sub-domain than allowed.
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "a=1; domain=.yo.foo.bar.com"));
-
- EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "b=2; domain=.foo.com"));
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "c=3; domain=.bar.foo.com"));
-
- // Different TLD, but the rest is a substring.
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "d=4; domain=.foo.bar.com.net"));
-
- // A substring that isn't really a parent domain.
- EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "e=5; domain=ar.com"));
-
- // Completely invalid domains:
- EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "f=6; domain=."));
- EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "g=7; domain=/"));
- EXPECT_FALSE(this->SetCookie(
- cs.get(), url_foobar, "h=8; domain=http://foo.bar.com"));
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "i=9; domain=..foo.bar.com"));
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "j=10; domain=..bar.com"));
-
- // Make sure there isn't something quirky in the domain canonicalization
- // that supports full URL semantics.
- EXPECT_FALSE(this->SetCookie(
- cs.get(), url_foobar, "k=11; domain=.foo.bar.com?blah"));
- EXPECT_FALSE(this->SetCookie(
- cs.get(), url_foobar, "l=12; domain=.foo.bar.com/blah"));
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "m=13; domain=.foo.bar.com:80"));
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "n=14; domain=.foo.bar.com:"));
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "o=15; domain=.foo.bar.com#sup"));
+ CookieStore* cs = this->GetCookieStore();
+ GURL url_foobar("http://foo.bar.com");
- this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), url_foobar));
- }
+ // More specific sub-domain than allowed.
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "a=1; domain=.yo.foo.bar.com"));
- {
- // Make sure the cookie code hasn't gotten its subdomain string handling
- // reversed, missed a suffix check, etc. It's important here that the two
- // hosts below have the same domain + registry.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url_foocom("http://foo.com.com");
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foocom, "a=1; domain=.foo.com.com.com"));
- this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), url_foocom));
- }
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "b=2; domain=.foo.com"));
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "c=3; domain=.bar.foo.com"));
+
+ // Different TLD, but the rest is a substring.
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "d=4; domain=.foo.bar.com.net"));
+
+ // A substring that isn't really a parent domain.
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "e=5; domain=ar.com"));
+
+ // Completely invalid domains:
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "f=6; domain=."));
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "g=7; domain=/"));
+ EXPECT_FALSE(
+ this->SetCookie(cs, url_foobar, "h=8; domain=http://foo.bar.com"));
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "i=9; domain=..foo.bar.com"));
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "j=10; domain=..bar.com"));
+
+ // Make sure there isn't something quirky in the domain canonicalization
+ // that supports full URL semantics.
+ EXPECT_FALSE(
+ this->SetCookie(cs, url_foobar, "k=11; domain=.foo.bar.com?blah"));
+ EXPECT_FALSE(
+ this->SetCookie(cs, url_foobar, "l=12; domain=.foo.bar.com/blah"));
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "m=13; domain=.foo.bar.com:80"));
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "n=14; domain=.foo.bar.com:"));
+ EXPECT_FALSE(
+ this->SetCookie(cs, url_foobar, "o=15; domain=.foo.bar.com#sup"));
+
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url_foobar));
}
-// Test the behavior of omitting dot prefix from domain, should
-// function the same as FireFox.
-// http://b/issue?id=889898
-TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotTest) {
- { // The omission of dot results in setting a domain cookie.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url_hosted("http://manage.hosted.filefront.com");
- GURL url_filefront("http://www.filefront.com");
- EXPECT_TRUE(
- this->SetCookie(cs.get(), url_hosted, "sawAd=1; domain=filefront.com"));
- this->MatchCookieLines("sawAd=1", this->GetCookies(cs.get(), url_hosted));
- this->MatchCookieLines("sawAd=1",
- this->GetCookies(cs.get(), url_filefront));
- }
+// Make sure the cookie code hasn't gotten its subdomain string handling
+// reversed, missed a suffix check, etc. It's important here that the two
+// hosts below have the same domain + registry.
+TYPED_TEST_P(CookieStoreTest, InvalidDomainSameDomainAndRegistry) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url_foocom("http://foo.com.com");
+ EXPECT_FALSE(this->SetCookie(cs, url_foocom, "a=1; domain=.foo.com.com.com"));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url_foocom));
+}
- { // Even when the domains match exactly, don't consider it host cookie.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://www.google.com");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=www.google.com"));
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- this->MatchCookieLines(
- "a=1", this->GetCookies(cs.get(), GURL("http://sub.www.google.com")));
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), GURL("http://something-else.com")));
- }
+// Setting the domain without a dot on a parent domain should add a domain
+// cookie.
+TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotParentDomain) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url_hosted("http://manage.hosted.filefront.com");
+ GURL url_filefront("http://www.filefront.com");
+ EXPECT_TRUE(this->SetCookie(cs, url_hosted, "sawAd=1; domain=filefront.com"));
+ this->MatchCookieLines("sawAd=1", this->GetCookies(cs, url_hosted));
+ this->MatchCookieLines("sawAd=1", this->GetCookies(cs, url_filefront));
+}
+
+// Even when the specified domain matches the domain of the URL exactly, treat
+// it as setting a domain cookie.
+TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotSameDomain) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://www.google.com");
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=www.google.com"));
+ this->MatchCookieLines("a=1", this->GetCookies(cs, url));
+ this->MatchCookieLines(
+ "a=1", this->GetCookies(cs, GURL("http://sub.www.google.com")));
+ this->MatchCookieLines(
+ std::string(), this->GetCookies(cs, GURL("http://something-else.com")));
}
// Test that the domain specified in cookie string is treated case-insensitive
-// http://b/issue?id=896475.
TYPED_TEST_P(CookieStoreTest, CaseInsensitiveDomainTest) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
GURL url("http://www.google.com");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=.GOOGLE.COM"));
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "b=2; domain=.wWw.gOOgLE.coM"));
- this->MatchCookieLines("a=1; b=2", this->GetCookies(cs.get(), url));
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=.GOOGLE.COM"));
+ EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.wWw.gOOgLE.coM"));
+ this->MatchCookieLines("a=1; b=2", this->GetCookies(cs, url));
}
TYPED_TEST_P(CookieStoreTest, TestIpAddress) {
GURL url_ip("http://1.2.3.4/weee");
- {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_TRUE(this->SetCookie(cs.get(), url_ip, kValidCookieLine));
- this->MatchCookieLines("A=B", this->GetCookies(cs.get(), url_ip));
- }
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_TRUE(this->SetCookie(cs, url_ip, kValidCookieLine));
+ this->MatchCookieLines("A=B", this->GetCookies(cs, url_ip));
+}
- { // IP addresses should not be able to set domain cookies.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "b=2; domain=.1.2.3.4"));
- EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "c=3; domain=.3.4"));
- this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url_ip));
- // It should be allowed to set a cookie if domain= matches the IP address
- // exactly. This matches IE/Firefox, even though it seems a bit wrong.
- EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "b=2; domain=1.2.3.3"));
- this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url_ip));
- EXPECT_TRUE(this->SetCookie(cs.get(), url_ip, "b=2; domain=1.2.3.4"));
- this->MatchCookieLines("b=2", this->GetCookies(cs.get(), url_ip));
- }
+// IP addresses should not be able to set domain cookies.
+TYPED_TEST_P(CookieStoreTest, TestIpAddressNoDomainCookies) {
+ GURL url_ip("http://1.2.3.4/weee");
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_FALSE(this->SetCookie(cs, url_ip, "b=2; domain=.1.2.3.4"));
+ EXPECT_FALSE(this->SetCookie(cs, url_ip, "c=3; domain=.3.4"));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url_ip));
+ // It should be allowed to set a cookie if domain= matches the IP address
+ // exactly. This matches IE/Firefox, even though it seems a bit wrong.
+ EXPECT_FALSE(this->SetCookie(cs, url_ip, "b=2; domain=1.2.3.3"));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url_ip));
+ EXPECT_TRUE(this->SetCookie(cs, url_ip, "b=2; domain=1.2.3.4"));
+ this->MatchCookieLines("b=2", this->GetCookies(cs, url_ip));
}
-// Test host cookies, and setting of cookies on TLD.
-TYPED_TEST_P(CookieStoreTest, TestNonDottedAndTLD) {
- if (TypeParam::supports_non_dotted_domains) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://com/");
- // Allow setting on "com", (but only as a host cookie).
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.com"));
-
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- // Make sure it doesn't show up for a normal .com, it should be a host
- // not a domain cookie.
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.com/")));
- this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), GURL("http://.com/")));
- }
+// Test a TLD setting cookies on itself.
+TYPED_TEST_P(CookieStoreTest, TestTLD) {
+ if (!TypeParam::supports_non_dotted_domains)
+ return;
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://com/");
- if (TypeParam::supports_non_dotted_domains) {
- // Exact matches between the domain attribute and the host are treated as
- // host cookies, not domain cookies.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://com/");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=com"));
+ // Allow setting on "com", (but only as a host cookie).
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
+ // Domain cookies can't be set.
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.com"));
+ // Exact matches between the domain attribute and the host are treated as
+ // host cookies, not domain cookies.
+ EXPECT_TRUE(this->SetCookie(cs, url, "c=3; domain=com"));
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- // Make sure it doesn't show up for a normal .com, it should be a host
- // not a domain cookie.
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.com/")));
- this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), GURL("http://.com/")));
- }
+ this->MatchCookieLines("a=1; c=3", this->GetCookies(cs, url));
- {
- // http://com. should be treated the same as http://com.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://com./index.html");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(),
- GURL("http://hopefully-no-cookies.com./")));
- }
+ // Make sure they don't show up for a normal .com, they should be host,
+ // domain, cookies.
+ this->MatchCookieLines(
+ std::string(),
+ this->GetCookies(cs, GURL("http://hopefully-no-cookies.com/")));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, GURL("http://.com/")));
+}
- { // Should not be able to set host cookie from a subdomain.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://a.b");
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.b"));
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=b"));
- this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
- }
+// http://com. should be treated the same as http://com.
+TYPED_TEST_P(CookieStoreTest, TestTLDWithTerminalDot) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://com./index.html");
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.com."));
+ this->MatchCookieLines("a=1", this->GetCookies(cs, url));
+ this->MatchCookieLines(
+ std::string(),
+ this->GetCookies(cs, GURL("http://hopefully-no-cookies.com./")));
+}
- { // Same test as above, but explicitly on a known TLD (com).
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://google.com");
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.com"));
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=com"));
- this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
- }
+TYPED_TEST_P(CookieStoreTest, TestSubdomainSettingCookiesOnUnknownTLD) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://a.b");
+ EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.b"));
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=b"));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url));
+}
- { // Make sure can't set cookie on TLD which is dotted.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://google.co.uk");
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.co.uk"));
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.uk"));
- this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), GURL("http://something-else.co.uk")));
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), GURL("http://something-else.uk")));
- }
+TYPED_TEST_P(CookieStoreTest, TestSubdomainSettingCookiesOnKnownTLD) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://google.com");
+ EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.com"));
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=com"));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url));
+}
- { // Intranet URLs should only be able to set host cookies.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://b");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.b"));
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- }
+TYPED_TEST_P(CookieStoreTest, TestSubdomainSettingCookiesOnKnownDottedTLD) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://google.co.uk");
+ EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.co.uk"));
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.uk"));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url));
+ this->MatchCookieLines(
+ std::string(), this->GetCookies(cs, GURL("http://something-else.co.uk")));
+ this->MatchCookieLines(
+ std::string(), this->GetCookies(cs, GURL("http://something-else.uk")));
+}
- if (TypeParam::supports_non_dotted_domains) {
- // Exact matches between the domain attribute and an intranet host are
- // treated as host cookies, not domain cookies.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://b/");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=b"));
+// Intranet URLs should only be able to set host cookies.
+TYPED_TEST_P(CookieStoreTest, TestSettingCookiesOnUnknownTLD) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://b");
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.b"));
+ this->MatchCookieLines("a=1", this->GetCookies(cs, url));
+}
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- // Make sure it doesn't show up for an intranet subdomain, it should be a
- // host not a domain cookie.
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.b/")));
- this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), GURL("http://.b/")));
- }
+// Exact matches between the domain attribute and an intranet host are
+// treated as host cookies, not domain cookies.
+TYPED_TEST_P(CookieStoreTest, TestSettingCookiesWithHostDomainOnUnknownTLD) {
+ if (!TypeParam::supports_non_dotted_domains)
+ return;
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://b");
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=b"));
+
+ this->MatchCookieLines("a=1", this->GetCookies(cs, url));
+
+ // Make sure it doesn't show up for an intranet subdomain, it should be
+ // a host, not domain, cookie.
+ this->MatchCookieLines(
+ std::string(),
+ this->GetCookies(cs, GURL("http://hopefully-no-cookies.b/")));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, GURL("http://.b/")));
}
// Test reading/writing cookies when the domain ends with a period,
// as in "www.google.com."
TYPED_TEST_P(CookieStoreTest, TestHostEndsWithDot) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
GURL url("http://www.google.com");
GURL url_with_dot("http://www.google.com.");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
+ this->MatchCookieLines("a=1", this->GetCookies(cs, url));
// Do not share cookie space with the dot version of domain.
// Note: this is not what FireFox does, but it _is_ what IE+Safari do.
if (TypeParam::preserves_trailing_dots) {
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url, "b=2; domain=.www.google.com."));
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- EXPECT_TRUE(
- this->SetCookie(cs.get(), url_with_dot, "b=2; domain=.google.com."));
- this->MatchCookieLines("b=2", this->GetCookies(cs.get(), url_with_dot));
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.www.google.com."));
+ this->MatchCookieLines("a=1", this->GetCookies(cs, url));
+ EXPECT_TRUE(this->SetCookie(cs, url_with_dot, "b=2; domain=.google.com."));
+ this->MatchCookieLines("b=2", this->GetCookies(cs, url_with_dot));
} else {
- EXPECT_TRUE(
- this->SetCookie(cs.get(), url, "b=2; domain=.www.google.com."));
- this->MatchCookieLines("a=1 b=2", this->GetCookies(cs.get(), url));
+ EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.www.google.com."));
+ this->MatchCookieLines("a=1 b=2", this->GetCookies(cs, url));
// Setting this cookie should fail, since the trailing dot on the domain
// isn't preserved, and then the domain mismatches the URL.
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_with_dot, "b=2; domain=.google.com."));
+ EXPECT_FALSE(this->SetCookie(cs, url_with_dot, "b=2; domain=.google.com."));
}
// Make sure there weren't any side effects.
this->MatchCookieLines(
std::string(),
- this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.com/")));
+ this->GetCookies(cs, GURL("http://hopefully-no-cookies.com/")));
this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), GURL("http://.com/")));
+ this->GetCookies(cs, GURL("http://.com/")));
}
TYPED_TEST_P(CookieStoreTest, InvalidScheme) {
if (!TypeParam::filters_schemes)
return;
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_FALSE(
- this->SetCookie(cs.get(), this->ftp_google_.url(), kValidCookieLine));
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_FALSE(this->SetCookie(cs, this->ftp_google_.url(), kValidCookieLine));
}
TYPED_TEST_P(CookieStoreTest, InvalidScheme_Read) {
@@ -663,39 +801,38 @@ TYPED_TEST_P(CookieStoreTest, InvalidScheme_Read) {
const std::string kValidDomainCookieLine =
this->http_www_google_.Format("A=B; path=/; domain=%D");
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
kValidDomainCookieLine));
this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), this->ftp_google_.url()));
+ this->GetCookies(cs, this->ftp_google_.url()));
+ EXPECT_EQ(0U, this->GetCookieListWithOptions(cs, this->ftp_google_.url(),
+ CookieOptions())
+ .size());
}
TYPED_TEST_P(CookieStoreTest, PathTest) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
std::string url("http://www.google.izzle");
- EXPECT_TRUE(this->SetCookie(cs.get(), GURL(url), "A=B; path=/wee"));
- this->MatchCookieLines("A=B", this->GetCookies(cs.get(), GURL(url + "/wee")));
- this->MatchCookieLines("A=B",
- this->GetCookies(cs.get(), GURL(url + "/wee/")));
- this->MatchCookieLines("A=B",
- this->GetCookies(cs.get(), GURL(url + "/wee/war")));
+ EXPECT_TRUE(this->SetCookie(cs, GURL(url), "A=B; path=/wee"));
+ this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee")));
+ this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee/")));
+ this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee/war")));
this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), GURL(url + "/wee/war/more/more")));
+ "A=B", this->GetCookies(cs, GURL(url + "/wee/war/more/more")));
if (!TypeParam::has_path_prefix_bug)
this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), GURL(url + "/weehee")));
- this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), GURL(url + "/")));
+ this->GetCookies(cs, GURL(url + "/weehee")));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, GURL(url + "/")));
// If we add a 0 length path, it should default to /
- EXPECT_TRUE(this->SetCookie(cs.get(), GURL(url), "A=C; path="));
- this->MatchCookieLines("A=B; A=C",
- this->GetCookies(cs.get(), GURL(url + "/wee")));
- this->MatchCookieLines("A=C", this->GetCookies(cs.get(), GURL(url + "/")));
+ EXPECT_TRUE(this->SetCookie(cs, GURL(url), "A=C; path="));
+ this->MatchCookieLines("A=B; A=C", this->GetCookies(cs, GURL(url + "/wee")));
+ this->MatchCookieLines("A=C", this->GetCookies(cs, GURL(url + "/")));
}
TYPED_TEST_P(CookieStoreTest, EmptyExpires) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
CookieOptions options;
if (!TypeParam::supports_http_only)
options.set_include_httponly();
@@ -704,152 +841,168 @@ TYPED_TEST_P(CookieStoreTest, EmptyExpires) {
"ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires=";
std::string cookie_line = "ACSTM=20130308043820420042";
- this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
+ this->SetCookieWithOptions(cs, url, set_cookie_line, options);
this->MatchCookieLines(cookie_line,
- this->GetCookiesWithOptions(cs.get(), url, options));
+ this->GetCookiesWithOptions(cs, url, options));
options.set_server_time(base::Time::Now() - base::TimeDelta::FromHours(1));
- this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
+ this->SetCookieWithOptions(cs, url, set_cookie_line, options);
this->MatchCookieLines(cookie_line,
- this->GetCookiesWithOptions(cs.get(), url, options));
+ this->GetCookiesWithOptions(cs, url, options));
options.set_server_time(base::Time::Now() + base::TimeDelta::FromHours(1));
- this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
+ this->SetCookieWithOptions(cs, url, set_cookie_line, options);
this->MatchCookieLines(cookie_line,
- this->GetCookiesWithOptions(cs.get(), url, options));
+ this->GetCookiesWithOptions(cs, url, options));
}
TYPED_TEST_P(CookieStoreTest, HttpOnlyTest) {
if (!TypeParam::supports_http_only)
return;
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
CookieOptions options;
options.set_include_httponly();
// Create a httponly cookie.
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookieWithOptions(cs, this->http_www_google_.url(),
"A=B; httponly", options));
// Check httponly read protection.
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
- this->MatchCookieLines(
- "A=B", this->GetCookiesWithOptions(cs.get(), this->http_www_google_.url(),
- options));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
+ this->MatchCookieLines("A=B", this->GetCookiesWithOptions(
+ cs, this->http_www_google_.url(), options));
// Check httponly overwrite protection.
- EXPECT_FALSE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=C"));
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
- this->MatchCookieLines(
- "A=B", this->GetCookiesWithOptions(cs.get(), this->http_www_google_.url(),
- options));
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
+ EXPECT_FALSE(this->SetCookie(cs, this->http_www_google_.url(), "A=C"));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
+ this->MatchCookieLines("A=B", this->GetCookiesWithOptions(
+ cs, this->http_www_google_.url(), options));
+ EXPECT_TRUE(this->SetCookieWithOptions(cs, this->http_www_google_.url(),
"A=C", options));
- this->MatchCookieLines(
- "A=C", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=C",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Check httponly create protection.
EXPECT_FALSE(
- this->SetCookie(cs.get(), this->http_www_google_.url(), "B=A; httponly"));
- this->MatchCookieLines(
- "A=C", this->GetCookiesWithOptions(cs.get(), this->http_www_google_.url(),
- options));
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
+ this->SetCookie(cs, this->http_www_google_.url(), "B=A; httponly"));
+ this->MatchCookieLines("A=C", this->GetCookiesWithOptions(
+ cs, this->http_www_google_.url(), options));
+ EXPECT_TRUE(this->SetCookieWithOptions(cs, this->http_www_google_.url(),
"B=A; httponly", options));
- this->MatchCookieLines("A=C; B=A",
- this->GetCookiesWithOptions(
- cs.get(), this->http_www_google_.url(), options));
this->MatchCookieLines(
- "A=C", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ "A=C; B=A",
+ this->GetCookiesWithOptions(cs, this->http_www_google_.url(), options));
+ this->MatchCookieLines("A=C",
+ this->GetCookies(cs, this->http_www_google_.url()));
}
TYPED_TEST_P(CookieStoreTest, TestCookieDeletion) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
// Create a session cookie.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
- kValidCookieLine));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), kValidCookieLine));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Delete it via Max-Age.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; max-age=0"));
- this->MatchCookieLineWithTimeout(cs.get(), this->http_www_google_.url(),
+ this->MatchCookieLineWithTimeout(cs, this->http_www_google_.url(),
std::string());
// Create a session cookie.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
- kValidCookieLine));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), kValidCookieLine));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Delete it via Expires.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
std::string(kValidCookieLine) +
"; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
// Create a persistent cookie.
EXPECT_TRUE(this->SetCookie(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Delete it via Max-Age.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; max-age=0"));
- this->MatchCookieLineWithTimeout(cs.get(), this->http_www_google_.url(),
+ this->MatchCookieLineWithTimeout(cs, this->http_www_google_.url(),
std::string());
// Create a persistent cookie.
EXPECT_TRUE(this->SetCookie(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Delete it via Expires.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
std::string(kValidCookieLine) +
"; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
// Create a persistent cookie.
EXPECT_TRUE(this->SetCookie(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Check that it is not deleted with significant enough clock skew.
base::Time server_time;
EXPECT_TRUE(base::Time::FromString("Sun, 17-Apr-1977 22:50:13 GMT",
&server_time));
EXPECT_TRUE(this->SetCookieWithServerTime(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
server_time));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Create a persistent cookie.
EXPECT_TRUE(this->SetCookie(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Delete it via Expires, with a unix epoch of 0.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
std::string(kValidCookieLine) +
"; expires=Thu, 1-Jan-1970 00:00:00 GMT"));
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
+}
+
+TYPED_TEST_P(CookieStoreTest, TestDeleteAll) {
+ CookieStore* cs = this->GetCookieStore();
+
+ // Set a session cookie.
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), kValidCookieLine));
+ EXPECT_EQ("A=B", this->GetCookies(cs, this->http_www_google_.url()));
+
+ // Set a persistent cookie.
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
+ "C=D; expires=Mon, 18-Apr-22 22:50:13 GMT"));
+
+ EXPECT_EQ(2u, this->GetAllCookies(cs).size());
+
+ // Delete both, and make sure it works
+ EXPECT_EQ(2, this->DeleteAll(cs));
+ EXPECT_EQ(0u, this->GetAllCookies(cs).size());
}
TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetween) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
const base::Time last_month = base::Time::Now() -
base::TimeDelta::FromDays(30);
const base::Time last_minute = base::Time::Now() -
@@ -860,90 +1013,86 @@ TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetween) {
base::TimeDelta::FromDays(30);
// Add a cookie.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=B"));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "A=B"));
// Check that the cookie is in the store.
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Remove cookies in empty intervals.
- EXPECT_EQ(0, this->DeleteCreatedBetween(cs.get(), last_month, last_minute));
- EXPECT_EQ(0, this->DeleteCreatedBetween(cs.get(), next_minute, next_month));
+ EXPECT_EQ(0, this->DeleteCreatedBetween(cs, last_month, last_minute));
+ EXPECT_EQ(0, this->DeleteCreatedBetween(cs, next_minute, next_month));
// Check that the cookie is still there.
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Remove the cookie with an interval defined by two dates.
- EXPECT_EQ(1, this->DeleteCreatedBetween(cs.get(), last_minute, next_minute));
+ EXPECT_EQ(1, this->DeleteCreatedBetween(cs, last_minute, next_minute));
// Check that the cookie disappeared.
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
// Add another cookie.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "C=D"));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "C=D"));
// Check that the cookie is in the store.
- this->MatchCookieLines(
- "C=D", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("C=D",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Remove the cookie with a null ending time.
- EXPECT_EQ(1, this->DeleteCreatedBetween(cs.get(), last_minute, base::Time()));
+ EXPECT_EQ(1, this->DeleteCreatedBetween(cs, last_minute, base::Time()));
// Check that the cookie disappeared.
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
}
TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetweenForHost) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
GURL url_not_google("http://www.notgoogle.com");
base::Time now = base::Time::Now();
// These 3 cookies match the time range and host.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=B"));
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "C=D"));
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "Y=Z"));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "A=B"));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "C=D"));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "Y=Z"));
// This cookie does not match host.
- EXPECT_TRUE(this->SetCookie(cs.get(), url_not_google, "E=F"));
+ EXPECT_TRUE(this->SetCookie(cs, url_not_google, "E=F"));
// Delete cookies.
- EXPECT_EQ(
- 3, // Deletes A=B, C=D, Y=Z
- this->DeleteAllCreatedBetweenForHost(cs.get(), now, base::Time::Max(),
- this->http_www_google_.url()));
+ EXPECT_EQ(3, // Deletes A=B, C=D, Y=Z
+ this->DeleteAllCreatedBetweenForHost(cs, now, base::Time::Max(),
+ this->http_www_google_.url()));
}
TYPED_TEST_P(CookieStoreTest, TestSecure) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=B"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->https_www_google_.url()));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "A=B"));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->https_www_google_.url()));
- EXPECT_TRUE(this->SetCookie(cs.get(), this->https_www_google_.url(),
- "A=B; secure"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->https_www_google_.url(), "A=B; secure"));
// The secure should overwrite the non-secure.
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), this->http_www_google_.url()));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->https_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->https_www_google_.url()));
- EXPECT_TRUE(this->SetCookie(cs.get(), this->https_www_google_.url(),
- "D=E; secure"));
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), this->http_www_google_.url()));
- this->MatchCookieLines(
- "A=B; D=E", this->GetCookies(cs.get(), this->https_www_google_.url()));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->https_www_google_.url(), "D=E; secure"));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
+ this->MatchCookieLines("A=B; D=E",
+ this->GetCookies(cs, this->https_www_google_.url()));
- EXPECT_TRUE(
- this->SetCookie(cs.get(), this->https_www_google_.url(), "A=B"));
+ EXPECT_TRUE(this->SetCookie(cs, this->https_www_google_.url(), "A=B"));
// The non-secure should overwrite the secure.
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
- this->MatchCookieLines(
- "D=E; A=B", this->GetCookies(cs.get(), this->https_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
+ this->MatchCookieLines("D=E; A=B",
+ this->GetCookies(cs, this->https_www_google_.url()));
}
static const int kLastAccessThresholdMilliseconds = 200;
@@ -952,17 +1101,17 @@ static const int kLastAccessThresholdMilliseconds = 200;
TYPED_TEST_P(CookieStoreTest, NetUtilCookieTest) {
const GURL test_url("http://mojo.jojo.google.izzle/");
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
- EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "foo=bar"));
- std::string value = this->GetCookies(cs.get(), test_url);
+ EXPECT_TRUE(this->SetCookie(cs, test_url, "foo=bar"));
+ std::string value = this->GetCookies(cs, test_url);
this->MatchCookieLines("foo=bar", value);
// test that we can retrieve all cookies:
- EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "x=1"));
- EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "y=2"));
+ EXPECT_TRUE(this->SetCookie(cs, test_url, "x=1"));
+ EXPECT_TRUE(this->SetCookie(cs, test_url, "y=2"));
- std::string result = this->GetCookies(cs.get(), test_url);
+ std::string result = this->GetCookies(cs, test_url);
EXPECT_FALSE(result.empty());
EXPECT_NE(result.find("x=1"), std::string::npos) << result;
EXPECT_NE(result.find("y=2"), std::string::npos) << result;
@@ -971,17 +1120,15 @@ TYPED_TEST_P(CookieStoreTest, NetUtilCookieTest) {
TYPED_TEST_P(CookieStoreTest, OverwritePersistentCookie) {
GURL url_google("http://www.google.com/");
GURL url_chromium("http://chromium.org");
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
// Insert a cookie "a" for path "/path1"
- EXPECT_TRUE(this->SetCookie(cs.get(),
- url_google,
+ EXPECT_TRUE(this->SetCookie(cs, url_google,
"a=val1; path=/path1; "
"expires=Mon, 18-Apr-22 22:50:13 GMT"));
// Insert a cookie "b" for path "/path1"
- EXPECT_TRUE(this->SetCookie(cs.get(),
- url_google,
+ EXPECT_TRUE(this->SetCookie(cs, url_google,
"b=val1; path=/path1; "
"expires=Mon, 18-Apr-22 22:50:14 GMT"));
@@ -989,105 +1136,233 @@ TYPED_TEST_P(CookieStoreTest, OverwritePersistentCookie) {
// overwrite the non-http-only version.
CookieOptions allow_httponly;
allow_httponly.set_include_httponly();
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(),
- url_google,
+ EXPECT_TRUE(this->SetCookieWithOptions(cs, url_google,
"b=val2; path=/path1; httponly; "
"expires=Mon, 18-Apr-22 22:50:14 GMT",
allow_httponly));
// Insert a cookie "a" for path "/path1". This should overwrite.
- EXPECT_TRUE(this->SetCookie(cs.get(),
- url_google,
+ EXPECT_TRUE(this->SetCookie(cs, url_google,
"a=val33; path=/path1; "
"expires=Mon, 18-Apr-22 22:50:14 GMT"));
// Insert a cookie "a" for path "/path2". This should NOT overwrite
// cookie "a", since the path is different.
- EXPECT_TRUE(this->SetCookie(cs.get(),
- url_google,
+ EXPECT_TRUE(this->SetCookie(cs, url_google,
"a=val9; path=/path2; "
"expires=Mon, 18-Apr-22 22:50:14 GMT"));
// Insert a cookie "a" for path "/path1", but this time for "chromium.org".
// Although the name and path match, the hostnames do not, so shouldn't
// overwrite.
- EXPECT_TRUE(this->SetCookie(cs.get(),
- url_chromium,
+ EXPECT_TRUE(this->SetCookie(cs, url_chromium,
"a=val99; path=/path1; "
"expires=Mon, 18-Apr-22 22:50:14 GMT"));
if (TypeParam::supports_http_only) {
this->MatchCookieLines(
- "a=val33",
- this->GetCookies(cs.get(), GURL("http://www.google.com/path1")));
+ "a=val33", this->GetCookies(cs, GURL("http://www.google.com/path1")));
} else {
this->MatchCookieLines(
"a=val33; b=val2",
- this->GetCookies(cs.get(), GURL("http://www.google.com/path1")));
+ this->GetCookies(cs, GURL("http://www.google.com/path1")));
}
this->MatchCookieLines(
- "a=val9",
- this->GetCookies(cs.get(), GURL("http://www.google.com/path2")));
+ "a=val9", this->GetCookies(cs, GURL("http://www.google.com/path2")));
this->MatchCookieLines(
- "a=val99", this->GetCookies(cs.get(), GURL("http://chromium.org/path1")));
+ "a=val99", this->GetCookies(cs, GURL("http://chromium.org/path1")));
}
TYPED_TEST_P(CookieStoreTest, CookieOrdering) {
// Put a random set of cookies into a store and make sure they're returned in
// the right order.
// Cookies should be sorted by path length and creation time, as per RFC6265.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_TRUE(this->SetCookie(
- cs.get(), GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
- EXPECT_TRUE(this->SetCookie(cs.get(),
- GURL("http://b.a.google.com/aa/bb/cc/x.html"),
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_TRUE(
+ this->SetCookie(cs, GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
+ EXPECT_TRUE(this->SetCookie(cs, GURL("http://b.a.google.com/aa/bb/cc/x.html"),
"d=1; domain=b.a.google.com"));
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
TypeParam::creation_time_granularity_in_ms));
- EXPECT_TRUE(this->SetCookie(cs.get(),
- GURL("http://b.a.google.com/aa/bb/cc/x.html"),
+ EXPECT_TRUE(this->SetCookie(cs, GURL("http://b.a.google.com/aa/bb/cc/x.html"),
"a=4; domain=b.a.google.com"));
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
TypeParam::creation_time_granularity_in_ms));
- EXPECT_TRUE(this->SetCookie(cs.get(),
+ EXPECT_TRUE(this->SetCookie(cs,
GURL("http://c.b.a.google.com/aa/bb/cc/x.html"),
"e=1; domain=c.b.a.google.com"));
EXPECT_TRUE(this->SetCookie(
- cs.get(), GURL("http://d.c.b.a.google.com/aa/bb/x.html"), "b=1"));
- EXPECT_TRUE(this->SetCookie(
- cs.get(), GURL("http://news.bbc.co.uk/midpath/x.html"), "g=10"));
- EXPECT_EQ("d=1; a=4; e=1; b=1; c=1",
- this->GetCookies(cs.get(),
- GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
+ cs, GURL("http://d.c.b.a.google.com/aa/bb/x.html"), "b=1"));
+ EXPECT_TRUE(this->SetCookie(cs, GURL("http://news.bbc.co.uk/midpath/x.html"),
+ "g=10"));
+ EXPECT_EQ(
+ "d=1; a=4; e=1; b=1; c=1",
+ this->GetCookies(cs, GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
+
+ CookieOptions options;
+ CookieList cookies = this->GetCookieListWithOptions(
+ cs, GURL("http://d.c.b.a.google.com/aa/bb/cc/dd"), options);
+ CookieList::const_iterator it = cookies.begin();
+
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ("d", it->Name());
+
+ ASSERT_TRUE(++it != cookies.end());
+ EXPECT_EQ("a", it->Name());
+
+ ASSERT_TRUE(++it != cookies.end());
+ EXPECT_EQ("e", it->Name());
+
+ ASSERT_TRUE(++it != cookies.end());
+ EXPECT_EQ("b", it->Name());
+
+ ASSERT_TRUE(++it != cookies.end());
+ EXPECT_EQ("c", it->Name());
+
+ EXPECT_TRUE(++it == cookies.end());
+}
+
+// Check that GetAllCookiesAsync returns cookies from multiple domains, in the
+// correct order.
+TYPED_TEST_P(CookieStoreTest, GetAllCookiesAsync) {
+ CookieStore* cs = this->GetCookieStore();
+
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=B; path=/a"));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_foo_com_.url(), "C=D;/"));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "E=F; path=/bar"));
+
+ // Check cookies for url.
+ CookieList cookies = this->GetAllCookies(cs);
+ CookieList::const_iterator it = cookies.begin();
+
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ(this->http_bar_com_.host(), it->Domain());
+ EXPECT_EQ("/bar", it->Path());
+ EXPECT_EQ("E", it->Name());
+ EXPECT_EQ("F", it->Value());
+
+ ASSERT_TRUE(++it != cookies.end());
+ EXPECT_EQ(this->http_www_google_.host(), it->Domain());
+ EXPECT_EQ("/a", it->Path());
+ EXPECT_EQ("A", it->Name());
+ EXPECT_EQ("B", it->Value());
+
+ ASSERT_TRUE(++it != cookies.end());
+ EXPECT_EQ(this->http_foo_com_.host(), it->Domain());
+ EXPECT_EQ("/", it->Path());
+ EXPECT_EQ("C", it->Name());
+ EXPECT_EQ("D", it->Value());
+
+ ASSERT_TRUE(++it == cookies.end());
+}
+
+TYPED_TEST_P(CookieStoreTest, DeleteCookieAsync) {
+ CookieStore* cs = this->GetCookieStore();
+
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=A1; path=/"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=A2; path=/foo"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=A3; path=/bar"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "B=B1; path=/"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "B=B2; path=/foo"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "B=B3; path=/bar"));
+
+ this->DeleteCookie(cs, this->http_www_google_.AppendPath("foo/bar"), "A");
+
+ CookieList cookies = this->GetAllCookies(cs);
+ size_t expected_size = 4;
+ EXPECT_EQ(expected_size, cookies.size());
+ for (const auto& cookie : cookies) {
+ EXPECT_NE("A1", cookie.Value());
+ EXPECT_NE("A2", cookie.Value());
+ }
+}
+
+TYPED_TEST_P(CookieStoreTest, DeleteCanonicalCookieAsync) {
+ CookieStore* cs = this->GetCookieStore();
+
+ // Set two cookies with the same name, and make sure both are set.
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=B;Path=/foo"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=C;Path=/bar"));
+ EXPECT_EQ(2u, this->GetAllCookies(cs).size());
+ EXPECT_EQ("A=B", this->GetCookies(cs, this->www_google_foo_.url()));
+ EXPECT_EQ("A=C", this->GetCookies(cs, this->www_google_bar_.url()));
+
+ // Delete the "/foo" cookie, and make sure only it was deleted.
+ CookieList cookies = this->GetCookieListWithOptions(
+ cs, this->www_google_foo_.url(), CookieOptions());
+ ASSERT_EQ(1u, cookies.size());
+ EXPECT_EQ(1, this->DeleteCanonicalCookie(cs, cookies[0]));
+ EXPECT_EQ(1u, this->GetAllCookies(cs).size());
+ EXPECT_EQ("", this->GetCookies(cs, this->www_google_foo_.url()));
+ EXPECT_EQ("A=C", this->GetCookies(cs, this->www_google_bar_.url()));
+
+ // Deleting the "/foo" cookie again should fail.
+ EXPECT_EQ(0, this->DeleteCanonicalCookie(cs, cookies[0]));
+
+ // Try to delete the "/bar" cookie after overwriting it with a new cookie.
+ cookies = this->GetCookieListWithOptions(cs, this->www_google_bar_.url(),
+ CookieOptions());
+ ASSERT_EQ(1u, cookies.size());
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=D;Path=/bar"));
+ EXPECT_EQ(0, this->DeleteCanonicalCookie(cs, cookies[0]));
+ EXPECT_EQ(1u, this->GetAllCookies(cs).size());
+ EXPECT_EQ("A=D", this->GetCookies(cs, this->www_google_bar_.url()));
+
+ // Delete the new "/bar" cookie.
+ cookies = this->GetCookieListWithOptions(cs, this->www_google_bar_.url(),
+ CookieOptions());
+ ASSERT_EQ(1u, cookies.size());
+ EXPECT_EQ(1, this->DeleteCanonicalCookie(cs, cookies[0]));
+ EXPECT_EQ(0u, this->GetAllCookies(cs).size());
+ EXPECT_EQ("", this->GetCookies(cs, this->www_google_bar_.url()));
}
TYPED_TEST_P(CookieStoreTest, DeleteSessionCookie) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
// Create a session cookie and a persistent cookie.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
std::string(kValidCookieLine)));
EXPECT_TRUE(this->SetCookie(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
this->http_www_google_.Format("C=D; path=/; domain=%D;"
"expires=Mon, 18-Apr-22 22:50:13 GMT")));
- this->MatchCookieLines(
- "A=B; C=D", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B; C=D",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Delete the session cookie.
- this->DeleteSessionCookies(cs.get());
+ this->DeleteSessionCookies(cs);
// Check that the session cookie has been deleted but not the persistent one.
- EXPECT_EQ("C=D", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ EXPECT_EQ("C=D", this->GetCookies(cs, this->http_www_google_.url()));
}
REGISTER_TYPED_TEST_CASE_P(CookieStoreTest,
- TypeTest,
+ SetCookieWithDetailsAsync,
DomainTest,
DomainWithTrailingDotTest,
ValidSubdomainTest,
InvalidDomainTest,
- DomainWithoutLeadingDotTest,
+ InvalidDomainSameDomainAndRegistry,
+ DomainWithoutLeadingDotParentDomain,
+ DomainWithoutLeadingDotSameDomain,
CaseInsensitiveDomainTest,
TestIpAddress,
- TestNonDottedAndTLD,
+ TestIpAddressNoDomainCookies,
+ TestTLD,
+ TestTLDWithTerminalDot,
+ TestSubdomainSettingCookiesOnUnknownTLD,
+ TestSubdomainSettingCookiesOnKnownTLD,
+ TestSubdomainSettingCookiesOnKnownDottedTLD,
+ TestSettingCookiesOnUnknownTLD,
+ TestSettingCookiesWithHostDomainOnUnknownTLD,
TestHostEndsWithDot,
InvalidScheme,
InvalidScheme_Read,
@@ -1095,188 +1370,18 @@ REGISTER_TYPED_TEST_CASE_P(CookieStoreTest,
EmptyExpires,
HttpOnlyTest,
TestCookieDeletion,
+ TestDeleteAll,
TestDeleteAllCreatedBetween,
TestDeleteAllCreatedBetweenForHost,
TestSecure,
NetUtilCookieTest,
OverwritePersistentCookie,
CookieOrdering,
+ GetAllCookiesAsync,
+ DeleteCookieAsync,
+ DeleteCanonicalCookieAsync,
DeleteSessionCookie);
-template<class CookieStoreTestTraits>
-class MultiThreadedCookieStoreTest :
- public CookieStoreTest<CookieStoreTestTraits> {
- public:
- MultiThreadedCookieStoreTest() : other_thread_("CMTthread") {}
-
- // Helper methods for calling the asynchronous CookieStore methods
- // from a different thread.
-
- void GetCookiesTask(CookieStore* cs,
- const GURL& url,
- StringResultCookieCallback* callback) {
- CookieOptions options;
- if (!CookieStoreTestTraits::supports_http_only)
- options.set_include_httponly();
- cs->GetCookiesWithOptionsAsync(
- url, options,
- base::Bind(&StringResultCookieCallback::Run,
- base::Unretained(callback)));
- }
-
- void GetCookiesWithOptionsTask(CookieStore* cs,
- const GURL& url,
- const CookieOptions& options,
- StringResultCookieCallback* callback) {
- cs->GetCookiesWithOptionsAsync(
- url, options,
- base::Bind(&StringResultCookieCallback::Run,
- base::Unretained(callback)));
- }
-
- void SetCookieWithOptionsTask(CookieStore* cs,
- const GURL& url,
- const std::string& cookie_line,
- const CookieOptions& options,
- ResultSavingCookieCallback<bool>* callback) {
- cs->SetCookieWithOptionsAsync(
- url, cookie_line, options,
- base::Bind(
- &ResultSavingCookieCallback<bool>::Run,
- base::Unretained(callback)));
- }
-
- void DeleteCookieTask(CookieStore* cs,
- const GURL& url,
- const std::string& cookie_name,
- NoResultCookieCallback* callback) {
- cs->DeleteCookieAsync(
- url, cookie_name,
- base::Bind(&NoResultCookieCallback::Run, base::Unretained(callback)));
- }
-
- void DeleteSessionCookiesTask(CookieStore* cs,
- ResultSavingCookieCallback<int>* callback) {
- cs->DeleteSessionCookiesAsync(
- base::Bind(
- &ResultSavingCookieCallback<int>::Run,
- base::Unretained(callback)));
- }
-
- protected:
- void RunOnOtherThread(const base::Closure& task) {
- other_thread_.Start();
- other_thread_.task_runner()->PostTask(FROM_HERE, task);
- CookieStoreTest<CookieStoreTestTraits>::RunFor(kTimeout);
- other_thread_.Stop();
- }
-
- Thread other_thread_;
-};
-
-TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest);
-
-// TODO(ycxiao): Eventually, we will need to create a separate thread, create
-// the cookie store on that thread (or at least its store, i.e., the DB
-// thread).
-TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookies) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=B"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
- StringResultCookieCallback callback(&this->other_thread_);
- base::Closure task = base::Bind(
- &MultiThreadedCookieStoreTest<TypeParam>::GetCookiesTask,
- base::Unretained(this), cs, this->http_www_google_.url(), &callback);
- this->RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_EQ("A=B", callback.result());
-}
-
-TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookiesWithOptions) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- CookieOptions options;
- if (!TypeParam::supports_http_only)
- options.set_include_httponly();
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=B"));
- this->MatchCookieLines(
- "A=B", this->GetCookiesWithOptions(cs.get(), this->http_www_google_.url(),
- options));
- StringResultCookieCallback callback(&this->other_thread_);
- base::Closure task = base::Bind(
- &MultiThreadedCookieStoreTest<TypeParam>::GetCookiesWithOptionsTask,
- base::Unretained(this), cs, this->http_www_google_.url(), options,
- &callback);
- this->RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_EQ("A=B", callback.result());
-}
-
-TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckSetCookieWithOptions) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- CookieOptions options;
- if (!TypeParam::supports_http_only)
- options.set_include_httponly();
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
- "A=B", options));
- ResultSavingCookieCallback<bool> callback(&this->other_thread_);
- base::Closure task = base::Bind(
- &MultiThreadedCookieStoreTest<TypeParam>::SetCookieWithOptionsTask,
- base::Unretained(this), cs, this->http_www_google_.url(), "A=B", options,
- &callback);
- this->RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_TRUE(callback.result());
-}
-
-TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckDeleteCookie) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- CookieOptions options;
- if (!TypeParam::supports_http_only)
- options.set_include_httponly();
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
- "A=B", options));
- this->DeleteCookie(cs.get(), this->http_www_google_.url(), "A");
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
- "A=B", options));
- NoResultCookieCallback callback(&this->other_thread_);
- base::Closure task = base::Bind(
- &MultiThreadedCookieStoreTest<TypeParam>::DeleteCookieTask,
- base::Unretained(this), cs, this->http_www_google_.url(), "A", &callback);
- this->RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
-}
-
-TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckDeleteSessionCookies) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- CookieOptions options;
- if (!TypeParam::supports_http_only)
- options.set_include_httponly();
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
- "A=B", options));
- EXPECT_TRUE(this->SetCookieWithOptions(
- cs.get(), this->http_www_google_.url(),
- "B=C; expires=Mon, 18-Apr-22 22:50:13 GMT", options));
- EXPECT_EQ(1, this->DeleteSessionCookies(cs.get()));
- EXPECT_EQ(0, this->DeleteSessionCookies(cs.get()));
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
- "A=B", options));
- ResultSavingCookieCallback<int> callback(&this->other_thread_);
- base::Closure task = base::Bind(
- &MultiThreadedCookieStoreTest<TypeParam>::DeleteSessionCookiesTask,
- base::Unretained(this), cs, &callback);
- this->RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_EQ(1, callback.result());
-}
-
-REGISTER_TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest,
- ThreadCheckGetCookies,
- ThreadCheckGetCookiesWithOptions,
- ThreadCheckSetCookieWithOptions,
- ThreadCheckDeleteCookie,
- ThreadCheckDeleteSessionCookies);
-
} // namespace net
#endif // NET_COOKIES_COOKIE_STORE_UNITTEST_H_
diff --git a/chromium/net/cookies/cookie_util.cc b/chromium/net/cookies/cookie_util.cc
index 4071e6fd380..210b8d479af 100644
--- a/chromium/net/cookies/cookie_util.cc
+++ b/chromium/net/cookies/cookie_util.cc
@@ -11,8 +11,8 @@
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
-#include "net/base/net_util.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/base/url_util.h"
#include "url/gurl.h"
namespace net {
diff --git a/chromium/net/cookies/parse_cookie_line_fuzzer.cc b/chromium/net/cookies/parse_cookie_line_fuzzer.cc
new file mode 100644
index 00000000000..997839841ba
--- /dev/null
+++ b/chromium/net/cookies/parse_cookie_line_fuzzer.cc
@@ -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.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "net/cookies/parsed_cookie.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::string input(data, data + size);
+ net::ParsedCookie parsed_cookie(input);
+ return 0;
+}
diff --git a/chromium/net/cookies/parsed_cookie.cc b/chromium/net/cookies/parsed_cookie.cc
index bd8b0dc2270..2175692f534 100644
--- a/chromium/net/cookies/parsed_cookie.cc
+++ b/chromium/net/cookies/parsed_cookie.cc
@@ -55,7 +55,7 @@ const char kExpiresTokenName[] = "expires";
const char kMaxAgeTokenName[] = "max-age";
const char kSecureTokenName[] = "secure";
const char kHttpOnlyTokenName[] = "httponly";
-const char kFirstPartyOnlyTokenName[] = "first-party-only";
+const char kSameSiteTokenName[] = "samesite";
const char kPriorityTokenName[] = "priority";
const char kTerminator[] = "\n\r\0";
@@ -163,7 +163,7 @@ ParsedCookie::ParsedCookie(const std::string& cookie_line)
maxage_index_(0),
secure_index_(0),
httponly_index_(0),
- firstpartyonly_index_(0),
+ same_site_index_(0),
priority_index_(0) {
if (cookie_line.size() > kMaxCookieSize) {
VLOG(1) << "Not parsing cookie, too large: " << cookie_line.size();
@@ -179,7 +179,13 @@ ParsedCookie::~ParsedCookie() {
}
bool ParsedCookie::IsValid() const {
- return !pairs_.empty();
+ return !pairs_.empty() && IsSameSiteAttributeValid();
+}
+
+CookieSameSite ParsedCookie::SameSite() const {
+ return (same_site_index_ == 0)
+ ? CookieSameSite::DEFAULT_MODE
+ : StringToCookieSameSite(pairs_[same_site_index_].second);
}
CookiePriority ParsedCookie::Priority() const {
@@ -230,9 +236,8 @@ bool ParsedCookie::SetIsHttpOnly(bool is_http_only) {
return SetBool(&httponly_index_, kHttpOnlyTokenName, is_http_only);
}
-bool ParsedCookie::SetIsFirstPartyOnly(bool is_first_party_only) {
- return SetBool(&firstpartyonly_index_, kFirstPartyOnlyTokenName,
- is_first_party_only);
+bool ParsedCookie::SetSameSite(const std::string& is_same_site) {
+ return SetString(&same_site_index_, kSameSiteTokenName, is_same_site);
}
bool ParsedCookie::SetPriority(const std::string& priority) {
@@ -245,8 +250,7 @@ std::string ParsedCookie::ToCookieLine() const {
if (!out.empty())
out.append("; ");
out.append(it->first);
- if (it->first != kSecureTokenName && it->first != kHttpOnlyTokenName &&
- it->first != kFirstPartyOnlyTokenName) {
+ if (it->first != kSecureTokenName && it->first != kHttpOnlyTokenName) {
out.append("=");
out.append(it->second);
}
@@ -437,8 +441,8 @@ void ParsedCookie::SetupAttributes() {
secure_index_ = i;
} else if (pairs_[i].first == kHttpOnlyTokenName) {
httponly_index_ = i;
- } else if (pairs_[i].first == kFirstPartyOnlyTokenName) {
- firstpartyonly_index_ = i;
+ } else if (pairs_[i].first == kSameSiteTokenName) {
+ same_site_index_ = i;
} else if (pairs_[i].first == kPriorityTokenName) {
priority_index_ = i;
} else {
@@ -490,14 +494,9 @@ void ParsedCookie::ClearAttributePair(size_t index) {
if (index == 0)
return;
- size_t* indexes[] = {&path_index_,
- &domain_index_,
- &expires_index_,
- &maxage_index_,
- &secure_index_,
- &httponly_index_,
- &firstpartyonly_index_,
- &priority_index_};
+ size_t* indexes[] = {&path_index_, &domain_index_, &expires_index_,
+ &maxage_index_, &secure_index_, &httponly_index_,
+ &same_site_index_, &priority_index_};
for (size_t i = 0; i < arraysize(indexes); ++i) {
if (*indexes[i] == index)
*indexes[i] = 0;
@@ -507,4 +506,8 @@ void ParsedCookie::ClearAttributePair(size_t index) {
pairs_.erase(pairs_.begin() + index);
}
+bool ParsedCookie::IsSameSiteAttributeValid() const {
+ return same_site_index_ == 0 || SameSite() != CookieSameSite::DEFAULT_MODE;
+}
+
} // namespace
diff --git a/chromium/net/cookies/parsed_cookie.h b/chromium/net/cookies/parsed_cookie.h
index 8317609be5f..f48015dbd2f 100644
--- a/chromium/net/cookies/parsed_cookie.h
+++ b/chromium/net/cookies/parsed_cookie.h
@@ -50,7 +50,7 @@ class NET_EXPORT ParsedCookie {
const std::string& MaxAge() const { return pairs_[maxage_index_].second; }
bool IsSecure() const { return secure_index_ != 0; }
bool IsHttpOnly() const { return httponly_index_ != 0; }
- bool IsFirstPartyOnly() const { return firstpartyonly_index_ != 0; }
+ CookieSameSite SameSite() const;
CookiePriority Priority() const;
// Returns the number of attributes, for example, returning 2 for:
@@ -70,7 +70,7 @@ class NET_EXPORT ParsedCookie {
bool SetMaxAge(const std::string& maxage);
bool SetIsSecure(bool is_secure);
bool SetIsHttpOnly(bool is_http_only);
- bool SetIsFirstPartyOnly(bool is_first_party_only);
+ bool SetSameSite(const std::string& same_site);
bool SetPriority(const std::string& priority);
// Returns the cookie description as it appears in a HTML response header.
@@ -129,6 +129,10 @@ class NET_EXPORT ParsedCookie {
// |index| refers to a position in |pairs_|.
void ClearAttributePair(size_t index);
+ // Returns false if a 'SameSite' attribute is present, but has an unrecognized
+ // value. In particular, this includes attributes with empty values.
+ bool IsSameSiteAttributeValid() const;
+
PairList pairs_;
// These will default to 0, but that should never be valid since the
// 0th index is the user supplied token/value, not an attribute.
@@ -140,7 +144,7 @@ class NET_EXPORT ParsedCookie {
size_t maxage_index_;
size_t secure_index_;
size_t httponly_index_;
- size_t firstpartyonly_index_;
+ size_t same_site_index_;
size_t priority_index_;
DISALLOW_COPY_AND_ASSIGN(ParsedCookie);
diff --git a/chromium/net/cookies/parsed_cookie_unittest.cc b/chromium/net/cookies/parsed_cookie_unittest.cc
index 61a61677799..27efb99adfc 100644
--- a/chromium/net/cookies/parsed_cookie_unittest.cc
+++ b/chromium/net/cookies/parsed_cookie_unittest.cc
@@ -93,11 +93,11 @@ TEST(ParsedCookieTest, TestNameless) {
TEST(ParsedCookieTest, TestAttributeCase) {
ParsedCookie pc(
- "BLAHHH; Path=/; sECuRe; httpONLY; first-PaRty-only; pRIoRitY=hIgH");
+ "BLAHHH; Path=/; sECuRe; httpONLY; sAmESitE=StrIct; pRIoRitY=hIgH");
EXPECT_TRUE(pc.IsValid());
EXPECT_TRUE(pc.IsSecure());
EXPECT_TRUE(pc.IsHttpOnly());
- EXPECT_TRUE(pc.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::STRICT_MODE, pc.SameSite());
EXPECT_TRUE(pc.HasPath());
EXPECT_EQ("/", pc.Path());
EXPECT_EQ("", pc.Name());
@@ -148,7 +148,7 @@ TEST(ParsedCookieTest, MissingValue) {
}
TEST(ParsedCookieTest, Whitespace) {
- ParsedCookie pc(" A = BC ;secure;;; first-party-only ");
+ ParsedCookie pc(" A = BC ;secure;;; samesite = lax ");
EXPECT_TRUE(pc.IsValid());
EXPECT_EQ("A", pc.Name());
EXPECT_EQ("BC", pc.Value());
@@ -156,7 +156,7 @@ TEST(ParsedCookieTest, Whitespace) {
EXPECT_FALSE(pc.HasDomain());
EXPECT_TRUE(pc.IsSecure());
EXPECT_FALSE(pc.IsHttpOnly());
- EXPECT_TRUE(pc.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::LAX_MODE, pc.SameSite());
EXPECT_EQ(COOKIE_PRIORITY_DEFAULT, pc.Priority());
// We parse anything between ; as attributes, so we end up with two
// attributes with an empty string name and value.
@@ -171,7 +171,7 @@ TEST(ParsedCookieTest, MultipleEquals) {
EXPECT_FALSE(pc.HasDomain());
EXPECT_TRUE(pc.IsSecure());
EXPECT_TRUE(pc.IsHttpOnly());
- EXPECT_FALSE(pc.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::DEFAULT_MODE, pc.SameSite());
EXPECT_EQ(COOKIE_PRIORITY_DEFAULT, pc.Priority());
EXPECT_EQ(4U, pc.NumberOfAttributes());
}
@@ -357,12 +357,12 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_TRUE(pc.SetIsSecure(true));
EXPECT_TRUE(pc.SetIsHttpOnly(true));
EXPECT_TRUE(pc.SetIsHttpOnly(true));
- EXPECT_TRUE(pc.SetIsFirstPartyOnly(true));
+ EXPECT_TRUE(pc.SetSameSite("LAX"));
EXPECT_TRUE(pc.SetPriority("HIGH"));
EXPECT_EQ(
"name=value; domain=domain.com; path=/; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; max-age=12345; secure; "
- "httponly; first-party-only; priority=HIGH",
+ "httponly; samesite=LAX; priority=HIGH",
pc.ToCookieLine());
EXPECT_TRUE(pc.HasDomain());
EXPECT_TRUE(pc.HasPath());
@@ -370,7 +370,7 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_TRUE(pc.HasMaxAge());
EXPECT_TRUE(pc.IsSecure());
EXPECT_TRUE(pc.IsHttpOnly());
- EXPECT_TRUE(pc.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::LAX_MODE, pc.SameSite());
EXPECT_EQ(COOKIE_PRIORITY_HIGH, pc.Priority());
// Clear one attribute from the middle.
@@ -383,7 +383,7 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_EQ(
"name=value; domain=domain.com; path=/foo; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; max-age=12345; secure; "
- "httponly; first-party-only; priority=HIGH",
+ "httponly; samesite=LAX; priority=HIGH",
pc.ToCookieLine());
// Set priority to medium.
@@ -391,7 +391,7 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_EQ(
"name=value; domain=domain.com; path=/foo; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; max-age=12345; secure; "
- "httponly; first-party-only; priority=medium",
+ "httponly; samesite=LAX; priority=medium",
pc.ToCookieLine());
// Clear the rest and change the name and value.
@@ -401,7 +401,7 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_TRUE(pc.SetMaxAge(std::string()));
EXPECT_TRUE(pc.SetIsSecure(false));
EXPECT_TRUE(pc.SetIsHttpOnly(false));
- EXPECT_TRUE(pc.SetIsFirstPartyOnly(false));
+ EXPECT_TRUE(pc.SetSameSite(std::string()));
EXPECT_TRUE(pc.SetName("name2"));
EXPECT_TRUE(pc.SetValue("value2"));
EXPECT_TRUE(pc.SetPriority(std::string()));
@@ -411,7 +411,7 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_FALSE(pc.HasMaxAge());
EXPECT_FALSE(pc.IsSecure());
EXPECT_FALSE(pc.IsHttpOnly());
- EXPECT_FALSE(pc.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::NO_RESTRICTION, pc.SameSite());
EXPECT_EQ("name2=value2", pc.ToCookieLine());
}
@@ -449,6 +449,56 @@ TEST(ParsedCookieTest, SetPriority) {
EXPECT_EQ(COOKIE_PRIORITY_DEFAULT, pc.Priority());
}
+TEST(ParsedCookieTest, SetSameSite) {
+ ParsedCookie pc("name=value");
+ EXPECT_TRUE(pc.IsValid());
+
+ EXPECT_EQ("name=value", pc.ToCookieLine());
+ EXPECT_EQ(CookieSameSite::DEFAULT_MODE, pc.SameSite());
+
+ // Test each priority, expect case-insensitive compare.
+ EXPECT_TRUE(pc.SetSameSite("strict"));
+ EXPECT_EQ("name=value; samesite=strict", pc.ToCookieLine());
+ EXPECT_EQ(CookieSameSite::STRICT_MODE, pc.SameSite());
+ EXPECT_TRUE(pc.IsValid());
+
+ EXPECT_TRUE(pc.SetSameSite("lAx"));
+ EXPECT_EQ("name=value; samesite=lAx", pc.ToCookieLine());
+ EXPECT_EQ(CookieSameSite::LAX_MODE, pc.SameSite());
+ EXPECT_TRUE(pc.IsValid());
+
+ EXPECT_TRUE(pc.SetSameSite("LAX"));
+ EXPECT_EQ("name=value; samesite=LAX", pc.ToCookieLine());
+ EXPECT_EQ(CookieSameSite::LAX_MODE, pc.SameSite());
+ EXPECT_TRUE(pc.IsValid());
+
+ EXPECT_TRUE(pc.SetSameSite(""));
+ EXPECT_EQ("name=value", pc.ToCookieLine());
+ EXPECT_EQ(CookieSameSite::DEFAULT_MODE, pc.SameSite());
+ EXPECT_TRUE(pc.IsValid());
+
+ EXPECT_TRUE(pc.SetSameSite("Blah"));
+ EXPECT_FALSE(pc.IsValid());
+}
+
+TEST(ParsedCookieTest, InvalidSameSiteValue) {
+ struct TestCase {
+ const char* cookie;
+ bool valid;
+ CookieSameSite mode;
+ } cases[]{{"n=v; samesite=strict", true, CookieSameSite::STRICT_MODE},
+ {"n=v; samesite=lax", true, CookieSameSite::LAX_MODE},
+ {"n=v; samesite=boo", false, CookieSameSite::DEFAULT_MODE},
+ {"n=v; samesite", false, CookieSameSite::DEFAULT_MODE}};
+
+ for (const auto& test : cases) {
+ SCOPED_TRACE(test.cookie);
+ ParsedCookie pc(test.cookie);
+ EXPECT_EQ(test.valid, pc.IsValid());
+ EXPECT_EQ(test.mode, pc.SameSite());
+ }
+}
+
TEST(ParsedCookieTest, InvalidNonAlphanumericChars) {
ParsedCookie pc1("name=\x05");
ParsedCookie pc2(
diff --git a/chromium/net/data/name_constraints_unittest/directoryname-excludeall.pem b/chromium/net/data/name_constraints_unittest/directoryname-excludeall.pem
index 4f8bdb2e9d4..2e91b30efdb 100644
--- a/chromium/net/data/name_constraints_unittest/directoryname-excludeall.pem
+++ b/chromium/net/data/name_constraints_unittest/directoryname-excludeall.pem
@@ -1,14 +1,16 @@
- 0:d=0 hl=2 l= 25 cons: SEQUENCE
- 2:d=1 hl=2 l= 17 cons: cont [ 0 ]
- 4:d=2 hl=2 l= 15 cons: SEQUENCE
- 6:d=3 hl=2 l= 13 cons: cont [ 4 ]
- 8:d=4 hl=2 l= 11 cons: SET
- 10:d=5 hl=2 l= 9 cons: SEQUENCE
- 12:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 17:d=6 hl=2 l= 2 prim: PRINTABLESTRING :US
- 21:d=1 hl=2 l= 4 cons: cont [ 1 ]
- 23:d=2 hl=2 l= 2 cons: SEQUENCE
- 25:d=3 hl=2 l= 0 cons: cont [ 4 ]
+ 0:d=0 hl=2 l= 29 cons: SEQUENCE
+ 2:d=1 hl=2 l= 19 cons: cont [ 0 ]
+ 4:d=2 hl=2 l= 17 cons: SEQUENCE
+ 6:d=3 hl=2 l= 15 cons: cont [ 4 ]
+ 8:d=4 hl=2 l= 13 cons: SEQUENCE
+ 10:d=5 hl=2 l= 11 cons: SET
+ 12:d=6 hl=2 l= 9 cons: SEQUENCE
+ 14:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 19:d=7 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 23:d=1 hl=2 l= 6 cons: cont [ 1 ]
+ 25:d=2 hl=2 l= 4 cons: SEQUENCE
+ 27:d=3 hl=2 l= 2 cons: cont [ 4 ]
+ 29:d=4 hl=2 l= 0 cons: SEQUENCE
-----BEGIN NAME CONSTRAINTS-----
-MBmgETAPpA0xCzAJBgNVBAYTAlVToQQwAqQA
+MB2gEzARpA8wDTELMAkGA1UEBhMCVVOhBjAEpAIwAA==
-----END NAME CONSTRAINTS-----
diff --git a/chromium/net/data/name_constraints_unittest/directoryname-excluded.pem b/chromium/net/data/name_constraints_unittest/directoryname-excluded.pem
index b55c8687bc3..fe525a3cb48 100644
--- a/chromium/net/data/name_constraints_unittest/directoryname-excluded.pem
+++ b/chromium/net/data/name_constraints_unittest/directoryname-excluded.pem
@@ -1,15 +1,16 @@
- 0:d=0 hl=2 l= 40 cons: SEQUENCE
- 2:d=1 hl=2 l= 38 cons: cont [ 1 ]
- 4:d=2 hl=2 l= 36 cons: SEQUENCE
- 6:d=3 hl=2 l= 34 cons: cont [ 4 ]
- 8:d=4 hl=2 l= 11 cons: SET
- 10:d=5 hl=2 l= 9 cons: SEQUENCE
- 12:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 17:d=6 hl=2 l= 2 prim: PRINTABLESTRING :US
- 21:d=4 hl=2 l= 19 cons: SET
- 23:d=5 hl=2 l= 17 cons: SEQUENCE
- 25:d=6 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
- 30:d=6 hl=2 l= 10 prim: UTF8STRING :California
+ 0:d=0 hl=2 l= 42 cons: SEQUENCE
+ 2:d=1 hl=2 l= 40 cons: cont [ 1 ]
+ 4:d=2 hl=2 l= 38 cons: SEQUENCE
+ 6:d=3 hl=2 l= 36 cons: cont [ 4 ]
+ 8:d=4 hl=2 l= 34 cons: SEQUENCE
+ 10:d=5 hl=2 l= 11 cons: SET
+ 12:d=6 hl=2 l= 9 cons: SEQUENCE
+ 14:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 19:d=7 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 23:d=5 hl=2 l= 19 cons: SET
+ 25:d=6 hl=2 l= 17 cons: SEQUENCE
+ 27:d=7 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 32:d=7 hl=2 l= 10 prim: UTF8STRING :California
-----BEGIN NAME CONSTRAINTS-----
-MCihJjAkpCIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
+MCqhKDAmpCQwIjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWE=
-----END NAME CONSTRAINTS-----
diff --git a/chromium/net/data/name_constraints_unittest/directoryname.pem b/chromium/net/data/name_constraints_unittest/directoryname.pem
index d79e691bc9a..01f11219d8f 100644
--- a/chromium/net/data/name_constraints_unittest/directoryname.pem
+++ b/chromium/net/data/name_constraints_unittest/directoryname.pem
@@ -1,55 +1,60 @@
- 0:d=0 hl=3 l= 172 cons: SEQUENCE
- 3:d=1 hl=2 l= 113 cons: cont [ 0 ]
- 5:d=2 hl=2 l= 15 cons: SEQUENCE
- 7:d=3 hl=2 l= 13 cons: cont [ 4 ]
- 9:d=4 hl=2 l= 11 cons: SET
- 11:d=5 hl=2 l= 9 cons: SEQUENCE
- 13:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 18:d=6 hl=2 l= 2 prim: PRINTABLESTRING :US
- 22:d=2 hl=2 l= 60 cons: SEQUENCE
- 24:d=3 hl=2 l= 58 cons: cont [ 4 ]
- 26:d=4 hl=2 l= 11 cons: SET
- 28:d=5 hl=2 l= 9 cons: SEQUENCE
- 30:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 35:d=6 hl=2 l= 2 prim: PRINTABLESTRING :US
- 39:d=4 hl=2 l= 19 cons: SET
- 41:d=5 hl=2 l= 17 cons: SEQUENCE
- 43:d=6 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
- 48:d=6 hl=2 l= 10 prim: UTF8STRING :California
- 60:d=4 hl=2 l= 22 cons: SET
- 62:d=5 hl=2 l= 20 cons: SEQUENCE
- 64:d=6 hl=2 l= 3 prim: OBJECT :localityName
- 69:d=6 hl=2 l= 13 prim: UTF8STRING :Mountain View
- 84:d=2 hl=2 l= 32 cons: SEQUENCE
- 86:d=3 hl=2 l= 30 cons: cont [ 4 ]
- 88:d=4 hl=2 l= 11 cons: SET
- 90:d=5 hl=2 l= 9 cons: SEQUENCE
- 92:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 97:d=6 hl=2 l= 2 prim: PRINTABLESTRING :JP
- 101:d=4 hl=2 l= 15 cons: SET
- 103:d=5 hl=2 l= 13 cons: SEQUENCE
- 105:d=6 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
- 110:d=6 hl=2 l= 6 prim: UTF8STRING :東京
- 118:d=1 hl=2 l= 55 cons: cont [ 1 ]
- 120:d=2 hl=2 l= 36 cons: SEQUENCE
- 122:d=3 hl=2 l= 34 cons: cont [ 4 ]
- 124:d=4 hl=2 l= 11 cons: SET
- 126:d=5 hl=2 l= 9 cons: SEQUENCE
- 128:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 133:d=6 hl=2 l= 2 prim: PRINTABLESTRING :US
- 137:d=4 hl=2 l= 19 cons: SET
- 139:d=5 hl=2 l= 17 cons: SEQUENCE
- 141:d=6 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
- 146:d=6 hl=2 l= 10 prim: UTF8STRING :California
- 158:d=2 hl=2 l= 15 cons: SEQUENCE
- 160:d=3 hl=2 l= 13 cons: cont [ 4 ]
- 162:d=4 hl=2 l= 11 cons: SET
- 164:d=5 hl=2 l= 9 cons: SEQUENCE
- 166:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 171:d=6 hl=2 l= 2 prim: PRINTABLESTRING :DE
+ 0:d=0 hl=3 l= 182 cons: SEQUENCE
+ 3:d=1 hl=2 l= 119 cons: cont [ 0 ]
+ 5:d=2 hl=2 l= 17 cons: SEQUENCE
+ 7:d=3 hl=2 l= 15 cons: cont [ 4 ]
+ 9:d=4 hl=2 l= 13 cons: SEQUENCE
+ 11:d=5 hl=2 l= 11 cons: SET
+ 13:d=6 hl=2 l= 9 cons: SEQUENCE
+ 15:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 20:d=7 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 24:d=2 hl=2 l= 62 cons: SEQUENCE
+ 26:d=3 hl=2 l= 60 cons: cont [ 4 ]
+ 28:d=4 hl=2 l= 58 cons: SEQUENCE
+ 30:d=5 hl=2 l= 11 cons: SET
+ 32:d=6 hl=2 l= 9 cons: SEQUENCE
+ 34:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 39:d=7 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 43:d=5 hl=2 l= 19 cons: SET
+ 45:d=6 hl=2 l= 17 cons: SEQUENCE
+ 47:d=7 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 52:d=7 hl=2 l= 10 prim: UTF8STRING :California
+ 64:d=5 hl=2 l= 22 cons: SET
+ 66:d=6 hl=2 l= 20 cons: SEQUENCE
+ 68:d=7 hl=2 l= 3 prim: OBJECT :localityName
+ 73:d=7 hl=2 l= 13 prim: UTF8STRING :Mountain View
+ 88:d=2 hl=2 l= 34 cons: SEQUENCE
+ 90:d=3 hl=2 l= 32 cons: cont [ 4 ]
+ 92:d=4 hl=2 l= 30 cons: SEQUENCE
+ 94:d=5 hl=2 l= 11 cons: SET
+ 96:d=6 hl=2 l= 9 cons: SEQUENCE
+ 98:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 103:d=7 hl=2 l= 2 prim: PRINTABLESTRING :JP
+ 107:d=5 hl=2 l= 15 cons: SET
+ 109:d=6 hl=2 l= 13 cons: SEQUENCE
+ 111:d=7 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 116:d=7 hl=2 l= 6 prim: UTF8STRING :東京
+ 124:d=1 hl=2 l= 59 cons: cont [ 1 ]
+ 126:d=2 hl=2 l= 38 cons: SEQUENCE
+ 128:d=3 hl=2 l= 36 cons: cont [ 4 ]
+ 130:d=4 hl=2 l= 34 cons: SEQUENCE
+ 132:d=5 hl=2 l= 11 cons: SET
+ 134:d=6 hl=2 l= 9 cons: SEQUENCE
+ 136:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 141:d=7 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 145:d=5 hl=2 l= 19 cons: SET
+ 147:d=6 hl=2 l= 17 cons: SEQUENCE
+ 149:d=7 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 154:d=7 hl=2 l= 10 prim: UTF8STRING :California
+ 166:d=2 hl=2 l= 17 cons: SEQUENCE
+ 168:d=3 hl=2 l= 15 cons: cont [ 4 ]
+ 170:d=4 hl=2 l= 13 cons: SEQUENCE
+ 172:d=5 hl=2 l= 11 cons: SET
+ 174:d=6 hl=2 l= 9 cons: SEQUENCE
+ 176:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 181:d=7 hl=2 l= 2 prim: PRINTABLESTRING :DE
-----BEGIN NAME CONSTRAINTS-----
-MIGsoHEwD6QNMQswCQYDVQQGEwJVUzA8pDoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9y
-bmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MCCkHjELMAkGA1UEBhMCSlAxDzANBgNVBAgMBuad
-seS6rKE3MCSkIjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEwD6QNMQswCQYDVQQG
-EwJERQ==
+MIG2oHcwEaQPMA0xCzAJBgNVBAYTAlVTMD6kPDA6MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2Fs
+aWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzAipCAwHjELMAkGA1UEBhMCSlAxDzANBgNV
+BAgMBuadseS6rKE7MCakJDAiMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTARpA8w
+DTELMAkGA1UEBhMCREU=
-----END NAME CONSTRAINTS-----
diff --git a/chromium/net/data/name_constraints_unittest/directoryname_and_dnsname.pem b/chromium/net/data/name_constraints_unittest/directoryname_and_dnsname.pem
index 9d4a84155f8..99c9aa8ba2a 100644
--- a/chromium/net/data/name_constraints_unittest/directoryname_and_dnsname.pem
+++ b/chromium/net/data/name_constraints_unittest/directoryname_and_dnsname.pem
@@ -1,73 +1,78 @@
- 0:d=0 hl=4 l= 402 cons: SEQUENCE
- 4:d=1 hl=4 l= 272 cons: cont [ 0 ]
- 8:d=2 hl=2 l= 15 cons: SEQUENCE
- 10:d=3 hl=2 l= 13 cons: cont [ 4 ]
- 12:d=4 hl=2 l= 11 cons: SET
- 14:d=5 hl=2 l= 9 cons: SEQUENCE
- 16:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 21:d=6 hl=2 l= 2 prim: PRINTABLESTRING :US
- 25:d=2 hl=2 l= 60 cons: SEQUENCE
- 27:d=3 hl=2 l= 58 cons: cont [ 4 ]
- 29:d=4 hl=2 l= 11 cons: SET
- 31:d=5 hl=2 l= 9 cons: SEQUENCE
- 33:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 38:d=6 hl=2 l= 2 prim: PRINTABLESTRING :US
- 42:d=4 hl=2 l= 19 cons: SET
- 44:d=5 hl=2 l= 17 cons: SEQUENCE
- 46:d=6 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
- 51:d=6 hl=2 l= 10 prim: UTF8STRING :California
- 63:d=4 hl=2 l= 22 cons: SET
- 65:d=5 hl=2 l= 20 cons: SEQUENCE
- 67:d=6 hl=2 l= 3 prim: OBJECT :localityName
- 72:d=6 hl=2 l= 13 prim: UTF8STRING :Mountain View
- 87:d=2 hl=2 l= 32 cons: SEQUENCE
- 89:d=3 hl=2 l= 30 cons: cont [ 4 ]
- 91:d=4 hl=2 l= 11 cons: SET
- 93:d=5 hl=2 l= 9 cons: SEQUENCE
- 95:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 100:d=6 hl=2 l= 2 prim: PRINTABLESTRING :JP
- 104:d=4 hl=2 l= 15 cons: SET
- 106:d=5 hl=2 l= 13 cons: SEQUENCE
- 108:d=6 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
- 113:d=6 hl=2 l= 6 prim: UTF8STRING :東京
- 121:d=2 hl=2 l= 23 cons: SEQUENCE
- 123:d=3 hl=2 l= 21 prim: cont [ 2 ]
- 146:d=2 hl=2 l= 24 cons: SEQUENCE
- 148:d=3 hl=2 l= 22 prim: cont [ 2 ]
- 172:d=2 hl=2 l= 25 cons: SEQUENCE
- 174:d=3 hl=2 l= 23 prim: cont [ 2 ]
- 199:d=2 hl=2 l= 27 cons: SEQUENCE
- 201:d=3 hl=2 l= 25 prim: cont [ 2 ]
- 228:d=2 hl=2 l= 50 cons: SEQUENCE
- 230:d=3 hl=2 l= 48 prim: cont [ 2 ]
- 280:d=1 hl=2 l= 124 cons: cont [ 1 ]
- 282:d=2 hl=2 l= 36 cons: SEQUENCE
- 284:d=3 hl=2 l= 34 cons: cont [ 4 ]
- 286:d=4 hl=2 l= 11 cons: SET
- 288:d=5 hl=2 l= 9 cons: SEQUENCE
- 290:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 295:d=6 hl=2 l= 2 prim: PRINTABLESTRING :US
- 299:d=4 hl=2 l= 19 cons: SET
- 301:d=5 hl=2 l= 17 cons: SEQUENCE
- 303:d=6 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
- 308:d=6 hl=2 l= 10 prim: UTF8STRING :California
- 320:d=2 hl=2 l= 15 cons: SEQUENCE
- 322:d=3 hl=2 l= 13 cons: cont [ 4 ]
- 324:d=4 hl=2 l= 11 cons: SET
- 326:d=5 hl=2 l= 9 cons: SEQUENCE
- 328:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 333:d=6 hl=2 l= 2 prim: PRINTABLESTRING :DE
- 337:d=2 hl=2 l= 32 cons: SEQUENCE
- 339:d=3 hl=2 l= 30 prim: cont [ 2 ]
- 371:d=2 hl=2 l= 33 cons: SEQUENCE
- 373:d=3 hl=2 l= 31 prim: cont [ 2 ]
+ 0:d=0 hl=4 l= 413 cons: SEQUENCE
+ 4:d=1 hl=4 l= 278 cons: cont [ 0 ]
+ 8:d=2 hl=2 l= 17 cons: SEQUENCE
+ 10:d=3 hl=2 l= 15 cons: cont [ 4 ]
+ 12:d=4 hl=2 l= 13 cons: SEQUENCE
+ 14:d=5 hl=2 l= 11 cons: SET
+ 16:d=6 hl=2 l= 9 cons: SEQUENCE
+ 18:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 23:d=7 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 27:d=2 hl=2 l= 62 cons: SEQUENCE
+ 29:d=3 hl=2 l= 60 cons: cont [ 4 ]
+ 31:d=4 hl=2 l= 58 cons: SEQUENCE
+ 33:d=5 hl=2 l= 11 cons: SET
+ 35:d=6 hl=2 l= 9 cons: SEQUENCE
+ 37:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 42:d=7 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 46:d=5 hl=2 l= 19 cons: SET
+ 48:d=6 hl=2 l= 17 cons: SEQUENCE
+ 50:d=7 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 55:d=7 hl=2 l= 10 prim: UTF8STRING :California
+ 67:d=5 hl=2 l= 22 cons: SET
+ 69:d=6 hl=2 l= 20 cons: SEQUENCE
+ 71:d=7 hl=2 l= 3 prim: OBJECT :localityName
+ 76:d=7 hl=2 l= 13 prim: UTF8STRING :Mountain View
+ 91:d=2 hl=2 l= 34 cons: SEQUENCE
+ 93:d=3 hl=2 l= 32 cons: cont [ 4 ]
+ 95:d=4 hl=2 l= 30 cons: SEQUENCE
+ 97:d=5 hl=2 l= 11 cons: SET
+ 99:d=6 hl=2 l= 9 cons: SEQUENCE
+ 101:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 106:d=7 hl=2 l= 2 prim: PRINTABLESTRING :JP
+ 110:d=5 hl=2 l= 15 cons: SET
+ 112:d=6 hl=2 l= 13 cons: SEQUENCE
+ 114:d=7 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 119:d=7 hl=2 l= 6 prim: UTF8STRING :東京
+ 127:d=2 hl=2 l= 23 cons: SEQUENCE
+ 129:d=3 hl=2 l= 21 prim: cont [ 2 ]
+ 152:d=2 hl=2 l= 24 cons: SEQUENCE
+ 154:d=3 hl=2 l= 22 prim: cont [ 2 ]
+ 178:d=2 hl=2 l= 25 cons: SEQUENCE
+ 180:d=3 hl=2 l= 23 prim: cont [ 2 ]
+ 205:d=2 hl=2 l= 27 cons: SEQUENCE
+ 207:d=3 hl=2 l= 25 prim: cont [ 2 ]
+ 234:d=2 hl=2 l= 50 cons: SEQUENCE
+ 236:d=3 hl=2 l= 48 prim: cont [ 2 ]
+ 286:d=1 hl=3 l= 128 cons: cont [ 1 ]
+ 289:d=2 hl=2 l= 38 cons: SEQUENCE
+ 291:d=3 hl=2 l= 36 cons: cont [ 4 ]
+ 293:d=4 hl=2 l= 34 cons: SEQUENCE
+ 295:d=5 hl=2 l= 11 cons: SET
+ 297:d=6 hl=2 l= 9 cons: SEQUENCE
+ 299:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 304:d=7 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 308:d=5 hl=2 l= 19 cons: SET
+ 310:d=6 hl=2 l= 17 cons: SEQUENCE
+ 312:d=7 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 317:d=7 hl=2 l= 10 prim: UTF8STRING :California
+ 329:d=2 hl=2 l= 17 cons: SEQUENCE
+ 331:d=3 hl=2 l= 15 cons: cont [ 4 ]
+ 333:d=4 hl=2 l= 13 cons: SEQUENCE
+ 335:d=5 hl=2 l= 11 cons: SET
+ 337:d=6 hl=2 l= 9 cons: SEQUENCE
+ 339:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 344:d=7 hl=2 l= 2 prim: PRINTABLESTRING :DE
+ 348:d=2 hl=2 l= 32 cons: SEQUENCE
+ 350:d=3 hl=2 l= 30 prim: cont [ 2 ]
+ 382:d=2 hl=2 l= 33 cons: SEQUENCE
+ 384:d=3 hl=2 l= 31 prim: cont [ 2 ]
-----BEGIN NAME CONSTRAINTS-----
-MIIBkqCCARAwD6QNMQswCQYDVQQGEwJVUzA8pDoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
-Zm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MCCkHjELMAkGA1UEBhMCSlAxDzANBgNVBAgM
-BuadseS6rDAXghVwZXJtaXR0ZWQuZXhhbXBsZS5jb20wGIIWcGVybWl0dGVkLmV4YW1wbGUyLmNv
-bTAZghdwZXJtaXR0ZWQuZXhhbXBsZTMuY29tLjAbghlhbHNvcGVybWl0dGVkLmV4YW1wbGUuY29t
-MDKCMHN0aWxsbm90cGVybWl0dGVkLmV4Y2x1ZGVkLnBlcm1pdHRlZC5leGFtcGxlLmNvbaF8MCSk
-IjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEwD6QNMQswCQYDVQQGEwJERTAggh5l
-eGNsdWRlZC5wZXJtaXR0ZWQuZXhhbXBsZS5jb20wIYIfZXh0cmFuZW91c2V4Y2x1c2lvbi5leGFt
-cGxlLmNvbQ==
+MIIBnaCCARYwEaQPMA0xCzAJBgNVBAYTAlVTMD6kPDA6MQswCQYDVQQGEwJVUzETMBEGA1UECAwK
+Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzAipCAwHjELMAkGA1UEBhMCSlAxDzAN
+BgNVBAgMBuadseS6rDAXghVwZXJtaXR0ZWQuZXhhbXBsZS5jb20wGIIWcGVybWl0dGVkLmV4YW1w
+bGUyLmNvbTAZghdwZXJtaXR0ZWQuZXhhbXBsZTMuY29tLjAbghlhbHNvcGVybWl0dGVkLmV4YW1w
+bGUuY29tMDKCMHN0aWxsbm90cGVybWl0dGVkLmV4Y2x1ZGVkLnBlcm1pdHRlZC5leGFtcGxlLmNv
+baGBgDAmpCQwIjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEwEaQPMA0xCzAJBgNV
+BAYTAkRFMCCCHmV4Y2x1ZGVkLnBlcm1pdHRlZC5leGFtcGxlLmNvbTAhgh9leHRyYW5lb3VzZXhj
+bHVzaW9uLmV4YW1wbGUuY29t
-----END NAME CONSTRAINTS-----
diff --git a/chromium/net/data/name_constraints_unittest/directoryname_and_dnsname_and_ipaddress.pem b/chromium/net/data/name_constraints_unittest/directoryname_and_dnsname_and_ipaddress.pem
index 93fc4705df6..211a774aec9 100644
--- a/chromium/net/data/name_constraints_unittest/directoryname_and_dnsname_and_ipaddress.pem
+++ b/chromium/net/data/name_constraints_unittest/directoryname_and_dnsname_and_ipaddress.pem
@@ -1,97 +1,102 @@
- 0:d=0 hl=4 l= 643 cons: SEQUENCE
- 4:d=1 hl=4 l= 416 cons: cont [ 0 ]
- 8:d=2 hl=2 l= 15 cons: SEQUENCE
- 10:d=3 hl=2 l= 13 cons: cont [ 4 ]
- 12:d=4 hl=2 l= 11 cons: SET
- 14:d=5 hl=2 l= 9 cons: SEQUENCE
- 16:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 21:d=6 hl=2 l= 2 prim: PRINTABLESTRING :US
- 25:d=2 hl=2 l= 60 cons: SEQUENCE
- 27:d=3 hl=2 l= 58 cons: cont [ 4 ]
- 29:d=4 hl=2 l= 11 cons: SET
- 31:d=5 hl=2 l= 9 cons: SEQUENCE
- 33:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 38:d=6 hl=2 l= 2 prim: PRINTABLESTRING :US
- 42:d=4 hl=2 l= 19 cons: SET
- 44:d=5 hl=2 l= 17 cons: SEQUENCE
- 46:d=6 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
- 51:d=6 hl=2 l= 10 prim: UTF8STRING :California
- 63:d=4 hl=2 l= 22 cons: SET
- 65:d=5 hl=2 l= 20 cons: SEQUENCE
- 67:d=6 hl=2 l= 3 prim: OBJECT :localityName
- 72:d=6 hl=2 l= 13 prim: UTF8STRING :Mountain View
- 87:d=2 hl=2 l= 32 cons: SEQUENCE
- 89:d=3 hl=2 l= 30 cons: cont [ 4 ]
- 91:d=4 hl=2 l= 11 cons: SET
- 93:d=5 hl=2 l= 9 cons: SEQUENCE
- 95:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 100:d=6 hl=2 l= 2 prim: PRINTABLESTRING :JP
- 104:d=4 hl=2 l= 15 cons: SET
- 106:d=5 hl=2 l= 13 cons: SEQUENCE
- 108:d=6 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
- 113:d=6 hl=2 l= 6 prim: UTF8STRING :東京
- 121:d=2 hl=2 l= 23 cons: SEQUENCE
- 123:d=3 hl=2 l= 21 prim: cont [ 2 ]
- 146:d=2 hl=2 l= 24 cons: SEQUENCE
- 148:d=3 hl=2 l= 22 prim: cont [ 2 ]
- 172:d=2 hl=2 l= 25 cons: SEQUENCE
- 174:d=3 hl=2 l= 23 prim: cont [ 2 ]
- 199:d=2 hl=2 l= 27 cons: SEQUENCE
- 201:d=3 hl=2 l= 25 prim: cont [ 2 ]
- 228:d=2 hl=2 l= 50 cons: SEQUENCE
- 230:d=3 hl=2 l= 48 prim: cont [ 2 ]
- 280:d=2 hl=2 l= 10 cons: SEQUENCE
- 282:d=3 hl=2 l= 8 prim: cont [ 7 ]
- 292:d=2 hl=2 l= 10 cons: SEQUENCE
- 294:d=3 hl=2 l= 8 prim: cont [ 7 ]
- 304:d=2 hl=2 l= 10 cons: SEQUENCE
- 306:d=3 hl=2 l= 8 prim: cont [ 7 ]
- 316:d=2 hl=2 l= 34 cons: SEQUENCE
- 318:d=3 hl=2 l= 32 prim: cont [ 7 ]
- 352:d=2 hl=2 l= 34 cons: SEQUENCE
- 354:d=3 hl=2 l= 32 prim: cont [ 7 ]
- 388:d=2 hl=2 l= 34 cons: SEQUENCE
- 390:d=3 hl=2 l= 32 prim: cont [ 7 ]
- 424:d=1 hl=3 l= 220 cons: cont [ 1 ]
- 427:d=2 hl=2 l= 36 cons: SEQUENCE
- 429:d=3 hl=2 l= 34 cons: cont [ 4 ]
- 431:d=4 hl=2 l= 11 cons: SET
- 433:d=5 hl=2 l= 9 cons: SEQUENCE
- 435:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 440:d=6 hl=2 l= 2 prim: PRINTABLESTRING :US
- 444:d=4 hl=2 l= 19 cons: SET
- 446:d=5 hl=2 l= 17 cons: SEQUENCE
- 448:d=6 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
- 453:d=6 hl=2 l= 10 prim: UTF8STRING :California
- 465:d=2 hl=2 l= 15 cons: SEQUENCE
- 467:d=3 hl=2 l= 13 cons: cont [ 4 ]
- 469:d=4 hl=2 l= 11 cons: SET
- 471:d=5 hl=2 l= 9 cons: SEQUENCE
- 473:d=6 hl=2 l= 3 prim: OBJECT :countryName
- 478:d=6 hl=2 l= 2 prim: PRINTABLESTRING :DE
- 482:d=2 hl=2 l= 32 cons: SEQUENCE
- 484:d=3 hl=2 l= 30 prim: cont [ 2 ]
- 516:d=2 hl=2 l= 33 cons: SEQUENCE
- 518:d=3 hl=2 l= 31 prim: cont [ 2 ]
- 551:d=2 hl=2 l= 10 cons: SEQUENCE
- 553:d=3 hl=2 l= 8 prim: cont [ 7 ]
- 563:d=2 hl=2 l= 10 cons: SEQUENCE
- 565:d=3 hl=2 l= 8 prim: cont [ 7 ]
- 575:d=2 hl=2 l= 34 cons: SEQUENCE
- 577:d=3 hl=2 l= 32 prim: cont [ 7 ]
- 611:d=2 hl=2 l= 34 cons: SEQUENCE
- 613:d=3 hl=2 l= 32 prim: cont [ 7 ]
+ 0:d=0 hl=4 l= 653 cons: SEQUENCE
+ 4:d=1 hl=4 l= 422 cons: cont [ 0 ]
+ 8:d=2 hl=2 l= 17 cons: SEQUENCE
+ 10:d=3 hl=2 l= 15 cons: cont [ 4 ]
+ 12:d=4 hl=2 l= 13 cons: SEQUENCE
+ 14:d=5 hl=2 l= 11 cons: SET
+ 16:d=6 hl=2 l= 9 cons: SEQUENCE
+ 18:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 23:d=7 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 27:d=2 hl=2 l= 62 cons: SEQUENCE
+ 29:d=3 hl=2 l= 60 cons: cont [ 4 ]
+ 31:d=4 hl=2 l= 58 cons: SEQUENCE
+ 33:d=5 hl=2 l= 11 cons: SET
+ 35:d=6 hl=2 l= 9 cons: SEQUENCE
+ 37:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 42:d=7 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 46:d=5 hl=2 l= 19 cons: SET
+ 48:d=6 hl=2 l= 17 cons: SEQUENCE
+ 50:d=7 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 55:d=7 hl=2 l= 10 prim: UTF8STRING :California
+ 67:d=5 hl=2 l= 22 cons: SET
+ 69:d=6 hl=2 l= 20 cons: SEQUENCE
+ 71:d=7 hl=2 l= 3 prim: OBJECT :localityName
+ 76:d=7 hl=2 l= 13 prim: UTF8STRING :Mountain View
+ 91:d=2 hl=2 l= 34 cons: SEQUENCE
+ 93:d=3 hl=2 l= 32 cons: cont [ 4 ]
+ 95:d=4 hl=2 l= 30 cons: SEQUENCE
+ 97:d=5 hl=2 l= 11 cons: SET
+ 99:d=6 hl=2 l= 9 cons: SEQUENCE
+ 101:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 106:d=7 hl=2 l= 2 prim: PRINTABLESTRING :JP
+ 110:d=5 hl=2 l= 15 cons: SET
+ 112:d=6 hl=2 l= 13 cons: SEQUENCE
+ 114:d=7 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 119:d=7 hl=2 l= 6 prim: UTF8STRING :東京
+ 127:d=2 hl=2 l= 23 cons: SEQUENCE
+ 129:d=3 hl=2 l= 21 prim: cont [ 2 ]
+ 152:d=2 hl=2 l= 24 cons: SEQUENCE
+ 154:d=3 hl=2 l= 22 prim: cont [ 2 ]
+ 178:d=2 hl=2 l= 25 cons: SEQUENCE
+ 180:d=3 hl=2 l= 23 prim: cont [ 2 ]
+ 205:d=2 hl=2 l= 27 cons: SEQUENCE
+ 207:d=3 hl=2 l= 25 prim: cont [ 2 ]
+ 234:d=2 hl=2 l= 50 cons: SEQUENCE
+ 236:d=3 hl=2 l= 48 prim: cont [ 2 ]
+ 286:d=2 hl=2 l= 10 cons: SEQUENCE
+ 288:d=3 hl=2 l= 8 prim: cont [ 7 ]
+ 298:d=2 hl=2 l= 10 cons: SEQUENCE
+ 300:d=3 hl=2 l= 8 prim: cont [ 7 ]
+ 310:d=2 hl=2 l= 10 cons: SEQUENCE
+ 312:d=3 hl=2 l= 8 prim: cont [ 7 ]
+ 322:d=2 hl=2 l= 34 cons: SEQUENCE
+ 324:d=3 hl=2 l= 32 prim: cont [ 7 ]
+ 358:d=2 hl=2 l= 34 cons: SEQUENCE
+ 360:d=3 hl=2 l= 32 prim: cont [ 7 ]
+ 394:d=2 hl=2 l= 34 cons: SEQUENCE
+ 396:d=3 hl=2 l= 32 prim: cont [ 7 ]
+ 430:d=1 hl=3 l= 224 cons: cont [ 1 ]
+ 433:d=2 hl=2 l= 38 cons: SEQUENCE
+ 435:d=3 hl=2 l= 36 cons: cont [ 4 ]
+ 437:d=4 hl=2 l= 34 cons: SEQUENCE
+ 439:d=5 hl=2 l= 11 cons: SET
+ 441:d=6 hl=2 l= 9 cons: SEQUENCE
+ 443:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 448:d=7 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 452:d=5 hl=2 l= 19 cons: SET
+ 454:d=6 hl=2 l= 17 cons: SEQUENCE
+ 456:d=7 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 461:d=7 hl=2 l= 10 prim: UTF8STRING :California
+ 473:d=2 hl=2 l= 17 cons: SEQUENCE
+ 475:d=3 hl=2 l= 15 cons: cont [ 4 ]
+ 477:d=4 hl=2 l= 13 cons: SEQUENCE
+ 479:d=5 hl=2 l= 11 cons: SET
+ 481:d=6 hl=2 l= 9 cons: SEQUENCE
+ 483:d=7 hl=2 l= 3 prim: OBJECT :countryName
+ 488:d=7 hl=2 l= 2 prim: PRINTABLESTRING :DE
+ 492:d=2 hl=2 l= 32 cons: SEQUENCE
+ 494:d=3 hl=2 l= 30 prim: cont [ 2 ]
+ 526:d=2 hl=2 l= 33 cons: SEQUENCE
+ 528:d=3 hl=2 l= 31 prim: cont [ 2 ]
+ 561:d=2 hl=2 l= 10 cons: SEQUENCE
+ 563:d=3 hl=2 l= 8 prim: cont [ 7 ]
+ 573:d=2 hl=2 l= 10 cons: SEQUENCE
+ 575:d=3 hl=2 l= 8 prim: cont [ 7 ]
+ 585:d=2 hl=2 l= 34 cons: SEQUENCE
+ 587:d=3 hl=2 l= 32 prim: cont [ 7 ]
+ 621:d=2 hl=2 l= 34 cons: SEQUENCE
+ 623:d=3 hl=2 l= 32 prim: cont [ 7 ]
-----BEGIN NAME CONSTRAINTS-----
-MIICg6CCAaAwD6QNMQswCQYDVQQGEwJVUzA8pDoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
-Zm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MCCkHjELMAkGA1UEBhMCSlAxDzANBgNVBAgM
-BuadseS6rDAXghVwZXJtaXR0ZWQuZXhhbXBsZS5jb20wGIIWcGVybWl0dGVkLmV4YW1wbGUyLmNv
-bTAZghdwZXJtaXR0ZWQuZXhhbXBsZTMuY29tLjAbghlhbHNvcGVybWl0dGVkLmV4YW1wbGUuY29t
-MDKCMHN0aWxsbm90cGVybWl0dGVkLmV4Y2x1ZGVkLnBlcm1pdHRlZC5leGFtcGxlLmNvbTAKhwjA
-qAAA//8AADAKhwjAqAUg////4DAKhwjApwUg////4DAihyABAgMEBQYHCAkKCwwAAAAA////////
-////////AAAAADAihyABAgMEBQYHCAkKCwwFIAAA/////////////////+AAADAihyABAgMEBQYH
-CAkKCwsFIAAA/////////////////+AAAKGB3DAkpCIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD
-YWxpZm9ybmlhMA+kDTELMAkGA1UEBhMCREUwIIIeZXhjbHVkZWQucGVybWl0dGVkLmV4YW1wbGUu
-Y29tMCGCH2V4dHJhbmVvdXNleGNsdXNpb24uZXhhbXBsZS5jb20wCocIwKgFAP///wAwCocIwKYF
-IP///+AwIocgAQIDBAUGBwgJCgsMBQAAAP////////////////8AAAAwIocgAQIDBAUGBwgJCgsK
-BSAAAP/////////////////gAAA=
+MIICjaCCAaYwEaQPMA0xCzAJBgNVBAYTAlVTMD6kPDA6MQswCQYDVQQGEwJVUzETMBEGA1UECAwK
+Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzAipCAwHjELMAkGA1UEBhMCSlAxDzAN
+BgNVBAgMBuadseS6rDAXghVwZXJtaXR0ZWQuZXhhbXBsZS5jb20wGIIWcGVybWl0dGVkLmV4YW1w
+bGUyLmNvbTAZghdwZXJtaXR0ZWQuZXhhbXBsZTMuY29tLjAbghlhbHNvcGVybWl0dGVkLmV4YW1w
+bGUuY29tMDKCMHN0aWxsbm90cGVybWl0dGVkLmV4Y2x1ZGVkLnBlcm1pdHRlZC5leGFtcGxlLmNv
+bTAKhwjAqAAA//8AADAKhwjAqAUg////4DAKhwjApwUg////4DAihyABAgMEBQYHCAkKCwwAAAAA
+////////////////AAAAADAihyABAgMEBQYHCAkKCwwFIAAA/////////////////+AAADAihyAB
+AgMEBQYHCAkKCwsFIAAA/////////////////+AAAKGB4DAmpCQwIjELMAkGA1UEBhMCVVMxEzAR
+BgNVBAgMCkNhbGlmb3JuaWEwEaQPMA0xCzAJBgNVBAYTAkRFMCCCHmV4Y2x1ZGVkLnBlcm1pdHRl
+ZC5leGFtcGxlLmNvbTAhgh9leHRyYW5lb3VzZXhjbHVzaW9uLmV4YW1wbGUuY29tMAqHCMCoBQD/
+//8AMAqHCMCmBSD////gMCKHIAECAwQFBgcICQoLDAUAAAD/////////////////AAAAMCKHIAEC
+AwQFBgcICQoLCgUgAAD/////////////////4AAA
-----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 5f9fa4d7d7a..cdf54940f3c 100755
--- a/chromium/net/data/name_constraints_unittest/generate_name_constraints.py
+++ b/chromium/net/data/name_constraints_unittest/generate_name_constraints.py
@@ -47,7 +47,7 @@ class SubjectAltNameGenerator:
self.names.append(general_name)
def __str__(self):
- s = "asn1 = OCTWRAP,SEQUENCE:subjectAltNameSequence\n"
+ s = "asn1 = SEQUENCE:subjectAltNameSequence\n"
s += "[subjectAltNameSequence]\n"
s_suffix = ""
for n, name in enumerate(self.names):
@@ -137,7 +137,7 @@ def x400_address():
def directory_name(name):
return str(name).replace(
- 'asn1 = SEQUENCE', 'directoryName = IMPLICIT:4,SEQUENCE')
+ 'asn1 = SEQUENCE', 'directoryName = EXPLICIT:4,SEQUENCE')
def edi_party_name():
diff --git a/chromium/net/data/name_constraints_unittest/san-edipartyname.pem b/chromium/net/data/name_constraints_unittest/san-edipartyname.pem
index bf263e58fed..699aeb5c538 100644
--- a/chromium/net/data/name_constraints_unittest/san-edipartyname.pem
+++ b/chromium/net/data/name_constraints_unittest/san-edipartyname.pem
@@ -1,4 +1,6 @@
- 0:d=0 hl=2 l= 9 prim: OCTET STRING [HEX DUMP]:3007A5058103666F6F
+ 0:d=0 hl=2 l= 7 cons: SEQUENCE
+ 2:d=1 hl=2 l= 5 cons: cont [ 5 ]
+ 4:d=2 hl=2 l= 3 prim: cont [ 1 ]
-----BEGIN SUBJECT ALTERNATIVE NAME-----
-BAkwB6UFgQNmb28=
+MAelBYEDZm9v
-----END SUBJECT ALTERNATIVE NAME-----
diff --git a/chromium/net/data/name_constraints_unittest/san-excluded-directoryname.pem b/chromium/net/data/name_constraints_unittest/san-excluded-directoryname.pem
index 3f10f60b8f4..cc586ff067c 100644
--- a/chromium/net/data/name_constraints_unittest/san-excluded-directoryname.pem
+++ b/chromium/net/data/name_constraints_unittest/san-excluded-directoryname.pem
@@ -1,6 +1,32 @@
- 0:d=0 hl=2 l= 124 prim: OCTET STRING [HEX DUMP]:307A82157065726D69747465642E6578616D706C652E636F6D8704C0A80102A41F310B30090603550406130255533110300E06035504080C074172697A6F6E61A43A310B30090603550406130255533113301106035504080C0A43616C69666F726E69613116301406035504070C0D4D6F756E7461696E2056696577
+ 0:d=0 hl=2 l= 126 cons: SEQUENCE
+ 2:d=1 hl=2 l= 21 prim: cont [ 2 ]
+ 25:d=1 hl=2 l= 4 prim: cont [ 7 ]
+ 31:d=1 hl=2 l= 33 cons: cont [ 4 ]
+ 33:d=2 hl=2 l= 31 cons: SEQUENCE
+ 35:d=3 hl=2 l= 11 cons: SET
+ 37:d=4 hl=2 l= 9 cons: SEQUENCE
+ 39:d=5 hl=2 l= 3 prim: OBJECT :countryName
+ 44:d=5 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 48:d=3 hl=2 l= 16 cons: SET
+ 50:d=4 hl=2 l= 14 cons: SEQUENCE
+ 52:d=5 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 57:d=5 hl=2 l= 7 prim: UTF8STRING :Arizona
+ 66:d=1 hl=2 l= 60 cons: cont [ 4 ]
+ 68:d=2 hl=2 l= 58 cons: SEQUENCE
+ 70:d=3 hl=2 l= 11 cons: SET
+ 72:d=4 hl=2 l= 9 cons: SEQUENCE
+ 74:d=5 hl=2 l= 3 prim: OBJECT :countryName
+ 79:d=5 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 83:d=3 hl=2 l= 19 cons: SET
+ 85:d=4 hl=2 l= 17 cons: SEQUENCE
+ 87:d=5 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 92:d=5 hl=2 l= 10 prim: UTF8STRING :California
+ 104:d=3 hl=2 l= 22 cons: SET
+ 106:d=4 hl=2 l= 20 cons: SEQUENCE
+ 108:d=5 hl=2 l= 3 prim: OBJECT :localityName
+ 113:d=5 hl=2 l= 13 prim: UTF8STRING :Mountain View
-----BEGIN SUBJECT ALTERNATIVE NAME-----
-BHwweoIVcGVybWl0dGVkLmV4YW1wbGUuY29thwTAqAECpB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQI
-DAdBcml6b25hpDoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1N
-b3VudGFpbiBWaWV3
+MH6CFXBlcm1pdHRlZC5leGFtcGxlLmNvbYcEwKgBAqQhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQI
+DAdBcml6b25hpDwwOjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
+DU1vdW50YWluIFZpZXc=
-----END SUBJECT ALTERNATIVE NAME-----
diff --git a/chromium/net/data/name_constraints_unittest/san-excluded-dnsname.pem b/chromium/net/data/name_constraints_unittest/san-excluded-dnsname.pem
index 834e28a49a3..4476b9c4f3a 100644
--- a/chromium/net/data/name_constraints_unittest/san-excluded-dnsname.pem
+++ b/chromium/net/data/name_constraints_unittest/san-excluded-dnsname.pem
@@ -1,6 +1,19 @@
- 0:d=0 hl=2 l= 118 prim: OCTET STRING [HEX DUMP]:307482157065726D69747465642E6578616D706C652E636F6D8704C0A80102A41F310B30090603550406130255533110300E06035504080C074172697A6F6E618234666F6F2E7374696C6C6E6F747065726D69747465642E6578636C756465642E7065726D69747465642E6578616D706C652E636F6D
+ 0:d=0 hl=2 l= 118 cons: SEQUENCE
+ 2:d=1 hl=2 l= 21 prim: cont [ 2 ]
+ 25:d=1 hl=2 l= 4 prim: cont [ 7 ]
+ 31:d=1 hl=2 l= 33 cons: cont [ 4 ]
+ 33:d=2 hl=2 l= 31 cons: SEQUENCE
+ 35:d=3 hl=2 l= 11 cons: SET
+ 37:d=4 hl=2 l= 9 cons: SEQUENCE
+ 39:d=5 hl=2 l= 3 prim: OBJECT :countryName
+ 44:d=5 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 48:d=3 hl=2 l= 16 cons: SET
+ 50:d=4 hl=2 l= 14 cons: SEQUENCE
+ 52:d=5 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 57:d=5 hl=2 l= 7 prim: UTF8STRING :Arizona
+ 66:d=1 hl=2 l= 52 prim: cont [ 2 ]
-----BEGIN SUBJECT ALTERNATIVE NAME-----
-BHYwdIIVcGVybWl0dGVkLmV4YW1wbGUuY29thwTAqAECpB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQI
+MHaCFXBlcm1pdHRlZC5leGFtcGxlLmNvbYcEwKgBAqQhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQI
DAdBcml6b25hgjRmb28uc3RpbGxub3RwZXJtaXR0ZWQuZXhjbHVkZWQucGVybWl0dGVkLmV4YW1w
bGUuY29t
-----END SUBJECT ALTERNATIVE NAME-----
diff --git a/chromium/net/data/name_constraints_unittest/san-excluded-ipaddress.pem b/chromium/net/data/name_constraints_unittest/san-excluded-ipaddress.pem
index b4b0f18ee31..3616e7caae5 100644
--- a/chromium/net/data/name_constraints_unittest/san-excluded-ipaddress.pem
+++ b/chromium/net/data/name_constraints_unittest/san-excluded-ipaddress.pem
@@ -1,5 +1,18 @@
- 0:d=0 hl=2 l= 70 prim: OCTET STRING [HEX DUMP]:304482157065726D69747465642E6578616D706C652E636F6D8704C0A80102A41F310B30090603550406130255533110300E06035504080C074172697A6F6E618704C0A80505
+ 0:d=0 hl=2 l= 70 cons: SEQUENCE
+ 2:d=1 hl=2 l= 21 prim: cont [ 2 ]
+ 25:d=1 hl=2 l= 4 prim: cont [ 7 ]
+ 31:d=1 hl=2 l= 33 cons: cont [ 4 ]
+ 33:d=2 hl=2 l= 31 cons: SEQUENCE
+ 35:d=3 hl=2 l= 11 cons: SET
+ 37:d=4 hl=2 l= 9 cons: SEQUENCE
+ 39:d=5 hl=2 l= 3 prim: OBJECT :countryName
+ 44:d=5 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 48:d=3 hl=2 l= 16 cons: SET
+ 50:d=4 hl=2 l= 14 cons: SEQUENCE
+ 52:d=5 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 57:d=5 hl=2 l= 7 prim: UTF8STRING :Arizona
+ 66:d=1 hl=2 l= 4 prim: cont [ 7 ]
-----BEGIN SUBJECT ALTERNATIVE NAME-----
-BEYwRIIVcGVybWl0dGVkLmV4YW1wbGUuY29thwTAqAECpB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQI
+MEaCFXBlcm1pdHRlZC5leGFtcGxlLmNvbYcEwKgBAqQhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQI
DAdBcml6b25hhwTAqAUF
-----END SUBJECT ALTERNATIVE NAME-----
diff --git a/chromium/net/data/name_constraints_unittest/san-invalid-empty.pem b/chromium/net/data/name_constraints_unittest/san-invalid-empty.pem
index 684007ca287..905d9fc6d05 100644
--- a/chromium/net/data/name_constraints_unittest/san-invalid-empty.pem
+++ b/chromium/net/data/name_constraints_unittest/san-invalid-empty.pem
@@ -1,4 +1,4 @@
- 0:d=0 hl=2 l= 2 prim: OCTET STRING [HEX DUMP]:3000
+ 0:d=0 hl=2 l= 0 cons: SEQUENCE
-----BEGIN SUBJECT ALTERNATIVE NAME-----
-BAIwAA==
+MAA=
-----END SUBJECT ALTERNATIVE NAME-----
diff --git a/chromium/net/data/name_constraints_unittest/san-invalid-ipaddress.pem b/chromium/net/data/name_constraints_unittest/san-invalid-ipaddress.pem
index 2a45350c8bc..02e4e62b591 100644
--- a/chromium/net/data/name_constraints_unittest/san-invalid-ipaddress.pem
+++ b/chromium/net/data/name_constraints_unittest/san-invalid-ipaddress.pem
@@ -1,4 +1,5 @@
- 0:d=0 hl=2 l= 9 prim: OCTET STRING [HEX DUMP]:30078705C0A8000500
+ 0:d=0 hl=2 l= 7 cons: SEQUENCE
+ 2:d=1 hl=2 l= 5 prim: cont [ 7 ]
-----BEGIN SUBJECT ALTERNATIVE NAME-----
-BAkwB4cFwKgABQA=
+MAeHBcCoAAUA
-----END SUBJECT ALTERNATIVE NAME-----
diff --git a/chromium/net/data/name_constraints_unittest/san-othername.pem b/chromium/net/data/name_constraints_unittest/san-othername.pem
index 21edf4337df..b00dcfe5deb 100644
--- a/chromium/net/data/name_constraints_unittest/san-othername.pem
+++ b/chromium/net/data/name_constraints_unittest/san-othername.pem
@@ -1,4 +1,7 @@
- 0:d=0 hl=2 l= 16 prim: OCTET STRING [HEX DUMP]:300EA00C06042A0304050404DEADBEEF
+ 0:d=0 hl=2 l= 14 cons: SEQUENCE
+ 2:d=1 hl=2 l= 12 cons: cont [ 0 ]
+ 4:d=2 hl=2 l= 4 prim: OBJECT :1.2.3.4.5
+ 10:d=2 hl=2 l= 4 prim: OCTET STRING [HEX DUMP]:DEADBEEF
-----BEGIN SUBJECT ALTERNATIVE NAME-----
-BBAwDqAMBgQqAwQFBATerb7v
+MA6gDAYEKgMEBQQE3q2+7w==
-----END SUBJECT ALTERNATIVE NAME-----
diff --git a/chromium/net/data/name_constraints_unittest/san-permitted.pem b/chromium/net/data/name_constraints_unittest/san-permitted.pem
index fbb26f74857..098340fdefb 100644
--- a/chromium/net/data/name_constraints_unittest/san-permitted.pem
+++ b/chromium/net/data/name_constraints_unittest/san-permitted.pem
@@ -1,5 +1,17 @@
- 0:d=0 hl=2 l= 64 prim: OCTET STRING [HEX DUMP]:303E82157065726D69747465642E6578616D706C652E636F6D8704C0A80102A41F310B30090603550406130255533110300E06035504080C074172697A6F6E61
+ 0:d=0 hl=2 l= 64 cons: SEQUENCE
+ 2:d=1 hl=2 l= 21 prim: cont [ 2 ]
+ 25:d=1 hl=2 l= 4 prim: cont [ 7 ]
+ 31:d=1 hl=2 l= 33 cons: cont [ 4 ]
+ 33:d=2 hl=2 l= 31 cons: SEQUENCE
+ 35:d=3 hl=2 l= 11 cons: SET
+ 37:d=4 hl=2 l= 9 cons: SEQUENCE
+ 39:d=5 hl=2 l= 3 prim: OBJECT :countryName
+ 44:d=5 hl=2 l= 2 prim: PRINTABLESTRING :US
+ 48:d=3 hl=2 l= 16 cons: SET
+ 50:d=4 hl=2 l= 14 cons: SEQUENCE
+ 52:d=5 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
+ 57:d=5 hl=2 l= 7 prim: UTF8STRING :Arizona
-----BEGIN SUBJECT ALTERNATIVE NAME-----
-BEAwPoIVcGVybWl0dGVkLmV4YW1wbGUuY29thwTAqAECpB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQI
+MECCFXBlcm1pdHRlZC5leGFtcGxlLmNvbYcEwKgBAqQhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQI
DAdBcml6b25h
-----END SUBJECT ALTERNATIVE NAME-----
diff --git a/chromium/net/data/name_constraints_unittest/san-registeredid.pem b/chromium/net/data/name_constraints_unittest/san-registeredid.pem
index 11870ff9eaa..f408fb646d4 100644
--- a/chromium/net/data/name_constraints_unittest/san-registeredid.pem
+++ b/chromium/net/data/name_constraints_unittest/san-registeredid.pem
@@ -1,4 +1,5 @@
- 0:d=0 hl=2 l= 7 prim: OCTET STRING [HEX DUMP]:300588032A0304
+ 0:d=0 hl=2 l= 5 cons: SEQUENCE
+ 2:d=1 hl=2 l= 3 prim: cont [ 8 ]
-----BEGIN SUBJECT ALTERNATIVE NAME-----
-BAcwBYgDKgME
+MAWIAyoDBA==
-----END SUBJECT ALTERNATIVE NAME-----
diff --git a/chromium/net/data/name_constraints_unittest/san-rfc822name.pem b/chromium/net/data/name_constraints_unittest/san-rfc822name.pem
index 5d5f5142e32..d69c0354d64 100644
--- a/chromium/net/data/name_constraints_unittest/san-rfc822name.pem
+++ b/chromium/net/data/name_constraints_unittest/san-rfc822name.pem
@@ -1,4 +1,5 @@
- 0:d=0 hl=2 l= 19 prim: OCTET STRING [HEX DUMP]:3011810F666F6F406578616D706C652E636F6D
+ 0:d=0 hl=2 l= 17 cons: SEQUENCE
+ 2:d=1 hl=2 l= 15 prim: cont [ 1 ]
-----BEGIN SUBJECT ALTERNATIVE NAME-----
-BBMwEYEPZm9vQGV4YW1wbGUuY29t
+MBGBD2Zvb0BleGFtcGxlLmNvbQ==
-----END SUBJECT ALTERNATIVE NAME-----
diff --git a/chromium/net/data/name_constraints_unittest/san-uri.pem b/chromium/net/data/name_constraints_unittest/san-uri.pem
index 5bb31198bd3..fdf79bbba45 100644
--- a/chromium/net/data/name_constraints_unittest/san-uri.pem
+++ b/chromium/net/data/name_constraints_unittest/san-uri.pem
@@ -1,4 +1,5 @@
- 0:d=0 hl=2 l= 22 prim: OCTET STRING [HEX DUMP]:30148612687474703A2F2F6578616D706C652E636F6D
+ 0:d=0 hl=2 l= 20 cons: SEQUENCE
+ 2:d=1 hl=2 l= 18 prim: cont [ 6 ]
-----BEGIN SUBJECT ALTERNATIVE NAME-----
-BBYwFIYSaHR0cDovL2V4YW1wbGUuY29t
+MBSGEmh0dHA6Ly9leGFtcGxlLmNvbQ==
-----END SUBJECT ALTERNATIVE NAME-----
diff --git a/chromium/net/data/name_constraints_unittest/san-x400address.pem b/chromium/net/data/name_constraints_unittest/san-x400address.pem
index 8984b4ae340..26ba77def1f 100644
--- a/chromium/net/data/name_constraints_unittest/san-x400address.pem
+++ b/chromium/net/data/name_constraints_unittest/san-x400address.pem
@@ -1,4 +1,8 @@
- 0:d=0 hl=2 l= 12 prim: OCTET STRING [HEX DUMP]:300AA3083006610413025553
+ 0:d=0 hl=2 l= 10 cons: SEQUENCE
+ 2:d=1 hl=2 l= 8 cons: cont [ 3 ]
+ 4:d=2 hl=2 l= 6 cons: SEQUENCE
+ 6:d=3 hl=2 l= 4 cons: appl [ 1 ]
+ 8:d=4 hl=2 l= 2 prim: PRINTABLESTRING :US
-----BEGIN SUBJECT ALTERNATIVE NAME-----
-BAwwCqMIMAZhBBMCVVM=
+MAqjCDAGYQQTAlVT
-----END SUBJECT ALTERNATIVE NAME-----
diff --git a/chromium/net/data/parse_certificate_unittest/basic_constraints_ca_false.pem b/chromium/net/data/parse_certificate_unittest/basic_constraints_ca_false.pem
index 9acb44bc95e..e12425853ea 100644
--- a/chromium/net/data/parse_certificate_unittest/basic_constraints_ca_false.pem
+++ b/chromium/net/data/parse_certificate_unittest/basic_constraints_ca_false.pem
@@ -4,4 +4,3 @@ $ openssl asn1parse -i < [BASIC CONSTRAINTS]
-----BEGIN BASIC CONSTRAINTS-----
MAMBAQA=
-----END BASIC CONSTRAINTS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/basic_constraints_ca_no_path.pem b/chromium/net/data/parse_certificate_unittest/basic_constraints_ca_no_path.pem
index 7d25c801ec2..f74352b1ecc 100644
--- a/chromium/net/data/parse_certificate_unittest/basic_constraints_ca_no_path.pem
+++ b/chromium/net/data/parse_certificate_unittest/basic_constraints_ca_no_path.pem
@@ -4,4 +4,3 @@ $ openssl asn1parse -i < [BASIC CONSTRAINTS]
-----BEGIN BASIC CONSTRAINTS-----
MAMBAf8=
-----END BASIC CONSTRAINTS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/basic_constraints_ca_path_9.pem b/chromium/net/data/parse_certificate_unittest/basic_constraints_ca_path_9.pem
index 7bb05d22d39..4df6f39ce74 100644
--- a/chromium/net/data/parse_certificate_unittest/basic_constraints_ca_path_9.pem
+++ b/chromium/net/data/parse_certificate_unittest/basic_constraints_ca_path_9.pem
@@ -5,4 +5,3 @@ $ openssl asn1parse -i < [BASIC CONSTRAINTS]
-----BEGIN BASIC CONSTRAINTS-----
MAYBAf8CAQk=
-----END BASIC CONSTRAINTS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/basic_constraints_negative_path.pem b/chromium/net/data/parse_certificate_unittest/basic_constraints_negative_path.pem
index cc2ef3bd0e4..659a38f2b52 100644
--- a/chromium/net/data/parse_certificate_unittest/basic_constraints_negative_path.pem
+++ b/chromium/net/data/parse_certificate_unittest/basic_constraints_negative_path.pem
@@ -5,4 +5,3 @@ $ openssl asn1parse -i < [BASIC CONSTRAINTS]
-----BEGIN BASIC CONSTRAINTS-----
MAYBAf8CAf8=
-----END BASIC CONSTRAINTS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/basic_constraints_not_ca.pem b/chromium/net/data/parse_certificate_unittest/basic_constraints_not_ca.pem
index 15ad41622e8..443914033f0 100644
--- a/chromium/net/data/parse_certificate_unittest/basic_constraints_not_ca.pem
+++ b/chromium/net/data/parse_certificate_unittest/basic_constraints_not_ca.pem
@@ -3,4 +3,3 @@ $ openssl asn1parse -i < [BASIC CONSTRAINTS]
-----BEGIN BASIC CONSTRAINTS-----
MAA=
-----END BASIC CONSTRAINTS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/basic_constraints_path_too_large.pem b/chromium/net/data/parse_certificate_unittest/basic_constraints_path_too_large.pem
index dd986d1a078..9952047a0d0 100644
--- a/chromium/net/data/parse_certificate_unittest/basic_constraints_path_too_large.pem
+++ b/chromium/net/data/parse_certificate_unittest/basic_constraints_path_too_large.pem
@@ -5,4 +5,3 @@ $ openssl asn1parse -i < [BASIC CONSTRAINTS]
-----BEGIN BASIC CONSTRAINTS-----
MB0BAf8CGA///////////////////////////////w==
-----END BASIC CONSTRAINTS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_255.pem b/chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_255.pem
index b97e27415da..01bb6961e8e 100644
--- a/chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_255.pem
+++ b/chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_255.pem
@@ -5,4 +5,3 @@ $ openssl asn1parse -i < [BASIC CONSTRAINTS]
-----BEGIN BASIC CONSTRAINTS-----
MAcBAf8CAgD/
-----END BASIC CONSTRAINTS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_256.pem b/chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_256.pem
index 23c21012d90..7a3322dea42 100644
--- a/chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_256.pem
+++ b/chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_256.pem
@@ -5,4 +5,3 @@ $ openssl asn1parse -i < [BASIC CONSTRAINTS]
-----BEGIN BASIC CONSTRAINTS-----
MAcBAf8CAgEA
-----END BASIC CONSTRAINTS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_not_ca.pem b/chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_not_ca.pem
index f462f1c540d..2fa12fc759d 100644
--- a/chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_not_ca.pem
+++ b/chromium/net/data/parse_certificate_unittest/basic_constraints_pathlen_not_ca.pem
@@ -4,4 +4,3 @@ $ openssl asn1parse -i < [BASIC CONSTRAINTS]
-----BEGIN BASIC CONSTRAINTS-----
MAMCAQE=
-----END BASIC CONSTRAINTS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/basic_constraints_unconsumed_data.pem b/chromium/net/data/parse_certificate_unittest/basic_constraints_unconsumed_data.pem
index b31bb5875dd..82e7f8c824a 100644
--- a/chromium/net/data/parse_certificate_unittest/basic_constraints_unconsumed_data.pem
+++ b/chromium/net/data/parse_certificate_unittest/basic_constraints_unconsumed_data.pem
@@ -4,4 +4,3 @@ $ openssl asn1parse -i < [BASIC CONSTRAINTS]
-----BEGIN BASIC CONSTRAINTS-----
MAIFAA==
-----END BASIC CONSTRAINTS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/cert_algorithm_not_sequence.pem b/chromium/net/data/parse_certificate_unittest/cert_algorithm_not_sequence.pem
index 1e566fc74fb..96f05fee492 100644
--- a/chromium/net/data/parse_certificate_unittest/cert_algorithm_not_sequence.pem
+++ b/chromium/net/data/parse_certificate_unittest/cert_algorithm_not_sequence.pem
@@ -2,14 +2,12 @@ This is a synthesized Certificate, where the signature algorithm is an INTEGER
rather than a SEQUENCE.
-
------BEGIN CERTIFICATE-----
-MAwwAgUAAgIFAAMCAKs=
------END CERTIFICATE-----
-
$ openssl asn1parse -i < [CERTIFICATE]
0:d=0 hl=2 l= 12 cons: SEQUENCE
2:d=1 hl=2 l= 2 cons: SEQUENCE
4:d=2 hl=2 l= 0 prim: NULL
6:d=1 hl=2 l= 2 prim: INTEGER :0500
10:d=1 hl=2 l= 2 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MAwwAgUAAgIFAAMCAKs=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/cert_data_after_signature.pem b/chromium/net/data/parse_certificate_unittest/cert_data_after_signature.pem
index 8ec6f6b4932..090c1267809 100644
--- a/chromium/net/data/parse_certificate_unittest/cert_data_after_signature.pem
+++ b/chromium/net/data/parse_certificate_unittest/cert_data_after_signature.pem
@@ -2,11 +2,6 @@ This is an otherwise "valid" input to ParseCertificate(), however there is a
trailing NULL after the signature field.
-
------BEGIN CERTIFICATE-----
-MA4wAgUAMAIFAAMCAKwFAA==
------END CERTIFICATE-----
-
$ openssl asn1parse -i < [CERTIFICATE]
0:d=0 hl=2 l= 14 cons: SEQUENCE
2:d=1 hl=2 l= 2 cons: SEQUENCE
@@ -15,3 +10,6 @@ $ openssl asn1parse -i < [CERTIFICATE]
8:d=2 hl=2 l= 0 prim: NULL
10:d=1 hl=2 l= 2 prim: BIT STRING
14:d=1 hl=2 l= 0 prim: NULL
+-----BEGIN CERTIFICATE-----
+MA4wAgUAMAIFAAMCAKwFAA==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/cert_empty_sequence.pem b/chromium/net/data/parse_certificate_unittest/cert_empty_sequence.pem
index 1ec818cbe47..f6b7f9a8b91 100644
--- a/chromium/net/data/parse_certificate_unittest/cert_empty_sequence.pem
+++ b/chromium/net/data/parse_certificate_unittest/cert_empty_sequence.pem
@@ -2,10 +2,8 @@ This is an empty SEQUENCE. It will fail to be parsed as a Certificate since it
contains no fields.
-
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=2 l= 0 cons: SEQUENCE
-----BEGIN CERTIFICATE-----
MAA=
-----END CERTIFICATE-----
-
-$ openssl asn1parse -i < [CERTIFICATE]
- 0:d=0 hl=2 l= 0 cons: SEQUENCE
diff --git a/chromium/net/data/parse_certificate_unittest/cert_missing_signature.pem b/chromium/net/data/parse_certificate_unittest/cert_missing_signature.pem
index 6b347cf1590..9a5960f6d18 100644
--- a/chromium/net/data/parse_certificate_unittest/cert_missing_signature.pem
+++ b/chromium/net/data/parse_certificate_unittest/cert_missing_signature.pem
@@ -2,14 +2,12 @@ This is an otherwise "valid" Certificate input for ParseCertificate(), however
it is missing the final field (signature).
-
------BEGIN CERTIFICATE-----
-MAgwAgUAMAIFAA==
------END CERTIFICATE-----
-
$ openssl asn1parse -i < [CERTIFICATE]
0:d=0 hl=2 l= 8 cons: SEQUENCE
2:d=1 hl=2 l= 2 cons: SEQUENCE
4:d=2 hl=2 l= 0 prim: NULL
6:d=1 hl=2 l= 2 cons: SEQUENCE
8:d=2 hl=2 l= 0 prim: NULL
+-----BEGIN CERTIFICATE-----
+MAgwAgUAMAIFAA==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/cert_not_sequence.pem b/chromium/net/data/parse_certificate_unittest/cert_not_sequence.pem
index e808f827bed..3ef1bde2b1e 100644
--- a/chromium/net/data/parse_certificate_unittest/cert_not_sequence.pem
+++ b/chromium/net/data/parse_certificate_unittest/cert_not_sequence.pem
@@ -2,10 +2,8 @@ This is an otherwise valid input for ParseCertificate(), however the SEQUENCE
tag was changed to be an INTEGER.
-
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=2 l= 16 prim: INTEGER :300605003002050030020500030200AC
-----BEGIN CERTIFICATE-----
AhAwBgUAMAIFADACBQADAgCs
-----END CERTIFICATE-----
-
-$ openssl asn1parse -i < [CERTIFICATE]
- 0:d=0 hl=2 l= 16 prim: INTEGER :300605003002050030020500030200AC
diff --git a/chromium/net/data/parse_certificate_unittest/cert_signature_not_bit_string.pem b/chromium/net/data/parse_certificate_unittest/cert_signature_not_bit_string.pem
index 9a5f8765e17..5d335b9de94 100644
--- a/chromium/net/data/parse_certificate_unittest/cert_signature_not_bit_string.pem
+++ b/chromium/net/data/parse_certificate_unittest/cert_signature_not_bit_string.pem
@@ -2,11 +2,6 @@ This is an otherwise valid input to ParseSignature(), however the signature was
changed from a BIT STRING to an OCTET STRING.
-
------BEGIN CERTIFICATE-----
-MAwwAgUAMAIFAAQCAQI=
------END CERTIFICATE-----
-
$ openssl asn1parse -i < [CERTIFICATE]
0:d=0 hl=2 l= 12 cons: SEQUENCE
2:d=1 hl=2 l= 2 cons: SEQUENCE
@@ -14,3 +9,6 @@ $ openssl asn1parse -i < [CERTIFICATE]
6:d=1 hl=2 l= 2 cons: SEQUENCE
8:d=2 hl=2 l= 0 prim: NULL
10:d=1 hl=2 l= 2 prim: OCTET STRING [HEX DUMP]:0102
+-----BEGIN CERTIFICATE-----
+MAwwAgUAMAIFAAQCAQI=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/cert_skeleton.pem b/chromium/net/data/parse_certificate_unittest/cert_skeleton.pem
index 49453de4d1f..a3049adad5c 100644
--- a/chromium/net/data/parse_certificate_unittest/cert_skeleton.pem
+++ b/chromium/net/data/parse_certificate_unittest/cert_skeleton.pem
@@ -1,11 +1,6 @@
This is a valid certificate from the perspective of ParseCertificate().
-
------BEGIN CERTIFICATE-----
-MBAwBgUAMAIFADACBQADAgCs
------END CERTIFICATE-----
-
$ openssl asn1parse -i < [CERTIFICATE]
0:d=0 hl=2 l= 16 cons: SEQUENCE
2:d=1 hl=2 l= 6 cons: SEQUENCE
@@ -15,30 +10,25 @@ $ openssl asn1parse -i < [CERTIFICATE]
10:d=1 hl=2 l= 2 cons: SEQUENCE
12:d=2 hl=2 l= 0 prim: NULL
14:d=1 hl=2 l= 2 prim: BIT STRING
-
-
-
------BEGIN TBS CERTIFICATE-----
-MAYFADACBQA=
------END TBS CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MBAwBgUAMAIFADACBQADAgCs
+-----END CERTIFICATE-----
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 6 cons: SEQUENCE
2:d=1 hl=2 l= 0 prim: NULL
4:d=1 hl=2 l= 2 cons: SEQUENCE
6:d=2 hl=2 l= 0 prim: NULL
-
-
-
------BEGIN SIGNATURE ALGORITHM-----
-MAIFAA==
------END SIGNATURE ALGORITHM-----
+-----BEGIN TBS CERTIFICATE-----
+MAYFADACBQA=
+-----END TBS CERTIFICATE-----
$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
0:d=0 hl=2 l= 2 cons: SEQUENCE
2:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN SIGNATURE ALGORITHM-----
+MAIFAA==
+-----END SIGNATURE ALGORITHM-----
-----BEGIN SIGNATURE-----
rA==
diff --git a/chromium/net/data/parse_certificate_unittest/cert_version3.pem b/chromium/net/data/parse_certificate_unittest/cert_version3.pem
index 4105348fe3b..dd8468eaf40 100644
--- a/chromium/net/data/parse_certificate_unittest/cert_version3.pem
+++ b/chromium/net/data/parse_certificate_unittest/cert_version3.pem
@@ -1,35 +1,6 @@
This is a valid real-world certificate.
-
------BEGIN CERTIFICATE-----
-MIIFVzCCBD+gAwIBAgIHK2OkKnBQdjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UEBhMCVVMxEDA
-OBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY2
-9tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL3JlcG9za
-XRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTER
-MA8GA1UEBRMIMDc5NjkyODcwHhcNMTIwNDE5MTM1MzI0WhcNMTMwNDE5MTM1MzI0WjBPMRQwEgY
-DVQQKEwtrdGh1bGh1Lm5ldDEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMRQwEg
-YDVQQDEwtrdGh1bGh1Lm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK80JLhGb
-+cZDSye0QoAGJh+LxvOxRTxZuSfvTm3pzQBapvFeQuCM15tfrO66NLJ3Szsgx+SDTQLSpLqqe5K
-rm5dW2z92ePkWtxDb+3KcEG0I6Gmo0SghkVC7P4xTAgAEoov/t45JLnzYpru3AXw1zkkEdmEGS+
-M4Q1u7LP88E1bKWJ8b1O6A3KjiMAphcEPxb2EwMRdbqMygbCXy/OeL9DCiOxhMsp+lvI2e3/HEn
-PGob6ywGLf3rQMa5h3DFFSW1voMV4sCbB349N0tf0cqR02+IEahM96V+sJfLKrST9C+Zl7kIBEq
-BAGeEqz2C8V8raq1Nci4t9sYFsB7tQO3yECAwEAAaOCAbowggG2MA8GA1UdEwEB/wQFMAMBAQAw
-HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIFoDAzBgNVHR8ELDA
-qMCigJqAkhiJodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dkczEtNjguY3JsMFMGA1UdIARMMEowSA
-YLYIZIAYb9bQEHFwEwOTA3BggrBgEFBQcCARYraHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5L
-mNvbS9yZXBvc2l0b3J5LzCBgAYIKwYBBQUHAQEEdDByMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
-cC5nb2RhZGR5LmNvbS8wSgYIKwYBBQUHMAKGPmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5
-jb20vcmVwb3NpdG9yeS9nZF9pbnRlcm1lZGlhdGUuY3J0MB8GA1UdIwQYMBaAFP2sYTKTbEXW4u
-6FX5q653aZaMznMCcGA1UdEQQgMB6CC2t0aHVsaHUubmV0gg93d3cua3RodWxodS5uZXQwHQYDV
-R0OBBYEFKMeGrGp5PVQvD4F4XTPAdCeNeAXMA0GCSqGSIb3DQEBBQUAA4IBAQC3hBvUM0guBBJc
-qsVDNehFGtd+wsbgqEHMDGSMIK5ahg4rgqUevqe98xVb9n3fMF0zCs/3LYA6mbzKQo8i2Xdbbyc
-rA0Lc+k2LST1+i19rr0idYb6Dl8mzyObf0RQQHZ5wjj+GShOk4SGXuId1hJyEJZoNUjdu3yHyPf
-+K6UaDtp4B3ECZZPyz19SFsYTsBX7Pm1u0tA6kDpNaNQxOlEEQQ+ogKFeqSJ7d0/3D83WFmIxtH
-KV7jpWcZcSVDjacjFZIsVTgjQgkgIkkUrAvqsFPFTcUnXogk6qtGxH4C17wXoQO7Tsa+j3McYP1
-HZmCxBi7r3fZJEu5k5TpvDU4Kemf
------END CERTIFICATE-----
-
$ openssl asn1parse -i < [CERTIFICATE]
0:d=0 hl=4 l=1367 cons: SEQUENCE
4:d=1 hl=4 l=1087 cons: SEQUENCE
@@ -124,31 +95,33 @@ $ openssl asn1parse -i < [CERTIFICATE]
1097:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
1108:d=2 hl=2 l= 0 prim: NULL
1110:d=1 hl=4 l= 257 prim: BIT STRING
-
-
-
------BEGIN TBS CERTIFICATE-----
-MIIEP6ADAgECAgcrY6QqcFB2MA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJVUzEQMA4GA1U
-ECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIE
-luYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9ye
-TEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MREwDwYD
-VQQFEwgwNzk2OTI4NzAeFw0xMjA0MTkxMzUzMjRaFw0xMzA0MTkxMzUzMjRaME8xFDASBgNVBAo
-TC2t0aHVsaHUubmV0MSEwHwYDVQQLExhEb21haW4gQ29udHJvbCBWYWxpZGF0ZWQxFDASBgNVBA
-MTC2t0aHVsaHUubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArzQkuEZv5xkNL
-J7RCgAYmH4vG87FFPFm5J+9ObenNAFqm8V5C4IzXm1+s7ro0sndLOyDH5INNAtKkuqp7kqubl1b
-bP3Z4+Ra3ENv7cpwQbQjoaajRKCGRULs/jFMCAASii/+3jkkufNimu7cBfDXOSQR2YQZL4zhDW7
-ss/zwTVspYnxvU7oDcqOIwCmFwQ/FvYTAxF1uozKBsJfL854v0MKI7GEyyn6W8jZ7f8cSc8ahvr
-LAYt/etAxrmHcMUVJbW+gxXiwJsHfj03S1/RypHTb4gRqEz3pX6wl8sqtJP0L5mXuQgESoEAZ4S
-rPYLxXytqrU1yLi32xgWwHu1A7fIQIDAQABo4IBujCCAbYwDwYDVR0TAQH/BAUwAwEBADAdBgNV
-HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQDAgWgMDMGA1UdHwQsMCowKKA
-moCSGImh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2RzMS02OC5jcmwwUwYDVR0gBEwwSjBIBgtghk
-gBhv1tAQcXATA5MDcGCCsGAQUFBwIBFitodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL
-3JlcG9zaXRvcnkvMIGABggrBgEFBQcBAQR0MHIwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmdv
-ZGFkZHkuY29tLzBKBggrBgEFBQcwAoY+aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9
-yZXBvc2l0b3J5L2dkX2ludGVybWVkaWF0ZS5jcnQwHwYDVR0jBBgwFoAU/axhMpNsRdbi7oVfmr
-rndplozOcwJwYDVR0RBCAwHoILa3RodWxodS5uZXSCD3d3dy5rdGh1bGh1Lm5ldDAdBgNVHQ4EF
-gQUox4asank9VC8PgXhdM8B0J414Bc=
------END TBS CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFVzCCBD+gAwIBAgIHK2OkKnBQdjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UEBhMCVVMxEDA
+OBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY2
+9tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL3JlcG9za
+XRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTER
+MA8GA1UEBRMIMDc5NjkyODcwHhcNMTIwNDE5MTM1MzI0WhcNMTMwNDE5MTM1MzI0WjBPMRQwEgY
+DVQQKEwtrdGh1bGh1Lm5ldDEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMRQwEg
+YDVQQDEwtrdGh1bGh1Lm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK80JLhGb
++cZDSye0QoAGJh+LxvOxRTxZuSfvTm3pzQBapvFeQuCM15tfrO66NLJ3Szsgx+SDTQLSpLqqe5K
+rm5dW2z92ePkWtxDb+3KcEG0I6Gmo0SghkVC7P4xTAgAEoov/t45JLnzYpru3AXw1zkkEdmEGS+
+M4Q1u7LP88E1bKWJ8b1O6A3KjiMAphcEPxb2EwMRdbqMygbCXy/OeL9DCiOxhMsp+lvI2e3/HEn
+PGob6ywGLf3rQMa5h3DFFSW1voMV4sCbB349N0tf0cqR02+IEahM96V+sJfLKrST9C+Zl7kIBEq
+BAGeEqz2C8V8raq1Nci4t9sYFsB7tQO3yECAwEAAaOCAbowggG2MA8GA1UdEwEB/wQFMAMBAQAw
+HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIFoDAzBgNVHR8ELDA
+qMCigJqAkhiJodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dkczEtNjguY3JsMFMGA1UdIARMMEowSA
+YLYIZIAYb9bQEHFwEwOTA3BggrBgEFBQcCARYraHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5L
+mNvbS9yZXBvc2l0b3J5LzCBgAYIKwYBBQUHAQEEdDByMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
+cC5nb2RhZGR5LmNvbS8wSgYIKwYBBQUHMAKGPmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5
+jb20vcmVwb3NpdG9yeS9nZF9pbnRlcm1lZGlhdGUuY3J0MB8GA1UdIwQYMBaAFP2sYTKTbEXW4u
+6FX5q653aZaMznMCcGA1UdEQQgMB6CC2t0aHVsaHUubmV0gg93d3cua3RodWxodS5uZXQwHQYDV
+R0OBBYEFKMeGrGp5PVQvD4F4XTPAdCeNeAXMA0GCSqGSIb3DQEBBQUAA4IBAQC3hBvUM0guBBJc
+qsVDNehFGtd+wsbgqEHMDGSMIK5ahg4rgqUevqe98xVb9n3fMF0zCs/3LYA6mbzKQo8i2Xdbbyc
+rA0Lc+k2LST1+i19rr0idYb6Dl8mzyObf0RQQHZ5wjj+GShOk4SGXuId1hJyEJZoNUjdu3yHyPf
++K6UaDtp4B3ECZZPyz19SFsYTsBX7Pm1u0tA6kDpNaNQxOlEEQQ+ogKFeqSJ7d0/3D83WFmIxtH
+KV7jpWcZcSVDjacjFZIsVTgjQgkgIkkUrAvqsFPFTcUnXogk6qtGxH4C17wXoQO7Tsa+j3McYP1
+HZmCxBi7r3fZJEu5k5TpvDU4Kemf
+-----END CERTIFICATE-----
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=4 l=1087 cons: SEQUENCE
@@ -239,19 +212,36 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
1060:d=3 hl=2 l= 29 cons: SEQUENCE
1062:d=4 hl=2 l= 3 prim: OBJECT :X509v3 Subject Key Identifier
1067:d=4 hl=2 l= 22 prim: OCTET STRING [HEX DUMP]:0414A31E1AB1A9E4F550BC3E05E174CF01D09E35E017
-
-
-
------BEGIN SIGNATURE ALGORITHM-----
-MA0GCSqGSIb3DQEBBQUA
------END SIGNATURE ALGORITHM-----
+-----BEGIN TBS CERTIFICATE-----
+MIIEP6ADAgECAgcrY6QqcFB2MA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJVUzEQMA4GA1U
+ECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIE
+luYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9ye
+TEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MREwDwYD
+VQQFEwgwNzk2OTI4NzAeFw0xMjA0MTkxMzUzMjRaFw0xMzA0MTkxMzUzMjRaME8xFDASBgNVBAo
+TC2t0aHVsaHUubmV0MSEwHwYDVQQLExhEb21haW4gQ29udHJvbCBWYWxpZGF0ZWQxFDASBgNVBA
+MTC2t0aHVsaHUubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArzQkuEZv5xkNL
+J7RCgAYmH4vG87FFPFm5J+9ObenNAFqm8V5C4IzXm1+s7ro0sndLOyDH5INNAtKkuqp7kqubl1b
+bP3Z4+Ra3ENv7cpwQbQjoaajRKCGRULs/jFMCAASii/+3jkkufNimu7cBfDXOSQR2YQZL4zhDW7
+ss/zwTVspYnxvU7oDcqOIwCmFwQ/FvYTAxF1uozKBsJfL854v0MKI7GEyyn6W8jZ7f8cSc8ahvr
+LAYt/etAxrmHcMUVJbW+gxXiwJsHfj03S1/RypHTb4gRqEz3pX6wl8sqtJP0L5mXuQgESoEAZ4S
+rPYLxXytqrU1yLi32xgWwHu1A7fIQIDAQABo4IBujCCAbYwDwYDVR0TAQH/BAUwAwEBADAdBgNV
+HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQDAgWgMDMGA1UdHwQsMCowKKA
+moCSGImh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2RzMS02OC5jcmwwUwYDVR0gBEwwSjBIBgtghk
+gBhv1tAQcXATA5MDcGCCsGAQUFBwIBFitodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL
+3JlcG9zaXRvcnkvMIGABggrBgEFBQcBAQR0MHIwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmdv
+ZGFkZHkuY29tLzBKBggrBgEFBQcwAoY+aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9
+yZXBvc2l0b3J5L2dkX2ludGVybWVkaWF0ZS5jcnQwHwYDVR0jBBgwFoAU/axhMpNsRdbi7oVfmr
+rndplozOcwJwYDVR0RBCAwHoILa3RodWxodS5uZXSCD3d3dy5rdGh1bGh1Lm5ldDAdBgNVHQ4EF
+gQUox4asank9VC8PgXhdM8B0J414Bc=
+-----END TBS CERTIFICATE-----
$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN SIGNATURE ALGORITHM-----
+MA0GCSqGSIb3DQEBBQUA
+-----END SIGNATURE ALGORITHM-----
-----BEGIN SIGNATURE-----
t4Qb1DNILgQSXKrFQzXoRRrXfsLG4KhBzAxkjCCuWoYOK4KlHr6nvfMVW/Z93zBdMwrP9y2AOpm
diff --git a/chromium/net/data/parse_certificate_unittest/extension_critical.pem b/chromium/net/data/parse_certificate_unittest/extension_critical.pem
index fb105bcee58..1f79e69580e 100644
--- a/chromium/net/data/parse_certificate_unittest/extension_critical.pem
+++ b/chromium/net/data/parse_certificate_unittest/extension_critical.pem
@@ -6,7 +6,6 @@ $ openssl asn1parse -i < [EXTENSION]
2:d=1 hl=2 l= 3 prim: OBJECT :X509v3 Basic Constraints
7:d=1 hl=2 l= 1 prim: BOOLEAN :255
10:d=1 hl=2 l= 2 prim: OCTET STRING [HEX DUMP]:3000
-
-----BEGIN EXTENSION-----
MAwGA1UdEwEB/wQCMAA=
-----END EXTENSION-----
diff --git a/chromium/net/data/parse_certificate_unittest/extension_critical_0.pem b/chromium/net/data/parse_certificate_unittest/extension_critical_0.pem
index a057ac54682..915cbbc4a1c 100644
--- a/chromium/net/data/parse_certificate_unittest/extension_critical_0.pem
+++ b/chromium/net/data/parse_certificate_unittest/extension_critical_0.pem
@@ -9,7 +9,6 @@ $ openssl asn1parse -i < [EXTENSION]
2:d=1 hl=2 l= 3 prim: OBJECT :X509v3 Basic Constraints
7:d=1 hl=2 l= 1 prim: BOOLEAN :0
10:d=1 hl=2 l= 2 prim: OCTET STRING [HEX DUMP]:3000
-
-----BEGIN EXTENSION-----
MAwGA1UdEwEBAAQCMAA=
-----END EXTENSION-----
diff --git a/chromium/net/data/parse_certificate_unittest/extension_critical_3.pem b/chromium/net/data/parse_certificate_unittest/extension_critical_3.pem
index 435c8432f6a..97b8f08ab48 100644
--- a/chromium/net/data/parse_certificate_unittest/extension_critical_3.pem
+++ b/chromium/net/data/parse_certificate_unittest/extension_critical_3.pem
@@ -9,7 +9,6 @@ $ openssl asn1parse -i < [EXTENSION]
2:d=1 hl=2 l= 3 prim: OBJECT :X509v3 Basic Constraints
7:d=1 hl=2 l= 1 prim: BOOLEAN :3
10:d=1 hl=2 l= 2 prim: OCTET STRING [HEX DUMP]:3000
-
-----BEGIN EXTENSION-----
MAwGA1UdEwEBAwQCMAA=
-----END EXTENSION-----
diff --git a/chromium/net/data/parse_certificate_unittest/extension_not_critical.pem b/chromium/net/data/parse_certificate_unittest/extension_not_critical.pem
index 0c845353a4f..7e90c7aa777 100644
--- a/chromium/net/data/parse_certificate_unittest/extension_not_critical.pem
+++ b/chromium/net/data/parse_certificate_unittest/extension_not_critical.pem
@@ -6,7 +6,6 @@ $ openssl asn1parse -i < [EXTENSION]
0:d=0 hl=2 l= 9 cons: SEQUENCE
2:d=1 hl=2 l= 3 prim: OBJECT :X509v3 Basic Constraints
7:d=1 hl=2 l= 2 prim: OCTET STRING [HEX DUMP]:3000
-
-----BEGIN EXTENSION-----
MAkGA1UdEwQCMAA=
-----END EXTENSION-----
diff --git a/chromium/net/data/parse_certificate_unittest/extensions_basic_constraints.pem b/chromium/net/data/parse_certificate_unittest/extensions_basic_constraints.pem
index 211cef081d8..771cb4038c8 100644
--- a/chromium/net/data/parse_certificate_unittest/extensions_basic_constraints.pem
+++ b/chromium/net/data/parse_certificate_unittest/extensions_basic_constraints.pem
@@ -13,4 +13,3 @@ $ openssl asn1parse -i < [BASIC CONSTRAINTS]
-----BEGIN BASIC CONSTRAINTS-----
MAA=
-----END BASIC CONSTRAINTS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/extensions_data_after_sequence.pem b/chromium/net/data/parse_certificate_unittest/extensions_data_after_sequence.pem
index 5bf26acb5c7..0c56b1dafe5 100644
--- a/chromium/net/data/parse_certificate_unittest/extensions_data_after_sequence.pem
+++ b/chromium/net/data/parse_certificate_unittest/extensions_data_after_sequence.pem
@@ -8,4 +8,3 @@ $ openssl asn1parse -i < [EXTENSIONS]
-----BEGIN EXTENSIONS-----
MBIwDgYDVR0PAQH/BAQDAgO4BQA=
-----END EXTENSIONS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/extensions_duplicate_key_usage.pem b/chromium/net/data/parse_certificate_unittest/extensions_duplicate_key_usage.pem
index c2633848a7a..85624e999ff 100644
--- a/chromium/net/data/parse_certificate_unittest/extensions_duplicate_key_usage.pem
+++ b/chromium/net/data/parse_certificate_unittest/extensions_duplicate_key_usage.pem
@@ -11,4 +11,3 @@ $ openssl asn1parse -i < [EXTENSIONS]
-----BEGIN EXTENSIONS-----
MCAwDgYDVR0PAQH/BAQDAgO4MA4GA1UdDwEB/wQEAwIDuA==
-----END EXTENSIONS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/extensions_empty_sequence.pem b/chromium/net/data/parse_certificate_unittest/extensions_empty_sequence.pem
index d3f1a73dd0b..fe021083609 100644
--- a/chromium/net/data/parse_certificate_unittest/extensions_empty_sequence.pem
+++ b/chromium/net/data/parse_certificate_unittest/extensions_empty_sequence.pem
@@ -3,4 +3,3 @@ $ openssl asn1parse -i < [EXTENSIONS]
-----BEGIN EXTENSIONS-----
MAA=
-----END EXTENSIONS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/extensions_extended_key_usage.pem b/chromium/net/data/parse_certificate_unittest/extensions_extended_key_usage.pem
index 9cda6e21e23..6b253cd02ca 100644
--- a/chromium/net/data/parse_certificate_unittest/extensions_extended_key_usage.pem
+++ b/chromium/net/data/parse_certificate_unittest/extensions_extended_key_usage.pem
@@ -17,4 +17,3 @@ $ openssl asn1parse -i < [EXTENDED KEY USAGE]
-----BEGIN EXTENDED KEY USAGE-----
MCsGCCsGAQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNwoDAwYJYIZIAYb4QgQB
-----END EXTENDED KEY USAGE-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/extensions_key_usage.pem b/chromium/net/data/parse_certificate_unittest/extensions_key_usage.pem
index 1b56edd0a33..7762c535371 100644
--- a/chromium/net/data/parse_certificate_unittest/extensions_key_usage.pem
+++ b/chromium/net/data/parse_certificate_unittest/extensions_key_usage.pem
@@ -13,4 +13,3 @@ $ openssl asn1parse -i < [KEY USAGE]
-----BEGIN KEY USAGE-----
AwIFoA==
-----END KEY USAGE-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/extensions_not_sequence.pem b/chromium/net/data/parse_certificate_unittest/extensions_not_sequence.pem
index f8cb11b7f32..4b1b625bada 100644
--- a/chromium/net/data/parse_certificate_unittest/extensions_not_sequence.pem
+++ b/chromium/net/data/parse_certificate_unittest/extensions_not_sequence.pem
@@ -3,4 +3,3 @@ $ openssl asn1parse -i < [EXTENSIONS]
-----BEGIN EXTENSIONS-----
BQA=
-----END EXTENSIONS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/extensions_policies.pem b/chromium/net/data/parse_certificate_unittest/extensions_policies.pem
index 79a1c90aa00..13457bcb13c 100644
--- a/chromium/net/data/parse_certificate_unittest/extensions_policies.pem
+++ b/chromium/net/data/parse_certificate_unittest/extensions_policies.pem
@@ -22,4 +22,3 @@ $ openssl asn1parse -i < [POLICIES]
MF0wTQYKKoMIjJweAQICATA/MD0GCCsGAQUFBwIBFjFodHRwczovL3JlcG8xLnNlY29tdHJ1c3Q
ubmV0L3NwY3BwL2Nwcy9pbmRleC5odG1sMAwGCiqDCIybG2SHBQE=
-----END POLICIES-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/extensions_real.pem b/chromium/net/data/parse_certificate_unittest/extensions_real.pem
index 5ece71c420a..5a475def8b0 100644
--- a/chromium/net/data/parse_certificate_unittest/extensions_real.pem
+++ b/chromium/net/data/parse_certificate_unittest/extensions_real.pem
@@ -1,5 +1,6 @@
A real world extensions sequence (taken from Google's GAI2).
+
$ openssl asn1parse -i < [EXTENSIONS]
0:d=0 hl=3 l= 228 cons: SEQUENCE
3:d=1 hl=2 l= 31 cons: SEQUENCE
@@ -32,4 +33,3 @@ JodHRwOi8vZy5zeW1jZC5jb20wEgYDVR0TAQH/BAgwBgEB/wIBADA1BgNVHR8ELjAsMCqgKKAmh
iRodHRwOi8vZy5zeW1jYi5jb20vY3Jscy9ndGdsb2JhbC5jcmwwFwYDVR0gBBAwDjAMBgorBgEE
AdZ5AgUB
-----END EXTENSIONS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/extensions_subject_alt_name.pem b/chromium/net/data/parse_certificate_unittest/extensions_subject_alt_name.pem
index 3ce5fdad035..98a59bd7169 100644
--- a/chromium/net/data/parse_certificate_unittest/extensions_subject_alt_name.pem
+++ b/chromium/net/data/parse_certificate_unittest/extensions_subject_alt_name.pem
@@ -13,4 +13,3 @@ $ openssl asn1parse -i < [SUBJECT ALT NAME]
-----BEGIN SUBJECT ALT NAME-----
MBWCE2VtZXJnZW5jeXN1cHBvcnQudXM=
-----END SUBJECT ALT NAME-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/extensions_unknown_critical.pem b/chromium/net/data/parse_certificate_unittest/extensions_unknown_critical.pem
index 3913615c74b..aa4503f5bb3 100644
--- a/chromium/net/data/parse_certificate_unittest/extensions_unknown_critical.pem
+++ b/chromium/net/data/parse_certificate_unittest/extensions_unknown_critical.pem
@@ -7,4 +7,3 @@ $ openssl asn1parse -i < [EXTENSIONS]
-----BEGIN EXTENSIONS-----
MBkwFwYMKoZIhvcSBAGEtwkAAQH/BAQDAgO4
-----END EXTENSIONS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/extensions_unknown_non_critical.pem b/chromium/net/data/parse_certificate_unittest/extensions_unknown_non_critical.pem
index 532cb2ab22a..0814267d404 100644
--- a/chromium/net/data/parse_certificate_unittest/extensions_unknown_non_critical.pem
+++ b/chromium/net/data/parse_certificate_unittest/extensions_unknown_non_critical.pem
@@ -6,4 +6,3 @@ $ openssl asn1parse -i < [EXTENSIONS]
-----BEGIN EXTENSIONS-----
MBYwFAYMKoZIhvcSBAGEtwkABAQDAgO4
-----END EXTENSIONS-----
-
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_explicit_v1.pem b/chromium/net/data/parse_certificate_unittest/tbs_explicit_v1.pem
index 67edbb3e6d5..03599eaaac6 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_explicit_v1.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_explicit_v1.pem
@@ -2,12 +2,6 @@ This is an otherwise valid v1 certificate, except the version has been encoded
explicitly as 0. Instead it should have been omitted.
-
------BEGIN TBS CERTIFICATE-----
-MDygAwIBAAIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
-DMAMEAfM=
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 60 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -24,3 +18,7 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
54:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
57:d=1 hl=2 l= 3 cons: SEQUENCE
59:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
+-----BEGIN TBS CERTIFICATE-----
+MDygAwIBAAIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
+DMAMEAfM=
+-----END TBS CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_negative_serial_number.pem b/chromium/net/data/parse_certificate_unittest/tbs_negative_serial_number.pem
index f7da2869fc1..fb9a712618b 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_negative_serial_number.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_negative_serial_number.pem
@@ -2,12 +2,6 @@ This is a valid TBSCertificate. However the Serial Number is negative (which
strictly speaking is not correct).
-
------BEGIN TBS CERTIFICATE-----
-MEOgAwIBAgIIiR6QqQAANUAwAwQBATADBAEFMB4XDTEyMTAxODAzMTIwMFoXDTEzMTAxODE0NTk
-1OVowAwQBgzADBAHz
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 67 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -24,67 +18,51 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
61:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
64:d=1 hl=2 l= 3 cons: SEQUENCE
66:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-
-
+-----BEGIN TBS CERTIFICATE-----
+MEOgAwIBAgIIiR6QqQAANUAwAwQBATADBAEFMB4XDTEyMTAxODAzMTIwMFoXDTEzMTAxODE0NTk
+1OVowAwQBgzADBAHz
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
iR6QqQAANUA=
-----END SERIAL NUMBER-----
-
-
+$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-----BEGIN SIGNATURE ALGORITHM-----
MAMEAQE=
-----END SIGNATURE ALGORITHM-----
-$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-----BEGIN ISSUER-----
MAMEAQU=
-----END ISSUER-----
-$ openssl asn1parse -i < [ISSUER]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-
-
-
+VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDEyLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0zLCBtaW51dGVzPTEyLCBzZWNvbmR
zPTA=
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-
-
-
+VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDEzLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0xNCwgbWludXRlcz01OSwgc2Vjb25
kcz01OQ==
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-
-
-
+$ openssl asn1parse -i < [SUBJECT]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-----BEGIN SUBJECT-----
MAMEAYM=
-----END SUBJECT-----
-$ openssl asn1parse -i < [SUBJECT]
+$ openssl asn1parse -i < [SPKI]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-----BEGIN SPKI-----
MAMEAfM=
-----END SPKI-----
-
-$ openssl asn1parse -i < [SPKI]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_serial_number_21_octets_leading_0.pem b/chromium/net/data/parse_certificate_unittest/tbs_serial_number_21_octets_leading_0.pem
index e09125fb7d5..efbf0533da4 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_serial_number_21_octets_leading_0.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_serial_number_21_octets_leading_0.pem
@@ -2,12 +2,6 @@ This is a TBSCertificate where the serial number is more than 20 octets (21
octets, where first octet is a 0). This violates the rules in RFC 5280.
-
------BEGIN TBS CERTIFICATE-----
-MFCgAwIBAAIVANjDfk2H+cjIK68m71NQHfH886UgMAMEAQEwAwQBBTAeFw0xMjEwMTgwMzEyMDB
-aFw0xMzEwMTgxNDU5NTlaMAMEAYMwAwQB8w==
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 80 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -24,3 +18,7 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
74:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
77:d=1 hl=2 l= 3 cons: SEQUENCE
79:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
+-----BEGIN TBS CERTIFICATE-----
+MFCgAwIBAAIVANjDfk2H+cjIK68m71NQHfH886UgMAMEAQEwAwQBBTAeFw0xMjEwMTgwMzEyMDB
+aFw0xMzEwMTgxNDU5NTlaMAMEAYMwAwQB8w==
+-----END TBS CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_serial_number_26_octets.pem b/chromium/net/data/parse_certificate_unittest/tbs_serial_number_26_octets.pem
index 0ea885bf0cb..fe24034a8de 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_serial_number_26_octets.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_serial_number_26_octets.pem
@@ -2,12 +2,6 @@ This is a TBSCertificate which has a serial number that is 26 octets long. This
violates RFC 5280.
-
------BEGIN TBS CERTIFICATE-----
-MFWgAwIBAAIaQsg8eFVS5Dkn5IvhKA+iD5+wj0f5RMMmaPkwAwQBATADBAEFMB4XDTEyMTAxODA
-zMTIwMFoXDTEzMTAxODE0NTk1OVowAwQBgzADBAHz
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 85 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -24,3 +18,7 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
79:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
82:d=1 hl=2 l= 3 cons: SEQUENCE
84:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
+-----BEGIN TBS CERTIFICATE-----
+MFWgAwIBAAIaQsg8eFVS5Dkn5IvhKA+iD5+wj0f5RMMmaPkwAwQBATADBAEFMB4XDTEyMTAxODA
+zMTIwMFoXDTEzMTAxODE0NTk1OVowAwQBgzADBAHz
+-----END TBS CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v1.pem b/chromium/net/data/parse_certificate_unittest/tbs_v1.pem
index ae0ebbd7be7..198cd2afd25 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v1.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v1.pem
@@ -1,12 +1,6 @@
This is a TBSCertificate which omits the version field (meaning it is v1).
-
------BEGIN TBS CERTIFICATE-----
-MDcCAQEwAwQBATADBAEFMB4XDTEyMTAxODAzMTIwMFoXDTEzMTAxODE0NTk1OVowAwQBgzADBAH
-z
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 55 cons: SEQUENCE
2:d=1 hl=2 l= 1 prim: INTEGER :01
@@ -21,67 +15,51 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
49:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
52:d=1 hl=2 l= 3 cons: SEQUENCE
54:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-
-
+-----BEGIN TBS CERTIFICATE-----
+MDcCAQEwAwQBATADBAEFMB4XDTEyMTAxODAzMTIwMFoXDTEzMTAxODE0NTk1OVowAwQBgzADBAH
+z
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
AQ==
-----END SERIAL NUMBER-----
-
-
+$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-----BEGIN SIGNATURE ALGORITHM-----
MAMEAQE=
-----END SIGNATURE ALGORITHM-----
-$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-----BEGIN ISSUER-----
MAMEAQU=
-----END ISSUER-----
-$ openssl asn1parse -i < [ISSUER]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-
-
-
+VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDEyLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0zLCBtaW51dGVzPTEyLCBzZWNvbmR
zPTA=
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-
-
-
+VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDEzLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0xNCwgbWludXRlcz01OSwgc2Vjb25
kcz01OQ==
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-
-
-
+$ openssl asn1parse -i < [SUBJECT]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-----BEGIN SUBJECT-----
MAMEAYM=
-----END SUBJECT-----
-$ openssl asn1parse -i < [SUBJECT]
+$ openssl asn1parse -i < [SPKI]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-----BEGIN SPKI-----
MAMEAfM=
-----END SPKI-----
-
-$ openssl asn1parse -i < [SPKI]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v1_extensions.pem b/chromium/net/data/parse_certificate_unittest/tbs_v1_extensions.pem
index 82b13a9e8bb..d55125630ed 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v1_extensions.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v1_extensions.pem
@@ -2,12 +2,6 @@ This is an otherwise valid TBSCertificate, however it lacks a version (making
it v1). As such extensions are not allowed.
-
------BEGIN TBS CERTIFICATE-----
-MD4CAQEwAwQBATADBAEFMB4XDTEyMTAxODAzMTIwMFoXDTEzMTAxODE0NTk1OVowAwQBgzADBAH
-zowUwAwQB3Q==
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 62 cons: SEQUENCE
2:d=1 hl=2 l= 1 prim: INTEGER :01
@@ -25,3 +19,7 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
57:d=1 hl=2 l= 5 cons: cont [ 3 ]
59:d=2 hl=2 l= 3 cons: SEQUENCE
61:d=3 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:DD
+-----BEGIN TBS CERTIFICATE-----
+MD4CAQEwAwQBATADBAEFMB4XDTEyMTAxODAzMTIwMFoXDTEzMTAxODE0NTk1OVowAwQBgzADBAH
+zowUwAwQB3Q==
+-----END TBS CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v2_extensions.pem b/chromium/net/data/parse_certificate_unittest/tbs_v2_extensions.pem
index ef84533cfe8..33ca59d229e 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v2_extensions.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v2_extensions.pem
@@ -2,12 +2,6 @@ This is a v2 certificate which contains extensions. This is invalid since v2
does not have extensions defined.
-
------BEGIN TBS CERTIFICATE-----
-MEOgAwIBAQIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
-DMAMEAfOjBTADBAHd
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 67 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -27,3 +21,7 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
62:d=1 hl=2 l= 5 cons: cont [ 3 ]
64:d=2 hl=2 l= 3 cons: SEQUENCE
66:d=3 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:DD
+-----BEGIN TBS CERTIFICATE-----
+MEOgAwIBAQIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
+DMAMEAfOjBTADBAHd
+-----END TBS CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v2_issuer_and_subject_unique_id.pem b/chromium/net/data/parse_certificate_unittest/tbs_v2_issuer_and_subject_unique_id.pem
index cbecd8d0385..eff7abccdf3 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v2_issuer_and_subject_unique_id.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v2_issuer_and_subject_unique_id.pem
@@ -2,12 +2,6 @@ This is a version 2 certificate containing both the issuer unique ID and
subject unique ID fields.
-
------BEGIN TBS CERTIFICATE-----
-MESgAwIBAQIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
-DMAMEAfOBAgC5ggIAyg==
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 68 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -26,79 +20,59 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
59:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
62:d=1 hl=2 l= 2 prim: cont [ 1 ]
66:d=1 hl=2 l= 2 prim: cont [ 2 ]
-
-
+-----BEGIN TBS CERTIFICATE-----
+MESgAwIBAQIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
+DMAMEAfOBAgC5ggIAyg==
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
AQ==
-----END SERIAL NUMBER-----
-
-
+$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-----BEGIN SIGNATURE ALGORITHM-----
MAMEAQE=
-----END SIGNATURE ALGORITHM-----
-$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-----BEGIN ISSUER-----
MAMEAQU=
-----END ISSUER-----
-$ openssl asn1parse -i < [ISSUER]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-
-
-
+VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDEyLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0zLCBtaW51dGVzPTEyLCBzZWNvbmR
zPTA=
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-
-
-
+VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDEzLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0xNCwgbWludXRlcz01OSwgc2Vjb25
kcz01OQ==
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-
-
-
+$ openssl asn1parse -i < [SUBJECT]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-----BEGIN SUBJECT-----
MAMEAYM=
-----END SUBJECT-----
-$ openssl asn1parse -i < [SUBJECT]
+$ openssl asn1parse -i < [SPKI]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-----BEGIN SPKI-----
MAMEAfM=
-----END SPKI-----
-$ openssl asn1parse -i < [SPKI]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-
-
-
-----BEGIN ISSUER UNIQUE ID-----
uQ==
-----END ISSUER UNIQUE ID-----
-
-
-----BEGIN SUBJECT UNIQUE ID-----
yg==
-----END SUBJECT UNIQUE ID-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v2_issuer_unique_id.pem b/chromium/net/data/parse_certificate_unittest/tbs_v2_issuer_unique_id.pem
index c608bb4cc1d..1ba13b17242 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v2_issuer_unique_id.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v2_issuer_unique_id.pem
@@ -1,12 +1,6 @@
This is a version 2 certificate containing the issuer unique ID field.
-
------BEGIN TBS CERTIFICATE-----
-MECgAwIBAQIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
-DMAMEAfOBAgC5
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 64 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -24,73 +18,55 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
57:d=1 hl=2 l= 3 cons: SEQUENCE
59:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
62:d=1 hl=2 l= 2 prim: cont [ 1 ]
-
-
+-----BEGIN TBS CERTIFICATE-----
+MECgAwIBAQIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
+DMAMEAfOBAgC5
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
AQ==
-----END SERIAL NUMBER-----
-
-
+$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-----BEGIN SIGNATURE ALGORITHM-----
MAMEAQE=
-----END SIGNATURE ALGORITHM-----
-$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-----BEGIN ISSUER-----
MAMEAQU=
-----END ISSUER-----
-$ openssl asn1parse -i < [ISSUER]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-
-
-
+VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDEyLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0zLCBtaW51dGVzPTEyLCBzZWNvbmR
zPTA=
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-
-
-
+VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDEzLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0xNCwgbWludXRlcz01OSwgc2Vjb25
kcz01OQ==
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-
-
-
+$ openssl asn1parse -i < [SUBJECT]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-----BEGIN SUBJECT-----
MAMEAYM=
-----END SUBJECT-----
-$ openssl asn1parse -i < [SUBJECT]
+$ openssl asn1parse -i < [SPKI]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-----BEGIN SPKI-----
MAMEAfM=
-----END SPKI-----
-$ openssl asn1parse -i < [SPKI]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-
-
-
-----BEGIN ISSUER UNIQUE ID-----
uQ==
-----END ISSUER UNIQUE ID-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v2_no_optionals.pem b/chromium/net/data/parse_certificate_unittest/tbs_v2_no_optionals.pem
index cdfe301de83..9ea675c016a 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v2_no_optionals.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v2_no_optionals.pem
@@ -1,12 +1,6 @@
This is a version 2 certificate with none of the optional fields.
-
------BEGIN TBS CERTIFICATE-----
-MDygAwIBAQIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
-DMAMEAfM=
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 60 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -23,67 +17,51 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
54:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
57:d=1 hl=2 l= 3 cons: SEQUENCE
59:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-
-
+-----BEGIN TBS CERTIFICATE-----
+MDygAwIBAQIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
+DMAMEAfM=
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
AQ==
-----END SERIAL NUMBER-----
-
-
+$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-----BEGIN SIGNATURE ALGORITHM-----
MAMEAQE=
-----END SIGNATURE ALGORITHM-----
-$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-----BEGIN ISSUER-----
MAMEAQU=
-----END ISSUER-----
-$ openssl asn1parse -i < [ISSUER]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-
-
-
+VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDEyLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0zLCBtaW51dGVzPTEyLCBzZWNvbmR
zPTA=
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-
-
-
+VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDEzLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0xNCwgbWludXRlcz01OSwgc2Vjb25
kcz01OQ==
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-
-
-
+$ openssl asn1parse -i < [SUBJECT]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-----BEGIN SUBJECT-----
MAMEAYM=
-----END SUBJECT-----
-$ openssl asn1parse -i < [SUBJECT]
+$ openssl asn1parse -i < [SPKI]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-----BEGIN SPKI-----
MAMEAfM=
-----END SPKI-----
-
-$ openssl asn1parse -i < [SPKI]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v3_all_optionals.pem b/chromium/net/data/parse_certificate_unittest/tbs_v3_all_optionals.pem
index 4212e1a29e8..5b989c84f39 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v3_all_optionals.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v3_all_optionals.pem
@@ -1,12 +1,6 @@
This is a version 3 TBSCertificate containing all the possible optional fields.
-
------BEGIN TBS CERTIFICATE-----
-MEugAwIBAgIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
-DMAMEAfOBAgC5ggIAyqMFMAMEAd0=
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 75 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -28,89 +22,66 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
70:d=1 hl=2 l= 5 cons: cont [ 3 ]
72:d=2 hl=2 l= 3 cons: SEQUENCE
74:d=3 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:DD
-
-
+-----BEGIN TBS CERTIFICATE-----
+MEugAwIBAgIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
+DMAMEAfOBAgC5ggIAyqMFMAMEAd0=
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
AQ==
-----END SERIAL NUMBER-----
-
-
+$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-----BEGIN SIGNATURE ALGORITHM-----
MAMEAQE=
-----END SIGNATURE ALGORITHM-----
-$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-----BEGIN ISSUER-----
MAMEAQU=
-----END ISSUER-----
-$ openssl asn1parse -i < [ISSUER]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-
-
-
+VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDEyLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0zLCBtaW51dGVzPTEyLCBzZWNvbmR
zPTA=
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-
-
-
+VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDEzLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0xNCwgbWludXRlcz01OSwgc2Vjb25
kcz01OQ==
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-
-
-
+$ openssl asn1parse -i < [SUBJECT]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-----BEGIN SUBJECT-----
MAMEAYM=
-----END SUBJECT-----
-$ openssl asn1parse -i < [SUBJECT]
+$ openssl asn1parse -i < [SPKI]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-----BEGIN SPKI-----
MAMEAfM=
-----END SPKI-----
-$ openssl asn1parse -i < [SPKI]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-
-
-
-----BEGIN ISSUER UNIQUE ID-----
uQ==
-----END ISSUER UNIQUE ID-----
-
-
-----BEGIN SUBJECT UNIQUE ID-----
yg==
-----END SUBJECT UNIQUE ID-----
-
-
------BEGIN EXTENSIONS-----
-MAMEAd0=
------END EXTENSIONS-----
-
$ openssl asn1parse -i < [EXTENSIONS]
0:d=0 hl=2 l= 3 cons: SEQUENCE
2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:DD
+-----BEGIN EXTENSIONS-----
+MAMEAd0=
+-----END EXTENSIONS-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v3_data_after_extensions.pem b/chromium/net/data/parse_certificate_unittest/tbs_v3_data_after_extensions.pem
index 6aaadb14781..7dc83279069 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v3_data_after_extensions.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v3_data_after_extensions.pem
@@ -2,12 +2,6 @@ This is an otherwise valid TBSCertificate, except there is a NULL after the
extensions.
-
------BEGIN TBS CERTIFICATE-----
-MEWgAwIBAgIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
-DMAMEAfOjBTADBAHdBQA=
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 69 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -28,3 +22,7 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
64:d=2 hl=2 l= 3 cons: SEQUENCE
66:d=3 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:DD
69:d=1 hl=2 l= 0 prim: NULL
+-----BEGIN TBS CERTIFICATE-----
+MEWgAwIBAgIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
+DMAMEAfOjBTADBAHdBQA=
+-----END TBS CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v3_extensions.pem b/chromium/net/data/parse_certificate_unittest/tbs_v3_extensions.pem
index c8a59aa2d5a..927a7831d27 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v3_extensions.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v3_extensions.pem
@@ -3,11 +3,6 @@ ParseTbsCertificate(), however its sub-fields are mainly bogus. This
TBSCertificate contains extensions.
------BEGIN TBS CERTIFICATE-----
-MEOgAwIBAgIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
-DMAMEAfOjBTADBAHd
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 67 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -27,77 +22,58 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
62:d=1 hl=2 l= 5 cons: cont [ 3 ]
64:d=2 hl=2 l= 3 cons: SEQUENCE
66:d=3 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:DD
-
-
+-----BEGIN TBS CERTIFICATE-----
+MEOgAwIBAgIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
+DMAMEAfOjBTADBAHd
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
AQ==
-----END SERIAL NUMBER-----
-
-
+$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-----BEGIN SIGNATURE ALGORITHM-----
MAMEAQE=
-----END SIGNATURE ALGORITHM-----
-$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-----BEGIN ISSUER-----
MAMEAQU=
-----END ISSUER-----
-$ openssl asn1parse -i < [ISSUER]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-
-
-
+VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDEyLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0zLCBtaW51dGVzPTEyLCBzZWNvbmR
zPTA=
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-
-
-
+VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDEzLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0xNCwgbWludXRlcz01OSwgc2Vjb25
kcz01OQ==
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-
-
-
+$ openssl asn1parse -i < [SUBJECT]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-----BEGIN SUBJECT-----
MAMEAYM=
-----END SUBJECT-----
-$ openssl asn1parse -i < [SUBJECT]
+$ openssl asn1parse -i < [SPKI]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-----BEGIN SPKI-----
MAMEAfM=
-----END SPKI-----
-$ openssl asn1parse -i < [SPKI]
+$ openssl asn1parse -i < [EXTENSIONS]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:DD
-----BEGIN EXTENSIONS-----
MAMEAd0=
-----END EXTENSIONS-----
-
-$ openssl asn1parse -i < [EXTENSIONS]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:DD
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v3_extensions_not_sequence.pem b/chromium/net/data/parse_certificate_unittest/tbs_v3_extensions_not_sequence.pem
index ef2ca979b55..7122fbd3e09 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v3_extensions_not_sequence.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v3_extensions_not_sequence.pem
@@ -2,12 +2,6 @@ This is an otherwise valid TBSCertificate, except the extensions is an OCTET
STRING rather than a SEQUENCE.
-
------BEGIN TBS CERTIFICATE-----
-MEOgAwIBAgIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
-DMAMEAfOjBQQDBAHd
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 67 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -26,3 +20,7 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
59:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
62:d=1 hl=2 l= 5 cons: cont [ 3 ]
64:d=2 hl=2 l= 3 prim: OCTET STRING [HEX DUMP]:0401DD
+-----BEGIN TBS CERTIFICATE-----
+MEOgAwIBAgIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
+DMAMEAfOjBQQDBAHd
+-----END TBS CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v3_no_optionals.pem b/chromium/net/data/parse_certificate_unittest/tbs_v3_no_optionals.pem
index 7b4c7cdc523..119ca262a56 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v3_no_optionals.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v3_no_optionals.pem
@@ -4,12 +4,6 @@ TBSCertificate contains no optional fields (no issuerUniqueID, subjectUniqueID,
extensions)
-
------BEGIN TBS CERTIFICATE-----
-MDygAwIBAgIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
-DMAMEAfM=
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 60 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -26,67 +20,51 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
54:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
57:d=1 hl=2 l= 3 cons: SEQUENCE
59:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-
-
+-----BEGIN TBS CERTIFICATE-----
+MDygAwIBAgIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
+DMAMEAfM=
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
AQ==
-----END SERIAL NUMBER-----
-
-
+$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-----BEGIN SIGNATURE ALGORITHM-----
MAMEAQE=
-----END SIGNATURE ALGORITHM-----
-$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-----BEGIN ISSUER-----
MAMEAQU=
-----END ISSUER-----
-$ openssl asn1parse -i < [ISSUER]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-
-
-
+VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDEyLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0zLCBtaW51dGVzPTEyLCBzZWNvbmR
zPTA=
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-
-
-
+VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDEzLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0xNCwgbWludXRlcz01OSwgc2Vjb25
kcz01OQ==
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-
-
-
+$ openssl asn1parse -i < [SUBJECT]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-----BEGIN SUBJECT-----
MAMEAYM=
-----END SUBJECT-----
-$ openssl asn1parse -i < [SUBJECT]
+$ openssl asn1parse -i < [SPKI]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-----BEGIN SPKI-----
MAMEAfM=
-----END SPKI-----
-
-$ openssl asn1parse -i < [SPKI]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v3_real.pem b/chromium/net/data/parse_certificate_unittest/tbs_v3_real.pem
index 337cccd0300..f4080d402bc 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v3_real.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v3_real.pem
@@ -1,30 +1,6 @@
This is a real-world certificate (in fact the same as cert_version3.pem)
-
------BEGIN TBS CERTIFICATE-----
-MIIEP6ADAgECAgcrY6QqcFB2MA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJVUzEQMA4GA1U
-ECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIE
-luYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9ye
-TEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MREwDwYD
-VQQFEwgwNzk2OTI4NzAeFw0xMjA0MTkxMzUzMjRaFw0xMzA0MTkxMzUzMjRaME8xFDASBgNVBAo
-TC2t0aHVsaHUubmV0MSEwHwYDVQQLExhEb21haW4gQ29udHJvbCBWYWxpZGF0ZWQxFDASBgNVBA
-MTC2t0aHVsaHUubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArzQkuEZv5xkNL
-J7RCgAYmH4vG87FFPFm5J+9ObenNAFqm8V5C4IzXm1+s7ro0sndLOyDH5INNAtKkuqp7kqubl1b
-bP3Z4+Ra3ENv7cpwQbQjoaajRKCGRULs/jFMCAASii/+3jkkufNimu7cBfDXOSQR2YQZL4zhDW7
-ss/zwTVspYnxvU7oDcqOIwCmFwQ/FvYTAxF1uozKBsJfL854v0MKI7GEyyn6W8jZ7f8cSc8ahvr
-LAYt/etAxrmHcMUVJbW+gxXiwJsHfj03S1/RypHTb4gRqEz3pX6wl8sqtJP0L5mXuQgESoEAZ4S
-rPYLxXytqrU1yLi32xgWwHu1A7fIQIDAQABo4IBujCCAbYwDwYDVR0TAQH/BAUwAwEBADAdBgNV
-HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQDAgWgMDMGA1UdHwQsMCowKKA
-moCSGImh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2RzMS02OC5jcmwwUwYDVR0gBEwwSjBIBgtghk
-gBhv1tAQcXATA5MDcGCCsGAQUFBwIBFitodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL
-3JlcG9zaXRvcnkvMIGABggrBgEFBQcBAQR0MHIwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmdv
-ZGFkZHkuY29tLzBKBggrBgEFBQcwAoY+aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9
-yZXBvc2l0b3J5L2dkX2ludGVybWVkaWF0ZS5jcnQwHwYDVR0jBBgwFoAU/axhMpNsRdbi7oVfmr
-rndplozOcwJwYDVR0RBCAwHoILa3RodWxodS5uZXSCD3d3dy5rdGh1bGh1Lm5ldDAdBgNVHQ4EF
-gQUox4asank9VC8PgXhdM8B0J414Bc=
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=4 l=1087 cons: SEQUENCE
4:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -114,32 +90,40 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
1060:d=3 hl=2 l= 29 cons: SEQUENCE
1062:d=4 hl=2 l= 3 prim: OBJECT :X509v3 Subject Key Identifier
1067:d=4 hl=2 l= 22 prim: OCTET STRING [HEX DUMP]:0414A31E1AB1A9E4F550BC3E05E174CF01D09E35E017
-
-
+-----BEGIN TBS CERTIFICATE-----
+MIIEP6ADAgECAgcrY6QqcFB2MA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJVUzEQMA4GA1U
+ECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIE
+luYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9ye
+TEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MREwDwYD
+VQQFEwgwNzk2OTI4NzAeFw0xMjA0MTkxMzUzMjRaFw0xMzA0MTkxMzUzMjRaME8xFDASBgNVBAo
+TC2t0aHVsaHUubmV0MSEwHwYDVQQLExhEb21haW4gQ29udHJvbCBWYWxpZGF0ZWQxFDASBgNVBA
+MTC2t0aHVsaHUubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArzQkuEZv5xkNL
+J7RCgAYmH4vG87FFPFm5J+9ObenNAFqm8V5C4IzXm1+s7ro0sndLOyDH5INNAtKkuqp7kqubl1b
+bP3Z4+Ra3ENv7cpwQbQjoaajRKCGRULs/jFMCAASii/+3jkkufNimu7cBfDXOSQR2YQZL4zhDW7
+ss/zwTVspYnxvU7oDcqOIwCmFwQ/FvYTAxF1uozKBsJfL854v0MKI7GEyyn6W8jZ7f8cSc8ahvr
+LAYt/etAxrmHcMUVJbW+gxXiwJsHfj03S1/RypHTb4gRqEz3pX6wl8sqtJP0L5mXuQgESoEAZ4S
+rPYLxXytqrU1yLi32xgWwHu1A7fIQIDAQABo4IBujCCAbYwDwYDVR0TAQH/BAUwAwEBADAdBgNV
+HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQDAgWgMDMGA1UdHwQsMCowKKA
+moCSGImh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2RzMS02OC5jcmwwUwYDVR0gBEwwSjBIBgtghk
+gBhv1tAQcXATA5MDcGCCsGAQUFBwIBFitodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL
+3JlcG9zaXRvcnkvMIGABggrBgEFBQcBAQR0MHIwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmdv
+ZGFkZHkuY29tLzBKBggrBgEFBQcwAoY+aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9
+yZXBvc2l0b3J5L2dkX2ludGVybWVkaWF0ZS5jcnQwHwYDVR0jBBgwFoAU/axhMpNsRdbi7oVfmr
+rndplozOcwJwYDVR0RBCAwHoILa3RodWxodS5uZXSCD3d3dy5rdGh1bGh1Lm5ldDAdBgNVHQ4EF
+gQUox4asank9VC8PgXhdM8B0J414Bc=
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
K2OkKnBQdg==
-----END SERIAL NUMBER-----
-
-
------BEGIN SIGNATURE ALGORITHM-----
-MA0GCSqGSIb3DQEBBQUA
------END SIGNATURE ALGORITHM-----
-
$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
-
------BEGIN ISSUER-----
-MIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTE
-aMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZX
-MuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZ
-mljYXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4Nw==
------END ISSUER-----
+-----BEGIN SIGNATURE ALGORITHM-----
+MA0GCSqGSIb3DQEBBQUA
+-----END SIGNATURE ALGORITHM-----
$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=3 l= 202 cons: SEQUENCE
@@ -171,32 +155,25 @@ $ openssl asn1parse -i < [ISSUER]
188:d=2 hl=2 l= 15 cons: SEQUENCE
190:d=3 hl=2 l= 3 prim: OBJECT :serialNumber
195:d=3 hl=2 l= 8 prim: PRINTABLESTRING :07969287
+-----BEGIN ISSUER-----
+MIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTE
+aMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZX
+MuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZ
+mljYXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4Nw==
+-----END ISSUER-----
-
-
+VALIDITY NOTBEFORE: year=2012, month=4, day=19, hours=13, minutes=53, seconds=24
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDEyLCBtb250aD00LCBkYXk9MTksIGhvdXJzPTEzLCBtaW51dGVzPTUzLCBzZWNvbmR
zPTI0
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2012, month=4, day=19, hours=13, minutes=53, seconds=24
-
-
-
+VALIDITY NOTAFTER: year=2013, month=4, day=19, hours=13, minutes=53, seconds=24
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDEzLCBtb250aD00LCBkYXk9MTksIGhvdXJzPTEzLCBtaW51dGVzPTUzLCBzZWNvbmR
zPTI0
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2013, month=4, day=19, hours=13, minutes=53, seconds=24
-
-
-
------BEGIN SUBJECT-----
-ME8xFDASBgNVBAoTC2t0aHVsaHUubmV0MSEwHwYDVQQLExhEb21haW4gQ29udHJvbCBWYWxpZGF
-0ZWQxFDASBgNVBAMTC2t0aHVsaHUubmV0
------END SUBJECT-----
-
$ openssl asn1parse -i < [SUBJECT]
0:d=0 hl=2 l= 79 cons: SEQUENCE
2:d=1 hl=2 l= 20 cons: SET
@@ -211,9 +188,17 @@ $ openssl asn1parse -i < [SUBJECT]
61:d=2 hl=2 l= 18 cons: SEQUENCE
63:d=3 hl=2 l= 3 prim: OBJECT :commonName
68:d=3 hl=2 l= 11 prim: PRINTABLESTRING :kthulhu.net
+-----BEGIN SUBJECT-----
+ME8xFDASBgNVBAoTC2t0aHVsaHUubmV0MSEwHwYDVQQLExhEb21haW4gQ29udHJvbCBWYWxpZGF
+0ZWQxFDASBgNVBAMTC2t0aHVsaHUubmV0
+-----END SUBJECT-----
-
-
+$ openssl asn1parse -i < [SPKI]
+ 0:d=0 hl=4 l= 290 cons: SEQUENCE
+ 4:d=1 hl=2 l= 13 cons: SEQUENCE
+ 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 17:d=2 hl=2 l= 0 prim: NULL
+ 19:d=1 hl=4 l= 271 prim: BIT STRING
-----BEGIN SPKI-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArzQkuEZv5xkNLJ7RCgAYmH4vG87FFPF
m5J+9ObenNAFqm8V5C4IzXm1+s7ro0sndLOyDH5INNAtKkuqp7kqubl1bbP3Z4+Ra3ENv7cpwQb
@@ -223,26 +208,6 @@ W+gxXiwJsHfj03S1/RypHTb4gRqEz3pX6wl8sqtJP0L5mXuQgESoEAZ4SrPYLxXytqrU1yLi32x
gWwHu1A7fIQIDAQAB
-----END SPKI-----
-$ openssl asn1parse -i < [SPKI]
- 0:d=0 hl=4 l= 290 cons: SEQUENCE
- 4:d=1 hl=2 l= 13 cons: SEQUENCE
- 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
- 17:d=2 hl=2 l= 0 prim: NULL
- 19:d=1 hl=4 l= 271 prim: BIT STRING
-
-
-
------BEGIN EXTENSIONS-----
-MIIBtjAPBgNVHRMBAf8EBTADAQEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgN
-VHQ8BAf8EBAMCBaAwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5LmNvbS9nZH
-MxLTY4LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcBMDkwNwYIKwYBBQUHAgEWK2h0dHA6L
-y9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS8wgYAGCCsGAQUFBwEBBHQwcjAk
-BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRkeS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8
-vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydD
-AfBgNVHSMEGDAWgBT9rGEyk2xF1uLuhV+auud2mWjM5zAnBgNVHREEIDAeggtrdGh1bGh1Lm5ld
-IIPd3d3Lmt0aHVsaHUubmV0MB0GA1UdDgQWBBSjHhqxqeT1ULw+BeF0zwHQnjXgFw==
------END EXTENSIONS-----
-
$ openssl asn1parse -i < [EXTENSIONS]
0:d=0 hl=4 l= 438 cons: SEQUENCE
4:d=1 hl=2 l= 15 cons: SEQUENCE
@@ -274,3 +239,13 @@ $ openssl asn1parse -i < [EXTENSIONS]
411:d=1 hl=2 l= 29 cons: SEQUENCE
413:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Subject Key Identifier
418:d=2 hl=2 l= 22 prim: OCTET STRING [HEX DUMP]:0414A31E1AB1A9E4F550BC3E05E174CF01D09E35E017
+-----BEGIN EXTENSIONS-----
+MIIBtjAPBgNVHRMBAf8EBTADAQEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgN
+VHQ8BAf8EBAMCBaAwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5LmNvbS9nZH
+MxLTY4LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcBMDkwNwYIKwYBBQUHAgEWK2h0dHA6L
+y9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS8wgYAGCCsGAQUFBwEBBHQwcjAk
+BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRkeS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8
+vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydD
+AfBgNVHSMEGDAWgBT9rGEyk2xF1uLuhV+auud2mWjM5zAnBgNVHREEIDAeggtrdGh1bGh1Lm5ld
+IIPd3d3Lmt0aHVsaHUubmV0MB0GA1UdDgQWBBSjHhqxqeT1ULw+BeF0zwHQnjXgFw==
+-----END EXTENSIONS-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_v4.pem b/chromium/net/data/parse_certificate_unittest/tbs_v4.pem
index 3b538667c55..7c94e7d9215 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_v4.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_v4.pem
@@ -2,12 +2,6 @@ This is a very basic TBSCertificate which would be valid except the version
number is v4 (3).
-
------BEGIN TBS CERTIFICATE-----
-MDygAwIBAwIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
-DMAMEAfM=
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 60 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -24,3 +18,7 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
54:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
57:d=1 hl=2 l= 3 cons: SEQUENCE
59:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
+-----BEGIN TBS CERTIFICATE-----
+MDygAwIBAwIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
+DMAMEAfM=
+-----END TBS CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_validity_both_generalized_time.pem b/chromium/net/data/parse_certificate_unittest/tbs_validity_both_generalized_time.pem
index 2b15076243a..2b7022a2f9e 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_validity_both_generalized_time.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_validity_both_generalized_time.pem
@@ -3,12 +3,6 @@ SEQUENCE (2 elem)
GeneralizedTime 2016-02-29 00:00:00 UTC
-
------BEGIN TBS CERTIFICATE-----
-MECgAwIBAgIBATADBAEBMAMEAQUwIhgPMjAxNDAxMzEwMDAwMDBaGA8yMDE2MDIyOTAwMDAwMFo
-wAwQBgzADBAHz
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 64 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -25,67 +19,51 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
58:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
61:d=1 hl=2 l= 3 cons: SEQUENCE
63:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-
-
+-----BEGIN TBS CERTIFICATE-----
+MECgAwIBAgIBATADBAEBMAMEAQUwIhgPMjAxNDAxMzEwMDAwMDBaGA8yMDE2MDIyOTAwMDAwMFo
+wAwQBgzADBAHz
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
AQ==
-----END SERIAL NUMBER-----
-
-
+$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-----BEGIN SIGNATURE ALGORITHM-----
MAMEAQE=
-----END SIGNATURE ALGORITHM-----
-$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-----BEGIN ISSUER-----
MAMEAQU=
-----END ISSUER-----
-$ openssl asn1parse -i < [ISSUER]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-
-
-
+VALIDITY NOTBEFORE: year=2014, month=1, day=31, hours=0, minutes=0, seconds=0
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDE0LCBtb250aD0xLCBkYXk9MzEsIGhvdXJzPTAsIG1pbnV0ZXM9MCwgc2Vjb25kcz0
w
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2014, month=1, day=31, hours=0, minutes=0, seconds=0
-
-
-
+VALIDITY NOTAFTER: year=2016, month=2, day=29, hours=0, minutes=0, seconds=0
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDE2LCBtb250aD0yLCBkYXk9MjksIGhvdXJzPTAsIG1pbnV0ZXM9MCwgc2Vjb25kcz0
w
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2016, month=2, day=29, hours=0, minutes=0, seconds=0
-
-
-
+$ openssl asn1parse -i < [SUBJECT]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-----BEGIN SUBJECT-----
MAMEAYM=
-----END SUBJECT-----
-$ openssl asn1parse -i < [SUBJECT]
+$ openssl asn1parse -i < [SPKI]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-----BEGIN SPKI-----
MAMEAfM=
-----END SPKI-----
-
-$ openssl asn1parse -i < [SPKI]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_validity_both_utc_time.pem b/chromium/net/data/parse_certificate_unittest/tbs_validity_both_utc_time.pem
index 67f82aa0a23..71bddb30b63 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_validity_both_utc_time.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_validity_both_utc_time.pem
@@ -3,12 +3,6 @@ SEQUENCE (2 elem)
UTCTime 2013-10-18 14:59:59 UTC
-
------BEGIN TBS CERTIFICATE-----
-MDygAwIBAgIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
-DMAMEAfM=
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 60 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -25,67 +19,51 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
54:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
57:d=1 hl=2 l= 3 cons: SEQUENCE
59:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-
-
+-----BEGIN TBS CERTIFICATE-----
+MDygAwIBAgIBATADBAEBMAMEAQUwHhcNMTIxMDE4MDMxMjAwWhcNMTMxMDE4MTQ1OTU5WjADBAG
+DMAMEAfM=
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
AQ==
-----END SERIAL NUMBER-----
-
-
+$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-----BEGIN SIGNATURE ALGORITHM-----
MAMEAQE=
-----END SIGNATURE ALGORITHM-----
-$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-----BEGIN ISSUER-----
MAMEAQU=
-----END ISSUER-----
-$ openssl asn1parse -i < [ISSUER]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-
-
-
+VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDEyLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0zLCBtaW51dGVzPTEyLCBzZWNvbmR
zPTA=
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-
-
-
+VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDEzLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0xNCwgbWludXRlcz01OSwgc2Vjb25
kcz01OQ==
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-
-
-
+$ openssl asn1parse -i < [SUBJECT]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-----BEGIN SUBJECT-----
MAMEAYM=
-----END SUBJECT-----
-$ openssl asn1parse -i < [SUBJECT]
+$ openssl asn1parse -i < [SPKI]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-----BEGIN SPKI-----
MAMEAfM=
-----END SPKI-----
-
-$ openssl asn1parse -i < [SPKI]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_validity_generalized_time_and_utc_time.pem b/chromium/net/data/parse_certificate_unittest/tbs_validity_generalized_time_and_utc_time.pem
index 874bb99b341..25fc37bd312 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_validity_generalized_time_and_utc_time.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_validity_generalized_time_and_utc_time.pem
@@ -3,12 +3,6 @@ SEQUENCE (2 elem)
UTCTime 2013-10-18 14:59:59 UTC
-
------BEGIN TBS CERTIFICATE-----
-MD6gAwIBAgIBATADBAEBMAMEAQUwIBgPMjAxNDAxMzEwMDAwMDBaFw0xMzEwMTgxNDU5NTlaMAM
-EAYMwAwQB8w==
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 62 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -25,67 +19,51 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
56:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
59:d=1 hl=2 l= 3 cons: SEQUENCE
61:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-
-
+-----BEGIN TBS CERTIFICATE-----
+MD6gAwIBAgIBATADBAEBMAMEAQUwIBgPMjAxNDAxMzEwMDAwMDBaFw0xMzEwMTgxNDU5NTlaMAM
+EAYMwAwQB8w==
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
AQ==
-----END SERIAL NUMBER-----
-
-
+$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-----BEGIN SIGNATURE ALGORITHM-----
MAMEAQE=
-----END SIGNATURE ALGORITHM-----
-$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-----BEGIN ISSUER-----
MAMEAQU=
-----END ISSUER-----
-$ openssl asn1parse -i < [ISSUER]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-
-
-
+VALIDITY NOTBEFORE: year=2014, month=1, day=31, hours=0, minutes=0, seconds=0
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDE0LCBtb250aD0xLCBkYXk9MzEsIGhvdXJzPTAsIG1pbnV0ZXM9MCwgc2Vjb25kcz0
w
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2014, month=1, day=31, hours=0, minutes=0, seconds=0
-
-
-
+VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDEzLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0xNCwgbWludXRlcz01OSwgc2Vjb25
kcz01OQ==
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2013, month=10, day=18, hours=14, minutes=59, seconds=59
-
-
-
+$ openssl asn1parse -i < [SUBJECT]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-----BEGIN SUBJECT-----
MAMEAYM=
-----END SUBJECT-----
-$ openssl asn1parse -i < [SUBJECT]
+$ openssl asn1parse -i < [SPKI]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-----BEGIN SPKI-----
MAMEAfM=
-----END SPKI-----
-
-$ openssl asn1parse -i < [SPKI]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_validity_relaxed.pem b/chromium/net/data/parse_certificate_unittest/tbs_validity_relaxed.pem
index 6143de9c723..c3f2ba627fe 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_validity_relaxed.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_validity_relaxed.pem
@@ -1,33 +1,6 @@
This certificate comes from the CT database. The encoding of validity fails to be parsed using the strict rules.
-
------BEGIN TBS CERTIFICATE-----
-MIIE/KADAgECAgMoIdUwDQYJKoZIhvcNAQEFBQAwgdwxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwd
-Bcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG
-9naWVzLCBJbmMuMTkwNwYDVQQLEzBodHRwOi8vY2VydGlmaWNhdGVzLnN0YXJmaWVsZHRlY2guY
-29tL3JlcG9zaXRvcnkxMTAvBgNVBAMTKFN0YXJmaWVsZCBTZWN1cmUgQ2VydGlmaWNhdGlvbiBB
-dXRob3JpdHkxETAPBgNVBAUTCDEwNjg4NDM1MBwXCzE0MDEwNzAwMDBaFw0xNjA0MDEwNzAwMDB
-aMIHrMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRgwFgYLKwYBBAGCNzwCAQITB0FyaXpvbmExHTAbBg
-NVBA8TFFByaXZhdGUgT3JnYW5pemF0aW9uMRQwEgYDVQQFEwtSLTE3MjQ3NDEtNjELMAkGA1UEB
-hMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJDAiBgNVBAoTG1N0
-YXJmaWVsZCBUZWNobm9sb2dpZXMsIExMQzErMCkGA1UEAxMidmFsaWQuc2ZpLmNhdGVzdC5zdGF
-yZmllbGR0ZWNoLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3UsdA7Nr22Qr
-HAYv7/IqL8V7kczSyO9wziJzVdWu+l7Brg//TgjMZKMgY7cJdpICvFAxLOxO3Z1w721InVmTxz0
-1lczx5WrH3aJMwR/05By5tanNaas9zdMAWFtWd8SYKm2xcSC3FsAhue2s14OT+EE92XgNgVhF2b
-dlOTgkwh/+q4Nl7k62LncnRSzFZdJKiorI811vrvVD45NB9IOPuRUXj5GLcUh4BXXp3ZSekFbVu
-A2oDnIhNGyQcThtf3wcM0dRMeKgemAD59d96NaQYH/QVA3gdtlzKxgeF/UvlxYG3P3DknTRiaMz
-l/Na9NzdRQX2i7ubskThqoRs05Zv0CAwEAAaOCAc4wggHKMAwGA1UdEwEB/wQCMAAwDgYDVR0PA
-QH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAtBgNVHREEJjAkgiJ2YWxp
-ZC5zZmkuY2F0ZXN0LnN0YXJmaWVsZHRlY2guY29tMB0GA1UdDgQWBBRw75ASplwemE9b2zPDD23
-L7UAaZDAfBgNVHSMEGDAWgBRJS1In0Ru88qEhamJ7UUJ6itfVVjA4BgNVHR8EMTAvMC2gK6Aphi
-dodHRwOi8vY3JsLnN0YXJmaWVsZHRlY2guY29tL3NmczMtMC5jcmwwgY0GCCsGAQUFBwEBBIGAM
-H4wKgYIKwYBBQUHMAGGHmh0dHA6Ly9vY3NwLnN0YXJmaWVsZHRlY2guY29tLzBQBggrBgEFBQcw
-AoZEaHR0cDovL2NlcnRpZmljYXRlcy5zdGFyZmllbGR0ZWNoLmNvbS9yZXBvc2l0b3J5L3NmX2l
-udGVybWVkaWF0ZS5jcnQwUgYDVR0gBEswSTBHBgtghkgBhv1uAQcXAzA4MDYGCCsGAQUFBwIBFi
-podHRwOi8vY2VydHMuc3RhcmZpZWxkdGVjaC5jb20vcmVwb3NpdG9yeS8=
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=4 l=1276 cons: SEQUENCE
4:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -141,3 +114,28 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
1196:d=3 hl=2 l= 82 cons: SEQUENCE
1198:d=4 hl=2 l= 3 prim: OBJECT :X509v3 Certificate Policies
1203:d=4 hl=2 l= 75 prim: OCTET STRING [HEX DUMP]:30493047060B6086480186FD6E010717033038303606082B06010505070201162A687474703A2F2F63657274732E737461726669656C64746563682E636F6D2F7265706F7369746F72792F
+-----BEGIN TBS CERTIFICATE-----
+MIIE/KADAgECAgMoIdUwDQYJKoZIhvcNAQEFBQAwgdwxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwd
+Bcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG
+9naWVzLCBJbmMuMTkwNwYDVQQLEzBodHRwOi8vY2VydGlmaWNhdGVzLnN0YXJmaWVsZHRlY2guY
+29tL3JlcG9zaXRvcnkxMTAvBgNVBAMTKFN0YXJmaWVsZCBTZWN1cmUgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkxETAPBgNVBAUTCDEwNjg4NDM1MBwXCzE0MDEwNzAwMDBaFw0xNjA0MDEwNzAwMDB
+aMIHrMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRgwFgYLKwYBBAGCNzwCAQITB0FyaXpvbmExHTAbBg
+NVBA8TFFByaXZhdGUgT3JnYW5pemF0aW9uMRQwEgYDVQQFEwtSLTE3MjQ3NDEtNjELMAkGA1UEB
+hMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJDAiBgNVBAoTG1N0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIExMQzErMCkGA1UEAxMidmFsaWQuc2ZpLmNhdGVzdC5zdGF
+yZmllbGR0ZWNoLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3UsdA7Nr22Qr
+HAYv7/IqL8V7kczSyO9wziJzVdWu+l7Brg//TgjMZKMgY7cJdpICvFAxLOxO3Z1w721InVmTxz0
+1lczx5WrH3aJMwR/05By5tanNaas9zdMAWFtWd8SYKm2xcSC3FsAhue2s14OT+EE92XgNgVhF2b
+dlOTgkwh/+q4Nl7k62LncnRSzFZdJKiorI811vrvVD45NB9IOPuRUXj5GLcUh4BXXp3ZSekFbVu
+A2oDnIhNGyQcThtf3wcM0dRMeKgemAD59d96NaQYH/QVA3gdtlzKxgeF/UvlxYG3P3DknTRiaMz
+l/Na9NzdRQX2i7ubskThqoRs05Zv0CAwEAAaOCAc4wggHKMAwGA1UdEwEB/wQCMAAwDgYDVR0PA
+QH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAtBgNVHREEJjAkgiJ2YWxp
+ZC5zZmkuY2F0ZXN0LnN0YXJmaWVsZHRlY2guY29tMB0GA1UdDgQWBBRw75ASplwemE9b2zPDD23
+L7UAaZDAfBgNVHSMEGDAWgBRJS1In0Ru88qEhamJ7UUJ6itfVVjA4BgNVHR8EMTAvMC2gK6Aphi
+dodHRwOi8vY3JsLnN0YXJmaWVsZHRlY2guY29tL3NmczMtMC5jcmwwgY0GCCsGAQUFBwEBBIGAM
+H4wKgYIKwYBBQUHMAGGHmh0dHA6Ly9vY3NwLnN0YXJmaWVsZHRlY2guY29tLzBQBggrBgEFBQcw
+AoZEaHR0cDovL2NlcnRpZmljYXRlcy5zdGFyZmllbGR0ZWNoLmNvbS9yZXBvc2l0b3J5L3NmX2l
+udGVybWVkaWF0ZS5jcnQwUgYDVR0gBEswSTBHBgtghkgBhv1uAQcXAzA4MDYGCCsGAQUFBwIBFi
+podHRwOi8vY2VydHMuc3RhcmZpZWxkdGVjaC5jb20vcmVwb3NpdG9yeS8=
+-----END TBS CERTIFICATE-----
diff --git a/chromium/net/data/parse_certificate_unittest/tbs_validity_utc_time_and_generalized_time.pem b/chromium/net/data/parse_certificate_unittest/tbs_validity_utc_time_and_generalized_time.pem
index 5a171a237be..2f98b8786fa 100644
--- a/chromium/net/data/parse_certificate_unittest/tbs_validity_utc_time_and_generalized_time.pem
+++ b/chromium/net/data/parse_certificate_unittest/tbs_validity_utc_time_and_generalized_time.pem
@@ -3,12 +3,6 @@ SEQUENCE (2 elem)
GeneralizedTime 2016-02-29 00:00:00 UTC
-
------BEGIN TBS CERTIFICATE-----
-MD6gAwIBAgIBATADBAEBMAMEAQUwIBcNMTIxMDE4MDMxMjAwWhgPMjAxNjAyMjkwMDAwMDBaMAM
-EAYMwAwQB8w==
------END TBS CERTIFICATE-----
-
$ openssl asn1parse -i < [TBS CERTIFICATE]
0:d=0 hl=2 l= 62 cons: SEQUENCE
2:d=1 hl=2 l= 3 cons: cont [ 0 ]
@@ -25,67 +19,51 @@ $ openssl asn1parse -i < [TBS CERTIFICATE]
56:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
59:d=1 hl=2 l= 3 cons: SEQUENCE
61:d=2 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-
-
+-----BEGIN TBS CERTIFICATE-----
+MD6gAwIBAgIBATADBAEBMAMEAQUwIBcNMTIxMDE4MDMxMjAwWhgPMjAxNjAyMjkwMDAwMDBaMAM
+EAYMwAwQB8w==
+-----END TBS CERTIFICATE-----
-----BEGIN SERIAL NUMBER-----
AQ==
-----END SERIAL NUMBER-----
-
-
+$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-----BEGIN SIGNATURE ALGORITHM-----
MAMEAQE=
-----END SIGNATURE ALGORITHM-----
-$ openssl asn1parse -i < [SIGNATURE ALGORITHM]
+$ openssl asn1parse -i < [ISSUER]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-----BEGIN ISSUER-----
MAMEAQU=
-----END ISSUER-----
-$ openssl asn1parse -i < [ISSUER]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:05
-
-
-
+VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-----BEGIN VALIDITY NOTBEFORE-----
eWVhcj0yMDEyLCBtb250aD0xMCwgZGF5PTE4LCBob3Vycz0zLCBtaW51dGVzPTEyLCBzZWNvbmR
zPTA=
-----END VALIDITY NOTBEFORE-----
-VALIDITY NOTBEFORE: year=2012, month=10, day=18, hours=3, minutes=12, seconds=0
-
-
-
+VALIDITY NOTAFTER: year=2016, month=2, day=29, hours=0, minutes=0, seconds=0
-----BEGIN VALIDITY NOTAFTER-----
eWVhcj0yMDE2LCBtb250aD0yLCBkYXk9MjksIGhvdXJzPTAsIG1pbnV0ZXM9MCwgc2Vjb25kcz0
w
-----END VALIDITY NOTAFTER-----
-VALIDITY NOTAFTER: year=2016, month=2, day=29, hours=0, minutes=0, seconds=0
-
-
-
+$ openssl asn1parse -i < [SUBJECT]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-----BEGIN SUBJECT-----
MAMEAYM=
-----END SUBJECT-----
-$ openssl asn1parse -i < [SUBJECT]
+$ openssl asn1parse -i < [SPKI]
0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:83
-
-
-
+ 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
-----BEGIN SPKI-----
MAMEAfM=
-----END SPKI-----
-
-$ openssl asn1parse -i < [SPKI]
- 0:d=0 hl=2 l= 3 cons: SEQUENCE
- 2:d=1 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:F3
diff --git a/chromium/net/data/parse_ocsp_unittest/annotate_test_data.py b/chromium/net/data/parse_ocsp_unittest/annotate_test_data.py
new file mode 100755
index 00000000000..256a0a2f722
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/annotate_test_data.py
@@ -0,0 +1,173 @@
+#!/usr/bin/python
+# 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.
+# TODO(svaldez): Deduplicate various annotate_test_data.
+
+"""This script is called without any arguments to re-format all of the *.pem
+files in the script's parent directory.
+
+The main formatting change is to run "openssl asn1parse" for each of the PEM
+block sections, and add that output to the comment. It also runs the command
+on the OCTET STRING representing BasicOCSPResponse.
+
+"""
+
+import glob
+import os
+import re
+import base64
+import subprocess
+
+
+def Transform(file_data):
+ """Returns a transformed (formatted) version of file_data"""
+
+ result = ''
+
+ for block in GetPemBlocks(file_data):
+ if len(result) != 0:
+ result += '\n'
+
+ # If there was a user comment (non-script-generated comment) associated
+ # with the block, output it immediately before the block.
+ user_comment = GetUserComment(block.comment)
+ if user_comment:
+ result += user_comment + '\n'
+
+ generated_comment = GenerateCommentForBlock(block.name, block.data)
+ result += generated_comment + '\n'
+
+
+ result += MakePemBlockString(block.name, block.data)
+
+ return result
+
+
+def GenerateCommentForBlock(block_name, block_data):
+ """Returns a string describing the ASN.1 structure of block_data"""
+
+ p = subprocess.Popen(['openssl', 'asn1parse', '-i', '-inform', 'DER'],
+ stdout=subprocess.PIPE, stdin=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout_data, stderr_data = p.communicate(input=block_data)
+ generated_comment = '$ openssl asn1parse -i < [%s]\n%s' % (block_name,
+ stdout_data)
+
+ # The OCTET STRING encoded BasicOCSPResponse is also parsed out using
+ #'openssl asn1parse'.
+ if block_name == 'OCSP RESPONSE':
+ if '[HEX DUMP]:' in generated_comment:
+ (generated_comment, response) = generated_comment.split('[HEX DUMP]:', 1)
+ response = response.replace('\n', '')
+ if len(response) % 2 != 0:
+ response = '0' + response
+ response = GenerateCommentForBlock('INNER', response.decode('hex'))
+ response = response.split('\n', 1)[1]
+ response = response.replace(': ', ': ')
+ generated_comment += '\n%s' % (response)
+ return generated_comment.strip('\n')
+
+
+
+def GetUserComment(comment):
+ """Removes any script-generated lines (everything after the $ openssl line)"""
+
+ # Consider everything after "$ openssl" to be a generated comment.
+ comment = comment.split('$ openssl asn1parse -i', 1)[0]
+ if IsEntirelyWhiteSpace(comment):
+ comment = ''
+ return comment
+
+
+def MakePemBlockString(name, data):
+ return ('-----BEGIN %s-----\n'
+ '%s'
+ '-----END %s-----\n') % (name, EncodeDataForPem(data), name)
+
+
+def GetPemFilePaths():
+ """Returns an iterable for all the paths to the PEM test files"""
+
+ base_dir = os.path.dirname(os.path.realpath(__file__))
+ return glob.iglob(os.path.join(base_dir, '*.pem'))
+
+
+def ReadFileToString(path):
+ with open(path, 'r') as f:
+ return f.read()
+
+
+def WrapTextToLineWidth(text, column_width):
+ result = ''
+ pos = 0
+ while pos < len(text):
+ result += text[pos : pos + column_width] + '\n'
+ pos += column_width
+ return result
+
+
+def EncodeDataForPem(data):
+ result = base64.b64encode(data)
+ return WrapTextToLineWidth(result, 75)
+
+
+class PemBlock(object):
+ def __init__(self):
+ self.name = None
+ self.data = None
+ self.comment = None
+
+
+def StripAllWhitespace(text):
+ pattern = re.compile(r'\s+')
+ return re.sub(pattern, '', text)
+
+
+def IsEntirelyWhiteSpace(text):
+ return len(StripAllWhitespace(text)) == 0
+
+
+def DecodePemBlockData(text):
+ text = StripAllWhitespace(text)
+ return base64.b64decode(text)
+
+
+def GetPemBlocks(data):
+ """Returns an iterable of PemBlock"""
+
+ comment_start = 0
+
+ regex = re.compile(r'-----BEGIN ([\w ]+)-----(.*?)-----END \1-----',
+ re.DOTALL)
+
+ for match in regex.finditer(data):
+ block = PemBlock()
+
+ block.name = match.group(1)
+ block.data = DecodePemBlockData(match.group(2))
+
+ # Keep track of any non-PEM text above blocks
+ block.comment = data[comment_start : match.start()].strip()
+ comment_start = match.end()
+
+ yield block
+
+
+def WriteStringToFile(data, path):
+ with open(path, "w") as f:
+ f.write(data)
+
+
+def main():
+ for path in GetPemFilePaths():
+ print "Processing %s ..." % (path)
+ original_data = ReadFileToString(path)
+ transformed_data = Transform(original_data)
+ if original_data != transformed_data:
+ WriteStringToFile(transformed_data, path)
+ print "Rewrote %s" % (path)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/chromium/net/data/parse_ocsp_unittest/bad_ocsp_type.pem b/chromium/net/data/parse_ocsp_unittest/bad_ocsp_type.pem
new file mode 100644
index 00000000000..3441d9e032a
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/bad_ocsp_type.pem
@@ -0,0 +1,123 @@
+Has an invalid OCSP OID
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 299 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 292 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 288 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :OCSP Nonce
+ 26:d=3 hl=4 l= 273 prim: OCTET STRING
+ 0:d=0 hl=4 l= 269 cons: SEQUENCE
+ 4:d=1 hl=2 l= 120 cons: SEQUENCE
+ 6:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 8:d=3 hl=2 l= 18 cons: SEQUENCE
+ 10:d=4 hl=2 l= 16 cons: SET
+ 12:d=5 hl=2 l= 14 cons: SEQUENCE
+ 14:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 19:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 28:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 45:d=2 hl=2 l= 79 cons: SEQUENCE
+ 47:d=3 hl=2 l= 77 cons: SEQUENCE
+ 49:d=4 hl=2 l= 56 cons: SEQUENCE
+ 51:d=5 hl=2 l= 7 cons: SEQUENCE
+ 53:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 60:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 82:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 104:d=5 hl=2 l= 1 prim: INTEGER :03
+ 107:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 109:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 126:d=1 hl=2 l= 13 cons: SEQUENCE
+ 128:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 139:d=2 hl=2 l= 0 prim: NULL
+ 141:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBKwoBAKCCASQwggEgBgkrBgEFBQcwAQIEggERMIIBDTB4oRQwEjEQMA4GA1UEAxMHVGVzdCB
+DQRgPMjAxNjAzMDQxNjQwMDJaME8wTTA4MAcGBSsOAwIaBBQC/3XaJN6K3RUPq2idzObmY20JAQ
+QUdzWstN/nudyCWTgbfu3wiCuXNTQCAQOAABgPMjAxNjAzMDQxNjQwMDJaMA0GCSqGSIb3DQEBB
+QUAA4GBAEaH8xtlTUtrtKBa/dKPjWhP5dl+FQMVmCpKVGYVkh+mq/mltWcFgqmVr2uMuCngTIXg
+xXd9xzvdjl3Y8PqbFXd2267ZQ5JWLkyU1FFxOYRQsjNZD45AnPmXUeHTJ+KqvmIoduFMc2O42RK
+/bUfjrcMZcpbblnbPReAfYUsUaiCE
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/bad_signature.pem b/chromium/net/data/parse_ocsp_unittest/bad_signature.pem
new file mode 100644
index 00000000000..f128604148f
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/bad_signature.pem
@@ -0,0 +1,121 @@
+Has an invalid signature
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=3 l= 170 cons: SEQUENCE
+ 3:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 6:d=1 hl=3 l= 164 cons: cont [ 0 ]
+ 9:d=2 hl=3 l= 161 cons: SEQUENCE
+ 12:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 23:d=3 hl=3 l= 147 prim: OCTET STRING
+ 0:d=0 hl=3 l= 144 cons: SEQUENCE
+ 3:d=1 hl=2 l= 120 cons: SEQUENCE
+ 5:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 7:d=3 hl=2 l= 18 cons: SEQUENCE
+ 9:d=4 hl=2 l= 16 cons: SET
+ 11:d=5 hl=2 l= 14 cons: SEQUENCE
+ 13:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 18:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 27:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 44:d=2 hl=2 l= 79 cons: SEQUENCE
+ 46:d=3 hl=2 l= 77 cons: SEQUENCE
+ 48:d=4 hl=2 l= 56 cons: SEQUENCE
+ 50:d=5 hl=2 l= 7 cons: SEQUENCE
+ 52:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 59:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 81:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 103:d=5 hl=2 l= 1 prim: INTEGER :03
+ 106:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 108:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 125:d=1 hl=2 l= 13 cons: SEQUENCE
+ 127:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 138:d=2 hl=2 l= 0 prim: NULL
+ 140:d=1 hl=2 l= 5 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIGqCgEAoIGkMIGhBgkrBgEFBQcwAQEEgZMwgZAweKEUMBIxEDAOBgNVBAMTB1Rlc3QgQ0EYDzI
+wMTYwMzA0MTY0MDAyWjBPME0wODAHBgUrDgMCGgQUAv912iTeit0VD6tonczm5mNtCQEEFHc1rL
+Tf57ncglk4G37t8IgrlzU0AgEDgAAYDzIwMTYwMzA0MTY0MDAyWjANBgkqhkiG9w0BAQUFAAMFA
+N6tvu8=
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/bad_status.pem b/chromium/net/data/parse_ocsp_unittest/bad_status.pem
new file mode 100644
index 00000000000..db7c66cce72
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/bad_status.pem
@@ -0,0 +1,91 @@
+Has an invalid status larger than the defined Status enumeration
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: ENUMERATED :11
+-----BEGIN OCSP RESPONSE-----
+MAMKARE=
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/good_response.pem b/chromium/net/data/parse_ocsp_unittest/good_response.pem
new file mode 100644
index 00000000000..f103d9a9a95
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/good_response.pem
@@ -0,0 +1,123 @@
+Is a valid response for the cert
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 299 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 292 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 288 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 273 prim: OCTET STRING
+ 0:d=0 hl=4 l= 269 cons: SEQUENCE
+ 4:d=1 hl=2 l= 120 cons: SEQUENCE
+ 6:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 8:d=3 hl=2 l= 18 cons: SEQUENCE
+ 10:d=4 hl=2 l= 16 cons: SET
+ 12:d=5 hl=2 l= 14 cons: SEQUENCE
+ 14:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 19:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 28:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 45:d=2 hl=2 l= 79 cons: SEQUENCE
+ 47:d=3 hl=2 l= 77 cons: SEQUENCE
+ 49:d=4 hl=2 l= 56 cons: SEQUENCE
+ 51:d=5 hl=2 l= 7 cons: SEQUENCE
+ 53:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 60:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 82:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 104:d=5 hl=2 l= 1 prim: INTEGER :03
+ 107:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 109:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 126:d=1 hl=2 l= 13 cons: SEQUENCE
+ 128:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 139:d=2 hl=2 l= 0 prim: NULL
+ 141:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBKwoBAKCCASQwggEgBgkrBgEFBQcwAQEEggERMIIBDTB4oRQwEjEQMA4GA1UEAxMHVGVzdCB
+DQRgPMjAxNjAzMDQxNjQwMDJaME8wTTA4MAcGBSsOAwIaBBQC/3XaJN6K3RUPq2idzObmY20JAQ
+QUdzWstN/nudyCWTgbfu3wiCuXNTQCAQOAABgPMjAxNjAzMDQxNjQwMDJaMA0GCSqGSIb3DQEBB
+QUAA4GBAEaH8xtlTUtrtKBa/dKPjWhP5dl+FQMVmCpKVGYVkh+mq/mltWcFgqmVr2uMuCngTIXg
+xXd9xzvdjl3Y8PqbFXd2267ZQ5JWLkyU1FFxOYRQsjNZD45AnPmXUeHTJ+KqvmIoduFMc2O42RK
+/bUfjrcMZcpbblnbPReAfYUsUaiCE
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/good_response_next_update.pem b/chromium/net/data/parse_ocsp_unittest/good_response_next_update.pem
new file mode 100644
index 00000000000..7169d7dbd2f
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/good_response_next_update.pem
@@ -0,0 +1,125 @@
+Is a valid response for the cert until nextUpdate
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 319 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 312 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 308 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 293 prim: OCTET STRING
+ 0:d=0 hl=4 l= 289 cons: SEQUENCE
+ 4:d=1 hl=3 l= 139 cons: SEQUENCE
+ 7:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 9:d=3 hl=2 l= 18 cons: SEQUENCE
+ 11:d=4 hl=2 l= 16 cons: SET
+ 13:d=5 hl=2 l= 14 cons: SEQUENCE
+ 15:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 20:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 29:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 46:d=2 hl=2 l= 98 cons: SEQUENCE
+ 48:d=3 hl=2 l= 96 cons: SEQUENCE
+ 50:d=4 hl=2 l= 56 cons: SEQUENCE
+ 52:d=5 hl=2 l= 7 cons: SEQUENCE
+ 54:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 61:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 83:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 105:d=5 hl=2 l= 1 prim: INTEGER :03
+ 108:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 110:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 127:d=4 hl=2 l= 17 cons: cont [ 0 ]
+ 129:d=5 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 146:d=1 hl=2 l= 13 cons: SEQUENCE
+ 148:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 159:d=2 hl=2 l= 0 prim: NULL
+ 161:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBPwoBAKCCATgwggE0BgkrBgEFBQcwAQEEggElMIIBITCBi6EUMBIxEDAOBgNVBAMTB1Rlc3Q
+gQ0EYDzIwMTYwMzA0MTY0MDAyWjBiMGAwODAHBgUrDgMCGgQUAv912iTeit0VD6tonczm5mNtCQ
+EEFHc1rLTf57ncglk4G37t8IgrlzU0AgEDgAAYDzIwMTYwMzA0MTY0MDAyWqARGA8yMDE2MDMwN
+DE2NDAwMlowDQYJKoZIhvcNAQEFBQADgYEAUaMzuLydF/skM3i+4I0fPNHhe0Ilzxidd4SW4l7s
+NhZLc5kngs2sP+WcPIc9UCHYeB5rGgL8ochmQj8EIO+Z+rlss3L5CLlyYXw2cv3i7Bcb9MJResS
+az0cM1VDLiDP2zxS+sPtPtWt5q2PQh91ATJjLH+rl94IJLrfqGJ8m5Vc=
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/has_extension.pem b/chromium/net/data/parse_ocsp_unittest/has_extension.pem
new file mode 100644
index 00000000000..5fcd28575ac
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/has_extension.pem
@@ -0,0 +1,124 @@
+Includes an x509v3 extension
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 319 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 312 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 308 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 293 prim: OCTET STRING
+ 0:d=0 hl=4 l= 289 cons: SEQUENCE
+ 4:d=1 hl=3 l= 139 cons: SEQUENCE
+ 7:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 9:d=3 hl=2 l= 18 cons: SEQUENCE
+ 11:d=4 hl=2 l= 16 cons: SET
+ 13:d=5 hl=2 l= 14 cons: SEQUENCE
+ 15:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 20:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 29:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 46:d=2 hl=2 l= 79 cons: SEQUENCE
+ 48:d=3 hl=2 l= 77 cons: SEQUENCE
+ 50:d=4 hl=2 l= 56 cons: SEQUENCE
+ 52:d=5 hl=2 l= 7 cons: SEQUENCE
+ 54:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 61:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 83:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 105:d=5 hl=2 l= 1 prim: INTEGER :03
+ 108:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 110:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 127:d=2 hl=2 l= 17 cons: cont [ 1 ]
+ 129:d=3 hl=2 l= 15 cons: SEQUENCE
+ 131:d=4 hl=2 l= 13 cons: SEQUENCE
+ 133:d=5 hl=2 l= 3 prim: OBJECT :1.2.3.4
+Error in encoding
+-----BEGIN OCSP RESPONSE-----
+MIIBPwoBAKCCATgwggE0BgkrBgEFBQcwAQEEggElMIIBITCBi6EUMBIxEDAOBgNVBAMTB1Rlc3Q
+gQ0EYDzIwMTYwMzA0MTY0MDAyWjBPME0wODAHBgUrDgMCGgQUAv912iTeit0VD6tonczm5mNtCQ
+EEFHc1rLTf57ncglk4G37t8IgrlzU0AgEDgAAYDzIwMTYwMzA0MTY0MDAyWqERMA8wDQYDKgMER
+EVBREJFRUYwDQYJKoZIhvcNAQEFBQADgYEAIAs38OAgwQtXMBhJwNs8EHgrIUMIKz5aZBX79OL3
+hAtpoA94hSvA/Z7iJ9R6XX+x6RAjVTODkFjQCpZb3cjgUQvJgQDr4ct34KdY0uDYNlEKGfrecaG
+z5TEAu92I16UVjj69lBbBuU7IxJQPKjU2ZoR0nqh9VyDgAyOvVcCz608=
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/has_single_extension.pem b/chromium/net/data/parse_ocsp_unittest/has_single_extension.pem
new file mode 100644
index 00000000000..385ee055fae
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/has_single_extension.pem
@@ -0,0 +1,124 @@
+Has an extension in the SingleResponse
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 319 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 312 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 308 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 293 prim: OCTET STRING
+ 0:d=0 hl=4 l= 289 cons: SEQUENCE
+ 4:d=1 hl=3 l= 139 cons: SEQUENCE
+ 7:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 9:d=3 hl=2 l= 18 cons: SEQUENCE
+ 11:d=4 hl=2 l= 16 cons: SET
+ 13:d=5 hl=2 l= 14 cons: SEQUENCE
+ 15:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 20:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 29:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 46:d=2 hl=2 l= 98 cons: SEQUENCE
+ 48:d=3 hl=2 l= 96 cons: SEQUENCE
+ 50:d=4 hl=2 l= 56 cons: SEQUENCE
+ 52:d=5 hl=2 l= 7 cons: SEQUENCE
+ 54:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 61:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 83:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 105:d=5 hl=2 l= 1 prim: INTEGER :03
+ 108:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 110:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 127:d=4 hl=2 l= 17 cons: cont [ 1 ]
+ 129:d=5 hl=2 l= 15 cons: SEQUENCE
+ 131:d=6 hl=2 l= 13 cons: SEQUENCE
+ 133:d=7 hl=2 l= 3 prim: OBJECT :1.2.3.4
+Error in encoding
+-----BEGIN OCSP RESPONSE-----
+MIIBPwoBAKCCATgwggE0BgkrBgEFBQcwAQEEggElMIIBITCBi6EUMBIxEDAOBgNVBAMTB1Rlc3Q
+gQ0EYDzIwMTYwMzA0MTY0MDAyWjBiMGAwODAHBgUrDgMCGgQUAv912iTeit0VD6tonczm5mNtCQ
+EEFHc1rLTf57ncglk4G37t8IgrlzU0AgEDgAAYDzIwMTYwMzA0MTY0MDAyWqERMA8wDQYDKgMER
+EVBREJFRUYwDQYJKoZIhvcNAQEFBQADgYEAbcAvOhDvLP8Wuine9UmLz2+gIkxLEdPLdexxb844
+9xAX+JuofgeDI4m7+Z3KYH+4Pl0c5d8hcoCNT0gievvtpyb533yOb3ROEEaSSasECEXFi4ZRIiz
+nHUH5pWBtqw0lA/BoVj66Lb0dG5AiuIyrZom3SylNh9A0pHAZIyIDe0M=
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/has_version.pem b/chromium/net/data/parse_ocsp_unittest/has_version.pem
new file mode 100644
index 00000000000..766d76d4a4b
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/has_version.pem
@@ -0,0 +1,123 @@
+Includes a default version V1
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 299 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 292 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 288 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 273 prim: OCTET STRING
+ 0:d=0 hl=4 l= 269 cons: SEQUENCE
+ 4:d=1 hl=2 l= 120 cons: SEQUENCE
+ 6:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 8:d=3 hl=2 l= 18 cons: SEQUENCE
+ 10:d=4 hl=2 l= 16 cons: SET
+ 12:d=5 hl=2 l= 14 cons: SEQUENCE
+ 14:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 19:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 28:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 45:d=2 hl=2 l= 79 cons: SEQUENCE
+ 47:d=3 hl=2 l= 77 cons: SEQUENCE
+ 49:d=4 hl=2 l= 56 cons: SEQUENCE
+ 51:d=5 hl=2 l= 7 cons: SEQUENCE
+ 53:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 60:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 82:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 104:d=5 hl=2 l= 1 prim: INTEGER :03
+ 107:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 109:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 126:d=1 hl=2 l= 13 cons: SEQUENCE
+ 128:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 139:d=2 hl=2 l= 0 prim: NULL
+ 141:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBKwoBAKCCASQwggEgBgkrBgEFBQcwAQEEggERMIIBDTB4oRQwEjEQMA4GA1UEAxMHVGVzdCB
+DQRgPMjAxNjAzMDQxNjQwMDJaME8wTTA4MAcGBSsOAwIaBBQC/3XaJN6K3RUPq2idzObmY20JAQ
+QUdzWstN/nudyCWTgbfu3wiCuXNTQCAQOAABgPMjAxNjAzMDQxNjQwMDJaMA0GCSqGSIb3DQEBB
+QUAA4GBAEaH8xtlTUtrtKBa/dKPjWhP5dl+FQMVmCpKVGYVkh+mq/mltWcFgqmVr2uMuCngTIXg
+xXd9xzvdjl3Y8PqbFXd2267ZQ5JWLkyU1FFxOYRQsjNZD45AnPmXUeHTJ+KqvmIoduFMc2O42RK
+/bUfjrcMZcpbblnbPReAfYUsUaiCE
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/malformed_status.pem b/chromium/net/data/parse_ocsp_unittest/malformed_status.pem
new file mode 100644
index 00000000000..be983d7f895
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/malformed_status.pem
@@ -0,0 +1,91 @@
+Has a status of MALFORMED_REQUEST
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=2 l= 3 cons: SEQUENCE
+ 2:d=1 hl=2 l= 1 prim: ENUMERATED :01
+-----BEGIN OCSP RESPONSE-----
+MAMKAQE=
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/missing_response.pem b/chromium/net/data/parse_ocsp_unittest/missing_response.pem
new file mode 100644
index 00000000000..a90453767e2
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/missing_response.pem
@@ -0,0 +1,112 @@
+Missing a response for the cert
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=3 l= 216 cons: SEQUENCE
+ 3:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 6:d=1 hl=3 l= 210 cons: cont [ 0 ]
+ 9:d=2 hl=3 l= 207 cons: SEQUENCE
+ 12:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 23:d=3 hl=3 l= 193 prim: OCTET STRING
+ 0:d=0 hl=3 l= 190 cons: SEQUENCE
+ 3:d=1 hl=2 l= 41 cons: SEQUENCE
+ 5:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 7:d=3 hl=2 l= 18 cons: SEQUENCE
+ 9:d=4 hl=2 l= 16 cons: SET
+ 11:d=5 hl=2 l= 14 cons: SEQUENCE
+ 13:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 18:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 27:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 44:d=2 hl=2 l= 0 cons: SEQUENCE
+ 46:d=1 hl=2 l= 13 cons: SEQUENCE
+ 48:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 59:d=2 hl=2 l= 0 prim: NULL
+ 61:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIHYCgEAoIHSMIHPBgkrBgEFBQcwAQEEgcEwgb4wKaEUMBIxEDAOBgNVBAMTB1Rlc3QgQ0EYDzI
+wMTYwMzA0MTY0MDAyWjAAMA0GCSqGSIb3DQEBBQUAA4GBAFEVksQxQGbZHWAsFEgQHN/UVO6fdf
+nOATPc/lnJLGVzGXgYoa/Rg9bRZ9hVdz0QYLE5u8PbQKqNCWzq31ilry2NZtMbFpd/Gr3TkAcIB
+hpBYTcxK3+x1nq8ztuep36XoV+gGbTaB3f7BqeR60t4/pWzwjf8A+8+6unFC5hYE07J
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/multiple_response.pem b/chromium/net/data/parse_ocsp_unittest/multiple_response.pem
new file mode 100644
index 00000000000..985bf82e4e4
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/multiple_response.pem
@@ -0,0 +1,133 @@
+Has multiple responses for the cert
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 380 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 373 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 369 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 354 prim: OCTET STRING
+ 0:d=0 hl=4 l= 350 cons: SEQUENCE
+ 4:d=1 hl=3 l= 200 cons: SEQUENCE
+ 7:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 9:d=3 hl=2 l= 18 cons: SEQUENCE
+ 11:d=4 hl=2 l= 16 cons: SET
+ 13:d=5 hl=2 l= 14 cons: SEQUENCE
+ 15:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 20:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 29:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 46:d=2 hl=3 l= 158 cons: SEQUENCE
+ 49:d=3 hl=2 l= 77 cons: SEQUENCE
+ 51:d=4 hl=2 l= 56 cons: SEQUENCE
+ 53:d=5 hl=2 l= 7 cons: SEQUENCE
+ 55:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 62:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 84:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 106:d=5 hl=2 l= 1 prim: INTEGER :03
+ 109:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 111:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 128:d=3 hl=2 l= 77 cons: SEQUENCE
+ 130:d=4 hl=2 l= 56 cons: SEQUENCE
+ 132:d=5 hl=2 l= 7 cons: SEQUENCE
+ 134:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 141:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 163:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 185:d=5 hl=2 l= 1 prim: INTEGER :03
+ 188:d=4 hl=2 l= 0 prim: cont [ 2 ]
+ 190:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 207:d=1 hl=2 l= 13 cons: SEQUENCE
+ 209:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 220:d=2 hl=2 l= 0 prim: NULL
+ 222:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBfAoBAKCCAXUwggFxBgkrBgEFBQcwAQEEggFiMIIBXjCByKEUMBIxEDAOBgNVBAMTB1Rlc3Q
+gQ0EYDzIwMTYwMzA0MTY0MDAyWjCBnjBNMDgwBwYFKw4DAhoEFAL/ddok3ordFQ+raJ3M5uZjbQ
+kBBBR3Nay03+e53IJZOBt+7fCIK5c1NAIBA4AAGA8yMDE2MDMwNDE2NDAwMlowTTA4MAcGBSsOA
+wIaBBQC/3XaJN6K3RUPq2idzObmY20JAQQUdzWstN/nudyCWTgbfu3wiCuXNTQCAQOCABgPMjAx
+NjAzMDQxNjQwMDJaMA0GCSqGSIb3DQEBBQUAA4GBADtJYfmQINzaAJV81Nocj2EBm0O0hXhSKd3
+Vb5EP5e2mAxywv6HzW+kde1cTfQCRLNaumm8/Mow4RpmfquWL/ZCIDYLk1flxYE2MR4Gr7QpPP0
+iiisfzJwe7LpiFSYMO7W4jxlqmPIGeHz28/KD1GT6R0fC+kXJF1dZoQyIRy9xE
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/no_response.pem b/chromium/net/data/parse_ocsp_unittest/no_response.pem
new file mode 100644
index 00000000000..73b40801514
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/no_response.pem
@@ -0,0 +1,112 @@
+No SingleResponses attached to the response
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=3 l= 216 cons: SEQUENCE
+ 3:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 6:d=1 hl=3 l= 210 cons: cont [ 0 ]
+ 9:d=2 hl=3 l= 207 cons: SEQUENCE
+ 12:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 23:d=3 hl=3 l= 193 prim: OCTET STRING
+ 0:d=0 hl=3 l= 190 cons: SEQUENCE
+ 3:d=1 hl=2 l= 41 cons: SEQUENCE
+ 5:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 7:d=3 hl=2 l= 18 cons: SEQUENCE
+ 9:d=4 hl=2 l= 16 cons: SET
+ 11:d=5 hl=2 l= 14 cons: SEQUENCE
+ 13:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 18:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 27:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 44:d=2 hl=2 l= 0 cons: SEQUENCE
+ 46:d=1 hl=2 l= 13 cons: SEQUENCE
+ 48:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 59:d=2 hl=2 l= 0 prim: NULL
+ 61:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIHYCgEAoIHSMIHPBgkrBgEFBQcwAQEEgcEwgb4wKaEUMBIxEDAOBgNVBAMTB1Rlc3QgQ0EYDzI
+wMTYwMzA0MTY0MDAyWjAAMA0GCSqGSIb3DQEBBQUAA4GBAFEVksQxQGbZHWAsFEgQHN/UVO6fdf
+nOATPc/lnJLGVzGXgYoa/Rg9bRZ9hVdz0QYLE5u8PbQKqNCWzq31ilry2NZtMbFpd/Gr3TkAcIB
+hpBYTcxK3+x1nq8ztuep36XoV+gGbTaB3f7BqeR60t4/pWzwjf8A+8+6unFC5hYE07J
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/ocsp_extra_certs.pem b/chromium/net/data/parse_ocsp_unittest/ocsp_extra_certs.pem
new file mode 100644
index 00000000000..cfdad7bb3ee
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/ocsp_extra_certs.pem
@@ -0,0 +1,205 @@
+Includes extra certs
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l=1165 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l=1158 cons: cont [ 0 ]
+ 11:d=2 hl=4 l=1154 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l=1139 prim: OCTET STRING
+ 0:d=0 hl=4 l=1135 cons: SEQUENCE
+ 4:d=1 hl=2 l= 120 cons: SEQUENCE
+ 6:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 8:d=3 hl=2 l= 18 cons: SEQUENCE
+ 10:d=4 hl=2 l= 16 cons: SET
+ 12:d=5 hl=2 l= 14 cons: SEQUENCE
+ 14:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 19:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 28:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 45:d=2 hl=2 l= 79 cons: SEQUENCE
+ 47:d=3 hl=2 l= 77 cons: SEQUENCE
+ 49:d=4 hl=2 l= 56 cons: SEQUENCE
+ 51:d=5 hl=2 l= 7 cons: SEQUENCE
+ 53:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 60:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 82:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 104:d=5 hl=2 l= 1 prim: INTEGER :03
+ 107:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 109:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 126:d=1 hl=2 l= 13 cons: SEQUENCE
+ 128:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 139:d=2 hl=2 l= 0 prim: NULL
+ 141:d=1 hl=3 l= 129 prim: BIT STRING
+ 273:d=1 hl=4 l= 862 cons: cont [ 0 ]
+ 277:d=2 hl=4 l= 858 cons: SEQUENCE
+ 281:d=3 hl=4 l= 408 cons: SEQUENCE
+ 285:d=4 hl=4 l= 257 cons: SEQUENCE
+ 289:d=5 hl=2 l= 3 cons: cont [ 0 ]
+ 291:d=6 hl=2 l= 1 prim: INTEGER :02
+ 294:d=5 hl=2 l= 1 prim: INTEGER :00
+ 297:d=5 hl=2 l= 13 cons: SEQUENCE
+ 299:d=6 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 310:d=6 hl=2 l= 0 prim: NULL
+ 312:d=5 hl=2 l= 18 cons: SEQUENCE
+ 314:d=6 hl=2 l= 16 cons: SET
+ 316:d=7 hl=2 l= 14 cons: SEQUENCE
+ 318:d=8 hl=2 l= 3 prim: OBJECT :commonName
+ 323:d=8 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 332:d=5 hl=2 l= 30 cons: SEQUENCE
+ 334:d=6 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 349:d=6 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 364:d=5 hl=2 l= 18 cons: SEQUENCE
+ 366:d=6 hl=2 l= 16 cons: SET
+ 368:d=7 hl=2 l= 14 cons: SEQUENCE
+ 370:d=8 hl=2 l= 3 prim: OBJECT :commonName
+ 375:d=8 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 384:d=5 hl=3 l= 159 cons: SEQUENCE
+ 387:d=6 hl=2 l= 13 cons: SEQUENCE
+ 389:d=7 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 400:d=7 hl=2 l= 0 prim: NULL
+ 402:d=6 hl=3 l= 141 prim: BIT STRING
+ 546:d=4 hl=2 l= 13 cons: SEQUENCE
+ 548:d=5 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 559:d=5 hl=2 l= 0 prim: NULL
+ 561:d=4 hl=3 l= 129 prim: BIT STRING
+ 693:d=3 hl=4 l= 442 cons: SEQUENCE
+ 697:d=4 hl=4 l= 291 cons: SEQUENCE
+ 701:d=5 hl=2 l= 3 cons: cont [ 0 ]
+ 703:d=6 hl=2 l= 1 prim: INTEGER :02
+ 706:d=5 hl=2 l= 1 prim: INTEGER :01
+ 709:d=5 hl=2 l= 13 cons: SEQUENCE
+ 711:d=6 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 722:d=6 hl=2 l= 0 prim: NULL
+ 724:d=5 hl=2 l= 18 cons: SEQUENCE
+ 726:d=6 hl=2 l= 16 cons: SET
+ 728:d=7 hl=2 l= 14 cons: SEQUENCE
+ 730:d=8 hl=2 l= 3 prim: OBJECT :commonName
+ 735:d=8 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 744:d=5 hl=2 l= 30 cons: SEQUENCE
+ 746:d=6 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 761:d=6 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 776:d=5 hl=2 l= 27 cons: SEQUENCE
+ 778:d=6 hl=2 l= 25 cons: SET
+ 780:d=7 hl=2 l= 23 cons: SEQUENCE
+ 782:d=8 hl=2 l= 3 prim: OBJECT :commonName
+ 787:d=8 hl=2 l= 16 prim: PRINTABLESTRING :Test OCSP Signer
+ 805:d=5 hl=3 l= 159 cons: SEQUENCE
+ 808:d=6 hl=2 l= 13 cons: SEQUENCE
+ 810:d=7 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 821:d=7 hl=2 l= 0 prim: NULL
+ 823:d=6 hl=3 l= 141 prim: BIT STRING
+ 967:d=5 hl=2 l= 23 cons: cont [ 3 ]
+ 969:d=6 hl=2 l= 21 cons: SEQUENCE
+ 971:d=7 hl=2 l= 19 cons: SEQUENCE
+ 973:d=8 hl=2 l= 3 prim: OBJECT :X509v3 Extended Key Usage
+ 978:d=8 hl=2 l= 12 prim: OCTET STRING [HEX DUMP]:300A06082B06010505070309
+ 992:d=4 hl=2 l= 13 cons: SEQUENCE
+ 994:d=5 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 1005:d=5 hl=2 l= 0 prim: NULL
+ 1007:d=4 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIEjQoBAKCCBIYwggSCBgkrBgEFBQcwAQEEggRzMIIEbzB4oRQwEjEQMA4GA1UEAxMHVGVzdCB
+DQRgPMjAxNjAzMDQxNjQwMDJaME8wTTA4MAcGBSsOAwIaBBQC/3XaJN6K3RUPq2idzObmY20JAQ
+QUdzWstN/nudyCWTgbfu3wiCuXNTQCAQOAABgPMjAxNjAzMDQxNjQwMDJaMA0GCSqGSIb3DQEBB
+QUAA4GBAEaH8xtlTUtrtKBa/dKPjWhP5dl+FQMVmCpKVGYVkh+mq/mltWcFgqmVr2uMuCngTIXg
+xXd9xzvdjl3Y8PqbFXd2267ZQ5JWLkyU1FFxOYRQsjNZD45AnPmXUeHTJ+KqvmIoduFMc2O42RK
+/bUfjrcMZcpbblnbPReAfYUsUaiCEoIIDXjCCA1owggGYMIIBAaADAgECAgEAMA0GCSqGSIb3DQ
+EBBQUAMBIxEDAOBgNVBAMTB1Rlc3QgQ0EwHhcNMTYwMzA0MjE0MDAyWhcNMjYwMzAyMjE0MDAyW
+jASMRAwDgYDVQQDEwdUZXN0IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDE3whHt7Lq
+NNVTJLqSQKq3bH3+bGdHPvs/LorB2bc/2OojCqsJG6oBd8LlBzJ7JRpcoJzj1uYvtzLrhSjBOuc
+iPKqJg5fRU7q3dl0pzLb/xTa7B0vmhk+UGSkjqZTu+X7espsqQ0808u/xqnAUXXMgdSbW26d3Xn
+Y+UwBZC7quZQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAJhpZ2OHHQBEaGzUOPU3pFch/RTrr2clz
+HReS4L/IvkmLXpyMjWzvpqtWMYrs49nTXXHj+A0xEuPfXDLEqx+DepB2ViRWXz0LC0D4rGCFChG
+EPxxJZjVo5BybiEzXUcTm3lXI1uF5I4FXCg5vzA5yBkURF8I1ZtzHZrdZhUkIahTMIIBujCCASO
+gAwIBAgIBATANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE2MDMwNDIxND
+AwMloXDTI2MDMwMjIxNDAwMlowGzEZMBcGA1UEAxMQVGVzdCBPQ1NQIFNpZ25lcjCBnzANBgkqh
+kiG9w0BAQEFAAOBjQAwgYkCgYEAr33RA+84nexEDSI0KGSwbWlLiaACkAiVbJQwXoWDqTSKrD1u
+b376zek9M+5WETYka2V0ZwnW9IbJiEpmnn4rKvTdItkHYv7vYK5+9KBi4s8w4aYRECYDdTKc6+0
+I6ZY/jAXY1Zxz/rAmfFVvV7roAD2QvVM3f7hUC2uIqQPjXJECAwEAAaMXMBUwEwYDVR0lBAwwCg
+YIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADgYEAvIZNLVTEHpgj0gKN9x1LvTJJUVSJovny2zI/Y
+Bt1HluMNjgMmTKUearYNJVBlqWKB0xytByOQVgkkPQjJYSTVFguc6ObfKG005OlhNXa2ZDffSn+
+gmo8NtdOQyDbz0ydaENNCxpSxr4QXNdOGMiwxN3FSjE1V7v0XdGGsAgrSRw=
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/ocsp_sign_bad_indirect.pem b/chromium/net/data/parse_ocsp_unittest/ocsp_sign_bad_indirect.pem
new file mode 100644
index 00000000000..308d2c7d423
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/ocsp_sign_bad_indirect.pem
@@ -0,0 +1,163 @@
+Signed through an intermediate without the correct key usage
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 750 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 743 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 739 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 724 prim: OCTET STRING
+ 0:d=0 hl=4 l= 720 cons: SEQUENCE
+ 4:d=1 hl=3 l= 135 cons: SEQUENCE
+ 7:d=2 hl=2 l= 35 cons: cont [ 1 ]
+ 9:d=3 hl=2 l= 33 cons: SEQUENCE
+ 11:d=4 hl=2 l= 31 cons: SET
+ 13:d=5 hl=2 l= 29 cons: SEQUENCE
+ 15:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 20:d=6 hl=2 l= 22 prim: PRINTABLESTRING :Test False OCSP Signer
+ 44:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 61:d=2 hl=2 l= 79 cons: SEQUENCE
+ 63:d=3 hl=2 l= 77 cons: SEQUENCE
+ 65:d=4 hl=2 l= 56 cons: SEQUENCE
+ 67:d=5 hl=2 l= 7 cons: SEQUENCE
+ 69:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 76:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 98:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 120:d=5 hl=2 l= 1 prim: INTEGER :03
+ 123:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 125:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 142:d=1 hl=2 l= 13 cons: SEQUENCE
+ 144:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 155:d=2 hl=2 l= 0 prim: NULL
+ 157:d=1 hl=3 l= 129 prim: BIT STRING
+ 289:d=1 hl=4 l= 431 cons: cont [ 0 ]
+ 293:d=2 hl=4 l= 427 cons: SEQUENCE
+ 297:d=3 hl=4 l= 423 cons: SEQUENCE
+ 301:d=4 hl=4 l= 272 cons: SEQUENCE
+ 305:d=5 hl=2 l= 3 cons: cont [ 0 ]
+ 307:d=6 hl=2 l= 1 prim: INTEGER :02
+ 310:d=5 hl=2 l= 1 prim: INTEGER :02
+ 313:d=5 hl=2 l= 13 cons: SEQUENCE
+ 315:d=6 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 326:d=6 hl=2 l= 0 prim: NULL
+ 328:d=5 hl=2 l= 18 cons: SEQUENCE
+ 330:d=6 hl=2 l= 16 cons: SET
+ 332:d=7 hl=2 l= 14 cons: SEQUENCE
+ 334:d=8 hl=2 l= 3 prim: OBJECT :commonName
+ 339:d=8 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 348:d=5 hl=2 l= 30 cons: SEQUENCE
+ 350:d=6 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 365:d=6 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 380:d=5 hl=2 l= 33 cons: SEQUENCE
+ 382:d=6 hl=2 l= 31 cons: SET
+ 384:d=7 hl=2 l= 29 cons: SEQUENCE
+ 386:d=8 hl=2 l= 3 prim: OBJECT :commonName
+ 391:d=8 hl=2 l= 22 prim: PRINTABLESTRING :Test False OCSP Signer
+ 415:d=5 hl=3 l= 159 cons: SEQUENCE
+ 418:d=6 hl=2 l= 13 cons: SEQUENCE
+ 420:d=7 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 431:d=7 hl=2 l= 0 prim: NULL
+ 433:d=6 hl=3 l= 141 prim: BIT STRING
+ 577:d=4 hl=2 l= 13 cons: SEQUENCE
+ 579:d=5 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 590:d=5 hl=2 l= 0 prim: NULL
+ 592:d=4 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIC7goBAKCCAucwggLjBgkrBgEFBQcwAQEEggLUMIIC0DCBh6EjMCExHzAdBgNVBAMTFlRlc3Q
+gRmFsc2UgT0NTUCBTaWduZXIYDzIwMTYwMzA0MTY0MDAyWjBPME0wODAHBgUrDgMCGgQUAv912i
+Teit0VD6tonczm5mNtCQEEFHc1rLTf57ncglk4G37t8IgrlzU0AgEDgAAYDzIwMTYwMzA0MTY0M
+DAyWjANBgkqhkiG9w0BAQUFAAOBgQBUbTwYMCKST8shnSN4BIA6rdPZn+kUZF2hEWLqY7A0Ru1H
+OaAd4idxtPIfb7nzydt3gXuaI1lgjT5F9Choe99e20X2+xkZpnnzoN5OKeUhiK08I8azqGHsxfC
+hWlrAASXdA7iwld5dGbw+RlNHB4nrAuknAUdTHFGdiP7x7TBhNaCCAa8wggGrMIIBpzCCARCgAw
+IBAgIBAjANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE2MDMwNDIxNDAwM
+loXDTI2MDMwMjIxNDAwMlowITEfMB0GA1UEAxMWVGVzdCBGYWxzZSBPQ1NQIFNpZ25lcjCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApn44UGWdpvHcClqexVMmT8yIGg8DjLaZzDMT4YktTYs
+Df011huQhUoNNOHbVR+zveTORiw+J+Xe2fvz10E35Fp8hrdc2BUXPywcIwGMBAqw4Xfn065B0it
+sUg8AYm4yPTL0/TPXFKj4LF5TbGdOlYD/hQgzehtvsPLEfCPLy6IsCAwEAATANBgkqhkiG9w0BA
+QUFAAOBgQCU24MnAyNiaNesmlQRj9sZSBERuSddMWKsLlXBMs4k3iVJBq92wxOcj3YCk84dFttM
+nj5hEKVnVxzHDTSGjOWLvzJtj7y8CjQ2CS1xkB1c1xrnsYXjQLqWSSIwUFIxC926BsTMIU7zOs/
+mjO7GAm4CJhP9MYGPwv3Yy4g66I+HUA==
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/ocsp_sign_direct.pem b/chromium/net/data/parse_ocsp_unittest/ocsp_sign_direct.pem
new file mode 100644
index 00000000000..23b245b2db0
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/ocsp_sign_direct.pem
@@ -0,0 +1,123 @@
+Signed directly by the issuer
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 299 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 292 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 288 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 273 prim: OCTET STRING
+ 0:d=0 hl=4 l= 269 cons: SEQUENCE
+ 4:d=1 hl=2 l= 120 cons: SEQUENCE
+ 6:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 8:d=3 hl=2 l= 18 cons: SEQUENCE
+ 10:d=4 hl=2 l= 16 cons: SET
+ 12:d=5 hl=2 l= 14 cons: SEQUENCE
+ 14:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 19:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 28:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 45:d=2 hl=2 l= 79 cons: SEQUENCE
+ 47:d=3 hl=2 l= 77 cons: SEQUENCE
+ 49:d=4 hl=2 l= 56 cons: SEQUENCE
+ 51:d=5 hl=2 l= 7 cons: SEQUENCE
+ 53:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 60:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 82:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 104:d=5 hl=2 l= 1 prim: INTEGER :03
+ 107:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 109:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 126:d=1 hl=2 l= 13 cons: SEQUENCE
+ 128:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 139:d=2 hl=2 l= 0 prim: NULL
+ 141:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBKwoBAKCCASQwggEgBgkrBgEFBQcwAQEEggERMIIBDTB4oRQwEjEQMA4GA1UEAxMHVGVzdCB
+DQRgPMjAxNjAzMDQxNjQwMDJaME8wTTA4MAcGBSsOAwIaBBQC/3XaJN6K3RUPq2idzObmY20JAQ
+QUdzWstN/nudyCWTgbfu3wiCuXNTQCAQOAABgPMjAxNjAzMDQxNjQwMDJaMA0GCSqGSIb3DQEBB
+QUAA4GBAEaH8xtlTUtrtKBa/dKPjWhP5dl+FQMVmCpKVGYVkh+mq/mltWcFgqmVr2uMuCngTIXg
+xXd9xzvdjl3Y8PqbFXd2267ZQ5JWLkyU1FFxOYRQsjNZD45AnPmXUeHTJ+KqvmIoduFMc2O42RK
+/bUfjrcMZcpbblnbPReAfYUsUaiCE
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/ocsp_sign_indirect.pem b/chromium/net/data/parse_ocsp_unittest/ocsp_sign_indirect.pem
new file mode 100644
index 00000000000..3c3cbe10902
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/ocsp_sign_indirect.pem
@@ -0,0 +1,168 @@
+Signed indirectly through an intermediate
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 763 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 756 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 752 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 737 prim: OCTET STRING
+ 0:d=0 hl=4 l= 733 cons: SEQUENCE
+ 4:d=1 hl=3 l= 129 cons: SEQUENCE
+ 7:d=2 hl=2 l= 29 cons: cont [ 1 ]
+ 9:d=3 hl=2 l= 27 cons: SEQUENCE
+ 11:d=4 hl=2 l= 25 cons: SET
+ 13:d=5 hl=2 l= 23 cons: SEQUENCE
+ 15:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 20:d=6 hl=2 l= 16 prim: PRINTABLESTRING :Test OCSP Signer
+ 38:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 55:d=2 hl=2 l= 79 cons: SEQUENCE
+ 57:d=3 hl=2 l= 77 cons: SEQUENCE
+ 59:d=4 hl=2 l= 56 cons: SEQUENCE
+ 61:d=5 hl=2 l= 7 cons: SEQUENCE
+ 63:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 70:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 92:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 114:d=5 hl=2 l= 1 prim: INTEGER :03
+ 117:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 119:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 136:d=1 hl=2 l= 13 cons: SEQUENCE
+ 138:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 149:d=2 hl=2 l= 0 prim: NULL
+ 151:d=1 hl=3 l= 129 prim: BIT STRING
+ 283:d=1 hl=4 l= 450 cons: cont [ 0 ]
+ 287:d=2 hl=4 l= 446 cons: SEQUENCE
+ 291:d=3 hl=4 l= 442 cons: SEQUENCE
+ 295:d=4 hl=4 l= 291 cons: SEQUENCE
+ 299:d=5 hl=2 l= 3 cons: cont [ 0 ]
+ 301:d=6 hl=2 l= 1 prim: INTEGER :02
+ 304:d=5 hl=2 l= 1 prim: INTEGER :01
+ 307:d=5 hl=2 l= 13 cons: SEQUENCE
+ 309:d=6 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 320:d=6 hl=2 l= 0 prim: NULL
+ 322:d=5 hl=2 l= 18 cons: SEQUENCE
+ 324:d=6 hl=2 l= 16 cons: SET
+ 326:d=7 hl=2 l= 14 cons: SEQUENCE
+ 328:d=8 hl=2 l= 3 prim: OBJECT :commonName
+ 333:d=8 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 342:d=5 hl=2 l= 30 cons: SEQUENCE
+ 344:d=6 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 359:d=6 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 374:d=5 hl=2 l= 27 cons: SEQUENCE
+ 376:d=6 hl=2 l= 25 cons: SET
+ 378:d=7 hl=2 l= 23 cons: SEQUENCE
+ 380:d=8 hl=2 l= 3 prim: OBJECT :commonName
+ 385:d=8 hl=2 l= 16 prim: PRINTABLESTRING :Test OCSP Signer
+ 403:d=5 hl=3 l= 159 cons: SEQUENCE
+ 406:d=6 hl=2 l= 13 cons: SEQUENCE
+ 408:d=7 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 419:d=7 hl=2 l= 0 prim: NULL
+ 421:d=6 hl=3 l= 141 prim: BIT STRING
+ 565:d=5 hl=2 l= 23 cons: cont [ 3 ]
+ 567:d=6 hl=2 l= 21 cons: SEQUENCE
+ 569:d=7 hl=2 l= 19 cons: SEQUENCE
+ 571:d=8 hl=2 l= 3 prim: OBJECT :X509v3 Extended Key Usage
+ 576:d=8 hl=2 l= 12 prim: OCTET STRING [HEX DUMP]:300A06082B06010505070309
+ 590:d=4 hl=2 l= 13 cons: SEQUENCE
+ 592:d=5 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 603:d=5 hl=2 l= 0 prim: NULL
+ 605:d=4 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIC+woBAKCCAvQwggLwBgkrBgEFBQcwAQEEggLhMIIC3TCBgaEdMBsxGTAXBgNVBAMTEFRlc3Q
+gT0NTUCBTaWduZXIYDzIwMTYwMzA0MTY0MDAyWjBPME0wODAHBgUrDgMCGgQUAv912iTeit0VD6
+tonczm5mNtCQEEFHc1rLTf57ncglk4G37t8IgrlzU0AgEDgAAYDzIwMTYwMzA0MTY0MDAyWjANB
+gkqhkiG9w0BAQUFAAOBgQClgWYlzN9DKHjCisGXYGbagKQmGo2zPi8/pK5zE9YPzDTx0mFP2w6T
+ZgrdtYW+e66U6WgtbYbUL1USBAugHy2mbXjeZroHiKRHxBdb17M2ADhqS/tyue4IyuPEGuyhUXt
+qvPxIiyXFCNnP4HU0uxcnQK9PMNWQnFlk5aA1ixoQjaCCAcIwggG+MIIBujCCASOgAwIBAgIBAT
+ANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE2MDMwNDIxNDAwMloXDTI2M
+DMwMjIxNDAwMlowGzEZMBcGA1UEAxMQVGVzdCBPQ1NQIFNpZ25lcjCBnzANBgkqhkiG9w0BAQEF
+AAOBjQAwgYkCgYEAr33RA+84nexEDSI0KGSwbWlLiaACkAiVbJQwXoWDqTSKrD1ub376zek9M+5
+WETYka2V0ZwnW9IbJiEpmnn4rKvTdItkHYv7vYK5+9KBi4s8w4aYRECYDdTKc6+0I6ZY/jAXY1Z
+xz/rAmfFVvV7roAD2QvVM3f7hUC2uIqQPjXJECAwEAAaMXMBUwEwYDVR0lBAwwCgYIKwYBBQUHA
+wkwDQYJKoZIhvcNAQEFBQADgYEAvIZNLVTEHpgj0gKN9x1LvTJJUVSJovny2zI/YBt1HluMNjgM
+mTKUearYNJVBlqWKB0xytByOQVgkkPQjJYSTVFguc6ObfKG005OlhNXa2ZDffSn+gmo8NtdOQyD
+bz0ydaENNCxpSxr4QXNdOGMiwxN3FSjE1V7v0XdGGsAgrSRw=
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/ocsp_sign_indirect_missing.pem b/chromium/net/data/parse_ocsp_unittest/ocsp_sign_indirect_missing.pem
new file mode 100644
index 00000000000..5286b556a31
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/ocsp_sign_indirect_missing.pem
@@ -0,0 +1,123 @@
+Signed indirectly through a missing intermediate
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 309 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 302 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 298 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 283 prim: OCTET STRING
+ 0:d=0 hl=4 l= 279 cons: SEQUENCE
+ 4:d=1 hl=3 l= 129 cons: SEQUENCE
+ 7:d=2 hl=2 l= 29 cons: cont [ 1 ]
+ 9:d=3 hl=2 l= 27 cons: SEQUENCE
+ 11:d=4 hl=2 l= 25 cons: SET
+ 13:d=5 hl=2 l= 23 cons: SEQUENCE
+ 15:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 20:d=6 hl=2 l= 16 prim: PRINTABLESTRING :Test OCSP Signer
+ 38:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 55:d=2 hl=2 l= 79 cons: SEQUENCE
+ 57:d=3 hl=2 l= 77 cons: SEQUENCE
+ 59:d=4 hl=2 l= 56 cons: SEQUENCE
+ 61:d=5 hl=2 l= 7 cons: SEQUENCE
+ 63:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 70:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 92:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 114:d=5 hl=2 l= 1 prim: INTEGER :03
+ 117:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 119:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 136:d=1 hl=2 l= 13 cons: SEQUENCE
+ 138:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 149:d=2 hl=2 l= 0 prim: NULL
+ 151:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBNQoBAKCCAS4wggEqBgkrBgEFBQcwAQEEggEbMIIBFzCBgaEdMBsxGTAXBgNVBAMTEFRlc3Q
+gT0NTUCBTaWduZXIYDzIwMTYwMzA0MTY0MDAyWjBPME0wODAHBgUrDgMCGgQUAv912iTeit0VD6
+tonczm5mNtCQEEFHc1rLTf57ncglk4G37t8IgrlzU0AgEDgAAYDzIwMTYwMzA0MTY0MDAyWjANB
+gkqhkiG9w0BAQUFAAOBgQClgWYlzN9DKHjCisGXYGbagKQmGo2zPi8/pK5zE9YPzDTx0mFP2w6T
+ZgrdtYW+e66U6WgtbYbUL1USBAugHy2mbXjeZroHiKRHxBdb17M2ADhqS/tyue4IyuPEGuyhUXt
+qvPxIiyXFCNnP4HU0uxcnQK9PMNWQnFlk5aA1ixoQjQ==
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/other_response.pem b/chromium/net/data/parse_ocsp_unittest/other_response.pem
new file mode 100644
index 00000000000..e151cacd350
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/other_response.pem
@@ -0,0 +1,135 @@
+Is a response for a different cert
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 397 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 390 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 386 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 371 prim: OCTET STRING
+ 0:d=0 hl=4 l= 367 cons: SEQUENCE
+ 4:d=1 hl=3 l= 217 cons: SEQUENCE
+ 7:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 9:d=3 hl=2 l= 18 cons: SEQUENCE
+ 11:d=4 hl=2 l= 16 cons: SET
+ 13:d=5 hl=2 l= 14 cons: SEQUENCE
+ 15:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 20:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 29:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 46:d=2 hl=3 l= 175 cons: SEQUENCE
+ 49:d=3 hl=2 l= 77 cons: SEQUENCE
+ 51:d=4 hl=2 l= 56 cons: SEQUENCE
+ 53:d=5 hl=2 l= 7 cons: SEQUENCE
+ 55:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 62:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:99D6B1D2B9004AD4235ABC2407F6A911CF4744F5
+ 84:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:47901C53047CFFA389F6D500D49AA1D45500EB94
+ 106:d=5 hl=2 l= 1 prim: INTEGER :04
+ 109:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 111:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 128:d=3 hl=2 l= 94 cons: SEQUENCE
+ 130:d=4 hl=2 l= 56 cons: SEQUENCE
+ 132:d=5 hl=2 l= 7 cons: SEQUENCE
+ 134:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 141:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:99D6B1D2B9004AD4235ABC2407F6A911CF4744F5
+ 163:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:47901C53047CFFA389F6D500D49AA1D45500EB94
+ 185:d=5 hl=2 l= 1 prim: INTEGER :04
+ 188:d=4 hl=2 l= 17 cons: cont [ 1 ]
+ 190:d=5 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 207:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 224:d=1 hl=2 l= 13 cons: SEQUENCE
+ 226:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 237:d=2 hl=2 l= 0 prim: NULL
+ 239:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBjQoBAKCCAYYwggGCBgkrBgEFBQcwAQEEggFzMIIBbzCB2aEUMBIxEDAOBgNVBAMTB1Rlc3Q
+gQ0EYDzIwMTYwMzA0MTY0MDAyWjCBrzBNMDgwBwYFKw4DAhoEFJnWsdK5AErUI1q8JAf2qRHPR0
+T1BBRHkBxTBHz/o4n21QDUmqHUVQDrlAIBBIAAGA8yMDE2MDMwNDE2NDAwMlowXjA4MAcGBSsOA
+wIaBBSZ1rHSuQBK1CNavCQH9qkRz0dE9QQUR5AcUwR8/6OJ9tUA1Jqh1FUA65QCAQShERgPMjAx
+NjAzMDQxNjQwMDJaGA8yMDE2MDMwNDE2NDAwMlowDQYJKoZIhvcNAQEFBQADgYEAYr+5Vsn/I0Z
+bEqIJbRm1hkZE8MFTkxvz+CArS+1FaBnGt+FUTiv8o6XDKDSgZmvAfPpgy5PSoK7cJ5H8Rp09BK
+SLGCeCWF/Kmv2EWGV8RspRFP5CmNYmbjayU0OOSUyNTQFHmmB90/2t1i7wwcLl7tbW4EuFdpBZ5
+hZSLXpsS6U=
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/responder_id.pem b/chromium/net/data/parse_ocsp_unittest/responder_id.pem
new file mode 100644
index 00000000000..13fed4f0599
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/responder_id.pem
@@ -0,0 +1,119 @@
+Uses byKey to identify the signer
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 301 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 294 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 290 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 275 prim: OCTET STRING
+ 0:d=0 hl=4 l= 271 cons: SEQUENCE
+ 4:d=1 hl=2 l= 122 cons: SEQUENCE
+ 6:d=2 hl=2 l= 22 cons: cont [ 2 ]
+ 8:d=3 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 30:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 47:d=2 hl=2 l= 79 cons: SEQUENCE
+ 49:d=3 hl=2 l= 77 cons: SEQUENCE
+ 51:d=4 hl=2 l= 56 cons: SEQUENCE
+ 53:d=5 hl=2 l= 7 cons: SEQUENCE
+ 55:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 62:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 84:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 106:d=5 hl=2 l= 1 prim: INTEGER :03
+ 109:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 111:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 128:d=1 hl=2 l= 13 cons: SEQUENCE
+ 130:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 141:d=2 hl=2 l= 0 prim: NULL
+ 143:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBLQoBAKCCASYwggEiBgkrBgEFBQcwAQEEggETMIIBDzB6ohYEFHc1rLTf57ncglk4G37t8Ig
+rlzU0GA8yMDE2MDMwNDE2NDAwMlowTzBNMDgwBwYFKw4DAhoEFAL/ddok3ordFQ+raJ3M5uZjbQ
+kBBBR3Nay03+e53IJZOBt+7fCIK5c1NAIBA4AAGA8yMDE2MDMwNDE2NDAwMlowDQYJKoZIhvcNA
+QEFBQADgYEAlBfILkufybGfg0K/0dK5o+xVYsra4kyHHfeGe2+X7Ie/QL88dafZRqycraUmO+Yv
+uqKgLMOUsMJCaWo/leyiAUVFcDa8NzcEWUiqPFtPzq4YSfnHoUIyzHliJMx1//Q9f6HtMAUqBk8
+FaET1SGuZB46eW0cck0ZgeNFT3rOmOno=
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/responder_name.pem b/chromium/net/data/parse_ocsp_unittest/responder_name.pem
new file mode 100644
index 00000000000..45293adafb6
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/responder_name.pem
@@ -0,0 +1,123 @@
+Uses byName to identify the signer
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 299 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 292 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 288 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 273 prim: OCTET STRING
+ 0:d=0 hl=4 l= 269 cons: SEQUENCE
+ 4:d=1 hl=2 l= 120 cons: SEQUENCE
+ 6:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 8:d=3 hl=2 l= 18 cons: SEQUENCE
+ 10:d=4 hl=2 l= 16 cons: SET
+ 12:d=5 hl=2 l= 14 cons: SEQUENCE
+ 14:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 19:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 28:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 45:d=2 hl=2 l= 79 cons: SEQUENCE
+ 47:d=3 hl=2 l= 77 cons: SEQUENCE
+ 49:d=4 hl=2 l= 56 cons: SEQUENCE
+ 51:d=5 hl=2 l= 7 cons: SEQUENCE
+ 53:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 60:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 82:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 104:d=5 hl=2 l= 1 prim: INTEGER :03
+ 107:d=4 hl=2 l= 0 prim: cont [ 0 ]
+ 109:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 126:d=1 hl=2 l= 13 cons: SEQUENCE
+ 128:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 139:d=2 hl=2 l= 0 prim: NULL
+ 141:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBKwoBAKCCASQwggEgBgkrBgEFBQcwAQEEggERMIIBDTB4oRQwEjEQMA4GA1UEAxMHVGVzdCB
+DQRgPMjAxNjAzMDQxNjQwMDJaME8wTTA4MAcGBSsOAwIaBBQC/3XaJN6K3RUPq2idzObmY20JAQ
+QUdzWstN/nudyCWTgbfu3wiCuXNTQCAQOAABgPMjAxNjAzMDQxNjQwMDJaMA0GCSqGSIb3DQEBB
+QUAA4GBAEaH8xtlTUtrtKBa/dKPjWhP5dl+FQMVmCpKVGYVkh+mq/mltWcFgqmVr2uMuCngTIXg
+xXd9xzvdjl3Y8PqbFXd2267ZQ5JWLkyU1FFxOYRQsjNZD45AnPmXUeHTJ+KqvmIoduFMc2O42RK
+/bUfjrcMZcpbblnbPReAfYUsUaiCE
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/revoke_response.pem b/chromium/net/data/parse_ocsp_unittest/revoke_response.pem
new file mode 100644
index 00000000000..dfeb6b1fe34
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/revoke_response.pem
@@ -0,0 +1,124 @@
+Is a REVOKE response for the cert
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 317 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 310 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 306 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 291 prim: OCTET STRING
+ 0:d=0 hl=4 l= 287 cons: SEQUENCE
+ 4:d=1 hl=3 l= 137 cons: SEQUENCE
+ 7:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 9:d=3 hl=2 l= 18 cons: SEQUENCE
+ 11:d=4 hl=2 l= 16 cons: SET
+ 13:d=5 hl=2 l= 14 cons: SEQUENCE
+ 15:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 20:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 29:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 46:d=2 hl=2 l= 96 cons: SEQUENCE
+ 48:d=3 hl=2 l= 94 cons: SEQUENCE
+ 50:d=4 hl=2 l= 56 cons: SEQUENCE
+ 52:d=5 hl=2 l= 7 cons: SEQUENCE
+ 54:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 61:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 83:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 105:d=5 hl=2 l= 1 prim: INTEGER :03
+ 108:d=4 hl=2 l= 17 cons: cont [ 1 ]
+ 110:d=5 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 127:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 144:d=1 hl=2 l= 13 cons: SEQUENCE
+ 146:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 157:d=2 hl=2 l= 0 prim: NULL
+ 159:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBPQoBAKCCATYwggEyBgkrBgEFBQcwAQEEggEjMIIBHzCBiaEUMBIxEDAOBgNVBAMTB1Rlc3Q
+gQ0EYDzIwMTYwMzA0MTY0MDAyWjBgMF4wODAHBgUrDgMCGgQUAv912iTeit0VD6tonczm5mNtCQ
+EEFHc1rLTf57ncglk4G37t8IgrlzU0AgEDoREYDzIwMTYwMzA0MTY0MDAyWhgPMjAxNjAzMDQxN
+jQwMDJaMA0GCSqGSIb3DQEBBQUAA4GBAA1dkQpeYy4+X5lBJfNwWY7W9AKtDHgLzI4kxhGmPfsF
+EGVlnyrHpTHP04csXfnW4oF/xK5wpN+3jMDNxoShEZR/OBcfGw0XDZm8ttSOAjHeloPpnO3ozTq
+Zvw+sMIEpWuygFcYMHJ7CnJycYS01A+is5GqCBuRyvXCxv5bVrEu4
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/revoke_response_reason.pem b/chromium/net/data/parse_ocsp_unittest/revoke_response_reason.pem
new file mode 100644
index 00000000000..0abcecf9c5d
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/revoke_response_reason.pem
@@ -0,0 +1,126 @@
+Is a REVOKE response for the cert with a reason
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 322 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 315 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 311 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 296 prim: OCTET STRING
+ 0:d=0 hl=4 l= 292 cons: SEQUENCE
+ 4:d=1 hl=3 l= 142 cons: SEQUENCE
+ 7:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 9:d=3 hl=2 l= 18 cons: SEQUENCE
+ 11:d=4 hl=2 l= 16 cons: SET
+ 13:d=5 hl=2 l= 14 cons: SEQUENCE
+ 15:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 20:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 29:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 46:d=2 hl=2 l= 101 cons: SEQUENCE
+ 48:d=3 hl=2 l= 99 cons: SEQUENCE
+ 50:d=4 hl=2 l= 56 cons: SEQUENCE
+ 52:d=5 hl=2 l= 7 cons: SEQUENCE
+ 54:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 61:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 83:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 105:d=5 hl=2 l= 1 prim: INTEGER :03
+ 108:d=4 hl=2 l= 22 cons: cont [ 1 ]
+ 110:d=5 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 127:d=5 hl=2 l= 3 cons: cont [ 0 ]
+ 129:d=6 hl=2 l= 1 prim: ENUMERATED :01
+ 132:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 149:d=1 hl=2 l= 13 cons: SEQUENCE
+ 151:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 162:d=2 hl=2 l= 0 prim: NULL
+ 164:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBQgoBAKCCATswggE3BgkrBgEFBQcwAQEEggEoMIIBJDCBjqEUMBIxEDAOBgNVBAMTB1Rlc3Q
+gQ0EYDzIwMTYwMzA0MTY0MDAyWjBlMGMwODAHBgUrDgMCGgQUAv912iTeit0VD6tonczm5mNtCQ
+EEFHc1rLTf57ncglk4G37t8IgrlzU0AgEDoRYYDzIwMTYwMzA0MTY0MDAyWqADCgEBGA8yMDE2M
+DMwNDE2NDAwMlowDQYJKoZIhvcNAQEFBQADgYEAdJ2fItNUjBLpAUqtph3z6OGWnlilggMBSayg
+rAWg/BgxKgxoBv/WXMKgjWKJw2/+gdqXsiXxQiunSvCKK4t7ghhTvelofc5R1KUO3zPU95tsMPX
+r1PXdp0BSkt+03qWhiB3xyIboZJp1esjcnGnBC3lQD39V7n28AXW+17n73/Q=
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/parse_ocsp_unittest/unknown_response.pem b/chromium/net/data/parse_ocsp_unittest/unknown_response.pem
new file mode 100644
index 00000000000..f19d37a1735
--- /dev/null
+++ b/chromium/net/data/parse_ocsp_unittest/unknown_response.pem
@@ -0,0 +1,123 @@
+Is an UNKNOWN response for the cert
+$ openssl asn1parse -i < [OCSP RESPONSE]
+ 0:d=0 hl=4 l= 299 cons: SEQUENCE
+ 4:d=1 hl=2 l= 1 prim: ENUMERATED :00
+ 7:d=1 hl=4 l= 292 cons: cont [ 0 ]
+ 11:d=2 hl=4 l= 288 cons: SEQUENCE
+ 15:d=3 hl=2 l= 9 prim: OBJECT :Basic OCSP Response
+ 26:d=3 hl=4 l= 273 prim: OCTET STRING
+ 0:d=0 hl=4 l= 269 cons: SEQUENCE
+ 4:d=1 hl=2 l= 120 cons: SEQUENCE
+ 6:d=2 hl=2 l= 20 cons: cont [ 1 ]
+ 8:d=3 hl=2 l= 18 cons: SEQUENCE
+ 10:d=4 hl=2 l= 16 cons: SET
+ 12:d=5 hl=2 l= 14 cons: SEQUENCE
+ 14:d=6 hl=2 l= 3 prim: OBJECT :commonName
+ 19:d=6 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 28:d=2 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 45:d=2 hl=2 l= 79 cons: SEQUENCE
+ 47:d=3 hl=2 l= 77 cons: SEQUENCE
+ 49:d=4 hl=2 l= 56 cons: SEQUENCE
+ 51:d=5 hl=2 l= 7 cons: SEQUENCE
+ 53:d=6 hl=2 l= 5 prim: OBJECT :sha1
+ 60:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:02FF75DA24DE8ADD150FAB689DCCE6E6636D0901
+ 82:d=5 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:7735ACB4DFE7B9DC8259381B7EEDF0882B973534
+ 104:d=5 hl=2 l= 1 prim: INTEGER :03
+ 107:d=4 hl=2 l= 0 prim: cont [ 2 ]
+ 109:d=4 hl=2 l= 15 prim: GENERALIZEDTIME :20160304164002Z
+ 126:d=1 hl=2 l= 13 cons: SEQUENCE
+ 128:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 139:d=2 hl=2 l= 0 prim: NULL
+ 141:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN OCSP RESPONSE-----
+MIIBKwoBAKCCASQwggEgBgkrBgEFBQcwAQEEggERMIIBDTB4oRQwEjEQMA4GA1UEAxMHVGVzdCB
+DQRgPMjAxNjAzMDQxNjQwMDJaME8wTTA4MAcGBSsOAwIaBBQC/3XaJN6K3RUPq2idzObmY20JAQ
+QUdzWstN/nudyCWTgbfu3wiCuXNTQCAQOCABgPMjAxNjAzMDQxNjQwMDJaMA0GCSqGSIb3DQEBB
+QUAA4GBADKSl26nGkptHNremzcuCoEVLVCrOT7EjBpbCktlga4QNAuMaOCwWccIa+yfxCQ1O04M
+jx0vbOWqTSZG/dRCgJYzGV007KNKxEOuQALdwtjrjNg89VZ+VaDp/zJEGO5LqOUdawiwbVxjQK1
+hcwGkVxiFuibzzZKeQf2/xf3jaMWy
+-----END OCSP RESPONSE-----
+
+$ openssl asn1parse -i < [CA CERTIFICATE]
+ 0:d=0 hl=4 l= 408 cons: SEQUENCE
+ 4:d=1 hl=4 l= 257 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :00
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 18 cons: SEQUENCE
+ 85:d=3 hl=2 l= 16 cons: SET
+ 87:d=4 hl=2 l= 14 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 103:d=2 hl=3 l= 159 cons: SEQUENCE
+ 106:d=3 hl=2 l= 13 cons: SEQUENCE
+ 108:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 119:d=4 hl=2 l= 0 prim: NULL
+ 121:d=3 hl=3 l= 141 prim: BIT STRING
+ 265:d=1 hl=2 l= 13 cons: SEQUENCE
+ 267:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 278:d=2 hl=2 l= 0 prim: NULL
+ 280:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CA CERTIFICATE-----
+MIIBmDCCAQGgAwIBAgIBADANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowEjEQMA4GA1UEAxMHVGVzdCBDQTCBnzANBgkqhk
+iG9w0BAQEFAAOBjQAwgYkCgYEAxN8IR7ey6jTVUyS6kkCqt2x9/mxnRz77Py6Kwdm3P9jqIwqrC
+RuqAXfC5QcyeyUaXKCc49bmL7cy64UowTrnIjyqiYOX0VO6t3ZdKcy2/8U2uwdL5oZPlBkpI6mU
+7vl+3rKbKkNPNPLv8apwFF1zIHUm1tund152PlMAWQu6rmUCAwEAATANBgkqhkiG9w0BAQUFAAO
+BgQCYaWdjhx0ARGhs1Dj1N6RXIf0U669nJcx0XkuC/yL5Ji16cjI1s76arVjGK7OPZ011x4/gNM
+RLj31wyxKsfg3qQdlYkVl89CwtA+KxghQoRhD8cSWY1aOQcm4hM11HE5t5VyNbheSOBVwoOb8wO
+cgZFERfCNWbcx2a3WYVJCGoUw==
+-----END CA CERTIFICATE-----
+
+$ openssl asn1parse -i < [CERTIFICATE]
+ 0:d=0 hl=4 l= 410 cons: SEQUENCE
+ 4:d=1 hl=4 l= 259 cons: SEQUENCE
+ 8:d=2 hl=2 l= 3 cons: cont [ 0 ]
+ 10:d=3 hl=2 l= 1 prim: INTEGER :02
+ 13:d=2 hl=2 l= 1 prim: INTEGER :03
+ 16:d=2 hl=2 l= 13 cons: SEQUENCE
+ 18:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 29:d=3 hl=2 l= 0 prim: NULL
+ 31:d=2 hl=2 l= 18 cons: SEQUENCE
+ 33:d=3 hl=2 l= 16 cons: SET
+ 35:d=4 hl=2 l= 14 cons: SEQUENCE
+ 37:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 42:d=5 hl=2 l= 7 prim: PRINTABLESTRING :Test CA
+ 51:d=2 hl=2 l= 30 cons: SEQUENCE
+ 53:d=3 hl=2 l= 13 prim: UTCTIME :160304214002Z
+ 68:d=3 hl=2 l= 13 prim: UTCTIME :260302214002Z
+ 83:d=2 hl=2 l= 20 cons: SEQUENCE
+ 85:d=3 hl=2 l= 18 cons: SET
+ 87:d=4 hl=2 l= 16 cons: SEQUENCE
+ 89:d=5 hl=2 l= 3 prim: OBJECT :commonName
+ 94:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Test Cert
+ 105:d=2 hl=3 l= 159 cons: SEQUENCE
+ 108:d=3 hl=2 l= 13 cons: SEQUENCE
+ 110:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 121:d=4 hl=2 l= 0 prim: NULL
+ 123:d=3 hl=3 l= 141 prim: BIT STRING
+ 267:d=1 hl=2 l= 13 cons: SEQUENCE
+ 269:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
+ 280:d=2 hl=2 l= 0 prim: NULL
+ 282:d=1 hl=3 l= 129 prim: BIT STRING
+-----BEGIN CERTIFICATE-----
+MIIBmjCCAQOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE
+2MDMwNDIxNDAwMloXDTI2MDMwMjIxNDAwMlowFDESMBAGA1UEAxMJVGVzdCBDZXJ0MIGfMA0GCS
+qGSIb3DQEBAQUAA4GNADCBiQKBgQCynU7qbknY0uuN2uYvVj9/UeLaZ+GTuIICagyaSvwhDdEFI
+ieSELYv5c3TlrIzAzuMlx78eOuhyxyL5SqDe1+YrD4tsHTMoWhSsmjRmKHpxfVScPwgBvnZ3i5d
+jS/iLKlvoTnH8qPE2QC+B2GgoU8HFEaVg5jI1NACo5gh75ZAawIDAQABMA0GCSqGSIb3DQEBBQU
+AA4GBAHSL52wcNMvGbcbSI3fZd9ckcx2Kgor0/FZOcjWFaI877E9ok7TGk1uwy5QsTcRZdEuCsl
+3Ph9kpZYkiB6JIGrEzvmE5Nmv8VmYtEAX4F1JX6WPETlRR95fA4D4WmHNb2bxBy8bP9wLpced2V
+42JEeS36VZs/yhLupvaLx9PcRwM
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/favicon.ico b/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/favicon.ico
new file mode 100644
index 00000000000..a559c5856e1
--- /dev/null
+++ b/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/favicon.ico
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
new file mode 100644
index 00000000000..d13a4d0258a
--- /dev/null
+++ b/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index.html
@@ -0,0 +1,15 @@
+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/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index2.html b/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index2.html
new file mode 100644
index 00000000000..74afa66a0bb
--- /dev/null
+++ b/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/index2.html
@@ -0,0 +1,16 @@
+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/index2.html
+X-Push-Url: https://quic.test.url/kitten-1.jpg
+X-Push-Url: https://quic.test.url/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_in_memory_cache_data_with_push/quic-datatesturl.com/kitten-1.jpg
new file mode 100644
index 00000000000..25ba08a5635
--- /dev/null
+++ b/chromium/net/data/quic_in_memory_cache_data_with_push/quic-datatesturl.com/kitten-1.jpg
Binary files differ
diff --git a/chromium/net/data/ssl/blacklist/0d136e439f0ab6e97f3a02a540da9f0641aa554e1d66ea51ae2920d51b2f7217.pem b/chromium/net/data/ssl/blacklist/0d136e439f0ab6e97f3a02a540da9f0641aa554e1d66ea51ae2920d51b2f7217.pem
new file mode 100644
index 00000000000..45994598880
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/0d136e439f0ab6e97f3a02a540da9f0641aa554e1d66ea51ae2920d51b2f7217.pem
@@ -0,0 +1,120 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 0c:76:da:9c:91:0c:4e:2c:9e:fe:15:d0:58:93:3c:4c
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=NL, O=DigiNotar, CN=DigiNotar Root CA/emailAddress=info@diginotar.nl
+ Validity
+ Not Before: May 16 17:19:36 2007 GMT
+ Not After : Mar 31 18:19:21 2025 GMT
+ Subject: C=NL, O=DigiNotar, CN=DigiNotar Root CA/emailAddress=info@diginotar.nl
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:ac:b0:58:c1:00:bd:d8:21:08:0b:2b:9a:fe:6e:
+ 56:30:05:9f:1b:77:90:10:41:5c:c3:0d:87:11:77:
+ 8e:81:f1:ca:7c:e9:8c:6a:ed:38:74:35:bb:da:df:
+ f9:bb:c0:09:37:b4:96:73:81:7d:33:1a:98:39:f7:
+ 93:6f:95:7f:3d:b9:b1:75:87:ba:51:48:e8:8b:70:
+ 3e:95:04:c5:d8:b6:c3:16:d9:88:b0:b1:87:1d:70:
+ da:86:b4:0f:14:8b:7a:cf:10:d1:74:36:a2:12:7b:
+ 77:86:4a:79:e6:7b:df:02:11:68:a5:4e:86:ae:34:
+ 58:9b:24:13:78:56:22:25:1e:01:8b:4b:51:71:fb:
+ 82:cc:59:96:69:88:5a:68:53:c5:b9:0d:02:37:cb:
+ 4b:bc:66:4a:90:7e:2a:0b:05:07:ed:16:5f:55:90:
+ 75:d8:46:c9:1b:83:e2:08:be:f1:23:cc:99:1d:d6:
+ 2a:0f:83:20:15:58:27:82:2e:fa:e2:22:c2:49:b1:
+ b9:01:81:6a:9d:6d:9d:40:77:68:76:4e:21:2a:6d:
+ 84:40:85:4e:76:99:7c:82:f3:f3:b7:02:59:d4:26:
+ 01:1b:8e:df:ad:53:06:d1:ae:18:dd:e2:b2:3a:cb:
+ d7:88:38:8e:ac:5b:29:b9:19:d3:98:f9:18:03:cf:
+ 48:82:86:66:0b:1b:69:0f:c9:eb:38:88:7a:26:1a:
+ 05:4c:92:d7:24:d4:96:f2:ac:52:2d:a3:47:d5:52:
+ f6:3f:fe:ce:84:06:70:a6:aa:3e:a2:f2:b6:56:34:
+ 18:57:a2:e4:81:6d:e7:ca:f0:6a:d3:c7:91:6b:02:
+ 83:41:7c:15:ef:6b:9a:64:5e:e3:d0:3c:e5:b1:eb:
+ 7b:5d:86:fb:cb:e6:77:49:cd:a3:65:dc:f7:b9:9c:
+ b8:e4:0b:5f:93:cf:cc:30:1a:32:1c:ce:1c:63:95:
+ a5:f9:ea:e1:74:8b:9e:e9:2b:a9:30:7b:a0:18:1f:
+ 0e:18:0b:e5:5b:a9:d3:d1:6c:1e:07:67:8f:91:4b:
+ a9:8a:bc:d2:66:aa:93:01:88:b2:91:fa:31:5c:d5:
+ a6:c1:52:08:09:cd:0a:63:a2:d3:22:a6:e8:a1:d9:
+ 39:06:97:f5:6e:8d:02:90:8c:14:7b:3f:80:cd:1b:
+ 9c:ba:c4:58:72:23:af:b6:56:9f:c6:7a:42:33:29:
+ 07:3f:82:c9:e6:1f:05:0d:cd:4c:28:36:8b:d3:c8:
+ 3e:1c:c6:88:ef:5e:ee:89:64:e9:1d:eb:da:89:7e:
+ 32:a6:69:d1:dd:cc:88:9f:d1:d0:c9:66:21:dc:06:
+ 67:c5:94:7a:9a:6d:62:4c:7d:cc:e0:64:80:b2:9e:
+ 47:8e:a3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 88:68:BF:E0:8E:35:C4:3B:38:6B:62:F7:28:3B:84:81:C8:0C:D7:4D
+ Signature Algorithm: sha1WithRSAEncryption
+ 3b:02:8d:cb:3c:30:e8:6e:a0:ad:f2:73:b3:5f:9e:25:13:04:
+ 05:d3:f6:e3:8b:bb:0b:79:ce:53:de:e4:96:c5:d1:af:73:bc:
+ d5:c3:d0:40:55:7c:40:7f:cd:1b:5f:09:d5:f2:7c:9f:68:1d:
+ bb:5d:ce:7a:39:c2:8c:d6:98:7b:c5:83:55:a8:d5:7d:40:ca:
+ e0:1e:f7:89:5e:63:5d:a1:13:c2:5d:8a:b6:8a:7c:00:f3:23:
+ c3:ed:85:5f:71:76:f0:68:63:aa:45:21:39:48:61:78:36:dc:
+ f1:43:93:d4:25:c7:f2:80:65:e1:53:02:75:51:fc:7a:3a:ef:
+ 37:ab:84:28:57:0c:d8:d4:d4:99:56:6c:e3:a2:fe:59:84:b4:
+ 31:e8:33:f8:64:94:94:51:97:ab:39:c5:4b:ed:da:dd:80:0b:
+ 6f:7c:29:0d:c4:8e:8a:72:0d:e7:53:14:b2:60:41:3d:84:91:
+ 31:68:3d:27:44:db:e5:de:f4:fa:63:45:c8:4c:3e:98:f5:3f:
+ 41:ba:4e:cb:37:0d:ba:66:98:f1:dd:cb:9f:5c:f7:54:36:82:
+ 6b:2c:bc:13:61:97:42:f8:78:bb:cc:c8:a2:9f:ca:f0:68:bd:
+ 6b:1d:b2:df:8d:6f:07:9d:da:8e:67:c7:47:1e:ca:b9:bf:2a:
+ 42:91:b7:63:53:66:f1:42:a3:e1:f4:5a:4d:58:6b:b5:e4:a4:
+ 33:ad:5c:70:1d:dc:e0:f2:eb:73:14:91:9a:03:c1:ea:00:65:
+ bc:07:fc:cf:12:11:22:2c:ae:a0:bd:3a:e0:a2:2a:d8:59:e9:
+ 29:d3:18:35:a4:ac:11:5f:19:b5:b5:1b:ff:22:4a:5c:c6:7a:
+ e4:17:ef:20:a9:a7:f4:3f:ad:8a:a7:9a:04:25:9d:0e:ca:37:
+ e6:50:fd:8c:42:29:04:9a:ec:b9:cf:4b:72:bd:e2:08:36:af:
+ 23:2f:62:e5:ca:01:d3:70:db:7c:82:23:2c:16:31:0c:c6:36:
+ 07:90:7a:b1:1f:67:58:c4:3b:58:59:89:b0:8c:8c:50:b3:d8:
+ 86:cb:68:a3:c4:0a:e7:69:4b:20:ce:c1:1e:56:4b:95:a9:23:
+ 68:d8:30:d8:c3:eb:b0:55:51:cd:e5:fd:2b:b8:f5:bb:11:9f:
+ 53:54:f6:34:19:8c:79:09:36:ca:61:17:25:17:0b:82:98:73:
+ 0c:77:74:c3:d5:0d:c7:a8:12:4c:c7:a7:54:71:47:2e:2c:1a:
+ 7d:c9:e3:2b:3b:48:de:27:84:a7:63:36:b3:7d:8f:a0:64:39:
+ 24:0d:3d:7b:87:af:66:5c:74:1b:4b:73:b2:e5:8c:f0:86:99:
+ b8:e5:c5:df:84:c1:b7:eb
+-----BEGIN CERTIFICATE-----
+MIIFijCCA3KgAwIBAgIQDHbanJEMTiye/hXQWJM8TDANBgkqhkiG9w0BAQUFADBf
+MQswCQYDVQQGEwJOTDESMBAGA1UEChMJRGlnaU5vdGFyMRowGAYDVQQDExFEaWdp
+Tm90YXIgUm9vdCBDQTEgMB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmww
+HhcNMDcwNTE2MTcxOTM2WhcNMjUwMzMxMTgxOTIxWjBfMQswCQYDVQQGEwJOTDES
+MBAGA1UEChMJRGlnaU5vdGFyMRowGAYDVQQDExFEaWdpTm90YXIgUm9vdCBDQTEg
+MB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmwwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCssFjBAL3YIQgLK5r+blYwBZ8bd5AQQVzDDYcRd46B
+8cp86Yxq7Th0Nbva3/m7wAk3tJZzgX0zGpg595NvlX89ubF1h7pRSOiLcD6VBMXY
+tsMW2YiwsYcdcNqGtA8Ui3rPENF0NqISe3eGSnnme98CEWilToauNFibJBN4ViIl
+HgGLS1Fx+4LMWZZpiFpoU8W5DQI3y0u8ZkqQfioLBQftFl9VkHXYRskbg+IIvvEj
+zJkd1ioPgyAVWCeCLvriIsJJsbkBgWqdbZ1Ad2h2TiEqbYRAhU52mXyC8/O3AlnU
+JgEbjt+tUwbRrhjd4rI6y9eIOI6sWym5GdOY+RgDz0iChmYLG2kPyes4iHomGgVM
+ktck1JbyrFIto0fVUvY//s6EBnCmqj6i8rZWNBhXouSBbefK8GrTx5FrAoNBfBXv
+a5pkXuPQPOWx63tdhvvL5ndJzaNl3Pe5nLjkC1+Tz8wwGjIczhxjlaX56uF0i57p
+K6kwe6AYHw4YC+VbqdPRbB4HZ4+RS6mKvNJmqpMBiLKR+jFc1abBUggJzQpjotMi
+puih2TkGl/VujQKQjBR7P4DNG5y6xFhyI6+2Vp/GekIzKQc/gsnmHwUNzUwoNovT
+yD4cxojvXu6JZOkd69qJfjKmadHdzIif0dDJZiHcBmfFlHqabWJMfczgZICynkeO
+owIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
+HQ4EFgQUiGi/4I41xDs4a2L3KDuEgcgM100wDQYJKoZIhvcNAQEFBQADggIBADsC
+jcs8MOhuoK3yc7NfniUTBAXT9uOLuwt5zlPe5JbF0a9zvNXD0EBVfEB/zRtfCdXy
+fJ9oHbtdzno5wozWmHvFg1Wo1X1AyuAe94leY12hE8JdiraKfADzI8PthV9xdvBo
+Y6pFITlIYXg23PFDk9Qlx/KAZeFTAnVR/Ho67zerhChXDNjU1JlWbOOi/lmEtDHo
+M/hklJRRl6s5xUvt2t2AC298KQ3EjopyDedTFLJgQT2EkTFoPSdE2+Xe9PpjRchM
+Ppj1P0G6Tss3DbpmmPHdy59c91Q2gmssvBNhl0L4eLvMyKKfyvBovWsdst+Nbwed
+2o5nx0ceyrm/KkKRt2NTZvFCo+H0Wk1Ya7XkpDOtXHAd3ODy63MUkZoDweoAZbwH
+/M8SESIsrqC9OuCiKthZ6SnTGDWkrBFfGbW1G/8iSlzGeuQX7yCpp/Q/rYqnmgQl
+nQ7KN+ZQ/YxCKQSa7LnPS3K94gg2ryMvYuXKAdNw23yCIywWMQzGNgeQerEfZ1jE
+O1hZibCMjFCz2IbLaKPECudpSyDOwR5WS5WpI2jYMNjD67BVUc3l/Su49bsRn1NU
+9jQZjHkJNsphFyUXC4KYcwx3dMPVDceoEkzHp1RxRy4sGn3J4ys7SN4nhKdjNrN9
+j6BkOSQNPXuHr2ZcdBtLc7LljPCGmbjlxd+Ewbfr
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/0f912fd7be760be25afbc56bdc09cd9e5dcc9c6f6a55a778aefcb6aa30e31554.pem b/chromium/net/data/ssl/blacklist/0f912fd7be760be25afbc56bdc09cd9e5dcc9c6f6a55a778aefcb6aa30e31554.pem
new file mode 100644
index 00000000000..079f0ee8345
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/0f912fd7be760be25afbc56bdc09cd9e5dcc9c6f6a55a778aefcb6aa30e31554.pem
@@ -0,0 +1,120 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ (Negative)5b:b3:c7:b8:07:11:8e:7f:bc:b2:4e:7f:46:58:16:9e
+ Signature Algorithm: sha512WithRSAEncryption
+ Issuer: OU=DSDTestProvider, O=DSDTestProvider, CN=DSDTestProvider
+ Validity
+ Not Before: May 27 13:36:18 2015 GMT
+ Not After : Dec 31 23:59:59 2039 GMT
+ Subject: OU=DSDTestProvider, O=DSDTestProvider, CN=DSDTestProvider
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:dd:26:a5:82:03:0b:93:1d:31:2c:7f:65:f8:31:
+ 51:f2:72:e0:48:e9:b8:7b:b1:72:46:44:ca:01:30:
+ 72:e8:18:46:39:04:5b:8f:d4:df:c8:83:d8:8f:74:
+ 2b:99:ba:21:5b:f5:e8:ce:d3:d5:a2:06:6f:29:fe:
+ 08:8a:85:07:41:99:8f:f5:23:1a:23:9e:82:39:82:
+ 73:02:e0:b9:77:c5:4e:ec:e3:94:6c:1a:37:79:fd:
+ 82:71:94:22:b0:78:17:dd:54:9c:01:52:71:d2:f5:
+ 4a:2b:a6:99:ca:35:8f:9e:c4:28:a8:ef:fd:b6:1a:
+ e5:50:a4:81:37:f0:96:ec:f7:40:b7:36:43:bf:66:
+ e9:2f:1b:d7:bc:a2:06:4e:3d:56:eb:68:64:5d:51:
+ ec:e4:8f:88:b9:d1:28:a6:9c:92:a4:84:8d:a8:9f:
+ bd:c0:19:3d:ed:e4:9e:02:95:e5:d0:bd:58:dc:ea:
+ 9c:7e:3e:f9:b4:96:66:d4:ed:3d:95:ef:1f:06:0a:
+ 10:31:e2:c7:40:e2:e9:68:b6:a9:bf:3d:e1:b3:57:
+ 27:2c:2a:a9:1e:d2:89:bd:57:66:3f:f3:15:76:5f:
+ 85:d4:84:a7:27:08:4f:d3:32:d1:09:7a:af:ca:58:
+ 57:7f:6d:06:31:bd:1e:0f:14:70:4d:e7:83:c8:de:
+ e8:77:b5:54:15:9d:76:e0:18:88:4f:99:4e:4f:88:
+ e7:86:c6:e5:71:e1:42:49:53:da:a7:80:01:2f:7e:
+ 34:f2:65:78:29:9f:9e:16:20:6f:ac:21:e7:7b:16:
+ 13:4c:06:e8:eb:46:4e:24:89:f9:32:c4:9f:d0:28:
+ 45:3d:1c:b6:b3:cb:44:49:26:0d:b5:d7:ad:d3:af:
+ 54:cd:d8:ec:a8:e1:5b:39:9e:4b:6f:1c:1b:6b:81:
+ 8a:39:b2:a6:7c:ba:66:b5:b0:82:70:66:e7:7a:f7:
+ 1a:f5:fc:35:c6:46:97:10:09:b3:7e:c9:42:8d:c4:
+ b4:ad:a4:ff:e8:2f:69:3c:9c:08:4c:d9:48:81:7a:
+ 9b:d7:6e:6f:46:52:dc:42:dc:98:9b:05:92:c3:9e:
+ 1e:3a:6a:b0:c0:91:0c:ec:c7:68:07:33:7f:76:22:
+ 57:ee:3e:db:a1:7e:3c:95:04:4a:6f:b9:b7:66:32:
+ c8:bf:f9:d2:62:54:96:92:ce:bb:44:c9:bb:4f:59:
+ a5:a3:f5:29:35:28:b4:c4:9d:20:1e:ca:3d:cd:34:
+ 4e:ba:24:c7:dc:b9:89:29:d4:99:fc:57:18:49:9f:
+ 81:70:44:50:03:5d:d4:a4:08:a6:54:3f:9a:3b:d7:
+ 5f:79:97:56:d4:76:e0:5f:3b:78:fe:35:50:0c:0c:
+ c6:78:e3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ 2.5.29.1:
+ 0v.....O.}...dr..n$..P0N1.0...U....DSDTestProvider1.0...U.
+..DSDTestProvider1.0...U....DSDTestProvider...L8G..q.CM.....b
+ Signature Algorithm: sha512WithRSAEncryption
+ 4a:17:5c:46:bc:5a:a4:c1:86:ca:77:04:c1:74:45:45:42:00:
+ e9:17:3a:17:05:41:42:65:79:e7:b0:23:48:b2:20:fb:6e:e0:
+ 4f:63:44:79:88:b8:b0:0b:41:5a:bb:a5:39:0f:9c:a9:b0:40:
+ e2:84:bc:86:ff:86:94:1f:52:a1:8f:9e:9d:08:e8:7a:4a:e4:
+ d5:bf:81:49:4f:b7:78:5e:10:73:d1:a9:17:02:53:55:96:ed:
+ bd:f6:82:d1:50:32:97:23:b9:da:d4:e6:8d:07:ec:57:21:66:
+ 94:9b:3b:0f:a1:6c:b3:14:db:c5:84:0f:82:c6:b4:88:1b:24:
+ 6e:a8:ef:56:38:1a:7d:99:66:e0:cc:30:eb:2b:e6:0f:27:2d:
+ f4:0b:28:cd:98:76:fe:54:f7:fc:5e:72:19:e5:b7:94:ac:5d:
+ 5c:a9:50:ea:8a:8a:08:28:2d:df:9a:86:bf:ac:54:a0:5c:c5:
+ 9d:b7:42:32:ab:f7:20:f0:a6:d5:f1:cd:34:bb:bc:a1:3b:62:
+ 64:d3:1c:df:f9:f4:9b:9c:25:15:09:31:a0:3b:b0:e9:bc:33:
+ 6f:23:f0:fa:95:8e:b4:8f:c4:70:b9:5f:0d:db:9a:aa:93:09:
+ 9a:2c:63:84:22:01:52:35:18:5f:a2:ac:3e:13:7e:61:03:3c:
+ 01:3a:2b:22:a0:53:9c:4e:35:42:b5:c7:76:d4:0c:58:1d:aa:
+ c8:b5:7b:34:8d:9c:c2:a4:20:f6:0d:23:fe:67:a9:bd:28:41:
+ 7f:be:19:50:b7:2b:3d:c1:18:95:3d:65:5a:7c:88:63:13:e8:
+ 34:fd:f9:09:ec:2f:05:08:84:8e:8b:38:01:3d:9b:bd:08:0e:
+ b9:b7:82:7c:86:13:76:dd:5c:1c:99:13:71:b8:b1:7b:4a:9f:
+ 86:8d:a9:1d:86:a9:0b:97:38:f8:9e:36:e6:c2:42:38:3a:52:
+ bd:ee:f7:e7:19:d4:69:56:d7:f4:c1:f5:22:2c:71:ae:87:03:
+ aa:7d:ef:e1:e3:5b:47:8d:72:c1:01:b0:9a:1a:57:a9:ab:7f:
+ 5d:9d:35:27:d1:03:55:e5:57:f4:9a:40:36:fd:77:a1:36:0f:
+ 65:1a:d2:48:4a:c0:c9:a0:7b:8b:52:f5:77:2b:d1:53:ec:04:
+ 50:e4:ff:cb:83:14:0b:1f:a3:43:32:71:fc:97:ab:9b:b5:73:
+ 53:cd:82:f6:4e:17:be:ef:ac:a7:ce:e5:6d:a2:00:18:24:e6:
+ e3:d2:e2:04:da:a1:20:20:87:bf:1e:7e:64:c1:27:1c:5c:ff:
+ 5d:83:ef:42:8a:61:86:b4:73:21:6c:38:af:d3:f9:2f:9a:76:
+ e9:bc:bd:5d:c1:7a:d0:7a
+-----BEGIN CERTIFICATE-----
+MIIFvDCCA6SgAwIBAgIQpEw4R/jucYBDTbGAuafpYjANBgkqhkiG9w0BAQ0FADBO
+MRgwFgYDVQQLEw9EU0RUZXN0UHJvdmlkZXIxGDAWBgNVBAoTD0RTRFRlc3RQcm92
+aWRlcjEYMBYGA1UEAxMPRFNEVGVzdFByb3ZpZGVyMB4XDTE1MDUyNzEzMzYxOFoX
+DTM5MTIzMTIzNTk1OVowTjEYMBYGA1UECxMPRFNEVGVzdFByb3ZpZGVyMRgwFgYD
+VQQKEw9EU0RUZXN0UHJvdmlkZXIxGDAWBgNVBAMTD0RTRFRlc3RQcm92aWRlcjCC
+AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAN0mpYIDC5MdMSx/ZfgxUfJy
+4EjpuHuxckZEygEwcugYRjkEW4/U38iD2I90K5m6IVv16M7T1aIGbyn+CIqFB0GZ
+j/UjGiOegjmCcwLguXfFTuzjlGwaN3n9gnGUIrB4F91UnAFScdL1Siummco1j57E
+KKjv/bYa5VCkgTfwluz3QLc2Q79m6S8b17yiBk49VutoZF1R7OSPiLnRKKackqSE
+jaifvcAZPe3kngKV5dC9WNzqnH4++bSWZtTtPZXvHwYKEDHix0Di6Wi2qb894bNX
+JywqqR7Sib1XZj/zFXZfhdSEpycIT9My0Ql6r8pYV39tBjG9Hg8UcE3ng8je6He1
+VBWdduAYiE+ZTk+I54bG5XHhQklT2qeAAS9+NPJleCmfnhYgb6wh53sWE0wG6OtG
+TiSJ+TLEn9AoRT0ctrPLREkmDbXXrdOvVM3Y7KjhWzmeS28cG2uBijmypny6ZrWw
+gnBm53r3GvX8NcZGlxAJs37JQo3EtK2k/+gvaTycCEzZSIF6m9dub0ZS3ELcmJsF
+ksOeHjpqsMCRDOzHaAczf3YiV+4+26F+PJUESm+5t2YyyL/50mJUlpLOu0TJu09Z
+paP1KTUotMSdIB7KPc00Trokx9y5iSnUmfxXGEmfgXBEUANd1KQIplQ/mjvXX3mX
+VtR24F87eP41UAwMxnjjAgMBAAGjgZUwgZIwDwYDVR0TAQH/BAUwAwEB/zB/BgNV
+HQEEeDB2gBDitI1Pkn2AA6NkchDgbiTQoVAwTjEYMBYGA1UECxMPRFNEVGVzdFBy
+b3ZpZGVyMRgwFgYDVQQKEw9EU0RUZXN0UHJvdmlkZXIxGDAWBgNVBAMTD0RTRFRl
+c3RQcm92aWRlcoIQpEw4R/jucYBDTbGAuafpYjANBgkqhkiG9w0BAQ0FAAOCAgEA
+ShdcRrxapMGGyncEwXRFRUIA6Rc6FwVBQmV557AjSLIg+27gT2NEeYi4sAtBWrul
+OQ+cqbBA4oS8hv+GlB9SoY+enQjoekrk1b+BSU+3eF4Qc9GpFwJTVZbtvfaC0VAy
+lyO52tTmjQfsVyFmlJs7D6FssxTbxYQPgsa0iBskbqjvVjgafZlm4Mww6yvmDyct
+9AsozZh2/lT3/F5yGeW3lKxdXKlQ6oqKCCgt35qGv6xUoFzFnbdCMqv3IPCm1fHN
+NLu8oTtiZNMc3/n0m5wlFQkxoDuw6bwzbyPw+pWOtI/EcLlfDduaqpMJmixjhCIB
+UjUYX6KsPhN+YQM8ATorIqBTnE41QrXHdtQMWB2qyLV7NI2cwqQg9g0j/mepvShB
+f74ZULcrPcEYlT1lWnyIYxPoNP35CewvBQiEjos4AT2bvQgOubeCfIYTdt1cHJkT
+cbixe0qfho2pHYapC5c4+J425sJCODpSve735xnUaVbX9MH1IixxrocDqn3v4eNb
+R41ywQGwmhpXqat/XZ01J9EDVeVX9JpANv13oTYPZRrSSErAyaB7i1L1dyvRU+wE
+UOT/y4MUCx+jQzJx/Jerm7VzU82C9k4Xvu+sp87lbaIAGCTm49LiBNqhICCHvx5+
+ZMEnHFz/XYPvQophhrRzIWw4r9P5L5p26by9XcF60Ho=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/159ca03a88897c8f13817a212629df84ce824709492b8c9adb8e5437d2fc72be.pem b/chromium/net/data/ssl/blacklist/159ca03a88897c8f13817a212629df84ce824709492b8c9adb8e5437d2fc72be.pem
new file mode 100644
index 00000000000..ce4133cea62
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/159ca03a88897c8f13817a212629df84ce824709492b8c9adb8e5437d2fc72be.pem
@@ -0,0 +1,26 @@
+-----BEGIN CERTIFICATE-----
+MIIEazCCA1OgAwIBAgIEBydxojANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTEyMDYyMDE4MzUxM1oX
+DTE5MDkxNDE4MzQwMFowQDELMAkGA1UEBhMCSlAxGDAWBgNVBAoTD0tlaW8gVW5p
+dmVyc2l0eTEXMBUGA1UEAxMOS0VJTyBVTklWLkNBIDIwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQC29SQ+EENagPIalA0bYSZQe1gm2reJtuL/VggiVvut
+DXhlbQ8TwJaJpwikGRHPlqdUG5zEPIR4O9PLeiu6tswFmA22a2eKqHd5RFl1k13W
+gc+I+ovpKS1dFNCr/WxdqBSwQdwrMGacWYtVc8wcWZAyBqPHWNOvgbi6ikeDPdA9
+AjwD553WXZU1zh84Sgz3h/NR1yCGrX39qW8p7mlib4Qg8CWntye97Ni3Ohlqm/m6
+thfpIptjwr8xq6/LJjOcB/f9a0CqNuiZBVMyIp9m3tNlSifCneWX2X/+G1GdOK80
+plltHay6W029QQV67PbW4lqymn5cjtSunMJLbOt6Nhv/AgMBAAGjggFRMIIBTTAS
+BgNVHRMBAf8ECDAGAQH/AgEAMFMGA1UdIARMMEowSAYJKwYBBAGxPgEAMDswOQYI
+KwYBBQUHAgEWLWh0dHA6Ly9jeWJlcnRydXN0Lm9tbmlyb290LmNvbS9yZXBvc2l0
+b3J5LmNmbTAOBgNVHQ8BAf8EBAMCAQYwbwYDVR0jBGgwZqFepFwwWjELMAkGA1UE
+BhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEi
+MCAGA1UEAxMZQmFsdGltb3JlIEN5YmVyVHJ1c3QgUm9vdIIEAgAAuTBCBgNVHR8E
+OzA5MDegNaAzhjFodHRwOi8vY2RwMS5wdWJsaWMtdHJ1c3QuY29tL0NSTC9PbW5p
+cm9vdDIwMjUuY3JsMB0GA1UdDgQWBBSkzpUuB63HsFQ6Ooir648h34D1qzANBgkq
+hkiG9w0BAQUFAAOCAQEAKcQLLMDFhnoR13BZM/8zbQXO2gTrjOWXiz1u0typn8G+
+wI6nzb7xoqNEUsHLqHzMzDLwc7FYQ+PLoRLiKKYcQx2faxfsmOAnkgdA9zr3jczC
+Ek10mEI/iXi/7ilrh5qRxI/SarXqLlLv5LFHCtHg5JGa/74ktsEa8SeUllKE2tTX
+nsfcl3gSY5H9c3duSZDLRSVrlasar6C7TJOZFWhUD616jcsMyTcpHvS6uedf0bGP
+lmVcwmRn5SbZQ4vE+6UPLO5npv+QGmmYJJirJmdHIHoekIAGK19E1Q5edb7duOxa
+9s/9NjVxhWsKNTcVh1UiB91lOcxnJrS1GJmvT0gIpg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/1af56c98ff043ef92bebff54cebb4dd67a25ba956c817f3e6dd3c1e52eb584c1.key b/chromium/net/data/ssl/blacklist/1af56c98ff043ef92bebff54cebb4dd67a25ba956c817f3e6dd3c1e52eb584c1.key
new file mode 100644
index 00000000000..1f4c721400f
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/1af56c98ff043ef92bebff54cebb4dd67a25ba956c817f3e6dd3c1e52eb584c1.key
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4ax+WmILhtQDBuW1VAY3
+gAKoOBGLD34GyKXHBKepRDLgn7n/3sYuXj4D8Og9sjhdBuw+o+jji2IFtZVbMjas
+6NU2BIX8dynmtmTn//d6ACALXEmD6JVP2Wqw+/ZxCQaf+JmPz9zX/6r2y8VpB1b9
+w1pEjQTUmAh9yexeWiGX+d0/XvkO+pAFCB8pYUYmU0AiXsU2XqZMj09rMw6tgaQk
+rQPP2N/op8qwT+4U35UaexCxjntaSqnoT3ulsTB+adlWcI2VP/+Lg43sW+TIe9EV
+u09ZW4BBQ2OjlqSHeVtWfeVwZySrgtyQU7FvDKJeMnGNc/vDlax1+9/zXU7wyyPd
+5QIDAQAB
+-----END PUBLIC KEY-----
diff --git a/chromium/net/data/ssl/blacklist/1f17f2cbb109f01c885c94d9e74a48625ae9659665d6d7e7bc5a10332976370f.pem b/chromium/net/data/ssl/blacklist/1f17f2cbb109f01c885c94d9e74a48625ae9659665d6d7e7bc5a10332976370f.pem
new file mode 100644
index 00000000000..d979bad5aa7
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/1f17f2cbb109f01c885c94d9e74a48625ae9659665d6d7e7bc5a10332976370f.pem
@@ -0,0 +1,104 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 4c:00:36:1b:e5:08:2b:a9:aa:ce:74:0a:05:3e:fb:34
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3
+ Validity
+ Not Before: May 18 00:00:00 2008 GMT
+ Not After : May 17 23:59:59 2018 GMT
+ Subject: C=EG, O=Egypt Trust, OU=VeriSign Trust Network, OU=Terms of use at https://www.egypttrust.com/repository/rpa (c)08, CN=Egypt Trust Class 3 Managed PKI Enterprise Administrator CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c6:74:6f:42:ae:7c:47:f1:58:f8:79:ad:90:1d:
+ 44:17:f3:84:34:9e:15:e2:2a:85:16:e9:4a:a4:c2:
+ 95:a8:27:9b:3a:95:db:48:c0:3a:95:d7:79:bb:7c:
+ 8b:a3:8e:d9:b7:89:bc:6e:7b:80:b3:ff:f3:3c:ce:
+ 0f:b5:b8:05:f0:02:2e:8b:db:2d:0b:40:72:36:ab:
+ 9e:2f:a6:fb:bc:cb:bb:ff:8f:09:e7:d8:15:6f:90:
+ 77:0c:1a:61:47:67:f3:2a:c2:54:68:1a:1f:16:fc:
+ 93:18:1d:79:98:cd:0d:57:10:33:42:df:4d:1f:e8:
+ 6f:f8:36:f1:da:c0:d0:d0:52:56:d9:4f:9e:c3:88:
+ 74:46:06:86:4b:5d:1e:0e:ba:f8:09:be:06:8e:77:
+ 88:7c:a3:9e:5b:e6:2f:e5:ae:87:cf:b5:e2:27:cf:
+ 1d:a7:81:c6:06:9d:2d:4d:49:c4:50:50:c7:b1:fb:
+ 33:34:df:20:6d:a1:aa:73:11:35:b1:20:6f:43:d1:
+ d1:49:1c:19:12:aa:f4:af:c2:35:38:c8:4f:85:d9:
+ a6:a1:b0:bc:a2:14:f2:00:ba:ee:c5:a3:fe:c5:ae:
+ 88:b2:f6:ee:1f:ad:dd:47:da:38:2b:59:5a:5d:c8:
+ fc:98:70:c1:a9:b4:37:d1:e6:e6:be:8f:82:9f:f4:
+ a1:7d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Certificate Policies:
+ Policy: 2.16.840.1.113733.1.7.23.3
+ CPS: https://www.egypttrust.com/repository/cps
+ User Notice:
+ Explicit Text: https://www.egypttrust.com/repository/rpa
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Netscape Cert Type:
+ SSL CA, S/MIME CA
+ X509v3 Subject Key Identifier:
+ 73:63:78:E5:C5:2E:46:04:03:EA:4E:82:08:0E:57:4C:FD:B9:EF:AB
+ X509v3 Authority Key Identifier:
+ DirName:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 1999 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G3
+ serial:9B:7E:06:49:A3:3E:62:B9:D5:EE:90:48:71:29:EF:57
+
+ Signature Algorithm: sha1WithRSAEncryption
+ c1:23:56:6d:c7:4d:44:9d:ef:aa:b9:2f:ca:63:3a:70:5f:7f:
+ 2e:86:95:c3:23:70:26:49:6c:12:bd:65:1a:37:08:f1:1b:89:
+ 02:9d:c7:7a:1d:26:56:6d:d8:eb:2c:0d:fd:0f:22:49:93:d3:
+ 21:39:ea:0b:bf:06:d9:44:59:5f:7f:5f:51:83:36:7f:0e:b2:
+ da:9e:62:6d:d2:d3:ca:b9:d7:31:f9:b3:b5:7b:14:9e:f6:e2:
+ c4:28:46:20:12:03:1d:2a:48:63:4f:23:ed:c8:8e:fd:95:c3:
+ c9:a8:ff:32:fd:c9:d0:79:2f:d3:51:5c:a5:7a:44:c0:15:9d:
+ 49:2d:57:09:2c:6b:11:1a:f5:a1:6d:3a:66:bd:22:f7:9a:b0:
+ 4f:ea:a3:58:c0:e3:ef:a7:1e:49:2b:18:e0:8e:26:38:73:11:
+ b4:0d:55:d4:78:87:28:da:5a:8e:d1:72:bc:66:9b:98:ad:15:
+ c9:84:81:da:24:99:42:6d:0b:94:d3:a2:28:a0:61:09:95:ba:
+ 95:3b:2a:26:3e:17:5f:d9:25:cc:fe:8c:11:26:69:f5:0d:68:
+ 81:06:ce:90:38:52:93:19:36:74:6f:4e:ed:6f:37:bc:03:3c:
+ 4e:77:1f:59:d3:62:ab:6a:ff:eb:f2:90:2b:31:ce:18:d9:90:
+ a1:d6:aa:0d
+-----BEGIN CERTIFICATE-----
+MIIGCTCCBPGgAwIBAgIQTAA2G+UIK6mqznQKBT77NDANBgkqhkiG9w0BAQUFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMTk5OSBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzMwHhcNMDgwNTE4MDAwMDAwWhcNMTgwNTE3MjM1OTU5WjCB1DEL
+MAkGA1UEBhMCRUcxFDASBgNVBAoTC0VneXB0IFRydXN0MR8wHQYDVQQLExZWZXJp
+U2lnbiBUcnVzdCBOZXR3b3JrMUgwRgYDVQQLEz9UZXJtcyBvZiB1c2UgYXQgaHR0
+cHM6Ly93d3cuZWd5cHR0cnVzdC5jb20vcmVwb3NpdG9yeS9ycGEgKGMpMDgxRDBC
+BgNVBAMTO0VneXB0IFRydXN0IENsYXNzIDMgTWFuYWdlZCBQS0kgRW50ZXJwcmlz
+ZSBBZG1pbmlzdHJhdG9yIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAxnRvQq58R/FY+HmtkB1EF/OENJ4V4iqFFulKpMKVqCebOpXbSMA6ldd5u3yL
+o47Zt4m8bnuAs//zPM4PtbgF8AIui9stC0ByNqueL6b7vMu7/48J59gVb5B3DBph
+R2fzKsJUaBofFvyTGB15mM0NVxAzQt9NH+hv+Dbx2sDQ0FJW2U+ew4h0RgaGS10e
+Drr4Cb4GjneIfKOeW+Yv5a6Hz7XiJ88dp4HGBp0tTUnEUFDHsfszNN8gbaGqcxE1
+sSBvQ9HRSRwZEqr0r8I1OMhPhdmmobC8ohTyALruxaP+xa6IsvbuH63dR9o4K1la
+Xcj8mHDBqbQ30ebmvo+Cn/ShfQIDAQABo4IB3TCCAdkwEgYDVR0TAQH/BAgwBgEB
+/wIBADCBjAYDVR0gBIGEMIGBMH8GC2CGSAGG+EUBBxcDMHAwNQYIKwYBBQUHAgEW
+KWh0dHBzOi8vd3d3LmVneXB0dHJ1c3QuY29tL3JlcG9zaXRvcnkvY3BzMDcGCCsG
+AQUFBwICMCsaKWh0dHBzOi8vd3d3LmVneXB0dHJ1c3QuY29tL3JlcG9zaXRvcnkv
+cnBhMA4GA1UdDwEB/wQEAwIBBjARBglghkgBhvhCAQEEBAMCAQYwHQYDVR0OBBYE
+FHNjeOXFLkYEA+pOgggOV0z9ue+rMIHxBgNVHSMEgekwgeahgdCkgc0wgcoxCzAJ
+BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy
+aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s
+IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp
+Z24gQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
+eSAtIEczghEAm34GSaM+YrnV7pBIcSnvVzANBgkqhkiG9w0BAQUFAAOCAQEAwSNW
+bcdNRJ3vqrkvymM6cF9/LoaVwyNwJklsEr1lGjcI8RuJAp3Heh0mVm3Y6ywN/Q8i
+SZPTITnqC78G2URZX39fUYM2fw6y2p5ibdLTyrnXMfmztXsUnvbixChGIBIDHSpI
+Y08j7ciO/ZXDyaj/Mv3J0Hkv01FcpXpEwBWdSS1XCSxrERr1oW06Zr0i95qwT+qj
+WMDj76ceSSsY4I4mOHMRtA1V1HiHKNpajtFyvGabmK0VyYSB2iSZQm0LlNOiKKBh
+CZW6lTsqJj4XX9klzP6MESZp9Q1ogQbOkDhSkxk2dG9O7W83vAM8TncfWdNiq2r/
+6/KQKzHOGNmQodaqDQ==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/294f55ef3bd7244c6ff8a68ab797e9186ec27582751a791515e3292e48372d61.pem b/chromium/net/data/ssl/blacklist/294f55ef3bd7244c6ff8a68ab797e9186ec27582751a791515e3292e48372d61.pem
new file mode 100644
index 00000000000..c3773c2c771
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/294f55ef3bd7244c6ff8a68ab797e9186ec27582751a791515e3292e48372d61.pem
@@ -0,0 +1,120 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 0a:82:bd:1e:14:4e:88:14:d7:5b:1a:55:27:be:bf:3e
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=NL, O=DigiNotar, CN=DigiNotar Root CA G2/emailAddress=info@diginotar.nl
+ Validity
+ Not Before: Jul 3 13:59:02 2009 GMT
+ Not After : Jul 3 13:59:02 2029 GMT
+ Subject: C=NL, O=DigiNotar, CN=DigiNotar Root CA G2/emailAddress=info@diginotar.nl
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:bf:ae:10:01:fb:4c:3e:b6:ac:03:f5:98:cf:23:
+ 92:28:a4:13:3d:1a:da:a0:4f:8b:65:e5:2e:e4:e0:
+ a6:8e:38:75:3b:e5:b3:58:15:dc:32:65:fe:7e:76:
+ 18:05:d9:82:a9:b6:a1:f6:fd:c4:bb:6b:6c:7b:24:
+ b4:81:f5:2c:3d:87:a9:c0:43:d7:dc:38:2c:e0:4d:
+ 12:84:17:bc:0d:4c:d3:71:4b:33:b8:42:04:31:71:
+ c7:24:1e:45:17:d0:fc:69:2a:5a:21:95:8d:04:87:
+ 8c:c0:77:13:62:8d:bd:e4:c8:8f:8a:10:15:7d:75:
+ c5:a0:76:65:b0:8e:01:36:0e:88:09:7c:a0:a3:39:
+ 25:ab:68:92:ad:e6:34:79:ef:94:17:d2:6b:2f:20:
+ 30:05:a9:91:39:ac:0c:5c:01:c7:a5:72:b0:8f:0f:
+ 18:8d:a2:39:da:dc:34:94:44:a5:90:40:45:b8:ee:
+ e7:e4:6b:f4:69:37:d8:d5:a2:80:2f:d5:f9:f6:4d:
+ 26:eb:53:a0:a1:85:5f:d0:bd:ca:2d:1c:26:ae:70:
+ 98:3d:1a:bc:71:63:23:99:43:89:ae:3c:3b:59:67:
+ 53:36:36:42:0d:e1:65:10:08:9a:53:b9:e8:7e:e1:
+ b0:ba:23:da:9b:22:47:2d:b3:5b:7d:c4:7f:02:fa:
+ 32:4e:16:fe:fa:8a:ab:59:1a:b6:62:3a:bd:c8:a0:
+ 5b:af:e3:93:b9:5c:86:b4:8d:e7:20:0b:6e:04:04:
+ fd:d2:a5:a6:ee:fd:b4:29:19:21:ef:42:91:23:84:
+ 4a:2b:fa:0e:4a:34:cd:b0:b0:95:7a:04:0d:a8:30:
+ 5e:3d:20:7b:3f:6a:03:45:db:05:05:94:90:c7:d6:
+ 4e:66:84:02:3b:80:cc:df:e2:87:6c:64:d2:70:5f:
+ 4f:70:bb:6c:43:18:1a:e9:6c:e0:80:56:c5:c5:e6:
+ 00:ad:df:4d:ed:51:8d:c6:ea:09:f1:09:0a:a2:da:
+ 53:47:4f:9b:98:d3:e0:c9:be:d8:87:5c:a5:53:a3:
+ 8d:ab:d3:bc:2e:0b:7a:bf:46:11:63:a4:58:15:aa:
+ 1c:6e:fe:49:06:53:02:4a:f3:d3:f2:41:cd:57:5f:
+ 95:25:b8:e1:87:f3:60:97:7f:ec:21:89:ca:d3:76:
+ 6c:dd:51:91:46:33:40:d8:48:94:2d:ea:05:72:bb:
+ b4:1c:a1:54:b7:c7:e6:e9:4a:7e:2b:b2:d7:21:19:
+ 5f:00:e4:9a:5c:8d:a1:38:af:39:2a:ec:60:35:48:
+ 58:2f:79:a2:ca:4c:2a:e4:7e:a8:11:88:51:ed:bf:
+ 0f:3b:6e:05:b1:80:47:39:e4:67:e2:87:61:c4:8e:
+ ac:87:c9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 29:0D:DB:3F:07:52:E5:0B:D4:21:68:2E:24:4A:DE:5B:5A:96:F2:21
+ Signature Algorithm: sha256WithRSAEncryption
+ 22:ef:ee:c0:53:e3:a4:65:e3:cf:20:ae:13:e2:a2:de:d7:37:
+ 2b:54:0f:0e:9b:8d:5f:98:e7:69:2a:1e:3b:a5:b5:59:bc:ac:
+ 7e:6a:e6:96:30:de:97:01:fd:74:f6:5f:25:00:f7:a3:63:8a:
+ b4:b1:0d:c2:19:18:03:ce:e5:30:21:12:91:30:71:e2:91:8b:
+ f3:dc:6b:c3:05:ad:cc:2d:62:98:36:27:5d:a3:e0:15:9b:82:
+ 3d:1a:68:75:95:dd:7a:68:2a:0f:22:69:36:33:b7:6b:a2:28:
+ 86:50:91:55:11:5a:12:00:8c:9d:51:dc:e0:b2:56:bd:50:45:
+ 74:ff:94:7b:d1:d7:f0:3b:e4:4d:e1:44:e9:df:6b:84:e2:22:
+ 4c:95:78:b4:94:cc:57:09:9e:21:87:ac:96:a1:13:1b:0b:c5:
+ 99:67:5c:1d:f1:15:b5:34:dc:bc:f8:1e:ec:ab:3f:94:27:b2:
+ 89:99:fc:d5:58:3e:a5:a4:06:d3:43:f9:1c:36:0d:8f:02:10:
+ 5c:f5:05:00:77:fa:a7:ec:99:56:ce:98:05:f8:72:a6:b9:05:
+ 1b:23:0e:0e:40:67:b5:79:4a:64:3b:81:b5:a1:8a:11:5b:9f:
+ 87:19:7c:f0:94:4e:33:a3:51:10:d5:bb:bd:51:8b:68:18:07:
+ ae:1a:57:ff:44:1b:c7:df:5b:d3:b3:cd:f9:b0:6f:4d:c2:cb:
+ 82:e5:8b:6e:29:d0:59:81:9c:6c:4e:fd:7b:10:d7:76:10:9f:
+ 2c:45:81:fe:5d:70:ac:bc:80:cb:f2:21:c2:c3:62:22:db:18:
+ 4e:10:8f:45:b0:1b:9a:22:23:a4:d4:1c:f7:6a:a2:33:df:f9:
+ cc:05:a8:55:e8:bd:97:85:a8:de:b3:65:dd:4e:04:12:78:9d:
+ e9:ca:93:36:2a:01:4a:7c:cd:e0:10:c3:94:48:90:a1:9d:87:
+ e8:75:d4:20:cf:87:11:35:ea:f0:c0:77:27:c2:52:f6:2d:6f:
+ 87:99:27:b5:f9:80:fe:ee:46:aa:ff:f6:3d:c5:bf:60:aa:34:
+ 61:35:2b:f3:02:01:8a:4a:9c:0a:22:61:fe:99:0b:05:59:f2:
+ 84:85:aa:ac:90:37:1f:f7:9f:14:e8:d3:7e:bd:04:46:3f:6d:
+ f6:e0:dc:42:4e:81:fc:5d:e0:9a:56:71:98:62:4f:e3:5e:fc:
+ 79:f9:cb:cc:c5:b8:5c:05:31:c8:62:f6:a9:6f:ff:6b:e3:f0:
+ 76:d3:ea:be:e7:41:01:f7:0c:a7:44:53:29:e0:dd:ef:d9:6b:
+ 2c:58:c8:d7:98:e2:1d:e4:29:b3:8b:e5:6c:76:c9:63:83:6d:
+ 1a:79:6e:73:4c:e0:c0:cb
+-----BEGIN CERTIFICATE-----
+MIIFkDCCA3igAwIBAgIQCoK9HhROiBTXWxpVJ76/PjANBgkqhkiG9w0BAQsFADBi
+MQswCQYDVQQGEwJOTDESMBAGA1UEChMJRGlnaU5vdGFyMR0wGwYDVQQDExREaWdp
+Tm90YXIgUm9vdCBDQSBHMjEgMB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIu
+bmwwHhcNMDkwNzAzMTM1OTAyWhcNMjkwNzAzMTM1OTAyWjBiMQswCQYDVQQGEwJO
+TDESMBAGA1UEChMJRGlnaU5vdGFyMR0wGwYDVQQDExREaWdpTm90YXIgUm9vdCBD
+QSBHMjEgMB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmwwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/rhAB+0w+tqwD9ZjPI5IopBM9GtqgT4tl
+5S7k4KaOOHU75bNYFdwyZf5+dhgF2YKptqH2/cS7a2x7JLSB9Sw9h6nAQ9fcOCzg
+TRKEF7wNTNNxSzO4QgQxccckHkUX0PxpKlohlY0Eh4zAdxNijb3kyI+KEBV9dcWg
+dmWwjgE2DogJfKCjOSWraJKt5jR575QX0msvIDAFqZE5rAxcAcelcrCPDxiNojna
+3DSURKWQQEW47ufka/RpN9jVooAv1fn2TSbrU6ChhV/QvcotHCaucJg9GrxxYyOZ
+Q4muPDtZZ1M2NkIN4WUQCJpTueh+4bC6I9qbIkcts1t9xH8C+jJOFv76iqtZGrZi
+Or3IoFuv45O5XIa0jecgC24EBP3Spabu/bQpGSHvQpEjhEor+g5KNM2wsJV6BA2o
+MF49IHs/agNF2wUFlJDH1k5mhAI7gMzf4odsZNJwX09wu2xDGBrpbOCAVsXF5gCt
+303tUY3G6gnxCQqi2lNHT5uY0+DJvtiHXKVTo42r07wuC3q/RhFjpFgVqhxu/kkG
+UwJK89PyQc1XX5UluOGH82CXf+whicrTdmzdUZFGM0DYSJQt6gVyu7QcoVS3x+bp
+Sn4rstchGV8A5JpcjaE4rzkq7GA1SFgveaLKTCrkfqgRiFHtvw87bgWxgEc55Gfi
+h2HEjqyHyQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUKQ3bPwdS5QvUIWguJEreW1qW8iEwDQYJKoZIhvcNAQELBQAD
+ggIBACLv7sBT46Rl488grhPiot7XNytUDw6bjV+Y52kqHjultVm8rH5q5pYw3pcB
+/XT2XyUA96NjirSxDcIZGAPO5TAhEpEwceKRi/Pca8MFrcwtYpg2J12j4BWbgj0a
+aHWV3XpoKg8iaTYzt2uiKIZQkVURWhIAjJ1R3OCyVr1QRXT/lHvR1/A75E3hROnf
+a4TiIkyVeLSUzFcJniGHrJahExsLxZlnXB3xFbU03Lz4HuyrP5QnsomZ/NVYPqWk
+BtND+Rw2DY8CEFz1BQB3+qfsmVbOmAX4cqa5BRsjDg5AZ7V5SmQ7gbWhihFbn4cZ
+fPCUTjOjURDVu71Ri2gYB64aV/9EG8ffW9Ozzfmwb03Cy4Lli24p0FmBnGxO/XsQ
+13YQnyxFgf5dcKy8gMvyIcLDYiLbGE4Qj0WwG5oiI6TUHPdqojPf+cwFqFXovZeF
+qN6zZd1OBBJ4nenKkzYqAUp8zeAQw5RIkKGdh+h11CDPhxE16vDAdyfCUvYtb4eZ
+J7X5gP7uRqr/9j3Fv2CqNGE1K/MCAYpKnAoiYf6ZCwVZ8oSFqqyQNx/3nxTo0369
+BEY/bfbg3EJOgfxd4JpWcZhiT+Ne/Hn5y8zFuFwFMchi9qlv/2vj8HbT6r7nQQH3
+DKdEUyng3e/ZayxYyNeY4h3kKbOL5Wx2yWODbRp5bnNM4MDL
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/2a3699deca1e9fd099ba45de8489e205977c9f2a5e29d5dd747381eec0744d71.pem b/chromium/net/data/ssl/blacklist/2a3699deca1e9fd099ba45de8489e205977c9f2a5e29d5dd747381eec0744d71.pem
new file mode 100644
index 00000000000..97dbe6bbd16
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/2a3699deca1e9fd099ba45de8489e205977c9f2a5e29d5dd747381eec0744d71.pem
@@ -0,0 +1,114 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ b0:b7:13:3e:d0:96:f9:b5:6f:ae:91:c8:74:bd:3a:c0
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
+ Validity
+ Not Before: Mar 15 00:00:00 2011 GMT
+ Not After : Mar 14 23:59:59 2014 GMT
+ Subject: C=US/postalCode=38477, ST=Florida, L=English/street=Sea Village 10, O=Google Ltd., OU=Tech Dept., OU=Hosted by GTI Group Corporation, OU=PlatinumSSL, CN=login.live.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:f3:fc:2b:2f:ef:e1:ad:59:f0:42:3c:c2:f1:82:
+ bf:2c:41:93:d1:f6:98:33:95:4c:bc:62:f1:95:58:
+ 08:b6:e9:7b:77:48:b0:d3:dc:17:3f:bc:6e:e6:ec:
+ 1e:ec:8d:17:fe:1c:24:c6:3e:67:3d:92:95:a2:30:
+ c0:a7:57:20:cf:70:88:97:4a:05:93:79:93:42:97:
+ 2f:3e:ff:c4:14:14:28:a2:13:36:b4:f8:ee:be:1d:
+ bc:78:5d:61:93:5f:eb:88:d7:d1:e4:2b:9a:cd:58:
+ e2:07:45:9f:4f:b8:b9:40:6a:33:2c:5b:21:03:5a:
+ 4a:94:f2:7a:97:59:1b:a8:b5:42:d8:83:00:aa:34:
+ cc:a7:76:d0:47:03:5f:05:af:3b:e1:b9:a1:34:25:
+ b7:6c:5f:9a:30:84:98:c2:c2:d7:f2:b8:42:4a:10:
+ 55:bd:fa:53:81:5d:8d:68:66:45:2c:52:7e:e5:c4:
+ 04:c3:54:e7:c3:39:da:7a:4a:c5:b9:98:82:20:e1:
+ 2c:60:57:bf:ba:f2:46:00:bc:5f:3a:dc:e3:33:97:
+ f8:4a:98:b9:ec:33:4f:2d:60:6c:15:92:a6:81:4a:
+ 0b:e9:ec:76:70:34:31:17:70:e6:70:4b:8e:8b:d3:
+ 75:cb:78:49:ab:66:9b:86:9f:8f:a9:c4:01:e8:ca:
+ 1b:e7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45
+
+ X509v3 Subject Key Identifier:
+ D4:64:F6:A9:E8:A5:7E:D7:BF:63:52:03:83:53:DB:C5:41:8D:EA:80
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6449.1.2.1.3.4
+ CPS: https://secure.comodo.com/CPS
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/UTN-USERFirst-Hardware.crl
+
+ Full Name:
+ URI:http://crl.comodo.net/UTN-USERFirst-Hardware.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://crt.comodoca.com/UTNAddTrustServerCA.crt
+ OCSP - URI:http://ocsp.comodoca.com
+
+ X509v3 Subject Alternative Name:
+ DNS:login.live.com, DNS:www.login.live.com
+ Signature Algorithm: sha1WithRSAEncryption
+ 54:e3:a4:9a:24:d2:f3:1d:42:ad:1b:f0:1e:ab:fb:da:d5:aa:
+ e9:cf:5a:b3:1e:57:7b:31:f2:6e:57:4b:31:af:33:bb:b6:0d:
+ 15:c7:5e:59:01:ce:44:b5:b7:bf:09:c9:d5:dc:69:84:e9:c5:
+ 1a:b7:f0:3e:d4:c0:24:bd:29:5f:b4:e9:d6:58:eb:45:11:89:
+ 34:34:d3:11:eb:34:ce:2a:4f:00:3d:f6:72:ef:69:66:c0:9f:
+ 9a:ac:7e:70:50:ac:55:47:da:be:43:5b:ec:8b:c8:c5:23:84:
+ c9:9f:b6:52:08:cf:91:1b:2f:80:69:e6:34:33:e6:b3:9f:a4:
+ e5:0d:9a:15:f9:57:fc:0b:a9:41:0b:f5:ff:58:41:92:22:27:
+ 66:12:06:c7:2a:d8:59:a7:c6:df:44:12:4f:c0:a8:7f:a7:41:
+ c8:c8:69:ff:ba:05:2e:97:ad:3b:d0:eb:f3:15:6d:7e:1b:e5:
+ ba:dd:34:be:22:11:ec:68:98:33:81:02:6a:0b:13:55:79:31:
+ 75:4e:3a:c8:b6:13:bd:97:6f:37:0a:0b:2d:88:0e:de:67:90:
+ c2:b3:ca:20:ca:9a:51:f4:64:3e:db:f4:2e:45:f2:c7:47:17:
+ a8:f4:fa:90:5a:7f:80:a6:82:ac:e4:6c:81:46:bb:52:85:20:
+ 24:f8:80:ea
+-----BEGIN CERTIFICATE-----
+MIIF7DCCBNSgAwIBAgIRALC3Ez7Qlvm1b66RyHS9OsAwDQYJKoZIhvcNAQEFBQAw
+gZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtl
+IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMY
+aHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR8wHQYDVQQDExZVVE4tVVNFUkZpcnN0
+LUhhcmR3YXJlMB4XDTExMDMxNTAwMDAwMFoXDTE0MDMxNDIzNTk1OVowgd4xCzAJ
+BgNVBAYTAlVTMQ4wDAYDVQQREwUzODQ3NzEQMA4GA1UECBMHRmxvcmlkYTEQMA4G
+A1UEBxMHRW5nbGlzaDEXMBUGA1UECRMOU2VhIFZpbGxhZ2UgMTAxFDASBgNVBAoT
+C0dvb2dsZSBMdGQuMRMwEQYDVQQLEwpUZWNoIERlcHQuMSgwJgYDVQQLEx9Ib3N0
+ZWQgYnkgR1RJIEdyb3VwIENvcnBvcmF0aW9uMRQwEgYDVQQLEwtQbGF0aW51bVNT
+TDEXMBUGA1UEAxMObG9naW4ubGl2ZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDz/Csv7+GtWfBCPMLxgr8sQZPR9pgzlUy8YvGVWAi26Xt3SLDT
+3Bc/vG7m7B7sjRf+HCTGPmc9kpWiMMCnVyDPcIiXSgWTeZNCly8+/8QUFCiiEza0
++O6+Hbx4XWGTX+uI19HkK5rNWOIHRZ9PuLlAajMsWyEDWkqU8nqXWRuotULYgwCq
+NMyndtBHA18FrzvhuaE0JbdsX5owhJjCwtfyuEJKEFW9+lOBXY1oZkUsUn7lxATD
+VOfDOdp6SsW5mIIg4SxgV7+68kYAvF863OMzl/hKmLnsM08tYGwVkqaBSgvp7HZw
+NDEXcOZwS46L03XLeEmrZpuGn4+pxAHoyhvnAgMBAAGjggHoMIIB5DAfBgNVHSME
+GDAWgBShcl8mGyiYQ5VdBzfVhZadS9LDRTAdBgNVHQ4EFgQU1GT2qeilfte/Y1ID
+g1PbxUGN6oAwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYw
+FAYIKwYBBQUHAwEGCCsGAQUFBwMCMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQME
+MCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMHsG
+A1UdHwR0MHIwOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1VUTi1VU0VS
+Rmlyc3QtSGFyZHdhcmUuY3JsMDagNKAyhjBodHRwOi8vY3JsLmNvbW9kby5uZXQv
+VVROLVVTRVJGaXJzdC1IYXJkd2FyZS5jcmwwcQYIKwYBBQUHAQEEZTBjMDsGCCsG
+AQUFBzAChi9odHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9VVE5BZGRUcnVzdFNlcnZl
+ckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMC0G
+A1UdEQQmMCSCDmxvZ2luLmxpdmUuY29tghJ3d3cubG9naW4ubGl2ZS5jb20wDQYJ
+KoZIhvcNAQEFBQADggEBAFTjpJok0vMdQq0b8B6r+9rVqunPWrMeV3sx8m5XSzGv
+M7u2DRXHXlkBzkS1t78JydXcaYTpxRq38D7UwCS9KV+06dZY60URiTQ00xHrNM4q
+TwA99nLvaWbAn5qsfnBQrFVH2r5DW+yLyMUjhMmftlIIz5EbL4Bp5jQz5rOfpOUN
+mhX5V/wLqUEL9f9YQZIiJ2YSBscq2Fmnxt9EEk/AqH+nQcjIaf+6BS6XrTvQ6/MV
+bX4b5brdNL4iEexomDOBAmoLE1V5MXVOOsi2E72XbzcKCy2IDt5nkMKzyiDKmlH0
+ZD7b9C5F8sdHF6j0+pBaf4CmgqzkbIFGu1KFICT4gOo=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/31c8fd37db9b56e708b03d1f01848b068c6da66f36fb5d82c008c6040fa3e133.pem b/chromium/net/data/ssl/blacklist/31c8fd37db9b56e708b03d1f01848b068c6da66f36fb5d82c008c6040fa3e133.pem
new file mode 100644
index 00000000000..328e48b5f6a
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/31c8fd37db9b56e708b03d1f01848b068c6da66f36fb5d82c008c6040fa3e133.pem
@@ -0,0 +1,96 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 20006006 (0x1314476)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden Overheid CA
+ Validity
+ Not Before: Jun 24 08:19:32 2004 GMT
+ Not After : Jun 23 08:17:36 2010 GMT
+ Subject: C=NL, O=DigiNotar B.V., CN=DigiNotar PKIoverheid CA Overheid
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:d4:a5:ae:e6:ed:6b:9b:65:3a:35:42:8b:f8:1b:
+ c8:b0:af:46:a7:c1:8f:11:bc:1f:9f:78:55:c2:87:
+ bb:45:80:61:cf:7d:48:f6:45:f5:cc:9c:8f:99:b0:
+ d8:6c:9f:42:fc:bf:58:8a:c6:ac:be:22:c8:da:b5:
+ 81:2a:91:d1:00:3f:99:35:ca:64:86:8f:ab:3a:43:
+ 85:d9:be:56:fa:ca:92:68:eb:6d:97:da:43:18:0c:
+ 4a:cd:c2:86:d0:6c:8d:c3:fd:2d:cd:17:d7:35:d9:
+ e1:0f:27:05:ed:e4:05:3a:7e:cd:e8:48:35:f9:9b:
+ 8e:81:20:5c:bc:6c:31:1e:51:43:a1:b1:cc:a8:ee:
+ 0b:4e:0f:42:96:c9:42:04:c8:6a:48:25:29:aa:98:
+ 70:30:d9:6c:4b:1c:5a:03:d5:1e:08:ff:d9:aa:07:
+ 96:3e:a5:79:6f:d3:84:76:7e:3b:8d:63:52:0b:84:
+ 98:12:d9:03:79:ae:dc:7a:c2:7e:b1:e7:b5:be:5d:
+ 3e:dd:22:87:34:b1:ec:6b:43:fd:26:97:e4:70:4b:
+ c6:73:f5:f3:d6:2e:a8:c9:39:89:10:3d:e4:2b:62:
+ 49:d2:9a:ba:fa:27:ff:14:4a:44:b3:60:1b:a5:c0:
+ cf:47:2d:4a:86:3b:c4:b0:dd:88:15:54:e6:42:5d:
+ 15:27
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Certificate Policies:
+ Policy: X509v3 Any Policy
+ CPS: http://www.diginotar.nl/cps/pkioverheid
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Authority Key Identifier:
+ keyid:0B:86:D6:0F:77:A3:68:B1:FB:64:09:C3:88:6E:5C:04:1C:57:E9:3D
+ DirName:/C=NL/O=Staat der Nederlanden/CN=Staat der Nederlanden Root CA
+ serial:98:9A:79
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.pkioverheid.nl/DomOvLatestCRL.crl
+
+ X509v3 Subject Key Identifier:
+ BD:16:98:42:1D:BE:91:D1:3D:C2:97:25:E0:28:D7:58:E0:B5:7F:E2
+ Signature Algorithm: sha1WithRSAEncryption
+ 68:50:b0:25:8b:89:a3:76:10:e8:4f:01:6f:89:40:fe:a8:5c:
+ 13:ab:2e:fe:70:ea:3a:1a:87:30:45:56:7d:41:89:e7:f3:9a:
+ 53:0a:8e:26:ea:29:8c:54:45:1b:cc:02:c3:24:87:cd:bf:31:
+ f2:fc:57:4c:3a:ba:0c:65:f3:59:6e:8b:8d:9d:73:19:7d:70:
+ a4:95:5c:a3:30:e1:b6:c1:cc:9d:95:40:8e:47:4c:80:01:c1:
+ e7:de:36:ec:bf:79:7e:a2:75:5c:18:76:dd:da:8c:01:fb:7d:
+ 40:3c:43:d0:aa:be:be:87:f0:1f:bc:9b:0a:04:a9:35:53:11:
+ 59:42:4a:c0:bf:11:7b:28:91:81:14:af:4e:8f:3f:34:6e:74:
+ a8:c3:9a:28:e0:8f:bc:c5:68:88:a8:64:d7:3c:86:4e:e0:b9:
+ f1:20:ae:cf:ed:99:c3:46:ca:5a:f0:44:78:02:5e:30:91:06:
+ dd:8d:1e:56:74:f2:5e:c0:d4:01:94:f0:77:07:95:26:c6:f5:
+ 49:ff:da:af:64:54:75:24:a6:cd:03:82:d5:1a:10:af:b1:ea:
+ 3a:40:bb:f4:7c:3a:37:b3:bb:ff:99:11:cc:30:8c:8f:ca:3a:
+ 11:be:f3:8f:9e:8c:59:ad:c8:49:2b:51:db:00:74:47:4b:7f:
+ fd:9d:2a:cc
+-----BEGIN CERTIFICATE-----
+MIIEezCCA2OgAwIBAgIEATFEdjANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJO
+TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSowKAYDVQQDEyFTdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gT3ZlcmhlaWQgQ0EwHhcNMDQwNjI0MDgxOTMyWhcN
+MTAwNjIzMDgxNzM2WjBSMQswCQYDVQQGEwJOTDEXMBUGA1UEChMORGlnaU5vdGFy
+IEIuVi4xKjAoBgNVBAMTIURpZ2lOb3RhciBQS0lvdmVyaGVpZCBDQSBPdmVyaGVp
+ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANSlrubta5tlOjVCi/gb
+yLCvRqfBjxG8H594VcKHu0WAYc99SPZF9cycj5mw2GyfQvy/WIrGrL4iyNq1gSqR
+0QA/mTXKZIaPqzpDhdm+VvrKkmjrbZfaQxgMSs3ChtBsjcP9Lc0X1zXZ4Q8nBe3k
+BTp+zehINfmbjoEgXLxsMR5RQ6GxzKjuC04PQpbJQgTIakglKaqYcDDZbEscWgPV
+Hgj/2aoHlj6leW/ThHZ+O41jUguEmBLZA3mu3HrCfrHntb5dPt0ihzSx7GtD/SaX
+5HBLxnP189YuqMk5iRA95CtiSdKauvon/xRKRLNgG6XAz0ctSoY7xLDdiBVU5kJd
+FScCAwEAAaOCAVAwggFMMEgGA1UdIARBMD8wPQYEVR0gADA1MDMGCCsGAQUFBwIB
+FidodHRwOi8vd3d3LmRpZ2lub3Rhci5ubC9jcHMvcGtpb3ZlcmhlaWQwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgYAGA1UdIwR5MHeAFAuG1g93o2ix
++2QJw4huXAQcV+k9oVmkVzBVMQswCQYDVQQGEwJOTDEeMBwGA1UEChMVU3RhYXQg
+ZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g
+Um9vdCBDQYIEAJiaeTA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnBraW92
+ZXJoZWlkLm5sL0RvbU92TGF0ZXN0Q1JMLmNybDAdBgNVHQ4EFgQUvRaYQh2+kdE9
+wpcl4CjXWOC1f+IwDQYJKoZIhvcNAQEFBQADggEBAGhQsCWLiaN2EOhPAW+JQP6o
+XBOrLv5w6joahzBFVn1BiefzmlMKjibqKYxURRvMAsMkh82/MfL8V0w6ugxl81lu
+i42dcxl9cKSVXKMw4bbBzJ2VQI5HTIABwefeNuy/eX6idVwYdt3ajAH7fUA8Q9Cq
+vr6H8B+8mwoEqTVTEVlCSsC/EXsokYEUr06PPzRudKjDmijgj7zFaIioZNc8hk7g
+ufEgrs/tmcNGylrwRHgCXjCRBt2NHlZ08l7A1AGU8HcHlSbG9Un/2q9kVHUkps0D
+gtUaEK+x6jpAu/R8Ojezu/+ZEcwwjI/KOhG+84+ejFmtyEkrUdsAdEdLf/2dKsw=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/32ecc96f912f96d889e73088cd031c7ded2c651c805016157a23b6f32f798a3b.key b/chromium/net/data/ssl/blacklist/32ecc96f912f96d889e73088cd031c7ded2c651c805016157a23b6f32f798a3b.key
new file mode 100644
index 00000000000..a1a0b1f997f
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/32ecc96f912f96d889e73088cd031c7ded2c651c805016157a23b6f32f798a3b.key
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjED82obyXeyJu4gC631I
+99oZfb1Txo//83D6qSlccQijj9twIaRSmqQ9Le87CfTpS5iSroVLIvE5UY9KltAq
+iHCh9P5nN3E7njYa0e14kRrMteSALPKQmFL5QetyLoNsf3tMbEGutDWIjxyPXcab
+lqRXkHkzb7xJSy8LzMHG4/Io2a+3QhwnD/NxQoa9fIJEZbsK6EmdkJmJr6uznuIt
+qh81gMYHnouAVnZVQNISLVc0ACBVk7bHvkiCLrpZd4AIyP/DW/TaKTuF1F9TXydD
+RZfwMzxh6qj/PLgq0jXQ98Bb67FwNuSHJAfbsCOr02msFxgJNl4DrEJijqieBlbG
+nQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/chromium/net/data/ssl/blacklist/372447c43185c38edd2ce0e9c853f9ac1576ddd1704c2f54d96076c089cb4227.pem b/chromium/net/data/ssl/blacklist/372447c43185c38edd2ce0e9c853f9ac1576ddd1704c2f54d96076c089cb4227.pem
new file mode 100644
index 00000000000..129a889292f
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/372447c43185c38edd2ce0e9c853f9ac1576ddd1704c2f54d96076c089cb4227.pem
@@ -0,0 +1,78 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2148 (0x864)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=T\xC3\x9CRKTRUST Elektronik Sunucu Sertifikas\xC4\xB1 Hizmetleri, C=TR, O=T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve Bili\xC5\x9Fim G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E. (c) Kas\xC4\xB1m 2005
+ Validity
+ Not Before: Aug 8 07:07:51 2011 GMT
+ Not After : Aug 5 07:07:51 2021 GMT
+ Subject: C=TR, ST=Lefkosa, L=Lefkosa, O=KKTC Merkez Bankasi, CN=e-islem.kktcmerkezbankasi.org/emailAddress=ileti@kktcmerkezbankasi.org
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c3:58:54:a6:e4:45:63:ae:cd:b1:9e:82:f6:bc:
+ d1:00:f0:9b:f5:15:69:8b:89:d9:cc:92:00:d5:3b:
+ c8:7e:be:21:30:f3:34:5f:98:ec:78:c7:f9:1a:f8:
+ 09:43:e7:01:31:9b:68:a0:37:7b:05:b6:4d:cb:6c:
+ fb:3b:90:3e:f0:f6:05:68:c0:dd:a2:40:84:37:1d:
+ 9e:3c:8a:80:56:e3:ba:0b:95:00:a8:ce:c9:de:7e:
+ 91:ae:18:ce:be:a8:b0:e9:d4:d0:31:bb:57:86:31:
+ 5a:a3:e6:0c:b8:15:6f:46:eb:a1:18:70:43:2b:72:
+ 5e:eb:84:ff:28:bc:dc:98:05:25:44:91:2e:cb:e6:
+ 4c:7b:b0:1a:b5:46:92:0e:bf:e3:cb:90:cc:03:9c:
+ 44:60:e7:6c:9d:2e:59:a3:7d:25:44:6f:bd:be:a6:
+ f1:6f:c0:90:8b:e1:3d:ee:c3:63:63:e5:b8:94:48:
+ 09:29:05:8c:36:1e:6b:0b:1a:38:1e:29:e4:9b:70:
+ 8a:c8:a5:f7:3c:04:be:0c:35:48:dc:b4:22:0a:22:
+ 10:50:e3:00:db:ed:4f:e5:a4:cf:4e:4a:6a:95:b8:
+ ea:85:b5:93:58:03:d6:38:a0:85:f5:df:37:a7:74:
+ 4c:5c:e6:2d:e4:66:a1:4b:ca:e0:e6:ee:be:b6:81:
+ 02:d5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ c2:35:b3:e6:db:14:bd:83:91:55:6f:0a:25:22:bf:6e:21:c5:
+ ac:09:c5:a2:d3:2d:a1:32:84:7b:04:66:9d:86:98:8f:05:c8:
+ af:52:0f:68:1a:a1:8e:41:86:be:22:cd:d9:e3:87:fe:ff:7b:
+ 52:58:ba:1c:2e:25:ce:12:87:7c:c4:14:4b:d2:85:fd:fe:67:
+ 19:c1:fc:89:00:72:fe:09:85:b1:f2:50:d4:a0:c2:e8:63:4c:
+ e0:27:cc:18:8c:f2:c6:36:21:3f:45:73:75:4b:4a:5f:73:c0:
+ 97:91:2a:80:c5:1c:76:a4:43:cb:a4:6e:cf:9e:7e:26:47:6f:
+ 08:bd:67:00:2e:f1:1f:e7:33:25:c6:55:c3:2b:13:74:67:cb:
+ 4c:28:7a:56:d6:0f:80:89:1e:2f:a5:3c:df:14:00:c8:cb:8e:
+ 1e:6e:f6:7b:12:65:8d:81:6a:22:c8:8d:bc:61:34:2a:e7:c2:
+ a8:2b:87:d4:f0:fd:ec:85:cc:ac:b9:70:1a:62:8a:83:98:cf:
+ df:8f:65:c9:20:69:26:39:ba:44:3a:82:4d:3f:ba:75:49:76:
+ 8e:45:5b:78:d9:9c:a3:df:58:ec:03:9d:b4:bb:0e:75:70:4c:
+ 0a:8e:71:f2:52:bc:cf:04:16:16:bc:c4:9a:cd:23:a0:75:c2:
+ a5:67:c6:58
+-----BEGIN CERTIFICATE-----
+MIID8DCCAtigAwIBAgICCGQwDQYJKoZIhvcNAQEFBQAwgawxPTA7BgNVBAMMNFTD
+nFJLVFJVU1QgRWxla3Ryb25payBTdW51Y3UgU2VydGlmaWthc8SxIEhpem1ldGxl
+cmkxCzAJBgNVBAYTAlRSMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0
+acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAo
+YykgS2FzxLFtICAyMDA1MB4XDTExMDgwODA3MDc1MVoXDTIxMDgwNTA3MDc1MVow
+gaMxCzAJBgNVBAYTAlRSMRAwDgYDVQQIEwdMZWZrb3NhMRAwDgYDVQQHEwdMZWZr
+b3NhMRwwGgYDVQQKExNLS1RDIE1lcmtleiBCYW5rYXNpMSYwJAYDVQQDEx1lLWlz
+bGVtLmtrdGNtZXJrZXpiYW5rYXNpLm9yZzEqMCgGCSqGSIb3DQEJARYbaWxldGlA
+a2t0Y21lcmtlemJhbmthc2kub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAw1hUpuRFY67NsZ6C9rzRAPCb9RVpi4nZzJIA1TvIfr4hMPM0X5jseMf5
+GvgJQ+cBMZtooDd7BbZNy2z7O5A+8PYFaMDdokCENx2ePIqAVuO6C5UAqM7J3n6R
+rhjOvqiw6dTQMbtXhjFao+YMuBVvRuuhGHBDK3Je64T/KLzcmAUlRJEuy+ZMe7Aa
+tUaSDr/jy5DMA5xEYOdsnS5Zo30lRG+9vqbxb8CQi+E97sNjY+W4lEgJKQWMNh5r
+Cxo4Hinkm3CKyKX3PAS+DDVI3LQiCiIQUOMA2+1P5aTPTkpqlbjqhbWTWAPWOKCF
+9d83p3RMXOYt5GahS8rg5u6+toEC1QIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAwjWz5tsUvYORVW8K
+JSK/biHFrAnFotMtoTKEewRmnYaYjwXIr1IPaBqhjkGGviLN2eOH/v97Uli6HC4l
+zhKHfMQUS9KF/f5nGcH8iQBy/gmFsfJQ1KDC6GNM4CfMGIzyxjYhP0VzdUtKX3PA
+l5EqgMUcdqRDy6Ruz55+JkdvCL1nAC7xH+czJcZVwysTdGfLTCh6VtYPgIkeL6U8
+3xQAyMuOHm72exJljYFqIsiNvGE0KufCqCuH1PD97IXMrLlwGmKKg5jP349lySBp
+Jjm6RDqCTT+6dUl2jkVbeNmco99Y7AOdtLsOdXBMCo5x8lK8zwQWFrzEms0joHXC
+pWfGWA==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/3946901f46b0071e90d78279e82fababca177231a704be72c5b0e8918566ea66.pem b/chromium/net/data/ssl/blacklist/3946901f46b0071e90d78279e82fababca177231a704be72c5b0e8918566ea66.pem
new file mode 100644
index 00000000000..a930c69519a
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/3946901f46b0071e90d78279e82fababca177231a704be72c5b0e8918566ea66.pem
@@ -0,0 +1,97 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 20015536 (0x13169b0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden Overheid CA
+ Validity
+ Not Before: Jul 5 08:42:07 2007 GMT
+ Not After : Jul 27 08:39:46 2015 GMT
+ Subject: C=NL, O=DigiNotar B.V., CN=DigiNotar PKIoverheid CA Overheid en Bedrijven
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:dc:bd:d2:a7:4e:6a:0a:bb:3b:a2:85:e1:7f:00:
+ ad:be:b4:30:68:98:07:cd:a0:7a:c4:94:cf:71:f9:
+ 8a:37:e4:53:eb:57:76:cc:8b:e6:6c:fe:ee:87:55:
+ c8:3e:bb:04:39:00:a7:80:78:ac:5b:4f:7e:f4:bd:
+ b8:54:b8:71:3b:07:31:49:39:93:54:7c:20:3b:79:
+ 2b:8f:bb:61:90:7d:b1:ac:e6:1f:90:2e:9d:45:01:
+ a9:64:2d:4d:c3:2f:b9:e7:50:d5:4e:2a:5c:ab:76:
+ 76:37:46:d7:79:ec:42:99:f7:a2:ec:a4:89:70:dc:
+ 38:2b:87:a6:aa:24:e6:9d:92:24:1b:be:f6:fd:d4:
+ 2f:19:17:7a:e6:32:07:94:54:05:53:43:e9:6c:bc:
+ af:47:cb:bc:cb:fd:bd:3b:44:12:81:f1:6b:4b:bb:
+ ed:b4:cf:ab:25:4f:18:d2:cc:02:fc:a3:4f:b5:42:
+ 33:cb:59:cd:09:dc:d3:50:fd:a0:76:8c:ac:7e:66:
+ 8a:42:f6:ad:1c:92:f3:b6:fb:14:46:eb:4d:d7:2f:
+ 30:e0:6d:ee:5b:36:be:44:74:b7:20:05:57:85:4d:
+ e8:00:19:a2:f6:0c:e6:ae:a1:c0:42:df:a7:ac:82:
+ 5d:c7:68:b7:18:e6:89:4b:9a:6b:fa:ce:79:f9:f3:
+ 2c:a7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Certificate Policies:
+ Policy: X509v3 Any Policy
+ CPS: http://www.diginotar.nl/cps/pkioverheid
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Authority Key Identifier:
+ keyid:0B:86:D6:0F:77:A3:68:B1:FB:64:09:C3:88:6E:5C:04:1C:57:E9:3D
+ DirName:/C=NL/O=Staat der Nederlanden/CN=Staat der Nederlanden Root CA
+ serial:98:9A:79
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.pkioverheid.nl/DomOvLatestCRL.crl
+
+ X509v3 Subject Key Identifier:
+ 4C:08:C9:8D:76:F1:98:C7:3E:DF:3C:D7:2F:75:0D:B1:76:79:97:CC
+ Signature Algorithm: sha1WithRSAEncryption
+ 0c:94:87:1a:bf:4d:e3:85:e2:ee:d7:d8:63:79:0e:50:df:c6:
+ 84:5b:d2:bb:d9:f5:31:0a:1a:35:97:74:df:14:fa:2a:0f:3e:
+ ed:a0:e3:08:f6:d5:4e:5b:af:a6:ae:25:e2:45:6b:22:0f:b7:
+ 54:28:7e:92:de:8d:14:6c:d1:1c:e5:6e:74:04:9c:b7:ef:34:
+ 44:45:df:c9:83:1d:19:1f:c0:29:69:df:89:d5:3f:c2:b0:53:
+ 6d:e5:4e:17:e4:73:61:23:13:26:71:43:fd:4c:59:cb:c3:df:
+ 22:aa:21:2b:d9:bf:95:11:1a:8a:a4:e2:ab:a7:5d:4b:6f:29:
+ f5:52:d1:e4:d2:15:b1:8b:fe:f0:03:cf:a7:7d:e9:99:87:38:
+ b3:0d:73:14:e4:72:2c:e1:ce:f5:ad:06:48:64:fa:d3:29:b9:
+ a2:d8:bb:f4:d5:0b:a5:40:44:43:8e:a0:bf:ce:5a:a5:52:4c:
+ 64:d3:17:31:61:cc:e8:a4:8a:e8:e4:88:fb:e9:e5:2f:06:33:
+ 33:9b:94:66:66:b1:ab:50:3a:a1:09:81:74:53:5a:27:b9:a6:
+ d2:25:cf:d3:c3:a7:ff:96:d0:2f:ea:e0:1e:8d:52:e9:18:1c:
+ 20:0a:47:a0:96:56:0e:40:90:51:44:ac:1a:fd:f1:ee:85:1f:
+ f7:42:5a:65
+-----BEGIN CERTIFICATE-----
+MIIEiDCCA3CgAwIBAgIEATFpsDANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJO
+TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSowKAYDVQQDEyFTdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gT3ZlcmhlaWQgQ0EwHhcNMDcwNzA1MDg0MjA3WhcN
+MTUwNzI3MDgzOTQ2WjBfMQswCQYDVQQGEwJOTDEXMBUGA1UEChMORGlnaU5vdGFy
+IEIuVi4xNzA1BgNVBAMTLkRpZ2lOb3RhciBQS0lvdmVyaGVpZCBDQSBPdmVyaGVp
+ZCBlbiBCZWRyaWp2ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDc
+vdKnTmoKuzuiheF/AK2+tDBomAfNoHrElM9x+Yo35FPrV3bMi+Zs/u6HVcg+uwQ5
+AKeAeKxbT370vbhUuHE7BzFJOZNUfCA7eSuPu2GQfbGs5h+QLp1FAalkLU3DL7nn
+UNVOKlyrdnY3Rtd57EKZ96LspIlw3Dgrh6aqJOadkiQbvvb91C8ZF3rmMgeUVAVT
+Q+lsvK9Hy7zL/b07RBKB8WtLu+20z6slTxjSzAL8o0+1QjPLWc0J3NNQ/aB2jKx+
+ZopC9q0ckvO2+xRG603XLzDgbe5bNr5EdLcgBVeFTegAGaL2DOauocBC36esgl3H
+aLcY5olLmmv6znn58yynAgMBAAGjggFQMIIBTDBIBgNVHSAEQTA/MD0GBFUdIAAw
+NTAzBggrBgEFBQcCARYnaHR0cDovL3d3dy5kaWdpbm90YXIubmwvY3BzL3BraW92
+ZXJoZWlkMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMIGABgNVHSME
+eTB3gBQLhtYPd6NosftkCcOIblwEHFfpPaFZpFcwVTELMAkGA1UEBhMCTkwxHjAc
+BgNVBAoTFVN0YWF0IGRlciBOZWRlcmxhbmRlbjEmMCQGA1UEAxMdU3RhYXQgZGVy
+IE5lZGVybGFuZGVuIFJvb3QgQ0GCBACYmnkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0
+cDovL2NybC5wa2lvdmVyaGVpZC5ubC9Eb21PdkxhdGVzdENSTC5jcmwwHQYDVR0O
+BBYEFEwIyY128ZjHPt881y91DbF2eZfMMA0GCSqGSIb3DQEBBQUAA4IBAQAMlIca
+v03jheLu19hjeQ5Q38aEW9K72fUxCho1l3TfFPoqDz7toOMI9tVOW6+mriXiRWsi
+D7dUKH6S3o0UbNEc5W50BJy37zRERd/Jgx0ZH8Apad+J1T/CsFNt5U4X5HNhIxMm
+cUP9TFnLw98iqiEr2b+VERqKpOKrp11Lbyn1UtHk0hWxi/7wA8+nfemZhzizDXMU
+5HIs4c71rQZIZPrTKbmi2Lv01QulQERDjqC/zlqlUkxk0xcxYczopIro5Ij76eUv
+BjMzm5RmZrGrUDqhCYF0U1onuabSJc/Tw6f/ltAv6uAejVLpGBwgCkegllYOQJBR
+RKwa/fHuhR/3Qlpl
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/3e26492e20b52de79e15766e6cb4251a1d566b0dbfb225aa7d08dda1dcebbf0a.pem b/chromium/net/data/ssl/blacklist/3e26492e20b52de79e15766e6cb4251a1d566b0dbfb225aa7d08dda1dcebbf0a.pem
new file mode 100644
index 00000000000..786d912deca
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/3e26492e20b52de79e15766e6cb4251a1d566b0dbfb225aa7d08dda1dcebbf0a.pem
@@ -0,0 +1,104 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 3e:0c:9e:87:69:aa:95:5c:ea:23:d8:45:9e:d4:5b:51
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3
+ Validity
+ Not Before: May 18 00:00:00 2008 GMT
+ Not After : May 17 23:59:59 2018 GMT
+ Subject: C=EG, O=Egypt Trust, OU=VeriSign Trust Network, OU=Terms of use at https://www.egypttrust.com/repository/rpa (c)08, CN=Egypt Trust Class 3 Managed PKI Operational Administrator CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c2:38:2e:af:54:92:8c:27:8b:ca:40:10:ee:01:
+ 5d:a5:9c:d9:09:2a:05:e8:f7:c9:73:89:11:0f:e4:
+ 6e:fb:d8:cd:3c:60:02:a4:48:9f:e2:0b:d5:c0:b5:
+ e6:a7:db:d9:3d:ec:e7:9b:2b:97:71:c3:87:9f:09:
+ 01:e0:9d:e9:21:5b:29:3d:af:28:eb:a7:6c:69:db:
+ 88:bf:13:eb:0d:c9:d2:32:69:06:e5:67:53:a6:4a:
+ c7:12:5d:4e:68:28:c3:6f:ac:fa:54:e6:d8:6f:dc:
+ 98:bf:71:4a:34:d0:8f:aa:c1:fe:15:fb:14:3a:13:
+ 8b:0e:d5:48:92:7e:77:03:d9:9a:ed:2e:9e:be:6d:
+ 45:c6:f7:55:46:65:db:16:88:5c:c5:a2:1e:c0:b4:
+ ed:83:41:2b:38:8c:79:ed:ff:e8:61:c0:9d:13:e1:
+ a2:95:29:54:59:28:a3:52:24:68:b5:f9:75:91:d2:
+ 6d:30:5e:97:35:87:f2:15:c4:55:d4:50:ac:e6:d5:
+ 3a:a2:35:69:35:9c:2f:18:a7:a3:64:92:11:e3:af:
+ 85:b0:c6:58:4e:8c:22:ac:f0:e6:be:38:e5:25:b5:
+ 97:61:1f:15:39:33:60:02:cd:40:43:59:1f:bc:47:
+ c0:15:ab:bd:2e:bf:22:94:8b:91:92:2b:61:c2:48:
+ f3:6b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Certificate Policies:
+ Policy: 2.16.840.1.113733.1.7.23.3
+ CPS: https://www.egypttrust.com/repository/cps
+ User Notice:
+ Explicit Text: https://www.egypttrust.com/repository/rpa
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Netscape Cert Type:
+ SSL CA, S/MIME CA
+ X509v3 Subject Key Identifier:
+ A7:4B:02:C9:76:5B:7E:E0:AB:4C:17:EB:5A:75:69:C6:C4:E5:05:DC
+ X509v3 Authority Key Identifier:
+ DirName:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 1999 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G3
+ serial:9B:7E:06:49:A3:3E:62:B9:D5:EE:90:48:71:29:EF:57
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 47:ac:be:84:8c:a7:af:63:88:d7:fc:a7:46:f5:c2:15:8e:99:
+ a6:93:33:0c:d0:cf:75:91:06:41:38:8e:ac:99:6b:c0:4b:ca:
+ f5:a9:7e:d6:89:11:26:f1:c6:93:f2:07:67:dc:8a:4b:89:b9:
+ a4:e8:10:87:f7:7f:65:21:65:d6:cf:9b:10:c0:9d:60:4a:1f:
+ 57:99:ae:e3:86:53:39:c4:b4:5c:ae:3c:14:5e:90:5e:41:e9:
+ ff:7b:4a:ea:b9:78:49:2c:b0:da:a1:50:67:95:7e:3b:d6:75:
+ e3:64:a8:50:cc:db:ed:07:bc:86:9b:c2:b5:bd:ec:5b:ed:e1:
+ c1:05:b3:f4:c3:d4:9d:33:91:37:06:5a:2f:76:9c:e8:d6:e2:
+ 6e:8e:77:3b:80:89:05:20:2a:11:19:e6:81:34:5e:91:d4:7d:
+ fc:a4:59:1c:4a:42:42:42:73:6f:89:97:e1:09:e7:8a:91:f0:
+ c0:de:4c:c2:d2:aa:76:81:e2:66:60:e2:48:08:d5:8d:a0:d6:
+ f8:6a:11:4b:af:f7:56:5b:03:1b:90:68:45:eb:cc:50:85:0c:
+ 3e:01:dc:af:fb:07:39:54:30:56:60:36:42:13:1b:64:ae:3b:
+ c7:c5:ad:24:80:70:46:d5:60:2c:d2:ed:e3:c1:2e:b5:a2:cd:
+ 06:8c:b0:65
+-----BEGIN CERTIFICATE-----
+MIIGCjCCBPKgAwIBAgIQPgyeh2mqlVzqI9hFntRbUTANBgkqhkiG9w0BAQUFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMTk5OSBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzMwHhcNMDgwNTE4MDAwMDAwWhcNMTgwNTE3MjM1OTU5WjCB1TEL
+MAkGA1UEBhMCRUcxFDASBgNVBAoTC0VneXB0IFRydXN0MR8wHQYDVQQLExZWZXJp
+U2lnbiBUcnVzdCBOZXR3b3JrMUgwRgYDVQQLEz9UZXJtcyBvZiB1c2UgYXQgaHR0
+cHM6Ly93d3cuZWd5cHR0cnVzdC5jb20vcmVwb3NpdG9yeS9ycGEgKGMpMDgxRTBD
+BgNVBAMTPEVneXB0IFRydXN0IENsYXNzIDMgTWFuYWdlZCBQS0kgT3BlcmF0aW9u
+YWwgQWRtaW5pc3RyYXRvciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMI4Lq9Ukowni8pAEO4BXaWc2QkqBej3yXOJEQ/kbvvYzTxgAqRIn+IL1cC1
+5qfb2T3s55srl3HDh58JAeCd6SFbKT2vKOunbGnbiL8T6w3J0jJpBuVnU6ZKxxJd
+Tmgow2+s+lTm2G/cmL9xSjTQj6rB/hX7FDoTiw7VSJJ+dwPZmu0unr5tRcb3VUZl
+2xaIXMWiHsC07YNBKziMee3/6GHAnRPhopUpVFkoo1IkaLX5dZHSbTBelzWH8hXE
+VdRQrObVOqI1aTWcLxino2SSEeOvhbDGWE6MIqzw5r445SW1l2EfFTkzYALNQENZ
+H7xHwBWrvS6/IpSLkZIrYcJI82sCAwEAAaOCAd0wggHZMBIGA1UdEwEB/wQIMAYB
+Af8CAQAwgYwGA1UdIASBhDCBgTB/BgtghkgBhvhFAQcXAzBwMDUGCCsGAQUFBwIB
+FilodHRwczovL3d3dy5lZ3lwdHRydXN0LmNvbS9yZXBvc2l0b3J5L2NwczA3Bggr
+BgEFBQcCAjArGilodHRwczovL3d3dy5lZ3lwdHRydXN0LmNvbS9yZXBvc2l0b3J5
+L3JwYTAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgEGMB0GA1UdDgQW
+BBSnSwLJdlt+4KtMF+tadWnGxOUF3DCB8QYDVR0jBIHpMIHmoYHQpIHNMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
+cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
+LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
+aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgLSBHM4IRAJt+BkmjPmK51e6QSHEp71cwDQYJKoZIhvcNAQEFBQADggEBAEes
+voSMp69jiNf8p0b1whWOmaaTMwzQz3WRBkE4jqyZa8BLyvWpftaJESbxxpPyB2fc
+ikuJuaToEIf3f2UhZdbPmxDAnWBKH1eZruOGUznEtFyuPBRekF5B6f97Suq5eEks
+sNqhUGeVfjvWdeNkqFDM2+0HvIabwrW97Fvt4cEFs/TD1J0zkTcGWi92nOjW4m6O
+dzuAiQUgKhEZ5oE0XpHUffykWRxKQkJCc2+Jl+EJ54qR8MDeTMLSqnaB4mZg4kgI
+1Y2g1vhqEUuv91ZbAxuQaEXrzFCFDD4B3K/7BzlUMFZgNkITG2SuO8fFrSSAcEbV
+YCzS7ePBLrWizQaMsGU=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/42187727be39faf667aeb92bf0cc4e268f6e2ead2cefbec575bdc90430024f69.pem b/chromium/net/data/ssl/blacklist/42187727be39faf667aeb92bf0cc4e268f6e2ead2cefbec575bdc90430024f69.pem
new file mode 100644
index 00000000000..c84c60a9fb9
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/42187727be39faf667aeb92bf0cc4e268f6e2ead2cefbec575bdc90430024f69.pem
@@ -0,0 +1,103 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2087 (0x827)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=T\xC3\x9CRKTRUST Elektronik Sunucu Sertifikas\xC4\xB1 Hizmetleri, C=TR, O=T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve Bili\xC5\x9Fim G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E. (c) Kas\xC4\xB1m 2005
+ Validity
+ Not Before: Aug 8 07:07:51 2011 GMT
+ Not After : Jul 6 07:07:51 2021 GMT
+ Subject: C=TR, ST=ANKARA, L=ANKARA, O=EGO, OU=EGO BILGI ISLEM, CN=*.EGO.GOV.TR
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:9c:e8:8f:60:69:76:5e:d1:d4:cf:f3:17:a4:
+ 1f:e2:cb:b6:17:cb:c3:a8:84:8a:be:e4:ee:c8:98:
+ 4d:00:78:45:18:70:ac:1e:36:a2:c4:63:07:b2:9b:
+ b3:d2:5d:d5:e7:49:2a:fc:40:96:6c:df:24:29:a7:
+ 93:ac:1d:75:d9:03:ab:59:35:36:ef:a8:ae:a7:51:
+ a1:f8:e9:44:3a:24:7d:be:54:38:54:03:f4:d1:d5:
+ 94:8c:3e:b3:f4:74:05:0a:2f:16:dc:4b:04:b6:28:
+ 87:89:83:94:f4:17:0f:a4:f9:1a:51:b1:02:c0:fe:
+ 27:19:5c:11:f1:a3:f0:84:1e:4f:18:12:5c:f7:ca:
+ e8:99:db:dc:89:89:14:a5:23:8e:c2:4b:92:46:da:
+ 28:03:bb:51:94:b1:6e:ef:64:1a:36:95:cd:d4:db:
+ 9e:07:7e:88:dd:a6:a3:3e:4d:18:ca:25:f2:db:0f:
+ 17:96:02:bb:40:8e:0f:49:20:67:4a:af:90:6e:51:
+ 68:71:65:66:2e:11:7d:e2:37:bb:a7:2e:a5:0a:79:
+ 65:ac:81:57:a5:1d:c5:59:92:c3:e4:67:08:e8:72:
+ a5:05:2e:fc:01:0f:88:30:12:c5:1e:1b:04:57:0e:
+ 4d:42:3f:74:72:14:99:0a:57:c1:58:16:73:21:a5:
+ 7d:47
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:AB:4E:36:03:30:D2:DB:D5:0A:68:BE:87:A5:50:6C:FC:F6:70:A5:25
+
+ X509v3 Subject Key Identifier:
+ 64:FB:1B:86:3D:B8:4A:F2:44:82:F9:56:3D:EA:26:C0:F4:E3:B3:34
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Certificate Policies:
+ Policy: 2.16.792.3.0.3.1.1.1
+ CPS: http://www.turktrust.com.tr/sue
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://www.turktrust.com.tr/sil/TURKTRUST_SSL_SIL_s2.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://www.turktrust.com.tr/sertifikalar/TURKTRUST_Elektronik_Sunucu_Sertifikasi_Hizmetleri_s2.crt
+ OCSP - URI:http://ocsp.turktrust.com.tr
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 8f:cf:50:08:2c:a8:5b:44:b6:d0:47:18:0d:90:27:bc:52:c5:
+ 9a:8b:a0:2b:de:c1:b7:af:22:57:53:8c:eb:6d:be:0b:27:b2:
+ 7f:84:b3:fb:52:c1:93:57:fd:9e:2d:df:19:3d:10:f9:15:99:
+ 25:85:aa:e5:8b:92:06:22:d5:82:4d:cd:2d:cc:67:c1:ed:f0:
+ 9a:7b:c4:ad:48:2a:d5:00:ed:01:a3:65:05:63:04:32:49:4e:
+ 95:61:9f:27:47:96:6a:29:65:52:c9:09:6c:37:78:2b:08:19:
+ 1c:31:23:ee:0f:e3:60:44:2a:53:5b:74:ce:82:5d:c0:cf:f3:
+ 36:c9:cb:1e:48:70:71:66:79:3d:09:e7:6e:97:df:d4:2b:7f:
+ d4:b1:ff:f2:97:72:d9:e4:43:99:19:aa:9e:22:d4:87:ca:f6:
+ 95:97:c9:7a:e7:55:64:6e:b2:21:bc:6c:a8:fd:ed:d8:90:aa:
+ e5:cd:8f:d6:30:e1:00:61:77:83:d0:e2:b2:41:f4:0b:3b:11:
+ 75:b5:69:a1:67:6b:f8:f6:35:5f:3f:f5:f4:6f:17:12:95:fd:
+ af:e2:01:26:12:dd:6e:4a:55:a3:44:21:d0:0d:74:9b:31:4f:
+ fc:65:24:e5:ff:fc:9e:1a:36:1e:f2:da:54:c8:56:bf:5a:8a:
+ 70:5f:08:85
+-----BEGIN CERTIFICATE-----
+MIIFPTCCBCWgAwIBAgICCCcwDQYJKoZIhvcNAQEFBQAwgawxPTA7BgNVBAMMNFTD
+nFJLVFJVU1QgRWxla3Ryb25payBTdW51Y3UgU2VydGlmaWthc8SxIEhpem1ldGxl
+cmkxCzAJBgNVBAYTAlRSMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0
+acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAo
+YykgS2FzxLFtICAyMDA1MB4XDTExMDgwODA3MDc1MVoXDTIxMDcwNjA3MDc1MVow
+bjELMAkGA1UEBhMCVFIxDzANBgNVBAgMBkFOS0FSQTEPMA0GA1UEBwwGQU5LQVJB
+MQwwCgYDVQQKDANFR08xGDAWBgNVBAsMD0VHTyBCSUxHSSBJU0xFTTEVMBMGA1UE
+AwwMKi5FR08uR09WLlRSMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+v5zoj2Bpdl7R1M/zF6Qf4su2F8vDqISKvuTuyJhNAHhFGHCsHjaixGMHspuz0l3V
+50kq/ECWbN8kKaeTrB112QOrWTU276iup1Gh+OlEOiR9vlQ4VAP00dWUjD6z9HQF
+Ci8W3EsEtiiHiYOU9BcPpPkaUbECwP4nGVwR8aPwhB5PGBJc98romdvciYkUpSOO
+wkuSRtooA7tRlLFu72QaNpXN1NueB36I3aajPk0YyiXy2w8XlgK7QI4PSSBnSq+Q
+blFocWVmLhF94je7py6lCnllrIFXpR3FWZLD5GcI6HKlBS78AQ+IMBLFHhsEVw5N
+Qj90chSZClfBWBZzIaV9RwIDAQABo4IBpDCCAaAwHwYDVR0jBBgwFoAUq042AzDS
+29UKaL6HpVBs/PZwpSUwHQYDVR0OBBYEFGT7G4Y9uEryRIL5Vj3qJsD047M0MA4G
+A1UdDwEB/wQEAwIBBjBFBgNVHSAEPjA8MDoGCWCGGAMAAwEBATAtMCsGCCsGAQUF
+BwIBFh9odHRwOi8vd3d3LnR1cmt0cnVzdC5jb20udHIvc3VlMA8GA1UdEwEB/wQF
+MAMBAf8wSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL3d3dy50dXJrdHJ1c3QuY29t
+LnRyL3NpbC9UVVJLVFJVU1RfU1NMX1NJTF9zMi5jcmwwgaoGCCsGAQUFBwEBBIGd
+MIGaMG4GCCsGAQUFBzAChmJodHRwOi8vd3d3LnR1cmt0cnVzdC5jb20udHIvc2Vy
+dGlmaWthbGFyL1RVUktUUlVTVF9FbGVrdHJvbmlrX1N1bnVjdV9TZXJ0aWZpa2Fz
+aV9IaXptZXRsZXJpX3MyLmNydDAoBggrBgEFBQcwAYYcaHR0cDovL29jc3AudHVy
+a3RydXN0LmNvbS50cjANBgkqhkiG9w0BAQUFAAOCAQEAj89QCCyoW0S20EcYDZAn
+vFLFmougK97Bt68iV1OM622+Cyeyf4Sz+1LBk1f9ni3fGT0Q+RWZJYWq5YuSBiLV
+gk3NLcxnwe3wmnvErUgq1QDtAaNlBWMEMklOlWGfJ0eWaillUskJbDd4KwgZHDEj
+7g/jYEQqU1t0zoJdwM/zNsnLHkhwcWZ5PQnnbpff1Ct/1LH/8pdy2eRDmRmqniLU
+h8r2lZfJeudVZG6yIbxsqP3t2JCq5c2P1jDhAGF3g9DiskH0CzsRdbVpoWdr+PY1
+Xz/19G8XEpX9r+IBJhLdbkpVo0Qh0A10mzFP/GUk5f/8nho2HvLaVMhWv1qKcF8I
+hQ==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/450f1b421bb05c8609854884559c323319619e8b06b001ea2dcbb74a23aa3be2.pem b/chromium/net/data/ssl/blacklist/450f1b421bb05c8609854884559c323319619e8b06b001ea2dcbb74a23aa3be2.pem
new file mode 100644
index 00000000000..181fe7b7afb
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/450f1b421bb05c8609854884559c323319619e8b06b001ea2dcbb74a23aa3be2.pem
@@ -0,0 +1,82 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1184640176 (0x469c2cb0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
+ Validity
+ Not Before: Jul 26 15:59:00 2007 GMT
+ Not After : Aug 26 16:29:00 2013 GMT
+ Subject: C=NL, O=DigiNotar, CN=DigiNotar Services 1024 CA/emailAddress=info@diginotar.nl
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:da:9b:4d:5d:3c:f9:d1:e2:8b:c6:c6:08:20:c5:
+ d9:1e:48:ec:66:58:67:79:62:2b:41:63:f4:89:8d:
+ 68:da:af:b8:94:36:8b:19:24:a4:a0:93:d2:99:0f:
+ b2:ad:2d:35:4d:cd:2f:6a:e1:f9:9b:19:2b:bc:04:
+ 1a:7e:2d:3d:52:64:cd:f1:3e:67:0f:89:2e:e8:f2:
+ 4f:ae:a6:08:a1:85:fe:a1:a9:09:e6:c6:ab:3e:43:
+ fc:af:7a:03:91:da:a6:39:a6:61:ee:98:4f:18:a8:
+ d3:b3:af:66:82:e9:9f:bc:dd:72:f9:06:04:bd:12:
+ d9:18:24:e7:ab:93:53:8b:59
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication, E-mail Protection
+ X509v3 Certificate Policies:
+ Policy: X509v3 Any Policy
+
+ Authority Information Access:
+ OCSP - URI:http://ocsp.entrust.net
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.entrust.net/server1.crl
+
+ X509v3 Subject Key Identifier:
+ FE:DC:94:49:0C:6F:EF:5C:7F:C6:F1:12:99:4F:16:49:AD:FB:82:65
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Authority Key Identifier:
+ keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
+
+ 1.2.840.113533.7.65.0:
+ 0
+..V7.1....
+ Signature Algorithm: sha1WithRSAEncryption
+ 63:74:6a:37:a9:3f:96:9c:66:c8:58:ac:09:c9:ef:f5:65:94:
+ 7f:a3:02:c4:38:31:bd:5d:23:87:ec:d4:56:b2:c9:b2:6e:e4:
+ 05:06:fc:ec:f5:fa:88:70:59:d4:ee:e6:dd:b5:7a:a0:a3:60:
+ 2f:02:0c:ab:de:12:5d:af:f0:35:4b:aa:8a:47:91:1a:f5:85:
+ 2c:42:c7:1d:ef:95:43:b3:5e:b8:95:93:a5:da:c5:28:aa:ad:
+ 72:2d:31:ad:99:6b:6c:ff:8c:21:27:af:ad:9a:91:2b:c7:dd:
+ 58:c3:6e:07:c5:9f:79:d2:c7:8c:55:bf:4c:c7:27:5e:51:16:
+ 2b:3e
+-----BEGIN CERTIFICATE-----
+MIIDzTCCAzagAwIBAgIERpwssDANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
+VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
+ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
+KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
+ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNzA3
+MjYxNTU5MDBaFw0xMzA4MjYxNjI5MDBaMGgxCzAJBgNVBAYTAk5MMRIwEAYDVQQK
+EwlEaWdpTm90YXIxIzAhBgNVBAMTGkRpZ2lOb3RhciBTZXJ2aWNlcyAxMDI0IENB
+MSAwHgYJKoZIhvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubDCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEA2ptNXTz50eKLxsYIIMXZHkjsZlhneWIrQWP0iY1o2q+4
+lDaLGSSkoJPSmQ+yrS01Tc0vauH5mxkrvAQafi09UmTN8T5nD4ku6PJPrqYIoYX+
+oakJ5sarPkP8r3oDkdqmOaZh7phPGKjTs69mgumfvN1y+QYEvRLZGCTnq5NTi1kC
+AwEAAaOCASYwggEiMBIGA1UdEwEB/wQIMAYBAf8CAQAwJwYDVR0lBCAwHgYIKwYB
+BQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDBDARBgNVHSAECjAIMAYGBFUdIAAwMwYI
+KwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5lbnRydXN0Lm5l
+dDAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLmVudHJ1c3QubmV0L3NlcnZl
+cjEuY3JsMB0GA1UdDgQWBBT+3JRJDG/vXH/G8RKZTxZJrfuCZTALBgNVHQ8EBAMC
+AQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0BowGQYJKoZIhvZ9B0EA
+BAwwChsEVjcuMQMCAIEwDQYJKoZIhvcNAQEFBQADgYEAY3RqN6k/lpxmyFisCcnv
+9WWUf6MCxDgxvV0jh+zUVrLJsm7kBQb87PX6iHBZ1O7m3bV6oKNgLwIMq94SXa/w
+NUuqikeRGvWFLELHHe+VQ7NeuJWTpdrFKKqtci0xrZlrbP+MISevrZqRK8fdWMNu
+B8WfedLHjFW/TMcnXlEWKz4=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/4bf6bb839b03b72839329b4ea70bb1b2f0d07e014d9d24aa9cc596114702bee3.pem b/chromium/net/data/ssl/blacklist/4bf6bb839b03b72839329b4ea70bb1b2f0d07e014d9d24aa9cc596114702bee3.pem
new file mode 100644
index 00000000000..66e24b2e8e8
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/4bf6bb839b03b72839329b4ea70bb1b2f0d07e014d9d24aa9cc596114702bee3.pem
@@ -0,0 +1,114 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 92:39:d5:34:8f:40:d1:69:5a:74:54:70:e1:f2:3f:43
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
+ Validity
+ Not Before: Mar 15 00:00:00 2011 GMT
+ Not After : Mar 14 23:59:59 2014 GMT
+ Subject: C=US/postalCode=38477, ST=Florida, L=English/street=Sea Village 10, O=Google Ltd., OU=Tech Dept., OU=Hosted by GTI Group Corporation, OU=PlatinumSSL, CN=addons.mozilla.org
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ab:c6:6d:36:f3:15:73:78:83:73:ce:74:85:d5:
+ ae:ec:b2:f0:e0:24:1f:13:83:b8:20:ac:bb:9a:fe:
+ 88:bb:ab:a1:1d:0b:1f:45:00:aa:49:b7:35:37:0c:
+ 6a:ef:47:4c:b9:d1:be:e3:57:12:04:8d:92:c7:b6:
+ ec:01:bc:b6:da:c7:81:38:20:ad:72:85:e6:0e:fc:
+ 81:6c:07:ad:68:76:38:c5:44:d7:cc:c6:4a:c5:97:
+ 3e:64:f4:51:e6:f0:7e:b2:ec:56:f7:25:82:4d:49:
+ 98:cb:16:98:dd:23:f1:89:91:d1:17:97:40:99:26:
+ d6:e2:a2:2b:5e:df:bd:89:f2:1b:1a:53:2d:cc:50:
+ 41:7a:d0:3d:2a:0c:55:70:14:01:e9:58:49:10:7a:
+ 0b:93:82:8b:e1:1e:ed:3a:80:10:82:ce:96:8a:34:
+ f0:cc:d7:d3:b9:b4:50:87:55:54:09:b8:9d:42:28:
+ 55:00:e5:8c:35:54:bf:dd:25:91:46:b7:0d:e5:5d:
+ 83:a8:e5:8b:fb:84:e4:3c:ae:76:da:c4:43:2b:5b:
+ 74:0b:f8:be:5d:68:f1:78:5b:b5:ce:7d:f1:5d:99:
+ 40:da:ca:ee:38:81:50:be:98:a1:6c:b8:24:ad:f3:
+ af:8c:0f:d7:11:28:2c:84:18:4c:7d:b5:d9:8f:30:
+ b5:1b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45
+
+ X509v3 Subject Key Identifier:
+ DD:80:D2:54:3D:F7:4C:70:CA:A3:B0:DD:34:7A:32:E4:E8:3B:5A:3B
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6449.1.2.1.3.4
+ CPS: https://secure.comodo.com/CPS
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/UTN-USERFirst-Hardware.crl
+
+ Full Name:
+ URI:http://crl.comodo.net/UTN-USERFirst-Hardware.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://crt.comodoca.com/UTNAddTrustServerCA.crt
+ OCSP - URI:http://ocsp.comodoca.com
+
+ X509v3 Subject Alternative Name:
+ DNS:addons.mozilla.org, DNS:www.addons.mozilla.org
+ Signature Algorithm: sha1WithRSAEncryption
+ 33:3b:63:15:fc:b1:ec:14:2c:93:dd:75:94:de:81:5a:d9:4e:
+ 99:be:fb:4a:a4:39:55:4d:a1:40:7a:de:13:2a:87:a9:37:cf:
+ e8:d5:fb:ad:d1:7b:6d:6f:8c:20:87:82:54:e6:57:49:bc:20:
+ 28:84:cd:d6:01:d9:93:8b:17:6e:23:66:e5:84:c8:80:3f:c6:
+ a1:70:80:e4:ec:4d:1d:f9:fc:91:5a:73:62:29:9a:f7:20:1c:
+ 61:e0:8b:39:9f:ca:bc:7e:8d:dd:bc:d9:b1:e3:9f:9e:df:15:
+ 53:91:21:52:0b:d9:1a:23:0f:66:36:db:ac:93:96:4a:a3:a5:
+ 22:cf:29:f7:a2:99:a8:f6:b6:d9:40:ae:d9:7e:b6:f6:58:2e:
+ 9b:ac:36:ca:64:8f:65:52:dc:86:9c:82:ab:6e:50:4b:da:5f:
+ fa:05:00:88:30:0e:de:8d:56:bf:81:47:8d:3d:06:e2:b2:62:
+ 92:67:8f:9e:c8:9a:b2:e5:06:b8:70:24:b8:77:7c:23:0a:38:
+ c3:79:08:d8:b1:51:9d:ac:95:11:c7:40:17:9e:a3:1c:8f:f2:
+ 11:a7:68:27:da:49:05:84:18:7c:58:2d:01:67:5c:e5:9f:a1:
+ 29:bb:4a:39:45:2f:bf:11:aa:79:a2:ed:b4:d4:b5:65:43:b7:
+ 93:46:8a:d3
+-----BEGIN CERTIFICATE-----
+MIIF+DCCBOCgAwIBAgIRAJI51TSPQNFpWnRUcOHyP0MwDQYJKoZIhvcNAQEFBQAw
+gZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtl
+IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMY
+aHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR8wHQYDVQQDExZVVE4tVVNFUkZpcnN0
+LUhhcmR3YXJlMB4XDTExMDMxNTAwMDAwMFoXDTE0MDMxNDIzNTk1OVowgeIxCzAJ
+BgNVBAYTAlVTMQ4wDAYDVQQREwUzODQ3NzEQMA4GA1UECBMHRmxvcmlkYTEQMA4G
+A1UEBxMHRW5nbGlzaDEXMBUGA1UECRMOU2VhIFZpbGxhZ2UgMTAxFDASBgNVBAoT
+C0dvb2dsZSBMdGQuMRMwEQYDVQQLEwpUZWNoIERlcHQuMSgwJgYDVQQLEx9Ib3N0
+ZWQgYnkgR1RJIEdyb3VwIENvcnBvcmF0aW9uMRQwEgYDVQQLEwtQbGF0aW51bVNT
+TDEbMBkGA1UEAxMSYWRkb25zLm1vemlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAq8ZtNvMVc3iDc850hdWu7LLw4CQfE4O4IKy7mv6Iu6uh
+HQsfRQCqSbc1Nwxq70dMudG+41cSBI2Sx7bsAby22seBOCCtcoXmDvyBbAetaHY4
+xUTXzMZKxZc+ZPRR5vB+suxW9yWCTUmYyxaY3SPxiZHRF5dAmSbW4qIrXt+9ifIb
+GlMtzFBBetA9KgxVcBQB6VhJEHoLk4KL4R7tOoAQgs6WijTwzNfTubRQh1VUCbid
+QihVAOWMNVS/3SWRRrcN5V2DqOWL+4TkPK522sRDK1t0C/i+XWjxeFu1zn3xXZlA
+2sruOIFQvpihbLgkrfOvjA/XESgshBhMfbXZjzC1GwIDAQABo4IB8DCCAewwHwYD
+VR0jBBgwFoAUoXJfJhsomEOVXQc31YWWnUvSw0UwHQYDVR0OBBYEFN2A0lQ990xw
+yqOw3TR6MuToO1o7MA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1Ud
+JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBGBgNVHSAEPzA9MDsGDCsGAQQBsjEB
+AgEDBDArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQ
+UzB7BgNVHR8EdDByMDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9VVE4t
+VVNFUkZpcnN0LUhhcmR3YXJlLmNybDA2oDSgMoYwaHR0cDovL2NybC5jb21vZG8u
+bmV0L1VUTi1VU0VSRmlyc3QtSGFyZHdhcmUuY3JsMHEGCCsGAQUFBwEBBGUwYzA7
+BggrBgEFBQcwAoYvaHR0cDovL2NydC5jb21vZG9jYS5jb20vVVROQWRkVHJ1c3RT
+ZXJ2ZXJDQS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNv
+bTA1BgNVHREELjAsghJhZGRvbnMubW96aWxsYS5vcmeCFnd3dy5hZGRvbnMubW96
+aWxsYS5vcmcwDQYJKoZIhvcNAQEFBQADggEBADM7YxX8sewULJPddZTegVrZTpm+
++0qkOVVNoUB63hMqh6k3z+jV+63Re21vjCCHglTmV0m8ICiEzdYB2ZOLF24jZuWE
+yIA/xqFwgOTsTR35/JFac2IpmvcgHGHgizmfyrx+jd282bHjn57fFVORIVIL2Roj
+D2Y226yTlkqjpSLPKfeimaj2ttlArtl+tvZYLpusNspkj2VS3IacgqtuUEvaX/oF
+AIgwDt6NVr+BR409BuKyYpJnj57ImrLlBrhwJLh3fCMKOMN5CNixUZ2slRHHQBee
+oxyP8hGnaCfaSQWEGHxYLQFnXOWfoSm7SjlFL78Rqnmi7bTUtWVDt5NGitM=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/4fee0163686ecbd65db968e7494f55d84b25486d438e9de558d629d28cd4d176.pem b/chromium/net/data/ssl/blacklist/4fee0163686ecbd65db968e7494f55d84b25486d438e9de558d629d28cd4d176.pem
new file mode 100644
index 00000000000..2b7ef66dfe3
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/4fee0163686ecbd65db968e7494f55d84b25486d438e9de558d629d28cd4d176.pem
@@ -0,0 +1,116 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1184644297 (0x469c3cc9)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
+ Validity
+ Not Before: Apr 26 05:00:00 2007 GMT
+ Not After : Aug 14 20:12:36 2013 GMT
+ Subject: C=NL, O=DigiNotar, CN=DigiNotar Root CA/emailAddress=info@diginotar.nl
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:ac:b0:58:c1:00:bd:d8:21:08:0b:2b:9a:fe:6e:
+ 56:30:05:9f:1b:77:90:10:41:5c:c3:0d:87:11:77:
+ 8e:81:f1:ca:7c:e9:8c:6a:ed:38:74:35:bb:da:df:
+ f9:bb:c0:09:37:b4:96:73:81:7d:33:1a:98:39:f7:
+ 93:6f:95:7f:3d:b9:b1:75:87:ba:51:48:e8:8b:70:
+ 3e:95:04:c5:d8:b6:c3:16:d9:88:b0:b1:87:1d:70:
+ da:86:b4:0f:14:8b:7a:cf:10:d1:74:36:a2:12:7b:
+ 77:86:4a:79:e6:7b:df:02:11:68:a5:4e:86:ae:34:
+ 58:9b:24:13:78:56:22:25:1e:01:8b:4b:51:71:fb:
+ 82:cc:59:96:69:88:5a:68:53:c5:b9:0d:02:37:cb:
+ 4b:bc:66:4a:90:7e:2a:0b:05:07:ed:16:5f:55:90:
+ 75:d8:46:c9:1b:83:e2:08:be:f1:23:cc:99:1d:d6:
+ 2a:0f:83:20:15:58:27:82:2e:fa:e2:22:c2:49:b1:
+ b9:01:81:6a:9d:6d:9d:40:77:68:76:4e:21:2a:6d:
+ 84:40:85:4e:76:99:7c:82:f3:f3:b7:02:59:d4:26:
+ 01:1b:8e:df:ad:53:06:d1:ae:18:dd:e2:b2:3a:cb:
+ d7:88:38:8e:ac:5b:29:b9:19:d3:98:f9:18:03:cf:
+ 48:82:86:66:0b:1b:69:0f:c9:eb:38:88:7a:26:1a:
+ 05:4c:92:d7:24:d4:96:f2:ac:52:2d:a3:47:d5:52:
+ f6:3f:fe:ce:84:06:70:a6:aa:3e:a2:f2:b6:56:34:
+ 18:57:a2:e4:81:6d:e7:ca:f0:6a:d3:c7:91:6b:02:
+ 83:41:7c:15:ef:6b:9a:64:5e:e3:d0:3c:e5:b1:eb:
+ 7b:5d:86:fb:cb:e6:77:49:cd:a3:65:dc:f7:b9:9c:
+ b8:e4:0b:5f:93:cf:cc:30:1a:32:1c:ce:1c:63:95:
+ a5:f9:ea:e1:74:8b:9e:e9:2b:a9:30:7b:a0:18:1f:
+ 0e:18:0b:e5:5b:a9:d3:d1:6c:1e:07:67:8f:91:4b:
+ a9:8a:bc:d2:66:aa:93:01:88:b2:91:fa:31:5c:d5:
+ a6:c1:52:08:09:cd:0a:63:a2:d3:22:a6:e8:a1:d9:
+ 39:06:97:f5:6e:8d:02:90:8c:14:7b:3f:80:cd:1b:
+ 9c:ba:c4:58:72:23:af:b6:56:9f:c6:7a:42:33:29:
+ 07:3f:82:c9:e6:1f:05:0d:cd:4c:28:36:8b:d3:c8:
+ 3e:1c:c6:88:ef:5e:ee:89:64:e9:1d:eb:da:89:7e:
+ 32:a6:69:d1:dd:cc:88:9f:d1:d0:c9:66:21:dc:06:
+ 67:c5:94:7a:9a:6d:62:4c:7d:cc:e0:64:80:b2:9e:
+ 47:8e:a3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:1
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication, E-mail Protection
+ X509v3 Certificate Policies:
+ Policy: X509v3 Any Policy
+
+ Authority Information Access:
+ OCSP - URI:http://ocsp.entrust.net
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.entrust.net/server1.crl
+
+ X509v3 Subject Key Identifier:
+ 88:68:BF:E0:8E:35:C4:3B:38:6B:62:F7:28:3B:84:81:C8:0C:D7:4D
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Authority Key Identifier:
+ keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
+
+ 1.2.840.113533.7.65.0:
+ 0
+..V7.1....
+ Signature Algorithm: sha1WithRSAEncryption
+ 8f:7b:f6:b0:5e:a7:cb:6e:dd:37:8b:ba:76:a9:82:c6:74:8e:
+ d5:e9:18:31:63:29:64:a4:f3:b7:63:d6:30:b2:62:2f:aa:fc:
+ 6c:83:c9:9e:99:41:93:51:3f:4b:05:fb:ab:70:b1:ca:b4:e6:
+ 50:a5:58:dc:b7:4d:13:8c:a7:b4:1e:ba:82:ce:1b:b5:2d:c3:
+ 73:89:6a:cc:14:b6:9e:18:82:50:0d:31:14:c7:11:ed:e0:f6:
+ 5b:62:7d:45:d1:1f:9b:52:bb:2e:ee:eb:28:b8:2c:3e:16:4e:
+ 6e:54:2c:fe:ab:fe:0e:a5:d0:29:e3:5d:86:f4:f9:bd:45:9b:
+ 3e:94
+-----BEGIN CERTIFICATE-----
+MIIFSDCCBLGgAwIBAgIERpw8yTANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
+VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
+ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
+KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
+ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNzA0
+MjYwNTAwMDBaFw0xMzA4MTQyMDEyMzZaMF8xCzAJBgNVBAYTAk5MMRIwEAYDVQQK
+EwlEaWdpTm90YXIxGjAYBgNVBAMTEURpZ2lOb3RhciBSb290IENBMSAwHgYJKoZI
+hvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubDCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAKywWMEAvdghCAsrmv5uVjAFnxt3kBBBXMMNhxF3joHxynzpjGrt
+OHQ1u9rf+bvACTe0lnOBfTMamDn3k2+Vfz25sXWHulFI6ItwPpUExdi2wxbZiLCx
+hx1w2oa0DxSLes8Q0XQ2ohJ7d4ZKeeZ73wIRaKVOhq40WJskE3hWIiUeAYtLUXH7
+gsxZlmmIWmhTxbkNAjfLS7xmSpB+KgsFB+0WX1WQddhGyRuD4gi+8SPMmR3WKg+D
+IBVYJ4Iu+uIiwkmxuQGBap1tnUB3aHZOISpthECFTnaZfILz87cCWdQmARuO361T
+BtGuGN3isjrL14g4jqxbKbkZ05j5GAPPSIKGZgsbaQ/J6ziIeiYaBUyS1yTUlvKs
+Ui2jR9VS9j/+zoQGcKaqPqLytlY0GFei5IFt58rwatPHkWsCg0F8Fe9rmmRe49A8
+5bHre12G+8vmd0nNo2Xc97mcuOQLX5PPzDAaMhzOHGOVpfnq4XSLnukrqTB7oBgf
+DhgL5Vup09FsHgdnj5FLqYq80maqkwGIspH6MVzVpsFSCAnNCmOi0yKm6KHZOQaX
+9W6NApCMFHs/gM0bnLrEWHIjr7ZWn8Z6QjMpBz+CyeYfBQ3NTCg2i9PIPhzGiO9e
+7olk6R3r2ol+MqZp0d3MiJ/R0MlmIdwGZ8WUepptYkx9zOBkgLKeR46jAgMBAAGj
+ggEmMIIBIjASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMB
+BggrBgEFBQcDAgYIKwYBBQUHAwQwEQYDVR0gBAowCDAGBgRVHSAAMDMGCCsGAQUF
+BwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZW50cnVzdC5uZXQwMwYD
+VR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9zZXJ2ZXIxLmNy
+bDAdBgNVHQ4EFgQUiGi/4I41xDs4a2L3KDuEgcgM100wCwYDVR0PBAQDAgEGMB8G
+A1UdIwQYMBaAFPAXYhNVPbP/CgBr+1CEl/PtYtAaMBkGCSqGSIb2fQdBAAQMMAob
+BFY3LjEDAgCBMA0GCSqGSIb3DQEBBQUAA4GBAI979rBep8tu3TeLunapgsZ0jtXp
+GDFjKWSk87dj1jCyYi+q/GyDyZ6ZQZNRP0sF+6twscq05lClWNy3TROMp7QeuoLO
+G7Utw3OJaswUtp4YglANMRTHEe3g9ltifUXRH5tSuy7u6yi4LD4WTm5ULP6r/g6l
+0CnjXYb0+b1Fmz6U
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/67ed4b703d15dc555f8c444b3a05a32579cb7599bd19c9babe10c584ea327ae0.pem b/chromium/net/data/ssl/blacklist/67ed4b703d15dc555f8c444b3a05a32579cb7599bd19c9babe10c584ea327ae0.pem
new file mode 100644
index 00000000000..bda150793f5
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/67ed4b703d15dc555f8c444b3a05a32579cb7599bd19c9babe10c584ea327ae0.pem
@@ -0,0 +1,96 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 10130 (0x2792)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=IN, O=India PKI, CN=CCA India 2011
+ Validity
+ Not Before: Mar 11 08:15:11 2011 GMT
+ Not After : Mar 11 06:30:00 2016 GMT
+ Subject: C=IN, O=National Informatics Centre, OU=Certifying Authority/postalCode=110003, ST=Delhi/street=Lodhi Road, New Delhi/houseIdentifier=A-Block, CGO Complex, CN=NIC CA 2011
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ec:9f:cd:f3:c3:28:5d:c0:87:4f:3e:00:e4:32:
+ 85:e7:df:bc:92:f4:a7:ae:21:ab:4c:4a:30:2d:26:
+ b9:34:2b:c7:fa:8f:3d:f8:c7:fb:57:6e:b4:90:a6:
+ 49:fe:14:28:c7:94:46:fc:5f:3f:81:8e:ee:f7:38:
+ 8b:7b:2a:5b:79:d7:86:f0:42:25:f3:c1:c2:e3:1f:
+ 61:4f:44:8d:2e:ca:e3:f6:aa:3d:d3:06:83:b8:66:
+ 01:e3:f2:90:f2:ae:44:ea:2b:d5:c7:15:74:7a:9c:
+ d0:7c:50:39:03:96:e2:2a:5b:4f:05:b9:2e:fc:ce:
+ 03:89:9f:93:a8:16:c7:c6:8e:a7:45:41:19:a2:e9:
+ 09:8b:4f:89:2f:29:06:23:85:69:26:54:01:ce:8c:
+ 34:e2:89:b1:41:46:47:ce:f0:9f:7e:8e:90:bc:de:
+ 85:77:36:74:32:8a:70:a9:a8:20:c9:f1:c3:16:ef:
+ 68:e1:e9:42:47:d2:9d:fe:86:d8:96:05:c0:1c:b6:
+ 30:26:53:74:a7:26:db:7b:65:a9:2a:3f:35:fe:9c:
+ 43:84:a8:31:ad:53:7e:39:96:88:e4:e3:01:06:48:
+ c3:45:01:be:67:21:27:41:bf:17:60:c3:4f:25:b3:
+ a0:40:66:20:b1:17:4f:3e:32:27:ee:9a:13:cf:17:
+ bb:49
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:1
+ X509v3 Subject Key Identifier:
+ 4E:55:4F:AE:B3:DF:A1:66
+ X509v3 Certificate Policies:
+ Policy: 2.16.356.100.2
+
+ X509v3 Authority Key Identifier:
+ keyid:4D:07:A8:63:F2:DB:1C:DF
+
+ Authority Information Access:
+ OCSP - URI:http://ocvs.gov.in
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://cca.gov.in/rw/resources/CCAIndia2011Latest.crl
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 79:2c:2a:ad:1d:bc:5f:3b:bd:8a:45:62:5b:5b:d7:40:1c:d8:
+ 76:c6:1f:27:ef:0b:2d:36:04:8f:1c:b6:e3:2f:90:74:97:b4:
+ 59:94:21:5a:bb:2e:1f:8d:cd:9f:68:c8:81:c6:73:aa:e6:81:
+ 17:78:86:41:ad:3d:8d:92:e1:32:99:0f:1f:d0:fc:e6:de:97:
+ 17:ac:c9:05:ae:3e:fc:4a:20:34:ef:f7:0f:41:28:41:28:aa:
+ 70:df:db:7a:a6:e2:55:f3:29:22:55:93:19:bd:20:a3:0b:3c:
+ d9:66:55:4e:d7:66:f6:0a:10:03:91:fe:b0:b6:c7:9f:b7:1e:
+ 4e:ff:30:6c:a8:fd:d8:db:ed:fe:2a:f1:1e:0d:5b:6e:b1:e2:
+ ae:15:5d:8e:c5:2b:2a:49:f7:df:26:ae:c8:61:3c:29:44:f3:
+ 95:cc:71:89:9e:35:77:22:0b:63:df:30:33:66:6f:02:5b:14:
+ 4c:ff:28:67:90:6c:95:73:ec:73:fd:3e:e8:59:8d:3c:ef:47:
+ 9c:89:1f:9b:98:b8:d9:f6:3d:28:a6:e7:59:47:a7:be:94:2b:
+ 0c:1c:7d:8b:c5:cf:02:ff:45:d1:70:2c:dc:81:a9:f1:7d:60:
+ 9b:fd:f6:f4:83:1e:38:89:8d:1a:fb:05:82:55:e6:e3:bb:22:
+ 94:fc:15:e4
+-----BEGIN CERTIFICATE-----
+MIIEWzCCA0OgAwIBAgICJ5IwDQYJKoZIhvcNAQELBQAwOjELMAkGA1UEBhMCSU4x
+EjAQBgNVBAoTCUluZGlhIFBLSTEXMBUGA1UEAxMOQ0NBIEluZGlhIDIwMTEwHhcN
+MTEwMzExMDgxNTExWhcNMTYwMzExMDYzMDAwWjCByDELMAkGA1UEBhMCSU4xJDAi
+BgNVBAoTG05hdGlvbmFsIEluZm9ybWF0aWNzIENlbnRyZTEdMBsGA1UECxMUQ2Vy
+dGlmeWluZyBBdXRob3JpdHkxDzANBgNVBBETBjExMDAwMzEOMAwGA1UECBMFRGVs
+aGkxHjAcBgNVBAkTFUxvZGhpIFJvYWQsIE5ldyBEZWxoaTEdMBsGA1UEMwwUQS1C
+bG9jaywgQ0dPIENvbXBsZXgxFDASBgNVBAMTC05JQyBDQSAyMDExMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7J/N88MoXcCHTz4A5DKF59+8kvSnriGr
+TEowLSa5NCvH+o89+Mf7V260kKZJ/hQox5RG/F8/gY7u9ziLeypbedeG8EIl88HC
+4x9hT0SNLsrj9qo90waDuGYB4/KQ8q5E6ivVxxV0epzQfFA5A5biKltPBbku/M4D
+iZ+TqBbHxo6nRUEZoukJi0+JLykGI4VpJlQBzow04omxQUZHzvCffo6QvN6FdzZ0
+MopwqaggyfHDFu9o4elCR9Kd/obYlgXAHLYwJlN0pybbe2WpKj81/pxDhKgxrVN+
+OZaI5OMBBkjDRQG+ZyEnQb8XYMNPJbOgQGYgsRdPPjIn7poTzxe7SQIDAQABo4Hb
+MIHYMBIGA1UdEwEB/wQIMAYBAf8CAQEwEQYDVR0OBAoECE5VT66z36FmMBIGA1Ud
+IAQLMAkwBwYFYIJkZAIwEwYDVR0jBAwwCoAITQeoY/LbHN8wLgYIKwYBBQUHAQEE
+IjAgMB4GCCsGAQUFBzABhhJodHRwOi8vb2N2cy5nb3YuaW4wDgYDVR0PAQH/BAQD
+AgEGMEYGA1UdHwQ/MD0wO6A5oDeGNWh0dHA6Ly9jY2EuZ292LmluL3J3L3Jlc291
+cmNlcy9DQ0FJbmRpYTIwMTFMYXRlc3QuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQB5
+LCqtHbxfO72KRWJbW9dAHNh2xh8n7wstNgSPHLbjL5B0l7RZlCFauy4fjc2faMiB
+xnOq5oEXeIZBrT2NkuEymQ8f0Pzm3pcXrMkFrj78SiA07/cPQShBKKpw39t6puJV
+8ykiVZMZvSCjCzzZZlVO12b2ChADkf6wtseftx5O/zBsqP3Y2+3+KvEeDVtuseKu
+FV2OxSsqSfffJq7IYTwpRPOVzHGJnjV3Igtj3zAzZm8CWxRM/yhnkGyVc+xz/T7o
+WY0870eciR+bmLjZ9j0opudZR6e+lCsMHH2Lxc8C/0XRcCzcganxfWCb/fb0gx44
+iY0a+wWCVebjuyKU/BXk
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/79f69a47cfd6c4b4ceae8030d04b49f6171d3b5d6c812f58d040e586f1cb3f14.pem b/chromium/net/data/ssl/blacklist/79f69a47cfd6c4b4ceae8030d04b49f6171d3b5d6c812f58d040e586f1cb3f14.pem
new file mode 100644
index 00000000000..31cd740cdf0
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/79f69a47cfd6c4b4ceae8030d04b49f6171d3b5d6c812f58d040e586f1cb3f14.pem
@@ -0,0 +1,114 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 3e:75:ce:d4:6b:69:30:21:21:88:30:ae:86:a8:2a:71
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
+ Validity
+ Not Before: Mar 15 00:00:00 2011 GMT
+ Not After : Mar 14 23:59:59 2014 GMT
+ Subject: C=US/postalCode=38477, ST=Florida, L=English/street=Sea Village 10, O=Google Ltd., OU=Tech Dept., OU=Hosted by GTI Group Corporation, OU=PlatinumSSL, CN=login.yahoo.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a1:a4:05:3d:ed:85:45:93:8a:18:4d:c6:03:00:
+ 57:e2:40:77:f0:1c:eb:d0:19:df:22:5d:08:7f:d1:
+ 07:3c:41:89:46:17:a3:09:fa:fc:f8:a9:04:d1:96:
+ 8f:ab:d7:4f:3c:f9:ad:18:a9:74:81:c4:57:0a:3a:
+ 26:16:ce:62:3e:bc:3f:6c:21:ee:93:8d:cb:0d:a0:
+ 1f:9a:96:d0:8f:ad:f5:93:93:82:ee:72:0c:a1:75:
+ 15:a3:7b:84:56:b8:ad:ff:52:11:71:84:bc:3a:30:
+ 0b:7e:98:a8:e1:a8:3f:37:52:d0:f1:7c:6f:90:d8:
+ 45:0a:ac:39:72:6a:61:d5:bb:c3:8c:f9:c2:cc:df:
+ fd:3a:71:b9:af:bc:dc:3a:dc:0c:b6:b1:d2:d1:89:
+ bb:41:b6:f2:de:57:d5:15:df:fc:fd:e2:31:c5:df:
+ ca:c1:d8:8f:2c:bf:f0:0e:5b:71:e0:34:71:c3:c5:
+ 4d:7d:7a:d4:fa:ed:30:4b:2f:ea:b6:2e:9e:93:3c:
+ e2:3a:f8:42:a2:1a:ee:dc:df:cd:0f:a9:f6:79:84:
+ 1a:8e:6c:02:b6:86:e5:bf:51:6a:66:f8:f3:9c:d3:
+ 59:0c:7b:a5:99:78:cd:7c:99:fa:c6:96:47:d8:32:
+ d4:74:76:0e:77:4b:20:74:a4:b7:89:75:92:4a:b4:
+ 5b:55
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45
+
+ X509v3 Subject Key Identifier:
+ 86:49:45:FC:33:19:33:D4:04:ED:27:61:EE:E8:01:C9:0C:7F:2F:7E
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6449.1.2.1.3.4
+ CPS: https://secure.comodo.com/CPS
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/UTN-USERFirst-Hardware.crl
+
+ Full Name:
+ URI:http://crl.comodo.net/UTN-USERFirst-Hardware.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://crt.comodoca.com/UTNAddTrustServerCA.crt
+ OCSP - URI:http://ocsp.comodoca.com
+
+ X509v3 Subject Alternative Name:
+ DNS:login.yahoo.com
+ Signature Algorithm: sha1WithRSAEncryption
+ 53:69:98:8e:28:4e:9c:2b:5b:1d:cc:6b:77:28:3d:bb:fa:a5:
+ 4e:7e:56:29:a4:ea:10:e2:f4:e6:2d:06:d1:84:db:23:ce:97:
+ f3:68:b6:0f:3a:de:15:0b:24:1d:91:e3:6c:2e:30:b7:e9:70:
+ b0:c3:46:80:f0:d3:b1:51:bf:4f:d6:78:a0:fc:ac:c6:cf:31:
+ 04:63:e2:34:55:05:4a:3d:f6:30:ba:f3:33:e5:ba:d2:96:f3:
+ d5:b1:b6:93:89:1a:a4:68:be:7e:ed:63:b4:1a:48:c0:53:e4:
+ a3:f0:39:0c:32:92:c7:43:0d:1a:71:ed:d0:46:93:bf:93:62:
+ 6c:33:4b:cd:36:0d:69:5e:bb:6c:96:99:21:69:c4:4b:67:72:
+ db:6c:6a:b8:f7:68:ed:c5:8f:ad:63:65:95:0a:4c:e0:f9:0f:
+ 7e:37:3d:aa:d4:93:ba:67:09:c3:a5:a4:0d:03:5a:6d:d5:0b:
+ fe:f0:40:14:b4:f6:b8:69:7c:6d:c2:32:4b:9f:b5:1a:e7:46:
+ ae:4c:5a:2b:aa:7a:5e:90:57:95:fa:db:66:02:20:1e:6a:69:
+ 66:15:9c:c2:b6:f5:bc:50:b5:fd:45:c7:1f:68:b4:47:59:ac:
+ c4:1b:28:93:4e:52:53:12:03:58:4b:71:83:9f:66:e6:ac:79:
+ 48:fe:fe:47
+-----BEGIN CERTIFICATE-----
+MIIF2TCCBMGgAwIBAgIQPnXO1GtpMCEhiDCuhqgqcTANBgkqhkiG9w0BAQUFADCB
+lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
+Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
+SGFyZHdhcmUwHhcNMTEwMzE1MDAwMDAwWhcNMTQwMzE0MjM1OTU5WjCB3zELMAkG
+A1UEBhMCVVMxDjAMBgNVBBETBTM4NDc3MRAwDgYDVQQIEwdGbG9yaWRhMRAwDgYD
+VQQHEwdFbmdsaXNoMRcwFQYDVQQJEw5TZWEgVmlsbGFnZSAxMDEUMBIGA1UEChML
+R29vZ2xlIEx0ZC4xEzARBgNVBAsTClRlY2ggRGVwdC4xKDAmBgNVBAsTH0hvc3Rl
+ZCBieSBHVEkgR3JvdXAgQ29ycG9yYXRpb24xFDASBgNVBAsTC1BsYXRpbnVtU1NM
+MRgwFgYDVQQDEw9sb2dpbi55YWhvby5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQChpAU97YVFk4oYTcYDAFfiQHfwHOvQGd8iXQh/0Qc8QYlGF6MJ
++vz4qQTRlo+r1088+a0YqXSBxFcKOiYWzmI+vD9sIe6TjcsNoB+altCPrfWTk4Lu
+cgyhdRWje4RWuK3/UhFxhLw6MAt+mKjhqD83UtDxfG+Q2EUKrDlyamHVu8OM+cLM
+3/06cbmvvNw63Ay2sdLRibtBtvLeV9UV3/z94jHF38rB2I8sv/AOW3HgNHHDxU19
+etT67TBLL+q2Lp6TPOI6+EKiGu7c380PqfZ5hBqObAK2huW/UWpm+POc01kMe6WZ
+eM18mfrGlkfYMtR0dg53SyB0pLeJdZJKtFtVAgMBAAGjggHVMIIB0TAfBgNVHSME
+GDAWgBShcl8mGyiYQ5VdBzfVhZadS9LDRTAdBgNVHQ4EFgQUhklF/DMZM9QE7Sdh
+7ugByQx/L34wDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYw
+FAYIKwYBBQUHAwEGCCsGAQUFBwMCMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQME
+MCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMHsG
+A1UdHwR0MHIwOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1VUTi1VU0VS
+Rmlyc3QtSGFyZHdhcmUuY3JsMDagNKAyhjBodHRwOi8vY3JsLmNvbW9kby5uZXQv
+VVROLVVTRVJGaXJzdC1IYXJkd2FyZS5jcmwwcQYIKwYBBQUHAQEEZTBjMDsGCCsG
+AQUFBzAChi9odHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9VVE5BZGRUcnVzdFNlcnZl
+ckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMBoG
+A1UdEQQTMBGCD2xvZ2luLnlhaG9vLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAU2mY
+jihOnCtbHcxrdyg9u/qlTn5WKaTqEOL05i0G0YTbI86X82i2DzreFQskHZHjbC4w
+t+lwsMNGgPDTsVG/T9Z4oPysxs8xBGPiNFUFSj32MLrzM+W60pbz1bG2k4kapGi+
+fu1jtBpIwFPko/A5DDKSx0MNGnHt0EaTv5NibDNLzTYNaV67bJaZIWnES2dy22xq
+uPdo7cWPrWNllQpM4PkPfjc9qtSTumcJw6WkDQNabdUL/vBAFLT2uGl8bcIyS5+1
+GudGrkxaK6p6XpBXlfrbZgIgHmppZhWcwrb1vFC1/UXHH2i0R1msxBsok05SUxID
+WEtxg59m5qx5SP7+Rw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/7abd72a323c9d179c722564f4e27a51dd4afd24006b38a40ce918b94960bcf18.pem b/chromium/net/data/ssl/blacklist/7abd72a323c9d179c722564f4e27a51dd4afd24006b38a40ce918b94960bcf18.pem
new file mode 100644
index 00000000000..5d4d44db39e
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/7abd72a323c9d179c722564f4e27a51dd4afd24006b38a40ce918b94960bcf18.pem
@@ -0,0 +1,104 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 12:bd:26:a2:ae:33:c0:7f:24:7b:6a:58:69:f2:0a:76
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3
+ Validity
+ Not Before: May 18 00:00:00 2008 GMT
+ Not After : May 17 23:59:59 2018 GMT
+ Subject: C=EG, O=Egypt Trust, OU=VeriSign Trust Network, OU=Terms of use at https://www.egypttrust.com/repository/rpa (c)08, CN=Egypt Trust Class 3 Managed PKI SCO Administrator CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ab:64:26:78:d0:0e:07:c2:d6:de:98:1f:19:ed:
+ b9:90:18:ae:d2:93:d9:39:44:bf:50:7a:88:dd:86:
+ e1:96:75:dd:2f:a2:a8:f9:86:c7:c2:2b:64:b4:a1:
+ 3a:cd:e4:17:4c:be:a8:8f:53:93:7b:af:9d:53:23:
+ db:cb:61:6a:84:d6:be:9e:03:74:35:ae:ee:fe:b2:
+ 7b:6f:4a:87:25:4c:59:df:0a:76:9e:00:43:6c:c6:
+ 30:72:ff:6a:4a:50:09:cd:ce:0c:bd:b7:6f:11:32:
+ c4:c0:1e:fc:85:9f:4e:34:d1:9e:5c:b6:ab:7f:c3:
+ 1f:5b:db:06:6b:4d:fe:ce:b1:b8:13:76:1b:21:2b:
+ 65:9a:1a:b1:33:5b:f2:29:a4:db:db:63:00:84:19:
+ 52:a3:a2:16:5f:ca:f7:ff:ed:42:7c:b1:2f:e5:cd:
+ 2c:6d:44:ab:ef:04:14:e2:f8:2d:cb:65:24:f4:46:
+ 8d:2c:ea:6f:51:68:04:7f:c7:b2:d2:5e:2a:2b:41:
+ fb:2c:d7:98:a1:11:78:f0:0d:be:96:16:73:7a:3a:
+ e6:11:d7:29:17:b0:41:23:93:6f:85:68:c4:67:7d:
+ d2:db:b4:fe:60:b7:02:26:4e:20:bc:99:f0:e7:73:
+ d2:67:a6:36:77:40:d8:26:d6:2f:86:be:00:5e:18:
+ de:cf
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Certificate Policies:
+ Policy: 2.16.840.1.113733.1.7.23.3
+ CPS: https://www.egypttrust.com/repository/cps
+ User Notice:
+ Explicit Text: https://www.egypttrust.com/repository/rpa
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Netscape Cert Type:
+ SSL CA, S/MIME CA
+ X509v3 Subject Key Identifier:
+ C7:00:13:EE:74:84:14:F8:B8:7C:8B:67:8A:FF:75:DD:DD:A7:CA:E6
+ X509v3 Authority Key Identifier:
+ DirName:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 1999 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G3
+ serial:9B:7E:06:49:A3:3E:62:B9:D5:EE:90:48:71:29:EF:57
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 97:15:d9:0b:5e:00:ad:e1:02:c1:4b:16:83:4d:b1:14:af:19:
+ 0d:80:71:5f:51:a2:d7:37:49:47:84:f1:14:6e:52:89:24:44:
+ d7:dc:8e:62:11:be:b1:6a:b0:ec:a2:b3:46:83:47:ae:30:8f:
+ d4:7c:78:e0:f9:2e:82:b0:7e:2b:e6:b6:c1:7f:2c:26:a9:76:
+ d9:2a:f6:c0:cd:6c:19:d0:1e:03:59:7f:e5:08:ee:e3:68:ea:
+ c9:45:a6:be:8f:de:94:e0:2a:ca:0d:ee:64:43:74:53:e3:44:
+ fe:37:6e:07:c3:85:eb:1d:4f:a7:6d:bc:a2:f0:be:73:13:dc:
+ 92:98:df:6a:80:ce:49:73:e7:28:9f:ca:b6:ad:37:c3:74:5a:
+ f8:af:82:0b:2a:cf:ae:4d:01:87:2e:ba:d2:00:df:b8:bf:88:
+ 73:ef:95:83:78:33:9d:11:57:8a:c4:92:46:e9:e2:3e:64:ef:
+ d4:bb:e8:4a:0b:dd:8a:8a:9e:bd:64:4e:56:46:07:9e:7d:bc:
+ b0:6e:2e:d7:d2:9a:0c:22:ee:2c:7f:ac:5a:40:64:a8:2b:c6:
+ b0:ce:55:9e:de:17:81:d2:8e:c2:e8:3b:ae:5e:14:25:ea:29:
+ 87:2e:a2:4c:90:f2:3c:8a:0e:be:a4:f1:ac:e6:1f:e3:7a:d6:
+ 72:c2:94:97
+-----BEGIN CERTIFICATE-----
+MIIGAjCCBOqgAwIBAgIQEr0moq4zwH8ke2pYafIKdjANBgkqhkiG9w0BAQUFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMTk5OSBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzMwHhcNMDgwNTE4MDAwMDAwWhcNMTgwNTE3MjM1OTU5WjCBzTEL
+MAkGA1UEBhMCRUcxFDASBgNVBAoTC0VneXB0IFRydXN0MR8wHQYDVQQLExZWZXJp
+U2lnbiBUcnVzdCBOZXR3b3JrMUgwRgYDVQQLEz9UZXJtcyBvZiB1c2UgYXQgaHR0
+cHM6Ly93d3cuZWd5cHR0cnVzdC5jb20vcmVwb3NpdG9yeS9ycGEgKGMpMDgxPTA7
+BgNVBAMTNEVneXB0IFRydXN0IENsYXNzIDMgTWFuYWdlZCBQS0kgU0NPIEFkbWlu
+aXN0cmF0b3IgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrZCZ4
+0A4HwtbemB8Z7bmQGK7Sk9k5RL9QeojdhuGWdd0voqj5hsfCK2S0oTrN5BdMvqiP
+U5N7r51TI9vLYWqE1r6eA3Q1ru7+sntvSoclTFnfCnaeAENsxjBy/2pKUAnNzgy9
+t28RMsTAHvyFn0400Z5ctqt/wx9b2wZrTf7OsbgTdhshK2WaGrEzW/IppNvbYwCE
+GVKjohZfyvf/7UJ8sS/lzSxtRKvvBBTi+C3LZST0Ro0s6m9RaAR/x7LSXiorQfss
+15ihEXjwDb6WFnN6OuYR1ykXsEEjk2+FaMRnfdLbtP5gtwImTiC8mfDnc9JnpjZ3
+QNgm1i+GvgBeGN7PAgMBAAGjggHdMIIB2TASBgNVHRMBAf8ECDAGAQH/AgEAMIGM
+BgNVHSAEgYQwgYEwfwYLYIZIAYb4RQEHFwMwcDA1BggrBgEFBQcCARYpaHR0cHM6
+Ly93d3cuZWd5cHR0cnVzdC5jb20vcmVwb3NpdG9yeS9jcHMwNwYIKwYBBQUHAgIw
+KxopaHR0cHM6Ly93d3cuZWd5cHR0cnVzdC5jb20vcmVwb3NpdG9yeS9ycGEwDgYD
+VR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIBBjAdBgNVHQ4EFgQUxwAT7nSE
+FPi4fItniv913d2nyuYwgfEGA1UdIwSB6TCB5qGB0KSBzTCByjELMAkGA1UEBhMC
+VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
+cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMTk5OSBWZXJpU2lnbiwgSW5jLiAt
+IEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFz
+cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzOC
+EQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAA4IBAQCXFdkLXgCt4QLB
+SxaDTbEUrxkNgHFfUaLXN0lHhPEUblKJJETX3I5iEb6xarDsorNGg0euMI/UfHjg
++S6CsH4r5rbBfywmqXbZKvbAzWwZ0B4DWX/lCO7jaOrJRaa+j96U4CrKDe5kQ3RT
+40T+N24Hw4XrHU+nbbyi8L5zE9ySmN9qgM5Jc+con8q2rTfDdFr4r4ILKs+uTQGH
+LrrSAN+4v4hz75WDeDOdEVeKxJJG6eI+ZO/Uu+hKC92Kip69ZE5WRgeefbywbi7X
+0poMIu4sf6xaQGSoK8awzlWe3heB0o7C6DuuXhQl6imHLqJMkPI8ig6+pPGs5h/j
+etZywpSX
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/817d4e05063d5942869c47d8504dc56a5208f7569c3d6d67f3457cfe921b3e29.pem b/chromium/net/data/ssl/blacklist/817d4e05063d5942869c47d8504dc56a5208f7569c3d6d67f3457cfe921b3e29.pem
new file mode 100644
index 00000000000..ef3665d1c78
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/817d4e05063d5942869c47d8504dc56a5208f7569c3d6d67f3457cfe921b3e29.pem
@@ -0,0 +1,94 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 314159303 (0x12b9b0c7)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=JP, O=SECOM Trust.net, OU=Security Communication RootCA1
+ Validity
+ Not Before: Mar 27 03:13:51 2009 GMT
+ Not After : Mar 27 03:13:51 2019 GMT
+ Subject: C=JP, L=Academe2, O=National Institute of Informatics, OU=UPKI, OU=NII Open Domain CA - G2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:e0:14:6d:09:18:48:e7:31:b2:60:d7:88:b4:38:
+ a2:b8:a8:f3:6b:d6:0c:0e:21:9c:09:44:87:61:e0:
+ bd:dc:62:1e:be:b0:a8:67:fe:54:af:96:20:9c:6c:
+ a1:6c:19:ab:3d:6e:3d:bb:77:d3:78:76:7c:e1:c9:
+ 06:9a:ba:b5:66:2c:5c:85:62:d6:1d:bf:c7:de:c8:
+ a7:26:48:de:d4:61:43:38:4a:87:80:7a:ae:bd:f4:
+ e0:8f:4c:b2:10:c3:66:9e:86:43:d2:18:7c:bb:79:
+ c1:f5:25:7e:94:63:0f:f8:d2:99:85:35:cf:88:4c:
+ 80:e3:a9:fd:3e:9b:02:53:44:cf:02:b5:3c:2f:7a:
+ 02:fb:93:97:d9:62:29:d7:5e:d5:e7:87:46:a2:86:
+ 8f:75:fe:6a:83:12:b5:8e:c3:e0:08:a4:f4:c2:0e:
+ 84:01:9e:ad:41:27:34:89:87:ef:5e:30:1a:a3:d4:
+ 1a:e3:71:75:0b:d2:9a:81:bf:35:73:e6:50:57:82:
+ b5:2a:df:39:95:83:7c:a3:4c:63:44:ac:b9:c1:83:
+ 7c:46:c5:1c:31:81:f0:92:a3:ab:d9:7b:a3:29:51:
+ e3:db:ed:86:ab:08:62:7d:f4:bd:84:34:67:74:a7:
+ 9d:c0:3a:6f:2b:5f:25:b4:2b:d5:92:2d:d6:d0:f6:
+ 1e:23
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 7B:0A:07:F7:18:CA:8C:0E:D6:DA:BC:50:80:6C:2C:47:02:D1:0D:FB
+ X509v3 Authority Key Identifier:
+ keyid:A0:73:49:99:68:DC:85:5B:65:E3:9B:28:2F:57:9F:BD:33:BC:07:48
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://repository.secomtrust.net/SC-Root1/SCRoot1CRL.crl
+
+ X509v3 Certificate Policies:
+ Policy: 1.2.392.200091.100.901.1
+ CPS: https://repository.secomtrust.net/SC-Root1/
+
+ Signature Algorithm: sha1WithRSAEncryption
+ aa:2a:a2:07:06:2c:77:43:96:45:e6:36:30:a4:23:d9:17:9f:
+ d2:3c:cc:73:67:ef:13:b7:61:d3:18:92:0b:08:91:84:80:89:
+ cf:7e:1f:05:87:24:f5:75:db:f6:da:3b:18:a0:a4:62:a4:63:
+ 6b:dc:48:40:f0:02:21:ea:4a:c5:53:1e:bc:d8:e9:0c:84:45:
+ 54:9a:6a:59:3e:0b:be:3e:b3:18:f1:c3:52:46:e4:b7:07:fb:
+ 08:2d:f8:4c:40:e2:66:4f:01:2e:ef:39:f8:03:92:78:be:ee:
+ 53:fd:62:b9:4b:47:5f:44:e8:ad:80:41:6e:86:dc:37:fc:ce:
+ 19:e4:39:fd:be:92:5f:a5:6a:f0:ef:4f:be:0a:ae:13:85:a2:
+ 36:19:4c:61:7a:0c:52:28:90:11:5f:bc:d0:5d:ae:ec:78:0a:
+ 42:2c:2a:1a:58:41:70:80:20:4b:b2:d7:60:85:65:45:c4:b4:
+ 70:79:5f:17:81:92:7b:5b:b3:69:5f:3f:fa:d6:6e:0d:89:d4:
+ 88:1e:cd:97:3a:b2:10:a7:dd:57:6b:2f:67:68:b9:51:63:68:
+ 05:e5:73:cc:f0:ca:cf:ca:22:92:f3:35:2c:4e:38:6c:09:74:
+ ac:45:4d:a2:33:1f:f7:a6:72:a2:a3:f7:72:5d:0c:2d:6b:ac:
+ 53:21:a0:f1
+-----BEGIN CERTIFICATE-----
+MIIEVDCCAzygAwIBAgIEErmwxzANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJK
+UDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBD
+b21tdW5pY2F0aW9uIFJvb3RDQTEwHhcNMDkwMzI3MDMxMzUxWhcNMTkwMzI3MDMx
+MzUxWjB9MQswCQYDVQQGEwJKUDERMA8GA1UEBxMIQWNhZGVtZTIxKjAoBgNVBAoT
+IU5hdGlvbmFsIEluc3RpdHV0ZSBvZiBJbmZvcm1hdGljczENMAsGA1UECxMEVVBL
+STEgMB4GA1UECxMXTklJIE9wZW4gRG9tYWluIENBIC0gRzIwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDgFG0JGEjnMbJg14i0OKK4qPNr1gwOIZwJRIdh
+4L3cYh6+sKhn/lSvliCcbKFsGas9bj27d9N4dnzhyQaaurVmLFyFYtYdv8feyKcm
+SN7UYUM4SoeAeq699OCPTLIQw2aehkPSGHy7ecH1JX6UYw/40pmFNc+ITIDjqf0+
+mwJTRM8CtTwvegL7k5fZYinXXtXnh0aiho91/mqDErWOw+AIpPTCDoQBnq1BJzSJ
+h+9eMBqj1BrjcXUL0pqBvzVz5lBXgrUq3zmVg3yjTGNErLnBg3xGxRwxgfCSo6vZ
+e6MpUePb7YarCGJ99L2ENGd0p53AOm8rXyW0K9WSLdbQ9h4jAgMBAAGjggEHMIIB
+AzAdBgNVHQ4EFgQUewoH9xjKjA7W2rxQgGwsRwLRDfswHwYDVR0jBBgwFoAUoHNJ
+mWjchVtl45soL1efvTO8B0gwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E
+BAMCAQYwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL3JlcG9zaXRvcnkuc2Vjb210
+cnVzdC5uZXQvU0MtUm9vdDEvU0NSb290MUNSTC5jcmwwUgYDVR0gBEswSTBHBgoq
+gwiMmxtkhwUBMDkwNwYIKwYBBQUHAgEWK2h0dHBzOi8vcmVwb3NpdG9yeS5zZWNv
+bXRydXN0Lm5ldC9TQy1Sb290MS8wDQYJKoZIhvcNAQEFBQADggEBAKoqogcGLHdD
+lkXmNjCkI9kXn9I8zHNn7xO3YdMYkgsIkYSAic9+HwWHJPV12/baOxigpGKkY2vc
+SEDwAiHqSsVTHrzY6QyERVSaalk+C74+sxjxw1JG5LcH+wgt+ExA4mZPAS7vOfgD
+kni+7lP9YrlLR19E6K2AQW6G3Df8zhnkOf2+kl+lavDvT74KrhOFojYZTGF6DFIo
+kBFfvNBdrux4CkIsKhpYQXCAIEuy12CFZUXEtHB5XxeBkntbs2lfP/rWbg2J1Ige
+zZc6shCn3VdrL2douVFjaAXlc8zwys/KIpLzNSxOOGwJdKxFTaIzH/emcqKj93Jd
+DC1rrFMhoPE=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/8290cc3fc1c3aac3239782c141ace8f88aeef4e9576a43d01867cf19d025be66.pem b/chromium/net/data/ssl/blacklist/8290cc3fc1c3aac3239782c141ace8f88aeef4e9576a43d01867cf19d025be66.pem
new file mode 100644
index 00000000000..6b99f2ddc0f
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/8290cc3fc1c3aac3239782c141ace8f88aeef4e9576a43d01867cf19d025be66.pem
@@ -0,0 +1,114 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 04:7e:cb:e9:fc:a5:5f:7b:d0:9e:ae:36:e1:0c:ae:1e
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
+ Validity
+ Not Before: Mar 15 00:00:00 2011 GMT
+ Not After : Mar 14 23:59:59 2014 GMT
+ Subject: C=US/postalCode=38477, ST=Florida, L=English/street=Sea Village 10, O=Google Ltd., OU=Tech Dept., OU=Hosted by GTI Group Corporation, OU=PlatinumSSL, CN=mail.google.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:b0:73:f0:f2:04:ee:c2:a2:46:ca:34:2a:aa:bb:
+ 60:23:d1:11:76:1f:1f:3a:d0:65:83:4e:9a:45:a8:
+ 43:70:85:76:f0:1f:87:00:02:1f:6e:3b:17:17:c4:
+ b5:e9:19:46:a2:92:25:8d:62:2a:b4:63:30:1f:b9:
+ 85:f8:35:e1:16:5a:76:49:cc:50:48:53:39:59:89:
+ d6:84:02:fb:9a:ec:1b:c7:51:d5:76:95:90:d4:3a:
+ 2a:b8:a6:de:02:4d:06:fb:cd:ed:a5:46:41:5f:55:
+ 74:e5:ec:7e:40:dc:50:9c:b5:e4:35:5d:1e:68:20:
+ f8:e9:de:a3:6a:28:bf:41:d2:a1:b3:e2:25:8d:0c:
+ 1b:ca:3d:93:0c:18:ae:df:c5:bc:fd:bc:82:ba:68:
+ 00:d7:16:32:71:9f:65:b5:11:da:68:59:d0:a6:57:
+ 64:1b:c9:fe:98:e5:f5:a5:65:ea:e1:db:ee:f4:b3:
+ 9d:b3:8e:ea:87:ae:16:d2:1e:a0:7c:7c:69:3f:29:
+ 16:85:01:53:a7:6c:f1:60:ab:dd:a2:fc:25:47:d4:
+ 32:d1:12:dd:f7:48:12:e0:fc:9c:a2:77:98:e9:89:
+ 99:b8:f8:38:f1:8c:06:c2:7a:23:36:6d:9b:9d:cd:
+ 30:c8:c7:34:17:1e:bb:7d:42:c8:ab:e7:15:16:f6:
+ 73:b5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45
+
+ X509v3 Subject Key Identifier:
+ 18:2A:A2:C8:D4:7A:3F:7B:AD:04:8B:BD:6F:9E:10:46:13:78:71:9D
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6449.1.2.1.3.4
+ CPS: https://secure.comodo.com/CPS
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/UTN-USERFirst-Hardware.crl
+
+ Full Name:
+ URI:http://crl.comodo.net/UTN-USERFirst-Hardware.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://crt.comodoca.com/UTNAddTrustServerCA.crt
+ OCSP - URI:http://ocsp.comodoca.com
+
+ X509v3 Subject Alternative Name:
+ DNS:mail.google.com, DNS:www.mail.google.com
+ Signature Algorithm: sha1WithRSAEncryption
+ 67:06:08:0a:27:c5:93:6e:02:f2:de:17:3f:d0:d3:1b:7c:ff:
+ b5:cd:7a:c7:77:c7:be:df:12:ca:19:de:b0:13:57:0c:03:91:
+ c4:79:52:cf:7f:b7:5e:55:20:84:49:dd:f5:d0:29:2f:0e:04:
+ da:59:9e:0e:13:9f:f4:c0:32:9b:ff:a1:11:24:2a:97:a3:f2:
+ 3f:3d:2a:6b:a8:ad:8c:19:75:95:0e:1d:25:fd:4f:c4:7a:15:
+ c3:1d:c7:13:40:c8:0d:be:97:60:72:a6:fe:25:be:8f:ec:d5:
+ a6:86:c3:21:5c:59:52:d9:6a:0b:5c:9f:4b:de:b5:f9:ec:e2:
+ f4:c5:cc:62:53:76:89:65:e4:29:da:b7:bf:96:e0:60:8d:0d:
+ b7:09:55:d6:40:55:1d:c1:f2:96:21:75:af:89:86:1f:5d:81:
+ 97:29:28:1e:29:d7:96:c1:20:03:32:7b:00:3b:6a:37:17:5a:
+ a3:b3:1a:6f:32:3b:6e:f1:a3:5d:ab:ab:cc:2a:cb:30:0c:1f:
+ 35:23:8b:69:44:5c:ea:ac:28:60:ed:ab:6b:63:9e:f6:92:bc:
+ bd:9a:5a:26:4c:c5:98:b8:0e:19:3e:fc:05:31:e3:16:d9:fd:
+ 90:05:03:86:c6:57:01:1f:7f:78:a0:cf:33:6a:aa:66:6b:22:
+ d0:a7:49:23
+-----BEGIN CERTIFICATE-----
+MIIF7jCCBNagAwIBAgIQBH7L6fylX3vQnq424QyuHjANBgkqhkiG9w0BAQUFADCB
+lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
+Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
+SGFyZHdhcmUwHhcNMTEwMzE1MDAwMDAwWhcNMTQwMzE0MjM1OTU5WjCB3zELMAkG
+A1UEBhMCVVMxDjAMBgNVBBETBTM4NDc3MRAwDgYDVQQIEwdGbG9yaWRhMRAwDgYD
+VQQHEwdFbmdsaXNoMRcwFQYDVQQJEw5TZWEgVmlsbGFnZSAxMDEUMBIGA1UEChML
+R29vZ2xlIEx0ZC4xEzARBgNVBAsTClRlY2ggRGVwdC4xKDAmBgNVBAsTH0hvc3Rl
+ZCBieSBHVEkgR3JvdXAgQ29ycG9yYXRpb24xFDASBgNVBAsTC1BsYXRpbnVtU1NM
+MRgwFgYDVQQDEw9tYWlsLmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQCwc/DyBO7CokbKNCqqu2Aj0RF2Hx860GWDTppFqENwhXbwH4cA
+Ah9uOxcXxLXpGUaikiWNYiq0YzAfuYX4NeEWWnZJzFBIUzlZidaEAvua7BvHUdV2
+lZDUOiq4pt4CTQb7ze2lRkFfVXTl7H5A3FCcteQ1XR5oIPjp3qNqKL9B0qGz4iWN
+DBvKPZMMGK7fxbz9vIK6aADXFjJxn2W1EdpoWdCmV2Qbyf6Y5fWlZerh2+70s52z
+juqHrhbSHqB8fGk/KRaFAVOnbPFgq92i/CVH1DLREt33SBLg/Jyid5jpiZm4+Djx
+jAbCeiM2bZudzTDIxzQXHrt9Qsir5xUW9nO1AgMBAAGjggHqMIIB5jAfBgNVHSME
+GDAWgBShcl8mGyiYQ5VdBzfVhZadS9LDRTAdBgNVHQ4EFgQUGCqiyNR6P3utBIu9
+b54QRhN4cZ0wDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYw
+FAYIKwYBBQUHAwEGCCsGAQUFBwMCMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQME
+MCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMHsG
+A1UdHwR0MHIwOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1VUTi1VU0VS
+Rmlyc3QtSGFyZHdhcmUuY3JsMDagNKAyhjBodHRwOi8vY3JsLmNvbW9kby5uZXQv
+VVROLVVTRVJGaXJzdC1IYXJkd2FyZS5jcmwwcQYIKwYBBQUHAQEEZTBjMDsGCCsG
+AQUFBzAChi9odHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9VVE5BZGRUcnVzdFNlcnZl
+ckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMC8G
+A1UdEQQoMCaCD21haWwuZ29vZ2xlLmNvbYITd3d3Lm1haWwuZ29vZ2xlLmNvbTAN
+BgkqhkiG9w0BAQUFAAOCAQEAZwYICifFk24C8t4XP9DTG3z/tc16x3fHvt8Syhne
+sBNXDAORxHlSz3+3XlUghEnd9dApLw4E2lmeDhOf9MAym/+hESQql6PyPz0qa6it
+jBl1lQ4dJf1PxHoVwx3HE0DIDb6XYHKm/iW+j+zVpobDIVxZUtlqC1yfS961+ezi
+9MXMYlN2iWXkKdq3v5bgYI0NtwlV1kBVHcHyliF1r4mGH12BlykoHinXlsEgAzJ7
+ADtqNxdao7MabzI7bvGjXaurzCrLMAwfNSOLaURc6qwoYO2ra2Oe9pK8vZpaJkzF
+mLgOGT78BTHjFtn9kAUDhsZXAR9/eKDPM2qqZmsi0KdJIw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/83618f932d6947744d5ecca299d4b2820c01483947bd16be814e683f7436be24.pem b/chromium/net/data/ssl/blacklist/83618f932d6947744d5ecca299d4b2820c01483947bd16be814e683f7436be24.pem
new file mode 100644
index 00000000000..fd9614cb406
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/83618f932d6947744d5ecca299d4b2820c01483947bd16be814e683f7436be24.pem
@@ -0,0 +1,131 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 52:84:46:9d:bf:7a:09:40:d3:c4:8a:95:af:2e:8b:06
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Domain Validation Secure Server CA
+ Validity
+ Not Before: Mar 20 00:00:00 2015 GMT
+ Not After : Mar 19 23:59:59 2016 GMT
+ Subject: OU=Domain Control Validated, OU=PositiveSSL, CN=xs4all.nl
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:e3:d4:a4:89:c0:58:6c:ef:f0:0b:b3:97:03:c5:
+ f2:37:b3:b4:8c:59:2d:9c:50:04:37:04:2f:b0:31:
+ df:a1:e7:fa:6d:78:25:3d:1a:e1:0c:48:7d:4e:af:
+ 3b:ff:57:d7:e5:19:85:fe:7d:f8:fe:90:33:a0:b0:
+ 4b:8e:1b:a9:86:4b:6a:70:70:f7:b4:22:de:90:62:
+ 99:8f:ba:42:8c:20:63:74:16:5d:29:23:4f:08:e1:
+ e2:0f:73:17:0f:f4:23:f3:86:6b:4c:24:0a:c1:28:
+ 9d:cf:82:73:9f:50:59:12:cc:15:60:bb:57:64:71:
+ 13:6f:b3:04:38:33:59:d3:9f:67:ce:07:0e:85:22:
+ a2:19:53:51:1b:76:3c:40:c9:4b:a2:0c:14:05:10:
+ 6f:f2:b3:6e:6c:b6:95:a6:60:17:d1:2f:bc:b7:19:
+ b0:5a:19:b2:98:a4:e9:10:b6:6e:64:68:f4:42:9d:
+ e3:b2:7a:17:e9:4b:cd:99:8d:ab:01:58:8f:69:ba:
+ a2:2e:e2:54:06:99:a8:72:14:71:a5:f3:25:9b:81:
+ 92:7a:0c:67:9b:73:5c:11:a8:69:96:1b:99:65:5f:
+ 64:96:41:f4:91:75:b7:26:cf:a8:2b:a0:28:dc:33:
+ 90:20:7a:7e:97:72:e0:7c:93:e9:22:a3:b8:28:84:
+ 58:08:fa:3b:17:08:e8:c4:ce:67:d4:50:23:5c:0e:
+ 7e:9d:0c:3f:f1:8c:41:53:83:7c:6e:b2:c4:7d:c5:
+ fb:68:cb:a5:06:9c:91:8d:3c:9d:2e:20:96:3b:c4:
+ b1:fa:ed:58:c2:37:fe:1e:a8:8a:c9:ea:a3:49:5d:
+ 8d:60:be:88:68:27:2a:cc:6e:e3:ef:55:23:85:7a:
+ fc:ad:ed:2f:0e:31:03:c7:10:ba:dd:12:9a:88:5d:
+ ef:58:2e:54:e7:78:6a:58:68:3b:e3:78:bc:0f:88:
+ 3e:b3:3c:2e:05:9e:54:6c:a1:db:e2:9b:01:be:e6:
+ 92:9d:a7:22:4d:49:17:e1:78:ba:ca:6a:fe:9e:ff:
+ d2:80:80:af:7b:a0:10:17:2a:57:f1:31:e4:f0:38:
+ 88:4b:0c:62:08:18:c5:8a:2a:18:ac:0c:b5:d2:b3:
+ 4a:e2:d4:de:5c:ba:77:d4:5e:99:a1:19:ab:0b:e7:
+ 82:a6:69:eb:eb:e2:99:20:9b:bc:84:6a:f4:bc:b0:
+ 87:78:9c:b2:12:0f:36:57:fa:73:ec:e2:64:90:5b:
+ 6a:c8:32:69:3b:b6:4e:f8:7d:c5:36:08:13:8b:b0:
+ 60:0f:90:07:99:c4:a0:fe:a2:b9:d2:e3:30:6b:4d:
+ 9c:ed:7e:2e:a2:d7:c4:52:01:0e:dd:69:87:12:22:
+ 8d:f0:87
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:90:AF:6A:3A:94:5A:0B:D8:90:EA:12:56:73:DF:43:B4:3A:28:DA:E7
+
+ X509v3 Subject Key Identifier:
+ 2A:53:FE:18:5C:23:C9:91:A4:71:6A:69:FE:B0:DB:6F:79:2B:43:D8
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6449.1.2.2.7
+ CPS: https://secure.comodo.com/CPS
+ Policy: 2.23.140.1.2.1
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/COMODORSADomainValidationSecureServerCA.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://crt.comodoca.com/COMODORSADomainValidationSecureServerCA.crt
+ OCSP - URI:http://ocsp.comodoca.com
+
+ X509v3 Subject Alternative Name:
+ DNS:xs4all.nl, DNS:www.xs4all.nl
+ Signature Algorithm: sha256WithRSAEncryption
+ 33:d6:51:87:3c:b5:7f:29:a7:58:49:54:45:73:c8:de:ab:41:
+ cd:6c:13:6d:c4:e7:c8:b4:85:dd:b2:6d:91:34:7b:75:d9:71:
+ 16:8a:e7:79:1a:b2:16:7f:ae:d5:2a:61:1d:6c:be:0b:10:af:
+ 1b:cf:a7:b6:7e:51:7c:49:20:07:da:2b:aa:2c:72:1b:70:ab:
+ 6a:ca:ad:8e:ba:7b:98:fa:5e:12:40:b4:cb:8f:dd:35:16:3b:
+ 8b:b4:14:59:56:8c:32:bc:5b:34:36:d4:fc:3a:d6:87:73:70:
+ ef:e5:fe:43:cf:55:3d:53:d8:ec:2b:ca:06:1b:72:8d:6a:c2:
+ 5f:4c:46:a6:b4:12:1a:0b:ff:f8:40:a1:21:63:31:a6:40:c6:
+ 9d:c3:67:c6:3f:28:6e:16:b6:39:ca:84:64:0d:b7:f3:dc:2f:
+ 76:ca:5a:63:0c:23:2b:5a:d2:7d:13:d5:77:8d:24:38:fe:ac:
+ 73:96:5e:fa:91:df:36:6e:be:4e:9c:52:c6:92:f3:f4:a6:fe:
+ 45:47:3b:e4:52:6d:df:09:76:58:50:29:0f:b9:00:80:bf:37:
+ 30:6e:32:b0:80:d6:97:ba:28:77:70:f0:2f:a0:66:ff:93:a8:
+ 74:89:b4:5d:39:57:3e:da:28:4e:06:48:a1:6c:81:fd:e1:f0:
+ 5a:cb:54:5d
+-----BEGIN CERTIFICATE-----
+MIIGPzCCBSegAwIBAgIQUoRGnb96CUDTxIqVry6LBjANBgkqhkiG9w0BAQsFADCB
+kDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxNjA0BgNV
+BAMTLUNPTU9ETyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD
+QTAeFw0xNTAzMjAwMDAwMDBaFw0xNjAzMTkyMzU5NTlaME0xITAfBgNVBAsTGERv
+bWFpbiBDb250cm9sIFZhbGlkYXRlZDEUMBIGA1UECxMLUG9zaXRpdmVTU0wxEjAQ
+BgNVBAMTCXhzNGFsbC5ubDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+AOPUpInAWGzv8AuzlwPF8jeztIxZLZxQBDcEL7Ax36Hn+m14JT0a4QxIfU6vO/9X
+1+UZhf59+P6QM6CwS44bqYZLanBw97Qi3pBimY+6QowgY3QWXSkjTwjh4g9zFw/0
+I/OGa0wkCsEonc+Cc59QWRLMFWC7V2RxE2+zBDgzWdOfZ84HDoUiohlTURt2PEDJ
+S6IMFAUQb/Kzbmy2laZgF9EvvLcZsFoZspik6RC2bmRo9EKd47J6F+lLzZmNqwFY
+j2m6oi7iVAaZqHIUcaXzJZuBknoMZ5tzXBGoaZYbmWVfZJZB9JF1tybPqCugKNwz
+kCB6fpdy4HyT6SKjuCiEWAj6OxcI6MTOZ9RQI1wOfp0MP/GMQVODfG6yxH3F+2jL
+pQackY08nS4gljvEsfrtWMI3/h6oisnqo0ldjWC+iGgnKsxu4+9VI4V6/K3tLw4x
+A8cQut0Smohd71guVOd4alhoO+N4vA+IPrM8LgWeVGyh2+KbAb7mkp2nIk1JF+F4
+uspq/p7/0oCAr3ugEBcqV/Ex5PA4iEsMYggYxYoqGKwMtdKzSuLU3ly6d9RemaEZ
+qwvngqZp6+vimSCbvIRq9Lywh3icshIPNlf6c+ziZJBbasgyaTu2Tvh9xTYIE4uw
+YA+QB5nEoP6iudLjMGtNnO1+LqLXxFIBDt1phxIijfCHAgMBAAGjggHVMIIB0TAf
+BgNVHSMEGDAWgBSQr2o6lFoL2JDqElZz30O0Oija5zAdBgNVHQ4EFgQUKlP+GFwj
+yZGkcWpp/rDbb3krQ9gwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYD
+VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCME8GA1UdIARIMEYwOgYLKwYBBAGy
+MQECAgcwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNvbS9D
+UFMwCAYGZ4EMAQIBMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly9jcmwuY29tb2Rv
+Y2EuY29tL0NPTU9ET1JTQURvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5j
+cmwwgYUGCCsGAQUFBwEBBHkwdzBPBggrBgEFBQcwAoZDaHR0cDovL2NydC5jb21v
+ZG9jYS5jb20vQ09NT0RPUlNBRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNB
+LmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMCMGA1Ud
+EQQcMBqCCXhzNGFsbC5ubIINd3d3LnhzNGFsbC5ubDANBgkqhkiG9w0BAQsFAAOC
+AQEAM9ZRhzy1fymnWElURXPI3qtBzWwTbcTnyLSF3bJtkTR7ddlxForneRqyFn+u
+1SphHWy+CxCvG8+ntn5RfEkgB9orqixyG3Crasqtjrp7mPpeEkC0y4/dNRY7i7QU
+WVaMMrxbNDbU/DrWh3Nw7+X+Q89VPVPY7CvKBhtyjWrCX0xGprQSGgv/+EChIWMx
+pkDGncNnxj8obha2OcqEZA2389wvdspaYwwjK1rSfRPVd40kOP6sc5Ze+pHfNm6+
+TpxSxpLz9Kb+RUc75FJt3wl2WFApD7kAgL83MG4ysIDWl7ood3DwL6Bm/5OodIm0
+XTlXPtooTgZIoWyB/eHwWstUXQ==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/8a1bd21661c60015065212cc98b1abb50dfd14c872a208e66bae890f25c448af.pem b/chromium/net/data/ssl/blacklist/8a1bd21661c60015065212cc98b1abb50dfd14c872a208e66bae890f25c448af.pem
new file mode 100644
index 00000000000..a78a0acbe72
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/8a1bd21661c60015065212cc98b1abb50dfd14c872a208e66bae890f25c448af.pem
@@ -0,0 +1,116 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1184640175 (0x469c2caf)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
+ Validity
+ Not Before: Jul 26 15:57:39 2007 GMT
+ Not After : Aug 26 16:27:39 2013 GMT
+ Subject: C=NL, O=DigiNotar, CN=DigiNotar Root CA/emailAddress=info@diginotar.nl
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:ac:b0:58:c1:00:bd:d8:21:08:0b:2b:9a:fe:6e:
+ 56:30:05:9f:1b:77:90:10:41:5c:c3:0d:87:11:77:
+ 8e:81:f1:ca:7c:e9:8c:6a:ed:38:74:35:bb:da:df:
+ f9:bb:c0:09:37:b4:96:73:81:7d:33:1a:98:39:f7:
+ 93:6f:95:7f:3d:b9:b1:75:87:ba:51:48:e8:8b:70:
+ 3e:95:04:c5:d8:b6:c3:16:d9:88:b0:b1:87:1d:70:
+ da:86:b4:0f:14:8b:7a:cf:10:d1:74:36:a2:12:7b:
+ 77:86:4a:79:e6:7b:df:02:11:68:a5:4e:86:ae:34:
+ 58:9b:24:13:78:56:22:25:1e:01:8b:4b:51:71:fb:
+ 82:cc:59:96:69:88:5a:68:53:c5:b9:0d:02:37:cb:
+ 4b:bc:66:4a:90:7e:2a:0b:05:07:ed:16:5f:55:90:
+ 75:d8:46:c9:1b:83:e2:08:be:f1:23:cc:99:1d:d6:
+ 2a:0f:83:20:15:58:27:82:2e:fa:e2:22:c2:49:b1:
+ b9:01:81:6a:9d:6d:9d:40:77:68:76:4e:21:2a:6d:
+ 84:40:85:4e:76:99:7c:82:f3:f3:b7:02:59:d4:26:
+ 01:1b:8e:df:ad:53:06:d1:ae:18:dd:e2:b2:3a:cb:
+ d7:88:38:8e:ac:5b:29:b9:19:d3:98:f9:18:03:cf:
+ 48:82:86:66:0b:1b:69:0f:c9:eb:38:88:7a:26:1a:
+ 05:4c:92:d7:24:d4:96:f2:ac:52:2d:a3:47:d5:52:
+ f6:3f:fe:ce:84:06:70:a6:aa:3e:a2:f2:b6:56:34:
+ 18:57:a2:e4:81:6d:e7:ca:f0:6a:d3:c7:91:6b:02:
+ 83:41:7c:15:ef:6b:9a:64:5e:e3:d0:3c:e5:b1:eb:
+ 7b:5d:86:fb:cb:e6:77:49:cd:a3:65:dc:f7:b9:9c:
+ b8:e4:0b:5f:93:cf:cc:30:1a:32:1c:ce:1c:63:95:
+ a5:f9:ea:e1:74:8b:9e:e9:2b:a9:30:7b:a0:18:1f:
+ 0e:18:0b:e5:5b:a9:d3:d1:6c:1e:07:67:8f:91:4b:
+ a9:8a:bc:d2:66:aa:93:01:88:b2:91:fa:31:5c:d5:
+ a6:c1:52:08:09:cd:0a:63:a2:d3:22:a6:e8:a1:d9:
+ 39:06:97:f5:6e:8d:02:90:8c:14:7b:3f:80:cd:1b:
+ 9c:ba:c4:58:72:23:af:b6:56:9f:c6:7a:42:33:29:
+ 07:3f:82:c9:e6:1f:05:0d:cd:4c:28:36:8b:d3:c8:
+ 3e:1c:c6:88:ef:5e:ee:89:64:e9:1d:eb:da:89:7e:
+ 32:a6:69:d1:dd:cc:88:9f:d1:d0:c9:66:21:dc:06:
+ 67:c5:94:7a:9a:6d:62:4c:7d:cc:e0:64:80:b2:9e:
+ 47:8e:a3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:1
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication, E-mail Protection
+ X509v3 Certificate Policies:
+ Policy: X509v3 Any Policy
+
+ Authority Information Access:
+ OCSP - URI:http://ocsp.entrust.net
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.entrust.net/server1.crl
+
+ X509v3 Subject Key Identifier:
+ 88:68:BF:E0:8E:35:C4:3B:38:6B:62:F7:28:3B:84:81:C8:0C:D7:4D
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Authority Key Identifier:
+ keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
+
+ 1.2.840.113533.7.65.0:
+ 0
+..V7.1....
+ Signature Algorithm: sha1WithRSAEncryption
+ 46:ba:45:c0:cd:70:42:06:52:59:03:25:46:3f:a5:64:dd:b3:
+ 8c:e1:c5:b5:64:a7:7c:12:9a:9c:0f:16:1c:79:7f:14:f2:17:
+ 81:c3:d8:be:b4:8e:5d:da:aa:34:c1:ee:03:e9:b0:bd:8f:93:
+ 94:19:94:db:22:de:de:14:90:25:7b:d1:43:9d:b9:e2:51:37:
+ 7a:3f:2c:eb:64:e3:e6:e3:5d:8d:a5:0b:4a:93:1d:b3:7c:d1:
+ 53:0b:a8:f8:e6:69:ff:60:85:20:3d:87:08:6c:91:db:4c:81:
+ 1b:20:7d:df:74:ab:94:0f:64:57:58:7f:e8:6d:85:cd:e6:e8:
+ 87:09
+-----BEGIN CERTIFICATE-----
+MIIFSDCCBLGgAwIBAgIERpwsrzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
+VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
+ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
+KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
+ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNzA3
+MjYxNTU3MzlaFw0xMzA4MjYxNjI3MzlaMF8xCzAJBgNVBAYTAk5MMRIwEAYDVQQK
+EwlEaWdpTm90YXIxGjAYBgNVBAMTEURpZ2lOb3RhciBSb290IENBMSAwHgYJKoZI
+hvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubDCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAKywWMEAvdghCAsrmv5uVjAFnxt3kBBBXMMNhxF3joHxynzpjGrt
+OHQ1u9rf+bvACTe0lnOBfTMamDn3k2+Vfz25sXWHulFI6ItwPpUExdi2wxbZiLCx
+hx1w2oa0DxSLes8Q0XQ2ohJ7d4ZKeeZ73wIRaKVOhq40WJskE3hWIiUeAYtLUXH7
+gsxZlmmIWmhTxbkNAjfLS7xmSpB+KgsFB+0WX1WQddhGyRuD4gi+8SPMmR3WKg+D
+IBVYJ4Iu+uIiwkmxuQGBap1tnUB3aHZOISpthECFTnaZfILz87cCWdQmARuO361T
+BtGuGN3isjrL14g4jqxbKbkZ05j5GAPPSIKGZgsbaQ/J6ziIeiYaBUyS1yTUlvKs
+Ui2jR9VS9j/+zoQGcKaqPqLytlY0GFei5IFt58rwatPHkWsCg0F8Fe9rmmRe49A8
+5bHre12G+8vmd0nNo2Xc97mcuOQLX5PPzDAaMhzOHGOVpfnq4XSLnukrqTB7oBgf
+DhgL5Vup09FsHgdnj5FLqYq80maqkwGIspH6MVzVpsFSCAnNCmOi0yKm6KHZOQaX
+9W6NApCMFHs/gM0bnLrEWHIjr7ZWn8Z6QjMpBz+CyeYfBQ3NTCg2i9PIPhzGiO9e
+7olk6R3r2ol+MqZp0d3MiJ/R0MlmIdwGZ8WUepptYkx9zOBkgLKeR46jAgMBAAGj
+ggEmMIIBIjASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMB
+BggrBgEFBQcDAgYIKwYBBQUHAwQwEQYDVR0gBAowCDAGBgRVHSAAMDMGCCsGAQUF
+BwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZW50cnVzdC5uZXQwMwYD
+VR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9zZXJ2ZXIxLmNy
+bDAdBgNVHQ4EFgQUiGi/4I41xDs4a2L3KDuEgcgM100wCwYDVR0PBAQDAgEGMB8G
+A1UdIwQYMBaAFPAXYhNVPbP/CgBr+1CEl/PtYtAaMBkGCSqGSIb2fQdBAAQMMAob
+BFY3LjEDAgCBMA0GCSqGSIb3DQEBBQUAA4GBAEa6RcDNcEIGUlkDJUY/pWTds4zh
+xbVkp3wSmpwPFhx5fxTyF4HD2L60jl3aqjTB7gPpsL2Pk5QZlNsi3t4UkCV70UOd
+ueJRN3o/LOtk4+bjXY2lC0qTHbN80VMLqPjmaf9ghSA9hwhskdtMgRsgfd90q5QP
+ZFdYf+hthc3m6IcJ
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/933f7d8cda9f0d7c8bfd3c22bf4653f4161fd38ccdcf66b22e95a2f49c2650f8.pem b/chromium/net/data/ssl/blacklist/933f7d8cda9f0d7c8bfd3c22bf4653f4161fd38ccdcf66b22e95a2f49c2650f8.pem
new file mode 100644
index 00000000000..dd45fc4e63a
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/933f7d8cda9f0d7c8bfd3c22bf4653f4161fd38ccdcf66b22e95a2f49c2650f8.pem
@@ -0,0 +1,114 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ d7:55:8f:da:f5:f1:10:5b:b2:13:28:2b:70:77:29:a3
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
+ Validity
+ Not Before: Mar 15 00:00:00 2011 GMT
+ Not After : Mar 14 23:59:59 2014 GMT
+ Subject: C=US/postalCode=38477, ST=Florida, L=English/street=Sea Village 10, O=Google Ltd., OU=Tech Dept., OU=Hosted by GTI Group Corporation, OU=PlatinumSSL, CN=login.yahoo.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a1:a4:05:3d:ed:85:45:93:8a:18:4d:c6:03:00:
+ 57:e2:40:77:f0:1c:eb:d0:19:df:22:5d:08:7f:d1:
+ 07:3c:41:89:46:17:a3:09:fa:fc:f8:a9:04:d1:96:
+ 8f:ab:d7:4f:3c:f9:ad:18:a9:74:81:c4:57:0a:3a:
+ 26:16:ce:62:3e:bc:3f:6c:21:ee:93:8d:cb:0d:a0:
+ 1f:9a:96:d0:8f:ad:f5:93:93:82:ee:72:0c:a1:75:
+ 15:a3:7b:84:56:b8:ad:ff:52:11:71:84:bc:3a:30:
+ 0b:7e:98:a8:e1:a8:3f:37:52:d0:f1:7c:6f:90:d8:
+ 45:0a:ac:39:72:6a:61:d5:bb:c3:8c:f9:c2:cc:df:
+ fd:3a:71:b9:af:bc:dc:3a:dc:0c:b6:b1:d2:d1:89:
+ bb:41:b6:f2:de:57:d5:15:df:fc:fd:e2:31:c5:df:
+ ca:c1:d8:8f:2c:bf:f0:0e:5b:71:e0:34:71:c3:c5:
+ 4d:7d:7a:d4:fa:ed:30:4b:2f:ea:b6:2e:9e:93:3c:
+ e2:3a:f8:42:a2:1a:ee:dc:df:cd:0f:a9:f6:79:84:
+ 1a:8e:6c:02:b6:86:e5:bf:51:6a:66:f8:f3:9c:d3:
+ 59:0c:7b:a5:99:78:cd:7c:99:fa:c6:96:47:d8:32:
+ d4:74:76:0e:77:4b:20:74:a4:b7:89:75:92:4a:b4:
+ 5b:55
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45
+
+ X509v3 Subject Key Identifier:
+ 86:49:45:FC:33:19:33:D4:04:ED:27:61:EE:E8:01:C9:0C:7F:2F:7E
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6449.1.2.1.3.4
+ CPS: https://secure.comodo.com/CPS
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/UTN-USERFirst-Hardware.crl
+
+ Full Name:
+ URI:http://crl.comodo.net/UTN-USERFirst-Hardware.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://crt.comodoca.com/UTNAddTrustServerCA.crt
+ OCSP - URI:http://ocsp.comodoca.com
+
+ X509v3 Subject Alternative Name:
+ DNS:login.yahoo.com, DNS:www.login.yahoo.com
+ Signature Algorithm: sha1WithRSAEncryption
+ 3d:57:c9:48:24:5c:ee:64:81:f5:ae:be:55:29:16:ff:2a:2f:
+ 84:ed:d9:f8:a3:03:c8:30:66:bb:c8:d4:81:2d:21:f7:08:f7:
+ ac:96:42:9a:41:75:7a:ba:5d:10:23:cb:92:42:61:fa:8a:da:
+ 6d:65:34:19:e5:a9:d6:2d:13:78:d7:81:44:92:a9:6e:80:63:
+ 15:cb:fe:35:1f:02:d1:8a:14:b0:a8:cc:94:20:3b:a8:1a:f0:
+ 5d:36:50:db:0d:ae:e9:64:e4:f6:8d:69:7d:30:c8:14:17:00:
+ 4a:e5:a6:35:fb:7d:0d:22:9d:79:76:52:2c:bc:97:06:88:9a:
+ 15:f4:73:e6:f1:f5:98:a5:cd:07:44:91:b8:a7:68:67:45:d2:
+ 72:11:60:e2:71:b7:50:55:e2:8a:a9:0d:d6:92:ee:04:2a:8b:
+ 30:a0:a2:05:46:34:6d:92:c6:3b:aa:4d:a0:d0:ab:01:19:0a:
+ 32:b7:e8:e3:cf:f1:d2:97:49:7b:ac:a4:97:f7:f0:57:ae:63:
+ 77:9a:7f:96:da:4d:fd:be:dc:07:36:e3:25:bd:89:79:8e:29:
+ 12:13:8b:88:07:fb:6b:db:a4:cd:b3:2d:27:e9:d4:ca:60:d7:
+ 85:53:fb:74:c6:5c:35:8c:70:1f:f9:b2:b7:92:27:20:c7:94:
+ d5:67:14:30
+-----BEGIN CERTIFICATE-----
+MIIF7zCCBNegAwIBAgIRANdVj9r18RBbshMoK3B3KaMwDQYJKoZIhvcNAQEFBQAw
+gZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtl
+IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMY
+aHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR8wHQYDVQQDExZVVE4tVVNFUkZpcnN0
+LUhhcmR3YXJlMB4XDTExMDMxNTAwMDAwMFoXDTE0MDMxNDIzNTk1OVowgd8xCzAJ
+BgNVBAYTAlVTMQ4wDAYDVQQREwUzODQ3NzEQMA4GA1UECBMHRmxvcmlkYTEQMA4G
+A1UEBxMHRW5nbGlzaDEXMBUGA1UECRMOU2VhIFZpbGxhZ2UgMTAxFDASBgNVBAoT
+C0dvb2dsZSBMdGQuMRMwEQYDVQQLEwpUZWNoIERlcHQuMSgwJgYDVQQLEx9Ib3N0
+ZWQgYnkgR1RJIEdyb3VwIENvcnBvcmF0aW9uMRQwEgYDVQQLEwtQbGF0aW51bVNT
+TDEYMBYGA1UEAxMPbG9naW4ueWFob28uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAoaQFPe2FRZOKGE3GAwBX4kB38Bzr0BnfIl0If9EHPEGJRhej
+Cfr8+KkE0ZaPq9dPPPmtGKl0gcRXCjomFs5iPrw/bCHuk43LDaAfmpbQj631k5OC
+7nIMoXUVo3uEVrit/1IRcYS8OjALfpio4ag/N1LQ8XxvkNhFCqw5cmph1bvDjPnC
+zN/9OnG5r7zcOtwMtrHS0Ym7Qbby3lfVFd/8/eIxxd/KwdiPLL/wDltx4DRxw8VN
+fXrU+u0wSy/qti6ekzziOvhCohru3N/ND6n2eYQajmwCtoblv1FqZvjznNNZDHul
+mXjNfJn6xpZH2DLUdHYOd0sgdKS3iXWSSrRbVQIDAQABo4IB6jCCAeYwHwYDVR0j
+BBgwFoAUoXJfJhsomEOVXQc31YWWnUvSw0UwHQYDVR0OBBYEFIZJRfwzGTPUBO0n
+Ye7oAckMfy9+MA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQW
+MBQGCCsGAQUFBwMBBggrBgEFBQcDAjBGBgNVHSAEPzA9MDsGDCsGAQQBsjEBAgED
+BDArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQUzB7
+BgNVHR8EdDByMDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9VVE4tVVNF
+UkZpcnN0LUhhcmR3YXJlLmNybDA2oDSgMoYwaHR0cDovL2NybC5jb21vZG8ubmV0
+L1VUTi1VU0VSRmlyc3QtSGFyZHdhcmUuY3JsMHEGCCsGAQUFBwEBBGUwYzA7Bggr
+BgEFBQcwAoYvaHR0cDovL2NydC5jb21vZG9jYS5jb20vVVROQWRkVHJ1c3RTZXJ2
+ZXJDQS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAv
+BgNVHREEKDAmgg9sb2dpbi55YWhvby5jb22CE3d3dy5sb2dpbi55YWhvby5jb20w
+DQYJKoZIhvcNAQEFBQADggEBAD1XyUgkXO5kgfWuvlUpFv8qL4Tt2fijA8gwZrvI
+1IEtIfcI96yWQppBdXq6XRAjy5JCYfqK2m1lNBnlqdYtE3jXgUSSqW6AYxXL/jUf
+AtGKFLCozJQgO6ga8F02UNsNrulk5PaNaX0wyBQXAErlpjX7fQ0inXl2Uiy8lwaI
+mhX0c+bx9ZilzQdEkbinaGdF0nIRYOJxt1BV4oqpDdaS7gQqizCgogVGNG2Sxjuq
+TaDQqwEZCjK36OPP8dKXSXuspJf38FeuY3eaf5baTf2+3Ac24yW9iXmOKRITi4gH
++2vbpM2zLSfp1Mpg14VT+3TGXDWMcB/5sreSJyDHlNVnFDA=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/9532e8b504964331c271f3f5f10070131a08bf8ba438978ce394c34feeae246f.pem b/chromium/net/data/ssl/blacklist/9532e8b504964331c271f3f5f10070131a08bf8ba438978ce394c34feeae246f.pem
new file mode 100644
index 00000000000..adb25eeea26
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/9532e8b504964331c271f3f5f10070131a08bf8ba438978ce394c34feeae246f.pem
@@ -0,0 +1,114 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ f5:c8:6a:f3:61:62:f1:3a:64:f5:4f:6d:c9:58:7c:06
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
+ Validity
+ Not Before: Mar 15 00:00:00 2011 GMT
+ Not After : Mar 14 23:59:59 2014 GMT
+ Subject: C=US/postalCode=38477, ST=Florida, L=English/street=Sea Village 10, O=Google Ltd., OU=Tech Dept., OU=Hosted by GTI Group Corporation, OU=PlatinumSSL, CN=www.google.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:b0:73:f0:f2:04:ee:c2:a2:46:ca:34:2a:aa:bb:
+ 60:23:d1:11:76:1f:1f:3a:d0:65:83:4e:9a:45:a8:
+ 43:70:85:76:f0:1f:87:00:02:1f:6e:3b:17:17:c4:
+ b5:e9:19:46:a2:92:25:8d:62:2a:b4:63:30:1f:b9:
+ 85:f8:35:e1:16:5a:76:49:cc:50:48:53:39:59:89:
+ d6:84:02:fb:9a:ec:1b:c7:51:d5:76:95:90:d4:3a:
+ 2a:b8:a6:de:02:4d:06:fb:cd:ed:a5:46:41:5f:55:
+ 74:e5:ec:7e:40:dc:50:9c:b5:e4:35:5d:1e:68:20:
+ f8:e9:de:a3:6a:28:bf:41:d2:a1:b3:e2:25:8d:0c:
+ 1b:ca:3d:93:0c:18:ae:df:c5:bc:fd:bc:82:ba:68:
+ 00:d7:16:32:71:9f:65:b5:11:da:68:59:d0:a6:57:
+ 64:1b:c9:fe:98:e5:f5:a5:65:ea:e1:db:ee:f4:b3:
+ 9d:b3:8e:ea:87:ae:16:d2:1e:a0:7c:7c:69:3f:29:
+ 16:85:01:53:a7:6c:f1:60:ab:dd:a2:fc:25:47:d4:
+ 32:d1:12:dd:f7:48:12:e0:fc:9c:a2:77:98:e9:89:
+ 99:b8:f8:38:f1:8c:06:c2:7a:23:36:6d:9b:9d:cd:
+ 30:c8:c7:34:17:1e:bb:7d:42:c8:ab:e7:15:16:f6:
+ 73:b5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45
+
+ X509v3 Subject Key Identifier:
+ 18:2A:A2:C8:D4:7A:3F:7B:AD:04:8B:BD:6F:9E:10:46:13:78:71:9D
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6449.1.2.1.3.4
+ CPS: https://secure.comodo.com/CPS
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/UTN-USERFirst-Hardware.crl
+
+ Full Name:
+ URI:http://crl.comodo.net/UTN-USERFirst-Hardware.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://crt.comodoca.com/UTNAddTrustServerCA.crt
+ OCSP - URI:http://ocsp.comodoca.com
+
+ X509v3 Subject Alternative Name:
+ DNS:www.google.com, DNS:google.com
+ Signature Algorithm: sha1WithRSAEncryption
+ 71:c0:99:3f:5e:f6:bd:33:ff:9e:16:cb:a8:bf:dd:70:f9:d2:
+ 53:3b:36:ae:c9:17:c8:ae:5e:4d:dd:62:f7:b7:d3:3e:77:a3:
+ fe:c0:7b:32:b5:c9:94:05:52:50:f2:5f:3d:79:84:49:4f:5d:
+ 6c:b0:d7:59:bd:d4:6c:88:fa:fc:c5:65:86:eb:28:52:a2:42:
+ f6:7c:bc:6a:c7:07:2e:25:d1:90:62:20:c6:8d:51:c2:2c:45:
+ 39:4e:03:da:f7:18:e8:cc:0a:3a:d9:45:d8:6c:6e:34:8b:62:
+ 9c:4e:15:f9:43:ee:e5:97:c0:3f:ad:35:13:c5:2b:06:c7:41:
+ fd:e2:f7:7e:45:ad:9b:d1:e1:66:ed:f8:7a:4b:94:39:7a:2f:
+ eb:e8:3f:43:d8:35:d6:56:fa:74:e7:6d:e6:ed:ac:65:84:fe:
+ d0:4d:06:12:de:da:59:00:3c:09:5c:cf:88:4b:e8:3d:b4:15:
+ 21:92:cc:6d:a6:51:e2:8e:97:f1:f4:82:46:cb:c4:53:5e:da:
+ 5c:9d:65:92:01:65:89:00:e5:b6:99:ff:26:40:f1:2f:19:31:
+ 08:1a:b1:67:55:86:0d:ae:35:33:86:bc:97:48:92:d7:96:60:
+ f8:ce:fc:96:eb:87:c4:73:cc:94:9b:58:5b:f3:7a:a4:27:13:
+ d6:4f:f4:69
+-----BEGIN CERTIFICATE-----
+MIIF5DCCBMygAwIBAgIRAPXIavNhYvE6ZPVPbclYfAYwDQYJKoZIhvcNAQEFBQAw
+gZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtl
+IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMY
+aHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR8wHQYDVQQDExZVVE4tVVNFUkZpcnN0
+LUhhcmR3YXJlMB4XDTExMDMxNTAwMDAwMFoXDTE0MDMxNDIzNTk1OVowgd4xCzAJ
+BgNVBAYTAlVTMQ4wDAYDVQQREwUzODQ3NzEQMA4GA1UECBMHRmxvcmlkYTEQMA4G
+A1UEBxMHRW5nbGlzaDEXMBUGA1UECRMOU2VhIFZpbGxhZ2UgMTAxFDASBgNVBAoT
+C0dvb2dsZSBMdGQuMRMwEQYDVQQLEwpUZWNoIERlcHQuMSgwJgYDVQQLEx9Ib3N0
+ZWQgYnkgR1RJIEdyb3VwIENvcnBvcmF0aW9uMRQwEgYDVQQLEwtQbGF0aW51bVNT
+TDEXMBUGA1UEAxMOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQCwc/DyBO7CokbKNCqqu2Aj0RF2Hx860GWDTppFqENwhXbwH4cA
+Ah9uOxcXxLXpGUaikiWNYiq0YzAfuYX4NeEWWnZJzFBIUzlZidaEAvua7BvHUdV2
+lZDUOiq4pt4CTQb7ze2lRkFfVXTl7H5A3FCcteQ1XR5oIPjp3qNqKL9B0qGz4iWN
+DBvKPZMMGK7fxbz9vIK6aADXFjJxn2W1EdpoWdCmV2Qbyf6Y5fWlZerh2+70s52z
+juqHrhbSHqB8fGk/KRaFAVOnbPFgq92i/CVH1DLREt33SBLg/Jyid5jpiZm4+Djx
+jAbCeiM2bZudzTDIxzQXHrt9Qsir5xUW9nO1AgMBAAGjggHgMIIB3DAfBgNVHSME
+GDAWgBShcl8mGyiYQ5VdBzfVhZadS9LDRTAdBgNVHQ4EFgQUGCqiyNR6P3utBIu9
+b54QRhN4cZ0wDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYw
+FAYIKwYBBQUHAwEGCCsGAQUFBwMCMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQME
+MCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMHsG
+A1UdHwR0MHIwOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1VUTi1VU0VS
+Rmlyc3QtSGFyZHdhcmUuY3JsMDagNKAyhjBodHRwOi8vY3JsLmNvbW9kby5uZXQv
+VVROLVVTRVJGaXJzdC1IYXJkd2FyZS5jcmwwcQYIKwYBBQUHAQEEZTBjMDsGCCsG
+AQUFBzAChi9odHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9VVE5BZGRUcnVzdFNlcnZl
+ckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMCUG
+A1UdEQQeMByCDnd3dy5nb29nbGUuY29tggpnb29nbGUuY29tMA0GCSqGSIb3DQEB
+BQUAA4IBAQBxwJk/Xva9M/+eFsuov91w+dJTOzauyRfIrl5N3WL3t9M+d6P+wHsy
+tcmUBVJQ8l89eYRJT11ssNdZvdRsiPr8xWWG6yhSokL2fLxqxwcuJdGQYiDGjVHC
+LEU5TgPa9xjozAo62UXYbG40i2KcThX5Q+7ll8A/rTUTxSsGx0H94vd+Ra2b0eFm
+7fh6S5Q5ei/r6D9D2DXWVvp0523m7axlhP7QTQYS3tpZADwJXM+IS+g9tBUhksxt
+plHijpfx9IJGy8RTXtpcnWWSAWWJAOW2mf8mQPEvGTEIGrFnVYYNrjUzhryXSJLX
+lmD4zvyW64fEc8yUm1hb83qkJxPWT/Rp
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/9ed8f9b0e8e42a1656b8e1dd18f42ba42dc06fe52686173ba2fc70e756f207dc.pem b/chromium/net/data/ssl/blacklist/9ed8f9b0e8e42a1656b8e1dd18f42ba42dc06fe52686173ba2fc70e756f207dc.pem
new file mode 100644
index 00000000000..0e087a667dd
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/9ed8f9b0e8e42a1656b8e1dd18f42ba42dc06fe52686173ba2fc70e756f207dc.pem
@@ -0,0 +1,111 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 120000525 (0x727100d)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Global Root
+ Validity
+ Not Before: Oct 4 10:54:11 2006 GMT
+ Not After : Oct 4 10:53:11 2011 GMT
+ Subject: C=NL, O=DigiNotar, CN=DigiNotar Cyber CA/emailAddress=info@diginotar.nl
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:d2:ce:15:0a:2d:a8:5e:84:67:ad:fd:be:ef:46:
+ c7:c8:b9:cf:73:fc:f4:34:b9:f9:2c:43:e7:60:13:
+ 3d:7a:e3:b2:cf:3b:67:6c:90:ad:c0:b9:3f:84:52:
+ f0:35:42:dc:74:dc:28:3b:bd:52:b4:a7:ac:72:45:
+ 17:c6:f0:89:eb:b4:aa:25:f2:5d:4b:5e:d1:d9:87:
+ ba:d6:7d:7c:f5:ce:32:9f:10:33:c5:b1:4a:bb:5e:
+ 91:31:c2:d0:e9:41:c2:91:64:7e:09:41:3b:db:8b:
+ 08:37:6a:aa:ca:52:de:b5:39:1e:c0:88:03:a5:3f:
+ 8b:99:13:61:43:b5:9b:82:b3:ee:20:6f:cf:a1:44:
+ a2:ea:2f:6b:40:9f:8f:2b:57:ad:a1:53:c2:85:22:
+ 69:9d:a0:3f:51:df:0b:41:91:0d:a5:e1:a8:aa:5c:
+ 49:08:5d:bd:de:70:41:b1:0f:c9:63:6b:d3:7f:34:
+ 74:02:2f:34:5a:78:75:1c:68:7a:81:67:8a:f3:da:
+ 40:f0:60:63:f4:92:20:d7:03:a6:3d:a3:1e:67:c4:
+ 84:1b:41:a5:c9:8c:e6:bd:ea:48:b6:05:16:08:b3:
+ 37:12:5a:f7:61:3c:f7:38:6f:2e:97:e0:6f:56:38:
+ 54:d3:28:b5:ad:14:6e:2e:4b:64:b5:27:65:b7:75:
+ 25:09:b6:07:3d:95:56:02:0a:82:60:b2:73:45:e0:
+ 33:26:51:74:9a:b9:d4:50:1c:f6:4d:5b:5b:52:52:
+ 13:5a:a6:7f:a7:0e:e1:e8:41:54:67:98:8c:87:d5:
+ c9:d3:6c:cb:d3:54:92:06:09:34:41:f7:81:6f:3f:
+ 9e:c9:7c:75:55:b0:e7:c1:b3:77:e8:c3:c4:00:35:
+ 95:40:70:10:4a:05:de:25:bb:9f:59:a5:64:bc:47:
+ 60:bf:60:e3:76:8b:13:55:dd:e1:74:7a:b9:cf:24:
+ a6:6a:7f:de:64:22:44:58:68:82:6a:10:f9:3d:e5:
+ 3e:1b:b9:bd:fc:22:f4:60:04:89:bb:55:6d:28:55:
+ fa:de:8e:8d:1b:21:14:d7:37:8b:34:7b:4d:f6:b2:
+ b2:10:cf:33:b1:7d:1c:62:99:48:cb:2b:6c:76:96:
+ 55:bf:19:0d:1d:1f:bb:65:aa:1b:8e:99:b5:c6:28:
+ 90:e5:82:2d:78:50:20:9a:fd:79:2f:24:7f:f0:89:
+ 29:69:f4:7d:cd:73:be:b3:ed:4e:c1:d1:ed:52:5e:
+ 8f:f7:b8:d7:8d:87:ad:b2:d9:1b:51:12:ff:56:b3:
+ e1:af:34:7d:5c:a4:78:88:10:9e:9d:03:c6:a5:aa:
+ a2:24:51:f7:49:14:c5:b1:ee:59:43:95:df:ab:68:
+ 28:30:3f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:1
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6334.1.0
+ CPS: http://www.public-trust.com/CPS/OmniRoot.html
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Authority Key Identifier:
+ keyid:A6:0C:1D:9F:61:FF:07:17:B5:BF:38:46:DB:43:30:D5:8E:B0:52:06
+ DirName:/C=US/O=GTE Corporation/OU=GTE CyberTrust Solutions, Inc./CN=GTE CyberTrust Global Root
+ serial:01:A5
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://www.public-trust.com/cgi-bin/CRL/2018/cdp.crl
+
+ X509v3 Subject Key Identifier:
+ AB:F9:68:DF:CF:4A:37:D7:7B:45:8C:5F:72:DE:40:44:C3:65:BB:C2
+ Signature Algorithm: sha1WithRSAEncryption
+ 8f:68:6b:a5:5b:07:ba:44:66:0e:1c:a8:5c:30:7b:33:e4:0a:
+ 26:04:fc:ef:9e:1a:38:d6:2e:a1:1f:d0:99:47:c2:75:64:24:
+ fd:9e:3b:28:76:b9:26:28:61:91:0c:6d:2c:f8:04:9f:7c:50:
+ 01:d5:e3:69:af:ef:15:d2:45:9b:24:09:2a:66:05:4f:25:81:
+ ca:5d:be:aa:c1:59:27:ae:33:8e:82:f7:df:74:b0:55:b3:8e:
+ f8:e7:37:c8:6e:aa:56:44:f6:bd:53:81:23:96:3d:b4:fa:32:
+ 8a:53:66:44:25:a2:25:c6:a6:3c:25:8c:f0:e0:28:06:22:b7:
+ 26:41
+-----BEGIN CERTIFICATE-----
+MIIFWjCCBMOgAwIBAgIEBycQDTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV
+UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
+cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
+b2JhbCBSb290MB4XDTA2MTAwNDEwNTQxMVoXDTExMTAwNDEwNTMxMVowYDELMAkG
+A1UEBhMCTkwxEjAQBgNVBAoTCURpZ2lOb3RhcjEbMBkGA1UEAxMSRGlnaU5vdGFy
+IEN5YmVyIENBMSAwHgYJKoZIhvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubDCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANLOFQotqF6EZ639vu9Gx8i5z3P8
+9DS5+SxD52ATPXrjss87Z2yQrcC5P4RS8DVC3HTcKDu9UrSnrHJFF8bwieu0qiXy
+XUte0dmHutZ9fPXOMp8QM8WxSrtekTHC0OlBwpFkfglBO9uLCDdqqspS3rU5HsCI
+A6U/i5kTYUO1m4Kz7iBvz6FEouova0CfjytXraFTwoUiaZ2gP1HfC0GRDaXhqKpc
+SQhdvd5wQbEPyWNr0380dAIvNFp4dRxoeoFnivPaQPBgY/SSINcDpj2jHmfEhBtB
+pcmM5r3qSLYFFgizNxJa92E89zhvLpfgb1Y4VNMota0Ubi5LZLUnZbd1JQm2Bz2V
+VgIKgmCyc0XgMyZRdJq51FAc9k1bW1JSE1qmf6cO4ehBVGeYjIfVydNsy9NUkgYJ
+NEH3gW8/nsl8dVWw58Gzd+jDxAA1lUBwEEoF3iW7n1mlZLxHYL9g43aLE1Xd4XR6
+uc8kpmp/3mQiRFhogmoQ+T3lPhu5vfwi9GAEibtVbShV+t6OjRshFNc3izR7Tfay
+shDPM7F9HGKZSMsrbHaWVb8ZDR0fu2WqG46ZtcYokOWCLXhQIJr9eS8kf/CJKWn0
+fc1zvrPtTsHR7VJej/e4142HrbLZG1ES/1az4a80fVykeIgQnp0DxqWqoiRR90kU
+xbHuWUOV36toKDA/AgMBAAGjggGGMIIBgjASBgNVHRMBAf8ECDAGAQH/AgEBMFMG
+A1UdIARMMEowSAYJKwYBBAGxPgEAMDswOQYIKwYBBQUHAgEWLWh0dHA6Ly93d3cu
+cHVibGljLXRydXN0LmNvbS9DUFMvT21uaVJvb3QuaHRtbDAOBgNVHQ8BAf8EBAMC
+AQYwgaAGA1UdIwSBmDCBlYAUpgwdn2H/Bxe1vzhG20Mw1Y6wUgaheaR3MHUxCzAJ
+BgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdU
+RSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVy
+VHJ1c3QgR2xvYmFsIFJvb3SCAgGlMEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly93
+d3cucHVibGljLXRydXN0LmNvbS9jZ2ktYmluL0NSTC8yMDE4L2NkcC5jcmwwHQYD
+VR0OBBYEFKv5aN/PSjfXe0WMX3LeQETDZbvCMA0GCSqGSIb3DQEBBQUAA4GBAI9o
+a6VbB7pEZg4cqFwwezPkCiYE/O+eGjjWLqEf0JlHwnVkJP2eOyh2uSYoYZEMbSz4
+BJ98UAHV42mv7xXSRZskCSpmBU8lgcpdvqrBWSeuM46C9990sFWzjvjnN8huqlZE
+9r1TgSOWPbT6MopTZkQloiXGpjwljPDgKAYityZB
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/README.md b/chromium/net/data/ssl/blacklist/README.md
new file mode 100644
index 00000000000..9d45f72143f
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/README.md
@@ -0,0 +1,195 @@
+# Certificate Blacklist
+
+This directory contains a number of certificates and public keys which are
+considered blacklisted within Chromium-based products.
+
+When applicable, additional information and the full certificate or key
+are included.
+
+## Compromises & Misissuances
+
+### Comodo
+
+For details, see <https://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html>,
+<https://blog.mozilla.org/security/2011/03/25/comodo-certificate-issue-follow-up/>,
+and <https://technet.microsoft.com/en-us/library/security/2524375.aspx>.
+
+As the result of a compromise of a partner RA of Comodo, nine certificates were
+misissued, for a variety of online services.
+
+ * <2a3699deca1e9fd099ba45de8489e205977c9f2a5e29d5dd747381eec0744d71.pem>
+ * <4bf6bb839b03b72839329b4ea70bb1b2f0d07e014d9d24aa9cc596114702bee3.pem>
+ * <79f69a47cfd6c4b4ceae8030d04b49f6171d3b5d6c812f58d040e586f1cb3f14.pem>
+ * <8290cc3fc1c3aac3239782c141ace8f88aeef4e9576a43d01867cf19d025be66.pem>
+ * <933f7d8cda9f0d7c8bfd3c22bf4653f4161fd38ccdcf66b22e95a2f49c2650f8.pem>
+ * <9532e8b504964331c271f3f5f10070131a08bf8ba438978ce394c34feeae246f.pem>
+ * <be144b56fb1163c49c9a0e6b5a458df6b29f7e6449985960c178a4744624b7bc.pem>
+ * <ead610e6e90b439f2ecb51628b0932620f6ef340bd843fca38d3181b8f4ba197.pem>
+ * <f8a5ff189fedbfe34e21103389a68340174439ad12974a4e8d4d784d1f3a0faa.pem>
+
+### DigiNotar
+
+For details, see <https://googleonlinesecurity.blogspot.com/2011/08/update-on-attempted-man-in-middle.html>
+and <https://en.wikipedia.org/wiki/DigiNotar>.
+
+As a result of a complete CA compromise, the following certificates (and
+their associated public keypairs) are revoked.
+
+ * <0d136e439f0ab6e97f3a02a540da9f0641aa554e1d66ea51ae2920d51b2f7217.pem>
+ * <294f55ef3bd7244c6ff8a68ab797e9186ec27582751a791515e3292e48372d61.pem>
+ * <31c8fd37db9b56e708b03d1f01848b068c6da66f36fb5d82c008c6040fa3e133.pem>
+ * <3946901f46b0071e90d78279e82fababca177231a704be72c5b0e8918566ea66.pem>
+ * <450f1b421bb05c8609854884559c323319619e8b06b001ea2dcbb74a23aa3be2.pem>
+ * <4fee0163686ecbd65db968e7494f55d84b25486d438e9de558d629d28cd4d176.pem>
+ * <8a1bd21661c60015065212cc98b1abb50dfd14c872a208e66bae890f25c448af.pem>
+ * <9ed8f9b0e8e42a1656b8e1dd18f42ba42dc06fe52686173ba2fc70e756f207dc.pem>
+ * <a686fee577c88ab664d0787ecdfff035f4806f3de418dc9e4d516324fff02083.pem>
+ * <b8686723e415534bc0dbd16326f9486f85b0b0799bf6639334e61daae67f36cd.pem>
+ * <fdedb5bdfcb67411513a61aee5cb5b5d7c52af06028efc996cc1b05b1d6cea2b.pem>
+
+### India CCA
+
+For details, see <https://googleonlinesecurity.blogspot.com/2014/07/maintaining-digital-certificate-security.html>
+and <https://technet.microsoft.com/en-us/library/security/2982792.aspx>
+
+An unknown number of misissued certificates were issued by a sub-CA of
+India CCA, the India NIC. Due to the scope of the misissuance, the sub-CA
+was wholly revoked, and India CCA was constrained to a subset of India's
+ccTLD namespace.
+
+ * <67ed4b703d15dc555f8c444b3a05a32579cb7599bd19c9babe10c584ea327ae0.pem>
+ * <a8e1dfd9cd8e470aa2f443914f931cfd61c323e94d75827affee985241c35ce5.pem>
+ * <e4f9a3235df7330255f36412bc849fb630f8519961ec3538301deb896c953da5.pem>
+
+### Trustwave
+
+For details, see <https://www.trustwave.com/Resources/SpiderLabs-Blog/Clarifying-The-Trustwave-CA-Policy-Update/>
+and <https://bugzilla.mozilla.org/show_bug.cgi?id=724929>
+
+Two certificates were issued by Trustwave for use in enterprise
+Man-in-the-Middle. The following public key was used for both certificates,
+and is revoked.
+
+ * <32ecc96f912f96d889e73088cd031c7ded2c651c805016157a23b6f32f798a3b.key>
+
+### TurkTrust
+
+For details, see <https://googleonlinesecurity.blogspot.com/2013/01/enhancing-digital-certificate-security.html>
+and <https://web.archive.org/web/20130326152502/http://turktrust.com.tr/kamuoyu-aciklamasi.2.html>
+
+As a result of a software configuration issue, two certificates were misissued
+by Turktrust that failed to properly set the basicConstraints extension.
+Because these certificates can be used to issue additional certificates, they
+have been revoked.
+
+ * <372447c43185c38edd2ce0e9c853f9ac1576ddd1704c2f54d96076c089cb4227.pem>
+ * <42187727be39faf667aeb92bf0cc4e268f6e2ead2cefbec575bdc90430024f69.pem>
+
+## Private Key Leakages
+
+### Cyberoam
+
+For details, see <https://blog.torproject.org/blog/security-vulnerability-found-cyberoam-dpi-devices-cve-2012-3372>
+
+Device manufacturer Cyberoam used the same private key for all devices by
+default, which subsequently leaked and is included below. The associated
+public key is blacklisted.
+
+ * <1af56c98ff043ef92bebff54cebb4dd67a25ba956c817f3e6dd3c1e52eb584c1.key>
+
+### Dell
+
+For details, see <http://www.dell.com/support/article/us/en/19/SLN300321>
+and <http://en.community.dell.com/dell-blogs/direct2dell/b/direct2dell/archive/2015/11/23/response-to-concerns-regarding-edellroot-certificate>
+
+The private keys for both the eDellRoot and DSDTestProvider certificates were
+trivially extracted, and thus their associated public keys are
+blacklisted.
+
+ * <0f912fd7be760be25afbc56bdc09cd9e5dcc9c6f6a55a778aefcb6aa30e31554.pem>
+ * <ec30c9c3065a06bb07dc5b1c6b497f370c1ca65c0f30c08e042ba6bcecc78f2c.pem>
+
+### sslip.io
+
+For details, see <https://blog.pivotal.io/labs/labs/sslip-io-a-valid-ssl-certificate-for-every-ip-address>
+
+A subscriber of Comodo's acquired a wildcard certificate for sslip.io, and
+then subsequently published the private key, as a means for developers
+to avoid having to acquire certificates.
+
+As the private key could be used to intercept all communications to this
+domain, the associated public key was blacklisted.
+
+ * <f3bae5e9c0adbfbfb6dbf7e04e74be6ead3ca98a5604ffe591cea86c241848ec.pem>
+
+### xs4all.nl
+
+For details, see <https://raymii.org/s/blog/How_I_got_a_valid_SSL_certificate_for_my_ISPs_main_website.html>
+
+A user of xs4all was able to register a reserved email address that can be
+used to cause certificate issuance, as described in the CA/Browser Forum's
+Baseline Requirements, and then subsequently published the private key.
+
+ * <83618f932d6947744d5ecca299d4b2820c01483947bd16be814e683f7436be24.pem>
+
+## Miscellaneous
+
+### DigiCert
+
+For details, see <https://bugzilla.mozilla.org/show_bug.cgi?id=1242758> and
+<https://bugzilla.mozilla.org/show_bug.cgi?id=1224104>
+
+These two intermediates were retired by DigiCert, and blacklisted for
+robustness at their request.
+
+ * <159ca03a88897c8f13817a212629df84ce824709492b8c9adb8e5437d2fc72be.pem>
+ * <b8c1b957c077ea76e00b0f45bff5ae3acb696f221d2e062164fe37125e5a8d25.pem>
+
+### Hacking Team
+
+The following keys were reported as used by Hacking Team to compromise users,
+and are blacklisted for robustness.
+
+ * <c4387d45364a313fbfe79812b35b815d42852ab03b06f11589638021c8f2cb44.key>
+ * <ea08c8d45d52ca593de524f0513ca6418da9859f7b08ef13ff9dd7bf612d6a37.key>
+
+### live.fi
+
+For details, see <https://technet.microsoft.com/en-us/library/security/3046310.aspx>
+
+A user of live.fi was able to register a reserved email address that can be
+used to cause certificate issuance, as described in the CA/Browser Forum's
+Baseline Requirements. This was not intended by Microsoft, the operators of
+live.fi, but conformed to the Baseline Requirements. It was blacklisted for
+robustness.
+
+ * <c67d722c1495be02cbf9ef1159f5ca4aa782dc832dc6aa60c9aa076a0ad1e69d.pem>
+
+### SECOM
+
+For details, see <https://bugzilla.mozilla.org/show_bug.cgi?id=1188582>
+
+This intermediate certificate was retired by SECOM, and blacklisted for
+robustness at their request.
+
+ * <817d4e05063d5942869c47d8504dc56a5208f7569c3d6d67f3457cfe921b3e29.pem>
+
+### Symantec
+
+For details, see <https://bugzilla.mozilla.org/show_bug.cgi?id=966060>
+
+These three intermediate certificates were retired by Symantec, and
+blacklisted for robustness at their request.
+
+ * <1f17f2cbb109f01c885c94d9e74a48625ae9659665d6d7e7bc5a10332976370f.pem>
+ * <3e26492e20b52de79e15766e6cb4251a1d566b0dbfb225aa7d08dda1dcebbf0a.pem>
+ * <7abd72a323c9d179c722564f4e27a51dd4afd24006b38a40ce918b94960bcf18.pem>
+
+### T-Systems
+
+For details, see <https://bugzilla.mozilla.org/show_bug.cgi?id=1076940>
+
+This intermediate certificate was retired by T-Systems, and blacklisted
+for robustness at their request.
+
+ * <f4a5984324de98bd979ef181a100cf940f2166173319a86a0d9d7c8fac3b0a8f.pem>
diff --git a/chromium/net/data/ssl/blacklist/a686fee577c88ab664d0787ecdfff035f4806f3de418dc9e4d516324fff02083.pem b/chromium/net/data/ssl/blacklist/a686fee577c88ab664d0787ecdfff035f4806f3de418dc9e4d516324fff02083.pem
new file mode 100644
index 00000000000..be77dee975a
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/a686fee577c88ab664d0787ecdfff035f4806f3de418dc9e4d516324fff02083.pem
@@ -0,0 +1,110 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 120000515 (0x7271003)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Global Root
+ Validity
+ Not Before: Sep 27 10:53:32 2006 GMT
+ Not After : Sep 27 10:52:30 2011 GMT
+ Subject: C=NL, O=DigiNotar, CN=DigiNotar Cyber CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:d2:ce:15:0a:2d:a8:5e:84:67:ad:fd:be:ef:46:
+ c7:c8:b9:cf:73:fc:f4:34:b9:f9:2c:43:e7:60:13:
+ 3d:7a:e3:b2:cf:3b:67:6c:90:ad:c0:b9:3f:84:52:
+ f0:35:42:dc:74:dc:28:3b:bd:52:b4:a7:ac:72:45:
+ 17:c6:f0:89:eb:b4:aa:25:f2:5d:4b:5e:d1:d9:87:
+ ba:d6:7d:7c:f5:ce:32:9f:10:33:c5:b1:4a:bb:5e:
+ 91:31:c2:d0:e9:41:c2:91:64:7e:09:41:3b:db:8b:
+ 08:37:6a:aa:ca:52:de:b5:39:1e:c0:88:03:a5:3f:
+ 8b:99:13:61:43:b5:9b:82:b3:ee:20:6f:cf:a1:44:
+ a2:ea:2f:6b:40:9f:8f:2b:57:ad:a1:53:c2:85:22:
+ 69:9d:a0:3f:51:df:0b:41:91:0d:a5:e1:a8:aa:5c:
+ 49:08:5d:bd:de:70:41:b1:0f:c9:63:6b:d3:7f:34:
+ 74:02:2f:34:5a:78:75:1c:68:7a:81:67:8a:f3:da:
+ 40:f0:60:63:f4:92:20:d7:03:a6:3d:a3:1e:67:c4:
+ 84:1b:41:a5:c9:8c:e6:bd:ea:48:b6:05:16:08:b3:
+ 37:12:5a:f7:61:3c:f7:38:6f:2e:97:e0:6f:56:38:
+ 54:d3:28:b5:ad:14:6e:2e:4b:64:b5:27:65:b7:75:
+ 25:09:b6:07:3d:95:56:02:0a:82:60:b2:73:45:e0:
+ 33:26:51:74:9a:b9:d4:50:1c:f6:4d:5b:5b:52:52:
+ 13:5a:a6:7f:a7:0e:e1:e8:41:54:67:98:8c:87:d5:
+ c9:d3:6c:cb:d3:54:92:06:09:34:41:f7:81:6f:3f:
+ 9e:c9:7c:75:55:b0:e7:c1:b3:77:e8:c3:c4:00:35:
+ 95:40:70:10:4a:05:de:25:bb:9f:59:a5:64:bc:47:
+ 60:bf:60:e3:76:8b:13:55:dd:e1:74:7a:b9:cf:24:
+ a6:6a:7f:de:64:22:44:58:68:82:6a:10:f9:3d:e5:
+ 3e:1b:b9:bd:fc:22:f4:60:04:89:bb:55:6d:28:55:
+ fa:de:8e:8d:1b:21:14:d7:37:8b:34:7b:4d:f6:b2:
+ b2:10:cf:33:b1:7d:1c:62:99:48:cb:2b:6c:76:96:
+ 55:bf:19:0d:1d:1f:bb:65:aa:1b:8e:99:b5:c6:28:
+ 90:e5:82:2d:78:50:20:9a:fd:79:2f:24:7f:f0:89:
+ 29:69:f4:7d:cd:73:be:b3:ed:4e:c1:d1:ed:52:5e:
+ 8f:f7:b8:d7:8d:87:ad:b2:d9:1b:51:12:ff:56:b3:
+ e1:af:34:7d:5c:a4:78:88:10:9e:9d:03:c6:a5:aa:
+ a2:24:51:f7:49:14:c5:b1:ee:59:43:95:df:ab:68:
+ 28:30:3f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:1
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6334.1.0
+ CPS: http://www.public-trust.com/CPS/OmniRoot.html
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Authority Key Identifier:
+ keyid:A6:0C:1D:9F:61:FF:07:17:B5:BF:38:46:DB:43:30:D5:8E:B0:52:06
+ DirName:/C=US/O=GTE Corporation/OU=GTE CyberTrust Solutions, Inc./CN=GTE CyberTrust Global Root
+ serial:01:A5
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://www.public-trust.com/cgi-bin/CRL/2018/cdp.crl
+
+ X509v3 Subject Key Identifier:
+ AB:F9:68:DF:CF:4A:37:D7:7B:45:8C:5F:72:DE:40:44:C3:65:BB:C2
+ Signature Algorithm: sha1WithRSAEncryption
+ 59:cc:86:66:18:b3:26:54:4f:d6:38:cd:ba:96:5e:cb:ec:99:
+ 1b:aa:0c:0d:6e:19:d7:56:e8:ae:23:07:6d:83:c2:9d:d0:44:
+ 6d:58:74:ef:39:8f:6d:9b:22:84:ec:3d:c3:fb:e6:e4:a6:d5:
+ 5f:90:a0:c5:4b:f8:46:1c:e1:ff:6d:05:6a:2c:5f:dc:fd:db:
+ a5:68:34:aa:0c:c7:55:5b:ac:35:54:7f:3f:9d:1a:2a:4a:5d:
+ 2b:78:69:f9:02:e5:e7:a7:be:95:63:9d:75:20:08:34:8a:66:
+ 72:ec:83:23:58:72:bb:30:7e:18:91:00:4a:6f:6d:35:4f:fa:
+ ae:cf
+-----BEGIN CERTIFICATE-----
+MIIFODCCBKGgAwIBAgIEBycQAzANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV
+UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
+cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
+b2JhbCBSb290MB4XDTA2MDkyNzEwNTMzMloXDTExMDkyNzEwNTIzMFowPjELMAkG
+A1UEBhMCTkwxEjAQBgNVBAoTCURpZ2lOb3RhcjEbMBkGA1UEAxMSRGlnaU5vdGFy
+IEN5YmVyIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0s4VCi2o
+XoRnrf2+70bHyLnPc/z0NLn5LEPnYBM9euOyzztnbJCtwLk/hFLwNULcdNwoO71S
+tKesckUXxvCJ67SqJfJdS17R2Ye61n189c4ynxAzxbFKu16RMcLQ6UHCkWR+CUE7
+24sIN2qqylLetTkewIgDpT+LmRNhQ7WbgrPuIG/PoUSi6i9rQJ+PK1etoVPChSJp
+naA/Ud8LQZENpeGoqlxJCF293nBBsQ/JY2vTfzR0Ai80Wnh1HGh6gWeK89pA8GBj
+9JIg1wOmPaMeZ8SEG0GlyYzmvepItgUWCLM3Elr3YTz3OG8ul+BvVjhU0yi1rRRu
+LktktSdlt3UlCbYHPZVWAgqCYLJzReAzJlF0mrnUUBz2TVtbUlITWqZ/pw7h6EFU
+Z5iMh9XJ02zL01SSBgk0QfeBbz+eyXx1VbDnwbN36MPEADWVQHAQSgXeJbufWaVk
+vEdgv2DjdosTVd3hdHq5zySman/eZCJEWGiCahD5PeU+G7m9/CL0YASJu1VtKFX6
+3o6NGyEU1zeLNHtN9rKyEM8zsX0cYplIyytsdpZVvxkNHR+7Zaobjpm1xiiQ5YIt
+eFAgmv15LyR/8IkpafR9zXO+s+1OwdHtUl6P97jXjYetstkbURL/VrPhrzR9XKR4
+iBCenQPGpaqiJFH3SRTFse5ZQ5Xfq2goMD8CAwEAAaOCAYYwggGCMBIGA1UdEwEB
+/wQIMAYBAf8CAQEwUwYDVR0gBEwwSjBIBgkrBgEEAbE+AQAwOzA5BggrBgEFBQcC
+ARYtaHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29tL0NQUy9PbW5pUm9vdC5odG1s
+MA4GA1UdDwEB/wQEAwIBBjCBoAYDVR0jBIGYMIGVgBSmDB2fYf8HF7W/OEbbQzDV
+jrBSBqF5pHcwdTELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD0dURSBDb3Jwb3JhdGlv
+bjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3QgU29sdXRpb25zLCBJbmMuMSMwIQYD
+VQQDExpHVEUgQ3liZXJUcnVzdCBHbG9iYWwgUm9vdIICAaUwRQYDVR0fBD4wPDA6
+oDigNoY0aHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29tL2NnaS1iaW4vQ1JMLzIw
+MTgvY2RwLmNybDAdBgNVHQ4EFgQUq/lo389KN9d7RYxfct5ARMNlu8IwDQYJKoZI
+hvcNAQEFBQADgYEAWcyGZhizJlRP1jjNupZey+yZG6oMDW4Z11boriMHbYPCndBE
+bVh07zmPbZsihOw9w/vm5KbVX5CgxUv4Rhzh/20Faixf3P3bpWg0qgzHVVusNVR/
+P50aKkpdK3hp+QLl56e+lWOddSAINIpmcuyDI1hyuzB+GJEASm9tNU/6rs8=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/a8e1dfd9cd8e470aa2f443914f931cfd61c323e94d75827affee985241c35ce5.pem b/chromium/net/data/ssl/blacklist/a8e1dfd9cd8e470aa2f443914f931cfd61c323e94d75827affee985241c35ce5.pem
new file mode 100644
index 00000000000..54a4bab2bdf
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/a8e1dfd9cd8e470aa2f443914f931cfd61c323e94d75827affee985241c35ce5.pem
@@ -0,0 +1,96 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 10161 (0x27b1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=IN, O=India PKI, CN=CCA India 2014
+ Validity
+ Not Before: Mar 5 11:15:24 2014 GMT
+ Not After : Mar 5 06:30:00 2024 GMT
+ Subject: C=IN, O=National Informatics Centre, OU=Certifying Authority/postalCode=110003, ST=Delhi/street=Lodhi Road, New Delhi/houseIdentifier=A-Block, CGO Complex, CN=NIC CA 2014
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:fc:e4:39:e8:67:bd:32:12:62:07:0b:4e:94:22:
+ 4f:e2:9e:60:8d:c0:ae:aa:44:36:e8:10:92:42:07:
+ c0:b3:1c:8d:c4:0c:2d:2f:57:f4:87:77:79:28:d1:
+ 48:22:72:06:d9:8f:4f:c0:18:14:ae:06:af:39:6c:
+ b6:71:92:02:c6:05:c8:19:a3:b3:2b:96:c8:4f:21:
+ a1:c5:83:0f:53:39:1a:cc:6a:69:7e:3d:12:71:6e:
+ c4:77:f9:23:78:39:e2:73:75:a5:62:43:f0:b4:d6:
+ 95:d6:ac:13:12:5a:fc:ce:a3:d4:b5:3d:bb:64:3a:
+ 9d:ea:ea:68:af:d3:08:0a:78:17:00:2d:6d:1e:38:
+ 4f:b8:6a:c6:b6:ee:22:e8:53:0f:ae:69:28:7f:07:
+ 61:f1:d9:2e:47:35:3f:38:f8:df:f6:50:3e:13:d4:
+ 2e:d0:db:ea:b2:82:3d:82:b2:40:d1:eb:60:45:f9:
+ fd:8e:e4:78:5f:72:93:1b:6d:6a:1e:7c:da:e7:43:
+ e9:31:80:b8:fa:f8:7c:8c:09:c8:4f:b2:9c:cf:c1:
+ a0:af:87:a0:86:4b:cf:fa:2c:f6:c8:4b:48:71:5f:
+ 4c:d7:17:a8:f7:c5:d4:fe:3c:6e:61:2e:cb:79:6b:
+ 4e:ef:d8:e4:8a:a0:88:aa:02:3c:4f:7c:7b:2c:7b:
+ 82:69
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:1
+ X509v3 Subject Key Identifier:
+ 46:70:CA:2F:25:4E:C3:47
+ X509v3 Certificate Policies:
+ Policy: 2.16.356.100.2
+
+ X509v3 Authority Key Identifier:
+ keyid:42:B8:C5:CF:6D:B3:57:E1
+
+ Authority Information Access:
+ OCSP - URI:http://ocvs.gov.in
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://cca.gov.in/rw/resources/CCAIndia2014Latest.crl
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 81:8b:78:89:79:49:64:7e:36:3d:e8:78:1f:04:85:04:b0:b8:
+ be:92:73:b7:55:4a:f1:0e:6c:29:b3:56:32:86:04:52:b7:6d:
+ 8d:40:b6:78:8e:4b:12:58:b2:36:11:06:e7:f6:4e:6d:1f:ca:
+ f0:49:bb:0e:59:ff:93:64:7e:e3:a5:a2:80:55:26:22:d4:68:
+ 44:6c:64:7f:0b:66:5e:16:25:80:4f:0b:4f:58:aa:15:1b:0c:
+ 7f:92:c5:0e:f5:83:cc:cd:fd:30:87:a7:c3:22:ec:81:24:8b:
+ 3f:9e:e3:7d:df:e2:f6:89:bf:93:4b:9b:e2:36:4c:be:1e:b4:
+ 77:5f:2a:84:d3:3e:37:5b:96:db:cc:c6:e2:76:8d:e5:6f:08:
+ 2b:76:b3:16:0f:a8:42:35:26:6c:f3:cf:0b:d1:27:b8:ae:7d:
+ 9e:8b:46:8f:98:79:b1:8c:38:db:13:11:77:34:5e:a6:da:e6:
+ 02:ff:00:11:e1:c5:48:cc:cb:ef:a6:d1:58:9f:e4:80:74:6f:
+ e9:c2:42:87:68:c5:67:70:1f:dc:c7:11:16:88:ac:ce:c5:5a:
+ 63:06:c3:38:37:5f:65:a7:1a:76:45:4f:e7:fb:1e:f1:44:ad:
+ d6:4d:0b:cd:01:97:54:ee:97:00:62:66:48:5c:fb:bf:11:2f:
+ 6a:a4:ae:1f
+-----BEGIN CERTIFICATE-----
+MIIEWzCCA0OgAwIBAgICJ7EwDQYJKoZIhvcNAQELBQAwOjELMAkGA1UEBhMCSU4x
+EjAQBgNVBAoTCUluZGlhIFBLSTEXMBUGA1UEAxMOQ0NBIEluZGlhIDIwMTQwHhcN
+MTQwMzA1MTExNTI0WhcNMjQwMzA1MDYzMDAwWjCByDELMAkGA1UEBhMCSU4xJDAi
+BgNVBAoTG05hdGlvbmFsIEluZm9ybWF0aWNzIENlbnRyZTEdMBsGA1UECxMUQ2Vy
+dGlmeWluZyBBdXRob3JpdHkxDzANBgNVBBETBjExMDAwMzEOMAwGA1UECBMFRGVs
+aGkxHjAcBgNVBAkTFUxvZGhpIFJvYWQsIE5ldyBEZWxoaTEdMBsGA1UEMxMUQS1C
+bG9jaywgQ0dPIENvbXBsZXgxFDASBgNVBAMTC05JQyBDQSAyMDE0MIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/OQ56Ge9MhJiBwtOlCJP4p5gjcCuqkQ2
+6BCSQgfAsxyNxAwtL1f0h3d5KNFIInIG2Y9PwBgUrgavOWy2cZICxgXIGaOzK5bI
+TyGhxYMPUzkazGppfj0ScW7Ed/kjeDnic3WlYkPwtNaV1qwTElr8zqPUtT27ZDqd
+6upor9MICngXAC1tHjhPuGrGtu4i6FMPrmkofwdh8dkuRzU/OPjf9lA+E9Qu0Nvq
+soI9grJA0etgRfn9juR4X3KTG21qHnza50PpMYC4+vh8jAnIT7Kcz8Ggr4eghkvP
++iz2yEtIcV9M1xeo98XU/jxuYS7LeWtO79jkiqCIqgI8T3x7LHuCaQIDAQABo4Hb
+MIHYMBIGA1UdEwEB/wQIMAYBAf8CAQEwEQYDVR0OBAoECEZwyi8lTsNHMBIGA1Ud
+IAQLMAkwBwYFYIJkZAIwEwYDVR0jBAwwCoAIQrjFz22zV+EwLgYIKwYBBQUHAQEE
+IjAgMB4GCCsGAQUFBzABhhJodHRwOi8vb2N2cy5nb3YuaW4wDgYDVR0PAQH/BAQD
+AgEGMEYGA1UdHwQ/MD0wO6A5oDeGNWh0dHA6Ly9jY2EuZ292LmluL3J3L3Jlc291
+cmNlcy9DQ0FJbmRpYTIwMTRMYXRlc3QuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQCB
+i3iJeUlkfjY96HgfBIUEsLi+knO3VUrxDmwps1YyhgRSt22NQLZ4jksSWLI2EQbn
+9k5tH8rwSbsOWf+TZH7jpaKAVSYi1GhEbGR/C2ZeFiWATwtPWKoVGwx/ksUO9YPM
+zf0wh6fDIuyBJIs/nuN93+L2ib+TS5viNky+HrR3XyqE0z43W5bbzMbido3lbwgr
+drMWD6hCNSZs888L0Se4rn2ei0aPmHmxjDjbExF3NF6m2uYC/wAR4cVIzMvvptFY
+n+SAdG/pwkKHaMVncB/cxxEWiKzOxVpjBsM4N19lpxp2RU/n+x7xRK3WTQvNAZdU
+7pcAYmZIXPu/ES9qpK4f
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/b8686723e415534bc0dbd16326f9486f85b0b0799bf6639334e61daae67f36cd.pem b/chromium/net/data/ssl/blacklist/b8686723e415534bc0dbd16326f9486f85b0b0799bf6639334e61daae67f36cd.pem
new file mode 100644
index 00000000000..7b3c3100099
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/b8686723e415534bc0dbd16326f9486f85b0b0799bf6639334e61daae67f36cd.pem
@@ -0,0 +1,139 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 20001983 (0x13134bf)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden Organisatie CA - G2
+ Validity
+ Not Before: May 12 08:51:38 2010 GMT
+ Not After : Mar 23 09:50:04 2020 GMT
+ Subject: C=NL, O=DigiNotar B.V., CN=DigiNotar PKIoverheid CA Organisatie - G2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:b1:13:19:0f:27:e6:6c:d4:55:86:4b:d0:ec:89:
+ 8a:45:91:78:ac:47:bd:47:2b:e4:fc:45:eb:4f:b4:
+ 26:73:5b:37:d3:c3:7f:f6:e3:de:d7:a3:f8:2d:68:
+ c5:08:3e:4b:94:d6:e4:87:25:36:6b:84:b5:18:74:
+ f3:28:58:73:2f:9b:6a:cf:bc:04:1e:f6:de:dd:af:
+ fc:4b:aa:f5:db:66:62:25:01:25:82:de:f2:97:5a:
+ 10:6e:dd:5d:a9:22:b1:04:a9:23:73:3a:f8:71:ad:
+ 1d:cf:84:44:eb:47:d1:af:6d:c8:7c:28:ab:c7:f2:
+ 37:7a:74:5f:5f:c5:02:14:8a:a3:5a:e3:1b:6c:01:
+ e3:5d:8e:d9:68:d6:f4:09:1b:32:dc:91:b5:2c:f5:
+ 20:eb:8c:03:6d:26:49:b8:93:c4:85:5d:d8:d2:9b:
+ af:56:6a:cc:05:33:cc:a0:42:9e:34:55:44:9c:6b:
+ a0:d4:12:d0:2b:54:cd:b7:89:0d:e5:f6:eb:e8:fb:
+ 85:01:33:4f:7a:6b:f1:9d:72:33:96:0e:f7:b2:84:
+ a5:a5:27:c4:27:f1:51:73:29:77:ba:67:6e:fe:4c:
+ dc:b4:e2:a1:a1:81:2f:39:49:8d:43:38:13:ce:d0:
+ a5:5c:c2:87:3a:00:67:65:42:23:f1:36:59:0a:1d:
+ a3:51:c8:bc:a3:94:2a:31:df:e3:3c:f2:9d:1a:3c:
+ 04:b0:ef:b1:0a:30:13:73:b6:d7:f3:a3:4c:01:75:
+ 14:85:78:c0:d7:8a:39:58:85:50:fa:2e:e6:c5:be:
+ cf:8b:3f:af:8f:36:d4:25:09:2d:d2:0f:ac:72:93:
+ f2:bf:8b:d4:50:b3:f9:15:50:9b:99:f5:14:d9:fb:
+ 8b:91:a3:32:26:26:a0:f8:df:3b:60:81:86:83:79:
+ 5b:2b:eb:13:3d:29:3a:c1:6d:dd:bd:9e:8e:87:d6:
+ 4a:ae:34:97:05:ee:14:a6:f6:dc:38:7e:4a:e9:24:
+ 54:07:3d:97:68:37:46:6b:0d:c7:a8:21:af:13:54:
+ e4:09:6a:f1:4d:46:0a:c9:5d:fb:9b:4f:bd:de:fb:
+ b7:54:cb:b8:38:9c:a7:39:fb:6a:2d:c0:7b:8d:ab:
+ a5:a7:57:ec:4a:92:8a:33:c5:e1:20:5c:73:d8:90:
+ 92:2b:80:d5:0f:86:18:69:7c:39:4f:84:86:bc:f7:
+ 4c:5b:f3:d5:b4:ca:a0:c2:f0:37:22:ca:79:52:1f:
+ 53:e6:aa:f3:90:b0:3b:dd:f2:28:fd:ac:eb:c5:06:
+ 24:a0:c9:d4:2f:0f:58:fd:b5:9e:ec:0f:cf:b2:59:
+ d0:a2:04:7a:38:6a:ae:72:fb:bd:f0:25:62:94:09:
+ a7:05:0b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Certificate Policies:
+ Policy: X509v3 Any Policy
+ CPS: http://www.diginotar.nl/cps/pkioverheid
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Authority Key Identifier:
+ keyid:39:10:8B:49:92:5C:DB:61:12:20:CD:49:9D:1A:8E:DA:9C:67:40:B9
+ DirName:/C=NL/O=Staat der Nederlanden/CN=Staat der Nederlanden Root CA - G2
+ serial:98:96:F4
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.pkioverheid.nl/DomOrganisatieLatestCRL-G2.crl
+
+ X509v3 Subject Key Identifier:
+ BC:5D:94:3B:D9:AB:7B:03:25:73:61:C2:DB:2D:EE:FC:AB:8F:65:A1
+ Signature Algorithm: sha256WithRSAEncryption
+ 8f:fc:2d:4c:b7:d9:2d:d5:1f:bd:ef:cb:f4:b7:68:17:75:9d:
+ 4e:d5:f7:dd:9c:f1:2a:26:ed:9f:a2:b6:1c:03:d5:53:b3:ec:
+ 08:cf:34:e2:e3:c3:f4:b5:16:2f:c8:c3:be:d7:d3:73:ab:00:
+ 36:f9:1a:4a:7e:d6:63:e9:5e:46:ba:a5:b6:8e:15:b7:a3:2a:
+ d8:43:1d:ef:5d:c8:1f:81:85:b3:8b:f7:ff:3c:f4:d9:f4:46:
+ 08:3f:9c:bc:1d:a0:d9:a8:4c:cd:25:52:4e:0a:b1:20:f7:1f:
+ e9:43:d9:54:46:81:13:9a:c0:5e:74:6c:2a:98:32:ea:fc:77:
+ bb:0d:a5:a2:31:98:22:7e:7c:7c:e7:da:a4:ad:ec:b7:2e:1a:
+ 19:71:f8:48:50:da:43:8f:2c:84:dd:c1:40:27:e3:b5:f0:15:
+ 4e:96:d4:f8:5c:e3:86:29:46:2b:d7:3b:07:eb:38:7f:c8:86:
+ 57:97:d3:ef:2a:33:c4:17:50:d5:64:69:6b:2b:6b:45:5e:5d:
+ 2f:17:ca:5a:4e:cf:c3:d7:39:3c:f5:3b:9f:46:b9:9b:e7:0e:
+ 49:97:9d:d6:d5:e3:1b:0f:ea:8f:01:4e:9a:13:94:59:0a:02:
+ 07:48:4b:1a:60:ab:7f:4f:ed:0b:d8:55:0d:68:6f:55:9c:69:
+ 65:15:42:ec:c0:dc:dd:6c:ac:c3:16:ce:0b:1d:56:9b:a4:c4:
+ c4:d2:2e:e0:0f:e2:44:27:2b:50:69:a4:dc:62:e8:8a:21:29:
+ 42:6c:cc:00:3a:96:76:9b:ef:40:c0:a4:5e:77:84:32:6c:26:
+ 2a:39:66:ae:5d:e3:b9:b9:b2:2c:68:1f:1e:9a:90:03:39:f0:
+ aa:b3:a4:cc:49:8b:18:34:e9:37:c9:7b:29:c7:84:7c:6f:44:
+ 15:2f:ec:61:59:04:c9:45:cb:a2:d6:52:a2:7c:7f:29:92:d6:
+ 4a:c5:8b:42:a8:d4:fe:ea:d8:c7:87:23:18:e4:9d:7a:7d:73:
+ 40:52:98:a0:ae:6e:e3:05:3f:05:0f:e0:a5:c6:6d:4d:ed:83:
+ 37:88:9c:c7:f3:dc:42:9a:6a:b6:d7:21:49:36:77:f2:ef:18:
+ 4f:c5:70:d9:9e:e9:de:b7:2b:8b:f4:bc:7e:28:df:0d:40:c9:
+ 85:5c:ae:9d:c5:31:ff:d0:5c:0e:b5:a8:7e:f0:e9:2f:ba:af:
+ 88:ae:e5:b5:d1:58:a5:af:9c:71:a7:29:01:90:83:69:37:82:
+ 05:ba:fc:09:c1:08:6e:8c:78:3b:c3:33:02:80:3f:44:85:08:
+ 1d:df:55:56:08:ad:2c:85:2d:5d:b1:03:e1:ae:aa:74:c5:a4:
+ f3:4e:ba:37:98:7b:82:b9
+-----BEGIN CERTIFICATE-----
+MIIGnDCCBISgAwIBAgIEATE0vzANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJO
+TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMTIwMAYDVQQDDClTdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gT3JnYW5pc2F0aWUgQ0EgLSBHMjAeFw0xMDA1MTIw
+ODUxMzhaFw0yMDAzMjMwOTUwMDRaMFoxCzAJBgNVBAYTAk5MMRcwFQYDVQQKDA5E
+aWdpTm90YXIgQi5WLjEyMDAGA1UEAwwpRGlnaU5vdGFyIFBLSW92ZXJoZWlkIENB
+IE9yZ2FuaXNhdGllIC0gRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQCxExkPJ+Zs1FWGS9DsiYpFkXisR71HK+T8RetPtCZzWzfTw3/2497Xo/gtaMUI
+PkuU1uSHJTZrhLUYdPMoWHMvm2rPvAQe9t7dr/xLqvXbZmIlASWC3vKXWhBu3V2p
+IrEEqSNzOvhxrR3PhETrR9Gvbch8KKvH8jd6dF9fxQIUiqNa4xtsAeNdjtlo1vQJ
+GzLckbUs9SDrjANtJkm4k8SFXdjSm69WaswFM8ygQp40VUSca6DUEtArVM23iQ3l
+9uvo+4UBM096a/GdcjOWDveyhKWlJ8Qn8VFzKXe6Z27+TNy04qGhgS85SY1DOBPO
+0KVcwoc6AGdlQiPxNlkKHaNRyLyjlCox3+M88p0aPASw77EKMBNzttfzo0wBdRSF
+eMDXijlYhVD6LubFvs+LP6+PNtQlCS3SD6xyk/K/i9RQs/kVUJuZ9RTZ+4uRozIm
+JqD43ztggYaDeVsr6xM9KTrBbd29no6H1kquNJcF7hSm9tw4fkrpJFQHPZdoN0Zr
+DceoIa8TVOQJavFNRgrJXfubT73e+7dUy7g4nKc5+2otwHuNq6WnV+xKkoozxeEg
+XHPYkJIrgNUPhhhpfDlPhIa890xb89W0yqDC8DciynlSH1PmqvOQsDvd8ij9rOvF
+BiSgydQvD1j9tZ7sD8+yWdCiBHo4aq5y+73wJWKUCacFCwIDAQABo4IBYTCCAV0w
+SAYDVR0gBEEwPzA9BgRVHSAAMDUwMwYIKwYBBQUHAgEWJ2h0dHA6Ly93d3cuZGln
+aW5vdGFyLm5sL2Nwcy9wa2lvdmVyaGVpZDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBBjCBhQYDVR0jBH4wfIAUORCLSZJc22ESIM1JnRqO2pxnQLmhXqRc
+MFoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4x
+KzApBgNVBAMMIlN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENBIC0gRzKCBACY
+lvQwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2NybC5wa2lvdmVyaGVpZC5ubC9E
+b21PcmdhbmlzYXRpZUxhdGVzdENSTC1HMi5jcmwwHQYDVR0OBBYEFLxdlDvZq3sD
+JXNhwtst7vyrj2WhMA0GCSqGSIb3DQEBCwUAA4ICAQCP/C1Mt9kt1R+978v0t2gX
+dZ1O1ffdnPEqJu2forYcA9VTs+wIzzTi48P0tRYvyMO+19NzqwA2+RpKftZj6V5G
+uqW2jhW3oyrYQx3vXcgfgYWzi/f/PPTZ9EYIP5y8HaDZqEzNJVJOCrEg9x/pQ9lU
+RoETmsBedGwqmDLq/He7DaWiMZgifnx859qkrey3LhoZcfhIUNpDjyyE3cFAJ+O1
+8BVOltT4XOOGKUYr1zsH6zh/yIZXl9PvKjPEF1DVZGlrK2tFXl0vF8paTs/D1zk8
+9TufRrmb5w5Jl53W1eMbD+qPAU6aE5RZCgIHSEsaYKt/T+0L2FUNaG9VnGllFULs
+wNzdbKzDFs4LHVabpMTE0i7gD+JEJytQaaTcYuiKISlCbMwAOpZ2m+9AwKRed4Qy
+bCYqOWauXeO5ubIsaB8empADOfCqs6TMSYsYNOk3yXspx4R8b0QVL+xhWQTJRcui
+1lKifH8pktZKxYtCqNT+6tjHhyMY5J16fXNAUpigrm7jBT8FD+Clxm1N7YM3iJzH
+89xCmmq21yFJNnfy7xhPxXDZnunetyuL9Lx+KN8NQMmFXK6dxTH/0FwOtah+8Okv
+uq+IruW10Vilr5xxpykBkINpN4IFuvwJwQhujHg7wzMCgD9EhQgd31VWCK0shS1d
+sQPhrqp0xaTzTro3mHuCuQ==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/b8c1b957c077ea76e00b0f45bff5ae3acb696f221d2e062164fe37125e5a8d25.pem b/chromium/net/data/ssl/blacklist/b8c1b957c077ea76e00b0f45bff5ae3acb696f221d2e062164fe37125e5a8d25.pem
new file mode 100644
index 00000000000..5e89ba9c3ca
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/b8c1b957c077ea76e00b0f45bff5ae3acb696f221d2e062164fe37125e5a8d25.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEKDCCAxCgAwIBAgIEBydr0TANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTEyMDExMTIyMTE1MFoX
+DTIyMDExMTIyMTEzMVowXTELMAkGA1UEBhMCQkUxHDAaBgNVBAoTE0NlcnRpcG9z
+dCBzLmEuL24udi4xMDAuBgNVBAMTJ0NlcnRpcG9zdCBFLVRydXN0IFByaW1hcnkg
+Tm9ybWFsaXNlZCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANWz
+qlKEeheTIg+4BBjKyfKCKqwVC6dQcbZMJWv3/wGqV1p3Tl4TFA1V8h7xhc2F14Ic
+DNoJK739vJ7+bYlNogIk5lHqN38xRlp7mnazLqBdX+T4mQoHvu6SJhLJe+ddbNCD
+Rw7AjKfReVfACxmcm55DxU6RJc6IK2152XmK1mZOIsMaRU7vyLBiJk4mVFCfDG+z
+a8x8n3/eDw21j8Nr1OHC+7tWUKqMPY8Aizz8SBdq0lrzdW1lgb1GXZ+iYlOuzvOp
+5JErWibDeWbRplNmNRwGcbHumQ7E+1gSrCJGLeIiktvhPL+7/obnkzRzz3hp08ve
++QyyaNrJigpgVMTzVmMCAwEAAaOB8jCB7zASBgNVHRMBAf8ECDAGAQH/AgEBMEUG
+A1UdIAQ+MDwwOgYEVR0gADAyMDAGCCsGAQUFBwIBFiRodHRwczovL3d3dy5jZXJ0
+aXBvc3QuY29tL3Nob3dwb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB8GA1UdIwQYMBaA
+FOWdWTCCR1jMrPoIVDaGezq1BE3wMEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6Ly9j
+ZHAxLnB1YmxpYy10cnVzdC5jb20vQ1JML09tbmlyb290MjAyNS5jcmwwHQYDVR0O
+BBYEFBHyC5bSMziBV1gT/UCkEW9OmfpnMA0GCSqGSIb3DQEBBQUAA4IBAQCDTfzh
+Nhln+aiZBvdDKvxd+/MR+HofOwAlvvV9VDNUH5B8fR+vFME4PgDg60zntgZEYg4F
+U13K53/2U9m4vvBiLpRLBWIxyXaZ8hwsx8rRcKZvORai3BMDOUxqK0XAl5evbxzc
+drpn1ao/fJURK6IBa8jblBrhNynpXChj5+dnNSheflN0mph3QXqNs8jAFxmw45Oq
+guO8tEfGpgvGo4hntsA8lWsxerSrtQlJnV3acoauXRProOdTU2+uLD5dJUHEW2QB
+/4um+9xTBDtyZ55YgTg2aalnbPet0lUjW3SRNYBEaEWDNsH0vToW7sjTSY0gEWrv
+BOUM95u+bb7mIp88
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/be144b56fb1163c49c9a0e6b5a458df6b29f7e6449985960c178a4744624b7bc.pem b/chromium/net/data/ssl/blacklist/be144b56fb1163c49c9a0e6b5a458df6b29f7e6449985960c178a4744624b7bc.pem
new file mode 100644
index 00000000000..bdc880d54cd
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/be144b56fb1163c49c9a0e6b5a458df6b29f7e6449985960c178a4744624b7bc.pem
@@ -0,0 +1,136 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ d8:f3:5f:4e:b7:87:2b:2d:ab:06:92:e3:15:38:2f:b0
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
+ Validity
+ Not Before: Mar 15 00:00:00 2011 GMT
+ Not After : Mar 14 23:59:59 2014 GMT
+ Subject: C=US/postalCode=38477, ST=Florida, L=Tampa/street=Sea Village 10, O=Global Trustee, OU=Global Trustee, OU=Hosted by GTI Group Corporation, OU=PlatinumSSL, CN=global trustee
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:d9:74:f2:aa:41:1d:df:f5:c2:16:43:49:5c:29:
+ bf:b6:89:74:29:bc:9c:8d:0c:46:4f:59:7e:b2:41:
+ 17:66:34:0c:65:89:e1:6c:25:e3:86:0a:9e:22:45:
+ 22:8c:dd:9d:e6:a3:95:de:dc:88:02:55:5c:e3:5b:
+ 91:75:eb:26:69:63:b9:2e:c6:ca:2e:27:df:88:ba:
+ 02:20:6e:fe:b9:0b:29:d7:a7:d6:d7:48:1a:1c:ce:
+ dd:1f:a9:27:0e:62:4f:a1:96:1e:dd:54:3a:34:63:
+ 4a:76:f5:77:7d:59:67:d8:10:d4:b5:0f:3a:43:22:
+ 98:db:f4:09:c4:0a:70:ce:dd:90:d4:2f:ef:74:13:
+ c3:cd:c2:89:39:62:15:9d:e6:74:a8:e8:9b:f0:63:
+ 6e:9c:89:b6:0e:ad:9b:f7:cc:82:e8:e8:2d:b8:0b:
+ da:22:ec:49:85:07:88:99:98:3f:f4:74:a9:09:f7:
+ 81:7c:97:0b:59:99:18:72:8b:db:94:82:2b:a7:e8:
+ aa:6b:97:bf:88:7e:75:b0:8b:45:45:0c:c7:a8:09:
+ ea:1b:41:58:30:3b:5f:78:65:15:34:d2:e4:3c:34:
+ 0d:1d:d8:64:3c:8a:a5:56:49:99:28:2d:4b:f2:cf:
+ cd:d9:6e:49:64:9b:a9:79:90:77:55:a9:08:1b:ad:
+ 1a:74:9e:e0:03:93:0a:09:b7:ad:a7:b4:5c:ef:83:
+ 6c:b7:9a:b4:c6:68:40:80:1d:42:d1:6e:79:9b:a9:
+ 19:21:9a:9c:f9:86:2d:00:d1:34:fe:e0:b6:f9:55:
+ b6:f5:26:c5:95:16:a5:7c:73:9f:0a:29:89:ac:3a:
+ 98:f7:9b:74:67:b7:90:b7:5d:09:23:6a:6a:ed:2c:
+ 10:ee:53:0a:10:f0:16:1f:57:b3:b1:0d:79:91:19:
+ b0:eb:cd:30:3f:a0:14:5f:b3:c6:fd:5c:33:a7:b0:
+ ff:98:b0:55:8c:b9:a5:f2:6f:47:24:49:21:69:cc:
+ 42:a2:51:00:40:85:8c:82:82:ab:32:a5:cb:9a:dc:
+ d0:d9:18:0d:df:19:f4:af:83:0d:c1:3e:31:db:24:
+ 48:b6:75:80:a1:e1:c9:77:64:1e:a7:e5:8b:7f:15:
+ 4d:4b:a7:c2:d0:ed:79:95:5e:91:31:ec:18:ff:4e:
+ 9f:48:14:ea:75:ba:21:ce:29:76:e9:1f:4e:51:87:
+ 2e:b3:cc:04:60:ba:23:1f:1f:65:b2:0a:b8:d5:6e:
+ 8f:4b:42:89:47:a9:81:90:5b:2b:b2:b6:ae:e6:a0:
+ 70:7b:78:90:0a:7a:c5:e5:e7:c5:fb:0a:f6:2f:69:
+ 8c:8c:1f:57:e0:06:99:ff:11:d5:52:32:20:97:27:
+ 98:ee:65
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45
+
+ X509v3 Subject Key Identifier:
+ B7:C3:DE:1A:43:ED:41:97:A9:8F:29:78:9C:03:B9:AC:40:42:00:AC
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6449.1.2.1.3.4
+ CPS: https://secure.comodo.com/CPS
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/UTN-USERFirst-Hardware.crl
+
+ Full Name:
+ URI:http://crl.comodo.net/UTN-USERFirst-Hardware.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://crt.comodoca.com/UTNAddTrustServerCA.crt
+ OCSP - URI:http://ocsp.comodoca.com
+
+ X509v3 Subject Alternative Name:
+ DNS:global trustee
+ Signature Algorithm: sha1WithRSAEncryption
+ 8f:ba:75:ba:39:d4:26:d3:70:0f:c4:b3:02:a7:c5:12:23:71:
+ c9:fe:63:e9:a3:62:78:24:44:4f:d4:b9:11:3e:1f:c7:28:e7:
+ 55:6b:ee:f4:e1:00:91:86:8a:c9:09:6b:9f:2e:a4:45:39:d1:
+ 61:62:5e:93:a5:05:45:78:9f:60:12:2c:f4:6c:65:65:0d:cc:
+ 46:34:8b:28:ba:a0:c6:f4:99:71:64:f3:22:76:ac:4f:f3:62:
+ c9:a7:33:5a:07:1f:3d:c9:86:80:dc:db:04:2f:87:27:e8:bf:
+ 48:44:81:c0:f0:49:23:6e:1f:e5:e4:03:86:24:13:a2:85:62:
+ 7c:58:04:ca:e6:8d:13:72:0a:ba:56:44:a2:0f:bc:fb:a0:3d:
+ 0d:2a:7f:fb:9e:a9:09:3d:b7:5a:d4:8a:8d:e1:25:e8:a4:09:
+ 84:70:ad:12:44:b9:cf:b9:33:7a:ba:5c:e6:4b:a6:bb:05:06:
+ 98:ff:f2:98:52:7b:77:80:27:4a:d9:e2:fa:b9:52:d4:fb:fb:
+ e6:d6:2d:9e:8f:c1:15:44:8d:9b:74:2f:ee:94:5a:4e:d3:c4:
+ 8b:8a:ac:43:9d:73:f6:ae:0c:87:89:ad:87:c9:c9:c7:dd:ba:
+ 14:60:7a:f8:b5:35:9d:c2:8d:c6:96:81:0d:a9:52:8a:29:40:
+ 04:e9:19:b4
+-----BEGIN CERTIFICATE-----
+MIIG3TCCBcWgAwIBAgIRANjzX063hystqwaS4xU4L7AwDQYJKoZIhvcNAQEFBQAw
+gZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtl
+IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMY
+aHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR8wHQYDVQQDExZVVE4tVVNFUkZpcnN0
+LUhhcmR3YXJlMB4XDTExMDMxNTAwMDAwMFoXDTE0MDMxNDIzNTk1OVowgeMxCzAJ
+BgNVBAYTAlVTMQ4wDAYDVQQREwUzODQ3NzEQMA4GA1UECBMHRmxvcmlkYTEOMAwG
+A1UEBxMFVGFtcGExFzAVBgNVBAkTDlNlYSBWaWxsYWdlIDEwMRcwFQYDVQQKEw5H
+bG9iYWwgVHJ1c3RlZTEXMBUGA1UECxMOR2xvYmFsIFRydXN0ZWUxKDAmBgNVBAsT
+H0hvc3RlZCBieSBHVEkgR3JvdXAgQ29ycG9yYXRpb24xFDASBgNVBAsTC1BsYXRp
+bnVtU1NMMRcwFQYDVQQDEw5nbG9iYWwgdHJ1c3RlZTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBANl08qpBHd/1whZDSVwpv7aJdCm8nI0MRk9ZfrJBF2Y0
+DGWJ4Wwl44YKniJFIozdneajld7ciAJVXONbkXXrJmljuS7Gyi4n34i6AiBu/rkL
+Kden1tdIGhzO3R+pJw5iT6GWHt1UOjRjSnb1d31ZZ9gQ1LUPOkMimNv0CcQKcM7d
+kNQv73QTw83CiTliFZ3mdKjom/BjbpyJtg6tm/fMgujoLbgL2iLsSYUHiJmYP/R0
+qQn3gXyXC1mZGHKL25SCK6foqmuXv4h+dbCLRUUMx6gJ6htBWDA7X3hlFTTS5Dw0
+DR3YZDyKpVZJmSgtS/LPzdluSWSbqXmQd1WpCButGnSe4AOTCgm3rae0XO+DbLea
+tMZoQIAdQtFueZupGSGanPmGLQDRNP7gtvlVtvUmxZUWpXxznwopiaw6mPebdGe3
+kLddCSNqau0sEO5TChDwFh9Xs7ENeZEZsOvNMD+gFF+zxv1cM6ew/5iwVYy5pfJv
+RyRJIWnMQqJRAECFjIKCqzKly5rc0NkYDd8Z9K+DDcE+MdskSLZ1gKHhyXdkHqfl
+i38VTUunwtDteZVekTHsGP9On0gU6nW6Ic4pdukfTlGHLrPMBGC6Ix8fZbIKuNVu
+j0tCiUepgZBbK7K2ruagcHt4kAp6xeXnxfsK9i9pjIwfV+AGmf8R1VIyIJcnmO5l
+AgMBAAGjggHUMIIB0DAfBgNVHSMEGDAWgBShcl8mGyiYQ5VdBzfVhZadS9LDRTAd
+BgNVHQ4EFgQUt8PeGkPtQZepjyl4nAO5rEBCAKwwDgYDVR0PAQH/BAQDAgWgMAwG
+A1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMEYGA1Ud
+IAQ/MD0wOwYMKwYBBAGyMQECAQMEMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2Vj
+dXJlLmNvbW9kby5jb20vQ1BTMHsGA1UdHwR0MHIwOKA2oDSGMmh0dHA6Ly9jcmwu
+Y29tb2RvY2EuY29tL1VUTi1VU0VSRmlyc3QtSGFyZHdhcmUuY3JsMDagNKAyhjBo
+dHRwOi8vY3JsLmNvbW9kby5uZXQvVVROLVVTRVJGaXJzdC1IYXJkd2FyZS5jcmww
+cQYIKwYBBQUHAQEEZTBjMDsGCCsGAQUFBzAChi9odHRwOi8vY3J0LmNvbW9kb2Nh
+LmNvbS9VVE5BZGRUcnVzdFNlcnZlckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDov
+L29jc3AuY29tb2RvY2EuY29tMBkGA1UdEQQSMBCCDmdsb2JhbCB0cnVzdGVlMA0G
+CSqGSIb3DQEBBQUAA4IBAQCPunW6OdQm03APxLMCp8USI3HJ/mPpo2J4JERP1LkR
+Ph/HKOdVa+704QCRhorJCWufLqRFOdFhYl6TpQVFeJ9gEiz0bGVlDcxGNIsouqDG
+9JlxZPMidqxP82LJpzNaBx89yYaA3NsEL4cn6L9IRIHA8Ekjbh/l5AOGJBOihWJ8
+WATK5o0Tcgq6VkSiD7z7oD0NKn/7nqkJPbda1IqN4SXopAmEcK0SRLnPuTN6ulzm
+S6a7BQaY//KYUnt3gCdK2eL6uVLU+/vm1i2ej8EVRI2bdC/ulFpO08SLiqxDnXP2
+rgyHia2HycnH3boUYHr4tTWdwo3GloENqVKKKUAE6Rm0
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/c4387d45364a313fbfe79812b35b815d42852ab03b06f11589638021c8f2cb44.key b/chromium/net/data/ssl/blacklist/c4387d45364a313fbfe79812b35b815d42852ab03b06f11589638021c8f2cb44.key
new file mode 100644
index 00000000000..1bf5f199c3b
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/c4387d45364a313fbfe79812b35b815d42852ab03b06f11589638021c8f2cb44.key
@@ -0,0 +1,6 @@
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1n+PVzIS7k8GOESR6SJ/sPSWd
+rIlBox8FpX41+lLAvUojxzwJrnoqvuCIFgfoZ/ZdyPTaTcxeqj5LNtNvA6L1vpoX
+4c1Sfpfj+/zqKupo424YsP6CDyJgS1MF9CFUa3/fhd4epL2YowYqbE4vGk4O2XPS
+mBNbAQSJwdED4lxMywIDAQAB
+-----END PUBLIC KEY-----
diff --git a/chromium/net/data/ssl/blacklist/c67d722c1495be02cbf9ef1159f5ca4aa782dc832dc6aa60c9aa076a0ad1e69d.pem b/chromium/net/data/ssl/blacklist/c67d722c1495be02cbf9ef1159f5ca4aa782dc832dc6aa60c9aa076a0ad1e69d.pem
new file mode 100644
index 00000000000..a736bfcb354
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/c67d722c1495be02cbf9ef1159f5ca4aa782dc832dc6aa60c9aa076a0ad1e69d.pem
@@ -0,0 +1,108 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 0f:d5:25:b4:33:e5:e1:75:5f:49:2a:90:3a:f7:62:c1
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Domain Validation Secure Server CA
+ Validity
+ Not Before: Jan 26 00:00:00 2015 GMT
+ Not After : Apr 26 23:59:59 2015 GMT
+ Subject: OU=Domain Control Validated, OU=Free SSL, CN=www.live.fi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c3:b8:25:3f:1c:ef:17:74:f4:21:2d:9b:f9:c4:
+ 93:cf:82:50:78:dd:d6:5d:55:3f:c0:aa:44:9e:29:
+ e9:a4:02:34:2e:10:4e:55:f9:6d:17:f0:ea:7f:c8:
+ 1f:d3:28:7f:59:f9:a3:e5:a1:eb:60:dd:46:6a:66:
+ 05:fd:4c:21:de:8d:2f:ed:77:87:d8:71:27:e9:f5:
+ d8:5f:08:af:40:0c:74:87:1a:d9:16:52:b4:b8:86:
+ 6d:25:4f:26:95:9f:db:19:9e:16:4e:1e:b7:a1:31:
+ bd:f1:92:5a:1e:e2:63:97:9b:17:79:b7:d5:57:08:
+ 5b:71:fb:9a:4e:94:33:29:c5:ae:d8:8d:9d:b3:cd:
+ 5a:05:8e:d4:f2:b9:38:c9:03:ec:94:3c:1e:0a:fb:
+ 51:d1:d2:5b:9b:82:d2:0b:02:ac:ba:8d:8d:d0:8c:
+ b7:b2:8c:41:de:31:d3:09:20:1d:15:f3:34:87:41:
+ 6d:6a:9d:9d:02:98:c0:c3:7d:26:86:6e:57:c3:b3:
+ 3a:4a:c4:00:ec:a3:ae:c5:12:ad:d9:fa:a8:8c:6a:
+ e8:ee:c9:d6:78:cd:b9:e8:f3:22:61:70:34:fd:d6:
+ 7a:c7:56:b4:23:34:f4:d1:d3:36:2e:6a:5b:36:c6:
+ 43:d4:ab:8b:7a:b4:49:4c:39:d7:e7:e5:c2:4b:df:
+ 22:97
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:90:AF:6A:3A:94:5A:0B:D8:90:EA:12:56:73:DF:43:B4:3A:28:DA:E7
+
+ X509v3 Subject Key Identifier:
+ D6:BE:93:22:2B:5E:8E:50:7A:A5:11:05:5D:28:E9:2E:AA:72:E8:8B
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6449.1.2.2.7
+ CPS: https://secure.comodo.com/CPS
+ Policy: 2.23.140.1.2.1
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/COMODORSADomainValidationSecureServerCA.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://crt.comodoca.com/COMODORSADomainValidationSecureServerCA.crt
+ OCSP - URI:http://ocsp.comodoca.com
+
+ X509v3 Subject Alternative Name:
+ DNS:www.live.fi, DNS:live.fi
+ Signature Algorithm: sha256WithRSAEncryption
+ 5c:91:36:dc:9b:a6:b4:90:51:db:6b:6d:71:26:6f:83:8c:7f:
+ 32:01:75:6c:3a:a6:9c:b2:34:0f:14:fe:4a:b9:98:ac:af:a0:
+ b7:82:d9:82:ea:7b:0f:78:66:1a:20:74:8c:6a:cc:79:ab:a0:
+ b8:05:96:64:ba:64:3c:cd:e1:77:d3:db:44:6e:e8:de:50:04:
+ 1d:7a:8c:ae:f9:e7:7d:40:41:0b:dc:25:84:ee:0c:a4:61:16:
+ 6b:63:48:32:42:7d:82:0f:94:9c:73:62:24:b5:f1:5e:7d:f6:
+ c8:de:1e:73:8f:97:42:5f:f5:9b:3a:c2:02:1f:06:8a:01:15:
+ 9d:d5:52:f3:5e:c0:2b:dd:b7:ec:5f:fe:74:68:30:39:b1:29:
+ b3:02:2d:bd:ed:a2:d0:2a:bc:86:f2:59:f9:fb:d0:6a:89:fb:
+ 34:eb:56:85:2e:39:8f:69:53:ae:98:64:b7:ce:d5:02:3f:d4:
+ 78:04:ae:73:9d:f5:3b:03:40:b5:dd:56:58:be:05:31:c1:eb:
+ 11:4e:78:c6:27:06:9e:47:23:3d:e9:e2:6d:b5:b3:d5:47:d1:
+ 88:96:51:18:26:21:ca:26:3d:7d:ea:6e:b0:83:7c:b8:1d:eb:
+ d1:59:3f:6e:4a:3a:7c:05:15:76:f7:d3:59:fd:ea:8d:3d:30:
+ 1c:13:af:bc
+-----BEGIN CERTIFICATE-----
+MIIFOjCCBCKgAwIBAgIQD9UltDPl4XVfSSqQOvdiwTANBgkqhkiG9w0BAQsFADCB
+kDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxNjA0BgNV
+BAMTLUNPTU9ETyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD
+QTAeFw0xNTAxMjYwMDAwMDBaFw0xNTA0MjYyMzU5NTlaMEwxITAfBgNVBAsTGERv
+bWFpbiBDb250cm9sIFZhbGlkYXRlZDERMA8GA1UECxMIRnJlZSBTU0wxFDASBgNV
+BAMTC3d3dy5saXZlLmZpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+w7glPxzvF3T0IS2b+cSTz4JQeN3WXVU/wKpEninppAI0LhBOVfltF/Dqf8gf0yh/
+Wfmj5aHrYN1GamYF/Uwh3o0v7XeH2HEn6fXYXwivQAx0hxrZFlK0uIZtJU8mlZ/b
+GZ4WTh63oTG98ZJaHuJjl5sXebfVVwhbcfuaTpQzKcWu2I2ds81aBY7U8rk4yQPs
+lDweCvtR0dJbm4LSCwKsuo2N0Iy3soxB3jHTCSAdFfM0h0Ftap2dApjAw30mhm5X
+w7M6SsQA7KOuxRKt2fqojGro7snWeM256PMiYXA0/dZ6x1a0IzT00dM2LmpbNsZD
+1KuLerRJTDnX5+XCS98ilwIDAQABo4IB0TCCAc0wHwYDVR0jBBgwFoAUkK9qOpRa
+C9iQ6hJWc99DtDoo2ucwHQYDVR0OBBYEFNa+kyIrXo5QeqURBV0o6S6qcuiLMA4G
+A1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMB
+BggrBgEFBQcDAjBPBgNVHSAESDBGMDoGCysGAQQBsjEBAgIHMCswKQYIKwYBBQUH
+AgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMAgGBmeBDAECATBUBgNV
+HR8ETTBLMEmgR6BFhkNodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9SU0FE
+b21haW5WYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3JsMIGFBggrBgEFBQcBAQR5
+MHcwTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET1JT
+QURvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5jcnQwJAYIKwYBBQUHMAGG
+GGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAfBgNVHREEGDAWggt3d3cubGl2ZS5m
+aYIHbGl2ZS5maTANBgkqhkiG9w0BAQsFAAOCAQEAXJE23JumtJBR22ttcSZvg4x/
+MgF1bDqmnLI0DxT+SrmYrK+gt4LZgup7D3hmGiB0jGrMeauguAWWZLpkPM3hd9Pb
+RG7o3lAEHXqMrvnnfUBBC9wlhO4MpGEWa2NIMkJ9gg+UnHNiJLXxXn32yN4ec4+X
+Ql/1mzrCAh8GigEVndVS817AK9237F/+dGgwObEpswItve2i0Cq8hvJZ+fvQaon7
+NOtWhS45j2lTrphkt87VAj/UeASuc531OwNAtd1WWL4FMcHrEU54xicGnkcjPeni
+bbWz1UfRiJZRGCYhyiY9fepusIN8uB3r0Vk/bko6fAUVdvfTWf3qjT0wHBOvvA==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/e4f9a3235df7330255f36412bc849fb630f8519961ec3538301deb896c953da5.pem b/chromium/net/data/ssl/blacklist/e4f9a3235df7330255f36412bc849fb630f8519961ec3538301deb896c953da5.pem
new file mode 100644
index 00000000000..1fad80a0faa
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/e4f9a3235df7330255f36412bc849fb630f8519961ec3538301deb896c953da5.pem
@@ -0,0 +1,89 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 10115 (0x2783)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=IN, O=India PKI, CN=CCA India 2007
+ Validity
+ Not Before: Jul 2 06:41:59 2007 GMT
+ Not After : Jul 4 06:30:00 2015 GMT
+ Subject: C=IN, O=National Informatics Centre, OU=NICCA, CN=NIC Certifying Authority, L=New Delhi/emailAddress=support@camail.nic.in, ST=Delhi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c0:b4:4a:0c:45:96:0b:58:96:73:1a:55:80:0e:
+ c6:24:48:d0:56:31:88:33:1f:57:3c:ba:1a:30:a5:
+ e2:11:07:5a:8c:78:26:8c:a7:4e:86:51:64:49:68:
+ 87:82:20:92:52:8d:fd:53:4f:d4:a0:2e:2b:01:8c:
+ c1:09:c7:c7:59:d0:06:8d:73:6c:ed:db:7f:73:3f:
+ a6:b8:ad:9a:32:83:e8:02:05:d6:2c:5d:80:e3:c0:
+ 89:32:b4:dc:c8:d1:44:1e:bc:88:60:97:82:88:af:
+ 03:4e:51:21:07:12:fc:20:8f:55:07:1f:2a:29:2a:
+ ae:8b:38:78:31:04:e6:a6:ab:df:8c:73:6a:77:aa:
+ 82:1c:5e:aa:f1:6e:37:f6:2a:39:91:52:05:9c:63:
+ 5d:fe:9d:15:e4:71:6f:d0:ea:56:78:5f:c8:a4:a2:
+ 40:d6:6d:65:6f:bd:bd:17:07:ec:56:9a:a2:a5:fe:
+ c3:2d:54:14:2a:d4:a3:2b:fd:f6:44:3b:41:86:70:
+ 26:90:39:56:e8:86:51:3e:cd:85:f3:de:80:e4:23:
+ 8f:48:38:c9:94:07:94:5f:c2:6a:0e:70:4e:af:ae:
+ 1b:3d:18:14:cb:45:43:9d:6f:ec:a1:10:77:92:79:
+ 27:e7:0e:6e:79:78:f7:0e:b8:0e:36:d8:c6:70:14:
+ b0:57
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 4C:27:7B:6E:0D:B2:FF:54
+ X509v3 Authority Key Identifier:
+ keyid:4F:1E:C0:58:27:D8:B8:E4
+
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:ldap://nrdc.cca.gov.in:389/cn=CCA India 2007,ou=CCA India 2007,o=India PKI,c=IN?certificaterevocationlist;binary?
+
+ Signature Algorithm: sha1WithRSAEncryption
+ ac:7a:46:45:60:30:64:00:0e:09:78:8d:3c:b7:a8:10:ea:f2:
+ 7b:e4:7a:00:da:0e:7b:e2:4d:4b:06:ce:c4:7a:46:9a:28:4f:
+ 4c:5d:c2:e2:a2:45:4d:08:ee:9d:a0:02:8e:ae:05:33:04:66:
+ d4:be:5d:62:73:fb:bc:65:7e:8e:1f:6a:8e:57:21:4e:1e:d5:
+ fc:64:42:ec:5d:74:cd:b7:fc:9e:cc:e3:e5:33:de:92:fb:ce:
+ 22:b9:45:c5:62:ce:14:2a:cf:72:23:48:7e:38:d3:f3:a8:16:
+ 15:01:4f:97:79:59:63:74:86:58:84:72:be:fe:ea:72:cf:00:
+ e7:00:5f:fa:91:e7:4f:5a:0e:37:7f:6a:89:df:c9:01:42:33:
+ 27:e2:3e:96:0b:c7:91:25:4e:ea:94:65:e1:c0:a4:9e:7c:f8:
+ 8a:6b:c1:bb:b7:10:8b:b1:f8:2f:a6:7d:2f:10:08:c6:3e:59:
+ 88:de:6a:87:02:23:02:2e:b6:b9:a8:c4:85:f1:1b:2f:72:57:
+ 93:8a:21:ed:be:e3:0b:02:4f:c6:8d:8a:7f:ba:01:5e:ea:35:
+ 39:85:56:1a:7e:30:5e:74:bf:af:4e:35:33:bb:c3:64:9a:fa:
+ 2a:de:d8:de:45:82:49:4c:5b:65:93:0a:2f:1d:f2:bc:0b:cd:
+ a5:ae:b1:ee
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgICJ4MwDQYJKoZIhvcNAQEFBQAwOjELMAkGA1UEBhMCSU4x
+EjAQBgNVBAoTCUluZGlhIFBLSTEXMBUGA1UEAxMOQ0NBIEluZGlhIDIwMDcwHhcN
+MDcwNzAyMDY0MTU5WhcNMTUwNzA0MDYzMDAwWjCBsDELMAkGA1UEBhMCSU4xJDAi
+BgNVBAoTG05hdGlvbmFsIEluZm9ybWF0aWNzIENlbnRyZTEOMAwGA1UECxMFTklD
+Q0ExITAfBgNVBAMTGE5JQyBDZXJ0aWZ5aW5nIEF1dGhvcml0eTESMBAGA1UEBxMJ
+TmV3IERlbGhpMSQwIgYJKoZIhvcNAQkBFhVzdXBwb3J0QGNhbWFpbC5uaWMuaW4x
+DjAMBgNVBAgTBURlbGhpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+wLRKDEWWC1iWcxpVgA7GJEjQVjGIMx9XPLoaMKXiEQdajHgmjKdOhlFkSWiHgiCS
+Uo39U0/UoC4rAYzBCcfHWdAGjXNs7dt/cz+muK2aMoPoAgXWLF2A48CJMrTcyNFE
+HryIYJeCiK8DTlEhBxL8II9VBx8qKSquizh4MQTmpqvfjHNqd6qCHF6q8W439io5
+kVIFnGNd/p0V5HFv0OpWeF/IpKJA1m1lb729FwfsVpqipf7DLVQUKtSjK/32RDtB
+hnAmkDlW6IZRPs2F896A5COPSDjJlAeUX8JqDnBOr64bPRgUy0VDnW/soRB3knkn
+5w5ueXj3DrgONtjGcBSwVwIDAQABo4HOMIHLMA8GA1UdEwEB/wQFMAMBAf8wEQYD
+VR0OBAoECEwne24Nsv9UMBMGA1UdIwQMMAqACE8ewFgn2LjkMAsGA1UdDwQEAwIB
+BjCBggYDVR0fBHsweTB3oHWgc4ZxbGRhcDovL25yZGMuY2NhLmdvdi5pbjozODkv
+Y249Q0NBIEluZGlhIDIwMDcsb3U9Q0NBIEluZGlhIDIwMDcsbz1JbmRpYSBQS0ks
+Yz1JTj9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0O2JpbmFyeT8wDQYJKoZIhvcN
+AQEFBQADggEBAKx6RkVgMGQADgl4jTy3qBDq8nvkegDaDnviTUsGzsR6RpooT0xd
+wuKiRU0I7p2gAo6uBTMEZtS+XWJz+7xlfo4fao5XIU4e1fxkQuxddM23/J7M4+Uz
+3pL7ziK5RcVizhQqz3IjSH440/OoFhUBT5d5WWN0hliEcr7+6nLPAOcAX/qR509a
+Djd/aonfyQFCMyfiPpYLx5ElTuqUZeHApJ58+Iprwbu3EIux+C+mfS8QCMY+WYje
+aocCIwIutrmoxIXxGy9yV5OKIe2+4wsCT8aNin+6AV7qNTmFVhp+MF50v69ONTO7
+w2Sa+ire2N5FgklMW2WTCi8d8rwLzaWuse4=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/ea08c8d45d52ca593de524f0513ca6418da9859f7b08ef13ff9dd7bf612d6a37.key b/chromium/net/data/ssl/blacklist/ea08c8d45d52ca593de524f0513ca6418da9859f7b08ef13ff9dd7bf612d6a37.key
new file mode 100644
index 00000000000..126cd6b6db1
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/ea08c8d45d52ca593de524f0513ca6418da9859f7b08ef13ff9dd7bf612d6a37.key
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAseh+Sv8HYOKWgE5Zbz44
+esmvXCzee8QDFlY2Fcw4rtR3eLbr9+4LLZ6FKrxngpgpIrHZMOxCVQkRMpAlriqd
+SJXd8o5GAFEvUcyw62fSL9OLclPOgnBlgdWc/s72qzdIW1l3El8uWjSkDDVP3LIH
+/rz0Pm/yR9TeV/JiZm3MVQjl5ZDA7YdK5hOtEaqz1IRcERxkN5nNGfDkZCQyWY06
+uhOtWDVxno8Y/aEo0+mxy3umMOASypoi1llxUh7BcdWNdDUzYFJ/69kO7z/Uky18
+EFyuvwcfhBU5zhWZMGMNhpLVgr7OCKFIbEMgY1LChnUIUTxhI1MntSY7a/9UJhDt
+0wIDAQAB
+-----END PUBLIC KEY-----
diff --git a/chromium/net/data/ssl/blacklist/ead610e6e90b439f2ecb51628b0932620f6ef340bd843fca38d3181b8f4ba197.pem b/chromium/net/data/ssl/blacklist/ead610e6e90b439f2ecb51628b0932620f6ef340bd843fca38d3181b8f4ba197.pem
new file mode 100644
index 00000000000..e7a98f6ea51
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/ead610e6e90b439f2ecb51628b0932620f6ef340bd843fca38d3181b8f4ba197.pem
@@ -0,0 +1,114 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ e9:02:8b:95:78:e4:15:dc:1a:71:0a:2b:88:15:44:47
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
+ Validity
+ Not Before: Mar 15 00:00:00 2011 GMT
+ Not After : Mar 14 23:59:59 2014 GMT
+ Subject: C=US/postalCode=38477, ST=Florida, L=English/street=Sea Village 10, O=Google Ltd., OU=Tech Dept., OU=Hosted by GTI Group Corporation, OU=PlatinumSSL, CN=login.skype.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:b0:78:99:86:0e:a2:73:23:d4:5a:c3:49:eb:b1:
+ 36:8c:7c:ca:84:ae:3c:af:38:88:28:99:8d:2d:58:
+ 13:b1:97:78:3e:52:20:67:ac:5b:73:98:6c:32:55:
+ c9:70:d1:d9:aa:15:e8:2e:26:85:81:bc:56:e4:bc:
+ 80:63:db:4e:d7:f5:02:be:51:63:1e:3c:db:df:d7:
+ 00:5d:5a:b9:e5:7b:6a:ea:38:20:b2:3b:b6:ee:75:
+ 54:84:f9:a6:ca:38:70:dd:bf:b0:ff:a5:85:5d:b4:
+ 41:fe:dd:3d:d9:2a:e1:30:43:1a:98:79:93:a0:5f:
+ e0:67:6c:95:fa:3e:7a:ae:71:7b:e3:6d:88:42:3f:
+ 25:d4:ee:be:68:68:ac:ad:ac:60:e0:20:a3:39:83:
+ b9:5b:28:a3:93:6d:a1:bd:76:0a:e3:eb:ae:87:27:
+ 0e:54:8f:b4:48:0c:9a:54:f4:5d:8e:37:50:dc:5e:
+ a4:8b:6b:4b:dc:a6:f3:34:be:77:59:22:88:ff:19:
+ 2b:6d:76:64:73:da:0c:87:07:2b:9a:37:3a:d0:e2:
+ 8c:f6:36:32:6b:9a:79:cc:d2:3b:93:6f:1a:4d:6c:
+ e6:c1:9d:40:ac:2d:74:c3:be:ea:5c:73:65:01:29:
+ b1:2a:bf:70:59:c1:ce:c6:c3:a2:c8:45:5f:ba:67:
+ 3d:0f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45
+
+ X509v3 Subject Key Identifier:
+ D5:8E:5A:51:13:B4:29:0D:31:B6:1C:8D:3E:51:51:31:0A:33:AA:81
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6449.1.2.1.3.4
+ CPS: https://secure.comodo.com/CPS
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/UTN-USERFirst-Hardware.crl
+
+ Full Name:
+ URI:http://crl.comodo.net/UTN-USERFirst-Hardware.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://crt.comodoca.com/UTNAddTrustServerCA.crt
+ OCSP - URI:http://ocsp.comodoca.com
+
+ X509v3 Subject Alternative Name:
+ DNS:login.skype.com, DNS:www.login.skype.com
+ Signature Algorithm: sha1WithRSAEncryption
+ 08:f2:81:75:91:bb:ce:12:04:18:c2:4d:5a:fb:46:90:0a:54:
+ 44:f4:f2:dd:07:81:f0:1f:a6:7a:6f:9f:cf:b8:0e:2c:4f:9c:
+ c4:9a:f5:a8:f6:ba:a4:c9:7a:5d:b1:e2:5a:ca:3c:fa:60:a8:
+ 68:3e:cb:ba:2d:e2:cd:d6:b6:e4:92:3c:69:ad:57:ea:a8:2f:
+ 38:10:84:72:e5:68:71:ed:be:eb:6e:18:ef:63:7a:be:e7:24:
+ ff:c0:63:fd:58:3b:4c:81:92:d8:29:ab:8e:35:5d:d7:d3:09:
+ 6b:85:d3:d5:73:05:44:e2:e5:bb:83:53:10:cb:f2:cf:b7:6e:
+ e1:69:b7:a1:92:64:c5:cf:cd:82:bb:36:a0:38:ad:d7:24:df:
+ 53:fc:3f:62:b7:b7:d5:c7:57:e3:93:31:70:8e:24:89:86:ca:
+ 63:2b:39:ba:5d:d9:6a:60:ec:a1:4e:8a:fe:53:f8:5e:92:df:
+ 2f:5c:26:17:6d:03:7d:02:0f:0f:aa:43:67:6d:b0:62:bf:7e:
+ 53:dd:cc:ec:78:73:95:e5:a5:f6:00:a3:04:fd:3f:04:2a:b3:
+ 98:c5:b7:03:1c:db:c9:50:ab:b0:05:1d:1e:be:56:b4:cf:3e:
+ 42:13:94:9e:f9:e7:01:81:a5:78:6f:0c:7a:76:ac:05:86:ec:
+ ac:c2:11:ac
+-----BEGIN CERTIFICATE-----
+MIIF7zCCBNegAwIBAgIRAOkCi5V45BXcGnEKK4gVREcwDQYJKoZIhvcNAQEFBQAw
+gZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtl
+IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMY
+aHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR8wHQYDVQQDExZVVE4tVVNFUkZpcnN0
+LUhhcmR3YXJlMB4XDTExMDMxNTAwMDAwMFoXDTE0MDMxNDIzNTk1OVowgd8xCzAJ
+BgNVBAYTAlVTMQ4wDAYDVQQREwUzODQ3NzEQMA4GA1UECBMHRmxvcmlkYTEQMA4G
+A1UEBxMHRW5nbGlzaDEXMBUGA1UECRMOU2VhIFZpbGxhZ2UgMTAxFDASBgNVBAoT
+C0dvb2dsZSBMdGQuMRMwEQYDVQQLEwpUZWNoIERlcHQuMSgwJgYDVQQLEx9Ib3N0
+ZWQgYnkgR1RJIEdyb3VwIENvcnBvcmF0aW9uMRQwEgYDVQQLEwtQbGF0aW51bVNT
+TDEYMBYGA1UEAxMPbG9naW4uc2t5cGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAsHiZhg6icyPUWsNJ67E2jHzKhK48rziIKJmNLVgTsZd4PlIg
+Z6xbc5hsMlXJcNHZqhXoLiaFgbxW5LyAY9tO1/UCvlFjHjzb39cAXVq55Xtq6jgg
+sju27nVUhPmmyjhw3b+w/6WFXbRB/t092SrhMEMamHmToF/gZ2yV+j56rnF7422I
+Qj8l1O6+aGisraxg4CCjOYO5Wyijk22hvXYK4+uuhycOVI+0SAyaVPRdjjdQ3F6k
+i2tL3KbzNL53WSKI/xkrbXZkc9oMhwcrmjc60OKM9jYya5p5zNI7k28aTWzmwZ1A
+rC10w77qXHNlASmxKr9wWcHOxsOiyEVfumc9DwIDAQABo4IB6jCCAeYwHwYDVR0j
+BBgwFoAUoXJfJhsomEOVXQc31YWWnUvSw0UwHQYDVR0OBBYEFNWOWlETtCkNMbYc
+jT5RUTEKM6qBMA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQW
+MBQGCCsGAQUFBwMBBggrBgEFBQcDAjBGBgNVHSAEPzA9MDsGDCsGAQQBsjEBAgED
+BDArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQUzB7
+BgNVHR8EdDByMDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9VVE4tVVNF
+UkZpcnN0LUhhcmR3YXJlLmNybDA2oDSgMoYwaHR0cDovL2NybC5jb21vZG8ubmV0
+L1VUTi1VU0VSRmlyc3QtSGFyZHdhcmUuY3JsMHEGCCsGAQUFBwEBBGUwYzA7Bggr
+BgEFBQcwAoYvaHR0cDovL2NydC5jb21vZG9jYS5jb20vVVROQWRkVHJ1c3RTZXJ2
+ZXJDQS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAv
+BgNVHREEKDAmgg9sb2dpbi5za3lwZS5jb22CE3d3dy5sb2dpbi5za3lwZS5jb20w
+DQYJKoZIhvcNAQEFBQADggEBAAjygXWRu84SBBjCTVr7RpAKVET08t0HgfAfpnpv
+n8+4DixPnMSa9aj2uqTJel2x4lrKPPpgqGg+y7ot4s3WtuSSPGmtV+qoLzgQhHLl
+aHHtvutuGO9jer7nJP/AY/1YO0yBktgpq441XdfTCWuF09VzBUTi5buDUxDL8s+3
+buFpt6GSZMXPzYK7NqA4rdck31P8P2K3t9XHV+OTMXCOJImGymMrObpd2Wpg7KFO
+iv5T+F6S3y9cJhdtA30CDw+qQ2dtsGK/flPdzOx4c5XlpfYAowT9PwQqs5jFtwMc
+28lQq7AFHR6+VrTPPkITlJ755wGBpXhvDHp2rAWG7KzCEaw=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/ec30c9c3065a06bb07dc5b1c6b497f370c1ca65c0f30c08e042ba6bcecc78f2c.pem b/chromium/net/data/ssl/blacklist/ec30c9c3065a06bb07dc5b1c6b497f370c1ca65c0f30c08e042ba6bcecc78f2c.pem
new file mode 100644
index 00000000000..c62a3a771fe
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/ec30c9c3065a06bb07dc5b1c6b497f370c1ca65c0f30c08e042ba6bcecc78f2c.pem
@@ -0,0 +1,71 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 6b:c5:7b:95:18:93:aa:97:4b:62:4a:c0:88:fc:3b:b6
+ Signature Algorithm: sha1WithRSA
+ Issuer: CN=eDellRoot
+ Validity
+ Not Before: Apr 7 10:23:27 2015 GMT
+ Not After : Dec 31 23:59:59 2039 GMT
+ Subject: CN=eDellRoot
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:bd:d1:26:0d:6e:cd:5b:84:5f:41:f0:e1:75:86:
+ ce:ce:a8:23:d5:be:a3:b1:d9:75:57:41:30:c5:5b:
+ e0:6c:db:e2:e6:63:09:33:63:6c:fc:78:6f:c2:cd:
+ 14:bd:6e:02:b5:2d:fb:95:55:31:00:ec:39:36:37:
+ 2e:0f:d7:7b:f5:0d:ba:46:36:6f:ed:25:95:43:b3:
+ cc:16:18:a5:bb:05:71:ca:38:9f:a4:ac:4e:f0:e1:
+ 36:2e:6d:fa:43:e8:ed:cd:b7:66:b6:01:3e:63:ae:
+ f3:67:84:27:a7:1a:be:cf:ed:df:db:be:c0:53:a4:
+ 5d:7c:2f:44:28:87:03:f9:56:c8:d5:8d:10:f8:75:
+ ef:e6:c2:10:fd:ea:e4:df:89:ad:5f:ba:1e:8d:f3:
+ 40:f1:2f:e5:05:09:61:d9:97:b0:c9:83:d8:23:10:
+ a2:37:90:52:3e:bc:27:dd:4f:e7:0e:41:2a:3b:ab:
+ 1b:4c:63:8a:fc:e1:4a:88:9e:f7:29:bb:55:1c:0b:
+ 16:35:92:71:1b:b0:ff:d5:d5:e8:22:ea:4f:22:f9:
+ c6:ba:a2:88:3a:75:b9:33:ae:a8:d8:f7:bb:1c:ad:
+ b3:da:1c:6e:ca:09:5e:ec:63:e6:21:18:91:23:35:
+ 9e:f2:ee:a4:4b:fe:96:0c:bd:5a:ac:c8:10:53:26:
+ d6:5f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ 2.5.29.1:
+ 0<..`...3...\f..k.Y...0.1.0...U....eDellRoot..k.{.....KbJ...;.
+ Signature Algorithm: sha1WithRSA
+ 2b:7d:d7:12:72:c7:b3:8f:ca:28:27:dd:94:c3:09:cf:82:0d:
+ fa:9e:83:a0:89:4b:39:5f:33:cb:3f:88:74:26:95:18:41:52:
+ 81:f6:16:35:59:30:f0:45:47:d3:28:68:7b:a0:d3:a8:c1:dd:
+ 36:ed:af:eb:55:26:ff:4c:d7:a8:88:92:2f:30:a9:f8:81:bb:
+ d5:09:60:22:1e:13:bc:bb:6b:b4:46:41:c2:0d:5b:1a:ed:ed:
+ 22:e2:77:29:b9:e5:ac:8a:18:e7:ea:30:6b:63:c4:fe:ed:e0:
+ d8:c2:21:53:fc:5d:37:03:c3:49:ee:62:b9:95:90:3c:48:57:
+ 79:09:30:f2:dc:40:54:53:95:30:cd:75:1c:e4:7a:08:45:4c:
+ 57:48:fc:9c:bb:76:88:05:66:b0:83:7b:02:74:a8:80:a2:29:
+ 12:70:f0:16:8f:46:cc:d2:f9:ac:3f:ff:10:4a:54:ce:06:a3:
+ be:40:54:3a:47:cd:81:b5:3b:c1:35:4d:ea:6d:52:02:57:84:
+ 0e:6e:cc:62:6f:ef:85:00:52:f9:e8:d0:29:3e:ab:24:83:b5:
+ 73:2d:f3:48:02:32:9a:6c:75:1c:8d:bb:99:92:68:3a:8e:be:
+ 01:7d:85:bb:fa:84:03:1c:2b:18:80:00:e3:8c:a1:9d:2b:3f:
+ fc:53:f7:cf
+-----BEGIN CERTIFICATE-----
+MIIC8zCCAd+gAwIBAgIQa8V7lRiTqpdLYkrAiPw7tjAJBgUrDgMCHQUAMBQxEjAQ
+BgNVBAMTCWVEZWxsUm9vdDAeFw0xNTA0MDcxMDIzMjdaFw0zOTEyMzEyMzU5NTla
+MBQxEjAQBgNVBAMTCWVEZWxsUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAL3RJg1uzVuEX0Hw4XWGzs6oI9W+o7HZdVdBMMVb4Gzb4uZjCTNjbPx4
+b8LNFL1uArUt+5VVMQDsOTY3Lg/Xe/UNukY2b+0llUOzzBYYpbsFcco4n6SsTvDh
+Ni5t+kPo7c23ZrYBPmOu82eEJ6cavs/t39u+wFOkXXwvRCiHA/lWyNWNEPh17+bC
+EP3q5N+JrV+6Ho3zQPEv5QUJYdmXsMmD2CMQojeQUj68J91P5w5BKjurG0xjivzh
+Soie9ym7VRwLFjWScRuw/9XV6CLqTyL5xrqiiDp1uTOuqNj3uxyts9ocbsoJXuxj
+5iEYkSM1nvLupEv+lgy9WqzIEFMm1l8CAwEAAaNJMEcwRQYDVR0BBD4wPIAQYA/f
+EzPwmaRcZuSaa/VZ1KEWMBQxEjAQBgNVBAMTCWVEZWxsUm9vdIIQa8V7lRiTqpdL
+YkrAiPw7tjAJBgUrDgMCHQUAA4IBAQArfdcScsezj8ooJ92UwwnPgg36noOgiUs5
+XzPLP4h0JpUYQVKB9hY1WTDwRUfTKGh7oNOowd027a/rVSb/TNeoiJIvMKn4gbvV
+CWAiHhO8u2u0RkHCDVsa7e0i4ncpueWsihjn6jBrY8T+7eDYwiFT/F03A8NJ7mK5
+lZA8SFd5CTDy3EBUU5UwzXUc5HoIRUxXSPycu3aIBWawg3sCdKiAoikScPAWj0bM
+0vmsP/8QSlTOBqO+QFQ6R82BtTvBNU3qbVICV4QObsxib++FAFL56NApPqskg7Vz
+LfNIAjKabHUcjbuZkmg6jr4BfYW7+oQDHCsYgADjjKGdKz/8U/fP
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/f3bae5e9c0adbfbfb6dbf7e04e74be6ead3ca98a5604ffe591cea86c241848ec.pem b/chromium/net/data/ssl/blacklist/f3bae5e9c0adbfbfb6dbf7e04e74be6ead3ca98a5604ffe591cea86c241848ec.pem
new file mode 100644
index 00000000000..c577069c062
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/f3bae5e9c0adbfbfb6dbf7e04e74be6ead3ca98a5604ffe591cea86c241848ec.pem
@@ -0,0 +1,131 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ ec:60:fa:fc:a1:ca:06:ae:e9:b7:36:48:0a:28:2f:aa
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Domain Validation Secure Server CA
+ Validity
+ Not Before: Aug 20 00:00:00 2015 GMT
+ Not After : Aug 19 23:59:59 2018 GMT
+ Subject: OU=Domain Control Validated, OU=PositiveSSL Multi-Domain, CN=*.sslip.io
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:ca:fe:22:9f:ab:1c:33:0d:ce:90:19:6b:fb:ed:
+ 4e:a2:82:ee:65:02:9f:b6:6c:06:20:ef:29:b8:e8:
+ fa:95:21:f8:1f:52:c8:18:94:d8:f1:ea:19:e9:fe:
+ d1:d7:5f:73:c8:a3:e0:1b:20:a5:59:21:54:8e:65:
+ cd:21:25:59:00:24:1c:63:0c:7e:77:5f:5b:51:84:
+ 3d:c2:67:33:b6:97:32:28:c1:24:6e:11:49:cb:d8:
+ 46:bd:01:e4:4d:0b:9b:1a:e3:55:d0:53:2b:83:7e:
+ 92:82:3f:82:50:13:8a:77:9c:01:35:16:07:ea:1a:
+ fd:98:1d:0a:16:e2:0f:6f:0a:3c:91:5c:26:12:a1:
+ 8b:a0:66:1e:c9:60:de:a5:bd:ba:80:01:70:83:a8:
+ 00:fb:60:c7:a9:5c:b0:99:f2:d7:6a:ff:44:3d:5a:
+ 8b:e5:e1:31:cf:b9:f0:33:36:a9:7a:57:a3:8d:68:
+ 70:5c:88:23:44:c5:b9:ab:b4:8c:d2:3a:ea:8b:f8:
+ 7a:71:0c:ce:83:96:36:3c:49:75:6c:b3:f0:f1:b3:
+ 79:14:33:49:b9:69:e1:c1:02:c5:eb:53:35:4e:0c:
+ 64:d2:31:6b:ae:e0:76:f3:ea:14:90:71:77:5e:05:
+ 15:84:71:3c:8a:eb:4a:29:21:f9:77:af:ed:96:1a:
+ 43:52:d6:6c:b9:14:93:22:99:f3:99:dc:68:b9:4a:
+ 68:f7:fd:94:fc:9f:43:e7:ee:5a:d1:9d:98:20:7c:
+ 74:46:1e:4b:74:39:9c:84:63:74:b3:67:62:9b:09:
+ dc:64:4a:af:07:63:40:d5:89:8c:f5:e2:02:7d:da:
+ ec:9f:c5:83:8b:54:06:69:85:7e:09:26:a4:23:41:
+ 1a:db:03:f9:60:bb:1e:80:95:e5:f9:76:a0:68:1e:
+ 35:e5:36:bb:46:73:fa:f7:ca:86:a6:ae:98:ed:58:
+ 76:fa:5f:f3:64:4b:9f:1d:54:6e:c3:40:f1:af:75:
+ ad:80:5e:c9:1b:17:d8:cc:e6:25:6f:79:a2:23:ce:
+ 45:f2:1d:8a:8e:48:48:8c:ae:39:a9:6c:db:d2:01:
+ e0:2b:8f:66:d2:fd:01:4c:b1:10:f2:41:3c:53:34:
+ c7:49:f0:53:d3:ab:4b:30:e9:c1:1d:47:94:7a:d0:
+ 71:89:a9:13:74:95:38:2f:8c:bf:86:95:66:3e:44:
+ 92:3a:cf:5b:04:57:d1:93:42:f1:6e:12:c3:56:e5:
+ d7:6a:d0:1b:3c:bb:81:37:96:4c:8d:83:19:6e:d4:
+ 40:c9:dc:b9:5e:ed:fa:2e:ff:af:3a:89:6c:21:15:
+ 12:0b:57:9a:88:a2:ab:c1:af:54:40:b1:85:d6:a4:
+ 27:0a:8d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:90:AF:6A:3A:94:5A:0B:D8:90:EA:12:56:73:DF:43:B4:3A:28:DA:E7
+
+ X509v3 Subject Key Identifier:
+ CB:5E:12:73:59:E9:E9:1D:9D:33:09:87:D8:4E:C7:C7:B8:34:7C:A0
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6449.1.2.2.7
+ CPS: https://secure.comodo.com/CPS
+ Policy: 2.23.140.1.2.1
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/COMODORSADomainValidationSecureServerCA.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://crt.comodoca.com/COMODORSADomainValidationSecureServerCA.crt
+ OCSP - URI:http://ocsp.comodoca.com
+
+ X509v3 Subject Alternative Name:
+ DNS:*.sslip.io, DNS:sslip.io
+ Signature Algorithm: sha256WithRSAEncryption
+ 25:50:87:c7:a7:3d:4b:1a:2e:49:ae:43:78:d9:ca:30:ba:48:
+ e9:58:1e:9c:09:8a:7d:01:a0:bf:d9:57:e6:eb:a7:15:18:33:
+ 35:29:ea:21:36:9c:95:f9:c8:e6:3a:e1:b9:21:39:27:af:59:
+ 72:31:aa:86:da:4a:40:ec:96:38:85:20:14:77:55:a4:53:a0:
+ 70:ad:fc:0a:57:ef:b0:8c:91:94:25:bc:25:e4:c2:2b:31:47:
+ 18:19:c8:70:c5:09:23:aa:d0:d3:fc:c9:13:29:86:85:8a:ac:
+ d8:c6:d4:08:6f:45:35:10:73:61:a0:41:3a:65:c2:ee:9b:82:
+ 7b:0c:1a:b6:6b:9e:d6:61:67:ae:f6:c9:f3:d2:d9:d5:d9:f2:
+ 5d:02:90:49:2d:fa:06:4f:39:93:37:42:61:a7:c5:ca:84:9e:
+ f7:60:db:4f:a1:4d:28:da:b3:47:04:56:18:c2:a4:0a:53:ea:
+ e9:8f:13:30:07:1e:f4:5a:06:e0:e3:d9:af:e2:7a:2a:28:b7:
+ d2:79:77:8c:7c:b7:da:37:ff:3b:07:a6:c2:c6:15:66:ab:f9:
+ 8d:b9:17:4f:5b:30:ca:cb:23:14:9c:a3:8e:86:a7:b3:66:7a:
+ 8a:c2:5c:08:97:5f:cc:53:cc:3c:94:8a:3d:91:08:a9:f9:96:
+ 1e:fc:2a:ab
+-----BEGIN CERTIFICATE-----
+MIIGSjCCBTKgAwIBAgIRAOxg+vyhygau6bc2SAooL6owDQYJKoZIhvcNAQELBQAw
+gZAxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
+BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTYwNAYD
+VQQDEy1DT01PRE8gUlNBIERvbWFpbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIg
+Q0EwHhcNMTUwODIwMDAwMDAwWhcNMTgwODE5MjM1OTU5WjBbMSEwHwYDVQQLExhE
+b21haW4gQ29udHJvbCBWYWxpZGF0ZWQxITAfBgNVBAsTGFBvc2l0aXZlU1NMIE11
+bHRpLURvbWFpbjETMBEGA1UEAwwKKi5zc2xpcC5pbzCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBAMr+Ip+rHDMNzpAZa/vtTqKC7mUCn7ZsBiDvKbjo+pUh
++B9SyBiU2PHqGen+0ddfc8ij4BsgpVkhVI5lzSElWQAkHGMMfndfW1GEPcJnM7aX
+MijBJG4RScvYRr0B5E0LmxrjVdBTK4N+koI/glATinecATUWB+oa/ZgdChbiD28K
+PJFcJhKhi6BmHslg3qW9uoABcIOoAPtgx6lcsJny12r/RD1ai+XhMc+58DM2qXpX
+o41ocFyII0TFuau0jNI66ov4enEMzoOWNjxJdWyz8PGzeRQzSblp4cECxetTNU4M
+ZNIxa67gdvPqFJBxd14FFYRxPIrrSikh+Xev7ZYaQ1LWbLkUkyKZ85ncaLlKaPf9
+lPyfQ+fuWtGdmCB8dEYeS3Q5nIRjdLNnYpsJ3GRKrwdjQNWJjPXiAn3a7J/Fg4tU
+BmmFfgkmpCNBGtsD+WC7HoCV5fl2oGgeNeU2u0Zz+vfKhqaumO1Ydvpf82RLnx1U
+bsNA8a91rYBeyRsX2MzmJW95oiPORfIdio5ISIyuOals29IB4CuPZtL9AUyxEPJB
+PFM0x0nwU9OrSzDpwR1HlHrQcYmpE3SVOC+Mv4aVZj5EkjrPWwRX0ZNC8W4Sw1bl
+12rQGzy7gTeWTI2DGW7UQMncuV7t+i7/rzqJbCEVEgtXmoiiq8GvVECxhdakJwqN
+AgMBAAGjggHRMIIBzTAfBgNVHSMEGDAWgBSQr2o6lFoL2JDqElZz30O0Oija5zAd
+BgNVHQ4EFgQUy14Sc1np6R2dMwmH2E7Hx7g0fKAwDgYDVR0PAQH/BAQDAgWgMAwG
+A1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCME8GA1Ud
+IARIMEYwOgYLKwYBBAGyMQECAgcwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1
+cmUuY29tb2RvLmNvbS9DUFMwCAYGZ4EMAQIBMFQGA1UdHwRNMEswSaBHoEWGQ2h0
+dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET1JTQURvbWFpblZhbGlkYXRpb25T
+ZWN1cmVTZXJ2ZXJDQS5jcmwwgYUGCCsGAQUFBwEBBHkwdzBPBggrBgEFBQcwAoZD
+aHR0cDovL2NydC5jb21vZG9jYS5jb20vQ09NT0RPUlNBRG9tYWluVmFsaWRhdGlv
+blNlY3VyZVNlcnZlckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29t
+b2RvY2EuY29tMB8GA1UdEQQYMBaCCiouc3NsaXAuaW+CCHNzbGlwLmlvMA0GCSqG
+SIb3DQEBCwUAA4IBAQAlUIfHpz1LGi5JrkN42cowukjpWB6cCYp9AaC/2Vfm66cV
+GDM1KeohNpyV+cjmOuG5ITknr1lyMaqG2kpA7JY4hSAUd1WkU6BwrfwKV++wjJGU
+Jbwl5MIrMUcYGchwxQkjqtDT/MkTKYaFiqzYxtQIb0U1EHNhoEE6ZcLum4J7DBq2
+a57WYWeu9snz0tnV2fJdApBJLfoGTzmTN0Jhp8XKhJ73YNtPoU0o2rNHBFYYwqQK
+U+rpjxMwBx70Wgbg49mv4noqKLfSeXeMfLfaN/87B6bCxhVmq/mNuRdPWzDKyyMU
+nKOOhqezZnqKwlwIl1/MU8w8lIo9kQip+ZYe/Cqr
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/f4a5984324de98bd979ef181a100cf940f2166173319a86a0d9d7c8fac3b0a8f.pem b/chromium/net/data/ssl/blacklist/f4a5984324de98bd979ef181a100cf940f2166173319a86a0d9d7c8fac3b0a8f.pem
new file mode 100644
index 00000000000..07362977af1
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/f4a5984324de98bd979ef181a100cf940f2166173319a86a0d9d7c8fac3b0a8f.pem
@@ -0,0 +1,98 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 61:1d:d8:61:00:00:00:00:00:04
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, O=Fraunhofer, OU=Fraunhofer Corporate PKI, CN=Fraunhofer Root CA 2007
+ Validity
+ Not Before: Apr 28 09:03:06 2008 GMT
+ Not After : Jun 30 23:59:59 2019 GMT
+ Subject: C=DE, O=Fraunhofer, OU=Fraunhofer Corporate PKI, CN=Fraunhofer Service CA 2007
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ac:9d:69:59:4a:62:16:a5:2c:be:3f:9a:45:5d:
+ ba:1a:6d:87:60:3c:d6:8d:78:9a:67:2c:96:28:5e:
+ e1:7c:7c:d0:05:26:67:3b:f9:ab:a5:3e:f8:b0:55:
+ fe:23:7e:78:ab:68:2b:c1:f1:6c:dd:d6:ec:94:88:
+ 2d:76:a7:2c:f1:7a:8e:a3:8c:e0:1a:2c:f5:b0:7b:
+ 20:dc:d0:ec:e5:55:8d:d3:a7:3a:51:1e:6f:5a:21:
+ 9e:e9:5e:cf:2f:fa:13:31:cc:3c:95:ef:e7:9d:a4:
+ 5e:02:6d:04:00:62:e4:76:71:15:f8:3c:0b:e2:05:
+ 66:59:bb:6e:ee:b0:16:a2:72:e8:9c:41:8c:ab:1d:
+ 83:40:a1:f7:db:65:f4:9c:ab:07:41:6e:9f:99:9f:
+ 8b:8e:7a:3f:cc:e9:5a:dd:47:14:d0:64:8d:20:1d:
+ 88:8e:55:55:51:c3:8f:47:29:72:b0:53:69:da:21:
+ 45:1b:5a:62:cf:eb:f1:34:81:9f:b7:aa:a3:83:75:
+ f2:c2:4e:1a:0d:58:66:6c:88:2b:f8:dc:59:05:70:
+ 94:d2:91:5d:42:b0:1e:ba:90:ce:01:5b:e5:53:a3:
+ 18:b3:bc:1b:8d:e4:91:c1:8a:ec:ce:d2:52:b1:0a:
+ f2:41:50:71:c4:4d:77:02:51:8a:c6:0b:c5:a0:66:
+ 07:0b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Subject Key Identifier:
+ 38:4D:0C:1D:C4:77:A7:B3:F8:67:86:D0:18:51:9F:58:9F:1E:9E:25
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Authority Key Identifier:
+ keyid:2F:45:42:1E:31:05:80:D5:70:D8:F8:1D:57:CB:5B:7A:D5:3D:9C:F7
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.pki.fraunhofer.de/fhg-root-ca-2007.crl
+ URI:http://crl.fraunhofer-pki.de/fhg-root-ca-2007.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://cert.pki.fraunhofer.de/fhg-root-ca-2007.cer
+ CA Issuers - URI:http://cert.fraunhofer-pki.de/fhg-root-ca-2007.cer
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 84:4a:dc:64:af:2d:f0:c3:1d:a7:54:8f:6a:c7:34:e7:98:c7:
+ 86:7f:81:4e:8d:17:c4:c4:93:3d:5f:0c:ee:05:3a:ec:79:fe:
+ 76:f1:e7:eb:9f:98:4c:0c:a8:c6:80:36:be:de:4b:80:4e:85:
+ 76:ee:7a:5c:4a:0e:9f:0e:24:d9:5d:d4:9c:7b:9e:c7:13:74:
+ f9:c9:79:0c:25:5a:4c:3f:ef:c9:5a:f6:46:4b:dd:56:e7:07:
+ 8c:5c:46:ee:54:21:f0:6a:29:63:c3:34:d7:59:b9:24:0d:4e:
+ de:8a:3b:0f:64:d2:67:59:fc:a9:42:60:68:2c:39:ca:10:76:
+ 0f:f3:30:37:8c:a5:07:4f:b7:d6:30:46:45:81:72:2a:67:77:
+ 04:26:72:36:9b:1c:49:86:56:81:3a:c0:65:1f:1e:9c:b9:18:
+ e6:37:6e:8f:3f:04:41:54:b4:e4:05:c0:02:20:71:11:ac:4f:
+ 55:c5:21:7c:4f:2f:2b:1b:b1:a3:04:02:ce:07:96:1b:d3:0b:
+ 7b:80:68:05:cc:fc:7f:95:95:61:62:3b:7c:39:ed:ef:3b:95:
+ 01:3d:d2:e6:67:af:c3:04:47:71:4f:4d:70:74:aa:1c:0b:0e:
+ 9e:e3:a9:17:fd:ae:cb:ae:f2:c2:91:2f:02:a1:48:be:bc:76:
+ f8:c0:2d:60
+-----BEGIN CERTIFICATE-----
+MIIEyTCCA7GgAwIBAgIKYR3YYQAAAAAABDANBgkqhkiG9w0BAQUFADBnMQswCQYD
+VQQGEwJERTETMBEGA1UEChMKRnJhdW5ob2ZlcjEhMB8GA1UECxMYRnJhdW5ob2Zl
+ciBDb3Jwb3JhdGUgUEtJMSAwHgYDVQQDExdGcmF1bmhvZmVyIFJvb3QgQ0EgMjAw
+NzAeFw0wODA0MjgwOTAzMDZaFw0xOTA2MzAyMzU5NTlaMGoxCzAJBgNVBAYTAkRF
+MRMwEQYDVQQKEwpGcmF1bmhvZmVyMSEwHwYDVQQLExhGcmF1bmhvZmVyIENvcnBv
+cmF0ZSBQS0kxIzAhBgNVBAMTGkZyYXVuaG9mZXIgU2VydmljZSBDQSAyMDA3MIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArJ1pWUpiFqUsvj+aRV26Gm2H
+YDzWjXiaZyyWKF7hfHzQBSZnO/mrpT74sFX+I354q2grwfFs3dbslIgtdqcs8XqO
+o4zgGiz1sHsg3NDs5VWN06c6UR5vWiGe6V7PL/oTMcw8le/nnaReAm0EAGLkdnEV
++DwL4gVmWbtu7rAWonLonEGMqx2DQKH322X0nKsHQW6fmZ+Ljno/zOla3UcU0GSN
+IB2IjlVVUcOPRylysFNp2iFFG1piz+vxNIGft6qjg3Xywk4aDVhmbIgr+NxZBXCU
+0pFdQrAeupDOAVvlU6MYs7wbjeSRwYrsztJSsQryQVBxxE13AlGKxgvFoGYHCwID
+AQABo4IBcjCCAW4wEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUOE0MHcR3
+p7P4Z4bQGFGfWJ8eniUwDgYDVR0PAQH/BAQDAgEGMB8GA1UdIwQYMBaAFC9FQh4x
+BYDVcNj4HVfLW3rVPZz3MHUGA1UdHwRuMGwwaqBooGaGMWh0dHA6Ly9jcmwucGtp
+LmZyYXVuaG9mZXIuZGUvZmhnLXJvb3QtY2EtMjAwNy5jcmyGMWh0dHA6Ly9jcmwu
+ZnJhdW5ob2Zlci1wa2kuZGUvZmhnLXJvb3QtY2EtMjAwNy5jcmwwgZAGCCsGAQUF
+BwEBBIGDMIGAMD4GCCsGAQUFBzAChjJodHRwOi8vY2VydC5wa2kuZnJhdW5ob2Zl
+ci5kZS9maGctcm9vdC1jYS0yMDA3LmNlcjA+BggrBgEFBQcwAoYyaHR0cDovL2Nl
+cnQuZnJhdW5ob2Zlci1wa2kuZGUvZmhnLXJvb3QtY2EtMjAwNy5jZXIwDQYJKoZI
+hvcNAQEFBQADggEBAIRK3GSvLfDDHadUj2rHNOeYx4Z/gU6NF8TEkz1fDO4FOux5
+/nbx5+ufmEwMqMaANr7eS4BOhXbuelxKDp8OJNld1Jx7nscTdPnJeQwlWkw/78la
+9kZL3VbnB4xcRu5UIfBqKWPDNNdZuSQNTt6KOw9k0mdZ/KlCYGgsOcoQdg/zMDeM
+pQdPt9YwRkWBcipndwQmcjabHEmGVoE6wGUfHpy5GOY3bo8/BEFUtOQFwAIgcRGs
+T1XFIXxPLysbsaMEAs4HlhvTC3uAaAXM/H+VlWFiO3w57e87lQE90uZnr8MER3FP
+TXB0qhwLDp7jqRf9rsuu8sKRLwKhSL68dvjALWA=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/f8a5ff189fedbfe34e21103389a68340174439ad12974a4e8d4d784d1f3a0faa.pem b/chromium/net/data/ssl/blacklist/f8a5ff189fedbfe34e21103389a68340174439ad12974a4e8d4d784d1f3a0faa.pem
new file mode 100644
index 00000000000..05e5e701e44
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/f8a5ff189fedbfe34e21103389a68340174439ad12974a4e8d4d784d1f3a0faa.pem
@@ -0,0 +1,114 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 39:2a:43:4f:0e:07:df:1f:8a:a3:05:de:34:e0:c2:29
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
+ Validity
+ Not Before: Mar 15 00:00:00 2011 GMT
+ Not After : Mar 14 23:59:59 2014 GMT
+ Subject: C=US/postalCode=38477, ST=Florida, L=English/street=Sea Village 10, O=Google Ltd., OU=Tech Dept., OU=Hosted by GTI Group Corporation, OU=PlatinumSSL, CN=login.yahoo.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a1:a4:05:3d:ed:85:45:93:8a:18:4d:c6:03:00:
+ 57:e2:40:77:f0:1c:eb:d0:19:df:22:5d:08:7f:d1:
+ 07:3c:41:89:46:17:a3:09:fa:fc:f8:a9:04:d1:96:
+ 8f:ab:d7:4f:3c:f9:ad:18:a9:74:81:c4:57:0a:3a:
+ 26:16:ce:62:3e:bc:3f:6c:21:ee:93:8d:cb:0d:a0:
+ 1f:9a:96:d0:8f:ad:f5:93:93:82:ee:72:0c:a1:75:
+ 15:a3:7b:84:56:b8:ad:ff:52:11:71:84:bc:3a:30:
+ 0b:7e:98:a8:e1:a8:3f:37:52:d0:f1:7c:6f:90:d8:
+ 45:0a:ac:39:72:6a:61:d5:bb:c3:8c:f9:c2:cc:df:
+ fd:3a:71:b9:af:bc:dc:3a:dc:0c:b6:b1:d2:d1:89:
+ bb:41:b6:f2:de:57:d5:15:df:fc:fd:e2:31:c5:df:
+ ca:c1:d8:8f:2c:bf:f0:0e:5b:71:e0:34:71:c3:c5:
+ 4d:7d:7a:d4:fa:ed:30:4b:2f:ea:b6:2e:9e:93:3c:
+ e2:3a:f8:42:a2:1a:ee:dc:df:cd:0f:a9:f6:79:84:
+ 1a:8e:6c:02:b6:86:e5:bf:51:6a:66:f8:f3:9c:d3:
+ 59:0c:7b:a5:99:78:cd:7c:99:fa:c6:96:47:d8:32:
+ d4:74:76:0e:77:4b:20:74:a4:b7:89:75:92:4a:b4:
+ 5b:55
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45
+
+ X509v3 Subject Key Identifier:
+ 86:49:45:FC:33:19:33:D4:04:ED:27:61:EE:E8:01:C9:0C:7F:2F:7E
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6449.1.2.1.3.4
+ CPS: https://secure.comodo.com/CPS
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/UTN-USERFirst-Hardware.crl
+
+ Full Name:
+ URI:http://crl.comodo.net/UTN-USERFirst-Hardware.crl
+
+ Authority Information Access:
+ CA Issuers - URI:http://crt.comodoca.com/UTNAddTrustServerCA.crt
+ OCSP - URI:http://ocsp.comodoca.com
+
+ X509v3 Subject Alternative Name:
+ DNS:login.yahoo.com
+ Signature Algorithm: sha1WithRSAEncryption
+ 57:62:e1:77:eb:fc:1f:bf:88:53:af:58:d3:d4:d6:6d:67:30:
+ 17:40:be:e0:1f:64:de:87:15:cc:e0:a4:56:a9:d1:9f:f9:01:
+ fe:02:b1:b1:ea:e2:5f:ee:71:16:31:f9:08:d5:c2:d7:9a:9b:
+ b2:5a:38:d7:a9:7f:e9:87:6b:31:f9:0b:ac:d9:fd:50:71:e0:
+ db:82:92:0f:81:9c:8d:77:e9:eb:2e:ea:d4:23:41:87:ec:2d:
+ b2:78:b3:8e:b1:67:d2:ee:71:03:08:12:99:b3:02:29:6f:de:
+ 8b:de:c1:a9:03:0a:5a:33:1c:3d:11:03:c6:48:0c:98:9c:15:
+ 2e:d9:a6:85:52:e7:05:8a:ae:30:23:eb:ed:28:6c:60:e9:2d:
+ 7f:8f:47:8b:2f:d0:dc:e6:bb:0f:7e:5f:f2:48:81:8e:50:04:
+ 63:b1:51:80:75:9a:a9:b6:10:1c:10:5f:6f:18:6f:e0:0e:96:
+ 45:ce:ee:f1:b5:20:db:ef:da:6e:c8:95:e3:f6:45:fd:ca:fc:
+ a5:5f:49:6d:06:1e:d2:de:61:3d:15:7d:37:e5:1c:35:8e:06:
+ c2:6b:f7:b4:a8:28:2c:31:cb:aa:b4:a7:97:4f:9d:8a:f6:af:
+ 7e:37:b9:7b:3d:df:92:66:8b:8f:4e:9d:c6:36:e7:5c:a6:ab:
+ 12:0f:d6:cf
+-----BEGIN CERTIFICATE-----
+MIIF2TCCBMGgAwIBAgIQOSpDTw4H3x+KowXeNODCKTANBgkqhkiG9w0BAQUFADCB
+lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
+Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
+SGFyZHdhcmUwHhcNMTEwMzE1MDAwMDAwWhcNMTQwMzE0MjM1OTU5WjCB3zELMAkG
+A1UEBhMCVVMxDjAMBgNVBBETBTM4NDc3MRAwDgYDVQQIEwdGbG9yaWRhMRAwDgYD
+VQQHEwdFbmdsaXNoMRcwFQYDVQQJEw5TZWEgVmlsbGFnZSAxMDEUMBIGA1UEChML
+R29vZ2xlIEx0ZC4xEzARBgNVBAsTClRlY2ggRGVwdC4xKDAmBgNVBAsTH0hvc3Rl
+ZCBieSBHVEkgR3JvdXAgQ29ycG9yYXRpb24xFDASBgNVBAsTC1BsYXRpbnVtU1NM
+MRgwFgYDVQQDEw9sb2dpbi55YWhvby5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQChpAU97YVFk4oYTcYDAFfiQHfwHOvQGd8iXQh/0Qc8QYlGF6MJ
++vz4qQTRlo+r1088+a0YqXSBxFcKOiYWzmI+vD9sIe6TjcsNoB+altCPrfWTk4Lu
+cgyhdRWje4RWuK3/UhFxhLw6MAt+mKjhqD83UtDxfG+Q2EUKrDlyamHVu8OM+cLM
+3/06cbmvvNw63Ay2sdLRibtBtvLeV9UV3/z94jHF38rB2I8sv/AOW3HgNHHDxU19
+etT67TBLL+q2Lp6TPOI6+EKiGu7c380PqfZ5hBqObAK2huW/UWpm+POc01kMe6WZ
+eM18mfrGlkfYMtR0dg53SyB0pLeJdZJKtFtVAgMBAAGjggHVMIIB0TAfBgNVHSME
+GDAWgBShcl8mGyiYQ5VdBzfVhZadS9LDRTAdBgNVHQ4EFgQUhklF/DMZM9QE7Sdh
+7ugByQx/L34wDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYw
+FAYIKwYBBQUHAwEGCCsGAQUFBwMCMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQME
+MCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMHsG
+A1UdHwR0MHIwOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1VUTi1VU0VS
+Rmlyc3QtSGFyZHdhcmUuY3JsMDagNKAyhjBodHRwOi8vY3JsLmNvbW9kby5uZXQv
+VVROLVVTRVJGaXJzdC1IYXJkd2FyZS5jcmwwcQYIKwYBBQUHAQEEZTBjMDsGCCsG
+AQUFBzAChi9odHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9VVE5BZGRUcnVzdFNlcnZl
+ckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMBoG
+A1UdEQQTMBGCD2xvZ2luLnlhaG9vLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAV2Lh
+d+v8H7+IU69Y09TWbWcwF0C+4B9k3ocVzOCkVqnRn/kB/gKxseriX+5xFjH5CNXC
+15qbslo416l/6YdrMfkLrNn9UHHg24KSD4GcjXfp6y7q1CNBh+wtsnizjrFn0u5x
+AwgSmbMCKW/ei97BqQMKWjMcPREDxkgMmJwVLtmmhVLnBYquMCPr7ShsYOktf49H
+iy/Q3Oa7D35f8kiBjlAEY7FRgHWaqbYQHBBfbxhv4A6WRc7u8bUg2+/absiV4/ZF
+/cr8pV9JbQYe0t5hPRV9N+UcNY4Gwmv3tKgoLDHLqrSnl0+divavfje5ez3fkmaL
+j06dxjbnXKarEg/Wzw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blacklist/fdedb5bdfcb67411513a61aee5cb5b5d7c52af06028efc996cc1b05b1d6cea2b.pem b/chromium/net/data/ssl/blacklist/fdedb5bdfcb67411513a61aee5cb5b5d7c52af06028efc996cc1b05b1d6cea2b.pem
new file mode 100644
index 00000000000..b3108c8ee26
--- /dev/null
+++ b/chromium/net/data/ssl/blacklist/fdedb5bdfcb67411513a61aee5cb5b5d7c52af06028efc996cc1b05b1d6cea2b.pem
@@ -0,0 +1,110 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 120000505 (0x7270ff9)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Global Root
+ Validity
+ Not Before: Sep 20 09:45:32 2006 GMT
+ Not After : Sep 20 09:44:06 2013 GMT
+ Subject: C=NL, O=DigiNotar, CN=DigiNotar Cyber CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:d2:ce:15:0a:2d:a8:5e:84:67:ad:fd:be:ef:46:
+ c7:c8:b9:cf:73:fc:f4:34:b9:f9:2c:43:e7:60:13:
+ 3d:7a:e3:b2:cf:3b:67:6c:90:ad:c0:b9:3f:84:52:
+ f0:35:42:dc:74:dc:28:3b:bd:52:b4:a7:ac:72:45:
+ 17:c6:f0:89:eb:b4:aa:25:f2:5d:4b:5e:d1:d9:87:
+ ba:d6:7d:7c:f5:ce:32:9f:10:33:c5:b1:4a:bb:5e:
+ 91:31:c2:d0:e9:41:c2:91:64:7e:09:41:3b:db:8b:
+ 08:37:6a:aa:ca:52:de:b5:39:1e:c0:88:03:a5:3f:
+ 8b:99:13:61:43:b5:9b:82:b3:ee:20:6f:cf:a1:44:
+ a2:ea:2f:6b:40:9f:8f:2b:57:ad:a1:53:c2:85:22:
+ 69:9d:a0:3f:51:df:0b:41:91:0d:a5:e1:a8:aa:5c:
+ 49:08:5d:bd:de:70:41:b1:0f:c9:63:6b:d3:7f:34:
+ 74:02:2f:34:5a:78:75:1c:68:7a:81:67:8a:f3:da:
+ 40:f0:60:63:f4:92:20:d7:03:a6:3d:a3:1e:67:c4:
+ 84:1b:41:a5:c9:8c:e6:bd:ea:48:b6:05:16:08:b3:
+ 37:12:5a:f7:61:3c:f7:38:6f:2e:97:e0:6f:56:38:
+ 54:d3:28:b5:ad:14:6e:2e:4b:64:b5:27:65:b7:75:
+ 25:09:b6:07:3d:95:56:02:0a:82:60:b2:73:45:e0:
+ 33:26:51:74:9a:b9:d4:50:1c:f6:4d:5b:5b:52:52:
+ 13:5a:a6:7f:a7:0e:e1:e8:41:54:67:98:8c:87:d5:
+ c9:d3:6c:cb:d3:54:92:06:09:34:41:f7:81:6f:3f:
+ 9e:c9:7c:75:55:b0:e7:c1:b3:77:e8:c3:c4:00:35:
+ 95:40:70:10:4a:05:de:25:bb:9f:59:a5:64:bc:47:
+ 60:bf:60:e3:76:8b:13:55:dd:e1:74:7a:b9:cf:24:
+ a6:6a:7f:de:64:22:44:58:68:82:6a:10:f9:3d:e5:
+ 3e:1b:b9:bd:fc:22:f4:60:04:89:bb:55:6d:28:55:
+ fa:de:8e:8d:1b:21:14:d7:37:8b:34:7b:4d:f6:b2:
+ b2:10:cf:33:b1:7d:1c:62:99:48:cb:2b:6c:76:96:
+ 55:bf:19:0d:1d:1f:bb:65:aa:1b:8e:99:b5:c6:28:
+ 90:e5:82:2d:78:50:20:9a:fd:79:2f:24:7f:f0:89:
+ 29:69:f4:7d:cd:73:be:b3:ed:4e:c1:d1:ed:52:5e:
+ 8f:f7:b8:d7:8d:87:ad:b2:d9:1b:51:12:ff:56:b3:
+ e1:af:34:7d:5c:a4:78:88:10:9e:9d:03:c6:a5:aa:
+ a2:24:51:f7:49:14:c5:b1:ee:59:43:95:df:ab:68:
+ 28:30:3f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:1
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6334.1.0
+ CPS: http://www.public-trust.com/CPS/OmniRoot.html
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Authority Key Identifier:
+ keyid:A6:0C:1D:9F:61:FF:07:17:B5:BF:38:46:DB:43:30:D5:8E:B0:52:06
+ DirName:/C=US/O=GTE Corporation/OU=GTE CyberTrust Solutions, Inc./CN=GTE CyberTrust Global Root
+ serial:01:A5
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://www.public-trust.com/cgi-bin/CRL/2018/cdp.crl
+
+ X509v3 Subject Key Identifier:
+ AB:F9:68:DF:CF:4A:37:D7:7B:45:8C:5F:72:DE:40:44:C3:65:BB:C2
+ Signature Algorithm: sha1WithRSAEncryption
+ 09:ca:62:0f:8d:bb:4a:e0:d4:7a:35:2b:06:2d:d1:28:61:b6:
+ ac:01:fb:83:49:bc:ae:d4:2f:2d:86:ae:19:83:a5:d6:1d:13:
+ e2:17:be:fe:32:74:e9:7a:14:38:ca:94:5e:f7:29:01:69:71:
+ 1b:91:1a:fd:a3:bb:aa:1d:ca:7b:e2:16:fd:a1:a3:0e:f3:0c:
+ 5f:b2:e1:20:31:94:2b:5e:92:76:ed:fa:e9:b5:23:a6:bf:0a:
+ 3b:03:a9:6f:52:60:54:cd:5f:e9:b7:2f:7c:a2:27:fd:41:83:
+ 75:b6:0d:fb:78:26:f3:b1:45:e9:32:95:2a:1a:35:21:95:c5:
+ a2:75
+-----BEGIN CERTIFICATE-----
+MIIFODCCBKGgAwIBAgIEBycP+TANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV
+UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
+cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
+b2JhbCBSb290MB4XDTA2MDkyMDA5NDUzMloXDTEzMDkyMDA5NDQwNlowPjELMAkG
+A1UEBhMCTkwxEjAQBgNVBAoTCURpZ2lOb3RhcjEbMBkGA1UEAxMSRGlnaU5vdGFy
+IEN5YmVyIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0s4VCi2o
+XoRnrf2+70bHyLnPc/z0NLn5LEPnYBM9euOyzztnbJCtwLk/hFLwNULcdNwoO71S
+tKesckUXxvCJ67SqJfJdS17R2Ye61n189c4ynxAzxbFKu16RMcLQ6UHCkWR+CUE7
+24sIN2qqylLetTkewIgDpT+LmRNhQ7WbgrPuIG/PoUSi6i9rQJ+PK1etoVPChSJp
+naA/Ud8LQZENpeGoqlxJCF293nBBsQ/JY2vTfzR0Ai80Wnh1HGh6gWeK89pA8GBj
+9JIg1wOmPaMeZ8SEG0GlyYzmvepItgUWCLM3Elr3YTz3OG8ul+BvVjhU0yi1rRRu
+LktktSdlt3UlCbYHPZVWAgqCYLJzReAzJlF0mrnUUBz2TVtbUlITWqZ/pw7h6EFU
+Z5iMh9XJ02zL01SSBgk0QfeBbz+eyXx1VbDnwbN36MPEADWVQHAQSgXeJbufWaVk
+vEdgv2DjdosTVd3hdHq5zySman/eZCJEWGiCahD5PeU+G7m9/CL0YASJu1VtKFX6
+3o6NGyEU1zeLNHtN9rKyEM8zsX0cYplIyytsdpZVvxkNHR+7Zaobjpm1xiiQ5YIt
+eFAgmv15LyR/8IkpafR9zXO+s+1OwdHtUl6P97jXjYetstkbURL/VrPhrzR9XKR4
+iBCenQPGpaqiJFH3SRTFse5ZQ5Xfq2goMD8CAwEAAaOCAYYwggGCMBIGA1UdEwEB
+/wQIMAYBAf8CAQEwUwYDVR0gBEwwSjBIBgkrBgEEAbE+AQAwOzA5BggrBgEFBQcC
+ARYtaHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29tL0NQUy9PbW5pUm9vdC5odG1s
+MA4GA1UdDwEB/wQEAwIBBjCBoAYDVR0jBIGYMIGVgBSmDB2fYf8HF7W/OEbbQzDV
+jrBSBqF5pHcwdTELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD0dURSBDb3Jwb3JhdGlv
+bjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3QgU29sdXRpb25zLCBJbmMuMSMwIQYD
+VQQDExpHVEUgQ3liZXJUcnVzdCBHbG9iYWwgUm9vdIICAaUwRQYDVR0fBD4wPDA6
+oDigNoY0aHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29tL2NnaS1iaW4vQ1JMLzIw
+MTgvY2RwLmNybDAdBgNVHQ4EFgQUq/lo389KN9d7RYxfct5ARMNlu8IwDQYJKoZI
+hvcNAQEFBQADgYEACcpiD427SuDUejUrBi3RKGG2rAH7g0m8rtQvLYauGYOl1h0T
+4he+/jJ06XoUOMqUXvcpAWlxG5Ea/aO7qh3Ke+IW/aGjDvMMX7LhIDGUK16Sdu36
+6bUjpr8KOwOpb1JgVM1f6bcvfKIn/UGDdbYN+3gm87FF6TKVKho1IZXFonU=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/README b/chromium/net/data/ssl/certificates/README
index 31a1630b234..3798af5ce0e 100644
--- a/chromium/net/data/ssl/certificates/README
+++ b/chromium/net/data/ssl/certificates/README
@@ -134,8 +134,6 @@ unit tests.
A certificate and private key only valid on 0001-01-01. Windows refuses to
parse this certificate.
-- sha256.pem: Used to test the handling of SHA-256 certs on Windows.
-
- spdy_pooling.pem : Used to test the handling of spdy IP connection pooling
- subjectAltName_sanity_check.pem : Used to test the handling of various types
@@ -209,6 +207,10 @@ unit tests.
- client_2.key
- client_2.pk8
- client_2_ca.pem
+- client_3.pem
+- client_3.key
+- client_3.pk8
+- client_3_ca.pem
This is a set of files used to unit test SSL client certificate
authentication.
- client_1_ca.pem and client_2_ca.pem are the certificates of
@@ -219,6 +221,10 @@ unit tests.
private key for a second certificate signed by client_2_ca.pem.
- each .pk8 file contains the same key as the corresponding .key file
as PKCS#8 PrivateKeyInfo in DER encoding.
+ - client_3.pem is nearly identical to client_2.pem, except it is used
+ to test wifi EAP-TLS authentication so it uses a different set
+ of X509v3 extensions. Specifically it includes two Subject
+ Alternative Name fields recognized by Chrome OS.
===== From net/data/ssl/scripts/generate-android-test-key.sh
- android-test-key-rsa.pem
diff --git a/chromium/net/data/ssl/certificates/client_1.key b/chromium/net/data/ssl/certificates/client_1.key
index a2fdf930c15..f09bd994ebd 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-----
-MIIEpQIBAAKCAQEA1d+6NMvCA7U3emGJGrUauSd/qSy6oTasg224RZ41gqTeo2k4
-JYRXAIxBhIZteEHUEJkbFRimBC+SoBwpw+Bd4pARLPqsGA3+Xo1cWgFK9yzJbjmO
-FDDZ/PZq7p2juiP+XaovlgdlOMqkPNKTIbC22/tAEgABmTBBZ+IvZWNxqqbvRSMF
-i7QobDW/QXNh8Z53jKdRz8dRY8cAq06j5Y/+PEX6ntIpvFmUfRTJNt/NCrWfv6z9
-HStt5RMwFHHed9+D820szRbApdzyH2WGN5EvMWZ+GktCtynhzR3Jcg5ljqlMdC6Q
-t+CRDOj+kianF5q2JX9miS+/VKdRTOaPTTShwwIDAQABAoIBAQCwmJWGNqCysxVm
-BddRqCyyqbytkfNgXma/9v7q7SG+CCiVwbHMuKOmHimTJfSKEcDrG6DTIJEkb6ug
-bODHjiG3i8HC5BDpo9RfelXBM8QUqHSCgR+h6Fx2lXniIWQptMK50GaOePjJlflb
-B3zZmrLCnYlf04V+WewHvSnpi901TDLklIM8fGIFHke+X1yGKxHKOKWKPak7QEPc
-Bt0BxcGi525kNDd0Mh7c7dQ1LSie2dhAUDUwniLjvwx1MY+aN52Z2nhP0LODMMo3
-E2H85Ggv/hIS/9GqcERxPJovLBp5xI5cD95Kk/p00dZjT99ZHS67aM8/OZGbM+Dm
-Eixy1EoBAoGBAPZGMhvGLVbsRbMPSQ7tKREru58PiDHdDQlhKWJJ4hinlWmpFXIU
-RryeVXXZ7Iiw3VwhoVXjQHCyfb4Xum/k/SeCc8XFm8Uqh46bbebcGjmN06UfrRx6
-hP+kqeFrOE2XmlIZT9jgTHQVXM9cPXRss5m2DEwdG7SIDWcbZ/22WqJDAoGBAN5R
-9/Z+GoApWqCf/61R/PSDQSMEWrJMXse5qjbFjWPNvNAR5El8G6WbCZys8NrzIOKs
-jD82RNtV3bOq9aWkCqiUn/ZI2Fx0CYxQbEJIe6gjSxTsCcB+/3kjPAn07J+FTETc
-hRtFXl3tCNMY7dmQXFluTpQk8Vygzmz64KTsgMqBAoGBAM4MDQCP3n9LT0VxFH8Y
-jbOAE4oRRLHzcGTYlfdWOYTHMYslnHvF2ykUkAv6OJxk3c+nk4R4jgG8VNgmoiXc
-QLI9wv9FRf7AhooaIOl2XbqpntoYlo2tNHlvG3Mucfz5SnRGGTgq8cxt0yjq08AE
-8n84gTFtaTCyZARQOcFcQJhhAoGAZxaRKV4+AZGrcXHfh8nNxr+aE5ewSp75EBm6
-oN0n+9Bprf2t4plG5JqocVsL8Cru48zo12LduOru+6HZeC5Btvv71KLgmLZBuyuL
-l4yusj9zUEdHGliJM+2vqFpG4o1X2VJ78jJPWLRR9DjKCalT+TAaBb2/oZj7PzNx
-uWflLIECgYEAgXxM6ViEf+5Fefe671FpNFH7Ogpu1EOJzrk3k2vSXcrCmmEEQISH
-BxrNcf1T6Ich/vVHY5mRw1lBbrhk0tiydI7YMh+voUrpwA+dZExzLvnWDIaIr9rQ
-Ry5Mc5H8EfmvdYsuGNayJG/ygBsJFozqku8k3P+wJ3s3CiB36B3NShk=
+MIIEpAIBAAKCAQEA0b2s/Agv3LIaQmnyaOIy5BxKAagy4XYBXpSaAIkFMiKslpdj
+u2Bz56SR/k4Ee6Hpczc7f5C0XB/PTP07Mwes6si0wuGqpr8yi9KXg/4y9i1gbnEd
+FlyL4wN86Ebhf8fOvq2B97R2/sbNj0rPBBi/xL/rLPqk80xhJ9un7hjR5DcOrTsD
+6XPqPPsFLc3/5ALYWpqPnCA7Nq0PpT+/mi2Uy3lP6uIHC7rZc3CuYpnsecctoz5M
+HquPJIoytJCM5dXD5QOXdc+wvI1OdD4/V/bEAyUzd9o+1GEYrCXnmEBfBmmjfEm6
+wyOsx4Cs60S8sQ7fykGvVYi3lwDYGYvl8fSoHwIDAQABAoIBAQCtFY0ic5Mj2mpn
+Mk1Ulo6OxnWgRnCutJZOue0Y0fpStGCe6ZHo+KDNoXbFWRbD/ArOBN951y2v9KQ7
+EaL/6q6dFkJtrJMKhjAtSP22dFkT5MB2g6wQXxElpyQ1/wBqVbZcjoz5oJiuidrr
+DD4oUFA5CnQGK1ViXj6zCMbdaugTHonM7N6q4jJrWN21HOFMlMCeX4Qy47IR737i
+KWEMiOhF2TOnWZLJ/S8pVyZ4oGOkCR8TmDtAQ8DrGfMkPCfGny5PPItBosxJIBNc
+90RLUFMIFn8a9Vlf7nfk+v2YUgIB/dONpkL0hWZyFEhLJgr44VrgLp38Rygk3AKG
+CEln81qZAoGBAO4KX9xx1OU5/goFJ9V+bhqRtw5nDIH3hoLNq9n/yCIP+QHNXX2C
+C4smy9bTfc28iwiX3GxaVgXPYSS+nwj3OYVIsFhSagSXsMUJAtQHvx2pB24qfiGf
+ia9PONjuAQAK74sZOC2+/zdgrfbExDSTukbSvZWxGebiutQ4JR8vAktlAoGBAOGQ
+taN+pDwDEAYIGo4J7nG9srlBHpZNHwBK/hiN9jBhPvd8TK+6wIQaKi4OACE8iHxJ
+zkkOR8GoJyB6JwW79S1fxn/bq7MfGWDhm70/M88wvklNW5A83YwGJxUFRiIzLSjg
+SdytO/vsqcF9X6+ELEPLii/FkjlsLWdwcpul4mczAoGAA54cvtjsB1/OQJC7fj8h
+pT25rnpack80uCAwEGwWuo3Llv9sAFBNpJu+VVF5g/rtkf/c1bi5vfTc4RYUjKpV
+MXVdWLpH6jHz+cqdRGOpv+Wlu0LiD9jA2u01S/ayBTIlWdPUSr2wW0MY4bsz0Ci+
+l/zz7KZ4Yk3n0PnZdpPcURECgYBw0nzHxjRHgBCns630lasaYRPf7V5rNy/maZwm
+k/srv7hK+XUyAGsCqEOovX/7H9f0ssXnbKkfiAfqCq8yAw1jIKCcmzeKZGfBOZc4
+VUCIxYyoBXVi886slvc9YGHwAUD5TRYkttFl9L4D9b3CgI3Tax83Pc8hwaYEMw5g
+I9zWWQKBgQCPLyginR+8N2i+QjZGUNm7iHljQNh2Ws1cABhuRdk1Py5l30SpxunV
++W5FPgJAWYeeozWcv/4XxUnsCQeCpG7gexEUnWjWzttc17fRRAN/s9EXzHf2b9r5
+SFjkgeZ85f+1CrYt7K4myurPWVS34ksaYj0PHf4ZkhsJ+JLK1lLCQw==
-----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 1a3bc137bd2..2d5ec769ea7 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: Aug 14 02:46:37 2014 GMT
- Not After : Aug 11 02:46:37 2024 GMT
+ Not Before: Feb 28 20:27:03 2016 GMT
+ Not After : Feb 25 20:27:03 2026 GMT
Subject: CN=Client Cert A
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:d5:df:ba:34:cb:c2:03:b5:37:7a:61:89:1a:b5:
- 1a:b9:27:7f:a9:2c:ba:a1:36:ac:83:6d:b8:45:9e:
- 35:82:a4:de:a3:69:38:25:84:57:00:8c:41:84:86:
- 6d:78:41:d4:10:99:1b:15:18:a6:04:2f:92:a0:1c:
- 29:c3:e0:5d:e2:90:11:2c:fa:ac:18:0d:fe:5e:8d:
- 5c:5a:01:4a:f7:2c:c9:6e:39:8e:14:30:d9:fc:f6:
- 6a:ee:9d:a3:ba:23:fe:5d:aa:2f:96:07:65:38:ca:
- a4:3c:d2:93:21:b0:b6:db:fb:40:12:00:01:99:30:
- 41:67:e2:2f:65:63:71:aa:a6:ef:45:23:05:8b:b4:
- 28:6c:35:bf:41:73:61:f1:9e:77:8c:a7:51:cf:c7:
- 51:63:c7:00:ab:4e:a3:e5:8f:fe:3c:45:fa:9e:d2:
- 29:bc:59:94:7d:14:c9:36:df:cd:0a:b5:9f:bf:ac:
- fd:1d:2b:6d:e5:13:30:14:71:de:77:df:83:f3:6d:
- 2c:cd:16:c0:a5:dc:f2:1f:65:86:37:91:2f:31:66:
- 7e:1a:4b:42:b7:29:e1:cd:1d:c9:72:0e:65:8e:a9:
- 4c:74:2e:90:b7:e0:91:0c:e8:fe:92:26:a7:17:9a:
- b6:25:7f:66:89:2f:bf:54:a7:51:4c:e6:8f:4d:34:
- a1:c3
+ 00:d1:bd:ac:fc:08:2f:dc:b2:1a:42:69:f2:68:e2:
+ 32:e4:1c:4a:01:a8:32:e1:76:01:5e:94:9a:00:89:
+ 05:32:22:ac:96:97:63:bb:60:73:e7:a4:91:fe:4e:
+ 04:7b:a1:e9:73:37:3b:7f:90:b4:5c:1f:cf:4c:fd:
+ 3b:33:07:ac:ea:c8:b4:c2:e1:aa:a6:bf:32:8b:d2:
+ 97:83:fe:32:f6:2d:60:6e:71:1d:16:5c:8b:e3:03:
+ 7c:e8:46:e1:7f:c7:ce:be:ad:81:f7:b4:76:fe:c6:
+ cd:8f:4a:cf:04:18:bf:c4:bf:eb:2c:fa:a4:f3:4c:
+ 61:27:db:a7:ee:18:d1:e4:37:0e:ad:3b:03:e9:73:
+ ea:3c:fb:05:2d:cd:ff:e4:02:d8:5a:9a:8f:9c:20:
+ 3b:36:ad:0f:a5:3f:bf:9a:2d:94:cb:79:4f:ea:e2:
+ 07:0b:ba:d9:73:70:ae:62:99:ec:79:c7:2d:a3:3e:
+ 4c:1e:ab:8f:24:8a:32:b4:90:8c:e5:d5:c3:e5:03:
+ 97:75:cf:b0:bc:8d:4e:74:3e:3f:57:f6:c4:03:25:
+ 33:77:da:3e:d4:61:18:ac:25:e7:98:40:5f:06:69:
+ a3:7c:49:ba:c3:23:ac:c7:80:ac:eb:44:bc:b1:0e:
+ df:ca:41:af:55:88:b7:97:00:d8:19:8b:e5:f1:f4:
+ a8:1f
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
- 6d:3e:c3:d4:c8:d1:fc:ec:0e:d3:ca:c8:4c:8d:fe:ab:51:fb:
- 1c:a4:f6:3c:13:07:76:58:7f:61:34:9c:b6:fd:9a:c5:7e:c7:
- b7:e0:89:fb:c5:67:76:75:ee:ab:d9:bf:fb:aa:3e:e9:5a:4a:
- c1:83:c3:c6:a0:01:8e:b1:f8:0d:08:9a:26:a7:b7:3c:19:b0:
- 76:77:57:03:c3:61:cf:56:7e:59:25:10:11:bb:4d:20:d5:49:
- 51:0d:c9:19:bb:50:4e:d1:f7:62:21:84:02:9b:9b:fa:ca:ef:
- de:7f:6c:a0:1e:f6:50:87:26:eb:2a:fd:e3:69:4b:12:10:9b:
- e3:f5:96:33:23:b5:06:31:42:26:8c:07:cc:0a:19:4a:a5:92:
- 44:a3:22:5a:69:ad:4a:96:61:b7:a8:6f:be:31:30:b2:1d:ee:
- 5a:21:87:a7:33:51:02:e4:24:86:ab:8e:aa:94:f4:25:6e:3f:
- 53:42:ce:12:91:99:23:52:1d:ba:df:59:11:0f:34:2e:8e:58:
- ac:df:6b:1a:08:a3:03:46:0f:c0:11:72:66:c4:e8:92:5a:20:
- 06:fe:e2:2b:e9:b3:9b:70:1a:b9:53:21:ad:d7:5f:a1:ab:26:
- 97:17:0b:ba:b0:8b:2d:db:0c:4e:ed:75:8b:72:46:b0:6b:23:
- 11:ba:1e:03
+ 45:11:56:e6:62:5f:b6:46:d3:70:ac:37:ed:44:31:75:bf:64:
+ 14:6d:c3:76:a2:e4:a7:40:31:f1:78:34:1d:4a:06:ac:2f:34:
+ f7:ba:2f:22:62:ed:11:c3:65:96:71:9d:03:57:97:b4:ce:d1:
+ 8f:85:6a:bb:00:ed:01:d7:6d:1a:15:13:0e:63:ee:3e:6f:3b:
+ bd:43:61:45:91:0a:9c:ef:f7:ca:4e:f4:c3:cc:82:48:e7:0a:
+ cc:9c:5b:d4:7f:3c:ef:c6:1d:ce:1d:63:18:4a:cf:f0:82:2a:
+ b7:de:14:ca:78:71:2a:e8:9c:a4:dd:bb:42:9f:2d:18:71:e7:
+ 32:73:7c:86:5c:7d:74:b2:2c:d4:7e:21:e5:86:f8:82:90:3b:
+ 84:4a:4f:26:14:3c:03:0f:3a:96:64:5d:08:8a:9c:c5:6c:40:
+ c7:a0:8c:4b:96:6d:c6:43:1a:62:2e:81:15:e2:4f:0a:60:9a:
+ 77:47:92:81:2c:5c:b1:33:a5:06:3f:3f:21:ef:69:88:3c:22:
+ 69:d9:1b:8a:31:88:05:f7:55:03:bd:5c:ef:9d:89:ba:4d:fb:
+ 1e:33:6f:9e:c0:a8:ab:0b:4d:06:3a:b6:7b:ac:47:05:be:dc:
+ 67:29:2a:98:7f:87:24:a9:f3:5d:49:4d:58:f9:14:42:d6:78:
+ 16:67:b2:21
-----BEGIN CERTIFICATE-----
MIIC0jCCAbqgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEQiBD
-QTAeFw0xNDA4MTQwMjQ2MzdaFw0yNDA4MTEwMjQ2MzdaMBgxFjAUBgNVBAMMDUNs
-aWVudCBDZXJ0IEEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDV37o0
-y8IDtTd6YYkatRq5J3+pLLqhNqyDbbhFnjWCpN6jaTglhFcAjEGEhm14QdQQmRsV
-GKYEL5KgHCnD4F3ikBEs+qwYDf5ejVxaAUr3LMluOY4UMNn89mrunaO6I/5dqi+W
-B2U4yqQ80pMhsLbb+0ASAAGZMEFn4i9lY3Gqpu9FIwWLtChsNb9Bc2HxnneMp1HP
-x1FjxwCrTqPlj/48Rfqe0im8WZR9FMk2380KtZ+/rP0dK23lEzAUcd5334PzbSzN
-FsCl3PIfZYY3kS8xZn4aS0K3KeHNHclyDmWOqUx0LpC34JEM6P6SJqcXmrYlf2aJ
-L79Up1FM5o9NNKHDAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
-KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBtPsPUyNH87A7T
-yshMjf6rUfscpPY8Ewd2WH9hNJy2/ZrFfse34In7xWd2de6r2b/7qj7pWkrBg8PG
-oAGOsfgNCJomp7c8GbB2d1cDw2HPVn5ZJRARu00g1UlRDckZu1BO0fdiIYQCm5v6
-yu/ef2ygHvZQhybrKv3jaUsSEJvj9ZYzI7UGMUImjAfMChlKpZJEoyJaaa1KlmG3
-qG++MTCyHe5aIYenM1EC5CSGq46qlPQlbj9TQs4SkZkjUh2631kRDzQujlis32sa
-CKMDRg/AEXJmxOiSWiAG/uIr6bObcBq5UyGt11+hqyaXFwu6sIst2wxO7XWLckaw
-ayMRuh4D
+QTAeFw0xNjAyMjgyMDI3MDNaFw0yNjAyMjUyMDI3MDNaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRvaz8
+CC/cshpCafJo4jLkHEoBqDLhdgFelJoAiQUyIqyWl2O7YHPnpJH+TgR7oelzNzt/
+kLRcH89M/TszB6zqyLTC4aqmvzKL0peD/jL2LWBucR0WXIvjA3zoRuF/x86+rYH3
+tHb+xs2PSs8EGL/Ev+ss+qTzTGEn26fuGNHkNw6tOwPpc+o8+wUtzf/kAthamo+c
+IDs2rQ+lP7+aLZTLeU/q4gcLutlzcK5imex5xy2jPkweq48kijK0kIzl1cPlA5d1
+z7C8jU50Pj9X9sQDJTN32j7UYRisJeeYQF8GaaN8SbrDI6zHgKzrRLyxDt/KQa9V
+iLeXANgZi+Xx9KgfAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
+KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBFEVbmYl+2RtNw
+rDftRDF1v2QUbcN2ouSnQDHxeDQdSgasLzT3ui8iYu0Rw2WWcZ0DV5e0ztGPhWq7
+AO0B120aFRMOY+4+bzu9Q2FFkQqc7/fKTvTDzIJI5wrMnFvUfzzvxh3OHWMYSs/w
+giq33hTKeHEq6Jyk3btCny0Ycecyc3yGXH10sizUfiHlhviCkDuESk8mFDwDDzqW
+ZF0IipzFbEDHoIxLlm3GQxpiLoEV4k8KYJp3R5KBLFyxM6UGPz8h72mIPCJp2RuK
+MYgF91UDvVzvnYm6TfseM2+ewKirC00GOrZ7rEcFvtxnKSqYf4ckqfNdSU1Y+RRC
+1ngWZ7Ih
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_1.pk8 b/chromium/net/data/ssl/certificates/client_1.pk8
index e6ae3ccef15..1b91cdebc3d 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 00cbca7410c..f610002ae89 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: Aug 14 02:46:37 2014 GMT
- Not After : Aug 11 02:46:37 2024 GMT
+ Not Before: Feb 28 20:27:03 2016 GMT
+ Not After : Feb 25 20:27:03 2026 GMT
Subject: CN=B CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:cd:08:8a:5d:c6:37:fe:01:86:d8:d6:78:68:78:
- a1:d8:60:e3:5c:8d:a7:2c:13:4c:29:08:f7:c8:24:
- ef:cc:64:7f:65:8c:f2:c6:b0:fe:40:4a:47:33:11:
- 17:f7:8d:2c:bc:e3:e7:15:fa:88:23:a2:35:81:3c:
- 8c:1e:55:9e:6e:87:ec:21:94:e5:ae:f3:aa:0c:dc:
- 9b:2b:d8:47:e6:4d:2e:98:be:8d:d8:81:0f:af:1b:
- 5e:4f:d8:a0:60:16:bd:ef:72:34:a8:01:5b:ad:b7:
- 0f:7f:43:46:6a:19:64:e5:f1:f4:3f:f3:a1:f1:ac:
- 97:cd:87:d9:d5:22:19:52:4c:43:9f:c7:6c:3c:6b:
- ae:3a:b3:1a:6f:8d:55:45:c3:34:e7:b7:83:97:ef:
- 39:d3:fa:29:90:4a:24:09:c1:e7:11:91:47:6e:13:
- 03:ad:b0:4a:5b:10:15:32:05:b7:e0:3b:95:b9:f5:
- 6d:38:0f:42:e5:96:17:9b:4b:e0:5f:37:ec:82:13:
- 4c:17:56:07:f5:2c:66:d5:f6:1e:27:c4:2a:a6:24:
- d4:bb:a0:68:61:81:45:73:29:d6:a9:bf:26:10:56:
- 0d:33:79:7e:12:70:02:ac:0a:6f:47:be:c2:53:84:
- 7d:a8:b2:31:a0:9a:84:6a:bf:5f:4e:b4:e3:12:f6:
- a9:a3
+ 00:bb:12:09:89:83:8a:9d:83:1a:48:c5:c7:0e:f2:
+ 93:3d:ba:25:28:c4:2e:49:7a:02:b9:58:8c:52:77:
+ 69:3f:d2:0a:1f:2a:6d:2e:20:96:7e:d1:1f:c0:8f:
+ 05:de:fc:a0:57:5f:84:82:90:af:0b:59:df:fa:b6:
+ d7:29:03:f4:10:12:de:a1:de:d9:87:5c:25:f9:bc:
+ fe:45:80:cb:90:ef:5e:4e:8d:5d:4e:2a:5f:7d:f8:
+ 2a:87:c1:00:4a:60:74:0f:e2:80:41:6a:d4:fd:65:
+ 1c:0b:88:7d:90:a9:31:17:d3:fa:2e:56:a2:15:6c:
+ 1a:2f:1f:fc:d8:29:46:f5:5a:30:e3:4b:35:f8:30:
+ e7:b9:b3:d6:56:ed:15:e0:44:21:29:97:d2:46:ec:
+ b8:9c:45:42:3f:c1:c2:18:b9:ff:41:c0:11:71:bc:
+ 7b:bc:cd:e1:c1:31:d3:23:d1:be:63:80:4d:17:55:
+ 6f:ff:1d:5b:6a:70:38:74:49:ab:d4:79:33:43:54:
+ 90:8b:13:4a:72:fb:e8:df:f3:f2:14:40:1c:cb:15:
+ dc:8b:9d:0b:96:1d:ec:65:d6:d4:01:ae:f5:af:a2:
+ 29:4f:90:e3:17:19:0a:88:f4:0c:2f:7d:b4:be:15:
+ 2a:e8:eb:57:59:00:7a:ab:0c:73:3e:7f:74:ac:e2:
+ eb:e7
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
- 1e:f6:59:47:12:4b:cd:64:8b:9d:4c:d5:57:aa:6e:ad:e9:1c:
- 3b:93:eb:c9:66:b2:9c:7e:fe:e1:c1:21:8e:47:5d:b4:fe:9b:
- 1e:80:6c:aa:85:ed:2e:29:0f:00:2b:ce:3b:f6:11:53:70:5d:
- ef:64:69:8c:3d:59:fd:46:84:a2:34:f1:f8:77:6d:8e:e5:2b:
- cf:10:6a:3a:30:92:35:71:81:7f:c4:a2:18:70:4d:30:82:d7:
- 6c:2c:eb:41:b9:8a:76:01:ee:f6:1c:ec:63:d8:f6:8e:3a:3b:
- 03:9d:68:f3:cf:8a:52:f9:64:5f:6a:b8:49:1c:eb:01:cf:f9:
- 7b:37:f0:79:07:fa:0c:aa:e9:fc:6b:7d:be:89:66:4d:38:50:
- 1c:c7:b9:99:56:7c:87:3b:5f:30:38:17:26:c7:63:f5:0e:17:
- 88:d2:80:a9:36:2e:e7:6c:17:2c:75:31:4c:fa:d8:7c:7f:0c:
- eb:54:51:71:e6:f9:bc:6a:8d:34:33:5d:2e:f7:f4:a0:99:78:
- 52:77:24:42:67:e3:98:d2:5a:a6:c4:3c:a8:65:58:41:85:53:
- bc:d1:c1:a4:8f:ef:c5:05:7d:06:8d:b9:e0:c0:34:b4:04:e0:
- 8c:2e:01:58:25:2a:57:f8:08:e1:70:ad:ed:ab:67:c2:8e:be:
- 7c:30:56:37
+ 82:1e:66:21:1e:36:15:96:43:c6:38:0f:e0:06:0f:0a:94:51:
+ e1:bc:36:30:9b:2a:b5:d0:06:51:e0:e7:06:7c:c5:fb:45:6a:
+ 23:f5:0e:9f:d4:01:ec:e6:c7:62:cd:6b:37:66:bb:0a:d8:07:
+ c9:66:dc:55:53:c9:a3:c3:4c:a1:06:20:f4:b8:c0:92:87:82:
+ a1:f5:40:f0:e1:a8:d9:bc:e5:ec:bb:4c:4b:48:f6:86:23:b0:
+ d8:a6:fd:16:fe:88:69:08:00:c5:da:c6:de:7c:4b:3c:5b:8e:
+ f3:f4:90:ca:f5:25:f2:48:65:b8:9c:f6:fc:9e:37:02:2c:a4:
+ c1:48:a4:fd:c5:07:cc:b0:ca:ed:13:d2:15:ad:09:08:0b:e0:
+ 9e:3b:9e:28:02:1e:93:ae:e7:c7:5e:3f:cf:1f:4b:f3:72:cf:
+ f7:f2:19:55:8e:67:be:9b:5a:15:b0:80:cd:cf:dd:7f:79:7d:
+ 0d:dd:ee:81:4f:47:f6:d5:87:46:15:f8:27:fc:eb:52:0d:c2:
+ 99:68:91:78:17:43:7f:d3:09:0f:87:35:77:80:31:69:f7:24:
+ b5:af:5c:5c:24:f2:8c:24:f5:da:bf:91:01:9d:9d:d1:a0:cb:
+ 72:93:11:6e:1c:b4:f5:f9:18:d8:5f:dc:b2:7d:43:b7:4b:8e:
+ 2e:11:79:0e
-----BEGIN CERTIFICATE-----
MIICwjCCAaqgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
-b290IENBMB4XDTE0MDgxNDAyNDYzN1oXDTI0MDgxMTAyNDYzN1owDzENMAsGA1UE
-AwwEQiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM0Iil3GN/4B
-htjWeGh4odhg41yNpywTTCkI98gk78xkf2WM8saw/kBKRzMRF/eNLLzj5xX6iCOi
-NYE8jB5Vnm6H7CGU5a7zqgzcmyvYR+ZNLpi+jdiBD68bXk/YoGAWve9yNKgBW623
-D39DRmoZZOXx9D/zofGsl82H2dUiGVJMQ5/HbDxrrjqzGm+NVUXDNOe3g5fvOdP6
-KZBKJAnB5xGRR24TA62wSlsQFTIFt+A7lbn1bTgPQuWWF5tL4F837IITTBdWB/Us
-ZtX2HifEKqYk1LugaGGBRXMp1qm/JhBWDTN5fhJwAqwKb0e+wlOEfaiyMaCahGq/
-X0604xL2qaMCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
-AQYwDQYJKoZIhvcNAQELBQADggEBAB72WUcSS81ki51M1Veqbq3pHDuT68lmspx+
-/uHBIY5HXbT+mx6AbKqF7S4pDwArzjv2EVNwXe9kaYw9Wf1GhKI08fh3bY7lK88Q
-ajowkjVxgX/EohhwTTCC12ws60G5inYB7vYc7GPY9o46OwOdaPPPilL5ZF9quEkc
-6wHP+Xs38HkH+gyq6fxrfb6JZk04UBzHuZlWfIc7XzA4FybHY/UOF4jSgKk2Luds
-Fyx1MUz62Hx/DOtUUXHm+bxqjTQzXS739KCZeFJ3JEJn45jSWqbEPKhlWEGFU7zR
-waSP78UFfQaNueDANLQE4IwuAVglKlf4COFwre2rZ8KOvnwwVjc=
+b290IENBMB4XDTE2MDIyODIwMjcwM1oXDTI2MDIyNTIwMjcwM1owDzENMAsGA1UE
+AwwEQiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALsSCYmDip2D
+GkjFxw7ykz26JSjELkl6ArlYjFJ3aT/SCh8qbS4gln7RH8CPBd78oFdfhIKQrwtZ
+3/q21ykD9BAS3qHe2YdcJfm8/kWAy5DvXk6NXU4qX334KofBAEpgdA/igEFq1P1l
+HAuIfZCpMRfT+i5WohVsGi8f/NgpRvVaMONLNfgw57mz1lbtFeBEISmX0kbsuJxF
+Qj/Bwhi5/0HAEXG8e7zN4cEx0yPRvmOATRdVb/8dW2pwOHRJq9R5M0NUkIsTSnL7
+6N/z8hRAHMsV3IudC5Yd7GXW1AGu9a+iKU+Q4xcZCoj0DC99tL4VKujrV1kAeqsM
+cz5/dKzi6+cCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAIIeZiEeNhWWQ8Y4D+AGDwqUUeG8NjCbKrXQ
+BlHg5wZ8xftFaiP1Dp/UAezmx2LNazdmuwrYB8lm3FVTyaPDTKEGIPS4wJKHgqH1
+QPDhqNm85ey7TEtI9oYjsNim/Rb+iGkIAMXaxt58SzxbjvP0kMr1JfJIZbic9vye
+NwIspMFIpP3FB8ywyu0T0hWtCQgL4J47nigCHpOu58deP88fS/Nyz/fyGVWOZ76b
+WhWwgM3P3X95fQ3d7oFPR/bVh0YV+Cf861INwplokXgXQ3/TCQ+HNXeAMWn3JLWv
+XFwk8owk9dq/kQGdndGgy3KTEW4ctPX5GNhf3LJ9Q7dLji4ReQ4=
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_2.key b/chromium/net/data/ssl/certificates/client_2.key
index 4c9f5cf6228..2b898f0c580 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-----
-MIIEpAIBAAKCAQEA57JEbvnvChDT62Y5CZOWQCI/5Lz7icpVIHGOBBiCpDYYhSY/
-iybARAKLjK/3q3IKjzNCn/FNEhRhaLNUV3JL/MVh9vxaNM4fBB725jKU9xHjgORh
-BsIMLKgkAp0cweboC/VDF2xHWUpvjQ+XT6xZEwLpkwKiFhWF2iC5hz8YeMrW4BVV
-5VvSYE3VYCTI/Lo8TgfK7qN8Mr+a4uIC54dld/vKPeBOSj/jxpinVjoXVELFrq8F
-9Ju4MObuOhwxNUtz1tN8TFJNH/gPFJfZ1ddn1te7pVLp0q1ojGEClY204TcMPzBk
-BU92SZxQ23alrdIttMPS0q0NZJrWz4W6DGEA4wIDAQABAoIBACIdu7njj3EZ/Tpi
-OO/SDYOwB1x0/0zQwCwgzFqKCWKInJ+ufBjPQexBu66hkoRqLGfdkmfergyFd7pk
-/XxK1imIHt6xVc8Essh2jsBinlCrD6bA+hB2rjg9IeBIph1fFLf+Czz9spvRPA+3
-Rf5zUEJeYWpGLvu1e5ocy3TAs6fFXpE9i1Jd5ec8BUYjXFCvdkBbIpTeW+sfI2cV
-+1Qeu22w2hHcRQFU9ViKVv151BUEf5IcApleCQrkJ06vq0XhZKE0KTIqp5NO8sNj
-TKsyicZ48b2CcVzaDl3LJEdJsN5mU0GtRg+DbTwZY17b0coOHaHJjlsU432lGFEe
-xOtOqMECgYEA+un7R8U/J1dbHUWL2pRnO2o6gyHcr0mZNQCN9rsrGV+5DzlSsdTA
-rKWS6Ykp4/UYJeozomnCOxvrx7HajfJVZ2xUBZOFQx7gHudJbypZ4RSeMcP11xB+
-zxC2k1ru2dQffbB8cYNlYpeFRhG9Wq6ygJeXgIBLrERHiZIPUFOAHjECgYEA7GSQ
-QFHY2qZsXYgJgZYeSwPq6hnlf+LBT3zz5bRKe2kPHMhuO0Tlz0G2wIMG7WuRAiwP
-c73Ed5euh+wwm4b2aAeUJTe3nGO2auOOMI8tzxoD1tqe1z9OS5lxm8kUUdflsUG0
-Ad+FP7FHEqJFWKKzcsD7Swk8HkKjQna8PCTp51MCgYEAyJ4se8YKKLp/73ebyri9
-kZPuFMsOWFjQVsCKwawFWdRfcvyyUd158JCyVmeFRu7A0A/iGQnWcsxwSMq7pKMO
-BhNnWs4IzxHwwMTMwkVqd7y0f7Xe6oYV3hnO4SLjtucUBrsFxPz6I0pjFRM6AzeL
-IaYTTHtIBgTR7f0KoX8iAQECgYAkUL6oYuqBjJeRNtjfA4Tb2Vo5ZIkRQHCaGYQO
-gcf/dYBQ16m3iToUwO+mW3qw9plsUAB/s2N/S9oQH4TIH8+y45cqsIiQifD4MsUh
-SJ2s9z4nv6YvQxZwHr6JRDbO6+/pb0KMFx6NTlqwziUBHN2cf3Ebceu+alZSW5NH
-WhRk6QKBgQCfY1Qs+l5ChPH9vsyCeIARw1m3oYmwXbIqVCMqEnG2HcZEMuWtiS+G
-cJTk+zB4N4Yt+k+41e+Nithaom5S61x54TF42dNFKrzXISm+u0RSt5uvNZBLdyqd
-/LB99iIESAHP0Bs5Y6Wxr2pzJswZGOEcxdu3aQGyL+BSo5XOm2l1vw==
+MIIEogIBAAKCAQEAzCwk5vzkVe8k+mJANot7xnoPsDl6LrCua/6yW3Zub4gORzVg
+85JV5hniNGixW+rRKpd4FYG0rUDmZA/lXa2Paw94PqWIU9+xg7C6i2iSR6uEHMo7
+E/Fa0wasup8Ja13LlT/CPPVYhGlb/6fbiZfWWBAMAonnVIGtV6S6R/QTNb9Nl/Z8
+u45JWjGeopWyHHt6FB2fZFmZAALl2CHYM5CsbZUY+NIkrm5F0eTin0xc4t2L/zuB
+iYRom+vPA8vlfVAAOtyVplC3+PSkVJqXn8YQ31QkYrfpaefm6i3hfJnVkCYlpbBm
+9Aux4+WcLTh5MMsYXCh42pv2lBA6ho+TG75uMwIDAQABAoIBAB18rqOxmGSU0jlb
+ITz/bhPfIw7nbi76E2bDdQzikNaIxs8f9W2YD9HYoSPCjwLgae8FyzEH94kiG2QO
+K6kY3OKwbERX8dVzNBb52icyJhY1vjHOPzQFIoHhr+aP+3NHK5TVjX7yTCNrd/73
+RiycAjfbsXBYbFF3HQrQXprvtCqJwVeH2YP33uznn6zjxfNcpVmv2D8EE431M7S7
+3eC9TT5q3b78hJcm6N4nbVFAA1E/zZuVTqJ5xuiBKPG03FqwpVmmOeKX3BU57EXy
+iDxXFxdiAen/eEwEoUuBuTGWtTUpUfvv8JyibM6FYuQYxggP7szgnvkDVriK1vZ0
+krMskhkCgYEA7xxeT2+qd1BpEBOUcGVMPJlSlFNmyH5vg/GSfbY8BWYKU6YQ2wca
+dkhk9q+OGgMUMZjdxMtrFFhICxn4QUmpPPGX2QRKALgthkSZc7B0PacgL45SHa10
+2mJbeX3e7zjUtjb0Jk6CIFQ1CRE9TS+0/+3ZlakSfm6tuIcaqIGxB8UCgYEA2pgE
+AxunlvJRnY5KICxxusCfja4VOtql6zFpHpdRaELMkl7kWiJZyZyx8iOVWc2Nt+QV
+PtFKi1nzn3wTQR0YHaRtq+w5HPl7UXSSDabMOmsMda53o47gjcjXqVUKLhmw03/i
+ng0uOAmBGJLA76qy+MqAAkfJy1iK5wKwF1E8BZcCgYA+Jfd1WibKgEHuhchNNmcM
+USWfm9XZQtOlTcKvnhAXrx/8AevbogsEt2hWneanaCl1grARmHWqgg+nowZdodG1
+H25CX9UEPtrGTUo9QZ3U8H1zHuDFCfKXWH1CJK8vKmxPOBVZZ4p28KwgQTTXvRCk
+fKPTPHCsIARTM/p/1cW3qQKBgGuGLSsONmCkr4rNzB6JXiQbziAWCnFZzhWjx255
+xlx/xzsUnETN8taeUlWmNTfoSZa0BdNRhdaIF7NSh/IWip9CG4Re/TUIbyWBLrqy
+WnE96PIWMNluVXzI13R+1TQaBQX0ORe/qgV8f1kEDw2VLNX+XftBLrzsv96kTtQZ
+bGnfAoGAHrVqcFGCpO/0tVOm6sy6jOahQhKkN0Qz8V5pbGt87M0WX1CtkrXgk6zh
+k3Ej9wRLvsyWuJfcLl7b7j6T234Y9GcfCO11ohd9T+3201ixMyjKnRkJOFM/s7VJ
+9Y7EWGHTwQJBIrRBcMeCujTQDKCLzYLghsYo738O/edxDQwVHck=
-----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 cae5fd42f8a..dc3221659b5 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: Aug 14 02:46:37 2014 GMT
- Not After : Aug 11 02:46:37 2024 GMT
+ Not Before: Feb 28 20:27:03 2016 GMT
+ Not After : Feb 25 20:27:03 2026 GMT
Subject: CN=Client Cert D
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:e7:b2:44:6e:f9:ef:0a:10:d3:eb:66:39:09:93:
- 96:40:22:3f:e4:bc:fb:89:ca:55:20:71:8e:04:18:
- 82:a4:36:18:85:26:3f:8b:26:c0:44:02:8b:8c:af:
- f7:ab:72:0a:8f:33:42:9f:f1:4d:12:14:61:68:b3:
- 54:57:72:4b:fc:c5:61:f6:fc:5a:34:ce:1f:04:1e:
- f6:e6:32:94:f7:11:e3:80:e4:61:06:c2:0c:2c:a8:
- 24:02:9d:1c:c1:e6:e8:0b:f5:43:17:6c:47:59:4a:
- 6f:8d:0f:97:4f:ac:59:13:02:e9:93:02:a2:16:15:
- 85:da:20:b9:87:3f:18:78:ca:d6:e0:15:55:e5:5b:
- d2:60:4d:d5:60:24:c8:fc:ba:3c:4e:07:ca:ee:a3:
- 7c:32:bf:9a:e2:e2:02:e7:87:65:77:fb:ca:3d:e0:
- 4e:4a:3f:e3:c6:98:a7:56:3a:17:54:42:c5:ae:af:
- 05:f4:9b:b8:30:e6:ee:3a:1c:31:35:4b:73:d6:d3:
- 7c:4c:52:4d:1f:f8:0f:14:97:d9:d5:d7:67:d6:d7:
- bb:a5:52:e9:d2:ad:68:8c:61:02:95:8d:b4:e1:37:
- 0c:3f:30:64:05:4f:76:49:9c:50:db:76:a5:ad:d2:
- 2d:b4:c3:d2:d2:ad:0d:64:9a:d6:cf:85:ba:0c:61:
- 00:e3
+ 00:cc:2c:24:e6:fc:e4:55:ef:24:fa:62:40:36:8b:
+ 7b:c6:7a:0f:b0:39:7a:2e:b0:ae:6b:fe:b2:5b:76:
+ 6e:6f:88:0e:47:35:60:f3:92:55:e6:19:e2:34:68:
+ b1:5b:ea:d1:2a:97:78:15:81:b4:ad:40:e6:64:0f:
+ e5:5d:ad:8f:6b:0f:78:3e:a5:88:53:df:b1:83:b0:
+ ba:8b:68:92:47:ab:84:1c:ca:3b:13:f1:5a:d3:06:
+ ac:ba:9f:09:6b:5d:cb:95:3f:c2:3c:f5:58:84:69:
+ 5b:ff:a7:db:89:97:d6:58:10:0c:02:89:e7:54:81:
+ ad:57:a4:ba:47:f4:13:35:bf:4d:97:f6:7c:bb:8e:
+ 49:5a:31:9e:a2:95:b2:1c:7b:7a:14:1d:9f:64:59:
+ 99:00:02:e5:d8:21:d8:33:90:ac:6d:95:18:f8:d2:
+ 24:ae:6e:45:d1:e4:e2:9f:4c:5c:e2:dd:8b:ff:3b:
+ 81:89:84:68:9b:eb:cf:03:cb:e5:7d:50:00:3a:dc:
+ 95:a6:50:b7:f8:f4:a4:54:9a:97:9f:c6:10:df:54:
+ 24:62:b7:e9:69:e7:e6:ea:2d:e1:7c:99:d5:90:26:
+ 25:a5:b0:66:f4:0b:b1:e3:e5:9c:2d:38:79:30:cb:
+ 18:5c:28:78:da:9b:f6:94:10:3a:86:8f:93:1b:be:
+ 6e:33
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
- ce:8a:6b:a8:70:1a:a3:bb:54:2b:78:29:84:b3:08:fa:4f:0a:
- 98:cd:10:1e:04:05:2d:e9:0d:d0:84:c1:49:21:74:30:2d:7e:
- fe:ec:69:a6:6c:5a:a1:7e:17:d1:b3:84:8c:a0:c1:88:c6:45:
- a6:26:82:ae:a6:54:ed:c2:80:49:e2:e1:94:06:02:42:bf:8d:
- 9a:c2:bc:0c:1e:4a:02:74:b0:7e:90:04:23:c2:12:52:14:e8:
- c5:b2:b8:ef:77:7e:6b:ac:a0:cc:68:a8:02:2d:a6:6a:d2:17:
- 7f:bd:14:21:8b:e3:07:02:cd:7f:e2:01:63:fa:e1:fd:9a:43:
- f9:81:52:56:7f:d2:42:71:ad:90:fe:b4:e3:ee:f9:76:14:86:
- 4e:4b:9b:7f:94:51:c8:5c:ce:56:5d:c5:ee:2d:b4:e4:d1:15:
- d8:49:59:4f:12:d8:5e:ad:8f:9e:50:ab:61:18:0d:df:bc:56:
- f3:75:89:1b:0f:19:df:2d:6e:81:85:dc:c7:28:6a:4b:70:6d:
- 85:8c:9d:7d:e1:5d:62:bb:47:18:dc:e8:83:c3:27:af:5b:ec:
- 58:07:95:e9:e4:9f:94:b4:2a:4a:67:aa:d7:57:37:1b:21:07:
- 11:d5:4e:ca:1e:72:8c:43:fe:cf:b9:ea:68:ea:5d:d7:d3:32:
- fb:8a:29:f6
+ a0:17:a0:22:a1:59:44:4f:64:6f:0a:1a:f3:a9:69:82:50:60:
+ 24:94:46:56:88:88:72:82:5f:d9:aa:bc:78:36:85:a2:90:d9:
+ 38:d3:32:26:93:f3:82:ca:9b:b6:f9:2d:1b:ef:8d:d2:5b:84:
+ 68:73:9e:ef:d2:03:71:ff:90:ac:47:e5:9b:e2:a4:12:20:f5:
+ 69:29:7d:90:4a:80:93:b6:38:66:dd:93:51:ac:29:13:96:3c:
+ 5d:3d:84:70:46:81:2f:ab:90:ec:e1:1c:23:a3:45:dc:95:71:
+ 73:6e:33:08:fb:02:05:a3:7e:d4:bd:a1:b7:06:07:a3:19:0a:
+ 35:b7:a2:a9:e1:45:56:9f:e0:23:35:34:f4:bb:e7:78:f7:be:
+ 1b:07:cb:58:c7:8d:f5:16:41:d9:66:07:a2:16:29:a1:e7:ed:
+ 7b:dd:38:9b:74:2f:3a:44:d4:df:46:ef:59:ef:1f:15:43:78:
+ 6f:36:fb:a4:3d:88:0b:e4:db:af:f7:ec:3a:66:4c:72:9e:f3:
+ d1:e4:27:a5:a9:ba:19:69:26:d6:2f:97:f0:35:0b:75:14:70:
+ 19:53:a4:c3:19:31:0b:19:ad:36:59:d0:51:26:2c:f9:88:a2:
+ 82:9b:ad:67:bd:94:f8:af:50:f1:56:47:df:c9:27:dc:bf:af:
+ 77:b8:de:75
-----BEGIN CERTIFICATE-----
MIIC0jCCAbqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwERSBD
-QTAeFw0xNDA4MTQwMjQ2MzdaFw0yNDA4MTEwMjQ2MzdaMBgxFjAUBgNVBAMMDUNs
-aWVudCBDZXJ0IEQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnskRu
-+e8KENPrZjkJk5ZAIj/kvPuJylUgcY4EGIKkNhiFJj+LJsBEAouMr/ercgqPM0Kf
-8U0SFGFos1RXckv8xWH2/Fo0zh8EHvbmMpT3EeOA5GEGwgwsqCQCnRzB5ugL9UMX
-bEdZSm+ND5dPrFkTAumTAqIWFYXaILmHPxh4ytbgFVXlW9JgTdVgJMj8ujxOB8ru
-o3wyv5ri4gLnh2V3+8o94E5KP+PGmKdWOhdUQsWurwX0m7gw5u46HDE1S3PW03xM
-Uk0f+A8Ul9nV12fW17ulUunSrWiMYQKVjbThNww/MGQFT3ZJnFDbdqWt0i20w9LS
-rQ1kmtbPhboMYQDjAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
-KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQDOimuocBqju1Qr
-eCmEswj6TwqYzRAeBAUt6Q3QhMFJIXQwLX7+7GmmbFqhfhfRs4SMoMGIxkWmJoKu
-plTtwoBJ4uGUBgJCv42awrwMHkoCdLB+kAQjwhJSFOjFsrjvd35rrKDMaKgCLaZq
-0hd/vRQhi+MHAs1/4gFj+uH9mkP5gVJWf9JCca2Q/rTj7vl2FIZOS5t/lFHIXM5W
-XcXuLbTk0RXYSVlPEtherY+eUKthGA3fvFbzdYkbDxnfLW6BhdzHKGpLcG2FjJ19
-4V1iu0cY3OiDwyevW+xYB5Xp5J+UtCpKZ6rXVzcbIQcR1U7KHnKMQ/7Puepo6l3X
-0zL7iin2
+QTAeFw0xNjAyMjgyMDI3MDNaFw0yNjAyMjUyMDI3MDNaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMLCTm
+/ORV7yT6YkA2i3vGeg+wOXousK5r/rJbdm5viA5HNWDzklXmGeI0aLFb6tEql3gV
+gbStQOZkD+VdrY9rD3g+pYhT37GDsLqLaJJHq4QcyjsT8VrTBqy6nwlrXcuVP8I8
+9ViEaVv/p9uJl9ZYEAwCiedUga1XpLpH9BM1v02X9ny7jklaMZ6ilbIce3oUHZ9k
+WZkAAuXYIdgzkKxtlRj40iSubkXR5OKfTFzi3Yv/O4GJhGib688Dy+V9UAA63JWm
+ULf49KRUmpefxhDfVCRit+lp5+bqLeF8mdWQJiWlsGb0C7Hj5ZwtOHkwyxhcKHja
+m/aUEDqGj5Mbvm4zAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
+KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCgF6AioVlET2Rv
+ChrzqWmCUGAklEZWiIhygl/Zqrx4NoWikNk40zImk/OCypu2+S0b743SW4Roc57v
+0gNx/5CsR+Wb4qQSIPVpKX2QSoCTtjhm3ZNRrCkTljxdPYRwRoEvq5Ds4Rwjo0Xc
+lXFzbjMI+wIFo37UvaG3BgejGQo1t6Kp4UVWn+AjNTT0u+d4974bB8tYx431FkHZ
+ZgeiFimh5+173TibdC86RNTfRu9Z7x8VQ3hvNvukPYgL5Nuv9+w6ZkxynvPR5Cel
+qboZaSbWL5fwNQt1FHAZU6TDGTELGa02WdBRJiz5iKKCm61nvZT4r1DxVkffySfc
+v693uN51
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_2.pk8 b/chromium/net/data/ssl/certificates/client_2.pk8
index 8affacd9357..9e433662596 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 70f10c4c38e..8753ac47571 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: Aug 14 02:46:37 2014 GMT
- Not After : Aug 11 02:46:37 2024 GMT
+ Not Before: Feb 28 20:27:03 2016 GMT
+ Not After : Feb 25 20:27:03 2026 GMT
Subject: CN=E CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:d5:07:2a:a9:ae:d5:c6:94:64:6f:84:5c:50:8c:
- de:f4:7a:81:ce:1b:0c:5a:d5:e7:96:9b:84:3f:67:
- 04:c8:49:0f:50:70:ad:a3:c6:39:39:fe:bb:e1:95:
- d0:3f:9a:4a:e7:67:0c:97:ae:ba:77:c8:d2:58:d9:
- 26:37:d3:29:37:c2:ec:60:41:1d:00:05:38:3a:75:
- 9c:93:e2:71:e1:eb:60:aa:a2:c6:18:74:9d:42:e6:
- c4:42:b2:87:4a:6c:51:37:54:a1:da:4b:7f:14:ab:
- a1:bc:e6:21:d1:fa:d6:bf:08:8c:17:54:13:86:27:
- e4:6a:fe:10:f0:96:e9:45:a8:ed:45:28:4c:50:1f:
- 45:25:c9:88:54:a2:27:31:4d:8b:55:e4:82:59:29:
- 76:35:4d:92:91:8d:38:cf:b2:48:dc:45:fe:b0:0c:
- 14:eb:9c:40:55:d7:7f:79:17:b5:07:33:81:db:a5:
- 84:61:13:ad:cb:07:02:50:82:5a:d9:14:60:4a:ec:
- 79:95:7e:ba:75:73:45:2a:07:ab:3d:77:a2:6a:08:
- 18:a4:43:24:e1:6d:27:69:ef:a4:b8:d7:40:68:08:
- 4f:24:87:5b:64:8e:f5:ab:a0:88:14:70:b9:80:5f:
- 6a:1f:a4:d6:78:3c:24:99:44:65:b2:3a:0c:8d:04:
- 54:05
+ 00:ba:41:e9:51:55:de:d0:9a:a9:ef:4c:fc:04:a4:
+ 26:76:de:1d:5a:fa:84:f9:a4:37:91:85:0b:92:d5:
+ 53:de:bd:77:ec:8b:b7:20:d1:db:26:63:4b:91:4a:
+ d3:93:3a:1a:1e:50:eb:02:fd:6a:c8:6d:14:72:b8:
+ c4:de:5c:4a:74:93:0e:ac:06:d3:5b:f8:f9:19:cd:
+ 0a:6f:3c:90:ec:7d:f8:43:9d:66:35:9a:58:e6:c2:
+ 8d:10:6c:94:79:e5:b3:fa:f6:98:de:50:8e:c0:b7:
+ 01:33:12:43:4c:52:57:ad:c8:0c:b1:62:e0:ae:89:
+ d8:ad:d4:94:d9:78:f3:b5:0d:13:3e:64:55:73:83:
+ 8b:2c:f6:6c:8c:9a:51:85:9e:cc:33:5d:aa:b0:1d:
+ 94:29:d7:7b:ed:b7:77:2c:53:a3:05:83:c2:69:c9:
+ 2d:ad:ce:76:62:d6:df:4e:e7:75:cb:19:2d:a8:e2:
+ 18:75:08:57:d1:a9:2a:29:68:70:02:8c:03:a3:00:
+ 22:37:d5:c0:7d:a2:a7:40:ce:2c:79:58:52:06:1f:
+ 7a:61:b7:ce:e7:c2:83:dd:6d:cc:0a:64:17:27:cb:
+ 21:56:38:c2:db:a0:ac:fd:18:b5:15:01:f5:50:25:
+ 96:b7:91:ab:51:42:47:8c:fc:df:6a:54:f9:ea:49:
+ a6:75
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
- 1f:db:57:30:59:e1:e7:4a:2d:2f:d8:06:9e:d1:e5:f7:36:cc:
- 68:13:1e:6c:83:56:d3:31:e1:d4:02:87:29:3e:90:aa:62:1b:
- 26:1e:cd:a6:d2:72:8e:40:87:c4:72:f0:ad:7e:e9:5f:94:96:
- 84:5e:06:71:e4:bb:0e:45:48:04:47:06:cf:10:b5:08:28:a5:
- 95:96:23:67:2a:cb:8a:7c:20:80:26:f4:12:c1:34:54:2b:36:
- 81:0b:37:a8:50:f8:6b:a5:59:ba:1f:94:f8:ed:83:95:90:e9:
- 68:bb:ef:dd:85:79:fd:8d:94:51:5a:10:83:aa:c2:68:56:ed:
- 22:90:23:f5:4c:a7:6e:6b:db:3f:7f:c1:74:54:ba:33:30:f1:
- cb:da:02:c2:bd:39:7c:bb:63:38:d0:e8:e1:81:bc:eb:3b:47:
- a4:66:67:74:ab:0c:a6:ae:e6:b5:ac:4c:a0:5d:df:4b:cf:e4:
- 68:72:6f:e2:53:e8:1d:74:d4:d5:91:d4:58:9b:c3:ce:3a:22:
- 17:06:ea:82:09:4d:d9:97:a5:09:a3:91:70:52:08:bb:21:7c:
- 81:e2:3d:ee:6e:0c:ad:6c:f6:21:35:3b:f5:d6:d6:67:40:33:
- 47:36:25:24:d7:9b:02:a5:b2:da:59:cd:a6:26:b0:9f:72:e8:
- 44:3a:fb:50
+ 63:37:df:42:58:b0:4e:d1:0e:88:99:d0:c8:a0:9f:21:f6:13:
+ 6a:c1:bb:8b:59:01:76:6e:01:1d:37:cb:b9:12:de:0d:78:49:
+ b8:26:26:6b:9c:32:83:7d:39:bc:e3:f8:55:6b:cc:12:59:b0:
+ 11:b4:70:4c:14:99:34:e5:19:ab:d2:ff:5a:41:14:99:f6:d1:
+ 03:f7:28:1c:22:56:06:ef:10:ac:e0:be:45:47:c1:f5:6b:d1:
+ e9:78:3a:88:4f:37:db:c5:2d:a6:95:3a:ff:84:9f:78:fc:2f:
+ b8:7e:b8:e4:94:69:c9:9c:26:f5:29:2f:81:9a:a0:26:82:65:
+ 50:93:63:54:71:fe:d6:d0:90:47:1d:f3:28:bc:8f:5a:e7:6e:
+ 54:8a:2f:5f:e8:4a:40:77:e6:cf:46:e9:4a:da:d2:7f:70:86:
+ 56:6f:10:17:7b:f1:d0:1d:d2:3d:b1:de:7c:5f:bd:fe:50:3d:
+ 13:cf:5f:43:c7:d0:10:60:b9:eb:cb:55:de:60:1a:c7:b6:50:
+ 37:ea:9e:cf:18:28:b0:df:c7:0e:ae:08:5a:21:25:02:c3:08:
+ ca:1c:3e:b1:9f:bb:72:15:f6:5e:0a:32:bf:03:c7:05:e6:20:
+ 5c:82:df:9f:9e:39:dc:86:45:f3:65:cc:f7:8c:48:08:53:a2:
+ 73:b3:e7:5d
-----BEGIN CERTIFICATE-----
MIICwjCCAaqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
-b290IENBMB4XDTE0MDgxNDAyNDYzN1oXDTI0MDgxMTAyNDYzN1owDzENMAsGA1UE
-AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANUHKqmu1caU
-ZG+EXFCM3vR6gc4bDFrV55abhD9nBMhJD1BwraPGOTn+u+GV0D+aSudnDJeuunfI
-0ljZJjfTKTfC7GBBHQAFODp1nJPiceHrYKqixhh0nULmxEKyh0psUTdUodpLfxSr
-obzmIdH61r8IjBdUE4Yn5Gr+EPCW6UWo7UUoTFAfRSXJiFSiJzFNi1XkglkpdjVN
-kpGNOM+ySNxF/rAMFOucQFXXf3kXtQczgdulhGETrcsHAlCCWtkUYErseZV+unVz
-RSoHqz13omoIGKRDJOFtJ2nvpLjXQGgITySHW2SO9augiBRwuYBfah+k1ng8JJlE
-ZbI6DI0EVAUCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
-AQYwDQYJKoZIhvcNAQELBQADggEBAB/bVzBZ4edKLS/YBp7R5fc2zGgTHmyDVtMx
-4dQChyk+kKpiGyYezabSco5Ah8Ry8K1+6V+UloReBnHkuw5FSARHBs8QtQgopZWW
-I2cqy4p8IIAm9BLBNFQrNoELN6hQ+GulWboflPjtg5WQ6Wi7792Fef2NlFFaEIOq
-wmhW7SKQI/VMp25r2z9/wXRUujMw8cvaAsK9OXy7YzjQ6OGBvOs7R6RmZ3SrDKau
-5rWsTKBd30vP5Ghyb+JT6B101NWR1Fibw846IhcG6oIJTdmXpQmjkXBSCLshfIHi
-Pe5uDK1s9iE1O/XW1mdAM0c2JSTXmwKlstpZzaYmsJ9y6EQ6+1A=
+b290IENBMB4XDTE2MDIyODIwMjcwM1oXDTI2MDIyNTIwMjcwM1owDzENMAsGA1UE
+AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpB6VFV3tCa
+qe9M/ASkJnbeHVr6hPmkN5GFC5LVU969d+yLtyDR2yZjS5FK05M6Gh5Q6wL9asht
+FHK4xN5cSnSTDqwG01v4+RnNCm88kOx9+EOdZjWaWObCjRBslHnls/r2mN5QjsC3
+ATMSQ0xSV63IDLFi4K6J2K3UlNl487UNEz5kVXODiyz2bIyaUYWezDNdqrAdlCnX
+e+23dyxTowWDwmnJLa3OdmLW307ndcsZLajiGHUIV9GpKilocAKMA6MAIjfVwH2i
+p0DOLHlYUgYfemG3zufCg91tzApkFyfLIVY4wtugrP0YtRUB9VAllreRq1FCR4z8
+32pU+epJpnUCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAGM330JYsE7RDoiZ0MignyH2E2rBu4tZAXZu
+AR03y7kS3g14SbgmJmucMoN9Obzj+FVrzBJZsBG0cEwUmTTlGavS/1pBFJn20QP3
+KBwiVgbvEKzgvkVHwfVr0el4OohPN9vFLaaVOv+En3j8L7h+uOSUacmcJvUpL4Ga
+oCaCZVCTY1Rx/tbQkEcd8yi8j1rnblSKL1/oSkB35s9G6Ura0n9whlZvEBd78dAd
+0j2x3nxfvf5QPRPPX0PH0BBguevLVd5gGse2UDfqns8YKLDfxw6uCFohJQLDCMoc
+PrGfu3IV9l4KMr8DxwXmIFyC35+eOdyGRfNlzPeMSAhTonOz510=
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_3.key b/chromium/net/data/ssl/certificates/client_3.key
new file mode 100644
index 00000000000..959067c2b77
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client_3.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpgIBAAKCAQEA6z9ms1VvYWgj200gTpdKD9ufjPjNp+KddsNAURQzKKXli1Wb
+RetHQ5NRlZFhBVWKvY0BNCprl12FYZm4a9huxYbM4nlfUJFMDTtxgUAZbpPmaEPe
+u+tNRtpLJZ3hhVdokoXiPiS8MNF5jeY+ouZK1kpJByjr7S+5N/DDssBkSuFVjEUW
+8Gy7cxEPsTADkAvef92W/LDWwMH9cPXmc0aBTZuG2eisyZGb3OfEQ7cO48gShxaH
+eRui0XP8/F7zNkBFo836DEB0j3UVAo4njEG5JNSAAXAx+NVVJI9G4YInch9mbopm
+jR9uTs/KBft9STgwL+9eI/+gIONYhFmkmuUY/wIDAQABAoIBAQC0i/JMTJOxFHYA
+h472AlLLHOm1Dfb4lIn5bhzcnT4uQjSL3WXQIaSODnCc8/icWWyj0aZM3Qm6IAKQ
+R6Qs0O0jGDQC1Nf8Q6c0uJyCcCmUnlpFR2GYpByo9jyaYDOHXPBbE/nxa8wrQ3mh
+GEaWS1zAXj7yCcwYO3pRnqzzcYkHlbRlARbRZir6xzNaqYCokU7O4Euh1h37zIc3
+QEwxbHBTDUDzVAXKDKa+srjUbtSkByp8nWPTPDW63IRMnbEsFHHTdM2tGzQgIXjC
+69iVGfbl2Mrc5+RmmBfnIvzyGnO71ywiC6J4Ncgg5X+ukbskkFhpMfhk8XZMdeW+
+Uw4rGbXBAoGBAP3UxsuE4Og31TR5EqObZWVymRVm9CEKc5uNiyrsBYkPWXwMtw7X
+U6s9N0E4iWOc7m57b0PGnD39hXEWxF5kAzttgvYZLnc2/SF8aRJvd8hy/gKcA7xm
+6OmNEfGEunHLyCOgTzr4hicZ5GWFkZV1GaBiYTDPOQlk1A79/LWtOUJRAoGBAO1B
++cAdDGDCjpKpYDShz6GN8Fx7ByG+7OuYcD4MlFb25yvZ0kgnjIKZRODHfNFsrXMf
+8QBTx13zjC187ghWY3Jtt15fecWWKuOhzyatWlgeHfHzeO62NdddP8S4AAr2FMUL
+P0pNbwrZmkVCyn+sE5Vc+u9lPIfIFJwmPEu+JQJPAoGBAJOJsscnBEdV9KIcYZ4h
+O+2cj6hmAC6YUZwvyJ15NLp25o95IIoK1MIqwcwyHYF9/QTQ0Fp3vec2TfLuxdML
+lOlc/Qsold6LYtSs6LHjgp9LX6OKpY1Dz8u4yJ42hNySE1HJ42OmguuFXEE6QuW5
+e9zCcjWZrVBtf+j67oF3H1oRAoGBAIdWgyjbaRwo3zs58u8S/mWhmeKnK0JMrskV
+g7Fha5zP6r5Q2mreZIB6/ZdbNBAidi6dodQV9jvZmbS49u86mC/F9juXKtdS+dQv
+kQL3D/oD9AD4aZuBxOS9BIsqipu2E9Lyv3+a/CSsTBwGJYz+k404JMw6a3To5RjN
+lsd+B45xAoGBAIFolC7ah49Skdfc0od0+FjxlCvwXqmubA/U8yvAYixlXSPIwsi+
+HelE1wjigyzpfm/UGMU5FnnD53ZN/uTTA0GMmnEQl11DwIQ0fIhnD0o/a5wRw5o5
+zCPydEt/BvXAoLB5bVqwY0pHO9b/Zb1R5RW4NCk13zM9mamMnsBJTYIU
+-----END RSA PRIVATE KEY-----
diff --git a/chromium/net/data/ssl/certificates/client_3.pem b/chromium/net/data/ssl/certificates/client_3.pem
new file mode 100644
index 00000000000..0a2a46b90e7
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client_3.pem
@@ -0,0 +1,70 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4099 (0x1003)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=E CA
+ Validity
+ Not Before: Feb 28 20:27:03 2016 GMT
+ Not After : Feb 25 20:27:03 2026 GMT
+ Subject: CN=Client Cert F
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:eb:3f:66:b3:55:6f:61:68:23:db:4d:20:4e:97:
+ 4a:0f:db:9f:8c:f8:cd:a7:e2:9d:76:c3:40:51:14:
+ 33:28:a5:e5:8b:55:9b:45:eb:47:43:93:51:95:91:
+ 61:05:55:8a:bd:8d:01:34:2a:6b:97:5d:85:61:99:
+ b8:6b:d8:6e:c5:86:cc:e2:79:5f:50:91:4c:0d:3b:
+ 71:81:40:19:6e:93:e6:68:43:de:bb:eb:4d:46:da:
+ 4b:25:9d:e1:85:57:68:92:85:e2:3e:24:bc:30:d1:
+ 79:8d:e6:3e:a2:e6:4a:d6:4a:49:07:28:eb:ed:2f:
+ b9:37:f0:c3:b2:c0:64:4a:e1:55:8c:45:16:f0:6c:
+ bb:73:11:0f:b1:30:03:90:0b:de:7f:dd:96:fc:b0:
+ d6:c0:c1:fd:70:f5:e6:73:46:81:4d:9b:86:d9:e8:
+ ac:c9:91:9b:dc:e7:c4:43:b7:0e:e3:c8:12:87:16:
+ 87:79:1b:a2:d1:73:fc:fc:5e:f3:36:40:45:a3:cd:
+ fa:0c:40:74:8f:75:15:02:8e:27:8c:41:b9:24:d4:
+ 80:01:70:31:f8:d5:55:24:8f:46:e1:82:27:72:1f:
+ 66:6e:8a:66:8d:1f:6e:4e:cf:ca:05:fb:7d:49:38:
+ 30:2f:ef:5e:23:ff:a0:20:e3:58:84:59:a4:9a:e5:
+ 18:ff
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ email:santest@example.com, othername:<unsupported>
+ Signature Algorithm: sha256WithRSAEncryption
+ 3f:63:47:b1:7f:67:6d:14:c9:b0:84:e8:c1:67:4e:a1:18:a5:
+ a6:d9:15:03:c3:5b:ec:f1:c3:ee:3d:f2:ea:01:f1:9c:07:da:
+ 29:b5:62:ae:0e:6b:8e:dc:fd:67:d7:d9:b0:9f:c8:81:ce:85:
+ 27:8d:80:cf:5b:ab:e6:c3:8c:37:1e:29:42:26:51:90:cf:31:
+ e0:4d:49:9f:04:6d:8d:f9:ac:c4:76:1e:3f:0e:f3:70:34:79:
+ c8:8e:a9:1e:06:e1:e1:4d:c3:9a:6c:fd:1a:41:66:79:ec:8c:
+ 78:52:ed:74:6b:90:f1:99:d3:1e:d7:cc:c8:74:d0:72:36:25:
+ 2e:fc:91:b0:13:6f:4a:53:2e:e9:72:57:f9:dd:f0:b4:60:f4:
+ a4:15:57:06:e5:38:be:19:3b:a8:1a:5a:73:42:88:3e:59:ab:
+ 9b:46:43:38:53:4a:1e:c7:9c:1a:4e:df:88:af:a6:92:17:81:
+ 28:e1:ad:a5:43:0d:ae:f7:c1:cd:6f:e5:55:2c:c0:9a:ac:18:
+ 1f:05:2f:52:f7:6c:a9:94:eb:1d:9a:a3:9f:db:44:cc:b2:e0:
+ 9e:3a:d5:0a:92:70:d8:89:5e:a9:5b:43:60:69:e4:ba:fb:2f:
+ 37:83:aa:27:a6:d9:b9:11:fa:58:a8:ac:23:6f:c2:a2:c5:c7:
+ 51:ec:94:f0
+-----BEGIN CERTIFICATE-----
+MIIC8jCCAdqgAwIBAgICEAMwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwERSBD
+QTAeFw0xNjAyMjgyMDI3MDNaFw0yNjAyMjUyMDI3MDNaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDrP2az
+VW9haCPbTSBOl0oP25+M+M2n4p12w0BRFDMopeWLVZtF60dDk1GVkWEFVYq9jQE0
+KmuXXYVhmbhr2G7FhszieV9QkUwNO3GBQBluk+ZoQ967601G2kslneGFV2iSheI+
+JLww0XmN5j6i5krWSkkHKOvtL7k38MOywGRK4VWMRRbwbLtzEQ+xMAOQC95/3Zb8
+sNbAwf1w9eZzRoFNm4bZ6KzJkZvc58RDtw7jyBKHFod5G6LRc/z8XvM2QEWjzfoM
+QHSPdRUCjieMQbkk1IABcDH41VUkj0bhgidyH2ZuimaNH25Oz8oF+31JODAv714j
+/6Ag41iEWaSa5Rj/AgMBAAGjTzBNMEsGA1UdEQREMEKBE3NhbnRlc3RAZXhhbXBs
+ZS5jb22gKwYKKwYBBAGCNxQCA6AdDBtzYW50ZXN0QGFkLmNvcnAuZXhhbXBsZS5j
+b20wDQYJKoZIhvcNAQELBQADggEBAD9jR7F/Z20UybCE6MFnTqEYpabZFQPDW+zx
+w+498uoB8ZwH2im1Yq4Oa47c/WfX2bCfyIHOhSeNgM9bq+bDjDceKUImUZDPMeBN
+SZ8EbY35rMR2Hj8O83A0eciOqR4G4eFNw5ps/RpBZnnsjHhS7XRrkPGZ0x7XzMh0
+0HI2JS78kbATb0pTLulyV/nd8LRg9KQVVwblOL4ZO6gaWnNCiD5Zq5tGQzhTSh7H
+nBpO34ivppIXgSjhraVDDa73wc1v5VUswJqsGB8FL1L3bKmU6x2ao5/bRMyy4J46
+1QqScNiJXqlbQ2Bp5Lr7LzeDqiem2bkR+liorCNvwqLFx1HslPA=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/client_3.pk8 b/chromium/net/data/ssl/certificates/client_3.pk8
new file mode 100644
index 00000000000..e0999f1718f
--- /dev/null
+++ 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
new file mode 100644
index 00000000000..8753ac47571
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/client_3_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: Feb 28 20:27:03 2016 GMT
+ Not After : Feb 25 20:27:03 2026 GMT
+ Subject: CN=E CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ba:41:e9:51:55:de:d0:9a:a9:ef:4c:fc:04:a4:
+ 26:76:de:1d:5a:fa:84:f9:a4:37:91:85:0b:92:d5:
+ 53:de:bd:77:ec:8b:b7:20:d1:db:26:63:4b:91:4a:
+ d3:93:3a:1a:1e:50:eb:02:fd:6a:c8:6d:14:72:b8:
+ c4:de:5c:4a:74:93:0e:ac:06:d3:5b:f8:f9:19:cd:
+ 0a:6f:3c:90:ec:7d:f8:43:9d:66:35:9a:58:e6:c2:
+ 8d:10:6c:94:79:e5:b3:fa:f6:98:de:50:8e:c0:b7:
+ 01:33:12:43:4c:52:57:ad:c8:0c:b1:62:e0:ae:89:
+ d8:ad:d4:94:d9:78:f3:b5:0d:13:3e:64:55:73:83:
+ 8b:2c:f6:6c:8c:9a:51:85:9e:cc:33:5d:aa:b0:1d:
+ 94:29:d7:7b:ed:b7:77:2c:53:a3:05:83:c2:69:c9:
+ 2d:ad:ce:76:62:d6:df:4e:e7:75:cb:19:2d:a8:e2:
+ 18:75:08:57:d1:a9:2a:29:68:70:02:8c:03:a3:00:
+ 22:37:d5:c0:7d:a2:a7:40:ce:2c:79:58:52:06:1f:
+ 7a:61:b7:ce:e7:c2:83:dd:6d:cc:0a:64:17:27:cb:
+ 21:56:38:c2:db:a0:ac:fd:18:b5:15:01:f5:50:25:
+ 96:b7:91:ab:51:42:47:8c:fc:df:6a:54:f9:ea:49:
+ a6:75
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 63:37:df:42:58:b0:4e:d1:0e:88:99:d0:c8:a0:9f:21:f6:13:
+ 6a:c1:bb:8b:59:01:76:6e:01:1d:37:cb:b9:12:de:0d:78:49:
+ b8:26:26:6b:9c:32:83:7d:39:bc:e3:f8:55:6b:cc:12:59:b0:
+ 11:b4:70:4c:14:99:34:e5:19:ab:d2:ff:5a:41:14:99:f6:d1:
+ 03:f7:28:1c:22:56:06:ef:10:ac:e0:be:45:47:c1:f5:6b:d1:
+ e9:78:3a:88:4f:37:db:c5:2d:a6:95:3a:ff:84:9f:78:fc:2f:
+ b8:7e:b8:e4:94:69:c9:9c:26:f5:29:2f:81:9a:a0:26:82:65:
+ 50:93:63:54:71:fe:d6:d0:90:47:1d:f3:28:bc:8f:5a:e7:6e:
+ 54:8a:2f:5f:e8:4a:40:77:e6:cf:46:e9:4a:da:d2:7f:70:86:
+ 56:6f:10:17:7b:f1:d0:1d:d2:3d:b1:de:7c:5f:bd:fe:50:3d:
+ 13:cf:5f:43:c7:d0:10:60:b9:eb:cb:55:de:60:1a:c7:b6:50:
+ 37:ea:9e:cf:18:28:b0:df:c7:0e:ae:08:5a:21:25:02:c3:08:
+ ca:1c:3e:b1:9f:bb:72:15:f6:5e:0a:32:bf:03:c7:05:e6:20:
+ 5c:82:df:9f:9e:39:dc:86:45:f3:65:cc:f7:8c:48:08:53:a2:
+ 73:b3:e7:5d
+-----BEGIN CERTIFICATE-----
+MIICwjCCAaqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
+b290IENBMB4XDTE2MDIyODIwMjcwM1oXDTI2MDIyNTIwMjcwM1owDzENMAsGA1UE
+AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpB6VFV3tCa
+qe9M/ASkJnbeHVr6hPmkN5GFC5LVU969d+yLtyDR2yZjS5FK05M6Gh5Q6wL9asht
+FHK4xN5cSnSTDqwG01v4+RnNCm88kOx9+EOdZjWaWObCjRBslHnls/r2mN5QjsC3
+ATMSQ0xSV63IDLFi4K6J2K3UlNl487UNEz5kVXODiyz2bIyaUYWezDNdqrAdlCnX
+e+23dyxTowWDwmnJLa3OdmLW307ndcsZLajiGHUIV9GpKilocAKMA6MAIjfVwH2i
+p0DOLHlYUgYfemG3zufCg91tzApkFyfLIVY4wtugrP0YtRUB9VAllreRq1FCR4z8
+32pU+epJpnUCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAGM330JYsE7RDoiZ0MignyH2E2rBu4tZAXZu
+AR03y7kS3g14SbgmJmucMoN9Obzj+FVrzBJZsBG0cEwUmTTlGavS/1pBFJn20QP3
+KBwiVgbvEKzgvkVHwfVr0el4OohPN9vFLaaVOv+En3j8L7h+uOSUacmcJvUpL4Ga
+oCaCZVCTY1Rx/tbQkEcd8yi8j1rnblSKL1/oSkB35s9G6Ura0n9whlZvEBd78dAd
+0j2x3nxfvf5QPRPPX0PH0BBguevLVd5gGse2UDfqns8YKLDfxw6uCFohJQLDCMoc
+PrGfu3IV9l4KMr8DxwXmIFyC35+eOdyGRfNlzPeMSAhTonOz510=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/globalsign_ev_sha256_ca_cert.pem b/chromium/net/data/ssl/certificates/globalsign_ev_sha256_ca_cert.pem
deleted file mode 100644
index bfad0aac94b..00000000000
--- a/chromium/net/data/ssl/certificates/globalsign_ev_sha256_ca_cert.pem
+++ /dev/null
@@ -1,25 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIEPDCCAySgAwIBAgILBAAAAAABJQcQRNUwDQYJKoZIhvcNAQELBQAwTDEgMB4G
-A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
-Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkxMTE4MTAwMDAwWhcNMTkwMzE4
-MTAwMDAwWjBwMSYwJAYDVQQLEx1FeHRlbmRlZCBWYWxpZGF0aW9uIFNIQTI1NiBD
-QTETMBEGA1UEChMKR2xvYmFsU2lnbjExMC8GA1UEAxMoR2xvYmFsU2lnbiBFeHRl
-bmRlZCBWYWxpZGF0aW9uIFNIQTI1NiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBALBif8TfrtmndK/ILyYLrRoXAmHWc7OhUAhQOi9KnUuv0F7PPbG3
-IoqTWVHc/5BXLTrU8v7FdKBKEyevSd8QqPltoW/wzqhwFShy8PPpWT5UrcxVGHNP
-BE99xpAPWq6JOAKSQxp59F0rhXCKUsFO+Gl+K/zR1tpYR9Oy9GKyowpIDvbxevkS
-n8b/ZAbtdi4YL3M6qy680hD7XFEgMiOcjgHvIHBj21Ga01L6yYv0klQHDRVFhhca
-wcSsQ/ckrODI508EwvESGrk18bmkypnNxDoZJJoqtQUeS8UBwUDsZ9ES63LitzBF
-uTG/nz5A/WWOzN18Adq6piOm8QGcKfwatMcCAwEAAaOB+jCB9zAOBgNVHQ8BAf8E
-BAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUivwUGz2jWWelO+Fz
-kqZikX/keDAwRgYDVR0gBD8wPTA7BgRVHSAAMDMwMQYIKwYBBQUHAgEWJWh0dHA6
-Ly93d3cuZ2xvYmFsc2lnbi5uZXQvcmVwb3NpdG9yeS8wNgYDVR0fBC8wLTAroCmg
-J4YlaHR0cDovL2NybC5nbG9iYWxzaWduLm5ldC9yb290LXIzLmNybDARBglghkgB
-hvhCAQEEBAMCAgQwHwYDVR0jBBgwFoAUj/BLf6guRSSuTVD6Y5qL3uLdG7wwDQYJ
-KoZIhvcNAQELBQADggEBAF2HVz/fP/IUd8jFBven7nszfYdjJJbzdpehLJqoLccQ
-EEHtGTy9xnqChzCkSgIoe705slJDt4wdXibIm5uV1CE0YidAEqLPeg4w1sU6y9eV
-L0E+IGJR7UF3FH0tBDbnyiTGEjviDxqi1VlSSbXvIoyhQHlsNvSeKdvTudDNmaSF
-lleJLy8SEXyJwieoACCibX27ZUk1vU4Hhvm2nY7AbP5ry6lzNuHozc+mMvuiwM/3
-Mc61UR+LBN8YxgpSHB1m1THyVG/Nz3b82rMe1XvSm1sYsULysrRLzSVc+89Up74A
-CIFMY+ZrQU0Yq+VrBBMPRtJ1Jc1BxkjaXf0O0c9CLFo=
------END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/multi-root-A-by-B.pem b/chromium/net/data/ssl/certificates/multi-root-A-by-B.pem
new file mode 100644
index 00000000000..01f99c25cfe
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-A-by-B.pem
@@ -0,0 +1,107 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAyCccGYHApzCTAxz4IbgviiK0iQ/asUCV39xGU/xvNiZmWlNt
+RXjCORaaP4KLusWweKgYvNWnkqXmrOIMgdCU5QzsXgMMF8U1Knurhuu/6GIKj7Al
+snD1EYwWT8F2ROV16JNP6efE5EIKCL5zLMuPc2pAd+szYKy+xSf9sU+ISxWvmP0y
+U66wKgyy9QXzOgYNblz+g/zjYK6ZjqEhwnIC5vRJV+aRMS6+kqGt+HExZHQQM9Cn
+DO0Yx7JQcfy5tq6VoI2sHzzVeaepiFC2As1oYCRFm7bpggjZnNR+KX0r2a5Xf2Jq
+VpaLSjOeX5OCsNEFAybNFfSHf2qa3+kBtdTJEQIDAQABAoIBAHadrupy2fB7OfSz
+W13oYMwVazZ7HdjD9M45JbiqNmI5+Zh4Lp7oRPo+KeWPgS2L8NxgimCGogunpAA6
+6ryYF1VzBjVkyurfZXWq2ulXl2Cpkaa79ms8xA/FHIfhmCyWa/0MKGTvhODdPkMW
+Uv1uGbKFenVW/xjA50HCRHerMZOE1yBaBzrAOGqLm4E/7snbZJ3K5Sx88mu9vAnA
+LBHMiqYwf4E9TJW+2AzDtlTI02/UbcQc4MDgRJc1YQSPz4pdtKbA3IvdDhXdsDCr
+Tum2gCpeUZS4zmXW6NcOBAHvrLdU8sEsodALCZ58hwkTU9YlqKyYE+DbuDd+3H5a
+3WIQbb0CgYEA6ZoLha/chlExbXr/5VcmiDfX/IRjAebG7uHMGC+QlSMxNxUGCuge
+kvw5+AkSsKdwHeSgr426SF3gPAwafK5KiTO4NoaD2pXFOvu5Z0Mpw4iT3kdTk/iO
+o2zTz4abEA0kQaqlhIbD5RrI5zU3K49BH8CkS+Kr5mCqtPu2b1aDac8CgYEA21gH
+/R1eTo4/0lBt+P4+4w8RMtt5Ky6rsZzSC87zJKznAKoGmo2rWCQKcxbZntznsuW3
+LN5MPYXXKqugp3fXebnRJYwBBE9HO39Cl5vb3l2EIYVRwspVeUs9KeTlt2FaiqQ1
+yE+s75bXFh9e3ztj4vOAWKGXi/KI2PHTdfo4tx8CgYEA5eX3BQDIdWAe1vJAOYMF
+pvXemOPpVIu8qIiMBhl5n2zdGKqWIdHDlUCqBFNZk4WVr7W79knzVRkef7ohrycQ
+r+q4luDXjx3q11u5YckVpxwY+p8TwALUzj1iT1DX9noYfo/lCYJf9G/h3Lngq/v2
+SbubdhuEtdvY5Pj82KI5/r0CgYAKDBxBkejR/F4cCicfcrX6vKPzCm6gdcDTn/VX
+KSGmGm1ycFdhGQAyR2RbJT7OshvC7BbZ7UzcvJbAk6AGS80I/GQCLkmVovQGW6v3
+OeJ2ax40UuEN5SrJJZMlqiCDp+f31dHI3S10xBoSH1m/K/9FVBYa+Tvx4yg1l84x
+50ZVzQKBgB6sEgCK7Q4HwOrSVyLvGjABZC41fuZSl58DB1bKdTtXq2ASP1igzmbR
+KEvawdUFqysM1TSz2F+QL4X393VVlSKi69w3LeORcMdOtbew2Rn7msBAHR4JO9sP
+dIdM/ccKebf1tgaTgI+c12yg+e+w7dey1Og0iPtcuMg3TumFX5q3
+-----END RSA PRIVATE KEY-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=B CA - Multi-root
+ Validity
+ Not Before: Mar 11 01:37:16 2016 GMT
+ Not After : Mar 9 01:37:16 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:c8:27:1c:19:81:c0:a7:30:93:03:1c:f8:21:b8:
+ 2f:8a:22:b4:89:0f:da:b1:40:95:df:dc:46:53:fc:
+ 6f:36:26:66:5a:53:6d:45:78:c2:39:16:9a:3f:82:
+ 8b:ba:c5:b0:78:a8:18:bc:d5:a7:92:a5:e6:ac:e2:
+ 0c:81:d0:94:e5:0c:ec:5e:03:0c:17:c5:35:2a:7b:
+ ab:86:eb:bf:e8:62:0a:8f:b0:25:b2:70:f5:11:8c:
+ 16:4f:c1:76:44:e5:75:e8:93:4f:e9:e7:c4:e4:42:
+ 0a:08:be:73:2c:cb:8f:73:6a:40:77:eb:33:60:ac:
+ be:c5:27:fd:b1:4f:88:4b:15:af:98:fd:32:53:ae:
+ b0:2a:0c:b2:f5:05:f3:3a:06:0d:6e:5c:fe:83:fc:
+ e3:60:ae:99:8e:a1:21:c2:72:02:e6:f4:49:57:e6:
+ 91:31:2e:be:92:a1:ad:f8:71:31:64:74:10:33:d0:
+ a7:0c:ed:18:c7:b2:50:71:fc:b9:b6:ae:95:a0:8d:
+ ac:1f:3c:d5:79:a7:a9:88:50:b6:02:cd:68:60:24:
+ 45:9b:b6:e9:82:08:d9:9c:d4:7e:29:7d:2b:d9:ae:
+ 57:7f:62:6a:56:96:8b:4a:33:9e:5f:93:82:b0:d1:
+ 05:03:26:cd:15:f4:87:7f:6a:9a:df:e9:01:b5:d4:
+ c9:11
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ FB:91:A9:5F:BC:27:81:98:55:30:BF:57:32:4D:B9:DA:56:DD:52:2C
+ X509v3 Authority Key Identifier:
+ keyid:90:CB:53:EE:36:0A:5A:B0:93:38:C9:11:B7:AC:FD:27:71:99:DC:81
+
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ Signature Algorithm: sha256WithRSAEncryption
+ b9:31:7a:95:b2:ba:3a:b4:f1:16:76:df:eb:d5:b9:af:67:b1:
+ 9d:8a:27:04:9b:61:6f:42:3f:c2:b3:cd:65:c4:86:cb:90:fb:
+ 9d:3a:ed:fc:b8:74:da:d7:6a:6c:2f:17:68:d1:73:58:f1:a2:
+ bb:8f:d6:b0:a8:7f:b6:a8:b0:74:d1:ea:c4:62:ed:bc:1e:ef:
+ 02:6b:d5:e8:2d:15:78:16:1e:90:fa:f4:29:5a:a8:43:ad:d2:
+ 58:40:b4:1c:60:4e:cd:bc:6f:1a:39:e4:46:b2:58:93:96:5a:
+ a8:a4:c4:31:73:ed:89:c4:81:27:e1:4c:66:20:7c:27:c4:f9:
+ 61:ff:d1:d5:a5:02:93:4c:06:fa:15:33:7a:1f:5f:eb:29:b2:
+ b5:6a:cd:7e:d6:d7:b7:51:a7:01:2f:22:9f:9e:7e:81:98:c4:
+ 72:11:36:2c:e7:c6:d0:f0:7d:98:36:ea:b7:a0:aa:13:8f:6e:
+ ae:41:59:9b:e6:c9:bc:9c:e8:93:f5:0c:4e:ca:b4:dd:e3:01:
+ fe:23:6e:fb:fa:b3:61:66:58:f5:fc:07:16:1d:a9:52:ec:a0:
+ 29:61:a4:39:ed:41:50:a3:a2:33:72:0e:3c:03:e1:0a:1a:1a:
+ cf:22:73:09:d7:ea:e8:15:fc:73:3c:d4:4e:34:6c:b4:18:94:
+ c4:d3:6e:12
+-----BEGIN CERTIFICATE-----
+MIIDZzCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwHDEaMBgGA1UEAwwRQiBD
+QSAtIE11bHRpLXJvb3QwHhcNMTYwMzExMDEzNzE2WhcNMjYwMzA5MDEzNzE2WjBg
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4x
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyCccGYHApzCTAxz4Ibgv
+iiK0iQ/asUCV39xGU/xvNiZmWlNtRXjCORaaP4KLusWweKgYvNWnkqXmrOIMgdCU
+5QzsXgMMF8U1Knurhuu/6GIKj7AlsnD1EYwWT8F2ROV16JNP6efE5EIKCL5zLMuP
+c2pAd+szYKy+xSf9sU+ISxWvmP0yU66wKgyy9QXzOgYNblz+g/zjYK6ZjqEhwnIC
+5vRJV+aRMS6+kqGt+HExZHQQM9CnDO0Yx7JQcfy5tq6VoI2sHzzVeaepiFC2As1o
+YCRFm7bpggjZnNR+KX0r2a5Xf2JqVpaLSjOeX5OCsNEFAybNFfSHf2qa3+kBtdTJ
+EQIDAQABo28wbTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBT7kalfvCeBmFUwv1cy
+TbnaVt1SLDAfBgNVHSMEGDAWgBSQy1PuNgpasJM4yRG3rP0ncZncgTAdBgNVHSUE
+FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBALkxepWy
+ujq08RZ23+vVua9nsZ2KJwSbYW9CP8KzzWXEhsuQ+5067fy4dNrXamwvF2jRc1jx
+oruP1rCof7aosHTR6sRi7bwe7wJr1egtFXgWHpD69ClaqEOt0lhAtBxgTs28bxo5
+5EayWJOWWqikxDFz7YnEgSfhTGYgfCfE+WH/0dWlApNMBvoVM3ofX+spsrVqzX7W
+17dRpwEvIp+efoGYxHIRNiznxtDwfZg26regqhOPbq5BWZvmybyc6JP1DE7KtN3j
+Af4jbvv6s2FmWPX8BxYdqVLsoClhpDntQVCjojNyDjwD4QoaGs8icwnX6ugV/HM8
+1E40bLQYlMTTbhI=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/multi-root-B-by-C.pem b/chromium/net/data/ssl/certificates/multi-root-B-by-C.pem
new file mode 100644
index 00000000000..5731bb1a699
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-B-by-C.pem
@@ -0,0 +1,74 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=C CA - Multi-root
+ Validity
+ Not Before: Jan 4 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=B CA - Multi-root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ca:e9:f3:21:f4:a0:e7:ba:82:8c:7f:b3:98:44:
+ 20:4a:9a:8b:f9:e5:0c:99:c4:22:72:f7:57:7c:1e:
+ cc:56:4c:c3:f5:fd:1e:90:a5:1c:bf:2c:c4:c4:29:
+ 29:38:cc:26:9e:1a:1d:e3:e4:db:97:58:35:14:e8:
+ e2:db:37:05:1c:32:f7:bb:19:22:c2:37:3f:01:76:
+ 8c:17:23:ca:fc:10:69:b4:d1:74:27:b6:10:7e:b7:
+ c1:07:a2:a1:af:18:4d:5c:2e:13:72:a9:fb:64:b1:
+ e7:9f:49:41:3c:dc:b8:5f:94:e6:68:05:a5:1f:c8:
+ 56:84:e2:e5:6a:84:71:9c:b8:ac:3e:ec:8e:0c:d2:
+ f2:5f:11:fd:f4:7f:40:a7:3b:08:01:bb:fd:6f:d0:
+ a9:16:1d:14:a1:28:20:30:98:ba:1e:22:4e:5b:09:
+ b9:c1:df:17:60:1b:80:43:97:49:69:cd:6a:4e:58:
+ 08:9c:dc:29:57:3f:1b:bf:d8:5f:32:94:ae:97:b2:
+ d4:8d:50:1a:d1:8b:03:84:00:fd:87:d9:2e:ed:91:
+ 3d:3f:b7:89:54:46:0a:cd:db:10:62:80:47:60:21:
+ b3:1d:0e:bc:41:4d:86:d4:9d:52:1b:53:82:1a:9f:
+ 46:91:98:1e:ed:9f:da:69:16:64:24:1c:de:f8:b3:
+ 34:69
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 90:CB:53:EE:36:0A:5A:B0:93:38:C9:11:B7:AC:FD:27:71:99:DC:81
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 97:cd:ae:5a:26:f4:25:f6:c0:8b:08:d8:df:82:35:d8:76:f3:
+ 5d:cc:99:bd:ac:70:c9:41:e0:24:c8:fd:e6:4e:41:2c:d4:69:
+ 8d:08:25:fd:f3:32:3a:58:0b:d3:58:9c:81:51:bf:97:a4:bc:
+ 00:18:1c:4f:1c:54:04:63:e3:72:87:f4:dc:9e:7b:dc:da:5d:
+ e1:ef:59:6b:f0:1f:3d:0c:11:55:1e:9a:1a:d8:8d:bc:7b:18:
+ b7:4f:92:1c:68:73:82:ec:f3:69:48:0a:86:40:4a:a5:6f:ae:
+ 8f:10:2e:12:0b:e8:7e:b9:bc:d7:26:f0:cf:f4:0f:5b:77:f2:
+ ff:77:28:b4:5f:5e:ef:65:08:21:b8:f9:1e:56:b9:69:3b:c4:
+ 7f:01:88:c9:7c:ca:d0:e2:df:e5:5e:8d:e9:2e:7d:4a:78:04:
+ 8b:c1:dc:d4:58:ac:90:fc:5c:8e:48:2b:60:99:63:37:3f:e5:
+ 61:da:8f:58:9f:4d:0a:ee:6c:8d:bc:1f:7e:c4:be:0f:32:4b:
+ 11:7a:28:bf:dd:d0:a0:40:42:a8:43:4d:0b:2f:01:0e:73:de:
+ 1b:a6:df:49:57:58:89:57:c0:23:76:83:f0:9a:0e:83:d9:9b:
+ cb:eb:ac:3f:89:d1:e8:3c:3e:f1:d5:80:0c:38:18:02:5c:5f:
+ e5:68:5e:cf
+-----BEGIN CERTIFICATE-----
+MIIC9jCCAd6gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwHDEaMBgGA1UEAwwRQyBD
+QSAtIE11bHRpLXJvb3QwHhcNMTYwMTA0MDAwMDAwWhcNMjYwMTAyMDAwMDAwWjAc
+MRowGAYDVQQDDBFCIENBIC0gTXVsdGktcm9vdDCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMrp8yH0oOe6gox/s5hEIEqai/nlDJnEInL3V3wezFZMw/X9
+HpClHL8sxMQpKTjMJp4aHePk25dYNRTo4ts3BRwy97sZIsI3PwF2jBcjyvwQabTR
+dCe2EH63wQeioa8YTVwuE3Kp+2Sx559JQTzcuF+U5mgFpR/IVoTi5WqEcZy4rD7s
+jgzS8l8R/fR/QKc7CAG7/W/QqRYdFKEoIDCYuh4iTlsJucHfF2AbgEOXSWnNak5Y
+CJzcKVc/G7/YXzKUrpey1I1QGtGLA4QA/YfZLu2RPT+3iVRGCs3bEGKAR2Ahsx0O
+vEFNhtSdUhtTghqfRpGYHu2f2mkWZCQc3vizNGkCAwEAAaNCMEAwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUkMtT7jYKWrCTOMkRt6z9J3GZ3IEwDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQCXza5aJvQl9sCLCNjfgjXYdvNdzJm9
+rHDJQeAkyP3mTkEs1GmNCCX98zI6WAvTWJyBUb+XpLwAGBxPHFQEY+Nyh/Tcnnvc
+2l3h71lr8B89DBFVHpoa2I28exi3T5IcaHOC7PNpSAqGQEqlb66PEC4SC+h+ubzX
+JvDP9A9bd/L/dyi0X17vZQghuPkeVrlpO8R/AYjJfMrQ4t/lXo3pLn1KeASLwdzU
+WKyQ/FyOSCtgmWM3P+Vh2o9Yn00K7myNvB9+xL4PMksReii/3dCgQEKoQ00LLwEO
+c94bpt9JV1iJV8AjdoPwmg6D2ZvL66w/idHoPD7x1YAMOBgCXF/laF7P
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/multi-root-B-by-F.pem b/chromium/net/data/ssl/certificates/multi-root-B-by-F.pem
new file mode 100644
index 00000000000..d7605803087
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-B-by-F.pem
@@ -0,0 +1,74 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=F CA - Multi-root
+ Validity
+ Not Before: Jan 5 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=B CA - Multi-root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ca:e9:f3:21:f4:a0:e7:ba:82:8c:7f:b3:98:44:
+ 20:4a:9a:8b:f9:e5:0c:99:c4:22:72:f7:57:7c:1e:
+ cc:56:4c:c3:f5:fd:1e:90:a5:1c:bf:2c:c4:c4:29:
+ 29:38:cc:26:9e:1a:1d:e3:e4:db:97:58:35:14:e8:
+ e2:db:37:05:1c:32:f7:bb:19:22:c2:37:3f:01:76:
+ 8c:17:23:ca:fc:10:69:b4:d1:74:27:b6:10:7e:b7:
+ c1:07:a2:a1:af:18:4d:5c:2e:13:72:a9:fb:64:b1:
+ e7:9f:49:41:3c:dc:b8:5f:94:e6:68:05:a5:1f:c8:
+ 56:84:e2:e5:6a:84:71:9c:b8:ac:3e:ec:8e:0c:d2:
+ f2:5f:11:fd:f4:7f:40:a7:3b:08:01:bb:fd:6f:d0:
+ a9:16:1d:14:a1:28:20:30:98:ba:1e:22:4e:5b:09:
+ b9:c1:df:17:60:1b:80:43:97:49:69:cd:6a:4e:58:
+ 08:9c:dc:29:57:3f:1b:bf:d8:5f:32:94:ae:97:b2:
+ d4:8d:50:1a:d1:8b:03:84:00:fd:87:d9:2e:ed:91:
+ 3d:3f:b7:89:54:46:0a:cd:db:10:62:80:47:60:21:
+ b3:1d:0e:bc:41:4d:86:d4:9d:52:1b:53:82:1a:9f:
+ 46:91:98:1e:ed:9f:da:69:16:64:24:1c:de:f8:b3:
+ 34:69
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 90:CB:53:EE:36:0A:5A:B0:93:38:C9:11:B7:AC:FD:27:71:99:DC:81
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 64:09:43:15:ae:ac:dc:ad:23:99:24:cb:3a:39:4b:ad:2b:83:
+ f2:69:c3:f8:7e:e8:79:1e:8f:b1:09:0c:17:e6:44:5f:47:33:
+ 14:fa:d4:f2:d8:d2:94:a9:75:58:4e:a8:44:8f:71:d0:53:c0:
+ 76:5d:8e:39:1c:23:95:3d:89:c7:18:0a:0e:80:37:3d:8d:a6:
+ 6d:60:c9:ad:08:a3:7a:8a:e8:00:3e:bf:67:e0:b6:09:b2:3b:
+ 55:a6:b8:36:24:00:5e:8d:89:89:53:df:ea:2d:a9:f8:d2:60:
+ 5a:e1:7b:f6:6c:a1:29:95:13:75:fe:62:57:cd:b4:0e:50:dc:
+ b5:41:3d:e9:19:0b:33:62:43:af:14:4d:40:c2:48:eb:72:88:
+ 65:d3:89:11:f4:98:e8:f7:13:b4:7a:11:8e:39:01:80:a5:2e:
+ 27:4a:98:3c:c8:d4:4f:31:70:3f:c2:de:e0:69:6b:59:54:d7:
+ 66:07:68:74:72:9c:c2:1c:1c:0c:0d:b9:65:90:47:41:93:2c:
+ ec:d1:f0:51:b7:69:7b:e6:88:d8:f7:f7:0f:f1:4e:8c:e1:e9:
+ 50:5d:7a:c3:62:1d:32:76:8e:df:7f:87:34:e4:57:bf:9c:1d:
+ 45:4b:3b:07:f2:d1:8b:d6:d0:e6:72:de:7b:4b:23:bf:ee:1b:
+ c7:40:d0:a7
+-----BEGIN CERTIFICATE-----
+MIIC9jCCAd6gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwHDEaMBgGA1UEAwwRRiBD
+QSAtIE11bHRpLXJvb3QwHhcNMTYwMTA1MDAwMDAwWhcNMjYwMTAyMDAwMDAwWjAc
+MRowGAYDVQQDDBFCIENBIC0gTXVsdGktcm9vdDCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMrp8yH0oOe6gox/s5hEIEqai/nlDJnEInL3V3wezFZMw/X9
+HpClHL8sxMQpKTjMJp4aHePk25dYNRTo4ts3BRwy97sZIsI3PwF2jBcjyvwQabTR
+dCe2EH63wQeioa8YTVwuE3Kp+2Sx559JQTzcuF+U5mgFpR/IVoTi5WqEcZy4rD7s
+jgzS8l8R/fR/QKc7CAG7/W/QqRYdFKEoIDCYuh4iTlsJucHfF2AbgEOXSWnNak5Y
+CJzcKVc/G7/YXzKUrpey1I1QGtGLA4QA/YfZLu2RPT+3iVRGCs3bEGKAR2Ahsx0O
+vEFNhtSdUhtTghqfRpGYHu2f2mkWZCQc3vizNGkCAwEAAaNCMEAwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUkMtT7jYKWrCTOMkRt6z9J3GZ3IEwDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQBkCUMVrqzcrSOZJMs6OUutK4PyacP4
+fuh5Ho+xCQwX5kRfRzMU+tTy2NKUqXVYTqhEj3HQU8B2XY45HCOVPYnHGAoOgDc9
+jaZtYMmtCKN6iugAPr9n4LYJsjtVprg2JABejYmJU9/qLan40mBa4Xv2bKEplRN1
+/mJXzbQOUNy1QT3pGQszYkOvFE1Awkjrcohl04kR9Jjo9xO0ehGOOQGApS4nSpg8
+yNRPMXA/wt7gaWtZVNdmB2h0cpzCHBwMDbllkEdBkyzs0fBRt2l75ojY9/cP8U6M
+4elQXXrDYh0ydo7ff4c05Fe/nB1FSzsH8tGL1tDmct57SyO/7hvHQNCn
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/multi-root-C-by-D.pem b/chromium/net/data/ssl/certificates/multi-root-C-by-D.pem
new file mode 100644
index 00000000000..bab6142cff2
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-C-by-D.pem
@@ -0,0 +1,74 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=D Root CA - Multi-root
+ Validity
+ Not Before: Jan 3 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=C CA - Multi-root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:b6:1f:67:e4:9e:db:e0:ff:eb:29:75:ee:68:a2:
+ 4e:95:6e:d2:f6:9d:c9:b6:dc:08:18:70:b5:76:bf:
+ b7:14:8b:cb:46:c6:6a:2c:fa:43:f9:54:93:fa:bd:
+ aa:f0:ee:a3:20:5b:2a:cd:08:f7:be:95:36:e4:88:
+ f8:fd:43:7d:b8:f9:38:b4:d2:4e:22:0b:8b:85:de:
+ 6a:fe:6f:da:3b:4b:0f:26:c1:f8:31:22:36:19:96:
+ 0c:ef:85:7c:72:67:ac:4c:5c:f9:23:a4:29:d8:a5:
+ 1c:b6:ec:95:eb:d3:c2:8d:cb:ae:9a:d7:08:c8:b7:
+ f7:a0:c6:28:44:5f:24:97:bd:ca:d9:6d:99:9b:17:
+ 47:1f:38:b3:e3:67:6a:b4:75:d6:92:cd:67:62:20:
+ 58:f0:a7:46:85:94:72:76:98:c5:ec:4c:75:1b:a1:
+ 76:67:4b:1f:c8:23:6c:2a:78:66:c2:a7:6b:af:ef:
+ 97:30:34:60:0a:db:98:94:3b:9f:95:3c:34:b6:35:
+ 40:12:fa:1d:bf:66:f4:7b:fd:66:1a:2a:49:8c:24:
+ 60:91:08:f9:61:39:f9:3b:29:98:64:7b:35:04:a9:
+ f5:af:8d:0f:1e:e7:28:b6:30:32:b4:5f:d4:29:16:
+ 7a:70:8d:db:b9:ba:bf:eb:22:98:5d:94:c8:47:e3:
+ 4b:11
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 90:53:F5:80:11:F6:3F:1B:A8:9D:8D:75:0D:56:3B:F2:2B:C5:9C:44
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 67:11:95:f4:b9:cb:47:e6:50:da:fd:a0:13:78:d7:e1:be:59:
+ ec:86:32:e5:56:3e:9b:8f:db:b0:3b:93:fb:d0:6e:b3:de:7e:
+ 10:5b:b4:30:f7:02:e8:3f:ff:4e:91:3a:e8:b8:4a:94:5e:14:
+ 7b:f8:84:e5:1f:63:2c:b4:7f:4f:ee:b1:d5:ee:92:79:7d:63:
+ 87:a0:e9:57:14:57:11:59:18:54:8b:e3:d1:51:80:a7:2f:51:
+ f2:6f:43:d2:87:e1:59:23:2c:fe:83:38:e1:25:da:b5:34:af:
+ 33:17:64:80:08:b6:bd:5f:92:05:2c:81:b0:c3:d3:80:cd:e1:
+ 5c:95:d2:ea:1e:d3:af:d9:93:c2:f4:23:ae:51:b0:a4:82:49:
+ 2d:ec:fe:d1:18:e3:a3:53:9f:63:4b:38:dc:54:25:ce:4c:90:
+ 37:02:e4:67:41:31:ba:7a:13:1a:68:1e:ed:34:0c:3d:66:ba:
+ a3:3a:71:76:5f:5f:89:a1:cd:95:50:f6:5d:1f:c0:91:31:93:
+ 5b:58:af:e7:9b:21:e6:57:b1:f4:d7:dd:c1:84:25:5b:83:f7:
+ 5f:c9:89:17:5b:6f:54:f2:8b:ed:47:de:27:57:9e:e9:8c:b3:
+ 58:2c:c2:77:25:e1:eb:22:06:d1:f6:c5:f4:d7:1a:3d:00:1c:
+ 2e:85:e9:70
+-----BEGIN CERTIFICATE-----
+MIIC+zCCAeOgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UEAwwWRCBS
+b290IENBIC0gTXVsdGktcm9vdDAeFw0xNjAxMDMwMDAwMDBaFw0yNjAxMDIwMDAw
+MDBaMBwxGjAYBgNVBAMMEUMgQ0EgLSBNdWx0aS1yb290MIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAth9n5J7b4P/rKXXuaKJOlW7S9p3JttwIGHC1dr+3
+FIvLRsZqLPpD+VST+r2q8O6jIFsqzQj3vpU25Ij4/UN9uPk4tNJOIguLhd5q/m/a
+O0sPJsH4MSI2GZYM74V8cmesTFz5I6Qp2KUctuyV69PCjcuumtcIyLf3oMYoRF8k
+l73K2W2ZmxdHHziz42dqtHXWks1nYiBY8KdGhZRydpjF7Ex1G6F2Z0sfyCNsKnhm
+wqdrr++XMDRgCtuYlDuflTw0tjVAEvodv2b0e/1mGipJjCRgkQj5YTn5OymYZHs1
+BKn1r40PHucotjAytF/UKRZ6cI3bubq/6yKYXZTIR+NLEQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBSQU/WAEfY/G6idjXUNVjvyK8WcRDAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAGcRlfS5y0fmUNr9oBN41+G+
+WeyGMuVWPpuP27A7k/vQbrPefhBbtDD3Aug//06ROui4SpReFHv4hOUfYyy0f0/u
+sdXuknl9Y4eg6VcUVxFZGFSL49FRgKcvUfJvQ9KH4VkjLP6DOOEl2rU0rzMXZIAI
+tr1fkgUsgbDD04DN4VyV0uoe06/Zk8L0I65RsKSCSS3s/tEY46NTn2NLONxUJc5M
+kDcC5GdBMbp6ExpoHu00DD1muqM6cXZfX4mhzZVQ9l0fwJExk1tYr+ebIeZXsfTX
+3cGEJVuD91/JiRdbb1Tyi+1H3idXnumMs1gswncl4esiBtH2xfTXGj0AHC6F6XA=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/multi-root-C-by-E.pem b/chromium/net/data/ssl/certificates/multi-root-C-by-E.pem
new file mode 100644
index 00000000000..5ecc8b2628a
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-C-by-E.pem
@@ -0,0 +1,74 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=E Root CA - Multi-root
+ Validity
+ Not Before: Jan 5 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=C CA - Multi-root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:b6:1f:67:e4:9e:db:e0:ff:eb:29:75:ee:68:a2:
+ 4e:95:6e:d2:f6:9d:c9:b6:dc:08:18:70:b5:76:bf:
+ b7:14:8b:cb:46:c6:6a:2c:fa:43:f9:54:93:fa:bd:
+ aa:f0:ee:a3:20:5b:2a:cd:08:f7:be:95:36:e4:88:
+ f8:fd:43:7d:b8:f9:38:b4:d2:4e:22:0b:8b:85:de:
+ 6a:fe:6f:da:3b:4b:0f:26:c1:f8:31:22:36:19:96:
+ 0c:ef:85:7c:72:67:ac:4c:5c:f9:23:a4:29:d8:a5:
+ 1c:b6:ec:95:eb:d3:c2:8d:cb:ae:9a:d7:08:c8:b7:
+ f7:a0:c6:28:44:5f:24:97:bd:ca:d9:6d:99:9b:17:
+ 47:1f:38:b3:e3:67:6a:b4:75:d6:92:cd:67:62:20:
+ 58:f0:a7:46:85:94:72:76:98:c5:ec:4c:75:1b:a1:
+ 76:67:4b:1f:c8:23:6c:2a:78:66:c2:a7:6b:af:ef:
+ 97:30:34:60:0a:db:98:94:3b:9f:95:3c:34:b6:35:
+ 40:12:fa:1d:bf:66:f4:7b:fd:66:1a:2a:49:8c:24:
+ 60:91:08:f9:61:39:f9:3b:29:98:64:7b:35:04:a9:
+ f5:af:8d:0f:1e:e7:28:b6:30:32:b4:5f:d4:29:16:
+ 7a:70:8d:db:b9:ba:bf:eb:22:98:5d:94:c8:47:e3:
+ 4b:11
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 90:53:F5:80:11:F6:3F:1B:A8:9D:8D:75:0D:56:3B:F2:2B:C5:9C:44
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 43:35:08:cc:aa:f8:10:9f:9e:fa:ab:24:dc:c6:e6:9a:23:52:
+ c9:4c:81:33:ba:64:b2:86:a8:29:f4:1f:5a:fa:5a:c4:91:56:
+ 16:d1:f9:84:96:89:8c:ac:1f:b6:ea:2f:cb:12:f4:92:ed:3b:
+ 85:09:eb:f3:7a:2e:09:39:ec:ee:09:4b:fa:86:3e:62:40:0e:
+ 57:72:07:de:fa:53:45:ac:40:1c:0d:0b:4a:67:9a:f7:39:ce:
+ 33:5e:d0:17:0b:8a:83:ae:33:6f:96:c0:f0:7a:ac:07:36:c5:
+ 86:a9:db:93:aa:2e:fa:71:d1:1a:dd:82:2a:f8:1c:30:2a:b9:
+ 7d:29:fa:75:62:76:7c:15:15:75:af:78:6c:7c:53:ae:2e:80:
+ 14:0d:0b:eb:0f:b1:6d:fa:df:72:0b:6f:f0:90:96:18:71:df:
+ 76:1d:8c:f1:d5:c0:4f:ab:38:1a:eb:e6:a1:dd:1d:dc:60:d4:
+ da:7f:40:db:17:fc:4a:56:65:3a:86:60:83:87:b3:f6:3b:a8:
+ 85:ac:2b:14:c2:26:77:8f:ee:a4:6f:11:f2:27:08:3f:bf:86:
+ 4a:e3:bd:ef:6b:51:ec:72:a7:51:08:47:16:f8:d3:d7:b1:8d:
+ a1:b1:ca:d3:cd:fd:56:0a:2c:2f:62:27:8c:e1:ff:88:83:ff:
+ 83:ab:87:70
+-----BEGIN CERTIFICATE-----
+MIIC+zCCAeOgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UEAwwWRSBS
+b290IENBIC0gTXVsdGktcm9vdDAeFw0xNjAxMDUwMDAwMDBaFw0yNjAxMDIwMDAw
+MDBaMBwxGjAYBgNVBAMMEUMgQ0EgLSBNdWx0aS1yb290MIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAth9n5J7b4P/rKXXuaKJOlW7S9p3JttwIGHC1dr+3
+FIvLRsZqLPpD+VST+r2q8O6jIFsqzQj3vpU25Ij4/UN9uPk4tNJOIguLhd5q/m/a
+O0sPJsH4MSI2GZYM74V8cmesTFz5I6Qp2KUctuyV69PCjcuumtcIyLf3oMYoRF8k
+l73K2W2ZmxdHHziz42dqtHXWks1nYiBY8KdGhZRydpjF7Ex1G6F2Z0sfyCNsKnhm
+wqdrr++XMDRgCtuYlDuflTw0tjVAEvodv2b0e/1mGipJjCRgkQj5YTn5OymYZHs1
+BKn1r40PHucotjAytF/UKRZ6cI3bubq/6yKYXZTIR+NLEQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBSQU/WAEfY/G6idjXUNVjvyK8WcRDAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAEM1CMyq+BCfnvqrJNzG5poj
+UslMgTO6ZLKGqCn0H1r6WsSRVhbR+YSWiYysH7bqL8sS9JLtO4UJ6/N6Lgk57O4J
+S/qGPmJADldyB976U0WsQBwNC0pnmvc5zjNe0BcLioOuM2+WwPB6rAc2xYap25Oq
+Lvpx0Rrdgir4HDAquX0p+nVidnwVFXWveGx8U64ugBQNC+sPsW3633ILb/CQlhhx
+33YdjPHVwE+rOBrr5qHdHdxg1Np/QNsX/EpWZTqGYIOHs/Y7qIWsKxTCJneP7qRv
+EfInCD+/hkrjve9rUexyp1EIRxb409exjaGxytPN/VYKLC9iJ4zh/4iD/4Orh3A=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/multi-root-D-by-D.pem b/chromium/net/data/ssl/certificates/multi-root-D-by-D.pem
new file mode 100644
index 00000000000..3030167863d
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-D-by-D.pem
@@ -0,0 +1,75 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=D Root CA - Multi-root
+ Validity
+ Not Before: Jan 2 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=D Root CA - Multi-root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:cd:cf:d9:70:03:4f:4f:f1:9f:93:a1:2c:6e:cb:
+ 2f:20:d7:67:29:ce:99:02:4e:db:7d:6b:5e:6a:3a:
+ a1:d2:7f:cd:f9:58:bd:34:fe:af:8d:8a:05:34:a2:
+ 67:16:ae:94:88:3b:77:3f:f2:a0:a5:46:2e:05:2e:
+ b8:a7:2f:ff:e0:df:1d:b8:1e:31:6f:57:f9:aa:55:
+ 9c:83:aa:04:94:cd:e4:0f:99:f4:74:c1:38:8d:4c:
+ 90:67:ba:7e:92:42:59:ff:14:d6:4e:22:31:78:04:
+ 89:63:7d:84:fa:60:e7:d2:0d:61:0b:d8:a5:20:b3:
+ 8a:ce:f1:ef:b7:b0:b5:a6:81:d0:47:50:fb:5a:09:
+ 34:e1:a0:e3:6b:cf:e8:26:38:4d:cb:70:ae:4c:96:
+ 2c:9e:46:18:0c:e3:11:9f:8d:8a:65:c5:b1:03:5c:
+ 61:d9:35:a8:5d:29:08:7c:45:2e:38:13:dc:b0:72:
+ a6:e6:29:04:85:6a:6d:fd:74:af:60:6c:24:51:e2:
+ 3a:58:38:c1:0f:b2:4e:ac:8e:63:81:36:01:9f:02:
+ 04:de:54:53:4c:fa:5f:67:44:db:f0:ed:ce:3f:f0:
+ 5b:e7:75:b3:72:d5:e8:76:9c:24:73:2b:0c:d9:7c:
+ dd:85:a8:61:b9:42:d1:69:35:04:88:03:8a:c2:aa:
+ 10:cb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ FA:45:82:63:D1:67:F2:93:F4:6A:6B:44:44:74:1A:D2:B0:CD:12:F6
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ ac:1c:7c:de:1a:4a:31:54:77:c5:94:7d:6a:0b:9d:c2:c9:d4:
+ 3b:2d:71:e4:99:df:ca:02:5c:a0:1c:1c:22:7d:f2:a5:0e:97:
+ 7c:91:20:12:c5:b7:f5:56:15:8c:1b:44:b2:32:94:8b:e5:b1:
+ c0:0b:f6:c0:b8:b4:cf:b9:27:d8:49:52:fc:81:9f:48:2a:08:
+ b8:94:a1:3f:78:fe:20:66:f5:ed:3f:61:f6:f7:23:5c:4c:36:
+ 49:48:10:07:de:40:62:eb:3b:bb:6b:4b:8e:e4:a7:b3:75:33:
+ 2f:4d:11:58:76:1e:1c:d9:b9:dc:1c:33:da:82:2b:5f:fc:51:
+ f1:26:35:7d:5e:eb:67:ba:da:2c:f2:d7:6e:88:b6:a1:34:ed:
+ 07:d2:a5:e4:ac:d6:9b:7c:6c:6e:77:aa:11:4e:d0:60:fa:86:
+ 94:a0:74:00:60:8b:1c:0b:3e:5d:05:c9:b9:8c:b4:6f:a5:e7:
+ 82:c0:6a:ef:60:73:de:1f:74:20:aa:67:c7:d9:c2:81:c7:4c:
+ d7:c9:57:e4:7d:db:80:bd:7d:4f:39:a4:77:d3:2e:65:79:87:
+ ae:05:f7:9c:28:ed:e8:4e:f6:ac:38:3f:8f:36:bb:ae:5e:42:
+ 71:d5:a9:5b:a7:df:42:9f:6b:e0:ec:3e:3b:6e:36:11:9b:34:
+ a8:66:ff:d5
+-----BEGIN CERTIFICATE-----
+MIIDADCCAeigAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UEAwwWRCBS
+b290IENBIC0gTXVsdGktcm9vdDAeFw0xNjAxMDIwMDAwMDBaFw0yNjAxMDIwMDAw
+MDBaMCExHzAdBgNVBAMMFkQgUm9vdCBDQSAtIE11bHRpLXJvb3QwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNz9lwA09P8Z+ToSxuyy8g12cpzpkCTtt9
+a15qOqHSf835WL00/q+NigU0omcWrpSIO3c/8qClRi4FLrinL//g3x24HjFvV/mq
+VZyDqgSUzeQPmfR0wTiNTJBnun6SQln/FNZOIjF4BIljfYT6YOfSDWEL2KUgs4rO
+8e+3sLWmgdBHUPtaCTThoONrz+gmOE3LcK5MliyeRhgM4xGfjYplxbEDXGHZNahd
+KQh8RS44E9ywcqbmKQSFam39dK9gbCRR4jpYOMEPsk6sjmOBNgGfAgTeVFNM+l9n
+RNvw7c4/8FvndbNy1eh2nCRzKwzZfN2FqGG5QtFpNQSIA4rCqhDLAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPpFgmPRZ/KT9GprRER0GtKwzRL2
+MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEArBx83hpKMVR3xZR9
+agudwsnUOy1x5JnfygJcoBwcIn3ypQ6XfJEgEsW39VYVjBtEsjKUi+WxwAv2wLi0
+z7kn2ElS/IGfSCoIuJShP3j+IGb17T9h9vcjXEw2SUgQB95AYus7u2tLjuSns3Uz
+L00RWHYeHNm53Bwz2oIrX/xR8SY1fV7rZ7raLPLXboi2oTTtB9Kl5KzWm3xsbneq
+EU7QYPqGlKB0AGCLHAs+XQXJuYy0b6XngsBq72Bz3h90IKpnx9nCgcdM18lX5H3b
+gL19Tzmkd9MuZXmHrgX3nCjt6E72rDg/jza7rl5CcdWpW6ffQp9r4Ow+O242EZs0
+qGb/1Q==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/multi-root-E-by-E.pem b/chromium/net/data/ssl/certificates/multi-root-E-by-E.pem
new file mode 100644
index 00000000000..15632ddd2de
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-E-by-E.pem
@@ -0,0 +1,75 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=E Root CA - Multi-root
+ Validity
+ Not Before: Jan 2 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=E Root CA - Multi-root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:b5:60:cb:b4:84:ab:6c:ba:59:52:a9:4c:6a:85:
+ 41:f2:41:17:49:40:3f:3e:e8:70:5c:05:df:dd:64:
+ 9e:fc:be:fb:38:ef:5d:67:ab:0e:de:9c:ea:ad:91:
+ e1:f4:db:8b:f4:c0:e6:d0:ad:e2:83:15:01:aa:49:
+ 42:97:ae:72:7b:78:e3:20:4e:7e:29:ee:b5:35:6b:
+ c4:af:d4:54:b0:86:2f:a9:09:a7:3b:8c:05:9e:fd:
+ b4:b8:1f:3a:aa:d5:b5:d2:91:0f:50:e9:d2:1e:62:
+ 1c:c1:30:07:41:aa:bd:c2:11:3f:cc:c8:0f:a9:7e:
+ 81:69:52:96:86:2a:07:63:7b:f0:23:9e:db:27:88:
+ 8c:dc:aa:8c:66:dd:35:3a:08:60:37:36:41:34:f5:
+ 48:69:23:1a:5b:18:a7:ec:df:68:0a:3c:19:fb:92:
+ b7:fa:53:9b:f3:70:b6:0d:4c:cb:2f:b7:0e:7e:5f:
+ 94:8c:a3:71:66:09:be:0d:af:db:52:f6:82:3f:88:
+ 64:72:cc:19:79:f4:7b:4d:6e:50:dc:93:88:d5:29:
+ 8a:e1:c8:1f:32:71:9f:d9:0e:14:31:f8:94:11:23:
+ b1:bf:64:eb:27:3a:64:fb:77:ee:40:8c:a7:03:ed:
+ 1d:ec:8f:ee:25:58:f0:26:91:3c:f8:28:a1:7a:45:
+ 9f:13
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 51:68:BC:D9:1B:1D:7F:8E:0D:4A:33:39:2D:A4:1F:14:29:92:70:8E
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 2d:d4:56:d9:90:bb:62:64:66:78:6d:cd:73:26:cc:42:ce:37:
+ f4:bf:e8:8f:e7:1e:00:cb:c2:bd:54:33:0b:a8:e2:04:e1:5f:
+ 59:2a:1a:41:70:0f:d6:32:5f:d0:14:86:fa:e2:a7:19:29:49:
+ 77:56:b9:d7:e6:eb:39:61:e4:25:67:22:eb:f8:46:86:b7:6b:
+ 7d:44:01:0b:18:cb:ba:e5:af:76:ab:c6:fe:43:6c:d8:f6:33:
+ f7:86:0b:22:da:27:78:91:07:55:3f:b2:c5:1e:10:88:09:b3:
+ cf:22:c6:7e:8f:c6:d0:c5:ec:67:90:72:8b:2b:c4:46:81:2c:
+ 82:d1:5c:57:4e:d5:af:c4:d2:d8:b2:a7:91:1a:42:b3:57:bc:
+ 4e:81:5e:cf:91:af:da:f1:53:29:de:31:6b:d3:69:a4:4d:a9:
+ 14:15:96:51:7d:0d:bd:28:11:03:71:d2:85:11:92:1d:96:1a:
+ 12:33:0c:4b:cf:c4:40:19:fb:eb:6a:fe:9b:e7:2d:cd:f7:75:
+ a3:66:4e:a6:7d:8e:8c:2e:5d:b8:2c:a8:5e:d7:42:1b:97:00:
+ ba:12:41:8c:9b:f1:ed:91:49:63:5a:11:0d:e4:7d:f0:dc:36:
+ 23:0b:1b:e8:5f:be:1f:6d:a7:aa:bb:30:76:e2:36:b2:5a:68:
+ 80:f5:75:7e
+-----BEGIN CERTIFICATE-----
+MIIDADCCAeigAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UEAwwWRSBS
+b290IENBIC0gTXVsdGktcm9vdDAeFw0xNjAxMDIwMDAwMDBaFw0yNjAxMDIwMDAw
+MDBaMCExHzAdBgNVBAMMFkUgUm9vdCBDQSAtIE11bHRpLXJvb3QwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1YMu0hKtsullSqUxqhUHyQRdJQD8+6HBc
+Bd/dZJ78vvs4711nqw7enOqtkeH024v0wObQreKDFQGqSUKXrnJ7eOMgTn4p7rU1
+a8Sv1FSwhi+pCac7jAWe/bS4Hzqq1bXSkQ9Q6dIeYhzBMAdBqr3CET/MyA+pfoFp
+UpaGKgdje/AjntsniIzcqoxm3TU6CGA3NkE09UhpIxpbGKfs32gKPBn7krf6U5vz
+cLYNTMsvtw5+X5SMo3FmCb4Nr9tS9oI/iGRyzBl59HtNblDck4jVKYrhyB8ycZ/Z
+DhQx+JQRI7G/ZOsnOmT7d+5AjKcD7R3sj+4lWPAmkTz4KKF6RZ8TAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFFovNkbHX+ODUozOS2kHxQpknCO
+MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEALdRW2ZC7YmRmeG3N
+cybMQs439L/oj+ceAMvCvVQzC6jiBOFfWSoaQXAP1jJf0BSG+uKnGSlJd1a51+br
+OWHkJWci6/hGhrdrfUQBCxjLuuWvdqvG/kNs2PYz94YLItoneJEHVT+yxR4QiAmz
+zyLGfo/G0MXsZ5ByiyvERoEsgtFcV07Vr8TS2LKnkRpCs1e8ToFez5Gv2vFTKd4x
+a9NppE2pFBWWUX0NvSgRA3HShRGSHZYaEjMMS8/EQBn762r+m+ctzfd1o2ZOpn2O
+jC5duCyoXtdCG5cAuhJBjJvx7ZFJY1oRDeR98Nw2Iwsb6F++H22nqrswduI2slpo
+gPV1fg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/multi-root-F-by-E.pem b/chromium/net/data/ssl/certificates/multi-root-F-by-E.pem
new file mode 100644
index 00000000000..86b2bae02ee
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-F-by-E.pem
@@ -0,0 +1,74 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4098 (0x1002)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=E Root CA - Multi-root
+ Validity
+ Not Before: Jan 2 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=F CA - Multi-root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:9d:41:79:88:93:ab:fe:e6:52:28:84:91:9d:c2:
+ 85:a0:2c:97:39:69:25:20:43:85:8c:db:64:8f:41:
+ f4:b5:25:e6:3e:16:41:fa:40:b7:6c:2c:fc:11:76:
+ 7d:86:b7:47:73:68:ae:e9:2c:7e:5d:8b:21:68:86:
+ 71:11:cd:21:f9:16:a0:20:67:ac:79:40:d0:94:e6:
+ bf:a2:dd:65:af:da:d3:c5:23:82:0a:a2:1c:a7:bc:
+ 7d:f0:c2:a8:0b:30:ca:20:d6:31:5f:28:c8:74:4b:
+ 09:1e:50:de:d4:51:d9:9c:f5:3d:fe:b0:8d:ee:11:
+ f2:22:3e:11:09:53:23:77:52:5c:cf:8d:dd:6c:3b:
+ c4:39:1b:33:c2:00:bc:34:2d:e6:dc:9d:af:e8:36:
+ ec:ac:c7:e4:73:09:44:ad:59:8d:51:c1:ee:11:60:
+ 5b:b5:c9:d8:cb:48:b0:f9:0a:57:38:d8:e3:be:c5:
+ 4e:38:7e:47:3f:24:66:a1:11:3d:2d:9f:ca:4a:dc:
+ 59:58:fd:cc:56:22:c7:d5:c9:70:2f:ec:66:81:4d:
+ ee:48:39:97:ef:dd:b6:02:34:b2:90:db:16:a4:60:
+ 9d:18:de:95:87:a1:14:6e:19:ab:88:42:37:57:cf:
+ 20:c4:d8:e3:c6:24:8d:bc:fd:4d:d2:4e:74:06:4a:
+ c4:3b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ CA:CF:14:CE:08:5C:4B:71:AD:DE:DA:70:78:A9:D1:D6:7F:25:76:E4
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 31:f4:da:87:3f:e3:55:1a:c6:e4:fc:71:23:9e:51:de:88:89:
+ f2:c7:b3:7c:8b:f7:c1:71:3a:bc:bd:ff:61:43:2a:3b:4c:6c:
+ 2c:eb:7c:f6:00:37:e1:0a:fc:2f:01:73:73:d7:b9:b8:dc:fa:
+ 6e:10:fc:55:2b:d6:d3:95:09:27:de:97:28:d5:b6:48:19:a5:
+ 0b:13:d3:29:cf:80:86:36:39:41:c1:15:17:74:8c:d7:2f:f6:
+ 00:63:06:cb:cb:74:9b:2e:35:1c:b7:d8:38:db:a4:d2:63:c0:
+ f1:97:db:be:1d:10:bc:3b:67:59:99:0d:3e:5f:2d:52:38:ca:
+ 80:49:6f:b4:f3:e5:0a:d4:b3:96:ef:45:9c:a4:15:35:af:9c:
+ 04:fd:5a:22:0f:44:67:32:0e:79:47:37:87:fb:3c:fb:2f:0a:
+ 1d:b3:20:cd:f5:fe:71:f6:c8:f1:0e:f2:ed:8d:a4:8c:c3:af:
+ a0:ce:8e:49:a8:af:ec:55:2c:17:4f:03:7e:6a:a9:ff:ae:46:
+ 25:89:0c:54:d7:32:7b:9b:8f:a2:df:ac:44:a8:03:cc:56:9e:
+ d6:cb:f6:af:c9:e4:f8:de:68:4d:0c:11:20:ac:5b:d2:e8:07:
+ b2:29:6f:27:b5:29:a8:fa:09:9d:f1:a1:f7:2c:72:05:07:7d:
+ 31:1e:98:d4
+-----BEGIN CERTIFICATE-----
+MIIC+zCCAeOgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UEAwwWRSBS
+b290IENBIC0gTXVsdGktcm9vdDAeFw0xNjAxMDIwMDAwMDBaFw0yNjAxMDIwMDAw
+MDBaMBwxGjAYBgNVBAMMEUYgQ0EgLSBNdWx0aS1yb290MIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAnUF5iJOr/uZSKISRncKFoCyXOWklIEOFjNtkj0H0
+tSXmPhZB+kC3bCz8EXZ9hrdHc2iu6Sx+XYshaIZxEc0h+RagIGeseUDQlOa/ot1l
+r9rTxSOCCqIcp7x98MKoCzDKINYxXyjIdEsJHlDe1FHZnPU9/rCN7hHyIj4RCVMj
+d1Jcz43dbDvEORszwgC8NC3m3J2v6DbsrMfkcwlErVmNUcHuEWBbtcnYy0iw+QpX
+ONjjvsVOOH5HPyRmoRE9LZ/KStxZWP3MViLH1clwL+xmgU3uSDmX7922AjSykNsW
+pGCdGN6Vh6EUbhmriEI3V88gxNjjxiSNvP1N0k50BkrEOwIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBTKzxTOCFxLca3e2nB4qdHWfyV25DAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBADH02oc/41UaxuT8cSOeUd6I
+ifLHs3yL98FxOry9/2FDKjtMbCzrfPYAN+EK/C8Bc3PXubjc+m4Q/FUr1tOVCSfe
+lyjVtkgZpQsT0ynPgIY2OUHBFRd0jNcv9gBjBsvLdJsuNRy32DjbpNJjwPGX274d
+ELw7Z1mZDT5fLVI4yoBJb7Tz5QrUs5bvRZykFTWvnAT9WiIPRGcyDnlHN4f7PPsv
+Ch2zIM31/nH2yPEO8u2NpIzDr6DOjkmor+xVLBdPA35qqf+uRiWJDFTXMnubj6Lf
+rESoA8xWntbL9q/J5PjeaE0MESCsW9LoB7Ipbye1Kaj6CZ3xofcscgUHfTEemNQ=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/multi-root-chain1.pem b/chromium/net/data/ssl/certificates/multi-root-chain1.pem
index d0578659491..9861944b7a7 100644
--- a/chromium/net/data/ssl/certificates/multi-root-chain1.pem
+++ b/chromium/net/data/ssl/certificates/multi-root-chain1.pem
@@ -1,328 +1,303 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEAzDKsONWbnA5Lau2SquZbKzmbj0hH0A2cPWjVR6O4YadTgD7M
-jUMRs+TJsYt42rXtEX2kTDXtkOsweRv/SJSGvh31uLBhQH/X1ZCFuOAUujqm+6vx
-JRN1RYqSvcXUGOf+LasWutPgAPULz/8AKHX23Uue0RtuWv+3wH2Eck2wno+S7IHR
-fGWP+W9fsuoGVyo0Iy3nd02BZtKCZeQUd9neAnkm8qSBssPbD2zi2OAve5MVsCkd
-oQAWhw0Jc0QArZ6m33AEZu3hvj3s64Rn1/VAmSjrxipWPZEayVplVrlLCeO/LBkQ
-oCRCTcQVhQVJnXFS00t7U2jHKjwnfajTwn7k/wIDAQABAoIBAQCKdiXP2BBPLmY3
-WGbmmZLiaYqxCqsfSctS3L4aeMqy9Poq8OpVM1BSsmWNjWxiqY/aF18MCllPthrF
-VJWzCnufeMNA++DGEqow93GlXdTQPqsx5nJ62InhoMhGBFoAlXcGUof0IW04WPEs
-ldXumabOgdNsKXSYIePgk3v24fVMXgnvj1TxgMhtSSP5vmP8h0/7pNnnfjWrBZNg
-B2bVqCYQ6AaxHRivLFsD85nBdSXl8La5lfoSCgvpWHKtIUvUeZrBAagxK2gGj6zg
-sJvKs4EnGUdzX0eGheLaJtdVXEdxWIj9HmusLFF02wvgq5yS6Hyj1hz6YHaJomb5
-mHGVcBDZAoGBAPNTRlNfiZ9fB21FFEufPx7YxEbqS4BFthBqLfatG8fM1gRkbz9m
-Dy/FSmgPQMxaqA5vjE8jhVlVTOCXznT8TsAhuof/ORmmFDvHleJs1iaqw/xhgOJv
-avMc+BZTOktBX4u9E4wSVwj+QfhutssCeG+SHtS9uVyiGAVUSIyhCNNjAoGBANbV
-ozqAElO7pF0frWIIZ7gGbPuEIULVqWhNQWZF19gvBf8sJQ+gfT0OhPRvopr734sc
-+/m2b1PORFVGVPmRYMXrNds7qvtFzoDSvki0X3dsi6TXFSY7lTI4lAyvCOxQcjbM
-x8sD9Csaips/i3EAV885BkG2QPMH+jEmp5U0y9C1AoGBAIgDsroEG4/ktOgVx0SG
-XehGT2E8srufPChs0gijt3W2QKPv6GfOCwsvA2qrrBMPUgXPwOSz/GR1VCXvdc7b
-AsJPmE9REYAO4ByScmxBXmv65Nb9QehRU71WIi+IkntiraAVLwoLbm9ugT331WIh
-nWTwjx9odmcbjMXd2TgTBDX1AoGAYysCygJMc3JukL4KnvIaToxIymFXqS5PoOHo
-ink7BYPPVNbf1LLUnNaS8PKHMNuLeP/MIJziDuFsEaEBoKJG9ZV5qtWEO7Ehfb3K
-MG1ylAH7BAB0ts1SNXiAfspdaBhKYJlusHwGvc7mpHtUtrjdz74W8UZb/NN13jJl
-sS5J1vECgYEAnpWIaGs3BCJWW8BSuuOx6NMSwFDfcpzqnJ6KvowdWVkW7lYK7kfZ
-JIZnNragGbybBDUcUcdSdz+V0GtzUj6oKYI420debUlQ6/Xc+Yud+esqf23ODS3A
-MsuJkwHALBIiocA552KN4Bsd69HRd91r/14G5BXtsjpsfhCXVPJreJ0=
------END RSA PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4096 (0x1000)
Signature Algorithm: sha256WithRSAEncryption
- Issuer: CN=B CA
+ Issuer: CN=B CA - Multi-root
Validity
- Not Before: Aug 14 02:47:31 2014 GMT
- Not After : Aug 11 02:47:31 2024 GMT
+ Not Before: Mar 11 01:37:16 2016 GMT
+ Not After : Mar 9 01:37:16 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:cc:32:ac:38:d5:9b:9c:0e:4b:6a:ed:92:aa:e6:
- 5b:2b:39:9b:8f:48:47:d0:0d:9c:3d:68:d5:47:a3:
- b8:61:a7:53:80:3e:cc:8d:43:11:b3:e4:c9:b1:8b:
- 78:da:b5:ed:11:7d:a4:4c:35:ed:90:eb:30:79:1b:
- ff:48:94:86:be:1d:f5:b8:b0:61:40:7f:d7:d5:90:
- 85:b8:e0:14:ba:3a:a6:fb:ab:f1:25:13:75:45:8a:
- 92:bd:c5:d4:18:e7:fe:2d:ab:16:ba:d3:e0:00:f5:
- 0b:cf:ff:00:28:75:f6:dd:4b:9e:d1:1b:6e:5a:ff:
- b7:c0:7d:84:72:4d:b0:9e:8f:92:ec:81:d1:7c:65:
- 8f:f9:6f:5f:b2:ea:06:57:2a:34:23:2d:e7:77:4d:
- 81:66:d2:82:65:e4:14:77:d9:de:02:79:26:f2:a4:
- 81:b2:c3:db:0f:6c:e2:d8:e0:2f:7b:93:15:b0:29:
- 1d:a1:00:16:87:0d:09:73:44:00:ad:9e:a6:df:70:
- 04:66:ed:e1:be:3d:ec:eb:84:67:d7:f5:40:99:28:
- eb:c6:2a:56:3d:91:1a:c9:5a:65:56:b9:4b:09:e3:
- bf:2c:19:10:a0:24:42:4d:c4:15:85:05:49:9d:71:
- 52:d3:4b:7b:53:68:c7:2a:3c:27:7d:a8:d3:c2:7e:
- e4:ff
+ 00:c8:27:1c:19:81:c0:a7:30:93:03:1c:f8:21:b8:
+ 2f:8a:22:b4:89:0f:da:b1:40:95:df:dc:46:53:fc:
+ 6f:36:26:66:5a:53:6d:45:78:c2:39:16:9a:3f:82:
+ 8b:ba:c5:b0:78:a8:18:bc:d5:a7:92:a5:e6:ac:e2:
+ 0c:81:d0:94:e5:0c:ec:5e:03:0c:17:c5:35:2a:7b:
+ ab:86:eb:bf:e8:62:0a:8f:b0:25:b2:70:f5:11:8c:
+ 16:4f:c1:76:44:e5:75:e8:93:4f:e9:e7:c4:e4:42:
+ 0a:08:be:73:2c:cb:8f:73:6a:40:77:eb:33:60:ac:
+ be:c5:27:fd:b1:4f:88:4b:15:af:98:fd:32:53:ae:
+ b0:2a:0c:b2:f5:05:f3:3a:06:0d:6e:5c:fe:83:fc:
+ e3:60:ae:99:8e:a1:21:c2:72:02:e6:f4:49:57:e6:
+ 91:31:2e:be:92:a1:ad:f8:71:31:64:74:10:33:d0:
+ a7:0c:ed:18:c7:b2:50:71:fc:b9:b6:ae:95:a0:8d:
+ ac:1f:3c:d5:79:a7:a9:88:50:b6:02:cd:68:60:24:
+ 45:9b:b6:e9:82:08:d9:9c:d4:7e:29:7d:2b:d9:ae:
+ 57:7f:62:6a:56:96:8b:4a:33:9e:5f:93:82:b0:d1:
+ 05:03:26:cd:15:f4:87:7f:6a:9a:df:e9:01:b5:d4:
+ c9:11
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
- 7A:DF:61:82:66:73:E5:9F:E2:84:99:26:22:18:18:2D:5C:5B:36:A7
+ FB:91:A9:5F:BC:27:81:98:55:30:BF:57:32:4D:B9:DA:56:DD:52:2C
X509v3 Authority Key Identifier:
- keyid:76:7F:E8:F6:A1:F7:91:56:BD:9C:7E:66:5C:97:F0:A5:1D:6C:06:28
+ keyid:90:CB:53:EE:36:0A:5A:B0:93:38:C9:11:B7:AC:FD:27:71:99:DC:81
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
- 59:31:d6:e2:3c:0e:31:c5:5c:a4:40:51:5d:eb:15:3d:2e:58:
- 13:c6:0f:26:cf:86:f7:ee:d1:30:31:81:83:86:83:ea:be:1c:
- bd:c9:20:6e:a0:47:4c:46:38:2e:1e:8f:70:da:80:38:f4:d7:
- 9c:59:9d:7f:23:d8:2a:c9:fe:fe:e9:57:5f:d9:69:58:e6:86:
- 19:af:3b:08:a1:ad:50:e5:c4:e8:33:c9:44:66:8c:12:b9:02:
- 19:4f:a7:18:a0:48:34:58:14:2d:c0:dc:44:b8:d9:ce:76:01:
- 21:0e:51:a8:7b:ba:db:93:e4:65:ab:b2:cb:b9:e1:30:26:b5:
- 9e:5e:df:62:15:86:45:99:f9:25:03:e3:b9:36:7f:8c:a7:e2:
- 85:d1:ac:09:5b:9f:d5:e3:ad:e5:a2:9b:e0:75:f0:61:8d:cd:
- b8:9d:5e:2f:b4:92:aa:6b:ca:05:95:84:b9:27:bd:e4:1e:d9:
- b6:74:1d:db:ec:08:35:39:a3:c0:64:7c:ab:86:8a:74:06:e1:
- 4d:f1:e6:bd:81:5d:2b:be:4d:d9:b2:b0:6e:cb:0a:df:e8:6d:
- 64:b3:c6:5a:28:22:82:d5:5b:e2:9e:84:1e:d1:06:1d:32:1b:
- 05:26:fd:e8:19:c9:25:81:4b:f7:78:09:b7:16:a1:63:82:b0:
- 79:68:89:72
+ b9:31:7a:95:b2:ba:3a:b4:f1:16:76:df:eb:d5:b9:af:67:b1:
+ 9d:8a:27:04:9b:61:6f:42:3f:c2:b3:cd:65:c4:86:cb:90:fb:
+ 9d:3a:ed:fc:b8:74:da:d7:6a:6c:2f:17:68:d1:73:58:f1:a2:
+ bb:8f:d6:b0:a8:7f:b6:a8:b0:74:d1:ea:c4:62:ed:bc:1e:ef:
+ 02:6b:d5:e8:2d:15:78:16:1e:90:fa:f4:29:5a:a8:43:ad:d2:
+ 58:40:b4:1c:60:4e:cd:bc:6f:1a:39:e4:46:b2:58:93:96:5a:
+ a8:a4:c4:31:73:ed:89:c4:81:27:e1:4c:66:20:7c:27:c4:f9:
+ 61:ff:d1:d5:a5:02:93:4c:06:fa:15:33:7a:1f:5f:eb:29:b2:
+ b5:6a:cd:7e:d6:d7:b7:51:a7:01:2f:22:9f:9e:7e:81:98:c4:
+ 72:11:36:2c:e7:c6:d0:f0:7d:98:36:ea:b7:a0:aa:13:8f:6e:
+ ae:41:59:9b:e6:c9:bc:9c:e8:93:f5:0c:4e:ca:b4:dd:e3:01:
+ fe:23:6e:fb:fa:b3:61:66:58:f5:fc:07:16:1d:a9:52:ec:a0:
+ 29:61:a4:39:ed:41:50:a3:a2:33:72:0e:3c:03:e1:0a:1a:1a:
+ cf:22:73:09:d7:ea:e8:15:fc:73:3c:d4:4e:34:6c:b4:18:94:
+ c4:d3:6e:12
-----BEGIN CERTIFICATE-----
-MIIDWjCCAkKgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEQiBD
-QTAeFw0xNDA4MTQwMjQ3MzFaFw0yNDA4MTEwMjQ3MzFaMGAxCzAJBgNVBAYTAlVT
-MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAw
-DgYDVQQKDAdUZXN0IENBMRIwEAYDVQQDDAkxMjcuMC4wLjEwggEiMA0GCSqGSIb3
-DQEBAQUAA4IBDwAwggEKAoIBAQDMMqw41ZucDktq7ZKq5lsrOZuPSEfQDZw9aNVH
-o7hhp1OAPsyNQxGz5Mmxi3jate0RfaRMNe2Q6zB5G/9IlIa+HfW4sGFAf9fVkIW4
-4BS6Oqb7q/ElE3VFipK9xdQY5/4tqxa60+AA9QvP/wAodfbdS57RG25a/7fAfYRy
-TbCej5LsgdF8ZY/5b1+y6gZXKjQjLed3TYFm0oJl5BR32d4CeSbypIGyw9sPbOLY
-4C97kxWwKR2hABaHDQlzRACtnqbfcARm7eG+PezrhGfX9UCZKOvGKlY9kRrJWmVW
-uUsJ478sGRCgJEJNxBWFBUmdcVLTS3tTaMcqPCd9qNPCfuT/AgMBAAGjbzBtMAwG
-A1UdEwEB/wQCMAAwHQYDVR0OBBYEFHrfYYJmc+Wf4oSZJiIYGC1cWzanMB8GA1Ud
-IwQYMBaAFHZ/6Pah95FWvZx+ZlyX8KUdbAYoMB0GA1UdJQQWMBQGCCsGAQUFBwMB
-BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAWTHW4jwOMcVcpEBRXesVPS5Y
-E8YPJs+G9+7RMDGBg4aD6r4cvckgbqBHTEY4Lh6PcNqAOPTXnFmdfyPYKsn+/ulX
-X9lpWOaGGa87CKGtUOXE6DPJRGaMErkCGU+nGKBINFgULcDcRLjZznYBIQ5RqHu6
-25PkZauyy7nhMCa1nl7fYhWGRZn5JQPjuTZ/jKfihdGsCVuf1eOt5aKb4HXwYY3N
-uJ1eL7SSqmvKBZWEuSe95B7ZtnQd2+wINTmjwGR8q4aKdAbhTfHmvYFdK75N2bKw
-bssK3+htZLPGWigigtVb4p6EHtEGHTIbBSb96BnJJYFL93gJtxahY4KweWiJcg==
+MIIDZzCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwHDEaMBgGA1UEAwwRQiBD
+QSAtIE11bHRpLXJvb3QwHhcNMTYwMzExMDEzNzE2WhcNMjYwMzA5MDEzNzE2WjBg
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4x
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyCccGYHApzCTAxz4Ibgv
+iiK0iQ/asUCV39xGU/xvNiZmWlNtRXjCORaaP4KLusWweKgYvNWnkqXmrOIMgdCU
+5QzsXgMMF8U1Knurhuu/6GIKj7AlsnD1EYwWT8F2ROV16JNP6efE5EIKCL5zLMuP
+c2pAd+szYKy+xSf9sU+ISxWvmP0yU66wKgyy9QXzOgYNblz+g/zjYK6ZjqEhwnIC
+5vRJV+aRMS6+kqGt+HExZHQQM9CnDO0Yx7JQcfy5tq6VoI2sHzzVeaepiFC2As1o
+YCRFm7bpggjZnNR+KX0r2a5Xf2JqVpaLSjOeX5OCsNEFAybNFfSHf2qa3+kBtdTJ
+EQIDAQABo28wbTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBT7kalfvCeBmFUwv1cy
+TbnaVt1SLDAfBgNVHSMEGDAWgBSQy1PuNgpasJM4yRG3rP0ncZncgTAdBgNVHSUE
+FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBALkxepWy
+ujq08RZ23+vVua9nsZ2KJwSbYW9CP8KzzWXEhsuQ+5067fy4dNrXamwvF2jRc1jx
+oruP1rCof7aosHTR6sRi7bwe7wJr1egtFXgWHpD69ClaqEOt0lhAtBxgTs28bxo5
+5EayWJOWWqikxDFz7YnEgSfhTGYgfCfE+WH/0dWlApNMBvoVM3ofX+spsrVqzX7W
+17dRpwEvIp+efoGYxHIRNiznxtDwfZg26regqhOPbq5BWZvmybyc6JP1DE7KtN3j
+Af4jbvv6s2FmWPX8BxYdqVLsoClhpDntQVCjojNyDjwD4QoaGs8icwnX6ugV/HM8
+1E40bLQYlMTTbhI=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 4097 (0x1001)
+ Serial Number: 4096 (0x1000)
Signature Algorithm: sha256WithRSAEncryption
- Issuer: CN=C CA
+ Issuer: CN=C CA - Multi-root
Validity
- Not Before: Aug 14 02:47:31 2014 GMT
- Not After : Aug 11 02:47:31 2024 GMT
- Subject: CN=B CA
+ Not Before: Jan 4 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=B CA - Multi-root
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:af:0f:4e:5f:ef:a4:fe:fc:3e:e4:30:fa:e3:d5:
- 9a:9f:32:e2:64:a3:d9:4a:80:f4:1d:51:19:88:79:
- fe:1f:a0:02:f5:55:e3:66:03:32:51:20:15:55:09:
- 48:e5:28:87:0e:95:f3:fc:4d:15:4c:34:ce:eb:e4:
- 53:0a:44:72:db:ca:b4:53:72:74:34:82:33:ee:51:
- 46:fa:9b:95:5a:cf:2a:da:ba:ae:46:c7:f2:da:0b:
- b9:db:ea:8f:8d:09:98:a1:d4:a9:48:85:fd:d4:3c:
- 59:69:90:e9:9c:91:88:6e:af:3b:16:ec:66:7d:a8:
- 1f:5b:4d:d9:64:19:ed:8d:e1:11:db:d6:1e:24:05:
- 8b:25:17:41:9f:a2:99:17:19:9a:d5:a2:00:93:c2:
- 2d:f0:34:aa:84:39:82:ff:e8:cd:2d:62:82:33:5d:
- 07:6b:35:b6:74:cc:10:c2:9e:69:f4:54:2a:45:17:
- 0f:d7:7c:f2:6d:22:c5:be:55:11:3c:40:25:24:f9:
- 88:79:f7:32:eb:2a:5a:00:cd:fe:29:fa:14:74:67:
- 24:62:51:f3:76:d7:e2:2f:7f:10:15:2d:a8:1c:17:
- c6:9b:ab:be:f3:4b:16:30:f1:82:8c:e7:da:f0:9e:
- 4e:14:1b:5d:92:41:61:ce:26:c0:53:7b:1d:21:b5:
- 73:9f
+ 00:ca:e9:f3:21:f4:a0:e7:ba:82:8c:7f:b3:98:44:
+ 20:4a:9a:8b:f9:e5:0c:99:c4:22:72:f7:57:7c:1e:
+ cc:56:4c:c3:f5:fd:1e:90:a5:1c:bf:2c:c4:c4:29:
+ 29:38:cc:26:9e:1a:1d:e3:e4:db:97:58:35:14:e8:
+ e2:db:37:05:1c:32:f7:bb:19:22:c2:37:3f:01:76:
+ 8c:17:23:ca:fc:10:69:b4:d1:74:27:b6:10:7e:b7:
+ c1:07:a2:a1:af:18:4d:5c:2e:13:72:a9:fb:64:b1:
+ e7:9f:49:41:3c:dc:b8:5f:94:e6:68:05:a5:1f:c8:
+ 56:84:e2:e5:6a:84:71:9c:b8:ac:3e:ec:8e:0c:d2:
+ f2:5f:11:fd:f4:7f:40:a7:3b:08:01:bb:fd:6f:d0:
+ a9:16:1d:14:a1:28:20:30:98:ba:1e:22:4e:5b:09:
+ b9:c1:df:17:60:1b:80:43:97:49:69:cd:6a:4e:58:
+ 08:9c:dc:29:57:3f:1b:bf:d8:5f:32:94:ae:97:b2:
+ d4:8d:50:1a:d1:8b:03:84:00:fd:87:d9:2e:ed:91:
+ 3d:3f:b7:89:54:46:0a:cd:db:10:62:80:47:60:21:
+ b3:1d:0e:bc:41:4d:86:d4:9d:52:1b:53:82:1a:9f:
+ 46:91:98:1e:ed:9f:da:69:16:64:24:1c:de:f8:b3:
+ 34:69
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
- 76:7F:E8:F6:A1:F7:91:56:BD:9C:7E:66:5C:97:F0:A5:1D:6C:06:28
+ 90:CB:53:EE:36:0A:5A:B0:93:38:C9:11:B7:AC:FD:27:71:99:DC:81
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
Signature Algorithm: sha256WithRSAEncryption
- bc:3e:d1:ed:69:da:91:cf:32:bc:0f:39:17:ec:d5:37:46:1e:
- 0e:d9:d3:78:d8:62:ea:03:d3:1c:d0:c6:34:45:cb:b2:50:ce:
- e2:03:96:a7:43:3f:1c:ff:58:93:70:bf:b2:98:e8:31:21:be:
- b6:89:e7:dc:ae:9d:5d:12:36:78:6f:ef:cc:be:b3:bb:ec:27:
- d4:56:ef:69:49:d8:cd:33:7a:ec:76:34:de:bd:91:3f:b1:9c:
- 67:23:94:fa:60:44:82:47:30:c1:84:f8:a5:d3:e1:fb:cf:c0:
- bd:53:fb:a9:ef:96:79:aa:34:4a:d1:b3:e4:f2:68:a4:d3:a8:
- 75:1c:19:a7:42:a7:62:0b:46:b8:e0:05:3d:c6:51:2c:77:09:
- a1:fc:b7:e8:a6:5d:b6:d2:9d:75:09:2b:5c:b7:00:42:31:a4:
- be:ea:c5:3c:3d:9f:02:8d:69:bc:d0:ad:d5:1c:99:51:4c:3e:
- 0b:96:47:c5:85:79:3c:10:5b:5c:9e:e8:a7:ee:f2:46:47:b4:
- fc:13:94:7b:1d:a5:3f:da:b0:3c:7a:08:bd:9e:1d:36:44:27:
- 0a:ab:07:b3:91:d0:ba:d2:6a:d5:a0:a5:91:62:b1:73:0b:07:
- 07:6f:00:e9:6a:e7:f5:60:cb:f6:84:38:8b:2e:5e:02:dd:7e:
- f3:d9:1e:1d
+ 97:cd:ae:5a:26:f4:25:f6:c0:8b:08:d8:df:82:35:d8:76:f3:
+ 5d:cc:99:bd:ac:70:c9:41:e0:24:c8:fd:e6:4e:41:2c:d4:69:
+ 8d:08:25:fd:f3:32:3a:58:0b:d3:58:9c:81:51:bf:97:a4:bc:
+ 00:18:1c:4f:1c:54:04:63:e3:72:87:f4:dc:9e:7b:dc:da:5d:
+ e1:ef:59:6b:f0:1f:3d:0c:11:55:1e:9a:1a:d8:8d:bc:7b:18:
+ b7:4f:92:1c:68:73:82:ec:f3:69:48:0a:86:40:4a:a5:6f:ae:
+ 8f:10:2e:12:0b:e8:7e:b9:bc:d7:26:f0:cf:f4:0f:5b:77:f2:
+ ff:77:28:b4:5f:5e:ef:65:08:21:b8:f9:1e:56:b9:69:3b:c4:
+ 7f:01:88:c9:7c:ca:d0:e2:df:e5:5e:8d:e9:2e:7d:4a:78:04:
+ 8b:c1:dc:d4:58:ac:90:fc:5c:8e:48:2b:60:99:63:37:3f:e5:
+ 61:da:8f:58:9f:4d:0a:ee:6c:8d:bc:1f:7e:c4:be:0f:32:4b:
+ 11:7a:28:bf:dd:d0:a0:40:42:a8:43:4d:0b:2f:01:0e:73:de:
+ 1b:a6:df:49:57:58:89:57:c0:23:76:83:f0:9a:0e:83:d9:9b:
+ cb:eb:ac:3f:89:d1:e8:3c:3e:f1:d5:80:0c:38:18:02:5c:5f:
+ e5:68:5e:cf
-----BEGIN CERTIFICATE-----
-MIIC3DCCAcSgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEQyBD
-QTAeFw0xNDA4MTQwMjQ3MzFaFw0yNDA4MTEwMjQ3MzFaMA8xDTALBgNVBAMMBEIg
-Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvD05f76T+/D7kMPrj
-1ZqfMuJko9lKgPQdURmIef4foAL1VeNmAzJRIBVVCUjlKIcOlfP8TRVMNM7r5FMK
-RHLbyrRTcnQ0gjPuUUb6m5Vazyrauq5Gx/LaC7nb6o+NCZih1KlIhf3UPFlpkOmc
-kYhurzsW7GZ9qB9bTdlkGe2N4RHb1h4kBYslF0GfopkXGZrVogCTwi3wNKqEOYL/
-6M0tYoIzXQdrNbZ0zBDCnmn0VCpFFw/XfPJtIsW+VRE8QCUk+Yh59zLrKloAzf4p
-+hR0ZyRiUfN21+IvfxAVLagcF8abq77zSxYw8YKM59rwnk4UG12SQWHOJsBTex0h
-tXOfAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHZ/6Pah95FW
-vZx+ZlyX8KUdbAYoMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEA
-vD7R7Wnakc8yvA85F+zVN0YeDtnTeNhi6gPTHNDGNEXLslDO4gOWp0M/HP9Yk3C/
-spjoMSG+tonn3K6dXRI2eG/vzL6zu+wn1FbvaUnYzTN67HY03r2RP7GcZyOU+mBE
-gkcwwYT4pdPh+8/AvVP7qe+Weao0StGz5PJopNOodRwZp0KnYgtGuOAFPcZRLHcJ
-ofy36KZdttKddQkrXLcAQjGkvurFPD2fAo1pvNCt1RyZUUw+C5ZHxYV5PBBbXJ7o
-p+7yRke0/BOUex2lP9qwPHoIvZ4dNkQnCqsHs5HQutJq1aClkWKxcwsHB28A6Wrn
-9WDL9oQ4iy5eAt1+89keHQ==
+MIIC9jCCAd6gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwHDEaMBgGA1UEAwwRQyBD
+QSAtIE11bHRpLXJvb3QwHhcNMTYwMTA0MDAwMDAwWhcNMjYwMTAyMDAwMDAwWjAc
+MRowGAYDVQQDDBFCIENBIC0gTXVsdGktcm9vdDCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMrp8yH0oOe6gox/s5hEIEqai/nlDJnEInL3V3wezFZMw/X9
+HpClHL8sxMQpKTjMJp4aHePk25dYNRTo4ts3BRwy97sZIsI3PwF2jBcjyvwQabTR
+dCe2EH63wQeioa8YTVwuE3Kp+2Sx559JQTzcuF+U5mgFpR/IVoTi5WqEcZy4rD7s
+jgzS8l8R/fR/QKc7CAG7/W/QqRYdFKEoIDCYuh4iTlsJucHfF2AbgEOXSWnNak5Y
+CJzcKVc/G7/YXzKUrpey1I1QGtGLA4QA/YfZLu2RPT+3iVRGCs3bEGKAR2Ahsx0O
+vEFNhtSdUhtTghqfRpGYHu2f2mkWZCQc3vizNGkCAwEAAaNCMEAwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUkMtT7jYKWrCTOMkRt6z9J3GZ3IEwDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQCXza5aJvQl9sCLCNjfgjXYdvNdzJm9
+rHDJQeAkyP3mTkEs1GmNCCX98zI6WAvTWJyBUb+XpLwAGBxPHFQEY+Nyh/Tcnnvc
+2l3h71lr8B89DBFVHpoa2I28exi3T5IcaHOC7PNpSAqGQEqlb66PEC4SC+h+ubzX
+JvDP9A9bd/L/dyi0X17vZQghuPkeVrlpO8R/AYjJfMrQ4t/lXo3pLn1KeASLwdzU
+WKyQ/FyOSCtgmWM3P+Vh2o9Yn00K7myNvB9+xL4PMksReii/3dCgQEKoQ00LLwEO
+c94bpt9JV1iJV8AjdoPwmg6D2ZvL66w/idHoPD7x1YAMOBgCXF/laF7P
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 4099 (0x1003)
+ Serial Number: 4097 (0x1001)
Signature Algorithm: sha256WithRSAEncryption
- Issuer: CN=D Root CA
+ Issuer: CN=D Root CA - Multi-root
Validity
- Not Before: Aug 14 02:47:31 2014 GMT
- Not After : Aug 11 02:47:31 2024 GMT
- Subject: CN=C CA
+ Not Before: Jan 3 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=C CA - Multi-root
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:ce:78:cf:1a:cb:5f:9f:b8:fb:9b:35:ee:dd:24:
- f1:6a:f4:cc:6a:63:1f:89:20:20:be:51:ba:2b:a5:
- e1:46:ad:df:4e:1e:ab:8d:2c:7b:ac:8f:d4:a1:48:
- f0:72:51:d8:4a:a4:b7:7c:c1:cd:92:c2:4d:74:d7:
- 43:e5:58:66:73:57:5d:e0:a6:30:72:38:ad:7a:04:
- 1a:45:4a:19:72:16:06:e1:3e:04:fa:06:29:69:61:
- 62:48:af:51:17:4f:31:a2:65:6b:61:9d:5a:54:91:
- f9:67:47:7b:4e:37:60:3a:86:03:cd:68:df:5c:a8:
- 0a:d0:33:e7:51:b0:b3:be:ba:90:9b:d1:e3:69:6e:
- 5c:17:9a:b2:5b:cf:af:c5:6a:fd:32:f5:56:06:8c:
- d8:11:dd:ed:fd:09:1f:88:6e:e3:e5:49:21:70:e2:
- c3:ff:f9:04:fd:09:62:e4:24:a0:f8:63:7b:e8:2d:
- c7:41:cf:b5:6f:76:8a:25:3f:a3:27:df:16:d0:cd:
- 74:ac:c2:91:16:6d:00:1e:73:f0:19:f6:08:70:bd:
- d1:46:82:82:ac:98:1b:df:a0:7c:c7:39:f6:ce:0a:
- f8:64:f6:3a:60:9b:f0:61:6d:24:9c:d9:bd:6e:38:
- f1:78:19:2b:7f:e8:c0:e3:e7:85:93:02:6e:8c:6d:
- 09:f7
+ 00:b6:1f:67:e4:9e:db:e0:ff:eb:29:75:ee:68:a2:
+ 4e:95:6e:d2:f6:9d:c9:b6:dc:08:18:70:b5:76:bf:
+ b7:14:8b:cb:46:c6:6a:2c:fa:43:f9:54:93:fa:bd:
+ aa:f0:ee:a3:20:5b:2a:cd:08:f7:be:95:36:e4:88:
+ f8:fd:43:7d:b8:f9:38:b4:d2:4e:22:0b:8b:85:de:
+ 6a:fe:6f:da:3b:4b:0f:26:c1:f8:31:22:36:19:96:
+ 0c:ef:85:7c:72:67:ac:4c:5c:f9:23:a4:29:d8:a5:
+ 1c:b6:ec:95:eb:d3:c2:8d:cb:ae:9a:d7:08:c8:b7:
+ f7:a0:c6:28:44:5f:24:97:bd:ca:d9:6d:99:9b:17:
+ 47:1f:38:b3:e3:67:6a:b4:75:d6:92:cd:67:62:20:
+ 58:f0:a7:46:85:94:72:76:98:c5:ec:4c:75:1b:a1:
+ 76:67:4b:1f:c8:23:6c:2a:78:66:c2:a7:6b:af:ef:
+ 97:30:34:60:0a:db:98:94:3b:9f:95:3c:34:b6:35:
+ 40:12:fa:1d:bf:66:f4:7b:fd:66:1a:2a:49:8c:24:
+ 60:91:08:f9:61:39:f9:3b:29:98:64:7b:35:04:a9:
+ f5:af:8d:0f:1e:e7:28:b6:30:32:b4:5f:d4:29:16:
+ 7a:70:8d:db:b9:ba:bf:eb:22:98:5d:94:c8:47:e3:
+ 4b:11
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
- 51:35:6F:D5:40:65:74:E3:C8:7B:0C:47:12:B5:FC:58:73:7C:16:D1
+ 90:53:F5:80:11:F6:3F:1B:A8:9D:8D:75:0D:56:3B:F2:2B:C5:9C:44
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
Signature Algorithm: sha256WithRSAEncryption
- 93:da:2d:fb:32:eb:ce:98:0d:0a:8b:53:17:0f:c9:42:cb:b4:
- 70:2d:56:5c:b0:dc:70:2a:d6:2a:b9:21:76:c2:a8:ef:c0:6b:
- 7c:ec:d8:c3:1f:e1:7f:41:8d:8a:bd:18:ea:90:08:77:72:19:
- c6:aa:97:59:fc:dd:31:e6:73:bb:a6:01:9f:a8:f0:a9:5e:ab:
- 14:9a:6d:75:2f:c7:3b:67:a6:4f:74:05:cd:3e:13:c1:e9:39:
- 52:99:50:7f:7c:1e:dc:8b:50:40:87:07:30:6d:fb:2b:b9:a0:
- 6e:4a:da:3c:ae:66:94:3b:49:a2:e0:24:16:80:d7:8b:56:79:
- 4e:b8:6f:1d:f9:9a:21:73:48:bb:11:f8:2e:f9:aa:f4:49:09:
- fb:98:6b:87:b8:7b:62:e7:cc:cd:cb:b7:14:1a:d4:38:51:ed:
- b3:4c:9f:62:b7:a8:23:e5:f4:1c:a9:e5:d3:2a:61:02:00:83:
- 3f:e3:35:a9:50:29:2b:20:51:dd:9f:a4:05:56:bc:2c:0a:a7:
- c2:c0:ac:85:48:b0:8f:be:e5:d0:76:81:45:5a:61:8d:65:c6:
- 0e:88:21:70:fb:5a:d1:37:ea:dc:d3:a4:c0:43:c8:98:06:b6:
- 37:95:14:76:fb:84:97:9f:ca:92:4e:a4:06:23:d1:1a:ce:1f:
- 36:3c:a1:47
+ 67:11:95:f4:b9:cb:47:e6:50:da:fd:a0:13:78:d7:e1:be:59:
+ ec:86:32:e5:56:3e:9b:8f:db:b0:3b:93:fb:d0:6e:b3:de:7e:
+ 10:5b:b4:30:f7:02:e8:3f:ff:4e:91:3a:e8:b8:4a:94:5e:14:
+ 7b:f8:84:e5:1f:63:2c:b4:7f:4f:ee:b1:d5:ee:92:79:7d:63:
+ 87:a0:e9:57:14:57:11:59:18:54:8b:e3:d1:51:80:a7:2f:51:
+ f2:6f:43:d2:87:e1:59:23:2c:fe:83:38:e1:25:da:b5:34:af:
+ 33:17:64:80:08:b6:bd:5f:92:05:2c:81:b0:c3:d3:80:cd:e1:
+ 5c:95:d2:ea:1e:d3:af:d9:93:c2:f4:23:ae:51:b0:a4:82:49:
+ 2d:ec:fe:d1:18:e3:a3:53:9f:63:4b:38:dc:54:25:ce:4c:90:
+ 37:02:e4:67:41:31:ba:7a:13:1a:68:1e:ed:34:0c:3d:66:ba:
+ a3:3a:71:76:5f:5f:89:a1:cd:95:50:f6:5d:1f:c0:91:31:93:
+ 5b:58:af:e7:9b:21:e6:57:b1:f4:d7:dd:c1:84:25:5b:83:f7:
+ 5f:c9:89:17:5b:6f:54:f2:8b:ed:47:de:27:57:9e:e9:8c:b3:
+ 58:2c:c2:77:25:e1:eb:22:06:d1:f6:c5:f4:d7:1a:3d:00:1c:
+ 2e:85:e9:70
-----BEGIN CERTIFICATE-----
-MIIC4TCCAcmgAwIBAgICEAMwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJRCBS
-b290IENBMB4XDTE0MDgxNDAyNDczMVoXDTI0MDgxMTAyNDczMVowDzENMAsGA1UE
-AwwEQyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM54zxrLX5+4
-+5s17t0k8Wr0zGpjH4kgIL5Ruiul4Uat304eq40se6yP1KFI8HJR2Eqkt3zBzZLC
-TXTXQ+VYZnNXXeCmMHI4rXoEGkVKGXIWBuE+BPoGKWlhYkivURdPMaJla2GdWlSR
-+WdHe043YDqGA81o31yoCtAz51Gws766kJvR42luXBeaslvPr8Vq/TL1VgaM2BHd
-7f0JH4hu4+VJIXDiw//5BP0JYuQkoPhje+gtx0HPtW92iiU/oyffFtDNdKzCkRZt
-AB5z8Bn2CHC90UaCgqyYG9+gfMc59s4K+GT2OmCb8GFtJJzZvW448XgZK3/owOPn
-hZMCboxtCfcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUUTVv
-1UBldOPIewxHErX8WHN8FtEwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUA
-A4IBAQCT2i37MuvOmA0Ki1MXD8lCy7RwLVZcsNxwKtYquSF2wqjvwGt87NjDH+F/
-QY2KvRjqkAh3chnGqpdZ/N0x5nO7pgGfqPCpXqsUmm11L8c7Z6ZPdAXNPhPB6TlS
-mVB/fB7ci1BAhwcwbfsruaBuSto8rmaUO0mi4CQWgNeLVnlOuG8d+Zohc0i7Efgu
-+ar0SQn7mGuHuHti58zNy7cUGtQ4Ue2zTJ9it6gj5fQcqeXTKmECAIM/4zWpUCkr
-IFHdn6QFVrwsCqfCwKyFSLCPvuXQdoFFWmGNZcYOiCFw+1rRN+rc06TAQ8iYBrY3
-lRR2+4SXn8qSTqQGI9Eazh82PKFH
+MIIC+zCCAeOgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UEAwwWRCBS
+b290IENBIC0gTXVsdGktcm9vdDAeFw0xNjAxMDMwMDAwMDBaFw0yNjAxMDIwMDAw
+MDBaMBwxGjAYBgNVBAMMEUMgQ0EgLSBNdWx0aS1yb290MIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAth9n5J7b4P/rKXXuaKJOlW7S9p3JttwIGHC1dr+3
+FIvLRsZqLPpD+VST+r2q8O6jIFsqzQj3vpU25Ij4/UN9uPk4tNJOIguLhd5q/m/a
+O0sPJsH4MSI2GZYM74V8cmesTFz5I6Qp2KUctuyV69PCjcuumtcIyLf3oMYoRF8k
+l73K2W2ZmxdHHziz42dqtHXWks1nYiBY8KdGhZRydpjF7Ex1G6F2Z0sfyCNsKnhm
+wqdrr++XMDRgCtuYlDuflTw0tjVAEvodv2b0e/1mGipJjCRgkQj5YTn5OymYZHs1
+BKn1r40PHucotjAytF/UKRZ6cI3bubq/6yKYXZTIR+NLEQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBSQU/WAEfY/G6idjXUNVjvyK8WcRDAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAGcRlfS5y0fmUNr9oBN41+G+
+WeyGMuVWPpuP27A7k/vQbrPefhBbtDD3Aug//06ROui4SpReFHv4hOUfYyy0f0/u
+sdXuknl9Y4eg6VcUVxFZGFSL49FRgKcvUfJvQ9KH4VkjLP6DOOEl2rU0rzMXZIAI
+tr1fkgUsgbDD04DN4VyV0uoe06/Zk8L0I65RsKSCSS3s/tEY46NTn2NLONxUJc5M
+kDcC5GdBMbp6ExpoHu00DD1muqM6cXZfX4mhzZVQ9l0fwJExk1tYr+ebIeZXsfTX
+3cGEJVuD91/JiRdbb1Tyi+1H3idXnumMs1gswncl4esiBtH2xfTXGj0AHC6F6XA=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 12250836319051526300 (0xaa03b6b97685309c)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: CN=D Root CA
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=D Root CA - Multi-root
Validity
- Not Before: Aug 14 02:47:31 2014 GMT
- Not After : Aug 11 02:47:31 2024 GMT
- Subject: CN=D Root CA
+ Not Before: Jan 2 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=D Root CA - Multi-root
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:c4:52:21:76:b2:08:c5:8f:63:c4:ec:37:5d:4d:
- 8c:26:63:fb:47:7c:fa:20:d1:54:9e:f4:82:bb:bc:
- 03:40:cd:6c:cc:65:07:f7:3b:63:7e:bf:c8:39:a1:
- 11:05:e3:e0:58:82:1c:ad:04:a2:08:16:08:c8:64:
- 44:09:7e:50:eb:6c:b7:5e:ee:51:81:1d:80:47:b2:
- 51:7e:ed:9b:37:79:0e:0a:06:61:7f:e0:26:0d:bb:
- 72:14:01:f0:a1:4d:71:fd:cc:c2:77:73:7a:bd:f4:
- 6a:08:35:5e:ee:02:2d:96:9a:aa:60:c3:5b:ba:79:
- 48:a3:7a:95:f9:d5:22:9c:7b:10:ca:8e:b2:57:d7:
- dd:7a:e9:c4:8d:79:7f:e9:71:04:15:4f:73:be:ed:
- 6a:04:f0:ce:9e:57:00:a2:92:92:c6:17:d3:05:c2:
- ef:86:45:50:f4:53:5e:97:62:f6:4a:ee:5f:fb:99:
- f9:bf:9c:47:27:63:5b:59:3e:06:3a:0c:5a:a4:9a:
- 7f:cd:bf:42:96:7c:ad:f5:06:98:d9:8a:f2:fe:a9:
- 1b:4b:c9:16:e1:ed:56:24:2a:21:c8:92:10:53:c7:
- 5c:4b:e0:a5:62:59:c7:93:b5:69:de:23:c9:f4:a5:
- e4:a4:fd:88:ce:59:48:e3:dc:6b:f4:de:5b:8d:5e:
- 05:53
+ 00:cd:cf:d9:70:03:4f:4f:f1:9f:93:a1:2c:6e:cb:
+ 2f:20:d7:67:29:ce:99:02:4e:db:7d:6b:5e:6a:3a:
+ a1:d2:7f:cd:f9:58:bd:34:fe:af:8d:8a:05:34:a2:
+ 67:16:ae:94:88:3b:77:3f:f2:a0:a5:46:2e:05:2e:
+ b8:a7:2f:ff:e0:df:1d:b8:1e:31:6f:57:f9:aa:55:
+ 9c:83:aa:04:94:cd:e4:0f:99:f4:74:c1:38:8d:4c:
+ 90:67:ba:7e:92:42:59:ff:14:d6:4e:22:31:78:04:
+ 89:63:7d:84:fa:60:e7:d2:0d:61:0b:d8:a5:20:b3:
+ 8a:ce:f1:ef:b7:b0:b5:a6:81:d0:47:50:fb:5a:09:
+ 34:e1:a0:e3:6b:cf:e8:26:38:4d:cb:70:ae:4c:96:
+ 2c:9e:46:18:0c:e3:11:9f:8d:8a:65:c5:b1:03:5c:
+ 61:d9:35:a8:5d:29:08:7c:45:2e:38:13:dc:b0:72:
+ a6:e6:29:04:85:6a:6d:fd:74:af:60:6c:24:51:e2:
+ 3a:58:38:c1:0f:b2:4e:ac:8e:63:81:36:01:9f:02:
+ 04:de:54:53:4c:fa:5f:67:44:db:f0:ed:ce:3f:f0:
+ 5b:e7:75:b3:72:d5:e8:76:9c:24:73:2b:0c:d9:7c:
+ dd:85:a8:61:b9:42:d1:69:35:04:88:03:8a:c2:aa:
+ 10:cb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
- 06:8D:1F:27:78:21:80:08:1A:7E:7F:F8:F7:4D:A2:24:02:4E:3F:01
+ FA:45:82:63:D1:67:F2:93:F4:6A:6B:44:44:74:1A:D2:B0:CD:12:F6
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
- Signature Algorithm: sha1WithRSAEncryption
- 11:ce:c4:71:a2:28:64:97:e8:19:3f:b8:0e:5e:b6:95:30:2b:
- a9:12:c8:eb:c6:bb:8a:82:e2:f1:10:68:75:d9:a2:d0:85:48:
- d0:62:54:b6:e2:b9:08:6c:04:57:d6:ed:3c:bd:98:52:9e:5f:
- 3b:91:aa:70:20:d7:b9:75:07:69:c7:ab:98:85:15:63:d0:13:
- 58:08:47:61:eb:b9:fc:b3:3f:a8:fd:50:d6:c2:78:ad:03:07:
- 24:50:af:43:a2:21:4f:a3:3d:9e:34:c2:bf:22:2a:69:e0:96:
- b0:02:c0:40:81:c3:8b:a7:c8:5f:33:d5:47:0a:4e:35:fe:85:
- 3d:2f:e2:aa:5b:e1:46:b9:6d:04:34:0f:c8:90:bc:48:26:a5:
- a0:b4:ca:23:8b:f5:a9:47:d2:47:ee:23:c6:7f:b4:01:87:85:
- 8a:81:25:47:fc:03:20:1f:26:d6:3e:af:ea:96:66:3d:4b:9e:
- cb:cc:e2:9f:99:21:a6:60:51:e5:28:7a:8b:a2:71:cf:db:18:
- 62:1d:ce:a8:1c:6e:ed:b9:ae:2d:10:b2:0f:10:65:da:2f:fc:
- d4:ab:52:04:b1:f2:bd:1f:0b:6e:50:7e:93:5a:f0:61:8f:a4:
- 24:a4:8c:4c:71:e2:36:26:8e:88:b8:8c:5a:3a:a0:75:c3:04:
- de:dd:b5:60
+ Signature Algorithm: sha256WithRSAEncryption
+ ac:1c:7c:de:1a:4a:31:54:77:c5:94:7d:6a:0b:9d:c2:c9:d4:
+ 3b:2d:71:e4:99:df:ca:02:5c:a0:1c:1c:22:7d:f2:a5:0e:97:
+ 7c:91:20:12:c5:b7:f5:56:15:8c:1b:44:b2:32:94:8b:e5:b1:
+ c0:0b:f6:c0:b8:b4:cf:b9:27:d8:49:52:fc:81:9f:48:2a:08:
+ b8:94:a1:3f:78:fe:20:66:f5:ed:3f:61:f6:f7:23:5c:4c:36:
+ 49:48:10:07:de:40:62:eb:3b:bb:6b:4b:8e:e4:a7:b3:75:33:
+ 2f:4d:11:58:76:1e:1c:d9:b9:dc:1c:33:da:82:2b:5f:fc:51:
+ f1:26:35:7d:5e:eb:67:ba:da:2c:f2:d7:6e:88:b6:a1:34:ed:
+ 07:d2:a5:e4:ac:d6:9b:7c:6c:6e:77:aa:11:4e:d0:60:fa:86:
+ 94:a0:74:00:60:8b:1c:0b:3e:5d:05:c9:b9:8c:b4:6f:a5:e7:
+ 82:c0:6a:ef:60:73:de:1f:74:20:aa:67:c7:d9:c2:81:c7:4c:
+ d7:c9:57:e4:7d:db:80:bd:7d:4f:39:a4:77:d3:2e:65:79:87:
+ ae:05:f7:9c:28:ed:e8:4e:f6:ac:38:3f:8f:36:bb:ae:5e:42:
+ 71:d5:a9:5b:a7:df:42:9f:6b:e0:ec:3e:3b:6e:36:11:9b:34:
+ a8:66:ff:d5
-----BEGIN CERTIFICATE-----
-MIIC7TCCAdWgAwIBAgIJAKoDtrl2hTCcMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
-BAMMCUQgUm9vdCBDQTAeFw0xNDA4MTQwMjQ3MzFaFw0yNDA4MTEwMjQ3MzFaMBQx
-EjAQBgNVBAMMCUQgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMRSIXayCMWPY8TsN11NjCZj+0d8+iDRVJ70gru8A0DNbMxlB/c7Y36/yDmh
-EQXj4FiCHK0EoggWCMhkRAl+UOtst17uUYEdgEeyUX7tmzd5DgoGYX/gJg27chQB
-8KFNcf3Mwndzer30agg1Xu4CLZaaqmDDW7p5SKN6lfnVIpx7EMqOslfX3XrpxI15
-f+lxBBVPc77tagTwzp5XAKKSksYX0wXC74ZFUPRTXpdi9kruX/uZ+b+cRydjW1k+
-BjoMWqSaf82/QpZ8rfUGmNmK8v6pG0vJFuHtViQqIciSEFPHXEvgpWJZx5O1ad4j
-yfSl5KT9iM5ZSOPca/TeW41eBVMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAd
-BgNVHQ4EFgQUBo0fJ3ghgAgafn/4902iJAJOPwEwDgYDVR0PAQH/BAQDAgEGMA0G
-CSqGSIb3DQEBBQUAA4IBAQARzsRxoihkl+gZP7gOXraVMCupEsjrxruKguLxEGh1
-2aLQhUjQYlS24rkIbARX1u08vZhSnl87kapwINe5dQdpx6uYhRVj0BNYCEdh67n8
-sz+o/VDWwnitAwckUK9DoiFPoz2eNMK/Iipp4JawAsBAgcOLp8hfM9VHCk41/oU9
-L+KqW+FGuW0ENA/IkLxIJqWgtMoji/WpR9JH7iPGf7QBh4WKgSVH/AMgHybWPq/q
-lmY9S57LzOKfmSGmYFHlKHqLonHP2xhiHc6oHG7tua4tELIPEGXaL/zUq1IEsfK9
-HwtuUH6TWvBhj6QkpIxMceI2Jo6IuIxaOqB1wwTe3bVg
+MIIDADCCAeigAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UEAwwWRCBS
+b290IENBIC0gTXVsdGktcm9vdDAeFw0xNjAxMDIwMDAwMDBaFw0yNjAxMDIwMDAw
+MDBaMCExHzAdBgNVBAMMFkQgUm9vdCBDQSAtIE11bHRpLXJvb3QwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNz9lwA09P8Z+ToSxuyy8g12cpzpkCTtt9
+a15qOqHSf835WL00/q+NigU0omcWrpSIO3c/8qClRi4FLrinL//g3x24HjFvV/mq
+VZyDqgSUzeQPmfR0wTiNTJBnun6SQln/FNZOIjF4BIljfYT6YOfSDWEL2KUgs4rO
+8e+3sLWmgdBHUPtaCTThoONrz+gmOE3LcK5MliyeRhgM4xGfjYplxbEDXGHZNahd
+KQh8RS44E9ywcqbmKQSFam39dK9gbCRR4jpYOMEPsk6sjmOBNgGfAgTeVFNM+l9n
+RNvw7c4/8FvndbNy1eh2nCRzKwzZfN2FqGG5QtFpNQSIA4rCqhDLAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPpFgmPRZ/KT9GprRER0GtKwzRL2
+MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEArBx83hpKMVR3xZR9
+agudwsnUOy1x5JnfygJcoBwcIn3ypQ6XfJEgEsW39VYVjBtEsjKUi+WxwAv2wLi0
+z7kn2ElS/IGfSCoIuJShP3j+IGb17T9h9vcjXEw2SUgQB95AYus7u2tLjuSns3Uz
+L00RWHYeHNm53Bwz2oIrX/xR8SY1fV7rZ7raLPLXboi2oTTtB9Kl5KzWm3xsbneq
+EU7QYPqGlKB0AGCLHAs+XQXJuYy0b6XngsBq72Bz3h90IKpnx9nCgcdM18lX5H3b
+gL19Tzmkd9MuZXmHrgX3nCjt6E72rDg/jza7rl5CcdWpW6ffQp9r4Ow+O242EZs0
+qGb/1Q==
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/multi-root-chain2.pem b/chromium/net/data/ssl/certificates/multi-root-chain2.pem
index 8c465a2881c..e7b911437db 100644
--- a/chromium/net/data/ssl/certificates/multi-root-chain2.pem
+++ b/chromium/net/data/ssl/certificates/multi-root-chain2.pem
@@ -1,328 +1,303 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEAzDKsONWbnA5Lau2SquZbKzmbj0hH0A2cPWjVR6O4YadTgD7M
-jUMRs+TJsYt42rXtEX2kTDXtkOsweRv/SJSGvh31uLBhQH/X1ZCFuOAUujqm+6vx
-JRN1RYqSvcXUGOf+LasWutPgAPULz/8AKHX23Uue0RtuWv+3wH2Eck2wno+S7IHR
-fGWP+W9fsuoGVyo0Iy3nd02BZtKCZeQUd9neAnkm8qSBssPbD2zi2OAve5MVsCkd
-oQAWhw0Jc0QArZ6m33AEZu3hvj3s64Rn1/VAmSjrxipWPZEayVplVrlLCeO/LBkQ
-oCRCTcQVhQVJnXFS00t7U2jHKjwnfajTwn7k/wIDAQABAoIBAQCKdiXP2BBPLmY3
-WGbmmZLiaYqxCqsfSctS3L4aeMqy9Poq8OpVM1BSsmWNjWxiqY/aF18MCllPthrF
-VJWzCnufeMNA++DGEqow93GlXdTQPqsx5nJ62InhoMhGBFoAlXcGUof0IW04WPEs
-ldXumabOgdNsKXSYIePgk3v24fVMXgnvj1TxgMhtSSP5vmP8h0/7pNnnfjWrBZNg
-B2bVqCYQ6AaxHRivLFsD85nBdSXl8La5lfoSCgvpWHKtIUvUeZrBAagxK2gGj6zg
-sJvKs4EnGUdzX0eGheLaJtdVXEdxWIj9HmusLFF02wvgq5yS6Hyj1hz6YHaJomb5
-mHGVcBDZAoGBAPNTRlNfiZ9fB21FFEufPx7YxEbqS4BFthBqLfatG8fM1gRkbz9m
-Dy/FSmgPQMxaqA5vjE8jhVlVTOCXznT8TsAhuof/ORmmFDvHleJs1iaqw/xhgOJv
-avMc+BZTOktBX4u9E4wSVwj+QfhutssCeG+SHtS9uVyiGAVUSIyhCNNjAoGBANbV
-ozqAElO7pF0frWIIZ7gGbPuEIULVqWhNQWZF19gvBf8sJQ+gfT0OhPRvopr734sc
-+/m2b1PORFVGVPmRYMXrNds7qvtFzoDSvki0X3dsi6TXFSY7lTI4lAyvCOxQcjbM
-x8sD9Csaips/i3EAV885BkG2QPMH+jEmp5U0y9C1AoGBAIgDsroEG4/ktOgVx0SG
-XehGT2E8srufPChs0gijt3W2QKPv6GfOCwsvA2qrrBMPUgXPwOSz/GR1VCXvdc7b
-AsJPmE9REYAO4ByScmxBXmv65Nb9QehRU71WIi+IkntiraAVLwoLbm9ugT331WIh
-nWTwjx9odmcbjMXd2TgTBDX1AoGAYysCygJMc3JukL4KnvIaToxIymFXqS5PoOHo
-ink7BYPPVNbf1LLUnNaS8PKHMNuLeP/MIJziDuFsEaEBoKJG9ZV5qtWEO7Ehfb3K
-MG1ylAH7BAB0ts1SNXiAfspdaBhKYJlusHwGvc7mpHtUtrjdz74W8UZb/NN13jJl
-sS5J1vECgYEAnpWIaGs3BCJWW8BSuuOx6NMSwFDfcpzqnJ6KvowdWVkW7lYK7kfZ
-JIZnNragGbybBDUcUcdSdz+V0GtzUj6oKYI420debUlQ6/Xc+Yud+esqf23ODS3A
-MsuJkwHALBIiocA552KN4Bsd69HRd91r/14G5BXtsjpsfhCXVPJreJ0=
------END RSA PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4096 (0x1000)
Signature Algorithm: sha256WithRSAEncryption
- Issuer: CN=B CA
+ Issuer: CN=B CA - Multi-root
Validity
- Not Before: Aug 14 02:47:31 2014 GMT
- Not After : Aug 11 02:47:31 2024 GMT
+ Not Before: Mar 11 01:37:16 2016 GMT
+ Not After : Mar 9 01:37:16 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:cc:32:ac:38:d5:9b:9c:0e:4b:6a:ed:92:aa:e6:
- 5b:2b:39:9b:8f:48:47:d0:0d:9c:3d:68:d5:47:a3:
- b8:61:a7:53:80:3e:cc:8d:43:11:b3:e4:c9:b1:8b:
- 78:da:b5:ed:11:7d:a4:4c:35:ed:90:eb:30:79:1b:
- ff:48:94:86:be:1d:f5:b8:b0:61:40:7f:d7:d5:90:
- 85:b8:e0:14:ba:3a:a6:fb:ab:f1:25:13:75:45:8a:
- 92:bd:c5:d4:18:e7:fe:2d:ab:16:ba:d3:e0:00:f5:
- 0b:cf:ff:00:28:75:f6:dd:4b:9e:d1:1b:6e:5a:ff:
- b7:c0:7d:84:72:4d:b0:9e:8f:92:ec:81:d1:7c:65:
- 8f:f9:6f:5f:b2:ea:06:57:2a:34:23:2d:e7:77:4d:
- 81:66:d2:82:65:e4:14:77:d9:de:02:79:26:f2:a4:
- 81:b2:c3:db:0f:6c:e2:d8:e0:2f:7b:93:15:b0:29:
- 1d:a1:00:16:87:0d:09:73:44:00:ad:9e:a6:df:70:
- 04:66:ed:e1:be:3d:ec:eb:84:67:d7:f5:40:99:28:
- eb:c6:2a:56:3d:91:1a:c9:5a:65:56:b9:4b:09:e3:
- bf:2c:19:10:a0:24:42:4d:c4:15:85:05:49:9d:71:
- 52:d3:4b:7b:53:68:c7:2a:3c:27:7d:a8:d3:c2:7e:
- e4:ff
+ 00:c8:27:1c:19:81:c0:a7:30:93:03:1c:f8:21:b8:
+ 2f:8a:22:b4:89:0f:da:b1:40:95:df:dc:46:53:fc:
+ 6f:36:26:66:5a:53:6d:45:78:c2:39:16:9a:3f:82:
+ 8b:ba:c5:b0:78:a8:18:bc:d5:a7:92:a5:e6:ac:e2:
+ 0c:81:d0:94:e5:0c:ec:5e:03:0c:17:c5:35:2a:7b:
+ ab:86:eb:bf:e8:62:0a:8f:b0:25:b2:70:f5:11:8c:
+ 16:4f:c1:76:44:e5:75:e8:93:4f:e9:e7:c4:e4:42:
+ 0a:08:be:73:2c:cb:8f:73:6a:40:77:eb:33:60:ac:
+ be:c5:27:fd:b1:4f:88:4b:15:af:98:fd:32:53:ae:
+ b0:2a:0c:b2:f5:05:f3:3a:06:0d:6e:5c:fe:83:fc:
+ e3:60:ae:99:8e:a1:21:c2:72:02:e6:f4:49:57:e6:
+ 91:31:2e:be:92:a1:ad:f8:71:31:64:74:10:33:d0:
+ a7:0c:ed:18:c7:b2:50:71:fc:b9:b6:ae:95:a0:8d:
+ ac:1f:3c:d5:79:a7:a9:88:50:b6:02:cd:68:60:24:
+ 45:9b:b6:e9:82:08:d9:9c:d4:7e:29:7d:2b:d9:ae:
+ 57:7f:62:6a:56:96:8b:4a:33:9e:5f:93:82:b0:d1:
+ 05:03:26:cd:15:f4:87:7f:6a:9a:df:e9:01:b5:d4:
+ c9:11
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
- 7A:DF:61:82:66:73:E5:9F:E2:84:99:26:22:18:18:2D:5C:5B:36:A7
+ FB:91:A9:5F:BC:27:81:98:55:30:BF:57:32:4D:B9:DA:56:DD:52:2C
X509v3 Authority Key Identifier:
- keyid:76:7F:E8:F6:A1:F7:91:56:BD:9C:7E:66:5C:97:F0:A5:1D:6C:06:28
+ keyid:90:CB:53:EE:36:0A:5A:B0:93:38:C9:11:B7:AC:FD:27:71:99:DC:81
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
- 59:31:d6:e2:3c:0e:31:c5:5c:a4:40:51:5d:eb:15:3d:2e:58:
- 13:c6:0f:26:cf:86:f7:ee:d1:30:31:81:83:86:83:ea:be:1c:
- bd:c9:20:6e:a0:47:4c:46:38:2e:1e:8f:70:da:80:38:f4:d7:
- 9c:59:9d:7f:23:d8:2a:c9:fe:fe:e9:57:5f:d9:69:58:e6:86:
- 19:af:3b:08:a1:ad:50:e5:c4:e8:33:c9:44:66:8c:12:b9:02:
- 19:4f:a7:18:a0:48:34:58:14:2d:c0:dc:44:b8:d9:ce:76:01:
- 21:0e:51:a8:7b:ba:db:93:e4:65:ab:b2:cb:b9:e1:30:26:b5:
- 9e:5e:df:62:15:86:45:99:f9:25:03:e3:b9:36:7f:8c:a7:e2:
- 85:d1:ac:09:5b:9f:d5:e3:ad:e5:a2:9b:e0:75:f0:61:8d:cd:
- b8:9d:5e:2f:b4:92:aa:6b:ca:05:95:84:b9:27:bd:e4:1e:d9:
- b6:74:1d:db:ec:08:35:39:a3:c0:64:7c:ab:86:8a:74:06:e1:
- 4d:f1:e6:bd:81:5d:2b:be:4d:d9:b2:b0:6e:cb:0a:df:e8:6d:
- 64:b3:c6:5a:28:22:82:d5:5b:e2:9e:84:1e:d1:06:1d:32:1b:
- 05:26:fd:e8:19:c9:25:81:4b:f7:78:09:b7:16:a1:63:82:b0:
- 79:68:89:72
+ b9:31:7a:95:b2:ba:3a:b4:f1:16:76:df:eb:d5:b9:af:67:b1:
+ 9d:8a:27:04:9b:61:6f:42:3f:c2:b3:cd:65:c4:86:cb:90:fb:
+ 9d:3a:ed:fc:b8:74:da:d7:6a:6c:2f:17:68:d1:73:58:f1:a2:
+ bb:8f:d6:b0:a8:7f:b6:a8:b0:74:d1:ea:c4:62:ed:bc:1e:ef:
+ 02:6b:d5:e8:2d:15:78:16:1e:90:fa:f4:29:5a:a8:43:ad:d2:
+ 58:40:b4:1c:60:4e:cd:bc:6f:1a:39:e4:46:b2:58:93:96:5a:
+ a8:a4:c4:31:73:ed:89:c4:81:27:e1:4c:66:20:7c:27:c4:f9:
+ 61:ff:d1:d5:a5:02:93:4c:06:fa:15:33:7a:1f:5f:eb:29:b2:
+ b5:6a:cd:7e:d6:d7:b7:51:a7:01:2f:22:9f:9e:7e:81:98:c4:
+ 72:11:36:2c:e7:c6:d0:f0:7d:98:36:ea:b7:a0:aa:13:8f:6e:
+ ae:41:59:9b:e6:c9:bc:9c:e8:93:f5:0c:4e:ca:b4:dd:e3:01:
+ fe:23:6e:fb:fa:b3:61:66:58:f5:fc:07:16:1d:a9:52:ec:a0:
+ 29:61:a4:39:ed:41:50:a3:a2:33:72:0e:3c:03:e1:0a:1a:1a:
+ cf:22:73:09:d7:ea:e8:15:fc:73:3c:d4:4e:34:6c:b4:18:94:
+ c4:d3:6e:12
-----BEGIN CERTIFICATE-----
-MIIDWjCCAkKgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEQiBD
-QTAeFw0xNDA4MTQwMjQ3MzFaFw0yNDA4MTEwMjQ3MzFaMGAxCzAJBgNVBAYTAlVT
-MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAw
-DgYDVQQKDAdUZXN0IENBMRIwEAYDVQQDDAkxMjcuMC4wLjEwggEiMA0GCSqGSIb3
-DQEBAQUAA4IBDwAwggEKAoIBAQDMMqw41ZucDktq7ZKq5lsrOZuPSEfQDZw9aNVH
-o7hhp1OAPsyNQxGz5Mmxi3jate0RfaRMNe2Q6zB5G/9IlIa+HfW4sGFAf9fVkIW4
-4BS6Oqb7q/ElE3VFipK9xdQY5/4tqxa60+AA9QvP/wAodfbdS57RG25a/7fAfYRy
-TbCej5LsgdF8ZY/5b1+y6gZXKjQjLed3TYFm0oJl5BR32d4CeSbypIGyw9sPbOLY
-4C97kxWwKR2hABaHDQlzRACtnqbfcARm7eG+PezrhGfX9UCZKOvGKlY9kRrJWmVW
-uUsJ478sGRCgJEJNxBWFBUmdcVLTS3tTaMcqPCd9qNPCfuT/AgMBAAGjbzBtMAwG
-A1UdEwEB/wQCMAAwHQYDVR0OBBYEFHrfYYJmc+Wf4oSZJiIYGC1cWzanMB8GA1Ud
-IwQYMBaAFHZ/6Pah95FWvZx+ZlyX8KUdbAYoMB0GA1UdJQQWMBQGCCsGAQUFBwMB
-BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAWTHW4jwOMcVcpEBRXesVPS5Y
-E8YPJs+G9+7RMDGBg4aD6r4cvckgbqBHTEY4Lh6PcNqAOPTXnFmdfyPYKsn+/ulX
-X9lpWOaGGa87CKGtUOXE6DPJRGaMErkCGU+nGKBINFgULcDcRLjZznYBIQ5RqHu6
-25PkZauyy7nhMCa1nl7fYhWGRZn5JQPjuTZ/jKfihdGsCVuf1eOt5aKb4HXwYY3N
-uJ1eL7SSqmvKBZWEuSe95B7ZtnQd2+wINTmjwGR8q4aKdAbhTfHmvYFdK75N2bKw
-bssK3+htZLPGWigigtVb4p6EHtEGHTIbBSb96BnJJYFL93gJtxahY4KweWiJcg==
+MIIDZzCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwHDEaMBgGA1UEAwwRQiBD
+QSAtIE11bHRpLXJvb3QwHhcNMTYwMzExMDEzNzE2WhcNMjYwMzA5MDEzNzE2WjBg
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4x
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyCccGYHApzCTAxz4Ibgv
+iiK0iQ/asUCV39xGU/xvNiZmWlNtRXjCORaaP4KLusWweKgYvNWnkqXmrOIMgdCU
+5QzsXgMMF8U1Knurhuu/6GIKj7AlsnD1EYwWT8F2ROV16JNP6efE5EIKCL5zLMuP
+c2pAd+szYKy+xSf9sU+ISxWvmP0yU66wKgyy9QXzOgYNblz+g/zjYK6ZjqEhwnIC
+5vRJV+aRMS6+kqGt+HExZHQQM9CnDO0Yx7JQcfy5tq6VoI2sHzzVeaepiFC2As1o
+YCRFm7bpggjZnNR+KX0r2a5Xf2JqVpaLSjOeX5OCsNEFAybNFfSHf2qa3+kBtdTJ
+EQIDAQABo28wbTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBT7kalfvCeBmFUwv1cy
+TbnaVt1SLDAfBgNVHSMEGDAWgBSQy1PuNgpasJM4yRG3rP0ncZncgTAdBgNVHSUE
+FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBALkxepWy
+ujq08RZ23+vVua9nsZ2KJwSbYW9CP8KzzWXEhsuQ+5067fy4dNrXamwvF2jRc1jx
+oruP1rCof7aosHTR6sRi7bwe7wJr1egtFXgWHpD69ClaqEOt0lhAtBxgTs28bxo5
+5EayWJOWWqikxDFz7YnEgSfhTGYgfCfE+WH/0dWlApNMBvoVM3ofX+spsrVqzX7W
+17dRpwEvIp+efoGYxHIRNiznxtDwfZg26regqhOPbq5BWZvmybyc6JP1DE7KtN3j
+Af4jbvv6s2FmWPX8BxYdqVLsoClhpDntQVCjojNyDjwD4QoaGs8icwnX6ugV/HM8
+1E40bLQYlMTTbhI=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 4097 (0x1001)
+ Serial Number: 4096 (0x1000)
Signature Algorithm: sha256WithRSAEncryption
- Issuer: CN=C CA
+ Issuer: CN=C CA - Multi-root
Validity
- Not Before: Aug 14 02:47:31 2014 GMT
- Not After : Aug 11 02:47:31 2024 GMT
- Subject: CN=B CA
+ Not Before: Jan 4 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=B CA - Multi-root
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:af:0f:4e:5f:ef:a4:fe:fc:3e:e4:30:fa:e3:d5:
- 9a:9f:32:e2:64:a3:d9:4a:80:f4:1d:51:19:88:79:
- fe:1f:a0:02:f5:55:e3:66:03:32:51:20:15:55:09:
- 48:e5:28:87:0e:95:f3:fc:4d:15:4c:34:ce:eb:e4:
- 53:0a:44:72:db:ca:b4:53:72:74:34:82:33:ee:51:
- 46:fa:9b:95:5a:cf:2a:da:ba:ae:46:c7:f2:da:0b:
- b9:db:ea:8f:8d:09:98:a1:d4:a9:48:85:fd:d4:3c:
- 59:69:90:e9:9c:91:88:6e:af:3b:16:ec:66:7d:a8:
- 1f:5b:4d:d9:64:19:ed:8d:e1:11:db:d6:1e:24:05:
- 8b:25:17:41:9f:a2:99:17:19:9a:d5:a2:00:93:c2:
- 2d:f0:34:aa:84:39:82:ff:e8:cd:2d:62:82:33:5d:
- 07:6b:35:b6:74:cc:10:c2:9e:69:f4:54:2a:45:17:
- 0f:d7:7c:f2:6d:22:c5:be:55:11:3c:40:25:24:f9:
- 88:79:f7:32:eb:2a:5a:00:cd:fe:29:fa:14:74:67:
- 24:62:51:f3:76:d7:e2:2f:7f:10:15:2d:a8:1c:17:
- c6:9b:ab:be:f3:4b:16:30:f1:82:8c:e7:da:f0:9e:
- 4e:14:1b:5d:92:41:61:ce:26:c0:53:7b:1d:21:b5:
- 73:9f
+ 00:ca:e9:f3:21:f4:a0:e7:ba:82:8c:7f:b3:98:44:
+ 20:4a:9a:8b:f9:e5:0c:99:c4:22:72:f7:57:7c:1e:
+ cc:56:4c:c3:f5:fd:1e:90:a5:1c:bf:2c:c4:c4:29:
+ 29:38:cc:26:9e:1a:1d:e3:e4:db:97:58:35:14:e8:
+ e2:db:37:05:1c:32:f7:bb:19:22:c2:37:3f:01:76:
+ 8c:17:23:ca:fc:10:69:b4:d1:74:27:b6:10:7e:b7:
+ c1:07:a2:a1:af:18:4d:5c:2e:13:72:a9:fb:64:b1:
+ e7:9f:49:41:3c:dc:b8:5f:94:e6:68:05:a5:1f:c8:
+ 56:84:e2:e5:6a:84:71:9c:b8:ac:3e:ec:8e:0c:d2:
+ f2:5f:11:fd:f4:7f:40:a7:3b:08:01:bb:fd:6f:d0:
+ a9:16:1d:14:a1:28:20:30:98:ba:1e:22:4e:5b:09:
+ b9:c1:df:17:60:1b:80:43:97:49:69:cd:6a:4e:58:
+ 08:9c:dc:29:57:3f:1b:bf:d8:5f:32:94:ae:97:b2:
+ d4:8d:50:1a:d1:8b:03:84:00:fd:87:d9:2e:ed:91:
+ 3d:3f:b7:89:54:46:0a:cd:db:10:62:80:47:60:21:
+ b3:1d:0e:bc:41:4d:86:d4:9d:52:1b:53:82:1a:9f:
+ 46:91:98:1e:ed:9f:da:69:16:64:24:1c:de:f8:b3:
+ 34:69
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
- 76:7F:E8:F6:A1:F7:91:56:BD:9C:7E:66:5C:97:F0:A5:1D:6C:06:28
+ 90:CB:53:EE:36:0A:5A:B0:93:38:C9:11:B7:AC:FD:27:71:99:DC:81
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
Signature Algorithm: sha256WithRSAEncryption
- bc:3e:d1:ed:69:da:91:cf:32:bc:0f:39:17:ec:d5:37:46:1e:
- 0e:d9:d3:78:d8:62:ea:03:d3:1c:d0:c6:34:45:cb:b2:50:ce:
- e2:03:96:a7:43:3f:1c:ff:58:93:70:bf:b2:98:e8:31:21:be:
- b6:89:e7:dc:ae:9d:5d:12:36:78:6f:ef:cc:be:b3:bb:ec:27:
- d4:56:ef:69:49:d8:cd:33:7a:ec:76:34:de:bd:91:3f:b1:9c:
- 67:23:94:fa:60:44:82:47:30:c1:84:f8:a5:d3:e1:fb:cf:c0:
- bd:53:fb:a9:ef:96:79:aa:34:4a:d1:b3:e4:f2:68:a4:d3:a8:
- 75:1c:19:a7:42:a7:62:0b:46:b8:e0:05:3d:c6:51:2c:77:09:
- a1:fc:b7:e8:a6:5d:b6:d2:9d:75:09:2b:5c:b7:00:42:31:a4:
- be:ea:c5:3c:3d:9f:02:8d:69:bc:d0:ad:d5:1c:99:51:4c:3e:
- 0b:96:47:c5:85:79:3c:10:5b:5c:9e:e8:a7:ee:f2:46:47:b4:
- fc:13:94:7b:1d:a5:3f:da:b0:3c:7a:08:bd:9e:1d:36:44:27:
- 0a:ab:07:b3:91:d0:ba:d2:6a:d5:a0:a5:91:62:b1:73:0b:07:
- 07:6f:00:e9:6a:e7:f5:60:cb:f6:84:38:8b:2e:5e:02:dd:7e:
- f3:d9:1e:1d
+ 97:cd:ae:5a:26:f4:25:f6:c0:8b:08:d8:df:82:35:d8:76:f3:
+ 5d:cc:99:bd:ac:70:c9:41:e0:24:c8:fd:e6:4e:41:2c:d4:69:
+ 8d:08:25:fd:f3:32:3a:58:0b:d3:58:9c:81:51:bf:97:a4:bc:
+ 00:18:1c:4f:1c:54:04:63:e3:72:87:f4:dc:9e:7b:dc:da:5d:
+ e1:ef:59:6b:f0:1f:3d:0c:11:55:1e:9a:1a:d8:8d:bc:7b:18:
+ b7:4f:92:1c:68:73:82:ec:f3:69:48:0a:86:40:4a:a5:6f:ae:
+ 8f:10:2e:12:0b:e8:7e:b9:bc:d7:26:f0:cf:f4:0f:5b:77:f2:
+ ff:77:28:b4:5f:5e:ef:65:08:21:b8:f9:1e:56:b9:69:3b:c4:
+ 7f:01:88:c9:7c:ca:d0:e2:df:e5:5e:8d:e9:2e:7d:4a:78:04:
+ 8b:c1:dc:d4:58:ac:90:fc:5c:8e:48:2b:60:99:63:37:3f:e5:
+ 61:da:8f:58:9f:4d:0a:ee:6c:8d:bc:1f:7e:c4:be:0f:32:4b:
+ 11:7a:28:bf:dd:d0:a0:40:42:a8:43:4d:0b:2f:01:0e:73:de:
+ 1b:a6:df:49:57:58:89:57:c0:23:76:83:f0:9a:0e:83:d9:9b:
+ cb:eb:ac:3f:89:d1:e8:3c:3e:f1:d5:80:0c:38:18:02:5c:5f:
+ e5:68:5e:cf
-----BEGIN CERTIFICATE-----
-MIIC3DCCAcSgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEQyBD
-QTAeFw0xNDA4MTQwMjQ3MzFaFw0yNDA4MTEwMjQ3MzFaMA8xDTALBgNVBAMMBEIg
-Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvD05f76T+/D7kMPrj
-1ZqfMuJko9lKgPQdURmIef4foAL1VeNmAzJRIBVVCUjlKIcOlfP8TRVMNM7r5FMK
-RHLbyrRTcnQ0gjPuUUb6m5Vazyrauq5Gx/LaC7nb6o+NCZih1KlIhf3UPFlpkOmc
-kYhurzsW7GZ9qB9bTdlkGe2N4RHb1h4kBYslF0GfopkXGZrVogCTwi3wNKqEOYL/
-6M0tYoIzXQdrNbZ0zBDCnmn0VCpFFw/XfPJtIsW+VRE8QCUk+Yh59zLrKloAzf4p
-+hR0ZyRiUfN21+IvfxAVLagcF8abq77zSxYw8YKM59rwnk4UG12SQWHOJsBTex0h
-tXOfAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHZ/6Pah95FW
-vZx+ZlyX8KUdbAYoMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEA
-vD7R7Wnakc8yvA85F+zVN0YeDtnTeNhi6gPTHNDGNEXLslDO4gOWp0M/HP9Yk3C/
-spjoMSG+tonn3K6dXRI2eG/vzL6zu+wn1FbvaUnYzTN67HY03r2RP7GcZyOU+mBE
-gkcwwYT4pdPh+8/AvVP7qe+Weao0StGz5PJopNOodRwZp0KnYgtGuOAFPcZRLHcJ
-ofy36KZdttKddQkrXLcAQjGkvurFPD2fAo1pvNCt1RyZUUw+C5ZHxYV5PBBbXJ7o
-p+7yRke0/BOUex2lP9qwPHoIvZ4dNkQnCqsHs5HQutJq1aClkWKxcwsHB28A6Wrn
-9WDL9oQ4iy5eAt1+89keHQ==
+MIIC9jCCAd6gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwHDEaMBgGA1UEAwwRQyBD
+QSAtIE11bHRpLXJvb3QwHhcNMTYwMTA0MDAwMDAwWhcNMjYwMTAyMDAwMDAwWjAc
+MRowGAYDVQQDDBFCIENBIC0gTXVsdGktcm9vdDCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMrp8yH0oOe6gox/s5hEIEqai/nlDJnEInL3V3wezFZMw/X9
+HpClHL8sxMQpKTjMJp4aHePk25dYNRTo4ts3BRwy97sZIsI3PwF2jBcjyvwQabTR
+dCe2EH63wQeioa8YTVwuE3Kp+2Sx559JQTzcuF+U5mgFpR/IVoTi5WqEcZy4rD7s
+jgzS8l8R/fR/QKc7CAG7/W/QqRYdFKEoIDCYuh4iTlsJucHfF2AbgEOXSWnNak5Y
+CJzcKVc/G7/YXzKUrpey1I1QGtGLA4QA/YfZLu2RPT+3iVRGCs3bEGKAR2Ahsx0O
+vEFNhtSdUhtTghqfRpGYHu2f2mkWZCQc3vizNGkCAwEAAaNCMEAwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUkMtT7jYKWrCTOMkRt6z9J3GZ3IEwDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQCXza5aJvQl9sCLCNjfgjXYdvNdzJm9
+rHDJQeAkyP3mTkEs1GmNCCX98zI6WAvTWJyBUb+XpLwAGBxPHFQEY+Nyh/Tcnnvc
+2l3h71lr8B89DBFVHpoa2I28exi3T5IcaHOC7PNpSAqGQEqlb66PEC4SC+h+ubzX
+JvDP9A9bd/L/dyi0X17vZQghuPkeVrlpO8R/AYjJfMrQ4t/lXo3pLn1KeASLwdzU
+WKyQ/FyOSCtgmWM3P+Vh2o9Yn00K7myNvB9+xL4PMksReii/3dCgQEKoQ00LLwEO
+c94bpt9JV1iJV8AjdoPwmg6D2ZvL66w/idHoPD7x1YAMOBgCXF/laF7P
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 4100 (0x1004)
+ Serial Number: 4097 (0x1001)
Signature Algorithm: sha256WithRSAEncryption
- Issuer: CN=E Root CA
+ Issuer: CN=E Root CA - Multi-root
Validity
- Not Before: Aug 14 02:47:31 2014 GMT
- Not After : Aug 11 02:47:31 2024 GMT
- Subject: CN=C CA
+ Not Before: Jan 5 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=C CA - Multi-root
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:ce:78:cf:1a:cb:5f:9f:b8:fb:9b:35:ee:dd:24:
- f1:6a:f4:cc:6a:63:1f:89:20:20:be:51:ba:2b:a5:
- e1:46:ad:df:4e:1e:ab:8d:2c:7b:ac:8f:d4:a1:48:
- f0:72:51:d8:4a:a4:b7:7c:c1:cd:92:c2:4d:74:d7:
- 43:e5:58:66:73:57:5d:e0:a6:30:72:38:ad:7a:04:
- 1a:45:4a:19:72:16:06:e1:3e:04:fa:06:29:69:61:
- 62:48:af:51:17:4f:31:a2:65:6b:61:9d:5a:54:91:
- f9:67:47:7b:4e:37:60:3a:86:03:cd:68:df:5c:a8:
- 0a:d0:33:e7:51:b0:b3:be:ba:90:9b:d1:e3:69:6e:
- 5c:17:9a:b2:5b:cf:af:c5:6a:fd:32:f5:56:06:8c:
- d8:11:dd:ed:fd:09:1f:88:6e:e3:e5:49:21:70:e2:
- c3:ff:f9:04:fd:09:62:e4:24:a0:f8:63:7b:e8:2d:
- c7:41:cf:b5:6f:76:8a:25:3f:a3:27:df:16:d0:cd:
- 74:ac:c2:91:16:6d:00:1e:73:f0:19:f6:08:70:bd:
- d1:46:82:82:ac:98:1b:df:a0:7c:c7:39:f6:ce:0a:
- f8:64:f6:3a:60:9b:f0:61:6d:24:9c:d9:bd:6e:38:
- f1:78:19:2b:7f:e8:c0:e3:e7:85:93:02:6e:8c:6d:
- 09:f7
+ 00:b6:1f:67:e4:9e:db:e0:ff:eb:29:75:ee:68:a2:
+ 4e:95:6e:d2:f6:9d:c9:b6:dc:08:18:70:b5:76:bf:
+ b7:14:8b:cb:46:c6:6a:2c:fa:43:f9:54:93:fa:bd:
+ aa:f0:ee:a3:20:5b:2a:cd:08:f7:be:95:36:e4:88:
+ f8:fd:43:7d:b8:f9:38:b4:d2:4e:22:0b:8b:85:de:
+ 6a:fe:6f:da:3b:4b:0f:26:c1:f8:31:22:36:19:96:
+ 0c:ef:85:7c:72:67:ac:4c:5c:f9:23:a4:29:d8:a5:
+ 1c:b6:ec:95:eb:d3:c2:8d:cb:ae:9a:d7:08:c8:b7:
+ f7:a0:c6:28:44:5f:24:97:bd:ca:d9:6d:99:9b:17:
+ 47:1f:38:b3:e3:67:6a:b4:75:d6:92:cd:67:62:20:
+ 58:f0:a7:46:85:94:72:76:98:c5:ec:4c:75:1b:a1:
+ 76:67:4b:1f:c8:23:6c:2a:78:66:c2:a7:6b:af:ef:
+ 97:30:34:60:0a:db:98:94:3b:9f:95:3c:34:b6:35:
+ 40:12:fa:1d:bf:66:f4:7b:fd:66:1a:2a:49:8c:24:
+ 60:91:08:f9:61:39:f9:3b:29:98:64:7b:35:04:a9:
+ f5:af:8d:0f:1e:e7:28:b6:30:32:b4:5f:d4:29:16:
+ 7a:70:8d:db:b9:ba:bf:eb:22:98:5d:94:c8:47:e3:
+ 4b:11
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
- 51:35:6F:D5:40:65:74:E3:C8:7B:0C:47:12:B5:FC:58:73:7C:16:D1
+ 90:53:F5:80:11:F6:3F:1B:A8:9D:8D:75:0D:56:3B:F2:2B:C5:9C:44
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
Signature Algorithm: sha256WithRSAEncryption
- bf:ad:09:bd:6b:f3:5e:bb:82:46:21:74:64:a4:e6:85:3b:6c:
- 49:e8:22:88:99:0d:aa:30:ea:5b:d0:54:ee:6b:b0:28:a9:c4:
- 6e:2c:a3:0b:71:ef:6f:6e:42:55:5b:54:d6:c0:10:0d:a0:00:
- 8a:8e:87:9e:ae:90:6a:64:90:bb:b0:62:22:66:2e:3b:5a:74:
- 91:da:4b:b1:75:aa:48:4f:3d:66:30:24:84:a0:3e:15:78:73:
- 8d:c2:c1:d5:77:5e:cc:19:3a:c8:33:0f:70:18:ed:29:3a:ef:
- df:3f:1f:36:8f:1c:d1:f8:a6:fa:bb:9d:cf:27:cc:3e:e6:a8:
- 2f:d2:28:96:23:eb:01:04:31:91:5c:94:11:30:50:50:ed:da:
- 91:0f:d5:dd:ce:ab:2b:a0:11:c3:e9:e7:88:6f:e1:32:7d:0b:
- a7:15:9e:90:3b:64:37:c1:ab:0d:ea:75:26:55:a1:10:b7:78:
- 5b:df:47:c6:12:54:b8:18:f1:60:bb:77:8a:71:0e:a9:88:03:
- 44:ce:e8:57:bf:b8:c4:40:2b:44:c9:5d:39:67:90:85:15:af:
- a4:fa:f7:e2:13:c1:3b:ca:b8:55:54:75:2a:5c:7e:73:44:26:
- 4c:3e:04:6d:83:13:48:cc:db:01:99:ac:5c:7c:1f:2c:24:1e:
- d7:c0:13:d9
+ 43:35:08:cc:aa:f8:10:9f:9e:fa:ab:24:dc:c6:e6:9a:23:52:
+ c9:4c:81:33:ba:64:b2:86:a8:29:f4:1f:5a:fa:5a:c4:91:56:
+ 16:d1:f9:84:96:89:8c:ac:1f:b6:ea:2f:cb:12:f4:92:ed:3b:
+ 85:09:eb:f3:7a:2e:09:39:ec:ee:09:4b:fa:86:3e:62:40:0e:
+ 57:72:07:de:fa:53:45:ac:40:1c:0d:0b:4a:67:9a:f7:39:ce:
+ 33:5e:d0:17:0b:8a:83:ae:33:6f:96:c0:f0:7a:ac:07:36:c5:
+ 86:a9:db:93:aa:2e:fa:71:d1:1a:dd:82:2a:f8:1c:30:2a:b9:
+ 7d:29:fa:75:62:76:7c:15:15:75:af:78:6c:7c:53:ae:2e:80:
+ 14:0d:0b:eb:0f:b1:6d:fa:df:72:0b:6f:f0:90:96:18:71:df:
+ 76:1d:8c:f1:d5:c0:4f:ab:38:1a:eb:e6:a1:dd:1d:dc:60:d4:
+ da:7f:40:db:17:fc:4a:56:65:3a:86:60:83:87:b3:f6:3b:a8:
+ 85:ac:2b:14:c2:26:77:8f:ee:a4:6f:11:f2:27:08:3f:bf:86:
+ 4a:e3:bd:ef:6b:51:ec:72:a7:51:08:47:16:f8:d3:d7:b1:8d:
+ a1:b1:ca:d3:cd:fd:56:0a:2c:2f:62:27:8c:e1:ff:88:83:ff:
+ 83:ab:87:70
-----BEGIN CERTIFICATE-----
-MIIC4TCCAcmgAwIBAgICEAQwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJRSBS
-b290IENBMB4XDTE0MDgxNDAyNDczMVoXDTI0MDgxMTAyNDczMVowDzENMAsGA1UE
-AwwEQyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM54zxrLX5+4
-+5s17t0k8Wr0zGpjH4kgIL5Ruiul4Uat304eq40se6yP1KFI8HJR2Eqkt3zBzZLC
-TXTXQ+VYZnNXXeCmMHI4rXoEGkVKGXIWBuE+BPoGKWlhYkivURdPMaJla2GdWlSR
-+WdHe043YDqGA81o31yoCtAz51Gws766kJvR42luXBeaslvPr8Vq/TL1VgaM2BHd
-7f0JH4hu4+VJIXDiw//5BP0JYuQkoPhje+gtx0HPtW92iiU/oyffFtDNdKzCkRZt
-AB5z8Bn2CHC90UaCgqyYG9+gfMc59s4K+GT2OmCb8GFtJJzZvW448XgZK3/owOPn
-hZMCboxtCfcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUUTVv
-1UBldOPIewxHErX8WHN8FtEwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUA
-A4IBAQC/rQm9a/Neu4JGIXRkpOaFO2xJ6CKImQ2qMOpb0FTua7AoqcRuLKMLce9v
-bkJVW1TWwBANoACKjoeerpBqZJC7sGIiZi47WnSR2kuxdapITz1mMCSEoD4VeHON
-wsHVd17MGTrIMw9wGO0pOu/fPx82jxzR+Kb6u53PJ8w+5qgv0iiWI+sBBDGRXJQR
-MFBQ7dqRD9XdzqsroBHD6eeIb+EyfQunFZ6QO2Q3wasN6nUmVaEQt3hb30fGElS4
-GPFgu3eKcQ6piANEzuhXv7jEQCtEyV05Z5CFFa+k+vfiE8E7yrhVVHUqXH5zRCZM
-PgRtgxNIzNsBmaxcfB8sJB7XwBPZ
+MIIC+zCCAeOgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UEAwwWRSBS
+b290IENBIC0gTXVsdGktcm9vdDAeFw0xNjAxMDUwMDAwMDBaFw0yNjAxMDIwMDAw
+MDBaMBwxGjAYBgNVBAMMEUMgQ0EgLSBNdWx0aS1yb290MIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAth9n5J7b4P/rKXXuaKJOlW7S9p3JttwIGHC1dr+3
+FIvLRsZqLPpD+VST+r2q8O6jIFsqzQj3vpU25Ij4/UN9uPk4tNJOIguLhd5q/m/a
+O0sPJsH4MSI2GZYM74V8cmesTFz5I6Qp2KUctuyV69PCjcuumtcIyLf3oMYoRF8k
+l73K2W2ZmxdHHziz42dqtHXWks1nYiBY8KdGhZRydpjF7Ex1G6F2Z0sfyCNsKnhm
+wqdrr++XMDRgCtuYlDuflTw0tjVAEvodv2b0e/1mGipJjCRgkQj5YTn5OymYZHs1
+BKn1r40PHucotjAytF/UKRZ6cI3bubq/6yKYXZTIR+NLEQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBSQU/WAEfY/G6idjXUNVjvyK8WcRDAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAEM1CMyq+BCfnvqrJNzG5poj
+UslMgTO6ZLKGqCn0H1r6WsSRVhbR+YSWiYysH7bqL8sS9JLtO4UJ6/N6Lgk57O4J
+S/qGPmJADldyB976U0WsQBwNC0pnmvc5zjNe0BcLioOuM2+WwPB6rAc2xYap25Oq
+Lvpx0Rrdgir4HDAquX0p+nVidnwVFXWveGx8U64ugBQNC+sPsW3633ILb/CQlhhx
+33YdjPHVwE+rOBrr5qHdHdxg1Np/QNsX/EpWZTqGYIOHs/Y7qIWsKxTCJneP7qRv
+EfInCD+/hkrjve9rUexyp1EIRxb409exjaGxytPN/VYKLC9iJ4zh/4iD/4Orh3A=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 10416553735984151763 (0x908f086f011a7cd3)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: CN=E Root CA
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=E Root CA - Multi-root
Validity
- Not Before: Aug 14 02:47:31 2014 GMT
- Not After : Aug 11 02:47:31 2024 GMT
- Subject: CN=E Root CA
+ Not Before: Jan 2 00:00:00 2016 GMT
+ Not After : Jan 2 00:00:00 2026 GMT
+ Subject: CN=E Root CA - Multi-root
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:e4:17:15:a0:f9:24:7f:02:c3:1f:c4:70:51:c1:
- f9:e4:70:87:93:d6:49:7d:07:1f:94:0a:2e:0f:b4:
- be:4f:fa:2c:2f:49:35:dc:08:28:dd:4c:a9:8c:4e:
- cc:79:5a:41:77:65:19:ed:e5:1c:10:9f:c3:64:30:
- d2:c5:0b:88:7c:b4:03:85:5b:48:5c:08:f2:84:6f:
- e9:88:ac:ec:15:43:6d:0b:87:06:aa:91:7e:e5:2c:
- dc:86:bd:0a:e6:a2:d4:a1:15:59:c8:a4:de:23:96:
- 61:d4:da:5f:34:d4:5b:58:84:99:fd:cc:5a:cc:27:
- d9:34:ee:cd:6f:11:99:a9:94:54:84:79:78:96:b3:
- 2b:5d:e5:c7:79:3d:a6:7e:ef:2d:af:fd:b9:92:04:
- e8:86:66:43:3a:ba:7d:de:ce:99:d7:99:b8:3d:54:
- 18:d7:a7:08:76:0a:68:6a:d6:2e:3d:1f:ea:48:4b:
- 63:21:e9:19:53:2f:be:ab:d9:82:70:14:a3:59:30:
- 34:3a:6b:96:2c:f7:de:c5:d7:23:6d:d5:56:fc:6f:
- 3c:1f:38:23:f3:f8:94:91:f3:bb:f8:10:29:70:9e:
- 32:ff:8d:9d:b2:c1:0a:0f:b1:ce:9d:55:91:11:46:
- 7f:3b:ce:ae:c8:a8:f5:a9:d2:49:16:c2:d9:e4:32:
- 4f:c1
+ 00:b5:60:cb:b4:84:ab:6c:ba:59:52:a9:4c:6a:85:
+ 41:f2:41:17:49:40:3f:3e:e8:70:5c:05:df:dd:64:
+ 9e:fc:be:fb:38:ef:5d:67:ab:0e:de:9c:ea:ad:91:
+ e1:f4:db:8b:f4:c0:e6:d0:ad:e2:83:15:01:aa:49:
+ 42:97:ae:72:7b:78:e3:20:4e:7e:29:ee:b5:35:6b:
+ c4:af:d4:54:b0:86:2f:a9:09:a7:3b:8c:05:9e:fd:
+ b4:b8:1f:3a:aa:d5:b5:d2:91:0f:50:e9:d2:1e:62:
+ 1c:c1:30:07:41:aa:bd:c2:11:3f:cc:c8:0f:a9:7e:
+ 81:69:52:96:86:2a:07:63:7b:f0:23:9e:db:27:88:
+ 8c:dc:aa:8c:66:dd:35:3a:08:60:37:36:41:34:f5:
+ 48:69:23:1a:5b:18:a7:ec:df:68:0a:3c:19:fb:92:
+ b7:fa:53:9b:f3:70:b6:0d:4c:cb:2f:b7:0e:7e:5f:
+ 94:8c:a3:71:66:09:be:0d:af:db:52:f6:82:3f:88:
+ 64:72:cc:19:79:f4:7b:4d:6e:50:dc:93:88:d5:29:
+ 8a:e1:c8:1f:32:71:9f:d9:0e:14:31:f8:94:11:23:
+ b1:bf:64:eb:27:3a:64:fb:77:ee:40:8c:a7:03:ed:
+ 1d:ec:8f:ee:25:58:f0:26:91:3c:f8:28:a1:7a:45:
+ 9f:13
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
- 90:96:6B:1E:0F:CF:8B:69:42:D0:1A:0C:A1:B9:B0:41:E1:A4:94:5D
+ 51:68:BC:D9:1B:1D:7F:8E:0D:4A:33:39:2D:A4:1F:14:29:92:70:8E
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
- Signature Algorithm: sha1WithRSAEncryption
- 6a:d5:0a:5d:74:38:eb:b1:0f:2e:72:3c:62:3c:5e:9e:60:cd:
- 9b:83:24:c1:e4:b2:f3:9f:56:c8:a8:97:b8:8f:eb:39:16:22:
- 11:76:e2:84:27:fb:be:4c:1f:57:e0:90:61:10:18:15:e6:5d:
- 78:a9:c1:f1:2b:f7:f1:42:0b:5c:68:6c:e0:63:8a:69:f6:72:
- 96:41:44:70:6c:15:e0:3f:96:62:3b:1a:a1:f2:c5:42:8b:1d:
- f2:5a:b2:c5:66:7b:3e:dd:6b:1d:3c:a0:57:84:78:69:dc:b6:
- 89:42:20:dd:23:af:9b:69:37:9e:c6:7a:53:f6:22:a4:83:c3:
- df:4e:79:9b:3e:6e:88:92:7b:3a:bc:eb:47:b2:4c:a2:c5:1f:
- b2:22:9c:66:e7:a8:36:b6:e2:bb:0a:76:a9:14:07:58:2c:e0:
- 37:26:4c:31:cb:52:ba:f9:63:14:0c:7f:ee:99:78:ee:6e:32:
- 5d:4f:22:ee:45:d5:04:10:06:02:3b:43:9a:81:c6:d3:10:11:
- 87:91:78:fa:f2:0b:19:c9:6b:0f:1a:55:76:1e:02:e0:a7:66:
- 80:18:af:88:4b:a7:59:a8:d5:4a:d1:36:85:ae:dd:53:2b:a9:
- 58:0d:e8:75:f9:70:74:4d:d6:a2:5c:5c:2d:00:d6:b1:cf:e7:
- d8:5c:97:d3
+ Signature Algorithm: sha256WithRSAEncryption
+ 2d:d4:56:d9:90:bb:62:64:66:78:6d:cd:73:26:cc:42:ce:37:
+ f4:bf:e8:8f:e7:1e:00:cb:c2:bd:54:33:0b:a8:e2:04:e1:5f:
+ 59:2a:1a:41:70:0f:d6:32:5f:d0:14:86:fa:e2:a7:19:29:49:
+ 77:56:b9:d7:e6:eb:39:61:e4:25:67:22:eb:f8:46:86:b7:6b:
+ 7d:44:01:0b:18:cb:ba:e5:af:76:ab:c6:fe:43:6c:d8:f6:33:
+ f7:86:0b:22:da:27:78:91:07:55:3f:b2:c5:1e:10:88:09:b3:
+ cf:22:c6:7e:8f:c6:d0:c5:ec:67:90:72:8b:2b:c4:46:81:2c:
+ 82:d1:5c:57:4e:d5:af:c4:d2:d8:b2:a7:91:1a:42:b3:57:bc:
+ 4e:81:5e:cf:91:af:da:f1:53:29:de:31:6b:d3:69:a4:4d:a9:
+ 14:15:96:51:7d:0d:bd:28:11:03:71:d2:85:11:92:1d:96:1a:
+ 12:33:0c:4b:cf:c4:40:19:fb:eb:6a:fe:9b:e7:2d:cd:f7:75:
+ a3:66:4e:a6:7d:8e:8c:2e:5d:b8:2c:a8:5e:d7:42:1b:97:00:
+ ba:12:41:8c:9b:f1:ed:91:49:63:5a:11:0d:e4:7d:f0:dc:36:
+ 23:0b:1b:e8:5f:be:1f:6d:a7:aa:bb:30:76:e2:36:b2:5a:68:
+ 80:f5:75:7e
-----BEGIN CERTIFICATE-----
-MIIC7TCCAdWgAwIBAgIJAJCPCG8BGnzTMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
-BAMMCUUgUm9vdCBDQTAeFw0xNDA4MTQwMjQ3MzFaFw0yNDA4MTEwMjQ3MzFaMBQx
-EjAQBgNVBAMMCUUgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAOQXFaD5JH8Cwx/EcFHB+eRwh5PWSX0HH5QKLg+0vk/6LC9JNdwIKN1MqYxO
-zHlaQXdlGe3lHBCfw2Qw0sULiHy0A4VbSFwI8oRv6Yis7BVDbQuHBqqRfuUs3Ia9
-Cuai1KEVWcik3iOWYdTaXzTUW1iEmf3MWswn2TTuzW8RmamUVIR5eJazK13lx3k9
-pn7vLa/9uZIE6IZmQzq6fd7OmdeZuD1UGNenCHYKaGrWLj0f6khLYyHpGVMvvqvZ
-gnAUo1kwNDprliz33sXXI23VVvxvPB84I/P4lJHzu/gQKXCeMv+NnbLBCg+xzp1V
-kRFGfzvOrsio9anSSRbC2eQyT8ECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAd
-BgNVHQ4EFgQUkJZrHg/Pi2lC0BoMobmwQeGklF0wDgYDVR0PAQH/BAQDAgEGMA0G
-CSqGSIb3DQEBBQUAA4IBAQBq1QpddDjrsQ8ucjxiPF6eYM2bgyTB5LLzn1bIqJe4
-j+s5FiIRduKEJ/u+TB9X4JBhEBgV5l14qcHxK/fxQgtcaGzgY4pp9nKWQURwbBXg
-P5ZiOxqh8sVCix3yWrLFZns+3WsdPKBXhHhp3LaJQiDdI6+baTeexnpT9iKkg8Pf
-TnmbPm6Ikns6vOtHskyixR+yIpxm56g2tuK7CnapFAdYLOA3Jkwxy1K6+WMUDH/u
-mXjubjJdTyLuRdUEEAYCO0OagcbTEBGHkXj68gsZyWsPGlV2HgLgp2aAGK+IS6dZ
-qNVK0TaFrt1TK6lYDeh1+XB0TdaiXFwtANaxz+fYXJfT
+MIIDADCCAeigAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UEAwwWRSBS
+b290IENBIC0gTXVsdGktcm9vdDAeFw0xNjAxMDIwMDAwMDBaFw0yNjAxMDIwMDAw
+MDBaMCExHzAdBgNVBAMMFkUgUm9vdCBDQSAtIE11bHRpLXJvb3QwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1YMu0hKtsullSqUxqhUHyQRdJQD8+6HBc
+Bd/dZJ78vvs4711nqw7enOqtkeH024v0wObQreKDFQGqSUKXrnJ7eOMgTn4p7rU1
+a8Sv1FSwhi+pCac7jAWe/bS4Hzqq1bXSkQ9Q6dIeYhzBMAdBqr3CET/MyA+pfoFp
+UpaGKgdje/AjntsniIzcqoxm3TU6CGA3NkE09UhpIxpbGKfs32gKPBn7krf6U5vz
+cLYNTMsvtw5+X5SMo3FmCb4Nr9tS9oI/iGRyzBl59HtNblDck4jVKYrhyB8ycZ/Z
+DhQx+JQRI7G/ZOsnOmT7d+5AjKcD7R3sj+4lWPAmkTz4KKF6RZ8TAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFFovNkbHX+ODUozOS2kHxQpknCO
+MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEALdRW2ZC7YmRmeG3N
+cybMQs439L/oj+ceAMvCvVQzC6jiBOFfWSoaQXAP1jJf0BSG+uKnGSlJd1a51+br
+OWHkJWci6/hGhrdrfUQBCxjLuuWvdqvG/kNs2PYz94YLItoneJEHVT+yxR4QiAmz
+zyLGfo/G0MXsZ5ByiyvERoEsgtFcV07Vr8TS2LKnkRpCs1e8ToFez5Gv2vFTKd4x
+a9NppE2pFBWWUX0NvSgRA3HShRGSHZYaEjMMS8/EQBn762r+m+ctzfd1o2ZOpn2O
+jC5duCyoXtdCG5cAuhJBjJvx7ZFJY1oRDeR98Nw2Iwsb6F++H22nqrswduI2slpo
+gPV1fg==
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/multi-root-crlset-C.raw b/chromium/net/data/ssl/certificates/multi-root-crlset-C.raw
new file mode 100644
index 00000000000..5beec4cac9d
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-crlset-C.raw
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/multi-root-crlset-CD-and-FE.raw b/chromium/net/data/ssl/certificates/multi-root-crlset-CD-and-FE.raw
new file mode 100644
index 00000000000..178cf4dda39
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-crlset-CD-and-FE.raw
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/multi-root-crlset-D-and-E.raw b/chromium/net/data/ssl/certificates/multi-root-crlset-D-and-E.raw
new file mode 100644
index 00000000000..89e7e20fc88
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-crlset-D-and-E.raw
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/multi-root-crlset-E.raw b/chromium/net/data/ssl/certificates/multi-root-crlset-E.raw
new file mode 100644
index 00000000000..46e4c362027
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-crlset-E.raw
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/multi-root-crlset-unrelated.raw b/chromium/net/data/ssl/certificates/multi-root-crlset-unrelated.raw
new file mode 100644
index 00000000000..98680b62900
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/multi-root-crlset-unrelated.raw
Binary files differ
diff --git a/chromium/net/data/ssl/certificates/sha256.pem b/chromium/net/data/ssl/certificates/sha256.pem
deleted file mode 100644
index 507ff04899e..00000000000
--- a/chromium/net/data/ssl/certificates/sha256.pem
+++ /dev/null
@@ -1,70 +0,0 @@
-Certificate:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 90:23:b2:54:1d:1a:a1:b4
- Signature Algorithm: sha256WithRSAEncryption
- Issuer: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1
- Validity
- Not Before: Sep 11 19:19:22 2014 GMT
- Not After : Sep 8 19:19:22 2024 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
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:d2:41:24:4c:b5:a5:83:ad:b9:64:5b:90:e2:d1:
- e5:17:14:fe:ee:d0:6a:d8:d0:74:3c:98:35:d1:6b:
- 2a:81:32:9e:e4:a2:77:5b:f2:81:2c:ae:c1:cc:ca:
- f0:45:dd:8e:21:d3:4c:a6:7a:69:1b:08:3e:83:31:
- 0e:cc:5a:f8:a4:b6:05:10:68:ec:a0:a2:44:b6:95:
- e9:c5:e3:7c:a2:fa:a0:72:de:b3:49:e7:ac:cc:dc:
- ce:f3:7c:af:9f:05:46:e4:c2:31:54:a4:2b:cc:bf:
- ab:c3:e2:a6:9d:30:24:f4:2b:4d:44:eb:63:5f:35:
- 0f:c5:ec:e9:77:40:0d:3d:35:6c:88:e7:18:c3:01:
- 95:4c:c1:d4:14:96:88:66:98:fd:8e:0f:0e:a1:50:
- d3:f9:13:e1:b6:5d:5a:8a:1c:8d:55:e1:43:3d:ca:
- c6:31:95:9c:0a:00:68:38:1a:b7:24:ce:cd:34:d6:
- 8d:f5:11:79:64:7b:01:b3:0f:76:fd:cf:ca:73:33:
- 96:03:e4:1a:2e:98:8b:54:4d:0b:b9:62:27:8f:0d:
- 9a:2c:1f:5d:b5:6a:e4:3a:27:33:02:eb:7f:0d:30:
- 6a:6f:ea:61:c9:78:fe:7a:9f:08:7b:61:cd:b8:b2:
- 04:98:24:37:d5:f7:ce:ec:34:29:b3:bc:26:ca:6f:
- 54:53
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha256WithRSAEncryption
- 73:89:72:15:fa:cf:c9:6a:4d:a5:1a:66:0d:da:03:13:2e:31:
- 6b:6f:df:f1:4f:dd:54:8d:bd:87:1e:e9:b1:b2:84:4a:da:8e:
- fa:76:b8:66:f0:2d:d6:f4:72:2d:55:ef:99:d4:e1:99:7c:79:
- 98:b7:b9:bc:9c:f8:69:47:6d:10:03:4b:41:59:ea:84:7c:04:
- 97:67:37:d4:a8:75:53:4a:f3:f9:9a:cb:bb:09:fb:dd:d7:b0:
- d5:35:48:04:f3:58:78:bc:fb:26:d7:dc:e2:bf:cb:64:22:3d:
- f7:bb:a4:5e:a3:98:5f:aa:29:46:aa:c6:a9:7c:8c:04:ac:21:
- 21:97:b1:94:da:eb:ee:49:03:9d:46:e0:a0:22:e4:dd:e4:2b:
- 3d:0d:0e:af:1b:59:39:41:e8:47:43:b8:58:36:82:86:c6:0e:
- d6:d3:c0:92:da:2b:a4:5a:5a:f8:4f:20:93:32:a7:74:21:13:
- 9d:b7:7b:68:20:71:81:4a:1a:32:b7:5e:e7:45:de:f7:e4:04:
- dd:c1:7b:89:3e:a2:cb:47:20:fa:36:a6:bc:17:5a:19:56:97:
- 1e:3c:fa:a7:fc:1e:d9:ad:dc:62:6b:ef:52:88:c8:d3:09:6c:
- 6f:ff:d4:28:4b:7d:1e:9d:bb:0c:08:12:f3:f8:fd:24:35:57:
- a2:3a:26:e2
------BEGIN CERTIFICATE-----
-MIIDPDCCAiQCCQCQI7JUHRqhtDANBgkqhkiG9w0BAQsFADBgMQswCQYDVQQGEwJV
-UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQ
-MA4GA1UECgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4xMB4XDTE0MDkxMTE5
-MTkyMloXDTI0MDkwODE5MTkyMlowYDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh
-bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB1Rlc3Qg
-Q0ExEjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
-AQoCggEBANJBJEy1pYOtuWRbkOLR5RcU/u7QatjQdDyYNdFrKoEynuSid1vygSyu
-wczK8EXdjiHTTKZ6aRsIPoMxDsxa+KS2BRBo7KCiRLaV6cXjfKL6oHLes0nnrMzc
-zvN8r58FRuTCMVSkK8y/q8Pipp0wJPQrTUTrY181D8Xs6XdADT01bIjnGMMBlUzB
-1BSWiGaY/Y4PDqFQ0/kT4bZdWoocjVXhQz3KxjGVnAoAaDgatyTOzTTWjfUReWR7
-AbMPdv3PynMzlgPkGi6Yi1RNC7liJ48NmiwfXbVq5DonMwLrfw0wam/qYcl4/nqf
-CHthzbiyBJgkN9X3zuw0KbO8JspvVFMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA
-c4lyFfrPyWpNpRpmDdoDEy4xa2/f8U/dVI29hx7psbKEStqO+na4ZvAt1vRyLVXv
-mdThmXx5mLe5vJz4aUdtEANLQVnqhHwEl2c31Kh1U0rz+ZrLuwn73dew1TVIBPNY
-eLz7Jtfc4r/LZCI997ukXqOYX6opRqrGqXyMBKwhIZexlNrr7kkDnUbgoCLk3eQr
-PQ0OrxtZOUHoR0O4WDaChsYO1tPAktorpFpa+E8gkzKndCETnbd7aCBxgUoaMrde
-50Xe9+QE3cF7iT6iy0cg+jamvBdaGVaXHjz6p/we2a3cYmvvUojI0wlsb//UKEt9
-Hp27DAgS8/j9JDVXojom4g==
------END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/scripts/client-certs.cnf b/chromium/net/data/ssl/scripts/client-certs.cnf
index 044bab17bc6..a028c73fc2d 100644
--- a/chromium/net/data/ssl/scripts/client-certs.cnf
+++ b/chromium/net/data/ssl/scripts/client-certs.cnf
@@ -42,6 +42,9 @@ distinguished_name = req_env_dn
basicConstraints = critical, CA:false
extendedKeyUsage = serverAuth,clientAuth
+[san_user_cert]
+subjectAltName = email:santest@example.com,otherName:msUPN;UTF8:santest@ad.corp.example.com
+
[ca_cert]
# Extensions to add when signing a request for an intermediate/CA cert
basicConstraints = critical, CA:true
diff --git a/chromium/net/data/ssl/scripts/generate-client-certificates.sh b/chromium/net/data/ssl/scripts/generate-client-certificates.sh
index 9ff313a231c..9fcc450c836 100755
--- a/chromium/net/data/ssl/scripts/generate-client-certificates.sh
+++ b/chromium/net/data/ssl/scripts/generate-client-certificates.sh
@@ -37,7 +37,7 @@ do
done
echo Generate the keys.
-for i in A B C D E
+for i in A B C D E F
do
try openssl genrsa -out out/$i.key 2048
done
@@ -104,7 +104,7 @@ COMMON_NAME="C CA" \
-config client-certs.cnf
echo Generate the leaf certs
-for id in A D
+for id in A D F
do
COMMON_NAME="Client Cert $id" \
ID=$id \
@@ -143,10 +143,22 @@ COMMON_NAME="E CA" \
-out out/D.pem \
-config client-certs.cnf
+echo E signs F
+COMMON_NAME="E CA" \
+ CA_DIR=out \
+ ID=E \
+ try openssl ca \
+ -batch \
+ -extensions san_user_cert \
+ -in out/F.csr \
+ -out out/F.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 openssl pkcs12 \
-in out/A-chain.pem \
@@ -160,6 +172,12 @@ try openssl pkcs12 \
-export \
-passout pass:chrome
+try openssl pkcs12 \
+ -in out/F-chain.pem \
+ -out client_3.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
@@ -170,3 +188,8 @@ try cp out/D.pem ../certificates/client_2.pem
try cp out/D.key ../certificates/client_2.key
try cp out/D.pk8 ../certificates/client_2.pk8
try cp out/E.pem ../certificates/client_2_ca.pem
+
+try cp out/F.pem ../certificates/client_3.pem
+try cp out/F.key ../certificates/client_3.key
+try cp out/F.pk8 ../certificates/client_3.pk8
+try cp out/E.pem ../certificates/client_3_ca.pem
diff --git a/chromium/net/data/ssl/scripts/generate-multi-root-test-chains.sh b/chromium/net/data/ssl/scripts/generate-multi-root-test-chains.sh
index 6f88325a3cc..c4d1792e1b7 100755
--- a/chromium/net/data/ssl/scripts/generate-multi-root-test-chains.sh
+++ b/chromium/net/data/ssl/scripts/generate-multi-root-test-chains.sh
@@ -4,158 +4,257 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-# This script generates two chains of test certificates:
+# The following documentation uses the annotation approach from RFC 4158.
+# CAs (entities that share the same name and public key) are denoted in boxes,
+# while the indication that a CA Foo signed a certificate for CA Bar is denoted
+# by directed arrows.
#
-# 1. A (end-entity) -> B -> C -> D (self-signed root)
-# 2. A (end-entity) -> B -> C2 -> E (self-signed root)
+# +---+ +-----+
+# | D | | E |
+# +---+ +-----+
+# | | |
+# +--v v--+ |
+# +---+ +---+
+# | C | | F |
+# +---+ +---+
+# | |
+# v v---+
+# +-----+
+# | B |
+# +-----+
+# |
+# v
+# +---+
+# | A |
+# +---+
#
-# C and C2 have the same subject and keypair.
+# To validate A, there are several possible paths, using A(B) to indicate
+# the certificate A signed by B:
#
-# We use these cert chains in CertVerifyProcChromeOSTest
-# to ensure that multiple verification paths are properly handled.
+# 1. A(B) -> B(C) -> C(D) -> D(D)
+# 3. A(B) -> B(C) -> C(E) -> E(E)
+# 4. A(B) -> B(F) -> F(E) -> E(E)
+#
+# That is, there are two different versions of C (signed by D and E) and
+# two versions of B (signed by C and F). Possible trust anchors are D and E,
+# which are both self-signed.
+#
+# The goal is to ensure that, as long as at least one of C or F is still valid,
+# clients are able to successfully build a valid path.
-try () {
- echo "$@"
- "$@" || exit 1
-}
+# Exit script as soon a something fails.
+set -e
-try rm -rf out
-try mkdir out
+rm -rf out
+mkdir out
-echo Create the serial number files.
+echo Create the serial and index number files.
serial=1000
-for i in B C C2 D E
+for i in B C D E F
do
- try /bin/sh -c "echo $serial > out/$i-serial"
- serial=$(expr $serial + 1)
+ /bin/sh -c "echo ${serial} > out/${i}-serial"
+ touch "out/${i}-index.txt"
done
echo Generate the keys.
-try openssl genrsa -out out/A.key 2048
-try openssl genrsa -out out/B.key 2048
-try openssl genrsa -out out/C.key 2048
-try openssl genrsa -out out/D.key 2048
-try openssl genrsa -out out/E.key 2048
-
-echo Generate the D CSR.
-CA_COMMON_NAME="D Root CA" \
- CERTIFICATE=D \
- try openssl req \
- -new \
- -key out/D.key \
- -out out/D.csr \
- -config redundant-ca.cnf
-
-echo D signs itself.
-CA_COMMON_NAME="D Root CA" \
- try openssl x509 \
- -req -days 3650 \
- -in out/D.csr \
- -extensions ca_cert \
- -extfile redundant-ca.cnf \
- -signkey out/D.key \
- -out out/D.pem \
- -text
-
-echo Generate the E CSR.
-CA_COMMON_NAME="E Root CA" \
- CERTIFICATE=E \
- try openssl req \
+for i in A B C D E F
+do
+ openssl genrsa -out "out/${i}.key" 2048
+done
+
+echo "Generating the self-signed roots"
+for i in D E
+do
+ echo "Generating CSR ${i}"
+ CA_COMMON_NAME="${i} Root CA - Multi-root" \
+ CERTIFICATE="${i}" \
+ openssl req \
+ -config redundant-ca.cnf \
-new \
- -key out/E.key \
- -out out/E.csr \
- -config redundant-ca.cnf
-
-echo E signs itself.
-CA_COMMON_NAME="E Root CA" \
- try openssl x509 \
- -req -days 3650 \
- -in out/E.csr \
+ -key "out/${i}.key" \
+ -out "out/${i}.csr"
+
+ echo "Generating self-signed ${i}"
+ CA_COMMON_NAME="${i} Root CA - Multi-root" \
+ CERTIFICATE="${i}" \
+ openssl ca \
+ -config redundant-ca.cnf \
+ -batch \
+ -startdate 160102000000Z \
+ -enddate 260102000000Z \
-extensions ca_cert \
-extfile redundant-ca.cnf \
- -signkey out/E.key \
- -out out/E.pem \
- -text
-
-echo Generate the C2 intermediary CSR.
-CA_COMMON_NAME="C CA" \
- CERTIFICATE=C2 \
- try openssl req \
+ -selfsign \
+ -in "out/${i}.csr" \
+ -out "out/${i}.pem"
+done
+
+echo "Generating intermediate CSRs"
+for i in B C F
+do
+ echo "Generating CSR ${i}"
+ CA_COMMON_NAME="${i} CA - Multi-root" \
+ CERTIFICATE="${i}" \
+ openssl req \
+ -config redundant-ca.cnf \
-new \
- -key out/C.key \
- -out out/C2.csr \
- -config redundant-ca.cnf
+ -key "out/${i}.key" \
+ -out "out/${i}.csr"
+done
+
+echo D signs C
+CA_COMMON_NAME="D CA - Multi-root" \
+CERTIFICATE=D \
+openssl ca \
+ -config redundant-ca.cnf \
+ -batch \
+ -startdate 160103000000Z \
+ -enddate 260102000000Z \
+ -extensions ca_cert \
+ -extfile redundant-ca.cnf \
+ -in out/C.csr \
+ -out out/C.pem
+
+echo C signs B
+CA_COMMON_NAME="C CA - Multi-root" \
+CERTIFICATE=C \
+openssl ca \
+ -config redundant-ca.cnf \
+ -batch \
+ -startdate 160104000000Z \
+ -enddate 260102000000Z \
+ -extensions ca_cert \
+ -extfile redundant-ca.cnf \
+ -in out/B.csr \
+ -out out/B.pem
+
+echo E signs C2
+CA_COMMON_NAME="E CA - Multi-root" \
+CERTIFICATE=E \
+openssl ca \
+ -config redundant-ca.cnf \
+ -batch \
+ -startdate 160105000000Z \
+ -enddate 260102000000Z \
+ -extensions ca_cert \
+ -extfile redundant-ca.cnf \
+ -in out/C.csr \
+ -out out/C2.pem
+
+echo E signs F
+CA_COMMON_NAME="E CA - Multi-root" \
+CERTIFICATE=E \
+openssl ca \
+ -config redundant-ca.cnf \
+ -batch \
+ -startdate 160102000000Z \
+ -enddate 260102000000Z \
+ -extensions ca_cert \
+ -extfile redundant-ca.cnf \
+ -in out/F.csr \
+ -out out/F.pem
-echo Generate the B and C intermediaries\' CSRs.
-for i in B C
+# Note: The startdate for B-by-F MUST be different than that of B-by-C; to make
+# B-by-F more preferable, the startdate is chosen to be GREATER (later) than
+# B-by-C.
+echo F signs B2
+CA_COMMON_NAME="F CA - Multi-root" \
+CERTIFICATE=F \
+openssl ca \
+ -config redundant-ca.cnf \
+ -batch \
+ -startdate 160105000000Z \
+ -enddate 260102000000Z \
+ -extensions ca_cert \
+ -extfile redundant-ca.cnf \
+ -in out/B.csr \
+ -out out/B2.pem
+
+echo "Generating leaf CSRs"
+for i in A
do
- CA_COMMON_NAME="$i CA" \
- CERTIFICATE="$i" \
- try openssl req \
- -new \
- -key "out/$i.key" \
- -out "out/$i.csr" \
- -config redundant-ca.cnf
+ echo "Generating leaf ${i}"
+ openssl req \
+ -config ee.cnf \
+ -new \
+ -key "out/${i}.key" \
+ -out "out/${i}.csr"
done
-echo D signs the C intermediate.
-# Make sure the signer's DB file exists.
-touch out/D-index.txt
-CA_COMMON_NAME="D Root CA" \
- CERTIFICATE=D \
- try openssl ca \
- -batch \
- -extensions ca_cert \
- -in out/C.csr \
- -out out/C.pem \
- -config redundant-ca.cnf
-
-echo E signs the C2 intermediate.
-# Make sure the signer's DB file exists.
-touch out/E-index.txt
-CA_COMMON_NAME="E Root CA" \
- CERTIFICATE=E \
- try openssl ca \
- -batch \
- -extensions ca_cert \
- -in out/C2.csr \
- -out out/C2.pem \
- -config redundant-ca.cnf
-
-echo C signs the B intermediate.
-touch out/C-index.txt
-CA_COMMON_NAME="C CA" \
- CERTIFICATE=C \
- try openssl ca \
- -batch \
- -extensions ca_cert \
- -in out/B.csr \
- -out out/B.pem \
- -config redundant-ca.cnf
-
-echo Generate the A end-entity CSR.
-try openssl req \
- -new \
- -key out/A.key \
- -out out/A.csr \
- -config ee.cnf
-
-echo B signs A.
-touch out/B-index.txt
-CA_COMMON_NAME="B CA" \
- CERTIFICATE=B \
- try openssl ca \
- -batch \
- -extensions user_cert \
- -in out/A.csr \
- -out out/A.pem \
- -config redundant-ca.cnf
+echo "Signing leaves"
+CA_COMMON_NAME="B CA - Multi-root" \
+CERTIFICATE=B \
+openssl ca \
+ -config redundant-ca.cnf \
+ -batch \
+ -days 3650 \
+ -extensions user_cert \
+ -extfile redundant-ca.cnf \
+ -in out/A.csr \
+ -out out/A.pem
-echo Create multi-root-chain1.pem
-try /bin/sh -c "cat out/A.key out/A.pem out/B.pem out/C.pem out/D.pem \
+echo "Copying outputs"
+/bin/sh -c "cat out/A.key out/A.pem > ../certificates/multi-root-A-by-B.pem"
+/bin/sh -c "cat out/A.pem out/B.pem out/C.pem out/D.pem \
> ../certificates/multi-root-chain1.pem"
-
-echo Create multi-root-chain2.pem
-try /bin/sh -c "cat out/A.key out/A.pem out/B.pem out/C2.pem out/E.pem \
+/bin/sh -c "cat out/A.pem out/B.pem out/C2.pem out/E.pem \
> ../certificates/multi-root-chain2.pem"
+cp out/B.pem ../certificates/multi-root-B-by-C.pem
+cp out/B2.pem ../certificates/multi-root-B-by-F.pem
+cp out/C.pem ../certificates/multi-root-C-by-D.pem
+cp out/C2.pem ../certificates/multi-root-C-by-E.pem
+cp out/F.pem ../certificates/multi-root-F-by-E.pem
+cp out/D.pem ../certificates/multi-root-D-by-D.pem
+cp out/E.pem ../certificates/multi-root-E-by-E.pem
+echo "Generating CRLSets"
+# Block D and E by SPKI; invalidates all paths.
+python crlsetutil.py -o ../certificates/multi-root-crlset-D-and-E.raw \
+<<CRLSETDOCBLOCK
+{
+ "BlockedBySPKI": [
+ "out/D.pem",
+ "out/E.pem"
+ ]
+}
+CRLSETDOCBLOCK
+
+# Block E by SPKI.
+python crlsetutil.py -o ../certificates/multi-root-crlset-E.raw \
+<<CRLSETDOCBLOCK
+{
+ "BlockedBySPKI": [
+ "out/E.pem"
+ ]
+}
+CRLSETDOCBLOCK
+
+# Block C-by-D (serial number 0x1001) and F-by-E (serial number 0x1002) by
+# way of serial number.
+python crlsetutil.py -o ../certificates/multi-root-crlset-CD-and-FE.raw \
+<<CRLSETDOCBLOCK
+{
+ "BlockedByHash": {
+ "out/D.pem": [4097],
+ "out/E.pem": [4098]
+ }
+}
+CRLSETDOCBLOCK
+
+# Block C (all versions) by way of SPKI
+python crlsetutil.py -o ../certificates/multi-root-crlset-C.raw \
+<<CRLSETDOCBLOCK
+{
+ "BlockedBySPKI": [ "out/C.pem" ]
+}
+CRLSETDOCBLOCK
+
+# Block an unrelated/unissued serial (0x0FFF) to enable all paths.
+python crlsetutil.py -o ../certificates/multi-root-crlset-unrelated.raw \
+<<CRLSETDOCBLOCK
+{
+ "BlockedByHash": {
+ "out/E.pem": [4095]
+ }
+}
+CRLSETDOCBLOCK
diff --git a/chromium/net/data/ssl/scripts/generate-test-certs.sh b/chromium/net/data/ssl/scripts/generate-test-certs.sh
index 13586531b8c..3f9e49518fb 100755
--- a/chromium/net/data/ssl/scripts/generate-test-certs.sh
+++ b/chromium/net/data/ssl/scripts/generate-test-certs.sh
@@ -152,12 +152,6 @@ try /bin/sh -c "cat out/ok_cert.key out/bad_validity.pem \
> ../certificates/bad_validity.pem"
# Now generate the one-off certs
-## SHA-256 general test cert
-try openssl req -x509 -days 3650 \
- -config ../scripts/ee.cnf -newkey rsa:2048 -text \
- -sha256 \
- -out ../certificates/sha256.pem
-
## Self-signed cert for SPDY/QUIC/HTTP2 pooling testing
try openssl req -x509 -days 3650 -extensions req_spdy_pooling \
-config ../scripts/ee.cnf -newkey rsa:2048 -text \
diff --git a/chromium/net/data/ssl/scripts/redundant-ca.cnf b/chromium/net/data/ssl/scripts/redundant-ca.cnf
index 5707b730bfb..46e395fa890 100644
--- a/chromium/net/data/ssl/scripts/redundant-ca.cnf
+++ b/chromium/net/data/ssl/scripts/redundant-ca.cnf
@@ -30,9 +30,16 @@ extendedKeyUsage = serverAuth,clientAuth
# Extensions to add when signing a request for an intermediate/CA cert
basicConstraints = critical, CA:true
subjectKeyIdentifier = hash
-#authorityKeyIdentifier = keyid:always
keyUsage = critical, keyCertSign, cRLSign
+[ca_cert_with_aki]
+# Extensions to add when signing a request for an intermediate/CA cert
+basicConstraints = critical, CA:true
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always
+keyUsage = critical, keyCertSign, cRLSign
+
+
[crl_extensions]
# Extensions to add when signing a CRL
authorityKeyIdentifier = keyid:always
diff --git a/chromium/net/data/url_request_unittest/expect-ct-header.html b/chromium/net/data/url_request_unittest/expect-ct-header.html
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/net/data/url_request_unittest/expect-ct-header.html
diff --git a/chromium/net/data/url_request_unittest/expect-ct-header.html.mock-http-headers b/chromium/net/data/url_request_unittest/expect-ct-header.html.mock-http-headers
new file mode 100644
index 00000000000..3e11658273d
--- /dev/null
+++ b/chromium/net/data/url_request_unittest/expect-ct-header.html.mock-http-headers
@@ -0,0 +1,4 @@
+HTTP/1.1 200 OK
+Cache-Control: private
+Content-Type: text/html; charset=ISO-8859-1
+Expect-CT: preload
diff --git a/chromium/net/data/verify_signed_data_unittest/annotate_test_data.py b/chromium/net/data/verify_signed_data_unittest/annotate_test_data.py
index 7928fa2ee96..733392ee060 100755
--- a/chromium/net/data/verify_signed_data_unittest/annotate_test_data.py
+++ b/chromium/net/data/verify_signed_data_unittest/annotate_test_data.py
@@ -24,21 +24,15 @@ def Transform(file_data):
result = ''
- # Get the file's description (all the text before the first PEM block)
- file_description = GetTextUntilNextPemBlock(file_data)
-
- result += file_description + '\n'
-
for block in GetPemBlocks(file_data):
- result += '\n\n\n'
-
- result += MakePemBlockString(block.name, block.data)
+ if len(result) != 0:
+ result += '\n'
# If there was a user comment (non-script-generated comment) associated
- # with the block, output it immediately after the block.
+ # with the block, output it immediately before the block.
user_comment = GetUserComment(block.comment)
if user_comment:
- result += '\n' + user_comment + '\n'
+ result += user_comment
# For every block except for DATA, try to pretty print the parsed ASN.1.
# DATA blocks likely would be DER in practice, but for the purposes of
@@ -46,7 +40,10 @@ def Transform(file_data):
# anything and is just a distraction.
if block.name != 'DATA':
generated_comment = GenerateCommentForBlock(block.name, block.data)
- result += '\n' + generated_comment + '\n'
+ result += generated_comment + '\n'
+
+
+ result += MakePemBlockString(block.name, block.data)
return result
@@ -63,15 +60,12 @@ def GenerateCommentForBlock(block_name, block_data):
return generated_comment.strip('\n')
-def GetTextUntilNextPemBlock(text):
- return text.split('-----BEGIN ', 1)[0].strip('\n')
-
def GetUserComment(comment):
"""Removes any script-generated lines (everything after the $ openssl line)"""
# Consider everything after "$ openssl" to be a generated comment.
- comment = comment.split('$ openssl asn1parse -i', 1)[0].strip('\n')
+ comment = comment.split('$ openssl asn1parse -i', 1)[0]
if IsEntirelyWhiteSpace(comment):
comment = ''
return comment
@@ -133,6 +127,8 @@ def DecodePemBlockData(text):
def GetPemBlocks(data):
"""Returns an iterable of PemBlock"""
+ comment_start = 0
+
regex = re.compile(r'-----BEGIN ([\w ]+)-----(.*?)-----END \1-----',
re.DOTALL)
@@ -142,8 +138,9 @@ def GetPemBlocks(data):
block.name = match.group(1)
block.data = DecodePemBlockData(match.group(2))
- # Keep track of any non-PEM text between blocks
- block.comment = GetTextUntilNextPemBlock(data[match.end():])
+ # Keep track of any non-PEM text above blocks
+ block.comment = data[comment_start : match.start()].strip()
+ comment_start = match.end()
yield block
diff --git a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-spki-params-null.pem b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-spki-params-null.pem
index 6f65be14832..cf5cb2f75fe 100644
--- a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-spki-params-null.pem
+++ b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-spki-params-null.pem
@@ -3,30 +3,23 @@ algorithm has been tampered with. The parameters for ecPublicKey should be a
namedCurve, but here they have been replaced by NULL.
-
------BEGIN PUBLIC KEY-----
-MFEwCwYHKoZIzj0CAQUAA0IABJywz2kwPa/HYdTkaHtOzwOebTSrlkr4CBDY1VikqNb3LVEjOhe
-IkgqG7gihlix576MX+3h54pfa0hRtuZX6HHg=
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=2 l= 81 cons: SEQUENCE
2:d=1 hl=2 l= 11 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 0 prim: NULL
15:d=1 hl=2 l= 66 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MAoGCCqGSM49BAME
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MFEwCwYHKoZIzj0CAQUAA0IABJywz2kwPa/HYdTkaHtOzwOebTSrlkr4CBDY1VikqNb3LVEjOhe
+IkgqG7gihlix576MX+3h54pfa0hRtuZX6HHg=
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 10 cons: SEQUENCE
2:d=1 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA512
-
-
+-----BEGIN ALGORITHM-----
+MAoGCCqGSM49BAME
+-----END ALGORITHM-----
-----BEGIN DATA-----
bikyFTMBpO72gOZCiSmtrpiMEI1mijH/VdBImUfXX/gaRr+J6E1kAfAjvm6HaI+814TXhcqEZzV
@@ -34,12 +27,9 @@ SSstS0ARSyEBApHnnzDMJNkQdk7vnIqlDKm4dsRK1yUA7ECcssTR/1hnUY/ep0iOtdv3gbYpog1
APuEMjWr/5jiQb37VTjD4=
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=2 l= 71 prim: BIT STRING
-----BEGIN SIGNATURE-----
A0cAMEQCIEufkeQoUocmGh0ckjz2Gc1SwXXP5/G+YKUljGEDSLo9AiAoxF+QHXHEGymGOOwNaoX
X/LDDO7/sWpyBCEa2OSiahA==
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=2 l= 71 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-unused-bits-signature.pem b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-unused-bits-signature.pem
index 24efda02bf5..a7c4960dc48 100644
--- a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-unused-bits-signature.pem
+++ b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-unused-bits-signature.pem
@@ -11,30 +11,23 @@ To:
03 47 02 30 ... 84
-
------BEGIN PUBLIC KEY-----
-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnLDPaTA9r8dh1ORoe07PA55tNKuWSvgIENjVWKS
-o1vctUSM6F4iSCobuCKGWLHnvoxf7eHnil9rSFG25lfoceA==
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=2 l= 89 cons: SEQUENCE
2:d=1 hl=2 l= 19 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
23:d=1 hl=2 l= 66 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MAoGCCqGSM49BAME
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnLDPaTA9r8dh1ORoe07PA55tNKuWSvgIENjVWKS
+o1vctUSM6F4iSCobuCKGWLHnvoxf7eHnil9rSFG25lfoceA==
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 10 cons: SEQUENCE
2:d=1 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA512
-
-
+-----BEGIN ALGORITHM-----
+MAoGCCqGSM49BAME
+-----END ALGORITHM-----
-----BEGIN DATA-----
bikyFTMBpO72gOZCiSmtrpiMEI1mijH/VdBImUfXX/gaRr+J6E1kAfAjvm6HaI+814TXhcqEZzV
@@ -42,12 +35,9 @@ SSstS0ARSyEBApHnnzDMJNkQdk7vnIqlDKm4dsRK1yUA7ECcssTR/1hnUY/ep0iOtdv3gbYpog1
APuEMjWr/5jiQb37VTjD4=
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=2 l= 71 prim: BIT STRING
-----BEGIN SIGNATURE-----
A0cCMEQCIEufkeQoUocmGh0ckjz2Gc1SwXXP5/G+YKUljGEDSLo9AiAoxF+QHXHEGymGOOwNaoX
X/LDDO7/sWpyBCEa2OSiahA==
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=2 l= 71 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecdh-key.pem b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecdh-key.pem
index 4f3e26c5cad..b0174324f68 100644
--- a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecdh-key.pem
+++ b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecdh-key.pem
@@ -6,30 +6,23 @@ This test should fail because the public key's algorithm does not match that of
the signature algorithm.
-
------BEGIN PUBLIC KEY-----
-MFcwEQYFK4EEAQwGCCqGSM49AwEHA0IABJywz2kwPa/HYdTkaHtOzwOebTSrlkr4CBDY1VikqNb
-3LVEjOheIkgqG7gihlix576MX+3h54pfa0hRtuZX6HHg=
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=2 l= 87 cons: SEQUENCE
2:d=1 hl=2 l= 17 cons: SEQUENCE
4:d=2 hl=2 l= 5 prim: OBJECT :1.3.132.1.12
11:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
21:d=1 hl=2 l= 66 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MAoGCCqGSM49BAME
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MFcwEQYFK4EEAQwGCCqGSM49AwEHA0IABJywz2kwPa/HYdTkaHtOzwOebTSrlkr4CBDY1VikqNb
+3LVEjOheIkgqG7gihlix576MX+3h54pfa0hRtuZX6HHg=
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 10 cons: SEQUENCE
2:d=1 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA512
-
-
+-----BEGIN ALGORITHM-----
+MAoGCCqGSM49BAME
+-----END ALGORITHM-----
-----BEGIN DATA-----
bikyFTMBpO72gOZCiSmtrpiMEI1mijH/VdBImUfXX/gaRr+J6E1kAfAjvm6HaI+814TXhcqEZzV
@@ -37,12 +30,9 @@ SSstS0ARSyEBApHnnzDMJNkQdk7vnIqlDKm4dsRK1yUA7ECcssTR/1hnUY/ep0iOtdv3gbYpog1
APuEMjWr/5jiQb37VTjD4=
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=2 l= 71 prim: BIT STRING
-----BEGIN SIGNATURE-----
A0cAMEQCIEufkeQoUocmGh0ckjz2Gc1SwXXP5/G+YKUljGEDSLo9AiAoxF+QHXHEGymGOOwNaoX
X/LDDO7/sWpyBCEa2OSiahA==
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=2 l= 71 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecmqv-key.pem b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecmqv-key.pem
index d0b906f0be6..23f4605cf38 100644
--- a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecmqv-key.pem
+++ b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecmqv-key.pem
@@ -6,30 +6,23 @@ This test should fail because the public key's algorithm does not match that of
the signature algorithm.
-
------BEGIN PUBLIC KEY-----
-MFcwEQYFK4EEAQ0GCCqGSM49AwEHA0IABJywz2kwPa/HYdTkaHtOzwOebTSrlkr4CBDY1VikqNb
-3LVEjOheIkgqG7gihlix576MX+3h54pfa0hRtuZX6HHg=
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=2 l= 87 cons: SEQUENCE
2:d=1 hl=2 l= 17 cons: SEQUENCE
4:d=2 hl=2 l= 5 prim: OBJECT :1.3.132.1.13
11:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
21:d=1 hl=2 l= 66 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MAoGCCqGSM49BAME
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MFcwEQYFK4EEAQ0GCCqGSM49AwEHA0IABJywz2kwPa/HYdTkaHtOzwOebTSrlkr4CBDY1VikqNb
+3LVEjOheIkgqG7gihlix576MX+3h54pfa0hRtuZX6HHg=
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 10 cons: SEQUENCE
2:d=1 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA512
-
-
+-----BEGIN ALGORITHM-----
+MAoGCCqGSM49BAME
+-----END ALGORITHM-----
-----BEGIN DATA-----
bikyFTMBpO72gOZCiSmtrpiMEI1mijH/VdBImUfXX/gaRr+J6E1kAfAjvm6HaI+814TXhcqEZzV
@@ -37,12 +30,9 @@ SSstS0ARSyEBApHnnzDMJNkQdk7vnIqlDKm4dsRK1yUA7ECcssTR/1hnUY/ep0iOtdv3gbYpog1
APuEMjWr/5jiQb37VTjD4=
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=2 l= 71 prim: BIT STRING
-----BEGIN SIGNATURE-----
A0cAMEQCIEufkeQoUocmGh0ckjz2Gc1SwXXP5/G+YKUljGEDSLo9AiAoxF+QHXHEGymGOOwNaoX
X/LDDO7/sWpyBCEa2OSiahA==
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=2 l= 71 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-rsa-algorithm.pem b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-rsa-algorithm.pem
index 8085486f726..f2b2168b204 100644
--- a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-rsa-algorithm.pem
+++ b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-rsa-algorithm.pem
@@ -5,31 +5,24 @@ The problem however is the signature algorithm is indicated as being RSA PKCS#1
Signature verification consequently should fail.
-
------BEGIN PUBLIC KEY-----
-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnLDPaTA9r8dh1ORoe07PA55tNKuWSvgIENjVWKS
-o1vctUSM6F4iSCobuCKGWLHnvoxf7eHnil9rSFG25lfoceA==
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=2 l= 89 cons: SEQUENCE
2:d=1 hl=2 l= 19 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
23:d=1 hl=2 l= 66 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBDQUA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnLDPaTA9r8dh1ORoe07PA55tNKuWSvgIENjVWKS
+o1vctUSM6F4iSCobuCKGWLHnvoxf7eHnil9rSFG25lfoceA==
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha512WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBDQUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
bikyFTMBpO72gOZCiSmtrpiMEI1mijH/VdBImUfXX/gaRr+J6E1kAfAjvm6HaI+814TXhcqEZzV
@@ -37,12 +30,9 @@ SSstS0ARSyEBApHnnzDMJNkQdk7vnIqlDKm4dsRK1yUA7ECcssTR/1hnUY/ep0iOtdv3gbYpog1
APuEMjWr/5jiQb37VTjD4=
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=2 l= 71 prim: BIT STRING
-----BEGIN SIGNATURE-----
A0cAMEQCIEufkeQoUocmGh0ckjz2Gc1SwXXP5/G+YKUljGEDSLo9AiAoxF+QHXHEGymGOOwNaoX
X/LDDO7/sWpyBCEa2OSiahA==
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=2 l= 71 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-wrong-signature-format.pem b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-wrong-signature-format.pem
index d51317ceeab..58c2e2c95c8 100644
--- a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-wrong-signature-format.pem
+++ b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512-wrong-signature-format.pem
@@ -5,30 +5,23 @@ concatenation of the r and s values. This is the format that WebCrypto uses for
ECDSA signature, but not what is used for digital signatures.
-
------BEGIN PUBLIC KEY-----
-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnLDPaTA9r8dh1ORoe07PA55tNKuWSvgIENjVWKS
-o1vctUSM6F4iSCobuCKGWLHnvoxf7eHnil9rSFG25lfoceA==
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=2 l= 89 cons: SEQUENCE
2:d=1 hl=2 l= 19 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
23:d=1 hl=2 l= 66 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MAoGCCqGSM49BAME
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnLDPaTA9r8dh1ORoe07PA55tNKuWSvgIENjVWKS
+o1vctUSM6F4iSCobuCKGWLHnvoxf7eHnil9rSFG25lfoceA==
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 10 cons: SEQUENCE
2:d=1 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA512
-
-
+-----BEGIN ALGORITHM-----
+MAoGCCqGSM49BAME
+-----END ALGORITHM-----
-----BEGIN DATA-----
bikyFTMBpO72gOZCiSmtrpiMEI1mijH/VdBImUfXX/gaRr+J6E1kAfAjvm6HaI+814TXhcqEZzV
@@ -36,12 +29,9 @@ SSstS0ARSyEBApHnnzDMJNkQdk7vnIqlDKm4dsRK1yUA7ECcssTR/1hnUY/ep0iOtdv3gbYpog1
APuEMjWr/5jiQb37VTjD4=
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=2 l= 65 prim: BIT STRING
-----BEGIN SIGNATURE-----
A0EAS5+R5ChShyYaHRySPPYZzVLBdc/n8b5gpSWMYQNIuj0oxF+QHXHEGymGOOwNaoXX/LDDO7/
sWpyBCEa2OSiahA==
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=2 l= 65 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512.pem b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512.pem
index 54f490c10cf..6e104e841ba 100644
--- a/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512.pem
+++ b/chromium/net/data/verify_signed_data_unittest/ecdsa-prime256v1-sha512.pem
@@ -7,30 +7,23 @@ and s tuple) was encoded into a Ecdsa-Sig-Value and then a BIT STRING.
It uses ECDSA verification, using curve prime256v1 and SHA-512
-
------BEGIN PUBLIC KEY-----
-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnLDPaTA9r8dh1ORoe07PA55tNKuWSvgIENjVWKS
-o1vctUSM6F4iSCobuCKGWLHnvoxf7eHnil9rSFG25lfoceA==
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=2 l= 89 cons: SEQUENCE
2:d=1 hl=2 l= 19 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
23:d=1 hl=2 l= 66 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MAoGCCqGSM49BAME
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnLDPaTA9r8dh1ORoe07PA55tNKuWSvgIENjVWKS
+o1vctUSM6F4iSCobuCKGWLHnvoxf7eHnil9rSFG25lfoceA==
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 10 cons: SEQUENCE
2:d=1 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA512
-
-
+-----BEGIN ALGORITHM-----
+MAoGCCqGSM49BAME
+-----END ALGORITHM-----
-----BEGIN DATA-----
bikyFTMBpO72gOZCiSmtrpiMEI1mijH/VdBImUfXX/gaRr+J6E1kAfAjvm6HaI+814TXhcqEZzV
@@ -38,12 +31,9 @@ SSstS0ARSyEBApHnnzDMJNkQdk7vnIqlDKm4dsRK1yUA7ECcssTR/1hnUY/ep0iOtdv3gbYpog1
APuEMjWr/5jiQb37VTjD4=
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=2 l= 71 prim: BIT STRING
-----BEGIN SIGNATURE-----
A0cAMEQCIEufkeQoUocmGh0ckjz2Gc1SwXXP5/G+YKUljGEDSLo9AiAoxF+QHXHEGymGOOwNaoX
X/LDDO7/sWpyBCEa2OSiahA==
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=2 l= 71 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/ecdsa-secp384r1-sha256-corrupted-data.pem b/chromium/net/data/verify_signed_data_unittest/ecdsa-secp384r1-sha256-corrupted-data.pem
index 5f5380bdd89..5cb5358f539 100644
--- a/chromium/net/data/verify_signed_data_unittest/ecdsa-secp384r1-sha256-corrupted-data.pem
+++ b/chromium/net/data/verify_signed_data_unittest/ecdsa-secp384r1-sha256-corrupted-data.pem
@@ -4,31 +4,24 @@ has been corrupted. The third byte has been set to 0.
This signature should NOT verify successfully.
-
------BEGIN PUBLIC KEY-----
-MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXFhBi+WKXuxeK9yCbC9jqEchwjCNsQ4RXAsJ07oHZ+Q
-qz55cNIY5BAhcQ0QYY5jv9BimGL9SuhUuOSuS3Pn9rrsIFGcFsihy4kDr8rq5+7RbN8bV057gW5
-emYjLtvDsQ
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=2 l= 118 cons: SEQUENCE
2:d=1 hl=2 l= 16 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 5 prim: OBJECT :secp384r1
20:d=1 hl=2 l= 98 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MAoGCCqGSM49BAMC
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXFhBi+WKXuxeK9yCbC9jqEchwjCNsQ4RXAsJ07oHZ+Q
+qz55cNIY5BAhcQ0QYY5jv9BimGL9SuhUuOSuS3Pn9rrsIFGcFsihy4kDr8rq5+7RbN8bV057gW5
+emYjLtvDsQ
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 10 cons: SEQUENCE
2:d=1 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA256
-
-
+-----BEGIN ALGORITHM-----
+MAoGCCqGSM49BAMC
+-----END ALGORITHM-----
-----BEGIN DATA-----
MIIA6KADAgECAgkAtUVxft6/Vc0wCgYIKoZIzj0EAwIwbzELMAkGA1UEBhMCQVUxEzARBgNVBAg
@@ -42,12 +35,9 @@ Fs3xtXTnuBbl6ZiMu28OxCjUDBOMB0GA1UdDgQWBBR6nDgtPalG2JvSlWzdGRCi/Cu7NjAfBgNV
HSMEGDAWgBR6nDgtPalG2JvSlWzdGRCi/Cu7NjAMBgNVHRMEBTADAQH/
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=2 l= 105 prim: BIT STRING
-----BEGIN SIGNATURE-----
A2kAMGYCMQCDwMSZVJZ8qThiNTV7VX57m8fdNnNS6cXIjRYoh4SozlYWmWGh87nhmJJCeD16jVM
CMQDkroAY8oNi8RxLUor+LozhhVgu24tu6lcp4MP8H3Zy8bBea5HerAd1AqJp3Ox7KDU=
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=2 l= 105 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/ecdsa-secp384r1-sha256.pem b/chromium/net/data/verify_signed_data_unittest/ecdsa-secp384r1-sha256.pem
index d5c3798c752..b417714f8fd 100644
--- a/chromium/net/data/verify_signed_data_unittest/ecdsa-secp384r1-sha256.pem
+++ b/chromium/net/data/verify_signed_data_unittest/ecdsa-secp384r1-sha256.pem
@@ -35,31 +35,24 @@ It uses ECDSA with curve secp384r1 an SHA-256.
base64 sig
-
------BEGIN PUBLIC KEY-----
-MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXFhBi+WKXuxeK9yCbC9jqEchwjCNsQ4RXAsJ07oHZ+Q
-qz55cNIY5BAhcQ0QYY5jv9BimGL9SuhUuOSuS3Pn9rrsIFGcFsihy4kDr8rq5+7RbN8bV057gW5
-emYjLtvDsQ
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=2 l= 118 cons: SEQUENCE
2:d=1 hl=2 l= 16 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 5 prim: OBJECT :secp384r1
20:d=1 hl=2 l= 98 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MAoGCCqGSM49BAMC
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXFhBi+WKXuxeK9yCbC9jqEchwjCNsQ4RXAsJ07oHZ+Q
+qz55cNIY5BAhcQ0QYY5jv9BimGL9SuhUuOSuS3Pn9rrsIFGcFsihy4kDr8rq5+7RbN8bV057gW5
+emYjLtvDsQ
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 10 cons: SEQUENCE
2:d=1 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA256
-
-
+-----BEGIN ALGORITHM-----
+MAoGCCqGSM49BAMC
+-----END ALGORITHM-----
-----BEGIN DATA-----
MIIB6KADAgECAgkAtUVxft6/Vc0wCgYIKoZIzj0EAwIwbzELMAkGA1UEBhMCQVUxEzARBgNVBAg
@@ -73,12 +66,9 @@ Fs3xtXTnuBbl6ZiMu28OxCjUDBOMB0GA1UdDgQWBBR6nDgtPalG2JvSlWzdGRCi/Cu7NjAfBgNV
HSMEGDAWgBR6nDgtPalG2JvSlWzdGRCi/Cu7NjAMBgNVHRMEBTADAQH/
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=2 l= 105 prim: BIT STRING
-----BEGIN SIGNATURE-----
A2kAMGYCMQCDwMSZVJZ8qThiNTV7VX57m8fdNnNS6cXIjRYoh4SozlYWmWGh87nhmJJCeD16jVM
CMQDkroAY8oNi8RxLUor+LozhhVgu24tu6lcp4MP8H3Zy8bBea5HerAd1AqJp3Ox7KDU=
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=2 l= 105 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/ecdsa-using-rsa-key.pem b/chromium/net/data/verify_signed_data_unittest/ecdsa-using-rsa-key.pem
index 653bcd782bf..06d18ef882e 100644
--- a/chromium/net/data/verify_signed_data_unittest/ecdsa-using-rsa-key.pem
+++ b/chromium/net/data/verify_signed_data_unittest/ecdsa-using-rsa-key.pem
@@ -2,31 +2,24 @@ This test specifies an ECDSA signature algorithm (and a valid ecdsa signature),
HOWEVER it provides an RSA key. Verification should fail.
-
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
-mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
-I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 159 cons: SEQUENCE
3:d=1 hl=2 l= 13 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
16:d=2 hl=2 l= 0 prim: NULL
18:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MAoGCCqGSM49BAMC
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
+mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
+I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 10 cons: SEQUENCE
2:d=1 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA256
-
-
+-----BEGIN ALGORITHM-----
+MAoGCCqGSM49BAMC
+-----END ALGORITHM-----
-----BEGIN DATA-----
MIIB6KADAgECAgkAtUVxft6/Vc0wCgYIKoZIzj0EAwIwbzELMAkGA1UEBhMCQVUxEzARBgNVBAg
@@ -40,12 +33,9 @@ Fs3xtXTnuBbl6ZiMu28OxCjUDBOMB0GA1UdDgQWBBR6nDgtPalG2JvSlWzdGRCi/Cu7NjAfBgNV
HSMEGDAWgBR6nDgtPalG2JvSlWzdGRCi/Cu7NjAMBgNVHRMEBTADAQH/
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=2 l= 105 prim: BIT STRING
-----BEGIN SIGNATURE-----
A2kAMGYCMQCDwMSZVJZ8qThiNTV7VX57m8fdNnNS6cXIjRYoh4SozlYWmWGh87nhmJJCeD16jVM
CMQDkroAY8oNi8RxLUor+LozhhVgu24tu6lcp4MP8H3Zy8bBea5HerAd1AqJp3Ox7KDU=
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=2 l= 105 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-length.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-length.pem
index ef7967d894f..c2ee87077f5 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-length.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-length.pem
@@ -2,28 +2,21 @@ Same test as rsa-pkcs1-sha1.pem except the length of the first SEQUENCE has
been increased by 2 (which makes it invalid).
-
+$ openssl asn1parse -i < [PUBLIC KEY]
+Error in encoding
-----BEGIN PUBLIC KEY-----
MIOfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
-----END PUBLIC KEY-----
-$ openssl asn1parse -i < [PUBLIC KEY]
-Error in encoding
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBBQUA
------END ALGORITHM-----
-
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBBQUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
zch9oiPXht87ReC7vHITJtHuKvgGzDFUdcxvDZxm4bYjcdRc4jkuGskoRMMQEC8Vag2NUsH0xAu
@@ -32,13 +25,10 @@ vr538Gznjgj0CY+6QfnWGTwDF+i2DUtghKy0LSnjgIo7w3LYXjMRcPy/fMctC3HClmSLOk0Q9BY
pXQgHqmJcqydE/Z6o/SI8QlNwKYKL0WvgJUbxMP0uM7k20mduCK7RtzMYt1CgFn0A==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBAGvDoGZWhCkwokfjDVhktNgZI2unxollhirX28TiSvKOhrtTHwM1i+X7dHd8YIb4UMrviT8
Nb8wtDJHsATaTtOoAuAzUmqxOy1+JEa/lOa2kqPOCPR0T5HLRSQVHxlnHYX89JAh9228rcglhZ/
wJfKsY6aRY/LY0zc6O41iUxITX
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-null.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-null.pem
index 59559f44878..a88a8063667 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-null.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-null.pem
@@ -5,13 +5,6 @@ The DER can still be parsed, however it should fail due to the unconsumed data
at the end.
-
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
-mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
-I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQABBQA=
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 159 cons: SEQUENCE
3:d=1 hl=2 l= 13 cons: SEQUENCE
@@ -19,19 +12,19 @@ $ openssl asn1parse -i < [PUBLIC KEY]
16:d=2 hl=2 l= 0 prim: NULL
18:d=1 hl=3 l= 141 prim: BIT STRING
162:d=0 hl=2 l= 0 prim: NULL
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBBQUA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
+mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
+I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQABBQA=
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBBQUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
zch9oiPXht87ReC7vHITJtHuKvgGzDFUdcxvDZxm4bYjcdRc4jkuGskoRMMQEC8Vag2NUsH0xAu
@@ -40,13 +33,10 @@ vr538Gznjgj0CY+6QfnWGTwDF+i2DUtghKy0LSnjgIo7w3LYXjMRcPy/fMctC3HClmSLOk0Q9BY
pXQgHqmJcqydE/Z6o/SI8QlNwKYKL0WvgJUbxMP0uM7k20mduCK7RtzMYt1CgFn0A==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBAGvDoGZWhCkwokfjDVhktNgZI2unxollhirX28TiSvKOhrtTHwM1i+X7dHd8YIb4UMrviT8
Nb8wtDJHsATaTtOoAuAzUmqxOy1+JEa/lOa2kqPOCPR0T5HLRSQVHxlnHYX89JAh9228rcglhZ/
wJfKsY6aRY/LY0zc6O41iUxITX
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-key-params-absent.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-key-params-absent.pem
index 10cc3d06d9e..58d18cc5fba 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-key-params-absent.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-key-params-absent.pem
@@ -4,31 +4,24 @@ algorithm parameters are absent rather than NULL.
This should fail because RFC 3279 says the parameters MUST be NULL.
-
------BEGIN PUBLIC KEY-----
-MIGdMAsGCSqGSIb3DQEBAQOBjQAwgYkCgYEApW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h9
-62ZHYxRBW/+2xYrTA8oOhKoijlN/1JqtykcuzB86r/OCx39XNlQgJbVsri2311nHvY3fAkhyyPC
-cKcOJZjm/4nRnxBazC0/DLNfKSgOE4a29kxO8i4eHyDQzoz/siSb2aITcCAwEAAQ==
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 157 cons: SEQUENCE
3:d=1 hl=2 l= 11 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
16:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBBQUA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGdMAsGCSqGSIb3DQEBAQOBjQAwgYkCgYEApW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h9
+62ZHYxRBW/+2xYrTA8oOhKoijlN/1JqtykcuzB86r/OCx39XNlQgJbVsri2311nHvY3fAkhyyPC
+cKcOJZjm/4nRnxBazC0/DLNfKSgOE4a29kxO8i4eHyDQzoz/siSb2aITcCAwEAAQ==
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBBQUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
zch9oiPXht87ReC7vHITJtHuKvgGzDFUdcxvDZxm4bYjcdRc4jkuGskoRMMQEC8Vag2NUsH0xAu
@@ -37,13 +30,10 @@ vr538Gznjgj0CY+6QfnWGTwDF+i2DUtghKy0LSnjgIo7w3LYXjMRcPy/fMctC3HClmSLOk0Q9BY
pXQgHqmJcqydE/Z6o/SI8QlNwKYKL0WvgJUbxMP0uM7k20mduCK7RtzMYt1CgFn0A==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBAGvDoGZWhCkwokfjDVhktNgZI2unxollhirX28TiSvKOhrtTHwM1i+X7dHd8YIb4UMrviT8
Nb8wtDJHsATaTtOoAuAzUmqxOy1+JEa/lOa2kqPOCPR0T5HLRSQVHxlnHYX89JAh9228rcglhZ/
wJfKsY6aRY/LY0zc6O41iUxITX
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-using-pss-key-no-params.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-using-pss-key-no-params.pem
index 0dfff975caa..ae6e9cf0a05 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-using-pss-key-no-params.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-using-pss-key-no-params.pem
@@ -6,31 +6,24 @@ Subsequently this should fail, as a PSS key should not be used with a signature
algorithm for PKCS#1 v1.5.
-
------BEGIN PUBLIC KEY-----
-MIGdMAsGCSqGSIb3DQEBCgOBjQAwgYkCgYEApW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h9
-62ZHYxRBW/+2xYrTA8oOhKoijlN/1JqtykcuzB86r/OCx39XNlQgJbVsri2311nHvY3fAkhyyPC
-cKcOJZjm/4nRnxBazC0/DLNfKSgOE4a29kxO8i4eHyDQzoz/siSb2aITcCAwEAAQ==
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 157 cons: SEQUENCE
3:d=1 hl=2 l= 11 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsassaPss
16:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBBQUA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGdMAsGCSqGSIb3DQEBCgOBjQAwgYkCgYEApW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h9
+62ZHYxRBW/+2xYrTA8oOhKoijlN/1JqtykcuzB86r/OCx39XNlQgJbVsri2311nHvY3fAkhyyPC
+cKcOJZjm/4nRnxBazC0/DLNfKSgOE4a29kxO8i4eHyDQzoz/siSb2aITcCAwEAAQ==
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBBQUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
zch9oiPXht87ReC7vHITJtHuKvgGzDFUdcxvDZxm4bYjcdRc4jkuGskoRMMQEC8Vag2NUsH0xAu
@@ -39,13 +32,10 @@ vr538Gznjgj0CY+6QfnWGTwDF+i2DUtghKy0LSnjgIo7w3LYXjMRcPy/fMctC3HClmSLOk0Q9BY
pXQgHqmJcqydE/Z6o/SI8QlNwKYKL0WvgJUbxMP0uM7k20mduCK7RtzMYt1CgFn0A==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBAGvDoGZWhCkwokfjDVhktNgZI2unxollhirX28TiSvKOhrtTHwM1i+X7dHd8YIb4UMrviT8
Nb8wtDJHsATaTtOoAuAzUmqxOy1+JEa/lOa2kqPOCPR0T5HLRSQVHxlnHYX89JAh9228rcglhZ/
wJfKsY6aRY/LY0zc6O41iUxITX
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-wrong-algorithm.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-wrong-algorithm.pem
index 9aaedbabc58..5d848cfcc82 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-wrong-algorithm.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1-wrong-algorithm.pem
@@ -2,32 +2,25 @@ This is the same as rsa-pkcs1-sha1.pem, however the ALGORITHM has been change
to have SHA256 instead of SHA1. Using this algorithm verification should fail.
-
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
-mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
-I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 159 cons: SEQUENCE
3:d=1 hl=2 l= 13 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
16:d=2 hl=2 l= 0 prim: NULL
18:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBCwUA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
+mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
+I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBCwUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
zch9oiPXht87ReC7vHITJtHuKvgGzDFUdcxvDZxm4bYjcdRc4jkuGskoRMMQEC8Vag2NUsH0xAu
@@ -36,13 +29,10 @@ vr538Gznjgj0CY+6QfnWGTwDF+i2DUtghKy0LSnjgIo7w3LYXjMRcPy/fMctC3HClmSLOk0Q9BY
pXQgHqmJcqydE/Z6o/SI8QlNwKYKL0WvgJUbxMP0uM7k20mduCK7RtzMYt1CgFn0A==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBAGvDoGZWhCkwokfjDVhktNgZI2unxollhirX28TiSvKOhrtTHwM1i+X7dHd8YIb4UMrviT8
Nb8wtDJHsATaTtOoAuAzUmqxOy1+JEa/lOa2kqPOCPR0T5HLRSQVHxlnHYX89JAh9228rcglhZ/
wJfKsY6aRY/LY0zc6O41iUxITX
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1.pem
index 0972aca9a20..c696af789e3 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha1.pem
@@ -7,32 +7,25 @@ It uses an RSA key with modulus length of 1024 bits, PKCS#1 v1.5 padding, and
SHA-1 as the digest.
-
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
-mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
-I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 159 cons: SEQUENCE
3:d=1 hl=2 l= 13 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
16:d=2 hl=2 l= 0 prim: NULL
18:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBBQUA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
+mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
+I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBBQUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
zch9oiPXht87ReC7vHITJtHuKvgGzDFUdcxvDZxm4bYjcdRc4jkuGskoRMMQEC8Vag2NUsH0xAu
@@ -41,13 +34,10 @@ vr538Gznjgj0CY+6QfnWGTwDF+i2DUtghKy0LSnjgIo7w3LYXjMRcPy/fMctC3HClmSLOk0Q9BY
pXQgHqmJcqydE/Z6o/SI8QlNwKYKL0WvgJUbxMP0uM7k20mduCK7RtzMYt1CgFn0A==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBAGvDoGZWhCkwokfjDVhktNgZI2unxollhirX28TiSvKOhrtTHwM1i+X7dHd8YIb4UMrviT8
Nb8wtDJHsATaTtOoAuAzUmqxOy1+JEa/lOa2kqPOCPR0T5HLRSQVHxlnHYX89JAh9228rcglhZ/
wJfKsY6aRY/LY0zc6O41iUxITX
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-key-encoded-ber.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-key-encoded-ber.pem
index 2a8db4a6b6a..afc14a37c60 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-key-encoded-ber.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-key-encoded-ber.pem
@@ -11,32 +11,25 @@ To:
(the length of 0x9F is being expressed using 2 bytes instead of 1)
-
------BEGIN PUBLIC KEY-----
-MIIAnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqkfgdjI9YqzadSZ2Ns0CEEUD8+8m7OplIx0
-94X+QD8mooNrunwT04asbLIINGL4qiI/+9IVSvyV3Kj9c4EeQIbANGoJ8AI3wf6MOBB/txxGFed
-qqcTffKVMQvtZdoYFbZ/MQkvyRsoyvunb/pWcN4sSaF9kY1bXSeP3J99fBIYUCAwEAAQ==
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=4 l= 159 cons: SEQUENCE
4:d=1 hl=2 l= 13 cons: SEQUENCE
6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
17:d=2 hl=2 l= 0 prim: NULL
19:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBCwUA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIIAnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqkfgdjI9YqzadSZ2Ns0CEEUD8+8m7OplIx0
+94X+QD8mooNrunwT04asbLIINGL4qiI/+9IVSvyV3Kj9c4EeQIbANGoJ8AI3wf6MOBB/txxGFed
+qqcTffKVMQvtZdoYFbZ/MQkvyRsoyvunb/pWcN4sSaF9kY1bXSeP3J99fBIYUCAwEAAQ==
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBCwUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
MIIB46ADAgECAgkA3l4tFOVii0UwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCQVUxEzARBgN
@@ -50,13 +43,10 @@ cn318EhhQIDAQABo1AwTjAdBgNVHQ4EFgQUzQBVKTEknyLndWd2HTsBdTKvyikwHwYDVR0jBBgw
FoAUzQBVKTEknyLndWd2HTsBdTKvyikwDAYDVR0TBAUwAwEB/w==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBADrHSmFSJw/Gv7hs5PNzpaJwAri/sitarIZfzN/SjR+n8L8yeTEoiDb1+BkxlFvXvPHTaOK
oO3WlslNNOxh1W5/JkYYGOUkCcyIjnln6qS560imcr3VNjomT/M8M2Iss+rJiKau1TRuaP7H8i6
+Gqf3saGdr8/LnvFAdNQvkalQt
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-spki-non-null-params.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-spki-non-null-params.pem
index 4e7fc969019..daecea64d64 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-spki-non-null-params.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-spki-non-null-params.pem
@@ -8,32 +8,25 @@ To:
02 00 (INTEGER)
-
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQIAA4GNADCBiQKBgQCqR+B2Mj1irNp1JnY2zQIQRQPz7ybs6mUjHT3
-hf5APyaig2u6fBPThqxssgg0YviqIj/70hVK/JXcqP1zgR5AhsA0agnwAjfB/ow4EH+3HEYV52q
-pxN98pUxC+1l2hgVtn8xCS/JGyjK+6dv+lZw3ixJoX2RjVtdJ4/cn318EhhQIDAQAB
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 159 cons: SEQUENCE
3:d=1 hl=2 l= 13 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
16:d=2 hl=2 l= 0 prim: INTEGER :00
18:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBCwUA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQIAA4GNADCBiQKBgQCqR+B2Mj1irNp1JnY2zQIQRQPz7ybs6mUjHT3
+hf5APyaig2u6fBPThqxssgg0YviqIj/70hVK/JXcqP1zgR5AhsA0agnwAjfB/ow4EH+3HEYV52q
+pxN98pUxC+1l2hgVtn8xCS/JGyjK+6dv+lZw3ixJoX2RjVtdJ4/cn318EhhQIDAQAB
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBCwUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
MIIB46ADAgECAgkA3l4tFOVii0UwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCQVUxEzARBgN
@@ -47,13 +40,10 @@ cn318EhhQIDAQABo1AwTjAdBgNVHQ4EFgQUzQBVKTEknyLndWd2HTsBdTKvyikwHwYDVR0jBBgw
FoAUzQBVKTEknyLndWd2HTsBdTKvyikwDAYDVR0TBAUwAwEB/w==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBADrHSmFSJw/Gv7hs5PNzpaJwAri/sitarIZfzN/SjR+n8L8yeTEoiDb1+BkxlFvXvPHTaOK
oO3WlslNNOxh1W5/JkYYGOUkCcyIjnln6qS560imcr3VNjomT/M8M2Iss+rJiKau1TRuaP7H8i6
+Gqf3saGdr8/LnvFAdNQvkalQt
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-using-ecdsa-algorithm.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-using-ecdsa-algorithm.pem
index a9b9eb92baa..e5650999f7f 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-using-ecdsa-algorithm.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-using-ecdsa-algorithm.pem
@@ -5,31 +5,24 @@ The problem however is the signature algorithm is indicated as being ECDSA.
Signature verification consequently should fail.
-
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqR+B2Mj1irNp1JnY2zQIQRQPz7ybs6mUjHT3
-hf5APyaig2u6fBPThqxssgg0YviqIj/70hVK/JXcqP1zgR5AhsA0agnwAjfB/ow4EH+3HEYV52q
-pxN98pUxC+1l2hgVtn8xCS/JGyjK+6dv+lZw3ixJoX2RjVtdJ4/cn318EhhQIDAQAB
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 159 cons: SEQUENCE
3:d=1 hl=2 l= 13 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
16:d=2 hl=2 l= 0 prim: NULL
18:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MAoGCCqGSM49BAMC
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqR+B2Mj1irNp1JnY2zQIQRQPz7ybs6mUjHT3
+hf5APyaig2u6fBPThqxssgg0YviqIj/70hVK/JXcqP1zgR5AhsA0agnwAjfB/ow4EH+3HEYV52q
+pxN98pUxC+1l2hgVtn8xCS/JGyjK+6dv+lZw3ixJoX2RjVtdJ4/cn318EhhQIDAQAB
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 10 cons: SEQUENCE
2:d=1 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA256
-
-
+-----BEGIN ALGORITHM-----
+MAoGCCqGSM49BAMC
+-----END ALGORITHM-----
-----BEGIN DATA-----
MIIB46ADAgECAgkA3l4tFOVii0UwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCQVUxEzARBgN
@@ -43,13 +36,10 @@ cn318EhhQIDAQABo1AwTjAdBgNVHQ4EFgQUzQBVKTEknyLndWd2HTsBdTKvyikwHwYDVR0jBBgw
FoAUzQBVKTEknyLndWd2HTsBdTKvyikwDAYDVR0TBAUwAwEB/w==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBADrHSmFSJw/Gv7hs5PNzpaJwAri/sitarIZfzN/SjR+n8L8yeTEoiDb1+BkxlFvXvPHTaOK
oO3WlslNNOxh1W5/JkYYGOUkCcyIjnln6qS560imcr3VNjomT/M8M2Iss+rJiKau1TRuaP7H8i6
+Gqf3saGdr8/LnvFAdNQvkalQt
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-using-id-ea-rsa.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-using-id-ea-rsa.pem
index dd5d39cb2b2..f5b223915cc 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-using-id-ea-rsa.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256-using-id-ea-rsa.pem
@@ -3,32 +3,25 @@ with. Rather than using an rsaEncryption OID for the key's algorithm, it uses
id-ea-rsa (2.5.8.1.1).
-
------BEGIN PUBLIC KEY-----
-MIGaMAgGBFUIAQEFAAOBjQAwgYkCgYEAqkfgdjI9YqzadSZ2Ns0CEEUD8+8m7OplIx094X+QD8m
-ooNrunwT04asbLIINGL4qiI/+9IVSvyV3Kj9c4EeQIbANGoJ8AI3wf6MOBB/txxGFedqqcTffKV
-MQvtZdoYFbZ/MQkvyRsoyvunb/pWcN4sSaF9kY1bXSeP3J99fBIYUCAwEAAQ==
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 154 cons: SEQUENCE
3:d=1 hl=2 l= 8 cons: SEQUENCE
5:d=2 hl=2 l= 4 prim: OBJECT :rsa
11:d=2 hl=2 l= 0 prim: NULL
13:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBCwUA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGaMAgGBFUIAQEFAAOBjQAwgYkCgYEAqkfgdjI9YqzadSZ2Ns0CEEUD8+8m7OplIx094X+QD8m
+ooNrunwT04asbLIINGL4qiI/+9IVSvyV3Kj9c4EeQIbANGoJ8AI3wf6MOBB/txxGFedqqcTffKV
+MQvtZdoYFbZ/MQkvyRsoyvunb/pWcN4sSaF9kY1bXSeP3J99fBIYUCAwEAAQ==
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBCwUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
MIIB46ADAgECAgkA3l4tFOVii0UwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCQVUxEzARBgN
@@ -42,13 +35,10 @@ cn318EhhQIDAQABo1AwTjAdBgNVHQ4EFgQUzQBVKTEknyLndWd2HTsBdTKvyikwHwYDVR0jBBgw
FoAUzQBVKTEknyLndWd2HTsBdTKvyikwDAYDVR0TBAUwAwEB/w==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBADrHSmFSJw/Gv7hs5PNzpaJwAri/sitarIZfzN/SjR+n8L8yeTEoiDb1+BkxlFvXvPHTaOK
oO3WlslNNOxh1W5/JkYYGOUkCcyIjnln6qS560imcr3VNjomT/M8M2Iss+rJiKau1TRuaP7H8i6
+Gqf3saGdr8/LnvFAdNQvkalQt
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256.pem
index 8509111ea9b..0fda8c22c33 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pkcs1-sha256.pem
@@ -35,32 +35,25 @@ It uses RSA PKCS#1 v1.5 with SHA-256 and a 1024-bit key.
base64 sig
-
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqR+B2Mj1irNp1JnY2zQIQRQPz7ybs6mUjHT3
-hf5APyaig2u6fBPThqxssgg0YviqIj/70hVK/JXcqP1zgR5AhsA0agnwAjfB/ow4EH+3HEYV52q
-pxN98pUxC+1l2hgVtn8xCS/JGyjK+6dv+lZw3ixJoX2RjVtdJ4/cn318EhhQIDAQAB
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 159 cons: SEQUENCE
3:d=1 hl=2 l= 13 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
16:d=2 hl=2 l= 0 prim: NULL
18:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBCwUA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqR+B2Mj1irNp1JnY2zQIQRQPz7ybs6mUjHT3
+hf5APyaig2u6fBPThqxssgg0YviqIj/70hVK/JXcqP1zgR5AhsA0agnwAjfB/ow4EH+3HEYV52q
+pxN98pUxC+1l2hgVtn8xCS/JGyjK+6dv+lZw3ixJoX2RjVtdJ4/cn318EhhQIDAQAB
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBCwUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
MIIB46ADAgECAgkA3l4tFOVii0UwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCQVUxEzARBgN
@@ -74,13 +67,10 @@ cn318EhhQIDAQABo1AwTjAdBgNVHQ4EFgQUzQBVKTEknyLndWd2HTsBdTKvyikwHwYDVR0jBBgw
FoAUzQBVKTEknyLndWd2HTsBdTKvyikwDAYDVR0TBAUwAwEB/w==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBADrHSmFSJw/Gv7hs5PNzpaJwAri/sitarIZfzN/SjR+n8L8yeTEoiDb1+BkxlFvXvPHTaOK
oO3WlslNNOxh1W5/JkYYGOUkCcyIjnln6qS560imcr3VNjomT/M8M2Iss+rJiKau1TRuaP7H8i6
+Gqf3saGdr8/LnvFAdNQvkalQt
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20-using-pss-key-no-params.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20-using-pss-key-no-params.pem
index 503cc2ed767..74adc3eb0b9 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20-using-pss-key-no-params.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20-using-pss-key-no-params.pem
@@ -3,31 +3,24 @@ algorithm identifier has been changed from rsaEncryption (1.2.840.113549.1.1.1)
to rsaPss (1.2.840.113549.1.1.10).
-
------BEGIN PUBLIC KEY-----
-MIGdMAsGCSqGSIb3DQEBCgOBjQAwgYkCgYEApW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h9
-62ZHYxRBW/+2xYrTA8oOhKoijlN/1JqtykcuzB86r/OCx39XNlQgJbVsri2311nHvY3fAkhyyPC
-cKcOJZjm/4nRnxBazC0/DLNfKSgOE4a29kxO8i4eHyDQzoz/siSb2aITcCAwEAAQ==
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 157 cons: SEQUENCE
3:d=1 hl=2 l= 11 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsassaPss
16:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBCjAA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGdMAsGCSqGSIb3DQEBCgOBjQAwgYkCgYEApW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h9
+62ZHYxRBW/+2xYrTA8oOhKoijlN/1JqtykcuzB86r/OCx39XNlQgJbVsri2311nHvY3fAkhyyPC
+cKcOJZjm/4nRnxBazC0/DLNfKSgOE4a29kxO8i4eHyDQzoz/siSb2aITcCAwEAAQ==
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :rsassaPss
13:d=1 hl=2 l= 0 cons: SEQUENCE
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBCjAA
+-----END ALGORITHM-----
-----BEGIN DATA-----
zch9oiPXht87ReC7vHITJtHuKvgGzDFUdcxvDZxm4bYjcdRc4jkuGskoRMMQEC8Vag2NUsH0xAu
@@ -36,13 +29,10 @@ vr538Gznjgj0CY+6QfnWGTwDF+i2DUtghKy0LSnjgIo7w3LYXjMRcPy/fMctC3HClmSLOk0Q9BY
pXQgHqmJcqydE/Z6o/SI8QlNwKYKL0WvgJUbxMP0uM7k20mduCK7RtzMYt1CgFn0A==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBAJB0MI+1mOlwGyKUOI5S+XH6rCtgpRRa8YXfUoe17SiH5Xzn/UTchjTkB8jg5DYLwibz7CJ
/nZ5UY46NMfUFEhXfbrucL5V5qndZijj5FLW5wb2DxOL584Kg0Ko1Qv/uZZhKYBvGnrKN6yfcoS
yCwtTD9mzVAPH/K5lNik4wy7M8
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20-using-pss-key-with-null-params.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20-using-pss-key-with-null-params.pem
index 222614bc037..42e9546af08 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20-using-pss-key-with-null-params.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20-using-pss-key-with-null-params.pem
@@ -4,32 +4,25 @@ to rsaPss (1.2.840.113549.1.1.10). Note that the PSS parameters have been
encoded as NULL which is incorrect.
-
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBCgUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
-mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
-I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 159 cons: SEQUENCE
3:d=1 hl=2 l= 13 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsassaPss
16:d=2 hl=2 l= 0 prim: NULL
18:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBCjAA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBCgUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
+mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
+I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :rsassaPss
13:d=1 hl=2 l= 0 cons: SEQUENCE
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBCjAA
+-----END ALGORITHM-----
-----BEGIN DATA-----
zch9oiPXht87ReC7vHITJtHuKvgGzDFUdcxvDZxm4bYjcdRc4jkuGskoRMMQEC8Vag2NUsH0xAu
@@ -38,13 +31,10 @@ vr538Gznjgj0CY+6QfnWGTwDF+i2DUtghKy0LSnjgIo7w3LYXjMRcPy/fMctC3HClmSLOk0Q9BY
pXQgHqmJcqydE/Z6o/SI8QlNwKYKL0WvgJUbxMP0uM7k20mduCK7RtzMYt1CgFn0A==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBAJB0MI+1mOlwGyKUOI5S+XH6rCtgpRRa8YXfUoe17SiH5Xzn/UTchjTkB8jg5DYLwibz7CJ
/nZ5UY46NMfUFEhXfbrucL5V5qndZijj5FLW5wb2DxOL584Kg0Ko1Qv/uZZhKYBvGnrKN6yfcoS
yCwtTD9mzVAPH/K5lNik4wy7M8
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20.pem
index e56f0fe0cd4..4f7a81cac87 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-salt20.pem
@@ -7,32 +7,25 @@ It uses an RSA key with modulus length of 1024 bits, PSS padding,
SHA-1 as the digest, MGF1 with SHA-1, and salt length of 20.
-
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
-mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
-I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 159 cons: SEQUENCE
3:d=1 hl=2 l= 13 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
16:d=2 hl=2 l= 0 prim: NULL
18:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBCjAA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
+mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
+I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :rsassaPss
13:d=1 hl=2 l= 0 cons: SEQUENCE
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBCjAA
+-----END ALGORITHM-----
-----BEGIN DATA-----
zch9oiPXht87ReC7vHITJtHuKvgGzDFUdcxvDZxm4bYjcdRc4jkuGskoRMMQEC8Vag2NUsH0xAu
@@ -41,13 +34,10 @@ vr538Gznjgj0CY+6QfnWGTwDF+i2DUtghKy0LSnjgIo7w3LYXjMRcPy/fMctC3HClmSLOk0Q9BY
pXQgHqmJcqydE/Z6o/SI8QlNwKYKL0WvgJUbxMP0uM7k20mduCK7RtzMYt1CgFn0A==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBAJB0MI+1mOlwGyKUOI5S+XH6rCtgpRRa8YXfUoe17SiH5Xzn/UTchjTkB8jg5DYLwibz7CJ
/nZ5UY46NMfUFEhXfbrucL5V5qndZijj5FLW5wb2DxOL584Kg0Ko1Qv/uZZhKYBvGnrKN6yfcoS
yCwtTD9mzVAPH/K5lNik4wy7M8
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-wrong-salt.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-wrong-salt.pem
index 57ec775f6e5..ffa9d52475c 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-wrong-salt.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha1-wrong-salt.pem
@@ -3,25 +3,17 @@ have a salt of 23. When verified using this algorithm it will fail, however if
the default salt of 20 were used it would succeed.
-
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
-mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
-I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 159 cons: SEQUENCE
3:d=1 hl=2 l= 13 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
16:d=2 hl=2 l= 0 prim: NULL
18:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MBIGCSqGSIb3DQEBCjAFogMCARc=
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
+mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
+I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 18 cons: SEQUENCE
@@ -29,8 +21,9 @@ $ openssl asn1parse -i < [ALGORITHM]
13:d=1 hl=2 l= 5 cons: SEQUENCE
15:d=2 hl=2 l= 3 cons: cont [ 2 ]
17:d=3 hl=2 l= 1 prim: INTEGER :17
-
-
+-----BEGIN ALGORITHM-----
+MBIGCSqGSIb3DQEBCjAFogMCARc=
+-----END ALGORITHM-----
-----BEGIN DATA-----
zch9oiPXht87ReC7vHITJtHuKvgGzDFUdcxvDZxm4bYjcdRc4jkuGskoRMMQEC8Vag2NUsH0xAu
@@ -39,13 +32,10 @@ vr538Gznjgj0CY+6QfnWGTwDF+i2DUtghKy0LSnjgIo7w3LYXjMRcPy/fMctC3HClmSLOk0Q9BY
pXQgHqmJcqydE/Z6o/SI8QlNwKYKL0WvgJUbxMP0uM7k20mduCK7RtzMYt1CgFn0A==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBAJB0MI+1mOlwGyKUOI5S+XH6rCtgpRRa8YXfUoe17SiH5Xzn/UTchjTkB8jg5DYLwibz7CJ
/nZ5UY46NMfUFEhXfbrucL5V5qndZijj5FLW5wb2DxOL584Kg0Ko1Qv/uZZhKYBvGnrKN6yfcoS
yCwtTD9mzVAPH/K5lNik4wy7M8
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-mgf1-sha512-salt33.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-mgf1-sha512-salt33.pem
index f3b9dcb6fe6..b322226dceb 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-mgf1-sha512-salt33.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-mgf1-sha512-salt33.pem
@@ -11,26 +11,17 @@ It constructs an RSASSA-PSS signature using:
* Mask gen function of MGF1 with SHA-512
-
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
-mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
-I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 159 cons: SEQUENCE
3:d=1 hl=2 l= 13 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
16:d=2 hl=2 l= 0 prim: NULL
18:d=1 hl=3 l= 141 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWU
-DBAIDBQCiAwIBIQ==
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLsDjatUqRN/rH
+mH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2VCAltWyuLbfXWce9jd8CSHL
+I8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh4fINDOjP+yJJvZohNwIDAQAB
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 65 cons: SEQUENCE
@@ -48,20 +39,19 @@ $ openssl asn1parse -i < [ALGORITHM]
60:d=5 hl=2 l= 0 prim: NULL
62:d=2 hl=2 l= 3 cons: cont [ 2 ]
64:d=3 hl=2 l= 1 prim: INTEGER :21
-
-
+-----BEGIN ALGORITHM-----
+MEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWU
+DBAIDBQCiAwIBIQ==
+-----END ALGORITHM-----
-----BEGIN DATA-----
VGVzdCBtZXNzYWdlIHRvIGJlIHNpZ25lZC4uLg==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBAFob0HSC5uuTqKu4J/lj+5bDa+Hhij4H3klWnvt6Yc+wwPza7/UC4lgGGyvZqD32RUEdt7v
Z14qqYNk53b5aj4C2gBMvLzV7Pay4mmQM4DSWa5JHMxTILqE3DDqihrbMcBw2q3XAsLcjeqLWQ9
yp8tfnV21h98qsCLtErrxZWHRr
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10-using-pss-key-with-params.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10-using-pss-key-with-params.pem
index e0140b34c48..62da07a2b52 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10-using-pss-key-with-params.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10-using-pss-key-with-params.pem
@@ -3,14 +3,6 @@ the SPKI using rsaEncryption it is specified using rsaPss along with
parameters that match those of the signature algorithm.
-
------BEGIN PUBLIC KEY-----
-MIHRMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZ
-IAWUDBAIBBQCiAwIBCgOBiwAwgYcCgYEAvkmbXn8GyD+gKT4xRlyOtrWK+SC65Sp7W5v+t6py2x
-JkES6z/UMdMaKn5QlBVmkpSUoOiR7VYTkYtLUbDR+5d4Oyas99DzhM+zX00oJPXdOAYjomvxgLY
-5YcYZ3NsgyuQG8i9uJ2yAo3JZSQz+tywacahPGEbTMId7o+MQHsnHsCARE=
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 209 cons: SEQUENCE
3:d=1 hl=2 l= 65 cons: SEQUENCE
@@ -29,13 +21,12 @@ $ openssl asn1parse -i < [PUBLIC KEY]
65:d=3 hl=2 l= 3 cons: cont [ 2 ]
67:d=4 hl=2 l= 1 prim: INTEGER :0A
70:d=1 hl=3 l= 139 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWU
-DBAIBBQCiAwIBCg==
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIHRMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZ
+IAWUDBAIBBQCiAwIBCgOBiwAwgYcCgYEAvkmbXn8GyD+gKT4xRlyOtrWK+SC65Sp7W5v+t6py2x
+JkES6z/UMdMaKn5QlBVmkpSUoOiR7VYTkYtLUbDR+5d4Oyas99DzhM+zX00oJPXdOAYjomvxgLY
+5YcYZ3NsgyuQG8i9uJ2yAo3JZSQz+tywacahPGEbTMId7o+MQHsnHsCARE=
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 65 cons: SEQUENCE
@@ -53,8 +44,10 @@ $ openssl asn1parse -i < [ALGORITHM]
60:d=5 hl=2 l= 0 prim: NULL
62:d=2 hl=2 l= 3 cons: cont [ 2 ]
64:d=3 hl=2 l= 1 prim: INTEGER :0A
-
-
+-----BEGIN ALGORITHM-----
+MEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWU
+DBAIBBQCiAwIBCg==
+-----END ALGORITHM-----
-----BEGIN DATA-----
x/UnD8pyX5vRn1GajXzKPMXAeQJAKfO65RD5sCFA/iOJCOT2wY8HqJxofIaEZpsfHbK6+SUaPIK
@@ -62,13 +55,10 @@ frMtJMIThbsnijViGgHSl1iIWZ91uUo0W/iyfPbTPr2xNzoyEOa84zqqqnOLsrnvI9KWlXjv5bf
nNV1xPnLMnlRuM3+QIcWg=
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBABHhafL9QLB2Qbl2iiqxmWX7bCfxD88DI/zG0S608cBrMw3aoepQRAevop3p6+A3T+nR59D
/vV/Bzzo0RuQUVBXSqyT3ibNGTFxDola7wdaSz38EgB2sW7QBpKA6t9VyioYMGeGk3Hl8pULIID
zsLmAesMUfVn8u2gIrC5693u76
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10-using-pss-key-with-wrong-params.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10-using-pss-key-with-wrong-params.pem
index 646ac1fbe9a..9b2b67950de 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10-using-pss-key-with-wrong-params.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10-using-pss-key-with-wrong-params.pem
@@ -3,14 +3,6 @@ except the hash in the PSS key's parameters has been changed from SHA-256 to
SHA-384.
-
------BEGIN PUBLIC KEY-----
-MIHRMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZ
-IAWUDBAIBBQCiAwIBCgOBiwAwgYcCgYEAvkmbXn8GyD+gKT4xRlyOtrWK+SC65Sp7W5v+t6py2x
-JkES6z/UMdMaKn5QlBVmkpSUoOiR7VYTkYtLUbDR+5d4Oyas99DzhM+zX00oJPXdOAYjomvxgLY
-5YcYZ3NsgyuQG8i9uJ2yAo3JZSQz+tywacahPGEbTMId7o+MQHsnHsCARE=
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 209 cons: SEQUENCE
3:d=1 hl=2 l= 65 cons: SEQUENCE
@@ -29,13 +21,12 @@ $ openssl asn1parse -i < [PUBLIC KEY]
65:d=3 hl=2 l= 3 cons: cont [ 2 ]
67:d=4 hl=2 l= 1 prim: INTEGER :0A
70:d=1 hl=3 l= 139 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWU
-DBAIBBQCiAwIBCg==
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIHRMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZ
+IAWUDBAIBBQCiAwIBCgOBiwAwgYcCgYEAvkmbXn8GyD+gKT4xRlyOtrWK+SC65Sp7W5v+t6py2x
+JkES6z/UMdMaKn5QlBVmkpSUoOiR7VYTkYtLUbDR+5d4Oyas99DzhM+zX00oJPXdOAYjomvxgLY
+5YcYZ3NsgyuQG8i9uJ2yAo3JZSQz+tywacahPGEbTMId7o+MQHsnHsCARE=
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 65 cons: SEQUENCE
@@ -53,8 +44,10 @@ $ openssl asn1parse -i < [ALGORITHM]
60:d=5 hl=2 l= 0 prim: NULL
62:d=2 hl=2 l= 3 cons: cont [ 2 ]
64:d=3 hl=2 l= 1 prim: INTEGER :0A
-
-
+-----BEGIN ALGORITHM-----
+MEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWU
+DBAIBBQCiAwIBCg==
+-----END ALGORITHM-----
-----BEGIN DATA-----
x/UnD8pyX5vRn1GajXzKPMXAeQJAKfO65RD5sCFA/iOJCOT2wY8HqJxofIaEZpsfHbK6+SUaPIK
@@ -62,13 +55,10 @@ frMtJMIThbsnijViGgHSl1iIWZ91uUo0W/iyfPbTPr2xNzoyEOa84zqqqnOLsrnvI9KWlXjv5bf
nNV1xPnLMnlRuM3+QIcWg=
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBABHhafL9QLB2Qbl2iiqxmWX7bCfxD88DI/zG0S608cBrMw3aoepQRAevop3p6+A3T+nR59D
/vV/Bzzo0RuQUVBXSqyT3ibNGTFxDola7wdaSz38EgB2sW7QBpKA6t9VyioYMGeGk3Hl8pULIID
zsLmAesMUfVn8u2gIrC5693u76
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10.pem b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10.pem
index fc37f41d1fe..72d729a0872 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-pss-sha256-salt10.pem
@@ -7,26 +7,17 @@ It uses an RSA key with modulus length of 1024 bits, PSS padding,
SHA-256 as the digest, MGF1 with SHA-256, and salt length of 10.
-
------BEGIN PUBLIC KEY-----
-MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC+SZtefwbIP6ApPjFGXI62tYr5ILrlKntbm/6
-3qnLbEmQRLrP9Qx0xoqflCUFWaSlJSg6JHtVhORi0tRsNH7l3g7Jqz30POEz7NfTSgk9d04BiOi
-a/GAtjlhxhnc2yDK5AbyL24nbICjcllJDP63LBpxqE8YRtMwh3uj4xAeycewIBEQ==
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=3 l= 157 cons: SEQUENCE
3:d=1 hl=2 l= 13 cons: SEQUENCE
5:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
16:d=2 hl=2 l= 0 prim: NULL
18:d=1 hl=3 l= 139 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWU
-DBAIBBQCiAwIBCg==
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC+SZtefwbIP6ApPjFGXI62tYr5ILrlKntbm/6
+3qnLbEmQRLrP9Qx0xoqflCUFWaSlJSg6JHtVhORi0tRsNH7l3g7Jqz30POEz7NfTSgk9d04BiOi
+a/GAtjlhxhnc2yDK5AbyL24nbICjcllJDP63LBpxqE8YRtMwh3uj4xAeycewIBEQ==
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 65 cons: SEQUENCE
@@ -44,8 +35,10 @@ $ openssl asn1parse -i < [ALGORITHM]
60:d=5 hl=2 l= 0 prim: NULL
62:d=2 hl=2 l= 3 cons: cont [ 2 ]
64:d=3 hl=2 l= 1 prim: INTEGER :0A
-
-
+-----BEGIN ALGORITHM-----
+MEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWU
+DBAIBBQCiAwIBCg==
+-----END ALGORITHM-----
-----BEGIN DATA-----
x/UnD8pyX5vRn1GajXzKPMXAeQJAKfO65RD5sCFA/iOJCOT2wY8HqJxofIaEZpsfHbK6+SUaPIK
@@ -53,13 +46,10 @@ frMtJMIThbsnijViGgHSl1iIWZ91uUo0W/iyfPbTPr2xNzoyEOa84zqqqnOLsrnvI9KWlXjv5bf
nNV1xPnLMnlRuM3+QIcWg=
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBABHhafL9QLB2Qbl2iiqxmWX7bCfxD88DI/zG0S608cBrMw3aoepQRAevop3p6+A3T+nR59D
/vV/Bzzo0RuQUVBXSqyT3ibNGTFxDola7wdaSz38EgB2sW7QBpKA6t9VyioYMGeGk3Hl8pULIID
zsLmAesMUfVn8u2gIrC5693u76
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa-using-ec-key.pem b/chromium/net/data/verify_signed_data_unittest/rsa-using-ec-key.pem
index b9a3777f171..b39b0be7781 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa-using-ec-key.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa-using-ec-key.pem
@@ -2,31 +2,24 @@ This test specifies an RSA PKCS#1 v1.5 signature algorithm (and a valid RSA
signature), HOWEVER it provides an EC key. Verification should fail.
-
------BEGIN PUBLIC KEY-----
-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnLDPaTA9r8dh1ORoe07PA55tNKuWSvgIENjVWKS
-o1vctUSM6F4iSCobuCKGWLHnvoxf7eHnil9rSFG25lfoceA==
------END PUBLIC KEY-----
-
$ openssl asn1parse -i < [PUBLIC KEY]
0:d=0 hl=2 l= 89 cons: SEQUENCE
2:d=1 hl=2 l= 19 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
23:d=1 hl=2 l= 66 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBCwUA
------END ALGORITHM-----
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnLDPaTA9r8dh1ORoe07PA55tNKuWSvgIENjVWKS
+o1vctUSM6F4iSCobuCKGWLHnvoxf7eHnil9rSFG25lfoceA==
+-----END PUBLIC KEY-----
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBCwUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
MIIB46ADAgECAgkA3l4tFOVii0UwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCQVUxEzARBgN
@@ -40,13 +33,10 @@ cn318EhhQIDAQABo1AwTjAdBgNVHQ4EFgQUzQBVKTEknyLndWd2HTsBdTKvyikwHwYDVR0jBBgw
FoAUzQBVKTEknyLndWd2HTsBdTKvyikwDAYDVR0TBAUwAwEB/w==
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=3 l= 129 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4GBADrHSmFSJw/Gv7hs5PNzpaJwAri/sitarIZfzN/SjR+n8L8yeTEoiDb1+BkxlFvXvPHTaOK
oO3WlslNNOxh1W5/JkYYGOUkCcyIjnln6qS560imcr3VNjomT/M8M2Iss+rJiKau1TRuaP7H8i6
+Gqf3saGdr8/LnvFAdNQvkalQt
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=3 l= 129 prim: BIT STRING
diff --git a/chromium/net/data/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem b/chromium/net/data/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem
index 342a31b85ea..4ebb23a086c 100644
--- a/chromium/net/data/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem
+++ b/chromium/net/data/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem
@@ -35,7 +35,12 @@ It uses RSA PKCS#1 v1.5 with SHA-512 and a 2048-bit key.
base64 sig
-
+$ openssl asn1parse -i < [PUBLIC KEY]
+ 0:d=0 hl=4 l= 290 cons: SEQUENCE
+ 4:d=1 hl=2 l= 13 cons: SEQUENCE
+ 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
+ 17:d=2 hl=2 l= 0 prim: NULL
+ 19:d=1 hl=4 l= 271 prim: BIT STRING
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzcu2shJRrXFAwMkf30y2AY1zIg9VF/h
egYcejzdR2AzUb8vU2TXld2i8pp44l+DrvtqmzS7G+yxx3uOx+zsoqBaUT0c9HfkbE+IRmcLkQF
@@ -45,25 +50,13 @@ ueMVPuNncqbT4nAMKz25J1CtRlQh21uZzfY2QRP3m6rAZquQUos1febC6A7qmhQljWKKmXtfVY+
fAamstdHrWwIDAQAB
-----END PUBLIC KEY-----
-$ openssl asn1parse -i < [PUBLIC KEY]
- 0:d=0 hl=4 l= 290 cons: SEQUENCE
- 4:d=1 hl=2 l= 13 cons: SEQUENCE
- 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
- 17:d=2 hl=2 l= 0 prim: NULL
- 19:d=1 hl=4 l= 271 prim: BIT STRING
-
-
-
------BEGIN ALGORITHM-----
-MA0GCSqGSIb3DQEBDQUA
------END ALGORITHM-----
-
$ openssl asn1parse -i < [ALGORITHM]
0:d=0 hl=2 l= 13 cons: SEQUENCE
2:d=1 hl=2 l= 9 prim: OBJECT :sha512WithRSAEncryption
13:d=1 hl=2 l= 0 prim: NULL
-
-
+-----BEGIN ALGORITHM-----
+MA0GCSqGSIb3DQEBDQUA
+-----END ALGORITHM-----
-----BEGIN DATA-----
MIICRaADAgECAgkA7jWRLkwHvHswDQYJKoZIhvcNAQENBQAwRTELMAkGA1UEBhMCQVUxEzARBgN
@@ -79,8 +72,8 @@ OMB0GA1UdDgQWBBRsCPajkEscZM6SpLbNTa/7dY5azzAfBgNVHSMEGDAWgBRsCPajkEscZM6SpL
bNTa/7dY5azzAMBgNVHRMEBTADAQH/
-----END DATA-----
-
-
+$ openssl asn1parse -i < [SIGNATURE]
+ 0:d=0 hl=4 l= 257 prim: BIT STRING
-----BEGIN SIGNATURE-----
A4IBAQAhKSNq+X/CfzhtNsMo6MJpTBjJBV5fhHerIZr6e3ozCTBCR29vYsVnJ4/6i5lL1pNeOhM
ldthnuSlMzTS1Zme1OqRWB3U8QmwCFwhDxW/i4fdT8kxDAmELNp4z0GcXbe27V895PE0R/m8P47
@@ -88,6 +81,3 @@ B6xbra+SQlEMW12K1EndUqrO6vgLbobV14mveWdgc0KIOnDKgsTHV8NTV1w3qtp1ujfvizYfBZu
yyMOA1yZPDpREZtClro7lufwDQ7+LgSdtNLMDAMzapfIjAEPVNVLmJzMgzaHqMsZM8gP8vWAdfc
R4mCmWXVotrM6d1rjJGdRADAONYCC4/+d1IMkVGoVfpaej6I
-----END SIGNATURE-----
-
-$ openssl asn1parse -i < [SIGNATURE]
- 0:d=0 hl=4 l= 257 prim: BIT STRING
diff --git a/chromium/net/der/input.cc b/chromium/net/der/input.cc
index 871f9f4ec7d..49955905fa2 100644
--- a/chromium/net/der/input.cc
+++ b/chromium/net/der/input.cc
@@ -24,12 +24,6 @@ Input::Input(const base::StringPiece& in)
Input::Input(const std::string* s) : Input(base::StringPiece(*s)) {}
-bool Input::Equals(const Input& other) const {
- if (len_ != other.len_)
- return false;
- return memcmp(data_, other.data_, len_) == 0;
-}
-
std::string Input::AsString() const {
return std::string(reinterpret_cast<const char*>(data_), len_);
}
@@ -38,6 +32,16 @@ base::StringPiece Input::AsStringPiece() const {
return base::StringPiece(reinterpret_cast<const char*>(data_), len_);
}
+bool operator==(const Input& lhs, const Input& rhs) {
+ if (lhs.Length() != rhs.Length())
+ return false;
+ return memcmp(lhs.UnsafeData(), rhs.UnsafeData(), lhs.Length()) == 0;
+}
+
+bool operator!=(const Input& lhs, const Input& rhs) {
+ return !(lhs == rhs);
+}
+
bool operator<(const Input& lhs, const Input& rhs) {
return std::lexicographical_compare(
lhs.UnsafeData(), lhs.UnsafeData() + lhs.Length(), rhs.UnsafeData(),
diff --git a/chromium/net/der/input.h b/chromium/net/der/input.h
index 9c3f5ca87a4..121a9e0770a 100644
--- a/chromium/net/der/input.h
+++ b/chromium/net/der/input.h
@@ -63,9 +63,6 @@ class NET_EXPORT_PRIVATE Input {
// Returns the length in bytes of an Input's data.
size_t Length() const { return len_; }
- // Return true if the Input's data and |other|'s data are byte-wise equal.
- bool Equals(const Input& other) const;
-
// Returns a pointer to the Input's data. This method is marked as "unsafe"
// because access to the Input's data should be done through ByteReader
// instead. This method should only be used where using a ByteReader truly
@@ -91,6 +88,12 @@ class NET_EXPORT_PRIVATE Input {
size_t len_;
};
+// Return true if |lhs|'s data and |rhs|'s data are byte-wise equal.
+NET_EXPORT_PRIVATE bool operator==(const Input& lhs, const Input& rhs);
+
+// Return true if |lhs|'s data and |rhs|'s data are not byte-wise equal.
+NET_EXPORT_PRIVATE bool operator!=(const Input& lhs, const Input& rhs);
+
// Returns true if |lhs|'s data is lexicographically less than |rhs|'s data.
NET_EXPORT_PRIVATE bool operator<(const Input& lhs, const Input& rhs);
diff --git a/chromium/net/der/input_unittest.cc b/chromium/net/der/input_unittest.cc
index e7193b08b52..6fcb436606f 100644
--- a/chromium/net/der/input_unittest.cc
+++ b/chromium/net/der/input_unittest.cc
@@ -16,16 +16,16 @@ const uint8_t kInput2[] = {'t', 'e', 'a', 'l'};
TEST(InputTest, Equals) {
Input test(kInput);
Input test2(kInput);
- EXPECT_TRUE(test.Equals(test2));
+ EXPECT_EQ(test, test2);
uint8_t input_copy[arraysize(kInput)] = {0};
memcpy(input_copy, kInput, arraysize(kInput));
Input test_copy(input_copy);
- EXPECT_TRUE(test.Equals(test_copy));
+ EXPECT_EQ(test, test_copy);
Input test_truncated(kInput, arraysize(kInput) - 1);
- EXPECT_FALSE(test.Equals(test_truncated));
- EXPECT_FALSE(test_truncated.Equals(test));
+ EXPECT_NE(test, test_truncated);
+ EXPECT_NE(test_truncated, test);
}
TEST(InputTest, LessThan) {
@@ -53,7 +53,7 @@ TEST(InputTest, StaticArray) {
EXPECT_EQ(arraysize(kInput), input.Length());
Input input2(kInput);
- EXPECT_TRUE(input.Equals(input2));
+ EXPECT_EQ(input, input2);
}
TEST(ByteReaderTest, NoReadPastEnd) {
diff --git a/chromium/net/der/parser.cc b/chromium/net/der/parser.cc
index 6419549cf04..0cb2600f5e6 100644
--- a/chromium/net/der/parser.cc
+++ b/chromium/net/der/parser.cc
@@ -179,6 +179,13 @@ bool Parser::ReadSequence(Parser* out) {
return ReadConstructed(kSequence, out);
}
+bool Parser::ReadUint8(uint8_t* out) {
+ Input encoded_int;
+ if (!ReadTag(kInteger, &encoded_int))
+ return false;
+ return ParseUint8(encoded_int, out);
+}
+
bool Parser::ReadUint64(uint64_t* out) {
Input encoded_int;
if (!ReadTag(kInteger, &encoded_int))
@@ -193,6 +200,13 @@ bool Parser::ReadBitString(BitString* bit_string) {
return ParseBitString(value, bit_string);
}
+bool Parser::ReadGeneralizedTime(GeneralizedTime* out) {
+ Input value;
+ if (!ReadTag(kGeneralizedTime, &value))
+ return false;
+ return ParseGeneralizedTime(value, out);
+}
+
} // namespace der
} // namespace net
diff --git a/chromium/net/der/parser.h b/chromium/net/der/parser.h
index 2192371d6c6..d18728e1858 100644
--- a/chromium/net/der/parser.h
+++ b/chromium/net/der/parser.h
@@ -19,6 +19,7 @@ namespace net {
namespace der {
class BitString;
+struct GeneralizedTime;
// Parses a DER-encoded ASN.1 structure. DER (distinguished encoding rules)
// encodes each data value with a tag, length, and value (TLV). The tag
@@ -146,10 +147,19 @@ class NET_EXPORT Parser {
// to be 0x30 (SEQUENCE).
bool ReadSequence(Parser* out) WARN_UNUSED_RESULT;
+ // Expects the current tag to be kInteger, and calls ParseUint8 on the
+ // current value. Note that DER-encoded integers are arbitrary precision,
+ // so this method will fail for valid input that represents an integer
+ // outside the range of an uint8_t.
+ //
+ // Note that on failure the Parser is left in an undefined state (the
+ // input may or may not have been advanced).
+ bool ReadUint8(uint8_t* out) WARN_UNUSED_RESULT;
+
// Expects the current tag to be kInteger, and calls ParseUint64 on the
// current value. Note that DER-encoded integers are arbitrary precision,
// so this method will fail for valid input that represents an integer
- // outside the range of an int64_t.
+ // outside the range of an uint64_t.
//
// Note that on failure the Parser is left in an undefined state (the
// input may or may not have been advanced).
@@ -161,6 +171,12 @@ class NET_EXPORT Parser {
// input may or may not have been advanced).
bool ReadBitString(BitString* out) WARN_UNUSED_RESULT;
+ // Reads a GeneralizeTime. On success fills |out| and returns true.
+ //
+ // Note that on failure the Parser is left in an undefined state (the
+ // input may or may not have been advanced).
+ bool ReadGeneralizedTime(GeneralizedTime* out) WARN_UNUSED_RESULT;
+
// Lower level methods. The previous methods couple reading data from the
// input with advancing the Parser's internal pointer to the next TLV; these
// lower level methods decouple those two steps into methods that read from
diff --git a/chromium/net/der/tag.cc b/chromium/net/der/tag.cc
index 99acf8cdfd8..a8240243943 100644
--- a/chromium/net/der/tag.cc
+++ b/chromium/net/der/tag.cc
@@ -20,18 +20,10 @@ Tag ContextSpecificPrimitive(uint8_t base) {
return (base & kTagNumberMask) | kTagPrimitive | kTagContextSpecific;
}
-bool IsContextSpecific(Tag tag) {
- return (tag & kTagClassMask) == kTagContextSpecific;
-}
-
bool IsConstructed(Tag tag) {
return (tag & kTagConstructionMask) == kTagConstructed;
}
-uint8_t GetTagNumber(Tag tag) {
- return tag & kTagNumberMask;
-}
-
} // namespace der
} // namespace net
diff --git a/chromium/net/der/tag.h b/chromium/net/der/tag.h
index cb18ac6a7c1..a168df66686 100644
--- a/chromium/net/der/tag.h
+++ b/chromium/net/der/tag.h
@@ -31,6 +31,7 @@ const Tag kOid = 0x06;
const Tag kEnumerated = 0x0A;
const Tag kUtf8String = 0x0C;
const Tag kPrintableString = 0x13;
+const Tag kTeletexString = 0x14;
const Tag kIA5String = 0x16;
const Tag kUtcTime = 0x17;
const Tag kGeneralizedTime = 0x18;
@@ -67,12 +68,8 @@ NET_EXPORT Tag ContextSpecificConstructed(uint8_t class_number);
NET_EXPORT Tag ContextSpecificPrimitive(uint8_t base);
-NET_EXPORT bool IsContextSpecific(Tag tag);
-
NET_EXPORT bool IsConstructed(Tag tag);
-NET_EXPORT uint8_t GetTagNumber(Tag tag);
-
} // namespace der
} // namespace net
diff --git a/chromium/net/disk_cache/backend_unittest.cc b/chromium/net/disk_cache/backend_unittest.cc
index bc407572f01..0c57a5bc169 100644
--- a/chromium/net/disk_cache/backend_unittest.cc
+++ b/chromium/net/disk_cache/backend_unittest.cc
@@ -4,6 +4,7 @@
#include <stdint.h>
+#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
@@ -31,6 +32,7 @@
#include "net/disk_cache/memory/mem_backend_impl.h"
#include "net/disk_cache/simple/simple_backend_impl.h"
#include "net/disk_cache/simple/simple_entry_format.h"
+#include "net/disk_cache/simple/simple_index.h"
#include "net/disk_cache/simple/simple_test_util.h"
#include "net/disk_cache/simple/simple_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -99,6 +101,7 @@ class DiskCacheBackendTest : public DiskCacheTestWithCache {
void BackendShutdownWithPendingFileIO(bool fast);
void BackendShutdownWithPendingIO(bool fast);
void BackendShutdownWithPendingCreate(bool fast);
+ void BackendShutdownWithPendingDoom();
void BackendSetSize();
void BackendLoad();
void BackendChain();
@@ -136,6 +139,8 @@ class DiskCacheBackendTest : public DiskCacheTestWithCache {
void BackendDisable3();
void BackendDisable4();
void BackendDisabledAPI();
+
+ void BackendEviction();
};
int DiskCacheBackendTest::GeneratePendingIO(net::TestCompletionCallback* cb) {
@@ -640,6 +645,7 @@ void DiskCacheBackendTest::BackendShutdownWithPendingIO(bool fast) {
}
base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_FALSE(cb.have_result());
}
TEST_F(DiskCacheBackendTest, ShutdownWithPendingIO) {
@@ -679,6 +685,7 @@ void DiskCacheBackendTest::BackendShutdownWithPendingCreate(bool fast) {
}
base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_FALSE(cb.have_result());
}
TEST_F(DiskCacheBackendTest, ShutdownWithPendingCreate) {
@@ -695,6 +702,38 @@ TEST_F(DiskCacheBackendTest, ShutdownWithPendingCreate_Fast) {
}
#endif
+void DiskCacheBackendTest::BackendShutdownWithPendingDoom() {
+ net::TestCompletionCallback cb;
+ {
+ ASSERT_TRUE(CleanupCacheDir());
+ base::Thread cache_thread("CacheThread");
+ ASSERT_TRUE(cache_thread.StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
+
+ disk_cache::BackendFlags flags = disk_cache::kNoRandom;
+ CreateBackend(flags, &cache_thread);
+
+ disk_cache::Entry* entry;
+ int rv = cache_->CreateEntry("some key", &entry, cb.callback());
+ ASSERT_EQ(net::OK, cb.GetResult(rv));
+ entry->Close();
+ entry = nullptr;
+
+ rv = cache_->DoomEntry("some key", cb.callback());
+ ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+ cache_.reset();
+ EXPECT_FALSE(cb.have_result());
+ }
+
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_FALSE(cb.have_result());
+}
+
+TEST_F(DiskCacheBackendTest, ShutdownWithPendingDoom) {
+ BackendShutdownWithPendingDoom();
+}
+
// Disabled on android since this test requires cache creator to create
// blockfile caches.
#if !defined(OS_ANDROID)
@@ -2867,6 +2906,49 @@ TEST_F(DiskCacheBackendTest, NewEvictionDisabledAPI) {
BackendDisabledAPI();
}
+// Test that some eviction of some kind happens.
+void DiskCacheBackendTest::BackendEviction() {
+ const int kMaxSize = 200 * 1024;
+ const int kMaxEntryCount = 20;
+ const int kWriteSize = kMaxSize / kMaxEntryCount;
+
+ const int kWriteEntryCount = kMaxEntryCount * 2;
+
+ static_assert(kWriteEntryCount * kWriteSize > kMaxSize,
+ "must write more than MaxSize");
+
+ SetMaxSize(kMaxSize);
+ InitSparseCache(nullptr, nullptr);
+
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kWriteSize));
+ CacheTestFillBuffer(buffer->data(), kWriteSize, false);
+
+ std::string key_prefix("prefix");
+ for (int i = 0; i < kWriteEntryCount; ++i) {
+ AddDelay();
+ disk_cache::Entry* entry = NULL;
+ ASSERT_EQ(net::OK, CreateEntry(key_prefix + base::IntToString(i), &entry));
+ disk_cache::ScopedEntryPtr entry_closer(entry);
+ EXPECT_EQ(kWriteSize,
+ WriteData(entry, 1, 0, buffer.get(), kWriteSize, false));
+ }
+
+ int size = CalculateSizeOfAllEntries();
+ EXPECT_GT(kMaxSize, size);
+}
+
+TEST_F(DiskCacheBackendTest, BackendEviction) {
+ BackendEviction();
+}
+
+TEST_F(DiskCacheBackendTest, MemoryOnlyBackendEviction) {
+ SetMemoryOnlyMode();
+ BackendEviction();
+}
+
+// TODO(gavinp): Enable BackendEviction test for simple cache after performance
+// problems are addressed. See crbug.com/588184 for more information.
+
// This overly specific looking test is a regression test aimed at
// crbug.com/589186.
TEST_F(DiskCacheBackendTest, MemoryOnlyUseAfterFree) {
@@ -3322,6 +3404,12 @@ TEST_F(DiskCacheBackendTest, SimpleCacheShutdownWithPendingCreate) {
BackendShutdownWithPendingCreate(false);
}
+TEST_F(DiskCacheBackendTest, SimpleCacheShutdownWithPendingDoom) {
+ SetCacheType(net::APP_CACHE);
+ SetSimpleCacheMode();
+ BackendShutdownWithPendingDoom();
+}
+
TEST_F(DiskCacheBackendTest, SimpleCacheShutdownWithPendingFileIO) {
SetCacheType(net::APP_CACHE);
SetSimpleCacheMode();
@@ -3662,3 +3750,35 @@ TEST_F(DiskCacheBackendTest, SimpleCacheDeleteQuickly) {
EXPECT_TRUE(CleanupCacheDir());
}
}
+
+TEST_F(DiskCacheBackendTest, SimpleCacheLateDoom) {
+ SetSimpleCacheMode();
+ InitCache();
+
+ disk_cache::Entry *entry1, *entry2;
+ ASSERT_EQ(net::OK, CreateEntry("first", &entry1));
+ ASSERT_EQ(net::OK, CreateEntry("second", &entry2));
+ entry1->Close();
+
+ // Ensure that the directory mtime is flushed to disk before serializing the
+ // index.
+ disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting();
+ base::RunLoop().RunUntilIdle();
+#if defined(OS_POSIX)
+ base::File cache_dir(cache_path_,
+ base::File::FLAG_OPEN | base::File::FLAG_READ);
+ EXPECT_TRUE(cache_dir.Flush());
+#endif // defined(OS_POSIX)
+ cache_.reset();
+
+ // The index is now written. Dooming the last entry can't delete a file,
+ // because that would advance the cache directory mtime and invalidate the
+ // index.
+ entry2->Doom();
+ entry2->Close();
+
+ DisableFirstCleanup();
+ InitCache();
+ EXPECT_EQ(disk_cache::SimpleIndex::INITIALIZE_METHOD_LOADED,
+ simple_cache_impl_->index()->init_method());
+}
diff --git a/chromium/net/disk_cache/blockfile/file_win.cc b/chromium/net/disk_cache/blockfile/file_win.cc
index ef7be4308d1..1c5a9668763 100644
--- a/chromium/net/disk_cache/blockfile/file_win.cc
+++ b/chromium/net/disk_cache/blockfile/file_win.cc
@@ -5,6 +5,7 @@
#include "net/disk_cache/blockfile/file.h"
#include <limits.h>
+#include <utility>
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
@@ -73,10 +74,7 @@ MyOverlapped::MyOverlapped(disk_cache::File* file, size_t offset,
namespace disk_cache {
File::File(base::File file)
- : init_(true),
- mixed_(true),
- sync_base_file_(file.Pass()) {
-}
+ : init_(true), mixed_(true), sync_base_file_(std::move(file)) {}
bool File::Init(const base::FilePath& name) {
DCHECK(!init_);
diff --git a/chromium/net/disk_cache/blockfile/in_flight_io.cc b/chromium/net/disk_cache/blockfile/in_flight_io.cc
index d5f172b6edd..f04b8ddae58 100644
--- a/chromium/net/disk_cache/blockfile/in_flight_io.cc
+++ b/chromium/net/disk_cache/blockfile/in_flight_io.cc
@@ -12,6 +12,7 @@
#include "base/task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread_restrictions.h"
+#include "base/trace_event/trace_event.h"
namespace disk_cache {
@@ -24,6 +25,7 @@ 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/index_table_v3.cc b/chromium/net/disk_cache/blockfile/index_table_v3.cc
index 9c24e8053fe..9dca3de0596 100644
--- a/chromium/net/disk_cache/blockfile/index_table_v3.cc
+++ b/chromium/net/disk_cache/blockfile/index_table_v3.cc
@@ -403,6 +403,8 @@ void EntryCell::Serialize(IndexCell* destination) const {
EntrySet::EntrySet() : evicted_count(0), current(0) {
}
+EntrySet::EntrySet(const EntrySet& other) = default;
+
EntrySet::~EntrySet() {
}
diff --git a/chromium/net/disk_cache/blockfile/index_table_v3.h b/chromium/net/disk_cache/blockfile/index_table_v3.h
index 78122c85fbd..001b43811f5 100644
--- a/chromium/net/disk_cache/blockfile/index_table_v3.h
+++ b/chromium/net/disk_cache/blockfile/index_table_v3.h
@@ -110,6 +110,7 @@ class NET_EXPORT_PRIVATE EntryCell {
// Keeps a collection of EntryCells in order to be processed.
struct NET_EXPORT_PRIVATE EntrySet {
EntrySet();
+ EntrySet(const EntrySet& other);
~EntrySet();
int evicted_count; // The numebr of evicted entries in this set.
diff --git a/chromium/net/disk_cache/entry_unittest.cc b/chromium/net/disk_cache/entry_unittest.cc
index ea5804930e4..22f793bb88b 100644
--- a/chromium/net/disk_cache/entry_unittest.cc
+++ b/chromium/net/disk_cache/entry_unittest.cc
@@ -1633,7 +1633,7 @@ TEST_F(DiskCacheEntryTest, MemoryOnlyEnumerationWithSparseEntries) {
++count;
disk_cache::MemEntryImpl* mem_entry =
reinterpret_cast<disk_cache::MemEntryImpl*>(entry);
- EXPECT_EQ(disk_cache::MemEntryImpl::kParentEntry, mem_entry->type());
+ EXPECT_EQ(disk_cache::MemEntryImpl::PARENT_ENTRY, mem_entry->type());
mem_entry->Close();
}
EXPECT_EQ(1, count);
diff --git a/chromium/net/disk_cache/memory/mem_backend_impl.cc b/chromium/net/disk_cache/memory/mem_backend_impl.cc
index 5b37ca92bfc..028c022f035 100644
--- a/chromium/net/disk_cache/memory/mem_backend_impl.cc
+++ b/chromium/net/disk_cache/memory/mem_backend_impl.cc
@@ -4,6 +4,8 @@
#include "net/disk_cache/memory/mem_backend_impl.h"
+#include <algorithm>
+#include <functional>
#include <utility>
#include "base/logging.h"
@@ -14,36 +16,39 @@
using base::Time;
+namespace disk_cache {
+
namespace {
const int kDefaultInMemoryCacheSize = 10 * 1024 * 1024;
-const int kCleanUpMargin = 1024 * 1024;
-
-int LowWaterAdjust(int high_water) {
- if (high_water < kCleanUpMargin)
- return 0;
-
- return high_water - kCleanUpMargin;
+const int kDefaultEvictionSize = kDefaultInMemoryCacheSize / 10;
+
+bool CheckLRUListOrder(const base::LinkedList<MemEntryImpl>& lru_list) {
+ // TODO(gavinp): Check MemBackendImpl::current_size_ here as well.
+ base::Time previous_last_use_time;
+ for (base::LinkNode<MemEntryImpl>* node = lru_list.head();
+ node != lru_list.end(); node = node->next()) {
+ if (node->value()->GetLastUsed() < previous_last_use_time)
+ return false;
+ previous_last_use_time = node->value()->GetLastUsed();
+ }
+ return true;
}
} // namespace
-namespace disk_cache {
-
MemBackendImpl::MemBackendImpl(net::NetLog* net_log)
: max_size_(0), current_size_(0), net_log_(net_log), weak_factory_(this) {
}
MemBackendImpl::~MemBackendImpl() {
- EntryMap::iterator it = entries_.begin();
- while (it != entries_.end()) {
- it->second->Doom();
- it = entries_.begin();
- }
+ DCHECK(CheckLRUListOrder(lru_list_));
+ while (!entries_.empty())
+ entries_.begin()->second->Doom();
DCHECK(!current_size_);
}
-// Static.
+// static
scoped_ptr<Backend> MemBackendImpl::CreateBackend(int max_bytes,
net::NetLog* net_log) {
scoped_ptr<MemBackendImpl> cache(new MemBackendImpl(net_log));
@@ -67,7 +72,7 @@ bool MemBackendImpl::Init() {
}
// We want to use up to 2% of the computer's memory, with a limit of 50 MB,
- // reached on systemd with more than 2.5 GB of RAM.
+ // reached on system with more than 2.5 GB of RAM.
total_memory = total_memory * 2 / 100;
if (total_memory > kDefaultInMemoryCacheSize * 5)
max_size_ = kDefaultInMemoryCacheSize * 5;
@@ -91,41 +96,33 @@ bool MemBackendImpl::SetMaxSize(int max_bytes) {
return true;
}
-void MemBackendImpl::InternalDoomEntry(MemEntryImpl* entry) {
- // Only parent entries can be passed into this method.
- DCHECK(entry->type() == MemEntryImpl::kParentEntry);
-
- rankings_.Remove(entry);
- EntryMap::iterator it = entries_.find(entry->GetKey());
- if (it != entries_.end())
- entries_.erase(it);
- else
- NOTREACHED();
-
- entry->InternalDoom();
-}
-
-void MemBackendImpl::UpdateRank(MemEntryImpl* node) {
- rankings_.UpdateRank(node);
+int MemBackendImpl::MaxFileSize() const {
+ return max_size_ / 8;
}
-void MemBackendImpl::ModifyStorageSize(int32_t old_size, int32_t new_size) {
- if (old_size >= new_size)
- SubstractStorageSize(old_size - new_size);
- else
- AddStorageSize(new_size - old_size);
+void MemBackendImpl::OnEntryInserted(MemEntryImpl* entry) {
+ lru_list_.Append(entry);
}
-int MemBackendImpl::MaxFileSize() const {
- return max_size_ / 8;
+void MemBackendImpl::OnEntryUpdated(MemEntryImpl* entry) {
+ DCHECK(CheckLRUListOrder(lru_list_));
+ // LinkedList<>::RemoveFromList() removes |entry| from |lru_list_|.
+ entry->RemoveFromList();
+ lru_list_.Append(entry);
}
-void MemBackendImpl::InsertIntoRankingList(MemEntryImpl* entry) {
- rankings_.Insert(entry);
+void MemBackendImpl::OnEntryDoomed(MemEntryImpl* entry) {
+ DCHECK(CheckLRUListOrder(lru_list_));
+ if (entry->type() == MemEntryImpl::PARENT_ENTRY)
+ entries_.erase(entry->key());
+ // LinkedList<>::RemoveFromList() removes |entry| from |lru_list_|.
+ entry->RemoveFromList();
}
-void MemBackendImpl::RemoveFromRankingList(MemEntryImpl* entry) {
- rankings_.Remove(entry);
+void MemBackendImpl::ModifyStorageSize(int32_t delta) {
+ current_size_ += delta;
+ if (delta > 0)
+ EvictIfNeeded();
}
net::CacheType MemBackendImpl::GetCacheType() const {
@@ -136,52 +133,71 @@ int32_t MemBackendImpl::GetEntryCount() const {
return static_cast<int32_t>(entries_.size());
}
-int MemBackendImpl::OpenEntry(const std::string& key, Entry** entry,
+int MemBackendImpl::OpenEntry(const std::string& key,
+ Entry** entry,
const CompletionCallback& callback) {
- if (OpenEntry(key, entry))
- return net::OK;
+ EntryMap::iterator it = entries_.find(key);
+ if (it == entries_.end())
+ return net::ERR_FAILED;
- return net::ERR_FAILED;
+ it->second->Open();
+
+ *entry = it->second;
+ return net::OK;
}
-int MemBackendImpl::CreateEntry(const std::string& key, Entry** entry,
+int MemBackendImpl::CreateEntry(const std::string& key,
+ Entry** entry,
const CompletionCallback& callback) {
- if (CreateEntry(key, entry))
- return net::OK;
+ std::pair<EntryMap::iterator, bool> create_result =
+ entries_.insert(EntryMap::value_type(key, nullptr));
+ const bool did_insert = create_result.second;
+ if (!did_insert)
+ return net::ERR_FAILED;
- return net::ERR_FAILED;
+ MemEntryImpl* cache_entry = new MemEntryImpl(this, key, net_log_);
+ create_result.first->second = cache_entry;
+ *entry = cache_entry;
+ return net::OK;
}
int MemBackendImpl::DoomEntry(const std::string& key,
const CompletionCallback& callback) {
- if (DoomEntry(key))
- return net::OK;
+ EntryMap::iterator it = entries_.find(key);
+ if (it == entries_.end())
+ return net::ERR_FAILED;
- return net::ERR_FAILED;
+ it->second->Doom();
+ return net::OK;
}
int MemBackendImpl::DoomAllEntries(const CompletionCallback& callback) {
- if (DoomAllEntries())
- return net::OK;
-
- return net::ERR_FAILED;
+ return DoomEntriesBetween(Time(), Time(), callback);
}
-int MemBackendImpl::DoomEntriesBetween(const base::Time initial_time,
- const base::Time end_time,
+int MemBackendImpl::DoomEntriesBetween(Time initial_time,
+ Time end_time,
const CompletionCallback& callback) {
- if (DoomEntriesBetween(initial_time, end_time))
- return net::OK;
+ if (end_time.is_null())
+ end_time = Time::Max();
+
+ DCHECK_GE(end_time, initial_time);
+
+ 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* to_doom = node->value();
+ node = node->next();
+ to_doom->Doom();
+ }
- return net::ERR_FAILED;
+ return net::OK;
}
-int MemBackendImpl::DoomEntriesSince(const base::Time initial_time,
+int MemBackendImpl::DoomEntriesSince(Time initial_time,
const CompletionCallback& callback) {
- if (DoomEntriesSince(initial_time))
- return net::OK;
-
- return net::ERR_FAILED;
+ return DoomEntriesBetween(initial_time, Time::Max(), callback);
}
int MemBackendImpl::CalculateSizeOfAllEntries(
@@ -189,35 +205,41 @@ int MemBackendImpl::CalculateSizeOfAllEntries(
return current_size_;
}
-class MemBackendImpl::MemIterator : public Backend::Iterator {
+class MemBackendImpl::MemIterator final : public Backend::Iterator {
public:
explicit MemIterator(base::WeakPtr<MemBackendImpl> backend)
- : backend_(backend), current_(NULL) {
- }
+ : backend_(backend), current_(nullptr) {}
int OpenNextEntry(Entry** next_entry,
const CompletionCallback& callback) override {
if (!backend_)
return net::ERR_FAILED;
- MemEntryImpl* node = backend_->rankings_.GetNext(current_);
+ // Iterate using |lru_list_|, from most recently used to least recently
+ // used, for compatibility with the unit tests that assume this behaviour.
+ // Consider the last element if we are beginning an iteration, otherwise
+ // progressively move earlier in the LRU list.
+ current_ = current_ ? current_->previous() : backend_->lru_list_.tail();
+
// We should never return a child entry so iterate until we hit a parent
// entry.
- while (node && node->type() != MemEntryImpl::kParentEntry)
- node = backend_->rankings_.GetNext(node);
- *next_entry = node;
- current_ = node;
-
- if (node) {
- node->Open();
- return net::OK;
+ while (current_ != backend_->lru_list_.end() &&
+ current_->value()->type() != MemEntryImpl::PARENT_ENTRY) {
+ current_ = current_->previous();
}
- return net::ERR_FAILED;
+ if (current_ == backend_->lru_list_.end()) {
+ *next_entry = nullptr;
+ return net::ERR_FAILED;
+ }
+
+ current_->value()->Open();
+ *next_entry = current_->value();
+ return net::OK;
}
private:
base::WeakPtr<MemBackendImpl> backend_;
- MemEntryImpl* current_;
+ base::LinkNode<MemEntryImpl>* current_;
};
scoped_ptr<Backend::Iterator> MemBackendImpl::CreateIterator() {
@@ -227,127 +249,23 @@ scoped_ptr<Backend::Iterator> MemBackendImpl::CreateIterator() {
void MemBackendImpl::OnExternalCacheHit(const std::string& key) {
EntryMap::iterator it = entries_.find(key);
- if (it != entries_.end()) {
- UpdateRank(it->second);
- }
-}
-
-bool MemBackendImpl::OpenEntry(const std::string& key, Entry** entry) {
- EntryMap::iterator it = entries_.find(key);
- if (it == entries_.end())
- return false;
-
- it->second->Open();
-
- *entry = it->second;
- return true;
-}
-
-bool MemBackendImpl::CreateEntry(const std::string& key, Entry** entry) {
- EntryMap::iterator it = entries_.find(key);
if (it != entries_.end())
- return false;
-
- MemEntryImpl* cache_entry = new MemEntryImpl(this);
- if (!cache_entry->CreateEntry(key, net_log_)) {
- delete entry;
- return false;
- }
-
- rankings_.Insert(cache_entry);
- entries_[key] = cache_entry;
-
- *entry = cache_entry;
- return true;
+ it->second->UpdateStateOnUse(MemEntryImpl::ENTRY_WAS_NOT_MODIFIED);
}
-bool MemBackendImpl::DoomEntry(const std::string& key) {
- Entry* entry;
- if (!OpenEntry(key, &entry))
- return false;
-
- entry->Doom();
- entry->Close();
- return true;
-}
-
-bool MemBackendImpl::DoomAllEntries() {
- TrimCache(true);
- return true;
-}
-
-bool MemBackendImpl::DoomEntriesBetween(const Time initial_time,
- const Time end_time) {
- if (end_time.is_null())
- return DoomEntriesSince(initial_time);
-
- DCHECK(end_time >= initial_time);
-
- MemEntryImpl* node = rankings_.GetNext(NULL);
- // Last valid entry before |node|.
- // Note, that entries after |node| may become invalid during |node| doom in
- // case when they are child entries of it. It is guaranteed that
- // parent node will go prior to it childs in ranking list (see
- // InternalReadSparseData and InternalWriteSparseData).
- MemEntryImpl* last_valid = NULL;
-
- // rankings_ is ordered by last used, this will descend through the cache
- // and start dooming items before the end_time, and will stop once it reaches
- // an item used before the initial time.
- while (node) {
- if (node->GetLastUsed() < initial_time)
- break;
-
- if (node->GetLastUsed() < end_time)
- node->Doom();
- else
- last_valid = node;
- node = rankings_.GetNext(last_valid);
- }
-
- return true;
-}
-
-bool MemBackendImpl::DoomEntriesSince(const Time initial_time) {
- for (;;) {
- // Get the entry in the front.
- Entry* entry = rankings_.GetNext(NULL);
-
- // Break the loop when there are no more entries or the entry is too old.
- if (!entry || entry->GetLastUsed() < initial_time)
- return true;
- entry->Doom();
- }
-}
-
-void MemBackendImpl::TrimCache(bool empty) {
- MemEntryImpl* next = rankings_.GetPrev(NULL);
- if (!next)
+void MemBackendImpl::EvictIfNeeded() {
+ if (current_size_ <= max_size_)
return;
- int target_size = empty ? 0 : LowWaterAdjust(max_size_);
- while (current_size_ > target_size && next) {
- MemEntryImpl* node = next;
- next = rankings_.GetPrev(next);
- if (!node->InUse() || empty) {
- node->Doom();
- }
- }
-
- return;
-}
-
-void MemBackendImpl::AddStorageSize(int32_t bytes) {
- current_size_ += bytes;
- DCHECK_GE(current_size_, 0);
+ int target_size = std::max(0, max_size_ - kDefaultEvictionSize);
- if (current_size_ > max_size_)
- TrimCache(false);
-}
-
-void MemBackendImpl::SubstractStorageSize(int32_t bytes) {
- current_size_ -= bytes;
- DCHECK_GE(current_size_, 0);
+ base::LinkNode<MemEntryImpl>* entry = lru_list_.head();
+ while (current_size_ > target_size && entry != lru_list_.end()) {
+ MemEntryImpl* to_doom = entry->value();
+ entry = entry->next();
+ if (!to_doom->InUse())
+ to_doom->Doom();
+ }
}
} // namespace disk_cache
diff --git a/chromium/net/disk_cache/memory/mem_backend_impl.h b/chromium/net/disk_cache/memory/mem_backend_impl.h
index e2a9f1afda6..8abcca5b7a2 100644
--- a/chromium/net/disk_cache/memory/mem_backend_impl.h
+++ b/chromium/net/disk_cache/memory/mem_backend_impl.h
@@ -9,13 +9,17 @@
#include <stdint.h>
+#include <string>
+
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
+#include "base/containers/linked_list.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_split.h"
+#include "base/time/time.h"
#include "net/disk_cache/disk_cache.h"
-#include "net/disk_cache/memory/mem_rankings.h"
+#include "net/disk_cache/memory/mem_entry_impl.h"
namespace net {
class NetLog;
@@ -23,11 +27,9 @@ class NetLog;
namespace disk_cache {
-class MemEntryImpl;
-
// This class implements the Backend interface. An object of this class handles
// the operations of the cache without writing to disk.
-class NET_EXPORT_PRIVATE MemBackendImpl : public Backend {
+class NET_EXPORT_PRIVATE MemBackendImpl final : public Backend {
public:
explicit MemBackendImpl(net::NetLog* net_log);
~MemBackendImpl() override;
@@ -45,26 +47,29 @@ class NET_EXPORT_PRIVATE MemBackendImpl : public Backend {
// Sets the maximum size for the total amount of data stored by this instance.
bool SetMaxSize(int max_bytes);
- // Permanently deletes an entry.
- void InternalDoomEntry(MemEntryImpl* entry);
+ // Returns the maximum size for a file to reside on the cache.
+ int MaxFileSize() const;
- // Updates the ranking information for an entry.
- void UpdateRank(MemEntryImpl* node);
+ // These next methods (before the implementation of the Backend interface) are
+ // called by MemEntryImpl to update the state of the backend during the entry
+ // lifecycle.
- // A user data block is being created, extended or truncated.
- void ModifyStorageSize(int32_t old_size, int32_t new_size);
+ // Signals that new entry has been created, and should be placed in
+ // |lru_list_| so that it is eligable for eviction.
+ void OnEntryInserted(MemEntryImpl* entry);
- // Returns the maximum size for a file to reside on the cache.
- int MaxFileSize() const;
+ // Signals that an entry has been updated, and thus should be moved to the end
+ // of |lru_list_|.
+ void OnEntryUpdated(MemEntryImpl* entry);
- // Insert an MemEntryImpl into the ranking list. This method is only called
- // from MemEntryImpl to insert child entries. The reference can be removed
- // by calling RemoveFromRankingList(|entry|).
- void InsertIntoRankingList(MemEntryImpl* entry);
+ // Signals that an entry has been doomed, and so it should be removed from the
+ // list of active entries as appropriate, as well as removed from the
+ // |lru_list_|.
+ void OnEntryDoomed(MemEntryImpl* entry);
- // Remove |entry| from ranking list. This method is only called from
- // MemEntryImpl to remove a child entry from the ranking list.
- void RemoveFromRankingList(MemEntryImpl* entry);
+ // Adjust the current size of this backend by |delta|. This is used to
+ // determine if eviction is neccessary and when eviction is finished.
+ void ModifyStorageSize(int32_t delta);
// Backend interface.
net::CacheType GetCacheType() const override;
@@ -94,26 +99,15 @@ class NET_EXPORT_PRIVATE MemBackendImpl : public Backend {
typedef base::hash_map<std::string, MemEntryImpl*> EntryMap;
- // Old Backend interface.
- bool OpenEntry(const std::string& key, Entry** entry);
- bool CreateEntry(const std::string& key, Entry** entry);
- bool DoomEntry(const std::string& key);
- bool DoomAllEntries();
- bool DoomEntriesBetween(const base::Time initial_time,
- const base::Time end_time);
- bool DoomEntriesSince(const base::Time initial_time);
-
// Deletes entries from the cache until the current size is below the limit.
- // If empty is true, the whole cache will be trimmed, regardless of being in
- // use.
- void TrimCache(bool empty);
-
- // Handles the used storage count.
- void AddStorageSize(int32_t bytes);
- void SubstractStorageSize(int32_t bytes);
+ void EvictIfNeeded();
EntryMap entries_;
- MemRankings rankings_; // Rankings to be able to trim the cache.
+
+ // Stored in increasing order of last use time, from least recently used to
+ // most recently used.
+ base::LinkedList<MemEntryImpl> lru_list_;
+
int32_t max_size_; // Maximum data size for this instance.
int32_t current_size_;
diff --git a/chromium/net/disk_cache/memory/mem_entry_impl.cc b/chromium/net/disk_cache/memory/mem_entry_impl.cc
index 9f47e46fd9d..bcbebb3cf2f 100644
--- a/chromium/net/disk_cache/memory/mem_entry_impl.cc
+++ b/chromium/net/disk_cache/memory/mem_entry_impl.cc
@@ -4,6 +4,7 @@
#include "net/disk_cache/memory/mem_entry_impl.h"
+#include <algorithm>
#include <utility>
#include "base/bind.h"
@@ -17,6 +18,8 @@
using base::Time;
+namespace disk_cache {
+
namespace {
const int kSparseData = 1;
@@ -28,12 +31,12 @@ const int kMaxSparseEntryBits = 12;
const int kMaxSparseEntrySize = 1 << kMaxSparseEntryBits;
// Convert global offset to child index.
-inline int ToChildIndex(int64_t offset) {
+int ToChildIndex(int64_t offset) {
return static_cast<int>(offset >> kMaxSparseEntryBits);
}
// Convert global offset to offset in child entry.
-inline int ToChildOffset(int64_t offset) {
+int ToChildOffset(int64_t offset) {
return static_cast<int>(offset & (kMaxSparseEntrySize - 1));
}
@@ -45,125 +48,104 @@ std::string GenerateChildName(const std::string& base_name, int child_id) {
return base::StringPrintf("Range_%s:%i", base_name.c_str(), child_id);
}
-// Returns NetLog parameters for the creation of a child MemEntryImpl. Separate
-// function needed because child entries don't suppport GetKey().
-scoped_ptr<base::Value> NetLogChildEntryCreationCallback(
- const disk_cache::MemEntryImpl* parent,
- int child_id,
+// Returns NetLog parameters for the creation of a MemEntryImpl. A separate
+// function is needed because child entries don't store their key().
+scoped_ptr<base::Value> NetLogEntryCreationCallback(
+ const MemEntryImpl* entry,
net::NetLogCaptureMode /* capture_mode */) {
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
- dict->SetString("key", GenerateChildName(parent->GetKey(), child_id));
+ std::string key;
+ switch (entry->type()) {
+ case MemEntryImpl::PARENT_ENTRY:
+ key = entry->key();
+ break;
+ case MemEntryImpl::CHILD_ENTRY:
+ key = GenerateChildName(entry->parent()->key(), entry->child_id());
+ break;
+ }
+ dict->SetString("key", key);
dict->SetBoolean("created", true);
return std::move(dict);
}
} // namespace
-namespace disk_cache {
-
-MemEntryImpl::MemEntryImpl(MemBackendImpl* backend) {
- doomed_ = false;
- backend_ = backend;
- ref_count_ = 0;
- parent_ = NULL;
- child_id_ = 0;
- child_first_pos_ = 0;
- next_ = NULL;
- prev_ = NULL;
- for (int i = 0; i < NUM_STREAMS; i++)
- data_size_[i] = 0;
-}
-
-// ------------------------------------------------------------------------
-
-bool MemEntryImpl::CreateEntry(const std::string& key, net::NetLog* net_log) {
- key_ = key;
- Time current = Time::Now();
- last_modified_ = current;
- last_used_ = current;
-
- net_log_ = net::BoundNetLog::Make(net_log,
- net::NetLog::SOURCE_MEMORY_CACHE_ENTRY);
- // Must be called after |key_| is set, so GetKey() works.
- net_log_.BeginEvent(
- net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL,
- CreateNetLogEntryCreationCallback(this, true));
-
+MemEntryImpl::MemEntryImpl(MemBackendImpl* backend,
+ const std::string& key,
+ net::NetLog* net_log)
+ : MemEntryImpl(backend,
+ key,
+ 0, // child_id
+ nullptr, // parent
+ net_log) {
Open();
- backend_->ModifyStorageSize(0, static_cast<int32_t>(key.size()));
- return true;
+ backend_->ModifyStorageSize(GetStorageSize());
}
-void MemEntryImpl::InternalDoom() {
- net_log_.AddEvent(net::NetLog::TYPE_ENTRY_DOOM);
- doomed_ = true;
- if (!ref_count_) {
- if (type() == kParentEntry) {
- // If this is a parent entry, we need to doom all the child entries.
- if (children_.get()) {
- EntryMap children;
- children.swap(*children_);
- for (EntryMap::iterator i = children.begin();
- i != children.end(); ++i) {
- // Since a pointer to this object is also saved in the map, avoid
- // dooming it.
- if (i->second != this)
- i->second->Doom();
- }
- DCHECK(children_->empty());
- }
- } else {
- // If this is a child entry, detach it from the parent.
- parent_->DetachChild(child_id_);
- }
- delete this;
- }
+MemEntryImpl::MemEntryImpl(MemBackendImpl* backend,
+ int child_id,
+ MemEntryImpl* parent,
+ net::NetLog* net_log)
+ : MemEntryImpl(backend,
+ std::string(), // key
+ child_id,
+ parent,
+ net_log) {
+ (*parent_->children_)[child_id] = this;
}
void MemEntryImpl::Open() {
// Only a parent entry can be opened.
- // TODO(hclam): make sure it's correct to not apply the concept of ref
- // counting to child entry.
- DCHECK(type() == kParentEntry);
- ref_count_++;
- DCHECK_GE(ref_count_, 0);
+ DCHECK_EQ(PARENT_ENTRY, type());
+ ++ref_count_;
+ DCHECK_GE(ref_count_, 1);
DCHECK(!doomed_);
}
-bool MemEntryImpl::InUse() {
- if (type() == kChildEntry)
+bool MemEntryImpl::InUse() const {
+ if (type() == CHILD_ENTRY)
return parent_->InUse();
return ref_count_ > 0;
}
-// ------------------------------------------------------------------------
+int MemEntryImpl::GetStorageSize() const {
+ int storage_size = static_cast<int32_t>(key_.size());
+ for (const auto& i : data_)
+ storage_size += i.size();
+ return storage_size;
+}
+
+void MemEntryImpl::UpdateStateOnUse(EntryModified modified_enum) {
+ if (!doomed_)
+ backend_->OnEntryUpdated(this);
+
+ last_used_ = Time::Now();
+ if (modified_enum == ENTRY_WAS_MODIFIED)
+ last_modified_ = last_used_;
+}
void MemEntryImpl::Doom() {
- if (doomed_)
- return;
- if (type() == kParentEntry) {
- // Perform internal doom from the backend if this is a parent entry.
- backend_->InternalDoomEntry(this);
- } else {
- // Manually detach from the backend and perform internal doom.
- backend_->RemoveFromRankingList(this);
- InternalDoom();
+ if (!doomed_) {
+ doomed_ = true;
+ backend_->OnEntryDoomed(this);
+ net_log_.AddEvent(net::NetLog::TYPE_ENTRY_DOOM);
}
+ if (!ref_count_)
+ delete this;
}
void MemEntryImpl::Close() {
- // Only a parent entry can be closed.
- DCHECK(type() == kParentEntry);
- ref_count_--;
+ DCHECK_EQ(PARENT_ENTRY, type());
+ --ref_count_;
DCHECK_GE(ref_count_, 0);
if (!ref_count_ && doomed_)
- InternalDoom();
+ delete this;
}
std::string MemEntryImpl::GetKey() const {
// A child entry doesn't have key so this method should not be called.
- DCHECK(type() == kParentEntry);
+ DCHECK_EQ(PARENT_ENTRY, type());
return key_;
}
@@ -176,9 +158,9 @@ Time MemEntryImpl::GetLastModified() const {
}
int32_t MemEntryImpl::GetDataSize(int index) const {
- if (index < 0 || index >= NUM_STREAMS)
+ if (index < 0 || index >= kNumStreams)
return 0;
- return data_size_[index];
+ return data_[index].size();
}
int MemEntryImpl::ReadData(int index, int offset, IOBuffer* buf, int buf_len,
@@ -256,7 +238,7 @@ int MemEntryImpl::GetAvailableRange(int64_t offset,
net::NetLog::TYPE_SPARSE_GET_RANGE,
CreateNetLogSparseOperationCallback(offset, len));
}
- int result = GetAvailableRange(offset, len, start);
+ int result = InternalGetAvailableRange(offset, len, start);
if (net_log_.IsCapturing()) {
net_log_.EndEvent(
net::NetLog::TYPE_SPARSE_GET_RANGE,
@@ -266,8 +248,8 @@ int MemEntryImpl::GetAvailableRange(int64_t offset,
}
bool MemEntryImpl::CouldBeSparse() const {
- DCHECK_EQ(kParentEntry, type());
- return (children_.get() != NULL);
+ DCHECK_EQ(PARENT_ENTRY, type());
+ return (children_.get() != nullptr);
}
int MemEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
@@ -276,41 +258,73 @@ int MemEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
// ------------------------------------------------------------------------
+MemEntryImpl::MemEntryImpl(MemBackendImpl* backend,
+ const ::std::string& key,
+ int child_id,
+ MemEntryImpl* parent,
+ net::NetLog* net_log)
+ : key_(key),
+ ref_count_(0),
+ child_id_(child_id),
+ child_first_pos_(0),
+ parent_(parent),
+ last_modified_(Time::Now()),
+ last_used_(last_modified_),
+ backend_(backend),
+ doomed_(false) {
+ backend_->OnEntryInserted(this);
+ net_log_ =
+ net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_MEMORY_CACHE_ENTRY);
+ net_log_.BeginEvent(net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL,
+ base::Bind(&NetLogEntryCreationCallback, this));
+}
+
MemEntryImpl::~MemEntryImpl() {
- for (int i = 0; i < NUM_STREAMS; i++)
- backend_->ModifyStorageSize(data_size_[i], 0);
- backend_->ModifyStorageSize(static_cast<int32_t>(key_.size()), 0);
+ backend_->ModifyStorageSize(-GetStorageSize());
+
+ if (type() == PARENT_ENTRY) {
+ if (children_) {
+ EntryMap children;
+ children_->swap(children);
+
+ for (auto& it : children) {
+ // Since |this| is stored in the map, it should be guarded against
+ // double dooming, which will result in double destruction.
+ if (it.second != this)
+ it.second->Doom();
+ }
+ }
+ } else {
+ parent_->children_->erase(child_id_);
+ }
net_log_.EndEvent(net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL);
}
int MemEntryImpl::InternalReadData(int index, int offset, IOBuffer* buf,
int buf_len) {
- DCHECK(type() == kParentEntry || index == kSparseData);
+ DCHECK(type() == PARENT_ENTRY || index == kSparseData);
- if (index < 0 || index >= NUM_STREAMS)
+ if (index < 0 || index >= kNumStreams || buf_len < 0)
return net::ERR_INVALID_ARGUMENT;
- int entry_size = GetDataSize(index);
+ int entry_size = data_[index].size();
if (offset >= entry_size || offset < 0 || !buf_len)
return 0;
- if (buf_len < 0)
- return net::ERR_INVALID_ARGUMENT;
-
if (offset + buf_len > entry_size)
buf_len = entry_size - offset;
- UpdateRank(false);
-
- memcpy(buf->data(), &(data_[index])[offset], buf_len);
+ UpdateStateOnUse(ENTRY_WAS_NOT_MODIFIED);
+ std::copy(data_[index].begin() + offset,
+ data_[index].begin() + offset + buf_len, buf->data());
return buf_len;
}
int MemEntryImpl::InternalWriteData(int index, int offset, IOBuffer* buf,
int buf_len, bool truncate) {
- DCHECK(type() == kParentEntry || index == kSparseData);
+ DCHECK(type() == PARENT_ENTRY || index == kSparseData);
- if (index < 0 || index >= NUM_STREAMS)
+ if (index < 0 || index >= kNumStreams)
return net::ERR_INVALID_ARGUMENT;
if (offset < 0 || buf_len < 0)
@@ -324,34 +338,32 @@ int MemEntryImpl::InternalWriteData(int index, int offset, IOBuffer* buf,
return net::ERR_FAILED;
}
- // Read the size at this point.
- int entry_size = GetDataSize(index);
-
- PrepareTarget(index, offset, buf_len);
+ int old_data_size = data_[index].size();
+ if (truncate || old_data_size < offset + buf_len) {
+ data_[index].resize(offset + buf_len);
- if (entry_size < offset + buf_len) {
- backend_->ModifyStorageSize(entry_size, offset + buf_len);
- data_size_[index] = offset + buf_len;
- } else if (truncate) {
- if (entry_size > offset + buf_len) {
- backend_->ModifyStorageSize(entry_size, offset + buf_len);
- data_size_[index] = offset + buf_len;
+ // Zero fill any hole.
+ if (old_data_size < offset) {
+ std::fill(data_[index].begin() + old_data_size,
+ data_[index].begin() + offset, 0);
}
+
+ backend_->ModifyStorageSize(data_[index].size() - old_data_size);
}
- UpdateRank(true);
+ UpdateStateOnUse(ENTRY_WAS_MODIFIED);
if (!buf_len)
return 0;
- memcpy(&(data_[index])[offset], buf->data(), buf_len);
+ std::copy(buf->data(), buf->data() + buf_len, data_[index].begin() + offset);
return buf_len;
}
int MemEntryImpl::InternalReadSparseData(int64_t offset,
IOBuffer* buf,
int buf_len) {
- DCHECK(type() == kParentEntry);
+ DCHECK_EQ(PARENT_ENTRY, type());
if (!InitSparseInfo())
return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
@@ -365,7 +377,7 @@ int MemEntryImpl::InternalReadSparseData(int64_t offset,
// Iterate until we have read enough.
while (io_buf->BytesRemaining()) {
- MemEntryImpl* child = OpenChild(offset + io_buf->BytesConsumed(), false);
+ MemEntryImpl* child = GetChild(offset + io_buf->BytesConsumed(), false);
// No child present for that offset.
if (!child)
@@ -381,7 +393,7 @@ int MemEntryImpl::InternalReadSparseData(int64_t offset,
if (net_log_.IsCapturing()) {
net_log_.BeginEvent(
net::NetLog::TYPE_SPARSE_READ_CHILD_DATA,
- CreateNetLogSparseReadWriteCallback(child->net_log().source(),
+ CreateNetLogSparseReadWriteCallback(child->net_log_.source(),
io_buf->BytesRemaining()));
}
int ret = child->ReadData(kSparseData, child_offset, io_buf.get(),
@@ -401,15 +413,14 @@ int MemEntryImpl::InternalReadSparseData(int64_t offset,
io_buf->DidConsume(ret);
}
- UpdateRank(false);
-
+ UpdateStateOnUse(ENTRY_WAS_NOT_MODIFIED);
return io_buf->BytesConsumed();
}
int MemEntryImpl::InternalWriteSparseData(int64_t offset,
IOBuffer* buf,
int buf_len) {
- DCHECK(type() == kParentEntry);
+ DCHECK_EQ(PARENT_ENTRY, type());
if (!InitSparseInfo())
return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
@@ -425,7 +436,7 @@ int MemEntryImpl::InternalWriteSparseData(int64_t offset,
// child entry until all |buf_len| bytes are written. The write operation can
// start in the middle of an entry.
while (io_buf->BytesRemaining()) {
- MemEntryImpl* child = OpenChild(offset + io_buf->BytesConsumed(), true);
+ MemEntryImpl* child = GetChild(offset + io_buf->BytesConsumed(), true);
int child_offset = ToChildOffset(offset + io_buf->BytesConsumed());
// Find the right amount to write, this evaluates the remaining bytes to
@@ -437,10 +448,9 @@ int MemEntryImpl::InternalWriteSparseData(int64_t offset,
int data_size = child->GetDataSize(kSparseData);
if (net_log_.IsCapturing()) {
- net_log_.BeginEvent(
- net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA,
- CreateNetLogSparseReadWriteCallback(child->net_log().source(),
- write_len));
+ net_log_.BeginEvent(net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA,
+ CreateNetLogSparseReadWriteCallback(
+ child->net_log_.source(), write_len));
}
// Always writes to the child entry. This operation may overwrite data
@@ -468,13 +478,14 @@ int MemEntryImpl::InternalWriteSparseData(int64_t offset,
io_buf->DidConsume(ret);
}
- UpdateRank(true);
-
+ UpdateStateOnUse(ENTRY_WAS_MODIFIED);
return io_buf->BytesConsumed();
}
-int MemEntryImpl::GetAvailableRange(int64_t offset, int len, int64_t* start) {
- DCHECK(type() == kParentEntry);
+int MemEntryImpl::InternalGetAvailableRange(int64_t offset,
+ int len,
+ int64_t* start) {
+ DCHECK_EQ(PARENT_ENTRY, type());
DCHECK(start);
if (!InitSparseInfo())
@@ -483,7 +494,7 @@ int MemEntryImpl::GetAvailableRange(int64_t offset, int len, int64_t* start) {
if (offset < 0 || len < 0 || !start)
return net::ERR_INVALID_ARGUMENT;
- MemEntryImpl* current_child = NULL;
+ MemEntryImpl* current_child = nullptr;
// Find the first child and record the number of empty bytes.
int empty = FindNextChild(offset, len, &current_child);
@@ -517,38 +528,10 @@ int MemEntryImpl::GetAvailableRange(int64_t offset, int len, int64_t* start) {
return 0;
}
-void MemEntryImpl::PrepareTarget(int index, int offset, int buf_len) {
- int entry_size = GetDataSize(index);
-
- if (entry_size >= offset + buf_len)
- return; // Not growing the stored data.
-
- if (static_cast<int>(data_[index].size()) < offset + buf_len)
- data_[index].resize(offset + buf_len);
-
- if (offset <= entry_size)
- return; // There is no "hole" on the stored data.
-
- // Cleanup the hole not written by the user. The point is to avoid returning
- // random stuff later on.
- memset(&(data_[index])[entry_size], 0, offset - entry_size);
-}
-
-void MemEntryImpl::UpdateRank(bool modified) {
- Time current = Time::Now();
- last_used_ = current;
-
- if (modified)
- last_modified_ = current;
-
- if (!doomed_)
- backend_->UpdateRank(this);
-}
-
bool MemEntryImpl::InitSparseInfo() {
- DCHECK(type() == kParentEntry);
+ DCHECK_EQ(PARENT_ENTRY, type());
- if (!children_.get()) {
+ if (!children_) {
// If we already have some data in sparse stream but we are being
// initialized as a sparse entry, we should fail.
if (GetDataSize(kSparseData))
@@ -562,52 +545,27 @@ bool MemEntryImpl::InitSparseInfo() {
return true;
}
-bool MemEntryImpl::InitChildEntry(MemEntryImpl* parent, int child_id,
- net::NetLog* net_log) {
- DCHECK(!parent_);
- DCHECK(!child_id_);
-
- net_log_ = net::BoundNetLog::Make(net_log,
- net::NetLog::SOURCE_MEMORY_CACHE_ENTRY);
- net_log_.BeginEvent(
- net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL,
- base::Bind(&NetLogChildEntryCreationCallback, parent, child_id_));
-
- parent_ = parent;
- child_id_ = child_id;
- Time current = Time::Now();
- last_modified_ = current;
- last_used_ = current;
- // Insert this to the backend's ranking list.
- backend_->InsertIntoRankingList(this);
- return true;
-}
-
-MemEntryImpl* MemEntryImpl::OpenChild(int64_t offset, bool create) {
- DCHECK(type() == kParentEntry);
+MemEntryImpl* MemEntryImpl::GetChild(int64_t offset, bool create) {
+ DCHECK_EQ(PARENT_ENTRY, type());
int index = ToChildIndex(offset);
EntryMap::iterator i = children_->find(index);
- if (i != children_->end()) {
+ if (i != children_->end())
return i->second;
- } else if (create) {
- MemEntryImpl* child = new MemEntryImpl(backend_);
- child->InitChildEntry(this, index, net_log_.net_log());
- (*children_)[index] = child;
- return child;
- }
- return NULL;
+ if (create)
+ return new MemEntryImpl(backend_, index, this, net_log_.net_log());
+ return nullptr;
}
int MemEntryImpl::FindNextChild(int64_t offset, int len, MemEntryImpl** child) {
DCHECK(child);
- *child = NULL;
+ *child = nullptr;
int scanned_len = 0;
// This loop tries to find the first existing child.
while (scanned_len < len) {
// This points to the current offset in the child.
int current_child_offset = ToChildOffset(offset + scanned_len);
- MemEntryImpl* current_child = OpenChild(offset + scanned_len, false);
+ MemEntryImpl* current_child = GetChild(offset + scanned_len, false);
if (current_child) {
int child_first_pos = current_child->child_first_pos_;
@@ -630,8 +588,4 @@ int MemEntryImpl::FindNextChild(int64_t offset, int len, MemEntryImpl** child) {
return scanned_len;
}
-void MemEntryImpl::DetachChild(int child_id) {
- children_->erase(child_id);
-}
-
} // namespace disk_cache
diff --git a/chromium/net/disk_cache/memory/mem_entry_impl.h b/chromium/net/disk_cache/memory/mem_entry_impl.h
index 52a1696f63c..11634e6ab9a 100644
--- a/chromium/net/disk_cache/memory/mem_entry_impl.h
+++ b/chromium/net/disk_cache/memory/mem_entry_impl.h
@@ -7,9 +7,15 @@
#include <stdint.h>
+#include <string>
+#include <vector>
+
#include "base/containers/hash_tables.h"
+#include "base/containers/linked_list.h"
+#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
#include "net/disk_cache/disk_cache.h"
#include "net/log/net_log.h"
@@ -18,8 +24,8 @@ namespace disk_cache {
class MemBackendImpl;
// This class implements the Entry interface for the memory-only cache. An
-// object of this class represents a single entry on the cache. We use two
-// types of entries, parent and child to support sparse caching.
+// object of this class represents a single entry on the cache. We use two types
+// of entries, parent and child to support sparse caching.
//
// A parent entry is non-sparse until a sparse method is invoked (i.e.
// ReadSparseData, WriteSparseData, GetAvailableRange) when sparse information
@@ -31,64 +37,62 @@ class MemBackendImpl;
// ReadData and WriteData cannot be applied to them. The lifetime of a child
// entry is managed by the parent entry that created it except that the entry
// can be evicted independently. A child entry does not have a key and it is not
-// registered in the backend's entry map. It is registered in the backend's
-// ranking list to enable eviction of a partial content.
+// registered in the backend's entry map.
//
-// A sparse entry has a fixed maximum size and can be partially filled. There
-// can only be one continous filled region in a sparse entry, as illustrated by
-// the following example:
+// A sparse child entry has a fixed maximum size and can be partially
+// filled. There can only be one continous filled region in a sparse entry, as
+// illustrated by the following example:
// | xxx ooooo |
// x = unfilled region
// o = filled region
-// It is guranteed that there is at most one unfilled region and one filled
+// It is guaranteed that there is at most one unfilled region and one filled
// region, and the unfilled region (if there is one) is always before the filled
// region. The book keeping for filled region in a sparse entry is done by using
-// the variable |child_first_pos_| (inclusive).
+// the variable |child_first_pos_|.
-class MemEntryImpl : public Entry {
+class NET_EXPORT_PRIVATE MemEntryImpl final
+ : public Entry,
+ public base::LinkNode<MemEntryImpl> {
public:
enum EntryType {
- kParentEntry,
- kChildEntry,
+ PARENT_ENTRY,
+ CHILD_ENTRY,
};
- explicit MemEntryImpl(MemBackendImpl* backend);
+ // Provided to better document calls to |UpdateStateOnUse()|.
+ enum EntryModified {
+ ENTRY_WAS_NOT_MODIFIED,
+ ENTRY_WAS_MODIFIED,
+ };
- // Performs the initialization of a EntryImpl that will be added to the
- // cache.
- bool CreateEntry(const std::string& key, net::NetLog* net_log);
+ // Constructor for parent entries.
+ MemEntryImpl(MemBackendImpl* backend,
+ const std::string& key,
+ net::NetLog* net_log);
- // Permanently destroys this entry.
- void InternalDoom();
+ // Constructor for child entries.
+ MemEntryImpl(MemBackendImpl* backend,
+ int child_id,
+ MemEntryImpl* parent,
+ net::NetLog* net_log);
void Open();
- bool InUse();
-
- MemEntryImpl* next() const {
- return next_;
- }
+ bool InUse() const;
- MemEntryImpl* prev() const {
- return prev_;
- }
+ EntryType type() const { return parent_ ? CHILD_ENTRY : PARENT_ENTRY; }
+ const std::string& key() const { return key_; }
+ const MemEntryImpl* parent() const { return parent_; }
+ int child_id() const { return child_id_; }
+ base::Time last_used() const { return last_used_; }
- void set_next(MemEntryImpl* next) {
- next_ = next;
- }
+ // The in-memory size of this entry to use for the purposes of eviction.
+ int GetStorageSize() const;
- void set_prev(MemEntryImpl* prev) {
- prev_ = prev;
- }
+ // Update an entry's position in the backend LRU list and set |last_used_|. If
+ // the entry was modified, also update |last_modified_|.
+ void UpdateStateOnUse(EntryModified modified_enum);
- EntryType type() const {
- return parent_ ? kChildEntry : kParentEntry;
- }
-
- const net::BoundNetLog& net_log() {
- return net_log_;
- }
-
- // Entry interface.
+ // From disk_cache::Entry:
void Doom() override;
void Close() override;
std::string GetKey() const override;
@@ -123,11 +127,15 @@ class MemEntryImpl : public Entry {
int ReadyForSparseIO(const CompletionCallback& callback) override;
private:
+ MemEntryImpl(MemBackendImpl* backend,
+ const std::string& key,
+ int child_id,
+ MemEntryImpl* parent,
+ net::NetLog* net_log);
+
typedef base::hash_map<int, MemEntryImpl*> EntryMap;
- enum {
- NUM_STREAMS = 3
- };
+ static const int kNumStreams = 3;
~MemEntryImpl() override;
@@ -138,53 +146,35 @@ class MemEntryImpl : public Entry {
bool truncate);
int InternalReadSparseData(int64_t offset, IOBuffer* buf, int buf_len);
int InternalWriteSparseData(int64_t offset, IOBuffer* buf, int buf_len);
-
- // Old Entry interface.
- int GetAvailableRange(int64_t offset, int len, int64_t* start);
-
- // Grows and cleans up the data buffer.
- void PrepareTarget(int index, int offset, int buf_len);
-
- // Updates ranking information.
- void UpdateRank(bool modified);
+ int InternalGetAvailableRange(int64_t offset, int len, int64_t* start);
// Initializes the children map and sparse info. This method is only called
// on a parent entry.
bool InitSparseInfo();
- // Performs the initialization of a MemEntryImpl as a child entry.
- // |parent| is the pointer to the parent entry. |child_id| is the ID of
- // the new child.
- bool InitChildEntry(MemEntryImpl* parent, int child_id, net::NetLog* net_log);
-
// Returns an entry responsible for |offset|. The returned entry can be a
// child entry or this entry itself if |offset| points to the first range.
// If such entry does not exist and |create| is true, a new child entry is
// created.
- MemEntryImpl* OpenChild(int64_t offset, bool create);
+ MemEntryImpl* GetChild(int64_t offset, bool create);
// Finds the first child located within the range [|offset|, |offset + len|).
// Returns the number of bytes ahead of |offset| to reach the first available
// bytes in the entry. The first child found is output to |child|.
int FindNextChild(int64_t offset, int len, MemEntryImpl** child);
- // Removes child indexed by |child_id| from the children map.
- void DetachChild(int child_id);
-
std::string key_;
- std::vector<char> data_[NUM_STREAMS]; // User data.
- int32_t data_size_[NUM_STREAMS];
+ std::vector<char> data_[kNumStreams]; // User data.
int ref_count_;
int child_id_; // The ID of a child entry.
int child_first_pos_; // The position of the first byte in a child
// entry.
- MemEntryImpl* next_; // Pointers for the LRU list.
- MemEntryImpl* prev_;
- MemEntryImpl* parent_; // Pointer to the parent entry.
+ // Pointer to the parent entry, or nullptr if this entry is a parent entry.
+ MemEntryImpl* parent_;
scoped_ptr<EntryMap> children_;
- base::Time last_modified_; // LRU information.
+ base::Time last_modified_;
base::Time last_used_;
MemBackendImpl* backend_; // Back pointer to the cache.
bool doomed_; // True if this entry was removed from the cache.
diff --git a/chromium/net/disk_cache/memory/mem_rankings.cc b/chromium/net/disk_cache/memory/mem_rankings.cc
deleted file mode 100644
index ba5e00b9938..00000000000
--- a/chromium/net/disk_cache/memory/mem_rankings.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium 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/disk_cache/memory/mem_rankings.h"
-
-#include "base/logging.h"
-#include "net/disk_cache/memory/mem_entry_impl.h"
-
-namespace disk_cache {
-
-MemRankings::~MemRankings() {
- DCHECK(!head_ && !tail_);
-}
-
-void MemRankings::Insert(MemEntryImpl* node) {
- if (head_)
- head_->set_prev(node);
-
- if (!tail_)
- tail_ = node;
-
- node->set_prev(NULL);
- node->set_next(head_);
- head_ = node;
-}
-
-void MemRankings::Remove(MemEntryImpl* node) {
- MemEntryImpl* prev = node->prev();
- MemEntryImpl* next = node->next();
-
- if (head_ == node)
- head_ = next;
-
- if (tail_ == node)
- tail_ = prev;
-
- if (prev)
- prev->set_next(next);
-
- if (next)
- next->set_prev(prev);
-
- node->set_next(NULL);
- node->set_prev(NULL);
-}
-
-void MemRankings::UpdateRank(MemEntryImpl* node) {
- Remove(node);
- Insert(node);
-}
-
-MemEntryImpl* MemRankings::GetNext(MemEntryImpl* node) {
- if (!node)
- return head_;
-
- return node->next();
-}
-
-MemEntryImpl* MemRankings::GetPrev(MemEntryImpl* node) {
- if (!node)
- return tail_;
-
- return node->prev();
-}
-
-} // namespace disk_cache
diff --git a/chromium/net/disk_cache/memory/mem_rankings.h b/chromium/net/disk_cache/memory/mem_rankings.h
deleted file mode 100644
index d660cabd83f..00000000000
--- a/chromium/net/disk_cache/memory/mem_rankings.h
+++ /dev/null
@@ -1,44 +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.
-
-// See net/disk_cache/disk_cache.h for the public interface.
-
-#ifndef NET_DISK_CACHE_MEMORY_MEM_RANKINGS_H_
-#define NET_DISK_CACHE_MEMORY_MEM_RANKINGS_H_
-
-#include "base/macros.h"
-
-namespace disk_cache {
-
-class MemEntryImpl;
-
-// This class handles the ranking information for the memory-only cache.
-class MemRankings {
- public:
- MemRankings() : head_(NULL), tail_(NULL) {}
- ~MemRankings();
-
- // Inserts a given entry at the head of the queue.
- void Insert(MemEntryImpl* node);
-
- // Removes a given entry from the LRU list.
- void Remove(MemEntryImpl* node);
-
- // Moves a given entry to the head.
- void UpdateRank(MemEntryImpl* node);
-
- // Iterates through the list.
- MemEntryImpl* GetNext(MemEntryImpl* node);
- MemEntryImpl* GetPrev(MemEntryImpl* node);
-
- private:
- MemEntryImpl* head_;
- MemEntryImpl* tail_;
-
- DISALLOW_COPY_AND_ASSIGN(MemRankings);
-};
-
-} // namespace disk_cache
-
-#endif // NET_DISK_CACHE_MEMORY_MEM_RANKINGS_H_
diff --git a/chromium/net/disk_cache/simple/simple_backend_impl.cc b/chromium/net/disk_cache/simple/simple_backend_impl.cc
index 9f410ed4677..00f6d15e129 100644
--- a/chromium/net/disk_cache/simple/simple_backend_impl.cc
+++ b/chromium/net/disk_cache/simple/simple_backend_impl.cc
@@ -295,8 +295,8 @@ void SimpleBackendImpl::OnDoomComplete(uint64_t entry_hash) {
to_run_closures.swap(it->second);
entries_pending_doom_.erase(it);
- std::for_each(to_run_closures.begin(), to_run_closures.end(),
- std::mem_fun_ref(&Closure::Run));
+ for (auto& closure : to_run_closures)
+ closure.Run();
}
void SimpleBackendImpl::DoomEntries(std::vector<uint64_t>* entry_hashes,
diff --git a/chromium/net/disk_cache/simple/simple_entry_impl.cc b/chromium/net/disk_cache/simple/simple_entry_impl.cc
index 2c25d0ff8d0..68f1b9e709a 100644
--- a/chromium/net/disk_cache/simple/simple_entry_impl.cc
+++ b/chromium/net/disk_cache/simple/simple_entry_impl.cc
@@ -789,13 +789,11 @@ void SimpleEntryImpl::CloseInternal() {
}
if (synchronous_entry_) {
- Closure task =
- base::Bind(&SimpleSynchronousEntry::Close,
- base::Unretained(synchronous_entry_),
- SimpleEntryStat(last_used_, last_modified_, data_size_,
- sparse_data_size_),
- base::Passed(&crc32s_to_write),
- stream_0_data_);
+ Closure task = base::Bind(
+ &SimpleSynchronousEntry::Close, base::Unretained(synchronous_entry_),
+ SimpleEntryStat(last_used_, last_modified_, data_size_,
+ sparse_data_size_),
+ base::Passed(&crc32s_to_write), base::RetainedRef(stream_0_data_));
Closure reply = base::Bind(&SimpleEntryImpl::CloseOperationComplete, this);
synchronous_entry_ = NULL;
worker_pool_->PostTaskAndReply(FROM_HERE, task, reply);
@@ -876,13 +874,9 @@ void SimpleEntryImpl::ReadDataInternal(int stream_index,
new SimpleEntryStat(last_used_, last_modified_, data_size_,
sparse_data_size_));
Closure task = base::Bind(
- &SimpleSynchronousEntry::ReadData,
- base::Unretained(synchronous_entry_),
+ &SimpleSynchronousEntry::ReadData, base::Unretained(synchronous_entry_),
SimpleSynchronousEntry::EntryOperationData(stream_index, offset, buf_len),
- make_scoped_refptr(buf),
- read_crc32.get(),
- entry_stat.get(),
- result.get());
+ base::RetainedRef(buf), read_crc32.get(), entry_stat.get(), result.get());
Closure reply = base::Bind(&SimpleEntryImpl::ReadOperationComplete,
this,
stream_index,
@@ -977,14 +971,11 @@ void SimpleEntryImpl::WriteDataInternal(int stream_index,
have_written_[0] = true;
scoped_ptr<int> result(new int());
- Closure task = base::Bind(&SimpleSynchronousEntry::WriteData,
- base::Unretained(synchronous_entry_),
- SimpleSynchronousEntry::EntryOperationData(
- stream_index, offset, buf_len, truncate,
- doomed_),
- make_scoped_refptr(buf),
- entry_stat.get(),
- result.get());
+ Closure task = base::Bind(
+ &SimpleSynchronousEntry::WriteData, base::Unretained(synchronous_entry_),
+ SimpleSynchronousEntry::EntryOperationData(stream_index, offset, buf_len,
+ truncate, doomed_),
+ base::RetainedRef(buf), entry_stat.get(), result.get());
Closure reply = base::Bind(&SimpleEntryImpl::WriteOperationComplete,
this,
stream_index,
@@ -1013,13 +1004,11 @@ void SimpleEntryImpl::ReadSparseDataInternal(
scoped_ptr<int> result(new int());
scoped_ptr<base::Time> last_used(new base::Time());
- Closure task = base::Bind(&SimpleSynchronousEntry::ReadSparseData,
- base::Unretained(synchronous_entry_),
- SimpleSynchronousEntry::EntryOperationData(
- sparse_offset, buf_len),
- make_scoped_refptr(buf),
- last_used.get(),
- result.get());
+ Closure task = base::Bind(
+ &SimpleSynchronousEntry::ReadSparseData,
+ base::Unretained(synchronous_entry_),
+ SimpleSynchronousEntry::EntryOperationData(sparse_offset, buf_len),
+ base::RetainedRef(buf), last_used.get(), result.get());
Closure reply = base::Bind(&SimpleEntryImpl::ReadSparseOperationComplete,
this,
callback,
@@ -1058,14 +1047,12 @@ void SimpleEntryImpl::WriteSparseDataInternal(
last_used_ = last_modified_ = base::Time::Now();
scoped_ptr<int> result(new int());
- Closure task = base::Bind(&SimpleSynchronousEntry::WriteSparseData,
- base::Unretained(synchronous_entry_),
- SimpleSynchronousEntry::EntryOperationData(
- sparse_offset, buf_len),
- make_scoped_refptr(buf),
- max_sparse_data_size,
- entry_stat.get(),
- result.get());
+ Closure task = base::Bind(
+ &SimpleSynchronousEntry::WriteSparseData,
+ base::Unretained(synchronous_entry_),
+ SimpleSynchronousEntry::EntryOperationData(sparse_offset, buf_len),
+ base::RetainedRef(buf), max_sparse_data_size, entry_stat.get(),
+ result.get());
Closure reply = base::Bind(&SimpleEntryImpl::WriteSparseOperationComplete,
this,
callback,
@@ -1101,6 +1088,25 @@ void SimpleEntryImpl::GetAvailableRangeInternal(
}
void SimpleEntryImpl::DoomEntryInternal(const CompletionCallback& callback) {
+ if (!backend_) {
+ // If there's no backend, we want to truncate the files rather than delete
+ // them. Removing files will update the entry directory's mtime, which will
+ // likely force a full index rebuild on the next startup; this is clearly an
+ // undesirable cost. Instead, the lesser evil is to set the entry files to
+ // length zero, leaving the invalid entry in the index. On the next attempt
+ // to open the entry, it will fail asynchronously (since the magic numbers
+ // will not be found), and the files will actually be removed.
+ PostTaskAndReplyWithResult(
+ worker_pool_.get(), FROM_HERE,
+ base::Bind(&SimpleSynchronousEntry::TruncateEntryFiles, path_,
+ entry_hash_),
+ base::Bind(&SimpleEntryImpl::DoomOperationComplete, this, callback,
+ // Return to STATE_FAILURE after dooming, since no operation
+ // can succeed on the truncated entry files.
+ STATE_FAILURE));
+ state_ = STATE_IO_PENDING;
+ return;
+ }
PostTaskAndReplyWithResult(
worker_pool_.get(),
FROM_HERE,
@@ -1330,8 +1336,7 @@ void SimpleEntryImpl::DoomOperationComplete(
int result) {
state_ = state_to_restore;
net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_DOOM_END);
- if (!callback.is_null())
- callback.Run(result);
+ PostClientCallback(callback, result);
RunNextOperationIfNeeded();
if (backend_)
backend_->OnDoomComplete(entry_hash_);
diff --git a/chromium/net/disk_cache/simple/simple_entry_impl.h b/chromium/net/disk_cache/simple/simple_entry_impl.h
index df9d240fc11..4d41edc00f2 100644
--- a/chromium/net/disk_cache/simple/simple_entry_impl.h
+++ b/chromium/net/disk_cache/simple/simple_entry_impl.h
@@ -149,9 +149,9 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
~SimpleEntryImpl() override;
// Must be used to invoke a client-provided completion callback for an
- // operation initiated through the backend (e.g. create, open) so that clients
- // don't get notified after they deleted the backend (which they would not
- // expect).
+ // operation initiated through the backend (e.g. create, open, doom) so that
+ // clients don't get notified after they deleted the backend (which they would
+ // not expect).
void PostClientCallback(const CompletionCallback& callback, int result);
// Sets entry to STATE_UNINITIALIZED.
diff --git a/chromium/net/disk_cache/simple/simple_index.cc b/chromium/net/disk_cache/simple/simple_index.cc
index 7df258a1d43..f6ccd3eb1dd 100644
--- a/chromium/net/disk_cache/simple/simple_index.cc
+++ b/chromium/net/disk_cache/simple/simple_index.cc
@@ -153,6 +153,7 @@ SimpleIndex::SimpleIndex(
low_watermark_(0),
eviction_in_progress_(false),
initialized_(false),
+ init_method_(INITIALIZE_METHOD_MAX),
index_file_(std::move(index_file)),
io_thread_(io_thread),
// Creating the callback once so it is reused every time
@@ -425,6 +426,7 @@ void SimpleIndex::MergeInitializingSet(
entries_set_.swap(*index_file_entries);
cache_size_ = merged_cache_size;
initialized_ = true;
+ init_method_ = load_result->init_method;
// The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow the
// merge down much.
diff --git a/chromium/net/disk_cache/simple/simple_index.h b/chromium/net/disk_cache/simple/simple_index.h
index 0946e5b5cf7..ed37bd076f4 100644
--- a/chromium/net/disk_cache/simple/simple_index.h
+++ b/chromium/net/disk_cache/simple/simple_index.h
@@ -78,6 +78,14 @@ static_assert(sizeof(EntryMetadata) == 8, "incorrect metadata size");
class NET_EXPORT_PRIVATE SimpleIndex
: public base::SupportsWeakPtr<SimpleIndex> {
public:
+ // Used in histograms. Please only add entries at the end.
+ enum IndexInitMethod {
+ INITIALIZE_METHOD_RECOVERED = 0,
+ INITIALIZE_METHOD_LOADED = 1,
+ INITIALIZE_METHOD_NEWCACHE = 2,
+ INITIALIZE_METHOD_MAX = 3,
+ };
+
typedef std::vector<uint64_t> HashList;
SimpleIndex(const scoped_refptr<base::SingleThreadTaskRunner>& io_thread,
@@ -138,6 +146,8 @@ class NET_EXPORT_PRIVATE SimpleIndex
// Returns whether the index has been initialized yet.
bool initialized() const { return initialized_; }
+ IndexInitMethod init_method() const { return init_method_; }
+
private:
friend class SimpleIndexTest;
FRIEND_TEST_ALL_PREFIXES(SimpleIndexTest, IndexSizeCorrectOnMerge);
@@ -178,6 +188,7 @@ class NET_EXPORT_PRIVATE SimpleIndex
// initialization.
base::hash_set<uint64_t> removed_entries_;
bool initialized_;
+ IndexInitMethod init_method_;
scoped_ptr<SimpleIndexFile> index_file_;
diff --git a/chromium/net/disk_cache/simple/simple_index_file.cc b/chromium/net/disk_cache/simple/simple_index_file.cc
index 7e80c02fa22..c23d64e6bd8 100644
--- a/chromium/net/disk_cache/simple/simple_index_file.cc
+++ b/chromium/net/disk_cache/simple/simple_index_file.cc
@@ -55,19 +55,10 @@ void UmaRecordIndexFileState(IndexFileState state, net::CacheType cache_type) {
"IndexFileStateOnLoad", cache_type, state, INDEX_STATE_MAX);
}
-// Used in histograms. Please only add new values at the end.
-enum IndexInitMethod {
- INITIALIZE_METHOD_RECOVERED = 0,
- INITIALIZE_METHOD_LOADED = 1,
- INITIALIZE_METHOD_NEWCACHE = 2,
- INITIALIZE_METHOD_MAX = 3,
-};
-
-void UmaRecordIndexInitMethod(IndexInitMethod method,
+void UmaRecordIndexInitMethod(SimpleIndex::IndexInitMethod method,
net::CacheType cache_type) {
- SIMPLE_CACHE_UMA(ENUMERATION,
- "IndexInitializeMethod", cache_type,
- method, INITIALIZE_METHOD_MAX);
+ SIMPLE_CACHE_UMA(ENUMERATION, "IndexInitializeMethod", cache_type, method,
+ SimpleIndex::INITIALIZE_METHOD_MAX);
}
bool WritePickleFile(base::Pickle* pickle, const base::FilePath& file_name) {
@@ -320,7 +311,8 @@ void SimpleIndexFile::SyncLoadIndexEntries(
} else {
UmaRecordIndexFileState(INDEX_STATE_FRESH, cache_type);
}
- UmaRecordIndexInitMethod(INITIALIZE_METHOD_LOADED, cache_type);
+ out_result->init_method = SimpleIndex::INITIALIZE_METHOD_LOADED;
+ UmaRecordIndexInitMethod(out_result->init_method, cache_type);
return;
}
UmaRecordIndexFileState(INDEX_STATE_STALE, cache_type);
@@ -334,13 +326,15 @@ void SimpleIndexFile::SyncLoadIndexEntries(
SIMPLE_CACHE_UMA(COUNTS, "IndexEntriesRestored", cache_type,
out_result->entries.size());
if (index_file_existed) {
- UmaRecordIndexInitMethod(INITIALIZE_METHOD_RECOVERED, cache_type);
+ out_result->init_method = SimpleIndex::INITIALIZE_METHOD_RECOVERED;
+
} else {
- UmaRecordIndexInitMethod(INITIALIZE_METHOD_NEWCACHE, cache_type);
+ out_result->init_method = SimpleIndex::INITIALIZE_METHOD_NEWCACHE;
SIMPLE_CACHE_UMA(COUNTS,
"IndexCreatedEntryCount", cache_type,
out_result->entries.size());
}
+ UmaRecordIndexInitMethod(out_result->init_method, cache_type);
}
// static
@@ -423,10 +417,7 @@ void SimpleIndexFile::Deserialize(const char* data, int data_len,
return;
}
-#if !defined(OS_WIN)
- // TODO(gavinp): Consider using std::unordered_map.
- entries->resize(index_metadata.GetNumberOfEntries() + kExtraSizeForMerge);
-#endif
+ entries->reserve(index_metadata.GetNumberOfEntries() + kExtraSizeForMerge);
while (entries->size() < index_metadata.GetNumberOfEntries()) {
uint64_t hash_key;
EntryMetadata entry_metadata;
diff --git a/chromium/net/disk_cache/simple/simple_index_file.h b/chromium/net/disk_cache/simple/simple_index_file.h
index eb13301168b..a5db59af2bc 100644
--- a/chromium/net/disk_cache/simple/simple_index_file.h
+++ b/chromium/net/disk_cache/simple/simple_index_file.h
@@ -37,6 +37,7 @@ struct NET_EXPORT_PRIVATE SimpleIndexLoadResult {
bool did_load;
SimpleIndex::EntrySet entries;
+ SimpleIndex::IndexInitMethod init_method;
bool flush_required;
};
diff --git a/chromium/net/disk_cache/simple/simple_synchronous_entry.cc b/chromium/net/disk_cache/simple/simple_synchronous_entry.cc
index 3fdb3cca345..220f6a8fea8 100644
--- a/chromium/net/disk_cache/simple/simple_synchronous_entry.cc
+++ b/chromium/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -111,6 +111,18 @@ bool CanOmitEmptyFile(int file_index) {
return file_index == disk_cache::simple_util::GetFileIndexFromStreamIndex(2);
}
+bool TruncatePath(const FilePath& filename_to_truncate) {
+ File file_to_truncate;
+ int flags = File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE |
+ File::FLAG_SHARE_DELETE;
+ file_to_truncate.Initialize(filename_to_truncate, flags);
+ if (!file_to_truncate.IsValid())
+ return false;
+ if (!file_to_truncate.SetLength(0))
+ return false;
+ return true;
+}
+
} // namespace
namespace disk_cache {
@@ -264,6 +276,13 @@ int SimpleSynchronousEntry::DoomEntry(const FilePath& path,
}
// static
+int SimpleSynchronousEntry::TruncateEntryFiles(const base::FilePath& path,
+ uint64_t entry_hash) {
+ const bool deleted_well = TruncateFilesForEntryHash(path, entry_hash);
+ return deleted_well ? net::OK : net::ERR_FAILED;
+}
+
+// static
int SimpleSynchronousEntry::DoomEntrySet(
const std::vector<uint64_t>* key_hashes,
const FilePath& path) {
@@ -1160,6 +1179,23 @@ bool SimpleSynchronousEntry::DeleteFilesForEntryHash(
return result;
}
+// static
+bool SimpleSynchronousEntry::TruncateFilesForEntryHash(
+ const FilePath& path,
+ const uint64_t entry_hash) {
+ bool result = true;
+ for (int i = 0; i < kSimpleEntryFileCount; ++i) {
+ FilePath filename_to_truncate =
+ path.AppendASCII(GetFilenameFromEntryHashAndFileIndex(entry_hash, i));
+ if (!TruncatePath(filename_to_truncate))
+ result = false;
+ }
+ FilePath to_delete =
+ path.AppendASCII(GetSparseFilenameFromEntryHash(entry_hash));
+ TruncatePath(to_delete);
+ return result;
+}
+
void SimpleSynchronousEntry::RecordSyncCreateResult(CreateEntryResult result,
bool had_index) {
DCHECK_LT(result, CREATE_ENTRY_MAX);
diff --git a/chromium/net/disk_cache/simple/simple_synchronous_entry.h b/chromium/net/disk_cache/simple/simple_synchronous_entry.h
index 6386a451235..963f665b931 100644
--- a/chromium/net/disk_cache/simple/simple_synchronous_entry.h
+++ b/chromium/net/disk_cache/simple/simple_synchronous_entry.h
@@ -132,6 +132,13 @@ class SimpleSynchronousEntry {
// executed through that instance). Returns a net error code.
static int DoomEntry(const base::FilePath& path, uint64_t entry_hash);
+ // Like |DoomEntry()| above, except that it truncates the entry files rather
+ // than deleting them. Used when dooming entries after the backend has
+ // shutdown. See implementation of |SimpleEntryImpl::DoomEntryInternal()| for
+ // more.
+ static int TruncateEntryFiles(const base::FilePath& path,
+ uint64_t entry_hash);
+
// Like |DoomEntry()| above. Deletes all entries corresponding to the
// |key_hashes|. Succeeds only when all entries are deleted. Returns a net
// error code.
@@ -299,6 +306,8 @@ class SimpleSynchronousEntry {
int file_index);
static bool DeleteFilesForEntryHash(const base::FilePath& path,
uint64_t entry_hash);
+ static bool TruncateFilesForEntryHash(const base::FilePath& path,
+ uint64_t entry_hash);
void RecordSyncCreateResult(CreateEntryResult result, bool had_index);
diff --git a/chromium/net/dns/address_sorter_posix.cc b/chromium/net/dns/address_sorter_posix.cc
index f0a04225c35..479748a0688 100644
--- a/chromium/net/dns/address_sorter_posix.cc
+++ b/chromium/net/dns/address_sorter_posix.cc
@@ -56,13 +56,13 @@ AddressSorterPosix::PolicyTable LoadPolicy(
// Search |table| for matching prefix of |address|. |table| must be sorted by
// descending prefix (prefix of another prefix must be later in table).
unsigned GetPolicyValue(const AddressSorterPosix::PolicyTable& table,
- const IPAddressNumber& address) {
- if (address.size() == kIPv4AddressSize)
- return GetPolicyValue(table, ConvertIPv4NumberToIPv6Number(address));
+ const IPAddress& address) {
+ if (address.IsIPv4())
+ return GetPolicyValue(table, ConvertIPv4ToIPv4MappedIPv6(address));
for (unsigned i = 0; i < table.size(); ++i) {
const AddressSorterPosix::PolicyEntry& entry = table[i];
- IPAddressNumber prefix(entry.prefix, entry.prefix + kIPv6AddressSize);
- if (IPNumberMatchesPrefix(address, prefix, entry.prefix_length))
+ IPAddress prefix(entry.prefix);
+ if (IPAddressMatchesPrefix(address, prefix, entry.prefix_length))
return entry.value;
}
NOTREACHED();
@@ -70,43 +70,39 @@ unsigned GetPolicyValue(const AddressSorterPosix::PolicyTable& table,
return table.back().value;
}
-bool IsIPv6Multicast(const IPAddressNumber& address) {
- DCHECK_EQ(kIPv6AddressSize, address.size());
- return address[0] == 0xFF;
+bool IsIPv6Multicast(const IPAddress& address) {
+ DCHECK(address.IsIPv6());
+ return address.bytes()[0] == 0xFF;
}
AddressSorterPosix::AddressScope GetIPv6MulticastScope(
- const IPAddressNumber& address) {
- DCHECK_EQ(kIPv6AddressSize, address.size());
- return static_cast<AddressSorterPosix::AddressScope>(address[1] & 0x0F);
+ const IPAddress& address) {
+ DCHECK(address.IsIPv6());
+ return static_cast<AddressSorterPosix::AddressScope>(address.bytes()[1] &
+ 0x0F);
}
-bool IsIPv6Loopback(const IPAddressNumber& address) {
- DCHECK_EQ(kIPv6AddressSize, address.size());
- // IN6_IS_ADDR_LOOPBACK
- unsigned char kLoopback[kIPv6AddressSize] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1,
- };
- return address == IPAddressNumber(kLoopback, kLoopback + kIPv6AddressSize);
+bool IsIPv6Loopback(const IPAddress& address) {
+ DCHECK(address.IsIPv6());
+ return address == IPAddress::IPv6Localhost();
}
-bool IsIPv6LinkLocal(const IPAddressNumber& address) {
- DCHECK_EQ(kIPv6AddressSize, address.size());
+bool IsIPv6LinkLocal(const IPAddress& address) {
+ DCHECK(address.IsIPv6());
// IN6_IS_ADDR_LINKLOCAL
- return (address[0] == 0xFE) && ((address[1] & 0xC0) == 0x80);
+ return (address.bytes()[0] == 0xFE) && ((address.bytes()[1] & 0xC0) == 0x80);
}
-bool IsIPv6SiteLocal(const IPAddressNumber& address) {
- DCHECK_EQ(kIPv6AddressSize, address.size());
+bool IsIPv6SiteLocal(const IPAddress& address) {
+ DCHECK(address.IsIPv6());
// IN6_IS_ADDR_SITELOCAL
- return (address[0] == 0xFE) && ((address[1] & 0xC0) == 0xC0);
+ return (address.bytes()[0] == 0xFE) && ((address.bytes()[1] & 0xC0) == 0xC0);
}
AddressSorterPosix::AddressScope GetScope(
const AddressSorterPosix::PolicyTable& ipv4_scope_table,
- const IPAddressNumber& address) {
- if (address.size() == kIPv6AddressSize) {
+ const IPAddress& address) {
+ if (address.IsIPv6()) {
if (IsIPv6Multicast(address)) {
return GetIPv6MulticastScope(address);
} else if (IsIPv6Loopback(address) || IsIPv6LinkLocal(address)) {
@@ -116,7 +112,7 @@ AddressSorterPosix::AddressScope GetScope(
} else {
return AddressSorterPosix::SCOPE_GLOBAL;
}
- } else if (address.size() == kIPv4AddressSize) {
+ } else if (address.IsIPv4()) {
return static_cast<AddressSorterPosix::AddressScope>(
GetPolicyValue(ipv4_scope_table, address));
} else {
@@ -178,7 +174,7 @@ AddressSorterPosix::PolicyEntry kDefaultIPv4ScopeTable[] = {
};
struct DestinationInfo {
- IPAddressNumber address;
+ IPAddress address;
AddressSorterPosix::AddressScope scope;
unsigned precedence;
unsigned label;
@@ -302,9 +298,9 @@ void AddressSorterPosix::Sort(const AddressList& list,
info->src = &src_info;
if (info->address.size() == src.address().size()) {
- info->common_prefix_length = std::min(
- CommonPrefixLength(info->address, src.address()),
- info->src->prefix_length);
+ info->common_prefix_length =
+ std::min(CommonPrefixLength(info->address, src.address()),
+ info->src->prefix_length);
}
sort_list.push_back(std::move(info));
}
@@ -329,7 +325,7 @@ void AddressSorterPosix::OnIPAddressChanged() {
typedef internal::AddressTrackerLinux::AddressMap AddressMap;
AddressMap map = tracker->GetAddressMap();
for (AddressMap::const_iterator it = map.begin(); it != map.end(); ++it) {
- const IPAddressNumber& address = it->first;
+ const IPAddress& address = it->first;
const struct ifaddrmsg& msg = it->second;
SourceAddressInfo& info = source_map_[address];
info.native = false; // TODO(szym): obtain this via netlink.
@@ -387,7 +383,7 @@ void AddressSorterPosix::OnIPAddressChanged() {
#endif
}
-void AddressSorterPosix::FillPolicy(const IPAddressNumber& address,
+void AddressSorterPosix::FillPolicy(const IPAddress& address,
SourceAddressInfo* info) const {
DCHECK(CalledOnValidThread());
info->scope = GetScope(ipv4_scope_table_, address);
diff --git a/chromium/net/dns/address_sorter_posix.h b/chromium/net/dns/address_sorter_posix.h
index 06d2dd8dd5f..3f3840ed0de 100644
--- a/chromium/net/dns/address_sorter_posix.h
+++ b/chromium/net/dns/address_sorter_posix.h
@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/threading/non_thread_safe.h"
#include "net/base/address_list.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "net/base/net_export.h"
#include "net/base/network_change_notifier.h"
#include "net/dns/address_sorter.h"
@@ -58,7 +58,7 @@ class NET_EXPORT_PRIVATE AddressSorterPosix
bool native;
};
- typedef std::map<IPAddressNumber, SourceAddressInfo> SourceAddressMap;
+ typedef std::map<IPAddress, SourceAddressInfo> SourceAddressMap;
explicit AddressSorterPosix(ClientSocketFactory* socket_factory);
~AddressSorterPosix() override;
@@ -74,8 +74,7 @@ class NET_EXPORT_PRIVATE AddressSorterPosix
void OnIPAddressChanged() override;
// Fills |info| with values for |address| from policy tables.
- void FillPolicy(const IPAddressNumber& address,
- SourceAddressInfo* info) const;
+ void FillPolicy(const IPAddress& address, SourceAddressInfo* info) const;
// Mutable to allow using default values for source addresses which were not
// found in most recent OnIPAddressChanged.
diff --git a/chromium/net/dns/address_sorter_posix_unittest.cc b/chromium/net/dns/address_sorter_posix_unittest.cc
index 13778ebefee..c10745bb92d 100644
--- a/chromium/net/dns/address_sorter_posix_unittest.cc
+++ b/chromium/net/dns/address_sorter_posix_unittest.cc
@@ -7,8 +7,8 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/test_completion_callback.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/ssl_client_socket.h"
@@ -20,11 +20,11 @@ namespace net {
namespace {
// Used to map destination address to source address.
-typedef std::map<IPAddressNumber, IPAddressNumber> AddressMapping;
+typedef std::map<IPAddress, IPAddress> AddressMapping;
-IPAddressNumber ParseIP(const std::string& str) {
- IPAddressNumber addr;
- CHECK(ParseIPLiteralToNumber(str, &addr));
+IPAddress ParseIP(const std::string& str) {
+ IPAddress addr;
+ CHECK(addr.AssignFromIPLiteral(str));
return addr;
}
@@ -58,11 +58,12 @@ class TestUDPClientSocket : public DatagramClientSocket {
*address = local_endpoint_;
return OK;
}
- int BindToNetwork(NetworkChangeNotifier::NetworkHandle network) override {
+ int ConnectUsingNetwork(NetworkChangeNotifier::NetworkHandle network,
+ const IPEndPoint& address) override {
NOTIMPLEMENTED();
return ERR_NOT_IMPLEMENTED;
}
- int BindToDefaultNetwork() override {
+ int ConnectUsingDefaultNetwork(const IPEndPoint& address) override {
NOTIMPLEMENTED();
return ERR_NOT_IMPLEMENTED;
}
@@ -122,7 +123,7 @@ class TestSocketFactory : public ClientSocketFactory {
}
void ClearSSLSessionCache() override { NOTIMPLEMENTED(); }
- void AddMapping(const IPAddressNumber& dst, const IPAddressNumber& src) {
+ void AddMapping(const IPAddress& dst, const IPAddress& src) {
mapping_[dst] = src;
}
@@ -154,7 +155,7 @@ class AddressSorterPosixTest : public testing::Test {
AddressSorterPosix::SourceAddressInfo* GetSourceInfo(
const std::string& addr) {
- IPAddressNumber address = ParseIP(addr);
+ IPAddress address = ParseIP(addr);
AddressSorterPosix::SourceAddressInfo* info = &sorter_.source_map_[address];
if (info->scope == AddressSorterPosix::SCOPE_UNDEFINED)
sorter_.FillPolicy(address, info);
diff --git a/chromium/net/dns/address_sorter_unittest.cc b/chromium/net/dns/address_sorter_unittest.cc
index 0c2be884d29..ec27a2f9b3f 100644
--- a/chromium/net/dns/address_sorter_unittest.cc
+++ b/chromium/net/dns/address_sorter_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "net/base/address_list.h"
-#include "net/base/net_util.h"
+#include "net/base/ip_address.h"
#include "net/base/test_completion_callback.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -23,8 +23,8 @@ namespace net {
namespace {
IPEndPoint MakeEndPoint(const std::string& str) {
- IPAddressNumber addr;
- CHECK(ParseIPLiteralToNumber(str, &addr));
+ IPAddress addr;
+ CHECK(addr.AssignFromIPLiteral(str));
return IPEndPoint(addr, 0);
}
diff --git a/chromium/net/dns/address_sorter_win.cc b/chromium/net/dns/address_sorter_win.cc
index 816b42d0b44..232369887f4 100644
--- a/chromium/net/dns/address_sorter_win.cc
+++ b/chromium/net/dns/address_sorter_win.cc
@@ -12,6 +12,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/free_deleter.h"
#include "base/threading/worker_pool.h"
#include "base/win/windows_version.h"
#include "net/base/address_list.h"
@@ -60,7 +61,7 @@ class AddressSorterWin : public AddressSorter {
IPEndPoint ipe = list[i];
// Addresses must be sockaddr_in6.
if (ipe.GetFamily() == ADDRESS_FAMILY_IPV4) {
- ipe = IPEndPoint(ConvertIPv4NumberToIPv6Number(ipe.address()),
+ ipe = IPEndPoint(ConvertIPv4NumberToIPv6Number(ipe.address().bytes()),
ipe.port());
}
@@ -116,9 +117,9 @@ class AddressSorterWin : public AddressSorter {
DCHECK(result) << "Unable to roundtrip between IPEndPoint and "
<< "SOCKET_ADDRESS!";
// Unmap V4MAPPED IPv6 addresses so that Happy Eyeballs works.
- if (IsIPv4Mapped(ipe.address())) {
- ipe = IPEndPoint(ConvertIPv4MappedToIPv4(ipe.address()),
- ipe.port());
+ if (IsIPv4Mapped(ipe.address().bytes())) {
+ ipe = IPEndPoint(ConvertIPv4MappedToIPv4(ipe.address().bytes()),
+ ipe.port());
}
list.push_back(ipe);
}
diff --git a/chromium/net/dns/dns_config_service.cc b/chromium/net/dns/dns_config_service.cc
index fbb429ade1e..e30ed7a23de 100644
--- a/chromium/net/dns/dns_config_service.cc
+++ b/chromium/net/dns/dns_config_service.cc
@@ -12,100 +12,21 @@
namespace net {
-NameServerClassifier::NameServerClassifier() {
- // Google Public DNS addresses from:
- // https://developers.google.com/speed/public-dns/docs/using
- AddRule("8.8.8.8", NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS);
- AddRule("8.8.4.4", NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS);
- AddRule("2001:4860:4860:0:0:0:0:8888", NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS),
- AddRule("2001:4860:4860:0:0:0:0:8844", NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS),
-
- // Count localhost as private, since we don't know what upstream it uses:
- AddRule("127.*.*.*", NAME_SERVERS_TYPE_PRIVATE);
- AddRule("0:0:0:0:0:0:0:1", NAME_SERVERS_TYPE_PRIVATE);
-
- // RFC 1918 private addresses:
- AddRule("10.*.*.*", NAME_SERVERS_TYPE_PRIVATE);
- AddRule("172.[16-31].*.*", NAME_SERVERS_TYPE_PRIVATE);
- AddRule("192.168.*.*", NAME_SERVERS_TYPE_PRIVATE);
-
- // IPv4 link-local addresses:
- AddRule("169.254.*.*", NAME_SERVERS_TYPE_PRIVATE);
-
- // IPv6 link-local addresses:
- AddRule("fe80:*:*:*:*:*:*:*", NAME_SERVERS_TYPE_PRIVATE);
-
- // Anything else counts as public:
- AddRule("*.*.*.*", NAME_SERVERS_TYPE_PUBLIC);
- AddRule("*:*:*:*:*:*:*:*", NAME_SERVERS_TYPE_PUBLIC);
-}
-
-NameServerClassifier::~NameServerClassifier() {}
-
-NameServerClassifier::NameServersType NameServerClassifier::GetNameServersType(
- const std::vector<IPEndPoint>& nameservers) const {
- NameServersType type = NAME_SERVERS_TYPE_NONE;
- for (std::vector<IPEndPoint>::const_iterator it = nameservers.begin();
- it != nameservers.end();
- ++it) {
- type = MergeNameServersTypes(type, GetNameServerType(it->address()));
- }
- return type;
-}
-
-struct NameServerClassifier::NameServerTypeRule {
- NameServerTypeRule(const char* pattern_string, NameServersType type)
- : type(type) {
- bool parsed = pattern.ParsePattern(pattern_string);
- DCHECK(parsed);
- }
-
- IPPattern pattern;
- NameServersType type;
-};
-
-void NameServerClassifier::AddRule(const char* pattern_string,
- NameServersType address_type) {
- rules_.push_back(new NameServerTypeRule(pattern_string, address_type));
-}
-
-NameServerClassifier::NameServersType NameServerClassifier::GetNameServerType(
- const IPAddressNumber& address) const {
- for (ScopedVector<NameServerTypeRule>::const_iterator it = rules_.begin();
- it != rules_.end();
- ++it) {
- if ((*it)->pattern.Match(address))
- return (*it)->type;
- }
- NOTREACHED();
- return NAME_SERVERS_TYPE_NONE;
-}
-
-NameServerClassifier::NameServersType
-NameServerClassifier::MergeNameServersTypes(NameServersType a,
- NameServersType b) {
- if (a == NAME_SERVERS_TYPE_NONE)
- return b;
- if (b == NAME_SERVERS_TYPE_NONE)
- return a;
- if (a == b)
- return a;
- return NAME_SERVERS_TYPE_MIXED;
-}
-
// Default values are taken from glibc resolv.h except timeout which is set to
-// |kDnsTimeoutSeconds|.
+// |kDnsDefaultTimeoutMs|.
DnsConfig::DnsConfig()
: unhandled_options(false),
append_to_multi_label_name(true),
randomize_ports(false),
ndots(1),
- timeout(base::TimeDelta::FromSeconds(kDnsTimeoutSeconds)),
+ timeout(base::TimeDelta::FromMilliseconds(kDnsDefaultTimeoutMs)),
attempts(2),
rotate(false),
edns0(false),
use_local_ipv6(false) {}
+DnsConfig::DnsConfig(const DnsConfig& other) = default;
+
DnsConfig::~DnsConfig() {}
bool DnsConfig::Equals(const DnsConfig& d) const {
@@ -234,10 +155,6 @@ void DnsConfigService::OnConfigRead(const DnsConfig& config) {
base::TimeTicks::Now() - last_sent_empty_time_);
}
UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigChange", changed);
- UMA_HISTOGRAM_ENUMERATION(
- "AsyncDNS.NameServersType",
- classifier_.GetNameServersType(dns_config_.nameservers),
- NameServerClassifier::NAME_SERVERS_TYPE_MAX_VALUE);
have_config_ = true;
if (have_hosts_ || watch_failed_)
diff --git a/chromium/net/dns/dns_config_service.h b/chromium/net/dns/dns_config_service.h
index fbbdb415e88..e62a5af31fb 100644
--- a/chromium/net/dns/dns_config_service.h
+++ b/chromium/net/dns/dns_config_service.h
@@ -28,44 +28,15 @@ class Value;
namespace net {
-// Always use 1 second timeout (followed by binary exponential backoff).
-// TODO(szym): Remove code which reads timeout from system.
-const unsigned kDnsTimeoutSeconds = 1;
+class IPAddress;
-// Classifies nameserver address lists for histograms.
-class NET_EXPORT_PRIVATE NameServerClassifier {
- public:
- // This is used in a histogram (AsyncDNS.NameServersType); add new entries
- // right before MAX_VALUE.
- enum NameServersType {
- NAME_SERVERS_TYPE_NONE,
- NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS,
- NAME_SERVERS_TYPE_PRIVATE,
- NAME_SERVERS_TYPE_PUBLIC,
- NAME_SERVERS_TYPE_MIXED,
- NAME_SERVERS_TYPE_MAX_VALUE
- };
-
- NameServerClassifier();
- ~NameServerClassifier();
-
- NameServersType GetNameServersType(
- const std::vector<IPEndPoint>& nameservers) const;
-
- private:
- struct NameServerTypeRule;
-
- void AddRule(const char* pattern_string, NameServersType type);
- NameServersType GetNameServerType(const IPAddressNumber& address) const;
- static NameServersType MergeNameServersTypes(NameServersType a,
- NameServersType b);
-
- ScopedVector<NameServerTypeRule> rules_;
-};
+// Default to 1 second timeout (before exponential backoff).
+const int64_t kDnsDefaultTimeoutMs = 1000;
// DnsConfig stores configuration of the system resolver.
struct NET_EXPORT_PRIVATE DnsConfig {
DnsConfig();
+ DnsConfig(const DnsConfig& other);
virtual ~DnsConfig();
bool Equals(const DnsConfig& d) const;
@@ -205,8 +176,6 @@ class NET_EXPORT_PRIVATE DnsConfigService
// Started in Invalidate*, cleared in On*Read.
base::OneShotTimer timer_;
- NameServerClassifier classifier_;
-
DISALLOW_COPY_AND_ASSIGN(DnsConfigService);
};
diff --git a/chromium/net/dns/dns_config_service_posix.cc b/chromium/net/dns/dns_config_service_posix.cc
index 31a40616b05..b12b019635f 100644
--- a/chromium/net/dns/dns_config_service_posix.cc
+++ b/chromium/net/dns/dns_config_service_posix.cc
@@ -18,8 +18,8 @@
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
-#include "net/base/net_util.h"
#include "net/dns/dns_hosts.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/notify_watcher_mac.h"
@@ -150,7 +150,7 @@ ConfigParsePosixResult ReadDnsConfig(DnsConfig* config) {
}
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
// Override timeout value to match default setting on Windows.
- config->timeout = base::TimeDelta::FromSeconds(kDnsTimeoutSeconds);
+ config->timeout = base::TimeDelta::FromMilliseconds(kDnsDefaultTimeoutMs);
return result;
}
#else // defined(OS_ANDROID)
@@ -173,18 +173,18 @@ ConfigParsePosixResult ReadDnsConfig(DnsConfig* dns_config) {
if (dns1_string.length() == 0 && dns2_string.length() == 0)
return CONFIG_PARSE_POSIX_NO_NAMESERVERS;
- IPAddressNumber dns1_number, dns2_number;
- bool parsed1 = ParseIPLiteralToNumber(dns1_string, &dns1_number);
- bool parsed2 = ParseIPLiteralToNumber(dns2_string, &dns2_number);
+ IPAddress dns1_address, dns2_address;
+ bool parsed1 = dns1_address.AssignFromIPLiteral(dns1_string);
+ bool parsed2 = dns2_address.AssignFromIPLiteral(dns2_string);
if (!parsed1 && !parsed2)
return CONFIG_PARSE_POSIX_BAD_ADDRESS;
if (parsed1) {
- IPEndPoint dns1(dns1_number, dns_protocol::kDefaultPort);
+ IPEndPoint dns1(dns1_address, dns_protocol::kDefaultPort);
dns_config->nameservers.push_back(dns1);
}
if (parsed2) {
- IPEndPoint dns2(dns2_number, dns_protocol::kDefaultPort);
+ IPEndPoint dns2(dns2_address, dns_protocol::kDefaultPort);
dns_config->nameservers.push_back(dns2);
}
@@ -542,9 +542,8 @@ ConfigParsePosixResult ConvertResStateToDnsConfig(const struct __res_state& res,
// If any name server is 0.0.0.0, assume the configuration is invalid.
// TODO(szym): Measure how often this happens. http://crbug.com/125599
- const IPAddressNumber kEmptyAddress(kIPv4AddressSize);
for (unsigned i = 0; i < dns_config->nameservers.size(); ++i) {
- if (dns_config->nameservers[i].address() == kEmptyAddress)
+ if (dns_config->nameservers[i].address().IsZero())
return CONFIG_PARSE_POSIX_NULL_ADDRESS;
}
return CONFIG_PARSE_POSIX_OK;
diff --git a/chromium/net/dns/dns_config_service_posix_unittest.cc b/chromium/net/dns/dns_config_service_posix_unittest.cc
index 04384d47a23..38c5cb6d586 100644
--- a/chromium/net/dns/dns_config_service_posix_unittest.cc
+++ b/chromium/net/dns/dns_config_service_posix_unittest.cc
@@ -9,6 +9,7 @@
#include "base/sys_byteorder.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
+#include "net/base/ip_address.h"
#include "net/dns/dns_config_service_posix.h"
#include "net/dns/dns_protocol.h"
@@ -117,8 +118,8 @@ void InitializeExpectedConfig(DnsConfig* config) {
config->nameservers.clear();
for (unsigned i = 0; i < arraysize(kNameserversIPv4) && i < MAXNS; ++i) {
- IPAddressNumber ip;
- ParseIPLiteralToNumber(kNameserversIPv4[i], &ip);
+ IPAddress ip;
+ EXPECT_TRUE(ip.AssignFromIPLiteral(kNameserversIPv4[i]));
config->nameservers.push_back(IPEndPoint(ip, NS_DEFAULTPORT + i));
}
@@ -126,8 +127,8 @@ void InitializeExpectedConfig(DnsConfig* config) {
for (unsigned i = 0; i < arraysize(kNameserversIPv6) && i < MAXNS; ++i) {
if (!kNameserversIPv6[i])
continue;
- IPAddressNumber ip;
- ParseIPLiteralToNumber(kNameserversIPv6[i], &ip);
+ IPAddress ip;
+ EXPECT_TRUE(ip.AssignFromIPLiteral(kNameserversIPv6[i]));
config->nameservers[i] = IPEndPoint(ip, NS_DEFAULTPORT - i);
}
#endif
@@ -211,11 +212,11 @@ class DnsConfigServicePosixTest : public testing::Test {
}
void MockDNSConfig(const char* dns_server) {
- IPAddressNumber dns_number;
- ASSERT_TRUE(ParseIPLiteralToNumber(dns_server, &dns_number));
+ IPAddress dns_address;
+ ASSERT_TRUE(dns_address.AssignFromIPLiteral(dns_server));
test_config_.nameservers.clear();
test_config_.nameservers.push_back(
- IPEndPoint(dns_number, dns_protocol::kDefaultPort));
+ IPEndPoint(dns_address, dns_protocol::kDefaultPort));
service_->SetDnsConfigForTesting(&test_config_);
}
diff --git a/chromium/net/dns/dns_config_service_unittest.cc b/chromium/net/dns/dns_config_service_unittest.cc
index 40796adfb16..ae8e5f6112e 100644
--- a/chromium/net/dns/dns_config_service_unittest.cc
+++ b/chromium/net/dns/dns_config_service_unittest.cc
@@ -13,7 +13,6 @@
#include "base/strings/string_split.h"
#include "base/test/test_timeouts.h"
#include "base/thread_task_runner_handle.h"
-#include "net/base/net_util.h"
#include "net/dns/dns_protocol.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -21,94 +20,6 @@ namespace net {
namespace {
-const NameServerClassifier::NameServersType kNone =
- NameServerClassifier::NAME_SERVERS_TYPE_NONE;
-const NameServerClassifier::NameServersType kGoogle =
- NameServerClassifier::NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS;
-const NameServerClassifier::NameServersType kPrivate =
- NameServerClassifier::NAME_SERVERS_TYPE_PRIVATE;
-const NameServerClassifier::NameServersType kPublic =
- NameServerClassifier::NAME_SERVERS_TYPE_PUBLIC;
-const NameServerClassifier::NameServersType kMixed =
- NameServerClassifier::NAME_SERVERS_TYPE_MIXED;
-
-class NameServerClassifierTest : public testing::Test {
- protected:
- NameServerClassifier::NameServersType Classify(
- const std::string& servers_string) {
- std::vector<IPEndPoint> servers;
- for (const base::StringPiece& server_str :
- base::SplitStringPiece(servers_string, " ", base::TRIM_WHITESPACE,
- base::SPLIT_WANT_ALL)) {
- if (server_str.empty())
- continue;
-
- IPAddressNumber address;
- bool parsed = ParseIPLiteralToNumber(server_str, &address);
- EXPECT_TRUE(parsed);
- servers.push_back(IPEndPoint(address, dns_protocol::kDefaultPort));
- }
-
- return classifier_.GetNameServersType(servers);
- }
-
- private:
- NameServerClassifier classifier_;
-};
-
-TEST_F(NameServerClassifierTest, None) {
- EXPECT_EQ(kNone, Classify(""));
-}
-
-TEST_F(NameServerClassifierTest, Google) {
- EXPECT_EQ(kGoogle, Classify("8.8.8.8"));
- EXPECT_EQ(kGoogle, Classify("8.8.8.8 8.8.4.4"));
- EXPECT_EQ(kGoogle, Classify("2001:4860:4860::8888"));
- EXPECT_EQ(kGoogle, Classify("2001:4860:4860::8888 2001:4860:4860::8844"));
- EXPECT_EQ(kGoogle, Classify("2001:4860:4860::8888 8.8.8.8"));
-
- // Make sure nobody took any shortcuts on the IP matching:
- EXPECT_EQ(kPublic, Classify("8.8.8.4"));
- EXPECT_EQ(kPublic, Classify("8.8.4.8"));
- EXPECT_EQ(kPublic, Classify("2001:4860:4860::8884"));
- EXPECT_EQ(kPublic, Classify("2001:4860:4860::8848"));
- EXPECT_EQ(kPublic, Classify("2001:4860:4860::1:8888"));
- EXPECT_EQ(kPublic, Classify("2001:4860:4860:1::8888"));
-}
-
-TEST_F(NameServerClassifierTest, PrivateLocalhost) {
- EXPECT_EQ(kPrivate, Classify("127.0.0.1"));
- EXPECT_EQ(kPrivate, Classify("::1"));
-}
-
-TEST_F(NameServerClassifierTest, PrivateRfc1918) {
- EXPECT_EQ(kPrivate, Classify("10.0.0.0 10.255.255.255"));
- EXPECT_EQ(kPrivate, Classify("172.16.0.0 172.31.255.255"));
- EXPECT_EQ(kPrivate, Classify("192.168.0.0 192.168.255.255"));
- EXPECT_EQ(kPrivate, Classify("10.1.1.1 172.16.1.1 192.168.1.1"));
-}
-
-TEST_F(NameServerClassifierTest, PrivateIPv4LinkLocal) {
- EXPECT_EQ(kPrivate, Classify("169.254.0.0 169.254.255.255"));
-}
-
-TEST_F(NameServerClassifierTest, PrivateIPv6LinkLocal) {
- EXPECT_EQ(kPrivate,
- Classify("fe80:: fe80:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
-}
-
-TEST_F(NameServerClassifierTest, Public) {
- EXPECT_EQ(kPublic, Classify("4.2.2.1"));
- EXPECT_EQ(kPublic, Classify("4.2.2.1 4.2.2.2"));
-}
-
-TEST_F(NameServerClassifierTest, Mixed) {
- EXPECT_EQ(kMixed, Classify("8.8.8.8 192.168.1.1"));
- EXPECT_EQ(kMixed, Classify("8.8.8.8 4.2.2.1"));
- EXPECT_EQ(kMixed, Classify("192.168.1.1 4.2.2.1"));
- EXPECT_EQ(kMixed, Classify("8.8.8.8 192.168.1.1 4.2.2.1"));
-}
-
class DnsConfigServiceTest : public testing::Test {
public:
void OnConfigChanged(const DnsConfig& config) {
@@ -158,9 +69,8 @@ class DnsConfigServiceTest : public testing::Test {
// Generate a config using the given seed..
DnsConfig MakeConfig(unsigned seed) {
DnsConfig config;
- IPAddressNumber ip;
- CHECK(ParseIPLiteralToNumber("1.2.3.4", &ip));
- config.nameservers.push_back(IPEndPoint(ip, seed & 0xFFFF));
+ config.nameservers.push_back(
+ IPEndPoint(IPAddress(1, 2, 3, 4), seed & 0xFFFF));
EXPECT_TRUE(config.IsValid());
return config;
}
diff --git a/chromium/net/dns/dns_config_service_win.cc b/chromium/net/dns/dns_config_service_win.cc
index 8c3192d90ba..546c78fd407 100644
--- a/chromium/net/dns/dns_config_service_win.cc
+++ b/chromium/net/dns/dns_config_service_win.cc
@@ -14,6 +14,7 @@
#include "base/files/file_path_watcher.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/free_deleter.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_split.h"
@@ -26,15 +27,13 @@
#include "base/win/registry.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h"
-#include "net/base/net_util.h"
+#include "net/base/ip_address.h"
#include "net/base/network_change_notifier.h"
#include "net/dns/dns_hosts.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/serial_worker.h"
#include "url/url_canon.h"
-#pragma comment(lib, "iphlpapi.lib")
-
namespace net {
namespace internal {
@@ -129,7 +128,7 @@ scoped_ptr<IP_ADAPTER_ADDRESSES, base::FreeDeleter> ReadIpHelper(ULONG flags) {
}
if (rv != NO_ERROR)
out.reset();
- return out.Pass();
+ return out;
}
// Converts a base::string16 domain name to ASCII, possibly using punycode.
@@ -221,13 +220,8 @@ ConfigParseWinResult ReadSystemSettings(DnsSystemSettings* settings) {
// Default address of "localhost" and local computer name can be overridden
// by the HOSTS file, but if it's not there, then we need to fill it in.
HostsParseWinResult AddLocalhostEntries(DnsHosts* hosts) {
- const unsigned char kIPv4Localhost[] = { 127, 0, 0, 1 };
- const unsigned char kIPv6Localhost[] = { 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1 };
- IPAddressNumber loopback_ipv4(kIPv4Localhost,
- kIPv4Localhost + arraysize(kIPv4Localhost));
- IPAddressNumber loopback_ipv6(kIPv6Localhost,
- kIPv6Localhost + arraysize(kIPv6Localhost));
+ IPAddress loopback_ipv4 = IPAddress::IPv4Localhost();
+ IPAddress loopback_ipv6 = IPAddress::IPv6Localhost();
// This does not override any pre-existing entries from the HOSTS file.
hosts->insert(std::make_pair(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4),
@@ -331,15 +325,12 @@ class RegistryWatcher : public base::NonThreadSafe {
// Returns true iff |address| is DNS address from IPv6 stateless discovery,
// i.e., matches fec0:0:0:ffff::{1,2,3}.
// http://tools.ietf.org/html/draft-ietf-ipngwg-dns-discovery
-bool IsStatelessDiscoveryAddress(const IPAddressNumber& address) {
- if (address.size() != kIPv6AddressSize)
+bool IsStatelessDiscoveryAddress(const IPAddress& address) {
+ if (!address.IsIPv6())
return false;
- const uint8_t kPrefix[] = {
- 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- };
- return std::equal(kPrefix, kPrefix + arraysize(kPrefix),
- address.begin()) && (address.back() < 4);
+ const uint8_t kPrefix[] = {0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ return IPAddressStartsWith(address, kPrefix) && (address.bytes().back() < 4);
}
// Returns the path to the HOSTS file.
diff --git a/chromium/net/dns/dns_config_service_win.h b/chromium/net/dns/dns_config_service_win.h
index 96d47130ee4..0485afd5f77 100644
--- a/chromium/net/dns/dns_config_service_win.h
+++ b/chromium/net/dns/dns_config_service_win.h
@@ -14,6 +14,7 @@
#include <vector>
#include "base/macros.h"
+#include "base/memory/free_deleter.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
diff --git a/chromium/net/dns/dns_config_service_win_unittest.cc b/chromium/net/dns/dns_config_service_win_unittest.cc
index 3a452bc9d79..30bd418742e 100644
--- a/chromium/net/dns/dns_config_service_win_unittest.cc
+++ b/chromium/net/dns/dns_config_service_win_unittest.cc
@@ -5,7 +5,9 @@
#include "net/dns/dns_config_service_win.h"
#include "base/logging.h"
+#include "base/memory/free_deleter.h"
#include "base/win/windows_version.h"
+#include "net/base/ip_address.h"
#include "net/dns/dns_protocol.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -96,8 +98,8 @@ scoped_ptr<IP_ADAPTER_ADDRESSES, base::FreeDeleter> CreateAdapterAddresses(
// Note that |address| is moving backwards.
address = address->Next = address - 1;
}
- IPAddressNumber ip;
- CHECK(ParseIPLiteralToNumber(info.dns_server_addresses[j], &ip));
+ IPAddress ip;
+ CHECK(ip.AssignFromIPLiteral(info.dns_server_addresses[j]));
IPEndPoint ipe = IPEndPoint(ip, info.ports[j]);
address->Address.lpSockaddr =
reinterpret_cast<LPSOCKADDR>(storage + num_addresses);
@@ -107,7 +109,7 @@ scoped_ptr<IP_ADAPTER_ADDRESSES, base::FreeDeleter> CreateAdapterAddresses(
}
}
- return heap.Pass();
+ return heap;
}
TEST(DnsConfigServiceWinTest, ConvertAdapterAddresses) {
@@ -173,8 +175,8 @@ TEST(DnsConfigServiceWinTest, ConvertAdapterAddresses) {
// Default settings for the rest.
std::vector<IPEndPoint> expected_nameservers;
for (size_t j = 0; !t.expected_nameservers[j].empty(); ++j) {
- IPAddressNumber ip;
- ASSERT_TRUE(ParseIPLiteralToNumber(t.expected_nameservers[j], &ip));
+ IPAddress ip;
+ ASSERT_TRUE(ip.AssignFromIPLiteral(t.expected_nameservers[j]));
uint16_t port = t.expected_ports[j];
if (!port)
port = dns_protocol::kDefaultPort;
diff --git a/chromium/net/dns/dns_hosts.cc b/chromium/net/dns/dns_hosts.cc
index a4f293f6d7e..098c6172511 100644
--- a/chromium/net/dns/dns_hosts.cc
+++ b/chromium/net/dns/dns_hosts.cc
@@ -134,7 +134,7 @@ void ParseHostsWithCommaMode(const std::string& contents,
CHECK(dns_hosts);
StringPiece ip_text;
- IPAddressNumber ip;
+ IPAddress ip;
AddressFamily family = ADDRESS_FAMILY_IPV4;
HostsParser parser(contents, comma_mode);
while (parser.Advance()) {
@@ -144,11 +144,11 @@ void ParseHostsWithCommaMode(const std::string& contents,
// the same IP address (usually 127.0.0.1). Don't bother parsing the IP
// again if it's the same as the one above it.
if (new_ip_text != ip_text) {
- IPAddressNumber new_ip;
- if (ParseIPLiteralToNumber(parser.token().as_string(), &new_ip)) {
+ IPAddress new_ip;
+ if (new_ip.AssignFromIPLiteral(parser.token())) {
ip_text = new_ip_text;
- ip.swap(new_ip);
- family = (ip.size() == 4) ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6;
+ ip = new_ip;
+ family = (ip.IsIPv4()) ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6;
} else {
parser.SkipRestOfLine();
}
@@ -156,7 +156,7 @@ void ParseHostsWithCommaMode(const std::string& contents,
} else {
DnsHostsKey key(parser.token().as_string(), family);
key.first = base::ToLowerASCII(key.first);
- IPAddressNumber* mapped_ip = &(*dns_hosts)[key];
+ IPAddress* mapped_ip = &(*dns_hosts)[key];
if (mapped_ip->empty())
*mapped_ip = ip;
// else ignore this entry (first hit counts)
diff --git a/chromium/net/dns/dns_hosts.h b/chromium/net/dns/dns_hosts.h
index d8ece2cd48e..2ce7c52dc16 100644
--- a/chromium/net/dns/dns_hosts.h
+++ b/chromium/net/dns/dns_hosts.h
@@ -15,7 +15,7 @@
#include "base/containers/hash_tables.h"
#include "base/files/file_path.h"
#include "net/base/address_family.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "net/base/net_export.h"
namespace net {
@@ -27,8 +27,7 @@ namespace BASE_HASH_NAMESPACE {
template<>
struct hash<net::DnsHostsKey> {
std::size_t operator()(const net::DnsHostsKey& key) const {
- hash<base::StringPiece> string_piece_hash;
- return string_piece_hash(key.first) + key.second;
+ return base::StringPieceHash()(key.first) + key.second;
}
};
@@ -58,11 +57,11 @@ enum ParseHostsCommaMode {
// 10.0.0.1 localhost
// The expected resolution of localhost is 127.0.0.1.
#if !defined(OS_ANDROID)
-typedef base::hash_map<DnsHostsKey, IPAddressNumber> DnsHosts;
+typedef base::hash_map<DnsHostsKey, IPAddress> DnsHosts;
#else
// Android's hash_map doesn't support ==, so fall back to map. (Chromium on
// Android doesn't use the built-in DNS resolver anyway, so it's irrelevant.)
-typedef std::map<DnsHostsKey, IPAddressNumber> DnsHosts;
+typedef std::map<DnsHostsKey, IPAddress> DnsHosts;
#endif
// Parses |contents| (as read from /etc/hosts or equivalent) and stores results
diff --git a/chromium/net/dns/dns_hosts_unittest.cc b/chromium/net/dns/dns_hosts_unittest.cc
index 1bce190ce4d..9e52f0e229a 100644
--- a/chromium/net/dns/dns_hosts_unittest.cc
+++ b/chromium/net/dns/dns_hosts_unittest.cc
@@ -4,6 +4,7 @@
#include "net/dns/dns_hosts.h"
+#include "net/base/ip_address.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -21,9 +22,9 @@ void PopulateExpectedHosts(const ExpectedHostsEntry* entries,
DnsHosts* expected_hosts_out) {
for (size_t i = 0; i < num_entries; ++i) {
DnsHostsKey key(entries[i].host, entries[i].family);
- IPAddressNumber& ip_ref = (*expected_hosts_out)[key];
+ IPAddress& ip_ref = (*expected_hosts_out)[key];
ASSERT_TRUE(ip_ref.empty());
- ASSERT_TRUE(ParseIPLiteralToNumber(entries[i].ip, &ip_ref));
+ ASSERT_TRUE(ip_ref.AssignFromIPLiteral(entries[i].ip));
ASSERT_EQ(ip_ref.size(),
(entries[i].family == ADDRESS_FAMILY_IPV4) ? 4u : 16u);
}
diff --git a/chromium/net/dns/dns_query.cc b/chromium/net/dns/dns_query.cc
index 76e2b56efb2..b5ebd46f761 100644
--- a/chromium/net/dns/dns_query.cc
+++ b/chromium/net/dns/dns_query.cc
@@ -17,14 +17,15 @@ namespace net {
// bit, which directs the name server to pursue query recursively, and sets
// the QDCOUNT to 1, meaning the question section has a single entry.
DnsQuery::DnsQuery(uint16_t id, const base::StringPiece& qname, uint16_t qtype)
- : qname_size_(qname.size()) {
+ : qname_size_(qname.size()),
+ io_buffer_(
+ new IOBufferWithSize(sizeof(dns_protocol::Header) + question_size())),
+ header_(reinterpret_cast<dns_protocol::Header*>(io_buffer_->data())) {
DCHECK(!DNSDomainToString(qname).empty());
- io_buffer_ = new IOBufferWithSize(sizeof(dns_protocol::Header) +
- question_size());
- *header() = {};
- header()->id = base::HostToNet16(id);
- header()->flags = base::HostToNet16(dns_protocol::kFlagRD);
- header()->qdcount = base::HostToNet16(1);
+ *header_ = {};
+ header_->id = base::HostToNet16(id);
+ header_->flags = base::HostToNet16(dns_protocol::kFlagRD);
+ header_->qdcount = base::HostToNet16(1);
// Write question section after the header.
base::BigEndianWriter writer(
@@ -42,9 +43,7 @@ scoped_ptr<DnsQuery> DnsQuery::CloneWithNewId(uint16_t id) const {
}
uint16_t DnsQuery::id() const {
- const dns_protocol::Header* header =
- reinterpret_cast<const dns_protocol::Header*>(io_buffer_->data());
- return base::NetToHost16(header->id);
+ return base::NetToHost16(header_->id);
}
base::StringPiece DnsQuery::qname() const {
@@ -65,7 +64,7 @@ base::StringPiece DnsQuery::question() const {
}
void DnsQuery::set_flags(uint16_t flags) {
- header()->flags = flags;
+ header_->flags = flags;
}
DnsQuery::DnsQuery(const DnsQuery& orig, uint16_t id) {
@@ -73,11 +72,8 @@ DnsQuery::DnsQuery(const DnsQuery& orig, uint16_t id) {
io_buffer_ = new IOBufferWithSize(orig.io_buffer()->size());
memcpy(io_buffer_.get()->data(), orig.io_buffer()->data(),
io_buffer_.get()->size());
- header()->id = base::HostToNet16(id);
-}
-
-dns_protocol::Header* DnsQuery::header() {
- return reinterpret_cast<dns_protocol::Header*>(io_buffer_->data());
+ header_ = reinterpret_cast<dns_protocol::Header*>(io_buffer_->data());
+ header_->id = base::HostToNet16(id);
}
} // namespace net
diff --git a/chromium/net/dns/dns_query.h b/chromium/net/dns/dns_query.h
index 77d5200a798..8547570ac48 100644
--- a/chromium/net/dns/dns_query.h
+++ b/chromium/net/dns/dns_query.h
@@ -51,9 +51,6 @@ class NET_EXPORT_PRIVATE DnsQuery {
private:
DnsQuery(const DnsQuery& orig, uint16_t id);
- // Convenience for header access.
- dns_protocol::Header* header();
-
// Returns the size of the question section.
size_t question_size() const {
// QNAME + QTYPE + QCLASS
@@ -67,6 +64,9 @@ class NET_EXPORT_PRIVATE DnsQuery {
// Contains query bytes to be consumed by higher level Write() call.
scoped_refptr<IOBufferWithSize> io_buffer_;
+ // Pointer to the dns header section.
+ dns_protocol::Header* header_;
+
DISALLOW_COPY_AND_ASSIGN(DnsQuery);
};
diff --git a/chromium/net/dns/dns_record_fuzzer.cc b/chromium/net/dns/dns_record_fuzzer.cc
new file mode 100644
index 00000000000..dfcaf03ec86
--- /dev/null
+++ b/chromium/net/dns/dns_record_fuzzer.cc
@@ -0,0 +1,20 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include "net/dns/dns_response.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ net::DnsRecordParser parser(data, size, 0);
+ if (!parser.IsValid()) {
+ return 0;
+ }
+ net::DnsResourceRecord record;
+ while (parser.ReadRecord(&record)) {
+ }
+ return 0;
+}
diff --git a/chromium/net/dns/dns_response.cc b/chromium/net/dns/dns_response.cc
index c11b8a9c8af..98967899156 100644
--- a/chromium/net/dns/dns_response.cc
+++ b/chromium/net/dns/dns_response.cc
@@ -11,6 +11,7 @@
#include "base/sys_byteorder.h"
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/dns_query.h"
@@ -290,7 +291,8 @@ DnsResponse::Result DnsResponse::ParseToAddressList(
expected_type == dns_protocol::kTypeAAAA);
size_t expected_size = (expected_type == dns_protocol::kTypeAAAA)
- ? kIPv6AddressSize : kIPv4AddressSize;
+ ? IPAddress::kIPv6AddressSize
+ : IPAddress::kIPv4AddressSize;
uint32_t ttl_sec = std::numeric_limits<uint32_t>::max();
IPAddressList ip_addresses;
@@ -322,8 +324,9 @@ DnsResponse::Result DnsResponse::ParseToAddressList(
return DNS_NAME_MISMATCH;
ttl_sec = std::min(ttl_sec, record.ttl);
- ip_addresses.push_back(IPAddressNumber(record.rdata.begin(),
- record.rdata.end()));
+ ip_addresses.push_back(
+ IPAddress(reinterpret_cast<const uint8_t*>(record.rdata.data()),
+ record.rdata.length()));
}
}
diff --git a/chromium/net/dns/dns_response_unittest.cc b/chromium/net/dns/dns_response_unittest.cc
index e701c9a9eca..46f50ed2459 100644
--- a/chromium/net/dns/dns_response_unittest.cc
+++ b/chromium/net/dns/dns_response_unittest.cc
@@ -7,7 +7,6 @@
#include "base/time/time.h"
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
-#include "net/base/net_util.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/dns_query.h"
#include "net/dns/dns_test_util.h"
diff --git a/chromium/net/dns/dns_session.cc b/chromium/net/dns/dns_session.cc
index 5148e0b878b..6a43eb08ca8 100644
--- a/chromium/net/dns/dns_session.cc
+++ b/chromium/net/dns/dns_session.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
+#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sample_vector.h"
#include "base/rand_util.h"
@@ -20,21 +21,28 @@
#include "net/base/net_errors.h"
#include "net/dns/dns_config_service.h"
#include "net/dns/dns_socket_pool.h"
+#include "net/dns/dns_util.h"
#include "net/socket/stream_socket.h"
#include "net/udp/datagram_client_socket.h"
namespace net {
namespace {
-// Never exceed max timeout.
-const unsigned kMaxTimeoutMs = 5000;
+
// Set min timeout, in case we are talking to a local DNS proxy.
const unsigned kMinTimeoutMs = 10;
+// Default maximum timeout between queries, even with exponential backoff.
+// (Can be overridden by field trial.)
+const unsigned kDefaultMaxTimeoutMs = 5000;
+
+// Maximum RTT that will fit in the RTT histograms.
+const int32_t kRTTMaxMs = 30000;
// Number of buckets in the histogram of observed RTTs.
-const size_t kRTTBucketCount = 100;
+const size_t kRTTBucketCount = 350;
// Target percentile in the RTT histogram used for retransmission timeout.
const unsigned kRTOPercentile = 99;
+
} // namespace
// Runtime statistics of DNS server.
@@ -72,7 +80,7 @@ base::LazyInstance<DnsSession::RttBuckets>::Leaky DnsSession::rtt_buckets_ =
LAZY_INSTANCE_INITIALIZER;
DnsSession::RttBuckets::RttBuckets() : base::BucketRanges(kRTTBucketCount + 1) {
- base::Histogram::InitializeBucketRanges(1, 5000, this);
+ base::Histogram::InitializeBucketRanges(1, kRTTMaxMs, this);
}
DnsSession::SocketLease::SocketLease(scoped_refptr<DnsSession> session,
@@ -100,14 +108,40 @@ DnsSession::DnsSession(const DnsConfig& config,
socket_pool_->Initialize(&config_.nameservers, net_log);
UMA_HISTOGRAM_CUSTOM_COUNTS(
"AsyncDNS.ServerCount", config_.nameservers.size(), 0, 10, 11);
+ UpdateTimeouts(NetworkChangeNotifier::GetConnectionType());
+ InitializeServerStats();
+ NetworkChangeNotifier::AddConnectionTypeObserver(this);
+}
+
+DnsSession::~DnsSession() {
+ RecordServerStats();
+ NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
+}
+
+void DnsSession::UpdateTimeouts(NetworkChangeNotifier::ConnectionType type) {
+ initial_timeout_ = GetTimeDeltaForConnectionTypeFromFieldTrialOrDefault(
+ "AsyncDnsInitialTimeoutMsByConnectionType", config_.timeout, type);
+ max_timeout_ = GetTimeDeltaForConnectionTypeFromFieldTrialOrDefault(
+ "AsyncDnsMaxTimeoutMsByConnectionType",
+ base::TimeDelta::FromMilliseconds(kDefaultMaxTimeoutMs), type);
+}
+
+void DnsSession::InitializeServerStats() {
+ server_stats_.clear();
for (size_t i = 0; i < config_.nameservers.size(); ++i) {
server_stats_.push_back(make_scoped_ptr(
- new ServerStats(config_.timeout, rtt_buckets_.Pointer())));
+ new ServerStats(initial_timeout_, rtt_buckets_.Pointer())));
}
}
-DnsSession::~DnsSession() {
- RecordServerStats();
+void DnsSession::OnConnectionTypeChanged(
+ NetworkChangeNotifier::ConnectionType type) {
+ UpdateTimeouts(type);
+ const char* kTrialName = "AsyncDnsFlushServerStatsOnConnectionTypeChange";
+ if (base::FieldTrialList::FindFullName(kTrialName) == "enable") {
+ RecordServerStats();
+ InitializeServerStats();
+ }
}
uint16_t DnsSession::NextQueryId() const {
@@ -223,9 +257,9 @@ void DnsSession::RecordServerStats() {
base::TimeDelta DnsSession::NextTimeout(unsigned server_index, int attempt) {
- // Respect config timeout if it exceeds |kMaxTimeoutMs|.
- if (config_.timeout.InMilliseconds() >= kMaxTimeoutMs)
- return config_.timeout;
+ // Respect initial timeout (from config or field trial) if it exceeds max.
+ if (initial_timeout_ > max_timeout_)
+ return initial_timeout_;
return NextTimeoutFromHistogram(server_index, attempt);
}
@@ -272,8 +306,7 @@ base::TimeDelta DnsSession::NextTimeoutFromJacobson(unsigned server_index,
// The timeout doubles every full round.
unsigned num_backoffs = attempt / config_.nameservers.size();
- return std::min(timeout * (1 << num_backoffs),
- base::TimeDelta::FromMilliseconds(kMaxTimeoutMs));
+ return std::min(timeout * (1 << num_backoffs), max_timeout_);
}
base::TimeDelta DnsSession::NextTimeoutFromHistogram(unsigned server_index,
@@ -303,8 +336,7 @@ base::TimeDelta DnsSession::NextTimeoutFromHistogram(unsigned server_index,
// The timeout still doubles every full round.
unsigned num_backoffs = attempt / config_.nameservers.size();
- return std::min(timeout * (1 << num_backoffs),
- base::TimeDelta::FromMilliseconds(kMaxTimeoutMs));
+ return std::min(timeout * (1 << num_backoffs), max_timeout_);
}
} // namespace net
diff --git a/chromium/net/dns/dns_session.h b/chromium/net/dns/dns_session.h
index 106493e94b8..b401a64f138 100644
--- a/chromium/net/dns/dns_session.h
+++ b/chromium/net/dns/dns_session.h
@@ -16,6 +16,7 @@
#include "base/metrics/bucket_ranges.h"
#include "base/time/time.h"
#include "net/base/net_export.h"
+#include "net/base/network_change_notifier.h"
#include "net/base/rand_callback.h"
#include "net/dns/dns_config_service.h"
#include "net/dns/dns_socket_pool.h"
@@ -36,7 +37,8 @@ class StreamSocket;
// Ref-counted so that DnsClient::Request can keep working in absence of
// DnsClient. A DnsSession must be recreated when DnsConfig changes.
class NET_EXPORT_PRIVATE DnsSession
- : NON_EXPORTED_BASE(public base::RefCounted<DnsSession>) {
+ : NON_EXPORTED_BASE(public base::RefCounted<DnsSession>),
+ public NetworkChangeNotifier::ConnectionTypeObserver {
public:
typedef base::Callback<int()> RandCallback;
@@ -110,7 +112,10 @@ class NET_EXPORT_PRIVATE DnsSession
private:
friend class base::RefCounted<DnsSession>;
- ~DnsSession();
+ ~DnsSession() override;
+
+ void UpdateTimeouts(NetworkChangeNotifier::ConnectionType type);
+ void InitializeServerStats();
// Release a socket.
void FreeSocket(unsigned server_index,
@@ -122,6 +127,10 @@ class NET_EXPORT_PRIVATE DnsSession
// Compute the timeout using the histogram method.
base::TimeDelta NextTimeoutFromHistogram(unsigned server_index, int attempt);
+ // NetworkChangeNotifier::ConnectionTypeObserver:
+ void OnConnectionTypeChanged(
+ NetworkChangeNotifier::ConnectionType type) override;
+
const DnsConfig config_;
scoped_ptr<DnsSocketPool> socket_pool_;
RandCallback rand_callback_;
@@ -130,6 +139,9 @@ class NET_EXPORT_PRIVATE DnsSession
// Current index into |config_.nameservers| to begin resolution with.
int server_index_;
+ base::TimeDelta initial_timeout_;
+ base::TimeDelta max_timeout_;
+
struct ServerStats;
// Track runtime statistics of each DNS server.
diff --git a/chromium/net/dns/dns_session_unittest.cc b/chromium/net/dns/dns_session_unittest.cc
index b2a09f187f9..e6040850bf6 100644
--- a/chromium/net/dns/dns_session_unittest.cc
+++ b/chromium/net/dns/dns_session_unittest.cc
@@ -11,6 +11,7 @@
#include "base/memory/scoped_ptr.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"
#include "net/log/net_log.h"
@@ -113,12 +114,9 @@ class MockDnsSocketPool : public DnsSocketPool {
void DnsSessionTest::Initialize(unsigned num_servers) {
CHECK(num_servers < 256u);
config_.nameservers.clear();
- IPAddressNumber dns_ip;
- bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip);
- EXPECT_TRUE(rv);
for (unsigned char i = 0; i < num_servers; ++i) {
- dns_ip[3] = i;
- IPEndPoint dns_endpoint(dns_ip, dns_protocol::kDefaultPort);
+ IPEndPoint dns_endpoint(IPAddress(192, 168, 1, i),
+ dns_protocol::kDefaultPort);
config_.nameservers.push_back(dns_endpoint);
}
@@ -221,27 +219,29 @@ TEST_F(DnsSessionTest, AllocateFree) {
EXPECT_TRUE(NoMoreEvents());
}
-// Expect default calculated timeout to be within 10ms of in DnsConfig.
+// Expect default calculated timeout to be within 10ms of one in DnsConfig.
TEST_F(DnsSessionTest, HistogramTimeoutNormal) {
Initialize(2);
- base::TimeDelta timeoutDelta = session_->NextTimeout(0, 0) - config_.timeout;
- EXPECT_LT(timeoutDelta.InMilliseconds(), 10);
+ base::TimeDelta delta = session_->NextTimeout(0, 0) - config_.timeout;
+ EXPECT_LE(delta.InMilliseconds(), 10);
}
-// Expect short calculated timeout to be within 10ms of in DnsConfig.
+// Expect short calculated timeout to be within 10ms of one in DnsConfig.
TEST_F(DnsSessionTest, HistogramTimeoutShort) {
config_.timeout = base::TimeDelta::FromMilliseconds(15);
Initialize(2);
- base::TimeDelta timeoutDelta = session_->NextTimeout(0, 0) - config_.timeout;
- EXPECT_LT(timeoutDelta.InMilliseconds(), 10);
+ base::TimeDelta delta = session_->NextTimeout(0, 0) - config_.timeout;
+ EXPECT_LE(delta.InMilliseconds(), 10);
}
// Expect long calculated timeout to be equal to one in DnsConfig.
+// (Default max timeout is 5 seconds, so NextTimeout should return exactly
+// the config timeout.)
TEST_F(DnsSessionTest, HistogramTimeoutLong) {
config_.timeout = base::TimeDelta::FromSeconds(15);
Initialize(2);
base::TimeDelta timeout = session_->NextTimeout(0, 0);
- EXPECT_EQ(config_.timeout.InMilliseconds(), timeout.InMilliseconds());
+ EXPECT_EQ(timeout.InMilliseconds(), config_.timeout.InMilliseconds());
}
} // namespace
diff --git a/chromium/net/dns/dns_transaction.cc b/chromium/net/dns/dns_transaction.cc
index 8eebb8c69f2..f726bd21c52 100644
--- a/chromium/net/dns/dns_transaction.cc
+++ b/chromium/net/dns/dns_transaction.cc
@@ -28,6 +28,7 @@
#include "base/values.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/dns/dns_protocol.h"
@@ -57,8 +58,8 @@ int CountLabels(const std::string& name) {
}
bool IsIPLiteral(const std::string& hostname) {
- IPAddressNumber ip;
- return ParseIPLiteralToNumber(hostname, &ip);
+ IPAddress ip;
+ return ip.AssignFromIPLiteral(hostname);
}
scoped_ptr<base::Value> NetLogStartCallback(
diff --git a/chromium/net/dns/dns_transaction.h b/chromium/net/dns/dns_transaction.h
index e338cb92956..198b4b81164 100644
--- a/chromium/net/dns/dns_transaction.h
+++ b/chromium/net/dns/dns_transaction.h
@@ -10,6 +10,7 @@
#include <string>
#include "base/callback_forward.h"
+#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/net_export.h"
diff --git a/chromium/net/dns/dns_transaction_unittest.cc b/chromium/net/dns/dns_transaction_unittest.cc
index 7b906ba2a0f..2f8e67553ee 100644
--- a/chromium/net/dns/dns_transaction_unittest.cc
+++ b/chromium/net/dns/dns_transaction_unittest.cc
@@ -14,6 +14,7 @@
#include "base/rand_util.h"
#include "base/sys_byteorder.h"
#include "base/test/test_timeouts.h"
+#include "net/base/ip_address.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/dns_query.h"
#include "net/dns/dns_response.h"
@@ -333,15 +334,9 @@ class DnsTransactionTest : public testing::Test {
void ConfigureNumServers(unsigned num_servers) {
CHECK_LE(num_servers, 255u);
config_.nameservers.clear();
- IPAddressNumber dns_ip;
- {
- bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip);
- EXPECT_TRUE(rv);
- }
for (unsigned i = 0; i < num_servers; ++i) {
- dns_ip[3] = i;
- config_.nameservers.push_back(IPEndPoint(dns_ip,
- dns_protocol::kDefaultPort));
+ config_.nameservers.push_back(
+ IPEndPoint(IPAddress(192, 168, 1, i), dns_protocol::kDefaultPort));
}
}
diff --git a/chromium/net/dns/dns_util.cc b/chromium/net/dns/dns_util.cc
index d2897ff2ae0..5f10ad2365f 100644
--- a/chromium/net/dns/dns_util.cc
+++ b/chromium/net/dns/dns_util.cc
@@ -9,6 +9,9 @@
#include <cstring>
+#include "base/metrics/field_trial.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
#include "build/build_config.h"
#if defined(OS_POSIX)
@@ -152,4 +155,41 @@ bool HaveOnlyLoopbackAddresses() {
#endif // defined(various platforms)
}
+#if !defined(OS_NACL)
+namespace {
+
+bool GetTimeDeltaForConnectionTypeFromFieldTrial(
+ const char* field_trial,
+ NetworkChangeNotifier::ConnectionType type,
+ base::TimeDelta* out) {
+ std::string group = base::FieldTrialList::FindFullName(field_trial);
+ if (group.empty())
+ return false;
+ std::vector<base::StringPiece> group_parts = base::SplitStringPiece(
+ group, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ if (type < 0)
+ return false;
+ size_t type_size = static_cast<size_t>(type);
+ if (type_size >= group_parts.size())
+ return false;
+ int64_t ms;
+ if (!base::StringToInt64(group_parts[type_size], &ms))
+ return false;
+ *out = base::TimeDelta::FromMilliseconds(ms);
+ return true;
+}
+
+} // namespace
+
+base::TimeDelta GetTimeDeltaForConnectionTypeFromFieldTrialOrDefault(
+ const char* field_trial,
+ base::TimeDelta default_delta,
+ NetworkChangeNotifier::ConnectionType type) {
+ base::TimeDelta out;
+ if (!GetTimeDeltaForConnectionTypeFromFieldTrial(field_trial, type, &out))
+ out = default_delta;
+ return out;
+}
+#endif // !defined(OS_NACL)
+
} // namespace net
diff --git a/chromium/net/dns/dns_util.h b/chromium/net/dns/dns_util.h
index 74f17cc839d..1acbd668cdc 100644
--- a/chromium/net/dns/dns_util.h
+++ b/chromium/net/dns/dns_util.h
@@ -8,7 +8,9 @@
#include <string>
#include "base/strings/string_piece.h"
+#include "base/time/time.h"
#include "net/base/net_export.h"
+#include "net/base/network_change_notifier.h"
namespace net {
@@ -30,6 +32,14 @@ NET_EXPORT_PRIVATE std::string DNSDomainToString(
// Also returns false if it cannot determine this.
NET_EXPORT_PRIVATE bool HaveOnlyLoopbackAddresses();
+#if !defined(OS_NACL)
+NET_EXPORT_PRIVATE
+base::TimeDelta GetTimeDeltaForConnectionTypeFromFieldTrialOrDefault(
+ const char* field_trial_name,
+ base::TimeDelta default_delta,
+ NetworkChangeNotifier::ConnectionType connection_type);
+#endif // !defined(OS_NACL)
+
} // namespace net
#endif // NET_DNS_DNS_UTIL_H_
diff --git a/chromium/net/dns/host_cache.cc b/chromium/net/dns/host_cache.cc
index e38016f159d..4bb2533ba1e 100644
--- a/chromium/net/dns/host_cache.cc
+++ b/chromium/net/dns/host_cache.cc
@@ -8,6 +8,7 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
+#include "base/trace_event/trace_event.h"
#include "net/base/net_errors.h"
namespace net {
@@ -53,6 +54,7 @@ void HostCache::Set(const Key& key,
const Entry& entry,
base::TimeTicks now,
base::TimeDelta ttl) {
+ TRACE_EVENT0("net", "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 16970cd5682..1a6bd612b99 100644
--- a/chromium/net/dns/host_resolver_impl.cc
+++ b/chromium/net/dns/host_resolver_impl.cc
@@ -35,13 +35,15 @@
#include "base/thread_task_runner_handle.h"
#include "base/threading/worker_pool.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/address_family.h"
#include "net/base/address_list.h"
#include "net/base/host_port_pair.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "net/dns/address_sorter.h"
#include "net/dns/dns_client.h"
#include "net/dns/dns_config_service.h"
@@ -64,6 +66,10 @@ namespace net {
namespace {
+// Default delay between calls to the system resolver for the same hostname.
+// (Can be overridden by field trial.)
+const int64_t kDnsDefaultUnresponsiveDelayMs = 6000;
+
// Limit the size of hostnames that will be resolved to combat issues in
// some platform's resolvers.
const size_t kMaxHostLength = 4096;
@@ -167,7 +173,7 @@ enum DnsResolveStatus {
// possible to navigate to http://127.0.53.53/ directly.
//
// For more details: https://www.icann.org/news/announcement-2-2014-08-01-en
-const unsigned char kIcanNameCollisionIp[] = {127, 0, 53, 53};
+const uint8_t kIcanNameCollisionIp[] = {127, 0, 53, 53};
void UmaAsyncDnsResolveStatus(DnsResolveStatus result) {
UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ResolveStatus",
@@ -195,8 +201,7 @@ bool ResemblesMulticastDNSName(const std::string& hostname) {
}
// Attempts to connect a UDP socket to |dest|:53.
-bool IsGloballyReachable(const IPAddressNumber& dest,
- const BoundNetLog& net_log) {
+bool IsGloballyReachable(const IPAddress& dest, const BoundNetLog& net_log) {
// TODO(eroman): Remove ScopedTracker below once crbug.com/455942 is fixed.
tracked_objects::ScopedTracker tracking_profile_1(
FROM_HERE_WITH_EXPLICIT_FUNCTION("455942 IsGloballyReachable"));
@@ -215,16 +220,17 @@ bool IsGloballyReachable(const IPAddressNumber& dest,
if (rv != OK)
return false;
DCHECK_EQ(ADDRESS_FAMILY_IPV6, endpoint.GetFamily());
- const IPAddressNumber& address = endpoint.address();
- bool is_link_local = (address[0] == 0xFE) && ((address[1] & 0xC0) == 0x80);
+ const IPAddress& address = endpoint.address();
+
+ bool is_link_local =
+ (address.bytes()[0] == 0xFE) && ((address.bytes()[1] & 0xC0) == 0x80);
if (is_link_local)
return false;
+
const uint8_t kTeredoPrefix[] = {0x20, 0x01, 0, 0};
- bool is_teredo = std::equal(kTeredoPrefix,
- kTeredoPrefix + arraysize(kTeredoPrefix),
- address.begin());
- if (is_teredo)
+ if (IPAddressStartsWith(address, kTeredoPrefix))
return false;
+
return true;
}
@@ -299,10 +305,10 @@ AddressList EnsurePortOnAddressList(const AddressList& list, uint16_t port) {
// Returns true if |addresses| contains only IPv4 loopback addresses.
bool IsAllIPv4Loopback(const AddressList& addresses) {
for (unsigned i = 0; i < addresses.size(); ++i) {
- const IPAddressNumber& address = addresses[i].address();
+ const IPAddress& address = addresses[i].address();
switch (addresses[i].GetFamily()) {
case ADDRESS_FAMILY_IPV4:
- if (address[0] != 127)
+ if (address.bytes()[0] != 127)
return false;
break;
case ADDRESS_FAMILY_IPV6:
@@ -490,6 +496,23 @@ class PriorityTracker {
//-----------------------------------------------------------------------------
+bool ResolveLocalHostname(base::StringPiece host,
+ uint16_t port,
+ AddressList* address_list) {
+ address_list->clear();
+
+ bool is_local6;
+ if (!IsLocalHostname(host, &is_local6))
+ return false;
+
+ address_list->push_back(IPEndPoint(IPAddress::IPv6Localhost(), port));
+ if (!is_local6) {
+ address_list->push_back(IPEndPoint(IPAddress::IPv4Localhost(), port));
+ }
+
+ return true;
+}
+
const unsigned HostResolverImpl::kMaximumDnsFailures = 16;
// Holds the data for a request that could not be completed synchronously.
@@ -711,9 +734,8 @@ class HostResolverImpl::ProcTask
// 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 IPAddressNumber& cur = it.address();
- if (cur.size() == arraysize(kIcanNameCollisionIp) &&
- 0 == memcmp(&cur.front(), kIcanNameCollisionIp, cur.size())) {
+ const IPAddress& cur = it.address();
+ if (cur.IsIPv4() && IPAddressStartsWith(cur, kIcanNameCollisionIp)) {
error = ERR_ICANN_NAME_COLLISION;
break;
}
@@ -747,6 +769,7 @@ class HostResolverImpl::ProcTask
const uint32_t attempt_number,
int error,
const int os_error) {
+ TRACE_EVENT0("net", "ProcTask::OnLookupComplete");
DCHECK(task_runner_->BelongsToCurrentThread());
// If results are empty, we should return an error.
bool empty_list_on_ok = (error == OK && results.empty());
@@ -1819,7 +1842,8 @@ HostResolverImpl::ProcTaskParams::ProcTaskParams(
size_t max_retry_attempts)
: resolver_proc(resolver_proc),
max_retry_attempts(max_retry_attempts),
- unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)),
+ unresponsive_delay(
+ base::TimeDelta::FromMilliseconds(kDnsDefaultUnresponsiveDelayMs)),
retry_factor(2) {
// Maximum of 4 retry attempts for host resolution.
static const size_t kDefaultMaxRetryAttempts = 4u;
@@ -1827,6 +1851,9 @@ HostResolverImpl::ProcTaskParams::ProcTaskParams(
max_retry_attempts = kDefaultMaxRetryAttempts;
}
+HostResolverImpl::ProcTaskParams::ProcTaskParams(const ProcTaskParams& other) =
+ default;
+
HostResolverImpl::ProcTaskParams::~ProcTaskParams() {}
HostResolverImpl::HostResolverImpl(const Options& options, NetLog* net_log)
@@ -1858,12 +1885,15 @@ HostResolverImpl::HostResolverImpl(const Options& options, NetLog* net_log)
new LoopbackProbeJob(weak_ptr_factory_.GetWeakPtr());
#endif
NetworkChangeNotifier::AddIPAddressObserver(this);
+ NetworkChangeNotifier::AddConnectionTypeObserver(this);
NetworkChangeNotifier::AddDNSObserver(this);
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) && \
!defined(OS_ANDROID)
EnsureDnsReloaderInit();
#endif
+ OnConnectionTypeChanged(NetworkChangeNotifier::GetConnectionType());
+
{
DnsConfig dns_config;
NetworkChangeNotifier::GetDnsConfig(&dns_config);
@@ -1883,6 +1913,7 @@ HostResolverImpl::~HostResolverImpl() {
STLDeleteValues(&jobs_);
NetworkChangeNotifier::RemoveIPAddressObserver(this);
+ NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
NetworkChangeNotifier::RemoveDNSObserver(this);
}
@@ -1909,16 +1940,16 @@ int HostResolverImpl::Resolve(const RequestInfo& info,
LogStartRequest(source_net_log, info);
- IPAddressNumber ip_number;
- IPAddressNumber* ip_number_ptr = nullptr;
- if (ParseIPLiteralToNumber(info.hostname(), &ip_number))
- ip_number_ptr = &ip_number;
+ IPAddress ip_address;
+ IPAddress* ip_address_ptr = nullptr;
+ if (ip_address.AssignFromIPLiteral(info.hostname()))
+ ip_address_ptr = &ip_address;
// Build a key that identifies the request in the cache and in the
// outstanding jobs map.
- Key key = GetEffectiveKeyForRequest(info, ip_number_ptr, source_net_log);
+ Key key = GetEffectiveKeyForRequest(info, ip_address_ptr, source_net_log);
- int rv = ResolveHelper(key, info, ip_number_ptr, addresses, source_net_log);
+ int rv = ResolveHelper(key, info, ip_address_ptr, addresses, source_net_log);
if (rv != ERR_DNS_CACHE_MISS) {
LogFinishRequest(source_net_log, info, rv);
RecordTotalTime(HaveDnsConfig(), info.is_speculative(), base::TimeDelta());
@@ -1964,7 +1995,7 @@ int HostResolverImpl::Resolve(const RequestInfo& info,
int HostResolverImpl::ResolveHelper(const Key& key,
const RequestInfo& info,
- const IPAddressNumber* ip_number,
+ const IPAddress* ip_address,
AddressList* addresses,
const BoundNetLog& source_net_log) {
// The result of |getaddrinfo| for empty hosts is inconsistent across systems.
@@ -1974,7 +2005,7 @@ int HostResolverImpl::ResolveHelper(const Key& key,
return ERR_NAME_NOT_RESOLVED;
int net_error = ERR_UNEXPECTED;
- if (ResolveAsIP(key, info, ip_number, &net_error, addresses))
+ if (ResolveAsIP(key, info, ip_address, &net_error, addresses))
return net_error;
if (ServeFromCache(key, info, &net_error, addresses)) {
source_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT);
@@ -2002,14 +2033,14 @@ int HostResolverImpl::ResolveFromCache(const RequestInfo& info,
// Update the net log and notify registered observers.
LogStartRequest(source_net_log, info);
- IPAddressNumber ip_number;
- IPAddressNumber* ip_number_ptr = nullptr;
- if (ParseIPLiteralToNumber(info.hostname(), &ip_number))
- ip_number_ptr = &ip_number;
+ IPAddress ip_address;
+ IPAddress* ip_address_ptr = nullptr;
+ if (ip_address.AssignFromIPLiteral(info.hostname()))
+ ip_address_ptr = &ip_address;
- Key key = GetEffectiveKeyForRequest(info, ip_number_ptr, source_net_log);
+ Key key = GetEffectiveKeyForRequest(info, ip_address_ptr, source_net_log);
- int rv = ResolveHelper(key, info, ip_number_ptr, addresses, source_net_log);
+ int rv = ResolveHelper(key, info, ip_address_ptr, addresses, source_net_log);
LogFinishRequest(source_net_log, info, rv);
return rv;
}
@@ -2054,27 +2085,22 @@ scoped_ptr<base::Value> HostResolverImpl::GetDnsConfigAsValue() const {
bool HostResolverImpl::ResolveAsIP(const Key& key,
const RequestInfo& info,
- const IPAddressNumber* ip_number,
+ const IPAddress* ip_address,
int* net_error,
AddressList* addresses) {
DCHECK(addresses);
DCHECK(net_error);
- if (ip_number == nullptr)
+ if (ip_address == nullptr)
return false;
- DCHECK_EQ(key.host_resolver_flags &
- ~(HOST_RESOLVER_CANONNAME | HOST_RESOLVER_LOOPBACK_ONLY |
- HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6),
- 0) << " Unhandled flag";
-
*net_error = OK;
- AddressFamily family = GetAddressFamily(*ip_number);
+ AddressFamily family = GetAddressFamily(*ip_address);
if (key.address_family != ADDRESS_FAMILY_UNSPECIFIED &&
key.address_family != family) {
// Don't return IPv6 addresses for IPv4 queries, and vice versa.
*net_error = ERR_NAME_NOT_RESOLVED;
} else {
- *addresses = AddressList::CreateFromIPAddress(*ip_number, info.port());
+ *addresses = AddressList::CreateFromIPAddress(*ip_address, info.port());
if (key.host_resolver_flags & HOST_RESOLVER_CANONNAME)
addresses->SetDefaultCanonicalName();
}
@@ -2205,7 +2231,7 @@ void HostResolverImpl::SetHaveOnlyLoopbackAddresses(bool result) {
HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest(
const RequestInfo& info,
- const IPAddressNumber* ip_number,
+ const IPAddress* ip_address,
const BoundNetLog& net_log) {
HostResolverFlags effective_flags =
info.host_resolver_flags() | additional_resolver_flags_;
@@ -2219,7 +2245,7 @@ HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest(
// that this query is UNSPECIFIED (see info.address_family()
// check above) so the code requesting the resolution should be amenable
// to receiving a IPv6 resolution.
- ip_number == nullptr) {
+ ip_address == nullptr) {
if (!IsIPv6Reachable(net_log)) {
effective_address_family = ADDRESS_FAMILY_IPV4;
effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
@@ -2234,9 +2260,8 @@ bool HostResolverImpl::IsIPv6Reachable(const BoundNetLog& net_log) {
base::TimeTicks now = base::TimeTicks::Now();
bool cached = true;
if ((now - last_ipv6_probe_time_).InMilliseconds() > kIPv6ProbePeriodMs) {
- IPAddressNumber address(kIPv6ProbeAddress,
- kIPv6ProbeAddress + arraysize(kIPv6ProbeAddress));
- last_ipv6_probe_result_ = IsGloballyReachable(address, net_log);
+ last_ipv6_probe_result_ =
+ IsGloballyReachable(IPAddress(kIPv6ProbeAddress), net_log);
last_ipv6_probe_time_ = now;
cached = false;
}
@@ -2327,6 +2352,15 @@ void HostResolverImpl::OnIPAddressChanged() {
// |this| may be deleted inside AbortAllInProgressJobs().
}
+void HostResolverImpl::OnConnectionTypeChanged(
+ NetworkChangeNotifier::ConnectionType type) {
+ proc_params_.unresponsive_delay =
+ GetTimeDeltaForConnectionTypeFromFieldTrialOrDefault(
+ "DnsUnresponsiveDelayMsByConnectionType",
+ base::TimeDelta::FromMilliseconds(kDnsDefaultUnresponsiveDelayMs),
+ type);
+}
+
void HostResolverImpl::OnInitialDNSConfigRead() {
UpdateDNSConfig(false);
}
diff --git a/chromium/net/dns/host_resolver_impl.h b/chromium/net/dns/host_resolver_impl.h
index 7c454991736..5334f7bd62f 100644
--- a/chromium/net/dns/host_resolver_impl.h
+++ b/chromium/net/dns/host_resolver_impl.h
@@ -13,9 +13,9 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/strings/string_piece.h"
#include "base/threading/non_thread_safe.h"
#include "base/time/time.h"
-#include "net/base/ip_address_number.h"
#include "net/base/net_export.h"
#include "net/base/network_change_notifier.h"
#include "net/dns/host_cache.h"
@@ -24,8 +24,10 @@
namespace net {
+class AddressList;
class BoundNetLog;
class DnsClient;
+class IPAddress;
class NetLog;
// For each hostname that is requested, HostResolver creates a
@@ -60,6 +62,7 @@ class NET_EXPORT HostResolverImpl
: public HostResolver,
NON_EXPORTED_BASE(public base::NonThreadSafe),
public NetworkChangeNotifier::IPAddressObserver,
+ public NetworkChangeNotifier::ConnectionTypeObserver,
public NetworkChangeNotifier::DNSObserver {
public:
// Parameters for ProcTask which resolves hostnames using HostResolveProc.
@@ -80,6 +83,8 @@ class NET_EXPORT HostResolverImpl
// Sets up defaults.
ProcTaskParams(HostResolverProc* resolver_proc, size_t max_retry_attempts);
+ ProcTaskParams(const ProcTaskParams& other);
+
~ProcTaskParams();
// The procedure to use for resolving host names. This will be NULL, except
@@ -165,7 +170,7 @@ class NET_EXPORT HostResolverImpl
// HOSTS and is not localhost.
int ResolveHelper(const Key& key,
const RequestInfo& info,
- const IPAddressNumber* ip_address,
+ const IPAddress* ip_address,
AddressList* addresses,
const BoundNetLog& request_net_log);
@@ -173,7 +178,7 @@ class NET_EXPORT HostResolverImpl
// succeeds, returns false otherwise.
bool ResolveAsIP(const Key& key,
const RequestInfo& info,
- const IPAddressNumber* ip_address,
+ const IPAddress* ip_address,
int* net_error,
AddressList* addresses);
@@ -204,7 +209,7 @@ class NET_EXPORT HostResolverImpl
// "effective" address family by inheriting the resolver's default address
// family when the request leaves it unspecified.
Key GetEffectiveKeyForRequest(const RequestInfo& info,
- const IPAddressNumber* ip_number,
+ const IPAddress* ip_address,
const BoundNetLog& net_log);
// Probes IPv6 support and returns true if IPv6 support is enabled.
@@ -236,6 +241,10 @@ class NET_EXPORT HostResolverImpl
// NetworkChangeNotifier::IPAddressObserver:
void OnIPAddressChanged() override;
+ // NetworkChangeNotifier::ConnectionTypeObserver:
+ void OnConnectionTypeChanged(
+ NetworkChangeNotifier::ConnectionType type) override;
+
// NetworkChangeNotifier::DNSObserver:
void OnDNSChanged() override;
void OnInitialDNSConfigRead() override;
@@ -307,6 +316,18 @@ class NET_EXPORT HostResolverImpl
DISALLOW_COPY_AND_ASSIGN(HostResolverImpl);
};
+// Resolves a local hostname (such as "localhost" or "localhost6") into
+// IP endpoints with the given port. Returns true if |host| is a local
+// hostname and false otherwise. Special IPv6 names (e.g. "localhost6")
+// will resolve to an IPv6 address only, whereas other names will
+// resolve to both IPv4 and IPv6.
+// This function is only exposed so it can be unit-tested.
+// TODO(tfarina): It would be better to change the tests so this function
+// gets exercised indirectly through HostResolverImpl.
+NET_EXPORT_PRIVATE bool ResolveLocalHostname(base::StringPiece host,
+ uint16_t port,
+ AddressList* address_list);
+
} // namespace net
#endif // NET_DNS_HOST_RESOLVER_IMPL_H_
diff --git a/chromium/net/dns/host_resolver_impl_unittest.cc b/chromium/net/dns/host_resolver_impl_unittest.cc
index 569d1ab8ad8..4fc447423d6 100644
--- a/chromium/net/dns/host_resolver_impl_unittest.cc
+++ b/chromium/net/dns/host_resolver_impl_unittest.cc
@@ -26,8 +26,8 @@
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "net/base/address_list.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/dns/dns_client.h"
#include "net/dns/dns_test_util.h"
#include "net/dns/mock_host_resolver.h"
@@ -190,8 +190,8 @@ class MockHostResolverProc : public HostResolverProc {
bool AddressListContains(const AddressList& list,
const std::string& address,
uint16_t port) {
- IPAddressNumber ip;
- bool rv = ParseIPLiteralToNumber(address, &ip);
+ IPAddress ip;
+ bool rv = ip.AssignFromIPLiteral(address);
DCHECK(rv);
return std::find(list.begin(),
list.end(),
@@ -447,6 +447,36 @@ class TestHostResolverImpl : public HostResolverImpl {
}
};
+const uint16_t kLocalhostLookupPort = 80;
+
+bool HasEndpoint(const IPEndPoint& endpoint, const AddressList& addresses) {
+ for (const auto& address : addresses) {
+ if (endpoint == address)
+ return true;
+ }
+ return false;
+}
+
+void TestBothLoopbackIPs(const std::string& host) {
+ IPEndPoint localhost_ipv4(IPAddress::IPv4Localhost(), kLocalhostLookupPort);
+ IPEndPoint localhost_ipv6(IPAddress::IPv6Localhost(), kLocalhostLookupPort);
+
+ AddressList addresses;
+ EXPECT_TRUE(ResolveLocalHostname(host, kLocalhostLookupPort, &addresses));
+ EXPECT_EQ(2u, addresses.size());
+ EXPECT_TRUE(HasEndpoint(localhost_ipv4, addresses));
+ EXPECT_TRUE(HasEndpoint(localhost_ipv6, addresses));
+}
+
+void TestIPv6LoopbackOnly(const std::string& host) {
+ IPEndPoint localhost_ipv6(IPAddress::IPv6Localhost(), kLocalhostLookupPort);
+
+ AddressList addresses;
+ EXPECT_TRUE(ResolveLocalHostname(host, kLocalhostLookupPort, &addresses));
+ EXPECT_EQ(1u, addresses.size());
+ EXPECT_TRUE(HasEndpoint(localhost_ipv6, addresses));
+}
+
} // namespace
class HostResolverImplTest : public testing::Test {
@@ -632,6 +662,22 @@ TEST_F(HostResolverImplTest, LocalhostIPV4IPV6Lookup) {
EXPECT_TRUE(req5->HasOneAddress("::1", 80));
}
+TEST_F(HostResolverImplTest, ResolveIPLiteralWithHostResolverSystemOnly) {
+ const char kIpLiteral[] = "178.78.32.1";
+ // Add a mapping to tell if the resolver proc was called (if it was called,
+ // then the result will be the remapped value. Otherwise it will be the IP
+ // literal).
+ proc_->AddRuleForAllFamilies(kIpLiteral, "183.45.32.1");
+
+ HostResolver::RequestInfo info_bypass(HostPortPair(kIpLiteral, 80));
+ info_bypass.set_host_resolver_flags(HOST_RESOLVER_SYSTEM_ONLY);
+
+ Request* req = CreateRequest(info_bypass, MEDIUM);
+ EXPECT_EQ(OK, req->Resolve());
+
+ EXPECT_TRUE(req->HasAddress(kIpLiteral, 80));
+}
+
TEST_F(HostResolverImplTest, EmptyListMeansNameNotResolved) {
proc_->AddRuleForAllFamilies("just.testing", "");
proc_->SignalMultiple(1u);
@@ -1406,10 +1452,7 @@ TEST_F(HostResolverImplTest, IsIPv6Reachable) {
}
DnsConfig CreateValidDnsConfig() {
- IPAddressNumber dns_ip;
- bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip);
- EXPECT_TRUE(rv);
-
+ IPAddress dns_ip(192, 168, 1, 0);
DnsConfig config;
config.nameservers.push_back(IPEndPoint(dns_ip, dns_protocol::kDefaultPort));
EXPECT_TRUE(config.IsValid());
@@ -1646,9 +1689,8 @@ TEST_F(HostResolverImplDnsTest, ServeFromHosts) {
EXPECT_EQ(ERR_IO_PENDING, req0->Resolve());
EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req0->WaitForResult());
- IPAddressNumber local_ipv4, local_ipv6;
- ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &local_ipv4));
- ASSERT_TRUE(ParseIPLiteralToNumber("::1", &local_ipv6));
+ IPAddress local_ipv4 = IPAddress::IPv4Localhost();
+ IPAddress local_ipv6 = IPAddress::IPv6Localhost();
DnsHosts hosts;
hosts[DnsHostsKey("nx_ipv4", ADDRESS_FAMILY_IPV4)] = local_ipv4;
@@ -1837,9 +1879,8 @@ TEST_F(HostResolverImplDnsTest, DualFamilyLocalhost) {
// Configure DnsClient with dual-host HOSTS file.
DnsConfig config_hosts = CreateValidDnsConfig();
DnsHosts hosts;
- IPAddressNumber local_ipv4, local_ipv6;
- ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &local_ipv4));
- ASSERT_TRUE(ParseIPLiteralToNumber("::1", &local_ipv6));
+ IPAddress local_ipv4 = IPAddress::IPv4Localhost();
+ IPAddress local_ipv6 = IPAddress::IPv6Localhost();
if (saw_ipv4)
hosts[DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4)] = local_ipv4;
if (saw_ipv6)
@@ -2178,4 +2219,62 @@ TEST_F(HostResolverImplDnsTest, ManuallyDisableDnsClientWithPendingRequests) {
EXPECT_TRUE(requests_[2]->HasOneAddress("192.168.0.3", 80));
}
+TEST_F(HostResolverImplTest, ResolveLocalHostname) {
+ AddressList addresses;
+
+ TestBothLoopbackIPs("localhost");
+ TestBothLoopbackIPs("localhoST");
+ TestBothLoopbackIPs("localhost.");
+ TestBothLoopbackIPs("localhoST.");
+ TestBothLoopbackIPs("localhost.localdomain");
+ TestBothLoopbackIPs("localhost.localdomAIn");
+ TestBothLoopbackIPs("localhost.localdomain.");
+ TestBothLoopbackIPs("localhost.localdomAIn.");
+ TestBothLoopbackIPs("foo.localhost");
+ TestBothLoopbackIPs("foo.localhOSt");
+ TestBothLoopbackIPs("foo.localhost.");
+ TestBothLoopbackIPs("foo.localhOSt.");
+
+ TestIPv6LoopbackOnly("localhost6");
+ TestIPv6LoopbackOnly("localhoST6");
+ TestIPv6LoopbackOnly("localhost6.");
+ TestIPv6LoopbackOnly("localhost6.localdomain6");
+ TestIPv6LoopbackOnly("localhost6.localdomain6.");
+
+ EXPECT_FALSE(
+ ResolveLocalHostname("127.0.0.1", kLocalhostLookupPort, &addresses));
+ EXPECT_FALSE(ResolveLocalHostname("::1", kLocalhostLookupPort, &addresses));
+ EXPECT_FALSE(ResolveLocalHostname("0:0:0:0:0:0:0:1", kLocalhostLookupPort,
+ &addresses));
+ EXPECT_FALSE(
+ ResolveLocalHostname("localhostx", kLocalhostLookupPort, &addresses));
+ EXPECT_FALSE(
+ ResolveLocalHostname("localhost.x", kLocalhostLookupPort, &addresses));
+ EXPECT_FALSE(ResolveLocalHostname("foo.localdomain", kLocalhostLookupPort,
+ &addresses));
+ EXPECT_FALSE(ResolveLocalHostname("foo.localdomain.x", kLocalhostLookupPort,
+ &addresses));
+ EXPECT_FALSE(
+ ResolveLocalHostname("localhost6x", kLocalhostLookupPort, &addresses));
+ EXPECT_FALSE(ResolveLocalHostname("localhost.localdomain6",
+ kLocalhostLookupPort, &addresses));
+ EXPECT_FALSE(ResolveLocalHostname("localhost6.localdomain",
+ kLocalhostLookupPort, &addresses));
+ EXPECT_FALSE(
+ ResolveLocalHostname("127.0.0.1.1", kLocalhostLookupPort, &addresses));
+ EXPECT_FALSE(
+ ResolveLocalHostname(".127.0.0.255", kLocalhostLookupPort, &addresses));
+ EXPECT_FALSE(ResolveLocalHostname("::2", kLocalhostLookupPort, &addresses));
+ EXPECT_FALSE(ResolveLocalHostname("::1:1", kLocalhostLookupPort, &addresses));
+ EXPECT_FALSE(ResolveLocalHostname("0:0:0:0:1:0:0:1", kLocalhostLookupPort,
+ &addresses));
+ EXPECT_FALSE(ResolveLocalHostname("::1:1", kLocalhostLookupPort, &addresses));
+ EXPECT_FALSE(ResolveLocalHostname("0:0:0:0:0:0:0:0:1", kLocalhostLookupPort,
+ &addresses));
+ EXPECT_FALSE(ResolveLocalHostname("foo.localhost.com", kLocalhostLookupPort,
+ &addresses));
+ EXPECT_FALSE(
+ ResolveLocalHostname("foo.localhoste", kLocalhostLookupPort, &addresses));
+}
+
} // namespace net
diff --git a/chromium/net/dns/host_resolver_mojo_unittest.cc b/chromium/net/dns/host_resolver_mojo_unittest.cc
index c5f3ba9433f..a210d78303b 100644
--- a/chromium/net/dns/host_resolver_mojo_unittest.cc
+++ b/chromium/net/dns/host_resolver_mojo_unittest.cc
@@ -9,6 +9,7 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "net/base/address_list.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
#include "net/base/test_completion_callback.h"
@@ -174,11 +175,10 @@ class HostResolverMojoTest : public testing::Test {
TEST_F(HostResolverMojoTest, Basic) {
AddressList address_list;
- IPAddressNumber address_number;
- ASSERT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &address_number));
- address_list.push_back(IPEndPoint(address_number, 12345));
+ IPAddress address(1, 2, 3, 4);
+ address_list.push_back(IPEndPoint(address, 12345));
address_list.push_back(
- IPEndPoint(ConvertIPv4NumberToIPv6Number(address_number), 12345));
+ IPEndPoint(ConvertIPv4ToIPv4MappedIPv6(address), 12345));
mock_resolver_->AddAction(HostResolverAction::ReturnResult(address_list));
HostResolver::RequestInfo request_info(
HostPortPair::FromString("example.com:12345"));
@@ -192,17 +192,16 @@ TEST_F(HostResolverMojoTest, Basic) {
interfaces::HostResolverRequestInfo& request = *mock_resolver_->requests()[0];
EXPECT_EQ("example.com", request.host.To<std::string>());
EXPECT_EQ(12345, request.port);
- EXPECT_EQ(interfaces::ADDRESS_FAMILY_UNSPECIFIED, request.address_family);
+ EXPECT_EQ(interfaces::AddressFamily::UNSPECIFIED, request.address_family);
EXPECT_FALSE(request.is_my_ip_address);
}
TEST_F(HostResolverMojoTest, ResolveCachedResult) {
AddressList address_list;
- IPAddressNumber address_number;
- ASSERT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &address_number));
- address_list.push_back(IPEndPoint(address_number, 12345));
+ IPAddress address(1, 2, 3, 4);
+ address_list.push_back(IPEndPoint(address, 12345));
address_list.push_back(
- IPEndPoint(ConvertIPv4NumberToIPv6Number(address_number), 12345));
+ IPEndPoint(ConvertIPv4ToIPv4MappedIPv6(address), 12345));
mock_resolver_->AddAction(HostResolverAction::ReturnResult(address_list));
HostResolver::RequestInfo request_info(
HostPortPair::FromString("example.com:12345"));
@@ -215,9 +214,9 @@ TEST_F(HostResolverMojoTest, ResolveCachedResult) {
EXPECT_EQ(OK, Resolve(request_info, &result));
ASSERT_EQ(2u, result.size());
address_list.clear();
- address_list.push_back(IPEndPoint(address_number, 6789));
+ address_list.push_back(IPEndPoint(address, 6789));
address_list.push_back(
- IPEndPoint(ConvertIPv4NumberToIPv6Number(address_number), 6789));
+ IPEndPoint(ConvertIPv4ToIPv4MappedIPv6(address), 6789));
EXPECT_EQ(address_list[0], result[0]);
EXPECT_EQ(address_list[1], result[1]);
EXPECT_EQ(1u, mock_resolver_->requests().size());
@@ -234,9 +233,8 @@ TEST_F(HostResolverMojoTest, ResolveCachedResult) {
TEST_F(HostResolverMojoTest, Multiple) {
AddressList address_list;
- IPAddressNumber address_number;
- ASSERT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &address_number));
- address_list.push_back(IPEndPoint(address_number, 12345));
+ IPAddress address(1, 2, 3, 4);
+ address_list.push_back(IPEndPoint(address, 12345));
mock_resolver_->AddAction(HostResolverAction::ReturnResult(address_list));
mock_resolver_->AddAction(
HostResolverAction::ReturnError(ERR_NAME_NOT_RESOLVED));
@@ -272,13 +270,13 @@ TEST_F(HostResolverMojoTest, Multiple) {
*mock_resolver_->requests()[0];
EXPECT_EQ("example.com", request1.host.To<std::string>());
EXPECT_EQ(12345, request1.port);
- EXPECT_EQ(interfaces::ADDRESS_FAMILY_IPV4, request1.address_family);
+ EXPECT_EQ(interfaces::AddressFamily::IPV4, request1.address_family);
EXPECT_TRUE(request1.is_my_ip_address);
interfaces::HostResolverRequestInfo& request2 =
*mock_resolver_->requests()[1];
EXPECT_EQ("example.org", request2.host.To<std::string>());
EXPECT_EQ(80, request2.port);
- EXPECT_EQ(interfaces::ADDRESS_FAMILY_IPV6, request2.address_family);
+ EXPECT_EQ(interfaces::AddressFamily::IPV6, request2.address_family);
EXPECT_FALSE(request2.is_my_ip_address);
}
@@ -296,7 +294,7 @@ TEST_F(HostResolverMojoTest, Error) {
interfaces::HostResolverRequestInfo& request = *mock_resolver_->requests()[0];
EXPECT_EQ("example.com", request.host.To<std::string>());
EXPECT_EQ(8080, request.port);
- EXPECT_EQ(interfaces::ADDRESS_FAMILY_IPV4, request.address_family);
+ EXPECT_EQ(interfaces::AddressFamily::IPV4, request.address_family);
EXPECT_FALSE(request.is_my_ip_address);
}
@@ -328,7 +326,7 @@ TEST_F(HostResolverMojoTest, Cancel) {
interfaces::HostResolverRequestInfo& request = *mock_resolver_->requests()[0];
EXPECT_EQ("example.com", request.host.To<std::string>());
EXPECT_EQ(80, request.port);
- EXPECT_EQ(interfaces::ADDRESS_FAMILY_IPV6, request.address_family);
+ EXPECT_EQ(interfaces::AddressFamily::IPV6, request.address_family);
EXPECT_FALSE(request.is_my_ip_address);
}
@@ -344,7 +342,7 @@ TEST_F(HostResolverMojoTest, ImplDropsClientConnection) {
interfaces::HostResolverRequestInfo& request = *mock_resolver_->requests()[0];
EXPECT_EQ("example.com", request.host.To<std::string>());
EXPECT_EQ(1, request.port);
- EXPECT_EQ(interfaces::ADDRESS_FAMILY_UNSPECIFIED, request.address_family);
+ EXPECT_EQ(interfaces::AddressFamily::UNSPECIFIED, request.address_family);
EXPECT_FALSE(request.is_my_ip_address);
}
@@ -359,11 +357,10 @@ TEST_F(HostResolverMojoTest, ResolveFromCache_Miss) {
TEST_F(HostResolverMojoTest, ResolveFromCache_Hit) {
AddressList address_list;
- IPAddressNumber address_number;
- ASSERT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &address_number));
- address_list.push_back(IPEndPoint(address_number, 12345));
+ IPAddress address(1, 2, 3, 4);
+ address_list.push_back(IPEndPoint(address, 12345));
address_list.push_back(
- IPEndPoint(ConvertIPv4NumberToIPv6Number(address_number), 12345));
+ IPEndPoint(ConvertIPv4ToIPv4MappedIPv6(address), 12345));
mock_resolver_->AddAction(HostResolverAction::ReturnResult(address_list));
HostResolver::RequestInfo request_info(
HostPortPair::FromString("example.com:12345"));
@@ -382,11 +379,10 @@ TEST_F(HostResolverMojoTest, ResolveFromCache_Hit) {
TEST_F(HostResolverMojoTest, ResolveFromCache_CacheNotAllowed) {
AddressList address_list;
- IPAddressNumber address_number;
- ASSERT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &address_number));
- address_list.push_back(IPEndPoint(address_number, 12345));
+ IPAddress address(1, 2, 3, 4);
+ address_list.push_back(IPEndPoint(address, 12345));
address_list.push_back(
- IPEndPoint(ConvertIPv4NumberToIPv6Number(address_number), 12345));
+ IPEndPoint(ConvertIPv4ToIPv4MappedIPv6(address), 12345));
mock_resolver_->AddAction(HostResolverAction::ReturnResult(address_list));
HostResolver::RequestInfo request_info(
HostPortPair::FromString("example.com:12345"));
diff --git a/chromium/net/dns/mapped_host_resolver.cc b/chromium/net/dns/mapped_host_resolver.cc
index 97461148873..5474cc3defa 100644
--- a/chromium/net/dns/mapped_host_resolver.cc
+++ b/chromium/net/dns/mapped_host_resolver.cc
@@ -10,7 +10,6 @@
#include "base/values.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
namespace net {
diff --git a/chromium/net/dns/mapped_host_resolver_unittest.cc b/chromium/net/dns/mapped_host_resolver_unittest.cc
index 002a9888b56..dd772ac4b8e 100644
--- a/chromium/net/dns/mapped_host_resolver_unittest.cc
+++ b/chromium/net/dns/mapped_host_resolver_unittest.cc
@@ -8,7 +8,6 @@
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
#include "net/log/net_log.h"
diff --git a/chromium/net/dns/mdns_client.cc b/chromium/net/dns/mdns_client.cc
index 8b4e037912f..f72d9c2d2b8 100644
--- a/chromium/net/dns/mdns_client.cc
+++ b/chromium/net/dns/mdns_client.cc
@@ -4,8 +4,8 @@
#include "net/dns/mdns_client.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/network_interfaces.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/mdns_client_impl.h"
@@ -18,9 +18,8 @@ const char kMDnsMulticastGroupIPv4[] = "224.0.0.251";
const char kMDnsMulticastGroupIPv6[] = "FF02::FB";
IPEndPoint GetMDnsIPEndPoint(const char* address) {
- IPAddressNumber multicast_group_number;
- bool success = ParseIPLiteralToNumber(address,
- &multicast_group_number);
+ IPAddress multicast_group_number;
+ bool success = multicast_group_number.AssignFromIPLiteral(address);
DCHECK(success);
return IPEndPoint(multicast_group_number,
dns_protocol::kDefaultPortMulticast);
@@ -29,7 +28,7 @@ IPEndPoint GetMDnsIPEndPoint(const char* address) {
int Bind(const IPEndPoint& multicast_addr,
uint32_t interface_index,
DatagramServerSocket* socket) {
- IPAddressNumber address_any(multicast_addr.address().size());
+ IPAddress address_any(std::vector<uint8_t>(multicast_addr.address().size()));
IPEndPoint bind_endpoint(address_any, multicast_addr.port());
socket->AllowAddressReuse();
diff --git a/chromium/net/dns/mdns_client_unittest.cc b/chromium/net/dns/mdns_client_unittest.cc
index ae1a8d915db..b8f38cffac1 100644
--- a/chromium/net/dns/mdns_client_unittest.cc
+++ b/chromium/net/dns/mdns_client_unittest.cc
@@ -15,6 +15,7 @@
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "base/timer/mock_timer.h"
+#include "net/base/ip_address.h"
#include "net/base/rand_callback.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mdns_client_impl.h"
@@ -930,13 +931,13 @@ TEST_F(MDnsTest, ListenerReentrantDelete) {
ACTION_P(SaveIPAddress, ip_container) {
::testing::StaticAssertTypeEq<const RecordParsed*, arg1_type>();
- ::testing::StaticAssertTypeEq<IPAddressNumber*, ip_container_type>();
+ ::testing::StaticAssertTypeEq<IPAddress*, ip_container_type>();
*ip_container = arg1->template rdata<ARecordRdata>()->address();
}
TEST_F(MDnsTest, DoubleRecordDisagreeing) {
- IPAddressNumber address;
+ IPAddress address;
StrictMock<MockListenerDelegate> delegate_privet;
scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
@@ -951,7 +952,7 @@ TEST_F(MDnsTest, DoubleRecordDisagreeing) {
SimulatePacketReceive(kCorruptedPacketDoubleRecord,
sizeof(kCorruptedPacketDoubleRecord));
- EXPECT_EQ("2.3.4.5", IPAddressToString(address));
+ EXPECT_EQ("2.3.4.5", address.ToString());
}
TEST_F(MDnsTest, NsecWithListener) {
diff --git a/chromium/net/dns/mock_host_resolver.cc b/chromium/net/dns/mock_host_resolver.cc
index 42ec6b9a532..b734cd319da 100644
--- a/chromium/net/dns/mock_host_resolver.cc
+++ b/chromium/net/dns/mock_host_resolver.cc
@@ -17,9 +17,9 @@
#include "base/strings/string_util.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/platform_thread.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/host_cache.h"
@@ -45,12 +45,12 @@ int ParseAddressList(const std::string& host_list,
addrlist->set_canonical_name(canonical_name);
for (const base::StringPiece& address : base::SplitStringPiece(
host_list, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
- IPAddressNumber ip_number;
- if (!ParseIPLiteralToNumber(address, &ip_number)) {
+ IPAddress ip_address;
+ if (!ip_address.AssignFromIPLiteral(address)) {
LOG(WARNING) << "Not a supported IP literal: " << address.as_string();
return ERR_UNEXPECTED;
}
- addrlist->push_back(IPEndPoint(ip_number, 0));
+ addrlist->push_back(IPEndPoint(ip_address, 0));
}
return OK;
}
@@ -155,15 +155,15 @@ MockHostResolverBase::MockHostResolverBase(bool use_caching)
int MockHostResolverBase::ResolveFromIPLiteralOrCache(const RequestInfo& info,
AddressList* addresses) {
- IPAddressNumber ip;
- if (ParseIPLiteralToNumber(info.hostname(), &ip)) {
+ IPAddress ip_address;
+ if (ip_address.AssignFromIPLiteral(info.hostname())) {
// This matches the behavior HostResolverImpl.
if (info.address_family() != ADDRESS_FAMILY_UNSPECIFIED &&
- info.address_family() != GetAddressFamily(ip)) {
+ info.address_family() != GetAddressFamily(ip_address)) {
return ERR_NAME_NOT_RESOLVED;
}
- *addresses = AddressList::CreateFromIPAddress(ip, info.port());
+ *addresses = AddressList::CreateFromIPAddress(ip_address, info.port());
if (info.host_resolver_flags() & HOST_RESOLVER_CANONNAME)
addresses->SetDefaultCanonicalName();
return OK;
@@ -285,8 +285,8 @@ void RuleBasedHostResolverProc::AddIPLiteralRule(
const std::string& canonical_name) {
// Literals are always resolved to themselves by HostResolverImpl,
// consequently we do not support remapping them.
- IPAddressNumber ip_number;
- DCHECK(!ParseIPLiteralToNumber(host_pattern, &ip_number));
+ IPAddress ip_address;
+ DCHECK(!ip_address.AssignFromIPLiteral(host_pattern));
HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
if (!canonical_name.empty())
diff --git a/chromium/net/dns/mock_mdns_socket_factory.h b/chromium/net/dns/mock_mdns_socket_factory.h
index a5b14222ce5..179fb390e98 100644
--- a/chromium/net/dns/mock_mdns_socket_factory.h
+++ b/chromium/net/dns/mock_mdns_socket_factory.h
@@ -16,6 +16,8 @@
namespace net {
+class IPAddress;
+
class MockMDnsDatagramServerSocket : public DatagramServerSocket {
public:
explicit MockMDnsDatagramServerSocket(AddressFamily address_family);
@@ -51,8 +53,8 @@ class MockMDnsDatagramServerSocket : public DatagramServerSocket {
MOCK_METHOD0(AllowAddressReuse, void());
MOCK_METHOD0(AllowBroadcast, void());
- MOCK_CONST_METHOD1(JoinGroup, int(const IPAddressNumber& group_address));
- MOCK_CONST_METHOD1(LeaveGroup, int(const IPAddressNumber& address));
+ MOCK_CONST_METHOD1(JoinGroup, int(const IPAddress& group_address));
+ MOCK_CONST_METHOD1(LeaveGroup, int(const IPAddress& address));
MOCK_METHOD1(SetMulticastInterface, int(uint32_t interface_index));
MOCK_METHOD1(SetMulticastTimeToLive, int(int ttl));
diff --git a/chromium/net/dns/mojo_host_resolver_impl_unittest.cc b/chromium/net/dns/mojo_host_resolver_impl_unittest.cc
index 3bf32758ba3..6816a6b8e3d 100644
--- a/chromium/net/dns/mojo_host_resolver_impl_unittest.cc
+++ b/chromium/net/dns/mojo_host_resolver_impl_unittest.cc
@@ -14,7 +14,6 @@
#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/dns/mojo_host_type_converters.h"
#include "net/log/net_log.h"
@@ -143,7 +142,7 @@ class MojoHostResolverImplTest : public testing::Test {
interfaces::HostResolverRequestInfo::New();
request->host = host;
request->port = port;
- request->address_family = interfaces::ADDRESS_FAMILY_IPV4;
+ request->address_family = interfaces::AddressFamily::IPV4;
request->is_my_ip_address = is_my_ip_address;
return request;
}
diff --git a/chromium/net/dns/mojo_host_type_converters.cc b/chromium/net/dns/mojo_host_type_converters.cc
index 07dfe4df23f..2e404e0f056 100644
--- a/chromium/net/dns/mojo_host_type_converters.cc
+++ b/chromium/net/dns/mojo_host_type_converters.cc
@@ -8,18 +8,17 @@
#include "mojo/public/cpp/bindings/type_converter.h"
#include "net/base/address_list.h"
-#include "net/base/net_util.h"
namespace net {
namespace {
AddressFamily AddressFamilyFromMojo(interfaces::AddressFamily address_family) {
switch (address_family) {
- case interfaces::ADDRESS_FAMILY_UNSPECIFIED:
+ case interfaces::AddressFamily::UNSPECIFIED:
return ADDRESS_FAMILY_UNSPECIFIED;
- case interfaces::ADDRESS_FAMILY_IPV4:
+ case interfaces::AddressFamily::IPV4:
return ADDRESS_FAMILY_IPV4;
- case interfaces::ADDRESS_FAMILY_IPV6:
+ case interfaces::AddressFamily::IPV6:
return ADDRESS_FAMILY_IPV6;
}
NOTREACHED();
@@ -29,14 +28,14 @@ AddressFamily AddressFamilyFromMojo(interfaces::AddressFamily address_family) {
interfaces::AddressFamily AddressFamilyToMojo(AddressFamily address_family) {
switch (address_family) {
case ADDRESS_FAMILY_UNSPECIFIED:
- return interfaces::ADDRESS_FAMILY_UNSPECIFIED;
+ return interfaces::AddressFamily::UNSPECIFIED;
case ADDRESS_FAMILY_IPV4:
- return interfaces::ADDRESS_FAMILY_IPV4;
+ return interfaces::AddressFamily::IPV4;
case ADDRESS_FAMILY_IPV6:
- return interfaces::ADDRESS_FAMILY_IPV6;
+ return interfaces::AddressFamily::IPV6;
}
NOTREACHED();
- return interfaces::ADDRESS_FAMILY_UNSPECIFIED;
+ return interfaces::AddressFamily::UNSPECIFIED;
}
} // namespace
@@ -77,7 +76,7 @@ TypeConverter<net::interfaces::AddressListPtr, net::AddressList>::Convert(
for (const auto& endpoint : obj) {
net::interfaces::IPEndPointPtr ep(net::interfaces::IPEndPoint::New());
ep->port = endpoint.port();
- ep->address = mojo::Array<uint8_t>::From(endpoint.address());
+ ep->address = mojo::Array<uint8_t>::From(endpoint.address().bytes());
result->addresses.push_back(std::move(ep));
}
return result;
diff --git a/chromium/net/dns/record_rdata.cc b/chromium/net/dns/record_rdata.cc
index 22134737b05..be9d387f36a 100644
--- a/chromium/net/dns/record_rdata.cc
+++ b/chromium/net/dns/record_rdata.cc
@@ -65,16 +65,12 @@ ARecordRdata::~ARecordRdata() {
scoped_ptr<ARecordRdata> ARecordRdata::Create(
const base::StringPiece& data,
const DnsRecordParser& parser) {
- if (data.size() != kIPv4AddressSize)
+ if (data.size() != IPAddress::kIPv4AddressSize)
return scoped_ptr<ARecordRdata>();
scoped_ptr<ARecordRdata> rdata(new ARecordRdata);
-
- rdata->address_.resize(kIPv4AddressSize);
- for (unsigned i = 0; i < kIPv4AddressSize; ++i) {
- rdata->address_[i] = data[i];
- }
-
+ rdata->address_ =
+ IPAddress(reinterpret_cast<const uint8_t*>(data.data()), data.length());
return rdata;
}
@@ -98,16 +94,12 @@ AAAARecordRdata::~AAAARecordRdata() {
scoped_ptr<AAAARecordRdata> AAAARecordRdata::Create(
const base::StringPiece& data,
const DnsRecordParser& parser) {
- if (data.size() != kIPv6AddressSize)
+ if (data.size() != IPAddress::kIPv6AddressSize)
return scoped_ptr<AAAARecordRdata>();
scoped_ptr<AAAARecordRdata> rdata(new AAAARecordRdata);
-
- rdata->address_.resize(kIPv6AddressSize);
- for (unsigned i = 0; i < kIPv6AddressSize; ++i) {
- rdata->address_[i] = data[i];
- }
-
+ rdata->address_ =
+ IPAddress(reinterpret_cast<const uint8_t*>(data.data()), data.length());
return rdata;
}
diff --git a/chromium/net/dns/record_rdata.h b/chromium/net/dns/record_rdata.h
index 8184edd62f4..fea1f6b544d 100644
--- a/chromium/net/dns/record_rdata.h
+++ b/chromium/net/dns/record_rdata.h
@@ -14,7 +14,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "net/base/net_export.h"
#include "net/dns/dns_protocol.h"
@@ -83,12 +83,12 @@ class NET_EXPORT_PRIVATE ARecordRdata : public RecordRdata {
bool IsEqual(const RecordRdata* other) const override;
uint16_t Type() const override;
- const IPAddressNumber& address() const { return address_; }
+ const IPAddress& address() const { return address_; }
private:
ARecordRdata();
- IPAddressNumber address_;
+ IPAddress address_;
DISALLOW_COPY_AND_ASSIGN(ARecordRdata);
};
@@ -105,12 +105,12 @@ class NET_EXPORT_PRIVATE AAAARecordRdata : public RecordRdata {
bool IsEqual(const RecordRdata* other) const override;
uint16_t Type() const override;
- const IPAddressNumber& address() const { return address_; }
+ const IPAddress& address() const { return address_; }
private:
AAAARecordRdata();
- IPAddressNumber address_;
+ IPAddress address_;
DISALLOW_COPY_AND_ASSIGN(AAAARecordRdata);
};
diff --git a/chromium/net/dns/record_rdata_unittest.cc b/chromium/net/dns/record_rdata_unittest.cc
index d83f497cb42..5db22e64473 100644
--- a/chromium/net/dns/record_rdata_unittest.cc
+++ b/chromium/net/dns/record_rdata_unittest.cc
@@ -5,7 +5,6 @@
#include "net/dns/record_rdata.h"
#include "base/memory/scoped_ptr.h"
-#include "net/base/ip_address_number.h"
#include "net/dns/dns_response.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -76,7 +75,7 @@ TEST(RecordRdataTest, ParseARecord) {
record_obj = ARecordRdata::Create(record_strpiece, parser);
ASSERT_TRUE(record_obj != NULL);
- ASSERT_EQ("127.0.0.1", IPAddressToString(record_obj->address()));
+ ASSERT_EQ("127.0.0.1", record_obj->address().ToString());
ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
}
@@ -98,8 +97,7 @@ TEST(RecordRdataTest, ParseAAAARecord) {
record_obj = AAAARecordRdata::Create(record_strpiece, parser);
ASSERT_TRUE(record_obj != NULL);
- ASSERT_EQ("1234:5678::9",
- IPAddressToString(record_obj->address()));
+ ASSERT_EQ("1234:5678::9", record_obj->address().ToString());
ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
}
diff --git a/chromium/net/docs/README.txt b/chromium/net/docs/README.txt
new file mode 100644
index 00000000000..cf6c2027c1d
--- /dev/null
+++ b/chromium/net/docs/README.txt
@@ -0,0 +1,20 @@
+To generate the output HTML from an input markdown file on Unix
+machines, execute the command:
+
+ PYTHONPATH=../../third_party python -m markdown -f <output>.html <input>.md
+
+On Windows machines, execute:
+
+ set PYTHONPATH=..\..\third_party
+ python -m markdown -f <output>.html <input>.md
+
+(This command line assumes that the net/docs directory is the current
+directory; if that's not the case, adjust the path to src/third_party
+to be accurate from whatever directory the command is executed from.)
+
+The diagrams included in the network stack documentation were
+generated with Graphviz, and both source (.dot) and output (.svg) are
+included in the repository. If graphviz is installed, the output may
+be regenerated from the source via:
+
+ dot dot -Tsvg <name>.dot > <name>.svg
diff --git a/chromium/net/docs/bug-triage-labels.md b/chromium/net/docs/bug-triage-labels.md
index 5f2b0d496c1..b8da2028d74 100644
--- a/chromium/net/docs/bug-triage-labels.md
+++ b/chromium/net/docs/bug-triage-labels.md
@@ -1,104 +1,104 @@
-# Chrome Network Bug Triage : Labels
+# Chrome Network Bug Triage : Components and labels
-## Some network label caveats
+## Some network component caveats
-**Cr-UI-Browser-Downloads**
+**UI>Browser>Downloads**
: Despite the name, this covers all issues related to downloading a file except
- saving entire pages (which is **Cr-Blink-SavePage**), not just UI issues.
+ 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.
-**Cr-UI-Browser-SafeBrowsing**
+**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 **Cr-UI-Browser-Downloads**, not SafeBrowsing.
+ belongs in **UI>Browser>Downloads**, not SafeBrowsing.
-**Cr-Internals-Network-SSL**
-: This includes issues that should be also tagged as **Cr-Security-UX**
+**Internals>Network>SSL**
+: This includes issues that should be also tagged as **Security>UX**
(certificate error pages or other security interstitials, omnibox indicators
that a page is secure), and more general SSL issues. If you see requests
that die in the SSL negotiation phase, in particular, this is often the
- correct label.
+ correct component.
-**Cr-Internals-Network-DataProxy**
+**Internals>Network>DataProxy**
: Flywheel / the Data Reduction Proxy. Issues require "Reduce Data Usage" be
turned on. Proxy url is [https://proxy.googlezip.net:443](), with
[http://compress.googlezip.net:80]() as a fallback. Currently Android and
iOS only.
-**Cr-Internals-Network-Cache**
+**Internals>Network>Cache**
: The cache is the layer that handles most range request logic (Though range
requests may also be issued by the PDF plugin, XHRs, or other components).
-**Cr-Internals-Network-SPDY**
+**Internals>Network>SPDY**
: Covers HTTP2 as well.
-**Cr-Internals-Network-HTTP**
+**Internals>Network>HTTP**
: Typically not used. Unclear what it covers, and there's no specific HTTP
owner.
-**Cr-Internals-Network-Logging**
+**Internals>Network>Logging**
: Covers **about:net-internals**, **about:net-export** as well as the what's
sent to the NetLog.
-**Cr-Internals-Network-Connectivity**
+**Internals>Network>Connectivity**
: Issues related to switching between networks, ERR_NETWORK_CHANGED, Chrome
thinking it's online when it's not / navigator.onLine inaccuracies, etc.
-**Cr-Internals-Network-Filters**
+**Internals>Network>Filters**
: Covers SDCH and gzip issues. ERR_CONTENT_DECODING_FAILED indicates a problem
at this layer, and bugs here can also cause response body corruption.
-## Common non-network labels
+## Common non-network components
-Bugs in these areas often receive the **Cr-Internals-Network** label, though
+Bugs in these areas often receive the **Internals>Network** component, though
they fall largely outside the purview of the network stack team:
-**Cr-Blink-Forms**
+**Blink>Forms**
: Issues submitting forms, forms having weird data, forms sending the wrong
method, etc.
-**Cr-Blink-Loader**
+**Blink>Loader**
: Cross origin issues are sometimes loader related. Blink also has an
in-memory cache, and when it's used, requests don't appear in
about:net-internals. Requests for the same URL are also often merged there
as well. This does *not* cover issues with content/browser/loader/ files.
-**Cr-Blink-ServiceWorker**
+**Blink>ServiceWorker**
-**Cr-Blink-Storage-AppCache**
+**Blink>Storage>AppCache**
-**Cr-Blink-Network-WebSockets**
-: Issues with the WebSockets. Attach this label to any issue about the
+**Blink>Network>WebSockets**
+: Issues with the WebSockets. Attach this component to any issue about the
WebSocket feature regardless of where the cause of the issue is (net/ or
Blink).
-**Cr-Blink-Network-FetchAPI**
+**Blink>Network>FetchAPI**
: Generic issues with the Fetch API - missing request or response
headers, multiple headers, etc. These will often run into issues in certain
- corner cases (Cross origin / CORS, proxy, whatever). Attach all labels that
+ corner cases (Cross origin / CORS, proxy, whatever). Attach all components that
seem appropriate.
-**Cr-Blink-Network-XHR**
+**Blink>Network>XHR**
: Generic issues with sync/async XHR requests.
-**Cr-Services-Sync**
+**Services>Sync**
: Sharing data/tabs/history/passwords/etc between machines not working.
-**Cr-Services-Chromoting**
+**Services>Chromoting**
-**Cr-Platform-Extensions**
+**Platform>Extensions**
: Issues extensions loading / not loading / hanging.
-**Cr-Platform-Extensions-API**
-: Issues with network related extension APIs should have this label.
+**Platform>Extensions>API**
+: Issues with network related extension APIs should have this component.
chrome.webRequest is the big one, I believe, but there are others.
-**Cr-Internals-Plugins-Pepper[-SDK]**
+**Internals>Plugins>Pepper[>SDK]**
-**Cr-UI-Browser-Omnibox**
+**UI>Browser>Omnibox**
: Basically any issue with the omnibox. URLs being treated as search queries
rather than navigations, dropdown results being weird, not handling certain
unicode characters, etc. If the issue is new TLDs not being recognized by
@@ -106,35 +106,37 @@ they fall largely outside the purview of the network stack team:
omnibox issue. Such TLD issues should be duped against
http://crbug.com/37436.
-**Cr-Internals-Media-Network**
+**Internals>Media>Network**
: Issues related to media. These often run into the 6 requests per hostname
issue, and also have fun interactions with the cache, particularly in the
range request case.
-**Cr-Internals-Plugins-PDF**
+**Internals>Plugins>PDF**
: Issues loading pdf files. These are often related to range requests, which
- also have some logic at the Internals-Network-Cache layer.
+ also have some logic at the Internals>Network>Cache layer.
-**Cr-UI-Browser-Navigation**
+**UI>Browser>Navigation**
-**Cr-UI-Browser-History**
+**UI>Browser>History**
: Issues which only appear with forward/back navigation.
-**Cr-OS-Systems-Network** / **Cr-OS-Systems-Mobile** / **Cr-OS-Systems-Bluetooth**
+**OS>Systems>Network** / **OS>Systems>Mobile** / **OS>Systems>Bluetooth**
: These should be used for issues with ChromeOS's platform network code, and
not net/ issues on ChromeOS.
-**Cr-Blink-SecurityFeature**
+**Blink>SecurityFeature**
: CORS / Cross origin issues. Main frame cross-origin navigation issues are
- often actually **Cr-UI-Browser-Navigation** issues.
+ often actually **UI>Browser>Navigation** issues.
-**Cr-Privacy**
+**Privacy**
: Privacy related bug (History, cookies discoverable by an entity that
shouldn't be able to do so, incognito state being saved in memory or on disk
beyond the lifetime of incognito tabs, etc). Generally used in conjunction
- with other labels.
+ with other components.
+
+## Common labels
**Type-Bug-Security**
: Security related bug (Allows for code execution from remote site, allows
- crossing security boundaries, unchecked array bounds,
- etc).
+ crossing security boundaries, unchecked array bounds, etc) should be tagged
+ with this label.
diff --git a/chromium/net/docs/bug-triage-suggested-workflow.md b/chromium/net/docs/bug-triage-suggested-workflow.md
index 43a8e41c88c..9be9f3c1a80 100644
--- a/chromium/net/docs/bug-triage-suggested-workflow.md
+++ b/chromium/net/docs/bug-triage-suggested-workflow.md
@@ -2,71 +2,16 @@
[TOC]
-## Looking for new crashers
-
-1. Go to [go/chromecrash](https://goto.google.com/chromecrash).
-
-2. For each platform, look through the releases for which releases to
- investigate. As per bug-triage.txt, this should be the most recent canary,
- the previous canary (if the most recent is less than a day old), and any of
- dev/beta/stable that were released in the last couple of days.
-
-3. For each release, in the "Process Type" frame, click on "browser".
-
-4. At the bottom of the "Magic Signature" frame, click "limit 1000". Reported
- crashers are sorted in decreasing order of the number of reports for that
- crash signature.
-
-5. Search the page for *"net::"*.
-
-6. For each found signature:
- * If there is a bug already filed, make sure it is correctly describing the
- current bug (e.g. not closed, or not describing a long-past issue), and
- make sure that if it is a *net* bug, that it is labeled as such.
- * Ignore signatures that only occur once, as memory corruption can easily
- cause one-off failures when the sample size is large enough.
- * Ignore signatures that only come from a single client ID, as individual
- machine malware and breakage can also easily cause one-off failures.
- * Click on the number of reports field to see details of crash. Ignore it
- if it doesn't appear to be a network bug.
- * Otherwise, file a new bug directly from chromecrash. Note that this may
- result in filing bugs for low- and very-low- frequency crashes. That's
- ok; the bug tracker is a better tool to figure out whether or not we put
- resources into those crashes than a snap judgement when filing bugs.
- * For each bug you file, include the following information:
- * The backtrace. Note that the backtrace should not be added to the
- bug if Restrict-View-Google isn't set on the bug as it may contain
- PII. Filing the bug from the crash reporter should do this
- automatically, but check.
- * The channel in which the bug is seen (canary/dev/beta/stable), its
- frequency in that channel, and its rank among crashers in the
- channel.
- * The frequency of this signature in recent releases. This information
- is available by:
- 1. Clicking on the signature in the "Magic Signature" list
- 2. Clicking "Edit" on the dremel query at the top of the page
- 3. Removing the "product.version='X.Y.Z.W' AND" string and clicking
- "Update".
- 4. Clicking "Limit 1000" in the Product Version list in the
- resulting page (without this, the listing will be restricted to
- the releases in which the signature is most common, which will
- often not include the canary/dev release being investigated).
- 5. Choose some subset of that list, or all of it, to include in the
- bug. Make sure to indicate if there is a defined point in the
- past before which the signature is not present.
-
## Identifying unlabeled network bugs on the tracker
* Look at new uncomfirmed 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).
-* Press **h** to bring up a preview of the bug text.
-
-* Use **j** and **k** to advance through bugs.
+* 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 in new tab.
+ 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
@@ -74,31 +19,51 @@
related. Be sure to check if other bug reports have that stack trace, and
mark as a dupe if so. Even if the bug isn't network related, paste the stack
trace in the bug, so no one else has to look up the crash stack from the ID.
- * If there's no other information than the crash ID, ask for more details
- and add the Needs-Feedback label.
+ * If there's just a blank form and a crash ID, just ignore the bug.
* If network causes are possible, ask for a net-internals log (If it's not a
browser crash) and attach the most specific internals-network label that's
- applicable. If there isn't an applicable narrower label, a clear owner for
- the issue, or there are multiple possibilities, attach the internals-network
- label and proceed with further investigation.
+ applicable. If there isn't an applicable narrower component, a clear owner
+ for the issue, or there are multiple possibilities, attach the
+ Internals>Network component and proceed with further investigation.
-* If non-network causes also seem possible, attach those labels as well.
+* If non-network causes also seem possible, attach those components as well.
-## Investigating Cr-Internals-Network bugs
+## Investigate UMA notifications
-* It's recommended that while on triage duty, you subscribe to the
- Cr-Internals-Network label. To do this, go to the issue tracker and click on
- [Subscriptions](https://code.google.com/p/chromium/issues/subscriptions).
- Enter "Cr-Internals-Network" and click submit.
+For each alert that fires, determine if it's a real alert and file a bug if so.
-* Look through uncomfirmed and untriaged Cr-Internals-Network bugs,
+* Don't file if the alert is coincident with a major volume change. The volume
+ at a particular date can be determined by hovering the mouse over the
+ appropriate location on the alert line.
+
+* Don't file if the alert is on a graph with very low volume (< ~200 data
+ points); it's probably noise, and we probably don't care even if it isn't.
+
+* Don't file if the graph is really noisy (but eyeball it to decide if there is
+ an underlying important shift under the noise).
+
+* Don't file if the alert is in the "Known Ignorable" list:
+ * SimpleCache on Windows
+ * DiskCache on Android.
+
+## Investigating component=Internals>Network bugs
+
+* It's recommended that while on triage duty, you subscribe to the
+ Internals>Network component (but not its subcomponents). To do this, go
+ to the issue tracker and then click "Saved Queries".
+ Add a query with these settings:
+ * Saved query name: Network Bug Triage
+ * Project: chromium
+ * Query: component=Internals>Network
+ * Subscription options: Notify Immediately
+
+* Look through uncomfirmed and untriaged component=Internals>Network bugs,
prioritizing those updated within the last week. [Use this issue tracker
- query](https://code.google.com/p/chromium/issues/list?can=2&q=Cr%3DInternals-Network+-status%3AAssigned+-status%3AStarted+-status%3AAvailable+&sort=-modified).
+ query](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=component%3DInternals%3ENetwork+status%3AUnconfirmed,Untriaged+-label:Needs-Feedback&sort=-modified).
* If more information is needed from the reporter, ask for it and add the
- Needs-Feedback label. If the reporter has answered an earlier request for
- information, remove that label.
+ Needs-Feedback label.
* While investigating a new issue, change the status to Untriaged.
@@ -107,28 +72,29 @@
it Type-Bug-Security. If it has privacy implication (History, cookies
discoverable by an entity that shouldn't be able to do so, incognito state
being saved in memory or on disk beyond the lifetime of incognito tabs, etc),
- mark it Cr-Privacy.
+ mark it with component Privacy.
-* For bugs that already have a more specific network label, go ahead and remove
- the Cr-Internals-Network label and move on.
+* For bugs that already have a more specific network component, go ahead and
+ remove the Internals>Network component to get them off the next triager's
+ radar and move on.
* Try to figure out if it's really a network bug. See common non-network
- labels section for description of common labels needed for issues incorrectly
- tagged as Cr-Internals-Network.
+ components section for description of common components for issues incorrectly
+ tagged as Internals>Network.
-* If it's not, attach appropriate labels and go no further.
+* If it's not, attach appropriate labels/components and go no further.
-* If it may be a network bug, attach additional possibly relevant labels if
+* If it may be a network bug, attach additional possibly relevant component if
any, and continue investigating. Once you either determine it's a
- non-network bug, or figure out accurate more specific network labels, your
+ non-network bug, or figure out accurate more specific network components, your
job is done, though you should still ask for a net-internals dump if it seems
likely to be useful.
* Note that ChromeOS-specific network-related code (Captive portal detection,
connectivity detection, login, etc) may not all have appropriate more
- specific labels, but are not in areas handled by the network stack team.
- Just make sure those have the OS-Chrome label, and any more specific labels
- if applicable, and then move on.
+ specific subcomponents, but are not in areas handled by the network stack
+ team. Just make sure those have the OS-Chrome label, and any more specific
+ labels if applicable, and then move on.
* Gather data and investigate.
* Remember to add the Needs-Feedback label whenever waiting for the user to
@@ -142,8 +108,8 @@
https://sites.google.com/a/chromium.org/dev/for-testers/providing-network-details.
Can just grab the link from about:net-internals, as needed.
-* Try to figure out what's going on, and which more specific network label is
- most appropriate.
+* Try to figure out what's going on, and which more specific network component
+ is most appropriate.
* If it's a regression, browse through the git history of relevant files to try
and figure out when it regressed. CC authors / primary reviewers of any
@@ -156,36 +122,59 @@
Write up a net-internals tips and tricks docs.
* If it appears to be a bug in the unowned core of the network stack (i.e. no
- sublabel applies, or only the Cr-Internals-Network-HTTP sublabel applies, and
- there's no clear owner), try to figure out the exact cause.
+ subcomponent applies, or only the Internals>Network>HTTP subcomponent
+ applies, and there's no clear owner), try to figure out the exact cause.
-## Monitoring UMA histograms and Chirp/Gasper alerts
-
-Sign up to chrome-network-debugging@google.com mailing list to receive automated
-e-mails about UMA alerts. Chirp is the new alert system, sending automated
-e-mails with sender address finch-chirp@google.com. Gasper is the old alert
-system, sending automated e-mails with sender address gasper-alerts@google.com.
-While Chirp is of higher priority, Gasper is not deprecated yet, so both alerts
-should be monitored for the time being.
+## Looking for new crashers
-For each alert that fires, determine if it's a real alert and file a bug if so.
+1. Go to [go/chromecrash](https://goto.google.com/chromecrash).
-* Don't file if the alert is coincident with a major volume change. The volume
- at a particular date can be determined by hovering the mouse over the
- appropriate location on the alert line.
+2. For each platform, look through the releases for which releases to
+ investigate. As per bug-triage.txt, this should be the most recent canary,
+ the previous canary (if the most recent is less than a day old), and any of
+ dev/beta/stable that were released in the last couple of days.
-* Don't file if the alert is on a graph with very low volume (< ~200 data
- points); it's probably noise, and we probably don't care even if it isn't.
+3. For each release, in the "Process Type" frame, click on "browser".
-* Don't file if the graph is really noisy (but eyeball it to decide if there is
- an underlying important shift under the noise).
+4. At the bottom of the "Magic Signature" frame, click "limit 1000" (Or reduce
+ the limit to 100 first, as that's all the triager needs to look at).
+ Reported crashers are sorted in decreasing order of the number of reports for
+ that crash signature.
-* Don't file if the alert is in the "Known Ignorable" list:
- * SimpleCache on Windows
- * DiskCache on Android.
+5. Search the page for *"net::"*.
-For each alert, respond to chrome-network-debugging@google.com with a summary of
-the action you've taken and why, including issue link if an issue was filed.
+6. For each found signature:
+ * Ignore signatures that only occur once or twice, as memory corruption can
+ easily cause one-off failures when the sample size is large enough. Also
+ ignore crashers that are not in the top 100 for that platform / release.
+ * If there is a bug already filed, make sure it is correctly describing the
+ current bug (e.g. not closed, or not describing a long-past issue), and
+ make sure that if it is a *net* bug, that it is labeled as such.
+ * Ignore signatures that only come from one or two client IDs, as individual
+ machine malware and breakage can cause one-off failures.
+ * Click on the number of reports field to see details of crash. Ignore it
+ if it doesn't appear to be a network bug.
+ * Otherwise, file a new bug directly from chromecrash.
+ * For each bug you file, include the following information:
+ * The backtrace. Note that the backtrace should not be added to the
+ bug if Restrict-View-Google isn't set on the bug as it may contain
+ PII. Filing the bug from the crash reporter should do this
+ automatically, but check.
+ * The channel in which the bug is seen (canary/dev/beta/stable), and its
+ rank among crashers in the channel.
+ * The frequency of this signature in recent releases. This information
+ is available by:
+ 1. Clicking on the signature in the "Magic Signature" list
+ 2. Clicking "Edit" on the dremel query at the top of the page
+ 3. Removing the "product.version='X.Y.Z.W' AND" string and clicking
+ "Update".
+ 4. Clicking "Limit 1000" in the Product Version list in the
+ resulting page (without this, the listing will be restricted to
+ the releases in which the signature is most common, which will
+ often not include the canary/dev release being investigated).
+ 5. Choose some subset of that list, or all of it, to include in the
+ bug. Make sure to indicate if there is a defined point in the
+ past before which the signature is not present.
## Investigating crashers
@@ -219,26 +208,3 @@ the action you've taken and why, including issue link if an issue was filed.
* Load crash dumps, try to figure out a cause. See
http://www.chromium.org/developers/crash-reports for more information
-
-## Dealing with old bugs
-
-* For all network issues (Even those with owners, or a more specific labels):
-
- * If the issue has had the Needs-Feedback label for over a month, verify it
- is waiting on feedback from the user. If not, remove the label.
- Otherwise, go ahead and mark the issue WontFix due to lack of response
- and suggest the user file a new bug if the issue is still present. [Use
- this issue tracker query for old Needs-Feedback
- issues](https://code.google.com/p/chromium/issues/list?can=2&q=Cr%3AInternals-Network%20Needs=Feedback+modified-before%3Atoday-30&sort=-modified).
-
- * If a bug is over 2 months old, and the underlying problem was never
- reproduced or really understood:
- * If it's over a year old, go ahead and mark the issue as Archived.
- * Otherwise, ask reporters if the issue is still present, and attach
- the Needs-Feedback label.
-
-* Old unconfirmed or untriaged Cr-Internals-Network issues can be investigated
- just like newer ones. Crashers should generally be given higher priority,
- since we can verify if they still occur, and then newer issues, as they're
- more likely to still be present, and more likely to have a still responsive
- bug reporter.
diff --git a/chromium/net/docs/bug-triage.md b/chromium/net/docs/bug-triage.md
index 38a7f63c3fc..415050b011e 100644
--- a/chromium/net/docs/bug-triage.md
+++ b/chromium/net/docs/bug-triage.md
@@ -6,16 +6,16 @@ label seems suitable.
## Responsibilities
-### Required:
-* Identify new crashers
-* Identify new network issues.
-* Request data about recent Cr-Internals-Network issue.
-* Investigate each recent Cr-Internals-Network issue.
-* Monitor UMA histograms and Chirp/Gasper alerts.
-
-### Best effort:
-* Investigate unowned and owned-but-forgotten net/ crashers
-* Investigate old bugs
+### Required, in rough order of priority:
+* Identify new network bugs on the tracker.
+* Investigate UMA notifications.
+* Investigate recent Internals>Network issues with no subcomponent.
+* Follow up on Needs-Feedback issues for all network components.
+* Identify and file bugs for significant new crashers.
+
+### Best effort, also in rough priority order:
+* Investigate unowned and owned-but-forgotten net/ crashers.
+* Investigate old bugs.
* Close obsolete bugs.
All of the above is to be done on each rotation. These responsibilities should
@@ -30,67 +30,106 @@ uniform, predictable two day commitment for all triagers.
### Required:
-* Identify new crashers that are potentially network related. You should check
- the most recent canary, the previous canary (if the most recent less than a
- day old), and any of dev/beta/stable that were released in the last couple of
- days, for each platform. File Cr-Internals-Network bugs on the tracker when
- new crashers are found.
-
-* Identify new network bugs, both on the bug tracker and on the crash server.
- All Unconfirmed issues filed during your triage rotation should be scanned,
- and, for suspected network bugs, a network label assigned. A triager is
- responsible for looking at bugs reported from noon PST / 3:00 pm EST of the
- last day of the previous triager's rotation until the same time on the last
- day of their rotation.
-
-* Investigate each recent (new comment within the past week or so)
- Cr-Internals-Network issue, driving getting information from reporters as
- needed, until you can do one of the following:
+* Identify new network bugs on the bug tracker. All Unconfirmed issues filed
+ during your triage rotation should be scanned, and, for suspected network
+ bugs, a network component assigned and an about:net-internals log requested.
+ A triager is responsible for looking at bugs reported from noon PST / 3:00 pm
+ EST of the last day of the previous triager's rotation until the same time on
+ the last day of their rotation. Once you've assigned a bug to a component,
+ mark it Untriaged, so other triagers sorting through Unconfirmed bugs won't
+ see it.
+
+ * For desktop bugs, ask for a net-internals log and give the user a link to
+ https://sites.google.com/a/chromium.org/dev/for-testers/providing-network-details
+ (A link there appears on about:net-internals, for easy reference) for
+ instructions. On mobile, point them to about:net-export. In either case,
+ attach the Needs-Feedback label.
+
+* Investigate UMA notifications.
+
+ * UMA notifications ("chirps") are alerts based on UMA histograms that are
+ sent to chrome-network-debugging@google.com. Triagers should subscribe
+ to this list. When an alert fires, the triager should determine if the
+ alert looks to be real and file a bug with the appropriate label if so.
+ Note that if no label more specific than Internals>Network is appropriate,
+ the responsibility remains with the triager to continue investigating the
+ bug, as above.
+
+ * The triager is responsible for looking at any notification previous
+ triagers did not, so when an issue is investigated, the person who did
+ so should respond to chrome-network-debugging@google.com with a short
+ email, describing their conclusions. Future triagers can then use the
+ fact an alert was responded to as an inidicator of which of them need
+ to be followed up on. Alerts fired before the beginning of the
+ previous triager's rotation may be ignored.
+
+* Investigate [Uncomfirmed / Untriaged Internals>Network issues that don't belong to a more specific network component](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=component%3DInternals%3ENetwork+status%3AUnconfirmed,Untriaged+-label:Needs-Feedback&sort=-modified),
+ prioritizing the most recent issues, ones with the most responsive reporters,
+ and major crashers. This will generally take up the majority of your time as
+ triager. Continue digging until you can do one of the following:
* Mark it as *WontFix* (working as intended, obsolete issue) or a
duplicate.
* Mark it as a feature request.
- * Remove the Cr-Internals-Network label, replacing it with at least one
- more specific network label or non-network label. Promptly adding
- non-network labels when appropriate is important to get new bugs in front
- of someone familiar with the relevant code, and to remove them from the
- next triager's radar. Because of the way the bug report wizard works, a
- lot of bugs incorrectly end up with the network label.
+ * Mark it as Needs-Feedback.
+
+ * Remove the Internals>Network component, replacing it with at least one
+ more specific network component or non-network component. Replacing the
+ Internals>Network component gets it off the next triager's radar, and
+ in front of someone more familiar with the relevant code. Note that
+ due to the way the bug report wizard works, a lot of bugs incorrectly end
+ up with the network component.
+
+ * The issue is assigned to an appropriate owner, and make sure to mark it
+ as "assigned" so the next triager doesn't run into it.
+
+ * If there is no more specific component for a bug, it should be
+ investigated by the triager until we have a good understanding of the
+ cause of the problem, and some idea how it should be fixed, at which point
+ its status should be set to Available. Future triagers should ignore bugs
+ with this status, unless investigating stale bugs.
- * The issue is assigned to an appropriate owner.
+* 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).
- * If there is no more specific label for a bug, it should be investigated
- until we have a good understanding of the cause of the problem, and some
- idea how it should be fixed, at which point its status should be set to
- Available. Future triagers should ignore bugs with this status, unless
- investigating stale bugs.
+ * Remove label once feedback is provided. Continue to investigate, if
+ the previous section applies.
-* Monitor UMA histograms and Chirp/Gasper alerts.
+ * If the Needs-Feedback label has been present for one week, ping the
+ reporter.
- * For each Chirp and Gasper alert that fires, the triager should determine
- if the alert is real (not due to noise), and file a bug with the
- appropriate label if so. Note that if no label more specific than
- Cr-Internals-Network is appropriate, the responsibility remains with the
- triager to continue investigating the bug, as above.
+ * Archive after two weeks with no feedback, telling users to file a new
+ bug if they still have the issue, with the requested information, unless
+ the reporter indicates they'll provide data when they can. In that case,
+ use your own judgment for further pings or archiving.
+
+* Identify significant new browser process
+ [crashers](https://goto.google.com/chromecrash) that are potentially network
+ related. You should look at crashes for the most recent canary that has at
+ least a day of data, and if there's been a dev or beta release from the start
+ of the last triager's shift to the start of yours, you should also look at
+ that once it has at least a day of data. Recent releases available
+ [here](https://omahaproxy.appspot.com/). If both dev and beta have been
+ released in that period, just look at beta. File Internals>Network bugs on
+ the tracker when new crashers are found. Bugs should only be filed for
+ crashes that are both in the top 100 for each release and occurred for more
+ than two users.
+
+ * Make sure to check for new crashes on all platforms, not just Windows.
### Best Effort (As you have time):
+* Investigate old bugs, and bugs associated with Internals>Network
+ subcomponents.
+
* Investigate unowned and owned but forgotten net/ crashers that are still
occurring (As indicated by
[go/chromecrash](https://goto.google.com/chromecrash)), prioritizing frequent
and long standing crashers.
-* Investigate old bugs, prioritizing the most recent.
-
* Close obsolete bugs.
-If you've investigated an issue (in code you don't normally work on) to an
-extent that you know how to fix it, and the fix is simple, feel free to take
-ownership of the issue and create a patch while on triage duty, but other tasks
-should take priority.
-
See [bug-triage-suggested-workflow.md](bug-triage-suggested-workflow.md) for
suggested workflows.
@@ -98,4 +137,4 @@ See [bug-triage-labels.md](bug-triage-labels.md) for labeling tips for network
and non-network bugs.
See [crash-course-in-net-internals.md](crash-course-in-net-internals.md) for
-some help on getting started with about:net-internals debugging. \ No newline at end of file
+some help on getting started with about:net-internals debugging.
diff --git a/chromium/net/docs/crash-course-in-net-internals.md b/chromium/net/docs/crash-course-in-net-internals.md
index 5dcfb244ced..fa2094c6bf9 100644
--- a/chromium/net/docs/crash-course-in-net-internals.md
+++ b/chromium/net/docs/crash-course-in-net-internals.md
@@ -5,8 +5,8 @@ with about:net-internals, with some commonly useful tips and tricks. This
document is aimed more at how to get started using some of its features to
investigate bug reports, rather than as a feature overview.
-It would probably be useful to read [life-of-a-url-request.md](
-life-of-a-url-request.md) before this document.
+It would probably be useful to read
+[life-of-a-url-request.md](life-of-a-url-request.md) before this document.
# What Data Net-Internals Contains
@@ -34,11 +34,12 @@ covers), but it's good to be aware of this distinction.
The Event View shows events logged by the NetLog. The NetLog model is that
long-lived network stack objects, called sources, emit events over their
-lifetime. 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. When looking at the code, a "BoundNetLog" 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.
"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
@@ -99,9 +100,8 @@ in a lot of cases:
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 sort:duration" will show the lonest-lived requests (as of
-when about:net-internals was opened) first. This is often useful in finding
-hung or slow requests.
+* "type:URL_REQUEST sort:duration" will show the longest-lived requests first.
+This is often useful in finding hung or slow requests.
For a list of other filter commands, you can mouse over the question mark on
about:net-internals.
diff --git a/chromium/net/docs/life-of-a-url-request.md b/chromium/net/docs/life-of-a-url-request.md
index 63f55f698bc..4de3567f992 100644
--- a/chromium/net/docs/life-of-a-url-request.md
+++ b/chromium/net/docs/life-of-a-url-request.md
@@ -293,6 +293,24 @@ Either way, the ClientSocketHandle returns the socket is then returned to the
socket pool, either for reuse or so the socket pool knows it has another free
socket slot.
+### Object Relationships and Ownership
+
+A sample of the object relationships involved in the above process is
+diagramed here:
+
+![Object Relationship Diagram for URLRequest lifetime](url_request.svg)
+
+There are a couple of points in the above diagram that do not come
+clear visually:
+
+* The method that generates the filter chain that is hung off the
+ URLRequestJob is declared on URLRequestJob, but the only current
+ implementation of it is on URLRequestHttpJob, so the generation is
+ shown as happening from that class.
+* HttpTransactions of different types are layered; i.e. a
+ HttpCache::Transaction contains a pointer to an HttpTransaction, but
+ that pointed-to HttpTransaction generally is an
+ HttpNetworkTransaction.
# Additional Topics
@@ -418,6 +436,33 @@ pool, they must have their own distinct group name. This is needed so that, for
instance, SSL and HTTP connections won't be grouped together in the
TcpClientSocketPool, which the SSLClientSocketPool sits on top of.
+### Socket Pool Class Relationships
+
+The relationships between the important classes in the socket pools is
+shown diagrammatically for the lowest layer socket pool
+(TransportSocketPool) below.
+
+![Object Relationship Diagram for Socket Pools](pools.svg)
+
+The ClientSocketPoolBase is a template class templatized on the class
+containing the parameters for the appropriate type of socket (in this
+case TransportSocketParams). It contains a pointer to the
+ClientSocketPoolBaseHelper, which contains all the type-independent
+machinery of the socket pool.
+
+When socket pools are initialized, they in turn initialize their
+templatized ClientSocketPoolBase member with an object with which it
+should create connect jobs. That object must derive from
+ClientSocketPoolBase::ConnectJobFactory templatized by the same type
+as the ClientSocketPoolBase. (In the case of the diagram above, that
+object is a TransportConnectJobFactory, which derives from
+ClientSocketPoolBase::ConnectJobFactory&lt;TransportSocketParams&gt;.)
+Internally, that object is wrapped in a type-unsafe wrapper
+(ClientSocketPoolBase::ConnectJobFactoryAdaptor) so that it can be
+passed to the initialization of the ClientSocketPoolBaseHelper. This
+allows the helper to create connect jobs while preserving a type-safe
+API to the initialization of the socket pool.
+
### SSL
When an SSL connection is needed, the ClientSocketPoolManager assembles the
diff --git a/chromium/net/docs/pools.dot b/chromium/net/docs/pools.dot
new file mode 100644
index 00000000000..271d98de138
--- /dev/null
+++ b/chromium/net/docs/pools.dot
@@ -0,0 +1,101 @@
+digraph SocketPools {
+ subgraph cluster_legend {
+ label="Legend";
+
+ ## The following legend is an attempt to match UML notation,
+ ## except for template_class and Factory->object, which are
+ ## invented for this diagram.
+ BaseClass;
+ SubClass [label="Derived Class"];
+ Whole;
+ Part;
+ A;
+ B;
+ Interface [label="Interface / ABC", style=dashed];
+ template_class [shape=diamond]; # Link will name parameter(s)
+
+ SubClass -> BaseClass [arrowhead="empty"];
+ SubClass -> Interface [arrowhead="empty", style=dashed];
+ Part -> Whole [arrowhead="diamond", label="ownership"];
+ Part -> Whole [arrowhead="odiamond", label="pointer"];
+ RefCountedPart -> Whole [arrowhead="diamond", color=red,
+ label="partial\nownership"];
+ A -> B [arrowhead="none", headlabel="?..?", taillabel="?..?",
+ label="association"];
+ // Often a "subgraph { rank=same; .. }" is used to wrap the
+ // below to make the generative relationship distinctive
+ // from the other class relationships.
+ Factory -> object [arrowhead=veevee];
+ };
+
+ ClientSocketPoolBase [shape=diamond];
+ ClientSocketPoolBaseHelper;
+
+ ClientSocketPoolBaseHelper_ConnectJobFactory
+ [style=dotted, label="ClientSocketPoolBaseHelper::\nConnectJobFactory"];
+ ClientSocketPoolBase_ConnectJobFactory
+ [style=dotted, shape=diamond,
+ label="ClientSocketPoolBase::\nConnectJobFactory"];
+ ClientSocketPoolBase_ConnectJobFactoryAdaptor
+ [shape=diamond,
+ label="ClientSocketPoolBase::\nConnectJobFactoryAdaptor"];
+
+ HigherLayeredPool [style=dotted];
+ LowerLayeredPool [style=dotted];
+ ClientSocketPool [style=dotted];
+
+ ConnectJob [style=dashed];
+ ConnectJob_Delegate [style=dotted, label="ConnectJob::Delegate"];
+
+ ClientSocketFactory [style=dotted];
+ DefaultClientSocketFactory;
+ TCPClientSocket;
+ StreamSocket [style=dotted]
+ Socket;
+
+ TransportSocketParams;
+ TransportConnectJobHelper;
+ TransportConnectJobFactory;
+ TransportConnectJob;
+
+ TransportClientSocketPool -> ClientSocketPool [arrowhead=empty];
+ ClientSocketPool -> LowerLayeredPool [arrowhead=empty];
+ ClientSocketPoolBaseHelper -> ConnectJob_Delegate [arrowhead=empty];
+ TransportConnectJobFactory -> ClientSocketPoolBase_ConnectJobFactory
+ [arrowhead=empty, label="TransportSocketParams"];
+ ClientSocketPoolBase_ConnectJobFactoryAdaptor ->
+ ClientSocketPoolBaseHelper_ConnectJobFactory
+ [arrowhead=empty, arrowtail=none];
+ TransportConnectJob -> ConnectJob [arrowhead=empty];
+ DefaultClientSocketFactory -> ClientSocketFactory [arrowhead=empty];
+ StreamSocket -> Socket [arrowhead=empty]
+ TCPClientSocket -> StreamSocket [arrowhead=empty]
+
+ ClientSocketPoolBaseHelper -> ClientSocketPoolBase [arrowhead=diamond];
+ ClientSocketPoolBase -> TransportClientSocketPool
+ [arrowhead=diamond, label="TransportSocketParams"];
+ ClientSocketPoolBase_ConnectJobFactory ->
+ ClientSocketPoolBase_ConnectJobFactoryAdaptor [arrowhead=diamond];
+ ClientSocketPoolBaseHelper_ConnectJobFactory ->
+ ClientSocketPoolBaseHelper [arrowhead=diamond];
+ TransportConnectJobHelper -> TransportConnectJob [arrowhead=diamond];
+ TransportSocketParams -> TransportConnectJobHelper
+ [arrowhead=diamond, color=red];
+
+ ConnectJob -> ConnectJob_Delegate
+ [dir=back, arrowhead=none, arrowtail=odiamond];
+ HigherLayeredPool -> ClientSocketPoolBaseHelper
+ [arrowhead=odiamond, taillabel="*"];
+ LowerLayeredPool -> ClientSocketPoolBaseHelper
+ [arrowhead=odiamond, taillabel="*"];
+ ClientSocketFactory -> ClientSocketPoolBaseHelper [arrowhead=odiamond];
+
+ subgraph {
+ rank=same;
+ ClientSocketPoolBaseHelper_ConnectJobFactory -> ConnectJob
+ [arrowhead=veevee];
+ }
+ ClientSocketPoolBase_ConnectJobFactory -> ConnectJob [arrowhead=veevee];
+ ClientSocketFactory -> TCPClientSocket [arrowhead=veevee]
+}
+
diff --git a/chromium/net/docs/pools.svg b/chromium/net/docs/pools.svg
new file mode 100644
index 00000000000..fb4efb60607
--- /dev/null
+++ b/chromium/net/docs/pools.svg
@@ -0,0 +1,335 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.34.0 (20130907.0228)
+ -->
+<!-- Title: SocketPools Pages: 1 -->
+<svg width="1612pt" height="653pt"
+ viewBox="0.00 0.00 1612.00 653.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 649)">
+<title>SocketPools</title>
+<polygon fill="white" stroke="white" points="-4,4 -4,-649 1608,-649 1608,4 -4,4"/>
+<g id="clust1" class="cluster"><title>cluster_legend</title>
+<polygon fill="none" stroke="black" points="8,-440 8,-637 743,-637 743,-440 8,-440"/>
+<text text-anchor="middle" x="375.5" y="-621.8" font-family="Times,serif" font-size="14.00">Legend</text>
+</g>
+<!-- BaseClass -->
+<g id="node1" class="node"><title>BaseClass</title>
+<ellipse fill="none" stroke="black" cx="687" cy="-466" rx="48.1437" ry="18"/>
+<text text-anchor="middle" x="687" y="-462.3" font-family="Times,serif" font-size="14.00">BaseClass</text>
+</g>
+<!-- SubClass -->
+<g id="node2" class="node"><title>SubClass</title>
+<ellipse fill="none" stroke="black" cx="673" cy="-588" rx="61.6163" ry="18"/>
+<text text-anchor="middle" x="673" y="-584.3" font-family="Times,serif" font-size="14.00">Derived Class</text>
+</g>
+<!-- SubClass&#45;&gt;BaseClass -->
+<g id="edge1" class="edge"><title>SubClass&#45;&gt;BaseClass</title>
+<path fill="none" stroke="black" d="M675.006,-569.807C677.303,-550.114 681.099,-517.583 683.805,-494.39"/>
+<polygon fill="none" stroke="black" points="687.315,-494.499 684.998,-484.161 680.363,-493.688 687.315,-494.499"/>
+</g>
+<!-- Interface -->
+<g id="node7" class="node"><title>Interface</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="5,2" cx="552" cy="-466" rx="68.3417" ry="18"/>
+<text text-anchor="middle" x="552" y="-462.3" font-family="Times,serif" font-size="14.00">Interface / ABC</text>
+</g>
+<!-- SubClass&#45;&gt;Interface -->
+<g id="edge2" class="edge"><title>SubClass&#45;&gt;Interface</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M656.175,-570.315C635.316,-549.627 599.623,-514.23 575.922,-490.724"/>
+<polygon fill="none" stroke="black" points="578.247,-488.1 568.682,-483.544 573.317,-493.071 578.247,-488.1"/>
+</g>
+<!-- Whole -->
+<g id="node3" class="node"><title>Whole</title>
+<ellipse fill="none" stroke="black" cx="430" cy="-466" rx="35.1455" ry="18"/>
+<text text-anchor="middle" x="430" y="-462.3" font-family="Times,serif" font-size="14.00">Whole</text>
+</g>
+<!-- Part -->
+<g id="node4" class="node"><title>Part</title>
+<ellipse fill="none" stroke="black" cx="409" cy="-588" rx="27" ry="18"/>
+<text text-anchor="middle" x="409" y="-584.3" font-family="Times,serif" font-size="14.00">Part</text>
+</g>
+<!-- Part&#45;&gt;Whole -->
+<g id="edge3" class="edge"><title>Part&#45;&gt;Whole</title>
+<path fill="none" stroke="black" d="M411.964,-570.061C415.322,-550.874 420.853,-519.267 424.906,-496.107"/>
+<polygon fill="black" stroke="black" points="424.914,-496.061 422.008,-489.462 426.983,-484.241 429.889,-490.841 424.914,-496.061"/>
+<text text-anchor="middle" x="450.5" y="-533.3" font-family="Times,serif" font-size="14.00">ownership</text>
+</g>
+<!-- Part&#45;&gt;Whole -->
+<g id="edge4" class="edge"><title>Part&#45;&gt;Whole</title>
+<path fill="none" stroke="black" d="M390.377,-574.55C383.219,-568.652 375.847,-560.934 372,-552 366.727,-539.754 366.735,-534.25 372,-522 377.706,-508.725 388.366,-497.15 399.005,-488.088"/>
+<polygon fill="none" stroke="black" points="399.207,-487.929 401.44,-481.072 408.628,-480.496 406.395,-487.353 399.207,-487.929"/>
+<text text-anchor="middle" x="392" y="-533.3" font-family="Times,serif" font-size="14.00">pointer</text>
+</g>
+<!-- A -->
+<g id="node5" class="node"><title>A</title>
+<ellipse fill="none" stroke="black" cx="137" cy="-588" rx="27" ry="18"/>
+<text text-anchor="middle" x="137" y="-584.3" font-family="Times,serif" font-size="14.00">A</text>
+</g>
+<!-- B -->
+<g id="node6" class="node"><title>B</title>
+<ellipse fill="none" stroke="black" cx="137" cy="-466" rx="27" ry="18"/>
+<text text-anchor="middle" x="137" y="-462.3" font-family="Times,serif" font-size="14.00">B</text>
+</g>
+<!-- A&#45;&gt;B -->
+<g id="edge6" class="edge"><title>A&#45;&gt;B</title>
+<path fill="none" stroke="black" d="M137,-569.807C137,-548.599 137,-512.502 137,-489.213"/>
+<polyline fill="none" stroke="black" points="137,-484.161 137,-489.161 "/>
+<text text-anchor="middle" x="168.5" y="-533.3" font-family="Times,serif" font-size="14.00">association</text>
+<text text-anchor="middle" x="127" y="-487.961" font-family="Times,serif" font-size="14.00">?..?</text>
+<text text-anchor="middle" x="127" y="-558.607" font-family="Times,serif" font-size="14.00">?..?</text>
+</g>
+<!-- template_class -->
+<g id="node8" class="node"><title>template_class</title>
+<polygon fill="none" stroke="black" points="273,-606 182.505,-588 273,-570 363.495,-588 273,-606"/>
+<text text-anchor="middle" x="273" y="-584.3" font-family="Times,serif" font-size="14.00">template_class</text>
+</g>
+<!-- RefCountedPart -->
+<g id="node9" class="node"><title>RefCountedPart</title>
+<ellipse fill="none" stroke="black" cx="524" cy="-588" rx="69.3156" ry="18"/>
+<text text-anchor="middle" x="524" y="-584.3" font-family="Times,serif" font-size="14.00">RefCountedPart</text>
+</g>
+<!-- RefCountedPart&#45;&gt;Whole -->
+<g id="edge5" class="edge"><title>RefCountedPart&#45;&gt;Whole</title>
+<path fill="none" stroke="red" d="M514.948,-570.026C507.41,-556.495 496.003,-537.34 484,-522 475.376,-510.979 464.787,-499.783 455.277,-490.396"/>
+<polygon fill="red" stroke="red" points="455.225,-490.346 448.13,-489.058 446.589,-482.014 453.684,-483.301 455.225,-490.346"/>
+<text text-anchor="middle" x="534.5" y="-540.8" font-family="Times,serif" font-size="14.00">partial</text>
+<text text-anchor="middle" x="534.5" y="-525.8" font-family="Times,serif" font-size="14.00">ownership</text>
+</g>
+<!-- Factory -->
+<g id="node10" class="node"><title>Factory</title>
+<ellipse fill="none" stroke="black" cx="54" cy="-588" rx="38.0212" ry="18"/>
+<text text-anchor="middle" x="54" y="-584.3" font-family="Times,serif" font-size="14.00">Factory</text>
+</g>
+<!-- object -->
+<g id="node11" class="node"><title>object</title>
+<ellipse fill="none" stroke="black" cx="54" cy="-466" rx="33.2209" ry="18"/>
+<text text-anchor="middle" x="54" y="-462.3" font-family="Times,serif" font-size="14.00">object</text>
+</g>
+<!-- Factory&#45;&gt;object -->
+<g id="edge7" class="edge"><title>Factory&#45;&gt;object</title>
+<path fill="none" stroke="black" d="M54,-569.807C54,-552.787 54,-526.178 54,-504.296"/>
+<polygon fill="black" stroke="black" points="54,-484.161 58.5,-494.161 54,-489.161 54,-494.161 54,-494.161 54,-494.161 54,-489.161 49.5,-494.161 54,-484.161 54,-484.161"/>
+<polygon fill="black" stroke="black" points="54,-494.161 58.5001,-504.161 54.0001,-499.161 54.0001,-504.161 54.0001,-504.161 54.0001,-504.161 54.0001,-499.161 49.5001,-504.161 54,-494.161 54,-494.161"/>
+</g>
+<!-- ClientSocketPoolBase -->
+<g id="node12" class="node"><title>ClientSocketPoolBase</title>
+<polygon fill="none" stroke="black" points="888,-606 757.72,-588 888,-570 1018.28,-588 888,-606"/>
+<text text-anchor="middle" x="888" y="-584.3" font-family="Times,serif" font-size="14.00">ClientSocketPoolBase</text>
+</g>
+<!-- TransportClientSocketPool -->
+<g id="node31" class="node"><title>TransportClientSocketPool</title>
+<ellipse fill="none" stroke="black" cx="901" cy="-466" rx="109.261" ry="18"/>
+<text text-anchor="middle" x="901" y="-462.3" font-family="Times,serif" font-size="14.00">TransportClientSocketPool</text>
+</g>
+<!-- ClientSocketPoolBase&#45;&gt;TransportClientSocketPool -->
+<g id="edge18" class="edge"><title>ClientSocketPoolBase&#45;&gt;TransportClientSocketPool</title>
+<path fill="none" stroke="black" d="M889.835,-570.061C891.904,-550.962 895.306,-519.56 897.812,-496.429"/>
+<polygon fill="black" stroke="black" points="897.84,-496.171 894.509,-489.775 899.132,-484.241 902.463,-490.637 897.84,-496.171"/>
+<text text-anchor="middle" x="961" y="-533.3" font-family="Times,serif" font-size="14.00">TransportSocketParams</text>
+</g>
+<!-- ClientSocketPoolBaseHelper -->
+<g id="node13" class="node"><title>ClientSocketPoolBaseHelper</title>
+<ellipse fill="none" stroke="black" cx="930" cy="-166" rx="116.484" ry="18"/>
+<text text-anchor="middle" x="930" y="-162.3" font-family="Times,serif" font-size="14.00">ClientSocketPoolBaseHelper</text>
+</g>
+<!-- ClientSocketPoolBaseHelper&#45;&gt;ClientSocketPoolBase -->
+<g id="edge17" class="edge"><title>ClientSocketPoolBaseHelper&#45;&gt;ClientSocketPoolBase</title>
+<path fill="none" stroke="black" d="M841.61,-177.778C801.552,-188.118 763,-208.365 763,-248 763,-467 763,-467 763,-467 763,-514.437 810.427,-548.965 846.854,-568.488"/>
+<polygon fill="black" stroke="black" points="847.06,-568.593 854.224,-567.768 857.741,-574.063 850.577,-574.888 847.06,-568.593"/>
+</g>
+<!-- ConnectJob_Delegate -->
+<g id="node21" class="node"><title>ConnectJob_Delegate</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="1,5" cx="1302" cy="-92" rx="90.4879" ry="18"/>
+<text text-anchor="middle" x="1302" y="-88.3" font-family="Times,serif" font-size="14.00">ConnectJob::Delegate</text>
+</g>
+<!-- ClientSocketPoolBaseHelper&#45;&gt;ConnectJob_Delegate -->
+<g id="edge10" class="edge"><title>ClientSocketPoolBaseHelper&#45;&gt;ConnectJob_Delegate</title>
+<path fill="none" stroke="black" d="M999.534,-151.542C1065.14,-138.843 1163.1,-119.884 1229.62,-107.008"/>
+<polygon fill="none" stroke="black" points="1230.46,-110.412 1239.61,-105.075 1229.13,-103.539 1230.46,-110.412"/>
+</g>
+<!-- ClientSocketPoolBaseHelper_ConnectJobFactory -->
+<g id="node14" class="node"><title>ClientSocketPoolBaseHelper_ConnectJobFactory</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="1,5" cx="1104" cy="-249" rx="132.404" ry="26.7407"/>
+<text text-anchor="middle" x="1104" y="-252.8" font-family="Times,serif" font-size="14.00">ClientSocketPoolBaseHelper::</text>
+<text text-anchor="middle" x="1104" y="-237.8" font-family="Times,serif" font-size="14.00">ConnectJobFactory</text>
+</g>
+<!-- ClientSocketPoolBaseHelper_ConnectJobFactory&#45;&gt;ClientSocketPoolBaseHelper -->
+<g id="edge20" class="edge"><title>ClientSocketPoolBaseHelper_ConnectJobFactory&#45;&gt;ClientSocketPoolBaseHelper</title>
+<path fill="none" stroke="black" d="M1052.74,-224.135C1028.44,-212.826 999.648,-199.422 976.057,-188.44"/>
+<polygon fill="black" stroke="black" points="975.816,-188.328 968.688,-189.422 964.937,-183.264 972.064,-182.17 975.816,-188.328"/>
+</g>
+<!-- ConnectJob -->
+<g id="node20" class="node"><title>ConnectJob</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="5,2" cx="1491" cy="-249" rx="53.4184" ry="18"/>
+<text text-anchor="middle" x="1491" y="-245.3" font-family="Times,serif" font-size="14.00">ConnectJob</text>
+</g>
+<!-- ClientSocketPoolBaseHelper_ConnectJobFactory&#45;&gt;ConnectJob -->
+<g id="edge27" class="edge"><title>ClientSocketPoolBaseHelper_ConnectJobFactory&#45;&gt;ConnectJob</title>
+<path fill="none" stroke="black" d="M1164.57,-272.905C1228.79,-294.786 1332.66,-320.226 1419,-295 1431.5,-291.349 1443.89,-284.795 1454.78,-277.757"/>
+<polygon fill="black" stroke="black" points="1471.44,-265.884 1465.9,-275.352 1467.36,-268.786 1463.29,-271.687 1463.29,-271.687 1463.29,-271.687 1467.36,-268.786 1460.68,-268.023 1471.44,-265.884 1471.44,-265.884"/>
+<polygon fill="black" stroke="black" points="1463.29,-271.687 1457.76,-281.156 1459.22,-274.589 1455.15,-277.491 1455.15,-277.491 1455.15,-277.491 1459.22,-274.589 1452.54,-273.827 1463.29,-271.687 1463.29,-271.687"/>
+</g>
+<!-- ClientSocketPoolBase_ConnectJobFactory -->
+<g id="node15" class="node"><title>ClientSocketPoolBase_ConnectJobFactory</title>
+<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="1194,-504 1045,-466 1194,-428 1343,-466 1194,-504"/>
+<text text-anchor="middle" x="1194" y="-469.8" font-family="Times,serif" font-size="14.00">ClientSocketPoolBase::</text>
+<text text-anchor="middle" x="1194" y="-454.8" font-family="Times,serif" font-size="14.00">ConnectJobFactory</text>
+</g>
+<!-- ClientSocketPoolBase_ConnectJobFactoryAdaptor -->
+<g id="node16" class="node"><title>ClientSocketPoolBase_ConnectJobFactoryAdaptor</title>
+<polygon fill="none" stroke="black" points="1146,-390 975,-352 1146,-314 1317,-352 1146,-390"/>
+<text text-anchor="middle" x="1146" y="-355.8" font-family="Times,serif" font-size="14.00">ClientSocketPoolBase::</text>
+<text text-anchor="middle" x="1146" y="-340.8" font-family="Times,serif" font-size="14.00">ConnectJobFactoryAdaptor</text>
+</g>
+<!-- ClientSocketPoolBase_ConnectJobFactory&#45;&gt;ClientSocketPoolBase_ConnectJobFactoryAdaptor -->
+<g id="edge19" class="edge"><title>ClientSocketPoolBase_ConnectJobFactory&#45;&gt;ClientSocketPoolBase_ConnectJobFactoryAdaptor</title>
+<path fill="none" stroke="black" d="M1179.6,-431.396C1175.13,-420.971 1170.13,-409.306 1165.38,-398.226"/>
+<polygon fill="black" stroke="black" points="1165.28,-397.997 1159.24,-394.058 1160.56,-386.967 1166.6,-390.906 1165.28,-397.997"/>
+</g>
+<!-- ClientSocketPoolBase_ConnectJobFactory&#45;&gt;ConnectJob -->
+<g id="edge28" class="edge"><title>ClientSocketPoolBase_ConnectJobFactory&#45;&gt;ConnectJob</title>
+<path fill="none" stroke="black" d="M1245.4,-440.879C1270.92,-427.675 1301.46,-409.949 1326,-390 1360.94,-361.599 1358.95,-343.467 1393,-314 1409.54,-299.689 1429.49,-286.1 1447.06,-275.155"/>
+<polygon fill="black" stroke="black" points="1464.27,-264.787 1458.03,-273.802 1459.99,-267.368 1455.7,-269.948 1455.7,-269.948 1455.7,-269.948 1459.99,-267.368 1453.38,-266.093 1464.27,-264.787 1464.27,-264.787"/>
+<polygon fill="black" stroke="black" points="1455.7,-269.948 1449.46,-278.963 1451.42,-272.528 1447.14,-275.108 1447.14,-275.108 1447.14,-275.108 1451.42,-272.528 1444.82,-271.254 1455.7,-269.948 1455.7,-269.948"/>
+</g>
+<!-- ClientSocketPoolBase_ConnectJobFactoryAdaptor&#45;&gt;ClientSocketPoolBaseHelper_ConnectJobFactory -->
+<g id="edge12" class="edge"><title>ClientSocketPoolBase_ConnectJobFactoryAdaptor&#45;&gt;ClientSocketPoolBaseHelper_ConnectJobFactory</title>
+<path fill="none" stroke="black" d="M1131.9,-317.087C1127.67,-306.925 1123.03,-295.755 1118.76,-285.494"/>
+<polygon fill="none" stroke="black" points="1121.88,-283.886 1114.81,-275.997 1115.42,-286.574 1121.88,-283.886"/>
+</g>
+<!-- HigherLayeredPool -->
+<g id="node17" class="node"><title>HigherLayeredPool</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="1,5" cx="1337" cy="-249" rx="82.3139" ry="18"/>
+<text text-anchor="middle" x="1337" y="-245.3" font-family="Times,serif" font-size="14.00">HigherLayeredPool</text>
+</g>
+<!-- HigherLayeredPool&#45;&gt;ClientSocketPoolBaseHelper -->
+<g id="edge24" class="edge"><title>HigherLayeredPool&#45;&gt;ClientSocketPoolBaseHelper</title>
+<path fill="none" stroke="black" d="M1290.91,-233.974C1276.31,-229.8 1260.05,-225.431 1245,-222 1171.14,-205.162 1086.52,-190.648 1023.6,-180.764"/>
+<polygon fill="none" stroke="black" points="1023.57,-180.759 1017.02,-183.788 1011.71,-178.911 1018.26,-175.883 1023.57,-180.759"/>
+<text text-anchor="middle" x="1286.91" y="-222.774" font-family="Times,serif" font-size="14.00">*</text>
+</g>
+<!-- LowerLayeredPool -->
+<g id="node18" class="node"><title>LowerLayeredPool</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="1,5" cx="872" cy="-249" rx="81.3646" ry="18"/>
+<text text-anchor="middle" x="872" y="-245.3" font-family="Times,serif" font-size="14.00">LowerLayeredPool</text>
+</g>
+<!-- LowerLayeredPool&#45;&gt;ClientSocketPoolBaseHelper -->
+<g id="edge25" class="edge"><title>LowerLayeredPool&#45;&gt;ClientSocketPoolBaseHelper</title>
+<path fill="none" stroke="black" d="M884.3,-230.822C891.913,-220.19 901.855,-206.306 910.521,-194.204"/>
+<polygon fill="none" stroke="black" points="910.731,-193.91 910.972,-186.703 917.717,-184.153 917.477,-191.36 910.731,-193.91"/>
+<text text-anchor="middle" x="880.3" y="-219.622" font-family="Times,serif" font-size="14.00">*</text>
+</g>
+<!-- ClientSocketPool -->
+<g id="node19" class="node"><title>ClientSocketPool</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="1,5" cx="879" cy="-352" rx="74.6146" ry="18"/>
+<text text-anchor="middle" x="879" y="-348.3" font-family="Times,serif" font-size="14.00">ClientSocketPool</text>
+</g>
+<!-- ClientSocketPool&#45;&gt;LowerLayeredPool -->
+<g id="edge9" class="edge"><title>ClientSocketPool&#45;&gt;LowerLayeredPool</title>
+<path fill="none" stroke="black" d="M877.813,-333.867C876.742,-318.414 875.148,-295.416 873.9,-277.409"/>
+<polygon fill="none" stroke="black" points="877.376,-276.951 873.193,-267.217 870.393,-277.435 877.376,-276.951"/>
+</g>
+<!-- ConnectJob&#45;&gt;ConnectJob_Delegate -->
+<g id="edge23" class="edge"><title>ConnectJob&#45;&gt;ConnectJob_Delegate</title>
+<path fill="none" stroke="black" d="M1461.84,-224.089C1423.16,-192.362 1355.84,-137.158 1322.26,-109.618"/>
+<polygon fill="none" stroke="black" points="1462.21,-224.387 1469.38,-225.098 1471.49,-231.996 1464.31,-231.284 1462.21,-224.387"/>
+</g>
+<!-- ClientSocketFactory -->
+<g id="node22" class="node"><title>ClientSocketFactory</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="1,5" cx="636" cy="-249" rx="85.19" ry="18"/>
+<text text-anchor="middle" x="636" y="-245.3" font-family="Times,serif" font-size="14.00">ClientSocketFactory</text>
+</g>
+<!-- ClientSocketFactory&#45;&gt;ClientSocketPoolBaseHelper -->
+<g id="edge26" class="edge"><title>ClientSocketFactory&#45;&gt;ClientSocketPoolBaseHelper</title>
+<path fill="none" stroke="black" d="M669.499,-232.343C691.664,-222.491 721.59,-210.144 749,-202 777.322,-193.585 808.753,-186.688 837.369,-181.308"/>
+<polygon fill="none" stroke="black" points="837.64,-181.259 842.821,-176.243 849.444,-179.096 844.263,-184.112 837.64,-181.259"/>
+</g>
+<!-- TCPClientSocket -->
+<g id="node24" class="node"><title>TCPClientSocket</title>
+<ellipse fill="none" stroke="black" cx="636" cy="-166" rx="74.6146" ry="18"/>
+<text text-anchor="middle" x="636" y="-162.3" font-family="Times,serif" font-size="14.00">TCPClientSocket</text>
+</g>
+<!-- ClientSocketFactory&#45;&gt;TCPClientSocket -->
+<g id="edge29" class="edge"><title>ClientSocketFactory&#45;&gt;TCPClientSocket</title>
+<path fill="none" stroke="black" d="M636,-230.822C636,-223.09 636,-213.637 636,-204.401"/>
+<polygon fill="black" stroke="black" points="636,-184.153 640.5,-194.153 636,-189.153 636,-194.153 636,-194.153 636,-194.153 636,-189.153 631.5,-194.153 636,-184.153 636,-184.153"/>
+<polygon fill="black" stroke="black" points="636,-194.153 640.5,-204.153 636,-199.153 636,-204.153 636,-204.153 636,-204.153 636,-199.153 631.5,-204.153 636,-194.153 636,-194.153"/>
+</g>
+<!-- DefaultClientSocketFactory -->
+<g id="node23" class="node"><title>DefaultClientSocketFactory</title>
+<ellipse fill="none" stroke="black" cx="622" cy="-352" rx="113.135" ry="18"/>
+<text text-anchor="middle" x="622" y="-348.3" font-family="Times,serif" font-size="14.00">DefaultClientSocketFactory</text>
+</g>
+<!-- DefaultClientSocketFactory&#45;&gt;ClientSocketFactory -->
+<g id="edge14" class="edge"><title>DefaultClientSocketFactory&#45;&gt;ClientSocketFactory</title>
+<path fill="none" stroke="black" d="M624.375,-333.867C626.527,-318.341 629.735,-295.2 632.236,-277.156"/>
+<polygon fill="none" stroke="black" points="635.707,-277.603 633.613,-267.217 628.773,-276.642 635.707,-277.603"/>
+</g>
+<!-- StreamSocket -->
+<g id="node25" class="node"><title>StreamSocket</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="1,5" cx="636" cy="-92" rx="61.1419" ry="18"/>
+<text text-anchor="middle" x="636" y="-88.3" font-family="Times,serif" font-size="14.00">StreamSocket</text>
+</g>
+<!-- TCPClientSocket&#45;&gt;StreamSocket -->
+<g id="edge16" class="edge"><title>TCPClientSocket&#45;&gt;StreamSocket</title>
+<path fill="none" stroke="black" d="M636,-147.937C636,-139.807 636,-129.876 636,-120.705"/>
+<polygon fill="none" stroke="black" points="639.5,-120.441 636,-110.441 632.5,-120.441 639.5,-120.441"/>
+</g>
+<!-- Socket -->
+<g id="node26" class="node"><title>Socket</title>
+<ellipse fill="none" stroke="black" cx="636" cy="-18" rx="35.6194" ry="18"/>
+<text text-anchor="middle" x="636" y="-14.3" font-family="Times,serif" font-size="14.00">Socket</text>
+</g>
+<!-- StreamSocket&#45;&gt;Socket -->
+<g id="edge15" class="edge"><title>StreamSocket&#45;&gt;Socket</title>
+<path fill="none" stroke="black" d="M636,-73.937C636,-65.8072 636,-55.8761 636,-46.7047"/>
+<polygon fill="none" stroke="black" points="639.5,-46.4406 636,-36.4407 632.5,-46.4407 639.5,-46.4406"/>
+</g>
+<!-- TransportSocketParams -->
+<g id="node27" class="node"><title>TransportSocketParams</title>
+<ellipse fill="none" stroke="black" cx="1491" cy="-588" rx="97.237" ry="18"/>
+<text text-anchor="middle" x="1491" y="-584.3" font-family="Times,serif" font-size="14.00">TransportSocketParams</text>
+</g>
+<!-- TransportConnectJobHelper -->
+<g id="node28" class="node"><title>TransportConnectJobHelper</title>
+<ellipse fill="none" stroke="black" cx="1491" cy="-466" rx="113.61" ry="18"/>
+<text text-anchor="middle" x="1491" y="-462.3" font-family="Times,serif" font-size="14.00">TransportConnectJobHelper</text>
+</g>
+<!-- TransportSocketParams&#45;&gt;TransportConnectJobHelper -->
+<g id="edge22" class="edge"><title>TransportSocketParams&#45;&gt;TransportConnectJobHelper</title>
+<path fill="none" stroke="red" d="M1491,-569.807C1491,-550.648 1491,-519.34 1491,-496.299"/>
+<polygon fill="red" stroke="red" points="1491,-496.161 1487,-490.161 1491,-484.161 1495,-490.161 1491,-496.161"/>
+</g>
+<!-- TransportConnectJob -->
+<g id="node30" class="node"><title>TransportConnectJob</title>
+<ellipse fill="none" stroke="black" cx="1491" cy="-352" rx="89.0632" ry="18"/>
+<text text-anchor="middle" x="1491" y="-348.3" font-family="Times,serif" font-size="14.00">TransportConnectJob</text>
+</g>
+<!-- TransportConnectJobHelper&#45;&gt;TransportConnectJob -->
+<g id="edge21" class="edge"><title>TransportConnectJobHelper&#45;&gt;TransportConnectJob</title>
+<path fill="none" stroke="black" d="M1491,-447.99C1491,-430.557 1491,-403.116 1491,-382.202"/>
+<polygon fill="black" stroke="black" points="1491,-382.17 1487,-376.171 1491,-370.17 1495,-376.17 1491,-382.17"/>
+</g>
+<!-- TransportConnectJobFactory -->
+<g id="node29" class="node"><title>TransportConnectJobFactory</title>
+<ellipse fill="none" stroke="black" cx="1194" cy="-588" rx="116.484" ry="18"/>
+<text text-anchor="middle" x="1194" y="-584.3" font-family="Times,serif" font-size="14.00">TransportConnectJobFactory</text>
+</g>
+<!-- TransportConnectJobFactory&#45;&gt;ClientSocketPoolBase_ConnectJobFactory -->
+<g id="edge11" class="edge"><title>TransportConnectJobFactory&#45;&gt;ClientSocketPoolBase_ConnectJobFactory</title>
+<path fill="none" stroke="black" d="M1194,-569.807C1194,-555.293 1194,-533.805 1194,-514.222"/>
+<polygon fill="none" stroke="black" points="1197.5,-514.202 1194,-504.202 1190.5,-514.202 1197.5,-514.202"/>
+<text text-anchor="middle" x="1261" y="-533.3" font-family="Times,serif" font-size="14.00">TransportSocketParams</text>
+</g>
+<!-- TransportConnectJob&#45;&gt;ConnectJob -->
+<g id="edge13" class="edge"><title>TransportConnectJob&#45;&gt;ConnectJob</title>
+<path fill="none" stroke="black" d="M1491,-333.867C1491,-318.414 1491,-295.416 1491,-277.409"/>
+<polygon fill="none" stroke="black" points="1494.5,-277.217 1491,-267.217 1487.5,-277.217 1494.5,-277.217"/>
+</g>
+<!-- TransportClientSocketPool&#45;&gt;ClientSocketPool -->
+<g id="edge8" class="edge"><title>TransportClientSocketPool&#45;&gt;ClientSocketPool</title>
+<path fill="none" stroke="black" d="M897.659,-447.99C894.121,-429.981 888.486,-401.293 884.333,-380.152"/>
+<polygon fill="none" stroke="black" points="887.735,-379.308 882.373,-370.17 880.866,-380.658 887.735,-379.308"/>
+</g>
+</g>
+</svg>
diff --git a/chromium/net/docs/url_request.dot b/chromium/net/docs/url_request.dot
new file mode 100644
index 00000000000..220393498af
--- /dev/null
+++ b/chromium/net/docs/url_request.dot
@@ -0,0 +1,186 @@
+digraph URLRequestRoot {
+ subgraph cluster_legend {
+ label="Legend";
+
+ ## The following legend is an attempt to match UML notation,
+ ## except for template_class and Factory->object, which are
+ ## invented for this diagram.
+ BaseClass;
+ SubClass [label="Derived Class"];
+ Whole;
+ Part;
+ A;
+ B;
+ Interface [label="Interface / ABC", style=dashed];
+ template_class [shape=diamond]; # Link will name parameter(s)
+
+ SubClass -> BaseClass [arrowhead="empty"];
+ SubClass -> Interface [arrowhead="empty", style=dashed];
+ Part -> Whole [arrowhead="diamond", label="ownership"];
+ Part -> Whole [arrowhead="odiamond", label="pointer"];
+ A -> B [arrowhead="none", headlabel="?..?", taillabel="?..?",
+ label="association"];
+ // Often a "subgraph { rank=same; .. }" is used to wrap the
+ // below to make the generative relationship distinctive
+ // from the other class relationships.
+ Factory -> object [arrowhead=veevee];
+ };
+
+ ## URLRequest, URLRequestJob, and subclasses
+ URLRequestContext;
+ URLRequest;
+ URLRequestJob [style=dashed];
+ URLRequestJob_Others [label="...other job types..."];
+ URLRequestHttpJob;
+ Filter;
+
+ {URLRequestHttpJob, URLRequestJob_Others} -> URLRequestJob
+ [arrowhead="empty"];
+
+ URLRequestJob -> URLRequest [arrowhead="diamond"];
+ Filter -> URLRequestJob [arrowhead="diamond"];
+ Filter -> Filter [arrowhead="diamond", taillabel="0..1"];
+
+ subgraph {
+ rank=same;
+ URLRequestContext -> URLRequest [arrowhead=veevee];
+ }
+ subgraph {
+ rank=same;
+ URLRequestHttpJob -> Filter [arrowhead=veevee];
+ }
+
+
+ ## HttpTransaction, subclasses, and generative classes.
+ HttpTransactionFactory;
+ HttpCache;
+ HttpNetworkLayer;
+ HttpTransaction [style=dashed];
+ HttpCache_Transaction [label="HttpCache::Transaction"];
+ HttpNetworkTransaction;
+
+ { HttpNetworkTransaction, HttpCache_Transaction } -> HttpTransaction
+ [style=dashed, arrowhead="empty"];
+ { HttpNetworkLayer, HttpCache } -> HttpTransactionFactory
+ [arrowhead=empty, style=dashed];
+
+ HttpTransaction -> HttpCache_Transaction [arrowhead=diamond];
+ HttpTransaction -> URLRequestHttpJob [arrowhead="diamond"]
+
+ subgraph {
+ rank=same;
+ HttpCache -> HttpCache_Transaction [arrowhead=veevee];
+ }
+ subgraph {
+ rank=same;
+ HttpTransactionFactory -> HttpTransaction [arrowhead=veevee];
+ }
+ subgraph {
+ rank=same;
+ HttpNetworkLayer -> HttpNetworkTransaction [arrowhead=veevee];
+ }
+
+ ## HttpStreamFactory and related.
+ HttpStreamFactoryImpl;
+ HttpStreamRequest [style=dashed];
+ HttpStream [style=dashed];
+ HttpStreamFactoryImpl_Request [label="HttpStreamFactoryImpl::Request"];
+ HttpStreamFactoryImpl_Job [label="HttpStreamFactoryImpl::Job"];
+ HttpStreamRequest_Delegate
+ [label="HttpStreamRequest::Delegate",style=dashed];
+ HttpBasicStream;
+ QuicHttpStream;
+ SpdyHttpStream;
+ HttpBasicState;
+
+ HttpNetworkTransaction -> HttpStreamRequest_Delegate
+ [style=dashed, arrowhead="empty"];
+ HttpStreamFactoryImpl_Request -> HttpStreamRequest
+ [style=dashed, arrowhead="empty"];
+ { HttpBasicStream, QuicHttpStream, SpdyHttpStream } -> HttpStream
+ [style=dashed, arrowhead="empty"];
+
+ HttpStreamRequest -> HttpNetworkTransaction [arrowhead="diamond"];
+ HttpStream -> HttpNetworkTransaction [arrowhead="diamond"];
+ HttpBasicState -> HttpBasicStream [arrowhead=diamond];
+ HttpStreamFactoryImpl_Job -> HttpStreamFactoryImpl_Request
+ [arrowhead="diamond",taillabel="1..*"];
+
+ HttpStreamRequest_Delegate -> HttpStreamFactoryImpl_Request
+ [arrowhead=odiamond];
+ HttpStreamFactoryImpl_Job -> HttpStreamFactoryImpl_Job
+ [arrowhead=odiamond, label="blocking_job_\nwaiting_job_"];
+
+ subgraph {
+ rank=same;
+ HttpStreamFactoryImpl -> HttpStreamRequest [arrowhead=veevee];
+ }
+ subgraph {
+ rank=same;
+ HttpStreamRequest -> HttpStream [arrowhead=veevee];
+ }
+
+ ## ClientSocketHandle and socket pools.
+ ClientSocketPool [style=dashed];
+ TransportClientSocketPool;
+ SSLClientSocketPool;
+ ClientSocketPool_Others [label="...others..."];
+ ClientSocketPoolBase [label="ClientSocketPoolBase", shape=diamond];
+ ClientSocketPoolBaseHelper;
+
+ ConnectJobFactory;
+ ConnectJob [style=dashed];
+ TransportConnectJob;
+ SSLConnectJob;
+ ConnectJob_Others [label="...other connect job types..."];
+ ConnectJob_Delegate [label="ConnectJob::Delegate",style=dashed];
+
+ StreamSocket [style=dashed];
+ TCPClientSocket;
+ StreamSocket_Others [label="...other socket types..."];
+
+ TransportConnectJobHelper;
+ SingleRequestHostResolver;
+
+ { SSLClientSocketPool, TransportClientSocketPool,
+ ClientSocketPool_Others} -> ClientSocketPool
+ [style=dashed, arrowhead=empty];
+ ClientSocketPoolBaseHelper -> ConnectJob_Delegate
+ [arrowhead=empty, style=dashed];
+ StreamSocket -> Socket [arrowhead=empty, style=dashed];
+ { TCPClientSocket, StreamSocket_Others } -> StreamSocket
+ [arrowhead=empty, style=dashed];
+ {SSLConnectJob, TransportConnectJob, ConnectJob_Others} -> ConnectJob
+ [style=dashed, arrowhead=empty];
+
+ ClientSocketHandle -> HttpStreamFactoryImpl_Job [arrowhead="diamond"];
+ ClientSocketHandle -> HttpBasicState [arrowhead="diamond"];
+ ClientSocketPoolBaseHelper -> ClientSocketPoolBase [arrowhead=diamond];
+ ClientSocketPoolBase -> TransportClientSocketPool
+ [arrowhead=diamond, label=TransportSocketParams];
+ ClientSocketPoolBase -> SSLClientSocketPool
+ [arrowhead=diamond, label=SSLSocketParams];
+
+ StreamSocket -> ClientSocketHandle [arrowhead=diamond];
+ ConnectJobFactory -> ClientSocketPoolBase [arrowhead=diamond];
+ StreamSocket -> ConnectJob [arrowhead=diamond];
+ SingleRequestHostResolver -> TransportConnectJobHelper
+ [arrowhead=diamond];
+ TransportConnectJobHelper -> TransportConnectJob [arrowhead=diamond];
+
+ ClientSocketPool -> ClientSocketHandle [arrowhead=odiamond];
+ ConnectJob_Delegate -> ConnectJob [arrowhead=odiamond];
+
+ subgraph {
+ rank=same;
+ ConnectJobFactory -> ConnectJob [arrowhead=veevee];
+ }
+ subgraph {
+ rank=same;
+ HttpStreamFactoryImpl_Job -> ClientSocketHandle [arrowhead=veevee];
+ }
+ subgraph {
+ rank=same;
+ TransportConnectJob -> StreamSocket [arrowhead=veevee];
+ }
+}
diff --git a/chromium/net/docs/url_request.svg b/chromium/net/docs/url_request.svg
new file mode 100644
index 00000000000..6bd00e7f7ca
--- /dev/null
+++ b/chromium/net/docs/url_request.svg
@@ -0,0 +1,594 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.34.0 (20130907.0228)
+ -->
+<!-- Title: URLRequestRoot Pages: 1 -->
+<svg width="1788pt" height="925pt"
+ viewBox="0.00 0.00 1788.00 925.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 921)">
+<title>URLRequestRoot</title>
+<polygon fill="white" stroke="white" points="-4,4 -4,-921 1784,-921 1784,4 -4,4"/>
+<g id="clust1" class="cluster"><title>cluster_legend</title>
+<polygon fill="none" stroke="black" points="107,-746 107,-909 685,-909 685,-746 107,-746"/>
+<text text-anchor="middle" x="396" y="-893.8" font-family="Times,serif" font-size="14.00">Legend</text>
+</g>
+<!-- BaseClass -->
+<g id="node1" class="node"><title>BaseClass</title>
+<ellipse fill="none" stroke="black" cx="473" cy="-772" rx="48.1437" ry="18"/>
+<text text-anchor="middle" x="473" y="-768.3" font-family="Times,serif" font-size="14.00">BaseClass</text>
+</g>
+<!-- SubClass -->
+<g id="node2" class="node"><title>SubClass</title>
+<ellipse fill="none" stroke="black" cx="615" cy="-860" rx="61.6163" ry="18"/>
+<text text-anchor="middle" x="615" y="-856.3" font-family="Times,serif" font-size="14.00">Derived Class</text>
+</g>
+<!-- SubClass&#45;&gt;BaseClass -->
+<g id="edge1" class="edge"><title>SubClass&#45;&gt;BaseClass</title>
+<path fill="none" stroke="black" d="M589.285,-843.426C565.835,-829.224 531.074,-808.172 505.666,-792.784"/>
+<polygon fill="none" stroke="black" points="507.47,-789.784 497.103,-787.598 503.844,-795.772 507.47,-789.784"/>
+</g>
+<!-- Interface -->
+<g id="node7" class="node"><title>Interface</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="5,2" cx="608" cy="-772" rx="68.3417" ry="18"/>
+<text text-anchor="middle" x="608" y="-768.3" font-family="Times,serif" font-size="14.00">Interface / ABC</text>
+</g>
+<!-- SubClass&#45;&gt;Interface -->
+<g id="edge2" class="edge"><title>SubClass&#45;&gt;Interface</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M613.583,-841.597C612.619,-829.746 611.322,-813.817 610.221,-800.292"/>
+<polygon fill="none" stroke="black" points="613.69,-799.767 609.391,-790.084 606.713,-800.335 613.69,-799.767"/>
+</g>
+<!-- Whole -->
+<g id="node3" class="node"><title>Whole</title>
+<ellipse fill="none" stroke="black" cx="372" cy="-772" rx="35.1455" ry="18"/>
+<text text-anchor="middle" x="372" y="-768.3" font-family="Times,serif" font-size="14.00">Whole</text>
+</g>
+<!-- Part -->
+<g id="node4" class="node"><title>Part</title>
+<ellipse fill="none" stroke="black" cx="508" cy="-860" rx="27" ry="18"/>
+<text text-anchor="middle" x="508" y="-856.3" font-family="Times,serif" font-size="14.00">Part</text>
+</g>
+<!-- Part&#45;&gt;Whole -->
+<g id="edge3" class="edge"><title>Part&#45;&gt;Whole</title>
+<path fill="none" stroke="black" d="M486.958,-848.263C482.117,-846.019 476.938,-843.792 472,-842 442.209,-831.187 428.423,-842.925 403,-824 395.025,-818.063 388.673,-809.412 383.848,-800.915"/>
+<polygon fill="black" stroke="black" points="383.784,-800.788 377.509,-797.234 378.376,-790.076 384.651,-793.629 383.784,-800.788"/>
+<text text-anchor="middle" x="432.5" y="-812.3" font-family="Times,serif" font-size="14.00">ownership</text>
+</g>
+<!-- Part&#45;&gt;Whole -->
+<g id="edge4" class="edge"><title>Part&#45;&gt;Whole</title>
+<path fill="none" stroke="black" d="M497.05,-843.387C488.566,-832.255 475.937,-817.615 462,-808 461.698,-807.792 434.867,-797.366 410.582,-787.948"/>
+<polygon fill="none" stroke="black" points="410.539,-787.932 403.499,-789.492 399.351,-783.594 406.391,-782.033 410.539,-787.932"/>
+<text text-anchor="middle" x="500" y="-812.3" font-family="Times,serif" font-size="14.00">pointer</text>
+</g>
+<!-- A -->
+<g id="node5" class="node"><title>A</title>
+<ellipse fill="none" stroke="black" cx="436" cy="-860" rx="27" ry="18"/>
+<text text-anchor="middle" x="436" y="-856.3" font-family="Times,serif" font-size="14.00">A</text>
+</g>
+<!-- B -->
+<g id="node6" class="node"><title>B</title>
+<ellipse fill="none" stroke="black" cx="292" cy="-772" rx="27" ry="18"/>
+<text text-anchor="middle" x="292" y="-768.3" font-family="Times,serif" font-size="14.00">B</text>
+</g>
+<!-- A&#45;&gt;B -->
+<g id="edge5" class="edge"><title>A&#45;&gt;B</title>
+<path fill="none" stroke="black" d="M415.171,-848.532C409.973,-846.171 404.352,-843.826 399,-842 365.327,-830.513 349.531,-845.255 321,-824 311.083,-816.612 304.05,-804.762 299.396,-794.342"/>
+<polyline fill="none" stroke="black" points="297.423,-789.677 299.371,-794.282 "/>
+<text text-anchor="middle" x="352.5" y="-812.3" font-family="Times,serif" font-size="14.00">association</text>
+<text text-anchor="middle" x="287.423" y="-793.477" font-family="Times,serif" font-size="14.00">?..?</text>
+<text text-anchor="middle" x="405.171" y="-837.332" font-family="Times,serif" font-size="14.00">?..?</text>
+</g>
+<!-- template_class -->
+<g id="node8" class="node"><title>template_class</title>
+<polygon fill="none" stroke="black" points="300,-878 209.505,-860 300,-842 390.495,-860 300,-878"/>
+<text text-anchor="middle" x="300" y="-856.3" font-family="Times,serif" font-size="14.00">template_class</text>
+</g>
+<!-- Factory -->
+<g id="node9" class="node"><title>Factory</title>
+<ellipse fill="none" stroke="black" cx="153" cy="-860" rx="38.0212" ry="18"/>
+<text text-anchor="middle" x="153" y="-856.3" font-family="Times,serif" font-size="14.00">Factory</text>
+</g>
+<!-- object -->
+<g id="node10" class="node"><title>object</title>
+<ellipse fill="none" stroke="black" cx="153" cy="-772" rx="33.2209" ry="18"/>
+<text text-anchor="middle" x="153" y="-768.3" font-family="Times,serif" font-size="14.00">object</text>
+</g>
+<!-- Factory&#45;&gt;object -->
+<g id="edge6" class="edge"><title>Factory&#45;&gt;object</title>
+<path fill="none" stroke="black" d="M153,-841.597C153,-832.562 153,-821.157 153,-810.254"/>
+<polygon fill="black" stroke="black" points="153,-790.084 157.5,-800.084 153,-795.084 153,-800.084 153,-800.084 153,-800.084 153,-795.084 148.5,-800.084 153,-790.084 153,-790.084"/>
+<polygon fill="black" stroke="black" points="153,-800.084 157.5,-810.084 153,-805.084 153,-810.084 153,-810.084 153,-810.084 153,-805.084 148.5,-810.084 153,-800.084 153,-800.084"/>
+</g>
+<!-- URLRequestContext -->
+<g id="node11" class="node"><title>URLRequestContext</title>
+<ellipse fill="none" stroke="black" cx="198" cy="-18" rx="87.1385" ry="18"/>
+<text text-anchor="middle" x="198" y="-14.3" font-family="Times,serif" font-size="14.00">URLRequestContext</text>
+</g>
+<!-- URLRequest -->
+<g id="node12" class="node"><title>URLRequest</title>
+<ellipse fill="none" stroke="black" cx="379" cy="-18" rx="58.2422" ry="18"/>
+<text text-anchor="middle" x="379" y="-14.3" font-family="Times,serif" font-size="14.00">URLRequest</text>
+</g>
+<!-- URLRequestContext&#45;&gt;URLRequest -->
+<g id="edge12" class="edge"><title>URLRequestContext&#45;&gt;URLRequest</title>
+<path fill="none" stroke="black" d="M285.318,-18C290.35,-18 295.382,-18 300.414,-18"/>
+<polygon fill="black" stroke="black" points="320.449,-18 310.449,-22.5 315.449,-18 310.449,-18 310.449,-18 310.449,-18 315.449,-18 310.449,-13.5 320.449,-18 320.449,-18"/>
+<polygon fill="black" stroke="black" points="310.449,-18 300.449,-22.5001 305.449,-18.0001 300.449,-18.0001 300.449,-18.0001 300.449,-18.0001 305.449,-18.0001 300.449,-13.5001 310.449,-18 310.449,-18"/>
+</g>
+<!-- URLRequestJob -->
+<g id="node13" class="node"><title>URLRequestJob</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="5,2" cx="379" cy="-92" rx="70.2668" ry="18"/>
+<text text-anchor="middle" x="379" y="-88.3" font-family="Times,serif" font-size="14.00">URLRequestJob</text>
+</g>
+<!-- URLRequestJob&#45;&gt;URLRequest -->
+<g id="edge9" class="edge"><title>URLRequestJob&#45;&gt;URLRequest</title>
+<path fill="none" stroke="black" d="M379,-73.937C379,-66.3374 379,-57.1638 379,-48.5081"/>
+<polygon fill="black" stroke="black" points="379,-48.4407 375,-42.4407 379,-36.4407 383,-42.4406 379,-48.4407"/>
+</g>
+<!-- URLRequestJob_Others -->
+<g id="node14" class="node"><title>URLRequestJob_Others</title>
+<ellipse fill="none" stroke="black" cx="79" cy="-166" rx="78.4642" ry="18"/>
+<text text-anchor="middle" x="79" y="-162.3" font-family="Times,serif" font-size="14.00">...other job types...</text>
+</g>
+<!-- URLRequestJob_Others&#45;&gt;URLRequestJob -->
+<g id="edge7" class="edge"><title>URLRequestJob_Others&#45;&gt;URLRequestJob</title>
+<path fill="none" stroke="black" d="M131.256,-152.459C183.725,-139.866 264.455,-120.491 319.39,-107.306"/>
+<polygon fill="none" stroke="black" points="320.428,-110.657 329.335,-104.92 318.794,-103.85 320.428,-110.657"/>
+</g>
+<!-- URLRequestHttpJob -->
+<g id="node15" class="node"><title>URLRequestHttpJob</title>
+<ellipse fill="none" stroke="black" cx="379" cy="-166" rx="87.1385" ry="18"/>
+<text text-anchor="middle" x="379" y="-162.3" font-family="Times,serif" font-size="14.00">URLRequestHttpJob</text>
+</g>
+<!-- URLRequestHttpJob&#45;&gt;URLRequestJob -->
+<g id="edge8" class="edge"><title>URLRequestHttpJob&#45;&gt;URLRequestJob</title>
+<path fill="none" stroke="black" d="M379,-147.937C379,-139.807 379,-129.876 379,-120.705"/>
+<polygon fill="none" stroke="black" points="382.5,-120.441 379,-110.441 375.5,-120.441 382.5,-120.441"/>
+</g>
+<!-- Filter -->
+<g id="node16" class="node"><title>Filter</title>
+<ellipse fill="none" stroke="black" cx="532" cy="-166" rx="30.3206" ry="18"/>
+<text text-anchor="middle" x="532" y="-162.3" font-family="Times,serif" font-size="14.00">Filter</text>
+</g>
+<!-- URLRequestHttpJob&#45;&gt;Filter -->
+<g id="edge13" class="edge"><title>URLRequestHttpJob&#45;&gt;Filter</title>
+<path fill="none" stroke="black" d="M466.258,-166C471.334,-166 476.41,-166 481.486,-166"/>
+<polygon fill="black" stroke="black" points="501.697,-166 491.697,-170.5 496.697,-166 491.697,-166 491.697,-166 491.697,-166 496.697,-166 491.697,-161.5 501.697,-166 501.697,-166"/>
+<polygon fill="black" stroke="black" points="491.697,-166 481.697,-170.5 486.697,-166 481.697,-166 481.697,-166 481.697,-166 486.697,-166 481.697,-161.5 491.697,-166 491.697,-166"/>
+</g>
+<!-- Filter&#45;&gt;URLRequestJob -->
+<g id="edge10" class="edge"><title>Filter&#45;&gt;URLRequestJob</title>
+<path fill="none" stroke="black" d="M509.094,-154.221C486.235,-143.463 450.544,-126.668 422.324,-113.388"/>
+<polygon fill="black" stroke="black" points="421.996,-113.233 414.864,-114.298 411.138,-108.124 418.27,-107.059 421.996,-113.233"/>
+</g>
+<!-- Filter&#45;&gt;Filter -->
+<g id="edge11" class="edge"><title>Filter&#45;&gt;Filter</title>
+<path fill="none" stroke="black" d="M560.103,-172.724C570.969,-173.022 580,-170.781 580,-166 580,-163.236 576.981,-161.321 572.335,-160.254"/>
+<polygon fill="black" stroke="black" points="572.065,-160.233 565.765,-163.742 560.103,-159.276 566.403,-155.767 572.065,-160.233"/>
+<text text-anchor="middle" x="571.103" y="-176.524" font-family="Times,serif" font-size="14.00">0..1</text>
+</g>
+<!-- HttpTransactionFactory -->
+<g id="node17" class="node"><title>HttpTransactionFactory</title>
+<ellipse fill="none" stroke="black" cx="419" cy="-240" rx="97.237" ry="18"/>
+<text text-anchor="middle" x="419" y="-236.3" font-family="Times,serif" font-size="14.00">HttpTransactionFactory</text>
+</g>
+<!-- HttpTransaction -->
+<g id="node20" class="node"><title>HttpTransaction</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="5,2" cx="734" cy="-240" rx="69.3156" ry="18"/>
+<text text-anchor="middle" x="734" y="-236.3" font-family="Times,serif" font-size="14.00">HttpTransaction</text>
+</g>
+<!-- HttpTransactionFactory&#45;&gt;HttpTransaction -->
+<g id="edge21" class="edge"><title>HttpTransactionFactory&#45;&gt;HttpTransaction</title>
+<path fill="none" stroke="black" d="M516.515,-240C559.052,-240 601.589,-240 644.127,-240"/>
+<polygon fill="black" stroke="black" points="664.337,-240 654.337,-244.5 659.337,-240 654.337,-240 654.337,-240 654.337,-240 659.337,-240 654.337,-235.5 664.337,-240 664.337,-240"/>
+<polygon fill="black" stroke="black" points="654.337,-240 644.337,-244.5 649.337,-240 644.337,-240 644.337,-240 644.337,-240 649.337,-240 644.337,-235.5 654.337,-240 654.337,-240"/>
+</g>
+<!-- HttpCache -->
+<g id="node18" class="node"><title>HttpCache</title>
+<ellipse fill="none" stroke="black" cx="225" cy="-166" rx="49.0941" ry="18"/>
+<text text-anchor="middle" x="225" y="-162.3" font-family="Times,serif" font-size="14.00">HttpCache</text>
+</g>
+<!-- HttpCache&#45;&gt;HttpTransactionFactory -->
+<g id="edge16" class="edge"><title>HttpCache&#45;&gt;HttpTransactionFactory</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M258.184,-179.316C288.306,-190.495 333.185,-207.151 367.886,-220.03"/>
+<polygon fill="none" stroke="black" points="366.789,-223.356 377.382,-223.554 369.225,-216.793 366.789,-223.356"/>
+</g>
+<!-- HttpCache_Transaction -->
+<g id="node21" class="node"><title>HttpCache_Transaction</title>
+<ellipse fill="none" stroke="black" cx="734" cy="-166" rx="97.237" ry="18"/>
+<text text-anchor="middle" x="734" y="-162.3" font-family="Times,serif" font-size="14.00">HttpCache::Transaction</text>
+</g>
+<!-- HttpCache&#45;&gt;HttpCache_Transaction -->
+<g id="edge20" class="edge"><title>HttpCache&#45;&gt;HttpCache_Transaction</title>
+<path fill="none" stroke="black" d="M247.344,-182.086C259.827,-190.078 276.045,-198.887 292,-203 361.291,-220.861 543.243,-213.661 614,-203 633.473,-200.066 654.144,-194.596 672.743,-188.745"/>
+<polygon fill="black" stroke="black" points="691.957,-182.348 683.891,-189.777 687.213,-183.928 682.469,-185.507 682.469,-185.507 682.469,-185.507 687.213,-183.928 681.048,-181.238 691.957,-182.348 691.957,-182.348"/>
+<polygon fill="black" stroke="black" points="682.469,-185.507 674.403,-192.935 677.725,-187.086 672.981,-188.666 672.981,-188.666 672.981,-188.666 677.725,-187.086 671.56,-184.396 682.469,-185.507 682.469,-185.507"/>
+</g>
+<!-- HttpNetworkLayer -->
+<g id="node19" class="node"><title>HttpNetworkLayer</title>
+<ellipse fill="none" stroke="black" cx="419" cy="-314" rx="79.4147" ry="18"/>
+<text text-anchor="middle" x="419" y="-310.3" font-family="Times,serif" font-size="14.00">HttpNetworkLayer</text>
+</g>
+<!-- HttpNetworkLayer&#45;&gt;HttpTransactionFactory -->
+<g id="edge17" class="edge"><title>HttpNetworkLayer&#45;&gt;HttpTransactionFactory</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M419,-295.937C419,-287.807 419,-277.876 419,-268.705"/>
+<polygon fill="none" stroke="black" points="422.5,-268.441 419,-258.441 415.5,-268.441 422.5,-268.441"/>
+</g>
+<!-- HttpNetworkTransaction -->
+<g id="node22" class="node"><title>HttpNetworkTransaction</title>
+<ellipse fill="none" stroke="black" cx="828" cy="-314" rx="101.087" ry="18"/>
+<text text-anchor="middle" x="828" y="-310.3" font-family="Times,serif" font-size="14.00">HttpNetworkTransaction</text>
+</g>
+<!-- HttpNetworkLayer&#45;&gt;HttpNetworkTransaction -->
+<g id="edge22" class="edge"><title>HttpNetworkLayer&#45;&gt;HttpNetworkTransaction</title>
+<path fill="none" stroke="black" d="M498.483,-314C567.85,-314 637.216,-314 706.583,-314"/>
+<polygon fill="black" stroke="black" points="726.635,-314 716.635,-318.5 721.635,-314 716.635,-314 716.635,-314 716.635,-314 721.635,-314 716.635,-309.5 726.635,-314 726.635,-314"/>
+<polygon fill="black" stroke="black" points="716.635,-314 706.635,-318.5 711.635,-314 706.635,-314 706.635,-314 706.635,-314 711.635,-314 706.635,-309.5 716.635,-314 716.635,-314"/>
+</g>
+<!-- HttpTransaction&#45;&gt;URLRequestHttpJob -->
+<g id="edge19" class="edge"><title>HttpTransaction&#45;&gt;URLRequestHttpJob</title>
+<path fill="none" stroke="black" d="M681.236,-228.299C620.105,-215.9 519.061,-195.407 450.808,-181.564"/>
+<polygon fill="black" stroke="black" points="450.645,-181.531 443.97,-184.259 438.885,-179.146 445.56,-176.418 450.645,-181.531"/>
+</g>
+<!-- HttpTransaction&#45;&gt;HttpCache_Transaction -->
+<g id="edge18" class="edge"><title>HttpTransaction&#45;&gt;HttpCache_Transaction</title>
+<path fill="none" stroke="black" d="M728.16,-221.937C727.354,-214.337 727.083,-205.164 727.349,-196.508"/>
+<polygon fill="black" stroke="black" points="727.354,-196.416 723.746,-190.173 728.121,-184.441 731.729,-190.684 727.354,-196.416"/>
+</g>
+<!-- HttpCache_Transaction&#45;&gt;HttpTransaction -->
+<g id="edge14" class="edge"><title>HttpCache_Transaction&#45;&gt;HttpTransaction</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M739.879,-184.441C740.723,-192.625 740.954,-202.572 740.571,-211.719"/>
+<polygon fill="none" stroke="black" points="737.062,-211.713 739.84,-221.937 744.045,-212.212 737.062,-211.713"/>
+</g>
+<!-- HttpNetworkTransaction&#45;&gt;HttpTransaction -->
+<g id="edge15" class="edge"><title>HttpNetworkTransaction&#45;&gt;HttpTransaction</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M806.198,-296.301C793.533,-286.599 777.401,-274.243 763.6,-263.672"/>
+<polygon fill="none" stroke="black" points="765.427,-260.663 755.359,-257.36 761.17,-266.22 765.427,-260.663"/>
+</g>
+<!-- HttpStreamRequest_Delegate -->
+<g id="node28" class="node"><title>HttpStreamRequest_Delegate</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="5,2" cx="951" cy="-240" rx="119.384" ry="18"/>
+<text text-anchor="middle" x="951" y="-236.3" font-family="Times,serif" font-size="14.00">HttpStreamRequest::Delegate</text>
+</g>
+<!-- HttpNetworkTransaction&#45;&gt;HttpStreamRequest_Delegate -->
+<g id="edge23" class="edge"><title>HttpNetworkTransaction&#45;&gt;HttpStreamRequest_Delegate</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M855.911,-296.662C873.088,-286.607 895.308,-273.6 913.948,-262.689"/>
+<polygon fill="none" stroke="black" points="915.912,-265.595 922.774,-257.522 912.376,-259.554 915.912,-265.595"/>
+</g>
+<!-- HttpStreamFactoryImpl -->
+<g id="node23" class="node"><title>HttpStreamFactoryImpl</title>
+<ellipse fill="none" stroke="black" cx="591" cy="-92" rx="97.237" ry="18"/>
+<text text-anchor="middle" x="591" y="-88.3" font-family="Times,serif" font-size="14.00">HttpStreamFactoryImpl</text>
+</g>
+<!-- HttpStreamRequest -->
+<g id="node24" class="node"><title>HttpStreamRequest</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="5,2" cx="831" cy="-92" rx="81.3398" ry="18"/>
+<text text-anchor="middle" x="831" y="-88.3" font-family="Times,serif" font-size="14.00">HttpStreamRequest</text>
+</g>
+<!-- HttpStreamFactoryImpl&#45;&gt;HttpStreamRequest -->
+<g id="edge34" class="edge"><title>HttpStreamFactoryImpl&#45;&gt;HttpStreamRequest</title>
+<path fill="none" stroke="black" d="M688.5,-92C701.992,-92 715.484,-92 728.976,-92"/>
+<polygon fill="black" stroke="black" points="749.452,-92 739.452,-96.5 744.452,-92 739.452,-92 739.452,-92 739.452,-92 744.452,-92 739.452,-87.5 749.452,-92 749.452,-92"/>
+<polygon fill="black" stroke="black" points="739.452,-92 729.452,-96.5001 734.452,-92.0001 729.452,-92.0001 729.452,-92.0001 729.452,-92.0001 734.452,-92.0001 729.452,-87.5001 739.452,-92 739.452,-92"/>
+</g>
+<!-- HttpStreamRequest&#45;&gt;HttpNetworkTransaction -->
+<g id="edge28" class="edge"><title>HttpStreamRequest&#45;&gt;HttpNetworkTransaction</title>
+<path fill="none" stroke="black" d="M763.969,-102.293C711.475,-111.106 644.641,-126.251 628,-148 597.411,-187.98 618.664,-223.16 655,-258 676.893,-278.992 706.776,-291.973 735.546,-300.001"/>
+<polygon fill="black" stroke="black" points="735.731,-300.048 742.539,-297.673 747.351,-303.045 740.542,-305.42 735.731,-300.048"/>
+</g>
+<!-- HttpStream -->
+<g id="node25" class="node"><title>HttpStream</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="5,2" cx="1319" cy="-92" rx="52.4675" ry="18"/>
+<text text-anchor="middle" x="1319" y="-88.3" font-family="Times,serif" font-size="14.00">HttpStream</text>
+</g>
+<!-- HttpStreamRequest&#45;&gt;HttpStream -->
+<g id="edge35" class="edge"><title>HttpStreamRequest&#45;&gt;HttpStream</title>
+<path fill="none" stroke="black" d="M912.492,-92C1023.84,-92 1135.19,-92 1246.54,-92"/>
+<polygon fill="black" stroke="black" points="1266.6,-92 1256.6,-96.5 1261.6,-92 1256.6,-92 1256.6,-92 1256.6,-92 1261.6,-92 1256.6,-87.5 1266.6,-92 1266.6,-92"/>
+<polygon fill="black" stroke="black" points="1256.6,-92 1246.6,-96.5001 1251.6,-92.0001 1246.6,-92.0001 1246.6,-92.0001 1246.6,-92.0001 1251.6,-92.0001 1246.6,-87.5001 1256.6,-92 1256.6,-92"/>
+</g>
+<!-- HttpStream&#45;&gt;HttpNetworkTransaction -->
+<g id="edge29" class="edge"><title>HttpStream&#45;&gt;HttpNetworkTransaction</title>
+<path fill="none" stroke="black" d="M1273.43,-101.133C1239.63,-108.879 1193.76,-123.152 1160,-148 1111.11,-183.992 1129.92,-224.936 1079,-258 1036.66,-285.489 982.719,-299.423 935.696,-306.414"/>
+<polygon fill="black" stroke="black" points="935.473,-306.444 930.076,-311.228 923.585,-308.086 928.982,-303.303 935.473,-306.444"/>
+</g>
+<!-- HttpStreamFactoryImpl_Request -->
+<g id="node26" class="node"><title>HttpStreamFactoryImpl_Request</title>
+<ellipse fill="none" stroke="black" cx="981" cy="-166" rx="131.408" ry="18"/>
+<text text-anchor="middle" x="981" y="-162.3" font-family="Times,serif" font-size="14.00">HttpStreamFactoryImpl::Request</text>
+</g>
+<!-- HttpStreamFactoryImpl_Request&#45;&gt;HttpStreamRequest -->
+<g id="edge24" class="edge"><title>HttpStreamFactoryImpl_Request&#45;&gt;HttpStreamRequest</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M946.587,-148.482C924.617,-137.936 895.998,-124.199 872.734,-113.032"/>
+<polygon fill="none" stroke="black" points="873.984,-109.75 863.455,-108.578 870.955,-116.061 873.984,-109.75"/>
+</g>
+<!-- HttpStreamFactoryImpl_Job -->
+<g id="node27" class="node"><title>HttpStreamFactoryImpl_Job</title>
+<ellipse fill="none" stroke="black" cx="1566" cy="-314" rx="115.06" ry="18"/>
+<text text-anchor="middle" x="1566" y="-310.3" font-family="Times,serif" font-size="14.00">HttpStreamFactoryImpl::Job</text>
+</g>
+<!-- HttpStreamFactoryImpl_Job&#45;&gt;HttpStreamFactoryImpl_Request -->
+<g id="edge31" class="edge"><title>HttpStreamFactoryImpl_Job&#45;&gt;HttpStreamFactoryImpl_Request</title>
+<path fill="none" stroke="black" d="M1553.63,-295.789C1537.2,-274.422 1506.02,-238.754 1470,-222 1453.28,-214.222 1236.53,-191.904 1097.28,-178.206"/>
+<polygon fill="black" stroke="black" points="1097.25,-178.203 1090.89,-181.598 1085.31,-177.031 1091.67,-173.636 1097.25,-178.203"/>
+<text text-anchor="middle" x="1542.63" y="-284.589" font-family="Times,serif" font-size="14.00">1..*</text>
+</g>
+<!-- HttpStreamFactoryImpl_Job&#45;&gt;HttpStreamFactoryImpl_Job -->
+<g id="edge33" class="edge"><title>HttpStreamFactoryImpl_Job&#45;&gt;HttpStreamFactoryImpl_Job</title>
+<path fill="none" stroke="black" d="M1674.54,-319.988C1689.22,-318.984 1699,-316.988 1699,-314 1699,-311.946 1694.38,-310.36 1686.72,-309.244"/>
+<polygon fill="none" stroke="black" points="1686.48,-309.22 1680.11,-312.595 1674.54,-308.012 1680.92,-304.636 1686.48,-309.22"/>
+<text text-anchor="middle" x="1739.5" y="-317.8" font-family="Times,serif" font-size="14.00">blocking_job_</text>
+<text text-anchor="middle" x="1739.5" y="-302.8" font-family="Times,serif" font-size="14.00">waiting_job_</text>
+</g>
+<!-- ClientSocketHandle -->
+<g id="node51" class="node"><title>ClientSocketHandle</title>
+<ellipse fill="none" stroke="black" cx="1332" cy="-314" rx="83.2649" ry="18"/>
+<text text-anchor="middle" x="1332" y="-310.3" font-family="Times,serif" font-size="14.00">ClientSocketHandle</text>
+</g>
+<!-- HttpStreamFactoryImpl_Job&#45;&gt;ClientSocketHandle -->
+<g id="edge59" class="edge"><title>HttpStreamFactoryImpl_Job&#45;&gt;ClientSocketHandle</title>
+<path fill="none" stroke="black" d="M1482.46,-326.396C1461.09,-327.807 1439.71,-327.866 1418.33,-326.572"/>
+<polygon fill="black" stroke="black" points="1398.27,-324.962 1408.6,-321.277 1403.25,-325.362 1408.24,-325.762 1408.24,-325.762 1408.24,-325.762 1403.25,-325.362 1407.88,-330.248 1398.27,-324.962 1398.27,-324.962"/>
+<polygon fill="black" stroke="black" points="1408.24,-325.762 1418.57,-322.077 1413.22,-326.162 1418.21,-326.562 1418.21,-326.562 1418.21,-326.562 1413.22,-326.162 1417.85,-331.048 1408.24,-325.762 1408.24,-325.762"/>
+</g>
+<!-- HttpStreamRequest_Delegate&#45;&gt;HttpStreamFactoryImpl_Request -->
+<g id="edge32" class="edge"><title>HttpStreamRequest_Delegate&#45;&gt;HttpStreamFactoryImpl_Request</title>
+<path fill="none" stroke="black" d="M958.11,-221.937C961.387,-214.072 965.366,-204.522 969.082,-195.604"/>
+<polygon fill="none" stroke="black" points="969.118,-195.518 967.733,-188.441 973.733,-184.441 975.118,-191.518 969.118,-195.518"/>
+</g>
+<!-- HttpBasicStream -->
+<g id="node29" class="node"><title>HttpBasicStream</title>
+<ellipse fill="none" stroke="black" cx="1561" cy="-166" rx="72.192" ry="18"/>
+<text text-anchor="middle" x="1561" y="-162.3" font-family="Times,serif" font-size="14.00">HttpBasicStream</text>
+</g>
+<!-- HttpBasicStream&#45;&gt;HttpStream -->
+<g id="edge25" class="edge"><title>HttpBasicStream&#45;&gt;HttpStream</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1516.33,-151.71C1474.01,-139.12 1410.64,-120.265 1367.2,-107.34"/>
+<polygon fill="none" stroke="black" points="1368.01,-103.93 1357.43,-104.433 1366.01,-110.64 1368.01,-103.93"/>
+</g>
+<!-- QuicHttpStream -->
+<g id="node30" class="node"><title>QuicHttpStream</title>
+<ellipse fill="none" stroke="black" cx="1239" cy="-166" rx="70.2909" ry="18"/>
+<text text-anchor="middle" x="1239" y="-162.3" font-family="Times,serif" font-size="14.00">QuicHttpStream</text>
+</g>
+<!-- QuicHttpStream&#45;&gt;HttpStream -->
+<g id="edge26" class="edge"><title>QuicHttpStream&#45;&gt;HttpStream</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1257.55,-148.301C1268.21,-138.715 1281.74,-126.537 1293.39,-116.05"/>
+<polygon fill="none" stroke="black" points="1296,-118.405 1301.1,-109.113 1291.32,-113.202 1296,-118.405"/>
+</g>
+<!-- SpdyHttpStream -->
+<g id="node31" class="node"><title>SpdyHttpStream</title>
+<ellipse fill="none" stroke="black" cx="1399" cy="-166" rx="71.2405" ry="18"/>
+<text text-anchor="middle" x="1399" y="-162.3" font-family="Times,serif" font-size="14.00">SpdyHttpStream</text>
+</g>
+<!-- SpdyHttpStream&#45;&gt;HttpStream -->
+<g id="edge27" class="edge"><title>SpdyHttpStream&#45;&gt;HttpStream</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1380.45,-148.301C1369.79,-138.715 1356.26,-126.537 1344.61,-116.05"/>
+<polygon fill="none" stroke="black" points="1346.68,-113.202 1336.9,-109.113 1342,-118.405 1346.68,-113.202"/>
+</g>
+<!-- HttpBasicState -->
+<g id="node32" class="node"><title>HttpBasicState</title>
+<ellipse fill="none" stroke="black" cx="1397" cy="-240" rx="64.4914" ry="18"/>
+<text text-anchor="middle" x="1397" y="-236.3" font-family="Times,serif" font-size="14.00">HttpBasicState</text>
+</g>
+<!-- HttpBasicState&#45;&gt;HttpBasicStream -->
+<g id="edge30" class="edge"><title>HttpBasicState&#45;&gt;HttpBasicStream</title>
+<path fill="none" stroke="black" d="M1430.19,-224.43C1454.84,-213.607 1488.74,-198.723 1515.86,-186.819"/>
+<polygon fill="black" stroke="black" points="1516.03,-186.744 1519.91,-180.669 1527.02,-181.92 1523.13,-187.994 1516.03,-186.744"/>
+</g>
+<!-- ClientSocketPool -->
+<g id="node33" class="node"><title>ClientSocketPool</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="5,2" cx="1015" cy="-388" rx="74.6146" ry="18"/>
+<text text-anchor="middle" x="1015" y="-384.3" font-family="Times,serif" font-size="14.00">ClientSocketPool</text>
+</g>
+<!-- ClientSocketPool&#45;&gt;ClientSocketHandle -->
+<g id="edge56" class="edge"><title>ClientSocketPool&#45;&gt;ClientSocketHandle</title>
+<path fill="none" stroke="black" d="M1067.35,-375.111C1121.39,-362.836 1205.91,-343.639 1264.85,-330.253"/>
+<polygon fill="none" stroke="black" points="1264.94,-330.231 1269.91,-325.001 1276.64,-327.573 1271.68,-332.803 1264.94,-330.231"/>
+</g>
+<!-- TransportClientSocketPool -->
+<g id="node34" class="node"><title>TransportClientSocketPool</title>
+<ellipse fill="none" stroke="black" cx="906" cy="-462" rx="109.261" ry="18"/>
+<text text-anchor="middle" x="906" y="-458.3" font-family="Times,serif" font-size="14.00">TransportClientSocketPool</text>
+</g>
+<!-- TransportClientSocketPool&#45;&gt;ClientSocketPool -->
+<g id="edge36" class="edge"><title>TransportClientSocketPool&#45;&gt;ClientSocketPool</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M931.281,-444.301C946.351,-434.346 965.653,-421.596 981.924,-410.848"/>
+<polygon fill="none" stroke="black" points="984.191,-413.545 990.606,-405.113 980.333,-407.705 984.191,-413.545"/>
+</g>
+<!-- SSLClientSocketPool -->
+<g id="node35" class="node"><title>SSLClientSocketPool</title>
+<ellipse fill="none" stroke="black" cx="1124" cy="-462" rx="90.0136" ry="18"/>
+<text text-anchor="middle" x="1124" y="-458.3" font-family="Times,serif" font-size="14.00">SSLClientSocketPool</text>
+</g>
+<!-- SSLClientSocketPool&#45;&gt;ClientSocketPool -->
+<g id="edge37" class="edge"><title>SSLClientSocketPool&#45;&gt;ClientSocketPool</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1099.27,-444.662C1084.11,-434.65 1064.52,-421.711 1048.05,-410.828"/>
+<polygon fill="none" stroke="black" points="1049.53,-407.617 1039.26,-405.025 1045.68,-413.457 1049.53,-407.617"/>
+</g>
+<!-- ClientSocketPool_Others -->
+<g id="node36" class="node"><title>ClientSocketPool_Others</title>
+<ellipse fill="none" stroke="black" cx="731" cy="-462" rx="46.1964" ry="18"/>
+<text text-anchor="middle" x="731" y="-458.3" font-family="Times,serif" font-size="14.00">...others...</text>
+</g>
+<!-- ClientSocketPool_Others&#45;&gt;ClientSocketPool -->
+<g id="edge38" class="edge"><title>ClientSocketPool_Others&#45;&gt;ClientSocketPool</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M765.861,-450.076C772.841,-447.985 780.137,-445.868 787,-444 842.638,-428.858 906.487,-413.639 952.44,-403.061"/>
+<polygon fill="none" stroke="black" points="953.291,-406.456 962.255,-400.809 951.726,-399.634 953.291,-406.456"/>
+</g>
+<!-- ClientSocketPoolBase -->
+<g id="node37" class="node"><title>ClientSocketPoolBase</title>
+<polygon fill="none" stroke="black" points="906,-568 775.72,-550 906,-532 1036.28,-550 906,-568"/>
+<text text-anchor="middle" x="906" y="-546.3" font-family="Times,serif" font-size="14.00">ClientSocketPoolBase</text>
+</g>
+<!-- ClientSocketPoolBase&#45;&gt;TransportClientSocketPool -->
+<g id="edge49" class="edge"><title>ClientSocketPoolBase&#45;&gt;TransportClientSocketPool</title>
+<path fill="none" stroke="black" d="M906,-531.597C906,-520.333 906,-505.384 906,-492.317"/>
+<polygon fill="black" stroke="black" points="906,-492.084 902,-486.084 906,-480.084 910,-486.084 906,-492.084"/>
+<text text-anchor="middle" x="973" y="-502.3" font-family="Times,serif" font-size="14.00">TransportSocketParams</text>
+</g>
+<!-- ClientSocketPoolBase&#45;&gt;SSLClientSocketPool -->
+<g id="edge50" class="edge"><title>ClientSocketPoolBase&#45;&gt;SSLClientSocketPool</title>
+<path fill="none" stroke="black" d="M960.062,-539.469C986.082,-533.841 1017.34,-525.522 1044,-514 1060.75,-506.762 1077.98,-496.239 1092.14,-486.63"/>
+<polygon fill="black" stroke="black" points="1092.47,-486.398 1095.1,-479.684 1102.31,-479.529 1099.68,-486.243 1092.47,-486.398"/>
+<text text-anchor="middle" x="1125" y="-502.3" font-family="Times,serif" font-size="14.00">SSLSocketParams</text>
+</g>
+<!-- ClientSocketPoolBaseHelper -->
+<g id="node38" class="node"><title>ClientSocketPoolBaseHelper</title>
+<ellipse fill="none" stroke="black" cx="812" cy="-772" rx="116.484" ry="18"/>
+<text text-anchor="middle" x="812" y="-768.3" font-family="Times,serif" font-size="14.00">ClientSocketPoolBaseHelper</text>
+</g>
+<!-- ClientSocketPoolBaseHelper&#45;&gt;ClientSocketPoolBase -->
+<g id="edge48" class="edge"><title>ClientSocketPoolBaseHelper&#45;&gt;ClientSocketPoolBase</title>
+<path fill="none" stroke="black" d="M739.499,-757.76C716.22,-749.708 692.888,-736.772 679,-716 670.107,-702.699 670.953,-693.829 679,-680 715.426,-617.402 794.808,-582.693 849.336,-565.443"/>
+<polygon fill="black" stroke="black" points="849.43,-565.415 854.007,-559.843 860.911,-561.924 856.334,-567.497 849.43,-565.415"/>
+</g>
+<!-- ConnectJob_Delegate -->
+<g id="node44" class="node"><title>ConnectJob_Delegate</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="5,2" cx="1015" cy="-698" rx="90.4879" ry="18"/>
+<text text-anchor="middle" x="1015" y="-694.3" font-family="Times,serif" font-size="14.00">ConnectJob::Delegate</text>
+</g>
+<!-- ClientSocketPoolBaseHelper&#45;&gt;ConnectJob_Delegate -->
+<g id="edge39" class="edge"><title>ClientSocketPoolBaseHelper&#45;&gt;ConnectJob_Delegate</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M856.298,-755.288C887.834,-744.103 930.307,-729.039 963.379,-717.309"/>
+<polygon fill="none" stroke="black" points="964.623,-720.581 972.878,-713.94 962.283,-713.984 964.623,-720.581"/>
+</g>
+<!-- ConnectJobFactory -->
+<g id="node39" class="node"><title>ConnectJobFactory</title>
+<ellipse fill="none" stroke="black" cx="906" cy="-624" rx="81.3646" ry="18"/>
+<text text-anchor="middle" x="906" y="-620.3" font-family="Times,serif" font-size="14.00">ConnectJobFactory</text>
+</g>
+<!-- ConnectJobFactory&#45;&gt;ClientSocketPoolBase -->
+<g id="edge52" class="edge"><title>ConnectJobFactory&#45;&gt;ClientSocketPoolBase</title>
+<path fill="none" stroke="black" d="M906,-605.937C906,-598.337 906,-589.164 906,-580.508"/>
+<polygon fill="black" stroke="black" points="906,-580.441 902,-574.441 906,-568.441 910,-574.441 906,-580.441"/>
+</g>
+<!-- ConnectJob -->
+<g id="node40" class="node"><title>ConnectJob</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="5,2" cx="1213" cy="-624" rx="53.4184" ry="18"/>
+<text text-anchor="middle" x="1213" y="-620.3" font-family="Times,serif" font-size="14.00">ConnectJob</text>
+</g>
+<!-- ConnectJobFactory&#45;&gt;ConnectJob -->
+<g id="edge58" class="edge"><title>ConnectJobFactory&#45;&gt;ConnectJob</title>
+<path fill="none" stroke="black" d="M987.247,-624C1037.85,-624 1088.45,-624 1139.06,-624"/>
+<polygon fill="black" stroke="black" points="1159.21,-624 1149.21,-628.5 1154.21,-624 1149.21,-624 1149.21,-624 1149.21,-624 1154.21,-624 1149.21,-619.5 1159.21,-624 1159.21,-624"/>
+<polygon fill="black" stroke="black" points="1149.21,-624 1139.21,-628.5 1144.21,-624 1139.21,-624 1139.21,-624 1139.21,-624 1144.21,-624 1139.21,-619.5 1149.21,-624 1149.21,-624"/>
+</g>
+<!-- TransportConnectJob -->
+<g id="node41" class="node"><title>TransportConnectJob</title>
+<ellipse fill="none" stroke="black" cx="1213" cy="-698" rx="89.0632" ry="18"/>
+<text text-anchor="middle" x="1213" y="-694.3" font-family="Times,serif" font-size="14.00">TransportConnectJob</text>
+</g>
+<!-- TransportConnectJob&#45;&gt;ConnectJob -->
+<g id="edge43" class="edge"><title>TransportConnectJob&#45;&gt;ConnectJob</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1213,-679.937C1213,-671.807 1213,-661.876 1213,-652.705"/>
+<polygon fill="none" stroke="black" points="1216.5,-652.441 1213,-642.441 1209.5,-652.441 1216.5,-652.441"/>
+</g>
+<!-- StreamSocket -->
+<g id="node45" class="node"><title>StreamSocket</title>
+<ellipse fill="none" stroke="black" stroke-dasharray="5,2" cx="1539" cy="-698" rx="61.1419" ry="18"/>
+<text text-anchor="middle" x="1539" y="-694.3" font-family="Times,serif" font-size="14.00">StreamSocket</text>
+</g>
+<!-- TransportConnectJob&#45;&gt;StreamSocket -->
+<g id="edge60" class="edge"><title>TransportConnectJob&#45;&gt;StreamSocket</title>
+<path fill="none" stroke="black" d="M1254.5,-713.973C1274.06,-720.671 1297.89,-727.669 1320,-731 1381.09,-740.206 1398.4,-743.008 1459,-731 1469.42,-728.936 1480.18,-725.495 1490.31,-721.596"/>
+<polygon fill="black" stroke="black" points="1508.73,-713.774 1501.28,-721.824 1504.13,-715.728 1499.53,-717.682 1499.53,-717.682 1499.53,-717.682 1504.13,-715.728 1497.77,-713.54 1508.73,-713.774 1508.73,-713.774"/>
+<polygon fill="black" stroke="black" points="1499.53,-717.682 1492.08,-725.733 1494.92,-719.636 1490.32,-721.59 1490.32,-721.59 1490.32,-721.59 1494.92,-719.636 1488.56,-717.448 1499.53,-717.682 1499.53,-717.682"/>
+</g>
+<!-- SSLConnectJob -->
+<g id="node42" class="node"><title>SSLConnectJob</title>
+<ellipse fill="none" stroke="black" cx="1390" cy="-698" rx="69.3156" ry="18"/>
+<text text-anchor="middle" x="1390" y="-694.3" font-family="Times,serif" font-size="14.00">SSLConnectJob</text>
+</g>
+<!-- SSLConnectJob&#45;&gt;ConnectJob -->
+<g id="edge44" class="edge"><title>SSLConnectJob&#45;&gt;ConnectJob</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1354.18,-682.43C1325.56,-670.787 1285.38,-654.443 1255.2,-642.166"/>
+<polygon fill="none" stroke="black" points="1256.36,-638.86 1245.78,-638.334 1253.72,-645.345 1256.36,-638.86"/>
+</g>
+<!-- ConnectJob_Others -->
+<g id="node43" class="node"><title>ConnectJob_Others</title>
+<ellipse fill="none" stroke="black" cx="797" cy="-698" rx="109.286" ry="18"/>
+<text text-anchor="middle" x="797" y="-694.3" font-family="Times,serif" font-size="14.00">...other connect job types...</text>
+</g>
+<!-- ConnectJob_Others&#45;&gt;ConnectJob -->
+<g id="edge45" class="edge"><title>ConnectJob_Others&#45;&gt;ConnectJob</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M869.462,-684.459C951.057,-670.336 1081.94,-647.684 1156.38,-634.799"/>
+<polygon fill="none" stroke="black" points="1157.25,-638.202 1166.5,-633.048 1156.05,-631.304 1157.25,-638.202"/>
+</g>
+<!-- ConnectJob_Delegate&#45;&gt;ConnectJob -->
+<g id="edge57" class="edge"><title>ConnectJob_Delegate&#45;&gt;ConnectJob</title>
+<path fill="none" stroke="black" d="M1056.51,-681.906C1088.76,-670.176 1133.48,-653.915 1166.86,-641.778"/>
+<polygon fill="none" stroke="black" points="1166.88,-641.772 1171.15,-635.962 1178.16,-637.671 1173.88,-643.481 1166.88,-641.772"/>
+</g>
+<!-- StreamSocket&#45;&gt;ConnectJob -->
+<g id="edge53" class="edge"><title>StreamSocket&#45;&gt;ConnectJob</title>
+<path fill="none" stroke="black" d="M1493.58,-685.965C1485.09,-683.946 1476.28,-681.884 1468,-680 1399.73,-664.466 1320.91,-647.634 1269.19,-636.739"/>
+<polygon fill="black" stroke="black" points="1269.03,-636.706 1262.34,-639.386 1257.29,-634.236 1263.99,-631.557 1269.03,-636.706"/>
+</g>
+<!-- Socket -->
+<g id="node50" class="node"><title>Socket</title>
+<ellipse fill="none" stroke="black" cx="1539" cy="-624" rx="35.6194" ry="18"/>
+<text text-anchor="middle" x="1539" y="-620.3" font-family="Times,serif" font-size="14.00">Socket</text>
+</g>
+<!-- StreamSocket&#45;&gt;Socket -->
+<g id="edge40" class="edge"><title>StreamSocket&#45;&gt;Socket</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1539,-679.937C1539,-671.807 1539,-661.876 1539,-652.705"/>
+<polygon fill="none" stroke="black" points="1542.5,-652.441 1539,-642.441 1535.5,-652.441 1542.5,-652.441"/>
+</g>
+<!-- StreamSocket&#45;&gt;ClientSocketHandle -->
+<g id="edge51" class="edge"><title>StreamSocket&#45;&gt;ClientSocketHandle</title>
+<path fill="none" stroke="black" d="M1508.89,-682.178C1488.78,-669.938 1466,-650.455 1466,-625 1466,-625 1466,-625 1466,-387 1466,-356.557 1438.83,-338.931 1408.96,-328.753"/>
+<polygon fill="black" stroke="black" points="1408.9,-328.735 1401.99,-330.793 1397.43,-325.205 1404.34,-323.147 1408.9,-328.735"/>
+</g>
+<!-- TCPClientSocket -->
+<g id="node46" class="node"><title>TCPClientSocket</title>
+<ellipse fill="none" stroke="black" cx="1670" cy="-772" rx="74.6146" ry="18"/>
+<text text-anchor="middle" x="1670" y="-768.3" font-family="Times,serif" font-size="14.00">TCPClientSocket</text>
+</g>
+<!-- TCPClientSocket&#45;&gt;StreamSocket -->
+<g id="edge41" class="edge"><title>TCPClientSocket&#45;&gt;StreamSocket</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1641.25,-755.199C1621.96,-744.598 1596.39,-730.541 1575.64,-719.138"/>
+<polygon fill="none" stroke="black" points="1577.23,-716.019 1566.78,-714.27 1573.86,-722.154 1577.23,-716.019"/>
+</g>
+<!-- StreamSocket_Others -->
+<g id="node47" class="node"><title>StreamSocket_Others</title>
+<ellipse fill="none" stroke="black" cx="1487" cy="-772" rx="90.0136" ry="18"/>
+<text text-anchor="middle" x="1487" y="-768.3" font-family="Times,serif" font-size="14.00">...other socket types...</text>
+</g>
+<!-- StreamSocket_Others&#45;&gt;StreamSocket -->
+<g id="edge42" class="edge"><title>StreamSocket_Others&#45;&gt;StreamSocket</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1499.32,-753.937C1505.73,-745.06 1513.7,-734.035 1520.8,-724.197"/>
+<polygon fill="none" stroke="black" points="1523.75,-726.097 1526.77,-715.941 1518.07,-721.998 1523.75,-726.097"/>
+</g>
+<!-- TransportConnectJobHelper -->
+<g id="node48" class="node"><title>TransportConnectJobHelper</title>
+<ellipse fill="none" stroke="black" cx="1213" cy="-772" rx="113.61" ry="18"/>
+<text text-anchor="middle" x="1213" y="-768.3" font-family="Times,serif" font-size="14.00">TransportConnectJobHelper</text>
+</g>
+<!-- TransportConnectJobHelper&#45;&gt;TransportConnectJob -->
+<g id="edge55" class="edge"><title>TransportConnectJobHelper&#45;&gt;TransportConnectJob</title>
+<path fill="none" stroke="black" d="M1213,-753.937C1213,-746.337 1213,-737.164 1213,-728.508"/>
+<polygon fill="black" stroke="black" points="1213,-728.441 1209,-722.441 1213,-716.441 1217,-722.441 1213,-728.441"/>
+</g>
+<!-- SingleRequestHostResolver -->
+<g id="node49" class="node"><title>SingleRequestHostResolver</title>
+<ellipse fill="none" stroke="black" cx="1213" cy="-860" rx="113.135" ry="18"/>
+<text text-anchor="middle" x="1213" y="-856.3" font-family="Times,serif" font-size="14.00">SingleRequestHostResolver</text>
+</g>
+<!-- SingleRequestHostResolver&#45;&gt;TransportConnectJobHelper -->
+<g id="edge54" class="edge"><title>SingleRequestHostResolver&#45;&gt;TransportConnectJobHelper</title>
+<path fill="none" stroke="black" d="M1213,-841.597C1213,-830.333 1213,-815.384 1213,-802.317"/>
+<polygon fill="black" stroke="black" points="1213,-802.084 1209,-796.084 1213,-790.084 1217,-796.084 1213,-802.084"/>
+</g>
+<!-- ClientSocketHandle&#45;&gt;HttpStreamFactoryImpl_Job -->
+<g id="edge46" class="edge"><title>ClientSocketHandle&#45;&gt;HttpStreamFactoryImpl_Job</title>
+<path fill="none" stroke="black" d="M1398.27,-303.038C1422.28,-300.636 1446.29,-299.939 1470.29,-300.947"/>
+<polygon fill="black" stroke="black" points="1470.48,-300.957 1476.69,-297.287 1482.46,-301.604 1476.26,-305.275 1470.48,-300.957"/>
+</g>
+<!-- ClientSocketHandle&#45;&gt;HttpBasicState -->
+<g id="edge47" class="edge"><title>ClientSocketHandle&#45;&gt;HttpBasicState</title>
+<path fill="none" stroke="black" d="M1347.4,-295.937C1355.18,-287.329 1364.77,-276.702 1373.44,-267.095"/>
+<polygon fill="black" stroke="black" points="1373.67,-266.848 1374.72,-259.714 1381.71,-257.941 1380.65,-265.075 1373.67,-266.848"/>
+</g>
+</g>
+</svg>
diff --git a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc
index 6f46d4fbef4..911f05a9581 100644
--- a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc
+++ b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc
@@ -181,6 +181,10 @@ class SQLitePersistentCookieStore::Backend
// that have been loaded from DB since last IO notification.
void Notify(const LoadedCallback& loaded_callback, bool load_success);
+ // Flushes (Commits) pending operations on the background runner, and invokes
+ // |callback| on the client thread when done.
+ void FlushAndNotifyInBackground(const base::Closure& callback);
+
// Sends notification when the entire store is loaded, and reports metrics
// for the total time to load and aggregated results from any priority loads
// that occurred.
@@ -369,6 +373,41 @@ CookiePriority DBCookiePriorityToCookiePriority(DBCookiePriority value) {
return COOKIE_PRIORITY_DEFAULT;
}
+// Possible values for the 'samesite' column
+enum DBCookieSameSite {
+ kCookieSameSiteNoRestriction = 0,
+ kCookieSameSiteLax = 1,
+ kCookieSameSiteStrict = 2,
+};
+
+DBCookieSameSite CookieSameSiteToDBCookieSameSite(CookieSameSite value) {
+ switch (value) {
+ case CookieSameSite::NO_RESTRICTION:
+ return kCookieSameSiteNoRestriction;
+ case CookieSameSite::LAX_MODE:
+ return kCookieSameSiteLax;
+ case CookieSameSite::STRICT_MODE:
+ return kCookieSameSiteStrict;
+ }
+
+ NOTREACHED();
+ return kCookieSameSiteNoRestriction;
+}
+
+CookieSameSite DBCookieSameSiteToCookieSameSite(DBCookieSameSite value) {
+ switch (value) {
+ case kCookieSameSiteNoRestriction:
+ return CookieSameSite::NO_RESTRICTION;
+ case kCookieSameSiteLax:
+ return CookieSameSite::LAX_MODE;
+ case kCookieSameSiteStrict:
+ return CookieSameSite::STRICT_MODE;
+ }
+
+ NOTREACHED();
+ return CookieSameSite::DEFAULT_MODE;
+}
+
// Increments a specified TimeDelta by the duration between this object's
// constructor and destructor. Not thread safe. Multiple instances may be
// created with the same delta instance as long as their lifetimes are nested.
@@ -410,8 +449,9 @@ bool InitTable(sql::Connection* db) {
"persistent INTEGER NOT NULL DEFAULT 1,"
"priority INTEGER NOT NULL DEFAULT %d,"
"encrypted_value BLOB DEFAULT '',"
- "firstpartyonly INTEGER NOT NULL DEFAULT 0)",
- CookiePriorityToDBCookiePriority(COOKIE_PRIORITY_DEFAULT)));
+ "firstpartyonly INTEGER NOT NULL DEFAULT %d)",
+ CookiePriorityToDBCookiePriority(COOKIE_PRIORITY_DEFAULT),
+ CookieSameSiteToDBCookieSameSite(CookieSameSite::DEFAULT_MODE)));
if (!db->Execute(stmt.c_str()))
return false;
@@ -508,6 +548,13 @@ void SQLitePersistentCookieStore::Backend::LoadKeyAndNotifyInBackground(
this, loaded_callback, success, posted_at));
}
+void SQLitePersistentCookieStore::Backend::FlushAndNotifyInBackground(
+ const base::Closure& callback) {
+ Commit();
+ if (!callback.is_null())
+ PostClientTask(FROM_HERE, callback);
+}
+
void SQLitePersistentCookieStore::Backend::CompleteLoadForKeyInForeground(
const LoadedCallback& loaded_callback,
bool load_success,
@@ -784,7 +831,8 @@ void SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement(
Time::FromInternalValue(smt.ColumnInt64(10)), // last_access_utc
smt.ColumnInt(7) != 0, // secure
smt.ColumnInt(8) != 0, // httponly
- smt.ColumnInt(9) != 0, // firstpartyonly
+ DBCookieSameSiteToCookieSameSite(
+ static_cast<DBCookieSameSite>(smt.ColumnInt(9))), // samesite
DBCookiePriorityToCookiePriority(
static_cast<DBCookiePriority>(smt.ColumnInt(13))))); // priority
DLOG_IF(WARNING, cc->CreationDate() > Time::Now())
@@ -1119,7 +1167,8 @@ void SQLitePersistentCookieStore::Backend::Commit() {
add_smt.BindInt64(6, po->cc().ExpiryDate().ToInternalValue());
add_smt.BindInt(7, po->cc().IsSecure());
add_smt.BindInt(8, po->cc().IsHttpOnly());
- add_smt.BindInt(9, po->cc().IsFirstPartyOnly());
+ add_smt.BindInt(9,
+ CookieSameSiteToDBCookieSameSite(po->cc().SameSite()));
add_smt.BindInt64(10, po->cc().LastAccessDate().ToInternalValue());
add_smt.BindInt(11, po->cc().IsPersistent());
add_smt.BindInt(12, po->cc().IsPersistent());
@@ -1159,14 +1208,8 @@ void SQLitePersistentCookieStore::Backend::Commit() {
void SQLitePersistentCookieStore::Backend::Flush(
const base::Closure& callback) {
DCHECK(!background_task_runner_->RunsTasksOnCurrentThread());
- PostBackgroundTask(FROM_HERE, base::Bind(&Backend::Commit, this));
-
- if (!callback.is_null()) {
- // We want the completion task to run immediately after Commit() returns.
- // Posting it from here means there is less chance of another task getting
- // onto the message queue first, than if we posted it from Commit() itself.
- PostBackgroundTask(FROM_HERE, callback);
- }
+ PostBackgroundTask(FROM_HERE, base::Bind(&Backend::FlushAndNotifyInBackground,
+ this, callback));
}
// Fire off a close message to the background runner. We could still have a
@@ -1357,6 +1400,7 @@ void SQLitePersistentCookieStore::Close(const base::Closure& callback) {
}
void SQLitePersistentCookieStore::Load(const LoadedCallback& loaded_callback) {
+ DCHECK(!loaded_callback.is_null());
if (backend_)
backend_->Load(loaded_callback);
else
@@ -1366,6 +1410,7 @@ void SQLitePersistentCookieStore::Load(const LoadedCallback& loaded_callback) {
void SQLitePersistentCookieStore::LoadCookiesForKey(
const std::string& key,
const LoadedCallback& loaded_callback) {
+ DCHECK(!loaded_callback.is_null());
if (backend_)
backend_->LoadCookiesForKey(key, loaded_callback);
else
diff --git a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc
index 4be580b811e..bbf594cd10b 100644
--- a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc
+++ b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc
@@ -80,7 +80,8 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test {
t += base::TimeDelta::FromInternalValue(10);
store_->AddCookie(CanonicalCookie(
gurl, base::StringPrintf("Cookie_%d", cookie_num), "1", domain_name,
- "/", t, t, t, false, false, false, COOKIE_PRIORITY_DEFAULT));
+ "/", t, t, t, false, false, CookieSameSite::DEFAULT_MODE,
+ COOKIE_PRIORITY_DEFAULT));
}
}
// Replace the store effectively destroying the current one and forcing it
diff --git a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
index 2166be022a1..8315d74e10e 100644
--- a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
+++ b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -168,9 +168,9 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
const std::string& domain,
const std::string& path,
const base::Time& creation) {
- store_->AddCookie(CanonicalCookie(GURL(), name, value, domain, path,
- creation, creation, creation, false,
- false, false, COOKIE_PRIORITY_DEFAULT));
+ store_->AddCookie(CanonicalCookie(
+ GURL(), name, value, domain, path, creation, creation, creation, false,
+ false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
}
void AddCookieWithExpiration(const std::string& name,
@@ -179,9 +179,9 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
const std::string& path,
const base::Time& creation,
const base::Time& expiration) {
- store_->AddCookie(CanonicalCookie(GURL(), name, value, domain, path,
- creation, expiration, creation, false,
- false, false, COOKIE_PRIORITY_DEFAULT));
+ store_->AddCookie(CanonicalCookie(
+ GURL(), name, value, domain, path, creation, expiration, creation,
+ false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
}
std::string ReadRawDBContents() {
@@ -442,10 +442,10 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) {
InitializeStore(false, true);
// Add a session cookie.
- store_->AddCookie(CanonicalCookie(GURL(), "C", "D", "sessioncookie.com", "/",
- base::Time::Now(), base::Time(),
- base::Time::Now(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ store_->AddCookie(CanonicalCookie(
+ GURL(), "C", "D", "sessioncookie.com", "/", base::Time::Now(),
+ base::Time(), base::Time::Now(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
// Force the store to write its data to the disk.
DestroyStore();
@@ -469,10 +469,10 @@ TEST_F(SQLitePersistentCookieStoreTest, TestDontLoadOldSessionCookies) {
InitializeStore(false, true);
// Add a session cookie.
- store_->AddCookie(CanonicalCookie(GURL(), "C", "D", "sessioncookie.com", "/",
- base::Time::Now(), base::Time(),
- base::Time::Now(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ store_->AddCookie(CanonicalCookie(
+ GURL(), "C", "D", "sessioncookie.com", "/", base::Time::Now(),
+ base::Time(), base::Time::Now(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
// Force the store to write its data to the disk.
DestroyStore();
@@ -499,16 +499,16 @@ TEST_F(SQLitePersistentCookieStoreTest, PersistIsPersistent) {
static const char kPersistentName[] = "persistent";
// Add a session cookie.
- store_->AddCookie(CanonicalCookie(GURL(), kSessionName, "val",
- "sessioncookie.com", "/", base::Time::Now(),
- base::Time(), base::Time::Now(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
+ store_->AddCookie(CanonicalCookie(
+ GURL(), kSessionName, "val", "sessioncookie.com", "/", base::Time::Now(),
+ base::Time(), base::Time::Now(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
// Add a persistent cookie.
store_->AddCookie(CanonicalCookie(
GURL(), kPersistentName, "val", "sessioncookie.com", "/",
base::Time::Now() - base::TimeDelta::FromDays(1),
base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(),
- false, false, false, COOKIE_PRIORITY_DEFAULT));
+ false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
// Force the store to write its data to the disk.
DestroyStore();
@@ -552,21 +552,21 @@ TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) {
GURL(), kLowName, kCookieValue, kCookieDomain, kCookiePath,
base::Time::Now() - base::TimeDelta::FromMinutes(1),
base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(),
- false, false, false, COOKIE_PRIORITY_LOW));
+ false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_LOW));
// Add a medium-priority persistent cookie.
store_->AddCookie(CanonicalCookie(
GURL(), kMediumName, kCookieValue, kCookieDomain, kCookiePath,
base::Time::Now() - base::TimeDelta::FromMinutes(2),
base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(),
- false, false, false, COOKIE_PRIORITY_MEDIUM));
+ false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_MEDIUM));
// Add a high-priority peristent cookie.
store_->AddCookie(CanonicalCookie(
GURL(), kHighName, kCookieValue, kCookieDomain, kCookiePath,
base::Time::Now() - base::TimeDelta::FromMinutes(3),
base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(),
- false, false, false, COOKIE_PRIORITY_HIGH));
+ false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_HIGH));
// Force the store to write its data to the disk.
DestroyStore();
@@ -601,6 +601,64 @@ TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) {
STLDeleteElements(&cookies);
}
+TEST_F(SQLitePersistentCookieStoreTest, SameSiteIsPersistent) {
+ const char kNoneName[] = "none";
+ const char kLaxName[] = "lax";
+ const char kStrictName[] = "strict";
+ const char kCookieDomain[] = "sessioncookie.com";
+ const char kCookieValue[] = "value";
+ const char kCookiePath[] = "/";
+
+ InitializeStore(false, true);
+
+ // Add a non-samesite cookie.
+ store_->AddCookie(CanonicalCookie(
+ GURL(), kNoneName, kCookieValue, kCookieDomain, kCookiePath,
+ base::Time::Now() - base::TimeDelta::FromMinutes(1),
+ base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(),
+ false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT));
+
+ // Add a lax-samesite persistent cookie.
+ store_->AddCookie(CanonicalCookie(
+ GURL(), kLaxName, kCookieValue, kCookieDomain, kCookiePath,
+ base::Time::Now() - base::TimeDelta::FromMinutes(2),
+ base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(),
+ false, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT));
+
+ // Add a strict-samesite peristent cookie.
+ store_->AddCookie(CanonicalCookie(
+ GURL(), kStrictName, kCookieValue, kCookieDomain, kCookiePath,
+ base::Time::Now() - base::TimeDelta::FromMinutes(3),
+ base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(),
+ false, false, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT));
+
+ // Force the store to write its data to the disk.
+ DestroyStore();
+
+ // Create a store that loads session cookie and test that the priority
+ // attribute values are restored.
+ CanonicalCookieVector cookies;
+ CreateAndLoad(false, true, &cookies);
+ ASSERT_EQ(3U, cookies.size());
+
+ // Put the cookies into a map, by name, for comparison below.
+ std::map<std::string, CanonicalCookie*> cookie_map;
+ for (const auto& cookie : cookies)
+ cookie_map[cookie->Name()] = cookie;
+
+ // Validate that each cookie has the correct SameSite.
+ ASSERT_EQ(1u, cookie_map.count(kNoneName));
+ EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie_map[kNoneName]->SameSite());
+
+ ASSERT_EQ(1u, cookie_map.count(kLaxName));
+ EXPECT_EQ(CookieSameSite::LAX_MODE, cookie_map[kLaxName]->SameSite());
+
+ ASSERT_EQ(1u, cookie_map.count(kStrictName));
+ EXPECT_EQ(CookieSameSite::STRICT_MODE, cookie_map[kStrictName]->SameSite());
+
+ STLDeleteElements(&cookies);
+}
+
TEST_F(SQLitePersistentCookieStoreTest, UpdateToEncryption) {
CanonicalCookieVector cookies;
diff --git a/chromium/net/filter/filter.cc b/chromium/net/filter/filter.cc
index 466aa109fd7..502ce5bb5d7 100644
--- a/chromium/net/filter/filter.cc
+++ b/chromium/net/filter/filter.cc
@@ -78,6 +78,8 @@ std::string FilterTypeAsString(Filter::FilterType type_id) {
return "FILTER_TYPE_SDCH_POSSIBLE ";
case Filter::FILTER_TYPE_UNSUPPORTED:
return "FILTER_TYPE_UNSUPPORTED";
+ case Filter::FILTER_TYPE_MAX:
+ return "FILTER_TYPE_MAX";
}
return "";
}
diff --git a/chromium/net/filter/filter.h b/chromium/net/filter/filter.h
index e9df3dbc9db..31d08d4980f 100644
--- a/chromium/net/filter/filter.h
+++ b/chromium/net/filter/filter.h
@@ -151,7 +151,8 @@ class NET_EXPORT_PRIVATE Filter {
FILTER_ERROR
};
- // Specifies type of filters that can be created.
+ // Specifies type of filters that can be created. Do not change the values
+ // of this enum; it is preserved in a histogram.
enum FilterType {
FILTER_TYPE_BROTLI,
FILTER_TYPE_DEFLATE,
@@ -160,6 +161,8 @@ class NET_EXPORT_PRIVATE Filter {
FILTER_TYPE_SDCH,
FILTER_TYPE_SDCH_POSSIBLE, // Sdch possible, but pass through allowed.
FILTER_TYPE_UNSUPPORTED,
+
+ FILTER_TYPE_MAX
};
virtual ~Filter();
@@ -233,6 +236,8 @@ class NET_EXPORT_PRIVATE Filter {
// Returns a string describing the FilterTypes implemented by this filter.
std::string OrderedFilterList() const;
+ FilterType type() const { return type_id_; }
+
protected:
friend class BrotliUnitTest;
friend class GZipUnitTest;
diff --git a/chromium/net/ftp/ftp_ctrl_response_buffer.cc b/chromium/net/ftp/ftp_ctrl_response_buffer.cc
index 064068e965e..8dd631b6c45 100644
--- a/chromium/net/ftp/ftp_ctrl_response_buffer.cc
+++ b/chromium/net/ftp/ftp_ctrl_response_buffer.cc
@@ -20,6 +20,8 @@ const int FtpCtrlResponse::kInvalidStatusCode = -1;
FtpCtrlResponse::FtpCtrlResponse() : status_code(kInvalidStatusCode) {}
+FtpCtrlResponse::FtpCtrlResponse(const FtpCtrlResponse& other) = default;
+
FtpCtrlResponse::~FtpCtrlResponse() {}
FtpCtrlResponseBuffer::FtpCtrlResponseBuffer(const BoundNetLog& net_log)
@@ -112,6 +114,9 @@ FtpCtrlResponseBuffer::ParsedLine::ParsedLine()
status_code(FtpCtrlResponse::kInvalidStatusCode) {
}
+FtpCtrlResponseBuffer::ParsedLine::ParsedLine(const ParsedLine& other) =
+ default;
+
// static
FtpCtrlResponseBuffer::ParsedLine FtpCtrlResponseBuffer::ParseLine(
const std::string& line) {
diff --git a/chromium/net/ftp/ftp_ctrl_response_buffer.h b/chromium/net/ftp/ftp_ctrl_response_buffer.h
index ae90fea5fcb..b53b7a91783 100644
--- a/chromium/net/ftp/ftp_ctrl_response_buffer.h
+++ b/chromium/net/ftp/ftp_ctrl_response_buffer.h
@@ -19,6 +19,7 @@ struct NET_EXPORT_PRIVATE FtpCtrlResponse {
static const int kInvalidStatusCode;
FtpCtrlResponse();
+ FtpCtrlResponse(const FtpCtrlResponse& other);
~FtpCtrlResponse();
int status_code; // Three-digit status code.
@@ -44,6 +45,7 @@ class NET_EXPORT_PRIVATE FtpCtrlResponseBuffer {
private:
struct ParsedLine {
ParsedLine();
+ ParsedLine(const ParsedLine& other);
// Indicates that this line begins with a valid 3-digit status code.
bool has_status_code;
diff --git a/chromium/net/ftp/ftp_ctrl_response_fuzzer.cc b/chromium/net/ftp/ftp_ctrl_response_fuzzer.cc
new file mode 100644
index 00000000000..227cfa28497
--- /dev/null
+++ b/chromium/net/ftp/ftp_ctrl_response_fuzzer.cc
@@ -0,0 +1,22 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include "net/ftp/ftp_ctrl_response_buffer.h"
+#include "net/log/net_log.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ const net::BoundNetLog log;
+ net::FtpCtrlResponseBuffer buffer(log);
+ if (!buffer.ConsumeData(reinterpret_cast<const char*>(data), size)) {
+ return 0;
+ }
+ while (buffer.ResponseAvailable()) {
+ (void)buffer.PopResponse();
+ }
+ return 0;
+}
diff --git a/chromium/net/ftp/ftp_directory_listing_fuzzer.cc b/chromium/net/ftp/ftp_directory_listing_fuzzer.cc
new file mode 100644
index 00000000000..459379e3eef
--- /dev/null
+++ b/chromium/net/ftp/ftp_directory_listing_fuzzer.cc
@@ -0,0 +1,20 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "base/time/time.h"
+#include "net/ftp/ftp_directory_listing_parser.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::string buffer(reinterpret_cast<const char*>(data), size);
+ std::vector<net::FtpDirectoryListingEntry> entries;
+ net::ParseFtpDirectoryListing(buffer, base::Time::Now(), &entries);
+ return 0;
+}
diff --git a/chromium/net/ftp/ftp_directory_listing_parser_vms.cc b/chromium/net/ftp/ftp_directory_listing_parser_vms.cc
index e05f2c73a93..8139ee0bc24 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser_vms.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser_vms.cc
@@ -113,7 +113,7 @@ bool LooksLikeVmsFileProtectionListingPart(const base::string16& input) {
bool LooksLikeVmsFileProtectionListing(const base::string16& input) {
if (input.length() < 2)
return false;
- if (input[0] != '(' || input[input.length() - 1] != ')')
+ if (input.front() != '(' || input.back() != ')')
return false;
// We expect four parts of the file protection listing: for System, Owner,
@@ -133,7 +133,7 @@ bool LooksLikeVmsFileProtectionListing(const base::string16& input) {
bool LooksLikeVmsUserIdentificationCode(const base::string16& input) {
if (input.length() < 2)
return false;
- return input[0] == '[' && input[input.length() - 1] == ']';
+ return input.front() == '[' && input.back() == ']';
}
bool LooksLikeVMSError(const base::string16& text) {
diff --git a/chromium/net/ftp/ftp_network_transaction.cc b/chromium/net/ftp/ftp_network_transaction.cc
index 9c2c136f633..0b458007e90 100644
--- a/chromium/net/ftp/ftp_network_transaction.cc
+++ b/chromium/net/ftp/ftp_network_transaction.cc
@@ -485,10 +485,11 @@ std::string FtpNetworkTransaction::GetRequestPathForFtpCommand(
}
// Make sure that if the path is expected to be a file, it won't end
// with a trailing slash.
- if (!is_directory && path.length() > 1 && path[path.length() - 1] == '/')
+ if (!is_directory && path.length() > 1 && path.back() == '/')
path.erase(path.length() - 1);
- UnescapeRule::Type unescape_rules = UnescapeRule::SPACES |
- UnescapeRule::URL_SPECIAL_CHARS;
+ UnescapeRule::Type unescape_rules =
+ 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.
path = UnescapeURLComponent(path, unescape_rules);
@@ -886,7 +887,7 @@ int FtpNetworkTransaction::ProcessResponsePWD(const FtpCtrlResponse& response) {
}
if (system_type_ == SYSTEM_TYPE_VMS)
line = FtpUtil::VMSPathToUnix(line);
- if (line.length() && line[line.length() - 1] == '/')
+ if (!line.empty() && line.back() == '/')
line.erase(line.length() - 1);
current_remote_directory_ = line;
next_state_ = STATE_CTRL_WRITE_TYPE;
diff --git a/chromium/net/ftp/ftp_network_transaction_unittest.cc b/chromium/net/ftp/ftp_network_transaction_unittest.cc
index ec1dc200c21..cf0b14e08c0 100644
--- a/chromium/net/ftp/ftp_network_transaction_unittest.cc
+++ b/chromium/net/ftp/ftp_network_transaction_unittest.cc
@@ -13,7 +13,6 @@
#include "base/strings/utf_string_conversions.h"
#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
-#include "net/base/net_util.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
#include "net/ftp/ftp_request_info.h"
@@ -431,6 +430,34 @@ class FtpSocketDataProviderFileDownload : public FtpSocketDataProvider {
DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownload);
};
+class FtpSocketDataProviderPathSeparatorsNotUnescaped
+ : public FtpSocketDataProvider {
+ public:
+ FtpSocketDataProviderPathSeparatorsNotUnescaped() {}
+
+ MockWriteResult OnWrite(const std::string& data) override {
+ if (InjectFault())
+ return MockWriteResult(ASYNC, data.length());
+ switch (state()) {
+ case PRE_SIZE:
+ return Verify("SIZE /foo%2f..%2fbar%5c\r\n", data, PRE_CWD,
+ "213 18\r\n");
+ case PRE_CWD:
+ return Verify("CWD /foo%2f..%2fbar%5c\r\n", data,
+ use_epsv() ? PRE_RETR_EPSV : PRE_RETR_PASV,
+ "550 Not a directory\r\n");
+ case PRE_RETR:
+ return Verify("RETR /foo%2f..%2fbar%5c\r\n", data, PRE_QUIT,
+ "200 OK\r\n");
+ default:
+ return FtpSocketDataProvider::OnWrite(data);
+ }
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderPathSeparatorsNotUnescaped);
+};
+
class FtpSocketDataProviderFileNotFound : public FtpSocketDataProvider {
public:
FtpSocketDataProviderFileNotFound() {
@@ -1310,6 +1337,18 @@ TEST_P(FtpNetworkTransactionTest, DownloadTransactionSpaceInPassword) {
ExecuteTransaction(&ctrl_socket, "ftp://test:hello%20world@host/file", OK);
}
+// Make sure FtpNetworkTransaction doesn't request paths like
+// "/foo/../bar". Doing so wouldn't be a security issue, client side, but just
+// doesn't seem like a good idea.
+TEST_P(FtpNetworkTransactionTest,
+ DownloadTransactionPathSeparatorsNotUnescaped) {
+ FtpSocketDataProviderPathSeparatorsNotUnescaped ctrl_socket;
+ 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);
+}
+
TEST_P(FtpNetworkTransactionTest, EvilRestartUser) {
FtpSocketDataProvider ctrl_socket1;
ctrl_socket1.InjectFailure(FtpSocketDataProvider::PRE_PASSWD,
diff --git a/chromium/net/ftp/ftp_util.cc b/chromium/net/ftp/ftp_util.cc
index a2bee15cf5d..d7f759ce786 100644
--- a/chromium/net/ftp/ftp_util.cc
+++ b/chromium/net/ftp/ftp_util.cc
@@ -82,7 +82,7 @@ std::string FtpUtil::UnixDirectoryPathToVMS(const std::string& unix_path) {
std::string path(unix_path);
- if (path[path.length() - 1] != '/')
+ if (path.back() != '/')
path.append("/");
// Reuse logic from UnixFilePathToVMS by appending a fake file name to the
@@ -121,7 +121,7 @@ std::string FtpUtil::VMSPathToUnix(const std::string& vms_path) {
std::replace(result.begin(), result.end(), ']', '/');
// Make sure the result doesn't end with a slash.
- if (result.length() && result[result.length() - 1] == '/')
+ if (!result.empty() && result.back() == '/')
result = result.substr(0, result.length() - 1);
return result;
diff --git a/chromium/net/http/OWNERS b/chromium/net/http/OWNERS
new file mode 100644
index 00000000000..60482fc1ed9
--- /dev/null
+++ b/chromium/net/http/OWNERS
@@ -0,0 +1,2 @@
+per-file transport_security_state_static.*=lgarron@chromium.org
+per-file transport_security_state_static.*=palmer@chromium.org \ No newline at end of file
diff --git a/chromium/net/http/bidirectional_stream.cc b/chromium/net/http/bidirectional_stream.cc
index cacb08478a0..5c04ca3c2e5 100644
--- a/chromium/net/http/bidirectional_stream.cc
+++ b/chromium/net/http/bidirectional_stream.cc
@@ -15,7 +15,9 @@
#include "net/base/net_errors.h"
#include "net/http/bidirectional_stream_request_info.h"
#include "net/http/http_network_session.h"
+#include "net/http/http_response_headers.h"
#include "net/http/http_stream.h"
+#include "net/spdy/spdy_http_utils.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_config.h"
#include "url/gurl.h"
@@ -43,6 +45,7 @@ BidirectionalStream::BidirectionalStream(
: request_info_(std::move(request_info)),
net_log_(BoundNetLog::Make(session->net_log(),
NetLog::SOURCE_BIDIRECTIONAL_STREAM)),
+ session_(session),
delegate_(delegate),
timer_(std::move(timer)) {
DCHECK(delegate_);
@@ -66,14 +69,14 @@ BidirectionalStream::BidirectionalStream(
http_request_info.method = request_info_->method;
http_request_info.extra_headers = request_info_->extra_headers;
stream_request_.reset(
- session->http_stream_factory()->RequestBidirectionalStreamJob(
+ session->http_stream_factory()->RequestBidirectionalStreamImpl(
http_request_info, request_info_->priority, server_ssl_config,
server_ssl_config, this, net_log_));
// Check that this call cannot fail to set a non-NULL |stream_request_|.
DCHECK(stream_request_);
- // Check that HttpStreamFactory does not invoke OnBidirectionalStreamJobReady
+ // Check that HttpStreamFactory does not invoke OnBidirectionalStreamImplReady
// synchronously.
- DCHECK(!stream_job_);
+ DCHECK(!stream_impl_);
}
BidirectionalStream::~BidirectionalStream() {
@@ -81,46 +84,46 @@ BidirectionalStream::~BidirectionalStream() {
}
int BidirectionalStream::ReadData(IOBuffer* buf, int buf_len) {
- DCHECK(stream_job_);
+ DCHECK(stream_impl_);
- return stream_job_->ReadData(buf, buf_len);
+ return stream_impl_->ReadData(buf, buf_len);
}
void BidirectionalStream::SendData(IOBuffer* data,
int length,
bool end_stream) {
- DCHECK(stream_job_);
+ DCHECK(stream_impl_);
- stream_job_->SendData(data, length, end_stream);
+ stream_impl_->SendData(data, length, end_stream);
}
void BidirectionalStream::Cancel() {
stream_request_.reset();
- if (stream_job_) {
- stream_job_->Cancel();
- stream_job_.reset();
+ if (stream_impl_) {
+ stream_impl_->Cancel();
+ stream_impl_.reset();
}
}
NextProto BidirectionalStream::GetProtocol() const {
- if (!stream_job_)
+ if (!stream_impl_)
return kProtoUnknown;
- return stream_job_->GetProtocol();
+ return stream_impl_->GetProtocol();
}
int64_t BidirectionalStream::GetTotalReceivedBytes() const {
- if (!stream_job_)
+ if (!stream_impl_)
return 0;
- return stream_job_->GetTotalReceivedBytes();
+ return stream_impl_->GetTotalReceivedBytes();
}
int64_t BidirectionalStream::GetTotalSentBytes() const {
- if (!stream_job_)
+ if (!stream_impl_)
return 0;
- return stream_job_->GetTotalSentBytes();
+ return stream_impl_->GetTotalSentBytes();
}
void BidirectionalStream::OnHeadersSent() {
@@ -129,6 +132,16 @@ void BidirectionalStream::OnHeadersSent() {
void BidirectionalStream::OnHeadersReceived(
const SpdyHeaderBlock& response_headers) {
+ HttpResponseInfo response_info;
+ if (!SpdyHeadersToHttpResponse(response_headers, HTTP2, &response_info)) {
+ DLOG(WARNING) << "Invalid headers";
+ delegate_->OnFailed(ERR_FAILED);
+ return;
+ }
+
+ session_->http_stream_factory()->ProcessAlternativeServices(
+ session_, response_info.headers.get(),
+ HostPortPair::FromURL(request_info_->url));
delegate_->OnHeadersReceived(response_headers);
}
@@ -154,15 +167,15 @@ void BidirectionalStream::OnStreamReady(const SSLConfig& used_ssl_config,
NOTREACHED();
}
-void BidirectionalStream::OnBidirectionalStreamJobReady(
+void BidirectionalStream::OnBidirectionalStreamImplReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
- BidirectionalStreamJob* stream) {
- DCHECK(!stream_job_);
+ BidirectionalStreamImpl* stream) {
+ DCHECK(!stream_impl_);
stream_request_.reset();
- stream_job_.reset(stream);
- stream_job_->Start(request_info_.get(), net_log_, this, std::move(timer_));
+ stream_impl_.reset(stream);
+ stream_impl_->Start(request_info_.get(), net_log_, this, std::move(timer_));
}
void BidirectionalStream::OnWebSocketHandshakeStreamReady(
diff --git a/chromium/net/http/bidirectional_stream.h b/chromium/net/http/bidirectional_stream.h
index 5de3135e99d..7e6152a48f9 100644
--- a/chromium/net/http/bidirectional_stream.h
+++ b/chromium/net/http/bidirectional_stream.h
@@ -10,14 +10,9 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
-#include "net/http/bidirectional_stream_job.h"
+#include "net/http/bidirectional_stream_impl.h"
#include "net/http/http_stream_factory.h"
#include "net/log/net_log.h"
-#include "net/net_features.h"
-
-#if !BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
-#error Only include this if ENABLE_BIDIRECTIONAL_STREAM is defined
-#endif
class GURL;
@@ -37,7 +32,7 @@ struct SSLConfig;
// ReadData or SendData should be in flight until the operation completes.
// The BidirectionalStream must be torn down before the HttpNetworkSession.
class NET_EXPORT BidirectionalStream
- : public NON_EXPORTED_BASE(BidirectionalStreamJob::Delegate),
+ : public NON_EXPORTED_BASE(BidirectionalStreamImpl::Delegate),
public NON_EXPORTED_BASE(HttpStreamRequest::Delegate) {
public:
// Delegate interface to get notified of success of failure. Callbacks will be
@@ -107,7 +102,7 @@ class NET_EXPORT BidirectionalStream
Delegate* delegate,
scoped_ptr<base::Timer> timer);
- // Cancels |stream_request_| or |stream_job_| if applicable.
+ // Cancels |stream_request_| or |stream_impl_| if applicable.
// |this| should not be destroyed during Delegate::OnHeadersSent or
// Delegate::OnDataSent.
~BidirectionalStream() override;
@@ -126,7 +121,7 @@ class NET_EXPORT BidirectionalStream
// flag.
void SendData(IOBuffer* data, int length, bool end_stream);
- // If |stream_request_| is non-NULL, cancel it. If |stream_job_| is
+ // If |stream_request_| is non-NULL, cancel it. If |stream_impl_| is
// established, cancel it. No delegate method will be called after Cancel().
// Any pending operations may or may not succeed.
void Cancel();
@@ -151,7 +146,7 @@ class NET_EXPORT BidirectionalStream
// remote end point.
private:
- // BidirectionalStreamJob::Delegate implementation:
+ // BidirectionalStreamImpl::Delegate implementation:
void OnHeadersSent() override;
void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override;
void OnDataRead(int bytes_read) override;
@@ -163,9 +158,10 @@ class NET_EXPORT BidirectionalStream
void OnStreamReady(const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStream* stream) override;
- void OnBidirectionalStreamJobReady(const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- BidirectionalStreamJob* stream) override;
+ void OnBidirectionalStreamImplReady(
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ BidirectionalStreamImpl* stream_impl) override;
void OnWebSocketHandshakeStreamReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
@@ -192,17 +188,19 @@ class NET_EXPORT BidirectionalStream
scoped_ptr<BidirectionalStreamRequestInfo> request_info_;
const BoundNetLog net_log_;
+ HttpNetworkSession* session_;
+
Delegate* const delegate_;
// Timer used to buffer data received in short time-spans and send a single
// read completion notification.
scoped_ptr<base::Timer> timer_;
- // HttpStreamRequest used to request a BidirectionalStreamJob. This is NULL if
- // the request has been canceled or completed.
+ // HttpStreamRequest used to request a BidirectionalStreamImpl. This is NULL
+ // if the request has been canceled or completed.
scoped_ptr<HttpStreamRequest> stream_request_;
- // The underlying BidirectioanlStreamJob used for this stream. It is non-NULL,
- // if the |stream_request_| successfully finishes.
- scoped_ptr<BidirectionalStreamJob> stream_job_;
+ // The underlying BidirectioanlStreamImpl used for this stream. It is
+ // non-NULL, if the |stream_request_| successfully finishes.
+ scoped_ptr<BidirectionalStreamImpl> stream_impl_;
DISALLOW_COPY_AND_ASSIGN(BidirectionalStream);
};
diff --git a/chromium/net/http/bidirectional_stream_impl.cc b/chromium/net/http/bidirectional_stream_impl.cc
new file mode 100644
index 00000000000..6cbf69f6b0f
--- /dev/null
+++ b/chromium/net/http/bidirectional_stream_impl.cc
@@ -0,0 +1,17 @@
+// 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/bidirectional_stream_impl.h"
+
+namespace net {
+
+BidirectionalStreamImpl::Delegate::Delegate() {}
+
+BidirectionalStreamImpl::Delegate::~Delegate() {}
+
+BidirectionalStreamImpl::BidirectionalStreamImpl() {}
+
+BidirectionalStreamImpl::~BidirectionalStreamImpl() {}
+
+} // namespace net
diff --git a/chromium/net/http/bidirectional_stream_job.h b/chromium/net/http/bidirectional_stream_impl.h
index 001944de5e5..3f82e6f6e41 100644
--- a/chromium/net/http/bidirectional_stream_job.h
+++ b/chromium/net/http/bidirectional_stream_impl.h
@@ -2,21 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_HTTP_BIDIRECTIONAL_STREAM_JOB_H_
-#define NET_HTTP_BIDIRECTIONAL_STREAM_JOB_H_
+#ifndef NET_HTTP_BIDIRECTIONAL_STREAM_IMPL_H_
+#define NET_HTTP_BIDIRECTIONAL_STREAM_IMPL_H_
#include <stdint.h>
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/net_export.h"
-#include "net/net_features.h"
#include "net/socket/next_proto.h"
-#if !BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
-#error Only include this if ENABLE_BIDIRECTIONAL_STREAM is defined
-#endif
-
namespace base {
class Timer;
} // namespace base
@@ -31,41 +26,41 @@ struct BidirectionalStreamRequestInfo;
// Exposes an interface to do HTTP/2 bidirectional streaming.
// Note that only one ReadData or SendData should be in flight until the
// operation completes synchronously or asynchronously.
-// BidirectionalStreamJob once created by HttpStreamFactoryImpl should be owned
+// BidirectionalStreamImpl once created by HttpStreamFactoryImpl should be owned
// by BidirectionalStream.
-class NET_EXPORT_PRIVATE BidirectionalStreamJob {
+class NET_EXPORT_PRIVATE BidirectionalStreamImpl {
public:
- // Delegate to handle BidirectionalStreamJob events.
+ // Delegate to handle BidirectionalStreamImpl events.
class NET_EXPORT_PRIVATE Delegate {
public:
Delegate();
// Called when the request headers have been sent.
- // The delegate may call BidirectionalStreamJob::ReadData to start reading,
- // call BidirectionalStreamJob::SendData to send data,
- // or call BidirectionalStreamJob::Cancel to cancel the stream.
- // The delegate should not call BidirectionalStreamJob::Cancel
+ // The delegate may call BidirectionalStreamImpl::ReadData to start reading,
+ // call BidirectionalStreamImpl::SendData to send data,
+ // or call BidirectionalStreamImpl::Cancel to cancel the stream.
+ // The delegate should not call BidirectionalStreamImpl::Cancel
// during this callback.
virtual void OnHeadersSent() = 0;
// Called when response headers are received.
// This is called at most once for the lifetime of a stream.
- // The delegate may call BidirectionalStreamJob::ReadData to start
- // reading, call BidirectionalStreamJob::SendData to send data,
- // or call BidirectionalStreamJob::Cancel to cancel the stream.
+ // The delegate may call BidirectionalStreamImpl::ReadData to start
+ // reading, call BidirectionalStreamImpl::SendData to send data,
+ // or call BidirectionalStreamImpl::Cancel to cancel the stream.
virtual void OnHeadersReceived(const SpdyHeaderBlock& response_headers) = 0;
// Called when read is completed asynchronously. |bytes_read| specifies how
// much data is available.
- // The delegate may call BidirectionalStreamJob::ReadData to continue
- // reading, call BidirectionalStreamJob::SendData to send data,
- // or call BidirectionalStreamJob::Cancel to cancel the stream.
+ // The delegate may call BidirectionalStreamImpl::ReadData to continue
+ // reading, call BidirectionalStreamImpl::SendData to send data,
+ // or call BidirectionalStreamImpl::Cancel to cancel the stream.
virtual void OnDataRead(int bytes_read) = 0;
// Called when the entire buffer passed through SendData is sent.
- // The delegate may call BidirectionalStreamJob::ReadData to continue
- // reading, or call BidirectionalStreamJob::SendData to send data.
- // The delegate should not call BidirectionalStreamJob::Cancel
+ // The delegate may call BidirectionalStreamImpl::ReadData to continue
+ // reading, or call BidirectionalStreamImpl::SendData to send data.
+ // The delegate should not call BidirectionalStreamImpl::Cancel
// during this callback.
virtual void OnDataSent() = 0;
@@ -86,16 +81,16 @@ class NET_EXPORT_PRIVATE BidirectionalStreamJob {
DISALLOW_COPY_AND_ASSIGN(Delegate);
};
- BidirectionalStreamJob();
+ BidirectionalStreamImpl();
// |this| should not be destroyed during Delegate::OnHeadersSent or
// Delegate::OnDataSent.
- virtual ~BidirectionalStreamJob();
+ virtual ~BidirectionalStreamImpl();
- // Starts the BidirectionalStreamJob and sends request headers.
+ // Starts the BidirectionalStreamImpl and sends request headers.
virtual void Start(const BidirectionalStreamRequestInfo* request_info,
const BoundNetLog& net_log,
- BidirectionalStreamJob::Delegate* delegate,
+ BidirectionalStreamImpl::Delegate* delegate,
scoped_ptr<base::Timer> timer) = 0;
// Reads at most |buf_len| bytes into |buf|. Returns the number of bytes read,
@@ -132,9 +127,9 @@ class NET_EXPORT_PRIVATE BidirectionalStreamJob {
virtual int64_t GetTotalSentBytes() const = 0;
private:
- DISALLOW_COPY_AND_ASSIGN(BidirectionalStreamJob);
+ DISALLOW_COPY_AND_ASSIGN(BidirectionalStreamImpl);
};
} // namespace net
-#endif // NET_HTTP_BIDIRECTIONAL_STREAM_JOB_H_
+#endif // NET_HTTP_BIDIRECTIONAL_STREAM_IMPL_H_
diff --git a/chromium/net/http/bidirectional_stream_job.cc b/chromium/net/http/bidirectional_stream_job.cc
deleted file mode 100644
index 3c307536f94..00000000000
--- a/chromium/net/http/bidirectional_stream_job.cc
+++ /dev/null
@@ -1,17 +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/bidirectional_stream_job.h"
-
-namespace net {
-
-BidirectionalStreamJob::Delegate::Delegate() {}
-
-BidirectionalStreamJob::Delegate::~Delegate() {}
-
-BidirectionalStreamJob::BidirectionalStreamJob() {}
-
-BidirectionalStreamJob::~BidirectionalStreamJob() {}
-
-} // namespace net
diff --git a/chromium/net/http/bidirectional_stream_unittest.cc b/chromium/net/http/bidirectional_stream_unittest.cc
index aeee7a869e0..4d6445f4631 100644
--- a/chromium/net/http/bidirectional_stream_unittest.cc
+++ b/chromium/net/http/bidirectional_stream_unittest.cc
@@ -16,6 +16,7 @@
#include "net/http/bidirectional_stream_request_info.h"
#include "net/http/http_network_session.h"
#include "net/http/http_response_headers.h"
+#include "net/http/http_server_properties.h"
#include "net/log/net_log.h"
#include "net/socket/socket_test_util.h"
#include "net/spdy/spdy_session.h"
@@ -296,7 +297,7 @@ class MockTimer : public base::MockTimer {
class BidirectionalStreamTest : public testing::TestWithParam<bool> {
public:
BidirectionalStreamTest()
- : spdy_util_(kProtoHTTP2, false),
+ : spdy_util_(kProtoHTTP2, true),
session_deps_(kProtoHTTP2),
ssl_data_(SSLSocketDataProvider(ASYNC, OK)) {
ssl_data_.SetNextProto(kProtoHTTP2);
@@ -353,12 +354,12 @@ TEST_F(BidirectionalStreamTest, CreateInsecureStream) {
}
// Simulates user calling ReadData after END_STREAM has been received in
-// BidirectionalStreamSpdyJob.
+// BidirectionalStreamSpdyImpl.
TEST_F(BidirectionalStreamTest, TestReadDataAfterClose) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
// Empty DATA frame with an END_STREAM flag.
- scoped_ptr<SpdyFrame> end_stream(
+ scoped_ptr<SpdySerializedFrame> end_stream(
spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
MockWrite writes[] = {
CreateMockWrite(*req.get(), 0),
@@ -366,12 +367,13 @@ TEST_F(BidirectionalStreamTest, TestReadDataAfterClose) {
const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
- scoped_ptr<SpdyFrame> body_frame(spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> body_frame(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
// Last body frame has END_STREAM flag set.
- scoped_ptr<SpdyFrame> last_body_frame(
+ scoped_ptr<SpdySerializedFrame> last_body_frame(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
@@ -398,7 +400,7 @@ TEST_F(BidirectionalStreamTest, TestReadDataAfterClose) {
scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
// Create a MockTimer. Retain a raw pointer since the underlying
- // BidirectionalStreamJob owns it.
+ // BidirectionalStreamImpl owns it.
MockTimer* timer = new MockTimer();
scoped_ptr<TestDelegateBase> delegate(new TestDelegateBase(
read_buffer.get(), kReadBufferSize, make_scoped_ptr(timer)));
@@ -443,26 +445,26 @@ TEST_F(BidirectionalStreamTest, TestReadDataAfterClose) {
}
TEST_F(BidirectionalStreamTest, TestInterleaveReadDataAndSendData) {
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
"https://www.example.org", 1, kBodyDataSize * 3, LOWEST, nullptr, 0));
- scoped_ptr<SpdyFrame> data_frame1(
+ scoped_ptr<SpdySerializedFrame> data_frame1(
framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> data_frame2(
+ scoped_ptr<SpdySerializedFrame> data_frame2(
framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> data_frame3(
+ scoped_ptr<SpdySerializedFrame> data_frame3(
framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_FIN));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*data_frame1, 3),
CreateMockWrite(*data_frame2, 6), CreateMockWrite(*data_frame3, 9),
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> response_body_frame1(
+ scoped_ptr<SpdySerializedFrame> response_body_frame1(
spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> response_body_frame2(
+ scoped_ptr<SpdySerializedFrame> response_body_frame2(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
@@ -549,21 +551,21 @@ TEST_F(BidirectionalStreamTest, TestInterleaveReadDataAndSendData) {
delegate->GetTotalReceivedBytes());
}
-// Tests that BidirectionalStreamSpdyJob::OnClose will complete any remaining
+// Tests that BidirectionalStreamSpdyImpl::OnClose will complete any remaining
// read even if the read queue is empty.
TEST_F(BidirectionalStreamTest, TestCompleteAsyncRead) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
// Empty DATA frame with an END_STREAM flag.
- scoped_ptr<SpdyFrame> end_stream(
+ scoped_ptr<SpdySerializedFrame> end_stream(
spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
MockWrite writes[] = {CreateMockWrite(*req.get(), 0)};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> response_body_frame(
+ scoped_ptr<SpdySerializedFrame> response_body_frame(
spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
MockRead reads[] = {
@@ -614,22 +616,23 @@ TEST_F(BidirectionalStreamTest, TestCompleteAsyncRead) {
}
TEST_F(BidirectionalStreamTest, TestBuffering) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
// Empty DATA frame with an END_STREAM flag.
- scoped_ptr<SpdyFrame> end_stream(
+ scoped_ptr<SpdySerializedFrame> end_stream(
spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
MockWrite writes[] = {CreateMockWrite(*req.get(), 0)};
const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
- scoped_ptr<SpdyFrame> body_frame(spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> body_frame(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
// Last body frame has END_STREAM flag set.
- scoped_ptr<SpdyFrame> last_body_frame(
+ scoped_ptr<SpdySerializedFrame> last_body_frame(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
@@ -695,10 +698,10 @@ TEST_F(BidirectionalStreamTest, TestBuffering) {
}
TEST_F(BidirectionalStreamTest, TestBufferingWithTrailers) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
// Empty DATA frame with an END_STREAM flag.
- scoped_ptr<SpdyFrame> end_stream(
+ scoped_ptr<SpdySerializedFrame> end_stream(
spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
MockWrite writes[] = {
@@ -707,14 +710,16 @@ TEST_F(BidirectionalStreamTest, TestBufferingWithTrailers) {
const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
- scoped_ptr<SpdyFrame> body_frame(spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> body_frame(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
- const char* const kTrailers[] = {"foo", "bar"};
- scoped_ptr<SpdyFrame> trailers(
- spdy_util_.ConstructSpdyHeaderFrame(1, kTrailers, 1, true));
+ SpdyHeaderBlock late_headers;
+ late_headers["foo"] = "bar";
+ scoped_ptr<SpdySerializedFrame> trailers(
+ spdy_util_.ConstructSpdyResponseHeaders(1, late_headers, true));
MockRead reads[] = {
CreateMockRead(*resp, 1), CreateMockRead(*body_frame, 2),
@@ -771,13 +776,13 @@ TEST_F(BidirectionalStreamTest, TestBufferingWithTrailers) {
}
TEST_F(BidirectionalStreamTest, CancelStreamAfterSendData) {
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
"https://www.example.org", 1, kBodyDataSize * 3, LOWEST, nullptr, 0));
- scoped_ptr<SpdyFrame> data_frame(
+ scoped_ptr<SpdySerializedFrame> data_frame(
framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
@@ -785,9 +790,9 @@ TEST_F(BidirectionalStreamTest, CancelStreamAfterSendData) {
CreateMockWrite(*rst, 5),
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> response_body_frame(
+ scoped_ptr<SpdySerializedFrame> response_body_frame(
spdy_util_.ConstructSpdyBodyFrame(1, false));
MockRead reads[] = {
@@ -841,22 +846,22 @@ TEST_F(BidirectionalStreamTest, CancelStreamAfterSendData) {
}
TEST_F(BidirectionalStreamTest, CancelStreamDuringReadData) {
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
"https://www.example.org", 1, kBodyDataSize * 3, LOWEST, nullptr, 0));
- scoped_ptr<SpdyFrame> data_frame(
+ scoped_ptr<SpdySerializedFrame> data_frame(
framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> response_body_frame(
+ scoped_ptr<SpdySerializedFrame> response_body_frame(
spdy_util_.ConstructSpdyBodyFrame(1, false));
MockRead reads[] = {
@@ -906,9 +911,9 @@ TEST_F(BidirectionalStreamTest, CancelStreamDuringReadData) {
// Receiving a header with uppercase ASCII will result in a protocol error,
// which should be propagated via Delegate::OnFailed.
TEST_F(BidirectionalStreamTest, PropagateProtocolError) {
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
"https://www.example.org", 1, kBodyDataSize * 3, LOW, nullptr, 0));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
@@ -916,7 +921,7 @@ TEST_F(BidirectionalStreamTest, PropagateProtocolError) {
};
const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
MockRead reads[] = {
@@ -960,10 +965,10 @@ INSTANTIATE_TEST_CASE_P(CancelOrDeleteTests,
::testing::Values(true, false));
TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnHeadersReceived) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
@@ -971,7 +976,7 @@ TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnHeadersReceived) {
const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
MockRead reads[] = {
@@ -1016,10 +1021,10 @@ TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnHeadersReceived) {
}
TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnDataRead) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
@@ -1027,10 +1032,10 @@ TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnDataRead) {
const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
- scoped_ptr<SpdyFrame> response_body_frame(
+ scoped_ptr<SpdySerializedFrame> response_body_frame(
spdy_util_.ConstructSpdyBodyFrame(1, false));
MockRead reads[] = {
@@ -1075,10 +1080,10 @@ TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnDataRead) {
}
TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnTrailersReceived) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
@@ -1086,15 +1091,16 @@ TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnTrailersReceived) {
const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
- scoped_ptr<SpdyFrame> response_body_frame(
+ scoped_ptr<SpdySerializedFrame> response_body_frame(
spdy_util_.ConstructSpdyBodyFrame(1, false));
- const char* const kTrailers[] = {"foo", "bar"};
- scoped_ptr<SpdyFrame> trailers(
- spdy_util_.ConstructSpdyHeaderFrame(1, kTrailers, 1, true));
+ SpdyHeaderBlock late_headers;
+ late_headers["foo"] = "bar";
+ scoped_ptr<SpdySerializedFrame> trailers(
+ spdy_util_.ConstructSpdyResponseHeaders(1, late_headers, true));
MockRead reads[] = {
CreateMockRead(*resp, 1), CreateMockRead(*response_body_frame, 2),
@@ -1140,10 +1146,10 @@ TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnTrailersReceived) {
}
TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnFailed) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
@@ -1151,7 +1157,7 @@ TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnFailed) {
};
const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
MockRead reads[] = {
@@ -1193,4 +1199,72 @@ TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnFailed) {
EXPECT_EQ(kProtoUnknown, delegate->GetProtocol());
}
+TEST_F(BidirectionalStreamTest, TestHonorAlternativeServiceHeader) {
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
+ // Empty DATA frame with an END_STREAM flag.
+ scoped_ptr<SpdySerializedFrame> end_stream(
+ spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
+
+ MockWrite writes[] = {CreateMockWrite(*req.get(), 0)};
+
+ std::string alt_svc_header_value = AlternateProtocolToString(QUIC);
+ alt_svc_header_value.append("=\"www.example.org:443\"");
+ const char* const kExtraResponseHeaders[] = {"alt-svc",
+ alt_svc_header_value.c_str()};
+
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
+ scoped_ptr<SpdySerializedFrame> body_frame(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+
+ MockRead reads[] = {
+ CreateMockRead(*resp, 1), CreateMockRead(*body_frame, 2),
+ MockRead(SYNCHRONOUS, 0, 3),
+ };
+
+ HostPortPair host_port_pair("www.example.org", 443);
+ SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
+ PRIVACY_MODE_DISABLED);
+ session_deps_.parse_alternative_services = true;
+ // Enable QUIC so that the alternative service header can be added to
+ // HttpServerProperties.
+ session_deps_.enable_quic = true;
+ InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
+
+ scoped_ptr<BidirectionalStreamRequestInfo> request_info(
+ new BidirectionalStreamRequestInfo);
+ request_info->method = "GET";
+ request_info->url = GURL("https://www.example.org/");
+ request_info->priority = LOWEST;
+ request_info->end_stream_on_headers = true;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ MockTimer* timer = new MockTimer();
+ scoped_ptr<TestDelegateBase> delegate(new TestDelegateBase(
+ read_buffer.get(), kReadBufferSize, make_scoped_ptr(timer)));
+ delegate->SetRunUntilCompletion(true);
+ delegate->Start(std::move(request_info), http_session_.get());
+
+ const SpdyHeaderBlock response_headers = delegate->response_headers();
+ EXPECT_EQ("200", response_headers.find(":status")->second);
+ EXPECT_EQ(alt_svc_header_value, response_headers.find("alt-svc")->second);
+ EXPECT_EQ(0, delegate->on_data_sent_count());
+ EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
+ EXPECT_EQ(kUploadData, delegate->data_received());
+ EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
+ delegate->GetTotalSentBytes());
+ EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
+ delegate->GetTotalReceivedBytes());
+
+ AlternativeServiceVector alternative_service_vector =
+ http_session_->http_server_properties()->GetAlternativeServices(
+ host_port_pair);
+ ASSERT_EQ(1u, alternative_service_vector.size());
+ EXPECT_EQ(AlternateProtocolFromNextProto(kProtoQUIC1SPDY3),
+ alternative_service_vector[0].protocol);
+ EXPECT_EQ("www.example.org", alternative_service_vector[0].host);
+ EXPECT_EQ(443, alternative_service_vector[0].port);
+}
+
} // namespace net
diff --git a/chromium/net/http/disk_based_cert_cache.cc b/chromium/net/http/disk_based_cert_cache.cc
deleted file mode 100644
index 913e1b7fba0..00000000000
--- a/chromium/net/http/disk_based_cert_cache.cc
+++ /dev/null
@@ -1,598 +0,0 @@
-// Copyright (c) 2014 The Chromium 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/disk_based_cert_cache.h"
-
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback_helpers.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 "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/disk_cache/disk_cache.h"
-
-namespace net {
-
-namespace {
-
-// TODO(brandonsalmon): change this number to improve performance.
-const size_t kMemoryCacheMaxSize = 30;
-
-// Used to obtain a unique cache key for a certificate in the form of
-// "cert:<hash>".
-std::string GetCacheKeyForCert(
- const X509Certificate::OSCertHandle cert_handle) {
- SHA1HashValue fingerprint =
- X509Certificate::CalculateFingerprint(cert_handle);
-
- return "cert:" +
- base::HexEncode(fingerprint.data, arraysize(fingerprint.data));
-}
-
-enum CacheResult {
- MEMORY_CACHE_HIT = 0,
- DISK_CACHE_HIT,
- DISK_CACHE_ENTRY_CORRUPT,
- DISK_CACHE_ERROR,
- CACHE_RESULT_MAX
-};
-
-void RecordCacheResult(CacheResult result) {
- UMA_HISTOGRAM_ENUMERATION(
- "DiskBasedCertCache.CertIoCacheResult", result, CACHE_RESULT_MAX);
-}
-
-} // namespace
-
-// WriteWorkers represent pending SetCertificate jobs in the DiskBasedCertCache.
-// Each certificate requested to be stored is assigned a WriteWorker.
-// The same certificate should not have multiple WriteWorkers at the same
-// time; instead, add a user callback to the existing WriteWorker.
-class DiskBasedCertCache::WriteWorker {
- public:
- // |backend| is the backend to store |certificate| in, using
- // |key| as the key for the disk_cache::Entry.
- // |cleanup_callback| is called to clean up this ReadWorker,
- // regardless of success or failure.
- WriteWorker(disk_cache::Backend* backend,
- const std::string& key,
- X509Certificate::OSCertHandle cert_handle,
- const base::Closure& cleanup_callback);
-
- ~WriteWorker();
-
- // Writes the given certificate to the cache. On completion, will invoke all
- // user callbacks.
- void Start();
-
- // Adds a callback to the set of callbacks to be run when this
- // WriteWorker finishes processing.
- void AddCallback(const SetCallback& user_callback);
-
- // Signals the WriteWorker to abort early. The WriteWorker will be destroyed
- // upon the completion of any pending callbacks. User callbacks will be
- // invoked with an empty string.
- void Cancel();
-
- private:
- enum State {
- STATE_OPEN,
- STATE_OPEN_COMPLETE,
- STATE_CREATE,
- STATE_CREATE_COMPLETE,
- STATE_WRITE,
- STATE_WRITE_COMPLETE,
- STATE_NONE
- };
-
- void OnIOComplete(int rv);
- int DoLoop(int rv);
-
- int DoOpen();
- int DoOpenComplete(int rv);
- int DoCreate();
- int DoCreateComplete(int rv);
- int DoWrite();
- int DoWriteComplete(int rv);
-
- void Finish(int rv);
-
- // Invokes all of the |user_callbacks_|
- void RunCallbacks(int rv);
-
- disk_cache::Backend* backend_;
- const X509Certificate::OSCertHandle cert_handle_;
- std::string key_;
- bool canceled_;
-
- disk_cache::Entry* entry_;
- State next_state_;
- scoped_refptr<IOBuffer> buffer_;
- int io_buf_len_;
-
- base::Closure cleanup_callback_;
- std::vector<SetCallback> user_callbacks_;
- CompletionCallback io_callback_;
-};
-
-DiskBasedCertCache::WriteWorker::WriteWorker(
- disk_cache::Backend* backend,
- const std::string& key,
- X509Certificate::OSCertHandle cert_handle,
- const base::Closure& cleanup_callback)
- : backend_(backend),
- cert_handle_(X509Certificate::DupOSCertHandle(cert_handle)),
- key_(key),
- canceled_(false),
- entry_(NULL),
- next_state_(STATE_NONE),
- io_buf_len_(0),
- cleanup_callback_(cleanup_callback),
- io_callback_(
- base::Bind(&WriteWorker::OnIOComplete, base::Unretained(this))) {
-}
-
-DiskBasedCertCache::WriteWorker::~WriteWorker() {
- if (cert_handle_)
- X509Certificate::FreeOSCertHandle(cert_handle_);
- if (entry_)
- entry_->Close();
-}
-
-void DiskBasedCertCache::WriteWorker::Start() {
- DCHECK_EQ(STATE_NONE, next_state_);
-
- next_state_ = STATE_OPEN;
- int rv = DoLoop(OK);
-
- if (rv == ERR_IO_PENDING)
- return;
-
- Finish(rv);
-}
-
-void DiskBasedCertCache::WriteWorker::AddCallback(
- const SetCallback& user_callback) {
- user_callbacks_.push_back(user_callback);
-}
-
-void DiskBasedCertCache::WriteWorker::Cancel() {
- canceled_ = true;
-}
-
-void DiskBasedCertCache::WriteWorker::OnIOComplete(int rv) {
- if (canceled_) {
- Finish(ERR_FAILED);
- return;
- }
-
- rv = DoLoop(rv);
-
- if (rv == ERR_IO_PENDING)
- return;
-
- Finish(rv);
-}
-
-int DiskBasedCertCache::WriteWorker::DoLoop(int rv) {
- do {
- State state = next_state_;
- next_state_ = STATE_NONE;
- switch (state) {
- case STATE_OPEN:
- rv = DoOpen();
- break;
- case STATE_OPEN_COMPLETE:
- rv = DoOpenComplete(rv);
- break;
- case STATE_CREATE:
- rv = DoCreate();
- break;
- case STATE_CREATE_COMPLETE:
- rv = DoCreateComplete(rv);
- break;
- case STATE_WRITE:
- rv = DoWrite();
- break;
- case STATE_WRITE_COMPLETE:
- rv = DoWriteComplete(rv);
- break;
- case STATE_NONE:
- NOTREACHED();
- break;
- }
- } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
-
- return rv;
-}
-
-int DiskBasedCertCache::WriteWorker::DoOpen() {
- next_state_ = STATE_OPEN_COMPLETE;
- return backend_->OpenEntry(key_, &entry_, io_callback_);
-}
-
-int DiskBasedCertCache::WriteWorker::DoOpenComplete(int rv) {
- // The entry doesn't exist yet, so we should create it.
- if (rv < 0) {
- next_state_ = STATE_CREATE;
- return OK;
- }
-
- next_state_ = STATE_WRITE;
- return OK;
-}
-
-int DiskBasedCertCache::WriteWorker::DoCreate() {
- next_state_ = STATE_CREATE_COMPLETE;
- return backend_->CreateEntry(key_, &entry_, io_callback_);
-}
-
-int DiskBasedCertCache::WriteWorker::DoCreateComplete(int rv) {
- if (rv < 0)
- return rv;
-
- next_state_ = STATE_WRITE;
- return OK;
-}
-
-int DiskBasedCertCache::WriteWorker::DoWrite() {
- std::string write_data;
- bool encoded = X509Certificate::GetDEREncoded(cert_handle_, &write_data);
-
- if (!encoded)
- return ERR_FAILED;
-
- buffer_ = new IOBuffer(write_data.size());
- io_buf_len_ = write_data.size();
- memcpy(buffer_->data(), write_data.data(), io_buf_len_);
-
- next_state_ = STATE_WRITE_COMPLETE;
-
- return entry_->WriteData(0 /* index */,
- 0 /* offset */,
- buffer_.get(),
- write_data.size(),
- io_callback_,
- true /* truncate */);
-}
-
-int DiskBasedCertCache::WriteWorker::DoWriteComplete(int rv) {
- if (rv < io_buf_len_)
- return ERR_FAILED;
-
- return OK;
-}
-
-void DiskBasedCertCache::WriteWorker::Finish(int rv) {
- cleanup_callback_.Run();
- cleanup_callback_.Reset();
- RunCallbacks(rv);
- delete this;
-}
-
-void DiskBasedCertCache::WriteWorker::RunCallbacks(int rv) {
- std::string key;
- if (rv >= 0)
- key = key_;
-
- for (std::vector<SetCallback>::const_iterator it = user_callbacks_.begin();
- it != user_callbacks_.end();
- ++it) {
- it->Run(key);
- }
- user_callbacks_.clear();
-}
-
-// ReadWorkers represent pending GetCertificate jobs in the DiskBasedCertCache.
-// Each certificate requested to be retrieved from the cache is assigned a
-// ReadWorker. The same |key| should not have multiple ReadWorkers at the
-// same time; instead, call AddCallback to add a user callback to the
-// existing ReadWorker.
-class DiskBasedCertCache::ReadWorker {
- public:
- // |backend| is the backend to read |certificate| from, using
- // |key| as the key for the disk_cache::Entry.
- // |cleanup_callback| is called to clean up this ReadWorker,
- // regardless of success or failure.
- ReadWorker(disk_cache::Backend* backend,
- const std::string& key,
- const GetCallback& cleanup_callback);
-
- ~ReadWorker();
-
- // Reads the given certificate from the cache. On completion, will invoke all
- // user callbacks.
- void Start();
-
- // Adds a callback to the set of callbacks to be run when this
- // ReadWorker finishes processing.
- void AddCallback(const GetCallback& user_callback);
-
- // Signals the ReadWorker to abort early. The ReadWorker will be destroyed
- // upon the completion of any pending callbacks. User callbacks will be
- // invoked with a NULL cert handle.
- void Cancel();
-
- private:
- enum State {
- STATE_OPEN,
- STATE_OPEN_COMPLETE,
- STATE_READ,
- STATE_READ_COMPLETE,
- STATE_NONE
- };
-
- void OnIOComplete(int rv);
- int DoLoop(int rv);
- int DoOpen();
- int DoOpenComplete(int rv);
- int DoRead();
- int DoReadComplete(int rv);
- void Finish(int rv);
-
- // Invokes all of |user_callbacks_|
- void RunCallbacks();
-
- disk_cache::Backend* backend_;
- X509Certificate::OSCertHandle cert_handle_;
- std::string key_;
- bool canceled_;
-
- disk_cache::Entry* entry_;
-
- State next_state_;
- scoped_refptr<IOBuffer> buffer_;
- int io_buf_len_;
-
- GetCallback cleanup_callback_;
- std::vector<GetCallback> user_callbacks_;
- CompletionCallback io_callback_;
-};
-
-DiskBasedCertCache::ReadWorker::ReadWorker(disk_cache::Backend* backend,
- const std::string& key,
- const GetCallback& cleanup_callback)
- : backend_(backend),
- cert_handle_(NULL),
- key_(key),
- canceled_(false),
- entry_(NULL),
- next_state_(STATE_NONE),
- io_buf_len_(0),
- cleanup_callback_(cleanup_callback),
- io_callback_(
- base::Bind(&ReadWorker::OnIOComplete, base::Unretained(this))) {
-}
-
-DiskBasedCertCache::ReadWorker::~ReadWorker() {
- if (entry_)
- entry_->Close();
- if (cert_handle_)
- X509Certificate::FreeOSCertHandle(cert_handle_);
-}
-
-void DiskBasedCertCache::ReadWorker::Start() {
- DCHECK_EQ(STATE_NONE, next_state_);
- next_state_ = STATE_OPEN;
- int rv = DoLoop(OK);
-
- if (rv == ERR_IO_PENDING)
- return;
-
- Finish(rv);
-}
-
-void DiskBasedCertCache::ReadWorker::AddCallback(
- const GetCallback& user_callback) {
- user_callbacks_.push_back(user_callback);
-}
-
-void DiskBasedCertCache::ReadWorker::Cancel() {
- canceled_ = true;
-}
-
-void DiskBasedCertCache::ReadWorker::OnIOComplete(int rv) {
- if (canceled_) {
- Finish(ERR_FAILED);
- return;
- }
-
- rv = DoLoop(rv);
-
- if (rv == ERR_IO_PENDING)
- return;
-
- Finish(rv);
-}
-
-int DiskBasedCertCache::ReadWorker::DoLoop(int rv) {
- do {
- State state = next_state_;
- next_state_ = STATE_NONE;
- switch (state) {
- case STATE_OPEN:
- rv = DoOpen();
- break;
- case STATE_OPEN_COMPLETE:
- rv = DoOpenComplete(rv);
- break;
- case STATE_READ:
- rv = DoRead();
- break;
- case STATE_READ_COMPLETE:
- rv = DoReadComplete(rv);
- break;
- case STATE_NONE:
- NOTREACHED();
- break;
- }
- } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
-
- return rv;
-}
-
-int DiskBasedCertCache::ReadWorker::DoOpen() {
- next_state_ = STATE_OPEN_COMPLETE;
- return backend_->OpenEntry(key_, &entry_, io_callback_);
-}
-
-int DiskBasedCertCache::ReadWorker::DoOpenComplete(int rv) {
- if (rv < 0) {
- RecordCacheResult(DISK_CACHE_ERROR);
- return rv;
- }
-
- next_state_ = STATE_READ;
- return OK;
-}
-
-int DiskBasedCertCache::ReadWorker::DoRead() {
- next_state_ = STATE_READ_COMPLETE;
- io_buf_len_ = entry_->GetDataSize(0 /* index */);
- buffer_ = new IOBuffer(io_buf_len_);
- return entry_->ReadData(
- 0 /* index */, 0 /* offset */, buffer_.get(), io_buf_len_, io_callback_);
-}
-
-int DiskBasedCertCache::ReadWorker::DoReadComplete(int rv) {
- // The cache should return the entire buffer length. If it does not,
- // it is probably indicative of an issue other than corruption.
- if (rv < io_buf_len_) {
- RecordCacheResult(DISK_CACHE_ERROR);
- return ERR_FAILED;
- }
- cert_handle_ = X509Certificate::CreateOSCertHandleFromBytes(buffer_->data(),
- io_buf_len_);
- if (!cert_handle_) {
- RecordCacheResult(DISK_CACHE_ENTRY_CORRUPT);
- return ERR_FAILED;
- }
-
- RecordCacheResult(DISK_CACHE_HIT);
- return OK;
-}
-
-void DiskBasedCertCache::ReadWorker::Finish(int rv) {
- cleanup_callback_.Run(cert_handle_);
- cleanup_callback_.Reset();
- RunCallbacks();
- delete this;
-}
-
-void DiskBasedCertCache::ReadWorker::RunCallbacks() {
- for (std::vector<GetCallback>::const_iterator it = user_callbacks_.begin();
- it != user_callbacks_.end();
- ++it) {
- it->Run(cert_handle_);
- }
- user_callbacks_.clear();
-}
-
-void DiskBasedCertCache::CertFree::operator()(
- X509Certificate::OSCertHandle cert_handle) {
- X509Certificate::FreeOSCertHandle(cert_handle);
-}
-
-DiskBasedCertCache::DiskBasedCertCache(disk_cache::Backend* backend)
- : backend_(backend),
- mru_cert_cache_(kMemoryCacheMaxSize),
- mem_cache_hits_(0),
- mem_cache_misses_(0),
- weak_factory_(this) {
- DCHECK(backend_);
-}
-
-DiskBasedCertCache::~DiskBasedCertCache() {
- for (WriteWorkerMap::iterator it = write_worker_map_.begin();
- it != write_worker_map_.end();
- ++it) {
- it->second->Cancel();
- }
- for (ReadWorkerMap::iterator it = read_worker_map_.begin();
- it != read_worker_map_.end();
- ++it) {
- it->second->Cancel();
- }
-}
-
-void DiskBasedCertCache::GetCertificate(const std::string& key,
- const GetCallback& cb) {
- DCHECK(!key.empty());
-
- // If the handle is already in the MRU cache, just return that (via callback).
- // Note, this will also bring the cert_handle to the front of the recency
- // list in the MRU cache.
- MRUCertCache::iterator mru_it = mru_cert_cache_.Get(key);
- if (mru_it != mru_cert_cache_.end()) {
- RecordCacheResult(MEMORY_CACHE_HIT);
- ++mem_cache_hits_;
- cb.Run(mru_it->second);
- return;
- }
- ++mem_cache_misses_;
-
- ReadWorkerMap::iterator it = read_worker_map_.find(key);
-
- if (it == read_worker_map_.end()) {
- ReadWorker* worker =
- new ReadWorker(backend_,
- key,
- base::Bind(&DiskBasedCertCache::FinishedReadOperation,
- weak_factory_.GetWeakPtr(),
- key));
- read_worker_map_[key] = worker;
- worker->AddCallback(cb);
- worker->Start();
- } else {
- it->second->AddCallback(cb);
- }
-}
-
-void DiskBasedCertCache::SetCertificate(
- const X509Certificate::OSCertHandle cert_handle,
- const SetCallback& cb) {
- DCHECK(!cb.is_null());
- DCHECK(cert_handle);
- std::string key = GetCacheKeyForCert(cert_handle);
-
- WriteWorkerMap::iterator it = write_worker_map_.find(key);
-
- if (it == write_worker_map_.end()) {
- WriteWorker* worker =
- new WriteWorker(backend_,
- key,
- cert_handle,
- base::Bind(&DiskBasedCertCache::FinishedWriteOperation,
- weak_factory_.GetWeakPtr(),
- key,
- cert_handle));
- write_worker_map_[key] = worker;
- worker->AddCallback(cb);
- worker->Start();
- } else {
- it->second->AddCallback(cb);
- }
-}
-
-void DiskBasedCertCache::FinishedReadOperation(
- const std::string& key,
- X509Certificate::OSCertHandle cert_handle) {
- if (cert_handle)
- mru_cert_cache_.Put(key, X509Certificate::DupOSCertHandle(cert_handle));
- read_worker_map_.erase(key);
-}
-
-void DiskBasedCertCache::FinishedWriteOperation(
- const std::string& key,
- X509Certificate::OSCertHandle cert_handle) {
- write_worker_map_.erase(key);
- if (!key.empty())
- mru_cert_cache_.Put(key, X509Certificate::DupOSCertHandle(cert_handle));
-}
-
-} // namespace net
diff --git a/chromium/net/http/disk_based_cert_cache.h b/chromium/net/http/disk_based_cert_cache.h
deleted file mode 100644
index 7c9edec01c5..00000000000
--- a/chromium/net/http/disk_based_cert_cache.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2014 The Chromium 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_DISK_BASED_CERT_CACHE_H
-#define NET_HTTP_DISK_BASED_CERT_CACHE_H
-
-#include <stddef.h>
-
-#include <string>
-
-#include "base/callback.h"
-#include "base/containers/hash_tables.h"
-#include "base/containers/mru_cache.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "net/base/net_export.h"
-#include "net/cert/x509_certificate.h"
-
-namespace disk_cache {
-class Backend;
-} // namespace disk_cache
-
-namespace net {
-
-// DiskBasedCertCache is used to store and retrieve X.509 certificates from the
-// cache. Each individual certificate is stored separately from its certificate
-// chain. No more than one copy (per certificate) will be stored on disk.
-class NET_EXPORT_PRIVATE DiskBasedCertCache {
- public:
- typedef base::Callback<void(const X509Certificate::OSCertHandle cert_handle)>
- GetCallback;
- typedef base::Callback<void(const std::string&)> SetCallback;
-
- // Initializes a new DiskBasedCertCache that will access the disk cache via
- // |backend|.
- explicit DiskBasedCertCache(disk_cache::Backend* backend);
- ~DiskBasedCertCache();
-
- // Fetches the certificate associated with |key|. If the certificate is
- // found within the cache, |cb| will be called with the certificate.
- // Otherwise, |cb| will be called with NULL. Callers that wish to store
- // a reference to the certificate need to use X509Certificate::DupOSCertHandle
- // inside |cb|.
- void GetCertificate(const std::string& key, const GetCallback& cb);
-
- // Stores |cert_handle| in the cache. If |cert_handle| is successfully stored,
- // |cb| will be called with the key. If |cb| is called with an empty
- // string, then |cert_handle| was not stored.
- void SetCertificate(const X509Certificate::OSCertHandle cert_handle,
- const SetCallback& cb);
-
- // Returns the number of in-memory MRU cache hits that have occurred
- // on SetCertificate and GetCertificate operations. Intended for test purposes
- // only.
- size_t mem_cache_hits_for_testing() const { return mem_cache_hits_; }
-
- // Returns the number of in-memory MRU cache misses that have occurred
- // on SetCertificate and GetCertificate operations. Intended for test purposes
- // only.
- size_t mem_cache_misses_for_testing() const { return mem_cache_misses_; }
-
- private:
- class ReadWorker;
- class WriteWorker;
-
- // A functor used to free an OSCertHandle. Used by the MRUCertCache.
- struct CertFree {
- void operator()(X509Certificate::OSCertHandle cert_handle);
- };
-
- // An in-memory cache that is used to prevent redundantly reading
- // from disk.
- typedef base::MRUCacheBase<std::string,
- X509Certificate::OSCertHandle,
- CertFree> MRUCertCache;
-
- // ReadWorkerMap and WriteWorkerMap map cache keys to their
- // corresponding Workers.
- typedef base::hash_map<std::string, ReadWorker*> ReadWorkerMap;
- typedef base::hash_map<std::string, WriteWorker*> WriteWorkerMap;
-
- // FinishedReadOperation and FinishedWriteOperation are used to remove
- // workers from their respective worker maps, and perform other necessary
- // cleanup. They are called from the workers via callback.
- void FinishedReadOperation(const std::string& key,
- X509Certificate::OSCertHandle cert_handle);
- void FinishedWriteOperation(const std::string& key,
- X509Certificate::OSCertHandle cert_handle);
-
- disk_cache::Backend* backend_;
-
- ReadWorkerMap read_worker_map_;
- WriteWorkerMap write_worker_map_;
- MRUCertCache mru_cert_cache_;
-
- int mem_cache_hits_;
- int mem_cache_misses_;
-
- base::WeakPtrFactory<DiskBasedCertCache> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(DiskBasedCertCache);
-};
-
-} // namespace net
-
-#endif // NET_HTTP_DISK_BASED_CERT_CACHE_H
diff --git a/chromium/net/http/disk_based_cert_cache_unittest.cc b/chromium/net/http/disk_based_cert_cache_unittest.cc
deleted file mode 100644
index b2b640b300e..00000000000
--- a/chromium/net/http/disk_based_cert_cache_unittest.cc
+++ /dev/null
@@ -1,535 +0,0 @@
-// Copyright (c) 2014 The Chromium 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/disk_based_cert_cache.h"
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "net/base/completion_callback.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
-#include "net/base/test_data_directory.h"
-#include "net/disk_cache/memory/mem_backend_impl.h"
-#include "net/http/mock_http_cache.h"
-#include "net/test/cert_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-
-namespace {
-
-// Testing the DiskBasedCertCache requires constant use of the
-// certificates in GetTestCertsDirectory(). The TestCertMetaData
-// struct stores metadata relevant to the DiskBasedCertCache for
-// each used test certificate.
-struct TestCertMetaData {
- const char* file_name;
- const char* cache_key;
-};
-
-const TestCertMetaData kCert1 = {
- "root_ca_cert.pem", "cert:738D348A8AFCEC4F79C3E4B1845D985AF601AB0F"};
-
-const TestCertMetaData kCert2 = {
- "ok_cert.pem", "cert:6C9DFD2CFA9885C71BE6DE0EA0CF962AC8F9131B"};
-
-// MockTransactions are required to use the MockDiskCache backend.
-// |key| is a cache key, and is equivalent to the key that will be
-// used to store or retrieve certificates in the cache. |test_mode|
-// is an integer that is used to indicate properties of the test
-// transaction, mostly whether or not it is synchronous.
-// For testing the DiskBasedCertCache, other data members of the struct
-// are irrelevant. Only one MockTransaction per certificate can be used
-// at a time.
-MockTransaction CreateMockTransaction(const char* key, int test_mode) {
- MockTransaction transaction = {key, "", base::Time(), "", LOAD_NORMAL,
- "", "", base::Time(), "", test_mode,
- NULL, 0, OK};
-
- return transaction;
-}
-
-// Helper class, for use with DiskBasedCertCache::GetCertificate, that will
-// store the returned certificate handle and allow users to WaitForResult of
-// DiskBasedCertCache::GetCertificate.
-class TestGetCallback {
- public:
- TestGetCallback() : cert_handle_(NULL) {}
- ~TestGetCallback() {
- if (cert_handle_)
- X509Certificate::FreeOSCertHandle(cert_handle_);
- }
-
- // Blocks until the underlying GetCertificate() operation has succeeded.
- void WaitForResult() { cb_.WaitForResult(); }
-
- // Returns a Callback suitable for use with
- // DiskBasedCertCache::GetCertificate(). The returned callback is only valid
- // while the TestGetCallback object is still valid.
- DiskBasedCertCache::GetCallback callback() {
- return base::Bind(&TestGetCallback::OnGetComplete, base::Unretained(this));
- }
-
- // Returns the associated certificate handle.
- const X509Certificate::OSCertHandle& cert_handle() const {
- return cert_handle_;
- }
-
- private:
- void OnGetComplete(const X509Certificate::OSCertHandle handle) {
- if (handle)
- cert_handle_ = X509Certificate::DupOSCertHandle(handle);
- cb_.callback().Run(OK);
- }
-
- TestCompletionCallback cb_;
- X509Certificate::OSCertHandle cert_handle_;
-};
-
-// Helper class, for use with DiskBasedCertCache::SetCertificate, that will
-// store the returned key and allow a user to WaitForResult of
-// DiskBasedCertCache::SetCertificate.
-class TestSetCallback {
- public:
- TestSetCallback() {}
- ~TestSetCallback() {}
-
- // Blocks until the underlying SetCertificate() operation has succeeded.
- void WaitForResult() { cb_.WaitForResult(); }
-
- // Returns a Callback suitable for use with
- // DiskBasedCertCache::SetCertificate(). The returned callback is only valid
- // while the TestSetCallback object is still valid.
- DiskBasedCertCache::SetCallback callback() {
- return base::Bind(&TestSetCallback::OnSetComplete, base::Unretained(this));
- }
-
- // Returns the associated certificate handle.
- const std::string& key() const { return key_; }
-
- private:
- void OnSetComplete(const std::string& key) {
- key_ = key;
- cb_.callback().Run(OK);
- }
-
- TestCompletionCallback cb_;
- std::string key_;
-};
-
-// Stores the certificate corresponding to |cert_data| in |backend|. If
-// |corrupt_data| is true, the certificate will be imported with errors
-// so as to mimic a corrupted file on disk.
-void ImportCert(disk_cache::Backend* backend,
- const TestCertMetaData& cert_data,
- bool corrupt_data) {
- disk_cache::Entry* entry;
- TestCompletionCallback callback;
- int rv =
- backend->CreateEntry(cert_data.cache_key, &entry, callback.callback());
- EXPECT_EQ(OK, callback.GetResult(rv));
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), cert_data.file_name));
- std::string write_data;
- bool encoded =
- X509Certificate::GetDEREncoded(cert->os_cert_handle(), &write_data);
- ASSERT_TRUE(encoded);
- if (corrupt_data) {
- for (size_t i = 0; i < write_data.size(); i += 20)
- ++write_data[i];
- }
- scoped_refptr<IOBuffer> buffer(new IOBuffer(write_data.size()));
- memcpy(buffer->data(), write_data.data(), write_data.size());
- rv = entry->WriteData(0 /* index */,
- 0 /* offset */,
- buffer.get(),
- write_data.size(),
- callback.callback(),
- true /* truncate */);
- ASSERT_EQ(static_cast<int>(write_data.size()), callback.GetResult(rv));
- entry->Close();
-}
-
-// Checks that the the certificate corresponding to |cert_data| is an existing,
-// correctly cached entry in |backend|.
-void CheckCertCached(disk_cache::Backend* backend,
- const TestCertMetaData& cert_data) {
- disk_cache::Entry* entry;
- TestCompletionCallback callback;
- int rv = backend->OpenEntry(cert_data.cache_key, &entry, callback.callback());
- EXPECT_EQ(OK, callback.GetResult(rv));
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), cert_data.file_name));
- std::string write_data;
- bool encoded =
- X509Certificate::GetDEREncoded(cert->os_cert_handle(), &write_data);
- ASSERT_TRUE(encoded);
- int entry_size = entry->GetDataSize(0 /* index */);
- scoped_refptr<IOBuffer> buffer(new IOBuffer(entry_size));
- rv = entry->ReadData(0 /* index */,
- 0 /* offset */,
- buffer.get(),
- entry_size,
- callback.callback());
- EXPECT_EQ(entry_size, callback.GetResult(rv));
- entry->Close();
- X509Certificate::OSCertHandle cached_cert_handle =
- X509Certificate::CreateOSCertHandleFromBytes(buffer->data(), entry_size);
- EXPECT_TRUE(X509Certificate::IsSameOSCert(cached_cert_handle,
- cert->os_cert_handle()));
- X509Certificate::FreeOSCertHandle(cached_cert_handle);
-}
-
-} // namespace
-
-// ----------------------------------------------------------------------------
-
-// Tests that a certificate can be stored in the cache.
-TEST(DiskBasedCertCache, SetCert) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
- MockDiskCache backend;
- DiskBasedCertCache cache(&backend);
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
- ASSERT_TRUE(cert.get());
- TestSetCallback set_callback;
-
- cache.SetCertificate(cert->os_cert_handle(), set_callback.callback());
- set_callback.WaitForResult();
- EXPECT_EQ(kCert1.cache_key, set_callback.key());
- ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1));
-}
-
-// Tests that a certificate can be retrieved from the cache.
-TEST(DiskBasedCertCache, GetCert) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
- MockDiskCache backend;
- ASSERT_NO_FATAL_FAILURE(
- ImportCert(&backend, kCert1, false /* not corrupted */));
- DiskBasedCertCache cache(&backend);
- TestGetCallback get_callback;
-
- cache.GetCertificate(kCert1.cache_key, get_callback.callback());
- get_callback.WaitForResult();
-
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
- EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback.cert_handle(),
- cert->os_cert_handle()));
-}
-
-// Tests that the DiskBasedCertCache successfully writes to the cache
-// if the cache acts synchronously
-TEST(DiskBasedCertCache, SyncSet) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_ALL));
- MockDiskCache backend;
- DiskBasedCertCache cache(&backend);
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
- ASSERT_TRUE(cert.get());
-
- TestSetCallback set_callback;
- cache.SetCertificate(cert->os_cert_handle(), set_callback.callback());
- set_callback.WaitForResult();
- EXPECT_EQ(kCert1.cache_key, set_callback.key());
- ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1));
-}
-
-// Tests that the DiskBasedCertCache successfully reads from the cache
-// if the cache acts synchronously
-TEST(DiskBasedCertCache, SyncGet) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_ALL));
- MockDiskCache backend;
- ASSERT_NO_FATAL_FAILURE(
- (ImportCert(&backend, kCert1, false /* not corrupted */)));
- DiskBasedCertCache cache(&backend);
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
- ASSERT_TRUE(cert.get());
-
- TestGetCallback get_callback;
- cache.GetCertificate(kCert1.cache_key, get_callback.callback());
- get_callback.WaitForResult();
- EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback.cert_handle(),
- cert->os_cert_handle()));
-}
-
-// Tests that GetCertificate will fail on a corrupted certificate.
-TEST(DiskBasedCertCache, GetBrokenCert) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
- MockDiskCache backend;
- ASSERT_NO_FATAL_FAILURE(ImportCert(&backend, kCert1, true /* corrupted */));
- DiskBasedCertCache cache(&backend);
- TestGetCallback get_callback;
-
- cache.GetCertificate(kCert1.cache_key, get_callback.callback());
- get_callback.WaitForResult();
-
- EXPECT_FALSE(get_callback.cert_handle());
-}
-
-// Tests that attempting to retrieve a cert that is not in the cache will
-// return NULL.
-TEST(DiskBasedCertCache, GetUncachedCert) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
- MockDiskCache backend;
- DiskBasedCertCache cache(&backend);
- TestGetCallback get_callback;
-
- cache.GetCertificate(kCert1.cache_key, get_callback.callback());
- get_callback.WaitForResult();
- EXPECT_EQ(NULL, get_callback.cert_handle());
-}
-
-// Issues two requests to store a certificate in the cache
-// (simultaneously), and checks that the DiskBasedCertCache stores the
-// certificate to the cache (in one write rather than two).
-TEST(DiskBasedCertCache, SetMultiple) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
- MockDiskCache backend;
- DiskBasedCertCache cache(&backend);
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
- ASSERT_TRUE(cert.get());
- TestSetCallback set_callback1, set_callback2;
-
- // Behind the scenes, these two operations will be combined
- // into one operation. IgnoreCallbacks guarantees that the
- // first SetCertificate operation is not yet complete when the second
- // SetCertificate is called, and then IgnoreCallbacks(false) continues the
- // (combined) operation in the |cache|.
- MockDiskEntry::IgnoreCallbacks(true);
- cache.SetCertificate(cert->os_cert_handle(), set_callback1.callback());
- cache.SetCertificate(cert->os_cert_handle(), set_callback2.callback());
- MockDiskEntry::IgnoreCallbacks(false);
-
- set_callback1.WaitForResult();
- set_callback2.WaitForResult();
- EXPECT_EQ(set_callback1.key(), set_callback2.key());
- ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1));
-}
-
-// Issues two requests to store a certificate in the cache
-// because the first transaction finishes before the second
-// one is issued, the first cache write is overwritten.
-TEST(DiskBasedCertCache, SetOverwrite) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
- MockDiskCache backend;
- backend.set_double_create_check(false);
- DiskBasedCertCache cache(&backend);
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
- ASSERT_TRUE(cert.get());
- TestSetCallback set_callback1, set_callback2;
-
- cache.SetCertificate(cert->os_cert_handle(), set_callback1.callback());
- set_callback1.WaitForResult();
- cache.SetCertificate(cert->os_cert_handle(), set_callback2.callback());
- set_callback2.WaitForResult();
-
- EXPECT_EQ(set_callback1.key(), set_callback2.key());
- ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1));
-}
-
-// Stores a certificate in the DiskBasedCertCache, then retrieves it
-// and makes sure it was retrieved successfully.
-TEST(DiskBasedCertCache, SimpleSetAndGet) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
- MockDiskCache backend;
- DiskBasedCertCache cache(&backend);
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
- ASSERT_TRUE(cert.get());
- TestSetCallback set_callback;
- TestGetCallback get_callback;
-
- cache.SetCertificate(cert->os_cert_handle(), set_callback.callback());
- set_callback.WaitForResult();
- cache.GetCertificate(set_callback.key(), get_callback.callback());
- get_callback.WaitForResult();
- EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback.cert_handle(),
- cert->os_cert_handle()));
-}
-
-// Tests some basic functionality of the DiskBasedCertCache, with multiple
-// set and get operations.
-TEST(DiskBasedCertCache, BasicUsage) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_CACHE_START));
- ScopedMockTransaction trans2(
- CreateMockTransaction(kCert2.cache_key, TEST_MODE_NORMAL));
- MockDiskCache backend;
- DiskBasedCertCache cache(&backend);
- scoped_refptr<X509Certificate> cert1(
- ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
- scoped_refptr<X509Certificate> cert2(
- ImportCertFromFile(GetTestCertsDirectory(), kCert2.file_name));
- ASSERT_TRUE(cert1.get());
- ASSERT_TRUE(cert2.get());
- ASSERT_FALSE(X509Certificate::IsSameOSCert(cert1->os_cert_handle(),
- cert2->os_cert_handle()));
- TestSetCallback set_callback1, set_callback2;
-
- // Callbacks are temporarily ignored here to guarantee the asynchronous
- // operations of the DiskBasedCertCache are always executed in the same
- // order.
- MockDiskEntry::IgnoreCallbacks(true);
- cache.SetCertificate(cert1->os_cert_handle(), set_callback1.callback());
- cache.SetCertificate(cert2->os_cert_handle(), set_callback2.callback());
- MockDiskEntry::IgnoreCallbacks(false);
- set_callback1.WaitForResult();
- set_callback2.WaitForResult();
-
- TestGetCallback get_callback1, get_callback2;
-
- MockDiskEntry::IgnoreCallbacks(true);
- cache.GetCertificate(set_callback1.key(), get_callback1.callback());
- cache.GetCertificate(set_callback2.key(), get_callback2.callback());
- MockDiskEntry::IgnoreCallbacks(false);
- get_callback1.WaitForResult();
- get_callback2.WaitForResult();
-
- EXPECT_TRUE(X509Certificate::IsSameOSCert(cert1->os_cert_handle(),
- get_callback1.cert_handle()));
- EXPECT_TRUE(X509Certificate::IsSameOSCert(cert2->os_cert_handle(),
- get_callback2.cert_handle()));
-}
-
-// Test the result of simultaneous requests to store and retrieve a
-// certificate from the cache, with the get operation attempting to
-// open the cache first and therefore failing to open the entry.
-TEST(DiskBasedCertCache, SimultaneousGetSet) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_CACHE_START));
- MockDiskCache backend;
- DiskBasedCertCache cache(&backend);
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
- ASSERT_TRUE(cert.get());
-
- TestGetCallback get_callback;
- TestSetCallback set_callback;
-
- MockDiskEntry::IgnoreCallbacks(true);
- cache.GetCertificate(kCert1.cache_key, get_callback.callback());
- cache.SetCertificate(cert->os_cert_handle(), set_callback.callback());
- MockDiskEntry::IgnoreCallbacks(false);
- get_callback.WaitForResult();
- set_callback.WaitForResult();
-
- EXPECT_EQ(NULL, get_callback.cert_handle());
- EXPECT_EQ(kCert1.cache_key, set_callback.key());
-}
-
-// Test the result of simultaneous requests to store and retrieve a
-// certificate from the cache, with the get operation opening the cache
-// after the set operation, leading to a successful read.
-TEST(DiskBasedCertCache, SimultaneousSetGet) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_CACHE_START));
- MockDiskCache backend;
- DiskBasedCertCache cache(&backend);
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
- ASSERT_TRUE(cert.get());
-
- TestSetCallback set_callback;
- TestGetCallback get_callback;
-
- MockDiskEntry::IgnoreCallbacks(true);
- cache.SetCertificate(cert->os_cert_handle(), set_callback.callback());
- cache.GetCertificate(kCert1.cache_key, get_callback.callback());
- MockDiskEntry::IgnoreCallbacks(false);
- set_callback.WaitForResult();
- get_callback.WaitForResult();
-
- EXPECT_EQ(kCert1.cache_key, set_callback.key());
- EXPECT_TRUE(X509Certificate::IsSameOSCert(cert->os_cert_handle(),
- get_callback.cert_handle()));
-}
-
-// Tests that the DiskBasedCertCache can be deleted without issues when
-// there are pending operations in the disk cache.
-TEST(DiskBasedCertCache, DeletedCertCache) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
- MockDiskCache backend;
- scoped_ptr<DiskBasedCertCache> cache(new DiskBasedCertCache(&backend));
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
- ASSERT_TRUE(cert.get());
- TestSetCallback set_callback;
-
- cache->SetCertificate(cert->os_cert_handle(), set_callback.callback());
- cache.reset();
- set_callback.WaitForResult();
- EXPECT_EQ(std::string(), set_callback.key());
-}
-
-// Issues two successive read requests for a certificate, and then
-// checks that the DiskBasedCertCache correctly read and recorded
-// reading through the in-memory MRU cache.
-TEST(DiskBasedCertCache, MemCacheGet) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
- MockDiskCache backend;
- ASSERT_NO_FATAL_FAILURE(
- ImportCert(&backend, kCert1, false /* not corrupted */));
- DiskBasedCertCache cache(&backend);
-
- TestGetCallback get_callback1, get_callback2;
- cache.GetCertificate(kCert1.cache_key, get_callback1.callback());
- get_callback1.WaitForResult();
- EXPECT_EQ(0U, cache.mem_cache_hits_for_testing());
- cache.GetCertificate(kCert1.cache_key, get_callback2.callback());
- get_callback2.WaitForResult();
- EXPECT_EQ(1U, cache.mem_cache_hits_for_testing());
- EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback1.cert_handle(),
- get_callback2.cert_handle()));
-}
-
-// Reads a corrupted certificate from the disk cache, and then overwrites
-// it and checks that the uncorrupted version was stored in the in-memory
-// cache.
-TEST(DiskBasedCertCache, CorruptOverwrite) {
- ScopedMockTransaction trans1(
- CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
- MockDiskCache backend;
- backend.set_double_create_check(false);
- ASSERT_NO_FATAL_FAILURE(ImportCert(&backend, kCert1, true /* corrupted */));
- DiskBasedCertCache cache(&backend);
- TestGetCallback get_callback1, get_callback2;
-
- cache.GetCertificate(kCert1.cache_key, get_callback1.callback());
- get_callback1.WaitForResult();
- EXPECT_FALSE(get_callback2.cert_handle());
-
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
- TestSetCallback set_callback;
-
- cache.SetCertificate(cert->os_cert_handle(), set_callback.callback());
- set_callback.WaitForResult();
- EXPECT_EQ(kCert1.cache_key, set_callback.key());
- EXPECT_EQ(0U, cache.mem_cache_hits_for_testing());
-
- cache.GetCertificate(kCert1.cache_key, get_callback2.callback());
- get_callback2.WaitForResult();
- EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback2.cert_handle(),
- cert->os_cert_handle()));
- EXPECT_EQ(1U, cache.mem_cache_hits_for_testing());
- ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1));
-}
-
-} // 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 6f6425ea175..490b935811d 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
@@ -116,12 +116,16 @@ TEST(DiskCacheBasedQuicServerInfo, Update) {
EXPECT_TRUE(state->certs.empty());
const string server_config_a = "server_config_a";
const string source_address_token_a = "source_address_token_a";
+ const string cert_sct_a = "cert_sct_a";
+ const string chlo_hash_a = "chlo_hash_a";
const string server_config_sig_a = "server_config_sig_a";
const string cert_a = "cert_a";
const string cert_b = "cert_b";
state->server_config = server_config_a;
state->source_address_token = source_address_token_a;
+ state->cert_sct = cert_sct_a;
+ state->chlo_hash = chlo_hash_a;
state->server_config_sig = server_config_sig_a;
state->certs.push_back(cert_a);
quic_server_info->Persist();
@@ -156,6 +160,8 @@ TEST(DiskCacheBasedQuicServerInfo, Update) {
const QuicServerInfo::State& state1 = quic_server_info->state();
EXPECT_EQ(server_config_a, state1.server_config);
EXPECT_EQ(source_address_token_a, state1.source_address_token);
+ EXPECT_EQ(cert_sct_a, state1.cert_sct);
+ EXPECT_EQ(chlo_hash_a, state1.chlo_hash);
EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
EXPECT_EQ(2U, state1.certs.size());
EXPECT_EQ(cert_a, state1.certs[0]);
@@ -183,11 +189,15 @@ TEST(DiskCacheBasedQuicServerInfo, UpdateDifferentPorts) {
EXPECT_TRUE(state1->certs.empty());
const string server_config_a = "server_config_a";
const string source_address_token_a = "source_address_token_a";
+ const string cert_sct_a = "cert_sct_a";
+ const string chlo_hash_a = "chlo_hash_a";
const string server_config_sig_a = "server_config_sig_a";
const string cert_a = "cert_a";
state1->server_config = server_config_a;
state1->source_address_token = source_address_token_a;
+ state1->cert_sct = cert_sct_a;
+ state1->chlo_hash = chlo_hash_a;
state1->server_config_sig = server_config_sig_a;
state1->certs.push_back(cert_a);
quic_server_info1->Persist();
@@ -207,11 +217,15 @@ TEST(DiskCacheBasedQuicServerInfo, UpdateDifferentPorts) {
EXPECT_TRUE(state2->certs.empty());
const string server_config_b = "server_config_b";
const string source_address_token_b = "source_address_token_b";
+ const string cert_sct_b = "cert_sct_b";
+ const string chlo_hash_b = "chlo_hash_b";
const string server_config_sig_b = "server_config_sig_b";
const string cert_b = "cert_b";
state2->server_config = server_config_b;
state2->source_address_token = source_address_token_b;
+ state2->cert_sct = cert_sct_b;
+ state2->chlo_hash = chlo_hash_b;
state2->server_config_sig = server_config_sig_b;
state2->certs.push_back(cert_b);
quic_server_info2->Persist();
@@ -230,6 +244,8 @@ TEST(DiskCacheBasedQuicServerInfo, UpdateDifferentPorts) {
const QuicServerInfo::State& state_a = quic_server_info->state();
EXPECT_EQ(server_config_a, state_a.server_config);
EXPECT_EQ(source_address_token_a, state_a.source_address_token);
+ EXPECT_EQ(cert_sct_a, state_a.cert_sct);
+ EXPECT_EQ(chlo_hash_a, state_a.chlo_hash);
EXPECT_EQ(server_config_sig_a, state_a.server_config_sig);
EXPECT_EQ(1U, state_a.certs.size());
EXPECT_EQ(cert_a, state_a.certs[0]);
@@ -245,6 +261,8 @@ TEST(DiskCacheBasedQuicServerInfo, UpdateDifferentPorts) {
const QuicServerInfo::State& state_b = quic_server_info->state();
EXPECT_EQ(server_config_b, state_b.server_config);
EXPECT_EQ(source_address_token_b, state_b.source_address_token);
+ EXPECT_EQ(cert_sct_b, state_b.cert_sct);
+ EXPECT_EQ(chlo_hash_b, state_b.chlo_hash);
EXPECT_EQ(server_config_sig_b, state_b.server_config_sig);
EXPECT_EQ(1U, state_b.certs.size());
EXPECT_EQ(cert_b, state_b.certs[0]);
@@ -272,11 +290,15 @@ TEST(DiskCacheBasedQuicServerInfo, IsReadyToPersist) {
EXPECT_TRUE(state->certs.empty());
const string server_config_a = "server_config_a";
const string source_address_token_a = "source_address_token_a";
+ const string cert_sct_a = "cert_sct_a";
+ const string chlo_hash_a = "chlo_hash_a";
const string server_config_sig_a = "server_config_sig_a";
const string cert_a = "cert_a";
state->server_config = server_config_a;
state->source_address_token = source_address_token_a;
+ state->cert_sct = cert_sct_a;
+ state->chlo_hash = chlo_hash_a;
state->server_config_sig = server_config_sig_a;
state->certs.push_back(cert_a);
EXPECT_TRUE(quic_server_info->IsReadyToPersist());
@@ -302,6 +324,8 @@ TEST(DiskCacheBasedQuicServerInfo, IsReadyToPersist) {
const QuicServerInfo::State& state1 = quic_server_info->state();
EXPECT_EQ(server_config_a, state1.server_config);
EXPECT_EQ(source_address_token_a, state1.source_address_token);
+ EXPECT_EQ(cert_sct_a, state1.cert_sct);
+ EXPECT_EQ(chlo_hash_a, state1.chlo_hash);
EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
EXPECT_EQ(1U, state1.certs.size());
EXPECT_EQ(cert_a, state1.certs[0]);
@@ -329,11 +353,15 @@ TEST(DiskCacheBasedQuicServerInfo, MultiplePersist) {
EXPECT_TRUE(state->certs.empty());
const string server_config_init = "server_config_init";
const string source_address_token_init = "source_address_token_init";
+ const string cert_sct_init = "cert_sct_init";
+ const string chlo_hash_init = "chlo_hash_init";
const string server_config_sig_init = "server_config_sig_init";
const string cert_init = "cert_init";
state->server_config = server_config_init;
state->source_address_token = source_address_token_init;
+ state->cert_sct = cert_sct_init;
+ state->chlo_hash = chlo_hash_init;
state->server_config_sig = server_config_sig_init;
state->certs.push_back(cert_init);
EXPECT_TRUE(quic_server_info->IsReadyToPersist());
@@ -352,11 +380,15 @@ TEST(DiskCacheBasedQuicServerInfo, MultiplePersist) {
// doing another Start() and WaitForDataReady.
const string server_config_a = "server_config_a";
const string source_address_token_a = "source_address_token_a";
+ const string cert_sct_a = "cert_sct_a";
+ const string chlo_hash_a = "chlo_hash_a";
const string server_config_sig_a = "server_config_sig_a";
const string cert_a = "cert_a";
state->server_config = server_config_a;
state->source_address_token = source_address_token_a;
+ state->cert_sct = cert_sct_a;
+ state->chlo_hash = chlo_hash_a;
state->server_config_sig = server_config_sig_a;
state->certs.push_back(cert_a);
EXPECT_TRUE(quic_server_info->IsReadyToPersist());
@@ -382,6 +414,8 @@ TEST(DiskCacheBasedQuicServerInfo, MultiplePersist) {
const QuicServerInfo::State& state1 = quic_server_info->state();
EXPECT_EQ(server_config_a, state1.server_config);
EXPECT_EQ(source_address_token_a, state1.source_address_token);
+ EXPECT_EQ(cert_sct_a, state1.cert_sct);
+ EXPECT_EQ(chlo_hash_a, state1.chlo_hash);
EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
EXPECT_EQ(1U, state1.certs.size());
EXPECT_EQ(cert_a, state1.certs[0]);
@@ -466,11 +500,15 @@ TEST(DiskCacheBasedQuicServerInfo, StartAndPersist) {
EXPECT_TRUE(state->certs.empty());
const string server_config_a = "server_config_a";
const string source_address_token_a = "source_address_token_a";
+ const string cert_sct_a = "cert_sct_a";
+ const string chlo_hash_a = "chlo_hash_a";
const string server_config_sig_a = "server_config_sig_a";
const string cert_a = "cert_a";
state->server_config = server_config_a;
state->source_address_token = source_address_token_a;
+ state->cert_sct = cert_sct_a;
+ state->chlo_hash = chlo_hash_a;
state->server_config_sig = server_config_sig_a;
state->certs.push_back(cert_a);
EXPECT_TRUE(quic_server_info->IsReadyToPersist());
@@ -498,6 +536,8 @@ TEST(DiskCacheBasedQuicServerInfo, StartAndPersist) {
const QuicServerInfo::State& state1 = quic_server_info->state();
EXPECT_EQ(server_config_a, state1.server_config);
EXPECT_EQ(source_address_token_a, state1.source_address_token);
+ EXPECT_EQ(cert_sct_a, state1.cert_sct);
+ EXPECT_EQ(chlo_hash_a, state1.chlo_hash);
EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
EXPECT_EQ(1U, state1.certs.size());
EXPECT_EQ(cert_a, state1.certs[0]);
@@ -527,11 +567,15 @@ TEST(DiskCacheBasedQuicServerInfo, PersistWhenNotReadyToPersist) {
EXPECT_TRUE(state->certs.empty());
const string server_config_init = "server_config_init";
const string source_address_token_init = "source_address_token_init";
+ const string cert_sct_init = "cert_sct_init";
+ const string chlo_hash_init = "chlo_hash_init";
const string server_config_sig_init = "server_config_sig_init";
const string cert_init = "cert_init";
state->server_config = server_config_init;
state->source_address_token = source_address_token_init;
+ state->cert_sct = cert_sct_init;
+ state->chlo_hash = chlo_hash_init;
state->server_config_sig = server_config_sig_init;
state->certs.push_back(cert_init);
EXPECT_FALSE(quic_server_info->IsReadyToPersist());
@@ -556,6 +600,8 @@ TEST(DiskCacheBasedQuicServerInfo, PersistWhenNotReadyToPersist) {
const QuicServerInfo::State& state1 = quic_server_info->state();
EXPECT_EQ(server_config_init, state1.server_config);
EXPECT_EQ(source_address_token_init, state1.source_address_token);
+ EXPECT_EQ(cert_sct_init, state1.cert_sct);
+ EXPECT_EQ(chlo_hash_init, state1.chlo_hash);
EXPECT_EQ(server_config_sig_init, state1.server_config_sig);
EXPECT_EQ(1U, state1.certs.size());
EXPECT_EQ(cert_init, state1.certs[0]);
@@ -582,11 +628,15 @@ TEST(DiskCacheBasedQuicServerInfo, MultiplePersistsWithoutWaiting) {
EXPECT_TRUE(state->certs.empty());
const string server_config_init = "server_config_init";
const string source_address_token_init = "source_address_token_init";
+ const string cert_sct_init = "cert_sct_init";
+ const string chlo_hash_init = "chlo_hash_init";
const string server_config_sig_init = "server_config_sig_init";
const string cert_init = "cert_init";
state->server_config = server_config_init;
state->source_address_token = source_address_token_init;
+ state->cert_sct = cert_sct_init;
+ state->chlo_hash = chlo_hash_init;
state->server_config_sig = server_config_sig_init;
state->certs.push_back(cert_init);
EXPECT_TRUE(quic_server_info->IsReadyToPersist());
@@ -600,11 +650,15 @@ TEST(DiskCacheBasedQuicServerInfo, MultiplePersistsWithoutWaiting) {
// doing another Start() and WaitForDataReady.
const string server_config_a = "server_config_a";
const string source_address_token_a = "source_address_token_a";
+ const string cert_sct_a = "cert_sct_a";
+ const string chlo_hash_a = "chlo_hash_a";
const string server_config_sig_a = "server_config_sig_a";
const string cert_a = "cert_a";
state->server_config = server_config_a;
state->source_address_token = source_address_token_a;
+ state->cert_sct = cert_sct_a;
+ state->chlo_hash = chlo_hash_a;
state->server_config_sig = server_config_sig_a;
state->certs.push_back(cert_a);
EXPECT_FALSE(quic_server_info->IsReadyToPersist());
@@ -627,6 +681,8 @@ TEST(DiskCacheBasedQuicServerInfo, MultiplePersistsWithoutWaiting) {
const QuicServerInfo::State& state1 = quic_server_info->state();
EXPECT_EQ(server_config_a, state1.server_config);
EXPECT_EQ(source_address_token_a, state1.source_address_token);
+ EXPECT_EQ(cert_sct_a, state1.cert_sct);
+ EXPECT_EQ(chlo_hash_a, state1.chlo_hash);
EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
EXPECT_EQ(1U, state1.certs.size());
EXPECT_EQ(cert_a, state1.certs[0]);
diff --git a/chromium/net/http/http_auth.cc b/chromium/net/http/http_auth.cc
index 15768a05fd4..570d8f7f5a9 100644
--- a/chromium/net/http/http_auth.cc
+++ b/chromium/net/http/http_auth.cc
@@ -24,7 +24,8 @@ HttpAuth::Identity::Identity() : source(IDENT_SRC_NONE), invalid(true) {}
// static
void HttpAuth::ChooseBestChallenge(
HttpAuthHandlerFactory* http_auth_handler_factory,
- const HttpResponseHeaders* headers,
+ const HttpResponseHeaders& response_headers,
+ const SSLInfo& ssl_info,
Target target,
const GURL& origin,
const std::set<Scheme>& disabled_schemes,
@@ -37,11 +38,11 @@ void HttpAuth::ChooseBestChallenge(
scoped_ptr<HttpAuthHandler> best;
const std::string header_name = GetChallengeHeaderName(target);
std::string cur_challenge;
- void* iter = NULL;
- while (headers->EnumerateHeader(&iter, header_name, &cur_challenge)) {
+ size_t iter = 0;
+ while (response_headers.EnumerateHeader(&iter, header_name, &cur_challenge)) {
scoped_ptr<HttpAuthHandler> cur;
int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
- cur_challenge, target, origin, net_log, &cur);
+ cur_challenge, target, ssl_info, origin, net_log, &cur);
if (rv != OK) {
VLOG(1) << "Unable to create AuthHandler. Status: "
<< ErrorToString(rv) << " Challenge: " << cur_challenge;
@@ -57,12 +58,11 @@ void HttpAuth::ChooseBestChallenge(
// static
HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse(
HttpAuthHandler* handler,
- const HttpResponseHeaders* headers,
+ const HttpResponseHeaders& response_headers,
Target target,
const std::set<Scheme>& disabled_schemes,
std::string* challenge_used) {
DCHECK(handler);
- DCHECK(headers);
DCHECK(challenge_used);
challenge_used->clear();
HttpAuth::Scheme current_scheme = handler->auth_scheme();
@@ -70,11 +70,11 @@ HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse(
return HttpAuth::AUTHORIZATION_RESULT_REJECT;
std::string current_scheme_name = SchemeToString(current_scheme);
const std::string header_name = GetChallengeHeaderName(target);
- void* iter = NULL;
+ size_t iter = 0;
std::string challenge;
HttpAuth::AuthorizationResult authorization_result =
HttpAuth::AUTHORIZATION_RESULT_INVALID;
- while (headers->EnumerateHeader(&iter, header_name, &challenge)) {
+ while (response_headers.EnumerateHeader(&iter, header_name, &challenge)) {
HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end());
if (!base::LowerCaseEqualsASCII(props.scheme(),
current_scheme_name.c_str()))
diff --git a/chromium/net/http/http_auth.h b/chromium/net/http/http_auth.h
index 5a2c7ac6606..f804a4d13bd 100644
--- a/chromium/net/http/http_auth.h
+++ b/chromium/net/http/http_auth.h
@@ -21,6 +21,7 @@ class BoundNetLog;
class HttpAuthHandler;
class HttpAuthHandlerFactory;
class HttpResponseHeaders;
+class SSLInfo;
// Utility class for http authentication.
class NET_EXPORT_PRIVATE HttpAuth {
@@ -122,18 +123,22 @@ class NET_EXPORT_PRIVATE HttpAuth {
// Returns a string representation of an authentication Scheme.
static const char* SchemeToString(Scheme scheme);
- // Iterate through the challenge headers, and pick the best one that
- // we support. Obtains the implementation class for handling the challenge,
- // and passes it back in |*handler|. If no supported challenge was found,
- // |*handler| is set to NULL.
+ // Iterate through |response_headers|, and pick the best one that we support.
+ // Obtains the implementation class for handling the challenge, and passes it
+ // back in |*handler|. If no supported challenge was found, |*handler| is set
+ // to NULL.
//
// |disabled_schemes| is the set of schemes that we should not use.
//
// |origin| is used by the NTLM and Negotiation authentication scheme to
- // construct the service principal name. It is ignored by other schemes.
+ // construct the service principal name. It is ignored by other schemes.
+ //
+ // |ssl_info| is passed through to the scheme specific authentication handlers
+ // to use as appropriate.
static void ChooseBestChallenge(
HttpAuthHandlerFactory* http_auth_handler_factory,
- const HttpResponseHeaders* headers,
+ const HttpResponseHeaders& response_headers,
+ const SSLInfo& ssl_info,
Target target,
const GURL& origin,
const std::set<Scheme>& disabled_schemes,
@@ -150,7 +155,7 @@ class NET_EXPORT_PRIVATE HttpAuth {
// |handler| must be non-NULL, and is the HttpAuthHandler from the previous
// authentication round.
//
- // |headers| must be non-NULL and contain the new HTTP response.
+ // |response_headers| must contain the new HTTP response.
//
// |target| specifies whether the authentication challenge response came
// from a server or a proxy.
@@ -163,7 +168,7 @@ class NET_EXPORT_PRIVATE HttpAuth {
// the value is cleared.
static AuthorizationResult HandleChallengeResponse(
HttpAuthHandler* handler,
- const HttpResponseHeaders* headers,
+ const HttpResponseHeaders& response_headers,
Target target,
const std::set<Scheme>& disabled_schemes,
std::string* challenge_used);
diff --git a/chromium/net/http/http_auth_cache.cc b/chromium/net/http/http_auth_cache.cc
index d76d3ed40cd..7a3a4e0f671 100644
--- a/chromium/net/http/http_auth_cache.cc
+++ b/chromium/net/http/http_auth_cache.cc
@@ -180,6 +180,8 @@ HttpAuthCache::Entry* HttpAuthCache::Add(const GURL& origin,
return entry;
}
+HttpAuthCache::Entry::Entry(const Entry& other) = default;
+
HttpAuthCache::Entry::~Entry() {
}
diff --git a/chromium/net/http/http_auth_cache.h b/chromium/net/http/http_auth_cache.h
index 53b998f7ffb..9190e42c508 100644
--- a/chromium/net/http/http_auth_cache.h
+++ b/chromium/net/http/http_auth_cache.h
@@ -31,6 +31,7 @@ class NET_EXPORT_PRIVATE HttpAuthCache {
public:
class NET_EXPORT_PRIVATE Entry {
public:
+ Entry(const Entry& other);
~Entry();
const GURL& origin() const {
diff --git a/chromium/net/http/http_auth_cache_unittest.cc b/chromium/net/http/http_auth_cache_unittest.cc
index 18866eaabb0..cb7d640f829 100644
--- a/chromium/net/http/http_auth_cache_unittest.cc
+++ b/chromium/net/http/http_auth_cache_unittest.cc
@@ -38,7 +38,8 @@ class MockAuthHandler : public HttpAuthHandler {
}
protected:
- bool Init(HttpAuthChallengeTokenizer* challenge) override {
+ bool Init(HttpAuthChallengeTokenizer* challenge,
+ const SSLInfo& ssl_info) override {
return false; // Unused.
}
diff --git a/chromium/net/http/http_auth_controller.cc b/chromium/net/http/http_auth_controller.cc
index 294bde0b72f..fa7d5aeb61b 100644
--- a/chromium/net/http/http_auth_controller.cc
+++ b/chromium/net/http/http_auth_controller.cc
@@ -24,35 +24,6 @@ namespace net {
namespace {
-// Returns a log message for all the response headers related to the auth
-// challenge.
-std::string AuthChallengeLogMessage(HttpResponseHeaders* headers) {
- std::string msg;
- std::string header_val;
- void* iter = NULL;
- while (headers->EnumerateHeader(&iter, "proxy-authenticate", &header_val)) {
- msg.append("\n Has header Proxy-Authenticate: ");
- msg.append(header_val);
- }
-
- iter = NULL;
- while (headers->EnumerateHeader(&iter, "www-authenticate", &header_val)) {
- msg.append("\n Has header WWW-Authenticate: ");
- msg.append(header_val);
- }
-
- // RFC 4559 requires that a proxy indicate its support of NTLM/Negotiate
- // authentication with a "Proxy-Support: Session-Based-Authentication"
- // response header.
- iter = NULL;
- while (headers->EnumerateHeader(&iter, "proxy-support", &header_val)) {
- msg.append("\n Has header Proxy-Support: ");
- msg.append(header_val);
- }
-
- return msg;
-}
-
enum AuthEvent {
AUTH_EVENT_START = 0,
AUTH_EVENT_REJECT,
@@ -247,15 +218,13 @@ void HttpAuthController::AddAuthorizationHeader(
int HttpAuthController::HandleAuthChallenge(
scoped_refptr<HttpResponseHeaders> headers,
+ const SSLInfo& ssl_info,
bool do_not_send_server_auth,
bool establishing_tunnel,
const BoundNetLog& net_log) {
DCHECK(CalledOnValidThread());
DCHECK(headers.get());
DCHECK(auth_origin_.is_valid());
- VLOG(1) << "The " << HttpAuth::GetAuthTargetString(target_) << " "
- << auth_origin_ << " requested auth "
- << AuthChallengeLogMessage(headers.get());
// Give the existing auth handler first try at the authentication headers.
// This will also evict the entry in the HttpAuthCache if the previous
@@ -263,12 +232,8 @@ int HttpAuthController::HandleAuthChallenge(
// case.
if (HaveAuth()) {
std::string challenge_used;
- HttpAuth::AuthorizationResult result =
- HttpAuth::HandleChallengeResponse(handler_.get(),
- headers.get(),
- target_,
- disabled_schemes_,
- &challenge_used);
+ HttpAuth::AuthorizationResult result = HttpAuth::HandleChallengeResponse(
+ handler_.get(), *headers, target_, disabled_schemes_, &challenge_used);
switch (result) {
case HttpAuth::AUTHORIZATION_RESULT_ACCEPT:
break;
@@ -317,24 +282,15 @@ int HttpAuthController::HandleAuthChallenge(
do {
if (!handler_.get() && can_send_auth) {
// Find the best authentication challenge that we support.
- HttpAuth::ChooseBestChallenge(http_auth_handler_factory_,
- headers.get(),
- target_,
- auth_origin_,
- disabled_schemes_,
- net_log,
- &handler_);
+ HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, *headers,
+ ssl_info, target_, auth_origin_,
+ disabled_schemes_, net_log, &handler_);
if (handler_.get())
HistogramAuthEvent(handler_.get(), AUTH_EVENT_START);
}
if (!handler_.get()) {
if (establishing_tunnel) {
- LOG(ERROR) << "Can't perform auth to the "
- << HttpAuth::GetAuthTargetString(target_) << " "
- << auth_origin_ << " when establishing a tunnel"
- << AuthChallengeLogMessage(headers.get());
-
// We are establishing a tunnel, we can't show the error page because an
// active network attacker could control its contents. Instead, we just
// fail to establish the tunnel.
diff --git a/chromium/net/http/http_auth_controller.h b/chromium/net/http/http_auth_controller.h
index b7d6e94d394..9b016f73c18 100644
--- a/chromium/net/http/http_auth_controller.h
+++ b/chromium/net/http/http_auth_controller.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -26,6 +26,7 @@ class HttpAuthHandlerFactory;
class HttpAuthCache;
class HttpRequestHeaders;
struct HttpRequestInfo;
+class SSLInfo;
class NET_EXPORT_PRIVATE HttpAuthController
: public base::RefCounted<HttpAuthController>,
@@ -55,6 +56,7 @@ class NET_EXPORT_PRIVATE HttpAuthController
// |HandleAuthChallenge()| returns OK on success, or a network error code
// otherwise. It may also populate |auth_info_|.
virtual int HandleAuthChallenge(scoped_refptr<HttpResponseHeaders> headers,
+ const SSLInfo& ssl_info,
bool do_not_send_server_auth,
bool establishing_tunnel,
const BoundNetLog& net_log);
diff --git a/chromium/net/http/http_auth_controller_unittest.cc b/chromium/net/http/http_auth_controller_unittest.cc
index cd97d293a1f..b3d1ca3c7a6 100644
--- a/chromium/net/http/http_auth_controller_unittest.cc
+++ b/chromium/net/http/http_auth_controller_unittest.cc
@@ -14,6 +14,7 @@
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/log/net_log.h"
+#include "net/ssl/ssl_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -72,8 +73,9 @@ void RunSingleRoundAuthTest(HandlerRunMode run_mode,
new HttpAuthController(HttpAuth::AUTH_PROXY,
GURL("http://example.com"),
&dummy_auth_cache, &auth_handler_factory));
- ASSERT_EQ(OK,
- controller->HandleAuthChallenge(headers, false, false, dummy_log));
+ SSLInfo null_ssl_info;
+ ASSERT_EQ(OK, controller->HandleAuthChallenge(headers, null_ssl_info, false,
+ false, dummy_log));
ASSERT_TRUE(controller->HaveAuthHandler());
controller->ResetAuth(AuthCredentials());
EXPECT_TRUE(controller->HaveAuth());
@@ -128,8 +130,9 @@ TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) {
}
protected:
- bool Init(HttpAuthChallengeTokenizer* challenge) override {
- HttpAuthHandlerMock::Init(challenge);
+ bool Init(HttpAuthChallengeTokenizer* challenge,
+ const SSLInfo& ssl_info) override {
+ HttpAuthHandlerMock::Init(challenge, ssl_info);
set_allows_default_credentials(true);
set_allows_explicit_credentials(false);
set_connection_based(true);
@@ -209,8 +212,9 @@ TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) {
new HttpAuthController(HttpAuth::AUTH_SERVER,
GURL("http://example.com"),
&dummy_auth_cache, &auth_handler_factory));
- ASSERT_EQ(OK,
- controller->HandleAuthChallenge(headers, false, false, dummy_log));
+ SSLInfo null_ssl_info;
+ ASSERT_EQ(OK, controller->HandleAuthChallenge(headers, null_ssl_info, false,
+ false, dummy_log));
ASSERT_TRUE(controller->HaveAuthHandler());
controller->ResetAuth(AuthCredentials());
EXPECT_TRUE(controller->HaveAuth());
@@ -222,8 +226,8 @@ TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) {
// Once a token is generated, simulate the receipt of a server response
// indicating that the authentication attempt was rejected.
- ASSERT_EQ(OK,
- controller->HandleAuthChallenge(headers, false, false, dummy_log));
+ ASSERT_EQ(OK, controller->HandleAuthChallenge(headers, null_ssl_info, false,
+ false, dummy_log));
ASSERT_TRUE(controller->HaveAuthHandler());
controller->ResetAuth(AuthCredentials(base::ASCIIToUTF16("Hello"),
base::string16()));
diff --git a/chromium/net/http/http_auth_gssapi_posix.cc b/chromium/net/http/http_auth_gssapi_posix.cc
index 1c3352c92dc..40fbd635add 100644
--- a/chromium/net/http/http_auth_gssapi_posix.cc
+++ b/chromium/net/http/http_auth_gssapi_posix.cc
@@ -16,7 +16,6 @@
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/http/http_auth_multi_round_parse.h"
// These are defined for the GSSAPI library:
@@ -701,6 +700,7 @@ HttpAuth::AuthorizationResult HttpAuthGSSAPI::ParseChallenge(
int HttpAuthGSSAPI::GenerateAuthToken(const AuthCredentials* credentials,
const std::string& spn,
+ const std::string& channel_bindings,
std::string* auth_token,
const CompletionCallback& /*callback*/) {
DCHECK(auth_token);
@@ -712,7 +712,8 @@ int HttpAuthGSSAPI::GenerateAuthToken(const AuthCredentials* credentials,
NULL;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
ScopedBuffer scoped_output_token(&output_token, library_);
- int rv = GetNextSecurityToken(spn, &input_token, &output_token);
+ int rv =
+ GetNextSecurityToken(spn, channel_bindings, &input_token, &output_token);
if (rv != OK)
return rv;
@@ -820,6 +821,7 @@ int MapInitSecContextStatusToError(OM_uint32 major_status) {
}
int HttpAuthGSSAPI::GetNextSecurityToken(const std::string& spn,
+ const std::string& channel_bindings,
gss_buffer_t in_token,
gss_buffer_t out_token) {
// Create a name for the principal
@@ -844,24 +846,32 @@ int HttpAuthGSSAPI::GetNextSecurityToken(const std::string& spn,
}
ScopedName scoped_name(principal_name, library_);
+ std::vector<char> channel_bindings_data;
+ scoped_ptr<gss_channel_bindings_struct> gss_channel_bindings;
+ if (!channel_bindings.empty()) {
+ gss_channel_bindings.reset(new gss_channel_bindings_struct);
+ memset(gss_channel_bindings.get(), 0, sizeof(gss_channel_bindings_struct));
+ channel_bindings_data.assign(channel_bindings.begin(),
+ channel_bindings.end());
+ gss_channel_bindings->application_data.value = channel_bindings_data.data();
+ gss_channel_bindings->application_data.length =
+ channel_bindings_data.size();
+ }
+
// Continue creating a security context.
OM_uint32 req_flags = 0;
if (can_delegate_)
req_flags |= GSS_C_DELEG_FLAG;
major_status = library_->init_sec_context(
- &minor_status,
- GSS_C_NO_CREDENTIAL,
- scoped_sec_context_.receive(),
- principal_name,
- gss_oid_,
- req_flags,
- GSS_C_INDEFINITE,
- GSS_C_NO_CHANNEL_BINDINGS,
+ &minor_status, GSS_C_NO_CREDENTIAL, scoped_sec_context_.receive(),
+ principal_name, gss_oid_, req_flags, GSS_C_INDEFINITE,
+ gss_channel_bindings ? gss_channel_bindings.get()
+ : GSS_C_NO_CHANNEL_BINDINGS,
in_token,
- NULL, // actual_mech_type
+ nullptr, // actual_mech_type
out_token,
- NULL, // ret flags
- NULL);
+ nullptr, // ret flags
+ nullptr);
rv = MapInitSecContextStatusToError(major_status);
if (rv != OK) {
LOG(ERROR) << "Problem initializing context. \n"
diff --git a/chromium/net/http/http_auth_gssapi_posix.h b/chromium/net/http/http_auth_gssapi_posix.h
index cf4dcd50f35..6a657616dcc 100644
--- a/chromium/net/http/http_auth_gssapi_posix.h
+++ b/chromium/net/http/http_auth_gssapi_posix.h
@@ -272,6 +272,7 @@ class NET_EXPORT_PRIVATE HttpAuthGSSAPI {
// credentials are used instead.
int GenerateAuthToken(const AuthCredentials* credentials,
const std::string& spn,
+ const std::string& channel_bindings,
std::string* auth_token,
const CompletionCallback& callback);
@@ -282,6 +283,7 @@ class NET_EXPORT_PRIVATE HttpAuthGSSAPI {
private:
int GetNextSecurityToken(const std::string& spn,
+ const std::string& channel_bindings,
gss_buffer_t in_token,
gss_buffer_t out_token);
diff --git a/chromium/net/http/http_auth_gssapi_posix_unittest.cc b/chromium/net/http/http_auth_gssapi_posix_unittest.cc
index 6334fbef9ff..82087010b20 100644
--- a/chromium/net/http/http_auth_gssapi_posix_unittest.cc
+++ b/chromium/net/http/http_auth_gssapi_posix_unittest.cc
@@ -209,7 +209,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_TwoRounds) {
EstablishInitialContext(&mock_library);
std::string auth_token;
EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
- &auth_token,
+ std::string(), &auth_token,
base::Bind(&UnexpectedCallback)));
std::string second_challenge_text = "Negotiate Zm9vYmFy";
@@ -247,7 +247,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_MissingTokenSecondRound) {
EstablishInitialContext(&mock_library);
std::string auth_token;
EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
- &auth_token,
+ std::string(), &auth_token,
base::Bind(&UnexpectedCallback)));
std::string second_challenge_text = "Negotiate";
HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
@@ -271,7 +271,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_NonBase64EncodedToken) {
EstablishInitialContext(&mock_library);
std::string auth_token;
EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
- &auth_token,
+ std::string(), &auth_token,
base::Bind(&UnexpectedCallback)));
std::string second_challenge_text = "Negotiate =happyjoy=";
HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
diff --git a/chromium/net/http/http_auth_handler.cc b/chromium/net/http/http_auth_handler.cc
index 4de2226caa2..32af2d2fdbf 100644
--- a/chromium/net/http/http_auth_handler.cc
+++ b/chromium/net/http/http_auth_handler.cc
@@ -22,11 +22,11 @@ HttpAuthHandler::HttpAuthHandler()
HttpAuthHandler::~HttpAuthHandler() {
}
-bool HttpAuthHandler::InitFromChallenge(
- HttpAuthChallengeTokenizer* challenge,
- HttpAuth::Target target,
- const GURL& origin,
- const BoundNetLog& net_log) {
+bool HttpAuthHandler::InitFromChallenge(HttpAuthChallengeTokenizer* challenge,
+ HttpAuth::Target target,
+ const SSLInfo& ssl_info,
+ const GURL& origin,
+ const BoundNetLog& net_log) {
origin_ = origin;
target_ = target;
score_ = -1;
@@ -34,7 +34,7 @@ bool HttpAuthHandler::InitFromChallenge(
net_log_ = net_log;
auth_challenge_ = challenge->challenge_text();
- bool ok = Init(challenge);
+ bool ok = Init(challenge, ssl_info);
// Init() is expected to set the scheme, realm, score, and properties. The
// realm may be empty.
diff --git a/chromium/net/http/http_auth_handler.h b/chromium/net/http/http_auth_handler.h
index 1aee79556b0..4a6cb79e389 100644
--- a/chromium/net/http/http_auth_handler.h
+++ b/chromium/net/http/http_auth_handler.h
@@ -16,6 +16,7 @@ namespace net {
class HttpAuthChallengeTokenizer;
struct HttpRequestInfo;
+class SSLInfo;
// HttpAuthHandler is the interface for the authentication schemes
// (basic, digest, NTLM, Negotiate).
@@ -32,6 +33,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandler {
// for later use, and are not part of the initial challenge.
bool InitFromChallenge(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
const BoundNetLog& net_log);
@@ -148,9 +150,14 @@ class NET_EXPORT_PRIVATE HttpAuthHandler {
// |challenge| must be non-NULL and have already tokenized the
// authentication scheme, but none of the tokens occurring after the
// authentication scheme.
+ //
+ // If the request was sent over an encrypted connection, |ssl_info| is valid
+ // and describes the connection.
+ //
// Implementations are expected to initialize the following members:
// scheme_, realm_, score_, properties_
- virtual bool Init(HttpAuthChallengeTokenizer* challenge) = 0;
+ virtual bool Init(HttpAuthChallengeTokenizer* challenge,
+ const SSLInfo& ssl_info) = 0;
// |GenerateAuthTokenImpl()} is the auth-scheme specific implementation
// of generating the next auth token. Callers should use |GenerateAuthToken()|
diff --git a/chromium/net/http/http_auth_handler_basic.cc b/chromium/net/http/http_auth_handler_basic.cc
index 45367857297..c5a1d235315 100644
--- a/chromium/net/http/http_auth_handler_basic.cc
+++ b/chromium/net/http/http_auth_handler_basic.cc
@@ -53,7 +53,8 @@ bool ParseRealm(const HttpAuthChallengeTokenizer& tokenizer,
} // namespace
-bool HttpAuthHandlerBasic::Init(HttpAuthChallengeTokenizer* challenge) {
+bool HttpAuthHandlerBasic::Init(HttpAuthChallengeTokenizer* challenge,
+ const SSLInfo& ssl_info) {
auth_scheme_ = HttpAuth::AUTH_SCHEME_BASIC;
score_ = 1;
properties_ = 0;
@@ -109,6 +110,7 @@ HttpAuthHandlerBasic::Factory::~Factory() {
int HttpAuthHandlerBasic::Factory::CreateAuthHandler(
HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int digest_nonce_count,
@@ -117,7 +119,8 @@ int HttpAuthHandlerBasic::Factory::CreateAuthHandler(
// TODO(cbentzel): Move towards model of parsing in the factory
// method and only constructing when valid.
scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerBasic());
- if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
+ if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin,
+ net_log))
return ERR_INVALID_RESPONSE;
handler->swap(tmp_handler);
return OK;
diff --git a/chromium/net/http/http_auth_handler_basic.h b/chromium/net/http/http_auth_handler_basic.h
index 186caf68304..9ad311a2dca 100644
--- a/chromium/net/http/http_auth_handler_basic.h
+++ b/chromium/net/http/http_auth_handler_basic.h
@@ -23,6 +23,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerBasic : public HttpAuthHandler {
int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int digest_nonce_count,
@@ -34,7 +35,8 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerBasic : public HttpAuthHandler {
HttpAuthChallengeTokenizer* challenge) override;
protected:
- bool Init(HttpAuthChallengeTokenizer* challenge) override;
+ bool Init(HttpAuthChallengeTokenizer* challenge,
+ const SSLInfo& ssl_info) override;
int GenerateAuthTokenImpl(const AuthCredentials* credentials,
const HttpRequestInfo* request,
diff --git a/chromium/net/http/http_auth_handler_basic_unittest.cc b/chromium/net/http/http_auth_handler_basic_unittest.cc
index e6a9818aac3..0b0e115c559 100644
--- a/chromium/net/http/http_auth_handler_basic_unittest.cc
+++ b/chromium/net/http/http_auth_handler_basic_unittest.cc
@@ -12,6 +12,7 @@
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_handler_basic.h"
#include "net/http/http_request_info.h"
+#include "net/ssl/ssl_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -34,9 +35,11 @@ TEST(HttpAuthHandlerBasicTest, GenerateAuthToken) {
HttpAuthHandlerBasic::Factory factory;
for (size_t i = 0; i < arraysize(tests); ++i) {
std::string challenge = "Basic realm=\"Atlantis\"";
+ SSLInfo null_ssl_info;
scoped_ptr<HttpAuthHandler> basic;
EXPECT_EQ(OK, factory.CreateAuthHandlerFromString(
- challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog(), &basic));
+ challenge, HttpAuth::AUTH_SERVER, null_ssl_info, origin,
+ BoundNetLog(), &basic));
AuthCredentials credentials(base::ASCIIToUTF16(tests[i].username),
base::ASCIIToUTF16(tests[i].password));
HttpRequestInfo request_info;
@@ -86,10 +89,11 @@ TEST(HttpAuthHandlerBasicTest, HandleAnotherChallenge) {
GURL origin("http://www.example.com");
HttpAuthHandlerBasic::Factory factory;
+ SSLInfo null_ssl_info;
scoped_ptr<HttpAuthHandler> basic;
EXPECT_EQ(OK, factory.CreateAuthHandlerFromString(
- tests[0].challenge, HttpAuth::AUTH_SERVER, origin,
- BoundNetLog(), &basic));
+ tests[0].challenge, HttpAuth::AUTH_SERVER, null_ssl_info,
+ origin, BoundNetLog(), &basic));
for (size_t i = 0; i < arraysize(tests); ++i) {
std::string challenge(tests[i].challenge);
@@ -186,9 +190,11 @@ TEST(HttpAuthHandlerBasicTest, InitFromChallenge) {
GURL origin("http://www.example.com");
for (size_t i = 0; i < arraysize(tests); ++i) {
std::string challenge = tests[i].challenge;
+ SSLInfo null_ssl_info;
scoped_ptr<HttpAuthHandler> basic;
int rv = factory.CreateAuthHandlerFromString(
- challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog(), &basic);
+ challenge, HttpAuth::AUTH_SERVER, null_ssl_info, origin, BoundNetLog(),
+ &basic);
EXPECT_EQ(tests[i].expected_rv, rv);
if (rv == OK)
EXPECT_EQ(tests[i].expected_realm, basic->realm());
diff --git a/chromium/net/http/http_auth_handler_digest.cc b/chromium/net/http/http_auth_handler_digest.cc
index 14c9ecded01..eb03ad75b1e 100644
--- a/chromium/net/http/http_auth_handler_digest.cc
+++ b/chromium/net/http/http_auth_handler_digest.cc
@@ -14,7 +14,7 @@
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
#include "net/base/net_string_util.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "net/http/http_auth.h"
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_scheme.h"
@@ -93,6 +93,7 @@ void HttpAuthHandlerDigest::Factory::set_nonce_generator(
int HttpAuthHandlerDigest::Factory::CreateAuthHandler(
HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int digest_nonce_count,
@@ -102,7 +103,8 @@ int HttpAuthHandlerDigest::Factory::CreateAuthHandler(
// method and only constructing when valid.
scoped_ptr<HttpAuthHandler> tmp_handler(
new HttpAuthHandlerDigest(digest_nonce_count, nonce_generator_.get()));
- if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
+ if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin,
+ net_log))
return ERR_INVALID_RESPONSE;
handler->swap(tmp_handler);
return OK;
@@ -135,7 +137,8 @@ HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge(
HttpAuth::AUTHORIZATION_RESULT_REJECT;
}
-bool HttpAuthHandlerDigest::Init(HttpAuthChallengeTokenizer* challenge) {
+bool HttpAuthHandlerDigest::Init(HttpAuthChallengeTokenizer* challenge,
+ const SSLInfo& ssl_info) {
return ParseChallenge(challenge);
}
diff --git a/chromium/net/http/http_auth_handler_digest.h b/chromium/net/http/http_auth_handler_digest.h
index 27cdfcd0ab0..2b98946e8ba 100644
--- a/chromium/net/http/http_auth_handler_digest.h
+++ b/chromium/net/http/http_auth_handler_digest.h
@@ -67,6 +67,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerDigest : public HttpAuthHandler {
int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int digest_nonce_count,
@@ -81,7 +82,8 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerDigest : public HttpAuthHandler {
HttpAuthChallengeTokenizer* challenge) override;
protected:
- bool Init(HttpAuthChallengeTokenizer* challenge) override;
+ bool Init(HttpAuthChallengeTokenizer* challenge,
+ const SSLInfo& ssl_info) override;
int GenerateAuthTokenImpl(const AuthCredentials* credentials,
const HttpRequestInfo* request,
diff --git a/chromium/net/http/http_auth_handler_digest_unittest.cc b/chromium/net/http/http_auth_handler_digest_unittest.cc
index 89f30109a39..92e3455072d 100644
--- a/chromium/net/http/http_auth_handler_digest_unittest.cc
+++ b/chromium/net/http/http_auth_handler_digest_unittest.cc
@@ -11,6 +11,7 @@
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_handler_digest.h"
#include "net/http/http_request_info.h"
+#include "net/ssl/ssl_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -52,9 +53,11 @@ bool RespondToChallenge(HttpAuth::Target target,
scoped_ptr<HttpAuthHandler> handler;
// Create a handler for a particular challenge.
+ SSLInfo null_ssl_info;
GURL url_origin(target == HttpAuth::AUTH_SERVER ? request_url : proxy_name);
int rv_create = factory->CreateAuthHandlerFromString(
- challenge, target, url_origin.GetOrigin(), BoundNetLog(), &handler);
+ challenge, target, null_ssl_info, url_origin.GetOrigin(), BoundNetLog(),
+ &handler);
if (rv_create != OK || handler.get() == NULL) {
ADD_FAILURE() << "Unable to create auth handler.";
return false;
@@ -351,12 +354,11 @@ TEST(HttpAuthHandlerDigestTest, ParseChallenge) {
scoped_ptr<HttpAuthHandlerDigest::Factory> factory(
new HttpAuthHandlerDigest::Factory());
for (size_t i = 0; i < arraysize(tests); ++i) {
+ SSLInfo null_ssl_info;
scoped_ptr<HttpAuthHandler> handler;
- int rv = factory->CreateAuthHandlerFromString(tests[i].challenge,
- HttpAuth::AUTH_SERVER,
- origin,
- BoundNetLog(),
- &handler);
+ int rv = factory->CreateAuthHandlerFromString(
+ tests[i].challenge, HttpAuth::AUTH_SERVER, null_ssl_info, origin,
+ BoundNetLog(), &handler);
if (tests[i].parsed_success) {
EXPECT_EQ(OK, rv);
} else {
@@ -516,12 +518,11 @@ TEST(HttpAuthHandlerDigestTest, AssembleCredentials) {
scoped_ptr<HttpAuthHandlerDigest::Factory> factory(
new HttpAuthHandlerDigest::Factory());
for (size_t i = 0; i < arraysize(tests); ++i) {
+ SSLInfo null_ssl_info;
scoped_ptr<HttpAuthHandler> handler;
- int rv = factory->CreateAuthHandlerFromString(tests[i].challenge,
- HttpAuth::AUTH_SERVER,
- origin,
- BoundNetLog(),
- &handler);
+ int rv = factory->CreateAuthHandlerFromString(
+ tests[i].challenge, HttpAuth::AUTH_SERVER, null_ssl_info, origin,
+ BoundNetLog(), &handler);
EXPECT_EQ(OK, rv);
ASSERT_TRUE(handler != NULL);
@@ -547,9 +548,10 @@ TEST(HttpAuthHandlerDigest, HandleAnotherChallenge) {
std::string default_challenge =
"Digest realm=\"Oblivion\", nonce=\"nonce-value\"";
GURL origin("intranet.google.com");
+ SSLInfo null_ssl_info;
int rv = factory->CreateAuthHandlerFromString(
- default_challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog(),
- &handler);
+ default_challenge, HttpAuth::AUTH_SERVER, null_ssl_info, origin,
+ BoundNetLog(), &handler);
EXPECT_EQ(OK, rv);
ASSERT_TRUE(handler.get() != NULL);
HttpAuthChallengeTokenizer tok_default(default_challenge.begin(),
diff --git a/chromium/net/http/http_auth_handler_factory.cc b/chromium/net/http/http_auth_handler_factory.cc
index c03792f1e93..af682e12d98 100644
--- a/chromium/net/http/http_auth_handler_factory.cc
+++ b/chromium/net/http/http_auth_handler_factory.cc
@@ -14,6 +14,7 @@
#include "net/http/http_auth_handler_ntlm.h"
#include "net/http/http_auth_preferences.h"
#include "net/http/http_auth_scheme.h"
+#include "net/ssl/ssl_info.h"
#if defined(USE_KERBEROS)
#include "net/http/http_auth_handler_negotiate.h"
@@ -24,12 +25,13 @@ namespace net {
int HttpAuthHandlerFactory::CreateAuthHandlerFromString(
const std::string& challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
const BoundNetLog& net_log,
scoped_ptr<HttpAuthHandler>* handler) {
HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end());
- return CreateAuthHandler(&props, target, origin, CREATE_CHALLENGE, 1,
- net_log, handler);
+ return CreateAuthHandler(&props, target, ssl_info, origin, CREATE_CHALLENGE,
+ 1, net_log, handler);
}
int HttpAuthHandlerFactory::CreatePreemptiveAuthHandlerFromString(
@@ -40,8 +42,10 @@ int HttpAuthHandlerFactory::CreatePreemptiveAuthHandlerFromString(
const BoundNetLog& net_log,
scoped_ptr<HttpAuthHandler>* handler) {
HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end());
- return CreateAuthHandler(&props, target, origin, CREATE_PREEMPTIVE,
- digest_nonce_count, net_log, handler);
+ SSLInfo null_ssl_info;
+ return CreateAuthHandler(&props, target, null_ssl_info, origin,
+ CREATE_PREEMPTIVE, digest_nonce_count, net_log,
+ handler);
}
namespace {
@@ -161,6 +165,7 @@ HttpAuthHandlerRegistryFactory::Create(const HttpAuthPreferences* prefs,
int HttpAuthHandlerRegistryFactory::CreateAuthHandler(
HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int digest_nonce_count,
@@ -178,8 +183,9 @@ int HttpAuthHandlerRegistryFactory::CreateAuthHandler(
return ERR_UNSUPPORTED_AUTH_SCHEME;
}
DCHECK(it->second);
- return it->second->CreateAuthHandler(challenge, target, origin, reason,
- digest_nonce_count, net_log, handler);
+ return it->second->CreateAuthHandler(challenge, target, ssl_info, origin,
+ reason, digest_nonce_count, net_log,
+ handler);
}
} // namespace net
diff --git a/chromium/net/http/http_auth_handler_factory.h b/chromium/net/http/http_auth_handler_factory.h
index a98f9d7f4b1..60ec3f928c5 100644
--- a/chromium/net/http/http_auth_handler_factory.h
+++ b/chromium/net/http/http_auth_handler_factory.h
@@ -73,6 +73,9 @@ class NET_EXPORT HttpAuthHandlerFactory {
// scheme, and indicates the number of handlers generated for a particular
// server nonce challenge.
//
+ // |ssl_info| is valid if the authentication session is being established over
+ // a secure connection.
+ //
// For the NTLM and Negotiate handlers:
// If |origin| does not match the authentication method's filters for
// the specified |target|, ERR_INVALID_AUTH_CREDENTIALS is returned.
@@ -81,6 +84,7 @@ class NET_EXPORT HttpAuthHandlerFactory {
// |*challenge| should not be reused after a call to |CreateAuthHandler()|,
virtual int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason create_reason,
int digest_nonce_count,
@@ -94,6 +98,7 @@ class NET_EXPORT HttpAuthHandlerFactory {
// more details on return values.
int CreateAuthHandlerFromString(const std::string& challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
const BoundNetLog& net_log,
scoped_ptr<HttpAuthHandler>* handler);
@@ -177,6 +182,7 @@ class NET_EXPORT HttpAuthHandlerRegistryFactory
// based on the first token in |challenge|.
int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int digest_nonce_count,
diff --git a/chromium/net/http/http_auth_handler_factory_unittest.cc b/chromium/net/http/http_auth_handler_factory_unittest.cc
index b73e47b8961..6d851211670 100644
--- a/chromium/net/http/http_auth_handler_factory_unittest.cc
+++ b/chromium/net/http/http_auth_handler_factory_unittest.cc
@@ -10,6 +10,7 @@
#include "net/http/http_auth_scheme.h"
#include "net/http/mock_allow_http_auth_preferences.h"
#include "net/http/url_security_manager.h"
+#include "net/ssl/ssl_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -24,6 +25,7 @@ class MockHttpAuthHandlerFactory : public HttpAuthHandlerFactory {
int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int nonce_count,
@@ -40,6 +42,7 @@ class MockHttpAuthHandlerFactory : public HttpAuthHandlerFactory {
} // namespace
TEST(HttpAuthHandlerFactoryTest, RegistryFactory) {
+ SSLInfo null_ssl_info;
HttpAuthHandlerRegistryFactory registry_factory;
GURL gurl("www.google.com");
const int kBasicReturnCode = ERR_INVALID_SPDY_STREAM;
@@ -59,42 +62,43 @@ TEST(HttpAuthHandlerFactoryTest, RegistryFactory) {
// No schemes should be supported in the beginning.
EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME,
registry_factory.CreateAuthHandlerFromString(
- "Basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
+ "Basic", HttpAuth::AUTH_SERVER, null_ssl_info, gurl,
+ BoundNetLog(), &handler));
// Test what happens with a single scheme.
registry_factory.RegisterSchemeFactory("Basic", mock_factory_basic);
- EXPECT_EQ(kBasicReturnCode,
- registry_factory.CreateAuthHandlerFromString(
- "Basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
+ EXPECT_EQ(kBasicReturnCode, registry_factory.CreateAuthHandlerFromString(
+ "Basic", HttpAuth::AUTH_SERVER, null_ssl_info,
+ gurl, BoundNetLog(), &handler));
EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME,
registry_factory.CreateAuthHandlerFromString(
- "Digest", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(),
- &handler));
+ "Digest", HttpAuth::AUTH_SERVER, null_ssl_info, gurl,
+ BoundNetLog(), &handler));
// Test multiple schemes
registry_factory.RegisterSchemeFactory("Digest", mock_factory_digest);
- EXPECT_EQ(kBasicReturnCode,
- registry_factory.CreateAuthHandlerFromString(
- "Basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
+ EXPECT_EQ(kBasicReturnCode, registry_factory.CreateAuthHandlerFromString(
+ "Basic", HttpAuth::AUTH_SERVER, null_ssl_info,
+ gurl, BoundNetLog(), &handler));
EXPECT_EQ(kDigestReturnCode,
registry_factory.CreateAuthHandlerFromString(
- "Digest", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(),
- &handler));
+ "Digest", HttpAuth::AUTH_SERVER, null_ssl_info, gurl,
+ BoundNetLog(), &handler));
// Test case-insensitivity
- EXPECT_EQ(kBasicReturnCode,
- registry_factory.CreateAuthHandlerFromString(
- "basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
+ EXPECT_EQ(kBasicReturnCode, registry_factory.CreateAuthHandlerFromString(
+ "basic", HttpAuth::AUTH_SERVER, null_ssl_info,
+ gurl, BoundNetLog(), &handler));
// Test replacement of existing auth scheme
registry_factory.RegisterSchemeFactory("Digest", mock_factory_digest_replace);
- EXPECT_EQ(kBasicReturnCode,
- registry_factory.CreateAuthHandlerFromString(
- "Basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
+ EXPECT_EQ(kBasicReturnCode, registry_factory.CreateAuthHandlerFromString(
+ "Basic", HttpAuth::AUTH_SERVER, null_ssl_info,
+ gurl, BoundNetLog(), &handler));
EXPECT_EQ(kDigestReturnCodeReplace,
registry_factory.CreateAuthHandlerFromString(
- "Digest", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(),
- &handler));
+ "Digest", HttpAuth::AUTH_SERVER, null_ssl_info, gurl,
+ BoundNetLog(), &handler));
}
TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
@@ -106,14 +110,12 @@ TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
&http_auth_preferences);
GURL server_origin("http://www.example.com");
GURL proxy_origin("http://cache.example.com:3128");
+ SSLInfo null_ssl_info;
{
scoped_ptr<HttpAuthHandler> handler;
int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
- "Basic realm=\"FooBar\"",
- HttpAuth::AUTH_SERVER,
- server_origin,
- BoundNetLog(),
- &handler);
+ "Basic realm=\"FooBar\"", HttpAuth::AUTH_SERVER, null_ssl_info,
+ server_origin, BoundNetLog(), &handler);
EXPECT_EQ(OK, rv);
ASSERT_FALSE(handler.get() == NULL);
EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, handler->auth_scheme());
@@ -125,22 +127,16 @@ TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
{
scoped_ptr<HttpAuthHandler> handler;
int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
- "UNSUPPORTED realm=\"FooBar\"",
- HttpAuth::AUTH_SERVER,
- server_origin,
- BoundNetLog(),
- &handler);
+ "UNSUPPORTED realm=\"FooBar\"", HttpAuth::AUTH_SERVER, null_ssl_info,
+ server_origin, BoundNetLog(), &handler);
EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, rv);
EXPECT_TRUE(handler.get() == NULL);
}
{
scoped_ptr<HttpAuthHandler> handler;
int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
- "Digest realm=\"FooBar\", nonce=\"xyz\"",
- HttpAuth::AUTH_PROXY,
- proxy_origin,
- BoundNetLog(),
- &handler);
+ "Digest realm=\"FooBar\", nonce=\"xyz\"", HttpAuth::AUTH_PROXY,
+ null_ssl_info, proxy_origin, BoundNetLog(), &handler);
EXPECT_EQ(OK, rv);
ASSERT_FALSE(handler.get() == NULL);
EXPECT_EQ(HttpAuth::AUTH_SCHEME_DIGEST, handler->auth_scheme());
@@ -152,11 +148,8 @@ TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
{
scoped_ptr<HttpAuthHandler> handler;
int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
- "NTLM",
- HttpAuth::AUTH_SERVER,
- server_origin,
- BoundNetLog(),
- &handler);
+ "NTLM", HttpAuth::AUTH_SERVER, null_ssl_info, server_origin,
+ BoundNetLog(), &handler);
EXPECT_EQ(OK, rv);
ASSERT_FALSE(handler.get() == NULL);
EXPECT_EQ(HttpAuth::AUTH_SCHEME_NTLM, handler->auth_scheme());
@@ -168,11 +161,8 @@ TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
{
scoped_ptr<HttpAuthHandler> handler;
int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
- "Negotiate",
- HttpAuth::AUTH_SERVER,
- server_origin,
- BoundNetLog(),
- &handler);
+ "Negotiate", HttpAuth::AUTH_SERVER, null_ssl_info, server_origin,
+ BoundNetLog(), &handler);
// Note the default factory doesn't support Kerberos on Android
#if defined(USE_KERBEROS) && !defined(OS_ANDROID)
EXPECT_EQ(OK, rv);
diff --git a/chromium/net/http/http_auth_handler_mock.cc b/chromium/net/http/http_auth_handler_mock.cc
index 04a09e4d6b1..513cbb69112 100644
--- a/chromium/net/http/http_auth_handler_mock.cc
+++ b/chromium/net/http/http_auth_handler_mock.cc
@@ -101,7 +101,8 @@ bool HttpAuthHandlerMock::AllowsExplicitCredentials() {
return allows_explicit_credentials_;
}
-bool HttpAuthHandlerMock::Init(HttpAuthChallengeTokenizer* challenge) {
+bool HttpAuthHandlerMock::Init(HttpAuthChallengeTokenizer* challenge,
+ const SSLInfo& ssl_info) {
auth_scheme_ = HttpAuth::AUTH_SCHEME_MOCK;
score_ = 1;
properties_ = connection_based_ ? IS_CONNECTION_BASED : 0;
@@ -167,6 +168,7 @@ void HttpAuthHandlerMock::Factory::AddMockHandler(
int HttpAuthHandlerMock::Factory::CreateAuthHandler(
HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int nonce_count,
@@ -178,7 +180,8 @@ int HttpAuthHandlerMock::Factory::CreateAuthHandler(
std::vector<scoped_ptr<HttpAuthHandler>>& handlers = handlers_[target];
handlers.erase(handlers.begin());
if (do_init_from_challenge_ &&
- !tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
+ !tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin,
+ net_log))
return ERR_INVALID_RESPONSE;
handler->swap(tmp_handler);
return OK;
diff --git a/chromium/net/http/http_auth_handler_mock.h b/chromium/net/http/http_auth_handler_mock.h
index 2677526803b..41aaa2d6d98 100644
--- a/chromium/net/http/http_auth_handler_mock.h
+++ b/chromium/net/http/http_auth_handler_mock.h
@@ -45,6 +45,7 @@ class HttpAuthHandlerMock : public HttpAuthHandler {
// HttpAuthHandlerFactory:
int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int nonce_count,
@@ -95,7 +96,8 @@ class HttpAuthHandlerMock : public HttpAuthHandler {
bool AllowsExplicitCredentials() override;
protected:
- bool Init(HttpAuthChallengeTokenizer* challenge) override;
+ bool Init(HttpAuthChallengeTokenizer* challenge,
+ const SSLInfo& ssl_info) override;
int GenerateAuthTokenImpl(const AuthCredentials* credentials,
const HttpRequestInfo* request,
diff --git a/chromium/net/http/http_auth_handler_negotiate.cc b/chromium/net/http/http_auth_handler_negotiate.cc
index 864a703e12e..1ca6d5478d9 100644
--- a/chromium/net/http/http_auth_handler_negotiate.cc
+++ b/chromium/net/http/http_auth_handler_negotiate.cc
@@ -7,16 +7,39 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/values.h"
#include "net/base/address_family.h"
#include "net/base/net_errors.h"
+#include "net/cert/x509_util.h"
#include "net/dns/host_resolver.h"
#include "net/dns/single_request_host_resolver.h"
#include "net/http/http_auth_filter.h"
#include "net/http/http_auth_preferences.h"
+#include "net/log/net_log.h"
+#include "net/ssl/ssl_info.h"
namespace net {
+namespace {
+
+scoped_ptr<base::Value> NetLogParameterChannelBindings(
+ const std::string& channel_binding_token,
+ NetLogCaptureMode capture_mode) {
+ scoped_ptr<base::DictionaryValue> dict;
+ if (!capture_mode.include_socket_bytes())
+ return std::move(dict);
+
+ dict.reset(new base::DictionaryValue());
+ dict->SetString("token", base::HexEncode(channel_binding_token.data(),
+ channel_binding_token.size()));
+ return std::move(dict);
+}
+
+} // namespace
+
HttpAuthHandlerNegotiate::Factory::Factory()
: resolver_(NULL),
#if defined(OS_WIN)
@@ -36,6 +59,7 @@ void HttpAuthHandlerNegotiate::Factory::set_host_resolver(
int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler(
HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int digest_nonce_count,
@@ -78,7 +102,8 @@ int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler(
scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNegotiate(
auth_library_.get(), http_auth_preferences(), resolver_));
#endif
- if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
+ if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin,
+ net_log))
return ERR_INVALID_RESPONSE;
handler->swap(tmp_handler);
return OK;
@@ -185,7 +210,8 @@ bool HttpAuthHandlerNegotiate::AllowsExplicitCredentials() {
// The Negotiate challenge header looks like:
// WWW-Authenticate: NEGOTIATE auth-data
-bool HttpAuthHandlerNegotiate::Init(HttpAuthChallengeTokenizer* challenge) {
+bool HttpAuthHandlerNegotiate::Init(HttpAuthChallengeTokenizer* challenge,
+ const SSLInfo& ssl_info) {
#if defined(OS_POSIX)
if (!auth_system_.Init()) {
VLOG(1) << "can't initialize GSSAPI library";
@@ -203,9 +229,21 @@ bool HttpAuthHandlerNegotiate::Init(HttpAuthChallengeTokenizer* challenge) {
auth_scheme_ = HttpAuth::AUTH_SCHEME_NEGOTIATE;
score_ = 4;
properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
+
HttpAuth::AuthorizationResult auth_result =
auth_system_.ParseChallenge(challenge);
- return (auth_result == HttpAuth::AUTHORIZATION_RESULT_ACCEPT);
+ if (auth_result != HttpAuth::AUTHORIZATION_RESULT_ACCEPT)
+ return false;
+
+ // Try to extract channel bindings.
+ if (ssl_info.is_valid())
+ x509_util::GetTLSServerEndPointChannelBinding(*ssl_info.cert,
+ &channel_bindings_);
+ if (!channel_bindings_.empty())
+ net_log_.AddEvent(
+ NetLog::TYPE_AUTH_CHANNEL_BINDINGS,
+ base::Bind(&NetLogParameterChannelBindings, channel_bindings_));
+ return true;
}
int HttpAuthHandlerNegotiate::GenerateAuthTokenImpl(
@@ -319,7 +357,7 @@ int HttpAuthHandlerNegotiate::DoGenerateAuthToken() {
next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE;
AuthCredentials* credentials = has_credentials_ ? &credentials_ : NULL;
return auth_system_.GenerateAuthToken(
- credentials, spn_, auth_token_,
+ credentials, spn_, channel_bindings_, auth_token_,
base::Bind(&HttpAuthHandlerNegotiate::OnIOComplete,
base::Unretained(this)));
}
diff --git a/chromium/net/http/http_auth_handler_negotiate.h b/chromium/net/http/http_auth_handler_negotiate.h
index 1d744318946..abdbe93f799 100644
--- a/chromium/net/http/http_auth_handler_negotiate.h
+++ b/chromium/net/http/http_auth_handler_negotiate.h
@@ -63,6 +63,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNegotiate : public HttpAuthHandler {
// HttpAuthHandlerFactory overrides
int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int digest_nonce_count,
@@ -104,7 +105,8 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNegotiate : public HttpAuthHandler {
bool AllowsExplicitCredentials() override;
protected:
- bool Init(HttpAuthChallengeTokenizer* challenge) override;
+ bool Init(HttpAuthChallengeTokenizer* challenge,
+ const SSLInfo& ssl_info) override;
int GenerateAuthTokenImpl(const AuthCredentials* credentials,
const HttpRequestInfo* request,
@@ -142,6 +144,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNegotiate : public HttpAuthHandler {
bool has_credentials_;
AuthCredentials credentials_;
std::string spn_;
+ std::string channel_bindings_;
// Things which vary each round.
CompletionCallback callback_;
diff --git a/chromium/net/http/http_auth_handler_negotiate_unittest.cc b/chromium/net/http/http_auth_handler_negotiate_unittest.cc
index fd467162ace..57a7b7eb406 100644
--- a/chromium/net/http/http_auth_handler_negotiate_unittest.cc
+++ b/chromium/net/http/http_auth_handler_negotiate_unittest.cc
@@ -13,6 +13,10 @@
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_request_info.h"
#include "net/http/mock_allow_http_auth_preferences.h"
+#include "net/ssl/ssl_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
#if defined(OS_ANDROID)
#include "net/android/dummy_spnego_authenticator.h"
#elif defined(OS_WIN)
@@ -20,8 +24,6 @@
#elif defined(OS_POSIX)
#include "net/http/mock_gssapi_library_posix.h"
#endif
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
namespace net {
@@ -189,10 +191,11 @@ class HttpAuthHandlerNegotiateTest : public PlatformTest {
#endif // defined(OS_POSIX)
- int CreateHandler(bool disable_cname_lookup, bool use_port,
- bool synchronous_resolve_mode,
- const std::string& url_string,
- scoped_ptr<HttpAuthHandlerNegotiate>* handler) {
+ int CreateHandler(bool disable_cname_lookup,
+ bool use_port,
+ bool synchronous_resolve_mode,
+ const std::string& url_string,
+ scoped_ptr<HttpAuthHandlerNegotiate>* handler) {
http_auth_preferences_->set_negotiate_disable_cname_lookup(
disable_cname_lookup);
http_auth_preferences_->set_negotiate_enable_port(use_port);
@@ -205,11 +208,10 @@ class HttpAuthHandlerNegotiateTest : public PlatformTest {
// after creating the handler, and make sure that generic_handler
// no longer holds on to the HttpAuthHandlerNegotiate object.
scoped_ptr<HttpAuthHandler> generic_handler;
- int rv = factory_->CreateAuthHandlerFromString("Negotiate",
- HttpAuth::AUTH_SERVER,
- gurl,
- BoundNetLog(),
- &generic_handler);
+ SSLInfo null_ssl_info;
+ int rv = factory_->CreateAuthHandlerFromString(
+ "Negotiate", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, BoundNetLog(),
+ &generic_handler);
if (rv != OK)
return rv;
HttpAuthHandlerNegotiate* negotiate_handler =
diff --git a/chromium/net/http/http_auth_handler_ntlm.cc b/chromium/net/http/http_auth_handler_ntlm.cc
index 2411f9fcd1e..cecf3b2917d 100644
--- a/chromium/net/http/http_auth_handler_ntlm.cc
+++ b/chromium/net/http/http_auth_handler_ntlm.cc
@@ -11,9 +11,11 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
+#include "net/cert/x509_util.h"
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_scheme.h"
+#include "net/http/http_response_info.h"
namespace net {
@@ -22,11 +24,16 @@ HttpAuth::AuthorizationResult HttpAuthHandlerNTLM::HandleAnotherChallenge(
return ParseChallenge(challenge, false);
}
-bool HttpAuthHandlerNTLM::Init(HttpAuthChallengeTokenizer* tok) {
+bool HttpAuthHandlerNTLM::Init(HttpAuthChallengeTokenizer* tok,
+ const SSLInfo& ssl_info) {
auth_scheme_ = HttpAuth::AUTH_SCHEME_NTLM;
score_ = 3;
properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
+ if (ssl_info.is_valid())
+ x509_util::GetTLSServerEndPointChannelBinding(*ssl_info.cert,
+ &channel_bindings_);
+
return ParseChallenge(tok, true) == HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
}
@@ -35,7 +42,7 @@ int HttpAuthHandlerNTLM::GenerateAuthTokenImpl(
const CompletionCallback& callback, std::string* auth_token) {
#if defined(NTLM_SSPI)
return auth_sspi_.GenerateAuthToken(credentials, CreateSPN(origin_),
- auth_token, callback);
+ channel_bindings_, auth_token, callback);
#else // !defined(NTLM_SSPI)
// TODO(cbentzel): Shouldn't be hitting this case.
if (!credentials) {
diff --git a/chromium/net/http/http_auth_handler_ntlm.h b/chromium/net/http/http_auth_handler_ntlm.h
index d71b498daa3..58e2993bf62 100644
--- a/chromium/net/http/http_auth_handler_ntlm.h
+++ b/chromium/net/http/http_auth_handler_ntlm.h
@@ -45,6 +45,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler {
int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int digest_nonce_count,
@@ -117,7 +118,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler {
// It does nothing in the portable implementation.
int InitializeBeforeFirstChallenge();
- bool Init(HttpAuthChallengeTokenizer* tok) override;
+ bool Init(HttpAuthChallengeTokenizer* tok, const SSLInfo& ssl_info) override;
int GenerateAuthTokenImpl(const AuthCredentials* credentials,
const HttpRequestInfo* request,
@@ -159,6 +160,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler {
base::string16 domain_;
AuthCredentials credentials_;
+ std::string channel_bindings_;
// The base64-encoded string following "NTLM" in the "WWW-Authenticate" or
// "Proxy-Authenticate" response header.
diff --git a/chromium/net/http/http_auth_handler_ntlm_portable.cc b/chromium/net/http/http_auth_handler_ntlm_portable.cc
index 0522c3179fa..b5a488260b7 100644
--- a/chromium/net/http/http_auth_handler_ntlm_portable.cc
+++ b/chromium/net/http/http_auth_handler_ntlm_portable.cc
@@ -18,7 +18,7 @@
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
+#include "net/base/network_interfaces.h"
#include "net/base/zap.h"
#include "net/http/des.h"
#include "net/http/md4.h"
@@ -714,6 +714,7 @@ int HttpAuthHandlerNTLM::GetNextToken(const void* in_token,
int HttpAuthHandlerNTLM::Factory::CreateAuthHandler(
HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int digest_nonce_count,
@@ -726,7 +727,8 @@ int HttpAuthHandlerNTLM::Factory::CreateAuthHandler(
// NOTE: Default credentials are not supported for the portable implementation
// of NTLM.
scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNTLM);
- if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
+ if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin,
+ net_log))
return ERR_INVALID_RESPONSE;
handler->swap(tmp_handler);
return OK;
diff --git a/chromium/net/http/http_auth_handler_ntlm_win.cc b/chromium/net/http/http_auth_handler_ntlm_win.cc
index 7aca5f07bd9..844a0a07193 100644
--- a/chromium/net/http/http_auth_handler_ntlm_win.cc
+++ b/chromium/net/http/http_auth_handler_ntlm_win.cc
@@ -11,12 +11,9 @@
#include "base/strings/string_util.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/http/http_auth_preferences.h"
#include "net/http/http_auth_sspi_win.h"
-#pragma comment(lib, "secur32.lib")
-
namespace net {
HttpAuthHandlerNTLM::HttpAuthHandlerNTLM(
@@ -53,6 +50,7 @@ HttpAuthHandlerNTLM::Factory::~Factory() {
int HttpAuthHandlerNTLM::Factory::CreateAuthHandler(
HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int digest_nonce_count,
@@ -72,7 +70,8 @@ int HttpAuthHandlerNTLM::Factory::CreateAuthHandler(
// method and only constructing when valid.
scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNTLM(
sspi_library_.get(), max_token_length_, http_auth_preferences()));
- if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
+ if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin,
+ net_log))
return ERR_INVALID_RESPONSE;
handler->swap(tmp_handler);
return OK;
diff --git a/chromium/net/http/http_auth_handler_unittest.cc b/chromium/net/http/http_auth_handler_unittest.cc
index 5757bb65c84..1bb384ff1cd 100644
--- a/chromium/net/http/http_auth_handler_unittest.cc
+++ b/chromium/net/http/http_auth_handler_unittest.cc
@@ -14,6 +14,7 @@
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_entry.h"
#include "net/log/test_net_log_util.h"
+#include "net/ssl/ssl_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -43,7 +44,8 @@ TEST(HttpAuthHandlerTest, NetLog) {
BoundNetLog bound_net_log(
BoundNetLog::Make(&test_net_log, NetLog::SOURCE_NONE));
- mock_handler.InitFromChallenge(&tokenizer, target,
+ SSLInfo empty_ssl_info;
+ mock_handler.InitFromChallenge(&tokenizer, target, empty_ssl_info,
origin, bound_net_log);
mock_handler.SetGenerateExpectation(async, rv);
mock_handler.GenerateAuthToken(&credentials, &request,
diff --git a/chromium/net/http/http_auth_preferences.h b/chromium/net/http/http_auth_preferences.h
index eabd13833f4..4f3a68befb6 100644
--- a/chromium/net/http/http_auth_preferences.h
+++ b/chromium/net/http/http_auth_preferences.h
@@ -5,6 +5,7 @@
#ifndef NET_HTTP_HTTP_AUTH_PREFERENCES_H_
#define NET_HTTP_HTTP_AUTH_PREFERENCES_H_
+#include <memory>
#include <set>
#include <string>
#include <vector>
@@ -76,7 +77,7 @@ class NET_EXPORT HttpAuthPreferences {
// sorts of problems for, for example, active Negotiate transactions.
const std::string gssapi_library_name_;
#endif
- scoped_ptr<URLSecurityManager> security_manager_;
+ std::unique_ptr<URLSecurityManager> security_manager_;
DISALLOW_COPY_AND_ASSIGN(HttpAuthPreferences);
};
diff --git a/chromium/net/http/http_auth_preferences_unittest.cc b/chromium/net/http/http_auth_preferences_unittest.cc
index 479b0d52b6d..e975b0c9514 100644
--- a/chromium/net/http/http_auth_preferences_unittest.cc
+++ b/chromium/net/http/http_auth_preferences_unittest.cc
@@ -8,8 +8,6 @@
#include <vector>
#include "base/callback.h"
-#include "base/prefs/pref_registry_simple.h"
-#include "base/prefs/testing_pref_service.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
diff --git a/chromium/net/http/http_auth_sspi_win.cc b/chromium/net/http/http_auth_sspi_win.cc
index f59ce4d9d78..a2929fbb569 100644
--- a/chromium/net/http/http_auth_sspi_win.cc
+++ b/chromium/net/http/http_auth_sspi_win.cc
@@ -292,6 +292,7 @@ HttpAuth::AuthorizationResult HttpAuthSSPI::ParseChallenge(
int HttpAuthSSPI::GenerateAuthToken(const AuthCredentials* credentials,
const std::string& spn,
+ const std::string& channel_bindings,
std::string* auth_token,
const CompletionCallback& /*callback*/) {
// Initial challenge.
@@ -305,12 +306,9 @@ int HttpAuthSSPI::GenerateAuthToken(const AuthCredentials* credentials,
void* out_buf;
int out_buf_len;
int rv = GetNextSecurityToken(
- spn,
- static_cast<void *>(const_cast<char *>(
- decoded_server_auth_token_.c_str())),
- decoded_server_auth_token_.length(),
- &out_buf,
- &out_buf_len);
+ spn, channel_bindings,
+ static_cast<void*>(const_cast<char*>(decoded_server_auth_token_.c_str())),
+ decoded_server_auth_token_.length(), &out_buf, &out_buf_len);
if (rv != OK)
return rv;
@@ -344,27 +342,27 @@ int HttpAuthSSPI::OnFirstRound(const AuthCredentials* credentials) {
return rv;
}
-int HttpAuthSSPI::GetNextSecurityToken(
- const std::string& spn,
- const void* in_token,
- int in_token_len,
- void** out_token,
- int* out_token_len) {
- CtxtHandle* ctxt_ptr;
+int HttpAuthSSPI::GetNextSecurityToken(const std::string& spn,
+ const std::string& channel_bindings,
+ const void* in_token,
+ int in_token_len,
+ void** out_token,
+ int* out_token_len) {
+ CtxtHandle* ctxt_ptr = nullptr;
SecBufferDesc in_buffer_desc, out_buffer_desc;
- SecBufferDesc* in_buffer_desc_ptr;
- SecBuffer in_buffer, out_buffer;
+ SecBufferDesc* in_buffer_desc_ptr = nullptr;
+ SecBuffer in_buffers[2], out_buffer;
+ in_buffer_desc.ulVersion = SECBUFFER_VERSION;
+ in_buffer_desc.cBuffers = 0;
+ in_buffer_desc.pBuffers = in_buffers;
if (in_token_len > 0) {
// Prepare input buffer.
- in_buffer_desc.ulVersion = SECBUFFER_VERSION;
- in_buffer_desc.cBuffers = 1;
- in_buffer_desc.pBuffers = &in_buffer;
- in_buffer.BufferType = SECBUFFER_TOKEN;
- in_buffer.cbBuffer = in_token_len;
- in_buffer.pvBuffer = const_cast<void*>(in_token);
+ SecBuffer& sec_buffer = in_buffers[in_buffer_desc.cBuffers++];
+ sec_buffer.BufferType = SECBUFFER_TOKEN;
+ sec_buffer.cbBuffer = in_token_len;
+ sec_buffer.pvBuffer = const_cast<void*>(in_token);
ctxt_ptr = &ctxt_;
- in_buffer_desc_ptr = &in_buffer_desc;
} else {
// If there is no input token, then we are starting a new authentication
// sequence. If we have already initialized our security context, then
@@ -373,10 +371,33 @@ int HttpAuthSSPI::GetNextSecurityToken(
NOTREACHED();
return ERR_UNEXPECTED;
}
- ctxt_ptr = NULL;
- in_buffer_desc_ptr = NULL;
}
+ std::vector<char> sec_channel_bindings_buffer;
+ if (!channel_bindings.empty()) {
+ sec_channel_bindings_buffer.reserve(sizeof(SEC_CHANNEL_BINDINGS) +
+ channel_bindings.size());
+ sec_channel_bindings_buffer.resize(sizeof(SEC_CHANNEL_BINDINGS));
+ SEC_CHANNEL_BINDINGS* bindings_desc =
+ reinterpret_cast<SEC_CHANNEL_BINDINGS*>(
+ &sec_channel_bindings_buffer.front());
+ bindings_desc->cbApplicationDataLength = channel_bindings.size();
+ bindings_desc->dwApplicationDataOffset = sizeof(SEC_CHANNEL_BINDINGS);
+ sec_channel_bindings_buffer.insert(sec_channel_bindings_buffer.end(),
+ channel_bindings.begin(),
+ channel_bindings.end());
+ DCHECK_EQ(sizeof(SEC_CHANNEL_BINDINGS) + channel_bindings.size(),
+ sec_channel_bindings_buffer.size());
+
+ SecBuffer& sec_buffer = in_buffers[in_buffer_desc.cBuffers++];
+ sec_buffer.BufferType = SECBUFFER_CHANNEL_BINDINGS;
+ sec_buffer.cbBuffer = sec_channel_bindings_buffer.size();
+ sec_buffer.pvBuffer = &sec_channel_bindings_buffer.front();
+ }
+
+ if (in_buffer_desc.cBuffers > 0)
+ in_buffer_desc_ptr = &in_buffer_desc;
+
// Prepare output buffer.
out_buffer_desc.ulVersion = SECBUFFER_VERSION;
out_buffer_desc.cBuffers = 1;
@@ -397,18 +418,18 @@ int HttpAuthSSPI::GetNextSecurityToken(
DWORD context_attribute;
base::string16 spn16 = base::ASCIIToUTF16(spn);
SECURITY_STATUS status = library_->InitializeSecurityContext(
- &cred_, // phCredential
- ctxt_ptr, // phContext
+ &cred_, // phCredential
+ ctxt_ptr, // phContext
const_cast<base::char16*>(spn16.c_str()), // pszTargetName
- context_flags, // fContextReq
- 0, // Reserved1 (must be 0)
- SECURITY_NATIVE_DREP, // TargetDataRep
- in_buffer_desc_ptr, // pInput
- 0, // Reserved2 (must be 0)
- &ctxt_, // phNewContext
- &out_buffer_desc, // pOutput
- &context_attribute, // pfContextAttr
- NULL); // ptsExpiry
+ context_flags, // fContextReq
+ 0, // Reserved1 (must be 0)
+ SECURITY_NATIVE_DREP, // TargetDataRep
+ in_buffer_desc_ptr, // pInput
+ 0, // Reserved2 (must be 0)
+ &ctxt_, // phNewContext
+ &out_buffer_desc, // pOutput
+ &context_attribute, // pfContextAttr
+ nullptr); // ptsExpiry
int rv = MapInitializeSecurityContextStatusToError(status);
if (rv != OK) {
ResetSecurityContext();
diff --git a/chromium/net/http/http_auth_sspi_win.h b/chromium/net/http/http_auth_sspi_win.h
index 1d524fa12c4..32f30dd903f 100644
--- a/chromium/net/http/http_auth_sspi_win.h
+++ b/chromium/net/http/http_auth_sspi_win.h
@@ -146,6 +146,7 @@ class NET_EXPORT_PRIVATE HttpAuthSSPI {
// credentials are used instead.
int GenerateAuthToken(const AuthCredentials* credentials,
const std::string& spn,
+ const std::string& channel_bindings,
std::string* auth_token,
const CompletionCallback& callback);
@@ -157,12 +158,12 @@ class NET_EXPORT_PRIVATE HttpAuthSSPI {
private:
int OnFirstRound(const AuthCredentials* credentials);
- int GetNextSecurityToken(
- const std::string& spn,
- const void* in_token,
- int in_token_len,
- void** out_token,
- int* out_token_len);
+ int GetNextSecurityToken(const std::string& spn,
+ const std::string& channing_bindings,
+ const void* in_token,
+ int in_token_len,
+ void** out_token,
+ int* out_token_len);
void ResetSecurityContext();
diff --git a/chromium/net/http/http_auth_sspi_win_unittest.cc b/chromium/net/http/http_auth_sspi_win_unittest.cc
index 0bb90ff70f3..c2841732283 100644
--- a/chromium/net/http/http_auth_sspi_win_unittest.cc
+++ b/chromium/net/http/http_auth_sspi_win_unittest.cc
@@ -89,7 +89,7 @@ TEST(HttpAuthSSPITest, ParseChallenge_TwoRounds) {
// Generate an auth token and create another thing.
std::string auth_token;
EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
- &auth_token,
+ std::string(), &auth_token,
base::Bind(&UnexpectedCallback)));
std::string second_challenge_text = "Negotiate Zm9vYmFy";
@@ -126,7 +126,7 @@ TEST(HttpAuthSSPITest, ParseChallenge_MissingTokenSecondRound) {
std::string auth_token;
EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
- &auth_token,
+ std::string(), &auth_token,
base::Bind(&UnexpectedCallback)));
std::string second_challenge_text = "Negotiate";
HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
@@ -149,7 +149,7 @@ TEST(HttpAuthSSPITest, ParseChallenge_NonBase64EncodedToken) {
std::string auth_token;
EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
- &auth_token,
+ std::string(), &auth_token,
base::Bind(&UnexpectedCallback)));
std::string second_challenge_text = "Negotiate =happyjoy=";
HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
diff --git a/chromium/net/http/http_auth_unittest.cc b/chromium/net/http/http_auth_unittest.cc
index c550803857b..82b37411814 100644
--- a/chromium/net/http/http_auth_unittest.cc
+++ b/chromium/net/http/http_auth_unittest.cc
@@ -20,6 +20,7 @@
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/http/mock_allow_http_auth_preferences.h"
+#include "net/ssl/ssl_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -33,10 +34,9 @@ HttpAuthHandlerMock* CreateMockHandler(bool connection_based) {
HttpAuthChallengeTokenizer challenge(challenge_text.begin(),
challenge_text.end());
GURL origin("www.example.com");
- EXPECT_TRUE(auth_handler->InitFromChallenge(&challenge,
- HttpAuth::AUTH_SERVER,
- origin,
- BoundNetLog()));
+ SSLInfo null_ssl_info;
+ EXPECT_TRUE(auth_handler->InitFromChallenge(
+ &challenge, HttpAuth::AUTH_SERVER, null_ssl_info, origin, BoundNetLog()));
return auth_handler;
}
@@ -54,12 +54,9 @@ HttpAuth::AuthorizationResult HandleChallengeResponse(
std::set<HttpAuth::Scheme> disabled_schemes;
scoped_refptr<HttpResponseHeaders> headers(
HeadersFromResponseText(headers_text));
- return HttpAuth::HandleChallengeResponse(
- mock_handler.get(),
- headers.get(),
- HttpAuth::AUTH_SERVER,
- disabled_schemes,
- challenge_used);
+ return HttpAuth::HandleChallengeResponse(mock_handler.get(), *headers,
+ HttpAuth::AUTH_SERVER,
+ disabled_schemes, challenge_used);
}
} // namespace
@@ -136,14 +133,11 @@ TEST(HttpAuthTest, ChooseBestChallenge) {
scoped_refptr<HttpResponseHeaders> headers(
HeadersFromResponseText(headers_with_status_line));
+ SSLInfo null_ssl_info;
scoped_ptr<HttpAuthHandler> handler;
- HttpAuth::ChooseBestChallenge(http_auth_handler_factory.get(),
- headers.get(),
- HttpAuth::AUTH_SERVER,
- origin,
- disabled_schemes,
- BoundNetLog(),
- &handler);
+ HttpAuth::ChooseBestChallenge(http_auth_handler_factory.get(), *headers,
+ null_ssl_info, HttpAuth::AUTH_SERVER, origin,
+ disabled_schemes, BoundNetLog(), &handler);
if (handler.get()) {
EXPECT_EQ(tests[i].challenge_scheme, handler->auth_scheme());
diff --git a/chromium/net/http/http_basic_stream.cc b/chromium/net/http/http_basic_stream.cc
index 260ad55f2f5..0dd7a9e1dcd 100644
--- a/chromium/net/http/http_basic_stream.cc
+++ b/chromium/net/http/http_basic_stream.cc
@@ -111,13 +111,19 @@ bool HttpBasicStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
return state_.connection()->socket()->GetPeerAddress(endpoint) == OK;
}
+Error HttpBasicStream::GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ return parser()->GetSignedEKMForTokenBinding(key, out);
+}
+
void HttpBasicStream::Drain(HttpNetworkSession* session) {
HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(this);
drainer->Start(session);
// |drainer| will delete itself.
}
-void HttpBasicStream::PopulateNetErrorDetails(NetErrorDetails* /*details*/) {
+void HttpBasicStream::PopulateNetErrorDetails(NetErrorDetails* details) {
+ details->connection_info = HttpResponseInfo::CONNECTION_INFO_HTTP1;
return;
}
diff --git a/chromium/net/http/http_basic_stream.h b/chromium/net/http/http_basic_stream.h
index 0ca196250b5..1bb9a0be7cc 100644
--- a/chromium/net/http/http_basic_stream.h
+++ b/chromium/net/http/http_basic_stream.h
@@ -76,6 +76,9 @@ class HttpBasicStream : public HttpStream {
bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override;
+
void Drain(HttpNetworkSession* session) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
diff --git a/chromium/net/http/http_cache.cc b/chromium/net/http/http_cache.cc
index ae678fd2f8b..f572c14f569 100644
--- a/chromium/net/http/http_cache.cc
+++ b/chromium/net/http/http_cache.cc
@@ -34,7 +34,6 @@
#include "net/base/net_errors.h"
#include "net/base/upload_data_stream.h"
#include "net/disk_cache/disk_cache.h"
-#include "net/http/disk_based_cert_cache.h"
#include "net/http/disk_cache_based_quic_server_info.h"
#include "net/http/http_cache_transaction.h"
#include "net/http/http_network_layer.h"
@@ -49,15 +48,6 @@
#include <unistd.h>
#endif
-namespace {
-
-bool UseCertCache() {
- return base::FieldTrialList::FindFullName("CertCacheTrial") ==
- "ExperimentGroup";
-}
-
-} // namespace
-
namespace net {
HttpCache::DefaultBackend::DefaultBackend(
@@ -354,7 +344,6 @@ HttpCache::~HttpCache() {
// Before deleting pending_ops_, we have to make sure that the disk cache is
// done with said operations, or it will attempt to use deleted data.
- cert_cache_.reset();
disk_cache_.reset();
PendingOpsMap::iterator pending_it = pending_ops_.begin();
@@ -1144,8 +1133,6 @@ void HttpCache::OnBackendCreated(int result, PendingOp* pending_op) {
backend_factory_.reset(); // Reclaim memory.
if (result == OK) {
disk_cache_ = std::move(pending_op->backend);
- if (UseCertCache())
- cert_cache_.reset(new DiskBasedCertCache(disk_cache_.get()));
}
}
diff --git a/chromium/net/http/http_cache.h b/chromium/net/http/http_cache.h
index 618709adc8e..1c9c8910fa8 100644
--- a/chromium/net/http/http_cache.h
+++ b/chromium/net/http/http_cache.h
@@ -49,7 +49,6 @@ namespace net {
class CertVerifier;
class ChannelIDService;
-class DiskBasedCertCache;
class HostResolver;
class HttpAuthHandlerFactory;
class HttpNetworkSession;
@@ -149,8 +148,6 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
HttpTransactionFactory* network_layer() { return network_layer_.get(); }
- DiskBasedCertCache* cert_cache() const { return cert_cache_.get(); }
-
// Retrieves the cache backend for this HttpCache instance. If the backend
// is not initialized yet, this method will initialize it. The return value is
// a network error code, and it could be ERR_IO_PENDING, in which case the
@@ -419,8 +416,6 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory,
scoped_ptr<disk_cache::Backend> disk_cache_;
- scoped_ptr<DiskBasedCertCache> cert_cache_;
-
// The set of active entries indexed by cache key.
ActiveEntriesMap active_entries_;
diff --git a/chromium/net/http/http_cache_transaction.cc b/chromium/net/http/http_cache_transaction.cc
index 3b9f28dc30c..178df98d6e1 100644
--- a/chromium/net/http/http_cache_transaction.cc
+++ b/chromium/net/http/http_cache_transaction.cc
@@ -36,7 +36,6 @@
#include "net/cert/cert_status_flags.h"
#include "net/cert/x509_certificate.h"
#include "net/disk_cache/disk_cache.h"
-#include "net/http/disk_based_cert_cache.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_info.h"
#include "net/http/http_util.h"
@@ -54,111 +53,6 @@ namespace {
// TODO(ricea): Move this to HttpResponseHeaders once it is standardised.
static const char kFreshnessHeader[] = "Resource-Freshness";
-// Stores data relevant to the statistics of writing and reading entire
-// certificate chains using DiskBasedCertCache. |num_pending_ops| is the number
-// of certificates in the chain that have pending operations in the
-// DiskBasedCertCache. |start_time| is the time that the read and write
-// commands began being issued to the DiskBasedCertCache.
-// TODO(brandonsalmon): Remove this when it is no longer necessary to
-// collect data.
-class SharedChainData : public base::RefCounted<SharedChainData> {
- public:
- SharedChainData(int num_ops, TimeTicks start)
- : num_pending_ops(num_ops), start_time(start) {}
-
- int num_pending_ops;
- TimeTicks start_time;
-
- private:
- friend class base::RefCounted<SharedChainData>;
- ~SharedChainData() {}
- DISALLOW_COPY_AND_ASSIGN(SharedChainData);
-};
-
-// Used to obtain a cache entry key for an OSCertHandle.
-// TODO(brandonsalmon): Remove this when cache keys are stored
-// and no longer have to be recomputed to retrieve the OSCertHandle
-// from the disk.
-std::string GetCacheKeyForCert(X509Certificate::OSCertHandle cert_handle) {
- SHA1HashValue fingerprint =
- X509Certificate::CalculateFingerprint(cert_handle);
-
- return "cert:" +
- base::HexEncode(fingerprint.data, arraysize(fingerprint.data));
-}
-
-// |dist_from_root| indicates the position of the read certificate in the
-// certificate chain, 0 indicating it is the root. |is_leaf| indicates
-// whether or not the read certificate was the leaf of the chain.
-// |shared_chain_data| contains data shared by each certificate in
-// the chain.
-void OnCertReadIOComplete(
- int dist_from_root,
- bool is_leaf,
- const scoped_refptr<SharedChainData>& shared_chain_data,
- X509Certificate::OSCertHandle cert_handle) {
- // If |num_pending_ops| is one, this was the last pending read operation
- // for this chain of certificates. The total time used to read the chain
- // can be calculated by subtracting the starting time from Now().
- shared_chain_data->num_pending_ops--;
- if (!shared_chain_data->num_pending_ops) {
- const TimeDelta read_chain_wait =
- TimeTicks::Now() - shared_chain_data->start_time;
- UMA_HISTOGRAM_CUSTOM_TIMES("DiskBasedCertCache.ChainReadTime",
- read_chain_wait,
- base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromMinutes(10),
- 50);
- }
-
- bool success = (cert_handle != NULL);
- if (is_leaf)
- UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.CertIoReadSuccessLeaf", success);
-
- if (success)
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "DiskBasedCertCache.CertIoReadSuccess", dist_from_root, 0, 10, 7);
- else
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "DiskBasedCertCache.CertIoReadFailure", dist_from_root, 0, 10, 7);
-}
-
-// |dist_from_root| indicates the position of the written certificate in the
-// certificate chain, 0 indicating it is the root. |is_leaf| indicates
-// whether or not the written certificate was the leaf of the chain.
-// |shared_chain_data| contains data shared by each certificate in
-// the chain.
-void OnCertWriteIOComplete(
- int dist_from_root,
- bool is_leaf,
- const scoped_refptr<SharedChainData>& shared_chain_data,
- const std::string& key) {
- // If |num_pending_ops| is one, this was the last pending write operation
- // for this chain of certificates. The total time used to write the chain
- // can be calculated by subtracting the starting time from Now().
- shared_chain_data->num_pending_ops--;
- if (!shared_chain_data->num_pending_ops) {
- const TimeDelta write_chain_wait =
- TimeTicks::Now() - shared_chain_data->start_time;
- UMA_HISTOGRAM_CUSTOM_TIMES("DiskBasedCertCache.ChainWriteTime",
- write_chain_wait,
- base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromMinutes(10),
- 50);
- }
-
- bool success = !key.empty();
- if (is_leaf)
- UMA_HISTOGRAM_BOOLEAN("DiskBasedCertCache.CertIoWriteSuccessLeaf", success);
-
- if (success)
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "DiskBasedCertCache.CertIoWriteSuccess", dist_from_root, 0, 10, 7);
- else
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "DiskBasedCertCache.CertIoWriteFailure", dist_from_root, 0, 10, 7);
-}
-
// From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6
// a "non-error response" is one with a 2xx (Successful) or 3xx
// (Redirection) status code.
@@ -1276,10 +1170,6 @@ int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
return OnCacheReadError(result, true);
}
- // cert_cache() will be null if the CertCacheTrial field trial is disabled.
- if (cache_->cert_cache() && response_.ssl_info.is_valid())
- ReadCertChain();
-
// Some resources may have slipped in as truncated when they're not.
int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
if (response_.headers->GetContentLength() == current_size)
@@ -1919,63 +1809,6 @@ int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) {
//-----------------------------------------------------------------------------
-void HttpCache::Transaction::ReadCertChain() {
- std::string key =
- GetCacheKeyForCert(response_.ssl_info.cert->os_cert_handle());
- const X509Certificate::OSCertHandles& intermediates =
- response_.ssl_info.cert->GetIntermediateCertificates();
- int dist_from_root = intermediates.size();
-
- scoped_refptr<SharedChainData> shared_chain_data(
- new SharedChainData(intermediates.size() + 1, TimeTicks::Now()));
- cache_->cert_cache()->GetCertificate(key,
- base::Bind(&OnCertReadIOComplete,
- dist_from_root,
- true /* is leaf */,
- shared_chain_data));
-
- for (X509Certificate::OSCertHandles::const_iterator it =
- intermediates.begin();
- it != intermediates.end();
- ++it) {
- --dist_from_root;
- key = GetCacheKeyForCert(*it);
- cache_->cert_cache()->GetCertificate(key,
- base::Bind(&OnCertReadIOComplete,
- dist_from_root,
- false /* is not leaf */,
- shared_chain_data));
- }
- DCHECK_EQ(0, dist_from_root);
-}
-
-void HttpCache::Transaction::WriteCertChain() {
- const X509Certificate::OSCertHandles& intermediates =
- response_.ssl_info.cert->GetIntermediateCertificates();
- int dist_from_root = intermediates.size();
-
- scoped_refptr<SharedChainData> shared_chain_data(
- new SharedChainData(intermediates.size() + 1, TimeTicks::Now()));
- cache_->cert_cache()->SetCertificate(
- response_.ssl_info.cert->os_cert_handle(),
- base::Bind(&OnCertWriteIOComplete,
- dist_from_root,
- true /* is leaf */,
- shared_chain_data));
- for (X509Certificate::OSCertHandles::const_iterator it =
- intermediates.begin();
- it != intermediates.end();
- ++it) {
- --dist_from_root;
- cache_->cert_cache()->SetCertificate(*it,
- base::Bind(&OnCertWriteIOComplete,
- dist_from_root,
- false /* is not leaf */,
- shared_chain_data));
- }
- DCHECK_EQ(0, dist_from_root);
-}
-
void HttpCache::Transaction::SetRequest(const BoundNetLog& net_log,
const HttpRequestInfo* request) {
net_log_ = net_log;
@@ -2663,10 +2496,6 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) {
return OK;
}
- // cert_cache() will be null if the CertCacheTrial field trial is disabled.
- if (cache_->cert_cache() && response_.ssl_info.is_valid())
- WriteCertChain();
-
if (truncated)
DCHECK_EQ(200, response_.headers->response_code());
@@ -2875,6 +2704,39 @@ void HttpCache::Transaction::RecordHistograms() {
cache_->mode() != NORMAL || request_->method != "GET") {
return;
}
+
+ std::string mime_type;
+ if (GetResponseInfo()->headers &&
+ GetResponseInfo()->headers->GetMimeType(&mime_type)) {
+ // Record the cache pattern by resource type. The type is inferred by
+ // response header mime type, which could be incorrect, so this is just an
+ // estimate.
+ if (mime_type == "text/html" && (request_->load_flags & LOAD_MAIN_FRAME)) {
+ UMA_HISTOGRAM_ENUMERATION(std::string("HttpCache.Pattern.MainFrameHTML"),
+ transaction_pattern_, PATTERN_MAX);
+ } else if (mime_type == "text/html") {
+ UMA_HISTOGRAM_ENUMERATION(
+ std::string("HttpCache.Pattern.NonMainFrameHTML"),
+ transaction_pattern_, PATTERN_MAX);
+ } else if (mime_type == "text/css") {
+ UMA_HISTOGRAM_ENUMERATION(std::string("HttpCache.Pattern.CSS"),
+ transaction_pattern_, PATTERN_MAX);
+ } else if (base::StartsWith(mime_type, "image/",
+ base::CompareCase::SENSITIVE)) {
+ UMA_HISTOGRAM_ENUMERATION(std::string("HttpCache.Pattern.Image"),
+ transaction_pattern_, PATTERN_MAX);
+ } else if (base::EndsWith(mime_type, "javascript",
+ base::CompareCase::SENSITIVE) ||
+ base::EndsWith(mime_type, "ecmascript",
+ base::CompareCase::SENSITIVE)) {
+ UMA_HISTOGRAM_ENUMERATION(std::string("HttpCache.Pattern.JavaScript"),
+ transaction_pattern_, PATTERN_MAX);
+ } else if (mime_type.find("font") != std::string::npos) {
+ UMA_HISTOGRAM_ENUMERATION(std::string("HttpCache.Pattern.Font"),
+ transaction_pattern_, PATTERN_MAX);
+ }
+ }
+
UMA_HISTOGRAM_ENUMERATION(
"HttpCache.Pattern", transaction_pattern_, PATTERN_MAX);
if (transaction_pattern_ == PATTERN_NOT_COVERED)
diff --git a/chromium/net/http/http_cache_transaction.h b/chromium/net/http/http_cache_transaction.h
index 175e3f948be..b3c90e94578 100644
--- a/chromium/net/http/http_cache_transaction.h
+++ b/chromium/net/http/http_cache_transaction.h
@@ -299,11 +299,6 @@ class HttpCache::Transaction : public HttpTransaction {
int DoCacheWriteTruncatedResponse();
int DoCacheWriteTruncatedResponseComplete(int result);
- // These functions are involved in a field trial testing storing certificates
- // in seperate entries from the HttpResponseInfo.
- void ReadCertChain();
- void WriteCertChain();
-
// Sets request_ and fields derived from it.
void SetRequest(const BoundNetLog& net_log, const HttpRequestInfo* request);
diff --git a/chromium/net/http/http_chunked_decoder_fuzzer.cc b/chromium/net/http/http_chunked_decoder_fuzzer.cc
new file mode 100644
index 00000000000..91506579672
--- /dev/null
+++ b/chromium/net/http/http_chunked_decoder_fuzzer.cc
@@ -0,0 +1,45 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <vector>
+
+#include "net/http/http_chunked_decoder.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ const char* data_ptr = reinterpret_cast<const char*>(data);
+ net::HttpChunkedDecoder decoder;
+
+ // Feed data to decoder.FilterBuf() by blocks of "random" size.
+ size_t block_size = 0;
+ for (size_t offset = 0; offset < size; offset += block_size) {
+ // Since there is no input for block_size values, but it should be strictly
+ // determined, let's calculate these values using a couple of data bytes.
+ uint8_t temp_block_size = data[offset] ^ data[size - offset - 1];
+
+ // Let temp_block_size be in range from 0 to 0x3F (0b00111111).
+ temp_block_size &= 0x3F;
+
+ // XOR with previous block size to get different values for different data.
+ block_size ^= temp_block_size;
+
+ // Prevent infinite loop if block_size == 0.
+ block_size = std::max(block_size, static_cast<size_t>(1));
+
+ // Prevent out-of-bounds access.
+ block_size = std::min(block_size, size - offset);
+
+ // Create new buffer with current block of data and feed it to the decoder.
+ std::vector<char> buffer(data_ptr + offset, data_ptr + offset + block_size);
+ int result = decoder.FilterBuf(buffer.data(), buffer.size());
+ if (result < 0)
+ return 0;
+ }
+
+ return 0;
+}
diff --git a/chromium/net/http/http_chunked_decoder_fuzzer.dict b/chromium/net/http/http_chunked_decoder_fuzzer.dict
new file mode 100644
index 00000000000..f8552c9cff6
--- /dev/null
+++ b/chromium/net/http/http_chunked_decoder_fuzzer.dict
@@ -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.
+
+"0"
+"1"
+"2"
+"3"
+"4"
+"5"
+"6"
+"7"
+"8"
+"9"
+"\x0a"
+"\x0d"
+"0x"
+"a"
+"b"
+"c"
+"d"
+"e"
+"f"
+"A"
+"B"
+"C"
+"D"
+"E"
+"F"
+"+"
+"-"
+"="
+":"
+";"
diff --git a/chromium/net/http/http_content_disposition.cc b/chromium/net/http/http_content_disposition.cc
index bef2d44a146..3f7d6b5f8a1 100644
--- a/chromium/net/http/http_content_disposition.cc
+++ b/chromium/net/http/http_content_disposition.cc
@@ -12,7 +12,6 @@
#include "base/strings/utf_string_conversions.h"
#include "net/base/escape.h"
#include "net/base/net_string_util.h"
-#include "net/base/net_util.h"
#include "net/http/http_util.h"
namespace net {
@@ -324,7 +323,8 @@ bool DecodeExtValue(const std::string& param_value, std::string* decoded) {
}
std::string unescaped = UnescapeURLComponent(
- value, UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS);
+ value, UnescapeRule::SPACES |
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS);
return ConvertToUtf8AndNormalize(unescaped, charset.c_str(), decoded);
}
diff --git a/chromium/net/http/http_network_session.cc b/chromium/net/http/http_network_session.cc
index 935453e5235..9d3a2292de2 100644
--- a/chromium/net/http/http_network_session.cc
+++ b/chromium/net/http/http_network_session.cc
@@ -81,7 +81,6 @@ HttpNetworkSession::Params::Params()
proxy_service(NULL),
ssl_config_service(NULL),
http_auth_handler_factory(NULL),
- network_delegate(NULL),
net_log(NULL),
host_mapping_rules(NULL),
socket_performance_watcher_factory(NULL),
@@ -89,18 +88,20 @@ HttpNetworkSession::Params::Params()
testing_fixed_http_port(0),
testing_fixed_https_port(0),
enable_tcp_fast_open_for_ssl(false),
- enable_spdy_compression(true),
enable_spdy_ping_based_connection_checking(true),
spdy_default_protocol(kProtoUnknown),
+ enable_spdy31(false),
+ enable_http2(true),
spdy_session_max_recv_window_size(kSpdySessionMaxRecvWindowSize),
spdy_stream_max_recv_window_size(kSpdyStreamMaxRecvWindowSize),
- spdy_initial_max_concurrent_streams(0),
time_func(&base::TimeTicks::Now),
- use_alternative_services(false),
- alternative_service_probability_threshold(1),
- enable_npn(true),
+ parse_alternative_services(false),
+ enable_alternative_service_with_different_host(false),
+ enable_npn(false),
enable_brotli(false),
+ enable_priority_dependencies(true),
enable_quic(false),
+ disable_quic_on_timeout_with_open_streams(false),
enable_quic_for_proxies(false),
enable_quic_port_selection(true),
quic_always_require_handshake_confirmation(false),
@@ -128,16 +129,20 @@ HttpNetworkSession::Params::Params()
quic_idle_connection_timeout_seconds(kIdleConnectionTimeoutSeconds),
quic_disable_preconnect_if_0rtt(false),
quic_migrate_sessions_on_network_change(false),
- proxy_delegate(NULL) {
- quic_supported_versions.push_back(QUIC_VERSION_25);
+ quic_migrate_sessions_early(false),
+ quic_disable_bidirectional_streams(false),
+ proxy_delegate(NULL),
+ enable_token_binding(false) {
+ quic_supported_versions.push_back(QUIC_VERSION_30);
}
+HttpNetworkSession::Params::Params(const Params& other) = default;
+
HttpNetworkSession::Params::~Params() {}
// TODO(mbelshe): Move the socket factories into HttpStreamFactory.
HttpNetworkSession::HttpNetworkSession(const Params& params)
: net_log_(params.net_log),
- network_delegate_(params.network_delegate),
http_server_properties_(params.http_server_properties),
cert_verifier_(params.cert_verifier),
http_auth_handler_factory_(params.http_auth_handler_factory),
@@ -178,21 +183,23 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
params.quic_delay_tcp_race,
params.quic_max_server_configs_stored_in_properties,
params.quic_close_sessions_on_ip_change,
+ params.disable_quic_on_timeout_with_open_streams,
params.quic_idle_connection_timeout_seconds,
params.quic_migrate_sessions_on_network_change,
- params.quic_connection_options),
+ params.quic_migrate_sessions_early,
+ params.quic_connection_options,
+ params.enable_token_binding),
spdy_session_pool_(params.host_resolver,
params.ssl_config_service,
params.http_server_properties,
params.transport_security_state,
- params.enable_spdy_compression,
params.enable_spdy_ping_based_connection_checking,
+ params.enable_priority_dependencies,
params.spdy_default_protocol,
params.spdy_session_max_recv_window_size,
params.spdy_stream_max_recv_window_size,
- params.spdy_initial_max_concurrent_streams,
params.time_func,
- params.trusted_spdy_proxy),
+ params.proxy_delegate),
http_stream_factory_(new HttpStreamFactoryImpl(this, false)),
http_stream_factory_for_websocket_(new HttpStreamFactoryImpl(this, true)),
params_(params) {
@@ -212,33 +219,31 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
enabled_protocols_[i - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] = false;
}
- // TODO(rtenneti): bug 116575 - consider combining the NextProto and
- // AlternateProtocol.
- for (std::vector<NextProto>::const_iterator it = params_.next_protos.begin();
- it != params_.next_protos.end(); ++it) {
- NextProto proto = *it;
-
- // Add the protocol to the TLS next protocol list, except for QUIC
- // since it uses UDP.
- if (proto != kProtoQUIC1SPDY3) {
- next_protos_.push_back(proto);
- }
-
- // Enable the corresponding alternate protocol, except for HTTP
- // which has not corresponding alternative.
- if (proto != kProtoHTTP11) {
- AlternateProtocol alternate = AlternateProtocolFromNextProto(proto);
- if (!IsAlternateProtocolValid(alternate)) {
- NOTREACHED() << "Invalid next proto: " << proto;
- continue;
- }
- enabled_protocols_[alternate - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] =
- true;
- }
+ // TODO(rtenneti): https://crbug.com/116575
+ // Consider combining the NextProto and AlternateProtocol.
+ if (params_.enable_http2) {
+ next_protos_.push_back(kProtoHTTP2);
+ AlternateProtocol alternate = AlternateProtocolFromNextProto(kProtoHTTP2);
+ enabled_protocols_[alternate - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] =
+ true;
+ }
+
+ if (params_.enable_spdy31) {
+ next_protos_.push_back(kProtoSPDY31);
+ AlternateProtocol alternate = AlternateProtocolFromNextProto(kProtoSPDY31);
+ enabled_protocols_[alternate - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] =
+ true;
}
- http_server_properties_->SetAlternativeServiceProbabilityThreshold(
- params.alternative_service_probability_threshold);
+ if (params_.enable_quic) {
+ AlternateProtocol alternate =
+ AlternateProtocolFromNextProto(kProtoQUIC1SPDY3);
+ enabled_protocols_[alternate - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] =
+ true;
+ }
+
+ next_protos_.push_back(kProtoHTTP11);
+
http_server_properties_->SetMaxServerConfigsStoredInProperties(
params.quic_max_server_configs_stored_in_properties);
}
@@ -312,10 +317,13 @@ scoped_ptr<base::Value> HttpNetworkSession::QuicInfoToValue() const {
connection_options->AppendString("'" + QuicUtils::TagToString(*it) + "'");
}
dict->Set("connection_options", std::move(connection_options));
- dict->SetString("origin_to_force_quic_on",
- params_.origin_to_force_quic_on.ToString());
- dict->SetDouble("alternative_service_probability_threshold",
- params_.alternative_service_probability_threshold);
+
+ scoped_ptr<base::ListValue> origins_to_force_quic_on(new base::ListValue);
+ for (const auto& origin : params_.origins_to_force_quic_on) {
+ origins_to_force_quic_on->AppendString("'" + origin.ToString() + "'");
+ }
+ dict->Set("origins_to_force_quic_on", std::move(origins_to_force_quic_on));
+
dict->SetDouble("load_server_info_timeout_srtt_multiplier",
params_.quic_load_server_info_timeout_srtt_multiplier);
dict->SetBoolean("enable_connection_racing",
@@ -332,6 +340,8 @@ scoped_ptr<base::Value> HttpNetworkSession::QuicInfoToValue() const {
params_.quic_idle_connection_timeout_seconds);
dict->SetBoolean("disable_preconnect_if_0rtt",
params_.quic_disable_preconnect_if_0rtt);
+ dict->SetBoolean("disable_quic_on_timeout_with_open_streams",
+ params_.disable_quic_on_timeout_with_open_streams);
dict->SetString("disabled_reason",
quic_stream_factory_.QuicDisabledReasonString());
return std::move(dict);
@@ -372,12 +382,6 @@ void HttpNetworkSession::GetNpnProtos(NextProtoVector* npn_protos) const {
}
}
-bool HttpNetworkSession::HasSpdyExclusion(
- HostPortPair host_port_pair) const {
- return params_.forced_spdy_exclusions.find(host_port_pair) !=
- params_.forced_spdy_exclusions.end();
-}
-
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 9f984896382..c77953924bc 100644
--- a/chromium/net/http/http_network_session.h
+++ b/chromium/net/http/http_network_session.h
@@ -45,7 +45,6 @@ class HttpProxyClientSocketPool;
class HttpResponseBodyDrainer;
class HttpServerProperties;
class NetLog;
-class NetworkDelegate;
class ProxyDelegate;
class ProxyService;
class QuicClock;
@@ -64,6 +63,7 @@ class NET_EXPORT HttpNetworkSession
public:
struct NET_EXPORT Params {
Params();
+ Params(const Params& other);
~Params();
ClientSocketFactory* client_socket_factory;
@@ -76,7 +76,6 @@ class NET_EXPORT HttpNetworkSession
ProxyService* proxy_service;
SSLConfigService* ssl_config_service;
HttpAuthHandlerFactory* http_auth_handler_factory;
- NetworkDelegate* network_delegate;
base::WeakPtr<HttpServerProperties> http_server_properties;
NetLog* net_log;
HostMappingRules* host_mapping_rules;
@@ -86,32 +85,20 @@ class NET_EXPORT HttpNetworkSession
uint16_t testing_fixed_https_port;
bool enable_tcp_fast_open_for_ssl;
- // Compress SPDY headers.
- bool enable_spdy_compression;
// Use SPDY ping frames to test for connection health after idle.
bool enable_spdy_ping_based_connection_checking;
NextProto spdy_default_protocol;
- // The protocols supported by NPN (next protocol negotiation) during the
- // SSL handshake as well as by HTTP Alternate-Protocol.
- // TODO(mmenke): This is currently empty by default, and alternate
- // protocols are disabled. We should use some reasonable
- // defaults.
- NextProtoVector next_protos;
+ bool enable_spdy31;
+ bool enable_http2;
size_t spdy_session_max_recv_window_size;
size_t spdy_stream_max_recv_window_size;
- size_t spdy_initial_max_concurrent_streams;
// Source of time for SPDY connections.
SpdySessionPool::TimeFunc time_func;
- // This SPDY proxy is allowed to push resources from origins that are
- // different from those of their associated streams.
- std::string trusted_spdy_proxy;
- // URLs to exclude from forced SPDY.
- std::set<HostPortPair> forced_spdy_exclusions;
- // Process Alt-Svc headers.
- bool use_alternative_services;
- // Only honor alternative service entries which have a higher probability
- // than this value.
- double alternative_service_probability_threshold;
+ // Whether to parse Alt-Svc headers.
+ bool parse_alternative_services;
+ // Whether to enable Alt-Svc entries with hostname different than that of
+ // the origin.
+ bool enable_alternative_service_with_different_host;
// Enables NPN support. Note that ALPN is always enabled.
bool enable_npn;
@@ -119,8 +106,13 @@ class NET_EXPORT HttpNetworkSession
// Enables Brotli Content-Encoding support.
bool enable_brotli;
+ // Enable setting of HTTP/2 dependencies based on priority.
+ bool enable_priority_dependencies;
+
// Enables QUIC support.
bool enable_quic;
+ // Disable QUIC if a connection times out with open streams.
+ bool disable_quic_on_timeout_with_open_streams;
// Enables QUIC for proxies.
bool enable_quic_for_proxies;
// Instruct QUIC to use consistent ephemeral ports when talking to
@@ -157,8 +149,9 @@ class NET_EXPORT HttpNetworkSession
// Maximum number of server configs that are to be stored in
// HttpServerProperties, instead of the disk cache.
size_t quic_max_server_configs_stored_in_properties;
- // If not empty, QUIC will be used for all connections to this origin.
- HostPortPair origin_to_force_quic_on;
+ // If not empty, QUIC will be used for all connections to the set of
+ // origins in |origins_to_force_quic_on|.
+ std::set<HostPortPair> origins_to_force_quic_on;
// Source of time for QUIC connections. Will be owned by QuicStreamFactory.
QuicClock* quic_clock;
// Source of entropy for QUIC connections.
@@ -185,10 +178,18 @@ class NET_EXPORT HttpNetworkSession
bool quic_disable_preconnect_if_0rtt;
// List of hosts for which QUIC is explicitly whitelisted.
std::unordered_set<std::string> quic_host_whitelist;
- // If true, active QUIC sessions may be migrated onto new IPs when network
- // changes.
+ // If true, active QUIC sessions may be migrated onto a new network when
+ // the platform indicates that the default network is changing.
bool quic_migrate_sessions_on_network_change;
+ // If true, active QUIC sessions experiencing poor connectivity may be
+ // migrated onto a new network.
+ bool quic_migrate_sessions_early;
+ // If true, bidirectional streams over QUIC will be disabled.
+ bool quic_disable_bidirectional_streams;
+
ProxyDelegate* proxy_delegate;
+ // Enable support for Token Binding.
+ bool enable_token_binding;
};
enum SocketPoolType {
@@ -229,9 +230,6 @@ class NET_EXPORT HttpNetworkSession
HttpAuthHandlerFactory* http_auth_handler_factory() {
return http_auth_handler_factory_;
}
- NetworkDelegate* network_delegate() {
- return network_delegate_;
- }
base::WeakPtr<HttpServerProperties> http_server_properties() {
return http_server_properties_;
}
@@ -269,17 +267,12 @@ class NET_EXPORT HttpNetworkSession
// Populates |*npn_protos| with protocols to be used with NPN.
void GetNpnProtos(NextProtoVector* npn_protos) const;
- // Convenience function for searching through |params_| for
- // |forced_spdy_exclusions|.
- bool HasSpdyExclusion(HostPortPair host_port_pair) const;
-
private:
friend class HttpNetworkSessionPeer;
ClientSocketPoolManager* GetSocketPoolManager(SocketPoolType pool_type);
NetLog* const net_log_;
- NetworkDelegate* const network_delegate_;
const base::WeakPtr<HttpServerProperties> http_server_properties_;
CertVerifier* const cert_verifier_;
HttpAuthHandlerFactory* const http_auth_handler_factory_;
diff --git a/chromium/net/http/http_network_transaction.cc b/chromium/net/http/http_network_transaction.cc
index 201e3915a24..ebbe1552250 100644
--- a/chromium/net/http/http_network_transaction.cc
+++ b/chromium/net/http/http_network_transaction.cc
@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
+#include "base/base64url.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
@@ -30,8 +31,8 @@
#include "net/base/load_flags.h"
#include "net/base/load_timing_info.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/upload_data_stream.h"
+#include "net/base/url_util.h"
#include "net/http/http_auth.h"
#include "net/http/http_auth_handler.h"
#include "net/http/http_auth_handler_factory.h"
@@ -62,6 +63,7 @@
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_private_key.h"
+#include "net/ssl/token_binding.h"
#include "url/gurl.h"
#include "url/url_canon.h"
@@ -69,43 +71,6 @@ namespace net {
namespace {
-void ProcessAlternativeServices(HttpNetworkSession* session,
- const HttpResponseHeaders& headers,
- const HostPortPair& http_host_port_pair) {
- if (session->params().use_alternative_services &&
- headers.HasHeader(kAlternativeServiceHeader)) {
- std::string alternative_service_str;
- headers.GetNormalizedHeader(kAlternativeServiceHeader,
- &alternative_service_str);
- session->http_stream_factory()->ProcessAlternativeService(
- session->http_server_properties(), alternative_service_str,
- http_host_port_pair, *session);
- // If there is an "Alt-Svc" header, then ignore "Alternate-Protocol".
- return;
- }
-
- if (!headers.HasHeader(kAlternateProtocolHeader))
- return;
-
- std::vector<std::string> alternate_protocol_values;
- void* iter = NULL;
- std::string alternate_protocol_str;
- while (headers.EnumerateHeader(&iter, kAlternateProtocolHeader,
- &alternate_protocol_str)) {
- base::TrimWhitespaceASCII(alternate_protocol_str, base::TRIM_ALL,
- &alternate_protocol_str);
- if (!alternate_protocol_str.empty()) {
- alternate_protocol_values.push_back(alternate_protocol_str);
- }
- }
-
- session->http_stream_factory()->ProcessAlternateProtocol(
- session->http_server_properties(),
- alternate_protocol_values,
- http_host_port_pair,
- *session);
-}
-
scoped_ptr<base::Value> NetLogSSLVersionFallbackCallback(
const GURL* url,
int net_error,
@@ -198,8 +163,12 @@ int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
response_.unused_since_prefetch = true;
// Channel ID is disabled if privacy mode is enabled for this request.
- if (request_->privacy_mode == PRIVACY_MODE_ENABLED)
+ if (request_->privacy_mode == PRIVACY_MODE_ENABLED) {
server_ssl_config_.channel_id_enabled = false;
+ } else if (session_->params().enable_token_binding &&
+ session_->params().channel_id_service) {
+ server_ssl_config_.token_binding_params.push_back(TB_PARAM_ECDSAP256);
+ }
next_state_ = STATE_NOTIFY_BEFORE_CREATE_STREAM;
int rv = DoLoop(OK);
@@ -525,10 +494,10 @@ void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config,
OnIOComplete(OK);
}
-void HttpNetworkTransaction::OnBidirectionalStreamJobReady(
+void HttpNetworkTransaction::OnBidirectionalStreamImplReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
- BidirectionalStreamJob* stream_job) {
+ BidirectionalStreamImpl* stream) {
NOTREACHED();
}
@@ -639,6 +608,42 @@ bool HttpNetworkTransaction::IsSecureRequest() const {
return request_->url.SchemeIsCryptographic();
}
+bool HttpNetworkTransaction::IsTokenBindingEnabled() const {
+ if (!IsSecureRequest())
+ return false;
+ SSLInfo ssl_info;
+ stream_->GetSSLInfo(&ssl_info);
+ return ssl_info.token_binding_negotiated &&
+ ssl_info.token_binding_key_param == TB_PARAM_ECDSAP256 &&
+ session_->params().channel_id_service;
+}
+
+void HttpNetworkTransaction::RecordTokenBindingSupport() const {
+ // This enum is used for an UMA histogram - do not change or re-use values.
+ enum {
+ DISABLED = 0,
+ CLIENT_ONLY = 1,
+ CLIENT_AND_SERVER = 2,
+ CLIENT_NO_CHANNEL_ID_SERVICE = 3,
+ TOKEN_BINDING_SUPPORT_MAX
+ } supported;
+ if (!IsSecureRequest())
+ return;
+ SSLInfo ssl_info;
+ stream_->GetSSLInfo(&ssl_info);
+ if (!session_->params().enable_token_binding) {
+ supported = DISABLED;
+ } else if (!session_->params().channel_id_service) {
+ supported = CLIENT_NO_CHANNEL_ID_SERVICE;
+ } else if (ssl_info.token_binding_negotiated) {
+ supported = CLIENT_AND_SERVER;
+ } else {
+ supported = CLIENT_ONLY;
+ }
+ UMA_HISTOGRAM_ENUMERATION("Net.TokenBinding.Support", supported,
+ TOKEN_BINDING_SUPPORT_MAX);
+}
+
bool HttpNetworkTransaction::UsingHttpProxyWithoutTunnel() const {
return (proxy_info_.is_http() || proxy_info_.is_https() ||
proxy_info_.is_quic()) &&
@@ -701,6 +706,20 @@ int HttpNetworkTransaction::DoLoop(int result) {
case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
rv = DoGenerateServerAuthTokenComplete(rv);
break;
+ case STATE_GET_PROVIDED_TOKEN_BINDING_KEY:
+ DCHECK_EQ(OK, rv);
+ rv = DoGetProvidedTokenBindingKey();
+ break;
+ case STATE_GET_PROVIDED_TOKEN_BINDING_KEY_COMPLETE:
+ rv = DoGetProvidedTokenBindingKeyComplete(rv);
+ break;
+ case STATE_GET_REFERRED_TOKEN_BINDING_KEY:
+ DCHECK_EQ(OK, rv);
+ rv = DoGetReferredTokenBindingKey();
+ break;
+ case STATE_GET_REFERRED_TOKEN_BINDING_KEY_COMPLETE:
+ rv = DoGetReferredTokenBindingKeyComplete(rv);
+ break;
case STATE_INIT_REQUEST_BODY:
DCHECK_EQ(OK, rv);
rv = DoInitRequestBody();
@@ -916,11 +935,58 @@ int HttpNetworkTransaction::DoGenerateServerAuthToken() {
int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
DCHECK_NE(ERR_IO_PENDING, rv);
if (rv == OK)
+ next_state_ = STATE_GET_PROVIDED_TOKEN_BINDING_KEY;
+ return rv;
+}
+
+int HttpNetworkTransaction::DoGetProvidedTokenBindingKey() {
+ next_state_ = STATE_GET_PROVIDED_TOKEN_BINDING_KEY_COMPLETE;
+ if (!IsTokenBindingEnabled())
+ return OK;
+
+ net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY);
+ ChannelIDService* channel_id_service = session_->params().channel_id_service;
+ return channel_id_service->GetOrCreateChannelID(
+ request_->url.host(), &provided_token_binding_key_, io_callback_,
+ &token_binding_request_);
+}
+
+int HttpNetworkTransaction::DoGetProvidedTokenBindingKeyComplete(int rv) {
+ DCHECK_NE(ERR_IO_PENDING, rv);
+ if (IsTokenBindingEnabled()) {
+ net_log_.EndEventWithNetErrorCode(
+ NetLog::TYPE_HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY, rv);
+ }
+
+ if (rv == OK)
+ next_state_ = STATE_GET_REFERRED_TOKEN_BINDING_KEY;
+ return rv;
+}
+
+int HttpNetworkTransaction::DoGetReferredTokenBindingKey() {
+ next_state_ = STATE_GET_REFERRED_TOKEN_BINDING_KEY_COMPLETE;
+ if (!IsTokenBindingEnabled() || request_->token_binding_referrer.empty())
+ return OK;
+
+ net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY);
+ ChannelIDService* channel_id_service = session_->params().channel_id_service;
+ return channel_id_service->GetOrCreateChannelID(
+ request_->token_binding_referrer, &referred_token_binding_key_,
+ io_callback_, &token_binding_request_);
+}
+
+int HttpNetworkTransaction::DoGetReferredTokenBindingKeyComplete(int rv) {
+ DCHECK_NE(ERR_IO_PENDING, rv);
+ if (IsTokenBindingEnabled() && !request_->token_binding_referrer.empty()) {
+ net_log_.EndEventWithNetErrorCode(
+ NetLog::TYPE_HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY, rv);
+ }
+ if (rv == OK)
next_state_ = STATE_INIT_REQUEST_BODY;
return rv;
}
-void HttpNetworkTransaction::BuildRequestHeaders(
+int HttpNetworkTransaction::BuildRequestHeaders(
bool using_http_proxy_without_tunnel) {
request_headers_.SetHeader(HttpRequestHeaders::kHost,
GetHostAndOptionalPort(request_->url));
@@ -953,6 +1019,16 @@ void HttpNetworkTransaction::BuildRequestHeaders(
request_headers_.SetHeader(HttpRequestHeaders::kContentLength, "0");
}
+ RecordTokenBindingSupport();
+ if (provided_token_binding_key_) {
+ std::string token_binding_header;
+ int rv = BuildTokenBindingHeader(&token_binding_header);
+ if (rv != OK)
+ return rv;
+ request_headers_.SetHeader(HttpRequestHeaders::kTokenBinding,
+ token_binding_header);
+ }
+
// Honor load flags that impact proxy caches.
if (request_->load_flags & LOAD_BYPASS_CACHE) {
request_headers_.SetHeader(HttpRequestHeaders::kPragma, "no-cache");
@@ -977,6 +1053,52 @@ void HttpNetworkTransaction::BuildRequestHeaders(
response_.did_use_http_auth =
request_headers_.HasHeader(HttpRequestHeaders::kAuthorization) ||
request_headers_.HasHeader(HttpRequestHeaders::kProxyAuthorization);
+ return OK;
+}
+
+int HttpNetworkTransaction::BuildTokenBindingHeader(std::string* out) {
+ base::TimeTicks start = base::TimeTicks::Now();
+ std::vector<uint8_t> signed_ekm;
+ int rv = stream_->GetSignedEKMForTokenBinding(
+ provided_token_binding_key_.get(), &signed_ekm);
+ if (rv != OK)
+ return rv;
+ std::string provided_token_binding;
+ rv = BuildTokenBinding(TokenBindingType::PROVIDED,
+ provided_token_binding_key_.get(), signed_ekm,
+ &provided_token_binding);
+ if (rv != OK)
+ return rv;
+
+ std::vector<base::StringPiece> token_bindings;
+ token_bindings.push_back(provided_token_binding);
+
+ std::string referred_token_binding;
+ if (referred_token_binding_key_) {
+ std::vector<uint8_t> referred_signed_ekm;
+ int rv = stream_->GetSignedEKMForTokenBinding(
+ referred_token_binding_key_.get(), &referred_signed_ekm);
+ if (rv != OK)
+ return rv;
+ rv = BuildTokenBinding(TokenBindingType::REFERRED,
+ referred_token_binding_key_.get(),
+ referred_signed_ekm, &referred_token_binding);
+ if (rv != OK)
+ return rv;
+ token_bindings.push_back(referred_token_binding);
+ }
+ std::string header;
+ rv = BuildTokenBindingMessageFromTokenBindings(token_bindings, &header);
+ if (rv != OK)
+ return rv;
+ base::Base64UrlEncode(header, base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ out);
+ base::TimeDelta header_creation_time = base::TimeTicks::Now() - start;
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.TokenBinding.HeaderCreationTime",
+ header_creation_time,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(1), 50);
+ return OK;
}
int HttpNetworkTransaction::DoInitRequestBody() {
@@ -1001,7 +1123,7 @@ int HttpNetworkTransaction::DoBuildRequest() {
// we have proxy info available.
if (request_headers_.IsEmpty()) {
bool using_http_proxy_without_tunnel = UsingHttpProxyWithoutTunnel();
- BuildRequestHeaders(using_http_proxy_without_tunnel);
+ return BuildRequestHeaders(using_http_proxy_without_tunnel);
}
return OK;
@@ -1125,16 +1247,16 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
return OK;
}
- ProcessAlternativeServices(session_, *response_.headers.get(),
- HostPortPair::FromURL(request_->url));
+ session_->http_stream_factory()->ProcessAlternativeServices(
+ session_, response_.headers.get(), HostPortPair::FromURL(request_->url));
+
+ if (IsSecureRequest())
+ stream_->GetSSLInfo(&response_.ssl_info);
int rv = HandleAuthChallenge();
if (rv != OK)
return rv;
- if (IsSecureRequest())
- stream_->GetSSLInfo(&response_.ssl_info);
-
headers_valid_ = true;
return OK;
}
@@ -1330,61 +1452,31 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
return OK;
}
+ // TODO(davidben): Remove this code once the dedicated error code is no
+ // longer needed and the flags to re-enable the fallback expire.
bool should_fallback = false;
uint16_t version_max = server_ssl_config_.version_max;
switch (error) {
+ // This could be a TLS-intolerant server or a server that chose a
+ // cipher suite defined only for higher protocol versions (such as
+ // an TLS 1.1 server that chose a TLS-1.2-only cipher suite). Fall
+ // back to the next lower version and retry.
case ERR_CONNECTION_CLOSED:
case ERR_SSL_PROTOCOL_ERROR:
case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
- if (version_max >= SSL_PROTOCOL_VERSION_TLS1 &&
- version_max > server_ssl_config_.version_min) {
- // This could be a TLS-intolerant server or a server that chose a
- // cipher suite defined only for higher protocol versions (such as
- // an SSL 3.0 server that chose a TLS-only cipher suite). Fall
- // back to the next lower version and retry.
- // NOTE: if the SSLClientSocket class doesn't support TLS 1.1,
- // specifying TLS 1.1 in version_max will result in a TLS 1.0
- // handshake, so falling back from TLS 1.1 to TLS 1.0 will simply
- // repeat the TLS 1.0 handshake. To avoid this problem, the default
- // version_max should match the maximum protocol version supported
- // by the SSLClientSocket class.
- version_max--;
-
- // Fallback to the lower SSL version.
- // While SSL 3.0 fallback should be eliminated because of security
- // reasons, there is a high risk of breaking the servers if this is
- // done in general.
- should_fallback = true;
- }
- break;
+ // Some servers trigger the TLS 1.1 fallback with ERR_CONNECTION_RESET
+ // (https://crbug.com/433406).
case ERR_CONNECTION_RESET:
- if (version_max >= SSL_PROTOCOL_VERSION_TLS1_1 &&
- version_max > server_ssl_config_.version_min) {
- // Some network devices that inspect application-layer packets seem to
- // inject TCP reset packets to break the connections when they see TLS
- // 1.1 in ClientHello or ServerHello. See http://crbug.com/130293.
- //
- // Only allow ERR_CONNECTION_RESET to trigger a fallback from TLS 1.1 or
- // 1.2. We don't lose much in this fallback because the explicit IV for
- // CBC mode in TLS 1.1 is approximated by record splitting in TLS
- // 1.0. The fallback will be more painful for TLS 1.2 when we have GCM
- // support.
- //
- // ERR_CONNECTION_RESET is a common network error, so we don't want it
- // to trigger a version fallback in general, especially the TLS 1.0 ->
- // SSL 3.0 fallback, which would drop TLS extensions.
- version_max--;
- should_fallback = true;
- }
- break;
+ // This was added for the TLS 1.0 fallback (https://crbug.com/260358) which
+ // has since been removed, but other servers may be relying on it for the
+ // TLS 1.1 fallback. It will be removed with the remainder of the fallback.
case ERR_SSL_BAD_RECORD_MAC_ALERT:
- if (version_max >= SSL_PROTOCOL_VERSION_TLS1_1 &&
+ // Fallback down to a TLS 1.1 ClientHello. By default, this is rejected
+ // but surfaces ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION to help diagnose
+ // server bugs.
+ if (version_max >= SSL_PROTOCOL_VERSION_TLS1_2 &&
version_max > server_ssl_config_.version_min) {
- // Some broken SSL devices negotiate TLS 1.0 when sent a TLS 1.1 or
- // 1.2 ClientHello, but then return a bad_record_mac alert. See
- // crbug.com/260358. In order to make the fallback as minimal as
- // possible, this fallback is only triggered for >= TLS 1.1.
version_max--;
should_fallback = true;
}
@@ -1486,6 +1578,8 @@ void HttpNetworkTransaction::ResetStateForAuthRestart() {
remote_endpoint_ = IPEndPoint();
net_error_details_.quic_broken = false;
net_error_details_.quic_connection_error = QUIC_NO_ERROR;
+ provided_token_binding_key_.reset();
+ referred_token_binding_key_.reset();
}
void HttpNetworkTransaction::CacheNetErrorDetailsAndResetStream() {
@@ -1619,10 +1713,11 @@ int HttpNetworkTransaction::HandleAuthChallenge() {
return ERR_UNEXPECTED_PROXY_AUTH;
int rv = auth_controllers_[target]->HandleAuthChallenge(
- headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
+ headers, response_.ssl_info,
+ (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
net_log_);
if (auth_controllers_[target]->HaveAuthHandler())
- pending_auth_target_ = target;
+ pending_auth_target_ = target;
scoped_refptr<AuthChallengeInfo> auth_info =
auth_controllers_[target]->auth_info();
diff --git a/chromium/net/http/http_network_transaction.h b/chromium/net/http/http_network_transaction.h
index f8584b842d8..98b2e72982e 100644
--- a/chromium/net/http/http_network_transaction.h
+++ b/chromium/net/http/http_network_transaction.h
@@ -14,6 +14,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
+#include "crypto/ec_private_key.h"
#include "net/base/net_error_details.h"
#include "net/base/request_priority.h"
#include "net/http/http_auth.h"
@@ -24,13 +25,18 @@
#include "net/log/net_log.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/connection_attempts.h"
+#include "net/ssl/channel_id_service.h"
#include "net/ssl/ssl_config_service.h"
#include "net/ssl/ssl_failure_state.h"
#include "net/websockets/websocket_handshake_stream_base.h"
+namespace crypto {
+class ECPrivateKey;
+}
+
namespace net {
-class BidirectionalStreamJob;
+class BidirectionalStreamImpl;
class ClientSocketHandle;
class HttpAuthController;
class HttpNetworkSession;
@@ -91,10 +97,9 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
void OnStreamReady(const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStream* stream) override;
- void OnBidirectionalStreamJobReady(
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- BidirectionalStreamJob* stream_job) override;
+ void OnBidirectionalStreamImplReady(const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ BidirectionalStreamImpl* stream) override;
void OnWebSocketHandshakeStreamReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
@@ -149,6 +154,10 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE,
STATE_GENERATE_SERVER_AUTH_TOKEN,
STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE,
+ STATE_GET_PROVIDED_TOKEN_BINDING_KEY,
+ STATE_GET_PROVIDED_TOKEN_BINDING_KEY_COMPLETE,
+ STATE_GET_REFERRED_TOKEN_BINDING_KEY,
+ STATE_GET_REFERRED_TOKEN_BINDING_KEY_COMPLETE,
STATE_INIT_REQUEST_BODY,
STATE_INIT_REQUEST_BODY_COMPLETE,
STATE_BUILD_REQUEST,
@@ -165,6 +174,8 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
};
bool IsSecureRequest() const;
+ bool IsTokenBindingEnabled() const;
+ void RecordTokenBindingSupport() const;
// Returns true if the request is using an HTTP(S) proxy without being
// tunneled via the CONNECT method.
@@ -189,6 +200,10 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
int DoGenerateProxyAuthTokenComplete(int result);
int DoGenerateServerAuthToken();
int DoGenerateServerAuthTokenComplete(int result);
+ int DoGetProvidedTokenBindingKey();
+ int DoGetProvidedTokenBindingKeyComplete(int result);
+ int DoGetReferredTokenBindingKey();
+ int DoGetReferredTokenBindingKeyComplete(int result);
int DoInitRequestBody();
int DoInitRequestBodyComplete(int result);
int DoBuildRequest();
@@ -202,7 +217,8 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
int DoDrainBodyForAuthRestart();
int DoDrainBodyForAuthRestartComplete(int result);
- void BuildRequestHeaders(bool using_http_proxy_without_tunnel);
+ int BuildRequestHeaders(bool using_http_proxy_without_tunnel);
+ int BuildTokenBindingHeader(std::string* out);
// Writes a log message to help debugging in the field when we block a proxy
// response to a CONNECT request.
@@ -328,6 +344,13 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
// The SSLFailureState which caused the last TLS version fallback.
SSLFailureState fallback_failure_state_;
+ // Keys to use for signing message in Token Binding header.
+ scoped_ptr<crypto::ECPrivateKey> provided_token_binding_key_;
+ scoped_ptr<crypto::ECPrivateKey> referred_token_binding_key_;
+ // Object to manage lookup of |provided_token_binding_key_| and
+ // |referred_token_binding_key_|.
+ ChannelIDService::Request token_binding_request_;
+
HttpRequestHeaders request_headers_;
// The size in bytes of the buffer we use to drain the response body that
diff --git a/chromium/net/http/http_network_transaction_ssl_unittest.cc b/chromium/net/http/http_network_transaction_ssl_unittest.cc
index 4aa59a68f8e..575b2b949e4 100644
--- a/chromium/net/http/http_network_transaction_ssl_unittest.cc
+++ b/chromium/net/http/http_network_transaction_ssl_unittest.cc
@@ -7,7 +7,6 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "net/base/net_util.h"
#include "net/base/request_priority.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_auth_handler_mock.h"
@@ -18,6 +17,7 @@
#include "net/http/transport_security_state.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/socket_test_util.h"
+#include "net/ssl/default_channel_id_store.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -54,6 +54,20 @@ class TLS12SSLConfigService : public SSLConfigService {
SSLConfig ssl_config_;
};
+class TokenBindingSSLConfigService : public SSLConfigService {
+ public:
+ TokenBindingSSLConfigService() {
+ ssl_config_.token_binding_params.push_back(TB_PARAM_ECDSAP256);
+ }
+
+ void GetSSLConfig(SSLConfig* config) override { *config = ssl_config_; }
+
+ private:
+ ~TokenBindingSSLConfigService() override {}
+
+ SSLConfig ssl_config_;
+};
+
} // namespace
class HttpNetworkTransactionSSLTest : public testing::Test {
@@ -100,7 +114,7 @@ class HttpNetworkTransactionSSLTest : public testing::Test {
};
// Tests that HttpNetworkTransaction attempts to fallback from
-// TLS 1.2 to TLS 1.1, then from TLS 1.1 to TLS 1.0.
+// TLS 1.2 to TLS 1.1.
TEST_F(HttpNetworkTransactionSSLTest, SSLFallback) {
ssl_config_service_ = new TLS12SSLConfigService;
session_params_.ssl_config_service = ssl_config_service_.get();
@@ -119,19 +133,11 @@ TEST_F(HttpNetworkTransactionSSLTest, SSLFallback) {
StaticSocketDataProvider data2(NULL, 0, NULL, 0);
mock_socket_factory_.AddSocketDataProvider(&data2);
- // |ssl_data3| contains the handshake result for a TLS 1.0
- // handshake which will be attempted after the TLS 1.1
- // handshake fails.
- SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
- mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data3);
- StaticSocketDataProvider data3(NULL, 0, NULL, 0);
- mock_socket_factory_.AddSocketDataProvider(&data3);
-
HttpNetworkSession session(session_params_);
HttpNetworkTransaction trans(DEFAULT_PRIORITY, &session);
TestCompletionCallback callback;
- // This will consume |ssl_data1|, |ssl_data2| and |ssl_data3|.
+ // This will consume |ssl_data1| and |ssl_data2|.
int rv =
callback.GetResult(trans.Start(GetRequestInfo("https://www.paypal.com/"),
callback.callback(), BoundNetLog()));
@@ -139,14 +145,99 @@ TEST_F(HttpNetworkTransactionSSLTest, SSLFallback) {
SocketDataProviderArray<SocketDataProvider>& mock_data =
mock_socket_factory_.mock_data();
- // Confirms that |ssl_data1|, |ssl_data2| and |ssl_data3| are consumed.
- EXPECT_EQ(3u, mock_data.next_index());
+ // Confirms that |ssl_data1| and |ssl_data2| are consumed.
+ EXPECT_EQ(2u, mock_data.next_index());
SSLConfig& ssl_config = GetServerSSLConfig(&trans);
- // |version_max| fallbacks to TLS 1.0.
- EXPECT_EQ(SSL_PROTOCOL_VERSION_TLS1, ssl_config.version_max);
+ // |version_max| falls back to TLS 1.1.
+ EXPECT_EQ(SSL_PROTOCOL_VERSION_TLS1_1, ssl_config.version_max);
EXPECT_TRUE(ssl_config.version_fallback);
}
-} // namespace net
+#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;
+
+ SSLSocketDataProvider ssl_data(ASYNC, OK);
+ ssl_data.token_binding_negotiated = true;
+ ssl_data.token_binding_key_param = TB_PARAM_ECDSAP256;
+ mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data);
+ MockRead mock_reads[] = {MockRead("HTTP/1.1 200 OK\r\n\r\n"),
+ MockRead(SYNCHRONOUS, OK)};
+ StaticSocketDataProvider data(mock_reads, arraysize(mock_reads), NULL, 0);
+ mock_socket_factory_.AddSocketDataProvider(&data);
+ HttpNetworkSession session(session_params_);
+ HttpNetworkTransaction trans1(DEFAULT_PRIORITY, &session);
+
+ TestCompletionCallback callback;
+ int rv = callback.GetResult(
+ trans1.Start(GetRequestInfo("https://www.example.com/"),
+ callback.callback(), BoundNetLog()));
+ EXPECT_EQ(OK, rv);
+
+ HttpRequestHeaders headers1;
+ ASSERT_TRUE(trans1.GetFullRequestHeaders(&headers1));
+ std::string token_binding_header1;
+ EXPECT_TRUE(headers1.GetHeader(HttpRequestHeaders::kTokenBinding,
+ &token_binding_header1));
+
+ // Send a second request and verify that the token binding header is the same
+ // as in the first request.
+ mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data);
+ StaticSocketDataProvider data2(mock_reads, arraysize(mock_reads), NULL, 0);
+ mock_socket_factory_.AddSocketDataProvider(&data2);
+ HttpNetworkTransaction trans2(DEFAULT_PRIORITY, &session);
+
+ rv = callback.GetResult(
+ trans2.Start(GetRequestInfo("https://www.example.com/"),
+ callback.callback(), BoundNetLog()));
+ EXPECT_EQ(OK, rv);
+
+ HttpRequestHeaders headers2;
+ ASSERT_TRUE(trans2.GetFullRequestHeaders(&headers2));
+ std::string token_binding_header2;
+ EXPECT_TRUE(headers2.GetHeader(HttpRequestHeaders::kTokenBinding,
+ &token_binding_header2));
+
+ EXPECT_EQ(token_binding_header1, token_binding_header2);
+}
+
+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;
+
+ SSLSocketDataProvider ssl_data(ASYNC, OK);
+ ssl_data.token_binding_negotiated = true;
+ ssl_data.token_binding_key_param = TB_PARAM_ECDSAP256;
+ mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data);
+ MockRead mock_reads[] = {MockRead("HTTP/1.1 200 OK\r\n\r\n"),
+ MockRead(SYNCHRONOUS, OK)};
+ StaticSocketDataProvider data(mock_reads, arraysize(mock_reads), NULL, 0);
+ mock_socket_factory_.AddSocketDataProvider(&data);
+
+ HttpNetworkSession session(session_params_);
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, &session);
+
+ TestCompletionCallback callback;
+ int rv =
+ callback.GetResult(trans.Start(GetRequestInfo("http://www.example.com/"),
+ callback.callback(), BoundNetLog()));
+ EXPECT_EQ(OK, rv);
+
+ HttpRequestHeaders headers;
+ ASSERT_TRUE(trans.GetFullRequestHeaders(&headers));
+ std::string token_binding_header;
+ EXPECT_FALSE(headers.GetHeader(HttpRequestHeaders::kTokenBinding,
+ &token_binding_header));
+}
+#endif // !defined(OS_IOS)
+
+} // namespace net
diff --git a/chromium/net/http/http_network_transaction_unittest.cc b/chromium/net/http/http_network_transaction_unittest.cc
index ed7470b3a61..6be19d7e408 100644
--- a/chromium/net/http/http_network_transaction_unittest.cc
+++ b/chromium/net/http/http_network_transaction_unittest.cc
@@ -32,9 +32,11 @@
#include "net/base/load_timing_info.h"
#include "net/base/load_timing_info_test_util.h"
#include "net/base/net_errors.h"
+#include "net/base/proxy_delegate.h"
#include "net/base/request_priority.h"
#include "net/base/test_completion_callback.h"
#include "net/base/test_data_directory.h"
+#include "net/base/test_proxy_delegate.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_file_element_reader.h"
#include "net/cert/mock_cert_verifier.h"
@@ -63,8 +65,10 @@
#include "net/proxy/proxy_config_service_fixed.h"
#include "net/proxy/proxy_info.h"
#include "net/proxy/proxy_resolver.h"
+#include "net/proxy/proxy_server.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/client_socket_factory.h"
+#include "net/socket/client_socket_pool.h"
#include "net/socket/client_socket_pool_manager.h"
#include "net/socket/connection_attempts.h"
#include "net/socket/mock_client_socket_pool_manager.h"
@@ -75,6 +79,7 @@
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_session_pool.h"
#include "net/spdy/spdy_test_util_common.h"
+#include "net/ssl/default_channel_id_store.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_config_service.h"
#include "net/ssl/ssl_config_service_defaults.h"
@@ -266,7 +271,6 @@ class HttpNetworkTransactionTest
HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
ClientSocketPoolManager::set_max_sockets_per_group(
HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
- SpdySession::SetPriorityDependencyDefaultForTesting(false);
}
protected:
@@ -277,8 +281,7 @@ class HttpNetworkTransactionTest
HttpNetworkSession::NORMAL_SOCKET_POOL)),
old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
HttpNetworkSession::NORMAL_SOCKET_POOL)) {
- SpdySession::SetPriorityDependencyDefaultForTesting(
- GetDependenciesFromPriority());
+ session_deps_.enable_priority_dependencies = GetDependenciesFromPriority();
}
struct SimpleGetHelperResult {
@@ -586,6 +589,7 @@ class CaptureGroupNameSocketPool : public ParentPool {
int RequestSocket(const std::string& group_name,
const void* socket_params,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) override {
@@ -1116,7 +1120,7 @@ TEST_P(HttpNetworkTransactionTest, Head) {
EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
std::string server_header;
- void* iter = NULL;
+ size_t iter = 0;
bool has_server_header = response->headers->EnumerateHeader(
&iter, "Server", &server_header);
EXPECT_TRUE(has_server_header);
@@ -1433,11 +1437,11 @@ void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
// SPDY versions of the request and response.
- scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
- request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
- scoped_ptr<SpdyFrame> spdy_response(
+ scoped_ptr<SpdySerializedFrame> spdy_request(spdy_util_.ConstructSpdyGet(
+ request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
+ scoped_ptr<SpdySerializedFrame> spdy_response(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> spdy_data(
+ scoped_ptr<SpdySerializedFrame> spdy_data(
spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
// HTTP/1.1 versions of the request and response.
@@ -4211,12 +4215,14 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
// fetch http://www.example.org/ via SPDY
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> data(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
};
@@ -4271,12 +4277,14 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
// Fetch http://www.example.org/ through the SPDY proxy.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> data(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
};
@@ -4341,19 +4349,16 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
// The first request will be a bare GET, the second request will be a
// GET with a Proxy-Authorization header.
- scoped_ptr<SpdyFrame> req_get(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
+ scoped_ptr<SpdySerializedFrame> req_get(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
spdy_util_.UpdateWithStreamDestruction(1);
const char* const kExtraAuthorizationHeaders[] = {
"proxy-authorization", "Basic Zm9vOmJhcg=="
};
- scoped_ptr<SpdyFrame> req_get_authorization(
+ scoped_ptr<SpdySerializedFrame> req_get_authorization(
spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
- arraysize(kExtraAuthorizationHeaders) / 2,
- false,
- 3,
- LOWEST,
- false));
+ arraysize(kExtraAuthorizationHeaders) / 2, 3,
+ LOWEST, false));
MockWrite spdy_writes[] = {
CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
};
@@ -4364,16 +4369,16 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
const char* const kExtraAuthenticationHeaders[] = {
"proxy-authenticate", "Basic realm=\"MyRealm1\""
};
- scoped_ptr<SpdyFrame> resp_authentication(
+ scoped_ptr<SpdySerializedFrame> resp_authentication(
spdy_util_.ConstructSpdySynReplyError(
- "407 Proxy Authentication Required",
- kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
- 1));
- scoped_ptr<SpdyFrame> body_authentication(
+ "407 Proxy Authentication Required", kExtraAuthenticationHeaders,
+ arraysize(kExtraAuthenticationHeaders) / 2, 1));
+ scoped_ptr<SpdySerializedFrame> body_authentication(
spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> resp_data(
+ scoped_ptr<SpdySerializedFrame> resp_data(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
+ scoped_ptr<SpdySerializedFrame> body_data(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp_authentication, 1),
CreateMockRead(*body_authentication, 2),
@@ -4444,7 +4449,7 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
// CONNECT to www.example.org:443 via SPDY
- scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
+ scoped_ptr<SpdySerializedFrame> connect(spdy_util_.ConstructSpdyConnect(
NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
// fetch https://www.example.org/ via HTTP
@@ -4452,17 +4457,17 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
"GET / HTTP/1.1\r\n"
"Host: www.example.org\r\n"
"Connection: keep-alive\r\n\r\n";
- scoped_ptr<SpdyFrame> wrapped_get(
+ scoped_ptr<SpdySerializedFrame> wrapped_get(
spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
- scoped_ptr<SpdyFrame> conn_resp(
+ scoped_ptr<SpdySerializedFrame> conn_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
const char resp[] = "HTTP/1.1 200 OK\r\n"
"Content-Length: 10\r\n\r\n";
- scoped_ptr<SpdyFrame> wrapped_get_resp(
+ scoped_ptr<SpdySerializedFrame> wrapped_get_resp(
spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
- scoped_ptr<SpdyFrame> wrapped_body(
+ scoped_ptr<SpdySerializedFrame> wrapped_body(
spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
- scoped_ptr<SpdyFrame> window_update(
+ scoped_ptr<SpdySerializedFrame> window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
MockWrite spdy_writes[] = {
@@ -4530,26 +4535,27 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
// CONNECT to www.example.org:443 via SPDY
- scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
+ scoped_ptr<SpdySerializedFrame> connect(spdy_util_.ConstructSpdyConnect(
NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
// fetch https://www.example.org/ via SPDY
const char kMyUrl[] = "https://www.example.org/";
- scoped_ptr<SpdyFrame> get(
- spdy_util_wrapped.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
- scoped_ptr<SpdyFrame> wrapped_get(
+ scoped_ptr<SpdySerializedFrame> get(
+ spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> wrapped_get(
spdy_util_.ConstructWrappedSpdyFrame(get, 1));
- scoped_ptr<SpdyFrame> conn_resp(
+ scoped_ptr<SpdySerializedFrame> conn_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> get_resp(
+ scoped_ptr<SpdySerializedFrame> get_resp(
spdy_util_wrapped.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> wrapped_get_resp(
+ scoped_ptr<SpdySerializedFrame> wrapped_get_resp(
spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_wrapped.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> wrapped_body(
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_wrapped.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> wrapped_body(
spdy_util_.ConstructWrappedSpdyFrame(body, 1));
- scoped_ptr<SpdyFrame> window_update_get_resp(
+ scoped_ptr<SpdySerializedFrame> window_update_get_resp(
spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
- scoped_ptr<SpdyFrame> window_update_body(
+ scoped_ptr<SpdySerializedFrame> window_update_body(
spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
MockWrite spdy_writes[] = {
@@ -4621,17 +4627,19 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
// CONNECT to www.example.org:443 via SPDY
- scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(
+ scoped_ptr<SpdySerializedFrame> connect(spdy_util_.ConstructSpdyConnect(
NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
- scoped_ptr<SpdyFrame> get(
+ scoped_ptr<SpdySerializedFrame> get(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite spdy_writes[] = {
CreateMockWrite(*connect, 0), CreateMockWrite(*get, 2),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
- scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdySynReplyError(1));
+ scoped_ptr<SpdySerializedFrame> data(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
};
@@ -4680,9 +4688,9 @@ TEST_P(HttpNetworkTransactionTest,
request2.load_flags = 0;
// CONNECT to www.example.org:443 via SPDY.
- scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
+ scoped_ptr<SpdySerializedFrame> connect1(spdy_util_.ConstructSpdyConnect(
NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
- scoped_ptr<SpdyFrame> conn_resp1(
+ scoped_ptr<SpdySerializedFrame> conn_resp1(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
// Fetch https://www.example.org/ via HTTP.
@@ -4690,15 +4698,15 @@ TEST_P(HttpNetworkTransactionTest,
"GET / HTTP/1.1\r\n"
"Host: www.example.org\r\n"
"Connection: keep-alive\r\n\r\n";
- scoped_ptr<SpdyFrame> wrapped_get1(
+ scoped_ptr<SpdySerializedFrame> wrapped_get1(
spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
const char resp1[] = "HTTP/1.1 200 OK\r\n"
"Content-Length: 1\r\n\r\n";
- scoped_ptr<SpdyFrame> wrapped_get_resp1(
+ scoped_ptr<SpdySerializedFrame> wrapped_get_resp1(
spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
- scoped_ptr<SpdyFrame> wrapped_body1(
+ scoped_ptr<SpdySerializedFrame> wrapped_body1(
spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
- scoped_ptr<SpdyFrame> window_update(
+ scoped_ptr<SpdySerializedFrame> window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
// CONNECT to mail.example.org:443 via SPDY.
@@ -4711,10 +4719,10 @@ TEST_P(HttpNetworkTransactionTest,
connect2_block[spdy_util_.GetHostKey()] = "mail.example.org";
connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443";
}
- scoped_ptr<SpdyFrame> connect2(
- spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
+ scoped_ptr<SpdySerializedFrame> connect2(
+ spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false));
- scoped_ptr<SpdyFrame> conn_resp2(
+ scoped_ptr<SpdySerializedFrame> conn_resp2(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
// Fetch https://mail.example.org/ via HTTP.
@@ -4722,13 +4730,13 @@ TEST_P(HttpNetworkTransactionTest,
"GET / HTTP/1.1\r\n"
"Host: mail.example.org\r\n"
"Connection: keep-alive\r\n\r\n";
- scoped_ptr<SpdyFrame> wrapped_get2(
+ scoped_ptr<SpdySerializedFrame> wrapped_get2(
spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
const char resp2[] = "HTTP/1.1 200 OK\r\n"
"Content-Length: 2\r\n\r\n";
- scoped_ptr<SpdyFrame> wrapped_get_resp2(
+ scoped_ptr<SpdySerializedFrame> wrapped_get_resp2(
spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
- scoped_ptr<SpdyFrame> wrapped_body2(
+ scoped_ptr<SpdySerializedFrame> wrapped_body2(
spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
MockWrite spdy_writes[] = {
@@ -4822,9 +4830,9 @@ TEST_P(HttpNetworkTransactionTest,
request2.load_flags = 0;
// CONNECT to www.example.org:443 via SPDY.
- scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(
+ scoped_ptr<SpdySerializedFrame> connect1(spdy_util_.ConstructSpdyConnect(
NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
- scoped_ptr<SpdyFrame> conn_resp1(
+ scoped_ptr<SpdySerializedFrame> conn_resp1(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
// Fetch https://www.example.org/ via HTTP.
@@ -4832,15 +4840,15 @@ TEST_P(HttpNetworkTransactionTest,
"GET / HTTP/1.1\r\n"
"Host: www.example.org\r\n"
"Connection: keep-alive\r\n\r\n";
- scoped_ptr<SpdyFrame> wrapped_get1(
+ scoped_ptr<SpdySerializedFrame> wrapped_get1(
spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
const char resp1[] = "HTTP/1.1 200 OK\r\n"
"Content-Length: 1\r\n\r\n";
- scoped_ptr<SpdyFrame> wrapped_get_resp1(
+ scoped_ptr<SpdySerializedFrame> wrapped_get_resp1(
spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
- scoped_ptr<SpdyFrame> wrapped_body1(
+ scoped_ptr<SpdySerializedFrame> wrapped_body1(
spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
- scoped_ptr<SpdyFrame> window_update(
+ scoped_ptr<SpdySerializedFrame> window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
// Fetch https://www.example.org/2 via HTTP.
@@ -4848,13 +4856,13 @@ TEST_P(HttpNetworkTransactionTest,
"GET /2 HTTP/1.1\r\n"
"Host: www.example.org\r\n"
"Connection: keep-alive\r\n\r\n";
- scoped_ptr<SpdyFrame> wrapped_get2(
+ scoped_ptr<SpdySerializedFrame> wrapped_get2(
spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
const char resp2[] = "HTTP/1.1 200 OK\r\n"
"Content-Length: 2\r\n\r\n";
- scoped_ptr<SpdyFrame> wrapped_get_resp2(
+ scoped_ptr<SpdySerializedFrame> wrapped_get_resp2(
spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
- scoped_ptr<SpdyFrame> wrapped_body2(
+ scoped_ptr<SpdySerializedFrame> wrapped_body2(
spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
MockWrite spdy_writes[] = {
@@ -4947,22 +4955,22 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
// http://www.example.org/
scoped_ptr<SpdyHeaderBlock> headers(
spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
- scoped_ptr<SpdyFrame> get1(
- spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
- scoped_ptr<SpdyFrame> get_resp1(
+ scoped_ptr<SpdySerializedFrame> get1(
+ spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> get_resp1(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body1(
+ scoped_ptr<SpdySerializedFrame> body1(
spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
spdy_util_.UpdateWithStreamDestruction(1);
// http://mail.example.org/
scoped_ptr<SpdyHeaderBlock> headers2(
spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
- scoped_ptr<SpdyFrame> get2(
- spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
- scoped_ptr<SpdyFrame> get_resp2(
+ scoped_ptr<SpdySerializedFrame> get2(
+ spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> get_resp2(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body2(
+ scoped_ptr<SpdySerializedFrame> body2(
spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
MockWrite spdy_writes[] = {
@@ -7393,9 +7401,9 @@ TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
request.url = GURL("https://www.example.org/");
request.load_flags = 0;
- scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
+ scoped_ptr<SpdySerializedFrame> conn(spdy_util_.ConstructSpdyConnect(
NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
- scoped_ptr<SpdyFrame> goaway(
+ scoped_ptr<SpdySerializedFrame> goaway(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite data_writes[] = {
CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
@@ -7406,9 +7414,8 @@ TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
"location",
"http://login.example.com/",
};
- scoped_ptr<SpdyFrame> resp(
- spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
- arraysize(kExtraHeaders)/2, 1));
+ scoped_ptr<SpdySerializedFrame> resp(spdy_util_.ConstructSpdySynReplyError(
+ "302 Redirect", kExtraHeaders, arraysize(kExtraHeaders) / 2, 1));
MockRead data_reads[] = {
CreateMockRead(*resp.get(), 1), MockRead(ASYNC, 0, 3), // EOF
};
@@ -7497,9 +7504,9 @@ TEST_P(HttpNetworkTransactionTest,
request.url = GURL("https://www.example.org/");
request.load_flags = 0;
- scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(
+ scoped_ptr<SpdySerializedFrame> conn(spdy_util_.ConstructSpdyConnect(
NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite data_writes[] = {
CreateMockWrite(*conn.get(), 0), CreateMockWrite(*rst.get(), 3),
@@ -7509,12 +7516,10 @@ TEST_P(HttpNetworkTransactionTest,
"location",
"http://login.example.com/",
};
- scoped_ptr<SpdyFrame> resp(
- spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
- arraysize(kExtraHeaders)/2, 1));
- scoped_ptr<SpdyFrame> body(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, "The host does not exist", 23, true));
+ scoped_ptr<SpdySerializedFrame> resp(spdy_util_.ConstructSpdySynReplyError(
+ "404 Not Found", kExtraHeaders, arraysize(kExtraHeaders) / 2, 1));
+ scoped_ptr<SpdySerializedFrame> body(spdy_util_.ConstructSpdyBodyFrame(
+ 1, "The host does not exist", 23, true));
MockRead data_reads[] = {
CreateMockRead(*resp.get(), 1),
CreateMockRead(*body.get(), 2),
@@ -7561,9 +7566,9 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
// Since we have proxy, should try to establish tunnel.
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyConnect(
NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
spdy_util_.UpdateWithStreamDestruction(1);
@@ -7572,7 +7577,7 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
const char* const kAuthCredentials[] = {
"proxy-authorization", "Basic Zm9vOmJhcg==",
};
- scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
+ scoped_ptr<SpdySerializedFrame> connect2(spdy_util_.ConstructSpdyConnect(
kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
HostPortPair("www.example.org", 443)));
// fetch https://www.example.org/ via HTTP
@@ -7580,7 +7585,7 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
"GET / HTTP/1.1\r\n"
"Host: www.example.org\r\n"
"Connection: keep-alive\r\n\r\n";
- scoped_ptr<SpdyFrame> wrapped_get(
+ scoped_ptr<SpdySerializedFrame> wrapped_get(
spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
MockWrite spdy_writes[] = {
@@ -7596,17 +7601,18 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
const char* const kAuthChallenge[] = {
"proxy-authenticate", "Basic realm=\"MyRealm1\"",
};
- scoped_ptr<SpdyFrame> conn_auth_resp(spdy_util_.ConstructSpdySynReplyError(
- kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
+ scoped_ptr<SpdySerializedFrame> conn_auth_resp(
+ spdy_util_.ConstructSpdySynReplyError(kAuthStatus, kAuthChallenge,
+ arraysize(kAuthChallenge) / 2, 1));
- scoped_ptr<SpdyFrame> conn_resp(
+ scoped_ptr<SpdySerializedFrame> conn_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
const char resp[] = "HTTP/1.1 200 OK\r\n"
"Content-Length: 5\r\n\r\n";
- scoped_ptr<SpdyFrame> wrapped_get_resp(
+ scoped_ptr<SpdySerializedFrame> wrapped_get_resp(
spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
- scoped_ptr<SpdyFrame> wrapped_body(
+ scoped_ptr<SpdySerializedFrame> wrapped_body(
spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
MockRead spdy_reads[] = {
CreateMockRead(*conn_auth_resp, 1, ASYNC),
@@ -7686,7 +7692,11 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
// Test that an explicitly trusted SPDY proxy can push a resource from an
// origin that is different from that of its associated resource.
-TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
+TEST_P(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
+ // Configure the proxy delegate to allow cross-origin SPDY pushes.
+ scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
+ proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
+ "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
HttpRequestInfo request;
HttpRequestInfo push_request;
@@ -7695,40 +7705,35 @@ TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
push_request.method = "GET";
push_request.url = GURL("http://www.another-origin.com/foo.dat");
- // Configure against https proxy server "myproxy:70".
+ // Configure against https proxy server "myproxy:443".
session_deps_.proxy_service =
- ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
+ ProxyService::CreateFixedFromPacResult("HTTPS myproxy:443");
BoundTestNetLog log;
session_deps_.net_log = log.bound().net_log();
- // Enable cross-origin push.
- session_deps_.trusted_spdy_proxy = "myproxy:70";
+ session_deps_.proxy_delegate.reset(proxy_delegate.release());
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
MockWrite spdy_writes[] = {
CreateMockWrite(*stream1_syn, 0, ASYNC),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame>
- stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame>
- stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
- 0,
- 2,
- 1,
- "http://www.another-origin.com/foo.dat"));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ NULL, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
const char kPushedData[] = "pushed";
- scoped_ptr<SpdyFrame> stream2_body(
- spdy_util_.ConstructSpdyBodyFrame(
- 2, kPushedData, strlen(kPushedData), true));
+ scoped_ptr<SpdySerializedFrame> stream2_body(
+ spdy_util_.ConstructSpdyBodyFrame(2, kPushedData, strlen(kPushedData),
+ true));
MockRead spdy_reads[] = {
CreateMockRead(*stream1_reply, 1, ASYNC),
@@ -7804,43 +7809,43 @@ TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
+ // Configure the proxy delegate to allow cross-origin SPDY pushes.
+ scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
+ proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
+ "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.example.org/");
- // Configure against https proxy server "myproxy:70".
- session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
+ session_deps_.proxy_service =
+ ProxyService::CreateFixed("https://myproxy:443");
BoundTestNetLog log;
session_deps_.net_log = log.bound().net_log();
// Enable cross-origin push.
- session_deps_.trusted_spdy_proxy = "myproxy:70";
+ session_deps_.proxy_delegate.reset(proxy_delegate.release());
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
- scoped_ptr<SpdyFrame> push_rst(
+ scoped_ptr<SpdySerializedFrame> push_rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
MockWrite spdy_writes[] = {
CreateMockWrite(*stream1_syn, 0, ASYNC), CreateMockWrite(*push_rst, 3),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame>
- stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame>
- stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
- 0,
- 2,
- 1,
- "https://www.another-origin.com/foo.dat"));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ NULL, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
MockRead spdy_reads[] = {
CreateMockRead(*stream1_reply, 1, ASYNC),
@@ -7882,6 +7887,92 @@ TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
session->CloseAllConnections();
}
+// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
+// resources.
+TEST_P(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
+ // Configure the proxy delegate to allow cross-origin SPDY pushes.
+ scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
+ proxy_delegate->set_trusted_spdy_proxy(
+ net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
+
+ HttpRequestInfo request;
+
+ request.method = "GET";
+ request.url = GURL("http://www.example.org/");
+
+ // Configure against https proxy server "myproxy:70".
+ session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
+ BoundTestNetLog log;
+ session_deps_.net_log = log.bound().net_log();
+
+ // Enable cross-origin push.
+ session_deps_.proxy_delegate.reset(proxy_delegate.release());
+
+ scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
+
+ MockWrite spdy_writes[] = {
+ CreateMockWrite(*stream1_syn, 0, ASYNC),
+ };
+
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ nullptr, 0, 2, 1, "https://myproxy:70/foo.dat"));
+
+ scoped_ptr<SpdySerializedFrame> stream1_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+
+ scoped_ptr<SpdySerializedFrame> stream2_reply(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+
+ scoped_ptr<SpdySerializedFrame> stream2_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+
+ 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
+ };
+
+ SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
+ arraysize(spdy_writes));
+ session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
+ // Negotiate SPDY to the proxy
+ SSLSocketDataProvider proxy(ASYNC, OK);
+ proxy.SetNextProto(GetProtocol());
+ session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
+
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
+ TestCompletionCallback callback;
+ int rv = trans->Start(&request, callback.callback(), log.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+
+ ASSERT_TRUE(response != nullptr);
+ EXPECT_TRUE(response->headers->IsKeepAlive());
+
+ EXPECT_EQ(200, response->headers->response_code());
+ EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
+
+ std::string response_data;
+ rv = ReadTransaction(trans.get(), &response_data);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("hello!", response_data);
+
+ trans.reset();
+ session->CloseAllConnections();
+}
+
// Test HTTPS connections to a site with a bad certificate, going through an
// HTTPS proxy
TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
@@ -8711,8 +8802,7 @@ scoped_ptr<HttpNetworkSession> SetupSessionForGroupNameTests(
AlternateProtocolFromNextProto(next_proto), "", 443);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
- HostPortPair("host.with.alternate", 80), alternative_service, 1.0,
- expiration);
+ HostPortPair("host.with.alternate", 80), alternative_service, expiration);
return session;
}
@@ -8771,7 +8861,8 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
},
};
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
for (size_t i = 0; i < arraysize(tests); ++i) {
session_deps_.proxy_service =
@@ -8833,7 +8924,8 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
},
};
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
for (size_t i = 0; i < arraysize(tests); ++i) {
session_deps_.proxy_service =
@@ -8903,7 +8995,8 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
},
};
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
for (size_t i = 0; i < arraysize(tests); ++i) {
session_deps_.proxy_service =
@@ -9564,8 +9657,8 @@ TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
}
TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
- session_deps_.next_protos = SpdyNextProtos();
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
std::string alternative_service_http_header =
GetAlternativeServiceHttpHeader();
@@ -9626,8 +9719,8 @@ TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
}
TEST_P(HttpNetworkTransactionTest, ClearAlternativeServices) {
- session_deps_.next_protos = SpdyNextProtos();
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
// Set an alternative service for origin.
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -9636,8 +9729,8 @@ TEST_P(HttpNetworkTransactionTest, ClearAlternativeServices) {
HostPortPair http_host_port_pair("www.example.org", 80);
AlternativeService alternative_service(QUIC, "", 80);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
- http_server_properties.SetAlternativeService(
- http_host_port_pair, alternative_service, 1.0, expiration);
+ http_server_properties.SetAlternativeService(http_host_port_pair,
+ alternative_service, expiration);
AlternativeServiceVector alternative_service_vector =
http_server_properties.GetAlternativeServices(http_host_port_pair);
EXPECT_EQ(1u, alternative_service_vector.size());
@@ -9682,11 +9775,10 @@ TEST_P(HttpNetworkTransactionTest, ClearAlternativeServices) {
EXPECT_TRUE(alternative_service_vector.empty());
}
-// Alternative Service headers must be ignored when |use_alternative_services|
-// is false.
+// Alternative Service headers must be ignored when
+// |parse_alternative_services| is false.
TEST_P(HttpNetworkTransactionTest, DoNotHonorAlternativeServiceHeader) {
- session_deps_.next_protos = SpdyNextProtos();
- session_deps_.use_alternative_services = false;
+ session_deps_.parse_alternative_services = false;
std::string alternative_service_http_header =
GetAlternativeServiceHttpHeader();
@@ -9743,15 +9835,16 @@ TEST_P(HttpNetworkTransactionTest, DoNotHonorAlternativeServiceHeader) {
}
TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
- session_deps_.next_protos = SpdyNextProtos();
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Alt-Svc: "),
MockRead(GetAlternateProtocolFromParam()),
MockRead("=\"www.example.com:443\";p=\"1.0\","),
- MockRead("quic=\":1234\"\r\n\r\n"),
+ MockRead(GetAlternateProtocolFromParam()),
+ MockRead("=\":1234\"\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, OK),
};
@@ -9801,16 +9894,16 @@ TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
alternative_service_vector[0].protocol);
EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
EXPECT_EQ(443, alternative_service_vector[0].port);
- EXPECT_EQ(QUIC, alternative_service_vector[1].protocol);
+ EXPECT_EQ(AlternateProtocolFromNextProto(GetProtocol()),
+ alternative_service_vector[1].protocol);
EXPECT_EQ("www.example.org", alternative_service_vector[1].host);
EXPECT_EQ(1234, alternative_service_vector[1].port);
}
-// Alternate Protocol headers must be honored even if |use_alternative_services|
-// is false.
+// Alternate Protocol headers must be honored even if
+// |parse_alternative_services| is false.
TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
- session_deps_.next_protos = SpdyNextProtos();
- session_deps_.use_alternative_services = false;
+ session_deps_.parse_alternative_services = false;
std::string alternate_protocol_http_header =
GetAlternateProtocolHttpHeader();
@@ -9870,8 +9963,8 @@ TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
}
TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
- session_deps_.next_protos = SpdyNextProtos();
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = false;
+ session_deps_.enable_alternative_service_with_different_host = false;
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
@@ -9898,8 +9991,8 @@ TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
*session->http_server_properties();
AlternativeService alternative_service(QUIC, "", 80);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
- http_server_properties.SetAlternativeService(
- http_host_port_pair, alternative_service, 1.0, expiration);
+ http_server_properties.SetAlternativeService(http_host_port_pair,
+ alternative_service, expiration);
AlternativeServiceVector alternative_service_vector =
http_server_properties.GetAlternativeServices(http_host_port_pair);
@@ -9930,9 +10023,11 @@ TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) {
EXPECT_TRUE(alternative_service_vector.empty());
}
+// When |session_deps_.parse_alternative_services = true| and the response has
+// an Alt-Svc header, then the Alternate-Protocol header is not parsed.
TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) {
- session_deps_.next_protos = SpdyNextProtos();
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
std::string alternative_service_http_header =
GetAlternativeServiceHttpHeader();
@@ -9994,10 +10089,11 @@ TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) {
EXPECT_EQ(443, alternative_service_vector[0].port);
}
-// When |use_alternative_services| is false, do not observe alternative service
-// entries that point to a different host.
+// When |enable_alternative_service_with_different_host| is false, do not
+// observe alternative service entries that point to a different host.
TEST_P(HttpNetworkTransactionTest, DisableAlternativeServiceToDifferentHost) {
- session_deps_.use_alternative_services = false;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo request;
request.method = "GET";
@@ -10026,7 +10122,7 @@ TEST_P(HttpNetworkTransactionTest, DisableAlternativeServiceToDifferentHost) {
80);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
- HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
+ HostPortPair::FromURL(request.url), alternative_service, expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10072,14 +10168,15 @@ TEST_P(HttpNetworkTransactionTest, IdentifyQuicBroken) {
session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
// Set up a QUIC alternative service for origin.
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
AlternativeService alternative_service(QUIC, alternative);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(origin, alternative_service,
- 1.0, expiration);
+ expiration);
// Mark the QUIC alternative service as broken.
http_server_properties->MarkAlternativeServiceBroken(alternative_service);
@@ -10132,7 +10229,8 @@ TEST_P(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = true;
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
@@ -10142,11 +10240,11 @@ TEST_P(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
AlternativeService alternative_service1(QUIC, alternative1);
- AlternativeServiceInfo alternative_service_info1(alternative_service1, 1.0,
+ AlternativeServiceInfo alternative_service_info1(alternative_service1,
expiration);
alternative_service_info_vector.push_back(alternative_service_info1);
AlternativeService alternative_service2(QUIC, alternative2);
- AlternativeServiceInfo alternative_service_info2(alternative_service2, 1.0,
+ AlternativeServiceInfo alternative_service_info2(alternative_service2,
expiration);
alternative_service_info_vector.push_back(alternative_service_info2);
@@ -10176,7 +10274,8 @@ TEST_P(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
TEST_P(HttpNetworkTransactionTest,
MarkBrokenAlternateProtocolAndFallback) {
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo request;
request.method = "GET";
@@ -10209,7 +10308,7 @@ TEST_P(HttpNetworkTransactionTest,
666); // Port is ignored by MockConnect anyway.
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
- host_port_pair, alternative_service, 1.0, expiration);
+ host_port_pair, alternative_service, expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10242,7 +10341,8 @@ TEST_P(HttpNetworkTransactionTest,
// cases.
TEST_P(HttpNetworkTransactionTest,
AlternateProtocolPortRestrictedBlocked) {
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo restricted_port_request;
restricted_port_request.method = "GET";
@@ -10274,7 +10374,7 @@ TEST_P(HttpNetworkTransactionTest,
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
HostPortPair::FromURL(restricted_port_request.url), alternative_service,
- 1.0, expiration);
+ expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10293,7 +10393,8 @@ TEST_P(HttpNetworkTransactionTest,
// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
TEST_P(HttpNetworkTransactionTest,
AlternateProtocolPortRestrictedPermitted) {
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
session_deps_.enable_user_alternate_protocol_ports = true;
HttpRequestInfo restricted_port_request;
@@ -10326,7 +10427,7 @@ TEST_P(HttpNetworkTransactionTest,
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
HostPortPair::FromURL(restricted_port_request.url), alternative_service,
- 1.0, expiration);
+ expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10345,7 +10446,8 @@ TEST_P(HttpNetworkTransactionTest,
// cases.
TEST_P(HttpNetworkTransactionTest,
AlternateProtocolPortRestrictedAllowed) {
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo restricted_port_request;
restricted_port_request.method = "GET";
@@ -10377,7 +10479,7 @@ TEST_P(HttpNetworkTransactionTest,
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
HostPortPair::FromURL(restricted_port_request.url), alternative_service,
- 1.0, expiration);
+ expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10397,7 +10499,8 @@ TEST_P(HttpNetworkTransactionTest,
// cases.
TEST_P(HttpNetworkTransactionTest,
AlternateProtocolPortUnrestrictedAllowed1) {
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo unrestricted_port_request;
unrestricted_port_request.method = "GET";
@@ -10429,7 +10532,7 @@ TEST_P(HttpNetworkTransactionTest,
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
- 1.0, expiration);
+ expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10448,7 +10551,8 @@ TEST_P(HttpNetworkTransactionTest,
// cases.
TEST_P(HttpNetworkTransactionTest,
AlternateProtocolPortUnrestrictedAllowed2) {
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo unrestricted_port_request;
unrestricted_port_request.method = "GET";
@@ -10480,7 +10584,7 @@ TEST_P(HttpNetworkTransactionTest,
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
HostPortPair::FromURL(unrestricted_port_request.url), alternative_service,
- 1.0, expiration);
+ expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10497,7 +10601,8 @@ TEST_P(HttpNetworkTransactionTest,
// to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
// once the alternate protocol request fails.
TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo request;
request.method = "GET";
@@ -10525,7 +10630,7 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
kUnsafePort);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(
- HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
+ HostPortPair::FromURL(request.url), alternative_service, expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -10547,8 +10652,8 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
}
TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
- session_deps_.use_alternative_services = true;
- session_deps_.next_protos = SpdyNextProtos();
+ session_deps_.parse_alternative_services = false;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo request;
request.method = "GET";
@@ -10576,12 +10681,14 @@ TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
ASSERT_TRUE(ssl.cert.get());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> data(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
};
@@ -10635,8 +10742,8 @@ TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
}
TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
- session_deps_.use_alternative_services = true;
- session_deps_.next_protos = SpdyNextProtos();
+ session_deps_.parse_alternative_services = false;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo request;
request.method = "GET";
@@ -10677,17 +10784,21 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
ASSERT_TRUE(ssl.cert.get());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
MockWrite spdy_writes[] = {
CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
};
- scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
+ scoped_ptr<SpdySerializedFrame> resp1(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> data1(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<SpdySerializedFrame> data2(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp1, 2),
CreateMockRead(*data1, 3),
@@ -10756,8 +10867,8 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
}
TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
- session_deps_.use_alternative_services = true;
- session_deps_.next_protos = SpdyNextProtos();
+ session_deps_.parse_alternative_services = false;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo request;
request.method = "GET";
@@ -10885,8 +10996,8 @@ class CapturingProxyResolverFactory : public ProxyResolverFactory {
TEST_P(HttpNetworkTransactionTest,
UseAlternateProtocolForTunneledNpnSpdy) {
- session_deps_.use_alternative_services = true;
- session_deps_.next_protos = SpdyNextProtos();
+ session_deps_.parse_alternative_services = false;
+ session_deps_.enable_alternative_service_with_different_host = false;
ProxyConfig proxy_config;
proxy_config.set_auto_detect(true);
@@ -10928,8 +11039,8 @@ TEST_P(HttpNetworkTransactionTest,
ASSERT_TRUE(ssl.cert.get());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite spdy_writes[] = {
MockWrite(ASYNC, 0,
"CONNECT www.example.org:443 HTTP/1.1\r\n"
@@ -10940,8 +11051,10 @@ TEST_P(HttpNetworkTransactionTest,
const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> data(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(*resp.get(), 3),
CreateMockRead(*data.get(), 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
@@ -11009,8 +11122,8 @@ TEST_P(HttpNetworkTransactionTest,
TEST_P(HttpNetworkTransactionTest,
UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
- session_deps_.use_alternative_services = true;
- session_deps_.next_protos = SpdyNextProtos();
+ session_deps_.parse_alternative_services = false;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo request;
request.method = "GET";
@@ -11038,12 +11151,14 @@ TEST_P(HttpNetworkTransactionTest,
ASSERT_TRUE(ssl.cert.get());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> data(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
};
@@ -11403,6 +11518,7 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
HttpAuthHandlerMock::Factory* auth_factory(
new HttpAuthHandlerMock::Factory());
session_deps_.http_auth_handler_factory.reset(auth_factory);
+ SSLInfo empty_ssl_info;
const TestConfig& test_config = test_configs[i];
// Set up authentication handlers as necessary.
@@ -11414,7 +11530,7 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
auth_challenge.end());
auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
- origin, BoundNetLog());
+ empty_ssl_info, origin, BoundNetLog());
auth_handler->SetGenerateExpectation(
test_config.proxy_auth_timing == AUTH_ASYNC,
test_config.proxy_auth_rv);
@@ -11428,7 +11544,7 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
auth_challenge.end());
auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
- origin, BoundNetLog());
+ empty_ssl_info, origin, BoundNetLog());
auth_handler->SetGenerateExpectation(
test_config.server_auth_timing == AUTH_ASYNC,
test_config.server_auth_rv);
@@ -11537,8 +11653,9 @@ TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
GURL origin("http://www.example.com");
HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
auth_challenge.end());
+ SSLInfo empty_ssl_info;
auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
- origin, BoundNetLog());
+ empty_ssl_info, origin, BoundNetLog());
auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
int rv = OK;
@@ -11709,10 +11826,8 @@ TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
// This tests the case that a request is issued via http instead of spdy after
// npn is negotiated.
TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
- session_deps_.use_alternative_services = true;
- NextProtoVector next_protos;
- next_protos.push_back(kProtoHTTP11);
- session_deps_.next_protos = next_protos;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo request;
request.method = "GET";
@@ -11774,8 +11889,8 @@ TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
// immediate server closing of the socket.
// Regression test for https://crbug.com/46369.
TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
- session_deps_.use_alternative_services = true;
- session_deps_.next_protos = SpdyNextProtos();
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
HttpRequestInfo request;
request.method = "GET";
@@ -11786,8 +11901,8 @@ TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
ssl.SetNextProto(GetProtocol());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite spdy_writes[] = {CreateMockWrite(*req, 1)};
MockRead spdy_reads[] = {
@@ -11835,8 +11950,8 @@ class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
// This test ensures that the URL passed into the proxy is upgraded to https
// when doing an Alternate Protocol upgrade.
TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
- session_deps_.use_alternative_services = true;
- session_deps_.next_protos = SpdyNextProtos();
+ session_deps_.parse_alternative_services = false;
+ session_deps_.enable_alternative_service_with_different_host = false;
session_deps_.proxy_service =
ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
@@ -11895,10 +12010,12 @@ TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
// retry-http-when-alternate-protocol fails logic kicks in, which was more
// complicated to set up expectations for than the SPDY session.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> data(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite data_writes_2[] = {
// First connection attempt without Proxy-Authorization.
@@ -12354,12 +12471,14 @@ TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
// Test for crbug.com/55424.
TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> data(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 1), CreateMockRead(*data, 2), MockRead(ASYNC, 0, 3),
};
@@ -12764,8 +12883,8 @@ TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
}
TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
- session_deps_.use_alternative_services = true;
- session_deps_.next_protos = SpdyNextProtos();
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
// Set up a special HttpNetworkSession with a MockCachingHostResolver.
session_deps_.host_resolver.reset(new MockCachingHostResolver());
@@ -12777,21 +12896,21 @@ TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
ssl.SetNextProto(GetProtocol());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
- scoped_ptr<SpdyFrame> host1_req(
- spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> host1_req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
spdy_util_.UpdateWithStreamDestruction(1);
- scoped_ptr<SpdyFrame> host2_req(
- spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
+ scoped_ptr<SpdySerializedFrame> host2_req(
+ spdy_util_.ConstructSpdyGet("https://www.gmail.com", 3, LOWEST));
MockWrite spdy_writes[] = {
CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
};
- scoped_ptr<SpdyFrame> host1_resp(
+ scoped_ptr<SpdySerializedFrame> host1_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> host1_resp_body(
+ scoped_ptr<SpdySerializedFrame> host1_resp_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> host2_resp(
+ scoped_ptr<SpdySerializedFrame> host2_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> host2_resp_body(
+ scoped_ptr<SpdySerializedFrame> host2_resp_body(
spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead spdy_reads[] = {
CreateMockRead(*host1_resp, 1),
@@ -12801,9 +12920,7 @@ TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
MockRead(ASYNC, 0, 6),
};
- IPAddressNumber ip;
- ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
- IPEndPoint peer_addr = IPEndPoint(ip, 443);
+ IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
MockConnect connect(ASYNC, OK, peer_addr);
SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
@@ -12864,8 +12981,8 @@ TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
}
TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
- session_deps_.use_alternative_services = true;
- session_deps_.next_protos = SpdyNextProtos();
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
// Set up a special HttpNetworkSession with a MockCachingHostResolver.
session_deps_.host_resolver.reset(new MockCachingHostResolver());
@@ -12877,21 +12994,21 @@ TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
ssl.SetNextProto(GetProtocol());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
- scoped_ptr<SpdyFrame> host1_req(
- spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> host1_req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
spdy_util_.UpdateWithStreamDestruction(1);
- scoped_ptr<SpdyFrame> host2_req(
- spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
+ scoped_ptr<SpdySerializedFrame> host2_req(
+ spdy_util_.ConstructSpdyGet("https://www.gmail.com", 3, LOWEST));
MockWrite spdy_writes[] = {
CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
};
- scoped_ptr<SpdyFrame> host1_resp(
+ scoped_ptr<SpdySerializedFrame> host1_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> host1_resp_body(
+ scoped_ptr<SpdySerializedFrame> host1_resp_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> host2_resp(
+ scoped_ptr<SpdySerializedFrame> host2_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> host2_resp_body(
+ scoped_ptr<SpdySerializedFrame> host2_resp_body(
spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead spdy_reads[] = {
CreateMockRead(*host1_resp, 1),
@@ -12901,9 +13018,7 @@ TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
MockRead(ASYNC, 0, 6),
};
- IPAddressNumber ip;
- ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
- IPEndPoint peer_addr = IPEndPoint(ip, 443);
+ IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
MockConnect connect(ASYNC, OK, peer_addr);
SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
@@ -12992,8 +13107,8 @@ class OneTimeCachingHostResolver : public HostResolver {
TEST_P(HttpNetworkTransactionTest,
UseIPConnectionPoolingWithHostCacheExpiration) {
- session_deps_.use_alternative_services = true;
- session_deps_.next_protos = SpdyNextProtos();
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
// Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
@@ -13008,21 +13123,21 @@ TEST_P(HttpNetworkTransactionTest,
ssl.SetNextProto(GetProtocol());
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
- scoped_ptr<SpdyFrame> host1_req(
- spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> host1_req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
spdy_util_.UpdateWithStreamDestruction(1);
- scoped_ptr<SpdyFrame> host2_req(
- spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
+ scoped_ptr<SpdySerializedFrame> host2_req(
+ spdy_util_.ConstructSpdyGet("https://www.gmail.com", 3, LOWEST));
MockWrite spdy_writes[] = {
CreateMockWrite(*host1_req, 0), CreateMockWrite(*host2_req, 3),
};
- scoped_ptr<SpdyFrame> host1_resp(
+ scoped_ptr<SpdySerializedFrame> host1_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> host1_resp_body(
+ scoped_ptr<SpdySerializedFrame> host1_resp_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> host2_resp(
+ scoped_ptr<SpdySerializedFrame> host2_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> host2_resp_body(
+ scoped_ptr<SpdySerializedFrame> host2_resp_body(
spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead spdy_reads[] = {
CreateMockRead(*host1_resp, 1),
@@ -13032,9 +13147,7 @@ TEST_P(HttpNetworkTransactionTest,
MockRead(ASYNC, 0, 6),
};
- IPAddressNumber ip;
- ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
- IPEndPoint peer_addr = IPEndPoint(ip, 443);
+ IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
MockConnect connect(ASYNC, OK, peer_addr);
SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
@@ -13098,15 +13211,17 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
const std::string http_url = "http://www.example.org:8080/";
// SPDY GET for HTTPS URL
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
MockWrite writes1[] = {
CreateMockWrite(*req1, 0),
};
- scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp1(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body1(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads1[] = {CreateMockRead(*resp1, 1), CreateMockRead(*body1, 2),
MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
@@ -13199,19 +13314,19 @@ class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
url1.append(origin.host());
url1.append(":443");
- scoped_ptr<SpdyFrame> req0;
- scoped_ptr<SpdyFrame> req1;
- scoped_ptr<SpdyFrame> resp0;
- scoped_ptr<SpdyFrame> body0;
- scoped_ptr<SpdyFrame> resp1;
- scoped_ptr<SpdyFrame> body1;
+ scoped_ptr<SpdySerializedFrame> req0;
+ scoped_ptr<SpdySerializedFrame> req1;
+ scoped_ptr<SpdySerializedFrame> resp0;
+ scoped_ptr<SpdySerializedFrame> body0;
+ scoped_ptr<SpdySerializedFrame> resp1;
+ scoped_ptr<SpdySerializedFrame> body1;
std::vector<MockWrite> writes;
std::vector<MockRead> reads;
if (pooling) {
- req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST));
+ req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), 1, LOWEST));
spdy_util_.UpdateWithStreamDestruction(1);
- req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST));
+ req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), 3, LOWEST));
writes.push_back(CreateMockWrite(*req0, 0));
writes.push_back(CreateMockWrite(*req1, 3));
@@ -13228,7 +13343,7 @@ class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
reads.push_back(CreateMockRead(*body1, 6));
reads.push_back(MockRead(ASYNC, OK, 7));
} else {
- req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST));
+ req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), 1, LOWEST));
writes.push_back(CreateMockWrite(*req1, 0));
@@ -13250,7 +13365,8 @@ class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
data_refused.set_connect_data(mock_connect);
session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = true;
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
@@ -13258,7 +13374,7 @@ class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
AlternateProtocolFromNextProto(GetProtocol()), alternative);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(origin, alternative_service,
- 1.0, expiration);
+ expiration);
// First request to alternative.
if (pooling) {
@@ -13354,7 +13470,8 @@ TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
// Set up alternative service for origin.
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = true;
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
@@ -13362,7 +13479,7 @@ TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
AlternateProtocolFromNextProto(GetProtocol()), alternative);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(origin, alternative_service,
- 1.0, expiration);
+ expiration);
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -13427,7 +13544,8 @@ TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
session_deps_.socket_factory->AddSocketDataProvider(&http_data);
// Set up alternative service for origin.
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = true;
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
@@ -13435,7 +13553,7 @@ TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
AlternateProtocolFromNextProto(GetProtocol()), alternative);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(origin, alternative_service,
- 1.0, expiration);
+ expiration);
HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
HttpRequestInfo request1;
@@ -13536,7 +13654,8 @@ TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
// Set up alternative service for origin.
- session_deps_.use_alternative_services = true;
+ session_deps_.parse_alternative_services = true;
+ session_deps_.enable_alternative_service_with_different_host = false;
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
base::WeakPtr<HttpServerProperties> http_server_properties =
session->http_server_properties();
@@ -13544,7 +13663,7 @@ TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
AlternateProtocolFromNextProto(GetProtocol()), alternative);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties->SetAlternativeService(origin, alternative_service,
- 1.0, expiration);
+ expiration);
// First transaction to alternative to open an HTTP/1.1 socket.
scoped_ptr<HttpTransaction> trans1(
@@ -13615,11 +13734,11 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
// SPDY GET for HTTPS URL (through CONNECT tunnel)
const HostPortPair host_port_pair("www.example.org", 8080);
- scoped_ptr<SpdyFrame> connect(
+ scoped_ptr<SpdySerializedFrame> connect(
spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
- scoped_ptr<SpdyFrame> req1(
- spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
- scoped_ptr<SpdyFrame> wrapped_req1(
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> wrapped_req1(
spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
// SPDY GET for HTTP URL (through the proxy, but not the tunnel).
@@ -13629,24 +13748,28 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
req2_block[spdy_util_.GetSchemeKey()] = "http";
req2_block[spdy_util_.GetPathKey()] = "/";
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, true));
MockWrite writes1[] = {
CreateMockWrite(*connect, 0), CreateMockWrite(*wrapped_req1, 2),
CreateMockWrite(*req2, 6),
};
- scoped_ptr<SpdyFrame> conn_resp(
- spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> wrapped_resp1(
+ scoped_ptr<SpdySerializedFrame> conn_resp(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp1(
+ spdy_util_wrapped.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body1(
+ spdy_util_wrapped.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> wrapped_resp1(
spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
- scoped_ptr<SpdyFrame> wrapped_body1(
+ scoped_ptr<SpdySerializedFrame> wrapped_body1(
spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead reads1[] = {
CreateMockRead(*conn_resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 3),
@@ -13739,15 +13862,17 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
// SPDY GET for HTTP URL (through SPDY proxy)
scoped_ptr<SpdyHeaderBlock> headers(
spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, true));
MockWrite writes1[] = {
CreateMockWrite(*req1, 0),
};
- scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp1(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body1(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads1[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(*resp1, 2),
CreateMockRead(*body1, 3), MockRead(ASYNC, OK, 4), // EOF
@@ -13755,23 +13880,24 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
SequencedSocketData data1(reads1, arraysize(reads1), writes1,
arraysize(writes1));
- IPAddressNumber ip;
- ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
+ IPAddress ip;
+ ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
IPEndPoint peer_addr = IPEndPoint(ip, 443);
MockConnect connect_data1(ASYNC, OK, peer_addr);
data1.set_connect_data(connect_data1);
// SPDY GET for HTTPS URL (direct)
- scoped_ptr<SpdyFrame> req2(
- spdy_util_secure.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
MockWrite writes2[] = {
CreateMockWrite(*req2, 0),
};
- scoped_ptr<SpdyFrame> resp2(
+ scoped_ptr<SpdySerializedFrame> resp2(
spdy_util_secure.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body2(spdy_util_secure.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_secure.ConstructSpdyBodyFrame(1, true));
MockRead reads2[] = {CreateMockRead(*resp2, 1), CreateMockRead(*body2, 2),
MockRead(ASYNC, OK, 3)};
@@ -13856,14 +13982,16 @@ TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
SequencedSocketData data1(reads1, arraysize(reads1), NULL, 0);
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
MockWrite writes2[] = {
CreateMockWrite(*req2, 0),
};
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads2[] = {
CreateMockRead(*resp2, 1),
CreateMockRead(*body2, 2),
@@ -13913,7 +14041,6 @@ TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
}
TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
- session_deps_.next_protos = SpdyNextProtos();
ClientSocketPoolManager::set_max_sockets_per_group(
HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
ClientSocketPoolManager::set_max_sockets_per_pool(
@@ -13931,14 +14058,14 @@ TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
- scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
- "https://www.a.com", false, 1, DEFAULT_PRIORITY));
+ scoped_ptr<SpdySerializedFrame> host1_req(
+ spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
MockWrite spdy1_writes[] = {
CreateMockWrite(*host1_req, 0),
};
- scoped_ptr<SpdyFrame> host1_resp(
+ scoped_ptr<SpdySerializedFrame> host1_resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> host1_resp_body(
+ scoped_ptr<SpdySerializedFrame> host1_resp_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy1_reads[] = {
CreateMockRead(*host1_resp, 1), CreateMockRead(*host1_resp_body, 2),
@@ -13953,14 +14080,14 @@ TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
arraysize(spdy1_writes)));
session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
- scoped_ptr<SpdyFrame> host2_req(spdy_util_2.ConstructSpdyGet(
- "https://www.b.com", false, 1, DEFAULT_PRIORITY));
+ scoped_ptr<SpdySerializedFrame> host2_req(
+ spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
MockWrite spdy2_writes[] = {
CreateMockWrite(*host2_req, 0),
};
- scoped_ptr<SpdyFrame> host2_resp(
+ scoped_ptr<SpdySerializedFrame> host2_resp(
spdy_util_2.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> host2_resp_body(
+ scoped_ptr<SpdySerializedFrame> host2_resp_body(
spdy_util_2.ConstructSpdyBodyFrame(1, true));
MockRead spdy2_reads[] = {
CreateMockRead(*host2_resp, 1), CreateMockRead(*host2_resp_body, 2),
@@ -14413,6 +14540,12 @@ class FakeStream : public HttpStream,
bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override {
+ ADD_FAILURE();
+ return ERR_NOT_IMPLEMENTED;
+ }
+
void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
@@ -14521,7 +14654,7 @@ class FakeStreamFactory : public HttpStreamFactory {
return fake_request;
}
- HttpStreamRequest* RequestBidirectionalStreamJob(
+ HttpStreamRequest* RequestBidirectionalStreamImpl(
const HttpRequestInfo& info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
@@ -14644,6 +14777,12 @@ class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override {
+ ADD_FAILURE();
+ return ERR_NOT_IMPLEMENTED;
+ }
+
void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
@@ -15778,7 +15917,6 @@ TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
}
TEST_P(HttpNetworkTransactionTest, EnableNPN) {
- session_deps_.next_protos = NextProtosDefaults();
session_deps_.enable_npn = true;
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -15791,7 +15929,6 @@ TEST_P(HttpNetworkTransactionTest, EnableNPN) {
}
TEST_P(HttpNetworkTransactionTest, DisableNPN) {
- session_deps_.next_protos = NextProtosDefaults();
session_deps_.enable_npn = false;
scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -15802,4 +15939,42 @@ TEST_P(HttpNetworkTransactionTest, DisableNPN) {
EXPECT_TRUE(trans.server_ssl_config_.npn_protos.empty());
}
+#if !defined(OS_IOS)
+TEST_P(HttpNetworkTransactionTest, TokenBindingSpdy) {
+ const std::string https_url = "https://www.example.com";
+ HttpRequestInfo request;
+ request.url = GURL(https_url);
+ request.method = "GET";
+
+ SSLSocketDataProvider ssl(ASYNC, OK);
+ ssl.token_binding_negotiated = true;
+ ssl.token_binding_key_param = TB_PARAM_ECDSAP256;
+ ssl.SetNextProto(GetProtocol());
+ session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
+
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+ MockRead reads[] = {CreateMockRead(*resp), CreateMockRead(*body),
+ MockRead(ASYNC, ERR_IO_PENDING)};
+ StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+ session_deps_.channel_id_service.reset(new ChannelIDService(
+ new DefaultChannelIDStore(nullptr), base::ThreadTaskRunnerHandle::Get()));
+ scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
+ TestCompletionCallback callback;
+ EXPECT_EQ(ERR_IO_PENDING,
+ trans.Start(&request, callback.callback(), BoundNetLog()));
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_TRUE(trans.GetResponseInfo()->was_fetched_via_spdy);
+ HttpRequestHeaders headers;
+ ASSERT_TRUE(trans.GetFullRequestHeaders(&headers));
+ EXPECT_TRUE(headers.HasHeader(HttpRequestHeaders::kTokenBinding));
+}
+#endif // !defined(OS_IOS)
+
} // namespace net
diff --git a/chromium/net/http/http_proxy_client_socket.cc b/chromium/net/http/http_proxy_client_socket.cc
index 562bff36b90..5105a7001ba 100644
--- a/chromium/net/http/http_proxy_client_socket.cc
+++ b/chromium/net/http/http_proxy_client_socket.cc
@@ -13,7 +13,6 @@
#include "net/base/auth.h"
#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
-#include "net/base/net_util.h"
#include "net/base/proxy_delegate.h"
#include "net/http/http_basic_stream.h"
#include "net/http/http_network_session.h"
@@ -175,14 +174,6 @@ bool HttpProxyClientSocket::WasEverUsed() const {
return false;
}
-bool HttpProxyClientSocket::UsingTCPFastOpen() const {
- if (transport_.get() && transport_->socket()) {
- return transport_->socket()->UsingTCPFastOpen();
- }
- NOTREACHED();
- return false;
-}
-
bool HttpProxyClientSocket::WasNpnNegotiated() const {
if (transport_.get() && transport_->socket()) {
return transport_->socket()->WasNpnNegotiated();
diff --git a/chromium/net/http/http_proxy_client_socket.h b/chromium/net/http/http_proxy_client_socket.h
index a8a5d275ede..fb090e6d92e 100644
--- a/chromium/net/http/http_proxy_client_socket.h
+++ b/chromium/net/http/http_proxy_client_socket.h
@@ -68,7 +68,6 @@ class HttpProxyClientSocket : public ProxyClientSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
bool WasNpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
diff --git a/chromium/net/http/http_proxy_client_socket_pool.cc b/chromium/net/http/http_proxy_client_socket_pool.cc
index f0f8795a08a..5368ab9684d 100644
--- a/chromium/net/http/http_proxy_client_socket_pool.cc
+++ b/chromium/net/http/http_proxy_client_socket_pool.cc
@@ -51,11 +51,6 @@ HttpProxySocketParams::HttpProxySocketParams(
proxy_delegate_(proxy_delegate) {
DCHECK((transport_params.get() == NULL && ssl_params.get() != NULL) ||
(transport_params.get() != NULL && ssl_params.get() == NULL));
- if (transport_params_.get()) {
- ignore_limits_ = transport_params->ignore_limits();
- } else {
- ignore_limits_ = ssl_params->ignore_limits();
- }
}
const HostResolver::RequestInfo& HttpProxySocketParams::destination() const {
@@ -81,6 +76,7 @@ static const int kHttpProxyConnectJobTimeoutInSeconds = 30;
HttpProxyConnectJob::HttpProxyConnectJob(
const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const scoped_refptr<HttpProxySocketParams>& params,
const base::TimeDelta& timeout_duration,
TransportClientSocketPool* transport_pool,
@@ -90,11 +86,13 @@ HttpProxyConnectJob::HttpProxyConnectJob(
: ConnectJob(group_name,
base::TimeDelta() /* The socket takes care of timeouts */,
priority,
+ respect_limits,
delegate,
BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
client_socket_(new HttpProxyClientSocketWrapper(
group_name,
priority,
+ respect_limits,
timeout_duration,
base::TimeDelta::FromSeconds(kHttpProxyConnectJobTimeoutInSeconds),
transport_pool,
@@ -177,14 +175,10 @@ HttpProxyClientSocketPool::HttpProxyConnectJobFactory::NewConnectJob(
const std::string& group_name,
const PoolBase::Request& request,
ConnectJob::Delegate* delegate) const {
- return scoped_ptr<ConnectJob>(new HttpProxyConnectJob(group_name,
- request.priority(),
- request.params(),
- ConnectionTimeout(),
- transport_pool_,
- ssl_pool_,
- delegate,
- net_log_));
+ return scoped_ptr<ConnectJob>(new HttpProxyConnectJob(
+ group_name, request.priority(), request.respect_limits(),
+ request.params(), ConnectionTimeout(), transport_pool_, ssl_pool_,
+ delegate, net_log_));
}
base::TimeDelta
@@ -217,15 +211,18 @@ HttpProxyClientSocketPool::HttpProxyClientSocketPool(
HttpProxyClientSocketPool::~HttpProxyClientSocketPool() {
}
-int HttpProxyClientSocketPool::RequestSocket(
- const std::string& group_name, const void* socket_params,
- RequestPriority priority, ClientSocketHandle* handle,
- const CompletionCallback& callback, const BoundNetLog& net_log) {
+int HttpProxyClientSocketPool::RequestSocket(const std::string& group_name,
+ const void* socket_params,
+ RequestPriority priority,
+ RespectLimits respect_limits,
+ ClientSocketHandle* handle,
+ const CompletionCallback& callback,
+ const BoundNetLog& net_log) {
const scoped_refptr<HttpProxySocketParams>* casted_socket_params =
static_cast<const scoped_refptr<HttpProxySocketParams>*>(socket_params);
return base_.RequestSocket(group_name, *casted_socket_params, priority,
- handle, callback, net_log);
+ respect_limits, handle, callback, net_log);
}
void HttpProxyClientSocketPool::RequestSockets(
diff --git a/chromium/net/http/http_proxy_client_socket_pool.h b/chromium/net/http/http_proxy_client_socket_pool.h
index 44f9ab6703d..64c13f17cd3 100644
--- a/chromium/net/http/http_proxy_client_socket_pool.h
+++ b/chromium/net/http/http_proxy_client_socket_pool.h
@@ -70,7 +70,6 @@ class NET_EXPORT_PRIVATE HttpProxySocketParams
}
const HostResolver::RequestInfo& destination() const;
bool tunnel() const { return tunnel_; }
- bool ignore_limits() const { return ignore_limits_; }
ProxyDelegate* proxy_delegate() const {
return proxy_delegate_;
@@ -88,7 +87,6 @@ class NET_EXPORT_PRIVATE HttpProxySocketParams
HttpAuthCache* const http_auth_cache_;
HttpAuthHandlerFactory* const http_auth_handler_factory_;
const bool tunnel_;
- bool ignore_limits_;
ProxyDelegate* proxy_delegate_;
DISALLOW_COPY_AND_ASSIGN(HttpProxySocketParams);
@@ -100,6 +98,7 @@ class HttpProxyConnectJob : public ConnectJob {
public:
HttpProxyConnectJob(const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const scoped_refptr<HttpProxySocketParams>& params,
const base::TimeDelta& timeout_duration,
TransportClientSocketPool* transport_pool,
@@ -152,6 +151,7 @@ class NET_EXPORT_PRIVATE HttpProxyClientSocketPool
int RequestSocket(const std::string& group_name,
const void* connect_params,
RequestPriority priority,
+ RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) override;
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 97d7270fa67..1daca24825c 100644
--- a/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -11,6 +11,7 @@
#include "net/base/net_errors.h"
#include "net/base/proxy_delegate.h"
#include "net/base/test_completion_callback.h"
+#include "net/base/test_proxy_delegate.h"
#include "net/http/http_network_session.h"
#include "net/http/http_proxy_client_socket.h"
#include "net/http/http_response_headers.h"
@@ -61,97 +62,6 @@ typedef ::testing::TestWithParam<HttpProxyType> TestWithHttpParam;
const char kHttpProxyHost[] = "httpproxy.example.com";
const char kHttpsProxyHost[] = "httpsproxy.example.com";
-class TestProxyDelegate : public ProxyDelegate {
- public:
- TestProxyDelegate()
- : on_before_tunnel_request_called_(false),
- on_tunnel_request_completed_called_(false),
- on_tunnel_headers_received_called_(false) {
- }
-
- ~TestProxyDelegate() override {}
-
- bool on_before_tunnel_request_called() const {
- return on_before_tunnel_request_called_;
- }
-
- bool on_tunnel_request_completed_called() const {
- return on_tunnel_request_completed_called_;
- }
-
- bool on_tunnel_headers_received_called() const {
- return on_tunnel_headers_received_called_;
- }
-
- void VerifyOnTunnelRequestCompleted(const std::string& endpoint,
- const std::string& proxy_server) const {
- EXPECT_TRUE(on_tunnel_request_completed_called_);
- EXPECT_TRUE(HostPortPair::FromString(endpoint).Equals(
- on_tunnel_request_completed_endpoint_));
- EXPECT_TRUE(HostPortPair::FromString(proxy_server).Equals(
- on_tunnel_request_completed_proxy_server_));
- }
-
- void VerifyOnTunnelHeadersReceived(const std::string& origin,
- const std::string& proxy_server,
- const std::string& status_line) const {
- EXPECT_TRUE(on_tunnel_headers_received_called_);
- EXPECT_TRUE(HostPortPair::FromString(origin).Equals(
- on_tunnel_headers_received_origin_));
- EXPECT_TRUE(HostPortPair::FromString(proxy_server).Equals(
- on_tunnel_headers_received_proxy_server_));
- EXPECT_EQ(status_line, on_tunnel_headers_received_status_line_);
- }
-
- // ProxyDelegate:
- void OnResolveProxy(const GURL& url,
- int load_flags,
- const ProxyService& proxy_service,
- ProxyInfo* result) override {}
-
- void OnTunnelConnectCompleted(const HostPortPair& endpoint,
- const HostPortPair& proxy_server,
- int net_error) override {
- on_tunnel_request_completed_called_ = true;
- on_tunnel_request_completed_endpoint_ = endpoint;
- on_tunnel_request_completed_proxy_server_ = proxy_server;
- }
-
- void OnFallback(const ProxyServer& bad_proxy, int net_error) override {}
-
- void OnBeforeSendHeaders(URLRequest* request,
- const ProxyInfo& proxy_info,
- HttpRequestHeaders* headers) override {}
-
- void OnBeforeTunnelRequest(const HostPortPair& proxy_server,
- HttpRequestHeaders* extra_headers) override {
- on_before_tunnel_request_called_ = true;
- if (extra_headers) {
- extra_headers->SetHeader("Foo", proxy_server.ToString());
- }
- }
-
- void OnTunnelHeadersReceived(
- const HostPortPair& origin,
- const HostPortPair& proxy_server,
- const HttpResponseHeaders& response_headers) override {
- on_tunnel_headers_received_called_ = true;
- on_tunnel_headers_received_origin_ = origin;
- on_tunnel_headers_received_proxy_server_ = proxy_server;
- on_tunnel_headers_received_status_line_ = response_headers.GetStatusLine();
- }
-
- private:
- bool on_before_tunnel_request_called_;
- bool on_tunnel_request_completed_called_;
- bool on_tunnel_headers_received_called_;
- HostPortPair on_tunnel_request_completed_endpoint_;
- HostPortPair on_tunnel_request_completed_proxy_server_;
- HostPortPair on_tunnel_headers_received_origin_;
- HostPortPair on_tunnel_headers_received_proxy_server_;
- std::string on_tunnel_headers_received_status_line_;
-};
-
} // namespace
class HttpProxyClientSocketPoolTest
@@ -176,20 +86,18 @@ class HttpProxyClientSocketPoolTest
NULL,
session_deps_.ssl_config_service.get(),
BoundNetLog().net_log()),
- session_(CreateNetworkSession()),
spdy_util_(GetParam().protocol, GetParam().priority_to_dependency),
pool_(kMaxSockets,
kMaxSocketsPerGroup,
&transport_socket_pool_,
&ssl_socket_pool_,
NULL) {
- SpdySession::SetPriorityDependencyDefaultForTesting(
- GetParam().priority_to_dependency);
+ session_deps_.enable_priority_dependencies =
+ GetParam().priority_to_dependency;
+ session_ = CreateNetworkSession();
}
- virtual ~HttpProxyClientSocketPoolTest() {
- SpdySession::SetPriorityDependencyDefaultForTesting(false);
- }
+ virtual ~HttpProxyClientSocketPoolTest() {}
void AddAuthToCache() {
const base::string16 kFoo(base::ASCIIToUTF16("foo"));
@@ -211,7 +119,6 @@ class HttpProxyClientSocketPoolTest
return new TransportSocketParams(
HostPortPair(kHttpProxyHost, 80),
false,
- false,
OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT);
}
@@ -223,7 +130,6 @@ class HttpProxyClientSocketPoolTest
new TransportSocketParams(
HostPortPair(kHttpsProxyHost, 443),
false,
- false,
OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT),
NULL,
@@ -311,7 +217,7 @@ class HttpProxyClientSocketPoolTest
scoped_ptr<CertVerifier> cert_verifier_;
SSLClientSocketPool ssl_socket_pool_;
- const scoped_ptr<HttpNetworkSession> session_;
+ scoped_ptr<HttpNetworkSession> session_;
protected:
SpdyTestUtil spdy_util_;
@@ -347,6 +253,7 @@ TEST_P(HttpProxyClientSocketPoolTest, NoTunnel) {
scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
int rv = handle_.Init("a", CreateNoTunnelParams(proxy_delegate.get()), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
CompletionCallback(), &pool_, BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(handle_.is_initialized());
@@ -361,9 +268,9 @@ TEST_P(HttpProxyClientSocketPoolTest, NoTunnel) {
// (non-SSL) socket request on Init.
TEST_P(HttpProxyClientSocketPoolTest, SetSocketRequestPriorityOnInit) {
Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
- EXPECT_EQ(OK,
- handle_.Init("a", CreateNoTunnelParams(NULL), HIGHEST,
- CompletionCallback(), &pool_, BoundNetLog()));
+ EXPECT_EQ(OK, handle_.Init("a", CreateNoTunnelParams(NULL), HIGHEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ CompletionCallback(), &pool_, BoundNetLog()));
EXPECT_EQ(HIGHEST, GetLastTransportRequestPriority());
}
@@ -381,9 +288,9 @@ TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
MockRead(ASYNC, 3, "Content-Length: 10\r\n\r\n"),
MockRead(ASYNC, 4, "0123456789"),
};
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyConnect(
NULL, 0, 1, LOW, HostPortPair("www.google.com", 443)));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite spdy_writes[] = {
CreateMockWrite(*req, 0, ASYNC),
@@ -394,7 +301,8 @@ TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
resp_block["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
spdy_util_.MaybeAddVersionHeader(&resp_block);
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, resp_block));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyReply(1, resp_block));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 1, ASYNC),
MockRead(ASYNC, 0, 3)
@@ -405,6 +313,7 @@ TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
arraysize(spdy_writes));
int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
callback_.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle_.is_initialized());
@@ -454,6 +363,7 @@ TEST_P(HttpProxyClientSocketPoolTest, HaveAuth) {
scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
int rv = handle_.Init("a", CreateTunnelParams(proxy_delegate.get()), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
callback_.callback(), &pool_, BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(handle_.is_initialized());
@@ -487,13 +397,14 @@ TEST_P(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
};
- scoped_ptr<SpdyFrame> req(
+ scoped_ptr<SpdySerializedFrame> req(
spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
HostPortPair("www.google.com", 443)));
MockWrite spdy_writes[] = {
CreateMockWrite(*req, 0, ASYNC)
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 1, ASYNC),
// Connection stays open.
@@ -507,6 +418,7 @@ TEST_P(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
int rv = handle_.Init("a", CreateTunnelParams(proxy_delegate.get()), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
callback_.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle_.is_initialized());
@@ -528,13 +440,14 @@ TEST_P(HttpProxyClientSocketPoolTest,
if (GetParam().proxy_type != SPDY)
return;
- scoped_ptr<SpdyFrame> req(
+ scoped_ptr<SpdySerializedFrame> req(
spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, MEDIUM,
HostPortPair("www.google.com", 443)));
MockWrite spdy_writes[] = {
CreateMockWrite(*req, 0, ASYNC)
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 1, ASYNC),
MockRead(ASYNC, 0, 2)
@@ -547,6 +460,7 @@ TEST_P(HttpProxyClientSocketPoolTest,
EXPECT_EQ(ERR_IO_PENDING,
handle_.Init("a", CreateTunnelParams(NULL), MEDIUM,
+ ClientSocketPool::RespectLimits::ENABLED,
callback_.callback(), &pool_, BoundNetLog()));
EXPECT_EQ(MEDIUM, GetLastTransportRequestPriority());
@@ -561,6 +475,7 @@ TEST_P(HttpProxyClientSocketPoolTest, TCPError) {
socket_factory()->AddSocketDataProvider(data_.get());
int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
callback_.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle_.is_initialized());
@@ -586,6 +501,7 @@ TEST_P(HttpProxyClientSocketPoolTest, SSLError) {
socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
callback_.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle_.is_initialized());
@@ -611,6 +527,7 @@ TEST_P(HttpProxyClientSocketPoolTest, SslClientAuth) {
socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
callback_.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle_.is_initialized());
@@ -634,7 +551,7 @@ TEST_P(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
MockRead(ASYNC, 1, "HTTP/1.1 200 Conn"),
MockRead(ASYNC, ERR_CONNECTION_CLOSED, 2),
};
- scoped_ptr<SpdyFrame> req(
+ scoped_ptr<SpdySerializedFrame> req(
spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
HostPortPair("www.google.com", 443)));
MockWrite spdy_writes[] = {
@@ -650,6 +567,7 @@ TEST_P(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
AddAuthToCache();
int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
callback_.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle_.is_initialized());
@@ -688,6 +606,7 @@ TEST_P(HttpProxyClientSocketPoolTest, Tunnel1xxResponse) {
NULL, 0, NULL, 0);
int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
callback_.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle_.is_initialized());
@@ -707,16 +626,17 @@ TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupError) {
MockRead reads[] = {
MockRead(ASYNC, 1, "HTTP/1.1 304 Not Modified\r\n\r\n"),
};
- scoped_ptr<SpdyFrame> req(
+ scoped_ptr<SpdySerializedFrame> req(
spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
HostPortPair("www.google.com", 443)));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite spdy_writes[] = {
CreateMockWrite(*req, 0, ASYNC),
CreateMockWrite(*rst, 2, ASYNC),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdySynReplyError(1));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 1, ASYNC),
MockRead(ASYNC, 0, 3),
@@ -728,6 +648,7 @@ TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupError) {
AddAuthToCache();
int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
callback_.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle_.is_initialized());
@@ -757,10 +678,10 @@ TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupRedirect) {
MockRead reads[] = {
MockRead(ASYNC, 1, responseText.c_str()),
};
- scoped_ptr<SpdyFrame> req(
+ scoped_ptr<SpdySerializedFrame> req(
spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
HostPortPair("www.google.com", 443)));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite spdy_writes[] = {
@@ -773,11 +694,8 @@ TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupRedirect) {
"set-cookie", "foo=bar",
};
const int responseHeadersSize = arraysize(responseHeaders) / 2;
- scoped_ptr<SpdyFrame> resp(
- spdy_util_.ConstructSpdySynReplyError(
- "302 Found",
- responseHeaders, responseHeadersSize,
- 1));
+ scoped_ptr<SpdySerializedFrame> resp(spdy_util_.ConstructSpdySynReplyError(
+ "302 Found", responseHeaders, responseHeadersSize, 1));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 1, ASYNC),
MockRead(ASYNC, 0, 2),
@@ -789,6 +707,7 @@ TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupRedirect) {
AddAuthToCache();
int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
callback_.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle_.is_initialized());
diff --git a/chromium/net/http/http_proxy_client_socket_wrapper.cc b/chromium/net/http/http_proxy_client_socket_wrapper.cc
index 1a56a5c488f..bf9acbfa8a3 100644
--- a/chromium/net/http/http_proxy_client_socket_wrapper.cc
+++ b/chromium/net/http/http_proxy_client_socket_wrapper.cc
@@ -12,7 +12,6 @@
#include "base/memory/weak_ptr.h"
#include "base/profiler/scoped_tracker.h"
#include "base/values.h"
-#include "net/base/net_util.h"
#include "net/base/proxy_delegate.h"
#include "net/http/http_proxy_client_socket.h"
#include "net/http/http_response_info.h"
@@ -29,6 +28,7 @@ namespace net {
HttpProxyClientSocketWrapper::HttpProxyClientSocketWrapper(
const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
base::TimeDelta connect_timeout_duration,
base::TimeDelta proxy_negotiation_timeout_duration,
TransportClientSocketPool* transport_pool,
@@ -46,6 +46,7 @@ HttpProxyClientSocketWrapper::HttpProxyClientSocketWrapper(
: next_state_(STATE_NONE),
group_name_(group_name),
priority_(priority),
+ respect_limits_(respect_limits),
connect_timeout_duration_(connect_timeout_duration),
proxy_negotiation_timeout_duration_(proxy_negotiation_timeout_duration),
transport_pool_(transport_pool),
@@ -231,12 +232,6 @@ bool HttpProxyClientSocketWrapper::WasEverUsed() const {
return false;
}
-bool HttpProxyClientSocketWrapper::UsingTCPFastOpen() const {
- if (transport_socket_)
- return transport_socket_->UsingTCPFastOpen();
- return false;
-}
-
bool HttpProxyClientSocketWrapper::WasNpnNegotiated() const {
if (transport_socket_)
return transport_socket_->WasNpnNegotiated();
@@ -404,7 +399,7 @@ int HttpProxyClientSocketWrapper::DoTransportConnect() {
next_state_ = STATE_TCP_CONNECT_COMPLETE;
transport_socket_handle_.reset(new ClientSocketHandle());
return transport_socket_handle_->Init(
- group_name_, transport_params_, priority_,
+ group_name_, transport_params_, priority_, respect_limits_,
base::Bind(&HttpProxyClientSocketWrapper::OnIOComplete,
base::Unretained(this)),
transport_pool_, net_log_);
@@ -427,7 +422,7 @@ int HttpProxyClientSocketWrapper::DoSSLConnect() {
if (tunnel_) {
SpdySessionKey key(GetDestination().host_port_pair(), ProxyServer::Direct(),
PRIVACY_MODE_DISABLED);
- if (spdy_session_pool_->FindAvailableSession(key, net_log_)) {
+ if (spdy_session_pool_->FindAvailableSession(key, GURL(), net_log_)) {
using_spdy_ = true;
next_state_ = STATE_SPDY_PROXY_CREATE_STREAM;
return OK;
@@ -436,7 +431,7 @@ int HttpProxyClientSocketWrapper::DoSSLConnect() {
next_state_ = STATE_SSL_CONNECT_COMPLETE;
transport_socket_handle_.reset(new ClientSocketHandle());
return transport_socket_handle_->Init(
- group_name_, ssl_params_, priority_,
+ group_name_, ssl_params_, priority_, respect_limits_,
base::Bind(&HttpProxyClientSocketWrapper::OnIOComplete,
base::Unretained(this)),
ssl_pool_, net_log_);
@@ -525,7 +520,7 @@ int HttpProxyClientSocketWrapper::DoSpdyProxyCreateStream() {
SpdySessionKey key(GetDestination().host_port_pair(), ProxyServer::Direct(),
PRIVACY_MODE_DISABLED);
base::WeakPtr<SpdySession> spdy_session =
- spdy_session_pool_->FindAvailableSession(key, net_log_);
+ spdy_session_pool_->FindAvailableSession(key, GURL(), net_log_);
// It's possible that a session to the proxy has recently been created
if (spdy_session) {
if (transport_socket_handle_.get()) {
@@ -587,7 +582,7 @@ int HttpProxyClientSocketWrapper::DoRestartWithAuthComplete(int result) {
// TODO(mmenke): This may still result in waiting in line, if there are
// other HIGHEST priority requests. Consider a workaround for
// that. Starting the new request before releasing the old
- // socket and using LOAD_IGNORE_LIMITS would do the trick,
+ // socket and using RespectLimits::Disabled would work,
// without exceding the the socket pool limits (Since the old
// socket would free up the extra socket slot when destroyed).
priority_ = HIGHEST;
diff --git a/chromium/net/http/http_proxy_client_socket_wrapper.h b/chromium/net/http/http_proxy_client_socket_wrapper.h
index 70e3882be68..c83ccd690a6 100644
--- a/chromium/net/http/http_proxy_client_socket_wrapper.h
+++ b/chromium/net/http/http_proxy_client_socket_wrapper.h
@@ -55,6 +55,7 @@ class HttpProxyClientSocketWrapper : public ProxyClientSocket {
HttpProxyClientSocketWrapper(
const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
base::TimeDelta connect_timeout_duration,
base::TimeDelta proxy_negotiation_timeout_duration,
TransportClientSocketPool* transport_pool,
@@ -96,7 +97,6 @@ class HttpProxyClientSocketWrapper : public ProxyClientSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
bool WasNpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
@@ -168,6 +168,7 @@ class HttpProxyClientSocketWrapper : public ProxyClientSocket {
const std::string group_name_;
RequestPriority priority_;
+ ClientSocketPool::RespectLimits respect_limits_;
const base::TimeDelta connect_timeout_duration_;
const base::TimeDelta proxy_negotiation_timeout_duration_;
diff --git a/chromium/net/http/http_request_headers.cc b/chromium/net/http/http_request_headers.cc
index d3f1401c777..312702c03f7 100644
--- a/chromium/net/http/http_request_headers.cc
+++ b/chromium/net/http/http_request_headers.cc
@@ -36,8 +36,9 @@ const char HttpRequestHeaders::kProxyAuthorization[] = "Proxy-Authorization";
const char HttpRequestHeaders::kProxyConnection[] = "Proxy-Connection";
const char HttpRequestHeaders::kRange[] = "Range";
const char HttpRequestHeaders::kReferer[] = "Referer";
-const char HttpRequestHeaders::kUserAgent[] = "User-Agent";
const char HttpRequestHeaders::kTransferEncoding[] = "Transfer-Encoding";
+const char HttpRequestHeaders::kTokenBinding[] = "Sec-Token-Binding";
+const char HttpRequestHeaders::kUserAgent[] = "User-Agent";
HttpRequestHeaders::HeaderKeyValuePair::HeaderKeyValuePair() {
}
@@ -69,6 +70,8 @@ bool HttpRequestHeaders::Iterator::GetNext() {
}
HttpRequestHeaders::HttpRequestHeaders() {}
+HttpRequestHeaders::HttpRequestHeaders(const HttpRequestHeaders& other) =
+ default;
HttpRequestHeaders::~HttpRequestHeaders() {}
bool HttpRequestHeaders::GetHeader(const base::StringPiece& key,
diff --git a/chromium/net/http/http_request_headers.h b/chromium/net/http/http_request_headers.h
index 76bf25e4af4..c500d8c3aad 100644
--- a/chromium/net/http/http_request_headers.h
+++ b/chromium/net/http/http_request_headers.h
@@ -76,10 +76,12 @@ class NET_EXPORT HttpRequestHeaders {
static const char kProxyConnection[];
static const char kRange[];
static const char kReferer[];
- static const char kUserAgent[];
static const char kTransferEncoding[];
+ static const char kTokenBinding[];
+ static const char kUserAgent[];
HttpRequestHeaders();
+ HttpRequestHeaders(const HttpRequestHeaders& other);
~HttpRequestHeaders();
bool IsEmpty() const { return headers_.empty(); }
diff --git a/chromium/net/http/http_request_info.cc b/chromium/net/http/http_request_info.cc
index 794aa1c3a7c..d51d3d07bf1 100644
--- a/chromium/net/http/http_request_info.cc
+++ b/chromium/net/http/http_request_info.cc
@@ -13,6 +13,8 @@ HttpRequestInfo::HttpRequestInfo()
privacy_mode(PRIVACY_MODE_DISABLED) {
}
+HttpRequestInfo::HttpRequestInfo(const HttpRequestInfo& other) = default;
+
HttpRequestInfo::~HttpRequestInfo() {}
} // namespace net
diff --git a/chromium/net/http/http_request_info.h b/chromium/net/http/http_request_info.h
index 0c4c09defbc..ceca265be3b 100644
--- a/chromium/net/http/http_request_info.h
+++ b/chromium/net/http/http_request_info.h
@@ -28,6 +28,7 @@ struct NET_EXPORT HttpRequestInfo {
};
HttpRequestInfo();
+ HttpRequestInfo(const HttpRequestInfo& other);
~HttpRequestInfo();
// The requested URL.
@@ -51,6 +52,10 @@ struct NET_EXPORT HttpRequestInfo {
// If enabled, then request must be sent over connection that cannot be
// tracked by the server (e.g. without channel id).
PrivacyMode privacy_mode;
+
+ // If present, the host of the referrer whose TokenBindingID should be
+ // included in a referred TokenBinding.
+ std::string token_binding_referrer;
};
} // namespace net
diff --git a/chromium/net/http/http_response_body_drainer_unittest.cc b/chromium/net/http/http_response_body_drainer_unittest.cc
index 4568cbacce6..9ee6f84e03a 100644
--- a/chromium/net/http/http_response_body_drainer_unittest.cc
+++ b/chromium/net/http/http_response_body_drainer_unittest.cc
@@ -107,6 +107,11 @@ class MockHttpStream : public HttpStream {
void GetSSLInfo(SSLInfo* ssl_info) override {}
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {}
bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override {
+ ADD_FAILURE();
+ return ERR_NOT_IMPLEMENTED;
+ }
// Mocked API
int ReadResponseBody(IOBuffer* buf,
diff --git a/chromium/net/http/http_response_headers.cc b/chromium/net/http/http_response_headers.cc
index ba51cfdbc57..8f8ce9d38aa 100644
--- a/chromium/net/http/http_response_headers.cc
+++ b/chromium/net/http/http_response_headers.cc
@@ -313,7 +313,7 @@ void HttpResponseHeaders::RemoveHeaderLine(const std::string& name,
new_raw_headers.reserve(raw_headers_.size());
- void* iter = NULL;
+ size_t iter = 0;
std::string old_header_name;
std::string old_header_value;
while (EnumerateHeaderLines(&iter, &old_header_name, &old_header_value)) {
@@ -549,10 +549,10 @@ std::string HttpResponseHeaders::GetStatusText() const {
return std::string(begin, end);
}
-bool HttpResponseHeaders::EnumerateHeaderLines(void** iter,
+bool HttpResponseHeaders::EnumerateHeaderLines(size_t* iter,
std::string* name,
std::string* value) const {
- size_t i = reinterpret_cast<size_t>(*iter);
+ size_t i = *iter;
if (i == parsed_.size())
return false;
@@ -567,18 +567,18 @@ bool HttpResponseHeaders::EnumerateHeaderLines(void** iter,
value->assign(value_begin, value_end);
- *iter = reinterpret_cast<void*>(i);
+ *iter = i;
return true;
}
-bool HttpResponseHeaders::EnumerateHeader(void** iter,
+bool HttpResponseHeaders::EnumerateHeader(size_t* iter,
const base::StringPiece& name,
std::string* value) const {
size_t i;
if (!iter || !*iter) {
i = FindHeader(0, name);
} else {
- i = reinterpret_cast<size_t>(*iter);
+ i = *iter;
if (i >= parsed_.size()) {
i = std::string::npos;
} else if (!parsed_[i].is_continuation()) {
@@ -592,7 +592,7 @@ bool HttpResponseHeaders::EnumerateHeader(void** iter,
}
if (iter)
- *iter = reinterpret_cast<void*>(i + 1);
+ *iter = i + 1;
value->assign(parsed_[i].value_begin, parsed_[i].value_end);
return true;
}
@@ -601,7 +601,7 @@ bool HttpResponseHeaders::HasHeaderValue(const base::StringPiece& name,
const base::StringPiece& value) const {
// The value has to be an exact match. This is important since
// 'cache-control: no-cache' != 'cache-control: no-cache="foo"'
- void* iter = NULL;
+ size_t iter = 0;
std::string temp;
while (EnumerateHeader(&iter, name, &temp)) {
if (base::EqualsCaseInsensitiveASCII(value, temp))
@@ -757,7 +757,7 @@ bool HttpResponseHeaders::GetCacheControlDirective(const StringPiece& directive,
size_t directive_size = directive.size();
- void* iter = NULL;
+ size_t iter = 0;
while (EnumerateHeader(&iter, name, &value)) {
if (value.size() > directive_size + 1 &&
base::StartsWith(value, directive,
@@ -814,7 +814,7 @@ void HttpResponseHeaders::AddNonCacheableHeaders(HeaderSet* result) const {
const size_t kPrefixLen = sizeof(kPrefix) - 1;
std::string value;
- void* iter = NULL;
+ size_t iter = 0;
while (EnumerateHeader(&iter, kCacheControl, &value)) {
// If the value is smaller than the prefix and a terminal quote, skip
// it.
@@ -889,7 +889,7 @@ void HttpResponseHeaders::GetMimeTypeAndCharset(std::string* mime_type,
bool had_charset = false;
- void* iter = NULL;
+ size_t iter = 0;
while (EnumerateHeader(&iter, name, &value))
HttpUtil::ParseContentType(value, mime_type, charset, &had_charset, NULL);
}
@@ -1152,7 +1152,7 @@ bool HttpResponseHeaders::GetMaxAgeValue(TimeDelta* result) const {
bool HttpResponseHeaders::GetAgeValue(TimeDelta* result) const {
std::string value;
- if (!EnumerateHeader(NULL, "Age", &value))
+ if (!EnumerateHeader(nullptr, "Age", &value))
return false;
int64_t seconds;
@@ -1181,7 +1181,7 @@ bool HttpResponseHeaders::GetStaleWhileRevalidateValue(
bool HttpResponseHeaders::GetTimeValuedHeader(const std::string& name,
Time* result) const {
std::string value;
- if (!EnumerateHeader(NULL, name, &value))
+ if (!EnumerateHeader(nullptr, name, &value))
return false;
// When parsing HTTP dates it's beneficial to default to GMT because:
@@ -1223,7 +1223,7 @@ bool HttpResponseHeaders::IsKeepAlive() const {
return false;
for (const char* header : kConnectionHeaders) {
- void* iterator = nullptr;
+ size_t iterator = 0;
std::string token;
while (EnumerateHeader(&iterator, header, &token)) {
for (const KeepAliveToken& keep_alive_token : kKeepAliveTokens) {
@@ -1237,17 +1237,26 @@ bool HttpResponseHeaders::IsKeepAlive() const {
bool HttpResponseHeaders::HasStrongValidators() const {
std::string etag_header;
- EnumerateHeader(NULL, "etag", &etag_header);
+ EnumerateHeader(nullptr, "etag", &etag_header);
std::string last_modified_header;
- EnumerateHeader(NULL, "Last-Modified", &last_modified_header);
+ EnumerateHeader(nullptr, "Last-Modified", &last_modified_header);
std::string date_header;
- EnumerateHeader(NULL, "Date", &date_header);
+ EnumerateHeader(nullptr, "Date", &date_header);
return HttpUtil::HasStrongValidators(GetHttpVersion(),
etag_header,
last_modified_header,
date_header);
}
+bool HttpResponseHeaders::HasValidators() const {
+ std::string etag_header;
+ EnumerateHeader(NULL, "etag", &etag_header);
+ std::string last_modified_header;
+ EnumerateHeader(NULL, "Last-Modified", &last_modified_header);
+ return HttpUtil::HasValidators(GetHttpVersion(), etag_header,
+ last_modified_header);
+}
+
// From RFC 2616:
// Content-Length = "Content-Length" ":" 1*DIGIT
int64_t HttpResponseHeaders::GetContentLength() const {
@@ -1256,7 +1265,7 @@ int64_t HttpResponseHeaders::GetContentLength() const {
int64_t HttpResponseHeaders::GetInt64HeaderValue(
const std::string& header) const {
- void* iter = NULL;
+ size_t iter = 0;
std::string content_length_val;
if (!EnumerateHeader(&iter, header, &content_length_val))
return -1;
@@ -1284,7 +1293,7 @@ int64_t HttpResponseHeaders::GetInt64HeaderValue(
bool HttpResponseHeaders::GetContentRange(int64_t* first_byte_position,
int64_t* last_byte_position,
int64_t* instance_length) const {
- void* iter = NULL;
+ 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))
@@ -1394,7 +1403,7 @@ scoped_ptr<base::Value> HttpResponseHeaders::NetLogCallback(
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
base::ListValue* headers = new base::ListValue();
headers->Append(new base::StringValue(GetStatusLine()));
- void* iterator = NULL;
+ size_t iterator = 0;
std::string name;
std::string value;
while (EnumerateHeaderLines(&iterator, &name, &value)) {
diff --git a/chromium/net/http/http_response_headers.h b/chromium/net/http/http_response_headers.h
index 91c223ebe81..a3126aa72d7 100644
--- a/chromium/net/http/http_response_headers.h
+++ b/chromium/net/http/http_response_headers.h
@@ -141,9 +141,6 @@ class NET_EXPORT HttpResponseHeaders
// NOTE: Do not make any assumptions about the encoding of this output
// string. It may be non-ASCII, and the encoding used by the server is not
// necessarily known to us. Do not assume that this output is UTF-8!
- //
- // TODO(darin): remove this method
- //
bool GetNormalizedHeader(const std::string& name, std::string* value) const;
// Returns the normalized status line.
@@ -163,20 +160,38 @@ class NET_EXPORT HttpResponseHeaders
// header appears on multiple lines, then it will appear multiple times in
// this enumeration (in the order the header lines were received from the
// server). Also, a given header might have an empty value. Initialize a
- // 'void*' variable to NULL and pass it by address to EnumerateHeaderLines.
+ // 'size_t' variable to 0 and pass it by address to EnumerateHeaderLines.
// Call EnumerateHeaderLines repeatedly until it returns false. The
// out-params 'name' and 'value' are set upon success.
- bool EnumerateHeaderLines(void** iter,
+ bool EnumerateHeaderLines(size_t* iter,
std::string* name,
std::string* value) const;
// Enumerate the values of the specified header. If you are only interested
- // in the first header, then you can pass NULL for the 'iter' parameter.
+ // in the first header, then you can pass nullptr for the 'iter' parameter.
// Otherwise, to iterate across all values for the specified header,
- // initialize a 'void*' variable to NULL and pass it by address to
+ // initialize a 'size_t' variable to 0 and pass it by address to
// EnumerateHeader. Note that a header might have an empty value. Call
// EnumerateHeader repeatedly until it returns false.
- bool EnumerateHeader(void** iter,
+ //
+ // Unless a header is explicitly marked as non-coalescing (see
+ // HttpUtil::IsNonCoalescingHeader), headers that contain
+ // comma-separated lists are treated "as if" they had been sent as
+ // distinct headers. That is, a header of "Foo: a, b, c" would
+ // enumerate into distinct values of "a", "b", and "c". This is also
+ // true for headers that occur multiple times in a response; unless
+ // they are marked non-coalescing, "Foo: a, b" followed by "Foo: c"
+ // will enumerate to "a", "b", "c". Commas inside quoted strings are ignored,
+ // for example a header of 'Foo: "a, b", "c"' would enumerate as '"a, b"',
+ // '"c"'.
+ //
+ // This can cause issues for headers that might have commas in fields that
+ // aren't quoted strings, for example a header of "Foo: <a, b>, <c>" would
+ // enumerate as '<a', 'b>', '<c>', rather than as '<a, b>', '<c>'.
+ //
+ // To handle cases such as this, use GetNormalizedHeader to return the full
+ // concatenated header, and then parse manually.
+ bool EnumerateHeader(size_t* iter,
const base::StringPiece& name,
std::string* value) const;
@@ -258,6 +273,11 @@ class NET_EXPORT HttpResponseHeaders
// See section 13.3.3 of RFC 2616.
bool HasStrongValidators() const;
+ // Returns true if this response has any validator (either a Last-Modified or
+ // an ETag) regardless of whether it is strong or weak. See section 13.3.3 of
+ // RFC 2616.
+ bool HasValidators() const;
+
// Extracts the value of the Content-Length header or returns -1 if there is
// no such header in the response.
int64_t GetContentLength() const;
diff --git a/chromium/net/http/http_response_headers_unittest.cc b/chromium/net/http/http_response_headers_unittest.cc
index 1bc99bbd7b8..70a5d09562a 100644
--- a/chromium/net/http/http_response_headers_unittest.cc
+++ b/chromium/net/http/http_response_headers_unittest.cc
@@ -457,7 +457,7 @@ TEST(HttpResponseHeadersTest, EnumerateHeader_Coalesced) {
HeadersToRaw(&headers);
scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
- void* iter = NULL;
+ size_t iter = 0;
std::string value;
EXPECT_TRUE(parsed->EnumerateHeader(&iter, "cache-control", &value));
EXPECT_EQ("private", value);
@@ -478,7 +478,7 @@ TEST(HttpResponseHeadersTest, EnumerateHeader_Challenge) {
HeadersToRaw(&headers);
scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
- void* iter = NULL;
+ size_t iter = 0;
std::string value;
EXPECT_TRUE(parsed->EnumerateHeader(&iter, "WWW-Authenticate", &value));
EXPECT_EQ("Digest realm=foobar, nonce=x, domain=y", value);
@@ -1055,7 +1055,7 @@ TEST_P(EnumerateHeaderLinesTest, EnumerateHeaderLines) {
std::string name, value, lines;
- void* iter = NULL;
+ size_t iter = 0;
while (parsed->EnumerateHeaderLines(&iter, &name, &value)) {
lines.append(name);
lines.append(": ");
@@ -1634,6 +1634,40 @@ INSTANTIATE_TEST_CASE_P(HttpResponseHeaders,
HasStrongValidatorsTest,
testing::ValuesIn(strong_validators_tests));
+TEST(HttpResponseHeadersTest, HasValidatorsNone) {
+ std::string headers("HTTP/1.1 200 OK");
+ HeadersToRaw(&headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
+ EXPECT_FALSE(parsed->HasValidators());
+}
+
+TEST(HttpResponseHeadersTest, HasValidatorsEtag) {
+ std::string headers(
+ "HTTP/1.1 200 OK\n"
+ "etag: \"anything\"");
+ HeadersToRaw(&headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
+ EXPECT_TRUE(parsed->HasValidators());
+}
+
+TEST(HttpResponseHeadersTest, HasValidatorsLastModified) {
+ std::string headers(
+ "HTTP/1.1 200 OK\n"
+ "Last-Modified: Wed, 28 Nov 2007 00:40:10 GMT");
+ HeadersToRaw(&headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
+ EXPECT_TRUE(parsed->HasValidators());
+}
+
+TEST(HttpResponseHeadersTest, HasValidatorsWeakEtag) {
+ std::string headers(
+ "HTTP/1.1 200 OK\n"
+ "etag: W/\"anything\"");
+ HeadersToRaw(&headers);
+ scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers));
+ EXPECT_TRUE(parsed->HasValidators());
+}
+
struct AddHeaderTestData {
const char* orig_headers;
const char* new_header;
diff --git a/chromium/net/http/http_security_headers.cc b/chromium/net/http/http_security_headers.cc
index ecb8e57d2b3..5174825cc9a 100644
--- a/chromium/net/http/http_security_headers.cc
+++ b/chromium/net/http/http_security_headers.cc
@@ -20,14 +20,16 @@ namespace {
enum MaxAgeParsing { REQUIRE_MAX_AGE, DO_NOT_REQUIRE_MAX_AGE };
static_assert(kMaxHSTSAgeSecs <= UINT32_MAX, "kMaxHSTSAgeSecs too large");
+static_assert(kMaxHPKPAgeSecs <= UINT32_MAX, "kMaxHPKPAgeSecs too large");
-// MaxAgeToInt converts a string representation of a "whole number" of
+// MaxAgeToLimitedInt converts a string representation of a "whole number" of
// seconds into a uint32_t. The string may contain an arbitrarily large number,
-// which will be clipped to kMaxHSTSAgeSecs and which is guaranteed to fit
+// which will be clipped to a supplied limit and which is guaranteed to fit
// within a 32-bit unsigned integer. False is returned on any parse error.
-bool MaxAgeToInt(std::string::const_iterator begin,
- std::string::const_iterator end,
- uint32_t* result) {
+bool MaxAgeToLimitedInt(std::string::const_iterator begin,
+ std::string::const_iterator end,
+ uint32_t limit,
+ uint32_t* result) {
const base::StringPiece s(begin, end);
if (s.empty())
return false;
@@ -39,15 +41,14 @@ bool MaxAgeToInt(std::string::const_iterator begin,
// properly handle and reject negative numbers (StringToUint64 does not return
// false on negative numbers). For values too large to be stored in an
// int64_t, StringToInt64 will return false with i set to
- // std::numeric_limits<int64_t>::max(), so this case is detected by the
- // immediately following if-statement and allowed to fall through so that i
- // gets clipped to kMaxHSTSAgeSecs.
+ // std::numeric_limits<int64_t>::max(), so this case is allowed to fall
+ // through so that i gets clipped to limit.
if (!base::StringToInt64(s, &i) && i != std::numeric_limits<int64_t>::max())
return false;
if (i < 0)
return false;
- if (i > kMaxHSTSAgeSecs)
- i = kMaxHSTSAgeSecs;
+ if (i > limit)
+ i = limit;
*result = (uint32_t)i;
return true;
}
@@ -143,8 +144,9 @@ bool ParseHPKPHeaderImpl(const std::string& value,
base::StringPiece(name_value_pairs.name_begin(),
name_value_pairs.name_end()),
"max-age")) {
- if (!MaxAgeToInt(name_value_pairs.value_begin(),
- name_value_pairs.value_end(), &max_age_candidate)) {
+ if (!MaxAgeToLimitedInt(name_value_pairs.value_begin(),
+ name_value_pairs.value_end(), kMaxHPKPAgeSecs,
+ &max_age_candidate)) {
return false;
}
parsed_max_age = true;
@@ -280,7 +282,8 @@ bool ParseHSTSHeader(const std::string& value,
if (base::IsAsciiWhitespace(*tokenizer.token_begin()))
continue;
unquoted = HttpUtil::Unquote(tokenizer.token());
- if (!MaxAgeToInt(unquoted.begin(), unquoted.end(), &max_age_candidate))
+ if (!MaxAgeToLimitedInt(unquoted.begin(), unquoted.end(),
+ kMaxHSTSAgeSecs, &max_age_candidate))
return false;
state = AFTER_MAX_AGE;
break;
@@ -304,7 +307,7 @@ bool ParseHSTSHeader(const std::string& value,
}
}
- // We've consumed all the input. Let's see what state we ended up in.
+ // We've consumed all the input. Let's see what state we ended up in.
if (max_age_observed != 1 ||
(include_subdomains_observed != 0 && include_subdomains_observed != 1)) {
return false;
diff --git a/chromium/net/http/http_security_headers.h b/chromium/net/http/http_security_headers.h
index af904307870..a2ddad2d46e 100644
--- a/chromium/net/http/http_security_headers.h
+++ b/chromium/net/http/http_security_headers.h
@@ -20,6 +20,10 @@ namespace net {
const int64_t kMaxHSTSAgeSecs = 86400 * 365; // 1 year
+// RFC7469 suggests that 60 days is a reasonable maximum max-age value
+// http://tools.ietf.org/html/rfc7469#section-4.1
+const int64_t kMaxHPKPAgeSecs = 86400 * 60; // 60 days
+
// Parses |value| as a Strict-Transport-Security header value. If successful,
// returns true and sets |*max_age| and |*include_subdomains|.
// Otherwise returns false and leaves the output parameters unchanged.
diff --git a/chromium/net/http/http_security_headers_unittest.cc b/chromium/net/http/http_security_headers_unittest.cc
index 9c0997217b3..7e80efa3270 100644
--- a/chromium/net/http/http_security_headers_unittest.cc
+++ b/chromium/net/http/http_security_headers_unittest.cc
@@ -530,7 +530,7 @@ static void TestValidPKPHeaders(HashValueTag tag) {
"max-age=39408299 ;" + backup_pin + ";" + good_pin + "; ", chain_hashes,
&max_age, &include_subdomains, &hashes, &report_uri));
expect_max_age = base::TimeDelta::FromSeconds(
- std::min(kMaxHSTSAgeSecs, static_cast<int64_t>(INT64_C(39408299))));
+ std::min(kMaxHPKPAgeSecs, static_cast<int64_t>(INT64_C(39408299))));
EXPECT_EQ(expect_max_age, max_age);
EXPECT_FALSE(include_subdomains);
@@ -539,7 +539,7 @@ static void TestValidPKPHeaders(HashValueTag tag) {
good_pin + ";" + backup_pin + "; ",
chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri));
expect_max_age = base::TimeDelta::FromSeconds(
- std::min(kMaxHSTSAgeSecs, static_cast<int64_t>(INT64_C(394082038))));
+ std::min(kMaxHPKPAgeSecs, static_cast<int64_t>(INT64_C(394082038))));
EXPECT_EQ(expect_max_age, max_age);
EXPECT_TRUE(include_subdomains);
@@ -561,7 +561,7 @@ static void TestValidPKPHeaders(HashValueTag tag) {
" max-age=999999999999999999999999999999999999999999999 ; " +
backup_pin + ";" + good_pin + "; ",
chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri));
- expect_max_age = base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs);
+ expect_max_age = base::TimeDelta::FromSeconds(kMaxHPKPAgeSecs);
EXPECT_EQ(expect_max_age, max_age);
EXPECT_FALSE(include_subdomains);
@@ -570,7 +570,7 @@ static void TestValidPKPHeaders(HashValueTag tag) {
backup_pin + ";" + good_pin +
"; report-uri=\"http://example.test/foo\"",
chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri));
- expect_max_age = base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs);
+ expect_max_age = base::TimeDelta::FromSeconds(kMaxHPKPAgeSecs);
expect_report_uri = GURL("http://example.test/foo");
EXPECT_EQ(expect_max_age, max_age);
EXPECT_FALSE(include_subdomains);
diff --git a/chromium/net/http/http_server_properties.cc b/chromium/net/http/http_server_properties.cc
index fc6281e43b5..850418d0b39 100644
--- a/chromium/net/http/http_server_properties.cc
+++ b/chromium/net/http/http_server_properties.cc
@@ -97,11 +97,10 @@ std::string AlternativeService::ToString() const {
std::string AlternativeServiceInfo::ToString() const {
base::Time::Exploded exploded;
expiration.LocalExplode(&exploded);
- return base::StringPrintf("%s, p=%f, expires %04d-%02d-%02d %02d:%02d:%02d",
- alternative_service.ToString().c_str(), probability,
- exploded.year, exploded.month,
- exploded.day_of_month, exploded.hour,
- exploded.minute, exploded.second);
+ return base::StringPrintf(
+ "%s, expires %04d-%02d-%02d %02d:%02d:%02d",
+ alternative_service.ToString().c_str(), exploded.year, exploded.month,
+ exploded.day_of_month, exploded.hour, exploded.minute, exploded.second);
}
// static
diff --git a/chromium/net/http/http_server_properties.h b/chromium/net/http/http_server_properties.h
index b8ea59b2c4f..44224db76f6 100644
--- a/chromium/net/http/http_server_properties.h
+++ b/chromium/net/http/http_server_properties.h
@@ -17,7 +17,6 @@
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "net/base/host_port_pair.h"
-#include "net/base/ip_address_number.h"
#include "net/base/net_export.h"
#include "net/quic/quic_bandwidth.h"
#include "net/quic/quic_server_id.h"
@@ -31,6 +30,7 @@ class Value;
namespace net {
+class IPAddress;
struct SSLConfig;
enum AlternateProtocolUsage {
@@ -138,22 +138,18 @@ struct NET_EXPORT AlternativeService {
};
struct NET_EXPORT AlternativeServiceInfo {
- AlternativeServiceInfo() : alternative_service(), probability(0.0) {}
+ AlternativeServiceInfo() : alternative_service() {}
AlternativeServiceInfo(const AlternativeService& alternative_service,
- double probability,
base::Time expiration)
: alternative_service(alternative_service),
- probability(probability),
expiration(expiration) {}
AlternativeServiceInfo(AlternateProtocol protocol,
const std::string& host,
uint16_t port,
- double probability,
base::Time expiration)
: alternative_service(protocol, host, port),
- probability(probability),
expiration(expiration) {}
AlternativeServiceInfo(
@@ -163,7 +159,7 @@ struct NET_EXPORT AlternativeServiceInfo {
bool operator==(const AlternativeServiceInfo& other) const {
return alternative_service == other.alternative_service &&
- probability == other.probability && expiration == other.expiration;
+ expiration == other.expiration;
}
bool operator!=(const AlternativeServiceInfo& other) const {
@@ -173,7 +169,6 @@ struct NET_EXPORT AlternativeServiceInfo {
std::string ToString() const;
AlternativeService alternative_service;
- double probability;
base::Time expiration;
};
@@ -265,8 +260,7 @@ class NET_EXPORT HttpServerProperties {
virtual void MaybeForceHTTP11(const HostPortPair& server,
SSLConfig* ssl_config) = 0;
- // Return all alternative services for |origin| with probability greater than
- // or equal to the threshold, including broken ones.
+ // Return all alternative services for |origin|, including broken ones.
// Returned alternative services never have empty hostnames.
virtual AlternativeServiceVector GetAlternativeServices(
const HostPortPair& origin) = 0;
@@ -278,7 +272,6 @@ class NET_EXPORT HttpServerProperties {
virtual bool SetAlternativeService(
const HostPortPair& origin,
const AlternativeService& alternative_service,
- double alternative_probability,
base::Time expiration) = 0;
// Set alternative services for |origin|. Previous alternative services for
@@ -325,13 +318,6 @@ class NET_EXPORT HttpServerProperties {
// Empty alternative service hostnames will be printed as such.
virtual scoped_ptr<base::Value> GetAlternativeServiceInfoAsValue() const = 0;
- // Sets the threshold to be used when evaluating alternative service
- // advertisments. Only advertisements with a probability greater than or equal
- // to |threshold| will be honored. |threshold| must be between 0.0 and 1.0
- // inclusive. Hence, a threshold of 0.0 implies that all advertisements will
- // be honored.
- virtual void SetAlternativeServiceProbabilityThreshold(double threshold) = 0;
-
// Gets a reference to the SettingsMap stored for a host.
// If no settings are stored, returns an empty SettingsMap.
virtual const SettingsMap& GetSpdySettings(
@@ -353,10 +339,10 @@ class NET_EXPORT HttpServerProperties {
// Returns all persistent SPDY settings.
virtual const SpdySettingsMap& spdy_settings_map() const = 0;
- virtual bool GetSupportsQuic(IPAddressNumber* last_address) const = 0;
+ virtual bool GetSupportsQuic(IPAddress* last_address) const = 0;
virtual void SetSupportsQuic(bool used_quic,
- const IPAddressNumber& last_address) = 0;
+ const IPAddress& last_address) = 0;
// Sets |stats| for |host_port_pair|.
virtual void SetServerNetworkStats(const HostPortPair& host_port_pair,
diff --git a/chromium/net/http/http_server_properties_impl.cc b/chromium/net/http/http_server_properties_impl.cc
index 662aab64b8d..a0a6bfe644f 100644
--- a/chromium/net/http/http_server_properties_impl.cc
+++ b/chromium/net/http/http_server_properties_impl.cc
@@ -32,7 +32,6 @@ HttpServerPropertiesImpl::HttpServerPropertiesImpl()
alternative_service_map_(AlternativeServiceMap::NO_AUTO_EVICT),
spdy_settings_map_(SpdySettingsMap::NO_AUTO_EVICT),
server_network_stats_map_(ServerNetworkStatsMap::NO_AUTO_EVICT),
- alternative_service_probability_threshold_(1.0),
quic_server_info_map_(QuicServerInfoMap::NO_AUTO_EVICT),
max_server_configs_stored_in_properties_(kMaxQuicServersToPersist),
weak_ptr_factory_(this) {
@@ -152,8 +151,7 @@ void HttpServerPropertiesImpl::InitializeSpdySettingsServers(
}
}
-void HttpServerPropertiesImpl::InitializeSupportsQuic(
- IPAddressNumber* last_address) {
+void HttpServerPropertiesImpl::InitializeSupportsQuic(IPAddress* last_address) {
if (last_address)
last_quic_address_ = *last_address;
}
@@ -230,7 +228,7 @@ void HttpServerPropertiesImpl::Clear() {
alternative_service_map_.Clear();
canonical_host_to_origin_map_.clear();
spdy_settings_map_.Clear();
- last_quic_address_.clear();
+ last_quic_address_ = IPAddress();
server_network_stats_map_.Clear();
quic_server_info_map_.Clear();
}
@@ -324,9 +322,8 @@ std::string HttpServerPropertiesImpl::GetCanonicalSuffix(
AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices(
const HostPortPair& origin) {
- // Copy alternative services with probability greater than or equal to the
- // threshold into |alternative_services_above_threshold|.
- AlternativeServiceVector alternative_services_above_threshold;
+ // Copy valid alternative services into |valid_alternative_services|.
+ AlternativeServiceVector valid_alternative_services;
const base::Time now = base::Time::Now();
AlternativeServiceMap::iterator map_it = alternative_service_map_.Get(origin);
if (map_it != alternative_service_map_.end()) {
@@ -336,11 +333,6 @@ AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices(
it = map_it->second.erase(it);
continue;
}
- if (it->probability == 0 ||
- it->probability < alternative_service_probability_threshold_) {
- ++it;
- continue;
- }
AlternativeService alternative_service(it->alternative_service);
if (alternative_service.host.empty()) {
alternative_service.host = origin.host();
@@ -354,13 +346,13 @@ AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices(
++it;
continue;
}
- alternative_services_above_threshold.push_back(alternative_service);
+ valid_alternative_services.push_back(alternative_service);
++it;
}
if (map_it->second.empty()) {
alternative_service_map_.Erase(map_it);
}
- return alternative_services_above_threshold;
+ return valid_alternative_services;
}
CanonicalHostMap::const_iterator canonical = GetCanonicalHost(origin);
@@ -377,10 +369,6 @@ AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices(
it = map_it->second.erase(it);
continue;
}
- if (it->probability < alternative_service_probability_threshold_) {
- ++it;
- continue;
- }
AlternativeService alternative_service(it->alternative_service);
if (alternative_service.host.empty()) {
alternative_service.host = canonical->second.host();
@@ -393,25 +381,23 @@ AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices(
++it;
continue;
}
- alternative_services_above_threshold.push_back(alternative_service);
+ valid_alternative_services.push_back(alternative_service);
++it;
}
if (map_it->second.empty()) {
alternative_service_map_.Erase(map_it);
}
- return alternative_services_above_threshold;
+ return valid_alternative_services;
}
bool HttpServerPropertiesImpl::SetAlternativeService(
const HostPortPair& origin,
const AlternativeService& alternative_service,
- double alternative_probability,
base::Time expiration) {
return SetAlternativeServices(
- origin, AlternativeServiceInfoVector(
- /*size=*/1,
- AlternativeServiceInfo(alternative_service,
- alternative_probability, expiration)));
+ origin,
+ AlternativeServiceInfoVector(
+ /*size=*/1, AlternativeServiceInfo(alternative_service, expiration)));
}
bool HttpServerPropertiesImpl::SetAlternativeServices(
@@ -615,8 +601,7 @@ HttpServerPropertiesImpl::spdy_settings_map() const {
return spdy_settings_map_;
}
-bool HttpServerPropertiesImpl::GetSupportsQuic(
- IPAddressNumber* last_address) const {
+bool HttpServerPropertiesImpl::GetSupportsQuic(IPAddress* last_address) const {
if (last_quic_address_.empty())
return false;
@@ -625,9 +610,9 @@ bool HttpServerPropertiesImpl::GetSupportsQuic(
}
void HttpServerPropertiesImpl::SetSupportsQuic(bool used_quic,
- const IPAddressNumber& address) {
+ const IPAddress& address) {
if (!used_quic) {
- last_quic_address_.clear();
+ last_quic_address_ = IPAddress();
} else {
last_quic_address_ = address;
}
@@ -699,11 +684,6 @@ void HttpServerPropertiesImpl::SetMaxServerConfigsStoredInProperties(
quic_server_info_map_.Swap(temp_map);
}
-void HttpServerPropertiesImpl::SetAlternativeServiceProbabilityThreshold(
- double threshold) {
- alternative_service_probability_threshold_ = threshold;
-}
-
AlternativeServiceMap::const_iterator
HttpServerPropertiesImpl::GetAlternateProtocolIterator(
const HostPortPair& server) {
diff --git a/chromium/net/http/http_server_properties_impl.h b/chromium/net/http/http_server_properties_impl.h
index b8678bed747..d6686733db1 100644
--- a/chromium/net/http/http_server_properties_impl.h
+++ b/chromium/net/http/http_server_properties_impl.h
@@ -14,11 +14,11 @@
#include <string>
#include <vector>
-#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/threading/non_thread_safe.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
+#include "net/base/ip_address.h"
#include "net/base/linked_hash_map.h"
#include "net/base/net_export.h"
#include "net/http/http_server_properties.h"
@@ -27,19 +27,14 @@ namespace base {
class ListValue;
}
-namespace BASE_HASH_NAMESPACE {
+namespace net {
-template <>
-struct hash<net::AlternativeService> {
+struct AlternativeServiceHash {
size_t operator()(const net::AlternativeService& entry) const {
- return entry.protocol ^ hash<std::string>()(entry.host) ^ entry.port;
+ return entry.protocol ^ std::hash<std::string>()(entry.host) ^ entry.port;
}
};
-} // namespace BASE_HASH_NAMESPACE
-
-namespace net {
-
// The implementation for setting/retrieving the HTTP server properties.
class NET_EXPORT HttpServerPropertiesImpl
: public HttpServerProperties,
@@ -58,7 +53,7 @@ class NET_EXPORT HttpServerPropertiesImpl
void InitializeSpdySettingsServers(SpdySettingsMap* spdy_settings_map);
- void InitializeSupportsQuic(IPAddressNumber* last_address);
+ void InitializeSupportsQuic(IPAddress* last_address);
void InitializeServerNetworkStats(
ServerNetworkStatsMap* server_network_stats_map);
@@ -95,7 +90,6 @@ class NET_EXPORT HttpServerPropertiesImpl
const HostPortPair& origin) override;
bool SetAlternativeService(const HostPortPair& origin,
const AlternativeService& alternative_service,
- double alternative_probability,
base::Time expiration) override;
bool SetAlternativeServices(const HostPortPair& origin,
const AlternativeServiceInfoVector&
@@ -113,7 +107,6 @@ class NET_EXPORT HttpServerPropertiesImpl
void ClearAlternativeServices(const HostPortPair& origin) override;
const AlternativeServiceMap& alternative_service_map() const override;
scoped_ptr<base::Value> GetAlternativeServiceInfoAsValue() const override;
- void SetAlternativeServiceProbabilityThreshold(double threshold) override;
const SettingsMap& GetSpdySettings(
const HostPortPair& host_port_pair) override;
bool SetSpdySetting(const HostPortPair& host_port_pair,
@@ -123,8 +116,8 @@ class NET_EXPORT HttpServerPropertiesImpl
void ClearSpdySettings(const HostPortPair& host_port_pair) override;
void ClearAllSpdySettings() override;
const SpdySettingsMap& spdy_settings_map() const override;
- bool GetSupportsQuic(IPAddressNumber* last_address) const override;
- void SetSupportsQuic(bool used_quic, const IPAddressNumber& address) override;
+ bool GetSupportsQuic(IPAddress* last_address) const override;
+ void SetSupportsQuic(bool used_quic, const IPAddress& address) override;
void SetServerNetworkStats(const HostPortPair& host_port_pair,
ServerNetworkStats stats) override;
const ServerNetworkStats* GetServerNetworkStats(
@@ -151,7 +144,9 @@ class NET_EXPORT HttpServerPropertiesImpl
// Linked hash map from AlternativeService to expiration time. This container
// is a queue with O(1) enqueue and dequeue, and a hash_map with O(1) lookup
// at the same time.
- typedef linked_hash_map<AlternativeService, base::TimeTicks>
+ typedef linked_hash_map<AlternativeService,
+ base::TimeTicks,
+ AlternativeServiceHash>
BrokenAlternativeServices;
// Map to the number of times each alternative service has been marked broken.
typedef std::map<AlternativeService, int> RecentlyBrokenAlternativeServices;
@@ -176,7 +171,7 @@ class NET_EXPORT HttpServerPropertiesImpl
// must also be in recently_broken_alternative_services_.
RecentlyBrokenAlternativeServices recently_broken_alternative_services_;
- IPAddressNumber last_quic_address_;
+ IPAddress last_quic_address_;
SpdySettingsMap spdy_settings_map_;
ServerNetworkStatsMap server_network_stats_map_;
// Contains a map of servers which could share the same alternate protocol.
@@ -187,8 +182,6 @@ class NET_EXPORT HttpServerPropertiesImpl
// ".googlevideo.com", ".googleusercontent.com") of canonical hostnames.
CanonicalSufficList canonical_suffixes_;
- double alternative_service_probability_threshold_;
-
QuicServerInfoMap quic_server_info_map_;
size_t max_server_configs_stored_in_properties_;
diff --git a/chromium/net/http/http_server_properties_impl_unittest.cc b/chromium/net/http/http_server_properties_impl_unittest.cc
index a4e81310ee0..f4edadb6a79 100644
--- a/chromium/net/http/http_server_properties_impl_unittest.cc
+++ b/chromium/net/http/http_server_properties_impl_unittest.cc
@@ -12,7 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
@@ -62,12 +62,10 @@ class HttpServerPropertiesImplTest : public testing::Test {
}
bool SetAlternativeService(const HostPortPair& origin,
- const AlternativeService& alternative_service,
- double alternative_probability) {
+ const AlternativeService& alternative_service) {
const base::Time expiration =
base::Time::Now() + base::TimeDelta::FromDays(1);
- return impl_.SetAlternativeService(origin, alternative_service,
- alternative_probability, expiration);
+ return impl_.SetAlternativeService(origin, alternative_service, expiration);
}
void InitializeSpdySettingsUploadBandwidth(SpdySettingsMap* spdy_settings_map,
@@ -223,14 +221,14 @@ TEST_F(SpdyServerPropertiesTest, SupportsRequestPriorityTest) {
// Add www.youtube.com:443 as supporting QUIC.
HostPortPair quic_server_youtube("www.youtube.com", 443);
const AlternativeService alternative_service1(QUIC, "www.youtube.com", 443);
- SetAlternativeService(quic_server_youtube, alternative_service1, 1.0);
+ SetAlternativeService(quic_server_youtube, alternative_service1);
EXPECT_TRUE(impl_.SupportsRequestPriority(quic_server_youtube));
// Add www.example.com:443 with two alternative services, one supporting QUIC.
HostPortPair quic_server_example("www.example.com", 443);
const AlternativeService alternative_service2(NPN_HTTP_2, "", 443);
- SetAlternativeService(quic_server_example, alternative_service2, 1.0);
- SetAlternativeService(quic_server_example, alternative_service1, 1.0);
+ SetAlternativeService(quic_server_example, alternative_service2);
+ SetAlternativeService(quic_server_example, alternative_service1);
EXPECT_TRUE(impl_.SupportsRequestPriority(quic_server_example));
// Verify all the entries are the same after additions.
@@ -358,7 +356,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Basic) {
EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
AlternativeService alternative_service(NPN_HTTP_2, "foo", 443);
- SetAlternativeService(test_host_port_pair, alternative_service, 1.0);
+ SetAlternativeService(test_host_port_pair, alternative_service);
const AlternativeServiceVector alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -374,19 +372,19 @@ TEST_F(AlternateProtocolServerPropertiesTest, ExcludeOrigin) {
// Same hostname, same port, TCP: should be ignored.
AlternativeService alternative_service1(NPN_HTTP_2, "foo", 443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, 1.0, expiration));
+ AlternativeServiceInfo(alternative_service1, expiration));
// Different hostname: GetAlternativeServices should return this one.
AlternativeService alternative_service2(NPN_HTTP_2, "bar", 443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, 1.0, expiration));
+ AlternativeServiceInfo(alternative_service2, expiration));
// Different port: GetAlternativeServices should return this one too.
AlternativeService alternative_service3(NPN_HTTP_2, "foo", 80);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service3, 1.0, expiration));
+ AlternativeServiceInfo(alternative_service3, expiration));
// QUIC: GetAlternativeServices should return this one too.
AlternativeService alternative_service4(QUIC, "foo", 443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service4, 1.0, expiration));
+ AlternativeServiceInfo(alternative_service4, expiration));
HostPortPair test_host_port_pair("foo", 443);
impl_.SetAlternativeServices(test_host_port_pair,
@@ -400,63 +398,6 @@ TEST_F(AlternateProtocolServerPropertiesTest, ExcludeOrigin) {
EXPECT_EQ(alternative_service4, alternative_service_vector[2]);
}
-TEST_F(AlternateProtocolServerPropertiesTest, DefaultProbabilityExcluded) {
- HostPortPair test_host_port_pair("foo", 80);
- const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443);
- SetAlternativeService(test_host_port_pair, alternative_service, 0.99);
-
- EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
-}
-
-// GetAlternativeServices and HasAlternativeServices should only return the ones
-// with probability greater than or equal to the threshold.
-TEST_F(AlternateProtocolServerPropertiesTest, Probability) {
- impl_.SetAlternativeServiceProbabilityThreshold(0.5);
-
- AlternativeServiceInfoVector alternative_service_info_vector;
- base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
- const AlternativeService alternative_service1(NPN_HTTP_2, "foo", 443);
- alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, 0.3, expiration));
- const AlternativeService alternative_service2(QUIC, "bar", 123);
- alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, 0.7, expiration));
- const AlternativeService alternative_service3(NPN_SPDY_3_1, "baz", 443);
- alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service3, 0.4, expiration));
- const AlternativeService alternative_service4(NPN_HTTP_2, "qux", 1234);
- alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service4, 0.6, expiration));
-
- HostPortPair test_host_port_pair("foo", 80);
- impl_.SetAlternativeServices(test_host_port_pair,
- alternative_service_info_vector);
-
- const AlternativeServiceVector alternative_service_vector =
- impl_.GetAlternativeServices(test_host_port_pair);
- ASSERT_EQ(2u, alternative_service_vector.size());
- EXPECT_EQ(alternative_service2, alternative_service_vector[0]);
- EXPECT_EQ(alternative_service4, alternative_service_vector[1]);
-}
-
-TEST_F(AlternateProtocolServerPropertiesTest, ProbabilityExcluded) {
- impl_.SetAlternativeServiceProbabilityThreshold(0.75);
-
- HostPortPair test_host_port_pair("foo", 80);
- const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443);
- SetAlternativeService(test_host_port_pair, alternative_service, 0.5);
- EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
-}
-
-TEST_F(AlternateProtocolServerPropertiesTest, ZeroProbabilityAlwaysExcluded) {
- impl_.SetAlternativeServiceProbabilityThreshold(0.0);
-
- HostPortPair test_host_port_pair("foo", 80);
- const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443);
- SetAlternativeService(test_host_port_pair, alternative_service, 0);
- EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
-}
-
TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
// |test_host_port_pair1| has an alternative service, which will not be
// affected by InitializeAlternativeServiceServers(), because
@@ -467,7 +408,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
const base::Time now = base::Time::Now();
base::Time expiration1 = now + base::TimeDelta::FromDays(1);
// 1st entry in the memory.
- impl_.SetAlternativeService(test_host_port_pair1, alternative_service1, 1.0,
+ impl_.SetAlternativeService(test_host_port_pair1, alternative_service1,
expiration1);
// |test_host_port_pair2| has an alternative service, which will be
@@ -478,7 +419,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
const AlternativeService alternative_service2(NPN_SPDY_3_1, "bar2", 443);
base::Time expiration2 = now + base::TimeDelta::FromDays(2);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, 1.0, expiration2));
+ AlternativeServiceInfo(alternative_service2, expiration2));
HostPortPair test_host_port_pair2("foo2", 80);
// 0th entry in the memory.
impl_.SetAlternativeServices(test_host_port_pair2,
@@ -491,7 +432,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
const AlternativeService alternative_service3(NPN_HTTP_2, "bar3", 123);
base::Time expiration3 = now + base::TimeDelta::FromDays(3);
const AlternativeServiceInfo alternative_service_info1(alternative_service3,
- 0.7, expiration3);
+ expiration3);
// Simulate updating data for 0th entry with data from Preferences.
alternative_service_map.Put(
test_host_port_pair2,
@@ -501,7 +442,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
const AlternativeService alternative_service4(NPN_HTTP_2, "bar4", 1234);
base::Time expiration4 = now + base::TimeDelta::FromDays(4);
const AlternativeServiceInfo alternative_service_info2(alternative_service4,
- 0.2, expiration4);
+ expiration4);
// Add an old entry from Preferences, this will be added to end of recency
// list.
alternative_service_map.Put(
@@ -520,19 +461,16 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
EXPECT_TRUE(map_it->first.Equals(test_host_port_pair2));
ASSERT_EQ(1u, map_it->second.size());
EXPECT_EQ(alternative_service3, map_it->second[0].alternative_service);
- EXPECT_EQ(0.7, map_it->second[0].probability);
EXPECT_EQ(expiration3, map_it->second[0].expiration);
++map_it;
EXPECT_TRUE(map_it->first.Equals(test_host_port_pair1));
ASSERT_EQ(1u, map_it->second.size());
EXPECT_EQ(alternative_service1, map_it->second[0].alternative_service);
- EXPECT_EQ(1.0, map_it->second[0].probability);
EXPECT_EQ(expiration1, map_it->second[0].expiration);
++map_it;
EXPECT_TRUE(map_it->first.Equals(test_host_port_pair3));
ASSERT_EQ(1u, map_it->second.size());
EXPECT_EQ(alternative_service4, map_it->second[0].alternative_service);
- EXPECT_EQ(0.2, map_it->second[0].probability);
EXPECT_EQ(expiration4, map_it->second[0].expiration);
}
@@ -545,8 +483,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, InitializeWithEmptyHostname) {
"", 1234);
const AlternativeService alternative_service_with_foo_hostname(NPN_HTTP_2,
"foo", 1234);
- SetAlternativeService(host_port_pair, alternative_service_with_empty_hostname,
- 1.0);
+ SetAlternativeService(host_port_pair,
+ alternative_service_with_empty_hostname);
impl_.MarkAlternativeServiceBroken(alternative_service_with_foo_hostname);
AlternativeServiceMap alternative_service_map(
@@ -570,7 +508,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, EmptyVector) {
const AlternativeService alternative_service(NPN_HTTP_2, "bar", 443);
base::Time expiration = base::Time::Now() - base::TimeDelta::FromDays(1);
const AlternativeServiceInfo alternative_service_info(alternative_service,
- 1.0, expiration);
+ expiration);
AlternativeServiceMap alternative_service_map(
AlternativeServiceMap::NO_AUTO_EVICT);
alternative_service_map.Put(
@@ -606,7 +544,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, EmptyVectorForCanonical) {
const AlternativeService alternative_service(NPN_HTTP_2, "", 443);
base::Time expiration = base::Time::Now() - base::TimeDelta::FromDays(1);
const AlternativeServiceInfo alternative_service_info(alternative_service,
- 1.0, expiration);
+ expiration);
AlternativeServiceMap alternative_service_map(
AlternativeServiceMap::NO_AUTO_EVICT);
alternative_service_map.Put(
@@ -641,10 +579,10 @@ TEST_F(AlternateProtocolServerPropertiesTest, EmptyVectorForCanonical) {
TEST_F(AlternateProtocolServerPropertiesTest, MRUOfGetAlternativeServices) {
HostPortPair test_host_port_pair1("foo1", 80);
const AlternativeService alternative_service1(NPN_SPDY_3_1, "foo1", 443);
- SetAlternativeService(test_host_port_pair1, alternative_service1, 1.0);
+ SetAlternativeService(test_host_port_pair1, alternative_service1);
HostPortPair test_host_port_pair2("foo2", 80);
const AlternativeService alternative_service2(NPN_HTTP_2, "foo2", 1234);
- SetAlternativeService(test_host_port_pair2, alternative_service2, 1.0);
+ SetAlternativeService(test_host_port_pair2, alternative_service2);
const AlternativeServiceMap& map = impl_.alternative_service_map();
AlternativeServiceMap::const_iterator it = map.begin();
@@ -667,7 +605,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, MRUOfGetAlternativeServices) {
TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) {
HostPortPair test_host_port_pair("foo", 80);
const AlternativeService alternative_service1(NPN_HTTP_2, "foo", 443);
- SetAlternativeService(test_host_port_pair, alternative_service1, 1.0);
+ SetAlternativeService(test_host_port_pair, alternative_service1);
AlternativeServiceVector alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -686,10 +624,10 @@ TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) {
AlternativeServiceInfoVector alternative_service_info_vector;
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, 1.0, expiration));
+ AlternativeServiceInfo(alternative_service1, expiration));
const AlternativeService alternative_service2(NPN_HTTP_2, "foo", 1234);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, 1.0, expiration));
+ AlternativeServiceInfo(alternative_service2, expiration));
impl_.SetAlternativeServices(test_host_port_pair,
alternative_service_info_vector);
alternative_service_vector =
@@ -701,7 +639,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) {
EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service_vector[1]));
// SetAlternativeService should add a broken alternative service to the map.
- SetAlternativeService(test_host_port_pair, alternative_service1, 1.0);
+ SetAlternativeService(test_host_port_pair, alternative_service1);
alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -718,13 +656,13 @@ TEST_F(AlternateProtocolServerPropertiesTest, MaxAge) {
// GetAlternativeServices().
const AlternativeService alternative_service1(NPN_SPDY_3_1, "foo", 443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, 1.0, now - one_day));
+ AlternativeServiceInfo(alternative_service1, now - one_day));
// Second alterrnative service will expire one day from now, should be
// returned by GetAlternativeSerices().
const AlternativeService alternative_service2(NPN_HTTP_2, "bar", 1234);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, 1.0, now + one_day));
+ AlternativeServiceInfo(alternative_service2, now + one_day));
HostPortPair test_host_port_pair("foo", 80);
impl_.SetAlternativeServices(test_host_port_pair,
@@ -745,13 +683,13 @@ TEST_F(AlternateProtocolServerPropertiesTest, MaxAgeCanonical) {
// GetAlternativeServices().
const AlternativeService alternative_service1(NPN_SPDY_3_1, "foo", 443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, 1.0, now - one_day));
+ AlternativeServiceInfo(alternative_service1, now - one_day));
// Second alterrnative service will expire one day from now, should be
// returned by GetAlternativeSerices().
const AlternativeService alternative_service2(NPN_HTTP_2, "bar", 1234);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, 1.0, now + one_day));
+ AlternativeServiceInfo(alternative_service2, now + one_day));
HostPortPair canonical_host_port_pair("bar.c.youtube.com", 80);
impl_.SetAlternativeServices(canonical_host_port_pair,
@@ -769,10 +707,10 @@ TEST_F(AlternateProtocolServerPropertiesTest, ClearAlternativeServices) {
const AlternativeService alternative_service1(NPN_SPDY_3_1, "foo", 443);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, 1.0, expiration));
+ AlternativeServiceInfo(alternative_service1, expiration));
const AlternativeService alternative_service2(NPN_HTTP_2, "bar", 1234);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, 1.0, expiration));
+ AlternativeServiceInfo(alternative_service2, expiration));
HostPortPair test_host_port_pair("foo", 80);
impl_.SetAlternativeServices(test_host_port_pair,
alternative_service_info_vector);
@@ -797,8 +735,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, BrokenShadowsCanonical) {
HostPortPair canonical_host_port_pair("bar.c.youtube.com", 80);
AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com",
1234);
- SetAlternativeService(canonical_host_port_pair, canonical_alternative_service,
- 1.0);
+ SetAlternativeService(canonical_host_port_pair,
+ canonical_alternative_service);
AlternativeServiceVector alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -808,7 +746,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, BrokenShadowsCanonical) {
impl_.MarkAlternativeServiceBroken(broken_alternative_service);
EXPECT_TRUE(impl_.IsAlternativeServiceBroken(broken_alternative_service));
- SetAlternativeService(test_host_port_pair, broken_alternative_service, 1.0);
+ SetAlternativeService(test_host_port_pair, broken_alternative_service);
alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -819,7 +757,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, BrokenShadowsCanonical) {
TEST_F(AlternateProtocolServerPropertiesTest, ClearBroken) {
HostPortPair test_host_port_pair("foo", 80);
const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443);
- SetAlternativeService(test_host_port_pair, alternative_service, 1.0);
+ SetAlternativeService(test_host_port_pair, alternative_service);
impl_.MarkAlternativeServiceBroken(alternative_service);
ASSERT_TRUE(HasAlternativeService(test_host_port_pair));
EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service));
@@ -832,7 +770,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, ClearBroken) {
TEST_F(AlternateProtocolServerPropertiesTest, MarkRecentlyBroken) {
HostPortPair host_port_pair("foo", 80);
const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443);
- SetAlternativeService(host_port_pair, alternative_service, 1.0);
+ SetAlternativeService(host_port_pair, alternative_service);
EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service));
EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service));
@@ -858,10 +796,10 @@ TEST_F(AlternateProtocolServerPropertiesTest, Canonical) {
QUIC, "bar.c.youtube.com", 1234);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(canonical_alternative_service1, 1.0, expiration));
+ AlternativeServiceInfo(canonical_alternative_service1, expiration));
const AlternativeService canonical_alternative_service2(NPN_HTTP_2, "", 443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(canonical_alternative_service2, 1.0, expiration));
+ AlternativeServiceInfo(canonical_alternative_service2, expiration));
impl_.SetAlternativeServices(canonical_host_port_pair,
alternative_service_info_vector);
@@ -888,42 +826,14 @@ TEST_F(AlternateProtocolServerPropertiesTest, Canonical) {
impl_.GetCanonicalSuffix(canonical_host_port_pair.host()));
}
-TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBelowThreshold) {
- impl_.SetAlternativeServiceProbabilityThreshold(0.02);
-
- HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
- HostPortPair canonical_host_port_pair("bar.c.youtube.com", 80);
- AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com",
- 1234);
-
- SetAlternativeService(canonical_host_port_pair, canonical_alternative_service,
- 0.01);
- EXPECT_FALSE(HasAlternativeService(canonical_host_port_pair));
- EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
-}
-
-TEST_F(AlternateProtocolServerPropertiesTest, CanonicalAboveThreshold) {
- impl_.SetAlternativeServiceProbabilityThreshold(0.02);
-
- HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
- HostPortPair canonical_host_port_pair("bar.c.youtube.com", 80);
- AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com",
- 1234);
-
- SetAlternativeService(canonical_host_port_pair, canonical_alternative_service,
- 0.03);
- EXPECT_TRUE(HasAlternativeService(canonical_host_port_pair));
- EXPECT_TRUE(HasAlternativeService(test_host_port_pair));
-}
-
TEST_F(AlternateProtocolServerPropertiesTest, ClearCanonical) {
HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
HostPortPair canonical_host_port_pair("bar.c.youtube.com", 80);
AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com",
1234);
- SetAlternativeService(canonical_host_port_pair, canonical_alternative_service,
- 1.0);
+ SetAlternativeService(canonical_host_port_pair,
+ canonical_alternative_service);
impl_.ClearAlternativeServices(canonical_host_port_pair);
EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
}
@@ -934,8 +844,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBroken) {
AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com",
1234);
- SetAlternativeService(canonical_host_port_pair, canonical_alternative_service,
- 1.0);
+ SetAlternativeService(canonical_host_port_pair,
+ canonical_alternative_service);
impl_.MarkAlternativeServiceBroken(canonical_alternative_service);
EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
}
@@ -945,7 +855,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, CanonicalOverride) {
HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
HostPortPair bar_host_port_pair("bar.c.youtube.com", 80);
AlternativeService bar_alternative_service(QUIC, "bar.c.youtube.com", 1234);
- SetAlternativeService(bar_host_port_pair, bar_alternative_service, 1.0);
+ SetAlternativeService(bar_host_port_pair, bar_alternative_service);
AlternativeServiceVector alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -953,7 +863,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, CanonicalOverride) {
HostPortPair qux_host_port_pair("qux.c.youtube.com", 80);
AlternativeService qux_alternative_service(QUIC, "qux.c.youtube.com", 443);
- SetAlternativeService(qux_host_port_pair, qux_alternative_service, 1.0);
+ SetAlternativeService(qux_host_port_pair, qux_alternative_service);
alternative_service_vector =
impl_.GetAlternativeServices(test_host_port_pair);
ASSERT_EQ(1u, alternative_service_vector.size());
@@ -966,8 +876,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, ClearWithCanonical) {
AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com",
1234);
- SetAlternativeService(canonical_host_port_pair, canonical_alternative_service,
- 1.0);
+ SetAlternativeService(canonical_host_port_pair,
+ canonical_alternative_service);
impl_.Clear();
EXPECT_FALSE(HasAlternativeService(test_host_port_pair));
}
@@ -976,7 +886,7 @@ TEST_F(AlternateProtocolServerPropertiesTest,
ExpireBrokenAlternateProtocolMappings) {
HostPortPair host_port_pair("foo", 443);
AlternativeService alternative_service(QUIC, "foo", 443);
- SetAlternativeService(host_port_pair, alternative_service, 1.0);
+ SetAlternativeService(host_port_pair, alternative_service);
EXPECT_TRUE(HasAlternativeService(host_port_pair));
EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service));
EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service));
@@ -997,17 +907,17 @@ TEST_F(AlternateProtocolServerPropertiesTest,
TEST_F(AlternateProtocolServerPropertiesTest, RemoveExpiredBrokenAltSvc) {
HostPortPair foo_host_port_pair("foo", 443);
AlternativeService bar_alternative_service(QUIC, "bar", 443);
- SetAlternativeService(foo_host_port_pair, bar_alternative_service, 1.0);
+ SetAlternativeService(foo_host_port_pair, bar_alternative_service);
EXPECT_TRUE(HasAlternativeService(foo_host_port_pair));
HostPortPair bar_host_port_pair1("bar", 80);
AlternativeService nohost_alternative_service(QUIC, "", 443);
- SetAlternativeService(bar_host_port_pair1, nohost_alternative_service, 1.0);
+ SetAlternativeService(bar_host_port_pair1, nohost_alternative_service);
EXPECT_TRUE(HasAlternativeService(bar_host_port_pair1));
HostPortPair bar_host_port_pair2("bar", 443);
AlternativeService baz_alternative_service(QUIC, "baz", 1234);
- SetAlternativeService(bar_host_port_pair2, baz_alternative_service, 1.0);
+ SetAlternativeService(bar_host_port_pair2, baz_alternative_service);
EXPECT_TRUE(HasAlternativeService(bar_host_port_pair2));
// Mark "bar:443" as broken.
@@ -1263,15 +1173,15 @@ TEST_F(SupportsQuicServerPropertiesTest, Initialize) {
HostPortPair quic_server_google("www.google.com", 443);
// Check by initializing empty address.
- IPAddressNumber initial_address;
+ IPAddress initial_address;
impl_.InitializeSupportsQuic(&initial_address);
- IPAddressNumber address;
+ IPAddress address;
EXPECT_FALSE(impl_.GetSupportsQuic(&address));
EXPECT_TRUE(address.empty());
// Check by initializing with a valid address.
- CHECK(ParseIPLiteralToNumber("127.0.0.1", &initial_address));
+ initial_address = IPAddress::IPv4Localhost();
impl_.InitializeSupportsQuic(&initial_address);
EXPECT_TRUE(impl_.GetSupportsQuic(&address));
@@ -1279,12 +1189,11 @@ TEST_F(SupportsQuicServerPropertiesTest, Initialize) {
}
TEST_F(SupportsQuicServerPropertiesTest, SetSupportsQuic) {
- IPAddressNumber address;
+ IPAddress address;
EXPECT_FALSE(impl_.GetSupportsQuic(&address));
EXPECT_TRUE(address.empty());
- IPAddressNumber actual_address;
- CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address));
+ IPAddress actual_address(127, 0, 0, 1);
impl_.SetSupportsQuic(true, actual_address);
EXPECT_TRUE(impl_.GetSupportsQuic(&address));
diff --git a/chromium/net/http/http_server_properties_manager.cc b/chromium/net/http/http_server_properties_manager.cc
index f7493ff0652..a592f441bb0 100644
--- a/chromium/net/http/http_server_properties_manager.cc
+++ b/chromium/net/http/http_server_properties_manager.cc
@@ -6,14 +6,13 @@
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
-#include "base/prefs/pref_service.h"
#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/thread_task_runner_handle.h"
#include "base/values.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "net/base/port_util.h"
namespace net {
@@ -62,7 +61,6 @@ const char kAlternativeServiceKey[] = "alternative_service";
const char kProtocolKey[] = "protocol_str";
const char kHostKey[] = "host";
const char kPortKey[] = "port";
-const char kProbabilityKey[] = "probability";
const char kExpirationKey[] = "expiration";
const char kNetworkStatsKey[] = "network_stats";
const char kSrttKey[] = "srtt";
@@ -72,23 +70,21 @@ const char kSrttKey[] = "srtt";
////////////////////////////////////////////////////////////////////////////////
// HttpServerPropertiesManager
+HttpServerPropertiesManager::PrefDelegate::~PrefDelegate() {}
+
HttpServerPropertiesManager::HttpServerPropertiesManager(
- PrefService* pref_service,
- const char* pref_path,
+ PrefDelegate* pref_delegate,
scoped_refptr<base::SequencedTaskRunner> network_task_runner)
: pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- pref_service_(pref_service),
+ pref_delegate_(pref_delegate),
setting_prefs_(false),
- path_(pref_path),
network_task_runner_(network_task_runner) {
- DCHECK(pref_service);
+ DCHECK(pref_delegate_);
pref_weak_ptr_factory_.reset(
new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
pref_weak_ptr_ = pref_weak_ptr_factory_->GetWeakPtr();
pref_cache_update_timer_.reset(new base::OneShotTimer);
- pref_change_registrar_.Init(pref_service_);
- pref_change_registrar_.Add(
- path_,
+ pref_delegate_->StartListeningForUpdates(
base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged,
base::Unretained(this)));
}
@@ -117,7 +113,7 @@ void HttpServerPropertiesManager::ShutdownOnPrefThread() {
// Cancel any pending updates, and stop listening for pref change updates.
pref_cache_update_timer_->Stop();
pref_weak_ptr_factory_.reset();
- pref_change_registrar_.RemoveAll();
+ pref_delegate_->StopListeningForUpdates();
}
// static
@@ -198,11 +194,10 @@ AlternativeServiceVector HttpServerPropertiesManager::GetAlternativeServices(
bool HttpServerPropertiesManager::SetAlternativeService(
const HostPortPair& origin,
const AlternativeService& alternative_service,
- double alternative_probability,
base::Time expiration) {
DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
const bool changed = http_server_properties_impl_->SetAlternativeService(
- origin, alternative_service, alternative_probability, expiration);
+ origin, alternative_service, expiration);
if (changed) {
ScheduleUpdatePrefsOnNetworkThread(SET_ALTERNATIVE_SERVICES);
}
@@ -291,13 +286,6 @@ HttpServerPropertiesManager::GetAlternativeServiceInfoAsValue()
return http_server_properties_impl_->GetAlternativeServiceInfoAsValue();
}
-void HttpServerPropertiesManager::SetAlternativeServiceProbabilityThreshold(
- double threshold) {
- DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
- http_server_properties_impl_->SetAlternativeServiceProbabilityThreshold(
- threshold);
-}
-
const SettingsMap& HttpServerPropertiesManager::GetSpdySettings(
const HostPortPair& host_port_pair) {
DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
@@ -337,19 +325,18 @@ const SpdySettingsMap& HttpServerPropertiesManager::spdy_settings_map()
}
bool HttpServerPropertiesManager::GetSupportsQuic(
- IPAddressNumber* last_address) const {
+ IPAddress* last_address) const {
DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
return http_server_properties_impl_->GetSupportsQuic(last_address);
}
-void HttpServerPropertiesManager::SetSupportsQuic(
- bool used_quic,
- const IPAddressNumber& address) {
+void HttpServerPropertiesManager::SetSupportsQuic(bool used_quic,
+ const IPAddress& address) {
DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
- IPAddressNumber old_last_quic_addr;
+ IPAddress old_last_quic_addr;
http_server_properties_impl_->GetSupportsQuic(&old_last_quic_addr);
http_server_properties_impl_->SetSupportsQuic(used_quic, address);
- IPAddressNumber new_last_quic_addr;
+ IPAddress new_last_quic_addr;
http_server_properties_impl_->GetSupportsQuic(&new_last_quic_addr);
if (old_last_quic_addr != new_last_quic_addr)
ScheduleUpdatePrefsOnNetworkThread(SET_SUPPORTS_QUIC);
@@ -445,12 +432,12 @@ void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread() {
// The preferences can only be read on the pref thread.
DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
- if (!pref_service_->HasPrefPath(path_))
+ if (!pref_delegate_->HasServerProperties())
return;
bool detected_corrupted_prefs = false;
const base::DictionaryValue& http_server_properties_dict =
- *pref_service_->GetDictionary(path_);
+ pref_delegate_->GetServerProperties();
int version = kMissingVersion;
if (!http_server_properties_dict.GetIntegerWithoutPathExpansion(kVersionKey,
@@ -499,7 +486,7 @@ void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread() {
}
}
- IPAddressNumber* addr = new IPAddressNumber;
+ IPAddress* addr = new IPAddress;
ReadSupportsQuic(http_server_properties_dict, addr);
// String is host/port pair of spdy server.
@@ -666,16 +653,6 @@ bool HttpServerPropertiesManager::ParseAlternativeServiceDict(
alternative_service_info->alternative_service.port =
static_cast<uint32_t>(port);
- // Probability is optional, defaults to 1.0.
- alternative_service_info->probability = 1.0;
- if (alternative_service_dict.HasKey(kProbabilityKey) &&
- !alternative_service_dict.GetDoubleWithoutPathExpansion(
- kProbabilityKey, &(alternative_service_info->probability))) {
- DVLOG(1) << "Malformed alternative service probability for server: "
- << server_str;
- return false;
- }
-
// Expiration is optional, defaults to one day.
base::Time expiration;
if (!alternative_service_dict.HasKey(kExpirationKey)) {
@@ -743,7 +720,7 @@ bool HttpServerPropertiesManager::AddToAlternativeServiceMap(
bool HttpServerPropertiesManager::ReadSupportsQuic(
const base::DictionaryValue& http_server_properties_dict,
- IPAddressNumber* last_quic_address) {
+ IPAddress* last_quic_address) {
const base::DictionaryValue* supports_quic_dict = nullptr;
if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
kSupportsQuicKey, &supports_quic_dict)) {
@@ -761,7 +738,7 @@ bool HttpServerPropertiesManager::ReadSupportsQuic(
std::string address;
if (!supports_quic_dict->GetStringWithoutPathExpansion(kAddressKey,
&address) ||
- !ParseIPLiteralToNumber(address, last_quic_address)) {
+ !last_quic_address->AssignFromIPLiteral(address)) {
DVLOG(1) << "Malformed SupportsQuic";
return false;
}
@@ -841,7 +818,7 @@ void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
ServerList* spdy_servers,
SpdySettingsMap* spdy_settings_map,
AlternativeServiceMap* alternative_service_map,
- IPAddressNumber* last_quic_address,
+ IPAddress* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
QuicServerInfoMap* quic_server_info_map,
bool detected_corrupted_prefs) {
@@ -1002,7 +979,7 @@ void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(
}
}
- IPAddressNumber* last_quic_addr = new IPAddressNumber;
+ IPAddress* last_quic_addr = new IPAddress;
http_server_properties_impl_->GetSupportsQuic(last_quic_addr);
// Update the preferences on the pref thread.
pref_task_runner_->PostTask(
@@ -1048,7 +1025,7 @@ void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
base::ListValue* spdy_server_list,
SpdySettingsMap* spdy_settings_map,
AlternativeServiceMap* alternative_service_map,
- IPAddressNumber* last_quic_address,
+ IPAddress* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
QuicServerInfoMap* quic_server_info_map,
const base::Closure& completion) {
@@ -1117,7 +1094,7 @@ void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
}
}
- // Persist properties to the |path_| in the MRU order.
+ // Persist properties to the prefs in the MRU order.
base::DictionaryValue http_server_properties_dict;
base::ListValue* servers_list = new base::ListValue;
for (ServerPrefMap::const_reverse_iterator map_it = server_pref_map.rbegin();
@@ -1152,7 +1129,7 @@ void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
&http_server_properties_dict);
setting_prefs_ = true;
- pref_service_->Set(path_, http_server_properties_dict);
+ pref_delegate_->SetServerProperties(http_server_properties_dict);
setting_prefs_ = false;
// Note that |completion| will be fired after we have written everything to
@@ -1200,8 +1177,6 @@ void HttpServerPropertiesManager::SaveAlternativeServiceToServerPrefs(
}
alternative_service_dict->SetString(
kProtocolKey, AlternateProtocolToString(alternative_service.protocol));
- alternative_service_dict->SetDouble(kProbabilityKey,
- alternative_service_info.probability);
// JSON cannot store int64_t, so expiration is converted to a string.
alternative_service_dict->SetString(
kExpirationKey,
@@ -1216,15 +1191,14 @@ void HttpServerPropertiesManager::SaveAlternativeServiceToServerPrefs(
}
void HttpServerPropertiesManager::SaveSupportsQuicToPrefs(
- const IPAddressNumber* last_quic_address,
+ const IPAddress* last_quic_address,
base::DictionaryValue* http_server_properties_dict) {
- if (!last_quic_address || last_quic_address->empty())
+ if (!last_quic_address || !last_quic_address->IsValid())
return;
base::DictionaryValue* supports_quic_dict = new base::DictionaryValue;
supports_quic_dict->SetBoolean(kUsedQuicKey, true);
- supports_quic_dict->SetString(kAddressKey,
- IPAddressToString(*last_quic_address));
+ supports_quic_dict->SetString(kAddressKey, last_quic_address->ToString());
http_server_properties_dict->SetWithoutPathExpansion(kSupportsQuicKey,
supports_quic_dict);
}
diff --git a/chromium/net/http/http_server_properties_manager.h b/chromium/net/http/http_server_properties_manager.h
index b08ae16d20a..a7ede48f0c6 100644
--- a/chromium/net/http/http_server_properties_manager.h
+++ b/chromium/net/http/http_server_properties_manager.h
@@ -15,7 +15,6 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/prefs/pref_change_registrar.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
@@ -30,6 +29,8 @@ class SequencedTaskRunner;
namespace net {
+class IPAddress;
+
////////////////////////////////////////////////////////////////////////////////
// HttpServerPropertiesManager
@@ -54,12 +55,36 @@ namespace net {
// and grab a WeakPtr.
class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
public:
- // Create an instance of the HttpServerPropertiesManager. The lifetime of the
- // PrefService objects must be longer than that of the
- // HttpServerPropertiesManager object. Must be constructed on the Pref thread.
+ // Provides an interface to interface with persistent preferences storage
+ // implemented by the embedder.
+ class NET_EXPORT PrefDelegate {
+ public:
+ virtual ~PrefDelegate();
+
+ // Returns true if the pref system has data for the server properties.
+ virtual bool HasServerProperties() = 0;
+
+ // Returns the branch of the preferences system for the server properties.
+ virtual const base::DictionaryValue& GetServerProperties() const = 0;
+
+ // Sets the server properties to the given value.
+ virtual void SetServerProperties(const base::DictionaryValue& value) = 0;
+
+ // Start and stop listening for external storage changes. There will only
+ // be one callback active at a time.
+ virtual void StartListeningForUpdates(const base::Closure& callback) = 0;
+ virtual void StopListeningForUpdates() = 0;
+ };
+
+ // Create an instance of the HttpServerPropertiesManager.
+ //
+ // Ownership of the PrefDelegate pointer is taken by this class. This is
+ // 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.
HttpServerPropertiesManager(
- PrefService* pref_service,
- const char* pref_path,
+ PrefDelegate* pref_delegate,
scoped_refptr<base::SequencedTaskRunner> network_task_runner);
~HttpServerPropertiesManager() override;
@@ -94,7 +119,6 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
const HostPortPair& origin) override;
bool SetAlternativeService(const HostPortPair& origin,
const AlternativeService& alternative_service,
- double alternative_probability,
base::Time expiration) override;
bool SetAlternativeServices(const HostPortPair& origin,
const AlternativeServiceInfoVector&
@@ -112,7 +136,6 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
void ClearAlternativeServices(const HostPortPair& origin) override;
const AlternativeServiceMap& alternative_service_map() const override;
scoped_ptr<base::Value> GetAlternativeServiceInfoAsValue() const override;
- void SetAlternativeServiceProbabilityThreshold(double threshold) override;
const SettingsMap& GetSpdySettings(
const HostPortPair& host_port_pair) override;
bool SetSpdySetting(const HostPortPair& host_port_pair,
@@ -122,9 +145,8 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
void ClearSpdySettings(const HostPortPair& host_port_pair) override;
void ClearAllSpdySettings() override;
const SpdySettingsMap& spdy_settings_map() const override;
- bool GetSupportsQuic(IPAddressNumber* last_address) const override;
- void SetSupportsQuic(bool used_quic,
- const IPAddressNumber& last_address) override;
+ bool GetSupportsQuic(IPAddress* last_address) const override;
+ void SetSupportsQuic(bool used_quic, const IPAddress& last_address) override;
void SetServerNetworkStats(const HostPortPair& host_port_pair,
ServerNetworkStats stats) override;
const ServerNetworkStats* GetServerNetworkStats(
@@ -182,7 +204,7 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
std::vector<std::string>* spdy_servers,
SpdySettingsMap* spdy_settings_map,
AlternativeServiceMap* alternative_service_map,
- IPAddressNumber* last_quic_address,
+ IPAddress* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
QuicServerInfoMap* quic_server_info_map,
bool detected_corrupted_prefs);
@@ -213,7 +235,7 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
void UpdatePrefsOnPrefThread(base::ListValue* spdy_server_list,
SpdySettingsMap* spdy_settings_map,
AlternativeServiceMap* alternative_service_map,
- IPAddressNumber* last_quic_address,
+ IPAddress* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
QuicServerInfoMap* quic_server_info_map,
const base::Closure& completion);
@@ -244,7 +266,7 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
const base::DictionaryValue& server_dict,
AlternativeServiceMap* alternative_service_map);
bool ReadSupportsQuic(const base::DictionaryValue& server_dict,
- IPAddressNumber* last_quic_address);
+ IPAddress* last_quic_address);
bool AddToNetworkStatsMap(const HostPortPair& server,
const base::DictionaryValue& server_dict,
ServerNetworkStatsMap* network_stats_map);
@@ -257,7 +279,7 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
const AlternativeServiceInfoVector* alternative_service_info_vector,
base::DictionaryValue* server_pref_dict);
void SaveSupportsQuicToPrefs(
- const IPAddressNumber* last_quic_address,
+ const IPAddress* last_quic_address,
base::DictionaryValue* http_server_properties_dict);
void SaveNetworkStatsToServerPrefs(
const ServerNetworkStats* server_network_stats,
@@ -277,11 +299,8 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties {
// Used to post cache update tasks.
scoped_ptr<base::OneShotTimer> pref_cache_update_timer_;
- // Used to track the spdy servers changes.
- PrefChangeRegistrar pref_change_registrar_;
- PrefService* pref_service_; // Weak.
+ scoped_ptr<PrefDelegate> pref_delegate_;
bool setting_prefs_;
- const char* path_;
// --------------
// Network thread
diff --git a/chromium/net/http/http_server_properties_manager_unittest.cc b/chromium/net/http/http_server_properties_manager_unittest.cc
index 49d19db177e..bf83ff78ec6 100644
--- a/chromium/net/http/http_server_properties_manager_unittest.cc
+++ b/chromium/net/http/http_server_properties_manager_unittest.cc
@@ -8,8 +8,6 @@
#include "base/json/json_writer.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
-#include "base/prefs/pref_registry_simple.h"
-#include "base/prefs/testing_pref_service.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
@@ -17,7 +15,7 @@
#include "base/test/test_simple_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/values.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -32,15 +30,52 @@ using ::testing::Invoke;
using ::testing::Mock;
using ::testing::StrictMock;
-const char kTestHttpServerProperties[] = "TestHttpServerProperties";
+class MockPrefDelegate : public net::HttpServerPropertiesManager::PrefDelegate {
+ public:
+ MockPrefDelegate() {}
+ ~MockPrefDelegate() override {}
+
+ // HttpServerPropertiesManager::PrefDelegate implementation.
+ bool HasServerProperties() override { return true; }
+ const base::DictionaryValue& GetServerProperties() const override {
+ return prefs_;
+ }
+ void SetServerProperties(const base::DictionaryValue& value) override {
+ prefs_.Clear();
+ prefs_.MergeDictionary(&value);
+ if (!prefs_changed_callback_.is_null())
+ prefs_changed_callback_.Run();
+ }
+ void StartListeningForUpdates(const base::Closure& callback) override {
+ CHECK(prefs_changed_callback_.is_null());
+ prefs_changed_callback_ = callback;
+ }
+ void StopListeningForUpdates() override {
+ CHECK(!prefs_changed_callback_.is_null());
+ prefs_changed_callback_ = base::Closure();
+ }
+
+ void SetPrefs(const base::DictionaryValue& value) {
+ // prefs_ = value;
+ prefs_.Clear();
+ prefs_.MergeDictionary(&value);
+ if (!prefs_changed_callback_.is_null())
+ prefs_changed_callback_.Run();
+ }
+
+ private:
+ base::DictionaryValue prefs_;
+ base::Closure prefs_changed_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockPrefDelegate);
+};
class TestingHttpServerPropertiesManager : public HttpServerPropertiesManager {
public:
TestingHttpServerPropertiesManager(
- PrefService* pref_service,
- const char* pref_path,
+ HttpServerPropertiesManager::PrefDelegate* pref_delegate,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
- : HttpServerPropertiesManager(pref_service, pref_path, io_task_runner) {
+ : HttpServerPropertiesManager(pref_delegate, io_task_runner) {
InitializeOnNetworkThread();
}
@@ -87,7 +122,7 @@ class TestingHttpServerPropertiesManager : public HttpServerPropertiesManager {
void(std::vector<std::string>* spdy_servers,
SpdySettingsMap* spdy_settings_map,
AlternativeServiceMap* alternative_service_map,
- IPAddressNumber* last_quic_address,
+ IPAddress* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
QuicServerInfoMap* quic_server_info_map,
bool detected_corrupted_prefs));
@@ -95,7 +130,7 @@ class TestingHttpServerPropertiesManager : public HttpServerPropertiesManager {
void(base::ListValue* spdy_server_list,
SpdySettingsMap* spdy_settings_map,
AlternativeServiceMap* alternative_service_map,
- IPAddressNumber* last_quic_address,
+ IPAddress* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
QuicServerInfoMap* quic_server_info_map,
const base::Closure& completion));
@@ -116,11 +151,10 @@ class HttpServerPropertiesManagerTest : public testing::TestWithParam<int> {
void SetUp() override {
one_day_from_now_ = base::Time::Now() + base::TimeDelta::FromDays(1);
- pref_service_.registry()->RegisterDictionaryPref(kTestHttpServerProperties);
+ pref_delegate_ = new MockPrefDelegate;
http_server_props_manager_.reset(
new StrictMock<TestingHttpServerPropertiesManager>(
- &pref_service_, kTestHttpServerProperties,
- base::ThreadTaskRunnerHandle::Get()));
+ pref_delegate_, base::ThreadTaskRunnerHandle::Get()));
ExpectCacheUpdate();
base::RunLoop().RunUntilIdle();
}
@@ -178,8 +212,7 @@ class HttpServerPropertiesManagerTest : public testing::TestWithParam<int> {
return !alternative_service_vector.empty();
}
- //base::RunLoop loop_;
- TestingPrefServiceSimple pref_service_;
+ MockPrefDelegate* pref_delegate_; // Owned by HttpServerPropertiesManager.
scoped_ptr<TestingHttpServerPropertiesManager> http_server_props_manager_;
base::Time one_day_from_now_;
@@ -256,25 +289,24 @@ TEST_P(HttpServerPropertiesManagerTest,
// Set the server preference for mail.google.com:80.
servers_dict->SetWithoutPathExpansion("mail.google.com:80",
server_pref_dict1);
- base::DictionaryValue* http_server_properties_dict =
- new base::DictionaryValue;
+ base::DictionaryValue http_server_properties_dict;
if (GetParam() == 4) {
// |servers_list| takes ownership of |servers_dict|.
servers_list->AppendIfNotPresent(servers_dict);
- HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1);
- http_server_properties_dict->SetWithoutPathExpansion("servers",
- servers_list);
+ HttpServerPropertiesManager::SetVersion(&http_server_properties_dict, -1);
+ http_server_properties_dict.SetWithoutPathExpansion("servers",
+ servers_list);
} else {
- HttpServerPropertiesManager::SetVersion(http_server_properties_dict,
+ HttpServerPropertiesManager::SetVersion(&http_server_properties_dict,
GetParam());
- http_server_properties_dict->SetWithoutPathExpansion("servers",
- servers_dict);
+ http_server_properties_dict.SetWithoutPathExpansion("servers",
+ servers_dict);
}
base::DictionaryValue* supports_quic = new base::DictionaryValue;
supports_quic->SetBoolean("used_quic", true);
supports_quic->SetString("address", "127.0.0.1");
- http_server_properties_dict->SetWithoutPathExpansion("supports_quic",
- supports_quic);
+ http_server_properties_dict.SetWithoutPathExpansion("supports_quic",
+ supports_quic);
// Set quic_server_info for www.google.com:80, mail.google.com:80 and
// play.google.com:80 and verify the MRU.
@@ -304,16 +336,12 @@ TEST_P(HttpServerPropertiesManagerTest,
QuicServerId play_quic_server_id("play.google.com", 80);
quic_servers_dict->SetWithoutPathExpansion(play_quic_server_id.ToString(),
quic_server_pref_dict3);
- http_server_properties_dict->SetWithoutPathExpansion("quic_servers",
- quic_servers_dict);
+ http_server_properties_dict.SetWithoutPathExpansion("quic_servers",
+ quic_servers_dict);
// Set the same value for kHttpServerProperties multiple times.
- pref_service_.SetManagedPref(kTestHttpServerProperties,
- http_server_properties_dict);
- base::DictionaryValue* http_server_properties_dict2 =
- http_server_properties_dict->DeepCopy();
- pref_service_.SetManagedPref(kTestHttpServerProperties,
- http_server_properties_dict2);
+ pref_delegate_->SetPrefs(http_server_properties_dict);
+ pref_delegate_->SetPrefs(http_server_properties_dict);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
@@ -368,9 +396,9 @@ TEST_P(HttpServerPropertiesManagerTest,
}
// Verify SupportsQuic.
- IPAddressNumber last_address;
+ IPAddress last_address;
EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&last_address));
- EXPECT_EQ("127.0.0.1", IPAddressToString(last_address));
+ EXPECT_EQ("127.0.0.1", last_address.ToString());
// Verify ServerNetworkStats.
const ServerNetworkStats* stats2 =
@@ -427,20 +455,19 @@ TEST_P(HttpServerPropertiesManagerTest, BadCachedHostPortPair) {
base::DictionaryValue* servers_dict = new base::DictionaryValue;
servers_dict->SetWithoutPathExpansion("www.google.com:65536",
server_pref_dict);
- base::DictionaryValue* http_server_properties_dict =
- new base::DictionaryValue;
+ base::DictionaryValue http_server_properties_dict;
if (GetParam() == 4) {
base::ListValue* servers_list = new base::ListValue;
// |servers_list| takes ownership of |servers_dict|.
servers_list->AppendIfNotPresent(servers_dict);
- HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1);
- http_server_properties_dict->SetWithoutPathExpansion("servers",
- servers_list);
+ HttpServerPropertiesManager::SetVersion(&http_server_properties_dict, -1);
+ http_server_properties_dict.SetWithoutPathExpansion("servers",
+ servers_list);
} else {
- HttpServerPropertiesManager::SetVersion(http_server_properties_dict,
+ HttpServerPropertiesManager::SetVersion(&http_server_properties_dict,
GetParam());
- http_server_properties_dict->SetWithoutPathExpansion("servers",
- servers_dict);
+ http_server_properties_dict.SetWithoutPathExpansion("servers",
+ servers_dict);
}
// Set quic_server_info for www.google.com:65536.
@@ -451,12 +478,11 @@ TEST_P(HttpServerPropertiesManagerTest, BadCachedHostPortPair) {
quic_servers_dict->SetWithoutPathExpansion("http://mail.google.com:65536",
quic_server_pref_dict1);
- http_server_properties_dict->SetWithoutPathExpansion("quic_servers",
- quic_servers_dict);
+ http_server_properties_dict.SetWithoutPathExpansion("quic_servers",
+ quic_servers_dict);
// Set up the pref.
- pref_service_.SetManagedPref(kTestHttpServerProperties,
- http_server_properties_dict);
+ pref_delegate_->SetPrefs(http_server_properties_dict);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
@@ -496,25 +522,23 @@ TEST_P(HttpServerPropertiesManagerTest, BadCachedAltProtocolPort) {
// Set the server preference for www.google.com:80.
base::DictionaryValue* servers_dict = new base::DictionaryValue;
servers_dict->SetWithoutPathExpansion("www.google.com:80", server_pref_dict);
- base::DictionaryValue* http_server_properties_dict =
- new base::DictionaryValue;
+ base::DictionaryValue http_server_properties_dict;
if (GetParam() == 4) {
base::ListValue* servers_list = new base::ListValue;
// |servers_list| takes ownership of |servers_dict|.
servers_list->AppendIfNotPresent(servers_dict);
- HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1);
- http_server_properties_dict->SetWithoutPathExpansion("servers",
- servers_list);
+ HttpServerPropertiesManager::SetVersion(&http_server_properties_dict, -1);
+ http_server_properties_dict.SetWithoutPathExpansion("servers",
+ servers_list);
} else {
- HttpServerPropertiesManager::SetVersion(http_server_properties_dict,
+ HttpServerPropertiesManager::SetVersion(&http_server_properties_dict,
GetParam());
- http_server_properties_dict->SetWithoutPathExpansion("servers",
- servers_dict);
+ http_server_properties_dict.SetWithoutPathExpansion("servers",
+ servers_dict);
}
// Set up the pref.
- pref_service_.SetManagedPref(kTestHttpServerProperties,
- http_server_properties_dict);
+ pref_delegate_->SetPrefs(http_server_properties_dict);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
@@ -660,10 +684,10 @@ TEST_P(HttpServerPropertiesManagerTest, GetAlternativeServices) {
const AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com",
443);
http_server_props_manager_->SetAlternativeService(
- spdy_server_mail, alternative_service, 1.0, one_day_from_now_);
+ spdy_server_mail, alternative_service, one_day_from_now_);
// ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
http_server_props_manager_->SetAlternativeService(
- spdy_server_mail, alternative_service, 1.0, one_day_from_now_);
+ spdy_server_mail, alternative_service, one_day_from_now_);
// Run the task.
base::RunLoop().RunUntilIdle();
@@ -685,10 +709,10 @@ TEST_P(HttpServerPropertiesManagerTest, SetAlternativeServices) {
const AlternativeService alternative_service1(NPN_HTTP_2, "mail.google.com",
443);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, 1.0, one_day_from_now_));
+ AlternativeServiceInfo(alternative_service1, one_day_from_now_));
const AlternativeService alternative_service2(QUIC, "mail.google.com", 1234);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service2, 1.0, one_day_from_now_));
+ AlternativeServiceInfo(alternative_service2, one_day_from_now_));
http_server_props_manager_->SetAlternativeServices(
spdy_server_mail, alternative_service_info_vector);
// ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
@@ -730,7 +754,7 @@ TEST_P(HttpServerPropertiesManagerTest, ClearAlternativeServices) {
EXPECT_FALSE(HasAlternativeService(spdy_server_mail));
AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 443);
http_server_props_manager_->SetAlternativeService(
- spdy_server_mail, alternative_service, 1.0, one_day_from_now_);
+ spdy_server_mail, alternative_service, one_day_from_now_);
ExpectScheduleUpdatePrefsOnNetworkThread();
http_server_props_manager_->ClearAlternativeServices(spdy_server_mail);
// ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
@@ -752,7 +776,7 @@ TEST_P(HttpServerPropertiesManagerTest, ConfirmAlternativeService) {
ExpectScheduleUpdatePrefsOnNetworkThread();
http_server_props_manager_->SetAlternativeService(
- spdy_server_mail, alternative_service, 1.0, one_day_from_now_);
+ spdy_server_mail, alternative_service, one_day_from_now_);
EXPECT_FALSE(http_server_props_manager_->IsAlternativeServiceBroken(
alternative_service));
@@ -793,11 +817,10 @@ TEST_P(HttpServerPropertiesManagerTest, SupportsQuic) {
ExpectPrefsUpdate();
ExpectScheduleUpdatePrefsOnNetworkThread();
- IPAddressNumber address;
+ IPAddress address;
EXPECT_FALSE(http_server_props_manager_->GetSupportsQuic(&address));
- IPAddressNumber actual_address;
- CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address));
+ IPAddress actual_address(127, 0, 0, 1);
http_server_props_manager_->SetSupportsQuic(true, actual_address);
// ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
http_server_props_manager_->SetSupportsQuic(true, actual_address);
@@ -863,9 +886,8 @@ TEST_P(HttpServerPropertiesManagerTest, Clear) {
http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true);
AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 1234);
http_server_props_manager_->SetAlternativeService(
- spdy_server_mail, alternative_service, 1.0, one_day_from_now_);
- IPAddressNumber actual_address;
- CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address));
+ spdy_server_mail, alternative_service, one_day_from_now_);
+ IPAddress actual_address(127, 0, 0, 1);
http_server_props_manager_->SetSupportsQuic(true, actual_address);
ServerNetworkStats stats;
stats.srtt = base::TimeDelta::FromMicroseconds(10);
@@ -888,7 +910,7 @@ TEST_P(HttpServerPropertiesManagerTest, Clear) {
EXPECT_TRUE(
http_server_props_manager_->SupportsRequestPriority(spdy_server_mail));
EXPECT_TRUE(HasAlternativeService(spdy_server_mail));
- IPAddressNumber address;
+ IPAddress address;
EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&address));
EXPECT_EQ(actual_address, address);
const ServerNetworkStats* stats1 =
@@ -970,31 +992,29 @@ TEST_P(HttpServerPropertiesManagerTest, BadSupportsQuic) {
// Set the server preference for mail.google.com:80.
servers_dict->SetWithoutPathExpansion("mail.google.com:80",
server_pref_dict1);
- base::DictionaryValue* http_server_properties_dict =
- new base::DictionaryValue;
+ base::DictionaryValue http_server_properties_dict;
if (GetParam() == 4) {
// |servers_list| takes ownership of |servers_dict|.
servers_list->AppendIfNotPresent(servers_dict);
- HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1);
- http_server_properties_dict->SetWithoutPathExpansion("servers",
- servers_list);
+ HttpServerPropertiesManager::SetVersion(&http_server_properties_dict, -1);
+ http_server_properties_dict.SetWithoutPathExpansion("servers",
+ servers_list);
} else {
- HttpServerPropertiesManager::SetVersion(http_server_properties_dict,
+ HttpServerPropertiesManager::SetVersion(&http_server_properties_dict,
GetParam());
- http_server_properties_dict->SetWithoutPathExpansion("servers",
- servers_dict);
+ http_server_properties_dict.SetWithoutPathExpansion("servers",
+ servers_dict);
}
// Set up SupportsQuic for 127.0.0.1
base::DictionaryValue* supports_quic = new base::DictionaryValue;
supports_quic->SetBoolean("used_quic", true);
supports_quic->SetString("address", "127.0.0.1");
- http_server_properties_dict->SetWithoutPathExpansion("supports_quic",
- supports_quic);
+ http_server_properties_dict.SetWithoutPathExpansion("supports_quic",
+ supports_quic);
// Set up the pref.
- pref_service_.SetManagedPref(kTestHttpServerProperties,
- http_server_properties_dict);
+ pref_delegate_->SetPrefs(http_server_properties_dict);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
@@ -1011,9 +1031,9 @@ TEST_P(HttpServerPropertiesManagerTest, BadSupportsQuic) {
}
// Verify SupportsQuic.
- IPAddressNumber address;
+ IPAddress address;
ASSERT_TRUE(http_server_props_manager_->GetSupportsQuic(&address));
- EXPECT_EQ("127.0.0.1", IPAddressToString(address));
+ EXPECT_EQ("127.0.0.1", address.ToString());
}
TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
@@ -1028,13 +1048,13 @@ TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
base::Time expiration1;
ASSERT_TRUE(base::Time::FromUTCString("2036-12-01 10:00:00", &expiration1));
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(www_alternative_service1, 1.0, expiration1));
+ AlternativeServiceInfo(www_alternative_service1, expiration1));
AlternativeService www_alternative_service2(NPN_HTTP_2, "www.google.com",
1234);
base::Time expiration2;
ASSERT_TRUE(base::Time::FromUTCString("2036-12-31 10:00:00", &expiration2));
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(www_alternative_service2, 0.7, expiration2));
+ AlternativeServiceInfo(www_alternative_service2, expiration2));
http_server_props_manager_->SetAlternativeServices(
server_www, alternative_service_info_vector);
@@ -1042,7 +1062,7 @@ TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
444);
base::Time expiration3 = base::Time::Max();
http_server_props_manager_->SetAlternativeService(
- server_mail, mail_alternative_service, 0.2, expiration3);
+ server_mail, mail_alternative_service, expiration3);
// Set ServerNetworkStats.
ServerNetworkStats stats;
@@ -1056,8 +1076,7 @@ TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
quic_server_info1);
// Set SupportsQuic.
- IPAddressNumber actual_address;
- CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address));
+ IPAddress actual_address(127, 0, 0, 1);
http_server_props_manager_->SetSupportsQuic(true, actual_address);
// Update cache.
@@ -1073,20 +1092,19 @@ TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
"\"servers\":["
"{\"www.google.com:80\":{"
"\"alternative_service\":[{\"expiration\":\"13756212000000000\","
- "\"port\":443,\"probability\":1.0,\"protocol_str\":\"npn-h2\"},"
+ "\"port\":443,\"protocol_str\":\"npn-h2\"},"
"{\"expiration\":\"13758804000000000\",\"host\":\"www.google.com\","
- "\"port\":1234,\"probability\":0.7,\"protocol_str\":\"npn-h2\"}]}},"
+ "\"port\":1234,\"protocol_str\":\"npn-h2\"}]}},"
"{\"mail.google.com:80\":{\"alternative_service\":[{"
"\"expiration\":\"9223372036854775807\",\"host\":\"foo.google.com\","
- "\"port\":444,\"probability\":0.2,\"protocol_str\":\"npn-spdy/3.1\"}],"
+ "\"port\":444,\"protocol_str\":\"npn-spdy/3.1\"}],"
"\"network_stats\":{\"srtt\":42}}}"
"],"
"\"supports_quic\":{\"address\":\"127.0.0.1\",\"used_quic\":true},"
"\"version\":4}";
const base::Value* http_server_properties =
- pref_service_.GetUserPref(kTestHttpServerProperties);
- ASSERT_NE(nullptr, http_server_properties);
+ &pref_delegate_->GetServerProperties();
std::string preferences_json;
EXPECT_TRUE(
base::JSONWriter::Write(*http_server_properties, &preferences_json));
@@ -1096,9 +1114,9 @@ TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
TEST_P(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) {
scoped_ptr<base::Value> server_value = base::JSONReader::Read(
"{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"npn-h2\"},"
- "{\"port\":123,\"protocol_str\":\"quic\",\"probability\":0.7,"
+ "{\"port\":123,\"protocol_str\":\"quic\","
"\"expiration\":\"9223372036854775807\"},{\"host\":\"example.org\","
- "\"port\":1234,\"protocol_str\":\"npn-h2\",\"probability\":0.2,"
+ "\"port\":1234,\"protocol_str\":\"npn-h2\","
"\"expiration\":\"13758804000000000\"}]}");
ASSERT_TRUE(server_value);
base::DictionaryValue* server_dict;
@@ -1119,8 +1137,6 @@ TEST_P(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) {
alternative_service_info_vector[0].alternative_service.protocol);
EXPECT_EQ("", alternative_service_info_vector[0].alternative_service.host);
EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service.port);
- // Probability defaults to 1.0.
- EXPECT_DOUBLE_EQ(1.0, alternative_service_info_vector[0].probability);
// Expiration defaults to one day from now, testing with tolerance.
const base::Time now = base::Time::Now();
const base::Time expiration = alternative_service_info_vector[0].expiration;
@@ -1131,7 +1147,6 @@ TEST_P(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) {
alternative_service_info_vector[1].alternative_service.protocol);
EXPECT_EQ("", alternative_service_info_vector[1].alternative_service.host);
EXPECT_EQ(123, alternative_service_info_vector[1].alternative_service.port);
- EXPECT_DOUBLE_EQ(0.7, alternative_service_info_vector[1].probability);
// numeric_limits<int64_t>::max() represents base::Time::Max().
EXPECT_EQ(base::Time::Max(), alternative_service_info_vector[1].expiration);
@@ -1140,7 +1155,6 @@ TEST_P(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) {
EXPECT_EQ("example.org",
alternative_service_info_vector[2].alternative_service.host);
EXPECT_EQ(1234, alternative_service_info_vector[2].alternative_service.port);
- EXPECT_DOUBLE_EQ(0.2, alternative_service_info_vector[2].probability);
base::Time expected_expiration;
ASSERT_TRUE(
base::Time::FromUTCString("2036-12-31 10:00:00", &expected_expiration));
@@ -1158,8 +1172,8 @@ TEST_P(HttpServerPropertiesManagerTest,
NPN_HTTP_2, "broken.example.com", 443);
const base::Time time_one_day_later =
base::Time::Now() + base::TimeDelta::FromDays(1);
- alternative_service_info_vector.push_back(AlternativeServiceInfo(
- broken_alternative_service, 1.0, time_one_day_later));
+ alternative_service_info_vector.push_back(
+ AlternativeServiceInfo(broken_alternative_service, time_one_day_later));
http_server_props_manager_->MarkAlternativeServiceBroken(
broken_alternative_service);
@@ -1167,13 +1181,13 @@ TEST_P(HttpServerPropertiesManagerTest,
NPN_HTTP_2, "expired.example.com", 443);
const base::Time time_one_day_ago =
base::Time::Now() - base::TimeDelta::FromDays(1);
- alternative_service_info_vector.push_back(AlternativeServiceInfo(
- expired_alternative_service, 1.0, time_one_day_ago));
+ alternative_service_info_vector.push_back(
+ AlternativeServiceInfo(expired_alternative_service, time_one_day_ago));
const AlternativeService valid_alternative_service(NPN_HTTP_2,
"valid.example.com", 443);
- alternative_service_info_vector.push_back(AlternativeServiceInfo(
- valid_alternative_service, 1.0, time_one_day_later));
+ alternative_service_info_vector.push_back(
+ AlternativeServiceInfo(valid_alternative_service, time_one_day_later));
const HostPortPair host_port_pair("www.example.com", 443);
http_server_props_manager_->SetAlternativeServices(
@@ -1185,15 +1199,11 @@ TEST_P(HttpServerPropertiesManagerTest,
http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
base::RunLoop().RunUntilIdle();
- const base::Value* pref_value =
- pref_service_.GetUserPref(kTestHttpServerProperties);
- ASSERT_NE(nullptr, pref_value);
-
- const base::DictionaryValue* pref_dict;
- ASSERT_TRUE(pref_value->GetAsDictionary(&pref_dict));
+ const base::DictionaryValue& pref_dict =
+ pref_delegate_->GetServerProperties();
const base::ListValue* servers_list = nullptr;
- ASSERT_TRUE(pref_dict->GetListWithoutPathExpansion("servers", &servers_list));
+ ASSERT_TRUE(pref_dict.GetListWithoutPathExpansion("servers", &servers_list));
base::ListValue::const_iterator it = servers_list->begin();
const base::DictionaryValue* server_pref_dict;
ASSERT_TRUE((*it)->GetAsDictionary(&server_pref_dict));
@@ -1222,7 +1232,6 @@ TEST_P(HttpServerPropertiesManagerTest, DoNotLoadExpiredAlternativeService) {
expired_dict->SetString("protocol_str", "npn-h2");
expired_dict->SetString("host", "expired.example.com");
expired_dict->SetInteger("port", 443);
- expired_dict->SetDouble("probability", 1.0);
base::Time time_one_day_ago =
base::Time::Now() - base::TimeDelta::FromDays(1);
expired_dict->SetString(
@@ -1233,7 +1242,6 @@ TEST_P(HttpServerPropertiesManagerTest, DoNotLoadExpiredAlternativeService) {
valid_dict->SetString("protocol_str", "npn-h2");
valid_dict->SetString("host", "valid.example.com");
valid_dict->SetInteger("port", 443);
- valid_dict->SetDouble("probability", 1.0);
valid_dict->SetString(
"expiration", base::Int64ToString(one_day_from_now_.ToInternalValue()));
alternative_service_list->Append(valid_dict);
@@ -1258,7 +1266,6 @@ TEST_P(HttpServerPropertiesManagerTest, DoNotLoadExpiredAlternativeService) {
EXPECT_EQ("valid.example.com",
alternative_service_info_vector[0].alternative_service.host);
EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service.port);
- EXPECT_DOUBLE_EQ(1.0, alternative_service_info_vector[0].probability);
EXPECT_EQ(one_day_from_now_, alternative_service_info_vector[0].expiration);
}
diff --git a/chromium/net/http/http_stream.h b/chromium/net/http/http_stream.h
index b7e7888ac20..096dd462299 100644
--- a/chromium/net/http/http_stream.h
+++ b/chromium/net/http/http_stream.h
@@ -13,14 +13,21 @@
#include <stdint.h>
+#include <vector>
+
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/completion_callback.h"
#include "net/base/net_error_details.h"
+#include "net/base/net_errors.h"
#include "net/base/net_export.h"
#include "net/base/request_priority.h"
#include "net/base/upload_progress.h"
+namespace crypto {
+class ECPrivateKey;
+}
+
namespace net {
class BoundNetLog;
@@ -151,6 +158,11 @@ class NET_EXPORT_PRIVATE HttpStream {
// and does not modify |endpoint| if it is unavailable.
virtual bool GetRemoteEndpoint(IPEndPoint* endpoint) = 0;
+ // Signs the EKM value for Token Binding from the TLS layer using |*key| and
+ // puts the result in |*out|. Returns OK or ERR_FAILED.
+ virtual Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) = 0;
+
// In the case of an HTTP error or redirect, flush the response body (usually
// a simple error or "this page has moved") so that we can re-use the
// underlying connection. This stream is responsible for deleting itself when
diff --git a/chromium/net/http/http_stream_factory.cc b/chromium/net/http/http_stream_factory.cc
index d6d76b453c8..6ea3224dc96 100644
--- a/chromium/net/http/http_stream_factory.cc
+++ b/chromium/net/http/http_stream_factory.cc
@@ -13,6 +13,7 @@
#include "net/base/host_port_pair.h"
#include "net/base/port_util.h"
#include "net/http/http_network_session.h"
+#include "net/http/http_response_headers.h"
#include "net/quic/quic_protocol.h"
#include "net/spdy/spdy_alt_svc_wire_format.h"
#include "url/gurl.h"
@@ -32,6 +33,59 @@ void HttpStreamFactory::ResetStaticSettingsToInit() {
spdy_enabled_ = true;
}
+void HttpStreamFactory::ProcessAlternativeServices(
+ HttpNetworkSession* session,
+ const HttpResponseHeaders* headers,
+ const HostPortPair& http_host_port_pair) {
+ if (session->params().parse_alternative_services) {
+ if (headers->HasHeader(kAlternativeServiceHeader)) {
+ std::string alternative_service_str;
+ headers->GetNormalizedHeader(kAlternativeServiceHeader,
+ &alternative_service_str);
+ ProcessAlternativeService(session->http_server_properties(),
+ alternative_service_str, http_host_port_pair,
+ *session);
+ }
+ // If "Alt-Svc" is enabled, then ignore "Alternate-Protocol".
+ return;
+ }
+
+ if (!headers->HasHeader(kAlternateProtocolHeader))
+ return;
+
+ std::vector<std::string> alternate_protocol_values;
+ size_t iter = 0;
+ std::string alternate_protocol_str;
+ while (headers->EnumerateHeader(&iter, kAlternateProtocolHeader,
+ &alternate_protocol_str)) {
+ base::TrimWhitespaceASCII(alternate_protocol_str, base::TRIM_ALL,
+ &alternate_protocol_str);
+ if (!alternate_protocol_str.empty()) {
+ alternate_protocol_values.push_back(alternate_protocol_str);
+ }
+ }
+
+ ProcessAlternateProtocol(session->http_server_properties(),
+ alternate_protocol_values, http_host_port_pair,
+ *session);
+}
+
+GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url,
+ HostPortPair* endpoint) {
+ const HostMappingRules* mapping_rules = GetHostMappingRules();
+ if (mapping_rules && mapping_rules->RewriteHost(endpoint)) {
+ url::Replacements<char> replacements;
+ const std::string port_str = base::UintToString(endpoint->port());
+ replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
+ replacements.SetHost(endpoint->host().c_str(),
+ url::Component(0, endpoint->host().size()));
+ return url.ReplaceComponents(replacements);
+ }
+ return url;
+}
+
+HttpStreamFactory::HttpStreamFactory() {}
+
void HttpStreamFactory::ProcessAlternativeService(
const base::WeakPtr<HttpServerProperties>& http_server_properties,
base::StringPiece alternative_service_str,
@@ -79,8 +133,8 @@ void HttpStreamFactory::ProcessAlternativeService(
base::Time expiration =
base::Time::Now() +
base::TimeDelta::FromSeconds(alternative_service_entry.max_age);
- AlternativeServiceInfo alternative_service_info(
- alternative_service, alternative_service_entry.probability, expiration);
+ AlternativeServiceInfo alternative_service_info(alternative_service,
+ expiration);
alternative_service_info_vector.push_back(alternative_service_info);
}
@@ -95,24 +149,14 @@ void HttpStreamFactory::ProcessAlternateProtocol(
const HttpNetworkSession& session) {
AlternateProtocol protocol = UNINITIALIZED_ALTERNATE_PROTOCOL;
int port = 0;
- double probability = 1;
bool is_valid = true;
for (size_t i = 0; i < alternate_protocol_values.size(); ++i) {
base::StringPiece alternate_protocol_str = alternate_protocol_values[i];
if (base::StartsWith(alternate_protocol_str, "p=",
base::CompareCase::SENSITIVE)) {
- if (!base::StringToDouble(alternate_protocol_str.substr(2).as_string(),
- &probability) ||
- probability < 0 || probability > 1) {
- DVLOG(1) << kAlternateProtocolHeader
- << " header has unrecognizable probability: "
- << alternate_protocol_values[i];
- is_valid = false;
- break;
- }
+ // Ignore deprecated probability.
continue;
}
-
std::vector<base::StringPiece> port_protocol_vector =
base::SplitStringPiece(alternate_protocol_str, ":",
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
@@ -153,25 +197,9 @@ void HttpStreamFactory::ProcessAlternateProtocol(
http_server_properties->SetAlternativeService(
RewriteHost(http_host_port_pair),
AlternativeService(protocol, "", static_cast<uint16_t>(port)),
- probability, base::Time::Now() + base::TimeDelta::FromDays(30));
-}
-
-GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url,
- HostPortPair* endpoint) {
- const HostMappingRules* mapping_rules = GetHostMappingRules();
- if (mapping_rules && mapping_rules->RewriteHost(endpoint)) {
- url::Replacements<char> replacements;
- const std::string port_str = base::UintToString(endpoint->port());
- replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
- replacements.SetHost(endpoint->host().c_str(),
- url::Component(0, endpoint->host().size()));
- return url.ReplaceComponents(replacements);
- }
- return url;
+ base::Time::Now() + base::TimeDelta::FromDays(30));
}
-HttpStreamFactory::HttpStreamFactory() {}
-
HostPortPair HttpStreamFactory::RewriteHost(HostPortPair host_port_pair) {
const HostMappingRules* mapping_rules = GetHostMappingRules();
if (mapping_rules)
diff --git a/chromium/net/http/http_stream_factory.h b/chromium/net/http/http_stream_factory.h
index 359f7f0dbda..59956e1c24f 100644
--- a/chromium/net/http/http_stream_factory.h
+++ b/chromium/net/http/http_stream_factory.h
@@ -33,11 +33,12 @@ namespace net {
class AuthCredentials;
class BoundNetLog;
-class BidirectionalStreamJob;
+class BidirectionalStreamImpl;
class HostMappingRules;
class HostPortPair;
class HttpAuthController;
class HttpNetworkSession;
+class HttpResponseHeaders;
class HttpResponseInfo;
class HttpServerProperties;
class HttpStream;
@@ -54,6 +55,12 @@ struct SSLConfig;
// which no callbacks will be invoked.
class NET_EXPORT_PRIVATE HttpStreamRequest {
public:
+ // Indicates which type of stream is requested.
+ enum StreamType {
+ BIDIRECTIONAL_STREAM,
+ HTTP_STREAM,
+ };
+
// The HttpStreamRequest::Delegate is a set of callback methods for a
// HttpStreamRequestJob. Generally, only one of these methods will be
// called as a result of a stream request.
@@ -85,10 +92,10 @@ class NET_EXPORT_PRIVATE HttpStreamRequest {
const ProxyInfo& used_proxy_info,
WebSocketHandshakeStreamBase* stream) = 0;
- virtual void OnBidirectionalStreamJobReady(
+ virtual void OnBidirectionalStreamImplReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
- BidirectionalStreamJob* stream) = 0;
+ BidirectionalStreamImpl* stream) = 0;
// This is the failure to create a stream case.
// |used_ssl_config| indicates the actual SSL configuration used for this
@@ -194,17 +201,9 @@ class NET_EXPORT HttpStreamFactory {
public:
virtual ~HttpStreamFactory();
- void ProcessAlternativeService(
- const base::WeakPtr<HttpServerProperties>& http_server_properties,
- base::StringPiece alternative_service_str,
- const HostPortPair& http_host_port_pair,
- const HttpNetworkSession& session);
-
- void ProcessAlternateProtocol(
- const base::WeakPtr<HttpServerProperties>& http_server_properties,
- const std::vector<std::string>& alternate_protocol_values,
- const HostPortPair& http_host_port_pair,
- const HttpNetworkSession& session);
+ void ProcessAlternativeServices(HttpNetworkSession* session,
+ const HttpResponseHeaders* headers,
+ const HostPortPair& http_host_port_pair);
GURL ApplyHostMappingRules(const GURL& url, HostPortPair* endpoint);
@@ -232,10 +231,10 @@ class NET_EXPORT HttpStreamFactory {
WebSocketHandshakeStreamBase::CreateHelper* create_helper,
const BoundNetLog& net_log) = 0;
- // Request a BidirectionalStreamJob.
- // Will call delegate->OnBidirectionalStreamJobReady on successful
+ // Request a BidirectionalStreamImpl.
+ // Will call delegate->OnBidirectionalStreamImplReady on successful
// completion.
- virtual HttpStreamRequest* RequestBidirectionalStreamJob(
+ virtual HttpStreamRequest* RequestBidirectionalStreamImpl(
const HttpRequestInfo& info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
@@ -268,6 +267,18 @@ class NET_EXPORT HttpStreamFactory {
HttpStreamFactory();
private:
+ void ProcessAlternativeService(
+ const base::WeakPtr<HttpServerProperties>& http_server_properties,
+ base::StringPiece alternative_service_str,
+ const HostPortPair& http_host_port_pair,
+ const HttpNetworkSession& session);
+
+ void ProcessAlternateProtocol(
+ const base::WeakPtr<HttpServerProperties>& http_server_properties,
+ const std::vector<std::string>& alternate_protocol_values,
+ const HostPortPair& http_host_port_pair,
+ const HttpNetworkSession& session);
+
static bool spdy_enabled_;
HostPortPair RewriteHost(HostPortPair host_port_pair);
diff --git a/chromium/net/http/http_stream_factory_impl.cc b/chromium/net/http/http_stream_factory_impl.cc
index c9272a8310f..d160c317468 100644
--- a/chromium/net/http/http_stream_factory_impl.cc
+++ b/chromium/net/http/http_stream_factory_impl.cc
@@ -9,22 +9,17 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
-#include "net/base/net_util.h"
#include "net/http/http_network_session.h"
#include "net/http/http_server_properties.h"
#include "net/http/http_stream_factory_impl_job.h"
#include "net/http/http_stream_factory_impl_request.h"
#include "net/http/transport_security_state.h"
#include "net/log/net_log.h"
-#include "net/net_features.h"
#include "net/quic/quic_server_id.h"
+#include "net/spdy/bidirectional_stream_spdy_impl.h"
#include "net/spdy/spdy_http_stream.h"
#include "url/gurl.h"
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
-#include "net/spdy/bidirectional_stream_spdy_job.h"
-#endif
-
namespace net {
HttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session,
@@ -55,13 +50,9 @@ HttpStreamRequest* HttpStreamFactoryImpl::RequestStream(
HttpStreamRequest::Delegate* delegate,
const BoundNetLog& net_log) {
DCHECK(!for_websockets_);
- return RequestStreamInternal(request_info,
- priority,
- server_ssl_config,
- proxy_ssl_config,
- delegate,
- NULL,
- net_log);
+ return RequestStreamInternal(request_info, priority, server_ssl_config,
+ proxy_ssl_config, delegate, nullptr,
+ HttpStreamRequest::HTTP_STREAM, net_log);
}
HttpStreamRequest* HttpStreamFactoryImpl::RequestWebSocketHandshakeStream(
@@ -74,16 +65,12 @@ HttpStreamRequest* HttpStreamFactoryImpl::RequestWebSocketHandshakeStream(
const BoundNetLog& net_log) {
DCHECK(for_websockets_);
DCHECK(create_helper);
- return RequestStreamInternal(request_info,
- priority,
- server_ssl_config,
- proxy_ssl_config,
- delegate,
- create_helper,
- net_log);
+ return RequestStreamInternal(request_info, priority, server_ssl_config,
+ proxy_ssl_config, delegate, create_helper,
+ HttpStreamRequest::HTTP_STREAM, net_log);
}
-HttpStreamRequest* HttpStreamFactoryImpl::RequestBidirectionalStreamJob(
+HttpStreamRequest* HttpStreamFactoryImpl::RequestBidirectionalStreamImpl(
const HttpRequestInfo& request_info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
@@ -93,24 +80,9 @@ HttpStreamRequest* HttpStreamFactoryImpl::RequestBidirectionalStreamJob(
DCHECK(!for_websockets_);
DCHECK(request_info.url.SchemeIs(url::kHttpsScheme));
-// TODO(xunjieli): Create QUIC's version of BidirectionalStreamJob.
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- HostPortPair server = HostPortPair::FromURL(request_info.url);
- GURL origin_url = ApplyHostMappingRules(request_info.url, &server);
- Request* request =
- new Request(request_info.url, this, delegate, nullptr, net_log,
- Request::BIDIRECTIONAL_STREAM_SPDY_JOB);
- Job* job = new Job(this, session_, request_info, priority, server_ssl_config,
- proxy_ssl_config, server, origin_url, net_log.net_log());
- request->AttachJob(job);
-
- job->Start(request);
- return request;
-
-#else
- DCHECK(false);
- return nullptr;
-#endif
+ return RequestStreamInternal(
+ request_info, priority, server_ssl_config, proxy_ssl_config, delegate,
+ nullptr, HttpStreamRequest::BIDIRECTIONAL_STREAM, net_log);
}
HttpStreamRequest* HttpStreamFactoryImpl::RequestStreamInternal(
@@ -121,10 +93,11 @@ HttpStreamRequest* HttpStreamFactoryImpl::RequestStreamInternal(
HttpStreamRequest::Delegate* delegate,
WebSocketHandshakeStreamBase::CreateHelper*
websocket_handshake_stream_create_helper,
+ HttpStreamRequest::StreamType stream_type,
const BoundNetLog& net_log) {
Request* request = new Request(request_info.url, this, delegate,
websocket_handshake_stream_create_helper,
- net_log, Request::HTTP_STREAM);
+ net_log, stream_type);
HostPortPair server = HostPortPair::FromURL(request_info.url);
GURL origin_url = ApplyHostMappingRules(request_info.url, &server);
@@ -133,7 +106,7 @@ HttpStreamRequest* HttpStreamFactoryImpl::RequestStreamInternal(
request->AttachJob(job);
const AlternativeService alternative_service =
- GetAlternativeServiceFor(request_info, delegate);
+ GetAlternativeServiceFor(request_info, delegate, stream_type);
if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) {
// Never share connection with other jobs for FTP requests.
@@ -171,8 +144,8 @@ void HttpStreamFactoryImpl::PreconnectStreams(
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config) {
DCHECK(!for_websockets_);
- AlternativeService alternative_service =
- GetAlternativeServiceFor(request_info, nullptr);
+ AlternativeService alternative_service = GetAlternativeServiceFor(
+ request_info, nullptr, HttpStreamRequest::HTTP_STREAM);
HostPortPair server;
if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) {
server = alternative_service.host_port_pair();
@@ -203,7 +176,8 @@ const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const {
AlternativeService HttpStreamFactoryImpl::GetAlternativeServiceFor(
const HttpRequestInfo& request_info,
- HttpStreamRequest::Delegate* delegate) {
+ HttpStreamRequest::Delegate* delegate,
+ HttpStreamRequest::StreamType stream_type) {
GURL original_url = request_info.url;
if (original_url.SchemeIs("ftp"))
@@ -221,7 +195,7 @@ AlternativeService HttpStreamFactoryImpl::GetAlternativeServiceFor(
bool quic_all_broken = true;
const bool enable_different_host =
- session_->params().use_alternative_services;
+ session_->params().enable_alternative_service_with_different_host;
// First Alt-Svc that is not marked as broken.
AlternativeService first_alternative_service;
@@ -258,9 +232,6 @@ AlternativeService HttpStreamFactoryImpl::GetAlternativeServiceFor(
if (!HttpStreamFactory::spdy_enabled())
continue;
- if (session_->HasSpdyExclusion(origin))
- continue;
-
// Cache this entry if we don't have a non-broken Alt-Svc yet.
if (first_alternative_service.protocol ==
UNINITIALIZED_ALTERNATE_PROTOCOL)
@@ -273,6 +244,14 @@ AlternativeService HttpStreamFactoryImpl::GetAlternativeServiceFor(
if (!session_->params().enable_quic)
continue;
+ if (!IsQuicWhitelistedForHost(origin.host()))
+ continue;
+
+ if (stream_type == HttpStreamRequest::BIDIRECTIONAL_STREAM &&
+ session_->params().quic_disable_bidirectional_streams) {
+ continue;
+ }
+
if (session_->quic_stream_factory()->IsQuicDisabled(origin.port()))
continue;
@@ -288,9 +267,6 @@ AlternativeService HttpStreamFactoryImpl::GetAlternativeServiceFor(
server_id, request_info.privacy_mode, origin_host))
return alternative_service;
- if (!IsQuicWhitelistedForHost(destination.host()))
- continue;
-
// Cache this entry if we don't have a non-broken Alt-Svc yet.
if (first_alternative_service.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
first_alternative_service = alternative_service;
@@ -342,14 +318,11 @@ void HttpStreamFactoryImpl::OnNewSpdySessionReady(
// TODO(ricea): Restore this code path when WebSocket over SPDY
// implementation is ready.
NOTREACHED();
- } else if (request->for_bidirectional()) {
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- request->OnBidirectionalStreamJobReady(
+ } else if (request->stream_type() ==
+ HttpStreamRequest::BIDIRECTIONAL_STREAM) {
+ request->OnBidirectionalStreamImplReady(
nullptr, used_ssl_config, used_proxy_info,
- new BidirectionalStreamSpdyJob(spdy_session));
-#else
- DCHECK(false);
-#endif
+ new BidirectionalStreamSpdyImpl(spdy_session));
} else {
bool use_relative_url = direct || request->url().SchemeIs("https");
request->OnStreamReady(
@@ -372,15 +345,23 @@ void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) {
}
bool HttpStreamFactoryImpl::IsQuicWhitelistedForHost(const std::string& host) {
- if (session_->params().transport_security_state->IsGooglePinnedHost(host))
+ bool whitelist_needed = false;
+ for (QuicVersion version : session_->params().quic_supported_versions) {
+ if (version <= QUIC_VERSION_30) {
+ whitelist_needed = true;
+ break;
+ }
+ }
+
+ // The QUIC whitelist is not needed in QUIC versions after 30.
+ if (!whitelist_needed)
return true;
- std::string lower_host = base::ToLowerASCII(host);
- if (ContainsKey(session_->params().quic_host_whitelist, lower_host))
+ if (session_->params().transport_security_state->IsGooglePinnedHost(host))
return true;
- return base::EndsWith(lower_host, ".snapchat.com",
- base::CompareCase::SENSITIVE);
+ return ContainsKey(session_->params().quic_host_whitelist,
+ base::ToLowerASCII(host));
}
} // namespace net
diff --git a/chromium/net/http/http_stream_factory_impl.h b/chromium/net/http/http_stream_factory_impl.h
index 799398f539e..97a9a6c9b1d 100644
--- a/chromium/net/http/http_stream_factory_impl.h
+++ b/chromium/net/http/http_stream_factory_impl.h
@@ -51,7 +51,7 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : public HttpStreamFactory {
WebSocketHandshakeStreamBase::CreateHelper* create_helper,
const BoundNetLog& net_log) override;
- HttpStreamRequest* RequestBidirectionalStreamJob(
+ HttpStreamRequest* RequestBidirectionalStreamImpl(
const HttpRequestInfo& info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
@@ -69,6 +69,7 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : public HttpStreamFactory {
private:
FRIEND_TEST_ALL_PREFIXES(HttpStreamFactoryImplRequestTest, SetPriority);
+ FRIEND_TEST_ALL_PREFIXES(HttpStreamFactoryImplRequestTest, DelayMainJob);
class NET_EXPORT_PRIVATE Request;
class NET_EXPORT_PRIVATE Job;
@@ -83,11 +84,13 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : public HttpStreamFactory {
const SSLConfig& proxy_ssl_config,
HttpStreamRequest::Delegate* delegate,
WebSocketHandshakeStreamBase::CreateHelper* create_helper,
+ HttpStreamRequest::StreamType stream_type,
const BoundNetLog& net_log);
AlternativeService GetAlternativeServiceFor(
const HttpRequestInfo& request_info,
- HttpStreamRequest::Delegate* delegate);
+ HttpStreamRequest::Delegate* delegate,
+ HttpStreamRequest::StreamType stream_type);
// Detaches |job| from |request|.
void OrphanJob(Job* job, const Request* request);
@@ -118,8 +121,7 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : public HttpStreamFactory {
// Called when the Preconnect completes. Used for testing.
virtual void OnPreconnectsCompleteInternal() {}
- // Returns true if QUIC is whitelisted for |host|, which should be
- // the result of calling ApplyHostMappingRules().
+ // Returns true if QUIC is whitelisted for |host|.
bool IsQuicWhitelistedForHost(const std::string& host);
HttpNetworkSession* const session_;
diff --git a/chromium/net/http/http_stream_factory_impl_job.cc b/chromium/net/http/http_stream_factory_impl_job.cc
index 791a390dac5..8da356fdac3 100644
--- a/chromium/net/http/http_stream_factory_impl_job.cc
+++ b/chromium/net/http/http_stream_factory_impl_job.cc
@@ -21,12 +21,13 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "build/build_config.h"
#include "net/base/connection_type_histograms.h"
-#include "net/base/net_util.h"
#include "net/base/port_util.h"
#include "net/cert/cert_verifier.h"
+#include "net/http/bidirectional_stream_impl.h"
#include "net/http/http_basic_stream.h"
#include "net/http/http_network_session.h"
#include "net/http/http_proxy_client_socket.h"
@@ -43,21 +44,75 @@
#include "net/socket/socks_client_socket_pool.h"
#include "net/socket/ssl_client_socket.h"
#include "net/socket/ssl_client_socket_pool.h"
+#include "net/spdy/bidirectional_stream_spdy_impl.h"
#include "net/spdy/spdy_http_stream.h"
#include "net/spdy/spdy_protocol.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_session_pool.h"
+#include "net/ssl/channel_id_service.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_failure_state.h"
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
-#include "net/http/bidirectional_stream_job.h"
-#include "net/spdy/bidirectional_stream_spdy_job.h"
-#endif
-
namespace net {
+namespace {
+
+void DoNothingAsyncCallback(int result){};
+void RecordChannelIDKeyMatch(SSLClientSocket* ssl_socket,
+ ChannelIDService* channel_id_service,
+ std::string host) {
+ SSLInfo ssl_info;
+ ssl_socket->GetSSLInfo(&ssl_info);
+ if (!ssl_info.channel_id_sent)
+ return;
+ scoped_ptr<crypto::ECPrivateKey> request_key;
+ ChannelIDService::Request request;
+ int result = channel_id_service->GetOrCreateChannelID(
+ host, &request_key, base::Bind(&DoNothingAsyncCallback), &request);
+ // GetOrCreateChannelID only returns ERR_IO_PENDING before its first call
+ // (over the lifetime of the ChannelIDService) has completed or if it is
+ // creating a new key. The key that is being looked up here should already
+ // have been looked up before the channel ID was sent on the ssl socket, so
+ // the expectation is that this call will return synchronously. If this does
+ // return ERR_IO_PENDING, treat that as any other lookup failure and cancel
+ // the async request.
+ if (result == ERR_IO_PENDING)
+ request.Cancel();
+ crypto::ECPrivateKey* socket_key = ssl_socket->GetChannelIDKey();
+
+ // This enum is used for an UMA histogram - do not change or re-use values.
+ enum {
+ NO_KEYS = 0,
+ MATCH = 1,
+ SOCKET_KEY_MISSING = 2,
+ REQUEST_KEY_MISSING = 3,
+ KEYS_DIFFER = 4,
+ KEY_LOOKUP_ERROR = 5,
+ KEY_MATCH_MAX
+ } match;
+ if (result != OK) {
+ match = KEY_LOOKUP_ERROR;
+ } else if (!socket_key && !request_key) {
+ match = NO_KEYS;
+ } else if (!socket_key) {
+ match = SOCKET_KEY_MISSING;
+ } else if (!request_key) {
+ match = REQUEST_KEY_MISSING;
+ } else {
+ match = KEYS_DIFFER;
+ std::string raw_socket_key, raw_request_key;
+ if (socket_key->ExportRawPublicKey(&raw_socket_key) &&
+ request_key->ExportRawPublicKey(&raw_request_key) &&
+ raw_socket_key == raw_request_key) {
+ match = MATCH;
+ }
+ }
+ UMA_HISTOGRAM_ENUMERATION("Net.TokenBinding.KeyMatch", match, KEY_MATCH_MAX);
+}
+
+} // namespace
+
// Returns parameters associated with the start of a HTTP stream job.
scoped_ptr<base::Value> NetLogHttpStreamJobCallback(
const NetLog::Source& source,
@@ -76,6 +131,15 @@ scoped_ptr<base::Value> NetLogHttpStreamJobCallback(
return std::move(dict);
}
+// Returns parameters associated with the delay of the HTTP stream job.
+scoped_ptr<base::Value> NetLogHttpStreamJobDelayCallback(
+ base::TimeDelta delay,
+ NetLogCaptureMode /* capture_mode */) {
+ scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ dict->SetInteger("resume_after_ms", static_cast<int>(delay.InMilliseconds()));
+ return std::move(dict);
+}
+
// Returns parameters associated with the Proto (with NPN negotiation) of a HTTP
// stream.
scoped_ptr<base::Value> NetLogHttpStreamProtoCallback(
@@ -150,7 +214,7 @@ HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory,
spdy_session_direct_(false),
job_status_(STATUS_RUNNING),
other_job_status_(STATUS_RUNNING),
- for_bidirectional_(false),
+ stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM),
ptr_factory_(this) {
DCHECK(stream_factory);
DCHECK(session);
@@ -182,8 +246,8 @@ HttpStreamFactoryImpl::Job::~Job() {
void HttpStreamFactoryImpl::Job::Start(Request* request) {
DCHECK(request);
request_ = request;
- // Saves |for_bidirectional_|, since request is nulled when job is orphaned.
- for_bidirectional_ = request_->for_bidirectional();
+ // Saves |stream_type_|, since request is nulled when job is orphaned.
+ stream_type_ = request_->stream_type();
StartInternal();
}
@@ -234,19 +298,32 @@ void HttpStreamFactoryImpl::Job::WaitFor(Job* job) {
job->waiting_job_ = this;
}
+void HttpStreamFactoryImpl::Job::ResumeAfterDelay() {
+ DCHECK(!blocking_job_);
+ DCHECK_EQ(STATE_WAIT_FOR_JOB_COMPLETE, next_state_);
+
+ net_log_.AddEvent(NetLog::TYPE_HTTP_STREAM_JOB_DELAYED,
+ base::Bind(&NetLogHttpStreamJobDelayCallback, wait_time_));
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::Bind(&HttpStreamFactoryImpl::Job::OnIOComplete,
+ ptr_factory_.GetWeakPtr(), OK),
+ wait_time_);
+}
+
void HttpStreamFactoryImpl::Job::Resume(Job* job,
const base::TimeDelta& delay) {
DCHECK_EQ(blocking_job_, job);
blocking_job_ = NULL;
+ // If |this| job is not past STATE_WAIT_FOR_JOB_COMPLETE state, then it will
+ // be delayed by the |wait_time_| when it resumes.
+ if (next_state_ == STATE_NONE || next_state_ <= STATE_WAIT_FOR_JOB_COMPLETE)
+ wait_time_ = delay;
+
// We know we're blocked if the next_state_ is STATE_WAIT_FOR_JOB_COMPLETE.
// Unblock |this|.
- if (next_state_ == STATE_WAIT_FOR_JOB_COMPLETE) {
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&HttpStreamFactoryImpl::Job::OnIOComplete,
- ptr_factory_.GetWeakPtr(), OK),
- delay);
- }
+ if (next_state_ == STATE_WAIT_FOR_JOB_COMPLETE)
+ ResumeAfterDelay();
}
void HttpStreamFactoryImpl::Job::Orphan(const Request* request) {
@@ -343,6 +420,9 @@ void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() {
DCHECK(!IsPreconnecting());
DCHECK(!stream_factory_->for_websockets_);
+ UMA_HISTOGRAM_TIMES("Net.HttpStreamFactoryJob.StreamReadyCallbackTime",
+ base::TimeTicks::Now() - job_stream_ready_start_time_);
+
MaybeCopyConnectionAttemptsFromSocketOrHandle();
if (IsOrphaned()) {
@@ -374,9 +454,8 @@ void HttpStreamFactoryImpl::Job::OnWebSocketHandshakeStreamReadyCallback() {
// |this| may be deleted after this call.
}
-void HttpStreamFactoryImpl::Job::OnBidirectionalStreamJobReadyCallback() {
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- DCHECK(bidirectional_stream_job_);
+void HttpStreamFactoryImpl::Job::OnBidirectionalStreamImplReadyCallback() {
+ DCHECK(bidirectional_stream_impl_);
MaybeCopyConnectionAttemptsFromSocketOrHandle();
@@ -385,22 +464,15 @@ void HttpStreamFactoryImpl::Job::OnBidirectionalStreamJobReadyCallback() {
} else {
request_->Complete(was_npn_negotiated(), protocol_negotiated(),
using_spdy());
- request_->OnBidirectionalStreamJobReady(
+ request_->OnBidirectionalStreamImplReady(
this, server_ssl_config_, proxy_info_,
- bidirectional_stream_job_.release());
+ bidirectional_stream_impl_.release());
}
// |this| may be deleted after this call.
-#else
- DCHECK(false);
-#endif
}
void HttpStreamFactoryImpl::Job::OnNewSpdySessionReadyCallback() {
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- DCHECK(stream_.get() || bidirectional_stream_job_.get());
-#else
- DCHECK(stream_.get());
-#endif
+ DCHECK(stream_.get() || bidirectional_stream_impl_.get());
DCHECK(!IsPreconnecting());
DCHECK(using_spdy());
// Note: an event loop iteration has passed, so |new_spdy_session_| may be
@@ -420,20 +492,15 @@ void HttpStreamFactoryImpl::Job::OnNewSpdySessionReadyCallback() {
}
stream_factory_->OnOrphanedJobComplete(this);
} else {
- if (for_bidirectional_) {
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- DCHECK(bidirectional_stream_job_);
+ if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) {
+ DCHECK(bidirectional_stream_impl_);
request_->OnNewSpdySessionReady(this, /*spdy_http_stream=*/nullptr,
- std::move(bidirectional_stream_job_),
+ std::move(bidirectional_stream_impl_),
spdy_session, spdy_session_direct_);
-#else
- DCHECK(false);
-#endif
-
} else {
DCHECK(stream_);
request_->OnNewSpdySessionReady(this, std::move(stream_),
- /** bidirectional_stream_job=*/nullptr,
+ /** bidirectional_stream_impl=*/nullptr,
spdy_session, spdy_session_direct_);
}
}
@@ -523,21 +590,27 @@ void HttpStreamFactoryImpl::Job::OnPreconnectsComplete() {
int HttpStreamFactoryImpl::Job::OnHostResolution(
SpdySessionPool* spdy_session_pool,
const SpdySessionKey& spdy_session_key,
+ const GURL& origin_url,
const AddressList& addresses,
const BoundNetLog& net_log) {
// It is OK to dereference spdy_session_pool, because the
// ClientSocketPoolManager will be destroyed in the same callback that
// destroys the SpdySessionPool.
- return
- spdy_session_pool->FindAvailableSession(spdy_session_key, net_log) ?
- ERR_SPDY_SESSION_ALREADY_EXISTS : OK;
+ return spdy_session_pool->FindAvailableSession(spdy_session_key, origin_url,
+ net_log)
+ ? ERR_SPDY_SESSION_ALREADY_EXISTS
+ : OK;
}
void HttpStreamFactoryImpl::Job::OnIOComplete(int result) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "HttpStreamFactoryImpl::Job::OnIOComplete");
RunLoop(result);
}
int HttpStreamFactoryImpl::Job::RunLoop(int result) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "HttpStreamFactoryImpl::Job::RunLoop");
result = DoLoop(result);
if (result == ERR_IO_PENDING)
@@ -583,15 +656,17 @@ int HttpStreamFactoryImpl::Job::RunLoop(int result) {
FROM_HERE,
base::Bind(&Job::OnNeedsProxyAuthCallback, ptr_factory_.GetWeakPtr(),
*proxy_socket->GetConnectResponseInfo(),
- proxy_socket->GetAuthController()));
+ base::RetainedRef(proxy_socket->GetAuthController())));
return ERR_IO_PENDING;
}
case ERR_SSL_CLIENT_AUTH_CERT_NEEDED:
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&Job::OnNeedsClientAuthCallback, ptr_factory_.GetWeakPtr(),
- connection_->ssl_error_response_info().cert_request_info));
+ base::Bind(
+ &Job::OnNeedsClientAuthCallback, ptr_factory_.GetWeakPtr(),
+ base::RetainedRef(
+ connection_->ssl_error_response_info().cert_request_info)));
return ERR_IO_PENDING;
case ERR_HTTPS_PROXY_TUNNEL_RESPONSE: {
@@ -622,22 +697,20 @@ int HttpStreamFactoryImpl::Job::RunLoop(int result) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&Job::OnWebSocketHandshakeStreamReadyCallback,
ptr_factory_.GetWeakPtr()));
- } else if (for_bidirectional_) {
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- if (!bidirectional_stream_job_) {
+ } else if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) {
+ if (!bidirectional_stream_impl_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&Job::OnStreamFailedCallback,
ptr_factory_.GetWeakPtr(), ERR_FAILED));
} else {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&Job::OnBidirectionalStreamJobReadyCallback,
- ptr_factory_.GetWeakPtr()));
+ FROM_HERE,
+ base::Bind(&Job::OnBidirectionalStreamImplReadyCallback,
+ ptr_factory_.GetWeakPtr()));
}
-#else
- DCHECK(false);
-#endif
} else {
DCHECK(stream_.get());
+ job_stream_ready_start_time_ = base::TimeTicks::Now();
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&Job::OnStreamReadyCallback, ptr_factory_.GetWeakPtr()));
@@ -788,8 +861,9 @@ int HttpStreamFactoryImpl::Job::DoResolveProxy() {
}
return session_->proxy_service()->ResolveProxy(
- url_for_proxy, request_info_.load_flags, &proxy_info_, io_callback_,
- &pac_request_, session_->network_delegate(), net_log_);
+ url_for_proxy, request_info_.method, request_info_.load_flags,
+ &proxy_info_, io_callback_, &pac_request_,
+ session_->params().proxy_delegate, net_log_);
}
int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
@@ -827,28 +901,37 @@ int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
return result;
}
- if (blocking_job_)
- next_state_ = STATE_WAIT_FOR_JOB;
- else
- next_state_ = STATE_INIT_CONNECTION;
+ next_state_ = STATE_WAIT_FOR_JOB;
return OK;
}
bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const {
return session_->params().enable_quic &&
- session_->params().origin_to_force_quic_on.Equals(server_) &&
+ ContainsKey(session_->params().origins_to_force_quic_on, server_) &&
proxy_info_.is_direct() && origin_url_.SchemeIs("https");
}
int HttpStreamFactoryImpl::Job::DoWaitForJob() {
- DCHECK(blocking_job_);
+ if (!blocking_job_ && wait_time_.is_zero()) {
+ // There is no |blocking_job_| and there is no |wait_time_|.
+ next_state_ = STATE_INIT_CONNECTION;
+ return OK;
+ }
+
next_state_ = STATE_WAIT_FOR_JOB_COMPLETE;
+ if (!wait_time_.is_zero()) {
+ // If there is a waiting_time, then resume the job after the wait_time_.
+ DCHECK(!blocking_job_);
+ ResumeAfterDelay();
+ }
+
return ERR_IO_PENDING;
}
int HttpStreamFactoryImpl::Job::DoWaitForJobComplete(int result) {
DCHECK(!blocking_job_);
DCHECK_EQ(OK, result);
+ wait_time_ = base::TimeDelta();
next_state_ = STATE_INIT_CONNECTION;
return OK;
}
@@ -878,14 +961,13 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() {
}
if (proxy_info_.is_https() || proxy_info_.is_quic()) {
- InitSSLConfig(proxy_info_.proxy_server().host_port_pair(),
- &proxy_ssl_config_, /*is_proxy=*/true);
+ InitSSLConfig(&proxy_ssl_config_, /*is_proxy=*/true);
// Disable revocation checking for HTTPS proxies since the revocation
// requests are probably going to need to go through the proxy too.
proxy_ssl_config_.rev_checking_enabled = false;
}
if (using_ssl_) {
- InitSSLConfig(server_, &server_ssl_config_, /*is_proxy=*/false);
+ InitSSLConfig(&server_ssl_config_, /*is_proxy=*/false);
}
if (using_quic_) {
@@ -895,13 +977,23 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() {
return ERR_NOT_IMPLEMENTED;
}
HostPortPair destination;
- std::string origin_host;
SSLConfig* ssl_config;
+ GURL url(request_info_.url);
if (proxy_info_.is_quic()) {
// A proxy's certificate is expected to be valid for the proxy hostname.
destination = proxy_info_.proxy_server().host_port_pair();
- origin_host = destination.host();
ssl_config = &proxy_ssl_config_;
+ GURL::Replacements replacements;
+ replacements.SetSchemeStr("https");
+ replacements.SetHostStr(destination.host());
+ const std::string new_port = base::UintToString(destination.port());
+ replacements.SetPortStr(new_port);
+ replacements.ClearUsername();
+ replacements.ClearPassword();
+ replacements.ClearPath();
+ replacements.ClearQuery();
+ replacements.ClearRef();
+ url = url.ReplaceComponents(replacements);
// If QUIC is disabled on the destination port, return error.
if (session_->quic_stream_factory()->IsQuicDisabled(destination.port()))
@@ -912,12 +1004,11 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() {
// for the origin of the request (in addition to being valid for the
// server itself).
destination = server_;
- origin_host = origin_url_.host();
ssl_config = &server_ssl_config_;
}
int rv =
quic_request_.Request(destination, request_info_.privacy_mode,
- ssl_config->GetCertVerifyFlags(), origin_host,
+ ssl_config->GetCertVerifyFlags(), url,
request_info_.method, net_log_, io_callback_);
if (rv == OK) {
using_existing_quic_session_ = true;
@@ -1004,7 +1095,7 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() {
OnHostResolutionCallback resolution_callback =
CanUseExistingSpdySession()
? base::Bind(&Job::OnHostResolution, session_->spdy_session_pool(),
- spdy_session_key)
+ spdy_session_key, origin_url_)
: OnHostResolutionCallback();
if (stream_factory_->for_websockets_) {
// TODO(ricea): Re-enable NPN when WebSockets over SPDY is supported.
@@ -1044,7 +1135,7 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
SpdySessionKey spdy_session_key = GetSpdySessionKey();
existing_spdy_session_ =
session_->spdy_session_pool()->FindAvailableSession(
- spdy_session_key, net_log_);
+ spdy_session_key, origin_url_, net_log_);
if (existing_spdy_session_) {
using_spdy_ = true;
next_state_ = STATE_CREATE_STREAM;
@@ -1156,7 +1247,20 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
MaybeMarkAlternativeServiceBroken();
return result;
}
- stream_ = quic_request_.ReleaseStream();
+ if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) {
+ bidirectional_stream_impl_ =
+ quic_request_.CreateBidirectionalStreamImpl();
+ if (!bidirectional_stream_impl_) {
+ // Quic session is closed before stream can be created.
+ return ERR_CONNECTION_CLOSED;
+ }
+ } else {
+ stream_ = quic_request_.CreateStream();
+ if (!stream_) {
+ // Quic session is closed before stream can be created.
+ return ERR_CONNECTION_CLOSED;
+ }
+ }
next_state_ = STATE_NONE;
return OK;
}
@@ -1206,22 +1310,16 @@ int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) {
return ERR_IO_PENDING;
}
-int HttpStreamFactoryImpl::Job::SetSpdyHttpStreamOrBidirectionalStreamJob(
+int HttpStreamFactoryImpl::Job::SetSpdyHttpStreamOrBidirectionalStreamImpl(
base::WeakPtr<SpdySession> session,
bool direct) {
// TODO(ricea): Restore the code for WebSockets over SPDY once it's
// implemented.
if (stream_factory_->for_websockets_)
return ERR_NOT_IMPLEMENTED;
- if (for_bidirectional_) {
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- // TODO(xunjieli): Create QUIC's version of BidirectionalStreamJob.
- bidirectional_stream_job_.reset(new BidirectionalStreamSpdyJob(session));
+ if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) {
+ bidirectional_stream_impl_.reset(new BidirectionalStreamSpdyImpl(session));
return OK;
-#else
- DCHECK(false);
- return ERR_FAILED;
-#endif
}
// TODO(willchan): Delete this code, because eventually, the
@@ -1243,6 +1341,13 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
next_state_ = STATE_CREATE_STREAM_COMPLETE;
+ if (using_ssl_ && connection_->socket()) {
+ SSLClientSocket* ssl_socket =
+ static_cast<SSLClientSocket*>(connection_->socket());
+ RecordChannelIDKeyMatch(ssl_socket, session_->params().channel_id_service,
+ server_.HostForURL());
+ }
+
// We only set the socket motivation if we're the first to use
// this socket. Is there a race for two SPDY requests? We really
// need to plumb this through to the connect level.
@@ -1276,7 +1381,7 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
connection_->socket()->Disconnect();
connection_->Reset();
- int set_result = SetSpdyHttpStreamOrBidirectionalStreamJob(
+ int set_result = SetSpdyHttpStreamOrBidirectionalStreamImpl(
existing_spdy_session_, direct);
existing_spdy_session_.reset();
return set_result;
@@ -1290,7 +1395,7 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
return result;
}
if (spdy_session) {
- return SetSpdyHttpStreamOrBidirectionalStreamJob(spdy_session, direct);
+ return SetSpdyHttpStreamOrBidirectionalStreamImpl(spdy_session, direct);
}
result = valid_spdy_session_pool_->CreateAvailableSessionFromSocket(
@@ -1325,13 +1430,13 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
if (http_server_properties)
http_server_properties->SetSupportsSpdy(host_port_pair, true);
- // Create a SpdyHttpStream or a BidirectionalStreamJob attached to the
+ // Create a SpdyHttpStream or a BidirectionalStreamImpl attached to the
// session; OnNewSpdySessionReadyCallback is not called until an event loop
// iteration later, so if the SpdySession is closed between then, allow
// reuse state from the underlying socket, sampled by SpdyHttpStream,
// bubble up to the request.
- return SetSpdyHttpStreamOrBidirectionalStreamJob(new_spdy_session_,
- spdy_session_direct_);
+ return SetSpdyHttpStreamOrBidirectionalStreamImpl(new_spdy_session_,
+ spdy_session_direct_);
}
int HttpStreamFactoryImpl::Job::DoCreateStreamComplete(int result) {
@@ -1339,7 +1444,7 @@ int HttpStreamFactoryImpl::Job::DoCreateStreamComplete(int result) {
return result;
session_->proxy_service()->ReportSuccess(proxy_info_,
- session_->network_delegate());
+ session_->params().proxy_delegate);
next_state_ = STATE_NONE;
return OK;
}
@@ -1411,8 +1516,7 @@ bool HttpStreamFactoryImpl::Job::IsQuicAlternative() const {
return alternative_service_.protocol == QUIC;
}
-void HttpStreamFactoryImpl::Job::InitSSLConfig(const HostPortPair& server,
- SSLConfig* ssl_config,
+void HttpStreamFactoryImpl::Job::InitSSLConfig(SSLConfig* ssl_config,
bool is_proxy) const {
if (!is_proxy) {
// Prior to HTTP/2 and SPDY, some servers use TLS renegotiation to request
@@ -1511,8 +1615,9 @@ int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) {
}
int rv = session_->proxy_service()->ReconsiderProxyAfterError(
- request_info_.url, request_info_.load_flags, error, &proxy_info_,
- io_callback_, &pac_request_, session_->network_delegate(), net_log_);
+ request_info_.url, request_info_.method, request_info_.load_flags, error,
+ &proxy_info_, io_callback_, &pac_request_,
+ session_->params().proxy_delegate, net_log_);
if (rv == OK || rv == ERR_IO_PENDING) {
// If the error was during connection setup, there is no socket to
// disconnect.
@@ -1615,6 +1720,8 @@ void HttpStreamFactoryImpl::Job::MaybeMarkAlternativeServiceBroken() {
return;
}
+ session_->quic_stream_factory()->OnTcpJobCompleted(job_status_ ==
+ STATUS_SUCCEEDED);
if (job_status_ == STATUS_SUCCEEDED && other_job_status_ == STATUS_BROKEN) {
HistogramBrokenAlternateProtocolLocation(
BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_MAIN);
@@ -1636,7 +1743,8 @@ int HttpStreamFactoryImpl::Job::ValidSpdySessionPool::FindAvailableSession(
const SpdySessionKey& key,
const BoundNetLog& net_log,
base::WeakPtr<SpdySession>* spdy_session) {
- *spdy_session = spdy_session_pool_->FindAvailableSession(key, net_log);
+ *spdy_session =
+ spdy_session_pool_->FindAvailableSession(key, origin_url_, net_log);
return CheckAlternativeServiceValidityForOrigin(*spdy_session);
}
@@ -1647,6 +1755,8 @@ int HttpStreamFactoryImpl::Job::ValidSpdySessionPool::
int certificate_error_code,
bool is_secure,
base::WeakPtr<SpdySession>* spdy_session) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "HttpStreamFactoryImpl::Job::CreateAvailableSessionFromSocket");
*spdy_session = spdy_session_pool_->CreateAvailableSessionFromSocket(
key, std::move(connection), net_log, certificate_error_code, is_secure);
return CheckAlternativeServiceValidityForOrigin(*spdy_session);
diff --git a/chromium/net/http/http_stream_factory_impl_job.h b/chromium/net/http/http_stream_factory_impl_job.h
index 5e935cc14d3..17519741959 100644
--- a/chromium/net/http/http_stream_factory_impl_job.h
+++ b/chromium/net/http/http_stream_factory_impl_job.h
@@ -17,7 +17,6 @@
#include "net/http/http_request_info.h"
#include "net/http/http_stream_factory_impl.h"
#include "net/log/net_log.h"
-#include "net/net_features.h"
#include "net/proxy/proxy_service.h"
#include "net/quic/quic_stream_factory.h"
#include "net/socket/client_socket_handle.h"
@@ -28,7 +27,7 @@
namespace net {
-class BidirectionalStreamJob;
+class BidirectionalStreamImpl;
class ClientSocketHandle;
class HttpAuthController;
class HttpNetworkSession;
@@ -93,7 +92,7 @@ class HttpStreamFactoryImpl::Job {
NextProto protocol_negotiated() const;
bool using_spdy() const;
const BoundNetLog& net_log() const { return net_log_; }
- bool for_bidirectional() const { return for_bidirectional_; }
+ HttpStreamRequest::StreamType stream_type() const { return stream_type_; }
const SSLConfig& server_ssl_config() const;
const SSLConfig& proxy_ssl_config() const;
@@ -113,6 +112,8 @@ class HttpStreamFactoryImpl::Job {
void MarkOtherJobComplete(const Job& job);
private:
+ FRIEND_TEST_ALL_PREFIXES(HttpStreamFactoryImplRequestTest, DelayMainJob);
+
enum State {
STATE_START,
STATE_RESOLVE_PROXY,
@@ -133,6 +134,8 @@ class HttpStreamFactoryImpl::Job {
// The npn-spdy job will Resume() the http job if, in
// STATE_INIT_CONNECTION_COMPLETE, it detects an error or does not find an
// existing SpdySession. In that case, the http and npn-spdy jobs will race.
+ // When QUIC protocol is used by the npn-spdy job, then http job will wait
+ // for |wait_time_| when the http job was resumed.
STATE_WAIT_FOR_JOB,
STATE_WAIT_FOR_JOB_COMPLETE,
@@ -201,8 +204,11 @@ class HttpStreamFactoryImpl::Job {
const bool is_spdy_alternative_;
};
+ // Resume the |this| job after the specified |wait_time_|.
+ void ResumeAfterDelay();
+
void OnStreamReadyCallback();
- void OnBidirectionalStreamJobReadyCallback();
+ void OnBidirectionalStreamImplReadyCallback();
void OnWebSocketHandshakeStreamReadyCallback();
// This callback function is called when a new SPDY session is created.
void OnNewSpdySessionReadyCallback();
@@ -237,10 +243,10 @@ class HttpStreamFactoryImpl::Job {
int DoRestartTunnelAuth();
int DoRestartTunnelAuthComplete(int result);
- // Creates a SpdyHttpStream or a BidirectionalStreamJob from the given values
- // and sets to |stream_| or |bidirectional_stream_job_| respectively. Does
+ // Creates a SpdyHttpStream or a BidirectionalStreamImpl from the given values
+ // and sets to |stream_| or |bidirectional_stream_impl_| respectively. Does
// nothing if |stream_factory_| is for WebSockets.
- int SetSpdyHttpStreamOrBidirectionalStreamJob(
+ int SetSpdyHttpStreamOrBidirectionalStreamImpl(
base::WeakPtr<SpdySession> session,
bool direct);
@@ -256,11 +262,9 @@ class HttpStreamFactoryImpl::Job {
bool IsSpdyAlternative() const;
bool IsQuicAlternative() const;
- // Sets several fields of |ssl_config| for |server| based on the proxy info
- // and other factors.
- void InitSSLConfig(const HostPortPair& server,
- SSLConfig* ssl_config,
- bool is_proxy) const;
+ // Sets several fields of |ssl_config| based on the proxy info and other
+ // factors.
+ void InitSSLConfig(SSLConfig* ssl_config, bool is_proxy) const;
// Retrieve SSLInfo from our SSL Socket.
// This must only be called when we are using an SSLSocket.
@@ -309,6 +313,7 @@ class HttpStreamFactoryImpl::Job {
// session is found, and OK otherwise.
static int OnHostResolution(SpdySessionPool* spdy_session_pool,
const SpdySessionKey& spdy_session_key,
+ const GURL& origin_url,
const AddressList& addresses,
const BoundNetLog& net_log);
@@ -352,6 +357,8 @@ class HttpStreamFactoryImpl::Job {
// proceed and then race the two Jobs.
Job* waiting_job_;
+ base::TimeDelta wait_time_;
+
// True if handling a HTTPS request, or using SPDY with SSL
bool using_ssl_;
@@ -380,9 +387,7 @@ class HttpStreamFactoryImpl::Job {
scoped_ptr<HttpStream> stream_;
scoped_ptr<WebSocketHandshakeStreamBase> websocket_stream_;
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- scoped_ptr<BidirectionalStreamJob> bidirectional_stream_job_;
-#endif
+ scoped_ptr<BidirectionalStreamImpl> bidirectional_stream_impl_;
// True if we negotiated NPN.
bool was_npn_negotiated_;
@@ -407,9 +412,10 @@ class HttpStreamFactoryImpl::Job {
JobStatus job_status_;
JobStatus other_job_status_;
+ base::TimeTicks job_stream_ready_start_time_;
- // True if BidirectionalStreamJob is requested.
- bool for_bidirectional_;
+ // Type of stream that is requested.
+ HttpStreamRequest::StreamType stream_type_;
base::WeakPtrFactory<Job> ptr_factory_;
diff --git a/chromium/net/http/http_stream_factory_impl_request.cc b/chromium/net/http/http_stream_factory_impl_request.cc
index 59b7b44c4ac..7c5cbc92ab5 100644
--- a/chromium/net/http/http_stream_factory_impl_request.cc
+++ b/chromium/net/http/http_stream_factory_impl_request.cc
@@ -7,14 +7,11 @@
#include "base/callback.h"
#include "base/logging.h"
#include "base/stl_util.h"
+#include "net/http/bidirectional_stream_impl.h"
#include "net/http/http_stream_factory_impl_job.h"
#include "net/spdy/spdy_http_stream.h"
#include "net/spdy/spdy_session.h"
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
-#include "net/http/bidirectional_stream_job.h"
-#endif
-
namespace net {
HttpStreamFactoryImpl::Request::Request(
@@ -35,7 +32,7 @@ HttpStreamFactoryImpl::Request::Request(
was_npn_negotiated_(false),
protocol_negotiated_(kProtoUnknown),
using_spdy_(false),
- for_bidirectional_(stream_type == BIDIRECTIONAL_STREAM_SPDY_JOB) {
+ stream_type_(stream_type) {
DCHECK(factory_);
DCHECK(delegate_);
@@ -83,7 +80,7 @@ void HttpStreamFactoryImpl::Request::OnStreamReady(
const ProxyInfo& used_proxy_info,
HttpStream* stream) {
DCHECK(!factory_->for_websockets_);
- DCHECK(!for_bidirectional_);
+ DCHECK_EQ(HttpStreamRequest::HTTP_STREAM, stream_type_);
DCHECK(stream);
DCHECK(completed_);
@@ -91,19 +88,19 @@ void HttpStreamFactoryImpl::Request::OnStreamReady(
delegate_->OnStreamReady(used_ssl_config, used_proxy_info, stream);
}
-void HttpStreamFactoryImpl::Request::OnBidirectionalStreamJobReady(
+void HttpStreamFactoryImpl::Request::OnBidirectionalStreamImplReady(
Job* job,
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
- BidirectionalStreamJob* stream_job) {
+ BidirectionalStreamImpl* stream_job) {
DCHECK(!factory_->for_websockets_);
- DCHECK(for_bidirectional_);
+ DCHECK_EQ(HttpStreamRequest::BIDIRECTIONAL_STREAM, stream_type_);
DCHECK(stream_job);
DCHECK(completed_);
OnJobSucceeded(job);
- delegate_->OnBidirectionalStreamJobReady(used_ssl_config, used_proxy_info,
- stream_job);
+ delegate_->OnBidirectionalStreamImplReady(used_ssl_config, used_proxy_info,
+ stream_job);
}
void HttpStreamFactoryImpl::Request::OnWebSocketHandshakeStreamReady(
@@ -112,7 +109,7 @@ void HttpStreamFactoryImpl::Request::OnWebSocketHandshakeStreamReady(
const ProxyInfo& used_proxy_info,
WebSocketHandshakeStreamBase* stream) {
DCHECK(factory_->for_websockets_);
- DCHECK(!for_bidirectional_);
+ DCHECK_EQ(HttpStreamRequest::HTTP_STREAM, stream_type_);
DCHECK(stream);
DCHECK(completed_);
@@ -275,11 +272,7 @@ bool HttpStreamFactoryImpl::Request::HasSpdySessionKey() const {
void HttpStreamFactoryImpl::Request::OnNewSpdySessionReady(
Job* job,
scoped_ptr<HttpStream> stream,
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- scoped_ptr<BidirectionalStreamJob> bidirectional_stream_job,
-#else
- void* bidirectional_stream_job,
-#endif
+ scoped_ptr<BidirectionalStreamImpl> bidirectional_stream_impl,
const base::WeakPtr<SpdySession>& spdy_session,
bool direct) {
DCHECK(job);
@@ -314,18 +307,14 @@ void HttpStreamFactoryImpl::Request::OnNewSpdySessionReady(
// TODO(ricea): Re-instate this code when WebSockets over SPDY is
// implemented.
NOTREACHED();
- } else if (for_bidirectional_) {
- DCHECK(bidirectional_stream_job);
+ } else if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) {
+ DCHECK(bidirectional_stream_impl);
DCHECK(!stream);
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- delegate_->OnBidirectionalStreamJobReady(
+ delegate_->OnBidirectionalStreamImplReady(
job->server_ssl_config(), job->proxy_info(),
- bidirectional_stream_job.release());
-#else
- NOTREACHED();
-#endif
+ bidirectional_stream_impl.release());
} else {
- DCHECK(!bidirectional_stream_job);
+ DCHECK(!bidirectional_stream_impl);
DCHECK(stream);
delegate_->OnStreamReady(job->server_ssl_config(), job->proxy_info(),
stream.release());
diff --git a/chromium/net/http/http_stream_factory_impl_request.h b/chromium/net/http/http_stream_factory_impl_request.h
index a92303c97b9..a84615fc54b 100644
--- a/chromium/net/http/http_stream_factory_impl_request.h
+++ b/chromium/net/http/http_stream_factory_impl_request.h
@@ -11,7 +11,6 @@
#include "base/memory/scoped_ptr.h"
#include "net/http/http_stream_factory_impl.h"
#include "net/log/net_log.h"
-#include "net/net_features.h"
#include "net/socket/connection_attempts.h"
#include "net/socket/ssl_client_socket.h"
#include "net/spdy/spdy_session_key.h"
@@ -20,19 +19,13 @@
namespace net {
-class BidirectionalStreamJob;
+class BidirectionalStreamImpl;
class ClientSocketHandle;
class HttpStream;
class SpdySession;
class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
public:
- // Indicates which type of stream is requested.
- enum StreamType {
- BIDIRECTIONAL_STREAM_SPDY_JOB,
- HTTP_STREAM,
- };
-
Request(const GURL& url,
HttpStreamFactoryImpl* factory,
HttpStreamRequest::Delegate* delegate,
@@ -69,16 +62,13 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
void RemoveRequestFromSpdySessionRequestMap();
// Called by an attached Job if it sets up a SpdySession.
- // |stream| is null when |for_bidirectional| is true.
- // |bidirectional_stream_spdy_job| is null when |for_bidirectional| is false.
+ // |stream| is null when |stream_type| is HttpStreamRequest::HTTP_STREAM.
+ // |bidirectional_stream_spdy_impl| is null when |stream_type| is
+ // HttpStreamRequest::BIDIRECTIONAL_STREAM.
void OnNewSpdySessionReady(
Job* job,
scoped_ptr<HttpStream> stream,
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- scoped_ptr<BidirectionalStreamJob> bidirectional_stream_spdy_job,
-#else
- void* unused,
-#endif
+ scoped_ptr<BidirectionalStreamImpl> bidirectional_stream_spdy_impl,
const base::WeakPtr<SpdySession>& spdy_session,
bool direct);
@@ -98,10 +88,10 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStream* stream);
- void OnBidirectionalStreamJobReady(Job* job,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- BidirectionalStreamJob* stream);
+ void OnBidirectionalStreamImplReady(Job* job,
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ BidirectionalStreamImpl* stream);
void OnWebSocketHandshakeStreamReady(Job* job,
const SSLConfig& used_ssl_config,
@@ -139,7 +129,7 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
NextProto protocol_negotiated() const override;
bool using_spdy() const override;
const ConnectionAttempts& connection_attempts() const override;
- bool for_bidirectional() const { return for_bidirectional_; }
+ HttpStreamRequest::StreamType stream_type() const { return stream_type_; }
private:
// Used to bind |job| to the request and orphan all other jobs in |jobs_|.
@@ -173,7 +163,7 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
bool using_spdy_;
ConnectionAttempts connection_attempts_;
- const bool for_bidirectional_;
+ const HttpStreamRequest::StreamType stream_type_;
DISALLOW_COPY_AND_ASSIGN(Request);
};
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 9e9c5d1f013..6a08a00ffae 100644
--- a/chromium/net/http/http_stream_factory_impl_request_unittest.cc
+++ b/chromium/net/http/http_stream_factory_impl_request_unittest.cc
@@ -35,10 +35,10 @@ class DoNothingRequestDelegate : public HttpStreamRequest::Delegate {
void OnStreamReady(const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStream* stream) override {}
- void OnBidirectionalStreamJobReady(
+ void OnBidirectionalStreamImplReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
- BidirectionalStreamJob* stream_job) override {}
+ BidirectionalStreamImpl* stream) override {}
void OnWebSocketHandshakeStreamReady(
const SSLConfig& used_ssl_config,
@@ -101,4 +101,66 @@ TEST_P(HttpStreamFactoryImplRequestTest, SetPriority) {
EXPECT_EQ(IDLE, job->priority());
}
+TEST_P(HttpStreamFactoryImplRequestTest, DelayMainJob) {
+ SpdySessionDependencies session_deps(GetParam(),
+ ProxyService::CreateDirect());
+
+ scoped_ptr<HttpNetworkSession> session =
+ SpdySessionDependencies::SpdyCreateSession(&session_deps);
+
+ StaticSocketDataProvider socket_data;
+ socket_data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
+ session_deps.socket_factory->AddSocketDataProvider(&socket_data);
+
+ HttpStreamFactoryImpl* factory =
+ static_cast<HttpStreamFactoryImpl*>(session->http_stream_factory());
+
+ DoNothingRequestDelegate request_delegate;
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("http://www.google.com");
+
+ HttpStreamFactoryImpl::Request request(
+ request_info.url, factory, &request_delegate, NULL, BoundNetLog(),
+ HttpStreamFactoryImpl::Request::HTTP_STREAM);
+
+ HostPortPair server = HostPortPair::FromURL(request_info.url);
+ GURL original_url = factory->ApplyHostMappingRules(request_info.url, &server);
+
+ HttpStreamFactoryImpl::Job* job = new HttpStreamFactoryImpl::Job(
+ factory, session.get(), request_info, DEFAULT_PRIORITY, SSLConfig(),
+ SSLConfig(), server, original_url, NULL);
+ request.AttachJob(job);
+ EXPECT_EQ(DEFAULT_PRIORITY, job->priority());
+
+ AlternativeService alternative_service(net::NPN_HTTP_2, server);
+ HttpStreamFactoryImpl::Job* alternative_job = new HttpStreamFactoryImpl::Job(
+ factory, session.get(), request_info, DEFAULT_PRIORITY, SSLConfig(),
+ SSLConfig(), server, original_url, alternative_service, NULL);
+ request.AttachJob(alternative_job);
+
+ job->WaitFor(alternative_job);
+ EXPECT_EQ(HttpStreamFactoryImpl::Job::STATE_NONE, job->next_state_);
+
+ // Test |alternative_job| resuming the |job| after delay.
+ int wait_time = 1;
+ base::TimeDelta delay = base::TimeDelta::FromMilliseconds(wait_time);
+ job->Resume(alternative_job, delay);
+
+ // Verify |job| has |wait_time_| and there is no |blocking_job_|
+ EXPECT_EQ(delay, job->wait_time_);
+ EXPECT_TRUE(!job->blocking_job_);
+
+ // Start the |job| and verify |job|'s |wait_time_| is cleared.
+ job->Start(&request);
+
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(wait_time + 1));
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_NE(delay, job->wait_time_);
+ EXPECT_TRUE(job->wait_time_.is_zero());
+ EXPECT_EQ(HttpStreamFactoryImpl::Job::STATE_INIT_CONNECTION_COMPLETE,
+ job->next_state_);
+}
+
} // namespace net
diff --git a/chromium/net/http/http_stream_factory_impl_unittest.cc b/chromium/net/http/http_stream_factory_impl_unittest.cc
index 32c20e32c7a..f95ea511fa3 100644
--- a/chromium/net/http/http_stream_factory_impl_unittest.cc
+++ b/chromium/net/http/http_stream_factory_impl_unittest.cc
@@ -11,10 +11,14 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "net/base/port_util.h"
#include "net/base/test_completion_callback.h"
+#include "net/base/test_data_directory.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/dns/mock_host_resolver.h"
+#include "net/http/bidirectional_stream_impl.h"
+#include "net/http/bidirectional_stream_request_info.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_network_session.h"
#include "net/http/http_network_session_peer.h"
@@ -25,11 +29,16 @@
#include "net/http/http_stream.h"
#include "net/http/transport_security_state.h"
#include "net/log/net_log.h"
-#include "net/net_features.h"
#include "net/proxy/proxy_info.h"
#include "net/proxy/proxy_service.h"
+#include "net/quic/quic_http_utils.h"
#include "net/quic/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"
#include "net/socket/next_proto.h"
@@ -39,19 +48,17 @@
#include "net/spdy/spdy_test_util_common.h"
#include "net/ssl/ssl_config_service.h"
#include "net/ssl/ssl_config_service_defaults.h"
+#include "net/test/cert_test_util.h"
+
// This file can be included from net/http even though
// it is in net/websockets because it doesn't
// introduce any link dependency to net/websockets.
#include "net/websockets/websocket_handshake_stream_base.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
-#include "net/http/bidirectional_stream_job.h"
-#endif
-
namespace net {
-class BidirectionalStreamJob;
+class BidirectionalStreamImpl;
namespace {
@@ -103,6 +110,11 @@ class MockWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
void GetSSLInfo(SSLInfo* ssl_info) override {}
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {}
bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override {
+ ADD_FAILURE();
+ return ERR_NOT_IMPLEMENTED;
+ }
void Drain(HttpNetworkSession* session) override {}
void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
void SetPriority(RequestPriority priority) override {}
@@ -175,17 +187,14 @@ class StreamRequestWaiter : public HttpStreamRequest::Delegate {
used_proxy_info_ = used_proxy_info;
}
- void OnBidirectionalStreamJobReady(const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- BidirectionalStreamJob* stream) override {
+ void OnBidirectionalStreamImplReady(
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ BidirectionalStreamImpl* stream) override {
stream_done_ = true;
if (waiting_for_stream_)
base::MessageLoop::current()->QuitWhenIdle();
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- bidirectional_stream_job_.reset(stream);
-#else
- DCHECK(!stream);
-#endif
+ bidirectional_stream_impl_.reset(stream);
used_ssl_config_ = used_ssl_config;
used_proxy_info_ = used_proxy_info;
}
@@ -243,11 +252,9 @@ class StreamRequestWaiter : public HttpStreamRequest::Delegate {
return static_cast<MockWebSocketHandshakeStream*>(websocket_stream_.get());
}
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- BidirectionalStreamJob* bidirectional_stream_job() {
- return bidirectional_stream_job_.get();
+ BidirectionalStreamImpl* bidirectional_stream_impl() {
+ return bidirectional_stream_impl_.get();
}
-#endif
bool stream_done() const { return stream_done_; }
int error_status() const { return error_status_; }
@@ -257,9 +264,7 @@ class StreamRequestWaiter : public HttpStreamRequest::Delegate {
bool stream_done_;
scoped_ptr<HttpStream> stream_;
scoped_ptr<WebSocketHandshakeStreamBase> websocket_stream_;
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
- scoped_ptr<BidirectionalStreamJob> bidirectional_stream_job_;
-#endif
+ scoped_ptr<BidirectionalStreamImpl> bidirectional_stream_impl_;
SSLConfig used_ssl_config_;
ProxyInfo used_proxy_info_;
int error_status_;
@@ -369,6 +374,7 @@ class CapturePreconnectsSocketPool : public ParentPool {
int RequestSocket(const std::string& group_name,
const void* socket_params,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) override {
@@ -732,6 +738,70 @@ TEST_P(HttpStreamFactoryTest, UnreachableQuicProxyMarkedAsBad) {
}
}
+// BidirectionalStreamImpl::Delegate to wait until response headers are
+// received.
+class TestBidirectionalDelegate : public BidirectionalStreamImpl::Delegate {
+ public:
+ void WaitUntilDone() { loop_.Run(); }
+
+ const SpdyHeaderBlock& response_headers() const { return response_headers_; }
+
+ private:
+ void OnHeadersSent() override {}
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override {
+ response_headers_ = response_headers;
+ loop_.Quit();
+ }
+ void OnDataRead(int bytes_read) override { NOTREACHED(); }
+ void OnDataSent() override { NOTREACHED(); }
+ void OnTrailersReceived(const SpdyHeaderBlock& trailers) override {
+ NOTREACHED();
+ }
+ void OnFailed(int error) override { NOTREACHED(); }
+ base::RunLoop loop_;
+ SpdyHeaderBlock response_headers_;
+};
+
+// Helper class to encapsulate MockReads and MockWrites for QUIC.
+// Simplify ownership issues and the interaction with the MockSocketFactory.
+class MockQuicData {
+ public:
+ MockQuicData() : packet_number_(0) {}
+
+ ~MockQuicData() { STLDeleteElements(&packets_); }
+
+ void AddRead(scoped_ptr<QuicEncryptedPacket> packet) {
+ reads_.push_back(
+ MockRead(ASYNC, packet->data(), packet->length(), packet_number_++));
+ packets_.push_back(packet.release());
+ }
+
+ void AddRead(IoMode mode, int rv) {
+ reads_.push_back(MockRead(mode, rv, packet_number_++));
+ }
+
+ void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
+ writes_.push_back(MockWrite(SYNCHRONOUS, packet->data(), packet->length(),
+ packet_number_++));
+ packets_.push_back(packet.release());
+ }
+
+ void AddSocketDataToFactory(MockClientSocketFactory* factory) {
+ MockRead* reads = reads_.empty() ? nullptr : &reads_[0];
+ MockWrite* writes = writes_.empty() ? nullptr : &writes_[0];
+ socket_data_.reset(
+ new SequencedSocketData(reads, reads_.size(), writes, writes_.size()));
+ factory->AddSocketDataProvider(socket_data_.get());
+ }
+
+ private:
+ std::vector<QuicEncryptedPacket*> packets_;
+ std::vector<MockWrite> writes_;
+ std::vector<MockRead> reads_;
+ size_t packet_number_;
+ scoped_ptr<SequencedSocketData> socket_data_;
+};
+
} // namespace
TEST_P(HttpStreamFactoryTest, QuicLossyProxyMarkedAsBad) {
@@ -762,6 +832,8 @@ TEST_P(HttpStreamFactoryTest, QuicLossyProxyMarkedAsBad) {
session->quic_stream_factory()->number_of_lossy_connections_[99] =
params.quic_max_number_of_lossy_connections;
+ session->quic_stream_factory()->MaybeDisableQuic(99);
+ ASSERT_TRUE(session->quic_stream_factory()->IsQuicDisabled(99));
StaticSocketDataProvider socket_data2;
socket_data2.set_connect_data(MockConnect(ASYNC, OK));
@@ -802,7 +874,7 @@ TEST_P(HttpStreamFactoryTest, UsePreConnectIfNoZeroRTT) {
AlternativeServiceInfoVector alternative_service_info_vector;
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service, 1.0, expiration));
+ AlternativeServiceInfo(alternative_service, expiration));
HostPortPair host_port_pair(alternative_service.host_port_pair());
http_server_properties.SetAlternativeServices(
host_port_pair, alternative_service_info_vector);
@@ -846,7 +918,7 @@ TEST_P(HttpStreamFactoryTest, QuicDisablePreConnectIfZeroRtt) {
AlternativeServiceInfoVector alternative_service_info_vector;
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service, 1.0, expiration));
+ AlternativeServiceInfo(alternative_service, expiration));
HostPortPair host_port_pair(alternative_service.host_port_pair());
http_server_properties.SetAlternativeServices(
host_port_pair, alternative_service_info_vector);
@@ -1385,8 +1457,7 @@ TEST_P(HttpStreamFactoryTest, RequestSpdyHttpStream) {
EXPECT_TRUE(waiter.used_proxy_info().is_direct());
}
-#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
-TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamJob) {
+TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamImpl) {
SpdySessionDependencies session_deps(GetParam(),
ProxyService::CreateDirect());
@@ -1412,14 +1483,14 @@ TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamJob) {
SSLConfig ssl_config;
StreamRequestWaiter waiter;
scoped_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestBidirectionalStreamJob(
+ session->http_stream_factory()->RequestBidirectionalStreamImpl(
request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
BoundNetLog()));
waiter.WaitForStream();
EXPECT_TRUE(waiter.stream_done());
EXPECT_FALSE(waiter.websocket_stream());
ASSERT_FALSE(waiter.stream());
- ASSERT_TRUE(waiter.bidirectional_stream_job());
+ ASSERT_TRUE(waiter.bidirectional_stream_impl());
EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetTransportSocketPool(
HttpNetworkSession::NORMAL_SOCKET_POOL)));
EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSSLSocketPool(
@@ -1434,7 +1505,296 @@ TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamJob) {
->num_orphaned_jobs());
}
-TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamJobFailure) {
+class HttpStreamFactoryBidirectionalQuicTest
+ : public ::testing::Test,
+ public ::testing::WithParamInterface<QuicVersion> {
+ protected:
+ HttpStreamFactoryBidirectionalQuicTest()
+ : clock_(new MockClock),
+ packet_maker_(GetParam(), 0, clock_, "www.example.org"),
+ random_generator_(0),
+ proxy_service_(ProxyService::CreateDirect()),
+ ssl_config_service_(new SSLConfigServiceDefaults) {
+ clock_->AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
+ }
+
+ // Disable bidirectional stream over QUIC. This should be invoked before
+ // Initialize().
+ void DisableQuicBidirectionalStream() {
+ params_.quic_disable_bidirectional_streams = true;
+ }
+
+ void Initialize() {
+ params_.enable_quic = true;
+ params_.http_server_properties = http_server_properties_.GetWeakPtr();
+ params_.quic_host_whitelist.insert("www.example.org");
+ params_.quic_random = &random_generator_;
+ params_.quic_clock = clock_;
+
+ // Load a certificate that is valid for *.example.org
+ scoped_refptr<X509Certificate> test_cert(
+ ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
+ EXPECT_TRUE(test_cert.get());
+ verify_details_.cert_verify_result.verified_cert = test_cert;
+ verify_details_.cert_verify_result.is_issued_by_known_root = true;
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
+ crypto_client_stream_factory_.set_handshake_mode(
+ MockCryptoClientStream::CONFIRM_HANDSHAKE);
+ params_.quic_crypto_client_stream_factory = &crypto_client_stream_factory_;
+ params_.quic_supported_versions = test::SupportedVersions(GetParam());
+ params_.transport_security_state = &transport_security_state_;
+ params_.host_resolver = &host_resolver_;
+ params_.proxy_service = proxy_service_.get();
+ params_.ssl_config_service = ssl_config_service_.get();
+ params_.client_socket_factory = &socket_factory_;
+ session_.reset(new HttpNetworkSession(params_));
+ session_->quic_stream_factory()->set_require_confirmation(false);
+ }
+
+ void AddQuicAlternativeService() {
+ const AlternativeService alternative_service(QUIC, "www.example.org", 443);
+ AlternativeServiceInfoVector alternative_service_info_vector;
+ base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
+ alternative_service_info_vector.push_back(
+ AlternativeServiceInfo(alternative_service, expiration));
+ HostPortPair host_port_pair(alternative_service.host_port_pair());
+ http_server_properties_.SetAlternativeServices(
+ host_port_pair, alternative_service_info_vector);
+ };
+
+ test::QuicTestPacketMaker& packet_maker() { return packet_maker_; }
+
+ MockClientSocketFactory& socket_factory() { return socket_factory_; }
+
+ HttpNetworkSession* session() { return session_.get(); }
+
+ private:
+ MockClock* clock_; // Owned by QuicStreamFactory
+ test::QuicTestPacketMaker packet_maker_;
+ MockClientSocketFactory socket_factory_;
+ scoped_ptr<HttpNetworkSession> session_;
+ test::MockRandom random_generator_;
+ ProofVerifyDetailsChromium verify_details_;
+ MockCryptoClientStreamFactory crypto_client_stream_factory_;
+ HttpServerPropertiesImpl http_server_properties_;
+ TransportSecurityState transport_security_state_;
+ MockHostResolver host_resolver_;
+ scoped_ptr<ProxyService> proxy_service_;
+ scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
+ HttpNetworkSession::Params params_;
+};
+
+INSTANTIATE_TEST_CASE_P(Version,
+ HttpStreamFactoryBidirectionalQuicTest,
+ ::testing::ValuesIn(QuicSupportedVersions()));
+
+TEST_P(HttpStreamFactoryBidirectionalQuicTest,
+ RequestBidirectionalStreamImplQuicAlternative) {
+ GURL url = GURL("https://www.example.org");
+
+ MockQuicData mock_quic_data;
+ SpdyPriority priority =
+ ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
+ size_t spdy_headers_frame_length;
+ mock_quic_data.AddWrite(packet_maker().MakeRequestHeadersPacket(
+ 1, test::kClientDataStreamId1, /*should_include_version=*/true,
+ /*fin=*/true, priority,
+ packet_maker().GetRequestHeaders("GET", "https", "/"),
+ &spdy_headers_frame_length));
+ size_t spdy_response_headers_frame_length;
+ mock_quic_data.AddRead(packet_maker().MakeResponseHeadersPacket(
+ 1, test::kClientDataStreamId1, /*should_include_version=*/false,
+ /*fin=*/true, packet_maker().GetResponseHeaders("200"),
+ &spdy_response_headers_frame_length));
+ mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
+ mock_quic_data.AddSocketDataToFactory(&socket_factory());
+
+ // Add hanging data for http job.
+ scoped_ptr<StaticSocketDataProvider> hanging_data;
+ hanging_data.reset(new StaticSocketDataProvider());
+ MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
+ hanging_data->set_connect_data(hanging_connect);
+ socket_factory().AddSocketDataProvider(hanging_data.get());
+ SSLSocketDataProvider ssl_data(ASYNC, OK);
+ socket_factory().AddSSLSocketDataProvider(&ssl_data);
+
+ // Set up QUIC as alternative_service.
+ AddQuicAlternativeService();
+ Initialize();
+
+ // Now request a stream.
+ SSLConfig ssl_config;
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("https://www.example.org");
+ request_info.load_flags = 0;
+
+ StreamRequestWaiter waiter;
+ scoped_ptr<HttpStreamRequest> request(
+ session()->http_stream_factory()->RequestBidirectionalStreamImpl(
+ request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
+ BoundNetLog()));
+
+ waiter.WaitForStream();
+ EXPECT_TRUE(waiter.stream_done());
+ EXPECT_FALSE(waiter.websocket_stream());
+ ASSERT_FALSE(waiter.stream());
+ ASSERT_TRUE(waiter.bidirectional_stream_impl());
+ BidirectionalStreamImpl* stream_impl = waiter.bidirectional_stream_impl();
+
+ BidirectionalStreamRequestInfo bidi_request_info;
+ bidi_request_info.method = "GET";
+ bidi_request_info.url = GURL("https://www.example.org/");
+ bidi_request_info.end_stream_on_headers = true;
+ bidi_request_info.priority = LOWEST;
+
+ TestBidirectionalDelegate delegate;
+ stream_impl->Start(&bidi_request_info, BoundNetLog(), &delegate, nullptr);
+ delegate.WaitUntilDone();
+
+ scoped_refptr<IOBuffer> buffer = new net::IOBuffer(1);
+ EXPECT_EQ(OK, stream_impl->ReadData(buffer.get(), 1));
+ EXPECT_EQ(kProtoQUIC1SPDY3, stream_impl->GetProtocol());
+ EXPECT_EQ("200", delegate.response_headers().find(":status")->second);
+ EXPECT_EQ(1, GetSocketPoolGroupCount(session()->GetTransportSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL)));
+ EXPECT_EQ(1, 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_TRUE(waiter.used_proxy_info().is_direct());
+}
+
+// Tests that when QUIC is not enabled for bidirectional streaming, HTTP/2 is
+// used instead.
+TEST_P(HttpStreamFactoryBidirectionalQuicTest,
+ RequestBidirectionalStreamImplQuicNotEnabled) {
+ GURL url = GURL("https://www.example.org");
+
+ // Make the http job fail.
+ scoped_ptr<StaticSocketDataProvider> http_job_data;
+ http_job_data.reset(new StaticSocketDataProvider());
+ MockConnect failed_connect(ASYNC, ERR_CONNECTION_REFUSED);
+ http_job_data->set_connect_data(failed_connect);
+ socket_factory().AddSocketDataProvider(http_job_data.get());
+ SSLSocketDataProvider ssl_data(ASYNC, OK);
+ socket_factory().AddSSLSocketDataProvider(&ssl_data);
+
+ // Set up QUIC as alternative_service.
+ AddQuicAlternativeService();
+ DisableQuicBidirectionalStream();
+ Initialize();
+
+ // Now request a stream.
+ SSLConfig ssl_config;
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("https://www.example.org");
+ request_info.load_flags = 0;
+
+ StreamRequestWaiter waiter;
+ scoped_ptr<HttpStreamRequest> request(
+ session()->http_stream_factory()->RequestBidirectionalStreamImpl(
+ request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
+ BoundNetLog()));
+
+ waiter.WaitForStream();
+ EXPECT_TRUE(waiter.stream_done());
+ EXPECT_FALSE(waiter.websocket_stream());
+ ASSERT_FALSE(waiter.stream());
+ ASSERT_FALSE(waiter.bidirectional_stream_impl());
+ // Since the alternative service job is not started, we will get the error
+ // from the http job.
+ ASSERT_EQ(ERR_CONNECTION_REFUSED, waiter.error_status());
+}
+
+// Tests that if Http job fails, but Quic job succeeds, we return
+// BidirectionalStreamQuicImpl.
+TEST_P(HttpStreamFactoryBidirectionalQuicTest,
+ RequestBidirectionalStreamImplHttpJobFailsQuicJobSucceeds) {
+ GURL url = GURL("https://www.example.org");
+
+ // Set up Quic data.
+ MockQuicData mock_quic_data;
+ SpdyPriority priority =
+ ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
+ size_t spdy_headers_frame_length;
+ mock_quic_data.AddWrite(packet_maker().MakeRequestHeadersPacket(
+ 1, test::kClientDataStreamId1, /*should_include_version=*/true,
+ /*fin=*/true, priority,
+ packet_maker().GetRequestHeaders("GET", "https", "/"),
+ &spdy_headers_frame_length));
+ size_t spdy_response_headers_frame_length;
+ mock_quic_data.AddRead(packet_maker().MakeResponseHeadersPacket(
+ 1, test::kClientDataStreamId1, /*should_include_version=*/false,
+ /*fin=*/true, packet_maker().GetResponseHeaders("200"),
+ &spdy_response_headers_frame_length));
+ mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
+ mock_quic_data.AddSocketDataToFactory(&socket_factory());
+
+ // Make the http job fail.
+ scoped_ptr<StaticSocketDataProvider> http_job_data;
+ http_job_data.reset(new StaticSocketDataProvider());
+ MockConnect failed_connect(ASYNC, ERR_CONNECTION_REFUSED);
+ http_job_data->set_connect_data(failed_connect);
+ socket_factory().AddSocketDataProvider(http_job_data.get());
+ SSLSocketDataProvider ssl_data(ASYNC, OK);
+ socket_factory().AddSSLSocketDataProvider(&ssl_data);
+
+ // Set up QUIC as alternative_service.
+ AddQuicAlternativeService();
+ Initialize();
+
+ // Now request a stream.
+ SSLConfig ssl_config;
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("https://www.example.org");
+ request_info.load_flags = 0;
+
+ StreamRequestWaiter waiter;
+ scoped_ptr<HttpStreamRequest> request(
+ session()->http_stream_factory()->RequestBidirectionalStreamImpl(
+ request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
+ BoundNetLog()));
+
+ waiter.WaitForStream();
+ EXPECT_TRUE(waiter.stream_done());
+ EXPECT_FALSE(waiter.websocket_stream());
+ ASSERT_FALSE(waiter.stream());
+ ASSERT_TRUE(waiter.bidirectional_stream_impl());
+ BidirectionalStreamImpl* stream_impl = waiter.bidirectional_stream_impl();
+
+ BidirectionalStreamRequestInfo bidi_request_info;
+ bidi_request_info.method = "GET";
+ bidi_request_info.url = GURL("https://www.example.org/");
+ bidi_request_info.end_stream_on_headers = true;
+ bidi_request_info.priority = LOWEST;
+
+ TestBidirectionalDelegate delegate;
+ stream_impl->Start(&bidi_request_info, BoundNetLog(), &delegate, nullptr);
+ delegate.WaitUntilDone();
+
+ // Make sure the BidirectionalStream negotiated goes through QUIC.
+ scoped_refptr<IOBuffer> buffer = new net::IOBuffer(1);
+ EXPECT_EQ(OK, stream_impl->ReadData(buffer.get(), 1));
+ EXPECT_EQ(kProtoQUIC1SPDY3, stream_impl->GetProtocol());
+ EXPECT_EQ("200", delegate.response_headers().find(":status")->second);
+ // There is no Http2 socket pool.
+ 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_TRUE(waiter.used_proxy_info().is_direct());
+}
+
+TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamImplFailure) {
SpdySessionDependencies session_deps(GetParam(),
ProxyService::CreateDirect());
@@ -1445,7 +1805,7 @@ TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamJobFailure) {
SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
- // If HTTP/1 is used, BidirectionalStreamJob should not be obtained.
+ // If HTTP/1 is used, BidirectionalStreamImpl should not be obtained.
ssl_socket_data.SetNextProto(kProtoHTTP11);
session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
@@ -1462,7 +1822,7 @@ TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamJobFailure) {
SSLConfig ssl_config;
StreamRequestWaiter waiter;
scoped_ptr<HttpStreamRequest> request(
- session->http_stream_factory()->RequestBidirectionalStreamJob(
+ session->http_stream_factory()->RequestBidirectionalStreamImpl(
request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
BoundNetLog()));
waiter.WaitForStream();
@@ -1470,7 +1830,7 @@ TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamJobFailure) {
ASSERT_EQ(ERR_FAILED, waiter.error_status());
EXPECT_FALSE(waiter.websocket_stream());
ASSERT_FALSE(waiter.stream());
- ASSERT_FALSE(waiter.bidirectional_stream_job());
+ ASSERT_FALSE(waiter.bidirectional_stream_impl());
EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetTransportSocketPool(
HttpNetworkSession::NORMAL_SOCKET_POOL)));
EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSSLSocketPool(
@@ -1483,7 +1843,6 @@ TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamJobFailure) {
static_cast<HttpStreamFactoryImpl*>(session->http_stream_factory())
->num_orphaned_jobs());
}
-#endif
// TODO(ricea): This test can be removed once the new WebSocket stack supports
// SPDY. Currently, even if we connect to a SPDY-supporting server, we need to
@@ -1619,7 +1978,8 @@ TEST_P(HttpStreamFactoryTest, DISABLED_RequestWebSocketSpdyHandshakeStream) {
TEST_P(HttpStreamFactoryTest, DISABLED_OrphanedWebSocketStream) {
SpdySessionDependencies session_deps(GetParam(),
ProxyService::CreateDirect());
- session_deps.use_alternative_services = true;
+ session_deps.parse_alternative_services = true;
+ session_deps.enable_alternative_service_with_different_host = false;
MockRead mock_read(ASYNC, OK);
SequencedSocketData socket_data(&mock_read, 1, nullptr, 0);
@@ -1647,7 +2007,7 @@ TEST_P(HttpStreamFactoryTest, DISABLED_OrphanedWebSocketStream) {
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
session->http_server_properties()->SetAlternativeService(
HostPortPair("www.google.com", 8888),
- AlternativeService(NPN_HTTP_2, "www.google.com", 9999), 1.0, expiration);
+ AlternativeService(NPN_HTTP_2, "www.google.com", 9999), expiration);
SSLConfig ssl_config;
StreamRequestWaiter waiter;
diff --git a/chromium/net/http/http_stream_parser.cc b/chromium/net/http/http_stream_parser.cc
index e115743ea59..1c33557ecb7 100644
--- a/chromium/net/http/http_stream_parser.cc
+++ b/chromium/net/http/http_stream_parser.cc
@@ -24,6 +24,7 @@
#include "net/http/http_util.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/ssl_client_socket.h"
+#include "net/ssl/token_binding.h"
namespace net {
@@ -66,7 +67,7 @@ std::string GetResponseHeaderLines(const HttpResponseHeaders& headers) {
// values.
bool HeadersContainMultipleCopiesOfField(const HttpResponseHeaders& headers,
const std::string& field_name) {
- void* it = NULL;
+ size_t it = 0;
std::string field_value;
if (!headers.EnumerateHeader(&it, field_name, &field_value))
return false;
@@ -592,6 +593,9 @@ int HttpStreamParser::DoReadHeaders() {
}
int HttpStreamParser::DoReadHeadersComplete(int result) {
+ // DoReadHeadersComplete is called with the result of Socket::Read, which is a
+ // (byte_count | error), and returns (error | OK).
+
result = HandleReadHeaderResult(result);
// TODO(mmenke): The code below is ugly and hacky. A much better and more
@@ -616,7 +620,7 @@ int HttpStreamParser::DoReadHeadersComplete(int result) {
// cases, can normally go to other states after an error reading headers.
io_state_ = STATE_DONE;
// Don't let caller see the headers.
- response_->headers = NULL;
+ response_->headers = nullptr;
return upload_error_;
}
@@ -634,7 +638,7 @@ int HttpStreamParser::DoReadHeadersComplete(int result) {
// Nothing else to do.
io_state_ = STATE_DONE;
// Don't let caller see the headers.
- response_->headers = NULL;
+ response_->headers = nullptr;
return upload_error_;
}
@@ -842,7 +846,7 @@ int HttpStreamParser::HandleReadHeaderResult(int result) {
read_buf_->set_offset(read_buf_->offset() + result);
DCHECK_LE(read_buf_->offset(), read_buf_->capacity());
- DCHECK_GE(result, 0);
+ DCHECK_GT(result, 0);
int end_of_header_offset = FindAndParseResponseHeaders();
@@ -892,7 +896,7 @@ int HttpStreamParser::HandleReadHeaderResult(int result) {
read_buf_unused_offset_ = end_of_header_offset;
// Now waiting for the body to be read.
}
- return result;
+ return OK;
}
int HttpStreamParser::FindAndParseResponseHeaders() {
@@ -1100,6 +1104,17 @@ void HttpStreamParser::GetSSLCertRequestInfo(
}
}
+Error HttpStreamParser::GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ if (!request_->url.SchemeIsCryptographic() || !connection_->socket()) {
+ NOTREACHED();
+ return ERR_FAILED;
+ }
+ SSLClientSocket* ssl_socket =
+ static_cast<SSLClientSocket*>(connection_->socket());
+ return ssl_socket->GetSignedEKMForTokenBinding(key, out);
+}
+
int HttpStreamParser::EncodeChunk(const base::StringPiece& payload,
char* output,
size_t output_size) {
diff --git a/chromium/net/http/http_stream_parser.h b/chromium/net/http/http_stream_parser.h
index d51cb9188bb..b8bb23a2073 100644
--- a/chromium/net/http/http_stream_parser.h
+++ b/chromium/net/http/http_stream_parser.h
@@ -15,7 +15,9 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
+#include "crypto/ec_private_key.h"
#include "net/base/completion_callback.h"
+#include "net/base/net_errors.h"
#include "net/base/net_export.h"
#include "net/base/upload_progress.h"
#include "net/log/net_log.h"
@@ -95,6 +97,9 @@ class NET_EXPORT_PRIVATE HttpStreamParser {
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out);
+
// Encodes the given |payload| in the chunked format to |output|.
// Returns the number of bytes written to |output|. |output_size| should
// be large enough to store the encoded chunk, which is payload.size() +
diff --git a/chromium/net/http/http_stream_parser_fuzzer.cc b/chromium/net/http/http_stream_parser_fuzzer.cc
new file mode 100644
index 00000000000..19cd9af8c8a
--- /dev/null
+++ b/chromium/net/http/http_stream_parser_fuzzer.cc
@@ -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.
+
+#include "net/http/http_stream_parser.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/numerics/safe_conversions.h"
+#include "net/base/address_list.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_request_info.h"
+#include "net/http/http_response_info.h"
+#include "net/log/net_log.h"
+#include "net/log/test_net_log.h"
+#include "net/socket/client_socket_handle.h"
+#include "net/socket/socket_test_util.h"
+#include "url/gurl.h"
+
+// Fuzzer for HttpStreamParser.
+//
+// |data| is the data received over a mock HTTP connection through one or more
+// reads, along with metadata about the size of each read, and whether or not
+// the read completely synchronously.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ // Needed for thread checks and waits.
+ base::MessageLoopForIO message_loop;
+
+ net::MockWrite writes[] = {
+ net::MockWrite(net::ASYNC, 0, "GET / HTTP/1.1\r\n\r\n"),
+ };
+
+ // Break the buffer into a sequence of variable sized sync and async
+ // reads. Use the last bytes of |data| exclusively for determining
+ // the size and type of each read.
+ std::vector<net::MockRead> reads;
+ // Sequence number for socket operations.
+ int last_sequence_number = 0;
+
+ // IoMode for the final read, where the server closes the mock socket.
+ net::IoMode close_socket_io_mode = net::ASYNC;
+
+ // Break |data| up into reads. The test may or may not make to the final
+ // read, where the server closes the socket.
+
+ // Each read needs a one byte seed to determine read size and whether it
+ // should be sync or async, so if there's only one byte left unused, can't use
+ // it here. The bytes used to get this metadata are not used as over-the-wire
+ // bytes.
+ while (size > 0) {
+ size_t read_seed = data[size - 1];
+ size--;
+ net::IoMode io_mode = net::ASYNC;
+ // Low order bit determines IoMode.
+ if (read_seed & 0x1)
+ io_mode = net::SYNCHRONOUS;
+
+ // Use second bit to determine if the last read, when the socket is closed,
+ // is synchronous. The second bit only matters the last time this loop is
+ // runs.
+ if (read_seed & 0x2) {
+ close_socket_io_mode = net::SYNCHRONOUS;
+ } else {
+ close_socket_io_mode = net::ASYNC;
+ }
+
+ // If there are no more bytes in |data|, next read is the connection close.
+ if (size == 0)
+ break;
+
+ read_seed >>= 2;
+
+ // Last 6 bits determine how many bytes are returned by the read.
+ int read_size = static_cast<int>(std::min(1 + read_seed, size));
+ reads.push_back(net::MockRead(io_mode, reinterpret_cast<const char*>(data),
+ read_size, ++last_sequence_number));
+
+ data += read_size;
+ size -= read_size;
+ }
+
+ // Server closes the socket.
+ reads.push_back(net::MockRead(close_socket_io_mode,
+ net::ERR_CONNECTION_CLOSED,
+ ++last_sequence_number));
+ net::SequencedSocketData socket_data(reads.data(), reads.size(), writes,
+ arraysize(writes));
+ socket_data.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK));
+
+ scoped_ptr<net::MockTCPClientSocket> socket(
+ new net::MockTCPClientSocket(net::AddressList(), nullptr, &socket_data));
+
+ net::TestCompletionCallback callback;
+ CHECK_EQ(net::OK, socket->Connect(callback.callback()));
+
+ net::ClientSocketHandle socket_handle;
+ socket_handle.SetSocket(std::move(socket));
+
+ net::HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("http://localhost/");
+
+ scoped_refptr<net::GrowableIOBuffer> read_buffer(new net::GrowableIOBuffer());
+ // Use a NetLog that listens to events, to get coverage of logging
+ // callbacks.
+ net::BoundTestNetLog net_log;
+ net::HttpStreamParser parser(&socket_handle, &request_info, read_buffer.get(),
+ net_log.bound());
+
+ net::HttpResponseInfo response_info;
+ int result =
+ parser.SendRequest("GET / HTTP/1.1\r\n", net::HttpRequestHeaders(),
+ &response_info, callback.callback());
+ CHECK_EQ(net::OK, callback.GetResult(result));
+
+ result = parser.ReadResponseHeaders(callback.callback());
+ result = callback.GetResult(result);
+
+ if (result < 0)
+ return 0;
+
+ while (true) {
+ // 64 exactly matches the maximum amount of data returned by a single
+ // MockRead, as created above.
+ scoped_refptr<net::IOBufferWithSize> io_buffer(
+ new net::IOBufferWithSize(64));
+ result = parser.ReadResponseBody(io_buffer.get(), io_buffer->size(),
+ callback.callback());
+
+ // Releasing the pointer to IOBuffer immediately is more likely to lead to a
+ // use-after-free.
+ io_buffer = nullptr;
+
+ if (callback.GetResult(result) <= 0)
+ break;
+ }
+
+ return 0;
+}
diff --git a/chromium/net/http/http_stream_parser_unittest.cc b/chromium/net/http/http_stream_parser_unittest.cc
index 79364264138..1fa10c9c3ba 100644
--- a/chromium/net/http/http_stream_parser_unittest.cc
+++ b/chromium/net/http/http_stream_parser_unittest.cc
@@ -466,7 +466,7 @@ TEST(HttpStreamParser, AsyncSingleChunkAndAsyncSocket) {
// Attempt to read the response status and the response headers.
ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback()));
- ASSERT_GT(callback.WaitForResult(), 0);
+ ASSERT_EQ(OK, callback.WaitForResult());
// Finally, attempt to read the response body.
scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize));
@@ -536,7 +536,7 @@ TEST(HttpStreamParser, SyncSingleChunkAndAsyncSocket) {
// Attempt to read the response status and the response headers.
ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback()));
- ASSERT_GT(callback.WaitForResult(), 0);
+ ASSERT_EQ(OK, callback.WaitForResult());
// Finally, attempt to read the response body.
scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize));
@@ -629,7 +629,7 @@ TEST(HttpStreamParser, AsyncChunkAndAsyncSocketWithMultipleChunks) {
// Attempt to read the response status and the response headers.
ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback()));
- ASSERT_GT(callback.WaitForResult(), 0);
+ ASSERT_EQ(OK, callback.WaitForResult());
// Finally, attempt to read the response body.
scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize));
@@ -699,7 +699,7 @@ TEST(HttpStreamParser, AsyncEmptyChunkedUpload) {
// Attempt to read the response status and the response headers.
ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback()));
- ASSERT_GT(callback.WaitForResult(), 0);
+ ASSERT_EQ(OK, callback.WaitForResult());
// Finally, attempt to read the response body.
scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize));
@@ -768,7 +768,7 @@ TEST(HttpStreamParser, SyncEmptyChunkedUpload) {
// Attempt to read the response status and the response headers.
ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback()));
- ASSERT_GT(callback.WaitForResult(), 0);
+ ASSERT_EQ(OK, callback.WaitForResult());
// Finally, attempt to read the response body.
scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize));
diff --git a/chromium/net/http/http_transaction_test_util.cc b/chromium/net/http/http_transaction_test_util.cc
index 4a97ae618e9..2bbe2e9b225 100644
--- a/chromium/net/http/http_transaction_test_util.cc
+++ b/chromium/net/http/http_transaction_test_util.cc
@@ -390,12 +390,7 @@ bool MockNetworkTransaction::GetLoadTimingInfo(
}
bool MockNetworkTransaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
- IPAddressNumber number;
- number.push_back(127);
- number.push_back(0);
- number.push_back(0);
- number.push_back(1);
- *endpoint = IPEndPoint(number, 80);
+ *endpoint = IPEndPoint(IPAddress(127, 0, 0, 1), 80);
return true;
}
diff --git a/chromium/net/http/http_transaction_test_util.h b/chromium/net/http/http_transaction_test_util.h
index 54e7c522c74..3a9532ed432 100644
--- a/chromium/net/http/http_transaction_test_util.h
+++ b/chromium/net/http/http_transaction_test_util.h
@@ -133,6 +133,7 @@ class TestTransactionConsumer {
const HttpResponseInfo* response_info() const {
return trans_->GetResponseInfo();
}
+ const HttpTransaction* transaction() const { return trans_.get(); }
const std::string& content() const { return content_; }
private:
diff --git a/chromium/net/http/http_util.cc b/chromium/net/http/http_util.cc
index 08382d9a18a..932f8386dad 100644
--- a/chromium/net/http/http_util.cc
+++ b/chromium/net/http/http_util.cc
@@ -16,6 +16,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
+#include "net/base/url_util.h"
namespace net {
@@ -41,6 +42,14 @@ static size_t FindStringEnd(const std::string& line, size_t start, char delim) {
// HttpUtil -------------------------------------------------------------------
// static
+std::string HttpUtil::SpecForRequest(const GURL& url) {
+ // We may get ftp scheme when fetching ftp resources through proxy.
+ DCHECK(url.is_valid() && (url.SchemeIsHTTPOrHTTPS() || url.SchemeIs("ftp") ||
+ url.SchemeIsWSOrWSS()));
+ return SimplifyUrlForRequest(url).spec();
+}
+
+// static
void HttpUtil::ParseContentType(const std::string& content_type_str,
std::string* mime_type,
std::string* charset,
@@ -729,6 +738,9 @@ bool HttpUtil::HasStrongValidators(HttpVersion version,
const std::string& etag_header,
const std::string& last_modified_header,
const std::string& date_header) {
+ if (!HasValidators(version, etag_header, last_modified_header))
+ return false;
+
if (version < HttpVersion(1, 1))
return false;
@@ -752,9 +764,27 @@ bool HttpUtil::HasStrongValidators(HttpVersion version,
if (!base::Time::FromString(date_header.c_str(), &date))
return false;
+ // Last-Modified is implicitly weak unless it is at least 60 seconds before
+ // the Date value.
return ((date - last_modified).InSeconds() >= 60);
}
+bool HttpUtil::HasValidators(HttpVersion version,
+ const std::string& etag_header,
+ const std::string& last_modified_header) {
+ if (version < HttpVersion(1, 0))
+ return false;
+
+ base::Time last_modified;
+ if (base::Time::FromString(last_modified_header.c_str(), &last_modified))
+ return true;
+
+ // It is OK to consider an empty string in etag_header to be a missing header
+ // since valid ETags are always quoted-strings (see RFC 2616 3.11) and thus
+ // empty ETags aren't empty strings (i.e., an empty ETag might be "\"\"").
+ return version >= HttpVersion(1, 1) && !etag_header.empty();
+}
+
// Functions for histogram initialization. The code 0 is put in the map to
// track status codes that are invalid.
// TODO(gavinp): Greatly prune the collected codes once we learn which
@@ -858,6 +888,8 @@ HttpUtil::ValuesIterator::ValuesIterator(
values_.set_quote_chars("\'\"");
}
+HttpUtil::ValuesIterator::ValuesIterator(const ValuesIterator& other) = default;
+
HttpUtil::ValuesIterator::~ValuesIterator() {
}
@@ -894,6 +926,9 @@ HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
char delimiter)
: NameValuePairsIterator(begin, end, delimiter, VALUES_NOT_OPTIONAL) {}
+HttpUtil::NameValuePairsIterator::NameValuePairsIterator(
+ const NameValuePairsIterator& other) = default;
+
HttpUtil::NameValuePairsIterator::~NameValuePairsIterator() {}
// We expect properties to be formatted as one of:
diff --git a/chromium/net/http/http_util.h b/chromium/net/http/http_util.h
index 13209b8f421..458a7187441 100644
--- a/chromium/net/http/http_util.h
+++ b/chromium/net/http/http_util.h
@@ -205,11 +205,20 @@ class NET_EXPORT HttpUtil {
// 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.
static bool HasStrongValidators(HttpVersion version,
const std::string& etag_header,
const std::string& last_modified_header,
const std::string& date_header);
+ // Returns true if this response has any validator (either a Last-Modified or
+ // an ETag) regardless of whether it is strong or weak. See section 13.3.3 of
+ // RFC 2616.
+ // An empty string should be passed for missing headers.
+ static bool HasValidators(HttpVersion version,
+ const std::string& etag_header,
+ const std::string& last_modified_header);
+
// Gets a vector of common HTTP status codes for histograms of status
// codes. Currently returns everything in the range [100, 600), plus 0
// (for invalid responses/status codes).
@@ -291,6 +300,7 @@ class NET_EXPORT HttpUtil {
ValuesIterator(std::string::const_iterator values_begin,
std::string::const_iterator values_end,
char delimiter);
+ ValuesIterator(const ValuesIterator& other);
~ValuesIterator();
// Advances the iterator to the next value, if any. Returns true if there
@@ -338,6 +348,8 @@ class NET_EXPORT HttpUtil {
std::string::const_iterator end,
char delimiter);
+ NameValuePairsIterator(const NameValuePairsIterator& other);
+
~NameValuePairsIterator();
// Advances the iterator to the next pair, if any. Returns true if there
diff --git a/chromium/net/http/http_util_icu.cc b/chromium/net/http/http_util_icu.cc
deleted file mode 100644
index 9ee7e98c02c..00000000000
--- a/chromium/net/http/http_util_icu.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// The rules for parsing content-types were borrowed from Firefox:
-// http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834
-
-#include "net/http/http_util.h"
-
-#include "base/logging.h"
-#include "net/base/net_util.h"
-
-namespace net {
-
-// static
-std::string HttpUtil::SpecForRequest(const GURL& url) {
- // We may get ftp scheme when fetching ftp resources through proxy.
- DCHECK(url.is_valid() && (url.SchemeIsHTTPOrHTTPS() || url.SchemeIs("ftp") ||
- url.SchemeIsWSOrWSS()));
- return SimplifyUrlForRequest(url).spec();
-}
-
-} // namespace net
diff --git a/chromium/net/http/http_util_unittest.cc b/chromium/net/http/http_util_unittest.cc
index e83f6b99163..2b456605d70 100644
--- a/chromium/net/http/http_util_unittest.cc
+++ b/chromium/net/http/http_util_unittest.cc
@@ -1200,4 +1200,63 @@ TEST(HttpUtilTest, IsValidHeaderValueRFC7230) {
EXPECT_TRUE(HttpUtil::IsValidHeaderValueRFC7230("q\x80q"));
}
+TEST(HttpUtilTest, HasValidators) {
+ const char* const kMissing = "";
+ const char* const kEtagEmpty = "\"\"";
+ const char* const kEtagStrong = "\"strong\"";
+ const char* const kEtagWeak = "W/\"weak\"";
+ const char* const kLastModified = "Tue, 15 Nov 1994 12:45:26 GMT";
+ const char* const kLastModifiedInvalid = "invalid";
+
+ const HttpVersion v0_9 = HttpVersion(0, 9);
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kMissing, kMissing));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagStrong, kMissing));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagWeak, kMissing));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagEmpty, kMissing));
+
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kMissing, kLastModified));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagStrong, kLastModified));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagWeak, kLastModified));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagEmpty, kLastModified));
+
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kMissing, kLastModifiedInvalid));
+ EXPECT_FALSE(
+ HttpUtil::HasValidators(v0_9, kEtagStrong, kLastModifiedInvalid));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagWeak, kLastModifiedInvalid));
+ EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagEmpty, kLastModifiedInvalid));
+
+ const HttpVersion v1_0 = HttpVersion(1, 0);
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kMissing, kMissing));
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagStrong, kMissing));
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagWeak, kMissing));
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagEmpty, kMissing));
+
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kMissing, kLastModified));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kEtagStrong, kLastModified));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kEtagWeak, kLastModified));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kEtagEmpty, kLastModified));
+
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kMissing, kLastModifiedInvalid));
+ EXPECT_FALSE(
+ HttpUtil::HasValidators(v1_0, kEtagStrong, kLastModifiedInvalid));
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagWeak, kLastModifiedInvalid));
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagEmpty, kLastModifiedInvalid));
+
+ const HttpVersion v1_1 = HttpVersion(1, 1);
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_1, kMissing, kMissing));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagStrong, kMissing));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagWeak, kMissing));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kMissing));
+
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kMissing, kLastModified));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagStrong, kLastModified));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagWeak, kLastModified));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kLastModified));
+
+ EXPECT_FALSE(HttpUtil::HasValidators(v1_1, kMissing, kLastModifiedInvalid));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagStrong, kLastModifiedInvalid));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagWeak, kLastModifiedInvalid));
+ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kLastModifiedInvalid));
+}
+
} // namespace net
diff --git a/chromium/net/http/http_vary_data.cc b/chromium/net/http/http_vary_data.cc
index 9938d290a31..6b3a02a9214 100644
--- a/chromium/net/http/http_vary_data.cc
+++ b/chromium/net/http/http_vary_data.cc
@@ -32,7 +32,7 @@ bool HttpVaryData::Init(const HttpRequestInfo& request_info,
// If the Vary header contains '*' then we should not construct any vary data
// since it is all usurped by a '*'. See section 13.6 of RFC 2616.
//
- void* iter = NULL;
+ size_t iter = 0;
std::string name = "vary", request_header;
while (response_headers.EnumerateHeader(&iter, name, &request_header)) {
if (request_header == "*")
diff --git a/chromium/net/http/mock_gssapi_library_posix.cc b/chromium/net/http/mock_gssapi_library_posix.cc
index b4d651461ec..ce21159a034 100644
--- a/chromium/net/http/mock_gssapi_library_posix.cc
+++ b/chromium/net/http/mock_gssapi_library_posix.cc
@@ -226,6 +226,9 @@ MockGSSAPILibrary::SecurityContextQuery::SecurityContextQuery(
}
}
+MockGSSAPILibrary::SecurityContextQuery::SecurityContextQuery(
+ const SecurityContextQuery& other) = default;
+
MockGSSAPILibrary::SecurityContextQuery::~SecurityContextQuery() {}
MockGSSAPILibrary::MockGSSAPILibrary() {
diff --git a/chromium/net/http/mock_gssapi_library_posix.h b/chromium/net/http/mock_gssapi_library_posix.h
index 3d5f248a035..07f2542805b 100644
--- a/chromium/net/http/mock_gssapi_library_posix.h
+++ b/chromium/net/http/mock_gssapi_library_posix.h
@@ -52,6 +52,7 @@ class MockGSSAPILibrary : public GSSAPILibrary {
const test::GssContextMockImpl& context_info,
const char* expected_input_token,
const char* output_token);
+ SecurityContextQuery(const SecurityContextQuery& other);
~SecurityContextQuery();
std::string expected_package;
diff --git a/chromium/net/http/proxy_client_socket.cc b/chromium/net/http/proxy_client_socket.cc
index b0dd40be47d..ffdbec86460 100644
--- a/chromium/net/http/proxy_client_socket.cc
+++ b/chromium/net/http/proxy_client_socket.cc
@@ -8,7 +8,6 @@
#include "base/strings/stringprintf.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/http/http_auth_controller.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_headers.h"
@@ -22,7 +21,7 @@ namespace {
void CopyHeaderValues(scoped_refptr<HttpResponseHeaders> source,
scoped_refptr<HttpResponseHeaders> dest,
const std::string& header_name) {
- void* iter = NULL;
+ size_t iter = 0;
std::string header_value;
while (source->EnumerateHeader(&iter, header_name, &header_value))
@@ -59,7 +58,8 @@ int ProxyClientSocket::HandleProxyAuthChallenge(HttpAuthController* auth,
HttpResponseInfo* response,
const BoundNetLog& net_log) {
DCHECK(response->headers.get());
- int rv = auth->HandleAuthChallenge(response->headers, false, true, net_log);
+ int rv = auth->HandleAuthChallenge(response->headers, response->ssl_info,
+ false, true, net_log);
response->auth_challenge = auth->auth_info();
if (rv == OK)
return ERR_PROXY_AUTH_REQUESTED;
diff --git a/chromium/net/http/proxy_connect_redirect_http_stream.cc b/chromium/net/http/proxy_connect_redirect_http_stream.cc
index 2b26b08888f..45d742450e5 100644
--- a/chromium/net/http/proxy_connect_redirect_http_stream.cc
+++ b/chromium/net/http/proxy_connect_redirect_http_stream.cc
@@ -102,6 +102,13 @@ bool ProxyConnectRedirectHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
return false;
}
+Error ProxyConnectRedirectHttpStream::GetSignedEKMForTokenBinding(
+ crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ NOTREACHED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
void ProxyConnectRedirectHttpStream::Drain(HttpNetworkSession* session) {
NOTREACHED();
}
diff --git a/chromium/net/http/proxy_connect_redirect_http_stream.h b/chromium/net/http/proxy_connect_redirect_http_stream.h
index af3940c2173..36e595c585b 100644
--- a/chromium/net/http/proxy_connect_redirect_http_stream.h
+++ b/chromium/net/http/proxy_connect_redirect_http_stream.h
@@ -57,6 +57,8 @@ class ProxyConnectRedirectHttpStream : public HttpStream {
void GetSSLInfo(SSLInfo* ssl_info) override;
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override;
void Drain(HttpNetworkSession* session) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
diff --git a/chromium/net/http/transport_security_persister.cc b/chromium/net/http/transport_security_persister.cc
index a07e632ab5d..de5d831b034 100644
--- a/chromium/net/http/transport_security_persister.cc
+++ b/chromium/net/http/transport_security_persister.cc
@@ -13,6 +13,7 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/location.h"
+#include "base/memory/scoped_ptr.h"
#include "base/sequenced_task_runner.h"
#include "base/task_runner_util.h"
#include "base/thread_task_runner_handle.h"
diff --git a/chromium/net/http/transport_security_persister_unittest.cc b/chromium/net/http/transport_security_persister_unittest.cc
index 0799f5820bd..dd5ae5ce117 100644
--- a/chromium/net/http/transport_security_persister_unittest.cc
+++ b/chromium/net/http/transport_security_persister_unittest.cc
@@ -11,6 +11,7 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "net/http/transport_security_state.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/http/transport_security_state.cc b/chromium/net/http/transport_security_state.cc
index 8eb29434f86..1a91f8a2c54 100644
--- a/chromium/net/http/transport_security_state.cc
+++ b/chromium/net/http/transport_security_state.cc
@@ -22,6 +22,7 @@
#include "base/values.h"
#include "crypto/sha2.h"
#include "net/base/host_port_pair.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/x509_cert_types.h"
#include "net/cert/x509_certificate.h"
#include "net/dns/dns_util.h"
@@ -39,6 +40,11 @@ const size_t kMaxHPKPReportCacheEntries = 50;
const int kTimeToRememberHPKPReportsMins = 60;
const size_t kReportCacheKeyLength = 16;
+void RecordUMAForHPKPReportFailure(const GURL& report_uri, int net_error) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.PublicKeyPinReportSendingFailure",
+ net_error);
+}
+
std::string TimeToISO8601(const base::Time& t) {
base::Time::Exploded exploded;
t.UTCExplode(&exploded);
@@ -596,6 +602,7 @@ TransportSecurityState::TransportSecurityState()
report_sender_(nullptr),
enable_static_pins_(true),
enable_static_expect_ct_(true),
+ expect_ct_reporter_(nullptr),
sent_reports_cache_(kMaxHPKPReportCacheEntries) {
// Static pinning is only enabled for official builds to make sure that
// others don't end up with pins that cannot be easily updated.
@@ -687,6 +694,14 @@ void TransportSecurityState::SetReportSender(
TransportSecurityState::ReportSender* report_sender) {
DCHECK(CalledOnValidThread());
report_sender_ = report_sender;
+ if (report_sender_)
+ report_sender_->SetErrorCallback(base::Bind(RecordUMAForHPKPReportFailure));
+}
+
+void TransportSecurityState::SetExpectCTReporter(
+ ExpectCTReporter* expect_ct_reporter) {
+ DCHECK(CalledOnValidThread());
+ expect_ct_reporter_ = expect_ct_reporter;
}
void TransportSecurityState::AddHSTSInternal(
@@ -820,6 +835,27 @@ bool TransportSecurityState::CheckPinsAndMaybeSendReport(
return false;
}
+bool TransportSecurityState::GetStaticExpectCTState(
+ const std::string& host,
+ ExpectCTState* expect_ct_state) const {
+ DCHECK(CalledOnValidThread());
+
+ if (!IsBuildTimely())
+ return false;
+
+ PreloadResult result;
+ if (!DecodeHSTSPreload(host, &result))
+ return false;
+
+ if (!enable_static_expect_ct_ || !result.expect_ct)
+ return false;
+
+ expect_ct_state->domain = host.substr(result.hostname_offset);
+ expect_ct_state->report_uri =
+ GURL(kExpectCTReportURIs[result.expect_ct_report_uri_id]);
+ return true;
+}
+
bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) {
DCHECK(CalledOnValidThread());
@@ -993,6 +1029,36 @@ bool TransportSecurityState::ProcessHPKPReportOnlyHeader(
return true;
}
+void TransportSecurityState::ProcessExpectCTHeader(
+ const std::string& value,
+ const HostPortPair& host_port_pair,
+ const SSLInfo& ssl_info) {
+ DCHECK(CalledOnValidThread());
+
+ if (!expect_ct_reporter_)
+ return;
+
+ if (value != "preload")
+ return;
+
+ if (!IsBuildTimely())
+ return;
+
+ if (!ssl_info.is_issued_by_known_root ||
+ !ssl_info.ct_compliance_details_available ||
+ ssl_info.ct_cert_policy_compliance ==
+ ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS) {
+ return;
+ }
+
+ ExpectCTState state;
+ if (!GetStaticExpectCTState(host_port_pair.host(), &state))
+ return;
+
+ expect_ct_reporter_->OnExpectCTFailed(host_port_pair, state.report_uri,
+ ssl_info);
+}
+
// static
void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) {
PreloadResult result;
@@ -1009,18 +1075,9 @@ void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) {
// static
bool TransportSecurityState::IsBuildTimely() {
- // If the build metadata aren't embedded in the binary then we can't use the
- // build time to determine if the build is timely, return true by default. If
- // we're building an official build then keep using the build time, even if
- // it's invalid it'd be a date in the past and this function will return
- // false.
-#if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD)
- return true;
-#else
const base::Time build_time = base::GetBuildTime();
// We consider built-in information to be timely for 10 weeks.
return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
-#endif
}
bool TransportSecurityState::CheckPublicKeyPinsImpl(
@@ -1119,27 +1176,6 @@ bool TransportSecurityState::IsGooglePinnedHost(const std::string& host) const {
return kPinsets[result.pinset_id].accepted_pins == kGoogleAcceptableCerts;
}
-bool TransportSecurityState::GetStaticExpectCTState(
- const std::string& host,
- ExpectCTState* expect_ct_state) const {
- DCHECK(CalledOnValidThread());
-
- if (!IsBuildTimely())
- return false;
-
- PreloadResult result;
- if (!DecodeHSTSPreload(host, &result))
- return false;
-
- if (!enable_static_expect_ct_ || !result.expect_ct)
- return false;
-
- expect_ct_state->domain = host.substr(result.hostname_offset);
- expect_ct_state->report_uri =
- GURL(kExpectCTReportURIs[result.expect_ct_report_uri_id]);
- return true;
-}
-
bool TransportSecurityState::GetDynamicSTSState(const std::string& host,
STSState* result) {
DCHECK(CalledOnValidThread());
@@ -1265,6 +1301,8 @@ TransportSecurityState::STSStateIterator::~STSStateIterator() {
TransportSecurityState::PKPState::PKPState() : include_subdomains(false) {
}
+TransportSecurityState::PKPState::PKPState(const PKPState& other) = default;
+
TransportSecurityState::PKPState::~PKPState() {
}
diff --git a/chromium/net/http/transport_security_state.h b/chromium/net/http/transport_security_state.h
index a4c52e7ecfe..84b229bbd95 100644
--- a/chromium/net/http/transport_security_state.h
+++ b/chromium/net/http/transport_security_state.h
@@ -12,6 +12,7 @@
#include <utility>
#include <vector>
+#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/threading/non_thread_safe.h"
@@ -110,6 +111,7 @@ class NET_EXPORT TransportSecurityState
class NET_EXPORT PKPState {
public:
PKPState();
+ PKPState(const PKPState& other);
~PKPState();
// The absolute time (UTC) when the |spki_hashes| (and other state) were
@@ -202,10 +204,30 @@ class NET_EXPORT TransportSecurityState
// Sends the given serialized |report| to |report_uri|.
virtual void Send(const GURL& report_uri, const std::string& report) = 0;
+ // Sets a callback to be called when report sending fails.
+ virtual void SetErrorCallback(
+ const base::Callback<void(const GURL&, int)>& error_callback) = 0;
+
protected:
virtual ~ReportSender() {}
};
+ // An interface for building and asynchronously sending reports when a
+ // site expects valid Certificate Transparency information but it
+ // wasn't supplied.
+ class NET_EXPORT ExpectCTReporter {
+ public:
+ // Called when the host in |host_port_pair| has opted in to have
+ // reports about Expect CT policy violations sent to |report_uri|,
+ // and such a violation has occurred.
+ virtual void OnExpectCTFailed(const net::HostPortPair& host_port_pair,
+ const GURL& report_uri,
+ const net::SSLInfo& ssl_info) = 0;
+
+ protected:
+ virtual ~ExpectCTReporter() {}
+ };
+
// Indicates whether or not a public key pin check should send a
// report if a violation is detected.
enum PublicKeyPinReportStatus { ENABLE_PIN_REPORTS, DISABLE_PIN_REPORTS };
@@ -237,6 +259,8 @@ class NET_EXPORT TransportSecurityState
void SetReportSender(ReportSender* report_sender);
+ void SetExpectCTReporter(ExpectCTReporter* expect_ct_reporter);
+
// Clears all dynamic data (e.g. HSTS and HPKP data).
//
// Does NOT persist changes using the Delegate, as this function is only
@@ -288,11 +312,6 @@ class NET_EXPORT TransportSecurityState
// deployed.
bool IsGooglePinnedHost(const std::string& host) const;
- // Returns true and updates |*expect_ct_result| iff there is a static
- // (built-in) state for |host| with expect_ct=true.
- bool GetStaticExpectCTState(const std::string& host,
- ExpectCTState* expect_ct_result) const;
-
// Returns true and updates |*result| iff |host| has HSTS (respectively, HPKP)
// state. If multiple HSTS (respectively, HPKP) entries match |host|, the
// most specific match determines the HSTS (respectively, HPKP) return value.
@@ -336,6 +355,18 @@ class NET_EXPORT TransportSecurityState
const HostPortPair& host_port_pair,
const SSLInfo& ssl_info);
+ // Parses |value| as a Expect CT header value and sends an Expect CT
+ // report for |host_port_pair| if the following conditions are true:
+ // 1. The header value is "preload", indicating that the site wants to
+ // be opted in to Expect CT.
+ // 2. The given host is present on the Expect CT preload list with a
+ // valid report-uri, and the build is timely (i.e. preload list is fresh).
+ // 3. |ssl_info| indicates that the connection violated the Expect CT policy.
+ // 4. An Expect CT reporter has been provided with SetExpectCTReporter().
+ void ProcessExpectCTHeader(const std::string& value,
+ const HostPortPair& host_port_pair,
+ const SSLInfo& ssl_info);
+
// The maximum number of seconds for which we'll cache an HSTS request.
static const long int kMaxHSTSAgeSecs;
@@ -344,6 +375,7 @@ class NET_EXPORT TransportSecurityState
FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, UpdateDynamicPKPOnly);
FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, UpdateDynamicPKPMaxAge0);
FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, NoClobberPins);
+ FRIEND_TEST_ALL_PREFIXES(URLRequestTestHTTP, ExpectCTHeader);
typedef std::map<std::string, STSState> STSStateMap;
typedef std::map<std::string, PKPState> PKPStateMap;
@@ -413,6 +445,11 @@ class NET_EXPORT TransportSecurityState
const TransportSecurityState::PublicKeyPinReportStatus report_status,
std::string* failure_log);
+ // Returns true and updates |*expect_ct_result| iff there is a static
+ // (built-in) state for |host| with expect_ct=true.
+ bool GetStaticExpectCTState(const std::string& host,
+ ExpectCTState* expect_ct_result) const;
+
// The sets of hosts that have enabled TransportSecurity. |domain| will always
// be empty for a STSState or PKPState in these maps; the domain
// comes from the map keys instead. In addition, |upgrade_mode| in the
@@ -431,6 +468,8 @@ class NET_EXPORT TransportSecurityState
// True if static expect-CT state should be used.
bool enable_static_expect_ct_;
+ ExpectCTReporter* expect_ct_reporter_;
+
// Keeps track of reports that have been sent recently for
// rate-limiting.
ExpiringCache<std::string, bool, base::TimeTicks, std::less<base::TimeTicks>>
diff --git a/chromium/net/http/transport_security_state_static.h b/chromium/net/http/transport_security_state_static.h
index 22c734393ef..3c42d8d6577 100644
--- a/chromium/net/http/transport_security_state_static.h
+++ b/chromium/net/http/transport_security_state_static.h
@@ -2,7 +2,8 @@
// 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.
+// This file is automatically generated by
+// transport_security_state_static_generate.go.
// You can find it at https://github.com/agl/transport-security-state-generate.
#ifndef NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
@@ -562,173 +563,175 @@ static const char* const kExpectCTReportURIs[] = {
// kNoRejectedPublicKeys is a placeholder for when no public keys are rejected.
static const char* const kNoRejectedPublicKeys[] = {
- NULL,
+ NULL,
};
// 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,
- NULL,
+ kSPKIHash_TestSPKI,
+ NULL,
};
static const char* const kGoogleAcceptableCerts[] = {
- kSPKIHash_GoogleBackup2048,
- kSPKIHash_GoogleG2,
- kSPKIHash_GeoTrustGlobal,
- NULL,
+ kSPKIHash_GoogleBackup2048,
+ kSPKIHash_GoogleG2,
+ kSPKIHash_GeoTrustGlobal,
+ 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,
- kSPKIHash_LetsEncryptAuthorityX1,
- kSPKIHash_LetsEncryptAuthorityX2,
- NULL,
+ kSPKIHash_RapidSSL,
+ kSPKIHash_DigiCertEVRoot,
+ kSPKIHash_Tor1,
+ kSPKIHash_Tor2,
+ kSPKIHash_Tor3,
+ kSPKIHash_LetsEncryptAuthorityX1,
+ kSPKIHash_LetsEncryptAuthorityX2,
+ 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,
- NULL,
+ 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,
+ NULL,
};
+static const char kTwitterComReportURI[] = "http://l.twimg.com/i/hpkp_report";
static const char* const kTwitterCDNAcceptableCerts[] = {
- 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_Entrust_2048,
- kSPKIHash_Entrust_EV,
- kSPKIHash_Entrust_G2,
- kSPKIHash_Entrust_SSL,
- kSPKIHash_AAACertificateServices,
- kSPKIHash_AddTrustClass1CARoot,
- kSPKIHash_AddTrustExternalCARoot,
- kSPKIHash_AddTrustPublicCARoot,
- kSPKIHash_AddTrustQualifiedCARoot,
- kSPKIHash_COMODOCertificationAuthority,
- kSPKIHash_SecureCertificateServices,
- kSPKIHash_TrustedCertificateServices,
- kSPKIHash_UTNDATACorpSGC,
- kSPKIHash_UTNUSERFirstClientAuthenticationandEmail,
- kSPKIHash_UTNUSERFirstHardware,
- kSPKIHash_UTNUSERFirstObject,
- kSPKIHash_GTECyberTrustGlobalRoot,
- kSPKIHash_BaltimoreCyberTrustRoot,
- kSPKIHash_GlobalSignRootCA,
- kSPKIHash_GlobalSignRootCA_R2,
- kSPKIHash_GlobalSignRootCA_R3,
- NULL,
+ 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_Entrust_2048,
+ kSPKIHash_Entrust_EV,
+ kSPKIHash_Entrust_G2,
+ kSPKIHash_Entrust_SSL,
+ kSPKIHash_AAACertificateServices,
+ kSPKIHash_AddTrustClass1CARoot,
+ kSPKIHash_AddTrustExternalCARoot,
+ kSPKIHash_AddTrustPublicCARoot,
+ kSPKIHash_AddTrustQualifiedCARoot,
+ kSPKIHash_COMODOCertificationAuthority,
+ kSPKIHash_SecureCertificateServices,
+ kSPKIHash_TrustedCertificateServices,
+ kSPKIHash_UTNDATACorpSGC,
+ kSPKIHash_UTNUSERFirstClientAuthenticationandEmail,
+ kSPKIHash_UTNUSERFirstHardware,
+ kSPKIHash_UTNUSERFirstObject,
+ kSPKIHash_GTECyberTrustGlobalRoot,
+ kSPKIHash_BaltimoreCyberTrustRoot,
+ kSPKIHash_GlobalSignRootCA,
+ kSPKIHash_GlobalSignRootCA_R2,
+ kSPKIHash_GlobalSignRootCA_R3,
+ 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,
- 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,
+ 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,
+ kSPKIHash_SymantecClass3EVG3,
+ kSPKIHash_DigiCertECCSecureServerCA,
+ kSPKIHash_DigiCertEVRoot,
+ kSPKIHash_FacebookBackup,
+ NULL,
};
static const char* const kSpideroakAcceptableCerts[] = {
- kSPKIHash_GeoTrustGlobal,
- kSPKIHash_DigiCertEVRoot,
- kSPKIHash_SpiderOak2,
- kSPKIHash_SpiderOak3,
- NULL,
+ kSPKIHash_GeoTrustGlobal,
+ kSPKIHash_DigiCertEVRoot,
+ kSPKIHash_SpiderOak2,
+ kSPKIHash_SpiderOak3,
+ NULL,
};
static const char* const kYahooAcceptableCerts[] = {
- kSPKIHash_VeriSignClass2_G2,
- kSPKIHash_VeriSignClass2_G3,
- kSPKIHash_VeriSignClass3_G3,
- kSPKIHash_VeriSignClass3_G4,
- kSPKIHash_VeriSignClass3_G5,
- kSPKIHash_VeriSignUniversal,
- kSPKIHash_GeoTrustGlobal,
- kSPKIHash_GeoTrustPrimary,
- kSPKIHash_GeoTrustPrimary_G2,
- kSPKIHash_GeoTrustPrimary_G3,
- kSPKIHash_GeoTrustUniversal,
- kSPKIHash_DigiCertGlobalRoot,
- kSPKIHash_DigiCertEVRoot,
- kSPKIHash_YahooBackup1,
- kSPKIHash_YahooBackup2,
- NULL,
+ kSPKIHash_VeriSignClass2_G2,
+ kSPKIHash_VeriSignClass2_G3,
+ kSPKIHash_VeriSignClass3_G3,
+ kSPKIHash_VeriSignClass3_G4,
+ kSPKIHash_VeriSignClass3_G5,
+ kSPKIHash_VeriSignUniversal,
+ kSPKIHash_GeoTrustGlobal,
+ kSPKIHash_GeoTrustPrimary,
+ kSPKIHash_GeoTrustPrimary_G2,
+ kSPKIHash_GeoTrustPrimary_G3,
+ kSPKIHash_GeoTrustUniversal,
+ kSPKIHash_DigiCertGlobalRoot,
+ kSPKIHash_DigiCertEVRoot,
+ kSPKIHash_YahooBackup1,
+ kSPKIHash_YahooBackup2,
+ NULL,
};
struct Pinset {
- const char *const *const accepted_pins;
- const char *const *const rejected_pins;
- const char *const report_uri;
+ const char* const* const accepted_pins;
+ const char* const* const rejected_pins;
+ const char* const report_uri;
};
static const struct Pinset kPinsets[] = {
- {kTestAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
- {kGoogleAcceptableCerts, kNoRejectedPublicKeys, kGoogleReportURI},
- {kTorAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
- {kTwitterComAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
- {kTwitterCDNAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
- {kDropboxAcceptableCerts, kNoRejectedPublicKeys, kDropboxReportURI},
- {kFacebookAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
- {kSpideroakAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
- {kYahooAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
+ {kTestAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
+ {kGoogleAcceptableCerts, kNoRejectedPublicKeys, kGoogleReportURI},
+ {kTorAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
+ {kTwitterComAcceptableCerts, kNoRejectedPublicKeys, kTwitterComReportURI},
+ {kTwitterCDNAcceptableCerts, kNoRejectedPublicKeys, kTwitterCDNReportURI},
+ {kDropboxAcceptableCerts, kNoRejectedPublicKeys, kDropboxReportURI},
+ {kFacebookAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
+ {kSpideroakAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
+ {kYahooAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
};
// kHSTSHuffmanTree describes a Huffman tree. The nodes of the tree are pairs
@@ -737,4127 +740,8386 @@ 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[] = {
- 0xf5, 0xe4, 0x00, 0xf2, 0x01, 0x80, 0xf9, 0xe6, 0x03, 0xe7, 0xe9, 0x04,
- 0xb7, 0xb6, 0x06, 0xb1, 0xb0, 0xb3, 0x07, 0x08, 0x09, 0xea, 0xf8, 0x0a,
- 0x0b, 0xf7, 0xed, 0x0c, 0x0d, 0xef, 0x05, 0x0e, 0x02, 0x0f, 0xeb, 0xe2,
- 0xe3, 0x11, 0xe1, 0x12, 0x13, 0xff, 0xec, 0xf3, 0xe5, 0x15, 0xb9, 0xb5,
- 0xb8, 0x17, 0xb2, 0x18, 0xb4, 0xf1, 0x19, 0x1a, 0xfa, 0x1b, 0x1c, 0xf6,
- 0xad, 0xae, 0x1d, 0x1e, 0x1f, 0xee, 0xe8, 0xf0, 0xf4, 0x21, 0x20, 0x22,
- 0x16, 0x23, 0x14, 0x24, 0x10, 0x25,
+ 0xf0, 0xf5, 0xb4, 0xb2, 0xb7, 0xb9, 0xb6, 0x02, 0x03, 0xf1, 0x01, 0x04,
+ 0x05, 0xae, 0xf9, 0x06, 0x07, 0xe4, 0x00, 0x08, 0xf7, 0xe6, 0x0a, 0xed,
+ 0xf2, 0x0b, 0x09, 0x0c, 0xe9, 0xef, 0x80, 0x0e, 0x0d, 0x0f, 0xeb, 0xe2,
+ 0xe3, 0x11, 0xe1, 0x12, 0x13, 0xff, 0xb5, 0xb8, 0xb3, 0x15, 0xb1, 0xb0,
+ 0x16, 0x17, 0x18, 0xf8, 0xad, 0x19, 0xea, 0xfa, 0x1b, 0xf6, 0x1a, 0x1c,
+ 0xec, 0x1d, 0xe5, 0x1e, 0xe8, 0xe7, 0xf3, 0x20, 0xee, 0xf4, 0x21, 0x22,
+ 0x1f, 0x23, 0x14, 0x24, 0x10, 0x25,
};
static const uint8_t kPreloadedHSTSData[] = {
- 0xfe, 0xe7, 0x9a, 0x5b, 0xba, 0xcd, 0x11, 0x2a, 0xef, 0xc0, 0x72, 0xf4,
- 0x85, 0xac, 0xe5, 0xdf, 0x78, 0xe5, 0xff, 0xf4, 0x76, 0x24, 0x2e, 0xaf,
- 0xd2, 0x8c, 0xf1, 0xcb, 0x9f, 0x67, 0x2a, 0x47, 0xfa, 0x11, 0x84, 0x4f,
- 0xbf, 0xd8, 0xd8, 0xc7, 0xba, 0x87, 0x2f, 0xfe, 0x03, 0x3a, 0x39, 0xf7,
- 0x85, 0xfa, 0x72, 0xff, 0xfd, 0x21, 0x7f, 0x3b, 0x37, 0x01, 0x8e, 0xc4,
- 0x8e, 0x56, 0xd1, 0x2e, 0xa2, 0x25, 0xd9, 0xb3, 0x97, 0x9d, 0xd6, 0x68,
- 0x8b, 0x55, 0x23, 0xe2, 0xc2, 0x45, 0x8b, 0x5d, 0xad, 0x9c, 0xad, 0x1e,
- 0x2e, 0xcb, 0xae, 0xf7, 0x8e, 0x5f, 0xff, 0x3f, 0x70, 0x75, 0xac, 0xfa,
- 0x5e, 0x46, 0x1c, 0xa9, 0x1f, 0x30, 0x05, 0xee, 0x5c, 0x1c, 0xbf, 0xf0,
- 0x1d, 0x41, 0xc9, 0xb5, 0x0d, 0x9c, 0xb8, 0x5b, 0x39, 0x58, 0x7d, 0xbd,
- 0x16, 0x6d, 0x02, 0xff, 0xf4, 0xa3, 0x07, 0xc0, 0x70, 0xee, 0x15, 0x39,
- 0x7f, 0x04, 0x61, 0x6c, 0x01, 0xcb, 0xfa, 0x3e, 0x0e, 0x9e, 0x47, 0x2f,
- 0x08, 0x60, 0xe5, 0xc1, 0x09, 0xcb, 0xfe, 0x6c, 0x53, 0x68, 0x3f, 0x48,
- 0xe5, 0xc9, 0x39, 0xcb, 0xfe, 0xf0, 0x34, 0xfb, 0x7c, 0xe9, 0xca, 0x09,
- 0xe7, 0xa0, 0xbd, 0x62, 0x30, 0x10, 0x5d, 0xe1, 0x11, 0x7f, 0xf2, 0xf5,
- 0x0a, 0xc0, 0xfb, 0x85, 0x70, 0xa6, 0xa4, 0xe5, 0xff, 0x76, 0x35, 0x9d,
- 0x4f, 0x84, 0xe5, 0xfd, 0xd1, 0x03, 0xaa, 0xb3, 0x94, 0x13, 0xe6, 0x43,
- 0x8b, 0x87, 0x67, 0x2a, 0x11, 0xe7, 0x90, 0xbc, 0x12, 0x1b, 0xfe, 0x5a,
- 0x9e, 0x49, 0x37, 0x9d, 0x39, 0x7f, 0xe8, 0xef, 0x62, 0x5e, 0x55, 0x34,
- 0x72, 0xcd, 0x67, 0x2f, 0xb5, 0xbc, 0x6c, 0xe5, 0xf0, 0xc7, 0xca, 0x41,
- 0xb7, 0xc1, 0x4a, 0x9d, 0x15, 0xa2, 0xed, 0x7f, 0x96, 0x9b, 0xd6, 0xa2,
- 0x47, 0x2f, 0xff, 0xd9, 0xfe, 0xd3, 0xe6, 0xf1, 0x70, 0x20, 0x79, 0x1c,
- 0xbf, 0xfa, 0x30, 0x7d, 0xbf, 0x66, 0x37, 0xb3, 0x95, 0x09, 0xeb, 0xa4,
- 0x3a, 0x3a, 0x46, 0x26, 0x7e, 0x56, 0xbb, 0x3e, 0x29, 0x68, 0x29, 0x6f,
- 0xf4, 0x69, 0xff, 0x17, 0xbf, 0xde, 0xcd, 0x7e, 0xc4, 0xd9, 0x4e, 0x66,
- 0xa6, 0xfe, 0x97, 0x53, 0x8e, 0x4c, 0x72, 0xa0, 0xfd, 0x9d, 0x1a, 0xfe,
- 0xea, 0x2e, 0x18, 0x87, 0x2f, 0xf4, 0x7f, 0x3b, 0xca, 0x1a, 0xce, 0x58,
- 0x60, 0xf8, 0xc4, 0xb2, 0xdc, 0xda, 0x96, 0x50, 0x07, 0x0b, 0x0c, 0x44,
- 0x27, 0x27, 0x2e, 0xc8, 0xdc, 0x15, 0x84, 0x42, 0xe1, 0x1f, 0xf1, 0x7a,
- 0x24, 0xcc, 0x5b, 0xa2, 0xee, 0xc3, 0x6c, 0x63, 0x25, 0xdc, 0xa0, 0x96,
- 0x91, 0x89, 0xa9, 0x08, 0x3b, 0xff, 0xff, 0x9d, 0x9c, 0xd3, 0x5a, 0x06,
- 0xb5, 0x03, 0x8a, 0xa7, 0x7b, 0x8a, 0x1c, 0xbf, 0xfd, 0xc2, 0x95, 0x6d,
- 0xae, 0x70, 0xf0, 0xdc, 0xb9, 0x75, 0xa1, 0xcb, 0xe5, 0xbb, 0xac, 0xd1,
- 0x51, 0x2f, 0xce, 0x32, 0x46, 0x1c, 0xad, 0x1e, 0xa3, 0x0b, 0xaf, 0xbb,
- 0x9a, 0xc3, 0x97, 0x92, 0x6e, 0x03, 0x95, 0x07, 0x83, 0xd2, 0x1b, 0xf2,
- 0xdf, 0xb1, 0xd3, 0x97, 0xff, 0xf0, 0x05, 0xd5, 0xe5, 0xe5, 0x60, 0x65,
- 0x9d, 0x46, 0x1c, 0xbf, 0xff, 0x7f, 0x29, 0xf8, 0x54, 0x35, 0x73, 0xaf,
- 0x5c, 0xb9, 0x75, 0xa1, 0xcb, 0xff, 0xf8, 0x02, 0xea, 0xf2, 0xf2, 0xb0,
- 0x32, 0xce, 0xa3, 0x0e, 0x5f, 0x6b, 0x58, 0xd0, 0xe5, 0x31, 0x10, 0x2e,
- 0xbb, 0x7f, 0xfe, 0x79, 0x0c, 0x6f, 0x3e, 0x58, 0xbe, 0x7c, 0xb3, 0x96,
- 0xe7, 0x25, 0x64, 0x79, 0x0b, 0x85, 0xb1, 0xa1, 0x0b, 0x09, 0xfa, 0xbb,
- 0xb8, 0x76, 0xf1, 0x22, 0xbf, 0xf0, 0x71, 0x9c, 0xda, 0x60, 0xa7, 0x8e,
- 0x5e, 0xc6, 0xf0, 0xe5, 0xe0, 0x44, 0xe7, 0x2f, 0xec, 0x9c, 0x31, 0x81,
- 0x39, 0x7c, 0x1e, 0xa4, 0xc7, 0x2b, 0x0f, 0x41, 0xcb, 0x6f, 0x36, 0xfd,
- 0x39, 0x74, 0x04, 0xe5, 0x41, 0xb3, 0xe8, 0xed, 0xfe, 0x88, 0x41, 0x10,
- 0x35, 0x9c, 0xb9, 0xc0, 0x72, 0xfe, 0x79, 0xf4, 0xef, 0xe3, 0x97, 0xdd,
- 0x4e, 0xf3, 0xe1, 0x13, 0x72, 0x08, 0xe2, 0xad, 0xb3, 0x29, 0xf4, 0x81,
- 0xb3, 0x36, 0x82, 0xd7, 0xed, 0x2d, 0xdd, 0x66, 0x8a, 0xf5, 0x7e, 0x4e,
- 0x05, 0x82, 0x73, 0x97, 0x44, 0x8e, 0x5d, 0x1f, 0x9c, 0xbf, 0xa7, 0x51,
- 0xa3, 0x8f, 0xe7, 0x2f, 0xfc, 0xe3, 0xfe, 0x7a, 0x05, 0x3f, 0x39, 0x50,
- 0x7d, 0xed, 0x0c, 0xad, 0xcf, 0x13, 0x1f, 0xd1, 0xa3, 0x96, 0x7e, 0x2c,
- 0xa4, 0x21, 0xaf, 0xfe, 0xe6, 0xf2, 0xe7, 0x9a, 0x5b, 0xba, 0xcd, 0x12,
- 0x32, 0xff, 0xf7, 0x36, 0x3c, 0xb9, 0xe6, 0x96, 0xee, 0xb3, 0x44, 0xf0,
- 0xbf, 0xfd, 0xcd, 0x8f, 0x2e, 0x79, 0xa5, 0xbb, 0xac, 0xd1, 0x3f, 0xaf,
- 0xff, 0x73, 0x63, 0xcb, 0x9e, 0x69, 0x6e, 0xeb, 0x34, 0x50, 0xcb, 0xff,
- 0x98, 0xf2, 0xe7, 0x9a, 0x5b, 0xba, 0xcd, 0x14, 0x42, 0xff, 0xd2, 0xe6,
- 0x0d, 0xf2, 0x8d, 0xc4, 0x8e, 0x57, 0x34, 0x4a, 0xc2, 0x95, 0xff, 0xa6,
- 0x4e, 0xfd, 0x9e, 0x0e, 0x30, 0xe5, 0xf6, 0x7b, 0x3f, 0x39, 0x7e, 0x10,
- 0x3c, 0xb6, 0x72, 0xf0, 0xbf, 0x31, 0x3c, 0x9f, 0x11, 0x5f, 0xb4, 0xb7,
- 0x75, 0x9a, 0x29, 0x15, 0xff, 0xdd, 0xe2, 0xfa, 0xdb, 0xf7, 0x71, 0x39,
- 0xcb, 0xff, 0x9f, 0xed, 0xf5, 0xb8, 0xff, 0x92, 0x8c, 0x39, 0x7f, 0xd1,
- 0x28, 0xd4, 0xf1, 0xa9, 0xce, 0x5e, 0x79, 0x73, 0xc4, 0xc0, 0x1c, 0xd3,
- 0xf4, 0x71, 0x4b, 0xbf, 0xff, 0xb8, 0xf3, 0x51, 0x79, 0xe8, 0x1f, 0x6d,
- 0xc4, 0x18, 0x72, 0xff, 0xf4, 0xb9, 0xe9, 0xff, 0x7f, 0x26, 0xb1, 0x87,
- 0x2f, 0xfd, 0xff, 0x3d, 0x83, 0x5f, 0xf2, 0x0c, 0xc7, 0x2f, 0xe9, 0x67,
- 0x7a, 0xf2, 0x39, 0x7f, 0xff, 0x60, 0x7b, 0x0a, 0x73, 0xf0, 0xbf, 0xfb,
- 0xdc, 0x7e, 0x52, 0xdc, 0xe1, 0x5c, 0x4a, 0xe1, 0x12, 0xc8, 0xcc, 0xfa,
- 0x9e, 0xeb, 0xdf, 0xa6, 0x79, 0x21, 0xa1, 0x6d, 0xff, 0xf7, 0x63, 0xa8,
- 0xae, 0xf7, 0x83, 0xfb, 0x4c, 0x39, 0x7c, 0xb7, 0x75, 0x9a, 0x25, 0x05,
- 0xff, 0xa3, 0xf6, 0x3c, 0xbb, 0x0f, 0xa3, 0x95, 0x24, 0x5f, 0x69, 0x48,
- 0x4b, 0xaf, 0xff, 0x0b, 0xfb, 0x6a, 0x08, 0x24, 0x38, 0xc3, 0x97, 0xdb,
- 0x70, 0xe1, 0xcb, 0xff, 0xcf, 0x3a, 0x6b, 0x49, 0xf4, 0xbc, 0xff, 0x1c,
- 0xbe, 0xe6, 0xf2, 0xe7, 0x88, 0xe5, 0x61, 0x7e, 0xd2, 0x5a, 0x10, 0xd4,
- 0xed, 0xda, 0xe4, 0xa9, 0x48, 0x21, 0x8c, 0x99, 0x72, 0xe5, 0xd2, 0x10,
- 0xad, 0x71, 0xd9, 0xea, 0x3a, 0x76, 0x2c, 0x75, 0x53, 0xf5, 0xae, 0x1d,
- 0x6b, 0x70, 0xef, 0x04, 0xba, 0xde, 0x09, 0x45, 0x57, 0xff, 0xb9, 0xb1,
- 0xe5, 0xcf, 0x34, 0xb7, 0x75, 0x9a, 0x27, 0x35, 0xff, 0xee, 0x6c, 0x79,
- 0x73, 0xcd, 0x2d, 0xdd, 0x66, 0x8a, 0x25, 0x7f, 0xc0, 0x7d, 0x49, 0xa8,
- 0xf1, 0xfd, 0x0e, 0x5f, 0x20, 0xc3, 0x0e, 0x5f, 0xc9, 0xb9, 0xa4, 0x9f,
- 0x9c, 0xbf, 0xd1, 0x3a, 0x8d, 0x1c, 0x7f, 0x39, 0x74, 0xb9, 0x85, 0x19,
- 0x18, 0x85, 0xd2, 0x05, 0x0b, 0xef, 0xff, 0x73, 0xd8, 0xe7, 0xf1, 0xfe,
- 0xb5, 0x0d, 0x9c, 0xad, 0x22, 0x67, 0xf4, 0xba, 0xd2, 0xa3, 0x9d, 0xad,
- 0x02, 0x3b, 0xbb, 0xf6, 0x96, 0xee, 0xb3, 0x44, 0x38, 0xbf, 0x80, 0xbd,
- 0x24, 0x09, 0xcb, 0x73, 0xc3, 0xe0, 0xe9, 0xa5, 0xff, 0x46, 0xb1, 0x7d,
- 0x8f, 0xa4, 0x72, 0xff, 0xe1, 0x75, 0x57, 0xd4, 0xd6, 0xa1, 0xb3, 0x97,
- 0xcb, 0x77, 0x59, 0xa2, 0x2f, 0x5f, 0x85, 0xff, 0x7d, 0x9c, 0xbf, 0x64,
- 0xd2, 0x7d, 0x9c, 0xad, 0x1f, 0xef, 0x8b, 0x94, 0x27, 0xbf, 0xb0, 0x3d,
- 0xcf, 0xdc, 0xe5, 0xf4, 0x03, 0x87, 0xd9, 0xca, 0xd9, 0xea, 0x36, 0x5b,
- 0x70, 0xce, 0x72, 0xff, 0xbc, 0x30, 0xc5, 0x03, 0xd8, 0x39, 0x50, 0x7a,
- 0x08, 0x2f, 0x76, 0xfe, 0x39, 0x7d, 0xe9, 0x42, 0xa5, 0x29, 0x86, 0xed,
- 0xc6, 0x2f, 0xcf, 0xf0, 0x1f, 0xc7, 0x2f, 0xcf, 0x3f, 0xb3, 0xa7, 0x2d,
- 0xce, 0x75, 0x57, 0xa1, 0x39, 0xc8, 0x61, 0x4d, 0x08, 0x4e, 0xb9, 0x8a,
- 0xd8, 0x08, 0x1a, 0x14, 0x5f, 0xff, 0xff, 0x0b, 0xf3, 0xc0, 0x70, 0xe8,
- 0xaa, 0x7b, 0xb8, 0x92, 0xdf, 0x2c, 0x56, 0x24, 0x72, 0xfd, 0x9b, 0x60,
- 0x60, 0xe5, 0xff, 0x9e, 0x5c, 0xf3, 0x4b, 0x77, 0x59, 0xa2, 0x64, 0x5b,
- 0x9a, 0xd1, 0xf1, 0xa8, 0x42, 0xb0, 0x9e, 0xf7, 0xb1, 0x87, 0x2e, 0xeb,
- 0x0e, 0x5f, 0xb4, 0xb7, 0x75, 0x9a, 0x2d, 0xe5, 0xb9, 0xc1, 0xf3, 0x84,
- 0x73, 0x05, 0xef, 0xff, 0x73, 0x63, 0xcb, 0x9e, 0x69, 0x6e, 0xeb, 0x34,
- 0x52, 0x6b, 0x9a, 0xa6, 0xac, 0xe5, 0xfd, 0x9e, 0x18, 0x86, 0x1c, 0xbf,
- 0xbe, 0xfd, 0x4d, 0x3f, 0xe7, 0x2e, 0xef, 0x3e, 0x10, 0xff, 0xba, 0x42,
- 0xe5, 0x75, 0x0b, 0xca, 0xf2, 0x95, 0xcd, 0x91, 0xbf, 0xee, 0x14, 0x9c,
- 0x4d, 0x54, 0x86, 0xc5, 0xfe, 0xe7, 0x9a, 0x5b, 0xba, 0xcd, 0x10, 0xea,
- 0xfd, 0xa5, 0xbb, 0xac, 0xd1, 0x2c, 0x2f, 0xb3, 0xf6, 0x21, 0xcb, 0xf7,
- 0x36, 0x3c, 0xb9, 0xe1, 0xeb, 0x34, 0x34, 0xbf, 0xdc, 0xf3, 0x4b, 0x77,
- 0x59, 0xa2, 0x30, 0x5f, 0xee, 0x60, 0x96, 0x6d, 0xf6, 0x72, 0xff, 0xfc,
- 0xff, 0xb4, 0xce, 0x62, 0xfe, 0x96, 0x7b, 0x02, 0x72, 0x85, 0x11, 0xbb,
- 0x35, 0xbe, 0xe7, 0x2c, 0xd9, 0xcb, 0xff, 0xfe, 0x96, 0xf9, 0xaf, 0xaf,
- 0x32, 0xfb, 0x9a, 0x6a, 0x7b, 0x33, 0x36, 0x72, 0xfd, 0x9e, 0xfe, 0x16,
- 0x72, 0xff, 0xf4, 0x79, 0x3f, 0x89, 0x07, 0xb0, 0x2b, 0x39, 0x7e, 0xd2,
- 0xdd, 0xd6, 0x68, 0x8f, 0x57, 0xdb, 0x7f, 0xb8, 0x9c, 0xba, 0x5c, 0xf0,
- 0xf6, 0x7c, 0x69, 0x7f, 0xff, 0x3f, 0x31, 0x06, 0x77, 0x07, 0xfc, 0x1f,
- 0x77, 0x0e, 0x5b, 0x9f, 0xc9, 0xe2, 0xcc, 0xe5, 0xa2, 0x87, 0x85, 0x10,
- 0x97, 0xdf, 0xb4, 0xb7, 0x75, 0x9a, 0x2c, 0x35, 0xfe, 0x90, 0xc6, 0x6f,
- 0x04, 0xe5, 0xc9, 0x23, 0x96, 0xe7, 0x87, 0xf5, 0xf1, 0xa7, 0xe6, 0x17,
- 0xf7, 0x86, 0x3f, 0x93, 0x0e, 0x5f, 0xff, 0xf4, 0x46, 0xf9, 0xf8, 0x28,
- 0xcf, 0xa5, 0xbf, 0xa5, 0x9a, 0x9c, 0xe5, 0xd1, 0xae, 0x68, 0x9a, 0x12,
- 0xeb, 0xfd, 0xcf, 0x34, 0xb7, 0x75, 0x9a, 0x2e, 0x75, 0xff, 0xff, 0xff,
- 0xd1, 0xc2, 0xf2, 0x9d, 0x7d, 0xe5, 0xcb, 0xad, 0x39, 0xce, 0x05, 0x78,
- 0x5a, 0x38, 0x4f, 0xa7, 0x9d, 0x6c, 0xe5, 0xcb, 0xad, 0x0e, 0x54, 0x2f,
- 0x4a, 0x4f, 0x09, 0x79, 0x22, 0x64, 0x33, 0x96, 0x44, 0x91, 0xf4, 0xb2,
- 0x1a, 0x5d, 0x86, 0x97, 0x8b, 0xf8, 0x10, 0x6f, 0xf7, 0x3c, 0xd2, 0xdd,
- 0xd6, 0x68, 0x87, 0x97, 0xcb, 0x77, 0x59, 0xa2, 0x26, 0x5f, 0xd9, 0xc0,
- 0x06, 0x60, 0x4e, 0x58, 0x07, 0x2f, 0xf7, 0x80, 0xff, 0x76, 0x38, 0x9c,
- 0xad, 0x22, 0x94, 0x4b, 0xb6, 0x61, 0xe1, 0x1b, 0xf7, 0xfb, 0xe5, 0x81,
- 0x39, 0x7f, 0x91, 0xbc, 0x1c, 0xfb, 0xc7, 0x29, 0x0f, 0x7b, 0x45, 0x77,
- 0xff, 0xe8, 0xd7, 0xfd, 0x8e, 0x33, 0x44, 0x33, 0x78, 0x13, 0x97, 0xfd,
- 0xde, 0xc7, 0x19, 0x66, 0xa0, 0xe5, 0xbd, 0xd4, 0x49, 0x3a, 0xc5, 0xff,
- 0x27, 0x93, 0xd9, 0xfc, 0x68, 0xe5, 0xf4, 0xfd, 0x04, 0xe7, 0x2b, 0x11,
- 0x0a, 0xe5, 0x00, 0x38, 0xbd, 0x81, 0xe9, 0xcb, 0xff, 0xfb, 0xdd, 0x8d,
- 0x7f, 0xbc, 0x0f, 0x80, 0xeb, 0xcd, 0x1c, 0xbb, 0xcc, 0x39, 0x7f, 0xfb,
- 0x3a, 0xa4, 0xfb, 0x84, 0xfb, 0xd0, 0xc3, 0x97, 0xfd, 0x12, 0x53, 0x35,
- 0xbc, 0x6c, 0xe5, 0xfe, 0x94, 0x2a, 0x9d, 0x79, 0xce, 0x54, 0xe7, 0xdc,
- 0x87, 0x55, 0x89, 0xa7, 0xfc, 0xb9, 0xd1, 0x70, 0x42, 0xea, 0xff, 0x83,
- 0x9c, 0x74, 0xfc, 0x7a, 0x87, 0x2f, 0xcd, 0x82, 0x35, 0x39, 0xcb, 0x27,
- 0x23, 0xe6, 0x6c, 0xf2, 0xfa, 0x5d, 0x53, 0x67, 0x2e, 0x75, 0x0d, 0x10,
- 0xba, 0xde, 0xf8, 0xf2, 0x00, 0x49, 0x7e, 0xee, 0x4e, 0x01, 0x39, 0x7c,
- 0xfa, 0x8e, 0x27, 0x28, 0x27, 0x97, 0xf9, 0x45, 0xfa, 0x69, 0x63, 0x89,
- 0xcb, 0x73, 0xc5, 0xd4, 0x4d, 0x42, 0x6b, 0xb1, 0x9c, 0x09, 0x76, 0xe3,
- 0x6b, 0xf4, 0x2a, 0x40, 0xe5, 0xc5, 0xd1, 0xa1, 0x1d, 0xff, 0xb4, 0x09,
- 0xf3, 0xb3, 0x0c, 0x04, 0xe5, 0xff, 0xfe, 0x74, 0xf0, 0x34, 0xfb, 0xc1,
- 0xee, 0x60, 0xcb, 0x67, 0x2e, 0xeb, 0x9c, 0xb0, 0x0e, 0x56, 0x1a, 0x7d,
- 0x8b, 0x5e, 0xff, 0x7c, 0xe1, 0x1c, 0x9d, 0x40, 0xf4, 0x21, 0x2f, 0xff,
- 0xb1, 0x25, 0xbe, 0x79, 0xf4, 0x9e, 0x75, 0x16, 0x72, 0xa1, 0x13, 0xbd,
- 0x49, 0xbf, 0xe6, 0xab, 0x84, 0xd6, 0x79, 0x3a, 0x03, 0x97, 0xdb, 0x49,
- 0xf8, 0x43, 0x94, 0xd5, 0x1f, 0x5b, 0x52, 0x87, 0x7f, 0xe6, 0xab, 0x84,
- 0x49, 0xe3, 0x92, 0xf7, 0x87, 0x2e, 0xe1, 0x42, 0x72, 0x9a, 0xa3, 0xe7,
- 0x6a, 0x52, 0xef, 0xfb, 0x3c, 0xa4, 0xef, 0xa4, 0x98, 0xe5, 0xfd, 0x2e,
- 0x15, 0x3f, 0x09, 0xc2, 0xcd, 0x44, 0xe5, 0x70, 0x88, 0x83, 0x6a, 0xce,
- 0xef, 0xe6, 0xa9, 0x4e, 0xf7, 0x27, 0x39, 0x6e, 0x9c, 0xa6, 0xa8, 0xf1,
- 0x80, 0x6b, 0x7c, 0x1c, 0x19, 0x8e, 0x5c, 0x9e, 0x39, 0x6f, 0x21, 0xb8,
- 0xe9, 0x15, 0xfe, 0xfb, 0xdf, 0x48, 0x02, 0xa9, 0xcb, 0xff, 0x44, 0xc3,
- 0x9c, 0x5d, 0x8c, 0x43, 0x94, 0xe7, 0xec, 0x03, 0x7b, 0xff, 0xff, 0xba,
- 0x00, 0xa6, 0x6a, 0x61, 0xce, 0x3d, 0xc0, 0xc6, 0xf7, 0x0a, 0x9c, 0xbf,
- 0xfc, 0x93, 0x4b, 0x3e, 0x97, 0x26, 0x3b, 0x89, 0xcb, 0x9f, 0x80, 0xe5,
- 0xff, 0xfe, 0xde, 0x7b, 0x97, 0x71, 0x70, 0xd8, 0xe0, 0x7a, 0x93, 0x1c,
- 0xb7, 0x09, 0x89, 0xfc, 0xab, 0x09, 0xc5, 0x90, 0xf5, 0xd1, 0xd3, 0x3c,
- 0x33, 0x73, 0x45, 0x4e, 0x5f, 0x3c, 0xa3, 0xf3, 0x97, 0xee, 0xbf, 0x9e,
- 0x47, 0x2f, 0xe4, 0xd0, 0xe6, 0x68, 0xe5, 0xe5, 0xcf, 0xd3, 0x97, 0xf6,
- 0xe3, 0x6d, 0x41, 0xaa, 0x6a, 0x8e, 0x5f, 0xa3, 0x60, 0xea, 0x1c, 0xae,
- 0x48, 0x83, 0x90, 0xf6, 0xcf, 0xaf, 0xfe, 0x67, 0x2d, 0x8e, 0x7d, 0x21,
- 0x79, 0xce, 0x5e, 0xda, 0x7e, 0x72, 0xb0, 0xf9, 0x11, 0x1e, 0xf3, 0x6d,
- 0xb6, 0x52, 0xfc, 0xe3, 0xee, 0xe1, 0x4e, 0x66, 0x82, 0xff, 0xff, 0xe8,
- 0x9f, 0x96, 0xc1, 0x1f, 0x7b, 0xb8, 0xcc, 0xf0, 0xc7, 0xff, 0xc1, 0xcb,
- 0xef, 0x4d, 0x9e, 0x39, 0x41, 0x44, 0xcb, 0xbb, 0x50, 0x53, 0x33, 0xfd,
- 0x00, 0x61, 0xa3, 0x7e, 0xe8, 0xb5, 0x16, 0x9c, 0x07, 0x2e, 0x77, 0x39,
- 0x6e, 0xa1, 0xe4, 0x39, 0x9d, 0xff, 0xfd, 0xfe, 0xa3, 0x96, 0xa3, 0xdf,
- 0x4a, 0x15, 0xd3, 0xb6, 0x72, 0xff, 0xc9, 0x37, 0x2e, 0xc2, 0x68, 0x0d,
- 0x67, 0x2a, 0x11, 0x4b, 0xfb, 0x0d, 0xfd, 0xa4, 0xe0, 0xd6, 0xf6, 0x72,
- 0xfe, 0x10, 0x79, 0x27, 0x83, 0x97, 0xfe, 0x45, 0x60, 0x63, 0x70, 0x8c,
- 0x39, 0x7e, 0xe2, 0x09, 0x66, 0xce, 0x5f, 0x7e, 0x82, 0x03, 0x95, 0x87,
- 0x98, 0x02, 0xab, 0xec, 0x0e, 0x4e, 0x72, 0xf9, 0xaf, 0x94, 0x35, 0x27,
- 0x2e, 0xd4, 0x1c, 0xa0, 0xae, 0xcb, 0xe1, 0x12, 0xc9, 0xfe, 0x85, 0x72,
- 0x47, 0x92, 0xd6, 0xfd, 0x34, 0x32, 0xf4, 0x46, 0xc3, 0x1e, 0x96, 0x8c,
- 0x22, 0x3c, 0x43, 0xc4, 0x8b, 0x80, 0xb2, 0xfc, 0xdc, 0x60, 0x50, 0xe5,
- 0xe0, 0x7b, 0x67, 0x2f, 0xff, 0xff, 0xfb, 0x7c, 0xbb, 0x93, 0xc3, 0x7f,
- 0x4b, 0x7c, 0x80, 0xbd, 0x6a, 0x39, 0x4c, 0xaf, 0xdc, 0xb9, 0x75, 0xa1,
- 0xcb, 0xfb, 0xee, 0x53, 0x66, 0x2c, 0xe5, 0x62, 0x63, 0xeb, 0x27, 0xf0,
- 0xe8, 0x21, 0x55, 0x70, 0x3f, 0x39, 0x73, 0x46, 0xa8, 0xe5, 0xee, 0x52,
- 0x59, 0xca, 0x83, 0xd5, 0x54, 0x61, 0x83, 0xd7, 0xff, 0xf6, 0xb9, 0x0e,
- 0x71, 0xcd, 0x4b, 0x94, 0x05, 0xe6, 0xd9, 0xcb, 0xff, 0xff, 0x87, 0xe8,
- 0x54, 0x70, 0x3d, 0x49, 0xb9, 0x6f, 0x3e, 0x96, 0xb1, 0xb3, 0x95, 0x88,
- 0xd8, 0x16, 0x1b, 0xef, 0x02, 0x27, 0x39, 0x7f, 0x49, 0xf5, 0xb4, 0x09,
- 0xcb, 0xfb, 0x3b, 0x8c, 0x85, 0x9c, 0xa8, 0x3d, 0x99, 0x16, 0xd2, 0x22,
- 0x77, 0xcf, 0x97, 0xff, 0xf7, 0xd2, 0xdb, 0x30, 0x79, 0x70, 0x27, 0x67,
- 0x4c, 0xd1, 0xcb, 0x35, 0x9c, 0xac, 0x3f, 0x55, 0xb0, 0xdf, 0xff, 0xf9,
- 0xbe, 0x43, 0x8b, 0xea, 0x0e, 0x03, 0xef, 0x72, 0x76, 0xf1, 0x53, 0x97,
- 0xf9, 0x50, 0x82, 0x3a, 0x30, 0x72, 0xff, 0x7d, 0x2d, 0xaa, 0x08, 0xf8,
- 0xe5, 0xfe, 0x76, 0xc1, 0x34, 0x79, 0xce, 0x5e, 0xe3, 0xe5, 0x0e, 0x54,
- 0x26, 0x61, 0x8e, 0x48, 0x66, 0x26, 0xed, 0x9a, 0x5f, 0xff, 0x87, 0x03,
- 0xd0, 0x37, 0xb4, 0xf7, 0x51, 0xff, 0x39, 0x7f, 0x87, 0x38, 0xf2, 0x93,
- 0x24, 0x72, 0xb4, 0x88, 0xdd, 0xab, 0x5d, 0xbe, 0x27, 0x2a, 0x0d, 0xe0,
- 0x08, 0xef, 0xbf, 0xf2, 0x4e, 0x72, 0xff, 0x7b, 0xa8, 0x3f, 0xa8, 0xc3,
- 0x97, 0xff, 0xf7, 0x53, 0x07, 0x10, 0x39, 0x1f, 0xba, 0xdf, 0x47, 0x2f,
- 0xf4, 0xf0, 0xc1, 0x8f, 0xbf, 0x39, 0x52, 0x46, 0x0f, 0xc6, 0xae, 0xaf,
- 0x7e, 0xef, 0x27, 0xcd, 0x9c, 0xa8, 0x3d, 0x9c, 0x30, 0xbf, 0xf9, 0xf5,
- 0x2e, 0x5e, 0x18, 0x96, 0x78, 0xe5, 0x42, 0xeb, 0xd6, 0x42, 0xf9, 0x21,
- 0x2f, 0xa8, 0xd4, 0x7b, 0x18, 0x8b, 0x90, 0x0c, 0x67, 0xc0, 0x20, 0xb3,
- 0x59, 0xcb, 0xff, 0xed, 0x20, 0x38, 0x78, 0xe5, 0xb0, 0x7e, 0xcc, 0xf1,
- 0xcb, 0xff, 0x42, 0xf7, 0x09, 0xf7, 0xa1, 0x87, 0x2d, 0x23, 0x94, 0x27,
- 0x9e, 0x03, 0xeb, 0xef, 0xf7, 0x3f, 0x8e, 0x5f, 0xf9, 0xd5, 0xe5, 0xe7,
- 0x71, 0xe5, 0x39, 0xca, 0x83, 0xe8, 0x12, 0x5b, 0xcf, 0xed, 0x9c, 0xb8,
- 0x13, 0x9c, 0xa9, 0x1b, 0x4d, 0x0e, 0x5f, 0xb2, 0x5d, 0x79, 0x1c, 0xb8,
- 0x7d, 0x31, 0xe4, 0x74, 0x86, 0xff, 0x38, 0xa9, 0xde, 0xc0, 0x4e, 0x5f,
- 0xc0, 0x5f, 0x20, 0xfc, 0xd9, 0xcb, 0xfe, 0x86, 0xfb, 0x83, 0xf4, 0x2a,
- 0x72, 0xed, 0x48, 0xe5, 0x42, 0x39, 0x7e, 0x2e, 0x43, 0x3d, 0x19, 0xb0,
- 0xea, 0xff, 0x6a, 0x03, 0x1d, 0x89, 0x1c, 0xbf, 0xfe, 0x8f, 0x72, 0x10,
- 0x70, 0x72, 0xcf, 0x34, 0xcf, 0x1c, 0xa4, 0x44, 0x50, 0x0c, 0xaf, 0xfe,
- 0xec, 0x2b, 0xcb, 0xc2, 0xfe, 0x8f, 0x1c, 0xbf, 0xdc, 0xbe, 0x92, 0x74,
- 0x0c, 0x39, 0x5f, 0x9f, 0xe8, 0xa3, 0x5f, 0xfd, 0x9c, 0x70, 0x3c, 0xbc,
- 0xaa, 0x37, 0xb3, 0x97, 0xfe, 0xd4, 0xdc, 0xb7, 0x09, 0x3b, 0xf8, 0xe5,
- 0x42, 0x2b, 0x82, 0x44, 0x04, 0xab, 0x9f, 0xf3, 0x97, 0xff, 0xdc, 0x86,
- 0x37, 0x13, 0x8e, 0x07, 0xa9, 0x31, 0xcb, 0xff, 0xff, 0xb7, 0xa1, 0x89,
- 0xb9, 0x29, 0xe4, 0x96, 0x7d, 0xec, 0xe2, 0x39, 0xb3, 0x95, 0xa4, 0x64,
- 0x0a, 0x8d, 0x79, 0x30, 0x10, 0x43, 0x7e, 0x8e, 0x5e, 0xf7, 0x25, 0x4e,
- 0x5d, 0x34, 0x8e, 0x54, 0x1e, 0x1f, 0xc1, 0x7a, 0x20, 0xbf, 0xf8, 0x7d,
- 0xbe, 0x29, 0xe8, 0xc1, 0x98, 0xe5, 0xfb, 0x49, 0xb8, 0xf8, 0xe5, 0x61,
- 0xf6, 0xba, 0x2d, 0xfe, 0x9f, 0x84, 0x9a, 0x49, 0xed, 0x9c, 0xbf, 0x0f,
- 0xbb, 0x9c, 0x07, 0x2f, 0xd3, 0x6d, 0xf4, 0xa9, 0xcb, 0xce, 0xde, 0xa0,
- 0xf5, 0x30, 0xaa, 0xa4, 0x8e, 0x14, 0x20, 0xd4, 0x23, 0xef, 0xfb, 0xa9,
- 0xa9, 0xba, 0xf9, 0xa3, 0x97, 0xff, 0xff, 0xf7, 0xfb, 0x1c, 0x7f, 0xb9,
- 0x07, 0xa0, 0xe4, 0x39, 0xf4, 0xb0, 0x13, 0x8e, 0x3f, 0xc7, 0x29, 0x68,
- 0xc8, 0x43, 0x9b, 0xce, 0xeb, 0x34, 0x53, 0x0a, 0xc3, 0xca, 0x59, 0x15,
- 0xff, 0xb0, 0x7e, 0x96, 0xfd, 0x1a, 0x98, 0xe5, 0xff, 0x9f, 0xec, 0x4d,
- 0x23, 0x21, 0x53, 0x97, 0xb1, 0x3f, 0x39, 0x6c, 0x39, 0x7b, 0xe1, 0xcf,
- 0xcd, 0x67, 0x11, 0xca, 0x44, 0x6f, 0xe9, 0x01, 0xda, 0xaf, 0x60, 0x34,
- 0x72, 0xe9, 0xe6, 0x39, 0x66, 0xce, 0x5c, 0x81, 0x39, 0x4d, 0x66, 0xa3,
- 0x62, 0x57, 0x06, 0x63, 0x97, 0xfd, 0xac, 0x0f, 0x61, 0xb6, 0x00, 0xe5,
- 0xca, 0xce, 0x72, 0xa1, 0x1a, 0x18, 0x82, 0xc2, 0x4e, 0x8c, 0x36, 0x75,
- 0x73, 0x3f, 0x39, 0x7b, 0x5d, 0x7e, 0x47, 0xc3, 0xfa, 0x4d, 0xfe, 0xe5,
- 0xf4, 0x86, 0x33, 0x67, 0x2b, 0xe4, 0xee, 0x12, 0x34, 0xd7, 0x36, 0xbf,
- 0xff, 0x7e, 0x9b, 0xe5, 0xd7, 0xdf, 0xa2, 0x6d, 0xf7, 0x0e, 0x5f, 0xdd,
- 0x7d, 0xf5, 0xe4, 0x72, 0xfe, 0x4e, 0xba, 0x4f, 0x07, 0x2f, 0x4a, 0x3e,
- 0x39, 0x7f, 0x98, 0x1e, 0xc4, 0xf8, 0xd9, 0xca, 0x84, 0x55, 0xe1, 0x6f,
- 0xc5, 0x8e, 0x3b, 0x7e, 0xf9, 0x63, 0x1c, 0x4e, 0x5f, 0xf9, 0xfe, 0xda,
- 0x9d, 0xec, 0x0a, 0xce, 0x56, 0x1f, 0x50, 0x0a, 0xae, 0xde, 0xce, 0x5b,
- 0x0e, 0x5f, 0xfa, 0x64, 0x55, 0x3c, 0x39, 0xc1, 0xcb, 0x46, 0x9f, 0x88,
- 0xbd, 0xff, 0xfe, 0x1c, 0x5f, 0xbd, 0x1e, 0xdc, 0xc3, 0x8d, 0xf2, 0x86,
- 0xa4, 0xe5, 0xff, 0x97, 0x0c, 0xee, 0x6f, 0x10, 0x4e, 0x54, 0x22, 0x93,
- 0xad, 0x17, 0xed, 0x47, 0x18, 0xd1, 0xcb, 0xf9, 0xc7, 0x90, 0x60, 0x4e,
- 0x54, 0x26, 0xf1, 0x91, 0x80, 0x21, 0x10, 0x0a, 0x6f, 0xfa, 0x1b, 0x5a,
- 0x4f, 0x9f, 0x78, 0xe5, 0x35, 0x6d, 0x82, 0x2c, 0x0a, 0x4f, 0x0a, 0x79,
- 0x42, 0x24, 0x31, 0xc0, 0xab, 0x0d, 0x35, 0xc6, 0x9b, 0xf4, 0x66, 0x08,
- 0xd9, 0x34, 0x6f, 0xba, 0x8d, 0x19, 0x91, 0x80, 0x76, 0x3e, 0x6f, 0xcd,
- 0x86, 0x30, 0x4d, 0xc2, 0x97, 0xd1, 0xe0, 0x71, 0x41, 0xbf, 0xed, 0x3b,
- 0x7c, 0x9c, 0x2f, 0x39, 0xcb, 0xf9, 0xdb, 0x98, 0x50, 0x27, 0x2f, 0xff,
- 0xf0, 0x72, 0x77, 0x1f, 0x6e, 0x17, 0xc9, 0x8c, 0x41, 0x59, 0xcb, 0xf8,
- 0x3b, 0x78, 0xfa, 0x47, 0x2a, 0x11, 0x20, 0xec, 0x57, 0xfa, 0x6e, 0xa4,
- 0x31, 0xc2, 0x72, 0xff, 0x72, 0xd6, 0x27, 0x60, 0x27, 0x2a, 0x0f, 0x9c,
- 0x4c, 0xe9, 0x54, 0xe8, 0xb4, 0x78, 0x30, 0xbe, 0x04, 0x22, 0x2f, 0xb0,
- 0x55, 0x6b, 0x39, 0x7f, 0xff, 0xfe, 0xea, 0x7b, 0xb9, 0xa8, 0xe3, 0xc9,
- 0x80, 0xe0, 0xe5, 0x9f, 0x4b, 0x00, 0x3f, 0xec, 0xe5, 0xbc, 0x88, 0xb3,
- 0xd9, 0x2d, 0xff, 0xa1, 0x7c, 0x85, 0xf6, 0xc8, 0x13, 0x97, 0xff, 0xba,
- 0x8b, 0xee, 0x72, 0xd8, 0x3b, 0x0d, 0x67, 0x2f, 0xfb, 0xd9, 0xd1, 0xcf,
- 0x75, 0x0e, 0x5b, 0x31, 0x10, 0xdf, 0x27, 0xdf, 0xff, 0x7b, 0xb9, 0xff,
- 0x26, 0x46, 0x78, 0x38, 0x27, 0x2c, 0xd9, 0xcb, 0xf9, 0xc3, 0xad, 0x02,
- 0x73, 0x97, 0xe8, 0xc1, 0xf3, 0x43, 0x94, 0xa9, 0xf4, 0xac, 0x49, 0x85,
- 0xf7, 0xde, 0x4d, 0x61, 0xcb, 0x7d, 0xc8, 0xf4, 0x70, 0xc2, 0xdb, 0xc4,
- 0xcd, 0x5e, 0x30, 0xba, 0x62, 0xa4, 0xf1, 0x86, 0x27, 0xa3, 0x5d, 0xbf,
- 0xff, 0xfe, 0xcf, 0xa4, 0x9b, 0x1c, 0xe3, 0xdc, 0x9b, 0xb0, 0x33, 0x72,
- 0x75, 0xa7, 0x13, 0x97, 0xff, 0xfd, 0x82, 0xaf, 0x2d, 0x47, 0x14, 0xf6,
- 0xf1, 0x54, 0xd3, 0xfc, 0x72, 0x85, 0x1d, 0xca, 0x42, 0x0e, 0x91, 0x35,
- 0x20, 0x46, 0x55, 0x7f, 0xf9, 0x03, 0xc9, 0x89, 0xca, 0x02, 0xf3, 0x6c,
- 0xe5, 0xd2, 0x91, 0xcb, 0x6a, 0x0f, 0x96, 0x74, 0xeb, 0xf4, 0xa3, 0xe9,
- 0x6c, 0xe5, 0xff, 0xff, 0xff, 0xb0, 0x55, 0xe4, 0x9d, 0x07, 0x39, 0x93,
- 0xd0, 0xc1, 0x75, 0x7a, 0x9c, 0xf3, 0xbf, 0x7f, 0x01, 0x29, 0x7f, 0xff,
- 0xf2, 0xd1, 0xb0, 0x83, 0x5c, 0x81, 0x13, 0xed, 0x7d, 0x07, 0x7e, 0x76,
- 0xce, 0x5c, 0x09, 0xfe, 0x4d, 0x15, 0x0a, 0x77, 0x0a, 0x2b, 0xf9, 0x51,
- 0xcf, 0x75, 0x0e, 0x54, 0x2f, 0x1a, 0x76, 0x5e, 0x4b, 0xc2, 0x38, 0x63,
- 0x6d, 0x02, 0x1d, 0x98, 0x72, 0xff, 0x3c, 0xb1, 0x8e, 0x3f, 0x9c, 0xbe,
- 0xce, 0xc4, 0xc7, 0x2f, 0x31, 0x7c, 0x9a, 0xb3, 0xe5, 0xe8, 0x8b, 0x99,
- 0x5f, 0xff, 0xfe, 0xd2, 0xc7, 0x38, 0xf2, 0xda, 0x60, 0xff, 0xc8, 0x73,
- 0x88, 0xe6, 0xf8, 0x9c, 0xbf, 0xd8, 0xec, 0xe4, 0xd2, 0x18, 0x72, 0xff,
- 0xf4, 0xa3, 0x7d, 0x06, 0xb3, 0xde, 0x46, 0x1c, 0xa5, 0xa2, 0x03, 0xe3,
- 0x6b, 0xff, 0xf0, 0x23, 0x90, 0xe0, 0x7a, 0x8a, 0x86, 0x15, 0xfc, 0xe5,
- 0x62, 0x6f, 0x9a, 0x87, 0xf8, 0x92, 0x5f, 0xff, 0x90, 0x7d, 0xdc, 0xe0,
- 0xf4, 0xd8, 0xd6, 0xe3, 0xf9, 0xcb, 0xe6, 0xf9, 0x6e, 0x63, 0x96, 0xf1,
- 0xca, 0x83, 0x70, 0xe4, 0xf7, 0xfe, 0x19, 0xc7, 0x38, 0xec, 0x11, 0xf1,
- 0xcb, 0xff, 0x07, 0xb1, 0xf7, 0x26, 0xa3, 0xc7, 0xf4, 0x39, 0x50, 0x88,
- 0xc9, 0xd0, 0x69, 0x13, 0x95, 0xd9, 0xa7, 0xa1, 0x26, 0x08, 0x55, 0xdf,
- 0xfc, 0xde, 0x6c, 0x10, 0xae, 0xe3, 0x53, 0x1c, 0xbe, 0xd4, 0x9c, 0x27,
- 0x2f, 0xfc, 0x32, 0x5f, 0x53, 0xa2, 0x09, 0xce, 0x5e, 0xf6, 0x70, 0xe7,
- 0x2a, 0x0f, 0x83, 0x0f, 0xef, 0x34, 0xce, 0x9c, 0xbb, 0x02, 0x72, 0xa7,
- 0x5c, 0xbc, 0x94, 0xb5, 0x8c, 0x47, 0x74, 0x7d, 0xc2, 0x0b, 0xc4, 0x1c,
- 0x47, 0xaf, 0xc9, 0xed, 0xe7, 0xe7, 0x2f, 0xdd, 0xce, 0x29, 0xc4, 0xe5,
- 0xff, 0xff, 0x85, 0xfd, 0xd8, 0x9b, 0x90, 0xe7, 0x53, 0xdb, 0x02, 0xc1,
- 0x07, 0x2e, 0xcf, 0xce, 0x5f, 0xfc, 0x3f, 0x8e, 0x24, 0xdd, 0x81, 0x54,
- 0xe5, 0x21, 0xed, 0xb8, 0xbd, 0xfa, 0x07, 0xaf, 0x23, 0x97, 0xa0, 0x30,
- 0x72, 0x82, 0x78, 0x2c, 0x26, 0xa3, 0x97, 0xa0, 0x30, 0x72, 0xfd, 0x9e,
- 0xdb, 0xcd, 0xc8, 0xf2, 0x20, 0x89, 0x81, 0x77, 0xcd, 0x5b, 0x50, 0xe1,
- 0x9a, 0xb3, 0x97, 0xc8, 0xe2, 0x13, 0x96, 0x6f, 0x91, 0xec, 0x04, 0xe2,
- 0xa4, 0x8d, 0x04, 0x85, 0x2d, 0xff, 0xfb, 0x40, 0xd6, 0xa0, 0x71, 0x54,
- 0xef, 0x71, 0x43, 0x97, 0xc0, 0x7f, 0xbc, 0x72, 0xa4, 0xac, 0xd0, 0x25,
- 0x18, 0x56, 0xac, 0x32, 0x26, 0x8d, 0xe7, 0x44, 0xfd, 0x56, 0xa3, 0x97,
- 0xf6, 0xd6, 0xb7, 0x15, 0x4e, 0x57, 0x0a, 0x37, 0x3e, 0x0b, 0xbf, 0xc3,
- 0xcb, 0x8f, 0xd2, 0xdc, 0xc7, 0x2e, 0x9f, 0xe3, 0x97, 0xee, 0xbb, 0x5c,
- 0x7e, 0x72, 0x82, 0x7f, 0xce, 0x75, 0xc0, 0x33, 0x7f, 0xb5, 0x30, 0xe7,
- 0x5f, 0xc7, 0x2a, 0x13, 0x09, 0xc8, 0x52, 0xa1, 0x8d, 0xf9, 0x34, 0x1c,
- 0x13, 0x97, 0xef, 0xf3, 0xca, 0x4e, 0x72, 0xff, 0x37, 0xec, 0xef, 0x2f,
- 0xb6, 0x72, 0xa0, 0xf8, 0xdc, 0xae, 0xa4, 0x8d, 0xce, 0x99, 0x8c, 0x22,
- 0x6f, 0xee, 0xe2, 0xe5, 0x0c, 0x39, 0x7f, 0xbb, 0x92, 0x71, 0xcf, 0x8e,
- 0x56, 0x1e, 0xff, 0x8b, 0x6f, 0xff, 0xf8, 0x5f, 0xfd, 0xcf, 0x88, 0x3e,
- 0x1c, 0xe3, 0xcb, 0x6d, 0x89, 0xcb, 0xfb, 0xb8, 0x3f, 0x42, 0xa7, 0x28,
- 0x51, 0x73, 0xe2, 0x16, 0xda, 0xaf, 0x62, 0x4c, 0x72, 0xff, 0xc9, 0x93,
- 0x72, 0xdc, 0x75, 0xda, 0xce, 0x5f, 0xff, 0x4b, 0x60, 0xc1, 0xe4, 0x39,
- 0xde, 0xb8, 0x4e, 0x5f, 0xf7, 0xd9, 0x1f, 0x4c, 0x30, 0xc3, 0x97, 0xf7,
- 0xdb, 0xee, 0x3e, 0x8e, 0x5f, 0xff, 0xf9, 0x19, 0xa4, 0xcf, 0x84, 0x1e,
- 0x8e, 0xf2, 0xe2, 0x9e, 0x9a, 0x0e, 0x53, 0xa2, 0x7b, 0xc5, 0xd5, 0x3a,
- 0x75, 0x21, 0x1c, 0xf9, 0x0f, 0xaa, 0x1e, 0x86, 0xc5, 0xff, 0xf6, 0x3c,
- 0xfd, 0x84, 0xf6, 0xe2, 0x7c, 0xd9, 0xcb, 0xfe, 0xcd, 0x4f, 0x09, 0xac,
- 0x13, 0x96, 0x61, 0xce, 0x46, 0xde, 0xf0, 0xe0, 0x4e, 0x54, 0x1b, 0xef,
- 0x88, 0xef, 0xef, 0xb7, 0x98, 0x2a, 0x9c, 0xbe, 0x62, 0x91, 0xf9, 0xcb,
- 0xff, 0xd3, 0x87, 0x4e, 0xb1, 0xce, 0x3a, 0x4d, 0x9c, 0xac, 0x44, 0xf2,
- 0x17, 0x00, 0x92, 0xfe, 0xf7, 0x5e, 0x65, 0x18, 0x72, 0xfe, 0xf4, 0x7f,
- 0x2c, 0xd9, 0xca, 0x73, 0xde, 0x13, 0x0b, 0xc0, 0xfb, 0xf3, 0x97, 0xf6,
- 0xe3, 0xef, 0xf5, 0x07, 0x2e, 0x0a, 0x1c, 0xa8, 0x5c, 0xbe, 0xc8, 0xf6,
- 0x56, 0xa4, 0x90, 0xc4, 0xd4, 0x2f, 0xde, 0x11, 0x82, 0x41, 0xb1, 0xfe,
- 0x25, 0xf7, 0xf7, 0x9f, 0xbc, 0x83, 0x07, 0x2f, 0xff, 0x7b, 0x6a, 0x6f,
- 0x97, 0x86, 0x25, 0x9e, 0x39, 0x7f, 0xbc, 0x93, 0xe7, 0x41, 0xe3, 0x97,
- 0xde, 0xdc, 0x2a, 0x72, 0xd3, 0x1c, 0xbf, 0xb0, 0x19, 0xd5, 0xce, 0x72,
- 0xdf, 0x41, 0xe0, 0x6c, 0x4a, 0xa1, 0x11, 0x78, 0xc7, 0x7f, 0x75, 0xe4,
- 0xcd, 0x21, 0xcb, 0xff, 0x95, 0x55, 0xfd, 0xbf, 0x0c, 0x7d, 0x23, 0x97,
- 0xf7, 0x86, 0x25, 0x9e, 0x39, 0x50, 0x7e, 0x72, 0x47, 0xb9, 0x36, 0x72,
- 0xcc, 0x39, 0x7b, 0x59, 0xf1, 0xca, 0x09, 0xe2, 0x74, 0x5b, 0xf1, 0x1b,
- 0xff, 0xce, 0xaf, 0x95, 0x81, 0x96, 0x75, 0x18, 0x72, 0xfc, 0x9b, 0xdc,
- 0x30, 0xe5, 0x22, 0x28, 0x44, 0xc3, 0x8a, 0x55, 0x42, 0xb3, 0x2c, 0x2f,
- 0x55, 0x35, 0x21, 0x7f, 0xf9, 0x08, 0xc2, 0x80, 0x11, 0x83, 0x5f, 0x82,
- 0x82, 0xe1, 0x39, 0x7b, 0x61, 0xf8, 0xe5, 0xdf, 0xac, 0xe5, 0xff, 0xec,
- 0x9b, 0xb0, 0x2a, 0x8e, 0x7b, 0xa0, 0x39, 0x4a, 0x9f, 0x17, 0x46, 0x2b,
- 0x92, 0x28, 0xe5, 0x08, 0x0a, 0x44, 0x79, 0xea, 0x19, 0x37, 0xff, 0xf9,
- 0x33, 0xe9, 0x6f, 0xdd, 0x86, 0x42, 0x07, 0x94, 0x35, 0x27, 0x2f, 0xf3,
- 0x8f, 0x25, 0xef, 0xf0, 0x9c, 0xbf, 0xf0, 0x37, 0xc9, 0x8a, 0x75, 0xfb,
- 0x07, 0x2f, 0xd9, 0xe0, 0x67, 0xc7, 0x2f, 0x2b, 0x9f, 0x1c, 0xba, 0x26,
- 0xe4, 0x78, 0xde, 0x28, 0xa1, 0x45, 0xc0, 0x21, 0x11, 0x7f, 0xff, 0xfe,
- 0x00, 0xf2, 0x6d, 0xfe, 0x96, 0x9f, 0xfe, 0x5b, 0x04, 0x7d, 0xdc, 0x41,
- 0xc5, 0x4e, 0x5f, 0xff, 0xef, 0x03, 0x07, 0x92, 0x67, 0x86, 0x3f, 0xe5,
- 0x88, 0x13, 0x97, 0xfc, 0xcc, 0x67, 0x26, 0x35, 0xf1, 0x91, 0xca, 0xd2,
- 0x28, 0xd8, 0xc5, 0x7f, 0xfd, 0xad, 0x67, 0xb7, 0xd4, 0xce, 0x5d, 0xfe,
- 0x0e, 0x52, 0x1f, 0xa8, 0x08, 0xeb, 0x13, 0xc3, 0xec, 0x74, 0x57, 0xec,
- 0x15, 0xa8, 0xc3, 0x97, 0xff, 0x77, 0x20, 0x66, 0x1c, 0xf6, 0xdc, 0xe5,
- 0xa5, 0xe3, 0xea, 0xe0, 0x28, 0xbf, 0xff, 0x07, 0x19, 0xcb, 0x83, 0xd1,
- 0xb9, 0xa4, 0xfa, 0x9c, 0xe5, 0xff, 0xfd, 0xe4, 0x9f, 0x03, 0xc9, 0x8f,
- 0x2d, 0x24, 0xee, 0xc3, 0x97, 0xfa, 0x77, 0x60, 0xc6, 0xa6, 0x39, 0x7f,
- 0xdf, 0x62, 0xbf, 0xb3, 0x39, 0x6b, 0x11, 0x24, 0x8b, 0xd7, 0xfd, 0x83,
- 0x3f, 0x2f, 0xdd, 0xe6, 0x39, 0x7f, 0xfd, 0x80, 0xd7, 0x29, 0xba, 0x05,
- 0x53, 0x05, 0x53, 0x97, 0xff, 0xcf, 0xe8, 0xd0, 0x18, 0x9b, 0xe5, 0xb9,
- 0x6c, 0xe5, 0xff, 0x6a, 0x78, 0x9e, 0x70, 0x6a, 0x73, 0x97, 0xfe, 0xe5,
- 0x37, 0x40, 0xaa, 0x60, 0xaa, 0x72, 0xff, 0x0f, 0x2d, 0x81, 0xa0, 0x34,
- 0x72, 0xb0, 0xfe, 0xc0, 0x87, 0x50, 0x8d, 0xad, 0xc2, 0xe6, 0xff, 0xf4,
- 0xfc, 0xb7, 0xd0, 0x72, 0xf6, 0xf7, 0x1a, 0x39, 0x7f, 0xfd, 0xd8, 0x9f,
- 0x90, 0xe7, 0x17, 0xef, 0x63, 0xe3, 0x97, 0xff, 0xfd, 0xf6, 0xd3, 0x1b,
- 0xe5, 0xdc, 0xf6, 0xf2, 0x7e, 0x58, 0x81, 0x39, 0x41, 0x46, 0x06, 0x2a,
- 0x5f, 0xf0, 0xe6, 0xb1, 0x78, 0x81, 0x39, 0x7f, 0x4f, 0xe9, 0x86, 0x18,
- 0x72, 0xff, 0xfe, 0xc9, 0xf1, 0x02, 0x20, 0xef, 0x28, 0x0b, 0xcd, 0xb3,
- 0x97, 0xfd, 0x8d, 0xe7, 0x53, 0x5d, 0x73, 0x95, 0x8a, 0x8b, 0x52, 0x31,
- 0x1e, 0x91, 0x39, 0xb6, 0xcb, 0xfc, 0xbb, 0x53, 0xb2, 0x6b, 0x02, 0xce,
- 0xac, 0x3b, 0x97, 0x1f, 0x57, 0xd0, 0x93, 0x42, 0xbd, 0x43, 0xbd, 0x8a,
- 0x9d, 0x3c, 0x15, 0x4d, 0xc6, 0x59, 0xe9, 0x4a, 0x97, 0xfb, 0xc3, 0x9e,
- 0xee, 0x4e, 0x72, 0xff, 0xcf, 0xae, 0xe7, 0xa0, 0x53, 0xf3, 0x97, 0xff,
- 0xc3, 0x93, 0xf2, 0xfc, 0x1e, 0xcc, 0x67, 0xed, 0x9c, 0xbe, 0x97, 0x92,
- 0x73, 0x97, 0xfd, 0x8d, 0xfd, 0x2d, 0xf2, 0xf2, 0x1c, 0xbf, 0xf4, 0xa3,
- 0x3f, 0xee, 0x60, 0xac, 0xe5, 0xff, 0xee, 0xa0, 0x87, 0x92, 0x8b, 0x1c,
- 0xee, 0x1c, 0xbf, 0xe7, 0xf6, 0xe6, 0x90, 0x07, 0xc7, 0x2b, 0x11, 0x85,
- 0x31, 0xef, 0xe9, 0x77, 0xfd, 0xd4, 0x64, 0x60, 0xfb, 0x67, 0x2f, 0xff,
- 0xf0, 0x3d, 0xa0, 0x4d, 0xcb, 0xd3, 0x74, 0x1f, 0xf9, 0x33, 0x80, 0xe5,
- 0xf4, 0x2e, 0x19, 0xc9, 0x1a, 0x6b, 0x31, 0x13, 0x7a, 0x85, 0x60, 0x2b,
- 0x33, 0xd1, 0xeb, 0xaa, 0x89, 0x1f, 0x04, 0x7a, 0x57, 0xff, 0xf6, 0xb1,
- 0xd9, 0xc9, 0x57, 0xfb, 0xb9, 0xde, 0xc7, 0x8e, 0x5f, 0x66, 0xa6, 0x91,
- 0xcb, 0xff, 0xca, 0xa7, 0xd2, 0xdf, 0x20, 0xa7, 0x18, 0x09, 0xcb, 0xfe,
- 0xc9, 0xa5, 0x9d, 0xce, 0x3b, 0x39, 0x7f, 0xfe, 0x0f, 0x41, 0xbe, 0x5d,
- 0x4f, 0x77, 0x35, 0x1c, 0x4e, 0x5f, 0xd9, 0xf0, 0xe6, 0x7e, 0x72, 0xb1,
- 0x10, 0xe2, 0xb5, 0x74, 0x33, 0x13, 0x56, 0x54, 0x8f, 0x4a, 0x03, 0x0c,
- 0x2b, 0x41, 0xcb, 0xe4, 0xd3, 0xfc, 0x72, 0xe4, 0xf2, 0x1b, 0x2d, 0x88,
- 0x5f, 0xfc, 0x9c, 0x50, 0x3c, 0xa2, 0x60, 0xbb, 0x67, 0x2f, 0xff, 0xff,
- 0x0a, 0x2b, 0xd7, 0x9b, 0x90, 0x83, 0x83, 0x96, 0x7d, 0x2c, 0x00, 0xff,
- 0xb3, 0x97, 0xee, 0xa4, 0x0c, 0xe7, 0x29, 0x88, 0xa8, 0xe3, 0x08, 0x1b,
- 0xe6, 0x22, 0x36, 0x72, 0xa0, 0xf3, 0x1c, 0xaa, 0xb6, 0x9a, 0xef, 0xa3,
- 0x3d, 0xa9, 0x27, 0x64, 0x91, 0xc4, 0x5e, 0x98, 0x01, 0x39, 0x50, 0xd9,
- 0x15, 0xe5, 0x27, 0x4d, 0x25, 0xe6, 0xe9, 0x7f, 0xb1, 0xda, 0x3c, 0xa3,
- 0x10, 0x14, 0xdf, 0xa0, 0x7c, 0x9c, 0x4e, 0x5f, 0x7b, 0x6f, 0xf9, 0xcb,
- 0xff, 0xba, 0x9c, 0x93, 0x40, 0x9d, 0xf4, 0xb3, 0x97, 0xc9, 0xd7, 0x9c,
- 0xe5, 0xf7, 0x18, 0xf4, 0x1c, 0xbf, 0x6f, 0x3c, 0x9b, 0x39, 0x7f, 0xf2,
- 0x7b, 0xa9, 0x98, 0x11, 0xc6, 0xce, 0x5e, 0xd2, 0x2a, 0x72, 0xff, 0xf8,
- 0x18, 0x9d, 0xc5, 0xf5, 0x39, 0x36, 0xc5, 0x9c, 0xbd, 0xec, 0x6c, 0xe5,
- 0xec, 0x04, 0xe2, 0x7d, 0xfe, 0x52, 0xbf, 0x03, 0x87, 0x17, 0xf1, 0xcb,
- 0xfb, 0xaf, 0x3f, 0x29, 0x78, 0xe5, 0xfc, 0xf3, 0x29, 0xb8, 0xc3, 0x97,
- 0xe7, 0xd0, 0xfc, 0x87, 0x2a, 0x11, 0x64, 0x85, 0x9d, 0x31, 0xf1, 0x75,
- 0xee, 0xb8, 0x9c, 0xa0, 0xab, 0x07, 0xc2, 0x85, 0x48, 0xd6, 0x8e, 0x84,
- 0x53, 0x11, 0xb0, 0x9d, 0xd0, 0x86, 0x11, 0x9e, 0x87, 0x2b, 0x67, 0x77,
- 0xc3, 0xe8, 0x61, 0xcb, 0xfd, 0xd8, 0x41, 0x7d, 0x2a, 0x72, 0xfe, 0x84,
- 0x17, 0xd2, 0xa7, 0x2f, 0xe7, 0xff, 0x5a, 0x4d, 0x72, 0x3d, 0xee, 0x99,
- 0x5f, 0xff, 0xfe, 0xe4, 0xc8, 0xcf, 0x72, 0xc9, 0x27, 0x11, 0xcd, 0xf2,
- 0x80, 0xbc, 0xdb, 0x39, 0x7f, 0x0a, 0xf9, 0x37, 0xbf, 0xce, 0x54, 0x91,
- 0x60, 0xef, 0xd4, 0x89, 0xcc, 0x7e, 0xfe, 0x08, 0x7b, 0xde, 0xdf, 0x90,
- 0xe5, 0xe9, 0xbf, 0xf8, 0xe5, 0xe8, 0x57, 0x92, 0xcd, 0xe7, 0xe3, 0x96,
- 0xfc, 0xe5, 0xfd, 0x1a, 0x9e, 0x35, 0x39, 0xcb, 0xff, 0x26, 0x37, 0xb0,
- 0x4c, 0x30, 0xc3, 0x97, 0x80, 0xfb, 0x39, 0x52, 0x44, 0x53, 0x0b, 0xd4,
- 0x3f, 0xbf, 0xff, 0x93, 0x5c, 0xb1, 0x30, 0x55, 0xea, 0x63, 0x31, 0x67,
- 0x2f, 0xff, 0xfc, 0xcd, 0xaf, 0xb0, 0xbf, 0xa4, 0x20, 0x0f, 0x24, 0x55,
- 0xc7, 0xf3, 0x97, 0xff, 0xfa, 0x7d, 0x43, 0x36, 0x08, 0xe5, 0x1a, 0x80,
- 0xf6, 0x18, 0x72, 0xb1, 0x1a, 0x88, 0xe3, 0x58, 0x9a, 0x7e, 0xa3, 0x2e,
- 0xbf, 0x7f, 0xb4, 0xf9, 0xb3, 0x97, 0xfe, 0xd6, 0x7d, 0xdf, 0xa1, 0x93,
- 0xc1, 0xcb, 0xff, 0xff, 0xda, 0xd2, 0x4f, 0xcb, 0xb9, 0xe1, 0x89, 0xbb,
- 0x93, 0xc7, 0xde, 0x02, 0xce, 0x5f, 0xff, 0xfd, 0x0a, 0xf6, 0x39, 0x0e,
- 0x01, 0x5e, 0x5f, 0x4b, 0x68, 0x2a, 0x44, 0xe7, 0x2f, 0xdf, 0x6d, 0x30,
- 0x4e, 0x56, 0x22, 0x80, 0x0f, 0x34, 0x89, 0x9f, 0xf6, 0x31, 0xdb, 0xff,
- 0xb4, 0x3f, 0x66, 0xc1, 0x30, 0xc3, 0x0e, 0x5f, 0xf2, 0x2b, 0xd8, 0x49,
- 0xe1, 0x53, 0x96, 0x92, 0x1f, 0xfe, 0xd1, 0x6f, 0xf8, 0x41, 0x30, 0xe7,
- 0x5f, 0xc7, 0x2f, 0xf7, 0x61, 0xb0, 0xf5, 0xd8, 0x72, 0xff, 0x99, 0x9b,
- 0xe5, 0x30, 0xc3, 0x0e, 0x5f, 0xff, 0xb7, 0x3b, 0xf2, 0x0f, 0x63, 0x5a,
- 0xce, 0x31, 0xf1, 0xca, 0x0a, 0x32, 0x98, 0x69, 0xe3, 0xbb, 0xff, 0xfe,
- 0x7d, 0x77, 0x3c, 0x98, 0x33, 0xee, 0x30, 0x43, 0xd8, 0x39, 0x7d, 0xee,
- 0x53, 0xe8, 0xe5, 0x7c, 0x88, 0x97, 0x63, 0xbf, 0xff, 0xf7, 0xd9, 0x38,
- 0x38, 0x39, 0x7d, 0x2f, 0x43, 0x7c, 0xb3, 0x5f, 0xff, 0x07, 0x2f, 0xff,
- 0x36, 0xe3, 0x3b, 0x00, 0x81, 0x41, 0x43, 0x97, 0xf4, 0xdf, 0x48, 0x11,
- 0xe3, 0x97, 0xff, 0xf4, 0xa3, 0x5f, 0x4b, 0x7c, 0xbb, 0x08, 0x2f, 0xa5,
- 0x4e, 0x5f, 0xd9, 0x2f, 0x0e, 0x48, 0xe5, 0xff, 0x75, 0xd8, 0x39, 0xd7,
- 0xf1, 0xcb, 0xbf, 0x6c, 0xe5, 0xf3, 0x4c, 0xd4, 0x1c, 0xb6, 0x68, 0xde,
- 0x71, 0x19, 0xa8, 0x4d, 0x57, 0xe3, 0x0e, 0xaf, 0x6c, 0xb3, 0xce, 0x77,
- 0xff, 0x67, 0xb7, 0xcb, 0x58, 0x9d, 0x80, 0x9c, 0xbf, 0xb3, 0xda, 0xd6,
- 0x48, 0xe5, 0x1c, 0xbf, 0x67, 0x47, 0x16, 0x72, 0xbf, 0x36, 0x22, 0x17,
- 0x53, 0x1f, 0xff, 0x97, 0xaf, 0x67, 0xde, 0x39, 0x78, 0x73, 0x7c, 0x8f,
- 0x01, 0xac, 0x8e, 0xff, 0xb1, 0x9d, 0x84, 0xd0, 0x1a, 0xce, 0x50, 0x59,
- 0x0b, 0x58, 0x52, 0xa9, 0x5a, 0xe3, 0x80, 0xfa, 0x15, 0x08, 0x4f, 0xa8,
- 0xc0, 0xbb, 0x0b, 0x97, 0x23, 0xdb, 0xd7, 0xa3, 0x9e, 0x02, 0x5f, 0x18,
- 0xc1, 0x14, 0x37, 0xbf, 0xe8, 0x60, 0xe0, 0x74, 0x93, 0x9c, 0xbf, 0xff,
- 0xcd, 0xf4, 0x11, 0xf7, 0x2d, 0x6a, 0x27, 0x17, 0x7d, 0x2a, 0x72, 0xff,
- 0x0e, 0x03, 0x15, 0x97, 0xe7, 0x29, 0xd1, 0x34, 0xdb, 0x35, 0x49, 0x1e,
- 0xb9, 0x0d, 0x2b, 0xca, 0xc6, 0x8e, 0x5f, 0xf8, 0x73, 0x96, 0xb3, 0xa3,
- 0x93, 0x1c, 0xbf, 0xff, 0xdd, 0x7f, 0xf7, 0xc8, 0x73, 0x88, 0xe6, 0xf1,
- 0x90, 0xb3, 0x95, 0x32, 0x2f, 0xc4, 0x77, 0x67, 0xf5, 0xc2, 0x99, 0xad,
- 0x11, 0x09, 0xcc, 0xa4, 0xed, 0x7d, 0x1e, 0xe3, 0xc3, 0x9a, 0xfe, 0xce,
- 0xa8, 0x3f, 0x7e, 0x72, 0xfe, 0xee, 0x0f, 0xbf, 0x01, 0xcb, 0xfe, 0x08,
- 0x63, 0xfe, 0x59, 0xf7, 0x8e, 0x5c, 0xcd, 0x9c, 0xbc, 0xfb, 0x43, 0x95,
- 0x06, 0xcb, 0xf1, 0x7a, 0x44, 0x48, 0x0b, 0x7d, 0xfe, 0xde, 0xe1, 0x27,
- 0x7f, 0x1c, 0xbf, 0x95, 0x1c, 0xdc, 0x68, 0xe5, 0xa5, 0x07, 0xc0, 0x03,
- 0x3b, 0x48, 0xe5, 0xf4, 0x31, 0xc2, 0x72, 0xa0, 0xd9, 0x08, 0x8d, 0xfe,
- 0xc9, 0xbb, 0x9e, 0x80, 0x9c, 0xbf, 0x87, 0xce, 0xc4, 0xf1, 0xcb, 0x48,
- 0xe5, 0x41, 0xbd, 0xf1, 0x65, 0xe1, 0x5c, 0x1c, 0xbf, 0xff, 0xfe, 0xee,
- 0x7b, 0x6f, 0x37, 0x21, 0xcf, 0xa5, 0x80, 0x9c, 0x70, 0x3d, 0x49, 0x8e,
- 0x5c, 0x05, 0x4e, 0x52, 0x22, 0xd3, 0x43, 0x7e, 0x84, 0x0d, 0xfe, 0xfd,
- 0x3d, 0xef, 0x63, 0x67, 0x2f, 0xec, 0x9c, 0x73, 0xed, 0x9c, 0xbf, 0xf8,
- 0x7f, 0x69, 0x9d, 0x48, 0x63, 0x84, 0xe5, 0xff, 0xff, 0xfa, 0x5b, 0xd8,
- 0x23, 0xc8, 0x1c, 0x19, 0xb9, 0x0e, 0x6a, 0x07, 0xdd, 0xce, 0x03, 0x97,
- 0xff, 0x7d, 0x2d, 0xe3, 0x3e, 0x8e, 0xf6, 0x0e, 0x57, 0xc8, 0xcc, 0xd4,
- 0x21, 0xad, 0xb3, 0x95, 0x89, 0xa5, 0x82, 0x31, 0x15, 0x0a, 0x6d, 0x39,
- 0xcb, 0xf6, 0xb3, 0xe9, 0x6c, 0xe5, 0xe5, 0xf7, 0x0e, 0x5b, 0x27, 0x3c,
- 0x5d, 0x14, 0xdf, 0xf7, 0xd1, 0xa9, 0xf9, 0x62, 0x04, 0xe5, 0xd3, 0x21,
- 0xca, 0xc4, 0x69, 0x0a, 0xb8, 0x0a, 0x38, 0x9e, 0x5f, 0xd9, 0xf4, 0xa3,
- 0xf8, 0x39, 0x7e, 0x1c, 0xeb, 0xf8, 0xe5, 0x7c, 0x7a, 0x8c, 0x2e, 0xbe,
- 0x4e, 0x39, 0xa3, 0x95, 0x07, 0x8d, 0xd2, 0x3b, 0xee, 0x4b, 0x9d, 0xb3,
- 0x97, 0xe9, 0xf9, 0x02, 0x26, 0x39, 0x7f, 0xff, 0xc3, 0x1f, 0xfd, 0x2d,
- 0x82, 0x3c, 0x38, 0x14, 0xcd, 0x4c, 0x72, 0x9d, 0x12, 0x7e, 0x2c, 0xa8,
- 0x5f, 0xea, 0x09, 0x86, 0x42, 0xfb, 0xe8, 0x40, 0xa2, 0xcc, 0xc3, 0xfd,
- 0x70, 0x78, 0x6a, 0x7e, 0x68, 0x26, 0xbb, 0x8d, 0xe7, 0xd1, 0x84, 0x82,
- 0x1a, 0xfc, 0x48, 0x54, 0x85, 0xd5, 0xfa, 0x49, 0xac, 0xf8, 0xe5, 0xed,
- 0xf7, 0x0e, 0x5f, 0xb3, 0x73, 0xe3, 0x67, 0x2b, 0xe3, 0xed, 0x98, 0xa3,
- 0xa3, 0x97, 0xff, 0xfb, 0xdb, 0xee, 0x7d, 0x8f, 0xf7, 0x20, 0xc4, 0xfc,
- 0x95, 0x54, 0xe5, 0xff, 0x62, 0xa3, 0x9e, 0xea, 0x36, 0x72, 0xa1, 0x14,
- 0x7a, 0x6a, 0xbf, 0xfe, 0x9f, 0x16, 0x1e, 0xa6, 0x2b, 0xc9, 0x50, 0x41,
- 0xcb, 0xff, 0xa4, 0x9e, 0xee, 0x6b, 0x59, 0xed, 0x9c, 0xbf, 0xee, 0x4a,
- 0x79, 0x38, 0xc0, 0xac, 0xe5, 0x22, 0x35, 0x66, 0x54, 0xea, 0x25, 0xff,
- 0xa5, 0xbf, 0x3c, 0xfc, 0x03, 0x9f, 0x1c, 0xbf, 0xd2, 0xec, 0x48, 0x0e,
- 0xa1, 0xcb, 0x47, 0xc7, 0xee, 0x28, 0x77, 0xfd, 0xd9, 0xd3, 0x07, 0xe9,
- 0x6c, 0xe5, 0xff, 0x7d, 0xdc, 0x58, 0xe0, 0x1a, 0xce, 0x5f, 0xff, 0x37,
- 0x8b, 0xde, 0x7a, 0x6c, 0x54, 0x73, 0xf3, 0x96, 0x94, 0x23, 0x23, 0x0e,
- 0x90, 0xf2, 0xfe, 0x4f, 0xbf, 0xd3, 0x84, 0xe5, 0xec, 0xd7, 0xe7, 0x2f,
- 0xdb, 0x4c, 0x1f, 0xce, 0x5b, 0x10, 0xf1, 0x36, 0x3b, 0x7e, 0x4f, 0xff,
- 0xcd, 0x1c, 0xae, 0xa3, 0x08, 0x5c, 0xf6, 0x4d, 0x7d, 0xc1, 0xec, 0xe9,
- 0xcb, 0x91, 0x87, 0x2f, 0xff, 0xfd, 0xf4, 0x9f, 0xee, 0x42, 0x0e, 0x0e,
- 0x59, 0xf4, 0xb0, 0x03, 0xfe, 0xce, 0x53, 0x11, 0x1b, 0xc0, 0x2d, 0x79,
- 0xa2, 0x70, 0xe7, 0x2b, 0x92, 0x65, 0x53, 0x97, 0xe4, 0x2c, 0x9a, 0x13,
- 0x5f, 0xff, 0xff, 0x7d, 0xb0, 0x47, 0xdc, 0xbb, 0x81, 0xe4, 0x38, 0x05,
- 0x79, 0x6f, 0xff, 0xd3, 0xc7, 0x2f, 0xff, 0xff, 0x36, 0x38, 0x16, 0x32,
- 0x3d, 0xbc, 0xf6, 0xf4, 0x98, 0xb1, 0xc0, 0x9c, 0xa8, 0x47, 0xfe, 0x42,
- 0x26, 0xfd, 0x03, 0xf3, 0xce, 0x72, 0xff, 0xff, 0xff, 0xd8, 0xb8, 0xec,
- 0x33, 0xd9, 0xbd, 0xc6, 0xb5, 0x03, 0x93, 0xe0, 0x36, 0x09, 0x86, 0x18,
- 0x72, 0xf0, 0x34, 0xa9, 0xca, 0x62, 0x2d, 0x9a, 0x42, 0x62, 0xfc, 0xff,
- 0xa8, 0xf3, 0x9c, 0xac, 0x3d, 0x44, 0x2a, 0xbc, 0x9f, 0xc1, 0xcb, 0xf8,
- 0x23, 0x9d, 0x7f, 0x1c, 0xbf, 0x7b, 0xe9, 0x26, 0x8e, 0x56, 0x1e, 0xae,
- 0xcb, 0x2a, 0x74, 0x49, 0x7e, 0xe3, 0x7b, 0x4e, 0xa1, 0xcb, 0xf4, 0x79,
- 0x89, 0xe3, 0x96, 0x9d, 0xcf, 0x10, 0x03, 0xb7, 0xfe, 0x85, 0x78, 0x01,
- 0x83, 0x32, 0x8c, 0x39, 0x7f, 0xff, 0xff, 0x95, 0x1c, 0xe4, 0x98, 0x2f,
- 0xee, 0xc4, 0xdc, 0x87, 0x3a, 0x9e, 0xd8, 0x16, 0x08, 0x39, 0x58, 0x8f,
- 0xcf, 0x8a, 0x00, 0x89, 0x7f, 0xec, 0xcf, 0xf7, 0xcb, 0x5b, 0x0e, 0xce,
- 0x5f, 0xed, 0x62, 0xfa, 0x9a, 0x98, 0xe5, 0xbc, 0x13, 0xf6, 0xc4, 0x2b,
- 0xfd, 0x8b, 0x4f, 0x68, 0x0c, 0x39, 0x58, 0x7b, 0x48, 0x4f, 0x79, 0x07,
- 0xc7, 0x2f, 0xe9, 0x6d, 0xd8, 0x0d, 0x9c, 0xa9, 0xcf, 0x25, 0xc6, 0xef,
- 0xd9, 0xde, 0xbc, 0x8e, 0x5f, 0xde, 0x4d, 0x4f, 0x8b, 0x39, 0x50, 0xcc,
- 0x15, 0x0c, 0x35, 0x32, 0x1e, 0xea, 0xc2, 0x9f, 0xe8, 0x77, 0xa4, 0xa1,
- 0xfd, 0x46, 0x8c, 0xc2, 0x6e, 0xc6, 0x64, 0xf0, 0xb2, 0x18, 0xd9, 0x77,
- 0x18, 0x00, 0x1a, 0x5a, 0x11, 0x70, 0x13, 0xde, 0x75, 0xe1, 0xca, 0x39,
- 0x7f, 0xdc, 0xbc, 0x38, 0xde, 0x26, 0xce, 0x53, 0x54, 0x78, 0xb3, 0x05,
- 0xd7, 0x0c, 0x88, 0x88, 0x60, 0xa3, 0x97, 0xf6, 0x32, 0x3a, 0xfd, 0x39,
- 0x77, 0x29, 0x8e, 0x57, 0x23, 0xc6, 0x09, 0x65, 0xff, 0xf7, 0xd2, 0x18,
- 0xe4, 0xc1, 0x85, 0x7c, 0x93, 0x9c, 0xa8, 0x46, 0x46, 0x28, 0xa1, 0x25,
- 0xfb, 0x5c, 0x87, 0x8b, 0x67, 0x2f, 0xba, 0xff, 0xc1, 0xcb, 0xdd, 0xcd,
- 0x1c, 0xa8, 0x3e, 0xb7, 0x2d, 0xe0, 0x22, 0xbf, 0xa7, 0x9a, 0x5c, 0x36,
- 0xa7, 0x39, 0x7e, 0x62, 0x07, 0x02, 0x72, 0xd3, 0x1c, 0xba, 0x18, 0x72,
- 0xde, 0x39, 0x5a, 0x34, 0xee, 0x2d, 0x41, 0x3d, 0x9e, 0x9c, 0xde, 0xd4,
- 0x4c, 0x72, 0xf6, 0xdf, 0xe3, 0x94, 0xe6, 0xeb, 0xc3, 0xb7, 0x4c, 0xe7,
- 0x2f, 0xe7, 0x6e, 0x3d, 0x93, 0x9c, 0xbf, 0x93, 0x5f, 0x48, 0x60, 0xe5,
- 0xfe, 0x0f, 0x63, 0xe9, 0x67, 0x8e, 0x57, 0x4f, 0x87, 0xc5, 0xb7, 0xfe,
- 0x69, 0x03, 0xed, 0x27, 0x1c, 0x09, 0xcb, 0x86, 0x63, 0x94, 0xd5, 0x2a,
- 0x53, 0x83, 0x7c, 0x84, 0x02, 0x2e, 0x30, 0x80, 0x45, 0xc1, 0x08, 0xf6,
- 0x84, 0x4a, 0x20, 0xdf, 0xe6, 0xf2, 0x42, 0x07, 0xd9, 0xcb, 0xf7, 0xcd,
- 0xb8, 0xfe, 0x72, 0xe1, 0x54, 0xe5, 0xb6, 0x87, 0x82, 0x02, 0xab, 0xff,
- 0xf3, 0x07, 0x17, 0xf7, 0x85, 0xfa, 0xc8, 0xcf, 0x1c, 0xbf, 0xfe, 0xc9,
- 0xdc, 0x57, 0xcb, 0x70, 0xc7, 0xfb, 0xc7, 0x2a, 0x11, 0x4d, 0xa5, 0x4b,
- 0xff, 0xec, 0xe2, 0xf2, 0xc1, 0x08, 0xc4, 0x83, 0xb3, 0x97, 0xff, 0xff,
- 0xc9, 0xd0, 0x31, 0x8f, 0x2e, 0x5c, 0x03, 0x8c, 0x85, 0xf2, 0x52, 0x79,
- 0xdf, 0xe3, 0x97, 0xff, 0xe8, 0xd4, 0x2f, 0x19, 0x0b, 0x92, 0x6c, 0x0c,
- 0x39, 0x50, 0xaa, 0x3a, 0x67, 0x4e, 0xc3, 0x34, 0x48, 0xbc, 0x9e, 0xd2,
- 0x11, 0x17, 0xf6, 0xb2, 0x15, 0x81, 0x39, 0x78, 0x5d, 0x87, 0x2e, 0xfe,
- 0x0e, 0x5f, 0xfd, 0xd6, 0x67, 0xd2, 0xdb, 0xc7, 0xd2, 0x39, 0x72, 0x93,
- 0x9c, 0xa4, 0x3d, 0xf1, 0x46, 0xa9, 0x23, 0x75, 0x0b, 0x04, 0x6f, 0xce,
- 0xd4, 0xd5, 0x42, 0x2c, 0x41, 0xa9, 0x84, 0x9f, 0x09, 0x0a, 0xf6, 0xad,
- 0xcf, 0x86, 0x94, 0xb1, 0xc2, 0xec, 0xf1, 0x3b, 0x63, 0x3c, 0x7f, 0xb2,
- 0x84, 0xb8, 0x67, 0xa0, 0x72, 0xb0, 0xd0, 0x56, 0x57, 0x6a, 0xe7, 0xcb,
- 0xfe, 0x9d, 0x7d, 0x49, 0x75, 0x13, 0x4a, 0x90, 0xd4, 0xf0, 0x53, 0x25,
- 0xe2, 0xf6, 0xb3, 0x92, 0x79, 0x71, 0x3f, 0xca, 0x3b, 0xe1, 0xdc, 0x86,
- 0x9b, 0x3d, 0xba, 0x42, 0xaf, 0xa9, 0xae, 0xe0, 0x8e, 0x4b, 0x8c, 0x3b,
- 0xdb, 0x84, 0xc3, 0x49, 0x50, 0x6a, 0x4b, 0x1c, 0xe0, 0x8d, 0x06, 0xff,
- 0xfe, 0x02, 0xf9, 0xfd, 0xed, 0x46, 0x7d, 0xc3, 0x05, 0xdd, 0x53, 0x95,
- 0xcd, 0x57, 0xc2, 0x4a, 0x93, 0xbf, 0x9d, 0x3d, 0xb4, 0x13, 0x97, 0x93,
- 0x58, 0x72, 0x9a, 0xcf, 0x1b, 0x65, 0x77, 0xed, 0x2d, 0xdd, 0x66, 0x8a,
- 0x75, 0x76, 0x7c, 0x72, 0xff, 0xf0, 0x00, 0x28, 0x31, 0xd4, 0x66, 0x6c,
- 0xe5, 0xb9, 0xc2, 0x2d, 0xf0, 0x97, 0xe3, 0x46, 0x0b, 0xdf, 0xfc, 0x9a,
- 0xe6, 0xd1, 0xe7, 0xf6, 0xdf, 0xf3, 0x97, 0xed, 0x2d, 0xdd, 0x66, 0x8a,
- 0x8d, 0x7f, 0xe7, 0x97, 0x3c, 0xd2, 0xdd, 0xd6, 0x68, 0x9a, 0x17, 0xff,
- 0x87, 0x26, 0x93, 0xea, 0x43, 0x9c, 0x5c, 0xe5, 0xf0, 0xc6, 0x7c, 0x72,
- 0xb1, 0x1d, 0x6c, 0x34, 0xda, 0x67, 0x92, 0xaf, 0xf2, 0x8f, 0xc7, 0x9f,
- 0x92, 0x73, 0x95, 0xcc, 0xfd, 0x60, 0xf2, 0xfd, 0xa5, 0xbb, 0xac, 0xd1,
- 0x57, 0xaf, 0xec, 0xe3, 0x03, 0xd0, 0x1c, 0xbf, 0x90, 0x21, 0x8d, 0x41,
- 0xcb, 0xff, 0xfb, 0xef, 0xc4, 0x0c, 0x50, 0x21, 0x8f, 0xd9, 0x19, 0xe3,
- 0x96, 0xe7, 0x88, 0xed, 0xd1, 0xa7, 0x4b, 0x94, 0x2c, 0xbf, 0x69, 0x6e,
- 0xeb, 0x34, 0x56, 0xcb, 0xfe, 0x97, 0x3c, 0xd2, 0xdd, 0xd6, 0x68, 0x90,
- 0x56, 0xe7, 0x87, 0xf6, 0xe6, 0x97, 0xff, 0x73, 0x79, 0x73, 0xcd, 0x2d,
- 0xdd, 0x66, 0x89, 0x0d, 0x7f, 0xed, 0xf3, 0xcf, 0x20, 0x70, 0x66, 0x39,
- 0x79, 0xdd, 0x67, 0x8c, 0x0d, 0x50, 0x7d, 0x0b, 0x40, 0xbb, 0xad, 0x67,
- 0x2f, 0xfd, 0x2e, 0xc7, 0xb6, 0xd4, 0xed, 0xab, 0x13, 0x97, 0xde, 0xf6,
- 0x70, 0x1c, 0xbf, 0xfd, 0xc2, 0xdc, 0x2c, 0xd4, 0xf6, 0x18, 0x2f, 0xd4,
- 0xd1, 0xcb, 0x7c, 0x72, 0xe4, 0x13, 0x97, 0xfb, 0x19, 0x8b, 0x17, 0x6b,
- 0x39, 0x7f, 0x40, 0x63, 0xce, 0x13, 0x97, 0xbb, 0x9b, 0x39, 0x67, 0x39,
- 0x41, 0x35, 0x9e, 0x1c, 0xa0, 0xa3, 0x52, 0x61, 0x2d, 0x8a, 0xf8, 0xd1,
- 0x45, 0x8b, 0xef, 0x6d, 0x38, 0x9c, 0xbf, 0xf9, 0x06, 0x78, 0x55, 0x4f,
- 0xff, 0x8f, 0x8e, 0x5f, 0x60, 0xff, 0xb3, 0x97, 0xff, 0x0b, 0xb7, 0xd4,
- 0x79, 0x79, 0x27, 0x39, 0x7d, 0x3e, 0xfe, 0x43, 0x95, 0x88, 0x8a, 0xd1,
- 0x16, 0xd1, 0x2f, 0xce, 0x15, 0x20, 0x4e, 0x5f, 0xfb, 0x5e, 0x50, 0x5d,
- 0x78, 0x2b, 0x39, 0x7c, 0xb7, 0x75, 0x9a, 0x2c, 0x45, 0xfb, 0x5a, 0x71,
- 0xf1, 0xcb, 0xe7, 0x0f, 0x40, 0x72, 0xf2, 0x23, 0x67, 0x2f, 0x00, 0x64,
- 0x72, 0xff, 0x2e, 0x33, 0x5f, 0xff, 0xe3, 0x95, 0x3a, 0x69, 0x38, 0x4f,
- 0xa3, 0xe6, 0x17, 0x74, 0x9c, 0x48, 0xbc, 0x38, 0x01, 0xcb, 0xf6, 0x6a,
- 0x05, 0x53, 0x96, 0x43, 0x96, 0x43, 0x96, 0x92, 0xa6, 0x83, 0xf1, 0x0b,
- 0xf2, 0x8d, 0x33, 0x50, 0x72, 0xfd, 0xef, 0x40, 0xce, 0x72, 0xf6, 0xe0,
- 0x4e, 0x54, 0x1f, 0x6e, 0x15, 0x21, 0x45, 0x2a, 0x8c, 0x2e, 0xc2, 0x5a,
- 0xff, 0xe8, 0xcd, 0xe0, 0x85, 0x3f, 0x81, 0x39, 0x78, 0x62, 0x73, 0x94,
- 0x27, 0xba, 0x04, 0x1b, 0xe8, 0xd4, 0x30, 0xe5, 0x48, 0xf0, 0xb6, 0x43,
- 0x79, 0x8f, 0xe3, 0x97, 0xff, 0xde, 0xcf, 0xa4, 0x20, 0xf3, 0xa0, 0xc0,
- 0x4e, 0x5c, 0x9f, 0x9c, 0xbc, 0xf1, 0xf1, 0xca, 0xd2, 0x27, 0x7c, 0x38,
- 0xd1, 0x3b, 0x80, 0x5e, 0xff, 0xfc, 0xfa, 0x93, 0x06, 0x35, 0x01, 0xc9,
- 0xa3, 0xa7, 0x2f, 0xb8, 0x81, 0xf6, 0x72, 0xc8, 0x72, 0xa4, 0x88, 0x84,
- 0x54, 0x98, 0x92, 0xff, 0x83, 0xdc, 0x66, 0x3e, 0xa7, 0x39, 0x7e, 0xf7,
- 0x9e, 0x5b, 0x39, 0x7f, 0xe0, 0x67, 0xc1, 0xe3, 0xdc, 0x79, 0x8e, 0x57,
- 0xc7, 0xd5, 0xc4, 0xa2, 0xd2, 0x39, 0x7d, 0x98, 0xde, 0xce, 0x54, 0x1b,
- 0x3f, 0x08, 0xdc, 0x01, 0x39, 0x50, 0x99, 0x8e, 0x42, 0x8f, 0x4b, 0x1b,
- 0x20, 0xbf, 0xdb, 0x53, 0x35, 0x99, 0x31, 0xcb, 0xfe, 0x7f, 0x6c, 0x20,
- 0x7d, 0x48, 0xe5, 0xf8, 0x7c, 0x20, 0x9c, 0xe5, 0x42, 0x25, 0x44, 0xd0,
- 0x07, 0x37, 0xf6, 0xa5, 0xfe, 0x64, 0xc7, 0x2f, 0x9e, 0x11, 0xa1, 0xca,
- 0xc3, 0xd1, 0xd1, 0x7d, 0xf4, 0x94, 0xec, 0x1c, 0xbd, 0xa8, 0x91, 0xca,
- 0x73, 0x7f, 0xc4, 0x8e, 0xfe, 0x86, 0x62, 0x6a, 0x63, 0x97, 0xca, 0x47,
- 0x06, 0xce, 0x5f, 0xb0, 0x3d, 0x8e, 0x9c, 0xbe, 0xd2, 0x36, 0xd6, 0x72,
- 0x84, 0xf3, 0x76, 0x4f, 0x7f, 0xfb, 0x48, 0xc8, 0xfb, 0xb0, 0x11, 0x76,
- 0xb3, 0x94, 0x14, 0x70, 0x6d, 0xcf, 0xc4, 0x35, 0x09, 0xdf, 0xa3, 0x07,
- 0x48, 0x9e, 0x30, 0xdb, 0xfb, 0xe5, 0xf6, 0x3e, 0xe0, 0x39, 0x7f, 0x20,
- 0xbb, 0x23, 0xa7, 0x2f, 0xff, 0x43, 0x22, 0x41, 0x18, 0xeb, 0xe6, 0x8e,
- 0x51, 0xca, 0x91, 0xe9, 0x34, 0x47, 0xbd, 0xec, 0xfc, 0xe5, 0xfc, 0xc4,
- 0xde, 0xd0, 0x27, 0x2f, 0x3e, 0x95, 0x39, 0x40, 0x3c, 0xa6, 0xcb, 0x6f,
- 0xf2, 0xc7, 0x38, 0x8e, 0x6c, 0xe5, 0xfe, 0x6b, 0xe4, 0xa4, 0x0b, 0xaa,
- 0x72, 0xff, 0x49, 0xf0, 0x73, 0xdb, 0x39, 0x58, 0x7d, 0x5f, 0x1c, 0xdf,
- 0xfb, 0x3e, 0x97, 0x63, 0x6a, 0xf6, 0x0e, 0x54, 0x2a, 0x5d, 0x91, 0x9f,
- 0xcf, 0xb3, 0x12, 0x69, 0x9f, 0xa4, 0x63, 0x09, 0xde, 0x02, 0x2b, 0x34,
- 0x39, 0x74, 0xb6, 0x72, 0xcf, 0x23, 0x55, 0xf0, 0x9d, 0xf7, 0x90, 0x5b,
- 0x29, 0x60, 0x1c, 0xb4, 0x61, 0xb3, 0xe9, 0x15, 0xff, 0x38, 0xfb, 0x7f,
- 0x6d, 0xda, 0xce, 0x53, 0xa2, 0xef, 0xf5, 0xa0, 0x12, 0xdf, 0xf9, 0x80,
- 0x9b, 0xed, 0xc4, 0xc9, 0xc4, 0xe5, 0xfe, 0xec, 0x30, 0x63, 0xe9, 0x1c,
- 0xbf, 0xba, 0x9b, 0xd6, 0xb0, 0xe5, 0xff, 0x93, 0x3d, 0xbd, 0x66, 0xe3,
- 0xe3, 0x97, 0xfe, 0x86, 0xd4, 0x9f, 0x78, 0xc8, 0x6b, 0x39, 0x73, 0xb6,
- 0x72, 0x82, 0x8f, 0x95, 0x99, 0xf4, 0xb7, 0xc7, 0xdc, 0x51, 0x2e, 0xcd,
- 0x9c, 0xa8, 0x4e, 0x7f, 0x23, 0x3d, 0x51, 0x32, 0xff, 0xee, 0xba, 0x7a,
- 0x58, 0xa8, 0xe7, 0xe7, 0x2f, 0x77, 0x1b, 0x39, 0x7f, 0x98, 0x9b, 0xea,
- 0x42, 0x1c, 0xbf, 0x0c, 0xd1, 0xd8, 0x39, 0x7e, 0xfd, 0xf8, 0xe0, 0x4e,
- 0x5f, 0xb3, 0xbf, 0x3b, 0x59, 0xcb, 0xef, 0xf7, 0x02, 0x72, 0xff, 0x6b,
- 0xae, 0x9b, 0x4e, 0x27, 0x2e, 0x55, 0x0e, 0x54, 0x1f, 0x6e, 0x11, 0x39,
- 0xa5, 0xff, 0xdd, 0xc1, 0x17, 0xf7, 0x29, 0x43, 0x0e, 0x52, 0x27, 0xd6,
- 0xd6, 0x88, 0xc1, 0xd7, 0x31, 0xfc, 0x9c, 0x4a, 0xb7, 0x09, 0x8f, 0x16,
- 0x5f, 0xcd, 0xc6, 0xb4, 0xf3, 0x1c, 0xbf, 0xe0, 0xc2, 0xd4, 0xff, 0xf8,
- 0xf8, 0xe5, 0xff, 0x3e, 0xb1, 0x88, 0xd2, 0x18, 0x72, 0x96, 0x7e, 0xc0,
- 0x3d, 0xbe, 0xcd, 0x66, 0xce, 0x5f, 0x7a, 0x3e, 0x91, 0xcb, 0xf9, 0x3f,
- 0x68, 0x29, 0xf9, 0xca, 0x9c, 0xf4, 0xf4, 0x47, 0x7c, 0x00, 0xf5, 0x0e,
- 0x5e, 0xf6, 0x28, 0x72, 0xa1, 0x39, 0xdc, 0x85, 0x2f, 0x48, 0x9d, 0xd3,
- 0x64, 0x7c, 0x04, 0x57, 0xf0, 0xc4, 0xa3, 0x8c, 0x1c, 0xba, 0x3f, 0x39,
- 0x7f, 0x71, 0xd3, 0xc2, 0x34, 0x39, 0x72, 0x4e, 0x72, 0xd8, 0x72, 0x91,
- 0x13, 0x73, 0x16, 0xb0, 0x5d, 0xcc, 0x04, 0x5e, 0xfa, 0x7f, 0x62, 0xce,
- 0x5f, 0xe7, 0x55, 0x4e, 0xf6, 0x24, 0x72, 0x9c, 0xf6, 0x1a, 0x11, 0xdf,
- 0xfb, 0xb8, 0x10, 0xa7, 0xd9, 0xf7, 0x8e, 0x5f, 0xdc, 0x82, 0xa3, 0xeb,
- 0x47, 0x2a, 0x73, 0xf1, 0x0a, 0x05, 0xfe, 0x0e, 0x7b, 0xb0, 0x2b, 0x39,
- 0x7c, 0xf0, 0x8d, 0x0e, 0x5f, 0xf0, 0x79, 0x66, 0xe3, 0x35, 0xf9, 0xcb,
- 0xdd, 0x53, 0x67, 0x2b, 0x0f, 0x65, 0xce, 0xef, 0xf2, 0x07, 0xc2, 0xff,
- 0x6c, 0xe5, 0xfe, 0xf6, 0xd3, 0xec, 0xfb, 0xc7, 0x2e, 0x9e, 0x0e, 0x54,
- 0x1f, 0xfb, 0x99, 0x80, 0xd6, 0xa1, 0x39, 0xc9, 0xc8, 0xc2, 0x65, 0xd7,
- 0xb1, 0x84, 0xfd, 0x35, 0x2d, 0xd6, 0x6b, 0x56, 0x35, 0xc3, 0x24, 0xb5,
- 0x02, 0x58, 0x8c, 0xc2, 0x74, 0xc9, 0x12, 0x06, 0x1a, 0x79, 0x1b, 0xc2,
- 0xae, 0x2b, 0x8c, 0x27, 0xe8, 0x64, 0x24, 0x2f, 0xe6, 0x86, 0x56, 0xa3,
- 0x61, 0x64, 0x35, 0xbb, 0x28, 0xf9, 0xe5, 0x4f, 0x7f, 0x1b, 0x00, 0xc7,
- 0x9f, 0xb9, 0x44, 0x3e, 0x94, 0x2a, 0x08, 0x7c, 0x34, 0x85, 0x02, 0x92,
- 0x8c, 0x2f, 0xdc, 0x0e, 0xb8, 0xd1, 0xcb, 0xff, 0x24, 0x7b, 0xae, 0xae,
- 0x0f, 0xe7, 0x2f, 0xff, 0x3e, 0xb9, 0x3f, 0xb9, 0x7b, 0xe5, 0xa0, 0x9c,
- 0xae, 0xa2, 0x33, 0x89, 0xf5, 0xfd, 0x9e, 0x84, 0x66, 0xce, 0x5f, 0xe0,
- 0xc4, 0xb3, 0x59, 0xb3, 0x97, 0xff, 0xd9, 0xad, 0x02, 0x5a, 0xc8, 0xfa,
- 0x48, 0xc3, 0x97, 0xb6, 0xa6, 0xce, 0x5f, 0xff, 0x67, 0xd2, 0xf0, 0x27,
- 0xe7, 0xd7, 0x62, 0x6c, 0xe5, 0xff, 0xbd, 0x0c, 0xdc, 0x24, 0xef, 0xe3,
- 0x97, 0xf3, 0xb5, 0xbe, 0x7d, 0xe3, 0x95, 0xf1, 0xf7, 0x74, 0xfa, 0xff,
- 0x3e, 0x05, 0x3e, 0x17, 0x39, 0x58, 0x7a, 0x80, 0x23, 0xb9, 0xb1, 0x39,
- 0x7b, 0xc3, 0x07, 0x2e, 0xef, 0x38, 0x56, 0x21, 0x90, 0xb6, 0x98, 0x95,
- 0x85, 0x9d, 0x32, 0x75, 0x01, 0x1e, 0xdc, 0x62, 0xcd, 0x90, 0xa8, 0x2f,
- 0x5c, 0xd7, 0x62, 0xa2, 0x73, 0x96, 0xfe, 0xcd, 0x2d, 0xdd, 0x66, 0x8b,
- 0x35, 0x7f, 0xf6, 0xba, 0xfc, 0xd8, 0x09, 0xba, 0x81, 0x39, 0x7f, 0xe8,
- 0xd7, 0xfe, 0xdf, 0x71, 0x02, 0x72, 0xfd, 0x93, 0x4a, 0x3e, 0x39, 0x7c,
- 0x82, 0xf3, 0x9c, 0xae, 0xa2, 0x24, 0x4f, 0xf6, 0x53, 0x6e, 0x9c, 0xba,
- 0x3a, 0x72, 0xfe, 0x1c, 0xe3, 0xd7, 0x91, 0xcb, 0x73, 0x9c, 0xf5, 0x7a,
- 0x23, 0xe1, 0x6a, 0xe6, 0x8b, 0xce, 0x08, 0x42, 0x57, 0x34, 0xfc, 0xd0,
- 0xe5, 0xe3, 0x8d, 0xbe, 0x46, 0x29, 0xa3, 0x97, 0xd0, 0xbc, 0xe9, 0xcb,
- 0xe4, 0x1d, 0x00, 0xe5, 0xfe, 0x8e, 0x2a, 0x78, 0x63, 0xf3, 0x97, 0xca,
- 0x0e, 0x6c, 0xe5, 0xcc, 0xe7, 0x08, 0xbd, 0x42, 0x39, 0x88, 0x7a, 0x42,
- 0xe6, 0xd7, 0x62, 0x1c, 0xbb, 0x02, 0x72, 0xff, 0xcf, 0x2e, 0x79, 0xa5,
- 0xbb, 0xac, 0xd1, 0x40, 0x2f, 0xf2, 0x32, 0x1a, 0xfb, 0x93, 0x9c, 0xb7,
- 0x39, 0x22, 0xb7, 0x05, 0x58, 0x2d, 0xd4, 0xcb, 0xa4, 0xc3, 0x97, 0xcf,
- 0xaf, 0xa4, 0x72, 0xfd, 0x1f, 0x79, 0xf4, 0x72, 0xfd, 0xed, 0xc9, 0x3f,
- 0x39, 0x52, 0x44, 0x5e, 0x0b, 0xa1, 0x1b, 0x94, 0x5f, 0xb9, 0xe4, 0xd1,
- 0x23, 0x97, 0xfd, 0x1e, 0xee, 0x33, 0x35, 0x87, 0x2f, 0xa6, 0xcc, 0x59,
- 0xcb, 0xf7, 0x95, 0x7d, 0xf3, 0xd1, 0xec, 0xa8, 0x6f, 0x52, 0x46, 0x33,
- 0x70, 0x83, 0xae, 0x69, 0x94, 0xc4, 0x60, 0x17, 0x03, 0xa7, 0x2f, 0xff,
- 0xdc, 0x63, 0xa8, 0x1e, 0xc4, 0xb6, 0xfd, 0x4d, 0x9c, 0xbf, 0xb7, 0x0c,
- 0x18, 0x98, 0xe5, 0xba, 0x72, 0xf2, 0x83, 0x31, 0xcb, 0x7b, 0x0d, 0x7f,
- 0xe2, 0x37, 0x64, 0xe7, 0x2b, 0x0d, 0xf0, 0x93, 0xd2, 0x26, 0x1f, 0xfa,
- 0xb0, 0xc2, 0x6a, 0xee, 0x5b, 0x39, 0x78, 0x01, 0xc3, 0x97, 0xfb, 0x35,
- 0xe1, 0x86, 0x6c, 0xe5, 0x9a, 0x1c, 0xa4, 0x3e, 0x1e, 0x8e, 0x7e, 0x65,
- 0x7c, 0xb7, 0x75, 0x9a, 0x2d, 0xf5, 0xe6, 0x8f, 0xe3, 0x97, 0xf2, 0x9e,
- 0x75, 0xbe, 0x8e, 0x56, 0x8f, 0xe9, 0x85, 0xdf, 0x8f, 0x5c, 0xab, 0x67,
- 0x2f, 0xb0, 0x52, 0x63, 0x97, 0xbb, 0x1a, 0x39, 0x7e, 0xea, 0x6b, 0xae,
- 0x72, 0xff, 0xf7, 0x62, 0x7f, 0x67, 0x47, 0x3d, 0xd4, 0x39, 0x79, 0x98,
- 0x13, 0x96, 0x61, 0xcb, 0xfe, 0xec, 0x4e, 0x1c, 0x6f, 0x7c, 0xe1, 0x17,
- 0x38, 0x39, 0x31, 0x3b, 0xa4, 0xa8, 0x39, 0x7e, 0xf4, 0xb6, 0xa6, 0xce,
- 0x5e, 0xdf, 0x42, 0x72, 0xfc, 0xa7, 0x86, 0x3f, 0x39, 0x4c, 0x3c, 0x6e,
- 0x23, 0xb7, 0xff, 0x7b, 0x69, 0xb8, 0x1c, 0xf7, 0x50, 0xe5, 0xe1, 0xce,
- 0x9c, 0xa6, 0x1e, 0xef, 0x14, 0x2b, 0xf0, 0x61, 0xac, 0x0c, 0x39, 0x7f,
- 0xcf, 0xb8, 0xc1, 0x0f, 0x60, 0xe5, 0xff, 0xd8, 0xcd, 0x67, 0xdd, 0x17,
- 0x6b, 0x9c, 0xe5, 0xdb, 0xde, 0x8f, 0xf8, 0x4d, 0xaa, 0x13, 0x7b, 0xc8,
- 0x40, 0xa1, 0x23, 0xc2, 0xa6, 0xf9, 0xd0, 0x7c, 0x72, 0xfd, 0xfe, 0xfd,
- 0x0c, 0x39, 0x7b, 0x51, 0xe3, 0x97, 0xf4, 0xce, 0x1e, 0xa3, 0x0e, 0x5f,
- 0xde, 0x4c, 0x0c, 0x30, 0xe5, 0x78, 0xf6, 0x9b, 0x2e, 0xbb, 0x62, 0x72,
- 0xfe, 0xfb, 0x70, 0xbc, 0x61, 0xca, 0x84, 0xc1, 0xb4, 0x52, 0xee, 0xdb,
- 0x23, 0x00, 0xb5, 0xfc, 0x93, 0x40, 0x8c, 0x1c, 0xbe, 0xea, 0xa1, 0x61,
- 0xcb, 0x48, 0xe5, 0xfe, 0xff, 0xf0, 0x6d, 0xaf, 0x3e, 0x39, 0x58, 0x79,
- 0x6e, 0x23, 0x58, 0x88, 0xf1, 0x6f, 0xbf, 0xde, 0x4d, 0xba, 0xde, 0x73,
- 0x94, 0xd5, 0xb2, 0x32, 0x22, 0x32, 0x69, 0x1a, 0x85, 0xeb, 0x21, 0x53,
- 0xf1, 0x82, 0x0c, 0xcd, 0x0d, 0xad, 0x3d, 0xf6, 0x3e, 0xbf, 0xd1, 0x06,
- 0x32, 0x6d, 0xa4, 0xfa, 0x17, 0x4a, 0x10, 0xdf, 0xcf, 0xf7, 0x36, 0x3f,
- 0x8e, 0x57, 0x34, 0xc9, 0x86, 0x1e, 0xd7, 0xf0, 0x79, 0xef, 0xdb, 0xf8,
- 0xe5, 0xcd, 0x53, 0x56, 0x72, 0xf3, 0x1f, 0xe3, 0x97, 0xbf, 0x7e, 0x9c,
- 0xbb, 0x8a, 0x1c, 0xbe, 0xd6, 0xb1, 0x43, 0x97, 0xfd, 0x12, 0x6d, 0xf5,
- 0xac, 0x50, 0xe5, 0xfb, 0x73, 0xe3, 0x7c, 0xda, 0x94, 0x68, 0x41, 0x0e,
- 0x0e, 0xcc, 0x3a, 0xe3, 0x02, 0x47, 0x50, 0x9b, 0xe2, 0x46, 0x05, 0x7f,
- 0xff, 0xdc, 0x3a, 0x78, 0x0f, 0x3f, 0x3c, 0x97, 0x63, 0x59, 0x82, 0xa9,
- 0xcb, 0xff, 0xff, 0xc8, 0xb7, 0xd3, 0xf6, 0x59, 0xec, 0x0e, 0xdd, 0x99,
- 0xa9, 0xe3, 0xe3, 0x97, 0xed, 0x2d, 0xdd, 0x66, 0x8a, 0x51, 0x7f, 0xfc,
- 0xfe, 0x1c, 0x9f, 0x51, 0xd4, 0xee, 0x68, 0xe5, 0xe7, 0x97, 0x38, 0x47,
- 0xce, 0x3b, 0xfe, 0x69, 0x7f, 0xd2, 0xe7, 0x9a, 0x5b, 0xba, 0xcd, 0x12,
- 0x72, 0x98, 0x88, 0x97, 0x42, 0xbf, 0xda, 0xe7, 0x9d, 0x89, 0x9c, 0xe5,
- 0x73, 0x3d, 0x77, 0x22, 0xa8, 0x86, 0x8c, 0x34, 0xf3, 0xc5, 0x52, 0x94,
- 0x44, 0x1c, 0x47, 0x4a, 0xe4, 0x65, 0x4a, 0xa2, 0x2e, 0x3a, 0xa4, 0x8c,
- 0x41, 0xae, 0x18, 0x13, 0x14, 0x6a, 0x17, 0x8c, 0xb4, 0x0f, 0x1d, 0x94,
- 0x44, 0xf0, 0xf4, 0xfe, 0x30, 0x31, 0x8f, 0xe3, 0x74, 0xa1, 0x9f, 0x47,
- 0x4c, 0x02, 0x8e, 0x32, 0x91, 0xaf, 0xda, 0x5b, 0xba, 0xcd, 0x10, 0xfa,
- 0xff, 0xcf, 0x2e, 0x79, 0xa5, 0xbb, 0xac, 0xd1, 0x29, 0xad, 0xcf, 0x11,
- 0x00, 0xc3, 0x4b, 0xfd, 0xcf, 0x34, 0xb7, 0x75, 0x9a, 0x22, 0x75, 0xf9,
- 0x3d, 0xb0, 0x30, 0xe5, 0xee, 0xc4, 0xc7, 0x2a, 0x63, 0xc5, 0xe9, 0x45,
- 0xff, 0xee, 0x14, 0xab, 0x6d, 0x73, 0x87, 0x86, 0xe5, 0xcb, 0xad, 0x0e,
- 0x5f, 0xb4, 0xb7, 0x75, 0x9a, 0x23, 0x15, 0xff, 0xfc, 0x01, 0x75, 0x79,
- 0x79, 0x58, 0x19, 0x67, 0x51, 0x87, 0x2f, 0xa1, 0x8b, 0xfc, 0xe5, 0xff,
- 0xf4, 0xa7, 0xe1, 0x50, 0xd5, 0xce, 0xbd, 0x72, 0xe5, 0xd6, 0x87, 0x2b,
- 0xa8, 0x88, 0xfc, 0x8e, 0xfe, 0xcf, 0x46, 0x7d, 0xe3, 0x97, 0xfe, 0xf2,
- 0xb0, 0x32, 0xce, 0xa3, 0x0e, 0x5f, 0xf2, 0xb0, 0x32, 0xce, 0xa3, 0x0e,
- 0x5f, 0x00, 0x5d, 0x5e, 0x47, 0xed, 0xe3, 0xeb, 0xf6, 0xbf, 0x4e, 0xc1,
- 0xca, 0x61, 0xf1, 0x80, 0xee, 0xf9, 0x3e, 0x93, 0x56, 0x72, 0xfd, 0xca,
- 0x61, 0x80, 0x9c, 0xb7, 0x38, 0x56, 0x7d, 0x22, 0x3c, 0x64, 0x61, 0xa7,
- 0x61, 0xca, 0x24, 0x9b, 0x8c, 0x1b, 0xc4, 0x4d, 0x0a, 0x2f, 0xff, 0x73,
- 0x63, 0xcb, 0x9e, 0x69, 0x6e, 0xeb, 0x34, 0x4f, 0x2b, 0xe8, 0xe3, 0x1d,
- 0x39, 0x7d, 0x03, 0x2d, 0x9c, 0xbf, 0x75, 0x07, 0x38, 0x9c, 0xad, 0x1f,
- 0x67, 0xe4, 0x6a, 0x10, 0xdf, 0x01, 0xf5, 0x23, 0x97, 0xe7, 0x0f, 0x63,
- 0x67, 0x2d, 0xcc, 0x27, 0x92, 0x24, 0x55, 0xcd, 0x14, 0x6d, 0xbd, 0x54,
- 0x2f, 0x07, 0xce, 0x55, 0x29, 0x78, 0x9d, 0x84, 0x97, 0xa3, 0x69, 0xbf,
- 0x69, 0x6e, 0xeb, 0x34, 0x44, 0x0b, 0xff, 0x3c, 0xb9, 0xe6, 0x96, 0xee,
- 0xb3, 0x44, 0xa8, 0xbf, 0xb4, 0x0e, 0xc0, 0xac, 0xe5, 0xfc, 0xb4, 0xce,
- 0x0e, 0xc1, 0xca, 0x83, 0xdc, 0xc2, 0xdb, 0x73, 0xc4, 0x7e, 0x30, 0xd0,
- 0x61, 0x51, 0x7e, 0xd2, 0xdd, 0xd6, 0x68, 0x8a, 0x17, 0xa3, 0xfc, 0x39,
- 0x6e, 0x78, 0x7a, 0x0a, 0x1a, 0x5f, 0xee, 0x79, 0xa5, 0xbb, 0xac, 0xd1,
- 0x19, 0x2f, 0xda, 0x5b, 0xba, 0xcd, 0x13, 0x2a, 0xfd, 0x2c, 0xf3, 0xac,
- 0xe5, 0xfb, 0x9b, 0x1e, 0x5c, 0xf0, 0xf6, 0xfe, 0x34, 0xbf, 0x69, 0x6e,
- 0xeb, 0x34, 0x54, 0x8b, 0x09, 0xcb, 0x28, 0x72, 0xdc, 0xf0, 0xf5, 0x9a,
- 0xcd, 0x00, 0x21, 0x7f, 0xb9, 0xe6, 0x96, 0xee, 0xb3, 0x45, 0x74, 0xbf,
- 0xdc, 0xf3, 0x4b, 0x77, 0x59, 0xa2, 0xc5, 0x5f, 0xfc, 0xc7, 0x97, 0x3c,
- 0xd2, 0xdd, 0xd6, 0x68, 0x9e, 0x97, 0x9b, 0x75, 0x9c, 0xbf, 0xbb, 0x09,
- 0xa4, 0xe1, 0xce, 0x5f, 0xa1, 0x1a, 0x27, 0x01, 0xcb, 0x9b, 0xe7, 0x87,
- 0xf2, 0xb1, 0xd7, 0x31, 0xbf, 0xff, 0xfc, 0x1c, 0x6f, 0x98, 0xe2, 0xaa,
- 0xbf, 0xb6, 0x83, 0x34, 0x2f, 0x59, 0xf1, 0xcb, 0xff, 0xfb, 0x33, 0xa8,
- 0xbe, 0xe7, 0x31, 0xcf, 0x75, 0x1b, 0x39, 0x7f, 0xfe, 0x98, 0x61, 0x9c,
- 0xf3, 0x68, 0xd8, 0x5d, 0xd5, 0x39, 0x76, 0xfc, 0x72, 0xec, 0xd9, 0xcb,
- 0xb7, 0xf9, 0xcb, 0xf0, 0xbb, 0x06, 0x0e, 0x5f, 0xc0, 0xdf, 0x5e, 0x5c,
- 0xda, 0xb3, 0xea, 0x71, 0x76, 0xc5, 0x94, 0x18, 0xbd, 0x3c, 0x35, 0x9c,
- 0xbb, 0x5e, 0x39, 0x7e, 0xcf, 0x6d, 0x18, 0x72, 0xff, 0xf4, 0x7d, 0xec,
- 0x99, 0x35, 0xed, 0x81, 0xac, 0xe5, 0xe7, 0xfb, 0x9c, 0x22, 0xb5, 0xc8,
- 0x04, 0x5f, 0xc4, 0xf5, 0x8a, 0x89, 0x35, 0x0c, 0x2d, 0xc6, 0x29, 0x41,
- 0x56, 0x6e, 0x2f, 0x9e, 0x94, 0xff, 0x5c, 0xd7, 0x1d, 0xa2, 0x19, 0x69,
- 0x2d, 0xce, 0xfc, 0xd4, 0xa4, 0x03, 0x87, 0x39, 0x7e, 0x4e, 0x8b, 0xcc,
- 0x72, 0xfd, 0x2c, 0x0f, 0x2c, 0x39, 0x5c, 0x21, 0xe8, 0x41, 0x3d, 0xcc,
- 0xfc, 0xe5, 0xfb, 0x3c, 0x80, 0xd9, 0xcb, 0x9a, 0x96, 0xa0, 0x72, 0x9a,
- 0x93, 0xe1, 0x6a, 0x03, 0x1c, 0x28, 0x9e, 0xfd, 0xc2, 0xcd, 0x4e, 0xf5,
- 0xe3, 0x97, 0xf9, 0x41, 0xcd, 0x6a, 0x16, 0x72, 0x9a, 0x93, 0xe8, 0xe1,
- 0x8d, 0x6f, 0xb4, 0xcf, 0x7c, 0x72, 0xfe, 0x6a, 0x5a, 0xae, 0x12, 0x24,
- 0xc3, 0x97, 0x97, 0x9d, 0x29, 0x79, 0x91, 0xb3, 0x97, 0xbf, 0xd4, 0x1c,
- 0xbf, 0xb3, 0xf4, 0x99, 0x1b, 0x39, 0x7f, 0xe7, 0xdf, 0x2d, 0xef, 0x25,
- 0x28, 0x39, 0x6d, 0x9c, 0xbf, 0xff, 0x0b, 0xaa, 0x9a, 0x89, 0x4b, 0x37,
- 0xff, 0xf0, 0x72, 0xff, 0x3f, 0x81, 0x98, 0x2a, 0x9c, 0xa0, 0xa6, 0x10,
- 0xa9, 0x7c, 0xc8, 0x1d, 0x11, 0xfd, 0x5a, 0xff, 0xfe, 0xd2, 0x70, 0x3b,
- 0x39, 0xc6, 0xb4, 0x9c, 0x0b, 0x04, 0xe7, 0x2f, 0x93, 0xaa, 0x30, 0xe5,
- 0xff, 0xe4, 0x57, 0x96, 0x0b, 0xfd, 0xb5, 0x55, 0x73, 0x94, 0xb3, 0xf1,
- 0x12, 0x3b, 0xff, 0xcf, 0xb1, 0xcf, 0xf9, 0xf5, 0x16, 0xfa, 0x39, 0x70,
- 0xb6, 0x72, 0xfe, 0x0e, 0x2b, 0xec, 0x59, 0xcb, 0xee, 0xc3, 0x16, 0x72,
- 0xa0, 0xf9, 0xdc, 0x5f, 0xc5, 0xd7, 0x83, 0x9d, 0x39, 0x7a, 0x64, 0x6c,
- 0xe5, 0x83, 0x23, 0x74, 0x83, 0x97, 0xff, 0x72, 0x88, 0x18, 0x67, 0x2e,
- 0x5d, 0x68, 0x72, 0xa0, 0xfc, 0x44, 0x9a, 0xff, 0xdd, 0xc9, 0xba, 0x9d,
- 0x8d, 0x41, 0xcb, 0x9f, 0xe3, 0x97, 0xf9, 0xf6, 0xfd, 0x00, 0xce, 0x72,
- 0x84, 0xf2, 0x80, 0x2f, 0x53, 0xae, 0x6c, 0x48, 0x71, 0x23, 0x25, 0xd2,
- 0x73, 0x21, 0xab, 0xd2, 0x11, 0x85, 0x97, 0xa1, 0xb0, 0xa1, 0x07, 0x04,
- 0x22, 0x2f, 0x0b, 0xf8, 0xe5, 0xe1, 0x4d, 0x9c, 0xb3, 0x7c, 0x21, 0xb6,
- 0x81, 0xbb, 0xa3, 0xa7, 0x2f, 0xb5, 0xc5, 0xd8, 0x72, 0xfc, 0x39, 0xe8,
- 0x6c, 0xe5, 0xff, 0xe4, 0xe5, 0xdc, 0x99, 0x3e, 0xdf, 0x71, 0x67, 0x2f,
- 0xcc, 0x17, 0xf6, 0xce, 0x5e, 0x8c, 0xd1, 0xcb, 0xff, 0xcb, 0x7d, 0x3f,
- 0x93, 0x70, 0x31, 0xf9, 0xcb, 0x4b, 0xa7, 0xc6, 0xa0, 0xdd, 0x7c, 0x8b,
- 0x3d, 0x42, 0x2a, 0xb1, 0x3b, 0x65, 0x96, 0x20, 0xb6, 0xc9, 0x3c, 0x4e,
- 0x08, 0xc0, 0x2f, 0x9d, 0x14, 0x61, 0xcb, 0xdb, 0xe0, 0xe0, 0x39, 0x7d,
- 0xca, 0x5f, 0xb0, 0xe5, 0xed, 0x60, 0x4e, 0x5f, 0xe7, 0xf4, 0x4d, 0xb4,
- 0x61, 0xca, 0x54, 0xf3, 0xfa, 0x39, 0x7f, 0xa2, 0x43, 0x9f, 0x7b, 0x0e,
- 0x5f, 0xff, 0x27, 0x5d, 0x70, 0x21, 0x9a, 0x51, 0xa9, 0xce, 0x5f, 0xff,
- 0x7b, 0x61, 0xd6, 0x22, 0xbd, 0x6d, 0xc6, 0x73, 0x97, 0xc2, 0x1c, 0x54,
- 0xe5, 0xee, 0x81, 0x87, 0x2a, 0x49, 0xf8, 0x61, 0x17, 0xc4, 0x68, 0xeb,
- 0xa2, 0x3e, 0x99, 0x6d, 0x43, 0xca, 0x40, 0x22, 0xbf, 0xbd, 0xb9, 0xa0,
- 0x67, 0x39, 0x7e, 0x15, 0x53, 0x36, 0x72, 0xfc, 0xdb, 0xf9, 0xd6, 0x72,
- 0xff, 0xec, 0x6d, 0xff, 0xc5, 0xf5, 0xff, 0xd9, 0xcb, 0xff, 0x6d, 0xfe,
- 0x81, 0x70, 0xe2, 0xa7, 0x29, 0x11, 0xa7, 0xd2, 0x71, 0x28, 0xf2, 0x35,
- 0xd1, 0xd3, 0x96, 0x09, 0xca, 0x61, 0xa7, 0x11, 0x6b, 0xe1, 0x0f, 0x25,
- 0x4e, 0x5f, 0xd9, 0xb6, 0xdc, 0x67, 0x39, 0x58, 0x7e, 0x6e, 0x40, 0x24,
- 0xb7, 0xed, 0x03, 0x6e, 0xb3, 0x97, 0xca, 0xec, 0x30, 0x72, 0xa0, 0xf2,
- 0xc0, 0x51, 0x6d, 0x9c, 0xb6, 0x1c, 0xb3, 0x10, 0xd0, 0xf0, 0x08, 0xdf,
- 0xf6, 0x0b, 0xcb, 0x72, 0x6e, 0x73, 0x97, 0xd2, 0xda, 0x09, 0xcb, 0x44,
- 0x8f, 0x6f, 0xe3, 0xab, 0xfc, 0xfa, 0x94, 0x2d, 0x16, 0x72, 0xa1, 0x5b,
- 0x76, 0x46, 0x04, 0x90, 0xd5, 0xeb, 0xbb, 0xa1, 0x0c, 0x21, 0x00, 0x51,
- 0x7f, 0xf9, 0x57, 0xcf, 0xbd, 0xe8, 0xce, 0x28, 0xb3, 0x97, 0xf8, 0x73,
- 0x7e, 0x77, 0x13, 0x94, 0xa9, 0xfe, 0x71, 0x4c, 0xbf, 0xff, 0xf2, 0x6b,
- 0x50, 0xa7, 0x90, 0x41, 0x2c, 0xd8, 0x40, 0xfa, 0x91, 0xcb, 0xff, 0xf8,
- 0x71, 0x5c, 0x1e, 0x5b, 0xf7, 0x71, 0x8a, 0x47, 0xe7, 0x2a, 0x11, 0x95,
- 0x8d, 0x97, 0xf8, 0x0f, 0xb4, 0x99, 0x1b, 0x39, 0x48, 0x9a, 0x27, 0x61,
- 0xde, 0x24, 0x37, 0xbb, 0x02, 0x72, 0xf7, 0xde, 0x61, 0xca, 0x59, 0xb9,
- 0x71, 0xbb, 0xf4, 0xe1, 0xd2, 0x36, 0x72, 0xff, 0x28, 0xfc, 0x52, 0x64,
- 0x6c, 0xe5, 0xfe, 0x06, 0xa7, 0x64, 0x67, 0x8e, 0x5f, 0xf6, 0xe1, 0x81,
- 0xec, 0x0a, 0xce, 0x5c, 0x83, 0x87, 0xd8, 0xa9, 0xa5, 0x42, 0x33, 0xc3,
- 0x0a, 0x3b, 0xd2, 0x06, 0xce, 0x5f, 0xc1, 0x7d, 0x7e, 0xd3, 0x0e, 0x5e,
- 0xea, 0x9c, 0x4e, 0x5f, 0xf4, 0x30, 0x71, 0x7a, 0x4f, 0xce, 0x5f, 0x82,
- 0xfb, 0xde, 0x1c, 0xa9, 0x1f, 0xfe, 0xc8, 0x00, 0x71, 0x7f, 0xd1, 0x2c,
- 0x4d, 0xec, 0x10, 0x72, 0xff, 0xde, 0x86, 0x7c, 0xb4, 0xfb, 0x34, 0x72,
- 0xfd, 0xdc, 0xd2, 0x6c, 0xe5, 0xe1, 0x49, 0x7c, 0x7c, 0xfe, 0x40, 0xbf,
- 0xf3, 0xe7, 0xf0, 0x2e, 0x1c, 0x54, 0xe5, 0x4e, 0x98, 0x74, 0xa1, 0x3d,
- 0xf9, 0x9d, 0xf7, 0xbd, 0x8d, 0x67, 0x2f, 0xfa, 0x32, 0x5d, 0xc4, 0x96,
- 0xce, 0x5c, 0xff, 0x6c, 0xf7, 0x3c, 0x4b, 0x73, 0x24, 0x72, 0xff, 0x9f,
- 0x16, 0x1c, 0xd7, 0xe8, 0x72, 0xe4, 0xd0, 0x4f, 0x3f, 0xa2, 0xf7, 0xfd,
- 0x12, 0xd8, 0xc7, 0xee, 0xc3, 0x97, 0xef, 0x46, 0x0a, 0xce, 0x5f, 0x7d,
- 0xe8, 0x61, 0xca, 0x54, 0xf2, 0x7e, 0x26, 0xbf, 0xe9, 0x29, 0xe4, 0xea,
- 0x0f, 0x8e, 0x5f, 0xfe, 0x8c, 0xfb, 0xdd, 0x8f, 0x0c, 0x7f, 0xb3, 0x97,
- 0x47, 0xe7, 0x2e, 0xeb, 0x0e, 0x52, 0xcd, 0x76, 0xc5, 0xe9, 0x11, 0xec,
- 0xe4, 0x9e, 0x39, 0x03, 0xc5, 0xff, 0xe1, 0x03, 0xc9, 0x80, 0xf7, 0x60,
- 0x1c, 0x39, 0xcb, 0xd3, 0xa6, 0x8e, 0x5f, 0xf6, 0xd3, 0xef, 0x4d, 0x28,
- 0xf8, 0xe5, 0xfb, 0x7e, 0xde, 0x78, 0xe5, 0x6c, 0xf9, 0x00, 0x79, 0x7f,
- 0x03, 0x87, 0x49, 0x91, 0xb3, 0x97, 0x67, 0x4e, 0x5e, 0x6d, 0xb6, 0xca,
- 0x5f, 0xfe, 0xf2, 0x7b, 0x7d, 0x46, 0x8a, 0x6a, 0x24, 0x53, 0x99, 0xa0,
- 0xa5, 0x53, 0x6c, 0x48, 0x40, 0xb9, 0x17, 0x8d, 0x00, 0x6d, 0x7f, 0xff,
- 0xc9, 0xe9, 0x40, 0xe7, 0xba, 0x99, 0xe8, 0x62, 0x6a, 0x47, 0x2a, 0x4c,
- 0x91, 0x30, 0xb6, 0xe1, 0x02, 0xe1, 0xf3, 0xf1, 0x3a, 0x0e, 0xcd, 0x0a,
- 0xfd, 0x46, 0x7a, 0xc8, 0x4a, 0x75, 0xf7, 0xf2, 0xd1, 0x8d, 0xdf, 0x67,
- 0x7e, 0x8e, 0xef, 0x8a, 0x7d, 0xff, 0x7d, 0x2d, 0xef, 0x02, 0xfe, 0x39,
- 0x6c, 0x39, 0x7d, 0xa1, 0x7e, 0x27, 0x2a, 0x0f, 0xb5, 0x53, 0xa4, 0x10,
- 0xbd, 0xfe, 0xf0, 0xe5, 0x9c, 0xe5, 0xe8, 0xee, 0xce, 0x57, 0xc6, 0xb1,
- 0x04, 0x2f, 0xfd, 0x0b, 0xe5, 0x83, 0x00, 0xe1, 0xf6, 0x72, 0xff, 0xfe,
- 0x7f, 0x27, 0x5d, 0x9c, 0xb3, 0x71, 0x9a, 0xc1, 0x39, 0x7f, 0xf6, 0xdf,
- 0xed, 0xef, 0x07, 0xf6, 0x98, 0x72, 0xff, 0xf2, 0x2f, 0x70, 0xd3, 0x3d,
- 0x29, 0x66, 0xce, 0x56, 0x93, 0x50, 0x61, 0x08, 0xa2, 0x79, 0x67, 0x8a,
- 0x3d, 0xf6, 0xbb, 0x82, 0x72, 0x90, 0xfb, 0x5d, 0x32, 0xfe, 0x1e, 0x4a,
- 0x6e, 0x30, 0xe5, 0xf7, 0xa3, 0xe6, 0xce, 0x52, 0xd5, 0x3c, 0xf6, 0x50,
- 0x37, 0xe4, 0x0d, 0x97, 0xdf, 0xff, 0xbc, 0x05, 0x3c, 0x31, 0xfb, 0xfb,
- 0xf5, 0x06, 0x47, 0x2e, 0x6f, 0xa7, 0x2f, 0xff, 0x40, 0xad, 0x4d, 0x3f,
- 0xe9, 0xee, 0xc1, 0xcb, 0xf9, 0x9c, 0xbb, 0x9f, 0xb9, 0xcb, 0xf9, 0xbd,
- 0xe6, 0x0c, 0xe7, 0x2b, 0x0f, 0x79, 0x0c, 0x2f, 0xa3, 0x71, 0xc4, 0xe5,
- 0xff, 0xd0, 0x2f, 0xe9, 0x42, 0xae, 0xdf, 0x8e, 0x57, 0x4f, 0x9c, 0x04,
- 0x77, 0xb9, 0x3a, 0xce, 0x54, 0x27, 0xc0, 0xb5, 0x9f, 0xc6, 0x37, 0x0a,
- 0x8f, 0x42, 0x1f, 0x80, 0x8a, 0xfe, 0x92, 0x8c, 0x62, 0x35, 0x9c, 0xbe,
- 0x62, 0x90, 0x27, 0x2f, 0x90, 0x38, 0xc3, 0x97, 0xce, 0xe3, 0xf9, 0xcb,
- 0x37, 0x07, 0x84, 0xa9, 0x0d, 0xc0, 0x61, 0xcb, 0xfc, 0xdb, 0xcd, 0x92,
- 0x86, 0xb3, 0x97, 0xee, 0x00, 0x4c, 0x93, 0x1c, 0xa4, 0x45, 0x27, 0x4a,
- 0x76, 0x2e, 0x03, 0x7b, 0xff, 0x42, 0x33, 0xbf, 0x3b, 0x5f, 0xb6, 0x72,
- 0xff, 0x43, 0xeb, 0xad, 0xb8, 0x4a, 0x5c, 0xdb, 0x65, 0x28, 0x27, 0x98,
- 0xd9, 0x9d, 0xef, 0x23, 0x59, 0x4e, 0x66, 0x8e, 0xfe, 0xf9, 0x69, 0xbe,
- 0xa1, 0xcb, 0xe0, 0x48, 0x1e, 0x39, 0x50, 0xaa, 0xa5, 0x0c, 0xa6, 0x8c,
- 0x21, 0x87, 0x9b, 0x85, 0x8f, 0x8c, 0x5a, 0x17, 0x5f, 0x08, 0x7a, 0xe7,
- 0x2f, 0x63, 0xb5, 0x9c, 0xac, 0x37, 0xfa, 0x21, 0xb9, 0xbd, 0x9c, 0xb6,
- 0x1c, 0xb7, 0xd8, 0x6a, 0x3c, 0x31, 0x7d, 0xf4, 0xb8, 0x4f, 0x8e, 0x5f,
- 0xfd, 0xbd, 0x84, 0x60, 0x3d, 0x8f, 0x6c, 0xe5, 0x42, 0x25, 0x70, 0x9c,
- 0x05, 0x57, 0xfb, 0xa8, 0xf2, 0xf2, 0x4e, 0x72, 0xff, 0xde, 0x4d, 0x3f,
- 0xfc, 0x1e, 0xce, 0x9c, 0xbf, 0xe4, 0x6c, 0x73, 0xc8, 0x0f, 0xce, 0x5f,
- 0x93, 0x41, 0x89, 0xce, 0x5f, 0xe7, 0xd7, 0xb6, 0x28, 0xa9, 0xcb, 0xff,
- 0xdb, 0xc5, 0x70, 0x1a, 0x70, 0xc7, 0x60, 0xe5, 0x49, 0x38, 0x0f, 0x8b,
- 0x90, 0xcd, 0xad, 0x0b, 0xa7, 0x2e, 0x51, 0xb3, 0x3b, 0xff, 0xff, 0x3a,
- 0x7a, 0x3a, 0x39, 0xee, 0xa2, 0x92, 0x8e, 0x28, 0x3f, 0x9c, 0xbf, 0x2f,
- 0x19, 0x1b, 0x39, 0x78, 0x02, 0x13, 0x95, 0xd4, 0x57, 0xbb, 0x67, 0xe4,
- 0xf7, 0xb1, 0x34, 0x72, 0xff, 0x49, 0x19, 0xdf, 0x9d, 0xac, 0xe5, 0xf3,
- 0xea, 0x24, 0x72, 0xff, 0x9f, 0xee, 0x5f, 0x6f, 0x05, 0x53, 0x95, 0x3a,
- 0x2c, 0x3e, 0x1b, 0x61, 0xbf, 0x88, 0x6f, 0xba, 0xd6, 0x8c, 0x39, 0x78,
- 0x63, 0xf3, 0x97, 0xa1, 0x99, 0xc8, 0xf0, 0x76, 0x4b, 0x7f, 0xe8, 0xfb,
- 0xb0, 0xc5, 0xf5, 0x26, 0x39, 0x50, 0x9e, 0xa6, 0x43, 0x81, 0x21, 0x01,
- 0xa3, 0x4b, 0xf8, 0x43, 0xbd, 0xa3, 0x0e, 0x5f, 0x96, 0xf3, 0xe3, 0x67,
- 0x2f, 0xd1, 0xa0, 0xe0, 0x9c, 0xac, 0x3f, 0xc1, 0x2d, 0xf1, 0x4d, 0xfa,
- 0x1a, 0x27, 0x40, 0x72, 0xff, 0xe8, 0xfe, 0x3a, 0xc1, 0x75, 0x7a, 0x87,
- 0x2d, 0xc3, 0x1c, 0xbf, 0xbb, 0x02, 0xdb, 0xfc, 0x72, 0xff, 0xc3, 0x34,
- 0x60, 0xcf, 0x9f, 0x78, 0xe5, 0x04, 0xfb, 0x5c, 0xba, 0xf2, 0xaa, 0x30,
- 0xe5, 0xff, 0xc8, 0x1e, 0xc2, 0xe3, 0xf7, 0x1f, 0xce, 0x5f, 0x9f, 0x73,
- 0xa6, 0x8e, 0x5f, 0x69, 0x01, 0x39, 0xe2, 0xf5, 0x5f, 0xfb, 0x13, 0x8e,
- 0x0e, 0x05, 0xe4, 0x78, 0xbd, 0x57, 0xe7, 0x1f, 0xa5, 0xcc, 0x27, 0xf4,
- 0xd9, 0x85, 0x05, 0x1c, 0x8c, 0x85, 0x15, 0xf9, 0x5f, 0x3b, 0x89, 0xcb,
- 0xc2, 0x09, 0xce, 0x53, 0x9e, 0x27, 0x89, 0xe9, 0x11, 0x1a, 0x2d, 0x95,
- 0x0a, 0xcc, 0xc2, 0x5b, 0xa2, 0x96, 0x22, 0x3c, 0x20, 0xc4, 0x87, 0x63,
- 0xe0, 0x8e, 0xd6, 0xe6, 0xa5, 0xab, 0x39, 0x79, 0x23, 0x47, 0x2b, 0x86,
- 0x37, 0x9d, 0x21, 0xbf, 0xfb, 0x48, 0xc8, 0x6b, 0x1c, 0x67, 0xd0, 0x72,
- 0xa4, 0x7d, 0x93, 0x13, 0x5f, 0x20, 0xb8, 0x4e, 0x5e, 0x9d, 0x88, 0x72,
- 0x82, 0x6f, 0x44, 0x82, 0xfd, 0x2c, 0xe3, 0x12, 0x39, 0x7b, 0x35, 0x07,
- 0x2b, 0xe4, 0x62, 0x23, 0x06, 0x88, 0x3a, 0x53, 0x70, 0xcc, 0x72, 0xfe,
- 0xeb, 0xcd, 0xa8, 0x9c, 0xe5, 0xfc, 0x9f, 0x6f, 0xb8, 0xb3, 0x97, 0xff,
- 0xd9, 0xed, 0xe4, 0xdd, 0x8e, 0x39, 0xde, 0xc1, 0xcb, 0xff, 0xff, 0xf2,
- 0x67, 0xdb, 0x4c, 0x6f, 0x96, 0x7d, 0x2d, 0xa7, 0xb6, 0x9f, 0x04, 0x20,
- 0x9c, 0xe5, 0xff, 0xf9, 0x04, 0x3c, 0x94, 0xf2, 0x6d, 0xd0, 0x41, 0x23,
- 0x97, 0xcf, 0x3f, 0x50, 0xe5, 0x62, 0x78, 0xc8, 0x2f, 0x31, 0x78, 0x97,
- 0x79, 0x47, 0x8c, 0x22, 0x5a, 0x2b, 0x5e, 0x06, 0xa4, 0x72, 0xff, 0xcc,
- 0x70, 0xea, 0x3d, 0xdc, 0x09, 0xcb, 0xf9, 0xfd, 0xfa, 0x83, 0x23, 0x97,
- 0xfc, 0x17, 0x76, 0xff, 0x7f, 0x6c, 0xe5, 0xfe, 0x92, 0x90, 0x22, 0x06,
- 0x1c, 0xae, 0x48, 0xf7, 0x81, 0xd9, 0xcf, 0x95, 0x2f, 0x73, 0xab, 0xfd,
- 0x12, 0x4e, 0x6d, 0xb6, 0xd9, 0x4b, 0xb3, 0xa7, 0x2f, 0x2b, 0x81, 0x39,
- 0x7f, 0x75, 0xf4, 0xb8, 0xf1, 0xcb, 0x9c, 0x27, 0x2f, 0xed, 0x3e, 0xfa,
- 0xf2, 0x39, 0x6f, 0x8e, 0x5c, 0x8d, 0x9c, 0xb9, 0x4f, 0xce, 0x54, 0xc6,
- 0xc3, 0xf1, 0x7b, 0xd2, 0x70, 0x9c, 0xb9, 0xb6, 0xce, 0x54, 0x91, 0xbb,
- 0x82, 0xcb, 0x2d, 0x44, 0x2d, 0x91, 0xb6, 0x39, 0x7b, 0xca, 0x7e, 0x53,
- 0x99, 0xeb, 0x5f, 0xec, 0x62, 0x06, 0x70, 0x6c, 0xe5, 0xff, 0xfd, 0xfb,
- 0x4c, 0xd4, 0x79, 0x16, 0x81, 0x9e, 0x06, 0x0e, 0x5e, 0xcf, 0xbc, 0x72,
- 0xd8, 0x27, 0xf3, 0xb5, 0xca, 0xea, 0x34, 0xf7, 0x0a, 0xdb, 0xfe, 0x40,
- 0xe3, 0x12, 0x64, 0x6c, 0xe5, 0xff, 0xe7, 0x0e, 0x60, 0xab, 0xbd, 0xe0,
- 0xfe, 0x72, 0xfb, 0xa0, 0x75, 0x61, 0x10, 0x4c, 0x39, 0xbc, 0x31, 0xd3,
- 0x97, 0xff, 0xf4, 0x9f, 0x7b, 0x8c, 0x9c, 0x12, 0x0e, 0x85, 0xdb, 0x39,
- 0x68, 0x0a, 0x2c, 0x55, 0x3a, 0x41, 0xba, 0xda, 0x72, 0x1e, 0x8d, 0x6e,
- 0xfe, 0x46, 0x2f, 0x05, 0x67, 0x2f, 0x9e, 0x7d, 0xf4, 0xe5, 0x68, 0xf3,
- 0xf6, 0x59, 0x5c, 0x97, 0x30, 0xe4, 0x2c, 0x11, 0xdf, 0xa3, 0x60, 0x49,
- 0x52, 0xbe, 0x79, 0xbf, 0x71, 0x53, 0xa9, 0xe3, 0x97, 0xfd, 0x9e, 0xec,
- 0x6b, 0xd8, 0xb3, 0x97, 0xef, 0xb0, 0x41, 0x31, 0xcb, 0xd1, 0xa9, 0x8e,
- 0x54, 0x32, 0x6f, 0xf2, 0x50, 0x1a, 0x46, 0xc7, 0xd4, 0xc7, 0x9c, 0xfb,
- 0xfd, 0xa4, 0x4a, 0xc0, 0x70, 0xd0, 0xa6, 0xf6, 0xde, 0x63, 0x97, 0xff,
- 0xb3, 0xec, 0xe3, 0x01, 0x1c, 0xf6, 0x7e, 0x72, 0xe5, 0x3f, 0x39, 0x5a,
- 0x3e, 0x4f, 0xd2, 0xef, 0xfe, 0x40, 0xbf, 0x93, 0x79, 0x2c, 0xe9, 0xcb,
- 0x9f, 0x80, 0xe5, 0xb3, 0xa7, 0xb7, 0xe4, 0x2b, 0xff, 0xbf, 0x50, 0x64,
- 0x39, 0xef, 0x64, 0xe7, 0x2b, 0xe4, 0xdb, 0x35, 0x08, 0x11, 0x7e, 0xf1,
- 0x3d, 0xe1, 0x5f, 0x01, 0xcb, 0xff, 0xfb, 0xed, 0x8b, 0xef, 0xb9, 0x2c,
- 0xea, 0x6b, 0xae, 0x72, 0xfb, 0x3e, 0x9f, 0x89, 0xcb, 0xfe, 0x10, 0xe0,
- 0x82, 0x59, 0xb3, 0x97, 0xe8, 0xfb, 0x60, 0xfc, 0xe5, 0xfe, 0x53, 0xc3,
- 0x93, 0xa6, 0x8e, 0x5f, 0x79, 0x36, 0x87, 0x2b, 0x13, 0x55, 0x41, 0xfd,
- 0x2d, 0x39, 0x37, 0xe6, 0xe2, 0x54, 0x03, 0x4b, 0xff, 0xa7, 0x85, 0x3f,
- 0x04, 0xa4, 0xfd, 0x01, 0xcb, 0xfe, 0xea, 0x05, 0x38, 0x78, 0x14, 0x39,
- 0x7f, 0x9e, 0x58, 0x1d, 0x6f, 0x67, 0x2f, 0xa3, 0x14, 0x09, 0xcb, 0xff,
- 0xfa, 0x43, 0x19, 0xbc, 0x1f, 0x77, 0x02, 0x0f, 0x6c, 0xe5, 0xfe, 0x55,
- 0x3c, 0xfd, 0x6d, 0xac, 0xe5, 0xfd, 0x13, 0xb4, 0xcd, 0x41, 0xcb, 0xfd,
- 0x93, 0x77, 0x36, 0xe2, 0x72, 0xff, 0xc1, 0xcf, 0xa5, 0xbf, 0x6d, 0xff,
- 0x39, 0x5a, 0x3f, 0x30, 0x19, 0x5f, 0xe6, 0xc3, 0xdc, 0xe3, 0x9a, 0x39,
- 0x7f, 0xf2, 0x33, 0x92, 0xfa, 0x9d, 0x5a, 0x6c, 0xe5, 0xfe, 0xc9, 0x60,
- 0x38, 0x77, 0x13, 0x97, 0xff, 0x44, 0xbb, 0x1f, 0x7a, 0x3a, 0xed, 0x67,
- 0x2a, 0x11, 0xf3, 0xa3, 0x6e, 0xa3, 0x09, 0xb5, 0xff, 0xfe, 0x41, 0xcf,
- 0xbc, 0xab, 0xfb, 0xb1, 0xdc, 0xe2, 0xf2, 0x39, 0x41, 0x56, 0x80, 0xb3,
- 0x3f, 0x88, 0x91, 0x66, 0x63, 0x8d, 0x42, 0x8b, 0xd1, 0x8d, 0xf1, 0x3b,
- 0xb8, 0x60, 0xe5, 0xff, 0x05, 0x35, 0x1c, 0x7f, 0xdc, 0x8e, 0x5d, 0x0c,
- 0x39, 0x50, 0x7a, 0x5d, 0x3c, 0xae, 0xa2, 0x23, 0xcc, 0xf7, 0xfd, 0xb7,
- 0xea, 0x05, 0x69, 0x39, 0xcb, 0xfc, 0xf2, 0xc0, 0xef, 0x70, 0x72, 0xa0,
- 0xfa, 0xf0, 0xe6, 0xa1, 0x74, 0xcb, 0x25, 0xbd, 0xbc, 0x61, 0x20, 0x84,
- 0x75, 0xe8, 0x1f, 0x1c, 0xbf, 0xfe, 0x8d, 0x67, 0x14, 0xf7, 0xe0, 0x1d,
- 0xa0, 0x4e, 0x5f, 0xe4, 0xea, 0x6a, 0x53, 0x41, 0xcb, 0xff, 0xf2, 0x01,
- 0x6a, 0x7d, 0xfb, 0xed, 0xf4, 0x9f, 0x7e, 0x72, 0xf9, 0xf5, 0x12, 0x39,
- 0x7f, 0xff, 0x20, 0xba, 0x0f, 0xfa, 0x8e, 0xba, 0x7a, 0x3a, 0x72, 0x84,
- 0xfe, 0x3c, 0x43, 0x7e, 0x4f, 0x6c, 0x13, 0x9c, 0xbf, 0xfc, 0x29, 0xff,
- 0xbe, 0x5a, 0x69, 0x48, 0x09, 0xcb, 0xfe, 0xea, 0x81, 0x07, 0xb7, 0xfc,
- 0x1c, 0xa8, 0x44, 0x43, 0xa6, 0x50, 0x53, 0xc5, 0x48, 0x69, 0x30, 0x87,
- 0xd0, 0xb1, 0xbf, 0x68, 0x0b, 0xec, 0x1c, 0xbf, 0xb5, 0x34, 0x93, 0xdb,
- 0x39, 0x61, 0x83, 0xd7, 0xc2, 0x8b, 0xfd, 0x33, 0xcc, 0xff, 0x4b, 0x67,
- 0x2f, 0xe7, 0x9d, 0x26, 0x46, 0xce, 0x5f, 0xff, 0xe7, 0x6f, 0xd9, 0xde,
- 0x41, 0xc9, 0xa4, 0xfa, 0x9f, 0xa0, 0x39, 0x58, 0x8c, 0xb7, 0x36, 0x12,
- 0xfb, 0xf6, 0x0c, 0xf8, 0xd9, 0xcb, 0xf3, 0xb3, 0xa8, 0xd9, 0xca, 0x9c,
- 0xf4, 0x02, 0x51, 0x7f, 0xd1, 0x3a, 0x92, 0xe8, 0x1e, 0x73, 0x95, 0x87,
- 0xbf, 0xa2, 0x3b, 0x70, 0xc7, 0x2f, 0xd1, 0xad, 0x67, 0x4e, 0x5f, 0xc2,
- 0xea, 0xc3, 0x20, 0xe5, 0x70, 0x87, 0xd3, 0x21, 0x60, 0x13, 0xdf, 0x44,
- 0xea, 0xaa, 0x72, 0xff, 0xfc, 0x8b, 0x86, 0x6d, 0xf5, 0x8c, 0x02, 0xde,
- 0x47, 0x2e, 0x4e, 0x27, 0x2d, 0xd3, 0x95, 0x23, 0xfd, 0x6b, 0x54, 0x00,
- 0xc5, 0xe0, 0xc3, 0x0e, 0x5f, 0xec, 0xff, 0x26, 0x8f, 0xb6, 0x72, 0xa0,
- 0xf4, 0x70, 0x72, 0xfe, 0xeb, 0xca, 0x37, 0x23, 0x97, 0xfd, 0x9d, 0x4f,
- 0xb7, 0xd0, 0x6c, 0xe5, 0xd8, 0x2b, 0x3e, 0x7f, 0xcb, 0x6f, 0xe1, 0x7f,
- 0xc3, 0x82, 0x72, 0xfc, 0x8d, 0x33, 0x4a, 0x9c, 0xb9, 0x59, 0x1c, 0xbf,
- 0x75, 0x38, 0xa2, 0xce, 0x5d, 0x9d, 0x91, 0xe0, 0xac, 0x62, 0x98, 0x89,
- 0x86, 0x8d, 0x77, 0x9b, 0x6d, 0xb2, 0x97, 0xfe, 0xd0, 0x81, 0xd4, 0xc9,
- 0xa1, 0x87, 0x39, 0x9a, 0x0b, 0xf7, 0x52, 0x64, 0x6c, 0xe5, 0x96, 0x72,
- 0xa1, 0x11, 0x78, 0xa3, 0xa2, 0x9b, 0xfd, 0x01, 0xc9, 0x40, 0xac, 0xe5,
- 0x43, 0x25, 0x62, 0x71, 0xb9, 0x28, 0xe4, 0x7f, 0x0d, 0x70, 0x9e, 0x9a,
- 0x1e, 0x1a, 0x86, 0xe3, 0x21, 0x15, 0xd3, 0x47, 0x85, 0x10, 0xc2, 0x0f,
- 0x70, 0x87, 0xf1, 0x68, 0x21, 0x88, 0xdc, 0x34, 0x14, 0x2e, 0xbf, 0x31,
- 0x34, 0xff, 0x9c, 0xbe, 0xd6, 0xb3, 0xa7, 0x2f, 0xee, 0xa7, 0x07, 0x00,
- 0x15, 0x39, 0x50, 0x7a, 0xeb, 0x22, 0xb7, 0x0e, 0x72, 0xc8, 0x72, 0xff,
- 0xbd, 0x1a, 0xdf, 0x60, 0x7c, 0x72, 0xdc, 0x39, 0xcb, 0xfe, 0xf4, 0x6b,
- 0x7d, 0x81, 0xf1, 0xcb, 0xb7, 0x07, 0x2f, 0x30, 0x30, 0x72, 0xff, 0x0f,
- 0x9e, 0x6d, 0xc7, 0x8e, 0x52, 0x1e, 0x7b, 0x8e, 0x5f, 0x23, 0xe2, 0xce,
- 0x5f, 0xfb, 0x38, 0x8e, 0x6e, 0x61, 0x80, 0x9c, 0xbe, 0x58, 0x62, 0x73,
- 0x97, 0x7f, 0x07, 0x2f, 0x6d, 0x34, 0x72, 0xb0, 0xf5, 0xbf, 0x23, 0xf0,
- 0xbd, 0xfe, 0x96, 0x0a, 0x07, 0x04, 0xe5, 0xef, 0x6f, 0x9c, 0x27, 0xcf,
- 0x82, 0xd3, 0x1c, 0x75, 0x97, 0xf2, 0x01, 0x20, 0xdc, 0x25, 0x7c, 0x5f,
- 0x76, 0xe0, 0xe5, 0xe6, 0x06, 0x0e, 0x5f, 0xe1, 0xf3, 0xcd, 0xb8, 0xf1,
- 0xca, 0x43, 0xcf, 0x71, 0xcb, 0xe4, 0x7c, 0x59, 0xcb, 0xff, 0x67, 0x11,
- 0xcd, 0xcc, 0x30, 0x13, 0x97, 0xcb, 0x0c, 0x4e, 0x72, 0xfe, 0x9b, 0xf4,
- 0x6b, 0x79, 0x8e, 0x5d, 0xfc, 0x1c, 0xbd, 0xb4, 0xd1, 0xca, 0xc4, 0x44,
- 0xac, 0x8f, 0xf3, 0x3f, 0x0b, 0xdf, 0xe9, 0x60, 0xa0, 0x70, 0x4e, 0x5f,
- 0xc2, 0xe1, 0xc5, 0x79, 0xc2, 0xe5, 0x48, 0x45, 0xb0, 0x41, 0x72, 0x87,
- 0xe6, 0x84, 0x57, 0x59, 0x7f, 0x20, 0x12, 0x0d, 0xc3, 0x23, 0xc7, 0xb7,
- 0xff, 0x6a, 0x3e, 0xd8, 0xc3, 0x33, 0xef, 0x1c, 0xbf, 0xff, 0x38, 0x73,
- 0x05, 0x55, 0x06, 0x06, 0x74, 0xd1, 0xcb, 0xcf, 0xa9, 0xcf, 0x20, 0x92,
- 0xfa, 0x59, 0xf4, 0x8f, 0x20, 0x92, 0xf6, 0xd0, 0x27, 0x90, 0x49, 0x73,
- 0x6d, 0x9e, 0x41, 0x25, 0x2d, 0x15, 0x33, 0x15, 0x78, 0xc1, 0xb2, 0x9b,
- 0x9f, 0xc5, 0x90, 0x48, 0xe6, 0x6f, 0xef, 0xec, 0xee, 0x60, 0xaa, 0x72,
- 0xf3, 0x8f, 0xfc, 0x97, 0xdb, 0xe2, 0x73, 0x2b, 0x50, 0xc2, 0x62, 0x28,
- 0xc6, 0x79, 0xe3, 0x6b, 0xe6, 0x98, 0xfd, 0x39, 0x6c, 0x6b, 0x45, 0x0f,
- 0xef, 0xd6, 0x91, 0xcb, 0xfa, 0x40, 0x9f, 0xc9, 0x39, 0x4b, 0xe7, 0x0f,
- 0x70, 0xe5, 0xe0, 0xa3, 0x0e, 0x5f, 0xfb, 0xb1, 0xe4, 0x18, 0x64, 0x6c,
- 0xe5, 0x2a, 0x7f, 0x2e, 0x43, 0xb1, 0xca, 0x99, 0x1b, 0x1d, 0x85, 0x4d,
- 0xff, 0x40, 0xc8, 0x63, 0xf7, 0x61, 0xcb, 0xf4, 0xd1, 0xd0, 0x68, 0xe5,
- 0xa0, 0xe5, 0xfe, 0x49, 0x01, 0xf7, 0xd4, 0x39, 0x7f, 0x67, 0x17, 0x66,
- 0x74, 0xe5, 0xa4, 0x52, 0xf3, 0xea, 0x72, 0x94, 0x52, 0xa0, 0xdc, 0xac,
- 0x45, 0x83, 0xb7, 0xa3, 0xf5, 0x94, 0xe6, 0x6b, 0x69, 0x88, 0xc3, 0x18,
- 0x4a, 0x54, 0x26, 0x39, 0x90, 0xf5, 0xbf, 0x6b, 0xf6, 0x26, 0xce, 0x5f,
- 0xca, 0x0c, 0xb7, 0xd0, 0x9c, 0xc3, 0x53, 0x7c, 0x07, 0xd4, 0x8e, 0x59,
- 0x87, 0x2e, 0xc9, 0x04, 0xd9, 0xcc, 0x45, 0x7f, 0xf6, 0x7d, 0xed, 0xa0,
- 0xc7, 0xee, 0xc3, 0x97, 0xd9, 0x32, 0x30, 0xe5, 0x4e, 0x7c, 0xcd, 0xa2,
- 0x5f, 0xa2, 0x69, 0x47, 0xe5, 0x2f, 0xff, 0xdd, 0xc4, 0x96, 0xf9, 0x7b,
- 0xb8, 0x10, 0x7b, 0x67, 0x29, 0x68, 0x81, 0xf1, 0x4d, 0x90, 0xe5, 0xff,
- 0x4e, 0x09, 0x07, 0xa0, 0x71, 0x39, 0x7f, 0x24, 0x32, 0x7c, 0x6c, 0xe5,
- 0xfb, 0x27, 0x66, 0x30, 0xe5, 0xed, 0xa6, 0x8e, 0x50, 0x9e, 0x27, 0x8a,
- 0x2f, 0xe1, 0x7f, 0xff, 0x06, 0xce, 0x5f, 0xc8, 0xaa, 0x90, 0xce, 0x61,
- 0x4c, 0x33, 0x04, 0x34, 0x75, 0xb7, 0x2f, 0x10, 0xd6, 0x2a, 0x44, 0x48,
- 0x52, 0x8c, 0x65, 0xf7, 0xf7, 0x7b, 0x93, 0xfb, 0x67, 0x2f, 0x64, 0xe0,
- 0x39, 0x58, 0x79, 0x82, 0x5f, 0x7f, 0xd9, 0xee, 0x43, 0x9f, 0xa9, 0xf1,
- 0xca, 0x86, 0x7e, 0xa4, 0xa9, 0x11, 0xe1, 0x2c, 0xc8, 0x74, 0xaa, 0x52,
- 0x86, 0xfa, 0x29, 0xec, 0x65, 0x9f, 0xa8, 0x0b, 0x8e, 0xe5, 0x6b, 0xfa,
- 0x10, 0xcd, 0x08, 0x2f, 0xff, 0xd3, 0xeb, 0x58, 0x17, 0x67, 0x5f, 0xc3,
- 0x13, 0x1c, 0xbf, 0xff, 0xfc, 0x0d, 0x02, 0x61, 0x7f, 0xf7, 0xbc, 0x57,
- 0x01, 0xa7, 0x0c, 0x76, 0x0e, 0x5f, 0xf7, 0x36, 0x38, 0x7b, 0x02, 0x03,
- 0x97, 0xd0, 0xd6, 0x18, 0x39, 0x7d, 0xc1, 0xd0, 0x28, 0x72, 0xf3, 0x6d,
- 0xb6, 0x52, 0xe9, 0x41, 0x4e, 0x66, 0x82, 0xf7, 0x78, 0x66, 0xce, 0x54,
- 0x27, 0x7f, 0x3a, 0xb6, 0x3c, 0xac, 0xeb, 0xe2, 0x4d, 0x23, 0xf1, 0x28,
- 0xbf, 0xfe, 0x4f, 0x4d, 0x9a, 0xd3, 0xcd, 0x9a, 0xcf, 0x1c, 0xbf, 0x95,
- 0x8d, 0x6b, 0x3a, 0x72, 0xfe, 0x9e, 0x69, 0x70, 0xda, 0x9c, 0xe5, 0xff,
- 0xef, 0xd8, 0xf2, 0xe5, 0x01, 0x9d, 0x91, 0xa3, 0x97, 0xc9, 0x03, 0xe3,
- 0x97, 0xa7, 0x71, 0x39, 0x5a, 0x44, 0x57, 0x53, 0xbc, 0x41, 0x7f, 0xe5,
- 0x41, 0xb9, 0x26, 0xa7, 0x07, 0xe7, 0x2e, 0x1c, 0x39, 0x79, 0xfe, 0x6c,
- 0xe5, 0x2a, 0x7e, 0xc8, 0x87, 0xd1, 0x5b, 0xf4, 0xfa, 0x48, 0x61, 0xcb,
- 0xff, 0xe8, 0x53, 0xc3, 0x1f, 0xbf, 0xbf, 0x50, 0x64, 0x72, 0x9a, 0xa5,
- 0x42, 0x19, 0x0c, 0x14, 0x85, 0x33, 0x97, 0xf8, 0xa2, 0xf9, 0x40, 0xf5,
- 0x0e, 0x5f, 0xf9, 0xfd, 0xb6, 0xf3, 0xbf, 0xbf, 0x8e, 0x5f, 0xff, 0xfb,
- 0x3d, 0x0b, 0x1c, 0xc1, 0x89, 0x7b, 0xae, 0xc1, 0xce, 0x27, 0x2a, 0x74,
- 0x66, 0x04, 0x8d, 0xb4, 0x0b, 0xca, 0x06, 0x63, 0x97, 0xa4, 0x82, 0x72,
- 0xfa, 0x75, 0x38, 0x1b, 0x39, 0x7f, 0xd1, 0xd7, 0x4f, 0x4c, 0x8d, 0x9c,
- 0xbf, 0xf7, 0xf9, 0xa4, 0xff, 0x3f, 0xd3, 0x0e, 0x5f, 0xfe, 0x56, 0x37,
- 0xa8, 0xe8, 0xe7, 0xa1, 0x87, 0x2e, 0x02, 0x87, 0x2f, 0xf0, 0xe7, 0x14,
- 0x99, 0x1b, 0x39, 0x5d, 0x3c, 0xdd, 0x8c, 0x5f, 0xff, 0xc0, 0x79, 0xd6,
- 0x09, 0xfd, 0x9d, 0x1c, 0xf7, 0x50, 0xe5, 0xfa, 0x26, 0x10, 0x6c, 0xe5,
- 0x62, 0x67, 0x89, 0x09, 0x6e, 0x91, 0x79, 0x72, 0xe4, 0x13, 0x97, 0xf3,
- 0x8f, 0xf9, 0xe5, 0x4e, 0x54, 0x2a, 0xcf, 0x9c, 0xca, 0x43, 0xee, 0x36,
- 0x25, 0x3b, 0x39, 0xf4, 0x6f, 0xbc, 0x50, 0x5a, 0x0a, 0xdf, 0x0f, 0xa1,
- 0xa1, 0xcb, 0xee, 0x81, 0x90, 0x72, 0xe7, 0xd9, 0xcb, 0x81, 0xc3, 0x9c,
- 0xa6, 0xa8, 0xfd, 0xdc, 0x8c, 0x48, 0x80, 0x2d, 0x73, 0xf3, 0x6a, 0x9f,
- 0xa3, 0x47, 0x84, 0x84, 0x0b, 0x57, 0x08, 0x7e, 0x1a, 0x15, 0x1c, 0x2e,
- 0x58, 0xd4, 0x09, 0x38, 0x58, 0xf6, 0x27, 0x3d, 0x27, 0x95, 0x2f, 0x29,
- 0x49, 0x81, 0x97, 0xd9, 0x94, 0xb4, 0x45, 0x63, 0x60, 0x5c, 0xaa, 0x7f,
- 0xa5, 0x14, 0x24, 0xb0, 0xe6, 0xb8, 0x58, 0xcd, 0x29, 0x77, 0x52, 0xba,
- 0x99, 0x2f, 0xd3, 0xb4, 0xba, 0x67, 0x94, 0x03, 0xfc, 0x73, 0x1c, 0x3b,
- 0x10, 0xce, 0xbd, 0x6e, 0x93, 0x4f, 0xea, 0xc3, 0x9c, 0x12, 0xa5, 0x78,
- 0xb3, 0xb6, 0xa0, 0xd2, 0x51, 0xf2, 0x92, 0xfc, 0xf8, 0x21, 0xff, 0x7e,
- 0x66, 0x23, 0xfe, 0x72, 0xf9, 0x6e, 0xeb, 0x34, 0x51, 0x4b, 0xff, 0xf3,
- 0xff, 0x0b, 0xea, 0x6f, 0xa9, 0xee, 0xe0, 0x9c, 0xad, 0x22, 0x08, 0x4b,
- 0xaf, 0x3c, 0xb9, 0xc2, 0x32, 0xf2, 0x15, 0x37, 0xff, 0xe0, 0xa4, 0xc3,
- 0x1e, 0xdf, 0xbe, 0x5a, 0x0c, 0xe7, 0x2d, 0xcd, 0x88, 0x90, 0xd9, 0xcd,
- 0xfe, 0xe7, 0x9a, 0x5b, 0xba, 0xcd, 0x17, 0x42, 0xff, 0xee, 0x6f, 0x2e,
- 0x79, 0xa5, 0xbb, 0xac, 0xd1, 0x25, 0xaf, 0xda, 0x5b, 0xba, 0xcd, 0x17,
- 0x92, 0xe7, 0xe2, 0x72, 0xdc, 0xf0, 0xf3, 0x1a, 0x1a, 0x54, 0x3f, 0xab,
- 0xac, 0xf0, 0x8b, 0x91, 0x56, 0x42, 0x71, 0x70, 0x99, 0x98, 0xe5, 0x88,
- 0x3d, 0x9c, 0xb7, 0x1b, 0xe9, 0x10, 0xdc, 0xe0, 0x9f, 0x8a, 0xc0, 0x83,
- 0xc6, 0x14, 0x17, 0xff, 0xb9, 0xb1, 0xe5, 0xcf, 0x34, 0xb7, 0x75, 0x9a,
- 0x25, 0x95, 0xb8, 0x63, 0x96, 0xe9, 0xca, 0x6a, 0x8d, 0x38, 0x05, 0xaf,
- 0xf2, 0x07, 0xb8, 0x82, 0xa9, 0xcb, 0xee, 0xbf, 0x80, 0x72, 0xfb, 0xb0,
- 0xd6, 0xc3, 0x97, 0xfe, 0xce, 0xa4, 0x87, 0x30, 0x1c, 0x39, 0xcb, 0xc0,
- 0x5b, 0x9c, 0xa9, 0x23, 0x59, 0x0c, 0x9a, 0xc8, 0x98, 0x4a, 0xa2, 0x0d,
- 0xfc, 0x1f, 0x01, 0xe5, 0xb3, 0x97, 0xc8, 0xd7, 0x13, 0x9c, 0xbd, 0xe7,
- 0x61, 0xcb, 0xf0, 0x3c, 0x9d, 0x83, 0x97, 0xfe, 0xec, 0x75, 0x15, 0xf6,
- 0xdf, 0xf3, 0x97, 0xfc, 0xf2, 0xd8, 0x3d, 0x1e, 0xd9, 0xcb, 0xf8, 0x7d,
- 0xa8, 0x75, 0x9c, 0xb9, 0xf6, 0x72, 0xff, 0xfc, 0xef, 0x27, 0xef, 0x2c,
- 0x9c, 0x1e, 0x4e, 0xc1, 0xca, 0x9c, 0xfb, 0x26, 0x16, 0xbc, 0xee, 0xb3,
- 0x44, 0x66, 0xbf, 0xff, 0xfb, 0x3d, 0xbf, 0x79, 0x3b, 0xf4, 0xb6, 0x20,
- 0xc5, 0x55, 0x47, 0x91, 0xca, 0x5a, 0x27, 0x34, 0x51, 0x7f, 0x24, 0x32,
- 0x7c, 0x6c, 0xe5, 0xc3, 0x23, 0x96, 0x61, 0xcb, 0xf2, 0x6b, 0xaf, 0xcf,
- 0x47, 0xaa, 0xc2, 0xe5, 0x05, 0xaf, 0xe7, 0x92, 0x69, 0xf4, 0x72, 0xff,
- 0xed, 0xa0, 0x37, 0x82, 0x09, 0x66, 0xce, 0x5e, 0xdc, 0x7c, 0x72, 0xa7,
- 0x56, 0x95, 0x22, 0x70, 0xa0, 0x61, 0xca, 0x42, 0x63, 0x50, 0xc0, 0x63,
- 0xc0, 0xa7, 0x6c, 0xb3, 0xc8, 0x77, 0xfd, 0xa7, 0x6f, 0xa9, 0x1a, 0x83,
- 0x97, 0xfd, 0x2d, 0xe4, 0x72, 0x8d, 0xb0, 0xe5, 0xf7, 0xdd, 0x8d, 0x9c,
- 0xbd, 0x1e, 0xd9, 0xcb, 0xff, 0x62, 0xbb, 0x8c, 0x10, 0xf6, 0x0e, 0x56,
- 0xcf, 0x64, 0x03, 0x95, 0x88, 0x9e, 0xdb, 0xe5, 0xff, 0xde, 0x4d, 0x3f,
- 0xfc, 0xbe, 0x94, 0x30, 0xe5, 0xf8, 0x62, 0x5b, 0x73, 0x94, 0x87, 0xdd,
- 0xc5, 0x22, 0xdd, 0x39, 0x7f, 0xff, 0xf7, 0x91, 0x9a, 0x4c, 0xf8, 0x41,
- 0xe8, 0xef, 0x2e, 0x29, 0xe9, 0xa0, 0xe5, 0xb3, 0x11, 0x0f, 0xe1, 0x1b,
- 0xfc, 0xf2, 0xde, 0xdc, 0x64, 0x72, 0xf2, 0xdc, 0x27, 0x2f, 0xfd, 0xe7,
- 0x1f, 0xf9, 0x29, 0x9f, 0x36, 0x72, 0xfb, 0xde, 0x86, 0x1c, 0xac, 0x3e,
- 0x65, 0x51, 0x2f, 0xff, 0x7a, 0x16, 0x9e, 0x46, 0x4d, 0xb4, 0x13, 0x97,
- 0xf9, 0x99, 0xaf, 0xc4, 0x1f, 0x9c, 0xb4, 0x8e, 0x52, 0x22, 0x3d, 0xd2,
- 0x54, 0x35, 0xbf, 0x7f, 0x1e, 0x80, 0x9c, 0xa8, 0x4e, 0x29, 0x21, 0x04,
- 0xf0, 0xb1, 0x01, 0x7d, 0xff, 0xf0, 0x3d, 0xbf, 0xa5, 0x03, 0xfe, 0xf9,
- 0x00, 0x4e, 0x5e, 0x8f, 0x41, 0xca, 0x09, 0xf7, 0xf1, 0x54, 0xbd, 0xdc,
- 0x13, 0x94, 0x86, 0xfc, 0x04, 0x97, 0x76, 0x63, 0x97, 0xd9, 0x36, 0x4c,
- 0x72, 0xfb, 0x34, 0x18, 0x39, 0x77, 0xdb, 0xe4, 0x78, 0x82, 0x47, 0x48,
- 0x88, 0xc7, 0x5c, 0xbf, 0xef, 0x6f, 0x35, 0xf8, 0x83, 0xf3, 0x97, 0xff,
- 0xb5, 0x1e, 0xdf, 0x61, 0x3d, 0xb8, 0x9c, 0xe5, 0xf7, 0x9f, 0xb0, 0x72,
- 0xfb, 0xdd, 0x03, 0x43, 0x97, 0xfb, 0x23, 0x4f, 0x24, 0xe9, 0xcb, 0xfc,
- 0x8d, 0xee, 0x3a, 0xed, 0x67, 0x2b, 0x47, 0xcf, 0xe3, 0x1a, 0x0a, 0x63,
- 0x3f, 0x25, 0x21, 0x0b, 0x21, 0x19, 0x7f, 0xf9, 0x3a, 0x06, 0xb0, 0xf4,
- 0x1b, 0xfa, 0x4e, 0x72, 0xa1, 0x3e, 0x6c, 0x8d, 0x51, 0xd0, 0xef, 0x29,
- 0x9c, 0x31, 0xcb, 0xff, 0xc0, 0xfd, 0x88, 0x39, 0xf8, 0xe3, 0xcc, 0x72,
- 0xff, 0x27, 0x52, 0x06, 0x60, 0x1c, 0xbf, 0xc9, 0xac, 0xc1, 0xfb, 0xc7,
- 0x2a, 0x0f, 0x91, 0xcc, 0xaf, 0xfc, 0x00, 0xeb, 0x01, 0xd8, 0x66, 0x1c,
- 0xac, 0x4c, 0xbb, 0x44, 0x5d, 0x85, 0x76, 0xc8, 0x2f, 0xff, 0xbe, 0x92,
- 0x68, 0x3d, 0x06, 0xb1, 0x7d, 0xc3, 0x97, 0x23, 0x67, 0x2e, 0xe0, 0xc3,
- 0x95, 0xb3, 0x61, 0xe1, 0x7b, 0xfb, 0x71, 0xed, 0xf5, 0x0e, 0x5f, 0x87,
- 0x19, 0xac, 0x39, 0x7d, 0xae, 0x38, 0x13, 0x95, 0x87, 0xee, 0xc2, 0xd0,
- 0x13, 0x5e, 0x0e, 0x78, 0xe5, 0xfe, 0xc1, 0xe5, 0xd8, 0xc6, 0xb3, 0x97,
- 0xfe, 0x4f, 0x6f, 0x03, 0x30, 0xc0, 0x4e, 0x5f, 0x7e, 0x9f, 0x48, 0xe5,
- 0xfe, 0x81, 0xf2, 0x4e, 0x30, 0x72, 0xff, 0xf2, 0x69, 0x27, 0x81, 0xce,
- 0xe8, 0x1c, 0x4e, 0x50, 0x53, 0x30, 0x60, 0xe7, 0x4d, 0xbf, 0x3e, 0x12,
- 0x4f, 0x18, 0xdf, 0xfe, 0x81, 0x5b, 0xf9, 0xd5, 0x52, 0x78, 0x9c, 0xe5,
- 0xff, 0x90, 0x20, 0xf6, 0xdf, 0xce, 0xa9, 0xcb, 0xfc, 0x98, 0xdf, 0xd2,
- 0xdf, 0x25, 0x51, 0x16, 0xe9, 0x94, 0xd5, 0xb6, 0x56, 0xf1, 0x0f, 0xc9,
- 0xd3, 0x64, 0x5c, 0x12, 0x5c, 0x96, 0xcc, 0xac, 0x25, 0x7e, 0x38, 0x48,
- 0x6c, 0x4d, 0x09, 0x0d, 0x42, 0xa9, 0x84, 0xfd, 0x8e, 0xf1, 0xe1, 0xe7,
- 0xfc, 0x2b, 0x06, 0x50, 0x3e, 0xe3, 0x62, 0xf2, 0x17, 0x18, 0x40, 0xb4,
- 0x84, 0xc2, 0x91, 0xaf, 0x70, 0x43, 0x8e, 0xfe, 0x64, 0xa2, 0x36, 0x87,
- 0x2e, 0x7f, 0xce, 0x54, 0x1e, 0x1b, 0x96, 0x5f, 0x9c, 0x2e, 0xff, 0x1c,
- 0xbb, 0xdc, 0xfa, 0x78, 0xee, 0x41, 0x7f, 0xff, 0xf0, 0x3e, 0x97, 0x37,
- 0x1f, 0x63, 0x36, 0x1e, 0xc6, 0x82, 0xee, 0xd9, 0xca, 0xe6, 0xaa, 0xe7,
- 0x25, 0x0a, 0x89, 0x7d, 0xff, 0xee, 0x6c, 0x79, 0x73, 0xcd, 0x2d, 0xdd,
- 0x66, 0x89, 0xa5, 0x7f, 0xfb, 0x9b, 0x1e, 0x5c, 0xf3, 0x4b, 0x77, 0x59,
- 0xa2, 0x71, 0x5f, 0xa5, 0x9e, 0x94, 0x8e, 0x5f, 0xee, 0x31, 0xde, 0x43,
- 0x12, 0x39, 0x7f, 0xe7, 0x97, 0x3c, 0xd2, 0xdd, 0xd6, 0x68, 0xa0, 0x57,
- 0xff, 0x92, 0x18, 0xe1, 0xd4, 0x7b, 0xb8, 0x13, 0x97, 0xdb, 0x1f, 0xa4,
- 0x72, 0xdc, 0xfe, 0x4c, 0x55, 0x0a, 0x18, 0x6d, 0xd4, 0xcf, 0x24, 0x5f,
- 0xb4, 0xb7, 0x75, 0x9a, 0x2e, 0x05, 0xfc, 0x39, 0xe5, 0xa6, 0xce, 0x5d,
- 0x08, 0x72, 0xfb, 0xa0, 0x79, 0x1c, 0xbf, 0xc3, 0x28, 0x40, 0xe3, 0x0e,
- 0x56, 0x23, 0x21, 0x86, 0x9d, 0x2c, 0xf0, 0xa8, 0x08, 0xaf, 0xd2, 0xe6,
- 0xaf, 0x08, 0xa9, 0xca, 0xe6, 0x7f, 0x70, 0x93, 0x73, 0xfe, 0x72, 0xfd,
- 0x34, 0xa0, 0x64, 0x72, 0x8e, 0x56, 0x1b, 0x31, 0x28, 0xbe, 0x8f, 0xf1,
- 0xb3, 0x97, 0x27, 0x3d, 0x22, 0x30, 0x52, 0x94, 0x1f, 0xbf, 0xe9, 0x73,
- 0xcd, 0x2d, 0xdd, 0x66, 0x89, 0x25, 0x6e, 0x7d, 0x44, 0x23, 0x9e, 0xdc,
- 0xdf, 0xe7, 0x2f, 0xf3, 0xf8, 0x72, 0x77, 0x13, 0x97, 0x2a, 0xd9, 0xcb,
- 0xfa, 0x4f, 0xa9, 0xc3, 0x07, 0x2f, 0xec, 0x17, 0xfa, 0x5b, 0x39, 0x7f,
- 0xfe, 0x00, 0xba, 0xbe, 0x56, 0x06, 0x59, 0xd4, 0x61, 0xcb, 0xfa, 0x19,
- 0xac, 0x0f, 0x8e, 0x5f, 0xb8, 0x3b, 0x02, 0xa9, 0xcb, 0x9f, 0x98, 0x53,
- 0x6b, 0x54, 0x67, 0xe3, 0x19, 0x86, 0x74, 0x5c, 0xc2, 0xdd, 0xaa, 0xf8,
- 0xb6, 0xa7, 0x6f, 0x34, 0xe5, 0x5a, 0xf8, 0xac, 0xe6, 0x65, 0xaf, 0xe3,
- 0x6f, 0xdc, 0x72, 0xde, 0x8c, 0xcf, 0x8c, 0x72, 0xb7, 0xfe, 0x55, 0xf9,
- 0xe6, 0x96, 0xee, 0xb3, 0x45, 0xa8, 0xbf, 0xf3, 0xcb, 0x9e, 0x69, 0x6e,
- 0xeb, 0x34, 0x4a, 0xab, 0x91, 0xb3, 0x94, 0x72, 0xdc, 0xd5, 0x45, 0xdb,
- 0x13, 0x7c, 0x99, 0xc0, 0x2f, 0x7f, 0x66, 0x96, 0xee, 0xb3, 0x44, 0x52,
- 0xbf, 0xf3, 0xbb, 0x33, 0x5f, 0x88, 0x3f, 0x39, 0x7f, 0xe8, 0xf6, 0xf3,
- 0x5f, 0x88, 0x3f, 0x39, 0x7c, 0x9b, 0x87, 0x39, 0x7f, 0x85, 0xff, 0xdf,
- 0xb1, 0x67, 0x2e, 0x67, 0x3e, 0xa3, 0x48, 0x4f, 0xf6, 0x81, 0xe2, 0x0a,
- 0xe6, 0x9a, 0xab, 0xc6, 0x17, 0x7f, 0xb9, 0xe6, 0x96, 0xee, 0xb3, 0x44,
- 0x68, 0xb8, 0x1d, 0x39, 0x7f, 0xe0, 0xe3, 0x13, 0x59, 0xb9, 0xa0, 0xe5,
- 0xff, 0xff, 0x38, 0x37, 0xdc, 0x0a, 0x8a, 0x6d, 0x14, 0xf2, 0x6e, 0x65,
- 0x0e, 0x5f, 0xfe, 0x99, 0x13, 0xb3, 0x67, 0xa3, 0xd0, 0x13, 0x97, 0x91,
- 0xdb, 0x29, 0x48, 0x98, 0x83, 0x59, 0xf4, 0xcd, 0x8c, 0x4a, 0xbe, 0x5b,
- 0xba, 0xcd, 0x14, 0xfa, 0xef, 0x41, 0xca, 0xd1, 0xe2, 0x78, 0xba, 0xff,
- 0x27, 0x93, 0xdd, 0x07, 0x8e, 0x5f, 0xf4, 0xd1, 0xee, 0xbc, 0xdc, 0xb0,
- 0xe5, 0x68, 0xfb, 0xfc, 0x67, 0x78, 0x1d, 0x01, 0xcb, 0xff, 0xc8, 0xc1,
- 0x07, 0x53, 0x59, 0xb9, 0xa0, 0xe5, 0xff, 0xc0, 0xf6, 0x81, 0x36, 0xd6,
- 0xf3, 0x6c, 0xe5, 0xff, 0xd9, 0x30, 0x06, 0x7d, 0xad, 0xe6, 0xd9, 0xcb,
- 0xe0, 0x75, 0x34, 0x72, 0xdc, 0xda, 0xb5, 0x6e, 0xd1, 0x19, 0x3e, 0x42,
- 0x15, 0x21, 0x23, 0xd2, 0x27, 0x1d, 0x14, 0x9f, 0x24, 0x34, 0x47, 0xbf,
- 0xfd, 0xcd, 0x8f, 0x2e, 0x79, 0xa5, 0xbb, 0xac, 0xd1, 0x35, 0x2f, 0xec,
- 0xd2, 0xdd, 0xd6, 0x68, 0xae, 0xd7, 0xff, 0xb3, 0x81, 0x3c, 0x92, 0xe4,
- 0x31, 0xed, 0x9c, 0xa3, 0x97, 0x37, 0xcf, 0xa7, 0xb0, 0xda, 0x6d, 0x73,
- 0x46, 0x1a, 0x42, 0x46, 0xef, 0xd0, 0xe5, 0xed, 0xc3, 0x0e, 0x5c, 0xc1,
- 0x39, 0x7c, 0xb7, 0x75, 0x9a, 0x2b, 0xe5, 0xe6, 0xdb, 0x6c, 0xa5, 0x84,
- 0xa7, 0x33, 0x41, 0x5a, 0x3f, 0x06, 0x27, 0x5e, 0x94, 0x7c, 0x72, 0xf4,
- 0xd9, 0xd3, 0x97, 0xfe, 0xce, 0xb6, 0xfe, 0xdc, 0x64, 0xe7, 0x2d, 0xe3,
- 0x97, 0xfc, 0x9a, 0xc9, 0xd2, 0x58, 0x13, 0x95, 0xa3, 0xc9, 0x71, 0x1b,
- 0xf7, 0xdc, 0x1d, 0x02, 0x87, 0x2d, 0xa3, 0x94, 0x72, 0x90, 0xbc, 0xd0,
- 0x8d, 0xd3, 0xaa, 0x72, 0xba, 0x6e, 0x1c, 0x7e, 0xdc, 0xda, 0x8a, 0xa6,
- 0x08, 0x17, 0x9c, 0x73, 0x21, 0x0d, 0x31, 0x13, 0x8e, 0x88, 0xee, 0xe1,
- 0x10, 0x02, 0x16, 0x90, 0x82, 0xbf, 0xfd, 0xcd, 0x8f, 0x2e, 0x79, 0xa5,
- 0xbb, 0xac, 0xd1, 0x3d, 0xaf, 0xa3, 0x81, 0xfe, 0x39, 0x79, 0x07, 0xf3,
- 0x95, 0xd3, 0xc1, 0xe2, 0x4b, 0x7e, 0xd2, 0xdd, 0xd6, 0x68, 0xb8, 0x56,
- 0xe7, 0x07, 0xb1, 0x84, 0x97, 0xff, 0x73, 0x79, 0x73, 0xcd, 0x2d, 0xdd,
- 0x66, 0x89, 0x3d, 0x50, 0xcb, 0xd9, 0x9e, 0x39, 0xe9, 0x15, 0xab, 0x2e,
- 0xdd, 0x70, 0x9a, 0x9a, 0x31, 0xdd, 0x4a, 0x89, 0xec, 0x2a, 0xb7, 0x0f,
- 0x3e, 0x25, 0x17, 0xfb, 0x9e, 0x69, 0x6e, 0xeb, 0x34, 0x45, 0x4b, 0xf6,
- 0x96, 0xee, 0xb3, 0x45, 0x32, 0xbf, 0x93, 0xb8, 0xff, 0x7e, 0x72, 0xdc,
- 0xf0, 0xf8, 0x9a, 0x1a, 0x5f, 0xfe, 0xe6, 0xc7, 0x97, 0x3c, 0xd2, 0xdd,
- 0xd6, 0x68, 0x99, 0xd7, 0xff, 0xb9, 0xb1, 0xe5, 0xcf, 0x34, 0xb7, 0x75,
- 0x9a, 0x28, 0xd5, 0x4e, 0x9c, 0x10, 0x61, 0x46, 0xa9, 0x5f, 0x96, 0xaf,
- 0xfc, 0xf2, 0xe7, 0x9a, 0x5b, 0xba, 0xcd, 0x11, 0xd2, 0xff, 0xed, 0x4f,
- 0xcf, 0x63, 0x9e, 0xdc, 0x30, 0xe5, 0xff, 0xfe, 0xd4, 0xb9, 0xe0, 0x83,
- 0xc0, 0x57, 0xdf, 0x2d, 0x35, 0xb3, 0x95, 0xcd, 0x1f, 0x30, 0x98, 0x88,
- 0xf7, 0x03, 0xa7, 0x2f, 0x96, 0xb0, 0x2c, 0xe5, 0xfb, 0x04, 0x39, 0x39,
- 0xcb, 0xfd, 0x10, 0xbc, 0xd6, 0xb0, 0xe5, 0x21, 0xec, 0x09, 0x3d, 0xfb,
- 0x34, 0xb0, 0x2a, 0x72, 0xff, 0xc3, 0x8a, 0xbc, 0xdb, 0xec, 0x04, 0xe5,
- 0xe9, 0x9f, 0xc7, 0x2f, 0x96, 0xee, 0xb3, 0x45, 0x34, 0xbf, 0x67, 0xcd,
- 0xbf, 0x4e, 0x5f, 0xfd, 0xbc, 0x10, 0xc7, 0x26, 0xa3, 0xc7, 0xf4, 0x39,
- 0x41, 0x4c, 0xa9, 0x0a, 0x66, 0x3f, 0xd0, 0xe8, 0x97, 0x6c, 0xa6, 0xff,
- 0xff, 0xb0, 0x7d, 0xb4, 0x5e, 0x0e, 0xd7, 0xd4, 0xea, 0xd4, 0x9c, 0xe5,
- 0xff, 0x6d, 0xfe, 0xc9, 0xa3, 0xbb, 0x39, 0x77, 0x50, 0x51, 0x43, 0xe6,
- 0x7b, 0xff, 0xa5, 0xd4, 0x19, 0xf6, 0x08, 0xd4, 0xc7, 0x2f, 0x49, 0x92,
- 0x39, 0x7b, 0xff, 0x21, 0xcb, 0xfd, 0xb5, 0xa6, 0xb4, 0x93, 0x9c, 0xa7,
- 0x3d, 0x1d, 0x8e, 0xdf, 0xff, 0xf6, 0x4f, 0x38, 0x35, 0x36, 0xe7, 0x89,
- 0xb7, 0xdc, 0x0a, 0x71, 0x39, 0x7f, 0x80, 0xe2, 0xbe, 0x53, 0xec, 0xe5,
- 0xfd, 0x03, 0xe6, 0x99, 0xe3, 0x97, 0xf9, 0xff, 0x7f, 0x7b, 0x3a, 0x72,
- 0xa4, 0x7c, 0x2d, 0x97, 0x5d, 0xd0, 0x1c, 0xac, 0x37, 0x5f, 0x91, 0xdf,
- 0xee, 0xc2, 0x7e, 0xfe, 0x01, 0xcb, 0xff, 0x08, 0x3d, 0xdc, 0x9a, 0x51,
- 0xf1, 0xcb, 0x4c, 0x72, 0xfd, 0x9d, 0x71, 0x09, 0xca, 0x9c, 0xdc, 0x7e,
- 0x25, 0x74, 0x2a, 0x72, 0xfe, 0x7f, 0xf7, 0xc2, 0xb8, 0x57, 0x0a, 0x39,
- 0x7f, 0x24, 0x32, 0x7c, 0x6c, 0xe5, 0xff, 0xf6, 0x7b, 0xb9, 0x2d, 0x38,
- 0xfb, 0xaf, 0x23, 0x97, 0x47, 0xe7, 0x2f, 0xf3, 0xfd, 0x0b, 0x45, 0xf3,
- 0xd2, 0x24, 0xc4, 0xb9, 0x44, 0xea, 0xc4, 0xf8, 0x11, 0xe3, 0xa4, 0x62,
- 0x2f, 0xb8, 0x6a, 0x5f, 0xbf, 0xec, 0x4b, 0x67, 0x2f, 0x36, 0xf3, 0x9c,
- 0xbf, 0xe8, 0xfd, 0xfd, 0xfa, 0x83, 0x23, 0x95, 0xd3, 0xd9, 0x11, 0xea,
- 0x84, 0x51, 0xfa, 0x10, 0x56, 0xe6, 0xd5, 0xb2, 0x18, 0x20, 0x5c, 0x2f,
- 0x79, 0x1a, 0x52, 0xe1, 0xf1, 0xf1, 0x6a, 0x23, 0x69, 0xbb, 0xa4, 0x3f,
- 0xb7, 0x0c, 0x34, 0x76, 0x43, 0xe9, 0x42, 0x6a, 0x43, 0xc2, 0xfd, 0xa5,
- 0xbb, 0xac, 0xd1, 0x55, 0x2f, 0xfc, 0xf2, 0xe7, 0x9a, 0x5b, 0xba, 0xcd,
- 0x13, 0x6a, 0xdc, 0xf1, 0x10, 0x0c, 0x34, 0xbf, 0xdc, 0xf3, 0x4b, 0x77,
- 0x59, 0xa2, 0xbf, 0x5f, 0xb4, 0xb7, 0x75, 0x9a, 0x2c, 0x65, 0xdc, 0x12,
- 0x39, 0x6e, 0x78, 0x79, 0xd3, 0x1a, 0x5f, 0xb6, 0xbe, 0xc2, 0xa7, 0x2f,
- 0xf0, 0x82, 0x59, 0xb7, 0xf1, 0xcb, 0xf9, 0xaa, 0x0b, 0x56, 0xd5, 0x8a,
- 0xa7, 0x2f, 0xf8, 0x41, 0x3c, 0xd2, 0x8d, 0x4e, 0x72, 0xed, 0x78, 0xe5,
- 0xf3, 0xcb, 0x02, 0x72, 0xfe, 0xf6, 0x68, 0x38, 0x27, 0x2d, 0x81, 0x3c,
- 0xdf, 0x10, 0xde, 0x56, 0x58, 0x72, 0xfe, 0xcd, 0x7b, 0xb9, 0x39, 0xcb,
- 0x73, 0xc4, 0xe0, 0x98, 0x65, 0xd3, 0xe7, 0x3c, 0x16, 0x4d, 0x93, 0xa8,
- 0x3b, 0x64, 0xe6, 0xa8, 0x5b, 0x51, 0xd5, 0xdf, 0xb4, 0xb7, 0x75, 0x9a,
- 0x2d, 0x55, 0xff, 0x9e, 0x5c, 0xf3, 0x4b, 0x77, 0x59, 0xa2, 0x82, 0x5f,
- 0xa1, 0xb6, 0x99, 0xa3, 0x96, 0xe7, 0x88, 0xaa, 0x61, 0xa2, 0x89, 0x97,
- 0xfe, 0x76, 0xfd, 0x9d, 0xe6, 0xfa, 0xf1, 0xcb, 0xfd, 0x03, 0xfc, 0x35,
- 0xbb, 0x0e, 0x5f, 0xfe, 0x9a, 0x38, 0xbe, 0xb7, 0xb4, 0xd6, 0x2a, 0x72,
- 0xff, 0xa1, 0x26, 0x8e, 0x2f, 0xad, 0x9c, 0xbb, 0x50, 0x72, 0xa4, 0x8d,
- 0x24, 0x35, 0xea, 0x6f, 0x01, 0xd5, 0xf2, 0xdd, 0xd6, 0x68, 0xb8, 0x97,
- 0xf0, 0x1f, 0xe0, 0xe6, 0x8e, 0x56, 0x8f, 0x73, 0x65, 0xd7, 0xec, 0x62,
- 0x70, 0x04, 0xe5, 0xd0, 0xc3, 0x94, 0xd6, 0x78, 0x1a, 0x2a, 0xbe, 0x7e,
- 0x04, 0x9c, 0xe5, 0xfb, 0xa0, 0x57, 0x04, 0xe5, 0xf8, 0x38, 0xd7, 0x1d,
- 0x39, 0x7b, 0x81, 0x16, 0x72, 0x82, 0x7e, 0x3a, 0x28, 0xe0, 0x2a, 0xbf,
- 0xcc, 0x79, 0x6d, 0x03, 0x87, 0x2f, 0xa1, 0x58, 0xd9, 0xcb, 0xf0, 0xf8,
- 0x5d, 0x53, 0x94, 0x72, 0xdb, 0xc3, 0x64, 0xd0, 0x9e, 0xfe, 0x63, 0xf1,
- 0x8d, 0x70, 0x1c, 0xbf, 0xf2, 0x07, 0x38, 0xb3, 0x25, 0xf4, 0x8e, 0x54,
- 0x1f, 0x9e, 0x19, 0x5f, 0xd9, 0xa7, 0xf0, 0x20, 0xe5, 0xff, 0xf3, 0x8c,
- 0x27, 0x06, 0xd3, 0x79, 0xdc, 0x68, 0x72, 0x82, 0x7f, 0xbc, 0x4b, 0x2f,
- 0xfe, 0x41, 0x04, 0xb3, 0x7b, 0x40, 0xe1, 0xca, 0x98, 0xf9, 0xbc, 0x49,
- 0x6e, 0x70, 0xb8, 0x63, 0x90, 0x9b, 0xd3, 0x17, 0x49, 0x5e, 0x12, 0xdf,
- 0x99, 0x09, 0x96, 0xd5, 0x3d, 0x09, 0xb5, 0x23, 0x03, 0xbf, 0xcd, 0x50,
- 0xb5, 0x7e, 0x68, 0xd5, 0x84, 0xe5, 0xfb, 0x86, 0xe1, 0x7f, 0xd5, 0x83,
- 0x97, 0xfe, 0x4f, 0xb8, 0x56, 0xf5, 0xcb, 0x97, 0x5a, 0x1c, 0xbe, 0xec,
- 0x79, 0x67, 0x29, 0xa8, 0x1f, 0x78, 0x53, 0x6f, 0xff, 0x70, 0xa5, 0x5b,
- 0x6b, 0x9c, 0x3c, 0x37, 0x2e, 0x5d, 0x68, 0x72, 0xfd, 0xa5, 0xbb, 0xac,
- 0xd1, 0x74, 0xaf, 0xd0, 0x2e, 0x18, 0x39, 0x7f, 0x4a, 0x3e, 0x7d, 0xc8,
- 0xe5, 0xe8, 0xf7, 0x01, 0xcb, 0xec, 0x0e, 0x04, 0xe5, 0xff, 0x3f, 0x18,
- 0xf6, 0xc0, 0xbe, 0x1c, 0xe5, 0xf6, 0xe7, 0x75, 0x0e, 0x5b, 0x9b, 0x52,
- 0xaa, 0x87, 0x85, 0x22, 0xc4, 0x29, 0x64, 0x51, 0x8c, 0x88, 0x69, 0x31,
- 0x2f, 0x4b, 0x9c, 0x7c, 0x48, 0x7c, 0x81, 0x7f, 0xfd, 0x83, 0xe4, 0x67,
- 0x61, 0x05, 0xf4, 0xa9, 0xcb, 0xff, 0x33, 0x60, 0xf4, 0x93, 0x8f, 0x50,
- 0xe5, 0xfd, 0x99, 0xb5, 0xfa, 0x0e, 0x5f, 0xd3, 0xc7, 0x9d, 0x50, 0x1c,
- 0xa3, 0x97, 0xff, 0x46, 0xbf, 0xe5, 0xbe, 0xc3, 0x1c, 0x4e, 0x5f, 0xe8,
- 0xd2, 0x9d, 0xee, 0x7e, 0x72, 0xa4, 0x7f, 0x7d, 0x46, 0xbf, 0xa4, 0xf2,
- 0x71, 0x59, 0xcb, 0xff, 0xd9, 0xe8, 0x6d, 0x49, 0xf7, 0x8c, 0x86, 0xb3,
- 0x96, 0xe6, 0xd5, 0x26, 0x47, 0x90, 0x86, 0x98, 0x88, 0x4b, 0x2b, 0x49,
- 0xd0, 0xb2, 0x35, 0x2b, 0xec, 0x6d, 0xaa, 0x61, 0xcb, 0xf8, 0x63, 0xe6,
- 0x3f, 0x8e, 0x5f, 0xfe, 0x6d, 0xc3, 0xd8, 0xfb, 0xd1, 0xd7, 0x6b, 0x39,
- 0x64, 0xd1, 0xfd, 0xf4, 0xb6, 0xff, 0xff, 0x81, 0xa9, 0x6f, 0xae, 0x9a,
- 0xd6, 0x81, 0xf2, 0x69, 0xf6, 0x72, 0xff, 0xc2, 0xed, 0xfb, 0x3a, 0xf3,
- 0x39, 0xcb, 0xff, 0xfb, 0xa2, 0x07, 0x6b, 0xc9, 0x77, 0x15, 0xc0, 0xcc,
- 0x03, 0x97, 0x2f, 0x0e, 0x54, 0x1f, 0xaa, 0xab, 0xf7, 0xf9, 0xfd, 0xb8,
- 0xea, 0x93, 0x1c, 0xbd, 0x28, 0x61, 0xcb, 0xca, 0xee, 0x47, 0x2f, 0xf6,
- 0xb4, 0xf2, 0x9f, 0x1b, 0x39, 0x74, 0xc0, 0x39, 0x69, 0x61, 0xe6, 0xb6,
- 0x6b, 0x7f, 0xf6, 0x06, 0x25, 0x1a, 0x85, 0x1c, 0x4e, 0x5f, 0xfb, 0x8e,
- 0x49, 0x81, 0x4e, 0x30, 0x13, 0x94, 0xc4, 0x42, 0x3a, 0x15, 0xcf, 0xce,
- 0x75, 0x58, 0xf3, 0x34, 0x6a, 0x16, 0x7d, 0x22, 0x73, 0x5d, 0x8e, 0x79,
- 0xad, 0x48, 0x56, 0x57, 0x55, 0xbd, 0x0c, 0xae, 0xeb, 0xfd, 0x2c, 0xf7,
- 0x61, 0x41, 0x39, 0x7f, 0xef, 0x22, 0xd0, 0x2e, 0x2a, 0xc1, 0xcb, 0xfe,
- 0x8f, 0xba, 0xfb, 0xf4, 0x36, 0x72, 0xa0, 0xfd, 0xf4, 0x7b, 0x70, 0x3a,
- 0x72, 0xfc, 0x39, 0xd7, 0xf1, 0xcb, 0xfa, 0x4f, 0x9c, 0x60, 0x27, 0x2b,
- 0x84, 0x3d, 0x46, 0xa2, 0x4d, 0x7c, 0x80, 0x94, 0x1c, 0xbe, 0x41, 0x8f,
- 0xce, 0x5f, 0x9e, 0x69, 0x27, 0x8e, 0x5f, 0xfa, 0x03, 0xa8, 0x92, 0x7d,
- 0xec, 0x39, 0x52, 0x45, 0x42, 0xc8, 0x7f, 0x21, 0xf1, 0x45, 0xff, 0xa3,
- 0x5b, 0xea, 0x2d, 0x60, 0x9c, 0xe5, 0xff, 0xff, 0x40, 0x7b, 0x9f, 0x78,
- 0x5f, 0xbf, 0xbe, 0xf6, 0xfa, 0x59, 0xcb, 0xfd, 0x99, 0x8a, 0xaa, 0xf2,
- 0x39, 0x4a, 0xa2, 0x6b, 0xcc, 0xf7, 0xec, 0xda, 0xfd, 0x07, 0x2f, 0xff,
- 0x23, 0x7b, 0x5f, 0x53, 0xef, 0x6b, 0x50, 0x72, 0xff, 0xff, 0x9d, 0xb5,
- 0x33, 0x42, 0xff, 0x49, 0x71, 0xed, 0xe7, 0xde, 0x39, 0x58, 0x8d, 0xcd,
- 0x13, 0xba, 0x65, 0xfb, 0x8a, 0x6b, 0x02, 0x72, 0xff, 0xfb, 0x7d, 0x4d,
- 0xfb, 0xb8, 0x14, 0xde, 0x09, 0xcb, 0xdd, 0x81, 0xc3, 0xf7, 0x01, 0x4d,
- 0xf9, 0xfb, 0x21, 0x59, 0xcb, 0xfd, 0x0c, 0xc4, 0x64, 0x35, 0x9c, 0xbf,
- 0xd2, 0x66, 0xd0, 0x7e, 0x91, 0xca, 0x59, 0xf4, 0x4c, 0x69, 0x7f, 0xfb,
- 0x35, 0xa7, 0x96, 0xc7, 0x18, 0xa7, 0xc7, 0x2f, 0x3b, 0xac, 0xd1, 0x26,
- 0x2f, 0x70, 0x26, 0xce, 0x52, 0xcf, 0x1f, 0x80, 0xa2, 0xfc, 0xbe, 0x15,
- 0xc3, 0x35, 0x5c, 0x21, 0xcb, 0xff, 0xdf, 0x4b, 0x79, 0xc5, 0xd9, 0x8a,
- 0xc6, 0xce, 0x5f, 0xec, 0xfb, 0xde, 0x79, 0x6c, 0xe5, 0x42, 0x2f, 0xf0,
- 0xfb, 0x49, 0xb7, 0xf8, 0x5f, 0xdb, 0x58, 0x04, 0xe5, 0xff, 0xf7, 0xe9,
- 0xfb, 0x78, 0x9c, 0x47, 0x3d, 0xd4, 0x39, 0x7f, 0x9f, 0xed, 0xbb, 0xcb,
- 0x67, 0x2d, 0xac, 0x44, 0x2f, 0x54, 0xab, 0x11, 0xbe, 0x90, 0xb7, 0xbf,
- 0xff, 0xc0, 0x7f, 0xb0, 0x61, 0xb5, 0x3c, 0x31, 0xfe, 0x7d, 0xe3, 0x95,
- 0x25, 0x7d, 0xe1, 0x31, 0xc8, 0x47, 0xac, 0x8f, 0x50, 0x92, 0x64, 0x39,
- 0x3b, 0x18, 0x6e, 0xc9, 0xaf, 0xe0, 0xff, 0xc2, 0x6f, 0xf6, 0x87, 0x2f,
- 0x6d, 0x02, 0x72, 0xfe, 0x18, 0xf9, 0x8f, 0xe3, 0x97, 0xfd, 0x0b, 0xf0,
- 0x3b, 0xa8, 0x6c, 0xe5, 0xff, 0x26, 0x36, 0xbe, 0xc2, 0x34, 0x39, 0x7f,
- 0x96, 0x9a, 0xdc, 0xd0, 0xe7, 0x2f, 0xfe, 0x06, 0xfa, 0xf2, 0xeb, 0xca,
- 0x04, 0xe5, 0x7c, 0x7e, 0xda, 0x33, 0xbb, 0xa9, 0x32, 0x6a, 0xda, 0x1c,
- 0x61, 0x6f, 0x0e, 0x75, 0xe8, 0x58, 0x5f, 0x79, 0x18, 0xe7, 0x2c, 0xa9,
- 0xcb, 0xfb, 0xbb, 0x8f, 0x40, 0x4e, 0x56, 0x1b, 0xf4, 0x12, 0xac, 0x3f,
- 0xff, 0x30, 0x5f, 0xf4, 0x77, 0xc9, 0x3b, 0x21, 0x67, 0x2f, 0xff, 0xce,
- 0xbd, 0x47, 0x47, 0x3d, 0x9c, 0xdb, 0x6d, 0xb2, 0x95, 0x24, 0x59, 0xec,
- 0x87, 0xc7, 0x37, 0xf2, 0xd6, 0x05, 0x8c, 0x1c, 0xbf, 0xfb, 0xe9, 0x0c,
- 0x4b, 0x51, 0xe7, 0xf1, 0xcb, 0xa2, 0x47, 0x2b, 0x0f, 0x68, 0x51, 0x2f,
- 0xfc, 0xfe, 0x8d, 0x6f, 0xb0, 0x3e, 0x39, 0x7e, 0xc9, 0x23, 0xf1, 0x39,
- 0x42, 0x7c, 0xbb, 0x3d, 0xa9, 0x22, 0x98, 0x10, 0x85, 0xbc, 0xc7, 0xe9,
- 0xcb, 0xff, 0xc3, 0x12, 0xd6, 0x81, 0xf2, 0x69, 0xf6, 0x72, 0xff, 0xfb,
- 0x78, 0xa8, 0xe7, 0xb7, 0x92, 0x17, 0x6c, 0xe5, 0x93, 0xa8, 0x99, 0xf2,
- 0x55, 0x22, 0x37, 0x78, 0xc2, 0xd6, 0xfb, 0x82, 0x3b, 0xb3, 0x97, 0xfa,
- 0x7f, 0x0c, 0x03, 0xdb, 0x39, 0x7f, 0x99, 0xec, 0x9a, 0x4e, 0x27, 0x2b,
- 0x0f, 0x9d, 0x0d, 0x2a, 0x11, 0xab, 0x85, 0x3a, 0x84, 0x65, 0xef, 0xff,
- 0x83, 0x97, 0xe1, 0x04, 0xff, 0x35, 0x9c, 0xad, 0x9e, 0x5f, 0x87, 0xaf,
- 0xff, 0x44, 0xe3, 0x99, 0x3f, 0x95, 0x81, 0x91, 0xcb, 0xff, 0x38, 0xcf,
- 0xd7, 0x62, 0x6d, 0x0e, 0x53, 0xa2, 0xa4, 0x48, 0x9b, 0x4a, 0xbc, 0xdb,
- 0x6d, 0x94, 0xbe, 0x9d, 0x89, 0xb2, 0x9c, 0xcd, 0x05, 0xd0, 0x13, 0x96,
- 0xd3, 0x9e, 0x58, 0x9a, 0xdf, 0xa3, 0x05, 0xd8, 0x72, 0xff, 0xcf, 0x2e,
- 0xa7, 0xdf, 0xe9, 0xc2, 0x72, 0xe0, 0xb6, 0x72, 0xff, 0xfd, 0x9c, 0x60,
- 0x7c, 0xc8, 0xc1, 0x0e, 0x7d, 0xe3, 0x97, 0x9c, 0x57, 0x39, 0xf6, 0xe8,
- 0x62, 0xbf, 0x4c, 0x14, 0x49, 0x41, 0x0a, 0xdb, 0xfd, 0x28, 0xd4, 0xf1,
- 0xa9, 0xce, 0x5f, 0xdb, 0xda, 0x60, 0xfe, 0x72, 0xf6, 0xb1, 0xac, 0xe5,
- 0xff, 0x36, 0xa4, 0xfb, 0xc6, 0x43, 0x59, 0xcb, 0xff, 0xc8, 0xbc, 0x10,
- 0xe9, 0xd7, 0x9f, 0x78, 0xe5, 0x42, 0x22, 0x36, 0x7f, 0x5a, 0x47, 0xb3,
- 0x0b, 0x7d, 0x0a, 0x7a, 0x84, 0xd8, 0x32, 0x32, 0xbb, 0xff, 0xe4, 0x98,
- 0x63, 0xdb, 0xf7, 0xcb, 0x41, 0x9c, 0xe5, 0xff, 0xff, 0xe4, 0x1f, 0xd4,
- 0x1c, 0xd6, 0xb1, 0xbc, 0x6b, 0xc1, 0x8f, 0xd8, 0xf2, 0x39, 0x7f, 0xff,
- 0x7b, 0x60, 0x0f, 0x53, 0x26, 0x74, 0x6b, 0x4f, 0xa4, 0x72, 0xff, 0xfe,
- 0x1c, 0xfd, 0xc7, 0xfd, 0x6b, 0x1b, 0xcf, 0xdf, 0xe3, 0x94, 0x28, 0xbc,
- 0xf2, 0xfd, 0xf9, 0x3d, 0x3e, 0x36, 0x72, 0xff, 0xa1, 0x7d, 0x10, 0x7a,
- 0x36, 0x72, 0xff, 0xe4, 0xe0, 0x85, 0xc3, 0x30, 0x2e, 0xc3, 0x97, 0xff,
- 0xa2, 0x5b, 0xc8, 0x0a, 0x0b, 0xe9, 0x53, 0x97, 0xff, 0xef, 0x77, 0x25,
- 0xc9, 0x7d, 0x4f, 0x7c, 0xb4, 0xd1, 0xca, 0x92, 0xa9, 0xf4, 0x8c, 0xdb,
- 0x44, 0x4c, 0x29, 0xe9, 0xc7, 0xe8, 0xa2, 0x91, 0x7f, 0xff, 0xba, 0x82,
- 0x1d, 0x62, 0xfb, 0x1d, 0xcd, 0x6a, 0x15, 0x39, 0x7f, 0xe5, 0xac, 0x0d,
- 0x7b, 0x46, 0xf3, 0x47, 0x2f, 0xff, 0xfc, 0x9e, 0x06, 0x9f, 0x6b, 0xea,
- 0x4c, 0x2e, 0xdf, 0xb3, 0xac, 0x39, 0x48, 0x8b, 0x07, 0x43, 0xbf, 0xe6,
- 0x46, 0xb8, 0xe6, 0xa2, 0x63, 0x97, 0xfe, 0xd2, 0xd9, 0x1f, 0x6f, 0x38,
- 0xe1, 0xcb, 0x9d, 0xac, 0xe5, 0xff, 0xfd, 0x30, 0xc0, 0x73, 0xef, 0x64,
- 0xa0, 0x67, 0x66, 0x1c, 0xbf, 0xbf, 0x69, 0x81, 0xc6, 0x1c, 0xae, 0xa2,
- 0x2c, 0x56, 0xef, 0xe1, 0xe4, 0xd3, 0x35, 0x07, 0x2a, 0x13, 0x37, 0x9d,
- 0x07, 0x21, 0x48, 0xe4, 0x57, 0xf9, 0xff, 0xe5, 0x81, 0x79, 0x1c, 0xb2,
- 0xa7, 0x2f, 0xfe, 0xc5, 0xf6, 0x3b, 0x9a, 0xd4, 0x2a, 0x72, 0xfd, 0x9a,
- 0xd4, 0x2a, 0x72, 0xf8, 0x53, 0xfd, 0xc1, 0xff, 0x68, 0x4b, 0xa8, 0x97,
- 0xfe, 0xce, 0xbf, 0xec, 0x79, 0x3e, 0xce, 0x56, 0x26, 0x6c, 0x90, 0xb3,
- 0xea, 0x2d, 0xff, 0xe7, 0x9f, 0xa9, 0x03, 0x93, 0x26, 0x90, 0xe5, 0x05,
- 0x7f, 0xc7, 0x25, 0x78, 0x4c, 0xd7, 0xd8, 0xc4, 0x3f, 0x21, 0xdc, 0x6e,
- 0x5e, 0x8d, 0xdd, 0xb3, 0x4b, 0xf0, 0xe7, 0x5f, 0xc7, 0x2f, 0xfd, 0x28,
- 0x19, 0xd4, 0xd0, 0x82, 0x47, 0x2f, 0xe1, 0x70, 0xff, 0xf7, 0xe7, 0x29,
- 0xad, 0x12, 0xd3, 0x13, 0x6d, 0x02, 0xfb, 0xd3, 0xe0, 0x4e, 0x5f, 0xf2,
- 0x2a, 0xa6, 0xbf, 0x62, 0x6c, 0xe5, 0x4c, 0x7b, 0xed, 0x08, 0xef, 0x36,
- 0xdb, 0x67, 0x2f, 0xff, 0xd8, 0xcf, 0x0c, 0x7f, 0x81, 0xde, 0x32, 0x16,
- 0x53, 0x99, 0xa0, 0xbf, 0xf6, 0x7d, 0xc8, 0x73, 0x8e, 0x93, 0x67, 0x2f,
- 0xe5, 0xf5, 0x20, 0x56, 0x72, 0xa0, 0xfb, 0xb1, 0x0a, 0xff, 0x6a, 0x3c,
- 0x8b, 0x40, 0x9c, 0xbf, 0x4a, 0x6c, 0xc5, 0x9c, 0xb6, 0x8e, 0x53, 0x52,
- 0x7d, 0x70, 0x64, 0xa1, 0x45, 0x62, 0xa6, 0xb4, 0x84, 0x9f, 0x51, 0x46,
- 0x1a, 0x9b, 0x84, 0x5d, 0xef, 0x4b, 0xa7, 0x2c, 0x87, 0x2f, 0xee, 0xc7,
- 0x25, 0xa4, 0xe7, 0x2f, 0xff, 0x4d, 0xd7, 0x66, 0x69, 0x55, 0x40, 0x3e,
- 0x39, 0x7f, 0x69, 0xf4, 0x31, 0x23, 0x97, 0xff, 0xcf, 0xee, 0xe7, 0x1e,
- 0xa7, 0x2d, 0xed, 0x18, 0x72, 0xff, 0xc9, 0x24, 0xd7, 0xd0, 0x31, 0xb3,
- 0x95, 0xc2, 0xe9, 0xa4, 0x84, 0x43, 0x0c, 0x34, 0x9a, 0x25, 0x9e, 0x53,
- 0xba, 0x5c, 0xda, 0xb7, 0x42, 0x23, 0xc3, 0x35, 0xc4, 0x35, 0x67, 0x3e,
- 0x94, 0x36, 0x83, 0x18, 0x06, 0x4e, 0x4a, 0x2b, 0x08, 0x75, 0xc7, 0x1d,
- 0xf4, 0x72, 0x68, 0x61, 0x34, 0x65, 0xba, 0x8f, 0x6b, 0xb1, 0x93, 0xbc,
- 0x26, 0xbf, 0x8c, 0xac, 0x63, 0x96, 0xdd, 0x20, 0x67, 0xd2, 0xe4, 0x1a,
- 0x2c, 0x29, 0x1b, 0x35, 0xff, 0xed, 0x63, 0x61, 0xee, 0x4c, 0x39, 0xa9,
- 0x1c, 0xbd, 0xac, 0x6b, 0x39, 0x7f, 0xe8, 0x6d, 0x49, 0xf7, 0x8c, 0x86,
- 0xb3, 0x95, 0xa4, 0x57, 0x31, 0x2f, 0xc3, 0xf7, 0xff, 0xce, 0xc8, 0xd2,
- 0xf4, 0x05, 0x74, 0x07, 0xd9, 0xca, 0xc4, 0x40, 0x80, 0xc2, 0xff, 0x69,
- 0x60, 0x70, 0xb2, 0x0e, 0x5f, 0xfd, 0x1a, 0x53, 0xc9, 0xee, 0xe0, 0x50,
- 0xe5, 0xfe, 0x1f, 0xbf, 0xcd, 0xbb, 0x59, 0xcb, 0xfe, 0x18, 0x9d, 0x4e,
- 0xf5, 0xda, 0xce, 0x56, 0x1f, 0xa7, 0x4d, 0xef, 0xff, 0xf9, 0x05, 0x3f,
- 0xde, 0xb1, 0x7d, 0x8e, 0xe6, 0xb5, 0x0a, 0x9c, 0xa8, 0x4d, 0xca, 0x73,
- 0x3c, 0x85, 0xc7, 0x88, 0x6f, 0x35, 0x16, 0xa6, 0x47, 0x2f, 0x3e, 0xa7,
- 0x39, 0x73, 0x6d, 0x9c, 0xbc, 0xeb, 0xe6, 0xb3, 0x6c, 0xd8, 0xed, 0xfd,
- 0x1a, 0x79, 0x27, 0x4e, 0x5f, 0xb1, 0x9d, 0x70, 0x9c, 0xb7, 0x38, 0x75,
- 0xc6, 0x32, 0x4d, 0x0a, 0x0e, 0x47, 0x9a, 0xa9, 0x52, 0xe7, 0x07, 0x66,
- 0x2b, 0xd4, 0x2a, 0x9e, 0xd0, 0x99, 0x0c, 0xac, 0xcd, 0xc7, 0x29, 0xe4,
- 0x2e, 0x2b, 0xcd, 0x9a, 0xf0, 0x16, 0x54, 0x9f, 0x19, 0xf8, 0x34, 0x89,
- 0x0f, 0xa3, 0x6b, 0xd1, 0x53, 0x21, 0x1f, 0xd9, 0x48, 0x1f, 0xc3, 0x70,
- 0x4e, 0x37, 0x3a, 0x89, 0xe9, 0x69, 0x40, 0xb5, 0xdb, 0xf7, 0xf6, 0xe2,
- 0x69, 0x24, 0xc7, 0x2f, 0xfb, 0xd0, 0x29, 0xfe, 0x7d, 0xe3, 0x97, 0xcd,
- 0x1c, 0x7f, 0x39, 0x74, 0x4f, 0x87, 0xba, 0xa1, 0xcd, 0x6d, 0x17, 0x4a,
- 0x42, 0x32, 0xff, 0x91, 0x68, 0x1e, 0x7d, 0x8f, 0xce, 0x57, 0x33, 0xe4,
- 0xf1, 0x4d, 0xff, 0x9d, 0x7c, 0xc1, 0xfa, 0x4b, 0x24, 0x72, 0xfd, 0xa5,
- 0xbb, 0xac, 0xd1, 0x1a, 0xaf, 0x2b, 0xf6, 0xce, 0x5b, 0x9c, 0xe8, 0x94,
- 0xc4, 0x1f, 0x1a, 0x5f, 0xff, 0xee, 0x30, 0x3e, 0xe6, 0xfc, 0x5c, 0x38,
- 0x17, 0x63, 0x84, 0xe5, 0xfb, 0x4b, 0x77, 0x59, 0xa2, 0xa5, 0x5c, 0xeb,
- 0x34, 0x43, 0x4b, 0x73, 0xc3, 0xd7, 0x73, 0x4b, 0xf6, 0x96, 0xee, 0xb3,
- 0x44, 0x7c, 0xbf, 0xf8, 0x1a, 0xfd, 0x7d, 0x49, 0x86, 0x3f, 0x39, 0x7f,
- 0xfc, 0x2f, 0xe9, 0x42, 0xbc, 0xa3, 0xdb, 0x8f, 0xce, 0x5e, 0x79, 0x73,
- 0xc4, 0x66, 0xec, 0xd1, 0x44, 0x7b, 0xff, 0x3c, 0xf1, 0xd4, 0xd2, 0x43,
- 0x0e, 0x5f, 0xe8, 0xd6, 0x0f, 0xb3, 0xa7, 0x2f, 0x33, 0x39, 0xb4, 0x3e,
- 0xe5, 0x0f, 0x6b, 0x9a, 0x3a, 0x62, 0x16, 0x37, 0xff, 0xfd, 0x20, 0x69,
- 0x57, 0xde, 0x06, 0x3e, 0xda, 0x9e, 0x55, 0x15, 0x39, 0x79, 0xb5, 0x56,
- 0x72, 0xfd, 0xf7, 0xd2, 0xcf, 0x1c, 0xad, 0x9e, 0x48, 0x07, 0xef, 0xff,
- 0x70, 0xa5, 0x5b, 0x6b, 0x9c, 0x3c, 0x37, 0x2e, 0x5d, 0x68, 0x72, 0xfd,
- 0xa5, 0xbb, 0xac, 0xd1, 0x63, 0xaf, 0xf6, 0x20, 0xcf, 0xec, 0xe9, 0xcb,
- 0x9f, 0x67, 0x2f, 0xe9, 0xd4, 0xd6, 0xb3, 0x47, 0x2a, 0x47, 0x8c, 0xe2,
- 0xd7, 0xfc, 0x2e, 0xaf, 0x52, 0x06, 0x73, 0x97, 0xff, 0xf0, 0x05, 0xd5,
- 0xe5, 0xe5, 0x60, 0x65, 0x9d, 0x46, 0x1c, 0xbf, 0xff, 0x7f, 0x29, 0xf8,
- 0x54, 0x35, 0x73, 0xaf, 0x5c, 0xb9, 0x75, 0xa1, 0xcb, 0x92, 0x47, 0x2f,
- 0xf7, 0x87, 0x38, 0xf5, 0xe4, 0x72, 0x82, 0x79, 0x58, 0x2d, 0x7e, 0x4f,
- 0x79, 0x3c, 0x72, 0xff, 0xfc, 0x01, 0x75, 0x7c, 0xac, 0x0c, 0xb3, 0xa8,
- 0xc3, 0x97, 0xda, 0xd6, 0x34, 0x39, 0x58, 0x8a, 0x06, 0x13, 0xba, 0xad,
- 0xfb, 0x35, 0x99, 0x31, 0xcb, 0x73, 0x85, 0xc6, 0x99, 0xe1, 0x6b, 0x22,
- 0x2c, 0x64, 0x54, 0xd1, 0x1e, 0x26, 0x21, 0x61, 0xc7, 0x57, 0x46, 0x16,
- 0xdb, 0x86, 0x0a, 0x85, 0xd7, 0xca, 0xa6, 0xa6, 0x39, 0x7b, 0x85, 0x31,
- 0x53, 0x97, 0xf7, 0x08, 0x39, 0xd7, 0xf1, 0xcb, 0xfc, 0xff, 0xed, 0xfd,
- 0xe7, 0x39, 0x73, 0x16, 0x72, 0x84, 0xf2, 0xbc, 0x67, 0x7f, 0xec, 0x6f,
- 0x58, 0x2f, 0xf4, 0xb6, 0x72, 0xfd, 0xd7, 0x64, 0x09, 0xcb, 0xed, 0xf5,
- 0x1b, 0x39, 0x7e, 0x86, 0xfd, 0x9d, 0x39, 0x7a, 0x14, 0xc3, 0x95, 0xc9,
- 0x11, 0xb8, 0x4c, 0x24, 0x7b, 0x28, 0xbf, 0xfd, 0x9c, 0x18, 0xbf, 0x7d,
- 0x2c, 0x1f, 0xdc, 0xe5, 0xf7, 0xec, 0x4d, 0x1c, 0xbd, 0x8e, 0x27, 0x2f,
- 0x76, 0x26, 0x39, 0x72, 0x79, 0x0d, 0xbb, 0x8d, 0x5f, 0xff, 0xf4, 0x68,
- 0x70, 0x39, 0xde, 0xa2, 0xfa, 0x9e, 0xdb, 0xfc, 0x72, 0xff, 0xfd, 0x93,
- 0x67, 0x00, 0xe7, 0x11, 0xcf, 0xd9, 0x12, 0x39, 0x7f, 0xcf, 0xf0, 0xe7,
- 0xb7, 0x8d, 0x9c, 0xa5, 0xa7, 0x90, 0x89, 0xad, 0x6b, 0x5d, 0x2a, 0x16,
- 0x50, 0x2c, 0xdf, 0xba, 0x9a, 0x04, 0x8e, 0x5f, 0xd1, 0xaf, 0xda, 0x03,
- 0xc7, 0x2f, 0xfa, 0x07, 0xdc, 0x33, 0xf8, 0x10, 0x72, 0xff, 0xf4, 0x76,
- 0x18, 0xbe, 0xa7, 0xb3, 0x18, 0x72, 0xfb, 0xff, 0xd1, 0x43, 0x97, 0xe9,
- 0x6e, 0x7c, 0x6c, 0xe5, 0xf7, 0x73, 0x53, 0x9c, 0xbc, 0xee, 0xb3, 0x45,
- 0xa0, 0xbf, 0xf3, 0xb7, 0xc0, 0xb7, 0xd4, 0xf8, 0xd9, 0xcb, 0xfb, 0xf8,
- 0x18, 0xf6, 0xce, 0x54, 0x23, 0x98, 0x25, 0x4b, 0x23, 0xd1, 0x47, 0xe8,
- 0x97, 0xff, 0xff, 0xc9, 0xae, 0xb8, 0xa4, 0x79, 0x3b, 0x1b, 0xee, 0x6f,
- 0x58, 0xbc, 0xf1, 0xcb, 0xff, 0xff, 0xc0, 0xdb, 0xea, 0x5b, 0x40, 0xe6,
- 0xa7, 0x4d, 0xf5, 0xff, 0xde, 0x09, 0xcb, 0xfa, 0x27, 0x63, 0xb8, 0x9c,
- 0xbf, 0xff, 0x77, 0x1b, 0xf3, 0x23, 0x3d, 0xdc, 0xc1, 0x59, 0xcb, 0xff,
- 0xf2, 0x7a, 0x59, 0xad, 0x3c, 0x94, 0x17, 0xf6, 0xce, 0x54, 0x2b, 0xf8,
- 0x91, 0x40, 0x4c, 0x56, 0x78, 0x89, 0x1a, 0x8c, 0x2f, 0xa9, 0x42, 0xf3,
- 0xb7, 0x8f, 0x16, 0x71, 0x54, 0xbb, 0x18, 0x72, 0xff, 0xe7, 0xfb, 0x8f,
- 0x5a, 0xd3, 0xc3, 0x0c, 0x39, 0x5a, 0x3d, 0xf7, 0x16, 0xbf, 0xff, 0x27,
- 0xb6, 0xff, 0x6f, 0x79, 0xd4, 0xd8, 0x27, 0x39, 0x7f, 0xfc, 0x09, 0xf4,
- 0x9e, 0x9c, 0x1a, 0x96, 0xda, 0xd0, 0xe5, 0x75, 0x15, 0xa2, 0xaf, 0x7f,
- 0x6d, 0xd4, 0xcf, 0xbc, 0x72, 0xff, 0x20, 0x71, 0x9c, 0xb0, 0x27, 0x2f,
- 0xff, 0x81, 0xad, 0x40, 0xe2, 0xa9, 0xde, 0xe2, 0x87, 0x2d, 0xc3, 0x9c,
- 0xad, 0x1f, 0x30, 0x14, 0x2f, 0xf3, 0x00, 0x3e, 0xd8, 0x34, 0x72, 0xa4,
- 0x8f, 0x0d, 0x42, 0x69, 0xa1, 0x15, 0xfc, 0x3f, 0x4b, 0xc0, 0x09, 0xcb,
- 0xf3, 0x5e, 0x0b, 0x10, 0xe5, 0x41, 0xec, 0x39, 0x7d, 0xff, 0xce, 0xdf,
- 0xb3, 0xbb, 0x9b, 0x32, 0x73, 0x97, 0xe9, 0xbb, 0x9f, 0xb9, 0xca, 0xea,
- 0x23, 0xc4, 0x83, 0x8a, 0x35, 0xff, 0xfe, 0xcc, 0xf6, 0xe2, 0x6e, 0xc7,
- 0x11, 0xc0, 0xf6, 0x36, 0x72, 0xfc, 0x2b, 0x7d, 0xa1, 0xcb, 0xff, 0xfb,
- 0x43, 0x11, 0xf7, 0x2d, 0xf8, 0x60, 0x3d, 0x8f, 0x1c, 0xb9, 0x3a, 0x72,
- 0xfa, 0x42, 0xea, 0x1c, 0xbf, 0xc1, 0x7f, 0xf5, 0xa7, 0xfc, 0xe5, 0xf6,
- 0x96, 0xd6, 0xd9, 0xcb, 0xe5, 0x78, 0x47, 0x6c, 0xe5, 0x61, 0xe8, 0x39,
- 0x3d, 0x22, 0x29, 0x46, 0x10, 0xb5, 0x09, 0xc2, 0xe1, 0x33, 0x5a, 0xe3,
- 0x8b, 0x02, 0x18, 0xf7, 0x9d, 0xad, 0x0e, 0x5f, 0xf9, 0x4f, 0x2a, 0x8a,
- 0xc6, 0x0c, 0x1c, 0xbf, 0x29, 0xe1, 0x8f, 0xce, 0x57, 0xc8, 0x86, 0xd0,
- 0xf7, 0x13, 0xfb, 0xf4, 0x7b, 0x3b, 0x07, 0x2f, 0xfd, 0x9f, 0x4b, 0x69,
- 0xe7, 0x1c, 0x39, 0x7f, 0xb1, 0x9d, 0xc9, 0x9e, 0x63, 0x97, 0xfe, 0xea,
- 0x07, 0x12, 0x7e, 0xc4, 0x72, 0x3f, 0x1f, 0x1e, 0xdf, 0xff, 0xfd, 0x08,
- 0x39, 0xe8, 0x63, 0x60, 0x79, 0xf9, 0x67, 0x53, 0x5d, 0x73, 0x97, 0xfe,
- 0xcf, 0xa5, 0xb9, 0xb4, 0xfe, 0xd9, 0xcb, 0xf0, 0xc2, 0xe4, 0xc3, 0x97,
- 0xff, 0x6f, 0x26, 0xec, 0x71, 0xce, 0xf6, 0x0e, 0x50, 0x4f, 0xb7, 0xc4,
- 0xf7, 0xf9, 0xff, 0xdb, 0x1f, 0xef, 0x1c, 0xac, 0x3d, 0x77, 0x22, 0xbf,
- 0xd1, 0x13, 0x67, 0x14, 0xd1, 0xcb, 0xe4, 0xd6, 0x09, 0xca, 0x13, 0xd4,
- 0xd9, 0xa5, 0x4e, 0xab, 0xe5, 0x70, 0x97, 0xd2, 0xb7, 0xee, 0x43, 0x18,
- 0x2f, 0x9d, 0x2f, 0xdc, 0xa6, 0x92, 0x4c, 0x72, 0xa1, 0x5d, 0xee, 0x4b,
- 0x2c, 0x46, 0x5b, 0xff, 0xba, 0x9c, 0xb0, 0x71, 0x34, 0xfc, 0x4e, 0x5f,
- 0xfc, 0x82, 0xe1, 0x1c, 0x0f, 0x63, 0x67, 0x2f, 0x29, 0x1a, 0x39, 0x7f,
- 0xff, 0xbb, 0x03, 0x9f, 0xef, 0x03, 0xd8, 0x9d, 0x80, 0x10, 0x9c, 0xbf,
- 0x27, 0xbd, 0x12, 0x39, 0x4a, 0xa6, 0x56, 0xb4, 0x5d, 0x20, 0xf8, 0x77,
- 0x8b, 0x0d, 0xff, 0xfd, 0x13, 0x60, 0x7b, 0x1c, 0x7b, 0x9e, 0x18, 0x86,
- 0x1c, 0xbf, 0xbe, 0xda, 0x93, 0x80, 0x4e, 0x5f, 0xf4, 0x2f, 0xa9, 0x33,
- 0xbc, 0xe7, 0x29, 0x88, 0xc5, 0x75, 0xbf, 0xcc, 0x6f, 0xf4, 0xa3, 0x53,
- 0xc6, 0xa7, 0x39, 0x7f, 0xe4, 0xe2, 0xe3, 0xff, 0x73, 0xf7, 0x39, 0x7f,
- 0x0c, 0xef, 0xd4, 0x13, 0x97, 0xfc, 0x80, 0x19, 0x6a, 0x30, 0x27, 0x2f,
- 0xff, 0xfb, 0xb9, 0x25, 0xf5, 0x3b, 0x19, 0xa9, 0x78, 0x61, 0x9b, 0x39,
- 0x7c, 0x08, 0xf8, 0x27, 0x28, 0x29, 0x95, 0xba, 0x06, 0xcb, 0x3c, 0x6e,
- 0xdb, 0x2d, 0xf7, 0x04, 0x6a, 0x73, 0x95, 0x09, 0xe8, 0xe4, 0x6c, 0x0e,
- 0x97, 0x7f, 0xb4, 0xb9, 0xb1, 0x3a, 0x03, 0x97, 0xfe, 0x4e, 0x23, 0x9b,
- 0xf2, 0xa8, 0xb3, 0x97, 0xfb, 0xdd, 0x6b, 0x4e, 0xbc, 0xc7, 0x2f, 0xe8,
- 0x58, 0xbf, 0xde, 0x39, 0x52, 0x45, 0x23, 0x5a, 0x03, 0x0d, 0xef, 0xd1,
- 0xe9, 0xf1, 0xb3, 0x97, 0xfe, 0xf9, 0x62, 0xf3, 0xbc, 0x93, 0xa7, 0x2b,
- 0x47, 0xd0, 0x02, 0x9b, 0xce, 0x3f, 0x9c, 0xbf, 0xff, 0xfe, 0x40, 0x6b,
- 0xb9, 0x34, 0xcf, 0xa9, 0xbd, 0xd0, 0x7f, 0xbc, 0x4e, 0x21, 0x83, 0x97,
- 0xef, 0x75, 0xc5, 0x53, 0x97, 0xfc, 0x20, 0x9c, 0x3d, 0xc1, 0x83, 0x96,
- 0xc0, 0xa3, 0x8f, 0x21, 0x06, 0xb2, 0x8b, 0xff, 0xbf, 0x5f, 0xe3, 0x9e,
- 0xdb, 0xb8, 0x9c, 0xbc, 0xc7, 0xf8, 0xe5, 0x68, 0xf8, 0x7f, 0x44, 0xa8,
- 0x56, 0xa3, 0x90, 0xd8, 0x48, 0x4d, 0xb9, 0x10, 0xc3, 0xfc, 0x10, 0x9a,
- 0xbf, 0xd9, 0xd9, 0x93, 0xa8, 0xc3, 0x97, 0xfa, 0x59, 0xad, 0x8c, 0x4e,
- 0x72, 0xf3, 0x4c, 0x9c, 0xe5, 0xff, 0x40, 0xc2, 0xf4, 0x90, 0xc3, 0x97,
- 0xb3, 0xae, 0x72, 0xfd, 0x30, 0x40, 0x01, 0x39, 0x41, 0x3c, 0x47, 0x1b,
- 0xbc, 0xd6, 0x8c, 0x39, 0x7f, 0xfe, 0x77, 0xff, 0x71, 0xff, 0xb1, 0x03,
- 0x83, 0x31, 0xce, 0x97, 0xf7, 0xf3, 0x78, 0xb5, 0xe3, 0x67, 0x2f, 0x42,
- 0xf8, 0x9c, 0xac, 0x3c, 0xdf, 0x17, 0xdf, 0xf7, 0xcc, 0xcc, 0x1f, 0x34,
- 0xc3, 0x97, 0x95, 0x90, 0x0e, 0x5f, 0xbb, 0x1a, 0x9d, 0x87, 0x2f, 0xf0,
- 0x1c, 0x7b, 0x8f, 0x31, 0xcb, 0x7d, 0x31, 0xed, 0xb6, 0x53, 0x48, 0x8a,
- 0x47, 0x79, 0xac, 0x4c, 0x81, 0xc8, 0x46, 0x1b, 0xd5, 0x8a, 0xd0, 0xfe,
- 0x33, 0x43, 0x3e, 0x8f, 0xbb, 0xd0, 0xa0, 0x6e, 0x3d, 0x1b, 0xc3, 0x9f,
- 0x9c, 0xb4, 0x1c, 0xaf, 0xcd, 0x67, 0x87, 0x2e, 0x7f, 0x1c, 0xad, 0x1b,
- 0x8e, 0x91, 0x5f, 0x32, 0x35, 0xb3, 0x97, 0xfd, 0xac, 0xee, 0x4f, 0xc9,
- 0x36, 0x72, 0xb0, 0xff, 0x90, 0x84, 0x04, 0x57, 0xf2, 0x08, 0x25, 0x9b,
- 0x39, 0x7f, 0xec, 0xf4, 0x7d, 0xfb, 0xf7, 0xa8, 0x72, 0xcc, 0x39, 0x7f,
- 0x20, 0x82, 0x59, 0xbe, 0x47, 0xa1, 0xc4, 0xfe, 0x95, 0x46, 0x1f, 0x9f,
- 0x2d, 0xcd, 0xa9, 0x74, 0x1b, 0xed, 0x59, 0x27, 0x0c, 0x49, 0x0f, 0x73,
- 0x90, 0xca, 0x19, 0x81, 0x94, 0x0b, 0x93, 0x8a, 0x2a, 0xc3, 0xf9, 0x70,
- 0xce, 0xf8, 0x89, 0x23, 0x1f, 0x9a, 0x31, 0xed, 0x18, 0xb2, 0x3e, 0x6e,
- 0xce, 0x49, 0xbc, 0x6c, 0x3f, 0xc6, 0x26, 0x32, 0x80, 0x77, 0x2e, 0x17,
- 0xd2, 0xea, 0xda, 0x46, 0x96, 0xa4, 0x3c, 0x2f, 0xee, 0x04, 0x08, 0xc4,
- 0xc7, 0x2f, 0x43, 0x89, 0xcb, 0xec, 0xeb, 0xf8, 0xe5, 0xb8, 0x4c, 0x3e,
- 0xbe, 0x98, 0x08, 0xd5, 0xff, 0xff, 0xee, 0xb8, 0xfb, 0x70, 0x92, 0xce,
- 0x01, 0xf4, 0x76, 0x15, 0x04, 0x70, 0x1c, 0xbe, 0xcd, 0xfe, 0x87, 0x2f,
- 0xda, 0x5b, 0xba, 0xcd, 0x16, 0xb2, 0xff, 0x31, 0x18, 0xf3, 0x67, 0x4e,
- 0x5f, 0xd9, 0xc1, 0xb7, 0x15, 0x9c, 0xbd, 0xa8, 0x61, 0xcb, 0xfb, 0xb9,
- 0xb8, 0x9f, 0x80, 0xe5, 0xff, 0x4b, 0x9e, 0x69, 0x6e, 0xeb, 0x34, 0x50,
- 0x6a, 0xc3, 0xf8, 0x73, 0x1b, 0xec, 0x9a, 0x3c, 0x72, 0xff, 0xa2, 0x51,
- 0xa9, 0xe3, 0x53, 0x9c, 0xbe, 0x57, 0xd9, 0xd3, 0x97, 0xf9, 0x22, 0x6f,
- 0xdc, 0x66, 0x39, 0x7f, 0xfd, 0xb4, 0x9d, 0xf6, 0xe2, 0xfe, 0xec, 0x4c,
- 0x72, 0xff, 0xce, 0x3f, 0xe7, 0xa0, 0x53, 0xf3, 0x95, 0xe4, 0x46, 0x34,
- 0x4f, 0xb7, 0x3e, 0x19, 0x5c, 0x1c, 0x1c, 0x49, 0xef, 0x08, 0x90, 0xd2,
- 0x63, 0x3d, 0x17, 0xb2, 0x12, 0x9d, 0x20, 0x12, 0x2d, 0x9d, 0x78, 0x8d,
- 0x48, 0x60, 0x5f, 0xfe, 0xe6, 0xc7, 0x97, 0x3c, 0xd2, 0xdd, 0xd6, 0x68,
- 0xa2, 0xd7, 0xfb, 0x9e, 0x69, 0x6e, 0xeb, 0x34, 0x5d, 0x4a, 0x87, 0x61,
- 0x87, 0x28, 0x5c, 0x61, 0xc2, 0xe1, 0x76, 0x91, 0xef, 0x32, 0x72, 0x4b,
- 0xb6, 0x86, 0x7b, 0xf9, 0xda, 0x6d, 0xc3, 0x27, 0xcb, 0x57, 0xed, 0x2d,
- 0xdd, 0x66, 0x88, 0x85, 0x7b, 0xa8, 0x27, 0x2e, 0xc0, 0x9c, 0xb2, 0xce,
- 0x52, 0xcf, 0x0b, 0xa3, 0x62, 0x2d, 0x7d, 0x9c, 0x53, 0x47, 0x2f, 0x93,
- 0x59, 0xf1, 0xca, 0xc4, 0x74, 0xfc, 0xec, 0xd6, 0x5c, 0xd0, 0x8e, 0xff,
- 0x7b, 0x9c, 0xc3, 0x1f, 0xec, 0xe5, 0x73, 0x3f, 0x9c, 0x42, 0xb3, 0x43,
- 0x97, 0xd1, 0xd8, 0x61, 0xcb, 0xe5, 0xbb, 0xac, 0xd1, 0x1b, 0x29, 0x67,
- 0x9f, 0xa2, 0x1b, 0x73, 0x0a, 0x21, 0x31, 0x8a, 0xff, 0x73, 0xcd, 0x2d,
- 0xdd, 0x66, 0x8a, 0x6d, 0x7e, 0xd2, 0xdd, 0xd6, 0x68, 0xa8, 0x17, 0xb3,
- 0xe6, 0xce, 0x5b, 0x9e, 0x1e, 0x97, 0x4d, 0x2f, 0xf7, 0x3c, 0xd2, 0xdd,
- 0xd6, 0x68, 0xa9, 0x97, 0xed, 0x2d, 0xdd, 0x66, 0x8a, 0xc1, 0x7e, 0x46,
- 0xc2, 0x0d, 0x1c, 0xbd, 0xfa, 0x92, 0x39, 0x76, 0xc4, 0xe5, 0xcc, 0xd9,
- 0xcb, 0xf9, 0x1a, 0x3c, 0x23, 0x43, 0x97, 0xfb, 0x9e, 0x69, 0x6e, 0xeb,
- 0x34, 0x47, 0xeb, 0xc3, 0x01, 0x39, 0x50, 0x88, 0xb9, 0x17, 0xa2, 0x0d,
- 0xa0, 0xe5, 0xd1, 0x39, 0xca, 0x91, 0xa7, 0xc1, 0x0b, 0xfb, 0xe9, 0x3c,
- 0x90, 0x4e, 0x5e, 0x81, 0x98, 0xe5, 0x61, 0xe4, 0xaa, 0x5b, 0x73, 0xf8,
- 0xe5, 0xde, 0xf1, 0xcb, 0x73, 0xc5, 0x48, 0x2b, 0x34, 0xf8, 0xa5, 0x07,
- 0xd8, 0x2c, 0xf0, 0xa2, 0x15, 0x5f, 0x34, 0xb4, 0x22, 0xe0, 0x16, 0xbf,
- 0xfd, 0xcd, 0x8f, 0x2e, 0x79, 0xa5, 0xbb, 0xac, 0xd1, 0x37, 0xaf, 0xfe,
- 0x63, 0xcb, 0x9e, 0x69, 0x6e, 0xeb, 0x34, 0x4f, 0xcb, 0xdc, 0x2e, 0xf2,
- 0x39, 0x79, 0x6a, 0x30, 0xe5, 0xfb, 0x51, 0xd0, 0x41, 0xcb, 0xf7, 0x73,
- 0xd0, 0x13, 0x95, 0xc2, 0x1f, 0x62, 0x0f, 0x39, 0x3d, 0xc2, 0xb3, 0x97,
- 0xdb, 0x99, 0x9b, 0x39, 0x72, 0xd6, 0x72, 0xff, 0x2f, 0xa9, 0xec, 0xc6,
- 0x1c, 0xbb, 0x8a, 0xcf, 0x18, 0x12, 0xa1, 0x15, 0x28, 0x2d, 0xf9, 0x26,
- 0xc5, 0xfc, 0x65, 0x7e, 0x6a, 0xb8, 0x46, 0x99, 0xf1, 0xcb, 0xf9, 0xa9,
- 0x79, 0xfa, 0x8d, 0x67, 0x2f, 0xcd, 0x5a, 0xaa, 0xe3, 0x59, 0xcb, 0xfb,
- 0xc8, 0x2d, 0xe0, 0x9c, 0xbb, 0x8a, 0xcf, 0x18, 0x0a, 0xdd, 0x39, 0x4d,
- 0x4a, 0x60, 0x1c, 0x21, 0xaf, 0x0b, 0x1b, 0x61, 0x97, 0x8b, 0x00, 0x4d,
- 0x7b, 0x4f, 0x87, 0x2f, 0x9c, 0x38, 0xc3, 0x94, 0xd5, 0x9b, 0xc6, 0xa2,
- 0x37, 0x7d, 0xc3, 0x4e, 0xcd, 0x9c, 0xbf, 0xff, 0x0b, 0xfa, 0x05, 0x68,
- 0xc0, 0x81, 0xf5, 0x23, 0x97, 0xe6, 0xfd, 0xe8, 0x61, 0xca, 0x6a, 0xcf,
- 0xf2, 0x75, 0x3b, 0xfe, 0x7e, 0xa7, 0x1e, 0x6d, 0xb6, 0xd9, 0x4b, 0xfd,
- 0xd7, 0xf7, 0x9d, 0xdb, 0x39, 0x5c, 0x32, 0x68, 0x0d, 0x46, 0x14, 0xad,
- 0x40, 0xa3, 0x85, 0x90, 0x2f, 0xff, 0xf3, 0x55, 0xc2, 0x6f, 0x50, 0x9e,
- 0xee, 0x05, 0x37, 0x83, 0xf9, 0xcb, 0xf9, 0xae, 0x34, 0xef, 0x23, 0x97,
- 0xee, 0xa3, 0xff, 0xc2, 0xc7, 0x29, 0xa9, 0x46, 0x47, 0x0a, 0x6a, 0xf1,
- 0x7d, 0xff, 0xcd, 0x5b, 0x56, 0xd4, 0xcc, 0x30, 0x1c, 0xfb, 0xc7, 0x2f,
- 0x87, 0x13, 0xf3, 0x97, 0xdc, 0x2f, 0xfa, 0xb0, 0x72, 0xb8, 0x43, 0xcc,
- 0xe1, 0x88, 0x6f, 0xfd, 0x11, 0x11, 0x11, 0x1f, 0x6c, 0xe5, 0xe9, 0xa3,
- 0xc7, 0x2e, 0x88, 0x83, 0xd8, 0x98, 0xee, 0xf2, 0x7d, 0x87, 0x2f, 0xda,
- 0x49, 0xdd, 0x85, 0x2e, 0x6d, 0xb2, 0x95, 0x87, 0x82, 0xd9, 0x45, 0x80,
- 0x53, 0x99, 0xa2, 0xbd, 0xdc, 0x59, 0xca, 0x84, 0x75, 0x7e, 0x59, 0xb7,
- 0xf5, 0x08, 0xef, 0xc0, 0x69, 0x00, 0xf8, 0xe5, 0xf3, 0x8c, 0x70, 0x1c,
- 0xac, 0x3c, 0xe7, 0x2b, 0xbf, 0xf8, 0x71, 0x91, 0xbd, 0xe4, 0x9a, 0x61,
- 0xcb, 0xff, 0x3f, 0x97, 0xd4, 0x11, 0x8f, 0x8e, 0x52, 0x22, 0x07, 0xa8,
- 0x97, 0xfb, 0x02, 0x9c, 0x77, 0xfa, 0xce, 0x5f, 0xff, 0xfb, 0x38, 0xa7,
- 0xa5, 0x9f, 0xec, 0x73, 0xfd, 0x44, 0xef, 0xa5, 0x9c, 0xba, 0x24, 0xe8,
- 0xa5, 0xd9, 0xb5, 0xfd, 0xed, 0xe6, 0x4f, 0x07, 0x2b, 0xa7, 0xb4, 0x25,
- 0xb7, 0xdb, 0x0f, 0x80, 0x72, 0xff, 0xff, 0xee, 0x31, 0xac, 0x08, 0xbe,
- 0x95, 0x7f, 0x03, 0xc9, 0xed, 0xf5, 0x0e, 0x5f, 0xed, 0x00, 0x41, 0xe0,
- 0x78, 0xe5, 0xee, 0xc0, 0x9c, 0xb4, 0x21, 0xe7, 0xf8, 0xd2, 0xa1, 0x32,
- 0xc5, 0x90, 0xa1, 0x1f, 0x61, 0x85, 0x78, 0x52, 0x0e, 0x5f, 0xa1, 0x46,
- 0x75, 0x0e, 0x56, 0x8f, 0x08, 0x46, 0xaf, 0xcf, 0x3c, 0x3a, 0xce, 0x5f,
- 0xca, 0x72, 0x8d, 0xc3, 0x0e, 0x57, 0x4f, 0x5d, 0xc9, 0xef, 0xe9, 0x6f,
- 0xd8, 0x2a, 0x9c, 0xbf, 0xfa, 0x17, 0x9a, 0xce, 0xa6, 0xba, 0xe7, 0x2f,
- 0x36, 0xed, 0x9c, 0xbf, 0xfa, 0x35, 0x25, 0xf5, 0x26, 0x17, 0x6c, 0xe5,
- 0xff, 0xda, 0x79, 0xc3, 0xd8, 0xdf, 0x81, 0xd3, 0x95, 0xb4, 0x45, 0xf9,
- 0x16, 0xcc, 0xd2, 0x61, 0xdd, 0x42, 0xdc, 0x2a, 0x6f, 0xf2, 0x29, 0x0d,
- 0x87, 0x18, 0x72, 0xb0, 0xfc, 0x3a, 0x79, 0x7f, 0xd1, 0xd8, 0xfa, 0x52,
- 0x89, 0xce, 0x5f, 0x2f, 0xa9, 0xa3, 0x95, 0xa3, 0xdc, 0x73, 0xab, 0xff,
- 0xff, 0xc2, 0xea, 0xa6, 0xa2, 0x5c, 0xba, 0x8c, 0x0c, 0x72, 0x68, 0x0e,
- 0xa6, 0x8e, 0x5f, 0x3c, 0x93, 0xe3, 0x97, 0xfc, 0x9e, 0xcd, 0x68, 0x13,
- 0xf1, 0x39, 0x7f, 0xdb, 0xcf, 0x07, 0x33, 0xfd, 0x9c, 0xae, 0x9f, 0xaf,
- 0x8f, 0x2f, 0xf9, 0x3d, 0x9a, 0xd0, 0x27, 0xe2, 0x72, 0xf6, 0xc0, 0x3c,
- 0x8f, 0x7b, 0xa4, 0x54, 0x15, 0x48, 0xba, 0x7d, 0xe9, 0x08, 0xbe, 0xee,
- 0x1e, 0xb7, 0xcc, 0x40, 0xc1, 0xcb, 0xf9, 0x3b, 0xad, 0x24, 0xe7, 0x2a,
- 0x0f, 0x3f, 0xa4, 0x37, 0x37, 0xe3, 0x97, 0xff, 0x22, 0x76, 0x6c, 0xf4,
- 0x7a, 0x02, 0x72, 0xd0, 0x72, 0xff, 0xfa, 0x3e, 0x93, 0x8f, 0xfc, 0xbf,
- 0x4d, 0x22, 0xa7, 0x2a, 0x11, 0x7f, 0x30, 0xc3, 0x44, 0x3e, 0x01, 0x0b,
- 0xef, 0x6f, 0xa8, 0x72, 0xfa, 0x76, 0x24, 0x8e, 0x5f, 0x47, 0xea, 0x30,
- 0xe5, 0xf0, 0x81, 0xe4, 0x72, 0x96, 0x78, 0xbb, 0x24, 0xbf, 0xdd, 0x86,
- 0x73, 0xff, 0xf8, 0x39, 0x50, 0x8c, 0x1c, 0x68, 0x42, 0x2b, 0xfa, 0x64,
- 0xef, 0xb1, 0x67, 0x2b, 0x13, 0x3e, 0xd4, 0x38, 0xdc, 0xb6, 0xff, 0x05,
- 0x48, 0x6b, 0xe8, 0x36, 0x72, 0xfd, 0xc0, 0x8c, 0xcf, 0x1c, 0xaf, 0x8f,
- 0x89, 0x87, 0x17, 0xb7, 0x0d, 0x9c, 0xb9, 0xfa, 0x72, 0xf2, 0xb1, 0xe3,
- 0x97, 0xff, 0xe0, 0xf6, 0x34, 0x9f, 0xc2, 0x91, 0x30, 0xc3, 0x0e, 0x5f,
- 0xe5, 0x60, 0x7d, 0xb7, 0xe9, 0xca, 0x44, 0x44, 0xba, 0xb5, 0xf8, 0x71,
- 0xc6, 0x73, 0x95, 0x09, 0xa1, 0xe1, 0x1a, 0x0e, 0xb8, 0xb0, 0xc2, 0x9b,
- 0x64, 0x37, 0xfb, 0xb1, 0x3e, 0xa3, 0x02, 0x72, 0xff, 0xf8, 0x73, 0x8a,
- 0xdf, 0x53, 0xbf, 0x9f, 0xef, 0xce, 0x54, 0x22, 0x19, 0xcc, 0xef, 0xf0,
- 0xbc, 0xff, 0x4a, 0x38, 0x0e, 0x5f, 0xed, 0xf5, 0xd4, 0xec, 0x48, 0xe5,
- 0x4e, 0x7d, 0x7f, 0x1b, 0xde, 0xcc, 0x98, 0xe5, 0xff, 0xfa, 0x6e, 0xc3,
- 0x13, 0x49, 0xc1, 0x0a, 0x4f, 0x8d, 0x9c, 0xbf, 0xf2, 0x6a, 0x36, 0xa0,
- 0x8c, 0x68, 0xe5, 0xff, 0x44, 0x85, 0xfd, 0x24, 0xe2, 0x72, 0xf2, 0x91,
- 0xf9, 0xca, 0xe9, 0xeb, 0xec, 0xe6, 0xcd, 0x67, 0x2f, 0x7a, 0x58, 0x72,
- 0xed, 0xe1, 0xcb, 0xff, 0xb7, 0x1a, 0x5f, 0x87, 0x27, 0x71, 0x39, 0x50,
- 0x9c, 0xd4, 0xeb, 0x79, 0x09, 0x44, 0x22, 0x71, 0x4f, 0xc7, 0x3c, 0x2d,
- 0x77, 0x98, 0x72, 0xfd, 0x30, 0x3d, 0x1d, 0x39, 0x50, 0x78, 0x00, 0x17,
- 0xbf, 0xf4, 0x79, 0xf7, 0x9d, 0xea, 0x30, 0xe5, 0xf8, 0x62, 0x78, 0x9c,
- 0xe5, 0x04, 0xf9, 0x66, 0x3d, 0xbf, 0x83, 0x0f, 0xaf, 0xc0, 0x72, 0xec,
- 0xe9, 0xca, 0x9c, 0xf1, 0x38, 0x97, 0x5e, 0xf2, 0x4c, 0x72, 0xa1, 0x15,
- 0x38, 0xcf, 0xb2, 0x5b, 0xfe, 0xd2, 0x6f, 0xae, 0xc8, 0x6b, 0x39, 0x7e,
- 0x86, 0xb4, 0x6d, 0x67, 0x2a, 0x1b, 0x30, 0xe9, 0xe1, 0x19, 0x28, 0x50,
- 0x86, 0x52, 0x6e, 0x42, 0x0d, 0x6f, 0x1f, 0x10, 0xa4, 0xbf, 0x16, 0xb8,
- 0x4f, 0xcd, 0x0e, 0x0d, 0x47, 0x00, 0xc8, 0xf6, 0x7b, 0x0d, 0xe7, 0x84,
- 0x67, 0xe4, 0x83, 0x1d, 0xb6, 0xe1, 0x51, 0xe8, 0xcb, 0xf8, 0x97, 0x28,
- 0x77, 0x72, 0xbe, 0x39, 0x7f, 0xff, 0xcd, 0x47, 0x86, 0x8c, 0x6a, 0x1a,
- 0xe1, 0xb8, 0x57, 0x16, 0xbe, 0x16, 0x07, 0x2e, 0x5d, 0x68, 0x72, 0xe4,
- 0x83, 0x97, 0xa6, 0x51, 0x87, 0x2f, 0xfb, 0x3d, 0xbc, 0xf7, 0x73, 0xf3,
- 0x94, 0xa9, 0xf6, 0xb8, 0xa8, 0x8f, 0xdc, 0xe2, 0x72, 0xb4, 0x78, 0x6c,
- 0x2e, 0xbe, 0x8f, 0x63, 0x0e, 0x5f, 0xbd, 0x02, 0x9f, 0x9c, 0xbf, 0x68,
- 0x1c, 0x7f, 0x6c, 0xe5, 0xfd, 0x8d, 0xbf, 0xec, 0xc3, 0x95, 0xc9, 0x14,
- 0x78, 0x43, 0xd2, 0x71, 0x2d, 0xbf, 0xf4, 0x31, 0x3e, 0xd8, 0x26, 0x02,
- 0xa7, 0x2f, 0xe4, 0x1f, 0x77, 0x24, 0x72, 0xff, 0x0c, 0x36, 0xd3, 0x35,
- 0x07, 0x2c, 0xdf, 0x24, 0x51, 0x49, 0x08, 0x25, 0x97, 0xed, 0x4f, 0x1e,
- 0xd9, 0xcb, 0xe7, 0xd3, 0xc8, 0xe5, 0xb5, 0x87, 0x94, 0x25, 0x37, 0x9b,
- 0x6d, 0xb3, 0x97, 0xd3, 0x8a, 0x41, 0x4e, 0x66, 0x82, 0xff, 0x9a, 0xfa,
- 0xe3, 0x20, 0xc4, 0xe7, 0x2f, 0x9f, 0xd0, 0x13, 0x97, 0x7d, 0x23, 0x97,
- 0xf9, 0x58, 0xf6, 0xfa, 0xe0, 0x39, 0x7e, 0x49, 0xf3, 0xef, 0x1c, 0xb9,
- 0x16, 0x72, 0xa1, 0x11, 0x6a, 0x8c, 0x30, 0xd3, 0xc5, 0x37, 0xe5, 0x5f,
- 0x7c, 0x64, 0x72, 0xbe, 0x3e, 0x8f, 0x1e, 0xde, 0xc0, 0x34, 0x39, 0x5c,
- 0x22, 0xec, 0x87, 0x0a, 0x18, 0x88, 0xd1, 0xc3, 0x0c, 0x5c, 0x86, 0xfa,
- 0x42, 0x0f, 0xa8, 0xce, 0x66, 0x27, 0x80, 0x8c, 0x51, 0xa1, 0x1d, 0xff,
- 0xdc, 0x5b, 0xcd, 0x8a, 0x46, 0xb2, 0x73, 0x97, 0xff, 0xff, 0xfe, 0x6b,
- 0xe5, 0xdc, 0xfa, 0x5d, 0x67, 0x25, 0xf4, 0x1e, 0xf6, 0x0f, 0x73, 0xd0,
- 0x1e, 0x5c, 0xba, 0xd0, 0xe5, 0xff, 0x07, 0x01, 0xc3, 0xa7, 0x5d, 0x87,
- 0x2f, 0xd0, 0xc1, 0xc9, 0x8e, 0x61, 0xbd, 0xbd, 0xc7, 0x02, 0x72, 0xfe,
- 0xea, 0x40, 0x82, 0x0e, 0x5f, 0xe8, 0x6b, 0x57, 0x36, 0xed, 0x67, 0x29,
- 0x53, 0xe4, 0xe9, 0x5d, 0x75, 0x14, 0xaf, 0x08, 0x2b, 0xee, 0xc2, 0x9d,
- 0x39, 0x41, 0x4c, 0x97, 0x70, 0xdb, 0xf1, 0x3d, 0xfd, 0x12, 0xec, 0x71,
- 0x43, 0x97, 0xe6, 0x00, 0x61, 0x87, 0x2c, 0x13, 0x97, 0x3e, 0xce, 0x5b,
- 0x4c, 0x34, 0xe0, 0x11, 0xa8, 0x3f, 0x57, 0x4e, 0xba, 0x5e, 0x39, 0x7d,
- 0x34, 0x79, 0xce, 0x5f, 0x03, 0xfc, 0x15, 0x9b, 0x90, 0x0b, 0xda, 0x47,
- 0x2a, 0x73, 0xc9, 0xe9, 0xc5, 0xff, 0xd1, 0xd5, 0x03, 0xe4, 0xc9, 0xa1,
- 0x87, 0x2f, 0xfd, 0xe4, 0x6d, 0x7d, 0x4e, 0x28, 0x13, 0x97, 0xfb, 0x52,
- 0xee, 0x71, 0x86, 0x1c, 0xaf, 0x8f, 0xd9, 0x10, 0x6f, 0xcf, 0x2d, 0xa7,
- 0x13, 0x97, 0xfd, 0x9a, 0xce, 0x59, 0xa8, 0x09, 0xcb, 0xfb, 0x25, 0xf4,
- 0xb3, 0xc7, 0x2d, 0xe9, 0x1f, 0x3f, 0x4e, 0x6f, 0xa3, 0xc0, 0x61, 0xca,
- 0x34, 0x41, 0xcb, 0xf9, 0xe7, 0xfd, 0xc4, 0x24, 0xac, 0x1a, 0xb6, 0xd6,
- 0x7a, 0x8d, 0x06, 0x29, 0x88, 0xa0, 0xf3, 0xb5, 0xff, 0xf9, 0x9b, 0x79,
- 0x75, 0x33, 0xdb, 0xd6, 0x07, 0x0e, 0x5f, 0xf4, 0x78, 0x73, 0x88, 0xe6,
- 0xce, 0x54, 0x22, 0xbf, 0x08, 0xf6, 0xa9, 0x7f, 0x3f, 0x61, 0xac, 0x12,
- 0x39, 0x52, 0x5c, 0xaa, 0x5c, 0x28, 0xf5, 0x0a, 0x26, 0x11, 0xf6, 0x17,
- 0x7f, 0x91, 0x0c, 0x24, 0x3d, 0x1b, 0xbf, 0x12, 0xeb, 0xfa, 0x43, 0x9f,
- 0x7b, 0x0e, 0x5f, 0xff, 0x94, 0xff, 0xf8, 0xfb, 0x27, 0x0b, 0xba, 0xdc,
- 0x27, 0x2a, 0x11, 0x0d, 0xa2, 0xdb, 0xf8, 0x7d, 0x2c, 0xd6, 0x1c, 0xb9,
- 0xa3, 0x9c, 0xa7, 0x3c, 0x45, 0x0b, 0x2f, 0xf7, 0x71, 0x6f, 0xd8, 0xe9,
- 0xcb, 0xff, 0x9d, 0x3d, 0x02, 0xbc, 0xf7, 0x50, 0xe5, 0xfc, 0x29, 0xfe,
- 0xfa, 0x87, 0x2e, 0xd0, 0x4e, 0x5c, 0xdb, 0x67, 0x2a, 0x46, 0xc1, 0xb1,
- 0x7b, 0xd0, 0x9c, 0x4a, 0x73, 0x34, 0x57, 0xfc, 0x82, 0x9f, 0xef, 0x3a,
- 0xe7, 0x2b, 0x13, 0x58, 0xe9, 0x93, 0xa0, 0xed, 0xff, 0xc5, 0xf7, 0xf4,
- 0x0f, 0xbb, 0x92, 0x39, 0x77, 0xfb, 0x39, 0x7f, 0x27, 0x51, 0x55, 0x60,
- 0xe5, 0x94, 0x09, 0xe3, 0x78, 0x62, 0xb4, 0x89, 0xbd, 0xb9, 0x52, 0x26,
- 0x0e, 0xa4, 0x39, 0x2f, 0x36, 0xdb, 0x65, 0x28, 0xa7, 0x33, 0x41, 0x7c,
- 0x8d, 0xa4, 0xc5, 0x29, 0x67, 0x80, 0x83, 0xb7, 0xec, 0xd4, 0x71, 0xc3,
- 0x95, 0x0c, 0xc0, 0xe9, 0xd1, 0xb2, 0x50, 0x62, 0x4e, 0x70, 0x6a, 0x32,
- 0x36, 0x33, 0x76, 0x54, 0x08, 0xc2, 0x27, 0x64, 0x37, 0xda, 0x90, 0x30,
- 0xe5, 0xfe, 0x1f, 0xbc, 0xa7, 0x5f, 0xf3, 0x97, 0x85, 0x36, 0x72, 0xf8,
- 0x2e, 0x3f, 0x9c, 0xbf, 0xfa, 0x07, 0xf1, 0x8f, 0xa6, 0x81, 0xfc, 0xe5,
- 0x62, 0x2e, 0x10, 0xdb, 0xf1, 0xbd, 0x91, 0x5f, 0x4b, 0xf9, 0x09, 0xcb,
- 0xf4, 0xcd, 0x3f, 0x69, 0x87, 0x2c, 0x87, 0x2f, 0xf9, 0xd5, 0x5f, 0x50,
- 0x2f, 0x23, 0x97, 0xd3, 0xce, 0xff, 0x1c, 0xbb, 0xfd, 0xa1, 0xf7, 0x08,
- 0x82, 0x87, 0x37, 0xd9, 0xae, 0xa1, 0xcb, 0xff, 0xcf, 0x21, 0xce, 0x2f,
- 0x34, 0x67, 0xb6, 0x72, 0xa0, 0xfa, 0xdc, 0x86, 0xff, 0xf3, 0x7f, 0xf7,
- 0x32, 0x74, 0xce, 0x31, 0xf1, 0xcb, 0xff, 0xdf, 0xc3, 0x35, 0xa8, 0x9f,
- 0xce, 0xea, 0x9c, 0xbf, 0xd2, 0xce, 0xe3, 0x21, 0x67, 0x2f, 0x63, 0x1a,
- 0xce, 0x5f, 0xf9, 0xf8, 0xe2, 0x83, 0x1d, 0x49, 0xce, 0x5f, 0xec, 0xd8,
- 0xe7, 0xba, 0x87, 0x28, 0x28, 0x90, 0xd0, 0xf8, 0xa0, 0x56, 0x2a, 0x51,
- 0x9a, 0x14, 0xdd, 0x20, 0xfd, 0x3b, 0xc9, 0x9c, 0x61, 0x85, 0x7d, 0x2f,
- 0xf3, 0xf3, 0x97, 0xf7, 0xb2, 0x61, 0x86, 0x1e, 0x20, 0x25, 0xf0, 0x87,
- 0xb0, 0x68, 0x80, 0x9c, 0xcd, 0xd5, 0x7c, 0x89, 0xe7, 0x5e, 0xbf, 0xf9,
- 0x3e, 0xd8, 0x70, 0x60, 0x41, 0x07, 0x2f, 0xda, 0x40, 0x70, 0xf0, 0x72,
- 0xff, 0x6b, 0x3e, 0xdf, 0xef, 0xe3, 0x97, 0x01, 0x70, 0x7c, 0x2a, 0x96,
- 0x5f, 0xa2, 0x4f, 0xf3, 0x67, 0x2f, 0xfb, 0x96, 0xb5, 0x9d, 0xfa, 0x5b,
- 0x39, 0x7f, 0xff, 0xb3, 0x60, 0x7f, 0xb3, 0x05, 0x5d, 0xef, 0x07, 0xdb,
- 0x39, 0x4b, 0x44, 0xef, 0xc7, 0xb7, 0xe7, 0x6c, 0x2a, 0xf1, 0x39, 0x58,
- 0x9f, 0x3a, 0x42, 0x8f, 0x45, 0xcf, 0x0c, 0x61, 0x24, 0xb4, 0xe7, 0x2f,
- 0xdc, 0xb2, 0x64, 0x61, 0xcb, 0xff, 0xc0, 0x8e, 0x5c, 0x1e, 0x4d, 0xf7,
- 0xe7, 0x6c, 0xe5, 0x4e, 0x7f, 0x7b, 0x2a, 0xbf, 0xf6, 0x07, 0xaf, 0xce,
- 0x3b, 0x1f, 0x1c, 0xae, 0x11, 0x1e, 0x1a, 0x84, 0x6b, 0x08, 0xef, 0xf8,
- 0x55, 0xd0, 0xa2, 0xc0, 0x27, 0x2f, 0xde, 0x8c, 0x18, 0x39, 0x48, 0x7b,
- 0xa2, 0x71, 0x79, 0x41, 0xf1, 0xcb, 0xc8, 0xc7, 0x39, 0x53, 0x9b, 0x85,
- 0x47, 0x6f, 0xff, 0xcf, 0xf7, 0xdb, 0x81, 0xf2, 0x93, 0x75, 0x3d, 0xb3,
- 0x95, 0x09, 0xb5, 0xe4, 0x25, 0xd1, 0x60, 0x04, 0x77, 0xcc, 0x8c, 0x61,
- 0xcb, 0xff, 0x63, 0x21, 0x69, 0xed, 0x01, 0x87, 0x2f, 0x27, 0xdb, 0x39,
- 0x52, 0x3d, 0xbf, 0xcf, 0xaf, 0xb4, 0xf2, 0x98, 0xe5, 0xfb, 0x7b, 0x8f,
- 0xda, 0x93, 0x94, 0xa9, 0xe8, 0xb6, 0x47, 0x50, 0x89, 0x87, 0x74, 0xbf,
- 0xda, 0x9b, 0x68, 0x3e, 0x43, 0x97, 0xfb, 0xa9, 0xf7, 0xfa, 0x70, 0x9c,
- 0xbe, 0xfb, 0xfd, 0x41, 0x4b, 0x9b, 0x6c, 0xa5, 0x41, 0xbd, 0x6c, 0x92,
- 0xe1, 0x42, 0x9c, 0xcd, 0x0d, 0xff, 0xff, 0xc3, 0xcf, 0x33, 0x82, 0x26,
- 0x46, 0x44, 0xdc, 0x87, 0xe9, 0x74, 0x1f, 0x9c, 0xa3, 0x97, 0x9f, 0x52,
- 0xe4, 0x9a, 0x04, 0xa1, 0x27, 0xf1, 0x3f, 0xef, 0x77, 0xf3, 0x8c, 0x96,
- 0x09, 0xce, 0x53, 0x56, 0xcd, 0x4e, 0x88, 0x6d, 0x4e, 0x79, 0x22, 0x3c,
- 0x95, 0xda, 0x91, 0x82, 0x6a, 0x50, 0x57, 0x65, 0x56, 0x3a, 0x00, 0xc6,
- 0x29, 0xe2, 0x10, 0x46, 0xe6, 0xda, 0xc5, 0xef, 0x23, 0x67, 0x2f, 0x4e,
- 0xec, 0x39, 0x72, 0x04, 0xe5, 0xef, 0x23, 0x67, 0x8c, 0x21, 0x78, 0x0e,
- 0xa1, 0xa2, 0x07, 0x7c, 0x6a, 0xab, 0xa7, 0xf7, 0xe4, 0x0a, 0x74, 0x5d,
- 0x02, 0x13, 0x17, 0x87, 0x5c, 0x39, 0xcb, 0xfd, 0x8b, 0x89, 0xc6, 0x16,
- 0x72, 0xdf, 0x9c, 0xb3, 0x5f, 0x23, 0xc4, 0x43, 0x2b, 0xa0, 0x07, 0x2f,
- 0xc0, 0x1f, 0xd4, 0x91, 0xcb, 0xff, 0xe1, 0xcd, 0xf2, 0x53, 0xb1, 0xfb,
- 0x1e, 0x5c, 0xb0, 0xf0, 0x36, 0x2d, 0x40, 0x46, 0xbf, 0x16, 0xcb, 0xff,
- 0x74, 0x13, 0xc7, 0x28, 0xf4, 0x04, 0xe5, 0xe7, 0xd4, 0xe7, 0x2e, 0x6d,
- 0xb3, 0x97, 0xfb, 0x49, 0x9c, 0x54, 0x97, 0x35, 0x9b, 0x66, 0xc7, 0x6f,
- 0xfc, 0x8a, 0xf2, 0xd8, 0x3f, 0x64, 0x48, 0xe5, 0xfe, 0xde, 0x79, 0xd9,
- 0x82, 0x72, 0x82, 0x99, 0xd6, 0x9d, 0xfa, 0x9f, 0xe4, 0x3b, 0xff, 0x6f,
- 0x07, 0x3b, 0x8b, 0xc1, 0x39, 0x7f, 0xd2, 0xdf, 0xbb, 0x8c, 0xc9, 0x1c,
- 0xbf, 0xf6, 0x2b, 0xd7, 0x92, 0x8f, 0xf4, 0x1c, 0xa9, 0x22, 0xd1, 0x0e,
- 0xc4, 0xe6, 0xa1, 0x32, 0x0c, 0x87, 0x95, 0xff, 0xcc, 0x63, 0xcb, 0x34,
- 0xb7, 0x75, 0x9a, 0x21, 0x85, 0xff, 0xff, 0xe7, 0xde, 0x0e, 0x2f, 0xb1,
- 0xf4, 0x9a, 0x67, 0x56, 0x98, 0x2e, 0xa9, 0xca, 0xc4, 0x63, 0x81, 0x42,
- 0xa1, 0x73, 0x2d, 0x23, 0x3c, 0xec, 0xa7, 0xf1, 0x87, 0x75, 0xf8, 0x63,
- 0xff, 0xbf, 0x39, 0x7f, 0x75, 0xe7, 0x18, 0x91, 0x4b, 0xff, 0x7b, 0xae,
- 0x9e, 0x8d, 0x47, 0xe7, 0x2f, 0xdd, 0x71, 0x52, 0x73, 0x95, 0x24, 0x5f,
- 0x30, 0xa8, 0x4b, 0x5b, 0x3e, 0xbf, 0xf2, 0x2e, 0x36, 0xfa, 0xd2, 0x36,
- 0x72, 0xff, 0xfb, 0x7f, 0xa6, 0x95, 0x5f, 0x53, 0xa2, 0x09, 0xce, 0x5d,
- 0xb0, 0x1c, 0xbf, 0xa5, 0xd7, 0x71, 0x83, 0x96, 0x85, 0x9e, 0x17, 0xc2,
- 0xf7, 0xff, 0x67, 0xa3, 0xa9, 0x8a, 0xab, 0x12, 0x39, 0x7e, 0xd2, 0xdd,
- 0xd6, 0x68, 0x82, 0x97, 0xbb, 0x0c, 0x39, 0x7f, 0xe8, 0x9d, 0xfd, 0xac,
- 0x93, 0x4c, 0x39, 0x41, 0x46, 0xa6, 0x22, 0x21, 0xa0, 0x8e, 0x5f, 0xbb,
- 0x0c, 0x07, 0xc7, 0x2f, 0xbd, 0xb8, 0xfc, 0xa5, 0xe7, 0xd4, 0xe5, 0x2f,
- 0x80, 0x2e, 0xa9, 0x4b, 0xfc, 0x93, 0xe7, 0xb7, 0x1f, 0x94, 0xa2, 0x97,
- 0xf6, 0x2e, 0x3b, 0x0c, 0x29, 0x73, 0x6d, 0x94, 0xbf, 0x86, 0x06, 0x74,
- 0xd1, 0x4a, 0xc4, 0xc4, 0x96, 0x46, 0xc1, 0xde, 0x91, 0x7e, 0x68, 0x21,
- 0x6d, 0x96, 0x28, 0x33, 0x72, 0x68, 0xa7, 0x33, 0xf3, 0xa9, 0x2a, 0x11,
- 0x98, 0xeb, 0xb1, 0xd7, 0x5f, 0xff, 0xa1, 0xbd, 0x8e, 0x7d, 0xe7, 0x19,
- 0xf3, 0xef, 0x1c, 0xa8, 0x5c, 0xad, 0xc3, 0xd4, 0x3e, 0xec, 0x25, 0x5e,
- 0x58, 0x68, 0x9c, 0xde, 0x63, 0x84, 0xe5, 0xff, 0xff, 0x0e, 0x7b, 0xd1,
- 0xf4, 0xb9, 0x76, 0x18, 0x0f, 0xb7, 0xd8, 0x39, 0x7f, 0x60, 0xed, 0x07,
- 0x0e, 0x5e, 0xe8, 0x18, 0x72, 0x95, 0x46, 0x6b, 0x58, 0xe7, 0x5a, 0xb8,
- 0x0a, 0xaf, 0xf3, 0x8e, 0x6f, 0x51, 0xb3, 0x97, 0xf0, 0x70, 0x5f, 0xdb,
- 0x39, 0x52, 0x3d, 0xdd, 0x98, 0xdf, 0xda, 0xe4, 0xf3, 0x67, 0x4e, 0x54,
- 0x1e, 0x92, 0x11, 0x5f, 0xb5, 0xf4, 0xb3, 0xc7, 0x2f, 0xff, 0x9d, 0x3f,
- 0xde, 0x2a, 0xec, 0xd4, 0x60, 0x9c, 0xbf, 0x79, 0x33, 0xef, 0x1c, 0xbf,
- 0xff, 0xee, 0xa6, 0xb0, 0x2e, 0xcc, 0x1f, 0x0c, 0x37, 0x9e, 0xd9, 0xcb,
- 0x41, 0xcb, 0xe8, 0xe2, 0x18, 0x59, 0xfa, 0x7e, 0xc9, 0x7f, 0xe7, 0x97,
- 0x5f, 0xdb, 0xc1, 0x91, 0xca, 0xe9, 0xfc, 0x78, 0xee, 0xb4, 0x9d, 0x6f,
- 0x4a, 0x76, 0x9d, 0xe8, 0xc5, 0x2f, 0x2f, 0x18, 0x72, 0xfe, 0x0b, 0xfb,
- 0x60, 0x91, 0xcb, 0xa4, 0xd2, 0x0f, 0x29, 0x41, 0xcb, 0xf9, 0xf5, 0x1e,
- 0x4e, 0x27, 0x2b, 0xe3, 0xde, 0x13, 0x0b, 0xff, 0xff, 0x6b, 0x51, 0xf4,
- 0xbe, 0xda, 0x69, 0x7d, 0xc5, 0x34, 0x90, 0x13, 0x97, 0xfc, 0xfa, 0xcf,
- 0xa5, 0x1f, 0xc1, 0xca, 0x84, 0x65, 0x61, 0x10, 0x1b, 0xef, 0xff, 0xcb,
- 0x55, 0xf7, 0x9a, 0x92, 0x75, 0xc7, 0xe9, 0x1c, 0xbf, 0xf2, 0xe3, 0xdb,
- 0xcf, 0x27, 0xcd, 0x9c, 0xb3, 0xe2, 0x25, 0x95, 0x56, 0xa8, 0x55, 0x45,
- 0xd8, 0xed, 0x86, 0x18, 0x97, 0xed, 0x88, 0x38, 0xc8, 0xe5, 0xe9, 0xd4,
- 0x59, 0xca, 0x83, 0xc9, 0x72, 0xab, 0x9f, 0xf3, 0x95, 0x23, 0x6f, 0xe2,
- 0x0b, 0xff, 0xf3, 0xbc, 0x9f, 0xbc, 0xb2, 0x70, 0x78, 0x0e, 0xa1, 0xa2,
- 0xfb, 0x5e, 0xfe, 0x02, 0x72, 0xfe, 0x75, 0xc0, 0xc7, 0xe7, 0x2f, 0xfd,
- 0xb4, 0x1f, 0xa5, 0xa0, 0x46, 0xce, 0x54, 0xc8, 0xed, 0xd3, 0x2f, 0x47,
- 0x7c, 0x59, 0x7e, 0xee, 0x4d, 0x0d, 0x67, 0x2f, 0xc1, 0xd6, 0xb1, 0xb3,
- 0x96, 0x89, 0xcf, 0x50, 0x4a, 0xec, 0xb3, 0x97, 0xff, 0xfb, 0xf4, 0xd2,
- 0xbd, 0x86, 0x4d, 0x24, 0x1e, 0xc6, 0xa0, 0xe5, 0xbd, 0x87, 0xe7, 0xb1,
- 0x1b, 0xef, 0x0e, 0x48, 0xe5, 0x41, 0xe4, 0x21, 0x3d, 0xff, 0x85, 0x25,
- 0xee, 0xe6, 0x93, 0x67, 0x2f, 0xd2, 0x1c, 0xc9, 0xce, 0x5d, 0xa9, 0xce,
- 0x54, 0x1b, 0xfc, 0x27, 0xbf, 0xce, 0x18, 0xfe, 0x1b, 0xd9, 0xca, 0xe9,
- 0xe9, 0xb8, 0xfd, 0xfc, 0xd1, 0xa8, 0x72, 0xe5, 0xd6, 0x87, 0x88, 0x05,
- 0x7f, 0xbd, 0xfa, 0x83, 0x2e, 0xe1, 0xe2, 0x01, 0x5e, 0x7d, 0x48, 0xf1,
- 0x00, 0xab, 0x0f, 0xac, 0x08, 0x57, 0x3c, 0x8f, 0x10, 0x0a, 0xf9, 0xc7,
- 0xe9, 0x1e, 0x20, 0x15, 0xfe, 0x45, 0xf7, 0x3f, 0xfe, 0x0f, 0x10, 0x0a,
- 0xf2, 0x08, 0x4f, 0x10, 0x0a, 0x82, 0x8b, 0xb6, 0x11, 0xf4, 0xbf, 0x8a,
- 0x0d, 0x95, 0x3c, 0x40, 0x2b, 0xda, 0x8f, 0x1e, 0x20, 0x15, 0x1e, 0x20,
- 0x15, 0xe6, 0x89, 0xf9, 0xe2, 0x01, 0x5d, 0x0c, 0x3c, 0x40, 0x2a, 0x09,
- 0xf3, 0xe0, 0xc2, 0x16, 0x5f, 0x23, 0x03, 0x07, 0x88, 0x05, 0x7b, 0xce,
- 0xb3, 0xc4, 0x02, 0xbf, 0xf0, 0xbc, 0xb9, 0xf5, 0x16, 0xfa, 0x3c, 0x40,
- 0x2b, 0xff, 0x9f, 0xc0, 0x9d, 0x07, 0xdd, 0x79, 0x1e, 0x20, 0x15, 0xce,
- 0x13, 0xc4, 0x02, 0xbf, 0xc2, 0xed, 0xef, 0x71, 0xf9, 0xe2, 0x01, 0x5f,
- 0x91, 0x57, 0x1f, 0xcf, 0x10, 0x0a, 0xe4, 0xd9, 0xe2, 0x01, 0x56, 0x8f,
- 0x63, 0xc6, 0xb7, 0xff, 0xba, 0x9e, 0xf6, 0x6f, 0x96, 0x92, 0x18, 0x78,
- 0x80, 0x57, 0xef, 0x0c, 0x7d, 0x23, 0x44, 0x02, 0xbb, 0xf8, 0x3c, 0x40,
- 0x2e, 0x66, 0xd6, 0xfc, 0x90, 0xc7, 0x09, 0xe2, 0x01, 0x5f, 0x01, 0xc5,
- 0x67, 0x88, 0x05, 0x7a, 0x34, 0xb3, 0xc4, 0x02, 0xbf, 0xf6, 0x7d, 0xb0,
- 0xc6, 0x0f, 0xfb, 0x3c, 0x40, 0x2b, 0xf0, 0x1e, 0x52, 0x83, 0xc4, 0x02,
- 0xbf, 0x3a, 0xfb, 0x1f, 0x1e, 0x20, 0x15, 0x62, 0x2d, 0x7a, 0x98, 0x03,
- 0x4b, 0xb5, 0xf9, 0xe2, 0x01, 0x54, 0x95, 0x9a, 0x04, 0x8f, 0x21, 0x32,
- 0xb2, 0x24, 0x84, 0x6f, 0x4d, 0xbf, 0x33, 0xd9, 0x77, 0xa1, 0xbc, 0x02,
- 0xfb, 0xf6, 0x7b, 0x6f, 0xf1, 0xe2, 0x01, 0x5f, 0xe0, 0xc2, 0xe6, 0xd4,
- 0x78, 0xf1, 0x00, 0x82, 0x6d, 0x6f, 0x6a, 0x1b, 0x3c, 0x40, 0x2a, 0x59,
- 0xfd, 0xe9, 0x46, 0xff, 0x01, 0xe5, 0x28, 0x51, 0x87, 0x88, 0x05, 0x7c,
- 0x83, 0x2d, 0x9e, 0x20, 0x15, 0xfc, 0xf3, 0x4b, 0x3e, 0x91, 0xe2, 0x01,
- 0x56, 0x23, 0x37, 0xa4, 0x5f, 0xa0, 0x80, 0xba, 0xff, 0xbb, 0x1b, 0xe7,
- 0xb0, 0x6b, 0xf3, 0xc4, 0x02, 0xb2, 0x1e, 0x20, 0x15, 0xcf, 0x38, 0x4f,
- 0x9f, 0xa9, 0x57, 0x6b, 0xf3, 0xc4, 0x02, 0xbf, 0x3f, 0xb6, 0x9f, 0x1e,
- 0x20, 0x15, 0xfc, 0x82, 0x09, 0x66, 0xcf, 0x10, 0x0a, 0xa1, 0x12, 0x62,
- 0x4b, 0xe3, 0x5a, 0x86, 0x53, 0xf8, 0x61, 0x6b, 0x90, 0xdc, 0x43, 0xf9,
- 0x87, 0xf5, 0x09, 0x0e, 0x96, 0xb9, 0x77, 0xe5, 0x22, 0x99, 0xb9, 0x70,
- 0xbe, 0x94, 0x30, 0xd2, 0x14, 0x8a, 0x43, 0x06, 0xf7, 0x91, 0xb3, 0xc6,
- 0x12, 0xbc, 0xee, 0xb3, 0x44, 0x02, 0xe6, 0x98, 0xa7, 0xd0, 0xea, 0xbe,
- 0x57, 0x85, 0xc2, 0xc3, 0x97, 0x71, 0x9c, 0xe5, 0xfd, 0x3c, 0x6b, 0xae,
- 0xd6, 0x72, 0xfd, 0xc4, 0x60, 0x3d, 0x39, 0x50, 0x7e, 0x98, 0x34, 0x86,
- 0x37, 0xff, 0x48, 0x71, 0x7d, 0x4f, 0xff, 0x04, 0xc7, 0x2f, 0xde, 0xc0,
- 0xbf, 0x4e, 0x5d, 0xfc, 0x14, 0xb2, 0xa5, 0x2f, 0x76, 0x27, 0x39, 0x73,
- 0x6d, 0x94, 0xa4, 0x3d, 0xf6, 0xb1, 0x79, 0x84, 0x9b, 0x1d, 0xb6, 0xca,
- 0x73, 0x3c, 0x0b, 0x33, 0x11, 0xd4, 0x90, 0xc6, 0xbf, 0xbd, 0xbc, 0x6f,
- 0xa8, 0x72, 0xde, 0x39, 0x64, 0xf1, 0xbf, 0x01, 0x75, 0xff, 0xef, 0x6f,
- 0x15, 0x4d, 0x29, 0xff, 0xf1, 0xf1, 0xca, 0x9d, 0x9f, 0x9f, 0x22, 0x00,
- 0xc3, 0x3d, 0x74, 0xbb, 0x44, 0x50, 0xd4, 0x27, 0xdc, 0xb3, 0xf8, 0xcc,
- 0x7c, 0xd6, 0xa1, 0x35, 0xff, 0x64, 0x90, 0x2e, 0xbd, 0xc8, 0xe5, 0xff,
- 0x31, 0x05, 0x69, 0xa4, 0xfc, 0xe5, 0x2c, 0xfc, 0x3a, 0x71, 0x79, 0x7d,
- 0x13, 0x97, 0xff, 0x79, 0xa6, 0x4d, 0x27, 0xd4, 0xe1, 0x83, 0x94, 0xc3,
- 0xe4, 0x11, 0xcb, 0x87, 0xf3, 0x97, 0x46, 0xce, 0x5e, 0xf2, 0x9c, 0x50,
- 0xd6, 0xf1, 0x17, 0xbf, 0xd9, 0xf7, 0xbc, 0xf2, 0xd9, 0xcb, 0xd2, 0xe1,
- 0xe4, 0x72, 0xef, 0xa4, 0x78, 0xc0, 0x15, 0xf1, 0xe3, 0x89, 0x15, 0xff,
- 0xfa, 0x33, 0xbb, 0x17, 0xf0, 0x3c, 0x1e, 0xa2, 0xa7, 0x2a, 0x13, 0xfd,
- 0xc8, 0x43, 0x22, 0x76, 0x8d, 0xdd, 0xec, 0x48, 0xaf, 0xff, 0xc2, 0x20,
- 0xfb, 0x3e, 0xf0, 0x74, 0xff, 0x64, 0xe7, 0x2f, 0xd9, 0xed, 0x46, 0xce,
- 0x52, 0x1f, 0xf8, 0xac, 0x5f, 0xa6, 0x94, 0x6a, 0x73, 0x97, 0xd0, 0xac,
- 0x30, 0xe5, 0x48, 0xfb, 0x34, 0x40, 0xc2, 0xab, 0xff, 0x4b, 0x7c, 0x87,
- 0x19, 0x1a, 0x54, 0xe5, 0xfb, 0x97, 0x2c, 0xeb, 0x9c, 0xbf, 0xa5, 0x1a,
- 0xfd, 0x46, 0x1c, 0xbf, 0xfb, 0x88, 0xe6, 0xfd, 0x83, 0x2c, 0xd9, 0xcb,
- 0xe6, 0x40, 0x3c, 0x72, 0xb0, 0xf9, 0x9d, 0x12, 0xfc, 0xfe, 0xf3, 0xe8,
- 0xe5, 0xef, 0x38, 0x9c, 0xb3, 0xe2, 0x3e, 0x06, 0x12, 0xdb, 0x20, 0xe0,
- 0x27, 0xae, 0x49, 0xb5, 0xf6, 0x32, 0x3b, 0xfe, 0x86, 0xb0, 0xf6, 0x27,
- 0x71, 0x39, 0x7f, 0xd0, 0xb8, 0x62, 0x33, 0xf4, 0x39, 0x5a, 0x44, 0xff,
- 0x4b, 0x38, 0x0e, 0xef, 0xe5, 0x1b, 0xd2, 0x67, 0x4a, 0x5f, 0xb7, 0xd8,
- 0xc9, 0xce, 0x5f, 0xfd, 0xf8, 0xa6, 0x7d, 0xe9, 0xa4, 0xfa, 0x39, 0x7d,
- 0x37, 0x5e, 0x63, 0x97, 0xcb, 0x7d, 0x4e, 0x72, 0xfd, 0x93, 0x4a, 0x3e,
- 0x39, 0x72, 0x4c, 0x72, 0xfe, 0xde, 0x68, 0x3d, 0xc3, 0x95, 0xd3, 0xc4,
- 0xd8, 0xbd, 0xe1, 0x89, 0x14, 0xbf, 0xf0, 0xfe, 0x9c, 0x1c, 0x00, 0x94,
- 0x35, 0x9c, 0xac, 0x3e, 0x37, 0x1b, 0xae, 0x49, 0xe3, 0xfc, 0x51, 0xa4,
- 0x6e, 0x92, 0x09, 0x1f, 0x9b, 0x78, 0x21, 0x0b, 0x50, 0xba, 0x25, 0x85,
- 0xe9, 0x29, 0x2f, 0xa6, 0x6f, 0x1f, 0xb5, 0xfd, 0xf6, 0xf5, 0xa8, 0xf1,
- 0xcb, 0xfa, 0x5b, 0x57, 0x4e, 0xb3, 0x97, 0x87, 0xdb, 0x39, 0x78, 0x52,
- 0x47, 0x2f, 0xdb, 0x00, 0x81, 0x67, 0x2f, 0xef, 0x4d, 0x2c, 0xfa, 0x47,
- 0x2a, 0x11, 0x7c, 0x85, 0xee, 0x38, 0x01, 0xb5, 0x0a, 0x2f, 0xfe, 0xeb,
- 0x71, 0xad, 0xe3, 0x6f, 0xa5, 0x4e, 0x5f, 0x04, 0x38, 0xc3, 0x97, 0x7f,
- 0x05, 0x2e, 0x6d, 0xb2, 0x94, 0x86, 0xc1, 0xb1, 0x7b, 0xf0, 0x40, 0xfa,
- 0x91, 0x4e, 0x66, 0x86, 0xb1, 0x15, 0xaa, 0xb9, 0xdf, 0xfe, 0xf7, 0xcb,
- 0x4e, 0xb4, 0x8f, 0x75, 0x4d, 0x9c, 0xbf, 0xd1, 0x24, 0xf4, 0xa3, 0xc7,
- 0x2e, 0xe1, 0xf6, 0x73, 0x46, 0xca, 0xff, 0xba, 0xfe, 0xda, 0xc7, 0x27,
- 0x39, 0x72, 0xd0, 0xe5, 0xf0, 0xa7, 0xd2, 0x39, 0x7f, 0xc9, 0xf7, 0x70,
- 0x3a, 0x75, 0x9c, 0xa8, 0x3d, 0xbd, 0x11, 0x5f, 0xed, 0xe2, 0x79, 0x54,
- 0xe9, 0xcb, 0xfe, 0xec, 0x6a, 0x16, 0x82, 0xb3, 0x97, 0x95, 0x7d, 0xad,
- 0x1f, 0x9a, 0x71, 0xf1, 0x0f, 0x01, 0x9d, 0x62, 0x70, 0xfe, 0x8c, 0xd6,
- 0xa4, 0xad, 0xd3, 0x50, 0xf4, 0x61, 0x18, 0x21, 0x02, 0xdc, 0x76, 0x77,
- 0xf3, 0x6a, 0xbf, 0x86, 0x0e, 0x5f, 0x01, 0x98, 0x13, 0x95, 0xf1, 0xe8,
- 0x70, 0x17, 0x5f, 0xfb, 0xb9, 0xc0, 0xe2, 0xae, 0x7d, 0xe3, 0x97, 0xfd,
- 0x8b, 0xea, 0x07, 0xa0, 0x54, 0xe5, 0xef, 0x62, 0xce, 0x53, 0x0f, 0x5b,
- 0x67, 0x57, 0xa4, 0xcf, 0xce, 0x52, 0xa8, 0xd8, 0xfe, 0x13, 0x1e, 0x22,
- 0xbf, 0xe5, 0x5f, 0x94, 0x30, 0x51, 0x53, 0x97, 0xfe, 0x7d, 0xb2, 0x13,
- 0x5a, 0x46, 0xce, 0x5b, 0x6a, 0x9f, 0xcf, 0x4e, 0xef, 0x9e, 0x4f, 0xa3,
- 0x97, 0xfd, 0x9e, 0xf2, 0x2b, 0xec, 0x59, 0xcb, 0xfa, 0x3e, 0xde, 0x7d,
- 0xe3, 0x97, 0x6a, 0x0e, 0x50, 0x4f, 0x17, 0xc5, 0xf7, 0xfb, 0xc8, 0xb4,
- 0x0c, 0x78, 0xe5, 0xfb, 0x70, 0xbc, 0x61, 0xca, 0x83, 0xd9, 0xd9, 0x95,
- 0xb6, 0x14, 0xc6, 0xb1, 0xfb, 0x4f, 0x75, 0xf2, 0x73, 0x4c, 0x29, 0xf4,
- 0x67, 0x77, 0xfd, 0xe4, 0x9e, 0x3e, 0xff, 0x50, 0x72, 0xf6, 0xfd, 0x87,
- 0x2e, 0xcd, 0xf2, 0x3d, 0x75, 0x0e, 0xef, 0xf7, 0x56, 0x9b, 0x04, 0x90,
- 0xe5, 0xff, 0xd9, 0xe4, 0xfa, 0x43, 0x1c, 0x33, 0x51, 0x68, 0x72, 0xff,
- 0xf0, 0x25, 0xd7, 0x4f, 0x20, 0xf8, 0x1d, 0x39, 0x7f, 0x95, 0xf7, 0xcb,
- 0x4d, 0x6c, 0xe5, 0xfb, 0x3d, 0xfb, 0xf8, 0xe5, 0x42, 0x65, 0x72, 0x33,
- 0xd2, 0x88, 0x12, 0x5a, 0x1b, 0x5f, 0xff, 0xa3, 0xaf, 0x83, 0x1a, 0x54,
- 0x20, 0x7d, 0x48, 0xe5, 0x49, 0x3f, 0xbf, 0x46, 0xb7, 0xc0, 0x99, 0x50,
- 0xbd, 0x73, 0x90, 0xad, 0x48, 0x7f, 0x3c, 0xa4, 0xa0, 0x4a, 0x8a, 0xbe,
- 0xea, 0x3c, 0x8e, 0x5f, 0xec, 0x19, 0x66, 0xd4, 0x61, 0xcb, 0xf3, 0x37,
- 0xfb, 0xb9, 0xca, 0xf1, 0xed, 0xa8, 0x67, 0x7f, 0xda, 0xc1, 0xe5, 0xdc,
- 0xf9, 0xb3, 0x97, 0xfd, 0x21, 0x07, 0xfc, 0x96, 0xcf, 0xce, 0x54, 0xe9,
- 0x8c, 0xc9, 0xf3, 0x08, 0xfe, 0x3c, 0xbf, 0xf9, 0xfb, 0xb4, 0x92, 0x7a,
- 0x3d, 0xb3, 0x97, 0xfb, 0x3d, 0xd4, 0x68, 0xf3, 0x9c, 0xbf, 0xe1, 0x8c,
- 0xfb, 0xd9, 0xa8, 0x39, 0x7f, 0xe8, 0xea, 0x9b, 0x1c, 0xf7, 0x70, 0xe5,
- 0x42, 0x65, 0x88, 0x7f, 0xd4, 0x37, 0x35, 0xfc, 0xde, 0xfc, 0xfc, 0x42,
- 0x18, 0x39, 0x76, 0xf6, 0x72, 0xf3, 0x6d, 0xb6, 0x72, 0xef, 0xdc, 0xa7,
- 0x33, 0x41, 0x5a, 0x3e, 0x0d, 0x9b, 0xdf, 0xfb, 0x36, 0x2e, 0xac, 0xc2,
- 0x93, 0x1c, 0xbf, 0xbf, 0x89, 0x75, 0x4d, 0x9c, 0xbf, 0x90, 0x7f, 0x5a,
- 0xd0, 0xe5, 0xe7, 0xff, 0x0a, 0x54, 0x93, 0x63, 0x64, 0x22, 0x7a, 0x45,
- 0xf9, 0xff, 0x13, 0x06, 0x85, 0xb7, 0xd0, 0x14, 0x09, 0xcb, 0xf0, 0x74,
- 0x80, 0x9c, 0xe5, 0xfe, 0x6f, 0x07, 0x38, 0xa6, 0x8e, 0x5f, 0xc3, 0x9f,
- 0x7e, 0xa4, 0x8e, 0x54, 0xc8, 0x8d, 0x12, 0x9f, 0x1a, 0x5f, 0xb3, 0x3d,
- 0xdc, 0x39, 0x73, 0xb0, 0xe5, 0xff, 0x03, 0x7e, 0x89, 0x81, 0xf6, 0xce,
- 0x5f, 0xec, 0xe3, 0x9c, 0xdb, 0x6d, 0xb2, 0x97, 0xe9, 0xa3, 0x3b, 0xb3,
- 0x95, 0xc9, 0x13, 0xc2, 0x78, 0xa1, 0xd5, 0xfe, 0xe1, 0xe0, 0x0b, 0xea,
- 0x68, 0xe5, 0xe6, 0x3f, 0x8e, 0x54, 0xc9, 0x9d, 0x76, 0x16, 0x80, 0x32,
- 0xe2, 0x71, 0x77, 0xed, 0x51, 0xcb, 0xf7, 0x17, 0x62, 0x30, 0xe5, 0x41,
- 0xe3, 0x08, 0xed, 0xfb, 0x26, 0x94, 0x48, 0xe5, 0xfd, 0x38, 0x63, 0x04,
- 0x27, 0x2a, 0x15, 0xd0, 0xc9, 0x89, 0x21, 0x5d, 0xd3, 0x07, 0x8d, 0x83,
- 0x70, 0x8c, 0xf1, 0x02, 0x85, 0x17, 0x9f, 0xf4, 0x39, 0x7f, 0xc1, 0x10,
- 0x6f, 0x27, 0xc9, 0xce, 0x5e, 0x8d, 0x09, 0xcb, 0xfd, 0x81, 0x17, 0xda,
- 0x04, 0xe5, 0xba, 0x72, 0xf0, 0x1e, 0x71, 0x3c, 0x2d, 0x98, 0xd9, 0x34,
- 0x89, 0x0f, 0x2e, 0xd3, 0x13, 0x0e, 0x71, 0xce, 0x1e, 0x19, 0x56, 0x13,
- 0x97, 0xd1, 0x3c, 0x48, 0xe5, 0x39, 0xb2, 0x11, 0x0b, 0xff, 0xd8, 0x17,
- 0x66, 0x7d, 0x2c, 0xff, 0x02, 0x72, 0xee, 0xb9, 0xcb, 0xa6, 0xd9, 0xcb,
- 0xf6, 0x71, 0x41, 0x0e, 0x1a, 0xe5, 0x05, 0xaf, 0xee, 0x5e, 0xcd, 0xee,
- 0x0e, 0x5f, 0xbb, 0x9f, 0x7a, 0x0e, 0x5f, 0xb8, 0x1e, 0x75, 0x24, 0x72,
- 0xb9, 0x26, 0x75, 0xcd, 0xe2, 0x0f, 0xb0, 0xbc, 0x05, 0x17, 0xc1, 0xce,
- 0xb9, 0xcb, 0xff, 0x60, 0xcb, 0xb8, 0x23, 0x0d, 0x9c, 0xbf, 0xf6, 0x6b,
- 0x4f, 0x2e, 0x5c, 0x61, 0xac, 0xe5, 0x42, 0x20, 0x64, 0x79, 0x5a, 0x4c,
- 0x44, 0x53, 0x7d, 0x0a, 0x2b, 0xfd, 0xad, 0xf7, 0x05, 0x36, 0x72, 0xa1,
- 0x56, 0x8a, 0x4a, 0x6a, 0x73, 0x5b, 0xfe, 0xc0, 0xe0, 0xc0, 0x82, 0x0e,
- 0x5d, 0x0d, 0x9c, 0xa8, 0x7c, 0x78, 0x39, 0xe1, 0xaf, 0x29, 0xcf, 0x20,
- 0xce, 0xdd, 0x64, 0x65, 0xca, 0xc3, 0xcd, 0x73, 0x8d, 0xff, 0x42, 0xed,
- 0x23, 0x0e, 0x9a, 0x12, 0x5a, 0xac, 0x2c, 0x59, 0x2c, 0x5b, 0xb3, 0xca,
- 0xae, 0xad, 0xfc, 0x3b, 0x46, 0x94, 0xeb, 0xb9, 0x54, 0xde, 0x9d, 0x4d,
- 0x04, 0x71, 0xfc, 0x65, 0x9e, 0xa8, 0x6d, 0xc0, 0x6b, 0x7f, 0xd9, 0xa1,
- 0x8f, 0x4b, 0x3a, 0x72, 0xff, 0xe1, 0x5a, 0xaf, 0xbc, 0x94, 0x0a, 0xce,
- 0x5f, 0xbf, 0xc0, 0xbc, 0x8e, 0x52, 0x1f, 0x58, 0xa1, 0xdf, 0xf7, 0xb7,
- 0xd4, 0x86, 0x38, 0x4e, 0x5f, 0xfb, 0xa8, 0x31, 0xf6, 0xd1, 0x90, 0x72,
- 0xf6, 0xe3, 0x47, 0x2e, 0xf6, 0xd6, 0x7b, 0x3f, 0x1e, 0xd4, 0x23, 0x00,
- 0x10, 0x91, 0xbf, 0xcb, 0x1c, 0x94, 0x9f, 0x67, 0x2f, 0xe7, 0x6f, 0x3f,
- 0x53, 0xc7, 0x2f, 0xcf, 0x2e, 0x41, 0x43, 0x97, 0xf6, 0xf0, 0x29, 0xb9,
- 0xce, 0x5e, 0x94, 0x7e, 0x72, 0xfc, 0xa4, 0xd2, 0x86, 0xb2, 0x95, 0x0a,
- 0xab, 0x32, 0x14, 0x4a, 0xc3, 0x81, 0x09, 0xf4, 0x65, 0xd3, 0x0d, 0x94,
- 0xf8, 0xb9, 0x41, 0xdb, 0x2c, 0xe5, 0xff, 0xca, 0x88, 0x1d, 0x4c, 0xda,
- 0x40, 0x9c, 0xbc, 0xd1, 0x02, 0x72, 0xb4, 0x7c, 0x2c, 0x43, 0xbd, 0x0f,
- 0xa3, 0x97, 0xf3, 0x3d, 0xd8, 0xe3, 0x07, 0x2f, 0xfe, 0xfb, 0xc0, 0x67,
- 0x61, 0x05, 0xc2, 0x72, 0xf9, 0x5d, 0x3b, 0x67, 0x2c, 0xa1, 0xa2, 0x05,
- 0x5b, 0xc6, 0xa0, 0x51, 0x5e, 0x37, 0xad, 0x8f, 0xd6, 0x22, 0x0d, 0x18,
- 0x6f, 0xe4, 0xe1, 0xd7, 0xd8, 0x6c, 0xe5, 0xfe, 0xea, 0x29, 0xcf, 0xff,
- 0xe0, 0xa5, 0x68, 0xfa, 0xda, 0x19, 0xdf, 0x0f, 0x07, 0x0f, 0xb3, 0x94,
- 0x87, 0x9c, 0xa1, 0x25, 0xfd, 0xdc, 0x07, 0x0f, 0x9b, 0x39, 0x7f, 0xc3,
- 0xed, 0x83, 0xef, 0x23, 0x67, 0x2f, 0xff, 0xd8, 0xdc, 0x30, 0x0e, 0x1f,
- 0x7c, 0xb4, 0x16, 0xce, 0x5f, 0xe0, 0x3e, 0xf3, 0x05, 0x53, 0x95, 0x08,
- 0xc4, 0x09, 0xdf, 0x55, 0xef, 0xfa, 0x3d, 0xbe, 0x58, 0xc4, 0x09, 0xcb,
- 0xff, 0x72, 0x17, 0x57, 0x96, 0xff, 0xfe, 0x0e, 0x5f, 0xfe, 0x9c, 0x1f,
- 0xee, 0x49, 0xbd, 0xc6, 0xa4, 0x72, 0xc8, 0xaa, 0x24, 0xb4, 0x8b, 0x7f,
- 0x9f, 0xbf, 0x6e, 0x07, 0xc7, 0x2b, 0x67, 0xb9, 0xe2, 0x9b, 0xff, 0xfe,
- 0x9c, 0x3d, 0x85, 0xf5, 0x26, 0x77, 0x92, 0xae, 0xa3, 0xb5, 0x9c, 0xbf,
- 0xdd, 0x49, 0xa5, 0x03, 0x23, 0x97, 0xfe, 0x86, 0xf7, 0xc2, 0x3a, 0xf3,
- 0xef, 0x1c, 0xa8, 0x47, 0x22, 0xdb, 0x3c, 0x67, 0x7d, 0x2e, 0xe4, 0xe7,
- 0x2f, 0xfa, 0x3e, 0x63, 0xfb, 0x3e, 0xf1, 0xcb, 0x9e, 0x73, 0x95, 0xf1,
- 0xfa, 0x09, 0x1b, 0x67, 0x57, 0xe0, 0x77, 0x50, 0xd9, 0xcb, 0x9a, 0x39,
- 0xcb, 0xa1, 0x7e, 0x3c, 0x15, 0x0a, 0x6e, 0xd3, 0x9c, 0xbf, 0xfb, 0x8a,
- 0x6f, 0x78, 0x2b, 0x71, 0xfc, 0xe5, 0xfe, 0xea, 0x04, 0x38, 0xdc, 0xc7,
- 0x2f, 0x46, 0xbf, 0xc3, 0xfa, 0x5a, 0x2d, 0x69, 0x18, 0x7d, 0x84, 0x85,
- 0xff, 0x9f, 0xed, 0xe7, 0x91, 0x8f, 0x23, 0x96, 0xf1, 0xca, 0xfc, 0xf3,
- 0xd4, 0x3e, 0xbf, 0xff, 0xd3, 0x0c, 0x33, 0x50, 0xbc, 0xd6, 0x75, 0x35,
- 0xd7, 0x39, 0x7f, 0xfc, 0xfa, 0xfd, 0xa6, 0x6a, 0x24, 0x9f, 0x7b, 0x0e,
- 0x5f, 0xff, 0xfc, 0x0d, 0xf5, 0xe5, 0xb9, 0x27, 0x94, 0xd4, 0x76, 0x3d,
- 0xb7, 0xf8, 0xe5, 0xfa, 0x30, 0x7c, 0xd0, 0xe5, 0xfc, 0x9f, 0x7f, 0xa7,
- 0x09, 0xcb, 0x30, 0xe5, 0x30, 0xfa, 0x3a, 0x50, 0x25, 0xf7, 0x69, 0xac,
- 0xe5, 0xe9, 0x00, 0x27, 0x2e, 0x7f, 0xb9, 0x1f, 0x2c, 0xc5, 0xce, 0x35,
- 0x58, 0xa8, 0xbd, 0x17, 0xf4, 0xa5, 0xb8, 0xd0, 0x6f, 0xff, 0xec, 0x19,
- 0xf7, 0xb8, 0xff, 0x3a, 0x9a, 0x76, 0xfc, 0x72, 0xfe, 0x0e, 0x0a, 0xba,
- 0x83, 0x95, 0x26, 0x47, 0x70, 0x61, 0xec, 0xb2, 0xff, 0xa3, 0x28, 0x9a,
- 0x30, 0x6d, 0x42, 0x8d, 0x8e, 0x3d, 0x87, 0x8f, 0xee, 0xfe, 0x94, 0xa6,
- 0xda, 0x1b, 0x45, 0xcb, 0xff, 0xfc, 0x38, 0x1e, 0xc3, 0x63, 0x89, 0x3b,
- 0x40, 0x75, 0x34, 0x72, 0xa1, 0x94, 0x86, 0x94, 0x91, 0x00, 0x43, 0x46,
- 0xd0, 0x72, 0xff, 0xfa, 0x67, 0x79, 0x6e, 0x18, 0x1e, 0xc0, 0xac, 0xe5,
- 0x41, 0xef, 0xa0, 0x85, 0xff, 0x64, 0xd2, 0x8f, 0xb3, 0xef, 0x1c, 0xbb,
- 0x53, 0xe1, 0xed, 0x89, 0x05, 0xf0, 0x7a, 0x09, 0xce, 0x5f, 0xe0, 0xbc,
- 0xb2, 0x70, 0x09, 0xcb, 0xff, 0x6b, 0x1a, 0xe6, 0xeb, 0xb1, 0x36, 0x72,
- 0xd3, 0xc2, 0x26, 0x70, 0x93, 0x46, 0x77, 0x70, 0xf8, 0x72, 0xb0, 0xf4,
- 0x1c, 0xd6, 0xfe, 0xf3, 0x40, 0x77, 0x16, 0x72, 0xff, 0x6a, 0x3c, 0x9f,
- 0xc4, 0x8e, 0x5f, 0xdf, 0x4e, 0xf2, 0x86, 0xb3, 0x97, 0x0c, 0x8e, 0x54,
- 0x1e, 0x44, 0xe6, 0x55, 0xc2, 0x33, 0xef, 0xe1, 0xca, 0x44, 0x4a, 0x8d,
- 0xa1, 0x7b, 0x21, 0x8f, 0xda, 0x58, 0xeb, 0xc3, 0xe8, 0x63, 0x16, 0xd9,
- 0x07, 0x8c, 0x00, 0xf7, 0x7f, 0xee, 0x11, 0x48, 0x62, 0xfa, 0xff, 0x7e,
- 0x72, 0xff, 0x4a, 0x6c, 0x17, 0xee, 0x1c, 0xbe, 0xfa, 0x50, 0xc3, 0x97,
- 0x47, 0x4e, 0x5f, 0xcf, 0x30, 0x60, 0x67, 0x39, 0x53, 0x9f, 0x38, 0x91,
- 0xf1, 0x16, 0xbe, 0x89, 0x93, 0xa7, 0x2f, 0x70, 0x43, 0x0e, 0x53, 0x9e,
- 0x0f, 0x01, 0x15, 0xf7, 0x04, 0x0a, 0xce, 0x5f, 0xdd, 0xc5, 0x5e, 0x27,
- 0x39, 0x7e, 0x64, 0x4d, 0xa8, 0x39, 0x7d, 0x00, 0xe1, 0xd0, 0xe5, 0xf9,
- 0xf7, 0xe4, 0x98, 0xe5, 0xfe, 0x4d, 0x44, 0xef, 0xa5, 0x9c, 0xb7, 0xb9,
- 0x26, 0x3f, 0x84, 0x8b, 0x24, 0x42, 0xed, 0x14, 0x6c, 0x9b, 0xc5, 0x17,
- 0xff, 0xb4, 0xb1, 0xce, 0x23, 0x91, 0xa8, 0xd9, 0xcb, 0xfc, 0xf3, 0x77,
- 0x19, 0x9b, 0x39, 0x58, 0x7f, 0x9c, 0x52, 0x6f, 0x34, 0x8f, 0x1c, 0xbf,
- 0x95, 0xe5, 0x1c, 0x53, 0x89, 0xca, 0x9c, 0xf4, 0x84, 0x7a, 0xfc, 0xaf,
- 0xb3, 0x18, 0x72, 0xb0, 0xf2, 0x90, 0x8a, 0xff, 0xf4, 0xc3, 0x8a, 0xaa,
- 0xfe, 0xda, 0x0c, 0xc7, 0x2f, 0xd8, 0x14, 0xd6, 0xce, 0x5f, 0x94, 0x92,
- 0x7f, 0xb3, 0x97, 0xed, 0x2e, 0x32, 0x73, 0x97, 0xbd, 0xef, 0x8e, 0x5f,
- 0xfd, 0xf2, 0xd3, 0xbc, 0xb8, 0x33, 0xa8, 0xc3, 0x95, 0xf9, 0xf4, 0x78,
- 0x7a, 0xe0, 0x68, 0xe5, 0x62, 0x32, 0xb7, 0x09, 0x06, 0x84, 0x76, 0x89,
- 0xd3, 0x51, 0x61, 0x3b, 0x70, 0xf4, 0xa8, 0x5d, 0x31, 0xc8, 0xe4, 0x52,
- 0x1c, 0xfd, 0x85, 0xfb, 0x90, 0x7a, 0x39, 0xdb, 0xff, 0x0a, 0x29, 0xf6,
- 0x71, 0xfa, 0x14, 0x39, 0x7f, 0xf9, 0x33, 0x41, 0x86, 0xf3, 0xb1, 0xf6,
- 0xce, 0x5f, 0x29, 0x1a, 0xfc, 0xe5, 0xff, 0xa3, 0xee, 0xf6, 0x27, 0x80,
- 0x30, 0xe5, 0xca, 0x48, 0xe5, 0xcf, 0xa3, 0x97, 0xf7, 0x92, 0x76, 0x42,
- 0xce, 0x50, 0x4f, 0x13, 0xa2, 0xd7, 0xff, 0xbf, 0x9a, 0x49, 0xa9, 0x4d,
- 0x24, 0xd4, 0x8e, 0x5e, 0xf2, 0x4e, 0x72, 0xbe, 0x3e, 0xbd, 0x27, 0x5f,
- 0x99, 0x80, 0xd4, 0xe7, 0x2f, 0x40, 0x42, 0x72, 0xec, 0xe0, 0x39, 0x7d,
- 0xfa, 0x83, 0x23, 0x96, 0x71, 0x37, 0xbe, 0x19, 0xbf, 0x6f, 0x78, 0x3f,
- 0x9c, 0xaf, 0xcf, 0x34, 0x49, 0x6a, 0x13, 0xa1, 0x48, 0x46, 0xb9, 0x1f,
- 0x8a, 0x41, 0x0a, 0x6b, 0xbe, 0x98, 0xe5, 0xf9, 0x4f, 0x7e, 0xcc, 0x39,
- 0x4c, 0x3c, 0x3f, 0xc6, 0x6f, 0x2e, 0x36, 0x72, 0xff, 0xa4, 0xfa, 0xf0,
- 0xc3, 0x36, 0x72, 0xff, 0x40, 0x63, 0x40, 0x8f, 0xce, 0x5c, 0xcd, 0xcc,
- 0x7d, 0x6c, 0x38, 0xbf, 0xfe, 0x8c, 0xfb, 0xdd, 0xc4, 0x92, 0x2a, 0xae,
- 0x1c, 0xbf, 0xff, 0x9d, 0xb0, 0xbb, 0xea, 0x7e, 0xbf, 0xba, 0x9a, 0x91,
- 0xcb, 0xff, 0x43, 0x8e, 0x7b, 0xc8, 0xdf, 0x8e, 0x54, 0x27, 0x85, 0x84,
- 0x69, 0x08, 0x7d, 0x17, 0x8a, 0x80, 0x17, 0x2b, 0x86, 0x66, 0x0d, 0xc2,
- 0x3c, 0xa7, 0x72, 0xb1, 0xb1, 0x68, 0x73, 0x25, 0x74, 0x93, 0xf4, 0x0d,
- 0xc7, 0xfb, 0xe9, 0x4a, 0xf7, 0xf4, 0x03, 0xe4, 0xfb, 0x80, 0xe5, 0xfb,
- 0x1b, 0xcf, 0xbc, 0x72, 0xb9, 0x1e, 0xda, 0x19, 0x5f, 0xef, 0xa5, 0x81,
- 0xee, 0x4e, 0x72, 0xb4, 0x7b, 0x02, 0x47, 0x7b, 0x59, 0xb3, 0x97, 0xe4,
- 0x1e, 0x39, 0x23, 0x97, 0xb1, 0x27, 0x39, 0x4a, 0x9f, 0x03, 0x07, 0x3a,
- 0x51, 0x7f, 0x44, 0xf9, 0xec, 0x61, 0xcb, 0xff, 0xb0, 0x40, 0xbe, 0xe3,
- 0x26, 0x75, 0x9c, 0xa4, 0x45, 0x0e, 0x8c, 0x36, 0x5b, 0x7c, 0xc4, 0x80,
- 0x9c, 0xbf, 0xc2, 0xaf, 0x61, 0x8c, 0x13, 0x97, 0xf3, 0x5a, 0x47, 0x00,
- 0x3c, 0x72, 0xfd, 0x13, 0x66, 0x2c, 0xe5, 0x42, 0x2b, 0xb0, 0x85, 0x0c,
- 0xfa, 0x67, 0x7f, 0xee, 0xe4, 0xc9, 0x30, 0x38, 0x01, 0xb3, 0x97, 0x93,
- 0x4a, 0x9c, 0xa4, 0x3e, 0x11, 0x44, 0xbf, 0x47, 0x07, 0x62, 0x63, 0x95,
- 0x23, 0xcb, 0xd9, 0x05, 0xff, 0xc0, 0x99, 0x3b, 0x1f, 0x4a, 0x26, 0x83,
- 0x97, 0xe0, 0xb8, 0xc7, 0x4e, 0x5f, 0xd2, 0x8f, 0xbd, 0x9d, 0x39, 0x7f,
- 0xfb, 0xdb, 0x4f, 0xe2, 0x5b, 0xcc, 0xfb, 0xc7, 0x2a, 0x63, 0xf9, 0xd9,
- 0x75, 0x75, 0x18, 0x4d, 0xc2, 0x7e, 0xff, 0x75, 0xe6, 0xc4, 0xe0, 0x09,
- 0xca, 0x43, 0xdf, 0xd9, 0x4d, 0xff, 0xfb, 0x40, 0xd6, 0xa0, 0x71, 0x54,
- 0xef, 0x71, 0x43, 0x97, 0xa6, 0xd4, 0x1c, 0xbf, 0x3a, 0x06, 0x04, 0xe5,
- 0xd0, 0x03, 0x95, 0x07, 0xb0, 0x23, 0xbb, 0x25, 0xbe, 0x9e, 0x38, 0x20,
- 0xe5, 0xf7, 0x7f, 0x7f, 0x1c, 0xb7, 0x4e, 0x5b, 0x8b, 0x9b, 0x40, 0x11,
- 0xdf, 0xfc, 0x8c, 0x4d, 0xf6, 0x13, 0x40, 0x6b, 0x39, 0x50, 0x8c, 0x74,
- 0x59, 0x72, 0x8b, 0xf8, 0x76, 0x9c, 0x60, 0x27, 0x2f, 0xfb, 0xf4, 0x1f,
- 0x46, 0xc1, 0xd3, 0x97, 0x85, 0x15, 0x39, 0x7f, 0x79, 0x34, 0x9e, 0x01,
- 0xcb, 0x47, 0x24, 0x41, 0x30, 0xe5, 0x41, 0xcb, 0xf8, 0x0a, 0x77, 0x3e,
- 0xd9, 0xcb, 0xff, 0xff, 0xf6, 0xa3, 0xc2, 0xeb, 0x4d, 0xcc, 0x9a, 0x5c,
- 0x6f, 0xd1, 0xf4, 0x29, 0x9b, 0x39, 0x7f, 0xbb, 0x9f, 0x46, 0x91, 0x87,
- 0x2f, 0xff, 0xff, 0xfb, 0x79, 0xee, 0xbb, 0x37, 0xad, 0x27, 0xde, 0x77,
- 0x57, 0x32, 0x60, 0x7a, 0x1b, 0xfa, 0x0e, 0x5f, 0x81, 0x36, 0x34, 0xc3,
- 0x95, 0xb4, 0x60, 0xfa, 0x12, 0xf7, 0xfd, 0xf6, 0xc5, 0x19, 0xec, 0x6b,
- 0x39, 0x76, 0x68, 0xe5, 0x41, 0xe9, 0x74, 0xf2, 0xfe, 0xf0, 0xbf, 0xf8,
- 0x27, 0x2f, 0xc2, 0xff, 0xe0, 0x9c, 0xae, 0x47, 0xa5, 0xe2, 0xca, 0x85,
- 0x51, 0x01, 0x84, 0x1b, 0xc3, 0xd3, 0xcf, 0x40, 0x73, 0xbf, 0xf7, 0x93,
- 0x62, 0xfe, 0x99, 0xc2, 0x72, 0xfb, 0xf7, 0xfb, 0x67, 0x2e, 0x6d, 0xb3,
- 0x95, 0xb3, 0x7a, 0xd9, 0x25, 0xf7, 0x5f, 0x3a, 0x53, 0x99, 0xa2, 0xac,
- 0x46, 0x82, 0x42, 0x76, 0xfc, 0xa6, 0x31, 0x34, 0x72, 0xff, 0x81, 0xe8,
- 0x15, 0xb5, 0x7f, 0xb0, 0xe5, 0xee, 0xc7, 0xe7, 0x2f, 0xfc, 0x00, 0xf5,
- 0x34, 0x9f, 0x4d, 0x07, 0x2b, 0x11, 0x88, 0x85, 0x0e, 0x7e, 0x23, 0xb7,
- 0xbb, 0xc9, 0xac, 0xe5, 0xfb, 0xb0, 0x39, 0x39, 0xca, 0x83, 0xc9, 0x72,
- 0x2b, 0xfd, 0xd8, 0xf0, 0x18, 0x0f, 0x1c, 0xa8, 0x66, 0x71, 0x4a, 0x32,
- 0x20, 0xc3, 0x77, 0xe8, 0x73, 0x35, 0x91, 0x4d, 0x1b, 0x3e, 0x88, 0x59,
- 0x0a, 0xee, 0xc3, 0xd1, 0xcb, 0x7f, 0x85, 0x87, 0x0e, 0x70, 0x32, 0xae,
- 0x37, 0x19, 0x27, 0xa1, 0xd5, 0xc6, 0x10, 0x5c, 0x04, 0x17, 0xc9, 0xa5,
- 0x26, 0x39, 0x7f, 0xe1, 0xfd, 0x8f, 0x21, 0x8f, 0x6c, 0xe5, 0xd9, 0x87,
- 0x2f, 0x97, 0xd4, 0x50, 0xe5, 0x75, 0x13, 0x4e, 0x49, 0xc3, 0x9f, 0x28,
- 0x2b, 0x7e, 0x9a, 0x26, 0xec, 0x1c, 0xbf, 0xfc, 0x3e, 0xda, 0x9e, 0x41,
- 0x04, 0xb3, 0x67, 0x2e, 0x52, 0x0e, 0x5e, 0x6d, 0xb6, 0xca, 0x5f, 0x4b,
- 0xd8, 0xb2, 0x9c, 0xcd, 0x05, 0xfb, 0x02, 0x9f, 0xec, 0xf7, 0x7f, 0x2b,
- 0x47, 0xd2, 0x26, 0x95, 0x09, 0x9a, 0x61, 0x4e, 0x92, 0x9e, 0x14, 0x17,
- 0x7b, 0x67, 0x2f, 0xf7, 0xbb, 0x1e, 0xdf, 0x50, 0xe5, 0xfb, 0x96, 0x4c,
- 0x93, 0x9c, 0xae, 0x47, 0xbd, 0xb3, 0x3b, 0x6c, 0xe5, 0xfe, 0xf7, 0xd2,
- 0xec, 0x0c, 0xe5, 0x2f, 0xfd, 0x9f, 0x49, 0x30, 0x47, 0x02, 0x72, 0xfd,
- 0x3b, 0x01, 0xf7, 0x8e, 0x54, 0x26, 0x8d, 0xf3, 0xae, 0x89, 0x04, 0x47,
- 0x66, 0xbe, 0x3c, 0xb2, 0x1c, 0xbe, 0x75, 0x1c, 0x27, 0x2e, 0xfa, 0x4e,
- 0x6c, 0x80, 0x21, 0x7f, 0xc3, 0x0d, 0xed, 0x07, 0xe9, 0x1c, 0xba, 0x16,
- 0x72, 0x84, 0xf3, 0xf8, 0x9c, 0xdf, 0x4e, 0xa4, 0x35, 0x9c, 0xbf, 0x0c,
- 0x37, 0x82, 0x72, 0xff, 0xbb, 0xf4, 0x2b, 0x34, 0xa1, 0xac, 0xe5, 0xb6,
- 0x13, 0xe5, 0xc2, 0x6a, 0xd2, 0x2c, 0xfd, 0x08, 0xca, 0x85, 0x40, 0x79,
- 0x08, 0x94, 0x7c, 0x78, 0x6b, 0x5f, 0xc3, 0xf6, 0xe6, 0xcf, 0x1c, 0xbf,
- 0x93, 0xc2, 0xff, 0xec, 0xe5, 0xff, 0xef, 0x4d, 0x9a, 0xc7, 0x64, 0x75,
- 0x02, 0x72, 0xfe, 0x03, 0x33, 0xbf, 0x39, 0xca, 0x55, 0x14, 0x82, 0x5b,
- 0xb4, 0x9b, 0xff, 0xc8, 0x11, 0x7f, 0x87, 0x3d, 0x89, 0xf9, 0xcb, 0xe5,
- 0x84, 0x13, 0x9c, 0xbd, 0x2d, 0x80, 0xe5, 0xd1, 0xec, 0x3c, 0x1e, 0x92,
- 0x5f, 0xba, 0xfa, 0xcd, 0x1c, 0xb8, 0x0e, 0x72, 0x96, 0x6f, 0x44, 0x9e,
- 0xfa, 0x5e, 0x00, 0x4e, 0x5f, 0xa1, 0x24, 0xfb, 0x39, 0x5f, 0x1e, 0x4e,
- 0x88, 0xef, 0xfd, 0xf6, 0xd1, 0x5c, 0xf2, 0x6b, 0x0e, 0x54, 0xe8, 0xcb,
- 0x16, 0x9f, 0x11, 0xdf, 0xe0, 0x8e, 0x71, 0x4d, 0x39, 0xca, 0x83, 0xe3,
- 0x01, 0x85, 0xfa, 0x76, 0xb4, 0xcf, 0x8e, 0x5f, 0x93, 0x71, 0x3b, 0x0f,
- 0x67, 0xea, 0xfd, 0x0f, 0xaf, 0xc0, 0x7b, 0x3f, 0x57, 0x3c, 0x8f, 0x67,
- 0xea, 0xf8, 0x12, 0xcd, 0x9e, 0xcf, 0xd5, 0x04, 0xf4, 0x84, 0x8e, 0xfd,
- 0x19, 0xbc, 0x13, 0xd9, 0xfa, 0xa3, 0xd9, 0xfa, 0xb9, 0xfc, 0x7b, 0x3f,
- 0x4c, 0x2e, 0x2d, 0x21, 0x3f, 0xc0, 0x25, 0x5f, 0x63, 0x44, 0xfc, 0xf6,
- 0x7e, 0xa8, 0xf6, 0x7e, 0xae, 0xfe, 0x0f, 0x67, 0xea, 0xff, 0xb3, 0xf7,
- 0xd6, 0x71, 0xc0, 0x9e, 0xcf, 0xd5, 0xfd, 0x9d, 0x4d, 0x82, 0x73, 0xd9,
- 0xfa, 0xaf, 0xd1, 0x4c, 0x24, 0x9b, 0x47, 0xbe, 0xd4, 0xf1, 0xe3, 0xd9,
- 0xfa, 0xa3, 0xd9, 0xfa, 0xc3, 0x61, 0x73, 0x6d, 0x9e, 0xcf, 0xd5, 0x49,
- 0x58, 0xe0, 0x4d, 0x72, 0x10, 0xff, 0x42, 0x77, 0x44, 0xec, 0x31, 0xdc,
- 0x2f, 0xbc, 0xc0, 0xd9, 0x3d, 0xe9, 0x42, 0xa5, 0xb3, 0xf4, 0xe6, 0x89,
- 0x0b, 0xfa, 0x31, 0x48, 0x94, 0x8e, 0x5f, 0xed, 0xe4, 0xa5, 0x1e, 0xf8,
- 0xe5, 0x62, 0x28, 0x04, 0xff, 0x65, 0xb7, 0xfe, 0xc5, 0x87, 0x34, 0xdb,
- 0xf6, 0x63, 0x97, 0xff, 0x6c, 0x72, 0x68, 0x9f, 0xf7, 0xfb, 0x67, 0x2e,
- 0x94, 0xe5, 0x2f, 0xa6, 0x77, 0xd1, 0xca, 0x9d, 0x1d, 0xff, 0x17, 0x75,
- 0x00, 0x51, 0xf8, 0x06, 0x2e, 0x49, 0xce, 0x56, 0x97, 0x73, 0x1e, 0x75,
- 0x9f, 0xc9, 0xd7, 0xf9, 0x9b, 0x1c, 0xf6, 0x7e, 0x72, 0xfe, 0xf6, 0x76,
- 0x35, 0xf9, 0xcb, 0xfe, 0x5c, 0x7e, 0x10, 0x3e, 0xa4, 0x72, 0xff, 0xce,
- 0xf3, 0xe3, 0x1c, 0x7e, 0x91, 0xcb, 0xce, 0xae, 0xf0, 0xfe, 0x26, 0x3a,
- 0xb3, 0x7c, 0x91, 0xb4, 0x30, 0xa6, 0xa8, 0x4c, 0xf5, 0xe3, 0x0d, 0xbf,
- 0x0f, 0xbb, 0x93, 0x9c, 0xb8, 0x2d, 0x9c, 0xa8, 0x3c, 0x0c, 0x28, 0xbf,
- 0xff, 0x4b, 0x51, 0xc5, 0xe6, 0x80, 0xf6, 0x18, 0xf3, 0x1c, 0xbf, 0xdc,
- 0x0f, 0xb4, 0xdc, 0xd8, 0x72, 0xbe, 0x44, 0x76, 0x96, 0x2f, 0x20, 0xc8,
- 0xe5, 0x43, 0x3e, 0xaa, 0x52, 0xe2, 0x71, 0x15, 0x21, 0xa6, 0xd6, 0x61,
- 0xa8, 0x44, 0xf6, 0x39, 0x77, 0x9d, 0xed, 0x18, 0xdd, 0xf6, 0xd0, 0x08,
- 0x57, 0x70, 0x12, 0x5f, 0xff, 0xf2, 0x75, 0xfb, 0x12, 0xe7, 0x9f, 0xc4,
- 0xb6, 0x1e, 0xc6, 0x8e, 0x5f, 0xf9, 0x58, 0xf8, 0x63, 0xbd, 0x02, 0xce,
- 0x5f, 0xfd, 0xa8, 0xc1, 0xc9, 0x27, 0x73, 0x89, 0xcb, 0xff, 0xe1, 0x75,
- 0x77, 0x9c, 0x63, 0xef, 0x6c, 0x0c, 0x39, 0x41, 0x44, 0xb0, 0xa1, 0xde,
- 0x1e, 0x38, 0x72, 0xfe, 0x17, 0x57, 0xaf, 0x23, 0x97, 0xe5, 0xe3, 0x23,
- 0x67, 0x2f, 0x36, 0xdb, 0x65, 0x2f, 0x29, 0x1f, 0x94, 0xe6, 0x68, 0x2f,
- 0xf9, 0xe4, 0xa6, 0xb3, 0x8b, 0xe8, 0xe5, 0xff, 0xfb, 0xb9, 0x25, 0x04,
- 0x72, 0x79, 0xa5, 0x1a, 0x9c, 0xe5, 0x0a, 0x24, 0xfc, 0x77, 0x7f, 0xfb,
- 0xf8, 0x93, 0x8c, 0x91, 0x99, 0xf7, 0x8e, 0x5f, 0xf7, 0x9c, 0x73, 0x7a,
- 0x8d, 0x9c, 0xbe, 0x94, 0x7f, 0xf1, 0xcb, 0xfb, 0xf8, 0x1c, 0xfb, 0xc7,
- 0x2e, 0x7f, 0xf9, 0x1e, 0x92, 0x84, 0x97, 0xff, 0x94, 0x19, 0x95, 0x70,
- 0xf7, 0x17, 0x9a, 0x39, 0x48, 0x9a, 0x83, 0xa5, 0x0c, 0x22, 0x76, 0x63,
- 0x7b, 0x8c, 0x68, 0xe5, 0x49, 0x72, 0x10, 0x2d, 0x19, 0x0d, 0x64, 0x22,
- 0x60, 0xeb, 0x96, 0xfe, 0x8e, 0x30, 0xc3, 0xf4, 0x6e, 0x5c, 0x50, 0x2e,
- 0x49, 0xce, 0x5f, 0xe1, 0x58, 0x53, 0x8c, 0x04, 0xe5, 0x04, 0xf2, 0xc0,
- 0x2f, 0x6f, 0xce, 0x5f, 0xf6, 0x43, 0x5f, 0x2e, 0xbe, 0x68, 0xe5, 0xe6,
- 0x24, 0xc7, 0x2f, 0xd9, 0xfe, 0xe2, 0x47, 0x2f, 0xc8, 0xc0, 0x87, 0x0e,
- 0x5b, 0xf1, 0x3c, 0xf6, 0x85, 0x17, 0xfd, 0xee, 0xe6, 0xf9, 0x79, 0x27,
- 0x39, 0x50, 0x7c, 0xc8, 0x55, 0x7f, 0xc2, 0x80, 0xe1, 0xf6, 0xd2, 0x3c,
- 0x72, 0xa4, 0x9b, 0xfc, 0xc2, 0x4c, 0x3c, 0xec, 0x34, 0x84, 0x82, 0xfb,
- 0x3c, 0xa4, 0xe7, 0x2f, 0x36, 0xdb, 0x65, 0x88, 0x40, 0xbe, 0x5b, 0xba,
- 0xcb, 0x10, 0x81, 0xcc, 0xd7, 0x5f, 0x3e, 0xb1, 0xb3, 0x95, 0xa3, 0xe3,
- 0xe2, 0x83, 0x79, 0xb6, 0xdb, 0x2c, 0x41, 0xe5, 0x16, 0x20, 0xf3, 0x99,
- 0xae, 0xbf, 0xb3, 0xdd, 0x03, 0xc8, 0xe5, 0xe6, 0xdb, 0x6c, 0xe5, 0xed,
- 0xc2, 0xa5, 0x39, 0x9a, 0x0a, 0xc4, 0x7c, 0xad, 0x48, 0x4a, 0xfc, 0x9b,
- 0x4d, 0x69, 0xf4, 0xb2, 0x3a, 0xeb, 0xff, 0xbb, 0x12, 0x4f, 0x67, 0x57,
- 0x0c, 0x39, 0x50, 0x7e, 0x1c, 0x4b, 0x6f, 0xfb, 0x63, 0x0c, 0xde, 0xc0,
- 0x27, 0x2f, 0xff, 0x67, 0x53, 0x5d, 0x7c, 0xda, 0x3c, 0xe7, 0x2f, 0xa3,
- 0xd0, 0xc3, 0x95, 0xf2, 0x28, 0x58, 0x71, 0xe4, 0x8b, 0xfe, 0xec, 0x0a,
- 0xfe, 0xdb, 0xb5, 0x9c, 0xbf, 0x38, 0x40, 0xea, 0x1c, 0xa9, 0x1f, 0x23,
- 0x67, 0x97, 0xc2, 0x90, 0xa9, 0xcb, 0xca, 0x47, 0xe7, 0x2a, 0x73, 0x7e,
- 0xc2, 0x1b, 0xf2, 0xe3, 0xb0, 0xc2, 0x97, 0xe1, 0x71, 0x1c, 0x29, 0x76,
- 0x2c, 0xa5, 0xcd, 0xb6, 0x52, 0xb0, 0xfe, 0xb6, 0x4f, 0xe2, 0x46, 0xc5,
- 0xaf, 0xf0, 0xa9, 0x1f, 0xf7, 0x38, 0x0a, 0x73, 0x37, 0x97, 0xff, 0xa7,
- 0x0e, 0x9d, 0x63, 0x9c, 0x74, 0x9b, 0x39, 0x50, 0xa9, 0x93, 0x21, 0x2a,
- 0x8c, 0x4f, 0x0d, 0x80, 0x24, 0xdf, 0xfd, 0x1f, 0xef, 0x30, 0x2e, 0x2e,
- 0xa9, 0xcb, 0xff, 0xf7, 0x53, 0x8a, 0x08, 0x77, 0x1a, 0x4c, 0xfb, 0x67,
- 0x2f, 0xe1, 0x8c, 0xd3, 0xfe, 0x72, 0xff, 0xd1, 0xae, 0xc2, 0x76, 0x05,
- 0x0e, 0x5d, 0x2d, 0xad, 0x17, 0xbe, 0x56, 0x6c, 0xb2, 0xff, 0x40, 0xe3,
- 0x13, 0xe9, 0x1c, 0xbf, 0xfe, 0xd8, 0xe7, 0xdf, 0xbe, 0xdf, 0x49, 0xf7,
- 0xe7, 0x2b, 0xe4, 0x60, 0xf8, 0xf5, 0xb3, 0x2a, 0xea, 0x7e, 0x6f, 0x1e,
- 0x0d, 0xee, 0x2a, 0x30, 0xe5, 0xfd, 0xb5, 0x02, 0x01, 0x91, 0xcb, 0xf9,
- 0x16, 0x1c, 0x7f, 0xce, 0x5f, 0xff, 0xbd, 0xbf, 0xb9, 0x07, 0x03, 0x0f,
- 0xac, 0x1f, 0xce, 0x5f, 0xff, 0xfb, 0x97, 0xa5, 0x9f, 0xb4, 0xce, 0x41,
- 0xc0, 0xc3, 0xeb, 0x07, 0xf2, 0x21, 0x7f, 0xf6, 0x7b, 0x92, 0xfa, 0x9d,
- 0xea, 0x7e, 0x68, 0x42, 0xd5, 0x24, 0x65, 0x6d, 0xda, 0xf4, 0x4f, 0xcf,
- 0x69, 0xa2, 0xfa, 0x32, 0x2b, 0xf3, 0x36, 0xdb, 0xfc, 0x72, 0xdb, 0x09,
- 0xf4, 0x28, 0x7d, 0x7f, 0x64, 0xd2, 0x4d, 0x6c, 0xe5, 0xfd, 0x1f, 0x29,
- 0xb8, 0xc3, 0x95, 0x0c, 0xd7, 0x60, 0xc3, 0xa3, 0x23, 0xa1, 0x49, 0x55,
- 0x3a, 0x96, 0x50, 0xf2, 0x91, 0x7f, 0x29, 0xe1, 0xc8, 0x04, 0xbf, 0x71,
- 0xed, 0x78, 0xa4, 0x05, 0xd7, 0x9b, 0x6d, 0xb2, 0x97, 0x9c, 0x42, 0x53,
- 0x99, 0xa0, 0xbe, 0xcd, 0x67, 0x8e, 0x57, 0xe7, 0x9d, 0xb2, 0xdb, 0xee,
- 0xa3, 0xc8, 0xe5, 0xfe, 0xf6, 0xd3, 0x5a, 0x46, 0x1c, 0xbc, 0xc9, 0xc2,
- 0x72, 0x84, 0xf4, 0x7c, 0x67, 0x7b, 0x92, 0xad, 0x0e, 0x5e, 0xf3, 0x84,
- 0xe5, 0x68, 0xdf, 0x6c, 0x8a, 0xfe, 0x5c, 0x7e, 0x9a, 0x54, 0xa5, 0xfc,
- 0xa6, 0x6b, 0x32, 0x63, 0x97, 0xe7, 0xef, 0x20, 0xc1, 0xca, 0x92, 0x73,
- 0x61, 0x23, 0xc7, 0x24, 0x5f, 0x12, 0x1d, 0x97, 0xf8, 0xba, 0xfc, 0xfa,
- 0xd6, 0x7c, 0x72, 0xff, 0xf7, 0xba, 0x8f, 0xfe, 0x68, 0x30, 0x32, 0x39,
- 0x7f, 0xfb, 0xee, 0x5f, 0x7f, 0x02, 0xb7, 0x9c, 0x5c, 0xe5, 0x42, 0x2f,
- 0xf0, 0xa0, 0x52, 0x6f, 0xd1, 0xb5, 0x06, 0x47, 0x2f, 0xb9, 0x2d, 0x24,
- 0x72, 0xff, 0xcb, 0xcd, 0x62, 0x6f, 0xb1, 0xc4, 0xe5, 0xff, 0xff, 0xce,
- 0x9e, 0x4e, 0xad, 0x39, 0x49, 0x3a, 0xe3, 0xe9, 0x66, 0xb0, 0xe5, 0xee,
- 0xe7, 0x01, 0xca, 0xea, 0x23, 0xdd, 0xc2, 0xff, 0x86, 0x3e, 0xdc, 0x7a,
- 0x02, 0x72, 0xf6, 0xd4, 0xdf, 0x23, 0xda, 0xc2, 0x2a, 0x0a, 0x70, 0x5f,
- 0x12, 0x7a, 0x32, 0x8b, 0xff, 0xff, 0xfe, 0x8d, 0xc7, 0xa7, 0xc6, 0xf5,
- 0x9d, 0x75, 0x37, 0x8a, 0xb8, 0xff, 0x03, 0x13, 0x76, 0x0e, 0x5f, 0xb7,
- 0xd7, 0x5c, 0x1c, 0xbf, 0x3c, 0xed, 0xbc, 0x8e, 0x50, 0xa3, 0x95, 0xb8,
- 0x4a, 0xa8, 0x4f, 0x7f, 0xff, 0xf2, 0x2b, 0xf4, 0xbd, 0x83, 0xed, 0xf2,
- 0xde, 0xf3, 0x58, 0x2f, 0x23, 0x97, 0xff, 0x73, 0x08, 0xc0, 0x17, 0x8a,
- 0xa6, 0x8e, 0x5d, 0x8d, 0x9c, 0xb6, 0x41, 0xee, 0xed, 0x1a, 0xfe, 0x9f,
- 0xaf, 0xed, 0x41, 0xcb, 0xfc, 0x1e, 0xc4, 0xce, 0xff, 0x1c, 0xbd, 0xdf,
- 0xf8, 0x9c, 0xad, 0x1e, 0xa7, 0x01, 0xa5, 0x49, 0x19, 0xba, 0x26, 0x78,
- 0x41, 0x5f, 0xfd, 0x9a, 0xfd, 0x89, 0xb5, 0x37, 0x18, 0x72, 0xfc, 0x1d,
- 0x47, 0xcd, 0x67, 0x2f, 0xff, 0xfd, 0xe8, 0xd7, 0xeb, 0xea, 0x49, 0x34,
- 0xff, 0xf8, 0x61, 0x9b, 0x39, 0x73, 0x5e, 0xce, 0x52, 0xa8, 0x87, 0x76,
- 0xda, 0x92, 0x63, 0x78, 0x8a, 0xf0, 0xb3, 0xbc, 0xd4, 0x8f, 0xe7, 0x2e,
- 0xc6, 0x1c, 0xbf, 0xfb, 0x07, 0xfe, 0x4a, 0x6b, 0xf6, 0x26, 0xce, 0x50,
- 0x4f, 0x7d, 0x82, 0xd7, 0xdf, 0xfb, 0x3f, 0x39, 0x7e, 0x8d, 0xed, 0x38,
- 0x9c, 0xa4, 0x3e, 0xfd, 0x11, 0x74, 0x92, 0xf3, 0x4f, 0xa0, 0xe5, 0xff,
- 0x2f, 0xa3, 0x1f, 0x24, 0x74, 0xe5, 0x43, 0x23, 0x86, 0x51, 0x90, 0x84,
- 0xb7, 0x23, 0xaa, 0x48, 0xc7, 0x74, 0x6c, 0xf1, 0xcf, 0x0c, 0x69, 0xfb,
- 0x34, 0x04, 0x3c, 0x1a, 0x17, 0x28, 0x3f, 0x7f, 0xe7, 0x40, 0x83, 0xdb,
- 0x9f, 0x1b, 0x39, 0x7e, 0xde, 0x2b, 0x1b, 0x39, 0x7f, 0x35, 0xed, 0x07,
- 0xe9, 0x1c, 0xbf, 0xf3, 0xe9, 0xa2, 0x77, 0x1f, 0xef, 0xce, 0x5f, 0xff,
- 0x93, 0xd0, 0xcc, 0xfb, 0xd0, 0xc5, 0x34, 0xff, 0x9c, 0xbe, 0x41, 0x70,
- 0x9c, 0xbf, 0xed, 0xc6, 0xbd, 0x1c, 0xc2, 0x87, 0x2a, 0x48, 0xb1, 0x0a,
- 0xbe, 0xc8, 0x2f, 0xff, 0xec, 0xef, 0x2c, 0x62, 0x76, 0x39, 0x6f, 0x78,
- 0x3f, 0x9c, 0xbf, 0xf9, 0x35, 0x12, 0xec, 0x4c, 0x20, 0x54, 0xe5, 0x75,
- 0x14, 0x7b, 0x5e, 0xb9, 0x6d, 0x0e, 0x5f, 0xca, 0xfa, 0x3b, 0x1b, 0x39,
- 0x7f, 0x75, 0x3e, 0xdb, 0xfc, 0x72, 0xa4, 0x7e, 0xc8, 0x33, 0xf9, 0x75,
- 0xff, 0xd8, 0xe3, 0x3b, 0x78, 0x21, 0xec, 0x1c, 0xbc, 0xb8, 0x6b, 0x39,
- 0x7f, 0xa6, 0xeb, 0xeb, 0x48, 0x13, 0x95, 0x87, 0xa6, 0xe3, 0xf7, 0xc9,
- 0xd7, 0x61, 0xcb, 0xfe, 0x11, 0xc9, 0xfd, 0xe8, 0x61, 0xca, 0x99, 0x30,
- 0xf1, 0x84, 0xb7, 0x88, 0x14, 0x21, 0xbf, 0x6b, 0x36, 0x8d, 0x9c, 0xbd,
- 0x0d, 0x45, 0xce, 0x5f, 0xca, 0x40, 0x16, 0x06, 0x1c, 0xb9, 0x04, 0xe5,
- 0xf4, 0xa0, 0x56, 0x72, 0x82, 0x6d, 0xb0, 0x56, 0xfe, 0x8f, 0x70, 0x8f,
- 0x1f, 0x1c, 0xae, 0x47, 0xa4, 0x84, 0x17, 0xd1, 0xfe, 0x09, 0xca, 0x92,
- 0xeb, 0xee, 0x14, 0x2c, 0xc5, 0x21, 0xe5, 0x34, 0x34, 0xf5, 0x09, 0x96,
- 0x46, 0x7c, 0xe8, 0x9b, 0x28, 0x01, 0x0b, 0x70, 0xb7, 0x68, 0x47, 0x7c,
- 0xce, 0x14, 0xd4, 0x5a, 0xb3, 0x97, 0x7b, 0x67, 0x29, 0x0f, 0x2e, 0x63,
- 0x4b, 0xe5, 0x21, 0xbd, 0x9c, 0xbb, 0xff, 0x1c, 0xbb, 0xfe, 0x9c, 0xbe,
- 0xd6, 0xb3, 0x67, 0x2e, 0xc9, 0x8e, 0x5a, 0x5c, 0x91, 0x1b, 0x39, 0x23,
- 0x06, 0x1c, 0x61, 0x42, 0x2b, 0xf2, 0x79, 0xc7, 0x0e, 0x5f, 0xb4, 0x1c,
- 0xc1, 0x39, 0x7f, 0xf3, 0x5a, 0x67, 0x63, 0x8e, 0xfb, 0x1f, 0x1c, 0xbf,
- 0xbe, 0xd0, 0x3e, 0xf4, 0x8e, 0x53, 0xa2, 0x83, 0x64, 0xc0, 0x49, 0xbf,
- 0x37, 0xef, 0x64, 0xe7, 0x2f, 0xfb, 0x07, 0x59, 0xbc, 0x4e, 0x9c, 0xbf,
- 0xfe, 0x97, 0x87, 0x1f, 0xc3, 0x9e, 0xf6, 0x36, 0x72, 0xec, 0xe2, 0x72,
- 0xff, 0x97, 0xdc, 0x0b, 0x13, 0x58, 0x72, 0xa7, 0x3d, 0x0c, 0x18, 0xbf,
- 0xa2, 0x35, 0xd8, 0xe2, 0x72, 0xff, 0xf7, 0xb7, 0x93, 0x76, 0x38, 0xe7,
- 0x7b, 0x07, 0x2f, 0xee, 0x85, 0x38, 0xc0, 0x4e, 0x56, 0x1f, 0xdb, 0xa6,
- 0x5f, 0x6d, 0x33, 0xf3, 0x97, 0xd9, 0xe4, 0xd9, 0xcb, 0xf9, 0xa9, 0x98,
- 0x5a, 0xb9, 0xc0, 0x72, 0xb6, 0x7b, 0x7e, 0x21, 0xbf, 0xf0, 0x1d, 0x9b,
- 0x41, 0x7d, 0x2a, 0x72, 0xa4, 0xae, 0xe8, 0x30, 0xc5, 0xc2, 0xf5, 0x95,
- 0x7c, 0x6d, 0xa8, 0x4f, 0x74, 0x88, 0x61, 0x53, 0xb2, 0x0f, 0x3e, 0xb6,
- 0x45, 0x7f, 0xfe, 0xf2, 0x6e, 0x7c, 0x6f, 0x69, 0x38, 0xbf, 0xde, 0x39,
- 0x79, 0xbc, 0xe9, 0xcb, 0xfd, 0xb4, 0x57, 0xae, 0x28, 0x72, 0xfd, 0x38,
- 0x45, 0xd5, 0x39, 0x7c, 0x9b, 0xc0, 0xe2, 0x34, 0x1d, 0x63, 0xc3, 0xaa,
- 0x19, 0x5f, 0xf9, 0xda, 0xff, 0x06, 0xd0, 0x7e, 0x91, 0xcb, 0xfc, 0x1c,
- 0x14, 0x6f, 0xa0, 0x39, 0x7f, 0xfd, 0xd4, 0x8f, 0x27, 0xf1, 0x2e, 0x6d,
- 0xb6, 0xd9, 0x4b, 0xff, 0x92, 0x3d, 0xfc, 0x4b, 0x9b, 0x6d, 0xb6, 0x52,
- 0xb1, 0x13, 0xfd, 0x55, 0xa9, 0xd1, 0xe9, 0xe8, 0x69, 0x5f, 0xee, 0x81,
- 0xd8, 0x17, 0x61, 0xca, 0x13, 0xdc, 0xf1, 0x4d, 0xf0, 0x73, 0x15, 0x29,
- 0x7c, 0xff, 0xbf, 0x8e, 0x5f, 0xf6, 0x9d, 0x7c, 0xbb, 0x0a, 0x09, 0xcb,
- 0xc0, 0x8d, 0x1c, 0xbb, 0xdb, 0x09, 0xeb, 0xcc, 0x77, 0x7a, 0x42, 0x03,
- 0x44, 0x32, 0xbd, 0xd8, 0x9c, 0xe5, 0xfb, 0xd1, 0x25, 0x58, 0x72, 0xf3,
- 0x6d, 0xb6, 0x52, 0xf6, 0x0a, 0xca, 0x73, 0x34, 0x17, 0xfe, 0xc9, 0xf0,
- 0x2f, 0x21, 0x89, 0xce, 0x54, 0x22, 0xd3, 0xf4, 0x91, 0x2d, 0xbe, 0x71,
- 0x6a, 0x1c, 0x31, 0xcb, 0x9a, 0x83, 0x50, 0x39, 0x7e, 0xcf, 0x78, 0x13,
- 0x9c, 0xb4, 0x9a, 0x81, 0xe6, 0x09, 0x1d, 0xe7, 0x6b, 0x83, 0x97, 0xec,
- 0x0f, 0x5d, 0xac, 0xe5, 0xf8, 0x70, 0x30, 0xc3, 0x95, 0x0a, 0xc9, 0xe7,
- 0x21, 0x09, 0x16, 0x3c, 0xfc, 0x5f, 0x31, 0x4e, 0xa1, 0xa3, 0xd2, 0xf7,
- 0x78, 0x01, 0x6f, 0x11, 0xe6, 0xca, 0xaf, 0xe6, 0x62, 0x6a, 0x69, 0x1c,
- 0xbf, 0xfe, 0x55, 0x47, 0x1e, 0xbc, 0xb7, 0x8c, 0x86, 0xb3, 0x95, 0x08,
- 0x81, 0x42, 0xeb, 0xde, 0x48, 0x39, 0x76, 0x09, 0xca, 0x43, 0x60, 0x01,
- 0xbb, 0xf0, 0xc7, 0xd1, 0xb3, 0x97, 0xfe, 0xc4, 0x17, 0xf6, 0xdb, 0x81,
- 0x39, 0x7b, 0xaf, 0xa8, 0x3e, 0x3d, 0x93, 0xdf, 0x26, 0xa3, 0xc7, 0x2f,
- 0xb7, 0x91, 0x23, 0x94, 0x13, 0xc2, 0x12, 0x1b, 0xf4, 0x4b, 0xb9, 0xf1,
- 0xcb, 0xbe, 0xfc, 0xe5, 0xfc, 0xc8, 0xdf, 0xe8, 0xb3, 0x97, 0xb7, 0x0a,
- 0xfe, 0x78, 0xfb, 0x19, 0xbf, 0xc0, 0xcd, 0x7f, 0xfa, 0x09, 0xcb, 0xce,
- 0xd5, 0xce, 0x72, 0xff, 0xd8, 0xc4, 0x0e, 0xb0, 0x2e, 0xc3, 0x97, 0xd8,
- 0xc5, 0x02, 0x72, 0xba, 0x7c, 0x02, 0x7b, 0x7f, 0xf9, 0x03, 0xd5, 0x37,
- 0x9a, 0x5b, 0xba, 0xcd, 0x10, 0x62, 0xff, 0xdd, 0x03, 0xab, 0x9e, 0xf6,
- 0x74, 0xe5, 0xff, 0xb7, 0xfb, 0xfd, 0xb5, 0x35, 0xd7, 0x39, 0x7c, 0x0e,
- 0xe2, 0xce, 0x54, 0x91, 0xf4, 0x15, 0x7f, 0x1f, 0xb4, 0x42, 0xbf, 0xed,
- 0xee, 0x35, 0x25, 0xa4, 0xe7, 0x2f, 0xe0, 0x2a, 0x39, 0x38, 0x0e, 0x54,
- 0x1f, 0x4f, 0x4e, 0xaf, 0x74, 0x0d, 0x67, 0x2f, 0xff, 0x69, 0xf8, 0xe0,
- 0xaf, 0xa9, 0xfa, 0x9e, 0x39, 0x50, 0x99, 0xb4, 0xa1, 0x51, 0xc3, 0x90,
- 0x80, 0x82, 0xbe, 0x57, 0x07, 0xd3, 0x51, 0x34, 0xdc, 0x20, 0xbd, 0x29,
- 0x46, 0xfd, 0xe4, 0x5a, 0x04, 0xe5, 0xfe, 0xd0, 0x1d, 0x40, 0x3a, 0x87,
- 0x2e, 0xe3, 0x87, 0x2b, 0x0f, 0x35, 0xcd, 0x6e, 0xff, 0xf3, 0x97, 0xfc,
- 0xbe, 0xa6, 0x85, 0x3d, 0xb3, 0x94, 0xc3, 0xd1, 0xfc, 0x66, 0xff, 0x7e,
- 0x9d, 0xee, 0x7e, 0xe7, 0x2f, 0xff, 0xf9, 0x99, 0xef, 0x3e, 0x86, 0x3e,
- 0x92, 0x9a, 0xfd, 0x89, 0xb3, 0x97, 0xfc, 0xc4, 0x6f, 0x04, 0x3d, 0x83,
- 0x97, 0x74, 0x07, 0x2f, 0xff, 0xd2, 0x41, 0x0f, 0x73, 0xe5, 0x1c, 0x7c,
- 0x21, 0x39, 0x79, 0x1b, 0x6b, 0x39, 0x7f, 0xb3, 0x8e, 0xfd, 0xe8, 0x61,
- 0xca, 0xd1, 0xea, 0xf4, 0x82, 0xa1, 0x38, 0x4c, 0x69, 0x43, 0x89, 0x85,
- 0xf7, 0x0a, 0xab, 0xf9, 0x18, 0xbc, 0x15, 0x9c, 0xbf, 0xb3, 0x6d, 0x33,
- 0x50, 0x72, 0xb4, 0x7b, 0x4d, 0x0b, 0x2a, 0x4c, 0x8e, 0xe0, 0xc2, 0x0f,
- 0x1d, 0x16, 0x42, 0x92, 0xfc, 0xa6, 0x58, 0x63, 0xa3, 0xb8, 0xfe, 0x47,
- 0xb8, 0xee, 0x3d, 0x0a, 0x8b, 0xfd, 0xbd, 0xe0, 0xfe, 0xd3, 0x0e, 0x5f,
- 0x0a, 0x70, 0x41, 0xcb, 0xe5, 0x07, 0x36, 0x72, 0xd3, 0x1c, 0xbf, 0xb7,
- 0x83, 0xfb, 0x4c, 0x39, 0x5c, 0x91, 0x77, 0x86, 0xae, 0x47, 0xf9, 0x16,
- 0xc4, 0xaf, 0xbc, 0xee, 0x27, 0x2b, 0x89, 0xf5, 0xb6, 0x97, 0x7f, 0xc0,
- 0xf7, 0xe0, 0x64, 0x67, 0x8e, 0x5f, 0xfe, 0x19, 0xf9, 0x4c, 0x83, 0x81,
- 0xc1, 0x54, 0xe5, 0xfc, 0x9f, 0x70, 0x76, 0x3c, 0x72, 0xf2, 0x99, 0x07,
- 0x2f, 0xfb, 0xb8, 0x1d, 0x3a, 0xfd, 0xf9, 0xca, 0x84, 0x69, 0xb5, 0xa6,
- 0x39, 0x8e, 0xc7, 0x2f, 0xff, 0xf6, 0x0b, 0xfb, 0x79, 0xaf, 0xff, 0x8c,
- 0xfb, 0xdb, 0x43, 0x97, 0x63, 0x43, 0x96, 0x70, 0x9f, 0xcf, 0x98, 0x6f,
- 0x46, 0xa6, 0x39, 0x5c, 0x9d, 0x04, 0x04, 0x4e, 0xde, 0xcf, 0x18, 0x70,
- 0x61, 0x5f, 0x93, 0x81, 0xab, 0x8d, 0xe7, 0xe5, 0x24, 0x9c, 0xba, 0xec,
- 0x66, 0x0f, 0x49, 0x3f, 0xfe, 0x3d, 0x81, 0x25, 0x04, 0x61, 0xad, 0xc2,
- 0xdd, 0xa1, 0x3d, 0xef, 0xa7, 0xe2, 0x72, 0xfc, 0xbe, 0xc7, 0xdc, 0x07,
- 0x2f, 0xdd, 0x7d, 0x31, 0x0e, 0x5f, 0xca, 0x2f, 0xb1, 0xf7, 0x01, 0xca,
- 0xe4, 0x88, 0x65, 0x96, 0x00, 0x9e, 0xf7, 0x2f, 0xdb, 0x39, 0x5f, 0x1e,
- 0x9f, 0x8c, 0xaf, 0xec, 0x6f, 0x30, 0x55, 0x39, 0x7c, 0xc7, 0xcd, 0x9c,
- 0xa4, 0x3c, 0xe7, 0x2d, 0xbf, 0xfe, 0x5c, 0x6f, 0x70, 0xcc, 0xf2, 0x6f,
- 0xae, 0x72, 0xff, 0x08, 0xc4, 0x99, 0x08, 0x72, 0xff, 0x79, 0x38, 0xa7,
- 0xa5, 0x05, 0x2c, 0xc3, 0x97, 0xf6, 0x0a, 0xba, 0x8e, 0x68, 0x78, 0xaa,
- 0x1a, 0x56, 0x26, 0x12, 0x89, 0xdb, 0x75, 0xbc, 0x0f, 0xa4, 0x72, 0xfa,
- 0x5a, 0x7e, 0x27, 0x2b, 0x47, 0x84, 0x23, 0xd7, 0xf8, 0x64, 0x38, 0xc8,
- 0x59, 0xcb, 0xcf, 0xb4, 0x39, 0x6c, 0x39, 0x7b, 0x31, 0x53, 0x96, 0x60,
- 0x4d, 0x67, 0x00, 0x85, 0x42, 0x30, 0xf0, 0x87, 0xa6, 0x2e, 0x8f, 0x7f,
- 0xc9, 0xc7, 0x34, 0xb7, 0x75, 0x9a, 0x30, 0xd5, 0xe6, 0x80, 0xf1, 0xcb,
- 0x93, 0x89, 0xcb, 0xe7, 0xd3, 0xa8, 0x72, 0xff, 0xf7, 0xa1, 0x88, 0x1c,
- 0x15, 0x7b, 0x0c, 0x39, 0x41, 0x47, 0x42, 0xd1, 0x98, 0x3f, 0xb1, 0x8f,
- 0x11, 0x5e, 0x55, 0x4e, 0x9c, 0xbf, 0xfe, 0x4f, 0x76, 0x37, 0x1d, 0x84,
- 0x9e, 0x15, 0x39, 0x7f, 0xbb, 0x13, 0x49, 0x35, 0x23, 0x97, 0xfb, 0xc8,
- 0xdc, 0xc2, 0xed, 0x9c, 0xbf, 0x7b, 0xdb, 0x7f, 0xce, 0x5f, 0xa1, 0x9e,
- 0xc5, 0x9c, 0xb9, 0x27, 0x39, 0x50, 0x98, 0xf8, 0x53, 0xfe, 0x34, 0x43,
- 0x5e, 0x94, 0xf8, 0x9e, 0xfc, 0xda, 0x07, 0x81, 0x0e, 0x5f, 0xf7, 0x62,
- 0x48, 0x38, 0xc8, 0x39, 0x7f, 0xd9, 0xee, 0xe3, 0x05, 0xfc, 0x72, 0xfe,
- 0xe2, 0x9a, 0xfa, 0x1a, 0xce, 0x58, 0x42, 0x7d, 0x58, 0x6f, 0x7e, 0x64,
- 0x2e, 0x70, 0x9c, 0xbe, 0x94, 0x31, 0xce, 0x5f, 0xb5, 0xfb, 0x13, 0x67,
- 0x2e, 0xf6, 0xf0, 0xfc, 0xdc, 0xa5, 0x42, 0x1a, 0x84, 0x69, 0x82, 0x13,
- 0x36, 0xd9, 0xcb, 0xfa, 0x27, 0xc1, 0x45, 0x4e, 0x56, 0x8d, 0xf6, 0xc4,
- 0x6f, 0xfe, 0x81, 0x7e, 0xc7, 0xfc, 0xf5, 0xbd, 0x94, 0xa9, 0xd5, 0x1f,
- 0x86, 0x37, 0x3c, 0x65, 0x61, 0x0d, 0xf9, 0xe6, 0x4c, 0xd9, 0xcb, 0xed,
- 0xc6, 0xa4, 0x72, 0xe7, 0x0f, 0x23, 0xc9, 0xd9, 0x3d, 0xc0, 0x9c, 0xe5,
- 0xfe, 0xfa, 0x5f, 0x6d, 0x3d, 0x07, 0x2f, 0x27, 0xdb, 0x39, 0x58, 0x7a,
- 0x48, 0x6b, 0x48, 0x88, 0xae, 0xb5, 0x5d, 0x8b, 0x39, 0x7b, 0x59, 0xb3,
- 0x9e, 0x2d, 0xaf, 0xff, 0x83, 0xc9, 0xd3, 0x37, 0x13, 0xe0, 0xa2, 0xa7,
- 0x2f, 0xf6, 0x99, 0x1f, 0x79, 0xd6, 0x72, 0xff, 0xfe, 0x1c, 0xf7, 0x72,
- 0x58, 0xb8, 0x5f, 0x85, 0xd8, 0x72, 0xb1, 0x1b, 0x88, 0xa1, 0xb3, 0x4b,
- 0xe4, 0x64, 0x4c, 0x72, 0xff, 0xed, 0xa7, 0xc3, 0x93, 0x6a, 0x3d, 0xb3,
- 0x97, 0xd9, 0x38, 0x24, 0x72, 0xa6, 0x44, 0x57, 0xe4, 0x4d, 0xa2, 0xdf,
- 0xed, 0xc4, 0x9e, 0x77, 0x61, 0xcb, 0xfb, 0xf9, 0xde, 0x50, 0xd6, 0x72,
- 0xf0, 0x43, 0x07, 0x2b, 0xe3, 0xce, 0x01, 0x95, 0x42, 0x35, 0xd0, 0xcd,
- 0xe1, 0x03, 0x76, 0x36, 0x72, 0x8b, 0x88, 0x61, 0x7f, 0x6d, 0x48, 0xd4,
- 0x30, 0xb8, 0x86, 0x14, 0x5c, 0x43, 0x0a, 0x2e, 0x21, 0x85, 0x17, 0x10,
- 0xc2, 0x8b, 0x88, 0x61, 0x52, 0x45, 0xca, 0x0c, 0xfe, 0x78, 0x01, 0x96,
- 0x83, 0x3c, 0x03, 0x37, 0x77, 0x0b, 0x88, 0x61, 0x7f, 0x3b, 0xfa, 0x68,
- 0x61, 0x71, 0x0c, 0x39, 0x1a, 0x4b, 0x70, 0xe5, 0xc4, 0x30, 0xa2, 0xe2,
- 0x18, 0x51, 0x71, 0x0c, 0x2a, 0x46, 0xc9, 0x06, 0x68, 0xb8, 0x86, 0x14,
- 0x5c, 0x43, 0x0a, 0x2e, 0x21, 0x85, 0x17, 0x10, 0xc2, 0x8b, 0x88, 0x61,
- 0x45, 0xc4, 0x30, 0xa9, 0xd1, 0x2c, 0x11, 0x94, 0x19, 0xfc, 0x67, 0x63,
- 0x3c, 0x46, 0x68, 0xb8, 0x86, 0x14, 0x5c, 0x43, 0x0a, 0x91, 0xb2, 0xd8,
- 0xcd, 0x17, 0x10, 0xc2, 0x8b, 0x88, 0x61, 0x45, 0xc4, 0x30, 0xa2, 0xe2,
- 0x18, 0x54, 0x8f, 0x93, 0xf1, 0x9f, 0x0c, 0xf0, 0x0c, 0xd1, 0x71, 0x0c,
- 0x28, 0xb8, 0x86, 0x14, 0x5c, 0x43, 0x0a, 0x2e, 0x21, 0x85, 0x4e, 0x7c,
- 0x8a, 0x8c, 0xe8, 0x67, 0xa3, 0x36, 0x54, 0xb8, 0x86, 0x14, 0x5c, 0x43,
- 0x0a, 0x2e, 0x21, 0x85, 0x17, 0x10, 0xc2, 0x8b, 0x88, 0x61, 0x41, 0x3e,
- 0x4f, 0x86, 0x7f, 0x19, 0x00, 0xcd, 0x17, 0x10, 0xc2, 0x8b, 0x88, 0x61,
- 0x45, 0xc4, 0x30, 0xbf, 0x76, 0x3f, 0xde, 0x17, 0x10, 0xc2, 0x8b, 0x88,
- 0x61, 0x52, 0x44, 0xd2, 0xc6, 0x7a, 0x32, 0xe3, 0x3f, 0x9b, 0x59, 0x65,
- 0xc4, 0x30, 0xa2, 0xe2, 0x18, 0x51, 0x71, 0x0c, 0x28, 0xb8, 0x86, 0x14,
- 0x5c, 0x43, 0x0a, 0x91, 0xf2, 0x7c, 0x32, 0x83, 0x3c, 0x46, 0x68, 0xb8,
- 0x86, 0x14, 0x5c, 0x43, 0x0a, 0x2e, 0x21, 0x85, 0x17, 0x10, 0xc2, 0xa4,
- 0x7c, 0x81, 0x19, 0xe8, 0xc8, 0x8c, 0xdb, 0xa5, 0xc4, 0x30, 0xa2, 0xe2,
- 0x18, 0x51, 0x71, 0x0c, 0x2d, 0x22, 0xe2, 0x18, 0x51, 0x71, 0x0c, 0x3e,
- 0x2f, 0xe8, 0xb8, 0x86, 0x14, 0x5c, 0x43, 0x0a, 0x2e, 0x21, 0x85, 0x17,
- 0x10, 0xc2, 0xa7, 0x46, 0xf4, 0x86, 0x55, 0x38, 0x59, 0x4c, 0xc3, 0x3f,
- 0x8c, 0xf8, 0x66, 0xd8, 0x5c, 0x43, 0x0a, 0x2e, 0x21, 0x85, 0x17, 0x10,
- 0xc2, 0xd2, 0x2e, 0x21, 0x85, 0x17, 0x10, 0xc3, 0xe2, 0xfe, 0x8b, 0x88,
- 0x61, 0x45, 0xc4, 0x30, 0xa8, 0x45, 0x64, 0x86, 0x50, 0xe3, 0x45, 0x2c,
- 0x19, 0xa2, 0xe2, 0x18, 0x51, 0x71, 0x0c, 0x28, 0xb8, 0x86, 0x14, 0x5c,
- 0x43, 0x0a, 0x2e, 0x21, 0x85, 0x41, 0xfe, 0xfc, 0x33, 0xa1, 0x96, 0x0c,
- 0x88, 0xcd, 0x17, 0x10, 0xc2, 0x8b, 0x88, 0x61, 0x45, 0xc4, 0x30, 0xad,
- 0x1e, 0x5e, 0xc6, 0x7c, 0x33, 0x45, 0xc4, 0x30, 0xa2, 0xe2, 0x18, 0x51,
- 0x71, 0x0c, 0x29, 0x87, 0x96, 0x23, 0x3e, 0x19, 0xb3, 0x0b, 0x88, 0x61,
- 0x45, 0xc4, 0x30, 0xa2, 0xe2, 0x18, 0x57, 0xe6, 0xc8, 0x03, 0x34, 0x5c,
- 0x43, 0x0a, 0x2e, 0x21, 0x85, 0x17, 0x10, 0xc2, 0x8b, 0x88, 0x61, 0x50,
- 0x7c, 0x93, 0x0c, 0xf4, 0x64, 0x03, 0x35, 0x0c, 0xc1, 0x49, 0xe1, 0x01,
- 0x24, 0xd0, 0xab, 0x64, 0x2d, 0x97, 0x08, 0xcf, 0xa1, 0x0a, 0x90, 0xa4,
- 0x6b, 0x3e, 0x9a, 0x10, 0x9a, 0x86, 0xc3, 0x12, 0xbb, 0x08, 0x37, 0x85,
- 0x17, 0xe7, 0x63, 0x0f, 0xdd, 0xb4, 0x7a, 0x19, 0x40, 0x86, 0x2f, 0x18,
- 0x49, 0xb6, 0xf4, 0xd0, 0xb9, 0x45, 0x1e, 0x08, 0x43, 0x5f, 0xa4, 0x31,
- 0x9b, 0x2e, 0x21, 0x87, 0x34, 0xe5, 0xaf, 0x24, 0x30, 0xb8, 0x86, 0x17,
- 0xc8, 0xb7, 0xd1, 0xf1, 0x0c, 0x5e, 0x40, 0xe1, 0xf1, 0x0c, 0x5b, 0x9f,
- 0xc8, 0xc8, 0xd2, 0x4f, 0x4a, 0x7c, 0x5d, 0x68, 0xe2, 0xcf, 0x88, 0x52,
- 0x9e, 0x85, 0x7f, 0xba, 0x8d, 0x87, 0x51, 0x39, 0xcb, 0xc9, 0xc7, 0x87,
- 0x39, 0x5f, 0x22, 0x42, 0x63, 0x8f, 0x1a, 0xdf, 0xb3, 0x26, 0x75, 0x0e,
- 0x5f, 0xe7, 0x15, 0x26, 0x92, 0x09, 0xcb, 0xbf, 0x83, 0x97, 0xf6, 0x9c,
- 0x54, 0x8f, 0xce, 0x5c, 0xfa, 0x39, 0x64, 0x38, 0xb2, 0xda, 0xcb, 0x39,
- 0x66, 0x1c, 0xb7, 0x34, 0x44, 0xe6, 0x85, 0xfa, 0x88, 0xe3, 0xea, 0x08,
- 0xd3, 0x13, 0x20, 0x69, 0x0c, 0xfb, 0xfe, 0xec, 0x33, 0x26, 0x81, 0x9c,
- 0xe5, 0xff, 0xdc, 0x9d, 0x61, 0xec, 0x7f, 0x83, 0xf9, 0xcb, 0xbf, 0x83,
- 0x95, 0x87, 0xbd, 0xfa, 0x3d, 0x62, 0x39, 0x3f, 0x2b, 0x04, 0x25, 0xef,
- 0xfe, 0x11, 0x89, 0xc7, 0x13, 0x8c, 0x34, 0x39, 0x7a, 0x3e, 0xd9, 0xca,
- 0x73, 0xe2, 0xda, 0x2d, 0xe7, 0xd4, 0x1c, 0xbf, 0x23, 0x47, 0x1f, 0xce,
- 0x5f, 0x93, 0xed, 0xbf, 0xc7, 0x2a, 0x47, 0xda, 0xc1, 0xbd, 0x94, 0xdf,
- 0xf2, 0x8e, 0x1d, 0xe3, 0x21, 0xac, 0xe5, 0xec, 0xf9, 0xb3, 0x97, 0xbe,
- 0xff, 0x34, 0x7b, 0x42, 0x79, 0x7d, 0xc7, 0x35, 0x23, 0x97, 0x82, 0xe2,
- 0x72, 0x90, 0xdf, 0xb9, 0x25, 0xff, 0xcf, 0xad, 0x3f, 0xf1, 0xcd, 0xb6,
- 0xdb, 0x39, 0x7f, 0xe5, 0x73, 0xef, 0x27, 0xb4, 0x06, 0x1c, 0xb4, 0x72,
- 0x44, 0x5f, 0x92, 0xaa, 0x13, 0xd0, 0x78, 0x44, 0xed, 0xcc, 0x10, 0xaa,
- 0xbf, 0xf8, 0x0a, 0x4d, 0xca, 0x14, 0x75, 0xc7, 0x4e, 0x57, 0x08, 0xe8,
- 0xdd, 0x22, 0x1f, 0x53, 0xb8, 0xca, 0x32, 0x90, 0xc6, 0x69, 0x91, 0x91,
- 0x2a, 0x94, 0xb8, 0xcf, 0xbe, 0x57, 0x49, 0x4d, 0x4d, 0x70, 0x8e, 0x9a,
- 0x17, 0x3a, 0x38, 0x64, 0x60, 0xfd, 0x8e, 0x3d, 0xeb, 0x04, 0xaf, 0xcc,
- 0x86, 0x51, 0x66, 0xe1, 0x2f, 0xe9, 0x4b, 0xca, 0x23, 0x5e, 0x66, 0xd6,
- 0x72, 0xf0, 0xae, 0x0e, 0x57, 0x23, 0x70, 0x83, 0xb7, 0xf3, 0x6f, 0xad,
- 0x3f, 0xc7, 0x2f, 0xff, 0xdb, 0xd6, 0x92, 0x6d, 0xea, 0x3c, 0x8b, 0x40,
- 0x9c, 0xa6, 0x22, 0x9c, 0x48, 0x9b, 0x2f, 0xbe, 0x67, 0xa3, 0x67, 0x2f,
- 0xdf, 0xa4, 0xe8, 0x13, 0x97, 0xda, 0x41, 0x54, 0xe5, 0xfe, 0xf4, 0x01,
- 0x7d, 0x4d, 0x1c, 0xbf, 0xb1, 0x7d, 0x8f, 0xa4, 0x72, 0xfe, 0x66, 0xd1,
- 0x5f, 0x36, 0x72, 0xfd, 0x1f, 0x76, 0x24, 0x72, 0xb4, 0x8d, 0xb1, 0x22,
- 0xf1, 0x9a, 0x85, 0xdc, 0x06, 0x17, 0xfd, 0x9f, 0x0e, 0x7b, 0xd9, 0x39,
- 0xcb, 0xbe, 0xf1, 0xcb, 0xf6, 0x0c, 0xe9, 0xa3, 0x97, 0xef, 0x38, 0x83,
- 0x0e, 0x5f, 0xed, 0xe3, 0x13, 0xdd, 0x73, 0x96, 0x8c, 0x44, 0xbe, 0x86,
- 0x04, 0x9f, 0xc4, 0xd7, 0xb9, 0x31, 0x0e, 0x5c, 0x2c, 0x39, 0x52, 0x36,
- 0x9b, 0x1e, 0xbd, 0xc1, 0xa8, 0x39, 0x7f, 0xdd, 0x4d, 0x75, 0xf8, 0x46,
- 0xdb, 0x39, 0x7f, 0xb4, 0x93, 0x0e, 0x71, 0x73, 0x96, 0xdf, 0x24, 0x5a,
- 0x41, 0x0e, 0x0f, 0xe9, 0x02, 0xf9, 0xc4, 0x18, 0x72, 0xbe, 0x3e, 0x3f,
- 0xd0, 0xef, 0xf8, 0x61, 0xe7, 0xec, 0x6b, 0xf3, 0x97, 0xf9, 0x34, 0x3e,
- 0xf6, 0x4e, 0x72, 0xe7, 0xe2, 0x72, 0xfe, 0x90, 0xa4, 0xbb, 0x87, 0x2f,
- 0xd3, 0xa6, 0xa2, 0x47, 0x29, 0x54, 0x4f, 0xcc, 0x67, 0xa1, 0x81, 0x2c,
- 0xbf, 0x03, 0xcd, 0x33, 0xc7, 0x2f, 0x05, 0x15, 0x39, 0x50, 0x78, 0xf8,
- 0x55, 0x7b, 0x5f, 0xa8, 0x72, 0xff, 0xe4, 0xf4, 0x7b, 0x7d, 0x74, 0xe8,
- 0x0e, 0x54, 0x1f, 0x13, 0x8f, 0xdf, 0x08, 0x82, 0x47, 0x2f, 0xfd, 0xd8,
- 0xd7, 0xe3, 0x8d, 0xbf, 0xe7, 0x2f, 0x66, 0x4c, 0x72, 0xd9, 0xd3, 0xdc,
- 0xfd, 0x02, 0xf4, 0x7c, 0xd9, 0xcb, 0xf6, 0x80, 0xc7, 0x13, 0x95, 0xe3,
- 0xc5, 0x00, 0xf5, 0xf3, 0x23, 0x27, 0x39, 0x7e, 0xce, 0x23, 0x1f, 0x1c,
- 0xa4, 0x3c, 0xbd, 0x91, 0x5f, 0x40, 0xf9, 0x67, 0x28, 0x2a, 0xe6, 0x32,
- 0x1b, 0x1a, 0x84, 0x2f, 0x61, 0x04, 0xe4, 0x02, 0xfb, 0xb6, 0xdf, 0x36,
- 0xb4, 0x21, 0xbf, 0xdf, 0xa9, 0x82, 0x1e, 0xc1, 0xca, 0x84, 0x61, 0x3c,
- 0x23, 0xaf, 0xed, 0xe3, 0x13, 0xb0, 0x72, 0xf7, 0xd2, 0xd9, 0xca, 0xf8,
- 0xf2, 0xb4, 0x59, 0x7b, 0x7f, 0xb6, 0x72, 0xff, 0xa4, 0xc7, 0x97, 0xb7,
- 0x0a, 0x9c, 0xa8, 0x3f, 0xcc, 0x23, 0x71, 0xfb, 0xff, 0x23, 0x63, 0x9a,
- 0xdf, 0x71, 0x67, 0x2f, 0x80, 0xfa, 0x91, 0xcb, 0xe8, 0x07, 0x0f, 0xb2,
- 0x97, 0xe9, 0x73, 0x6d, 0xb6, 0xce, 0x50, 0x9e, 0xa8, 0x09, 0xef, 0x9f,
- 0xcc, 0xf1, 0xca, 0x0a, 0x2e, 0xb1, 0xdf, 0xf2, 0x1b, 0xfd, 0xf8, 0xe7,
- 0x1d, 0x26, 0xce, 0x5f, 0xe5, 0x04, 0x5d, 0xb7, 0xe9, 0xca, 0x86, 0x59,
- 0x26, 0x18, 0x7c, 0x44, 0x91, 0x82, 0x69, 0x35, 0x90, 0xd0, 0x78, 0xe2,
- 0xff, 0x9c, 0x7e, 0x18, 0x76, 0x6c, 0xb0, 0x10, 0xf8, 0xe2, 0x60, 0xd9,
- 0xad, 0xe6, 0xa9, 0xa8, 0xf0, 0x87, 0x2f, 0x48, 0x5c, 0xe5, 0xbe, 0x6a,
- 0x8f, 0x22, 0x0b, 0x6f, 0xdc, 0x11, 0x2d, 0x41, 0xcb, 0xde, 0x7f, 0xce,
- 0x5f, 0xd1, 0xa9, 0xe3, 0x53, 0x9c, 0xbf, 0xf4, 0x0f, 0xba, 0x07, 0x94,
- 0xa0, 0xe5, 0xf8, 0x1f, 0xe0, 0xac, 0xe5, 0xed, 0x44, 0xc7, 0x2f, 0x90,
- 0x5e, 0x63, 0x97, 0xfe, 0x18, 0x57, 0xaf, 0xe5, 0x33, 0xf3, 0x97, 0xb7,
- 0xac, 0x39, 0x7f, 0x66, 0xbf, 0x10, 0x7e, 0x72, 0x90, 0xf2, 0xf6, 0x39,
- 0x66, 0xb3, 0x97, 0xf6, 0x29, 0x13, 0x26, 0xce, 0x50, 0x9e, 0x17, 0x85,
- 0x2a, 0x15, 0x14, 0x4e, 0x55, 0x21, 0xd0, 0x97, 0xe8, 0xf5, 0x85, 0x1d,
- 0x1d, 0x12, 0x1f, 0x42, 0x2f, 0x8b, 0x1d, 0xff, 0x42, 0x76, 0x19, 0x3e,
- 0x36, 0x72, 0xfd, 0xd4, 0x9d, 0xc4, 0xe5, 0xf8, 0x0a, 0xb8, 0xfe, 0x72,
- 0xfe, 0xde, 0xa3, 0x02, 0x87, 0x2a, 0x0f, 0xf3, 0xa4, 0xfc, 0x4a, 0x6f,
- 0xfa, 0x71, 0xc9, 0x77, 0x3f, 0xd9, 0xcb, 0xff, 0x60, 0xfd, 0x2d, 0xe8,
- 0x11, 0xf9, 0xcb, 0xf6, 0x7b, 0x78, 0xa9, 0xca, 0x43, 0xe8, 0x62, 0x05,
- 0xff, 0xb5, 0xd6, 0xdc, 0x3c, 0x7d, 0x8b, 0x39, 0x7e, 0xf7, 0x2e, 0xe7,
- 0x01, 0xca, 0x73, 0xef, 0x14, 0x2b, 0xc1, 0x8e, 0x27, 0x2f, 0xff, 0x08,
- 0xc3, 0x61, 0x18, 0xfa, 0x48, 0x27, 0x2f, 0xcc, 0xce, 0xbf, 0x01, 0xca,
- 0xc3, 0xf2, 0x44, 0x8b, 0xff, 0xcf, 0xca, 0x69, 0x46, 0xa7, 0xe4, 0xde,
- 0x74, 0xe5, 0x42, 0x64, 0x21, 0x20, 0xec, 0x24, 0x04, 0x82, 0xff, 0x99,
- 0xdc, 0xf6, 0x03, 0x53, 0x9c, 0xbf, 0xfb, 0xdb, 0x41, 0x9a, 0x17, 0xac,
- 0xf8, 0xe5, 0xf8, 0x2a, 0xaa, 0x0f, 0x8e, 0x59, 0x57, 0x3f, 0x10, 0x22,
- 0xdf, 0xf4, 0x7b, 0x34, 0xb7, 0x75, 0x9a, 0x2f, 0x85, 0xfb, 0x35, 0x1f,
- 0x48, 0xe5, 0xee, 0xc3, 0x16, 0x7d, 0x9e, 0x44, 0xbf, 0xff, 0x0a, 0xf9,
- 0x76, 0x13, 0x48, 0xc4, 0x69, 0x0c, 0x39, 0x79, 0xf5, 0x39, 0xa2, 0xff,
- 0x54, 0x22, 0xd3, 0x0c, 0xd6, 0xaf, 0x7f, 0xcf, 0xed, 0xa0, 0xfd, 0x26,
- 0x1c, 0xbf, 0xe8, 0xcd, 0x72, 0x92, 0x7d, 0x23, 0x95, 0xf9, 0xfa, 0x78,
- 0xe6, 0xff, 0xff, 0x75, 0xf6, 0x91, 0xbe, 0x5e, 0xee, 0x33, 0x16, 0xfa,
- 0x39, 0x74, 0x70, 0x1c, 0xbe, 0xde, 0xdd, 0x87, 0x2b, 0xa8, 0x9c, 0xfd,
- 0x87, 0xc3, 0x37, 0xfe, 0x9f, 0x3e, 0xf2, 0x9d, 0xee, 0x35, 0x9c, 0xbe,
- 0xfa, 0x5e, 0x73, 0x97, 0xff, 0xc1, 0x5f, 0x50, 0x73, 0x8b, 0xcb, 0x68,
- 0x13, 0x95, 0x87, 0xe6, 0xe4, 0x77, 0xef, 0xf7, 0xec, 0xe9, 0xcb, 0xf9,
- 0xbf, 0x67, 0x65, 0x87, 0x2a, 0x0f, 0x5d, 0xca, 0x6a, 0x13, 0x4f, 0x94,
- 0x2e, 0x05, 0xde, 0xff, 0xa1, 0x9c, 0x83, 0x99, 0xfe, 0xce, 0x5f, 0x23,
- 0x35, 0x39, 0xcb, 0xff, 0x7a, 0x37, 0xb8, 0x49, 0xdf, 0xc7, 0x2f, 0xf9,
- 0x30, 0x42, 0xaa, 0x66, 0x8e, 0x52, 0x23, 0x4f, 0x47, 0x7e, 0x23, 0xe0,
- 0x3e, 0xbd, 0xec, 0xf8, 0xe5, 0xfc, 0xfa, 0xfa, 0x59, 0xe3, 0x97, 0xfe,
- 0xf6, 0xd3, 0x5e, 0x10, 0x3c, 0x8e, 0x5f, 0xff, 0x93, 0x78, 0x1e, 0xe7,
- 0x93, 0x37, 0x3e, 0x36, 0x72, 0xff, 0xf3, 0x21, 0xa6, 0x00, 0x73, 0x38,
- 0xc7, 0xc7, 0x2f, 0xfd, 0x19, 0xac, 0xd7, 0xec, 0x4d, 0x9c, 0xbc, 0xff,
- 0x70, 0x1c, 0xbf, 0x9f, 0xdb, 0x8c, 0x9c, 0xe5, 0x42, 0x73, 0x18, 0x5c,
- 0xb3, 0xe4, 0x55, 0x14, 0xce, 0x27, 0xcd, 0x90, 0x5f, 0xf0, 0x21, 0x9b,
- 0xc6, 0x43, 0x59, 0xcb, 0xff, 0x6a, 0x7c, 0x0e, 0x77, 0xb8, 0xd6, 0x72,
- 0xca, 0x9c, 0xbf, 0xde, 0xda, 0x9c, 0x63, 0x3e, 0x39, 0x6c, 0x83, 0xc9,
- 0x11, 0x2a, 0xc4, 0x58, 0x6e, 0x11, 0x77, 0xf6, 0xde, 0x43, 0x0c, 0x39,
- 0x7f, 0xfd, 0x28, 0xd4, 0xfe, 0x45, 0x77, 0xb7, 0x19, 0x1c, 0xbf, 0xa7,
- 0xde, 0x32, 0x1a, 0xce, 0x54, 0xc8, 0x82, 0x51, 0x46, 0xb4, 0x8d, 0x36,
- 0xe1, 0x5d, 0x79, 0x3a, 0x87, 0x2e, 0x0c, 0x8e, 0x5e, 0x1c, 0x91, 0xcb,
- 0x4b, 0x46, 0xcb, 0xc2, 0xf7, 0xcc, 0xf2, 0x4e, 0x72, 0xb0, 0xf2, 0x90,
- 0x9e, 0xff, 0xee, 0x3e, 0x56, 0x06, 0x59, 0xd4, 0x61, 0xcb, 0xa7, 0xf1,
- 0xcb, 0xfd, 0xc7, 0xaf, 0x28, 0xc1, 0x39, 0x50, 0x79, 0x78, 0x31, 0x7f,
- 0xfe, 0x97, 0x63, 0x4f, 0xe0, 0x79, 0x3d, 0xbe, 0xa1, 0xcb, 0xfb, 0x1b,
- 0x53, 0xaf, 0xe3, 0x97, 0xf4, 0x99, 0xe1, 0x04, 0xc7, 0x2f, 0xff, 0x94,
- 0x94, 0x71, 0x41, 0xff, 0x49, 0x0c, 0xc2, 0x95, 0xa4, 0x40, 0x78, 0xbe,
- 0xfb, 0xaa, 0x7d, 0xe3, 0x97, 0xec, 0x66, 0x27, 0x13, 0x97, 0xa7, 0x99,
- 0xac, 0xe5, 0x42, 0x72, 0xd3, 0xaa, 0xe4, 0x2b, 0xd6, 0x46, 0x84, 0xa0,
- 0x28, 0xbb, 0xd8, 0x72, 0xfd, 0xa4, 0x9d, 0xd8, 0x69, 0x84, 0xd7, 0xde,
- 0x04, 0x39, 0xa6, 0x13, 0x5d, 0xfc, 0x1a, 0x81, 0x35, 0xfe, 0x17, 0x57,
- 0xd1, 0xaf, 0xcd, 0x40, 0x9a, 0xff, 0x6f, 0x3a, 0x9b, 0x04, 0xe6, 0x98,
- 0x4d, 0x76, 0x04, 0xd3, 0x09, 0xae, 0x6d, 0xb3, 0xcc, 0x26, 0xac, 0x4d,
- 0x4b, 0xe3, 0x54, 0x2e, 0x61, 0x26, 0xd0, 0x78, 0xa0, 0xb6, 0x47, 0x6f,
- 0x16, 0x61, 0x33, 0x99, 0xf3, 0xd9, 0x3e, 0x54, 0x02, 0xdc, 0x79, 0xf5,
- 0x0b, 0xb6, 0xa8, 0x53, 0xd8, 0x4b, 0xb9, 0x00, 0xc2, 0x47, 0x71, 0xdb,
- 0x7a, 0x52, 0xe5, 0xf3, 0xf1, 0xc6, 0xce, 0x5f, 0xff, 0xba, 0xf2, 0xec,
- 0x42, 0x7b, 0x68, 0x3f, 0x48, 0xe5, 0xe1, 0xfd, 0x87, 0x2f, 0xfa, 0x01,
- 0xe1, 0x4e, 0x2a, 0x30, 0xe5, 0xd9, 0xbc, 0x3d, 0x8d, 0x0e, 0xd6, 0x91,
- 0xf8, 0xe4, 0x83, 0x0a, 0xcb, 0xec, 0x4d, 0x2a, 0x72, 0xf0, 0x7f, 0x98,
- 0xe5, 0x43, 0x68, 0x97, 0x3c, 0x28, 0x83, 0x1d, 0x8e, 0x20, 0xab, 0x0a,
- 0xb5, 0xc6, 0x91, 0xf4, 0x28, 0x92, 0x17, 0xf3, 0x47, 0x01, 0xa8, 0xc1,
- 0xd8, 0x7f, 0xd8, 0xed, 0x45, 0x93, 0x70, 0xeb, 0xf4, 0xf5, 0x7f, 0x18,
- 0xdd, 0x9a, 0x19, 0xa8, 0x45, 0x7e, 0xef, 0xdb, 0x48, 0x39, 0x7d, 0x9a,
- 0x45, 0x4e, 0x54, 0x1e, 0x50, 0x4a, 0x2f, 0xee, 0xc2, 0x83, 0xf7, 0xe7,
- 0x2f, 0x35, 0x79, 0xc0, 0x72, 0xf6, 0x63, 0x67, 0x2e, 0x45, 0x4e, 0x54,
- 0xe6, 0xcd, 0x07, 0x2f, 0xde, 0xc9, 0x91, 0x87, 0x2f, 0xd1, 0xf7, 0xff,
- 0xc1, 0xca, 0x83, 0xd2, 0x12, 0x8b, 0xf4, 0x71, 0x81, 0xf1, 0xcb, 0xf2,
- 0x71, 0xf2, 0x4e, 0x72, 0xff, 0xcc, 0x14, 0x56, 0x3d, 0xb4, 0xd1, 0xcb,
- 0xe9, 0x7b, 0x16, 0x72, 0xb0, 0xf8, 0x1c, 0xfa, 0xfc, 0x38, 0xa6, 0x4c,
- 0x72, 0xff, 0xf8, 0x56, 0x8c, 0x08, 0x1f, 0x52, 0xcf, 0xbc, 0x72, 0xff,
- 0xce, 0x3f, 0xfd, 0xed, 0x46, 0x36, 0x72, 0xff, 0xdb, 0xea, 0x72, 0xfa,
- 0x51, 0x93, 0x9c, 0xb6, 0x35, 0xa2, 0x0b, 0xf4, 0x0b, 0xfe, 0xeb, 0xb3,
- 0xa9, 0x1f, 0x48, 0xe5, 0xfc, 0xa0, 0xc9, 0xa3, 0xce, 0x72, 0xa1, 0x36,
- 0x89, 0x43, 0x49, 0x0b, 0x3f, 0x39, 0xa9, 0xd5, 0x62, 0x04, 0x81, 0x65,
- 0x1a, 0x84, 0x50, 0x90, 0x7a, 0x39, 0x0b, 0xff, 0x63, 0xf6, 0x64, 0x1e,
- 0xe7, 0xc7, 0x2f, 0xef, 0xe6, 0x94, 0x7b, 0x67, 0x2f, 0xff, 0xff, 0xbb,
- 0x83, 0xfe, 0x0f, 0xbb, 0x9d, 0x8c, 0x99, 0x35, 0x37, 0x53, 0xef, 0x1c,
- 0xbf, 0xcc, 0xd2, 0x2f, 0xb9, 0x31, 0xca, 0xc4, 0x59, 0x3b, 0xf5, 0xf0,
- 0xc6, 0x36, 0x72, 0xfa, 0x3e, 0xdb, 0x9c, 0xa8, 0x6f, 0x45, 0xa7, 0x84,
- 0x98, 0x61, 0x6b, 0x95, 0xa3, 0xda, 0x47, 0x18, 0xd6, 0x43, 0x31, 0x86,
- 0x95, 0xde, 0x59, 0xb8, 0xb2, 0x78, 0xf8, 0x10, 0xe2, 0xe2, 0x42, 0xa1,
- 0x0d, 0xff, 0xf2, 0x0e, 0x32, 0x14, 0x10, 0x48, 0x71, 0x87, 0x2f, 0xf8,
- 0x29, 0x82, 0x09, 0x66, 0xce, 0x5f, 0xf6, 0xb5, 0x0b, 0xef, 0xce, 0xd6,
- 0x72, 0xc0, 0x39, 0x7f, 0x2c, 0x0e, 0x16, 0x41, 0xcb, 0xfe, 0xea, 0x4b,
- 0xaf, 0x24, 0x61, 0xcb, 0xff, 0x6d, 0x07, 0xe9, 0x79, 0x36, 0x87, 0x2b,
- 0x0f, 0xdb, 0xc7, 0x17, 0xed, 0xb2, 0x03, 0x07, 0x2a, 0x49, 0xde, 0xe2,
- 0x6a, 0x1b, 0xcc, 0x7b, 0xa1, 0x16, 0x42, 0x8f, 0xc4, 0x37, 0xc3, 0x1a,
- 0x91, 0xcb, 0xfe, 0xec, 0x49, 0x04, 0x41, 0xf1, 0xcb, 0xfe, 0x89, 0x27,
- 0xa5, 0x03, 0xf9, 0xcb, 0xfe, 0x8c, 0xf2, 0x9f, 0xff, 0x1f, 0x1c, 0xb6,
- 0xa1, 0x19, 0xb8, 0x43, 0xa3, 0x86, 0x1c, 0x5f, 0xc3, 0x0b, 0xd4, 0x48,
- 0xe5, 0xff, 0xf7, 0x5d, 0x3d, 0x20, 0x0f, 0xb7, 0xd7, 0x91, 0xc5, 0x0d,
- 0x65, 0xff, 0xb6, 0xa7, 0x90, 0x41, 0x2c, 0xd9, 0xcb, 0x83, 0xb3, 0x94,
- 0xd6, 0x8b, 0x6e, 0xb0, 0x09, 0xfd, 0xff, 0xfd, 0x9f, 0x66, 0xdc, 0x7a,
- 0x91, 0xee, 0x81, 0xd8, 0x72, 0xa1, 0x3a, 0xe7, 0x8c, 0x8c, 0x4c, 0xaf,
- 0xc0, 0x62, 0x76, 0x0e, 0x5f, 0xb3, 0x4b, 0x8c, 0x39, 0x42, 0x79, 0xaa,
- 0x13, 0xdf, 0xf6, 0x33, 0x34, 0x93, 0xbb, 0x0e, 0x5f, 0xfc, 0xec, 0x18,
- 0xf9, 0xa2, 0xbe, 0xce, 0x9c, 0xbf, 0xff, 0x38, 0xf9, 0xdf, 0xa3, 0x1e,
- 0xdb, 0x79, 0xd3, 0x97, 0xff, 0x33, 0x6f, 0x2d, 0x46, 0xe0, 0x67, 0x39,
- 0x7f, 0xd1, 0xee, 0xe3, 0x33, 0x58, 0x72, 0xfd, 0xee, 0xa4, 0x6c, 0xe5,
- 0xe9, 0xdc, 0x74, 0x7b, 0xdb, 0x37, 0xbf, 0xe8, 0xff, 0x61, 0x03, 0xea,
- 0x47, 0x2f, 0x6b, 0x7b, 0x3c, 0x40, 0x6b, 0xe5, 0xbb, 0xac, 0xd1, 0x01,
- 0xb9, 0x9a, 0xab, 0x64, 0x91, 0x49, 0xa6, 0x4b, 0xfe, 0x8e, 0xad, 0x36,
- 0xe9, 0x39, 0xcb, 0xed, 0x47, 0x63, 0x91, 0xf0, 0x68, 0xa2, 0xb1, 0x50,
- 0x9b, 0xc2, 0x89, 0x48, 0xcd, 0xe8, 0x2a, 0xc8, 0x7a, 0x71, 0xfa, 0x3f,
- 0xa5, 0x33, 0x5e, 0xe3, 0x1d, 0x39, 0x58, 0xae, 0xa1, 0x25, 0xa1, 0xa8,
- 0x8f, 0x73, 0xfc, 0x72, 0xf7, 0x5d, 0xac, 0xe5, 0xf4, 0x7e, 0xd3, 0x0e,
- 0x5f, 0x31, 0x8f, 0xe3, 0x94, 0xc3, 0xfc, 0xfc, 0x5f, 0xc3, 0xea, 0x12,
- 0x5f, 0x0f, 0xbf, 0x01, 0xcb, 0xf3, 0x1a, 0xa6, 0xa9, 0xaa, 0x6a, 0x4e,
- 0x5f, 0xff, 0xd2, 0xcd, 0xa6, 0xb4, 0x8c, 0x53, 0xdd, 0xc6, 0xfc, 0x72,
- 0xb1, 0x17, 0xa8, 0x46, 0xe7, 0xb7, 0xff, 0x9b, 0xc1, 0xf6, 0x0c, 0xb3,
- 0x6a, 0x30, 0xe5, 0xff, 0xe9, 0x67, 0xd2, 0x52, 0x3f, 0xe6, 0xdb, 0x6d,
- 0x94, 0xbf, 0x31, 0xbc, 0x4e, 0x27, 0x2f, 0x4b, 0x06, 0x63, 0xfd, 0x51,
- 0x4e, 0xa1, 0x1f, 0x6f, 0x0c, 0x7b, 0xff, 0xf3, 0xea, 0x41, 0xec, 0x6c,
- 0x71, 0xb7, 0xd2, 0xa7, 0x2a, 0x15, 0x4f, 0xf6, 0x1f, 0x63, 0x19, 0x40,
- 0x09, 0xaf, 0xf9, 0x06, 0x5b, 0x6a, 0x0d, 0x4b, 0x54, 0xd4, 0x9c, 0xbe,
- 0x9b, 0x79, 0x31, 0xcb, 0xf7, 0xf1, 0xec, 0x6b, 0x39, 0x7f, 0xa3, 0x34,
- 0xb7, 0x75, 0x9a, 0x20, 0x95, 0xff, 0x47, 0xb3, 0x4b, 0x77, 0x59, 0xa2,
- 0xf9, 0x5f, 0x9c, 0x3d, 0x85, 0x4e, 0x5e, 0x1c, 0xd8, 0x51, 0x54, 0xb3,
- 0xe6, 0x22, 0x50, 0xa6, 0x2b, 0xc6, 0x1a, 0xb7, 0xff, 0x47, 0x51, 0x5c,
- 0xd4, 0xec, 0x07, 0xc7, 0x2f, 0xf8, 0x3a, 0xc6, 0x64, 0x9c, 0x27, 0x2b,
- 0x13, 0xe2, 0x48, 0xce, 0x7a, 0x54, 0xe8, 0xf7, 0xe9, 0x67, 0xea, 0x78,
- 0xe5, 0xfd, 0xd6, 0x9d, 0x45, 0xf4, 0xe5, 0x39, 0xed, 0x00, 0xaa, 0xff,
- 0xde, 0x86, 0x6e, 0x12, 0x77, 0xf1, 0xcb, 0xff, 0x4e, 0xff, 0x34, 0xcf,
- 0x0b, 0xf1, 0x39, 0x7f, 0xfd, 0x9e, 0x81, 0xf6, 0xf3, 0x15, 0x55, 0xe4,
- 0x72, 0xfe, 0x57, 0x3d, 0xec, 0x09, 0xcb, 0xff, 0x60, 0x62, 0x51, 0xdc,
- 0xfd, 0xce, 0x5f, 0xcf, 0x20, 0x49, 0xc2, 0x72, 0xfe, 0xea, 0x4f, 0xbd,
- 0xb9, 0xcb, 0xcd, 0xb6, 0xd9, 0x4b, 0xf7, 0x71, 0x6f, 0xa2, 0x9c, 0xcd,
- 0x05, 0xff, 0xfe, 0x9b, 0x51, 0xc7, 0x92, 0xaf, 0xc9, 0x49, 0xb7, 0xcb,
- 0x3e, 0xf1, 0xca, 0x84, 0x7b, 0x79, 0x39, 0x43, 0x9b, 0xff, 0xc9, 0xa4,
- 0xf0, 0x33, 0xce, 0xcc, 0x13, 0x95, 0x3a, 0xa9, 0x75, 0xa1, 0xe9, 0x3d,
- 0x85, 0xdf, 0x9e, 0x8c, 0x64, 0x7e, 0x30, 0xbf, 0xf3, 0x23, 0xed, 0x8e,
- 0x4e, 0xa4, 0x8e, 0x5f, 0xff, 0xe4, 0xeb, 0x8f, 0xd2, 0x52, 0x50, 0x32,
- 0x76, 0x60, 0x4e, 0x5f, 0xfe, 0xcc, 0xe8, 0x7b, 0x1b, 0xce, 0xa7, 0xe7,
- 0x2f, 0xd3, 0x4a, 0x35, 0xb3, 0x97, 0xfb, 0x04, 0x12, 0xdc, 0xee, 0x72,
- 0xca, 0xf2, 0x3d, 0xc0, 0x94, 0xd4, 0xe9, 0xb8, 0xc9, 0x04, 0x2c, 0x09,
- 0x0a, 0x5b, 0xee, 0x49, 0xd0, 0x1c, 0xbf, 0x64, 0xbb, 0x1a, 0x39, 0x4b,
- 0x3c, 0xb6, 0xb2, 0x4b, 0xfd, 0xe8, 0x4e, 0xab, 0x1f, 0x1c, 0xbf, 0xfb,
- 0xdb, 0x79, 0x6f, 0x17, 0x0c, 0x43, 0x97, 0xff, 0xbe, 0x1e, 0x4b, 0xea,
- 0x7f, 0xfc, 0x6a, 0x47, 0x2a, 0x11, 0xd6, 0x84, 0xa0, 0x34, 0x51, 0x0e,
- 0xfe, 0x4d, 0xe0, 0x54, 0xc3, 0x97, 0xee, 0x04, 0x1c, 0xe2, 0x72, 0xff,
- 0x6b, 0x02, 0x80, 0x5f, 0x56, 0x7b, 0x0e, 0x5b, 0x7f, 0xb6, 0x39, 0xc7,
- 0xaf, 0x23, 0x97, 0xb7, 0x2e, 0x27, 0x29, 0x0f, 0x4d, 0xac, 0xd2, 0xff,
- 0xf4, 0x4e, 0xa7, 0x63, 0xef, 0x64, 0xe2, 0x13, 0x94, 0x89, 0x86, 0xbc,
- 0x27, 0x04, 0x92, 0xff, 0xf7, 0x5e, 0x58, 0x11, 0x47, 0xec, 0x30, 0xe5,
- 0xfe, 0x8c, 0x1f, 0x70, 0x8d, 0xac, 0xe5, 0xfe, 0xee, 0x71, 0xe5, 0xb9,
- 0x2c, 0xe5, 0x6c, 0xfc, 0x3c, 0x71, 0x5e, 0x46, 0xc8, 0x21, 0x6f, 0x7f,
- 0x0f, 0x25, 0x35, 0xd7, 0x39, 0x7f, 0xe0, 0x3c, 0xb9, 0x42, 0x07, 0x18,
- 0x72, 0x9c, 0xfb, 0xc4, 0xc2, 0xff, 0xda, 0x4f, 0xe7, 0xec, 0x6c, 0x1b,
- 0x39, 0x7e, 0xcd, 0x3f, 0xcd, 0x9c, 0xbf, 0xff, 0xd3, 0xe3, 0x63, 0x81,
- 0xd2, 0x02, 0x70, 0xf6, 0x06, 0x73, 0x95, 0x3a, 0x23, 0x36, 0x53, 0x7f,
- 0xa6, 0x17, 0x6f, 0xd9, 0xd3, 0x97, 0xbb, 0x8b, 0x39, 0x79, 0xb6, 0xdb,
- 0x29, 0x7f, 0x7f, 0x03, 0x9f, 0x78, 0xa7, 0x33, 0x41, 0x5c, 0x91, 0x60,
- 0xd0, 0xd1, 0x43, 0xcb, 0xff, 0xfb, 0x87, 0xe4, 0xbe, 0xa0, 0x43, 0x8d,
- 0xf2, 0xf6, 0xf2, 0x73, 0x95, 0xd4, 0x4e, 0x00, 0xd6, 0xa1, 0x53, 0x02,
- 0x43, 0x35, 0xe3, 0x70, 0xbf, 0xe5, 0x23, 0x78, 0xda, 0x83, 0xe3, 0x95,
- 0x3b, 0x3d, 0x46, 0x52, 0x8c, 0x03, 0x09, 0xbf, 0x88, 0x52, 0x56, 0xae,
- 0xa3, 0xde, 0x64, 0x6f, 0x3d, 0x8e, 0x84, 0x63, 0x0c, 0xdc, 0x25, 0xfd,
- 0x2a, 0x01, 0x43, 0xab, 0xff, 0x62, 0x0c, 0xee, 0x3e, 0xc6, 0x1c, 0xbf,
- 0xfd, 0xa5, 0x54, 0xf2, 0x6c, 0x73, 0x8a, 0x04, 0xe5, 0xff, 0x23, 0x61,
- 0xee, 0x79, 0xa6, 0x1c, 0xa8, 0x44, 0x47, 0x53, 0x6f, 0x85, 0xfe, 0xf1,
- 0xcb, 0xd8, 0x3f, 0x9c, 0xbe, 0xcf, 0x4d, 0x23, 0x97, 0xff, 0x70, 0x0c,
- 0x70, 0x6d, 0xc5, 0x4f, 0xf6, 0x72, 0xba, 0x7d, 0xce, 0x47, 0x7f, 0xec,
- 0xf4, 0x6b, 0x7d, 0x81, 0xf1, 0xe2, 0x08, 0x5f, 0xd9, 0xa5, 0xbb, 0xac,
- 0xd1, 0x04, 0x39, 0x9e, 0x55, 0xe8, 0x0a, 0x1c, 0xa8, 0x3e, 0x7d, 0xa6,
- 0x5e, 0xe3, 0x0c, 0x39, 0x7f, 0x3f, 0x75, 0xa4, 0x6c, 0xe5, 0xfc, 0xd6,
- 0x16, 0xdc, 0x64, 0x72, 0xb0, 0xff, 0x44, 0x78, 0x05, 0xd7, 0xff, 0xa6,
- 0x92, 0x0f, 0xa3, 0xf9, 0x85, 0x26, 0x39, 0x70, 0xcc, 0x72, 0xd0, 0x13,
- 0xe3, 0xc4, 0xca, 0x9d, 0x56, 0x92, 0xa4, 0x5d, 0x84, 0x57, 0xf0, 0xd2,
- 0x18, 0x4f, 0x71, 0x84, 0x85, 0xfd, 0xdc, 0xf7, 0x91, 0x87, 0x2f, 0xef,
- 0x29, 0x9d, 0x7f, 0x8e, 0x57, 0xc7, 0xb8, 0x25, 0xb7, 0xf6, 0x7d, 0xed,
- 0x6a, 0x0e, 0x5f, 0xfd, 0xb1, 0x7f, 0x3b, 0x14, 0x89, 0xf0, 0xe5, 0x04,
- 0xfc, 0xb6, 0x5d, 0x50, 0x8b, 0x60, 0x42, 0x52, 0xfe, 0xc5, 0xa9, 0xc7,
- 0xb8, 0x72, 0xff, 0xfe, 0x41, 0x0e, 0xb1, 0x7d, 0x8e, 0xe6, 0xb5, 0x0a,
- 0x9c, 0xba, 0x15, 0x39, 0x72, 0x09, 0xcb, 0x36, 0x72, 0x82, 0x69, 0xd4,
- 0x15, 0xbc, 0x20, 0x9c, 0xe5, 0xfb, 0xaf, 0x2c, 0x13, 0x97, 0xf2, 0x78,
- 0x73, 0xa8, 0x72, 0xec, 0xef, 0x23, 0xd1, 0x82, 0x6b, 0x9d, 0xbe, 0x48,
- 0xfc, 0xc3, 0xee, 0x91, 0x79, 0xba, 0xa4, 0x9f, 0xbe, 0x13, 0xf4, 0xc0,
- 0x63, 0x56, 0xbf, 0xb6, 0x81, 0x0e, 0x09, 0xcb, 0xff, 0xfb, 0xdd, 0xcd,
- 0xef, 0x30, 0x1a, 0x9f, 0x00, 0x3e, 0x39, 0x7f, 0xdd, 0x8d, 0x78, 0x63,
- 0x3e, 0x39, 0x7f, 0xff, 0xc9, 0x3c, 0x4b, 0x7a, 0xd2, 0x7d, 0x34, 0x9f,
- 0x4c, 0xcf, 0x8e, 0x5f, 0xe8, 0x79, 0xdf, 0x4e, 0xa1, 0xcb, 0xdd, 0xc1,
- 0x0a, 0x35, 0x7a, 0x71, 0xe6, 0xaa, 0xc4, 0xe7, 0x10, 0xb3, 0xd1, 0x98,
- 0x5f, 0xa3, 0x53, 0x6e, 0x73, 0x97, 0xfd, 0xd8, 0xcd, 0x4b, 0x60, 0x61,
- 0xca, 0x9c, 0xf8, 0xd6, 0x55, 0x72, 0x6c, 0xe5, 0xff, 0x64, 0xef, 0xef,
- 0xd4, 0x19, 0x1c, 0xbf, 0x9f, 0xdc, 0xa2, 0x4a, 0x9c, 0xbf, 0x94, 0x66,
- 0xdb, 0x7f, 0x8e, 0x54, 0x26, 0xdb, 0x90, 0x98, 0x54, 0x8f, 0x42, 0xce,
- 0x77, 0xe3, 0x0b, 0xda, 0xce, 0x9c, 0xbd, 0xb4, 0x61, 0xca, 0xd1, 0xb8,
- 0xf0, 0xe5, 0xc9, 0x39, 0xca, 0x83, 0x71, 0xc0, 0x43, 0x7f, 0xf7, 0x52,
- 0x07, 0x93, 0x8c, 0x91, 0x87, 0x2f, 0x92, 0x64, 0x6c, 0xe5, 0xff, 0xcc,
- 0x7f, 0x94, 0xf2, 0x6a, 0x01, 0xc3, 0x9c, 0xbf, 0xff, 0x02, 0x71, 0x8c,
- 0xef, 0x38, 0xf6, 0x74, 0x1a, 0x39, 0x7d, 0xed, 0xa9, 0xbe, 0x49, 0x84,
- 0x05, 0x0f, 0x08, 0xd4, 0x4b, 0xbf, 0x6d, 0x99, 0xed, 0x9c, 0xbf, 0xf9,
- 0x15, 0xcf, 0x27, 0x73, 0xd1, 0xa3, 0x97, 0xe7, 0x90, 0xa4, 0x1c, 0xbf,
- 0xa1, 0xc7, 0xd8, 0x27, 0x2a, 0x4a, 0x8f, 0xb2, 0x32, 0xb4, 0x59, 0xd1,
- 0x43, 0x10, 0xc4, 0x96, 0xfd, 0xd4, 0x68, 0x8a, 0x9c, 0xbe, 0xcf, 0xd3,
- 0x89, 0xca, 0x59, 0xe7, 0x09, 0x55, 0xff, 0xdf, 0xc6, 0xd9, 0x09, 0xad,
- 0x23, 0x67, 0x2f, 0x3b, 0xc8, 0xe5, 0x21, 0xf0, 0x7e, 0x8b, 0x7f, 0x0e,
- 0xf1, 0x90, 0xd6, 0x72, 0xf9, 0xaf, 0xb9, 0x39, 0xcb, 0xfd, 0x01, 0xcf,
- 0x27, 0x40, 0x72, 0xa0, 0xf6, 0x02, 0x4d, 0x50, 0x8a, 0x86, 0x42, 0x1e,
- 0xff, 0xde, 0x53, 0xf8, 0x52, 0x3f, 0x8f, 0xce, 0x5f, 0xff, 0xf9, 0x8e,
- 0x3f, 0xc9, 0x36, 0x06, 0x75, 0x23, 0xdd, 0x03, 0xb0, 0xe5, 0xff, 0xf0,
- 0x83, 0xd2, 0x4f, 0xfa, 0xe9, 0xe7, 0x61, 0xcb, 0xb9, 0x35, 0x9c, 0xbf,
- 0xff, 0x3a, 0x79, 0x03, 0x81, 0xcf, 0x23, 0x13, 0x47, 0x2f, 0xff, 0x42,
- 0xc3, 0x8a, 0x79, 0x35, 0x00, 0xe1, 0xce, 0x5e, 0xd3, 0xef, 0x13, 0x0c,
- 0xd2, 0x7f, 0x47, 0x05, 0x4a, 0xde, 0x74, 0xf1, 0x41, 0x1b, 0xc5, 0x7c,
- 0xa8, 0xdd, 0x25, 0x04, 0x5d, 0x28, 0x39, 0x7f, 0xfa, 0x70, 0xf6, 0x3b,
- 0x9f, 0x7f, 0x9e, 0xd9, 0xca, 0x73, 0xe3, 0x00, 0xb5, 0x05, 0x71, 0x67,
- 0x21, 0x02, 0x90, 0xca, 0x79, 0x4b, 0xc3, 0x08, 0xfb, 0xfb, 0x51, 0x3a,
- 0x0f, 0x8e, 0x5e, 0x0a, 0x8c, 0x39, 0x7e, 0x18, 0x0e, 0x4c, 0x72, 0xfb,
- 0x60, 0xd2, 0xa7, 0x2f, 0xd1, 0xdf, 0x44, 0x8e, 0x5f, 0x04, 0x1e, 0xdc,
- 0x1f, 0x97, 0xc4, 0xff, 0x92, 0x5f, 0xbf, 0xc6, 0x47, 0x4e, 0x5f, 0xff,
- 0xfe, 0xc9, 0xf7, 0x0a, 0xbe, 0xfd, 0x2c, 0x55, 0x5c, 0xfb, 0xda, 0x8c,
- 0xf8, 0xe5, 0xfa, 0x39, 0x68, 0x64, 0x72, 0xb6, 0x8a, 0x50, 0x3e, 0x5e,
- 0xe1, 0xfb, 0x87, 0x28, 0x2a, 0x85, 0xb0, 0xb5, 0x21, 0x20, 0x29, 0x1e,
- 0x86, 0x68, 0x08, 0xef, 0x69, 0x4d, 0x9c, 0xbf, 0xee, 0xc7, 0xde, 0x8e,
- 0xbb, 0x59, 0xca, 0x39, 0x5c, 0x8f, 0x1f, 0x85, 0xcf, 0x2f, 0xde, 0xf7,
- 0xb1, 0xb3, 0x95, 0x07, 0xa8, 0x85, 0x77, 0xfe, 0x71, 0x5e, 0x69, 0x6e,
- 0xeb, 0x34, 0x42, 0x2b, 0xa5, 0x39, 0xca, 0x84, 0xce, 0xbf, 0x85, 0xc8,
- 0x08, 0x38, 0xa4, 0xdf, 0xb2, 0x7d, 0xfe, 0xe7, 0x2f, 0xff, 0xff, 0x77,
- 0x01, 0xa5, 0x7a, 0x9f, 0x47, 0x81, 0xd1, 0xcf, 0xbc, 0x07, 0xd9, 0xcb,
- 0xff, 0xb3, 0xe5, 0x3c, 0x82, 0x09, 0x66, 0xce, 0x5f, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xb0, 0x67, 0x17, 0x0c, 0x0c, 0xf1, 0xa0, 0xe0, 0xe7, 0xb6,
- 0x8b, 0xc1, 0x52, 0x7c, 0xd4, 0x6c, 0x5d, 0x5d, 0xe2, 0x7f, 0xf8, 0x3f,
- 0x17, 0x0c, 0x0c, 0xf1, 0xa3, 0x95, 0x09, 0xa7, 0xe2, 0x2d, 0xff, 0xde,
- 0x71, 0x9f, 0xe9, 0x0c, 0x66, 0xce, 0x5f, 0xff, 0xa3, 0xf9, 0xa5, 0x13,
- 0x8b, 0xab, 0xb1, 0x89, 0x1c, 0xbf, 0xf2, 0x99, 0xd7, 0x67, 0x36, 0xdb,
- 0x6c, 0xe5, 0xff, 0xfb, 0x17, 0xd8, 0x10, 0x8a, 0x4f, 0x82, 0x8a, 0x9c,
- 0xb3, 0xce, 0x89, 0x89, 0x22, 0xd4, 0x93, 0x18, 0x78, 0x77, 0xdf, 0xff,
- 0xd3, 0x0c, 0x7f, 0xb5, 0xf5, 0x35, 0x30, 0xc7, 0xfb, 0x39, 0x7f, 0xff,
- 0x7b, 0x70, 0xac, 0x93, 0xae, 0x3e, 0x96, 0x6b, 0x0e, 0x5f, 0xf9, 0x37,
- 0x81, 0xe4, 0xff, 0xb4, 0xc3, 0x97, 0xfe, 0xea, 0x71, 0xeb, 0xcb, 0x50,
- 0xa9, 0xca, 0xc4, 0x6e, 0xad, 0x6b, 0xc8, 0x57, 0xf0, 0x3c, 0x80, 0x15,
- 0x4e, 0x5f, 0xd8, 0xde, 0x08, 0x3f, 0x39, 0x7e, 0x96, 0x7a, 0x3f, 0x39,
- 0x74, 0x32, 0x73, 0xd6, 0xf8, 0xba, 0xff, 0xff, 0xef, 0xd8, 0xf2, 0xeb,
- 0xa7, 0x90, 0x38, 0x1c, 0xf2, 0x31, 0x34, 0x72, 0xb6, 0x89, 0xf0, 0x17,
- 0xdf, 0xff, 0x87, 0x37, 0x9d, 0x7e, 0x05, 0xf5, 0x19, 0x0b, 0x39, 0x7e,
- 0x9d, 0x90, 0x18, 0x39, 0x52, 0x5e, 0x9d, 0x0c, 0x79, 0x3f, 0x11, 0x4d,
- 0x1a, 0xe6, 0x8a, 0x3b, 0x19, 0xde, 0xcb, 0xfd, 0x19, 0x1f, 0x12, 0x35,
- 0x15, 0xaf, 0xfd, 0x0a, 0xab, 0x03, 0x9e, 0xea, 0x1c, 0xbf, 0xd1, 0xbd,
- 0xc4, 0xf8, 0xd9, 0xcb, 0xfd, 0xdc, 0x66, 0x74, 0x02, 0x72, 0x82, 0x7c,
- 0xde, 0x34, 0xbe, 0xcd, 0x2a, 0x87, 0x2a, 0x19, 0x0b, 0x39, 0x3d, 0x8c,
- 0x90, 0xab, 0x78, 0x52, 0x00, 0x8a, 0xf3, 0x6d, 0xb6, 0x52, 0xff, 0xb3,
- 0xf7, 0xd6, 0x71, 0xc0, 0x94, 0xe6, 0x68, 0x2e, 0x6d, 0xb2, 0x97, 0x9b,
- 0x6d, 0xb2, 0x97, 0xf3, 0xce, 0x1e, 0xc6, 0xca, 0x73, 0x34, 0x14, 0x28,
- 0xc5, 0x6d, 0x31, 0xa1, 0xcd, 0xf9, 0x68, 0x15, 0x18, 0x53, 0x99, 0xb2,
- 0xbc, 0xdb, 0x6d, 0x94, 0xbd, 0xb8, 0xd1, 0x4e, 0x66, 0x82, 0xf9, 0xc7,
- 0xef, 0x1c, 0xb7, 0xe8, 0x8a, 0xbf, 0x2d, 0xb6, 0x5d, 0x7f, 0x04, 0x62,
- 0x4e, 0xb3, 0x97, 0xed, 0x82, 0x76, 0x82, 0x72, 0xfc, 0x14, 0xe3, 0x01,
- 0x39, 0x7d, 0x83, 0x8d, 0x67, 0x2b, 0x47, 0x98, 0xc2, 0x9a, 0x44, 0x4c,
- 0xa8, 0xef, 0x7f, 0xf7, 0x5e, 0x42, 0xea, 0xcc, 0x29, 0x31, 0xcb, 0xfe,
- 0x9e, 0x3e, 0xda, 0x0e, 0x7e, 0x72, 0xf9, 0xe4, 0x9f, 0x9c, 0xad, 0x1e,
- 0xe7, 0x4e, 0xaf, 0xfb, 0x17, 0x13, 0x87, 0xb1, 0xb3, 0x95, 0x87, 0xb6,
- 0xd0, 0x8a, 0xfe, 0xee, 0x71, 0xcf, 0x6c, 0xe5, 0x2d, 0x34, 0xef, 0xe1,
- 0xf9, 0xe2, 0x3a, 0xd2, 0xa6, 0xde, 0xc3, 0x14, 0x63, 0x71, 0xba, 0x7f,
- 0x1c, 0xa8, 0x55, 0xf1, 0x92, 0xa9, 0x04, 0xf2, 0xfd, 0x3b, 0x4e, 0xe2,
- 0xce, 0x5c, 0xd4, 0x1a, 0x93, 0x97, 0xed, 0xcd, 0xb8, 0xf1, 0xca, 0xc3,
- 0xf6, 0xf8, 0xaf, 0xc4, 0x57, 0xe5, 0xc7, 0x61, 0x87, 0x2e, 0x7f, 0x1c,
- 0xbf, 0x63, 0x5b, 0x8f, 0xf8, 0x6f, 0x44, 0x9e, 0xff, 0xa0, 0x64, 0x21,
- 0xec, 0x4e, 0x72, 0xfe, 0x0e, 0x69, 0xa3, 0x02, 0x72, 0xf7, 0x52, 0x62,
- 0x95, 0xa3, 0xcd, 0xd9, 0x85, 0xff, 0x3f, 0xde, 0xc9, 0x81, 0xa5, 0x4e,
- 0x59, 0x68, 0x7b, 0xc0, 0x22, 0xbf, 0xc3, 0x9f, 0x4b, 0x68, 0xa9, 0xcb,
- 0xe7, 0x7d, 0x2a, 0x72, 0xca, 0x9c, 0xbf, 0xfb, 0x17, 0xd8, 0xee, 0x6b,
- 0x50, 0xa9, 0xcb, 0xc9, 0xfe, 0xe0, 0xf5, 0xb4, 0x25, 0x5c, 0x91, 0xbf,
- 0x39, 0xa0, 0xbc, 0x5f, 0xf6, 0x62, 0xff, 0x8c, 0xfa, 0x47, 0x2f, 0xa1,
- 0xd9, 0xc4, 0xa5, 0xff, 0xdd, 0x47, 0xff, 0xf8, 0xfe, 0x3b, 0xb3, 0x97,
- 0xf7, 0x71, 0x8c, 0x79, 0x1c, 0xbc, 0xdb, 0x6d, 0x94, 0xbf, 0xc3, 0xee,
- 0xa4, 0x0c, 0xe5, 0x39, 0x9a, 0x0b, 0xd1, 0xfe, 0x49, 0x12, 0x38, 0x9b,
- 0x5e, 0x4c, 0x29, 0x48, 0x6b, 0xdb, 0x16, 0x9a, 0xbb, 0x23, 0x2d, 0xbf,
- 0xbf, 0x8f, 0xe3, 0xbb, 0x39, 0x7f, 0xa1, 0x4d, 0x69, 0x3d, 0xb3, 0x95,
- 0x0b, 0x9c, 0xf2, 0x6c, 0x54, 0xfb, 0xe8, 0x71, 0xa4, 0x60, 0xd3, 0x19,
- 0x76, 0x39, 0x0f, 0xcb, 0xc4, 0xbe, 0xfd, 0xfe, 0x27, 0x55, 0x39, 0x7f,
- 0xfd, 0x8b, 0x81, 0x7f, 0x6c, 0x20, 0x7d, 0x48, 0xe5, 0x7c, 0x7e, 0xec,
- 0x29, 0xbf, 0xa0, 0x56, 0xd5, 0x35, 0x16, 0xac, 0xe5, 0xfa, 0x19, 0xa8,
- 0xe2, 0x72, 0xff, 0xf6, 0xa1, 0x7e, 0x18, 0x6f, 0x3d, 0xbd, 0x9c, 0xbf,
- 0xff, 0xf8, 0x5d, 0x91, 0xa5, 0x87, 0xb1, 0xb0, 0x3a, 0x4b, 0x7d, 0x79,
- 0x1c, 0xbc, 0x0f, 0x6c, 0xe5, 0xe5, 0xc6, 0xce, 0x5f, 0xfc, 0xa4, 0xb3,
- 0xaf, 0xd4, 0xd6, 0xa0, 0xe5, 0x61, 0xf0, 0x7e, 0x39, 0x7e, 0x8f, 0x6f,
- 0x8e, 0x1c, 0xbf, 0x03, 0x4a, 0xf5, 0x0e, 0x54, 0x2a, 0x34, 0x09, 0x1a,
- 0xcf, 0x74, 0x52, 0xe9, 0x5f, 0xb8, 0x0b, 0xef, 0x88, 0x9a, 0x14, 0xdf,
- 0xe1, 0x76, 0xf0, 0x5d, 0x53, 0x97, 0xff, 0x67, 0xb6, 0xa6, 0xd8, 0x31,
- 0xa8, 0x39, 0x7b, 0x8e, 0x08, 0x4f, 0xd9, 0x86, 0x57, 0xff, 0x37, 0x1a,
- 0x17, 0x9e, 0x35, 0x12, 0x39, 0x48, 0x7f, 0x1d, 0x34, 0xbf, 0xff, 0xe0,
- 0xf5, 0x1b, 0xce, 0x04, 0x63, 0xfb, 0x60, 0x96, 0x7d, 0xe3, 0x95, 0x88,
- 0x8c, 0x72, 0x1b, 0xfe, 0x99, 0x7d, 0x46, 0x46, 0x95, 0x39, 0x7e, 0x9f,
- 0x90, 0x22, 0x63, 0x96, 0x91, 0xcb, 0xca, 0x0c, 0xc7, 0x2a, 0x46, 0xbf,
- 0xf1, 0x1a, 0xc4, 0x5c, 0x39, 0xde, 0xd6, 0xea, 0x1f, 0x2b, 0xe2, 0x79,
- 0x5c, 0x92, 0x9c, 0x29, 0x0c, 0xb5, 0x3c, 0xa7, 0xcc, 0xab, 0x0e, 0x15,
- 0xc3, 0x11, 0x25, 0x7a, 0x4d, 0x2d, 0xeb, 0x52, 0xd2, 0xd9, 0x2c, 0x27,
- 0xb3, 0xa0, 0x6f, 0x29, 0xd7, 0xf8, 0xe6, 0x86, 0x91, 0x3d, 0xb9, 0xd1,
- 0x6f, 0x4e, 0xc9, 0x82, 0x59, 0xf3, 0x71, 0xfd, 0x29, 0x0d, 0x9b, 0xdc,
- 0x60, 0x4e, 0x5f, 0xff, 0x60, 0xf3, 0xf2, 0xa9, 0xf6, 0xfb, 0x9f, 0xb9,
- 0xca, 0x91, 0xf8, 0x04, 0x76, 0xf3, 0xbb, 0x67, 0x2e, 0xfe, 0x0e, 0x5f,
- 0x97, 0x9e, 0xea, 0x1c, 0xb3, 0x84, 0xf6, 0x90, 0x70, 0x45, 0xef, 0xff,
- 0xfb, 0x3a, 0xea, 0x6f, 0x15, 0x71, 0xfe, 0x06, 0x26, 0xec, 0x1c, 0xb4,
- 0x1c, 0xbf, 0xff, 0x46, 0xbb, 0x0c, 0xe0, 0x04, 0x0c, 0x4d, 0xd8, 0x39,
- 0x7e, 0x4d, 0x4d, 0x1d, 0xd2, 0x33, 0x7f, 0x66, 0x11, 0x0a, 0xf9, 0x3c,
- 0x86, 0x3e, 0x29, 0x0f, 0xfb, 0x70, 0xb9, 0xcb, 0xff, 0x7b, 0xaf, 0x2f,
- 0x4c, 0x30, 0xc3, 0x97, 0xfe, 0x71, 0xff, 0x90, 0x40, 0xfa, 0x91, 0xcb,
- 0xe4, 0x19, 0xe0, 0xe5, 0xef, 0x6a, 0x0e, 0x5f, 0xf0, 0xc3, 0x10, 0x71,
- 0x90, 0x72, 0xe4, 0x0e, 0x1e, 0x8c, 0xc3, 0x94, 0xd6, 0x8e, 0x0d, 0x20,
- 0x8b, 0x95, 0xff, 0xc3, 0xed, 0xf5, 0xe5, 0xcb, 0x3e, 0xf1, 0xca, 0x6a,
- 0x29, 0xd8, 0x40, 0xc6, 0x46, 0x3e, 0x03, 0x2b, 0xfe, 0x76, 0xb9, 0xb7,
- 0x1d, 0x76, 0xb3, 0x97, 0xa0, 0x67, 0x39, 0x7c, 0x9d, 0x46, 0x1c, 0xb7,
- 0x50, 0xde, 0xcc, 0x39, 0x7f, 0x42, 0xe3, 0x7e, 0x43, 0x97, 0xfd, 0x1e,
- 0xeb, 0xfe, 0xff, 0x6c, 0xe5, 0x04, 0xf9, 0x84, 0xb2, 0xff, 0xff, 0x08,
- 0x1d, 0x7b, 0x03, 0xa4, 0xa0, 0x57, 0x9f, 0x78, 0xe5, 0xff, 0xb5, 0xff,
- 0x2e, 0xa2, 0xc1, 0xaf, 0xce, 0x5e, 0x98, 0x1a, 0x39, 0x7f, 0xe7, 0x4d,
- 0x67, 0xdc, 0xdb, 0x6d, 0xb3, 0x95, 0x08, 0xa6, 0x74, 0x4d, 0x8f, 0x5f,
- 0xff, 0x0c, 0x4b, 0x92, 0x9e, 0x41, 0x04, 0xb3, 0x67, 0x2b, 0x15, 0x19,
- 0x2e, 0x11, 0xac, 0x21, 0xec, 0x60, 0xbf, 0x97, 0x5e, 0xfd, 0xd8, 0x72,
- 0xec, 0xfc, 0xe5, 0x41, 0xb4, 0xc1, 0xdb, 0xcf, 0x8c, 0x39, 0x70, 0xc8,
- 0x4d, 0xd7, 0x00, 0xfd, 0xfe, 0x6f, 0x63, 0x81, 0x17, 0x39, 0x72, 0xd0,
- 0xe5, 0xf8, 0x62, 0x78, 0xf8, 0xe5, 0xb6, 0xb3, 0x7c, 0x82, 0xd5, 0x08,
- 0xc4, 0x42, 0xe7, 0x70, 0xbf, 0x6b, 0x63, 0x13, 0x9c, 0xbf, 0xfe, 0x6f,
- 0x17, 0xbc, 0xf4, 0xd8, 0xa8, 0xe7, 0xe7, 0x2b, 0x0f, 0xe9, 0x0a, 0x2f,
- 0xfb, 0x1b, 0xcd, 0x2d, 0xdd, 0x66, 0x8c, 0x39, 0x7e, 0xf7, 0x5c, 0x7f,
- 0x39, 0x53, 0x9f, 0x6b, 0xa2, 0xdf, 0xf9, 0xfd, 0x93, 0x3c, 0x0c, 0x4c,
- 0x72, 0xff, 0xdd, 0x4c, 0x53, 0x26, 0x6e, 0x3e, 0x39, 0x64, 0xd2, 0x28,
- 0x3a, 0x45, 0xb3, 0xdb, 0x96, 0xb3, 0x46, 0x08, 0xa9, 0x27, 0x0c, 0xb8,
- 0xcb, 0x7f, 0x35, 0xbf, 0xcd, 0x4e, 0xc2, 0x39, 0xde, 0x10, 0xe5, 0xd8,
- 0x27, 0x2f, 0xff, 0x7a, 0x05, 0x79, 0xee, 0xa6, 0xbf, 0x59, 0xcb, 0xf0,
- 0x53, 0x7d, 0x43, 0x97, 0xf2, 0x0e, 0x7b, 0xa8, 0x72, 0xd1, 0x87, 0xa5,
- 0xb2, 0x7a, 0x0a, 0x35, 0xf0, 0x54, 0x10, 0x9c, 0xbf, 0xd0, 0xcd, 0xed,
- 0xc6, 0x73, 0x97, 0xfd, 0xfe, 0xe4, 0x9d, 0x74, 0x9c, 0xe5, 0xf6, 0xf0,
- 0x7c, 0x72, 0xf7, 0x04, 0x68, 0xe5, 0x21, 0xfd, 0x39, 0xd0, 0x08, 0x6f,
- 0x79, 0xda, 0xce, 0x5f, 0xef, 0x75, 0x39, 0xfe, 0xe8, 0x72, 0xff, 0x2b,
- 0xd8, 0x90, 0x1f, 0x47, 0x2c, 0x27, 0x29, 0x0f, 0x10, 0x06, 0x97, 0x29,
- 0x87, 0x2a, 0x75, 0x5e, 0x41, 0x8c, 0x53, 0xa6, 0x83, 0x0a, 0xdf, 0x16,
- 0x80, 0x7d, 0xa3, 0xca, 0x84, 0x37, 0xe5, 0x7f, 0x49, 0xb6, 0x72, 0xfb,
- 0xa8, 0xf2, 0x39, 0x78, 0x2f, 0x23, 0x95, 0x06, 0xf7, 0x08, 0x6c, 0x08,
- 0x44, 0x3f, 0xed, 0x17, 0xff, 0xb9, 0x0b, 0xfa, 0x34, 0x09, 0x6a, 0x24,
- 0x72, 0xef, 0x6c, 0xe5, 0xf9, 0xd5, 0x6e, 0x34, 0x72, 0x91, 0x11, 0x6e,
- 0x96, 0x22, 0xf7, 0xff, 0x22, 0xc7, 0x19, 0x13, 0x06, 0x27, 0x39, 0x7f,
- 0xcb, 0xcf, 0x47, 0x14, 0x1f, 0xce, 0x5f, 0xff, 0xc0, 0x8f, 0x6f, 0x07,
- 0x96, 0xa1, 0x02, 0x2f, 0x23, 0x97, 0xe5, 0xf7, 0xe7, 0x6b, 0x39, 0x7f,
- 0xf2, 0x04, 0x41, 0xed, 0xc0, 0xc6, 0xce, 0x52, 0xd3, 0x46, 0x44, 0x41,
- 0x3a, 0x02, 0xd7, 0x12, 0xcb, 0xff, 0x3e, 0xb3, 0x8e, 0x07, 0x42, 0xd9,
- 0xcb, 0xff, 0xf9, 0x00, 0x32, 0xc1, 0xf2, 0x34, 0xcf, 0x0b, 0xc8, 0xe5,
- 0x7e, 0x89, 0x9f, 0x20, 0x5f, 0xff, 0xc3, 0x9b, 0x07, 0x2c, 0xeb, 0x8e,
- 0x4d, 0x28, 0xf8, 0xe5, 0xfb, 0x4b, 0x77, 0x59, 0xa2, 0x06, 0x5f, 0xcf,
- 0x3f, 0xee, 0x21, 0x25, 0x60, 0xf5, 0xec, 0xd8, 0x30, 0xfc, 0x1a, 0x1a,
- 0x5e, 0xeb, 0xcb, 0x92, 0x60, 0x03, 0x0c, 0xcb, 0xfe, 0xea, 0x60, 0xe2,
- 0xc3, 0x87, 0x29, 0x89, 0xca, 0xfa, 0x32, 0x4e, 0x27, 0x77, 0xbc, 0x08,
- 0x39, 0x7d, 0xfe, 0xb7, 0xb3, 0x97, 0xfb, 0xff, 0x24, 0xec, 0x85, 0x9c,
- 0xaf, 0x8f, 0xd5, 0xc7, 0x04, 0x92, 0xfc, 0x16, 0xad, 0xc2, 0xd5, 0x9c,
- 0xbf, 0xff, 0x3c, 0xb6, 0x81, 0xe5, 0x99, 0xf7, 0xee, 0x3e, 0x39, 0x50,
- 0xaf, 0x7b, 0x25, 0x3c, 0xa4, 0x2b, 0x9c, 0xb8, 0x06, 0x57, 0x24, 0x8e,
- 0x5f, 0xdf, 0x78, 0x39, 0x8a, 0x9c, 0xa0, 0x9e, 0x2e, 0x0b, 0x5f, 0xd9,
- 0xe8, 0x14, 0xfc, 0xe5, 0xfe, 0xd0, 0xbb, 0x6a, 0x7c, 0xd9, 0xcb, 0xbf,
- 0xe2, 0x72, 0x82, 0x7a, 0x3d, 0x37, 0xbc, 0xfa, 0x9c, 0xd1, 0x82, 0xaf,
- 0xfc, 0xfa, 0xc1, 0xff, 0x7e, 0xdf, 0xc7, 0x2f, 0xff, 0xff, 0xec, 0xf7,
- 0x5c, 0x55, 0xe5, 0xbd, 0x3b, 0xfb, 0x8e, 0x07, 0x96, 0x31, 0xc7, 0xe9,
- 0x1e, 0x20, 0xb5, 0xff, 0x9d, 0xd5, 0x5b, 0x87, 0x92, 0xad, 0x9e, 0x20,
- 0xb5, 0xff, 0xdd, 0x4e, 0xa4, 0x0f, 0xb9, 0x2a, 0xd9, 0xe2, 0x0b, 0x5f,
- 0xe8, 0x41, 0xf7, 0x25, 0x5b, 0x3c, 0x41, 0x6b, 0xf9, 0x98, 0x1e, 0x4a,
- 0xb6, 0x78, 0x82, 0xd7, 0xff, 0xfc, 0xe2, 0x28, 0xce, 0x5b, 0x5f, 0x53,
- 0x48, 0xac, 0xf8, 0xd9, 0xe2, 0x0b, 0x5d, 0xf7, 0x20, 0xa7, 0x38, 0xb5,
- 0x0d, 0x2a, 0x3a, 0x18, 0x9f, 0xd4, 0x2a, 0xcf, 0xea, 0x00, 0xca, 0x37,
- 0xbf, 0xc9, 0x0a, 0xef, 0xdb, 0xf8, 0xe5, 0xf3, 0xeb, 0xf7, 0x39, 0x7f,
- 0xf7, 0x53, 0xa9, 0x03, 0xee, 0x4a, 0xb6, 0x78, 0x82, 0xd7, 0xfd, 0x36,
- 0xd6, 0x93, 0xf2, 0x55, 0xb3, 0xc4, 0x16, 0xbf, 0x7b, 0x70, 0xce, 0x4b,
- 0x45, 0x0a, 0x8a, 0x97, 0xff, 0xb9, 0x2f, 0xa8, 0xb8, 0xf6, 0xf9, 0x2a,
- 0xd9, 0xe2, 0x0b, 0x5f, 0xff, 0xfc, 0x22, 0x8c, 0xe4, 0x0c, 0xe5, 0xb5,
- 0xf5, 0x34, 0x8a, 0xcf, 0x8d, 0x9e, 0x20, 0xb5, 0x62, 0x64, 0xbf, 0x21,
- 0xba, 0xf5, 0xff, 0x75, 0x34, 0x8a, 0xcf, 0x8d, 0x9e, 0x20, 0xb5, 0xff,
- 0xf3, 0xbf, 0xd2, 0xdf, 0x50, 0x21, 0x8d, 0x41, 0x4b, 0xff, 0x64, 0xa4,
- 0x0d, 0xe8, 0x67, 0x68, 0x78, 0x82, 0xd4, 0xb4, 0x73, 0x69, 0x23, 0x69,
- 0xf7, 0xfe, 0x5a, 0x6b, 0xcf, 0xfe, 0xf9, 0x36, 0x78, 0x82, 0xd7, 0xf7,
- 0x53, 0xbd, 0x4f, 0xcd, 0x00, 0x5a, 0xfd, 0x9f, 0xf2, 0x55, 0xb3, 0xc4,
- 0x16, 0xbb, 0x3c, 0xb3, 0xf5, 0xe9, 0xdd, 0x7c, 0x8f, 0x2d, 0xc3, 0x16,
- 0xfe, 0x66, 0x07, 0x92, 0xad, 0x9e, 0x20, 0xb5, 0xff, 0x97, 0xd4, 0xd2,
- 0x2b, 0x3e, 0x36, 0x78, 0x82, 0xd7, 0x67, 0x27, 0x44, 0x6e, 0xcf, 0xef,
- 0xf0, 0x11, 0x8e, 0x3f, 0x48, 0xf1, 0x05, 0xaf, 0xfd, 0x89, 0xc7, 0x07,
- 0x02, 0xf2, 0x3c, 0x41, 0x66, 0x1e, 0x05, 0x05, 0x78, 0x33, 0x46, 0xff,
- 0x9a, 0x8c, 0x7d, 0x1b, 0x8c, 0x5b, 0xd1, 0x91, 0x02, 0x16, 0xcd, 0xb7,
- 0xdd, 0xfc, 0x1a, 0x20, 0xb7, 0x34, 0x46, 0x5c, 0xeb, 0x39, 0x6d, 0xad,
- 0x93, 0xbf, 0xfd, 0x26, 0x47, 0xc7, 0x17, 0x4b, 0x80, 0xe5, 0xe8, 0x97,
- 0x01, 0xca, 0x83, 0x72, 0x23, 0x55, 0x3b, 0x2c, 0xec, 0x24, 0x3f, 0x3e,
- 0xff, 0x4a, 0x01, 0x17, 0xdb, 0xff, 0xb2, 0x43, 0x9e, 0xea, 0x67, 0xde,
- 0x39, 0x7f, 0xa3, 0xa8, 0xdf, 0xd2, 0xd9, 0xcb, 0xf4, 0x7b, 0x7d, 0x43,
- 0x97, 0xfe, 0xd6, 0x2b, 0xdc, 0x60, 0x35, 0x39, 0xcb, 0xfe, 0xf8, 0x71,
- 0x19, 0x83, 0xf9, 0xcb, 0xff, 0x6e, 0x69, 0x00, 0x33, 0x48, 0x01, 0x39,
- 0x53, 0xa6, 0x31, 0x23, 0x50, 0x93, 0xe2, 0x0f, 0x8e, 0x2f, 0xfe, 0x8f,
- 0xa4, 0xa3, 0x37, 0xe8, 0xf9, 0xb3, 0x97, 0xe9, 0x70, 0x70, 0x02, 0x73,
- 0x96, 0xea, 0x1f, 0xcb, 0xa4, 0xdf, 0xb5, 0x1f, 0x4b, 0x67, 0x2a, 0x47,
- 0x9f, 0xa2, 0x6b, 0xcc, 0x7f, 0x1c, 0xbf, 0xf0, 0x36, 0xd3, 0x35, 0xfb,
- 0x13, 0x67, 0x2f, 0xfe, 0xe3, 0xc6, 0x36, 0xfd, 0xfa, 0x59, 0xe3, 0x95,
- 0xfa, 0x22, 0xd4, 0x42, 0xbf, 0xdf, 0x83, 0xc3, 0x1e, 0xd9, 0xca, 0x92,
- 0x60, 0x1f, 0xc2, 0x9f, 0x64, 0xb5, 0x0a, 0x9b, 0x32, 0x31, 0x37, 0x8c,
- 0x8a, 0xfe, 0x79, 0x47, 0x17, 0xe9, 0xcb, 0xff, 0xb3, 0xef, 0x6d, 0x06,
- 0x3f, 0x76, 0x1c, 0xbf, 0xf7, 0x0f, 0x82, 0x38, 0xa4, 0x0f, 0xe7, 0x2a,
- 0x74, 0x43, 0x01, 0x12, 0xfb, 0xed, 0xc7, 0xc7, 0x2f, 0xfd, 0x2c, 0xfa,
- 0x5a, 0x8f, 0x3f, 0x8e, 0x5e, 0x64, 0x48, 0xe5, 0xfb, 0x03, 0xd0, 0x36,
- 0x72, 0xb9, 0x22, 0xa2, 0x62, 0x47, 0x3f, 0x11, 0xcb, 0xc1, 0x7f, 0x1c,
- 0xbf, 0xf6, 0xe0, 0x62, 0x5e, 0xee, 0x09, 0xca, 0xd2, 0x25, 0x9c, 0xfb,
- 0x63, 0x97, 0x91, 0xa6, 0x1c, 0xbc, 0xfa, 0xfc, 0xe5, 0xbe, 0x83, 0x75,
- 0xe1, 0xdb, 0xe6, 0xf3, 0xae, 0x72, 0xf9, 0x5d, 0x23, 0x67, 0x2f, 0xd3,
- 0xbf, 0x61, 0xac, 0xe5, 0x35, 0x27, 0x9f, 0x84, 0x95, 0x0a, 0xcf, 0x72,
- 0x16, 0x89, 0x1b, 0x13, 0xb4, 0xfe, 0x4e, 0x2e, 0x37, 0xff, 0x0c, 0x4e,
- 0xce, 0xa6, 0xb4, 0xf2, 0x39, 0x47, 0x28, 0x4f, 0x3d, 0xa2, 0x25, 0xfe,
- 0x9e, 0x78, 0x1f, 0xb3, 0xc7, 0x2b, 0x0f, 0x61, 0x08, 0xef, 0xfe, 0xd0,
- 0x83, 0xef, 0x0e, 0x4e, 0xe2, 0x72, 0xff, 0xfe, 0x0f, 0x41, 0x3a, 0x66,
- 0xb5, 0x91, 0xf4, 0x91, 0x87, 0x2f, 0x3e, 0xa7, 0x39, 0x77, 0xf0, 0x72,
- 0xf9, 0x21, 0x98, 0x72, 0x8e, 0x5f, 0xce, 0xaf, 0xa3, 0x5f, 0x9c, 0xa0,
- 0x9b, 0xa1, 0x0b, 0xbf, 0xff, 0xd0, 0x81, 0x18, 0x02, 0xfd, 0x8b, 0x0c,
- 0x2d, 0x46, 0x1c, 0xbb, 0xf8, 0x39, 0x74, 0x2a, 0x72, 0xff, 0xb3, 0xdb,
- 0x86, 0x29, 0x93, 0x1c, 0xbf, 0xdb, 0xce, 0xa6, 0xc1, 0x39, 0xcb, 0x9b,
- 0x6c, 0xa5, 0xff, 0x0e, 0x71, 0x79, 0x6d, 0x02, 0x72, 0x96, 0x9f, 0xe2,
- 0x0e, 0xe8, 0x5d, 0x8b, 0x5d, 0x20, 0xfd, 0x83, 0x87, 0x17, 0x11, 0x7d,
- 0x9d, 0x36, 0x68, 0xa0, 0xcd, 0xe6, 0xdb, 0x6c, 0xa5, 0x98, 0x53, 0x99,
- 0xa0, 0xbe, 0x99, 0xdf, 0x45, 0x39, 0xa3, 0x89, 0x48, 0x5f, 0xd4, 0xea,
- 0xf1, 0xd6, 0x88, 0xf2, 0xce, 0xaf, 0xef, 0x46, 0x77, 0x27, 0x39, 0x76,
- 0x30, 0xe5, 0x7c, 0x78, 0x7b, 0x2d, 0xa8, 0x75, 0x78, 0x92, 0x8f, 0xa0,
- 0x29, 0x19, 0x2a, 0xb9, 0x58, 0xe2, 0x7e, 0x94, 0x5a, 0x92, 0xca, 0xb5,
- 0x18, 0x43, 0x21, 0x69, 0xd9, 0xd5, 0x17, 0xa5, 0xea, 0x7e, 0xb2, 0x32,
- 0xf1, 0xf7, 0x2d, 0xe3, 0xd1, 0x83, 0x82, 0x5f, 0x3f, 0x17, 0xcb, 0xfb,
- 0x3f, 0xfd, 0x35, 0x23, 0x97, 0x2f, 0x0e, 0x50, 0x4f, 0x15, 0xcb, 0xee,
- 0xc6, 0xce, 0x5d, 0x1e, 0x39, 0x53, 0x9a, 0xd5, 0x8b, 0xd9, 0x87, 0x2b,
- 0x0d, 0x9f, 0x88, 0xaf, 0xf4, 0x90, 0x71, 0x80, 0xe9, 0xcb, 0xff, 0x67,
- 0xb7, 0xd4, 0x63, 0xe6, 0x8e, 0x54, 0x1f, 0x78, 0x99, 0x5f, 0xb3, 0x96,
- 0x7f, 0xe3, 0x97, 0xdc, 0xbd, 0x1c, 0x4e, 0x5f, 0x63, 0x33, 0xc7, 0x2f,
- 0x79, 0xd5, 0x39, 0x7c, 0xec, 0x79, 0x8e, 0x5f, 0x85, 0xfd, 0xf6, 0xce,
- 0x5f, 0xff, 0xf9, 0xe6, 0x04, 0x80, 0xbe, 0x5d, 0x4f, 0x7a, 0x3e, 0x89,
- 0xe3, 0x67, 0x2f, 0xc2, 0xed, 0x73, 0xcc, 0x72, 0xfa, 0x6d, 0xc7, 0x8e,
- 0x52, 0xd1, 0x81, 0x33, 0x88, 0x0b, 0x2f, 0xff, 0xf9, 0xac, 0x5d, 0xf8,
- 0xc4, 0xbb, 0x1a, 0x9e, 0x3d, 0xb7, 0x91, 0xcb, 0xc9, 0xf4, 0xc7, 0x2f,
- 0x81, 0xc3, 0xb1, 0x0e, 0x5f, 0xb3, 0x27, 0x06, 0xce, 0x5f, 0x68, 0x53,
- 0xf3, 0x97, 0xc8, 0xb7, 0xd1, 0xcb, 0xa3, 0xf3, 0x97, 0xc0, 0x9c, 0x1c,
- 0xfa, 0x6e, 0x14, 0x21, 0xa4, 0x44, 0xbf, 0x56, 0xae, 0x6b, 0xfc, 0xe5,
- 0xf9, 0xe3, 0xec, 0x59, 0xcb, 0xfe, 0xeb, 0xef, 0xa9, 0x3b, 0x89, 0xcb,
- 0xe7, 0x9d, 0x49, 0x1c, 0xae, 0x19, 0x74, 0x9e, 0x21, 0x03, 0x28, 0x47,
- 0x84, 0x83, 0x0a, 0xbe, 0x26, 0x42, 0x16, 0xb1, 0xd9, 0x88, 0xb5, 0x0e,
- 0x87, 0x31, 0xfd, 0xab, 0x87, 0x1e, 0xd9, 0x3f, 0xa1, 0x7e, 0x02, 0x26,
- 0xc6, 0xd4, 0x27, 0xe0, 0x38, 0xbf, 0x84, 0x01, 0x63, 0xc8, 0xe5, 0xe4,
- 0x9c, 0x07, 0x2f, 0xd1, 0xfa, 0x7d, 0x87, 0x2e, 0x67, 0x13, 0x96, 0x0c,
- 0x1e, 0x08, 0x94, 0x5f, 0xfe, 0x90, 0xc7, 0x26, 0x0c, 0x2b, 0xe4, 0x9c,
- 0xe5, 0xf9, 0xd9, 0x9d, 0x61, 0xca, 0xf8, 0xfc, 0xfc, 0x99, 0x7b, 0xda,
- 0x83, 0x97, 0xfb, 0x7e, 0xe3, 0x83, 0x81, 0x39, 0x7f, 0x66, 0xf2, 0x49,
- 0xa3, 0x97, 0xbb, 0x1c, 0x4e, 0x5e, 0xdc, 0xa7, 0x39, 0x58, 0x6f, 0x14,
- 0x1e, 0xa8, 0x54, 0x41, 0x22, 0xdc, 0x5e, 0x48, 0x4c, 0xb0, 0x8d, 0xc7,
- 0x04, 0xd3, 0xcd, 0x17, 0x9f, 0x92, 0x87, 0x2f, 0x4c, 0x9d, 0x39, 0x7f,
- 0x46, 0x9e, 0x64, 0xe9, 0xcb, 0xf6, 0xc3, 0x03, 0x3b, 0x9e, 0x56, 0xc7,
- 0x6f, 0xf6, 0xb2, 0x78, 0xef, 0x60, 0xe5, 0xe6, 0x43, 0x0e, 0x57, 0xc8,
- 0x8d, 0xd1, 0xf3, 0x0c, 0xef, 0xff, 0x86, 0x5c, 0xb0, 0x29, 0xbf, 0xbc,
- 0x07, 0xd9, 0xcb, 0xf7, 0x40, 0x31, 0xc4, 0xe5, 0xfc, 0x2f, 0xe9, 0x42,
- 0xa7, 0x2a, 0x0f, 0x59, 0x42, 0x9b, 0xec, 0xcf, 0xa4, 0x72, 0xf6, 0xd2,
- 0x63, 0x96, 0x54, 0x4d, 0xfe, 0xc8, 0xaf, 0xfb, 0x49, 0x1e, 0xce, 0x2e,
- 0x13, 0x97, 0xff, 0x3c, 0xe3, 0x1f, 0x20, 0x46, 0x27, 0x39, 0x5a, 0x45,
- 0x27, 0x49, 0xc4, 0xe6, 0xfd, 0xcb, 0xb1, 0xa9, 0x1c, 0xae, 0x4a, 0xcb,
- 0x62, 0x1e, 0xd8, 0x62, 0xb8, 0x54, 0x3c, 0x60, 0xad, 0x97, 0xde, 0x66,
- 0xe0, 0xe5, 0xfd, 0x3c, 0xd2, 0xe1, 0xb5, 0x39, 0xcb, 0xe6, 0x63, 0xf4,
- 0xe5, 0xa7, 0x39, 0x7e, 0xf7, 0x51, 0x9a, 0x39, 0x52, 0x37, 0x5a, 0x12,
- 0xbd, 0xd0, 0xa1, 0xcb, 0xf7, 0x71, 0x25, 0xb3, 0x97, 0xff, 0xdd, 0x85,
- 0x39, 0xf8, 0x5f, 0xfd, 0xee, 0x3f, 0x29, 0x7e, 0xcf, 0x38, 0x38, 0x73,
- 0x97, 0xed, 0x2d, 0xdd, 0x67, 0x88, 0x11, 0x7b, 0x71, 0xf1, 0xcb, 0x7f,
- 0x87, 0xa3, 0xf1, 0xa5, 0xef, 0x24, 0xe7, 0x2f, 0x4e, 0xe2, 0x72, 0xa4,
- 0x9a, 0xd0, 0x49, 0xfe, 0x54, 0xd3, 0xeb, 0x0a, 0x7c, 0x3b, 0x7f, 0x0a,
- 0xdd, 0x5e, 0xa1, 0xcb, 0xb8, 0x24, 0x72, 0xfb, 0xd3, 0xb8, 0x9c, 0xbc,
- 0x2e, 0xa9, 0xcb, 0xfc, 0xae, 0x4e, 0x0f, 0x71, 0xf1, 0xcb, 0xfe, 0x79,
- 0x6a, 0x27, 0x7d, 0x2c, 0xe5, 0xe5, 0x53, 0xc7, 0x2f, 0x6d, 0xfc, 0x72,
- 0x95, 0x37, 0x3f, 0x0e, 0xdd, 0xcb, 0xa7, 0x2f, 0xe6, 0x79, 0x02, 0x08,
- 0x39, 0x79, 0x9e, 0x59, 0xcb, 0x7a, 0x0f, 0x2b, 0x0b, 0x6f, 0xe8, 0x66,
- 0x2b, 0x1b, 0x39, 0x53, 0xa7, 0xb7, 0x83, 0x4b, 0x22, 0xd0, 0xe3, 0x0e,
- 0x3a, 0xe5, 0xf9, 0x18, 0xb1, 0xf8, 0x9a, 0xed, 0x00, 0xe5, 0xfe, 0x17,
- 0x6f, 0x7b, 0x8f, 0xce, 0x5f, 0xf6, 0xb4, 0x9f, 0x4b, 0xcf, 0xf1, 0xcb,
- 0xcd, 0x1d, 0x53, 0x97, 0xfd, 0x0c, 0x96, 0x4f, 0x80, 0xe1, 0xce, 0x5f,
- 0xf4, 0x7e, 0x92, 0xea, 0x0f, 0xe7, 0x2d, 0x39, 0xcb, 0x9f, 0xda, 0x3c,
- 0xbe, 0x1c, 0xe6, 0xb1, 0x1b, 0x48, 0x3e, 0xf0, 0x89, 0xbc, 0xdc, 0x28,
- 0x72, 0xf3, 0x6d, 0xb6, 0x7a, 0xbe, 0x97, 0x9c, 0x42, 0x5a, 0xbe, 0xae,
- 0x66, 0xb6, 0xfa, 0x40, 0x85, 0x4e, 0x5b, 0xf3, 0x95, 0x86, 0xd5, 0xc8,
- 0xea, 0x15, 0x36, 0x04, 0x5d, 0x0d, 0x35, 0x18, 0xaf, 0x4c, 0xbf, 0x4b,
- 0xf3, 0x85, 0xfe, 0xf7, 0x72, 0x5d, 0x4e, 0x27, 0x2f, 0x99, 0xa0, 0x4e,
- 0x72, 0xff, 0xf8, 0x51, 0x5e, 0x7b, 0xf7, 0x40, 0xf2, 0x94, 0x1c, 0xa8,
- 0x3f, 0x6c, 0x24, 0xa9, 0xd3, 0x36, 0x93, 0x5a, 0xb0, 0xab, 0xbe, 0xc0,
- 0xbc, 0x8e, 0x5f, 0x9c, 0x45, 0x18, 0x72, 0xf6, 0x71, 0x50, 0xe5, 0xc9,
- 0xd3, 0x97, 0x82, 0xf2, 0x39, 0x7c, 0xec, 0xc6, 0x1c, 0xbe, 0x46, 0x43,
- 0x59, 0xcb, 0x93, 0x5c, 0x8f, 0x17, 0x08, 0x68, 0x28, 0xa5, 0xc1, 0x6e,
- 0xb0, 0xdf, 0x91, 0x8e, 0x38, 0x72, 0xb9, 0x32, 0x97, 0x5a, 0xa1, 0xc8,
- 0x37, 0x92, 0xd8, 0x48, 0x72, 0x37, 0x65, 0x56, 0x52, 0x50, 0x43, 0xce,
- 0x10, 0xfe, 0x70, 0x24, 0x3b, 0x25, 0x04, 0x31, 0x1a, 0x17, 0xdf, 0xd9,
- 0xdc, 0x58, 0x30, 0xe5, 0xf9, 0x3d, 0x1e, 0xd9, 0x4b, 0xe5, 0xc7, 0xb6,
- 0x52, 0xe6, 0xdb, 0x29, 0x52, 0x3e, 0x2c, 0x27, 0x6c, 0x8a, 0xcd, 0x94,
- 0xe6, 0x6b, 0xef, 0x38, 0xfe, 0x72, 0xb0, 0xf0, 0x15, 0x24, 0xbe, 0x98,
- 0x5d, 0xb3, 0x97, 0xa6, 0xea, 0x1c, 0xbf, 0xfe, 0xf4, 0x2f, 0x30, 0x7d,
- 0xd4, 0x81, 0x9c, 0xe5, 0x1c, 0xac, 0x3d, 0x8d, 0xa6, 0xd4, 0xc9, 0xec,
- 0x7f, 0x0f, 0xd1, 0x22, 0xd9, 0x1b, 0x6e, 0xb7, 0xff, 0x86, 0x3e, 0xff,
- 0x06, 0x25, 0xad, 0x41, 0xcb, 0xff, 0x7b, 0x78, 0xbe, 0xb8, 0xfb, 0x67,
- 0x2f, 0x20, 0xfe, 0x73, 0x91, 0xbe, 0xb4, 0x31, 0x16, 0xbc, 0x61, 0x0f,
- 0x7f, 0xa7, 0x8e, 0xc7, 0x62, 0x73, 0x97, 0x3e, 0xce, 0x5b, 0xb0, 0x79,
- 0x4e, 0x69, 0x7e, 0x97, 0x41, 0x1a, 0x39, 0x7f, 0xf3, 0xb3, 0x51, 0xc5,
- 0x38, 0x88, 0x36, 0x72, 0xbe, 0x3e, 0xfe, 0x94, 0x5f, 0xb0, 0x0c, 0x8d,
- 0x9c, 0xa3, 0x97, 0x64, 0xda, 0x36, 0x5b, 0x27, 0xbf, 0xe4, 0x07, 0x0f,
- 0xd8, 0x50, 0x67, 0x39, 0x7f, 0xd1, 0x3c, 0x7d, 0xe1, 0xc9, 0xce, 0x56,
- 0x22, 0x99, 0x65, 0xa8, 0x7f, 0x7f, 0xf2, 0x9b, 0x4d, 0xcc, 0x81, 0xc1,
- 0xfc, 0xe5, 0xf3, 0x06, 0x3e, 0x39, 0x41, 0x3e, 0x87, 0x46, 0xa9, 0x93,
- 0xb2, 0xd4, 0x3e, 0xfb, 0x09, 0x6b, 0xec, 0xee, 0x4e, 0x72, 0xf4, 0x9f,
- 0x47, 0x2f, 0xef, 0xd8, 0xf2, 0xc0, 0x9c, 0xbe, 0xcf, 0x60, 0x4a, 0x5f,
- 0x3a, 0xbf, 0xb6, 0x72, 0xa4, 0x78, 0xc2, 0x43, 0x7d, 0x02, 0x30, 0x72,
- 0xa6, 0x46, 0x86, 0x87, 0x3c, 0xe8, 0xa1, 0x0d, 0xf7, 0xfb, 0x66, 0x8e,
- 0x52, 0xa9, 0xaa, 0xa4, 0x3c, 0xbc, 0x7f, 0x7f, 0xc3, 0x9d, 0xce, 0x5d,
- 0xc9, 0xce, 0x5f, 0xff, 0xfd, 0xfc, 0x0a, 0xdf, 0xcf, 0xf7, 0xff, 0x79,
- 0x19, 0xbe, 0xc2, 0x82, 0x72, 0xfe, 0x07, 0x0e, 0x9a, 0xd6, 0x1c, 0xbe,
- 0xf2, 0xb9, 0xd3, 0x97, 0xfe, 0x1c, 0xf7, 0x81, 0x3f, 0xb1, 0x67, 0x2f,
- 0xc1, 0x03, 0xea, 0x47, 0x2d, 0xb3, 0x97, 0x27, 0xe7, 0x2e, 0xea, 0x1c,
- 0xb8, 0x1b, 0xe4, 0x6b, 0x66, 0x17, 0xa7, 0x3e, 0xef, 0xcf, 0xae, 0xfe,
- 0x0e, 0x5d, 0xfc, 0x1c, 0xbf, 0x02, 0x58, 0x3c, 0xd0, 0xd7, 0x7e, 0x2f,
- 0x50, 0x9c, 0x3a, 0xa4, 0x68, 0x7f, 0xfc, 0x25, 0x85, 0x42, 0xff, 0xfb,
- 0x05, 0xfe, 0xda, 0xaa, 0xbf, 0x25, 0xb3, 0xf3, 0x97, 0xff, 0x7b, 0xb8,
- 0xc5, 0x23, 0xfc, 0xfb, 0xc7, 0x2f, 0xf7, 0xcb, 0x4d, 0x29, 0x01, 0x39,
- 0x7d, 0xfb, 0x1e, 0x5c, 0x91, 0xa3, 0xb5, 0x5f, 0x23, 0xdc, 0x0f, 0x1c,
- 0xbf, 0xbf, 0x62, 0x9b, 0x52, 0x73, 0x97, 0xf6, 0xd0, 0x46, 0x3e, 0x39,
- 0x76, 0x7c, 0x72, 0xbe, 0x3f, 0x6f, 0x19, 0xb4, 0x2c, 0xbe, 0xff, 0x49,
- 0xa3, 0x95, 0x09, 0x96, 0x49, 0x29, 0xe1, 0x1a, 0xd9, 0x95, 0xe0, 0x7d,
- 0xe3, 0x96, 0x73, 0x95, 0xb3, 0x5d, 0xe1, 0xeb, 0xb1, 0xb3, 0x97, 0xfd,
- 0x1f, 0x67, 0xf1, 0xc7, 0x27, 0x39, 0x7f, 0x0e, 0x7b, 0x6f, 0xf9, 0xca,
- 0xd2, 0x20, 0x3f, 0x17, 0xd9, 0xe5, 0xff, 0x44, 0xfb, 0xd6, 0x2e, 0x27,
- 0x39, 0x7f, 0xb0, 0x67, 0xc0, 0xbf, 0x4e, 0x54, 0xc7, 0xd8, 0xd9, 0xd5,
- 0xfd, 0x8c, 0xc0, 0xa3, 0x67, 0x2e, 0x64, 0x1c, 0xa6, 0x1e, 0x1b, 0x96,
- 0xdf, 0xc3, 0x93, 0x75, 0x3c, 0x72, 0xfb, 0x33, 0xbb, 0x39, 0x58, 0x8d,
- 0x67, 0x67, 0xf1, 0x0f, 0x01, 0x6d, 0xe6, 0xdb, 0x6c, 0xa5, 0xfb, 0x15,
- 0x10, 0x6c, 0xa7, 0x33, 0x41, 0x7d, 0xcd, 0xb6, 0xdb, 0x39, 0x76, 0x7e,
- 0x72, 0xb0, 0xdf, 0xf8, 0xa2, 0xa1, 0x13, 0x3e, 0x79, 0xbf, 0xfe, 0x49,
- 0x3e, 0xd8, 0xc7, 0x93, 0xab, 0xd4, 0x39, 0x7c, 0x9a, 0xff, 0x67, 0x2f,
- 0xfb, 0x7a, 0x80, 0x78, 0x53, 0x89, 0xcb, 0xff, 0x0e, 0x6d, 0x7d, 0x45,
- 0xc0, 0x9c, 0xbf, 0xff, 0xca, 0xb6, 0xfa, 0x57, 0x9e, 0xf2, 0x42, 0x07,
- 0xde, 0x09, 0xca, 0x84, 0x6d, 0x61, 0xd2, 0x1e, 0x5f, 0xda, 0x02, 0xfa,
- 0x9b, 0x39, 0x7c, 0xdb, 0x8c, 0x8e, 0x5f, 0xf7, 0xa3, 0xef, 0xdf, 0xbd,
- 0x43, 0x96, 0xe9, 0xca, 0xc3, 0xcb, 0x59, 0xd5, 0xf6, 0xd1, 0x90, 0x72,
- 0xfc, 0x39, 0xe8, 0xd1, 0xcb, 0xcd, 0xb6, 0xd9, 0x4b, 0xf3, 0xab, 0xd4,
- 0xf1, 0x4e, 0x66, 0x82, 0xa1, 0x10, 0x08, 0x8d, 0x7b, 0x8c, 0x30, 0xe5,
- 0xef, 0x23, 0x67, 0x2f, 0x6d, 0xf4, 0x72, 0xbe, 0x37, 0x3e, 0x1d, 0xbd,
- 0xd8, 0x09, 0xca, 0xc4, 0x4a, 0xa2, 0xbb, 0x91, 0x5f, 0xb3, 0xfc, 0xc9,
- 0x8e, 0x5b, 0x7c, 0x93, 0xcd, 0xf8, 0x87, 0x50, 0xa1, 0xec, 0x2d, 0x84,
- 0xb6, 0xd2, 0x0a, 0xa9, 0x7c, 0x94, 0x75, 0x5c, 0x32, 0xaf, 0x60, 0x4a,
- 0xc5, 0xbf, 0x70, 0xfd, 0x89, 0xc0, 0x72, 0xff, 0xe4, 0xf4, 0x6b, 0x07,
- 0xce, 0xe2, 0x72, 0xa6, 0x5c, 0xbf, 0xec, 0x3f, 0x46, 0x59, 0x18, 0x0c,
- 0x78, 0x97, 0x5e, 0x8e, 0x30, 0x72, 0xb1, 0x76, 0x19, 0x27, 0x43, 0x85,
- 0x6e, 0xf0, 0xc7, 0x13, 0x97, 0xff, 0x6a, 0x17, 0xd1, 0x7f, 0x0c, 0x36,
- 0x72, 0xee, 0x1d, 0x0e, 0x5c, 0x9d, 0x39, 0x53, 0x9b, 0x1d, 0x0d, 0xd4,
- 0x22, 0x59, 0xdd, 0x2f, 0xbd, 0xb0, 0x35, 0x9c, 0xbf, 0xd0, 0x32, 0x14,
- 0x8f, 0x8e, 0x54, 0x36, 0x99, 0x12, 0x8c, 0x1c, 0x2f, 0x39, 0x29, 0x1d,
- 0x58, 0xe4, 0x56, 0x6d, 0xf1, 0xd2, 0x3a, 0xea, 0x3b, 0x9e, 0xca, 0x4c,
- 0x77, 0x0f, 0xe1, 0x42, 0x31, 0xb9, 0xee, 0x1e, 0xfe, 0x9d, 0xa8, 0xe2,
- 0x70, 0xd2, 0x16, 0x6a, 0x10, 0xf0, 0x13, 0x5f, 0x92, 0x69, 0x20, 0x9c,
- 0xb9, 0xa9, 0x43, 0x97, 0xfd, 0x37, 0xb8, 0x37, 0x13, 0x03, 0x47, 0x2f,
- 0xf0, 0x60, 0x59, 0x01, 0x83, 0x95, 0x07, 0xe0, 0xe7, 0xf7, 0xff, 0x08,
- 0xbf, 0xde, 0xec, 0x2f, 0x26, 0x39, 0x7f, 0x4f, 0x02, 0x8c, 0xc3, 0x97,
- 0xff, 0x62, 0x76, 0x03, 0xd0, 0x47, 0xdb, 0x39, 0x78, 0x2a, 0xfe, 0x72,
- 0xfc, 0xcd, 0x69, 0xfc, 0x72, 0xb9, 0x1e, 0x3c, 0x0f, 0xdf, 0xfd, 0x33,
- 0xaf, 0xb1, 0x2f, 0x0e, 0x30, 0xe5, 0xfd, 0xac, 0x11, 0x79, 0xce, 0x52,
- 0xcf, 0xc1, 0x11, 0x2f, 0xfe, 0x86, 0xfe, 0x96, 0xf9, 0x67, 0x70, 0x4e,
- 0x5f, 0xff, 0x23, 0x3e, 0x96, 0xf9, 0x60, 0x8e, 0x27, 0xe7, 0x2f, 0x27,
- 0x40, 0x72, 0xb9, 0x2b, 0x35, 0x6a, 0x89, 0xe5, 0x08, 0xbc, 0x20, 0x44,
- 0x4d, 0x16, 0x76, 0x11, 0x6f, 0x09, 0x31, 0x21, 0xf2, 0x3f, 0x15, 0x1b,
- 0x73, 0x6a, 0xa5, 0x06, 0x5c, 0x35, 0x30, 0x8f, 0xe1, 0x21, 0xb6, 0xd5,
- 0xc6, 0x93, 0xc3, 0x42, 0x93, 0x85, 0xe3, 0x6c, 0x6a, 0x31, 0x91, 0xb5,
- 0x03, 0xbe, 0x15, 0x0a, 0x18, 0xad, 0x1f, 0x27, 0x9e, 0xf5, 0x95, 0x33,
- 0x30, 0x34, 0xde, 0xec, 0xbc, 0x86, 0x75, 0x67, 0x16, 0xd7, 0x58, 0x24,
- 0x7d, 0x4c, 0xdf, 0x4a, 0x71, 0xf3, 0x5c, 0x79, 0xb3, 0x56, 0x24, 0x1a,
- 0xac, 0xb3, 0x99, 0x4b, 0xba, 0xed, 0xa1, 0x4a, 0x7b, 0x49, 0x25, 0xfd,
- 0x36, 0x0f, 0x87, 0x8c, 0x84, 0x6b, 0xf6, 0xbd, 0xde, 0x6d, 0x17, 0xad,
- 0x7c, 0xb0, 0x27, 0xac, 0x38, 0xcb, 0x48, 0x6e, 0x5d, 0x03, 0x4a, 0x56,
- 0x32, 0x95, 0xbc, 0x1f, 0x04, 0xe3, 0xed, 0x73, 0x94, 0x20, 0x87, 0x2d,
- 0x41, 0xa1, 0x57, 0x99, 0x9e, 0x39, 0x7f, 0x9d, 0x91, 0xe4, 0xda, 0x1c,
- 0xbf, 0x66, 0x94, 0xf6, 0xce, 0x5b, 0x9f, 0xe7, 0xec, 0x23, 0x9b, 0x31,
- 0xbf, 0xdc, 0xf3, 0x4b, 0x77, 0x59, 0xa2, 0xe3, 0x5f, 0xee, 0x79, 0xa5,
- 0xbb, 0xac, 0xd1, 0x75, 0xaf, 0xfe, 0xe6, 0xf2, 0xe7, 0x9a, 0x5b, 0xba,
- 0xcd, 0x12, 0x8a, 0xa2, 0x50, 0xb8, 0x4c, 0xa1, 0x4e, 0x12, 0xa5, 0x61,
- 0x26, 0xb2, 0x94, 0x95, 0x04, 0xd7, 0x09, 0xc7, 0xd4, 0x21, 0x3b, 0xfc,
- 0x2d, 0x36, 0x6f, 0xe4, 0x1e, 0x04, 0x1b, 0xff, 0xdc, 0xd8, 0xf2, 0xe7,
- 0x9a, 0x5b, 0xba, 0xcd, 0x12, 0xd2, 0xff, 0xb8, 0x5b, 0xa8, 0xd6, 0xf1,
- 0xf7, 0x01, 0xcb, 0xf6, 0x96, 0xee, 0xb3, 0x44, 0x6e, 0xbf, 0xe4, 0xd2,
- 0x70, 0xeb, 0xec, 0x36, 0x72, 0xff, 0xff, 0xfb, 0x88, 0xe6, 0xf6, 0x18,
- 0xcd, 0x2d, 0xdd, 0x7c, 0xe4, 0x9e, 0x8f, 0x6c, 0xd1, 0x87, 0xad, 0xd8,
- 0x46, 0x52, 0x1f, 0x5f, 0xb5, 0x0d, 0xb0, 0x27, 0x2f, 0xfc, 0xf2, 0xe7,
- 0x9a, 0x5b, 0xba, 0xcd, 0x12, 0xfa, 0xfe, 0x8f, 0x29, 0xd7, 0xf1, 0xcb,
- 0xf9, 0x4d, 0x2b, 0xd0, 0x6c, 0xe5, 0xe8, 0xd4, 0x1c, 0xac, 0x3c, 0xc4,
- 0x31, 0xbf, 0xee, 0xe2, 0x6a, 0x5d, 0x46, 0xce, 0x5f, 0x03, 0xa9, 0xa3,
- 0x97, 0xa6, 0xde, 0x8e, 0x5b, 0x9b, 0x50, 0x55, 0xe7, 0x88, 0xcb, 0x87,
- 0xf6, 0x89, 0xd8, 0x53, 0xd4, 0xc1, 0x7a, 0xf1, 0x03, 0x43, 0x95, 0x08,
- 0xaf, 0xff, 0x7d, 0x2f, 0x24, 0xdc, 0xc2, 0x9c, 0x60, 0x27, 0x2f, 0xf7,
- 0x3c, 0xd2, 0xdd, 0xd6, 0x68, 0xaa, 0xd7, 0x27, 0x01, 0xcb, 0xb3, 0x47,
- 0x2f, 0x91, 0x8f, 0xc4, 0xe5, 0x2a, 0x7a, 0x4e, 0x33, 0xe1, 0x6b, 0xc3,
- 0xc0, 0xd9, 0xcb, 0xfb, 0xb1, 0xc4, 0x01, 0xc3, 0x97, 0xf3, 0xf6, 0x61,
- 0x80, 0x9c, 0xbf, 0xfb, 0xdd, 0x8d, 0x8b, 0x83, 0x87, 0x4d, 0x1c, 0xbd,
- 0x12, 0xc3, 0x95, 0x24, 0x5f, 0x84, 0xbf, 0xe2, 0xd9, 0x92, 0x2f, 0xf9,
- 0x5c, 0x1c, 0xfb, 0xce, 0xc3, 0x97, 0xb8, 0x23, 0xc7, 0x2f, 0xf6, 0xa1,
- 0x8a, 0x40, 0xac, 0xe5, 0xef, 0x9f, 0xe3, 0x97, 0xcf, 0xe7, 0xf8, 0xe5,
- 0xc1, 0x43, 0x97, 0xf6, 0x69, 0x6e, 0xeb, 0x34, 0x48, 0x0a, 0xe4, 0x79,
- 0xfc, 0xc5, 0xaf, 0xdb, 0x71, 0x7f, 0x8e, 0x5c, 0x08, 0x39, 0x52, 0x3e,
- 0x3f, 0x89, 0xb4, 0x4f, 0x7f, 0xa5, 0x1a, 0x9e, 0x35, 0x39, 0xcb, 0xfd,
- 0xa9, 0xd9, 0x03, 0x2d, 0x9c, 0xa8, 0x3e, 0x9c, 0x35, 0xbd, 0x3b, 0x84,
- 0xe5, 0xfe, 0x5a, 0x63, 0x60, 0x1f, 0x1c, 0xac, 0x3d, 0x0f, 0x87, 0x6e,
- 0xe1, 0x3a, 0x72, 0xff, 0xf6, 0x4d, 0xd7, 0x67, 0xbb, 0x1e, 0x03, 0x0e,
- 0x54, 0xeb, 0x8b, 0x81, 0x2f, 0xc8, 0x6f, 0xaa, 0x7e, 0xd6, 0x73, 0x30,
- 0xfb, 0x0c, 0xfa, 0x3c, 0xf0, 0xd4, 0x18, 0x4c, 0xf9, 0xc1, 0xa1, 0x12,
- 0x83, 0x97, 0xe8, 0x11, 0xcf, 0x1c, 0xbe, 0xd6, 0x91, 0x67, 0x2f, 0x87,
- 0x27, 0xe6, 0xd0, 0xf1, 0xd4, 0x25, 0xbf, 0xdc, 0xfa, 0xec, 0xc8, 0x09,
- 0xca, 0xe6, 0x9c, 0x1e, 0xa3, 0x11, 0x68, 0x7d, 0x7f, 0xb9, 0xe6, 0x96,
- 0xee, 0xb3, 0x45, 0x90, 0xbf, 0xdc, 0xf3, 0x4b, 0x77, 0x59, 0xa2, 0xd7,
- 0x5f, 0xfe, 0xc5, 0x22, 0x7e, 0x79, 0x37, 0x83, 0x02, 0x72, 0xff, 0x73,
- 0xcd, 0x2d, 0xdd, 0x66, 0x8b, 0x91, 0x7e, 0xd2, 0xdd, 0xd6, 0x68, 0xbb,
- 0x17, 0xfe, 0x79, 0x73, 0xcd, 0x2d, 0xdd, 0x66, 0x8a, 0x39, 0x6e, 0x78,
- 0x88, 0x06, 0x1a, 0x5f, 0x0c, 0x49, 0x87, 0x2f, 0xfd, 0xc3, 0x70, 0x8c,
- 0x8d, 0x4b, 0x13, 0x89, 0xcb, 0x48, 0xe5, 0xfb, 0x4b, 0x77, 0x59, 0xa2,
- 0x95, 0x5f, 0xf2, 0xfa, 0x93, 0x76, 0x27, 0xc3, 0x97, 0xff, 0xbb, 0x13,
- 0xc7, 0x53, 0x8b, 0x87, 0xa8, 0x73, 0x99, 0xba, 0xba, 0x5c, 0xf1, 0x19,
- 0x73, 0x37, 0x57, 0xc9, 0x86, 0xbc, 0x37, 0x2f, 0xfc, 0xe9, 0xe9, 0x00,
- 0x2e, 0x3f, 0x9c, 0xb7, 0x30, 0xa7, 0xbf, 0xf1, 0x0b, 0x23, 0x57, 0xe9,
- 0x4d, 0x4e, 0xce, 0xd1, 0x94, 0xb4, 0xdc, 0x85, 0x0f, 0xca, 0x09, 0x3c,
- 0xe4, 0xc3, 0xbf, 0xd0, 0x45, 0x07, 0x69, 0xbe, 0x86, 0x0f, 0x19, 0x41,
- 0x37, 0xfd, 0x2e, 0x79, 0xa5, 0xbb, 0xac, 0xd1, 0x1c, 0x2f, 0xf9, 0x39,
- 0xe6, 0x96, 0xee, 0xb3, 0x45, 0x6a, 0xb7, 0x37, 0x44, 0x6f, 0x91, 0xef,
- 0xff, 0x73, 0x63, 0xcb, 0x9e, 0x69, 0x6e, 0xeb, 0x34, 0x4b, 0x6b, 0xc0,
- 0xd7, 0xe7, 0x2e, 0xcf, 0x8e, 0x5f, 0xe0, 0xe3, 0x19, 0x09, 0xb3, 0x97,
- 0xb8, 0x82, 0x47, 0x29, 0x68, 0x86, 0xf8, 0x79, 0x05, 0xf8, 0x99, 0x5e,
- 0xe8, 0x64, 0x72, 0xff, 0xb3, 0xe1, 0xcf, 0xff, 0x79, 0x1c, 0xb9, 0x8b,
- 0x39, 0x7f, 0xb1, 0x3e, 0xd8, 0x70, 0x4e, 0x54, 0x22, 0x0e, 0x47, 0x5a,
- 0x17, 0xbe, 0x18, 0xfa, 0x47, 0x2f, 0xe9, 0xe1, 0x6f, 0xaf, 0xce, 0x5f,
- 0xff, 0x9f, 0xef, 0xc3, 0xd7, 0x96, 0x6c, 0x40, 0xea, 0x1c, 0xbe, 0xff,
- 0x35, 0x31, 0xca, 0x5a, 0x33, 0x34, 0x45, 0xd2, 0xff, 0xd5, 0xec, 0xa9,
- 0xcb, 0xf9, 0x34, 0x29, 0xed, 0x9c, 0xbf, 0x69, 0xc7, 0x20, 0xe5, 0x1a,
- 0x21, 0xb2, 0x1f, 0x1f, 0x44, 0x9c, 0xb2, 0xe8, 0x13, 0x97, 0xb1, 0x02,
- 0x72, 0xf0, 0x71, 0x87, 0x2e, 0x41, 0x09, 0xb7, 0x41, 0xba, 0x83, 0xf6,
- 0x92, 0x65, 0xf6, 0x4d, 0x2c, 0x39, 0x7f, 0xe7, 0x97, 0x3c, 0xd2, 0xdd,
- 0xd6, 0x68, 0x98, 0x17, 0x9b, 0x4f, 0xce, 0x5f, 0x6d, 0xc7, 0xf3, 0x95,
- 0x31, 0xe0, 0x7e, 0x3d, 0x7f, 0x81, 0xf6, 0x92, 0x19, 0x87, 0x2f, 0xdd,
- 0x48, 0x19, 0xce, 0x5f, 0xf4, 0x4f, 0xe1, 0x80, 0x7b, 0x67, 0x2d, 0xee,
- 0xa2, 0x4f, 0x66, 0x6d, 0x09, 0xef, 0xbe, 0x5a, 0x2a, 0x72, 0xb0, 0xf7,
- 0x3c, 0x71, 0x7f, 0x27, 0xb1, 0x91, 0xd3, 0x97, 0xff, 0x46, 0x93, 0xf9,
- 0xfb, 0x1b, 0x06, 0xce, 0x56, 0x8f, 0xcb, 0xc5, 0x97, 0xfe, 0xc6, 0x66,
- 0xb3, 0xe9, 0x67, 0x8e, 0x5f, 0xc9, 0xd4, 0x66, 0x2a, 0x72, 0xba, 0x7d,
- 0x7b, 0x3e, 0xbf, 0xfc, 0xf3, 0xf5, 0x20, 0x72, 0x64, 0xd2, 0x1c, 0xac,
- 0x47, 0xbf, 0xa1, 0x1a, 0xd9, 0x15, 0xcb, 0xc3, 0x97, 0x03, 0xf2, 0x94,
- 0x86, 0xbb, 0x42, 0xd7, 0xe5, 0x62, 0x58, 0x13, 0x97, 0xfb, 0x02, 0x39,
- 0xee, 0xe1, 0xcb, 0xb8, 0x65, 0x9e, 0x30, 0xa5, 0xf9, 0x46, 0x8e, 0x3f,
- 0x9c, 0xbf, 0xb3, 0xae, 0xa0, 0xf8, 0xe5, 0x4e, 0x7b, 0x01, 0x2b, 0xbf,
- 0xb3, 0xde, 0x8d, 0x6c, 0xe5, 0xfc, 0xe3, 0xfc, 0xff, 0xf8, 0xe5, 0x42,
- 0x20, 0x04, 0x8d, 0xa1, 0x6d, 0xb9, 0xc3, 0x22, 0xae, 0x73, 0xf0, 0xc2,
- 0x83, 0x21, 0xf6, 0xb8, 0x50, 0xfd, 0x0b, 0x7d, 0x10, 0xb0, 0x89, 0xe1,
- 0x18, 0x31, 0x89, 0xee, 0x38, 0xaf, 0x31, 0x80, 0x83, 0x89, 0x43, 0x66,
- 0x2a, 0x46, 0x03, 0x79, 0x80, 0xd1, 0x4b, 0xff, 0x3c, 0xb9, 0xe6, 0x96,
- 0xee, 0xb3, 0x44, 0xc6, 0xbe, 0x8d, 0x47, 0x01, 0xcb, 0x73, 0x44, 0x46,
- 0xb0, 0x77, 0xa9, 0x97, 0xfc, 0x14, 0xe3, 0xcf, 0xef, 0xd4, 0x91, 0xcb,
- 0xe8, 0x9e, 0x34, 0x72, 0xf7, 0xa2, 0x63, 0x97, 0xec, 0x89, 0x91, 0x87,
- 0x29, 0x0f, 0x9a, 0x62, 0x2d, 0x0e, 0xdf, 0xc1, 0x64, 0x67, 0xb6, 0x72,
- 0xff, 0x76, 0x35, 0x3a, 0x80, 0xfc, 0xe5, 0xf0, 0x27, 0x71, 0x39, 0x73,
- 0xec, 0xe5, 0xf7, 0x2f, 0x67, 0x4e, 0x5a, 0x3a, 0x6e, 0xb6, 0x2d, 0x7a,
- 0x06, 0x73, 0x97, 0xff, 0xff, 0xd2, 0xdf, 0x70, 0x0d, 0xef, 0xb8, 0xbc,
- 0xdf, 0x2c, 0xfa, 0x5b, 0x41, 0x43, 0x97, 0x9d, 0xd6, 0x68, 0xac, 0x57,
- 0xce, 0xa4, 0x2a, 0x72, 0x96, 0x79, 0x7a, 0x28, 0xbf, 0xf3, 0x4c, 0xf0,
- 0xe0, 0x20, 0x7c, 0x72, 0xff, 0x0e, 0x6f, 0xfc, 0xc0, 0x9c, 0xa5, 0x53,
- 0x9f, 0x59, 0x37, 0xc3, 0x9a, 0x86, 0x5f, 0x88, 0xb8, 0x9f, 0x5f, 0xfc,
- 0xa8, 0x3d, 0xb1, 0xce, 0x23, 0x9b, 0x39, 0x7f, 0xf0, 0xf9, 0x50, 0x40,
- 0xe2, 0xe3, 0x47, 0x2f, 0xf6, 0xa7, 0xf6, 0xdf, 0xe5, 0x9c, 0xa8, 0x3f,
- 0x97, 0x43, 0xbf, 0xe9, 0x67, 0xb0, 0x61, 0xb6, 0x87, 0x2f, 0xdc, 0x1e,
- 0xcf, 0xa6, 0x39, 0x7f, 0xff, 0xff, 0x9f, 0xde, 0xce, 0xed, 0xe4, 0x83,
- 0xe9, 0x66, 0xb3, 0x79, 0xd7, 0x9c, 0x62, 0x47, 0x2a, 0x11, 0x71, 0xb2,
- 0xdb, 0xf8, 0x0d, 0x17, 0xd4, 0xe1, 0xce, 0x5f, 0xd9, 0xbf, 0xa5, 0x1d,
- 0x39, 0x74, 0x71, 0x39, 0x5d, 0x3c, 0x61, 0x2e, 0xbf, 0xd3, 0x3e, 0x24,
- 0x94, 0x61, 0xca, 0x09, 0xea, 0xa1, 0x0d, 0xff, 0x47, 0xd2, 0x9a, 0x4f,
- 0xa9, 0xce, 0x54, 0x26, 0x5b, 0x90, 0xd0, 0x42, 0x1b, 0xd1, 0x2f, 0x1c,
- 0xbf, 0xf6, 0x07, 0x48, 0x09, 0xff, 0xdc, 0x8e, 0x5f, 0x31, 0xfe, 0xf1,
- 0xcb, 0xff, 0xa7, 0x8f, 0x72, 0x51, 0x6a, 0x70, 0x29, 0xb3, 0x97, 0xfd,
- 0xa8, 0xdb, 0xe8, 0x62, 0x47, 0x2b, 0x48, 0x86, 0xe2, 0x9f, 0x7a, 0x4f,
- 0x39, 0xcb, 0xdc, 0xa7, 0x61, 0xcb, 0x83, 0xe3, 0x95, 0xc3, 0x26, 0x45,
- 0x90, 0xa9, 0xf8, 0x95, 0x07, 0x44, 0x82, 0xff, 0xc2, 0xe1, 0xec, 0x71,
- 0xeb, 0x89, 0xcb, 0xff, 0xff, 0x02, 0x7c, 0x5f, 0x21, 0x07, 0x07, 0x2c,
- 0xfa, 0x58, 0x01, 0xff, 0x67, 0x2f, 0xff, 0x4f, 0x9f, 0x7b, 0x68, 0x31,
- 0xfb, 0xb0, 0xe5, 0xfe, 0xf8, 0x70, 0x3d, 0x76, 0xce, 0x56, 0x1f, 0xfb,
- 0xa5, 0xd0, 0x53, 0x53, 0x13, 0xed, 0xc3, 0xd6, 0xfe, 0x9e, 0x69, 0x70,
- 0xda, 0x9c, 0xe5, 0xf0, 0x8e, 0x78, 0xe5, 0xf9, 0x1a, 0xf5, 0xa4, 0x39,
- 0x4d, 0x52, 0x20, 0x60, 0xdf, 0xa4, 0x17, 0xf4, 0xea, 0x34, 0x71, 0xfc,
- 0xe5, 0xf3, 0x5c, 0x6c, 0x4e, 0x5f, 0xfb, 0xae, 0xcf, 0x76, 0x3c, 0x06,
- 0x1c, 0xac, 0x3e, 0x39, 0x89, 0x2f, 0xfe, 0xcc, 0x55, 0x90, 0x9a, 0xd2,
- 0x36, 0x72, 0xff, 0x92, 0x49, 0xd0, 0x31, 0x88, 0x72, 0xec, 0xf1, 0xca,
- 0x84, 0xd2, 0x72, 0x12, 0xba, 0x22, 0xf2, 0x23, 0x43, 0x8b, 0xc2, 0xfc,
- 0x07, 0x2f, 0x75, 0x39, 0xc3, 0x30, 0x22, 0x72, 0xf9, 0x16, 0x84, 0xdf,
- 0x23, 0xfb, 0x55, 0x85, 0x70, 0xbf, 0xf8, 0x83, 0x50, 0xf2, 0xec, 0x69,
- 0xee, 0x66, 0x23, 0x9b, 0x8d, 0x8f, 0xd1, 0xd3, 0x34, 0x85, 0xb2, 0x91,
- 0xbe, 0xf0, 0x28, 0x5e, 0xe1, 0x66, 0x8d, 0x51, 0xcb, 0xa4, 0x27, 0x2f,
- 0xed, 0x6a, 0x03, 0x8c, 0x39, 0x7d, 0x3e, 0xa2, 0x73, 0x97, 0x29, 0xf9,
- 0xcb, 0xbf, 0xd9, 0xcb, 0xdd, 0x46, 0x1c, 0xb4, 0xc7, 0x29, 0x0f, 0x19,
- 0xc6, 0x00, 0x39, 0x7e, 0x71, 0x9c, 0x1b, 0x39, 0x7f, 0xd0, 0x1e, 0xe0,
- 0x74, 0xeb, 0x39, 0x48, 0x99, 0xeb, 0x96, 0xfe, 0x48, 0x2b, 0xfb, 0x2d,
- 0xf1, 0x45, 0xba, 0x72, 0xf6, 0xd4, 0xd9, 0xcb, 0xef, 0xa7, 0x85, 0x4e,
- 0x54, 0xe7, 0xa8, 0x11, 0x10, 0x0f, 0x5d, 0xe8, 0x39, 0x7f, 0xbe, 0xd4,
- 0x24, 0x9f, 0x67, 0x2f, 0xb0, 0x62, 0x47, 0x2b, 0x0f, 0x4d, 0x86, 0x76,
- 0x68, 0x72, 0xff, 0x67, 0xfb, 0xcf, 0x26, 0x8e, 0x5f, 0x03, 0xd9, 0xb3,
- 0x97, 0x0b, 0x59, 0xcb, 0xda, 0x71, 0x39, 0x6f, 0x8e, 0x54, 0x1a, 0xd0,
- 0x0d, 0xdf, 0xb3, 0x52, 0x86, 0x1c, 0xbf, 0xcf, 0xa9, 0x7e, 0x9f, 0x6c,
- 0xe5, 0xf6, 0xf7, 0x1f, 0x9c, 0xa8, 0x4d, 0xb8, 0x24, 0x38, 0x26, 0x86,
- 0x6c, 0x22, 0xea, 0x33, 0x90, 0x00, 0x9d, 0xb3, 0x5b, 0xf9, 0x04, 0x73,
- 0x8b, 0x9c, 0xbd, 0x25, 0x3c, 0x72, 0xfa, 0x5f, 0x82, 0x47, 0x2f, 0xb4,
- 0xa4, 0x7e, 0x72, 0xa0, 0xf2, 0x10, 0x92, 0xff, 0x24, 0xee, 0xcf, 0xff,
- 0x83, 0x97, 0x20, 0x4e, 0x5f, 0xf2, 0x2f, 0xb9, 0x30, 0xc0, 0x4e, 0x5f,
- 0x4b, 0xd8, 0xa1, 0xcb, 0xcb, 0x8f, 0xce, 0x5e, 0xd4, 0x30, 0xe5, 0x39,
- 0xee, 0x00, 0x8d, 0xb1, 0xdb, 0xe9, 0xd4, 0xc9, 0x8e, 0x5e, 0x8d, 0x4e,
- 0x72, 0xa0, 0xf0, 0x90, 0x96, 0xf4, 0x0c, 0x8e, 0x5f, 0x78, 0x53, 0x80,
- 0xe5, 0x05, 0x53, 0x0f, 0xc5, 0x93, 0x33, 0x68, 0x81, 0x86, 0xbd, 0x16,
- 0x18, 0x4a, 0x6d, 0xc7, 0xc4, 0x00, 0x1b, 0xbf, 0xdd, 0x79, 0x70, 0x70,
- 0x02, 0x73, 0x97, 0x75, 0xa1, 0xcb, 0xff, 0x46, 0x6f, 0x94, 0x20, 0x54,
- 0x91, 0xcb, 0xf9, 0x1b, 0xdc, 0xf8, 0xd9, 0xca, 0x13, 0xf0, 0xf2, 0x05,
- 0xfa, 0x03, 0xec, 0x59, 0xcb, 0xd0, 0x2b, 0x39, 0x7f, 0xff, 0x3b, 0x61,
- 0x77, 0xd4, 0xfd, 0x7f, 0x75, 0x35, 0x23, 0x95, 0xd3, 0xf7, 0x11, 0xba,
- 0x92, 0x38, 0x36, 0x43, 0xe8, 0x4f, 0x5f, 0x38, 0xbc, 0xc7, 0x2f, 0xc9,
- 0xe1, 0xc9, 0x1c, 0xbe, 0x86, 0xe2, 0x63, 0x97, 0x28, 0xc3, 0x97, 0xf7,
- 0x85, 0xff, 0xc1, 0x39, 0x7e, 0x17, 0xff, 0x04, 0xe5, 0x81, 0xc8, 0xf4,
- 0xbc, 0x59, 0x53, 0xa3, 0xf9, 0x52, 0x14, 0x26, 0xe9, 0x18, 0xb5, 0x5f,
- 0xe8, 0x6c, 0x20, 0x7d, 0x48, 0xe5, 0xfc, 0x9a, 0xfb, 0x71, 0x23, 0x96,
- 0xe2, 0x72, 0xb4, 0x7e, 0xbd, 0x34, 0xe0, 0x2e, 0xbc, 0x28, 0xa9, 0xcb,
- 0xec, 0x0a, 0x71, 0x39, 0x74, 0x33, 0x0d, 0xfb, 0x8e, 0x5f, 0xf6, 0x36,
- 0xff, 0x76, 0x14, 0x13, 0x96, 0xd9, 0xca, 0x43, 0xf5, 0xd1, 0x53, 0x9d,
- 0x5b, 0xe3, 0x97, 0x7f, 0x05, 0x2e, 0x6d, 0xb2, 0x94, 0x86, 0xc1, 0xb1,
- 0x7b, 0xfa, 0x43, 0x9e, 0xea, 0x14, 0xe6, 0x68, 0x68, 0x28, 0xa1, 0x76,
- 0x3b, 0xdd, 0x86, 0xce, 0x5e, 0x7f, 0xb6, 0x72, 0xdb, 0x39, 0x7c, 0xa7,
- 0x5f, 0xc7, 0x2a, 0x73, 0xee, 0x08, 0xef, 0xc3, 0xbe, 0x11, 0xbd, 0x03,
- 0x31, 0xcb, 0x86, 0x0e, 0x5a, 0x63, 0x95, 0x31, 0xe1, 0xe8, 0x71, 0xc5,
- 0x6f, 0xfe, 0x55, 0x05, 0x7b, 0x86, 0x3f, 0xde, 0x39, 0x7b, 0xfc, 0xe0,
- 0x39, 0x4a, 0x9f, 0x2e, 0x91, 0x6f, 0x99, 0xb0, 0x30, 0xe5, 0x95, 0x39,
- 0x66, 0x87, 0x2e, 0xd2, 0xa7, 0x2a, 0x0f, 0x81, 0x08, 0xc0, 0x24, 0xa0,
- 0x9d, 0xff, 0xf7, 0x72, 0x5b, 0x8f, 0x4b, 0x1a, 0xdc, 0x7f, 0x39, 0x7f,
- 0xc9, 0xee, 0xe7, 0xde, 0x04, 0x1c, 0xbe, 0x52, 0x35, 0xf9, 0xca, 0x91,
- 0xee, 0xf4, 0xe6, 0xec, 0xd9, 0xca, 0x83, 0x71, 0x22, 0x2a, 0xda, 0x60,
- 0xfe, 0x87, 0x3d, 0xbf, 0x39, 0x7e, 0x48, 0x64, 0x30, 0xe5, 0xb0, 0xe5,
- 0x21, 0xf8, 0xb9, 0x4e, 0xc4, 0x9a, 0x13, 0x59, 0x53, 0x95, 0x0a, 0xe6,
- 0x72, 0x10, 0x29, 0x09, 0x4e, 0xc2, 0x0d, 0xe3, 0xb3, 0xe0, 0x3c, 0xbd,
- 0xb8, 0x98, 0xe5, 0xfd, 0x81, 0xce, 0x29, 0xa3, 0x94, 0x72, 0xcc, 0x39,
- 0x5e, 0x2f, 0x38, 0x85, 0xdf, 0x05, 0xdf, 0xe3, 0x97, 0xef, 0xd3, 0x48,
- 0xa9, 0xcb, 0x9d, 0x53, 0x97, 0x67, 0xc7, 0x2a, 0x64, 0xc0, 0x98, 0x3b,
- 0xd4, 0xa7, 0x22, 0xfc, 0x88, 0x4a, 0x5a, 0x0b, 0xdd, 0x9a, 0x39, 0x77,
- 0xa0, 0xe5, 0xfa, 0x3b, 0x9c, 0x5c, 0xe5, 0x30, 0xf5, 0x1c, 0x5b, 0xf1,
- 0x6b, 0xf9, 0x3d, 0x9d, 0x75, 0x4e, 0x5f, 0xdd, 0x03, 0xcf, 0xd4, 0x39,
- 0x79, 0xb6, 0xdb, 0x29, 0x7f, 0xc1, 0x89, 0xd4, 0xce, 0xbf, 0xc5, 0x39,
- 0x9a, 0x0b, 0xb2, 0x73, 0x97, 0xa5, 0x0c, 0x39, 0x41, 0x46, 0x72, 0xd3,
- 0x91, 0x36, 0x61, 0x7b, 0xd0, 0xc4, 0x39, 0x58, 0x7b, 0x0b, 0x3d, 0xbe,
- 0x4d, 0x70, 0x04, 0xe5, 0xfb, 0xb1, 0xf3, 0xb5, 0x9c, 0xbf, 0xfe, 0x8f,
- 0x6c, 0x39, 0xe4, 0xe8, 0x33, 0xef, 0x1c, 0xae, 0x9f, 0xdf, 0x8a, 0xed,
- 0xa3, 0x97, 0xfb, 0x31, 0x6a, 0x71, 0xee, 0x1c, 0xbf, 0xe8, 0x1f, 0x0e,
- 0x7a, 0x1b, 0x39, 0x7f, 0xb1, 0xbd, 0xa0, 0xfd, 0x23, 0x94, 0x87, 0xd7,
- 0xa3, 0x7b, 0xde, 0xd0, 0x0e, 0x5b, 0x67, 0x28, 0x4d, 0x70, 0x07, 0x6f,
- 0xff, 0xd8, 0x18, 0xcf, 0x94, 0xf2, 0x08, 0x25, 0x9b, 0x39, 0x73, 0x3f,
- 0x39, 0x73, 0x89, 0xca, 0xe9, 0xad, 0x71, 0x8b, 0xf3, 0x13, 0xdf, 0xb9,
- 0xca, 0x9d, 0x55, 0x66, 0x42, 0x81, 0xac, 0x8a, 0x61, 0x1d, 0x42, 0x81,
- 0xd3, 0xc4, 0x83, 0xd0, 0x82, 0x01, 0x05, 0xda, 0x54, 0xe5, 0xf7, 0x7c,
- 0x93, 0x9c, 0xbf, 0xcb, 0x4d, 0x8e, 0x71, 0x73, 0x97, 0xd1, 0x3b, 0xc8,
- 0xe5, 0xf7, 0xb7, 0xd4, 0x39, 0x7f, 0x0b, 0xfa, 0x7c, 0x6c, 0xe5, 0x1c,
- 0xa1, 0x37, 0x3e, 0x2e, 0xa8, 0x3f, 0xbc, 0x5b, 0xbf, 0x64, 0xe3, 0x9f,
- 0x1c, 0xbe, 0xf2, 0x0e, 0xce, 0x5f, 0x97, 0xcb, 0x3e, 0xf1, 0xca, 0xc3,
- 0xcc, 0x42, 0x1a, 0x84, 0xef, 0xf0, 0x63, 0xe2, 0x3d, 0x19, 0xf6, 0x13,
- 0xa2, 0x41, 0xb7, 0x4b, 0xca, 0x01, 0x43, 0x97, 0x85, 0x1a, 0xce, 0x5f,
- 0x05, 0xa3, 0xaa, 0x72, 0xa0, 0xf0, 0xf0, 0x7a, 0xf7, 0x60, 0x27, 0x2e,
- 0xd6, 0xce, 0x51, 0xc4, 0x2d, 0xef, 0xf4, 0x0c, 0x9d, 0x98, 0x13, 0x97,
- 0xde, 0x63, 0x34, 0x72, 0xff, 0xef, 0xe0, 0x56, 0xfe, 0xfd, 0x41, 0x91,
- 0xcb, 0xd2, 0x4e, 0x9c, 0xbe, 0xf0, 0xe4, 0x8e, 0x5f, 0x03, 0x87, 0xdb,
- 0x9c, 0xbf, 0x4e, 0x17, 0x76, 0xce, 0x56, 0x1e, 0x80, 0x09, 0xef, 0xff,
- 0x26, 0xfb, 0x81, 0x1c, 0xe2, 0x39, 0xb3, 0x95, 0x24, 0xe4, 0x55, 0x31,
- 0xf8, 0x8e, 0x64, 0x6d, 0x0e, 0x0b, 0x8f, 0x88, 0x69, 0xaa, 0x6f, 0x42,
- 0x78, 0x62, 0xb8, 0x8d, 0x4e, 0x78, 0x55, 0x48, 0xc0, 0x31, 0xeb, 0xe4,
- 0xad, 0xd5, 0x61, 0x26, 0xb3, 0xbf, 0xa3, 0x69, 0x48, 0xcc, 0xe6, 0x85,
- 0xfe, 0xa1, 0xcc, 0xc8, 0x67, 0x76, 0x70, 0xa5, 0xe3, 0x6f, 0xfe, 0x17,
- 0x7c, 0x39, 0x78, 0xc6, 0xa7, 0xb9, 0x59, 0xbe, 0x94, 0xa0, 0x06, 0x8e,
- 0x2c, 0x4d, 0x90, 0x34, 0x33, 0x52, 0x3a, 0xab, 0xfe, 0xe7, 0xe4, 0xce,
- 0x0d, 0x82, 0x0e, 0x5f, 0xff, 0xf0, 0x23, 0x9f, 0xb6, 0x9d, 0x74, 0xf6,
- 0x6b, 0xf6, 0x3c, 0x8e, 0x57, 0x35, 0x4f, 0xf3, 0xc7, 0xb4, 0x13, 0xdb,
- 0xf6, 0x96, 0xee, 0xb3, 0x45, 0x6e, 0xbf, 0xf3, 0xcb, 0x9e, 0x69, 0x6e,
- 0xeb, 0x34, 0x4e, 0x0b, 0x73, 0xc4, 0x40, 0x30, 0xd2, 0xee, 0x18, 0x27,
- 0x2d, 0xd3, 0x96, 0xd9, 0xca, 0x01, 0xa2, 0x68, 0x23, 0x7e, 0xc6, 0xf6,
- 0x8d, 0x9c, 0xbe, 0x5b, 0xba, 0xcd, 0x16, 0x8a, 0xff, 0xf6, 0x07, 0xae,
- 0xac, 0xd3, 0x26, 0xc0, 0xc3, 0x95, 0xa3, 0xfb, 0xe9, 0x75, 0xf2, 0xdc,
- 0x7f, 0x39, 0x7f, 0xd3, 0x63, 0x5e, 0xf5, 0xa7, 0xf1, 0xcb, 0xfa, 0x1c,
- 0x40, 0x1c, 0x39, 0x7f, 0xf0, 0xe7, 0x1d, 0xe7, 0x70, 0x54, 0x09, 0xcb,
- 0xfd, 0x9a, 0xff, 0x26, 0x53, 0x67, 0x2c, 0xa9, 0xcb, 0xfe, 0xc8, 0x9f,
- 0x26, 0xd2, 0x6c, 0xe5, 0x21, 0xe5, 0xcc, 0x25, 0x7f, 0xfe, 0x9e, 0x3d,
- 0x01, 0xd4, 0x75, 0xf6, 0x39, 0xf9, 0xcb, 0xff, 0x47, 0xce, 0xd7, 0xd1,
- 0x76, 0xb9, 0xce, 0x5f, 0xfa, 0x35, 0xfe, 0x26, 0x6b, 0xc0, 0x39, 0x50,
- 0x8d, 0x8e, 0xaa, 0xed, 0x16, 0xd8, 0x14, 0xfb, 0xd1, 0x16, 0x68, 0x40,
- 0xee, 0x1f, 0x57, 0x23, 0x67, 0x2e, 0x49, 0x1c, 0xbf, 0xdd, 0xe8, 0x15,
- 0x64, 0x6c, 0xe5, 0xff, 0xf9, 0x36, 0x39, 0xc5, 0xfc, 0x39, 0xbe, 0xbc,
- 0xc7, 0x2f, 0xd1, 0xed, 0xa9, 0xd3, 0x95, 0x08, 0xc9, 0xc1, 0x69, 0x8d,
- 0x45, 0x56, 0xfb, 0x3f, 0x7e, 0x9c, 0xbb, 0xbb, 0x39, 0x6e, 0x7c, 0x22,
- 0xea, 0x0b, 0x56, 0x7d, 0x39, 0x1e, 0x42, 0x91, 0x64, 0x53, 0x11, 0x30,
- 0xf7, 0xb2, 0x86, 0xb6, 0x9b, 0xe8, 0x70, 0x34, 0x3b, 0x50, 0x8a, 0xf6,
- 0xd9, 0xb3, 0x97, 0xff, 0xfe, 0xec, 0x7e, 0xc7, 0x97, 0x2f, 0x77, 0x19,
- 0x8b, 0x8e, 0xc3, 0x0e, 0x5f, 0xc9, 0x3f, 0x27, 0x1f, 0xce, 0x5f, 0x2d,
- 0xdd, 0x66, 0x8b, 0x69, 0x7f, 0xff, 0x43, 0xfa, 0x3b, 0x1b, 0x44, 0x92,
- 0x6b, 0x02, 0x72, 0xfe, 0xec, 0x32, 0x10, 0x27, 0x29, 0x13, 0x4f, 0x99,
- 0xbb, 0x46, 0x1b, 0x2e, 0xf2, 0xbd, 0xff, 0xba, 0x81, 0x79, 0x07, 0xa8,
- 0xc3, 0x97, 0xfd, 0x98, 0xb6, 0x80, 0xea, 0x68, 0xe5, 0xf4, 0x71, 0xc4,
- 0x39, 0x66, 0xa4, 0xe5, 0xff, 0xd9, 0xe8, 0x60, 0xba, 0xa3, 0x9f, 0x9c,
- 0xb7, 0xe7, 0x2a, 0x63, 0xeb, 0x11, 0x6f, 0x21, 0xdf, 0xf8, 0x11, 0xff,
- 0x62, 0x71, 0xcd, 0x9c, 0xbf, 0xe8, 0x94, 0x6a, 0x78, 0xd4, 0xe7, 0x2f,
- 0xff, 0xf4, 0x20, 0xbf, 0x81, 0xec, 0x0c, 0x30, 0x3d, 0x8f, 0x8e, 0x5f,
- 0xff, 0x0a, 0x71, 0x4f, 0x76, 0x3d, 0xb8, 0xe3, 0x07, 0x2b, 0x48, 0xb0,
- 0x02, 0xfd, 0xce, 0x13, 0x97, 0xfd, 0x1a, 0xe5, 0xb8, 0xeb, 0xa1, 0xcb,
- 0xfd, 0xd4, 0x79, 0x79, 0x27, 0x39, 0x7e, 0x0c, 0x60, 0xa1, 0xca, 0x6a,
- 0x57, 0x37, 0xb2, 0x36, 0xc5, 0xa5, 0xcc, 0x7d, 0xa3, 0xa6, 0x42, 0x37,
- 0xa5, 0xe2, 0x7f, 0xb8, 0x75, 0x78, 0x8d, 0xb1, 0x66, 0x87, 0x2a, 0x19,
- 0xdf, 0xca, 0xbe, 0x82, 0x01, 0x39, 0x7f, 0xd1, 0xe4, 0x5a, 0x07, 0xe1,
- 0x39, 0x78, 0x1f, 0x48, 0xe5, 0xfc, 0x2d, 0x13, 0x58, 0xa9, 0xcb, 0xf2,
- 0x4e, 0xc8, 0x59, 0xcb, 0xf3, 0xfd, 0x25, 0x36, 0x72, 0xff, 0xc9, 0x36,
- 0xf8, 0xb8, 0xce, 0x00, 0x9c, 0xb7, 0x35, 0x53, 0x47, 0xd1, 0x77, 0x4e,
- 0x04, 0x7b, 0xc5, 0xfc, 0x4a, 0x14, 0x2a, 0xae, 0x6a, 0xa1, 0x3f, 0x94,
- 0x29, 0x73, 0x3a, 0x72, 0xfd, 0xa5, 0xbb, 0xac, 0xd1, 0x72, 0xaf, 0xe7,
- 0x0f, 0x60, 0x67, 0x39, 0x6e, 0x61, 0x3f, 0x8c, 0x17, 0xe9, 0xa5, 0xfb,
- 0x4b, 0x77, 0x59, 0xa2, 0xed, 0x5e, 0x9f, 0x1b, 0x39, 0x7f, 0xc9, 0x29,
- 0x20, 0xff, 0x12, 0x39, 0x7c, 0x9a, 0x7f, 0xce, 0x5b, 0x9e, 0x22, 0xb1,
- 0x86, 0x8e, 0x3d, 0xb3, 0x8a, 0x87, 0xc9, 0x14, 0x9c, 0xaa, 0x54, 0x98,
- 0xb0, 0xc7, 0x3f, 0x86, 0xea, 0xd3, 0x2b, 0xd2, 0xd0, 0x5b, 0xb5, 0xc2,
- 0xef, 0xb3, 0xad, 0x63, 0x48, 0x31, 0xdc, 0x29, 0xfd, 0x0e, 0x2b, 0xfd,
- 0xcf, 0x34, 0xb7, 0x75, 0x9a, 0x2a, 0x75, 0xf8, 0x79, 0xeb, 0x7b, 0x39,
- 0x74, 0xec, 0x39, 0x7e, 0xf9, 0x8e, 0xe2, 0x72, 0x82, 0x6f, 0xc0, 0x31,
- 0x6f, 0x1c, 0xbf, 0xe8, 0x79, 0xf9, 0x7d, 0xb8, 0x09, 0xca, 0x43, 0xcd,
- 0x11, 0x1b, 0xe5, 0xbb, 0xac, 0xd1, 0x5c, 0xaf, 0xf7, 0x3c, 0xd2, 0xdd,
- 0xd6, 0x68, 0xb3, 0x97, 0x3c, 0x8e, 0x5f, 0xd2, 0xf7, 0xcb, 0x4d, 0x9c,
- 0xa7, 0x3c, 0x50, 0x0b, 0x5f, 0xc9, 0xbc, 0x17, 0x6c, 0xe5, 0x69, 0x30,
- 0x1e, 0x97, 0x0c, 0x21, 0xbc, 0x43, 0x7f, 0xfb, 0xd1, 0xbe, 0x40, 0xdf,
- 0xa2, 0x69, 0x90, 0xe5, 0xfc, 0x8c, 0x9c, 0x1a, 0x91, 0xcb, 0xf3, 0x32,
- 0x67, 0xfc, 0xe5, 0xf4, 0xfd, 0x7f, 0x1c, 0xa7, 0x3c, 0xc0, 0x14, 0xdf,
- 0xe8, 0xef, 0x26, 0x35, 0x7c, 0x27, 0x8e, 0x56, 0x26, 0x55, 0xd4, 0xe1,
- 0x7b, 0xe2, 0x43, 0x7f, 0xc3, 0x0c, 0xd8, 0x24, 0xea, 0x9c, 0xbf, 0x6b,
- 0x3c, 0x8c, 0x39, 0x7c, 0xe3, 0x01, 0x39, 0x7e, 0x9a, 0x19, 0x0a, 0x1c,
- 0xba, 0x4c, 0x39, 0x58, 0x78, 0x02, 0x53, 0x7f, 0xfb, 0xa9, 0xcb, 0xae,
- 0x9e, 0x8c, 0x0a, 0x1c, 0xbf, 0x69, 0x6e, 0xeb, 0x34, 0x48, 0x4b, 0xff,
- 0xfb, 0x69, 0xa5, 0xf7, 0x39, 0x6b, 0x58, 0xdb, 0x48, 0x61, 0xcb, 0xff,
- 0x63, 0x31, 0xf5, 0x3f, 0x2f, 0x98, 0x72, 0xff, 0x7d, 0xbf, 0x0c, 0x33,
- 0x67, 0x2f, 0xff, 0x38, 0xaf, 0x90, 0x45, 0xe5, 0xd7, 0x91, 0xca, 0x43,
- 0xfe, 0x01, 0xa5, 0xfd, 0x82, 0x9f, 0xee, 0x0e, 0x5b, 0x9c, 0x93, 0xea,
- 0xc4, 0x9f, 0x8d, 0x3a, 0xc1, 0xfc, 0x30, 0x36, 0x43, 0x72, 0x74, 0xe5,
- 0xff, 0x9d, 0x49, 0x85, 0x3c, 0x31, 0xf9, 0xca, 0x92, 0x2e, 0xfe, 0x66,
- 0xf0, 0xb5, 0xff, 0xdd, 0x46, 0x66, 0xf9, 0x7d, 0x2c, 0xf1, 0xcb, 0xe9,
- 0x75, 0x4d, 0x9c, 0xa8, 0x3e, 0xbc, 0x47, 0xbe, 0x6a, 0xfb, 0x0c, 0x39,
- 0x7f, 0x77, 0x7b, 0xcd, 0x4e, 0x72, 0xe8, 0x6c, 0xe5, 0xff, 0x7f, 0x81,
- 0x17, 0xfe, 0x38, 0x9c, 0xac, 0x44, 0x0a, 0x17, 0xb8, 0xbd, 0xe6, 0x71,
- 0x91, 0xcb, 0xff, 0xdd, 0x8f, 0xd8, 0xf2, 0xdf, 0xb3, 0x18, 0x72, 0xdc,
- 0xe7, 0x64, 0x5c, 0x05, 0xbb, 0x23, 0x21, 0x48, 0xdb, 0x26, 0x3e, 0xd1,
- 0xcb, 0x09, 0xfa, 0xc0, 0xf2, 0xb1, 0x46, 0x13, 0x9b, 0x20, 0xf4, 0x2a,
- 0x00, 0x5a, 0xa0, 0xfd, 0xff, 0xec, 0xfb, 0x98, 0x40, 0xfa, 0x97, 0x5b,
- 0x73, 0x97, 0xff, 0x73, 0xeb, 0xec, 0x73, 0xde, 0x8f, 0xce, 0x5f, 0xfe,
- 0xe6, 0xc7, 0x97, 0x3c, 0xd2, 0xdd, 0xd6, 0x68, 0x9f, 0x14, 0xb6, 0x59,
- 0xba, 0x20, 0xb5, 0xd2, 0x48, 0x75, 0x0e, 0x76, 0x27, 0x75, 0x1a, 0xff,
- 0xfe, 0x00, 0xba, 0xbc, 0xbc, 0xac, 0x0c, 0xb3, 0xa8, 0xc3, 0x97, 0x27,
- 0xc7, 0x2f, 0xff, 0xa5, 0x3f, 0x0a, 0x86, 0xae, 0x75, 0xeb, 0x97, 0x2e,
- 0xb4, 0x39, 0x52, 0x3f, 0xcf, 0xc5, 0xef, 0xff, 0x0c, 0xfd, 0x84, 0xf6,
- 0xd0, 0x7e, 0x91, 0xcb, 0xff, 0x79, 0x58, 0x19, 0x67, 0x51, 0x87, 0x2f,
- 0xf9, 0x58, 0x19, 0x67, 0x51, 0x87, 0x2f, 0x80, 0x2e, 0xaf, 0x23, 0xf6,
- 0xf1, 0xf5, 0xfb, 0x5f, 0xa7, 0x60, 0xe5, 0x30, 0xf8, 0xc0, 0x77, 0x7e,
- 0xcd, 0x66, 0x4c, 0x72, 0xdc, 0xd8, 0xa9, 0xa3, 0xb0, 0xd9, 0x72, 0x3d,
- 0xc6, 0x46, 0xa1, 0x15, 0xfb, 0x4b, 0x77, 0x59, 0xa2, 0xb2, 0x5f, 0xf9,
- 0xe5, 0xcf, 0x34, 0xb7, 0x75, 0x9a, 0x26, 0xe5, 0xb9, 0xe2, 0x20, 0x18,
- 0x69, 0x4b, 0x4c, 0x25, 0x21, 0xbf, 0x7c, 0xb7, 0x75, 0x9a, 0x25, 0x65,
- 0xff, 0xf6, 0xa7, 0x18, 0xd3, 0x84, 0x5f, 0x51, 0xc4, 0xe5, 0x68, 0xff,
- 0x80, 0x5d, 0x7e, 0x18, 0x0b, 0xf4, 0xe5, 0xfe, 0x84, 0x18, 0x94, 0x70,
- 0x1c, 0xbf, 0x73, 0x63, 0xcb, 0x9e, 0x1f, 0xda, 0x11, 0x6c, 0x9a, 0xff,
- 0xde, 0xce, 0x79, 0xa4, 0x9d, 0xd8, 0x72, 0xff, 0xf3, 0x52, 0xd5, 0x70,
- 0x9b, 0xc7, 0x92, 0x66, 0xb0, 0xe5, 0xff, 0x93, 0x60, 0x60, 0xa7, 0x10,
- 0x39, 0xcb, 0xfa, 0x05, 0xd6, 0xed, 0x67, 0x2a, 0x47, 0xda, 0xc3, 0xfb,
- 0x83, 0xa3, 0x97, 0xed, 0x2d, 0xdd, 0x66, 0x89, 0x71, 0x7f, 0xc8, 0xf2,
- 0xf0, 0xc3, 0x36, 0x72, 0xfd, 0x26, 0x89, 0xd7, 0x39, 0x7a, 0x1a, 0x41,
- 0xcb, 0xff, 0xfb, 0x00, 0xbe, 0xc0, 0xc4, 0x9c, 0x31, 0xf6, 0x90, 0xe5,
- 0xe4, 0x18, 0x39, 0x52, 0x45, 0xc8, 0x4a, 0x5a, 0xc7, 0x78, 0xac, 0xdf,
- 0xfc, 0x09, 0x0a, 0x4a, 0x3c, 0x20, 0x91, 0xcb, 0xf4, 0x6f, 0xf6, 0x78,
- 0xe5, 0xcf, 0xe4, 0x3e, 0xce, 0xa1, 0xdf, 0xd2, 0xee, 0x0e, 0x2c, 0xe5,
- 0xe9, 0x77, 0xc7, 0x2e, 0xec, 0x21, 0xe4, 0xf4, 0xb2, 0xff, 0xe1, 0x4f,
- 0xf7, 0xa8, 0x49, 0x3e, 0xce, 0x56, 0x1f, 0x7a, 0x16, 0x5f, 0xda, 0x46,
- 0x0b, 0xc8, 0xe5, 0xff, 0xbe, 0x96, 0x7b, 0x34, 0xb8, 0xc3, 0x97, 0x9e,
- 0x5c, 0xda, 0x8a, 0xe1, 0xec, 0x43, 0x12, 0x44, 0x58, 0x2f, 0xd3, 0x47,
- 0x87, 0x86, 0xe1, 0x5d, 0xe8, 0x72, 0x00, 0x83, 0x80, 0xb2, 0xff, 0xc0,
- 0x67, 0x3d, 0xc0, 0xfb, 0x34, 0x72, 0xff, 0x83, 0x9c, 0xe3, 0x49, 0xd0,
- 0x1c, 0xb7, 0x34, 0x5d, 0xb2, 0x64, 0xe3, 0xee, 0xe1, 0x76, 0x04, 0x0b,
- 0xff, 0xb9, 0xbc, 0xb9, 0xe6, 0x96, 0xee, 0xb3, 0x44, 0x76, 0xbf, 0xef,
- 0x77, 0x25, 0xcd, 0xc7, 0x67, 0x2f, 0xee, 0x18, 0x61, 0x78, 0x27, 0x2e,
- 0x07, 0x4e, 0x5f, 0xdc, 0x20, 0xe7, 0x5f, 0xc7, 0x2f, 0xff, 0xef, 0x49,
- 0x03, 0xd4, 0xe3, 0xcb, 0x03, 0xa4, 0x02, 0xce, 0x5f, 0xec, 0x6f, 0x70,
- 0x3e, 0xd9, 0xcb, 0xfb, 0xf1, 0xcf, 0xbd, 0x87, 0x2f, 0xce, 0xaf, 0x73,
- 0xf3, 0x97, 0xf0, 0xfe, 0xfa, 0x75, 0x0e, 0x54, 0x22, 0x17, 0x45, 0xce,
- 0x53, 0x7f, 0xff, 0xfe, 0xec, 0x77, 0xae, 0x11, 0x7e, 0x5b, 0xec, 0x6f,
- 0x90, 0x1f, 0x94, 0xb3, 0x8c, 0x1c, 0xbf, 0xf2, 0x6b, 0x96, 0xc7, 0x19,
- 0x0b, 0x39, 0x7f, 0x81, 0xe4, 0x7e, 0x2f, 0x23, 0x97, 0xf3, 0xf1, 0x0e,
- 0x0a, 0xa7, 0x2d, 0x02, 0x7c, 0x6a, 0x1a, 0x5f, 0xf8, 0x41, 0x2e, 0x58,
- 0x83, 0x0c, 0x39, 0x7c, 0xb7, 0x75, 0x9a, 0x2a, 0x15, 0xff, 0x67, 0x70,
- 0x5f, 0x5a, 0x43, 0x95, 0x24, 0xfd, 0x15, 0x84, 0x4a, 0xe1, 0x44, 0x84,
- 0xfa, 0x3e, 0xd9, 0x75, 0xe6, 0xb7, 0x83, 0x97, 0x4b, 0x0e, 0x5f, 0xf4,
- 0xbc, 0x9a, 0x75, 0xa0, 0x9c, 0xbd, 0xfe, 0xf0, 0xe5, 0xfe, 0xd8, 0x26,
- 0x70, 0xbc, 0xc7, 0x2a, 0x47, 0xa5, 0xf0, 0xed, 0xfa, 0x43, 0x0c, 0x54,
- 0xe5, 0xff, 0xcc, 0xcd, 0x0e, 0x27, 0x14, 0xd3, 0x9c, 0xaf, 0x8f, 0xad,
- 0xca, 0x2f, 0xfc, 0x39, 0x37, 0xbb, 0x9a, 0x4d, 0x9c, 0xbf, 0xf9, 0xd9,
- 0xc9, 0x8f, 0xee, 0x5d, 0xf6, 0x8e, 0x57, 0x51, 0x0e, 0x27, 0xd7, 0xef,
- 0x85, 0x18, 0x87, 0x2f, 0xd1, 0xc3, 0x4f, 0x8d, 0x9c, 0xa8, 0x4c, 0x83,
- 0x21, 0x52, 0x84, 0x5a, 0x27, 0xbf, 0xd1, 0xe7, 0xef, 0x20, 0xc1, 0xcb,
- 0xfd, 0xed, 0xa0, 0xaf, 0xb0, 0x72, 0xff, 0xd9, 0xed, 0xeb, 0x26, 0xea,
- 0x2a, 0x72, 0xff, 0xc3, 0x8a, 0xe3, 0x11, 0xa4, 0x30, 0xe5, 0xff, 0x72,
- 0x71, 0xce, 0x0e, 0x5d, 0x01, 0xca, 0x84, 0x78, 0x21, 0x93, 0xa0, 0x00,
- 0xfe, 0xff, 0x4a, 0x35, 0x3c, 0x6a, 0x73, 0x97, 0xfe, 0xde, 0x0f, 0xb7,
- 0x92, 0x4e, 0x9c, 0xbf, 0xb7, 0x9c, 0x46, 0x3e, 0x39, 0x5b, 0x3e, 0xcf,
- 0x1e, 0xdf, 0xff, 0x47, 0xf8, 0x3c, 0x9f, 0xdc, 0xbb, 0x9f, 0xb9, 0xcb,
- 0x86, 0x73, 0x95, 0x09, 0x96, 0xe4, 0x28, 0x50, 0x88, 0x54, 0xef, 0xee,
- 0x2e, 0xce, 0xb6, 0xe7, 0x2f, 0xff, 0xf2, 0x47, 0x9f, 0xbc, 0xf7, 0xdc,
- 0x1f, 0x72, 0xfe, 0x5b, 0x39, 0x48, 0x89, 0x51, 0x30, 0xbd, 0xb0, 0x68,
- 0xe5, 0xfd, 0xa7, 0x1f, 0xff, 0x83, 0x95, 0x87, 0xd8, 0x84, 0x2a, 0x0e,
- 0xde, 0xf6, 0x4e, 0x72, 0xfd, 0x8b, 0x03, 0xce, 0x72, 0xba, 0x78, 0xa2,
- 0x3b, 0x7f, 0xff, 0xb1, 0x6f, 0xdc, 0x94, 0x6a, 0x3f, 0xd4, 0x28, 0xe2,
- 0x72, 0xfd, 0x93, 0xb8, 0xf1, 0x39, 0x7f, 0xff, 0xff, 0xa2, 0x5c, 0xbd,
- 0xd4, 0x8d, 0xf2, 0xc0, 0x2e, 0x38, 0xf2, 0xcd, 0x6b, 0x38, 0x81, 0xfa,
- 0x72, 0xfb, 0xa2, 0xfc, 0x07, 0x2b, 0x13, 0x64, 0xe9, 0x08, 0xaf, 0xec,
- 0xa7, 0xd0, 0x97, 0xbf, 0xff, 0xe0, 0x3b, 0x5a, 0x4f, 0xd7, 0x4f, 0x47,
- 0x53, 0xdb, 0xc0, 0x9c, 0xbf, 0xfc, 0x39, 0xc5, 0xe5, 0x82, 0x11, 0x89,
- 0x1c, 0xb7, 0x3e, 0x11, 0x9a, 0xbc, 0xd5, 0x98, 0x70, 0xc2, 0xf0, 0x63,
- 0x3a, 0xf8, 0x61, 0x71, 0x92, 0x88, 0x95, 0x62, 0x58, 0xf7, 0xc2, 0xc9,
- 0x08, 0x9d, 0x47, 0x5c, 0xc4, 0x0e, 0xc6, 0x48, 0x31, 0xb3, 0xee, 0x34,
- 0x0f, 0x47, 0xae, 0xd1, 0x39, 0x46, 0x8b, 0xe5, 0xbb, 0xac, 0xd1, 0x54,
- 0x2f, 0xf6, 0xa3, 0x8f, 0xd2, 0xcf, 0x1c, 0xad, 0x1f, 0x20, 0x0b, 0xaf,
- 0xfc, 0xf2, 0xe7, 0x9a, 0x5b, 0xba, 0xcd, 0x13, 0x5a, 0xfa, 0x35, 0x1e,
- 0x39, 0x73, 0xf8, 0xe5, 0x04, 0xdb, 0xb0, 0x86, 0xdc, 0xf1, 0x18, 0xcc,
- 0x22, 0x78, 0x41, 0xdf, 0xb4, 0xb7, 0x75, 0x9a, 0x2a, 0xc5, 0xff, 0x44,
- 0xa3, 0x53, 0xc6, 0xa7, 0x39, 0x6e, 0x78, 0x7d, 0xc2, 0x69, 0x7f, 0xdd,
- 0x8f, 0xbd, 0x1d, 0x76, 0xb3, 0x97, 0xff, 0x7f, 0x83, 0xce, 0x5f, 0xee,
- 0x77, 0x13, 0x95, 0xcd, 0x10, 0x90, 0x79, 0x7e, 0xdc, 0x4d, 0x1f, 0x1c,
- 0xbf, 0xe9, 0x73, 0xcd, 0x2d, 0xdd, 0x66, 0x89, 0x11, 0x7f, 0x4f, 0x1a,
- 0xeb, 0xa1, 0xcb, 0x73, 0xc4, 0x4e, 0xb9, 0x4e, 0xd1, 0xef, 0xda, 0x5b,
- 0xba, 0xcd, 0x16, 0x92, 0xff, 0xcf, 0x2e, 0x79, 0xa5, 0xbb, 0xac, 0xd1,
- 0x3e, 0xad, 0xcf, 0x11, 0x00, 0xc3, 0x4b, 0xff, 0xdc, 0xd8, 0xf2, 0xe7,
- 0x9a, 0x5b, 0xba, 0xcd, 0x14, 0x22, 0xff, 0xec, 0x6f, 0x9f, 0x95, 0x7d,
- 0xa7, 0xa0, 0xe5, 0xfb, 0xc0, 0x5b, 0xec, 0xe5, 0xf2, 0x4f, 0x1a, 0x39,
- 0x4c, 0x3c, 0xae, 0x94, 0x5f, 0xb4, 0xb7, 0x75, 0x9a, 0x28, 0xf5, 0xff,
- 0x44, 0xa3, 0x53, 0xc6, 0xa7, 0x39, 0x7f, 0xff, 0xff, 0x94, 0x4d, 0x4d,
- 0x1d, 0xd6, 0x75, 0xd4, 0xde, 0x2a, 0xe3, 0xfc, 0x0c, 0x4d, 0xd8, 0x39,
- 0x7e, 0x7d, 0xa7, 0xa0, 0xe5, 0xff, 0x44, 0xd0, 0x31, 0x37, 0x60, 0xe5,
- 0x42, 0x3b, 0x95, 0x84, 0x80, 0x93, 0x5f, 0xff, 0xd8, 0x1e, 0xc2, 0x9c,
- 0xfc, 0x2f, 0xfe, 0xf7, 0x1f, 0x94, 0xbc, 0xf2, 0xe7, 0x0a, 0x84, 0x70,
- 0x88, 0x4d, 0x3d, 0x19, 0x43, 0x43, 0x4b, 0xff, 0xb3, 0xbc, 0xfc, 0xab,
- 0xed, 0x3d, 0x07, 0x2d, 0xce, 0x75, 0x69, 0x8c, 0x95, 0x45, 0xe6, 0x4a,
- 0x86, 0xf6, 0x52, 0x79, 0xe0, 0x09, 0x2a, 0x62, 0xa2, 0xb4, 0xd9, 0x85,
- 0xca, 0x76, 0xfa, 0x15, 0x29, 0x0a, 0xc9, 0xa1, 0x83, 0xd8, 0x5b, 0x7e,
- 0x55, 0xe9, 0x74, 0xd7, 0xfb, 0x9e, 0x69, 0x6e, 0xeb, 0x34, 0x44, 0x4b,
- 0xfb, 0x34, 0xb7, 0x75, 0x9a, 0x22, 0xb5, 0xff, 0x35, 0xf3, 0xcd, 0x2d,
- 0xdd, 0x66, 0x8a, 0xe1, 0x5c, 0xd1, 0x06, 0xe7, 0x37, 0xff, 0xbf, 0x81,
- 0x5f, 0x37, 0xf7, 0xea, 0x0c, 0x8e, 0x5f, 0x73, 0x9e, 0x66, 0xb3, 0x96,
- 0x4f, 0x8f, 0xe3, 0xf4, 0xeb, 0xec, 0xeb, 0xf8, 0xe5, 0xfe, 0xc4, 0xd7,
- 0xff, 0x83, 0x67, 0x2d, 0xc2, 0x09, 0xeb, 0x6c, 0x86, 0xff, 0xfe, 0xf6,
- 0xd3, 0xae, 0x92, 0x41, 0xf0, 0x3b, 0xac, 0x39, 0x7e, 0xd2, 0xdd, 0xd6,
- 0x68, 0xa7, 0x97, 0xf8, 0x3f, 0xf2, 0x86, 0xb8, 0x91, 0xcb, 0xfc, 0xc4,
- 0x08, 0x1f, 0x52, 0x39, 0x73, 0x10, 0xe5, 0x41, 0xe4, 0xac, 0xce, 0xff,
- 0xfe, 0x8f, 0x6c, 0x0c, 0x5a, 0x7f, 0x19, 0xd4, 0x02, 0xce, 0x5f, 0xd0,
- 0xcd, 0xc2, 0x4e, 0x72, 0xa4, 0x88, 0x8f, 0x2d, 0xdf, 0x4a, 0x32, 0x73,
- 0x97, 0xff, 0xed, 0x03, 0x5a, 0x81, 0xc5, 0x53, 0xbd, 0xc5, 0x0e, 0x57,
- 0xc7, 0xf1, 0xa2, 0x2b, 0xff, 0x92, 0x58, 0x3f, 0xc3, 0x13, 0x52, 0x39,
- 0x7f, 0xa5, 0x1a, 0x9e, 0x35, 0x39, 0xcb, 0xee, 0x42, 0xf2, 0x39, 0x7e,
- 0x7c, 0xea, 0x30, 0xe5, 0x6c, 0xf2, 0x78, 0x91, 0xd4, 0x22, 0x8b, 0x1f,
- 0xaf, 0xfb, 0x8b, 0xb3, 0x90, 0x7a, 0x8c, 0x39, 0x7f, 0xc3, 0x0c, 0x89,
- 0x0e, 0x30, 0xe5, 0x61, 0xf9, 0xa1, 0xed, 0xff, 0x40, 0xaf, 0x38, 0xe7,
- 0xb6, 0x72, 0xfc, 0xf3, 0xc6, 0x80, 0x72, 0xb8, 0x65, 0xc9, 0xc8, 0x2c,
- 0xc5, 0x95, 0x4d, 0x17, 0x08, 0x2f, 0xa1, 0x52, 0x90, 0x9b, 0x72, 0x31,
- 0x87, 0x2e, 0xe1, 0x29, 0xc4, 0x81, 0xa1, 0xcd, 0xff, 0xe7, 0x97, 0x30,
- 0x8b, 0xb7, 0xbd, 0xc7, 0xe7, 0x2f, 0xff, 0x7f, 0xf8, 0x37, 0xcd, 0x41,
- 0x76, 0x0c, 0x1c, 0xbf, 0xf8, 0x73, 0xf7, 0x1f, 0xf9, 0xb1, 0x18, 0x72,
- 0xb4, 0x89, 0x4f, 0x27, 0x5f, 0xff, 0xe4, 0x1f, 0xc7, 0x3d, 0xdc, 0xe7,
- 0xd7, 0xef, 0x52, 0x63, 0x95, 0xcd, 0x51, 0x68, 0x61, 0x8e, 0x90, 0xe1,
- 0xd9, 0x1d, 0xb0, 0xe5, 0xf8, 0x60, 0x1c, 0x3e, 0xce, 0x5f, 0xca, 0xe9,
- 0xc2, 0xe2, 0x72, 0x82, 0x7d, 0x38, 0x20, 0xe5, 0x97, 0xff, 0x20, 0x74,
- 0xff, 0x73, 0xd6, 0xa2, 0x73, 0x95, 0xcc, 0xfd, 0x7a, 0x5b, 0x70, 0x60,
- 0xe5, 0xff, 0xfb, 0xb1, 0xac, 0x92, 0x3f, 0xb0, 0x28, 0x05, 0x94, 0xbf,
- 0x44, 0xbf, 0x04, 0x8e, 0x5f, 0x2d, 0xdd, 0x66, 0x8a, 0xcd, 0x53, 0x1e,
- 0xbe, 0x8a, 0x6f, 0xbc, 0x8c, 0xd9, 0xcb, 0xca, 0xed, 0x53, 0x97, 0xf7,
- 0x11, 0x18, 0x6b, 0x98, 0xe5, 0xf9, 0x90, 0x32, 0xd9, 0xca, 0x83, 0xd9,
- 0x9c, 0xca, 0xfb, 0xdb, 0x53, 0x67, 0x2c, 0xe7, 0x2b, 0x0d, 0xa6, 0xc9,
- 0x2e, 0x9d, 0x0e, 0x5f, 0xed, 0xcc, 0x83, 0xdc, 0xf8, 0xe5, 0x41, 0xe5,
- 0xe0, 0xbd, 0xfb, 0xdf, 0xa8, 0x32, 0x39, 0x7f, 0xfd, 0x0c, 0xf6, 0x60,
- 0xfb, 0x7d, 0xcf, 0xdc, 0xe5, 0xe0, 0x3e, 0xce, 0x5f, 0xf6, 0x49, 0x00,
- 0xd6, 0xd5, 0xfe, 0xc3, 0x96, 0x43, 0x97, 0xf7, 0x70, 0x45, 0xfc, 0x73,
- 0x65, 0x85, 0xfb, 0x26, 0x9c, 0x1f, 0x9c, 0xbf, 0xbd, 0x1a, 0xfe, 0x26,
- 0x39, 0x6e, 0x70, 0xaf, 0x60, 0x22, 0xd9, 0x0a, 0xaf, 0x88, 0xd0, 0x8b,
- 0x4f, 0x0c, 0x56, 0xeb, 0x5b, 0x90, 0x7e, 0x54, 0x29, 0xdb, 0x1c, 0xf2,
- 0x92, 0x87, 0x5c, 0x05, 0x77, 0xfe, 0xea, 0x79, 0xf5, 0x3c, 0x20, 0x4e,
- 0x5f, 0xfb, 0xc0, 0x66, 0x2f, 0x5f, 0x3b, 0x67, 0x2f, 0xf6, 0xa1, 0x5c,
- 0x14, 0x54, 0xe5, 0xff, 0xe8, 0x6d, 0x46, 0x0e, 0x7d, 0xe8, 0xc6, 0xce,
- 0x5f, 0xbc, 0x83, 0x8c, 0x39, 0x7d, 0x27, 0x1e, 0x78, 0x99, 0x27, 0xc7,
- 0xda, 0x41, 0x50, 0xcf, 0x81, 0x32, 0xff, 0xcf, 0x2e, 0x79, 0xa5, 0xbb,
- 0xac, 0xd1, 0x22, 0xaf, 0xff, 0xde, 0xee, 0x0f, 0x3f, 0x3b, 0xfd, 0xb5,
- 0x55, 0x73, 0x97, 0xfe, 0x7f, 0x73, 0x84, 0xd2, 0x78, 0x07, 0x2b, 0x9a,
- 0x39, 0x21, 0x31, 0xd6, 0x6f, 0xec, 0xd2, 0xdd, 0xd6, 0x68, 0xb2, 0x57,
- 0xe9, 0xd0, 0x65, 0xb3, 0x97, 0xf8, 0x13, 0xf6, 0x3d, 0xb4, 0x39, 0x7e,
- 0xf6, 0xd4, 0xdf, 0x3c, 0x3d, 0xcd, 0x14, 0x57, 0x34, 0x6b, 0xe4, 0x25,
- 0x6f, 0xf7, 0x02, 0x32, 0x3a, 0xa0, 0x4e, 0x5f, 0xdd, 0x4d, 0x44, 0xb6,
- 0x72, 0xfe, 0x67, 0x93, 0xae, 0xc3, 0x97, 0xff, 0x93, 0xdd, 0xcf, 0x60,
- 0xc7, 0xa0, 0x27, 0x2a, 0x0f, 0xd1, 0xcb, 0x6f, 0xf9, 0xd3, 0xc0, 0xd3,
- 0xef, 0x9e, 0x23, 0xe1, 0x66, 0xfd, 0x85, 0x0d, 0xfd, 0x9a, 0x5b, 0xba,
- 0xcd, 0x16, 0xc2, 0xff, 0xfe, 0xe1, 0x3b, 0xc8, 0x73, 0x5e, 0xdf, 0x66,
- 0xe5, 0xcb, 0xad, 0x0e, 0x5e, 0xd0, 0x3a, 0x72, 0xef, 0x73, 0x84, 0x44,
- 0x69, 0xae, 0xb9, 0xa3, 0xc5, 0x21, 0x83, 0x7b, 0x37, 0x87, 0x2f, 0x96,
- 0xee, 0xb3, 0x45, 0xb6, 0xbe, 0xdc, 0xef, 0xa3, 0x95, 0xa3, 0xd1, 0xf1,
- 0x75, 0xfc, 0x9d, 0xf2, 0x7e, 0x03, 0x97, 0xfd, 0x12, 0x8d, 0x4f, 0x1a,
- 0x9c, 0xe5, 0xf4, 0x4d, 0xb4, 0x39, 0x52, 0x4c, 0x63, 0x1b, 0x26, 0x22,
- 0x12, 0xee, 0x03, 0xab, 0xff, 0x07, 0x48, 0x09, 0xf9, 0xef, 0x5e, 0x39,
- 0x5c, 0xd1, 0x21, 0x89, 0xb7, 0xff, 0xb0, 0x7f, 0xe6, 0xc7, 0x0e, 0x60,
- 0xaa, 0x72, 0xf7, 0x0d, 0xd0, 0x9c, 0xbd, 0x3f, 0x50, 0xe5, 0xff, 0xb8,
- 0x6e, 0x1b, 0x85, 0xfd, 0xdc, 0x18, 0xfc, 0xe5, 0xe6, 0xa3, 0xc2, 0xcd,
- 0x44, 0xe5, 0xfd, 0x03, 0x20, 0x81, 0x87, 0x2f, 0xfb, 0x35, 0xa8, 0x93,
- 0xfc, 0xd9, 0xcb, 0xe5, 0xbb, 0xac, 0xd1, 0x78, 0x2f, 0xde, 0xf9, 0x69,
- 0xa3, 0x97, 0xfe, 0x7f, 0x47, 0x1d, 0x6b, 0x3e, 0xd9, 0xca, 0xd2, 0x26,
- 0x18, 0x5c, 0x25, 0x37, 0xde, 0x69, 0x9d, 0x39, 0x7e, 0x64, 0x0c, 0x9c,
- 0xe5, 0xfd, 0x03, 0xee, 0x2e, 0xb3, 0x97, 0xf4, 0xa3, 0x8c, 0x6b, 0xe3,
- 0x95, 0x23, 0xde, 0xc2, 0xeb, 0xfd, 0x1e, 0x7e, 0xf2, 0x0c, 0x1c, 0xbf,
- 0xf2, 0x8c, 0xfa, 0x5e, 0xc1, 0xf6, 0xce, 0x5d, 0x8a, 0x9c, 0xa8, 0x3d,
- 0x8c, 0x41, 0xbe, 0x49, 0xf1, 0x87, 0x2f, 0xd8, 0x3f, 0xf0, 0x41, 0xcb,
- 0xf4, 0x28, 0x07, 0xd9, 0xcb, 0xff, 0x99, 0x0b, 0xe5, 0x82, 0x09, 0x66,
- 0xce, 0x5f, 0xee, 0xa3, 0x6a, 0xe9, 0xdb, 0x39, 0x7f, 0xff, 0xe7, 0x4f,
- 0x3b, 0x1c, 0x7f, 0x5f, 0x53, 0x52, 0x52, 0x58, 0x27, 0x2f, 0xe8, 0xfb,
- 0xe9, 0x3f, 0xc7, 0x2b, 0x13, 0x16, 0x5a, 0x2f, 0x4d, 0x80, 0xd7, 0x7f,
- 0xf6, 0x77, 0xaf, 0x26, 0x24, 0x6a, 0x47, 0x2f, 0xa0, 0x64, 0xd6, 0x72,
- 0xe8, 0xfc, 0xe5, 0x48, 0xff, 0x95, 0x43, 0xf1, 0x25, 0x70, 0x8b, 0xba,
- 0xfc, 0x31, 0x13, 0x51, 0x1d, 0xe1, 0x65, 0x09, 0xcc, 0x02, 0x5b, 0x90,
- 0xd2, 0xf8, 0xbd, 0x09, 0x26, 0x84, 0x23, 0x08, 0x7b, 0x08, 0xc7, 0x20,
- 0xfc, 0x88, 0x4a, 0xb7, 0x19, 0xf7, 0xa1, 0x77, 0x7f, 0xbe, 0xe7, 0x9f,
- 0xbe, 0xb6, 0x72, 0xff, 0x7f, 0xce, 0x69, 0x40, 0xf8, 0xe5, 0x73, 0x4e,
- 0x22, 0x23, 0x1a, 0xd1, 0xbd, 0xe4, 0xcf, 0x8e, 0x5f, 0x2d, 0xdd, 0x66,
- 0x8b, 0xd1, 0x7f, 0xe4, 0xf7, 0x45, 0xe5, 0xfb, 0xfe, 0x72, 0xb4, 0x7d,
- 0xac, 0x2e, 0xbf, 0xf3, 0xa7, 0x81, 0xa7, 0xe3, 0x81, 0x39, 0x79, 0x89,
- 0xe3, 0x97, 0xfc, 0xfe, 0x94, 0x2b, 0xe4, 0x9c, 0xe5, 0x30, 0xf5, 0x84,
- 0x72, 0xfd, 0x8c, 0xeb, 0x84, 0xe5, 0x05, 0x38, 0x8c, 0x84, 0x4f, 0x48,
- 0x94, 0x84, 0xaf, 0x01, 0x0d, 0xff, 0xd8, 0x1e, 0xe3, 0x18, 0xf2, 0xc1,
- 0x39, 0x78, 0x11, 0xf9, 0xcb, 0xee, 0x38, 0x3c, 0xc2, 0x7b, 0xfa, 0x42,
- 0xbf, 0xdc, 0xfd, 0x93, 0x49, 0xc2, 0x72, 0x90, 0xfc, 0xba, 0x79, 0x5c,
- 0xd3, 0x4a, 0xc8, 0xca, 0x6a, 0x1d, 0x0b, 0x3c, 0xf0, 0xc4, 0x94, 0x27,
- 0x32, 0x7d, 0x21, 0x71, 0x94, 0x24, 0xbf, 0xc9, 0xa5, 0x00, 0x6a, 0x34,
- 0xb6, 0x46, 0x0f, 0xd8, 0xc8, 0x7f, 0x8d, 0x50, 0x63, 0xd1, 0xd9, 0x20,
- 0x27, 0xea, 0x9b, 0x96, 0x15, 0x70, 0x3a, 0x72, 0xff, 0xe0, 0x44, 0xc3,
- 0x9c, 0x5d, 0x8c, 0x43, 0x97, 0xd9, 0xd7, 0xf1, 0xcb, 0xfd, 0x89, 0xaf,
- 0xff, 0x06, 0xce, 0x5b, 0x84, 0x55, 0x13, 0x62, 0x8b, 0xb2, 0x1b, 0xff,
- 0xde, 0xd8, 0x23, 0x79, 0xe4, 0x63, 0xc8, 0xe5, 0xe8, 0xfa, 0x73, 0x94,
- 0x27, 0xcf, 0xe4, 0x9b, 0xfe, 0xf6, 0xf3, 0xe9, 0x74, 0x0a, 0x9c, 0xbd,
- 0xb8, 0x98, 0xe5, 0x21, 0xfd, 0x09, 0x0e, 0xcf, 0x2f, 0xa3, 0x8c, 0x48,
- 0xe5, 0xfc, 0xfa, 0x90, 0x81, 0xce, 0x5c, 0x8c, 0x39, 0x40, 0x3c, 0x2e,
- 0x02, 0xcb, 0xce, 0xeb, 0x34, 0x44, 0x6b, 0xe5, 0x56, 0xfa, 0x39, 0x4b,
- 0x3c, 0xb4, 0x28, 0xbf, 0x70, 0xde, 0xdb, 0xfe, 0x72, 0xb4, 0x79, 0xec,
- 0x21, 0xbf, 0xfe, 0xe8, 0x37, 0xbc, 0x60, 0xe7, 0x1e, 0x50, 0xd4, 0x9c,
- 0xbf, 0xe8, 0x9f, 0x59, 0xef, 0x27, 0x8e, 0x5e, 0x18, 0xf8, 0xe5, 0x48,
- 0xf5, 0x42, 0x73, 0x7f, 0xd9, 0xac, 0xde, 0x38, 0xce, 0x72, 0xf6, 0x05,
- 0x87, 0x2f, 0xff, 0xf7, 0x5d, 0x3d, 0x1d, 0x1c, 0xf7, 0x53, 0xb8, 0x8d,
- 0x9c, 0xbf, 0xff, 0xfd, 0xef, 0x23, 0x34, 0x99, 0xf0, 0x83, 0xd1, 0xde,
- 0x5c, 0x53, 0xd3, 0x41, 0xcb, 0xfe, 0xc7, 0x1f, 0xf4, 0x08, 0xfc, 0xe5,
- 0x42, 0x62, 0x78, 0xbd, 0xa7, 0xcb, 0xfc, 0xec, 0xcd, 0x4a, 0x18, 0x72,
- 0xe9, 0xd8, 0x52, 0xe6, 0xdb, 0x29, 0x7f, 0xee, 0x6b, 0xea, 0x4d, 0xd8,
- 0x9f, 0x9f, 0xe6, 0xc5, 0xb1, 0x8b, 0xee, 0x31, 0xe8, 0x39, 0x52, 0x44,
- 0x02, 0x2e, 0xdf, 0xd8, 0xec, 0xcf, 0xbc, 0x72, 0xff, 0x81, 0x1d, 0xc9,
- 0xa4, 0xf3, 0x9c, 0xbf, 0xb9, 0xed, 0x34, 0xff, 0x9c, 0xac, 0x3e, 0xa7,
- 0x3a, 0xb3, 0x59, 0xcb, 0xfe, 0x8c, 0xfa, 0x1e, 0x4f, 0x23, 0x97, 0xf8,
- 0x39, 0xff, 0x21, 0xcf, 0xce, 0x5f, 0x33, 0xdf, 0xb9, 0xca, 0x6a, 0x91,
- 0x48, 0x11, 0x4c, 0x37, 0x73, 0x6b, 0xf0, 0xe7, 0x5f, 0xc7, 0x2f, 0x72,
- 0xda, 0xce, 0x53, 0x59, 0xe2, 0xf4, 0x9a, 0xff, 0x23, 0xff, 0xad, 0x03,
- 0xa7, 0x2f, 0xe8, 0x57, 0x05, 0x15, 0x39, 0x7f, 0x67, 0xb8, 0x3d, 0x9d,
- 0x39, 0x58, 0x8b, 0x6e, 0x92, 0x89, 0xa6, 0xcb, 0x6f, 0xff, 0xe5, 0xf3,
- 0xd3, 0x8a, 0x7b, 0x9e, 0xa3, 0xc2, 0xff, 0x9c, 0xbf, 0xfb, 0xc3, 0x1f,
- 0xbf, 0xbf, 0x50, 0x64, 0x72, 0x9a, 0xb6, 0x50, 0xff, 0x0d, 0x0b, 0x28,
- 0x8c, 0x72, 0x45, 0xa1, 0x65, 0xc8, 0x5f, 0xac, 0x8b, 0xe8, 0x56, 0xa1,
- 0x14, 0xc6, 0xfa, 0x8c, 0xbf, 0xa5, 0xef, 0x0e, 0x3f, 0xc8, 0x86, 0x12,
- 0xfb, 0x86, 0x27, 0xa3, 0x3b, 0xe2, 0x76, 0xa2, 0xf5, 0xdc, 0x1d, 0x39,
- 0x7e, 0xd2, 0xdd, 0xd6, 0x68, 0x8b, 0x97, 0xef, 0x7e, 0xa0, 0xc8, 0xa5,
- 0xfb, 0x7e, 0xec, 0x7e, 0x72, 0xfc, 0xf3, 0xc6, 0x80, 0x72, 0xdc, 0xe7,
- 0x46, 0x4e, 0x0d, 0x39, 0xa0, 0x0a, 0x9a, 0x14, 0xd7, 0x35, 0x4b, 0x72,
- 0x94, 0x11, 0x7f, 0xf3, 0x1e, 0x5c, 0xf3, 0x4b, 0x77, 0x59, 0xa2, 0x66,
- 0x5f, 0xdc, 0x2b, 0x85, 0xf8, 0x4d, 0xc7, 0x8e, 0x5e, 0xfa, 0x36, 0x72,
- 0xff, 0xf7, 0x09, 0xe9, 0x67, 0x7a, 0xf2, 0x44, 0x13, 0x97, 0x96, 0x8c,
- 0x39, 0x7d, 0xc3, 0x79, 0xc4, 0xe5, 0xcd, 0x1a, 0xa3, 0x97, 0x60, 0x0e,
- 0x5f, 0xfd, 0x0c, 0x7f, 0x67, 0xdf, 0xb1, 0x4e, 0x9c, 0xbf, 0xfe, 0x85,
- 0xe8, 0x13, 0xfd, 0xb4, 0xd2, 0xfb, 0x87, 0x2b, 0xa8, 0x99, 0x14, 0x7b,
- 0xe4, 0x9c, 0x02, 0x72, 0xfd, 0x93, 0xe7, 0xf3, 0x1c, 0xae, 0x47, 0x99,
- 0xe2, 0x2b, 0xfd, 0xcb, 0x05, 0xf5, 0xfb, 0x43, 0x97, 0xff, 0xe6, 0x3f,
- 0x73, 0xef, 0xfa, 0xdb, 0xf6, 0x6e, 0x80, 0xe5, 0xfd, 0x9b, 0x85, 0x06,
- 0x0e, 0x50, 0x51, 0x7b, 0x86, 0xfd, 0x5a, 0xbb, 0x78, 0x72, 0xee, 0x0f,
- 0x1c, 0xb7, 0x0e, 0x72, 0xdf, 0xc1, 0xb0, 0x00, 0xd5, 0xff, 0xff, 0x90,
- 0x61, 0x63, 0x0c, 0xe5, 0x1a, 0xd2, 0x71, 0xd3, 0xbf, 0xe7, 0x2f, 0x93,
- 0xd1, 0x23, 0x94, 0xd5, 0x2b, 0x46, 0x58, 0xf2, 0x42, 0xbe, 0x66, 0xee,
- 0xc3, 0x85, 0xcb, 0xff, 0x46, 0xf1, 0x3f, 0x16, 0xdb, 0xf9, 0xb8, 0x11,
- 0xcf, 0x1c, 0xbe, 0x7e, 0xa4, 0xc7, 0x2f, 0xbb, 0x34, 0x04, 0xe5, 0x61,
- 0xf8, 0xac, 0xb1, 0xc8, 0xaf, 0xf2, 0xd3, 0x04, 0x3d, 0x83, 0x94, 0x72,
- 0xfb, 0x51, 0x82, 0x72, 0xf9, 0xfd, 0x2f, 0xce, 0x5f, 0xf6, 0xd1, 0x6f,
- 0x9a, 0xcf, 0x1c, 0xbf, 0xcf, 0xa4, 0x86, 0xb4, 0x61, 0xca, 0x62, 0x2b,
- 0xba, 0x41, 0xe2, 0x3e, 0x26, 0xf7, 0xff, 0xb9, 0x75, 0xd3, 0xdf, 0x80,
- 0x45, 0xe4, 0x72, 0xff, 0x94, 0x66, 0x6d, 0xdf, 0xe9, 0x1c, 0xbc, 0xd4,
- 0x5a, 0xae, 0x10, 0xe5, 0x62, 0x7b, 0x6b, 0x31, 0x48, 0x5c, 0xb0, 0xff,
- 0xf4, 0xb1, 0x3a, 0xbf, 0xff, 0xff, 0xff, 0xfc, 0xd4, 0x78, 0x4c, 0x6a,
- 0x3c, 0x37, 0x0b, 0xf0, 0xba, 0xf8, 0x78, 0xe1, 0x6e, 0x1b, 0x53, 0xf0,
- 0x60, 0x02, 0xd4, 0x21, 0xa7, 0xca, 0x77, 0x86, 0x88, 0xe1, 0x9a, 0xf8,
- 0x57, 0xb9, 0x72, 0xeb, 0x43, 0x97, 0xff, 0xef, 0xfe, 0x97, 0x41, 0x1a,
- 0xe7, 0xd4, 0x5b, 0xe8, 0xe5, 0xff, 0xbb, 0x83, 0x8a, 0xe0, 0xe0, 0x4e,
- 0x5f, 0xfd, 0xf3, 0x71, 0xe0, 0xa3, 0x5e, 0xe1, 0x87, 0x2f, 0x90, 0x7d,
- 0xb3, 0x97, 0xff, 0xfc, 0xc4, 0xd7, 0x41, 0xb9, 0x47, 0x1d, 0x40, 0xfb,
- 0xb9, 0x23, 0x95, 0x24, 0x44, 0xa1, 0x0d, 0xff, 0x93, 0xc8, 0xb4, 0x0f,
- 0xb1, 0x67, 0x2a, 0x49, 0xb6, 0xe1, 0xe7, 0xa1, 0xa5, 0xc0, 0x45, 0x7d,
- 0xe6, 0x99, 0xd3, 0x97, 0xff, 0xf9, 0xc5, 0x63, 0x81, 0xe8, 0x39, 0x76,
- 0x25, 0xa8, 0x9c, 0xe5, 0x62, 0x21, 0x80, 0x49, 0x7f, 0xff, 0x9d, 0x51,
- 0xcf, 0xc1, 0xbe, 0x52, 0x4e, 0xc2, 0xc5, 0xce, 0x5f, 0x37, 0x0c, 0xf1,
- 0xcb, 0xc9, 0xd4, 0x39, 0x50, 0x6f, 0xbc, 0x47, 0x7f, 0xcf, 0xa9, 0x72,
- 0xc5, 0x87, 0x0e, 0x57, 0x0c, 0xb9, 0xc3, 0x11, 0x99, 0xe4, 0x78, 0xfd,
- 0x86, 0x5b, 0x91, 0x0c, 0x28, 0x00, 0x41, 0x6d, 0x1c, 0xbf, 0xbd, 0x8c,
- 0xfb, 0x18, 0x72, 0xdd, 0xc3, 0x7e, 0x82, 0x37, 0xf8, 0x01, 0x79, 0x6d,
- 0x24, 0x72, 0xfc, 0xb0, 0x0f, 0xb6, 0x72, 0xfa, 0x24, 0xd1, 0xb3, 0x97,
- 0xfe, 0x18, 0x5a, 0xaf, 0x9a, 0x4f, 0xce, 0x5f, 0xdb, 0xc4, 0xd6, 0x9c,
- 0xe5, 0x4e, 0x7d, 0x5f, 0x9f, 0x5f, 0xff, 0x20, 0xcf, 0x9b, 0x47, 0xef,
- 0x36, 0xdb, 0x6c, 0xa5, 0x41, 0xfc, 0x04, 0x92, 0xfe, 0xfb, 0x3a, 0x0f,
- 0xbf, 0x39, 0x7e, 0xec, 0x4f, 0xd0, 0x1c, 0xac, 0x3d, 0xaf, 0x18, 0xdf,
- 0xf0, 0xe4, 0x2a, 0xfe, 0x75, 0x4e, 0x5f, 0xa5, 0xbf, 0xc1, 0x31, 0xcb,
- 0xcb, 0x02, 0xce, 0x57, 0xc7, 0x90, 0x02, 0xbb, 0xfe, 0x9f, 0x3f, 0x08,
- 0x1f, 0x52, 0x39, 0x7f, 0x3b, 0x87, 0x8e, 0x04, 0xe5, 0xe7, 0x75, 0x9a,
- 0x2c, 0xf5, 0xfd, 0xfb, 0x8c, 0x91, 0x87, 0x2a, 0x74, 0x5f, 0x04, 0xed,
- 0x65, 0xdf, 0x94, 0x5f, 0xee, 0xfb, 0x6f, 0xf2, 0x8c, 0x39, 0x7f, 0xdd,
- 0x89, 0x27, 0xa3, 0xdb, 0x39, 0x50, 0x7d, 0xc8, 0x6d, 0x7f, 0xfb, 0x5d,
- 0x7e, 0x59, 0xc4, 0x73, 0x78, 0x27, 0x2f, 0xfa, 0x10, 0x38, 0xc6, 0xf3,
- 0xa7, 0x2f, 0xfe, 0xdf, 0x92, 0x66, 0xdc, 0x31, 0xf6, 0xce, 0x52, 0x23,
- 0x29, 0xd2, 0xc0, 0x71, 0x79, 0xb6, 0xdb, 0x29, 0x7f, 0xe7, 0x96, 0xc7,
- 0x16, 0x1c, 0xd1, 0x4e, 0x66, 0x82, 0xfd, 0xc0, 0x06, 0x60, 0x4e, 0x5f,
- 0xef, 0x77, 0x38, 0xf2, 0x93, 0x0e, 0x56, 0x1f, 0x18, 0x0a, 0xef, 0xfd,
- 0xf4, 0x84, 0x1f, 0xf2, 0x5b, 0x3f, 0x39, 0x74, 0x2a, 0x72, 0xff, 0x83,
- 0x03, 0x1f, 0xcb, 0xa8, 0x72, 0xa1, 0x12, 0x93, 0xa2, 0xa0, 0xbd, 0xfe,
- 0xea, 0x04, 0x5d, 0xe6, 0x39, 0x7f, 0x83, 0xd0, 0x3f, 0xed, 0x30, 0xe5,
- 0x41, 0xf4, 0x21, 0x95, 0xfe, 0x8e, 0x5e, 0xcd, 0xee, 0x0e, 0x5f, 0xc1,
- 0x50, 0x20, 0xf6, 0xce, 0x59, 0x34, 0x7c, 0x82, 0x69, 0x7a, 0x05, 0x53,
- 0x95, 0x26, 0x41, 0x68, 0x49, 0x70, 0xcd, 0x52, 0x85, 0xc6, 0x0f, 0xf3,
- 0xda, 0x10, 0xcd, 0x08, 0x0d, 0x43, 0x85, 0x90, 0xad, 0xec, 0x3a, 0xbf,
- 0x4e, 0x18, 0x59, 0x6e, 0x16, 0xbe, 0x84, 0xbf, 0x18, 0x42, 0x28, 0x4d,
- 0x77, 0xfb, 0x39, 0x7f, 0xc0, 0xf6, 0xc7, 0x26, 0x86, 0x1c, 0xbe, 0xfd,
- 0xdb, 0xf1, 0xcb, 0xfc, 0xed, 0xf5, 0x23, 0x50, 0x72, 0x82, 0x8a, 0x75,
- 0x46, 0x10, 0xe7, 0x44, 0x97, 0xfe, 0xd2, 0x6e, 0x4a, 0x76, 0x06, 0x0e,
- 0x5f, 0x69, 0x21, 0x87, 0x2f, 0xff, 0xde, 0x54, 0x11, 0x81, 0xee, 0x6f,
- 0xe9, 0x47, 0x4e, 0x56, 0x91, 0x6c, 0xc3, 0xe1, 0x21, 0xb9, 0xe4, 0x72,
- 0xff, 0xff, 0xfe, 0x17, 0x6f, 0xd9, 0xd1, 0xcf, 0x03, 0xf6, 0x3c, 0x9c,
- 0x30, 0x2f, 0xa7, 0x91, 0xcb, 0xfd, 0x9d, 0xe8, 0x3c, 0xe2, 0x72, 0xe4,
- 0x09, 0xcb, 0xfb, 0xab, 0x7d, 0x3c, 0x8e, 0x59, 0x72, 0x3c, 0x3c, 0x16,
- 0xbc, 0x93, 0x6c, 0xe5, 0x41, 0xe2, 0x30, 0x9e, 0xc8, 0x14, 0xdd, 0xa6,
- 0x16, 0xd4, 0x21, 0x99, 0x0b, 0x9b, 0xfb, 0x92, 0x75, 0xd8, 0x87, 0x2f,
- 0x71, 0xc0, 0x9c, 0xb6, 0xa7, 0x3c, 0xc9, 0x8b, 0xaf, 0xfd, 0x8d, 0xf0,
- 0x6b, 0x38, 0x04, 0x0d, 0x9c, 0xa8, 0x55, 0x5f, 0xd8, 0xe9, 0x5e, 0x13,
- 0x42, 0x55, 0x7f, 0xff, 0xfd, 0xfe, 0xf3, 0x05, 0x55, 0x34, 0x31, 0x9d,
- 0xe7, 0xb1, 0xc9, 0xd9, 0x8c, 0x39, 0x7e, 0x52, 0x05, 0x46, 0x1c, 0xac,
- 0x45, 0x4f, 0xa1, 0x01, 0x77, 0xfb, 0x39, 0x7c, 0xfd, 0x85, 0x0e, 0x56,
- 0x1b, 0xae, 0x23, 0x17, 0xff, 0xc0, 0xfa, 0x5b, 0x0f, 0x63, 0x41, 0x77,
- 0x6c, 0xe5, 0x62, 0x35, 0x51, 0x84, 0x48, 0xaf, 0x0b, 0x10, 0xe5, 0xed,
- 0xc4, 0xe7, 0x2f, 0x06, 0x24, 0x72, 0xff, 0xa3, 0x17, 0xd4, 0xe2, 0xfa,
- 0x39, 0x76, 0x74, 0xe5, 0x39, 0xf5, 0x88, 0xe3, 0x43, 0x9b, 0xb0, 0x27,
- 0x2a, 0x49, 0x8a, 0xe1, 0x6e, 0xc6, 0xfd, 0x08, 0x8e, 0x25, 0xf7, 0xba,
- 0x06, 0xce, 0x5e, 0xfc, 0x0b, 0x39, 0x7b, 0xd8, 0xa1, 0xcb, 0xfd, 0x0c,
- 0x06, 0xfd, 0x9e, 0x39, 0x7f, 0x47, 0xdb, 0xe5, 0xa8, 0x39, 0x78, 0x20,
- 0x59, 0xcb, 0xe0, 0x8c, 0x48, 0xe5, 0x21, 0xbe, 0x71, 0xda, 0x0a, 0x63,
- 0x3f, 0x0f, 0x20, 0xf4, 0xc3, 0xac, 0x33, 0xeb, 0x75, 0xfe, 0x49, 0x9c,
- 0x53, 0xed, 0x9c, 0xbb, 0x16, 0x72, 0xff, 0x0f, 0xb6, 0x31, 0xed, 0x9c,
- 0xbf, 0x27, 0x1c, 0x1d, 0x9c, 0xac, 0x3d, 0xad, 0x19, 0x5f, 0xdf, 0x7b,
- 0x3a, 0x06, 0xb3, 0x97, 0xf6, 0xb3, 0xbd, 0x07, 0x8e, 0x5f, 0xba, 0x31,
- 0x9a, 0x31, 0x7f, 0x66, 0xa7, 0x03, 0x84, 0xd1, 0x06, 0xb9, 0x9a, 0x6b,
- 0x6a, 0x74, 0x50, 0xc9, 0x52, 0xf8, 0x7b, 0x9f, 0x1c, 0xa8, 0x4c, 0x7d,
- 0x21, 0xa6, 0xe5, 0x57, 0xe7, 0x5a, 0x32, 0x0e, 0x5f, 0xd2, 0xe8, 0xbf,
- 0xde, 0x39, 0x4b, 0x3d, 0x41, 0x26, 0xbe, 0x50, 0x5e, 0x73, 0x95, 0x87,
- 0x89, 0xb2, 0x1b, 0xf4, 0x7b, 0x93, 0x1b, 0x39, 0x7f, 0xa4, 0x8c, 0x8e,
- 0xa8, 0x13, 0x97, 0xff, 0xa3, 0x07, 0xef, 0x66, 0x92, 0x77, 0x61, 0xcb,
- 0xf3, 0xb7, 0xec, 0xee, 0xcf, 0xf7, 0xc6, 0x95, 0xc9, 0x5d, 0xb3, 0x56,
- 0x67, 0x0e, 0x12, 0x8d, 0x03, 0x21, 0x97, 0xa2, 0x11, 0x85, 0x45, 0xed,
- 0xe4, 0x8e, 0x5d, 0x8a, 0x1c, 0xbe, 0xff, 0xb0, 0x13, 0x97, 0xfd, 0x1f,
- 0xb2, 0x30, 0x7d, 0xb3, 0x94, 0x87, 0xb7, 0xd2, 0x3b, 0xf2, 0x7d, 0x24,
- 0x13, 0x97, 0x93, 0xb8, 0x72, 0xe8, 0x66, 0x1e, 0x12, 0xc9, 0xef, 0xe6,
- 0xf1, 0x91, 0xa5, 0x4e, 0x5f, 0x07, 0x7d, 0x83, 0x97, 0xe1, 0xd3, 0x6f,
- 0x39, 0xca, 0x83, 0xfa, 0xc2, 0xf7, 0x22, 0xbf, 0x67, 0xb6, 0x8c, 0x39,
- 0x70, 0x04, 0xe5, 0x42, 0xa0, 0x09, 0x0e, 0x63, 0x92, 0x31, 0xea, 0x14,
- 0xc2, 0x59, 0xb2, 0x7b, 0xdd, 0xc1, 0x39, 0x7f, 0xb0, 0x73, 0xef, 0x49,
- 0x87, 0x2e, 0xf4, 0x1c, 0xa8, 0x3c, 0x97, 0x33, 0xbf, 0xd3, 0x44, 0xec,
- 0x79, 0xa0, 0xe5, 0xff, 0xf3, 0xab, 0xe8, 0xd7, 0xfa, 0x8f, 0x0b, 0xfe,
- 0x72, 0xfe, 0x1c, 0xff, 0x06, 0x47, 0x2f, 0xff, 0x95, 0xe4, 0xa0, 0xbf,
- 0xb6, 0x9f, 0x75, 0x1b, 0x39, 0x61, 0xc4, 0x40, 0xb9, 0x65, 0x62, 0x76,
- 0x3a, 0x64, 0x72, 0x01, 0x35, 0x04, 0x34, 0xae, 0xdf, 0x13, 0x97, 0x27,
- 0x8e, 0x5f, 0x20, 0xb8, 0x4e, 0x5f, 0xf9, 0x99, 0xed, 0xa9, 0xb7, 0x96,
- 0x1c, 0xbf, 0x6e, 0x35, 0xe8, 0x39, 0xcc, 0xdf, 0xd0, 0x51, 0x31, 0xb5,
- 0xfb, 0xf2, 0x93, 0x3b, 0xe8, 0xe5, 0xf7, 0x71, 0x38, 0x9c, 0xbf, 0xb6,
- 0x9a, 0xc0, 0x68, 0xe5, 0xff, 0xfd, 0x37, 0x24, 0x58, 0x35, 0xb0, 0x72,
- 0x62, 0x7b, 0xa8, 0x72, 0xe8, 0x54, 0xe5, 0x41, 0xfc, 0x23, 0x0d, 0x62,
- 0x7f, 0x6a, 0x8c, 0xa4, 0x2b, 0x98, 0x47, 0xd2, 0x9f, 0x11, 0xf0, 0x42,
- 0x96, 0xe6, 0x70, 0x86, 0x8b, 0xf1, 0x7d, 0xbd, 0x66, 0x1c, 0xbf, 0xfa,
- 0x5e, 0x04, 0xa4, 0xcf, 0x7a, 0x18, 0x72, 0xff, 0x7b, 0x71, 0x3e, 0x6c,
- 0x27, 0x2e, 0xee, 0x1c, 0xbf, 0xfe, 0xec, 0x07, 0x17, 0xcb, 0x07, 0x03,
- 0xd8, 0x39, 0x7f, 0xda, 0x8e, 0xa7, 0x1d, 0x44, 0x8e, 0x5f, 0xfc, 0x98,
- 0x39, 0x9b, 0xe5, 0x2d, 0xb0, 0xe5, 0xff, 0x9e, 0x3e, 0x97, 0x2d, 0xfc,
- 0x18, 0x39, 0x41, 0x4f, 0x03, 0xe2, 0x14, 0x46, 0x6b, 0x34, 0x98, 0x5b,
- 0x49, 0xfb, 0x3a, 0xf2, 0x25, 0xe5, 0x63, 0x47, 0x2f, 0xe0, 0xc7, 0xfa,
- 0xcf, 0x8e, 0x57, 0x33, 0xcc, 0x60, 0xed, 0xcb, 0x9c, 0xe5, 0xfe, 0x86,
- 0x62, 0x6a, 0x69, 0x1c, 0xb9, 0x26, 0x39, 0x7f, 0xb5, 0x0a, 0x84, 0x63,
- 0xe3, 0x97, 0xff, 0xbd, 0x1d, 0x17, 0x9e, 0x35, 0xa7, 0x91, 0xcb, 0xde,
- 0x49, 0xce, 0x5f, 0xbf, 0x7f, 0xa2, 0x63, 0x97, 0x86, 0x16, 0x72, 0xff,
- 0xe0, 0xa4, 0xdd, 0x8d, 0x7d, 0x28, 0xd1, 0xcb, 0xff, 0xc8, 0x2f, 0xf6,
- 0xf7, 0x9a, 0x0f, 0x70, 0xe5, 0x72, 0x4e, 0x16, 0x42, 0xe8, 0x68, 0xc4,
- 0x97, 0x1d, 0x12, 0xad, 0x8d, 0xf0, 0x23, 0x5a, 0x0e, 0x5e, 0xea, 0x78,
- 0xe5, 0xb8, 0xe1, 0xac, 0x50, 0x42, 0xa1, 0x77, 0x64, 0x2e, 0x39, 0x1f,
- 0x4a, 0x43, 0x09, 0x84, 0x9d, 0x18, 0x78, 0xee, 0x3f, 0x85, 0x05, 0xe6,
- 0x3a, 0x87, 0x2f, 0xfb, 0x06, 0x43, 0x8c, 0x85, 0x9c, 0xbf, 0x75, 0x38,
- 0xe0, 0x4e, 0x5f, 0xf8, 0x30, 0x38, 0x20, 0x96, 0x6c, 0xe5, 0xf9, 0xd8,
- 0x9c, 0x18, 0x72, 0xfe, 0xce, 0xbf, 0x9e, 0x63, 0x97, 0x47, 0xc7, 0x2b,
- 0xe3, 0xc4, 0xf1, 0x6d, 0x62, 0x24, 0x1d, 0xb6, 0xf4, 0x24, 0xc7, 0x2e,
- 0xd6, 0x1c, 0xbc, 0x2d, 0x57, 0x01, 0xcb, 0xf6, 0x4e, 0xc8, 0xd9, 0xcb,
- 0xff, 0xff, 0x47, 0x51, 0x9c, 0xe6, 0x93, 0xe9, 0x4e, 0xa7, 0xdb, 0x5a,
- 0x4e, 0x72, 0xa7, 0x54, 0xb2, 0x11, 0xd5, 0x4d, 0x90, 0xa6, 0x68, 0x66,
- 0x74, 0x87, 0xf1, 0xc1, 0x16, 0xd9, 0x27, 0x01, 0x45, 0xe4, 0xee, 0xce,
- 0x5f, 0x72, 0x79, 0x35, 0x27, 0x2f, 0xfe, 0xce, 0x38, 0x1c, 0x10, 0x4b,
- 0x36, 0x72, 0xfd, 0xa8, 0xea, 0x81, 0x39, 0x5a, 0x3e, 0xd7, 0x44, 0xbe,
- 0x84, 0x9e, 0x0e, 0x5f, 0x36, 0xf9, 0xb3, 0x97, 0xf0, 0x63, 0xf1, 0xcf,
- 0x8e, 0x5f, 0xf4, 0x98, 0xf2, 0xf6, 0xe1, 0x53, 0x95, 0x08, 0x8a, 0xc2,
- 0x27, 0x2e, 0xbd, 0xb4, 0x13, 0x97, 0xe1, 0x5f, 0x2d, 0xfc, 0x72, 0xff,
- 0x29, 0x28, 0xe2, 0x83, 0xf9, 0xca, 0xc3, 0xfc, 0x71, 0xb1, 0x2b, 0xac,
- 0x54, 0xa6, 0xd6, 0x38, 0xf0, 0x96, 0xfc, 0x84, 0x61, 0x56, 0x08, 0x54,
- 0xdd, 0x3c, 0x8e, 0x5e, 0x4e, 0xa1, 0xca, 0xf8, 0xd9, 0xf8, 0x62, 0xf9,
- 0x40, 0x3e, 0xce, 0x5f, 0xf2, 0x2b, 0x01, 0x8e, 0x39, 0xd3, 0x97, 0xfd,
- 0xd4, 0x6f, 0xe9, 0x6f, 0x16, 0x72, 0xfe, 0x06, 0xe2, 0x60, 0x68, 0xe5,
- 0xe0, 0x67, 0xc7, 0x2b, 0xa7, 0x99, 0xe2, 0xfb, 0xfd, 0x20, 0x0c, 0xfb,
- 0x4f, 0x8e, 0x5f, 0x7f, 0xfe, 0x7c, 0x72, 0xfe, 0xe0, 0xf6, 0x38, 0xac,
- 0xe5, 0xff, 0x01, 0xe4, 0x1c, 0xcf, 0xf6, 0x72, 0xff, 0xdf, 0x4b, 0xb0,
- 0xc7, 0xfa, 0x58, 0x72, 0xfe, 0x4f, 0xbe, 0x96, 0x78, 0xe5, 0x61, 0xf7,
- 0xfe, 0x81, 0x5d, 0x46, 0x56, 0xe1, 0x51, 0x7e, 0xfb, 0x6c, 0x46, 0xb3,
- 0x97, 0xff, 0xec, 0xdf, 0x2e, 0xba, 0x7b, 0xf0, 0x08, 0xbc, 0x8e, 0x54,
- 0x22, 0x08, 0x4b, 0x2f, 0xe7, 0x9f, 0xf7, 0x10, 0x9c, 0xa9, 0xd5, 0x97,
- 0x84, 0xe9, 0x70, 0x87, 0x98, 0x8b, 0x46, 0xbd, 0x25, 0xf4, 0x3e, 0x78,
- 0xc2, 0xa9, 0xa1, 0x0d, 0xef, 0x60, 0x9c, 0xbd, 0xd7, 0x6b, 0x39, 0x7f,
- 0x94, 0x85, 0xb4, 0xcd, 0x41, 0xcb, 0xfe, 0x0e, 0x03, 0x53, 0xad, 0x27,
- 0x39, 0x7f, 0x47, 0x53, 0x50, 0xc3, 0x95, 0x24, 0x6b, 0x2a, 0x37, 0xd1,
- 0xf7, 0x35, 0xf1, 0xdd, 0x42, 0xe8, 0x3e, 0x4b, 0x52, 0x78, 0xda, 0xee,
- 0x98, 0x07, 0x2c, 0xc3, 0x95, 0xf1, 0xa9, 0xe1, 0xc6, 0x2f, 0xf7, 0xbf,
- 0x00, 0xed, 0x02, 0x72, 0xfd, 0x2f, 0xf3, 0x02, 0x72, 0xfa, 0x35, 0x9c,
- 0x50, 0xf7, 0x1c, 0xd2, 0xff, 0xf4, 0xc3, 0x1e, 0xdf, 0xbe, 0x5a, 0x0c,
- 0xe7, 0x2f, 0xc8, 0xc5, 0x26, 0xd9, 0xcb, 0xf9, 0xfe, 0x90, 0xc0, 0x4e,
- 0x5f, 0xf4, 0x7d, 0x24, 0x16, 0x3f, 0x8e, 0x52, 0x23, 0x6f, 0xa9, 0x8e,
- 0x54, 0x25, 0xb7, 0xe7, 0x96, 0x4f, 0x07, 0x2f, 0xfe, 0x8d, 0xef, 0x19,
- 0xe1, 0x86, 0x6c, 0xe5, 0xfe, 0x0e, 0xd3, 0xbd, 0xc0, 0x9c, 0xbf, 0xf9,
- 0x23, 0x62, 0xf2, 0xe5, 0xbc, 0xd1, 0xcb, 0xff, 0xfc, 0x9b, 0x9f, 0x1b,
- 0xc1, 0x07, 0x04, 0x73, 0xc1, 0x7d, 0x1c, 0xbf, 0xdf, 0x4b, 0x73, 0x4a,
- 0x27, 0x39, 0x41, 0x4d, 0xf1, 0x64, 0xee, 0x86, 0x26, 0x7e, 0x44, 0x03,
- 0x25, 0xff, 0xff, 0xba, 0x9f, 0x7b, 0x3e, 0xf6, 0xb5, 0x1e, 0xfd, 0x41,
- 0x97, 0x70, 0xe5, 0xfb, 0xb1, 0xc4, 0x30, 0x72, 0xf0, 0x5c, 0x4e, 0x5b,
- 0x89, 0xcb, 0xf7, 0xde, 0x18, 0xe9, 0xcb, 0x6a, 0x0d, 0xdb, 0x89, 0xdc,
- 0x0d, 0x1c, 0xa9, 0x22, 0xec, 0x25, 0x3a, 0x56, 0xd9, 0x2d, 0xff, 0xa5,
- 0x03, 0xed, 0x27, 0x1c, 0x09, 0xcb, 0xff, 0x3f, 0xb6, 0x09, 0x28, 0x14,
- 0xf1, 0xcb, 0xd8, 0x9b, 0x39, 0x7f, 0xfd, 0x3b, 0xf7, 0x03, 0xcb, 0x04,
- 0x71, 0x3f, 0x39, 0x53, 0x9f, 0x5e, 0x86, 0xef, 0xfb, 0xab, 0x47, 0xe5,
- 0xb7, 0xe9, 0xca, 0xc3, 0xdd, 0x72, 0x3b, 0xfb, 0xae, 0x3f, 0x49, 0x0e,
- 0x5f, 0xff, 0xb6, 0x3c, 0xba, 0xe9, 0xef, 0xc0, 0x22, 0xf2, 0x39, 0x7f,
- 0xba, 0x8a, 0xb4, 0x06, 0x95, 0x39, 0x7f, 0xd0, 0xdb, 0x3b, 0x08, 0x33,
- 0x9c, 0xbf, 0xfe, 0x1c, 0xde, 0x32, 0x17, 0x9e, 0x4d, 0x61, 0xcb, 0x62,
- 0xd1, 0x7b, 0xe3, 0x8e, 0x27, 0x37, 0xf4, 0xf9, 0xa4, 0x5c, 0x1c, 0xbe,
- 0x10, 0xc3, 0x0e, 0x5f, 0xff, 0x00, 0x7d, 0xbe, 0xa4, 0xc3, 0x0c, 0x79,
- 0x1c, 0xbe, 0xc1, 0x03, 0x9c, 0xa6, 0x1f, 0x7f, 0x14, 0xfb, 0xf9, 0xff,
- 0xc0, 0xbc, 0x8e, 0x54, 0x23, 0x87, 0x21, 0x20, 0x84, 0x94, 0x89, 0xa0,
- 0x76, 0x30, 0xea, 0x86, 0x4a, 0x8c, 0xf0, 0x83, 0x0c, 0x62, 0x79, 0x1d,
- 0xb2, 0xd5, 0x92, 0x32, 0xb9, 0x8f, 0x58, 0x7f, 0xd8, 0xc2, 0x1c, 0x83,
- 0xf2, 0xd1, 0x8c, 0x4f, 0xd1, 0xbb, 0xdf, 0xfd, 0x83, 0xfe, 0x66, 0xb7,
- 0xe8, 0xc3, 0x97, 0xfd, 0xf7, 0xb3, 0x49, 0x3b, 0xb0, 0xe5, 0xec, 0xe3,
- 0x87, 0x2d, 0x9f, 0xa2, 0x64, 0x50, 0xb6, 0x75, 0x7b, 0x87, 0x92, 0x1c,
- 0xbe, 0x81, 0x79, 0x1c, 0xbf, 0x63, 0x5b, 0x8f, 0xfc, 0x8f, 0x07, 0x44,
- 0x37, 0xf7, 0x1e, 0xa4, 0x6b, 0x67, 0x2f, 0xfd, 0xd4, 0x60, 0x72, 0x68,
- 0xcd, 0x1c, 0xbd, 0x28, 0xf8, 0xe5, 0xf4, 0x7e, 0xec, 0x39, 0x70, 0xcb,
- 0x0f, 0xf6, 0x63, 0xe1, 0x1d, 0xbe, 0xda, 0x7a, 0x0e, 0x54, 0x1e, 0xd3,
- 0x9c, 0xdf, 0xfc, 0xb4, 0xd7, 0x21, 0x79, 0xc6, 0x3e, 0x39, 0x7c, 0xbe,
- 0xa4, 0xc7, 0x2f, 0xff, 0xc3, 0x8a, 0xaa, 0x81, 0xea, 0x4d, 0xd4, 0xfb,
- 0xc7, 0x2a, 0x0f, 0xef, 0x08, 0xef, 0x2d, 0xf4, 0x72, 0xfd, 0xb5, 0xc6,
- 0x95, 0x39, 0x7f, 0x27, 0xff, 0x4b, 0x3c, 0x72, 0xba, 0x7e, 0x9f, 0x8e,
- 0x71, 0x29, 0xbf, 0xa5, 0x88, 0x1e, 0xa1, 0xcb, 0xcf, 0xa5, 0x4e, 0x56,
- 0x1e, 0x4b, 0x96, 0x5f, 0xfd, 0x9f, 0x7b, 0x68, 0x31, 0xfb, 0xb0, 0xe5,
- 0xe9, 0x33, 0xa7, 0x2a, 0x73, 0xe1, 0xf2, 0x25, 0xfd, 0xf6, 0xf1, 0x90,
- 0xd6, 0x72, 0xf2, 0xa8, 0xd9, 0xcb, 0xf3, 0x69, 0x82, 0xa9, 0xca, 0x43,
- 0xc6, 0x00, 0xf5, 0x62, 0x2e, 0xdc, 0x8c, 0x5d, 0xee, 0xe5, 0x87, 0x2f,
- 0xb6, 0x30, 0xc3, 0x95, 0x06, 0xe7, 0xe1, 0x8b, 0xdd, 0x93, 0x0e, 0x5d,
- 0xd4, 0x39, 0x58, 0x6c, 0xfc, 0x3b, 0x50, 0xbb, 0x8b, 0x27, 0x6c, 0x43,
- 0x56, 0x30, 0x6f, 0x88, 0x3b, 0x0c, 0x17, 0x84, 0xa0, 0xbd, 0xee, 0x33,
- 0xc0, 0x33, 0x34, 0x54, 0xbf, 0xd1, 0x32, 0x7d, 0xb0, 0x30, 0xe5, 0xcc,
- 0x59, 0xca, 0x9c, 0xf3, 0x02, 0x6b, 0x7f, 0x2c, 0x29, 0xc6, 0x02, 0x72,
- 0xdd, 0x39, 0x6f, 0xce, 0x5d, 0xb9, 0x1c, 0xa7, 0x3e, 0x9f, 0xcb, 0xf6,
- 0x22, 0x01, 0x2b, 0xfa, 0x79, 0xa5, 0xc3, 0x6a, 0x73, 0x97, 0x9f, 0x34,
- 0x72, 0xf0, 0xe7, 0x8e, 0x57, 0x4d, 0xb0, 0x8d, 0xdd, 0xe1, 0x39, 0x7a,
- 0x3e, 0xd9, 0xcb, 0xe4, 0x19, 0x61, 0xcb, 0xd3, 0xb8, 0x9c, 0xa0, 0x9e,
- 0xcb, 0x07, 0x7c, 0x41, 0x7e, 0xcf, 0x75, 0x3c, 0x72, 0xfc, 0xff, 0x67,
- 0xde, 0x39, 0x65, 0x7a, 0x7a, 0x1e, 0x27, 0xb4, 0xe7, 0x2d, 0xa3, 0x95,
- 0x39, 0xa3, 0x41, 0x2b, 0xfa, 0x7e, 0x53, 0xbb, 0xf4, 0xe5, 0x35, 0x4a,
- 0x86, 0x61, 0xb6, 0x44, 0x18, 0xde, 0x8f, 0xfd, 0x4c, 0x72, 0x1b, 0xfe,
- 0xc0, 0x85, 0x3e, 0xcf, 0xbc, 0x72, 0xf9, 0x63, 0x12, 0x39, 0x5d, 0x3d,
- 0xb7, 0x3a, 0xbf, 0xd1, 0x9e, 0x8e, 0xb8, 0x4e, 0x54, 0xe7, 0xa4, 0x12,
- 0x1b, 0xec, 0xc1, 0xf1, 0xcb, 0xf0, 0x40, 0xfa, 0x91, 0xcb, 0xff, 0x83,
- 0x01, 0xd4, 0x79, 0x16, 0x81, 0x39, 0x7d, 0x34, 0x70, 0x48, 0xe5, 0xfd,
- 0xe5, 0x84, 0x2c, 0xd1, 0xcb, 0xfe, 0x9b, 0x7c, 0x5c, 0x67, 0x00, 0x4e,
- 0x5f, 0x67, 0xb1, 0x87, 0x2e, 0x15, 0x4e, 0x5b, 0x6e, 0x6e, 0x00, 0x43,
- 0x7f, 0x74, 0x13, 0xcd, 0xd4, 0x39, 0x7f, 0xf8, 0x41, 0x2c, 0xda, 0xfa,
- 0x82, 0xf3, 0x9c, 0xbc, 0x39, 0xe3, 0x94, 0x87, 0xc8, 0x29, 0x35, 0x0a,
- 0x94, 0xa7, 0x23, 0x91, 0x00, 0x4a, 0x31, 0x0d, 0x52, 0x64, 0x2f, 0x99,
- 0xd7, 0xa4, 0xde, 0x84, 0xa5, 0xfd, 0xca, 0x68, 0xf0, 0xf1, 0x39, 0x7f,
- 0xf8, 0x63, 0x8e, 0xa3, 0x58, 0x9d, 0x80, 0x9c, 0xb9, 0xd8, 0x72, 0xe9,
- 0x9a, 0x1c, 0xa1, 0x36, 0x1c, 0x45, 0xaa, 0x48, 0xcd, 0xc3, 0x24, 0x79,
- 0xb7, 0x36, 0xa9, 0xf5, 0x47, 0xda, 0xb4, 0x0e, 0x18, 0x77, 0x85, 0xd3,
- 0x5a, 0x80, 0xe4, 0x4b, 0x6c, 0x9e, 0x30, 0x29, 0x4a, 0x08, 0x0c, 0xe9,
- 0xe6, 0x52, 0x3a, 0x95, 0x8f, 0x0d, 0x72, 0xe8, 0xbe, 0x95, 0xb4, 0x91,
- 0xb5, 0x4d, 0x38, 0x1f, 0xa9, 0x4f, 0x4c, 0x94, 0x31, 0xda, 0x41, 0x0b,
- 0xca, 0xe0, 0xfe, 0x57, 0x57, 0x0f, 0x09, 0xc1, 0x9d, 0x29, 0xdd, 0x26,
- 0xdf, 0xd3, 0xe7, 0x60, 0x87, 0xeb, 0x70, 0x8c, 0x69, 0x29, 0x55, 0x49,
- 0x6c, 0xdc, 0x11, 0xaf, 0xd7, 0x37, 0xd7, 0xd2, 0xed, 0xea, 0xb8, 0xdf,
- 0xfe, 0xe6, 0xc7, 0x97, 0x3c, 0xd2, 0xdd, 0xd6, 0x68, 0x9b, 0x17, 0xfb,
- 0x9e, 0x69, 0x6e, 0xeb, 0x34, 0x55, 0xab, 0xfd, 0x29, 0x03, 0xc3, 0x12,
- 0x39, 0x7d, 0x9d, 0x7f, 0x1c, 0xb7, 0x09, 0x87, 0xa8, 0x26, 0x77, 0xff,
- 0xfe, 0x94, 0x71, 0x84, 0xd2, 0xd1, 0x8f, 0x24, 0x1c, 0x0e, 0x2a, 0x72,
- 0xff, 0xf6, 0x92, 0x59, 0x2c, 0x79, 0x0c, 0x30, 0xe5, 0xfe, 0xd6, 0x2e,
- 0x3f, 0x51, 0x87, 0x2f, 0xf7, 0x62, 0x7d, 0x46, 0x04, 0xe5, 0xff, 0xfa,
- 0x27, 0x8d, 0x43, 0x22, 0x3d, 0xd4, 0xfd, 0x87, 0x2a, 0x11, 0x11, 0xd3,
- 0x3a, 0x92, 0x72, 0x28, 0xd7, 0xa4, 0x7e, 0xc2, 0xf6, 0xfb, 0x4c, 0xe8,
- 0x4e, 0x5f, 0xfd, 0xa9, 0x0e, 0x7b, 0x70, 0xcf, 0x2c, 0xe5, 0x41, 0xf3,
- 0x80, 0x8e, 0xf0, 0x70, 0x4e, 0x5e, 0x77, 0x59, 0xa2, 0xb4, 0x5f, 0x95,
- 0xfb, 0x60, 0xf8, 0xe5, 0x2c, 0xf5, 0x10, 0xa2, 0xff, 0xf2, 0x7a, 0x50,
- 0xbe, 0xa7, 0xb6, 0xff, 0x1c, 0xad, 0x1f, 0x5f, 0x12, 0x1b, 0xfc, 0x1f,
- 0xf9, 0x66, 0x91, 0x53, 0x97, 0xff, 0xba, 0x8c, 0x85, 0xe3, 0x30, 0x7c,
- 0xd0, 0xe5, 0xe9, 0x7d, 0x23, 0x97, 0xff, 0xf3, 0xa7, 0x04, 0x08, 0x24,
- 0x9b, 0xdc, 0x72, 0x62, 0xce, 0x5f, 0xff, 0x2e, 0x35, 0x9f, 0xbb, 0x1e,
- 0x50, 0x8b, 0x39, 0x7f, 0xfd, 0x2d, 0xe0, 0xc3, 0x1f, 0x3d, 0xe8, 0x61,
- 0xcb, 0x7a, 0x11, 0x36, 0xe9, 0xd5, 0xd4, 0xc8, 0x3d, 0x0f, 0x9b, 0xff,
- 0xff, 0xd1, 0xc5, 0x3d, 0xbc, 0x55, 0x7d, 0x4f, 0x64, 0xc3, 0x0c, 0x9f,
- 0x1b, 0x39, 0x7f, 0xa3, 0xcf, 0xde, 0x41, 0x83, 0x97, 0xd2, 0xf2, 0x4e,
- 0x72, 0xfc, 0xa7, 0x86, 0x3f, 0x39, 0x5f, 0x1e, 0x67, 0x12, 0x3b, 0xfc,
- 0xf2, 0xf2, 0x4f, 0xd4, 0x39, 0x50, 0x7b, 0x08, 0x4b, 0x7e, 0xce, 0xa6,
- 0x30, 0xe5, 0xf9, 0x3f, 0x62, 0x68, 0xe5, 0xff, 0xc2, 0xe8, 0xbe, 0xb8,
- 0x27, 0xd2, 0x1c, 0xa9, 0xd1, 0x22, 0x12, 0x6e, 0x94, 0x5f, 0xe9, 0x46,
- 0xa7, 0x8d, 0x4e, 0x72, 0xfa, 0x5a, 0xc6, 0x1c, 0xbd, 0x9a, 0xfc, 0xe5,
- 0xfa, 0x6c, 0x0b, 0x1a, 0xce, 0x5f, 0xc3, 0x0d, 0xfd, 0x2d, 0x9c, 0xaf,
- 0x91, 0x34, 0x84, 0x53, 0x0e, 0xf0, 0x16, 0x54, 0x26, 0x21, 0x90, 0xcf,
- 0xbf, 0xff, 0xff, 0xb1, 0x17, 0x9e, 0x81, 0xf6, 0xf9, 0x42, 0x07, 0x19,
- 0xcb, 0x50, 0x92, 0x7d, 0x9c, 0xbf, 0xb3, 0xce, 0x3f, 0x80, 0xe5, 0xfd,
- 0xde, 0x49, 0x3b, 0x89, 0xcb, 0xfd, 0x0c, 0xd8, 0x45, 0xdb, 0x39, 0x7c,
- 0xff, 0xb8, 0x4e, 0x54, 0x91, 0x63, 0x85, 0xa2, 0x5f, 0xb3, 0x3b, 0x73,
- 0xe1, 0x99, 0x49, 0x91, 0x1d, 0xe4, 0xf0, 0xa9, 0x09, 0x0e, 0x43, 0x69,
- 0x52, 0x45, 0x9b, 0xfc, 0x94, 0x91, 0x9f, 0x68, 0xa5, 0x8f, 0x7d, 0x86,
- 0xc3, 0xc2, 0xc4, 0x63, 0x41, 0xd9, 0x3f, 0xa3, 0x39, 0xbf, 0x69, 0x6e,
- 0xeb, 0x34, 0x58, 0x0b, 0xf3, 0xad, 0x4e, 0xcc, 0x72, 0xdc, 0xf0, 0xf7,
- 0xb6, 0x69, 0x7e, 0xd2, 0xdd, 0xd6, 0x68, 0x9d, 0x57, 0xff, 0xfb, 0xb1,
- 0x38, 0x71, 0x9c, 0xf7, 0xbc, 0xea, 0x6c, 0x13, 0x9c, 0xbf, 0x73, 0x63,
- 0xcb, 0x9e, 0x22, 0x66, 0x63, 0x4b, 0xff, 0xfd, 0x02, 0x08, 0xf6, 0xf0,
- 0x79, 0xff, 0xfc, 0x75, 0xe7, 0x39, 0x79, 0x58, 0x61, 0xcb, 0xe7, 0x5a,
- 0x8c, 0x39, 0x7a, 0x5b, 0xe6, 0xa9, 0xe0, 0x71, 0x1d, 0xbf, 0x69, 0x6e,
- 0xeb, 0x34, 0x5b, 0x2b, 0xfb, 0xcf, 0xde, 0x41, 0x83, 0x97, 0xff, 0xf4,
- 0xb9, 0xee, 0x13, 0x02, 0x99, 0xbc, 0xf0, 0xc1, 0xca, 0x84, 0x44, 0x39,
- 0x7d, 0xfa, 0x50, 0x9c, 0x60, 0xe5, 0xff, 0x46, 0xf9, 0xf5, 0x16, 0xfa,
- 0x39, 0x50, 0x7c, 0x5f, 0x94, 0x5f, 0xf4, 0x4a, 0x35, 0x3c, 0x6a, 0x73,
- 0x96, 0xe7, 0x89, 0xcd, 0xb2, 0x17, 0x8f, 0x08, 0x31, 0x22, 0xbf, 0xf0,
- 0xf3, 0x60, 0x13, 0xc2, 0xfc, 0x07, 0x2f, 0xfe, 0x06, 0xf9, 0xe6, 0x9f,
- 0x7d, 0x79, 0x1c, 0xb9, 0xff, 0xc4, 0x44, 0x7e, 0x85, 0x77, 0xcb, 0x39,
- 0x7c, 0xb7, 0x75, 0x9a, 0x2e, 0x65, 0x98, 0x72, 0xb4, 0x6f, 0xdb, 0x2e,
- 0xbf, 0xda, 0x1c, 0xfb, 0xf4, 0x91, 0xcb, 0xa6, 0x61, 0xca, 0x39, 0x6e,
- 0x70, 0x8d, 0x0c, 0x57, 0x42, 0x26, 0xcd, 0x1a, 0x0c, 0x5f, 0xb4, 0xb7,
- 0x75, 0x9a, 0x2e, 0xf5, 0xfe, 0x97, 0x3d, 0xeb, 0x48, 0xd9, 0xcb, 0x73,
- 0xc3, 0xeb, 0x73, 0x4b, 0xee, 0x6a, 0x87, 0xf3, 0x95, 0x0f, 0xd6, 0x85,
- 0x97, 0xb0, 0x00, 0xb3, 0x8f, 0x96, 0x92, 0x95, 0xc3, 0xa8, 0xdc, 0x99,
- 0x0c, 0x2e, 0xa2, 0x3c, 0x28, 0xff, 0x8f, 0x50, 0x61, 0xab, 0xb8, 0x7f,
- 0xfa, 0x17, 0xaa, 0x14, 0x5f, 0xf9, 0xb7, 0x19, 0xf6, 0x83, 0xf4, 0x8e,
- 0x5f, 0xfd, 0x93, 0xe3, 0x7d, 0xcd, 0xe2, 0x09, 0xcb, 0x93, 0x9f, 0x51,
- 0x06, 0x28, 0x17, 0xed, 0xed, 0x8f, 0x23, 0x97, 0xff, 0xff, 0xfe, 0xea,
- 0x75, 0x20, 0x7c, 0x2e, 0xae, 0x78, 0x1e, 0x4f, 0x6f, 0xa9, 0xa8, 0x9d,
- 0xf4, 0xb3, 0x97, 0x6e, 0x0e, 0x5f, 0xfd, 0xf2, 0xc0, 0xff, 0x7b, 0x30,
- 0x55, 0x39, 0x78, 0x5f, 0x9c, 0x26, 0x38, 0xb2, 0x8d, 0xc2, 0x63, 0xc2,
- 0xd7, 0x80, 0xec, 0x39, 0x7e, 0xce, 0x0f, 0x42, 0xa7, 0x2d, 0xc0, 0x72,
- 0xa7, 0x37, 0xf8, 0x57, 0x5a, 0x3f, 0xc1, 0x5b, 0xbf, 0xf6, 0xdd, 0x5e,
- 0xa4, 0x08, 0x20, 0xe5, 0xff, 0xba, 0xfe, 0x7e, 0xfd, 0x2c, 0xf1, 0xca,
- 0xc3, 0xfc, 0x43, 0xdb, 0x9f, 0xf3, 0x97, 0xff, 0xff, 0x85, 0xdb, 0x1c,
- 0xf7, 0xb2, 0x78, 0x17, 0x57, 0x6c, 0x8c, 0x10, 0x9c, 0xbd, 0x8a, 0x6c,
- 0xe5, 0x62, 0x2a, 0x74, 0x2f, 0xc0, 0xeb, 0x7f, 0xbb, 0x81, 0x4e, 0x3a,
- 0xc3, 0x97, 0xf9, 0xe5, 0xac, 0x68, 0x9f, 0x9c, 0xbc, 0xee, 0xb3, 0x44,
- 0xae, 0xbf, 0xca, 0xb8, 0xff, 0xec, 0xe9, 0xca, 0x59, 0xee, 0x21, 0x45,
- 0xfe, 0xf8, 0x5d, 0x57, 0xf4, 0x8e, 0x5f, 0xfd, 0xdc, 0x92, 0xfa, 0x81,
- 0x81, 0xf1, 0xca, 0x43, 0xf7, 0xf1, 0xa5, 0x49, 0x37, 0xe0, 0x9a, 0x6a,
- 0x12, 0x23, 0x09, 0x8b, 0xfd, 0x1a, 0x79, 0x3f, 0xd2, 0x39, 0x7f, 0xff,
- 0xfd, 0xa7, 0x15, 0x23, 0xfc, 0x97, 0x63, 0x88, 0x63, 0x9e, 0x08, 0x25,
- 0x9b, 0x39, 0x74, 0xa7, 0x39, 0x7f, 0xff, 0x9f, 0xed, 0xe6, 0xbd, 0xe7,
- 0x9d, 0x46, 0x07, 0xa8, 0xa9, 0xcb, 0xfe, 0xc4, 0xe2, 0x31, 0x9a, 0x91,
- 0xcb, 0xff, 0xf7, 0xa5, 0x8d, 0x6e, 0x3f, 0xfd, 0xed, 0x46, 0x36, 0x71,
- 0xb3, 0x71, 0x7e, 0xfb, 0xdd, 0x8f, 0xce, 0x53, 0xa2, 0x54, 0x0d, 0x77,
- 0xff, 0xa6, 0x18, 0xf6, 0xfd, 0xf2, 0xd0, 0x67, 0x39, 0x7f, 0xce, 0xd8,
- 0x7b, 0x13, 0xe3, 0x67, 0x29, 0x11, 0x0e, 0x29, 0x97, 0xff, 0xec, 0x4f,
- 0xf1, 0x89, 0xed, 0xc3, 0x1f, 0xef, 0x1c, 0xbf, 0xe8, 0x67, 0xb2, 0x69,
- 0x27, 0x8e, 0x54, 0x91, 0x1d, 0xe5, 0x5b, 0xe0, 0x3e, 0xa4, 0x72, 0xfe,
- 0x18, 0x9f, 0xf7, 0xf1, 0xcb, 0xfc, 0xe1, 0x53, 0x82, 0x06, 0x47, 0x2d,
- 0x0b, 0x3e, 0x46, 0x17, 0x5f, 0xff, 0xe4, 0xf3, 0xb1, 0xc7, 0xfe, 0xb6,
- 0xe3, 0x3a, 0xd2, 0x73, 0x94, 0x14, 0xc3, 0xd2, 0x10, 0xce, 0x4f, 0x7f,
- 0xc0, 0xfd, 0x8f, 0x2d, 0xe8, 0x27, 0x2f, 0xff, 0xf6, 0x20, 0xfb, 0x07,
- 0x90, 0xb8, 0x60, 0x67, 0x8d, 0x1c, 0xb6, 0x79, 0x13, 0x3c, 0x4e, 0xef,
- 0xfb, 0xef, 0xf3, 0x59, 0x9e, 0xd9, 0xca, 0x0a, 0xb1, 0x2c, 0x85, 0x7f,
- 0x63, 0x32, 0x18, 0x66, 0xa8, 0x55, 0x7f, 0xec, 0xef, 0x5e, 0x5f, 0xeb,
- 0x3e, 0x39, 0x7f, 0xd9, 0xf6, 0xc3, 0x0e, 0x33, 0x9c, 0xbf, 0xe7, 0x96,
- 0xfb, 0x1a, 0x50, 0x27, 0x2a, 0x48, 0xb3, 0xc4, 0x0f, 0x1c, 0xdf, 0xfd,
- 0xe4, 0xe2, 0x9e, 0x9a, 0x50, 0x3e, 0x39, 0x7f, 0xf9, 0xf2, 0x5d, 0xc4,
- 0x1c, 0xfd, 0xa6, 0x1c, 0xbc, 0xf2, 0xe7, 0x0c, 0xae, 0x19, 0x42, 0x74,
- 0x30, 0xc9, 0xc8, 0xec, 0x3e, 0x47, 0xd1, 0x9b, 0x21, 0x01, 0xf8, 0xc0,
- 0xc6, 0x65, 0xb9, 0x77, 0x7e, 0x8c, 0x39, 0x42, 0xfe, 0x04, 0x6b, 0xff,
- 0xd9, 0xde, 0x63, 0x81, 0x41, 0xf6, 0x74, 0xe5, 0xef, 0x40, 0x4a, 0x5f,
- 0xfe, 0xeb, 0xa7, 0xa2, 0x49, 0xa9, 0xc1, 0xf9, 0x4b, 0xfc, 0xeb, 0xe6,
- 0x1d, 0x70, 0xfc, 0xe0, 0xf9, 0xf6, 0x39, 0x6e, 0x61, 0x67, 0x79, 0xae,
- 0x34, 0xb6, 0x52, 0xec, 0x7d, 0x0f, 0x4e, 0x30, 0xb0, 0xbf, 0xfd, 0xcd,
- 0x8f, 0x2e, 0x79, 0xa5, 0xbb, 0xac, 0xd1, 0x30, 0xaf, 0xff, 0xec, 0xe2,
- 0xe1, 0xec, 0x73, 0xf7, 0x70, 0x20, 0xf6, 0xce, 0x5f, 0xfe, 0xd3, 0xff,
- 0xcd, 0x5f, 0x49, 0xb8, 0xdc, 0x8e, 0x5d, 0x9c, 0xc5, 0x15, 0xea, 0x2f,
- 0xdc, 0xce, 0x27, 0x2f, 0xfe, 0xe1, 0x33, 0xe9, 0x01, 0xfc, 0x31, 0x23,
- 0x97, 0xe6, 0xad, 0xab, 0x6a, 0x5a, 0x35, 0x47, 0x2f, 0xd8, 0xce, 0x5f,
- 0x35, 0x9c, 0xbf, 0xa1, 0x99, 0xfc, 0x71, 0x39, 0x41, 0x3d, 0xde, 0x97,
- 0x5f, 0xed, 0x62, 0xe3, 0xf5, 0x18, 0x72, 0xfe, 0x8d, 0x43, 0x13, 0x47,
- 0x2f, 0xdd, 0x80, 0xa2, 0xa7, 0x29, 0x11, 0x57, 0xa2, 0x26, 0x1a, 0xf0,
- 0x16, 0x5e, 0xe2, 0xfb, 0x39, 0x7f, 0xa1, 0xe7, 0xf2, 0xaf, 0xa3, 0x97,
- 0xe7, 0xd4, 0x9d, 0x87, 0x2b, 0x0f, 0xe4, 0x47, 0x80, 0x69, 0x7f, 0xb7,
- 0x18, 0x21, 0xec, 0x1c, 0xbf, 0xa3, 0x04, 0x3d, 0x83, 0x97, 0x81, 0xa9,
- 0xb9, 0x1e, 0xe6, 0xcc, 0x6f, 0xff, 0x69, 0x01, 0x8a, 0xe7, 0x81, 0x1f,
- 0x04, 0xe5, 0xff, 0xf9, 0x35, 0xd7, 0xe4, 0x1c, 0x97, 0x63, 0x88, 0x60,
- 0xe5, 0xff, 0x36, 0xa7, 0x61, 0x7d, 0x49, 0x8e, 0x5f, 0x01, 0x98, 0x13,
- 0x96, 0xcf, 0x8f, 0x7b, 0x80, 0xf2, 0xfe, 0x8d, 0x44, 0xb7, 0x87, 0x29,
- 0x69, 0xc7, 0xe8, 0xdf, 0xa9, 0x63, 0x0b, 0x6f, 0x15, 0xdf, 0xfe, 0x85,
- 0xec, 0x1e, 0x4e, 0xa2, 0xbd, 0x43, 0x97, 0xf3, 0x23, 0x07, 0xcd, 0x0e,
- 0x5b, 0x67, 0x2f, 0xd1, 0x83, 0xe6, 0x87, 0x2f, 0x6d, 0xfe, 0xe4, 0x7c,
- 0xf3, 0x17, 0x30, 0x46, 0x98, 0x8f, 0x5f, 0x42, 0xc6, 0xff, 0x9a, 0xf0,
- 0x3d, 0x86, 0xb1, 0x83, 0x94, 0x87, 0xca, 0xe5, 0x17, 0xfd, 0xa9, 0xd7,
- 0xd4, 0xe8, 0x3c, 0x72, 0xba, 0x7b, 0x6e, 0x41, 0x7f, 0x7a, 0x19, 0xc7,
- 0xf9, 0x1c, 0xbb, 0xc8, 0x72, 0xa4, 0x78, 0xea, 0x98, 0xde, 0xd0, 0x36,
- 0x72, 0xff, 0xfb, 0xb0, 0x39, 0xee, 0xe7, 0xbb, 0x00, 0xe1, 0xce, 0x5f,
- 0xff, 0xe6, 0xf8, 0x3d, 0x9d, 0xe4, 0x39, 0x3a, 0x60, 0xfd, 0x2d, 0x9c,
- 0xbf, 0x37, 0xec, 0xea, 0xce, 0x56, 0x22, 0x41, 0xd9, 0xeb, 0x13, 0x21,
- 0x41, 0xd1, 0x87, 0x1d, 0xff, 0xef, 0x0b, 0xff, 0xdc, 0x40, 0x83, 0xdb,
- 0x39, 0x7d, 0xc7, 0x03, 0x07, 0x2f, 0xfa, 0x27, 0x52, 0x5d, 0x03, 0xce,
- 0x72, 0xa1, 0x15, 0x38, 0x95, 0xa2, 0x3b, 0xff, 0xb3, 0xe9, 0x72, 0xeb,
- 0xae, 0x04, 0x27, 0x2f, 0x92, 0x3e, 0xd9, 0xcb, 0xf2, 0x9e, 0x18, 0xfc,
- 0xe5, 0x78, 0xf2, 0xf8, 0x91, 0x5f, 0x7b, 0xd8, 0xd9, 0xcb, 0xff, 0xd1,
- 0xef, 0xe2, 0x59, 0xf7, 0xa7, 0x03, 0x67, 0x2f, 0x6d, 0xff, 0x39, 0x50,
- 0x8b, 0x2c, 0x24, 0x42, 0x3f, 0x27, 0x5c, 0xf2, 0x39, 0x7f, 0xf9, 0x37,
- 0x12, 0xe5, 0x9d, 0x4d, 0x75, 0xce, 0x53, 0x59, 0xf0, 0x74, 0x5a, 0xfe,
- 0x7f, 0xf5, 0xa4, 0xd1, 0xcb, 0xde, 0xe5, 0x87, 0x2b, 0xf3, 0xcc, 0x50,
- 0xba, 0xfb, 0xa0, 0xfb, 0xc7, 0x2f, 0xfd, 0xd4, 0xf2, 0x63, 0x07, 0x27,
- 0x39, 0x7f, 0x6d, 0x15, 0x63, 0xf8, 0xe5, 0xff, 0xb8, 0xc2, 0xb2, 0x41,
- 0x8d, 0x41, 0xcb, 0xff, 0xff, 0x6b, 0x38, 0xc0, 0xfb, 0x92, 0x83, 0x1d,
- 0x74, 0xf4, 0x7b, 0x67, 0x2f, 0xe1, 0xcd, 0xf2, 0x5f, 0x0c, 0x72, 0x96,
- 0x9a, 0x67, 0xc7, 0xa8, 0x5d, 0xa3, 0xfe, 0x2d, 0xd7, 0xdc, 0xb8, 0xf0,
- 0x4e, 0x72, 0x82, 0x9f, 0x46, 0x46, 0xe0, 0xaa, 0x6d, 0x9a, 0xce, 0x5f,
- 0x99, 0xac, 0x0f, 0x8e, 0x5d, 0xec, 0x39, 0x7f, 0xc1, 0x81, 0x8f, 0xdd,
- 0xf8, 0x0e, 0x5f, 0xb7, 0x9e, 0xd4, 0x1c, 0xbf, 0xfd, 0xc3, 0x8c, 0x31,
- 0xd3, 0xaf, 0xee, 0xc1, 0xca, 0x84, 0x61, 0xa0, 0xb6, 0xce, 0x80, 0x4f,
- 0x73, 0xac, 0xe5, 0xfc, 0x93, 0x3a, 0xf7, 0x23, 0x94, 0xb3, 0xc4, 0xe8,
- 0xb5, 0xff, 0xfe, 0xea, 0x08, 0x75, 0x8b, 0xec, 0x77, 0x35, 0xa8, 0x54,
- 0xe5, 0xf8, 0x1c, 0x09, 0x8c, 0x39, 0x7e, 0xf3, 0xb1, 0x3c, 0x72, 0x95,
- 0x3d, 0x11, 0x2a, 0xbf, 0xf2, 0x78, 0x1a, 0x7d, 0xf2, 0x67, 0x8e, 0x54,
- 0x1f, 0x1b, 0x91, 0x5f, 0xf6, 0x26, 0x30, 0x72, 0x77, 0x39, 0x7e, 0x8f,
- 0x6f, 0xf0, 0x1c, 0xa6, 0xa9, 0x59, 0x9c, 0x0a, 0x64, 0x3a, 0xd6, 0xff,
- 0x31, 0x17, 0x63, 0x14, 0x12, 0x0f, 0x1b, 0x5f, 0xff, 0xba, 0x39, 0xee,
- 0xa6, 0x7d, 0xec, 0xe3, 0x1b, 0x39, 0x7c, 0xfb, 0xf4, 0xe7, 0x2f, 0xfe,
- 0x71, 0xec, 0x20, 0x53, 0x79, 0x23, 0x97, 0xa3, 0xf5, 0x0e, 0x5f, 0xd9,
- 0xc7, 0xa9, 0xfc, 0xc7, 0x2b, 0x13, 0x09, 0x55, 0x59, 0xc8, 0xc5, 0x07,
- 0x63, 0xd7, 0xdd, 0x8d, 0xc1, 0xcb, 0xca, 0x07, 0x0e, 0x5e, 0xe1, 0xf7,
- 0xc3, 0x1c, 0xa0, 0x9f, 0x2b, 0x90, 0xec, 0x76, 0xfb, 0x93, 0x39, 0x2c,
- 0xe5, 0xec, 0x58, 0x4e, 0x5f, 0x7b, 0x07, 0xf3, 0x97, 0xf3, 0xb7, 0x1e,
- 0xc9, 0xce, 0x56, 0x1f, 0x62, 0x0e, 0x09, 0x15, 0xf3, 0x73, 0x6e, 0x0e,
- 0x5f, 0xf9, 0xfd, 0xb0, 0xe9, 0xfd, 0xd0, 0x1c, 0xaf, 0x8f, 0x8c, 0x49,
- 0x2d, 0xcd, 0xaa, 0x6d, 0x28, 0x78, 0x61, 0x96, 0xa0, 0x93, 0x11, 0xa3,
- 0x86, 0x17, 0x19, 0x28, 0x61, 0x72, 0x81, 0x3e, 0x68, 0x9a, 0x34, 0x4d,
- 0x43, 0x71, 0x85, 0xdd, 0x8d, 0x0d, 0xe1, 0x35, 0xfb, 0x88, 0xca, 0x0c,
- 0xdc, 0xb6, 0xaf, 0x47, 0x14, 0x08, 0x57, 0x36, 0x5c, 0xd2, 0x12, 0x6a,
- 0x42, 0x3e, 0xff, 0xfb, 0x49, 0xf4, 0xb6, 0x9e, 0xec, 0x6b, 0xd0, 0x72,
- 0xf3, 0xba, 0xcd, 0x15, 0x72, 0xfe, 0x75, 0x3b, 0xd7, 0x61, 0xca, 0x59,
- 0xeb, 0x74, 0xa2, 0xfe, 0x4d, 0x75, 0xd4, 0x61, 0xca, 0xd1, 0xe8, 0x74,
- 0x8a, 0xf8, 0x78, 0x36, 0xe7, 0x2f, 0x6a, 0x18, 0x72, 0xff, 0x46, 0xbd,
- 0x03, 0x1f, 0x9c, 0xbf, 0xdc, 0xf3, 0x4b, 0x77, 0x59, 0xa2, 0x3c, 0x5f,
- 0xf6, 0x07, 0x3a, 0x9a, 0xeb, 0x9c, 0xa9, 0x1f, 0xc3, 0x10, 0x6f, 0xfa,
- 0x25, 0x1a, 0x9e, 0x35, 0x39, 0xcb, 0xfe, 0xf2, 0x03, 0x87, 0xc9, 0x4f,
- 0x31, 0xcb, 0xf8, 0x73, 0xdb, 0xc6, 0xce, 0x54, 0x1f, 0x6b, 0xa0, 0x5f,
- 0xf7, 0xcb, 0x4d, 0xf5, 0x3c, 0x87, 0x2f, 0xde, 0xf6, 0x0f, 0xe7, 0x2f,
- 0xf7, 0x03, 0x86, 0x30, 0x28, 0x72, 0xdc, 0xc2, 0xae, 0x03, 0x21, 0xec,
- 0x84, 0x5a, 0x24, 0xe8, 0xe3, 0xc2, 0xa8, 0x48, 0xb7, 0x0a, 0x7f, 0x10,
- 0x28, 0x73, 0xc0, 0x51, 0x7e, 0xd2, 0xdd, 0xd6, 0x68, 0xb0, 0x57, 0x95,
- 0x89, 0xce, 0x5f, 0xff, 0xc2, 0x07, 0x9d, 0x98, 0xd0, 0x1a, 0xcd, 0x49,
- 0x49, 0x1c, 0xbf, 0x60, 0xe7, 0xb6, 0x72, 0xff, 0x69, 0xd8, 0xa6, 0x9f,
- 0xe3, 0x96, 0xe7, 0x89, 0x86, 0x2a, 0x68, 0xb1, 0xe7, 0x5f, 0x50, 0x9a,
- 0xff, 0x73, 0xcd, 0x2d, 0xdd, 0x66, 0x8b, 0x29, 0x7e, 0xd2, 0xdd, 0xd6,
- 0x68, 0xb4, 0xd7, 0xfc, 0xe1, 0xeb, 0xcd, 0xd4, 0x61, 0xcb, 0x73, 0xc3,
- 0xed, 0x61, 0xa5, 0xfb, 0x85, 0xda, 0x8b, 0x54, 0xd5, 0x35, 0x67, 0x2f,
- 0xfb, 0x86, 0xea, 0x36, 0x17, 0x75, 0x9c, 0xbf, 0x70, 0xbf, 0x09, 0xbc,
- 0x83, 0x97, 0xf9, 0x46, 0x67, 0xb6, 0x9b, 0x39, 0x64, 0x39, 0x5c, 0x31,
- 0xe2, 0x34, 0x34, 0xbf, 0xd1, 0x3e, 0x9c, 0x33, 0xb9, 0xcb, 0xff, 0xf7,
- 0x5c, 0x7d, 0x2c, 0xd6, 0x40, 0x8e, 0x78, 0xe5, 0x49, 0x10, 0xa8, 0x69,
- 0x7e, 0xe2, 0xe1, 0xc6, 0x1c, 0xbe, 0x64, 0x7d, 0xb3, 0x97, 0xff, 0x26,
- 0x3f, 0xf1, 0x2d, 0x46, 0x09, 0xcb, 0xe4, 0xe3, 0xde, 0x27, 0x2f, 0xf7,
- 0x02, 0x7f, 0xc9, 0xfa, 0x03, 0x95, 0x24, 0xc3, 0xb0, 0x8a, 0x62, 0x91,
- 0x23, 0xda, 0x0f, 0x01, 0x35, 0xfe, 0x62, 0x8c, 0xfd, 0x89, 0xf9, 0xcb,
- 0xf7, 0x2d, 0x68, 0x1d, 0x39, 0x7e, 0x45, 0x60, 0x56, 0x72, 0xb6, 0x7a,
- 0x5e, 0x2b, 0xa8, 0x45, 0x5e, 0x42, 0x26, 0xff, 0xf8, 0x57, 0xd4, 0xea,
- 0x6a, 0x26, 0x6f, 0x3a, 0x72, 0xff, 0xdb, 0x4e, 0x5d, 0x7d, 0x47, 0x18,
- 0x39, 0x7f, 0xcc, 0x79, 0x34, 0x07, 0x53, 0x47, 0x2b, 0x47, 0xf8, 0xc4,
- 0x1b, 0xf3, 0xef, 0xd0, 0x13, 0x95, 0x07, 0x92, 0x02, 0x2b, 0xfc, 0xfa,
- 0x93, 0xf9, 0xd6, 0x72, 0xa1, 0x36, 0x8e, 0xc6, 0x2a, 0x02, 0x1b, 0xe8,
- 0x52, 0x3a, 0x72, 0xf9, 0x6e, 0xeb, 0x34, 0x5b, 0x8b, 0xe9, 0xa0, 0x38,
- 0x72, 0xff, 0xd9, 0xac, 0x1e, 0x5d, 0xcf, 0x9b, 0x39, 0x7e, 0x1f, 0xdf,
- 0xed, 0x9c, 0xa8, 0x3e, 0xa7, 0x41, 0xaf, 0x91, 0xf9, 0xa2, 0x27, 0x2e,
- 0xdc, 0x23, 0x2f, 0xf3, 0x8f, 0xf3, 0x0c, 0x30, 0xe5, 0xe6, 0x0a, 0x1c,
- 0xb0, 0x9c, 0xbf, 0xee, 0x81, 0xf7, 0x98, 0x2a, 0x9c, 0xbf, 0x6d, 0xfe,
- 0x70, 0x9c, 0xb2, 0x04, 0xf8, 0x3c, 0x71, 0x50, 0x8b, 0x2c, 0x1b, 0xeb,
- 0x85, 0xff, 0x43, 0x8f, 0x73, 0x05, 0x67, 0x2f, 0xf7, 0xbc, 0x93, 0xb2,
- 0x04, 0xe5, 0x48, 0xfa, 0x30, 0xd6, 0xff, 0xa0, 0x40, 0xc8, 0xdf, 0x90,
- 0xe5, 0xe8, 0xcd, 0x1c, 0xbf, 0xdd, 0x89, 0x23, 0x4c, 0x61, 0xca, 0x09,
- 0xe7, 0xec, 0x6e, 0xfd, 0xcb, 0xed, 0xa2, 0xa7, 0x2c, 0xf3, 0x9e, 0x77,
- 0xc4, 0x57, 0xff, 0x4b, 0x3a, 0x9a, 0x0f, 0x60, 0x56, 0x72, 0xff, 0x7d,
- 0x28, 0x1f, 0x67, 0xe7, 0x2f, 0xb7, 0xfa, 0x78, 0xe5, 0x3a, 0x30, 0xf6,
- 0x52, 0x04, 0x35, 0x0d, 0x2f, 0xcf, 0xaf, 0x67, 0x4e, 0x5f, 0xf9, 0x3f,
- 0x89, 0x07, 0xb0, 0x2b, 0x39, 0x52, 0x3e, 0x5f, 0x13, 0xdf, 0xde, 0x96,
- 0x6b, 0x36, 0x72, 0x8e, 0x5e, 0x03, 0xf8, 0xe5, 0xc0, 0x83, 0x95, 0x23,
- 0x65, 0xe1, 0xca, 0x39, 0x7d, 0xf2, 0xd3, 0x47, 0x2f, 0x43, 0x39, 0xe2,
- 0x23, 0x3e, 0x3d, 0x61, 0x0f, 0x82, 0xef, 0xf8, 0x7d, 0xd7, 0x90, 0x1d,
- 0x43, 0x95, 0x09, 0xb2, 0x61, 0x12, 0x42, 0xe5, 0xd4, 0x2f, 0x0f, 0x9a,
- 0x1c, 0xbd, 0xc9, 0xab, 0x6a, 0xce, 0x5f, 0xf4, 0xb9, 0xe6, 0x96, 0xee,
- 0xb3, 0x45, 0x0e, 0xa4, 0x44, 0x74, 0xc3, 0xce, 0x53, 0x7e, 0xfe, 0x17,
- 0x8c, 0x39, 0x7d, 0x13, 0x60, 0x4e, 0x56, 0x8f, 0x2b, 0x65, 0x17, 0xfd,
- 0x90, 0x1e, 0xc7, 0x04, 0x4c, 0x72, 0xff, 0x7e, 0x9d, 0xee, 0x7e, 0xe7,
- 0x29, 0x87, 0xdf, 0xf9, 0xdd, 0x42, 0x2d, 0x1e, 0x12, 0x37, 0xfe, 0x70,
- 0xc0, 0x7a, 0x82, 0x8c, 0x39, 0x7f, 0xee, 0x2f, 0xad, 0xbf, 0x77, 0x13,
- 0x9c, 0xbf, 0xdb, 0x02, 0xf3, 0xc3, 0x07, 0x29, 0x88, 0xaf, 0xe9, 0xe7,
- 0x90, 0x6f, 0xfe, 0x04, 0xba, 0xfa, 0xfb, 0xd0, 0x93, 0x9c, 0xbf, 0xd2,
- 0x8d, 0x4f, 0x1a, 0x9c, 0xe5, 0xf9, 0xf7, 0xc7, 0x36, 0x72, 0xa0, 0xf7,
- 0xbf, 0x35, 0xbf, 0x72, 0xee, 0x7e, 0xe7, 0x2f, 0xe9, 0x3e, 0xb3, 0xef,
- 0x1c, 0xbf, 0x82, 0xec, 0xea, 0x36, 0x72, 0xa0, 0xf7, 0x30, 0xba, 0xff,
- 0xb3, 0xdb, 0x53, 0x7a, 0x7d, 0x9c, 0xbf, 0x27, 0xb6, 0xe8, 0x72, 0xff,
- 0xb5, 0xfe, 0x9c, 0x7d, 0x9f, 0x9c, 0xa9, 0xd3, 0x40, 0xd4, 0x21, 0x98,
- 0x41, 0xf9, 0xd0, 0x09, 0xaf, 0x29, 0xa9, 0x1c, 0xbf, 0x94, 0xf0, 0x23,
- 0x27, 0x39, 0x7f, 0x7f, 0xd7, 0x4e, 0x80, 0xe5, 0x48, 0xfe, 0xe6, 0x1e,
- 0xd1, 0x7d, 0xff, 0xcb, 0x18, 0xf0, 0xe7, 0x1c, 0xd4, 0x8e, 0x5f, 0xf0,
- 0x05, 0x55, 0x3b, 0xd0, 0x6c, 0xe5, 0xff, 0x29, 0x1f, 0xcd, 0x28, 0xd4,
- 0xe7, 0x2f, 0xe1, 0x7f, 0x29, 0x0b, 0x39, 0x4c, 0x3e, 0xa1, 0x3d, 0xbe,
- 0x1f, 0xe7, 0xfc, 0xe5, 0x61, 0xe3, 0x21, 0x0d, 0xfe, 0xdf, 0x2f, 0x72,
- 0x0e, 0x09, 0xcb, 0x7e, 0x72, 0xc9, 0xf1, 0xe4, 0xe8, 0xde, 0xfc, 0xff,
- 0x6f, 0xc8, 0x72, 0xa1, 0x50, 0xce, 0x18, 0x22, 0x27, 0x61, 0xd8, 0x2d,
- 0x3b, 0x28, 0xbf, 0x38, 0x15, 0x85, 0x0e, 0x5f, 0xb8, 0x6c, 0xd4, 0x6c,
- 0xe5, 0x4c, 0x7a, 0xa2, 0x53, 0x7f, 0x67, 0x90, 0x38, 0xc3, 0x97, 0xc3,
- 0x24, 0x61, 0xcb, 0x72, 0x98, 0xf3, 0x5c, 0xb2, 0xff, 0x6e, 0x26, 0xfa,
- 0x59, 0xc4, 0xe5, 0x04, 0xf8, 0x5c, 0xaa, 0xff, 0xfc, 0x1e, 0xc2, 0x9c,
- 0xfc, 0x2f, 0xfe, 0xf7, 0x1f, 0x94, 0xb8, 0x38, 0x72, 0xfd, 0x3c, 0x4e,
- 0xfb, 0x39, 0x58, 0x89, 0x94, 0x5a, 0x71, 0x6b, 0xbf, 0x01, 0xcb, 0xf9,
- 0xff, 0x98, 0x60, 0x27, 0x2f, 0xf8, 0x72, 0x70, 0xf7, 0x07, 0xc7, 0x2a,
- 0x0f, 0xfb, 0xa3, 0x02, 0x5d, 0x4d, 0x4b, 0x6d, 0xe4, 0xd5, 0xa2, 0xb5,
- 0x13, 0xee, 0x14, 0xef, 0x11, 0xde, 0x4a, 0x30, 0x50, 0xc7, 0x1d, 0x91,
- 0x99, 0x2a, 0x84, 0xb8, 0x72, 0xfd, 0x09, 0x64, 0x21, 0x9a, 0x39, 0x7d,
- 0x4a, 0x06, 0x64, 0x33, 0x7b, 0x19, 0x6b, 0xc3, 0x57, 0xf3, 0x01, 0x85,
- 0x26, 0xe3, 0x62, 0xf4, 0xae, 0x60, 0x42, 0xbf, 0x8c, 0x34, 0x1a, 0x42,
- 0xe9, 0x48, 0x55, 0xdf, 0xff, 0x97, 0xcf, 0xfd, 0x67, 0xcb, 0xea, 0x7b,
- 0x6f, 0xf1, 0xca, 0xe6, 0xa8, 0xb4, 0x11, 0xe9, 0x5f, 0x46, 0xa4, 0xc3,
- 0x97, 0xdf, 0x6d, 0xda, 0xce, 0x5e, 0x7d, 0x2a, 0x72, 0xdc, 0xe7, 0x3e,
- 0x54, 0x22, 0x6c, 0x9a, 0xff, 0x73, 0xcd, 0x2d, 0xdd, 0x66, 0x8b, 0xcd,
- 0x50, 0xee, 0x1a, 0x24, 0xe2, 0x18, 0xc2, 0x72, 0xb4, 0xd1, 0xfa, 0x74,
- 0x33, 0x51, 0xde, 0xb1, 0x4f, 0xb0, 0xae, 0x1a, 0xe5, 0x23, 0x70, 0x92,
- 0xe2, 0x71, 0x7f, 0xb9, 0xe6, 0x96, 0xee, 0xb3, 0x45, 0x2c, 0xbf, 0x69,
- 0x6e, 0xeb, 0x34, 0x58, 0x4b, 0xff, 0xec, 0x10, 0xc7, 0x63, 0xef, 0x60,
- 0xbb, 0x0e, 0x5e, 0x10, 0x2c, 0xe5, 0x41, 0xf4, 0xba, 0x6d, 0xb6, 0x72,
- 0xfe, 0x06, 0x92, 0x77, 0x61, 0xcb, 0x73, 0xc4, 0x7e, 0x32, 0x13, 0xbb,
- 0x20, 0x68, 0x23, 0x7f, 0xb9, 0xe6, 0x96, 0xee, 0xb3, 0x45, 0x96, 0xb4,
- 0x8e, 0x5d, 0xa5, 0x4e, 0x5f, 0x73, 0x57, 0x85, 0x35, 0x27, 0x28, 0xa5,
- 0xee, 0x6a, 0x30, 0xe5, 0x2c, 0xf7, 0x36, 0x62, 0x00, 0xba, 0x55, 0x16,
- 0x82, 0x23, 0xb7, 0x4b, 0xa3, 0xa7, 0x2d, 0xf9, 0xcb, 0x95, 0x9c, 0xe5,
- 0xb5, 0x23, 0x57, 0x82, 0x54, 0xb3, 0xe7, 0x74, 0x1b, 0x93, 0xf3, 0x97,
- 0xfc, 0xff, 0x0e, 0x7d, 0xe8, 0x54, 0xe5, 0xfe, 0x9f, 0xed, 0xc0, 0x7c,
- 0x87, 0x2f, 0xd1, 0x9c, 0x63, 0x67, 0x2d, 0x0e, 0x7b, 0xad, 0x9a, 0xd3,
- 0xa2, 0xf8, 0x61, 0x2f, 0x7c, 0xf2, 0x90, 0x4e, 0x5f, 0xcf, 0xa8, 0xf3,
- 0xf4, 0xe5, 0xe6, 0xdb, 0x6c, 0xa5, 0xff, 0x44, 0xbe, 0xf6, 0xa3, 0x3e,
- 0x29, 0xcc, 0xd0, 0x5f, 0xf0, 0x1f, 0xec, 0xf2, 0x7c, 0xd9, 0xcb, 0xa3,
- 0x67, 0x28, 0x29, 0x85, 0xf4, 0x88, 0x53, 0x36, 0x99, 0xc4, 0xee, 0xee,
- 0x14, 0xd4, 0x9c, 0xbf, 0x91, 0xf7, 0xfe, 0xc0, 0x72, 0xff, 0xe4, 0x93,
- 0xed, 0xc4, 0x0b, 0xcd, 0x94, 0xbf, 0xff, 0xba, 0x9e, 0xee, 0x6c, 0x71,
- 0x80, 0xdf, 0x5e, 0x47, 0x2f, 0xf4, 0x4b, 0xcf, 0xd7, 0x09, 0xca, 0x84,
- 0x67, 0x62, 0x16, 0x96, 0xad, 0x23, 0x96, 0x91, 0xcb, 0x48, 0xe5, 0x96,
- 0x72, 0xa0, 0xf1, 0x15, 0x11, 0x41, 0x1f, 0xc4, 0x6f, 0xe0, 0x6f, 0xaf,
- 0x2c, 0x39, 0x7f, 0xfd, 0xb4, 0x5e, 0x0e, 0xa0, 0x70, 0x38, 0xa9, 0xca,
- 0x61, 0xfd, 0x78, 0xb6, 0xdf, 0x1c, 0xb2, 0xa7, 0x2c, 0x03, 0x94, 0x26,
- 0x8f, 0x62, 0x55, 0x87, 0xef, 0xb2, 0x2f, 0x1a, 0xdd, 0xb5, 0x4e, 0x5b,
- 0x0e, 0x5c, 0x0f, 0xe0, 0xd4, 0x04, 0x62, 0xe4, 0x83, 0x97, 0xf0, 0xc3,
- 0x06, 0x30, 0xe5, 0xff, 0xd0, 0xfa, 0xf7, 0x70, 0x20, 0xf6, 0xce, 0x5d,
- 0x28, 0x39, 0x7b, 0x61, 0x54, 0xe5, 0x4e, 0x8e, 0x40, 0x96, 0xcc, 0x2b,
- 0xd2, 0xa0, 0x22, 0x28, 0x2d, 0x7f, 0xff, 0xfd, 0xd8, 0xf6, 0xd3, 0x7b,
- 0x8f, 0x75, 0x23, 0x5f, 0xb1, 0xe5, 0x2f, 0x2a, 0x72, 0xe4, 0xf8, 0xe5,
- 0xd0, 0xc3, 0x97, 0xff, 0xe8, 0x10, 0x4a, 0x51, 0xee, 0xe3, 0x14, 0x8f,
- 0xce, 0x5f, 0xff, 0x20, 0x82, 0x59, 0xbd, 0x42, 0x49, 0xf6, 0x52, 0xa4,
- 0x8a, 0x3f, 0x2b, 0x5c, 0xbe, 0x70, 0xc8, 0xcd, 0x9e, 0x12, 0xf2, 0x21,
- 0x0c, 0x35, 0x72, 0x33, 0x15, 0x53, 0x16, 0x45, 0xa8, 0x7e, 0x3b, 0x90,
- 0xc6, 0x5b, 0xb8, 0xce, 0xbc, 0xb5, 0xc5, 0xfd, 0xa0, 0xba, 0x90, 0xb9,
- 0xbf, 0xfd, 0xcd, 0x8f, 0x2e, 0x79, 0xa5, 0xbb, 0xac, 0xd1, 0x46, 0x2f,
- 0xdc, 0x63, 0x51, 0xf9, 0xcb, 0xf0, 0xbf, 0xf0, 0xa1, 0xcb, 0xff, 0x27,
- 0xd2, 0xd8, 0xe7, 0xba, 0x03, 0x97, 0xfc, 0x9a, 0xee, 0x60, 0xcb, 0x67,
- 0x2d, 0xf4, 0x8f, 0xd9, 0x67, 0xf7, 0xfe, 0x79, 0x2f, 0xa8, 0xc8, 0xd2,
- 0xa7, 0x2d, 0xce, 0x13, 0x30, 0xe9, 0x57, 0xa1, 0x3c, 0xd9, 0x4d, 0x49,
- 0x9c, 0x4d, 0xa8, 0xcf, 0x58, 0x96, 0xf4, 0x9c, 0x2d, 0xc6, 0x0f, 0xe8,
- 0xe2, 0xaf, 0xfe, 0xe6, 0xf2, 0xe7, 0x9a, 0x5b, 0xba, 0xcd, 0x11, 0xca,
- 0xff, 0xf7, 0x36, 0x3c, 0xb9, 0xe6, 0x96, 0xee, 0xb3, 0x44, 0xe4, 0xbf,
- 0xdc, 0xf3, 0x4b, 0x77, 0x59, 0xa2, 0xcc, 0x5f, 0xf4, 0xb6, 0xec, 0xe7,
- 0xdf, 0x7e, 0x72, 0xff, 0xb8, 0x58, 0x38, 0xc8, 0xfa, 0x18, 0x72, 0xff,
- 0x6a, 0x3d, 0xd7, 0xfa, 0x47, 0x2f, 0xff, 0xff, 0xa2, 0x6e, 0xc7, 0xa1,
- 0x44, 0xd4, 0xd1, 0xdc, 0xe3, 0x9d, 0xc0, 0xf1, 0xc3, 0x95, 0xfa, 0x2d,
- 0x44, 0xd2, 0xff, 0xb3, 0x6f, 0xef, 0xd4, 0x19, 0x1c, 0xbf, 0xd9, 0xbd,
- 0x6b, 0x3e, 0xd9, 0xcb, 0xda, 0xc6, 0x1c, 0xbe, 0x41, 0xcd, 0x9c, 0xb6,
- 0x78, 0xde, 0x70, 0x0e, 0x5f, 0xf9, 0x06, 0x37, 0x1e, 0x9f, 0x1b, 0x39,
- 0x77, 0x25, 0x0e, 0x5f, 0xda, 0x5f, 0x5d, 0x38, 0x73, 0x97, 0xe7, 0x18,
- 0xe2, 0x03, 0x97, 0x7c, 0xc3, 0x97, 0xff, 0x34, 0x71, 0xff, 0x3d, 0x02,
- 0x9f, 0x9c, 0xb7, 0x36, 0xa5, 0x57, 0xd4, 0x43, 0xd6, 0x72, 0x39, 0x1d,
- 0x05, 0xc1, 0x85, 0x3b, 0x3e, 0x00, 0xd7, 0x13, 0x26, 0x85, 0x0a, 0x0c,
- 0x5f, 0xee, 0x79, 0xa5, 0xbb, 0xac, 0xd1, 0x6e, 0xaf, 0xe1, 0x7e, 0x7a,
- 0x9f, 0xa7, 0x2f, 0x27, 0xdf, 0x9c, 0xbf, 0xfb, 0x4e, 0xbf, 0xc1, 0xbf,
- 0x47, 0xcd, 0x9c, 0xb8, 0x55, 0x39, 0x7c, 0xb7, 0x75, 0x9a, 0x29, 0x05,
- 0x61, 0xe2, 0xe8, 0x5e, 0xff, 0x4b, 0xc8, 0xde, 0xff, 0x43, 0x97, 0xfe,
- 0xce, 0xa7, 0x1e, 0xe6, 0x0a, 0xce, 0x5e, 0x79, 0x73, 0x0a, 0x64, 0x39,
- 0x08, 0xdf, 0x88, 0x76, 0x6b, 0x7f, 0x90, 0x20, 0xf6, 0xd8, 0x27, 0x2f,
- 0x38, 0xc8, 0xe5, 0xb9, 0xad, 0x50, 0x9e, 0x8c, 0x19, 0x19, 0xfb, 0xab,
- 0x36, 0x67, 0x7f, 0xf7, 0x37, 0x97, 0x3c, 0xd2, 0xdd, 0xd6, 0x68, 0x94,
- 0x95, 0x3a, 0xfe, 0xcc, 0xca, 0x8c, 0x5a, 0x74, 0x1f, 0xe5, 0x9b, 0x8c,
- 0x2c, 0x7d, 0x29, 0x53, 0x81, 0x6a, 0xfe, 0x41, 0xf6, 0x20, 0x4e, 0x5d,
- 0x2f, 0x1c, 0xbc, 0x30, 0xd9, 0xcb, 0xa3, 0x9e, 0x8d, 0x98, 0x8b, 0xd4,
- 0x91, 0x17, 0xe5, 0xeb, 0xdb, 0x03, 0x0e, 0x5b, 0x9f, 0xc7, 0x80, 0x84,
- 0x77, 0x85, 0xe4, 0x72, 0xfd, 0xa5, 0xbb, 0xac, 0xd1, 0x3b, 0x2f, 0xfe,
- 0xce, 0x8b, 0xc8, 0x1f, 0xb1, 0xe4, 0x72, 0xf3, 0xcb, 0x9e, 0x1f, 0xc0,
- 0x9a, 0x5d, 0x3b, 0x59, 0xcb, 0xff, 0xf2, 0x04, 0x0c, 0x8e, 0x07, 0x08,
- 0xc0, 0xe2, 0xce, 0x5f, 0xe9, 0x46, 0xa7, 0x8d, 0x4e, 0x72, 0xff, 0xdd,
- 0x17, 0x90, 0x3f, 0x63, 0xc8, 0xe5, 0x41, 0xfa, 0x61, 0xad, 0xb9, 0xe2,
- 0x79, 0x4c, 0x84, 0x9f, 0x4c, 0xdc, 0x6c, 0x61, 0x93, 0x7c, 0x9a, 0x8e,
- 0x27, 0x2f, 0xfe, 0x68, 0xe3, 0xfe, 0x7a, 0x05, 0x3f, 0x39, 0x6e, 0x7b,
- 0x3e, 0x85, 0x08, 0xef, 0xfe, 0x76, 0x77, 0x16, 0xfd, 0x85, 0x24, 0x72,
- 0xf2, 0x05, 0xce, 0x5f, 0xfc, 0x39, 0xd7, 0x9f, 0x36, 0x2f, 0xf1, 0xcb,
- 0x9a, 0x73, 0x0a, 0x28, 0xba, 0x89, 0xb1, 0xba, 0x92, 0xbc, 0x36, 0x47,
- 0xe9, 0xb8, 0x61, 0x34, 0x86, 0x6d, 0xff, 0xfc, 0x17, 0xf7, 0x3c, 0xdc,
- 0x0f, 0xdf, 0xef, 0x71, 0xf9, 0xcb, 0xf6, 0x96, 0xee, 0xb3, 0x44, 0x58,
- 0xbf, 0xf3, 0xcb, 0x9e, 0x69, 0x6e, 0xeb, 0x34, 0x4b, 0xab, 0xff, 0xfb,
- 0x03, 0xd8, 0x53, 0x9f, 0x85, 0xff, 0xde, 0xe3, 0xf2, 0x96, 0xe7, 0x88,
- 0xdf, 0x61, 0xa3, 0x44, 0xcb, 0xff, 0x98, 0xf2, 0xe7, 0x9a, 0x5b, 0xba,
- 0xcd, 0x13, 0x12, 0xff, 0xfb, 0x17, 0x1c, 0xfa, 0xe8, 0xd1, 0x3f, 0xc0,
- 0x9c, 0xae, 0x68, 0xa4, 0xea, 0x95, 0xfb, 0x4b, 0x77, 0x59, 0xa2, 0xa9,
- 0x5b, 0x0e, 0x56, 0x1e, 0x22, 0xa6, 0x97, 0xfe, 0x03, 0xea, 0x43, 0x8d,
- 0xbf, 0xe7, 0x2f, 0xfe, 0x7d, 0xe9, 0x1b, 0xf7, 0x53, 0x52, 0x39, 0x7f,
- 0xda, 0x7e, 0xfd, 0x2c, 0xf7, 0x30, 0xa2, 0x13, 0xa7, 0xf5, 0xcd, 0x1f,
- 0x4f, 0x0a, 0x6b, 0xff, 0xdc, 0xd8, 0xf2, 0xe7, 0x9a, 0x5b, 0xba, 0xcd,
- 0x13, 0xa2, 0xff, 0x23, 0xea, 0x24, 0xfc, 0x4e, 0x5f, 0xa6, 0x89, 0xa3,
- 0x67, 0x2f, 0xe6, 0xf1, 0x38, 0xe0, 0x9c, 0xa4, 0x3d, 0x7d, 0x94, 0xde,
- 0x4e, 0xc1, 0xce, 0x66, 0x86, 0xff, 0xe0, 0x6f, 0xd1, 0xf7, 0x30, 0x4c,
- 0x8c, 0x39, 0x4c, 0x3f, 0x6e, 0x96, 0xdf, 0xf9, 0xe5, 0xcf, 0x34, 0xb7,
- 0x75, 0x9a, 0x27, 0x75, 0xfb, 0xc0, 0x76, 0x21, 0x4b, 0xff, 0x0c, 0x7b,
- 0x37, 0x99, 0xf4, 0x8e, 0x50, 0x53, 0xf3, 0xc8, 0xc8, 0x58, 0x44, 0xe9,
- 0x9e, 0x27, 0xbf, 0xe0, 0xc4, 0xa3, 0x9b, 0x7b, 0xfc, 0xe5, 0xfd, 0x1c,
- 0xff, 0x1c, 0x09, 0xca, 0xe6, 0x8b, 0xbc, 0x4f, 0x13, 0xdb, 0xff, 0xdc,
- 0xd8, 0xf2, 0xe7, 0x9a, 0x5b, 0xba, 0xcd, 0x14, 0x2a, 0xff, 0xf9, 0xfd,
- 0x2c, 0x14, 0x0f, 0x3d, 0xcf, 0x1a, 0x39, 0x7f, 0xff, 0xfb, 0xa0, 0x63,
- 0x1e, 0x5c, 0xd7, 0xd0, 0x7a, 0x07, 0x27, 0x54, 0x11, 0x31, 0xcb, 0xf0,
- 0x3e, 0xf2, 0x2c, 0xe5, 0xfb, 0x3f, 0xc7, 0x13, 0x97, 0xdb, 0x46, 0xfc,
- 0x72, 0xf4, 0x7f, 0xce, 0x73, 0xf2, 0x12, 0x9f, 0x13, 0x52, 0x26, 0x64,
- 0x30, 0xef, 0xbf, 0xfd, 0xcd, 0x8f, 0x2e, 0x79, 0xa5, 0xbb, 0xac, 0xd1,
- 0x49, 0x2f, 0xff, 0xf6, 0x6f, 0x9a, 0x99, 0x37, 0x5d, 0x9e, 0xec, 0x78,
- 0x0c, 0x39, 0x50, 0xc9, 0xa2, 0x9e, 0x33, 0xe9, 0x43, 0x75, 0x71, 0xb1,
- 0xe8, 0xa5, 0x92, 0xc2, 0x3f, 0x30, 0x15, 0xaf, 0x47, 0x06, 0x02, 0x76,
- 0x8b, 0x57, 0xfb, 0x9e, 0x69, 0x6e, 0xeb, 0x34, 0x44, 0x8b, 0xff, 0xdc,
- 0xd8, 0xf2, 0xe7, 0x9a, 0x5b, 0xba, 0xcd, 0x12, 0xf2, 0xff, 0xe8, 0xe2,
- 0xf3, 0x26, 0xbe, 0x94, 0x4c, 0x72, 0xf3, 0x52, 0xcf, 0xce, 0x5f, 0x68,
- 0x1e, 0xd9, 0xcb, 0xf6, 0xbf, 0x62, 0x6c, 0xe5, 0xe8, 0x1f, 0x8e, 0x5f,
- 0xbc, 0xa3, 0x06, 0x0e, 0x59, 0x3a, 0x78, 0x82, 0x39, 0x7f, 0xfb, 0xbc,
- 0x60, 0x7f, 0x6b, 0xc0, 0xe6, 0xbe, 0x39, 0x74, 0x78, 0xe5, 0xff, 0x3c,
- 0xfa, 0x8f, 0xa4, 0x8c, 0x39, 0x7f, 0xf8, 0x01, 0x4d, 0x29, 0x37, 0x00,
- 0x1c, 0x66, 0x39, 0x52, 0x4c, 0x59, 0x09, 0xbf, 0x50, 0x11, 0x6d, 0x9d,
- 0x5f, 0xdf, 0xf6, 0x34, 0x8c, 0x39, 0x7f, 0xe9, 0xb7, 0x1c, 0x5f, 0xb1,
- 0xf4, 0xc7, 0x2a, 0x0f, 0xc5, 0xcb, 0xaf, 0x93, 0x81, 0x46, 0x1c, 0xbf,
- 0x64, 0xf9, 0xb6, 0x1c, 0xbf, 0x9e, 0x77, 0xdb, 0xfe, 0x72, 0xff, 0xe9,
- 0xb9, 0x28, 0x31, 0xc5, 0xf8, 0xc4, 0xc7, 0x28, 0xe5, 0xfa, 0x4f, 0xe7,
- 0xe2, 0x72, 0xfc, 0xfb, 0x8e, 0x38, 0x72, 0xa6, 0x3d, 0x1e, 0x25, 0x35,
- 0x08, 0xcd, 0xc4, 0xc7, 0x5c, 0xbb, 0x50, 0x72, 0x82, 0xb8, 0x1a, 0x84,
- 0x73, 0x47, 0x07, 0xa8, 0x5d, 0xf4, 0x80, 0x49, 0xbc, 0x51, 0xc6, 0x1f,
- 0x7c, 0x05, 0xb7, 0x60, 0x9c, 0xbf, 0xb9, 0x6f, 0xb8, 0x9e, 0x39, 0x41,
- 0x3c, 0x44, 0x15, 0xb8, 0x3f, 0x1c, 0xbf, 0x84, 0x1e, 0x9a, 0x15, 0x39,
- 0x7b, 0x87, 0x4d, 0x1c, 0xb2, 0x39, 0xe8, 0x00, 0xbe, 0xfc, 0x39, 0x3a,
- 0x9c, 0x4e, 0x5f, 0x64, 0xea, 0x71, 0x39, 0x7e, 0x0c, 0x7c, 0x17, 0xe4,
- 0x7a, 0x22, 0x57, 0x7f, 0xfc, 0x9a, 0xe5, 0xd8, 0x4f, 0x6c, 0x0b, 0x04,
- 0x1c, 0xbe, 0x49, 0xff, 0x6b, 0x39, 0x7c, 0xb7, 0x75, 0x9a, 0x29, 0x75,
- 0xf0, 0xfa, 0x34, 0x72, 0xff, 0xb3, 0x4d, 0x78, 0x1c, 0xd7, 0xc7, 0x29,
- 0x0f, 0x77, 0x89, 0x0d, 0x49, 0x36, 0x65, 0x50, 0x26, 0x51, 0xd1, 0x3f,
- 0x61, 0x17, 0x7f, 0x07, 0xe8, 0xd2, 0x7c, 0x72, 0xfb, 0xd3, 0xe3, 0x67,
- 0x29, 0x0f, 0x4c, 0x4b, 0xef, 0xc8, 0xae, 0xb3, 0x67, 0x2f, 0xfd, 0x03,
- 0x1d, 0xe4, 0x01, 0x02, 0xce, 0x5e, 0x03, 0xec, 0xe5, 0xf4, 0xc0, 0x79,
- 0x8e, 0x5f, 0xa3, 0xf7, 0xfb, 0x67, 0x2f, 0x0a, 0x7e, 0x72, 0xf6, 0x7b,
- 0x67, 0x2a, 0x0d, 0xc6, 0xc7, 0x2a, 0x49, 0x94, 0x04, 0xa2, 0x63, 0xfe,
- 0x8e, 0x7e, 0x49, 0xe6, 0x1b, 0xf3, 0x5b, 0x88, 0x78, 0x0e, 0x5d, 0x1f,
- 0x1c, 0xbf, 0xef, 0xf7, 0xa8, 0xfa, 0x48, 0xc3, 0x97, 0xbc, 0xfc, 0x4e,
- 0x5f, 0xa7, 0x04, 0xd0, 0xd6, 0x72, 0xf8, 0x13, 0x43, 0x59, 0xcb, 0x9e,
- 0x7e, 0x47, 0xa7, 0x39, 0x6d, 0x42, 0x37, 0x5c, 0xec, 0x0e, 0x37, 0xfc,
- 0x9b, 0x99, 0x07, 0xd1, 0xf9, 0xcb, 0xff, 0x87, 0xdc, 0x63, 0x5b, 0x71,
- 0x86, 0xb3, 0x95, 0x24, 0x57, 0x30, 0xbb, 0x67, 0x37, 0xfa, 0x1a, 0xf7,
- 0x0c, 0x7f, 0x1c, 0xb9, 0xc4, 0xe5, 0xff, 0x47, 0xfc, 0xbb, 0x0c, 0x71,
- 0x39, 0x5f, 0x1e, 0x7f, 0x11, 0x5a, 0x92, 0x2a, 0x75, 0x08, 0x4b, 0xfa,
- 0x1b, 0x4e, 0x81, 0xac, 0xe5, 0xfd, 0xf4, 0xb6, 0xe3, 0xf1, 0xca, 0x85,
- 0x66, 0x12, 0x2d, 0xc8, 0xe8, 0x92, 0x1b, 0x3a, 0x28, 0x50, 0xc6, 0xff,
- 0xc3, 0x37, 0x2d, 0x47, 0xd2, 0x46, 0x1c, 0xba, 0x18, 0x72, 0xa0, 0xf6,
- 0x34, 0x85, 0x7f, 0x40, 0xcd, 0xe4, 0x54, 0xe5, 0xff, 0x4b, 0x35, 0x36,
- 0x0c, 0x30, 0xe5, 0xfb, 0xf8, 0x5e, 0x30, 0xe5, 0xfe, 0xc9, 0xf7, 0x13,
- 0x03, 0x47, 0x29, 0x11, 0x2b, 0xa3, 0x81, 0x28, 0xba, 0x58, 0x72, 0xfd,
- 0xb5, 0x74, 0xed, 0x9c, 0xbc, 0x30, 0xc3, 0x94, 0x13, 0xc5, 0xd1, 0x55,
- 0xe8, 0xff, 0x67, 0x2a, 0x11, 0x90, 0x12, 0xec, 0x5b, 0x6c, 0x8a, 0xf9,
- 0xfa, 0xf3, 0x9c, 0xbf, 0x74, 0x0a, 0xe0, 0x9c, 0xbf, 0xcd, 0x8b, 0xfa,
- 0x4e, 0x13, 0x97, 0xef, 0x29, 0x3c, 0x74, 0xe5, 0xff, 0x47, 0x76, 0xfe,
- 0x8d, 0x70, 0x1c, 0xbf, 0xf3, 0x1c, 0x2a, 0x4d, 0x28, 0x1f, 0x8e, 0x50,
- 0x4f, 0xf1, 0x0e, 0xef, 0xb5, 0xfa, 0x9c, 0x4e, 0x5e, 0x46, 0xfc, 0x72,
- 0xba, 0x78, 0x9b, 0x27, 0xa9, 0xd3, 0xaa, 0x09, 0x17, 0xc5, 0x13, 0x19,
- 0xf6, 0x14, 0xde, 0x65, 0xbf, 0xc3, 0xec, 0xda, 0x3f, 0x4e, 0x5f, 0xf7,
- 0xe9, 0xdc, 0xd3, 0xcd, 0xb3, 0x97, 0xff, 0xe8, 0x90, 0xc4, 0xea, 0x4d,
- 0xbe, 0xe7, 0x06, 0xbf, 0x39, 0x7f, 0x72, 0x66, 0x79, 0xfc, 0x72, 0xfe,
- 0xea, 0x05, 0x34, 0xb3, 0x96, 0x59, 0xcb, 0xbe, 0xde, 0x1f, 0x6a, 0xcb,
- 0xdc, 0xb6, 0xf4, 0x20, 0x4e, 0x54, 0x27, 0x13, 0xf1, 0x8b, 0x0e, 0x9e,
- 0x19, 0x3b, 0x3a, 0xbf, 0xd8, 0xdc, 0x93, 0x60, 0x61, 0xcb, 0xb8, 0xec,
- 0xe5, 0xfc, 0x0d, 0xc4, 0xc0, 0xd1, 0xcb, 0xf6, 0x4f, 0x9d, 0xd9, 0xca,
- 0x83, 0xf0, 0xe8, 0xc8, 0x97, 0xde, 0xcd, 0x6c, 0xe5, 0x2c, 0xf2, 0x78,
- 0x96, 0xdf, 0xf7, 0xf1, 0xfa, 0x9c, 0x60, 0x78, 0x0e, 0x54, 0x26, 0xa3,
- 0x90, 0xed, 0x42, 0x4b, 0xff, 0xff, 0xbb, 0x1a, 0xf9, 0x69, 0xf7, 0x25,
- 0x5f, 0x96, 0xfa, 0xeb, 0x81, 0x09, 0xcb, 0xe4, 0x55, 0xa6, 0x1c, 0xbf,
- 0x94, 0xf4, 0x4e, 0x3f, 0x1c, 0xbc, 0x28, 0xc3, 0x95, 0xa3, 0xef, 0xfc,
- 0x93, 0xc6, 0x17, 0xf8, 0x61, 0xc7, 0xd8, 0x27, 0x2f, 0xf4, 0x7d, 0xb6,
- 0xb8, 0xd2, 0xa7, 0x2f, 0xf7, 0x5e, 0x64, 0xd4, 0x4e, 0x72, 0xfe, 0xce,
- 0x06, 0x46, 0x78, 0xe5, 0xd8, 0xc3, 0x94, 0x14, 0xfd, 0xf2, 0x1c, 0xec,
- 0x30, 0xe9, 0x7b, 0x9c, 0x00, 0xd3, 0x89, 0x7d, 0xfb, 0x81, 0x19, 0x1b,
- 0x39, 0x7e, 0x7e, 0x39, 0xad, 0x9c, 0xa0, 0x9e, 0x9b, 0x0a, 0xaf, 0xdd,
- 0x71, 0x46, 0x1c, 0xbe, 0x56, 0x6d, 0xc1, 0xcb, 0xfb, 0xff, 0xbf, 0xcd,
- 0x61, 0xcb, 0xf9, 0x70, 0x9e, 0x49, 0x1c, 0xbf, 0x9f, 0xf6, 0x46, 0x78,
- 0xe5, 0x42, 0x22, 0x70, 0xc1, 0x0b, 0x2f, 0xf3, 0xff, 0xb8, 0xec, 0x6c,
- 0xe5, 0xfb, 0xef, 0x6f, 0x27, 0x39, 0x76, 0x4e, 0x72, 0x9c, 0xf0, 0x44,
- 0xaa, 0xa1, 0x3b, 0x6c, 0x22, 0x42, 0x6e, 0xc2, 0xb4, 0x4b, 0x76, 0xe9,
- 0x77, 0xeb, 0x39, 0x6d, 0x9c, 0xb9, 0x15, 0xd9, 0xa9, 0x00, 0xc5, 0xef,
- 0xdd, 0x67, 0x2f, 0x9b, 0x9b, 0x70, 0x72, 0xfe, 0xd8, 0xbc, 0xf1, 0xe3,
- 0x97, 0xe9, 0xdf, 0x79, 0x23, 0x97, 0xff, 0xc1, 0xce, 0x2f, 0xa9, 0x94,
- 0x93, 0xf9, 0xd8, 0x72, 0xa0, 0xfe, 0xd0, 0xa2, 0xfe, 0x7f, 0xbf, 0x62,
- 0x6c, 0xe5, 0x42, 0x67, 0x1f, 0x0e, 0xcc, 0x49, 0xa8, 0x54, 0x74, 0x82,
- 0xff, 0x79, 0x1b, 0x79, 0xa1, 0x87, 0x2d, 0xcf, 0x84, 0x6f, 0x03, 0x1a,
- 0xb4, 0x88, 0x9c, 0x30, 0x9e, 0x1b, 0x32, 0x21, 0x0b, 0x46, 0x47, 0xbb,
- 0xf4, 0x29, 0x52, 0x34, 0x89, 0xa5, 0xc5, 0x6a, 0x17, 0x4c, 0x21, 0xec,
- 0x71, 0x6f, 0x1f, 0x37, 0xf1, 0xf4, 0x8c, 0x74, 0x1b, 0x94, 0x55, 0xe9,
- 0x4e, 0x6d, 0x21, 0x04, 0xa4, 0x6c, 0xbc, 0x0a, 0x37, 0xfb, 0x9e, 0x69,
- 0x6e, 0xeb, 0x34, 0x53, 0x8b, 0xfc, 0xc8, 0x66, 0x70, 0x47, 0x8e, 0x5f,
- 0x66, 0xd4, 0x91, 0xcb, 0xff, 0x26, 0x9f, 0x7d, 0xcc, 0x15, 0x9c, 0xbf,
- 0x33, 0x5a, 0xcd, 0x9c, 0xbf, 0xff, 0x74, 0x1e, 0xd4, 0x7b, 0x78, 0xbd,
- 0xc6, 0x96, 0x72, 0xff, 0xb6, 0x8a, 0xe4, 0xa3, 0xfd, 0x9c, 0xbf, 0xff,
- 0xbd, 0x93, 0x0a, 0x6f, 0xd0, 0xa2, 0x6a, 0x68, 0xe9, 0xcb, 0xfc, 0x8c,
- 0x0c, 0x6c, 0x02, 0x72, 0xfe, 0x7f, 0xb7, 0xcb, 0x6a, 0x1c, 0xbf, 0x7b,
- 0xe9, 0x43, 0x67, 0x2f, 0xe7, 0x53, 0x38, 0xc6, 0xce, 0x56, 0x1e, 0xc8,
- 0x0a, 0xaf, 0xfc, 0x9f, 0x6c, 0x70, 0x3d, 0x76, 0xce, 0x5f, 0xff, 0x64,
- 0xf9, 0xf7, 0xb6, 0x83, 0x1f, 0xbb, 0x0e, 0x52, 0xa8, 0x8f, 0xd9, 0xfd,
- 0xff, 0xb3, 0xb1, 0xac, 0xe6, 0xdb, 0x6d, 0x94, 0xb9, 0x1b, 0x39, 0x74,
- 0xfc, 0xe1, 0x5c, 0x9c, 0x8d, 0x42, 0x47, 0x87, 0x8b, 0x28, 0xf9, 0x59,
- 0x0e, 0xba, 0xb9, 0xf9, 0x90, 0xc2, 0x2f, 0xd0, 0xb0, 0x68, 0x49, 0xc0,
- 0x87, 0x7e, 0xd2, 0xdd, 0xd6, 0x68, 0xaf, 0x17, 0xff, 0xf6, 0x07, 0xb0,
- 0xa7, 0x3f, 0x0b, 0xff, 0xbd, 0xc7, 0xe5, 0x2d, 0xcf, 0x11, 0x26, 0xd0,
- 0xd2, 0xff, 0xee, 0x6f, 0x2e, 0x79, 0xa5, 0xbb, 0xac, 0xd1, 0x23, 0xaf,
- 0x2f, 0x18, 0x72, 0xf2, 0x7f, 0x07, 0x2f, 0x2f, 0x18, 0x53, 0x99, 0x79,
- 0x7e, 0xd2, 0xdd, 0xd6, 0x68, 0x92, 0x17, 0xff, 0xf4, 0x26, 0x93, 0x82,
- 0x06, 0x78, 0xf2, 0x75, 0xe7, 0x39, 0x7f, 0xf9, 0xfd, 0x36, 0xf0, 0x21,
- 0x03, 0xea, 0x47, 0x2f, 0xff, 0x0e, 0x7e, 0xd3, 0x35, 0x13, 0xbe, 0x96,
- 0x72, 0xe9, 0x73, 0x84, 0xd5, 0x30, 0xb7, 0xa6, 0x9f, 0xae, 0x79, 0x2e,
- 0xfd, 0x9d, 0xe7, 0x8c, 0x39, 0x6e, 0x70, 0xa8, 0x35, 0xe3, 0x8c, 0xf2,
- 0xc5, 0xff, 0xdc, 0xde, 0x5c, 0xf3, 0x4b, 0x77, 0x59, 0xa2, 0x4a, 0x5f,
- 0xb4, 0xb7, 0x75, 0x9a, 0x2f, 0x15, 0xff, 0x4b, 0x9e, 0x69, 0x6e, 0xeb,
- 0x34, 0x49, 0xab, 0x73, 0xc3, 0xfb, 0x73, 0x4b, 0xfe, 0xd2, 0xe2, 0x7c,
- 0xc1, 0xf1, 0xcb, 0xfa, 0x36, 0x8c, 0x89, 0x8e, 0x5b, 0xa7, 0x29, 0x0f,
- 0xd9, 0x87, 0x0d, 0x96, 0xdf, 0xf6, 0x7e, 0x1e, 0xc0, 0xc3, 0x67, 0x2f,
- 0xbf, 0xde, 0x09, 0xca, 0x83, 0xdb, 0x43, 0x9b, 0xff, 0x90, 0x0b, 0xde,
- 0xdf, 0x5e, 0x85, 0x4e, 0x5f, 0x48, 0x11, 0xf1, 0xcb, 0xff, 0xe0, 0x3f,
- 0xd9, 0x8a, 0xaa, 0xf2, 0xcf, 0xbc, 0x72, 0xa4, 0x8d, 0xa0, 0x90, 0x4c,
- 0x8b, 0xb2, 0x3b, 0xff, 0x24, 0x33, 0xb8, 0x10, 0xa7, 0xc7, 0x2f, 0xb8,
- 0x12, 0x15, 0x39, 0x7a, 0x5f, 0x2a, 0x72, 0xf0, 0x03, 0xf1, 0xcb, 0xff,
- 0x9f, 0xf5, 0xf5, 0x34, 0x29, 0xed, 0x9c, 0xb8, 0x67, 0x39, 0x50, 0x8b,
- 0xd0, 0x92, 0xa0, 0xfb, 0x8f, 0x28, 0x89, 0x6f, 0x1c, 0xbb, 0x58, 0x72,
- 0xb4, 0x69, 0xff, 0x11, 0xbf, 0xf6, 0x80, 0xce, 0xa4, 0x31, 0xc4, 0xe5,
- 0xff, 0x6e, 0x18, 0x39, 0x28, 0x13, 0x95, 0xa3, 0xf3, 0xf1, 0xed, 0xe6,
- 0x9c, 0x33, 0x67, 0x2b, 0x0f, 0x1f, 0x80, 0x8a, 0xfd, 0xe4, 0xec, 0x71,
- 0x39, 0x70, 0xce, 0x72, 0xf7, 0xa3, 0x47, 0x2a, 0x0f, 0x72, 0x62, 0x90,
- 0x0b, 0xdc, 0xeb, 0x39, 0x7f, 0x2c, 0x20, 0x9d, 0x46, 0x1c, 0xbe, 0x0e,
- 0x76, 0x0e, 0x54, 0x1f, 0x46, 0x0b, 0x39, 0x8d, 0xfa, 0x6d, 0xed, 0x18,
- 0x72, 0xff, 0xfa, 0x76, 0xde, 0x5b, 0xde, 0x69, 0xb8, 0xd2, 0xa7, 0x2c,
- 0x27, 0x2e, 0x51, 0x43, 0x95, 0x88, 0xa6, 0x72, 0x9f, 0xd5, 0x14, 0x10,
- 0xb9, 0xa7, 0x38, 0x5e, 0x0e, 0xc8, 0xd9, 0x34, 0x7d, 0xd8, 0x7d, 0xbb,
- 0x78, 0xc3, 0x73, 0x70, 0x80, 0xf4, 0x25, 0xd4, 0x86, 0x95, 0x43, 0xae,
- 0x62, 0x9d, 0x06, 0x55, 0xe3, 0x30, 0x63, 0x91, 0x49, 0x7a, 0x93, 0x46,
- 0xc6, 0xc2, 0xce, 0xca, 0x61, 0xf1, 0xf0, 0x21, 0x9e, 0xa4, 0xf5, 0x65,
- 0x44, 0xef, 0x31, 0x24, 0xf2, 0xd0, 0xe5, 0x3d, 0xde, 0x19, 0xf0, 0x6c,
- 0xc6, 0x91, 0x7a, 0xb4, 0x81, 0x95, 0xdf, 0xb6, 0x87, 0xd5, 0xed, 0xea,
- 0x53, 0x4c, 0x5a, 0xe5, 0x1f, 0x4d, 0x78, 0xf7, 0x9a, 0xb6, 0x57, 0x6c,
- 0xd4, 0x32, 0x55, 0xda, 0x7d, 0x7b, 0xde, 0x52, 0xff, 0xf4, 0xc2, 0x7e,
- 0x1e, 0x5e, 0xe0, 0xd7, 0xd6, 0xbb, 0xb4, 0x48, 0xde, 0xbf, 0x8e, 0x10,
- 0x5e, 0x46, 0xe7, 0x1a, 0x77, 0xb3, 0x74, 0x84, 0xe6, 0x93, 0xa3, 0x2a,
- 0x52, 0x7c, 0xf8, 0x2d, 0x78, 0xf5, 0x00,
+ 0xfb, 0x5d, 0xbb, 0xf6, 0xa8, 0x89, 0x57, 0xbc, 0xda, 0x59, 0x7f, 0xcf,
+ 0x2c, 0xd6, 0x7f, 0xa9, 0xd6, 0x5f, 0xf3, 0x0f, 0x0a, 0x4d, 0xe0, 0xac,
+ 0xb0, 0xbc, 0x46, 0x1c, 0xc6, 0xc7, 0x1c, 0xf9, 0xd5, 0xdb, 0x59, 0xab,
+ 0x2e, 0x00, 0x56, 0x5e, 0x91, 0x6e, 0x2c, 0xbb, 0xaf, 0xac, 0xbf, 0xfe,
+ 0x8f, 0x44, 0x89, 0xcd, 0xea, 0x51, 0x9f, 0x59, 0x7f, 0xd8, 0x7e, 0xbe,
+ 0xde, 0xcd, 0xd5, 0x96, 0xe2, 0xca, 0x19, 0xe6, 0xb9, 0xe5, 0xf0, 0x77,
+ 0x47, 0x0b, 0x2a, 0x48, 0xfa, 0x18, 0xc3, 0x42, 0x73, 0xc4, 0x37, 0xfb,
+ 0x0c, 0x28, 0xff, 0x99, 0x65, 0xc0, 0x3a, 0xcb, 0x9d, 0x96, 0x54, 0x1a,
+ 0xcf, 0x0b, 0xdf, 0xfe, 0x08, 0xaf, 0x9d, 0xf9, 0xbd, 0x19, 0xa9, 0x2c,
+ 0xbf, 0xec, 0xf0, 0x93, 0x71, 0xba, 0x31, 0x65, 0x42, 0x23, 0x09, 0x3e,
+ 0xc4, 0xb2, 0xff, 0x48, 0xb3, 0x79, 0x67, 0x16, 0x56, 0x1e, 0x1b, 0x88,
+ 0x5f, 0xfc, 0x13, 0xf8, 0xb3, 0xaf, 0x93, 0xf9, 0x65, 0xff, 0xfa, 0x44,
+ 0xff, 0x73, 0xf2, 0x07, 0x1e, 0x89, 0x2c, 0xae, 0x22, 0x5c, 0x44, 0x4b,
+ 0xb3, 0x8b, 0x2f, 0x3b, 0xf6, 0xa8, 0x8b, 0x55, 0x23, 0xe3, 0xc2, 0x4e,
+ 0xc5, 0xaf, 0xff, 0xef, 0x3e, 0x13, 0xff, 0x9c, 0xef, 0xcd, 0xbe, 0x38,
+ 0xb2, 0xfb, 0xe4, 0xe6, 0xac, 0xbf, 0x46, 0xb3, 0xaf, 0xac, 0xb3, 0x69,
+ 0x14, 0xde, 0x5c, 0x01, 0x15, 0xf9, 0x8d, 0xfe, 0xa1, 0x65, 0xda, 0xe2,
+ 0xcb, 0xfe, 0x6f, 0xb9, 0xde, 0x4f, 0xa5, 0x97, 0xb8, 0x27, 0xd6, 0x50,
+ 0xd5, 0x5c, 0x6a, 0x31, 0xaf, 0x43, 0x54, 0x8d, 0x78, 0x51, 0xbc, 0x5c,
+ 0x43, 0x7b, 0xbf, 0xf5, 0x97, 0xff, 0xc1, 0xff, 0x07, 0xe8, 0xe4, 0x78,
+ 0x31, 0xc5, 0x97, 0xff, 0xcf, 0xec, 0x2d, 0x6b, 0x3a, 0x97, 0xd8, 0xeb,
+ 0x2a, 0x48, 0xb6, 0x34, 0x5c, 0x2a, 0x17, 0x77, 0x0b, 0x2f, 0x8e, 0xc6,
+ 0x71, 0x65, 0xff, 0xe3, 0x5b, 0x5f, 0xeb, 0xb6, 0xc3, 0x25, 0x3a, 0xca,
+ 0x39, 0xf9, 0x7c, 0x8e, 0xff, 0x9c, 0x42, 0xc9, 0xb5, 0x06, 0x2c, 0xa6,
+ 0x3d, 0xc0, 0x91, 0x5c, 0x46, 0x2c, 0xac, 0x4c, 0x77, 0xd0, 0xe5, 0x30,
+ 0x86, 0xfe, 0x3b, 0x75, 0xc8, 0xe9, 0x65, 0xff, 0xd1, 0x85, 0xf0, 0xb8,
+ 0xf9, 0x06, 0xac, 0xbf, 0xa0, 0x7d, 0x72, 0x26, 0x59, 0x50, 0x8a, 0x19,
+ 0x17, 0xf1, 0x0e, 0xe7, 0xde, 0xb2, 0xfa, 0x3b, 0x38, 0x56, 0x53, 0x1b,
+ 0xb2, 0x18, 0xbd, 0xa6, 0xe9, 0x65, 0x0c, 0xde, 0x7c, 0x7e, 0xfd, 0xd0,
+ 0xf4, 0xf2, 0x59, 0x7f, 0x82, 0x02, 0xc9, 0xc4, 0x92, 0xcb, 0xfd, 0x1f,
+ 0xe1, 0xc3, 0x13, 0xac, 0xa8, 0x44, 0x97, 0x8a, 0x48, 0xd6, 0xff, 0xc5,
+ 0xff, 0x64, 0x8c, 0x8e, 0xb8, 0xb2, 0xff, 0xd1, 0xd7, 0x3e, 0xd3, 0xce,
+ 0xdf, 0x59, 0x70, 0xe1, 0x65, 0x42, 0x25, 0xf4, 0x80, 0x48, 0x37, 0x98,
+ 0x0e, 0xb2, 0xc3, 0x59, 0x7f, 0xb9, 0x1a, 0x9a, 0x66, 0xf2, 0xca, 0x19,
+ 0xe3, 0x70, 0x46, 0xfe, 0xd4, 0x1f, 0x08, 0xeb, 0x2f, 0xf1, 0x37, 0x18,
+ 0xba, 0x92, 0xca, 0xd1, 0xef, 0x18, 0x59, 0x73, 0x4e, 0xb2, 0xf1, 0xc0,
+ 0xcb, 0x2f, 0xed, 0x3f, 0x1f, 0x3c, 0xb2, 0xdf, 0x73, 0xc8, 0x08, 0xe5,
+ 0xd1, 0xb8, 0xb2, 0x86, 0x89, 0xf6, 0x5f, 0x39, 0x3d, 0x62, 0x6e, 0x2d,
+ 0x08, 0x07, 0x86, 0x15, 0xff, 0x1f, 0x35, 0xa6, 0xde, 0xfd, 0xac, 0xbf,
+ 0xfb, 0xbd, 0x41, 0xb0, 0x5f, 0xda, 0x7b, 0x4f, 0x6a, 0x59, 0x78, 0x52,
+ 0x43, 0x59, 0x7f, 0x6b, 0x3c, 0xdd, 0x12, 0xcb, 0xe3, 0x41, 0x1f, 0x59,
+ 0x6f, 0x41, 0xe8, 0x31, 0x6d, 0xfd, 0xe2, 0x0b, 0x9b, 0xda, 0xcb, 0xfa,
+ 0x35, 0x83, 0x79, 0x2c, 0xa1, 0xa2, 0x05, 0x89, 0x84, 0x2f, 0xb8, 0xb8,
+ 0xb2, 0xa1, 0x38, 0xe1, 0xab, 0xe4, 0x3c, 0x48, 0xc2, 0xff, 0xbb, 0x13,
+ 0xed, 0x23, 0x33, 0xcb, 0x2f, 0xff, 0x7f, 0x99, 0x31, 0x41, 0xf5, 0xa8,
+ 0xe9, 0x65, 0xff, 0x04, 0x56, 0x3c, 0xff, 0x33, 0xcb, 0x2d, 0xf8, 0x44,
+ 0x43, 0xa5, 0xdf, 0xf7, 0x78, 0x59, 0x3c, 0xe1, 0x25, 0x96, 0xdc, 0x59,
+ 0x7d, 0xae, 0x61, 0x8b, 0x2f, 0xc4, 0x51, 0xd0, 0x90, 0x6d, 0xf0, 0x52,
+ 0xfe, 0x6e, 0x6b, 0x51, 0x25, 0x97, 0xff, 0xcd, 0xf0, 0xe9, 0xf9, 0xf6,
+ 0xdb, 0xc0, 0x42, 0xca, 0xec, 0xff, 0x9c, 0xb6, 0xff, 0xfd, 0x80, 0xe3,
+ 0x74, 0x66, 0x77, 0x04, 0x17, 0x92, 0xcb, 0xfe, 0x2f, 0xf3, 0xf9, 0x86,
+ 0x71, 0x65, 0xcf, 0xe5, 0x95, 0x87, 0x9f, 0xd1, 0xcd, 0xff, 0xfa, 0x69,
+ 0x40, 0x35, 0x9d, 0xc4, 0x9b, 0x4d, 0xc5, 0x95, 0x07, 0xf1, 0x84, 0x57,
+ 0xec, 0xf6, 0xd6, 0x2a, 0x0a, 0xb5, 0x95, 0x0a, 0xeb, 0x72, 0x18, 0x9d,
+ 0x93, 0xb3, 0x8f, 0xa1, 0x74, 0x44, 0x5f, 0x8c, 0x74, 0xc2, 0x0b, 0xff,
+ 0x67, 0xdc, 0x80, 0xe7, 0x3b, 0x2c, 0xbf, 0xff, 0xf0, 0x7d, 0x83, 0xff,
+ 0xb0, 0xf9, 0xef, 0x3b, 0x7e, 0x3f, 0xc5, 0x97, 0xcd, 0xcc, 0x25, 0x95,
+ 0x24, 0x63, 0xb1, 0xe7, 0x1a, 0xef, 0x1b, 0x9b, 0xab, 0x2e, 0xdd, 0xdd,
+ 0x59, 0x76, 0x74, 0x92, 0xd0, 0x92, 0xc0, 0xd1, 0xa7, 0x00, 0xbd, 0xfe,
+ 0xfe, 0x68, 0x07, 0x6e, 0x24, 0x16, 0x69, 0xef, 0xe9, 0x79, 0xb7, 0xe4,
+ 0xcb, 0x2a, 0x0f, 0xd5, 0xd1, 0x6f, 0xef, 0x37, 0x70, 0x76, 0x59, 0x7f,
+ 0xa0, 0x13, 0xbc, 0xa3, 0x71, 0x65, 0x41, 0xf1, 0x91, 0x6d, 0xff, 0xf8,
+ 0xb0, 0x0e, 0x40, 0x10, 0xff, 0x0b, 0xcf, 0x0b, 0x28, 0x8f, 0xd7, 0xe4,
+ 0x16, 0x17, 0xb5, 0xb6, 0xd3, 0xdb, 0x50, 0xe8, 0xab, 0x17, 0x88, 0xc6,
+ 0x67, 0x41, 0x92, 0xf0, 0xe1, 0x59, 0x92, 0xc7, 0x0d, 0x8c, 0xa7, 0xb8,
+ 0xd3, 0xba, 0x86, 0xbb, 0x42, 0x9a, 0x68, 0x59, 0xea, 0x18, 0xa7, 0x2e,
+ 0xf4, 0x7a, 0x4e, 0x70, 0x51, 0xe4, 0xf2, 0x5f, 0x6f, 0xe3, 0x48, 0x09,
+ 0x79, 0x84, 0x1b, 0x70, 0xe0, 0x12, 0x1f, 0x17, 0xff, 0xff, 0x39, 0xc5,
+ 0xb6, 0xb4, 0x1d, 0x6a, 0x0b, 0x0d, 0x6f, 0x7b, 0x04, 0x59, 0x7d, 0xa0,
+ 0xff, 0x16, 0x5f, 0xfc, 0x69, 0x9b, 0x93, 0x8c, 0x51, 0xb3, 0x67, 0xb6,
+ 0xd6, 0x5f, 0xa2, 0x77, 0xd7, 0x6b, 0x2e, 0x6d, 0xeb, 0x2f, 0x47, 0xf8,
+ 0xb2, 0xf7, 0x02, 0x7d, 0x1e, 0xe8, 0x0a, 0x48, 0x62, 0xb6, 0x9a, 0x3d,
+ 0x5a, 0x16, 0xb7, 0xfb, 0x01, 0xcc, 0xed, 0xc6, 0xb2, 0xfc, 0x4e, 0x67,
+ 0x38, 0xb2, 0xb0, 0xf6, 0xf4, 0x67, 0x7d, 0xdb, 0xbf, 0x6a, 0x8a, 0x89,
+ 0x78, 0xd8, 0xe2, 0xcb, 0xfb, 0xd1, 0xf8, 0xe8, 0xc5, 0x97, 0xc5, 0x26,
+ 0x3a, 0xcb, 0xf4, 0xb0, 0x98, 0x6b, 0x2b, 0x11, 0x26, 0xc3, 0xae, 0x5f,
+ 0xf2, 0x1a, 0xd2, 0x3f, 0x4f, 0x0c, 0x3b, 0xef, 0x66, 0xb1, 0x65, 0xe6,
+ 0x9b, 0x75, 0x65, 0x41, 0xe0, 0xf8, 0x86, 0xfd, 0xdb, 0xfa, 0x3c, 0xb2,
+ 0xff, 0xfe, 0x09, 0x39, 0xbb, 0x3e, 0x6c, 0x14, 0xb3, 0xcc, 0x75, 0x97,
+ 0x04, 0x45, 0x97, 0xc3, 0x1c, 0x1d, 0x65, 0xff, 0xf4, 0xa7, 0xda, 0x71,
+ 0xb4, 0x4f, 0xde, 0xb6, 0x6c, 0xf6, 0xda, 0xca, 0x84, 0x50, 0xb0, 0xc0,
+ 0x08, 0xaf, 0xda, 0x6e, 0xdb, 0x7a, 0xcb, 0xe1, 0xc6, 0x12, 0xcb, 0xf3,
+ 0x9b, 0x9e, 0x75, 0x95, 0x87, 0x8e, 0x12, 0x0b, 0xff, 0xf8, 0x24, 0xe6,
+ 0xec, 0xf9, 0xb0, 0x52, 0xcf, 0x31, 0xd6, 0x5f, 0x6b, 0x59, 0xb6, 0xb2,
+ 0x8e, 0x88, 0x27, 0x5d, 0xbf, 0xff, 0x3c, 0x8a, 0x39, 0x9d, 0x76, 0x4f,
+ 0x9d, 0x76, 0xb2, 0xfd, 0x06, 0x67, 0x9d, 0x65, 0xe1, 0xb6, 0xf5, 0x96,
+ 0x17, 0x0b, 0xcd, 0x92, 0x8c, 0x5c, 0x70, 0x88, 0xc8, 0xc7, 0xbb, 0x69,
+ 0x62, 0x13, 0x94, 0x7a, 0x1f, 0xce, 0x5c, 0x4e, 0x3c, 0x85, 0x1e, 0xf2,
+ 0x21, 0x15, 0xb7, 0x49, 0xef, 0xfb, 0x0e, 0x2f, 0x6f, 0x09, 0xbe, 0xb2,
+ 0xff, 0xbc, 0xda, 0xf3, 0xf3, 0x04, 0x59, 0x70, 0xc9, 0x65, 0xfc, 0xcf,
+ 0x2f, 0xb4, 0xeb, 0x2f, 0x3f, 0xd9, 0x65, 0xd0, 0x2f, 0x11, 0x2f, 0xd1,
+ 0xcf, 0x85, 0xb8, 0x5b, 0x43, 0x4c, 0x77, 0x90, 0xd3, 0xbd, 0x86, 0x62,
+ 0xcb, 0xc1, 0x89, 0xd6, 0x5f, 0xcf, 0x2e, 0xb9, 0x13, 0xac, 0xbf, 0xe7,
+ 0xe8, 0xb3, 0x7e, 0x9b, 0x8b, 0x2f, 0xcd, 0x12, 0x79, 0x2c, 0xa1, 0xa2,
+ 0x3c, 0xe5, 0xfe, 0x3a, 0xbf, 0xb2, 0x71, 0xc6, 0x0d, 0x65, 0xf0, 0xfc,
+ 0xd3, 0x2c, 0xac, 0x3d, 0x07, 0x2d, 0xbf, 0x13, 0xee, 0xe4, 0xeb, 0x2f,
+ 0x18, 0xfe, 0x59, 0x74, 0x0d, 0x65, 0x41, 0xb3, 0xf0, 0xed, 0xff, 0x39,
+ 0x7f, 0x9a, 0xc8, 0x3a, 0xcb, 0xf3, 0x11, 0x07, 0x71, 0x65, 0xff, 0x73,
+ 0x07, 0x9a, 0x94, 0x69, 0x65, 0x41, 0xf0, 0xe8, 0xa6, 0xd3, 0xac, 0xa8,
+ 0x36, 0x78, 0x43, 0x7d, 0xdc, 0x68, 0xd5, 0x97, 0xe9, 0x3f, 0xe4, 0xeb,
+ 0x2f, 0xa0, 0x00, 0x85, 0x95, 0x07, 0x90, 0x44, 0xf7, 0xfc, 0x43, 0xcd,
+ 0x0d, 0xdc, 0x6b, 0x2c, 0x15, 0x95, 0x07, 0x90, 0xe6, 0xf6, 0x25, 0x97,
+ 0xe9, 0xf4, 0xef, 0xf5, 0x94, 0xc6, 0xe1, 0xc4, 0x2f, 0xbc, 0xde, 0x16,
+ 0x29, 0x5c, 0x1a, 0x18, 0xe6, 0x42, 0xb0, 0xd8, 0x40, 0x76, 0x41, 0x32,
+ 0xe9, 0xc8, 0x3d, 0x0c, 0xbe, 0x0f, 0xfd, 0xb0, 0xc6, 0x8d, 0xb5, 0x8b,
+ 0xdc, 0xc2, 0x59, 0x7e, 0xd7, 0x6e, 0xfd, 0xaa, 0x2b, 0xd5, 0xf9, 0xb7,
+ 0x7b, 0x0c, 0xeb, 0x2d, 0x25, 0x96, 0x3a, 0xca, 0x83, 0x44, 0xe2, 0x37,
+ 0x40, 0x16, 0x5e, 0xf4, 0x74, 0xb2, 0xfe, 0x9c, 0x4d, 0xb7, 0x20, 0x2c,
+ 0xbf, 0xf3, 0x90, 0x33, 0xf0, 0x4c, 0x05, 0x95, 0x07, 0xdb, 0xb6, 0x65,
+ 0x61, 0x72, 0x4e, 0x0f, 0x06, 0xf4, 0x6c, 0xe9, 0xe0, 0x1f, 0x08, 0xb0,
+ 0x90, 0x8a, 0xbf, 0xf8, 0x5b, 0xc8, 0x5e, 0x6b, 0xb7, 0x7e, 0xd5, 0x12,
+ 0x32, 0xff, 0xf0, 0xb3, 0xbc, 0x85, 0xe6, 0xbb, 0x77, 0xed, 0x51, 0x3c,
+ 0x2f, 0xff, 0x0b, 0x3b, 0xc8, 0x5e, 0x6b, 0xb7, 0x7e, 0xd5, 0x13, 0xfa,
+ 0xff, 0xf0, 0xb3, 0xbc, 0x85, 0xe6, 0xbb, 0x77, 0xed, 0x51, 0x43, 0x2f,
+ 0xfc, 0xf2, 0x17, 0x9a, 0xed, 0xdf, 0xb5, 0x45, 0x10, 0xbf, 0x9f, 0xb1,
+ 0x60, 0x69, 0xd6, 0x51, 0xcf, 0xff, 0x7a, 0x75, 0xff, 0xa4, 0x2c, 0x3c,
+ 0xd9, 0x1c, 0x89, 0x2c, 0xa1, 0x67, 0xcf, 0x04, 0x97, 0xfe, 0x99, 0xbd,
+ 0xd6, 0x7c, 0x78, 0x75, 0x97, 0xff, 0x9c, 0x58, 0xdc, 0x9f, 0xbd, 0x82,
+ 0x39, 0xd6, 0x5f, 0xcd, 0xf6, 0xd3, 0x81, 0x65, 0xf6, 0x7f, 0x00, 0xb2,
+ 0xfc, 0x41, 0x79, 0x71, 0x65, 0x8e, 0xb2, 0xff, 0xb7, 0xe7, 0x52, 0xd3,
+ 0xbc, 0x96, 0x5e, 0x27, 0x17, 0x24, 0x60, 0x11, 0x67, 0xc8, 0x76, 0xc9,
+ 0xc4, 0x11, 0xbf, 0xff, 0x7b, 0x0b, 0x0d, 0xf3, 0xcb, 0xc6, 0x38, 0x87,
+ 0x59, 0x7d, 0xdb, 0xbf, 0x6a, 0x8a, 0x45, 0x52, 0x44, 0x3e, 0x95, 0xef,
+ 0xc1, 0xf9, 0x47, 0x96, 0x5f, 0xfd, 0xed, 0xef, 0xae, 0x3f, 0xb9, 0x13,
+ 0xac, 0xbf, 0xf9, 0xfa, 0xe7, 0x8c, 0x80, 0x6c, 0x10, 0xeb, 0x2f, 0xfa,
+ 0x25, 0x1a, 0x9e, 0x35, 0x3a, 0xcb, 0xff, 0xc5, 0x9e, 0xf9, 0x40, 0x30,
+ 0x9e, 0x4b, 0x2f, 0xf1, 0x41, 0xf8, 0x0f, 0xba, 0xcb, 0xfc, 0xff, 0x3b,
+ 0x7f, 0xcc, 0xb2, 0xf3, 0xc8, 0x5e, 0x27, 0x7f, 0x31, 0x1b, 0x93, 0x81,
+ 0x1c, 0x92, 0xb8, 0x75, 0xf4, 0x61, 0x0c, 0xaf, 0x85, 0xc6, 0x1d, 0x65,
+ 0xff, 0xf8, 0x58, 0x9d, 0xe7, 0xe0, 0xbf, 0xc7, 0x20, 0xe2, 0xca, 0x63,
+ 0xfa, 0xde, 0x47, 0x7f, 0xfa, 0x42, 0xf4, 0xe0, 0x7f, 0xb6, 0xb0, 0xeb,
+ 0x2f, 0xfd, 0xd7, 0x24, 0xdc, 0xe4, 0x6a, 0x4b, 0x2f, 0xf9, 0xbb, 0x83,
+ 0xf3, 0xf1, 0x25, 0x97, 0x7b, 0x16, 0x5d, 0x06, 0x2c, 0xbf, 0x83, 0xa0,
+ 0x6c, 0x1c, 0xcb, 0x2c, 0x2e, 0x48, 0x98, 0x19, 0xcf, 0x85, 0xb8, 0x2f,
+ 0x4e, 0x98, 0xe8, 0x21, 0xb1, 0x7f, 0x4b, 0x3d, 0xe7, 0x92, 0xcb, 0xff,
+ 0xe6, 0x98, 0x5f, 0xfc, 0xce, 0x08, 0x08, 0xae, 0x16, 0x5f, 0xfb, 0xb1,
+ 0x63, 0x6d, 0x8e, 0x5d, 0xc2, 0xca, 0xc4, 0x4c, 0x3a, 0xad, 0xff, 0xfd,
+ 0x83, 0xf4, 0x08, 0x2f, 0xe4, 0xe0, 0xe7, 0x20, 0x09, 0x2c, 0x2e, 0x17,
+ 0xf9, 0xc6, 0x81, 0xdc, 0x61, 0xc7, 0x95, 0x4b, 0xe8, 0x7f, 0x39, 0x18,
+ 0x23, 0x68, 0xf9, 0x46, 0xf8, 0x62, 0xed, 0x90, 0xde, 0xe6, 0x71, 0x65,
+ 0xf0, 0x77, 0x47, 0x0b, 0x2b, 0xa3, 0xc1, 0xf0, 0xe5, 0xff, 0xf7, 0xa3,
+ 0xcc, 0x6f, 0x39, 0x84, 0x0d, 0xbc, 0x59, 0x7d, 0xdb, 0xbf, 0x6a, 0x89,
+ 0x41, 0x7f, 0xe8, 0x01, 0xde, 0x5e, 0x87, 0xd2, 0xca, 0x92, 0x2f, 0xf4,
+ 0xa4, 0x46, 0x17, 0xf9, 0xcc, 0x2c, 0x04, 0x01, 0x65, 0xfe, 0xc1, 0xe0,
+ 0xe0, 0xbe, 0xb2, 0x88, 0xf8, 0xf8, 0x65, 0x7e, 0x91, 0x34, 0x1a, 0xb2,
+ 0xff, 0xe7, 0xff, 0x04, 0x20, 0xc8, 0xb0, 0xeb, 0x29, 0xcf, 0xac, 0x89,
+ 0xef, 0xfa, 0x25, 0xc0, 0x80, 0xef, 0x25, 0x97, 0xff, 0x67, 0xf9, 0x07,
+ 0xcf, 0xb8, 0x45, 0x6b, 0x2f, 0x0f, 0x50, 0xb2, 0xf3, 0x8f, 0x16, 0x56,
+ 0x1b, 0x7e, 0x0e, 0x5f, 0xf4, 0xb3, 0xc5, 0x9f, 0xf3, 0x2c, 0xbf, 0xfc,
+ 0xf3, 0xb6, 0xb4, 0xdd, 0x4b, 0xef, 0xd2, 0xcb, 0xde, 0xf9, 0xd6, 0x5f,
+ 0x0b, 0x79, 0x0b, 0x85, 0x72, 0xf9, 0x0e, 0x29, 0xa1, 0x24, 0x78, 0x46,
+ 0x78, 0x80, 0x8e, 0x78, 0xfd, 0xf2, 0x0d, 0xb3, 0x7d, 0xd4, 0xca, 0x9d,
+ 0xdc, 0x1a, 0x4a, 0xb6, 0xe3, 0x1c, 0x77, 0x1d, 0xcf, 0x70, 0x34, 0xa0,
+ 0x4d, 0xc9, 0xc4, 0x3d, 0x4a, 0x5d, 0x3b, 0x8f, 0x95, 0x80, 0xb8, 0x2b,
+ 0x5c, 0xe4, 0x68, 0x41, 0xa4, 0x05, 0x6e, 0xce, 0x47, 0xdf, 0xfe, 0x16,
+ 0x77, 0x90, 0xbc, 0xd7, 0x6e, 0xfd, 0xaa, 0x27, 0x35, 0xff, 0xe1, 0x67,
+ 0x79, 0x0b, 0xcd, 0x76, 0xef, 0xda, 0xa2, 0x89, 0x5f, 0xf0, 0x5f, 0x52,
+ 0x15, 0x37, 0x81, 0x96, 0x5e, 0x6e, 0xb8, 0xb2, 0xf1, 0x41, 0xd6, 0x5f,
+ 0xf1, 0x3f, 0x5f, 0x7f, 0xc9, 0xd6, 0x5f, 0xde, 0xcc, 0xff, 0xb1, 0x65,
+ 0x4e, 0x89, 0xc6, 0x1d, 0x00, 0xdf, 0xce, 0x2e, 0xdf, 0x0b, 0x2f, 0xe1,
+ 0xea, 0x37, 0xb6, 0xf5, 0x97, 0xf3, 0x72, 0x69, 0x30, 0x16, 0x5f, 0xd8,
+ 0x31, 0x06, 0xe7, 0x59, 0x7f, 0xfe, 0xc2, 0x96, 0xcc, 0x1b, 0x73, 0xaf,
+ 0x85, 0xf8, 0xb2, 0xff, 0x44, 0xe2, 0x6d, 0xb9, 0x01, 0x65, 0xd2, 0x16,
+ 0x35, 0x49, 0x99, 0x0d, 0xce, 0xcf, 0x58, 0x63, 0xc6, 0x3b, 0xcb, 0x8c,
+ 0x2e, 0x11, 0x5e, 0xfe, 0xe1, 0x6c, 0xda, 0xc6, 0xcb, 0x2f, 0xfc, 0x58,
+ 0x08, 0x06, 0xb5, 0x06, 0x2c, 0xb0, 0xb8, 0x3f, 0x2e, 0x1a, 0x56, 0x93,
+ 0x24, 0x04, 0x3e, 0xeb, 0x4b, 0x8a, 0x3c, 0x5c, 0x0c, 0xbc, 0xcb, 0xf6,
+ 0xbb, 0x77, 0xed, 0x51, 0x0e, 0x2f, 0xe0, 0xf7, 0xa6, 0x82, 0x59, 0x7e,
+ 0x62, 0xfc, 0x1d, 0x65, 0x85, 0xe2, 0x22, 0x7c, 0x6d, 0xb6, 0x5b, 0x7f,
+ 0xe6, 0x1e, 0x1c, 0xb3, 0xaf, 0xba, 0xcb, 0xfd, 0xac, 0xef, 0xd1, 0xd4,
+ 0x96, 0x58, 0xc5, 0x95, 0x07, 0x8f, 0x86, 0xb4, 0xb2, 0xff, 0xe2, 0x73,
+ 0x7b, 0xf3, 0x6b, 0x50, 0x62, 0xcb, 0xff, 0xbb, 0xf4, 0x1a, 0xdc, 0x15,
+ 0x5b, 0x53, 0xf9, 0x65, 0x82, 0xb2, 0xb7, 0x0f, 0x88, 0xea, 0x37, 0x11,
+ 0x2c, 0xbe, 0xed, 0xdf, 0xb5, 0x44, 0x5e, 0xbf, 0xd9, 0xd0, 0x38, 0xed,
+ 0x3a, 0xcb, 0xf1, 0x38, 0x1f, 0x8b, 0x2f, 0xd9, 0x34, 0x9f, 0x8b, 0x29,
+ 0x91, 0xd9, 0x31, 0x2e, 0x85, 0x48, 0xc3, 0xe6, 0x82, 0x13, 0x5f, 0xe9,
+ 0xfd, 0x9e, 0xc6, 0x9d, 0x65, 0xe8, 0x33, 0xeb, 0x2c, 0xfa, 0x3d, 0x12,
+ 0x34, 0xbe, 0x3f, 0x9b, 0x4b, 0x2f, 0xb7, 0x58, 0xa6, 0x59, 0x7f, 0x60,
+ 0xfd, 0x80, 0x75, 0x97, 0xd0, 0x11, 0x5f, 0x16, 0x56, 0x1f, 0xbf, 0x09,
+ 0x4c, 0x2c, 0xbf, 0xec, 0x60, 0x70, 0x00, 0x6f, 0xac, 0xb8, 0x4e, 0x2c,
+ 0xb4, 0x96, 0x54, 0x1a, 0x97, 0x18, 0xbf, 0xc0, 0xff, 0x3d, 0x8c, 0x35,
+ 0x96, 0x9d, 0x65, 0x68, 0xf1, 0x48, 0xce, 0xff, 0xbe, 0x50, 0x71, 0x07,
+ 0xe8, 0x59, 0x7e, 0x79, 0x1e, 0x24, 0xb2, 0xc7, 0x59, 0x50, 0x89, 0x26,
+ 0x21, 0xf1, 0xcf, 0xc9, 0xef, 0xa6, 0x93, 0xc9, 0x65, 0xdc, 0xe9, 0x65,
+ 0xf7, 0xe5, 0x06, 0xa4, 0xbe, 0xc1, 0xff, 0x8b, 0x2b, 0x11, 0x00, 0x72,
+ 0x37, 0x18, 0x22, 0x3b, 0xfc, 0x59, 0xd4, 0xb8, 0xc6, 0xac, 0xbf, 0x7b,
+ 0x3b, 0x79, 0x2c, 0xbf, 0x3f, 0x41, 0x7f, 0xac, 0xbb, 0x6c, 0x96, 0x5f,
+ 0x9e, 0x7f, 0xe7, 0x96, 0x5f, 0xe8, 0x06, 0x10, 0x79, 0x0b, 0x2c, 0x2e,
+ 0x17, 0xc6, 0xe7, 0x84, 0x24, 0x88, 0x06, 0x17, 0x91, 0xca, 0x77, 0x0a,
+ 0x86, 0x26, 0x9a, 0x13, 0x3a, 0x2f, 0x3b, 0x0f, 0xa1, 0xec, 0x50, 0xbb,
+ 0xe1, 0xd7, 0xcd, 0x02, 0x51, 0xbc, 0xa3, 0x6c, 0x64, 0x42, 0x8b, 0xfe,
+ 0x7e, 0xc5, 0xcb, 0x35, 0x92, 0x59, 0x7f, 0xff, 0xfc, 0x4e, 0x2f, 0x02,
+ 0x2b, 0x63, 0x5b, 0xfe, 0xc6, 0x97, 0x36, 0x61, 0xb1, 0x25, 0x97, 0xec,
+ 0xe1, 0xc7, 0x0b, 0x2f, 0xfc, 0xf2, 0x17, 0x9a, 0xed, 0xdf, 0xb5, 0x44,
+ 0xc8, 0xb0, 0xb9, 0xd3, 0x34, 0xec, 0xef, 0x50, 0x84, 0x39, 0x3d, 0xef,
+ 0xe1, 0xd6, 0x5d, 0xe3, 0xac, 0xbf, 0x6b, 0xb7, 0x7e, 0xd5, 0x16, 0xf2,
+ 0xc2, 0xe0, 0xfa, 0x46, 0x39, 0x82, 0xf7, 0x3e, 0xea, 0xcb, 0xfc, 0x08,
+ 0x18, 0x5f, 0x52, 0x59, 0x7f, 0xe7, 0x90, 0xbc, 0xd7, 0x6e, 0xfd, 0xaa,
+ 0x29, 0x35, 0x85, 0xe2, 0x26, 0x98, 0x64, 0xe6, 0x77, 0x6d, 0x7b, 0x42,
+ 0xcb, 0xff, 0x61, 0x67, 0xf4, 0xc6, 0xf8, 0x2b, 0x2c, 0x75, 0x97, 0xfc,
+ 0x17, 0xeb, 0x5a, 0x0c, 0xdc, 0x59, 0x52, 0x3c, 0xde, 0x08, 0xdc, 0x7e,
+ 0x96, 0x5f, 0xd9, 0xf2, 0x88, 0x3a, 0xcb, 0xfb, 0xa0, 0x09, 0xa7, 0x02,
+ 0xcb, 0xbc, 0x2c, 0x52, 0x9a, 0x08, 0xc8, 0x72, 0x11, 0x67, 0x22, 0xf0,
+ 0xc3, 0x95, 0xd4, 0x33, 0x45, 0x25, 0x3e, 0xab, 0x92, 0x95, 0xb9, 0x0b,
+ 0x6d, 0xf0, 0xcf, 0x12, 0x37, 0x7b, 0xfc, 0x2f, 0x35, 0xdb, 0xbf, 0x6a,
+ 0x88, 0x75, 0x7e, 0xd7, 0x6e, 0xfd, 0xaa, 0x25, 0x85, 0xf6, 0x00, 0xec,
+ 0xb2, 0xfc, 0x2c, 0xef, 0x21, 0x78, 0x7a, 0xfb, 0x66, 0xd7, 0xf8, 0x5e,
+ 0x6b, 0xb7, 0x7e, 0xd5, 0x11, 0x82, 0xf1, 0x90, 0x75, 0x97, 0xa4, 0xc3,
+ 0x59, 0x7e, 0x96, 0x71, 0xf8, 0xb2, 0xc2, 0xf0, 0xf8, 0x26, 0x1d, 0x08,
+ 0xe5, 0xff, 0xf9, 0xc1, 0xb7, 0x82, 0xc9, 0xff, 0x2c, 0xfe, 0x0d, 0x65,
+ 0xff, 0xf9, 0x8e, 0xda, 0x17, 0xfd, 0xbc, 0xf7, 0xe3, 0xa3, 0x16, 0x51,
+ 0x23, 0xaf, 0x86, 0xff, 0x58, 0xbe, 0x17, 0x2c, 0xe2, 0xcb, 0xdf, 0x69,
+ 0x96, 0x5f, 0xff, 0xff, 0xff, 0x61, 0x82, 0xfa, 0x82, 0x09, 0xf5, 0x1f,
+ 0x6e, 0xd8, 0x7e, 0x8e, 0xfd, 0x13, 0x9d, 0xbe, 0xf3, 0x3f, 0xd6, 0x5f,
+ 0xff, 0xf4, 0xb8, 0x2f, 0xbf, 0x3c, 0xdd, 0xfb, 0x35, 0xb5, 0x7a, 0x63,
+ 0xf1, 0x65, 0xf4, 0x78, 0x3f, 0x59, 0x7e, 0xcf, 0x82, 0x3b, 0x59, 0x7f,
+ 0xfa, 0x3e, 0xc0, 0x89, 0x0f, 0xd0, 0x5d, 0xac, 0xbe, 0x62, 0x03, 0x2c,
+ 0xbe, 0xed, 0xdf, 0xb5, 0x44, 0x7a, 0xa9, 0x1e, 0x86, 0x88, 0x2f, 0xff,
+ 0x6e, 0x14, 0x38, 0xdb, 0x87, 0x81, 0x81, 0x65, 0xf7, 0x1f, 0xad, 0xeb,
+ 0x2e, 0x90, 0xbc, 0x44, 0x93, 0x91, 0x7d, 0x2e, 0xff, 0xf0, 0x73, 0xd8,
+ 0x40, 0xc2, 0xff, 0xb1, 0x65, 0xe8, 0xd4, 0xcb, 0x2e, 0x71, 0x64, 0x7c,
+ 0x9c, 0x47, 0xb0, 0xb8, 0x57, 0x09, 0x38, 0xef, 0x50, 0xb0, 0x67, 0x49,
+ 0x88, 0xb4, 0x50, 0xf1, 0x95, 0x94, 0x28, 0x2f, 0xff, 0xe2, 0x73, 0x05,
+ 0xf3, 0xe5, 0x1b, 0x00, 0x71, 0x34, 0xeb, 0x2f, 0xda, 0xed, 0xdf, 0xb5,
+ 0x45, 0x86, 0xbf, 0xd2, 0x28, 0xce, 0x61, 0x2c, 0xb9, 0xa4, 0xb2, 0xc2,
+ 0xf0, 0xff, 0x3a, 0x36, 0x01, 0x85, 0xf0, 0xb0, 0x16, 0x2c, 0xbb, 0xaf,
+ 0xac, 0xbf, 0x83, 0x3b, 0x10, 0x4e, 0xb2, 0xa0, 0xf1, 0x88, 0x62, 0xf4,
+ 0x14, 0xeb, 0x2d, 0x0b, 0x2f, 0xa0, 0x12, 0x3a, 0xca, 0xf1, 0xb2, 0x21,
+ 0x0a, 0x64, 0x47, 0x78, 0x83, 0xe9, 0xd7, 0xff, 0xfd, 0x11, 0xc1, 0x7f,
+ 0x1b, 0x1f, 0xa9, 0x73, 0xa9, 0x66, 0xa7, 0x59, 0x42, 0xd1, 0x36, 0x45,
+ 0xf6, 0x89, 0xd3, 0xb6, 0xd4, 0x72, 0x57, 0xf8, 0x5e, 0x6b, 0xb7, 0x7e,
+ 0xd5, 0x17, 0x3a, 0xf9, 0xb5, 0xa7, 0x59, 0x7d, 0xc8, 0x23, 0x56, 0x56,
+ 0x1e, 0x18, 0x84, 0x37, 0x8a, 0x3a, 0x59, 0x7c, 0xfa, 0x90, 0xbe, 0x1b,
+ 0xed, 0xd2, 0x2b, 0xff, 0xff, 0xff, 0xa3, 0x69, 0x4a, 0x7e, 0xfd, 0xb3,
+ 0x67, 0xb6, 0xc5, 0xce, 0x13, 0x45, 0x5c, 0x0a, 0x7a, 0x9e, 0x7e, 0xcf,
+ 0xb3, 0x67, 0xb6, 0xd6, 0x54, 0x32, 0xe5, 0x67, 0x84, 0xd4, 0x91, 0x72,
+ 0x38, 0xee, 0xcb, 0xda, 0x5d, 0x46, 0xa1, 0x14, 0x78, 0x6e, 0x7a, 0x3e,
+ 0xdf, 0x98, 0x06, 0x18, 0x9b, 0xa7, 0xb7, 0xed, 0x76, 0xef, 0xda, 0xa2,
+ 0x1e, 0x5f, 0xfe, 0xf3, 0x41, 0xdc, 0x62, 0x6e, 0xc1, 0x49, 0x65, 0x85,
+ 0xe2, 0x20, 0xb8, 0x6d, 0x7f, 0xf6, 0xfd, 0x37, 0x20, 0x6e, 0x4c, 0x75,
+ 0x97, 0xbf, 0xd8, 0x16, 0x5f, 0xed, 0x43, 0x7c, 0xa0, 0xeb, 0x2f, 0xf0,
+ 0x79, 0xb0, 0x64, 0xfe, 0x59, 0x7f, 0xff, 0xfd, 0xec, 0xd6, 0xa3, 0xa9,
+ 0x09, 0xf6, 0x20, 0xcb, 0x38, 0x59, 0x38, 0x92, 0x59, 0x7d, 0xdb, 0xbf,
+ 0x6a, 0x88, 0x99, 0x7e, 0xc6, 0xfe, 0x82, 0xb2, 0xfb, 0x73, 0xd0, 0x6a,
+ 0xcb, 0xff, 0xfd, 0xa2, 0xc9, 0xf0, 0x78, 0x60, 0x75, 0x9d, 0xfa, 0x37,
+ 0xac, 0xbb, 0x27, 0x59, 0x7c, 0x13, 0xe0, 0xd6, 0x54, 0x22, 0x77, 0xa6,
+ 0x4d, 0xd1, 0x7b, 0xf7, 0xf9, 0x3e, 0x18, 0xb2, 0xff, 0xbe, 0x13, 0x76,
+ 0x7b, 0x00, 0xeb, 0x2b, 0x11, 0x32, 0xe6, 0x61, 0x2a, 0xb0, 0x56, 0x5f,
+ 0xef, 0x85, 0xfa, 0xf4, 0x6f, 0x59, 0x5d, 0xaa, 0xa8, 0xd4, 0x20, 0x0e,
+ 0x60, 0xe4, 0xe5, 0x1a, 0xe7, 0x0b, 0xbe, 0x23, 0x7f, 0xce, 0xe4, 0x0d,
+ 0x34, 0x1a, 0xb2, 0xe0, 0xce, 0xb2, 0xd8, 0xb2, 0xe6, 0x15, 0xac, 0xa2,
+ 0x3c, 0x2d, 0xe3, 0x06, 0x08, 0x5f, 0xe2, 0xc3, 0x35, 0x9e, 0xe2, 0xcb,
+ 0xf0, 0x39, 0xb3, 0x06, 0xb2, 0xff, 0x31, 0x98, 0x59, 0xd7, 0xd6, 0x53,
+ 0x1e, 0xee, 0x8a, 0xae, 0xcd, 0xd5, 0x97, 0xbb, 0x61, 0xac, 0xbc, 0xe4,
+ 0x3c, 0x36, 0xcc, 0x33, 0x7e, 0x6d, 0x87, 0xee, 0x65, 0x94, 0xe7, 0xb6,
+ 0x45, 0xf7, 0xfd, 0x1e, 0x8d, 0xe7, 0x82, 0x9d, 0x65, 0xff, 0xc1, 0xff,
+ 0x08, 0x21, 0xfc, 0xa0, 0xd5, 0x97, 0xb8, 0xe4, 0xb2, 0xff, 0xfd, 0x1a,
+ 0x07, 0xa3, 0x7c, 0xd1, 0x07, 0xe6, 0x0d, 0x65, 0xff, 0x7b, 0xd1, 0xbe,
+ 0x59, 0xa8, 0x59, 0x5e, 0x44, 0x8b, 0xab, 0xd4, 0xc9, 0xa7, 0x11, 0xd7,
+ 0x11, 0xbf, 0x0a, 0xcb, 0xfc, 0x4e, 0x02, 0x79, 0x12, 0xcb, 0xf7, 0xf0,
+ 0x11, 0xa5, 0x97, 0x37, 0xe0, 0xf5, 0xd8, 0xc2, 0xfa, 0x7f, 0x06, 0x75,
+ 0x95, 0x88, 0xea, 0x78, 0x4d, 0x04, 0xae, 0xfa, 0x73, 0xc6, 0x96, 0x5f,
+ 0x76, 0x12, 0x35, 0x65, 0xce, 0xeb, 0x29, 0xcf, 0x70, 0x88, 0xc4, 0x24,
+ 0xbf, 0xf3, 0xf5, 0xc9, 0xb7, 0x18, 0xbf, 0xc5, 0x97, 0x0f, 0xcb, 0x2f,
+ 0xff, 0x7e, 0x59, 0xad, 0x3c, 0xb0, 0xf1, 0xda, 0xca, 0xc3, 0xe1, 0x71,
+ 0x7b, 0xfe, 0xf8, 0x7d, 0x03, 0xf3, 0x01, 0x65, 0xff, 0x44, 0xb1, 0x8b,
+ 0x20, 0xd5, 0x97, 0xff, 0xef, 0x46, 0x81, 0xcc, 0x1f, 0xc2, 0xfd, 0xe6,
+ 0x96, 0x56, 0xe2, 0x31, 0x66, 0x39, 0xf9, 0xb5, 0xdf, 0x3a, 0xcb, 0xf6,
+ 0x1c, 0xf0, 0x35, 0x97, 0xfe, 0x12, 0x7e, 0x43, 0x75, 0xf8, 0x3a, 0xcb,
+ 0xff, 0xb8, 0xef, 0xde, 0x77, 0x05, 0x1d, 0xac, 0xb6, 0x4c, 0x8a, 0xcf,
+ 0x13, 0xf1, 0x06, 0xf4, 0x6b, 0x8b, 0x2f, 0xff, 0x66, 0xf2, 0xce, 0x77,
+ 0xe6, 0xdd, 0x6e, 0x2c, 0xbf, 0xe8, 0x90, 0x99, 0xae, 0x61, 0x8b, 0x2f,
+ 0xf4, 0xa0, 0xd6, 0xf3, 0xce, 0xb2, 0xa7, 0x3e, 0xe6, 0x3a, 0xbc, 0x41,
+ 0x1a, 0xca, 0xc5, 0x48, 0x7d, 0x1a, 0x7a, 0x18, 0x60, 0x36, 0x21, 0xc0,
+ 0xc2, 0xf0, 0x42, 0x2b, 0xf1, 0x3b, 0x10, 0x16, 0x5f, 0x8c, 0x0c, 0x6a,
+ 0x75, 0x95, 0xb0, 0xf3, 0xcc, 0x25, 0xbf, 0xf9, 0x9c, 0x1a, 0x82, 0xff,
+ 0xb2, 0x4b, 0x29, 0x8f, 0x9f, 0xc4, 0xb7, 0x31, 0xd6, 0x5f, 0x4b, 0xc2,
+ 0x71, 0x65, 0xce, 0x22, 0xa2, 0x17, 0x57, 0x47, 0x90, 0x12, 0x4a, 0x99,
+ 0x10, 0x3f, 0x5e, 0xbf, 0x7b, 0x27, 0x09, 0x2c, 0xbe, 0x7d, 0x46, 0xf5,
+ 0x94, 0x33, 0xcb, 0x01, 0x45, 0xfa, 0x69, 0x63, 0x92, 0xcb, 0xd0, 0x79,
+ 0x2c, 0xbc, 0x41, 0x35, 0x65, 0x74, 0x6e, 0x48, 0x72, 0xfb, 0xcd, 0x13,
+ 0x2c, 0xb0, 0xb8, 0x67, 0xd4, 0xce, 0x89, 0x21, 0xe1, 0x98, 0xe4, 0xad,
+ 0xd3, 0x5c, 0x19, 0xe6, 0x63, 0x1d, 0x42, 0x40, 0xf0, 0xb2, 0xf4, 0xa5,
+ 0x87, 0x84, 0x78, 0x0b, 0x8a, 0x14, 0x9c, 0x96, 0x51, 0xf8, 0xc9, 0x83,
+ 0x0a, 0x2d, 0xed, 0xfb, 0x64, 0x42, 0x30, 0x6e, 0x90, 0xdf, 0xb3, 0x5c,
+ 0x68, 0x59, 0x78, 0x55, 0x0a, 0x82, 0x85, 0x97, 0xfe, 0xd0, 0x67, 0xcf,
+ 0x4c, 0x50, 0x35, 0x97, 0xc5, 0x18, 0x6a, 0xcb, 0xfd, 0xff, 0x66, 0x7f,
+ 0xd8, 0xb2, 0xfe, 0xf4, 0x3f, 0x43, 0xe9, 0x65, 0xf6, 0x1c, 0x27, 0x59,
+ 0x7f, 0xb5, 0x05, 0x83, 0x1c, 0x2c, 0xbf, 0xf3, 0x91, 0xaf, 0xf8, 0xfb,
+ 0x81, 0x65, 0xf0, 0xc4, 0x82, 0x59, 0x7f, 0xff, 0x37, 0xc3, 0xa7, 0xe6,
+ 0x17, 0xb3, 0x0a, 0x5c, 0x59, 0x50, 0x7f, 0x4e, 0x45, 0x4b, 0x2f, 0xcf,
+ 0x9f, 0xc3, 0xac, 0xb8, 0x11, 0x06, 0xc4, 0x82, 0xef, 0xc1, 0xd0, 0x36,
+ 0x42, 0xcb, 0xbc, 0xeb, 0x2e, 0x63, 0x56, 0x58, 0x2b, 0x2b, 0x0d, 0xf4,
+ 0xc2, 0xdc, 0x17, 0xbe, 0xfc, 0x16, 0xf5, 0x96, 0xfa, 0xca, 0xf1, 0xb4,
+ 0xf9, 0x1d, 0xe0, 0x70, 0x5e, 0xd0, 0xae, 0x10, 0x55, 0x93, 0x41, 0x60,
+ 0xd0, 0x30, 0x87, 0xb3, 0x26, 0x2f, 0xd1, 0x11, 0xcc, 0x7d, 0x0b, 0x70,
+ 0x28, 0xf0, 0xab, 0xed, 0x02, 0x31, 0x5f, 0x86, 0x2f, 0x1b, 0x71, 0x65,
+ 0xff, 0xe6, 0x97, 0x05, 0xe7, 0x52, 0x79, 0xc4, 0xed, 0x65, 0x41, 0xfe,
+ 0x61, 0x65, 0x42, 0x70, 0x1e, 0x8d, 0x82, 0xff, 0xb6, 0xb1, 0x4e, 0xb3,
+ 0xed, 0xe0, 0xac, 0xbe, 0xe3, 0x4e, 0x29, 0x59, 0x7e, 0x09, 0x13, 0x49,
+ 0x65, 0x6d, 0x68, 0x8f, 0xda, 0x90, 0xb8, 0x4f, 0x7f, 0xed, 0xac, 0x52,
+ 0xd3, 0xc6, 0xce, 0xf9, 0x8b, 0x2e, 0xda, 0x64, 0xb2, 0xf7, 0xb3, 0x4b,
+ 0x2b, 0x6b, 0x44, 0x1e, 0xd4, 0x97, 0xe1, 0xcb, 0xff, 0x64, 0x89, 0xcd,
+ 0x9b, 0x91, 0xf5, 0x97, 0xdf, 0x6d, 0x62, 0xca, 0xda, 0x47, 0xc1, 0x87,
+ 0xf7, 0xfd, 0x9f, 0x12, 0x77, 0xd3, 0x4c, 0xb2, 0xfe, 0x96, 0xd3, 0x9c,
+ 0x52, 0x2a, 0xc5, 0x45, 0x97, 0x8b, 0x3c, 0xb2, 0xfe, 0x63, 0xe4, 0x68,
+ 0xd5, 0x94, 0x33, 0xc8, 0xec, 0x6e, 0xf0, 0xaa, 0xda, 0x5b, 0x42, 0xcb,
+ 0xfd, 0x9c, 0xe6, 0x31, 0x76, 0xb2, 0xb6, 0xa4, 0xdc, 0x85, 0x24, 0xfb,
+ 0x41, 0xd8, 0xa2, 0x11, 0xa2, 0xac, 0x8c, 0x8b, 0xaf, 0x69, 0xf8, 0xb2,
+ 0xfe, 0xda, 0xc4, 0xf7, 0xb2, 0x75, 0x97, 0x6d, 0xf4, 0xb2, 0xde, 0x59,
+ 0x5b, 0x0f, 0xf7, 0x6b, 0x1c, 0xda, 0x46, 0xa1, 0x1b, 0xbf, 0xf6, 0xd6,
+ 0x29, 0xe6, 0x11, 0x63, 0xf6, 0xb2, 0xe3, 0x61, 0x65, 0xf0, 0xf0, 0xa6,
+ 0x59, 0x73, 0x7d, 0x65, 0xbe, 0xc6, 0xe3, 0xc4, 0x57, 0xfb, 0xaf, 0xf5,
+ 0x20, 0x91, 0xab, 0x2f, 0xfd, 0x13, 0x16, 0x6f, 0x73, 0x9d, 0x96, 0x53,
+ 0x9f, 0xb0, 0x4d, 0xef, 0xff, 0xfe, 0xf0, 0x46, 0xd9, 0xa9, 0x8b, 0x37,
+ 0xfb, 0x07, 0x1c, 0xe4, 0x1a, 0xb2, 0xff, 0xf3, 0x4d, 0x2c, 0xea, 0x5b,
+ 0x0e, 0xee, 0x4b, 0x2e, 0x7d, 0xd5, 0x97, 0xff, 0xfb, 0x99, 0xfd, 0x9e,
+ 0xce, 0xe0, 0xc2, 0xc1, 0xf9, 0xa6, 0x59, 0x53, 0xaa, 0x49, 0xc4, 0xf3,
+ 0x61, 0x39, 0xd9, 0x0f, 0x9d, 0x1d, 0x33, 0xe3, 0x35, 0xb5, 0x2a, 0xfb,
+ 0x14, 0xca, 0x8f, 0xbf, 0xdd, 0x47, 0xf3, 0x3a, 0x92, 0xcb, 0xfb, 0x1b,
+ 0xe5, 0x1d, 0x2c, 0xb1, 0xab, 0x2b, 0x69, 0x9f, 0x90, 0xab, 0x34, 0xdb,
+ 0x2c, 0xba, 0x7f, 0x2c, 0xbd, 0xae, 0x71, 0x65, 0xc5, 0xc5, 0x94, 0x29,
+ 0x36, 0x7b, 0xc7, 0x6f, 0x1e, 0x3b, 0x59, 0x42, 0x83, 0xc4, 0xc2, 0x7b,
+ 0xfb, 0x68, 0x83, 0x1f, 0xb8, 0x59, 0x7f, 0x0a, 0xbd, 0xa8, 0xb6, 0xe0,
+ 0xeb, 0x2b, 0x68, 0x3e, 0xe1, 0x56, 0x67, 0x7f, 0xfe, 0x1e, 0xcc, 0xe1,
+ 0x4f, 0x3b, 0xee, 0x6c, 0xd9, 0xed, 0xb5, 0x97, 0xf3, 0x94, 0xfe, 0x8d,
+ 0xc5, 0x97, 0xa5, 0x00, 0x59, 0x43, 0x3c, 0xc7, 0x30, 0xbf, 0x79, 0xfe,
+ 0xf2, 0x59, 0x7f, 0x36, 0x8b, 0x33, 0x4b, 0x2f, 0x77, 0x3f, 0x96, 0x5f,
+ 0xa3, 0x82, 0xab, 0x6b, 0xda, 0xd6, 0x5c, 0x73, 0xac, 0xae, 0x1e, 0x78,
+ 0x4e, 0x2f, 0xd1, 0xc0, 0xf9, 0x96, 0x56, 0xc4, 0x5b, 0xc9, 0xbb, 0x84,
+ 0x54, 0xb2, 0xfd, 0x27, 0xd3, 0xf6, 0xb2, 0xe6, 0x99, 0x65, 0x41, 0xbf,
+ 0xc2, 0x8b, 0xfc, 0x59, 0xd4, 0x89, 0xe7, 0x59, 0x5a, 0x3d, 0x2e, 0x0f,
+ 0xdf, 0xb8, 0x17, 0x20, 0x2c, 0xad, 0x87, 0x93, 0xf2, 0x2b, 0xf8, 0xb3,
+ 0x79, 0x67, 0x16, 0x51, 0xcf, 0x44, 0x04, 0x97, 0xb8, 0xc0, 0x59, 0x7c,
+ 0xc5, 0x1c, 0x59, 0x58, 0x7b, 0xcc, 0x45, 0xe1, 0xcb, 0xc6, 0x18, 0x62,
+ 0x4b, 0xf3, 0x97, 0xfd, 0x89, 0x05, 0x9a, 0x0b, 0xff, 0xff, 0xa2, 0x7d,
+ 0x9c, 0x0c, 0x75, 0xff, 0x61, 0xf3, 0xe5, 0x00, 0x04, 0x2c, 0xbb, 0x6f,
+ 0x16, 0x5f, 0x7e, 0x6c, 0xfa, 0xcb, 0x0d, 0x65, 0x0d, 0x18, 0x38, 0xe8,
+ 0xe3, 0x21, 0x23, 0xa8, 0x56, 0x2a, 0x38, 0xe5, 0x00, 0x9a, 0x50, 0xf9,
+ 0xbf, 0x78, 0x85, 0x4d, 0xbd, 0xd5, 0x97, 0x3b, 0xac, 0xb7, 0x98, 0xf2,
+ 0x1c, 0xce, 0xff, 0xfe, 0x06, 0xa3, 0x66, 0xa3, 0xfd, 0x4a, 0x0d, 0xd3,
+ 0x98, 0xb2, 0xf8, 0x4e, 0x38, 0x16, 0x5d, 0x37, 0x96, 0x5f, 0xf8, 0xfb,
+ 0x31, 0xb4, 0xc7, 0x83, 0x56, 0x53, 0x1e, 0xc3, 0x8c, 0x5f, 0xf9, 0xa6,
+ 0xd9, 0xe8, 0x6d, 0x07, 0x71, 0x65, 0x42, 0x67, 0xfa, 0x60, 0xf3, 0xd8,
+ 0x08, 0x2f, 0xff, 0xdd, 0xf8, 0x83, 0xfd, 0x85, 0x9b, 0xbf, 0x6c, 0xdd,
+ 0x59, 0x70, 0x7c, 0xb2, 0xfc, 0xdb, 0xba, 0xe7, 0x16, 0x54, 0x22, 0x7c,
+ 0xd5, 0xdd, 0x0b, 0xdf, 0xc4, 0x1f, 0xb4, 0xf0, 0xb2, 0xff, 0x41, 0x47,
+ 0x21, 0x8e, 0xb2, 0xf3, 0xff, 0x8b, 0x28, 0xd3, 0xcc, 0xd1, 0x85, 0xed,
+ 0xd1, 0xc2, 0xca, 0x63, 0xc2, 0x09, 0x1d, 0xef, 0x38, 0xad, 0x65, 0xfb,
+ 0x78, 0x65, 0x9c, 0x59, 0x7c, 0x06, 0x20, 0xac, 0xac, 0x3c, 0xb0, 0x95,
+ 0x5f, 0x60, 0xf2, 0x75, 0x97, 0xdb, 0x9b, 0x23, 0x6a, 0x59, 0x7f, 0x8a,
+ 0x36, 0xf0, 0x98, 0xd5, 0x97, 0xfb, 0xef, 0xd7, 0x1f, 0xa3, 0x16, 0x5a,
+ 0x16, 0x5e, 0x68, 0x25, 0x95, 0xa3, 0x55, 0xf1, 0x0a, 0xda, 0x99, 0x51,
+ 0xa3, 0x85, 0x86, 0x10, 0xf6, 0x4f, 0xd4, 0x38, 0x9a, 0x5a, 0x3e, 0xe4,
+ 0x24, 0x26, 0x8d, 0x97, 0x50, 0xdc, 0x39, 0x87, 0xa1, 0x76, 0x2b, 0x21,
+ 0x26, 0xbf, 0x90, 0xef, 0x22, 0xdb, 0x2c, 0x10, 0xd3, 0x75, 0x82, 0xfd,
+ 0xac, 0xdf, 0x1d, 0x2c, 0xbc, 0x59, 0xf5, 0x97, 0xff, 0xba, 0x97, 0x39,
+ 0x0d, 0xd7, 0xff, 0x07, 0x59, 0x5a, 0x44, 0x89, 0x15, 0x18, 0x37, 0x7f,
+ 0xe9, 0xf0, 0xa0, 0xcf, 0x9a, 0xfc, 0x59, 0x7f, 0xb3, 0x7b, 0xb7, 0x78,
+ 0x4b, 0x2e, 0x2f, 0xe1, 0xf9, 0x92, 0x05, 0xf4, 0x60, 0xd9, 0x65, 0x31,
+ 0xe5, 0x98, 0x57, 0x78, 0x3f, 0xe2, 0xcb, 0xfe, 0xdc, 0x7f, 0xcd, 0x26,
+ 0xd4, 0xcb, 0x2f, 0xfa, 0x24, 0x63, 0xeb, 0xf1, 0x8b, 0x2f, 0xff, 0xff,
+ 0xfb, 0x9b, 0x3d, 0x93, 0xc1, 0x9d, 0x4b, 0x9b, 0x03, 0xde, 0xb5, 0x1b,
+ 0x26, 0x37, 0xad, 0x9b, 0x3d, 0xb6, 0xb2, 0xfe, 0xeb, 0x64, 0xd9, 0x9d,
+ 0xac, 0xa8, 0x55, 0x03, 0x90, 0xee, 0xec, 0x89, 0xc7, 0x48, 0xfb, 0xe7,
+ 0x01, 0x85, 0x65, 0xfb, 0xd0, 0x08, 0xdc, 0x59, 0x63, 0x16, 0x5f, 0xd2,
+ 0x91, 0xe6, 0x8d, 0xd5, 0x96, 0x02, 0xca, 0x63, 0xff, 0x01, 0x51, 0x09,
+ 0x04, 0xca, 0xed, 0xb8, 0x59, 0x7a, 0x0d, 0x65, 0x97, 0x41, 0xd6, 0x5d,
+ 0x1d, 0x2c, 0xa1, 0x9a, 0xd9, 0x85, 0xa8, 0x91, 0x09, 0xc1, 0x9f, 0xa4,
+ 0xdd, 0xb7, 0xb5, 0xac, 0xbf, 0xfc, 0x08, 0x2e, 0xf6, 0x61, 0x06, 0x59,
+ 0xc5, 0x97, 0xf9, 0xfa, 0x06, 0x9b, 0xa0, 0x2c, 0xbf, 0xf0, 0x4f, 0x19,
+ 0xc2, 0xcd, 0xee, 0xb2, 0xff, 0x01, 0xcb, 0x27, 0x12, 0x4b, 0x2b, 0xa4,
+ 0x79, 0x79, 0x2f, 0x86, 0xbf, 0x3e, 0xbd, 0xb2, 0x5d, 0xac, 0xbf, 0xcd,
+ 0xb3, 0x8f, 0x1d, 0x49, 0x65, 0xff, 0x73, 0x66, 0x14, 0x04, 0x57, 0xc5,
+ 0x95, 0x0a, 0xb3, 0xf2, 0x17, 0xc6, 0x97, 0xb4, 0x62, 0x27, 0x3e, 0xf1,
+ 0x01, 0x1a, 0xdf, 0xff, 0xda, 0xd8, 0x59, 0xbf, 0x35, 0x2d, 0x90, 0x37,
+ 0x9b, 0x8b, 0x2f, 0xff, 0x6b, 0xc6, 0x38, 0xf6, 0x08, 0x00, 0x36, 0xea,
+ 0xcb, 0xff, 0xb0, 0xcd, 0xd3, 0x85, 0x8f, 0x84, 0x05, 0x97, 0xff, 0xfe,
+ 0xea, 0x0d, 0x2c, 0x1f, 0x9a, 0x6d, 0x9c, 0xce, 0xa5, 0xac, 0x31, 0x65,
+ 0x32, 0x2e, 0x49, 0x1e, 0xb1, 0x38, 0xd7, 0x61, 0x28, 0xc2, 0xef, 0xbe,
+ 0x18, 0x9d, 0x65, 0xfd, 0x27, 0xd7, 0x18, 0x6b, 0x2f, 0xec, 0xf6, 0x1e,
+ 0x3b, 0x59, 0x50, 0x7b, 0x52, 0x2d, 0xbf, 0x36, 0x9b, 0x7e, 0x2c, 0xa6,
+ 0x46, 0x37, 0xdf, 0x77, 0x48, 0x6f, 0xb6, 0xf3, 0x50, 0xb2, 0xfe, 0x8e,
+ 0x7a, 0x0b, 0xeb, 0x2f, 0xff, 0xee, 0xa5, 0xc3, 0xe1, 0x6c, 0xdd, 0x6f,
+ 0x4e, 0xd9, 0xa5, 0x96, 0xdc, 0x59, 0x7b, 0xf9, 0xc5, 0x95, 0x24, 0x5e,
+ 0xe1, 0x67, 0x6c, 0x21, 0x14, 0xbf, 0xff, 0xc5, 0x9d, 0xf9, 0x8b, 0x03,
+ 0xd7, 0xf6, 0x39, 0x98, 0x6a, 0xcb, 0xff, 0x67, 0x6f, 0x3f, 0xb3, 0xbc,
+ 0x25, 0x96, 0x33, 0x62, 0x28, 0xfc, 0xc9, 0x7f, 0x8d, 0x18, 0x63, 0xc5,
+ 0x0b, 0x2f, 0xe9, 0x70, 0xd0, 0xc7, 0x4b, 0x2f, 0xb0, 0x6f, 0x25, 0x95,
+ 0xd1, 0xe8, 0x98, 0x61, 0x7d, 0xa8, 0x89, 0xd6, 0x5f, 0x4d, 0x1f, 0x75,
+ 0x97, 0xfd, 0x3c, 0x4f, 0xc8, 0x99, 0xb7, 0xac, 0xb9, 0xcc, 0xe2, 0x20,
+ 0x42, 0x44, 0x21, 0x15, 0xed, 0xff, 0x11, 0x65, 0x42, 0x76, 0x58, 0x58,
+ 0xd0, 0x84, 0x28, 0x52, 0x98, 0x7b, 0x7f, 0xcd, 0xa9, 0xc2, 0x0c, 0x2c,
+ 0x59, 0x74, 0xc7, 0x59, 0x7f, 0xa5, 0xcf, 0x87, 0x07, 0xb2, 0x63, 0xd0,
+ 0x01, 0xc5, 0xff, 0xf6, 0x0f, 0xc1, 0x33, 0x8d, 0xff, 0x33, 0x81, 0x65,
+ 0x74, 0x89, 0xe2, 0x4e, 0xb8, 0xf2, 0x59, 0x7f, 0xfa, 0x35, 0xd9, 0xa0,
+ 0xc7, 0x2e, 0xa5, 0xc5, 0x95, 0x23, 0xe3, 0xe0, 0xbd, 0xf6, 0x6a, 0x0e,
+ 0xb2, 0xf1, 0x66, 0xfd, 0x87, 0x86, 0x44, 0x55, 0xa4, 0x7f, 0x72, 0x19,
+ 0x37, 0xf8, 0x8d, 0x2c, 0x6e, 0xbe, 0xb2, 0xdb, 0xd6, 0x56, 0x1e, 0x37,
+ 0x0c, 0xea, 0x11, 0x1e, 0x16, 0xeb, 0xe8, 0xcf, 0x71, 0x65, 0xcd, 0x3a,
+ 0xcb, 0x02, 0x63, 0x71, 0xf2, 0x1b, 0xfd, 0xd9, 0x60, 0xfc, 0xfc, 0x59,
+ 0x7f, 0x03, 0x08, 0x7e, 0x85, 0x97, 0xf7, 0x98, 0x80, 0x21, 0xd6, 0x53,
+ 0x1e, 0xd7, 0xcb, 0x2e, 0x1b, 0x2c, 0xbf, 0xff, 0xbc, 0xd8, 0x58, 0xc3,
+ 0xc8, 0x03, 0xf6, 0xfa, 0x59, 0x7f, 0xa7, 0x83, 0x94, 0x74, 0x05, 0x95,
+ 0x09, 0xa7, 0xca, 0x11, 0xbd, 0x90, 0xf4, 0x2c, 0xea, 0xf7, 0xef, 0x6c,
+ 0x7c, 0xe2, 0xca, 0x83, 0xf9, 0xc5, 0x0b, 0x05, 0x65, 0xfd, 0xf2, 0x89,
+ 0x67, 0xd6, 0x5f, 0x11, 0x67, 0xd6, 0x5e, 0x31, 0xf8, 0xb2, 0xf3, 0xea,
+ 0x5b, 0x0f, 0xa6, 0x0b, 0x3c, 0x41, 0x50, 0xca, 0x91, 0xc8, 0x7d, 0x74,
+ 0x64, 0xd0, 0xe1, 0xd4, 0xa9, 0x2f, 0x4a, 0xcd, 0x75, 0xa2, 0x8f, 0xc3,
+ 0x84, 0x01, 0x7a, 0xb6, 0xe2, 0xcb, 0x7d, 0x65, 0xd0, 0x05, 0x97, 0xff,
+ 0x98, 0x22, 0xb8, 0xd9, 0xc0, 0x80, 0xf9, 0xf5, 0x95, 0xd1, 0xf3, 0x68,
+ 0x5a, 0xff, 0xd1, 0xdf, 0x21, 0xba, 0xfc, 0x1d, 0x65, 0x2c, 0xbd, 0xa0,
+ 0xee, 0x2c, 0xa9, 0x1a, 0xbf, 0x85, 0xd1, 0x22, 0x2c, 0x2d, 0x57, 0xc0,
+ 0xe4, 0xff, 0x59, 0x7f, 0x3f, 0xa0, 0xa2, 0x4b, 0x2f, 0xff, 0xfd, 0xfc,
+ 0x82, 0xce, 0xc9, 0xe7, 0x8d, 0x6a, 0x3f, 0xec, 0x1a, 0xcb, 0xed, 0xe5,
+ 0x9c, 0xd8, 0x89, 0x5c, 0x2b, 0xbf, 0xfe, 0xc2, 0xc3, 0x7c, 0xf2, 0xf1,
+ 0x8e, 0x21, 0xd6, 0x5f, 0xf9, 0xcd, 0xd9, 0xf7, 0x72, 0xd9, 0x3a, 0xca,
+ 0x84, 0xe2, 0x5a, 0x17, 0x3e, 0x3c, 0x25, 0x1b, 0xcf, 0xfe, 0x2c, 0xb8,
+ 0x33, 0xac, 0xa9, 0x1b, 0x4d, 0x0e, 0x5f, 0xb2, 0x5e, 0x79, 0x2c, 0xb8,
+ 0xbf, 0x31, 0xe4, 0x78, 0x86, 0xff, 0x39, 0x09, 0xef, 0x40, 0xd6, 0x5f,
+ 0xff, 0x7f, 0x91, 0x9b, 0x35, 0x1f, 0x6e, 0xd8, 0x6b, 0x2f, 0xdd, 0xec,
+ 0x1f, 0x46, 0x2c, 0xae, 0x1f, 0xf8, 0x54, 0x6f, 0xf1, 0x9e, 0xc2, 0xea,
+ 0x0d, 0x59, 0x7c, 0x19, 0x9c, 0x6b, 0x2f, 0xd9, 0xfd, 0x61, 0x8b, 0x2d,
+ 0xde, 0xc3, 0xcb, 0xf1, 0x1d, 0x42, 0x2a, 0xda, 0x10, 0x17, 0x6a, 0x4b,
+ 0x2f, 0xf1, 0xaf, 0xcc, 0xf8, 0x93, 0xac, 0xbe, 0xd9, 0xd9, 0x90, 0xb2,
+ 0xa4, 0x7b, 0x87, 0x36, 0xa8, 0x54, 0xd1, 0xd1, 0x73, 0x42, 0xcb, 0x50,
+ 0xcd, 0x39, 0x33, 0xb9, 0xdf, 0xc6, 0x8a, 0x34, 0xd0, 0x6a, 0xcb, 0xf0,
+ 0xc9, 0xdf, 0xcb, 0x28, 0x8f, 0x67, 0x86, 0x77, 0xec, 0xe7, 0xdf, 0x4b,
+ 0x2f, 0xff, 0x73, 0x1c, 0xb6, 0x73, 0xa8, 0x28, 0xe2, 0xcb, 0x4b, 0xc7,
+ 0xe3, 0xf2, 0x7b, 0xfa, 0x07, 0x1e, 0x89, 0x2c, 0xbf, 0xd1, 0xfd, 0x8f,
+ 0xdb, 0x6f, 0x59, 0x5a, 0x3e, 0x32, 0x2c, 0xbf, 0xff, 0xf3, 0x75, 0xf7,
+ 0xf1, 0x60, 0xfc, 0xd3, 0x73, 0xbc, 0x62, 0x99, 0x65, 0xff, 0xf4, 0x7f,
+ 0x61, 0x07, 0x77, 0x66, 0x7f, 0x6f, 0x3e, 0xb2, 0xa1, 0x37, 0x26, 0x84,
+ 0x5e, 0x88, 0x42, 0xdb, 0x73, 0xfd, 0x65, 0xff, 0xde, 0x83, 0x76, 0x7c,
+ 0x9f, 0xf1, 0xf5, 0x97, 0xfb, 0x67, 0x52, 0x6f, 0x04, 0xeb, 0x2b, 0xc8,
+ 0x93, 0x00, 0xb1, 0x23, 0x5f, 0x8c, 0x7f, 0x4d, 0xb5, 0xac, 0xbf, 0xec,
+ 0x1e, 0xcf, 0x9a, 0xc6, 0x71, 0x65, 0xb3, 0x47, 0xd9, 0xbc, 0xbe, 0xfe,
+ 0x7f, 0x1b, 0x1a, 0x75, 0x97, 0xfe, 0xd4, 0xdb, 0x39, 0x0d, 0x3b, 0xfd,
+ 0x65, 0x42, 0x66, 0x63, 0x84, 0xd9, 0x14, 0x84, 0xb6, 0xe7, 0x02, 0xcb,
+ 0xff, 0xed, 0x85, 0x1c, 0x89, 0xcb, 0x07, 0xe6, 0x99, 0x65, 0xff, 0xff,
+ 0xdc, 0xd1, 0x44, 0xdb, 0x04, 0xfb, 0x4b, 0x3a, 0xfe, 0x6f, 0x2c, 0xe2,
+ 0xca, 0xd2, 0x32, 0x09, 0x46, 0xbe, 0x98, 0x00, 0x61, 0xbd, 0x4b, 0x29,
+ 0x65, 0xfd, 0x0c, 0x4f, 0xa3, 0x56, 0x5d, 0xfd, 0x86, 0x9b, 0x7f, 0x05,
+ 0xdd, 0x34, 0x96, 0x54, 0x22, 0x2b, 0xa4, 0x2d, 0x18, 0x5f, 0xfc, 0x5f,
+ 0xe6, 0xf6, 0xfc, 0x61, 0x4c, 0xb2, 0xfd, 0xa6, 0xe4, 0x74, 0xb2, 0xb0,
+ 0xfb, 0x5d, 0x16, 0xff, 0xfd, 0x2e, 0x00, 0x33, 0x6c, 0xc6, 0xd3, 0x1e,
+ 0x0d, 0x59, 0x7f, 0x0a, 0x66, 0x93, 0x7f, 0x8b, 0x2f, 0x70, 0x4e, 0x2c,
+ 0xa9, 0xcf, 0x44, 0xe6, 0x77, 0x40, 0x16, 0x5f, 0x8b, 0xfe, 0xcd, 0xd5,
+ 0x97, 0xe9, 0xb8, 0xfa, 0x35, 0x65, 0xe7, 0x33, 0x50, 0x7a, 0x98, 0x55,
+ 0x7f, 0xc4, 0x6c, 0x4c, 0xc5, 0x07, 0x59, 0x7f, 0x1a, 0xf2, 0x28, 0x3a,
+ 0xca, 0x83, 0xe5, 0x63, 0x8a, 0x92, 0xa0, 0xee, 0x88, 0x1a, 0x15, 0x53,
+ 0x11, 0xe9, 0xab, 0xd0, 0x97, 0xbe, 0x6e, 0xdf, 0x4b, 0x2f, 0x1d, 0xcc,
+ 0x59, 0x6e, 0x48, 0xdf, 0xb9, 0x15, 0xfe, 0x61, 0xe1, 0x4b, 0xd8, 0xb2,
+ 0xff, 0xfd, 0xcd, 0x98, 0xc6, 0x6c, 0x2c, 0x01, 0x63, 0xcc, 0xb2, 0xff,
+ 0xbc, 0xda, 0x9b, 0xcf, 0x9a, 0x59, 0x7f, 0xff, 0xff, 0x03, 0x85, 0x8f,
+ 0xd6, 0xc1, 0xf8, 0x3b, 0x0b, 0x3a, 0x96, 0x06, 0x72, 0xc7, 0xe9, 0x65,
+ 0x62, 0x63, 0xfd, 0xac, 0x31, 0xcd, 0xcf, 0xda, 0xa2, 0x98, 0x58, 0xd5,
+ 0x94, 0xe6, 0xd8, 0x24, 0x97, 0xe9, 0xdc, 0xfc, 0xdb, 0x59, 0x50, 0xa8,
+ 0xa2, 0x72, 0x6c, 0x8d, 0x43, 0xb6, 0x66, 0x20, 0xbf, 0xff, 0xdf, 0xe0,
+ 0x9c, 0xd9, 0x92, 0xf4, 0x36, 0x80, 0x77, 0x92, 0xcb, 0xfe, 0x2e, 0xa5,
+ 0xcf, 0xc6, 0xa6, 0x59, 0x7f, 0xee, 0xbb, 0x0b, 0xfb, 0x3e, 0xfe, 0x59,
+ 0x58, 0x7f, 0x7f, 0x3b, 0xbf, 0xf3, 0xf5, 0x8d, 0xa6, 0x3c, 0x1a, 0xb2,
+ 0xf6, 0x30, 0x16, 0x5b, 0x16, 0x5b, 0x00, 0x6a, 0xf7, 0x8d, 0xd2, 0xcb,
+ 0xb5, 0x8b, 0x2d, 0xd1, 0x1e, 0x4f, 0x0a, 0x02, 0x17, 0x58, 0x9f, 0x3b,
+ 0x43, 0x7f, 0x44, 0x2f, 0x0b, 0x2b, 0xd8, 0x1d, 0x2c, 0xb4, 0xcb, 0x2f,
+ 0x83, 0x9d, 0x12, 0xca, 0x9c, 0xda, 0x1c, 0x4a, 0xc6, 0x2c, 0xb9, 0x86,
+ 0xb2, 0xb7, 0x0d, 0x47, 0x04, 0xae, 0x1c, 0xcb, 0x2f, 0xfb, 0x58, 0x3f,
+ 0x41, 0x87, 0x0a, 0xcb, 0xfb, 0xd8, 0x36, 0x2f, 0xac, 0xb4, 0xeb, 0x2e,
+ 0xf7, 0x16, 0x51, 0xa6, 0xa5, 0xc4, 0xaa, 0x13, 0x36, 0xc4, 0xa3, 0x92,
+ 0x78, 0x63, 0xe7, 0x46, 0x2a, 0xdf, 0xbc, 0x13, 0x72, 0x75, 0x97, 0xec,
+ 0x39, 0xdc, 0xeb, 0x2e, 0x38, 0x16, 0x5d, 0xe7, 0xd8, 0x8b, 0xf1, 0xab,
+ 0xe8, 0xa8, 0x04, 0xf7, 0xf6, 0xa3, 0xe4, 0xe0, 0x59, 0x5a, 0x3f, 0x6d,
+ 0xd4, 0xab, 0xfd, 0xb3, 0xa9, 0x14, 0x67, 0x16, 0x57, 0x4a, 0xc5, 0x5a,
+ 0x55, 0xdb, 0x92, 0xdf, 0xff, 0x80, 0xdc, 0xd9, 0xe7, 0xe7, 0xe2, 0x6e,
+ 0x7b, 0x16, 0x52, 0xcb, 0xf8, 0x2c, 0x36, 0x26, 0x59, 0x63, 0x58, 0xdb,
+ 0x1c, 0x2e, 0xfc, 0xfc, 0xf3, 0xc9, 0x65, 0xf3, 0xc9, 0x8e, 0xb2, 0xfd,
+ 0xdb, 0xeb, 0x3b, 0x59, 0x7f, 0xc1, 0xea, 0x5c, 0xd9, 0xcf, 0xf6, 0xb2,
+ 0xfe, 0x2f, 0xcb, 0x01, 0xc5, 0x97, 0x8d, 0x7e, 0x6c, 0x44, 0xae, 0x8a,
+ 0x5c, 0xfe, 0xbc, 0x8f, 0x9f, 0xc2, 0xda, 0xb4, 0x9b, 0x7f, 0x89, 0xcc,
+ 0x8c, 0x82, 0xfe, 0x6f, 0x3b, 0x4f, 0x0b, 0x2f, 0x4a, 0x3a, 0x59, 0x7f,
+ 0x1b, 0xad, 0x67, 0x5c, 0x59, 0x7f, 0xfe, 0x2c, 0xeb, 0xfb, 0x3c, 0xfb,
+ 0xf6, 0x0f, 0xc1, 0x9d, 0x65, 0xfb, 0xd1, 0x3e, 0x18, 0xb2, 0xc7, 0x84,
+ 0x43, 0x8d, 0x7a, 0xfe, 0xce, 0x49, 0x81, 0x8b, 0x2f, 0x4b, 0x3e, 0xb2,
+ 0xa4, 0x79, 0x1f, 0x2c, 0xa8, 0x4f, 0x2b, 0x0e, 0x3a, 0x2c, 0x61, 0xd7,
+ 0x85, 0xb8, 0x5c, 0x2f, 0xde, 0x6e, 0x47, 0x4b, 0x2f, 0xdd, 0x76, 0x51,
+ 0xbd, 0x65, 0xfc, 0xfa, 0x9a, 0x4d, 0xe5, 0x97, 0xf8, 0x33, 0xf9, 0xb7,
+ 0xe4, 0xcb, 0x2f, 0xe1, 0x3d, 0xe8, 0x2e, 0xd6, 0x5f, 0x14, 0x1f, 0x8b,
+ 0x2e, 0x7e, 0xb8, 0x7a, 0x1f, 0x2f, 0xa8, 0x4c, 0xdb, 0x0a, 0x1c, 0xaf,
+ 0x85, 0xc1, 0x84, 0x3d, 0xdc, 0xe2, 0xcb, 0x62, 0xcb, 0xfe, 0x63, 0x5b,
+ 0xe5, 0x9b, 0xbb, 0x34, 0x69, 0xf7, 0x8b, 0xdf, 0xe6, 0x20, 0x61, 0xdf,
+ 0xa5, 0x95, 0x32, 0x21, 0xf7, 0xaa, 0xdf, 0xff, 0xe2, 0xce, 0xff, 0xf8,
+ 0xff, 0x26, 0x2c, 0x33, 0x64, 0x6d, 0x4b, 0x2f, 0xfd, 0xdc, 0x1f, 0xd9,
+ 0xcc, 0x62, 0x59, 0x50, 0x8a, 0x6f, 0x34, 0xdf, 0xb5, 0x1b, 0xe3, 0x4b,
+ 0x2f, 0xa3, 0xbc, 0x3a, 0xcb, 0xfd, 0xb3, 0x39, 0xc6, 0xc3, 0x16, 0x59,
+ 0xa6, 0x3d, 0x7d, 0x11, 0x5f, 0xce, 0x5b, 0x07, 0x04, 0xb2, 0xa1, 0x3c,
+ 0x3c, 0x86, 0x63, 0x11, 0x72, 0x10, 0x01, 0x28, 0xbe, 0xc3, 0xc7, 0x6b,
+ 0x2f, 0xee, 0xda, 0x7c, 0xeb, 0xeb, 0x2d, 0x12, 0x3d, 0x23, 0x08, 0xaf,
+ 0x46, 0xa4, 0xb2, 0xff, 0xff, 0x68, 0x3d, 0x4b, 0x9b, 0x20, 0x87, 0xe8,
+ 0xdb, 0xcd, 0x42, 0xca, 0xda, 0x1d, 0x0b, 0x20, 0xaa, 0x14, 0x87, 0x79,
+ 0xe1, 0x5d, 0x28, 0xea, 0xc7, 0x2c, 0x93, 0x21, 0x74, 0x6c, 0xa0, 0x4e,
+ 0xe5, 0x03, 0xf5, 0x1a, 0x0b, 0x42, 0xce, 0x69, 0x55, 0x7a, 0x95, 0x96,
+ 0x79, 0x47, 0x1e, 0x96, 0xb4, 0x03, 0x82, 0x97, 0x8f, 0xc8, 0xe4, 0x3f,
+ 0x2a, 0xfb, 0x7c, 0x29, 0x0c, 0x28, 0xdd, 0x1c, 0xbd, 0x3e, 0x4e, 0xb2,
+ 0xff, 0xb4, 0xe6, 0x6c, 0x71, 0xbc, 0xeb, 0x2f, 0x4b, 0xae, 0xd6, 0x5f,
+ 0xce, 0x64, 0xc4, 0xc3, 0x59, 0x74, 0x80, 0xb2, 0xe9, 0xce, 0xb2, 0xb6,
+ 0x1a, 0xf6, 0x17, 0xbf, 0xff, 0x13, 0x4f, 0xb1, 0xb0, 0xb3, 0xbd, 0xdf,
+ 0xe1, 0xd6, 0x5e, 0x3c, 0x76, 0xb2, 0xf7, 0x5e, 0xc9, 0x8f, 0xd8, 0x0b,
+ 0x37, 0xff, 0xf6, 0x4e, 0xe5, 0xfe, 0x47, 0x7b, 0x0e, 0x76, 0x2e, 0xd6,
+ 0x5f, 0xd2, 0xe4, 0xd2, 0x89, 0x96, 0x50, 0xd1, 0x1d, 0xd2, 0xf5, 0xfc,
+ 0x3e, 0x3c, 0x75, 0x25, 0x95, 0x07, 0xa4, 0xe4, 0x97, 0xfa, 0x6f, 0x34,
+ 0x1d, 0xc6, 0xb2, 0xff, 0x6c, 0xd6, 0x37, 0xa0, 0x6b, 0x2a, 0x0f, 0x9c,
+ 0x8c, 0xeb, 0x15, 0x95, 0x1a, 0x3c, 0xc7, 0x9a, 0x1f, 0xf2, 0xeb, 0xc2,
+ 0x60, 0xa3, 0x15, 0x0c, 0x21, 0xef, 0xb0, 0x8d, 0xdc, 0x59, 0x7f, 0xff,
+ 0xfe, 0xf3, 0x7f, 0xd9, 0xa8, 0xdf, 0xb0, 0xe1, 0xdd, 0xd9, 0x9d, 0x4b,
+ 0x02, 0x40, 0xe2, 0xcb, 0x7d, 0x91, 0x65, 0xc2, 0x5b, 0xff, 0xe2, 0x9b,
+ 0xd0, 0xda, 0x63, 0xb6, 0xdc, 0x1d, 0x65, 0xcc, 0x75, 0x94, 0xc7, 0xcf,
+ 0x32, 0x8d, 0xff, 0x8e, 0x76, 0x9b, 0xce, 0x51, 0x0b, 0x2f, 0xf3, 0xca,
+ 0x6f, 0x37, 0x5f, 0x59, 0x7f, 0xd2, 0x09, 0x7e, 0x37, 0xbf, 0x96, 0x5f,
+ 0xfa, 0x3b, 0xd8, 0x4f, 0xc3, 0xc1, 0x2c, 0xbf, 0x41, 0x7f, 0x60, 0xd6,
+ 0x5f, 0xbf, 0xb0, 0x1d, 0x01, 0x65, 0x31, 0xea, 0x84, 0xa6, 0xff, 0xf7,
+ 0x9b, 0xbf, 0x66, 0xce, 0x07, 0xd1, 0xb8, 0xb2, 0xfe, 0x28, 0xea, 0x4c,
+ 0x4b, 0x29, 0x65, 0xfe, 0xcf, 0x16, 0x7f, 0xcc, 0xb2, 0x86, 0x7d, 0x04,
+ 0x59, 0xf0, 0xbb, 0xfe, 0xfc, 0x4b, 0x93, 0x4a, 0x27, 0x59, 0x6c, 0xc4,
+ 0xc8, 0x7a, 0x85, 0xc7, 0xcb, 0xaf, 0xff, 0xbf, 0xec, 0x06, 0xc3, 0xc6,
+ 0x7c, 0x78, 0x4b, 0x2d, 0xa5, 0x96, 0x31, 0x65, 0xfc, 0xe3, 0xd6, 0x83,
+ 0x3a, 0xcb, 0xf4, 0x61, 0x7f, 0x6d, 0x65, 0xb6, 0x85, 0x95, 0x88, 0x91,
+ 0x34, 0x47, 0xb1, 0x23, 0x97, 0xf0, 0xa6, 0xfb, 0xed, 0xac, 0x59, 0x6e,
+ 0xb6, 0x1f, 0x66, 0x25, 0xdb, 0x98, 0x9b, 0xbb, 0xc6, 0x9b, 0x43, 0x5c,
+ 0x25, 0x98, 0xd4, 0xe7, 0x5e, 0x84, 0xa1, 0x46, 0x85, 0xf8, 0xec, 0xaf,
+ 0xff, 0xff, 0x36, 0x1f, 0x3c, 0xd8, 0x7d, 0x85, 0x9f, 0xf6, 0x4b, 0xcd,
+ 0x87, 0x59, 0x7f, 0xff, 0xf4, 0x9b, 0x85, 0x9b, 0xfd, 0x93, 0x7a, 0x0a,
+ 0x6d, 0x8f, 0xdb, 0x6f, 0x59, 0x7f, 0xf9, 0xb0, 0xc2, 0xce, 0x67, 0xbc,
+ 0xdc, 0x59, 0x6c, 0xe9, 0x18, 0x1f, 0x78, 0xbf, 0xff, 0x9b, 0x0c, 0x2c,
+ 0x9f, 0x03, 0xf2, 0x73, 0x5f, 0x8b, 0x2f, 0xfd, 0x9a, 0xf4, 0x6c, 0x7f,
+ 0x86, 0x16, 0x5f, 0xff, 0xfe, 0x83, 0x0b, 0x37, 0xfb, 0x35, 0xac, 0xff,
+ 0x37, 0x7f, 0x1c, 0xf3, 0x62, 0xca, 0x64, 0x5d, 0x68, 0xfe, 0xff, 0xff,
+ 0xb0, 0x8d, 0xd9, 0xa8, 0xde, 0xdf, 0xe6, 0x1a, 0xda, 0x7e, 0x96, 0x57,
+ 0x95, 0x7f, 0x94, 0x66, 0xbc, 0x29, 0xfc, 0x62, 0x82, 0x11, 0x53, 0x2b,
+ 0xc2, 0x0c, 0xb6, 0xab, 0xff, 0xcc, 0x3d, 0x87, 0x6d, 0x90, 0x37, 0x9b,
+ 0x8b, 0x2f, 0xde, 0x6f, 0xe1, 0xd6, 0x5a, 0x4b, 0x28, 0x52, 0x6e, 0x24,
+ 0x4f, 0x6d, 0x42, 0x2a, 0xe7, 0x84, 0x35, 0xff, 0xfe, 0x9f, 0xce, 0x53,
+ 0x6c, 0xf7, 0x6d, 0xcc, 0x1c, 0xf8, 0x62, 0xcb, 0xf4, 0xa3, 0xa9, 0x71,
+ 0x65, 0xff, 0xff, 0xff, 0xb0, 0x8d, 0xd8, 0xde, 0x08, 0xb9, 0x9b, 0xf0,
+ 0x72, 0x73, 0x7c, 0xc2, 0xf3, 0xdd, 0x02, 0x06, 0x92, 0xff, 0xff, 0xcc,
+ 0x60, 0xc3, 0xad, 0x81, 0x89, 0xf9, 0xdf, 0x83, 0xee, 0x9c, 0xc5, 0x97,
+ 0xff, 0xf6, 0x6f, 0x82, 0xd9, 0xc6, 0xd3, 0x81, 0xca, 0x68, 0x59, 0x5d,
+ 0xa3, 0x47, 0xce, 0xb6, 0x9f, 0xa4, 0xef, 0xd8, 0xa7, 0x91, 0xb9, 0x56,
+ 0x2a, 0x64, 0x0c, 0xa2, 0x6b, 0xf8, 0xd2, 0xcf, 0xf9, 0x96, 0x5c, 0x3c,
+ 0x59, 0x50, 0xcc, 0xab, 0xc8, 0x47, 0xb1, 0x17, 0xa9, 0x04, 0x8f, 0x0d,
+ 0x62, 0x95, 0x24, 0x12, 0xbd, 0xb2, 0xdb, 0x6e, 0xac, 0xb1, 0xd6, 0x5f,
+ 0xe7, 0x96, 0x1d, 0xc8, 0x0b, 0x2f, 0xb3, 0xd1, 0x32, 0xca, 0xda, 0x0f,
+ 0x93, 0xc2, 0x2e, 0x63, 0x77, 0x31, 0x65, 0xc7, 0xef, 0x61, 0xe4, 0xb1,
+ 0x9d, 0xb7, 0x16, 0x5f, 0xff, 0xfd, 0xd9, 0x66, 0xfd, 0x9c, 0x6c, 0x20,
+ 0x6c, 0x2c, 0xde, 0x59, 0xcd, 0xeb, 0x2f, 0x9c, 0xed, 0xc5, 0x97, 0xef,
+ 0x39, 0xdb, 0x8b, 0x2b, 0xc7, 0x91, 0xc2, 0x1a, 0xd2, 0x38, 0xca, 0x18,
+ 0x37, 0xff, 0xbc, 0x1c, 0x23, 0x76, 0x7f, 0xa9, 0x61, 0x2c, 0xbf, 0xd8,
+ 0xe7, 0xd9, 0xb7, 0x07, 0x59, 0x7f, 0xfa, 0x51, 0xcf, 0x07, 0x59, 0xff,
+ 0xb1, 0xd6, 0x50, 0xd1, 0x9d, 0xda, 0x6f, 0x46, 0xf7, 0xfe, 0x2c, 0x09,
+ 0xba, 0x68, 0x3e, 0x2c, 0xbf, 0xff, 0x06, 0x36, 0x16, 0x0f, 0xcc, 0x68,
+ 0xe0, 0xd0, 0x2c, 0xac, 0x4e, 0xf3, 0x50, 0xf5, 0x39, 0x91, 0x1e, 0xdf,
+ 0xfe, 0xff, 0xb3, 0x77, 0xf3, 0x66, 0xe3, 0x90, 0x16, 0x5f, 0xe8, 0x3b,
+ 0x97, 0x52, 0x85, 0x94, 0x48, 0x82, 0xfa, 0x85, 0xff, 0xd8, 0xc0, 0xd8,
+ 0x59, 0xbd, 0xb4, 0xeb, 0x29, 0x8f, 0x9f, 0xe4, 0x57, 0xc6, 0x6c, 0xe4,
+ 0xcb, 0x2d, 0xf5, 0x95, 0x06, 0xe1, 0xc9, 0xef, 0xfc, 0x53, 0x96, 0x6f,
+ 0xe0, 0x63, 0xa5, 0x97, 0xfd, 0xe8, 0xeb, 0x60, 0xa9, 0xbc, 0x0c, 0xb2,
+ 0xfd, 0xfe, 0xa4, 0xdb, 0x6b, 0x28, 0x67, 0xdf, 0xc4, 0x3a, 0x84, 0x69,
+ 0x4f, 0x0b, 0x0a, 0x92, 0xea, 0x7b, 0x4a, 0xb3, 0xe4, 0x65, 0x5f, 0x59,
+ 0x0c, 0x3c, 0x6f, 0xdb, 0xf7, 0x7f, 0x9e, 0x59, 0x7f, 0xec, 0xe0, 0x60,
+ 0xde, 0x46, 0xa6, 0x59, 0x4c, 0x7d, 0xa6, 0x16, 0xdf, 0x6a, 0x4e, 0x35,
+ 0x97, 0x3f, 0x6b, 0x2f, 0xda, 0xcd, 0xb6, 0x02, 0xcb, 0xfd, 0xdf, 0x9b,
+ 0xc4, 0x19, 0xd6, 0x5f, 0xa3, 0xa0, 0x6a, 0x16, 0x54, 0x8f, 0x77, 0xe6,
+ 0xb5, 0x3a, 0x2a, 0x4a, 0x10, 0xf7, 0xbf, 0x82, 0xb5, 0x94, 0x29, 0x4c,
+ 0x22, 0x21, 0x81, 0x85, 0x17, 0xfa, 0x33, 0xe0, 0x10, 0xa4, 0xb2, 0xec,
+ 0xf2, 0xca, 0x23, 0xc9, 0xdb, 0x33, 0xb8, 0xd8, 0x59, 0x76, 0x0d, 0x65,
+ 0x6d, 0x4c, 0x92, 0x99, 0xe1, 0x83, 0x29, 0xd7, 0xfc, 0x86, 0x5b, 0x91,
+ 0x72, 0x32, 0xaf, 0xc2, 0x04, 0x24, 0x9b, 0xc5, 0xef, 0xcd, 0xfe, 0x60,
+ 0x16, 0x5f, 0xbd, 0x9b, 0xdb, 0x7a, 0xcb, 0xff, 0xff, 0x13, 0xff, 0xd1,
+ 0x36, 0xc2, 0xcf, 0x37, 0xf8, 0x1e, 0xc3, 0x0b, 0x2e, 0xc0, 0x2c, 0xbf,
+ 0xf8, 0x80, 0x58, 0xd3, 0x7a, 0x08, 0xd5, 0x94, 0xc7, 0xb2, 0xe2, 0xd7,
+ 0xf4, 0xb9, 0xf6, 0x8e, 0x96, 0x5f, 0xff, 0xf3, 0xcd, 0xb3, 0x9c, 0xcf,
+ 0x6b, 0x58, 0x61, 0x61, 0x8e, 0x05, 0x97, 0xe8, 0x2f, 0x3c, 0x96, 0x5f,
+ 0xf7, 0xf2, 0x78, 0xe3, 0x6b, 0x16, 0x5e, 0x81, 0xc2, 0xca, 0x19, 0xfc,
+ 0xf4, 0x4c, 0x73, 0x8a, 0x59, 0x4b, 0x2f, 0xfb, 0xf9, 0x3c, 0x71, 0xb5,
+ 0x8b, 0x2f, 0x40, 0xe1, 0x65, 0xee, 0x3c, 0xdb, 0x11, 0x33, 0x06, 0x18,
+ 0x17, 0xd0, 0x59, 0xce, 0x2d, 0x84, 0x9e, 0xcf, 0xe3, 0x7c, 0xbe, 0xda,
+ 0x05, 0x50, 0xa3, 0x68, 0x59, 0x7c, 0xce, 0x43, 0x59, 0x63, 0x36, 0x1e,
+ 0xb8, 0xcd, 0xef, 0xd8, 0xfd, 0x4b, 0x8b, 0x2f, 0xe7, 0x9b, 0xf8, 0x5f,
+ 0x59, 0x40, 0x3d, 0x53, 0x0a, 0x2a, 0x49, 0x94, 0x34, 0x21, 0x79, 0x08,
+ 0x0b, 0xee, 0xfc, 0xdd, 0xac, 0xbe, 0x0f, 0xa0, 0xeb, 0x2f, 0xff, 0x83,
+ 0xad, 0x41, 0x61, 0xad, 0xef, 0x60, 0x8b, 0x2a, 0x11, 0x2d, 0x84, 0x9a,
+ 0x22, 0xbe, 0xf4, 0x04, 0x96, 0x5f, 0x05, 0xfa, 0xfa, 0xcb, 0x8b, 0xeb,
+ 0x2f, 0xff, 0xfe, 0x37, 0x35, 0xa6, 0x3e, 0xc9, 0xa4, 0x13, 0xf5, 0x2e,
+ 0x72, 0x35, 0xda, 0xcb, 0xbc, 0xeb, 0x2c, 0xec, 0x89, 0x0d, 0xef, 0x57,
+ 0xe8, 0x63, 0x60, 0xeb, 0x2f, 0x69, 0xba, 0x59, 0x78, 0x23, 0x85, 0x97,
+ 0xff, 0xcc, 0x36, 0x7f, 0xb3, 0xff, 0x67, 0x1a, 0x65, 0x95, 0x25, 0xf2,
+ 0x91, 0x93, 0xe1, 0x59, 0xb0, 0xc7, 0xe8, 0x82, 0x69, 0x65, 0xfa, 0x86,
+ 0x81, 0xcb, 0xbc, 0x42, 0xe4, 0x65, 0x0a, 0x6e, 0x14, 0xfc, 0x9f, 0x78,
+ 0xee, 0xd8, 0xe5, 0xb7, 0x56, 0x5e, 0x9e, 0x27, 0x59, 0x4b, 0x2f, 0xec,
+ 0x38, 0xfd, 0x9c, 0x59, 0x7e, 0x9f, 0x67, 0x6d, 0x3a, 0xcb, 0xfb, 0x9d,
+ 0xf6, 0xe4, 0x6a, 0xca, 0xda, 0x68, 0x95, 0x9c, 0x2f, 0x45, 0xbf, 0x2d,
+ 0xbf, 0xc5, 0xb3, 0x7f, 0x52, 0xe4, 0xcb, 0x2f, 0xff, 0xf0, 0xfd, 0x9f,
+ 0xfb, 0x97, 0x78, 0xda, 0x63, 0xc1, 0xab, 0x2e, 0x9f, 0xa5, 0x97, 0xef,
+ 0x3e, 0xe4, 0x01, 0x65, 0x0d, 0x1b, 0xac, 0x74, 0xec, 0x1b, 0xa3, 0x37,
+ 0xed, 0x82, 0x4f, 0x13, 0xac, 0xbf, 0x16, 0x79, 0xfe, 0xb2, 0xa4, 0x7a,
+ 0x73, 0x16, 0xdf, 0xc6, 0xb7, 0x5c, 0x0f, 0x16, 0x56, 0x8f, 0x4c, 0x88,
+ 0xea, 0x15, 0x13, 0x64, 0x64, 0x2d, 0x0e, 0x4b, 0xfd, 0x1b, 0x0b, 0x37,
+ 0xe7, 0x96, 0x59, 0x96, 0x5f, 0xf0, 0x4b, 0x64, 0xcd, 0x38, 0x66, 0x59,
+ 0x7f, 0x60, 0xe6, 0x94, 0x6e, 0x2c, 0xbf, 0xe3, 0x93, 0x9b, 0xe6, 0x9c,
+ 0xeb, 0x2f, 0xf8, 0xfc, 0x79, 0xb7, 0x7d, 0x93, 0xac, 0xa8, 0x3f, 0x8c,
+ 0x3a, 0xa9, 0xd3, 0x07, 0xd1, 0xf7, 0xe1, 0x53, 0x76, 0x12, 0xcb, 0xd2,
+ 0x80, 0x2c, 0xb6, 0x86, 0x6c, 0x70, 0x56, 0xf8, 0x1c, 0xdc, 0xed, 0x65,
+ 0x31, 0xe6, 0x84, 0x9a, 0xfc, 0x0c, 0xf8, 0x93, 0xac, 0xbf, 0xc5, 0x86,
+ 0x6e, 0xff, 0x3c, 0xb2, 0xfe, 0xe6, 0x7b, 0xec, 0x6a, 0xcb, 0xfe, 0xe7,
+ 0x83, 0x36, 0xc3, 0x37, 0x3a, 0x59, 0x63, 0x26, 0x45, 0x3f, 0x0d, 0xbe,
+ 0x5d, 0x6f, 0xac, 0xb7, 0x16, 0x5f, 0x8c, 0xfe, 0x7b, 0x61, 0xa6, 0x8b,
+ 0xa1, 0x1b, 0xd3, 0xc8, 0xd5, 0x95, 0x09, 0xc6, 0xe4, 0x34, 0x5d, 0x68,
+ 0x28, 0x74, 0x28, 0x5f, 0x16, 0x81, 0x49, 0x4a, 0xd9, 0x34, 0xeb, 0xb3,
+ 0x56, 0x8c, 0x5f, 0xd0, 0xb5, 0x28, 0xeb, 0xaf, 0xfe, 0x93, 0xf3, 0x27,
+ 0x7f, 0xcf, 0x86, 0x2c, 0xbf, 0xec, 0xf6, 0xc1, 0x1f, 0x73, 0xd8, 0xb2,
+ 0xfe, 0xf6, 0x77, 0x28, 0x3a, 0xcb, 0xfd, 0xec, 0x93, 0x96, 0x74, 0xb2,
+ 0xb0, 0xf8, 0x3e, 0x5d, 0x7f, 0xff, 0xe9, 0x44, 0xfd, 0x4b, 0x8c, 0x6e,
+ 0xce, 0x67, 0x6c, 0x70, 0xea, 0x75, 0x97, 0xfb, 0x0c, 0xd9, 0xe6, 0xc3,
+ 0xac, 0xbf, 0xfe, 0x9f, 0x18, 0xbe, 0x59, 0xbf, 0x67, 0x0c, 0x25, 0x97,
+ 0x38, 0x27, 0x44, 0x47, 0x0d, 0x6b, 0xa4, 0xca, 0xca, 0x1f, 0x97, 0xf7,
+ 0xb0, 0xba, 0x83, 0x56, 0x5f, 0xce, 0x5f, 0x0e, 0xa7, 0x59, 0x4c, 0xaa,
+ 0xd4, 0x08, 0xc5, 0x09, 0xef, 0xc6, 0x98, 0x61, 0x48, 0x85, 0xd7, 0x0f,
+ 0x75, 0x65, 0xec, 0x69, 0x96, 0x5f, 0xf9, 0xb2, 0x6d, 0x9c, 0x8f, 0x3e,
+ 0xe2, 0xcb, 0xfe, 0xc7, 0xeb, 0xd9, 0xf0, 0x3a, 0xcb, 0xff, 0x47, 0xb6,
+ 0x6b, 0x27, 0xc7, 0x3a, 0xcb, 0xff, 0xdc, 0x0e, 0x16, 0xc2, 0xcf, 0x79,
+ 0xc6, 0xb2, 0xff, 0x64, 0xfb, 0x26, 0x9c, 0x1a, 0x59, 0x52, 0x44, 0x1f,
+ 0xd2, 0xaf, 0x8a, 0x35, 0x0b, 0x2f, 0xff, 0xe1, 0xec, 0xe3, 0x6d, 0xc1,
+ 0x03, 0xd8, 0x58, 0xde, 0x59, 0x7f, 0xf9, 0xb6, 0xe0, 0x81, 0xec, 0x2c,
+ 0x6f, 0x2c, 0xbe, 0x2c, 0x3e, 0xc2, 0x45, 0x37, 0x17, 0x6f, 0xfb, 0xac,
+ 0x8e, 0xa6, 0x28, 0x3a, 0xcb, 0xfb, 0xae, 0x7b, 0x1f, 0x4b, 0x2f, 0xff,
+ 0xfc, 0xc7, 0xd3, 0x67, 0x44, 0x1f, 0xc7, 0xb6, 0x6f, 0x6f, 0xcd, 0x0b,
+ 0x29, 0xd1, 0x3d, 0xf2, 0xeb, 0xff, 0x41, 0x7e, 0x24, 0xc4, 0x6c, 0x2c,
+ 0xa9, 0xd5, 0xd9, 0x8c, 0x70, 0xd4, 0x3e, 0xce, 0x3a, 0x86, 0x1b, 0x11,
+ 0xcd, 0x0c, 0x6f, 0x1d, 0x7e, 0x1b, 0x1b, 0xc8, 0xaf, 0xff, 0xb1, 0xe7,
+ 0xf4, 0x37, 0xf9, 0x13, 0xe7, 0x16, 0x5f, 0xed, 0x4f, 0x0d, 0xac, 0x25,
+ 0x97, 0x8d, 0xe4, 0xcb, 0x2b, 0x0f, 0x47, 0xa3, 0x2b, 0x1d, 0x66, 0xc3,
+ 0x45, 0x7d, 0x33, 0x64, 0xeb, 0x2f, 0x16, 0x0d, 0x65, 0xfd, 0x80, 0xc0,
+ 0xea, 0x75, 0x97, 0xdb, 0x3c, 0xf3, 0x2c, 0xa8, 0x45, 0xa6, 0x11, 0xf4,
+ 0x46, 0x43, 0x7c, 0x2e, 0xbf, 0x14, 0x61, 0x93, 0xac, 0xbd, 0xb6, 0x1f,
+ 0xac, 0xbf, 0x7f, 0x84, 0xc6, 0xac, 0xa1, 0x41, 0xf8, 0x48, 0xa0, 0xe4,
+ 0x17, 0xf7, 0x5c, 0xcc, 0x23, 0x56, 0x5f, 0x1c, 0x48, 0x02, 0xcb, 0xff,
+ 0xd3, 0x8f, 0x4f, 0xd9, 0x66, 0xfd, 0x37, 0x16, 0x54, 0x23, 0x47, 0x0c,
+ 0xd8, 0xb8, 0x24, 0x77, 0x7f, 0x8b, 0x2f, 0xef, 0xf9, 0xe6, 0x10, 0xeb,
+ 0x29, 0x65, 0xbc, 0xb2, 0xbc, 0x5e, 0x38, 0x5d, 0xd9, 0xc5, 0x97, 0x3e,
+ 0x96, 0x58, 0x12, 0x35, 0x9a, 0x16, 0xbe, 0x79, 0x08, 0x35, 0x96, 0xfc,
+ 0x1e, 0x57, 0x89, 0xe9, 0xd3, 0x08, 0x02, 0x61, 0x42, 0x56, 0xe8, 0x1a,
+ 0xcb, 0xb8, 0xcb, 0x2e, 0xe8, 0x0b, 0x2b, 0xc7, 0x88, 0x2b, 0x16, 0x08,
+ 0xb5, 0xfd, 0xc8, 0xe8, 0x1a, 0x85, 0x97, 0x0d, 0x96, 0x54, 0x32, 0x86,
+ 0xa7, 0x64, 0xc9, 0x79, 0xbd, 0xc2, 0x89, 0xa3, 0x76, 0xd4, 0x71, 0x3e,
+ 0x3a, 0x78, 0xc7, 0xc9, 0xe3, 0x86, 0x7b, 0xcb, 0xaf, 0x6f, 0xf6, 0x2c,
+ 0xbe, 0x63, 0xc7, 0x96, 0x5f, 0x9f, 0xdb, 0x07, 0x0b, 0x29, 0x8f, 0xa3,
+ 0xc3, 0xdf, 0x21, 0xbf, 0xbe, 0x51, 0x2c, 0xfa, 0xcb, 0xec, 0x27, 0x92,
+ 0xcb, 0xef, 0xf0, 0x4e, 0x6c, 0x3c, 0xc1, 0x41, 0x65, 0xfe, 0xfb, 0x4f,
+ 0x9e, 0x0f, 0xd6, 0x5b, 0x16, 0x5e, 0xe4, 0x1a, 0xb2, 0xbc, 0x6b, 0x7e,
+ 0x21, 0x69, 0x96, 0x5f, 0xd8, 0x1c, 0xf7, 0x73, 0xac, 0xa8, 0x3c, 0x1e,
+ 0x09, 0x5f, 0xb6, 0x60, 0xf0, 0x96, 0x57, 0x47, 0x92, 0x44, 0x37, 0xbd,
+ 0x03, 0x59, 0x50, 0x8e, 0x9c, 0x85, 0x5c, 0xc4, 0x57, 0xff, 0xf0, 0x76,
+ 0x77, 0xe6, 0x19, 0x43, 0xcf, 0xdf, 0x9f, 0x4b, 0x2f, 0xec, 0xd0, 0x18,
+ 0xbe, 0xb2, 0xee, 0xba, 0x59, 0x63, 0xec, 0x3c, 0x53, 0x96, 0x5f, 0xbe,
+ 0xd3, 0x93, 0xac, 0xbf, 0xfb, 0xfc, 0xd9, 0xbb, 0xfc, 0xf7, 0xd8, 0xeb,
+ 0x2a, 0x47, 0xe2, 0x44, 0xf7, 0xf7, 0x9e, 0x47, 0xd3, 0x2c, 0xbf, 0xf8,
+ 0xd3, 0x5f, 0xfc, 0xf9, 0x47, 0x52, 0x59, 0x7f, 0x66, 0x39, 0x7f, 0x8b,
+ 0x2f, 0xc5, 0x12, 0xcf, 0xac, 0xa2, 0x3d, 0x1f, 0x95, 0xd4, 0x22, 0xe6,
+ 0x50, 0x98, 0xb9, 0xb8, 0xb2, 0xc7, 0x59, 0x7b, 0x59, 0xd2, 0xcb, 0xd8,
+ 0xd3, 0xac, 0xbe, 0x83, 0x9d, 0x96, 0x5b, 0x27, 0x37, 0xbf, 0x1c, 0xa1,
+ 0xa2, 0xa3, 0xc2, 0xc0, 0x11, 0x25, 0xab, 0xe9, 0xc3, 0xae, 0xd6, 0x5f,
+ 0xf1, 0xb0, 0x52, 0xcf, 0x31, 0xd6, 0x5c, 0xe6, 0xce, 0x7b, 0xbf, 0x25,
+ 0xbf, 0x37, 0x39, 0x07, 0x59, 0x4c, 0x8e, 0xf2, 0x84, 0xce, 0xf2, 0xfa,
+ 0x85, 0xe7, 0x2c, 0x7a, 0x35, 0x05, 0xa3, 0x4a, 0xd1, 0xa1, 0xe1, 0x48,
+ 0xf0, 0x9b, 0x01, 0x09, 0x43, 0x98, 0x31, 0xdf, 0x5f, 0x86, 0xc4, 0xe3,
+ 0x59, 0x7b, 0x83, 0xe9, 0x65, 0xc0, 0xed, 0x65, 0xff, 0xec, 0x9b, 0xd0,
+ 0x46, 0x96, 0x7f, 0xc1, 0x59, 0x46, 0x9f, 0x17, 0x86, 0x2f, 0xbb, 0x0b,
+ 0xc9, 0x65, 0x6c, 0x46, 0x34, 0xa1, 0x01, 0xd1, 0x1d, 0x32, 0x64, 0x9a,
+ 0x87, 0x65, 0xfd, 0xaf, 0x66, 0x83, 0x8b, 0x2f, 0xff, 0xec, 0xea, 0x5c,
+ 0xff, 0xa0, 0xf0, 0xc3, 0xd9, 0x1b, 0x52, 0xca, 0xc4, 0x47, 0xb1, 0x6d,
+ 0xff, 0x68, 0xb2, 0x79, 0xc3, 0xa9, 0xd6, 0x5f, 0xc5, 0xb3, 0xbe, 0x00,
+ 0x6b, 0x2a, 0x0f, 0xb5, 0xcf, 0x2f, 0xfc, 0x1e, 0x6c, 0x38, 0x9e, 0x7f,
+ 0x42, 0xcb, 0xf6, 0x7c, 0x39, 0xd2, 0xcb, 0xc6, 0xe7, 0x4b, 0x2e, 0x89,
+ 0xb6, 0x1e, 0x37, 0xca, 0x28, 0x91, 0x70, 0x18, 0x44, 0x5f, 0xff, 0xc6,
+ 0x7f, 0x18, 0xfb, 0x0b, 0x3b, 0x6d, 0x69, 0xa7, 0x59, 0x7f, 0xff, 0xfe,
+ 0x09, 0x6c, 0x31, 0xfa, 0x96, 0x9c, 0x1b, 0x38, 0x18, 0xeb, 0xd8, 0xc5,
+ 0x86, 0xac, 0xbf, 0xff, 0xff, 0xdd, 0xe7, 0x65, 0x9f, 0xf0, 0x7c, 0xfd,
+ 0x4b, 0x9f, 0xd6, 0x19, 0x8c, 0x3f, 0xf1, 0x96, 0x5f, 0xff, 0xef, 0x87,
+ 0x0b, 0x63, 0x67, 0xca, 0x01, 0xb3, 0x18, 0x6b, 0x2f, 0xf8, 0xf8, 0x7d,
+ 0x87, 0xdc, 0xdf, 0x25, 0x97, 0xff, 0xff, 0xb3, 0x66, 0x84, 0xe4, 0x6c,
+ 0xe3, 0x61, 0x4d, 0xcf, 0xb6, 0x4e, 0x50, 0xb2, 0xb4, 0x98, 0xe9, 0xd8,
+ 0x7c, 0x83, 0x7f, 0xfd, 0xad, 0x67, 0xf9, 0xe6, 0xcd, 0x9e, 0x04, 0x2c,
+ 0xa8, 0x54, 0x60, 0xd1, 0xd7, 0x04, 0xc6, 0xff, 0xfe, 0x8f, 0x60, 0xcd,
+ 0x0c, 0x7b, 0x3f, 0x07, 0x7f, 0xac, 0xa8, 0x57, 0x4f, 0x8b, 0xde, 0x95,
+ 0x72, 0x13, 0x6b, 0xff, 0xff, 0xe6, 0x9b, 0xd9, 0xcd, 0x67, 0x7b, 0x3c,
+ 0xd8, 0x59, 0xbc, 0xb0, 0x61, 0x25, 0x97, 0xec, 0x2e, 0xc4, 0x3a, 0xcb,
+ 0xff, 0xbd, 0x90, 0x53, 0x16, 0x7f, 0x8e, 0xb2, 0xd2, 0x24, 0x75, 0x7d,
+ 0xff, 0x74, 0xa6, 0xff, 0xdb, 0xbf, 0x8e, 0x4d, 0x27, 0xd4, 0xeb, 0x2f,
+ 0x7d, 0x8d, 0x59, 0x76, 0x1f, 0x61, 0xf0, 0x8a, 0x11, 0x2f, 0xfe, 0x69,
+ 0xdc, 0xe7, 0x6d, 0x83, 0x6d, 0xeb, 0x28, 0x67, 0xf7, 0xa3, 0x3b, 0xd3,
+ 0x36, 0xe2, 0xcb, 0xff, 0xfb, 0xed, 0x3e, 0x0f, 0x61, 0xde, 0x5a, 0x69,
+ 0xdc, 0xeb, 0x2f, 0xf4, 0xee, 0x72, 0x8d, 0x4c, 0xb2, 0xff, 0xba, 0xc3,
+ 0x40, 0x7c, 0xd9, 0xac, 0x44, 0x93, 0x2f, 0x5f, 0x01, 0xde, 0x65, 0x96,
+ 0x85, 0x97, 0xb0, 0xa7, 0xd8, 0x6c, 0xbb, 0x22, 0xbf, 0xfe, 0xc0, 0xeb,
+ 0x64, 0xde, 0x09, 0xad, 0x84, 0x6a, 0xcb, 0xf8, 0xe1, 0x06, 0xc3, 0xe9,
+ 0x65, 0xff, 0xf3, 0xfe, 0x34, 0x13, 0xb7, 0x36, 0x72, 0x5c, 0x59, 0x7f,
+ 0xda, 0x9e, 0x27, 0x9c, 0x3a, 0x9d, 0x65, 0xff, 0xb6, 0x4d, 0xe0, 0x9a,
+ 0xd8, 0x46, 0xac, 0xbf, 0xc5, 0xb3, 0x81, 0xdb, 0x0e, 0x96, 0x56, 0x1f,
+ 0xe0, 0x50, 0xef, 0xff, 0xfd, 0x1d, 0x6e, 0xfe, 0x0b, 0x27, 0xd9, 0x38,
+ 0x75, 0x2f, 0xc4, 0xdc, 0x59, 0x50, 0x9a, 0x87, 0x21, 0x74, 0x12, 0x1b,
+ 0xf0, 0xf3, 0xa7, 0x25, 0x97, 0xff, 0x6c, 0xe7, 0x83, 0xb3, 0xfc, 0xe4,
+ 0x69, 0x65, 0xff, 0xfd, 0x1a, 0x06, 0xc8, 0xde, 0xfe, 0x8d, 0x6b, 0x3f,
+ 0xc5, 0x95, 0x3a, 0x2a, 0x3c, 0x95, 0x7f, 0xe9, 0x47, 0xc3, 0xde, 0xce,
+ 0x7d, 0x96, 0x5f, 0xff, 0x7a, 0x27, 0xd8, 0x59, 0xbd, 0xfd, 0xe8, 0xe9,
+ 0x65, 0xff, 0xff, 0x75, 0xc6, 0xc3, 0x36, 0x7b, 0x3f, 0xcc, 0x9f, 0x66,
+ 0x30, 0xd6, 0x50, 0xd1, 0x81, 0x8a, 0x97, 0xff, 0x67, 0xdb, 0xa9, 0x14,
+ 0x6c, 0xdd, 0xed, 0x65, 0xff, 0xf4, 0x75, 0x2e, 0x79, 0xb3, 0xfd, 0x49,
+ 0xbc, 0xb2, 0xff, 0x8b, 0x35, 0x9d, 0xe3, 0x0d, 0x65, 0xfd, 0x3f, 0xe6,
+ 0x28, 0x3a, 0xcb, 0xf3, 0xc4, 0xd1, 0x32, 0xcb, 0xf6, 0x0f, 0xc1, 0x31,
+ 0x65, 0xd1, 0x36, 0xc3, 0xd1, 0x22, 0x8b, 0xff, 0xfb, 0x27, 0xc6, 0x19,
+ 0x07, 0xdb, 0x20, 0x6f, 0x37, 0x16, 0x5f, 0xd9, 0xe6, 0xd7, 0x9d, 0x65,
+ 0xfb, 0xcd, 0xaf, 0x3a, 0xcb, 0xb0, 0xcd, 0x87, 0xa7, 0x85, 0x95, 0x0b,
+ 0x8e, 0xf9, 0x0c, 0xfe, 0x89, 0x1a, 0x30, 0x29, 0x88, 0xb4, 0x95, 0xe5,
+ 0x17, 0x37, 0x28, 0x40, 0x70, 0xbf, 0xf0, 0xb0, 0xbe, 0xfe, 0x60, 0xd6,
+ 0x54, 0xed, 0x85, 0x28, 0xe1, 0x1c, 0x6c, 0x36, 0x3b, 0x97, 0x9d, 0xd4,
+ 0x65, 0xcd, 0x18, 0xa4, 0xc4, 0x5a, 0x85, 0x91, 0xe1, 0x0b, 0xe3, 0x50,
+ 0x2a, 0x11, 0x8f, 0x23, 0xa2, 0xfc, 0xe5, 0x66, 0xec, 0x2b, 0x6f, 0xff,
+ 0x9b, 0x98, 0x39, 0xf0, 0xcd, 0x84, 0x59, 0xd2, 0xcb, 0xfd, 0xf2, 0xcf,
+ 0xfb, 0x27, 0x59, 0x7f, 0x7f, 0x99, 0x13, 0x9d, 0x65, 0xfe, 0xd9, 0xac,
+ 0xea, 0x4c, 0x75, 0x95, 0xa3, 0xe4, 0x30, 0xba, 0xff, 0xcf, 0xaf, 0x67,
+ 0xe0, 0x98, 0x0b, 0x2d, 0xba, 0xb2, 0xff, 0xf8, 0xb2, 0x7d, 0x80, 0x0f,
+ 0xf3, 0x0e, 0x03, 0x16, 0x5f, 0x4b, 0xed, 0x3a, 0xcb, 0xfd, 0xdb, 0x73,
+ 0x07, 0xb0, 0x6b, 0x2f, 0xee, 0xa5, 0xcd, 0x9f, 0x65, 0x96, 0xcf, 0x1f,
+ 0x39, 0x86, 0xd7, 0xfe, 0x94, 0x60, 0x3d, 0x98, 0x5d, 0xac, 0xbf, 0xfd,
+ 0xe6, 0x21, 0xec, 0x13, 0xb2, 0xcf, 0x62, 0xcb, 0xfe, 0x7f, 0xf2, 0x69,
+ 0x04, 0xbe, 0xb2, 0xb1, 0x18, 0x73, 0x1e, 0x81, 0x32, 0xff, 0xbc, 0xc7,
+ 0x8c, 0x2f, 0xf1, 0x65, 0xff, 0xfe, 0x0f, 0xf4, 0x19, 0xb6, 0x7e, 0x6f,
+ 0x04, 0x1f, 0x6c, 0xdd, 0x59, 0x7d, 0x1d, 0xc1, 0xf6, 0x23, 0x47, 0xb3,
+ 0x02, 0x37, 0xa8, 0x57, 0xd9, 0x90, 0x97, 0xec, 0x8d, 0x8f, 0x34, 0x28,
+ 0xea, 0x65, 0x08, 0xad, 0xd8, 0xef, 0x2f, 0xff, 0xed, 0x63, 0x9f, 0x61,
+ 0xaf, 0xd7, 0xb3, 0xde, 0x8f, 0xac, 0xbe, 0xcc, 0x07, 0x16, 0x5f, 0x66,
+ 0xa6, 0x92, 0xcb, 0xff, 0x9b, 0xa9, 0x73, 0x60, 0xdb, 0x7c, 0x0d, 0x65,
+ 0xee, 0xa3, 0x71, 0x65, 0x1a, 0x7d, 0x2e, 0x93, 0x7d, 0x9e, 0x7d, 0xeb,
+ 0x2f, 0xe9, 0x67, 0xb3, 0x7f, 0x16, 0x5b, 0x06, 0x7a, 0x53, 0x11, 0xdf,
+ 0xff, 0x78, 0x3c, 0xd9, 0xe6, 0xff, 0xb3, 0x51, 0xbd, 0x65, 0xfb, 0x8d,
+ 0x9d, 0x1d, 0x65, 0x0c, 0xff, 0x3e, 0xa9, 0x7f, 0x67, 0x45, 0x98, 0x05,
+ 0x95, 0x87, 0x9c, 0x44, 0x57, 0xf1, 0x47, 0x5e, 0xc9, 0xd6, 0x5d, 0x07,
+ 0x1a, 0xa6, 0x1c, 0x21, 0x36, 0x11, 0x9a, 0x74, 0x28, 0x79, 0x7c, 0x82,
+ 0xff, 0xed, 0x41, 0x9b, 0xa5, 0x06, 0x75, 0x2e, 0x2c, 0xb4, 0x2c, 0xbe,
+ 0x6d, 0x3f, 0x4b, 0x2d, 0xf6, 0x36, 0x5c, 0x10, 0xa1, 0xa2, 0x89, 0x9f,
+ 0x2f, 0xf9, 0xcb, 0xbf, 0x31, 0xca, 0x16, 0x5f, 0xfc, 0x32, 0x79, 0xa6,
+ 0x8f, 0x83, 0x38, 0xb2, 0xff, 0xf8, 0xa2, 0x7f, 0x43, 0x7f, 0x8c, 0x5d,
+ 0x49, 0x65, 0xc7, 0x11, 0x65, 0xd1, 0x32, 0xca, 0x83, 0x5e, 0xc3, 0x17,
+ 0xff, 0x36, 0xf6, 0x1e, 0xc8, 0x98, 0x6e, 0x62, 0xcb, 0xff, 0xff, 0xc4,
+ 0xc6, 0xf9, 0xe6, 0xd8, 0x41, 0xdd, 0xd9, 0x9d, 0x4b, 0x02, 0x40, 0xe2,
+ 0xcb, 0xff, 0xe6, 0x97, 0xf9, 0x9b, 0xf5, 0x80, 0xe3, 0xf6, 0xb2, 0xff,
+ 0xd8, 0x3c, 0x73, 0x76, 0x18, 0xe6, 0x2c, 0xbf, 0x79, 0xa0, 0xa7, 0x59,
+ 0x47, 0x4c, 0xef, 0xd0, 0x80, 0x25, 0x2d, 0xe8, 0x57, 0xff, 0xf0, 0x46,
+ 0xe4, 0x0d, 0x9f, 0xcf, 0x47, 0xf5, 0x83, 0x59, 0x7c, 0x76, 0x63, 0x16,
+ 0x54, 0x23, 0x0a, 0x48, 0x8e, 0xb9, 0x44, 0xaa, 0x4f, 0x83, 0xff, 0x94,
+ 0x8d, 0x7f, 0xb5, 0x13, 0xf9, 0xb0, 0x6b, 0x2f, 0xa2, 0x6e, 0x32, 0xca,
+ 0x92, 0xe1, 0xe0, 0xc8, 0xb0, 0xdf, 0xb4, 0x56, 0x96, 0x23, 0xa3, 0x82,
+ 0x33, 0xbf, 0xff, 0xa5, 0x1a, 0x34, 0xe4, 0xdd, 0x4b, 0x83, 0xd3, 0x4e,
+ 0xb2, 0xff, 0xff, 0x71, 0x82, 0x3d, 0x86, 0x93, 0x8c, 0x39, 0xed, 0x93,
+ 0x4c, 0xb2, 0xd9, 0x32, 0x31, 0xb8, 0xbd, 0x7a, 0x26, 0xe2, 0xcb, 0x82,
+ 0x35, 0x97, 0xf7, 0x08, 0xb0, 0x1c, 0x59, 0x53, 0x1e, 0x1f, 0xc5, 0xef,
+ 0xff, 0xfc, 0xe3, 0xc2, 0x7f, 0xf3, 0x34, 0x00, 0x46, 0x75, 0xfe, 0x32,
+ 0xca, 0x87, 0x42, 0xff, 0x95, 0x8a, 0xe7, 0x71, 0x88, 0xb4, 0xe1, 0xf6,
+ 0xa1, 0x05, 0xe9, 0x57, 0xef, 0x3a, 0x96, 0x51, 0x99, 0x7c, 0xa4, 0x2c,
+ 0x06, 0x11, 0xdf, 0xd1, 0x26, 0x1e, 0x12, 0xcb, 0xe2, 0xfb, 0x6f, 0x59,
+ 0x7d, 0x20, 0xbf, 0xd6, 0x5d, 0x1b, 0x8b, 0x2e, 0x0e, 0xe2, 0xcb, 0xd0,
+ 0x50, 0xb2, 0xbb, 0x3c, 0xdd, 0x0c, 0x9c, 0x6a, 0xa1, 0x18, 0x58, 0x46,
+ 0xcd, 0xf7, 0xdf, 0xe3, 0x81, 0x65, 0xff, 0xde, 0x6d, 0x8d, 0xa0, 0xce,
+ 0xfa, 0xed, 0x65, 0xf3, 0x79, 0xe7, 0x59, 0x7e, 0x82, 0x39, 0xa6, 0xac,
+ 0xbf, 0xcd, 0xc6, 0x08, 0xac, 0x70, 0xb2, 0xf4, 0x7e, 0x16, 0x50, 0xcf,
+ 0xeb, 0xe5, 0x3b, 0xcd, 0xaf, 0xde, 0x3b, 0x17, 0x6b, 0x2f, 0xb3, 0xed,
+ 0xc5, 0x95, 0x87, 0x93, 0xc2, 0x8b, 0xd2, 0x83, 0xac, 0xb9, 0xc4, 0x59,
+ 0x5e, 0x36, 0x7c, 0x1c, 0xbf, 0xf7, 0xfc, 0xd9, 0x83, 0x2c, 0x31, 0x65,
+ 0x61, 0xef, 0x31, 0x0d, 0xff, 0xb9, 0x13, 0x67, 0x9b, 0x5e, 0x75, 0x97,
+ 0x67, 0x96, 0x53, 0x1e, 0xa1, 0xcf, 0xaf, 0x69, 0x8d, 0x59, 0x7f, 0xfc,
+ 0x1c, 0x6f, 0x67, 0x7e, 0x6d, 0x86, 0x1f, 0xb5, 0x97, 0xbf, 0x86, 0x2c,
+ 0xb8, 0x33, 0x91, 0xf8, 0xfd, 0x52, 0xf4, 0xe1, 0xfa, 0xcb, 0xef, 0x33,
+ 0x81, 0x65, 0x61, 0xbf, 0xf8, 0xf5, 0x62, 0x23, 0x40, 0xdb, 0x7e, 0x08,
+ 0xac, 0x9f, 0xeb, 0x2f, 0xd3, 0xb9, 0x7f, 0x8b, 0x2f, 0xef, 0x3c, 0xfb,
+ 0x25, 0xf5, 0x97, 0xe2, 0x04, 0x36, 0xf5, 0x97, 0xe9, 0x84, 0xe4, 0x62,
+ 0xca, 0x63, 0xd1, 0x72, 0x8b, 0xf3, 0xe8, 0xba, 0x65, 0x97, 0xa6, 0x8f,
+ 0xac, 0xa8, 0x4c, 0xe7, 0x0a, 0xd8, 0xa3, 0xd0, 0x82, 0xf9, 0x00, 0x49,
+ 0xef, 0x79, 0xc9, 0x65, 0x4e, 0xbd, 0x98, 0x38, 0x76, 0xe1, 0x69, 0xa4,
+ 0x5d, 0xa4, 0x34, 0x27, 0x26, 0x7a, 0x3c, 0x2c, 0xbc, 0xe8, 0xe4, 0x25,
+ 0x18, 0xdf, 0xe3, 0x5b, 0x31, 0x6a, 0xe6, 0xe9, 0x65, 0x85, 0x2b, 0x2f,
+ 0x7e, 0x0e, 0xb2, 0x85, 0x06, 0xc4, 0x85, 0x6e, 0x94, 0xeb, 0x2e, 0xe8,
+ 0xd5, 0x97, 0xf1, 0xde, 0x5a, 0xc3, 0x16, 0x5d, 0x9d, 0x0c, 0xf1, 0xf0,
+ 0x66, 0xf8, 0x53, 0xcf, 0xe2, 0xcb, 0xee, 0xf0, 0x80, 0xb2, 0xff, 0xde,
+ 0x82, 0x8e, 0xf5, 0x18, 0x4b, 0x29, 0xcf, 0x7b, 0xe4, 0x57, 0xf6, 0x4f,
+ 0x06, 0xbf, 0x16, 0x5f, 0xde, 0x61, 0xb6, 0xbb, 0x59, 0x7f, 0xfe, 0x7e,
+ 0x87, 0xa2, 0x73, 0x0b, 0x00, 0x0c, 0x02, 0xcb, 0xba, 0xe6, 0xc4, 0x69,
+ 0x0c, 0x87, 0xb2, 0xef, 0x97, 0x5f, 0xef, 0x43, 0x13, 0xe8, 0xd5, 0x97,
+ 0xf4, 0x31, 0x3e, 0x8d, 0x59, 0x7d, 0xad, 0x36, 0xb6, 0x1e, 0xf7, 0x8c,
+ 0xaf, 0xf7, 0x65, 0x93, 0x69, 0xf7, 0xac, 0xb3, 0x80, 0xfc, 0x48, 0xee,
+ 0xf1, 0x61, 0xd6, 0x5b, 0xa5, 0x97, 0x3c, 0xa4, 0x6b, 0x78, 0x37, 0x7f,
+ 0xff, 0xfb, 0x61, 0xe3, 0x3f, 0xb3, 0x24, 0xdb, 0xcb, 0x39, 0xb2, 0x06,
+ 0xf3, 0x71, 0x65, 0xe3, 0x38, 0x05, 0x97, 0xf6, 0x1c, 0x6e, 0xfd, 0xac,
+ 0xb8, 0xbb, 0xd8, 0x79, 0x7e, 0x1e, 0xa9, 0x23, 0xe5, 0xe1, 0x93, 0x5d,
+ 0xae, 0x84, 0xb2, 0x44, 0xc4, 0x9a, 0x5f, 0x39, 0x6b, 0xc6, 0xac, 0x08,
+ 0xc7, 0x09, 0x4c, 0x31, 0x92, 0xde, 0xe7, 0xd9, 0x65, 0xe9, 0x81, 0xd2,
+ 0xcb, 0xd0, 0x6e, 0xce, 0xcd, 0xd8, 0x07, 0x2f, 0x80, 0x00, 0xee, 0x2c,
+ 0xb0, 0x16, 0x5f, 0xb5, 0x3c, 0x6a, 0x75, 0x97, 0xe6, 0x2f, 0x88, 0x75,
+ 0x95, 0x07, 0xa4, 0x02, 0xab, 0xd2, 0xe6, 0x2c, 0xbf, 0x0a, 0x4a, 0x30,
+ 0x0b, 0x2b, 0x47, 0x8c, 0x01, 0xcb, 0xff, 0x36, 0x19, 0xc0, 0xcc, 0x50,
+ 0x75, 0x97, 0x82, 0xfc, 0x59, 0x52, 0x47, 0x26, 0x33, 0x9c, 0x88, 0x43,
+ 0xfb, 0xfc, 0x61, 0xe1, 0xb4, 0x1d, 0xc5, 0x97, 0x10, 0x56, 0x52, 0xcb,
+ 0xa3, 0x5b, 0x0d, 0x0f, 0x05, 0xab, 0x11, 0x0c, 0x15, 0x8b, 0xff, 0xf9,
+ 0xb5, 0xb3, 0x1b, 0x08, 0xdf, 0x36, 0x1f, 0x3b, 0x59, 0x7f, 0xd9, 0xd4,
+ 0xb9, 0xd4, 0x83, 0xa5, 0x97, 0xff, 0xfe, 0x3f, 0x3b, 0xf4, 0x77, 0xd4,
+ 0x88, 0x23, 0xd8, 0xc6, 0xb9, 0x01, 0x65, 0xff, 0xfe, 0x9f, 0x50, 0x7e,
+ 0x06, 0x36, 0x46, 0xa0, 0x7e, 0x83, 0xac, 0xac, 0x46, 0xab, 0x39, 0x5f,
+ 0xf4, 0xb6, 0x46, 0xcf, 0xfb, 0x09, 0x65, 0x62, 0x79, 0x2c, 0xb7, 0xa8,
+ 0xc4, 0x5c, 0x86, 0xfc, 0x0e, 0x37, 0x46, 0x2c, 0xbf, 0x75, 0x07, 0x9e,
+ 0x16, 0x5f, 0x75, 0x26, 0xf2, 0xcb, 0xda, 0xce, 0xbc, 0x79, 0x9f, 0x29,
+ 0xbf, 0xba, 0x79, 0x14, 0x1d, 0x65, 0xff, 0xff, 0x14, 0xde, 0xce, 0xa5,
+ 0x04, 0x3d, 0x85, 0x9b, 0xf4, 0xdc, 0x59, 0x7f, 0xc5, 0x37, 0xcb, 0x27,
+ 0x72, 0x59, 0x4c, 0x8a, 0x20, 0xb5, 0x5f, 0xff, 0xfe, 0xd6, 0x9a, 0x7d,
+ 0x9e, 0xcf, 0x94, 0x4d, 0xec, 0x9e, 0x3a, 0xf8, 0x7b, 0x59, 0x7f, 0xff,
+ 0xf4, 0x1b, 0xe8, 0xd8, 0x58, 0x13, 0x76, 0x75, 0x2e, 0x31, 0x09, 0x13,
+ 0xac, 0xbf, 0x10, 0x38, 0x41, 0x59, 0x7e, 0xeb, 0x8d, 0x84, 0xb2, 0xb1,
+ 0x18, 0xec, 0xf2, 0x12, 0x7b, 0xff, 0xec, 0xdd, 0x2c, 0x3b, 0x97, 0xf9,
+ 0xb2, 0x0c, 0x59, 0x50, 0xaa, 0xdf, 0x21, 0x9e, 0xc4, 0x5e, 0x8d, 0x14,
+ 0x25, 0xd7, 0xfe, 0xf9, 0xce, 0xf3, 0x6c, 0x2c, 0x31, 0x65, 0xff, 0xda,
+ 0x2e, 0xb3, 0x81, 0x98, 0xa0, 0xeb, 0x2f, 0xf9, 0x8d, 0xf4, 0x34, 0xf0,
+ 0x6a, 0xca, 0x63, 0xff, 0xe2, 0x2d, 0x6c, 0x47, 0x14, 0xa1, 0x83, 0x7f,
+ 0xee, 0x67, 0x52, 0x6d, 0x17, 0x58, 0xb2, 0xff, 0x06, 0x62, 0xcf, 0x3f,
+ 0xd6, 0x54, 0xe7, 0xe4, 0x47, 0xf7, 0xff, 0x48, 0x20, 0xe1, 0x67, 0x39,
+ 0x06, 0x2c, 0xbe, 0x33, 0x64, 0xec, 0xb2, 0xfe, 0x83, 0x07, 0xe7, 0x3a,
+ 0xca, 0xc3, 0xd4, 0xf1, 0x35, 0xff, 0xb2, 0x6f, 0x43, 0x13, 0xe8, 0xd5,
+ 0x97, 0xfc, 0x7c, 0xe6, 0xc9, 0x8a, 0x0e, 0xb2, 0xff, 0xfd, 0xc9, 0xdf,
+ 0x60, 0xfd, 0x1a, 0xd6, 0x6f, 0x8e, 0x96, 0x50, 0xd1, 0xeb, 0xa2, 0x13,
+ 0x9f, 0x7c, 0xee, 0xff, 0xfd, 0x19, 0x3e, 0xc1, 0xe9, 0xa7, 0xfb, 0x61,
+ 0x4e, 0xb2, 0xfb, 0x7e, 0x07, 0xb5, 0x97, 0xff, 0xfc, 0xfa, 0xf6, 0x7d,
+ 0xb0, 0xa7, 0xe4, 0x61, 0x0f, 0xd0, 0xb2, 0xda, 0x59, 0x7f, 0x66, 0xef,
+ 0xd8, 0xa7, 0x59, 0x77, 0xf6, 0x4e, 0x78, 0x24, 0x23, 0x58, 0x8f, 0x9e,
+ 0x89, 0x5e, 0x14, 0x97, 0xff, 0xfe, 0xeb, 0x27, 0x0e, 0xee, 0xce, 0xa5,
+ 0xf8, 0x33, 0x66, 0x68, 0x00, 0x85, 0x97, 0xfd, 0x93, 0x6d, 0x87, 0xf9,
+ 0xd7, 0xd6, 0x5e, 0xcd, 0x0d, 0x65, 0xd1, 0x25, 0x97, 0xff, 0xdc, 0xd9,
+ 0xa8, 0xef, 0x0a, 0x69, 0x67, 0xf8, 0xb2, 0xb1, 0x18, 0x67, 0x3e, 0x00,
+ 0xe0, 0x45, 0xaf, 0xfe, 0x9d, 0xcb, 0x3d, 0x9f, 0xd6, 0x18, 0xb2, 0xff,
+ 0xff, 0xfd, 0x81, 0x34, 0x83, 0xf9, 0xb3, 0xed, 0xd4, 0x8a, 0x0b, 0x3c,
+ 0xd9, 0xa9, 0x96, 0x56, 0x23, 0x1f, 0xa4, 0x4b, 0xfe, 0xc3, 0x3d, 0x06,
+ 0xe7, 0xf8, 0xb2, 0xff, 0xe7, 0x29, 0xce, 0x16, 0x1b, 0x13, 0x2c, 0xa6,
+ 0x3f, 0xc3, 0x0e, 0xaf, 0xe9, 0xba, 0x90, 0x63, 0xeb, 0x2f, 0xf8, 0x3d,
+ 0x7b, 0x3f, 0xac, 0x31, 0x65, 0xff, 0xfd, 0x28, 0xd7, 0x52, 0xe6, 0xcf,
+ 0x43, 0x13, 0xe8, 0xd5, 0x97, 0xe9, 0x7c, 0xb2, 0x4b, 0x2f, 0xfd, 0xd0,
+ 0xfc, 0x17, 0xe1, 0x60, 0xd6, 0x56, 0x1f, 0x30, 0x49, 0xef, 0xf9, 0xff,
+ 0xfc, 0x9a, 0x4d, 0xf5, 0x97, 0xf6, 0x1a, 0x6b, 0xff, 0x8b, 0x2f, 0xb3,
+ 0xcf, 0xf5, 0x97, 0x39, 0xf6, 0x1e, 0x81, 0x17, 0xd4, 0x22, 0xdf, 0xd0,
+ 0x89, 0xb8, 0x06, 0x2c, 0xbe, 0xdb, 0xcd, 0x42, 0xcb, 0x66, 0x8d, 0xe6,
+ 0xf1, 0x8a, 0x85, 0x52, 0x58, 0x61, 0xd1, 0xdf, 0xa1, 0x89, 0xc8, 0x6c,
+ 0x7d, 0x8e, 0xff, 0xec, 0xff, 0x36, 0x6b, 0x1b, 0xd0, 0x35, 0x97, 0xfd,
+ 0xef, 0x47, 0x5b, 0x0c, 0x3f, 0x6b, 0x2f, 0xec, 0xfe, 0xb5, 0x92, 0x59,
+ 0x4b, 0x2f, 0xd9, 0xe2, 0xce, 0xd6, 0x50, 0x0d, 0x91, 0x05, 0xd4, 0xc7,
+ 0xff, 0xf5, 0xfb, 0xd9, 0xd7, 0xd6, 0x5f, 0xec, 0x1b, 0x6f, 0xfb, 0x69,
+ 0x65, 0xd9, 0xcd, 0x87, 0xe9, 0xb8, 0x46, 0xe3, 0xb4, 0xe9, 0xb8, 0x14,
+ 0x66, 0x57, 0xfd, 0x87, 0xf4, 0x36, 0x83, 0xb8, 0xb2, 0xfe, 0xfb, 0x4e,
+ 0x4e, 0x75, 0x95, 0x3b, 0x66, 0x12, 0x38, 0xfa, 0xf1, 0x04, 0xd7, 0x6e,
+ 0xe5, 0x75, 0xf5, 0x19, 0xb3, 0x42, 0x72, 0x62, 0x2d, 0x47, 0x1c, 0x73,
+ 0xdf, 0x46, 0xa2, 0xe6, 0x80, 0x8c, 0xec, 0xa3, 0x03, 0xe4, 0x27, 0xff,
+ 0x2a, 0xd0, 0x2c, 0x5b, 0xe3, 0xb5, 0x10, 0xa3, 0x74, 0xee, 0xff, 0xa0,
+ 0xe5, 0x83, 0xd3, 0x4e, 0xb2, 0xff, 0xff, 0x19, 0xe0, 0xc7, 0x5b, 0x35,
+ 0xa8, 0x9c, 0x9d, 0xf4, 0x6a, 0xcb, 0xfc, 0x58, 0x1c, 0x36, 0x40, 0x59,
+ 0x4e, 0x89, 0x93, 0x19, 0xaa, 0x48, 0xf4, 0xc8, 0x68, 0xde, 0x36, 0x34,
+ 0xb2, 0xff, 0xfa, 0x36, 0x79, 0xf7, 0xec, 0xc3, 0x9e, 0x34, 0x6a, 0xcb,
+ 0xf0, 0x0f, 0x99, 0xf5, 0x97, 0xfd, 0x9b, 0x35, 0x9e, 0x2c, 0x99, 0x65,
+ 0x61, 0xf0, 0x91, 0x3d, 0xff, 0xfe, 0xf3, 0x83, 0x9b, 0x0b, 0x37, 0x96,
+ 0x73, 0x0f, 0x1d, 0xac, 0xbf, 0xff, 0xfe, 0xd0, 0x4e, 0xdc, 0xd9, 0x34,
+ 0x82, 0x5f, 0xd9, 0xe8, 0x93, 0x16, 0x1e, 0x16, 0x5b, 0x8b, 0x2f, 0xdf,
+ 0xd9, 0xdf, 0xce, 0xb2, 0xa1, 0x17, 0xcf, 0x08, 0x10, 0x88, 0xd4, 0xca,
+ 0x92, 0x3c, 0x3a, 0x50, 0xb7, 0xe1, 0x07, 0xe3, 0x21, 0xbf, 0x82, 0x73,
+ 0x60, 0xbb, 0x59, 0x5b, 0x5b, 0x74, 0xfb, 0xb4, 0xc9, 0xa2, 0x34, 0x7c,
+ 0xac, 0xf3, 0x3a, 0x94, 0x9e, 0xf2, 0x9b, 0xc9, 0x5e, 0xfd, 0xe1, 0x0b,
+ 0xa0, 0x2c, 0xbf, 0xed, 0x9b, 0xbf, 0xcf, 0x7d, 0x8e, 0xb2, 0xff, 0xe9,
+ 0xdf, 0xfa, 0xc9, 0xdc, 0xbf, 0xc5, 0x95, 0x88, 0xad, 0xec, 0xa9, 0x8f,
+ 0xaf, 0xff, 0xe9, 0x7b, 0x1a, 0x5c, 0xc2, 0x0f, 0xcb, 0x01, 0x0b, 0x2c,
+ 0xcb, 0x2d, 0xac, 0x3e, 0x80, 0x2c, 0x5f, 0xff, 0x67, 0xfd, 0x83, 0x0f,
+ 0xf9, 0x1c, 0x0f, 0x16, 0x5f, 0xd1, 0x85, 0xd8, 0x87, 0x59, 0x7f, 0xbe,
+ 0x18, 0xc9, 0xc4, 0x3a, 0xcb, 0xff, 0x7a, 0x08, 0x33, 0x67, 0x39, 0x0b,
+ 0x2d, 0xb9, 0xe4, 0x78, 0xfd, 0x40, 0x42, 0xed, 0xd3, 0x5a, 0x84, 0xd8,
+ 0x9e, 0x31, 0x8b, 0xfb, 0xd8, 0x5f, 0x00, 0x56, 0x5f, 0xff, 0xf9, 0xb7,
+ 0x96, 0x73, 0x67, 0xdb, 0x66, 0x7e, 0x3b, 0x6d, 0xf1, 0xe5, 0x97, 0xf8,
+ 0x70, 0x0d, 0x99, 0xd7, 0xd6, 0x5f, 0xff, 0x3e, 0x9f, 0xdd, 0x4b, 0x3f,
+ 0xb3, 0xbe, 0x6e, 0x2c, 0xbf, 0x9a, 0x4f, 0xff, 0x32, 0xcb, 0xff, 0xe7,
+ 0x38, 0xfd, 0x1a, 0x2c, 0x1f, 0x9c, 0xc5, 0x94, 0x34, 0xc2, 0x3b, 0x36,
+ 0xfa, 0xbe, 0xf2, 0xcb, 0xf9, 0xf7, 0x06, 0x59, 0xe5, 0x97, 0x1f, 0x8b,
+ 0x2f, 0x3f, 0x19, 0x65, 0x41, 0xb2, 0x00, 0xbd, 0xff, 0x09, 0x3e, 0x13,
+ 0x9d, 0xfc, 0xb2, 0xf9, 0xb4, 0x4e, 0xb2, 0xa4, 0xaa, 0x55, 0xa3, 0x7a,
+ 0x99, 0x04, 0x98, 0x7e, 0x41, 0xbc, 0xe6, 0xff, 0x73, 0x90, 0xd3, 0xbf,
+ 0xd6, 0x5f, 0xf7, 0x1c, 0xcd, 0xd6, 0xc2, 0x1a, 0xcb, 0xfb, 0x3f, 0x8e,
+ 0x53, 0x2c, 0xbe, 0xce, 0x46, 0x96, 0x58, 0xdf, 0x1e, 0x69, 0x16, 0x5a,
+ 0x50, 0x8e, 0x3c, 0x33, 0x0c, 0x22, 0x2d, 0x25, 0x97, 0x86, 0x10, 0x2c,
+ 0xbf, 0xff, 0xa3, 0x73, 0x63, 0x61, 0x67, 0x9b, 0x0b, 0xa9, 0x71, 0x65,
+ 0xfe, 0xdd, 0x6c, 0xeb, 0xcd, 0x8b, 0x2c, 0x5d, 0x22, 0x48, 0x0b, 0xb7,
+ 0xd0, 0x77, 0x1a, 0xca, 0x84, 0xc2, 0x86, 0x23, 0x90, 0xaf, 0x22, 0x9b,
+ 0xfd, 0x93, 0x7b, 0x3f, 0x03, 0x59, 0x7d, 0x07, 0xe1, 0xd6, 0x5f, 0xfb,
+ 0x0d, 0xf6, 0x7f, 0x85, 0x12, 0x59, 0x4c, 0x7c, 0x01, 0x22, 0xbe, 0x9f,
+ 0xed, 0x3a, 0xcb, 0xf7, 0xdc, 0xed, 0xf5, 0x95, 0x87, 0x96, 0x44, 0x97,
+ 0x86, 0xc3, 0x59, 0x7f, 0xff, 0xe0, 0xc6, 0xb6, 0x47, 0xa0, 0x7b, 0x3e,
+ 0xd9, 0xbb, 0xd4, 0x9f, 0xa5, 0x97, 0x80, 0xfb, 0x8b, 0x2f, 0xdc, 0x28,
+ 0x9b, 0xeb, 0x28, 0x68, 0xd7, 0x21, 0xce, 0x3a, 0x7c, 0x7e, 0xee, 0x0a,
+ 0xa5, 0x96, 0x92, 0xca, 0x84, 0xd8, 0x72, 0x1e, 0xee, 0x79, 0xf1, 0xdb,
+ 0xc5, 0xdc, 0x2c, 0xbf, 0xff, 0xfe, 0xf6, 0x7f, 0x8f, 0x36, 0xc2, 0xce,
+ 0xa5, 0x81, 0x9c, 0xb0, 0x7e, 0x69, 0x96, 0x5f, 0xff, 0x37, 0x22, 0x5f,
+ 0xcf, 0x16, 0x7f, 0xcc, 0xb2, 0xe0, 0x9a, 0xb2, 0x99, 0x30, 0x2d, 0x0e,
+ 0x7a, 0x10, 0x3f, 0x4d, 0xbc, 0x7f, 0x3a, 0xcb, 0xff, 0x02, 0x6f, 0x30,
+ 0x09, 0xfa, 0x92, 0xca, 0x59, 0x6c, 0x73, 0xcb, 0xe2, 0x05, 0xef, 0x1b,
+ 0xf5, 0x97, 0xef, 0xff, 0xf8, 0x62, 0xca, 0x83, 0xc7, 0x61, 0xea, 0x84,
+ 0x7a, 0x1d, 0x9c, 0x0d, 0xb7, 0x8f, 0x1d, 0xac, 0xbb, 0x58, 0xb2, 0xf6,
+ 0x30, 0xd6, 0x5b, 0x8b, 0x2e, 0x2c, 0xec, 0xd6, 0x74, 0x37, 0x79, 0xb0,
+ 0x96, 0x5e, 0x68, 0x99, 0x65, 0xff, 0xd8, 0x0d, 0x9e, 0x6f, 0xf0, 0x9a,
+ 0x65, 0x97, 0xfe, 0x2c, 0xe6, 0xce, 0x00, 0xf9, 0xc5, 0x95, 0x3a, 0x3a,
+ 0x4e, 0x5b, 0xc1, 0xaf, 0x8e, 0x6f, 0x46, 0xad, 0xa1, 0x39, 0x58, 0x1d,
+ 0xc8, 0xca, 0xef, 0xfe, 0x20, 0x6d, 0xe7, 0x9a, 0x0e, 0xe3, 0x59, 0x7f,
+ 0x6b, 0x24, 0x50, 0x75, 0x97, 0xec, 0x91, 0x41, 0xd6, 0x5c, 0x40, 0xd8,
+ 0x7a, 0x5a, 0x2c, 0xbf, 0xff, 0xff, 0x4b, 0x9c, 0x0c, 0x7d, 0x87, 0x85,
+ 0x36, 0xc2, 0xcd, 0x41, 0x7f, 0xd9, 0xba, 0xb2, 0xff, 0xd1, 0x8d, 0xff,
+ 0x41, 0x47, 0x6b, 0x2f, 0xe3, 0xf5, 0x1e, 0xf4, 0x2c, 0xbd, 0xd4, 0xb9,
+ 0x39, 0xf5, 0x61, 0xe5, 0x62, 0x6a, 0x9d, 0x17, 0xea, 0x1e, 0x16, 0xe2,
+ 0xca, 0xc5, 0x46, 0x41, 0x8f, 0xac, 0x43, 0x6b, 0x4e, 0xb2, 0xfd, 0x3c,
+ 0x7f, 0x00, 0xb2, 0xfe, 0x1b, 0x94, 0x98, 0xeb, 0x2f, 0xda, 0xce, 0xa5,
+ 0xc5, 0x97, 0xbb, 0xf6, 0x2c, 0xb6, 0x4e, 0x78, 0xda, 0x29, 0xbf, 0xee,
+ 0xa3, 0x53, 0xec, 0xc6, 0x1a, 0xcb, 0xa6, 0x65, 0x95, 0x89, 0x93, 0xb0,
+ 0x93, 0x94, 0x13, 0x90, 0x4a, 0x37, 0x9e, 0x5f, 0x7b, 0x68, 0xef, 0x6d,
+ 0x65, 0xfd, 0x9d, 0x4a, 0x01, 0x0b, 0x2f, 0xc5, 0x9e, 0x7f, 0xac, 0xae,
+ 0x8f, 0x4c, 0xe5, 0xb7, 0xda, 0xc9, 0xa1, 0x65, 0xf3, 0x6f, 0xcd, 0x2c,
+ 0xad, 0xa9, 0x1c, 0xf0, 0xfe, 0xc4, 0x7e, 0x22, 0xbe, 0xd9, 0xdc, 0xe6,
+ 0x2c, 0xbf, 0x8b, 0x00, 0x78, 0x92, 0xcb, 0xf1, 0x67, 0xfc, 0xcb, 0x28,
+ 0x67, 0xa4, 0x61, 0x65, 0xfa, 0x7d, 0x81, 0x89, 0x96, 0x5f, 0xff, 0xf1,
+ 0x40, 0x3a, 0x97, 0x03, 0x1f, 0x2c, 0x1b, 0x66, 0xa6, 0x59, 0x50, 0x8b,
+ 0x57, 0x23, 0xf9, 0x65, 0x43, 0x69, 0xd5, 0x3c, 0x7f, 0x23, 0x28, 0xc9,
+ 0x58, 0x5d, 0x46, 0x86, 0xd1, 0xa1, 0xcc, 0x81, 0xa8, 0x49, 0xfa, 0x3c,
+ 0xd7, 0x8d, 0x08, 0x11, 0x9b, 0x14, 0x78, 0x9c, 0x94, 0xd9, 0xf8, 0xd7,
+ 0xc3, 0x19, 0xee, 0xf4, 0x01, 0x23, 0x2f, 0xbf, 0x49, 0xb5, 0x9d, 0x2c,
+ 0xbd, 0xcf, 0x62, 0xcb, 0xf6, 0x72, 0x7c, 0x31, 0x65, 0xff, 0xde, 0x08,
+ 0xfc, 0x1f, 0xf3, 0xc1, 0x99, 0x65, 0x74, 0x8b, 0x59, 0x8a, 0x3c, 0x38,
+ 0x45, 0x37, 0xff, 0x9b, 0x4d, 0x9d, 0x6c, 0xfc, 0xc5, 0x07, 0x59, 0x7f,
+ 0xf6, 0x3f, 0x5b, 0x07, 0x13, 0xec, 0x34, 0xd5, 0x95, 0xda, 0x26, 0x3a,
+ 0x4c, 0xbf, 0xa0, 0xe5, 0x93, 0xe2, 0xcb, 0xdf, 0xe7, 0xb0, 0xf4, 0x7c,
+ 0x4b, 0x7f, 0xfe, 0x3f, 0x52, 0xe6, 0xba, 0x8f, 0xf2, 0x3c, 0xdf, 0x59,
+ 0x7f, 0xd8, 0x69, 0x67, 0xfc, 0xc6, 0x2c, 0xbf, 0x61, 0x98, 0x33, 0xac,
+ 0xbf, 0xfd, 0x1d, 0x79, 0xb0, 0x86, 0xdb, 0xe0, 0x6b, 0x2a, 0x13, 0x36,
+ 0x63, 0x3d, 0x2c, 0x78, 0xe4, 0x8a, 0x2e, 0xdc, 0x1a, 0xcb, 0xff, 0xe9,
+ 0xf3, 0xb1, 0xf9, 0xb0, 0xdd, 0x86, 0x86, 0x16, 0x5f, 0xd9, 0xad, 0x67,
+ 0xf8, 0xb2, 0xfe, 0x27, 0x34, 0xef, 0x25, 0x97, 0xa4, 0xdf, 0xf1, 0xed,
+ 0x7c, 0xb6, 0xfd, 0x87, 0x2c, 0xe9, 0x65, 0xfd, 0xf6, 0xdf, 0x05, 0xda,
+ 0xca, 0xe1, 0xeb, 0x08, 0x4f, 0x77, 0xb1, 0x65, 0xfa, 0x0e, 0xde, 0x85,
+ 0x97, 0x88, 0x4f, 0x2c, 0xbf, 0xd9, 0xff, 0x37, 0xf3, 0xb5, 0x97, 0xd1,
+ 0x85, 0xda, 0xca, 0xd8, 0x8d, 0x09, 0x11, 0xe8, 0x59, 0xc9, 0x88, 0x77,
+ 0xe6, 0x74, 0x28, 0x54, 0xf2, 0xc3, 0x53, 0x42, 0xbf, 0xd1, 0xac, 0xdf,
+ 0xfa, 0x5c, 0xfb, 0xcf, 0xba, 0x59, 0xd2, 0xcb, 0xfb, 0xd1, 0x20, 0xb8,
+ 0x8b, 0x2f, 0xc3, 0xf6, 0x17, 0xd6, 0x54, 0x8f, 0x56, 0x62, 0xea, 0xe9,
+ 0x17, 0x65, 0x09, 0x8b, 0xfe, 0xd3, 0x61, 0x9f, 0xfb, 0x92, 0xcb, 0xba,
+ 0x35, 0x65, 0xcd, 0xd6, 0xc3, 0xd1, 0x19, 0xc5, 0xe6, 0x06, 0x2c, 0xb0,
+ 0x16, 0x5b, 0x92, 0x35, 0x9f, 0x1b, 0xbf, 0xfd, 0x86, 0x6e, 0xfb, 0x3f,
+ 0x80, 0x3b, 0xcc, 0xb2, 0xa1, 0x34, 0xad, 0x3c, 0xba, 0xe1, 0x13, 0xdf,
+ 0xf9, 0xf7, 0x96, 0x7f, 0x00, 0x43, 0x59, 0x60, 0x2c, 0xa6, 0x3c, 0xf9,
+ 0x8f, 0xaf, 0xfb, 0xd3, 0xb6, 0x17, 0x52, 0xe2, 0xcb, 0xfe, 0xeb, 0xd9,
+ 0xd9, 0x60, 0x77, 0x16, 0x5f, 0xff, 0x19, 0x9d, 0xf3, 0x3f, 0x36, 0x1a,
+ 0x58, 0x05, 0x96, 0x94, 0x23, 0x27, 0x0e, 0x98, 0xf6, 0xff, 0xc5, 0x01,
+ 0xef, 0xaf, 0xb6, 0x12, 0xcb, 0xf9, 0xba, 0x06, 0x9c, 0x6b, 0x2f, 0x66,
+ 0x80, 0xb2, 0xfd, 0xc6, 0xc2, 0x02, 0xcb, 0x63, 0x1e, 0x17, 0x07, 0x2f,
+ 0xcc, 0x00, 0x66, 0x96, 0x50, 0xd1, 0xf7, 0xe3, 0xe2, 0x70, 0xe1, 0x35,
+ 0xb6, 0xa5, 0x97, 0xe7, 0xc2, 0x63, 0x56, 0x5e, 0xfe, 0x79, 0x65, 0x11,
+ 0xe1, 0x6e, 0x93, 0x5c, 0xc7, 0x59, 0x7f, 0xff, 0xee, 0xa4, 0xfd, 0x6c,
+ 0x20, 0xee, 0xec, 0xce, 0xa5, 0x81, 0x20, 0x71, 0x65, 0x1d, 0x11, 0x9b,
+ 0xa2, 0xd7, 0xfc, 0x28, 0xff, 0xd8, 0xba, 0x97, 0x16, 0x5f, 0x6e, 0x7b,
+ 0x37, 0x16, 0x5e, 0xdb, 0x61, 0x5a, 0xca, 0xd8, 0x9f, 0x98, 0xa0, 0xf2,
+ 0x75, 0x8c, 0x85, 0x81, 0xa4, 0xce, 0x7d, 0xb6, 0x51, 0x7f, 0xff, 0xfd,
+ 0xd7, 0x03, 0x1d, 0x6c, 0xf6, 0x0f, 0x61, 0x60, 0x4d, 0xd9, 0xc0, 0x01,
+ 0xbe, 0xb2, 0xff, 0xff, 0xd8, 0x33, 0x9e, 0x3f, 0xcc, 0xff, 0x34, 0xd9,
+ 0xd9, 0x60, 0xd6, 0x5f, 0xfe, 0xf8, 0x63, 0x27, 0xd9, 0xc6, 0x26, 0xd2,
+ 0xcb, 0x18, 0x48, 0xb6, 0x11, 0xae, 0xa1, 0x36, 0x7c, 0x8c, 0xf6, 0xfd,
+ 0x05, 0xd3, 0xce, 0xb2, 0xfe, 0x99, 0x87, 0x87, 0x65, 0x97, 0xff, 0xff,
+ 0xfd, 0xdc, 0x7a, 0x0f, 0xfc, 0xe7, 0x23, 0x5a, 0x82, 0xc9, 0xf0, 0x3c,
+ 0x0c, 0xc5, 0x07, 0x59, 0x50, 0x8c, 0x1c, 0x2d, 0xbc, 0x1d, 0x1a, 0xb2,
+ 0x8e, 0x6f, 0xf6, 0xc8, 0x6f, 0xce, 0x01, 0x1e, 0x75, 0x97, 0xff, 0xff,
+ 0x4f, 0xb3, 0xf3, 0xb6, 0x6a, 0x7d, 0x93, 0x49, 0xbd, 0x83, 0xeb, 0x37,
+ 0x56, 0x56, 0x23, 0x2d, 0x89, 0x02, 0x53, 0x79, 0x81, 0x0b, 0x2f, 0xf6,
+ 0xc2, 0xcd, 0x34, 0x1d, 0x65, 0xff, 0xb4, 0xff, 0xd6, 0x37, 0xa0, 0x6b,
+ 0x2f, 0xe1, 0x96, 0x79, 0xfe, 0xb2, 0xfd, 0xfe, 0xa4, 0xda, 0x59, 0x58,
+ 0x7a, 0xbc, 0x2c, 0xa9, 0xd3, 0x01, 0x18, 0xde, 0x8c, 0xc1, 0x09, 0x2b,
+ 0xda, 0x71, 0x16, 0x5f, 0xa3, 0xe7, 0x6f, 0xac, 0xa7, 0x3c, 0x40, 0x8e,
+ 0xdf, 0x17, 0x58, 0x75, 0x95, 0x39, 0xe1, 0x98, 0x43, 0x7f, 0xe8, 0x37,
+ 0x74, 0x38, 0x53, 0x08, 0x75, 0x97, 0xfc, 0x66, 0x68, 0x6d, 0x9f, 0xe2,
+ 0xcb, 0xfc, 0x0e, 0x66, 0xce, 0xfe, 0x75, 0x97, 0xff, 0xff, 0xf8, 0xd2,
+ 0xcd, 0x8d, 0x84, 0xff, 0xf4, 0x4d, 0xb0, 0xb3, 0xcd, 0xfe, 0x07, 0xb0,
+ 0xc2, 0xca, 0xc4, 0xda, 0x7a, 0x24, 0x64, 0x47, 0x39, 0x09, 0xbd, 0xff,
+ 0xe7, 0x37, 0x08, 0x3f, 0xf6, 0x6f, 0x1c, 0x2c, 0xbf, 0xfb, 0x3f, 0x8d,
+ 0x3e, 0x76, 0xd3, 0x71, 0x65, 0xff, 0xb3, 0x01, 0xcd, 0x9a, 0xe0, 0xf8,
+ 0xb2, 0xff, 0x6b, 0x3b, 0xf3, 0x6a, 0x65, 0x95, 0xb1, 0x17, 0x63, 0x45,
+ 0xc4, 0x1b, 0xff, 0xef, 0x36, 0xcc, 0x9b, 0xa9, 0x73, 0xfe, 0xce, 0x96,
+ 0x51, 0x27, 0x19, 0xf8, 0xc1, 0xb7, 0x98, 0xdf, 0x7f, 0x41, 0x3a, 0xcb,
+ 0xff, 0xfd, 0x87, 0x3b, 0x75, 0xb0, 0xd3, 0x70, 0xbe, 0x68, 0x63, 0x4b,
+ 0x2e, 0xce, 0xd9, 0x11, 0x3a, 0x23, 0xbe, 0xe8, 0xb3, 0x6d, 0x65, 0x62,
+ 0x62, 0x8d, 0x0c, 0x17, 0x2e, 0xbf, 0x61, 0xe4, 0x4c, 0xb2, 0xf3, 0x17,
+ 0xd6, 0x5f, 0xd2, 0xe3, 0x9c, 0x3c, 0x59, 0x53, 0x9e, 0x4b, 0x8d, 0xdf,
+ 0x7b, 0xcf, 0x25, 0x96, 0xe2, 0xca, 0xc3, 0x66, 0xc4, 0x57, 0xf7, 0xdb,
+ 0x53, 0xe7, 0x6b, 0x2a, 0x1b, 0x78, 0xd1, 0xca, 0x5d, 0xc9, 0x58, 0x26,
+ 0xca, 0x53, 0xee, 0x11, 0x5d, 0x43, 0xad, 0xa5, 0x90, 0xea, 0x3d, 0xa3,
+ 0x94, 0x7a, 0x3f, 0x37, 0x8c, 0xbc, 0xa5, 0x1a, 0x72, 0x57, 0x4f, 0xcc,
+ 0xc2, 0xdf, 0xb6, 0xab, 0xba, 0x3f, 0x7f, 0x89, 0xcd, 0xcc, 0x23, 0x56,
+ 0x5d, 0xde, 0x2c, 0xa3, 0x9e, 0x4b, 0x99, 0x52, 0xcb, 0xff, 0xb6, 0x64,
+ 0xdd, 0x4b, 0x9f, 0xf6, 0x74, 0xb2, 0xfb, 0x77, 0xcd, 0xa5, 0x97, 0xfa,
+ 0x50, 0x3d, 0x83, 0x69, 0x96, 0x5f, 0xf6, 0xcf, 0x96, 0x19, 0x8d, 0xc5,
+ 0x97, 0xff, 0xfe, 0xfb, 0xcc, 0x59, 0x3b, 0xec, 0x2e, 0xb0, 0xc2, 0xc0,
+ 0xe1, 0xab, 0x2b, 0x6b, 0x4d, 0x66, 0x70, 0xbe, 0xd2, 0xba, 0x25, 0x98,
+ 0xdb, 0x74, 0xea, 0xf7, 0xa0, 0x0b, 0x2f, 0xf7, 0x98, 0x11, 0xf6, 0xde,
+ 0xb2, 0xfe, 0x66, 0x83, 0x22, 0x65, 0x97, 0xdf, 0x72, 0x02, 0xcb, 0xff,
+ 0xf3, 0x9a, 0x68, 0x1e, 0x6d, 0xd2, 0x83, 0x3a, 0x97, 0x16, 0x58, 0x47,
+ 0x3f, 0xe2, 0x21, 0xbe, 0x7d, 0xc8, 0x02, 0xca, 0x14, 0x2b, 0x24, 0x88,
+ 0xde, 0xb1, 0x93, 0xb1, 0xc9, 0x8d, 0x1e, 0x15, 0x66, 0x13, 0xde, 0xe7,
+ 0xd9, 0x65, 0x2c, 0xbf, 0xb0, 0xf1, 0xe7, 0xf2, 0xcb, 0x69, 0x65, 0x2c,
+ 0xb6, 0xcc, 0x2f, 0x26, 0x11, 0xbd, 0xe6, 0x35, 0x65, 0x6c, 0x44, 0x68,
+ 0xd2, 0x0d, 0x28, 0xbf, 0xfe, 0xea, 0x45, 0x1b, 0x0e, 0x50, 0x6f, 0xda,
+ 0x75, 0x97, 0xff, 0x6c, 0xfe, 0xb0, 0xcc, 0x9c, 0xb0, 0xc5, 0x95, 0xb1,
+ 0x38, 0x28, 0x1c, 0xc8, 0x4c, 0x31, 0x9f, 0xd4, 0xef, 0xda, 0xd8, 0x5b,
+ 0xcc, 0x59, 0x6e, 0x2c, 0xbc, 0xe0, 0x85, 0x94, 0x73, 0x59, 0xe1, 0x1b,
+ 0xcf, 0x34, 0x2c, 0xbd, 0xec, 0xd2, 0xca, 0x84, 0x59, 0x3a, 0xc9, 0x84,
+ 0x3b, 0xa3, 0x97, 0xf4, 0xf3, 0x48, 0x51, 0xa9, 0xd6, 0x5f, 0x08, 0x59,
+ 0xbd, 0x65, 0xf3, 0x0f, 0x06, 0xb2, 0xba, 0x3c, 0x53, 0x92, 0x5a, 0x65,
+ 0x97, 0x41, 0xd6, 0x5b, 0xeb, 0x2b, 0x46, 0x9d, 0xc5, 0xa8, 0x67, 0xb3,
+ 0xe3, 0x9b, 0xe8, 0x1b, 0xc9, 0x65, 0xef, 0xe7, 0x16, 0x5f, 0xfb, 0x1f,
+ 0xa0, 0x4d, 0x28, 0xd4, 0xeb, 0x2f, 0x6a, 0x26, 0x59, 0x70, 0x4c, 0x59,
+ 0x73, 0xf4, 0xb2, 0xb0, 0xd7, 0xf0, 0x62, 0xa7, 0x47, 0x51, 0xa4, 0x3e,
+ 0x1c, 0x74, 0x1f, 0xa6, 0x5f, 0x49, 0xcb, 0x6d, 0x65, 0xd3, 0x3a, 0xcb,
+ 0xa5, 0x3a, 0xcb, 0xed, 0x9f, 0x89, 0x2c, 0xbf, 0xfe, 0xc8, 0x20, 0x43,
+ 0x7f, 0xd8, 0x7c, 0x1a, 0xcb, 0xc2, 0x06, 0x75, 0x97, 0x41, 0xab, 0x2a,
+ 0x74, 0x53, 0x48, 0x90, 0xd4, 0xcf, 0x8f, 0xdf, 0xce, 0x64, 0x7f, 0x27,
+ 0x59, 0x7f, 0x36, 0xba, 0x91, 0x42, 0xcb, 0xf4, 0x7e, 0x4d, 0xf5, 0x97,
+ 0xf7, 0xa3, 0xa9, 0x67, 0xd6, 0x54, 0x8f, 0x54, 0x64, 0xf5, 0xe4, 0x52,
+ 0x7e, 0x10, 0x57, 0xfd, 0x3e, 0xb2, 0x69, 0x31, 0x1a, 0xb2, 0xff, 0xa0,
+ 0xbf, 0xa6, 0xdf, 0x83, 0x59, 0x4e, 0x7e, 0x9b, 0x67, 0x77, 0x67, 0xd6,
+ 0x5a, 0x65, 0x95, 0xe3, 0x50, 0x42, 0xd5, 0xb5, 0xae, 0xb0, 0x43, 0xde,
+ 0x3e, 0x34, 0x61, 0x93, 0x25, 0x9c, 0x93, 0xc2, 0xef, 0x0b, 0xe2, 0x3f,
+ 0x0c, 0x34, 0xb6, 0xe1, 0x38, 0x22, 0x65, 0xfe, 0x33, 0x24, 0x41, 0x7e,
+ 0x2c, 0xbf, 0x74, 0x63, 0x90, 0x16, 0x5c, 0x46, 0xac, 0xb7, 0x18, 0xf0,
+ 0x02, 0x53, 0x73, 0xf9, 0x65, 0xff, 0x8f, 0x06, 0xff, 0xd9, 0xf8, 0x02,
+ 0xcb, 0xf3, 0x8e, 0x30, 0x96, 0x58, 0xd5, 0x95, 0x3a, 0x23, 0x18, 0x5b,
+ 0xc7, 0xe4, 0x4b, 0x7f, 0xfe, 0x39, 0x67, 0x7d, 0x7c, 0x9f, 0xc7, 0x8c,
+ 0xfa, 0xcb, 0xff, 0xec, 0x9d, 0xcb, 0xbd, 0x9c, 0x83, 0xbf, 0x5f, 0x59,
+ 0x50, 0x8a, 0x8d, 0x2a, 0xdf, 0xed, 0xcf, 0x64, 0xfa, 0xd4, 0x2c, 0xa5,
+ 0x97, 0xff, 0x3c, 0xb0, 0x86, 0x51, 0x21, 0xf1, 0x65, 0xb3, 0x0f, 0x37,
+ 0x78, 0x5d, 0xdc, 0xda, 0x96, 0x5f, 0xfe, 0x2c, 0x3c, 0x77, 0xb0, 0x49,
+ 0xe7, 0x7e, 0x96, 0x5f, 0xc1, 0x39, 0xde, 0x5b, 0x3e, 0x7d, 0x9b, 0xa3,
+ 0x97, 0xe0, 0xc8, 0x4d, 0x71, 0x65, 0x9b, 0xc7, 0xe8, 0x49, 0x57, 0xff,
+ 0xe8, 0xd4, 0x77, 0x87, 0x8e, 0xe4, 0xdc, 0x09, 0xd6, 0x54, 0x2e, 0x1a,
+ 0x4c, 0xe7, 0xa8, 0x59, 0xfa, 0x1c, 0x8e, 0x44, 0x50, 0x84, 0xfc, 0x61,
+ 0x1b, 0x64, 0xd7, 0xf6, 0xb2, 0x0d, 0x82, 0x59, 0x73, 0xf9, 0x65, 0xe2,
+ 0x73, 0xac, 0xbf, 0xff, 0xfb, 0x37, 0x66, 0x8f, 0x67, 0xca, 0x26, 0xd9,
+ 0x85, 0x9d, 0x49, 0xb8, 0xb2, 0xff, 0xfe, 0xf3, 0xcc, 0x70, 0x93, 0x9b,
+ 0xcc, 0xef, 0xc1, 0xdc, 0x59, 0x74, 0x7c, 0x08, 0xd7, 0xe3, 0xb5, 0xc0,
+ 0x85, 0x97, 0x67, 0x16, 0x5f, 0xf8, 0xf9, 0xd4, 0xb8, 0xf1, 0xd4, 0x96,
+ 0x57, 0x67, 0xad, 0xe1, 0x6b, 0x84, 0x9d, 0x65, 0x31, 0xbc, 0x22, 0x3a,
+ 0x92, 0xa2, 0x9c, 0x2c, 0x61, 0x6f, 0x43, 0xc8, 0x8b, 0xbf, 0x0a, 0x8a,
+ 0xda, 0xe3, 0x1c, 0x97, 0xda, 0xa1, 0x7a, 0x29, 0x94, 0x19, 0xb4, 0x43,
+ 0xc4, 0x51, 0x2d, 0x13, 0x69, 0x42, 0x9c, 0x54, 0x3e, 0x15, 0x50, 0x8f,
+ 0xda, 0x70, 0x93, 0x8a, 0x55, 0xd4, 0xf3, 0x88, 0x92, 0x97, 0x76, 0x3a,
+ 0x64, 0x66, 0x5a, 0x20, 0xd3, 0x67, 0x33, 0xbb, 0xa6, 0xee, 0xf5, 0x49,
+ 0xb6, 0x69, 0xfc, 0xe9, 0xa9, 0x00, 0x1a, 0xa6, 0xaf, 0x1e, 0x7e, 0x4f,
+ 0xd6, 0x8d, 0x21, 0xe7, 0xe6, 0x41, 0x3b, 0xb4, 0x2b, 0x86, 0x69, 0x57,
+ 0x56, 0x7c, 0xad, 0x89, 0xbf, 0x5c, 0xbe, 0x86, 0x72, 0x8b, 0x7c, 0x7e,
+ 0xe6, 0x46, 0x03, 0xb7, 0x3b, 0x3e, 0x24, 0xe7, 0xb6, 0xec, 0xab, 0x3b,
+ 0xff, 0xf8, 0x3d, 0x8b, 0xeb, 0xfa, 0x8c, 0xe8, 0x50, 0x37, 0x73, 0x56,
+ 0x50, 0xb5, 0x6c, 0xad, 0x2c, 0x02, 0xfe, 0x76, 0xff, 0x18, 0x96, 0x5e,
+ 0x6d, 0x62, 0xca, 0xdc, 0x3c, 0x6e, 0x15, 0xdf, 0xb5, 0xdb, 0xbf, 0x6a,
+ 0x8a, 0x75, 0x76, 0x74, 0xb2, 0xfb, 0xfa, 0x6e, 0x96, 0x5f, 0xfe, 0x08,
+ 0x49, 0x8a, 0x3c, 0xc7, 0xce, 0x2c, 0xbb, 0x47, 0x59, 0x61, 0x70, 0x8f,
+ 0x3c, 0x25, 0xe8, 0xd9, 0x85, 0xce, 0x46, 0x04, 0x7b, 0xff, 0xf4, 0x85,
+ 0xe4, 0xbd, 0x8d, 0x2e, 0x47, 0xe0, 0x6b, 0x2f, 0x66, 0x71, 0x65, 0xfc,
+ 0xf3, 0xff, 0x8e, 0x05, 0x97, 0x68, 0x5f, 0x8f, 0x27, 0x6c, 0x6e, 0xa1,
+ 0x1a, 0x4d, 0x09, 0xfb, 0xf6, 0xbb, 0x77, 0xed, 0x51, 0x51, 0xaf, 0xfc,
+ 0xf2, 0x17, 0x9a, 0xed, 0xdf, 0xb5, 0x44, 0xd0, 0xbf, 0xfc, 0x59, 0x34,
+ 0x9f, 0x52, 0x2c, 0xde, 0xeb, 0x2f, 0x8a, 0x33, 0xa5, 0x95, 0x88, 0xef,
+ 0x39, 0xb7, 0x13, 0xbe, 0x95, 0x7f, 0x84, 0x7d, 0xe2, 0xfe, 0xd3, 0xac,
+ 0xa1, 0x67, 0xeb, 0x07, 0x97, 0xe9, 0xc4, 0x9e, 0x27, 0x59, 0x7d, 0xdb,
+ 0xbf, 0x6a, 0x8a, 0xbd, 0x58, 0x7b, 0x9a, 0x2c, 0xbf, 0xfd, 0xe6, 0xff,
+ 0x22, 0x5e, 0x83, 0x1c, 0x96, 0x5f, 0xfd, 0xf0, 0x60, 0xfd, 0x83, 0x1b,
+ 0x74, 0xb2, 0xfb, 0xfa, 0x6e, 0x96, 0x5f, 0xb7, 0xc1, 0x78, 0x2b, 0x2f,
+ 0xfc, 0xfd, 0x4b, 0x99, 0xd8, 0xf3, 0xa5, 0x95, 0x87, 0xd4, 0xe5, 0x37,
+ 0xf3, 0x0c, 0x71, 0xa8, 0x59, 0x7e, 0xe1, 0x3c, 0x71, 0x65, 0xff, 0xff,
+ 0xb0, 0x98, 0x67, 0x77, 0x2e, 0xc7, 0xe8, 0xc1, 0xb1, 0x4e, 0xb2, 0xa1,
+ 0x11, 0xf2, 0x26, 0xbf, 0xf9, 0xfd, 0x33, 0xff, 0xfd, 0x76, 0xc4, 0xb2,
+ 0xff, 0xfc, 0x02, 0x09, 0xc4, 0x18, 0xe0, 0x07, 0x8c, 0xfa, 0xcb, 0xf9,
+ 0xff, 0xcc, 0xeb, 0xeb, 0x2b, 0xa4, 0x42, 0x12, 0xb5, 0x85, 0xe2, 0xb2,
+ 0x6e, 0xc8, 0x7a, 0x49, 0x64, 0x5d, 0x42, 0x37, 0xc4, 0x1f, 0x85, 0xd9,
+ 0x84, 0x42, 0x43, 0x2a, 0xfd, 0xae, 0xdd, 0xfb, 0x54, 0x56, 0xcb, 0xfe,
+ 0x90, 0xbc, 0xd7, 0x6e, 0xfd, 0xaa, 0x24, 0x15, 0xf6, 0x1e, 0x37, 0x16,
+ 0x58, 0x5e, 0x22, 0x8d, 0xcd, 0xb8, 0x93, 0x7c, 0x76, 0x28, 0x59, 0x7e,
+ 0xd7, 0x6e, 0xfd, 0xaa, 0x24, 0x35, 0xfd, 0xa0, 0xef, 0x83, 0x0e, 0xb2,
+ 0xfe, 0x2c, 0xe7, 0xe5, 0x0b, 0x2f, 0x85, 0xbc, 0x85, 0xc2, 0x2c, 0xf0,
+ 0x81, 0x8d, 0xb7, 0x98, 0xdf, 0xec, 0xfb, 0x0f, 0x0a, 0x65, 0x97, 0xf9,
+ 0xcd, 0x16, 0x69, 0xb9, 0xb8, 0xb2, 0xdc, 0x16, 0x7d, 0xa4, 0x65, 0x79,
+ 0xdf, 0xb5, 0xc6, 0x06, 0xa8, 0x3d, 0x2e, 0xca, 0x6d, 0xda, 0xcb, 0x6e,
+ 0x2c, 0xac, 0x34, 0xde, 0x12, 0xb8, 0xcf, 0xac, 0xbd, 0xc6, 0x35, 0x65,
+ 0x0c, 0xda, 0xf4, 0x31, 0x76, 0xd1, 0x3a, 0xcb, 0xfe, 0xf4, 0x7f, 0x9b,
+ 0x57, 0x36, 0x82, 0x59, 0x5b, 0x59, 0xf0, 0x48, 0x76, 0xfb, 0xff, 0xcd,
+ 0xd5, 0x96, 0x25, 0x96, 0x65, 0x95, 0xb5, 0x1a, 0x01, 0x56, 0x21, 0x7f,
+ 0xf8, 0x55, 0x8a, 0xbd, 0xab, 0xd0, 0x72, 0x7f, 0x36, 0x96, 0x5b, 0xa5,
+ 0x97, 0xbf, 0x80, 0x59, 0x73, 0x12, 0xcb, 0xc1, 0xfe, 0x2c, 0xba, 0x26,
+ 0x59, 0x7f, 0x1f, 0x3b, 0x27, 0xdc, 0x59, 0x7b, 0x1a, 0x75, 0x96, 0x11,
+ 0x65, 0x61, 0xef, 0x68, 0xc0, 0x23, 0x97, 0xe1, 0xc7, 0xdc, 0x6b, 0x2e,
+ 0x6d, 0xeb, 0x2a, 0x0d, 0xff, 0xc9, 0xef, 0x7b, 0x38, 0xb2, 0xce, 0xb2,
+ 0x86, 0x6b, 0x3e, 0x39, 0x43, 0x4e, 0xbb, 0x70, 0x4a, 0x61, 0xcd, 0x0a,
+ 0xf8, 0x73, 0x8e, 0xbf, 0x6d, 0x11, 0x32, 0xfb, 0xfc, 0x6d, 0xeb, 0x2c,
+ 0x4b, 0x2f, 0xc3, 0x82, 0x9f, 0x71, 0x65, 0xfe, 0x83, 0x44, 0x00, 0x23,
+ 0xa5, 0x95, 0x07, 0xc3, 0x39, 0x5d, 0xf9, 0xfc, 0xc7, 0xc5, 0x95, 0x88,
+ 0xb9, 0x27, 0x1d, 0xe4, 0x57, 0xf6, 0x77, 0xe8, 0x89, 0x96, 0x5b, 0x6d,
+ 0x65, 0x31, 0xf9, 0x78, 0xc0, 0x25, 0xd7, 0x88, 0x1c, 0x59, 0x7e, 0x79,
+ 0xc4, 0xc9, 0x96, 0x56, 0x1e, 0x31, 0x0e, 0x5e, 0xec, 0xb7, 0x16, 0x5f,
+ 0xf9, 0xcc, 0xf3, 0x3c, 0xbe, 0xd3, 0xac, 0xa7, 0x3d, 0xf2, 0x20, 0xbf,
+ 0xf0, 0x33, 0xae, 0x09, 0xa6, 0x3e, 0x2c, 0xb9, 0xa6, 0x59, 0x6c, 0xe8,
+ 0xf5, 0xf4, 0x81, 0x7d, 0x3f, 0x3a, 0x65, 0x97, 0xff, 0xa3, 0xa9, 0x31,
+ 0xcc, 0xc2, 0x1f, 0xa1, 0x65, 0x62, 0x71, 0x9a, 0x7f, 0x27, 0x7e, 0x14,
+ 0x04, 0x92, 0xfc, 0xe3, 0x12, 0x09, 0x65, 0xfe, 0x60, 0xee, 0x7a, 0x32,
+ 0x75, 0x97, 0xfe, 0xd7, 0xc4, 0x27, 0xef, 0x0b, 0xb5, 0x97, 0xd0, 0x76,
+ 0xdb, 0x59, 0x74, 0x6e, 0xac, 0xbf, 0xf1, 0x8f, 0x2d, 0x63, 0x7a, 0x06,
+ 0xb2, 0xfb, 0xb7, 0x7e, 0xd5, 0x16, 0x22, 0xfd, 0xad, 0x39, 0x7d, 0x65,
+ 0xfd, 0xaf, 0x3f, 0x30, 0x45, 0x97, 0x87, 0xe0, 0xac, 0xa6, 0x3c, 0xb7,
+ 0x2e, 0xb1, 0x8b, 0x2e, 0xe3, 0x2c, 0xa6, 0x35, 0x00, 0x12, 0xbf, 0xf4,
+ 0xb3, 0x9f, 0xf6, 0x36, 0xa4, 0xb2, 0x98, 0xf7, 0x82, 0x41, 0x7f, 0x44,
+ 0x74, 0x77, 0x1a, 0xcb, 0xc1, 0x29, 0x2c, 0xbf, 0xdd, 0xc6, 0x68, 0x00,
+ 0xfa, 0xca, 0x9d, 0x57, 0xf4, 0x89, 0xf0, 0xdb, 0xb4, 0x0e, 0x89, 0x18,
+ 0x67, 0x47, 0xc7, 0x30, 0xf3, 0x91, 0x42, 0x9b, 0x84, 0x3f, 0x2d, 0x08,
+ 0xe5, 0xf6, 0xa0, 0x8d, 0x59, 0x7a, 0x51, 0xb8, 0xb2, 0xb0, 0xf0, 0x66,
+ 0x22, 0xb3, 0x2c, 0xb3, 0x2c, 0xb4, 0x8d, 0x34, 0x00, 0x10, 0xbf, 0x09,
+ 0xb7, 0x9a, 0x85, 0x97, 0x07, 0x4b, 0x2f, 0xbf, 0x05, 0x3a, 0xca, 0x98,
+ 0xdc, 0xfc, 0x5e, 0xc4, 0xb2, 0xe8, 0x25, 0x97, 0xf4, 0x70, 0x49, 0xe2,
+ 0x75, 0x94, 0x47, 0xab, 0xc1, 0x01, 0x05, 0x6f, 0xb7, 0x3c, 0x1d, 0xc5,
+ 0x95, 0x09, 0x99, 0xe3, 0x23, 0x3b, 0x84, 0xbe, 0xff, 0x83, 0x39, 0x60,
+ 0xfc, 0x13, 0x56, 0x51, 0xa9, 0xe8, 0xfa, 0x35, 0xb2, 0x3b, 0xbe, 0xf7,
+ 0x03, 0x0b, 0x2f, 0xff, 0x67, 0x5d, 0x01, 0xff, 0xc6, 0x2e, 0xa4, 0xb2,
+ 0xff, 0xe8, 0xce, 0x61, 0x0d, 0x81, 0x04, 0xb2, 0xf1, 0x44, 0xeb, 0x29,
+ 0x91, 0x50, 0x49, 0x81, 0x40, 0xbe, 0x8d, 0x41, 0xd6, 0x54, 0x26, 0x33,
+ 0x28, 0x65, 0x70, 0xba, 0xf8, 0x62, 0x6d, 0x52, 0x59, 0x7e, 0x07, 0x7e,
+ 0x61, 0x5a, 0xcb, 0xde, 0xc0, 0x2c, 0xbf, 0xba, 0xe7, 0xa1, 0xbe, 0xb2,
+ 0xe7, 0xfa, 0xca, 0x63, 0xc4, 0x39, 0x75, 0xef, 0x40, 0x16, 0x5c, 0x1d,
+ 0xb5, 0x97, 0xcc, 0x51, 0x3a, 0xcb, 0xff, 0xef, 0xe7, 0x52, 0x20, 0xfd,
+ 0xd8, 0xa0, 0x6b, 0x2f, 0xe3, 0x96, 0x46, 0xe4, 0xcb, 0x2c, 0x05, 0x95,
+ 0x07, 0x82, 0xc6, 0x17, 0x9e, 0x3a, 0x59, 0x5b, 0x42, 0x7f, 0x38, 0x53,
+ 0xd9, 0x6e, 0x98, 0x3c, 0x42, 0x43, 0x9c, 0x1a, 0xf9, 0x0e, 0xdc, 0x23,
+ 0xf7, 0x48, 0x2f, 0x3f, 0xf8, 0xb2, 0xff, 0xfb, 0x52, 0x39, 0x46, 0xa0,
+ 0x79, 0x34, 0x79, 0x65, 0x31, 0xf5, 0xb8, 0xe5, 0xf6, 0x76, 0xfc, 0x59,
+ 0x7d, 0xbc, 0x2f, 0xc5, 0x96, 0x65, 0x97, 0xfd, 0x1f, 0xe7, 0x3f, 0x1d,
+ 0x18, 0xb2, 0xfc, 0xda, 0x63, 0x05, 0x6b, 0x2d, 0xd2, 0xca, 0x92, 0x3b,
+ 0xf0, 0x81, 0x88, 0xa6, 0x24, 0xd0, 0x87, 0x8e, 0xc4, 0x2c, 0xbf, 0xf3,
+ 0x7b, 0xa9, 0x67, 0xf3, 0xaf, 0xac, 0xbf, 0xde, 0xc3, 0xe3, 0xea, 0x75,
+ 0x95, 0x23, 0xf3, 0x1a, 0x05, 0xfb, 0xff, 0x79, 0x71, 0x65, 0xec, 0xd4,
+ 0x2c, 0xbc, 0x58, 0x75, 0x9b, 0x65, 0xdd, 0xff, 0x83, 0x9d, 0x0f, 0x7f,
+ 0xb1, 0xe6, 0x59, 0x5d, 0x22, 0xca, 0x64, 0x3d, 0xe5, 0xb6, 0x92, 0xcb,
+ 0xdd, 0x71, 0xd6, 0x5f, 0x66, 0x19, 0xc5, 0x95, 0x07, 0xa1, 0x82, 0x3f,
+ 0x1d, 0xb6, 0xf5, 0x97, 0x04, 0x96, 0x58, 0x56, 0xb2, 0xdb, 0xd6, 0x54,
+ 0x27, 0xad, 0x90, 0xd4, 0xd4, 0x21, 0x00, 0x5b, 0xc1, 0x3f, 0x8b, 0x6f,
+ 0x15, 0xbf, 0xbb, 0x8f, 0xfb, 0x00, 0xb2, 0xfe, 0x13, 0x35, 0x99, 0x32,
+ 0xca, 0x23, 0xdc, 0xe1, 0x75, 0xfb, 0xae, 0x46, 0xb8, 0xb2, 0xff, 0x9f,
+ 0xfc, 0x18, 0x5f, 0x52, 0x59, 0x7f, 0xa7, 0xea, 0x5c, 0x26, 0x99, 0x65,
+ 0xf7, 0xc8, 0x33, 0xac, 0xa8, 0x3d, 0x92, 0x36, 0xa8, 0x47, 0xe6, 0x10,
+ 0x91, 0x48, 0x61, 0x25, 0x7f, 0x6a, 0x40, 0xcc, 0x99, 0x65, 0xc1, 0x11,
+ 0x65, 0xf3, 0xc3, 0x6d, 0xac, 0xbf, 0x87, 0xe6, 0xdf, 0x04, 0xb2, 0xee,
+ 0x4c, 0xb2, 0xf6, 0x84, 0xe2, 0xca, 0xc4, 0x66, 0x9a, 0x5d, 0xa1, 0x82,
+ 0x23, 0xf9, 0x76, 0xf1, 0x8b, 0xfe, 0xe1, 0xba, 0x81, 0xfa, 0x37, 0xac,
+ 0xbe, 0x90, 0x9e, 0x85, 0x97, 0xb5, 0x12, 0x59, 0x4e, 0x6f, 0xf7, 0x91,
+ 0xdf, 0x8f, 0x8d, 0xa9, 0x96, 0x5b, 0x71, 0x65, 0x41, 0xbc, 0x72, 0x8b,
+ 0xe1, 0x23, 0x77, 0x8b, 0x2f, 0xfc, 0x44, 0xe7, 0xe6, 0x1e, 0x37, 0x16,
+ 0x5f, 0xf9, 0xa7, 0x72, 0xf3, 0xf2, 0x37, 0x16, 0x5e, 0xf4, 0x79, 0x65,
+ 0x2c, 0xb6, 0x0c, 0xd3, 0x9c, 0x72, 0xfb, 0x4c, 0x66, 0xe2, 0xca, 0x64,
+ 0x79, 0x78, 0xfc, 0x99, 0xf8, 0x4d, 0x7f, 0xfb, 0x4c, 0x78, 0xeb, 0xd0,
+ 0x32, 0x7d, 0xc5, 0x94, 0x34, 0xe7, 0xf9, 0x18, 0xc7, 0xce, 0xef, 0xbb,
+ 0xf4, 0x69, 0x65, 0xe6, 0xcd, 0x2c, 0xae, 0x8d, 0xf0, 0x84, 0x77, 0xf8,
+ 0x01, 0x71, 0x3d, 0x12, 0x59, 0x50, 0xae, 0xef, 0x16, 0x19, 0xef, 0xcb,
+ 0xcf, 0x1d, 0xf0, 0x5d, 0x4c, 0x23, 0xba, 0x24, 0xb2, 0xfd, 0xdf, 0xa3,
+ 0xad, 0xd5, 0x94, 0x33, 0xc3, 0xe8, 0x5a, 0xc3, 0x59, 0x7e, 0x27, 0x3c,
+ 0x79, 0x65, 0x61, 0xb7, 0x61, 0x1b, 0xff, 0xd0, 0x78, 0x90, 0xca, 0x3c,
+ 0xf9, 0xa5, 0x97, 0x37, 0x96, 0x52, 0xca, 0x91, 0xf4, 0x7d, 0x1f, 0x6c,
+ 0x5a, 0xfc, 0x51, 0xe8, 0xdc, 0x59, 0x7b, 0xf8, 0x05, 0x97, 0xf1, 0xdb,
+ 0x9c, 0x61, 0xac, 0xbc, 0xfa, 0x35, 0x65, 0x04, 0xf2, 0x8c, 0x2d, 0xbf,
+ 0x8b, 0x37, 0x96, 0x71, 0x65, 0xcd, 0xa5, 0x95, 0xd9, 0xe1, 0xf8, 0xb6,
+ 0xff, 0x6e, 0x6c, 0x12, 0x09, 0xcd, 0x59, 0x7f, 0xa4, 0xf8, 0x59, 0xfe,
+ 0x2c, 0xbf, 0x87, 0x98, 0x5d, 0x7d, 0x65, 0x62, 0x25, 0xfa, 0x39, 0x01,
+ 0x8d, 0xf0, 0xe1, 0xf4, 0xb2, 0xff, 0xd9, 0xd4, 0xbd, 0x1c, 0x37, 0xd0,
+ 0xb2, 0xa1, 0x5a, 0x9c, 0x96, 0xba, 0x84, 0x3b, 0x19, 0x4c, 0x53, 0xa6,
+ 0x6f, 0x33, 0x14, 0x2e, 0xb8, 0x61, 0xba, 0x43, 0x7d, 0xf7, 0x79, 0xd6,
+ 0x5b, 0x6d, 0x65, 0xd2, 0xe2, 0xcb, 0x3c, 0x8d, 0x5f, 0x42, 0x97, 0xdf,
+ 0x62, 0x31, 0x25, 0x82, 0xb2, 0xd1, 0x86, 0xcf, 0xc4, 0x57, 0x66, 0x96,
+ 0x5f, 0xe2, 0xff, 0x3a, 0xe3, 0xee, 0x2c, 0xbf, 0xb0, 0x7b, 0x99, 0xd6,
+ 0xe2, 0xca, 0x73, 0xeb, 0x23, 0x7a, 0xdc, 0x4d, 0xb5, 0xd3, 0x40, 0xb4,
+ 0x44, 0xa1, 0x84, 0x0d, 0xe1, 0x3c, 0x15, 0x97, 0xfe, 0x38, 0x66, 0xeb,
+ 0x91, 0x33, 0x6f, 0x59, 0x7f, 0x9b, 0x9e, 0x72, 0x88, 0x59, 0x70, 0x7c,
+ 0xb2, 0xb4, 0x78, 0xe7, 0x30, 0xbf, 0xfe, 0xcf, 0x75, 0x2e, 0x4d, 0x26,
+ 0x2f, 0xc0, 0x16, 0x5f, 0xd0, 0x72, 0x8e, 0xa4, 0xb2, 0x98, 0xff, 0xbc,
+ 0xa3, 0x7b, 0x5a, 0xc5, 0x97, 0xba, 0x97, 0x16, 0x5d, 0xe6, 0xe1, 0xba,
+ 0x30, 0x72, 0xfb, 0x58, 0xfb, 0xab, 0x2f, 0x41, 0x92, 0x59, 0x7f, 0xd9,
+ 0xfe, 0x6b, 0x39, 0x1d, 0x2c, 0xbd, 0x8f, 0xda, 0xca, 0xec, 0xfc, 0x98,
+ 0x74, 0x8e, 0x6f, 0xfd, 0x06, 0x09, 0x3f, 0x30, 0xf1, 0xb8, 0xb2, 0xe7,
+ 0x31, 0x65, 0x4e, 0xa9, 0x1c, 0x70, 0xa0, 0xed, 0x6f, 0x45, 0xbe, 0x84,
+ 0xb7, 0xcb, 0xb7, 0xa2, 0x5d, 0xce, 0x96, 0x5d, 0x9c, 0x59, 0x76, 0xee,
+ 0x96, 0x54, 0x2b, 0x8e, 0xc9, 0x5a, 0x4c, 0xe8, 0x20, 0xc6, 0xe8, 0xb5,
+ 0xff, 0xda, 0xec, 0x2e, 0x3c, 0x21, 0xf9, 0x96, 0x5f, 0xb3, 0xdd, 0x4b,
+ 0x8b, 0x2f, 0xc7, 0x17, 0xde, 0xf3, 0x16, 0x53, 0x1e, 0xc0, 0x85, 0x37,
+ 0x1e, 0x16, 0x5e, 0x6d, 0xf8, 0xb2, 0xff, 0xbb, 0x27, 0xe7, 0x03, 0x1d,
+ 0xac, 0xac, 0x3e, 0xdf, 0x8b, 0x04, 0x76, 0xff, 0xce, 0xdf, 0x96, 0x1a,
+ 0x58, 0x05, 0x97, 0xee, 0xa4, 0x58, 0x35, 0x95, 0xe3, 0xe5, 0x23, 0xdb,
+ 0xde, 0xc3, 0x16, 0x5f, 0xcd, 0xcf, 0x34, 0x32, 0xcb, 0xff, 0xf1, 0x66,
+ 0x77, 0xe8, 0xdc, 0x2c, 0xfe, 0x30, 0x16, 0x51, 0xd1, 0x00, 0xe5, 0x77,
+ 0xfb, 0x0b, 0xa8, 0xe3, 0xee, 0x2c, 0xbf, 0x14, 0xd1, 0xe8, 0x59, 0x4b,
+ 0x2e, 0xc1, 0xac, 0xb8, 0x0f, 0xd1, 0xa1, 0xde, 0x17, 0x7e, 0xcf, 0x74,
+ 0xfb, 0x8b, 0x2f, 0x81, 0xc8, 0x25, 0x97, 0xfb, 0x5e, 0x76, 0xe3, 0x6f,
+ 0x59, 0x71, 0xac, 0xb2, 0xa0, 0xfb, 0x30, 0x85, 0xcd, 0x2f, 0xfd, 0x84,
+ 0x4f, 0xfd, 0x92, 0x83, 0xac, 0xb7, 0x6b, 0x2b, 0xc7, 0xa0, 0x13, 0xeb,
+ 0xf3, 0xfc, 0x2e, 0x22, 0xca, 0x85, 0xca, 0x71, 0xc2, 0x73, 0x21, 0x1e,
+ 0xd0, 0x93, 0xdc, 0x21, 0x3c, 0x27, 0x7c, 0x44, 0xe6, 0xa0, 0x48, 0x22,
+ 0xfe, 0x42, 0x5f, 0xef, 0x81, 0x22, 0xbf, 0x8c, 0x8d, 0x69, 0xe6, 0x59,
+ 0x7f, 0xc3, 0x8e, 0xc4, 0x00, 0x23, 0xa5, 0x97, 0xb8, 0xfd, 0x2c, 0xbf,
+ 0xe7, 0xd6, 0x1d, 0xb6, 0xe0, 0xeb, 0x2b, 0xb4, 0x49, 0xb1, 0xe0, 0x47,
+ 0x6f, 0x9f, 0x9b, 0x82, 0x2c, 0xbf, 0x74, 0x31, 0xb7, 0x16, 0x5e, 0xd6,
+ 0x71, 0x65, 0x41, 0xe2, 0xe1, 0x4d, 0xf7, 0xe3, 0xa9, 0x2c, 0xbf, 0x98,
+ 0x1b, 0x64, 0xc0, 0x59, 0x76, 0x01, 0x65, 0x4e, 0x7d, 0x1a, 0x23, 0x22,
+ 0xfb, 0xff, 0xbc, 0xed, 0xfc, 0xd0, 0x0e, 0xf2, 0x59, 0x78, 0x7e, 0x65,
+ 0x94, 0xc7, 0xbe, 0x14, 0x3b, 0xfd, 0x31, 0x39, 0x98, 0x40, 0x59, 0x78,
+ 0xa2, 0x75, 0x94, 0xe7, 0x9e, 0x46, 0x77, 0xbf, 0x82, 0x2c, 0xa8, 0x56,
+ 0x41, 0x90, 0xc2, 0x34, 0xc3, 0xcd, 0x6f, 0x08, 0x8e, 0x42, 0x38, 0x2e,
+ 0x1b, 0xa4, 0x17, 0xf1, 0x44, 0xa3, 0x7c, 0x2c, 0xb0, 0x16, 0x5f, 0x8d,
+ 0x72, 0x0c, 0xcb, 0x2a, 0x0d, 0xd0, 0x44, 0x6f, 0x82, 0xdb, 0xa7, 0x59,
+ 0x7f, 0x6f, 0xd3, 0xc3, 0x6d, 0xac, 0xb9, 0xa7, 0x59, 0x6c, 0x59, 0x4c,
+ 0x98, 0x24, 0xcc, 0xfa, 0x20, 0x39, 0x2b, 0x98, 0x90, 0xbd, 0xfb, 0x3d,
+ 0xbd, 0xb4, 0xb2, 0xff, 0x14, 0xbc, 0xdb, 0xf0, 0x6b, 0x2d, 0x0b, 0x29,
+ 0xcf, 0x10, 0x8d, 0x2f, 0x66, 0xa1, 0x65, 0xf4, 0xc6, 0x41, 0xab, 0x2f,
+ 0x8b, 0xfb, 0xb0, 0xb2, 0xfa, 0x7f, 0xe7, 0x6b, 0x2f, 0xf3, 0x9a, 0x27,
+ 0xbd, 0x12, 0x59, 0x50, 0x8b, 0xdc, 0x1b, 0x62, 0x57, 0x24, 0xdb, 0x24,
+ 0xbf, 0xf7, 0xb0, 0x63, 0x6e, 0xb3, 0xaf, 0xac, 0xbf, 0xb6, 0x0c, 0x47,
+ 0xd6, 0x96, 0x54, 0xe7, 0xe2, 0x34, 0x0b, 0xfc, 0x3c, 0xff, 0xa0, 0xbb,
+ 0x59, 0x7a, 0x1b, 0x6d, 0x65, 0xf7, 0xf8, 0x21, 0xd6, 0x53, 0x9e, 0x10,
+ 0x47, 0xaf, 0xf8, 0x7b, 0x33, 0x91, 0x9a, 0x02, 0xcb, 0xde, 0x13, 0x8b,
+ 0x2b, 0x0f, 0x61, 0xce, 0xaf, 0x73, 0xcc, 0xb2, 0xff, 0x30, 0xfe, 0x4f,
+ 0xd7, 0x16, 0x52, 0xcb, 0xfb, 0x8d, 0xd6, 0x75, 0xf5, 0x95, 0xd1, 0xba,
+ 0xf8, 0x5d, 0xd3, 0xc2, 0xca, 0x84, 0x53, 0x3b, 0x68, 0x48, 0xaf, 0xb3,
+ 0x8c, 0x05, 0x95, 0x0a, 0x90, 0xa7, 0x23, 0x1b, 0xaf, 0x9e, 0x40, 0x40,
+ 0x50, 0xc2, 0xdb, 0x2e, 0xad, 0xa9, 0xda, 0xdc, 0x0a, 0x55, 0x76, 0x88,
+ 0x41, 0x0a, 0x09, 0xf6, 0x92, 0x28, 0xaa, 0x2c, 0x89, 0x41, 0x13, 0xbb,
+ 0xca, 0x34, 0xf1, 0xca, 0x00, 0xc9, 0x68, 0xe6, 0xc3, 0xeb, 0xb9, 0x42,
+ 0x7d, 0x46, 0xa0, 0xd2, 0x8b, 0xa6, 0x8f, 0xd7, 0x52, 0xab, 0x4f, 0x1e,
+ 0x3f, 0xa7, 0x31, 0xde, 0x5f, 0xf8, 0x25, 0x03, 0x0a, 0xd4, 0x4a, 0x5d,
+ 0x67, 0x27, 0x3e, 0xff, 0x2f, 0xb0, 0x31, 0xc3, 0xef, 0x56, 0x31, 0xb7,
+ 0x6e, 0x1b, 0xa2, 0x4a, 0xfc, 0xbb, 0xb8, 0x59, 0x7c, 0xfd, 0xc6, 0x96,
+ 0x51, 0x86, 0xe7, 0x74, 0x5e, 0xe3, 0x31, 0x65, 0xff, 0x9a, 0x3f, 0xe7,
+ 0x37, 0x08, 0x0b, 0x2f, 0xff, 0x3e, 0xb6, 0x3f, 0xf6, 0x7f, 0xae, 0xd8,
+ 0x96, 0x53, 0x22, 0x8f, 0xc2, 0xfb, 0xcf, 0x6f, 0x6b, 0x24, 0xb2, 0xe6,
+ 0x3a, 0xca, 0xf9, 0xb2, 0xdd, 0x1c, 0xbf, 0xb3, 0xf0, 0xc7, 0xe2, 0xcb,
+ 0xd0, 0x06, 0x59, 0x7f, 0x44, 0xb3, 0x59, 0xc5, 0x97, 0xef, 0x67, 0xe3,
+ 0xcb, 0x28, 0x67, 0xa6, 0xe5, 0x97, 0xff, 0xb5, 0xa0, 0xcb, 0x59, 0x1d,
+ 0x49, 0x8e, 0xb2, 0xe9, 0x99, 0x65, 0x61, 0xf1, 0x3a, 0x5d, 0xee, 0x09,
+ 0xc5, 0x97, 0xff, 0x4b, 0xe1, 0x9c, 0x5f, 0x9c, 0xed, 0xc5, 0x97, 0xfe,
+ 0xf0, 0x7a, 0xe4, 0x1d, 0xfa, 0xfa, 0xcb, 0x67, 0x48, 0x89, 0xfa, 0x45,
+ 0xff, 0xbf, 0x07, 0xe4, 0x34, 0xef, 0xf5, 0x97, 0xf3, 0xee, 0x3e, 0x75,
+ 0xf5, 0x95, 0xd1, 0xf7, 0x78, 0xfa, 0xff, 0x3e, 0x0d, 0xba, 0x27, 0x59,
+ 0x58, 0x7a, 0x81, 0x23, 0xb8, 0x66, 0xac, 0xbe, 0x8f, 0xc9, 0xd6, 0x5f,
+ 0x6b, 0x76, 0x09, 0x65, 0x89, 0x65, 0x41, 0xb4, 0x30, 0x92, 0xf7, 0xca,
+ 0x16, 0x5d, 0xe1, 0x70, 0xb9, 0xd1, 0x90, 0xc8, 0x66, 0x39, 0x89, 0x34,
+ 0x58, 0x76, 0xef, 0x42, 0x0d, 0xc8, 0x0a, 0x14, 0xfc, 0x87, 0x5f, 0xc8,
+ 0x77, 0x8c, 0x18, 0xaa, 0x21, 0x0d, 0x0b, 0x64, 0x26, 0xc4, 0xfb, 0x4d,
+ 0xfd, 0x9a, 0xed, 0xdf, 0xb5, 0x45, 0x9a, 0xbf, 0xc0, 0x8e, 0x33, 0xf4,
+ 0x62, 0xcb, 0xf0, 0x66, 0xf3, 0x0d, 0x65, 0xff, 0xb0, 0x79, 0x86, 0x8c,
+ 0x9a, 0x75, 0x97, 0x9f, 0x3e, 0xb2, 0xfb, 0x5e, 0x71, 0x6c, 0x8b, 0x63,
+ 0x9a, 0x11, 0x4f, 0x0f, 0xaf, 0xf7, 0xfd, 0x8d, 0x39, 0xe1, 0x65, 0xff,
+ 0xa3, 0x40, 0xff, 0x3d, 0x8c, 0x35, 0x97, 0x6d, 0x6e, 0xb2, 0xd3, 0xac,
+ 0xbd, 0x28, 0xe9, 0x65, 0xb2, 0x0d, 0x7c, 0xc2, 0x57, 0xcc, 0x4f, 0x3a,
+ 0xca, 0xc4, 0xc0, 0xbc, 0x66, 0xe7, 0xc4, 0x95, 0xc2, 0x6b, 0x79, 0x65,
+ 0xfb, 0xd1, 0xcf, 0x32, 0xcb, 0xff, 0x37, 0xe0, 0xe4, 0xe6, 0xf9, 0x96,
+ 0x5d, 0x1e, 0x59, 0x7f, 0x16, 0x6f, 0xf3, 0xc9, 0x65, 0x85, 0xce, 0x8b,
+ 0x9c, 0x11, 0x98, 0x9f, 0xc7, 0xbf, 0x16, 0xa1, 0x69, 0xaa, 0x6e, 0xc6,
+ 0x03, 0x7f, 0xfc, 0x17, 0x9f, 0x58, 0x71, 0x7e, 0x89, 0xc8, 0x2b, 0x28,
+ 0x5a, 0xe0, 0xeb, 0x43, 0xc5, 0xe5, 0x55, 0x11, 0x7d, 0xf3, 0x1c, 0x4d,
+ 0x2c, 0xbd, 0xe6, 0x31, 0x65, 0xf7, 0x0a, 0x0c, 0x59, 0x7b, 0xbc, 0xf2,
+ 0xcb, 0xb9, 0x0b, 0x2f, 0xc1, 0xe7, 0xe3, 0x8b, 0x2a, 0x46, 0xfa, 0x61,
+ 0x6a, 0x83, 0xfd, 0x65, 0xbb, 0xf8, 0xa0, 0xfc, 0x69, 0xd6, 0x5e, 0x2d,
+ 0x05, 0x65, 0x48, 0xf2, 0x58, 0xb6, 0xe3, 0x34, 0xb2, 0xfc, 0x16, 0x15,
+ 0x05, 0x3b, 0x52, 0xcb, 0xc1, 0xeb, 0x8b, 0x2f, 0xc2, 0x7c, 0xa0, 0x0b,
+ 0x2b, 0x47, 0x8d, 0xbc, 0x7a, 0xfd, 0x38, 0x64, 0x18, 0x59, 0x50, 0x79,
+ 0xac, 0x49, 0x7c, 0xc7, 0x6d, 0xd5, 0x97, 0x04, 0x45, 0x97, 0x8b, 0x38,
+ 0xb2, 0xa0, 0xf5, 0xe6, 0x24, 0x10, 0x62, 0xfb, 0xcd, 0xd7, 0x16, 0x5d,
+ 0x1d, 0x2c, 0xb9, 0xb6, 0xd6, 0x56, 0xe1, 0xe9, 0xcc, 0x46, 0x20, 0xbd,
+ 0xda, 0x35, 0x65, 0xc7, 0x17, 0x0a, 0xe4, 0x06, 0x47, 0xd0, 0xeb, 0x42,
+ 0x7e, 0x66, 0x9d, 0x10, 0x9c, 0x63, 0xd0, 0xc9, 0x77, 0x70, 0xc2, 0x0c,
+ 0x43, 0x4b, 0xb1, 0x96, 0x5d, 0x83, 0x59, 0x7e, 0xd7, 0x6e, 0xfd, 0xaa,
+ 0x28, 0x05, 0xfc, 0xfa, 0x6f, 0xf3, 0x16, 0x5e, 0x79, 0x0b, 0xc3, 0xe2,
+ 0xe1, 0xb5, 0xfe, 0x63, 0xc6, 0xe7, 0xb2, 0x75, 0x96, 0x17, 0x24, 0x7b,
+ 0xe0, 0xa9, 0xde, 0x3c, 0x69, 0x7f, 0x17, 0xf9, 0x03, 0x85, 0x97, 0x48,
+ 0xeb, 0x2f, 0xe6, 0xe4, 0xc5, 0x03, 0x59, 0x7b, 0x5d, 0x49, 0x65, 0x0c,
+ 0xf2, 0xdc, 0xb6, 0xfd, 0x1d, 0x7d, 0xf4, 0xb2, 0xfd, 0xfe, 0x49, 0x80,
+ 0xb2, 0xdb, 0xd6, 0x5b, 0xeb, 0x2a, 0x46, 0x93, 0xb1, 0x3b, 0xf9, 0xbd,
+ 0x05, 0x1f, 0x59, 0x78, 0x6e, 0xcb, 0x2a, 0x13, 0x8b, 0x91, 0x66, 0x31,
+ 0x31, 0x0b, 0x94, 0x12, 0x67, 0x08, 0x82, 0x57, 0x7a, 0x68, 0x92, 0xcb,
+ 0xb5, 0xf5, 0x96, 0x17, 0x86, 0xd3, 0x83, 0xb7, 0xfd, 0x1f, 0xf6, 0x1f,
+ 0x35, 0x8b, 0x2f, 0xa6, 0xcc, 0xed, 0x65, 0xfb, 0xe6, 0xbf, 0x05, 0xe8,
+ 0xf6, 0x84, 0x37, 0xa9, 0x23, 0x14, 0xc8, 0x41, 0x50, 0xb4, 0xe3, 0xe2,
+ 0x36, 0x6b, 0xb9, 0xf5, 0x96, 0x85, 0x96, 0xf2, 0xca, 0x39, 0xa1, 0x08,
+ 0x85, 0xf0, 0xa7, 0x7f, 0x5c, 0x59, 0x78, 0x78, 0x75, 0x97, 0xff, 0x7d,
+ 0x83, 0xc1, 0x0f, 0xad, 0x31, 0xab, 0x2f, 0xff, 0xdb, 0xe3, 0xcc, 0x3f,
+ 0x44, 0xb8, 0xfe, 0x6e, 0x2c, 0xbf, 0xb9, 0x07, 0x28, 0x99, 0x65, 0xbc,
+ 0xb2, 0xf0, 0x85, 0x32, 0xcb, 0x7f, 0x0d, 0x78, 0x04, 0x6e, 0xc9, 0xd6,
+ 0x56, 0x1b, 0xd2, 0x26, 0xbe, 0x63, 0xc4, 0xcb, 0x2a, 0x74, 0xe4, 0xe4,
+ 0x38, 0xc8, 0xe0, 0x56, 0x28, 0x4c, 0xed, 0x8f, 0xdf, 0xfe, 0x0e, 0xa5,
+ 0x9c, 0x60, 0x8a, 0xca, 0x0e, 0xb2, 0xdc, 0x59, 0x7c, 0x36, 0x20, 0x2c,
+ 0xad, 0x86, 0xc9, 0xc4, 0x6f, 0xff, 0xb5, 0x38, 0xfc, 0xda, 0xe4, 0x6a,
+ 0x66, 0xf2, 0xcb, 0xff, 0xb0, 0x1c, 0x27, 0x37, 0x37, 0xb6, 0x96, 0x5e,
+ 0x08, 0xf1, 0x65, 0xfd, 0xaf, 0x94, 0x1f, 0x8b, 0x2f, 0xff, 0xda, 0x1b,
+ 0x91, 0xbe, 0xcd, 0xcd, 0x31, 0xe0, 0xd5, 0x95, 0x88, 0x86, 0x09, 0x6d,
+ 0xb6, 0xd6, 0x54, 0x26, 0xdf, 0x8a, 0x4c, 0x8b, 0xe8, 0x51, 0x00, 0x8a,
+ 0xf3, 0xeb, 0x16, 0x5e, 0xe4, 0x01, 0x65, 0xf4, 0x98, 0xb1, 0x65, 0x7c,
+ 0xde, 0x18, 0x39, 0x7d, 0xdb, 0xbf, 0x6a, 0x8b, 0x7d, 0x7b, 0x6d, 0xfe,
+ 0xb2, 0xff, 0x31, 0x41, 0xc0, 0xff, 0x59, 0x7a, 0x6c, 0x02, 0xcb, 0xf0,
+ 0x93, 0xfa, 0x34, 0xb2, 0xbb, 0x4d, 0x01, 0x95, 0xf4, 0x44, 0x73, 0x0f,
+ 0x0f, 0xb9, 0x8f, 0xc7, 0x6f, 0xf9, 0xbd, 0x1d, 0x46, 0xe6, 0x74, 0xb2,
+ 0xff, 0xff, 0x9e, 0x61, 0xb6, 0xbd, 0x83, 0x28, 0xed, 0xe7, 0x28, 0x3a,
+ 0xcb, 0xfe, 0xd0, 0x79, 0xe7, 0x90, 0x19, 0x65, 0x98, 0x08, 0x9f, 0xfb,
+ 0x35, 0xf7, 0xf8, 0xff, 0x59, 0x7f, 0xed, 0x66, 0xe4, 0xde, 0x73, 0xb7,
+ 0x16, 0x5d, 0x93, 0xe1, 0xf2, 0x68, 0x8a, 0xbc, 0x8b, 0x92, 0x84, 0x65,
+ 0x8c, 0x59, 0x7f, 0xce, 0x5d, 0xf2, 0x3c, 0xfb, 0x8b, 0x28, 0xd3, 0xcd,
+ 0xf8, 0x95, 0xf6, 0x13, 0x4c, 0xb2, 0xf9, 0xb3, 0x5b, 0xd6, 0x5f, 0x75,
+ 0x29, 0xe1, 0x65, 0xe8, 0x33, 0x6d, 0x65, 0x61, 0xe2, 0x68, 0x92, 0xf7,
+ 0xa3, 0x4b, 0x2f, 0xde, 0x6d, 0x79, 0xd6, 0x5f, 0xfe, 0xf4, 0x4f, 0xfc,
+ 0xf1, 0x67, 0xfc, 0xcb, 0x2f, 0x1f, 0x06, 0xb2, 0xc7, 0x59, 0x7f, 0xa2,
+ 0x71, 0xe1, 0x9c, 0x17, 0x08, 0xb9, 0xc1, 0xc9, 0x89, 0xdd, 0x24, 0x41,
+ 0xca, 0x92, 0x69, 0xfe, 0x86, 0xd5, 0xf0, 0xcf, 0x9d, 0x2c, 0xbe, 0x97,
+ 0x04, 0xe2, 0xca, 0x83, 0xc7, 0xf9, 0x1d, 0xf6, 0x7f, 0x98, 0xb2, 0xfe,
+ 0x7e, 0x86, 0xc5, 0x3a, 0xca, 0x83, 0xcf, 0xd1, 0x0d, 0xee, 0x78, 0x6b,
+ 0x2f, 0xc2, 0x7c, 0xa0, 0x0b, 0x28, 0xe7, 0x8b, 0xbc, 0x76, 0xe2, 0x85,
+ 0x97, 0xff, 0x7f, 0x8d, 0xc8, 0x2c, 0xff, 0x99, 0x65, 0xff, 0x9f, 0x77,
+ 0x4c, 0x6e, 0x79, 0xa4, 0xb2, 0xff, 0x80, 0xdf, 0x27, 0xfc, 0x0d, 0x65,
+ 0xe2, 0xcf, 0x2c, 0xad, 0x23, 0xa8, 0xe2, 0xbe, 0x42, 0xe2, 0x0e, 0xf3,
+ 0x7b, 0xfe, 0x6e, 0x60, 0xe2, 0x66, 0x3a, 0xcb, 0xf0, 0xe3, 0x70, 0x27,
+ 0x59, 0x7f, 0xcf, 0xc8, 0xc2, 0x1f, 0xa1, 0x65, 0xfe, 0xf4, 0x0d, 0xb7,
+ 0xc0, 0xd6, 0x5f, 0xf6, 0xb3, 0xaf, 0x13, 0xee, 0x4e, 0xb2, 0xd8, 0x33,
+ 0xf1, 0x39, 0xa5, 0xdc, 0xe6, 0x91, 0x9c, 0x50, 0xa7, 0xa8, 0x55, 0x7d,
+ 0x91, 0x87, 0x76, 0x98, 0xc7, 0x0f, 0x0f, 0x9b, 0xf0, 0x99, 0xe7, 0x3a,
+ 0xcb, 0x82, 0x6a, 0xcb, 0xe3, 0xcd, 0x02, 0x2c, 0xba, 0x3c, 0xb2, 0xff,
+ 0xdb, 0xae, 0x71, 0x34, 0x03, 0xb7, 0x16, 0x57, 0x68, 0xbd, 0x39, 0x43,
+ 0x8c, 0x11, 0x26, 0xe8, 0xb5, 0xe6, 0x2f, 0xac, 0xb8, 0x3d, 0x2c, 0xbf,
+ 0xe7, 0x97, 0xf9, 0x86, 0x79, 0x96, 0x5e, 0xe9, 0xfc, 0xb2, 0x9d, 0x11,
+ 0x20, 0x1b, 0x21, 0x80, 0x9c, 0xdf, 0xe8, 0xe6, 0x75, 0xf6, 0xd2, 0xcb,
+ 0xee, 0x7e, 0x0e, 0xb2, 0xb4, 0x7a, 0xa0, 0x33, 0xbf, 0xde, 0x09, 0x0f,
+ 0xcc, 0x62, 0xcb, 0xff, 0xa6, 0x08, 0xdc, 0x81, 0xb1, 0x8f, 0xf5, 0x95,
+ 0xe3, 0xfb, 0xf9, 0xa5, 0xed, 0x47, 0xd6, 0x5f, 0xfa, 0x3e, 0x17, 0x9e,
+ 0x3d, 0x07, 0x59, 0x7f, 0x4c, 0xe3, 0xf3, 0x1d, 0x65, 0xfd, 0xf6, 0xc1,
+ 0xc1, 0xd6, 0x57, 0x48, 0x98, 0xf9, 0xf1, 0x85, 0xd7, 0xcf, 0x38, 0x49,
+ 0x65, 0xdc, 0x25, 0x97, 0xf7, 0x5c, 0x8e, 0xf0, 0xeb, 0x2f, 0x8f, 0xde,
+ 0x12, 0xca, 0x85, 0x45, 0xd9, 0x09, 0xdd, 0x11, 0x3c, 0x2d, 0x08, 0xcb,
+ 0x84, 0x41, 0x16, 0x10, 0xbe, 0x96, 0x5f, 0xa6, 0x82, 0x28, 0x59, 0x77,
+ 0x7a, 0x59, 0x73, 0x92, 0xca, 0x83, 0xde, 0x60, 0xbf, 0x93, 0x04, 0x62,
+ 0xfc, 0xf3, 0xc7, 0x9d, 0x65, 0xe2, 0x83, 0x56, 0x5f, 0x66, 0xe3, 0xf9,
+ 0x65, 0xe2, 0x7f, 0xf6, 0x78, 0x1c, 0x1c, 0xbf, 0xe2, 0xcf, 0xff, 0x26,
+ 0x79, 0x96, 0x5e, 0x98, 0x3e, 0x59, 0x70, 0xce, 0xb2, 0xfd, 0x93, 0x4a,
+ 0x3a, 0x59, 0x58, 0x7b, 0xc6, 0x8f, 0x10, 0xbd, 0xd0, 0x4b, 0x2b, 0xb4,
+ 0xc3, 0x58, 0xcf, 0xd0, 0x97, 0x30, 0xba, 0xf7, 0x8c, 0x75, 0x97, 0xff,
+ 0x07, 0x9e, 0x79, 0x8b, 0x00, 0x1e, 0x2c, 0xbf, 0x61, 0x7e, 0x38, 0xb2,
+ 0xf3, 0x91, 0xab, 0x2d, 0x25, 0x97, 0xf8, 0x00, 0x0f, 0x37, 0x33, 0xa5,
+ 0x95, 0x87, 0x92, 0xe2, 0x37, 0xfe, 0x7e, 0xba, 0xe3, 0x0f, 0x0c, 0xe2,
+ 0xca, 0x85, 0x60, 0xd9, 0x1b, 0xa3, 0x22, 0x68, 0x77, 0xc8, 0xae, 0x4c,
+ 0x4c, 0xbc, 0x20, 0xbf, 0xfe, 0x7e, 0xb5, 0x99, 0xd1, 0x9e, 0x0c, 0x75,
+ 0xc5, 0x97, 0xe7, 0x9f, 0xb7, 0x1a, 0xcb, 0xfd, 0xf6, 0xe3, 0xf6, 0xf3,
+ 0xac, 0xbf, 0x39, 0x0f, 0xd0, 0xb2, 0xf8, 0x0c, 0x46, 0xac, 0xa7, 0x3c,
+ 0x80, 0x13, 0x50, 0xa5, 0xb8, 0xc5, 0xda, 0x0e, 0x36, 0x91, 0x0c, 0x47,
+ 0x7b, 0x3a, 0xfc, 0x9f, 0xc7, 0x1c, 0x8e, 0x47, 0x1a, 0x6b, 0x27, 0x71,
+ 0xca, 0x74, 0xe8, 0xc4, 0x7b, 0x84, 0x33, 0x47, 0x6d, 0xa7, 0x03, 0xb8,
+ 0x7a, 0x59, 0x23, 0xc6, 0x22, 0x08, 0x6a, 0x94, 0xab, 0xee, 0x43, 0x63,
+ 0xf2, 0xd0, 0x02, 0xe9, 0xb6, 0xa6, 0x21, 0x4e, 0xeb, 0xe5, 0xd1, 0x3a,
+ 0xcb, 0x9f, 0xeb, 0x2f, 0x3f, 0x42, 0xc6, 0x6b, 0x4e, 0x2f, 0x42, 0xd5,
+ 0x0f, 0x14, 0x7d, 0x37, 0xf0, 0xc5, 0xf3, 0xfc, 0xe9, 0x65, 0xee, 0xdf,
+ 0xb5, 0x97, 0xff, 0x09, 0xde, 0xc8, 0xd6, 0x98, 0x9f, 0xb5, 0x97, 0xfb,
+ 0x6d, 0xc8, 0x1f, 0x89, 0x96, 0x56, 0x22, 0x70, 0xe3, 0xc2, 0x24, 0x5d,
+ 0xb5, 0xed, 0x0b, 0x2f, 0x1d, 0xfa, 0x59, 0x78, 0x0f, 0xe5, 0x97, 0xfd,
+ 0xf6, 0x3f, 0x3d, 0x86, 0x3a, 0xcb, 0xb7, 0xb2, 0xcb, 0xed, 0x6b, 0x04,
+ 0x59, 0x7f, 0xd1, 0x23, 0x1f, 0x5a, 0xc1, 0x16, 0x5e, 0xc3, 0x05, 0xed,
+ 0x49, 0x84, 0x41, 0x0e, 0x0e, 0xf4, 0x39, 0x31, 0xcb, 0x8c, 0x11, 0x1d,
+ 0xb8, 0x2d, 0x3b, 0x49, 0xe3, 0x38, 0xbf, 0xff, 0xef, 0xb7, 0xf9, 0xe6,
+ 0x17, 0xff, 0x33, 0x83, 0x03, 0xa9, 0xd6, 0x54, 0x2b, 0x1e, 0x69, 0x50,
+ 0x41, 0x33, 0xbf, 0x4e, 0x2c, 0x01, 0xe9, 0x65, 0xff, 0xfe, 0x6f, 0x85,
+ 0xe7, 0x17, 0x92, 0xf4, 0x6b, 0x30, 0x8d, 0x59, 0x5a, 0x44, 0x78, 0xac,
+ 0xb6, 0xff, 0xff, 0xee, 0xdf, 0x4f, 0xe9, 0x67, 0xf0, 0x7c, 0x73, 0xe6,
+ 0xa7, 0x8e, 0x96, 0x5f, 0xd8, 0x37, 0x3e, 0x12, 0xcb, 0xff, 0xec, 0x08,
+ 0xaf, 0x09, 0xdb, 0xcf, 0xff, 0x42, 0xca, 0x64, 0x77, 0x69, 0xcf, 0xc5,
+ 0x77, 0xed, 0x76, 0xef, 0xda, 0xa2, 0x94, 0x5f, 0xff, 0x3f, 0xcb, 0x27,
+ 0xd4, 0x79, 0xbd, 0x9a, 0x59, 0x77, 0x0c, 0x59, 0x7f, 0xef, 0x40, 0x0e,
+ 0xf2, 0xe7, 0x0c, 0x59, 0x79, 0xe4, 0x2e, 0x13, 0x0b, 0xc2, 0xf0, 0x1b,
+ 0x71, 0x38, 0x41, 0x8b, 0xff, 0x37, 0x6f, 0xa7, 0x93, 0x70, 0x0b, 0x2f,
+ 0xda, 0xed, 0xdf, 0xb5, 0x44, 0x9c, 0xba, 0x42, 0xe0, 0xfd, 0x30, 0xfa,
+ 0x8e, 0x8f, 0xf7, 0x86, 0x8d, 0xf7, 0xa2, 0x67, 0x59, 0x7d, 0xd9, 0x04,
+ 0xd5, 0x97, 0x68, 0x5e, 0x1e, 0x33, 0x91, 0x50, 0xb4, 0x4d, 0xbb, 0x6d,
+ 0x44, 0x76, 0x0d, 0x13, 0xd3, 0xf4, 0xe5, 0x3c, 0xca, 0x3c, 0xc8, 0x2d,
+ 0x32, 0x36, 0x63, 0x63, 0x2f, 0xee, 0x38, 0xa6, 0x97, 0x4b, 0xb9, 0x19,
+ 0xe4, 0xd0, 0xe9, 0xd4, 0x62, 0xc7, 0xb7, 0xc9, 0xbe, 0x9c, 0x4d, 0x79,
+ 0x7b, 0x60, 0x8e, 0xb8, 0xa5, 0xaf, 0x72, 0xbb, 0x0e, 0xfc, 0xb4, 0xa0,
+ 0xc3, 0x1b, 0x7c, 0xbb, 0xab, 0xf6, 0xbb, 0x77, 0xed, 0x51, 0x0f, 0xaf,
+ 0xfc, 0xf2, 0x17, 0x9a, 0xed, 0xdf, 0xb5, 0x44, 0xa6, 0xb0, 0xbc, 0x44,
+ 0x21, 0xcd, 0xaf, 0xf0, 0xbc, 0xd7, 0x6e, 0xfd, 0xaa, 0x22, 0x75, 0xf9,
+ 0xbf, 0xc0, 0x9d, 0x65, 0xf8, 0x27, 0x27, 0x35, 0x65, 0xef, 0x44, 0xcb,
+ 0x2e, 0xea, 0x4b, 0x2a, 0x64, 0x42, 0xe8, 0xa3, 0xc5, 0x01, 0x1d, 0xbf,
+ 0xc1, 0xe8, 0x41, 0x87, 0xfc, 0x59, 0x7f, 0xfb, 0x69, 0x9a, 0x66, 0xe4,
+ 0xe3, 0x14, 0x6c, 0xd9, 0xed, 0xb5, 0x97, 0xed, 0x76, 0xef, 0xda, 0xa2,
+ 0x31, 0x5f, 0xb8, 0xdb, 0xe0, 0xeb, 0x2f, 0x75, 0x29, 0xd6, 0x5b, 0xd0,
+ 0x79, 0x18, 0x53, 0x7f, 0x4a, 0x01, 0xe6, 0x31, 0x65, 0xff, 0xfc, 0x12,
+ 0x73, 0x76, 0x7c, 0xd8, 0x29, 0x67, 0x98, 0xeb, 0x2f, 0xd3, 0x47, 0x52,
+ 0x75, 0x97, 0xd0, 0x7e, 0xc0, 0xb2, 0xff, 0xfa, 0x53, 0xed, 0x38, 0xda,
+ 0x27, 0xef, 0x5b, 0x36, 0x7b, 0x6d, 0x65, 0x62, 0x2c, 0xfc, 0x52, 0x02,
+ 0x3b, 0xf6, 0x9b, 0xb6, 0xde, 0xb2, 0xfc, 0x1f, 0xc7, 0x52, 0x59, 0x7b,
+ 0x3a, 0xfa, 0xcb, 0xfd, 0x85, 0xec, 0xfc, 0x0d, 0x65, 0xd9, 0xf8, 0x3c,
+ 0xe6, 0x1d, 0xbf, 0xf7, 0xcd, 0x82, 0x96, 0x79, 0x8e, 0xb2, 0xff, 0x8d,
+ 0x82, 0x96, 0x79, 0x8e, 0xb2, 0xf8, 0x24, 0xe6, 0xec, 0x3f, 0x6f, 0x9f,
+ 0x5f, 0xb4, 0x06, 0xf4, 0x2c, 0xa3, 0x9f, 0x10, 0x4e, 0xef, 0x75, 0x2d,
+ 0xa1, 0x65, 0xfd, 0xef, 0xf3, 0x3a, 0x92, 0xca, 0x63, 0xd2, 0x09, 0x1d,
+ 0xfb, 0x64, 0xc5, 0x03, 0x59, 0x78, 0x49, 0x6e, 0x2c, 0xb0, 0xb8, 0x5d,
+ 0x6e, 0x9c, 0xfa, 0x46, 0xf8, 0xc9, 0xdb, 0xf4, 0xc4, 0xc7, 0x2e, 0xf4,
+ 0x62, 0x0e, 0x5e, 0x02, 0xa2, 0x77, 0xe4, 0x60, 0x7f, 0x74, 0xdb, 0x21,
+ 0xdd, 0x2a, 0xbf, 0xfc, 0x2c, 0xef, 0x21, 0x79, 0xae, 0xdd, 0xfb, 0x54,
+ 0x4f, 0x2b, 0xdb, 0xe3, 0xcb, 0x2d, 0x0b, 0x2a, 0x0d, 0x76, 0x87, 0xaf,
+ 0xa0, 0xa5, 0xc5, 0x97, 0x67, 0x16, 0x5e, 0xfc, 0x1d, 0x65, 0xfb, 0xcc,
+ 0x59, 0xbd, 0x65, 0x69, 0x13, 0x60, 0x20, 0x15, 0x90, 0xfc, 0x58, 0x41,
+ 0xcb, 0xf7, 0x02, 0x3c, 0x3a, 0xcb, 0xa4, 0x22, 0xcb, 0xe0, 0xbe, 0xa4,
+ 0xb2, 0xf7, 0xc4, 0x9d, 0x65, 0xe3, 0x87, 0x71, 0x65, 0xf9, 0xc7, 0xe8,
+ 0xe2, 0xcb, 0xfd, 0x9e, 0xf4, 0x74, 0xfb, 0x8b, 0x2c, 0x2e, 0x11, 0xfd,
+ 0x22, 0x81, 0x8c, 0x61, 0x10, 0x07, 0xc8, 0x83, 0x84, 0xf4, 0x2d, 0x3b,
+ 0x63, 0x23, 0x4d, 0xa8, 0x65, 0x28, 0x4e, 0x55, 0x29, 0xe3, 0x6f, 0x43,
+ 0xa3, 0xf2, 0xb6, 0xef, 0xda, 0xed, 0xdf, 0xb5, 0x44, 0x40, 0xbf, 0xf3,
+ 0xc8, 0x5e, 0x6b, 0xb7, 0x7e, 0xd5, 0x12, 0xa2, 0xfe, 0xd0, 0x7d, 0x05,
+ 0xda, 0xcb, 0xfb, 0xb6, 0xcd, 0xdf, 0x42, 0xca, 0x83, 0xde, 0xc2, 0xeb,
+ 0x0b, 0xc4, 0xc0, 0x8e, 0x6c, 0x50, 0xac, 0xbf, 0x6b, 0xb7, 0x7e, 0xd5,
+ 0x11, 0x42, 0xfd, 0xa8, 0x3c, 0x74, 0xb2, 0xfd, 0xe6, 0x38, 0x46, 0xb2,
+ 0xf1, 0xc3, 0xb8, 0xb2, 0xff, 0x9e, 0x58, 0x32, 0x77, 0x1a, 0xcb, 0xff,
+ 0x05, 0xf4, 0xf2, 0xfb, 0x70, 0x2b, 0x2f, 0xfa, 0x3a, 0x2c, 0xff, 0x20,
+ 0xeb, 0x28, 0x8f, 0xd8, 0x27, 0xd7, 0xa0, 0x18, 0xb2, 0xc2, 0xf1, 0x38,
+ 0xe6, 0x36, 0x72, 0x80, 0x14, 0x11, 0x07, 0x21, 0x58, 0x21, 0x0d, 0xfe,
+ 0x17, 0x9a, 0xed, 0xdf, 0xb5, 0x44, 0x64, 0xbf, 0x6b, 0xb7, 0x7e, 0xd5,
+ 0x13, 0x2a, 0xfd, 0x2c, 0xfb, 0xf6, 0xb2, 0xfc, 0x2c, 0xef, 0x21, 0x78,
+ 0x7b, 0xdd, 0x1b, 0x5d, 0xd0, 0x56, 0x5f, 0xb5, 0xdb, 0xbf, 0x6a, 0x8a,
+ 0x91, 0x62, 0x59, 0x74, 0x8e, 0xb2, 0xf8, 0xf9, 0x9f, 0x59, 0x61, 0x16,
+ 0x58, 0x5c, 0x91, 0x51, 0x83, 0x1b, 0x86, 0xda, 0x10, 0x71, 0x70, 0x90,
+ 0xdf, 0xe1, 0x79, 0xae, 0xdd, 0xfb, 0x54, 0x57, 0x4b, 0xfc, 0x2f, 0x35,
+ 0xdb, 0xbf, 0x6a, 0x8b, 0x15, 0x7f, 0xd1, 0xce, 0x41, 0xff, 0x9d, 0xac,
+ 0xbe, 0xed, 0xdf, 0xb5, 0x44, 0xf4, 0xbf, 0x1d, 0xe4, 0x2f, 0x3b, 0x3e,
+ 0x9d, 0x1c, 0xde, 0x31, 0xfb, 0x59, 0x7f, 0x7a, 0x1b, 0x4c, 0x2b, 0x59,
+ 0x7e, 0x86, 0xdb, 0x6d, 0xd5, 0x97, 0xd1, 0xd3, 0xee, 0xac, 0xb8, 0xc1,
+ 0x78, 0x89, 0xfe, 0xc7, 0x9c, 0xc0, 0x8b, 0x2f, 0xff, 0x41, 0x0b, 0xcf,
+ 0x3e, 0xc3, 0xc6, 0x7d, 0x65, 0xff, 0xff, 0xe1, 0xe1, 0x82, 0xcb, 0x0d,
+ 0x35, 0xff, 0xc6, 0x29, 0xa3, 0xbd, 0x67, 0x4b, 0x2f, 0xff, 0xff, 0xdf,
+ 0x7d, 0x48, 0x5e, 0x70, 0x2f, 0xd6, 0x14, 0x18, 0x27, 0xda, 0x59, 0xd7,
+ 0xd6, 0x5f, 0xb3, 0xfe, 0x63, 0x16, 0x5f, 0xfb, 0x98, 0x4e, 0x6f, 0x9a,
+ 0x09, 0x65, 0xff, 0x66, 0x79, 0xbb, 0xf6, 0x0b, 0x23, 0xe4, 0xf9, 0x45,
+ 0xff, 0xfa, 0x62, 0x83, 0x8b, 0xce, 0x31, 0x83, 0x77, 0x35, 0x65, 0xdc,
+ 0xfa, 0xcb, 0xb3, 0x8b, 0x2f, 0xfd, 0x9a, 0xea, 0x0f, 0xe7, 0xcd, 0x2c,
+ 0xbb, 0x80, 0x59, 0x7e, 0x27, 0x39, 0x42, 0xcb, 0xf8, 0x3c, 0xf3, 0xc8,
+ 0x5e, 0xd0, 0x8a, 0x77, 0x17, 0x21, 0x63, 0x0f, 0x84, 0x17, 0xbd, 0x3c,
+ 0x6e, 0x2c, 0xbb, 0x5f, 0x59, 0x7e, 0xcf, 0xf1, 0x8e, 0xb2, 0xff, 0xf4,
+ 0x75, 0xfc, 0x99, 0xb5, 0xfe, 0x07, 0x71, 0x65, 0xe7, 0xe8, 0x5c, 0x22,
+ 0xb5, 0xc8, 0x08, 0x5f, 0xe4, 0xf5, 0x8a, 0x9b, 0xb5, 0x0f, 0xfe, 0x46,
+ 0x43, 0x52, 0x5c, 0xad, 0x1a, 0x5f, 0x4f, 0xa5, 0x0e, 0xbf, 0xca, 0xbe,
+ 0xa1, 0x6b, 0xc6, 0x11, 0x0e, 0x06, 0x9c, 0xf7, 0xbf, 0xfc, 0x31, 0x7f,
+ 0xf8, 0x67, 0x12, 0x6e, 0x07, 0xa5, 0x97, 0xa0, 0x22, 0xb5, 0x97, 0xed,
+ 0x77, 0xe6, 0xe2, 0xca, 0x63, 0xc9, 0x09, 0x05, 0xdf, 0x85, 0x95, 0xb5,
+ 0x1b, 0x7e, 0x88, 0x6f, 0xf8, 0xb3, 0x79, 0x67, 0x00, 0x75, 0x97, 0xe6,
+ 0xf1, 0x3c, 0xcb, 0x2f, 0xd2, 0xc1, 0xec, 0xc5, 0x97, 0xe7, 0x69, 0xf5,
+ 0x0b, 0x2f, 0xdf, 0x20, 0xb8, 0xa1, 0x65, 0x6d, 0x48, 0xdb, 0x14, 0x9c,
+ 0xc1, 0x3f, 0x8a, 0x44, 0x27, 0xb8, 0xe0, 0x59, 0x7e, 0xcf, 0xb0, 0x78,
+ 0xb2, 0xed, 0xa8, 0x55, 0x2c, 0xad, 0xa8, 0xf8, 0x05, 0x50, 0xbe, 0xd3,
+ 0x27, 0xbf, 0x0a, 0xbd, 0xab, 0x9a, 0xfa, 0xcb, 0xfc, 0x21, 0x66, 0xb5,
+ 0x1d, 0xac, 0xad, 0xa8, 0xfa, 0x05, 0x06, 0x97, 0xda, 0x3f, 0xfa, 0x59,
+ 0x7e, 0xda, 0xc5, 0x27, 0xe1, 0xab, 0x2e, 0x6e, 0x2c, 0xad, 0xa8, 0xf2,
+ 0x7b, 0x33, 0xbf, 0x6d, 0x62, 0x98, 0x91, 0xd6, 0x5e, 0xf4, 0x6e, 0x2c,
+ 0xbf, 0xf6, 0xd3, 0xda, 0x05, 0x02, 0x91, 0x40, 0xa0, 0x54, 0x14, 0x6d,
+ 0x4b, 0x2f, 0xfc, 0x2a, 0xc5, 0x02, 0xa0, 0xab, 0x15, 0x62, 0x91, 0x4e,
+ 0xd7, 0xb5, 0x2c, 0xbf, 0xf0, 0xa9, 0xb4, 0xc5, 0x58, 0xa8, 0x2a, 0xc5,
+ 0x22, 0xa8, 0x55, 0xed, 0x4b, 0x2f, 0xfb, 0xc3, 0x90, 0xb9, 0x70, 0x85,
+ 0x8a, 0x53, 0x4a, 0xda, 0x1a, 0x85, 0x53, 0x75, 0x6d, 0x4a, 0x83, 0x45,
+ 0x26, 0x22, 0xaa, 0x36, 0x9b, 0xf0, 0xa4, 0xee, 0xe4, 0xb2, 0xfe, 0x86,
+ 0xff, 0xe0, 0xeb, 0x2e, 0x1e, 0xe2, 0xca, 0xda, 0xcf, 0xc0, 0x55, 0x95,
+ 0x74, 0x59, 0x7b, 0xbc, 0xf2, 0x4b, 0xb9, 0xa5, 0x97, 0x8f, 0x1c, 0x59,
+ 0x7f, 0xff, 0xbe, 0x26, 0xa3, 0xd1, 0x9d, 0x8d, 0x8a, 0x73, 0xc4, 0x96,
+ 0x5d, 0xa8, 0x59, 0x4c, 0x7f, 0x00, 0x62, 0xbf, 0x46, 0xb4, 0xf2, 0x59,
+ 0x7f, 0xf7, 0xa3, 0x8e, 0x27, 0xbc, 0xdd, 0x71, 0x65, 0xff, 0x34, 0x16,
+ 0x6f, 0xd4, 0x71, 0x65, 0x76, 0x7f, 0xde, 0x46, 0xbd, 0x33, 0x18, 0xb2,
+ 0xec, 0x92, 0xcb, 0x01, 0x8d, 0xa3, 0x8f, 0x5f, 0xf9, 0xb6, 0x79, 0x9e,
+ 0x5f, 0x69, 0xd6, 0x56, 0x1f, 0x2f, 0x89, 0x6f, 0xdf, 0x00, 0x85, 0x32,
+ 0xcb, 0xff, 0x3f, 0x36, 0x73, 0x99, 0x29, 0x42, 0xcb, 0x71, 0x65, 0xfd,
+ 0x1d, 0xb4, 0xee, 0x4b, 0x2f, 0xff, 0xc4, 0xe6, 0xb6, 0xa2, 0x52, 0xce,
+ 0x00, 0x10, 0xb2, 0xff, 0x3f, 0xc3, 0x98, 0x46, 0xac, 0xa1, 0xa6, 0x9f,
+ 0x84, 0x26, 0x95, 0x4c, 0x81, 0xa1, 0x1f, 0x16, 0x81, 0x52, 0xfe, 0xcf,
+ 0xc1, 0x44, 0xcb, 0x2f, 0xfc, 0x58, 0x1e, 0xcb, 0x27, 0x12, 0x4b, 0x2f,
+ 0xff, 0x39, 0xc5, 0xc6, 0xb4, 0xdb, 0xbd, 0x86, 0x75, 0x97, 0x69, 0x89,
+ 0x12, 0x3b, 0xa8, 0x17, 0xcd, 0xe1, 0x0e, 0xb2, 0xff, 0xf3, 0x1b, 0xb3,
+ 0x09, 0xfa, 0xe1, 0xa6, 0xba, 0xca, 0xec, 0xfc, 0x48, 0x8e, 0xff, 0xf3,
+ 0xf0, 0xb0, 0x02, 0xfc, 0xdd, 0xbe, 0x96, 0x5c, 0x46, 0x2c, 0xbf, 0x70,
+ 0x82, 0xf2, 0x59, 0x7f, 0x7e, 0x69, 0x3e, 0x8d, 0x59, 0x76, 0x76, 0xb2,
+ 0xf0, 0xf0, 0xd7, 0x3c, 0x7f, 0x98, 0x5f, 0x7a, 0x0f, 0xda, 0xca, 0x84,
+ 0x6d, 0xe0, 0xbb, 0xb7, 0x7c, 0xce, 0xe0, 0x81, 0x65, 0xfb, 0xfe, 0x60,
+ 0x8a, 0xd6, 0x54, 0x8f, 0x0f, 0x05, 0xef, 0xb3, 0x08, 0xd5, 0x95, 0xc3,
+ 0xc2, 0xf9, 0x0d, 0xe1, 0xe7, 0x96, 0x5e, 0x99, 0x8c, 0x59, 0x61, 0xc8,
+ 0xdd, 0x30, 0xe5, 0xff, 0xec, 0xec, 0x6c, 0x42, 0x66, 0xb5, 0x1b, 0xd6,
+ 0x5f, 0xfd, 0xb2, 0x20, 0xa0, 0xfb, 0x36, 0x7b, 0x6d, 0x65, 0x42, 0x2f,
+ 0x80, 0x4c, 0x49, 0x97, 0xfc, 0x2b, 0x94, 0x61, 0x0e, 0x0e, 0xb2, 0xff,
+ 0xde, 0xc9, 0xbc, 0xde, 0x8d, 0x42, 0xcb, 0x9f, 0xa5, 0x97, 0x8a, 0x37,
+ 0x16, 0x5f, 0xe7, 0xe3, 0xf8, 0x25, 0x3a, 0xca, 0x23, 0xe8, 0xf8, 0xb8,
+ 0x47, 0xab, 0x63, 0x26, 0x7a, 0x71, 0x79, 0x42, 0x50, 0x64, 0x3d, 0x42,
+ 0x95, 0xa5, 0x05, 0xcc, 0xcd, 0xa8, 0x5e, 0x9e, 0x14, 0x3e, 0x22, 0x28,
+ 0xc9, 0xb9, 0x0b, 0xff, 0xc6, 0x34, 0x12, 0xe1, 0x0e, 0xf7, 0x61, 0x4d,
+ 0x77, 0x02, 0xb2, 0xda, 0x59, 0x74, 0x69, 0x65, 0xd9, 0xe5, 0x97, 0xed,
+ 0x75, 0x2f, 0xc2, 0xcb, 0xd9, 0xbf, 0x16, 0x56, 0x1e, 0x31, 0x14, 0xd6,
+ 0xc4, 0x51, 0xf6, 0x23, 0xb6, 0x2c, 0x22, 0xe5, 0xf6, 0x1d, 0xbe, 0xb2,
+ 0xa1, 0x31, 0xfd, 0x42, 0xeb, 0xe8, 0x97, 0xbb, 0x0e, 0x96, 0x5d, 0xa0,
+ 0x2c, 0xb9, 0xf1, 0x65, 0x74, 0x6b, 0x34, 0x2f, 0x78, 0x9f, 0xeb, 0x2f,
+ 0x13, 0x71, 0x65, 0x8c, 0x14, 0x9b, 0x68, 0x1b, 0xba, 0x3c, 0xb2, 0xfb,
+ 0x5b, 0xdc, 0xeb, 0x2f, 0xee, 0xce, 0x51, 0xd0, 0x16, 0x5f, 0xc0, 0xe6,
+ 0x66, 0x32, 0xcb, 0xff, 0xcd, 0xb2, 0x26, 0x6f, 0xea, 0x3b, 0x0f, 0x6b,
+ 0x2f, 0x01, 0xfa, 0x59, 0x7d, 0x9f, 0x83, 0x16, 0x56, 0x1b, 0xf2, 0x1d,
+ 0xbf, 0xfc, 0xdb, 0x3d, 0x93, 0x37, 0x5c, 0xf6, 0x76, 0xb2, 0xe2, 0xe2,
+ 0xcb, 0xe2, 0x7f, 0xf1, 0x65, 0x48, 0xdb, 0x9c, 0x5a, 0xf4, 0x66, 0x96,
+ 0x5f, 0xfe, 0xed, 0xf4, 0xff, 0x6e, 0x41, 0x40, 0x16, 0x5a, 0x5e, 0x3e,
+ 0x31, 0x06, 0xeb, 0xa4, 0x56, 0xea, 0x10, 0x95, 0x0a, 0xe7, 0x67, 0x35,
+ 0x1a, 0x56, 0x2c, 0x76, 0x56, 0xc2, 0xd3, 0x12, 0x1c, 0xbc, 0x05, 0x7c,
+ 0x84, 0x6f, 0xc7, 0xc3, 0x19, 0x95, 0xf0, 0xce, 0x67, 0x16, 0x5f, 0xf0,
+ 0x3b, 0xf3, 0x69, 0xb2, 0x4b, 0x2f, 0x30, 0x87, 0x59, 0x73, 0x0d, 0x65,
+ 0x39, 0xb3, 0x10, 0x76, 0xf7, 0xa0, 0x96, 0x5e, 0xe6, 0xee, 0xea, 0xcb,
+ 0xed, 0x92, 0x01, 0xd6, 0x5e, 0xd6, 0x0d, 0x65, 0xfe, 0x7f, 0xc4, 0xdc,
+ 0x63, 0xac, 0xa3, 0x4f, 0x3f, 0xc3, 0x97, 0xfa, 0x24, 0x59, 0xd7, 0xf1,
+ 0x65, 0xfb, 0xb6, 0xea, 0x72, 0x59, 0x7f, 0xf3, 0xf7, 0x04, 0x39, 0xa5,
+ 0x1a, 0x9d, 0x65, 0x74, 0x7e, 0x1e, 0x2a, 0xb7, 0x16, 0x53, 0x1b, 0x4e,
+ 0x11, 0xdf, 0xc5, 0xa7, 0x77, 0xfa, 0xcb, 0xff, 0xef, 0xf0, 0x7a, 0xc6,
+ 0x37, 0xc6, 0x39, 0x4e, 0xb2, 0xf8, 0x87, 0x86, 0xac, 0xbd, 0xe0, 0x9d,
+ 0x65, 0xdb, 0xc6, 0xb2, 0xb6, 0x92, 0xb5, 0x18, 0x24, 0x93, 0x60, 0xc8,
+ 0x70, 0x6f, 0xa2, 0x36, 0x74, 0xd1, 0x1f, 0xa1, 0xac, 0xe4, 0x1c, 0x2b,
+ 0xfa, 0x90, 0x48, 0x8c, 0x1d, 0xbf, 0x61, 0x14, 0x4e, 0xb2, 0xdd, 0x2c,
+ 0xd1, 0xa6, 0xbc, 0x12, 0x92, 0xcb, 0xf7, 0x26, 0x82, 0x9d, 0x65, 0x61,
+ 0xf3, 0x9a, 0x45, 0xf1, 0xcb, 0xdb, 0x25, 0x3a, 0xcb, 0xf1, 0x1a, 0xd9,
+ 0xc5, 0x97, 0xef, 0x37, 0x18, 0x6b, 0x2f, 0x34, 0x1d, 0x65, 0xb5, 0x23,
+ 0xc2, 0xf1, 0x3d, 0xf3, 0xfd, 0xfb, 0x59, 0x4c, 0x79, 0x46, 0x14, 0x5f,
+ 0x04, 0x57, 0xc9, 0xd6, 0x5f, 0xf8, 0xc7, 0x06, 0x77, 0xe7, 0x07, 0x16,
+ 0x54, 0x1f, 0x46, 0x14, 0x5f, 0xfb, 0x8f, 0xd4, 0x13, 0x8f, 0x0d, 0x59,
+ 0x4c, 0x9c, 0xdf, 0xa1, 0x66, 0x50, 0x8a, 0xf9, 0x05, 0xff, 0xef, 0xfb,
+ 0x0e, 0x07, 0xd6, 0x6f, 0xc1, 0xac, 0xba, 0x3c, 0xb2, 0xc3, 0x59, 0x47,
+ 0x34, 0xe4, 0x2d, 0x63, 0x56, 0x5e, 0x20, 0x42, 0xcb, 0x88, 0x7b, 0x0d,
+ 0x6f, 0x04, 0xae, 0xcf, 0xac, 0xbf, 0xb3, 0x86, 0x39, 0x4e, 0xb2, 0xa1,
+ 0x33, 0x1c, 0x72, 0x74, 0xd0, 0x17, 0x10, 0xb5, 0xfe, 0x27, 0x33, 0x63,
+ 0xf7, 0x8b, 0x2f, 0x83, 0xc7, 0xed, 0x65, 0xff, 0x82, 0x3f, 0x34, 0x6f,
+ 0xd0, 0x9c, 0x59, 0x5a, 0x3e, 0x52, 0x23, 0xbd, 0xc1, 0xc2, 0xcb, 0xfe,
+ 0xe7, 0xf3, 0xb0, 0x81, 0xf1, 0x65, 0x1a, 0x7a, 0xae, 0x39, 0x50, 0x89,
+ 0x80, 0xbb, 0x5b, 0x8b, 0x2d, 0x8b, 0x29, 0x8d, 0x0e, 0xe8, 0x8d, 0xf7,
+ 0x45, 0x06, 0xac, 0xa3, 0x9e, 0x33, 0x91, 0xdf, 0xf6, 0x13, 0xcb, 0x92,
+ 0x32, 0x75, 0x97, 0xd2, 0xe3, 0x12, 0xcb, 0xef, 0x77, 0x1d, 0xac, 0xbf,
+ 0xf7, 0x64, 0xfe, 0x7e, 0xb3, 0xaf, 0xac, 0xa9, 0x22, 0xff, 0xa3, 0xa6,
+ 0x21, 0x09, 0x25, 0xf6, 0xb1, 0xce, 0xb2, 0xa0, 0xf7, 0x9c, 0xf6, 0xfe,
+ 0x8e, 0x47, 0xa3, 0x8b, 0x2f, 0xed, 0x4a, 0x3b, 0x6e, 0xd6, 0x56, 0x8f,
+ 0x6d, 0xcb, 0x2e, 0xfe, 0x2c, 0xa8, 0x5f, 0x53, 0x9c, 0xbf, 0x23, 0xbb,
+ 0x68, 0xdd, 0xf4, 0x8f, 0xe8, 0xcc, 0x9e, 0x11, 0x25, 0x19, 0xf0, 0x5e,
+ 0xc4, 0x21, 0xbf, 0xfc, 0x6b, 0xe7, 0x5f, 0xfc, 0x66, 0xf6, 0xed, 0x65,
+ 0xfe, 0x2c, 0xe7, 0xdd, 0xc9, 0x65, 0x1a, 0x7f, 0xbb, 0xd3, 0x6f, 0xb7,
+ 0x77, 0x63, 0x71, 0x65, 0xff, 0xf7, 0xd8, 0x83, 0x2c, 0xe0, 0xc2, 0xfa,
+ 0x92, 0xcb, 0x46, 0xc3, 0xfa, 0x10, 0xae, 0xff, 0xc7, 0x79, 0x67, 0x9b,
+ 0x5e, 0x75, 0x97, 0x36, 0xb4, 0x7c, 0xe0, 0x2a, 0xbf, 0xff, 0x8b, 0x0d,
+ 0xc2, 0xd9, 0xcf, 0xfb, 0x0e, 0x24, 0x01, 0x65, 0x42, 0x22, 0xb0, 0xb6,
+ 0xff, 0x05, 0xf8, 0xd3, 0x31, 0x8b, 0x29, 0x93, 0xe5, 0xf4, 0x72, 0x04,
+ 0x43, 0x7b, 0xd0, 0x4b, 0x2e, 0xf9, 0xd6, 0x5b, 0x6d, 0x65, 0x74, 0x6a,
+ 0xfc, 0x2f, 0x5d, 0x9f, 0x43, 0xa3, 0x5f, 0x0f, 0x4c, 0x62, 0xcb, 0xfb,
+ 0x32, 0x7c, 0xcf, 0xac, 0xb8, 0xdd, 0xeb, 0x2f, 0x60, 0x46, 0xb2, 0xa7,
+ 0x44, 0x28, 0xc8, 0xc8, 0xb3, 0x83, 0x57, 0x98, 0xbe, 0xb2, 0xfa, 0x3b,
+ 0xcd, 0x2c, 0xbe, 0xf4, 0x6f, 0xc5, 0x97, 0xf3, 0xef, 0x69, 0x98, 0xc5,
+ 0x94, 0x74, 0x48, 0x10, 0xdf, 0xc8, 0x84, 0x23, 0xbf, 0xc1, 0xd4, 0xe7,
+ 0x8c, 0xfa, 0xcb, 0xfe, 0xe4, 0x1c, 0x7e, 0x82, 0xed, 0x65, 0xcc, 0x58,
+ 0x7d, 0xa6, 0x9a, 0x54, 0x23, 0x58, 0x70, 0xaa, 0xbd, 0x20, 0xf1, 0x65,
+ 0xfc, 0x37, 0xd0, 0x36, 0xf1, 0x65, 0xef, 0x09, 0xbd, 0x65, 0xff, 0x41,
+ 0xcb, 0x3b, 0xd3, 0x01, 0x65, 0x86, 0xb2, 0xf7, 0x39, 0x8b, 0x2c, 0x38,
+ 0x35, 0xae, 0x23, 0x52, 0x45, 0x57, 0x08, 0x02, 0xcb, 0x7f, 0x79, 0xdb,
+ 0xbc, 0x25, 0x97, 0xfa, 0x58, 0xdc, 0xe0, 0x61, 0x65, 0xfc, 0x3c, 0x29,
+ 0x7b, 0x16, 0x5f, 0xff, 0xfe, 0xce, 0x7b, 0x35, 0x04, 0xfd, 0x4b, 0xd1,
+ 0xff, 0xc7, 0x5e, 0x83, 0xac, 0xa8, 0x46, 0xab, 0x19, 0x1c, 0xb2, 0xff,
+ 0xdf, 0x83, 0xf5, 0xdb, 0x75, 0x9a, 0x59, 0x7e, 0xf6, 0x69, 0xb8, 0xb2,
+ 0xf1, 0x34, 0xba, 0x3e, 0x8f, 0xa0, 0xdf, 0xf6, 0x02, 0x09, 0xc7, 0x86,
+ 0xac, 0xbf, 0xa3, 0xf8, 0xc1, 0x15, 0xac, 0xa7, 0x3e, 0x70, 0x1b, 0xdf,
+ 0xf6, 0x4f, 0x83, 0xc2, 0x8d, 0xc5, 0x95, 0x0a, 0xa3, 0x27, 0x8c, 0x06,
+ 0x50, 0x96, 0x04, 0x26, 0x88, 0x86, 0xff, 0xf1, 0x7f, 0x6f, 0x26, 0x93,
+ 0xea, 0x71, 0xc2, 0xcb, 0xff, 0xf8, 0xa5, 0x1f, 0x7f, 0x71, 0x9f, 0xe0,
+ 0x10, 0xa4, 0xb2, 0xfb, 0xff, 0xcd, 0xc5, 0x97, 0xfd, 0x19, 0x2f, 0x63,
+ 0x4b, 0x8b, 0x2b, 0x87, 0xb9, 0xf2, 0x5b, 0xf0, 0xe6, 0xf0, 0x77, 0x16,
+ 0x57, 0x47, 0x9e, 0x44, 0x55, 0x89, 0xba, 0xb2, 0x73, 0xc6, 0x0b, 0x7e,
+ 0xd1, 0x36, 0x1a, 0xb2, 0xfd, 0x1e, 0x6e, 0xa4, 0xb2, 0xe3, 0xc9, 0x65,
+ 0xff, 0x3e, 0x76, 0x3c, 0xd0, 0x19, 0x65, 0x6c, 0x3f, 0x71, 0x94, 0x78,
+ 0x5e, 0xff, 0x75, 0xc1, 0x09, 0xa0, 0x6b, 0x2b, 0x47, 0xca, 0x46, 0x35,
+ 0x09, 0x92, 0x34, 0x60, 0x77, 0xfa, 0x5c, 0x28, 0x03, 0x9d, 0x65, 0xf9,
+ 0xfa, 0xfc, 0xf0, 0xb2, 0xa0, 0xf6, 0xc8, 0xca, 0xfe, 0xd1, 0xb8, 0x1d,
+ 0x4e, 0xb2, 0xfe, 0x6d, 0x4e, 0x10, 0x62, 0xcb, 0xf7, 0xe3, 0x0b, 0xb5,
+ 0x97, 0xdd, 0x7e, 0x0e, 0xb2, 0x8d, 0x3c, 0xae, 0x89, 0xef, 0xfa, 0x42,
+ 0x7d, 0xbc, 0xc5, 0xf5, 0x97, 0xfe, 0xcd, 0xc1, 0xfa, 0x3d, 0x1f, 0xe2,
+ 0xcb, 0xff, 0xd1, 0x9d, 0x7f, 0xd1, 0xf2, 0x80, 0x71, 0x65, 0xd0, 0x05,
+ 0x97, 0x78, 0xeb, 0x2f, 0xff, 0xf6, 0x83, 0x26, 0x2c, 0x08, 0x36, 0x67,
+ 0x08, 0x2f, 0x3a, 0xca, 0xed, 0x11, 0xfc, 0x16, 0xf8, 0xbd, 0x42, 0xa4,
+ 0xf9, 0xcc, 0x19, 0xe1, 0xc9, 0x08, 0xe7, 0xe8, 0x21, 0x86, 0xc5, 0xf8,
+ 0x6e, 0x41, 0x3a, 0xcb, 0xff, 0x04, 0x19, 0xde, 0x6b, 0x4f, 0x25, 0x97,
+ 0xff, 0x05, 0xe4, 0x70, 0xff, 0xd0, 0x11, 0x5a, 0xcb, 0xa0, 0xeb, 0x2b,
+ 0x11, 0x8b, 0xa2, 0x72, 0x3f, 0xe2, 0x4d, 0xe9, 0xdb, 0x4b, 0x2f, 0xfb,
+ 0x8d, 0xd7, 0xe6, 0x94, 0x74, 0xb2, 0xfd, 0xcf, 0xf3, 0x3e, 0xb2, 0xb8,
+ 0x7c, 0x81, 0x3c, 0xbf, 0x0a, 0xda, 0x66, 0x31, 0x65, 0xfc, 0x51, 0x30,
+ 0x5c, 0x45, 0x94, 0x13, 0xdb, 0x10, 0xb6, 0xec, 0xf2, 0xcb, 0xc6, 0x18,
+ 0x62, 0x4b, 0xff, 0xdf, 0x6f, 0xf3, 0xcd, 0xb6, 0x26, 0xa2, 0x49, 0x05,
+ 0x9a, 0x0a, 0x35, 0x3b, 0x76, 0x84, 0x0b, 0xbe, 0xfc, 0x8c, 0x26, 0xd7,
+ 0xfc, 0x2b, 0x6d, 0x4e, 0x10, 0x61, 0x2c, 0xba, 0x66, 0x59, 0x7f, 0xff,
+ 0x4a, 0x0b, 0x3f, 0xe6, 0xcf, 0xc1, 0xdb, 0x52, 0x59, 0x5a, 0x3e, 0xff,
+ 0x8b, 0xdf, 0xc7, 0x10, 0xb3, 0x7e, 0x2c, 0xbf, 0x67, 0x02, 0x5f, 0x59,
+ 0x4c, 0x7f, 0x0e, 0x44, 0x45, 0xf7, 0xff, 0xe8, 0xd4, 0xf1, 0xe7, 0x6d,
+ 0x69, 0x8f, 0xb5, 0xed, 0x25, 0x95, 0x26, 0xc7, 0xe4, 0x70, 0x9d, 0xc8,
+ 0x53, 0xf7, 0x1d, 0x1f, 0x44, 0xec, 0x3b, 0x34, 0x36, 0xb5, 0x2a, 0xf0,
+ 0xf1, 0xe8, 0x7a, 0x35, 0x80, 0x42, 0x0c, 0xa5, 0x37, 0xf2, 0x32, 0xdf,
+ 0xc7, 0xe4, 0x14, 0xfd, 0xf1, 0x92, 0x6e, 0x96, 0x5f, 0xf7, 0x52, 0xe7,
+ 0x30, 0x6f, 0xf5, 0x97, 0xf6, 0xbf, 0x01, 0x15, 0xf1, 0x65, 0xcd, 0xb6,
+ 0xb2, 0xfd, 0x9a, 0xf8, 0x7c, 0xb2, 0xb4, 0x78, 0x22, 0x0c, 0xdb, 0x16,
+ 0x5b, 0x16, 0x6e, 0x16, 0x17, 0xda, 0x27, 0xde, 0xb2, 0xf6, 0x39, 0x2c,
+ 0xb9, 0xcc, 0x59, 0x50, 0x9a, 0xb0, 0xce, 0xb1, 0xcc, 0xd3, 0x36, 0x22,
+ 0xd1, 0x19, 0xc6, 0xaf, 0xff, 0xe2, 0xcf, 0xfb, 0x25, 0xa8, 0xf3, 0xb7,
+ 0xe3, 0xcb, 0x2f, 0x03, 0x98, 0xb2, 0xff, 0x3c, 0xa6, 0xf3, 0x75, 0xf5,
+ 0x97, 0xd2, 0x82, 0x92, 0xcb, 0x3a, 0xcb, 0xd1, 0xee, 0x2c, 0xae, 0x8d,
+ 0x63, 0x08, 0x5f, 0xfa, 0x3b, 0xd9, 0x85, 0x01, 0x15, 0xf1, 0x65, 0xff,
+ 0xfc, 0xff, 0x6f, 0x39, 0xf6, 0x67, 0x23, 0x35, 0x84, 0xb2, 0xff, 0xee,
+ 0x3f, 0x5c, 0xe6, 0x10, 0x36, 0xf1, 0x65, 0xff, 0xe6, 0xef, 0x91, 0xb7,
+ 0x9f, 0x94, 0xb3, 0x8b, 0x28, 0x69, 0xea, 0x4c, 0x6b, 0xa4, 0xd3, 0x90,
+ 0x92, 0x27, 0xd6, 0x77, 0xa3, 0xdf, 0x6b, 0xd8, 0x4b, 0x2f, 0xff, 0xc5,
+ 0x8d, 0xc6, 0xd4, 0x07, 0xf3, 0x46, 0x0d, 0x65, 0x32, 0x36, 0xdd, 0x9c,
+ 0x24, 0x37, 0xe1, 0x24, 0xc0, 0xe2, 0xcb, 0xd9, 0x10, 0xb2, 0xfc, 0x27,
+ 0x0c, 0xcf, 0x2c, 0xa9, 0xcf, 0x13, 0x83, 0x54, 0x34, 0x48, 0x69, 0xb6,
+ 0xfe, 0x2d, 0x82, 0x72, 0x31, 0x65, 0xf6, 0x9c, 0xec, 0xb2, 0xfb, 0xf1,
+ 0xd1, 0x8b, 0x2b, 0x17, 0x1e, 0x3b, 0x58, 0xf4, 0xac, 0xb7, 0x85, 0xf0,
+ 0x08, 0xc2, 0x5e, 0x61, 0x0d, 0xff, 0xfb, 0xe1, 0x13, 0xe5, 0x00, 0x7f,
+ 0x80, 0x42, 0x92, 0xcb, 0xf7, 0xff, 0x84, 0x75, 0x97, 0xff, 0xfa, 0x33,
+ 0x98, 0x5a, 0x89, 0x31, 0xf3, 0xa9, 0x4c, 0x15, 0x94, 0xc8, 0x87, 0x22,
+ 0x7b, 0x8c, 0xf2, 0xcb, 0xff, 0xd0, 0x5d, 0x89, 0xa7, 0x03, 0x7f, 0xd0,
+ 0xb2, 0xf9, 0xe7, 0x72, 0x59, 0x7e, 0xff, 0xb0, 0x0e, 0xb2, 0xba, 0x3c,
+ 0x82, 0x21, 0xbf, 0x8f, 0xb3, 0xd8, 0x07, 0x59, 0x7f, 0x19, 0xcc, 0xc2,
+ 0x9d, 0x65, 0x41, 0xff, 0xe1, 0x13, 0x17, 0xdf, 0xda, 0xc2, 0x0c, 0x69,
+ 0x65, 0xf4, 0x72, 0x37, 0xac, 0xbf, 0xfa, 0x09, 0xff, 0x28, 0x35, 0xcc,
+ 0xfa, 0xca, 0x14, 0x22, 0x4f, 0xc5, 0x81, 0x23, 0xbd, 0xb1, 0xfb, 0x59,
+ 0x50, 0xac, 0xea, 0x50, 0xde, 0xec, 0x84, 0x03, 0x1c, 0x8c, 0x47, 0xf0,
+ 0xbf, 0xdd, 0x34, 0xbf, 0xa4, 0x21, 0xce, 0xdb, 0x8b, 0x2f, 0xb3, 0x91,
+ 0x25, 0x97, 0xda, 0xf3, 0x08, 0xb2, 0xfe, 0x97, 0x3e, 0xd1, 0xd2, 0xcb,
+ 0xe3, 0x89, 0x04, 0xb2, 0xf9, 0x87, 0x87, 0x59, 0x7c, 0xee, 0x40, 0x59,
+ 0x63, 0x20, 0xf0, 0x4d, 0x21, 0xb8, 0x27, 0x59, 0x7f, 0x8c, 0x79, 0xb2,
+ 0x51, 0xb8, 0xb2, 0xfd, 0xba, 0x19, 0x9a, 0x65, 0x94, 0xc8, 0xa4, 0xf1,
+ 0x4f, 0x05, 0xc2, 0x6f, 0x7f, 0xcc, 0x7f, 0x74, 0xfb, 0x9f, 0xe2, 0xcb,
+ 0xfb, 0xb7, 0xf7, 0xb0, 0x6b, 0x2a, 0x0f, 0xac, 0x27, 0xb7, 0xd0, 0x63,
+ 0x98, 0xb2, 0xff, 0x43, 0xeb, 0xc6, 0x38, 0xd2, 0x5c, 0x61, 0x89, 0x28,
+ 0x67, 0x98, 0x61, 0x9d, 0xef, 0xb6, 0xe2, 0x41, 0x66, 0x8e, 0xfe, 0xeb,
+ 0xb6, 0xe7, 0x99, 0x65, 0xe3, 0xc1, 0xd6, 0x5e, 0x90, 0x7e, 0xb2, 0xa0,
+ 0xdc, 0x84, 0x72, 0xa1, 0x5d, 0xf0, 0xcc, 0xb0, 0x87, 0xa2, 0x36, 0x2e,
+ 0x9a, 0x30, 0x73, 0xc2, 0x9c, 0x04, 0x3c, 0x84, 0x97, 0xcc, 0x76, 0xda,
+ 0x2f, 0x88, 0x7e, 0x75, 0x97, 0xb1, 0xf7, 0x16, 0x5e, 0xd6, 0x0d, 0x65,
+ 0x61, 0xed, 0xe8, 0x87, 0x78, 0xf5, 0xef, 0x46, 0x96, 0x5f, 0xd8, 0x02,
+ 0x8f, 0xf1, 0x65, 0xc6, 0x71, 0x65, 0xb1, 0x65, 0xba, 0xc3, 0x51, 0xf1,
+ 0x8b, 0xee, 0xa4, 0x29, 0xe9, 0x65, 0xbc, 0xb2, 0xff, 0xdc, 0x19, 0x40,
+ 0xfd, 0x1f, 0xe2, 0xca, 0x83, 0xcf, 0xe0, 0x8d, 0x42, 0x30, 0x30, 0x9c,
+ 0x2f, 0x17, 0xff, 0xfd, 0x86, 0x64, 0xbd, 0x8d, 0x2e, 0x75, 0xc6, 0xfb,
+ 0x14, 0xeb, 0x2e, 0xf4, 0xcb, 0x2f, 0xf7, 0x99, 0xe5, 0xf6, 0x9d, 0x65,
+ 0xff, 0xbe, 0xda, 0x70, 0x6e, 0xff, 0x3c, 0xb2, 0xff, 0x98, 0xc2, 0xcf,
+ 0xb0, 0x40, 0xb2, 0xfe, 0xfc, 0x31, 0x09, 0xc5, 0x97, 0xe3, 0xb4, 0xcc,
+ 0x62, 0xca, 0x83, 0xd6, 0x62, 0xdb, 0xf3, 0x68, 0x71, 0x3a, 0xcb, 0xfc,
+ 0xfa, 0xff, 0x09, 0x8d, 0x59, 0x7f, 0x75, 0xcc, 0xf8, 0x93, 0xac, 0xbf,
+ 0xc6, 0x7f, 0x3c, 0x38, 0x3a, 0xca, 0x83, 0xe5, 0x73, 0x1b, 0xff, 0xdc,
+ 0xc3, 0x70, 0x3a, 0x71, 0xc7, 0xa1, 0x65, 0xf0, 0x83, 0xf4, 0x2c, 0xa1,
+ 0x4a, 0xe2, 0x5c, 0x0e, 0x4a, 0x31, 0x4c, 0x2e, 0xed, 0x9f, 0xa1, 0x86,
+ 0x33, 0xdc, 0x41, 0xd4, 0x23, 0xbc, 0x40, 0xe5, 0x05, 0x09, 0x8e, 0x10,
+ 0x05, 0x26, 0xf4, 0xcf, 0xa5, 0x97, 0xfd, 0xff, 0x60, 0x03, 0x1d, 0x08,
+ 0xb2, 0xff, 0xff, 0xce, 0xdf, 0x8f, 0x16, 0x7f, 0xcc, 0x24, 0xa3, 0x7b,
+ 0x10, 0x16, 0x5f, 0xbb, 0xc3, 0xc7, 0x16, 0x5e, 0x09, 0x0d, 0x65, 0xff,
+ 0xef, 0x63, 0x4e, 0x78, 0x76, 0x93, 0xf1, 0x65, 0xff, 0xec, 0xf6, 0x17,
+ 0xf9, 0x9b, 0xca, 0x3a, 0x59, 0x50, 0x9c, 0xcf, 0x43, 0xbe, 0x3b, 0x76,
+ 0xb0, 0x14, 0x7c, 0x70, 0xc4, 0x8b, 0x9b, 0xa5, 0x97, 0xa0, 0xbe, 0xb2,
+ 0xe6, 0xd2, 0xca, 0x9c, 0xd8, 0xe0, 0xdd, 0xfe, 0x93, 0x1f, 0xdd, 0x3e,
+ 0xe2, 0xcb, 0xe7, 0xd4, 0x49, 0x65, 0xf7, 0x58, 0x19, 0x96, 0x5f, 0xf8,
+ 0x31, 0xa3, 0x5c, 0x4f, 0xb4, 0x96, 0x5f, 0xf3, 0xf5, 0xb3, 0xae, 0x61,
+ 0x1a, 0xb2, 0xa7, 0x4c, 0x6b, 0xa2, 0x13, 0x9b, 0xf8, 0x84, 0x89, 0x3e,
+ 0x81, 0x7d, 0xed, 0xc6, 0x3a, 0xcb, 0xc5, 0x00, 0x59, 0x5b, 0x0f, 0x03,
+ 0x84, 0xb7, 0xf7, 0xdc, 0xe7, 0x83, 0xac, 0xb1, 0xf0, 0xf4, 0x7a, 0x24,
+ 0xbf, 0xdd, 0x7b, 0x26, 0xf3, 0x69, 0x65, 0x41, 0xee, 0xe1, 0x45, 0xff,
+ 0xa3, 0xaf, 0x41, 0xfb, 0xf3, 0x4c, 0xb2, 0xf9, 0xf9, 0xd3, 0xac, 0xbf,
+ 0xe9, 0x73, 0xcf, 0xdc, 0x10, 0xd6, 0x5e, 0x07, 0xfc, 0xb2, 0xa4, 0x7f,
+ 0x1d, 0x11, 0x00, 0xe6, 0xff, 0xff, 0xda, 0xc1, 0xf1, 0xf7, 0x1b, 0xaf,
+ 0x3b, 0x4a, 0x07, 0xe0, 0x9a, 0xb2, 0xc0, 0x59, 0x4e, 0x8b, 0x1e, 0x18,
+ 0x08, 0xe1, 0x7e, 0x6e, 0xf1, 0xce, 0xb2, 0xa1, 0x73, 0xbe, 0x4c, 0xb9,
+ 0x1b, 0x13, 0x46, 0x8f, 0xa2, 0x07, 0x8d, 0xa8, 0x8c, 0x2f, 0xe2, 0x1f,
+ 0x38, 0xc7, 0x59, 0x7e, 0xed, 0xe7, 0xc3, 0x16, 0x5f, 0xa3, 0x43, 0xc2,
+ 0x59, 0x58, 0x7f, 0xa4, 0x5b, 0xf2, 0xab, 0xf4, 0x6d, 0xb7, 0x82, 0xb2,
+ 0xfc, 0x12, 0x2c, 0x35, 0x65, 0xed, 0x37, 0x96, 0x57, 0x67, 0x86, 0x44,
+ 0xf7, 0xdb, 0xbf, 0x63, 0x56, 0x5d, 0x02, 0x2c, 0xae, 0x1b, 0xdd, 0xb2,
+ 0x6b, 0xff, 0xa0, 0x11, 0xe3, 0x93, 0x9b, 0xe6, 0x59, 0x61, 0x42, 0xcb,
+ 0xfb, 0xd0, 0x46, 0x3f, 0x4b, 0x2f, 0xfc, 0x53, 0x46, 0x14, 0xf9, 0xd7,
+ 0xd6, 0x50, 0xcf, 0xb5, 0xcb, 0xaf, 0xfe, 0x61, 0xfa, 0x3b, 0x80, 0x39,
+ 0x01, 0x65, 0xf1, 0x8f, 0x07, 0x59, 0x7e, 0x7e, 0x4e, 0xda, 0x59, 0x7d,
+ 0xa6, 0x0c, 0xeb, 0x8b, 0xd5, 0x7b, 0xb0, 0xce, 0xb8, 0xbd, 0x57, 0xfe,
+ 0xc6, 0xdf, 0x85, 0x83, 0x79, 0x2e, 0x2f, 0x55, 0xf9, 0xcb, 0xa9, 0x0b,
+ 0x1a, 0x29, 0xb8, 0x60, 0x61, 0x65, 0xcf, 0xba, 0xb2, 0x86, 0x99, 0xb9,
+ 0xe1, 0x9c, 0x4a, 0x17, 0xe3, 0x7e, 0xee, 0x4b, 0x2f, 0x10, 0x67, 0x59,
+ 0x4e, 0x78, 0x9f, 0x27, 0xa6, 0x44, 0xd1, 0x3c, 0xd4, 0x2e, 0x2d, 0x0c,
+ 0xb7, 0x1b, 0x59, 0x7f, 0x44, 0x87, 0x43, 0x78, 0x41, 0x70, 0x87, 0xe8,
+ 0x61, 0x8f, 0xce, 0xff, 0x13, 0x9f, 0xd1, 0x83, 0x59, 0x76, 0xd5, 0xb4,
+ 0x2c, 0xbc, 0xd1, 0xa5, 0x94, 0x28, 0x37, 0x9e, 0x21, 0xbf, 0xfb, 0x4c,
+ 0x78, 0xdc, 0x2c, 0x3f, 0x50, 0xb2, 0xa4, 0x7d, 0x73, 0x12, 0xde, 0x27,
+ 0x1a, 0xcb, 0xdc, 0x9d, 0xd6, 0x53, 0x1b, 0x81, 0x06, 0xef, 0xf7, 0xdb,
+ 0x51, 0xde, 0x6f, 0x59, 0x71, 0xd9, 0x65, 0x41, 0xe5, 0xce, 0x6b, 0x7e,
+ 0xc3, 0xe9, 0xfa, 0x59, 0x43, 0x45, 0xb1, 0x36, 0x70, 0x8a, 0xfd, 0x2c,
+ 0xdf, 0x12, 0x59, 0x7b, 0x35, 0x0b, 0x2f, 0x6f, 0xc1, 0xac, 0xae, 0xd5,
+ 0x3d, 0x75, 0x0d, 0x86, 0x8c, 0x47, 0x45, 0xfe, 0x29, 0x08, 0xdd, 0x8c,
+ 0x59, 0x7f, 0x98, 0xc8, 0x61, 0xe1, 0xd6, 0x59, 0xb0, 0xf1, 0x26, 0x12,
+ 0xbc, 0xfa, 0x9d, 0x65, 0x2c, 0xb1, 0x76, 0x6a, 0x26, 0x1d, 0xbf, 0xbc,
+ 0xf3, 0x6a, 0x27, 0x59, 0x7f, 0x37, 0x5c, 0xf6, 0x76, 0xb2, 0xfb, 0xd8,
+ 0xd3, 0x2c, 0xbf, 0xa3, 0x7e, 0x7b, 0xd0, 0xb2, 0xfd, 0x9f, 0xe6, 0x4c,
+ 0xb3, 0xc6, 0xba, 0xff, 0xff, 0xfb, 0x3a, 0xe3, 0x61, 0x9b, 0x33, 0xa9,
+ 0x71, 0xbf, 0xc6, 0xe8, 0x63, 0x0c, 0xeb, 0x2f, 0xfd, 0x1d, 0x96, 0x4d,
+ 0xe0, 0xea, 0x65, 0x94, 0xc8, 0xc5, 0x28, 0x42, 0x5f, 0xff, 0x98, 0x87,
+ 0xb0, 0x4f, 0xb7, 0x1d, 0x88, 0x32, 0x59, 0x7c, 0xf3, 0xf9, 0x96, 0x56,
+ 0x2a, 0x71, 0x62, 0x89, 0x8b, 0xf4, 0x5e, 0x4a, 0x1f, 0x87, 0xee, 0xf2,
+ 0x6d, 0xb5, 0x6b, 0xc1, 0xd4, 0x96, 0x5f, 0xf8, 0xee, 0x3d, 0x47, 0xfd,
+ 0x83, 0x59, 0x7f, 0x3f, 0xc0, 0x21, 0x49, 0x65, 0xfa, 0x7e, 0xfd, 0x1a,
+ 0x59, 0x7f, 0x9d, 0xcc, 0x03, 0xff, 0x8b, 0x2e, 0x13, 0x8b, 0x28, 0x67,
+ 0x97, 0xe3, 0x3b, 0xff, 0x0e, 0x3e, 0xf2, 0xcd, 0xee, 0x35, 0x97, 0xe6,
+ 0x9e, 0x76, 0xd2, 0xcb, 0xf4, 0x11, 0x04, 0xeb, 0x2d, 0x2f, 0x9e, 0x78,
+ 0x85, 0x35, 0xb1, 0x3d, 0x78, 0x1d, 0x9c, 0xfb, 0x0b, 0x8d, 0x75, 0x39,
+ 0x13, 0xc2, 0x3a, 0xfc, 0xc2, 0xcc, 0x30, 0xc4, 0x97, 0xfe, 0x35, 0xfa,
+ 0xd9, 0xe7, 0x3b, 0x71, 0x65, 0xa2, 0x47, 0xde, 0x72, 0xdb, 0xb3, 0xcb,
+ 0x2e, 0xc1, 0xac, 0xbf, 0x7c, 0x02, 0x14, 0x96, 0x51, 0xa6, 0xfd, 0xc5,
+ 0xaf, 0xcf, 0xae, 0xe3, 0xeb, 0x2e, 0x6d, 0x2c, 0xaf, 0x1b, 0xe0, 0x94,
+ 0x5b, 0xb5, 0x97, 0x38, 0xd6, 0x5f, 0xda, 0x7e, 0x79, 0xe4, 0xb2, 0xdd,
+ 0x2c, 0xb9, 0x8c, 0x59, 0x70, 0x80, 0x59, 0x53, 0x1a, 0xf0, 0x0b, 0xde,
+ 0x93, 0x8d, 0x65, 0xc6, 0x18, 0xb2, 0xa4, 0x8d, 0xbc, 0x16, 0xec, 0xb5,
+ 0x90, 0x78, 0x44, 0x60, 0xe5, 0xc2, 0x01, 0x20, 0xb3, 0xd7, 0xa7, 0x4d,
+ 0xbf, 0xf1, 0xa2, 0x5f, 0xec, 0x3b, 0x0e, 0x70, 0xf1, 0x65, 0xff, 0xfc,
+ 0x0d, 0xbc, 0xd4, 0x7d, 0xbb, 0x61, 0xcf, 0x05, 0x0b, 0x2f, 0x67, 0x5f,
+ 0x59, 0x6c, 0x23, 0xfa, 0xe2, 0xed, 0x79, 0x1a, 0x9c, 0x85, 0x75, 0xff,
+ 0x30, 0xf0, 0xed, 0x33, 0x18, 0xb2, 0xff, 0xff, 0xa5, 0xe8, 0x1c, 0x37,
+ 0x40, 0xd6, 0x0e, 0x34, 0xdd, 0x01, 0x65, 0xff, 0xff, 0x47, 0x9d, 0xbf,
+ 0x12, 0x08, 0xf0, 0x4c, 0xd7, 0xc3, 0xe5, 0x97, 0xff, 0x9c, 0x79, 0x84,
+ 0x6f, 0x39, 0x84, 0x05, 0x97, 0xde, 0x0b, 0x9b, 0x09, 0xa7, 0x61, 0xce,
+ 0x99, 0xce, 0xcd, 0x78, 0xa3, 0xcb, 0x2f, 0xff, 0xe9, 0x3f, 0x39, 0x19,
+ 0x38, 0x64, 0x3d, 0x13, 0x98, 0xb2, 0xd0, 0x34, 0x65, 0x9a, 0xa8, 0xc3,
+ 0x75, 0xc5, 0x4e, 0xdf, 0x94, 0x83, 0x7d, 0x2f, 0x37, 0x16, 0x5f, 0xcf,
+ 0x3e, 0x61, 0x1a, 0xb2, 0xfe, 0x63, 0xf7, 0x85, 0xda, 0xcb, 0xe7, 0x9f,
+ 0x9e, 0x59, 0x5a, 0x3d, 0x1e, 0x17, 0x56, 0xc5, 0xea, 0x59, 0x2a, 0x8d,
+ 0x7f, 0xa8, 0xe4, 0x1a, 0x5b, 0x99, 0x16, 0x70, 0x8b, 0xef, 0xd6, 0xda,
+ 0x96, 0x5e, 0x77, 0x3a, 0xcb, 0xde, 0x6f, 0xac, 0xb6, 0xf1, 0x49, 0xe6,
+ 0xf8, 0x58, 0x41, 0xbb, 0xfe, 0xcf, 0xfa, 0x35, 0xfc, 0xed, 0x65, 0xc6,
+ 0xba, 0xcb, 0xec, 0x20, 0xcc, 0xb2, 0xff, 0xfd, 0xc7, 0xff, 0x0b, 0x39,
+ 0x1d, 0x03, 0xf9, 0xc5, 0x95, 0xd1, 0xfb, 0xfc, 0x8a, 0xed, 0x4c, 0xb2,
+ 0xed, 0x42, 0xca, 0x83, 0x5d, 0x83, 0x15, 0x0c, 0xfa, 0x39, 0x42, 0xa7,
+ 0x25, 0x60, 0x34, 0xa5, 0x2f, 0x43, 0x69, 0xe7, 0xb3, 0x01, 0x0c, 0xf2,
+ 0x3c, 0xf9, 0xc8, 0x61, 0x1d, 0xb6, 0xa3, 0x7f, 0xff, 0xff, 0xff, 0xb6,
+ 0xf0, 0xef, 0x26, 0xe0, 0x30, 0x1e, 0x76, 0x94, 0x0f, 0xc1, 0x36, 0x18,
+ 0x9f, 0xf1, 0x27, 0xdf, 0xe7, 0x92, 0xcb, 0xf7, 0x9b, 0x7e, 0x4e, 0xb2,
+ 0x99, 0x1c, 0xfc, 0x85, 0xed, 0xff, 0x78, 0x3f, 0xf6, 0x69, 0xb8, 0xb2,
+ 0xf7, 0x1e, 0x65, 0x97, 0xfe, 0x1c, 0x14, 0xc1, 0xf3, 0xfa, 0x16, 0x5f,
+ 0x1e, 0x3a, 0x92, 0xcb, 0xff, 0x66, 0xf8, 0x19, 0x67, 0xf0, 0x0b, 0x2e,
+ 0xc2, 0x59, 0x6c, 0xe8, 0xf4, 0xf7, 0x9f, 0x5f, 0xbd, 0xf8, 0x91, 0xd6,
+ 0x5c, 0x20, 0x16, 0x53, 0x23, 0x83, 0x4e, 0xde, 0x2a, 0x01, 0x45, 0xe6,
+ 0x21, 0xac, 0xbf, 0xf9, 0x86, 0xff, 0x6e, 0x64, 0xb3, 0xcb, 0x2e, 0x7d,
+ 0xd5, 0x97, 0xb3, 0xaf, 0xac, 0xaf, 0x1f, 0xc7, 0xd0, 0xb7, 0x46, 0x6f,
+ 0xec, 0xd4, 0x7f, 0x98, 0xb2, 0xff, 0xf9, 0xfa, 0x94, 0x4b, 0x07, 0xc8,
+ 0x94, 0x12, 0xca, 0xc4, 0x56, 0x31, 0x91, 0x16, 0x5f, 0xdc, 0x7f, 0x34,
+ 0x01, 0x65, 0xf8, 0xbf, 0xcc, 0x25, 0x97, 0xfe, 0x10, 0xa4, 0x59, 0xff,
+ 0xe4, 0xeb, 0x29, 0x8f, 0x94, 0x04, 0xd7, 0xed, 0x3e, 0xfd, 0xd7, 0x59,
+ 0x52, 0x5c, 0x21, 0x19, 0x3f, 0x47, 0x2c, 0x3b, 0xa8, 0xc7, 0xbc, 0x78,
+ 0x51, 0x9f, 0xf0, 0xb7, 0xf0, 0x91, 0xde, 0x43, 0x7e, 0xda, 0x85, 0x1b,
+ 0x5e, 0xdf, 0xd6, 0x5f, 0xe9, 0xfe, 0x7f, 0x60, 0x1d, 0x65, 0xf6, 0x13,
+ 0x1a, 0xb2, 0xa4, 0x88, 0xf3, 0x9d, 0x6f, 0x34, 0xbb, 0xbd, 0xd5, 0x97,
+ 0xb9, 0x2f, 0x2c, 0xa2, 0x37, 0x1f, 0x1b, 0xbf, 0xff, 0xba, 0xe1, 0x3f,
+ 0x3d, 0x92, 0xcf, 0x36, 0xbc, 0xeb, 0x2f, 0xb3, 0xa9, 0xf7, 0xac, 0xbe,
+ 0xcf, 0xcc, 0x75, 0x97, 0xfb, 0x83, 0x73, 0xc7, 0xfb, 0x59, 0x7f, 0x87,
+ 0x84, 0x19, 0x67, 0x16, 0x57, 0x47, 0xcc, 0x46, 0x97, 0xdd, 0x70, 0x20,
+ 0x59, 0x71, 0x76, 0xb2, 0xa0, 0xdd, 0xb9, 0x25, 0xfe, 0x13, 0xe5, 0x93,
+ 0xb6, 0x96, 0x5f, 0x8b, 0xb3, 0x47, 0xd2, 0xcb, 0xe7, 0xdd, 0xc2, 0x59,
+ 0x79, 0xb8, 0xcb, 0x29, 0xcf, 0xa7, 0x85, 0x7f, 0x23, 0xbf, 0xb3, 0xb8,
+ 0xf4, 0x1d, 0x65, 0x42, 0xb0, 0x7c, 0x6a, 0x62, 0x0d, 0x2d, 0x1c, 0x99,
+ 0xe1, 0x12, 0x05, 0xd2, 0x1f, 0x0c, 0x27, 0x4c, 0x2e, 0xbf, 0xf4, 0x08,
+ 0x00, 0xca, 0x4f, 0xe0, 0xac, 0xbd, 0x98, 0x6a, 0xcb, 0xe9, 0x40, 0x38,
+ 0xb2, 0x86, 0x6f, 0xb0, 0x72, 0xa7, 0x44, 0xf7, 0x4f, 0xd7, 0xdf, 0x0b,
+ 0x92, 0xcb, 0xfe, 0xf3, 0x0d, 0x85, 0x70, 0x4c, 0xb2, 0xff, 0xf9, 0x8d,
+ 0xc6, 0x3e, 0xa0, 0x22, 0xb7, 0xf7, 0x16, 0x5f, 0xe7, 0x96, 0x0f, 0x5c,
+ 0xe2, 0xcb, 0xe8, 0xc1, 0x06, 0xb2, 0xff, 0xfe, 0x91, 0x46, 0x73, 0x0b,
+ 0xfe, 0xc1, 0x87, 0xfc, 0x59, 0x7e, 0xe7, 0xbd, 0x04, 0xb2, 0xfe, 0x6f,
+ 0xbf, 0x8c, 0xdc, 0x59, 0x58, 0x7b, 0x06, 0x93, 0xdf, 0xd1, 0x3e, 0xde,
+ 0x6a, 0x16, 0x5f, 0xec, 0x9b, 0xd9, 0xc7, 0x25, 0x97, 0xfe, 0x1e, 0x75,
+ 0x2e, 0x7f, 0x8e, 0x05, 0x95, 0xa3, 0xf2, 0x09, 0x95, 0xf7, 0x39, 0x86,
+ 0x2c, 0xbf, 0xc6, 0x0f, 0xd9, 0xbf, 0x34, 0xb2, 0xff, 0xe6, 0x3e, 0xce,
+ 0xfc, 0xde, 0xed, 0xb8, 0xb2, 0xff, 0x64, 0xb0, 0x22, 0xb7, 0x25, 0x97,
+ 0xff, 0x44, 0xbd, 0x1d, 0x7e, 0x3c, 0xfb, 0x8b, 0x2a, 0x11, 0xf5, 0xa3,
+ 0x6f, 0x24, 0x11, 0xad, 0xff, 0xfe, 0x62, 0xce, 0xbe, 0x6b, 0xff, 0xd1,
+ 0xec, 0xde, 0xf2, 0x59, 0x7b, 0x30, 0x96, 0x54, 0xeb, 0x82, 0x63, 0x53,
+ 0xec, 0xcf, 0xa2, 0x26, 0x85, 0x8c, 0xc4, 0x5a, 0x85, 0x17, 0x88, 0xbf,
+ 0x18, 0xee, 0xf3, 0xbd, 0xd6, 0x2b, 0x8a, 0x16, 0x5f, 0xc3, 0xe7, 0xa0,
+ 0xce, 0x2c, 0xbf, 0xe1, 0xb6, 0xa3, 0x78, 0x39, 0x25, 0x97, 0x41, 0xd6,
+ 0x54, 0x1e, 0x8f, 0x8e, 0xeb, 0xc8, 0xb6, 0x71, 0x5f, 0xc2, 0x02, 0xff,
+ 0xb8, 0xfe, 0x61, 0xf6, 0xd3, 0xac, 0xbf, 0xcf, 0x2c, 0x1f, 0x39, 0x0b,
+ 0x2f, 0xef, 0xfa, 0x0f, 0x31, 0x2c, 0xa8, 0x44, 0xd6, 0x1d, 0x00, 0xca,
+ 0xb6, 0xb5, 0xed, 0x38, 0x21, 0xc9, 0xc4, 0xd7, 0x8d, 0xa4, 0x30, 0xce,
+ 0xb8, 0xbe, 0xb2, 0xf0, 0x75, 0x3a, 0xcb, 0xdd, 0x86, 0x16, 0x54, 0x1e,
+ 0x8c, 0x85, 0x98, 0x7a, 0xfb, 0x03, 0xa9, 0xd6, 0x5f, 0xfb, 0x7b, 0x7c,
+ 0x01, 0x2e, 0x30, 0xd6, 0x5f, 0xb3, 0x9e, 0x0c, 0xeb, 0x2d, 0xad, 0x88,
+ 0x8c, 0xc2, 0x3f, 0x20, 0x5f, 0xff, 0xe7, 0x90, 0x92, 0xf6, 0x04, 0x57,
+ 0x84, 0x69, 0x16, 0x4c, 0xb2, 0xa1, 0x13, 0x87, 0x37, 0xbf, 0xed, 0x83,
+ 0x27, 0x34, 0xd7, 0x31, 0x65, 0xf9, 0xb5, 0x29, 0xa1, 0x65, 0xff, 0xde,
+ 0xc2, 0x73, 0x7c, 0xdf, 0x93, 0x2c, 0xaf, 0x1f, 0x5f, 0x0a, 0x2b, 0x11,
+ 0x94, 0xd0, 0xa8, 0xbf, 0xfe, 0x0f, 0x62, 0x74, 0x07, 0xe3, 0xe9, 0xba,
+ 0x02, 0xcb, 0xf4, 0x78, 0xb0, 0xd5, 0x94, 0xc7, 0xf7, 0xe5, 0x4b, 0xf4,
+ 0x4d, 0xe6, 0xd2, 0xcb, 0xf8, 0x3f, 0xe4, 0x02, 0x75, 0x97, 0xcf, 0xa8,
+ 0x92, 0xcb, 0xff, 0xf9, 0x89, 0xd8, 0x81, 0xa8, 0xf3, 0xb7, 0xe3, 0xcb,
+ 0x28, 0x68, 0xa6, 0x22, 0xff, 0x90, 0xdf, 0x7f, 0x81, 0x9d, 0x65, 0xff,
+ 0xff, 0x75, 0xa8, 0x0f, 0xc2, 0x7d, 0x3b, 0x80, 0xb3, 0x7b, 0x69, 0x65,
+ 0x32, 0x23, 0x1c, 0x92, 0xff, 0xd2, 0x10, 0x6f, 0x3e, 0x1d, 0xf8, 0xb2,
+ 0xff, 0xa5, 0x1e, 0x8f, 0xf9, 0xce, 0xb2, 0xa0, 0xfe, 0x02, 0x81, 0x7f,
+ 0xf8, 0x98, 0x1f, 0xeb, 0xb6, 0xd0, 0x90, 0x35, 0x97, 0xfd, 0xe1, 0x06,
+ 0x1f, 0xf0, 0x10, 0xb2, 0xa1, 0x10, 0xee, 0x99, 0x43, 0x56, 0x19, 0xd9,
+ 0x0b, 0x43, 0x38, 0xf0, 0xbb, 0x28, 0x4c, 0xfe, 0x15, 0x17, 0xff, 0xc0,
+ 0x3e, 0x1f, 0x09, 0xcf, 0x12, 0x13, 0x8b, 0x2f, 0xe7, 0x03, 0xb0, 0xd9,
+ 0x65, 0xf3, 0x9f, 0x8e, 0xb2, 0xf4, 0x1e, 0x16, 0x57, 0x48, 0xb6, 0xd2,
+ 0x7f, 0x0a, 0xf7, 0x90, 0xdf, 0xb4, 0x1e, 0xfd, 0x0b, 0x2f, 0xed, 0x4d,
+ 0x26, 0xff, 0x16, 0x58, 0xa0, 0xf6, 0x30, 0xa6, 0xfb, 0x35, 0x1c, 0x59,
+ 0x7f, 0xa6, 0x79, 0x9f, 0xa9, 0x71, 0x65, 0xfc, 0xf3, 0xb4, 0xcc, 0x62,
+ 0xcb, 0xff, 0xfc, 0xe6, 0x7f, 0x3d, 0xb0, 0x79, 0x34, 0x9f, 0x53, 0xf8,
+ 0x2b, 0x2a, 0x11, 0xd9, 0x84, 0x2e, 0x6c, 0x45, 0xf7, 0xec, 0x29, 0xf0,
+ 0xc5, 0x97, 0xe7, 0x3f, 0x98, 0xc5, 0x95, 0x39, 0xe8, 0x0c, 0xa2, 0xff,
+ 0xa2, 0x71, 0x25, 0xe0, 0xbc, 0xeb, 0x2f, 0xf3, 0xff, 0x9d, 0xf6, 0xdd,
+ 0x2c, 0xbf, 0xe6, 0xef, 0x26, 0x72, 0x9c, 0x52, 0xb2, 0xb1, 0x1a, 0x7a,
+ 0x23, 0x73, 0xc2, 0x36, 0xb0, 0xa1, 0x65, 0xfa, 0x35, 0xac, 0xf2, 0xcb,
+ 0xcf, 0x2f, 0xac, 0xbf, 0xfe, 0x83, 0x4c, 0xc6, 0xde, 0x63, 0x8e, 0x30,
+ 0xeb, 0x2f, 0xe2, 0x73, 0x60, 0xf0, 0xb2, 0x85, 0x28, 0xd6, 0x90, 0xa9,
+ 0xc9, 0xc8, 0x70, 0x2a, 0x57, 0xa7, 0x34, 0xd5, 0x97, 0xb6, 0x9e, 0xe0,
+ 0x16, 0x5b, 0x71, 0x65, 0xf4, 0x82, 0x31, 0x7b, 0x41, 0xba, 0x34, 0x9a,
+ 0xfe, 0x3b, 0xf5, 0xb5, 0x67, 0x96, 0x5e, 0x31, 0xf8, 0xb2, 0xfe, 0x3c,
+ 0x61, 0x7f, 0x8b, 0x2f, 0xd1, 0x3e, 0x49, 0x96, 0x5e, 0x10, 0x62, 0xf1,
+ 0x14, 0x7e, 0x33, 0xe0, 0xef, 0xcb, 0x2a, 0x64, 0xcd, 0x7d, 0x0e, 0x4b,
+ 0xef, 0x7b, 0x3a, 0x59, 0x7f, 0x38, 0xe0, 0xa0, 0x0b, 0x2f, 0x9b, 0x98,
+ 0x38, 0x3c, 0xed, 0xb2, 0x3b, 0xde, 0x71, 0xac, 0xbf, 0xe6, 0x83, 0xec,
+ 0xc1, 0xb6, 0xf5, 0x95, 0xe3, 0xd7, 0xe0, 0xe5, 0x42, 0xab, 0xa1, 0xc7,
+ 0x1f, 0xdb, 0xc3, 0xc2, 0x46, 0xff, 0xfc, 0xdd, 0xc1, 0xf8, 0xfa, 0xc3,
+ 0x87, 0xb7, 0x92, 0xcb, 0xfe, 0x7d, 0x3f, 0xdb, 0x4e, 0x05, 0x97, 0x36,
+ 0xf5, 0x97, 0xfa, 0x09, 0xfc, 0x12, 0x9d, 0x65, 0xff, 0x98, 0xd8, 0x1b,
+ 0x13, 0xe8, 0xd5, 0x97, 0xff, 0xb3, 0xaf, 0xf5, 0xf6, 0x33, 0x06, 0xf2,
+ 0x59, 0x58, 0x88, 0xa0, 0x1f, 0x5b, 0xcb, 0x2f, 0xe6, 0xd0, 0x0e, 0xdc,
+ 0x59, 0x52, 0x4f, 0x07, 0xb5, 0x6d, 0xc3, 0x73, 0x8c, 0x14, 0x2f, 0x02,
+ 0x45, 0xb6, 0x23, 0x78, 0x70, 0x75, 0x97, 0xf0, 0x32, 0x68, 0xeb, 0x8b,
+ 0x2f, 0xfd, 0xec, 0x2e, 0xf6, 0x60, 0xdb, 0x7a, 0xcb, 0xff, 0xfc, 0x4e,
+ 0x67, 0xb0, 0xee, 0x67, 0xf9, 0x86, 0x0d, 0x8e, 0xb2, 0xf7, 0xb2, 0x65,
+ 0x97, 0xfb, 0xf9, 0xac, 0x9a, 0x0d, 0x59, 0x7f, 0xff, 0xf7, 0x3d, 0x1e,
+ 0x86, 0xe8, 0x1a, 0xc1, 0xc7, 0xf8, 0xc5, 0xd4, 0x96, 0x56, 0x27, 0x2c,
+ 0xc5, 0xf3, 0x21, 0x79, 0x8b, 0xe3, 0xa6, 0x1a, 0x5e, 0x1b, 0x1d, 0x65,
+ 0xfe, 0x34, 0xb2, 0x79, 0xc2, 0x4b, 0x2a, 0x15, 0x2d, 0xe4, 0x76, 0x4c,
+ 0xb0, 0x11, 0xcb, 0xfb, 0xcf, 0x28, 0xe4, 0x96, 0x5f, 0xf6, 0x79, 0xba,
+ 0xe7, 0x83, 0xc5, 0x97, 0x61, 0x76, 0x7c, 0xe0, 0x2d, 0xbf, 0xff, 0x82,
+ 0xfb, 0x9b, 0x36, 0xc3, 0x1b, 0x33, 0x84, 0x17, 0x9d, 0x65, 0xff, 0xba,
+ 0x94, 0x7f, 0xf0, 0xe7, 0x9d, 0x65, 0xff, 0xec, 0xf3, 0xb9, 0xc9, 0xf4,
+ 0xd1, 0xc5, 0x96, 0xc3, 0xa2, 0x1b, 0x7a, 0x05, 0xfa, 0x7d, 0xd8, 0xeb,
+ 0x8b, 0x2f, 0xce, 0x01, 0xe1, 0x2c, 0xac, 0x4d, 0xa3, 0xd0, 0xeb, 0x72,
+ 0xa2, 0x2d, 0xbf, 0xdd, 0xc4, 0xbf, 0xe7, 0x1a, 0xcb, 0xf3, 0x6d, 0xe6,
+ 0x8d, 0x59, 0x7d, 0xbc, 0xb3, 0x8b, 0x2f, 0xe2, 0x73, 0x4b, 0x00, 0xb2,
+ 0x98, 0xf3, 0xce, 0x47, 0x73, 0xc2, 0xcb, 0xfa, 0x3f, 0xcd, 0x9f, 0x92,
+ 0xcb, 0x8d, 0x92, 0xcb, 0xf7, 0x9b, 0x7b, 0x76, 0xb2, 0xec, 0xf4, 0x8f,
+ 0x0b, 0xb1, 0x8a, 0xc4, 0xe1, 0x0e, 0x68, 0xef, 0x5c, 0x21, 0xf8, 0xae,
+ 0xdb, 0x95, 0xe3, 0x0c, 0x31, 0x25, 0xff, 0xb4, 0x41, 0x71, 0x32, 0x68,
+ 0x3a, 0xc1, 0x66, 0x82, 0xf4, 0xcc, 0x62, 0xcb, 0xde, 0x08, 0x16, 0x5b,
+ 0xcc, 0x6e, 0xe6, 0x1e, 0xb7, 0x6b, 0x2a, 0x11, 0x8b, 0x90, 0x8c, 0xd1,
+ 0x3d, 0xfe, 0x81, 0xe4, 0xa0, 0xbb, 0x59, 0x50, 0xdc, 0x53, 0x4f, 0x1a,
+ 0xac, 0xa1, 0xd9, 0x92, 0xeb, 0x5a, 0x32, 0x2d, 0xc8, 0x4c, 0x4d, 0x18,
+ 0x8e, 0xa3, 0x5c, 0x3c, 0x62, 0x1e, 0x96, 0x0e, 0xf2, 0x82, 0x8a, 0x56,
+ 0x5f, 0x21, 0x53, 0xf8, 0xe5, 0x43, 0x1e, 0x21, 0x91, 0x9f, 0x08, 0x67,
+ 0x7c, 0xda, 0x70, 0x2c, 0xbf, 0xc3, 0xf4, 0x4e, 0x59, 0xd2, 0xcb, 0xc3,
+ 0xf4, 0x2c, 0xa3, 0x9f, 0x88, 0x08, 0x78, 0x69, 0x7d, 0xad, 0x67, 0x96,
+ 0x5f, 0xde, 0x6d, 0xdd, 0xd0, 0x9a, 0xb2, 0xa0, 0xf5, 0xfb, 0x22, 0xb0,
+ 0xad, 0x65, 0xc5, 0xc5, 0x96, 0x65, 0x97, 0xf6, 0xb9, 0xe8, 0x2f, 0xac,
+ 0xba, 0x00, 0xb2, 0xdf, 0x83, 0xc3, 0xe1, 0x6d, 0xff, 0xed, 0x4e, 0x27,
+ 0xdb, 0xc1, 0x39, 0xde, 0x4b, 0x2c, 0x2b, 0x59, 0x7f, 0xdf, 0x8d, 0x73,
+ 0xd0, 0x5f, 0x59, 0x77, 0x21, 0x65, 0xe3, 0x8e, 0x16, 0x5f, 0xe2, 0xfb,
+ 0xcd, 0xc8, 0xfa, 0xca, 0x63, 0xcf, 0x71, 0xcb, 0xe6, 0x7c, 0xed, 0x65,
+ 0xff, 0xb3, 0x79, 0x67, 0x26, 0x28, 0x1a, 0xcb, 0xee, 0xc7, 0x13, 0xac,
+ 0xb8, 0x10, 0xb2, 0xf7, 0x1b, 0x4b, 0x2b, 0x0f, 0x58, 0x04, 0x9f, 0x16,
+ 0xbf, 0xd2, 0xc2, 0x61, 0xe1, 0x2c, 0xbb, 0x82, 0xe1, 0x3e, 0x6c, 0x15,
+ 0x98, 0xe3, 0xcc, 0xa0, 0x20, 0x22, 0x1e, 0x42, 0x57, 0xe5, 0xd4, 0xea,
+ 0xad, 0xbf, 0x28, 0xce, 0xfb, 0xa1, 0xbc, 0xeb, 0x2e, 0xe4, 0x2c, 0xbc,
+ 0x71, 0xc2, 0xcb, 0xfc, 0x5f, 0x79, 0xb9, 0x1f, 0x59, 0x4c, 0x79, 0xee,
+ 0x39, 0x7c, 0xcf, 0x9d, 0xac, 0xbf, 0xf6, 0x6f, 0x2c, 0xe4, 0xc5, 0x03,
+ 0x59, 0x7d, 0xd8, 0xe2, 0x75, 0x97, 0xf4, 0xc0, 0x6d, 0xc7, 0x99, 0x65,
+ 0xe6, 0x07, 0x16, 0x5c, 0x08, 0x59, 0x7b, 0x8d, 0xa5, 0x97, 0x64, 0xcb,
+ 0x2b, 0x11, 0x77, 0xd9, 0x27, 0x8c, 0x80, 0x39, 0xf1, 0x61, 0x07, 0x2f,
+ 0xec, 0x26, 0x1e, 0x12, 0xcb, 0xf6, 0x11, 0x3f, 0xd6, 0x5f, 0xa7, 0xfe,
+ 0x61, 0xd6, 0x54, 0x8f, 0xdf, 0xc5, 0x4e, 0x4b, 0x7f, 0x13, 0x8f, 0x0d,
+ 0x17, 0x0b, 0xc8, 0xf2, 0x15, 0x18, 0xb6, 0x29, 0xf7, 0x2b, 0x75, 0x8a,
+ 0xe6, 0x24, 0xf3, 0x28, 0x08, 0x08, 0x87, 0x90, 0xfa, 0xfc, 0x33, 0xef,
+ 0xfe, 0xd4, 0x75, 0xc2, 0x83, 0xe7, 0x5f, 0x59, 0x7f, 0xfe, 0x71, 0xe6,
+ 0x11, 0xa2, 0x14, 0x14, 0xed, 0xa5, 0x97, 0x9f, 0x53, 0xae, 0x41, 0x25,
+ 0xf4, 0xb3, 0xa9, 0x2e, 0x41, 0x25, 0xee, 0x30, 0xd7, 0x20, 0x92, 0xe3,
+ 0x0c, 0x5c, 0x82, 0x4a, 0xed, 0x15, 0x33, 0x15, 0x7c, 0xc0, 0xc2, 0x9b,
+ 0x9f, 0xe9, 0x90, 0x48, 0x16, 0x78, 0x17, 0xff, 0xff, 0x0c, 0xa0, 0x7e,
+ 0x8f, 0xf2, 0x3f, 0x03, 0x8f, 0xe1, 0xc0, 0x62, 0xcb, 0xfb, 0x3d, 0x98,
+ 0x46, 0xac, 0xbc, 0xe4, 0x0d, 0x8c, 0x99, 0xa8, 0x9e, 0x69, 0xd4, 0x36,
+ 0xce, 0x8a, 0x51, 0x9e, 0xf0, 0xdf, 0xee, 0x37, 0xdb, 0x78, 0xfe, 0x59,
+ 0x6c, 0xdc, 0x45, 0x78, 0x21, 0x17, 0x69, 0x2c, 0xbf, 0xa4, 0x19, 0xfe,
+ 0xd3, 0xa4, 0xbe, 0xd0, 0x1b, 0xeb, 0x2f, 0x6f, 0x8e, 0x2c, 0xbe, 0x71,
+ 0xfb, 0x16, 0x5e, 0x1b, 0x1d, 0x65, 0xff, 0xbd, 0x1f, 0x62, 0x83, 0xc7,
+ 0x16, 0x5b, 0x71, 0x65, 0x42, 0x33, 0x70, 0x88, 0xd1, 0xe7, 0x21, 0xe0,
+ 0xe6, 0xe9, 0xe5, 0x4c, 0x9a, 0xaf, 0xa1, 0xfb, 0x7f, 0xd0, 0x52, 0x28,
+ 0x03, 0x9d, 0x65, 0xfd, 0xdb, 0x73, 0xf9, 0xe5, 0x97, 0xe6, 0xfe, 0x82,
+ 0x75, 0x97, 0xd1, 0xe0, 0xe9, 0x65, 0xef, 0x3f, 0xd6, 0x54, 0xe7, 0xcd,
+ 0x31, 0x47, 0x08, 0xae, 0x8f, 0x2c, 0xb4, 0x2c, 0xf9, 0x6d, 0x7f, 0x9a,
+ 0x41, 0x7e, 0x79, 0x96, 0x5f, 0xd9, 0xbd, 0xcf, 0x9e, 0x59, 0x69, 0x24,
+ 0xbc, 0xfa, 0x9d, 0x25, 0x24, 0xa8, 0x37, 0x3d, 0x88, 0x9c, 0x76, 0xf4,
+ 0x03, 0xb4, 0x82, 0xcd, 0x75, 0x1d, 0x18, 0x85, 0x09, 0x5b, 0xc5, 0x2f,
+ 0x2c, 0xbd, 0xd4, 0xb8, 0xb2, 0xa1, 0x35, 0x7c, 0x87, 0xb1, 0xc9, 0xdc,
+ 0x72, 0xff, 0x3c, 0xf8, 0x53, 0xb6, 0x96, 0x5f, 0xb4, 0x03, 0xb7, 0x16,
+ 0x5f, 0xc2, 0x14, 0xb9, 0xe1, 0xac, 0xc3, 0x51, 0x7f, 0x7f, 0x80, 0x77,
+ 0xd2, 0xcb, 0xe8, 0xed, 0xb8, 0xb2, 0xf8, 0x2f, 0xa9, 0x2c, 0xb1, 0xd6,
+ 0x5a, 0x43, 0x36, 0x73, 0x11, 0x5f, 0xff, 0xff, 0xe0, 0x00, 0x3c, 0x7f,
+ 0xfe, 0x59, 0xef, 0x3c, 0xb6, 0xf3, 0x9c, 0x0f, 0x3f, 0xcc, 0x31, 0x65,
+ 0x42, 0x67, 0xd3, 0x96, 0xe2, 0xab, 0x94, 0x5f, 0xfd, 0x9d, 0x7f, 0x8c,
+ 0x50, 0x07, 0x3a, 0xcb, 0xd2, 0x8e, 0x96, 0x5d, 0x83, 0x59, 0x7d, 0x93,
+ 0x31, 0xd6, 0x54, 0xe8, 0x98, 0x99, 0x0f, 0xe3, 0xa6, 0x0b, 0x5f, 0xa2,
+ 0x69, 0x40, 0x12, 0x5c, 0x40, 0x59, 0x7f, 0x7d, 0xb4, 0xd3, 0xc2, 0xca,
+ 0xc3, 0xc3, 0x10, 0x5a, 0xff, 0xfd, 0xec, 0x69, 0x73, 0x67, 0xfd, 0x83,
+ 0x0f, 0xf8, 0xb2, 0xbb, 0x47, 0x2e, 0x9a, 0xfe, 0x45, 0x7f, 0xc0, 0x72,
+ 0xfc, 0xd9, 0xac, 0x59, 0x7f, 0xef, 0xfb, 0x06, 0x1f, 0xf2, 0x68, 0x59,
+ 0x66, 0x59, 0x7f, 0xd3, 0x86, 0x43, 0xf0, 0x5c, 0x96, 0x5f, 0xcd, 0x07,
+ 0x9f, 0x0c, 0x59, 0x7e, 0xc9, 0xcf, 0x87, 0x59, 0x7b, 0x8d, 0xa5, 0x94,
+ 0x47, 0x89, 0xf2, 0x8b, 0xf8, 0x9c, 0x00, 0x0f, 0x16, 0x5e, 0x83, 0x8b,
+ 0x1a, 0x61, 0x58, 0x21, 0xa3, 0xae, 0x39, 0x7c, 0x86, 0xe6, 0x37, 0x89,
+ 0xd3, 0x89, 0x1a, 0x55, 0x62, 0xb6, 0xc6, 0x8c, 0x95, 0xcc, 0x4a, 0x3d,
+ 0xfb, 0xfb, 0xde, 0xc9, 0xff, 0xc5, 0x97, 0xb2, 0x70, 0xac, 0xac, 0x3c,
+ 0xc2, 0x2f, 0xbf, 0xec, 0xfe, 0xc2, 0xc0, 0x09, 0xd2, 0xca, 0x86, 0xd9,
+ 0x72, 0x54, 0xac, 0xf1, 0x98, 0x64, 0x6c, 0xc6, 0x95, 0x74, 0x6c, 0xd0,
+ 0x94, 0xd2, 0x3f, 0xa3, 0x76, 0x74, 0x00, 0x2d, 0x94, 0x6f, 0x9c, 0x9c,
+ 0x40, 0xfc, 0x24, 0xf6, 0xc8, 0x2f, 0xff, 0xd3, 0xeb, 0x58, 0x37, 0x3f,
+ 0x9f, 0xe5, 0x13, 0x2c, 0xbf, 0xff, 0xfc, 0x1d, 0x06, 0x62, 0x70, 0x73,
+ 0x98, 0x6e, 0x07, 0x4e, 0x38, 0xf4, 0x2c, 0xbf, 0xfe, 0xcf, 0xc7, 0xf9,
+ 0xa8, 0x2f, 0xfb, 0x24, 0xb2, 0xfe, 0x61, 0x23, 0xa8, 0xe9, 0x65, 0xfc,
+ 0x18, 0xd6, 0x9a, 0x75, 0x97, 0xf9, 0x85, 0xb7, 0xf5, 0x92, 0x59, 0x7f,
+ 0x79, 0xb7, 0x84, 0x12, 0x59, 0x7f, 0xb9, 0x0d, 0xad, 0x64, 0xeb, 0x2f,
+ 0xe9, 0x40, 0x3c, 0xc6, 0x2c, 0xbf, 0x9c, 0x7e, 0x82, 0x0a, 0xcb, 0xfe,
+ 0x83, 0x96, 0x0d, 0xbd, 0xc5, 0x97, 0xb1, 0x80, 0xb2, 0xfb, 0xb3, 0x74,
+ 0x05, 0x97, 0x9d, 0xc9, 0x65, 0xfd, 0x28, 0x9b, 0x18, 0x0b, 0x2c, 0x2c,
+ 0x69, 0xee, 0xe1, 0x71, 0xa6, 0x9d, 0x18, 0x4c, 0x66, 0x72, 0xef, 0x16,
+ 0x0a, 0xcd, 0xc8, 0x6f, 0xe4, 0xbb, 0xa3, 0x57, 0x04, 0xc5, 0x97, 0xd1,
+ 0xb8, 0x38, 0x59, 0x7d, 0xbb, 0xe0, 0x88, 0xb2, 0xfe, 0x08, 0x9c, 0x6c,
+ 0x25, 0x97, 0x64, 0xcb, 0x2e, 0x12, 0x65, 0x94, 0xc6, 0xc1, 0xc5, 0xed,
+ 0x13, 0x1f, 0xe7, 0x17, 0x6f, 0x18, 0x61, 0x89, 0x2d, 0x09, 0x05, 0x9a,
+ 0x0b, 0xa5, 0x3a, 0xca, 0x91, 0xba, 0x39, 0x15, 0xef, 0x40, 0x16, 0x5f,
+ 0xc2, 0x8f, 0x40, 0x23, 0x71, 0x65, 0x7c, 0xf4, 0x04, 0x1c, 0xbb, 0xda,
+ 0x59, 0x7b, 0xc2, 0x83, 0x16, 0x5f, 0x4d, 0x99, 0xda, 0xca, 0x85, 0xe2,
+ 0x29, 0xd5, 0xa4, 0xf0, 0x34, 0xec, 0x94, 0x18, 0x6c, 0x2a, 0x7b, 0x18,
+ 0xe8, 0x92, 0x68, 0x51, 0xea, 0x10, 0x4e, 0xe3, 0xf2, 0x3d, 0xe2, 0xe6,
+ 0x11, 0x5f, 0x0f, 0x33, 0x4b, 0x2f, 0xff, 0x7e, 0x6c, 0xd6, 0x9e, 0x6c,
+ 0xd6, 0x7d, 0x65, 0x61, 0xf6, 0x31, 0x0d, 0xff, 0xe2, 0x96, 0xc9, 0x37,
+ 0xe5, 0x1a, 0x8e, 0xd6, 0x5f, 0xa3, 0x5a, 0xcf, 0x2c, 0xac, 0x3f, 0x33,
+ 0x53, 0x2f, 0xe9, 0xe6, 0x90, 0xa3, 0x53, 0xac, 0xbf, 0xfc, 0x03, 0xbc,
+ 0xb6, 0x40, 0xe7, 0x3c, 0x69, 0x65, 0xf3, 0x41, 0x7d, 0x65, 0xe9, 0xdc,
+ 0x96, 0x56, 0x91, 0x13, 0xe4, 0xdf, 0x90, 0x5f, 0xf8, 0xd0, 0xf2, 0x4d,
+ 0xa9, 0xc2, 0x05, 0x97, 0x16, 0x2c, 0xbc, 0x27, 0x44, 0xb2, 0xfc, 0x59,
+ 0xd0, 0x38, 0xb2, 0xee, 0x8c, 0x59, 0x7d, 0x9b, 0x90, 0x75, 0x95, 0x87,
+ 0xca, 0xe5, 0x1c, 0x19, 0xa3, 0x53, 0x07, 0x64, 0x23, 0x8a, 0xfa, 0x10,
+ 0x77, 0x98, 0xf0, 0xb2, 0xf3, 0x41, 0xd6, 0x5c, 0xe3, 0x59, 0x5a, 0x36,
+ 0x3f, 0x1b, 0xbf, 0x4f, 0xec, 0x03, 0xac, 0xa9, 0xcf, 0x27, 0x44, 0x37,
+ 0xde, 0x1e, 0x12, 0xcb, 0xff, 0xe8, 0x13, 0xe5, 0x00, 0x7f, 0x80, 0x42,
+ 0x92, 0xca, 0xda, 0xd5, 0xb1, 0x64, 0x2f, 0xda, 0x33, 0x7d, 0x21, 0xbc,
+ 0x25, 0x78, 0x47, 0xf2, 0x1b, 0xe1, 0x07, 0xe6, 0x59, 0x7f, 0xe7, 0xff,
+ 0x0c, 0xcf, 0x01, 0xfe, 0xb2, 0xfc, 0x0c, 0x1b, 0xc9, 0x65, 0xf6, 0xf0,
+ 0xb9, 0x2c, 0xbf, 0xff, 0xf6, 0x7e, 0x3b, 0x2c, 0xc2, 0x89, 0x7f, 0xce,
+ 0x72, 0xcd, 0xeb, 0x2a, 0x74, 0xc5, 0x86, 0x47, 0xa3, 0xf2, 0x27, 0x30,
+ 0x8e, 0xf0, 0x83, 0x99, 0x65, 0xe9, 0x31, 0x2c, 0xbf, 0xf9, 0x8e, 0x4e,
+ 0x6f, 0x3d, 0x05, 0xf5, 0x97, 0xee, 0x3f, 0x9b, 0x8b, 0x2e, 0x12, 0x4b,
+ 0x2f, 0xf4, 0x18, 0x58, 0x00, 0xf1, 0x65, 0x1a, 0x79, 0x7a, 0x18, 0xbf,
+ 0xff, 0xfd, 0x2e, 0x79, 0xdb, 0xe1, 0xd3, 0xf3, 0x0a, 0x24, 0x3d, 0x37,
+ 0x52, 0x59, 0x78, 0x4d, 0xd3, 0x16, 0x5f, 0xff, 0x03, 0x07, 0xfe, 0x37,
+ 0xfd, 0x9b, 0xc7, 0x0b, 0x2e, 0x6e, 0x96, 0x54, 0xe8, 0x8a, 0xd1, 0x17,
+ 0xd4, 0x6f, 0xe7, 0x6f, 0xcc, 0xc6, 0x2c, 0xbf, 0xfa, 0x76, 0xd4, 0x0f,
+ 0xd0, 0x63, 0xfd, 0x65, 0xa3, 0xc7, 0xe6, 0x45, 0xd7, 0xfe, 0x06, 0x69,
+ 0x81, 0x80, 0xd1, 0xd6, 0x5f, 0xfe, 0x36, 0x39, 0xa8, 0xf1, 0x67, 0xe0,
+ 0xeb, 0x2e, 0x08, 0x8b, 0x2f, 0xf8, 0x32, 0xce, 0x09, 0x38, 0x49, 0x65,
+ 0xfe, 0x2c, 0xde, 0xd3, 0x31, 0x8b, 0x2b, 0xc8, 0x88, 0x21, 0x8e, 0x1d,
+ 0xdf, 0xff, 0xc1, 0x79, 0xfb, 0x0c, 0xff, 0xcf, 0x16, 0x7f, 0xcc, 0xb2,
+ 0xfd, 0x13, 0x10, 0x78, 0xb2, 0xb1, 0x38, 0x56, 0x86, 0x8f, 0x8b, 0xfe,
+ 0xbb, 0x73, 0x12, 0xcb, 0xf9, 0xc8, 0x19, 0xf3, 0x56, 0x54, 0x2e, 0xb7,
+ 0xce, 0x99, 0x21, 0xf3, 0x46, 0xe6, 0x43, 0xd3, 0x97, 0x88, 0xde, 0x30,
+ 0x12, 0x85, 0x27, 0x09, 0xbf, 0x1e, 0x1e, 0xf4, 0x1d, 0xb1, 0x5b, 0xe2,
+ 0xfc, 0x6d, 0xac, 0xbd, 0x05, 0xf5, 0x97, 0xd1, 0xa7, 0xf2, 0xca, 0x19,
+ 0xbc, 0xde, 0x37, 0x76, 0x4c, 0xb2, 0xfb, 0xc1, 0x3c, 0x2c, 0xa5, 0x94,
+ 0xb2, 0xce, 0x72, 0xdb, 0x81, 0x77, 0x04, 0x56, 0xb2, 0xfb, 0xd8, 0x07,
+ 0x59, 0x7d, 0xf6, 0xf0, 0x56, 0x5f, 0xd9, 0xae, 0xa5, 0xf8, 0x59, 0x74,
+ 0x6e, 0x0a, 0xa3, 0xd0, 0x10, 0x8a, 0xb6, 0xb4, 0xee, 0x99, 0x82, 0x62,
+ 0x37, 0x17, 0x23, 0x80, 0x92, 0xef, 0x1b, 0xdd, 0x71, 0xb0, 0xbd, 0xae,
+ 0x18, 0xb2, 0xa2, 0x98, 0xc0, 0xb6, 0x88, 0x59, 0x8a, 0x21, 0x51, 0xb4,
+ 0x8a, 0xc5, 0x46, 0xd1, 0x55, 0x28, 0xd7, 0x69, 0xc2, 0xdc, 0x55, 0x9d,
+ 0xc5, 0x26, 0xee, 0x79, 0xdd, 0x19, 0x4e, 0x01, 0x8e, 0x91, 0x55, 0x95,
+ 0xa8, 0x19, 0xb2, 0xa3, 0x3b, 0x9c, 0xdb, 0xea, 0x5d, 0x6b, 0x4e, 0x1b,
+ 0xee, 0x46, 0x0f, 0x34, 0xe3, 0xde, 0xa7, 0xd7, 0x8f, 0x3a, 0x97, 0xea,
+ 0xca, 0xc9, 0xe7, 0x73, 0x01, 0x38, 0x6c, 0x2b, 0x8c, 0xc4, 0xa7, 0xbe,
+ 0x39, 0x5c, 0xac, 0xfe, 0xb8, 0x15, 0x0c, 0xf9, 0x06, 0xf8, 0xd2, 0x4c,
+ 0x84, 0x9e, 0xdc, 0xb8, 0x41, 0x27, 0xbf, 0x77, 0x65, 0x42, 0xdf, 0xfe,
+ 0x9c, 0xf1, 0xd0, 0xbd, 0xaf, 0x69, 0xfc, 0x9c, 0x0b, 0x29, 0xd5, 0xb1,
+ 0x06, 0x58, 0x4d, 0xf3, 0x10, 0x19, 0x65, 0xe7, 0x3f, 0x16, 0x54, 0x8d,
+ 0xe6, 0xf2, 0x0b, 0xf1, 0xf1, 0x9c, 0x0b, 0x2f, 0xbb, 0x77, 0xed, 0x51,
+ 0x45, 0x2f, 0xff, 0xce, 0x08, 0xef, 0xcd, 0xcf, 0x37, 0xfd, 0x84, 0xb2,
+ 0xb4, 0x88, 0x42, 0x30, 0xbe, 0xfe, 0x9b, 0xa5, 0x97, 0xfe, 0x8f, 0xb0,
+ 0x22, 0x5f, 0xe6, 0xd4, 0xb2, 0xfd, 0xdc, 0x14, 0x01, 0x65, 0xf7, 0xcd,
+ 0x6e, 0xd6, 0x53, 0x9e, 0x5f, 0x09, 0xef, 0xec, 0x00, 0x9a, 0x70, 0x2c,
+ 0xbc, 0xf2, 0x17, 0x09, 0xe6, 0x64, 0x2a, 0x98, 0x8b, 0x44, 0x7e, 0x84,
+ 0x77, 0xc8, 0x6f, 0xfe, 0x87, 0xd1, 0x05, 0xfa, 0xcf, 0x3a, 0xcb, 0xff,
+ 0xe6, 0x98, 0xa3, 0xfc, 0xff, 0x5d, 0xb1, 0x4e, 0xb2, 0xff, 0xfb, 0x3d,
+ 0xf6, 0x31, 0xb2, 0x4d, 0xa7, 0x02, 0xca, 0x1a, 0x28, 0x38, 0xa5, 0x61,
+ 0x78, 0xad, 0x98, 0xf1, 0xf7, 0xf9, 0xcb, 0x90, 0xe2, 0xbf, 0xc2, 0xf3,
+ 0x5d, 0xbb, 0xf6, 0xa8, 0xba, 0x17, 0xff, 0x0b, 0x79, 0x0b, 0xcd, 0x76,
+ 0xef, 0xda, 0xa2, 0x4b, 0x5f, 0xb5, 0xdb, 0xbf, 0x6a, 0x8b, 0xc9, 0x73,
+ 0xef, 0x59, 0x61, 0x78, 0x79, 0xdb, 0x66, 0xd5, 0x10, 0xda, 0x7f, 0x9e,
+ 0x3c, 0xa9, 0x37, 0xe4, 0x28, 0x7b, 0x87, 0x5c, 0xcc, 0x07, 0x43, 0xf4,
+ 0xf6, 0xe3, 0xa0, 0x16, 0x32, 0x72, 0xb9, 0x2f, 0x37, 0xea, 0x21, 0x43,
+ 0xdf, 0x0a, 0x4b, 0xff, 0xc2, 0xce, 0xf2, 0x17, 0x9a, 0xed, 0xdf, 0xb5,
+ 0x44, 0xb2, 0xbe, 0xda, 0xcd, 0xdb, 0xda, 0xd6, 0x58, 0x50, 0xb2, 0xdb,
+ 0xab, 0x2d, 0xe5, 0x95, 0xb5, 0x9b, 0xad, 0xa0, 0x54, 0x22, 0x97, 0xf9,
+ 0x87, 0xec, 0x62, 0x35, 0x65, 0xf7, 0x9f, 0xe1, 0x59, 0x7d, 0xe8, 0xdc,
+ 0x3a, 0xcb, 0xff, 0x67, 0x9a, 0x45, 0x98, 0x11, 0x5a, 0xcb, 0xff, 0x63,
+ 0x6f, 0x62, 0x0c, 0xb3, 0x8b, 0x2f, 0xfa, 0x07, 0xb2, 0x3f, 0xac, 0x1a,
+ 0xcb, 0xc1, 0xed, 0xd6, 0x54, 0x93, 0x4e, 0x63, 0x2d, 0xc2, 0x23, 0x92,
+ 0x92, 0x07, 0xcf, 0x84, 0x3a, 0xbf, 0x87, 0xf0, 0xbc, 0xb8, 0xb2, 0xff,
+ 0x81, 0xb1, 0xbf, 0xc8, 0xd0, 0x16, 0x5f, 0xb8, 0xe6, 0xf9, 0x96, 0x5d,
+ 0x13, 0xac, 0xbf, 0xf6, 0x1f, 0x8f, 0x21, 0x39, 0x18, 0xb2, 0xb7, 0x0f,
+ 0x57, 0xe2, 0xf5, 0x08, 0xdd, 0xc3, 0xb6, 0x7d, 0xbd, 0xe3, 0x1d, 0x65,
+ 0xfc, 0x78, 0x23, 0x72, 0x75, 0x97, 0x39, 0xd6, 0x5f, 0xf9, 0xf5, 0x28,
+ 0xff, 0xa0, 0x22, 0xb5, 0x95, 0xb4, 0x22, 0x8f, 0x07, 0x7e, 0x5c, 0x11,
+ 0x6b, 0xf0, 0x7e, 0xde, 0x85, 0x97, 0xfe, 0xf4, 0x79, 0x8d, 0xff, 0x1c,
+ 0x0b, 0x2f, 0xf9, 0xe5, 0xc0, 0xfe, 0x3f, 0xc5, 0x97, 0xf1, 0x7f, 0x50,
+ 0xfd, 0xac, 0xb9, 0xf8, 0xb2, 0xff, 0xfc, 0xef, 0x27, 0xf6, 0xcc, 0x9c,
+ 0x3f, 0x6f, 0x42, 0xca, 0x9c, 0xfb, 0x26, 0x16, 0xb8, 0x3a, 0x59, 0x7e,
+ 0x97, 0x1f, 0x6f, 0x16, 0x5e, 0x77, 0xed, 0x51, 0x19, 0xaf, 0xf4, 0x75,
+ 0x28, 0xd1, 0xe4, 0xb2, 0xff, 0xff, 0xb9, 0xff, 0xb7, 0xba, 0x97, 0x08,
+ 0x38, 0x69, 0xac, 0xf2, 0x59, 0x6c, 0x02, 0x27, 0x7e, 0x69, 0x7f, 0xff,
+ 0xd2, 0xcd, 0x8f, 0xf0, 0xc6, 0xc1, 0x94, 0x6b, 0x4d, 0x87, 0x59, 0x50,
+ 0x9c, 0x07, 0x65, 0x5a, 0x86, 0x33, 0x94, 0x5f, 0xcd, 0x07, 0x9f, 0x0c,
+ 0x59, 0x71, 0x49, 0x65, 0x8e, 0xb2, 0xfc, 0xda, 0xf3, 0x8b, 0xd1, 0xea,
+ 0x9c, 0xb8, 0x41, 0x6b, 0x79, 0x65, 0xd1, 0xa5, 0x96, 0x6e, 0xcd, 0x3e,
+ 0xf1, 0x1b, 0xe6, 0xd3, 0xe9, 0x65, 0xdc, 0xdc, 0x59, 0x67, 0x91, 0xbb,
+ 0xf9, 0x0d, 0xff, 0xdc, 0x60, 0xf3, 0x08, 0x32, 0xce, 0x2c, 0xba, 0x3a,
+ 0x59, 0x79, 0x8b, 0xb5, 0x95, 0xc3, 0x67, 0xf1, 0x7b, 0xff, 0xe1, 0x5b,
+ 0x7f, 0x8d, 0xf2, 0x80, 0xbe, 0x8d, 0x59, 0x53, 0xae, 0xb9, 0xc8, 0x9c,
+ 0x67, 0xf8, 0x72, 0xd0, 0x99, 0x98, 0x93, 0x51, 0xcb, 0x9e, 0x12, 0xfe,
+ 0x75, 0x26, 0x4e, 0x13, 0x7d, 0xd8, 0x24, 0x37, 0xf9, 0xcc, 0xf3, 0x46,
+ 0xa1, 0x65, 0xff, 0xff, 0xf9, 0xc7, 0xcf, 0x61, 0xc9, 0xa7, 0xd8, 0x70,
+ 0x93, 0x9b, 0xe2, 0xcf, 0xeb, 0x16, 0x56, 0x91, 0x6c, 0x46, 0x57, 0xff,
+ 0xfb, 0xcd, 0xff, 0xb7, 0x04, 0x9e, 0x27, 0x2c, 0x00, 0x78, 0xb2, 0xfd,
+ 0xf6, 0x3c, 0x4c, 0xb2, 0xfe, 0xc8, 0xd9, 0x1c, 0x3a, 0xca, 0xc3, 0xd6,
+ 0xe1, 0x45, 0xfe, 0x27, 0x33, 0xe4, 0xe6, 0xac, 0xa9, 0x1e, 0xa7, 0xc8,
+ 0x6f, 0xb5, 0xa7, 0xe2, 0xcb, 0xf7, 0xb0, 0x9c, 0xeb, 0x2f, 0xba, 0xf4,
+ 0x71, 0x65, 0xe9, 0x9c, 0x96, 0x5e, 0x8f, 0xf1, 0x65, 0xff, 0xb0, 0xde,
+ 0x46, 0x10, 0xfd, 0x0b, 0x2b, 0x87, 0xb2, 0x11, 0xca, 0xd8, 0x98, 0x14,
+ 0x88, 0xb0, 0x9a, 0x62, 0x3e, 0x3a, 0xdf, 0xb7, 0x49, 0xcc, 0x1a, 0xcb,
+ 0xfd, 0x1a, 0x9f, 0x58, 0x3c, 0x59, 0x7f, 0xf7, 0xdb, 0x4e, 0x0d, 0x9d,
+ 0x4a, 0x0e, 0xb2, 0xfc, 0x51, 0x2e, 0x3a, 0xca, 0x84, 0x65, 0xc8, 0xad,
+ 0x8c, 0xf7, 0xa3, 0xdf, 0xf7, 0x7e, 0x83, 0xee, 0xe3, 0xcc, 0xb2, 0xde,
+ 0x59, 0x7f, 0xff, 0xf7, 0xd8, 0xfa, 0x6c, 0xe8, 0x83, 0xf8, 0xf6, 0xcd,
+ 0xed, 0xf9, 0xa1, 0x65, 0x62, 0x21, 0xfe, 0x23, 0x7f, 0xd0, 0x7f, 0x3f,
+ 0xdc, 0x80, 0xb2, 0xfc, 0xe4, 0x24, 0x01, 0x65, 0x42, 0x68, 0x99, 0x0c,
+ 0x46, 0x22, 0xd1, 0xbd, 0xfd, 0x2e, 0x71, 0xca, 0x4b, 0x2f, 0x4f, 0xce,
+ 0x2c, 0xbf, 0x17, 0xf8, 0x1d, 0x2c, 0xa7, 0x3f, 0x32, 0x2d, 0x08, 0xf5,
+ 0xce, 0x35, 0x97, 0xe9, 0x39, 0x07, 0xb5, 0x95, 0xd9, 0xbe, 0xe8, 0x5a,
+ 0xe7, 0xed, 0x65, 0xd1, 0xb8, 0xb2, 0xa7, 0x36, 0x02, 0xb1, 0x7b, 0xff,
+ 0x7d, 0xc8, 0x1b, 0x04, 0xce, 0x8c, 0x59, 0x7d, 0xff, 0xc1, 0xd6, 0x5f,
+ 0x4b, 0xed, 0x3a, 0xca, 0xc4, 0x44, 0x1a, 0x86, 0xe4, 0x57, 0x8b, 0x3b,
+ 0x59, 0x7f, 0xee, 0xdb, 0xec, 0x79, 0xb8, 0xc4, 0xb2, 0xff, 0xd0, 0xda,
+ 0xff, 0xf2, 0x34, 0x05, 0x96, 0xfc, 0x1f, 0xe4, 0xc7, 0xf7, 0xf8, 0xf9,
+ 0xa0, 0x10, 0x40, 0xb2, 0xd2, 0x59, 0x58, 0x98, 0x23, 0x42, 0x61, 0xca,
+ 0x04, 0x33, 0xbf, 0x02, 0x3f, 0x03, 0x59, 0x50, 0xaa, 0x73, 0x14, 0xda,
+ 0x15, 0xcf, 0x19, 0x98, 0x50, 0x6f, 0xff, 0x83, 0xfe, 0x75, 0x28, 0x20,
+ 0x73, 0x60, 0x49, 0x65, 0xe8, 0xfc, 0x2c, 0xa1, 0x9f, 0x76, 0xf5, 0x3b,
+ 0xe3, 0x87, 0xe1, 0x59, 0x7b, 0xd8, 0x4b, 0x29, 0x8f, 0x8b, 0xc4, 0x81,
+ 0x23, 0xbb, 0xd3, 0x2c, 0xbe, 0xc9, 0xb2, 0x65, 0x97, 0xed, 0x07, 0xf9,
+ 0x3a, 0xcb, 0xec, 0xd0, 0xe1, 0x65, 0xb9, 0xb0, 0xfb, 0x60, 0x8c, 0x8a,
+ 0x6d, 0xe5, 0x95, 0xd1, 0xe3, 0x39, 0xad, 0xf4, 0x4b, 0x09, 0x65, 0x32,
+ 0x61, 0xaf, 0x0c, 0xb0, 0x11, 0x5e, 0xcc, 0xed, 0x65, 0xff, 0x7f, 0x99,
+ 0xa0, 0x10, 0x40, 0xb2, 0xff, 0xe8, 0xff, 0x3d, 0x0d, 0xfe, 0x44, 0xeb,
+ 0x2f, 0xd9, 0xa8, 0x9b, 0x8b, 0x2b, 0x47, 0xd9, 0xe4, 0x4b, 0xef, 0xbf,
+ 0xa1, 0x65, 0xf7, 0xfc, 0x1d, 0xb5, 0x97, 0xfb, 0x23, 0x4f, 0x26, 0xf2,
+ 0xcb, 0xfc, 0xc6, 0x72, 0x3c, 0xfb, 0x8b, 0x2b, 0x47, 0xcf, 0xf3, 0x1b,
+ 0xf7, 0xfd, 0xd6, 0x6e, 0xac, 0xa1, 0xa6, 0x3d, 0xd1, 0x13, 0x10, 0x9e,
+ 0x11, 0xbe, 0x22, 0xbf, 0x71, 0xcd, 0xf3, 0x2c, 0xbf, 0xed, 0xc1, 0xf8,
+ 0x3c, 0xea, 0x4e, 0xb2, 0xe6, 0xf6, 0x1f, 0x30, 0x4a, 0x2a, 0x15, 0x52,
+ 0xe4, 0x78, 0x6f, 0x0b, 0x6b, 0xfc, 0xd2, 0x89, 0x41, 0xe4, 0xb2, 0xf0,
+ 0x98, 0x28, 0x59, 0x7f, 0xfa, 0x35, 0x00, 0xf3, 0x46, 0x80, 0x79, 0x2c,
+ 0xbf, 0xfc, 0x10, 0x1d, 0x8b, 0x00, 0x58, 0xf3, 0x2c, 0xbf, 0xcd, 0xe6,
+ 0x82, 0x98, 0x2b, 0x2f, 0x47, 0x85, 0x2b, 0x2f, 0xf3, 0x6b, 0x30, 0xba,
+ 0xfa, 0xca, 0x84, 0x42, 0x31, 0x93, 0x90, 0x5f, 0xf8, 0x23, 0xd6, 0x07,
+ 0xd0, 0x7c, 0x59, 0x7f, 0xfd, 0x9b, 0xf3, 0x60, 0x9f, 0x6d, 0x34, 0xee,
+ 0x75, 0x97, 0xff, 0xfd, 0x80, 0xdb, 0xcd, 0x85, 0x93, 0x89, 0x2d, 0x9c,
+ 0xe3, 0x19, 0xc5, 0x95, 0xe4, 0x62, 0x12, 0xa5, 0x42, 0xab, 0x9c, 0x32,
+ 0x62, 0x1d, 0x24, 0xfa, 0x19, 0x9c, 0x2d, 0xfc, 0x60, 0x57, 0xff, 0xc5,
+ 0xa8, 0xf3, 0xb7, 0xe3, 0xc5, 0xd3, 0x2c, 0xbf, 0xf7, 0xa3, 0x40, 0xd6,
+ 0xa0, 0xfc, 0x59, 0x7e, 0x7e, 0x13, 0x42, 0xcb, 0xff, 0x9b, 0x43, 0xf0,
+ 0x75, 0x9d, 0xfb, 0x16, 0x5f, 0x9b, 0x4f, 0xba, 0xcb, 0x2a, 0x47, 0xdd,
+ 0xda, 0x2d, 0xfd, 0x3b, 0xce, 0x41, 0xfa, 0xcb, 0xef, 0x85, 0xfe, 0xb2,
+ 0xf0, 0x5f, 0xeb, 0x2b, 0x61, 0xbe, 0xf9, 0x15, 0xed, 0xf9, 0xa5, 0x95,
+ 0x07, 0x83, 0x84, 0x77, 0x37, 0x16, 0x54, 0x2a, 0x26, 0xc4, 0xd3, 0x4f,
+ 0xfa, 0x84, 0x9b, 0x11, 0x94, 0x2b, 0xb6, 0xc8, 0x2f, 0x04, 0x23, 0x59,
+ 0x7f, 0x4c, 0xde, 0xd6, 0x1d, 0x65, 0xcc, 0x62, 0xcb, 0xb7, 0x71, 0x65,
+ 0x39, 0xef, 0x70, 0xbb, 0xe2, 0xf7, 0xf7, 0x23, 0xfc, 0xf3, 0x2c, 0xbf,
+ 0x16, 0x1f, 0x58, 0xb2, 0xfb, 0x5b, 0xf0, 0x6b, 0x2b, 0x0f, 0xdc, 0xe5,
+ 0xa1, 0x26, 0xbf, 0x7a, 0x34, 0x79, 0x2c, 0xbc, 0x3c, 0xfa, 0xcb, 0xfd,
+ 0x85, 0xb3, 0xd1, 0x9b, 0x8b, 0x2f, 0xfc, 0xdf, 0xe6, 0x0e, 0x62, 0x81,
+ 0xac, 0xbe, 0x03, 0x75, 0x25, 0x97, 0xfa, 0x0b, 0xed, 0x39, 0x42, 0xcb,
+ 0xff, 0xcd, 0xa6, 0x9e, 0x0b, 0x3d, 0xa0, 0xef, 0x59, 0x52, 0x4d, 0x5c,
+ 0x65, 0x07, 0x1c, 0xf1, 0xb0, 0x0f, 0x88, 0x8f, 0xe6, 0x37, 0xff, 0xa0,
+ 0xbb, 0x7f, 0xb9, 0xa2, 0x4f, 0x13, 0xac, 0xbf, 0xf3, 0x0c, 0x3f, 0xe3,
+ 0xfd, 0xcd, 0x59, 0x7f, 0x61, 0x9d, 0x4b, 0x9b, 0x0d, 0x44, 0x63, 0xa6,
+ 0xdf, 0xff, 0xd8, 0x58, 0x6f, 0x9e, 0x6f, 0x39, 0xb9, 0xac, 0xfa, 0xcb,
+ 0xff, 0x84, 0x8e, 0x84, 0x22, 0xc6, 0xeb, 0xeb, 0x29, 0x91, 0xd7, 0xe4,
+ 0xa7, 0x5b, 0xad, 0xad, 0xd2, 0x00, 0x6d, 0x0d, 0x71, 0x1c, 0x34, 0xec,
+ 0xf2, 0x8c, 0x2c, 0x70, 0xd0, 0xc9, 0xdb, 0x43, 0x63, 0x7a, 0xec, 0x8b,
+ 0xa8, 0xc3, 0x5a, 0x32, 0x49, 0xa3, 0x18, 0xd4, 0x70, 0x27, 0x85, 0x9f,
+ 0xa5, 0x83, 0xbc, 0x64, 0x60, 0x8c, 0xec, 0x56, 0x68, 0x52, 0xb0, 0x79,
+ 0x2b, 0xcf, 0xf2, 0xa5, 0x02, 0xe3, 0xbd, 0xef, 0x6e, 0x14, 0xa2, 0x47,
+ 0x0b, 0xbb, 0x1e, 0xdd, 0xff, 0x7e, 0x07, 0xad, 0x41, 0xf8, 0xb2, 0xe3,
+ 0x7b, 0x59, 0x7f, 0x1e, 0x51, 0x1c, 0x65, 0x97, 0x38, 0x16, 0x54, 0x1e,
+ 0x13, 0x96, 0x5f, 0x0d, 0xdf, 0xa5, 0x97, 0xf3, 0x74, 0xdd, 0xc0, 0x8b,
+ 0x29, 0xcf, 0x44, 0x88, 0xaf, 0x30, 0x87, 0x59, 0x7f, 0x16, 0x7b, 0xa7,
+ 0xdc, 0x59, 0x7b, 0xb7, 0xde, 0xb2, 0xef, 0x8b, 0x84, 0xe4, 0x4e, 0x73,
+ 0xe5, 0xb7, 0x71, 0x01, 0x07, 0x07, 0x7e, 0x61, 0x7f, 0xff, 0xf0, 0x7a,
+ 0x90, 0xb7, 0x2f, 0xe1, 0xf8, 0x3f, 0x46, 0x86, 0xee, 0x62, 0xcb, 0xff,
+ 0xa0, 0xc1, 0x78, 0x50, 0x66, 0xa0, 0xeb, 0x28, 0x5a, 0xe5, 0x56, 0x4b,
+ 0x7e, 0x27, 0x1f, 0xba, 0xdf, 0xfe, 0x16, 0x77, 0x90, 0xbc, 0xd7, 0x6e,
+ 0xfd, 0xaa, 0x26, 0x95, 0xff, 0xe1, 0x67, 0x79, 0x0b, 0xcd, 0x76, 0xef,
+ 0xda, 0xa2, 0x71, 0x5e, 0x01, 0x42, 0xcb, 0xf4, 0x98, 0x80, 0xcb, 0x2f,
+ 0xd2, 0xcf, 0xca, 0x4b, 0x2f, 0xf6, 0xf8, 0xf6, 0xc2, 0x89, 0x2c, 0xbf,
+ 0xf3, 0xc8, 0x5e, 0x6b, 0xb7, 0x7e, 0xd5, 0x14, 0x0a, 0xff, 0xf3, 0x41,
+ 0xdc, 0x7a, 0x8f, 0xfb, 0x06, 0xb2, 0xfb, 0x85, 0xd4, 0x96, 0x58, 0x5c,
+ 0x26, 0xb1, 0x83, 0x7d, 0x13, 0x31, 0x41, 0xcd, 0xbc, 0x9d, 0xf4, 0x8b,
+ 0xb6, 0xb1, 0x42, 0xcb, 0xee, 0xdd, 0xfb, 0x54, 0x5c, 0x0b, 0xfc, 0x3f,
+ 0x46, 0xde, 0x6a, 0x16, 0x56, 0x8f, 0x94, 0x8c, 0x2e, 0xeb, 0x8b, 0x2f,
+ 0x8d, 0xed, 0xc6, 0xb2, 0xe8, 0x11, 0x65, 0xfc, 0x59, 0xfe, 0xdb, 0x8b,
+ 0x2e, 0x86, 0x59, 0x7d, 0xe0, 0xbc, 0x96, 0x5f, 0xe2, 0x94, 0x30, 0xf0,
+ 0xeb, 0x28, 0x50, 0x9c, 0x76, 0x42, 0x17, 0xa2, 0x16, 0x18, 0xd1, 0x21,
+ 0xc5, 0xfc, 0x5b, 0xf1, 0x50, 0x91, 0x5f, 0xa4, 0x2c, 0xd1, 0x49, 0xab,
+ 0x28, 0x5a, 0x2e, 0x22, 0x10, 0xf7, 0xfb, 0x6a, 0xda, 0xc5, 0x32, 0x04,
+ 0x99, 0x65, 0xfc, 0x78, 0xf8, 0x66, 0x75, 0x97, 0x38, 0x16, 0x5f, 0xa6,
+ 0x94, 0x14, 0x96, 0x52, 0xca, 0xc3, 0x66, 0x45, 0x17, 0xf4, 0xb0, 0xd2,
+ 0xc0, 0x2c, 0xbc, 0x0c, 0x31, 0x65, 0xf1, 0x46, 0x79, 0x65, 0x41, 0xbd,
+ 0x9c, 0x76, 0xe6, 0x16, 0x2a, 0x26, 0xc7, 0x08, 0x5a, 0x2e, 0x24, 0x9f,
+ 0x8f, 0x88, 0xd5, 0x7f, 0xe2, 0xcf, 0xf5, 0xdb, 0x73, 0xcc, 0xb2, 0xfd,
+ 0xae, 0xdd, 0xfb, 0x54, 0x49, 0x2b, 0xa4, 0x2e, 0x0f, 0xd7, 0x0f, 0xec,
+ 0x2f, 0xc9, 0x86, 0x3c, 0x37, 0xaf, 0xd8, 0x60, 0x03, 0xc5, 0x97, 0x18,
+ 0x05, 0x97, 0xfe, 0xef, 0xd1, 0xac, 0xf9, 0x41, 0xd6, 0x5f, 0xe7, 0xf9,
+ 0x64, 0xee, 0x4b, 0x2f, 0xd1, 0x31, 0x40, 0xd6, 0x5c, 0x69, 0x8b, 0x2f,
+ 0xe9, 0x3e, 0xa7, 0x1c, 0x2c, 0xbf, 0xb0, 0x9f, 0xa9, 0x71, 0x65, 0xff,
+ 0xf8, 0x24, 0xe6, 0xfc, 0xd8, 0x29, 0x67, 0x98, 0xeb, 0x2f, 0xff, 0xd9,
+ 0xdc, 0x7a, 0x0f, 0xdf, 0x9b, 0xf9, 0x87, 0x59, 0x7e, 0x3e, 0xb0, 0x7f,
+ 0x59, 0x7f, 0xa3, 0xa1, 0x3e, 0x50, 0x05, 0x95, 0x07, 0xb8, 0x12, 0x8b,
+ 0xf6, 0xef, 0xa0, 0x8d, 0x59, 0x61, 0xac, 0xbf, 0xa7, 0x2c, 0xde, 0x18,
+ 0x59, 0x53, 0x9e, 0x03, 0x88, 0xdc, 0xe2, 0xe7, 0x55, 0xfe, 0x32, 0x9c,
+ 0x18, 0x34, 0xfb, 0xb3, 0x1e, 0x89, 0xe6, 0x19, 0xd1, 0x71, 0xcb, 0x49,
+ 0x57, 0x90, 0xb1, 0xf9, 0x0e, 0xdb, 0x5d, 0x4e, 0xed, 0x28, 0x65, 0x6a,
+ 0x41, 0xbb, 0x47, 0x99, 0x70, 0x11, 0xda, 0x72, 0x55, 0x8f, 0xe5, 0x4c,
+ 0x6f, 0x96, 0x5f, 0x7e, 0xd7, 0xc8, 0x3f, 0x59, 0x7f, 0xe3, 0x5c, 0x5e,
+ 0x6b, 0xb7, 0x7e, 0xd5, 0x16, 0xa2, 0xfb, 0x91, 0xfe, 0x2c, 0xbf, 0xf3,
+ 0xc8, 0x5e, 0x6b, 0xb7, 0x7e, 0xd5, 0x12, 0xaa, 0xe6, 0x31, 0x65, 0x2c,
+ 0xb0, 0xbc, 0x4c, 0x24, 0xd2, 0x8e, 0x93, 0xce, 0x45, 0xf4, 0xed, 0xd1,
+ 0x7b, 0xfb, 0x35, 0xdb, 0xbf, 0x6a, 0x88, 0xa5, 0x7f, 0xe7, 0x73, 0xe6,
+ 0x80, 0x41, 0x02, 0xcb, 0xff, 0x47, 0xf9, 0x9a, 0x01, 0x04, 0x0b, 0x2f,
+ 0x9b, 0x90, 0xeb, 0x2f, 0xf1, 0x38, 0x39, 0xfc, 0xed, 0x65, 0xc7, 0x17,
+ 0xe4, 0x67, 0x11, 0xef, 0x0f, 0xbe, 0x41, 0x42, 0xd3, 0x53, 0x78, 0xc2,
+ 0x6f, 0xda, 0xed, 0xdf, 0xb5, 0x44, 0x68, 0xbf, 0x89, 0x87, 0xa6, 0x9d,
+ 0x65, 0x85, 0xe1, 0xf1, 0xb1, 0xb5, 0xe1, 0x57, 0xb7, 0xb5, 0xac, 0xbe,
+ 0xda, 0xb6, 0x90, 0xab, 0x15, 0x6b, 0x2e, 0x0f, 0x96, 0x5f, 0xf8, 0x78,
+ 0x76, 0xd6, 0x72, 0x68, 0x59, 0x7f, 0xbf, 0xf6, 0x7d, 0xf1, 0xf5, 0x97,
+ 0xff, 0xf8, 0x3c, 0xf6, 0x0c, 0x41, 0x38, 0xc2, 0x7d, 0xb9, 0x30, 0x8b,
+ 0x2a, 0x11, 0x36, 0xe6, 0x97, 0xff, 0xa6, 0x66, 0xf4, 0xd9, 0xf8, 0xfc,
+ 0x0d, 0x65, 0xe6, 0x73, 0x12, 0x5f, 0xfa, 0x23, 0x7c, 0x14, 0x4d, 0x13,
+ 0x2c, 0xbf, 0x4d, 0xc7, 0xcf, 0xac, 0xbf, 0xda, 0xd4, 0x75, 0xcf, 0x0d,
+ 0x65, 0xbd, 0x07, 0xba, 0xc5, 0x17, 0xff, 0xd1, 0xe8, 0x9b, 0x81, 0xf8,
+ 0x43, 0x34, 0x6f, 0x59, 0x4c, 0xa9, 0xdb, 0x72, 0x1b, 0x33, 0x10, 0x9d,
+ 0x28, 0x87, 0x3f, 0x09, 0xcd, 0xe4, 0xd7, 0xdd, 0xbb, 0xf6, 0xa8, 0xa7,
+ 0xd7, 0xff, 0x9b, 0x5e, 0x7f, 0xf1, 0xfa, 0x72, 0x02, 0xcb, 0xbf, 0x0b,
+ 0x2b, 0x48, 0x8f, 0xf1, 0x87, 0xd2, 0x6f, 0x8c, 0xee, 0x61, 0x4a, 0xcb,
+ 0xff, 0xef, 0x37, 0xf9, 0x9b, 0xfc, 0xdb, 0x79, 0xa3, 0x56, 0x5f, 0xe6,
+ 0xfb, 0x7f, 0xc1, 0xfa, 0xcb, 0xe8, 0x3e, 0x9d, 0x65, 0xfe, 0x8f, 0xf9,
+ 0xe6, 0xd9, 0x8b, 0x2e, 0x6e, 0x96, 0x54, 0xc7, 0x99, 0xa3, 0x5a, 0xd2,
+ 0x30, 0xc8, 0xcf, 0xed, 0xb7, 0xfc, 0xf2, 0x61, 0xfa, 0x25, 0xc5, 0x97,
+ 0xe0, 0xff, 0xf1, 0xbd, 0x65, 0xff, 0xd1, 0x34, 0xcc, 0x08, 0x9a, 0x6c,
+ 0x02, 0xcb, 0xde, 0x68, 0xd1, 0xf8, 0x91, 0x55, 0xde, 0x0a, 0xca, 0xc3,
+ 0xc8, 0x09, 0x8d, 0xfb, 0x3c, 0xc5, 0xf5, 0x97, 0xff, 0x1c, 0x83, 0xe6,
+ 0xd6, 0x72, 0x68, 0x59, 0x7f, 0xff, 0xfe, 0x8f, 0xb1, 0x3f, 0x39, 0x9f,
+ 0xf3, 0x9f, 0xd8, 0x51, 0x1c, 0x70, 0xef, 0x59, 0x7c, 0xf3, 0x37, 0x96,
+ 0x5f, 0xfe, 0xd6, 0x34, 0xdc, 0x0c, 0x74, 0x51, 0xf5, 0x97, 0xed, 0xe1,
+ 0xdc, 0x80, 0x2c, 0xa9, 0x27, 0x06, 0xc4, 0xda, 0x44, 0x3c, 0x20, 0x3e,
+ 0x44, 0x14, 0xab, 0xee, 0xbe, 0x1d, 0x2c, 0xbf, 0xf7, 0xf4, 0x19, 0xb9,
+ 0xdb, 0xcd, 0xc5, 0x95, 0x87, 0xce, 0x12, 0x4b, 0xfc, 0xe5, 0x1f, 0x28,
+ 0xfa, 0xcb, 0xff, 0x47, 0xfa, 0xcf, 0xc4, 0xcd, 0xc5, 0x97, 0xfe, 0x98,
+ 0x25, 0x3f, 0x3b, 0x79, 0xb8, 0xb2, 0xa1, 0x10, 0x58, 0x7f, 0x73, 0xf1,
+ 0x65, 0xf8, 0x33, 0x4c, 0xe6, 0xac, 0xbf, 0xef, 0xc7, 0x4f, 0x36, 0xa3,
+ 0x7a, 0xca, 0xdc, 0x3f, 0xde, 0x0b, 0x7c, 0xae, 0xf8, 0x3e, 0x6d, 0x2c,
+ 0xb6, 0x2c, 0xb0, 0xbd, 0xad, 0x95, 0x87, 0xb5, 0x15, 0xed, 0x07, 0x51,
+ 0x2a, 0x37, 0x23, 0x03, 0x34, 0xc3, 0xb2, 0xa6, 0x8c, 0x60, 0xe5, 0xfe,
+ 0x87, 0x8b, 0xc7, 0x48, 0x50, 0xc3, 0xe1, 0x0f, 0xe1, 0x64, 0x18, 0x4f,
+ 0x6d, 0x99, 0x6e, 0x91, 0x5f, 0xfe, 0x16, 0x77, 0x90, 0xbc, 0xd7, 0x6e,
+ 0xfd, 0xaa, 0x26, 0xa5, 0xfd, 0x9a, 0xed, 0xdf, 0xb5, 0x45, 0x76, 0xbf,
+ 0xfd, 0x9b, 0xad, 0xf6, 0x96, 0xc2, 0x8f, 0xf1, 0x65, 0x2c, 0xb8, 0xc1,
+ 0x7e, 0x3d, 0x83, 0x13, 0x68, 0x5a, 0x31, 0x5a, 0x12, 0x77, 0x01, 0x96,
+ 0x58, 0x6b, 0x2e, 0x83, 0xac, 0xaf, 0x1a, 0x7e, 0x08, 0xdb, 0x6d, 0x65,
+ 0x89, 0x65, 0x4e, 0x69, 0x0e, 0x29, 0x74, 0xf0, 0xb2, 0xfb, 0xb7, 0x7e,
+ 0xd5, 0x15, 0xf2, 0xf1, 0x86, 0x18, 0x92, 0xc4, 0x90, 0x59, 0xa0, 0xad,
+ 0x1f, 0x91, 0xd4, 0x2f, 0xf7, 0xb0, 0xd7, 0x8e, 0xb7, 0x56, 0x5e, 0x94,
+ 0x74, 0xb2, 0xfb, 0x3f, 0xe6, 0x59, 0x70, 0x78, 0xb2, 0xec, 0xf2, 0xca,
+ 0x19, 0xad, 0x98, 0x5e, 0xe7, 0xde, 0xb2, 0xff, 0x18, 0xff, 0xe4, 0x64,
+ 0xeb, 0x2f, 0x72, 0x00, 0xb2, 0xbc, 0x7a, 0x1f, 0x34, 0xbe, 0x27, 0xeb,
+ 0x8b, 0x2b, 0x0f, 0x13, 0xe4, 0x57, 0x8c, 0xcd, 0x2c, 0xb7, 0xd6, 0x5f,
+ 0xf3, 0x6b, 0x27, 0x69, 0x60, 0xd6, 0x5f, 0xed, 0x03, 0xfc, 0x70, 0x62,
+ 0xca, 0x64, 0x4c, 0xe8, 0x75, 0xc4, 0x42, 0x71, 0x7b, 0xc4, 0x05, 0x97,
+ 0xdb, 0xbe, 0x08, 0x8b, 0x2f, 0x4d, 0x93, 0x2c, 0xb3, 0x2c, 0xae, 0x8f,
+ 0x56, 0x62, 0x73, 0x8f, 0x5b, 0x4b, 0x29, 0x65, 0x31, 0x79, 0xa1, 0x1a,
+ 0x59, 0x66, 0x59, 0x69, 0xcd, 0x2e, 0xfc, 0x17, 0x6d, 0xeb, 0x2b, 0xc7,
+ 0xea, 0xe7, 0x41, 0x28, 0xbe, 0xc2, 0x89, 0x2c, 0xb0, 0xb1, 0x51, 0x74,
+ 0xd6, 0x0f, 0x67, 0x45, 0x91, 0x16, 0x42, 0x27, 0xb2, 0x29, 0x8d, 0xf4,
+ 0x3a, 0xe9, 0xc0, 0x22, 0x28, 0x56, 0x72, 0x17, 0x5f, 0x3b, 0x0b, 0x8e,
+ 0xdc, 0x30, 0x84, 0x2e, 0xbf, 0xfc, 0x2c, 0xef, 0x21, 0x79, 0xae, 0xdd,
+ 0xfb, 0x54, 0x4f, 0x6b, 0x0a, 0xd6, 0x5f, 0xf0, 0xdf, 0xb8, 0xec, 0x24,
+ 0x35, 0x97, 0xff, 0xcd, 0x2e, 0x6e, 0x78, 0x3d, 0xe4, 0xfb, 0x07, 0xa5,
+ 0x97, 0xd1, 0xba, 0xfd, 0x2c, 0xbc, 0xc4, 0x05, 0x95, 0x3a, 0x34, 0xa4,
+ 0x75, 0xe5, 0x8d, 0xe4, 0xb7, 0xff, 0x07, 0x53, 0x69, 0xa7, 0x73, 0xb7,
+ 0x16, 0x5f, 0x98, 0x71, 0xae, 0x2c, 0xbf, 0x6b, 0xb7, 0x7e, 0xd5, 0x17,
+ 0x0a, 0xf8, 0xe1, 0xff, 0x16, 0x5f, 0xef, 0x34, 0x82, 0x08, 0x99, 0x65,
+ 0xfd, 0x0d, 0xad, 0x31, 0x8b, 0x2c, 0x2c, 0x52, 0xa9, 0x3a, 0x21, 0xcf,
+ 0x3a, 0x04, 0x91, 0xb0, 0x9c, 0xd3, 0x66, 0x23, 0x39, 0xa5, 0xff, 0xc2,
+ 0xde, 0x42, 0xf3, 0x5d, 0xbb, 0xf6, 0xa8, 0x93, 0xd7, 0xfe, 0x69, 0x85,
+ 0xc0, 0x63, 0xf0, 0x05, 0x97, 0xf8, 0xd1, 0x73, 0x7a, 0x08, 0xd5, 0x95,
+ 0x0d, 0xce, 0xdc, 0xf1, 0xdb, 0xca, 0x11, 0xc6, 0xd2, 0xba, 0xfb, 0x8c,
+ 0xc6, 0x68, 0xc8, 0x75, 0x3a, 0xbd, 0xe8, 0xc0, 0x39, 0x2a, 0xab, 0x7c,
+ 0x20, 0xcc, 0x56, 0x11, 0x02, 0xff, 0x0b, 0xcd, 0x76, 0xef, 0xda, 0xa2,
+ 0x2a, 0x5f, 0xb5, 0xdb, 0xbf, 0x6a, 0x8a, 0x65, 0x7f, 0x37, 0xb1, 0xfa,
+ 0x02, 0xcb, 0x0b, 0xc3, 0xe3, 0xdb, 0x36, 0xbf, 0xfc, 0x2c, 0xef, 0x21,
+ 0x79, 0xae, 0xdd, 0xfb, 0x54, 0x4c, 0xeb, 0xff, 0xc2, 0xce, 0xf2, 0x17,
+ 0x9a, 0xed, 0xdf, 0xb5, 0x45, 0x1a, 0xa9, 0xd3, 0x8a, 0x1c, 0x29, 0x8d,
+ 0x2c, 0xfa, 0xe5, 0xff, 0x9e, 0x42, 0xf3, 0x5d, 0xbb, 0xf6, 0xa8, 0x8e,
+ 0x97, 0xf1, 0x67, 0xf9, 0x07, 0x59, 0x7a, 0x3f, 0xc5, 0x97, 0xb5, 0x38,
+ 0xbe, 0x1e, 0x40, 0x85, 0x97, 0xff, 0xfb, 0x52, 0x17, 0x84, 0x1f, 0x84,
+ 0xdf, 0xf5, 0xdb, 0x6b, 0x8b, 0x28, 0x5a, 0x66, 0xb1, 0x09, 0x66, 0x38,
+ 0xb8, 0x3e, 0x59, 0x7e, 0x14, 0x0a, 0x75, 0xce, 0x2c, 0xbe, 0xef, 0xb0,
+ 0xf6, 0xb2, 0xfb, 0x81, 0x3b, 0x2c, 0xb8, 0xcf, 0x2c, 0xa6, 0x37, 0x46,
+ 0x11, 0x5f, 0xb0, 0x87, 0x93, 0xac, 0xbf, 0xe6, 0xd7, 0x0b, 0x07, 0xe8,
+ 0x59, 0x7f, 0xa2, 0x3b, 0xcd, 0x6b, 0x16, 0x53, 0x22, 0x43, 0xc4, 0xe4,
+ 0x6f, 0x7e, 0xcd, 0x76, 0x13, 0x56, 0x5f, 0xf7, 0x70, 0x7c, 0x63, 0xc6,
+ 0xe2, 0xcb, 0xe6, 0xd3, 0xb2, 0xcb, 0xff, 0x16, 0x1a, 0xf3, 0x73, 0xd0,
+ 0x35, 0x97, 0xa6, 0x7f, 0xac, 0xbe, 0xed, 0xdf, 0xb5, 0x45, 0x34, 0xbf,
+ 0x67, 0x46, 0x3f, 0x96, 0x5f, 0xfd, 0xcc, 0x21, 0xc6, 0xc1, 0x53, 0x78,
+ 0x19, 0x65, 0x0d, 0x38, 0x6c, 0x2a, 0x34, 0xed, 0x88, 0x26, 0x3f, 0xd0,
+ 0xe9, 0x18, 0x70, 0xa6, 0xfb, 0x4e, 0x36, 0x59, 0x7f, 0xfb, 0xb7, 0xd7,
+ 0x3c, 0xed, 0xce, 0x67, 0x16, 0x5f, 0xff, 0xf6, 0x17, 0xf8, 0xdd, 0xe1,
+ 0x73, 0xbf, 0x37, 0xbb, 0x12, 0x75, 0x97, 0xfd, 0xc7, 0xeb, 0x26, 0x8f,
+ 0x71, 0x65, 0x9b, 0xc8, 0xee, 0x24, 0xaf, 0xb5, 0x5f, 0xed, 0x4f, 0xcd,
+ 0x6a, 0x0c, 0x59, 0x7f, 0x64, 0xf9, 0xde, 0x0d, 0x65, 0x79, 0x13, 0x0e,
+ 0x68, 0x46, 0xd7, 0xfe, 0xf3, 0x14, 0xfc, 0x0c, 0x6a, 0x65, 0x97, 0xff,
+ 0xec, 0x9e, 0x38, 0xda, 0xcd, 0x98, 0xc5, 0x07, 0x59, 0x52, 0x44, 0xa7,
+ 0xd0, 0x2f, 0x48, 0xf2, 0x59, 0x7d, 0xfe, 0x38, 0x16, 0x5e, 0x07, 0xd9,
+ 0x65, 0xfe, 0xe7, 0x6d, 0xad, 0x34, 0xeb, 0x2a, 0x0f, 0xcd, 0xc8, 0xb8,
+ 0x39, 0x7f, 0xff, 0x4e, 0x1d, 0x4d, 0xc9, 0xe2, 0x6e, 0x7b, 0x06, 0xdb,
+ 0xd6, 0x5f, 0xff, 0xef, 0x39, 0xa5, 0x92, 0xf4, 0x4b, 0x3c, 0x58, 0xf3,
+ 0xac, 0xbf, 0xec, 0xd3, 0xc3, 0x14, 0x1d, 0x65, 0xff, 0xff, 0xf4, 0x75,
+ 0xdf, 0xb3, 0x67, 0xb3, 0xbf, 0x37, 0xb0, 0x9c, 0xdc, 0xdf, 0x1d, 0x2c,
+ 0xbf, 0x4f, 0xb3, 0xc0, 0xde, 0xb2, 0xa7, 0x4e, 0x9c, 0x6c, 0x5c, 0x5f,
+ 0xde, 0x6a, 0x24, 0x20, 0xef, 0xfb, 0x7f, 0x7e, 0x60, 0x79, 0x8e, 0xb2,
+ 0xff, 0x4b, 0x64, 0x11, 0xbe, 0x65, 0x95, 0x88, 0xc5, 0x65, 0x47, 0x3c,
+ 0xbb, 0x41, 0x59, 0x7d, 0x9e, 0x13, 0x4b, 0x28, 0xe6, 0xe8, 0x85, 0xee,
+ 0x3e, 0xda, 0xcb, 0xf9, 0xcb, 0xbd, 0x93, 0xf1, 0x65, 0x00, 0xf2, 0xc2,
+ 0x35, 0x7f, 0x41, 0x7f, 0x6f, 0x3e, 0xb2, 0xff, 0xd1, 0xe8, 0x3c, 0x17,
+ 0xfc, 0xcb, 0x2f, 0xf3, 0x81, 0xff, 0xfc, 0xf2, 0xca, 0x92, 0x27, 0x7b,
+ 0x2f, 0x30, 0xf2, 0xfb, 0xcd, 0x9a, 0x59, 0x77, 0x82, 0xb2, 0xd2, 0x59,
+ 0x58, 0x7f, 0x6c, 0x64, 0x02, 0x1d, 0xe2, 0xf7, 0xbc, 0x60, 0x16, 0x5b,
+ 0xeb, 0x29, 0x8d, 0x7f, 0x87, 0xae, 0x1c, 0x2c, 0xbf, 0xff, 0x7f, 0x82,
+ 0x73, 0x50, 0x3c, 0xf7, 0x78, 0x53, 0xac, 0xa8, 0x3e, 0xec, 0x16, 0xbf,
+ 0xa1, 0x80, 0xff, 0x0a, 0xcb, 0xff, 0x60, 0x33, 0x26, 0x98, 0xa0, 0x6b,
+ 0x2b, 0x13, 0x18, 0x3c, 0x23, 0xbc, 0x40, 0x45, 0x97, 0xbf, 0x12, 0x59,
+ 0x7f, 0xc1, 0xff, 0xb2, 0x69, 0x47, 0x4b, 0x2f, 0xff, 0x13, 0xff, 0x3f,
+ 0xcc, 0xf6, 0x6e, 0x7d, 0x65, 0x79, 0x14, 0x44, 0x39, 0xbc, 0xee, 0xd3,
+ 0x2c, 0xb9, 0xfc, 0xb2, 0xfd, 0x9e, 0x72, 0x1a, 0xca, 0x9c, 0xf3, 0xa4,
+ 0x24, 0x01, 0x6b, 0xa0, 0xd5, 0x97, 0xf3, 0x83, 0x9b, 0x4f, 0x69, 0xed,
+ 0x35, 0x97, 0xf3, 0x41, 0xe7, 0xc3, 0x16, 0x5f, 0xff, 0x67, 0xfd, 0x92,
+ 0xd3, 0x97, 0xfc, 0xf2, 0x59, 0x74, 0x01, 0x65, 0xfe, 0x7e, 0xa3, 0xb6,
+ 0xec, 0x5e, 0x91, 0x24, 0x45, 0xc2, 0x27, 0x56, 0x27, 0xe8, 0xcf, 0xfe,
+ 0x30, 0x21, 0x7e, 0x43, 0x4a, 0xf3, 0xcd, 0xc5, 0x97, 0xe2, 0xe7, 0xb3,
+ 0x71, 0x65, 0xb4, 0xb2, 0xb0, 0xdd, 0x88, 0x55, 0x7e, 0x07, 0xa2, 0x5c,
+ 0x59, 0x78, 0x82, 0x6a, 0xcb, 0xc6, 0x3c, 0xeb, 0x2f, 0xfa, 0x00, 0xff,
+ 0x00, 0x85, 0x25, 0x95, 0xe3, 0xd7, 0x21, 0xea, 0x84, 0x5e, 0x91, 0x47,
+ 0xdd, 0x2c, 0x2f, 0x68, 0x6c, 0x52, 0x85, 0x50, 0xbc, 0x18, 0xc9, 0x80,
+ 0x70, 0xb1, 0xc8, 0xed, 0x0d, 0x71, 0xee, 0x3a, 0x7e, 0xa1, 0x84, 0xc4,
+ 0x7a, 0x84, 0x87, 0xa5, 0x4c, 0xbb, 0x38, 0x1a, 0xca, 0x33, 0xae, 0x47,
+ 0x07, 0xf9, 0x5a, 0xe1, 0x4d, 0xdb, 0x58, 0x12, 0x1b, 0xd7, 0x4f, 0xb6,
+ 0xb2, 0xf9, 0x88, 0x0c, 0xb2, 0xfb, 0xb7, 0x7e, 0xd5, 0x15, 0x52, 0xa4,
+ 0x7a, 0x1a, 0x20, 0xbf, 0x6b, 0xb7, 0x7e, 0xd5, 0x13, 0x6a, 0xfb, 0xfa,
+ 0x6e, 0x96, 0x5e, 0x79, 0x0b, 0xc3, 0xd9, 0x63, 0x6b, 0x0b, 0x9d, 0x31,
+ 0x9c, 0x6b, 0x3b, 0xdd, 0xfe, 0x17, 0x9a, 0xed, 0xdf, 0xb5, 0x45, 0x7e,
+ 0xbf, 0x6b, 0xb7, 0x7e, 0xd5, 0x16, 0x32, 0xed, 0xd9, 0x2c, 0xb0, 0xbc,
+ 0x3d, 0x09, 0x8d, 0xaf, 0xdc, 0xef, 0xd0, 0x6a, 0xcb, 0xfe, 0x9e, 0x38,
+ 0xe0, 0xe3, 0x0d, 0x65, 0xfc, 0x19, 0x67, 0x1f, 0xeb, 0x2f, 0xf0, 0x73,
+ 0x5d, 0xf9, 0xb8, 0xb2, 0xb4, 0x89, 0xa2, 0x39, 0xe1, 0x6d, 0xfe, 0xd4,
+ 0x19, 0xb6, 0x27, 0x9d, 0x65, 0xf8, 0x7b, 0x46, 0xd0, 0x46, 0xac, 0xbe,
+ 0xff, 0x1f, 0xa5, 0x95, 0xb5, 0x9e, 0xb4, 0x19, 0xdf, 0xf1, 0x06, 0x79,
+ 0xa5, 0x1a, 0x9d, 0x65, 0xda, 0xfa, 0xcb, 0xe7, 0x96, 0x0d, 0x65, 0xfd,
+ 0xfc, 0xd0, 0xf0, 0x96, 0x5b, 0x06, 0x79, 0xbf, 0x21, 0xba, 0x58, 0xb2,
+ 0xfe, 0x77, 0xff, 0xf3, 0xcb, 0x2f, 0xff, 0x61, 0xc9, 0xcd, 0x2c, 0x06,
+ 0xc3, 0x05, 0x0b, 0x28, 0xd4, 0x49, 0x68, 0x58, 0x8b, 0x2f, 0xf1, 0x90,
+ 0x63, 0x97, 0x5f, 0x59, 0x7e, 0xd7, 0xfd, 0x93, 0xac, 0xa8, 0x3d, 0xec,
+ 0x35, 0xbf, 0xbe, 0xc7, 0xea, 0x5c, 0x59, 0x61, 0x78, 0xac, 0x67, 0x45,
+ 0xe7, 0x84, 0x77, 0x89, 0x9c, 0xf0, 0x99, 0x39, 0x0b, 0x91, 0x21, 0x1d,
+ 0xba, 0x41, 0x66, 0x16, 0xb8, 0xeb, 0xa9, 0x7b, 0xb7, 0xed, 0x76, 0xef,
+ 0xda, 0xa2, 0xd5, 0x5f, 0xb5, 0xdb, 0xbf, 0x6a, 0x8a, 0x09, 0x74, 0xfe,
+ 0x59, 0x79, 0xe4, 0x2f, 0x0f, 0x38, 0x06, 0xd7, 0xe8, 0x33, 0x6f, 0x34,
+ 0xb2, 0xc2, 0xf1, 0x1c, 0x67, 0x84, 0x20, 0x86, 0x97, 0xdf, 0xd3, 0xf9,
+ 0x65, 0xfd, 0xe6, 0x9e, 0x70, 0xf1, 0x65, 0xfd, 0x83, 0xd4, 0x7f, 0x8b,
+ 0x2f, 0xe8, 0x3b, 0xf5, 0xf9, 0x2c, 0xac, 0x45, 0x6f, 0x64, 0x44, 0x61,
+ 0xc2, 0xdb, 0xfb, 0x3c, 0x2d, 0xf5, 0xf5, 0x97, 0x39, 0x82, 0xcf, 0xaf,
+ 0xe7, 0x97, 0xf0, 0xaa, 0xda, 0xbf, 0xb7, 0x9e, 0x59, 0x7f, 0xa0, 0x81,
+ 0x1b, 0x8e, 0x75, 0x97, 0xff, 0xa6, 0x8d, 0xef, 0xae, 0x71, 0xb5, 0x86,
+ 0xac, 0xbf, 0xcd, 0x34, 0x6f, 0x7d, 0x71, 0x65, 0xb8, 0xb2, 0xa0, 0xf1,
+ 0x88, 0xd6, 0xff, 0xe8, 0x00, 0x7f, 0xc2, 0x8d, 0xd8, 0x9d, 0x65, 0xda,
+ 0x85, 0x95, 0x24, 0xd1, 0x18, 0xd3, 0xd0, 0x93, 0xde, 0x41, 0xba, 0x8f,
+ 0x7c, 0xde, 0x7e, 0x2c, 0xbe, 0xed, 0xdf, 0xb5, 0x45, 0xc4, 0xbf, 0x82,
+ 0xfd, 0x0f, 0x34, 0xb2, 0xb4, 0x7b, 0xdc, 0x30, 0xbf, 0xff, 0x48, 0x4f,
+ 0x49, 0xfe, 0xe0, 0x09, 0x3e, 0xf1, 0xac, 0xb8, 0x49, 0x96, 0x5f, 0xf7,
+ 0x31, 0x80, 0x27, 0xdf, 0xcb, 0x2f, 0xdd, 0xb7, 0x3c, 0xcb, 0x2e, 0x6e,
+ 0x96, 0x57, 0x46, 0xff, 0x45, 0x15, 0x3a, 0x2c, 0xfc, 0x33, 0xf7, 0x8b,
+ 0xff, 0xe9, 0x47, 0xc1, 0xb3, 0x3d, 0xac, 0x00, 0x66, 0x59, 0x76, 0x1a,
+ 0xb2, 0xff, 0x6f, 0xcf, 0xf3, 0x7c, 0x79, 0x65, 0x48, 0xf3, 0xbc, 0x2f,
+ 0x58, 0x8c, 0x36, 0x85, 0x0d, 0xff, 0xbe, 0x4e, 0x0e, 0x7a, 0x0b, 0xeb,
+ 0x2f, 0xd8, 0x76, 0xdd, 0x1a, 0xcb, 0xa0, 0xeb, 0x2a, 0x0f, 0xf7, 0x70,
+ 0xf7, 0x45, 0x57, 0xf0, 0x49, 0xcd, 0x90, 0x16, 0x5f, 0x3e, 0xeb, 0x4e,
+ 0xb2, 0xfd, 0xe0, 0x9b, 0x84, 0xb2, 0xfc, 0x3c, 0xdc, 0x8f, 0x2c, 0xbd,
+ 0xba, 0xdd, 0xac, 0xa1, 0x9f, 0x96, 0x8a, 0x37, 0x4a, 0xaf, 0xf1, 0xde,
+ 0x5c, 0x61, 0xe2, 0xcb, 0xc6, 0xc7, 0x16, 0x5f, 0xe9, 0x44, 0xcf, 0xe8,
+ 0xdc, 0x59, 0x7f, 0xe9, 0x83, 0x21, 0x37, 0xc7, 0x9f, 0x7a, 0xca, 0x84,
+ 0x4c, 0x60, 0xeb, 0x9b, 0x5b, 0x8b, 0x2f, 0xfb, 0x3d, 0xf2, 0x80, 0x6c,
+ 0x65, 0x97, 0xe2, 0xf9, 0x39, 0xab, 0x29, 0x65, 0x61, 0xb2, 0xdb, 0x27,
+ 0xa7, 0x44, 0xf9, 0x08, 0xf1, 0xae, 0xfe, 0x3b, 0xef, 0x8d, 0x6e, 0xac,
+ 0xbf, 0xf3, 0x0f, 0x37, 0x9f, 0x25, 0xd4, 0x96, 0x5f, 0x9f, 0x8e, 0x40,
+ 0x59, 0x7f, 0x36, 0xf9, 0x1e, 0x26, 0x59, 0x7f, 0xe8, 0xc2, 0x3c, 0x7b,
+ 0x75, 0xf7, 0x56, 0x54, 0x8f, 0xcb, 0x46, 0x17, 0xfd, 0x87, 0xcd, 0x64,
+ 0xf8, 0x62, 0xca, 0x84, 0xd9, 0xb0, 0xc8, 0xd4, 0x16, 0x84, 0xc7, 0x88,
+ 0xad, 0xb5, 0xac, 0xbf, 0xb3, 0x4f, 0xf0, 0xc2, 0xcb, 0xff, 0xe7, 0x28,
+ 0x6d, 0xde, 0x37, 0x33, 0xd9, 0xb6, 0xb2, 0x86, 0x7f, 0xdb, 0xcb, 0x2f,
+ 0xfe, 0x62, 0x0c, 0xb3, 0x9c, 0x61, 0xe2, 0xca, 0x98, 0xf9, 0xbe, 0x49,
+ 0x61, 0x62, 0xa3, 0x2b, 0x52, 0x23, 0x80, 0x92, 0xa6, 0x3f, 0xf4, 0x44,
+ 0xd1, 0x85, 0xcd, 0x0f, 0x4d, 0x42, 0x8c, 0xe6, 0x3e, 0x2e, 0x78, 0x4b,
+ 0x80, 0xc8, 0xa1, 0x95, 0xc8, 0x66, 0x7e, 0x39, 0x4d, 0xb4, 0xe1, 0x21,
+ 0xf5, 0x7f, 0x6d, 0x5b, 0x56, 0x9d, 0xe4, 0xb2, 0xff, 0x6d, 0x65, 0xb4,
+ 0x7f, 0x6f, 0x68, 0x1a, 0xcb, 0xfd, 0xb5, 0x60, 0x44, 0xf4, 0x1a, 0xb2,
+ 0xe7, 0x14, 0xac, 0xa1, 0x49, 0xea, 0x11, 0xd5, 0xf8, 0x51, 0xb4, 0x80,
+ 0x6c, 0x2c, 0xbf, 0xf3, 0x75, 0xb4, 0xf9, 0xad, 0x9b, 0x3d, 0xb6, 0xb2,
+ 0xfb, 0xd1, 0xfe, 0xd6, 0x50, 0xaa, 0x3f, 0x11, 0xa7, 0x5f, 0xf4, 0x69,
+ 0xfe, 0x01, 0x0a, 0x4b, 0x2f, 0xfe, 0x34, 0xcd, 0xc9, 0xc6, 0x28, 0xd9,
+ 0xb3, 0xdb, 0x6b, 0x2f, 0xa3, 0x35, 0x25, 0x95, 0xb4, 0xcf, 0xe4, 0x96,
+ 0x2f, 0xdc, 0xe3, 0xef, 0xc5, 0x97, 0xdd, 0xbb, 0xf6, 0xa8, 0xba, 0x57,
+ 0xe2, 0x0f, 0xe3, 0x8b, 0x2b, 0x47, 0xaf, 0xe3, 0x0b, 0xfc, 0xe3, 0x12,
+ 0x4c, 0x0e, 0x2c, 0xbe, 0x27, 0x1c, 0x2c, 0xbf, 0xd1, 0xbd, 0xca, 0x37,
+ 0xf1, 0x65, 0x41, 0xea, 0xf8, 0x82, 0xff, 0xed, 0xaf, 0x9c, 0x9a, 0x42,
+ 0xbd, 0x9b, 0x3d, 0xb6, 0xb2, 0xfe, 0x94, 0x74, 0xfc, 0x92, 0xcb, 0xfe,
+ 0x29, 0xb5, 0x1d, 0x49, 0x8e, 0xb2, 0xff, 0xdb, 0xe0, 0xbf, 0xc0, 0xff,
+ 0x34, 0xb2, 0xa0, 0xfe, 0xb0, 0xea, 0xfa, 0x5b, 0xb9, 0xf5, 0x97, 0xdc,
+ 0x8d, 0xde, 0x2c, 0xa8, 0x3c, 0xad, 0xd2, 0x5b, 0xd1, 0xfd, 0xd5, 0x97,
+ 0xf6, 0x49, 0xa2, 0x5b, 0x8b, 0x2f, 0x0f, 0x06, 0xb2, 0x86, 0x79, 0x78,
+ 0x5f, 0x7f, 0xa7, 0x82, 0xec, 0x62, 0x71, 0x65, 0xff, 0x36, 0x17, 0xb3,
+ 0xf0, 0x35, 0x97, 0xfe, 0x62, 0xd4, 0x7d, 0xbb, 0x61, 0xac, 0xa9, 0xd1,
+ 0x53, 0xf3, 0x6d, 0xe6, 0xd7, 0xfb, 0x7c, 0x7f, 0x81, 0xec, 0x56, 0xb2,
+ 0xb0, 0xfb, 0x9c, 0xce, 0xff, 0xc3, 0xf3, 0x19, 0xfe, 0xbb, 0x6f, 0x2c,
+ 0xb9, 0xc4, 0x59, 0x7f, 0xef, 0xec, 0xe3, 0x97, 0x7e, 0x6d, 0x2c, 0xb7,
+ 0x27, 0x3d, 0x8c, 0x17, 0xbf, 0xd1, 0xf7, 0x9c, 0x2d, 0x25, 0x97, 0x09,
+ 0xe5, 0x94, 0x47, 0x96, 0x21, 0x9d, 0xff, 0xf9, 0xe4, 0x51, 0xcc, 0xeb,
+ 0xb2, 0x7c, 0xeb, 0xb5, 0x97, 0xfc, 0xde, 0xce, 0x81, 0x21, 0xe2, 0xcb,
+ 0x0b, 0xda, 0xd9, 0x1e, 0xbb, 0x51, 0xbe, 0xd1, 0x09, 0xad, 0xa6, 0x4b,
+ 0x10, 0xa4, 0x9c, 0xa2, 0x50, 0xb2, 0x19, 0x3e, 0x42, 0x03, 0xb2, 0x26,
+ 0x84, 0x4e, 0xe1, 0x0c, 0xcb, 0x1a, 0x85, 0x41, 0xda, 0xbc, 0x48, 0xed,
+ 0x45, 0x19, 0xc7, 0x08, 0x3f, 0x09, 0xa0, 0xb9, 0xef, 0x22, 0xdb, 0x56,
+ 0xba, 0x36, 0xd6, 0x5f, 0xfe, 0x2f, 0xb1, 0xfd, 0x0c, 0x4f, 0xa3, 0x56,
+ 0x5f, 0xcf, 0xf8, 0x3c, 0x12, 0xca, 0xc3, 0xf3, 0xd2, 0x45, 0xff, 0x8f,
+ 0xc0, 0xfe, 0x4d, 0xbf, 0xcc, 0xb2, 0xfe, 0xcc, 0xe7, 0x7f, 0x85, 0x97,
+ 0xf4, 0xf1, 0xf7, 0x34, 0x2b, 0x29, 0x65, 0xff, 0xd1, 0xa0, 0x6c, 0xe7,
+ 0xa0, 0xee, 0x4b, 0x2f, 0xf4, 0x68, 0x4f, 0x7b, 0x00, 0xb2, 0xa4, 0x7f,
+ 0x3e, 0x45, 0xbf, 0xa4, 0xf2, 0x72, 0xed, 0x65, 0xc5, 0x0b, 0x2d, 0xc5,
+ 0x95, 0x06, 0x9b, 0xe2, 0xb7, 0xff, 0xb3, 0xf0, 0x60, 0x93, 0xf3, 0x0f,
+ 0x1b, 0x8b, 0x2c, 0x75, 0x97, 0xf3, 0xcb, 0x4c, 0x63, 0x2c, 0xbe, 0x28,
+ 0x1e, 0x96, 0x5f, 0xf9, 0xa4, 0xda, 0xea, 0x0a, 0x38, 0xb2, 0xa7, 0x3d,
+ 0xef, 0x90, 0xd8, 0x5e, 0xd6, 0xa8, 0x9f, 0x21, 0x09, 0x31, 0x17, 0x94,
+ 0xc8, 0x83, 0xe9, 0xfb, 0x62, 0x22, 0x42, 0x2e, 0xb4, 0xab, 0x8c, 0xf2,
+ 0x95, 0xaf, 0xb0, 0xcd, 0xac, 0xeb, 0x2f, 0xe2, 0x8e, 0x8e, 0xff, 0x59,
+ 0x7f, 0xf8, 0xc7, 0x1f, 0xa3, 0xaf, 0xc7, 0x9f, 0x71, 0x65, 0x9b, 0x47,
+ 0xf7, 0xe2, 0xdb, 0xff, 0xfe, 0x0e, 0xa5, 0xcf, 0x3b, 0x6b, 0x5a, 0x0f,
+ 0x4d, 0xa7, 0xe2, 0xcb, 0xff, 0xb5, 0xdc, 0x67, 0xa3, 0xe5, 0x1f, 0x59,
+ 0x78, 0x3e, 0xe2, 0xcb, 0xff, 0x39, 0xbd, 0xf9, 0xa6, 0xd4, 0x18, 0xb2,
+ 0xf4, 0x67, 0x5d, 0x9e, 0xf9, 0x0e, 0xdf, 0xfc, 0xe7, 0xe7, 0xc9, 0xc1,
+ 0xd7, 0xf6, 0x9a, 0xcb, 0x7f, 0x47, 0xfc, 0x13, 0x3b, 0xff, 0x13, 0x99,
+ 0xfc, 0xf3, 0xcc, 0xeb, 0x2f, 0xff, 0xc0, 0x04, 0x6c, 0xf4, 0x7c, 0x3d,
+ 0xfa, 0x09, 0xd6, 0x5f, 0xff, 0x88, 0x2f, 0xb9, 0x92, 0xf6, 0x1b, 0x83,
+ 0x98, 0x2b, 0x2b, 0x11, 0x61, 0xe5, 0x7b, 0xbb, 0xc5, 0x97, 0xf4, 0x49,
+ 0xba, 0xfe, 0x2c, 0xbf, 0xfe, 0x7e, 0xa5, 0xce, 0xbe, 0x4f, 0xec, 0xeb,
+ 0xeb, 0x2a, 0x11, 0x70, 0x69, 0x16, 0x85, 0xdc, 0xb6, 0xfb, 0x5c, 0x6d,
+ 0x2c, 0xbf, 0xff, 0xfe, 0xfc, 0x34, 0x9f, 0x9c, 0x8e, 0x67, 0x98, 0xa0,
+ 0xfa, 0x81, 0x1c, 0x96, 0x5f, 0xb9, 0x1e, 0x12, 0x65, 0x94, 0xc8, 0xa3,
+ 0xfb, 0xcd, 0x42, 0x39, 0xde, 0x18, 0xb7, 0xa5, 0x07, 0x59, 0x6d, 0xa1,
+ 0x65, 0xdc, 0x92, 0xcb, 0xff, 0xf7, 0xb0, 0x61, 0xff, 0x3b, 0xf3, 0x70,
+ 0x2f, 0xd2, 0xca, 0x34, 0xfb, 0xfe, 0x2f, 0x7f, 0xb5, 0xa7, 0x94, 0xf8,
+ 0x62, 0xca, 0x59, 0x74, 0xc1, 0x59, 0x58, 0x7b, 0x1e, 0x35, 0x30, 0x2e,
+ 0xff, 0xbc, 0x27, 0xdb, 0x4d, 0x3c, 0x2c, 0xbe, 0xd4, 0x19, 0xc5, 0x97,
+ 0xbd, 0x93, 0x2c, 0xbf, 0xfe, 0x09, 0x7f, 0x98, 0xc7, 0xc1, 0xc4, 0xa3,
+ 0x0f, 0x03, 0xe4, 0x75, 0x24, 0xc3, 0x30, 0xbf, 0x8f, 0x57, 0xff, 0x60,
+ 0xe2, 0x51, 0xa8, 0x11, 0xc9, 0x65, 0xff, 0xb7, 0xe4, 0x8e, 0x36, 0xdf,
+ 0x03, 0x59, 0x7f, 0xfc, 0xde, 0x09, 0xce, 0xf2, 0xf3, 0x9d, 0xb8, 0xb2,
+ 0x8e, 0x8d, 0x37, 0x42, 0xfa, 0x15, 0xce, 0x2e, 0x75, 0xff, 0x9c, 0x68,
+ 0xea, 0x32, 0x09, 0x8a, 0x35, 0x1d, 0x37, 0xa3, 0x23, 0x72, 0x62, 0x1c,
+ 0xe4, 0x21, 0x7f, 0x1c, 0x38, 0x91, 0x81, 0xd7, 0x99, 0x1d, 0x85, 0x48,
+ 0x20, 0xbf, 0xd2, 0xcf, 0xfa, 0x04, 0x25, 0x97, 0xfe, 0xfb, 0x76, 0xc3,
+ 0x72, 0x36, 0x16, 0x5f, 0xf4, 0x75, 0xe7, 0xe7, 0xe0, 0xc5, 0x95, 0x07,
+ 0xf1, 0xa3, 0xeb, 0xfc, 0xff, 0x20, 0xcf, 0xd6, 0xe2, 0xcb, 0x0a, 0x56,
+ 0x5c, 0x1f, 0x2c, 0xbf, 0x16, 0x79, 0xfe, 0xb2, 0xfe, 0x93, 0xe6, 0xf8,
+ 0x1a, 0xca, 0x14, 0x9e, 0xa0, 0xa8, 0x4d, 0x7e, 0x14, 0x0a, 0x75, 0xce,
+ 0x2c, 0xbe, 0x60, 0xca, 0x16, 0x5f, 0x67, 0x50, 0x75, 0x97, 0xcc, 0x50,
+ 0x05, 0x97, 0xe8, 0xde, 0xf9, 0xa5, 0x97, 0xb7, 0x47, 0x0b, 0x2b, 0xc7,
+ 0x8e, 0x12, 0x8b, 0xf3, 0xcd, 0x26, 0xfa, 0xcb, 0xfc, 0x1d, 0xd6, 0xdf,
+ 0xfc, 0xf2, 0xcb, 0xff, 0x40, 0xf5, 0x12, 0x6e, 0xbf, 0x8b, 0x2f, 0xff,
+ 0x9f, 0xd1, 0x21, 0xfa, 0x3a, 0xfb, 0x1f, 0x8b, 0x2a, 0x49, 0xdd, 0x1a,
+ 0x43, 0xd9, 0x17, 0x99, 0xc0, 0x44, 0x45, 0x1f, 0x38, 0xde, 0x7d, 0x7f,
+ 0xda, 0xe7, 0x9b, 0xbe, 0xc3, 0x3a, 0xcb, 0xf8, 0xcc, 0xde, 0x41, 0x92,
+ 0xcb, 0xf8, 0x26, 0xe1, 0x6e, 0xe2, 0xcb, 0xff, 0xff, 0xb5, 0x2e, 0xfc,
+ 0xc7, 0x3b, 0x19, 0xce, 0xbb, 0x6c, 0xd0, 0xe3, 0xa5, 0x95, 0x09, 0x8a,
+ 0x61, 0xe9, 0x18, 0x04, 0xc2, 0xff, 0xff, 0xa0, 0x7e, 0xce, 0xbe, 0x4f,
+ 0xe0, 0x3f, 0x38, 0xfa, 0xed, 0x65, 0xf4, 0xfb, 0x6e, 0x6a, 0xcb, 0xfd,
+ 0x99, 0x86, 0x9a, 0xf2, 0x59, 0x46, 0xa3, 0x07, 0xcc, 0xff, 0x27, 0xbf,
+ 0x67, 0x3b, 0xfc, 0x2c, 0xbf, 0xfc, 0xc6, 0x73, 0xbf, 0x37, 0x5f, 0xd6,
+ 0xa1, 0x65, 0xff, 0xb5, 0xf7, 0x97, 0x37, 0x87, 0x4c, 0xb2, 0xff, 0xe7,
+ 0xe1, 0x39, 0xa3, 0xf0, 0x5f, 0x8b, 0x2a, 0x11, 0x0a, 0x14, 0x1b, 0xff,
+ 0xfe, 0x73, 0x04, 0xcd, 0x13, 0xf5, 0x2e, 0xe3, 0xfc, 0xce, 0xbe, 0xb2,
+ 0xfc, 0x58, 0x08, 0x02, 0xcb, 0xfa, 0x71, 0x33, 0xcf, 0xd2, 0xcb, 0xfd,
+ 0x26, 0x29, 0xa4, 0xde, 0x59, 0x68, 0x92, 0x22, 0x70, 0x9a, 0x63, 0x0a,
+ 0xc5, 0x48, 0x9a, 0x28, 0xf4, 0x34, 0x9c, 0x88, 0xa1, 0xe7, 0x7e, 0xde,
+ 0xda, 0xc1, 0xac, 0xbf, 0xfe, 0xe7, 0x9b, 0x9f, 0xf6, 0x0d, 0xb9, 0x84,
+ 0xb2, 0xf7, 0xa0, 0xb0, 0xfd, 0xc2, 0x53, 0x7e, 0x7f, 0x48, 0xbb, 0x59,
+ 0x7f, 0xa0, 0xf8, 0xc7, 0x8d, 0xc5, 0x97, 0xfa, 0x47, 0xe3, 0x17, 0x52,
+ 0x59, 0x5d, 0x9f, 0x44, 0xc6, 0x97, 0xf9, 0xb4, 0xe4, 0x0c, 0x25, 0x97,
+ 0xfb, 0xec, 0x59, 0xd4, 0xa1, 0x65, 0xff, 0xda, 0xd3, 0xcb, 0x85, 0x87,
+ 0x13, 0xa5, 0x95, 0x07, 0xf1, 0x86, 0x57, 0xfc, 0xd2, 0x2c, 0xf1, 0x3c,
+ 0x96, 0x5f, 0xff, 0xa5, 0x84, 0x3f, 0x46, 0x14, 0x00, 0xef, 0x25, 0x94,
+ 0x48, 0x88, 0x10, 0xda, 0xf3, 0xbf, 0x6a, 0x89, 0x31, 0x7b, 0x75, 0xb8,
+ 0xb2, 0xa4, 0x7d, 0x7d, 0x91, 0xee, 0x94, 0xdf, 0xbb, 0xda, 0x62, 0x8d,
+ 0xac, 0x52, 0xb2, 0xff, 0xff, 0xf6, 0x77, 0x01, 0xef, 0xd1, 0xad, 0x98,
+ 0x4d, 0xd7, 0x04, 0x9c, 0xb0, 0x6b, 0x2f, 0xf6, 0xf7, 0x3e, 0x1b, 0x1c,
+ 0x59, 0x7b, 0xa9, 0x73, 0x62, 0x2c, 0x71, 0xf2, 0xff, 0x67, 0x5f, 0xfb,
+ 0xcb, 0x8b, 0x2a, 0x13, 0x59, 0xc8, 0x77, 0x68, 0xde, 0xff, 0x13, 0xff,
+ 0x9d, 0x84, 0x96, 0x5f, 0xff, 0x01, 0x80, 0x66, 0x36, 0xf2, 0xcf, 0xf9,
+ 0x96, 0x5e, 0x9f, 0xec, 0xb2, 0xff, 0xe2, 0x73, 0x38, 0x63, 0x8e, 0x3a,
+ 0xe2, 0xcb, 0x62, 0xca, 0xd1, 0xeb, 0x7d, 0x1a, 0xfd, 0xc7, 0x79, 0x71,
+ 0x65, 0xfc, 0xf2, 0xe6, 0x10, 0x16, 0x59, 0xf6, 0x23, 0xa0, 0x6e, 0x7d,
+ 0x11, 0x7c, 0x9e, 0xda, 0xc4, 0xdf, 0x7d, 0x19, 0xc5, 0xff, 0xfc, 0xf3,
+ 0x94, 0x75, 0xd7, 0x61, 0x7d, 0x03, 0x3a, 0xfa, 0xca, 0xc5, 0x47, 0xcd,
+ 0x1d, 0x81, 0x17, 0xdf, 0xf3, 0xcb, 0x98, 0x51, 0xd7, 0x16, 0x5f, 0x72,
+ 0x4c, 0x05, 0x97, 0xff, 0xdf, 0x35, 0xf9, 0xad, 0x64, 0xe0, 0x3c, 0x49,
+ 0x65, 0x48, 0xfd, 0x0c, 0x22, 0xbf, 0xff, 0xf7, 0xb2, 0x5e, 0xc1, 0x94,
+ 0x76, 0x24, 0x19, 0x9c, 0xe3, 0x9a, 0xb2, 0xa1, 0x12, 0x3f, 0x23, 0xbf,
+ 0xf1, 0x98, 0x37, 0x97, 0xf8, 0xe0, 0x59, 0x7f, 0xf8, 0xa0, 0xc1, 0x3e,
+ 0x50, 0x0c, 0xeb, 0xeb, 0x2f, 0xf6, 0x6b, 0xc5, 0x1d, 0x49, 0x65, 0xcf,
+ 0xd6, 0x1f, 0xf0, 0x89, 0x74, 0xc8, 0xeb, 0x0c, 0x2f, 0x6f, 0xfe, 0x6e,
+ 0x8c, 0xff, 0x9a, 0x0b, 0x3b, 0x59, 0x7f, 0xf0, 0xc9, 0xce, 0x06, 0xd3,
+ 0x74, 0x05, 0x97, 0xfc, 0xc6, 0xc0, 0xe7, 0x3c, 0x69, 0x65, 0x49, 0x94,
+ 0x0e, 0x33, 0x1c, 0x84, 0x81, 0xa4, 0x9d, 0xc2, 0xa3, 0x51, 0x89, 0x9e,
+ 0x38, 0xcf, 0x4a, 0x72, 0x01, 0xa9, 0x46, 0x7b, 0xc8, 0xc3, 0x7e, 0x4e,
+ 0x14, 0x5d, 0xe8, 0x97, 0xf0, 0xc0, 0x29, 0xe0, 0x36, 0xd6, 0x5e, 0xdd,
+ 0xdd, 0x85, 0x97, 0xff, 0x87, 0x86, 0x79, 0xff, 0xc8, 0xf0, 0x93, 0x2c,
+ 0xbd, 0xc6, 0x1a, 0xcb, 0xf8, 0xa3, 0xa3, 0xbf, 0xd6, 0x5f, 0xf4, 0x77,
+ 0xf0, 0xfb, 0x50, 0x62, 0xcb, 0xfe, 0x6c, 0x33, 0xbf, 0x43, 0x6d, 0xac,
+ 0xbf, 0xfd, 0x05, 0x2c, 0x0e, 0xa7, 0x06, 0x60, 0xd6, 0x5f, 0xee, 0xdb,
+ 0x5c, 0x9a, 0x1d, 0x65, 0xfe, 0x6f, 0x82, 0x3c, 0x27, 0x16, 0x5f, 0x3c,
+ 0xa0, 0x96, 0x5f, 0x83, 0xcf, 0x3c, 0xa4, 0x7a, 0x9e, 0x34, 0xbf, 0x9c,
+ 0x18, 0x43, 0x92, 0xcb, 0xff, 0x9f, 0xaf, 0xfb, 0x18, 0x70, 0x5d, 0xac,
+ 0xa3, 0x53, 0x80, 0xe9, 0x27, 0x50, 0x88, 0x23, 0xfe, 0x16, 0x59, 0x86,
+ 0xab, 0x7a, 0x64, 0xdd, 0x0e, 0x1c, 0xb4, 0x56, 0x77, 0xf8, 0xef, 0x2f,
+ 0xc3, 0x8e, 0x7d, 0x96, 0x5f, 0xb2, 0x73, 0xb4, 0xcb, 0x2a, 0x15, 0xdc,
+ 0xfa, 0x58, 0x03, 0xb4, 0x91, 0x3d, 0xf7, 0xd8, 0xee, 0xb2, 0xf8, 0xcf,
+ 0x07, 0xb5, 0x96, 0x35, 0x65, 0xfd, 0xee, 0x47, 0xe0, 0x6b, 0x2a, 0x0f,
+ 0x93, 0x09, 0x58, 0x4a, 0xb1, 0x16, 0x3f, 0x84, 0x2d, 0xff, 0xe0, 0xbf,
+ 0x9c, 0x72, 0x3f, 0xa0, 0x42, 0x59, 0x7f, 0x79, 0xb9, 0xe8, 0xd2, 0xcb,
+ 0xfe, 0x8f, 0x7d, 0xa7, 0x3c, 0x76, 0xb2, 0xff, 0xfc, 0xfd, 0xea, 0x3c,
+ 0x59, 0xfc, 0x16, 0x61, 0x86, 0x24, 0xa9, 0x26, 0x65, 0xd9, 0x3b, 0xa5,
+ 0x70, 0xb7, 0xe7, 0x57, 0xee, 0xc3, 0xd9, 0x42, 0xcb, 0xf7, 0x26, 0xf4,
+ 0x7d, 0x65, 0xed, 0x37, 0x4b, 0x2b, 0xb3, 0xef, 0x98, 0xa7, 0xe5, 0x37,
+ 0xff, 0x75, 0x22, 0x89, 0x6a, 0x3e, 0xff, 0x59, 0x7f, 0xc3, 0x12, 0x3a,
+ 0xdb, 0xcd, 0x42, 0xcb, 0xa2, 0x4b, 0x2b, 0x11, 0x2e, 0xe8, 0x84, 0x7b,
+ 0x7c, 0x1d, 0xc8, 0x92, 0xcb, 0xff, 0x3f, 0xe3, 0x5c, 0xf4, 0x17, 0xd6,
+ 0x5f, 0xb2, 0x4c, 0xfb, 0xd6, 0x57, 0x91, 0x14, 0x44, 0xbc, 0x3d, 0xa9,
+ 0x23, 0x98, 0x30, 0xb7, 0xbc, 0x77, 0xf2, 0xcb, 0xff, 0xc5, 0x12, 0xd6,
+ 0x83, 0xd3, 0x69, 0xf8, 0xb2, 0xff, 0xfb, 0x98, 0x69, 0x67, 0xf9, 0x92,
+ 0x27, 0x31, 0x65, 0x9b, 0xc8, 0x99, 0xfa, 0x55, 0x32, 0x37, 0x77, 0xc2,
+ 0xd6, 0xfb, 0x76, 0x3d, 0xc5, 0x97, 0xfd, 0x07, 0xff, 0xb0, 0xa0, 0x0b,
+ 0x2f, 0xc7, 0x89, 0x6e, 0x76, 0xb2, 0xfc, 0x50, 0x1f, 0xf1, 0x65, 0x00,
+ 0xf4, 0xfe, 0x59, 0x7f, 0xdc, 0x93, 0x7c, 0x02, 0x14, 0x96, 0x54, 0xe7,
+ 0xb9, 0xd1, 0x15, 0xfe, 0x3f, 0xf2, 0x69, 0x39, 0x2c, 0xac, 0x3d, 0x76,
+ 0x24, 0xa8, 0x4e, 0xaf, 0x0a, 0x58, 0x97, 0x51, 0x9e, 0xdf, 0xff, 0xf7,
+ 0x5d, 0xf9, 0x8e, 0x4d, 0x3c, 0x7f, 0x82, 0x7f, 0xd8, 0x35, 0x97, 0xfc,
+ 0x6e, 0xc1, 0x33, 0x5b, 0x6e, 0x6a, 0xcb, 0x0a, 0xd6, 0x54, 0x1e, 0xb3,
+ 0xa0, 0xdf, 0xff, 0xc4, 0xe6, 0xfa, 0x1a, 0x4c, 0x5f, 0x96, 0x6b, 0x16,
+ 0x54, 0x26, 0x70, 0x50, 0xc0, 0x09, 0x05, 0xff, 0xe0, 0x67, 0x5f, 0xc2,
+ 0x0f, 0xc1, 0x12, 0x59, 0x7e, 0x0f, 0xbf, 0x13, 0x2c, 0xbf, 0xfe, 0xfc,
+ 0x76, 0xdf, 0x63, 0xec, 0xe3, 0x8c, 0x6b, 0x2f, 0xf7, 0x9c, 0xe3, 0xcd,
+ 0x87, 0x59, 0x70, 0x21, 0x65, 0x0c, 0xf2, 0xc0, 0x6b, 0x7f, 0xef, 0x36,
+ 0xfc, 0xdc, 0x19, 0x3e, 0x96, 0x5f, 0x06, 0x7e, 0xb7, 0x16, 0x57, 0x67,
+ 0xd4, 0x48, 0x54, 0xc9, 0xa5, 0xf2, 0x13, 0xbf, 0x84, 0x65, 0xff, 0xe8,
+ 0x9c, 0xb3, 0x27, 0xf9, 0xb0, 0x52, 0x59, 0x7f, 0xe7, 0x29, 0xfc, 0xe7,
+ 0x6e, 0x32, 0xca, 0xc5, 0x4f, 0xfe, 0x4a, 0x78, 0xdd, 0x08, 0xe8, 0xc4,
+ 0xab, 0xff, 0x83, 0xb9, 0xec, 0xc1, 0x96, 0x4f, 0x0b, 0x2f, 0xfb, 0xed,
+ 0xc6, 0x08, 0xac, 0x70, 0xb2, 0xf1, 0x86, 0x18, 0x92, 0xfa, 0x73, 0xb7,
+ 0x12, 0x0b, 0x34, 0x17, 0x40, 0xd6, 0x53, 0x9e, 0x59, 0x1a, 0xdf, 0xf3,
+ 0x72, 0x25, 0x37, 0x98, 0x0b, 0x2f, 0xf6, 0x75, 0xac, 0xdb, 0x60, 0x2c,
+ 0xa1, 0xa6, 0xf8, 0xc8, 0xda, 0x85, 0x3f, 0x88, 0x08, 0xe6, 0xe1, 0x3c,
+ 0xb2, 0xfd, 0x18, 0x4e, 0x75, 0x97, 0xfe, 0x79, 0x79, 0xba, 0x06, 0x9c,
+ 0x6b, 0x2e, 0x19, 0x8b, 0x2f, 0xff, 0xd9, 0xbe, 0x0b, 0xe7, 0x8c, 0x21,
+ 0xe7, 0x5f, 0x59, 0x79, 0xcb, 0xb9, 0xcf, 0xb7, 0x43, 0x14, 0xc9, 0x8e,
+ 0x80, 0x60, 0x89, 0x43, 0x0a, 0xcb, 0xf6, 0xa7, 0x8d, 0x4e, 0xb2, 0xfc,
+ 0xc5, 0xf1, 0x0e, 0xb2, 0xd2, 0x83, 0xd2, 0x01, 0x55, 0xff, 0x7a, 0x0f,
+ 0x05, 0xff, 0x32, 0xcb, 0xff, 0xb3, 0x9c, 0xc3, 0x8d, 0xb7, 0xc0, 0xd6,
+ 0x54, 0x1f, 0xe7, 0x8d, 0xef, 0xe8, 0x3c, 0xde, 0x6d, 0x2c, 0xbf, 0xb3,
+ 0x98, 0x77, 0xe9, 0x65, 0xfb, 0x8d, 0x84, 0x05, 0x95, 0xa3, 0xd3, 0xe1,
+ 0x6d, 0xed, 0x66, 0xe2, 0xcb, 0xff, 0xc1, 0xe7, 0x9b, 0x26, 0x69, 0xf3,
+ 0xaf, 0xac, 0xbf, 0xe3, 0x04, 0x9f, 0x98, 0x78, 0xdc, 0x59, 0x7f, 0xf8,
+ 0x3d, 0x66, 0x84, 0xff, 0x30, 0xd6, 0xd2, 0xcb, 0xff, 0xcd, 0xde, 0x10,
+ 0xf4, 0xfd, 0xe7, 0x5f, 0x59, 0x50, 0x8d, 0x7f, 0x1f, 0xf1, 0x36, 0xff,
+ 0xcc, 0x42, 0x64, 0xdc, 0x6e, 0x8c, 0x59, 0x7c, 0xe0, 0xf8, 0xad, 0x65,
+ 0x76, 0xaa, 0x72, 0x62, 0x1d, 0x42, 0x04, 0xe4, 0x44, 0x3f, 0xf8, 0xc8,
+ 0xf7, 0x97, 0x98, 0x83, 0x7e, 0xce, 0xbf, 0xe8, 0x59, 0x7e, 0x6d, 0xff,
+ 0x8c, 0x59, 0x5e, 0x3d, 0x0e, 0x14, 0x54, 0x2e, 0x19, 0xe4, 0xb3, 0xf7,
+ 0x86, 0x95, 0xff, 0xf9, 0xb9, 0xc8, 0xd4, 0xb5, 0x1f, 0xe0, 0x85, 0x25,
+ 0x97, 0xf0, 0x99, 0xad, 0xb7, 0x35, 0x65, 0xfb, 0x35, 0xb6, 0xe6, 0xac,
+ 0xbb, 0x39, 0xb0, 0xf7, 0x44, 0x32, 0xbf, 0xfd, 0x31, 0x47, 0xf9, 0xfe,
+ 0xbb, 0x62, 0x9d, 0x65, 0xff, 0xb0, 0xbf, 0xa7, 0x7e, 0xa5, 0xc5, 0x97,
+ 0xfc, 0xe6, 0xec, 0xf4, 0x02, 0x37, 0x16, 0x56, 0x23, 0xe5, 0x8c, 0x3c,
+ 0x9a, 0xe7, 0xd7, 0xff, 0xfe, 0x00, 0x85, 0x9a, 0xd6, 0x19, 0x9b, 0x98,
+ 0x50, 0x03, 0xbc, 0x96, 0x5f, 0xff, 0xff, 0xf1, 0x67, 0x01, 0xde, 0x13,
+ 0x75, 0xc2, 0xcf, 0xf3, 0x24, 0x4e, 0x67, 0x5f, 0x0b, 0xf1, 0x65, 0x98,
+ 0x93, 0x02, 0xde, 0xdd, 0x7f, 0xff, 0x7f, 0x81, 0x1f, 0x9b, 0x26, 0x76,
+ 0xdc, 0x6e, 0xa4, 0xb2, 0xff, 0xfe, 0x2c, 0x03, 0x90, 0x35, 0xac, 0x33,
+ 0x00, 0xfd, 0x2c, 0xa2, 0x45, 0xcf, 0xd7, 0xef, 0xcd, 0xf9, 0xf0, 0xc5,
+ 0x97, 0xfd, 0x1d, 0xf8, 0x83, 0xf8, 0xe2, 0xcb, 0xff, 0x6e, 0xc7, 0x70,
+ 0x7c, 0x1b, 0x9d, 0x65, 0xfb, 0x70, 0x42, 0x8e, 0xd6, 0x53, 0x1f, 0x6b,
+ 0xa0, 0xdf, 0xfd, 0x2e, 0x64, 0x0d, 0x89, 0xf4, 0x6a, 0xcb, 0xf6, 0xa3,
+ 0x06, 0xcb, 0x2f, 0xef, 0x30, 0xc7, 0x86, 0x2c, 0xbf, 0x6b, 0x37, 0xfb,
+ 0x36, 0x1e, 0xa7, 0x64, 0xd5, 0x08, 0xda, 0x78, 0x4b, 0xdf, 0xff, 0xff,
+ 0x03, 0x99, 0x2f, 0x43, 0x68, 0x00, 0x8d, 0x60, 0x4d, 0x1b, 0x69, 0xf8,
+ 0xb2, 0xff, 0xfb, 0xd9, 0x2d, 0x9d, 0xf9, 0xbf, 0xd7, 0x6d, 0xa5, 0x95,
+ 0x08, 0xd2, 0xfb, 0xed, 0x49, 0x5f, 0x43, 0x43, 0x8f, 0x44, 0x47, 0x29,
+ 0xf4, 0x29, 0x81, 0x0f, 0xa2, 0x87, 0xc5, 0xff, 0xef, 0xc1, 0xfb, 0x71,
+ 0xe1, 0x82, 0x6a, 0x4b, 0x2f, 0x8a, 0x7d, 0xe3, 0x59, 0x7f, 0xe7, 0xd6,
+ 0xc2, 0x7f, 0xc9, 0xc6, 0xb2, 0xff, 0xfe, 0x62, 0x1e, 0xb3, 0xbf, 0x47,
+ 0xb3, 0x5a, 0x83, 0x56, 0x54, 0x91, 0x35, 0xe3, 0xfb, 0xf9, 0xdf, 0xfb,
+ 0x6d, 0xda, 0xcb, 0xfe, 0x3b, 0x8c, 0x4d, 0xd8, 0x29, 0x2c, 0xbf, 0xee,
+ 0xc3, 0xb9, 0xc6, 0x33, 0x34, 0xb2, 0xa0, 0xfe, 0xbb, 0x3c, 0xbf, 0xff,
+ 0xef, 0x87, 0x4f, 0xce, 0xfc, 0xd3, 0x13, 0x99, 0xfc, 0xf1, 0xd6, 0x5f,
+ 0xfe, 0xe6, 0x6b, 0x67, 0x7e, 0x6d, 0xec, 0x43, 0x59, 0x4c, 0x8b, 0x7e,
+ 0x34, 0xd3, 0x23, 0xed, 0xe1, 0xb3, 0x7f, 0xe6, 0x18, 0x7f, 0xc8, 0x26,
+ 0xc5, 0x97, 0xfc, 0x78, 0xd6, 0xfc, 0xd4, 0x4c, 0xb2, 0xff, 0xff, 0x67,
+ 0xfc, 0x1e, 0xbf, 0xc7, 0xeb, 0xbd, 0xbc, 0xe7, 0x31, 0x65, 0xff, 0xb5,
+ 0xd9, 0xe3, 0xae, 0x66, 0xfc, 0x59, 0x73, 0xee, 0x2c, 0xa5, 0x97, 0x68,
+ 0xd5, 0x94, 0x69, 0xa3, 0x70, 0xbb, 0xff, 0xfa, 0x62, 0x81, 0xe7, 0x5f,
+ 0xc9, 0x41, 0x4e, 0x7c, 0x59, 0x7f, 0x03, 0x6f, 0x07, 0x87, 0x59, 0x5a,
+ 0x45, 0x67, 0x88, 0x49, 0x6e, 0xfb, 0xef, 0xae, 0x2c, 0xbf, 0x6c, 0xdb,
+ 0xcd, 0x42, 0xca, 0x9c, 0xf3, 0x88, 0x8a, 0xa1, 0x3c, 0x99, 0xd0, 0xb2,
+ 0x1d, 0x0e, 0xfb, 0x7f, 0xd2, 0x6f, 0xf3, 0xb8, 0xff, 0x16, 0x5f, 0xc0,
+ 0xd9, 0x83, 0x79, 0x2c, 0xa9, 0x8f, 0xa5, 0xce, 0xac, 0x6a, 0xcb, 0xff,
+ 0xb3, 0xbf, 0x47, 0xb3, 0x5a, 0x83, 0x56, 0x5f, 0xb3, 0x5a, 0x83, 0x56,
+ 0x5f, 0x13, 0x03, 0x90, 0x7f, 0xfa, 0x12, 0xf2, 0x2d, 0xff, 0x79, 0xc0,
+ 0x77, 0x93, 0xf1, 0x65, 0xfe, 0x79, 0x4a, 0x25, 0xdf, 0x16, 0x56, 0x1f,
+ 0x60, 0x4e, 0x2f, 0xff, 0xfe, 0x6f, 0xfb, 0x07, 0x26, 0xfe, 0x1f, 0x8f,
+ 0x2d, 0xbc, 0xe7, 0x31, 0x65, 0x62, 0x7c, 0xad, 0x0a, 0x1f, 0x42, 0xc3,
+ 0x84, 0x37, 0xff, 0x9e, 0x7f, 0x34, 0x16, 0x4c, 0xda, 0x65, 0x95, 0x26,
+ 0xc0, 0x18, 0x71, 0xd6, 0x64, 0xe9, 0x27, 0x4f, 0x0c, 0x9b, 0x34, 0x2f,
+ 0xf4, 0x47, 0xe8, 0xe9, 0x5c, 0x98, 0x07, 0x84, 0x77, 0xc9, 0x46, 0x1f,
+ 0x95, 0x1e, 0x62, 0x35, 0xff, 0xfb, 0x09, 0x87, 0xcf, 0x3f, 0x18, 0x8a,
+ 0x3a, 0x59, 0x7e, 0x2c, 0xf3, 0xfd, 0x65, 0xff, 0xa5, 0x05, 0x38, 0x9a,
+ 0x20, 0xc9, 0x65, 0xee, 0x66, 0x96, 0x5f, 0xc4, 0xe3, 0x07, 0x40, 0x59,
+ 0x5b, 0x88, 0xb0, 0x98, 0x9b, 0xc8, 0x1c, 0x1c, 0xbf, 0xf9, 0xca, 0x5a,
+ 0x7e, 0xbd, 0x19, 0xc5, 0x97, 0xff, 0x76, 0xda, 0xf6, 0x4d, 0xe6, 0xd4,
+ 0xeb, 0x2f, 0xbf, 0x3e, 0x0d, 0x65, 0xff, 0x31, 0xa2, 0x68, 0x07, 0x6e,
+ 0x2c, 0xa9, 0x8f, 0x7b, 0x6c, 0x8e, 0xff, 0xcd, 0xd7, 0x00, 0xe4, 0x39,
+ 0x82, 0xb2, 0xf1, 0x86, 0x18, 0xb2, 0xff, 0xe2, 0x80, 0x60, 0xf9, 0x87,
+ 0x8e, 0xd2, 0x0b, 0x34, 0x14, 0x04, 0x5a, 0xfd, 0x82, 0xff, 0x79, 0xb0,
+ 0x70, 0x5f, 0x59, 0x47, 0x3d, 0x4d, 0xe4, 0x77, 0xfe, 0x70, 0x77, 0xe6,
+ 0x98, 0xa0, 0x0b, 0x2b, 0x0f, 0x8d, 0x89, 0x2f, 0xed, 0x66, 0xef, 0x9c,
+ 0x6b, 0x2f, 0xfd, 0x9d, 0x6c, 0x2c, 0xdf, 0xa6, 0xe2, 0xcb, 0xfb, 0xbf,
+ 0x34, 0x17, 0x6b, 0x2a, 0x0f, 0xc3, 0x10, 0xaf, 0xf6, 0xa3, 0xed, 0xdb,
+ 0x0d, 0x65, 0xfa, 0x53, 0x66, 0x76, 0xb2, 0xff, 0x06, 0x78, 0x61, 0xe1,
+ 0xd6, 0x5b, 0x4b, 0x2b, 0x6a, 0x45, 0x04, 0x19, 0x91, 0x48, 0x86, 0x77,
+ 0xe3, 0x30, 0xef, 0xd2, 0xcb, 0xe0, 0x63, 0xee, 0x2c, 0xa8, 0x3c, 0xd6,
+ 0x29, 0xb9, 0xb8, 0xb2, 0xa4, 0xbc, 0x03, 0x91, 0x81, 0x1a, 0x83, 0xd2,
+ 0x1b, 0x42, 0x97, 0xd1, 0xc9, 0x39, 0x01, 0x42, 0x83, 0x90, 0xc0, 0xfc,
+ 0x23, 0xb6, 0xc8, 0x2f, 0x8a, 0x78, 0xf2, 0xcb, 0xf7, 0xbf, 0xc0, 0xee,
+ 0x2c, 0xb8, 0xcd, 0xa9, 0x65, 0x41, 0xe4, 0xf4, 0x59, 0x7e, 0xff, 0xd8,
+ 0xfc, 0x59, 0x73, 0xb2, 0xcb, 0xf7, 0x5f, 0xdf, 0x84, 0xb2, 0xfc, 0xff,
+ 0x93, 0x8d, 0x65, 0x8d, 0xc3, 0xd1, 0x22, 0xab, 0xa5, 0xe5, 0x94, 0xc8,
+ 0xcc, 0xf1, 0x43, 0xb3, 0x7c, 0x9e, 0xcc, 0xb2, 0xff, 0xff, 0x19, 0x05,
+ 0x06, 0x94, 0x1a, 0x26, 0xdc, 0x6a, 0x3b, 0x85, 0x97, 0xf7, 0xa3, 0x67,
+ 0x6d, 0x3a, 0xcb, 0xff, 0x39, 0xf3, 0x46, 0x9a, 0x12, 0xfa, 0xcb, 0xfd,
+ 0x1f, 0xe7, 0x18, 0xa6, 0x59, 0x5e, 0x3f, 0x32, 0x40, 0xbf, 0xf1, 0x8e,
+ 0x52, 0xf0, 0x63, 0xae, 0x2c, 0xbf, 0xff, 0x9c, 0xfa, 0xcd, 0xf0, 0x5f,
+ 0xcf, 0x36, 0xbc, 0xeb, 0x2f, 0xf9, 0xff, 0xcf, 0xfd, 0xe5, 0xc5, 0x95,
+ 0x32, 0x3d, 0x34, 0x43, 0xe4, 0x02, 0x5a, 0xbf, 0xf9, 0xf4, 0xf2, 0xce,
+ 0x3f, 0xf2, 0x65, 0x97, 0xfd, 0xfd, 0x46, 0x75, 0xb1, 0xf8, 0xb2, 0xfe,
+ 0xd3, 0xe8, 0xa2, 0x4b, 0x2f, 0xff, 0xf7, 0xff, 0x12, 0x27, 0xf4, 0x1f,
+ 0xd8, 0x37, 0xe8, 0x96, 0x5f, 0xfe, 0xff, 0xb3, 0x7f, 0x9b, 0x67, 0x38,
+ 0xc7, 0x59, 0x58, 0x8a, 0xd7, 0x5f, 0xbf, 0xe9, 0x36, 0xba, 0x82, 0x8e,
+ 0x2c, 0xbf, 0xe8, 0xc9, 0xf5, 0x1f, 0x7f, 0xac, 0xa6, 0x3f, 0x00, 0x9c,
+ 0x56, 0xd2, 0x5c, 0x53, 0x81, 0x01, 0xb2, 0xe4, 0x73, 0x1d, 0x9e, 0xf4,
+ 0x87, 0xa3, 0xb2, 0x86, 0xcf, 0xe1, 0x23, 0x7f, 0x4a, 0x26, 0xc6, 0x02,
+ 0xcb, 0x0b, 0xda, 0x9f, 0x24, 0xe3, 0x68, 0x15, 0x14, 0x35, 0x8a, 0xa2,
+ 0xb8, 0x8f, 0xae, 0x78, 0xe2, 0x65, 0x0f, 0xc1, 0xca, 0x75, 0xca, 0x56,
+ 0x89, 0xb0, 0xee, 0xee, 0x5f, 0x7f, 0x52, 0x89, 0x9a, 0x17, 0x53, 0x47,
+ 0x5d, 0xa9, 0x56, 0x07, 0x8d, 0xe7, 0xd2, 0xac, 0xde, 0x3c, 0xc0, 0x46,
+ 0xd6, 0x53, 0x98, 0xdc, 0xac, 0x10, 0xbf, 0x3d, 0xd6, 0x18, 0x5e, 0x18,
+ 0xd7, 0xb7, 0x0e, 0xe1, 0x27, 0x23, 0xb7, 0x61, 0x2d, 0x7e, 0x97, 0x50,
+ 0x43, 0x59, 0x52, 0x54, 0x96, 0x52, 0x88, 0xef, 0xff, 0x6b, 0x0c, 0x1f,
+ 0xb2, 0x62, 0xcd, 0x49, 0x65, 0xed, 0x66, 0xe2, 0xcb, 0xff, 0x41, 0x82,
+ 0x4f, 0xcc, 0x3c, 0x6e, 0x2c, 0xad, 0x22, 0xb8, 0xe9, 0x7f, 0x1f, 0xbf,
+ 0xfe, 0x73, 0xc6, 0xbb, 0xd0, 0x4d, 0xd0, 0x5f, 0x8b, 0x2b, 0x11, 0x04,
+ 0x13, 0x0b, 0xfd, 0xae, 0xc2, 0xe3, 0x3c, 0x2c, 0xbf, 0xfa, 0x34, 0x27,
+ 0xdb, 0xfe, 0xc1, 0xb2, 0xcb, 0xfc, 0x5d, 0x03, 0x38, 0xfb, 0x8b, 0x2f,
+ 0xf8, 0xa2, 0x71, 0x3d, 0xe7, 0xdc, 0x59, 0x7d, 0x18, 0x3e, 0x96, 0x56,
+ 0x22, 0x57, 0xc6, 0xdb, 0xcf, 0x6f, 0xe7, 0x7f, 0xed, 0xb7, 0x6b, 0x2e,
+ 0xdf, 0xba, 0xb2, 0xff, 0xff, 0x98, 0x98, 0x1c, 0xd6, 0x77, 0xe8, 0xf6,
+ 0x6b, 0x50, 0x6a, 0xca, 0x84, 0xfc, 0x27, 0x34, 0xc8, 0x6c, 0xe8, 0xc4,
+ 0x06, 0x1f, 0x1c, 0xbc, 0x2a, 0x6d, 0x52, 0x59, 0x79, 0xf5, 0x3a, 0xcb,
+ 0xfd, 0x9f, 0xe3, 0x77, 0x84, 0xb2, 0xe3, 0x0c, 0x59, 0x79, 0xfb, 0x17,
+ 0xd9, 0xf4, 0x10, 0xe9, 0x86, 0x57, 0xed, 0x3c, 0x9b, 0xcb, 0x2f, 0xfe,
+ 0xd7, 0x3c, 0xc6, 0x79, 0xa7, 0x72, 0x59, 0x50, 0x7d, 0x8e, 0x4f, 0x7e,
+ 0xc3, 0xf9, 0xc6, 0xb2, 0xc2, 0xf6, 0xa7, 0xdf, 0xbe, 0x88, 0x46, 0x48,
+ 0x84, 0x68, 0x39, 0x2c, 0x40, 0xd2, 0xce, 0xe9, 0x31, 0xf3, 0x17, 0xea,
+ 0x15, 0x7e, 0x21, 0x7b, 0xcb, 0xbb, 0x28, 0xd6, 0xf9, 0x28, 0x4b, 0xeb,
+ 0x9b, 0xe1, 0x1e, 0x64, 0x2c, 0x37, 0x48, 0x2a, 0x50, 0x93, 0x70, 0x1d,
+ 0x63, 0x01, 0xd4, 0xa7, 0xad, 0x1c, 0x9e, 0x12, 0x7e, 0x9c, 0x9f, 0x04,
+ 0x62, 0xe5, 0x1a, 0xaf, 0x29, 0x60, 0x9f, 0xa5, 0x0e, 0x86, 0xf8, 0x50,
+ 0xaf, 0xd8, 0x3f, 0x41, 0x8b, 0x2f, 0xee, 0x44, 0xd2, 0x69, 0x96, 0x5f,
+ 0xf7, 0xe0, 0x98, 0x19, 0xd7, 0xd6, 0x5f, 0x6d, 0xb9, 0x01, 0x65, 0xd1,
+ 0x3e, 0x1e, 0xe0, 0x87, 0x14, 0x48, 0xe1, 0xe1, 0x40, 0x90, 0x8b, 0xbf,
+ 0xcf, 0xae, 0xc5, 0xcb, 0x3a, 0x59, 0x7f, 0xfa, 0x4f, 0xc1, 0x65, 0x19,
+ 0xf8, 0xea, 0x4b, 0x2f, 0x1a, 0xda, 0x59, 0x74, 0x01, 0x65, 0xf7, 0xff,
+ 0x07, 0x59, 0x79, 0x86, 0x2d, 0x8f, 0x57, 0xc3, 0xa2, 0x0b, 0x5f, 0xfa,
+ 0x24, 0x2c, 0x48, 0x30, 0x49, 0xb8, 0xb2, 0xcd, 0xda, 0x21, 0xc0, 0x85,
+ 0x42, 0xd3, 0xbc, 0x9c, 0xd5, 0x8d, 0xff, 0x19, 0x3d, 0xff, 0x9f, 0xb1,
+ 0x61, 0x03, 0x4b, 0x24, 0xb2, 0xfd, 0xae, 0xdd, 0xfb, 0x54, 0x46, 0xab,
+ 0xff, 0xef, 0x31, 0x8e, 0x5d, 0xea, 0x1a, 0x4f, 0xc5, 0x97, 0xdf, 0xd3,
+ 0x74, 0xb2, 0xfc, 0x1f, 0x86, 0x68, 0x59, 0x7e, 0x61, 0xbe, 0x7d, 0x65,
+ 0xe3, 0x7a, 0xe2, 0xcb, 0x0b, 0x9d, 0x35, 0x7c, 0x41, 0xec, 0xd9, 0x93,
+ 0xfc, 0x46, 0xe5, 0x3f, 0x26, 0xbf, 0xff, 0xdb, 0xe0, 0xbe, 0x2d, 0xf7,
+ 0xb8, 0xf0, 0x6e, 0x77, 0x1a, 0xcb, 0xf6, 0xbb, 0x77, 0xed, 0x51, 0x52,
+ 0xad, 0xda, 0xa2, 0x1a, 0x52, 0xca, 0x73, 0x54, 0x01, 0xfb, 0x0b, 0xc4,
+ 0x40, 0x3b, 0x05, 0xf7, 0xdf, 0xa0, 0x2c, 0xbf, 0xfd, 0x9e, 0x61, 0x3e,
+ 0xc4, 0x19, 0x67, 0x16, 0x5f, 0xec, 0xf1, 0x3f, 0xff, 0x0b, 0x2f, 0x13,
+ 0x8b, 0x74, 0x4e, 0xfc, 0x8c, 0x44, 0x9b, 0xdb, 0x5e, 0xd2, 0x14, 0x2c,
+ 0xbf, 0x39, 0xe7, 0x7d, 0xc5, 0x97, 0xdd, 0xbb, 0xf6, 0xa8, 0x8f, 0x97,
+ 0x0e, 0x16, 0x56, 0x8f, 0x18, 0xe6, 0x17, 0xfb, 0x8d, 0xe3, 0x1f, 0x52,
+ 0x59, 0x78, 0x7e, 0x0a, 0xcb, 0xba, 0xe2, 0xcb, 0x1a, 0xb2, 0xb0, 0xd5,
+ 0x6d, 0x8c, 0x5f, 0xfc, 0x1d, 0x03, 0xbf, 0x34, 0xc5, 0x00, 0x59, 0x7f,
+ 0xa5, 0x9b, 0x8e, 0x40, 0x14, 0x2c, 0xbd, 0xf8, 0xc5, 0x97, 0xff, 0x7e,
+ 0x50, 0x6e, 0xc8, 0xff, 0x20, 0x0b, 0x2c, 0x58, 0x7c, 0x4e, 0x37, 0x74,
+ 0x85, 0xed, 0x6a, 0x98, 0xe7, 0x2c, 0xc7, 0x1e, 0x88, 0x9c, 0xd0, 0x08,
+ 0xfc, 0x23, 0xfa, 0x30, 0x90, 0x9b, 0xae, 0xd5, 0x9f, 0x3c, 0xaa, 0x5b,
+ 0xf8, 0x5f, 0x1e, 0x3a, 0x92, 0xcb, 0xf7, 0xfd, 0x04, 0x6a, 0xcb, 0xfb,
+ 0x4e, 0x07, 0xcd, 0x2c, 0xbe, 0xf0, 0x4a, 0x75, 0x97, 0xfe, 0x79, 0xe3,
+ 0xcd, 0xa6, 0x83, 0xac, 0xbf, 0xd1, 0xac, 0x2f, 0xe7, 0x96, 0x5d, 0x82,
+ 0xe1, 0x1c, 0xa3, 0x28, 0xf1, 0x66, 0xd9, 0x18, 0x87, 0xb4, 0x6a, 0x6d,
+ 0xe7, 0x8c, 0x56, 0x85, 0xa7, 0x8d, 0x11, 0xcd, 0xdf, 0xff, 0xe0, 0xe8,
+ 0xd7, 0xe6, 0x0e, 0x3a, 0xe0, 0x9f, 0x35, 0x8d, 0x59, 0x7d, 0x1c, 0x7e,
+ 0x2c, 0xa9, 0x22, 0x1e, 0x66, 0x6b, 0xc6, 0x1b, 0xda, 0xcb, 0xf7, 0x5d,
+ 0x4b, 0x3e, 0xb2, 0xb8, 0x79, 0x41, 0x20, 0xbf, 0xfd, 0xb4, 0xcd, 0x33,
+ 0x72, 0x71, 0x8a, 0x36, 0x6c, 0xf6, 0xda, 0xcb, 0xff, 0x05, 0xf5, 0x22,
+ 0xce, 0x46, 0x96, 0x5f, 0x76, 0xef, 0xda, 0xa2, 0xc7, 0x5f, 0xa3, 0xc4,
+ 0xe2, 0x2c, 0xad, 0x1e, 0xb9, 0xcc, 0x2f, 0xf6, 0x31, 0x4f, 0xfc, 0xf2,
+ 0xcb, 0x9f, 0x8b, 0x2f, 0xe9, 0xc4, 0xd6, 0xb3, 0x4b, 0x2f, 0x1f, 0x90,
+ 0xb2, 0xa4, 0x7c, 0x4e, 0x2c, 0x13, 0x0b, 0xfe, 0x27, 0x37, 0xcd, 0x05,
+ 0x3a, 0xcb, 0xf8, 0xbf, 0xa0, 0xc1, 0xd6, 0x5f, 0xff, 0x89, 0xcd, 0xd9,
+ 0xf3, 0x60, 0xa5, 0x9e, 0x63, 0xac, 0xa7, 0x44, 0x20, 0x4b, 0x6f, 0xe0,
+ 0x3f, 0xf9, 0x06, 0xac, 0xbb, 0x7e, 0x2c, 0xbf, 0xcd, 0xf8, 0xd1, 0xbe,
+ 0x65, 0x97, 0xff, 0xd2, 0x9f, 0x69, 0xc6, 0xd1, 0x3f, 0x7a, 0xd9, 0xb3,
+ 0xdb, 0x6b, 0x2f, 0xfb, 0x37, 0xc4, 0xba, 0x96, 0x7d, 0x65, 0x62, 0x63,
+ 0x6c, 0x5c, 0xe3, 0x00, 0x33, 0x26, 0x7b, 0x9a, 0x4b, 0x2f, 0xf6, 0x17,
+ 0xb3, 0xf0, 0x35, 0x97, 0xec, 0xdf, 0xe7, 0x92, 0xcb, 0x7d, 0x8f, 0x68,
+ 0x8c, 0x68, 0x68, 0x96, 0xc7, 0x0b, 0xfe, 0x93, 0x7c, 0x4d, 0x47, 0xa1,
+ 0x65, 0xf9, 0xbf, 0xf6, 0xfa, 0xcb, 0xff, 0xf0, 0x49, 0xcd, 0xf9, 0xb0,
+ 0x52, 0xcf, 0x31, 0xd6, 0x5f, 0x6b, 0x59, 0xb6, 0xb2, 0xfd, 0xa0, 0x37,
+ 0xa1, 0x65, 0x6c, 0x4c, 0x07, 0x0e, 0x4e, 0x4e, 0xea, 0xa1, 0x25, 0xbf,
+ 0x66, 0xb3, 0x26, 0x59, 0x61, 0x70, 0xbd, 0xaf, 0x3b, 0x74, 0x88, 0x86,
+ 0xc9, 0x90, 0x94, 0x34, 0x89, 0xa1, 0x29, 0x31, 0x71, 0xe1, 0x79, 0xe8,
+ 0xcf, 0x4a, 0x1b, 0xbc, 0x8c, 0x8c, 0x44, 0xbb, 0xdd, 0x7f, 0x16, 0x5e,
+ 0x6d, 0x4c, 0xb2, 0xfa, 0x5f, 0x08, 0xd6, 0x51, 0xa7, 0x81, 0xd0, 0xed,
+ 0xff, 0xff, 0xfb, 0xd8, 0xed, 0xcf, 0x60, 0x36, 0x73, 0x07, 0x87, 0x6e,
+ 0xa4, 0x50, 0x68, 0x16, 0x5f, 0xc4, 0xe6, 0x7f, 0x3c, 0xb2, 0xb6, 0xa4,
+ 0x58, 0xcd, 0x08, 0x4b, 0x8e, 0x6a, 0xca, 0x14, 0x9e, 0x36, 0xd3, 0x2e,
+ 0xbf, 0x16, 0x79, 0xfe, 0xb2, 0xf0, 0xab, 0xda, 0x80, 0xb2, 0x85, 0x27,
+ 0x9d, 0xb4, 0xc9, 0xaf, 0xfd, 0xb5, 0x6d, 0x62, 0x90, 0xe6, 0x8a, 0x00,
+ 0xb2, 0xfe, 0xce, 0xe3, 0xed, 0xbd, 0x65, 0xff, 0xb0, 0xce, 0x63, 0x73,
+ 0xf9, 0xb8, 0xb2, 0xbc, 0x7e, 0x04, 0x5f, 0x7b, 0xc1, 0x1a, 0xcb, 0xf8,
+ 0x78, 0x7d, 0xaf, 0x69, 0x6d, 0x6b, 0x2f, 0xfa, 0x26, 0x6f, 0xf1, 0x8a,
+ 0x65, 0x97, 0xff, 0xbb, 0x80, 0x7b, 0x71, 0x8f, 0xfe, 0x3f, 0x4b, 0x2f,
+ 0x6e, 0x8e, 0x16, 0x53, 0x1f, 0x70, 0x53, 0xef, 0xf3, 0x83, 0x8f, 0xff,
+ 0xba, 0xcb, 0x8f, 0xda, 0xcb, 0xfe, 0x71, 0xb7, 0x52, 0xfb, 0x69, 0x65,
+ 0xff, 0xa3, 0x40, 0x2c, 0x9a, 0x4d, 0x32, 0xca, 0x1a, 0xa0, 0x6c, 0x21,
+ 0x61, 0xdd, 0x1f, 0x7a, 0x14, 0xe4, 0x43, 0xf3, 0x2d, 0xe3, 0x1b, 0xa7,
+ 0x37, 0xfc, 0x66, 0xb0, 0x9f, 0xa9, 0x71, 0x65, 0xc4, 0x6a, 0xcb, 0xb0,
+ 0x6b, 0x2b, 0x0f, 0x9d, 0xce, 0xb7, 0x8b, 0xdf, 0xbc, 0xe7, 0x82, 0x59,
+ 0x7d, 0xcf, 0x31, 0x8b, 0x2f, 0xfe, 0x9b, 0x71, 0xa7, 0xf6, 0x4c, 0x58,
+ 0x62, 0xcb, 0xfb, 0xb7, 0xd6, 0xdb, 0xf9, 0x65, 0xde, 0xf2, 0xcb, 0xf4,
+ 0x19, 0xfc, 0xf2, 0xcb, 0x84, 0xc5, 0x97, 0xc3, 0xce, 0xbe, 0xb2, 0xa0,
+ 0xdd, 0x30, 0xbd, 0x6c, 0x4d, 0x73, 0x09, 0x8d, 0x23, 0x64, 0xa1, 0x59,
+ 0x89, 0x0b, 0xf1, 0x8a, 0xfe, 0x28, 0x04, 0xbb, 0x9d, 0x65, 0xff, 0xd1,
+ 0x1b, 0xbe, 0xc7, 0x1e, 0x61, 0xd6, 0x5d, 0xfe, 0x4c, 0x7e, 0x7e, 0x2f,
+ 0xb7, 0x6b, 0x2f, 0x03, 0x6b, 0xf2, 0xca, 0xda, 0x46, 0xd3, 0x82, 0x57,
+ 0xc1, 0xe7, 0xb1, 0x65, 0x68, 0xf2, 0x48, 0x9e, 0xff, 0xf6, 0x6e, 0xe7,
+ 0x7f, 0xea, 0x58, 0x40, 0x75, 0x97, 0xff, 0xff, 0x31, 0x6f, 0xc1, 0x93,
+ 0xbe, 0xfc, 0xdc, 0xfe, 0xe3, 0x7c, 0xa0, 0x0b, 0x2f, 0x30, 0x40, 0xb2,
+ 0xdd, 0x6e, 0x22, 0x4e, 0x67, 0x7b, 0xc7, 0x6d, 0x2c, 0xac, 0x3c, 0xa0,
+ 0x17, 0x5e, 0xc7, 0x25, 0x97, 0xbd, 0x13, 0x2c, 0xb9, 0xbe, 0xc6, 0xdd,
+ 0xc6, 0xae, 0x90, 0xd6, 0x5f, 0xfd, 0x86, 0x70, 0xb2, 0x69, 0x04, 0xbe,
+ 0xb2, 0xfa, 0x5b, 0x8c, 0x75, 0x97, 0xdc, 0x77, 0xdc, 0x59, 0x7e, 0xcf,
+ 0x6e, 0x31, 0x39, 0xe4, 0xfc, 0x96, 0xd8, 0x48, 0xcd, 0xdf, 0x08, 0xeb,
+ 0xff, 0xde, 0x8e, 0xb2, 0x72, 0x08, 0x7f, 0x1e, 0x59, 0x7f, 0xcd, 0xdf,
+ 0x9b, 0xfc, 0x7e, 0x96, 0x5f, 0x8b, 0x07, 0x9e, 0xed, 0x10, 0xbe, 0x4b,
+ 0xbf, 0xdd, 0xb1, 0x99, 0x33, 0xee, 0x2c, 0xad, 0x1f, 0xbf, 0x8f, 0xef,
+ 0xff, 0xfc, 0x58, 0x72, 0x08, 0x0d, 0xdc, 0x62, 0x1e, 0x4e, 0x60, 0x5e,
+ 0x75, 0x95, 0x08, 0x93, 0xc2, 0x2b, 0xff, 0xfd, 0x06, 0x7b, 0x34, 0xe7,
+ 0xcf, 0xfb, 0x30, 0xf9, 0xda, 0xcb, 0xff, 0xe9, 0xb3, 0x74, 0xb3, 0x79,
+ 0x60, 0x0f, 0x12, 0x59, 0x50, 0x8b, 0x3c, 0x60, 0xbf, 0xe7, 0xe8, 0xb3,
+ 0xfc, 0xc3, 0x16, 0x54, 0x2f, 0x24, 0x64, 0x2b, 0x3b, 0x21, 0x68, 0xca,
+ 0xb7, 0x16, 0x26, 0x2a, 0xd4, 0x39, 0x3d, 0x1d, 0xe9, 0x43, 0x50, 0x24,
+ 0x37, 0xef, 0x36, 0x83, 0x25, 0x97, 0xfd, 0x3b, 0x7a, 0x67, 0x93, 0x79,
+ 0x65, 0xfb, 0x40, 0xdb, 0x0f, 0xd6, 0x5f, 0xed, 0xfe, 0x61, 0xfb, 0x38,
+ 0xb2, 0xff, 0xff, 0x82, 0x1e, 0x8b, 0x37, 0xec, 0x1e, 0x7e, 0x59, 0xef,
+ 0x3c, 0x96, 0x5f, 0xf1, 0xf9, 0xec, 0xf9, 0x41, 0xd6, 0x5e, 0x2c, 0xe1,
+ 0x22, 0x8f, 0x6d, 0xae, 0x9d, 0x30, 0xdd, 0xf0, 0xd8, 0xbf, 0xfd, 0xad,
+ 0x44, 0xf8, 0x67, 0x52, 0xf8, 0x46, 0xb2, 0xfb, 0x30, 0x8d, 0x59, 0x7f,
+ 0xe6, 0x37, 0x24, 0xcf, 0xbf, 0xcc, 0xb2, 0xd0, 0xc8, 0xae, 0xd2, 0x77,
+ 0x88, 0x6a, 0x15, 0x22, 0xb4, 0x67, 0x3e, 0x86, 0xc5, 0xfe, 0x2f, 0x8a,
+ 0x1f, 0xe1, 0x85, 0x97, 0xf4, 0x8b, 0x3a, 0xfb, 0xac, 0xbf, 0x87, 0xf3,
+ 0x58, 0x86, 0xb2, 0xa1, 0x12, 0x2e, 0x6c, 0x12, 0xdb, 0xc3, 0xc2, 0x59,
+ 0x7f, 0x9e, 0x7f, 0xf1, 0xdf, 0x71, 0x65, 0x4e, 0x7a, 0x3b, 0xc6, 0xef,
+ 0xfc, 0xda, 0xef, 0xcd, 0x33, 0xbc, 0x96, 0x5f, 0xfd, 0xe8, 0x3f, 0x7e,
+ 0x6f, 0xe6, 0x1d, 0x65, 0xf6, 0xa7, 0x83, 0x56, 0x59, 0x96, 0x5c, 0xe6,
+ 0xe1, 0xb4, 0xf9, 0x25, 0x42, 0x29, 0x09, 0xe2, 0xff, 0xf1, 0x67, 0x84,
+ 0xe7, 0x02, 0x7e, 0x3f, 0x4b, 0x2f, 0x81, 0x8c, 0xeb, 0x2f, 0x01, 0x84,
+ 0x59, 0x7f, 0xff, 0xfa, 0x0b, 0xfc, 0x6f, 0x31, 0xc7, 0x1e, 0xcd, 0xfb,
+ 0x8c, 0x43, 0xc9, 0xd6, 0x57, 0x69, 0x81, 0xba, 0x60, 0x08, 0x3e, 0x3b,
+ 0x7f, 0xcf, 0xa9, 0xfc, 0xd9, 0xa9, 0x96, 0x5f, 0xfc, 0xee, 0x40, 0xe6,
+ 0x6e, 0x4c, 0xee, 0xb2, 0xff, 0xff, 0xff, 0x63, 0x7b, 0x71, 0x8b, 0x3f,
+ 0xf8, 0x9c, 0x65, 0x10, 0x0f, 0xcb, 0x08, 0x9e, 0x4b, 0x2b, 0xb4, 0xc2,
+ 0xe6, 0x3a, 0xfa, 0x2d, 0xfa, 0x5c, 0x9f, 0x0c, 0x59, 0x7b, 0x35, 0x3a,
+ 0xcb, 0xce, 0x53, 0x2c, 0xaf, 0x1b, 0x97, 0x1d, 0xbc, 0xef, 0xda, 0xa2,
+ 0xd0, 0x5f, 0xff, 0xec, 0x1c, 0x76, 0xc5, 0x3f, 0x3b, 0xf3, 0x0c, 0x78,
+ 0x4b, 0x2f, 0xcf, 0xa9, 0xf0, 0xc5, 0x97, 0x9c, 0xcd, 0xdd, 0x88, 0x8a,
+ 0xed, 0x86, 0xfe, 0x04, 0x14, 0x7f, 0x8b, 0x2a, 0x13, 0x9d, 0x1b, 0x1f,
+ 0x64, 0x1a, 0x85, 0x98, 0x0e, 0xef, 0x49, 0x80, 0xb2, 0xff, 0xba, 0xfc,
+ 0x1b, 0xb8, 0xc1, 0x1a, 0xcb, 0xf9, 0xbf, 0xe7, 0x23, 0x56, 0x54, 0xc8,
+ 0x87, 0x71, 0xce, 0x1f, 0x5e, 0x08, 0x74, 0xb2, 0xf1, 0x46, 0x96, 0x5d,
+ 0xa9, 0xa6, 0x37, 0x1c, 0x1d, 0xbf, 0xff, 0xdc, 0x72, 0xf4, 0x6f, 0xf6,
+ 0x7f, 0x1c, 0xbb, 0xc1, 0xac, 0xbf, 0xff, 0xcd, 0x1f, 0x6f, 0x47, 0x3d,
+ 0x9c, 0xd6, 0x77, 0x9f, 0x59, 0x7f, 0xf4, 0x03, 0x85, 0x9b, 0x83, 0x8f,
+ 0xf1, 0x65, 0x9c, 0x91, 0x4b, 0xc5, 0xfb, 0x6a, 0x13, 0x2c, 0xf4, 0x60,
+ 0xb7, 0xf4, 0xfb, 0x26, 0x94, 0x4e, 0xb2, 0xb1, 0x3b, 0xd6, 0x8d, 0x6d,
+ 0xcb, 0xef, 0xc3, 0x89, 0x98, 0xeb, 0x2f, 0xe3, 0x0b, 0x27, 0x12, 0x4b,
+ 0x2f, 0xc3, 0xc0, 0x3c, 0x2c, 0xbf, 0xff, 0xf3, 0xea, 0x5c, 0x61, 0xe6,
+ 0xa7, 0x6e, 0x79, 0xc1, 0xcc, 0x25, 0x95, 0x88, 0x91, 0xe1, 0x35, 0x32,
+ 0x38, 0xc3, 0x0c, 0x1b, 0xf4, 0xe7, 0x77, 0x25, 0x97, 0xfc, 0xe0, 0xc6,
+ 0xe7, 0x20, 0x0b, 0x2a, 0x0f, 0x7b, 0x84, 0xf7, 0xfe, 0x1e, 0xde, 0x70,
+ 0x7e, 0x6d, 0x4e, 0xb2, 0xff, 0xfb, 0x0c, 0xf9, 0xe3, 0x3f, 0xec, 0xc2,
+ 0xed, 0x65, 0x42, 0x24, 0xbc, 0x87, 0x7b, 0x6a, 0x14, 0xed, 0x0b, 0x2f,
+ 0xb0, 0xa4, 0xcb, 0x2f, 0xfe, 0xcd, 0x69, 0xe4, 0x21, 0x3f, 0xf8, 0xb2,
+ 0xa0, 0xf9, 0x24, 0x41, 0x66, 0xd2, 0x2c, 0x3f, 0x08, 0xfb, 0xfd, 0x37,
+ 0xa3, 0xfe, 0x89, 0x96, 0x54, 0x33, 0xf7, 0xa7, 0x28, 0x94, 0xa7, 0xf1,
+ 0xc3, 0x33, 0x1f, 0xcd, 0x25, 0xee, 0x1c, 0x6d, 0x19, 0x26, 0xe4, 0x69,
+ 0x3a, 0x8f, 0x40, 0xf0, 0xd7, 0xf4, 0xa2, 0x57, 0x34, 0x28, 0xc2, 0xf9,
+ 0x08, 0x5f, 0xc2, 0xcf, 0x7c, 0x34, 0x84, 0x2d, 0xbf, 0xff, 0x37, 0x52,
+ 0x28, 0x71, 0xb7, 0x79, 0xe7, 0xfa, 0xcb, 0x01, 0x65, 0xe1, 0xfa, 0x16,
+ 0x5f, 0x67, 0x5f, 0x75, 0x96, 0xe6, 0xc3, 0x7c, 0x43, 0x96, 0x0e, 0x8f,
+ 0xdf, 0xe9, 0xf6, 0xc5, 0x97, 0xff, 0x87, 0xe8, 0x86, 0xff, 0x18, 0xba,
+ 0x92, 0xcb, 0x04, 0x67, 0xb2, 0x42, 0x17, 0x61, 0xd6, 0x5f, 0xff, 0x1a,
+ 0xda, 0xce, 0xbf, 0xe6, 0x12, 0x07, 0x0b, 0x2f, 0xfd, 0xd6, 0xff, 0x6e,
+ 0x37, 0xca, 0x0e, 0xb2, 0xb1, 0x12, 0xae, 0xa3, 0x7a, 0x27, 0x65, 0x95,
+ 0x8a, 0x96, 0xcd, 0x86, 0x5b, 0x42, 0x07, 0x44, 0xef, 0x0a, 0xb2, 0x21,
+ 0xbf, 0xff, 0xed, 0x60, 0xc9, 0xdf, 0x7f, 0x33, 0x73, 0xe5, 0x99, 0xa9,
+ 0x96, 0x5f, 0x8b, 0xfb, 0x0f, 0x3a, 0xcb, 0xe0, 0x9d, 0xfe, 0xb2, 0xff,
+ 0xfc, 0xd3, 0x96, 0x6f, 0xf3, 0x7f, 0xa9, 0x41, 0x4c, 0xb2, 0xa1, 0x14,
+ 0xa3, 0x2b, 0xf1, 0x15, 0xff, 0xff, 0x9b, 0x4d, 0x9b, 0xf2, 0x7c, 0x6f,
+ 0xc1, 0xc9, 0xcd, 0xf3, 0x2c, 0xbf, 0xfa, 0x50, 0xf2, 0xd8, 0xd3, 0x36,
+ 0x12, 0xcb, 0xfe, 0x98, 0xa0, 0xfe, 0x8d, 0xe7, 0x59, 0x7f, 0xfa, 0x4d,
+ 0xa0, 0x3f, 0xf2, 0x69, 0x37, 0xd6, 0x5f, 0xbe, 0xdb, 0x79, 0x3a, 0xcb,
+ 0xdb, 0x56, 0xd7, 0xb5, 0x2c, 0xbf, 0xdc, 0xcf, 0x37, 0x03, 0x3a, 0xcb,
+ 0xe6, 0xdb, 0xc9, 0xd6, 0x5c, 0xfd, 0x6c, 0x45, 0x86, 0xd3, 0x2b, 0xe1,
+ 0x67, 0xcd, 0x2e, 0x7e, 0x96, 0x56, 0x27, 0x3b, 0xd1, 0xdf, 0x21, 0xf5,
+ 0xf5, 0x1b, 0x30, 0xd5, 0x5f, 0x76, 0x5f, 0xd3, 0x5f, 0xe3, 0xe1, 0xbf,
+ 0xef, 0x37, 0xf8, 0xfd, 0x00, 0xc5, 0x97, 0x86, 0xf3, 0xac, 0xbb, 0x53,
+ 0xf6, 0x7b, 0x02, 0x1d, 0xdf, 0xff, 0x06, 0x7d, 0x37, 0xe7, 0x0e, 0xa5,
+ 0xcd, 0xc6, 0x59, 0x4c, 0xb9, 0xef, 0xe9, 0x79, 0x8f, 0x0a, 0x42, 0x31,
+ 0xbf, 0xb3, 0xf8, 0x4f, 0x32, 0xcb, 0xfb, 0x4d, 0xd9, 0x47, 0x96, 0x5f,
+ 0xf0, 0x5f, 0xef, 0x27, 0xea, 0x4b, 0x2f, 0xce, 0x26, 0x75, 0xf5, 0x97,
+ 0x6b, 0x8b, 0x2a, 0x48, 0xd2, 0xc2, 0xce, 0xcb, 0x78, 0x73, 0xb6, 0x53,
+ 0x7f, 0x98, 0x78, 0x7d, 0x98, 0x35, 0x97, 0x3f, 0x16, 0x5f, 0x98, 0xcd,
+ 0xac, 0x53, 0xb5, 0xac, 0xbf, 0xfe, 0x0e, 0xb5, 0x05, 0x86, 0xb7, 0xbd,
+ 0x82, 0x2c, 0xb0, 0xad, 0x65, 0x68, 0xf9, 0x42, 0xa1, 0x7d, 0x1a, 0x89,
+ 0x96, 0x5e, 0x28, 0x3a, 0xcb, 0x42, 0xca, 0x98, 0xd5, 0x9c, 0x6e, 0xff,
+ 0x1c, 0x25, 0xfe, 0x07, 0x4b, 0x2a, 0x49, 0xd5, 0x8c, 0xd0, 0xd1, 0x6d,
+ 0x42, 0x70, 0xe4, 0x44, 0x9b, 0xb6, 0x45, 0x6d, 0x2c, 0xbd, 0xac, 0xc5,
+ 0x94, 0x03, 0x59, 0xba, 0x23, 0x7f, 0xff, 0x75, 0xc8, 0x96, 0xb2, 0x78,
+ 0xd6, 0x7d, 0xba, 0x31, 0x65, 0x8d, 0x59, 0x53, 0x9f, 0x81, 0x2f, 0x5f,
+ 0xba, 0x96, 0xb9, 0xc5, 0x95, 0x07, 0x99, 0x84, 0x57, 0xff, 0x6e, 0x84,
+ 0xfe, 0x83, 0xcd, 0xb8, 0xc3, 0x59, 0x7f, 0xba, 0xf6, 0x4d, 0x33, 0xf1,
+ 0x65, 0x32, 0x20, 0x9d, 0x32, 0xfe, 0x2e, 0xa5, 0xf0, 0x8d, 0x65, 0xfb,
+ 0x73, 0x08, 0xec, 0xb2, 0xa0, 0xf6, 0x1c, 0xbe, 0xf8, 0xa3, 0x0c, 0x59,
+ 0x78, 0xb0, 0x0b, 0x2f, 0xff, 0x9b, 0x66, 0xe3, 0x4f, 0xb3, 0xd9, 0x31,
+ 0x61, 0x8b, 0x2f, 0xa6, 0xcc, 0x9d, 0x65, 0xfb, 0x8d, 0xf2, 0x85, 0x97,
+ 0x67, 0xb8, 0x79, 0x3f, 0x23, 0xb1, 0x82, 0x94, 0xc2, 0xb4, 0x43, 0xe1,
+ 0xbf, 0xc2, 0x86, 0xfe, 0x33, 0xe5, 0x07, 0xe2, 0xca, 0x73, 0xfc, 0x0a,
+ 0x75, 0xfa, 0x6f, 0x60, 0x1d, 0x65, 0x42, 0xbe, 0xa9, 0x43, 0x83, 0x21,
+ 0x45, 0xe7, 0x92, 0x8e, 0x9b, 0x79, 0x0d, 0xff, 0xff, 0x7b, 0x3f, 0xf7,
+ 0x9f, 0x3e, 0x76, 0x09, 0x4c, 0x58, 0x62, 0xcb, 0xff, 0x3e, 0xbf, 0x9d,
+ 0x01, 0xde, 0x65, 0x97, 0xff, 0xfc, 0x4e, 0x0e, 0x77, 0xe6, 0x2c, 0x69,
+ 0x7a, 0x3c, 0xc6, 0xac, 0xa1, 0xa6, 0x17, 0x33, 0x3f, 0xcf, 0xef, 0xef,
+ 0xfb, 0x25, 0x20, 0x2c, 0xa8, 0x3e, 0x02, 0x32, 0xbf, 0xc4, 0xef, 0xbe,
+ 0x5b, 0xc0, 0xb2, 0xff, 0xfb, 0x91, 0x37, 0xa3, 0x79, 0x60, 0xfd, 0x1c,
+ 0x59, 0x43, 0x44, 0x3f, 0xcd, 0xaf, 0xbb, 0x80, 0x71, 0x65, 0xfd, 0xe6,
+ 0x33, 0x6e, 0x00, 0xb2, 0xff, 0xf1, 0xdb, 0xa9, 0x70, 0xb3, 0xbf, 0x84,
+ 0x96, 0x5f, 0xee, 0x66, 0xe0, 0x1d, 0xe6, 0x59, 0x58, 0x8f, 0x8e, 0xc8,
+ 0xe6, 0x23, 0x39, 0x8f, 0x92, 0xef, 0xfe, 0xff, 0xb3, 0x7e, 0xe3, 0x04,
+ 0x78, 0x35, 0x97, 0xfc, 0xff, 0x2c, 0x1f, 0xb3, 0xeb, 0x2f, 0xe0, 0x34,
+ 0xb8, 0xc3, 0x59, 0x50, 0xaa, 0x5f, 0x23, 0x9f, 0x64, 0xb7, 0x49, 0x09,
+ 0xbd, 0xf8, 0xbb, 0x7e, 0x32, 0xcb, 0xff, 0xfb, 0x45, 0x11, 0xd6, 0xce,
+ 0x7c, 0xa0, 0x7e, 0x8f, 0xac, 0xb9, 0xbc, 0xb2, 0xfa, 0x44, 0xe2, 0x2c,
+ 0xbf, 0xc3, 0x70, 0x6b, 0x4e, 0x05, 0x97, 0xda, 0xef, 0x70, 0xc5, 0x97,
+ 0xc6, 0x8a, 0x5c, 0xc5, 0x95, 0x87, 0xa0, 0xe5, 0x14, 0xc8, 0xa3, 0x28,
+ 0x41, 0xd4, 0x27, 0x09, 0x84, 0xfb, 0x8b, 0x8e, 0x2c, 0x18, 0x62, 0xdf,
+ 0xfd, 0xa2, 0xcd, 0xfa, 0xc6, 0xf4, 0x0d, 0x65, 0xe7, 0xdc, 0x65, 0x97,
+ 0xfe, 0x13, 0xe6, 0xb1, 0xb1, 0x85, 0x0b, 0x2d, 0xd2, 0xcb, 0xff, 0xcc,
+ 0xef, 0x37, 0xfd, 0x92, 0xf3, 0x6f, 0x59, 0x7f, 0xfd, 0x9f, 0xe6, 0x19,
+ 0x9e, 0x6d, 0x06, 0x00, 0xb2, 0xa1, 0x15, 0x9b, 0x82, 0x44, 0x97, 0x7e,
+ 0x13, 0xe5, 0x00, 0x59, 0x50, 0x9d, 0x37, 0x48, 0x9a, 0x1e, 0x3c, 0x3a,
+ 0xf7, 0x98, 0xdf, 0xa3, 0xf9, 0xe8, 0x59, 0x7f, 0xe0, 0x94, 0xde, 0xc2,
+ 0xc6, 0x1a, 0xcb, 0xd3, 0xcd, 0x8b, 0x2f, 0xff, 0xb7, 0xe7, 0x7a, 0x77,
+ 0xea, 0x5c, 0xdc, 0x62, 0x59, 0x50, 0x7e, 0x6e, 0x3d, 0x7f, 0xf6, 0xe3,
+ 0x67, 0xa3, 0x7f, 0x3d, 0x1d, 0x2c, 0xa6, 0x4c, 0x67, 0xd0, 0xb0, 0xe1,
+ 0x05, 0xf4, 0x7f, 0x0e, 0xb2, 0xff, 0xdc, 0xf6, 0x19, 0xe6, 0x30, 0xb1,
+ 0x65, 0x00, 0xf8, 0x37, 0x90, 0xdf, 0xba, 0x91, 0x41, 0xd6, 0x5f, 0xff,
+ 0xff, 0xe3, 0xee, 0x37, 0x81, 0x8e, 0x5d, 0xe7, 0x52, 0xe3, 0x7f, 0x8d,
+ 0xd4, 0x8a, 0x3d, 0x0b, 0x2f, 0xec, 0xf3, 0x66, 0xa6, 0x59, 0x7f, 0xec,
+ 0xea, 0x5c, 0x6f, 0xb9, 0x62, 0xcb, 0xfd, 0x87, 0xf6, 0x4c, 0xf3, 0x2c,
+ 0xbf, 0x34, 0xfe, 0x88, 0xd8, 0x7e, 0x3f, 0x3d, 0xad, 0x88, 0xde, 0xc8,
+ 0x4f, 0x5f, 0xfe, 0xf4, 0x75, 0x9a, 0x8f, 0xb7, 0x6c, 0x35, 0x97, 0x83,
+ 0xa9, 0x96, 0x5f, 0x64, 0xd9, 0xf1, 0x9f, 0x47, 0x12, 0xac, 0xc3, 0x46,
+ 0x57, 0xa1, 0x23, 0x50, 0xaa, 0x3b, 0x0a, 0x3d, 0x28, 0xe6, 0xff, 0xff,
+ 0xcc, 0x59, 0xf8, 0x39, 0x81, 0x79, 0xf6, 0x67, 0x9b, 0x5e, 0x75, 0x97,
+ 0xe3, 0x4d, 0x7f, 0xf1, 0x65, 0xff, 0xf6, 0x4e, 0xe3, 0x60, 0xf7, 0xa6,
+ 0x32, 0x66, 0x59, 0x50, 0x8e, 0x9c, 0x6d, 0xd1, 0x55, 0xcf, 0xba, 0xb2,
+ 0xf7, 0x98, 0xc5, 0x97, 0xee, 0xa5, 0xc2, 0xc3, 0x9b, 0x6f, 0x8c, 0xdf,
+ 0xfb, 0x3a, 0x97, 0x26, 0xd3, 0xff, 0x8b, 0x2f, 0xc5, 0x1d, 0xc8, 0xeb,
+ 0x2f, 0xff, 0x66, 0xe7, 0x83, 0x37, 0xb2, 0x69, 0x47, 0x4b, 0x2f, 0xfe,
+ 0xe6, 0x4d, 0xe8, 0xdf, 0x9e, 0xf4, 0x2c, 0xa1, 0xa2, 0xfb, 0x45, 0x1f,
+ 0x50, 0xbf, 0xce, 0x0e, 0x1d, 0xfa, 0xfa, 0xca, 0x59, 0x7f, 0xdc, 0x20,
+ 0x87, 0xf2, 0x83, 0x56, 0x57, 0x47, 0x8b, 0xf0, 0xba, 0xc4, 0x66, 0x39,
+ 0x80, 0x5e, 0x6f, 0xfd, 0x93, 0xea, 0x23, 0xed, 0xe8, 0x59, 0x7f, 0xe6,
+ 0x9b, 0x84, 0xee, 0x3f, 0x32, 0xcb, 0xf8, 0xb3, 0x9e, 0x81, 0xac, 0xa8,
+ 0x3e, 0x9c, 0x3d, 0xa2, 0x46, 0x37, 0x21, 0x4d, 0x7f, 0xfa, 0x4c, 0x6b,
+ 0x7c, 0xb2, 0x5a, 0xe7, 0x16, 0x5f, 0xfd, 0x87, 0x0c, 0x9c, 0x7b, 0x3e,
+ 0x70, 0x2c, 0xbf, 0xa2, 0x6c, 0xde, 0xda, 0x59, 0x7f, 0xfa, 0x5e, 0x79,
+ 0x76, 0x4f, 0xbb, 0xbb, 0xba, 0xcb, 0x2a, 0x11, 0x05, 0x85, 0xf7, 0xcd,
+ 0xac, 0x25, 0x95, 0x09, 0xaa, 0x79, 0x28, 0xa1, 0x93, 0xc2, 0x1b, 0xff,
+ 0xcc, 0x11, 0xe1, 0x06, 0x4c, 0x3c, 0x02, 0xcb, 0xff, 0x82, 0xe7, 0xf9,
+ 0x64, 0xe5, 0x9d, 0x2c, 0xbf, 0xec, 0xee, 0x3c, 0xd0, 0x43, 0x59, 0x7f,
+ 0xf7, 0xb0, 0xc0, 0xe3, 0x7b, 0x91, 0x3a, 0xcb, 0x98, 0x33, 0x9f, 0xe7,
+ 0x46, 0xf5, 0x3b, 0x2f, 0xe8, 0x71, 0x9f, 0xe4, 0x25, 0x7b, 0x95, 0x65,
+ 0xa8, 0xc8, 0x1d, 0x90, 0x07, 0xc5, 0x1e, 0x5f, 0x21, 0xe9, 0xf8, 0xde,
+ 0xf7, 0xa0, 0x98, 0x91, 0xbb, 0x0c, 0x0b, 0xe9, 0xa4, 0xd3, 0x2c, 0xb8,
+ 0xa7, 0x59, 0x7c, 0x0d, 0x3e, 0xda, 0xca, 0xd8, 0x7c, 0x1b, 0x41, 0x27,
+ 0x42, 0xf7, 0xfe, 0x63, 0x37, 0x1a, 0x7e, 0x44, 0x4c, 0xb2, 0xdb, 0xab,
+ 0x2e, 0xf6, 0xea, 0xcb, 0xff, 0xd9, 0xbf, 0xcf, 0x20, 0x3f, 0x40, 0x6e,
+ 0x96, 0x5b, 0xf0, 0x7c, 0xfe, 0x1a, 0xbf, 0xfe, 0xd4, 0xf1, 0xb9, 0xc2,
+ 0xcf, 0xfd, 0xb5, 0xda, 0xcb, 0xfb, 0x27, 0xe1, 0x66, 0xf5, 0x95, 0x24,
+ 0xc9, 0x59, 0xed, 0xc9, 0xfe, 0xa9, 0x63, 0x56, 0x54, 0x33, 0xe0, 0xb2,
+ 0x98, 0x98, 0xd1, 0xa4, 0xee, 0x1b, 0xbc, 0x6d, 0x02, 0x1e, 0x5f, 0xff,
+ 0xa5, 0x9c, 0x72, 0x07, 0xb2, 0x3f, 0xc8, 0x02, 0xcb, 0xe7, 0x3b, 0xc9,
+ 0x65, 0xff, 0xde, 0x6d, 0x98, 0x58, 0xda, 0x7d, 0xeb, 0x2f, 0xfe, 0x62,
+ 0x71, 0x96, 0x0f, 0xd1, 0xc5, 0x97, 0x84, 0x8d, 0x2c, 0xbf, 0xe9, 0xcf,
+ 0x1a, 0xf9, 0x44, 0xeb, 0x2f, 0xbb, 0xe8, 0xde, 0xd6, 0x5e, 0x12, 0x00,
+ 0xb2, 0x98, 0xf1, 0x00, 0x4f, 0x7d, 0xbe, 0x0b, 0xb5, 0x97, 0xff, 0xf4,
+ 0x16, 0x03, 0x98, 0x3f, 0x44, 0xe7, 0x09, 0x0d, 0x65, 0x31, 0xff, 0x78,
+ 0x92, 0xfc, 0xdf, 0xfc, 0x49, 0x65, 0xd1, 0xd2, 0xca, 0x92, 0xa9, 0x31,
+ 0xa9, 0x9a, 0x43, 0xda, 0x2e, 0x90, 0x5c, 0x74, 0x9f, 0xbf, 0x09, 0xfd,
+ 0xe4, 0x3b, 0x64, 0xf7, 0xf1, 0x7e, 0x39, 0xf6, 0x59, 0x7f, 0xff, 0x44,
+ 0xd8, 0x3f, 0x46, 0xff, 0x67, 0xca, 0x20, 0xeb, 0x2f, 0xee, 0x86, 0x3c,
+ 0x79, 0xd6, 0x5f, 0xff, 0xbc, 0xdb, 0xcb, 0x0c, 0xc6, 0xfb, 0x69, 0xc0,
+ 0xb2, 0xf1, 0x40, 0xd6, 0x5f, 0x4b, 0x3d, 0x8b, 0x2f, 0x4e, 0x12, 0x59,
+ 0x77, 0x5c, 0x84, 0x6e, 0xf6, 0x5f, 0x32, 0xab, 0x8d, 0x88, 0x43, 0x7f,
+ 0x79, 0xa6, 0x77, 0x9d, 0x65, 0xe8, 0xc0, 0x2c, 0xb4, 0x76, 0x79, 0x33,
+ 0x17, 0x54, 0x2a, 0x2e, 0x39, 0x63, 0xc6, 0x70, 0x08, 0x50, 0xdf, 0x34,
+ 0xe7, 0x85, 0x97, 0xf4, 0x6a, 0x78, 0xd4, 0xeb, 0x2f, 0xff, 0x13, 0x99,
+ 0xe8, 0x93, 0x16, 0x1e, 0x16, 0x5f, 0xfd, 0x9d, 0x7e, 0x33, 0x5a, 0x88,
+ 0xdd, 0x59, 0x63, 0x26, 0x44, 0x69, 0x23, 0xd4, 0x91, 0xcd, 0x90, 0xbc,
+ 0xbf, 0xed, 0xee, 0x40, 0xf6, 0x01, 0xd6, 0x5f, 0x98, 0xdf, 0xb4, 0xeb,
+ 0x2f, 0xff, 0x66, 0x00, 0xf1, 0x37, 0x07, 0xe7, 0x9d, 0x65, 0x32, 0x2b,
+ 0x7c, 0x72, 0x45, 0x37, 0xff, 0xa3, 0xd0, 0x79, 0x8b, 0x0c, 0xfe, 0x79,
+ 0x65, 0xf3, 0xf9, 0x89, 0x65, 0xf6, 0x02, 0x09, 0x65, 0x8a, 0x73, 0xc0,
+ 0xf1, 0x05, 0x2c, 0xbf, 0x4b, 0x51, 0x83, 0x59, 0x73, 0x07, 0xa3, 0x64,
+ 0x41, 0x77, 0xff, 0xfb, 0x25, 0xdf, 0x9b, 0xd1, 0x9a, 0x97, 0xca, 0x0f,
+ 0xc5, 0x97, 0xfe, 0xd3, 0xce, 0x18, 0xc2, 0x0c, 0xeb, 0x2b, 0xc8, 0x9f,
+ 0xe3, 0x05, 0xff, 0xd1, 0xc2, 0xc3, 0x5b, 0xde, 0xcd, 0xc5, 0x97, 0xfc,
+ 0x1f, 0xee, 0x73, 0x18, 0x86, 0xb2, 0xf8, 0x31, 0xd0, 0xd6, 0x5f, 0xec,
+ 0x3e, 0x4d, 0x26, 0xc5, 0x94, 0x35, 0x5a, 0xdd, 0x97, 0x3c, 0x22, 0xb8,
+ 0xb5, 0xf8, 0x65, 0x84, 0x8f, 0x7a, 0x31, 0x87, 0x62, 0x11, 0xdc, 0x33,
+ 0xac, 0xbe, 0xdd, 0x8d, 0x4e, 0xb2, 0xf0, 0x7f, 0xc5, 0x97, 0xb7, 0x58,
+ 0xc5, 0x95, 0x0b, 0x96, 0x59, 0x2e, 0xaa, 0x68, 0x47, 0x38, 0xb8, 0x49,
+ 0xb7, 0x47, 0x6f, 0xf6, 0xbb, 0x9b, 0x1b, 0xc1, 0x59, 0x7f, 0xfe, 0x6f,
+ 0xf1, 0xbb, 0x7d, 0x77, 0xe6, 0xde, 0xe7, 0x59, 0x7f, 0xff, 0xce, 0x6f,
+ 0x06, 0xd9, 0xd7, 0x6c, 0x4f, 0xd1, 0xe2, 0x38, 0xb2, 0xff, 0x44, 0xbe,
+ 0x6b, 0x76, 0xcb, 0x2b, 0xc8, 0x9b, 0x26, 0x7b, 0xc3, 0xc9, 0x2c, 0xbd,
+ 0xb8, 0xc6, 0x2c, 0xbc, 0x6b, 0x76, 0xb2, 0xfc, 0xdb, 0xcb, 0x39, 0xb0,
+ 0xf6, 0xbc, 0x39, 0xf2, 0x0b, 0xfe, 0xdf, 0x83, 0x9b, 0x30, 0x8d, 0x59,
+ 0x7f, 0xfa, 0x51, 0xcf, 0x41, 0x7f, 0xdb, 0x8c, 0x75, 0x94, 0x48, 0x87,
+ 0xf9, 0xdd, 0xfe, 0xff, 0xb7, 0x1b, 0xcf, 0x32, 0xcb, 0xfa, 0x3b, 0x27,
+ 0xeb, 0xeb, 0x2f, 0xf7, 0x35, 0x13, 0xbe, 0xbb, 0x59, 0x7d, 0x3e, 0xdc,
+ 0x1d, 0x65, 0x31, 0xed, 0x88, 0x6b, 0x52, 0x4f, 0x65, 0xa1, 0xab, 0xb8,
+ 0x44, 0x73, 0x7f, 0xc2, 0x26, 0xfd, 0x1f, 0x9f, 0x0c, 0x59, 0x7f, 0xee,
+ 0xbb, 0x27, 0x9d, 0xe4, 0xde, 0x59, 0x5a, 0x3e, 0x90, 0x94, 0xdf, 0x63,
+ 0x03, 0x8b, 0x2f, 0xfe, 0xe3, 0xf5, 0xff, 0xe7, 0x63, 0x0c, 0xeb, 0x2d,
+ 0x9d, 0x9f, 0x4f, 0xc8, 0x6f, 0xc3, 0xec, 0x39, 0xb8, 0xb2, 0xff, 0xc5,
+ 0x1d, 0x7a, 0x18, 0x9c, 0x6b, 0x2a, 0x63, 0xe8, 0x39, 0x65, 0xf7, 0x30,
+ 0x8d, 0x59, 0x7d, 0x19, 0x27, 0x59, 0x5d, 0x1e, 0x17, 0x88, 0xaf, 0xda,
+ 0x06, 0xd0, 0x29, 0xda, 0x96, 0x54, 0x22, 0xfc, 0x6c, 0xae, 0x47, 0x7f,
+ 0x87, 0xbe, 0x0b, 0xf8, 0x05, 0x97, 0xe8, 0xff, 0xa3, 0xeb, 0x2e, 0x20,
+ 0x2c, 0xa9, 0xcf, 0xc7, 0x46, 0x8e, 0x4f, 0x7f, 0xff, 0xf8, 0x3a, 0xf6,
+ 0x4d, 0x33, 0xea, 0x6f, 0xf8, 0x20, 0xe6, 0x36, 0xf1, 0xc2, 0xcb, 0xfe,
+ 0x6f, 0x73, 0x4c, 0x50, 0x75, 0x97, 0xf4, 0x73, 0x71, 0xba, 0xfa, 0xcb,
+ 0xfa, 0x39, 0x31, 0x64, 0xcb, 0x29, 0x93, 0x13, 0xdc, 0x7d, 0xd1, 0xbf,
+ 0x8c, 0x6f, 0xdf, 0xf3, 0x91, 0xab, 0x2f, 0xf6, 0xe9, 0x04, 0x3d, 0xb1,
+ 0xab, 0x2d, 0xf5, 0x94, 0xb2, 0xf9, 0x8c, 0x3b, 0xf4, 0x5e, 0x7c, 0x46,
+ 0xff, 0x06, 0x71, 0xfb, 0x0a, 0x16, 0x54, 0x22, 0xff, 0xb5, 0x42, 0x38,
+ 0xbf, 0xfe, 0x83, 0xee, 0x34, 0x41, 0x6b, 0x18, 0xf8, 0xb2, 0xff, 0xec,
+ 0x1f, 0xa0, 0xce, 0xa5, 0xf0, 0x8d, 0x65, 0xff, 0xc0, 0xf3, 0x07, 0xfc,
+ 0xf0, 0x73, 0xeb, 0x2e, 0xce, 0x2c, 0xb9, 0xfe, 0xb2, 0xd2, 0xd1, 0xac,
+ 0xf0, 0xb5, 0xb8, 0xe8, 0x98, 0x0b, 0x8d, 0xb0, 0x6a, 0xaa, 0xf1, 0x03,
+ 0xb8, 0x73, 0xcc, 0x5e, 0x49, 0xdf, 0x86, 0xfd, 0xff, 0xec, 0xd0, 0xa3,
+ 0x9f, 0x26, 0xeb, 0x9b, 0x3e, 0xb2, 0xff, 0xf6, 0x41, 0x67, 0x65, 0x9f,
+ 0x0b, 0x98, 0xb2, 0xff, 0xf4, 0x17, 0xb2, 0x3a, 0x76, 0xe0, 0x86, 0xac,
+ 0xbf, 0xec, 0x06, 0xde, 0x38, 0xf3, 0x8b, 0x2f, 0xfe, 0x6f, 0xfb, 0x1a,
+ 0x5c, 0xce, 0xbe, 0xb2, 0x86, 0x98, 0x86, 0x24, 0x12, 0x57, 0x0e, 0xaf,
+ 0xf8, 0x05, 0x9f, 0xe3, 0xb9, 0x2c, 0xbf, 0xf8, 0x39, 0x36, 0x37, 0x65,
+ 0x9e, 0xc5, 0x96, 0x07, 0x67, 0xf2, 0x46, 0xd7, 0x8e, 0xfd, 0x2c, 0xbf,
+ 0xff, 0xa4, 0xc3, 0xcf, 0x64, 0xf1, 0x26, 0xe7, 0x33, 0x71, 0x65, 0x69,
+ 0x14, 0x40, 0x28, 0xf8, 0xed, 0xc1, 0x35, 0x65, 0xfe, 0xcf, 0x0f, 0xd0,
+ 0x53, 0xac, 0xb0, 0xfc, 0x79, 0x66, 0x0c, 0x5f, 0x7b, 0x06, 0xcb, 0x2a,
+ 0x0f, 0x2b, 0x85, 0x35, 0x0c, 0xea, 0x99, 0x1a, 0x8e, 0x1e, 0x79, 0x29,
+ 0x55, 0xa1, 0x81, 0xa8, 0x45, 0xfa, 0x34, 0xf7, 0x84, 0xf9, 0x4b, 0xed,
+ 0xe3, 0x47, 0xe3, 0x61, 0x0c, 0x6a, 0xe2, 0x43, 0x16, 0xff, 0x60, 0xe7,
+ 0xd0, 0x60, 0x0b, 0x2f, 0xff, 0x80, 0xfe, 0xc0, 0x01, 0xf5, 0x9b, 0xfd,
+ 0x8b, 0x2f, 0xff, 0xdf, 0xe1, 0x04, 0x3d, 0x4b, 0x83, 0xf6, 0x37, 0xd6,
+ 0x5a, 0x34, 0x8d, 0xb3, 0x9a, 0x12, 0x85, 0xff, 0xe2, 0x61, 0x8e, 0x3f,
+ 0xc1, 0xfa, 0x09, 0x65, 0x8e, 0xb2, 0xfc, 0x06, 0x29, 0x71, 0x65, 0x74,
+ 0x6e, 0x3e, 0x23, 0x58, 0x8a, 0x26, 0x84, 0x05, 0xfd, 0xe9, 0x9b, 0xcc,
+ 0x75, 0x97, 0x03, 0x8b, 0x2f, 0xbb, 0x20, 0xf1, 0x65, 0xff, 0x0f, 0x0e,
+ 0x59, 0xff, 0x32, 0xcb, 0xf0, 0x74, 0x0d, 0xaf, 0x69, 0x2c, 0xac, 0x44,
+ 0x73, 0x11, 0xf0, 0xde, 0xb1, 0x30, 0x16, 0x2e, 0xf4, 0x29, 0x6f, 0xda,
+ 0xe1, 0x44, 0xeb, 0x2f, 0xff, 0xdb, 0xa5, 0x9b, 0xdf, 0x8d, 0x85, 0xed,
+ 0xc6, 0x3a, 0xcb, 0x4b, 0x11, 0x04, 0xc5, 0x17, 0xda, 0x8c, 0x25, 0x97,
+ 0xc6, 0xea, 0x0e, 0xb2, 0xf4, 0xf8, 0x62, 0xcb, 0xb2, 0x75, 0x95, 0xb0,
+ 0xfe, 0x20, 0x80, 0xc2, 0x3d, 0xb1, 0xeb, 0xfc, 0xc5, 0xf9, 0x66, 0xb1,
+ 0x65, 0xfd, 0x1d, 0xe9, 0xa0, 0xeb, 0x2a, 0x47, 0xbc, 0x46, 0x37, 0xff,
+ 0x8e, 0x07, 0xd6, 0x6f, 0xc6, 0x1f, 0x99, 0x65, 0xff, 0x9c, 0x1a, 0x82,
+ 0xff, 0xb2, 0x4b, 0x2f, 0xff, 0x03, 0x18, 0xbf, 0x87, 0x7f, 0x81, 0xd6,
+ 0x54, 0x23, 0xbf, 0x08, 0x59, 0x28, 0x27, 0xb7, 0xb3, 0xce, 0xb2, 0xf0,
+ 0x42, 0x4b, 0x2f, 0xcd, 0xef, 0x60, 0xd6, 0x5a, 0x65, 0x83, 0x3c, 0x3e,
+ 0x0e, 0x50, 0xd1, 0x1c, 0xeb, 0xd7, 0xfe, 0xc9, 0x79, 0xe5, 0xb3, 0xf2,
+ 0x65, 0x97, 0xe2, 0xc0, 0x07, 0x8b, 0x2f, 0xf4, 0x7f, 0xd8, 0xc4, 0xeb,
+ 0x2a, 0x73, 0xd7, 0xd1, 0x3d, 0xfe, 0x06, 0xde, 0x38, 0xf3, 0x8b, 0x2f,
+ 0x6e, 0x31, 0xd6, 0x5f, 0xff, 0x38, 0x39, 0x00, 0xfe, 0x30, 0xf0, 0xa6,
+ 0x59, 0xe2, 0xfe, 0xa1, 0x1a, 0x98, 0x46, 0xea, 0x97, 0xfa, 0x5f, 0xf6,
+ 0x6a, 0x3e, 0xb2, 0xfe, 0x33, 0x3b, 0xef, 0x0c, 0x59, 0x77, 0x7b, 0xd6,
+ 0x58, 0x0b, 0x2f, 0xff, 0x4b, 0x99, 0xa8, 0xe1, 0x60, 0x03, 0xc5, 0x95,
+ 0x87, 0xb4, 0xe2, 0x35, 0x08, 0x94, 0xf3, 0xa5, 0x62, 0x39, 0xff, 0x0c,
+ 0x5b, 0xff, 0xd9, 0xba, 0x03, 0xc4, 0xdf, 0x60, 0xeb, 0x8b, 0x2f, 0xf1,
+ 0xf3, 0x0b, 0xfb, 0x78, 0xb2, 0xff, 0xee, 0x7e, 0x23, 0x40, 0x98, 0xb0,
+ 0xc5, 0x97, 0xde, 0x6c, 0xe9, 0x65, 0x74, 0x89, 0xb7, 0x34, 0x02, 0x2d,
+ 0xe3, 0x64, 0x15, 0x97, 0xef, 0x46, 0xa7, 0x3a, 0xcb, 0xfc, 0x17, 0x2f,
+ 0x63, 0xcc, 0xb2, 0xdd, 0x4c, 0x7b, 0x66, 0x14, 0xd3, 0x22, 0x91, 0xde,
+ 0x6a, 0x15, 0x8f, 0xe4, 0x63, 0x4c, 0x4e, 0xf0, 0xe9, 0x28, 0x6a, 0x54,
+ 0x32, 0xb6, 0x25, 0x0d, 0x6c, 0x8c, 0x9f, 0xa8, 0x5b, 0x34, 0x27, 0xfd,
+ 0x1c, 0x73, 0xc3, 0x20, 0x04, 0x45, 0x1b, 0x5f, 0x25, 0xa6, 0x5c, 0x12,
+ 0x59, 0x7d, 0xd7, 0x23, 0xa5, 0x94, 0x2b, 0x37, 0x44, 0x2d, 0x7e, 0x99,
+ 0xa7, 0xce, 0x96, 0x5e, 0xd0, 0x64, 0xb2, 0xba, 0x3c, 0x7f, 0x95, 0x5f,
+ 0xdb, 0x3e, 0x50, 0x7e, 0x2c, 0xa6, 0x3d, 0x27, 0x23, 0xbf, 0xf3, 0xeb,
+ 0x58, 0x26, 0x0d, 0xe4, 0xb2, 0xf1, 0x60, 0x16, 0x5a, 0x16, 0x50, 0x0d,
+ 0x5f, 0xc6, 0xee, 0x7f, 0xac, 0xad, 0x1b, 0x7f, 0x10, 0xdf, 0x1e, 0x35,
+ 0xc5, 0x97, 0xfa, 0x0e, 0x58, 0x00, 0xf1, 0x65, 0xff, 0x6b, 0x3d, 0x93,
+ 0xec, 0x6e, 0x2c, 0xac, 0x45, 0x83, 0x10, 0x91, 0x10, 0x4c, 0xaf, 0xf4,
+ 0x9b, 0x9c, 0x8d, 0x49, 0x65, 0xf3, 0x9e, 0x19, 0x65, 0xef, 0xb1, 0x8b,
+ 0x28, 0x67, 0xe1, 0x31, 0x99, 0x84, 0x17, 0xf3, 0x10, 0x65, 0x9c, 0x59,
+ 0x7f, 0xfe, 0x93, 0x7f, 0x9d, 0xf9, 0xbf, 0xd4, 0x9b, 0xfc, 0x59, 0x7f,
+ 0xd0, 0x03, 0xbc, 0xb5, 0x93, 0xac, 0xbd, 0x3e, 0x6e, 0xac, 0xbf, 0xa3,
+ 0x3f, 0xc7, 0xe9, 0x65, 0xff, 0x7e, 0x3a, 0x03, 0xfb, 0xcc, 0xb2, 0xf9,
+ 0xb6, 0xf2, 0x75, 0x95, 0x87, 0xbd, 0xf3, 0x9b, 0x1d, 0x65, 0xfc, 0xc4,
+ 0x19, 0x67, 0x36, 0x1b, 0x2d, 0xe4, 0x35, 0x0a, 0x84, 0x4d, 0x31, 0x98,
+ 0xb3, 0xcb, 0x04, 0x73, 0xc2, 0x0f, 0xc2, 0xf6, 0xfb, 0xc1, 0xcf, 0xac,
+ 0xbf, 0xf0, 0x7a, 0x97, 0x3d, 0x93, 0x84, 0x96, 0x5f, 0x89, 0xfe, 0xe7,
+ 0x59, 0x4c, 0x88, 0x9d, 0x11, 0x08, 0x83, 0x61, 0x7b, 0x5b, 0xfa, 0xdd,
+ 0xed, 0x4b, 0xbb, 0x44, 0x63, 0x62, 0x87, 0xa1, 0x50, 0xb2, 0x25, 0x61,
+ 0x4f, 0x0e, 0xe9, 0x47, 0x16, 0x39, 0xf2, 0x4c, 0xac, 0x22, 0x0d, 0x97,
+ 0x35, 0xdc, 0xea, 0xe7, 0x51, 0x8d, 0xb4, 0x7f, 0x13, 0x4e, 0x41, 0xea,
+ 0x71, 0xa8, 0xf1, 0xe9, 0x7a, 0xb1, 0x78, 0x79, 0x60, 0x60, 0x95, 0x8a,
+ 0x2b, 0x48, 0x29, 0xdb, 0xae, 0x53, 0xc4, 0x3f, 0x4c, 0x9e, 0x0c, 0x3c,
+ 0xb7, 0xc2, 0xf4, 0xc2, 0x0d, 0xb8, 0xd4, 0x04, 0x95, 0x77, 0xbb, 0x0f,
+ 0x4b, 0xfb, 0x42, 0xc7, 0xbd, 0xa1, 0x65, 0xfd, 0xba, 0xc3, 0x28, 0x99,
+ 0x65, 0xe8, 0x72, 0x59, 0x7d, 0x9e, 0x7f, 0xac, 0xb0, 0xa7, 0x0f, 0xaf,
+ 0xc6, 0x04, 0x35, 0x7f, 0x0a, 0x9b, 0x43, 0xff, 0x37, 0x56, 0x5f, 0xfd,
+ 0x07, 0x28, 0xd9, 0x34, 0xa3, 0x53, 0xac, 0xbf, 0xfd, 0x1a, 0x0c, 0xd3,
+ 0x37, 0x98, 0xee, 0x35, 0x97, 0xf1, 0x3f, 0xf9, 0x1b, 0x8b, 0x2f, 0xef,
+ 0x09, 0xbb, 0x04, 0x05, 0x97, 0xff, 0xfe, 0x2f, 0xf2, 0x1a, 0x59, 0xba,
+ 0x5f, 0x8f, 0x41, 0xa1, 0x8d, 0xd5, 0x97, 0xb7, 0x47, 0x0b, 0x29, 0xd1,
+ 0x1e, 0x17, 0x0b, 0xf0, 0x7f, 0x34, 0x1a, 0xb2, 0xff, 0xa2, 0x7e, 0x4c,
+ 0xc7, 0x79, 0x96, 0x50, 0xd5, 0x04, 0x76, 0x8e, 0xc9, 0x73, 0x17, 0xfa,
+ 0x18, 0x04, 0x45, 0xba, 0x55, 0x7f, 0xff, 0xf6, 0x6e, 0x93, 0xf7, 0xba,
+ 0x2f, 0x8c, 0x61, 0x67, 0x36, 0x3f, 0xc3, 0x0b, 0x2e, 0x03, 0x2c, 0xad,
+ 0x22, 0x47, 0x8f, 0x77, 0xf7, 0x6f, 0xa9, 0xf0, 0xc5, 0x95, 0x87, 0xa6,
+ 0xc4, 0x77, 0xff, 0xef, 0x61, 0x61, 0xbe, 0x79, 0x78, 0xc7, 0x10, 0xeb,
+ 0x2d, 0xd2, 0xcb, 0xfe, 0x86, 0xe6, 0x37, 0xa3, 0xeb, 0x2a, 0x47, 0x91,
+ 0xe1, 0x2b, 0xee, 0xdd, 0xfb, 0x54, 0x5a, 0xcb, 0xff, 0x9b, 0x5e, 0x7e,
+ 0x3f, 0xc9, 0xc0, 0xb2, 0xf9, 0xb5, 0xb8, 0x35, 0x95, 0x24, 0xd6, 0x1a,
+ 0x13, 0xfa, 0x22, 0xf1, 0x86, 0xf4, 0x2b, 0xf6, 0x49, 0xbc, 0x15, 0x97,
+ 0xfd, 0x20, 0xb7, 0xa7, 0x72, 0x1a, 0xcb, 0xff, 0x13, 0xea, 0x26, 0xd9,
+ 0x9a, 0x65, 0x97, 0xf3, 0x1d, 0xe6, 0xcf, 0x2c, 0xa6, 0x3e, 0xc3, 0x9f,
+ 0xdf, 0x81, 0x9b, 0xa5, 0xf5, 0x97, 0xf8, 0x25, 0x9b, 0xac, 0x63, 0x2c,
+ 0xbe, 0xe3, 0x97, 0x6b, 0x2b, 0xc7, 0xaf, 0xba, 0x6b, 0x50, 0x8a, 0x6c,
+ 0x84, 0x0d, 0xed, 0x41, 0xd6, 0x5f, 0xde, 0xce, 0x44, 0xfb, 0xab, 0x2f,
+ 0xff, 0x0e, 0x0e, 0x51, 0xb2, 0x69, 0x46, 0xa7, 0x59, 0x70, 0x06, 0xb2,
+ 0xfd, 0xae, 0xdd, 0xfb, 0x54, 0x50, 0x6b, 0xec, 0xef, 0x3a, 0x59, 0x74,
+ 0x85, 0xc2, 0x2f, 0x46, 0x9b, 0x82, 0xfe, 0x36, 0xac, 0x4c, 0xdd, 0xe1,
+ 0xdd, 0x7f, 0xde, 0xdd, 0x70, 0x0b, 0x8e, 0x18, 0xb2, 0xf4, 0xd1, 0xf5,
+ 0x95, 0x07, 0xb9, 0x87, 0xf6, 0xed, 0x65, 0xfd, 0xec, 0xff, 0x9c, 0xeb,
+ 0x2f, 0xf6, 0xcf, 0xc1, 0xdb, 0x53, 0x2c, 0xac, 0x3e, 0x30, 0x16, 0xdf,
+ 0xd8, 0x5d, 0xb9, 0x01, 0x65, 0x6c, 0x46, 0x11, 0x3a, 0xf0, 0x86, 0xff,
+ 0x4a, 0x35, 0x3c, 0x6a, 0x75, 0x97, 0xfb, 0xa9, 0x46, 0x7f, 0x66, 0x2c,
+ 0xbd, 0xdc, 0x76, 0xb2, 0xa1, 0x11, 0x18, 0x6a, 0xe6, 0xb7, 0xe3, 0xe6,
+ 0xe9, 0x01, 0x65, 0xec, 0x3b, 0x2c, 0xbe, 0xd3, 0x1a, 0x75, 0x97, 0xbf,
+ 0x9e, 0x59, 0x7f, 0xa0, 0xbf, 0x1a, 0x63, 0xac, 0xbb, 0xec, 0xb2, 0xff,
+ 0xfb, 0x00, 0xfa, 0xcd, 0xf8, 0x3c, 0x3c, 0x76, 0xb2, 0xa1, 0x31, 0xb1,
+ 0x95, 0x60, 0xd9, 0xa4, 0x7e, 0x1c, 0x73, 0x12, 0x16, 0xb8, 0xf3, 0x2c,
+ 0xbe, 0x00, 0x4a, 0x65, 0x97, 0x37, 0x6b, 0x2a, 0x0d, 0xd6, 0xd9, 0x1d,
+ 0xbd, 0xb0, 0xfd, 0x45, 0xa9, 0x5f, 0x9f, 0x87, 0x80, 0x2c, 0xbf, 0x4c,
+ 0x07, 0x29, 0x96, 0x5c, 0x4c, 0xb2, 0xa0, 0xdf, 0x76, 0x53, 0x7c, 0xe0,
+ 0xcd, 0x2c, 0xbe, 0x81, 0x63, 0x1a, 0xcb, 0xfd, 0x81, 0xef, 0xd1, 0xac,
+ 0x59, 0x7f, 0xda, 0x83, 0x0b, 0x06, 0xda, 0x59, 0x7f, 0xfd, 0x9e, 0xf3,
+ 0xb7, 0xe0, 0xb3, 0xd9, 0xda, 0xca, 0xc4, 0xeb, 0xcd, 0x2c, 0x66, 0x5f,
+ 0x10, 0x91, 0x0f, 0x09, 0x02, 0x67, 0xb6, 0x71, 0x7f, 0xa6, 0x6f, 0x86,
+ 0x66, 0xfa, 0xcb, 0xff, 0x9f, 0x77, 0x99, 0xba, 0x4f, 0xfc, 0xdd, 0x59,
+ 0x7f, 0xff, 0xf6, 0x80, 0xe3, 0x8d, 0x6e, 0xf3, 0x37, 0x48, 0x11, 0x30,
+ 0x9b, 0xa1, 0x3a, 0xcb, 0xff, 0xf9, 0xff, 0x87, 0xc6, 0x9a, 0x5e, 0xc1,
+ 0x87, 0xfc, 0x59, 0x7f, 0xfd, 0xc6, 0x9d, 0xf8, 0xe4, 0xff, 0xf4, 0x4c,
+ 0xb2, 0xff, 0xce, 0x40, 0xcf, 0xc1, 0x30, 0x16, 0x54, 0x26, 0xc4, 0x37,
+ 0xdf, 0xad, 0xed, 0xa7, 0xd8, 0x58, 0xa1, 0xb1, 0x21, 0xda, 0x46, 0xf1,
+ 0x29, 0x0a, 0x51, 0xa9, 0x64, 0x6f, 0x06, 0xa8, 0xf4, 0x4e, 0xd0, 0xa5,
+ 0x9a, 0x18, 0xfa, 0x26, 0x3c, 0x6a, 0x7e, 0x84, 0x1b, 0xc3, 0x88, 0xa1,
+ 0x73, 0xc8, 0xd2, 0x3f, 0x2a, 0x18, 0x2e, 0x66, 0x1a, 0x89, 0x1d, 0x6d,
+ 0xfe, 0x34, 0x5b, 0xfb, 0xd9, 0x3a, 0xcb, 0xff, 0xc2, 0xce, 0xf2, 0x17,
+ 0x9a, 0xed, 0xdf, 0xb5, 0x45, 0x16, 0xbf, 0xc2, 0xf3, 0x5d, 0xbb, 0xf6,
+ 0xa8, 0xba, 0x95, 0x10, 0x9d, 0x34, 0x94, 0x73, 0xb8, 0xd9, 0xdc, 0x39,
+ 0x1a, 0x77, 0x28, 0xf3, 0xf1, 0x3e, 0xbf, 0x69, 0x87, 0x94, 0xda, 0x0a,
+ 0xc6, 0xf4, 0xa3, 0x5c, 0xe1, 0xbf, 0xd7, 0x2f, 0xda, 0xed, 0xdf, 0xb5,
+ 0x44, 0x42, 0xb4, 0xeb, 0x2f, 0x79, 0x89, 0x65, 0xd8, 0x35, 0x96, 0xed,
+ 0x65, 0x76, 0x78, 0x7e, 0x1b, 0x21, 0x6b, 0xec, 0xde, 0xda, 0x59, 0x7c,
+ 0xda, 0xce, 0x96, 0x56, 0x23, 0xfc, 0xd3, 0x6e, 0x95, 0x77, 0x0b, 0xf6,
+ 0xc8, 0xef, 0x8a, 0x01, 0xc5, 0x97, 0xf6, 0x83, 0xed, 0xf8, 0x35, 0x97,
+ 0xb3, 0x06, 0xb2, 0xef, 0x8b, 0x98, 0xfb, 0x34, 0x42, 0x46, 0x14, 0x2d,
+ 0x1f, 0x59, 0x0b, 0xdb, 0xff, 0x85, 0x8a, 0xe0, 0xbe, 0x21, 0xcb, 0x27,
+ 0x59, 0x6d, 0xb5, 0x97, 0xd1, 0xe8, 0x3a, 0xcb, 0xee, 0xdd, 0xfb, 0x54,
+ 0x46, 0xca, 0xec, 0xf4, 0x74, 0x43, 0x61, 0x63, 0x44, 0x46, 0x32, 0xdf,
+ 0xe1, 0x79, 0xae, 0xdd, 0xfb, 0x54, 0x53, 0x6b, 0x9e, 0x4b, 0x2f, 0xbb,
+ 0x77, 0xed, 0x51, 0x50, 0x28, 0x67, 0x8d, 0xa1, 0x6b, 0xd9, 0xd1, 0x8b,
+ 0x2c, 0x2f, 0x0f, 0x03, 0xc4, 0x57, 0xf8, 0x5e, 0x6b, 0xb7, 0x7e, 0xd5,
+ 0x15, 0x32, 0xe0, 0x32, 0xcb, 0xc1, 0x6d, 0x2c, 0xbe, 0xed, 0xdf, 0xb5,
+ 0x45, 0x60, 0xbe, 0xfc, 0x75, 0x25, 0x95, 0xa3, 0xd3, 0x39, 0x85, 0xf9,
+ 0x8c, 0x18, 0x74, 0xb2, 0xd3, 0xac, 0xb8, 0x49, 0x2c, 0xbc, 0xe5, 0xda,
+ 0xca, 0x83, 0xc6, 0x00, 0x97, 0xc6, 0x2e, 0xe1, 0x2c, 0xb8, 0x66, 0xac,
+ 0xbd, 0x00, 0x65, 0x97, 0x1f, 0x8b, 0x2f, 0xcf, 0x2f, 0xb4, 0xeb, 0x2f,
+ 0xdc, 0xe1, 0x60, 0x16, 0x53, 0x1e, 0x7b, 0x94, 0x5c, 0xdb, 0x6b, 0x2d,
+ 0xa5, 0x97, 0x9b, 0x6d, 0xe0, 0xd5, 0x04, 0x66, 0xff, 0x0b, 0xcd, 0x76,
+ 0xef, 0xda, 0xa2, 0x3f, 0x5c, 0x1e, 0x2c, 0xbc, 0x50, 0x35, 0x95, 0x08,
+ 0xa8, 0x91, 0x98, 0xd0, 0xd8, 0x5e, 0xfb, 0x30, 0xa4, 0xb2, 0xd0, 0xb2,
+ 0xd3, 0xac, 0xbf, 0x37, 0x3e, 0x17, 0x59, 0x50, 0x6e, 0x46, 0x25, 0x52,
+ 0x3e, 0x9c, 0x49, 0xbd, 0x30, 0x74, 0xb2, 0xe1, 0x92, 0xca, 0x83, 0x69,
+ 0xe1, 0xeb, 0xfb, 0xa9, 0x3c, 0x98, 0x96, 0x5e, 0x82, 0x99, 0x65, 0xf4,
+ 0xd2, 0x8e, 0x96, 0x5f, 0x47, 0x1a, 0x65, 0x95, 0x88, 0x8f, 0x34, 0xb5,
+ 0x87, 0x34, 0x49, 0x78, 0xd7, 0xfa, 0xcb, 0x9f, 0xeb, 0x2e, 0x3e, 0xea,
+ 0xcb, 0xbf, 0xf5, 0x96, 0x16, 0x2a, 0x2e, 0xa6, 0x8c, 0x5b, 0x1b, 0xfb,
+ 0x22, 0xe9, 0xbd, 0x8b, 0xb7, 0x05, 0xb4, 0x30, 0x71, 0xbf, 0x33, 0x3c,
+ 0x3c, 0x80, 0x76, 0x50, 0x89, 0xe2, 0xaf, 0xe1, 0x5e, 0x13, 0xcd, 0xb1,
+ 0xd1, 0x05, 0xb7, 0x46, 0xaf, 0xff, 0x0b, 0x3b, 0xc8, 0x5e, 0x6b, 0xb7,
+ 0x7e, 0xd5, 0x13, 0x7a, 0xff, 0xe3, 0xbc, 0x85, 0xe6, 0xbb, 0x77, 0xed,
+ 0x51, 0x3f, 0x2f, 0x6d, 0x5b, 0x5e, 0xd4, 0xb2, 0xff, 0xff, 0xbc, 0x1f,
+ 0x93, 0x9b, 0xd7, 0xf5, 0x19, 0xd3, 0xb7, 0x4e, 0xb2, 0xdb, 0x56, 0xd4,
+ 0x89, 0x4c, 0x2c, 0xbf, 0x9c, 0xf0, 0x78, 0x11, 0x65, 0xff, 0xb6, 0xb1,
+ 0x4b, 0xcb, 0xcd, 0xbf, 0x27, 0x59, 0x73, 0xc9, 0x65, 0xcc, 0x75, 0x95,
+ 0xb5, 0xa3, 0x57, 0x6a, 0x32, 0x14, 0x96, 0xed, 0x24, 0xad, 0x0b, 0x5f,
+ 0xfb, 0x6a, 0x81, 0xe6, 0xf2, 0x08, 0x90, 0xb2, 0xfb, 0x6a, 0x9f, 0x80,
+ 0x59, 0x7e, 0x79, 0xfe, 0x13, 0x56, 0x5f, 0xbb, 0xd1, 0x44, 0x96, 0x50,
+ 0xab, 0x3f, 0xbd, 0x14, 0xb9, 0x55, 0xc2, 0x1d, 0x65, 0xfd, 0x86, 0xb7,
+ 0xca, 0x16, 0x57, 0x67, 0x89, 0xb6, 0x31, 0x74, 0x8e, 0xb2, 0xfe, 0xe3,
+ 0x9f, 0x51, 0xc5, 0x97, 0xed, 0x47, 0x83, 0x0b, 0x2f, 0xde, 0xcf, 0xc0,
+ 0xd6, 0x56, 0xd6, 0x9f, 0x86, 0xd5, 0x0c, 0x01, 0x4b, 0xc6, 0xd3, 0x26,
+ 0x15, 0x62, 0xec, 0x5a, 0xe4, 0xf7, 0xed, 0xaa, 0x3f, 0x03, 0x59, 0x7b,
+ 0x98, 0x4b, 0x2f, 0xe1, 0x46, 0xd0, 0x78, 0xcf, 0xac, 0xbf, 0xc2, 0xaf,
+ 0x6a, 0x6d, 0xbf, 0x30, 0xad, 0x65, 0xc5, 0xda, 0xcb, 0xee, 0x4c, 0x7e,
+ 0x2c, 0xbf, 0x17, 0xfc, 0xc7, 0x59, 0x7d, 0x30, 0x5c, 0x45, 0x95, 0x07,
+ 0x96, 0xe4, 0xf7, 0x8f, 0x1c, 0x59, 0x77, 0x7d, 0xac, 0xbf, 0xdd, 0xf9,
+ 0xbf, 0x98, 0x75, 0x97, 0x6f, 0xed, 0x71, 0x81, 0x2b, 0x6b, 0x4f, 0xdc,
+ 0x50, 0x59, 0xb4, 0xc6, 0xc5, 0x59, 0xb4, 0x22, 0xb0, 0xbc, 0xcd, 0xfa,
+ 0x20, 0x00, 0xe7, 0x06, 0x7e, 0x67, 0x7e, 0xda, 0xc5, 0x3b, 0x79, 0xd2,
+ 0xcb, 0xfb, 0x6a, 0x79, 0xfc, 0xdb, 0x8b, 0x2f, 0xfb, 0x67, 0xfd, 0x87,
+ 0xcd, 0x62, 0xcb, 0xf8, 0x55, 0x6d, 0x7b, 0x58, 0xa7, 0x90, 0xb2, 0xfd,
+ 0xb4, 0x1a, 0x6e, 0x6e, 0x2c, 0xbf, 0xbe, 0xc4, 0x66, 0x12, 0xcb, 0xb7,
+ 0xf6, 0xb8, 0xc0, 0x56, 0xf2, 0xcb, 0x80, 0x05, 0x95, 0xb5, 0x27, 0x28,
+ 0x29, 0x35, 0x14, 0x1b, 0x6d, 0x23, 0xa1, 0x56, 0x85, 0x86, 0x5f, 0x2c,
+ 0x09, 0x38, 0x82, 0x37, 0xd2, 0x71, 0xb2, 0xcb, 0xfb, 0xcd, 0xf2, 0x89,
+ 0x96, 0x5c, 0xf8, 0xb2, 0xbb, 0x3c, 0x2d, 0x16, 0xdf, 0x38, 0xf0, 0xeb,
+ 0x2f, 0x77, 0x04, 0xb2, 0xff, 0xdb, 0xe3, 0xcd, 0x13, 0x4d, 0x1d, 0xac,
+ 0xa1, 0x4a, 0x60, 0xbb, 0x43, 0x18, 0xa8, 0x47, 0x84, 0x2c, 0x39, 0x7c,
+ 0x28, 0x9c, 0xfc, 0x59, 0x7f, 0x64, 0xd0, 0x4d, 0xd2, 0xcb, 0xf8, 0x98,
+ 0xdf, 0x3c, 0x96, 0x5f, 0xff, 0x3f, 0xe0, 0xbb, 0x63, 0x8c, 0x2f, 0xa9,
+ 0x2c, 0xa3, 0x9f, 0xe1, 0x16, 0xdf, 0x8c, 0xff, 0xe0, 0xeb, 0x2b, 0x68,
+ 0x3c, 0xa9, 0xc8, 0x6f, 0xf9, 0xfc, 0xdb, 0xc5, 0x98, 0x61, 0x89, 0x2f,
+ 0xf7, 0x9f, 0xff, 0x77, 0x31, 0x65, 0xd0, 0x35, 0x97, 0xec, 0xed, 0xf8,
+ 0xcb, 0x28, 0x50, 0x9f, 0x9e, 0xd2, 0x28, 0x15, 0x21, 0xe6, 0x2a, 0x8a,
+ 0x05, 0x5a, 0x07, 0x46, 0x7e, 0x16, 0xbf, 0xff, 0xde, 0x6e, 0x44, 0xb3,
+ 0xcd, 0xaf, 0x3e, 0x07, 0x3c, 0xb2, 0xff, 0xfb, 0x50, 0xdf, 0xf6, 0x0d,
+ 0xb9, 0x84, 0x05, 0x96, 0x14, 0xba, 0x2a, 0xf8, 0xbd, 0x77, 0x21, 0x65,
+ 0x6d, 0x67, 0x85, 0x22, 0xcb, 0xfb, 0x72, 0x34, 0xef, 0x25, 0x97, 0xef,
+ 0x33, 0x80, 0x55, 0xac, 0xbd, 0x1d, 0x49, 0x65, 0x6d, 0x48, 0xa0, 0xda,
+ 0x64, 0xff, 0x2f, 0xdd, 0x2d, 0xbf, 0xf6, 0xd1, 0xb5, 0x4c, 0x50, 0x3c,
+ 0xeb, 0xeb, 0x2f, 0xb0, 0x6f, 0x25, 0x97, 0xfb, 0x04, 0x3e, 0x16, 0x6e,
+ 0x2c, 0xbd, 0xa0, 0xee, 0xac, 0xad, 0xa1, 0x18, 0x02, 0xa2, 0x50, 0xaa,
+ 0x21, 0x09, 0xad, 0xff, 0xfb, 0x6a, 0x27, 0xfc, 0x61, 0x48, 0xf1, 0x84,
+ 0x35, 0x97, 0xc5, 0x8c, 0x05, 0x97, 0xdb, 0x48, 0x06, 0xc2, 0xcb, 0xf3,
+ 0x68, 0x00, 0x85, 0x97, 0x34, 0xeb, 0x2b, 0x6b, 0x46, 0xe8, 0xa5, 0x58,
+ 0x50, 0x41, 0x22, 0x9f, 0x93, 0xde, 0x7c, 0xf2, 0xcb, 0xfe, 0x7f, 0xf5,
+ 0x2f, 0xe6, 0x8d, 0x59, 0x73, 0x01, 0x65, 0x6d, 0x47, 0xd8, 0x2a, 0xc6,
+ 0xc8, 0xee, 0xf8, 0x54, 0xda, 0x05, 0x7b, 0x52, 0xcb, 0xff, 0x44, 0x44,
+ 0x44, 0x47, 0x5c, 0x59, 0x7a, 0x68, 0xfa, 0xcb, 0xa2, 0x20, 0xf6, 0x26,
+ 0x3b, 0xbf, 0xfd, 0xe8, 0x9b, 0xae, 0x67, 0x5b, 0x91, 0x04, 0xb2, 0xf3,
+ 0x75, 0x8b, 0x2f, 0xda, 0x69, 0xdc, 0xe9, 0x2e, 0x30, 0xc4, 0x95, 0x87,
+ 0x82, 0x61, 0x45, 0x82, 0x90, 0x59, 0xa2, 0xbd, 0xec, 0xed, 0x65, 0x42,
+ 0x67, 0x3e, 0x2c, 0x02, 0x77, 0x1f, 0xc4, 0x23, 0xbf, 0x07, 0x6e, 0x03,
+ 0xd2, 0xcb, 0xff, 0x47, 0xb0, 0x18, 0x3f, 0x3c, 0x96, 0x5f, 0x39, 0x46,
+ 0xea, 0xcb, 0xfa, 0x50, 0x78, 0xd6, 0x96, 0x56, 0x22, 0xe7, 0x45, 0x8e,
+ 0x7a, 0x12, 0x3b, 0xff, 0xfb, 0xec, 0x7c, 0x2f, 0xf2, 0x0d, 0xe0, 0x47,
+ 0xe6, 0x59, 0x7f, 0xba, 0x96, 0xce, 0x30, 0x74, 0xb2, 0xff, 0xf3, 0xb1,
+ 0x60, 0x36, 0x46, 0xa7, 0x8f, 0xac, 0xbf, 0xf6, 0xeb, 0x6e, 0x7a, 0x68,
+ 0xdc, 0x73, 0xac, 0xbf, 0xf6, 0x1e, 0x39, 0xcc, 0x96, 0xde, 0x2c, 0xa1,
+ 0xa3, 0x4b, 0xc9, 0x44, 0x91, 0x7e, 0x3b, 0x9f, 0x06, 0xb2, 0xff, 0xbf,
+ 0xdf, 0x98, 0x8a, 0x3a, 0x59, 0x50, 0x7c, 0x0e, 0x4f, 0x7f, 0xe8, 0x9e,
+ 0x38, 0xdb, 0x79, 0xa8, 0x59, 0x5b, 0x15, 0x29, 0xe2, 0xdb, 0x46, 0x13,
+ 0xe8, 0x47, 0x91, 0x05, 0xff, 0x14, 0x6c, 0x9a, 0x51, 0xa9, 0xd6, 0x5f,
+ 0xec, 0x1b, 0x6f, 0xe0, 0x3b, 0x59, 0x7f, 0xff, 0xec, 0xde, 0xdf, 0x96,
+ 0x03, 0x85, 0x80, 0xd4, 0x4e, 0xfa, 0xed, 0x65, 0xd1, 0x27, 0x45, 0x27,
+ 0x0d, 0xaf, 0xef, 0xf3, 0x32, 0x78, 0x59, 0x47, 0x4c, 0xeb, 0xd0, 0xe0,
+ 0x22, 0xdb, 0xee, 0x0f, 0xe1, 0x59, 0x7f, 0xff, 0xf6, 0xf8, 0xd6, 0x0c,
+ 0x9f, 0x46, 0xbf, 0xc3, 0xf6, 0xff, 0x3c, 0xcb, 0x2f, 0xf6, 0x82, 0x41,
+ 0xf8, 0x7e, 0xb2, 0xf7, 0xa0, 0x96, 0x53, 0x1e, 0x7f, 0xcd, 0x2f, 0xb4,
+ 0x27, 0xf8, 0xb2, 0xa0, 0xf1, 0x70, 0x86, 0xff, 0x44, 0xc5, 0x07, 0x0c,
+ 0xeb, 0x2f, 0xcf, 0xc6, 0x38, 0x56, 0x51, 0xcf, 0x6f, 0xc6, 0x97, 0x1a,
+ 0x62, 0xcb, 0xff, 0xf4, 0xa0, 0x8a, 0x27, 0x31, 0xe7, 0xf3, 0x41, 0x2c,
+ 0xa8, 0x54, 0xd3, 0xd9, 0xab, 0x11, 0xfa, 0x30, 0x77, 0x7b, 0xf9, 0x10,
+ 0x46, 0x6f, 0x9a, 0x77, 0x3a, 0xcb, 0xc4, 0xd0, 0xb2, 0xfd, 0x02, 0x1f,
+ 0xcc, 0xb2, 0x86, 0x7c, 0x9a, 0x22, 0x21, 0xab, 0xed, 0xf2, 0x3c, 0x2c,
+ 0xbf, 0x3c, 0xf0, 0xfd, 0xac, 0xbe, 0x8e, 0x41, 0xd6, 0x5f, 0xe8, 0x9c,
+ 0x83, 0x9d, 0x7d, 0x65, 0x84, 0xd8, 0x7a, 0xbe, 0x21, 0xac, 0x46, 0x67,
+ 0x89, 0x1d, 0xf6, 0xfe, 0x97, 0x3f, 0x84, 0x6a, 0xcb, 0xee, 0x3c, 0xb7,
+ 0x16, 0x5f, 0xfa, 0x5c, 0x89, 0x40, 0x39, 0x9b, 0xd6, 0x5e, 0x81, 0xb2,
+ 0xcb, 0xfd, 0xa1, 0x3f, 0xc9, 0xf0, 0xc5, 0x97, 0xff, 0x47, 0x79, 0xac,
+ 0xf3, 0x6b, 0xce, 0xb2, 0xff, 0xf3, 0x73, 0x07, 0xa8, 0x0f, 0xc9, 0xb7,
+ 0xac, 0xb9, 0xcc, 0x59, 0x5d, 0x9f, 0x09, 0x89, 0x57, 0xff, 0x46, 0xa5,
+ 0xdf, 0x9a, 0x62, 0x73, 0x16, 0x5f, 0xfd, 0xa7, 0x9c, 0x7e, 0x8e, 0x7c,
+ 0x3e, 0x59, 0x5c, 0x44, 0x67, 0xd1, 0xaf, 0x7d, 0xa6, 0x59, 0x63, 0xc9,
+ 0x3e, 0x6c, 0x1b, 0xd1, 0xbf, 0xa1, 0x49, 0xc8, 0x58, 0x7c, 0x8e, 0xfa,
+ 0x0f, 0x1e, 0x59, 0x7e, 0x83, 0x07, 0x87, 0x59, 0x66, 0x91, 0xe4, 0x88,
+ 0x43, 0x50, 0xab, 0xfb, 0x25, 0x13, 0x7a, 0x16, 0x17, 0xf3, 0x81, 0xfb,
+ 0x7d, 0x2c, 0xbf, 0xfe, 0x09, 0x14, 0x1a, 0x7f, 0x47, 0x5f, 0x8f, 0x2c,
+ 0xbf, 0xff, 0x8b, 0xfc, 0x0c, 0x7a, 0x0e, 0x58, 0x03, 0xc4, 0x96, 0x5e,
+ 0x1b, 0xf9, 0x65, 0xff, 0x47, 0xa3, 0xa9, 0x4a, 0x27, 0x59, 0x7d, 0xdf,
+ 0x9b, 0x4b, 0x2f, 0xed, 0xc2, 0xc9, 0xf0, 0xc5, 0x95, 0x09, 0x81, 0xe2,
+ 0xce, 0x87, 0x1c, 0xe8, 0x24, 0x77, 0xff, 0xbc, 0xc7, 0x1c, 0x6c, 0xdb,
+ 0x0f, 0x9b, 0x4b, 0x2f, 0xef, 0xc7, 0x8a, 0x24, 0xb2, 0xb6, 0x1f, 0xdb,
+ 0x27, 0xd2, 0xcb, 0xf8, 0x9c, 0xd6, 0xd4, 0x48, 0xd7, 0x78, 0x8e, 0xf9,
+ 0xff, 0xa8, 0x59, 0x7e, 0x8d, 0x69, 0xe6, 0x59, 0x73, 0x74, 0xb2, 0xff,
+ 0x00, 0x38, 0x03, 0xbc, 0x96, 0x5d, 0x90, 0xb2, 0xa4, 0x7b, 0xfd, 0x0b,
+ 0x9c, 0xce, 0xa7, 0x45, 0xbb, 0xc2, 0x1e, 0xff, 0xff, 0x79, 0xba, 0x82,
+ 0x8e, 0x0f, 0xd1, 0xc6, 0x2e, 0xa4, 0xb2, 0xff, 0xff, 0xbc, 0xe3, 0xf3,
+ 0x13, 0xfe, 0x26, 0x63, 0x58, 0xb3, 0x7a, 0xcb, 0xfe, 0x6f, 0xe6, 0xb4,
+ 0x19, 0xf7, 0xac, 0xbf, 0xee, 0x67, 0xc7, 0x98, 0x0e, 0x2c, 0xaf, 0x1f,
+ 0xa7, 0xcf, 0x2f, 0xf9, 0xbf, 0x9a, 0xd0, 0x67, 0xde, 0xb2, 0xe0, 0x96,
+ 0xc3, 0xde, 0xf1, 0x15, 0x42, 0x78, 0xf8, 0xc1, 0xc8, 0xce, 0x2a, 0x4c,
+ 0x90, 0xe1, 0xcb, 0x23, 0xc3, 0xce, 0xcb, 0x75, 0x1a, 0x9f, 0xa1, 0xe2,
+ 0x04, 0x22, 0x86, 0xc7, 0x23, 0xef, 0xbe, 0x3b, 0x0e, 0x16, 0x5f, 0xcd,
+ 0xed, 0x69, 0xa7, 0x59, 0x50, 0x79, 0xfe, 0x21, 0xb8, 0xcf, 0xac, 0xbf,
+ 0xf9, 0x9b, 0xd3, 0x67, 0xe3, 0xf0, 0x35, 0x97, 0xc2, 0x1a, 0x21, 0xab,
+ 0x2d, 0x0b, 0x2f, 0xff, 0xa3, 0xa9, 0x39, 0x03, 0x60, 0x1b, 0x4c, 0x6a,
+ 0xca, 0x84, 0x72, 0x4c, 0x30, 0x62, 0x1e, 0xd9, 0x3e, 0xe8, 0x85, 0xfe,
+ 0x8e, 0xa6, 0xf4, 0x11, 0xab, 0x2e, 0x29, 0x96, 0x5e, 0xe7, 0x99, 0x65,
+ 0x1c, 0xd9, 0xfc, 0x5e, 0xfa, 0x73, 0xb4, 0x96, 0x5f, 0x40, 0x04, 0x3a,
+ 0xcb, 0xe2, 0x0b, 0xc9, 0x65, 0x76, 0x78, 0x9c, 0x23, 0xbf, 0xa0, 0xe2,
+ 0xc0, 0x08, 0x59, 0x78, 0x57, 0x1f, 0x59, 0x7f, 0x1e, 0x30, 0xbf, 0xc5,
+ 0x95, 0xe3, 0xfb, 0x09, 0x7e, 0xe9, 0x05, 0x42, 0x66, 0xf8, 0xce, 0xd0,
+ 0x9e, 0xbf, 0x37, 0xbf, 0x9d, 0xac, 0xbd, 0x84, 0x05, 0x95, 0x31, 0xe1,
+ 0xee, 0x94, 0x54, 0x2a, 0x5c, 0xc6, 0x8d, 0x46, 0xb0, 0xee, 0xd7, 0xf8,
+ 0x62, 0x46, 0xe7, 0x83, 0xc5, 0x97, 0xed, 0xd6, 0x3e, 0x7d, 0x65, 0xfb,
+ 0xf9, 0xf2, 0x85, 0x95, 0xd2, 0x22, 0x0e, 0x70, 0x45, 0x57, 0x82, 0xfc,
+ 0x59, 0x74, 0x18, 0xb2, 0xb4, 0x6c, 0xf8, 0x39, 0x73, 0xf9, 0x65, 0xd3,
+ 0x42, 0xcb, 0xa3, 0xeb, 0x2a, 0x0d, 0x69, 0xa2, 0xf7, 0xc3, 0xc2, 0x92,
+ 0xcb, 0xf6, 0x34, 0xbd, 0x0b, 0x2e, 0x9b, 0xec, 0x78, 0xfe, 0x21, 0xbf,
+ 0xff, 0x0f, 0xd1, 0xa6, 0x04, 0x09, 0x13, 0x14, 0x1d, 0x65, 0xfe, 0x36,
+ 0x0b, 0xfc, 0x7f, 0x2c, 0xa8, 0x45, 0xb3, 0x17, 0x3a, 0xad, 0xf8, 0xb1,
+ 0xca, 0x75, 0x95, 0x0a, 0x8e, 0x31, 0x8d, 0x88, 0x5d, 0x0c, 0xa3, 0x1e,
+ 0xe1, 0x6d, 0xe7, 0xcd, 0x2c, 0xbf, 0xec, 0xe4, 0x0f, 0x90, 0xc3, 0x59,
+ 0x7f, 0x44, 0xfa, 0x8c, 0x1a, 0xcb, 0xff, 0x61, 0xf9, 0xe8, 0xeb, 0xf1,
+ 0xe5, 0x97, 0xf7, 0xa3, 0xff, 0x83, 0xac, 0xbf, 0xff, 0xb5, 0x83, 0xe1,
+ 0x07, 0x24, 0x17, 0x1f, 0x33, 0x4b, 0x28, 0x68, 0x87, 0x62, 0xda, 0xd2,
+ 0x6c, 0xe7, 0x1b, 0xf1, 0xbf, 0xcb, 0x44, 0x86, 0x35, 0xf1, 0x41, 0xf8,
+ 0xb2, 0xf1, 0xdf, 0xa5, 0x9f, 0x34, 0x37, 0x7f, 0xb5, 0x97, 0xcd, 0xa0,
+ 0x71, 0x65, 0x61, 0xf3, 0xe8, 0xb7, 0xe3, 0x17, 0xf1, 0x46, 0xc0, 0x02,
+ 0x16, 0x5f, 0x38, 0x22, 0x4b, 0x2f, 0xe9, 0x78, 0x1b, 0xc5, 0x3b, 0x52,
+ 0xcb, 0xf9, 0xca, 0x3d, 0xe8, 0x59, 0x7f, 0xa3, 0x4f, 0x12, 0x89, 0x2c,
+ 0xb8, 0x24, 0xb2, 0xec, 0xed, 0x65, 0xd1, 0x2f, 0x1a, 0xdf, 0x8b, 0x57,
+ 0x48, 0xef, 0x98, 0xeb, 0x45, 0x64, 0xbd, 0x7f, 0xfc, 0x59, 0xbf, 0xb7,
+ 0xd4, 0xef, 0xf7, 0xe8, 0x0b, 0x2f, 0xf6, 0x0d, 0xb8, 0x63, 0xe9, 0x65,
+ 0x42, 0xb0, 0x91, 0xc3, 0x67, 0x0b, 0xbb, 0x2e, 0x68, 0xc4, 0x1c, 0xfb,
+ 0xea, 0x77, 0xf8, 0x9e, 0x7e, 0xa5, 0x1b, 0xab, 0x2f, 0xf7, 0x3c, 0xe2,
+ 0x7a, 0x24, 0xb2, 0xa7, 0x3e, 0xbe, 0x8d, 0xee, 0xc9, 0x96, 0x5f, 0xf9,
+ 0xfa, 0xf4, 0x30, 0x1f, 0xe1, 0x59, 0x7f, 0xff, 0xa1, 0xa4, 0xfc, 0xe4,
+ 0x61, 0x44, 0xb0, 0xef, 0xd2, 0xcb, 0x61, 0xd1, 0x37, 0xf3, 0xea, 0xc4,
+ 0x6d, 0x72, 0x16, 0x57, 0xec, 0x9f, 0x3a, 0x92, 0xcb, 0xff, 0xef, 0x41,
+ 0xdb, 0x4d, 0xbb, 0x02, 0x4f, 0x86, 0x2c, 0xbf, 0xf6, 0x0e, 0x04, 0x39,
+ 0x47, 0x52, 0x59, 0x7f, 0x60, 0x7b, 0x13, 0x3a, 0x59, 0x43, 0x47, 0x64,
+ 0xc5, 0x3c, 0x54, 0xde, 0x7f, 0x7f, 0xe6, 0xd4, 0x70, 0x42, 0x28, 0xd2,
+ 0xcb, 0xfe, 0x89, 0x13, 0xfe, 0x4d, 0xbd, 0x65, 0xe1, 0x20, 0x0b, 0x2b,
+ 0xc7, 0xad, 0xc3, 0x9b, 0x6e, 0x2c, 0xbf, 0xec, 0x98, 0xa2, 0x7e, 0x47,
+ 0x6b, 0x2e, 0x96, 0x2c, 0xaf, 0x1e, 0x87, 0xce, 0xae, 0xe6, 0x2c, 0xbf,
+ 0x44, 0xcd, 0x1c, 0x59, 0x7f, 0xf7, 0x23, 0x5d, 0xfc, 0xb2, 0x77, 0x25,
+ 0x97, 0xfe, 0xff, 0xb3, 0x7b, 0x90, 0xf0, 0x0b, 0x2d, 0xe5, 0x95, 0x0a,
+ 0x93, 0x27, 0x40, 0xc8, 0x49, 0xb1, 0x13, 0xb2, 0x00, 0x88, 0x85, 0xbe,
+ 0x4e, 0x14, 0x43, 0x0f, 0xee, 0xf9, 0xd6, 0x5f, 0xcf, 0x9a, 0x00, 0x21,
+ 0x65, 0xfb, 0x3c, 0xcf, 0x25, 0x97, 0xdc, 0xe8, 0xb4, 0xb2, 0xff, 0x6b,
+ 0x3c, 0xc5, 0x07, 0x59, 0x7f, 0xfd, 0x8c, 0x59, 0x34, 0x4e, 0xf3, 0x9d,
+ 0xa7, 0x59, 0x50, 0x88, 0x1e, 0x18, 0xd4, 0x26, 0x5e, 0xe2, 0xfc, 0x2c,
+ 0xf9, 0x30, 0x61, 0x49, 0x7f, 0xdf, 0x7e, 0x67, 0xbc, 0xc7, 0x59, 0x77,
+ 0xb8, 0xb2, 0xff, 0xb3, 0x98, 0xc3, 0x76, 0x9d, 0x65, 0xff, 0x89, 0xc1,
+ 0x85, 0xfe, 0x3c, 0x96, 0x54, 0x23, 0x08, 0xd3, 0x8d, 0x0b, 0xfc, 0xde,
+ 0xfc, 0x51, 0x3c, 0x4e, 0xb2, 0x86, 0x7c, 0xb3, 0x1e, 0xdf, 0xc3, 0x87,
+ 0xd0, 0x02, 0xb2, 0xec, 0xf2, 0xca, 0x9c, 0xf0, 0xf7, 0x96, 0xdf, 0xd8,
+ 0x30, 0x31, 0x7d, 0x65, 0xff, 0xf6, 0x31, 0xd8, 0x0f, 0xf2, 0xc9, 0xf5,
+ 0x0b, 0x2f, 0x7b, 0xec, 0xb2, 0xfe, 0xdc, 0xcd, 0xe5, 0x92, 0x59, 0x73,
+ 0x4c, 0xb2, 0x98, 0xf2, 0x3e, 0x63, 0x7b, 0xde, 0x85, 0x97, 0xf1, 0xaf,
+ 0x2e, 0x30, 0xd6, 0x56, 0x1e, 0x53, 0x0e, 0x54, 0x27, 0xe7, 0x8c, 0xda,
+ 0x25, 0xf1, 0x63, 0xa6, 0xf1, 0x93, 0xed, 0x77, 0x06, 0x4b, 0x2f, 0xef,
+ 0x36, 0xb5, 0x9f, 0x59, 0x7f, 0xc4, 0xdb, 0xe0, 0x8b, 0x3e, 0xb2, 0xa7,
+ 0x3f, 0xbe, 0xc5, 0xfe, 0x5b, 0x7f, 0x9b, 0x9e, 0x73, 0xc6, 0xe2, 0xcb,
+ 0xff, 0xd3, 0x49, 0xb7, 0xc6, 0xb1, 0xa4, 0x1d, 0x2c, 0xad, 0x22, 0x05,
+ 0xcd, 0x6e, 0x79, 0x2c, 0xbf, 0x17, 0xf6, 0xe0, 0xeb, 0x29, 0xcf, 0x00,
+ 0x22, 0xd7, 0xdb, 0x8c, 0x67, 0x6b, 0x2e, 0x69, 0x2c, 0xa8, 0x37, 0xbf,
+ 0x27, 0xbf, 0xec, 0x3f, 0x1b, 0x6f, 0x35, 0x0b, 0x2b, 0x69, 0x3a, 0xdf,
+ 0x48, 0x8f, 0x1e, 0x78, 0xc1, 0x25, 0x2a, 0x38, 0x72, 0xfe, 0x72, 0x19,
+ 0xdd, 0xc3, 0xeb, 0xa2, 0xe6, 0xa4, 0x9e, 0x6e, 0x43, 0xb6, 0x68, 0xc1,
+ 0x75, 0x2a, 0xb4, 0xf2, 0xc0, 0xbd, 0x39, 0x94, 0xf0, 0xd9, 0x04, 0x3f,
+ 0x8a, 0x5a, 0xff, 0x23, 0xbe, 0xfc, 0xb6, 0x80, 0xc3, 0x77, 0x7c, 0x2c,
+ 0xb6, 0xd8, 0x84, 0x5e, 0xdd, 0x20, 0xb3, 0x2c, 0xbb, 0x60, 0x16, 0x56,
+ 0xc3, 0x53, 0xc1, 0x0b, 0x8d, 0xfa, 0xcb, 0xff, 0xfe, 0x15, 0x05, 0x11,
+ 0x82, 0xab, 0x42, 0x8d, 0xa7, 0xbf, 0x70, 0x55, 0x87, 0x66, 0xcf, 0x6d,
+ 0xac, 0xbf, 0xe9, 0x40, 0x39, 0x31, 0x40, 0xd6, 0x5c, 0xd0, 0xb2, 0xf4,
+ 0xc2, 0x1d, 0x65, 0xff, 0x67, 0xf9, 0x9f, 0xf6, 0x01, 0x65, 0xfe, 0xd9,
+ 0x1b, 0x0e, 0xc5, 0xf5, 0x97, 0xf9, 0x8d, 0x72, 0xfe, 0x12, 0xcb, 0xfc,
+ 0xe6, 0xb7, 0x38, 0xec, 0xb2, 0xb1, 0x33, 0xe3, 0x4e, 0x5c, 0x54, 0x87,
+ 0xf8, 0x71, 0xf3, 0x6d, 0xe6, 0x37, 0x39, 0x2c, 0xad, 0x1f, 0xd1, 0xd9,
+ 0x6f, 0xa3, 0xf8, 0x75, 0x97, 0xef, 0xc1, 0x30, 0x16, 0x5d, 0xd7, 0x4b,
+ 0x2f, 0xda, 0x0e, 0xf0, 0x18, 0xb2, 0xe2, 0xe2, 0xcb, 0xfb, 0x0c, 0x70,
+ 0x1f, 0x16, 0x5f, 0xc5, 0x9f, 0x0b, 0x98, 0xb2, 0xb6, 0x23, 0xf3, 0x08,
+ 0x7a, 0x26, 0xf0, 0xc8, 0x0b, 0x08, 0x5b, 0x79, 0x6d, 0xff, 0xa0, 0xed,
+ 0xd7, 0x03, 0x30, 0x4d, 0x59, 0x7e, 0x2f, 0xfb, 0x24, 0xb2, 0xee, 0x62,
+ 0xca, 0x63, 0x7a, 0xe4, 0xf7, 0xf8, 0xa0, 0xcd, 0xbc, 0xd4, 0x2c, 0xbf,
+ 0xf0, 0x5b, 0xde, 0xcd, 0x69, 0x8e, 0xb2, 0xf8, 0x87, 0x1b, 0xab, 0x2c,
+ 0x66, 0xc4, 0xcd, 0x64, 0xfe, 0x31, 0xf3, 0x9a, 0xb9, 0xf5, 0xf4, 0xf1,
+ 0xfe, 0x2c, 0xbd, 0x00, 0xe2, 0xca, 0xd1, 0xbf, 0x22, 0x3b, 0xe7, 0xd3,
+ 0xc9, 0x65, 0xb5, 0x87, 0x82, 0x44, 0x17, 0x8c, 0x30, 0xc5, 0x97, 0xd3,
+ 0x93, 0x42, 0x41, 0x66, 0x82, 0xf0, 0x4b, 0xeb, 0x2f, 0xe7, 0x29, 0x0e,
+ 0x27, 0x59, 0x6d, 0xcc, 0x3c, 0x9f, 0x0e, 0x5f, 0x3f, 0xe0, 0x6b, 0x2f,
+ 0x61, 0x76, 0xb2, 0xee, 0xa4, 0xb2, 0xff, 0x1b, 0x1f, 0xe7, 0x9c, 0x2b,
+ 0x2f, 0xcd, 0x3e, 0x75, 0xf5, 0x97, 0xf9, 0xfc, 0x59, 0xbd, 0xfb, 0x59,
+ 0x60, 0x2c, 0xb7, 0x6b, 0x2b, 0x0d, 0x1b, 0x08, 0xd4, 0x23, 0xac, 0xd1,
+ 0x83, 0x9a, 0x11, 0x4f, 0xd5, 0xef, 0xfa, 0x5d, 0x71, 0xb5, 0xdf, 0xb1,
+ 0x65, 0xf8, 0xd7, 0xe6, 0xf9, 0x2c, 0xae, 0x91, 0x5f, 0xa4, 0x9f, 0x9d,
+ 0xdf, 0x9c, 0xa4, 0xc7, 0x59, 0x7b, 0x03, 0xb6, 0xb2, 0xb6, 0x32, 0x53,
+ 0x45, 0x24, 0x7b, 0x4c, 0x62, 0x25, 0x26, 0x0e, 0x31, 0xec, 0x8e, 0x71,
+ 0xa1, 0xa7, 0xe4, 0x67, 0x7c, 0x22, 0xae, 0x10, 0x86, 0x3b, 0x6d, 0xe6,
+ 0x3b, 0x64, 0xd7, 0xb6, 0xad, 0xa5, 0xb5, 0xac, 0xbf, 0xef, 0x3c, 0xc5,
+ 0x19, 0xa9, 0x2c, 0xbf, 0xf3, 0x90, 0x93, 0x71, 0x8b, 0xa9, 0x2c, 0xbf,
+ 0xf1, 0x99, 0xc2, 0x68, 0xd6, 0x4e, 0xb2, 0xb7, 0x11, 0x6c, 0x13, 0x8d,
+ 0xe8, 0x17, 0xc1, 0x9e, 0x26, 0x59, 0x7f, 0xff, 0xff, 0xdb, 0x3d, 0x9d,
+ 0x4b, 0xc7, 0xd9, 0xdf, 0x83, 0xff, 0xe1, 0x7b, 0x3f, 0x03, 0xd9, 0xb3,
+ 0xdb, 0x6b, 0x2a, 0x11, 0x8f, 0xb8, 0x49, 0x7e, 0x28, 0xd3, 0xf1, 0x65,
+ 0xff, 0x0f, 0x02, 0x2b, 0x6f, 0x39, 0xd6, 0x5f, 0xa0, 0xe5, 0x93, 0x2c,
+ 0xc3, 0x79, 0x7e, 0xe6, 0x79, 0xbc, 0xb2, 0xf6, 0xa3, 0x7a, 0xcb, 0xdb,
+ 0xf0, 0x6b, 0x2f, 0xef, 0x34, 0x10, 0x61, 0x65, 0xfe, 0x8d, 0xc3, 0x73,
+ 0x8f, 0xb8, 0xb2, 0x8d, 0x3e, 0x4f, 0x15, 0xdf, 0xb0, 0x62, 0x03, 0x8b,
+ 0x2f, 0xb8, 0xe5, 0x25, 0x95, 0xb1, 0x30, 0xdf, 0x0f, 0x3c, 0x20, 0x88,
+ 0x8f, 0x85, 0x37, 0xde, 0x81, 0x3c, 0xb2, 0xfc, 0xf3, 0x72, 0x3a, 0x59,
+ 0x5b, 0x15, 0x34, 0x0d, 0x88, 0x06, 0xdc, 0x8c, 0xd3, 0xea, 0x1b, 0xc8,
+ 0xef, 0xe8, 0x97, 0xa3, 0x7b, 0x2c, 0xbf, 0x61, 0xe7, 0x7d, 0xc5, 0x97,
+ 0xbc, 0x27, 0x16, 0x5f, 0xe6, 0x94, 0x03, 0xd2, 0x85, 0x97, 0xc1, 0x28,
+ 0x3a, 0xcb, 0xce, 0xe7, 0x59, 0x47, 0x37, 0x9e, 0x21, 0xb0, 0xd6, 0x5c,
+ 0xfc, 0x59, 0x6d, 0x1c, 0xd3, 0x84, 0x46, 0xa0, 0xfb, 0xdd, 0x22, 0xe9,
+ 0x7d, 0x65, 0xf4, 0xd1, 0xf7, 0x59, 0x7c, 0x10, 0x61, 0x76, 0x6e, 0x42,
+ 0x2f, 0x69, 0x2c, 0xa9, 0xcf, 0x27, 0xc7, 0x17, 0xff, 0x47, 0x84, 0x1f,
+ 0xdb, 0x26, 0x83, 0xac, 0xbf, 0xfb, 0xb2, 0x7f, 0xc6, 0x18, 0xe4, 0xeb,
+ 0x2f, 0x41, 0x1a, 0xb2, 0xff, 0xdf, 0x63, 0x3b, 0xf3, 0x6f, 0x61, 0xac,
+ 0xbf, 0xda, 0x97, 0xb3, 0x7c, 0x1d, 0x65, 0xf0, 0x45, 0x7c, 0xc5, 0x95,
+ 0x08, 0xfb, 0xed, 0x0b, 0xa1, 0xc6, 0x42, 0x73, 0x5b, 0xf3, 0xcb, 0x8d,
+ 0xbd, 0x65, 0xf6, 0x6a, 0x06, 0xb2, 0xfa, 0x6f, 0x64, 0xcb, 0x2f, 0x66,
+ 0xb3, 0x61, 0xe2, 0xb9, 0x0d, 0xe3, 0x87, 0x7a, 0xcb, 0xfb, 0x25, 0xd4,
+ 0xb3, 0xeb, 0x2d, 0xf9, 0x22, 0x03, 0x0c, 0xfc, 0x3f, 0x73, 0x76, 0xb2,
+ 0xfc, 0x71, 0x46, 0xee, 0xe0, 0xd6, 0x50, 0x0f, 0x28, 0x22, 0xf7, 0xbe,
+ 0x13, 0xac, 0xbe, 0xea, 0x5e, 0x65, 0x95, 0x07, 0x80, 0xe3, 0xb7, 0xf7,
+ 0xe3, 0x7b, 0x10, 0x16, 0x52, 0xa2, 0x0e, 0x5f, 0xcf, 0x38, 0x1c, 0x86,
+ 0x8a, 0xc1, 0xab, 0x73, 0x11, 0x03, 0xd9, 0x76, 0xd8, 0xc5, 0x1d, 0x1b,
+ 0x5f, 0x85, 0x0d, 0xff, 0x36, 0x7f, 0x9a, 0xc1, 0xe2, 0xcb, 0xfb, 0xce,
+ 0x72, 0x8e, 0x96, 0x5f, 0x1f, 0x8f, 0x2f, 0x1f, 0x20, 0x86, 0xf7, 0xf0,
+ 0x3c, 0x59, 0xfe, 0x2c, 0xbf, 0x8b, 0x37, 0x96, 0x71, 0x65, 0xa3, 0x47,
+ 0xb5, 0xf2, 0xda, 0x84, 0xd1, 0xf2, 0x11, 0x9c, 0x84, 0xa5, 0xb8, 0xb2,
+ 0xfd, 0xe8, 0xdc, 0x0c, 0x96, 0x54, 0x1b, 0xc7, 0x11, 0xbe, 0x7f, 0xe1,
+ 0x8b, 0x2a, 0x4c, 0x84, 0x81, 0x97, 0x61, 0x59, 0xa3, 0xdd, 0xc3, 0x77,
+ 0x50, 0xa2, 0x39, 0x1f, 0xa3, 0x40, 0x02, 0x49, 0x43, 0xbb, 0x8f, 0xff,
+ 0x95, 0x07, 0xbd, 0xd7, 0x6c, 0x7e, 0xfe, 0x91, 0x67, 0x5f, 0xc5, 0x97,
+ 0xa5, 0xf9, 0xd6, 0x5f, 0xfe, 0x2c, 0xf6, 0x3f, 0x7e, 0x82, 0x08, 0xd6,
+ 0x5f, 0xfe, 0x04, 0x75, 0x93, 0x8d, 0xdf, 0xb7, 0x1a, 0xcb, 0x09, 0xda,
+ 0x24, 0xc0, 0x91, 0x50, 0x98, 0x48, 0xcb, 0x75, 0x0b, 0x1b, 0xf8, 0xbf,
+ 0x2c, 0xd6, 0x2c, 0xbb, 0x6d, 0xd6, 0x53, 0x9e, 0x28, 0x85, 0x97, 0xfb,
+ 0x53, 0xf1, 0xfb, 0xd6, 0x2c, 0xbf, 0xde, 0xce, 0xdf, 0xd1, 0xe5, 0x97,
+ 0xff, 0x3b, 0x7e, 0x0b, 0xbc, 0xff, 0x99, 0x65, 0xfc, 0x4c, 0x0e, 0x79,
+ 0x96, 0x5d, 0xa1, 0xac, 0xb8, 0xc3, 0x16, 0x54, 0x8d, 0x81, 0x82, 0xf7,
+ 0xa1, 0xb7, 0xa4, 0x16, 0x68, 0xaf, 0xf9, 0x89, 0x81, 0xcc, 0xf3, 0xac,
+ 0xbf, 0x8b, 0x0c, 0xc2, 0x1a, 0xca, 0xc4, 0xe1, 0x3c, 0x66, 0xe8, 0x5c,
+ 0x7e, 0xf9, 0x78, 0x86, 0xd7, 0xf4, 0x17, 0xfd, 0x92, 0x59, 0x70, 0x38,
+ 0xb2, 0xfe, 0x6f, 0x31, 0xa6, 0xc2, 0xcb, 0x08, 0x33, 0xc5, 0xf8, 0xbd,
+ 0x69, 0x13, 0x5c, 0x71, 0xbe, 0x20, 0xb8, 0x8b, 0x2a, 0x15, 0x77, 0xb4,
+ 0x77, 0x22, 0x43, 0xc7, 0x74, 0x8e, 0xee, 0x7d, 0x65, 0xe6, 0x27, 0x59,
+ 0x69, 0xd6, 0x5b, 0x24, 0x6b, 0x08, 0x6a, 0xff, 0xa0, 0xfb, 0x33, 0x53,
+ 0xb4, 0xeb, 0x2b, 0xb4, 0x52, 0x6e, 0x21, 0x91, 0x2d, 0xef, 0x44, 0x2c,
+ 0xbf, 0x8f, 0x83, 0x82, 0xed, 0x65, 0x1c, 0xf2, 0x04, 0x1b, 0xbc, 0x61,
+ 0x86, 0x24, 0xa4, 0x82, 0xcd, 0x05, 0xf3, 0x18, 0xd3, 0x24, 0xae, 0xcf,
+ 0x01, 0x87, 0x6f, 0xb5, 0x1b, 0xf1, 0x65, 0xe9, 0xb3, 0xcb, 0x2b, 0x0f,
+ 0x01, 0xc8, 0xef, 0xb3, 0xe1, 0x75, 0x97, 0x60, 0xad, 0x65, 0x6d, 0x0d,
+ 0xa9, 0xd4, 0x43, 0x8e, 0x78, 0x7e, 0x64, 0xa8, 0xd6, 0xa4, 0x55, 0xea,
+ 0x3e, 0xd3, 0xbd, 0x7a, 0x58, 0x8b, 0xc3, 0xc0, 0x0f, 0x65, 0x08, 0x3e,
+ 0x31, 0x7c, 0x80, 0xc2, 0x1b, 0xf1, 0x3c, 0xb0, 0x6b, 0x2f, 0xb5, 0x20,
+ 0xe2, 0xcb, 0xfe, 0xf7, 0x6d, 0x00, 0x3c, 0x49, 0x65, 0xfc, 0x58, 0x00,
+ 0x60, 0x16, 0x5f, 0xff, 0xf7, 0xf9, 0x9b, 0xca, 0x3a, 0xc3, 0xbf, 0x33,
+ 0x4f, 0xd1, 0x8b, 0x2f, 0xdf, 0x13, 0xce, 0x05, 0x95, 0x3a, 0x24, 0xba,
+ 0x69, 0xae, 0x91, 0xc6, 0x50, 0xbe, 0xbc, 0x4d, 0xc5, 0x97, 0x9f, 0x3b,
+ 0x59, 0x79, 0xb2, 0x75, 0x97, 0xff, 0xb5, 0xe3, 0x1c, 0x7b, 0x04, 0x00,
+ 0x1b, 0x75, 0x65, 0xf0, 0xdc, 0x80, 0xb2, 0xff, 0x9c, 0xed, 0xee, 0xb9,
+ 0x03, 0x59, 0x7f, 0xf4, 0x10, 0x0a, 0x3a, 0x9a, 0x08, 0x0b, 0x2b, 0x62,
+ 0xa8, 0x6c, 0x8c, 0x71, 0x8a, 0x34, 0x37, 0xe1, 0xc7, 0x1c, 0x02, 0x91,
+ 0x10, 0xf0, 0xe6, 0xfa, 0x40, 0x91, 0x2c, 0xbf, 0x4d, 0xb6, 0x0d, 0xbc,
+ 0x59, 0x7b, 0xef, 0xe5, 0x97, 0xef, 0x94, 0x1f, 0x8b, 0x2a, 0x0f, 0x0f,
+ 0xa1, 0xcb, 0xff, 0x0f, 0x27, 0x3e, 0x75, 0xf8, 0x3a, 0xcb, 0xf6, 0xb3,
+ 0x7b, 0xf9, 0x65, 0x99, 0x65, 0xff, 0x39, 0xbd, 0xf9, 0x86, 0xf2, 0x59,
+ 0x7d, 0xd7, 0x6d, 0xa5, 0x97, 0xd3, 0xce, 0xfd, 0x2c, 0xb7, 0x19, 0x12,
+ 0x64, 0x21, 0xf3, 0xa1, 0x09, 0x2f, 0xff, 0xf7, 0xa0, 0xa0, 0x3d, 0xfd,
+ 0xfd, 0x87, 0x6f, 0x80, 0x2b, 0x28, 0xd4, 0xd7, 0x81, 0x0b, 0xcf, 0xa1,
+ 0x5f, 0xfe, 0x35, 0xbe, 0x59, 0x2d, 0x9d, 0x9c, 0x10, 0xb2, 0xfb, 0x35,
+ 0xe6, 0x59, 0x7f, 0xf9, 0xe4, 0x59, 0xbd, 0xe6, 0x8c, 0xff, 0x16, 0x54,
+ 0x1f, 0x5b, 0x90, 0xdb, 0x6d, 0x65, 0xf0, 0xdd, 0x86, 0xb2, 0xb6, 0x83,
+ 0x6b, 0x82, 0x97, 0xb7, 0xe1, 0x2c, 0xbd, 0xf0, 0x05, 0x65, 0xff, 0x31,
+ 0x93, 0x6c, 0x8d, 0x6b, 0x16, 0x54, 0x1f, 0xb3, 0x0e, 0xcc, 0x3b, 0x7f,
+ 0xb2, 0x71, 0x3d, 0xec, 0xdc, 0x59, 0x7f, 0xf0, 0x3d, 0x99, 0x3b, 0x66,
+ 0xf8, 0xe9, 0x65, 0x41, 0xff, 0x18, 0x71, 0x7f, 0xf4, 0x1f, 0x5a, 0x89,
+ 0xfe, 0xee, 0x6a, 0xcb, 0xa0, 0xc5, 0x94, 0x03, 0xdc, 0x24, 0x5b, 0xff,
+ 0xe0, 0x8a, 0xf9, 0xce, 0xfc, 0xdd, 0x7f, 0x5a, 0x85, 0x97, 0xb9, 0xec,
+ 0x59, 0x50, 0x7e, 0x61, 0x57, 0xbc, 0x78, 0xed, 0x65, 0xff, 0x3c, 0xb8,
+ 0x07, 0xdf, 0x83, 0x59, 0x76, 0x7b, 0x0f, 0x5f, 0xc3, 0xb7, 0xff, 0xe6,
+ 0xd7, 0x83, 0xe7, 0x6f, 0xc4, 0x82, 0x3c, 0x59, 0x7e, 0xd3, 0x4e, 0xe7,
+ 0x59, 0x71, 0x86, 0x2c, 0xac, 0x3c, 0x13, 0x0a, 0x2c, 0x14, 0x82, 0xcd,
+ 0x15, 0x1d, 0x1b, 0x5e, 0x85, 0xbd, 0xff, 0xed, 0xfe, 0x6c, 0x2e, 0xfc,
+ 0xc7, 0x8e, 0xd6, 0x5f, 0xce, 0x0e, 0xa5, 0x9f, 0x59, 0x58, 0x7f, 0x4c,
+ 0x99, 0x7a, 0x42, 0x1d, 0x65, 0xf3, 0xf4, 0x31, 0xac, 0xbd, 0x00, 0xe2,
+ 0xca, 0x92, 0xa2, 0x56, 0x8c, 0x1b, 0xd0, 0xa2, 0x72, 0x0e, 0x0f, 0x04,
+ 0x8e, 0xf6, 0x1f, 0x71, 0x65, 0xff, 0x9f, 0x7e, 0x08, 0x51, 0xe6, 0x9d,
+ 0x65, 0xfe, 0xce, 0x16, 0x7f, 0xcc, 0xb2, 0x86, 0x89, 0x0d, 0x0f, 0x92,
+ 0x05, 0xfc, 0xde, 0x72, 0x63, 0xac, 0xa1, 0xb2, 0x49, 0x32, 0x39, 0xe6,
+ 0x37, 0x9a, 0x17, 0x1a, 0x55, 0x3c, 0x26, 0xfd, 0x0a, 0xc0, 0x3f, 0x14,
+ 0x25, 0x3f, 0x2a, 0x77, 0x7c, 0x3c, 0xb7, 0x4b, 0xe9, 0x65, 0xfd, 0x1c,
+ 0x6f, 0x94, 0x2c, 0xa8, 0x36, 0xde, 0x0b, 0xbe, 0xcf, 0x31, 0x8b, 0x2f,
+ 0xa4, 0x0c, 0x02, 0xcb, 0xe7, 0xc1, 0x31, 0x65, 0xfd, 0xfc, 0x98, 0xa0,
+ 0xeb, 0x88, 0x09, 0x7c, 0x43, 0xf4, 0x2a, 0x20, 0x20, 0xb3, 0x75, 0x53,
+ 0xa3, 0x7f, 0xa2, 0x2f, 0x11, 0x3a, 0xdd, 0xff, 0xba, 0x91, 0x34, 0xff,
+ 0x79, 0x71, 0x65, 0xff, 0x70, 0x78, 0x50, 0x41, 0x85, 0x96, 0x63, 0x4f,
+ 0xdb, 0xa4, 0x0b, 0xff, 0xfb, 0xd1, 0xee, 0xdb, 0x98, 0x32, 0xc9, 0xa6,
+ 0x89, 0xd6, 0x5f, 0x8e, 0x0d, 0x67, 0x4b, 0x28, 0x68, 0x86, 0xc5, 0xdb,
+ 0xf6, 0x98, 0x22, 0xb8, 0x59, 0x7f, 0xb5, 0x9d, 0x70, 0x0f, 0xf5, 0x97,
+ 0xd3, 0x19, 0x1d, 0x2c, 0xa8, 0x44, 0x21, 0xa5, 0x7c, 0x34, 0xb0, 0x67,
+ 0x46, 0xb7, 0x70, 0xa6, 0xbf, 0x44, 0x9f, 0xa3, 0x16, 0x5f, 0xf6, 0xcd,
+ 0x6b, 0x3d, 0xd4, 0xb8, 0xb2, 0xff, 0xff, 0x67, 0x02, 0xfd, 0x66, 0x11,
+ 0xbc, 0xe6, 0x17, 0xf8, 0xb2, 0xff, 0xa4, 0xc5, 0xff, 0x64, 0xb6, 0xd6,
+ 0x57, 0x68, 0xd8, 0xe8, 0xf4, 0xec, 0x17, 0x1b, 0xbd, 0x65, 0xff, 0x7f,
+ 0x51, 0x9d, 0x6d, 0x21, 0x53, 0x68, 0x59, 0x7f, 0xdf, 0x0c, 0x64, 0xfb,
+ 0x48, 0x54, 0xda, 0x16, 0x5c, 0xe6, 0x0d, 0x15, 0xdd, 0x0d, 0x08, 0x95,
+ 0x58, 0xaf, 0x51, 0xa3, 0x85, 0xd1, 0x83, 0xc6, 0x02, 0x50, 0xe0, 0xbe,
+ 0xff, 0x03, 0x25, 0x97, 0xe0, 0xed, 0xe6, 0x80, 0xb2, 0xfd, 0xa0, 0x1d,
+ 0xe4, 0xb2, 0x9c, 0xfd, 0xb8, 0x46, 0x21, 0x5d, 0xa7, 0x59, 0x7e, 0xd9,
+ 0x93, 0x31, 0xd6, 0x5f, 0xfa, 0x3a, 0xfe, 0x49, 0x88, 0x0c, 0xb2, 0xff,
+ 0xf0, 0x63, 0x66, 0xef, 0xdb, 0x9e, 0xe9, 0xcc, 0x59, 0x53, 0xa2, 0xe1,
+ 0x8a, 0xb8, 0x7b, 0x7f, 0xec, 0x1f, 0x9c, 0x5c, 0x7a, 0x3a, 0x59, 0x7f,
+ 0xde, 0x7e, 0x31, 0x14, 0x74, 0xb2, 0x96, 0x0a, 0x53, 0x71, 0xd4, 0x32,
+ 0x8e, 0x61, 0xc4, 0x0b, 0xfe, 0x23, 0x74, 0x4d, 0xd8, 0x49, 0x65, 0xfb,
+ 0xf1, 0x85, 0x0b, 0x29, 0x8f, 0x78, 0x8e, 0x6f, 0x08, 0x5f, 0x59, 0x79,
+ 0x8e, 0xeb, 0x2f, 0xf8, 0x78, 0xc6, 0xb0, 0xdc, 0xeb, 0x2a, 0x73, 0xf0,
+ 0x34, 0x74, 0xe3, 0x77, 0xfe, 0x86, 0xe4, 0x7f, 0x91, 0xe8, 0x59, 0x7f,
+ 0xd9, 0x39, 0x41, 0xb9, 0xd7, 0xd6, 0x51, 0xa7, 0xec, 0x21, 0xe5, 0xfb,
+ 0xbc, 0x6e, 0x1d, 0x65, 0xff, 0xdc, 0x82, 0xf8, 0x93, 0x79, 0xbf, 0xc5,
+ 0x97, 0xd9, 0xa8, 0xde, 0xb2, 0xba, 0x3e, 0x9f, 0xa3, 0x5f, 0xff, 0xee,
+ 0xc0, 0x78, 0x96, 0x76, 0x36, 0x2c, 0xd7, 0x71, 0x8b, 0x2b, 0xa4, 0x42,
+ 0x11, 0x1d, 0x1d, 0x33, 0x87, 0x8c, 0x56, 0xa1, 0x5b, 0x46, 0x42, 0xb1,
+ 0xa1, 0x20, 0xf0, 0xa7, 0x0c, 0x6b, 0x97, 0xb7, 0x63, 0xa5, 0x97, 0xf8,
+ 0xb0, 0x1c, 0x11, 0xfe, 0xb2, 0xf4, 0x61, 0xd6, 0x5c, 0xd8, 0xb2, 0xfe,
+ 0xcd, 0x69, 0xa6, 0xe2, 0xca, 0x91, 0xe1, 0xfc, 0x56, 0xf1, 0xe7, 0x85,
+ 0x97, 0xfb, 0x0a, 0x3a, 0xe3, 0xf6, 0xb2, 0x8d, 0x3f, 0x2e, 0xc8, 0x8c,
+ 0x1d, 0xbe, 0xce, 0x4b, 0xb5, 0x97, 0x80, 0x7f, 0xac, 0xa9, 0x27, 0x2a,
+ 0xc4, 0x07, 0x33, 0x78, 0x68, 0x00, 0xc8, 0x88, 0xef, 0xfd, 0x87, 0x8e,
+ 0xdb, 0xfa, 0x09, 0xd6, 0x5f, 0xbc, 0xf3, 0x8f, 0x7a, 0xcb, 0xff, 0x69,
+ 0xa7, 0xd4, 0x34, 0x9f, 0x8b, 0x2f, 0xfc, 0xf9, 0x84, 0x68, 0x9f, 0x08,
+ 0xd6, 0x5e, 0x99, 0xc6, 0xb2, 0xd3, 0xe9, 0x13, 0x5e, 0x3e, 0x09, 0xfd,
+ 0xe6, 0xeb, 0x8b, 0x2f, 0xfe, 0xe4, 0x4f, 0x9a, 0x98, 0xa0, 0x1c, 0x59,
+ 0x7f, 0x9b, 0xd9, 0xad, 0x67, 0x4b, 0x2f, 0xd3, 0x14, 0x6a, 0x4b, 0x2d,
+ 0x12, 0x3d, 0xbc, 0x33, 0xa9, 0x2a, 0x1e, 0xec, 0xfd, 0xe1, 0x8a, 0x03,
+ 0x7f, 0x8e, 0x99, 0x0a, 0x0b, 0xed, 0x3c, 0xa6, 0x59, 0x7f, 0xee, 0xbf,
+ 0x85, 0x00, 0xc2, 0x02, 0xcb, 0xee, 0x40, 0x36, 0xa5, 0x95, 0x87, 0xc9,
+ 0xc3, 0xda, 0x35, 0x15, 0x06, 0x42, 0x1e, 0xfb, 0xd8, 0x07, 0x59, 0x50,
+ 0x9a, 0xbb, 0xc6, 0x19, 0xc2, 0xab, 0xfd, 0xa9, 0xb8, 0xc5, 0xf6, 0x59,
+ 0x7f, 0xe9, 0x31, 0xcc, 0xc2, 0x1f, 0xa1, 0x65, 0xfe, 0x37, 0x34, 0x03,
+ 0xb7, 0x16, 0x57, 0x47, 0xe4, 0x47, 0xd7, 0xfb, 0xcd, 0xd0, 0x34, 0xe3,
+ 0x59, 0x69, 0x96, 0x5f, 0x74, 0x0d, 0x42, 0x4b, 0x8c, 0x31, 0x25, 0x41,
+ 0xbc, 0x30, 0x8e, 0xcc, 0x90, 0x59, 0xa1, 0xaf, 0x22, 0x44, 0x9b, 0xef,
+ 0xff, 0xfe, 0x21, 0x79, 0x9b, 0xb1, 0x33, 0x1e, 0x26, 0xd8, 0x5d, 0x4b,
+ 0xc1, 0x02, 0xcb, 0x9b, 0xb5, 0x96, 0xdd, 0x59, 0x7c, 0xfb, 0x04, 0x3a,
+ 0xca, 0xde, 0x6e, 0x4c, 0x14, 0xbf, 0x86, 0xdb, 0xfd, 0x9b, 0xab, 0x2d,
+ 0x32, 0xca, 0xc3, 0xc4, 0x63, 0x2a, 0x59, 0x76, 0xa5, 0xb1, 0x52, 0x24,
+ 0xa1, 0x8b, 0xd1, 0x16, 0x9e, 0xbc, 0xa0, 0xed, 0x00, 0x20, 0xa8, 0x55,
+ 0xbe, 0xf2, 0x99, 0xaf, 0xc5, 0x2e, 0xc3, 0x3a, 0xcb, 0xd1, 0xa9, 0x96,
+ 0x53, 0x9e, 0x38, 0x4a, 0xaf, 0xe1, 0x0e, 0x4f, 0xfe, 0x2c, 0xad, 0x8e,
+ 0x8f, 0x33, 0x68, 0x26, 0x89, 0x55, 0x13, 0xc2, 0x12, 0x44, 0x43, 0x72,
+ 0xca, 0x4a, 0x37, 0x51, 0x84, 0x34, 0x3f, 0xf5, 0x39, 0x10, 0x78, 0x67,
+ 0xfa, 0x74, 0x21, 0xe3, 0xf2, 0x29, 0x79, 0xff, 0x35, 0x0c, 0xb8, 0x43,
+ 0x1c, 0x44, 0x21, 0xbd, 0xf6, 0x31, 0x65, 0x8d, 0x59, 0x7f, 0x4f, 0xb6,
+ 0x1f, 0x36, 0x96, 0x5f, 0xe2, 0x97, 0x07, 0xe6, 0x31, 0x65, 0xe9, 0xdc,
+ 0xeb, 0x2e, 0xe8, 0x96, 0x5f, 0xba, 0x97, 0x84, 0xe2, 0xcb, 0x3e, 0x1e,
+ 0x11, 0x0b, 0xdc, 0xc3, 0x59, 0x69, 0x96, 0x5c, 0x78, 0x59, 0x7b, 0xec,
+ 0x62, 0xe3, 0x08, 0x5c, 0xe2, 0x2a, 0x20, 0x77, 0x46, 0xaa, 0xb6, 0x22,
+ 0x1d, 0x84, 0x82, 0x81, 0x52, 0x47, 0x9f, 0x89, 0x7f, 0x09, 0xda, 0xd8,
+ 0x9f, 0xfc, 0x09, 0x31, 0x93, 0x9a, 0x06, 0x35, 0x2b, 0xf8, 0x18, 0x51,
+ 0x3c, 0x2c, 0xbb, 0x42, 0xb5, 0x95, 0xa3, 0xc7, 0x22, 0xcb, 0xfb, 0x08,
+ 0x19, 0x83, 0x59, 0x7f, 0x8d, 0x76, 0xeb, 0x8c, 0xeb, 0x2f, 0xff, 0xfd,
+ 0x2e, 0xfc, 0xda, 0x9c, 0xf1, 0xdf, 0xa1, 0x87, 0x1e, 0x89, 0x2c, 0xbd,
+ 0xe8, 0x35, 0x65, 0x74, 0x88, 0xbd, 0xed, 0xd7, 0xf0, 0x35, 0xa6, 0xe8,
+ 0x0b, 0x2f, 0xfe, 0x94, 0x10, 0x33, 0x40, 0x3b, 0x71, 0x65, 0xfe, 0xce,
+ 0xe2, 0x72, 0x8e, 0xd6, 0x5f, 0xbb, 0x28, 0xea, 0x4b, 0x2c, 0x05, 0x96,
+ 0xdc, 0xd8, 0x7d, 0xd8, 0x68, 0xc5, 0x37, 0xec, 0xff, 0x1f, 0xa5, 0x97,
+ 0x40, 0x56, 0x5f, 0x82, 0x40, 0x12, 0x4b, 0x2f, 0xf7, 0xa0, 0x07, 0x79,
+ 0x6c, 0xc3, 0x7f, 0xc1, 0x6a, 0x1a, 0x2c, 0x44, 0x67, 0xbf, 0xd0, 0x09,
+ 0xa4, 0xc1, 0x15, 0xac, 0xbc, 0x59, 0xcd, 0x87, 0xb8, 0x21, 0x25, 0x1a,
+ 0xac, 0xf9, 0xe1, 0x7c, 0x44, 0xdf, 0x2f, 0x0c, 0x2c, 0x77, 0xc6, 0x8b,
+ 0x7f, 0xf6, 0x9b, 0xa1, 0x3f, 0x8d, 0x27, 0xe2, 0xcb, 0xfe, 0x0c, 0xf1,
+ 0xb2, 0x3f, 0x03, 0x59, 0x5a, 0x44, 0x07, 0x91, 0x6f, 0xe8, 0xd9, 0xbb,
+ 0xbb, 0x1b, 0x8b, 0x2f, 0xc7, 0x79, 0x00, 0xeb, 0x2d, 0xad, 0x1f, 0x00,
+ 0x0e, 0x2f, 0x3e, 0xa7, 0x59, 0x71, 0x86, 0x2c, 0xbf, 0xda, 0x6c, 0xde,
+ 0x24, 0x85, 0xf6, 0x6d, 0x8c, 0x1d, 0xbe, 0x27, 0xe8, 0x0b, 0x2f, 0xfc,
+ 0xc6, 0xec, 0xe0, 0x40, 0x78, 0x92, 0xcb, 0xfd, 0xcc, 0xfb, 0x9f, 0x09,
+ 0x65, 0x0d, 0x3c, 0x66, 0x84, 0x1e, 0x97, 0x8e, 0xa1, 0xe2, 0x2f, 0xa1,
+ 0x5f, 0xfb, 0x98, 0x59, 0xec, 0xef, 0x09, 0x65, 0xff, 0xe6, 0xe6, 0x16,
+ 0xc1, 0x35, 0x36, 0x61, 0x8b, 0x2f, 0xb4, 0xd0, 0x75, 0x97, 0xfb, 0x9f,
+ 0xf6, 0x1f, 0x24, 0xb2, 0xe8, 0xe2, 0xca, 0x91, 0xe4, 0x80, 0xce, 0xf8,
+ 0xc7, 0x10, 0xeb, 0x2f, 0x3f, 0x50, 0xb2, 0xfd, 0x86, 0xf9, 0xe5, 0xe3,
+ 0xc0, 0x10, 0x92, 0xa4, 0x9c, 0xa8, 0xcf, 0x0d, 0x4d, 0x66, 0xa2, 0x62,
+ 0xa8, 0x54, 0x77, 0x91, 0xf8, 0xdf, 0xed, 0xe6, 0x61, 0x0f, 0xd0, 0xb2,
+ 0xfe, 0x61, 0xeb, 0x0f, 0x8b, 0x2f, 0xfb, 0xfc, 0x13, 0x51, 0xf8, 0x92,
+ 0xcb, 0xee, 0xdd, 0xfb, 0x54, 0x43, 0x0b, 0xfc, 0xd1, 0xa9, 0x06, 0x31,
+ 0x65, 0x6c, 0x44, 0xde, 0x8e, 0x88, 0xc2, 0xf8, 0xe7, 0x79, 0x6c, 0x47,
+ 0xc6, 0x43, 0x1e, 0xff, 0xff, 0x8b, 0x3b, 0xf4, 0x75, 0x2d, 0xbc, 0xf7,
+ 0x6d, 0x84, 0xe6, 0xac, 0xbb, 0xb0, 0x2c, 0xb9, 0xf9, 0x88, 0x82, 0x3b,
+ 0x55, 0x62, 0x3b, 0xc3, 0x0c, 0x2b, 0xfd, 0xcf, 0xbf, 0x5b, 0x6c, 0x6a,
+ 0xcb, 0xf6, 0x4d, 0x04, 0x35, 0x95, 0x07, 0xbf, 0xa3, 0x8a, 0x86, 0x5b,
+ 0x0c, 0x88, 0x5a, 0x5b, 0x4f, 0xa7, 0x3a, 0xdc, 0xa4, 0xa5, 0x0e, 0x06,
+ 0x10, 0xd7, 0xe2, 0x80, 0x74, 0x05, 0x97, 0xec, 0x94, 0x68, 0x0b, 0x2e,
+ 0x81, 0x16, 0x5f, 0x9e, 0x72, 0x89, 0x24, 0xa9, 0x8d, 0xf7, 0x85, 0xef,
+ 0xf3, 0xb7, 0xe3, 0x50, 0x05, 0x97, 0xfe, 0xf9, 0x40, 0x06, 0x4d, 0xd7,
+ 0xd6, 0x5b, 0xfe, 0x3e, 0xf1, 0x0c, 0x6f, 0xde, 0x72, 0x12, 0x75, 0x95,
+ 0x24, 0xdc, 0x0d, 0x28, 0x3b, 0x29, 0x42, 0x44, 0xc2, 0x9b, 0xff, 0x37,
+ 0x71, 0xc7, 0xd6, 0x98, 0xc5, 0x97, 0xfd, 0x3c, 0x8f, 0x1e, 0x76, 0x35,
+ 0x65, 0xff, 0xbe, 0xc5, 0x3e, 0x75, 0xff, 0x3a, 0xcb, 0xff, 0x9b, 0x46,
+ 0xf7, 0xe6, 0xf1, 0x06, 0x75, 0x95, 0x88, 0x86, 0x01, 0xfd, 0xff, 0xfc,
+ 0x3d, 0x13, 0x99, 0xb1, 0xb5, 0x05, 0x9e, 0xce, 0xd6, 0x51, 0x26, 0x7d,
+ 0xc8, 0x60, 0x18, 0x45, 0x7c, 0x1c, 0xe3, 0x2c, 0xbb, 0x81, 0x59, 0x7f,
+ 0x4b, 0xce, 0xe5, 0x0b, 0x2d, 0x1d, 0x9e, 0x17, 0x42, 0xf7, 0xff, 0x67,
+ 0xe3, 0xcd, 0x86, 0x9b, 0x12, 0x59, 0x7e, 0xd7, 0x6e, 0xfd, 0xaa, 0x20,
+ 0xa5, 0xef, 0x41, 0xd6, 0x5f, 0xfa, 0x27, 0x7f, 0xeb, 0x25, 0xb7, 0x8b,
+ 0x2f, 0x4e, 0xda, 0x59, 0x43, 0x47, 0xa6, 0x22, 0x31, 0xb1, 0x0e, 0x71,
+ 0x06, 0xfd, 0xe8, 0x38, 0x7a, 0x59, 0x7b, 0x91, 0xd2, 0xcb, 0xef, 0xf2,
+ 0x00, 0x92, 0xf3, 0xea, 0x74, 0x97, 0xc1, 0x27, 0x35, 0x25, 0xfe, 0x69,
+ 0xf3, 0xfc, 0x80, 0x24, 0xa4, 0x97, 0xf6, 0x77, 0x1e, 0x83, 0xa4, 0xb8,
+ 0xc3, 0x12, 0x5f, 0xc5, 0x05, 0x3b, 0x69, 0x25, 0x62, 0x62, 0x3d, 0x91,
+ 0x1c, 0x77, 0xc4, 0x40, 0x33, 0x20, 0xb3, 0x0b, 0x44, 0x19, 0xb6, 0x92,
+ 0x0b, 0x3f, 0x3a, 0x59, 0x5d, 0x27, 0xa0, 0xd1, 0xd0, 0x88, 0x49, 0x52,
+ 0x54, 0xf1, 0x32, 0x3f, 0xa3, 0xf9, 0xbf, 0xfe, 0x33, 0x85, 0x9d, 0x7d,
+ 0xca, 0x7c, 0xeb, 0xeb, 0x2f, 0xed, 0xfb, 0x1e, 0x52, 0xc5, 0x95, 0x08,
+ 0x83, 0xc5, 0x2b, 0xff, 0xf1, 0x67, 0xc2, 0x03, 0xbc, 0x84, 0x3e, 0xdb,
+ 0x1a, 0xb2, 0xe7, 0xd2, 0xcb, 0xf4, 0xf8, 0x38, 0x3a, 0xcb, 0xf3, 0x7b,
+ 0xb8, 0x39, 0x86, 0xf8, 0x41, 0x6a, 0x1a, 0x36, 0x3f, 0x09, 0x8a, 0x85,
+ 0xfd, 0x9c, 0x51, 0x68, 0xdf, 0x74, 0x6d, 0xe6, 0x37, 0x97, 0x2a, 0x50,
+ 0xbc, 0x0c, 0x3e, 0x6f, 0xff, 0xe7, 0x97, 0xca, 0x33, 0xac, 0xee, 0x3f,
+ 0xe6, 0xde, 0xb2, 0xe7, 0x1a, 0xca, 0x34, 0xfc, 0x8e, 0xb9, 0x7f, 0xff,
+ 0xc5, 0x9f, 0xfc, 0x75, 0x2d, 0x9e, 0x83, 0x87, 0xae, 0x7a, 0x16, 0x5f,
+ 0xd8, 0x5c, 0x62, 0xc5, 0x97, 0xf1, 0xf0, 0x7e, 0xc9, 0xd6, 0x5f, 0xfe,
+ 0x27, 0x37, 0x80, 0xff, 0xfa, 0xfe, 0x76, 0xb2, 0xfd, 0xfd, 0x9f, 0xd4,
+ 0x2c, 0xa8, 0x45, 0x29, 0xa5, 0xdd, 0x26, 0xde, 0xf0, 0x4e, 0xb2, 0x8d,
+ 0x4e, 0xab, 0x70, 0x8f, 0xcd, 0x45, 0x0c, 0xfd, 0xd3, 0x1b, 0xf8, 0xb3,
+ 0x9a, 0x8e, 0x2c, 0xbc, 0x19, 0x62, 0xca, 0x73, 0xc8, 0x01, 0x65, 0xfb,
+ 0x09, 0xff, 0xc5, 0x97, 0xde, 0x82, 0x92, 0xcb, 0xf6, 0x78, 0x9e, 0x65,
+ 0x94, 0x33, 0xee, 0xc2, 0x62, 0x21, 0xa9, 0x22, 0xf3, 0x90, 0x8f, 0xbe,
+ 0x79, 0xb3, 0xcb, 0x2f, 0xfa, 0x18, 0x9f, 0xf3, 0x31, 0x8b, 0x2f, 0xfd,
+ 0x98, 0x67, 0x3a, 0x82, 0x8e, 0x2c, 0xb6, 0xb6, 0x22, 0x63, 0x84, 0x5f,
+ 0x38, 0xa8, 0x47, 0xc3, 0x43, 0x02, 0xfe, 0x3b, 0x8f, 0xd0, 0x4b, 0x2f,
+ 0xda, 0xea, 0x59, 0xf5, 0x97, 0xf9, 0x9f, 0xf9, 0xdc, 0x01, 0x65, 0xff,
+ 0xf3, 0xb0, 0x39, 0x86, 0xb9, 0xf5, 0x18, 0x4b, 0x2f, 0x76, 0x20, 0x16,
+ 0x5f, 0xff, 0xdf, 0xe7, 0xb3, 0x75, 0xc8, 0xd1, 0xe3, 0x6b, 0x50, 0xb2,
+ 0xa0, 0xff, 0x1c, 0x7e, 0xfb, 0xd1, 0xd7, 0x16, 0x5f, 0x36, 0x75, 0xf5,
+ 0x95, 0x87, 0x8b, 0xf2, 0x3b, 0xff, 0xfe, 0xf3, 0x6b, 0x06, 0xe7, 0xc2,
+ 0xf9, 0x41, 0x99, 0xfe, 0x2c, 0xb4, 0x2c, 0xbe, 0x8d, 0xe3, 0x8e, 0xcf,
+ 0xd0, 0x0c, 0x97, 0xfe, 0x79, 0x79, 0xff, 0xcc, 0x29, 0x2c, 0xaf, 0x1f,
+ 0xc7, 0xce, 0xea, 0x4a, 0xb9, 0x34, 0x58, 0x72, 0x9f, 0x19, 0x14, 0x32,
+ 0x78, 0xcb, 0xf8, 0xc3, 0x6f, 0xff, 0x66, 0x81, 0xfd, 0x64, 0xff, 0x8c,
+ 0xe2, 0xcb, 0xdd, 0xe1, 0xd6, 0x5f, 0xff, 0xd9, 0xdc, 0x07, 0xbf, 0x46,
+ 0xbc, 0xe3, 0xf3, 0xe9, 0x65, 0xfc, 0x37, 0xff, 0x03, 0x25, 0x97, 0x4b,
+ 0x6e, 0x11, 0x4f, 0x83, 0xa2, 0x2e, 0x5f, 0xcf, 0xa8, 0xfb, 0x6f, 0x59,
+ 0x5d, 0x1f, 0x61, 0x1f, 0x5f, 0xff, 0xfb, 0x5a, 0x8e, 0xa5, 0xd7, 0x1b,
+ 0x5d, 0xfb, 0x04, 0xd3, 0x40, 0xd6, 0x5f, 0x88, 0xd1, 0x33, 0xa5, 0x97,
+ 0xfc, 0xfa, 0xce, 0xa5, 0x00, 0x85, 0x95, 0x08, 0xf4, 0xc2, 0x26, 0x70,
+ 0x09, 0x55, 0xff, 0x75, 0x2f, 0xe7, 0x3f, 0x9b, 0x8b, 0x2f, 0xff, 0xdd,
+ 0x9a, 0xfc, 0xcd, 0x49, 0xbc, 0xe5, 0xd4, 0x96, 0x5f, 0xfb, 0xb8, 0xff,
+ 0x33, 0xed, 0xd1, 0x8b, 0x2b, 0x11, 0x30, 0x6a, 0xbd, 0x42, 0x3e, 0x1e,
+ 0x1a, 0xb5, 0x0b, 0x83, 0x23, 0x70, 0xf4, 0xa5, 0x12, 0x8c, 0xca, 0xfd,
+ 0xc2, 0x0e, 0xf9, 0x2c, 0xbf, 0x61, 0x7b, 0x09, 0x65, 0xe9, 0xc4, 0xed,
+ 0x65, 0xf1, 0x34, 0xdb, 0x8b, 0x2a, 0x11, 0x29, 0xe2, 0xa7, 0x25, 0xe1,
+ 0x05, 0xce, 0x05, 0x95, 0x23, 0xd1, 0xf9, 0xdd, 0xff, 0x4b, 0x3e, 0x78,
+ 0xc2, 0x1a, 0xcb, 0xff, 0xf3, 0xbc, 0x9f, 0xdb, 0x32, 0x70, 0xfc, 0x2e,
+ 0x22, 0xa2, 0xfb, 0x5e, 0xde, 0x1f, 0xac, 0xba, 0x06, 0xb2, 0xa0, 0xda,
+ 0x80, 0x7e, 0xfe, 0x7e, 0xe0, 0xa0, 0x0b, 0x2f, 0xfd, 0xc6, 0x2e, 0xa5,
+ 0xa0, 0xc7, 0x16, 0x5f, 0xb3, 0x58, 0x38, 0x59, 0x5d, 0x27, 0x05, 0x31,
+ 0xbe, 0xa1, 0x35, 0xe2, 0x0f, 0x96, 0x6f, 0x3f, 0xbf, 0x7b, 0x26, 0x8d,
+ 0xc5, 0x97, 0xe1, 0xeb, 0x58, 0x62, 0xca, 0x9c, 0xf5, 0x08, 0xae, 0xfe,
+ 0x62, 0xcf, 0xc4, 0xcb, 0x2f, 0xf7, 0xa0, 0x3d, 0x49, 0xb6, 0xd6, 0x5f,
+ 0xfd, 0x2e, 0x41, 0xf3, 0xb2, 0x7c, 0xed, 0x65, 0xf4, 0x11, 0xa3, 0x59,
+ 0x79, 0xc1, 0x0b, 0x2f, 0xff, 0x0d, 0x8f, 0xd4, 0xb8, 0x59, 0xa1, 0x3e,
+ 0xb2, 0xa1, 0x35, 0x29, 0x11, 0x76, 0x59, 0xd1, 0xbf, 0x91, 0x38, 0x45,
+ 0xf1, 0xbb, 0xa5, 0xc5, 0x97, 0xe9, 0x37, 0x6f, 0xa5, 0x97, 0xff, 0x9c,
+ 0xb3, 0xf0, 0xda, 0x63, 0x4d, 0x85, 0x95, 0xc3, 0xf0, 0x10, 0xa2, 0xdd,
+ 0xac, 0xbf, 0xff, 0xc0, 0x6d, 0x1b, 0xe8, 0x3c, 0xd2, 0x62, 0xf4, 0x6a,
+ 0x16, 0x5b, 0xf8, 0x7e, 0x7c, 0x12, 0xbc, 0xda, 0xc5, 0x97, 0x8b, 0x24,
+ 0xb2, 0xbb, 0x36, 0xdf, 0x1b, 0xbc, 0x50, 0x75, 0x95, 0x08, 0x9a, 0x65,
+ 0xde, 0x11, 0x5f, 0xf3, 0x4b, 0xfe, 0xcd, 0x37, 0x16, 0x5f, 0xff, 0xa5,
+ 0x84, 0x3f, 0x46, 0x14, 0x00, 0xef, 0x25, 0x94, 0x48, 0x8a, 0x10, 0xe2,
+ 0xff, 0x67, 0xba, 0x97, 0xe0, 0xeb, 0x2f, 0xd2, 0x2c, 0xc9, 0xd6, 0x5d,
+ 0xa9, 0xd6, 0x5f, 0xf4, 0xc2, 0x9f, 0xb0, 0xc7, 0x84, 0xb2, 0xa0, 0xff,
+ 0x30, 0x9d, 0x86, 0x2f, 0xf3, 0x8e, 0x01, 0x06, 0x71, 0x65, 0x62, 0x61,
+ 0xfe, 0x85, 0x83, 0x96, 0x5f, 0xdb, 0x62, 0xab, 0x66, 0xcf, 0x6d, 0xae,
+ 0x20, 0x15, 0xfe, 0xf8, 0x04, 0x29, 0x7b, 0x17, 0x10, 0x0a, 0xf3, 0xea,
+ 0x4b, 0x88, 0x05, 0x58, 0x7d, 0x41, 0x41, 0xb9, 0xe4, 0xb8, 0x80, 0x57,
+ 0xce, 0x5d, 0x49, 0x71, 0x00, 0xaf, 0xf3, 0x77, 0xec, 0x00, 0x21, 0x71,
+ 0x00, 0xaf, 0x31, 0x0d, 0x71, 0x00, 0xa8, 0x68, 0xba, 0x39, 0x1f, 0x8b,
+ 0xf7, 0xa0, 0x58, 0xd5, 0xc4, 0x02, 0xbd, 0xa8, 0xfa, 0xe2, 0x01, 0x52,
+ 0xe2, 0x01, 0x5e, 0xdb, 0x60, 0x2e, 0x20, 0x15, 0xd0, 0x75, 0xc4, 0x02,
+ 0xa1, 0x9f, 0x3e, 0x0c, 0x31, 0x65, 0xf3, 0x1c, 0x70, 0xb8, 0x80, 0x57,
+ 0xbe, 0xfd, 0xae, 0x20, 0x15, 0xff, 0x89, 0xe4, 0x2f, 0xcd, 0xdb, 0xe9,
+ 0x71, 0x00, 0xaf, 0xfe, 0x7f, 0x86, 0x76, 0x2f, 0xf9, 0xe4, 0xb8, 0x80,
+ 0x57, 0x38, 0xd7, 0x10, 0x0a, 0xff, 0x13, 0x99, 0xce, 0x40, 0x17, 0x10,
+ 0x0a, 0xfc, 0xc6, 0xb9, 0x01, 0x71, 0x00, 0xae, 0x6e, 0x2e, 0x20, 0x15,
+ 0x68, 0xf5, 0xfe, 0x69, 0x7f, 0xfb, 0xcd, 0xff, 0xe7, 0x36, 0x69, 0xa0,
+ 0xeb, 0x88, 0x05, 0x7e, 0xf9, 0x47, 0x52, 0x54, 0x40, 0x2b, 0x81, 0x0b,
+ 0x88, 0x04, 0x2c, 0xda, 0xd2, 0xe2, 0x01, 0x5f, 0x41, 0xdc, 0x6b, 0x88,
+ 0x05, 0x43, 0x3c, 0x66, 0x18, 0xbe, 0x0b, 0x97, 0x6b, 0x88, 0x05, 0x7a,
+ 0x35, 0xda, 0xe2, 0x01, 0x5f, 0xfb, 0x3a, 0xe0, 0xe3, 0x08, 0x1c, 0x5c,
+ 0x40, 0x2b, 0xf0, 0x5e, 0x52, 0x85, 0xc4, 0x02, 0xbf, 0x3f, 0x7e, 0x8e,
+ 0x97, 0x10, 0x0a, 0xb1, 0x16, 0xbe, 0x4b, 0x09, 0xa5, 0xda, 0x02, 0xe2,
+ 0x01, 0x54, 0x95, 0xb3, 0x0c, 0x8f, 0x21, 0x2f, 0xd9, 0x13, 0x42, 0x37,
+ 0xcf, 0x60, 0x21, 0xe1, 0x7f, 0xe1, 0xbe, 0x12, 0xfb, 0xf6, 0x7f, 0x8f,
+ 0xd2, 0xe2, 0x01, 0x5f, 0xe1, 0xc7, 0x73, 0x6a, 0x3e, 0xb8, 0x80, 0x43,
+ 0x36, 0xb7, 0xb5, 0x06, 0x2e, 0x20, 0x15, 0x76, 0x7f, 0x9a, 0x52, 0xbf,
+ 0xc1, 0x79, 0x4a, 0x04, 0x3a, 0xe2, 0x01, 0x5f, 0x31, 0x4b, 0x8b, 0x88,
+ 0x05, 0x7f, 0x3c, 0xd2, 0xce, 0xa4, 0xb8, 0x80, 0x55, 0x88, 0xce, 0xf1,
+ 0x18, 0x10, 0x42, 0x5d, 0x7f, 0xde, 0x8e, 0x0b, 0xe0, 0x74, 0x05, 0xc4,
+ 0x02, 0xb3, 0x2e, 0x20, 0x15, 0xcf, 0x38, 0xcf, 0x9b, 0xc9, 0x37, 0x68,
+ 0x0b, 0x88, 0x05, 0x7e, 0x7f, 0xf1, 0xba, 0x5c, 0x40, 0x2b, 0xf9, 0x88,
+ 0x32, 0xce, 0x2e, 0x20, 0x15, 0x42, 0x24, 0x88, 0x93, 0xe6, 0xb5, 0x0c,
+ 0xab, 0x21, 0xc2, 0xdb, 0x21, 0xb6, 0xc7, 0xf3, 0x0f, 0xea, 0x12, 0x1e,
+ 0x2d, 0x72, 0xe0, 0x15, 0x12, 0x6f, 0x25, 0xdb, 0xfe, 0x50, 0xd6, 0xdc,
+ 0x28, 0x84, 0x86, 0x05, 0xef, 0xb1, 0x8b, 0x8c, 0x25, 0x79, 0xdf, 0xb5,
+ 0x44, 0x02, 0x16, 0x98, 0xa7, 0x50, 0xea, 0xbd, 0x06, 0x71, 0x65, 0xbe,
+ 0xb2, 0xf1, 0x67, 0x7d, 0x9a, 0xe6, 0x1d, 0xb8, 0x67, 0x59, 0x7f, 0xfc,
+ 0x40, 0xff, 0xb3, 0xb8, 0x3f, 0x27, 0x94, 0xeb, 0x2f, 0xf0, 0x7f, 0x9c,
+ 0xfe, 0x76, 0xb2, 0xb6, 0x92, 0x27, 0x9c, 0x5c, 0x0a, 0x77, 0xf7, 0xcb,
+ 0x01, 0xb7, 0x8b, 0x28, 0x69, 0x9a, 0x1b, 0x0d, 0x03, 0x9a, 0xdf, 0xe9,
+ 0x37, 0xcd, 0x37, 0x37, 0x16, 0x5f, 0x47, 0xe0, 0x6b, 0x2d, 0x3a, 0xca,
+ 0x91, 0xb3, 0xde, 0x43, 0x7f, 0x4f, 0x1a, 0xf3, 0xee, 0x2c, 0xb7, 0x16,
+ 0x5f, 0x14, 0x0f, 0xcb, 0x2b, 0xc6, 0xcb, 0x78, 0x8d, 0x42, 0x2a, 0x70,
+ 0x8d, 0x98, 0xef, 0xfc, 0x59, 0xdf, 0x98, 0x00, 0x0c, 0xcb, 0x2f, 0xf8,
+ 0x78, 0x69, 0x67, 0xe0, 0xc5, 0x97, 0xf6, 0x6b, 0x25, 0x28, 0x59, 0x52,
+ 0x45, 0x28, 0x10, 0x08, 0xe6, 0xfd, 0xfc, 0x1b, 0xf9, 0x65, 0xc0, 0x84,
+ 0x96, 0x35, 0x25, 0xef, 0x44, 0xeb, 0x2e, 0x30, 0xc4, 0x94, 0xc7, 0xbd,
+ 0xb8, 0x2d, 0x30, 0x91, 0x83, 0xb6, 0xe2, 0x41, 0x67, 0x81, 0x58, 0x8e,
+ 0x96, 0x86, 0x2d, 0xff, 0xd8, 0x09, 0x37, 0xe0, 0xf0, 0x43, 0x59, 0x47,
+ 0x3e, 0x87, 0x26, 0xbf, 0xb0, 0x7e, 0x82, 0x1a, 0xcb, 0xfb, 0xfc, 0xc3,
+ 0x3c, 0xcb, 0x2d, 0xf5, 0x95, 0xf3, 0x7e, 0x12, 0xeb, 0xf4, 0x4f, 0xc3,
+ 0xc9, 0x65, 0x31, 0xe5, 0x7c, 0x86, 0xff, 0xfd, 0xd4, 0xb8, 0x5d, 0x41,
+ 0xbc, 0x8e, 0xa4, 0xc7, 0x59, 0x7f, 0xfb, 0xfc, 0xc3, 0x5b, 0x42, 0x00,
+ 0x11, 0xd2, 0xca, 0x14, 0x36, 0xd1, 0x11, 0x08, 0x79, 0xe3, 0x30, 0x94,
+ 0x2e, 0x07, 0x19, 0x97, 0x74, 0xbf, 0xa6, 0x8e, 0xce, 0x63, 0x7d, 0x46,
+ 0x28, 0xf0, 0xd2, 0x04, 0x70, 0x04, 0x43, 0xf8, 0x5a, 0x84, 0x84, 0x45,
+ 0x9b, 0xfe, 0xc9, 0x30, 0xdf, 0xbe, 0x49, 0x65, 0xfe, 0x62, 0xed, 0xb4,
+ 0xc0, 0x59, 0x7b, 0x30, 0x0b, 0x28, 0xe7, 0x9a, 0x46, 0x55, 0xda, 0x29,
+ 0xfd, 0x08, 0x6b, 0xfb, 0xe3, 0xf0, 0x5c, 0x96, 0x5e, 0xef, 0xc4, 0xb2,
+ 0xff, 0xef, 0xed, 0xe4, 0xd2, 0x7d, 0x4e, 0x38, 0x59, 0x5d, 0x22, 0x4c,
+ 0xe5, 0xa4, 0x3b, 0x7f, 0xfb, 0xcd, 0xbd, 0xbb, 0xd4, 0x4e, 0xfa, 0xed,
+ 0x65, 0xfd, 0x1d, 0x41, 0x3f, 0xd6, 0x5c, 0x40, 0x59, 0x74, 0x71, 0x65,
+ 0x31, 0xac, 0xde, 0x2d, 0x5e, 0x3f, 0xad, 0xeb, 0x16, 0xff, 0x68, 0xec,
+ 0x12, 0x19, 0x17, 0xfb, 0x3a, 0xff, 0xde, 0x5c, 0x59, 0x7f, 0x84, 0x83,
+ 0x35, 0x18, 0x4b, 0x2f, 0x48, 0x57, 0x25, 0x97, 0x75, 0x25, 0xc6, 0x00,
+ 0xbf, 0xfd, 0x86, 0x47, 0xf2, 0x69, 0x37, 0xf8, 0xeb, 0x2f, 0xa6, 0xd4,
+ 0x7d, 0x65, 0x49, 0x1c, 0xdd, 0x19, 0x91, 0x0f, 0x09, 0x7e, 0x95, 0x7f,
+ 0xfe, 0x8c, 0xf7, 0x09, 0xfe, 0x1f, 0x8f, 0xcc, 0x6a, 0xcb, 0xfe, 0x6e,
+ 0xb9, 0xf2, 0x83, 0xf1, 0x65, 0xff, 0xff, 0xff, 0xfc, 0x1d, 0xc2, 0x7c,
+ 0xf3, 0x88, 0x59, 0xbf, 0x09, 0xcd, 0x9a, 0x41, 0xe7, 0x0c, 0x71, 0xf9,
+ 0x8c, 0xe6, 0x38, 0xd6, 0x51, 0xa8, 0xf5, 0xe1, 0xcd, 0x42, 0xe6, 0xd6,
+ 0x42, 0xf1, 0xa3, 0x1c, 0xd1, 0x83, 0xc6, 0x34, 0x49, 0x5f, 0x8d, 0x2a,
+ 0xff, 0xfc, 0x44, 0x1e, 0xb3, 0xaf, 0x8f, 0x4f, 0xd6, 0x4e, 0xb2, 0xfd,
+ 0x9f, 0xd4, 0x71, 0x65, 0x31, 0xff, 0x92, 0xc5, 0xe0, 0x44, 0x96, 0x5a,
+ 0x75, 0x94, 0xb2, 0xf4, 0xd2, 0x8d, 0x17, 0xa0, 0x12, 0xbe, 0x83, 0x60,
+ 0xeb, 0x2a, 0x48, 0xad, 0xe8, 0x83, 0x47, 0x27, 0x32, 0xbf, 0xf4, 0xb9,
+ 0xb0, 0xb0, 0xf1, 0xa3, 0x56, 0x5f, 0xff, 0xf4, 0xa0, 0xe2, 0x67, 0x9c,
+ 0xf8, 0x76, 0xfe, 0x1a, 0xda, 0x59, 0x7e, 0xd9, 0xb3, 0x3c, 0xeb, 0x2f,
+ 0xfb, 0xce, 0xdf, 0x97, 0x82, 0x6a, 0xcb, 0xcf, 0xee, 0x2c, 0xae, 0x1e,
+ 0xb1, 0x87, 0x57, 0xf4, 0xa3, 0x40, 0x10, 0xeb, 0x2f, 0xfe, 0x63, 0x4d,
+ 0x62, 0xef, 0x64, 0xfe, 0x35, 0x65, 0xff, 0xdb, 0xcb, 0x39, 0xfc, 0x29,
+ 0x67, 0x16, 0x5f, 0x1e, 0x03, 0xf5, 0x95, 0x87, 0xcc, 0xe8, 0x97, 0xdf,
+ 0xfb, 0xe9, 0x65, 0xfb, 0x26, 0xf4, 0x4e, 0xb2, 0x9c, 0xf2, 0xc8, 0x8a,
+ 0xff, 0xc4, 0xff, 0xe3, 0x74, 0x50, 0x62, 0xcb, 0xdf, 0x72, 0x59, 0x67,
+ 0xd8, 0x9f, 0x3e, 0x11, 0xf8, 0xbc, 0xa1, 0x63, 0xc6, 0xb1, 0x08, 0x37,
+ 0x4f, 0xab, 0x62, 0xad, 0xbf, 0x4a, 0x68, 0xbf, 0xe8, 0xdc, 0x1f, 0xa2,
+ 0x77, 0x25, 0x97, 0xff, 0xd0, 0x71, 0x0b, 0xfe, 0x0b, 0xcb, 0xc1, 0xe2,
+ 0xcb, 0xfe, 0x8e, 0xe0, 0xec, 0x70, 0x32, 0xca, 0xe9, 0x70, 0xcf, 0x52,
+ 0xd0, 0x7c, 0x5c, 0x47, 0x7b, 0xaa, 0x37, 0xf0, 0x86, 0x69, 0xb3, 0xc9,
+ 0x2f, 0xf3, 0xfe, 0x24, 0x11, 0xe2, 0xcb, 0xef, 0x46, 0x4e, 0xb2, 0x88,
+ 0xf5, 0x38, 0x65, 0x7d, 0xc6, 0x80, 0x2c, 0xbe, 0x9b, 0x30, 0xc5, 0x97,
+ 0xd2, 0x6d, 0x71, 0x65, 0xf3, 0x7e, 0x34, 0xb2, 0xff, 0x9b, 0x3a, 0xfc,
+ 0xd2, 0x7d, 0x2c, 0xb0, 0x3c, 0x7b, 0x64, 0x43, 0x7d, 0x37, 0x9e, 0x65,
+ 0x97, 0xdd, 0xbe, 0xa7, 0x59, 0x7a, 0x67, 0xfa, 0xcb, 0xf6, 0x4d, 0x28,
+ 0xe9, 0x65, 0xcd, 0x32, 0xcb, 0xcd, 0x04, 0xb2, 0xfd, 0x9a, 0x1f, 0xb1,
+ 0x65, 0x0c, 0xf0, 0x78, 0x35, 0x5e, 0x3f, 0xae, 0x2c, 0x5e, 0x72, 0x02,
+ 0xcb, 0xc5, 0x12, 0x49, 0x7f, 0xe2, 0x03, 0x6e, 0xee, 0x86, 0x51, 0xb8,
+ 0xb2, 0xc7, 0x59, 0x5b, 0x11, 0x1d, 0x83, 0x6e, 0x36, 0x22, 0x3d, 0x6c,
+ 0x55, 0xff, 0x04, 0x23, 0x21, 0xc2, 0x3e, 0x9f, 0x74, 0x4f, 0xe2, 0x47,
+ 0x24, 0x21, 0xdf, 0xc2, 0x8f, 0x76, 0x16, 0x15, 0x0c, 0x93, 0x1c, 0x3e,
+ 0x69, 0xc7, 0x4f, 0x2b, 0xbc, 0xb8, 0x2b, 0xf7, 0x35, 0xa8, 0xfa, 0xcb,
+ 0xfd, 0x9e, 0x7c, 0x00, 0x9f, 0x59, 0x7b, 0xed, 0x3a, 0xca, 0xe8, 0xfe,
+ 0x37, 0x0a, 0x0e, 0x67, 0x7e, 0xe1, 0xba, 0x7e, 0xd6, 0x5d, 0xc9, 0x2c,
+ 0xa9, 0x1e, 0x0e, 0xf2, 0xab, 0xc5, 0xfe, 0x2c, 0xbf, 0xdd, 0xf9, 0x87,
+ 0x05, 0xf5, 0x97, 0x34, 0x96, 0x57, 0x47, 0x92, 0x46, 0x77, 0x10, 0x16,
+ 0x5f, 0xb5, 0xe7, 0x73, 0xac, 0xbe, 0x09, 0x07, 0xb5, 0x94, 0xe7, 0x95,
+ 0xc2, 0x7b, 0xfb, 0xf3, 0x4b, 0x3a, 0x92, 0xca, 0x84, 0xd7, 0x18, 0x91,
+ 0xd9, 0x7e, 0x44, 0x16, 0x01, 0x08, 0x6f, 0xf8, 0x4c, 0xc0, 0xfb, 0x37,
+ 0xc2, 0xcb, 0xff, 0x19, 0x1a, 0xe6, 0x18, 0xfa, 0x35, 0x65, 0xec, 0xe0,
+ 0x56, 0x5f, 0xff, 0xbd, 0x9d, 0x90, 0x46, 0x50, 0x26, 0x9a, 0x09, 0x65,
+ 0x62, 0x3a, 0xfc, 0x74, 0x48, 0x3f, 0x1c, 0xbf, 0xc6, 0x67, 0x5f, 0xfc,
+ 0x1d, 0x65, 0xf8, 0xb0, 0x01, 0xe2, 0xcb, 0xfe, 0xed, 0xb0, 0xb3, 0x7b,
+ 0xf1, 0x65, 0x4e, 0x7c, 0x1e, 0x27, 0xa7, 0x45, 0xc7, 0x21, 0x2b, 0x7c,
+ 0x31, 0xe1, 0xd6, 0x5c, 0x08, 0x49, 0x71, 0x86, 0x24, 0xa6, 0x35, 0xe6,
+ 0x0b, 0x5f, 0x86, 0x17, 0xd4, 0x92, 0x0b, 0x34, 0x35, 0x88, 0xac, 0x35,
+ 0xca, 0xff, 0xf7, 0xfa, 0xed, 0xbd, 0xb7, 0x1f, 0xf0, 0x9c, 0x59, 0x61,
+ 0x51, 0x65, 0xfe, 0x89, 0x37, 0xe5, 0x1f, 0x59, 0x70, 0xaf, 0x8b, 0x05,
+ 0x59, 0xe4, 0x68, 0x5a, 0xff, 0xbc, 0xff, 0xe7, 0x65, 0x93, 0xac, 0xbd,
+ 0xb4, 0x85, 0x02, 0x85, 0x97, 0x76, 0xcb, 0x2f, 0x89, 0xba, 0x92, 0xcb,
+ 0xfe, 0x6e, 0xbd, 0x83, 0xd3, 0xf6, 0xb2, 0xa0, 0xf7, 0x34, 0x45, 0x7d,
+ 0x9b, 0xf0, 0x96, 0x5f, 0xee, 0x63, 0x7c, 0xd6, 0xf2, 0xcb, 0xfe, 0xf4,
+ 0x6a, 0x3b, 0x62, 0xed, 0x65, 0xe3, 0x5f, 0x9b, 0x49, 0x34, 0xde, 0xca,
+ 0xf4, 0xe7, 0xe2, 0x1f, 0x91, 0x6e, 0x99, 0xd6, 0x27, 0xf7, 0xf8, 0xe1,
+ 0xea, 0x4b, 0x9c, 0xbd, 0x43, 0xcf, 0x50, 0xd3, 0x39, 0x18, 0x61, 0x32,
+ 0x64, 0xa3, 0xab, 0xf7, 0x9b, 0x81, 0x9d, 0x65, 0xfc, 0x61, 0xaf, 0xf2,
+ 0x85, 0x97, 0x8e, 0x1d, 0x2c, 0xbd, 0xdb, 0x71, 0x65, 0xf0, 0x4f, 0x83,
+ 0x59, 0x5d, 0x22, 0x29, 0x8b, 0xbc, 0x3b, 0xba, 0x3b, 0x7f, 0xff, 0x6a,
+ 0x41, 0x8c, 0xf7, 0x6d, 0xcc, 0x1c, 0xf8, 0x62, 0xcb, 0xff, 0x7b, 0x37,
+ 0x5c, 0x8d, 0xce, 0xbe, 0xb2, 0xfe, 0xf3, 0x0f, 0xc1, 0x35, 0x65, 0xf8,
+ 0xa2, 0x66, 0xe9, 0x65, 0xb3, 0xb3, 0xd7, 0x62, 0xfb, 0xdf, 0xce, 0xd6,
+ 0x51, 0xcf, 0x13, 0x84, 0xf7, 0xa4, 0x70, 0x2c, 0xbf, 0x7c, 0xb3, 0x50,
+ 0xb2, 0xa1, 0x39, 0xf3, 0x57, 0x41, 0x0d, 0xdf, 0x91, 0x18, 0x3b, 0x7d,
+ 0x84, 0xc6, 0xac, 0xbf, 0xe3, 0x5f, 0x64, 0x1c, 0x98, 0xd5, 0x97, 0xfe,
+ 0x7e, 0x1e, 0x1b, 0x5a, 0x63, 0x16, 0x5f, 0xa7, 0xc1, 0xc1, 0xd6, 0x5b,
+ 0x86, 0xa2, 0x87, 0xc7, 0x62, 0x1f, 0x5f, 0xff, 0xfd, 0xe8, 0xe6, 0x02,
+ 0x3f, 0xcd, 0x64, 0xf1, 0xae, 0x7b, 0xb6, 0xe2, 0xcb, 0xd2, 0x7d, 0x2c,
+ 0xa1, 0xa2, 0x3d, 0xdc, 0xef, 0xe3, 0xeb, 0x4d, 0xd0, 0x16, 0x5f, 0x7d,
+ 0xfd, 0x32, 0xcb, 0xf8, 0xa3, 0xbf, 0x36, 0xea, 0xcb, 0xc6, 0xc7, 0x16,
+ 0x5f, 0xf6, 0x7f, 0xec, 0x6f, 0xf3, 0xb5, 0x97, 0xf4, 0x75, 0xcc, 0xeb,
+ 0xeb, 0x2e, 0xd4, 0x2c, 0xa1, 0x9e, 0x2f, 0xcb, 0xef, 0xc1, 0x21, 0xed,
+ 0x1b, 0x42, 0xcb, 0xff, 0xef, 0xea, 0x33, 0xad, 0xb2, 0x38, 0x7e, 0x07,
+ 0x59, 0x7f, 0xbe, 0xdd, 0xb0, 0xe3, 0xeb, 0x2f, 0xdc, 0x8e, 0xf0, 0xeb,
+ 0x2a, 0x0f, 0x6f, 0x86, 0x76, 0xe6, 0xc5, 0x42, 0x50, 0x47, 0x23, 0x01,
+ 0x8e, 0xe3, 0xff, 0x64, 0x5d, 0x19, 0x6a, 0x15, 0xd5, 0x25, 0xc6, 0xce,
+ 0xa1, 0x84, 0x78, 0x63, 0xb9, 0x17, 0xe5, 0x20, 0xdf, 0xf7, 0xda, 0x78,
+ 0xe8, 0x1a, 0x85, 0x97, 0x7a, 0x75, 0x97, 0xb9, 0xfc, 0x59, 0x76, 0x73,
+ 0x61, 0xf7, 0x76, 0x74, 0x20, 0xc5, 0xf9, 0xc1, 0xb6, 0xc7, 0x59, 0x7f,
+ 0x76, 0xdc, 0x0c, 0x99, 0x65, 0xe2, 0x0f, 0x16, 0x57, 0x8f, 0x2b, 0x79,
+ 0x75, 0xff, 0xd9, 0xf6, 0xea, 0x45, 0x02, 0x81, 0x53, 0x6d, 0x65, 0xff,
+ 0x3b, 0x7d, 0x8b, 0xe1, 0xf2, 0xcb, 0xde, 0x6d, 0xeb, 0x2e, 0x0c, 0xbc,
+ 0x7a, 0xa2, 0x1b, 0xdf, 0xff, 0xec, 0xde, 0x38, 0xff, 0x03, 0xa2, 0xc1,
+ 0xfa, 0x0c, 0x85, 0x97, 0xf8, 0xdf, 0xf5, 0xdb, 0x6b, 0x8b, 0x2f, 0xd9,
+ 0xf0, 0x3f, 0xd6, 0x54, 0x27, 0x71, 0x22, 0x4d, 0x42, 0x97, 0xc5, 0xe1,
+ 0x62, 0xdb, 0x37, 0xbf, 0xff, 0x47, 0x9f, 0x0a, 0x34, 0x68, 0xc2, 0xfa,
+ 0x92, 0xca, 0x92, 0xb1, 0xde, 0x1f, 0x7e, 0x51, 0x66, 0xea, 0xfd, 0x43,
+ 0x2f, 0xcc, 0x6e, 0x59, 0x0b, 0x36, 0x8f, 0x7d, 0xe7, 0x2f, 0x43, 0x2f,
+ 0xa6, 0xf3, 0x3c, 0x96, 0x5b, 0x6d, 0x65, 0x78, 0xd7, 0xed, 0x8d, 0xdf,
+ 0xec, 0x29, 0x67, 0x04, 0x3a, 0xcb, 0xf1, 0xf8, 0x07, 0x75, 0x95, 0xf3,
+ 0xda, 0x10, 0xce, 0xff, 0x61, 0x6c, 0xf6, 0x74, 0x62, 0xcb, 0xfa, 0x3c,
+ 0xdb, 0xf2, 0x65, 0x95, 0xa3, 0xe5, 0x01, 0xb5, 0xff, 0x48, 0x82, 0x0d,
+ 0x9d, 0x9c, 0x0b, 0x2a, 0x74, 0xd9, 0x64, 0xfd, 0x90, 0x88, 0xe8, 0x8a,
+ 0xff, 0xb3, 0xa9, 0x7b, 0x77, 0x76, 0x37, 0x16, 0x5f, 0xfb, 0xdc, 0x69,
+ 0x37, 0xe3, 0xfc, 0x59, 0x7f, 0xf8, 0x04, 0x1e, 0x7f, 0x91, 0xac, 0xeb,
+ 0xeb, 0x29, 0xd1, 0x12, 0x47, 0xd7, 0xff, 0x36, 0xb6, 0x3c, 0x4a, 0x08,
+ 0x32, 0x59, 0x7d, 0x1a, 0xcd, 0xeb, 0x2f, 0xde, 0x6d, 0xb7, 0x9d, 0x65,
+ 0x49, 0x12, 0x5c, 0x44, 0xf9, 0x1d, 0xfe, 0x07, 0x30, 0xb3, 0x81, 0x59,
+ 0x58, 0x7c, 0x4e, 0x61, 0x69, 0x2c, 0xbf, 0xd1, 0x9d, 0x7f, 0x35, 0x0b,
+ 0x2b, 0x47, 0x86, 0x42, 0x37, 0xfe, 0x8f, 0x09, 0xc2, 0xcf, 0xfb, 0x16,
+ 0x5f, 0xfd, 0xe0, 0xf3, 0x91, 0xae, 0xf0, 0x4c, 0x59, 0x7b, 0x00, 0xeb,
+ 0x2d, 0xbd, 0x8f, 0x87, 0xc8, 0xd7, 0xa0, 0x18, 0xb2, 0xff, 0xe9, 0x1a,
+ 0xe2, 0x7d, 0xb5, 0x01, 0x15, 0xac, 0xaf, 0x1f, 0x2b, 0x8d, 0xd6, 0x22,
+ 0xbc, 0x30, 0x8e, 0xbf, 0xe7, 0xe8, 0x33, 0xc1, 0x47, 0x4b, 0x2a, 0x17,
+ 0x16, 0x31, 0x11, 0xa1, 0x99, 0xe8, 0xc5, 0x5d, 0x8c, 0x04, 0x25, 0x1a,
+ 0x70, 0x49, 0xef, 0xff, 0xc6, 0xb7, 0xcb, 0x25, 0xd7, 0xc9, 0xa7, 0xe0,
+ 0x56, 0x5f, 0x6f, 0x18, 0xe1, 0x65, 0xff, 0xd9, 0xad, 0x99, 0xe7, 0x34,
+ 0x83, 0xc5, 0x94, 0xc8, 0xc1, 0x75, 0x70, 0x92, 0x5f, 0xff, 0xda, 0x96,
+ 0xc1, 0xfa, 0x36, 0x16, 0x75, 0xf8, 0xc3, 0x16, 0x5d, 0xce, 0x2c, 0xbf,
+ 0x46, 0x7f, 0x8e, 0xb2, 0xf1, 0x86, 0x18, 0xb2, 0xe0, 0x3a, 0x41, 0x66,
+ 0x82, 0xff, 0x6a, 0x37, 0xe6, 0x1c, 0x6b, 0x29, 0x93, 0x19, 0xd3, 0x01,
+ 0xc5, 0xf8, 0x8c, 0x12, 0x8b, 0xff, 0x67, 0x09, 0xcd, 0x98, 0x9a, 0x65,
+ 0x97, 0xf0, 0x22, 0x5e, 0x13, 0x8b, 0x2f, 0xf9, 0x80, 0x26, 0x6f, 0x20,
+ 0xf1, 0x65, 0xfb, 0x81, 0x06, 0x12, 0xcb, 0xf9, 0x88, 0x1d, 0xf6, 0xcb,
+ 0x2f, 0x38, 0x31, 0x25, 0x49, 0x55, 0x51, 0xe3, 0x47, 0xf2, 0x50, 0x0f,
+ 0xc8, 0xbf, 0xe7, 0x7b, 0xc9, 0xf6, 0xcb, 0xaf, 0xa0, 0x6c, 0x35, 0x97,
+ 0xf7, 0x3c, 0xdd, 0xbe, 0x96, 0x5f, 0x87, 0xa6, 0x0c, 0xeb, 0x2f, 0xd9,
+ 0xfe, 0x3f, 0x4b, 0x2f, 0xf1, 0x98, 0x59, 0xbd, 0xb4, 0xb2, 0xfe, 0x2c,
+ 0xe8, 0x02, 0x49, 0x65, 0xff, 0xf7, 0x3f, 0x9e, 0x10, 0xf9, 0xdc, 0x7a,
+ 0x0e, 0xb2, 0xdc, 0x59, 0x58, 0x9a, 0x24, 0xc5, 0xda, 0x29, 0x22, 0x8f,
+ 0x9a, 0x04, 0xbc, 0xc5, 0x1b, 0xf6, 0x67, 0xfd, 0x8b, 0x2e, 0x73, 0xac,
+ 0xbf, 0xff, 0xb0, 0x8a, 0x25, 0xa8, 0xe1, 0x66, 0xf6, 0xf0, 0x56, 0x5f,
+ 0xf0, 0x79, 0xf8, 0x98, 0x3d, 0x71, 0x65, 0xf3, 0x6b, 0x50, 0xb2, 0xff,
+ 0x66, 0xfc, 0x16, 0x61, 0x86, 0x24, 0xbc, 0x66, 0x79, 0x65, 0xfa, 0x68,
+ 0xcf, 0x71, 0x65, 0x6c, 0x46, 0xe7, 0x8f, 0x08, 0x87, 0xe7, 0x42, 0x0e,
+ 0xdf, 0xe1, 0x5c, 0x07, 0xbf, 0x36, 0x96, 0x5e, 0x3b, 0xfd, 0x65, 0xfc,
+ 0x51, 0x30, 0x5c, 0x45, 0x95, 0x32, 0xa1, 0x93, 0x8b, 0x7a, 0x33, 0x50,
+ 0xa6, 0x6f, 0x38, 0x10, 0x72, 0xff, 0xfb, 0x06, 0xec, 0x4f, 0xf6, 0x29,
+ 0x73, 0x16, 0x5f, 0xde, 0x7d, 0x36, 0x69, 0x65, 0x41, 0xfb, 0xba, 0x5d,
+ 0x2c, 0xbe, 0xeb, 0xb6, 0xd2, 0xcb, 0x03, 0x6b, 0x35, 0xff, 0x0b, 0xbf,
+ 0xdb, 0xfc, 0xd9, 0x27, 0xde, 0xb2, 0xfd, 0xbd, 0xce, 0xc7, 0x59, 0x50,
+ 0x88, 0xbc, 0x2c, 0x23, 0x6b, 0xf6, 0x4d, 0x28, 0x92, 0xcb, 0xe8, 0x11,
+ 0x80, 0xb2, 0xff, 0x8e, 0xf2, 0xc9, 0x40, 0x38, 0xb2, 0xff, 0xf9, 0xbf,
+ 0xcf, 0x30, 0xcf, 0xf2, 0x8c, 0xe9, 0x65, 0x4e, 0x8a, 0x90, 0x11, 0x7c,
+ 0xe2, 0xfe, 0x9c, 0x71, 0x84, 0x35, 0x95, 0x0b, 0xf2, 0xd2, 0x7d, 0x68,
+ 0xd9, 0x7c, 0xca, 0xf2, 0x8f, 0xca, 0x1b, 0x5c, 0x86, 0xd7, 0xcb, 0x43,
+ 0x0d, 0x11, 0x0c, 0x6f, 0x38, 0x19, 0x65, 0xff, 0xb3, 0x7c, 0x47, 0xa2,
+ 0x78, 0xe9, 0x65, 0xff, 0x0c, 0x83, 0xcc, 0x9f, 0x27, 0x59, 0x7a, 0x34,
+ 0x4b, 0x2f, 0xf6, 0x0c, 0x9f, 0x8c, 0x35, 0x96, 0xf2, 0xcb, 0xc1, 0x79,
+ 0xc8, 0xf0, 0xb8, 0x63, 0x5a, 0x44, 0x87, 0xd7, 0x6f, 0x8f, 0xcc, 0x3a,
+ 0xca, 0x63, 0xc5, 0x72, 0x3b, 0xfa, 0x35, 0xff, 0xe6, 0xe2, 0xcb, 0xa3,
+ 0x7a, 0xca, 0x3a, 0x7a, 0x5e, 0x1b, 0x74, 0x01, 0x5c, 0x61, 0xe4, 0x41,
+ 0xba, 0x61, 0x7f, 0x08, 0x32, 0x8c, 0x9d, 0x65, 0x89, 0x65, 0xf4, 0x4f,
+ 0x12, 0x59, 0x43, 0x3e, 0x07, 0x2e, 0x21, 0x0b, 0xfb, 0xcd, 0xf2, 0x83,
+ 0xac, 0xbf, 0xfd, 0x83, 0x73, 0xe7, 0x52, 0xc0, 0x60, 0xd6, 0x5d, 0xe7,
+ 0x59, 0x74, 0xdc, 0x59, 0x7e, 0xcd, 0xec, 0x43, 0xc3, 0x5c, 0x20, 0xb5,
+ 0xfd, 0xb3, 0xf9, 0xce, 0x42, 0xcb, 0xec, 0xeb, 0xf0, 0xb2, 0xff, 0xe7,
+ 0xd6, 0x1a, 0xda, 0xcd, 0xef, 0xa5, 0x95, 0xe3, 0xe7, 0xde, 0x45, 0x7f,
+ 0xe2, 0xcd, 0x69, 0x8f, 0x9d, 0x7d, 0x65, 0xfb, 0x75, 0xe7, 0x12, 0x4b,
+ 0x2b, 0x62, 0x7b, 0x42, 0xdd, 0xe0, 0xfb, 0x21, 0x2d, 0xc2, 0x40, 0x9f,
+ 0x5d, 0xe7, 0x59, 0x7f, 0xef, 0x33, 0x83, 0x0a, 0x3a, 0xe2, 0xcb, 0x0f,
+ 0x0f, 0x4f, 0xe2, 0xd7, 0xfc, 0x52, 0xf6, 0x11, 0x41, 0x8b, 0x2f, 0xff,
+ 0x3c, 0xf1, 0xad, 0x3c, 0xb6, 0x00, 0x78, 0xb2, 0xb1, 0x10, 0x64, 0x6f,
+ 0x7f, 0xe2, 0xcf, 0xf9, 0xa3, 0x70, 0xf8, 0xb2, 0xff, 0xb5, 0xa7, 0x96,
+ 0xcd, 0xf1, 0xb8, 0xb2, 0xa0, 0xff, 0xf0, 0xfe, 0xa1, 0x18, 0x12, 0x85,
+ 0x05, 0x69, 0x52, 0x19, 0x42, 0xcb, 0xf1, 0xb5, 0x5f, 0xb0, 0x9f, 0xfc,
+ 0x59, 0x7f, 0x73, 0xd8, 0x4d, 0xc5, 0x97, 0xf7, 0x66, 0x39, 0x14, 0x2c,
+ 0xa9, 0x1f, 0xfe, 0x89, 0x88, 0xb2, 0xfa, 0x6f, 0x36, 0x96, 0x5f, 0x38,
+ 0xc4, 0x3a, 0xcb, 0xb3, 0x82, 0x93, 0xc6, 0x91, 0x1d, 0x42, 0xee, 0xb6,
+ 0x16, 0xb4, 0xe2, 0x4b, 0xc2, 0xec, 0x9d, 0x2f, 0xfb, 0x07, 0x85, 0x04,
+ 0x18, 0x59, 0x63, 0x16, 0x5f, 0xfe, 0x06, 0x75, 0xf8, 0xea, 0x5f, 0x04,
+ 0x49, 0x65, 0xfe, 0xf9, 0x37, 0x5c, 0x10, 0xeb, 0x28, 0x91, 0x03, 0xc4,
+ 0xcb, 0xf3, 0xbf, 0x52, 0xe2, 0xca, 0x84, 0x6e, 0xb4, 0x24, 0xf4, 0x45,
+ 0x51, 0x08, 0x26, 0x79, 0xe5, 0x0e, 0x4a, 0x97, 0xf0, 0x3a, 0x4e, 0x46,
+ 0x4a, 0xa2, 0x36, 0x52, 0x97, 0x73, 0xe4, 0x7d, 0x46, 0x60, 0xd1, 0xd2,
+ 0x4d, 0x28, 0x1f, 0x55, 0xb7, 0x71, 0xe7, 0xa4, 0x7d, 0x4a, 0xd6, 0x78,
+ 0x68, 0x82, 0x3d, 0x02, 0xac, 0x86, 0x79, 0x3c, 0xbb, 0xfa, 0x5c, 0x08,
+ 0x65, 0x3c, 0xef, 0x9e, 0x99, 0x11, 0x57, 0x76, 0x31, 0x2b, 0xfd, 0xa2,
+ 0x8f, 0xcb, 0x3c, 0xb2, 0xf7, 0x20, 0x0b, 0x2b, 0x0f, 0x3b, 0xe6, 0x57,
+ 0xfe, 0xf6, 0x0f, 0xd8, 0xe5, 0x9b, 0x8b, 0x2f, 0xe9, 0x16, 0x76, 0xdf,
+ 0x59, 0x7f, 0xf1, 0x76, 0x6b, 0xf3, 0x25, 0x05, 0xda, 0xcb, 0xec, 0x1b,
+ 0xc9, 0x65, 0xcd, 0x3a, 0xca, 0x01, 0xb8, 0xf9, 0x0d, 0x62, 0x61, 0x5d,
+ 0x1f, 0xb1, 0x69, 0x3e, 0xdf, 0xf7, 0xf9, 0xe6, 0x83, 0xb8, 0xd6, 0x5f,
+ 0x0f, 0x4f, 0x25, 0x97, 0x84, 0x80, 0x2c, 0xbe, 0xf0, 0x63, 0x8b, 0x2f,
+ 0x3b, 0x81, 0x65, 0xef, 0x47, 0x20, 0xde, 0xe8, 0x8a, 0xff, 0xde, 0x62,
+ 0x8e, 0xb8, 0xc7, 0x85, 0x97, 0xb9, 0x1a, 0x59, 0x77, 0xf8, 0x34, 0x45,
+ 0x76, 0x63, 0xd1, 0xed, 0x42, 0x6f, 0x86, 0x9c, 0x39, 0x10, 0x61, 0xc9,
+ 0x7a, 0x5f, 0x3a, 0xcb, 0xf8, 0xb2, 0x52, 0x7e, 0x2c, 0xbf, 0xa0, 0x4e,
+ 0x0f, 0xa3, 0xac, 0xae, 0xcf, 0x70, 0x8b, 0x2f, 0xe7, 0x33, 0x00, 0x27,
+ 0xd6, 0x5c, 0x36, 0x59, 0x7d, 0xd7, 0x23, 0xa5, 0x97, 0x3c, 0xb6, 0x1b,
+ 0xa6, 0x16, 0xbc, 0x6f, 0x99, 0x65, 0xff, 0xd3, 0x6a, 0x37, 0xfa, 0x1b,
+ 0x4d, 0x32, 0xca, 0x91, 0xf2, 0x74, 0x3b, 0x7f, 0x0f, 0xd9, 0xfe, 0x3a,
+ 0xcb, 0xfd, 0xc2, 0xc3, 0xbb, 0xce, 0xb2, 0x9c, 0xf7, 0xc2, 0x5b, 0x7f,
+ 0x73, 0x06, 0xdc, 0x9d, 0x65, 0xe9, 0x40, 0x16, 0x5f, 0x84, 0x9a, 0x51,
+ 0xb8, 0x92, 0xa1, 0x77, 0x53, 0x23, 0x2b, 0x36, 0x3b, 0x8e, 0xd0, 0x99,
+ 0xe7, 0x44, 0x5e, 0x69, 0x78, 0x48, 0x94, 0x20, 0xb8, 0x43, 0xf2, 0xe1,
+ 0x07, 0x2f, 0xe1, 0xe9, 0xfb, 0x7e, 0xd6, 0x5f, 0xff, 0xf0, 0xaa, 0x9e,
+ 0x36, 0x83, 0xc0, 0xaa, 0x14, 0x0a, 0xbf, 0xce, 0x0d, 0x9b, 0x3d, 0xb6,
+ 0xb2, 0xdd, 0xac, 0xbf, 0xf1, 0x05, 0xc4, 0xce, 0x34, 0x12, 0xcb, 0xf4,
+ 0xb9, 0xfd, 0xe0, 0x59, 0x46, 0x9f, 0x3f, 0x47, 0x97, 0xb6, 0xd8, 0x6b,
+ 0x2b, 0x47, 0x86, 0x72, 0x4b, 0xfb, 0x61, 0x66, 0xf7, 0xd2, 0xcb, 0xd0,
+ 0xfa, 0x59, 0x7f, 0x6f, 0x13, 0xff, 0x0f, 0x96, 0x5f, 0xc7, 0xff, 0xa3,
+ 0x7c, 0x2c, 0xbe, 0xc2, 0xec, 0x0b, 0x2f, 0xf7, 0xe5, 0x1f, 0xf3, 0xc9,
+ 0x65, 0xff, 0xbe, 0x13, 0xfa, 0x18, 0x9c, 0x6b, 0x2f, 0xa5, 0x27, 0xfa,
+ 0xca, 0x9d, 0x12, 0x5d, 0x19, 0xb9, 0xed, 0xf1, 0xba, 0x73, 0x16, 0x5d,
+ 0xde, 0xf5, 0x96, 0x11, 0x51, 0x02, 0xad, 0xf5, 0x50, 0x28, 0xad, 0x1e,
+ 0xbf, 0xc6, 0x8c, 0x1f, 0xac, 0x45, 0x5b, 0x3d, 0xdf, 0xdd, 0xb4, 0xff,
+ 0x71, 0xac, 0xbf, 0x98, 0x57, 0xdf, 0xa0, 0xc5, 0x97, 0xfb, 0xcc, 0x20,
+ 0xb0, 0x02, 0x12, 0x56, 0x8f, 0xa7, 0x6c, 0xce, 0xfd, 0x87, 0x77, 0x9d,
+ 0x65, 0xfa, 0x3b, 0xf4, 0x69, 0x65, 0xef, 0x04, 0xd5, 0x97, 0xb7, 0x45,
+ 0x7c, 0x59, 0x5e, 0x3c, 0x22, 0x1e, 0xa9, 0xd3, 0x6f, 0x68, 0x4c, 0x11,
+ 0x2f, 0xc9, 0xc4, 0x6a, 0xbf, 0x8f, 0xe8, 0x0f, 0x4c, 0xb2, 0xff, 0x88,
+ 0x03, 0xf3, 0x89, 0x93, 0xac, 0xbf, 0x60, 0x45, 0x79, 0xc5, 0x94, 0xc7,
+ 0xcb, 0xe3, 0xab, 0xff, 0xc4, 0x6b, 0xb9, 0x00, 0x82, 0xfd, 0x6d, 0x4b,
+ 0x2f, 0xf7, 0xf8, 0x1e, 0xbe, 0xc6, 0x2c, 0xac, 0x44, 0x21, 0x27, 0x5f,
+ 0xff, 0xb0, 0xc8, 0x38, 0x5c, 0x7f, 0xeb, 0xb6, 0x23, 0x16, 0x5f, 0xfb,
+ 0xaf, 0xf7, 0xe6, 0x1f, 0xb2, 0x75, 0x97, 0xf3, 0x75, 0xcf, 0x31, 0x8b,
+ 0x2c, 0x2b, 0x59, 0x40, 0x3c, 0x42, 0x2f, 0xac, 0x45, 0x3e, 0xa1, 0x0d,
+ 0x7f, 0x3f, 0x33, 0x08, 0xd5, 0x95, 0x87, 0xa6, 0x12, 0x7b, 0xce, 0xe6,
+ 0x2c, 0xa8, 0x4e, 0xc0, 0x64, 0x3e, 0x8d, 0x48, 0x88, 0x6f, 0xf7, 0xf9,
+ 0xb3, 0x0e, 0xc3, 0x59, 0x7f, 0xcf, 0xa9, 0x8a, 0x01, 0xc0, 0xac, 0xa8,
+ 0x3e, 0xe1, 0x9a, 0xdf, 0xbf, 0x81, 0x2f, 0xac, 0xbf, 0x4b, 0x82, 0x46,
+ 0xe2, 0xcb, 0x46, 0x1e, 0x9b, 0x93, 0xdf, 0xfb, 0x61, 0x39, 0xbb, 0x38,
+ 0x00, 0x42, 0xcb, 0xff, 0xd3, 0x84, 0x1c, 0x93, 0x73, 0x91, 0xa9, 0x2c,
+ 0xb3, 0x1a, 0x88, 0xfd, 0x21, 0xdf, 0xe7, 0xf7, 0x5c, 0x82, 0xfa, 0xca,
+ 0x92, 0x62, 0x1c, 0x85, 0xa7, 0xca, 0x6f, 0xff, 0xf0, 0xfd, 0x1d, 0xf9,
+ 0xa6, 0x77, 0x91, 0xae, 0x23, 0xee, 0x2c, 0xbf, 0xff, 0xf7, 0x9d, 0xb8,
+ 0xd2, 0xc1, 0xff, 0xd0, 0xda, 0xd3, 0x14, 0xeb, 0x2f, 0x8b, 0x37, 0xe2,
+ 0xca, 0x9d, 0x1e, 0x47, 0x66, 0x31, 0xaa, 0xff, 0x79, 0xa6, 0x94, 0x14,
+ 0x96, 0x5f, 0xff, 0xd1, 0xfe, 0x08, 0x5f, 0xf0, 0x5e, 0x5f, 0xe6, 0x18,
+ 0xb2, 0xff, 0xd1, 0x3e, 0x7e, 0x58, 0x4c, 0x35, 0x97, 0xfe, 0x73, 0x3f,
+ 0x9e, 0xfb, 0x46, 0xe2, 0xcb, 0xff, 0x41, 0x9c, 0x14, 0xbf, 0x79, 0xd7,
+ 0xd6, 0x54, 0x27, 0x0b, 0xd9, 0x96, 0x8c, 0xfc, 0xba, 0x47, 0xbf, 0x41,
+ 0xbe, 0x97, 0xb2, 0x75, 0x97, 0xcd, 0x3f, 0x72, 0x59, 0x7f, 0xd1, 0xd1,
+ 0xdf, 0xf9, 0xd7, 0xd6, 0x5c, 0xf3, 0xac, 0xae, 0x91, 0x31, 0xa2, 0x32,
+ 0x24, 0x30, 0xea, 0xf7, 0x9f, 0x8b, 0x2d, 0xd2, 0xca, 0x83, 0x5c, 0x31,
+ 0xcb, 0xfc, 0x77, 0xe1, 0x46, 0x1a, 0xb2, 0xc1, 0x59, 0x7f, 0xc1, 0x0f,
+ 0x9b, 0xfe, 0x79, 0x2c, 0xbd, 0x2c, 0xfa, 0xcb, 0xe7, 0xf6, 0x69, 0x65,
+ 0x78, 0xde, 0xef, 0x1c, 0xbf, 0x07, 0xda, 0x83, 0x16, 0x5d, 0xb6, 0xeb,
+ 0x2e, 0x8e, 0xf6, 0x26, 0x7d, 0x84, 0x06, 0x99, 0x1c, 0x45, 0xdd, 0xbe,
+ 0x46, 0x21, 0x4d, 0xe2, 0x15, 0xf1, 0x65, 0xf4, 0xbc, 0xdb, 0xd6, 0x5e,
+ 0x82, 0xfe, 0xc3, 0xc4, 0x62, 0x0b, 0xb4, 0xeb, 0x2f, 0xfe, 0xde, 0xdc,
+ 0xe6, 0x17, 0x6e, 0x40, 0x59, 0x7f, 0xbc, 0xc3, 0x1e, 0x19, 0x32, 0xcb,
+ 0xcd, 0xd7, 0x16, 0x5f, 0xb3, 0x7e, 0x48, 0x56, 0xb2, 0x8d, 0x3c, 0xaf,
+ 0x0e, 0xd8, 0x18, 0x8e, 0x7e, 0xd1, 0x7e, 0xff, 0x7c, 0x27, 0x9f, 0xeb,
+ 0x2d, 0x1a, 0x3d, 0x93, 0x9b, 0x53, 0x27, 0x61, 0xa3, 0x3f, 0x46, 0xad,
+ 0x7f, 0xe7, 0xeb, 0x99, 0xf6, 0x3b, 0xc9, 0x65, 0xbe, 0xb2, 0x80, 0x79,
+ 0xe2, 0x1f, 0x5f, 0xff, 0x13, 0xe7, 0x9b, 0x5e, 0x70, 0xfb, 0x0e, 0xb2,
+ 0xff, 0xde, 0x6e, 0xfd, 0x9f, 0xc3, 0x64, 0xb2, 0x86, 0x88, 0xdc, 0x4d,
+ 0xbf, 0xff, 0xf3, 0xe8, 0xd1, 0xfa, 0x39, 0xec, 0xea, 0x5f, 0x69, 0xa3,
+ 0x81, 0x59, 0x58, 0x89, 0x17, 0x22, 0xbe, 0x2d, 0x9d, 0xcc, 0xb2, 0xff,
+ 0xff, 0x4c, 0x50, 0x7d, 0x47, 0x79, 0xac, 0xf3, 0x6b, 0xce, 0xb2, 0xff,
+ 0xf9, 0xf4, 0x0d, 0xbc, 0xd4, 0x49, 0xba, 0xfe, 0x2c, 0xbf, 0xff, 0xf8,
+ 0x3c, 0xf3, 0xcb, 0x92, 0x6f, 0x89, 0xa8, 0xf4, 0x7f, 0x8f, 0xd2, 0xcb,
+ 0xff, 0xce, 0x0c, 0x28, 0x94, 0x6c, 0x83, 0x9d, 0x65, 0xfa, 0x30, 0xbf,
+ 0xb6, 0xb2, 0xfe, 0x6e, 0x81, 0xa7, 0x1a, 0xcb, 0xff, 0xdb, 0xcb, 0x39,
+ 0xb3, 0x08, 0x32, 0xce, 0x2c, 0xa5, 0x95, 0x87, 0xae, 0x74, 0xca, 0x3a,
+ 0x33, 0xfc, 0x52, 0x50, 0x85, 0xbf, 0x7a, 0x35, 0xc6, 0x59, 0x76, 0xb7,
+ 0x16, 0x5e, 0x90, 0x46, 0xb2, 0xe7, 0xeb, 0x62, 0x24, 0x86, 0x69, 0x31,
+ 0x3b, 0x8d, 0x5f, 0xe7, 0x21, 0x1e, 0x58, 0x35, 0x95, 0x0a, 0xdc, 0xf0,
+ 0x99, 0x98, 0x34, 0xa4, 0x4e, 0x9c, 0x8e, 0xa8, 0x29, 0x77, 0xf3, 0x68,
+ 0x51, 0xcf, 0xb2, 0xcb, 0xff, 0xfb, 0x0a, 0x7e, 0x72, 0x01, 0x9e, 0x6d,
+ 0x39, 0x9f, 0x59, 0x7f, 0x0f, 0x08, 0xdd, 0x42, 0xcb, 0xb6, 0xfa, 0x59,
+ 0x52, 0x6c, 0xb3, 0x07, 0x29, 0x57, 0xb8, 0x58, 0x75, 0x1c, 0x24, 0xd2,
+ 0xab, 0x75, 0x0e, 0xf3, 0xc7, 0x55, 0xe9, 0x4c, 0xe0, 0x84, 0x29, 0x46,
+ 0x83, 0xf9, 0x72, 0x9b, 0xda, 0x0c, 0x31, 0xdb, 0x5b, 0x10, 0xb6, 0xf9,
+ 0xe7, 0x09, 0x8b, 0x2e, 0x15, 0xee, 0xac, 0xbc, 0xc7, 0xc5, 0x97, 0x41,
+ 0xab, 0x2a, 0x47, 0xe9, 0xd1, 0x26, 0x87, 0x8c, 0x1b, 0xb7, 0x6b, 0x2f,
+ 0xff, 0xec, 0x1f, 0xa0, 0xc2, 0xc6, 0x9f, 0x6c, 0x3e, 0x6d, 0x2c, 0xad,
+ 0xc3, 0xf0, 0x21, 0x2a, 0x86, 0xd8, 0x33, 0x14, 0x1a, 0xb3, 0x5f, 0x78,
+ 0xe2, 0xc3, 0x0a, 0xeb, 0xe8, 0xed, 0xbb, 0x59, 0x7b, 0x4c, 0x62, 0xcb,
+ 0xfd, 0xcc, 0xd0, 0xc9, 0xe4, 0xb2, 0x86, 0x79, 0xfc, 0x1d, 0xbf, 0xcf,
+ 0xb0, 0xb0, 0x01, 0xe2, 0xcb, 0xde, 0xc0, 0x2c, 0xb4, 0x2c, 0xbf, 0xfe,
+ 0x99, 0xde, 0x5c, 0x83, 0x8f, 0xd0, 0x5d, 0xac, 0xa8, 0x3e, 0x06, 0x10,
+ 0xbf, 0xe0, 0xf7, 0x9a, 0x9e, 0x70, 0xce, 0xb2, 0xff, 0xb2, 0x69, 0x47,
+ 0x59, 0xd7, 0xd6, 0x56, 0xc4, 0xd2, 0x60, 0xd3, 0x1f, 0x0e, 0x40, 0x47,
+ 0xd7, 0xa7, 0x6e, 0x96, 0x5d, 0xe1, 0xac, 0xa9, 0xcf, 0xfd, 0x92, 0xb8,
+ 0x3d, 0x52, 0x55, 0x16, 0x37, 0x2d, 0x47, 0xd5, 0x7c, 0x3f, 0x06, 0x75,
+ 0x97, 0xf3, 0xcb, 0x27, 0x09, 0x2c, 0xbb, 0x06, 0xb2, 0x86, 0x78, 0x7d,
+ 0x96, 0xdf, 0xfb, 0x59, 0xb9, 0x37, 0x9c, 0xed, 0xc5, 0x97, 0xfd, 0x9f,
+ 0xfb, 0x18, 0x76, 0xfa, 0xcb, 0x4f, 0x09, 0x82, 0xe3, 0x3e, 0x88, 0xfc,
+ 0x85, 0x66, 0x59, 0x70, 0xaf, 0x16, 0x56, 0x1f, 0x6e, 0x90, 0xdc, 0x42,
+ 0xff, 0xdb, 0xdb, 0xf2, 0x8d, 0x9f, 0x80, 0xac, 0xb4, 0xcb, 0x2f, 0x6f,
+ 0xc1, 0xac, 0xbf, 0x6d, 0x87, 0xd9, 0xda, 0xcb, 0x8f, 0xc5, 0x95, 0x88,
+ 0xb5, 0x99, 0x08, 0xe2, 0x5f, 0x1e, 0x09, 0x65, 0xfd, 0x1f, 0x60, 0x44,
+ 0x96, 0x5d, 0x27, 0x59, 0x5a, 0x3c, 0x27, 0x2c, 0xbf, 0xba, 0x9d, 0xe5,
+ 0x1b, 0x8b, 0x2e, 0x29, 0x2c, 0xa8, 0x3c, 0x89, 0xcc, 0xae, 0x32, 0x16,
+ 0x56, 0xc7, 0x44, 0x2f, 0xb5, 0x17, 0x8a, 0x61, 0x1b, 0x10, 0xbc, 0x9c,
+ 0x8a, 0x46, 0x18, 0x36, 0x69, 0x97, 0x65, 0xed, 0x0b, 0x43, 0xc3, 0x73,
+ 0xd5, 0xbc, 0xe3, 0xca, 0xeb, 0x28, 0xea, 0xb9, 0x0e, 0x2f, 0xc2, 0x30,
+ 0x2d, 0x3b, 0x64, 0x57, 0xfe, 0x14, 0x89, 0x07, 0xef, 0xcf, 0xd0, 0x16,
+ 0x5f, 0xe9, 0x4d, 0x84, 0xfe, 0xc5, 0x97, 0xdd, 0x4a, 0x0e, 0xb2, 0xff,
+ 0xa0, 0xa7, 0xe6, 0x1e, 0x37, 0x16, 0x5f, 0xff, 0x4f, 0xfc, 0xe7, 0x83,
+ 0xc8, 0x9c, 0x25, 0x0b, 0x2e, 0x8f, 0x2c, 0xbf, 0x9e, 0x61, 0xc1, 0x4e,
+ 0xb2, 0xa7, 0x47, 0x98, 0xc8, 0xf0, 0xec, 0x94, 0x77, 0x8b, 0x5f, 0xef,
+ 0x3f, 0xf8, 0x66, 0x79, 0x65, 0xf4, 0x4c, 0xde, 0x59, 0x7f, 0xa3, 0xe5,
+ 0x93, 0xb6, 0x96, 0x5e, 0xdd, 0x83, 0xac, 0xac, 0x45, 0x3b, 0x9a, 0x70,
+ 0x8b, 0x74, 0xca, 0xfc, 0x43, 0xf4, 0x49, 0x65, 0xe2, 0x8e, 0xd6, 0x5f,
+ 0x44, 0xb3, 0x8b, 0x2f, 0xf9, 0xcc, 0x10, 0x8b, 0x3a, 0x92, 0xca, 0xc3,
+ 0xf7, 0xf0, 0xe3, 0x90, 0xdf, 0x6e, 0xc1, 0x76, 0xb2, 0xfe, 0xf6, 0x1a,
+ 0xf1, 0x3a, 0xcb, 0xe8, 0x9b, 0x50, 0xb2, 0xd0, 0xb2, 0xd8, 0xb2, 0xb4,
+ 0x68, 0x0e, 0x21, 0x47, 0x3e, 0x3f, 0x21, 0x5f, 0x40, 0x45, 0x6c, 0xb2,
+ 0xfb, 0x85, 0x06, 0x2c, 0xbf, 0x0f, 0xd8, 0x52, 0x59, 0x58, 0x79, 0x2e,
+ 0x45, 0x7a, 0x4c, 0x05, 0x97, 0xff, 0xf6, 0x7f, 0x82, 0x73, 0xfe, 0x72,
+ 0x37, 0x37, 0xc1, 0x8b, 0x2f, 0xb9, 0xf6, 0x99, 0x65, 0x1d, 0x10, 0x4e,
+ 0xbf, 0x7f, 0x9b, 0x51, 0x3b, 0xeb, 0xb5, 0x97, 0x77, 0x32, 0xcb, 0x7f,
+ 0x62, 0xb7, 0xc8, 0x3e, 0x1c, 0x27, 0xb0, 0xb7, 0xb2, 0x56, 0x84, 0x8e,
+ 0x88, 0xbc, 0xdc, 0xe4, 0x1c, 0x84, 0xf7, 0xc8, 0xb6, 0xcd, 0x2f, 0xff,
+ 0x6b, 0xb2, 0xcd, 0xe5, 0x91, 0xa8, 0xe2, 0xcb, 0xff, 0x1d, 0xb3, 0xac,
+ 0x61, 0xc6, 0xea, 0xcb, 0xfc, 0xf3, 0x7b, 0x0f, 0x9c, 0x59, 0x58, 0x8b,
+ 0xdd, 0x25, 0x6f, 0x40, 0xbd, 0xb7, 0x1f, 0x59, 0x7d, 0x1b, 0xdb, 0x7a,
+ 0xcb, 0xb0, 0xeb, 0x2c, 0x6e, 0xc3, 0x76, 0xc4, 0xb5, 0x3a, 0x20, 0xc9,
+ 0x6a, 0xfc, 0x6f, 0xf3, 0x0e, 0xb2, 0xff, 0xd2, 0x93, 0x77, 0x07, 0x9b,
+ 0x90, 0xb2, 0xff, 0xf4, 0xe2, 0x79, 0xa0, 0xa7, 0x01, 0xe2, 0x4b, 0x2b,
+ 0x11, 0xae, 0xc4, 0x6e, 0x50, 0x14, 0x0b, 0xff, 0x8b, 0x0d, 0x35, 0xff,
+ 0xc6, 0x29, 0x96, 0x5e, 0xc9, 0x32, 0xca, 0x98, 0xf8, 0x34, 0x8b, 0x7b,
+ 0x27, 0x25, 0x97, 0xb0, 0x3d, 0x2c, 0xaf, 0x1b, 0x92, 0x1c, 0xbf, 0x60,
+ 0xdb, 0x5c, 0x59, 0x7e, 0x12, 0x4c, 0x0e, 0x2c, 0xbc, 0x17, 0xd2, 0xcb,
+ 0xee, 0xe3, 0x27, 0x59, 0x4c, 0x6f, 0xf4, 0x39, 0x7b, 0xff, 0xe9, 0x65,
+ 0xff, 0xdd, 0x76, 0xde, 0xd9, 0xbb, 0x9e, 0x63, 0xac, 0xa0, 0x1f, 0x4f,
+ 0xc7, 0xae, 0x0e, 0x96, 0x56, 0x23, 0x0b, 0x90, 0x89, 0xdb, 0x22, 0xa9,
+ 0xd3, 0x88, 0x39, 0x39, 0x91, 0x95, 0x5f, 0x09, 0xec, 0xed, 0x65, 0xfb,
+ 0x9f, 0x77, 0x25, 0x95, 0xd1, 0xe5, 0x18, 0x49, 0x50, 0x8a, 0x76, 0x84,
+ 0x1d, 0x43, 0x2b, 0x7f, 0x27, 0x1b, 0x9a, 0x37, 0xbf, 0x47, 0x16, 0xf0,
+ 0x9a, 0xe2, 0xe7, 0xe5, 0x27, 0xdf, 0xf8, 0x98, 0x4e, 0xb3, 0x7f, 0x50,
+ 0x22, 0xcb, 0x49, 0x65, 0xff, 0xe6, 0xcd, 0x0e, 0x0c, 0xcf, 0x47, 0x5c,
+ 0x59, 0x7c, 0x24, 0x68, 0x0b, 0x2f, 0xfd, 0x1d, 0x7b, 0xd1, 0x3c, 0x04,
+ 0xeb, 0x2f, 0xfe, 0xd6, 0x9c, 0x19, 0xe6, 0xd7, 0x9d, 0x65, 0xa4, 0xb2,
+ 0xb8, 0x7a, 0x82, 0x21, 0xdc, 0xfa, 0x59, 0x7f, 0xfe, 0x37, 0x3e, 0xdc,
+ 0xf0, 0x73, 0xe0, 0x71, 0xc2, 0xcb, 0xfb, 0xed, 0x39, 0xe3, 0xb5, 0x94,
+ 0x34, 0x4d, 0x68, 0x5b, 0xca, 0xb7, 0xd2, 0x6d, 0x49, 0x65, 0xfc, 0x09,
+ 0xa4, 0xda, 0x92, 0xc9, 0x8d, 0x15, 0xfe, 0xf6, 0x7b, 0x3b, 0x7e, 0xd6,
+ 0x5c, 0xd3, 0xac, 0xae, 0xcf, 0x2f, 0xe6, 0x95, 0xd2, 0x2b, 0xb5, 0x08,
+ 0xbb, 0xfd, 0xdc, 0xcc, 0x70, 0xbf, 0x16, 0x5f, 0x60, 0x75, 0x3a, 0xcb,
+ 0xa3, 0x71, 0x65, 0x74, 0x7e, 0x27, 0x35, 0xf1, 0x1d, 0xf6, 0xa0, 0x3b,
+ 0x8b, 0x2f, 0x40, 0xc6, 0xb2, 0xec, 0xdd, 0x59, 0x7c, 0x01, 0x0a, 0x4b,
+ 0x2c, 0xe4, 0x6f, 0x3e, 0x33, 0x7e, 0xe7, 0x30, 0x80, 0xb2, 0x80, 0x79,
+ 0x84, 0x4b, 0x50, 0xaa, 0xd1, 0xa3, 0x00, 0x78, 0x4d, 0x70, 0xc3, 0xe4,
+ 0xa1, 0x85, 0x25, 0xa6, 0x59, 0x7f, 0xc1, 0x71, 0x26, 0x96, 0x75, 0x25,
+ 0x95, 0xd1, 0xe7, 0x10, 0x95, 0xf1, 0x3f, 0x5c, 0x59, 0x7d, 0xf0, 0x1f,
+ 0x16, 0x57, 0xcf, 0x10, 0x42, 0x2a, 0x3a, 0x22, 0x40, 0xcd, 0x74, 0x71,
+ 0x65, 0xf4, 0x7a, 0x06, 0xb2, 0xbb, 0x36, 0xf3, 0x0b, 0x5f, 0xf1, 0xa3,
+ 0xf4, 0x68, 0xa2, 0x4b, 0x2f, 0xde, 0x62, 0x79, 0xd6, 0x5f, 0xf4, 0x9f,
+ 0x5f, 0x28, 0x3f, 0x16, 0x5f, 0xe8, 0x1c, 0x68, 0x30, 0x05, 0x97, 0x8b,
+ 0x3a, 0x59, 0x6e, 0x76, 0x8a, 0xd9, 0x89, 0xce, 0x70, 0x46, 0x55, 0x09,
+ 0x95, 0x1e, 0x1c, 0xd7, 0xff, 0xd1, 0x9d, 0x7f, 0xd8, 0xd2, 0x63, 0x4d,
+ 0xc5, 0x97, 0xe2, 0x8d, 0xd2, 0x85, 0x97, 0xff, 0x9d, 0xf5, 0x3f, 0x9f,
+ 0xfe, 0x6d, 0x49, 0x65, 0xfb, 0x43, 0xf3, 0x4c, 0xb2, 0xe7, 0x30, 0x67,
+ 0xe7, 0x89, 0x57, 0xfc, 0xe5, 0x9f, 0xfb, 0x19, 0xf5, 0x97, 0xff, 0xff,
+ 0x4d, 0x26, 0x2f, 0xc0, 0x37, 0x7e, 0xc6, 0xeb, 0x23, 0xa9, 0x31, 0xd6,
+ 0x54, 0x22, 0xb8, 0x8e, 0x2a, 0x15, 0xdb, 0x62, 0xd3, 0x46, 0x9b, 0xa2,
+ 0x87, 0x50, 0x28, 0x4d, 0x86, 0x1b, 0x74, 0x28, 0x6d, 0xbe, 0x21, 0x1a,
+ 0x54, 0xc0, 0x4c, 0x84, 0x21, 0xa8, 0x7d, 0x88, 0xcc, 0x95, 0xe2, 0x30,
+ 0x42, 0x53, 0x92, 0xdc, 0x7f, 0x39, 0xe7, 0x7e, 0x61, 0x02, 0xfc, 0x59,
+ 0x7f, 0xf7, 0xfa, 0x96, 0x7d, 0xb7, 0xc1, 0x76, 0xb2, 0xfe, 0x80, 0xf4,
+ 0xdd, 0x6e, 0xac, 0xbf, 0x61, 0x99, 0xd7, 0xd6, 0x56, 0xc3, 0xdb, 0x63,
+ 0x2b, 0xfd, 0xd4, 0xb0, 0x7e, 0xc9, 0xd6, 0x50, 0xd3, 0x22, 0xe8, 0xa3,
+ 0x50, 0xa2, 0x22, 0x3b, 0xf4, 0x6b, 0xa9, 0x71, 0x65, 0xff, 0xff, 0x6a,
+ 0x67, 0xf3, 0x72, 0x26, 0x6f, 0xff, 0x3c, 0x06, 0xde, 0xb2, 0xa7, 0x44,
+ 0x90, 0x4a, 0x6f, 0x6b, 0x38, 0xb2, 0xfc, 0xc5, 0xbf, 0x24, 0xb2, 0xf6,
+ 0x34, 0xeb, 0x28, 0xd3, 0xe0, 0x38, 0xe7, 0x8a, 0x2f, 0xe8, 0x9f, 0x3f,
+ 0x87, 0x59, 0x7e, 0x13, 0x67, 0xb9, 0x8b, 0x2f, 0xfe, 0xc2, 0x0f, 0x7e,
+ 0xc3, 0xcc, 0xfd, 0xac, 0xa6, 0x46, 0x76, 0x8c, 0x00, 0x5b, 0xc2, 0xbb,
+ 0xe3, 0xb4, 0x0d, 0x65, 0xfe, 0x23, 0x7d, 0x07, 0x39, 0x2c, 0xbf, 0xb7,
+ 0x1a, 0x37, 0x43, 0xf5, 0x97, 0xe8, 0x9b, 0x33, 0xb5, 0x97, 0x8b, 0x37,
+ 0x56, 0x54, 0x23, 0x37, 0x08, 0x58, 0xcf, 0xc6, 0x61, 0x28, 0xbc, 0x77,
+ 0xfa, 0xcb, 0xe3, 0xbc, 0x74, 0xb2, 0x88, 0xdf, 0x18, 0x39, 0x7f, 0xbf,
+ 0xc6, 0xdf, 0xa6, 0xe2, 0xcb, 0xfe, 0x32, 0x4d, 0xa1, 0x0a, 0x50, 0xb2,
+ 0xe6, 0x92, 0xca, 0xc4, 0x42, 0xb1, 0xa9, 0x1d, 0x5e, 0x36, 0x3b, 0x59,
+ 0x7f, 0xef, 0x64, 0xcd, 0x30, 0x77, 0x43, 0xc5, 0x97, 0x9b, 0x46, 0xac,
+ 0xbe, 0xfb, 0x47, 0x4b, 0x2a, 0x11, 0x42, 0xc3, 0xc4, 0x89, 0xc1, 0xdb,
+ 0xfe, 0x89, 0xa3, 0xfe, 0xcd, 0x76, 0xb2, 0xf7, 0xa2, 0x65, 0x96, 0x8e,
+ 0x8f, 0x5f, 0x74, 0xea, 0xa4, 0x8b, 0xce, 0x42, 0x46, 0xf1, 0x33, 0x2c,
+ 0xb9, 0xe7, 0x59, 0x7f, 0x39, 0xf3, 0x7b, 0xe9, 0x65, 0x4e, 0x78, 0xa7,
+ 0x17, 0xbf, 0xf4, 0xcd, 0xe8, 0xea, 0x51, 0x34, 0x2c, 0xa6, 0x3e, 0x30,
+ 0x91, 0xdf, 0x1e, 0x3e, 0x75, 0x97, 0xfd, 0xc0, 0xcf, 0x13, 0x6c, 0x07,
+ 0xd6, 0x5f, 0x86, 0xe5, 0x1e, 0x59, 0x7f, 0x4a, 0x3a, 0xfe, 0x79, 0x65,
+ 0xff, 0xef, 0xf1, 0x81, 0x12, 0xe6, 0x67, 0x5f, 0x59, 0x53, 0x1f, 0xc7,
+ 0x0b, 0xab, 0xa4, 0x7f, 0xf8, 0xf8, 0xc8, 0x4f, 0x5f, 0xe3, 0xc4, 0xc7,
+ 0x81, 0xc2, 0xcb, 0xf4, 0xd8, 0xdb, 0xa3, 0x59, 0x6f, 0x31, 0xef, 0x39,
+ 0x9d, 0x42, 0x7b, 0x8d, 0x19, 0x0f, 0x21, 0x2b, 0x7e, 0xce, 0xa5, 0xe6,
+ 0x59, 0x7d, 0xba, 0x41, 0x9d, 0x65, 0x6c, 0x3c, 0xe3, 0x94, 0x5f, 0xcd,
+ 0xe6, 0x99, 0xa7, 0x59, 0x68, 0x59, 0x5c, 0x37, 0xdf, 0x2e, 0xbf, 0x7d,
+ 0x8a, 0x50, 0xb2, 0xfe, 0xea, 0x58, 0x1d, 0x4e, 0xb2, 0xff, 0xf6, 0xb5,
+ 0x05, 0x86, 0xb7, 0xbd, 0x82, 0x2c, 0xac, 0x45, 0x03, 0x13, 0x04, 0xc2,
+ 0xa1, 0x35, 0x1c, 0x62, 0xd4, 0x30, 0x6f, 0xe6, 0x35, 0xbe, 0xfe, 0x59,
+ 0x7b, 0xbf, 0x42, 0xcb, 0xb5, 0x0b, 0x2a, 0x47, 0xc1, 0xd1, 0x6c, 0xc3,
+ 0xb7, 0xe8, 0x6f, 0xed, 0x42, 0xad, 0x65, 0xf9, 0xd8, 0x70, 0x4b, 0x2e,
+ 0x80, 0xac, 0xa8, 0x44, 0xf7, 0x8c, 0x48, 0xcb, 0x84, 0xb7, 0x6e, 0xc2,
+ 0xcb, 0x8b, 0xb5, 0x95, 0x06, 0xc1, 0x86, 0x6f, 0xf0, 0x58, 0xb3, 0x9c,
+ 0xc5, 0x95, 0x39, 0xe8, 0x1c, 0x7e, 0xfb, 0xc0, 0x7f, 0xac, 0xb7, 0x96,
+ 0x53, 0x9b, 0x30, 0x91, 0x5f, 0xe2, 0xcf, 0xc4, 0x83, 0xa5, 0x95, 0xbc,
+ 0xf4, 0xb7, 0x48, 0x2f, 0xfe, 0x63, 0xb7, 0x3d, 0x0d, 0xa0, 0xee, 0x2c,
+ 0xa8, 0x4c, 0x55, 0xa1, 0x50, 0xe4, 0xf7, 0xf1, 0x71, 0xb7, 0xc0, 0xd6,
+ 0x5f, 0xf0, 0x18, 0xbf, 0x1c, 0x0f, 0x96, 0x5f, 0xed, 0x4e, 0xdd, 0xb6,
+ 0xb1, 0x65, 0xe2, 0x63, 0x56, 0x5f, 0x9f, 0x5a, 0x89, 0xd6, 0x5f, 0xdf,
+ 0x6d, 0x37, 0xc2, 0xb2, 0xb6, 0x23, 0x77, 0x0e, 0x0e, 0x69, 0xf1, 0xc1,
+ 0x0a, 0x2f, 0x71, 0xc0, 0xb2, 0xa0, 0xfa, 0x3e, 0x99, 0x7e, 0x13, 0xd9,
+ 0xd7, 0x16, 0x5c, 0xfb, 0x8b, 0x28, 0x27, 0x86, 0x21, 0x55, 0xff, 0xff,
+ 0xf4, 0x7c, 0x9f, 0xb6, 0xe4, 0xcd, 0xae, 0xe3, 0x9f, 0x8e, 0xa0, 0x4c,
+ 0xe2, 0xcb, 0xfd, 0xcc, 0xd4, 0x6f, 0x8d, 0xc5, 0x95, 0xa4, 0x5b, 0x7d,
+ 0xfe, 0xff, 0x7b, 0x3a, 0x8d, 0x31, 0xd6, 0x5f, 0x7e, 0x0f, 0x0b, 0x2f,
+ 0xfd, 0x1b, 0x0e, 0x4e, 0x6b, 0x78, 0x2b, 0x2f, 0xff, 0xff, 0xfb, 0x99,
+ 0xff, 0x39, 0xf9, 0xad, 0x37, 0x5f, 0x77, 0x37, 0x32, 0x60, 0xfe, 0x0c,
+ 0xea, 0x16, 0x5f, 0x83, 0x36, 0x6d, 0xe2, 0xcb, 0xbc, 0xeb, 0x2b, 0x88,
+ 0xd8, 0xfc, 0x25, 0xf7, 0x95, 0xdf, 0xf7, 0x5c, 0x26, 0x3f, 0xf3, 0x71,
+ 0x65, 0xd9, 0xa5, 0x95, 0x07, 0xa5, 0xe3, 0xcb, 0xfb, 0xe4, 0xe0, 0xc2,
+ 0x59, 0x74, 0x1a, 0xb2, 0xf9, 0xc1, 0x84, 0xb2, 0xa6, 0x36, 0xe4, 0x2f,
+ 0x5b, 0x11, 0x07, 0xf6, 0x2a, 0x85, 0x5c, 0x23, 0x23, 0xc3, 0x3e, 0xc8,
+ 0x5e, 0x31, 0x8f, 0xc2, 0x24, 0x30, 0xa4, 0xbf, 0xd2, 0x7e, 0x9b, 0x75,
+ 0x86, 0xb2, 0xff, 0xdf, 0x6e, 0x13, 0xfe, 0x67, 0x1a, 0xcb, 0xe0, 0x3f,
+ 0x5c, 0x59, 0x71, 0x86, 0x2c, 0xae, 0x1b, 0xc3, 0x08, 0xef, 0xbc, 0xf9,
+ 0xe4, 0x82, 0xcd, 0x15, 0xff, 0xf8, 0x46, 0x38, 0x79, 0x02, 0x31, 0xe2,
+ 0x68, 0x31, 0x65, 0xcd, 0x3a, 0xca, 0x84, 0xdd, 0x30, 0xd9, 0xa1, 0x38,
+ 0xe6, 0x7b, 0xd6, 0x2f, 0xc2, 0x61, 0xdb, 0x4b, 0x2f, 0xcd, 0xaf, 0xe7,
+ 0x6b, 0x2f, 0xdd, 0xb7, 0x3c, 0xcb, 0x2f, 0xee, 0x9a, 0x73, 0xb7, 0x16,
+ 0x5c, 0x77, 0x59, 0x7f, 0xbf, 0x05, 0xde, 0xd0, 0x03, 0xac, 0xa8, 0x3f,
+ 0xef, 0x17, 0x84, 0x5a, 0xe6, 0xe9, 0x65, 0xef, 0x40, 0x16, 0x5e, 0xdd,
+ 0xdd, 0x85, 0x97, 0xfc, 0x3f, 0x36, 0x9b, 0xa9, 0xa1, 0x65, 0x39, 0xee,
+ 0x04, 0x8a, 0xed, 0xaf, 0x7a, 0xca, 0xc4, 0xfc, 0x8d, 0x28, 0xe8, 0xa1,
+ 0xa1, 0x4d, 0xa2, 0xe7, 0x17, 0x27, 0x8f, 0x90, 0xde, 0xf6, 0xcd, 0xc5,
+ 0x97, 0x8b, 0xb6, 0x59, 0x7e, 0xf4, 0x16, 0x4e, 0xb2, 0xa0, 0xf9, 0x58,
+ 0x89, 0xc7, 0x2f, 0xcd, 0x3b, 0x84, 0x96, 0x5f, 0xd1, 0xf0, 0x9c, 0x3f,
+ 0x59, 0x7f, 0xa0, 0xbc, 0xe0, 0x0c, 0xcb, 0x2b, 0xc7, 0xc3, 0xba, 0x5d,
+ 0x50, 0xdc, 0xa3, 0x4f, 0x0d, 0x59, 0x46, 0xa4, 0x38, 0xc2, 0x72, 0x10,
+ 0xa6, 0xc2, 0x9b, 0xa8, 0xe2, 0x98, 0xa3, 0x72, 0x18, 0x53, 0x47, 0xfb,
+ 0xa8, 0xf6, 0x4f, 0x19, 0x97, 0xa3, 0xd0, 0x73, 0x30, 0x46, 0xe6, 0x2b,
+ 0x64, 0x29, 0x77, 0x5c, 0x8f, 0xa3, 0xf2, 0x90, 0x37, 0xc3, 0x68, 0x42,
+ 0xcd, 0xd8, 0x44, 0x5f, 0x6b, 0x3f, 0x8b, 0x2f, 0xf7, 0x7e, 0x6f, 0xf1,
+ 0xfa, 0x59, 0x7b, 0x35, 0xbd, 0x65, 0xed, 0x09, 0x32, 0xcb, 0x8f, 0xe5,
+ 0x94, 0xc6, 0xdb, 0x83, 0xf7, 0xfe, 0x20, 0x1d, 0xe4, 0x51, 0xfe, 0x2c,
+ 0xbb, 0x31, 0x65, 0xf7, 0x7e, 0x61, 0x16, 0x56, 0x26, 0x80, 0x69, 0x0b,
+ 0x1a, 0xf9, 0x51, 0xc8, 0x05, 0x67, 0xa2, 0x0a, 0xdf, 0xa6, 0x89, 0xbd,
+ 0x0b, 0x2f, 0xff, 0x17, 0xf8, 0x27, 0xd8, 0x83, 0x2c, 0xe2, 0xcb, 0x84,
+ 0x85, 0x97, 0xf7, 0xb2, 0x67, 0x29, 0xd6, 0x5e, 0x30, 0xc3, 0x12, 0x5f,
+ 0x4b, 0xf9, 0xda, 0x41, 0x66, 0x82, 0xfd, 0x83, 0x60, 0x71, 0x77, 0x7f,
+ 0x2b, 0x62, 0x2d, 0xf4, 0x9c, 0x46, 0xb7, 0x72, 0x4b, 0x2f, 0x71, 0xc0,
+ 0xb2, 0xa0, 0xd9, 0xf4, 0x2f, 0x7b, 0x0f, 0xb6, 0xb2, 0xa1, 0x3e, 0x5c,
+ 0x29, 0xd2, 0x53, 0xc3, 0x38, 0x0c, 0x84, 0x43, 0x7c, 0x71, 0xe1, 0x2c,
+ 0xbb, 0xfc, 0x59, 0x7f, 0xf8, 0x79, 0x86, 0xec, 0xcf, 0xb7, 0x3c, 0xcb,
+ 0x2f, 0xf7, 0xfd, 0x1f, 0xe7, 0x99, 0x65, 0xcf, 0x25, 0x97, 0xed, 0x99,
+ 0x33, 0x4e, 0xb2, 0xb6, 0x1f, 0xa1, 0xcc, 0xf8, 0x2d, 0x6e, 0x2c, 0xbf,
+ 0xdf, 0xea, 0x5e, 0x82, 0x9d, 0x25, 0xff, 0xb3, 0xa9, 0x36, 0x11, 0x60,
+ 0xd6, 0x5f, 0x1c, 0x3d, 0x7d, 0x65, 0xf6, 0x7a, 0x37, 0xac, 0xa9, 0xcf,
+ 0x1f, 0x84, 0x95, 0x09, 0xf9, 0xce, 0x2f, 0xd4, 0x2f, 0xf4, 0x62, 0x42,
+ 0x3c, 0x35, 0xfc, 0x20, 0xef, 0xf7, 0x7e, 0x61, 0xc3, 0xe9, 0x65, 0xe6,
+ 0xe3, 0x2c, 0xb3, 0x2c, 0xbe, 0x71, 0x1c, 0x6b, 0x2f, 0x46, 0x8d, 0x59,
+ 0x69, 0x78, 0xfa, 0x9c, 0x6c, 0x22, 0x06, 0x11, 0x5f, 0xff, 0xe1, 0xfb,
+ 0x3f, 0xf7, 0x2e, 0xf9, 0x1a, 0x79, 0x9b, 0xcb, 0x28, 0x69, 0xa0, 0x75,
+ 0x09, 0xd6, 0x42, 0xbf, 0xe2, 0x83, 0x38, 0xc5, 0xd4, 0x96, 0x5f, 0xff,
+ 0xfb, 0x80, 0x6d, 0x0f, 0x0b, 0xcd, 0xdf, 0x9b, 0xe6, 0xc1, 0x49, 0x65,
+ 0xd1, 0xda, 0xca, 0x24, 0x5e, 0x7c, 0xe7, 0x7b, 0x65, 0xe1, 0x23, 0x71,
+ 0x65, 0xde, 0x65, 0x96, 0x02, 0xca, 0x34, 0xd3, 0x90, 0xb5, 0x4e, 0x7d,
+ 0x0c, 0x8f, 0x7f, 0xdf, 0xf3, 0x40, 0x27, 0xe1, 0xab, 0x2f, 0xc5, 0x06,
+ 0x61, 0x2c, 0xbf, 0xef, 0x75, 0x06, 0xcd, 0x28, 0xdc, 0x59, 0x6e, 0x0c,
+ 0xf9, 0x70, 0x9a, 0xb4, 0x8e, 0x92, 0x22, 0xfc, 0x28, 0x29, 0x65, 0xfa,
+ 0x5a, 0x68, 0x3a, 0xcb, 0xc2, 0x74, 0x62, 0xca, 0x9c, 0xf4, 0xba, 0x0b,
+ 0xe1, 0x3d, 0x42, 0xe6, 0xd6, 0x47, 0x5e, 0xd0, 0xf2, 0x78, 0xe0, 0x83,
+ 0x08, 0x6b, 0xcc, 0x08, 0x59, 0x7d, 0x2c, 0xfb, 0x2c, 0xad, 0x86, 0xf3,
+ 0xa1, 0xbb, 0xfd, 0x2f, 0x47, 0x5f, 0x8f, 0x2c, 0xbf, 0xfd, 0x2f, 0x87,
+ 0xda, 0x83, 0x24, 0xc0, 0xc5, 0x97, 0x39, 0xd6, 0x57, 0x68, 0xb9, 0xe8,
+ 0x90, 0x8d, 0x37, 0xa5, 0xdf, 0xff, 0xbe, 0xfa, 0xc6, 0x07, 0x33, 0xcd,
+ 0xaf, 0x3a, 0xcb, 0xfe, 0xf3, 0x6a, 0x62, 0x88, 0xe9, 0x65, 0xe8, 0x21,
+ 0xac, 0xbf, 0x75, 0xc9, 0xb3, 0xeb, 0x2b, 0x13, 0x11, 0xe9, 0x01, 0x94,
+ 0xfc, 0x72, 0x43, 0x77, 0xf3, 0x7c, 0x9c, 0x1c, 0x59, 0x7e, 0x83, 0xff,
+ 0x3c, 0xb2, 0xf8, 0x48, 0x29, 0x96, 0x5f, 0x71, 0xa3, 0xb5, 0x97, 0xff,
+ 0x4d, 0x9a, 0xc7, 0x3c, 0x79, 0x86, 0xb2, 0xb0, 0xf9, 0x7e, 0x45, 0x7f,
+ 0x04, 0xf9, 0xee, 0x9d, 0x65, 0x1a, 0x99, 0x57, 0x65, 0x9e, 0x27, 0x28,
+ 0x44, 0x70, 0x86, 0xff, 0xf3, 0x0c, 0x9f, 0xa2, 0xcf, 0xe3, 0x01, 0x65,
+ 0xf4, 0xf3, 0xbe, 0xe2, 0xcb, 0xee, 0xc6, 0x19, 0xd6, 0x5e, 0x97, 0x02,
+ 0xb2, 0xfe, 0x2f, 0xb7, 0xa4, 0x4b, 0x2f, 0xff, 0xff, 0xde, 0x8c, 0x9e,
+ 0x4d, 0xfe, 0x46, 0xb0, 0x5b, 0x02, 0x23, 0x7c, 0x41, 0x76, 0xb2, 0xdf,
+ 0xc4, 0x79, 0x78, 0x95, 0xc7, 0x78, 0x59, 0x78, 0xc3, 0x0c, 0x59, 0x7f,
+ 0xfc, 0x7c, 0xeb, 0xe5, 0x93, 0x9f, 0x0f, 0x84, 0x90, 0x59, 0xa0, 0xa8,
+ 0x46, 0x13, 0x30, 0xdf, 0x4f, 0x9e, 0x75, 0x97, 0xfb, 0x44, 0xe6, 0x67,
+ 0x9d, 0x65, 0xff, 0xbf, 0x1f, 0xe6, 0x3e, 0xbd, 0x8b, 0x2f, 0xde, 0x7d,
+ 0x66, 0x96, 0x5f, 0xfd, 0x39, 0x06, 0x70, 0xf3, 0xfc, 0xc3, 0x16, 0x5f,
+ 0xba, 0xed, 0x8a, 0x75, 0x97, 0xfb, 0xd1, 0x29, 0xa4, 0xe4, 0xb2, 0xbe,
+ 0x7b, 0xa2, 0x15, 0x54, 0x23, 0x21, 0xe1, 0x4b, 0x70, 0x5d, 0x65, 0x0d,
+ 0x39, 0xac, 0x32, 0xec, 0xf7, 0xd0, 0xef, 0x22, 0x6b, 0xfe, 0x01, 0x67,
+ 0x6d, 0x9f, 0xe2, 0xcb, 0xdf, 0x81, 0xac, 0xbe, 0x97, 0xc2, 0x35, 0x97,
+ 0xe8, 0x69, 0x3f, 0x16, 0x54, 0x1f, 0x2f, 0x43, 0x9a, 0x23, 0xbf, 0xb3,
+ 0xfe, 0x0c, 0x74, 0xb2, 0xfb, 0xed, 0xac, 0x59, 0x7d, 0xd7, 0x18, 0xd1,
+ 0x9e, 0x7e, 0x17, 0x54, 0xe9, 0xd2, 0x69, 0x3c, 0xa1, 0x3b, 0xf7, 0xeb,
+ 0xfd, 0x9c, 0x2c, 0xdf, 0xe6, 0x59, 0x7f, 0xe3, 0xc7, 0x45, 0x80, 0xe4,
+ 0x6e, 0x2c, 0xad, 0x1f, 0xa1, 0xcc, 0xef, 0xf0, 0xcb, 0x37, 0xb6, 0x9d,
+ 0x65, 0x0a, 0x17, 0x1b, 0x22, 0x5b, 0x03, 0x42, 0xdc, 0x24, 0x57, 0xe9,
+ 0xf7, 0x1b, 0x3a, 0x59, 0x7e, 0x6e, 0x44, 0xe7, 0x5d, 0x9f, 0xab, 0xf4,
+ 0x3e, 0x80, 0x15, 0xd9, 0xfa, 0xb9, 0xe4, 0xbb, 0x3f, 0x57, 0xc1, 0x96,
+ 0x71, 0x76, 0x7e, 0xa8, 0x67, 0xa4, 0x44, 0x77, 0xe8, 0xce, 0x61, 0x2e,
+ 0xcf, 0xd5, 0x2e, 0xcf, 0xd5, 0xcf, 0xf5, 0xd9, 0xfa, 0x39, 0x71, 0x69,
+ 0x11, 0xfe, 0x05, 0x2a, 0xfb, 0x36, 0xd8, 0x0b, 0xb3, 0xf5, 0x4b, 0xb3,
+ 0xf5, 0x70, 0x21, 0x76, 0x7e, 0xaf, 0xfb, 0x00, 0xfa, 0xcd, 0xf8, 0x35,
+ 0xd9, 0xfa, 0xbf, 0xb3, 0xcd, 0xc0, 0xce, 0xbb, 0x3f, 0x54, 0x04, 0x52,
+ 0x11, 0x1f, 0x11, 0xaf, 0xb5, 0x3c, 0x7d, 0x76, 0x7e, 0xa9, 0x76, 0x7e,
+ 0xb0, 0xd8, 0x5c, 0x61, 0x8b, 0xb3, 0xf5, 0x52, 0x56, 0x30, 0x33, 0x5c,
+ 0x84, 0x37, 0x50, 0x9d, 0xd1, 0x39, 0xcc, 0x79, 0x0b, 0xcf, 0xaf, 0x98,
+ 0x4f, 0x74, 0x1a, 0x9b, 0x3f, 0x41, 0x68, 0x90, 0xbf, 0xe9, 0xe3, 0x7e,
+ 0x36, 0xb2, 0x75, 0x97, 0xff, 0x3f, 0xbb, 0xf3, 0x13, 0xe9, 0xe4, 0xb2,
+ 0xa4, 0x8b, 0x7d, 0x1c, 0xfc, 0xee, 0xfe, 0x8c, 0x12, 0x25, 0x25, 0x97,
+ 0xfb, 0x99, 0x29, 0x47, 0xfa, 0x59, 0x7f, 0xd1, 0xa0, 0x7d, 0x9c, 0xd9,
+ 0x2c, 0xac, 0x46, 0x51, 0x18, 0x70, 0xb4, 0x43, 0x4b, 0xff, 0x67, 0x63,
+ 0xcd, 0x18, 0xfe, 0x99, 0x65, 0x2c, 0xbf, 0xf1, 0x64, 0xd1, 0x38, 0x1f,
+ 0xae, 0x2c, 0xa8, 0x3c, 0xbe, 0x05, 0xdd, 0x29, 0xd2, 0x5f, 0x4c, 0xef,
+ 0xa5, 0x95, 0x3a, 0x64, 0x7d, 0x1e, 0x7a, 0x11, 0x84, 0x43, 0xba, 0x31,
+ 0x7c, 0x51, 0x37, 0x16, 0x5c, 0xd3, 0xac, 0xad, 0x2f, 0x82, 0xbc, 0xf3,
+ 0xc1, 0x2a, 0x7c, 0x8a, 0xed, 0xb3, 0x56, 0x5f, 0xdc, 0x28, 0xf0, 0x74,
+ 0xb2, 0xfe, 0xe1, 0x67, 0xf0, 0x0b, 0x2b, 0xa3, 0xd9, 0x39, 0x6d, 0xff,
+ 0x4c, 0x59, 0xbf, 0xdd, 0x3e, 0xe2, 0xcb, 0xfb, 0xf9, 0xe8, 0xd0, 0x16,
+ 0x5f, 0x69, 0xb3, 0x7a, 0xcb, 0xf6, 0x73, 0x3a, 0xfa, 0xcb, 0xe3, 0xc1,
+ 0x1b, 0xb0, 0xf2, 0xdc, 0x8e, 0xff, 0xb4, 0xc7, 0xe0, 0x91, 0x93, 0x2c,
+ 0xbf, 0xee, 0xe0, 0x03, 0x0b, 0xea, 0x4b, 0x2f, 0xfc, 0xef, 0x3e, 0x1d,
+ 0xcb, 0xa9, 0x2c, 0xbc, 0xe6, 0xf3, 0x0f, 0xe2, 0x63, 0xab, 0xfd, 0xff,
+ 0x61, 0xc4, 0x80, 0x2c, 0xbf, 0x6d, 0x46, 0xe9, 0xfb, 0x59, 0x6f, 0x6c,
+ 0x3e, 0x3d, 0xa6, 0x69, 0x7f, 0xfa, 0x39, 0x87, 0x8e, 0xdf, 0x06, 0xdb,
+ 0xd6, 0x56, 0x1f, 0xd1, 0x18, 0x58, 0xcd, 0x8a, 0xa5, 0x71, 0xe3, 0x47,
+ 0x45, 0x0b, 0x2f, 0xc6, 0x23, 0x5b, 0x15, 0xe4, 0xc3, 0xa6, 0x11, 0xbc,
+ 0xad, 0x4b, 0xe6, 0x35, 0x8c, 0x59, 0x7d, 0xff, 0x64, 0xeb, 0x28, 0xe7,
+ 0x8c, 0x44, 0x77, 0x0c, 0xc5, 0x97, 0xf8, 0x62, 0x6f, 0x77, 0x2e, 0xd6,
+ 0x54, 0x1f, 0x7e, 0x10, 0xb0, 0xc5, 0xe3, 0x83, 0x4b, 0x2e, 0xf9, 0x2c,
+ 0xbf, 0x3f, 0xf6, 0xf3, 0x8b, 0x2f, 0x10, 0x3b, 0x59, 0x43, 0x3d, 0xdf,
+ 0x0b, 0x70, 0xaa, 0xff, 0xf7, 0x5f, 0xf3, 0x08, 0x3c, 0xc2, 0xe3, 0x2c,
+ 0xbf, 0xff, 0x4b, 0x51, 0xbd, 0xe6, 0x81, 0xfa, 0x0e, 0xf3, 0x2c, 0xbf,
+ 0xdb, 0xaf, 0xc6, 0xe4, 0xd8, 0xb2, 0xff, 0xf4, 0x68, 0x19, 0xbd, 0xbf,
+ 0x18, 0x52, 0x59, 0x5b, 0x13, 0xca, 0x16, 0xf5, 0x85, 0xfd, 0x25, 0x69,
+ 0x60, 0x43, 0x6b, 0x7d, 0x65, 0xfb, 0x39, 0xc3, 0xf4, 0xb2, 0xe8, 0xeb,
+ 0x61, 0xba, 0x81, 0x1b, 0xcc, 0x52, 0x59, 0x50, 0xe8, 0x54, 0x67, 0x59,
+ 0x94, 0xf7, 0x76, 0x4a, 0x65, 0x68, 0xdc, 0xf7, 0x14, 0x66, 0x47, 0xd4,
+ 0x7b, 0x7e, 0x9c, 0x8d, 0x79, 0xf5, 0x32, 0x9c, 0x0f, 0xe4, 0x3e, 0x83,
+ 0x1f, 0xb1, 0x90, 0x97, 0xdd, 0x2e, 0xbf, 0x78, 0xf1, 0xb4, 0x62, 0xcb,
+ 0xfd, 0xdc, 0x7f, 0xd1, 0xbf, 0x16, 0x5d, 0x3e, 0x2c, 0xb7, 0x78, 0x79,
+ 0x80, 0x35, 0xa5, 0x96, 0x7d, 0x1b, 0x33, 0x94, 0x5f, 0xd8, 0x79, 0x9d,
+ 0xe4, 0xb2, 0xff, 0xfe, 0x7f, 0x44, 0x85, 0xe0, 0x22, 0x5c, 0x1f, 0xa3,
+ 0x4b, 0x2c, 0xc3, 0x44, 0x4f, 0x8b, 0x6f, 0xfc, 0x6c, 0x74, 0x51, 0xef,
+ 0x07, 0xb5, 0x97, 0xff, 0x6a, 0x30, 0xb2, 0x4d, 0xec, 0xde, 0xb2, 0xfb,
+ 0x34, 0xc6, 0xac, 0xbf, 0x79, 0xb9, 0x12, 0x59, 0x7f, 0xf9, 0xcd, 0xe6,
+ 0x6f, 0x8e, 0xbf, 0xc0, 0x9d, 0x65, 0x39, 0xfa, 0x91, 0x3d, 0x0d, 0x1f,
+ 0x47, 0x43, 0x28, 0x4b, 0xdf, 0xfc, 0x58, 0x77, 0x96, 0xd8, 0x46, 0xde,
+ 0x59, 0x7f, 0x8a, 0x3f, 0xd4, 0xce, 0x75, 0x97, 0xef, 0x87, 0xf8, 0x35,
+ 0x96, 0xc5, 0x94, 0xe6, 0xe3, 0x79, 0x45, 0xff, 0xde, 0xce, 0x73, 0x36,
+ 0x75, 0x2c, 0xfa, 0xca, 0x92, 0x63, 0x67, 0x46, 0x26, 0xcf, 0x91, 0x5f,
+ 0xb4, 0x07, 0xc0, 0x2c, 0xbf, 0xb3, 0x75, 0xbe, 0xd2, 0x59, 0x7d, 0xe8,
+ 0x9f, 0x98, 0x7a, 0xde, 0x27, 0xbf, 0x89, 0xcd, 0xf3, 0xc9, 0x65, 0xff,
+ 0x8e, 0x59, 0xf2, 0x8e, 0xda, 0x4b, 0x2f, 0xff, 0xef, 0xc7, 0x8b, 0x3f,
+ 0xe6, 0xd8, 0x7c, 0xfb, 0xfd, 0x65, 0x2c, 0xa6, 0x3e, 0x6d, 0x2d, 0xd3,
+ 0x23, 0x11, 0xe1, 0x47, 0x7e, 0xef, 0x0f, 0x1c, 0x59, 0x78, 0xc3, 0x0c,
+ 0x49, 0x78, 0x48, 0x02, 0x41, 0x66, 0x82, 0xff, 0x9e, 0x42, 0x6b, 0x37,
+ 0xbe, 0x96, 0x5b, 0x4b, 0x2f, 0xf1, 0x44, 0x8d, 0xd6, 0x71, 0x65, 0xff,
+ 0x88, 0xb2, 0x79, 0xa5, 0x1a, 0x9d, 0x65, 0xef, 0x64, 0xa1, 0x10, 0x98,
+ 0x22, 0x21, 0x9d, 0x12, 0x3f, 0xff, 0x0b, 0xfb, 0xfc, 0x52, 0x63, 0xe7,
+ 0x5f, 0x59, 0x7d, 0xd7, 0x6c, 0x4b, 0x29, 0xcf, 0x5b, 0xe6, 0x74, 0xb2,
+ 0xe0, 0x44, 0x8d, 0x60, 0xac, 0x86, 0xfd, 0xb2, 0x3b, 0xcd, 0x2c, 0xbf,
+ 0xff, 0xe6, 0xff, 0x9e, 0x42, 0xf3, 0xcf, 0xd0, 0x3e, 0x50, 0x7e, 0x2c,
+ 0xbf, 0xf6, 0xc8, 0x20, 0x9e, 0x0c, 0x8e, 0x2c, 0xb6, 0x0d, 0x1a, 0x5e,
+ 0x2a, 0x26, 0x8b, 0xfe, 0xfb, 0x96, 0x73, 0x51, 0xc5, 0x97, 0xd2, 0x80,
+ 0x74, 0xb2, 0xff, 0xff, 0x3b, 0x7e, 0x24, 0xda, 0x9c, 0x20, 0xdb, 0xdb,
+ 0xc1, 0xb2, 0xcb, 0xff, 0xfe, 0x7d, 0xed, 0xbc, 0x83, 0xc1, 0x0a, 0x07,
+ 0xe7, 0x96, 0x71, 0x65, 0xfc, 0x08, 0x2c, 0xeb, 0xeb, 0x2e, 0x70, 0x6c,
+ 0x4c, 0x7f, 0xc4, 0x64, 0xcc, 0x23, 0x4d, 0xff, 0xe1, 0x0a, 0x63, 0x5c,
+ 0x7e, 0xce, 0xf3, 0x4b, 0x29, 0x95, 0x92, 0x7a, 0x30, 0x27, 0x34, 0x28,
+ 0xd5, 0xb8, 0x97, 0x7b, 0xf2, 0x65, 0x97, 0xb7, 0xc6, 0x96, 0x5e, 0x0e,
+ 0x79, 0x65, 0x4e, 0xcb, 0x32, 0x94, 0x2b, 0xc6, 0x51, 0x91, 0x9d, 0xb4,
+ 0x69, 0xf3, 0x42, 0x4c, 0xe7, 0x3e, 0x87, 0x8b, 0x93, 0x01, 0x20, 0xa3,
+ 0x2e, 0xfc, 0xbc, 0xd0, 0xaa, 0xef, 0x1c, 0x30, 0x7a, 0xe6, 0x9d, 0x65,
+ 0xfe, 0x2e, 0xc6, 0xdb, 0xe0, 0x6b, 0x28, 0x67, 0x98, 0x11, 0x7b, 0xff,
+ 0xec, 0x6d, 0x7a, 0x1b, 0xfc, 0x62, 0xea, 0x4b, 0x2f, 0xec, 0xef, 0xfb,
+ 0x79, 0xe5, 0x94, 0xb2, 0xbc, 0x6f, 0x00, 0x63, 0x7f, 0xf4, 0xde, 0x89,
+ 0xc4, 0xff, 0x82, 0xf2, 0x59, 0x7e, 0x34, 0x32, 0x71, 0xac, 0xbf, 0xd1,
+ 0xb9, 0xb3, 0xcf, 0x9a, 0x59, 0x7b, 0x35, 0x0b, 0x2f, 0xbd, 0xec, 0xe9,
+ 0x65, 0xd8, 0x7d, 0xb3, 0x7c, 0x20, 0xdd, 0x62, 0x29, 0x49, 0xd6, 0xdb,
+ 0x8b, 0x2d, 0x32, 0xcb, 0x1d, 0x65, 0x31, 0xa3, 0x71, 0x2a, 0x34, 0xf5,
+ 0x8e, 0x6f, 0x7e, 0xc0, 0x72, 0x24, 0xb2, 0xfc, 0xc7, 0x18, 0xf1, 0x65,
+ 0x80, 0x47, 0x9d, 0xb6, 0x4f, 0x7f, 0xdf, 0xf6, 0x73, 0x67, 0xda, 0x75,
+ 0x97, 0xf6, 0x4d, 0x9a, 0x1b, 0x2c, 0xa8, 0x44, 0x9b, 0x15, 0x11, 0xe5,
+ 0xff, 0x13, 0x04, 0x57, 0xcd, 0xb8, 0xfa, 0xcb, 0xfc, 0x0d, 0x36, 0x78,
+ 0x3c, 0x59, 0x7b, 0x3a, 0x3a, 0xcb, 0xfb, 0x01, 0xbb, 0xf6, 0x3a, 0xca,
+ 0x84, 0x40, 0x11, 0x9f, 0xc7, 0x6f, 0xfe, 0x7f, 0xe8, 0x26, 0xe7, 0xd8,
+ 0x1c, 0x59, 0x79, 0xf4, 0x05, 0x95, 0x3a, 0xe5, 0xbc, 0xa1, 0x14, 0x32,
+ 0x16, 0x48, 0x9a, 0x19, 0xc7, 0x77, 0xf4, 0x60, 0x84, 0x5b, 0xf8, 0x5f,
+ 0x98, 0x5d, 0xb6, 0x8b, 0x7d, 0x9f, 0x12, 0x75, 0x97, 0xe2, 0x86, 0xea,
+ 0x4b, 0x2f, 0x18, 0x61, 0x89, 0x88, 0x40, 0xbe, 0xed, 0xdf, 0xb4, 0xc4,
+ 0x20, 0x0b, 0x35, 0xd7, 0xcf, 0xac, 0x31, 0x65, 0x68, 0xf9, 0x77, 0xa1,
+ 0xde, 0x30, 0xc3, 0x13, 0x10, 0x79, 0x49, 0x88, 0x3c, 0x16, 0x6b, 0xaf,
+ 0xef, 0xb9, 0xcf, 0x07, 0x59, 0x7e, 0x7f, 0xb9, 0x01, 0x65, 0xfd, 0x9f,
+ 0xf0, 0x5e, 0x4b, 0x2f, 0x18, 0x61, 0x8b, 0x2f, 0x72, 0x0d, 0x48, 0x2c,
+ 0xd0, 0x54, 0x2a, 0x06, 0xc8, 0x5d, 0x76, 0xa5, 0xd1, 0x5f, 0x8b, 0x48,
+ 0x9b, 0xe9, 0xb5, 0xb8, 0xaa, 0x50, 0xf2, 0x8a, 0xaf, 0x19, 0x04, 0xb2,
+ 0xff, 0xff, 0xe8, 0x29, 0xf9, 0xe7, 0x39, 0xde, 0x42, 0x16, 0xfc, 0x1e,
+ 0x75, 0xf5, 0x97, 0xff, 0x7a, 0x24, 0xdf, 0xcf, 0x77, 0x07, 0x59, 0x50,
+ 0x98, 0x23, 0x97, 0xf0, 0x73, 0x7b, 0xad, 0xff, 0xbc, 0xd3, 0x13, 0x99,
+ 0xfc, 0xf2, 0xcb, 0xa3, 0x8b, 0x2b, 0xb3, 0xd5, 0xf9, 0xfd, 0xff, 0xbc,
+ 0xc3, 0x82, 0xfe, 0x75, 0xf5, 0x97, 0xf8, 0xa0, 0xfc, 0xe0, 0x49, 0x65,
+ 0x76, 0x7e, 0x1c, 0x3e, 0xbf, 0xfb, 0xcd, 0xaf, 0x3e, 0x71, 0x9e, 0x75,
+ 0x97, 0xfe, 0x8f, 0xe6, 0xb3, 0x99, 0xd7, 0xd6, 0x56, 0x22, 0x04, 0x90,
+ 0xef, 0xfd, 0x39, 0xf0, 0xf8, 0x5f, 0xce, 0xd6, 0x5f, 0x47, 0xe0, 0xeb,
+ 0x2f, 0xf6, 0x13, 0x1b, 0xb3, 0xbf, 0x2c, 0xa1, 0x42, 0x7d, 0xdd, 0x42,
+ 0x4c, 0xf0, 0xa4, 0x22, 0x1f, 0x9f, 0x98, 0x43, 0x7f, 0xde, 0x82, 0xef,
+ 0xae, 0x3e, 0xe2, 0xcb, 0xdb, 0xb1, 0x3a, 0xcb, 0xe2, 0x0c, 0xe4, 0xb2,
+ 0xf3, 0x75, 0x25, 0x95, 0x23, 0x7e, 0x02, 0x2b, 0xf8, 0x7c, 0xc3, 0xc6,
+ 0xe2, 0xcb, 0xc1, 0x71, 0x16, 0x5d, 0x3f, 0x4b, 0x2c, 0xe3, 0x36, 0xc0,
+ 0x1d, 0xa9, 0x26, 0x92, 0x33, 0xde, 0x97, 0xdc, 0x84, 0xc6, 0x6b, 0xfd,
+ 0xcf, 0x67, 0x3f, 0x9d, 0xac, 0xbf, 0x17, 0xfd, 0x92, 0x59, 0x79, 0xa0,
+ 0xd5, 0x94, 0xc7, 0xee, 0xe6, 0x84, 0x4f, 0x7f, 0xd8, 0x51, 0xef, 0x41,
+ 0x8c, 0xb2, 0xfb, 0xbf, 0x31, 0x8b, 0x2f, 0x09, 0x00, 0x59, 0x7f, 0xff,
+ 0xff, 0xdb, 0x0b, 0x0d, 0x6f, 0x7b, 0x37, 0x36, 0x47, 0x6e, 0x26, 0xcc,
+ 0x29, 0xdb, 0x4c, 0x11, 0x5e, 0x2c, 0xa9, 0xd3, 0x45, 0x34, 0xb3, 0xa3,
+ 0x73, 0x92, 0x18, 0x3b, 0x7e, 0xee, 0x3d, 0x07, 0x49, 0x7e, 0x27, 0x22,
+ 0xc4, 0x97, 0x67, 0x69, 0x2e, 0x30, 0xc4, 0x95, 0x87, 0xf9, 0xc2, 0x8f,
+ 0x92, 0x18, 0x2f, 0x7f, 0x88, 0x48, 0x07, 0xb3, 0x75, 0x20, 0xb3, 0x79,
+ 0x7f, 0xfa, 0x71, 0xe9, 0xfb, 0x2c, 0xdf, 0xa6, 0xe2, 0xca, 0x85, 0xd5,
+ 0x4c, 0x8e, 0xc1, 0xa5, 0x04, 0x3c, 0x60, 0xe1, 0x48, 0xbf, 0xfb, 0xd0,
+ 0x0f, 0xfb, 0x25, 0xe6, 0xde, 0xb2, 0xff, 0xe8, 0x07, 0x33, 0x06, 0xe4,
+ 0xe6, 0xac, 0xbf, 0xef, 0xf1, 0xfa, 0x68, 0xeb, 0xeb, 0x2f, 0xf8, 0x81,
+ 0xe7, 0xff, 0xd8, 0x0b, 0x2f, 0xff, 0xde, 0x6d, 0xec, 0x43, 0xe4, 0x69,
+ 0xb3, 0xae, 0x2c, 0xbf, 0xd9, 0xbe, 0x0b, 0xf2, 0x15, 0xac, 0xbf, 0xdd,
+ 0xb7, 0x30, 0x72, 0x15, 0xac, 0xbf, 0xd9, 0x85, 0x12, 0x90, 0xad, 0x65,
+ 0xfc, 0x51, 0x9a, 0x70, 0x2c, 0xbf, 0xf4, 0x6b, 0xd0, 0xde, 0x82, 0x65,
+ 0x97, 0x4b, 0x98, 0x9c, 0xcf, 0x67, 0x1a, 0x56, 0xf1, 0xc1, 0x1c, 0x7c,
+ 0xd4, 0xc2, 0xbb, 0xfd, 0x05, 0x87, 0x6e, 0xa4, 0xb2, 0xff, 0x7a, 0x32,
+ 0x51, 0x80, 0x59, 0x7f, 0xf8, 0xb3, 0xa0, 0x3f, 0x1f, 0x4d, 0xd0, 0x16,
+ 0x50, 0xcf, 0xef, 0x86, 0x35, 0x25, 0x62, 0x7d, 0x47, 0xa7, 0xf7, 0x13,
+ 0x21, 0x5b, 0x7f, 0xbf, 0xe7, 0x91, 0x41, 0xd6, 0x5f, 0x7f, 0x81, 0xe2,
+ 0xca, 0x92, 0xe1, 0xe7, 0x91, 0x9e, 0x5a, 0xa9, 0x26, 0x70, 0xca, 0xf6,
+ 0xf1, 0x0e, 0xb2, 0xfb, 0xd3, 0xe1, 0x8b, 0x2f, 0x86, 0x12, 0x92, 0xcb,
+ 0x71, 0xcf, 0x18, 0x42, 0x4b, 0xf7, 0x63, 0xc7, 0x02, 0xcb, 0x0a, 0xb5,
+ 0x97, 0xfe, 0xce, 0x7e, 0x58, 0x69, 0x60, 0x16, 0x5e, 0x1e, 0x12, 0xca,
+ 0x14, 0x9f, 0x83, 0x8b, 0xee, 0x9f, 0x53, 0x23, 0x34, 0x30, 0x98, 0xbe,
+ 0x6f, 0x1d, 0xd6, 0x5f, 0xf8, 0xc1, 0xea, 0x3c, 0xe3, 0x91, 0xd6, 0x5f,
+ 0xff, 0xbf, 0xce, 0xb6, 0x0f, 0x07, 0x0f, 0xac, 0x20, 0x2c, 0xbf, 0xff,
+ 0xf6, 0xcf, 0xcb, 0x01, 0xb7, 0x9b, 0x07, 0x83, 0x87, 0xd6, 0x10, 0x10,
+ 0x85, 0xff, 0xd9, 0xfd, 0x9d, 0xf9, 0xbd, 0xe6, 0x02, 0xa1, 0x0b, 0x54,
+ 0x91, 0x93, 0xc7, 0x5b, 0xd1, 0x38, 0xbe, 0x26, 0x87, 0xf8, 0xc8, 0x2f,
+ 0xb3, 0xb7, 0xed, 0x65, 0xf8, 0xfc, 0x31, 0xfa, 0x59, 0x43, 0x44, 0x5f,
+ 0xcf, 0x84, 0x23, 0xa8, 0x54, 0xc1, 0xd1, 0x0f, 0x25, 0x07, 0x5f, 0xd9,
+ 0x34, 0x9b, 0x5c, 0x59, 0x7e, 0x9e, 0x3e, 0xd3, 0x2c, 0xbe, 0x13, 0x91,
+ 0x8b, 0x2b, 0xb3, 0xcb, 0xe8, 0xa6, 0xfb, 0x9b, 0x35, 0x8b, 0x2f, 0xbd,
+ 0xdb, 0x71, 0x65, 0x41, 0xf5, 0xb9, 0x27, 0xc9, 0x2f, 0xff, 0xf8, 0x41,
+ 0xfa, 0x25, 0xfc, 0xc3, 0x38, 0x59, 0xff, 0xb4, 0xeb, 0x2d, 0x8b, 0x2c,
+ 0xf3, 0x9f, 0xc6, 0xf6, 0x8b, 0xcc, 0x58, 0xb2, 0xfd, 0xad, 0x38, 0x21,
+ 0x65, 0x48, 0xf0, 0x5c, 0x6a, 0x85, 0x2e, 0xa4, 0xda, 0x29, 0x7b, 0xa3,
+ 0x8d, 0x17, 0x27, 0x36, 0x5a, 0x71, 0x33, 0x53, 0xfa, 0xaf, 0x39, 0x30,
+ 0x05, 0x21, 0x5b, 0x31, 0x43, 0xd7, 0x92, 0xa1, 0xfe, 0x72, 0x18, 0x72,
+ 0x19, 0x0a, 0x51, 0x1a, 0xee, 0xda, 0xf6, 0x85, 0x97, 0x8c, 0x30, 0xc4,
+ 0x97, 0x9c, 0x86, 0x90, 0x59, 0xa0, 0xbe, 0xcd, 0x67, 0xd6, 0x50, 0x0f,
+ 0x3b, 0x85, 0xb7, 0xde, 0x67, 0x92, 0xcb, 0xfc, 0x59, 0xef, 0x94, 0x01,
+ 0x65, 0xff, 0xe1, 0x08, 0xb2, 0x78, 0xea, 0x52, 0x83, 0xac, 0xbc, 0x51,
+ 0x25, 0x97, 0xda, 0xd3, 0x1d, 0x65, 0xb8, 0x33, 0x7a, 0xc3, 0x75, 0x24,
+ 0x57, 0x7e, 0x11, 0x17, 0x8f, 0x38, 0xd6, 0x54, 0xe9, 0x92, 0x94, 0x37,
+ 0xfe, 0x51, 0x7e, 0xd6, 0x77, 0x1e, 0x59, 0x7b, 0x61, 0xbb, 0x6b, 0x2f,
+ 0x7d, 0xc6, 0xb2, 0xb4, 0x6f, 0xf8, 0x47, 0x7f, 0xa3, 0xbf, 0x41, 0x64,
+ 0xcb, 0x2f, 0xf1, 0xbd, 0x7f, 0x51, 0x9d, 0x2c, 0xbe, 0x03, 0x68, 0xd4,
+ 0x97, 0xda, 0xd3, 0x4e, 0xb2, 0xdd, 0xc1, 0xe3, 0x39, 0x1d, 0xfc, 0x26,
+ 0x6b, 0x32, 0x65, 0x97, 0xe7, 0xf6, 0xc1, 0xc2, 0xca, 0x92, 0xb5, 0x31,
+ 0x91, 0x64, 0x68, 0xc6, 0x9b, 0x33, 0x3e, 0x88, 0x5c, 0xcc, 0x9f, 0x38,
+ 0x4f, 0xf2, 0xeb, 0xf3, 0xeb, 0x59, 0xd2, 0xcb, 0xff, 0xdf, 0xf3, 0x38,
+ 0x33, 0x43, 0x82, 0x92, 0xcb, 0xff, 0xdd, 0x6c, 0xe8, 0x10, 0x5d, 0xbc,
+ 0xe4, 0xeb, 0x2a, 0x11, 0x7d, 0x85, 0x04, 0x91, 0x7e, 0x8e, 0x08, 0x52,
+ 0x59, 0x7b, 0xb6, 0x92, 0xcb, 0xfd, 0x1f, 0x7d, 0x6b, 0x3a, 0x59, 0x5b,
+ 0x0f, 0x43, 0xc3, 0xb7, 0xfe, 0xef, 0x35, 0x8d, 0xcf, 0x46, 0xf5, 0x97,
+ 0xfe, 0x7e, 0x9c, 0x6f, 0xd6, 0x98, 0xd5, 0x97, 0xe8, 0xdd, 0x9f, 0x0c,
+ 0x59, 0x7f, 0xff, 0xf3, 0xb7, 0xdb, 0xdd, 0xb6, 0xc9, 0x37, 0x9c, 0xbf,
+ 0x2c, 0xd6, 0x2c, 0xbb, 0x3c, 0xb2, 0xec, 0xdd, 0x59, 0x53, 0x1a, 0xff,
+ 0x0b, 0x57, 0x91, 0x84, 0xf0, 0xa0, 0xbf, 0x30, 0x1c, 0x80, 0xb2, 0xff,
+ 0x47, 0x5c, 0x8f, 0xc0, 0xd6, 0x50, 0x0f, 0x64, 0x89, 0xaf, 0x70, 0x4e,
+ 0x6c, 0x45, 0x0e, 0x42, 0x02, 0x86, 0xa9, 0xbf, 0xa2, 0x43, 0xa0, 0x79,
+ 0x03, 0xf1, 0xc7, 0xdd, 0xc9, 0x2c, 0xbf, 0xed, 0x44, 0x9b, 0xec, 0x52,
+ 0x59, 0x7f, 0xff, 0xff, 0xd1, 0xc8, 0xfc, 0xf8, 0x66, 0xb3, 0xce, 0x27,
+ 0x30, 0xd7, 0x20, 0x41, 0x44, 0xde, 0x85, 0x97, 0xfa, 0x4d, 0xbc, 0x43,
+ 0xe4, 0xeb, 0x2f, 0xdc, 0xf3, 0xf7, 0x0b, 0x2f, 0xcf, 0x39, 0x8f, 0x25,
+ 0x95, 0x09, 0xa9, 0x91, 0xbf, 0xe1, 0x28, 0x61, 0xb8, 0x85, 0x17, 0xfd,
+ 0xcf, 0x43, 0xeb, 0x59, 0xd2, 0xcb, 0xff, 0xff, 0x1b, 0xd4, 0xbf, 0x85,
+ 0xfe, 0x6c, 0xe7, 0x33, 0x58, 0x4f, 0x25, 0x95, 0x88, 0xa8, 0x63, 0x9b,
+ 0xe0, 0x7f, 0x27, 0x59, 0x63, 0xac, 0xa8, 0x36, 0x87, 0x23, 0xbf, 0xf8,
+ 0x58, 0xca, 0x03, 0xde, 0x1a, 0xda, 0x59, 0x7b, 0x4f, 0xc5, 0x97, 0x61,
+ 0x8b, 0x2a, 0x0f, 0xe8, 0x68, 0xfc, 0x1c, 0xbe, 0x87, 0xd7, 0x16, 0x5e,
+ 0xff, 0xa1, 0x65, 0x61, 0xf5, 0xf8, 0xb9, 0xc8, 0x6f, 0xde, 0x82, 0x7f,
+ 0x2c, 0xbf, 0xa7, 0xf3, 0xff, 0x50, 0xb2, 0xf4, 0xb3, 0x8b, 0x2f, 0x47,
+ 0x5c, 0x59, 0x7f, 0x87, 0xe8, 0x99, 0xdf, 0xa5, 0x97, 0xee, 0xb8, 0x12,
+ 0x92, 0xcb, 0xde, 0x06, 0xf5, 0x95, 0x3a, 0x2d, 0x46, 0x39, 0xa1, 0xd2,
+ 0x34, 0xdd, 0x29, 0xb9, 0xa7, 0x59, 0x7b, 0xa7, 0xdc, 0x59, 0x5a, 0x36,
+ 0xfe, 0x17, 0xbe, 0x8d, 0xb6, 0x35, 0x65, 0x49, 0x50, 0x00, 0xcb, 0x74,
+ 0x4c, 0xf0, 0xe3, 0x28, 0x42, 0x7c, 0x86, 0xff, 0xfe, 0x37, 0xfe, 0x67,
+ 0x06, 0x14, 0x75, 0xcc, 0xeb, 0xeb, 0x2f, 0xfe, 0xcd, 0x00, 0xed, 0xc1,
+ 0x39, 0x18, 0xb2, 0xf4, 0x75, 0xb8, 0xb2, 0xfb, 0x84, 0xc6, 0xac, 0xad,
+ 0x1e, 0x17, 0xc8, 0x2f, 0xb0, 0x6f, 0x25, 0x94, 0x33, 0xc3, 0x34, 0x8a,
+ 0xff, 0xe3, 0x4c, 0x8d, 0x7a, 0x19, 0xff, 0xc5, 0x97, 0xc7, 0x28, 0x99,
+ 0x65, 0xff, 0xf7, 0x9a, 0x4d, 0xa7, 0x07, 0xca, 0x0f, 0xc5, 0x97, 0xdf,
+ 0x8d, 0x02, 0x0f, 0xc3, 0xb2, 0x2b, 0xb7, 0x38, 0xb2, 0xff, 0xb9, 0xdf,
+ 0x9c, 0x7b, 0x58, 0xa4, 0x50, 0xb2, 0x8d, 0x44, 0xdb, 0x9c, 0xfc, 0x6a,
+ 0xa1, 0x56, 0x44, 0x97, 0x32, 0x19, 0x2c, 0x46, 0xf1, 0xa8, 0x5e, 0xda,
+ 0x88, 0x0b, 0x2f, 0xd0, 0x21, 0x3c, 0x96, 0x5f, 0xfe, 0xd3, 0x97, 0xf0,
+ 0x1b, 0x70, 0x31, 0xc2, 0xcb, 0xff, 0x8a, 0x00, 0x30, 0xc4, 0xf1, 0xd4,
+ 0x96, 0x5f, 0xd2, 0xd4, 0x49, 0xf4, 0xb2, 0xec, 0x3a, 0xcb, 0xdf, 0x83,
+ 0x16, 0x5e, 0xf0, 0x9a, 0x59, 0x52, 0x37, 0x7f, 0x1d, 0xbf, 0xe0, 0xe8,
+ 0xd7, 0x6e, 0x36, 0xf5, 0x97, 0xed, 0x00, 0xed, 0xc5, 0x97, 0xd8, 0x40,
+ 0xd9, 0xb6, 0x7c, 0x62, 0x1d, 0xdf, 0x3f, 0x65, 0x8b, 0x2f, 0xe6, 0xf3,
+ 0x67, 0x5f, 0x59, 0x43, 0x4d, 0x87, 0xa5, 0x13, 0xc2, 0x10, 0x8f, 0xbe,
+ 0x43, 0x4b, 0x2f, 0x81, 0xfc, 0x02, 0xcb, 0xee, 0x71, 0xb7, 0xac, 0xbf,
+ 0xff, 0x61, 0x1a, 0xfc, 0xf3, 0xb0, 0x0f, 0x1d, 0x49, 0x65, 0x41, 0xfc,
+ 0xf6, 0x49, 0x7c, 0x72, 0x28, 0x59, 0x7f, 0xcc, 0x3f, 0x44, 0xb3, 0xaf,
+ 0xac, 0xbf, 0xee, 0xe3, 0x7c, 0x71, 0x81, 0xd2, 0xcb, 0x9c, 0xd8, 0x44,
+ 0xa8, 0xc8, 0x30, 0xe6, 0xfd, 0xf7, 0xf8, 0x61, 0x65, 0xff, 0xfd, 0xe6,
+ 0xff, 0x9e, 0x42, 0x0d, 0xe7, 0x1f, 0x98, 0xeb, 0x2f, 0xfc, 0xdf, 0x96,
+ 0x03, 0x85, 0x80, 0x59, 0x43, 0x5c, 0xed, 0xc2, 0x73, 0x52, 0xfa, 0x45,
+ 0x68, 0xe3, 0xa6, 0x50, 0xd0, 0x5f, 0xa1, 0x36, 0x50, 0xb7, 0xe1, 0xd0,
+ 0x49, 0xf7, 0xae, 0xde, 0xdb, 0xea, 0x16, 0x5f, 0xef, 0x14, 0x74, 0xd1,
+ 0xe5, 0x97, 0xf3, 0xfc, 0x02, 0x14, 0x96, 0x57, 0x67, 0xc1, 0xe3, 0x2a,
+ 0xda, 0xdb, 0x83, 0xa8, 0x97, 0xc5, 0x28, 0xd3, 0x86, 0x5b, 0x92, 0xb9,
+ 0xcd, 0x53, 0x68, 0xda, 0xb5, 0x0f, 0x83, 0xaa, 0xbc, 0xb0, 0x52, 0x96,
+ 0x53, 0xc5, 0x30, 0xce, 0x87, 0x6d, 0xc2, 0xe8, 0x48, 0x40, 0x5f, 0xf9,
+ 0xd8, 0x61, 0xff, 0x27, 0xc3, 0x16, 0x5d, 0xb5, 0x12, 0xcb, 0xf7, 0x30,
+ 0xd8, 0xe2, 0xcb, 0xf6, 0xde, 0x13, 0x9a, 0xb2, 0xfd, 0xd1, 0xdc, 0x80,
+ 0xb2, 0xb6, 0x1e, 0x94, 0x15, 0x5f, 0xdb, 0x9c, 0x62, 0xea, 0x4b, 0x2f,
+ 0xfc, 0xfa, 0xdb, 0x6f, 0x63, 0xf4, 0x05, 0x97, 0xf0, 0x04, 0x2f, 0x67,
+ 0x4b, 0x2f, 0xff, 0xcd, 0xf8, 0x3e, 0x75, 0xf8, 0x38, 0x9a, 0x70, 0x2c,
+ 0xbe, 0x62, 0x71, 0xac, 0xbf, 0xee, 0x46, 0xbf, 0x02, 0xc6, 0xcb, 0x2a,
+ 0x48, 0xb0, 0x1a, 0xb7, 0x08, 0x2f, 0xff, 0xec, 0xf6, 0xcc, 0x3b, 0x7a,
+ 0x36, 0x73, 0x98, 0x40, 0x59, 0x7f, 0xf3, 0x6a, 0x25, 0xe8, 0x98, 0x82,
+ 0x6a, 0xca, 0xf2, 0x28, 0xb8, 0xbb, 0x7f, 0xe9, 0xe2, 0x62, 0x8e, 0x64,
+ 0x49, 0x65, 0xdd, 0xed, 0xac, 0xbf, 0x8d, 0xfc, 0x7a, 0x38, 0xb2, 0xff,
+ 0xb8, 0x59, 0xfe, 0x46, 0xa7, 0x59, 0x7f, 0x79, 0xba, 0xe3, 0xf4, 0xb2,
+ 0xff, 0x60, 0xf3, 0x52, 0x8d, 0x2c, 0xbd, 0xe6, 0xfa, 0xca, 0x84, 0xcf,
+ 0x64, 0x7c, 0xc3, 0x73, 0x17, 0x00, 0xe7, 0x85, 0xe2, 0x19, 0x5f, 0x9f,
+ 0xd9, 0xd7, 0xd6, 0x5f, 0xf9, 0xff, 0xc8, 0xc2, 0x1f, 0xa1, 0x65, 0xf7,
+ 0x7e, 0x80, 0xac, 0xaf, 0x1e, 0xff, 0xcf, 0x2f, 0xfc, 0xe5, 0x39, 0x98,
+ 0x43, 0xf4, 0x2c, 0xb9, 0xa7, 0x59, 0x58, 0x7a, 0xa4, 0x7d, 0x7f, 0x83,
+ 0xd4, 0xb8, 0x24, 0x6e, 0x2c, 0xbd, 0xdc, 0x6e, 0x2c, 0xbf, 0xd3, 0x79,
+ 0xf5, 0xa6, 0x1a, 0xca, 0xc3, 0xd4, 0x72, 0x0b, 0xfc, 0xfd, 0x09, 0xa6,
+ 0x3e, 0x2c, 0xbf, 0x9c, 0xa7, 0x3b, 0xfd, 0x65, 0x11, 0xf0, 0xf0, 0xd2,
+ 0xf9, 0xbc, 0xe7, 0x59, 0x7f, 0xc4, 0x59, 0x3f, 0xff, 0x07, 0x59, 0x52,
+ 0x55, 0x4d, 0x90, 0x87, 0x99, 0xdf, 0x44, 0x05, 0x08, 0xde, 0x42, 0x07,
+ 0xe4, 0x22, 0x10, 0xdf, 0xb5, 0x9c, 0x63, 0x16, 0x5f, 0x1e, 0x35, 0xc5,
+ 0x97, 0xff, 0xa0, 0x7e, 0x09, 0xa2, 0x40, 0xfc, 0x1e, 0x2c, 0xb6, 0xe0,
+ 0xcf, 0xbc, 0x42, 0x2b, 0xb2, 0x75, 0x95, 0x07, 0x87, 0x85, 0x97, 0xfe,
+ 0x20, 0xc8, 0x1e, 0x86, 0x29, 0xd6, 0x5c, 0x2a, 0x3a, 0xcb, 0xff, 0xff,
+ 0xef, 0xc1, 0x77, 0x85, 0x06, 0x7c, 0xd7, 0xe0, 0xe1, 0xf5, 0xe3, 0x1c,
+ 0x6b, 0x2f, 0xb0, 0xf1, 0xb8, 0xb2, 0xff, 0xfc, 0xe3, 0x09, 0xa1, 0x10,
+ 0x2e, 0x24, 0xdb, 0x01, 0xf5, 0x95, 0x09, 0x8d, 0x30, 0xdf, 0x1f, 0x82,
+ 0x49, 0x7f, 0x09, 0x01, 0xec, 0x27, 0x59, 0x73, 0x12, 0xcb, 0xe9, 0x41,
+ 0x76, 0xb2, 0x86, 0x6d, 0xf0, 0x56, 0xd3, 0x2c, 0xbe, 0x14, 0xbc, 0x74,
+ 0xb2, 0xd0, 0x46, 0xe3, 0xe2, 0x55, 0xb0, 0xff, 0x59, 0x62, 0xfa, 0x01,
+ 0x84, 0xb2, 0xa4, 0xcb, 0x62, 0x1b, 0xd6, 0x11, 0xf6, 0x63, 0xd2, 0x0b,
+ 0x43, 0x7e, 0x68, 0x69, 0x6a, 0x36, 0x03, 0xcb, 0x0b, 0x78, 0x41, 0x02,
+ 0x1b, 0x44, 0x41, 0xc8, 0xd6, 0x02, 0x78, 0x64, 0x39, 0x36, 0xc8, 0xef,
+ 0x8f, 0xb4, 0xc5, 0x4d, 0xa1, 0x65, 0xdf, 0xe2, 0xca, 0x63, 0xca, 0x98,
+ 0xce, 0xf8, 0x48, 0x33, 0x8b, 0x2e, 0x07, 0xd6, 0x5c, 0x0f, 0x2c, 0xbe,
+ 0xd6, 0xb3, 0x8b, 0x2e, 0xc9, 0x96, 0x5a, 0x5b, 0x11, 0x17, 0x39, 0x21,
+ 0xc5, 0xdc, 0x5c, 0x42, 0x2b, 0xef, 0xb9, 0x62, 0xcb, 0xed, 0xd8, 0x29,
+ 0x2c, 0xa6, 0x3c, 0x41, 0x08, 0x2f, 0x89, 0xff, 0xc5, 0x97, 0xed, 0x0f,
+ 0x30, 0x96, 0x5f, 0x1b, 0xa7, 0x31, 0x65, 0xff, 0x9b, 0x3d, 0x1b, 0xf9,
+ 0xe8, 0xe9, 0x65, 0x61, 0xf2, 0x6e, 0x12, 0x5f, 0xdd, 0x68, 0x3d, 0x7e,
+ 0x4b, 0x2f, 0xf9, 0xfa, 0x33, 0x08, 0x7e, 0x85, 0x97, 0x44, 0xeb, 0x2b,
+ 0x13, 0x50, 0x72, 0x1e, 0x42, 0x28, 0x24, 0x86, 0x18, 0x88, 0x73, 0x7e,
+ 0x33, 0xff, 0xc9, 0xd6, 0x5f, 0xcf, 0x00, 0xce, 0xa4, 0xb2, 0x96, 0x5f,
+ 0xe2, 0xd6, 0x73, 0x1b, 0xcb, 0x28, 0x52, 0x6f, 0x30, 0x2e, 0xff, 0xfa,
+ 0x5f, 0x2c, 0x7f, 0x96, 0x7f, 0xf8, 0x62, 0xcb, 0xfb, 0x4d, 0xff, 0x64,
+ 0x96, 0x5e, 0xf4, 0x6f, 0x59, 0x5a, 0x3c, 0xbf, 0x96, 0xdc, 0xfb, 0xab,
+ 0x2f, 0xf7, 0xf3, 0x53, 0xc7, 0xf8, 0xb2, 0xa4, 0x79, 0xae, 0x33, 0x7f,
+ 0xfd, 0x83, 0x6f, 0xe1, 0xfd, 0x11, 0xd9, 0xdd, 0x65, 0xd9, 0xbd, 0x65,
+ 0xff, 0x77, 0xec, 0x19, 0xdb, 0x58, 0xb2, 0xfe, 0x8e, 0x7a, 0x08, 0xd5,
+ 0x95, 0x08, 0xcc, 0x9d, 0x3b, 0x06, 0x34, 0x73, 0x7b, 0x6f, 0x0d, 0x59,
+ 0x7f, 0x44, 0x6b, 0xd1, 0xbd, 0x65, 0xf3, 0x14, 0xdb, 0x8b, 0x2f, 0x8a,
+ 0x3a, 0x92, 0xca, 0x01, 0xe3, 0xfc, 0x96, 0xfe, 0x8d, 0xf9, 0xef, 0x42,
+ 0xcb, 0xef, 0xf3, 0x26, 0x59, 0xe3, 0x5d, 0x7f, 0x78, 0x6d, 0xbe, 0x06,
+ 0xb2, 0xb0, 0xf8, 0x9c, 0xce, 0xfb, 0x4c, 0xf3, 0xac, 0xbc, 0xd8, 0x05,
+ 0x95, 0x86, 0xf7, 0x84, 0x57, 0xf9, 0x83, 0xaf, 0x66, 0xfe, 0x2c, 0xbf,
+ 0xff, 0xd9, 0xf6, 0xea, 0x45, 0x1b, 0x3e, 0xd9, 0xba, 0x3f, 0x62, 0xcb,
+ 0xec, 0xfb, 0x71, 0x65, 0xfd, 0xb5, 0x4c, 0x5b, 0x44, 0xe1, 0x59, 0x5b,
+ 0x88, 0xf4, 0x98, 0xd7, 0x8c, 0x9f, 0x21, 0xbf, 0xf0, 0x5c, 0xfc, 0x62,
+ 0x7d, 0x1a, 0xb2, 0xa4, 0xbf, 0xdc, 0x38, 0xdc, 0xb1, 0x74, 0xd2, 0xae,
+ 0xda, 0x7a, 0x24, 0x68, 0x4c, 0xcc, 0xdf, 0xa8, 0x76, 0x9c, 0xf3, 0xc4,
+ 0x00, 0x75, 0x28, 0x59, 0x71, 0x77, 0xf1, 0x8a, 0x18, 0x83, 0x7d, 0xff,
+ 0xb4, 0x96, 0x5f, 0xd8, 0x61, 0x6f, 0xd4, 0x96, 0x5f, 0xff, 0xbe, 0xdc,
+ 0x9f, 0x0c, 0xe3, 0x4e, 0x4f, 0xd7, 0xd6, 0x5f, 0xf4, 0xb3, 0xf8, 0x36,
+ 0x20, 0x2c, 0xbc, 0x66, 0x79, 0x65, 0xfd, 0x9a, 0xd0, 0x4d, 0xd2, 0xcb,
+ 0xf8, 0xa4, 0x63, 0xfb, 0x8b, 0x2f, 0xc6, 0xf9, 0xc9, 0x96, 0x5b, 0x98,
+ 0x7a, 0xac, 0x5d, 0x7d, 0xa1, 0x20, 0xc5, 0x97, 0xc3, 0x27, 0x35, 0x65,
+ 0xff, 0xcd, 0x27, 0xd6, 0x6f, 0xeb, 0xb6, 0xe9, 0x65, 0x42, 0x23, 0xa7,
+ 0x24, 0xf9, 0x15, 0xf3, 0x73, 0x07, 0x0a, 0x99, 0xa7, 0x22, 0xc3, 0x0e,
+ 0x96, 0x1c, 0xdc, 0x87, 0x7f, 0x08, 0x41, 0x21, 0x69, 0x7f, 0x80, 0x1e,
+ 0x31, 0x75, 0x25, 0x97, 0xf0, 0x1b, 0x4d, 0xd0, 0x16, 0x59, 0xf7, 0x0f,
+ 0x8a, 0x63, 0x4b, 0x01, 0x65, 0xfe, 0x1e, 0x13, 0x19, 0xe0, 0xac, 0xbf,
+ 0xfe, 0xf3, 0x47, 0xd8, 0x11, 0x21, 0x66, 0x18, 0x62, 0x4b, 0xff, 0x9a,
+ 0x3e, 0x08, 0x90, 0xb3, 0x0c, 0x31, 0x25, 0x62, 0x27, 0x7c, 0xa9, 0x53,
+ 0xa3, 0xcb, 0xf0, 0xd0, 0xbf, 0xde, 0x0b, 0x9c, 0x6e, 0x75, 0x94, 0x47,
+ 0xb9, 0xf2, 0x9b, 0xd9, 0x86, 0xa4, 0xbe, 0xe6, 0x40, 0x16, 0x50, 0xcd,
+ 0xef, 0xc7, 0x2f, 0x01, 0xfe, 0xb2, 0xfb, 0xfc, 0x0e, 0xe2, 0xca, 0x73,
+ 0xc2, 0x08, 0xe5, 0xff, 0x69, 0xfb, 0xd9, 0xe8, 0x10, 0x96, 0x5e, 0x0c,
+ 0x69, 0x65, 0xdf, 0xe0, 0xcf, 0x62, 0x63, 0xcb, 0xe3, 0x42, 0x0e, 0x2c,
+ 0xb8, 0x82, 0xa8, 0x86, 0x57, 0xf4, 0x1e, 0x39, 0xac, 0x59, 0x52, 0x3c,
+ 0xf9, 0x88, 0xef, 0x7a, 0x27, 0x59, 0x7e, 0xfc, 0x48, 0xd3, 0xac, 0xbf,
+ 0xc1, 0x2e, 0xfd, 0x1d, 0x6e, 0xac, 0xbc, 0x61, 0x86, 0x24, 0xbd, 0x85,
+ 0xda, 0x41, 0x66, 0x82, 0xff, 0xd9, 0x3e, 0x0d, 0xe4, 0x51, 0x3a, 0xca,
+ 0x84, 0x76, 0xb1, 0x48, 0x16, 0x08, 0xba, 0xff, 0xf6, 0x6b, 0xff, 0xce,
+ 0x14, 0x66, 0xa4, 0xb2, 0xfc, 0xde, 0xf6, 0x7d, 0x65, 0xa3, 0x61, 0xf7,
+ 0xf1, 0x22, 0xfb, 0xce, 0x46, 0xac, 0xa1, 0x9e, 0x5f, 0xca, 0x6f, 0xee,
+ 0xa5, 0xc2, 0x7e, 0xd6, 0x5f, 0x3e, 0xe7, 0xf8, 0xb2, 0xf1, 0x0a, 0xa1,
+ 0x42, 0xca, 0xc3, 0xfa, 0xe8, 0xbd, 0xc9, 0x6e, 0x15, 0x42, 0xa9, 0x65,
+ 0xfa, 0x5d, 0xe7, 0x5f, 0x59, 0x7e, 0xcf, 0xfc, 0x33, 0xac, 0xbf, 0xf3,
+ 0x4f, 0xe6, 0x79, 0x7d, 0xa7, 0x59, 0x69, 0x0a, 0xa4, 0x5a, 0xc8, 0x8c,
+ 0x8a, 0xbe, 0x53, 0x7e, 0xe6, 0x0d, 0xfc, 0xb2, 0xf8, 0x7e, 0xce, 0xd6,
+ 0x5e, 0x7d, 0xc8, 0x59, 0x7e, 0xc1, 0xf9, 0xf7, 0x16, 0x5f, 0x8b, 0x07,
+ 0x07, 0x59, 0x5b, 0x42, 0xfe, 0xdc, 0x46, 0xbf, 0x3a, 0xf0, 0xd8, 0xf1,
+ 0xe4, 0xd2, 0xfe, 0x9c, 0xe6, 0x23, 0xd4, 0x61, 0x47, 0x87, 0xa7, 0xa1,
+ 0x38, 0xf0, 0xe3, 0x02, 0x41, 0x13, 0x84, 0x8f, 0x78, 0xf1, 0x85, 0x57,
+ 0xf1, 0xf1, 0xb5, 0x34, 0x96, 0x5f, 0xff, 0x1a, 0x23, 0x97, 0x9e, 0x5c,
+ 0xc3, 0xc6, 0xe2, 0xca, 0x84, 0x40, 0xb1, 0x75, 0xf4, 0x7c, 0x22, 0x2c,
+ 0xbd, 0xf6, 0x85, 0x97, 0x61, 0x2c, 0xa6, 0x36, 0x01, 0x1b, 0xbf, 0x14,
+ 0x75, 0x1c, 0x59, 0x7f, 0xec, 0x62, 0x7f, 0xf0, 0xc8, 0x25, 0x97, 0xbc,
+ 0xfa, 0x83, 0xe3, 0xe1, 0x3d, 0xf3, 0x6a, 0x3e, 0xb2, 0xfb, 0x99, 0x12,
+ 0x59, 0x43, 0x3c, 0x22, 0x21, 0xbd, 0xec, 0xe9, 0x65, 0xf8, 0x7a, 0x68,
+ 0x3a, 0xcb, 0x44, 0x8f, 0x10, 0x87, 0x6f, 0xa4, 0xd1, 0xda, 0xcb, 0xba,
+ 0x02, 0xcb, 0xf8, 0xf1, 0xc0, 0x37, 0x6b, 0x2f, 0x72, 0x0d, 0x01, 0xe3,
+ 0x70, 0x62, 0xfe, 0x2c, 0xdd, 0x68, 0x99, 0x65, 0xfd, 0x9a, 0x00, 0x18,
+ 0x96, 0x53, 0x9e, 0xd8, 0x4b, 0xef, 0xe2, 0xfb, 0x4e, 0x50, 0xb2, 0xdc,
+ 0x59, 0x76, 0xd1, 0x3a, 0xca, 0x83, 0xda, 0x91, 0x63, 0x88, 0xdf, 0xe6,
+ 0x1e, 0xb0, 0x6e, 0x75, 0x97, 0xd3, 0x72, 0x38, 0xb2, 0xd8, 0x73, 0xd5,
+ 0x01, 0x95, 0xf6, 0x1c, 0x41, 0xac, 0xbf, 0x1b, 0x34, 0x17, 0xd6, 0x57,
+ 0x8f, 0xcc, 0x89, 0xc2, 0x47, 0x7f, 0xff, 0xdb, 0xe0, 0x6c, 0x4f, 0xa3,
+ 0x49, 0xd8, 0xb0, 0x01, 0xe2, 0xcb, 0xff, 0x78, 0x4e, 0x66, 0xbb, 0x77,
+ 0xed, 0x51, 0x06, 0x2f, 0xfe, 0x9e, 0x0d, 0xcd, 0x7f, 0xf1, 0x9c, 0x59,
+ 0x43, 0x44, 0x99, 0x27, 0x54, 0x26, 0x34, 0xd0, 0xf8, 0xbf, 0xf7, 0x82,
+ 0xe6, 0xe7, 0xff, 0x9e, 0x59, 0x7f, 0xb7, 0xc1, 0x60, 0x98, 0x75, 0x97,
+ 0xfb, 0xd0, 0x5f, 0x03, 0xfd, 0x65, 0xff, 0xe9, 0x6a, 0x25, 0xdf, 0x9b,
+ 0xc4, 0xe7, 0x59, 0x5c, 0x3f, 0xc0, 0x99, 0x5f, 0xff, 0xc7, 0x82, 0xed,
+ 0xc8, 0x18, 0x3e, 0x10, 0x5e, 0x4b, 0x2f, 0xfb, 0xb6, 0x39, 0xdb, 0x67,
+ 0x02, 0xb2, 0xff, 0xdc, 0x03, 0xf5, 0xc1, 0x35, 0xe7, 0x59, 0x7f, 0x3f,
+ 0xb0, 0x8f, 0x8b, 0x2f, 0x83, 0xec, 0xed, 0x65, 0x49, 0x52, 0xe0, 0xc9,
+ 0xd8, 0xff, 0x50, 0xb0, 0x39, 0x11, 0x2c, 0xfc, 0xf3, 0x7a, 0x0e, 0xd9,
+ 0x5d, 0xff, 0xdf, 0xe4, 0xf0, 0x21, 0x47, 0x9a, 0x75, 0x97, 0xfb, 0x91,
+ 0xa9, 0x76, 0xd3, 0xac, 0xbe, 0xf3, 0x38, 0x16, 0x51, 0x22, 0x73, 0x88,
+ 0xdf, 0x35, 0xbf, 0xff, 0xed, 0x69, 0xe5, 0xc1, 0xfb, 0x3b, 0xcd, 0x73,
+ 0xaf, 0x88, 0x75, 0x97, 0xf0, 0x4d, 0x2c, 0x9c, 0x2b, 0x2a, 0x11, 0x93,
+ 0x85, 0xfe, 0x6b, 0xbf, 0xff, 0x17, 0xc3, 0xe1, 0x3e, 0xc4, 0xfd, 0x7c,
+ 0x30, 0xb2, 0xf7, 0x83, 0xb8, 0xb2, 0xff, 0xcc, 0x5f, 0xe3, 0x0c, 0x1d,
+ 0x01, 0x65, 0xff, 0xcf, 0xbf, 0x0b, 0xbf, 0x30, 0x04, 0xfa, 0xca, 0x9d,
+ 0x10, 0xda, 0x3f, 0xa8, 0x56, 0x77, 0x28, 0xfb, 0x58, 0xb8, 0x56, 0xac,
+ 0x18, 0x53, 0x5e, 0xc2, 0x35, 0x65, 0xfe, 0x71, 0xfb, 0x33, 0xaf, 0xac,
+ 0xac, 0x3c, 0xf3, 0x47, 0x2b, 0xa6, 0x4d, 0x47, 0xa1, 0x1e, 0x4f, 0x7c,
+ 0x87, 0xaf, 0xe7, 0xb7, 0xf7, 0x61, 0x51, 0x78, 0xa0, 0xc5, 0x97, 0xcd,
+ 0xdb, 0x0d, 0x65, 0x61, 0xbe, 0xf8, 0xe5, 0xff, 0xee, 0xbf, 0x0c, 0x5f,
+ 0xd4, 0x7d, 0xfe, 0xb2, 0xfa, 0x3e, 0xd3, 0x2c, 0xbf, 0x82, 0xe2, 0x05,
+ 0xc4, 0x59, 0x53, 0x1e, 0x8e, 0x88, 0xae, 0xdf, 0x8b, 0x2b, 0x0d, 0xdb,
+ 0x91, 0xdf, 0xfc, 0xf2, 0xd9, 0x9f, 0xcf, 0x46, 0x80, 0xb2, 0xe0, 0x01,
+ 0x65, 0xff, 0x77, 0xe6, 0xd1, 0x37, 0xf8, 0xb2, 0xa4, 0x89, 0x53, 0xa2,
+ 0x80, 0x5e, 0xff, 0x01, 0xbd, 0xec, 0x03, 0xac, 0xbf, 0xdc, 0x6c, 0x2c,
+ 0xe8, 0xc5, 0x97, 0xff, 0xfb, 0x3f, 0xf7, 0xd1, 0x47, 0x52, 0x13, 0x40,
+ 0x3b, 0x71, 0x65, 0x6e, 0x22, 0x54, 0xe6, 0x77, 0xe0, 0xf5, 0xde, 0x1d,
+ 0x65, 0xfe, 0x63, 0x30, 0x87, 0xe8, 0x59, 0x7c, 0xfd, 0x10, 0xd6, 0x51,
+ 0xcf, 0x50, 0x06, 0x57, 0xff, 0xa3, 0xfc, 0x0f, 0x7b, 0x3c, 0xe5, 0x10,
+ 0xb2, 0xef, 0x05, 0x65, 0xff, 0xfa, 0x4c, 0x43, 0xf6, 0x74, 0x23, 0x97,
+ 0xc8, 0x6b, 0x2f, 0xff, 0xe6, 0x33, 0xcf, 0xdc, 0x10, 0xf3, 0xaf, 0xf9,
+ 0xc6, 0xb2, 0xff, 0xa7, 0xfc, 0xb3, 0x71, 0xc8, 0x0b, 0x2f, 0xf9, 0xf7,
+ 0x3c, 0x26, 0xa5, 0x1b, 0x8b, 0x2f, 0xa6, 0xf3, 0xfd, 0x65, 0x62, 0x27,
+ 0xfa, 0x3c, 0x64, 0x0b, 0xfd, 0x83, 0xf6, 0x75, 0x9c, 0x59, 0x79, 0x8c,
+ 0xdc, 0x59, 0x7f, 0xb3, 0x7f, 0x3f, 0xf8, 0x3a, 0xca, 0xd1, 0xea, 0xf8,
+ 0x82, 0xa1, 0x5a, 0x88, 0xc9, 0xb1, 0xf8, 0xd2, 0x26, 0x4b, 0x98, 0x5f,
+ 0x4a, 0xbe, 0x87, 0xd9, 0x17, 0xf2, 0x11, 0x17, 0xfe, 0x93, 0x14, 0x84,
+ 0xf7, 0xa0, 0x6b, 0x2e, 0x31, 0x96, 0x5f, 0x8f, 0xde, 0x17, 0x6b, 0x2a,
+ 0x0f, 0x01, 0x85, 0xef, 0xfb, 0x06, 0x6b, 0xcd, 0xe8, 0x9d, 0x65, 0xf8,
+ 0x3f, 0x9f, 0x86, 0xac, 0xbf, 0xf9, 0xe7, 0xe3, 0x8e, 0x27, 0x89, 0x42,
+ 0xcb, 0xfb, 0x39, 0xb7, 0x9a, 0x85, 0x95, 0xd2, 0x6f, 0x1a, 0x7f, 0xf1,
+ 0x01, 0x1d, 0xf0, 0xaf, 0x6d, 0x12, 0xf9, 0xa0, 0xa6, 0x59, 0x53, 0xb6,
+ 0xa2, 0x52, 0x53, 0x1c, 0x20, 0xf1, 0xd3, 0xb6, 0x5e, 0x89, 0x9a, 0x94,
+ 0x21, 0x34, 0x2c, 0xf4, 0x40, 0x78, 0x6a, 0xbc, 0x2d, 0x00, 0x61, 0xc9,
+ 0xc1, 0x8f, 0xca, 0x0d, 0x31, 0x6e, 0xff, 0x73, 0x98, 0x40, 0xdb, 0xc5,
+ 0x97, 0xc4, 0xdb, 0xb0, 0xb2, 0xe0, 0x42, 0xcb, 0xc5, 0x9c, 0x59, 0x44,
+ 0x6c, 0x44, 0x16, 0xb4, 0xcb, 0x2f, 0xee, 0x61, 0x03, 0x6f, 0x16, 0x56,
+ 0xc4, 0x75, 0xe1, 0xab, 0xaa, 0x00, 0x87, 0x82, 0x57, 0xdf, 0x77, 0x25,
+ 0x95, 0xbc, 0xfa, 0x8c, 0x4a, 0xbf, 0xc0, 0x70, 0x46, 0xe4, 0x49, 0x65,
+ 0xff, 0xd2, 0x6c, 0xf3, 0xfb, 0xd1, 0xd7, 0x16, 0x5f, 0xef, 0x60, 0xca,
+ 0x30, 0x96, 0x54, 0x91, 0x53, 0xd1, 0xa8, 0x11, 0x2f, 0x0f, 0x09, 0x65,
+ 0xf8, 0x27, 0x8c, 0xfa, 0xcb, 0xec, 0x04, 0x01, 0x65, 0x00, 0xf2, 0x08,
+ 0x9e, 0xa7, 0x44, 0x27, 0xd8, 0xe9, 0xd1, 0xb2, 0x18, 0x5a, 0xdf, 0xfe,
+ 0x29, 0xf6, 0x4c, 0xc5, 0x83, 0xc2, 0x35, 0x65, 0xff, 0x04, 0x22, 0x13,
+ 0x6c, 0x07, 0xd6, 0x5f, 0xfb, 0x37, 0xc7, 0x5b, 0x71, 0xac, 0x25, 0x97,
+ 0xf3, 0x75, 0xbb, 0xe8, 0xfa, 0xcb, 0xf0, 0x78, 0xcd, 0xd2, 0xcb, 0xf1,
+ 0x67, 0xfc, 0xcb, 0x2f, 0x09, 0x90, 0xb2, 0xe0, 0x9a, 0xb2, 0xfd, 0x04,
+ 0x41, 0x3a, 0xca, 0xf1, 0xbe, 0x10, 0x62, 0xf7, 0xe0, 0x45, 0x97, 0xfb,
+ 0x07, 0xa7, 0xef, 0xe0, 0x59, 0x7e, 0xc2, 0x1f, 0xa1, 0x65, 0x61, 0xfb,
+ 0xf8, 0x74, 0xc3, 0x4b, 0xd2, 0xce, 0x2c, 0xa8, 0x55, 0x0f, 0x3a, 0x61,
+ 0xa7, 0x9b, 0x88, 0x53, 0x18, 0xe8, 0xa1, 0xc9, 0x89, 0x6b, 0x90, 0x99,
+ 0xf9, 0x7d, 0xf0, 0xf4, 0xf2, 0x59, 0x7f, 0xff, 0xb0, 0x9f, 0xfc, 0xcd,
+ 0x00, 0x11, 0x9d, 0x7f, 0x8c, 0xb2, 0xe9, 0x42, 0xcb, 0x6d, 0xac, 0xad,
+ 0x86, 0xab, 0x05, 0xa8, 0x68, 0xab, 0xfc, 0x22, 0x6a, 0x11, 0xea, 0xf0,
+ 0xcd, 0xbd, 0x1a, 0x99, 0x65, 0xe1, 0xc1, 0x2c, 0xad, 0x8f, 0x83, 0xdf,
+ 0xb5, 0xa0, 0x45, 0x2d, 0xf6, 0x78, 0xd5, 0x87, 0x0a, 0xdc, 0xa4, 0x42,
+ 0xf7, 0x2d, 0x7f, 0xa8, 0x7a, 0x35, 0x20, 0x1b, 0xd1, 0xc6, 0xbd, 0x6a,
+ 0x66, 0x09, 0x4a, 0x85, 0x1d, 0x38, 0x65, 0x57, 0x19, 0x1c, 0x56, 0xd9,
+ 0x30, 0x83, 0xb7, 0xba, 0x9f, 0x7a, 0xcb, 0xfd, 0xdf, 0x9c, 0xa0, 0x3d,
+ 0x2c, 0xbf, 0x77, 0xe8, 0xeb, 0x75, 0x65, 0xc1, 0x15, 0xac, 0xbf, 0x79,
+ 0xf4, 0x76, 0x59, 0x78, 0x48, 0xdc, 0x59, 0x7f, 0x09, 0xdf, 0xa3, 0xad,
+ 0xd5, 0x95, 0xb1, 0x18, 0x72, 0x2d, 0xec, 0x6f, 0x84, 0xe1, 0x20, 0xbc,
+ 0xc5, 0x8b, 0x2f, 0xef, 0x30, 0xaf, 0xd1, 0x3a, 0xcb, 0x0e, 0x47, 0x99,
+ 0xd8, 0xd5, 0xc0, 0x31, 0x65, 0xfd, 0xe8, 0x6d, 0xc3, 0xb2, 0xca, 0xd8,
+ 0x78, 0xfd, 0x8c, 0x50, 0xd5, 0x12, 0xf5, 0x0f, 0x76, 0x84, 0xcf, 0xdc,
+ 0x2f, 0xec, 0x33, 0x30, 0x8d, 0x59, 0x73, 0x4e, 0xb2, 0xe8, 0x11, 0x65,
+ 0xe7, 0xce, 0x2c, 0xbf, 0x3c, 0xec, 0x19, 0x2c, 0xbc, 0x00, 0x42, 0xca,
+ 0x91, 0xfb, 0x1c, 0x5f, 0xc3, 0x64, 0x51, 0x7b, 0x08, 0xd5, 0x94, 0xc9,
+ 0x88, 0x9c, 0xb5, 0xe1, 0x1b, 0xba, 0x77, 0x7f, 0xee, 0x6a, 0x3e, 0x4e,
+ 0x73, 0xb2, 0xcb, 0xff, 0xd1, 0xce, 0x41, 0xf3, 0xed, 0xcf, 0x3a, 0xcb,
+ 0xcc, 0x5f, 0x59, 0x5d, 0x9f, 0x1f, 0x92, 0x2f, 0xfd, 0xe6, 0xf4, 0x66,
+ 0xa5, 0xa9, 0x2c, 0xbf, 0xf8, 0xf1, 0xfe, 0x3e, 0x68, 0x07, 0xc5, 0x97,
+ 0xf1, 0x44, 0x8f, 0x0c, 0xb2, 0x80, 0x7d, 0xc4, 0x87, 0x7e, 0xf4, 0x4f,
+ 0x1e, 0x59, 0x7e, 0xd3, 0x9e, 0x3b, 0x59, 0x7e, 0xcd, 0xe5, 0x9c, 0x59,
+ 0x7f, 0xbe, 0xdb, 0xdb, 0xf2, 0x84, 0x96, 0x3a, 0xcb, 0xfb, 0x08, 0xdd,
+ 0x40, 0xb6, 0x3c, 0x51, 0x0d, 0x2e, 0xc3, 0x56, 0x56, 0xc5, 0x55, 0x59,
+ 0x0a, 0x0e, 0xc8, 0xda, 0x15, 0x93, 0x10, 0xb9, 0x41, 0x14, 0x71, 0xb7,
+ 0x6d, 0x1a, 0xff, 0xf3, 0xef, 0x8c, 0x1b, 0xcb, 0x3c, 0xc6, 0x2c, 0xbc,
+ 0x1e, 0xa4, 0xb2, 0xf6, 0x9f, 0x7a, 0xcb, 0xf0, 0xf5, 0xac, 0xe2, 0xca,
+ 0x91, 0xe3, 0x38, 0xf5, 0x49, 0x19, 0xfa, 0x4a, 0x26, 0x4b, 0xfc, 0x52,
+ 0x2c, 0x3c, 0x76, 0xb2, 0xf4, 0xcf, 0xf5, 0x97, 0x8a, 0x0e, 0xb2, 0xa0,
+ 0xdc, 0x4c, 0x3b, 0x7e, 0x6f, 0x14, 0x49, 0x65, 0xf6, 0x9d, 0xa7, 0x59,
+ 0x77, 0x19, 0x65, 0x31, 0xb8, 0x72, 0x2b, 0x62, 0xcb, 0xd9, 0x86, 0xac,
+ 0xb1, 0xc6, 0x6b, 0x37, 0x44, 0x2f, 0xfd, 0xc1, 0x35, 0xf9, 0x31, 0x7f,
+ 0x8b, 0x2a, 0x13, 0xcd, 0xc2, 0xf6, 0x6a, 0xd1, 0x0f, 0x97, 0x9d, 0x2c,
+ 0x25, 0x57, 0xfc, 0xdb, 0xf3, 0x5d, 0xbb, 0xf6, 0xa8, 0xc3, 0x57, 0xb6,
+ 0xc3, 0xf5, 0x97, 0x36, 0xf5, 0x97, 0xfe, 0xef, 0xd0, 0x4f, 0xfe, 0x64,
+ 0xeb, 0x2f, 0x69, 0xc4, 0x59, 0x58, 0x7b, 0x8e, 0x7f, 0x76, 0x1a, 0xb2,
+ 0xff, 0xe8, 0x3b, 0x0f, 0x08, 0xdf, 0x41, 0xd6, 0x57, 0x8f, 0x6b, 0xe2,
+ 0xf7, 0xd8, 0x78, 0x11, 0x65, 0x0d, 0x39, 0xae, 0xd2, 0x0e, 0x41, 0xc7,
+ 0x4f, 0xbd, 0x6f, 0x22, 0xb8, 0x4f, 0x2c, 0xbf, 0x13, 0x98, 0x21, 0xd6,
+ 0x5f, 0x3f, 0x5f, 0xc5, 0x96, 0x69, 0x8f, 0x2f, 0x85, 0x34, 0x6a, 0x22,
+ 0xfc, 0xc7, 0x7f, 0xfc, 0xdf, 0xf4, 0x72, 0x3d, 0x0d, 0x3c, 0x1a, 0xb2,
+ 0xff, 0x7a, 0x26, 0x93, 0x6a, 0x4b, 0x2f, 0xc5, 0x31, 0x41, 0xd6, 0x5f,
+ 0xef, 0xb1, 0x93, 0x13, 0x98, 0xb2, 0xef, 0x32, 0xcb, 0xfe, 0xcd, 0xf0,
+ 0x3f, 0x63, 0x7d, 0x65, 0xee, 0x38, 0x16, 0x51, 0x1e, 0xaf, 0xce, 0x6b,
+ 0x71, 0x11, 0x9f, 0x6b, 0xbf, 0x82, 0x20, 0x01, 0x1d, 0x2c, 0xbe, 0x3f,
+ 0xf3, 0xb5, 0x97, 0xd3, 0xc7, 0x50, 0xb2, 0xa0, 0xf1, 0x98, 0x8e, 0xe3,
+ 0x3e, 0xb2, 0xfd, 0x12, 0x01, 0x62, 0xcb, 0x9a, 0x75, 0x95, 0x0a, 0x9f,
+ 0x06, 0x9f, 0x86, 0x9d, 0x13, 0xb4, 0x30, 0x66, 0x26, 0xf3, 0xb3, 0x90,
+ 0x10, 0xc7, 0xc9, 0xaf, 0xcf, 0xfd, 0x46, 0xf5, 0x97, 0xd1, 0xd0, 0x77,
+ 0x16, 0x5f, 0xff, 0xbb, 0x0f, 0x8d, 0x62, 0x8f, 0x41, 0x90, 0x58, 0xb2,
+ 0xa6, 0x3f, 0xb2, 0x26, 0xbe, 0x61, 0xee, 0xb2, 0xca, 0x84, 0x75, 0x3c,
+ 0x29, 0x0c, 0x22, 0xbf, 0xef, 0x44, 0x98, 0xb0, 0xf0, 0xb2, 0xf9, 0xc7,
+ 0x29, 0xd6, 0x5f, 0xf6, 0x7f, 0xd8, 0x72, 0x7f, 0xac, 0xbf, 0xb7, 0xb6,
+ 0xba, 0x8d, 0xc5, 0x94, 0x33, 0xea, 0xc3, 0x7a, 0xf2, 0x2b, 0x8a, 0x11,
+ 0xb7, 0x10, 0x16, 0x5f, 0x8f, 0x1d, 0xce, 0x35, 0x97, 0xd2, 0x83, 0xba,
+ 0xcb, 0xf6, 0x80, 0x76, 0xe2, 0xcb, 0xbf, 0xc1, 0x4a, 0x22, 0x70, 0x59,
+ 0xca, 0x84, 0x21, 0xa8, 0x47, 0xe0, 0x61, 0x61, 0x6e, 0x2c, 0xbf, 0xa2,
+ 0x7c, 0x26, 0x35, 0x65, 0x68, 0xdf, 0x70, 0x46, 0xff, 0xc4, 0xfe, 0x80,
+ 0x0b, 0xd7, 0x38, 0x92, 0xf7, 0xb0, 0x6b, 0x2a, 0x0f, 0x71, 0x90, 0x2f,
+ 0xa3, 0xf2, 0x75, 0x97, 0xf0, 0x04, 0x29, 0x7b, 0x16, 0x5d, 0x3c, 0xeb,
+ 0x2f, 0x67, 0x70, 0xb2, 0xa7, 0x56, 0xcc, 0x38, 0xf8, 0x31, 0x94, 0xef,
+ 0xbe, 0x20, 0xf9, 0x08, 0x4b, 0xb7, 0x8c, 0xde, 0x3c, 0x76, 0xb2, 0xfc,
+ 0xf3, 0x36, 0x71, 0x65, 0xf7, 0x23, 0x52, 0x59, 0x61, 0xec, 0x3c, 0x9e,
+ 0x13, 0xd4, 0x22, 0x41, 0xd9, 0xaf, 0xf8, 0x87, 0xe8, 0xff, 0xe0, 0xeb,
+ 0x2e, 0x0c, 0xeb, 0x2f, 0xa0, 0x4d, 0xd1, 0xac, 0xbe, 0xe3, 0x7e, 0x16,
+ 0x5d, 0xd4, 0xa7, 0x3c, 0x7e, 0x89, 0xaf, 0x37, 0x5c, 0x59, 0x58, 0x79,
+ 0xcc, 0x63, 0x58, 0x98, 0x2b, 0x1c, 0x7a, 0x15, 0xb7, 0x67, 0x6b, 0x2d,
+ 0xc5, 0x9f, 0x2d, 0xef, 0xc3, 0x83, 0xb8, 0xd6, 0x56, 0x1e, 0x3b, 0x10,
+ 0x5e, 0xfe, 0x79, 0x65, 0xf4, 0xff, 0x63, 0x56, 0x56, 0x8f, 0x80, 0x24,
+ 0x02, 0x0e, 0x5f, 0xfe, 0xd8, 0xed, 0x9c, 0x89, 0xf0, 0x98, 0xd5, 0x97,
+ 0x6f, 0x85, 0x94, 0x33, 0xe2, 0x3a, 0x55, 0xfe, 0xd1, 0xe3, 0xaf, 0xbf,
+ 0x6b, 0x2f, 0xff, 0xe2, 0xcf, 0xfb, 0x25, 0x9d, 0xc7, 0x7f, 0x27, 0x3a,
+ 0xca, 0xc4, 0x58, 0xb1, 0x17, 0x0d, 0x6f, 0xf9, 0xa4, 0xdc, 0xea, 0x4c,
+ 0x4b, 0x2f, 0xf0, 0x1a, 0x5a, 0xd3, 0x18, 0xb2, 0xb4, 0x7d, 0x84, 0x71,
+ 0x7c, 0xc7, 0x89, 0x96, 0x5f, 0xfd, 0xc6, 0xe8, 0xb2, 0x6d, 0x47, 0xf8,
+ 0xb2, 0xfb, 0x27, 0x0c, 0x96, 0x5f, 0x36, 0xa2, 0x75, 0x94, 0xc8, 0xcd,
+ 0x98, 0x84, 0x04, 0x46, 0x22, 0x88, 0x47, 0x7f, 0x4d, 0xcf, 0x66, 0xfe,
+ 0x2c, 0xbd, 0x3b, 0x9d, 0x65, 0xee, 0x44, 0xa0, 0xf3, 0x9c, 0xc6, 0xf9,
+ 0xf4, 0xfd, 0x2c, 0xbf, 0x81, 0x3b, 0xca, 0x37, 0x16, 0x5f, 0xb6, 0x44,
+ 0xd0, 0x62, 0xcb, 0xc3, 0x1c, 0x2c, 0xb9, 0x89, 0x65, 0x1a, 0x8a, 0xfe,
+ 0x88, 0x8e, 0x62, 0x12, 0xb1, 0x07, 0x2a, 0x13, 0xc7, 0x68, 0x4d, 0x3c,
+ 0x38, 0x2f, 0xb5, 0x18, 0x75, 0x97, 0x61, 0x8b, 0x29, 0x38, 0x86, 0x17,
+ 0xf7, 0x04, 0x8d, 0x41, 0xd3, 0x88, 0x61, 0x49, 0xc4, 0x30, 0xa4, 0xe2,
+ 0x18, 0x52, 0x71, 0x0c, 0x29, 0x38, 0x86, 0x15, 0x24, 0x5c, 0xb0, 0xc8,
+ 0x0f, 0x02, 0x33, 0xb6, 0x33, 0xba, 0x33, 0x77, 0xb1, 0x38, 0x86, 0x17,
+ 0xf3, 0xbf, 0xe6, 0x83, 0xa7, 0x10, 0xc3, 0x61, 0xa4, 0xb0, 0xad, 0x38,
+ 0x86, 0x14, 0x9c, 0x43, 0x0a, 0x4e, 0x21, 0x85, 0x48, 0xd9, 0x30, 0xcd,
+ 0x27, 0x10, 0xc2, 0x93, 0x88, 0x61, 0x49, 0xc4, 0x30, 0xa4, 0xe2, 0x18,
+ 0x52, 0x71, 0x0c, 0x29, 0x38, 0x86, 0x15, 0x3a, 0x25, 0x86, 0x32, 0xc3,
+ 0x20, 0x19, 0xe0, 0xce, 0xf1, 0x9a, 0x4e, 0x21, 0x85, 0x27, 0x10, 0xc2,
+ 0xa4, 0x6c, 0xb8, 0x33, 0x49, 0xc4, 0x30, 0xa4, 0xe2, 0x18, 0x52, 0x71,
+ 0x0c, 0x29, 0x38, 0x86, 0x15, 0x23, 0xe4, 0x00, 0xcf, 0xc6, 0x77, 0x46,
+ 0x69, 0x38, 0x86, 0x14, 0x9c, 0x43, 0x0a, 0x4e, 0x21, 0x85, 0x27, 0x10,
+ 0xc2, 0xa7, 0x3e, 0x43, 0x46, 0x74, 0x33, 0xe1, 0x9b, 0x1a, 0x9c, 0x43,
+ 0x0a, 0x4e, 0x21, 0x85, 0x27, 0x10, 0xc2, 0x93, 0x88, 0x61, 0x49, 0xc4,
+ 0x30, 0xa1, 0x9f, 0x27, 0x43, 0x20, 0x19, 0x08, 0xcd, 0x27, 0x10, 0xc2,
+ 0x93, 0x88, 0x61, 0x49, 0xc4, 0x30, 0xbf, 0x7a, 0x01, 0xcc, 0x4e, 0x21,
+ 0x85, 0x27, 0x10, 0xc2, 0xa4, 0x89, 0x9e, 0xc6, 0x7c, 0x32, 0xe3, 0x20,
+ 0x35, 0xb7, 0x69, 0xc4, 0x30, 0xa4, 0xe2, 0x18, 0x52, 0x71, 0x0c, 0x29,
+ 0x38, 0x86, 0x14, 0x9c, 0x43, 0x0a, 0x91, 0xf2, 0x74, 0x32, 0xc3, 0x3b,
+ 0xc6, 0x69, 0x38, 0x86, 0x14, 0x9c, 0x43, 0x0a, 0x4e, 0x21, 0x85, 0x27,
+ 0x10, 0xc2, 0xa4, 0x7c, 0x83, 0x19, 0xf0, 0xc9, 0x0c, 0xdb, 0xc9, 0xc4,
+ 0x30, 0xa4, 0xe2, 0x18, 0x52, 0x71, 0x0c, 0x2d, 0x24, 0xe2, 0x18, 0x52,
+ 0x71, 0x0c, 0x3a, 0x2f, 0xe9, 0x38, 0x86, 0x14, 0x9c, 0x43, 0x0a, 0x4e,
+ 0x21, 0x85, 0x27, 0x10, 0xc2, 0xa7, 0x46, 0xf4, 0x86, 0x4d, 0x38, 0xec,
+ 0xa6, 0x61, 0x90, 0x0c, 0xfc, 0x66, 0xd8, 0x9c, 0x43, 0x0a, 0x4e, 0x21,
+ 0x85, 0x27, 0x10, 0xc2, 0xd2, 0x4e, 0x21, 0x85, 0x27, 0x10, 0xc3, 0xa2,
+ 0xfe, 0x93, 0x88, 0x61, 0x49, 0xc4, 0x30, 0xa8, 0x45, 0x64, 0x86, 0x58,
+ 0xe3, 0x45, 0x27, 0x19, 0xa4, 0xe2, 0x18, 0x52, 0x71, 0x0c, 0x29, 0x38,
+ 0x86, 0x14, 0x9c, 0x43, 0x0a, 0x4e, 0x21, 0x85, 0x41, 0xfe, 0xf4, 0x33,
+ 0xa1, 0x93, 0x8c, 0x90, 0xcd, 0x27, 0x10, 0xc2, 0x93, 0x88, 0x61, 0x49,
+ 0xc4, 0x30, 0xad, 0x1e, 0x5f, 0x06, 0x7e, 0x33, 0x49, 0xc4, 0x30, 0xa4,
+ 0xe2, 0x18, 0x52, 0x71, 0x0c, 0x28, 0xe7, 0x96, 0x43, 0x3f, 0x19, 0xb1,
+ 0xd3, 0x88, 0x61, 0x49, 0xc4, 0x30, 0xa4, 0xe2, 0x18, 0x50, 0x0d, 0x90,
+ 0x46, 0x69, 0x38, 0x86, 0x14, 0x9c, 0x43, 0x0a, 0x4e, 0x21, 0x85, 0x27,
+ 0x10, 0xc2, 0xa0, 0xf9, 0x26, 0x19, 0xf0, 0xc8, 0x46, 0x6a, 0x19, 0x81,
+ 0xf3, 0xc2, 0x02, 0x49, 0xa3, 0x55, 0xc8, 0x5b, 0x77, 0x08, 0xbe, 0xa1,
+ 0x0a, 0xd0, 0xa3, 0xdc, 0x3e, 0x9a, 0x10, 0x9a, 0x86, 0xb1, 0xd2, 0xbd,
+ 0x08, 0x47, 0x85, 0x10, 0x0e, 0xca, 0x1f, 0xbc, 0x68, 0xfc, 0x32, 0x83,
+ 0x0c, 0x5d, 0xf0, 0x93, 0x31, 0xeb, 0x6c, 0xb8, 0x45, 0x1d, 0xd8, 0x42,
+ 0xdf, 0xa4, 0x51, 0x9c, 0x4e, 0x21, 0x80, 0xb4, 0xe5, 0xef, 0x34, 0x1d,
+ 0x38, 0x86, 0x17, 0xcd, 0xdb, 0xe9, 0x78, 0x86, 0x2f, 0x30, 0xf1, 0x78,
+ 0x86, 0x2c, 0x2f, 0xa4, 0x64, 0xe9, 0x27, 0xc5, 0x3f, 0x2f, 0xb4, 0x6f,
+ 0x67, 0xc2, 0x89, 0x4f, 0x3f, 0xbc, 0xc5, 0x3a, 0xcb, 0xf9, 0x8c, 0x1e,
+ 0xa2, 0x75, 0x95, 0x23, 0xcb, 0xf0, 0xe5, 0xdb, 0xe1, 0x65, 0xcf, 0xd2,
+ 0xcb, 0xe9, 0x37, 0x82, 0xb2, 0xfa, 0x36, 0xe3, 0xeb, 0x2f, 0x36, 0xf1,
+ 0x5a, 0xcb, 0x9b, 0x75, 0x65, 0x76, 0xd8, 0x7d, 0xf5, 0x4f, 0xa6, 0x9a,
+ 0x10, 0x67, 0x22, 0xf0, 0xc3, 0x8b, 0x91, 0x17, 0xc9, 0x37, 0x48, 0xaf,
+ 0x78, 0x72, 0x59, 0x7a, 0x67, 0x11, 0x65, 0x0c, 0xdd, 0xe0, 0xed, 0xf9,
+ 0x88, 0x2f, 0xf5, 0x97, 0xff, 0xfe, 0xcc, 0x20, 0xfd, 0xbc, 0x41, 0x34,
+ 0xb3, 0xaf, 0xc6, 0x69, 0x65, 0x62, 0x2c, 0x38, 0x41, 0xb6, 0x4d, 0x7b,
+ 0xc1, 0xed, 0x65, 0xf7, 0xb3, 0x7e, 0x2c, 0xaf, 0x1e, 0x0f, 0xc7, 0xaf,
+ 0x00, 0x3c, 0x59, 0x7f, 0x9c, 0x84, 0x9a, 0x4c, 0x4b, 0x2e, 0x04, 0x2c,
+ 0xbf, 0xb4, 0xe4, 0x24, 0x01, 0x65, 0xcf, 0xa5, 0x96, 0x65, 0x9d, 0x96,
+ 0xd6, 0xed, 0x65, 0x8e, 0xb2, 0xc2, 0xd9, 0x13, 0x9a, 0x16, 0xf2, 0x1b,
+ 0x90, 0x08, 0x25, 0x7f, 0x75, 0x2f, 0x41, 0x4e, 0xb2, 0x8e, 0x9a, 0x7e,
+ 0xdc, 0x33, 0xf7, 0x54, 0x6f, 0xff, 0xfd, 0x92, 0xf4, 0x79, 0x8d, 0x76,
+ 0x28, 0xf3, 0xb4, 0x98, 0x6b, 0x2e, 0x96, 0x2c, 0xbf, 0x88, 0x3f, 0xf6,
+ 0x6f, 0x59, 0x7b, 0x4d, 0x3a, 0xcb, 0xfd, 0x07, 0xc9, 0xa0, 0xa7, 0x59,
+ 0x4b, 0x2e, 0x1e, 0xf5, 0x95, 0x88, 0xa3, 0xd1, 0x7f, 0x87, 0x40, 0x66,
+ 0x41, 0x77, 0xec, 0x3f, 0xa0, 0x0b, 0x2f, 0xfe, 0xd8, 0xfd, 0x8f, 0xd0,
+ 0x0c, 0x20, 0x2c, 0xb8, 0x10, 0xb2, 0xb0, 0xf7, 0x00, 0x8d, 0x50, 0xaf,
+ 0x5e, 0x44, 0x59, 0x1b, 0x63, 0x1e, 0x4c, 0xd0, 0x08, 0x5c, 0xfd, 0x20,
+ 0x30, 0x83, 0xbe, 0x89, 0x72, 0x16, 0x5f, 0xfc, 0x45, 0x13, 0x96, 0x36,
+ 0xf8, 0xdb, 0x59, 0x7a, 0x3a, 0xe2, 0xca, 0x3a, 0x21, 0x1c, 0x87, 0x88,
+ 0xd7, 0x9f, 0x50, 0xb2, 0xfc, 0xdb, 0x6e, 0x40, 0x59, 0x7e, 0x6e, 0xb8,
+ 0xfd, 0x2c, 0xa9, 0x1f, 0x69, 0xc6, 0xf8, 0x53, 0x7d, 0xbc, 0xf0, 0xcb,
+ 0x2f, 0xd3, 0x31, 0xde, 0x65, 0x97, 0xfc, 0x23, 0x8f, 0x98, 0x78, 0xdc,
+ 0x59, 0x7b, 0x3a, 0x31, 0x65, 0x68, 0xf6, 0x88, 0xf2, 0xff, 0x66, 0x14,
+ 0x84, 0x21, 0xac, 0xb0, 0x30, 0xf4, 0xe6, 0x21, 0xbf, 0xfc, 0xdb, 0x81,
+ 0x35, 0xba, 0xe6, 0x4d, 0x1f, 0x59, 0x6d, 0xc5, 0x95, 0xd2, 0x22, 0xce,
+ 0x50, 0xe9, 0xf7, 0x06, 0x16, 0x5e, 0xcd, 0x49, 0x65, 0x0c, 0xd9, 0x6f,
+ 0x16, 0xbc, 0x37, 0x25, 0x94, 0xc6, 0xf9, 0xc8, 0xef, 0xbb, 0x72, 0x35,
+ 0x65, 0xff, 0xff, 0xb5, 0xfc, 0x28, 0xec, 0xa0, 0xfc, 0xe6, 0x4b, 0xcc,
+ 0x40, 0x59, 0x50, 0x88, 0xd7, 0x23, 0xbf, 0xf9, 0xf5, 0xa7, 0x04, 0x0b,
+ 0x30, 0xc3, 0x16, 0x5e, 0x93, 0x01, 0x65, 0xff, 0x8d, 0xce, 0xbe, 0xdf,
+ 0xd0, 0x4e, 0xb2, 0xb6, 0x22, 0x99, 0xd2, 0x7e, 0x39, 0x74, 0x49, 0x65,
+ 0x41, 0xe3, 0x80, 0xc6, 0xa1, 0x70, 0xbb, 0x0b, 0xd8, 0x8d, 0xe3, 0x61,
+ 0xe4, 0x28, 0x3f, 0x0a, 0xc0, 0xc6, 0x1d, 0x7c, 0xe3, 0xcf, 0xac, 0xbf,
+ 0xf8, 0xb1, 0xbd, 0x1d, 0x03, 0x3f, 0xc5, 0x97, 0xff, 0x04, 0x49, 0xb6,
+ 0x40, 0x8f, 0xdc, 0x79, 0x65, 0xc4, 0x6a, 0xcb, 0xff, 0x80, 0xf2, 0xe6,
+ 0x4b, 0xd0, 0x46, 0xac, 0xbf, 0x8f, 0xcc, 0x3c, 0x6e, 0x2c, 0xa8, 0x3f,
+ 0x46, 0x44, 0xbf, 0xcc, 0x6f, 0x18, 0xba, 0x92, 0xcb, 0x46, 0x8f, 0x53,
+ 0xc4, 0x14, 0xc9, 0x83, 0x6e, 0xc3, 0x7e, 0x85, 0x2e, 0xec, 0x0e, 0x25,
+ 0x23, 0x4f, 0x1a, 0xd4, 0xa5, 0x77, 0x0e, 0x59, 0x4e, 0x47, 0xf6, 0x6c,
+ 0x39, 0xbb, 0x95, 0x41, 0xd4, 0x6f, 0x2d, 0x2e, 0x6b, 0x72, 0x30, 0xb9,
+ 0xa3, 0x26, 0xd4, 0x3c, 0x8f, 0x1a, 0x1f, 0xa5, 0x97, 0x3d, 0x62, 0x66,
+ 0x08, 0xe0, 0x0a, 0x71, 0x2b, 0x91, 0x82, 0xfe, 0x73, 0x2b, 0x7b, 0xce,
+ 0xd9, 0x08, 0x88, 0x7b, 0xb1, 0xa8, 0x5e, 0x04, 0xf8, 0xb2, 0xf1, 0xf9,
+ 0xda, 0xcb, 0xc5, 0xdc, 0x2c, 0xbe, 0xcf, 0xbf, 0x4b, 0x2b, 0x61, 0xee,
+ 0x30, 0xf6, 0x87, 0x2f, 0xfb, 0x86, 0xb9, 0x46, 0x4f, 0x0b, 0x2f, 0xa5,
+ 0x9a, 0x85, 0x97, 0xf1, 0x8f, 0xad, 0x3f, 0x4b, 0x2f, 0xff, 0xdc, 0xd6,
+ 0x9a, 0x6e, 0x6a, 0x3e, 0xdd, 0xb0, 0xd6, 0x51, 0xd3, 0x0f, 0x73, 0x00,
+ 0x1c, 0x11, 0x09, 0x85, 0xf7, 0xbf, 0x1c, 0x59, 0x62, 0x59, 0x7e, 0x1e,
+ 0x60, 0x38, 0xb2, 0xc0, 0xdb, 0x36, 0xe2, 0x08, 0x51, 0xcf, 0xf8, 0x94,
+ 0xef, 0x4e, 0xc3, 0x59, 0x60, 0xac, 0xb0, 0x18, 0xd7, 0x10, 0xed, 0x85,
+ 0x2b, 0x2f, 0xb4, 0xc4, 0x6a, 0xcb, 0xf0, 0x7b, 0xf3, 0x69, 0x65, 0xd8,
+ 0x6a, 0xcb, 0x7e, 0x0f, 0x03, 0x85, 0x37, 0xf6, 0x77, 0xe8, 0xea, 0x4b,
+ 0x2f, 0xe3, 0xf1, 0x8d, 0xf9, 0x8b, 0x2f, 0xd1, 0xd7, 0xa2, 0x4b, 0x28,
+ 0x50, 0x99, 0x2e, 0x85, 0x49, 0x8b, 0xe4, 0xe2, 0x17, 0xee, 0x98, 0x5f,
+ 0xb3, 0xff, 0xc9, 0xd6, 0x5f, 0xf4, 0x73, 0x99, 0xfe, 0x64, 0xeb, 0x2d,
+ 0xd1, 0x1f, 0x08, 0x85, 0x17, 0xf4, 0x75, 0x2c, 0xdd, 0x92, 0xca, 0xc3,
+ 0xda, 0x39, 0x4d, 0xdd, 0x7d, 0x65, 0xfb, 0x0a, 0x76, 0xd2, 0xcb, 0xf7,
+ 0xdc, 0x83, 0x8b, 0x2f, 0xf7, 0x30, 0xed, 0xff, 0x3a, 0xca, 0xc4, 0x4b,
+ 0xe8, 0x60, 0x89, 0xfe, 0x4d, 0x7f, 0x40, 0x7f, 0xe7, 0x02, 0xcb, 0xde,
+ 0x81, 0xac, 0xad, 0x1e, 0x4f, 0x0b, 0x6f, 0xa5, 0xa2, 0x0a, 0xca, 0x91,
+ 0xe2, 0x74, 0x45, 0x50, 0x8e, 0xb7, 0x86, 0x45, 0xed, 0x87, 0x65, 0x97,
+ 0xf6, 0x4d, 0xa8, 0xff, 0x16, 0x5c, 0x47, 0x59, 0x52, 0x3e, 0x22, 0x1e,
+ 0xe1, 0x75, 0xed, 0xdd, 0x42, 0xcb, 0xff, 0x14, 0x3c, 0xfc, 0xcd, 0xf0,
+ 0x62, 0xcb, 0xfe, 0xf3, 0x6b, 0xce, 0x29, 0x30, 0xc5, 0x97, 0xfd, 0xfd,
+ 0x46, 0x74, 0x2a, 0x85, 0x02, 0x95, 0x97, 0xff, 0x89, 0xcc, 0xe1, 0x67,
+ 0x52, 0xf8, 0x67, 0x59, 0x7f, 0xb4, 0xd3, 0x16, 0x6f, 0x75, 0x97, 0xfb,
+ 0x0a, 0x59, 0xc7, 0xf2, 0xcb, 0xff, 0xda, 0x34, 0xc7, 0x9c, 0xb3, 0x7e,
+ 0x9b, 0x8b, 0x2d, 0xcd, 0x8a, 0x84, 0xe0, 0xb8, 0x63, 0xf8, 0x81, 0xd1,
+ 0xfc, 0xc9, 0x1a, 0x4c, 0xf9, 0xa0, 0x86, 0x37, 0xfb, 0x45, 0x83, 0xf6,
+ 0x12, 0xcb, 0xe7, 0x20, 0xe2, 0xcb, 0xf0, 0xf9, 0xc8, 0x3a, 0xca, 0xe9,
+ 0x30, 0x27, 0x84, 0x48, 0x0c, 0x48, 0x82, 0xff, 0x8a, 0x1e, 0x7f, 0x46,
+ 0x80, 0xb2, 0xff, 0x36, 0x8b, 0xff, 0xc9, 0xd6, 0x5f, 0x7e, 0x7c, 0x31,
+ 0x65, 0xcf, 0xbd, 0x65, 0xfd, 0x22, 0x69, 0x7b, 0x16, 0x5f, 0xa7, 0x6d,
+ 0x44, 0x96, 0x51, 0xa8, 0xc3, 0xe8, 0xce, 0x62, 0x4d, 0x0c, 0x11, 0x65,
+ 0xef, 0xb1, 0xab, 0x2f, 0xc1, 0xfe, 0xde, 0x7d, 0x65, 0xe1, 0xb1, 0xab,
+ 0x2a, 0x0f, 0x23, 0x0a, 0xef, 0xe7, 0xf0, 0x9a, 0x70, 0x2c, 0xbd, 0xa0,
+ 0x08, 0xb2, 0xff, 0xe6, 0xfc, 0x7f, 0x9e, 0x76, 0xf0, 0x56, 0x54, 0x1f,
+ 0x0b, 0x8f, 0x5f, 0x11, 0x06, 0x4b, 0x2f, 0x71, 0x8c, 0x59, 0x7f, 0x88,
+ 0x3c, 0xc3, 0xc7, 0x6b, 0x2f, 0xfd, 0xe8, 0xd0, 0x0b, 0x0c, 0x70, 0x2c,
+ 0xbd, 0x99, 0x32, 0xca, 0x35, 0x11, 0xbe, 0x33, 0x01, 0xf5, 0xf7, 0xc1,
+ 0x12, 0x59, 0x58, 0x7a, 0x61, 0x31, 0xbd, 0x1d, 0x18, 0xb2, 0xfd, 0xa0,
+ 0x9d, 0xc9, 0x65, 0x7c, 0xf1, 0x42, 0x3d, 0x7c, 0x78, 0xc9, 0xd6, 0x5f,
+ 0xb3, 0x79, 0x47, 0x4b, 0x29, 0x8f, 0x2f, 0x84, 0x57, 0xd0, 0x5f, 0xed,
+ 0x65, 0xfb, 0x46, 0xce, 0xfb, 0x8b, 0x28, 0x6b, 0x9b, 0x99, 0x0f, 0xb6,
+ 0x4c, 0xd3, 0x29, 0xc8, 0x3d, 0x08, 0xf7, 0x20, 0x01, 0x09, 0x43, 0xf7,
+ 0x8c, 0xdf, 0x6d, 0xdb, 0x21, 0x10, 0x8a, 0xfd, 0xb7, 0xec, 0x03, 0xac,
+ 0xbf, 0xc0, 0x13, 0x08, 0x7e, 0x85, 0x95, 0x09, 0x90, 0x9e, 0x18, 0x8e,
+ 0x55, 0x7f, 0x73, 0x0e, 0xde, 0x85, 0x97, 0xba, 0x97, 0x16, 0x57, 0x47,
+ 0x95, 0xa2, 0xcb, 0xdc, 0x01, 0x8b, 0x2f, 0xba, 0xe4, 0x74, 0xb2, 0xfd,
+ 0x2f, 0xf2, 0x0d, 0x59, 0x7f, 0xf4, 0x6a, 0x26, 0x27, 0x33, 0xf9, 0xe5,
+ 0x94, 0xe7, 0xda, 0x45, 0x36, 0x93, 0x22, 0xc4, 0xf0, 0x91, 0xa8, 0x4c,
+ 0x7f, 0x08, 0xde, 0x19, 0xf7, 0xfc, 0x61, 0x66, 0xb9, 0xec, 0xed, 0x65,
+ 0xff, 0xc5, 0x9c, 0xc1, 0xcd, 0x28, 0xd4, 0xeb, 0x29, 0x8f, 0xff, 0xe7,
+ 0x57, 0xf1, 0xbf, 0x28, 0x3f, 0x16, 0x5f, 0x60, 0xd8, 0x96, 0x5f, 0x05,
+ 0xf5, 0x25, 0x97, 0xd0, 0x11, 0x5f, 0x12, 0x5f, 0xa4, 0x2c, 0xc3, 0x0c,
+ 0x59, 0x44, 0x7a, 0x81, 0x26, 0xbf, 0x6d, 0xbc, 0xfe, 0x65, 0x97, 0xff,
+ 0xde, 0x63, 0x4d, 0x8f, 0xf2, 0x08, 0xb3, 0xeb, 0x2f, 0x8b, 0x0f, 0x0b,
+ 0x2f, 0xf4, 0x7d, 0xc0, 0xf9, 0xa5, 0x97, 0x67, 0xd6, 0x5f, 0xff, 0xdf,
+ 0x2c, 0x03, 0x90, 0x3e, 0x4e, 0x03, 0x33, 0xcb, 0x2e, 0x2e, 0xf6, 0x26,
+ 0x75, 0xd9, 0x5b, 0x27, 0x9c, 0x83, 0xc6, 0x22, 0x0b, 0x5e, 0xf9, 0xfe,
+ 0xb2, 0xfc, 0x16, 0x26, 0xe2, 0xca, 0x73, 0xc3, 0xe0, 0xed, 0xfb, 0x9a,
+ 0x87, 0xed, 0x65, 0xfa, 0x0b, 0xb8, 0xde, 0xb2, 0xb0, 0xf4, 0x7c, 0x51,
+ 0x5b, 0x15, 0x97, 0x0c, 0x83, 0x1d, 0x9e, 0x35, 0xb0, 0x42, 0xab, 0xee,
+ 0x57, 0xf8, 0x05, 0x9b, 0xf4, 0xdc, 0x59, 0x7f, 0x84, 0x22, 0x73, 0x1f,
+ 0xcb, 0x28, 0x52, 0xdb, 0x8c, 0xc4, 0x71, 0x19, 0x0c, 0x8e, 0x93, 0xda,
+ 0x34, 0xad, 0x46, 0x34, 0x78, 0xe8, 0xde, 0x5c, 0xe8, 0x27, 0x8f, 0xca,
+ 0x39, 0xde, 0x42, 0xcb, 0xe4, 0x21, 0x96, 0xb9, 0xbd, 0x90, 0xc3, 0x4b,
+ 0xe0, 0x09, 0x00, 0x59, 0x7b, 0x6b, 0x15, 0x05, 0x2b, 0x2f, 0x48, 0x9d,
+ 0x65, 0xfe, 0xfc, 0x1f, 0xa9, 0x67, 0xd6, 0x5f, 0xfd, 0x3b, 0xee, 0x77,
+ 0xe6, 0xee, 0x3f, 0xc5, 0x95, 0xb5, 0xa3, 0x12, 0x0a, 0xf0, 0x6f, 0x86,
+ 0x95, 0x09, 0x93, 0xf5, 0x0e, 0x7b, 0xf6, 0xec, 0x4b, 0x50, 0xb2, 0xf7,
+ 0x98, 0xeb, 0x2e, 0x70, 0x2c, 0xa7, 0x36, 0x5f, 0x1c, 0xbf, 0x6a, 0x78,
+ 0xd4, 0xeb, 0x2f, 0xec, 0xff, 0x02, 0x5f, 0x59, 0x7e, 0x62, 0xf8, 0x87,
+ 0x59, 0x79, 0xf5, 0xc5, 0x95, 0x08, 0x9b, 0xc2, 0xa0, 0x16, 0xfc, 0xa2,
+ 0xff, 0xd0, 0x5f, 0xf0, 0x5e, 0x52, 0x85, 0x97, 0xb4, 0x1d, 0xc5, 0x97,
+ 0x34, 0xcb, 0x29, 0x8d, 0xb9, 0x10, 0x5a, 0x75, 0x97, 0xed, 0x47, 0x98,
+ 0xd5, 0x97, 0xfd, 0x21, 0x3e, 0xc5, 0x1d, 0x49, 0x65, 0x4e, 0x89, 0x33,
+ 0x47, 0xfb, 0x12, 0xd1, 0x45, 0xf8, 0x20, 0xc2, 0xed, 0x65, 0xed, 0x44,
+ 0xcb, 0x2f, 0x13, 0xcc, 0xb2, 0xfd, 0xc3, 0x1f, 0xae, 0x2c, 0xa6, 0x3c,
+ 0x67, 0x1c, 0xbe, 0xe7, 0xe0, 0xeb, 0x2f, 0xfc, 0x50, 0x6f, 0x9f, 0xe2,
+ 0x60, 0x16, 0x5e, 0xe6, 0xb1, 0x65, 0xe2, 0xc9, 0x2c, 0xbf, 0x68, 0x04,
+ 0x10, 0x2c, 0xa8, 0x3c, 0x3c, 0x1b, 0xa6, 0x3f, 0xfe, 0x2f, 0xdb, 0x71,
+ 0x65, 0xfd, 0x82, 0x44, 0xcd, 0xc5, 0x94, 0x47, 0x85, 0xf1, 0x4a, 0x85,
+ 0xca, 0x89, 0xd7, 0x25, 0x0b, 0xb1, 0x9d, 0xe4, 0x60, 0xfa, 0x40, 0x39,
+ 0x47, 0x98, 0xc0, 0x40, 0x44, 0x5f, 0x85, 0xf6, 0xf6, 0x3b, 0xfe, 0x86,
+ 0xf4, 0x1e, 0x7c, 0x31, 0x65, 0xff, 0xb9, 0x0c, 0x32, 0x89, 0x30, 0x16,
+ 0x5f, 0xbc, 0xd3, 0xb9, 0x2c, 0xb8, 0x6c, 0xb2, 0xfc, 0x13, 0x5c, 0x80,
+ 0xb2, 0xef, 0x32, 0xca, 0x83, 0xfb, 0xc2, 0x7f, 0x0b, 0x6e, 0x94, 0x5f,
+ 0xf4, 0xe5, 0x92, 0xf6, 0x03, 0x8b, 0x2f, 0xe3, 0x78, 0xc5, 0xd4, 0x96,
+ 0x5f, 0xf4, 0x17, 0x7b, 0x06, 0x4e, 0x62, 0xcb, 0xff, 0x61, 0x75, 0x2e,
+ 0x68, 0x30, 0x05, 0x97, 0xb9, 0x86, 0xac, 0xb9, 0xce, 0xb2, 0xbe, 0x6c,
+ 0xf7, 0x8e, 0xdf, 0xfb, 0xe1, 0xfc, 0xc1, 0x9c, 0xed, 0xf5, 0x95, 0x87,
+ 0xca, 0xc4, 0x77, 0xdd, 0x9c, 0x10, 0xb2, 0xfe, 0x96, 0x73, 0x8c, 0x35,
+ 0x96, 0x96, 0xc3, 0xd0, 0xf9, 0x1d, 0x42, 0x7b, 0x73, 0x97, 0xb1, 0xd9,
+ 0xe1, 0xae, 0x23, 0x85, 0xff, 0xb5, 0xe3, 0x1c, 0x7b, 0xff, 0x9d, 0xac,
+ 0xbe, 0xc3, 0xc7, 0x6b, 0x2f, 0x7b, 0x37, 0x56, 0x5f, 0xef, 0x36, 0x8b,
+ 0x3f, 0xc5, 0x97, 0xd2, 0x7f, 0xf1, 0x65, 0xbf, 0xb0, 0xfc, 0xfb, 0x1f,
+ 0x98, 0xca, 0x9d, 0x31, 0x10, 0x21, 0x94, 0x25, 0x6f, 0x0e, 0x37, 0xac,
+ 0xbf, 0x61, 0xb8, 0x52, 0x59, 0x74, 0x4c, 0xb2, 0xff, 0xe2, 0x83, 0x06,
+ 0x51, 0xd4, 0x98, 0x96, 0x56, 0x8f, 0x68, 0x85, 0xef, 0xc7, 0xcf, 0x3e,
+ 0xea, 0xca, 0xc3, 0xcb, 0x62, 0x1b, 0xf7, 0x5d, 0xb7, 0xf8, 0xb2, 0xff,
+ 0xd3, 0x4a, 0x35, 0x3e, 0xc3, 0x33, 0xcb, 0x2f, 0xf7, 0x9b, 0xc5, 0x19,
+ 0xa5, 0x97, 0xe8, 0xdf, 0xa1, 0x38, 0xb2, 0xb6, 0x22, 0x83, 0xb4, 0x4f,
+ 0x18, 0xd4, 0x23, 0xf5, 0xe1, 0x95, 0x50, 0xa9, 0x84, 0x66, 0x9a, 0x1e,
+ 0xf4, 0x33, 0x0a, 0x31, 0xdb, 0xfd, 0xec, 0xfe, 0x07, 0x53, 0xac, 0xbe,
+ 0x20, 0xbf, 0xd6, 0x5f, 0x75, 0xdb, 0x74, 0xb2, 0x8e, 0x7f, 0x40, 0x34,
+ 0xe1, 0x0d, 0xfe, 0x28, 0x94, 0xde, 0x89, 0xd6, 0x5d, 0xdb, 0x2c, 0xbf,
+ 0xe6, 0x29, 0xa3, 0xbd, 0x67, 0x4b, 0x29, 0xcf, 0x47, 0x82, 0xf4, 0x34,
+ 0x53, 0x7e, 0x10, 0xb7, 0xe1, 0x9a, 0x68, 0x7a, 0x59, 0x63, 0x5c, 0xf5,
+ 0x02, 0x51, 0x7f, 0xd1, 0xfc, 0xd7, 0x6e, 0xfd, 0xaa, 0x2f, 0x85, 0xfc,
+ 0xec, 0x38, 0xff, 0x16, 0x5f, 0xff, 0xef, 0xb6, 0x74, 0x3f, 0x07, 0x99,
+ 0xde, 0xcf, 0x36, 0x1d, 0x65, 0xfb, 0x35, 0x1d, 0x49, 0x65, 0xd0, 0x7e,
+ 0xd1, 0xfd, 0xe4, 0x6e, 0x16, 0x7d, 0x92, 0xff, 0x9c, 0xde, 0x37, 0x1b,
+ 0xaf, 0xac, 0xaf, 0x22, 0x0c, 0x92, 0x6f, 0xff, 0xc5, 0xde, 0xcf, 0x43,
+ 0x69, 0x8e, 0xdb, 0x70, 0x75, 0x97, 0x9f, 0x53, 0xaa, 0x2f, 0xf5, 0xff,
+ 0xd8, 0x40, 0x33, 0x3a, 0xff, 0xe0, 0xeb, 0x2f, 0xfc, 0x5f, 0xd6, 0x47,
+ 0x52, 0x63, 0xac, 0xbd, 0x93, 0xee, 0xac, 0xa8, 0x4d, 0x23, 0x08, 0xbb,
+ 0x59, 0xf1, 0x53, 0xa2, 0x91, 0xf5, 0xef, 0xb1, 0x8b, 0x2f, 0xe7, 0x9c,
+ 0x41, 0xbe, 0xe2, 0xca, 0xf9, 0xe7, 0x84, 0x76, 0xff, 0x6b, 0x59, 0x31,
+ 0xe3, 0x8b, 0x2f, 0xf9, 0xff, 0xc6, 0x2e, 0xa4, 0x75, 0x97, 0xfc, 0xda,
+ 0x9c, 0x20, 0x04, 0x7d, 0x65, 0xff, 0x46, 0x6b, 0x64, 0x9b, 0xa9, 0x2c,
+ 0xa9, 0x26, 0x09, 0x84, 0x40, 0x34, 0xe1, 0xcf, 0xce, 0xaf, 0xff, 0xf7,
+ 0x9f, 0x8d, 0x1c, 0xd9, 0xff, 0x61, 0xf3, 0xb7, 0xd2, 0xcb, 0xa3, 0x75,
+ 0x65, 0xf7, 0x38, 0xe7, 0x59, 0x5e, 0x44, 0xe8, 0x18, 0xbe, 0x33, 0x7f,
+ 0xba, 0xf8, 0x9e, 0xf6, 0x6e, 0x2c, 0xbf, 0x63, 0x4f, 0x06, 0xac, 0xac,
+ 0x3e, 0x1f, 0x1c, 0xdf, 0x81, 0xcd, 0xb8, 0xfa, 0xcb, 0xec, 0xd0, 0x93,
+ 0x2c, 0xa9, 0xcf, 0xc3, 0x08, 0x74, 0x57, 0x7d, 0x38, 0xda, 0x65, 0x97,
+ 0xdd, 0x4b, 0xee, 0xb2, 0xff, 0xf7, 0x7e, 0x62, 0xcd, 0xef, 0x2e, 0x30,
+ 0xd6, 0x5f, 0xe9, 0x16, 0x1c, 0xef, 0x25, 0x97, 0xcd, 0xdb, 0x0d, 0x65,
+ 0xda, 0x86, 0x3d, 0x4f, 0x99, 0x50, 0xd1, 0x97, 0xa8, 0x4f, 0xdf, 0xdc,
+ 0xf9, 0x46, 0x74, 0xb2, 0xa1, 0x36, 0x7c, 0x24, 0x78, 0x77, 0x04, 0xa2,
+ 0xff, 0xf6, 0x73, 0xce, 0xdf, 0x83, 0x93, 0x9a, 0xb2, 0xfc, 0x0e, 0x7f,
+ 0x3c, 0xb2, 0xf8, 0x7e, 0x8e, 0x96, 0x5f, 0x67, 0xa5, 0x8b, 0x2c, 0x63,
+ 0x1e, 0x27, 0xc8, 0xed, 0x8b, 0x2a, 0x11, 0x48, 0xed, 0x9f, 0x28, 0xa8,
+ 0x55, 0xe1, 0x28, 0xe5, 0xb1, 0x00, 0xa1, 0xd9, 0x7f, 0xe0, 0x1d, 0xb3,
+ 0xaf, 0x8e, 0x06, 0xb2, 0xfe, 0xd8, 0x3c, 0xc0, 0x71, 0x65, 0xff, 0xfb,
+ 0xf9, 0xa9, 0xdb, 0x8d, 0xbf, 0xcd, 0x9d, 0x7d, 0x65, 0x1d, 0x10, 0xe4,
+ 0x5f, 0x7f, 0x8b, 0xfc, 0x08, 0xfc, 0xcb, 0x2a, 0x0f, 0x57, 0x08, 0xae,
+ 0x7e, 0x96, 0x5f, 0x6c, 0x30, 0xbe, 0xb2, 0xee, 0x61, 0xcd, 0xe1, 0x0b,
+ 0xde, 0x3e, 0xa7, 0x59, 0x58, 0x79, 0x2c, 0x57, 0x7f, 0xef, 0xc7, 0x39,
+ 0x0d, 0x3b, 0xfd, 0x65, 0xff, 0x36, 0x10, 0xcd, 0x6c, 0xd2, 0xca, 0x85,
+ 0x4a, 0xad, 0x18, 0xde, 0xa1, 0x4b, 0xf2, 0x0d, 0xd3, 0xeb, 0xfe, 0xe6,
+ 0x4f, 0xc6, 0x27, 0x9d, 0x65, 0xff, 0xb3, 0xa9, 0x31, 0x1e, 0x07, 0x0b,
+ 0x2e, 0xce, 0x96, 0x56, 0x22, 0x35, 0x8e, 0x7e, 0x7b, 0x7f, 0x3e, 0xba,
+ 0x96, 0x7d, 0x65, 0xff, 0xbf, 0xc6, 0xd7, 0xc8, 0x2f, 0x25, 0x97, 0xff,
+ 0xe6, 0xe6, 0x0f, 0xd9, 0xf6, 0xce, 0x4f, 0x86, 0x2c, 0xbf, 0xfe, 0x2f,
+ 0xf7, 0xe6, 0x33, 0x85, 0x80, 0x0f, 0x16, 0x5f, 0xb1, 0xb6, 0xd8, 0x6b,
+ 0x2f, 0xfe, 0x8d, 0xbc, 0x09, 0x66, 0x6f, 0x8e, 0x96, 0x54, 0x23, 0x04,
+ 0x6a, 0x27, 0x29, 0xbf, 0xf4, 0x66, 0xb3, 0x40, 0x3b, 0x71, 0x65, 0xf7,
+ 0xf8, 0x0e, 0xd6, 0x5e, 0x7e, 0xb7, 0x56, 0x5f, 0xcf, 0xfe, 0x46, 0x4e,
+ 0xb2, 0xa1, 0x52, 0xfe, 0x17, 0x76, 0x7c, 0xd1, 0x8b, 0x11, 0x78, 0x4f,
+ 0x77, 0x92, 0x18, 0x41, 0x7e, 0x03, 0xf5, 0x2c, 0x59, 0x7f, 0x75, 0xc6,
+ 0x2e, 0xa4, 0xb2, 0xfe, 0x2f, 0xe4, 0xd1, 0xb8, 0xb2, 0xa0, 0xf7, 0xf0,
+ 0xbe, 0xff, 0xec, 0x00, 0xdd, 0xfb, 0xf1, 0xe0, 0x6b, 0x2a, 0x11, 0xd6,
+ 0x78, 0x43, 0x80, 0x82, 0xff, 0x83, 0x07, 0xe6, 0x1e, 0x37, 0x16, 0x5f,
+ 0xfb, 0x53, 0xe0, 0xf3, 0xde, 0xcd, 0xc5, 0x96, 0x35, 0x65, 0xfe, 0xff,
+ 0x04, 0xdf, 0x19, 0xd2, 0xca, 0x83, 0xc9, 0x21, 0x2b, 0xff, 0x6b, 0x87,
+ 0x13, 0x34, 0xd1, 0x32, 0xca, 0xc3, 0xe0, 0x09, 0x05, 0xf9, 0xca, 0x7e,
+ 0x0d, 0x65, 0x62, 0x66, 0x9c, 0x87, 0x59, 0x84, 0x37, 0xdf, 0xf6, 0x12,
+ 0xcb, 0xfb, 0x8f, 0x22, 0x83, 0xac, 0xbc, 0x51, 0xb8, 0xb2, 0xff, 0xfa,
+ 0x51, 0xa9, 0xfe, 0xc6, 0xf3, 0x8e, 0x52, 0x59, 0x7f, 0x4f, 0xcc, 0x3c,
+ 0x6e, 0x2c, 0xa9, 0x91, 0x04, 0x22, 0x8d, 0x62, 0x62, 0x5a, 0x21, 0xe1,
+ 0x61, 0x90, 0xa0, 0xbc, 0xde, 0x65, 0x97, 0xef, 0x0f, 0xf9, 0xbd, 0x65,
+ 0xc3, 0x92, 0xcb, 0xfd, 0x83, 0x0f, 0xf9, 0x21, 0x5a, 0xcb, 0xb2, 0x4b,
+ 0x2b, 0xc7, 0x9c, 0x47, 0x16, 0x94, 0x22, 0xc3, 0x45, 0x5f, 0x65, 0xbe,
+ 0x3f, 0xda, 0x75, 0x95, 0x87, 0xb0, 0xc6, 0xb7, 0xff, 0x6f, 0xf9, 0xb0,
+ 0x52, 0xcf, 0x31, 0xd6, 0x5d, 0x3f, 0xd6, 0x5f, 0xed, 0xfe, 0x79, 0x46,
+ 0x12, 0xca, 0x83, 0xcb, 0xc1, 0x8b, 0xe9, 0x3e, 0xa4, 0xb2, 0xff, 0xf4,
+ 0x69, 0xfe, 0x1f, 0xb7, 0xf9, 0xe6, 0x59, 0x69, 0x4c, 0x7d, 0x7e, 0x22,
+ 0xbf, 0xb0, 0xc1, 0x3c, 0xff, 0x59, 0x7f, 0x48, 0xff, 0x20, 0xcc, 0xb2,
+ 0xff, 0xf8, 0x49, 0x46, 0xf6, 0x20, 0x69, 0xa0, 0xf8, 0x92, 0xb4, 0x7f,
+ 0xff, 0x2f, 0xbe, 0xf0, 0x9d, 0x7d, 0x65, 0xfb, 0x0f, 0x8d, 0xbd, 0x65,
+ 0xe9, 0xe6, 0xdc, 0x59, 0x63, 0x16, 0x54, 0x26, 0xf5, 0x39, 0x4e, 0x42,
+ 0xbb, 0xb2, 0x26, 0x25, 0x09, 0x46, 0xd9, 0x15, 0xdf, 0xc5, 0x97, 0xed,
+ 0x34, 0xee, 0x75, 0x4c, 0x26, 0xbe, 0xf8, 0x61, 0xd5, 0x30, 0x9a, 0xe0,
+ 0x42, 0xa8, 0x13, 0x5f, 0xe2, 0x73, 0x7f, 0x1a, 0x02, 0xa8, 0x13, 0x5f,
+ 0xee, 0x67, 0x9b, 0x81, 0x9d, 0x53, 0x09, 0xae, 0xc1, 0xaa, 0x61, 0x35,
+ 0xc6, 0x18, 0xb9, 0x84, 0xd5, 0x89, 0xa8, 0x74, 0x6a, 0xc5, 0xc7, 0x23,
+ 0xe2, 0x06, 0xf4, 0x13, 0x08, 0xed, 0xf4, 0xcc, 0x26, 0x0b, 0x3e, 0x7a,
+ 0xe9, 0x3f, 0xf3, 0x23, 0xcd, 0xbe, 0xc1, 0x84, 0x96, 0x53, 0x1e, 0x6b,
+ 0x96, 0x5f, 0xff, 0x80, 0x77, 0x97, 0x3d, 0x1b, 0xf0, 0x41, 0xbc, 0x96,
+ 0x54, 0x2f, 0xa6, 0x32, 0x1f, 0xa3, 0x23, 0x72, 0x02, 0x84, 0x8f, 0x25,
+ 0x02, 0xfe, 0x55, 0xc0, 0x48, 0x2f, 0xff, 0xb0, 0xcf, 0x3b, 0x7e, 0x3e,
+ 0x10, 0x61, 0x2c, 0xbf, 0xf4, 0x89, 0xcd, 0x9a, 0x4d, 0xa9, 0x2c, 0xbf,
+ 0xe7, 0x34, 0xb2, 0x69, 0x47, 0x4b, 0x2b, 0x47, 0xf4, 0x48, 0x17, 0xff,
+ 0xf1, 0x0f, 0x0a, 0x0c, 0xf9, 0xaf, 0xcc, 0xc2, 0x35, 0x65, 0xf3, 0xef,
+ 0xc3, 0x16, 0x5b, 0x6a, 0x59, 0x7f, 0xfc, 0xf2, 0xf4, 0x43, 0x7f, 0x8c,
+ 0x5d, 0x49, 0x65, 0x48, 0xf9, 0x3c, 0x2d, 0x7a, 0x68, 0xe2, 0xcb, 0xc4,
+ 0x03, 0xac, 0xbf, 0xe8, 0x0f, 0xc9, 0xb7, 0x88, 0x75, 0x97, 0xfd, 0x9f,
+ 0x6c, 0xe4, 0xf8, 0x62, 0xcb, 0xa0, 0xeb, 0x2e, 0xce, 0x42, 0x30, 0xf0,
+ 0x77, 0x43, 0x9e, 0x3b, 0xdb, 0x39, 0xbf, 0xfc, 0xf2, 0xf4, 0x6f, 0x10,
+ 0xee, 0xfa, 0xed, 0x65, 0x42, 0xb5, 0x3c, 0x86, 0x43, 0x10, 0xe9, 0x69,
+ 0xe1, 0x10, 0x50, 0xe5, 0x0a, 0xb5, 0xfe, 0x6d, 0xfb, 0x3c, 0xfc, 0xdc,
+ 0x59, 0x7f, 0x7c, 0x2f, 0xce, 0x7d, 0x65, 0xfb, 0x91, 0x80, 0x85, 0x97,
+ 0xc0, 0xf1, 0x67, 0x47, 0xa9, 0xf2, 0xeb, 0xfe, 0xf4, 0x08, 0x7c, 0xde,
+ 0xdd, 0xac, 0xac, 0x4c, 0x0d, 0xe1, 0x1d, 0xc3, 0x9b, 0xcd, 0xa3, 0x56,
+ 0x5d, 0xa0, 0x2c, 0xac, 0x36, 0x8c, 0x3b, 0x74, 0xfa, 0x59, 0x70, 0x26,
+ 0x59, 0x7f, 0xf1, 0xe6, 0x93, 0x94, 0xe3, 0x82, 0x9d, 0x65, 0x41, 0xfb,
+ 0x0c, 0x63, 0x06, 0x2f, 0x67, 0x24, 0xb2, 0xf9, 0xbc, 0xe7, 0x59, 0x7d,
+ 0xa8, 0xe4, 0xeb, 0x2b, 0x47, 0xc1, 0xf1, 0xc1, 0x08, 0x6a, 0x1d, 0x4f,
+ 0x8c, 0xf2, 0x85, 0x07, 0x2f, 0x0b, 0x21, 0x9e, 0x6c, 0x65, 0x3d, 0xca,
+ 0xf1, 0xea, 0x3a, 0x86, 0x87, 0x3c, 0xd2, 0xfc, 0x75, 0x2a, 0x70, 0xf0,
+ 0xe5, 0xf4, 0xa8, 0xd0, 0x46, 0xc8, 0x46, 0x9c, 0x8d, 0xbf, 0xf4, 0x89,
+ 0x4d, 0xf2, 0xf7, 0x0c, 0x8d, 0xcf, 0x6d, 0xa0, 0x48, 0x4a, 0xee, 0xc2,
+ 0x36, 0xfa, 0x73, 0xff, 0x8b, 0x2e, 0xc2, 0x59, 0x77, 0xf8, 0xb2, 0xa0,
+ 0xd6, 0x10, 0xad, 0xff, 0xd9, 0xec, 0xff, 0x5d, 0xb6, 0xbd, 0x8b, 0x2e,
+ 0xce, 0x2c, 0xa9, 0x1f, 0xd0, 0xc7, 0xc0, 0x8b, 0x7f, 0x4a, 0x69, 0x41,
+ 0x7d, 0x65, 0xfd, 0x92, 0x20, 0xbf, 0x16, 0x5f, 0x75, 0xc6, 0x85, 0x97,
+ 0xfb, 0x0b, 0x77, 0xec, 0x46, 0xac, 0xae, 0x91, 0x63, 0xa2, 0xef, 0x16,
+ 0x00, 0x8a, 0xfb, 0x34, 0xc6, 0xac, 0xbc, 0x64, 0xe7, 0x59, 0x7f, 0xfd,
+ 0xbf, 0x59, 0x3e, 0xc0, 0xc6, 0x7e, 0x3a, 0x92, 0xcb, 0xfe, 0xf4, 0x1c,
+ 0x9e, 0x59, 0xe5, 0x95, 0x09, 0x85, 0x8c, 0xfb, 0x08, 0x9c, 0x7f, 0x8a,
+ 0xb7, 0xf7, 0xa0, 0x42, 0xe8, 0x0b, 0x2e, 0xcd, 0xd5, 0x97, 0x09, 0xc5,
+ 0x97, 0xef, 0x99, 0x85, 0x3a, 0xcb, 0x47, 0x8f, 0x04, 0x86, 0x2b, 0x68,
+ 0x44, 0x04, 0x96, 0xaf, 0x66, 0x18, 0xb2, 0xe6, 0x35, 0x65, 0x4e, 0x6c,
+ 0xd8, 0x72, 0xfd, 0xfc, 0x99, 0x8e, 0xb2, 0xfd, 0x1d, 0x00, 0x10, 0xb2,
+ 0xa0, 0xf4, 0x08, 0xa2, 0xfd, 0x1b, 0xe0, 0xbe, 0xb2, 0xfc, 0xdb, 0xfe,
+ 0xd3, 0xac, 0xbf, 0x7f, 0xd1, 0xa9, 0x2c, 0xbf, 0xf6, 0x1e, 0x0a, 0x00,
+ 0x77, 0x92, 0xcb, 0xff, 0x1c, 0x98, 0xd8, 0xff, 0x1b, 0x4b, 0x2f, 0xa5,
+ 0xfc, 0xed, 0x65, 0x61, 0xf0, 0xb9, 0xf5, 0xc5, 0x0b, 0x2f, 0xfb, 0xcf,
+ 0x28, 0x98, 0xa0, 0xeb, 0x2f, 0xe1, 0xbf, 0xfc, 0xc6, 0x2c, 0xbf, 0x16,
+ 0x09, 0x93, 0x2c, 0xbf, 0xff, 0x67, 0x60, 0x83, 0xe7, 0xdb, 0x99, 0x84,
+ 0x6a, 0xcb, 0xf8, 0xed, 0x07, 0x72, 0x59, 0x5e, 0x3f, 0xf0, 0x2a, 0x5f,
+ 0xfc, 0xc7, 0x18, 0x5f, 0x52, 0xce, 0xbe, 0xb2, 0xc5, 0x87, 0xcf, 0xd9,
+ 0x15, 0xff, 0x9c, 0x81, 0xd7, 0xf5, 0x18, 0x62, 0xcb, 0xff, 0x73, 0xcd,
+ 0xb3, 0xa9, 0x46, 0x4e, 0xb2, 0xff, 0x60, 0xf5, 0xa6, 0x9b, 0x8b, 0x2e,
+ 0xd9, 0xba, 0xb2, 0xd9, 0xb8, 0x8d, 0x10, 0x1f, 0xfd, 0x0b, 0x79, 0xa5,
+ 0xec, 0x1e, 0xda, 0xcb, 0xfe, 0xf3, 0x9f, 0xcd, 0x1d, 0x49, 0x65, 0xfe,
+ 0xc3, 0x8d, 0x80, 0x19, 0x2c, 0xbe, 0xf3, 0xb9, 0xd6, 0x5f, 0x3f, 0xbc,
+ 0xcb, 0x28, 0x8f, 0x0b, 0x79, 0x0d, 0xf8, 0xa5, 0xb6, 0xf3, 0xac, 0xa8,
+ 0x3c, 0xe1, 0x08, 0xea, 0x15, 0x3e, 0x4a, 0x1f, 0x06, 0xa3, 0xb0, 0xff,
+ 0x8e, 0x41, 0x0c, 0x3b, 0xff, 0xfc, 0xdb, 0xc8, 0x3c, 0xd8, 0x21, 0x40,
+ 0xfc, 0xf2, 0xce, 0x2c, 0xb8, 0xd6, 0x59, 0x53, 0xaf, 0x1c, 0x8c, 0x83,
+ 0xb2, 0x8e, 0x8a, 0xb7, 0x0a, 0x35, 0x09, 0xd3, 0x90, 0x78, 0x55, 0xce,
+ 0x08, 0xbb, 0xf2, 0xe2, 0xb7, 0xb1, 0x6d, 0xb2, 0x5f, 0xef, 0x75, 0x2e,
+ 0x7b, 0x27, 0x59, 0x7f, 0xcf, 0xe9, 0x98, 0xbd, 0x9d, 0x2c, 0xa8, 0x3e,
+ 0xfc, 0x36, 0xbc, 0x1e, 0xa7, 0x59, 0x7e, 0x9a, 0x51, 0xfe, 0x2c, 0xbb,
+ 0x80, 0x59, 0x5e, 0x3d, 0xf0, 0x0f, 0xed, 0x94, 0xdf, 0xff, 0xff, 0x7b,
+ 0x08, 0x18, 0x5f, 0xf6, 0x7a, 0x32, 0x66, 0xd4, 0xde, 0x6e, 0xbe, 0xb2,
+ 0xfe, 0xd3, 0x77, 0xec, 0x99, 0x65, 0xff, 0xf1, 0x64, 0xce, 0x0c, 0xfc,
+ 0x6f, 0x62, 0x02, 0xca, 0x39, 0xff, 0x7c, 0xbe, 0xb1, 0x31, 0xd7, 0x87,
+ 0xdd, 0xf1, 0x46, 0x18, 0xb2, 0xf7, 0x5c, 0x75, 0x97, 0xdc, 0x8d, 0x42,
+ 0xca, 0x83, 0x7d, 0xf1, 0xda, 0x87, 0x77, 0xa1, 0x3c, 0x2e, 0x24, 0x72,
+ 0x38, 0x5b, 0xe5, 0xaa, 0x2e, 0xee, 0x39, 0xce, 0xa1, 0x94, 0xd1, 0xf5,
+ 0xee, 0x24, 0x4d, 0x0a, 0xfd, 0x2d, 0xbc, 0xf5, 0x51, 0x46, 0x73, 0xf7,
+ 0xf0, 0xc6, 0x9f, 0xbc, 0x9c, 0x45, 0xfb, 0xdc, 0xe7, 0x16, 0x5f, 0xff,
+ 0x31, 0x61, 0xe0, 0x42, 0x0c, 0x8b, 0x0e, 0xb2, 0xfc, 0x41, 0x96, 0x71,
+ 0x65, 0xff, 0x60, 0xfd, 0x1f, 0xf4, 0x71, 0x65, 0xc3, 0x6c, 0x3d, 0xf2,
+ 0x27, 0xbf, 0xfc, 0xd1, 0xff, 0x05, 0xcf, 0x34, 0xa2, 0x75, 0x97, 0xf1,
+ 0x66, 0xb5, 0x9d, 0x2c, 0xaf, 0x1f, 0xc7, 0x12, 0xef, 0xfb, 0x5a, 0x8e,
+ 0xfd, 0xd3, 0xee, 0x2c, 0xbc, 0x51, 0xc5, 0x97, 0xd8, 0x58, 0x75, 0x94,
+ 0xb2, 0xa0, 0xf1, 0xa4, 0x36, 0x12, 0x0b, 0xfb, 0xb0, 0xb8, 0xcf, 0x0b,
+ 0x2f, 0xfb, 0xcd, 0x2f, 0x3c, 0x98, 0xeb, 0x2f, 0x8a, 0x05, 0x56, 0xd2,
+ 0x59, 0x7f, 0xee, 0x31, 0x75, 0x2f, 0xb7, 0x19, 0x65, 0x62, 0x28, 0xdc,
+ 0xe3, 0xe5, 0xb7, 0xcc, 0x4d, 0x32, 0xcb, 0xf7, 0xfd, 0x01, 0x15, 0xac,
+ 0xbb, 0xce, 0xb2, 0x9c, 0xf0, 0xbe, 0x59, 0x7f, 0xe6, 0x3e, 0x0f, 0xcd,
+ 0xc2, 0xc5, 0x97, 0xc7, 0x81, 0xc2, 0xca, 0x23, 0xdd, 0xe1, 0xe5, 0x49,
+ 0x70, 0x93, 0x21, 0x59, 0xdc, 0x28, 0xd8, 0x8a, 0x68, 0x42, 0x68, 0xb8,
+ 0xf0, 0xd1, 0xf1, 0x71, 0x31, 0xfd, 0xfa, 0xfb, 0xd8, 0x07, 0x59, 0x7c,
+ 0x51, 0xa9, 0x2c, 0xbf, 0xef, 0x44, 0x98, 0x88, 0x3d, 0x2c, 0xbf, 0xe8,
+ 0x93, 0x7e, 0x50, 0x40, 0x59, 0x7f, 0xd1, 0x9f, 0x10, 0x00, 0x8e, 0x96,
+ 0x5e, 0xc2, 0x35, 0x65, 0xb5, 0x08, 0xe6, 0xc2, 0x1d, 0x1c, 0x1c, 0xdc,
+ 0x56, 0x75, 0x62, 0x59, 0x7f, 0xd1, 0xb8, 0x4f, 0xf9, 0x36, 0xf5, 0x97,
+ 0xbd, 0x03, 0x59, 0x7f, 0x14, 0x77, 0xa8, 0x92, 0xcb, 0xff, 0xce, 0xdf,
+ 0x90, 0x4b, 0xfc, 0xf3, 0xc9, 0x60, 0x86, 0xb6, 0xe8, 0xf2, 0xca, 0x64,
+ 0x5c, 0xf9, 0x27, 0x7a, 0xd5, 0xff, 0xb8, 0x27, 0xd8, 0x83, 0x2c, 0xe2,
+ 0xcb, 0x87, 0xc5, 0x95, 0x24, 0xdf, 0x37, 0x21, 0xeb, 0xe3, 0x12, 0x3f,
+ 0xbf, 0xff, 0xb3, 0xac, 0xe3, 0x97, 0x9a, 0x3f, 0xe0, 0xb9, 0xd6, 0x56,
+ 0xc5, 0x70, 0x71, 0x18, 0x3b, 0x29, 0x3c, 0x71, 0x84, 0x8b, 0x78, 0xed,
+ 0x8b, 0x2f, 0x71, 0xfb, 0x59, 0x6c, 0x59, 0x7e, 0x09, 0xdb, 0xd0, 0xb2,
+ 0xfd, 0x9a, 0xee, 0x31, 0x65, 0x4e, 0x7b, 0xc4, 0x20, 0x21, 0x3d, 0xff,
+ 0x61, 0xf3, 0x4d, 0x3b, 0x9d, 0x65, 0xff, 0x41, 0x77, 0xb1, 0xb5, 0x9d,
+ 0xac, 0xbf, 0xfd, 0xb3, 0xfe, 0xc3, 0xe7, 0x71, 0xe8, 0x3a, 0xcb, 0xce,
+ 0x7e, 0x2c, 0xac, 0x3e, 0x87, 0x4c, 0xa0, 0x23, 0x0f, 0xf0, 0xa3, 0xbb,
+ 0x27, 0x59, 0x7f, 0xf4, 0x78, 0x41, 0xeb, 0x59, 0xff, 0x32, 0xcb, 0xfe,
+ 0x28, 0xeb, 0x6c, 0xdf, 0xe7, 0x96, 0x5d, 0xfd, 0xb5, 0x96, 0x73, 0x9e,
+ 0xb9, 0x1e, 0xde, 0xdb, 0x60, 0x2c, 0xbf, 0xfe, 0x2f, 0xbb, 0xf8, 0xa3,
+ 0xfc, 0x33, 0x3c, 0xb2, 0x98, 0xfb, 0x5c, 0x7e, 0xff, 0xd8, 0x7c, 0xdd,
+ 0xcc, 0x08, 0xaf, 0x8b, 0x2f, 0xe1, 0x06, 0xfa, 0xc3, 0xac, 0xbe, 0xdf,
+ 0x05, 0x25, 0x96, 0xd6, 0xc3, 0xd1, 0xc2, 0xea, 0xfa, 0x2f, 0x84, 0x84,
+ 0xad, 0xff, 0xc7, 0xe3, 0xcb, 0x51, 0xc8, 0x29, 0xd6, 0x5f, 0xf4, 0x7f,
+ 0xd8, 0x7c, 0xd6, 0x2c, 0xbf, 0x7f, 0xcd, 0x1c, 0x59, 0x7a, 0x77, 0x2d,
+ 0x1e, 0xf7, 0x0d, 0xef, 0xff, 0xe6, 0xfc, 0x7f, 0x85, 0x9e, 0x68, 0xff,
+ 0x9e, 0x4b, 0x2f, 0xfa, 0x01, 0xc1, 0x85, 0xf5, 0x25, 0x97, 0xb5, 0xce,
+ 0x2e, 0x20, 0x35, 0xf7, 0x6e, 0xfd, 0xaa, 0x20, 0x30, 0xb3, 0x55, 0x6c,
+ 0x92, 0x29, 0x74, 0xc7, 0x7f, 0xc7, 0x7e, 0x9e, 0x5c, 0x69, 0x2c, 0xbf,
+ 0xe8, 0xf7, 0x6d, 0xc7, 0x69, 0xd6, 0x5a, 0x36, 0x22, 0x6b, 0x0a, 0x34,
+ 0x73, 0x78, 0xef, 0x25, 0x95, 0xe3, 0xd2, 0x01, 0xb5, 0xc5, 0x8b, 0x2e,
+ 0x70, 0x2c, 0xa8, 0x3c, 0xd2, 0x22, 0xf8, 0xad, 0xbb, 0x59, 0x5a, 0x37,
+ 0xe4, 0x5b, 0x58, 0xad, 0xa9, 0xe1, 0x45, 0xc3, 0x31, 0x25, 0x3a, 0xd0,
+ 0xd7, 0xc9, 0x3a, 0x87, 0xde, 0x8a, 0x0e, 0x2f, 0xe8, 0x4e, 0x02, 0x12,
+ 0x65, 0x0d, 0xef, 0xcb, 0x93, 0xbe, 0x1f, 0xa3, 0x6d, 0x65, 0xff, 0xe3,
+ 0xbf, 0xf8, 0x19, 0x79, 0xd8, 0x9d, 0x65, 0xff, 0xfc, 0xc3, 0x2c, 0xe4,
+ 0x6b, 0x67, 0x3c, 0xe3, 0x81, 0xac, 0xbd, 0xbe, 0x3c, 0xb2, 0xa1, 0x92,
+ 0xbf, 0x21, 0xbc, 0x7b, 0x69, 0xf5, 0x47, 0x84, 0x78, 0x09, 0x78, 0x90,
+ 0x22, 0xdd, 0xf9, 0xbe, 0xfb, 0x78, 0xb2, 0xfd, 0x9a, 0x90, 0x92, 0x59,
+ 0x7f, 0xa7, 0xe4, 0x1d, 0xfa, 0xfa, 0xca, 0x9c, 0xf7, 0x88, 0xa6, 0xe7,
+ 0xe9, 0x65, 0xfc, 0xdb, 0xdd, 0xcb, 0xb5, 0x97, 0xbc, 0xfb, 0x8b, 0x2f,
+ 0xa0, 0x1b, 0x78, 0xb2, 0xf8, 0xe7, 0x7f, 0xac, 0xa9, 0x26, 0xa7, 0x90,
+ 0x87, 0x39, 0x17, 0x85, 0xc0, 0x5d, 0xf1, 0xf1, 0x09, 0x2f, 0xec, 0xdd,
+ 0x77, 0xf7, 0x16, 0x5f, 0xfd, 0x9c, 0xfb, 0xf4, 0x26, 0xec, 0x14, 0x96,
+ 0x5b, 0x16, 0x5f, 0xfd, 0x84, 0xf2, 0xf3, 0x9c, 0xef, 0x25, 0x96, 0x9b,
+ 0x68, 0x3d, 0x21, 0x40, 0x85, 0xff, 0xfe, 0x60, 0xcf, 0x33, 0xbc, 0xff,
+ 0xc9, 0x8a, 0x0f, 0xe7, 0x59, 0x7f, 0x4e, 0x36, 0xd4, 0x6f, 0x59, 0x7f,
+ 0xfe, 0xe6, 0xcc, 0x1e, 0xce, 0x66, 0x80, 0x7c, 0xdb, 0xc5, 0x94, 0x48,
+ 0x8c, 0xf9, 0x85, 0xfe, 0x23, 0x5f, 0xbf, 0x34, 0xeb, 0x2f, 0x7c, 0x01,
+ 0x59, 0x4c, 0x7a, 0x44, 0x6b, 0x7e, 0x3e, 0xd7, 0xb5, 0xed, 0x7b, 0x52,
+ 0xcb, 0xff, 0xfa, 0x59, 0xc6, 0xd6, 0x98, 0xe2, 0x7f, 0xd8, 0x67, 0xd6,
+ 0x54, 0x26, 0x5d, 0x8e, 0x8c, 0x40, 0xe7, 0xb7, 0xff, 0xde, 0x76, 0xfc,
+ 0x34, 0xb0, 0x80, 0x08, 0x59, 0x79, 0xfd, 0x0b, 0x2e, 0xc0, 0x2c, 0xb4,
+ 0xfe, 0x36, 0x26, 0x0d, 0xdf, 0xf7, 0xa3, 0x9f, 0xe6, 0x04, 0x56, 0xb2,
+ 0xff, 0xd0, 0xde, 0xf6, 0x7f, 0xd9, 0x25, 0x97, 0xfb, 0x0a, 0x59, 0xc1,
+ 0x0e, 0xb2, 0xec, 0x21, 0xa2, 0xb7, 0x47, 0xbf, 0x3d, 0xa9, 0x93, 0x8d,
+ 0x77, 0xd3, 0x21, 0xad, 0x7f, 0xfa, 0x59, 0xd4, 0x84, 0x80, 0x0b, 0x30,
+ 0xc3, 0x12, 0x5f, 0x8e, 0x66, 0x36, 0xf5, 0x97, 0x61, 0x4c, 0x7f, 0x82,
+ 0x29, 0x5f, 0xff, 0x73, 0x9e, 0x0f, 0x71, 0x26, 0xd0, 0x30, 0x96, 0x54,
+ 0x8f, 0xf8, 0xc2, 0xea, 0x84, 0xd5, 0x1e, 0x33, 0x1b, 0xff, 0xed, 0x48,
+ 0x7e, 0x8e, 0x16, 0x18, 0xfa, 0x35, 0x65, 0xe0, 0x07, 0x8b, 0x2f, 0xd9,
+ 0x85, 0x12, 0x59, 0x6e, 0x41, 0xe1, 0x10, 0xed, 0x3a, 0x2e, 0x7f, 0x09,
+ 0x3a, 0x85, 0xfa, 0x41, 0xb5, 0x61, 0x7b, 0x42, 0x6b, 0x46, 0x5e, 0x94,
+ 0x38, 0x52, 0xc6, 0xc3, 0x0e, 0x1b, 0xfe, 0x62, 0x97, 0x05, 0x56, 0xd5,
+ 0xb5, 0xed, 0x4b, 0x2f, 0x09, 0xa3, 0x56, 0x5f, 0x4d, 0xcc, 0x99, 0x65,
+ 0xf8, 0x11, 0xfc, 0xdc, 0x59, 0x7f, 0xc3, 0xdb, 0x63, 0x4d, 0x82, 0xfa,
+ 0xcb, 0xfb, 0x9a, 0xd3, 0x4d, 0xc5, 0x97, 0xfa, 0x33, 0x5d, 0xbb, 0xf6,
+ 0xa8, 0x82, 0x57, 0xfd, 0x1f, 0xcd, 0x76, 0xef, 0xda, 0xa2, 0xf9, 0x5f,
+ 0x9c, 0x7e, 0x83, 0x56, 0x5f, 0xff, 0xf6, 0x36, 0xb0, 0x7e, 0x8e, 0xa5,
+ 0xa8, 0xff, 0x04, 0x29, 0x2c, 0xbf, 0xf1, 0x67, 0xfe, 0xdc, 0xfe, 0x01,
+ 0x65, 0xd9, 0xc1, 0x4a, 0x70, 0x23, 0x2f, 0xed, 0x00, 0xe8, 0xc4, 0x51,
+ 0xc6, 0x7a, 0xc5, 0x44, 0xa5, 0x1d, 0xf5, 0x12, 0xa7, 0x8d, 0xf2, 0x93,
+ 0xef, 0xfe, 0x8f, 0x31, 0xb9, 0xa9, 0xce, 0x1e, 0x96, 0x5f, 0xf0, 0xf5,
+ 0x87, 0xc9, 0x38, 0xd6, 0x5f, 0xff, 0x82, 0xfc, 0xc2, 0xef, 0xcc, 0x3f,
+ 0x67, 0x5b, 0xab, 0x2a, 0x15, 0xe0, 0x60, 0xfb, 0x4a, 0x9c, 0xf1, 0x6b,
+ 0xa3, 0x91, 0xc5, 0xfa, 0x35, 0x83, 0x85, 0x97, 0xe9, 0x60, 0x04, 0xfa,
+ 0xcb, 0xfb, 0xdb, 0x7e, 0x6e, 0xfc, 0xb2, 0x99, 0x10, 0x2e, 0x4c, 0x12,
+ 0x9b, 0xf0, 0x22, 0x5c, 0xc5, 0x97, 0xff, 0xdd, 0xfa, 0x35, 0x9c, 0x20,
+ 0xbc, 0x8d, 0x75, 0x97, 0xff, 0xe7, 0xdf, 0xb3, 0x9e, 0x76, 0xfc, 0x7f,
+ 0xd9, 0xf5, 0x94, 0x14, 0x54, 0x08, 0xa1, 0x7f, 0xe7, 0x9f, 0xd1, 0x3e,
+ 0x7f, 0x98, 0xb2, 0xa0, 0xf8, 0xc8, 0x92, 0xff, 0xbf, 0x07, 0xf6, 0x6f,
+ 0xce, 0x2c, 0xbf, 0xe8, 0x3f, 0x21, 0xa7, 0x7f, 0xac, 0xa9, 0x1f, 0x97,
+ 0xce, 0xaf, 0xfd, 0x3b, 0xf5, 0xb7, 0x9f, 0x27, 0xde, 0xb2, 0xff, 0xfb,
+ 0x3f, 0x05, 0xfe, 0x66, 0x1a, 0x6b, 0xc9, 0x65, 0xfc, 0x6e, 0x7f, 0xf8,
+ 0x35, 0x97, 0xfe, 0xc1, 0xc4, 0xa3, 0xd8, 0x07, 0x59, 0x7f, 0x3c, 0x83,
+ 0x27, 0x1a, 0xcb, 0xff, 0xfe, 0xf0, 0x5e, 0x7d, 0x47, 0x9d, 0xb9, 0xcc,
+ 0x35, 0xc8, 0x0b, 0x2f, 0xcd, 0x3f, 0x38, 0xeb, 0x28, 0x68, 0x8e, 0xf3,
+ 0x35, 0xff, 0xf7, 0xf9, 0xc8, 0xc2, 0x1f, 0xa3, 0xd1, 0xc5, 0x97, 0x8c,
+ 0x30, 0xc4, 0x97, 0xef, 0x67, 0x6f, 0xa4, 0x82, 0xcd, 0x05, 0xff, 0xfe,
+ 0x9b, 0x51, 0xbf, 0x61, 0xaf, 0xb0, 0x49, 0xb9, 0xb3, 0x3a, 0xfa, 0xca,
+ 0x84, 0xce, 0x9c, 0x8f, 0xed, 0xc2, 0x1d, 0x5f, 0xf7, 0x98, 0xcf, 0xcd,
+ 0xa8, 0xfa, 0xcb, 0xff, 0x37, 0xc3, 0x9f, 0x73, 0xe1, 0x2c, 0xa9, 0x1f,
+ 0xbe, 0x8e, 0xef, 0xfa, 0x01, 0xfc, 0x29, 0x67, 0x16, 0x5f, 0xf6, 0x01,
+ 0xc8, 0x12, 0x36, 0x4b, 0x29, 0x91, 0x25, 0xe2, 0x22, 0x37, 0xa9, 0xd7,
+ 0x19, 0xbb, 0x44, 0xd2, 0x79, 0xcb, 0x80, 0x78, 0x51, 0xfa, 0xfe, 0x34,
+ 0x6b, 0x9f, 0xeb, 0x2f, 0x73, 0x27, 0x59, 0x71, 0x4e, 0x03, 0x67, 0xf1,
+ 0x6a, 0x59, 0x50, 0x6e, 0x0e, 0x5b, 0x4b, 0x29, 0x65, 0xb8, 0x61, 0x6d,
+ 0xba, 0x17, 0x7e, 0x76, 0x9c, 0x9d, 0x65, 0xff, 0xf3, 0x76, 0xc3, 0xe4,
+ 0x79, 0xc8, 0x39, 0xe5, 0x95, 0x24, 0x4f, 0x70, 0xab, 0xe4, 0xd7, 0xfe,
+ 0x3c, 0x75, 0xc2, 0xc9, 0xc4, 0x92, 0xcb, 0xff, 0xfc, 0xde, 0x72, 0xea,
+ 0x42, 0x4a, 0x0a, 0x4e, 0x7c, 0x1a, 0xcb, 0xff, 0xd9, 0x9e, 0x1f, 0xa3,
+ 0x99, 0xe6, 0x02, 0xcb, 0xf4, 0xd2, 0x8d, 0x71, 0x65, 0xfe, 0xc2, 0x0c,
+ 0xb9, 0x3b, 0xac, 0xb1, 0xbb, 0x0f, 0x70, 0x65, 0x37, 0xfe, 0x6f, 0xce,
+ 0x1e, 0x6c, 0xd6, 0xa1, 0x65, 0x42, 0x7c, 0x53, 0x98, 0x49, 0x04, 0x6c,
+ 0x0d, 0x0a, 0x4f, 0x95, 0xdf, 0x6c, 0x6f, 0x05, 0x65, 0xfb, 0x25, 0xe8,
+ 0xd2, 0xcb, 0xe3, 0x76, 0x79, 0x96, 0x57, 0x67, 0xe1, 0xb8, 0x49, 0xa2,
+ 0x7b, 0xf3, 0x78, 0xd8, 0xe9, 0x65, 0xfb, 0x06, 0x51, 0xd2, 0xcb, 0x7e,
+ 0x0f, 0x40, 0x8a, 0x6f, 0xff, 0xff, 0xdd, 0x7c, 0xa0, 0xfc, 0x1f, 0xa3,
+ 0x99, 0x26, 0x34, 0xd7, 0xf9, 0x41, 0xf8, 0xb2, 0xff, 0x02, 0x4d, 0xfe,
+ 0x08, 0x75, 0x97, 0xfe, 0xe3, 0xcb, 0x99, 0xdc, 0x1d, 0x96, 0x56, 0x8f,
+ 0xcf, 0xe6, 0xb7, 0xfd, 0xdf, 0x98, 0x00, 0x8d, 0x49, 0x65, 0xf6, 0xa7,
+ 0x69, 0xd6, 0x5d, 0xd1, 0x6c, 0x3d, 0xec, 0x3a, 0xa8, 0x54, 0x9e, 0xd0,
+ 0x83, 0x72, 0x60, 0xc3, 0xdc, 0x48, 0x40, 0x5f, 0xf7, 0x50, 0xc7, 0xc2,
+ 0xcd, 0xc5, 0x97, 0xbe, 0xfd, 0xac, 0xbf, 0xfd, 0x2e, 0x60, 0xf3, 0xcc,
+ 0xff, 0xf4, 0x2c, 0xa9, 0xd1, 0x3f, 0xd9, 0xd7, 0x43, 0xb7, 0xe9, 0xfd,
+ 0x01, 0xc5, 0x97, 0xff, 0xd2, 0x83, 0xea, 0x1a, 0x4f, 0xc7, 0x20, 0x2c,
+ 0xbf, 0x9b, 0x98, 0x31, 0x31, 0x65, 0xfb, 0x75, 0x8b, 0x37, 0xac, 0xbf,
+ 0xb0, 0x6c, 0x1e, 0xfd, 0xd9, 0xec, 0x39, 0x6d, 0xfd, 0xc9, 0x31, 0xde,
+ 0x4b, 0x2a, 0x13, 0x3f, 0xe8, 0xa3, 0x50, 0xa5, 0x02, 0x2d, 0xfe, 0xe1,
+ 0x66, 0xff, 0x3c, 0x96, 0x5e, 0xe4, 0xb7, 0xac, 0xa6, 0x3d, 0x3d, 0xc3,
+ 0x4b, 0xff, 0xd1, 0x38, 0x9e, 0x8e, 0xbf, 0x93, 0x90, 0xd6, 0x56, 0x2a,
+ 0x79, 0x68, 0xdc, 0x9e, 0x12, 0xc4, 0x49, 0x7f, 0x80, 0x77, 0x01, 0xdc,
+ 0x0b, 0x2f, 0xfe, 0x79, 0x60, 0xc9, 0x9f, 0xd0, 0x75, 0x97, 0x3f, 0x96,
+ 0x57, 0x8f, 0x5f, 0xe8, 0x37, 0x19, 0xda, 0xcb, 0xfe, 0x1b, 0x89, 0xa2,
+ 0x68, 0x35, 0x65, 0xf4, 0x61, 0x7c, 0x52, 0x7a, 0x43, 0x19, 0xbf, 0xde,
+ 0xcd, 0xfb, 0x39, 0x2e, 0xd6, 0x57, 0x0f, 0xd3, 0xe7, 0x75, 0xf4, 0xc2,
+ 0x83, 0x0e, 0x8b, 0xff, 0xc5, 0x9f, 0x69, 0x39, 0x67, 0xfc, 0xcb, 0x2f,
+ 0xe2, 0x7e, 0xa4, 0xd8, 0xb2, 0xff, 0x10, 0x0b, 0x3f, 0xec, 0xd8, 0x7e,
+ 0x5e, 0x46, 0xbf, 0x8b, 0x60, 0x9a, 0xf3, 0xac, 0xbf, 0xf0, 0x5e, 0x5b,
+ 0x21, 0x87, 0x87, 0x59, 0x4c, 0x8b, 0x97, 0x4a, 0x23, 0x0b, 0xff, 0x69,
+ 0x81, 0x3f, 0xa3, 0x81, 0xe2, 0xcb, 0xf6, 0x69, 0xfa, 0x31, 0x65, 0xa4,
+ 0xb2, 0xff, 0xfc, 0x61, 0x60, 0xf4, 0xc1, 0x9c, 0x7e, 0x82, 0x9d, 0x65,
+ 0xa7, 0x83, 0xe8, 0xc1, 0x1a, 0x9d, 0x17, 0x1c, 0x84, 0x8d, 0xfe, 0x98,
+ 0x9c, 0xcf, 0xe7, 0x96, 0x5e, 0xf6, 0x76, 0xb2, 0xf1, 0x86, 0x18, 0x92,
+ 0xfe, 0x04, 0x16, 0x75, 0xf4, 0x82, 0xcd, 0x05, 0x6c, 0x45, 0x86, 0xd9,
+ 0xa0, 0x87, 0xb7, 0xff, 0xf0, 0xaf, 0x67, 0x7e, 0x61, 0x8f, 0x0c, 0xd9,
+ 0xfe, 0x64, 0xeb, 0x2b, 0xc8, 0x9d, 0x09, 0xb5, 0x42, 0xa9, 0x16, 0x87,
+ 0xc3, 0xc6, 0xed, 0x7f, 0xd9, 0xbf, 0x18, 0x6e, 0xe6, 0xac, 0xbf, 0xff,
+ 0x37, 0xfd, 0x1c, 0xc6, 0xff, 0x18, 0xba, 0x92, 0xca, 0xf2, 0x23, 0x45,
+ 0x67, 0x37, 0xe8, 0xf7, 0x23, 0x4b, 0x2f, 0xf8, 0x48, 0xe6, 0x18, 0x21,
+ 0x7d, 0x65, 0x4e, 0xde, 0x60, 0xca, 0x70, 0x38, 0x70, 0xdc, 0xc2, 0xee,
+ 0xe3, 0x32, 0xea, 0x12, 0x4d, 0x39, 0x11, 0x34, 0x37, 0xf5, 0x2a, 0xd8,
+ 0xf2, 0xc6, 0xfd, 0x2d, 0xc5, 0xd1, 0x8a, 0x39, 0x4e, 0x46, 0xa9, 0xf9,
+ 0x57, 0xc1, 0x86, 0x3e, 0xf2, 0x71, 0x09, 0xef, 0xf9, 0x8a, 0x77, 0x2f,
+ 0xe1, 0xd6, 0x5d, 0x00, 0x59, 0x58, 0x79, 0xbf, 0x37, 0xbf, 0xf8, 0xd1,
+ 0x3e, 0xdc, 0x2c, 0xde, 0xc3, 0x59, 0x7f, 0x16, 0x0f, 0xce, 0x62, 0xca,
+ 0xd1, 0xfa, 0x1d, 0x1e, 0xff, 0xff, 0xc5, 0x8c, 0x0d, 0x9e, 0x7f, 0xfc,
+ 0x33, 0xec, 0x13, 0x5a, 0xc9, 0xd6, 0x5e, 0x27, 0x3a, 0xcb, 0xff, 0x71,
+ 0xb4, 0xfe, 0x6e, 0x44, 0x96, 0x5f, 0xc3, 0xf6, 0x7f, 0x6f, 0x16, 0x59,
+ 0xa4, 0x8f, 0xbf, 0x39, 0xfc, 0x6c, 0xc3, 0xda, 0x84, 0xd8, 0x3d, 0x18,
+ 0xed, 0xfe, 0x23, 0x78, 0xda, 0x79, 0x2c, 0xbe, 0x27, 0xeb, 0xeb, 0x2f,
+ 0x61, 0x01, 0x65, 0xfd, 0xdc, 0x74, 0x50, 0x62, 0xcb, 0xfd, 0x21, 0xf8,
+ 0x27, 0x1e, 0x2c, 0xbc, 0x26, 0xde, 0x2c, 0xac, 0x3d, 0x40, 0x1a, 0x5f,
+ 0x67, 0xe6, 0x92, 0xcb, 0xff, 0xb7, 0x4a, 0x37, 0x78, 0xe4, 0x20, 0x38,
+ 0xb2, 0xbc, 0x7d, 0xae, 0x47, 0x7f, 0xec, 0xfc, 0x6b, 0x9e, 0x82, 0xfa,
+ 0xe2, 0x08, 0x5f, 0xd9, 0xae, 0xdd, 0xfb, 0x54, 0x41, 0x01, 0x67, 0x95,
+ 0x7a, 0x06, 0xcb, 0x2a, 0x0f, 0xa7, 0x89, 0xd7, 0xfe, 0x22, 0xc3, 0x5f,
+ 0x0e, 0xe4, 0xb2, 0xed, 0xe3, 0x59, 0x7b, 0x7c, 0x1d, 0x65, 0xf7, 0x5c,
+ 0xcd, 0x2c, 0xbf, 0x4f, 0x9a, 0x89, 0x2c, 0xbe, 0xd6, 0x98, 0xc5, 0x94,
+ 0x73, 0xcb, 0xf1, 0x45, 0x42, 0x24, 0x1d, 0xba, 0xfe, 0xdc, 0x19, 0x8e,
+ 0x52, 0x59, 0x50, 0x9a, 0xa4, 0xe7, 0x78, 0x32, 0x50, 0xae, 0x09, 0x0d,
+ 0xff, 0xff, 0xe8, 0x2e, 0xf9, 0x05, 0xfe, 0x60, 0x4e, 0x27, 0x1f, 0x51,
+ 0xde, 0x12, 0xcb, 0xff, 0xd3, 0x49, 0x8b, 0xf0, 0x09, 0x89, 0xa6, 0x59,
+ 0x71, 0x4c, 0xb2, 0xd0, 0x33, 0xe2, 0xc4, 0xba, 0x85, 0xd1, 0x79, 0xcc,
+ 0xcd, 0x22, 0xec, 0x6f, 0x50, 0x83, 0xf4, 0x23, 0x81, 0x0d, 0x42, 0x8d,
+ 0xd7, 0xe9, 0xdb, 0xe1, 0xb3, 0x69, 0x2c, 0xbd, 0x1a, 0x02, 0xcb, 0x78,
+ 0x66, 0xb5, 0x84, 0x6f, 0xef, 0x36, 0x8b, 0x27, 0x59, 0x77, 0x3c, 0xb2,
+ 0xb4, 0x78, 0x80, 0x2d, 0xbf, 0x6a, 0x3b, 0xc2, 0x59, 0x58, 0x79, 0x2e,
+ 0x45, 0x7f, 0x7b, 0x3f, 0xf6, 0x3a, 0xcb, 0xff, 0xb8, 0x32, 0x69, 0xc4,
+ 0xd1, 0x46, 0x2c, 0xbf, 0xbe, 0x26, 0x79, 0xfa, 0x59, 0x5d, 0x22, 0x83,
+ 0xc5, 0xa4, 0x89, 0x7f, 0xc5, 0x3e, 0x68, 0x04, 0x10, 0x2c, 0xbf, 0xb3,
+ 0xaf, 0xeb, 0x50, 0xb2, 0xff, 0xee, 0x13, 0xfd, 0xce, 0x24, 0x4f, 0x8b,
+ 0x28, 0x67, 0xe5, 0xc2, 0xea, 0x84, 0x7e, 0xb1, 0x80, 0x61, 0x57, 0x7f,
+ 0xce, 0xdf, 0x73, 0xb9, 0x01, 0x65, 0xed, 0xfe, 0xc5, 0x96, 0xef, 0xc7,
+ 0xa8, 0x21, 0xb5, 0xf0, 0x7f, 0x04, 0xb2, 0xb0, 0xf2, 0xf8, 0x55, 0x7e,
+ 0xde, 0x3f, 0x47, 0x16, 0x58, 0xeb, 0x2f, 0xf4, 0x7c, 0x7e, 0x0b, 0xf1,
+ 0x60, 0x85, 0x8d, 0xff, 0x4e, 0xf2, 0x82, 0xfe, 0xde, 0x2c, 0xbf, 0xfb,
+ 0x3b, 0xf4, 0x7b, 0x35, 0xa8, 0x35, 0x65, 0xc0, 0x85, 0x97, 0x10, 0xf4,
+ 0x7b, 0x60, 0x45, 0xbe, 0x28, 0xe8, 0x0b, 0x2a, 0x11, 0xca, 0xd0, 0x96,
+ 0x10, 0xb6, 0xe8, 0x35, 0x65, 0xfe, 0xcd, 0x30, 0x0e, 0xf2, 0x59, 0x73,
+ 0x12, 0xcb, 0xfe, 0x82, 0x34, 0x6d, 0x20, 0xe9, 0x65, 0x8c, 0x59, 0x43,
+ 0x3e, 0x03, 0x8a, 0x88, 0x73, 0x78, 0x83, 0x3a, 0xcb, 0xd3, 0x94, 0x2c,
+ 0xbf, 0x79, 0xe5, 0x84, 0xb2, 0xfe, 0x6f, 0x96, 0x79, 0x96, 0x5c, 0xd3,
+ 0x2c, 0xbe, 0xdd, 0x8d, 0x1a, 0xb2, 0xde, 0xd8, 0x88, 0xe8, 0x26, 0x72,
+ 0xbd, 0xd1, 0x7b, 0xfe, 0x8e, 0x79, 0xb5, 0xa7, 0x92, 0xca, 0xc3, 0xfe,
+ 0x24, 0x6b, 0x9c, 0xcd, 0x8a, 0x8f, 0x86, 0x2f, 0x90, 0x92, 0xf1, 0x83,
+ 0x8e, 0xfe, 0x32, 0x8b, 0xfa, 0x27, 0xff, 0x33, 0xeb, 0x2a, 0x17, 0xc8,
+ 0xe5, 0x1d, 0xee, 0x43, 0x49, 0x88, 0x74, 0x77, 0xe8, 0xca, 0x0a, 0x53,
+ 0x91, 0x8e, 0x17, 0xf7, 0x18, 0x63, 0xc2, 0x59, 0x7f, 0xff, 0xf6, 0x7e,
+ 0x0e, 0x3c, 0xfc, 0x61, 0x48, 0xb3, 0xa9, 0x46, 0x7d, 0x65, 0xff, 0xfb,
+ 0xd9, 0xce, 0x66, 0x07, 0x53, 0xe0, 0x4b, 0xeb, 0x28, 0x91, 0x87, 0xf6,
+ 0xeb, 0xfe, 0xf4, 0x6b, 0xe5, 0x19, 0xd2, 0xcb, 0xff, 0xfe, 0x69, 0xe2,
+ 0x5c, 0xd6, 0x9b, 0xa9, 0xa4, 0xfa, 0x3e, 0x74, 0xb2, 0xff, 0x43, 0xce,
+ 0xfa, 0x71, 0x16, 0x5e, 0xf6, 0x10, 0xd1, 0xab, 0xe3, 0x8f, 0xb5, 0x56,
+ 0x2a, 0x26, 0x68, 0x77, 0xfe, 0x1e, 0xf7, 0xe8, 0xd4, 0xdc, 0x9d, 0x65,
+ 0xff, 0x7a, 0x33, 0x52, 0xe0, 0x4e, 0xb2, 0xa7, 0x3e, 0x3e, 0xca, 0xae,
+ 0x6e, 0x2c, 0xbf, 0xec, 0x9d, 0xfe, 0x01, 0x0a, 0x4b, 0x2f, 0x44, 0x8d,
+ 0x59, 0x7e, 0xce, 0x4f, 0x86, 0x2c, 0xb9, 0xbb, 0x59, 0x6f, 0xec, 0x3d,
+ 0xd9, 0x0e, 0xed, 0x94, 0xdf, 0xfb, 0xfe, 0x79, 0x30, 0xfd, 0x12, 0x59,
+ 0x4e, 0x7f, 0x04, 0x75, 0x7f, 0x08, 0x7e, 0x18, 0xfd, 0x2c, 0xa8, 0x54,
+ 0x6f, 0x90, 0x9d, 0x34, 0x93, 0x42, 0xcf, 0x18, 0x7f, 0xc8, 0x2f, 0xf8,
+ 0x4f, 0xb7, 0xb0, 0xb3, 0x8b, 0x2f, 0x4a, 0x58, 0xb2, 0xe8, 0x11, 0x65,
+ 0x74, 0x6c, 0xdc, 0x72, 0xff, 0x44, 0x84, 0xe0, 0x04, 0xed, 0x65, 0x31,
+ 0xec, 0x7c, 0x86, 0xec, 0x29, 0x23, 0x90, 0x70, 0xc3, 0xbd, 0xac, 0xf2,
+ 0xcb, 0xdc, 0x63, 0xac, 0xad, 0x1b, 0x8f, 0x8e, 0x5d, 0x9d, 0x2c, 0xb9,
+ 0xa7, 0x59, 0x50, 0x79, 0xe2, 0x10, 0xee, 0x8b, 0xdf, 0xee, 0x16, 0x1c,
+ 0xed, 0xf5, 0x96, 0x14, 0xac, 0xbf, 0xf3, 0x41, 0x6c, 0x72, 0x93, 0x1d,
+ 0x65, 0x61, 0xe9, 0x78, 0x56, 0xf9, 0xa6, 0x63, 0x16, 0x5f, 0xf9, 0xfa,
+ 0x13, 0xed, 0xa8, 0x08, 0xad, 0x65, 0xc2, 0x4e, 0xb2, 0x8e, 0x7b, 0xbf,
+ 0x44, 0xbf, 0x3f, 0x0a, 0x26, 0x59, 0x76, 0xfd, 0x2c, 0xbf, 0xff, 0x06,
+ 0x72, 0x8c, 0xf0, 0xb8, 0xfe, 0x78, 0x3a, 0x59, 0x7b, 0x82, 0x73, 0x62,
+ 0x6b, 0x43, 0x21, 0xc8, 0x40, 0x1a, 0x44, 0x44, 0xe2, 0x0c, 0xd7, 0x6a,
+ 0x94, 0x3f, 0x1e, 0xf5, 0xc4, 0x62, 0xcb, 0xf7, 0x0f, 0x9f, 0xe2, 0xcb,
+ 0xf8, 0x1a, 0x8e, 0xf0, 0x96, 0x5f, 0xf8, 0xdc, 0xfb, 0x7b, 0x3f, 0x1a,
+ 0x59, 0x50, 0x7d, 0x6c, 0x5b, 0x7e, 0x79, 0x13, 0x42, 0xcb, 0xf3, 0x97,
+ 0xf0, 0x96, 0x5f, 0xd8, 0x7c, 0xc2, 0x35, 0x65, 0xfe, 0x7f, 0xf3, 0x37,
+ 0xf9, 0x96, 0x58, 0xd1, 0x9f, 0x01, 0x16, 0x54, 0x22, 0xb5, 0xe1, 0x0b,
+ 0x7f, 0xc4, 0xe6, 0x4d, 0x27, 0xd4, 0x96, 0x5f, 0xcd, 0xac, 0xdf, 0x1b,
+ 0x8b, 0x2a, 0x63, 0xeb, 0xf1, 0xd5, 0xfc, 0xda, 0xd4, 0x61, 0x2c, 0xbf,
+ 0xe8, 0x97, 0x33, 0xb2, 0x8d, 0x2c, 0xa3, 0x4f, 0x8f, 0x45, 0x76, 0x65,
+ 0x97, 0xf7, 0x1b, 0x5d, 0xfb, 0x16, 0x5e, 0x27, 0x37, 0x0f, 0x87, 0xb2,
+ 0x3e, 0x84, 0x2a, 0x17, 0xaf, 0x25, 0x0b, 0x9c, 0x95, 0x05, 0xd9, 0x63,
+ 0x0b, 0xea, 0x12, 0x67, 0x20, 0x28, 0x69, 0x72, 0x12, 0x21, 0x87, 0x3d,
+ 0xff, 0xf4, 0xf9, 0xa9, 0xdb, 0xf2, 0xcd, 0x69, 0xe4, 0xb2, 0xf7, 0x6c,
+ 0x35, 0x97, 0xff, 0x6b, 0x0e, 0xfd, 0x6e, 0xc7, 0x67, 0x3a, 0xcb, 0xff,
+ 0xfd, 0xc6, 0xe7, 0x23, 0x9d, 0x93, 0xcf, 0x05, 0x13, 0x71, 0x65, 0x62,
+ 0x63, 0x1d, 0x28, 0xb8, 0xef, 0xd2, 0x6f, 0xde, 0x6d, 0xb6, 0x35, 0x65,
+ 0xf6, 0x01, 0xb7, 0xac, 0xbe, 0x00, 0x02, 0x05, 0x95, 0xd9, 0xf8, 0x91,
+ 0x58, 0x84, 0x77, 0xc1, 0xd7, 0xd9, 0x65, 0xf8, 0xa5, 0xc9, 0xc0, 0xb2,
+ 0xff, 0xfe, 0x97, 0xda, 0x6e, 0xfc, 0xdd, 0x7c, 0x42, 0xcd, 0xf8, 0xb2,
+ 0xff, 0xe0, 0x47, 0x0f, 0x0d, 0xad, 0x31, 0x8b, 0x2f, 0x3b, 0xc9, 0x65,
+ 0xfe, 0x6f, 0xb4, 0xb3, 0xaf, 0xac, 0xa1, 0xa6, 0x7b, 0x84, 0x5d, 0x14,
+ 0xb3, 0x00, 0x11, 0x37, 0x46, 0xef, 0xc7, 0x6f, 0xfe, 0x16, 0x5e, 0x6c,
+ 0x31, 0x65, 0xf3, 0x73, 0x06, 0xc7, 0x86, 0x44, 0xf7, 0xf1, 0x73, 0x0f,
+ 0x1b, 0x8b, 0x2f, 0xfe, 0xce, 0xa5, 0x9e, 0x6d, 0x13, 0x42, 0xcb, 0xfe,
+ 0x88, 0xe7, 0x1b, 0x58, 0x75, 0x95, 0x23, 0xf9, 0x1a, 0x15, 0xf6, 0xe7,
+ 0xb2, 0x75, 0x97, 0xfa, 0x07, 0x9f, 0x6f, 0x05, 0x65, 0x41, 0xec, 0x0c,
+ 0x9a, 0xff, 0xd2, 0xfb, 0x4f, 0xa8, 0x93, 0xe9, 0x65, 0xf1, 0xad, 0xd7,
+ 0x16, 0x54, 0x27, 0x4d, 0x34, 0x2a, 0x0e, 0xf4, 0xe4, 0x3f, 0x3f, 0xbf,
+ 0xf7, 0xc4, 0x04, 0x09, 0x00, 0x80, 0x2c, 0xbf, 0xe6, 0xd4, 0xe1, 0x06,
+ 0xc8, 0xdc, 0x59, 0x7f, 0xfc, 0x4c, 0x69, 0xb0, 0x27, 0xdb, 0xcc, 0x5f,
+ 0x59, 0x52, 0x44, 0x79, 0xcf, 0xef, 0xff, 0xc0, 0xe7, 0x9b, 0x0e, 0xfd,
+ 0x73, 0xfe, 0x0f, 0x4b, 0x2f, 0xe7, 0xe3, 0x14, 0x71, 0x65, 0xde, 0x75,
+ 0x97, 0xc3, 0x72, 0x07, 0x8f, 0x04, 0x56, 0x57, 0x58, 0x8d, 0x50, 0xc2,
+ 0x66, 0xff, 0xff, 0xc7, 0x72, 0x04, 0x9b, 0x81, 0x3f, 0x9a, 0x3f, 0xe0,
+ 0xb9, 0xd6, 0x5f, 0x72, 0x53, 0xe2, 0xcb, 0xff, 0xb0, 0xcd, 0x43, 0x16,
+ 0x00, 0xec, 0xb2, 0xe2, 0x85, 0x97, 0xff, 0x83, 0xf9, 0x30, 0x3c, 0xed,
+ 0xf7, 0x3a, 0xca, 0xf1, 0xef, 0x10, 0xad, 0xdb, 0x37, 0x16, 0x5f, 0xff,
+ 0x9d, 0xbe, 0xc3, 0xc1, 0xe7, 0xd8, 0xed, 0xa5, 0x97, 0xd2, 0xe4, 0x1d,
+ 0x65, 0xff, 0xe8, 0xec, 0x78, 0x27, 0xdb, 0x50, 0x11, 0x5a, 0xcb, 0xc1,
+ 0xc1, 0xac, 0xbd, 0xa7, 0xe6, 0xc4, 0xf7, 0xe7, 0x23, 0xc8, 0x50, 0x68,
+ 0x87, 0xc3, 0x8e, 0xa4, 0x44, 0x5b, 0x69, 0xf6, 0xfc, 0x2b, 0xf4, 0x94,
+ 0x3e, 0x1c, 0x9c, 0x32, 0x92, 0xaf, 0xfd, 0x1c, 0xef, 0xcc, 0x38, 0xcd,
+ 0x2c, 0xae, 0x97, 0x54, 0x1a, 0x73, 0x0f, 0x49, 0xf7, 0x4a, 0x16, 0x5f,
+ 0xfb, 0xd1, 0xec, 0xe8, 0x19, 0xfe, 0x2c, 0xbd, 0x33, 0x1d, 0x65, 0xa7,
+ 0x19, 0xee, 0x61, 0xfd, 0x3a, 0x26, 0x82, 0xe5, 0x7f, 0xff, 0xfb, 0xbd,
+ 0x93, 0x7a, 0x35, 0x3e, 0xce, 0x01, 0xc8, 0x1b, 0x33, 0xb8, 0xff, 0x16,
+ 0x54, 0x32, 0xeb, 0x07, 0x0a, 0xec, 0x8d, 0xb7, 0xb8, 0x4e, 0xb4, 0x7b,
+ 0x8f, 0x3b, 0x3e, 0x50, 0xd5, 0x09, 0x15, 0xed, 0x6a, 0x16, 0x5f, 0xf4,
+ 0xed, 0x3f, 0x30, 0xef, 0xe5, 0x97, 0xfd, 0x28, 0x1b, 0x0f, 0x1f, 0xcb,
+ 0x2c, 0xda, 0x3f, 0x1f, 0x9d, 0x5f, 0xda, 0x89, 0xd8, 0xbe, 0xb2, 0xe1,
+ 0x0e, 0xb2, 0xed, 0xaf, 0x6a, 0x59, 0x43, 0x37, 0x3c, 0x18, 0xbd, 0xb4,
+ 0x85, 0x56, 0xd4, 0xb2, 0xfc, 0x50, 0x3c, 0x99, 0x65, 0xf7, 0x03, 0xa3,
+ 0x56, 0x5f, 0xa3, 0xdf, 0x89, 0x2c, 0xbe, 0x18, 0x7f, 0xcd, 0xad, 0x14,
+ 0x10, 0x5d, 0xd1, 0x38, 0x09, 0x2f, 0x78, 0x4d, 0x2c, 0xbf, 0xd0, 0x4f,
+ 0xe0, 0x94, 0xeb, 0x2f, 0xff, 0xde, 0x6d, 0x79, 0xe0, 0x8d, 0x79, 0x9d,
+ 0xe7, 0x59, 0x7d, 0x8c, 0x0e, 0x2c, 0xbe, 0x6e, 0x44, 0xb0, 0xfd, 0xb4,
+ 0xab, 0x7a, 0x71, 0xc2, 0xcb, 0xda, 0x7e, 0xd6, 0x5e, 0x3c, 0x79, 0x65,
+ 0xe8, 0x90, 0xa5, 0x65, 0x80, 0x33, 0xd9, 0xc1, 0xd2, 0x1c, 0xbf, 0xe8,
+ 0xe4, 0x7f, 0x98, 0x52, 0x59, 0x7f, 0xff, 0xfb, 0x27, 0xe4, 0x1a, 0xfc,
+ 0xfc, 0xb0, 0xd3, 0x73, 0xaf, 0xea, 0x33, 0xa5, 0x97, 0xb4, 0x52, 0x59,
+ 0x7f, 0xc4, 0x0f, 0xb0, 0xf0, 0xa4, 0xb2, 0xd1, 0xb0, 0xf4, 0xdc, 0x72,
+ 0xbc, 0x99, 0x77, 0x0d, 0xc3, 0x0c, 0xfb, 0xc2, 0xbf, 0x62, 0xca, 0x14,
+ 0x2e, 0xaf, 0xca, 0x11, 0xa3, 0x27, 0xc6, 0x66, 0x86, 0x0c, 0xcb, 0x47,
+ 0x1e, 0xf4, 0x2a, 0x1c, 0xdc, 0x9d, 0xbf, 0x1b, 0x08, 0x4d, 0xae, 0x13,
+ 0x8b, 0x2f, 0xfd, 0xfe, 0x64, 0xce, 0x0e, 0x64, 0xeb, 0x2b, 0x47, 0xb0,
+ 0x43, 0x17, 0xec, 0x33, 0xe2, 0x1d, 0x65, 0xff, 0xff, 0x70, 0x48, 0x00,
+ 0xfd, 0x1a, 0xc2, 0x67, 0x97, 0x33, 0xeb, 0x2e, 0xe4, 0xeb, 0x2f, 0xe2,
+ 0x83, 0x35, 0x07, 0x59, 0x43, 0x3c, 0x5c, 0x18, 0xad, 0x23, 0x2f, 0xf0,
+ 0xaa, 0xbf, 0xdc, 0x0e, 0x81, 0x9e, 0x75, 0x97, 0xdc, 0x3b, 0xb2, 0xca,
+ 0x91, 0xea, 0x7c, 0xce, 0xff, 0xf4, 0xb6, 0x6a, 0x38, 0xd0, 0x40, 0x04,
+ 0x2c, 0xa8, 0x3e, 0xc7, 0x22, 0xbe, 0x73, 0xe0, 0xd6, 0x5f, 0xd8, 0x37,
+ 0x27, 0xde, 0xb2, 0xbe, 0x79, 0xdb, 0xc8, 0x6f, 0xfb, 0xd1, 0xd7, 0xe3,
+ 0xcf, 0xb8, 0xb2, 0x96, 0x5b, 0x7a, 0xca, 0xd8, 0x7b, 0x5b, 0x48, 0xf3,
+ 0x6c, 0x2e, 0xdd, 0x2c, 0xbb, 0x0c, 0x59, 0x77, 0xfe, 0xc6, 0xa7, 0xe2,
+ 0x55, 0x08, 0x8f, 0x66, 0x3b, 0xff, 0x39, 0x77, 0x9a, 0xed, 0xdf, 0xb5,
+ 0x44, 0x22, 0xb4, 0xeb, 0x2f, 0x8d, 0x72, 0x02, 0xcb, 0xce, 0xdb, 0xab,
+ 0x2a, 0x47, 0xa4, 0xc2, 0x5e, 0x22, 0xa8, 0x5c, 0x66, 0xc2, 0x16, 0x87,
+ 0xa9, 0xe1, 0xd0, 0xed, 0xc0, 0x8c, 0x34, 0x24, 0x3b, 0xe1, 0x3d, 0x7b,
+ 0x80, 0x75, 0x97, 0xf7, 0xbb, 0x6e, 0x60, 0xd6, 0x54, 0xe7, 0x95, 0xd8,
+ 0xe5, 0xff, 0x69, 0xc7, 0x8d, 0xbd, 0xce, 0xb2, 0xff, 0xff, 0xfc, 0xc7,
+ 0xce, 0x61, 0x07, 0xfe, 0xcd, 0xe3, 0x8f, 0x34, 0x7f, 0xc1, 0x73, 0xac,
+ 0xbf, 0xb8, 0xfd, 0xf9, 0xa7, 0x59, 0x58, 0x98, 0x76, 0x89, 0x3c, 0x73,
+ 0xf8, 0x41, 0x5f, 0x9b, 0x52, 0xdb, 0xfa, 0xcb, 0xff, 0x9f, 0x93, 0xc7,
+ 0xb3, 0xb1, 0x36, 0xdd, 0x65, 0x1c, 0xfd, 0x08, 0xae, 0xff, 0xff, 0xf7,
+ 0xb0, 0x3a, 0x37, 0xcd, 0xd4, 0x7c, 0x3e, 0x2c, 0xeb, 0xe1, 0x7e, 0x2c,
+ 0xbf, 0xfb, 0x3a, 0x13, 0xec, 0x41, 0x96, 0x71, 0x65, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xfb, 0x0a, 0x72, 0x71, 0xc1, 0x4f, 0x1a, 0x1e, 0x16, 0x7f,
+ 0x8d, 0xde, 0x10, 0x93, 0xe6, 0xa3, 0x84, 0xe6, 0xf3, 0x18, 0x00, 0x08,
+ 0x09, 0xc7, 0x05, 0x3c, 0x69, 0x65, 0xf9, 0xf7, 0x73, 0xaf, 0xac, 0xbf,
+ 0xa4, 0x59, 0x81, 0x15, 0xac, 0xbf, 0xcf, 0xf9, 0x66, 0xb3, 0x8b, 0x2a,
+ 0x13, 0xda, 0xc4, 0x5f, 0x46, 0x10, 0xe5, 0x64, 0x61, 0x7e, 0xef, 0xe6,
+ 0xb7, 0x6b, 0x2f, 0xff, 0x7a, 0x0b, 0xfb, 0x3c, 0xe3, 0xf3, 0xe9, 0x65,
+ 0x39, 0xfb, 0x70, 0xae, 0xff, 0xce, 0x58, 0xda, 0x28, 0xea, 0x4b, 0x2f,
+ 0xff, 0xfb, 0xe1, 0x9f, 0x3c, 0xdf, 0xf6, 0x1f, 0x35, 0x2c, 0xeb, 0xeb,
+ 0x2f, 0xef, 0x37, 0xbd, 0x07, 0x59, 0x7e, 0x91, 0x46, 0x71, 0x65, 0xe7,
+ 0x29, 0xfb, 0x3d, 0x3e, 0x8b, 0x6a, 0x48, 0xf0, 0xfc, 0x2e, 0xef, 0xff,
+ 0xd0, 0x09, 0xa5, 0x13, 0x93, 0x9b, 0xc2, 0x89, 0x2c, 0xbf, 0xf0, 0x99,
+ 0xe7, 0x38, 0xb3, 0x0c, 0x31, 0x65, 0xff, 0xfb, 0x3b, 0xf4, 0x10, 0xc9,
+ 0xa7, 0xc2, 0x63, 0x56, 0x54, 0xe8, 0x99, 0x92, 0x2d, 0xff, 0xd3, 0x81,
+ 0xba, 0xe7, 0x78, 0xc5, 0xda, 0xca, 0x73, 0xeb, 0x22, 0x4a, 0x92, 0x6f,
+ 0x4f, 0x1a, 0xd5, 0xff, 0xfd, 0x31, 0x40, 0x39, 0xdf, 0x9b, 0x53, 0x14,
+ 0x03, 0x8b, 0x2f, 0xff, 0xef, 0xf2, 0x0d, 0x93, 0x79, 0xcb, 0xf2, 0xcd,
+ 0x62, 0xcb, 0xff, 0x37, 0x30, 0x7b, 0x1c, 0x1b, 0x78, 0xb2, 0xe0, 0xef,
+ 0x59, 0x7f, 0xa0, 0xfd, 0x7e, 0x33, 0xa5, 0x97, 0xfe, 0xf3, 0x6f, 0xf3,
+ 0xcb, 0x50, 0x6a, 0xca, 0xc4, 0xca, 0xbb, 0x5a, 0xd2, 0x17, 0x86, 0x7e,
+ 0x69, 0x7f, 0xfe, 0xd7, 0x5f, 0x63, 0x39, 0xe6, 0xe8, 0x1a, 0x71, 0xac,
+ 0xbf, 0x7d, 0x82, 0x46, 0xac, 0xa8, 0x44, 0x08, 0x56, 0x6f, 0xec, 0x33,
+ 0x08, 0x20, 0x59, 0x7e, 0x96, 0x7e, 0x00, 0xb2, 0xe8, 0x3c, 0xe7, 0xa9,
+ 0xd1, 0x6d, 0xff, 0xcd, 0xc2, 0x8f, 0xf3, 0x37, 0xb1, 0xab, 0x2f, 0xff,
+ 0xfe, 0x01, 0xde, 0x5e, 0x76, 0xfb, 0x0f, 0x07, 0x9f, 0x63, 0xb6, 0x96,
+ 0x57, 0x11, 0xc7, 0xf2, 0xf0, 0xa2, 0xdf, 0xfb, 0xcf, 0xbb, 0xdf, 0x98,
+ 0xf1, 0xda, 0xcb, 0xc5, 0x06, 0x2c, 0xbc, 0x59, 0xcc, 0x3d, 0xf3, 0xa1,
+ 0xdf, 0xa7, 0x3c, 0x0e, 0x16, 0x54, 0xec, 0xae, 0x49, 0x10, 0x8e, 0x52,
+ 0xa1, 0xb0, 0xc3, 0xec, 0x87, 0xa8, 0xcb, 0x26, 0x8e, 0x8b, 0x45, 0x3e,
+ 0x8e, 0x1f, 0x90, 0xcc, 0xfc, 0x6b, 0x3b, 0xe1, 0x1e, 0x21, 0x8d, 0xff,
+ 0xa0, 0xd3, 0x60, 0xb3, 0xfe, 0x65, 0x97, 0xfa, 0x39, 0xc8, 0x9f, 0x0c,
+ 0x59, 0x7f, 0xfc, 0x3f, 0x85, 0xfa, 0xf8, 0x30, 0x7b, 0x3c, 0xcb, 0x2f,
+ 0xff, 0xb7, 0xbf, 0xbc, 0xc3, 0xcf, 0xf0, 0x25, 0xf5, 0x97, 0xdf, 0x20,
+ 0xfd, 0x65, 0xc1, 0x25, 0x97, 0xb0, 0xf9, 0xa3, 0x71, 0xe2, 0x2a, 0x84,
+ 0x5d, 0x7a, 0x11, 0x34, 0x34, 0xda, 0x1c, 0xd3, 0xf1, 0x86, 0xdf, 0x66,
+ 0x8d, 0x65, 0x95, 0x0c, 0xe8, 0x4c, 0xa5, 0xcd, 0x34, 0x3b, 0x1e, 0x3a,
+ 0x60, 0x9b, 0x5e, 0x30, 0xc3, 0x12, 0x5f, 0xf6, 0x01, 0xf5, 0x9b, 0xf0,
+ 0x69, 0x05, 0x9a, 0x0b, 0x8c, 0x31, 0x25, 0xe3, 0x0c, 0x31, 0x25, 0xfc,
+ 0xf3, 0x8f, 0xd1, 0xc4, 0x82, 0xcd, 0x05, 0x12, 0x31, 0x0c, 0x4b, 0xdb,
+ 0x39, 0xbf, 0x76, 0xc3, 0x10, 0xe9, 0x05, 0x9b, 0x3b, 0xc6, 0x18, 0x62,
+ 0x4b, 0xdc, 0x8d, 0x24, 0x16, 0x68, 0x2f, 0x9c, 0xba, 0xfa, 0xcb, 0x01,
+ 0x91, 0x59, 0xf5, 0xc3, 0x0b, 0xae, 0xdb, 0xda, 0x96, 0x5f, 0xf3, 0x17,
+ 0x65, 0x86, 0x38, 0x16, 0x5f, 0x8a, 0x24, 0xfd, 0xac, 0xbd, 0x93, 0x32,
+ 0xca, 0x19, 0xe1, 0x88, 0x4f, 0x7e, 0xe0, 0x67, 0xdb, 0x25, 0x97, 0xe1,
+ 0xb6, 0xf8, 0x1a, 0xcb, 0xec, 0x2c, 0xdc, 0x59, 0x5a, 0x3c, 0xc3, 0x94,
+ 0xd3, 0x22, 0x68, 0x47, 0x8b, 0xff, 0xbc, 0xf2, 0x27, 0x36, 0x62, 0x69,
+ 0x96, 0x5f, 0xc2, 0xac, 0xb0, 0xc7, 0x02, 0xcb, 0xfe, 0x9e, 0x3a, 0xe3,
+ 0x16, 0x01, 0x65, 0xf3, 0xc9, 0x80, 0xb2, 0xb4, 0x7b, 0x5e, 0x39, 0xbf,
+ 0x64, 0xe7, 0xc3, 0xac, 0xbf, 0xa2, 0x71, 0xfa, 0x38, 0xb2, 0xff, 0x46,
+ 0x77, 0x9b, 0xd8, 0x6b, 0x2d, 0x9d, 0x9f, 0x11, 0x17, 0x50, 0xab, 0x4d,
+ 0x83, 0x21, 0x1a, 0x44, 0x5b, 0x70, 0x8a, 0xbf, 0xbd, 0x9b, 0xf3, 0xfc,
+ 0x59, 0x5d, 0xaa, 0x23, 0x04, 0x74, 0xbf, 0x4f, 0xa9, 0x2b, 0xd6, 0x18,
+ 0xfe, 0x9e, 0xfd, 0x0b, 0xd2, 0x94, 0x8d, 0x7f, 0xbf, 0x2c, 0xf7, 0x9e,
+ 0x4b, 0x2f, 0x99, 0xc8, 0x6b, 0x2e, 0x08, 0x16, 0x50, 0xcd, 0xb8, 0x08,
+ 0x2f, 0xd1, 0x93, 0x36, 0x96, 0x54, 0xe7, 0x90, 0x44, 0x37, 0x4f, 0xf5,
+ 0x95, 0x0b, 0xa9, 0xf9, 0x38, 0x18, 0x6a, 0xbb, 0xc2, 0xc8, 0x88, 0xaf,
+ 0xb6, 0xfd, 0x9d, 0xac, 0xbe, 0x03, 0x17, 0xd6, 0x54, 0xe7, 0x8f, 0xc2,
+ 0x6b, 0x85, 0x56, 0xd4, 0xb2, 0xf7, 0x23, 0xeb, 0x2e, 0x01, 0x8b, 0x2f,
+ 0xdc, 0x09, 0x08, 0x75, 0x96, 0xe4, 0xc7, 0xba, 0xe3, 0x9f, 0x18, 0xac,
+ 0x46, 0xbf, 0x44, 0x7f, 0x7f, 0xbf, 0x77, 0x1e, 0x83, 0xac, 0xb9, 0xfe,
+ 0xb2, 0xfb, 0x71, 0xc8, 0x18, 0x6f, 0x88, 0xa2, 0xff, 0x61, 0xa6, 0xbc,
+ 0xa4, 0x35, 0x97, 0xf3, 0xb8, 0xfe, 0x17, 0x59, 0x7c, 0x37, 0x20, 0x61,
+ 0xf0, 0x91, 0xad, 0x62, 0x33, 0xc3, 0x09, 0x9b, 0xff, 0x81, 0xff, 0x44,
+ 0xa4, 0xdc, 0xc1, 0xac, 0xbf, 0xf7, 0xf3, 0x51, 0xbf, 0xe4, 0xe0, 0x59,
+ 0x74, 0xd2, 0x84, 0x41, 0xb2, 0x25, 0xff, 0x41, 0x48, 0x87, 0xe8, 0x9d,
+ 0x65, 0xfc, 0x3c, 0xd6, 0xd9, 0xc6, 0xb2, 0xf7, 0x9a, 0x64, 0x95, 0xa3,
+ 0xce, 0xe1, 0x8d, 0xff, 0x3f, 0x5f, 0xc9, 0x83, 0xa3, 0x56, 0x5b, 0xb6,
+ 0x3d, 0xe0, 0x91, 0x5f, 0xe2, 0xce, 0xa5, 0xc6, 0x35, 0x65, 0xed, 0x06,
+ 0x75, 0x97, 0x9f, 0x46, 0xac, 0xad, 0x1b, 0xb7, 0x1e, 0xb1, 0xab, 0x2f,
+ 0xfe, 0xce, 0xfd, 0x1e, 0xcd, 0x6a, 0x0d, 0x59, 0x79, 0x81, 0xc8, 0x3d,
+ 0x7d, 0x09, 0x56, 0xc4, 0xc6, 0x27, 0x6f, 0x27, 0x7b, 0xfe, 0xcc, 0xec,
+ 0x11, 0x9d, 0x49, 0x65, 0xff, 0x83, 0xcc, 0x28, 0xf0, 0xc4, 0x3a, 0xcb,
+ 0xff, 0xbf, 0xa0, 0xf3, 0xcf, 0x20, 0x30, 0xd6, 0x5f, 0x43, 0x9f, 0x7a,
+ 0x4b, 0xda, 0xc1, 0x42, 0xcb, 0xff, 0xbc, 0xce, 0x00, 0x40, 0x23, 0xdc,
+ 0x59, 0x7f, 0x7b, 0x0e, 0x77, 0x92, 0xcb, 0xc6, 0x18, 0x62, 0x4b, 0xfc,
+ 0x5f, 0xf3, 0x41, 0x4e, 0x90, 0x59, 0xa0, 0xbe, 0x8d, 0x3f, 0x96, 0x5e,
+ 0x80, 0x64, 0x91, 0x65, 0x89, 0xbf, 0x44, 0xac, 0x4d, 0x53, 0xe4, 0x02,
+ 0x43, 0xd6, 0xfe, 0xcd, 0x9f, 0x70, 0x71, 0x65, 0x76, 0x9e, 0xe1, 0xe3,
+ 0x77, 0xde, 0x6d, 0x7f, 0xce, 0x02, 0xc9, 0xa5, 0x1d, 0x2c, 0xa8, 0x55,
+ 0x29, 0x92, 0x88, 0x58, 0xea, 0xff, 0x9c, 0x8b, 0x35, 0xa6, 0x99, 0x65,
+ 0xfc, 0x42, 0x68, 0x83, 0x25, 0x95, 0x39, 0xf2, 0xb9, 0xbd, 0xff, 0xfd,
+ 0x2f, 0x3c, 0xbb, 0xf3, 0x7e, 0x59, 0xef, 0x3c, 0x96, 0x5f, 0xa0, 0x11,
+ 0xee, 0x2c, 0xac, 0x44, 0x18, 0x17, 0x2f, 0xfe, 0x10, 0xa1, 0x87, 0xec,
+ 0x97, 0x99, 0x65, 0xff, 0x84, 0x8d, 0x03, 0xfe, 0x71, 0xb2, 0xcb, 0xff,
+ 0xe7, 0xf8, 0x61, 0xa3, 0xae, 0xfd, 0x9d, 0x71, 0x65, 0xfb, 0x5a, 0x6f,
+ 0xf1, 0x65, 0x6c, 0x47, 0xd8, 0xd0, 0xc0, 0x7e, 0x22, 0x8d, 0xff, 0xf0,
+ 0x36, 0xf2, 0x39, 0xe8, 0xeb, 0xe6, 0x87, 0x4b, 0x2f, 0xfe, 0x9a, 0x41,
+ 0x2f, 0xcb, 0x35, 0x9c, 0x59, 0x7f, 0xfe, 0x2e, 0xfc, 0xd3, 0x4a, 0x0b,
+ 0xfa, 0xd4, 0x49, 0x67, 0x0f, 0x16, 0xff, 0xfe, 0x6e, 0x69, 0x9f, 0x50,
+ 0xdf, 0xf6, 0x73, 0x98, 0xb2, 0xff, 0x64, 0x49, 0xbe, 0x50, 0xb2, 0xc0,
+ 0xc4, 0x77, 0x9d, 0x9f, 0x6d, 0x62, 0xa1, 0x50, 0x0e, 0x20, 0x3c, 0x71,
+ 0x37, 0xff, 0xf3, 0x80, 0xb0, 0xe4, 0xff, 0xe0, 0x9a, 0x68, 0x1a, 0xcb,
+ 0xa5, 0xc5, 0x97, 0x44, 0x86, 0x7e, 0x0c, 0xb3, 0x50, 0xcc, 0xa7, 0x94,
+ 0x67, 0xb9, 0x0a, 0xa3, 0x4b, 0xba, 0x87, 0x23, 0x46, 0x81, 0x31, 0x9e,
+ 0x8e, 0x7d, 0x2b, 0x4d, 0xe1, 0x36, 0x08, 0x52, 0x94, 0xb1, 0xee, 0x42,
+ 0x96, 0xff, 0xfe, 0xfb, 0x1f, 0x0b, 0xfc, 0x83, 0x78, 0x11, 0xf9, 0x96,
+ 0x5f, 0x81, 0x8d, 0xe3, 0x56, 0x5f, 0xff, 0x67, 0x70, 0x4f, 0xfe, 0x0c,
+ 0x2f, 0xa9, 0x2c, 0xae, 0x8f, 0xdc, 0xe5, 0x17, 0xdc, 0xf6, 0x71, 0x65,
+ 0xf3, 0x7e, 0x3e, 0xb2, 0x98, 0xf0, 0xf4, 0x45, 0x7f, 0x41, 0x77, 0xb5,
+ 0x8a, 0x9b, 0x42, 0xcb, 0xee, 0xbe, 0xd3, 0xac, 0xbf, 0x41, 0xf5, 0x1b,
+ 0xd6, 0x5f, 0xfe, 0xfb, 0x19, 0xc2, 0x8f, 0xf3, 0x5a, 0x85, 0x97, 0xa5,
+ 0x04, 0xb2, 0xf0, 0xe0, 0xd5, 0x97, 0xff, 0x47, 0x7f, 0x28, 0x33, 0x3f,
+ 0xce, 0x2c, 0xbf, 0xf3, 0xfb, 0x51, 0xf6, 0xed, 0x86, 0xb2, 0xff, 0xbf,
+ 0xec, 0x6d, 0x48, 0x43, 0xac, 0xbb, 0x00, 0xb2, 0xbc, 0x88, 0xee, 0x1f,
+ 0x7c, 0xea, 0x99, 0x32, 0x0d, 0x0e, 0x82, 0x1a, 0x77, 0xff, 0xff, 0x13,
+ 0x9e, 0x35, 0xd8, 0xfd, 0x1c, 0x0b, 0xb4, 0xb9, 0xe7, 0x92, 0xcb, 0xc1,
+ 0xff, 0x16, 0x5f, 0x8c, 0x7f, 0x41, 0xd6, 0x5e, 0xee, 0x38, 0xb2, 0xff,
+ 0xe1, 0x25, 0x9e, 0x7f, 0x36, 0xb5, 0x0b, 0x2a, 0x11, 0x13, 0x85, 0x00,
+ 0x1d, 0xbe, 0x93, 0x90, 0x16, 0x5f, 0xfe, 0x6f, 0x87, 0x4f, 0xc9, 0x37,
+ 0x22, 0x75, 0x96, 0xf6, 0x1f, 0x5b, 0x90, 0xde, 0xe6, 0xfc, 0x59, 0x74,
+ 0x69, 0x65, 0x7c, 0xda, 0x6d, 0x8f, 0x5f, 0xd9, 0x3f, 0x37, 0x1b, 0xb5,
+ 0x95, 0x07, 0xac, 0x44, 0x97, 0xe0, 0xe8, 0xdf, 0x32, 0xca, 0xd8, 0xbc,
+ 0x8d, 0x10, 0xd2, 0x9d, 0x98, 0x64, 0x38, 0x7b, 0xd9, 0x27, 0x45, 0x2c,
+ 0x95, 0xa8, 0xce, 0xdc, 0xd4, 0x0e, 0x25, 0x0a, 0x6e, 0x42, 0x67, 0xf0,
+ 0xb0, 0xdb, 0x20, 0xb1, 0x8b, 0x2f, 0xf8, 0x82, 0xe6, 0x80, 0xf1, 0x25,
+ 0x95, 0xa3, 0xcb, 0x00, 0x95, 0xfe, 0x27, 0x33, 0x09, 0xcd, 0x59, 0x7f,
+ 0xf6, 0x7f, 0x82, 0x70, 0xe5, 0x1a, 0x85, 0x97, 0xb7, 0xe1, 0x0c, 0xfd,
+ 0x8e, 0x65, 0x7f, 0xee, 0xe3, 0xfe, 0x6d, 0xf9, 0xd7, 0xd6, 0x5f, 0xfa,
+ 0x34, 0x4f, 0x3c, 0x6a, 0x24, 0xb2, 0xb0, 0xff, 0xcc, 0x42, 0xa6, 0x46,
+ 0xaf, 0xa1, 0x67, 0x7f, 0xff, 0xbc, 0xc6, 0x66, 0xeb, 0x1d, 0xff, 0xc0,
+ 0xcb, 0x3a, 0xfa, 0xcb, 0xff, 0xb4, 0xc0, 0x13, 0xd0, 0x77, 0x7f, 0xac,
+ 0xbf, 0xff, 0xa7, 0x1f, 0xa3, 0x99, 0xd7, 0x23, 0x5f, 0xe6, 0x4e, 0xb2,
+ 0x86, 0x98, 0x3e, 0x99, 0x49, 0x12, 0xe8, 0x65, 0x95, 0x0a, 0xb8, 0x32,
+ 0x36, 0xd7, 0x8c, 0xb8, 0x06, 0x17, 0xfd, 0x37, 0x7e, 0x63, 0xc6, 0x8d,
+ 0x59, 0x7f, 0x9b, 0x53, 0x67, 0xe2, 0x65, 0x97, 0xf4, 0x7a, 0x3f, 0x1e,
+ 0x59, 0x7d, 0xba, 0xc5, 0xda, 0xca, 0xc3, 0xd1, 0xdd, 0x2c, 0xbf, 0x4f,
+ 0xb0, 0x31, 0x32, 0xcb, 0x49, 0x65, 0xfa, 0x5f, 0x6d, 0x76, 0xb2, 0xf0,
+ 0x85, 0x32, 0xca, 0x91, 0xec, 0x74, 0x22, 0x02, 0x9a, 0xc4, 0xe6, 0x7b,
+ 0x3c, 0xd4, 0x21, 0x5c, 0x93, 0x90, 0x84, 0xad, 0xa2, 0x14, 0x70, 0x91,
+ 0x38, 0x83, 0x3c, 0xe1, 0x24, 0xa9, 0x36, 0xa3, 0xa4, 0xbb, 0x65, 0x7a,
+ 0x92, 0x6c, 0x73, 0x5d, 0xc7, 0xea, 0xd3, 0xa8, 0x1b, 0x90, 0xd8, 0x9a,
+ 0x7f, 0x5b, 0x53, 0x9c, 0xc7, 0xa4, 0x01, 0x7a, 0x9a, 0xde, 0xf3, 0xbe,
+ 0x60, 0x9d, 0x7c, 0x2a, 0xc1, 0x8f, 0x93, 0xee, 0x1f, 0xa7, 0x0e, 0x06,
+ 0x7c, 0xb4, 0xc9, 0xc1, 0x71, 0x23, 0xe1, 0xba, 0x0e, 0xb2, 0xf7, 0xb3,
+ 0x8b, 0x2f, 0xbe, 0x01, 0x3b, 0x59, 0x7f, 0x98, 0xdf, 0xf5, 0xdb, 0x79,
+ 0x65, 0x74, 0x7b, 0x64, 0x4b, 0x43, 0x44, 0xce, 0x3b, 0xde, 0xdd, 0x6d,
+ 0xeb, 0x2e, 0x6f, 0x2c, 0xbe, 0xcc, 0x2f, 0xac, 0xba, 0x09, 0x65, 0x78,
+ 0xf2, 0xf8, 0x2d, 0xbc, 0x82, 0xff, 0xfb, 0x08, 0x5f, 0xcd, 0x6e, 0xb9,
+ 0xec, 0x03, 0xac, 0xbf, 0xfe, 0x1c, 0x3e, 0xbc, 0x63, 0x8f, 0x6d, 0xe7,
+ 0xdb, 0x59, 0x52, 0x46, 0xd0, 0xcc, 0x7e, 0xa5, 0x79, 0xdc, 0xc5, 0x97,
+ 0x02, 0x16, 0x5f, 0xbb, 0xcf, 0xf9, 0x96, 0x59, 0xc6, 0x7b, 0x4c, 0x38,
+ 0x42, 0xd7, 0xdd, 0xf9, 0x85, 0x6b, 0x2f, 0xdb, 0x3a, 0x96, 0x7d, 0x65,
+ 0xe6, 0xd4, 0x2c, 0xbf, 0x48, 0x4e, 0x46, 0x2c, 0xbb, 0x9e, 0xc3, 0xc3,
+ 0x71, 0xbb, 0xf1, 0x9f, 0xe3, 0x9d, 0x65, 0xff, 0xff, 0x67, 0x9c, 0x4e,
+ 0x61, 0xae, 0x40, 0x82, 0x89, 0xbd, 0x0b, 0x2d, 0x0b, 0x2f, 0xff, 0xd1,
+ 0xaf, 0x41, 0xf7, 0x43, 0x05, 0x13, 0x7a, 0x16, 0x5f, 0x9b, 0x53, 0x47,
+ 0xb4, 0x8c, 0xc0, 0x32, 0x90, 0x85, 0x49, 0x70, 0x9b, 0x08, 0xba, 0x8d,
+ 0x18, 0xf0, 0x8a, 0x01, 0x91, 0x13, 0xfd, 0xb8, 0x25, 0x82, 0x43, 0xd6,
+ 0xfd, 0x37, 0xa2, 0x7c, 0x59, 0x6f, 0x2c, 0xa9, 0x1b, 0xa1, 0x94, 0xdb,
+ 0x69, 0x2c, 0xbf, 0xf7, 0xfc, 0xf2, 0xfc, 0xc5, 0x07, 0x59, 0x79, 0x87,
+ 0x8b, 0x2f, 0xfc, 0xe4, 0x0d, 0x83, 0x0b, 0xea, 0x4b, 0x2f, 0x98, 0xa7,
+ 0x85, 0x97, 0x67, 0x16, 0x5d, 0xa8, 0x59, 0x5e, 0x35, 0x9f, 0x16, 0xbf,
+ 0xe2, 0x83, 0xb1, 0x61, 0xe1, 0x65, 0xff, 0xb5, 0xa6, 0x9b, 0x98, 0x6b,
+ 0x69, 0x65, 0xef, 0x34, 0x96, 0x5c, 0xd0, 0xb2, 0xe6, 0x1e, 0x23, 0x1e,
+ 0x62, 0x1e, 0x1a, 0xfd, 0x00, 0xc1, 0xca, 0xdc, 0x4e, 0xab, 0x48, 0x05,
+ 0x18, 0xa5, 0xfc, 0x31, 0xc4, 0xdf, 0xc5, 0x97, 0xff, 0x17, 0xf9, 0xe7,
+ 0x96, 0xcc, 0xeb, 0xeb, 0x28, 0x54, 0x55, 0x93, 0x02, 0xf2, 0x3f, 0xc8,
+ 0xf1, 0x58, 0xe4, 0x25, 0xd7, 0xfc, 0xfb, 0x93, 0x72, 0x3c, 0xfb, 0x8b,
+ 0x2f, 0xf8, 0x48, 0x98, 0x48, 0xd3, 0xcc, 0xb2, 0xfd, 0xcc, 0xcf, 0xe2,
+ 0xcb, 0xd0, 0x53, 0xac, 0xbe, 0x6f, 0x31, 0xd6, 0x53, 0x1b, 0xd9, 0x87,
+ 0x2f, 0xfd, 0xfe, 0x0a, 0x44, 0x83, 0x3c, 0x12, 0x59, 0x5d, 0x23, 0x27,
+ 0xcc, 0x64, 0x43, 0x7b, 0x9f, 0x65, 0x97, 0x4c, 0x15, 0x97, 0x47, 0x70,
+ 0x6d, 0x08, 0x72, 0xff, 0xa3, 0xfe, 0x70, 0x3f, 0x5c, 0x59, 0x43, 0x3e,
+ 0x42, 0x2b, 0xbf, 0xfb, 0x27, 0x79, 0xb6, 0x7a, 0x39, 0xc7, 0x59, 0x7f,
+ 0xf0, 0x5d, 0xa5, 0x05, 0xde, 0x75, 0xf5, 0x97, 0xc4, 0x17, 0xef, 0x62,
+ 0x22, 0xf8, 0x8f, 0x71, 0xd9, 0x65, 0xff, 0x03, 0x67, 0x9b, 0xb0, 0xe8,
+ 0x0b, 0x2f, 0xef, 0xf9, 0xb6, 0x17, 0x4b, 0x2f, 0x6e, 0xc6, 0xe2, 0xca,
+ 0xd2, 0x23, 0xc8, 0xf7, 0x74, 0xc2, 0xed, 0xf0, 0xb2, 0xf4, 0xc1, 0xd2,
+ 0xcb, 0xd8, 0xdf, 0x59, 0x7f, 0xcd, 0xac, 0xe8, 0x59, 0x86, 0x18, 0xb2,
+ 0xbc, 0x7b, 0x4e, 0x37, 0x42, 0x94, 0xe2, 0x22, 0x14, 0xac, 0x64, 0xe3,
+ 0x1c, 0x78, 0xbf, 0xfe, 0x28, 0x96, 0xc1, 0x3e, 0xc4, 0x19, 0x67, 0x16,
+ 0x5f, 0xff, 0xbc, 0x1e, 0x1e, 0x3a, 0xef, 0xcc, 0x72, 0x69, 0xd6, 0x5f,
+ 0xff, 0xf9, 0xf7, 0x0b, 0x18, 0x8b, 0x01, 0x9f, 0x83, 0xb7, 0xfc, 0xcb,
+ 0x28, 0x6b, 0xb4, 0x19, 0x18, 0x2f, 0x70, 0xc8, 0x3c, 0x2b, 0x3d, 0x1e,
+ 0x20, 0x14, 0x78, 0xa2, 0x15, 0x8b, 0xb8, 0x15, 0x97, 0xf7, 0x98, 0xfd,
+ 0xb0, 0xd6, 0x5e, 0x03, 0x9d, 0x65, 0xd8, 0x05, 0x95, 0x06, 0xcb, 0x07,
+ 0x2f, 0x3e, 0x1d, 0x65, 0x4e, 0x8b, 0x1c, 0x17, 0x26, 0x0d, 0xd1, 0xfb,
+ 0xff, 0x9c, 0x4f, 0x44, 0xb9, 0xad, 0x67, 0x4b, 0x2c, 0x52, 0x44, 0x2f,
+ 0x8f, 0xef, 0xa3, 0xc1, 0xd2, 0xcb, 0xfb, 0x85, 0x83, 0x27, 0x59, 0x44,
+ 0x79, 0xa6, 0x11, 0x5d, 0xdb, 0x2c, 0xbf, 0x14, 0x4f, 0x1d, 0x2c, 0xbf,
+ 0x9f, 0x47, 0x0e, 0x80, 0xb2, 0xed, 0x01, 0x65, 0x48, 0xf1, 0x58, 0xba,
+ 0xdc, 0xed, 0x14, 0xac, 0x2e, 0xed, 0xb5, 0x09, 0xb8, 0xb3, 0xab, 0xc3,
+ 0x1e, 0xfb, 0x85, 0x13, 0xac, 0xbf, 0xe9, 0xdf, 0xce, 0x32, 0x7e, 0xd6,
+ 0x56, 0x8f, 0x6c, 0x88, 0xaf, 0xff, 0x8c, 0xce, 0xf9, 0x9f, 0x9b, 0x0d,
+ 0x2c, 0x02, 0xca, 0xc3, 0xf3, 0x62, 0x1b, 0xfe, 0x23, 0x7c, 0xed, 0xf7,
+ 0x3a, 0xcb, 0xfe, 0xc3, 0x33, 0x5d, 0xbb, 0xf6, 0xa8, 0xc3, 0x97, 0xff,
+ 0x07, 0x83, 0xf3, 0x9f, 0xa9, 0x31, 0x2c, 0xbf, 0x7f, 0xce, 0x40, 0x59,
+ 0x53, 0xa2, 0xcf, 0xc8, 0xee, 0x8b, 0x7f, 0xe7, 0xfe, 0x4c, 0xf0, 0x51,
+ 0x32, 0xcb, 0xff, 0x79, 0xb0, 0x4c, 0x98, 0xc8, 0xe9, 0x65, 0x9b, 0x13,
+ 0x99, 0xd4, 0x3a, 0xfc, 0x61, 0xc3, 0xdb, 0xbb, 0xed, 0x51, 0x82, 0x2a,
+ 0x4a, 0x89, 0xbb, 0x8e, 0xe4, 0x08, 0xf7, 0xf1, 0x47, 0xf8, 0xdb, 0xd6,
+ 0x5f, 0xed, 0xab, 0x83, 0x2c, 0xf0, 0xa5, 0x65, 0xd8, 0x4b, 0x29, 0x65,
+ 0xff, 0xd0, 0x5d, 0xe7, 0xfc, 0xda, 0x07, 0x6b, 0x28, 0x8f, 0x43, 0xe1,
+ 0x77, 0xcd, 0xcf, 0x32, 0xcb, 0xd9, 0xd7, 0xd6, 0x50, 0xcd, 0xf1, 0xc8,
+ 0x6f, 0xe6, 0x2c, 0xff, 0x99, 0x65, 0xa3, 0x0f, 0x33, 0x84, 0x34, 0x34,
+ 0xcd, 0xb1, 0x94, 0x30, 0xab, 0xbf, 0xfd, 0xe6, 0x9b, 0xcd, 0xd7, 0xcb,
+ 0x37, 0xba, 0xcb, 0xc3, 0x79, 0x96, 0x5f, 0xf3, 0x6f, 0xf6, 0x6b, 0x4d,
+ 0xbd, 0x65, 0x41, 0xec, 0xf8, 0x76, 0xe8, 0x02, 0xcb, 0xfe, 0xe4, 0x1b,
+ 0xc0, 0x8f, 0xcc, 0xb2, 0xec, 0x29, 0x8f, 0x43, 0xe2, 0xd7, 0xf1, 0xf9,
+ 0xc7, 0x29, 0xd6, 0x5c, 0x73, 0xac, 0xa8, 0x3c, 0x57, 0x2e, 0xbf, 0x37,
+ 0x9d, 0xa7, 0x59, 0x74, 0x6e, 0x2c, 0xb8, 0x1c, 0x91, 0xe0, 0x31, 0x3d,
+ 0xf7, 0x30, 0xbe, 0xb2, 0xf6, 0xec, 0x69, 0x65, 0x31, 0xf6, 0xb9, 0x68,
+ 0x48, 0x6f, 0x79, 0xfe, 0xb2, 0xf7, 0xdf, 0x71, 0x65, 0xfe, 0xff, 0x98,
+ 0x58, 0x1d, 0x96, 0x5f, 0xe3, 0x7d, 0x12, 0x0b, 0xe9, 0x65, 0x89, 0x65,
+ 0x31, 0xe2, 0x04, 0xd2, 0xe1, 0x31, 0x65, 0x42, 0xea, 0x14, 0xe5, 0xc3,
+ 0x8d, 0xcb, 0xb3, 0x59, 0xa1, 0x4a, 0x77, 0x1f, 0x39, 0x14, 0x33, 0x78,
+ 0x5b, 0xf1, 0xc0, 0x8f, 0xed, 0xbc, 0x08, 0x43, 0x7a, 0x6c, 0xdc, 0x59,
+ 0x7e, 0x34, 0x0d, 0x37, 0x16, 0x5f, 0x79, 0x9e, 0x4b, 0x2f, 0x0d, 0xe4,
+ 0xb2, 0xa0, 0xde, 0xe1, 0x0d, 0xfe, 0xf3, 0xcd, 0xb3, 0xb8, 0x1a, 0xcb,
+ 0x06, 0x11, 0x7a, 0x06, 0x7e, 0x0f, 0xdf, 0xde, 0x89, 0x78, 0x23, 0x59,
+ 0x7f, 0xfb, 0x61, 0x3f, 0xe3, 0x41, 0x96, 0xa2, 0x4b, 0x2f, 0xd1, 0xff,
+ 0x44, 0xcb, 0x2e, 0xff, 0x16, 0x5f, 0x9c, 0xd3, 0x23, 0x4b, 0x2a, 0x48,
+ 0xe1, 0x62, 0xef, 0x25, 0xb9, 0x41, 0x0b, 0xdf, 0xe6, 0x2f, 0xcb, 0x35,
+ 0x8b, 0x2f, 0xfe, 0x6e, 0xcb, 0x0f, 0x13, 0x0e, 0x27, 0x59, 0x7f, 0xf4,
+ 0x8b, 0x0e, 0xe5, 0x9e, 0x73, 0xac, 0xbf, 0xd9, 0xf8, 0xde, 0xc4, 0x05,
+ 0x97, 0xff, 0xc0, 0x3b, 0xca, 0x58, 0x01, 0x3f, 0x3f, 0x02, 0xb2, 0xbb,
+ 0x44, 0x36, 0x8c, 0xef, 0xfc, 0x27, 0x5b, 0x23, 0x64, 0xc5, 0x07, 0x59,
+ 0x7f, 0xb5, 0x0c, 0x32, 0x79, 0x2c, 0xbf, 0xf6, 0x98, 0xbb, 0x2c, 0x9f,
+ 0x0c, 0x59, 0x7f, 0xd9, 0xbe, 0x33, 0xae, 0xbe, 0x2a, 0x96, 0x5f, 0xa3,
+ 0xfc, 0xc2, 0xd8, 0x8b, 0x2d, 0x18, 0xf8, 0xfe, 0x86, 0x9a, 0x20, 0x61,
+ 0xef, 0x7e, 0xef, 0xdd, 0x3e, 0xe2, 0xcb, 0xfd, 0xc8, 0x91, 0xa6, 0xe6,
+ 0xe2, 0xcb, 0xff, 0x0c, 0x83, 0xfe, 0x41, 0x47, 0x16, 0x54, 0x1f, 0xab,
+ 0x1c, 0x58, 0x56, 0xb2, 0xa4, 0xae, 0x97, 0xb3, 0x1e, 0x91, 0x5a, 0x18,
+ 0xe5, 0x1b, 0x40, 0x4a, 0x77, 0xc2, 0x88, 0xc2, 0x0b, 0xde, 0x63, 0x56,
+ 0x5f, 0xfe, 0x68, 0xf9, 0x67, 0xfd, 0x8d, 0x2d, 0xeb, 0x2f, 0xfb, 0xae,
+ 0x01, 0xc8, 0x73, 0x05, 0x65, 0xff, 0x6b, 0x37, 0xe0, 0xf4, 0x46, 0x2c,
+ 0xa6, 0x3f, 0x67, 0x3b, 0xbf, 0xff, 0x04, 0xa5, 0x85, 0xf6, 0xdb, 0xcf,
+ 0x93, 0xc9, 0x65, 0xfe, 0x80, 0x47, 0xb3, 0xa9, 0x2c, 0xa6, 0x44, 0x41,
+ 0x2a, 0xd7, 0x93, 0x88, 0x04, 0x2f, 0xff, 0x0a, 0x8b, 0xe9, 0x9e, 0x67,
+ 0x59, 0x7c, 0xff, 0x0c, 0x96, 0x5d, 0x1c, 0x59, 0x5b, 0x0f, 0x6c, 0x88,
+ 0xfe, 0x45, 0x7f, 0xde, 0x72, 0xc9, 0xa5, 0x1d, 0x2c, 0xbf, 0xfb, 0xcd,
+ 0xac, 0xe1, 0x66, 0xff, 0x32, 0xcb, 0xf1, 0x67, 0x03, 0xb3, 0x0f, 0xf6,
+ 0x63, 0x9b, 0xf6, 0xbb, 0x77, 0xed, 0x51, 0x03, 0x2f, 0xe7, 0x9c, 0x0e,
+ 0x43, 0x45, 0x60, 0xf5, 0xec, 0xe0, 0x70, 0xfc, 0x76, 0xcd, 0xaf, 0x79,
+ 0xe5, 0xb1, 0x1c, 0xc5, 0x0b, 0x1b, 0xfe, 0xf3, 0x61, 0x67, 0x63, 0xc5,
+ 0x95, 0xda, 0xe1, 0xf9, 0xe3, 0xa5, 0x28, 0x4b, 0x7e, 0x39, 0x3d, 0xe7,
+ 0x57, 0xbe, 0x18, 0x59, 0x7f, 0xfb, 0xcd, 0xfc, 0xc3, 0xf2, 0x30, 0x6c,
+ 0xb2, 0xee, 0x71, 0x65, 0xf0, 0xfc, 0xe7, 0x59, 0x7f, 0xd9, 0x38, 0x92,
+ 0x68, 0xeb, 0xeb, 0x2c, 0x0e, 0xd1, 0x77, 0xa4, 0x77, 0x17, 0x22, 0x2b,
+ 0xfc, 0x0f, 0xb4, 0xe7, 0x8e, 0xd6, 0x57, 0x49, 0xa7, 0x3c, 0x35, 0xc9,
+ 0x0a, 0xfc, 0x3d, 0xa1, 0xc7, 0xb4, 0x2c, 0xbf, 0xbb, 0xeb, 0xdd, 0x3e,
+ 0xe2, 0xcb, 0xf3, 0xeb, 0xf9, 0xda, 0xcb, 0xe1, 0xb4, 0x4e, 0xb2, 0xd1,
+ 0xa3, 0xca, 0x09, 0x45, 0xff, 0xcc, 0x3d, 0x99, 0x9d, 0x01, 0xcb, 0xeb,
+ 0x2d, 0x29, 0x1f, 0x67, 0x09, 0xea, 0x13, 0x12, 0x78, 0x75, 0x54, 0x32,
+ 0x04, 0xf2, 0x73, 0x15, 0xa3, 0xae, 0x73, 0x50, 0xc6, 0x89, 0x73, 0x49,
+ 0x65, 0xfd, 0xd7, 0xc7, 0x98, 0x6a, 0xcb, 0xfb, 0xcd, 0xfe, 0x67, 0xd6,
+ 0x5f, 0x64, 0xcc, 0x75, 0x94, 0x34, 0x4a, 0x60, 0xb7, 0x65, 0xe2, 0x16,
+ 0xda, 0x16, 0x5f, 0x41, 0x30, 0x16, 0x5b, 0x3c, 0x6c, 0x3e, 0x21, 0x7f,
+ 0xb4, 0x4e, 0x60, 0x9d, 0x18, 0xb2, 0xe0, 0x6f, 0x59, 0x7e, 0xff, 0x83,
+ 0x38, 0x56, 0x50, 0xcf, 0xeb, 0xc6, 0xe1, 0x19, 0xbf, 0xfc, 0xc0, 0xef,
+ 0xcd, 0xe2, 0x8c, 0xd6, 0x2c, 0xbf, 0xc3, 0xea, 0x59, 0x85, 0x3a, 0xcb,
+ 0xff, 0x4a, 0x37, 0x33, 0x5f, 0xe4, 0x49, 0x65, 0xff, 0x74, 0x38, 0xe3,
+ 0x0f, 0xd0, 0xb2, 0xff, 0x37, 0xf8, 0xfd, 0x00, 0xc5, 0x97, 0x6a, 0x75,
+ 0x46, 0x0a, 0xaf, 0x1e, 0xd3, 0x9a, 0xdf, 0xf9, 0xf5, 0x84, 0x0e, 0x7f,
+ 0x9d, 0x2c, 0xbf, 0xff, 0xff, 0xb3, 0xfe, 0x72, 0x37, 0x67, 0x34, 0xef,
+ 0xfd, 0xf8, 0x3d, 0x98, 0x77, 0x2e, 0xa4, 0xb8, 0x82, 0xd7, 0xfe, 0x77,
+ 0x37, 0xb7, 0x1e, 0xc3, 0x4c, 0x5c, 0x41, 0x6b, 0xff, 0xbc, 0xde, 0x68,
+ 0x2f, 0xec, 0x34, 0xc5, 0xc4, 0x16, 0xbf, 0xd0, 0xc5, 0xfd, 0x86, 0x98,
+ 0xb8, 0x82, 0xd7, 0xf1, 0xf0, 0x7b, 0x0d, 0x31, 0x71, 0x05, 0xaf, 0xff,
+ 0xf9, 0xc8, 0x98, 0xfb, 0x39, 0xdf, 0x9b, 0x4c, 0x6c, 0xf8, 0x62, 0xe2,
+ 0x0b, 0x5d, 0xd6, 0xc1, 0xa7, 0x3d, 0xda, 0x8e, 0x95, 0x1d, 0x0c, 0x8f,
+ 0xea, 0x15, 0x68, 0xf8, 0xfc, 0xa5, 0x1c, 0xdf, 0xe6, 0x83, 0x79, 0xfe,
+ 0x74, 0xb2, 0xf9, 0xf4, 0x07, 0x59, 0x7f, 0xf7, 0x9b, 0xcd, 0x05, 0xfd,
+ 0x86, 0x98, 0xb8, 0x82, 0xd7, 0xfd, 0x37, 0x3b, 0x69, 0xf6, 0x1a, 0x62,
+ 0xe2, 0x0b, 0x5f, 0xbf, 0xc8, 0x3e, 0xce, 0xd1, 0x44, 0x22, 0xa5, 0xff,
+ 0xed, 0x9d, 0xf9, 0xbb, 0x8f, 0xf3, 0x61, 0xa6, 0x2e, 0x20, 0xb5, 0xff,
+ 0xff, 0xc4, 0x4c, 0x7d, 0x81, 0xcd, 0x9c, 0xef, 0xcd, 0xa6, 0x36, 0x7c,
+ 0x31, 0x71, 0x05, 0xab, 0x13, 0x29, 0xe9, 0x11, 0xd8, 0x2f, 0xfb, 0xcd,
+ 0xa6, 0x36, 0x7c, 0x31, 0x71, 0x05, 0xaf, 0xff, 0x9d, 0xfa, 0x97, 0x3c,
+ 0xc3, 0x1c, 0x6a, 0x12, 0x5f, 0xfb, 0x25, 0x20, 0xf3, 0x45, 0x3e, 0xda,
+ 0xe2, 0x0b, 0x57, 0x68, 0xe7, 0xd2, 0x47, 0x13, 0xef, 0xfd, 0xdb, 0x6b,
+ 0xee, 0x0e, 0x6c, 0x31, 0x71, 0x05, 0xaf, 0xef, 0x37, 0xbc, 0xc0, 0x54,
+ 0x01, 0x6b, 0xf6, 0x03, 0x61, 0xa6, 0x2e, 0x20, 0xb5, 0xd9, 0xfe, 0xcf,
+ 0xcf, 0xc7, 0x55, 0xd2, 0x3c, 0x79, 0x0c, 0x3b, 0xf8, 0xf8, 0x3d, 0x86,
+ 0x98, 0xb8, 0x82, 0xd7, 0xfe, 0xef, 0xcd, 0xa6, 0x36, 0x7c, 0x31, 0x71,
+ 0x05, 0xae, 0xcd, 0x8e, 0x88, 0xee, 0x1f, 0xdf, 0xe0, 0xb1, 0xdc, 0xba,
+ 0x92, 0xe2, 0x0b, 0x5f, 0xfb, 0x1b, 0x7e, 0x16, 0x0d, 0xe4, 0xb8, 0x82,
+ 0xc7, 0x3c, 0x0a, 0x1a, 0xf0, 0x96, 0x8d, 0xc0, 0x6a, 0x51, 0xf6, 0x72,
+ 0x31, 0x7f, 0xc6, 0x44, 0x18, 0x5b, 0x98, 0xdf, 0x70, 0x21, 0x51, 0x05,
+ 0x85, 0xa2, 0x2e, 0xe7, 0xed, 0x65, 0x0d, 0x94, 0xe1, 0xdc, 0x24, 0xc1,
+ 0x49, 0x8f, 0xf9, 0xbd, 0x63, 0x2c, 0xd6, 0x63, 0x4e, 0x52, 0xac, 0x6e,
+ 0x96, 0xea, 0xcb, 0xd1, 0x2d, 0xd5, 0x95, 0x06, 0xe4, 0x86, 0xaa, 0x76,
+ 0x6a, 0x78, 0xdb, 0xba, 0x85, 0x06, 0x8b, 0xc1, 0x4b, 0x7d, 0x27, 0x6b,
+ 0xff, 0x48, 0xb3, 0xfe, 0x6c, 0xeb, 0xeb, 0x2f, 0xe2, 0x97, 0x3f, 0xe8,
+ 0x59, 0x58, 0x7d, 0x6c, 0x7d, 0x7f, 0xa3, 0xcc, 0x67, 0x52, 0xe2, 0xcb,
+ 0xf4, 0x7f, 0x9e, 0x65, 0x97, 0xfe, 0xd6, 0x1b, 0xec, 0x38, 0x75, 0x3a,
+ 0xcb, 0xfe, 0xe8, 0xb1, 0x8f, 0x84, 0x05, 0x97, 0xff, 0xff, 0xe7, 0x98,
+ 0x9c, 0xcc, 0xde, 0xdc, 0xf6, 0x03, 0x6f, 0x3f, 0xc7, 0x3e, 0x75, 0xf5,
+ 0x97, 0xe9, 0x7f, 0x98, 0x4b, 0x2f, 0xff, 0x3f, 0x70, 0x43, 0x2c, 0xdf,
+ 0xa6, 0xe2, 0xcb, 0xff, 0x72, 0x69, 0x04, 0x73, 0x48, 0x23, 0x59, 0x53,
+ 0xaa, 0x10, 0x91, 0xa8, 0xc9, 0xf1, 0x04, 0xd3, 0x7e, 0xa1, 0x11, 0xe2,
+ 0x7f, 0xa5, 0x5f, 0xf6, 0x7c, 0xcc, 0x21, 0xfa, 0x16, 0x5f, 0xfd, 0x1d,
+ 0x48, 0x43, 0xf3, 0xf1, 0xd1, 0x8b, 0x2f, 0xd2, 0xdd, 0xdd, 0x0c, 0xeb,
+ 0x2d, 0xe6, 0x3f, 0x97, 0x49, 0xbe, 0xf9, 0x41, 0xd6, 0x5f, 0xb5, 0x1d,
+ 0x4b, 0x8b, 0x2a, 0x74, 0xc8, 0x65, 0x0b, 0x16, 0x26, 0xd1, 0x0d, 0xff,
+ 0x41, 0xbe, 0xc2, 0x2c, 0xe9, 0x65, 0xe3, 0xbf, 0xd6, 0x5c, 0xfc, 0x59,
+ 0x7a, 0x4d, 0xf5, 0x97, 0xff, 0xbe, 0xc4, 0x19, 0x67, 0x01, 0xff, 0xf4,
+ 0xb2, 0xc5, 0x31, 0xf3, 0x88, 0x39, 0x7f, 0xdc, 0x7e, 0xb6, 0xc3, 0xe6,
+ 0xd2, 0xcb, 0xfb, 0x34, 0x03, 0xb7, 0x16, 0x5c, 0x1e, 0x7c, 0xfa, 0xb6,
+ 0xcf, 0x6f, 0x66, 0x8d, 0x59, 0x7f, 0xf6, 0xfd, 0xf1, 0xc7, 0xf7, 0x52,
+ 0xcf, 0xac, 0xac, 0x4c, 0xa8, 0x10, 0x93, 0xdb, 0x31, 0x10, 0x76, 0xfe,
+ 0x0c, 0xd0, 0x5c, 0x65, 0x97, 0xf8, 0x84, 0xcd, 0x14, 0x1d, 0x65, 0xfc,
+ 0x1f, 0x94, 0x7f, 0x8b, 0x2b, 0x0f, 0x7c, 0x06, 0x55, 0x25, 0x56, 0xc6,
+ 0x8e, 0x02, 0x3a, 0x72, 0x46, 0xe4, 0x23, 0x2a, 0x17, 0x48, 0xf2, 0x39,
+ 0xbe, 0x90, 0xde, 0x57, 0x75, 0xe3, 0xb7, 0x16, 0x5f, 0xa5, 0x1b, 0xdf,
+ 0xcb, 0x2a, 0x73, 0xc5, 0x71, 0xcb, 0xff, 0xb3, 0xaf, 0xf1, 0x8a, 0x00,
+ 0xe7, 0x59, 0x7d, 0xbb, 0x99, 0x3a, 0xcb, 0xff, 0xf6, 0x7f, 0xcd, 0xb0,
+ 0xd7, 0xd8, 0x58, 0x63, 0x81, 0x65, 0xf1, 0xc7, 0x87, 0x59, 0x7f, 0xfb,
+ 0xc3, 0x13, 0xed, 0xe2, 0xcf, 0xc0, 0x16, 0x5f, 0xf6, 0xf6, 0x21, 0x87,
+ 0xd8, 0x75, 0x97, 0xf3, 0xf9, 0xb9, 0x12, 0x59, 0x5b, 0x11, 0xa5, 0x04,
+ 0x58, 0x95, 0xc3, 0xab, 0xff, 0x0a, 0xf0, 0x8b, 0x04, 0x82, 0x02, 0xcb,
+ 0xfd, 0x9e, 0x6e, 0x30, 0x64, 0xb2, 0xa7, 0x54, 0x85, 0xe4, 0x32, 0x25,
+ 0xfc, 0x65, 0x61, 0x3d, 0xdd, 0x40, 0xbe, 0xeb, 0x91, 0xd2, 0xcb, 0xff,
+ 0x4b, 0x3a, 0x96, 0xa3, 0xef, 0xf5, 0x97, 0x8f, 0x12, 0x59, 0x7e, 0xc1,
+ 0xf8, 0x26, 0x2c, 0xad, 0x88, 0xa8, 0x98, 0x91, 0xcf, 0xc8, 0x72, 0xff,
+ 0xbb, 0xf3, 0x0f, 0xd1, 0xfe, 0x2c, 0xbc, 0x37, 0xfa, 0xcb, 0xff, 0xf7,
+ 0xff, 0x93, 0x4b, 0x27, 0xd9, 0xd4, 0x14, 0x71, 0x65, 0xff, 0xef, 0xe4,
+ 0xd2, 0xc9, 0xfa, 0x82, 0x8e, 0x2c, 0xbc, 0x51, 0xd6, 0xc4, 0x52, 0x7d,
+ 0x66, 0xff, 0xdc, 0x82, 0x89, 0x7f, 0xd8, 0x4b, 0x2b, 0x49, 0xd5, 0x1c,
+ 0xf9, 0xce, 0x81, 0x0c, 0x0e, 0x1b, 0x5e, 0x6d, 0xbc, 0x59, 0x79, 0xba,
+ 0xfa, 0xcb, 0xde, 0x9d, 0x96, 0x5d, 0x86, 0x70, 0xdd, 0x04, 0x76, 0xff,
+ 0xda, 0x27, 0x31, 0xf5, 0xac, 0xe9, 0x65, 0xe2, 0x63, 0x56, 0x5f, 0xdc,
+ 0x61, 0xe1, 0x9c, 0x59, 0x7f, 0x3e, 0x9c, 0x6d, 0x8b, 0x2e, 0xd0, 0x16,
+ 0x5d, 0x86, 0x2c, 0xa7, 0x35, 0xdf, 0x17, 0xa8, 0x4e, 0x1e, 0x75, 0x81,
+ 0x96, 0xe1, 0xff, 0x43, 0x9e, 0x2e, 0xfa, 0xcd, 0xe3, 0xbb, 0x2c, 0xae,
+ 0x91, 0x00, 0x06, 0x5b, 0xe3, 0x33, 0xce, 0xb2, 0xf8, 0xdd, 0x31, 0x8b,
+ 0x2f, 0xd3, 0xbf, 0xa3, 0x71, 0x65, 0xff, 0x1b, 0x85, 0x12, 0xfe, 0x76,
+ 0xb2, 0xfd, 0x3f, 0xf6, 0xf3, 0xeb, 0x2b, 0x6a, 0x45, 0xa6, 0x12, 0x31,
+ 0x58, 0x4e, 0x6f, 0xe3, 0x7d, 0x1d, 0x7f, 0x16, 0x5f, 0xe2, 0xc1, 0xfa,
+ 0x0c, 0x25, 0x95, 0x07, 0xc3, 0xa2, 0xfb, 0xff, 0xfd, 0xa8, 0xf4, 0x6b,
+ 0x51, 0x3f, 0xdd, 0xcd, 0xce, 0xbe, 0xb2, 0xa1, 0x93, 0x19, 0x92, 0x99,
+ 0x1a, 0x55, 0xa3, 0xca, 0x56, 0x01, 0x21, 0x43, 0x58, 0x30, 0xa1, 0x10,
+ 0x86, 0xf8, 0xa6, 0xe6, 0x2c, 0xbf, 0x4b, 0x27, 0xfc, 0x2c, 0xbf, 0xff,
+ 0xa3, 0xe2, 0x4e, 0x3c, 0xfc, 0x6f, 0x6f, 0x82, 0x24, 0xb2, 0xff, 0xd1,
+ 0x39, 0xfc, 0xda, 0xd3, 0xc9, 0x65, 0x4e, 0x89, 0xd2, 0x5e, 0xa5, 0x94,
+ 0xc9, 0x8a, 0xcc, 0x44, 0x50, 0xc5, 0xdb, 0x23, 0xbf, 0xd3, 0xcf, 0x05,
+ 0xd6, 0x7d, 0x65, 0xf8, 0x79, 0x85, 0xda, 0xcb, 0xf7, 0x5f, 0x27, 0xf2,
+ 0xcb, 0xa2, 0x65, 0x95, 0x39, 0xf3, 0x48, 0x9c, 0x05, 0x15, 0x89, 0x88,
+ 0x32, 0x28, 0x61, 0x37, 0x7f, 0xf6, 0x88, 0x3d, 0x7c, 0xb2, 0x77, 0x25,
+ 0x97, 0xff, 0xf0, 0xfc, 0x19, 0xdb, 0x35, 0xac, 0x8e, 0xa4, 0xc7, 0x59,
+ 0x7f, 0x9e, 0x62, 0x0f, 0xca, 0x16, 0x5f, 0xc3, 0x13, 0xff, 0x63, 0x16,
+ 0x5c, 0x53, 0x2c, 0xa7, 0x3c, 0x70, 0x98, 0x5d, 0xe3, 0x56, 0x5f, 0xf7,
+ 0xa3, 0xa2, 0xc1, 0xbc, 0x96, 0x5e, 0x7d, 0x4e, 0xb2, 0xe0, 0x42, 0xcb,
+ 0xe6, 0x83, 0xe2, 0xca, 0x59, 0x7f, 0x39, 0xbf, 0x8d, 0x01, 0x65, 0x0c,
+ 0xdc, 0x90, 0x5d, 0xff, 0xfe, 0x86, 0x19, 0x40, 0x7b, 0xfe, 0x76, 0x38,
+ 0xec, 0x43, 0xac, 0xb8, 0x10, 0xb2, 0xe8, 0x35, 0x65, 0xff, 0x67, 0xf9,
+ 0x07, 0x13, 0x26, 0x59, 0x7f, 0xb9, 0x9e, 0x6e, 0x06, 0x75, 0x97, 0x18,
+ 0x62, 0x4b, 0xfe, 0x2c, 0xde, 0xf2, 0xe3, 0x0d, 0x65, 0x76, 0x9f, 0xe3,
+ 0x0e, 0xe8, 0x58, 0xeb, 0x3e, 0x20, 0x03, 0x18, 0xac, 0x58, 0x85, 0xf8,
+ 0x74, 0x61, 0xa0, 0x83, 0x37, 0x8c, 0x30, 0xc4, 0x96, 0x3a, 0x41, 0x66,
+ 0x82, 0xf3, 0xbe, 0x92, 0x0b, 0x47, 0x08, 0x90, 0xbe, 0xa1, 0xab, 0x6f,
+ 0xec, 0x62, 0x69, 0x62, 0xb5, 0x3a, 0xe7, 0x27, 0x68, 0x9d, 0x2e, 0x79,
+ 0xe5, 0xe5, 0xc8, 0x5f, 0xdf, 0x8c, 0xf6, 0x4e, 0xb2, 0xec, 0x3a, 0xca,
+ 0xe8, 0xf0, 0xf8, 0x5b, 0x7f, 0xef, 0x79, 0xdb, 0xf1, 0x85, 0x32, 0xcb,
+ 0x71, 0x65, 0x61, 0xe7, 0x31, 0xed, 0x0a, 0x5f, 0x4b, 0x56, 0x27, 0x35,
+ 0x67, 0x86, 0x5c, 0xa5, 0x75, 0x0d, 0x87, 0x27, 0x77, 0xcd, 0x96, 0x63,
+ 0xd4, 0xb2, 0x76, 0x9d, 0x7b, 0x9a, 0x19, 0x5a, 0x86, 0xe9, 0xe3, 0x16,
+ 0xf5, 0x2f, 0xfd, 0xe9, 0xc8, 0x20, 0x86, 0xa9, 0x4f, 0xa9, 0xf2, 0x94,
+ 0x39, 0xf9, 0x56, 0xa1, 0x9d, 0x18, 0xdf, 0x09, 0x9d, 0xb7, 0x1b, 0x84,
+ 0xfa, 0xcb, 0xfb, 0x00, 0x06, 0xd4, 0x96, 0x5e, 0xf0, 0x4d, 0x59, 0x77,
+ 0x78, 0xb2, 0x86, 0x7c, 0x4c, 0x5a, 0xe3, 0xd7, 0xfe, 0x83, 0xed, 0xbc,
+ 0xf8, 0x36, 0x31, 0x65, 0xd8, 0x62, 0xcb, 0xa3, 0xeb, 0x2a, 0x73, 0x5b,
+ 0xd8, 0xbd, 0x8e, 0xb2, 0xa4, 0x8a, 0x3c, 0x6f, 0xf9, 0x1d, 0xfe, 0x93,
+ 0x16, 0x1c, 0x3e, 0x59, 0x7e, 0xf3, 0xb1, 0x3a, 0xcb, 0xff, 0x67, 0xf9,
+ 0xe6, 0x3b, 0xe6, 0x96, 0x5d, 0x83, 0x59, 0x50, 0x8a, 0xa3, 0x4c, 0x88,
+ 0x97, 0x79, 0xed, 0xfb, 0x36, 0x60, 0x3e, 0xb2, 0xfb, 0x67, 0xe3, 0x7a,
+ 0xcb, 0xf6, 0x77, 0x07, 0x65, 0x97, 0xd8, 0x7c, 0xfa, 0xcb, 0xfb, 0xd0,
+ 0x23, 0x44, 0xeb, 0x2f, 0xf9, 0xb7, 0xeb, 0x26, 0xce, 0xbe, 0xb2, 0xbb,
+ 0x3e, 0xaf, 0x17, 0x5c, 0xe6, 0xac, 0xad, 0x1b, 0xaf, 0x91, 0xdf, 0x39,
+ 0xde, 0x65, 0x97, 0xff, 0xa6, 0x69, 0xb6, 0x37, 0x5c, 0x71, 0x18, 0xeb,
+ 0x2f, 0xcd, 0x06, 0x44, 0xcb, 0x2f, 0xf6, 0xcf, 0x38, 0x00, 0xde, 0x59,
+ 0x7c, 0xff, 0xeb, 0x8b, 0x2a, 0x11, 0x9e, 0xc9, 0xee, 0x50, 0x46, 0xb7,
+ 0xff, 0xfe, 0x79, 0x83, 0x20, 0xf7, 0xb3, 0xcd, 0xff, 0xc7, 0x51, 0x3c,
+ 0x71, 0x65, 0xf8, 0x9f, 0x72, 0x79, 0x96, 0x5f, 0x4d, 0xc8, 0xfa, 0xca,
+ 0xed, 0x18, 0x33, 0x39, 0x04, 0xb2, 0xc6, 0x2c, 0xbf, 0xff, 0xc4, 0xef,
+ 0xbe, 0x25, 0xe8, 0xd4, 0xf1, 0xfe, 0x3c, 0x96, 0x5f, 0xd1, 0xdf, 0xf8,
+ 0xfd, 0x2c, 0xbe, 0xf6, 0x3c, 0xeb, 0x2f, 0xb0, 0xef, 0xd2, 0xca, 0xdc,
+ 0x46, 0xa1, 0x30, 0xf0, 0xbc, 0x42, 0x2b, 0xcd, 0xd4, 0xcb, 0x2f, 0x82,
+ 0x2b, 0x3b, 0x2c, 0xbf, 0x66, 0x4e, 0x1e, 0x2c, 0xbe, 0xd1, 0x30, 0x16,
+ 0x5f, 0x37, 0x6f, 0xa5, 0x97, 0x40, 0x16, 0x5f, 0x06, 0x70, 0x8b, 0xf1,
+ 0xb8, 0x10, 0x8a, 0x99, 0x12, 0xde, 0x59, 0xb0, 0x16, 0x5d, 0x9d, 0xac,
+ 0xbf, 0x66, 0xb4, 0xda, 0x59, 0x5b, 0x87, 0x9f, 0xe1, 0x10, 0x0b, 0xdf,
+ 0x47, 0x59, 0xda, 0xcb, 0xf0, 0x8d, 0x1c, 0x75, 0x94, 0xe7, 0x94, 0x12,
+ 0x3b, 0xfe, 0xf3, 0xf3, 0xcd, 0x3b, 0x92, 0xcb, 0xe7, 0x9c, 0x49, 0x2c,
+ 0xa1, 0x4b, 0x25, 0xb0, 0x50, 0xf5, 0x10, 0xd0, 0x94, 0x36, 0x46, 0x7d,
+ 0x85, 0x26, 0x93, 0x74, 0x4e, 0xd0, 0xc5, 0xdc, 0x21, 0x9a, 0x1e, 0x3a,
+ 0x87, 0xd7, 0x8c, 0x9e, 0x1c, 0xc0, 0x40, 0x15, 0x8f, 0x70, 0x9b, 0xf0,
+ 0xbe, 0x0b, 0x89, 0x8f, 0x82, 0x10, 0xee, 0x9c, 0x5f, 0xec, 0x26, 0x07,
+ 0x3c, 0xcb, 0x2d, 0xb8, 0xb2, 0xf8, 0x67, 0x79, 0x2c, 0xa6, 0x36, 0xc1,
+ 0x14, 0xad, 0x88, 0x87, 0x26, 0x7b, 0xcd, 0x38, 0x56, 0x5c, 0xf0, 0xb2,
+ 0xfd, 0x00, 0x6e, 0xb1, 0x65, 0xc7, 0x0a, 0xcb, 0xf3, 0xff, 0xc1, 0x25,
+ 0x97, 0x1f, 0x7a, 0xcb, 0xfe, 0x0b, 0xb1, 0x3f, 0xdf, 0xcb, 0x2b, 0x62,
+ 0x32, 0x60, 0x55, 0x89, 0xfc, 0x2e, 0x44, 0xfc, 0x19, 0xbf, 0xfa, 0x38,
+ 0xc0, 0x8d, 0x37, 0xa0, 0x6b, 0x2f, 0x38, 0x45, 0x6b, 0x2f, 0xfd, 0x9d,
+ 0x96, 0x73, 0x6f, 0x35, 0x0b, 0x28, 0x68, 0xf8, 0x25, 0x6f, 0xa1, 0x08,
+ 0x41, 0x7f, 0xfa, 0x45, 0x1b, 0x0e, 0x50, 0x6f, 0xda, 0x75, 0x97, 0xd8,
+ 0x1d, 0x4e, 0xb2, 0xfc, 0xe7, 0xcf, 0x1d, 0x65, 0x74, 0x89, 0x6d, 0x26,
+ 0x7c, 0x8e, 0xc6, 0x2c, 0xbd, 0xfd, 0x42, 0xcb, 0xdc, 0x7f, 0xac, 0xbe,
+ 0xc9, 0xc4, 0x92, 0xcb, 0xc2, 0x10, 0x16, 0x57, 0x47, 0xba, 0x43, 0x9f,
+ 0x24, 0xbf, 0xbf, 0xbf, 0x0b, 0x06, 0xb2, 0xa6, 0x3d, 0xde, 0x17, 0xdf,
+ 0xb9, 0x92, 0x6d, 0x2c, 0xbf, 0x4d, 0x27, 0xeb, 0x8b, 0x2b, 0x0f, 0x47,
+ 0x84, 0xf7, 0x83, 0xb9, 0xba, 0xb2, 0xdb, 0xd6, 0x5f, 0xf6, 0xbc, 0xe2,
+ 0x3f, 0x98, 0x0b, 0x2a, 0x0f, 0x31, 0x84, 0xef, 0xe6, 0x29, 0xfc, 0x1e,
+ 0x2c, 0xaf, 0x1e, 0x77, 0xc8, 0x2e, 0xdc, 0xdd, 0x59, 0x7b, 0x92, 0x9d,
+ 0x65, 0x4e, 0x98, 0xd6, 0x42, 0xf4, 0x24, 0x42, 0x0e, 0xd4, 0x2e, 0xf0,
+ 0xc8, 0x93, 0x23, 0xde, 0x68, 0x69, 0xcc, 0x62, 0x71, 0x27, 0x86, 0xb1,
+ 0x3a, 0x7e, 0x33, 0xbb, 0xcf, 0xb0, 0x45, 0x97, 0xa6, 0x6f, 0x2c, 0xbf,
+ 0xa3, 0x4f, 0x33, 0x79, 0x65, 0xfb, 0x83, 0x82, 0x9d, 0xcf, 0x2b, 0x83,
+ 0xb7, 0xff, 0xbf, 0xf8, 0x28, 0x34, 0xd8, 0x96, 0xe1, 0xd6, 0x5f, 0xd9,
+ 0x3c, 0x7b, 0xd0, 0xb2, 0xfd, 0x93, 0x7b, 0x09, 0x65, 0xfb, 0x04, 0x20,
+ 0x81, 0x65, 0xf8, 0x0e, 0xf2, 0x3a, 0xca, 0x83, 0xcf, 0xc2, 0x8a, 0x64,
+ 0xc4, 0x74, 0x9d, 0xe2, 0xd2, 0x76, 0xbc, 0x78, 0x3a, 0xca, 0xe9, 0x3a,
+ 0x7d, 0x46, 0x9e, 0x73, 0xcb, 0xe3, 0xeb, 0x50, 0xb2, 0xfe, 0x6d, 0x70,
+ 0x48, 0x02, 0xcb, 0xff, 0xb3, 0xfe, 0x6f, 0xfb, 0x0a, 0x00, 0xb2, 0xdb,
+ 0xc0, 0x7e, 0x04, 0x5d, 0x7f, 0xfa, 0x5b, 0x30, 0x6d, 0xce, 0xbe, 0x17,
+ 0xe2, 0xcb, 0xfe, 0xe6, 0x7e, 0x0e, 0xda, 0x92, 0xca, 0x64, 0x57, 0x11,
+ 0x4f, 0xd3, 0x6f, 0xde, 0x09, 0x46, 0xf5, 0x97, 0xf1, 0x3f, 0xe5, 0x06,
+ 0xac, 0xa8, 0x3d, 0x61, 0x0a, 0x6e, 0x3f, 0x16, 0x5f, 0x4f, 0xb3, 0x77,
+ 0xb5, 0x97, 0xf7, 0x98, 0xcc, 0xeb, 0xeb, 0x2f, 0xff, 0x72, 0x35, 0xdf,
+ 0xf8, 0xdf, 0xf6, 0x0d, 0x65, 0xf6, 0x67, 0x52, 0x59, 0x7b, 0x8d, 0x32,
+ 0xca, 0x23, 0x7f, 0xc2, 0x2b, 0xf3, 0x6f, 0xd6, 0x1d, 0x65, 0x1a, 0x79,
+ 0x3e, 0x20, 0xb7, 0x16, 0x5f, 0xce, 0xfa, 0x33, 0x3c, 0xb2, 0xff, 0x34,
+ 0x7f, 0x37, 0xb8, 0xd6, 0x5f, 0xef, 0x46, 0x9b, 0xb6, 0xde, 0xb2, 0xa6,
+ 0x44, 0xae, 0x8b, 0x7e, 0x67, 0x7f, 0xe9, 0xca, 0x3a, 0x61, 0x94, 0x4e,
+ 0xb2, 0xff, 0x03, 0x9f, 0x28, 0x3f, 0x16, 0x5f, 0xe3, 0xc7, 0x9f, 0x91,
+ 0xb8, 0xb2, 0xa0, 0xfa, 0x1c, 0xce, 0x9d, 0x18, 0xe5, 0x0a, 0x7a, 0x1a,
+ 0xae, 0x9e, 0xcb, 0xf5, 0x0d, 0x33, 0x91, 0xfa, 0x14, 0xc5, 0x0f, 0x8b,
+ 0xe3, 0x4c, 0x19, 0xd6, 0x5f, 0xb6, 0x7a, 0x35, 0x25, 0x95, 0xb1, 0x90,
+ 0x1f, 0x12, 0x84, 0x27, 0x38, 0xc8, 0xd0, 0x3b, 0x84, 0x24, 0xc4, 0x47,
+ 0x17, 0x79, 0x62, 0x7f, 0x68, 0x30, 0x96, 0xf1, 0xf9, 0x0b, 0x2f, 0xe9,
+ 0xe6, 0x90, 0xa3, 0x53, 0xac, 0xbe, 0x3e, 0x3f, 0x96, 0x5a, 0x75, 0x97,
+ 0xef, 0xf9, 0x8f, 0xa5, 0x95, 0x23, 0x75, 0xa1, 0x2b, 0xde, 0x1b, 0x2c,
+ 0xbf, 0x7b, 0x1a, 0x5c, 0x59, 0x7f, 0xfd, 0xe8, 0x10, 0x5f, 0xc9, 0xc1,
+ 0xce, 0x40, 0x12, 0x5f, 0xb3, 0xee, 0x11, 0x5a, 0xcb, 0x6e, 0x2c, 0xbf,
+ 0x6b, 0xb7, 0x7e, 0xd7, 0x10, 0x22, 0xf7, 0x23, 0xa5, 0x97, 0xcd, 0xcd,
+ 0x49, 0x65, 0x81, 0x08, 0x89, 0xc1, 0x4e, 0x8d, 0x8e, 0x3b, 0x7c, 0x58,
+ 0x66, 0xea, 0xcb, 0x9a, 0x75, 0x94, 0xc6, 0xf3, 0xe4, 0xb7, 0x82, 0x5d,
+ 0xac, 0xbe, 0x9c, 0x9c, 0xeb, 0x2e, 0x72, 0x59, 0x50, 0x6d, 0xe7, 0x22,
+ 0xa9, 0x2a, 0x40, 0x19, 0x3f, 0x4a, 0x5a, 0x85, 0xa1, 0xdf, 0xbc, 0x41,
+ 0xf5, 0x4b, 0xf9, 0xf5, 0x9b, 0xf0, 0x6b, 0x2f, 0xdd, 0xb9, 0xbe, 0x65,
+ 0x94, 0x03, 0xd7, 0x22, 0xeb, 0xed, 0x0d, 0x8e, 0xb2, 0xf0, 0xde, 0x4b,
+ 0x2d, 0x25, 0x95, 0x06, 0xb7, 0x74, 0x72, 0xfb, 0xf3, 0xb9, 0x2c, 0xbc,
+ 0x78, 0xed, 0x65, 0xce, 0x6a, 0xca, 0xc3, 0x68, 0x43, 0xb6, 0x92, 0xcb,
+ 0xfb, 0x27, 0x0f, 0xf7, 0xfd, 0x65, 0x41, 0xe1, 0x1a, 0x23, 0x7f, 0xcf,
+ 0x2d, 0x44, 0xef, 0xae, 0xd6, 0x59, 0x96, 0x5f, 0xff, 0x9f, 0xa0, 0x77,
+ 0xe6, 0x98, 0x9c, 0xcf, 0xe7, 0x96, 0x5e, 0x35, 0xbe, 0xb2, 0xf7, 0x1f,
+ 0xeb, 0x2a, 0x11, 0x43, 0x82, 0x06, 0xac, 0x74, 0x3b, 0x76, 0xcf, 0x2c,
+ 0xbf, 0x7d, 0x86, 0x18, 0x59, 0x7c, 0xf2, 0xc1, 0xac, 0xa3, 0x9e, 0x41,
+ 0x13, 0xde, 0x3f, 0xfb, 0x59, 0x6f, 0xc1, 0xbf, 0xc2, 0x1b, 0xfa, 0x0f,
+ 0x86, 0xc7, 0x16, 0x54, 0xea, 0xc1, 0xb0, 0x8f, 0xb5, 0x6d, 0x30, 0x9c,
+ 0x8b, 0xd0, 0xdb, 0x01, 0xe9, 0x42, 0x83, 0xe4, 0xb7, 0x98, 0xf0, 0xb2,
+ 0xe8, 0x3a, 0xcb, 0xd9, 0xac, 0x59, 0x5d, 0x9b, 0x13, 0x8b, 0x5f, 0xf0,
+ 0x3d, 0x9d, 0x4b, 0xed, 0x32, 0xca, 0xc3, 0xdd, 0x09, 0x15, 0xd9, 0x3a,
+ 0xcb, 0x05, 0x65, 0x0c, 0xd4, 0x68, 0x5e, 0xff, 0x46, 0x17, 0xf9, 0xb7,
+ 0xbd, 0x65, 0xfd, 0x1b, 0x9e, 0x67, 0x92, 0xcb, 0xd1, 0xcd, 0x87, 0x3e,
+ 0x62, 0x37, 0xbf, 0x9c, 0xce, 0x72, 0x00, 0xb2, 0xbc, 0x7c, 0x44, 0x69,
+ 0x7a, 0x1f, 0x4b, 0x2f, 0xfd, 0xe7, 0x2f, 0xf0, 0x82, 0xe2, 0x2c, 0xbf,
+ 0xed, 0x69, 0xba, 0x97, 0xdf, 0xa5, 0x97, 0xb6, 0xdc, 0xd5, 0x97, 0xfd,
+ 0x07, 0x96, 0x4f, 0x81, 0x15, 0xac, 0xbf, 0xe8, 0x03, 0x4b, 0xcc, 0x40,
+ 0x59, 0x69, 0xd6, 0x5c, 0xff, 0xd1, 0xe4, 0x8a, 0xcd, 0xeb, 0x11, 0xae,
+ 0xc4, 0x0f, 0x08, 0x6b, 0xc6, 0x40, 0x8b, 0x2f, 0xfe, 0x7e, 0x09, 0xf6,
+ 0x20, 0xcb, 0x38, 0xb2, 0xe2, 0x1a, 0xea, 0xfa, 0x54, 0x1f, 0x3b, 0xa2,
+ 0x5c, 0x07, 0x59, 0x7d, 0x20, 0xc1, 0xab, 0x2c, 0x05, 0x95, 0x86, 0xd1,
+ 0xc8, 0xea, 0x15, 0xda, 0x8e, 0x1d, 0x26, 0x90, 0xf6, 0x36, 0xc7, 0xda,
+ 0x8c, 0x4b, 0xc6, 0x40, 0x84, 0x29, 0x10, 0x7d, 0x2a, 0xff, 0x0f, 0xce,
+ 0x71, 0x20, 0x96, 0x5f, 0xde, 0xc9, 0x79, 0xb7, 0xac, 0xad, 0xc3, 0xe2,
+ 0xf9, 0x9d, 0x89, 0x65, 0xed, 0x06, 0x75, 0x95, 0x23, 0x5c, 0x71, 0x0b,
+ 0xff, 0xe2, 0x63, 0x45, 0xf3, 0xfe, 0x0b, 0xca, 0x50, 0xb2, 0xa0, 0xfc,
+ 0xf0, 0x86, 0xfd, 0xec, 0xff, 0x21, 0x65, 0xf8, 0xbe, 0x1c, 0xf2, 0xcb,
+ 0x05, 0x65, 0x2c, 0xad, 0x85, 0xe0, 0x44, 0x6a, 0x0f, 0x96, 0x74, 0x3b,
+ 0xb7, 0x59, 0x65, 0xdb, 0xe1, 0x65, 0x82, 0xb2, 0xec, 0xd2, 0xcb, 0x70,
+ 0x06, 0x9f, 0xe2, 0x35, 0x3a, 0xb1, 0x19, 0x43, 0xf8, 0xd8, 0x63, 0x76,
+ 0x41, 0xa8, 0x46, 0x39, 0x17, 0x06, 0x7e, 0x7f, 0x78, 0x6f, 0x25, 0x97,
+ 0x36, 0x96, 0x56, 0x1b, 0x2f, 0x0e, 0x5f, 0x9c, 0x89, 0x8e, 0xb2, 0xf6,
+ 0x6f, 0x11, 0x65, 0xcd, 0xe5, 0x97, 0x86, 0xf2, 0x59, 0x7c, 0xe7, 0xc3,
+ 0xac, 0xbe, 0x63, 0xc6, 0xe2, 0xcb, 0x9b, 0x5b, 0x0f, 0x17, 0x08, 0x68,
+ 0x68, 0xa5, 0xc1, 0x6f, 0x30, 0xdf, 0x98, 0xee, 0x58, 0xb2, 0xf3, 0x44,
+ 0x96, 0x56, 0xc6, 0xc7, 0x4f, 0x6b, 0x1c, 0x83, 0x69, 0x2d, 0x8c, 0x87,
+ 0x25, 0x2e, 0x1b, 0x0c, 0x3e, 0xc8, 0x5a, 0x5a, 0xae, 0xa1, 0x15, 0xe8,
+ 0x54, 0xbc, 0xf8, 0x78, 0x21, 0x6c, 0x44, 0x1c, 0x25, 0x0c, 0x31, 0x36,
+ 0xcb, 0xf7, 0x49, 0x6f, 0xfe, 0xfc, 0x37, 0x9f, 0x50, 0x6e, 0x4c, 0xb2,
+ 0xfc, 0x38, 0xf4, 0x08, 0xb2, 0x9c, 0xfb, 0x02, 0x89, 0x7f, 0xcf, 0xc2,
+ 0xcd, 0xed, 0xe0, 0xac, 0xbf, 0xb3, 0xd9, 0xd8, 0x71, 0x65, 0xff, 0x16,
+ 0x7e, 0x37, 0xb1, 0x01, 0x65, 0xfe, 0xfc, 0x6f, 0x6f, 0xca, 0x16, 0x5f,
+ 0xff, 0xd8, 0x24, 0x68, 0x0d, 0xfd, 0x04, 0xfc, 0xfe, 0x69, 0x65, 0x62,
+ 0x24, 0x08, 0xd2, 0xfc, 0x37, 0x2c, 0xdc, 0x59, 0x58, 0x98, 0x90, 0x21,
+ 0x91, 0xc2, 0x1b, 0xb4, 0x75, 0x97, 0xcd, 0xf8, 0x92, 0xcb, 0xfc, 0x17,
+ 0x69, 0x41, 0x76, 0xb2, 0xb0, 0xfa, 0xbc, 0x2f, 0xc2, 0x1b, 0xde, 0xc0,
+ 0x2c, 0xbf, 0xf3, 0x6b, 0xcf, 0xc3, 0x75, 0xfe, 0xd6, 0x5f, 0x9b, 0xf1,
+ 0xfe, 0x24, 0xbe, 0xee, 0x3f, 0xc4, 0x97, 0x18, 0x62, 0x4a, 0x91, 0xf1,
+ 0xe1, 0x39, 0x84, 0x74, 0x90, 0x59, 0xaf, 0xa9, 0x26, 0x19, 0xe1, 0xc3,
+ 0x21, 0xa7, 0x79, 0xc8, 0x0b, 0x2f, 0x3f, 0x9d, 0x65, 0xf8, 0xcf, 0x89,
+ 0x00, 0x59, 0x58, 0x89, 0x73, 0x4d, 0xfc, 0x36, 0xe3, 0x77, 0x89, 0xcc,
+ 0x59, 0x7e, 0xf3, 0x46, 0x80, 0xb2, 0xa6, 0x3c, 0x3f, 0x8e, 0x5e, 0x9b,
+ 0xcc, 0xb2, 0xff, 0xb0, 0xbf, 0xe6, 0x82, 0x9d, 0x65, 0xff, 0xfe, 0xf6,
+ 0x1c, 0x48, 0x06, 0xa3, 0x85, 0x9b, 0xdb, 0xc1, 0x59, 0x7b, 0xf1, 0xde,
+ 0x22, 0x67, 0xe6, 0xf7, 0xff, 0x8c, 0x7e, 0x7d, 0xbc, 0xd8, 0x6b, 0x69,
+ 0x65, 0x2c, 0xac, 0x44, 0x4f, 0x8d, 0x38, 0x95, 0x43, 0x5e, 0x19, 0xec,
+ 0x86, 0x63, 0x9d, 0x46, 0x7e, 0x78, 0x4f, 0x82, 0x3d, 0x12, 0x7f, 0xe1,
+ 0x19, 0x91, 0x9f, 0xdf, 0xe0, 0x97, 0xe6, 0xdc, 0x20, 0x2c, 0xbf, 0x8a,
+ 0x25, 0xad, 0x42, 0xcb, 0xd1, 0xa0, 0x2c, 0xbe, 0x28, 0xe8, 0x18, 0x79,
+ 0x1e, 0x2c, 0xbf, 0xf7, 0xf9, 0x9d, 0xf9, 0xcb, 0xfc, 0x59, 0x79, 0x88,
+ 0x0b, 0x36, 0x1b, 0xfa, 0x3a, 0x29, 0x37, 0xbb, 0xdd, 0xcf, 0xac, 0xbf,
+ 0xf1, 0xdb, 0x0f, 0xfe, 0x04, 0xbe, 0xb2, 0xff, 0xfe, 0xd0, 0x79, 0xe7,
+ 0x97, 0x7e, 0x6e, 0xa5, 0x0f, 0x25, 0x96, 0x83, 0x51, 0x37, 0xf3, 0xea,
+ 0x84, 0xc0, 0x30, 0x97, 0xd0, 0xb2, 0xb4, 0xeb, 0x2f, 0xee, 0x41, 0x9f,
+ 0xce, 0xd6, 0x5f, 0xf6, 0x6f, 0x7d, 0x3c, 0x9e, 0x4b, 0x2e, 0x81, 0xf6,
+ 0x7f, 0x5d, 0x09, 0x70, 0xbe, 0xfe, 0x8f, 0x47, 0xa2, 0x75, 0x97, 0xbf,
+ 0x03, 0x59, 0x7f, 0xe6, 0x7e, 0xa5, 0xfe, 0x13, 0x1a, 0xb2, 0xfe, 0xcd,
+ 0xb0, 0xf9, 0xb4, 0xb2, 0xa4, 0x7d, 0xe2, 0x1f, 0xd4, 0x22, 0xbb, 0x21,
+ 0x17, 0x53, 0xa6, 0x03, 0x28, 0x6d, 0xdb, 0x8b, 0x29, 0x65, 0x39, 0x78,
+ 0x60, 0x8d, 0x41, 0xf3, 0x3a, 0x35, 0xff, 0x6b, 0x0e, 0xe5, 0xfe, 0x42,
+ 0xca, 0x1a, 0x7f, 0x5e, 0x8e, 0x8d, 0xc8, 0x2f, 0xd2, 0xf0, 0x63, 0x4b,
+ 0x2f, 0xf4, 0x6f, 0x6d, 0xe4, 0x1e, 0x2c, 0xbf, 0x9b, 0x8f, 0xd4, 0xb1,
+ 0x65, 0xce, 0x7d, 0x1f, 0x1e, 0xd9, 0xb5, 0xfe, 0x68, 0xf9, 0x41, 0xf8,
+ 0xb2, 0xba, 0x47, 0x67, 0xa1, 0x16, 0x46, 0x17, 0xec, 0x09, 0xe3, 0x8b,
+ 0x29, 0x65, 0xd9, 0x36, 0x8d, 0x97, 0x09, 0xef, 0xf9, 0x82, 0x2b, 0xf4,
+ 0x08, 0x53, 0xac, 0xbf, 0xe8, 0x9e, 0x3a, 0xf9, 0x64, 0xeb, 0x2f, 0x6e,
+ 0xb1, 0x8b, 0x2b, 0x11, 0x8b, 0xd9, 0x6b, 0x1f, 0x6e, 0x9d, 0x5f, 0xfc,
+ 0x27, 0x1b, 0x93, 0x30, 0xf0, 0x80, 0xb2, 0xf4, 0x89, 0xd6, 0x5f, 0x3f,
+ 0xf2, 0x75, 0x97, 0x47, 0x4b, 0x2e, 0x28, 0x59, 0x63, 0xc1, 0xf4, 0xf8,
+ 0x6c, 0x88, 0xbe, 0x2f, 0x7f, 0x64, 0xde, 0x81, 0x09, 0x65, 0xff, 0xf3,
+ 0xee, 0x08, 0x51, 0xe7, 0x6f, 0xc7, 0xf8, 0xb2, 0xa0, 0xff, 0xc2, 0x5d,
+ 0x43, 0x4e, 0x39, 0xe1, 0x5c, 0x50, 0xbf, 0xbe, 0xed, 0xb5, 0x8b, 0x2f,
+ 0xfe, 0x2c, 0xdc, 0x9c, 0x3a, 0x96, 0x75, 0xf5, 0x97, 0xf6, 0x9b, 0x99,
+ 0x9a, 0x59, 0x53, 0x2b, 0xc9, 0xd4, 0x65, 0x9e, 0x8f, 0x34, 0x8e, 0x78,
+ 0x45, 0xbd, 0x26, 0xf7, 0xb2, 0x75, 0x96, 0xdb, 0x59, 0x58, 0x6c, 0x5c,
+ 0x76, 0xf4, 0x9f, 0x4b, 0x2f, 0xe0, 0x1d, 0xe5, 0x83, 0x59, 0x60, 0xac,
+ 0xbc, 0xcf, 0x25, 0x97, 0xde, 0x82, 0xfa, 0xca, 0xd8, 0x6f, 0x38, 0x37,
+ 0x6c, 0xe1, 0xf8, 0x6f, 0x4d, 0xbe, 0xcf, 0xe0, 0xd2, 0x5f, 0xf3, 0x91,
+ 0xb8, 0x4f, 0xfe, 0x2c, 0xbe, 0x73, 0x40, 0x62, 0xca, 0x91, 0xfe, 0x78,
+ 0x84, 0x8d, 0xef, 0xa0, 0x8a, 0x16, 0x54, 0xc9, 0xd5, 0xe8, 0x70, 0xa1,
+ 0x3b, 0xf8, 0x52, 0x88, 0x5d, 0x7f, 0x39, 0x8f, 0xf7, 0x35, 0x65, 0xee,
+ 0x1f, 0x4b, 0x2e, 0x6e, 0xd6, 0x50, 0x0d, 0xa7, 0x07, 0x68, 0xd5, 0x54,
+ 0x6d, 0x1e, 0x56, 0x95, 0xbe, 0xc5, 0x7f, 0xff, 0x75, 0x2c, 0xf8, 0xa4,
+ 0x51, 0x83, 0x0f, 0xdb, 0xf1, 0xa5, 0x97, 0xf7, 0xdb, 0x50, 0x11, 0x5a,
+ 0xcb, 0xb4, 0xfe, 0x44, 0xa8, 0x8c, 0x97, 0xbd, 0x93, 0xac, 0xbd, 0x29,
+ 0x42, 0xcb, 0xd9, 0xec, 0xd8, 0x6e, 0x42, 0x3b, 0x4e, 0x89, 0xb2, 0x68,
+ 0xbf, 0xfb, 0xed, 0x3f, 0xf8, 0x1d, 0xcf, 0xbf, 0x96, 0x5f, 0xff, 0x16,
+ 0x7d, 0xb0, 0xbd, 0x9f, 0xf3, 0x76, 0xb2, 0xff, 0xbe, 0xc7, 0xe7, 0xa0,
+ 0x42, 0x59, 0x7f, 0x89, 0xb9, 0xc8, 0xf4, 0x2c, 0xbf, 0xe8, 0x2e, 0xdf,
+ 0xef, 0xd0, 0x36, 0x22, 0xdf, 0xa4, 0xd6, 0x39, 0xbf, 0xe8, 0xce, 0xb2,
+ 0x73, 0x1f, 0xa5, 0x97, 0xfc, 0xe6, 0x6b, 0x1b, 0xd0, 0x35, 0x95, 0xa3,
+ 0xf3, 0x23, 0xba, 0x92, 0x7e, 0x80, 0x8c, 0x03, 0xf0, 0xd3, 0xbf, 0x82,
+ 0x2b, 0x6d, 0x6b, 0x16, 0x5f, 0xff, 0xb3, 0xa9, 0x7d, 0xa7, 0xcd, 0x7f,
+ 0xed, 0xa8, 0x59, 0x7f, 0xbd, 0x86, 0xbc, 0x36, 0xda, 0xcb, 0xfd, 0x9c,
+ 0xcd, 0xcf, 0x40, 0xd6, 0x5d, 0x13, 0xac, 0xbd, 0xe8, 0x99, 0x65, 0xfe,
+ 0x86, 0x2c, 0x9c, 0x49, 0x2c, 0xb7, 0x43, 0x3e, 0x7c, 0x17, 0xf0, 0xed,
+ 0xf9, 0xe6, 0x26, 0x99, 0x65, 0x76, 0x99, 0x77, 0x8d, 0x43, 0x09, 0xcd,
+ 0xe6, 0xb5, 0x89, 0xe5, 0x72, 0x38, 0x4b, 0xef, 0x9b, 0x9e, 0x59, 0x76,
+ 0xa4, 0xb2, 0xff, 0xc5, 0x9f, 0xf8, 0x67, 0xfe, 0x76, 0xb2, 0xfc, 0x30,
+ 0xbe, 0xa4, 0xb2, 0xfe, 0x7e, 0xb9, 0x9d, 0x7d, 0x65, 0xd8, 0x62, 0xca,
+ 0x01, 0xe3, 0x11, 0x7d, 0xf1, 0xf8, 0x21, 0xd6, 0x54, 0x1e, 0x2e, 0x10,
+ 0xdb, 0x8b, 0x2c, 0x62, 0xcb, 0x98, 0x0b, 0x2f, 0x8c, 0x72, 0x92, 0xcb,
+ 0x86, 0xcb, 0x2e, 0xf3, 0x2c, 0xbe, 0x97, 0x3d, 0x8b, 0x2f, 0x98, 0x22,
+ 0xbc, 0x59, 0x6e, 0x6c, 0x45, 0x58, 0xc5, 0xbb, 0x22, 0x98, 0x59, 0xc5,
+ 0x80, 0x45, 0x4c, 0x98, 0xe8, 0x61, 0x7b, 0x4e, 0x9a, 0xb0, 0x23, 0x2e,
+ 0xb8, 0x10, 0xb2, 0xe0, 0x42, 0xcb, 0xf0, 0x65, 0x84, 0x2d, 0x8d, 0x60,
+ 0x05, 0xaf, 0xff, 0xfb, 0xd8, 0x1d, 0x1b, 0xd4, 0xbd, 0x84, 0x6f, 0x8a,
+ 0x33, 0x4b, 0x2a, 0x15, 0xcf, 0x0c, 0x8c, 0xd1, 0x76, 0x40, 0xd4, 0x2c,
+ 0xc1, 0x1b, 0xb1, 0x2a, 0xfc, 0xfa, 0xfe, 0xd0, 0x9f, 0xe4, 0x85, 0x6b,
+ 0x2f, 0xf0, 0x72, 0x68, 0x3c, 0x85, 0x6b, 0x2f, 0xd8, 0x38, 0x94, 0x61,
+ 0xf6, 0x00, 0xd2, 0xff, 0xf1, 0x3f, 0x5c, 0x34, 0xd7, 0xd9, 0xd9, 0xc0,
+ 0xb2, 0xfa, 0x35, 0x1e, 0x59, 0x58, 0x7e, 0x2e, 0xa1, 0x7f, 0xd8, 0xdd,
+ 0x7f, 0x51, 0x9d, 0x2c, 0xbf, 0xfc, 0x4d, 0xd7, 0x26, 0x2c, 0x9f, 0x3a,
+ 0xfa, 0xcb, 0xff, 0x7b, 0x0e, 0x24, 0x03, 0x3a, 0xfa, 0xca, 0xc4, 0x46,
+ 0x7d, 0x32, 0xff, 0x75, 0xdb, 0x68, 0x48, 0x1a, 0xcb, 0xe0, 0x1d, 0xe5,
+ 0xb1, 0x33, 0xd2, 0x20, 0xe4, 0x31, 0x7e, 0x45, 0x70, 0x7e, 0xb2, 0xed,
+ 0xb8, 0x59, 0x7f, 0x00, 0xe2, 0x70, 0x49, 0xd6, 0x5f, 0xdc, 0x62, 0x28,
+ 0xe9, 0x65, 0xd9, 0xd2, 0xca, 0xe8, 0xfd, 0x7e, 0x65, 0xb6, 0x59, 0x7f,
+ 0xf8, 0x48, 0x32, 0x26, 0x93, 0x96, 0x75, 0xf5, 0x97, 0xc0, 0xd3, 0x69,
+ 0x65, 0x42, 0x74, 0x32, 0x5b, 0xc1, 0x77, 0x84, 0x77, 0x0c, 0xcc, 0x4c,
+ 0xbf, 0x8b, 0x3a, 0x03, 0x49, 0x65, 0xfd, 0xce, 0x44, 0xa3, 0x4b, 0x2f,
+ 0xfb, 0x50, 0x76, 0x9a, 0x1f, 0x71, 0x65, 0x61, 0xf4, 0x76, 0x5b, 0x78,
+ 0x3d, 0x7d, 0x65, 0x9d, 0x65, 0xd3, 0x71, 0x65, 0x4e, 0x8f, 0xd2, 0x84,
+ 0xaf, 0x08, 0xbe, 0x3c, 0x20, 0x85, 0xd8, 0x62, 0xcb, 0xfe, 0x09, 0x77,
+ 0xec, 0x9f, 0x8c, 0xb2, 0xff, 0xa3, 0xac, 0x04, 0x6f, 0xc9, 0xd6, 0x5f,
+ 0xc5, 0x9f, 0xe3, 0x81, 0x65, 0x69, 0x17, 0x07, 0x17, 0x01, 0xd7, 0x0e,
+ 0xef, 0xf1, 0x4e, 0xda, 0xeb, 0xd3, 0xac, 0xbf, 0xd3, 0xf3, 0x59, 0xdc,
+ 0x4e, 0xb2, 0xfa, 0x3a, 0xfe, 0xe2, 0xca, 0x83, 0xdc, 0x91, 0xb5, 0xff,
+ 0xef, 0xbe, 0x9c, 0x70, 0x4f, 0xa7, 0x92, 0xcb, 0xfe, 0x15, 0xea, 0x3e,
+ 0xdd, 0xb0, 0xd6, 0x5f, 0xec, 0x29, 0xf0, 0x6f, 0xe5, 0x95, 0x32, 0x35,
+ 0xfe, 0x42, 0x14, 0x73, 0x0f, 0x6f, 0xec, 0x3e, 0x0d, 0x8c, 0x59, 0x71,
+ 0xe1, 0x65, 0xff, 0xa5, 0x06, 0xf5, 0xfd, 0x46, 0x18, 0xb2, 0x8e, 0x88,
+ 0x47, 0x2d, 0xf8, 0xb5, 0xdf, 0xe2, 0xcb, 0xfe, 0x79, 0x6c, 0x1b, 0x6f,
+ 0x81, 0xac, 0xbf, 0x64, 0xde, 0x6f, 0xac, 0xbf, 0xff, 0x13, 0x9b, 0x34,
+ 0x67, 0xe0, 0xf1, 0xe8, 0x02, 0xcb, 0xff, 0xf7, 0xca, 0x37, 0x5b, 0x59,
+ 0xd4, 0xbf, 0x85, 0xda, 0xcb, 0xff, 0xf8, 0x7e, 0x61, 0x40, 0x9f, 0x6e,
+ 0x16, 0x6f, 0x6f, 0x05, 0x65, 0x62, 0x61, 0xac, 0xa8, 0x15, 0x8a, 0x24,
+ 0xd9, 0x39, 0x19, 0xad, 0xf6, 0x67, 0xb8, 0xb2, 0xa1, 0x71, 0x73, 0x23,
+ 0x69, 0x78, 0x61, 0x8a, 0xcb, 0xc8, 0x5f, 0xf1, 0xd0, 0x6e, 0x94, 0xde,
+ 0x30, 0xc3, 0x12, 0x5f, 0xb0, 0xd2, 0x0f, 0x12, 0x0b, 0x34, 0x17, 0x8e,
+ 0xff, 0x59, 0x7c, 0x2c, 0xc3, 0x0c, 0x59, 0x76, 0x01, 0x65, 0x61, 0xbe,
+ 0xf9, 0x45, 0xe8, 0x07, 0x16, 0x54, 0x23, 0x40, 0xe7, 0x5f, 0x5a, 0x10,
+ 0x82, 0xff, 0xf9, 0xa4, 0xfc, 0x39, 0xde, 0x4e, 0x6f, 0x99, 0x65, 0xfd,
+ 0x07, 0x7f, 0x86, 0x16, 0x5f, 0x36, 0x81, 0xc5, 0x97, 0xfe, 0x08, 0xaf,
+ 0x36, 0xcb, 0x0c, 0x70, 0x2c, 0xbf, 0xf4, 0x02, 0x25, 0x1a, 0xd6, 0x18,
+ 0xb2, 0xff, 0xfa, 0x38, 0x3f, 0x31, 0x9e, 0x38, 0x7e, 0x18, 0x59, 0x53,
+ 0xa2, 0x3f, 0xb3, 0xea, 0x84, 0x7c, 0xb4, 0x35, 0x2f, 0xfb, 0x9a, 0x80,
+ 0xfc, 0x9b, 0x7a, 0xcb, 0xff, 0x16, 0x73, 0xbf, 0x37, 0x70, 0x4b, 0x2f,
+ 0xff, 0xf1, 0xa6, 0x3e, 0x8d, 0x17, 0xcc, 0x91, 0x05, 0xf9, 0x84, 0xb2,
+ 0xff, 0xf7, 0xfc, 0xce, 0x0c, 0x2f, 0xfb, 0x24, 0xb2, 0xff, 0xef, 0x36,
+ 0xbc, 0xfa, 0xce, 0xdf, 0xeb, 0x2f, 0x8e, 0x77, 0x96, 0xc4, 0x46, 0x62,
+ 0x45, 0x42, 0x74, 0x78, 0x74, 0xc7, 0xc1, 0x87, 0x85, 0xfd, 0xa0, 0xf7,
+ 0xe6, 0xe2, 0xcb, 0xe3, 0x1c, 0xa4, 0xb2, 0xff, 0xbf, 0x1d, 0x01, 0xfd,
+ 0xe6, 0x59, 0x6f, 0x2c, 0xac, 0x3c, 0xae, 0xce, 0x6f, 0x69, 0xfb, 0x59,
+ 0x7f, 0x4e, 0xdd, 0xfa, 0x3e, 0xb2, 0xfa, 0x27, 0x20, 0xac, 0xad, 0x1e,
+ 0x8f, 0x8b, 0xef, 0xb8, 0xc7, 0x85, 0x97, 0xfe, 0x8c, 0x29, 0xf0, 0x9f,
+ 0xae, 0x2c, 0xbf, 0x16, 0x7e, 0x34, 0xb2, 0xf1, 0x86, 0x18, 0x92, 0xfc,
+ 0xe6, 0xf9, 0xbe, 0x90, 0x59, 0xa0, 0xa8, 0x44, 0x03, 0x23, 0x5f, 0x1f,
+ 0x91, 0xf5, 0x97, 0xb7, 0xc1, 0xd6, 0x5e, 0xfb, 0x18, 0xb2, 0xf7, 0x1f,
+ 0x4b, 0x2b, 0xa3, 0x73, 0xf1, 0xdb, 0xa0, 0x6b, 0x2f, 0xf6, 0xb5, 0x13,
+ 0x8f, 0x09, 0x65, 0x78, 0xf2, 0x5c, 0x5a, 0xa1, 0x30, 0x5c, 0x22, 0x65,
+ 0x77, 0x6b, 0xbe, 0x06, 0x64, 0xcb, 0x2f, 0xb9, 0x85, 0xf5, 0x95, 0x87,
+ 0x86, 0xe4, 0x56, 0xe6, 0xc5, 0x6a, 0x63, 0x22, 0xc6, 0xee, 0x88, 0xa6,
+ 0x21, 0xd4, 0x2f, 0x7d, 0x19, 0x31, 0x3e, 0xde, 0xdb, 0xce, 0x96, 0x5a,
+ 0x43, 0x5c, 0x65, 0xc9, 0x77, 0xed, 0x08, 0x6a, 0x14, 0x2e, 0x6b, 0x86,
+ 0x72, 0x52, 0xfe, 0x83, 0xc7, 0xa0, 0x0b, 0x2f, 0x44, 0xe1, 0x59, 0x61,
+ 0x5e, 0x1e, 0x4f, 0x8b, 0x2f, 0xfe, 0x6f, 0xc6, 0xb0, 0xbe, 0xee, 0x4b,
+ 0x2a, 0x4c, 0x90, 0xd9, 0x8b, 0x35, 0x18, 0xdf, 0xa3, 0xc9, 0x29, 0xd1,
+ 0x70, 0xbd, 0xef, 0x2b, 0xbf, 0xfa, 0x30, 0xb0, 0x6f, 0x22, 0x89, 0xd6,
+ 0x5f, 0x77, 0xa8, 0x92, 0xcb, 0xb7, 0xc2, 0xcb, 0xff, 0x36, 0xbb, 0xf3,
+ 0x77, 0xe6, 0x25, 0x97, 0xff, 0xff, 0x9c, 0x81, 0xff, 0x61, 0xff, 0xcc,
+ 0xdf, 0xe6, 0xef, 0xcc, 0x20, 0x67, 0x59, 0x53, 0xa2, 0xec, 0x07, 0xf5,
+ 0x08, 0xf7, 0xc8, 0x69, 0xdf, 0xf6, 0x6e, 0x41, 0xfa, 0x96, 0x7d, 0x65,
+ 0x63, 0x2e, 0x5d, 0xa9, 0x2b, 0x9a, 0x7e, 0x74, 0x12, 0x8c, 0x6b, 0x84,
+ 0xd7, 0xf7, 0x72, 0xce, 0x7d, 0x96, 0x5e, 0x28, 0xde, 0xb2, 0xff, 0xed,
+ 0x47, 0x7e, 0x27, 0xf9, 0x41, 0x8b, 0x2e, 0x15, 0xb2, 0xca, 0x59, 0x6f,
+ 0x2c, 0xa9, 0x17, 0x8c, 0x17, 0x53, 0x9e, 0xae, 0x8d, 0xaa, 0x11, 0x78,
+ 0xf0, 0x99, 0xbd, 0x33, 0xce, 0xb2, 0xf7, 0x03, 0xb8, 0xb2, 0xb0, 0xdf,
+ 0x7c, 0x7a, 0xff, 0x41, 0x48, 0x9a, 0x3a, 0x59, 0x50, 0xec, 0x78, 0x27,
+ 0x84, 0xd4, 0xa5, 0x11, 0x8e, 0x55, 0x46, 0x4e, 0x75, 0x9b, 0x2c, 0xef,
+ 0xb8, 0xdd, 0x7a, 0x94, 0x2a, 0xc7, 0x93, 0x47, 0xf7, 0xa9, 0x78, 0xe7,
+ 0x87, 0x47, 0xa5, 0xc5, 0xbc, 0x6b, 0x00, 0x8c, 0x20, 0xa7, 0x26, 0x79,
+ 0x1b, 0x5f, 0xe9, 0x7a, 0x81, 0x66, 0xde, 0x5d, 0xb7, 0x0d, 0x91, 0x19,
+ 0x37, 0x48, 0x2f, 0xcd, 0x34, 0x98, 0x96, 0x5d, 0xb5, 0x32, 0xcb, 0xfe,
+ 0x9b, 0xfb, 0xbc, 0x89, 0x83, 0xa5, 0x97, 0xf8, 0x70, 0x47, 0x81, 0xc2,
+ 0xca, 0x83, 0xf0, 0x73, 0xfb, 0xfe, 0xf4, 0x4f, 0xa8, 0x93, 0xe9, 0x65,
+ 0xff, 0xef, 0x47, 0x8b, 0x0d, 0x1e, 0x14, 0x6e, 0x2c, 0xbf, 0x11, 0xa2,
+ 0x40, 0x16, 0x5f, 0xf8, 0x9f, 0xaf, 0xfa, 0x3b, 0xc9, 0x96, 0x5f, 0x98,
+ 0x7e, 0x63, 0x56, 0x5e, 0x11, 0xc9, 0x65, 0x0d, 0x1f, 0x18, 0x96, 0x45,
+ 0x3f, 0x40, 0xdd, 0x28, 0xbf, 0x41, 0x31, 0xf1, 0x65, 0xf1, 0x9f, 0xcd,
+ 0xc5, 0x95, 0x39, 0xe5, 0xf4, 0x4b, 0x7f, 0xfe, 0x27, 0x33, 0x4d, 0x1e,
+ 0x13, 0xed, 0xe8, 0xde, 0xb2, 0xff, 0xcd, 0xe8, 0x1f, 0x83, 0x1d, 0x71,
+ 0x65, 0xe2, 0x2c, 0x59, 0x58, 0x7b, 0x2e, 0x7f, 0x78, 0x66, 0x81, 0x65,
+ 0xf8, 0xfa, 0xd3, 0xfd, 0x65, 0xed, 0x9b, 0xbd, 0xac, 0xbb, 0x3e, 0xb2,
+ 0xa7, 0x37, 0x3e, 0x23, 0xbf, 0xf1, 0xc7, 0x05, 0x9b, 0xcb, 0x38, 0xb2,
+ 0xf7, 0x88, 0xeb, 0x2b, 0x62, 0x3e, 0xe0, 0x7b, 0x18, 0x58, 0x89, 0xcf,
+ 0xaf, 0xfe, 0x99, 0xfb, 0xf4, 0x4b, 0xe5, 0x87, 0x59, 0x7f, 0x6b, 0x08,
+ 0x9e, 0x75, 0x97, 0xfe, 0x12, 0x0f, 0x9a, 0x3b, 0x91, 0xab, 0x2b, 0xb4,
+ 0x58, 0x32, 0x2f, 0xcb, 0x2f, 0xfc, 0x67, 0x52, 0xe6, 0xcc, 0xf6, 0x12,
+ 0xcb, 0xff, 0x4d, 0x1d, 0x73, 0x4d, 0xbf, 0x06, 0xb2, 0xa1, 0x10, 0x98,
+ 0x85, 0x7f, 0xf8, 0xfd, 0x4b, 0x9b, 0x30, 0x8b, 0x18, 0x0b, 0x2f, 0xe7,
+ 0xd0, 0x63, 0xa9, 0x2c, 0xa6, 0x3f, 0x97, 0x4b, 0xbf, 0xfa, 0x06, 0x7c,
+ 0xee, 0x39, 0xec, 0x3a, 0xcb, 0xf3, 0xe0, 0xdb, 0x7a, 0xca, 0xd1, 0xf6,
+ 0x1d, 0x12, 0xf3, 0x78, 0x2b, 0x2f, 0xbe, 0xde, 0x0a, 0xcb, 0xfb, 0x35,
+ 0xd4, 0xbf, 0x0b, 0x2d, 0xb8, 0x2a, 0x8f, 0x40, 0x42, 0x2b, 0xf1, 0x99,
+ 0xdc, 0x01, 0x65, 0xf7, 0x7e, 0xcd, 0x2c, 0xa8, 0x3f, 0xe6, 0x32, 0xdd,
+ 0x29, 0xad, 0x8c, 0x89, 0x6d, 0xac, 0x9e, 0x50, 0x8b, 0x19, 0x06, 0x46,
+ 0x62, 0xd0, 0x96, 0x98, 0x93, 0x50, 0xb0, 0xf4, 0x63, 0x6f, 0x0f, 0x82,
+ 0x85, 0xa7, 0xe1, 0x34, 0x18, 0x46, 0x6f, 0x22, 0xdd, 0x87, 0x55, 0x85,
+ 0xed, 0x73, 0x82, 0xf7, 0x5b, 0x54, 0xa4, 0xe1, 0x4c, 0xa7, 0x9d, 0xa2,
+ 0x52, 0x08, 0xa2, 0x39, 0xdd, 0xa5, 0x29, 0x28, 0x54, 0x94, 0x26, 0x2a,
+ 0xa3, 0x0b, 0xda, 0x71, 0x95, 0x0a, 0xb8, 0x61, 0xc5, 0xae, 0x2d, 0x9e,
+ 0x96, 0x89, 0x2a, 0xd8, 0x9c, 0x76, 0x93, 0x0f, 0x31, 0x07, 0x5e, 0x6c,
+ 0xff, 0x7f, 0x76, 0x8b, 0x4f, 0xaa, 0xe0, 0xc9, 0xab, 0xb2, 0xcd, 0xc9,
+ 0x5b, 0x53, 0x5a, 0x39, 0xed, 0x5a, 0xa4, 0xf3, 0xd7, 0x2a, 0xde, 0xbc,
+ 0x30, 0x47, 0xb7, 0x8a, 0xc0, 0xae, 0x3d, 0x05, 0x72, 0x8e, 0x4a, 0xf0,
+ 0x28, 0x79, 0x8a, 0x4b, 0x4f, 0xde, 0xa5, 0xa8, 0x69, 0x62, 0x7b, 0xe7,
+ 0xf2, 0x4c, 0xa4, 0x51, 0x6d, 0xd6, 0x4f, 0xc2, 0x5b, 0x99, 0x6d, 0xda,
+ 0x52, 0x4d, 0x0b, 0x9c, 0x1c, 0xef, 0x96, 0xe0, 0xcb, 0xbd, 0xe3, 0xe7,
+ 0xd6, 0x5f, 0xe7, 0x3c, 0x7d, 0xb8, 0xcb, 0x2f, 0xd9, 0xa1, 0x3f, 0xc5,
+ 0x97, 0x7a, 0x16, 0x58, 0x58, 0x11, 0x18, 0x43, 0x9c, 0x31, 0x10, 0xa6,
+ 0xfb, 0xb2, 0x8c, 0x59, 0x7e, 0xd7, 0x6e, 0xfd, 0xaa, 0x2e, 0x35, 0x85,
+ 0xc1, 0xeb, 0xe1, 0x0d, 0xfe, 0x17, 0x9a, 0xed, 0xdf, 0xb5, 0x45, 0xd6,
+ 0xbf, 0xf8, 0x5b, 0xc8, 0x5e, 0x6b, 0xb7, 0x7e, 0xd5, 0x12, 0x8a, 0xa2,
+ 0x70, 0xa1, 0x0e, 0x72, 0x99, 0x43, 0x4c, 0x65, 0x46, 0xc3, 0x27, 0xb2,
+ 0x96, 0x9d, 0x90, 0xdc, 0x8c, 0x9d, 0xf7, 0x07, 0x52, 0xc1, 0x0c, 0xce,
+ 0x42, 0x73, 0xe5, 0x1b, 0xa8, 0x77, 0xff, 0x85, 0x9d, 0xe4, 0x2f, 0x35,
+ 0xdb, 0xbf, 0x6a, 0x89, 0x69, 0x7f, 0xc2, 0xaf, 0xcd, 0xb8, 0xf1, 0xd6,
+ 0xea, 0xcb, 0xff, 0xe3, 0x3b, 0xda, 0x85, 0x20, 0x15, 0xeb, 0x68, 0xd9,
+ 0xb3, 0xdb, 0x6b, 0x2f, 0xff, 0xfd, 0xbb, 0xf1, 0x40, 0xce, 0x28, 0x26,
+ 0x15, 0x5f, 0x15, 0xeb, 0x68, 0xd9, 0xb3, 0xdb, 0x6b, 0x2b, 0xc8, 0xfe,
+ 0x31, 0xba, 0xfc, 0x2b, 0x90, 0xa0, 0x49, 0xd6, 0x5e, 0xdc, 0x3b, 0x2c,
+ 0xbf, 0xec, 0x21, 0xfa, 0x34, 0xe4, 0xb2, 0xa0, 0xf5, 0x70, 0x7e, 0xf3,
+ 0xbf, 0x6a, 0x88, 0xdd, 0x7e, 0xea, 0x62, 0x81, 0xac, 0xae, 0xcf, 0x49,
+ 0xca, 0x6f, 0xc3, 0xf4, 0x66, 0x96, 0x56, 0x8f, 0x24, 0x88, 0xaf, 0xf6,
+ 0x98, 0x57, 0xdf, 0xa0, 0xc5, 0x97, 0x83, 0xb6, 0x62, 0xcb, 0xed, 0x06,
+ 0x00, 0xb2, 0x98, 0xff, 0x26, 0x39, 0x10, 0x86, 0xff, 0xff, 0xfb, 0x79,
+ 0x67, 0x38, 0x38, 0xcd, 0x76, 0xef, 0xd8, 0xb9, 0x37, 0xe3, 0xfc, 0x54,
+ 0x61, 0xeb, 0x7a, 0x11, 0x7c, 0xc6, 0x17, 0xf7, 0x05, 0x99, 0xcd, 0xc1,
+ 0x16, 0x5f, 0xdb, 0x8d, 0x3f, 0x9b, 0x6d, 0x65, 0xfb, 0x74, 0x5e, 0x85,
+ 0x66, 0x2c, 0xbe, 0x19, 0x60, 0x16, 0x5f, 0x41, 0x87, 0x1a, 0xcb, 0xee,
+ 0xfd, 0x06, 0x2c, 0xbd, 0xe8, 0x35, 0x65, 0x62, 0x21, 0x74, 0x42, 0x2b,
+ 0x23, 0x10, 0x92, 0xff, 0xcf, 0x21, 0x79, 0xae, 0xdd, 0xfb, 0x54, 0x4b,
+ 0xeb, 0x62, 0xcb, 0xde, 0x7f, 0xac, 0xb7, 0xf8, 0x6b, 0x04, 0x10, 0xbf,
+ 0x89, 0xa0, 0xc0, 0xee, 0x2c, 0xbf, 0x84, 0x6e, 0xb7, 0x74, 0x62, 0xca,
+ 0x84, 0x46, 0x61, 0x43, 0x18, 0x5f, 0xd0, 0xdb, 0x99, 0xd4, 0x96, 0x5f,
+ 0xb4, 0x6f, 0x83, 0xc5, 0x95, 0xe3, 0xda, 0x10, 0xc2, 0xf4, 0x6a, 0x16,
+ 0x56, 0x1b, 0xe6, 0x23, 0xb9, 0xfc, 0xb2, 0xf8, 0x03, 0xe4, 0x2c, 0xbe,
+ 0x7d, 0x4f, 0x3a, 0xcb, 0x61, 0x1e, 0x36, 0xf2, 0x2a, 0x92, 0x21, 0x38,
+ 0xb9, 0x78, 0x10, 0x62, 0xcb, 0xfd, 0x8d, 0xa9, 0x79, 0x8c, 0x59, 0x5b,
+ 0x87, 0xa1, 0xe1, 0xdb, 0xf6, 0xeb, 0xce, 0x24, 0x96, 0x5f, 0x07, 0xcd,
+ 0xa5, 0x97, 0xdc, 0xf4, 0x79, 0x65, 0xfe, 0x89, 0xe0, 0xa7, 0xcd, 0xd5,
+ 0x97, 0x73, 0x4b, 0x2a, 0x0f, 0xbe, 0x72, 0x29, 0x8d, 0xac, 0x2c, 0x55,
+ 0x32, 0x60, 0xe2, 0x34, 0x39, 0xc9, 0x07, 0x08, 0x8c, 0x85, 0xdf, 0x71,
+ 0xad, 0xf4, 0x4e, 0xc6, 0xdb, 0x86, 0x9a, 0x85, 0xc1, 0xd0, 0x7d, 0x18,
+ 0x31, 0x43, 0x17, 0x90, 0xa3, 0xfb, 0x98, 0x49, 0x76, 0xcb, 0x44, 0x84,
+ 0x8d, 0xff, 0xf8, 0xa3, 0xb1, 0x7f, 0xeb, 0xb6, 0xe1, 0x66, 0xf7, 0x59,
+ 0x7f, 0xf4, 0xbe, 0xd3, 0x0b, 0x1b, 0x6f, 0x81, 0xac, 0xbf, 0x18, 0x2d,
+ 0x8d, 0x9d, 0x65, 0xfe, 0x16, 0x07, 0xe8, 0x0d, 0xd2, 0xca, 0x1a, 0x60,
+ 0xfd, 0x2d, 0x32, 0x49, 0x16, 0xdf, 0xb5, 0xdb, 0xbf, 0x6a, 0x8a, 0xad,
+ 0x7e, 0xce, 0x7a, 0x3a, 0x59, 0x61, 0x78, 0x7b, 0xde, 0x36, 0xbe, 0x0e,
+ 0xe8, 0xe1, 0x65, 0xb6, 0xb5, 0x95, 0xe3, 0x77, 0xb6, 0x4b, 0x73, 0x6e,
+ 0xac, 0xbb, 0x34, 0xb2, 0xf6, 0x75, 0xf5, 0x97, 0xcc, 0x77, 0xde, 0xb2,
+ 0x8d, 0x3e, 0xf7, 0x19, 0x00, 0xb7, 0xc7, 0x6f, 0x16, 0xe9, 0x8b, 0x2f,
+ 0xef, 0x46, 0xf0, 0x8f, 0x16, 0x5f, 0xcf, 0xe9, 0x8a, 0x06, 0xb2, 0xff,
+ 0xfb, 0xe0, 0x38, 0x47, 0x99, 0xf0, 0x1c, 0x3d, 0x2c, 0xbf, 0xfb, 0xfe,
+ 0x8e, 0x13, 0x84, 0x56, 0xda, 0x59, 0x7a, 0x25, 0x8b, 0x2f, 0xe6, 0x0f,
+ 0x65, 0x13, 0x2c, 0xa9, 0x26, 0x7c, 0x32, 0xfc, 0x2d, 0xe9, 0x4a, 0x64,
+ 0x7f, 0x0d, 0xdf, 0xf1, 0xb8, 0x59, 0xd7, 0xdc, 0xeb, 0x2d, 0xba, 0xb2,
+ 0xc6, 0x2c, 0xae, 0x8d, 0x37, 0xc5, 0x2f, 0x6e, 0xc7, 0xd6, 0x5f, 0xd0,
+ 0x71, 0x20, 0xbb, 0x59, 0x74, 0x69, 0x65, 0x68, 0xf1, 0x38, 0x5d, 0x73,
+ 0xf4, 0xb2, 0xf0, 0x90, 0x05, 0x95, 0xd1, 0xb4, 0xf8, 0xbd, 0xf4, 0xc4,
+ 0x1e, 0xd6, 0x5f, 0xd8, 0x79, 0x9d, 0xe7, 0x59, 0x7e, 0xe3, 0x79, 0x8d,
+ 0x59, 0x73, 0xf4, 0xb2, 0x88, 0xdf, 0xfc, 0xa2, 0xff, 0xfa, 0x5e, 0x79,
+ 0x1a, 0xfc, 0xc0, 0xf3, 0x8c, 0xb2, 0x96, 0x56, 0x1e, 0xde, 0xea, 0x85,
+ 0x42, 0x66, 0x0c, 0x48, 0xed, 0xa4, 0xf7, 0x70, 0xd9, 0x65, 0xff, 0x14,
+ 0x4b, 0xec, 0x71, 0xc2, 0xcb, 0xf6, 0xbb, 0x77, 0xed, 0x51, 0x20, 0x2f,
+ 0xb5, 0x85, 0xf5, 0x97, 0xc3, 0xda, 0xc5, 0x4d, 0xa1, 0x65, 0x0d, 0x18,
+ 0x18, 0x6f, 0xa3, 0x6e, 0x10, 0xd6, 0xc4, 0xc4, 0x85, 0xc3, 0x5a, 0xfd,
+ 0xc7, 0x27, 0xe9, 0x65, 0xff, 0x7d, 0xb8, 0xc1, 0x15, 0x8e, 0x16, 0x5d,
+ 0x84, 0xb2, 0xe0, 0xc2, 0xca, 0x92, 0x2e, 0xfa, 0x2d, 0x62, 0x7d, 0xc3,
+ 0xcd, 0x0a, 0xdf, 0xd1, 0xa9, 0xe3, 0x53, 0xac, 0xbe, 0x63, 0xc7, 0x16,
+ 0x54, 0x8f, 0x40, 0xd2, 0xfb, 0xfd, 0xa9, 0xcf, 0x05, 0x2e, 0x2c, 0xa8,
+ 0x3d, 0x7c, 0x23, 0xbf, 0xfe, 0x3b, 0x10, 0x04, 0xfb, 0x10, 0x65, 0x9c,
+ 0x59, 0x7f, 0xf3, 0x41, 0xdc, 0x62, 0x6e, 0xc1, 0x49, 0x65, 0xff, 0xff,
+ 0x37, 0xcb, 0x37, 0x96, 0x72, 0x7c, 0x33, 0x6c, 0x3e, 0x6d, 0x2c, 0xac,
+ 0x4c, 0x03, 0xc9, 0xe0, 0x46, 0xbf, 0x01, 0xc0, 0x47, 0x59, 0x7a, 0x77,
+ 0x1a, 0xcb, 0xfd, 0xdb, 0x61, 0x81, 0x2f, 0xac, 0xa8, 0x3f, 0x8c, 0x27,
+ 0xe8, 0x76, 0xfe, 0x10, 0x51, 0xa6, 0x83, 0xac, 0xbb, 0x92, 0x59, 0x4e,
+ 0x79, 0x3c, 0x32, 0xbf, 0xff, 0xa3, 0xbf, 0xb6, 0xb5, 0x80, 0xe7, 0xdf,
+ 0xce, 0x35, 0x97, 0x0a, 0x7c, 0xb2, 0xff, 0xe9, 0xbc, 0xe7, 0xff, 0xa3,
+ 0xe1, 0x3a, 0xcb, 0xff, 0xb0, 0x71, 0x28, 0xc1, 0xc1, 0x7d, 0x65, 0x62,
+ 0x21, 0xce, 0x8d, 0x7b, 0x76, 0x3e, 0xb2, 0xa1, 0x97, 0x57, 0x3c, 0x24,
+ 0xc6, 0x79, 0x91, 0xaf, 0x1a, 0xb3, 0xd2, 0xfe, 0xe1, 0x14, 0xcc, 0x67,
+ 0x56, 0xf4, 0x6a, 0x4f, 0x28, 0x1c, 0xa1, 0xe9, 0xc8, 0xc8, 0x3f, 0x0a,
+ 0x80, 0xbb, 0xef, 0x21, 0xdb, 0x5b, 0x12, 0x14, 0x5b, 0xa4, 0x57, 0xfe,
+ 0x94, 0x60, 0x3d, 0x98, 0x5d, 0xac, 0xbf, 0x41, 0x16, 0x7d, 0x65, 0xf6,
+ 0xb4, 0xdd, 0xac, 0xbe, 0x2c, 0x9c, 0x5e, 0x22, 0x17, 0x6c, 0xf4, 0x42,
+ 0x5b, 0xf8, 0x5f, 0x0d, 0x97, 0xb1, 0x65, 0xfe, 0x17, 0xe7, 0x3e, 0x40,
+ 0xd6, 0x50, 0xb5, 0x4e, 0x7a, 0x8f, 0x08, 0xc4, 0xcd, 0xb3, 0x1b, 0xfc,
+ 0x2f, 0x35, 0xdb, 0xbf, 0x6a, 0x8b, 0x21, 0x7f, 0xff, 0xbc, 0xfa, 0x17,
+ 0xe7, 0xf9, 0x06, 0x7e, 0x61, 0xe3, 0x71, 0x65, 0xfc, 0xdb, 0xc5, 0xf2,
+ 0x3a, 0x59, 0x7f, 0xff, 0x82, 0x3c, 0x16, 0x26, 0x78, 0x82, 0xfb, 0x98,
+ 0x6c, 0x71, 0x65, 0xff, 0xfb, 0xb6, 0xe6, 0x0f, 0x0a, 0x0c, 0xf9, 0xaf,
+ 0xc5, 0x97, 0xfd, 0xe6, 0x70, 0x60, 0x75, 0x3a, 0xcb, 0xf7, 0x82, 0xe6,
+ 0x8b, 0xf2, 0x23, 0xfe, 0xad, 0x68, 0x92, 0x67, 0x03, 0x87, 0xad, 0x71,
+ 0x39, 0x8f, 0xc6, 0xd5, 0x43, 0x54, 0x50, 0xd1, 0xff, 0x5f, 0xe1, 0x79,
+ 0xae, 0xdd, 0xfb, 0x54, 0x5a, 0xeb, 0xf4, 0xdf, 0x1c, 0x12, 0xcb, 0xfc,
+ 0x59, 0x3e, 0xb4, 0xc6, 0x2c, 0xbe, 0xf3, 0x44, 0xcb, 0x2f, 0xd8, 0x24,
+ 0x4e, 0x2f, 0x0f, 0xfb, 0xb2, 0x8d, 0xd3, 0x4b, 0xfc, 0x2f, 0x35, 0xdb,
+ 0xbf, 0x6a, 0x8b, 0x91, 0x7e, 0xd7, 0x6e, 0xfd, 0xaa, 0x2e, 0xc5, 0xff,
+ 0x9e, 0x42, 0xf3, 0x5d, 0xbb, 0xf6, 0xa8, 0xa3, 0x96, 0x17, 0x88, 0x84,
+ 0x39, 0xb5, 0xf1, 0x44, 0x8e, 0xb2, 0xfd, 0x26, 0x20, 0x32, 0xcb, 0xff,
+ 0x0a, 0x05, 0x27, 0x8d, 0x4b, 0x1b, 0x7a, 0xcb, 0x49, 0x65, 0xfb, 0x5d,
+ 0xbb, 0xf6, 0xa8, 0xa5, 0x57, 0xfd, 0xdf, 0x9a, 0x6f, 0x44, 0xf8, 0xb2,
+ 0xff, 0xf7, 0xa2, 0x78, 0xf3, 0x6f, 0x71, 0xf9, 0x96, 0x0b, 0x37, 0x77,
+ 0x48, 0x5e, 0x23, 0x3a, 0x67, 0x1a, 0xe9, 0x31, 0x07, 0x86, 0xfd, 0xff,
+ 0x9d, 0xbf, 0x20, 0x8d, 0xc8, 0x0b, 0x2e, 0xf0, 0x56, 0x58, 0x58, 0xd5,
+ 0x0e, 0x61, 0x0f, 0x44, 0xc7, 0x8d, 0x63, 0xc5, 0x3c, 0x3d, 0xbf, 0xff,
+ 0xf9, 0xff, 0x80, 0x89, 0x0b, 0x10, 0xf8, 0x38, 0x94, 0x0d, 0xdc, 0xd5,
+ 0x95, 0x3b, 0xa3, 0x18, 0x95, 0x27, 0x7f, 0x25, 0x21, 0x75, 0x09, 0xb6,
+ 0xa7, 0x41, 0x1d, 0x2d, 0xe5, 0x35, 0x80, 0xa8, 0xa1, 0x83, 0xc5, 0x2f,
+ 0xc3, 0x1f, 0x7c, 0xa4, 0x63, 0x19, 0xef, 0xfa, 0x42, 0xf3, 0x5d, 0xbb,
+ 0xf6, 0xa8, 0x8e, 0x17, 0xfc, 0xc2, 0xf3, 0x5d, 0xbb, 0xf6, 0xa8, 0xad,
+ 0x56, 0x16, 0xe8, 0x91, 0xfa, 0x4d, 0xff, 0xe1, 0x67, 0x79, 0x0b, 0xcd,
+ 0x76, 0xef, 0xda, 0xa2, 0x5b, 0x5b, 0xb5, 0x97, 0x83, 0xa0, 0x2c, 0xbb,
+ 0x3a, 0x59, 0x7e, 0x39, 0xe1, 0xb8, 0xb2, 0xfe, 0x8d, 0x01, 0xfa, 0xe2,
+ 0xcb, 0x0f, 0x0f, 0x57, 0xc4, 0xf7, 0xef, 0xc7, 0x84, 0xe2, 0xcb, 0xdb,
+ 0xc3, 0x25, 0x94, 0x29, 0x4c, 0x2b, 0xb1, 0x2e, 0x87, 0x59, 0xb0, 0x89,
+ 0xf7, 0x94, 0xdc, 0x39, 0x2c, 0xbf, 0xfe, 0xc3, 0x32, 0x7f, 0xff, 0x0c,
+ 0x7f, 0xb9, 0xab, 0x2b, 0xc7, 0xd2, 0x42, 0xf7, 0xe6, 0xdd, 0x1c, 0x74,
+ 0xb2, 0xff, 0xb3, 0xa2, 0xc0, 0x01, 0xe4, 0xb2, 0xe3, 0xf6, 0xb2, 0xfe,
+ 0x6e, 0xb8, 0x3c, 0x25, 0x97, 0xf7, 0x59, 0x28, 0xd0, 0x16, 0x56, 0x1e,
+ 0xdb, 0x96, 0xdf, 0xff, 0x41, 0x4f, 0xc0, 0xbb, 0x4b, 0x9e, 0x79, 0x2c,
+ 0xa8, 0x4c, 0x6a, 0x47, 0x1a, 0x73, 0xf1, 0x05, 0xe7, 0xf0, 0x8b, 0x2f,
+ 0x8a, 0x3a, 0x92, 0xcb, 0xff, 0x31, 0x7f, 0x83, 0x0b, 0xea, 0x4b, 0x2f,
+ 0xe9, 0xe3, 0xb7, 0xd0, 0x16, 0x5f, 0xfb, 0x5e, 0x7c, 0x20, 0xcb, 0x38,
+ 0xb2, 0xff, 0xfb, 0xa0, 0x0f, 0xcf, 0x2c, 0xe1, 0x05, 0xc4, 0x59, 0x4c,
+ 0x88, 0xe7, 0x3d, 0xbe, 0x06, 0x6a, 0x65, 0x97, 0xe6, 0xf4, 0x09, 0x32,
+ 0xcb, 0xdf, 0x83, 0xac, 0xa1, 0xa7, 0x87, 0xd8, 0xec, 0xc4, 0x5a, 0x3e,
+ 0xf4, 0x2f, 0x40, 0x43, 0xf2, 0x3d, 0xd2, 0x9b, 0xff, 0x8d, 0x82, 0xfe,
+ 0x69, 0xa7, 0x73, 0xac, 0xbe, 0x79, 0x1a, 0xcb, 0x2c, 0x6a, 0xcf, 0x1a,
+ 0x2b, 0xf9, 0xb4, 0x4d, 0xfe, 0x2c, 0xbf, 0x69, 0xcb, 0x21, 0x65, 0x2a,
+ 0x21, 0xb3, 0x1f, 0x9f, 0x88, 0x9c, 0xb2, 0xe8, 0x25, 0x97, 0xb1, 0x86,
+ 0xb2, 0xf0, 0xf0, 0xeb, 0x2e, 0x62, 0x19, 0xb7, 0x61, 0xba, 0x83, 0xf6,
+ 0x92, 0x65, 0xf7, 0x03, 0x07, 0x59, 0x7e, 0xf3, 0x6a, 0x06, 0xb2, 0xff,
+ 0xcf, 0x38, 0x85, 0x9c, 0x20, 0xf9, 0x65, 0x76, 0x7c, 0xce, 0x4f, 0x7d,
+ 0x93, 0x4b, 0x16, 0x5c, 0xf2, 0x59, 0x7f, 0xd2, 0x17, 0x9a, 0xed, 0xdf,
+ 0xb5, 0x44, 0xc0, 0xa8, 0x3d, 0xf7, 0x16, 0xbf, 0x05, 0xfe, 0xdf, 0x59,
+ 0x7f, 0xa7, 0x7f, 0x80, 0x42, 0x92, 0xcb, 0x42, 0xcb, 0xa7, 0x65, 0x95,
+ 0x86, 0x9c, 0x84, 0x2e, 0xe4, 0x2c, 0xa8, 0x45, 0xc3, 0x13, 0xba, 0xe0,
+ 0x47, 0xef, 0x18, 0xc0, 0x59, 0x76, 0xde, 0x2c, 0xbe, 0xe3, 0x90, 0x16,
+ 0x5e, 0x28, 0x9d, 0x65, 0x4c, 0x7e, 0x7e, 0x1d, 0x00, 0xc8, 0xac, 0x86,
+ 0xff, 0x07, 0xad, 0x34, 0x1f, 0x16, 0x5f, 0xbc, 0xd0, 0x53, 0xac, 0xbf,
+ 0xe8, 0x9f, 0xe5, 0x01, 0xff, 0x16, 0x57, 0x91, 0x27, 0xc3, 0x3d, 0xb2,
+ 0x7b, 0xe2, 0xce, 0x42, 0xca, 0xf9, 0xe9, 0xef, 0x33, 0xbd, 0x26, 0x02,
+ 0xcb, 0xf1, 0x16, 0x7d, 0x96, 0x5f, 0x75, 0xdb, 0x1a, 0xb2, 0xfc, 0xe6,
+ 0xe7, 0x9d, 0x65, 0x62, 0x2c, 0x66, 0x24, 0x71, 0xcf, 0x92, 0x84, 0x96,
+ 0xff, 0xf4, 0xbd, 0x84, 0x60, 0x9a, 0xf3, 0x41, 0xd6, 0x5f, 0xcd, 0xfc,
+ 0x3c, 0x79, 0x65, 0xff, 0x30, 0x27, 0xf4, 0x70, 0x3c, 0x59, 0x7f, 0xa4,
+ 0xff, 0xe3, 0x14, 0x2c, 0xb4, 0x68, 0xfa, 0xc8, 0xea, 0xba, 0x4c, 0x23,
+ 0x49, 0x7f, 0x84, 0xbd, 0xff, 0xe2, 0x73, 0x33, 0xbf, 0x47, 0x52, 0xdb,
+ 0xc5, 0x97, 0xf3, 0x4d, 0xcf, 0xb4, 0xeb, 0x2f, 0xfd, 0x87, 0xcd, 0x67,
+ 0x52, 0xcf, 0xac, 0xbf, 0x9b, 0xcc, 0x7c, 0x35, 0x65, 0x78, 0xfa, 0xf8,
+ 0x7d, 0x7f, 0xcf, 0xed, 0x43, 0x49, 0xf8, 0xb2, 0xff, 0xf3, 0xcf, 0xe6,
+ 0x82, 0xc9, 0x9b, 0x4c, 0xb2, 0xb1, 0x3c, 0x09, 0x8d, 0xfc, 0x9d, 0xf8,
+ 0x4d, 0x04, 0x88, 0xc3, 0x7b, 0x12, 0xcb, 0x6d, 0xac, 0xbe, 0xed, 0xb0,
+ 0x6b, 0x29, 0x65, 0xbb, 0x59, 0x84, 0xbb, 0x82, 0x04, 0x97, 0x48, 0x6b,
+ 0x2b, 0x6b, 0x44, 0xf4, 0xe2, 0x1d, 0x0a, 0x31, 0x6e, 0x87, 0xce, 0x2f,
+ 0x7e, 0x36, 0x25, 0x83, 0x59, 0x7d, 0x9f, 0xf6, 0x2c, 0xb9, 0xcd, 0x59,
+ 0x76, 0x0c, 0x8d, 0xc6, 0xd9, 0x0d, 0xc2, 0x8e, 0xd7, 0x18, 0x52, 0xef,
+ 0x81, 0x65, 0xdb, 0xb2, 0x59, 0x7c, 0x6e, 0x75, 0xf5, 0x95, 0x39, 0xea,
+ 0xe8, 0x5d, 0xc6, 0xaf, 0xc2, 0x6d, 0xb9, 0x01, 0x65, 0xfd, 0x9e, 0x71,
+ 0x0b, 0xeb, 0x2a, 0x73, 0xd8, 0x19, 0x5d, 0xe7, 0x7e, 0xd6, 0x5f, 0xd9,
+ 0xff, 0xc6, 0xb8, 0xb2, 0xfe, 0x72, 0x04, 0xe0, 0xfa, 0xca, 0x84, 0x4d,
+ 0x4e, 0x46, 0x43, 0x9b, 0x65, 0xb6, 0x17, 0x0d, 0x8d, 0xc4, 0xf0, 0xc7,
+ 0x91, 0x08, 0xe3, 0x45, 0xc9, 0x40, 0x06, 0xbe, 0x77, 0x0d, 0x9e, 0xa1,
+ 0x6e, 0xc4, 0x33, 0x42, 0x23, 0x44, 0x47, 0x84, 0x0f, 0xa1, 0xb0, 0xf0,
+ 0xad, 0x28, 0xf6, 0x39, 0x2c, 0x47, 0xf0, 0xfc, 0x0a, 0xee, 0xf6, 0x03,
+ 0x0b, 0xb6, 0xdf, 0x84, 0x8c, 0x86, 0xf1, 0xc3, 0xa4, 0x97, 0xfe, 0x79,
+ 0x0b, 0xcd, 0x76, 0xef, 0xda, 0xa2, 0x63, 0x5d, 0x1b, 0xab, 0x2e, 0xd6,
+ 0x2c, 0xb4, 0x68, 0xd7, 0xf8, 0x66, 0xfc, 0x27, 0xe5, 0x06, 0xac, 0xb0,
+ 0xb6, 0x47, 0x51, 0xc7, 0x7c, 0xfb, 0xc2, 0x6b, 0xfe, 0x1b, 0x6f, 0x17,
+ 0xd0, 0x04, 0x92, 0xcb, 0xc6, 0x18, 0x62, 0xcb, 0xf8, 0x53, 0xb5, 0x8a,
+ 0x92, 0x97, 0x96, 0x5e, 0xda, 0x52, 0x1a, 0xca, 0xda, 0xcf, 0x83, 0x69,
+ 0x9e, 0xdf, 0xda, 0xd0, 0x4b, 0x3c, 0xb2, 0xfa, 0x09, 0xbc, 0xb2, 0xfa,
+ 0x27, 0x8d, 0x2c, 0xbf, 0xdc, 0x80, 0x3f, 0xdc, 0xd5, 0x97, 0xbf, 0x13,
+ 0x2c, 0xbe, 0x89, 0x98, 0xeb, 0x2f, 0xff, 0x31, 0x16, 0x07, 0xb2, 0xc9,
+ 0xc4, 0x92, 0xca, 0xc3, 0xec, 0xd1, 0x15, 0xf7, 0x23, 0x50, 0xb2, 0xfa,
+ 0x70, 0x8f, 0x71, 0x65, 0xff, 0x6e, 0xb0, 0x36, 0x64, 0xd0, 0x75, 0x94,
+ 0x34, 0xe9, 0x58, 0x83, 0x70, 0x8a, 0x63, 0x3d, 0x42, 0x27, 0xe4, 0x22,
+ 0x10, 0xee, 0x93, 0xda, 0x4b, 0x2f, 0xc7, 0x8c, 0xff, 0x16, 0x5f, 0xb8,
+ 0xc5, 0xd4, 0x96, 0x5d, 0x93, 0x2c, 0xb1, 0x9b, 0x0d, 0xfe, 0x14, 0x56,
+ 0xd0, 0x8a, 0x01, 0x88, 0xe3, 0x35, 0xfe, 0xf4, 0x6a, 0x71, 0x02, 0x05,
+ 0x97, 0xc1, 0x9d, 0xc9, 0x65, 0xff, 0xff, 0x98, 0x3d, 0xeb, 0x37, 0xc1,
+ 0x7f, 0x41, 0x9f, 0xd1, 0xfe, 0x32, 0xcb, 0x9f, 0x8b, 0x2f, 0xb6, 0x7f,
+ 0x3c, 0xb2, 0xbc, 0x6e, 0xb8, 0x2d, 0x7f, 0xff, 0x37, 0x5f, 0xe4, 0xfa,
+ 0xce, 0x6c, 0xce, 0xfc, 0x1d, 0xc5, 0x95, 0x08, 0x85, 0xd1, 0x0d, 0xe8,
+ 0x29, 0xd6, 0x5f, 0xff, 0xff, 0x4b, 0x9e, 0xc0, 0x99, 0xcf, 0x67, 0x79,
+ 0xcd, 0x99, 0xd4, 0xb8, 0xc4, 0xcb, 0x2f, 0x3b, 0xf6, 0xa8, 0xac, 0x57,
+ 0xce, 0x24, 0x1a, 0xb2, 0xbb, 0x3c, 0xcd, 0x14, 0xdf, 0xbc, 0xc7, 0x8d,
+ 0x2c, 0xbf, 0xfc, 0x17, 0x9f, 0x58, 0x7f, 0x44, 0xe4, 0x15, 0x94, 0xc7,
+ 0xe4, 0x44, 0xf7, 0xf8, 0x32, 0xce, 0x03, 0xa0, 0x2c, 0xbf, 0xf6, 0xde,
+ 0x7c, 0xb0, 0x30, 0x5f, 0x59, 0x7f, 0x8b, 0x38, 0x0c, 0xc1, 0xac, 0xa1,
+ 0xab, 0x93, 0x36, 0x32, 0xee, 0xc8, 0xba, 0x1c, 0xd4, 0x33, 0x7d, 0x09,
+ 0x52, 0x20, 0xf9, 0xae, 0xf3, 0xfb, 0xff, 0x07, 0xfc, 0x2c, 0xde, 0x59,
+ 0xc5, 0x97, 0xdf, 0x2c, 0xdd, 0x59, 0x79, 0x82, 0x35, 0x94, 0x69, 0xff,
+ 0xb1, 0xfe, 0xe1, 0x25, 0xff, 0xc5, 0xf3, 0x43, 0x05, 0x9d, 0xc6, 0x96,
+ 0x5f, 0xd0, 0xc2, 0xb7, 0x0f, 0x6b, 0x2f, 0xf6, 0xa7, 0xff, 0x1f, 0xae,
+ 0xd6, 0x54, 0x22, 0xb3, 0xc8, 0x8e, 0x63, 0x7f, 0xb3, 0xf8, 0x50, 0x66,
+ 0xda, 0xcb, 0xfd, 0x1a, 0x93, 0x4c, 0xc6, 0x2c, 0xbf, 0xf9, 0x8f, 0xcd,
+ 0x9e, 0x6f, 0x94, 0x1d, 0x65, 0x49, 0x15, 0xdc, 0x35, 0xf9, 0xa5, 0xf3,
+ 0xfd, 0xfb, 0x59, 0x7f, 0xd1, 0xbd, 0xf5, 0xdf, 0x9f, 0x75, 0x65, 0xfe,
+ 0x68, 0xec, 0xb1, 0xa7, 0x59, 0x47, 0x44, 0x97, 0x88, 0xb7, 0x4f, 0xaf,
+ 0xf4, 0x17, 0xfd, 0x80, 0x75, 0x97, 0xd0, 0x77, 0xfa, 0xca, 0x91, 0xe9,
+ 0x70, 0xc6, 0xfd, 0xbb, 0xfc, 0xea, 0x65, 0x97, 0xdc, 0x99, 0x8d, 0x59,
+ 0x78, 0xf1, 0xa5, 0x97, 0xff, 0xff, 0xf9, 0xff, 0xfc, 0xf7, 0x1e, 0x4c,
+ 0x5f, 0x96, 0x6b, 0x39, 0x9e, 0x79, 0xca, 0x24, 0xb2, 0xf7, 0xe2, 0x65,
+ 0x95, 0x09, 0x8a, 0xe1, 0x68, 0x09, 0x38, 0x38, 0x24, 0x22, 0xef, 0xe0,
+ 0xed, 0xf7, 0xe6, 0x15, 0xac, 0xbe, 0xea, 0x51, 0xe5, 0x97, 0xfb, 0x83,
+ 0xf6, 0x76, 0x1d, 0xc5, 0x96, 0xce, 0x1e, 0xd8, 0x48, 0xee, 0x8d, 0xeb,
+ 0x2b, 0xc6, 0xfc, 0x89, 0xef, 0xef, 0x30, 0xcb, 0x02, 0xb2, 0xff, 0x4c,
+ 0xf8, 0xd2, 0x10, 0xeb, 0x28, 0x68, 0x80, 0xec, 0x81, 0x8b, 0x2f, 0xf7,
+ 0x52, 0x9a, 0x4f, 0xa9, 0xd6, 0x5f, 0x4b, 0xed, 0x3a, 0xca, 0x83, 0xda,
+ 0x73, 0x7b, 0xff, 0xfd, 0x07, 0x34, 0xd7, 0xeb, 0xd0, 0xdf, 0xe3, 0x17,
+ 0x52, 0x59, 0x7f, 0xfe, 0x6f, 0xc7, 0x6d, 0xf6, 0x3e, 0xce, 0x38, 0xc6,
+ 0xb2, 0xa1, 0x55, 0xa6, 0x46, 0xa0, 0xd0, 0x8a, 0xf1, 0x03, 0xb1, 0xdd,
+ 0x2f, 0xac, 0xbf, 0xa0, 0x07, 0x8e, 0x12, 0xcb, 0xfb, 0x27, 0xc2, 0xc9,
+ 0x2c, 0xa8, 0x3e, 0xf6, 0x17, 0xd1, 0x65, 0xff, 0xdc, 0xf6, 0x6e, 0xb7,
+ 0xda, 0x5c, 0x0a, 0xcb, 0xf8, 0xff, 0x0b, 0xcf, 0x0b, 0x2c, 0xdd, 0x1f,
+ 0xa8, 0x88, 0xf7, 0x83, 0xd6, 0x2c, 0xbf, 0xda, 0x60, 0xce, 0x0e, 0x49,
+ 0x65, 0xe6, 0x89, 0xd6, 0x5f, 0xfc, 0x38, 0xe4, 0x37, 0x5f, 0xfc, 0x1d,
+ 0x65, 0xfd, 0x06, 0x4c, 0x50, 0x35, 0x95, 0x3a, 0x38, 0x06, 0x3b, 0x31,
+ 0xae, 0x87, 0x3e, 0x89, 0x7e, 0xef, 0xd0, 0x46, 0xac, 0xac, 0x3f, 0x57,
+ 0x4c, 0xbe, 0x3b, 0xf5, 0xf5, 0x97, 0xff, 0x4f, 0x1f, 0xd8, 0x27, 0x62,
+ 0x6e, 0x89, 0xc5, 0x97, 0xff, 0x3e, 0xe6, 0x13, 0x8d, 0xf3, 0xaf, 0xac,
+ 0xbf, 0xed, 0x47, 0x1f, 0x45, 0x12, 0x59, 0x5a, 0x46, 0x67, 0x94, 0x37,
+ 0xa2, 0xde, 0x93, 0xce, 0xb2, 0xf6, 0xc9, 0xce, 0xb2, 0xff, 0x9f, 0xa9,
+ 0x37, 0xbc, 0xfb, 0x8b, 0x2f, 0xe2, 0x89, 0xca, 0x27, 0x59, 0x6f, 0xac,
+ 0xbf, 0xf1, 0xbc, 0xe6, 0x79, 0xb8, 0x19, 0xd6, 0x50, 0xcf, 0x48, 0x22,
+ 0x34, 0x28, 0x54, 0x77, 0x90, 0xef, 0xe8, 0xc9, 0x87, 0x74, 0x40, 0xe7,
+ 0x84, 0xff, 0x7d, 0x13, 0x44, 0xeb, 0x2f, 0xfc, 0x4e, 0x3f, 0x46, 0xff,
+ 0x39, 0x2c, 0xbf, 0xfd, 0x2c, 0x2f, 0x87, 0xcd, 0xbb, 0xbb, 0x1b, 0x8b,
+ 0x2f, 0xff, 0xff, 0x61, 0xf3, 0x40, 0x00, 0x79, 0xe6, 0xfc, 0xb3, 0xce,
+ 0x06, 0x1c, 0x2c, 0xba, 0x37, 0x16, 0x5f, 0xff, 0xf8, 0x33, 0xe7, 0x7b,
+ 0x08, 0x3b, 0xbb, 0x33, 0xa9, 0x60, 0x48, 0x1c, 0x59, 0x7f, 0xfa, 0x7c,
+ 0xeb, 0xfc, 0x62, 0x80, 0x39, 0xd6, 0x5f, 0xee, 0x8b, 0x07, 0xe7, 0x31,
+ 0x65, 0x61, 0xff, 0x3a, 0x55, 0x4e, 0xa9, 0x58, 0x64, 0x7d, 0x1f, 0x79,
+ 0x49, 0xdd, 0x88, 0x67, 0x90, 0xf4, 0xbe, 0xfc, 0xa1, 0x96, 0x5f, 0xf6,
+ 0x0e, 0x7c, 0x33, 0x3c, 0xeb, 0x2f, 0xe9, 0xe6, 0x90, 0xa3, 0x53, 0xac,
+ 0xbe, 0x22, 0xcf, 0xac, 0xbf, 0x36, 0xe6, 0xb4, 0xcb, 0x2b, 0x6b, 0x44,
+ 0x04, 0x1b, 0x78, 0x82, 0xfe, 0x9c, 0x4d, 0xb7, 0x20, 0x2c, 0xbe, 0xdc,
+ 0x8e, 0x12, 0xcb, 0xff, 0x79, 0xcf, 0xff, 0x47, 0xc2, 0x75, 0x95, 0x87,
+ 0xc7, 0x31, 0x25, 0xff, 0xd9, 0x86, 0x9e, 0x1b, 0x5a, 0x63, 0x16, 0x5e,
+ 0x77, 0xd2, 0xcb, 0xfe, 0x69, 0x37, 0x82, 0x73, 0xb2, 0xcb, 0xb3, 0xeb,
+ 0x2a, 0x13, 0x64, 0xc8, 0x4a, 0xe8, 0x8b, 0xc8, 0x9f, 0x1b, 0xdb, 0x38,
+ 0xb9, 0xf7, 0x56, 0x5f, 0xfe, 0x8d, 0xc3, 0xc0, 0xcb, 0x3f, 0xf7, 0x25,
+ 0x94, 0x47, 0xc7, 0xba, 0x33, 0x7b, 0xcc, 0x2f, 0x68, 0x6e, 0xf2, 0xf6,
+ 0x94, 0x20, 0x05, 0x51, 0x6c, 0x47, 0xa5, 0x3c, 0x63, 0xd2, 0x34, 0x19,
+ 0xb6, 0x4b, 0xb5, 0x36, 0x31, 0x3e, 0xe1, 0xbd, 0xd4, 0x37, 0x1a, 0x18,
+ 0x53, 0x42, 0x17, 0x51, 0x9b, 0xfa, 0x58, 0x1b, 0xc3, 0x08, 0x10, 0xa2,
+ 0x28, 0xdf, 0xb9, 0x29, 0x6f, 0xf2, 0xb0, 0x82, 0xd7, 0xbc, 0x87, 0x6e,
+ 0x17, 0x22, 0x47, 0x31, 0xbb, 0x0c, 0x1b, 0xc2, 0xaf, 0x6f, 0x6b, 0x59,
+ 0x7d, 0xfd, 0xbc, 0xf2, 0xcb, 0x12, 0xca, 0x14, 0x9b, 0x59, 0x12, 0xdc,
+ 0x28, 0x15, 0x16, 0x5e, 0xda, 0xf6, 0x96, 0xda, 0xcb, 0xdf, 0x8f, 0x2c,
+ 0xbe, 0x81, 0xe1, 0xd6, 0x5b, 0x50, 0x6f, 0x74, 0x39, 0x6d, 0xc5, 0x97,
+ 0x36, 0xea, 0xcb, 0xe9, 0xf5, 0x13, 0xac, 0xb8, 0x40, 0x2c, 0xbb, 0x3c,
+ 0xb2, 0xf7, 0xb2, 0x65, 0x97, 0xbc, 0xc7, 0x59, 0x69, 0x96, 0x54, 0xe7,
+ 0xc2, 0x31, 0x67, 0x1d, 0x08, 0xe5, 0xf9, 0xca, 0x70, 0xf1, 0x65, 0xfb,
+ 0x07, 0xa7, 0xed, 0x65, 0xf3, 0xcf, 0x1a, 0x59, 0x74, 0x0f, 0xc7, 0x94,
+ 0x45, 0x16, 0x1a, 0xca, 0x64, 0xf6, 0xe6, 0x26, 0x38, 0xa3, 0x8c, 0x80,
+ 0x90, 0x9e, 0x78, 0x79, 0xf7, 0x2d, 0xb2, 0xcb, 0x79, 0x65, 0xee, 0x09,
+ 0xc5, 0x97, 0xdd, 0x4f, 0x06, 0xac, 0xa9, 0xcf, 0x50, 0x62, 0x21, 0x1e,
+ 0xbf, 0x75, 0x2f, 0xbf, 0x4b, 0x2d, 0x0b, 0x29, 0xcd, 0xd7, 0xca, 0xaf,
+ 0xf7, 0x5a, 0x86, 0x93, 0xf1, 0x65, 0xf6, 0x14, 0x49, 0x65, 0x61, 0xe9,
+ 0x9c, 0xce, 0xdb, 0x6b, 0x2f, 0xdc, 0xcf, 0xb6, 0x96, 0x5e, 0xce, 0xbe,
+ 0xb2, 0xd8, 0x03, 0xc4, 0xe1, 0x3d, 0xce, 0x35, 0x97, 0xbf, 0x9c, 0x59,
+ 0x71, 0x42, 0xca, 0x91, 0xe3, 0x84, 0x5b, 0x78, 0xe5, 0xff, 0x30, 0x67,
+ 0x8e, 0x81, 0xa8, 0x59, 0x7a, 0x51, 0xd2, 0xcb, 0x6e, 0x2c, 0xa9, 0x8d,
+ 0x89, 0x0e, 0xde, 0xd3, 0x92, 0xca, 0x59, 0x6d, 0xb5, 0x97, 0xf1, 0x66,
+ 0xfd, 0x37, 0x16, 0x54, 0xe7, 0x84, 0x60, 0xa5, 0xba, 0x59, 0x50, 0x89,
+ 0xec, 0x1b, 0x64, 0xd0, 0x92, 0x5f, 0xb3, 0x52, 0x83, 0xac, 0xbe, 0xf3,
+ 0xe6, 0x96, 0x5f, 0xa7, 0xc2, 0x63, 0x56, 0x54, 0x1e, 0x4b, 0x10, 0xdf,
+ 0xe7, 0xd4, 0x80, 0xdd, 0x71, 0x65, 0xf7, 0x39, 0x00, 0x59, 0x50, 0xad,
+ 0x88, 0x64, 0x38, 0xb0, 0xcd, 0xda, 0x31, 0x3b, 0x5f, 0xa1, 0x7e, 0xe7,
+ 0x44, 0xe0, 0x12, 0x03, 0x0d, 0x2f, 0xfd, 0x85, 0x86, 0x96, 0x7f, 0xcc,
+ 0xb2, 0xfe, 0x73, 0x70, 0x6f, 0x25, 0x95, 0xe3, 0xe9, 0x23, 0xcb, 0xf9,
+ 0x88, 0xb3, 0x7b, 0xac, 0xbd, 0x21, 0x3e, 0xb2, 0xf6, 0xb4, 0xeb, 0x2f,
+ 0xa4, 0x00, 0xc9, 0x65, 0xf6, 0x84, 0x80, 0x2c, 0xbd, 0x1e, 0x85, 0x95,
+ 0x07, 0xc2, 0xc4, 0x7e, 0x23, 0xbf, 0xcd, 0x3b, 0x9c, 0x00, 0x85, 0x97,
+ 0x30, 0xd6, 0x5c, 0xfd, 0x2c, 0xbf, 0xbd, 0x93, 0x14, 0x0d, 0x65, 0xff,
+ 0x4a, 0x0f, 0xcc, 0xd4, 0x71, 0x65, 0x76, 0x7c, 0xbd, 0x16, 0xdf, 0x8d,
+ 0x98, 0x9c, 0xc5, 0x94, 0x34, 0x65, 0x33, 0xe3, 0x92, 0x5e, 0xfb, 0x01,
+ 0x65, 0xf0, 0x20, 0xbb, 0x59, 0x61, 0x5a, 0xca, 0x34, 0xf4, 0xfa, 0x1c,
+ 0x09, 0x15, 0xf4, 0xbf, 0x82, 0x2c, 0xbd, 0xdc, 0x01, 0x65, 0xed, 0x41,
+ 0xd6, 0x53, 0x22, 0x35, 0xcc, 0x42, 0x46, 0x60, 0xed, 0xfb, 0x3a, 0xfb,
+ 0x9d, 0x65, 0xd9, 0x32, 0xcb, 0x4e, 0x46, 0xfc, 0x42, 0x8b, 0xd1, 0xa9,
+ 0xd6, 0x54, 0x1e, 0x2b, 0x14, 0x52, 0xcb, 0xdd, 0xc0, 0x16, 0x58, 0xa4,
+ 0x6a, 0x30, 0x2e, 0xfe, 0xf3, 0x1f, 0x3c, 0xeb, 0x2a, 0x0f, 0x44, 0x24,
+ 0xb7, 0xd1, 0x28, 0x3a, 0xcb, 0xc4, 0xdb, 0xab, 0x28, 0x56, 0x6f, 0xfe,
+ 0x43, 0x70, 0x78, 0xb2, 0xfc, 0x19, 0x73, 0xc3, 0x59, 0x50, 0x78, 0x04,
+ 0x2f, 0x7e, 0xc9, 0xa4, 0xfc, 0x59, 0x52, 0x5d, 0x9c, 0x19, 0x0f, 0x45,
+ 0x8c, 0x3d, 0x33, 0xee, 0x8b, 0x4e, 0x67, 0xe8, 0x70, 0x14, 0x61, 0xdc,
+ 0x86, 0x07, 0xe1, 0x32, 0x16, 0x0d, 0xec, 0xa2, 0x10, 0x5f, 0xcf, 0x2d,
+ 0xdd, 0xd0, 0xce, 0xb2, 0xc4, 0xb2, 0xe9, 0x6e, 0x2c, 0xaf, 0x1e, 0xff,
+ 0x0d, 0x7e, 0x21, 0x7f, 0xbf, 0xc7, 0xeb, 0xed, 0x3a, 0xca, 0x59, 0x4c,
+ 0x78, 0x1b, 0x66, 0xb7, 0xf6, 0x4e, 0x3f, 0x36, 0x96, 0x57, 0x8f, 0x48,
+ 0x89, 0x2f, 0xfd, 0x19, 0xcd, 0x90, 0xc3, 0x12, 0x4b, 0x2f, 0xe6, 0x33,
+ 0x93, 0xe1, 0x8b, 0x28, 0x8f, 0xc3, 0xe8, 0x17, 0x14, 0x2c, 0xbc, 0x00,
+ 0x42, 0xcb, 0xb3, 0xb5, 0x97, 0x40, 0xf8, 0x6c, 0xfe, 0x39, 0x7a, 0x0b,
+ 0xb5, 0x97, 0xff, 0xf3, 0x98, 0x37, 0x7d, 0x4f, 0xe7, 0xff, 0x9b, 0x52,
+ 0x59, 0x7e, 0xef, 0xbf, 0x46, 0x96, 0x57, 0x91, 0x44, 0x43, 0x81, 0x5c,
+ 0xa9, 0x26, 0xcd, 0xd9, 0x0f, 0x12, 0x3f, 0x0c, 0xeb, 0xe7, 0x27, 0x99,
+ 0x65, 0xfb, 0x34, 0x27, 0xf8, 0xb2, 0xfc, 0xdf, 0x2c, 0x92, 0xcb, 0xe8,
+ 0x32, 0x26, 0x59, 0x7f, 0xee, 0x6f, 0x7f, 0x41, 0xb9, 0xfe, 0x2c, 0xb8,
+ 0x43, 0xac, 0xbf, 0x16, 0x68, 0x38, 0xb2, 0xf3, 0xf4, 0x4b, 0x2f, 0xef,
+ 0x93, 0x83, 0x09, 0x65, 0xf8, 0x9c, 0x18, 0x4b, 0x2b, 0x61, 0xe8, 0x7c,
+ 0xae, 0x86, 0x89, 0x00, 0xb6, 0x54, 0xe9, 0xe2, 0xc8, 0x84, 0xd2, 0x96,
+ 0x26, 0x98, 0x8f, 0xc8, 0x20, 0x18, 0x28, 0x5b, 0x5f, 0x73, 0x0b, 0xb5,
+ 0x97, 0xf4, 0x17, 0xfb, 0x0c, 0xeb, 0x2d, 0xc5, 0x97, 0xfa, 0x0c, 0x18,
+ 0x5f, 0x52, 0x59, 0x7b, 0x91, 0x25, 0x97, 0xef, 0x66, 0x9b, 0x8b, 0x2e,
+ 0x6d, 0x74, 0x78, 0x7f, 0x1c, 0xb6, 0xf5, 0x95, 0x09, 0x8d, 0x48, 0x8a,
+ 0x62, 0xfd, 0x08, 0xf9, 0xdf, 0x74, 0xba, 0xff, 0xf1, 0x7f, 0xd9, 0x2f,
+ 0xc6, 0x17, 0x5f, 0x59, 0x78, 0x98, 0xd5, 0x97, 0xd8, 0x36, 0xde, 0xb2,
+ 0xe8, 0x3e, 0x1b, 0xf7, 0x1c, 0xbf, 0x4b, 0xec, 0x7f, 0xac, 0xbf, 0x9f,
+ 0xaf, 0x40, 0x84, 0xb2, 0xd9, 0xd1, 0xeb, 0x18, 0x51, 0x78, 0x4e, 0x89,
+ 0x65, 0xfc, 0xf2, 0x72, 0xcd, 0xd5, 0x97, 0x30, 0xd6, 0x5f, 0x73, 0xcf,
+ 0x25, 0x96, 0xfa, 0xca, 0x84, 0xf1, 0x9a, 0x11, 0x1a, 0x84, 0x07, 0x8a,
+ 0x5c, 0x78, 0x05, 0xc1, 0x16, 0x10, 0x8a, 0xf6, 0x14, 0xcb, 0x2d, 0xd2,
+ 0xcb, 0x81, 0x09, 0x2e, 0x30, 0xc4, 0x94, 0xc6, 0xbc, 0xc1, 0x6b, 0xf1,
+ 0x67, 0xfc, 0xc9, 0x05, 0x9a, 0x1b, 0xe3, 0x4b, 0x38, 0xb2, 0xa4, 0x7b,
+ 0x43, 0x38, 0xbb, 0xb0, 0x2c, 0xbf, 0xce, 0x6c, 0x11, 0x67, 0xd6, 0x5e,
+ 0x60, 0x3a, 0xca, 0x84, 0xd7, 0x86, 0x38, 0xf0, 0xbc, 0x01, 0x11, 0x0c,
+ 0x04, 0xc6, 0xf7, 0xa0, 0xc5, 0x97, 0x9f, 0xae, 0x2c, 0xb7, 0x16, 0x5f,
+ 0x09, 0xe7, 0xfa, 0xca, 0x9c, 0xfb, 0x86, 0x3b, 0xd0, 0xef, 0xc4, 0x6f,
+ 0x41, 0x4c, 0xb2, 0xe2, 0x85, 0x94, 0xb2, 0x96, 0x54, 0xc5, 0xb1, 0xc2,
+ 0xee, 0xf4, 0xcb, 0x2e, 0x60, 0x2c, 0xa8, 0x35, 0xc0, 0x18, 0xa9, 0x91,
+ 0x6d, 0xa1, 0xc7, 0x2b, 0x02, 0x7d, 0xff, 0xc6, 0xb1, 0x77, 0xc8, 0x3b,
+ 0xf5, 0xf5, 0x97, 0x81, 0x9b, 0xab, 0x2f, 0xff, 0x8b, 0x01, 0x87, 0x0c,
+ 0x6b, 0x4c, 0x1e, 0xd6, 0x5f, 0x14, 0x1e, 0x65, 0x94, 0x6a, 0x35, 0xb4,
+ 0x8c, 0x43, 0xff, 0x4f, 0xbe, 0x3f, 0x02, 0x75, 0x96, 0x35, 0x65, 0xb6,
+ 0xd6, 0x5d, 0xa3, 0x56, 0x54, 0x1f, 0x0b, 0x11, 0x84, 0x48, 0x41, 0x4b,
+ 0xff, 0xef, 0x64, 0xb9, 0x1f, 0x96, 0x6e, 0x39, 0x01, 0x65, 0xff, 0x37,
+ 0xfd, 0x9d, 0x7c, 0x30, 0xb2, 0xf8, 0x48, 0xd0, 0x16, 0x54, 0x8f, 0x73,
+ 0xc7, 0x37, 0x67, 0x16, 0x5f, 0xfe, 0xc9, 0x6d, 0xe1, 0xaf, 0x9f, 0x8f,
+ 0xf1, 0x65, 0x42, 0x21, 0x24, 0x44, 0x01, 0x6a, 0xe2, 0x6c, 0x1f, 0x8c,
+ 0xc6, 0xe8, 0xe2, 0xcb, 0x01, 0x65, 0xf4, 0x1e, 0x0e, 0xb2, 0xfc, 0xc6,
+ 0x1d, 0xfe, 0xb2, 0x98, 0xf2, 0x74, 0x43, 0x6c, 0x59, 0x4c, 0x8c, 0xbd,
+ 0x15, 0x38, 0xb7, 0x16, 0xb6, 0xc8, 0x6c, 0x6a, 0xca, 0x85, 0xd6, 0x8c,
+ 0x87, 0xa3, 0x46, 0x27, 0xe8, 0x4f, 0x3c, 0xa6, 0x6d, 0xd4, 0xbb, 0xe8,
+ 0x30, 0x33, 0x2c, 0xbd, 0xc8, 0x99, 0x65, 0xfd, 0x83, 0xcd, 0xed, 0xa5,
+ 0x94, 0xb2, 0xda, 0x59, 0x63, 0xac, 0xaf, 0x9a, 0xd0, 0x85, 0xef, 0x11,
+ 0xbe, 0x1b, 0xbf, 0x4b, 0x2f, 0xc0, 0x6d, 0x31, 0xab, 0x2e, 0x73, 0x56,
+ 0x5d, 0x9d, 0x2c, 0xae, 0xd3, 0x44, 0x98, 0x90, 0xe3, 0xbe, 0x5b, 0x73,
+ 0x00, 0x11, 0x11, 0x46, 0xd8, 0xbd, 0xd9, 0xe5, 0x97, 0xf1, 0x7f, 0x09,
+ 0x8c, 0x59, 0x7f, 0x7f, 0x98, 0x76, 0xfa, 0xcb, 0x69, 0x65, 0x41, 0xbe,
+ 0xc2, 0xda, 0x59, 0x4b, 0x2d, 0x0b, 0x28, 0x56, 0x69, 0x88, 0x2f, 0xe1,
+ 0x77, 0xb3, 0x7b, 0xac, 0xbe, 0xf7, 0xb0, 0x0b, 0x2d, 0x1e, 0x37, 0xe2,
+ 0x0e, 0xd4, 0x26, 0xb8, 0xc2, 0xc7, 0x6a, 0x74, 0x50, 0x38, 0x5f, 0xdf,
+ 0xce, 0xa5, 0x12, 0x59, 0x7e, 0xfe, 0x79, 0xcd, 0x59, 0x5d, 0x1e, 0xb3,
+ 0x17, 0x5f, 0xba, 0x06, 0xd4, 0x1e, 0x2c, 0xbd, 0xe7, 0x3a, 0xcb, 0xf9,
+ 0xfe, 0x01, 0x0a, 0x4b, 0x28, 0x67, 0x95, 0xb8, 0x39, 0x7f, 0x7c, 0x6c,
+ 0x08, 0x25, 0x97, 0xa7, 0xf3, 0x2c, 0xbb, 0xc1, 0xe8, 0xf2, 0x5c, 0xb2,
+ 0xf1, 0x86, 0x18, 0x92, 0xff, 0x44, 0xe2, 0x67, 0x9f, 0xa4, 0x82, 0xcd,
+ 0x05, 0xfe, 0x61, 0xb9, 0x75, 0x2e, 0x2c, 0xa1, 0x9f, 0xd7, 0x91, 0xee,
+ 0xc9, 0xd6, 0x5f, 0x8e, 0x24, 0x68, 0x0b, 0x29, 0x65, 0x2c, 0xb4, 0x1c,
+ 0xb6, 0x00, 0x5d, 0x41, 0xf2, 0x48, 0xfe, 0xff, 0xdc, 0x89, 0x7b, 0x30,
+ 0xa5, 0xc5, 0x94, 0x34, 0xf0, 0xfb, 0x86, 0x43, 0x11, 0x4c, 0xf7, 0xf2,
+ 0x1b, 0xd0, 0x76, 0x59, 0x7a, 0x59, 0xda, 0xcb, 0xe8, 0x1b, 0x1d, 0x65,
+ 0x6d, 0x0a, 0xd5, 0x21, 0xe7, 0x25, 0x18, 0xf6, 0xa3, 0xd0, 0xdb, 0x0e,
+ 0xde, 0xd6, 0xe8, 0xd6, 0x5b, 0xcb, 0x29, 0x8d, 0x8e, 0xe9, 0x05, 0xfb,
+ 0xd1, 0xd3, 0xee, 0x2c, 0xbf, 0xfe, 0x8f, 0xf0, 0x79, 0xf6, 0xf0, 0x73,
+ 0xaf, 0xac, 0xaf, 0x1f, 0xdf, 0xca, 0xef, 0x16, 0x79, 0x65, 0xb4, 0xb2,
+ 0xff, 0x66, 0x76, 0x26, 0xff, 0x62, 0xcb, 0xfe, 0x82, 0xf9, 0x67, 0xe0,
+ 0xc5, 0x97, 0xf1, 0x9c, 0x62, 0xea, 0x4b, 0x2f, 0xa7, 0xfe, 0x79, 0x65,
+ 0x61, 0xe9, 0x04, 0xbe, 0x96, 0x53, 0x22, 0xd7, 0x50, 0x89, 0x72, 0x1b,
+ 0xee, 0x7d, 0xd9, 0x65, 0xfd, 0x93, 0x00, 0xf9, 0x32, 0xcb, 0xef, 0xf2,
+ 0x00, 0xb2, 0xed, 0x05, 0x65, 0x61, 0xb9, 0xf9, 0x15, 0xb8, 0xb2, 0x88,
+ 0xd8, 0x84, 0x82, 0xff, 0x3e, 0xfc, 0x1c, 0xf8, 0x62, 0xcb, 0xff, 0xd1,
+ 0x9d, 0x09, 0xf6, 0x20, 0xcb, 0x38, 0xb2, 0xf4, 0x64, 0xeb, 0x2d, 0x83,
+ 0x3e, 0x6d, 0xe9, 0x57, 0xd9, 0xe1, 0x34, 0xb2, 0xe3, 0x81, 0x65, 0xce,
+ 0x4b, 0x2b, 0xc6, 0xb1, 0xc5, 0xee, 0x63, 0x56, 0x5f, 0x37, 0xc0, 0xeb,
+ 0x2f, 0xd1, 0xd4, 0xb0, 0xeb, 0x2a, 0x47, 0xc0, 0x71, 0x7f, 0x10, 0xdf,
+ 0x72, 0x08, 0xd5, 0x95, 0x3a, 0xe6, 0x4e, 0x42, 0x79, 0x88, 0xb7, 0x06,
+ 0xe6, 0x11, 0xd4, 0x3a, 0xce, 0x67, 0xe2, 0x17, 0x84, 0xc8, 0x08, 0x0a,
+ 0x13, 0x9c, 0x29, 0xfa, 0x78, 0x61, 0x00, 0x21, 0x7d, 0xda, 0x35, 0x65,
+ 0xf4, 0x1d, 0xfc, 0xb2, 0xf7, 0xfe, 0xeb, 0x2f, 0xb4, 0x18, 0xde, 0xb2,
+ 0xfd, 0x9b, 0x8e, 0x40, 0x19, 0xf0, 0xb9, 0x0f, 0xc7, 0x2f, 0xbd, 0xf6,
+ 0x9d, 0x65, 0xfe, 0xed, 0xb8, 0x59, 0xbd, 0xd6, 0x5f, 0x44, 0xef, 0x25,
+ 0x97, 0x00, 0xeb, 0x2f, 0x73, 0xcc, 0xb2, 0xb4, 0x6c, 0xfe, 0x2f, 0x7f,
+ 0x13, 0xfe, 0x7c, 0x31, 0x65, 0x2c, 0xa2, 0x37, 0x3f, 0x2e, 0xa8, 0x3f,
+ 0xac, 0x5a, 0xbe, 0x9c, 0xb3, 0xa5, 0x97, 0xf0, 0x39, 0x83, 0x79, 0x2c,
+ 0xac, 0x3d, 0x07, 0x23, 0xbe, 0xfb, 0x17, 0x16, 0x5f, 0x6c, 0xce, 0xbe,
+ 0xb2, 0xfe, 0xe4, 0x75, 0x2c, 0xfa, 0xca, 0xec, 0xf4, 0xf8, 0x4b, 0x7d,
+ 0x9f, 0x6e, 0x2c, 0xa5, 0x95, 0xd1, 0xac, 0x72, 0x1a, 0xc4, 0x72, 0x33,
+ 0xa3, 0xa7, 0xd4, 0x2b, 0x8c, 0x93, 0xce, 0x26, 0x74, 0x47, 0xa3, 0x4f,
+ 0x43, 0x3c, 0x9c, 0x39, 0x18, 0x25, 0xe1, 0x02, 0x22, 0xcb, 0xc4, 0xdb,
+ 0x8b, 0x2f, 0xef, 0x47, 0xf9, 0xe6, 0x59, 0x73, 0x9a, 0xb2, 0xc3, 0xf9,
+ 0xe2, 0x6d, 0x96, 0xde, 0xeb, 0x83, 0x59, 0x50, 0x8a, 0xbc, 0x62, 0x62,
+ 0xbb, 0x6d, 0xac, 0xba, 0x06, 0xb2, 0x85, 0x26, 0xab, 0xc2, 0x96, 0xe2,
+ 0xcb, 0x1d, 0x65, 0xb4, 0xb2, 0x9c, 0xd1, 0x04, 0x46, 0xb4, 0x7a, 0x7e,
+ 0x33, 0xbf, 0xa7, 0x1e, 0x98, 0x33, 0xac, 0xb0, 0x16, 0x52, 0xc6, 0x3e,
+ 0x37, 0x22, 0xdb, 0x30, 0xbf, 0xd0, 0x52, 0x73, 0xe0, 0xd6, 0x5f, 0x7c,
+ 0xe7, 0xd2, 0xcb, 0xff, 0x81, 0x05, 0xdb, 0xfc, 0x02, 0x14, 0x96, 0x5e,
+ 0x93, 0x79, 0x65, 0xf7, 0xcb, 0x24, 0xb2, 0xf8, 0x22, 0xbe, 0x3a, 0xcb,
+ 0xf4, 0xe3, 0x77, 0x31, 0x65, 0x61, 0xe7, 0x84, 0x9a, 0xff, 0xee, 0x7b,
+ 0x06, 0x59, 0xbc, 0xb3, 0x8b, 0x2f, 0x3c, 0xdc, 0x59, 0x4c, 0x7c, 0x3f,
+ 0x44, 0xa9, 0x27, 0x90, 0x69, 0x8f, 0x44, 0x73, 0x22, 0xe8, 0x70, 0x9c,
+ 0x3f, 0x08, 0x2b, 0x84, 0xed, 0x65, 0x6d, 0x6e, 0xda, 0xe4, 0x50, 0xc0,
+ 0x2a, 0x12, 0x8a, 0xb2, 0x08, 0x94, 0x87, 0x3c, 0x35, 0x24, 0xd4, 0x39,
+ 0x7a, 0xb9, 0x3d, 0x40, 0x6c, 0x67, 0x3d, 0xc3, 0x07, 0xa8, 0xfd, 0xda,
+ 0x50, 0x4c, 0xd1, 0xc9, 0x6a, 0x51, 0x09, 0xe3, 0xd8, 0xf4, 0xf1, 0x83,
+ 0xc7, 0x68, 0x08, 0xf4, 0x45, 0x70, 0x9e, 0x29, 0x6e, 0xdc, 0x9d, 0x5e,
+ 0xfc, 0xe3, 0xb0, 0x5f, 0x37, 0xc3, 0x28, 0xc5, 0x7d, 0xb8, 0x6d, 0x89,
+ 0x1f, 0xfe, 0xeb, 0x65, 0xff, 0x0b, 0xfb, 0x66, 0xef, 0x03, 0x0b, 0x2f,
+ 0x00, 0x49, 0x2c, 0xbf, 0xfe, 0xe3, 0x79, 0xdb, 0xf9, 0xa0, 0x1d, 0xe4,
+ 0xb2, 0xc2, 0xfa, 0x3e, 0xcf, 0x8f, 0x5f, 0xee, 0x0b, 0x8d, 0xf0, 0x1e,
+ 0xd6, 0x58, 0x30, 0x7c, 0x7f, 0x2b, 0xa1, 0x6a, 0xd8, 0xe7, 0x94, 0x60,
+ 0x38, 0xc3, 0x2f, 0xda, 0xed, 0xdf, 0xb5, 0x45, 0x6e, 0xbf, 0xf3, 0xc8,
+ 0x5e, 0x6b, 0xb7, 0x7e, 0xd5, 0x13, 0x82, 0xc2, 0xf1, 0x10, 0x87, 0x36,
+ 0xb8, 0x50, 0x35, 0x96, 0xf2, 0xcb, 0x71, 0x65, 0x04, 0xd1, 0x6d, 0x88,
+ 0xdf, 0xb0, 0xce, 0x31, 0x8b, 0x2f, 0x4b, 0x9c, 0x59, 0x7d, 0xdb, 0xbf,
+ 0x6a, 0x8b, 0x45, 0x7f, 0xfb, 0x07, 0xe7, 0x36, 0x69, 0x9b, 0x81, 0x3a,
+ 0xcb, 0xfd, 0x13, 0xfb, 0x34, 0x1e, 0xd6, 0x56, 0x91, 0x65, 0xe3, 0x0e,
+ 0x26, 0xde, 0x62, 0xed, 0x65, 0xe7, 0x20, 0x2c, 0xac, 0x36, 0xfd, 0x8e,
+ 0x5f, 0x02, 0x0b, 0xb5, 0x97, 0xb7, 0xc4, 0xcb, 0x2f, 0xf6, 0x6e, 0x73,
+ 0x5a, 0x7f, 0xac, 0xbf, 0xa2, 0x77, 0xf3, 0x9d, 0x65, 0x32, 0x20, 0xa6,
+ 0x1f, 0xf1, 0xb5, 0xfd, 0x1f, 0xc2, 0xef, 0x16, 0x5b, 0x8b, 0x29, 0x8d,
+ 0xef, 0x8b, 0x2f, 0xe8, 0x72, 0x08, 0xf1, 0x65, 0xfb, 0x43, 0x0f, 0xf8,
+ 0xb2, 0xff, 0xa2, 0x7f, 0x67, 0x3d, 0x9b, 0x8b, 0x2f, 0xdd, 0xe3, 0x17,
+ 0x6b, 0x2f, 0xf6, 0x76, 0x50, 0x0e, 0x42, 0xcb, 0xa3, 0xbd, 0x87, 0xb5,
+ 0xc2, 0x8b, 0xfe, 0xdf, 0xcc, 0xf6, 0x10, 0x83, 0x59, 0x50, 0x7d, 0x78,
+ 0x61, 0x5e, 0x4c, 0x84, 0xa3, 0x01, 0xbf, 0xd9, 0xa0, 0x64, 0xc2, 0x71,
+ 0x65, 0x8d, 0x59, 0x7f, 0xd9, 0x13, 0xe4, 0xda, 0x6e, 0x2c, 0xa6, 0x3c,
+ 0xb9, 0x84, 0xaf, 0xff, 0xd3, 0xc7, 0xe0, 0x7a, 0x8f, 0x3f, 0x0b, 0x00,
+ 0xb2, 0xff, 0xd1, 0xd3, 0xee, 0x78, 0x9f, 0x72, 0x75, 0x97, 0xfe, 0x8d,
+ 0x03, 0x1b, 0x35, 0xf0, 0xac, 0xa8, 0x46, 0xb7, 0x95, 0x38, 0x8b, 0x43,
+ 0x4f, 0x41, 0x8a, 0x66, 0x84, 0x07, 0x21, 0xf1, 0x7f, 0x46, 0xf2, 0x7f,
+ 0xf1, 0x65, 0xff, 0xf7, 0xe0, 0x7e, 0x0b, 0x9b, 0xde, 0x31, 0x76, 0xb2,
+ 0xff, 0xdc, 0xf6, 0x02, 0x6e, 0x13, 0xf9, 0x65, 0xf1, 0xd8, 0xa4, 0xb2,
+ 0x99, 0x16, 0x3b, 0x8a, 0x3c, 0x3f, 0xa8, 0x5c, 0x73, 0xc9, 0x63, 0x5e,
+ 0x48, 0x78, 0x6f, 0xdd, 0x1e, 0x59, 0x77, 0x0e, 0xb2, 0xa6, 0x35, 0xbe,
+ 0x16, 0xa5, 0x97, 0xb5, 0x06, 0xac, 0xbf, 0x37, 0xca, 0x0e, 0xb2, 0xb6,
+ 0xb3, 0xce, 0x98, 0x2f, 0xc3, 0xb7, 0xfa, 0x0f, 0xad, 0x30, 0x38, 0xb2,
+ 0xf7, 0x78, 0x62, 0xcb, 0x64, 0xc7, 0xa3, 0xe3, 0x3b, 0xff, 0xe6, 0xff,
+ 0x1b, 0xb7, 0xd7, 0x78, 0xc5, 0xda, 0xcb, 0x18, 0xb2, 0xff, 0x6a, 0x3f,
+ 0xd4, 0xb3, 0xeb, 0x2f, 0xff, 0xec, 0x99, 0xca, 0x70, 0x37, 0x5c, 0xef,
+ 0x18, 0xbb, 0x59, 0x76, 0x0d, 0x65, 0xe9, 0xdc, 0xeb, 0x2f, 0x40, 0x35,
+ 0x06, 0xcd, 0x85, 0xaf, 0xfe, 0xeb, 0x9f, 0x2c, 0xdf, 0xff, 0xb0, 0xd6,
+ 0x54, 0x93, 0x9d, 0x65, 0x09, 0x84, 0x88, 0xd3, 0x90, 0x90, 0x09, 0x85,
+ 0xcd, 0x25, 0x97, 0xf6, 0x6f, 0xf8, 0x63, 0xb5, 0x97, 0xfb, 0xde, 0x09,
+ 0xa7, 0x8e, 0x2c, 0xbf, 0x6c, 0x97, 0x84, 0xe2, 0xcb, 0x8d, 0x1a, 0xcb,
+ 0xff, 0xee, 0x16, 0x6f, 0x7f, 0x96, 0x73, 0xcf, 0x32, 0xca, 0xc3, 0xe8,
+ 0x61, 0x8b, 0xf4, 0x7f, 0x82, 0x79, 0x65, 0x42, 0x6b, 0x03, 0x16, 0xc3,
+ 0x06, 0x35, 0x9a, 0x12, 0x84, 0x41, 0x7c, 0x4d, 0xd4, 0x96, 0x5e, 0x03,
+ 0xf9, 0x65, 0xfe, 0x9f, 0x18, 0x6e, 0xe6, 0xac, 0xac, 0x3c, 0xf7, 0x1c,
+ 0xbf, 0xb5, 0x03, 0x82, 0x99, 0x65, 0xb8, 0xb2, 0xa7, 0x37, 0xde, 0x2d,
+ 0xb0, 0xb1, 0x4b, 0x37, 0x83, 0x68, 0x3d, 0x9c, 0x90, 0x65, 0x39, 0x0c,
+ 0xfe, 0xd9, 0xfa, 0x21, 0x9a, 0x14, 0x9a, 0x6d, 0x39, 0x07, 0xa7, 0x27,
+ 0x9d, 0xd8, 0x0e, 0x05, 0x08, 0x6e, 0x47, 0x8b, 0xf8, 0xed, 0x02, 0xb5,
+ 0xb6, 0xe2, 0x22, 0xf5, 0xee, 0x1f, 0x8b, 0x2f, 0xf0, 0xa6, 0x1b, 0xf2,
+ 0xce, 0x2c, 0xbf, 0xfe, 0x6f, 0xb6, 0x9c, 0x11, 0xe6, 0xee, 0x00, 0xb2,
+ 0xe9, 0x49, 0x65, 0xff, 0xd8, 0x51, 0x86, 0xc4, 0xbf, 0x93, 0xac, 0xbf,
+ 0xf3, 0xfb, 0x64, 0x67, 0xfc, 0xc7, 0x59, 0x7f, 0xff, 0x9b, 0xf1, 0xe2,
+ 0xcf, 0xea, 0x3c, 0x59, 0xbc, 0x3d, 0xac, 0xbf, 0xfe, 0x8c, 0xff, 0x9e,
+ 0x5a, 0x08, 0xe0, 0xa1, 0x65, 0x49, 0x39, 0x5d, 0xc4, 0xef, 0x0b, 0x85,
+ 0x0f, 0x79, 0xfe, 0xeb, 0x0d, 0xff, 0xe6, 0xf3, 0xb4, 0xff, 0x62, 0x60,
+ 0x71, 0x65, 0xff, 0x14, 0x4b, 0x39, 0x8d, 0x0b, 0x2d, 0x3a, 0xca, 0x83,
+ 0xc7, 0x23, 0x5b, 0xff, 0xfe, 0x80, 0x1d, 0xe5, 0xb3, 0xfe, 0xc3, 0xe7,
+ 0x71, 0xe8, 0x3a, 0xcb, 0xff, 0xe6, 0x2f, 0x87, 0xcd, 0xcd, 0xb7, 0xfe,
+ 0x0d, 0x65, 0x79, 0x17, 0x3f, 0x68, 0xbf, 0x9a, 0x7d, 0x8e, 0x40, 0x59,
+ 0x7f, 0xff, 0xde, 0x76, 0xe6, 0x1a, 0xe4, 0x0d, 0x99, 0xb9, 0x04, 0xe6,
+ 0xac, 0xbc, 0xef, 0xda, 0xa2, 0xda, 0x54, 0x22, 0x4b, 0xb6, 0x9b, 0xff,
+ 0xfa, 0x1f, 0xf1, 0xe8, 0xe3, 0x34, 0x9b, 0x58, 0x35, 0x97, 0xf7, 0xa0,
+ 0xf0, 0xc3, 0x59, 0x4c, 0x9c, 0x54, 0xc4, 0x7a, 0x86, 0x0f, 0x08, 0xfe,
+ 0xaf, 0x7f, 0x3c, 0x87, 0xe6, 0x3a, 0xcb, 0xfd, 0x93, 0x14, 0x1f, 0x67,
+ 0x6b, 0x2e, 0xf3, 0x0c, 0xf8, 0xfe, 0x5b, 0x7f, 0xfb, 0xd9, 0x27, 0x2f,
+ 0xbc, 0x98, 0xd8, 0x59, 0x7f, 0xd9, 0x9d, 0xed, 0x87, 0xcd, 0xa5, 0x97,
+ 0xff, 0x7b, 0x27, 0xe3, 0x6a, 0x37, 0x5c, 0x96, 0x5d, 0x8c, 0xb2, 0xbb,
+ 0x3d, 0xbd, 0xe8, 0xd7, 0xf4, 0x0a, 0x39, 0x3e, 0x18, 0xb2, 0xa0, 0xf6,
+ 0x34, 0x4b, 0x6d, 0xa9, 0x65, 0xff, 0xd9, 0xf8, 0x39, 0x39, 0xa5, 0x80,
+ 0x59, 0x60, 0x2c, 0xa9, 0x8f, 0xa4, 0x85, 0xbe, 0x85, 0x7f, 0xe6, 0x21,
+ 0xc4, 0x1f, 0x75, 0xe4, 0xb2, 0xff, 0xa0, 0x1e, 0x89, 0xcb, 0x38, 0xb2,
+ 0xa0, 0xfd, 0xc2, 0x7f, 0x7d, 0xe8, 0xd1, 0xab, 0x2f, 0xff, 0x36, 0xa3,
+ 0x3c, 0x16, 0xe7, 0xb0, 0x0b, 0x2f, 0xff, 0x86, 0x1f, 0xf0, 0x79, 0x2f,
+ 0x46, 0xf1, 0xc2, 0xcb, 0x83, 0x8b, 0x2a, 0x48, 0xd3, 0x19, 0x1b, 0x24,
+ 0x12, 0x95, 0xff, 0x44, 0xa3, 0x53, 0xc6, 0xa7, 0x59, 0x7f, 0xfa, 0x25,
+ 0xe8, 0x23, 0x4b, 0x27, 0x12, 0x4b, 0x2f, 0xff, 0xf4, 0x31, 0x3f, 0xc3,
+ 0xfc, 0x1c, 0x1c, 0x7e, 0x8e, 0x96, 0x5f, 0xe6, 0x38, 0xe3, 0x82, 0x71,
+ 0x65, 0xef, 0xe7, 0x6b, 0x2f, 0xff, 0x89, 0xb7, 0xb7, 0xfd, 0x1f, 0xe4,
+ 0x6f, 0x85, 0x94, 0xc9, 0xa6, 0x69, 0x2f, 0xcb, 0xff, 0x34, 0x08, 0xed,
+ 0xfe, 0x1e, 0x14, 0x9b, 0xc1, 0x59, 0x61, 0xac, 0xbf, 0x83, 0xdf, 0xa3,
+ 0x58, 0xb2, 0xf7, 0x5c, 0xf2, 0xca, 0xc3, 0xcc, 0x72, 0xea, 0x64, 0x57,
+ 0xb9, 0x97, 0x17, 0x6f, 0xfe, 0xfb, 0xb6, 0x46, 0x9e, 0x4d, 0xe5, 0x97,
+ 0xe7, 0x1e, 0x10, 0x16, 0x54, 0x8f, 0x9d, 0x90, 0x6f, 0xfa, 0x35, 0xb3,
+ 0x91, 0xe7, 0x65, 0x97, 0xfb, 0xcc, 0xf2, 0xfb, 0x4e, 0xb2, 0xfa, 0x30,
+ 0x99, 0x65, 0xf7, 0xe3, 0x06, 0xb2, 0x86, 0x78, 0x1d, 0x0f, 0xde, 0xfe,
+ 0x4e, 0xb2, 0xb6, 0xa6, 0x6e, 0x88, 0xa4, 0x76, 0x23, 0xcb, 0x93, 0x00,
+ 0xe1, 0x1f, 0x92, 0x98, 0xfb, 0x85, 0x9b, 0x16, 0xcc, 0x91, 0xa8, 0x77,
+ 0x9e, 0x11, 0x5e, 0x85, 0x33, 0xc3, 0xd0, 0x8e, 0xf9, 0x1c, 0x37, 0xe1,
+ 0xf2, 0x18, 0x4a, 0x98, 0x43, 0xb6, 0x72, 0x23, 0x9e, 0xe9, 0x1d, 0xec,
+ 0xc3, 0x56, 0x5f, 0xd1, 0x2e, 0x3e, 0x76, 0xb2, 0xe8, 0x17, 0xa3, 0xc9,
+ 0xf0, 0xe5, 0xff, 0x46, 0x9f, 0xe0, 0x10, 0xa4, 0xb2, 0xff, 0xfe, 0xd4,
+ 0x7d, 0xbb, 0x61, 0xc3, 0x69, 0xa4, 0xdc, 0x59, 0x7f, 0x1a, 0xfa, 0x18,
+ 0x49, 0x65, 0xfe, 0xfb, 0x76, 0xc3, 0xe8, 0x96, 0x5f, 0xd0, 0x7c, 0x0e,
+ 0x1d, 0x65, 0x41, 0xf0, 0x31, 0xa5, 0xff, 0xff, 0xff, 0x86, 0x51, 0xdf,
+ 0x5d, 0xb7, 0x47, 0x72, 0x37, 0x09, 0xfa, 0x33, 0xbf, 0x34, 0xc4, 0xc7,
+ 0xe2, 0xcb, 0xff, 0x37, 0xe3, 0xed, 0xbe, 0x0b, 0xb5, 0x97, 0x75, 0x25,
+ 0x95, 0x88, 0xf6, 0x78, 0x4f, 0x84, 0xfe, 0xfe, 0x2d, 0xb6, 0xd6, 0x1a,
+ 0xb2, 0xef, 0xf9, 0x65, 0xff, 0x67, 0xf8, 0x27, 0x3f, 0x9e, 0x59, 0x53,
+ 0x9e, 0x89, 0xc5, 0xef, 0xcd, 0x39, 0xe3, 0xb5, 0x97, 0xe7, 0xea, 0x42,
+ 0x71, 0x65, 0xff, 0x9a, 0x6e, 0x6f, 0x72, 0x9c, 0x23, 0x59, 0x61, 0x73,
+ 0xab, 0xa2, 0xc3, 0x93, 0x56, 0x75, 0x08, 0xef, 0x46, 0x2c, 0x46, 0x7c,
+ 0x84, 0x0f, 0xc8, 0xf7, 0x94, 0x88, 0x55, 0x42, 0xd7, 0x8a, 0x72, 0x3b,
+ 0x00, 0x4b, 0xd1, 0xb8, 0xfe, 0x59, 0x7e, 0xd7, 0x6e, 0xfd, 0xaa, 0x2e,
+ 0x55, 0xfc, 0xe3, 0xf4, 0x14, 0xeb, 0x2e, 0x37, 0xcb, 0x2c, 0x2c, 0x68,
+ 0x92, 0xc1, 0x7f, 0x1b, 0x39, 0x6d, 0xcc, 0x6a, 0xcb, 0xf6, 0xbb, 0x77,
+ 0xed, 0x51, 0x76, 0xaf, 0x4f, 0x86, 0x2c, 0xbc, 0x0d, 0xee, 0xb2, 0xff,
+ 0x9a, 0x52, 0x62, 0x04, 0x49, 0x65, 0xc7, 0xdb, 0x59, 0x7c, 0xda, 0x70,
+ 0x2c, 0xbc, 0xf3, 0xc2, 0xcb, 0x0b, 0x1a, 0x62, 0xf8, 0x2e, 0x73, 0x6f,
+ 0x0f, 0x38, 0xf1, 0x1b, 0xf0, 0x68, 0x24, 0x35, 0x10, 0x94, 0xb8, 0x9c,
+ 0xaa, 0x55, 0x98, 0xf0, 0xe5, 0x36, 0xe2, 0x21, 0xb5, 0xe0, 0x5b, 0x5b,
+ 0xc0, 0x9d, 0xc8, 0x63, 0x7a, 0x9c, 0x14, 0x55, 0xa9, 0xbf, 0x21, 0xa7,
+ 0xf8, 0xd6, 0xaf, 0xf0, 0xbc, 0xd7, 0x6e, 0xfd, 0xaa, 0x2a, 0x75, 0xfe,
+ 0xd7, 0xdb, 0xf3, 0x87, 0x8b, 0x2e, 0xe7, 0x16, 0x5c, 0x42, 0xf0, 0xf3,
+ 0x34, 0x6b, 0x7f, 0xf3, 0x6f, 0x8f, 0x34, 0x4d, 0x34, 0x76, 0xb2, 0xe9,
+ 0xf1, 0x65, 0xf7, 0x0b, 0xdf, 0x59, 0x7f, 0xbd, 0x1c, 0x83, 0x86, 0x65,
+ 0x97, 0xc1, 0x94, 0x4e, 0xb2, 0xff, 0xba, 0x97, 0x36, 0x66, 0xf7, 0xd2,
+ 0xca, 0x92, 0x2d, 0xc6, 0x45, 0xa3, 0x4f, 0x11, 0xdf, 0xc1, 0xe8, 0xee,
+ 0xe4, 0xb2, 0xdf, 0x59, 0x7d, 0xd7, 0x20, 0x6b, 0x2c, 0x15, 0x97, 0xa1,
+ 0xe7, 0xd8, 0x6d, 0x00, 0x47, 0x4c, 0x7f, 0x24, 0x8b, 0x7d, 0xdb, 0xbf,
+ 0x6a, 0x8a, 0xe5, 0x71, 0xe1, 0x65, 0xfb, 0x5d, 0xbb, 0xf6, 0xa8, 0xb3,
+ 0x96, 0x17, 0x07, 0x99, 0x82, 0xd7, 0x3c, 0x96, 0x5f, 0xd2, 0xff, 0x5d,
+ 0xb7, 0x16, 0x53, 0x9e, 0x30, 0x45, 0xaf, 0xe6, 0xe6, 0x13, 0x98, 0xb2,
+ 0xf0, 0x65, 0x0b, 0x2b, 0x49, 0xa9, 0xf9, 0xf0, 0x9b, 0xbe, 0x43, 0xbc,
+ 0xb2, 0xff, 0xf7, 0xe3, 0x9b, 0x03, 0xcf, 0xc4, 0xd3, 0x32, 0xcb, 0xff,
+ 0xf3, 0xfb, 0x0f, 0x07, 0xd9, 0x98, 0x69, 0xaf, 0x25, 0x97, 0xf3, 0x1e,
+ 0x70, 0xea, 0x4b, 0x2f, 0xc7, 0xc9, 0x9c, 0x0b, 0x2f, 0xa7, 0xf3, 0xfd,
+ 0x65, 0x39, 0xe5, 0x84, 0xa2, 0xf8, 0xfb, 0x40, 0xa7, 0xeb, 0x2f, 0xd1,
+ 0x34, 0xd1, 0xda, 0xcb, 0xa3, 0xdb, 0x0f, 0x59, 0x8b, 0x2b, 0x13, 0xc4,
+ 0x99, 0x3b, 0xca, 0xe4, 0xf5, 0xbd, 0xde, 0xff, 0x8a, 0x0f, 0xc0, 0xc9,
+ 0xcd, 0x59, 0x7e, 0xd6, 0x7d, 0x8e, 0xb2, 0xe3, 0xef, 0x59, 0x78, 0xa0,
+ 0x6b, 0x2b, 0x0d, 0xa3, 0x8c, 0xdd, 0xec, 0x59, 0x7e, 0xc9, 0xa6, 0x0c,
+ 0xeb, 0x2c, 0x6e, 0x1e, 0x0f, 0x85, 0xaf, 0xd3, 0x41, 0xe0, 0x45, 0x97,
+ 0xff, 0xfd, 0xa6, 0xe0, 0x33, 0x63, 0x6f, 0x8f, 0x34, 0x4d, 0x34, 0x76,
+ 0xb2, 0xe9, 0x1d, 0x65, 0x42, 0x34, 0xf0, 0xa1, 0xca, 0x49, 0xae, 0xfc,
+ 0x78, 0x3e, 0x12, 0xcb, 0xfc, 0x23, 0x4d, 0x1c, 0x63, 0xac, 0xbf, 0xfd,
+ 0xe6, 0xd9, 0xe7, 0x6f, 0xc6, 0x0d, 0x96, 0x5f, 0xf9, 0xb5, 0xb2, 0x0e,
+ 0xdb, 0x8f, 0x32, 0xcb, 0xee, 0xdd, 0xfb, 0x54, 0x48, 0x4a, 0x34, 0xfc,
+ 0xf4, 0x87, 0x7f, 0xd9, 0xfe, 0x06, 0x51, 0x3c, 0x2c, 0xbf, 0xff, 0x36,
+ 0xbb, 0xf6, 0x6c, 0xd6, 0xb0, 0xcd, 0xb8, 0x3a, 0xca, 0x92, 0x25, 0x78,
+ 0x73, 0x7d, 0xfd, 0x37, 0x4b, 0x2f, 0xe7, 0x7e, 0xa5, 0xc6, 0x59, 0x7f,
+ 0x81, 0x1b, 0x91, 0xf8, 0x1a, 0xcb, 0xfe, 0x3e, 0x3e, 0xa7, 0xd9, 0xd1,
+ 0xd6, 0x54, 0x1f, 0x96, 0x1a, 0xdf, 0xee, 0xb9, 0xf2, 0x83, 0xf1, 0x65,
+ 0xff, 0xe7, 0x2e, 0xf6, 0x0c, 0x9e, 0x5e, 0x79, 0x2c, 0xa6, 0x3f, 0xf0,
+ 0x9a, 0x5f, 0xd8, 0x4c, 0x0e, 0x42, 0xcb, 0x0b, 0x85, 0x6f, 0x12, 0x34,
+ 0xc8, 0x5e, 0x75, 0x0b, 0x86, 0x23, 0xd1, 0x1f, 0xa1, 0x3e, 0x08, 0x4f,
+ 0xf0, 0x86, 0xe6, 0xf2, 0xcb, 0xff, 0x38, 0x93, 0x13, 0x7c, 0xa0, 0x0b,
+ 0x2a, 0x75, 0xc8, 0xc9, 0x4b, 0x9e, 0xea, 0x13, 0x5f, 0x16, 0xbf, 0xf3,
+ 0x1f, 0x39, 0xb3, 0xa9, 0x67, 0xd6, 0x5f, 0x70, 0x63, 0x85, 0x95, 0xe3,
+ 0xe3, 0xfa, 0x0d, 0xf4, 0xbc, 0x27, 0x16, 0x5c, 0x2a, 0x6d, 0x0b, 0x2f,
+ 0xff, 0xde, 0x69, 0xbc, 0xdd, 0x7f, 0xdd, 0xb7, 0x30, 0x6b, 0x2f, 0xa1,
+ 0x83, 0xc5, 0x96, 0x17, 0xb4, 0x91, 0x35, 0xd9, 0x0f, 0x96, 0x2a, 0x13,
+ 0x1f, 0xc2, 0x27, 0x85, 0xf5, 0xf6, 0xd1, 0xe8, 0x3a, 0xcb, 0xf7, 0x39,
+ 0x9a, 0x9d, 0x65, 0xee, 0x41, 0xab, 0x2b, 0xc7, 0x8d, 0xc2, 0x9b, 0xa0,
+ 0xc5, 0x97, 0xfc, 0x0c, 0x19, 0x38, 0x23, 0x7a, 0xca, 0xc3, 0xf2, 0x62,
+ 0x27, 0x17, 0xbc, 0x7d, 0xf2, 0x59, 0x7e, 0x8d, 0x6c, 0x07, 0xd6, 0x58,
+ 0x45, 0x97, 0xff, 0x40, 0x0e, 0xf2, 0xe7, 0xf3, 0x0e, 0xb2, 0x86, 0x7a,
+ 0xbe, 0x12, 0xbd, 0x31, 0xe6, 0x59, 0x61, 0x62, 0x86, 0xc1, 0x00, 0x55,
+ 0x23, 0xc4, 0x33, 0xa7, 0x3d, 0x1c, 0x29, 0xb2, 0x37, 0x36, 0x94, 0x21,
+ 0x32, 0x66, 0x8e, 0x4e, 0xb7, 0xe8, 0xcc, 0xde, 0x73, 0x14, 0xa3, 0xd0,
+ 0xe1, 0x9f, 0xe1, 0xbe, 0x12, 0xc3, 0x07, 0xc4, 0x7f, 0xdd, 0x22, 0xbf,
+ 0xc1, 0x7d, 0x4b, 0xc6, 0x3a, 0xcb, 0xff, 0xff, 0xfa, 0x3e, 0x4e, 0x02,
+ 0x7d, 0xed, 0xbc, 0x83, 0xc1, 0x0a, 0x07, 0xe7, 0x96, 0x71, 0x65, 0xff,
+ 0x84, 0x28, 0x1f, 0x9e, 0x59, 0xc5, 0x97, 0xfc, 0x50, 0x3f, 0x3c, 0xb3,
+ 0x8b, 0x2f, 0xf3, 0xef, 0x6d, 0xe4, 0x1e, 0x6c, 0x3f, 0x51, 0x0f, 0xaf,
+ 0x67, 0x42, 0xc6, 0x9c, 0x16, 0x8d, 0x0a, 0x1f, 0xd7, 0xff, 0x0b, 0xf3,
+ 0xf0, 0xb3, 0xff, 0x80, 0x2c, 0xbf, 0xfc, 0x2c, 0xef, 0x21, 0x79, 0xae,
+ 0xdd, 0xfb, 0x54, 0x4f, 0x8b, 0xff, 0xd2, 0x17, 0x9b, 0xd8, 0xde, 0x72,
+ 0x0e, 0x15, 0x97, 0xfd, 0x86, 0x66, 0xf6, 0xfc, 0xa1, 0x65, 0xf0, 0x75,
+ 0x1c, 0x59, 0x7d, 0xbb, 0xb6, 0x28, 0x31, 0x65, 0xf8, 0xd7, 0xfe, 0x18,
+ 0xb2, 0xff, 0x44, 0xe2, 0x6d, 0xb9, 0x01, 0x65, 0x85, 0xce, 0x8e, 0xa1,
+ 0x9d, 0x11, 0x10, 0x4b, 0x84, 0x29, 0xa7, 0x4e, 0x33, 0xf1, 0x9c, 0xd7,
+ 0x6d, 0xb3, 0x3b, 0x42, 0x3f, 0x72, 0xb0, 0x6e, 0xd4, 0xac, 0xb3, 0xa4,
+ 0xf9, 0x15, 0xe3, 0xe8, 0xbf, 0xc4, 0xff, 0xe1, 0x73, 0xeb, 0x2f, 0xff,
+ 0xe0, 0x93, 0x9b, 0xb3, 0xe6, 0xc1, 0x4b, 0x3c, 0xc7, 0x59, 0x73, 0x74,
+ 0xb2, 0xff, 0xfa, 0x53, 0xed, 0x38, 0xda, 0x27, 0xef, 0x5b, 0x36, 0x7b,
+ 0x6d, 0x65, 0x48, 0xff, 0x80, 0x2f, 0x7f, 0xf8, 0xa7, 0xf4, 0x37, 0xf8,
+ 0xc5, 0xd4, 0x96, 0x5f, 0xfd, 0x9f, 0x6c, 0x2f, 0x67, 0xe0, 0x6b, 0x2f,
+ 0xfd, 0xf3, 0x60, 0xa5, 0x9e, 0x63, 0xac, 0xbf, 0xe3, 0x60, 0xa5, 0x9e,
+ 0x63, 0xac, 0xbe, 0x09, 0x39, 0xbb, 0x0f, 0xdb, 0xe7, 0xd7, 0xed, 0x01,
+ 0xbd, 0x0b, 0x28, 0xe7, 0xc4, 0x13, 0xbb, 0xf6, 0x6b, 0x32, 0x65, 0x96,
+ 0x17, 0x8a, 0xb6, 0xce, 0x65, 0xe8, 0x6d, 0xb9, 0x11, 0x25, 0x72, 0x31,
+ 0x91, 0x08, 0xaf, 0xda, 0xed, 0xdf, 0xb5, 0x45, 0x64, 0xbf, 0xf3, 0xc8,
+ 0x5e, 0x6b, 0xb7, 0x7e, 0xd5, 0x13, 0x72, 0xc2, 0xf1, 0x10, 0x87, 0x36,
+ 0xae, 0xd3, 0x25, 0x68, 0x7d, 0xdf, 0x76, 0xef, 0xda, 0xa2, 0x56, 0x5f,
+ 0xff, 0x6a, 0x72, 0x8d, 0x38, 0xc9, 0xf5, 0x1b, 0xd6, 0x56, 0x91, 0x00,
+ 0x13, 0x0b, 0xfe, 0x76, 0x93, 0x10, 0x60, 0xeb, 0x2f, 0xa0, 0x6f, 0xe5,
+ 0x97, 0xb4, 0xdd, 0x2c, 0xa5, 0x97, 0xf9, 0xa4, 0xc4, 0x18, 0x3a, 0xcb,
+ 0xf1, 0x3b, 0x75, 0xd9, 0xcd, 0xe3, 0x85, 0xd1, 0x22, 0xdf, 0xe4, 0x3b,
+ 0xab, 0x37, 0xfa, 0x18, 0xa2, 0x51, 0xba, 0xb2, 0xf8, 0x23, 0xc3, 0x56,
+ 0x5f, 0x1d, 0xe4, 0x2f, 0x13, 0x98, 0xec, 0x8d, 0xa1, 0xdb, 0xc3, 0x2d,
+ 0xb3, 0x3b, 0xf0, 0xb7, 0x9b, 0x98, 0xb2, 0xfc, 0x2f, 0x25, 0x00, 0x59,
+ 0x42, 0xd1, 0x7d, 0x3b, 0x5c, 0x8a, 0xaf, 0xfd, 0xfc, 0x17, 0x9a, 0x69,
+ 0xdc, 0xeb, 0x2f, 0xe1, 0x4b, 0x9f, 0x51, 0xc5, 0x97, 0xff, 0xb6, 0xad,
+ 0xac, 0x53, 0xcc, 0x79, 0x36, 0x6b, 0x16, 0x5f, 0xf9, 0xb8, 0x13, 0x93,
+ 0x6f, 0x0b, 0xac, 0xbf, 0xfe, 0xf4, 0x49, 0x81, 0xac, 0xf3, 0x93, 0xc9,
+ 0x65, 0xfd, 0x04, 0xfd, 0xbe, 0xe2, 0xcb, 0xe0, 0xee, 0x8e, 0x16, 0x5f,
+ 0xf4, 0x77, 0x1a, 0x6f, 0xc7, 0x6b, 0x2a, 0x49, 0x8c, 0xf4, 0x7e, 0x74,
+ 0xdf, 0x17, 0xfc, 0x96, 0xda, 0x59, 0x7f, 0xe0, 0x7f, 0x3d, 0x05, 0xfd,
+ 0xbc, 0x59, 0x43, 0x3d, 0x10, 0x88, 0xdf, 0x76, 0xef, 0xda, 0xa2, 0x5c,
+ 0x5f, 0xff, 0x7b, 0x07, 0x1e, 0x89, 0x14, 0x69, 0xc6, 0xb2, 0xb4, 0x7f,
+ 0xbc, 0x30, 0xbf, 0x4b, 0x3f, 0xbb, 0x3a, 0xcb, 0xef, 0xe9, 0xba, 0x59,
+ 0x7f, 0x9e, 0x5f, 0x28, 0x3f, 0x16, 0x5f, 0xfc, 0xdc, 0x09, 0xbc, 0xc3,
+ 0xb7, 0xa1, 0x65, 0x31, 0xfb, 0x39, 0x95, 0xfa, 0x5b, 0x6d, 0xe7, 0x59,
+ 0x76, 0xdc, 0x2c, 0xbf, 0xf8, 0xa4, 0xe3, 0x78, 0x94, 0x13, 0xac, 0xa8,
+ 0x3d, 0x9c, 0x19, 0xbf, 0x14, 0x76, 0xfa, 0x59, 0x7f, 0xff, 0x60, 0x7b,
+ 0xf4, 0x14, 0x49, 0xc7, 0x1d, 0x69, 0x96, 0x5f, 0xfb, 0x8c, 0x41, 0xfe,
+ 0xdb, 0x6f, 0x3a, 0xcb, 0xff, 0xff, 0xe2, 0xcf, 0xf3, 0x06, 0xe3, 0x82,
+ 0x7e, 0xbd, 0x9c, 0x8e, 0x71, 0xfc, 0xb2, 0xf3, 0x14, 0x2c, 0xa9, 0x27,
+ 0xf6, 0x38, 0x41, 0xb1, 0x06, 0xe1, 0x39, 0xd6, 0x89, 0x0f, 0x7b, 0xd5,
+ 0xfe, 0xcf, 0xf9, 0xb4, 0xfc, 0x59, 0x7f, 0xfd, 0xf6, 0x28, 0x96, 0x0f,
+ 0x25, 0x84, 0x05, 0x97, 0xe6, 0x00, 0x1b, 0xa5, 0x97, 0xfd, 0x1e, 0x76,
+ 0x93, 0x1b, 0x0b, 0x2f, 0xfe, 0x20, 0xcb, 0xcf, 0x2c, 0xea, 0x50, 0xb2,
+ 0xff, 0xe0, 0xc8, 0x9a, 0x51, 0xf2, 0x0c, 0x96, 0x5f, 0xa3, 0x80, 0x3f,
+ 0xd6, 0x53, 0x1f, 0x5f, 0x90, 0xe8, 0x69, 0x83, 0xf0, 0xdf, 0xf0, 0xaf,
+ 0xb7, 0x6b, 0x2a, 0x13, 0xc3, 0xc4, 0xc7, 0x8c, 0xbc, 0x06, 0xd7, 0xf4,
+ 0xbd, 0x85, 0x9d, 0xac, 0xbd, 0x2f, 0x7d, 0x65, 0x31, 0xe5, 0x78, 0xb6,
+ 0xfb, 0xaf, 0x47, 0x6b, 0x2d, 0xe8, 0x3c, 0x57, 0x21, 0xbf, 0xf8, 0x98,
+ 0x1c, 0xd4, 0x34, 0x9f, 0x8b, 0x2f, 0xe7, 0xe8, 0x0e, 0xfa, 0x59, 0x73,
+ 0x71, 0x65, 0x62, 0x2a, 0xd8, 0x9b, 0x88, 0x5b, 0x65, 0xb7, 0xf6, 0x98,
+ 0xe4, 0xf2, 0x59, 0x7f, 0xee, 0xa5, 0x9f, 0xcd, 0x77, 0x18, 0xb2, 0xf3,
+ 0xc8, 0x5e, 0xd0, 0xca, 0x64, 0x15, 0x0c, 0x62, 0x36, 0xf9, 0x42, 0x77,
+ 0x21, 0x3f, 0xd1, 0x13, 0x16, 0x7a, 0x13, 0x2f, 0x28, 0x6c, 0x9b, 0x79,
+ 0x1f, 0xaf, 0xe3, 0x7b, 0x09, 0xf6, 0xe9, 0x65, 0xff, 0x82, 0x71, 0x7c,
+ 0x82, 0xfe, 0x69, 0x65, 0xff, 0xfb, 0x3c, 0x2f, 0x91, 0xf8, 0xdf, 0x05,
+ 0xdb, 0xf1, 0x65, 0xff, 0x0f, 0x05, 0xc6, 0x9b, 0xc1, 0x59, 0x7f, 0xf0,
+ 0xe0, 0x5e, 0xee, 0x75, 0x2f, 0x47, 0x16, 0x58, 0x5b, 0x33, 0x31, 0xcf,
+ 0x4a, 0xa4, 0xe4, 0x60, 0xff, 0x40, 0x0a, 0xc6, 0xf3, 0xab, 0xff, 0x85,
+ 0xbc, 0x85, 0xe6, 0xbb, 0x77, 0xed, 0x51, 0x1d, 0xaf, 0xff, 0x83, 0x1d,
+ 0x49, 0x8e, 0x66, 0x10, 0xfd, 0x0b, 0x2f, 0xff, 0xfe, 0x3c, 0x77, 0xdf,
+ 0x9a, 0x6f, 0x31, 0x0d, 0xf5, 0x06, 0x9a, 0x19, 0xd6, 0x5c, 0x11, 0x16,
+ 0x5f, 0x13, 0xbf, 0x4b, 0x2f, 0xba, 0xfb, 0x18, 0xb2, 0xa0, 0xf1, 0x4e,
+ 0x43, 0x74, 0xe2, 0xc6, 0x9a, 0x2e, 0x28, 0x1d, 0xdc, 0x45, 0xdb, 0xff,
+ 0xfc, 0xe0, 0x16, 0x24, 0x4f, 0x9f, 0x82, 0x60, 0x67, 0x5f, 0x59, 0x7e,
+ 0xe3, 0x6f, 0xf6, 0xf5, 0x97, 0x17, 0x16, 0x5f, 0x7b, 0x24, 0x2e, 0x0f,
+ 0x09, 0xcb, 0x2b, 0x13, 0x2b, 0x99, 0x37, 0xf0, 0xa5, 0xbc, 0x29, 0xd8,
+ 0x35, 0x97, 0xfc, 0x29, 0xdb, 0xc3, 0x5b, 0xe5, 0x0b, 0x2f, 0xe1, 0x41,
+ 0x47, 0x78, 0x4b, 0x2e, 0x0f, 0x96, 0x5f, 0xc2, 0x92, 0xcf, 0x3f, 0xd6,
+ 0x58, 0xc5, 0x97, 0xd8, 0x7d, 0x42, 0xcb, 0xf6, 0x13, 0x00, 0x45, 0x94,
+ 0x47, 0x91, 0xc2, 0x1b, 0xd9, 0xa8, 0x59, 0x7c, 0x1d, 0xd1, 0xc2, 0xcb,
+ 0xff, 0xf4, 0x98, 0x7e, 0x6d, 0xfb, 0x30, 0x7a, 0x60, 0xf6, 0xb2, 0xfa,
+ 0x35, 0x1a, 0x59, 0x42, 0x84, 0xcd, 0x99, 0x6b, 0x44, 0x3e, 0x1b, 0xf9,
+ 0x28, 0x8b, 0x57, 0xa6, 0x89, 0xd6, 0x5f, 0x41, 0x7f, 0x8b, 0x2e, 0xc3,
+ 0x20, 0xdf, 0xf0, 0x7a, 0xff, 0xdc, 0xfe, 0x7a, 0x0b, 0xfe, 0x65, 0x97,
+ 0xfd, 0x19, 0xf6, 0x79, 0xe3, 0x4b, 0x2e, 0x10, 0xeb, 0x2b, 0x11, 0x18,
+ 0x03, 0xdf, 0x9b, 0xdd, 0xb5, 0x71, 0x65, 0xfc, 0x02, 0xce, 0xbf, 0x8b,
+ 0x2e, 0x9f, 0x71, 0x65, 0xff, 0xdb, 0xe0, 0x7f, 0xc8, 0x6f, 0xc4, 0xcb,
+ 0x2f, 0x8d, 0xf6, 0x01, 0x65, 0xfc, 0xe6, 0x67, 0xe3, 0xb5, 0x94, 0xe7,
+ 0xa2, 0x44, 0x77, 0xf1, 0x01, 0xf4, 0xe2, 0x2c, 0xbf, 0xfe, 0x8f, 0xc7,
+ 0xf6, 0x7f, 0xd8, 0x4f, 0xa3, 0x56, 0x56, 0xd0, 0x9c, 0xc4, 0x0e, 0x4e,
+ 0x5a, 0xc3, 0x7a, 0x84, 0xb3, 0x90, 0x11, 0x6d, 0xff, 0xf7, 0xb6, 0x16,
+ 0x36, 0x9a, 0x77, 0x39, 0xd9, 0x65, 0xff, 0xff, 0xde, 0x71, 0x93, 0xec,
+ 0xe7, 0xa3, 0x9b, 0x02, 0xfb, 0x25, 0x9b, 0xe1, 0x65, 0xf1, 0xa5, 0x92,
+ 0x59, 0x5e, 0x44, 0xd1, 0x3c, 0x5f, 0xfe, 0x2c, 0x37, 0xcf, 0x2f, 0x18,
+ 0xe2, 0x1d, 0x65, 0x41, 0xf7, 0x61, 0x15, 0x32, 0x6f, 0x1e, 0x8d, 0x62,
+ 0xfd, 0xad, 0x46, 0xfe, 0x2c, 0xbf, 0xf3, 0x6b, 0x67, 0x0b, 0x0f, 0x1d,
+ 0xac, 0xbf, 0xc1, 0xfb, 0x3e, 0xf7, 0x92, 0xcb, 0xf9, 0xf7, 0x8f, 0x08,
+ 0xd5, 0x96, 0x82, 0x3e, 0x31, 0x0d, 0x2f, 0xff, 0xfe, 0x04, 0x17, 0x6f,
+ 0xf7, 0xe8, 0x1b, 0x30, 0x9a, 0x03, 0xef, 0x42, 0xcb, 0xff, 0x10, 0x65,
+ 0xb3, 0x18, 0xa0, 0xeb, 0x2f, 0xee, 0x49, 0xbb, 0x7d, 0x2c, 0xbc, 0xef,
+ 0xda, 0xa2, 0xa1, 0x5f, 0xfe, 0x6d, 0xf8, 0xc5, 0x9a, 0x8e, 0xe3, 0x4b,
+ 0x2c, 0x75, 0x97, 0xb0, 0x3f, 0x23, 0xda, 0x0a, 0x4d, 0x42, 0x38, 0xfb,
+ 0x2e, 0xd4, 0x20, 0xef, 0xe8, 0x9a, 0x41, 0xea, 0x4b, 0x2f, 0xf8, 0x1c,
+ 0xd9, 0xc0, 0x3e, 0x4c, 0xb2, 0xfe, 0xdd, 0x72, 0x18, 0x9d, 0x2c, 0xa6,
+ 0x3e, 0xe7, 0x3c, 0xbf, 0x83, 0xdb, 0x1a, 0xfd, 0xac, 0xbe, 0xd7, 0x61,
+ 0x02, 0xcb, 0xfb, 0x09, 0xf5, 0xa6, 0x59, 0x6c, 0x63, 0xcf, 0xf1, 0x25,
+ 0x49, 0x71, 0x23, 0x0a, 0x4d, 0x2a, 0xee, 0x14, 0x7d, 0x13, 0xb3, 0x96,
+ 0xa3, 0x21, 0x39, 0xaf, 0xa1, 0x3c, 0x44, 0x1c, 0x7f, 0xbd, 0xb8, 0xf0,
+ 0xb2, 0xd8, 0xb2, 0xff, 0xf9, 0x8f, 0x1d, 0xec, 0xef, 0xcd, 0xbb, 0x07,
+ 0x85, 0x97, 0xff, 0x05, 0xe7, 0xe6, 0x37, 0x7d, 0xe6, 0xf5, 0x95, 0x24,
+ 0x56, 0xf8, 0x40, 0x95, 0x6f, 0xfa, 0x5f, 0x6d, 0x3f, 0x6c, 0x4b, 0x2f,
+ 0x03, 0x98, 0xb2, 0xff, 0x70, 0x33, 0x38, 0xde, 0x65, 0x97, 0xff, 0xf7,
+ 0x0c, 0x7d, 0xde, 0x36, 0xa6, 0xe4, 0x1d, 0xfa, 0xfa, 0xcb, 0xfa, 0x3b,
+ 0x62, 0x89, 0x2c, 0xbf, 0xed, 0x90, 0xc5, 0x87, 0xd4, 0x2c, 0xbd, 0xa6,
+ 0xe9, 0x65, 0x49, 0x33, 0x3e, 0x87, 0x26, 0x35, 0x3b, 0x0f, 0x0b, 0x3e,
+ 0x71, 0x7e, 0x29, 0xc1, 0x02, 0x2c, 0xbf, 0xa5, 0xb9, 0x1f, 0x82, 0x59,
+ 0x68, 0xc3, 0xd8, 0xdd, 0x29, 0xbf, 0x48, 0xa0, 0xe6, 0xac, 0xbf, 0xf8,
+ 0xf9, 0xa2, 0xc6, 0xde, 0xda, 0x75, 0x95, 0xd1, 0xf5, 0xb9, 0x45, 0xff,
+ 0xf9, 0xb5, 0xb3, 0x3e, 0x18, 0xc9, 0xfd, 0x8d, 0x25, 0x97, 0xfe, 0x2c,
+ 0x9b, 0xfe, 0xcd, 0x37, 0x16, 0x5f, 0xf8, 0xfb, 0x0e, 0xff, 0xd9, 0xef,
+ 0xe9, 0x65, 0xfe, 0x83, 0xe3, 0x68, 0x3b, 0x8b, 0x29, 0xcf, 0xe4, 0x28,
+ 0x95, 0xe4, 0x6c, 0x14, 0x2d, 0xef, 0xdd, 0x13, 0x1d, 0x96, 0x5e, 0x9f,
+ 0x0c, 0x59, 0x7b, 0x35, 0xe5, 0x96, 0x81, 0x41, 0xba, 0xec, 0x7a, 0xfb,
+ 0x6c, 0x3b, 0xb0, 0xb2, 0xa1, 0x51, 0x58, 0xc8, 0xb2, 0x32, 0xe6, 0x27,
+ 0xd3, 0x08, 0x4a, 0xef, 0xef, 0xbf, 0xb6, 0x0e, 0x16, 0x5f, 0xf7, 0xf8,
+ 0x27, 0x1f, 0xa9, 0x62, 0xcb, 0xfc, 0xf2, 0xd9, 0xc0, 0x81, 0xd6, 0x5f,
+ 0x47, 0xa2, 0x75, 0x96, 0x61, 0x9e, 0xbf, 0x8d, 0x6a, 0x11, 0xd1, 0x85,
+ 0xe1, 0x84, 0x95, 0xfb, 0x8d, 0xec, 0x1a, 0xcb, 0xf4, 0xa3, 0xf9, 0x3a,
+ 0xca, 0xdc, 0x3c, 0xfd, 0x13, 0xde, 0xeb, 0xf8, 0xb2, 0xfe, 0xe3, 0x17,
+ 0x7e, 0x85, 0x95, 0x87, 0xdf, 0xa2, 0x5f, 0x8e, 0xdf, 0x36, 0xdb, 0x79,
+ 0x65, 0xff, 0xb3, 0xfc, 0xd6, 0x4d, 0xe6, 0x35, 0x65, 0xff, 0xfc, 0xdc,
+ 0x06, 0x48, 0xa0, 0x0f, 0xee, 0xa5, 0x9f, 0x59, 0x7f, 0xf7, 0x6d, 0xad,
+ 0x3c, 0x9f, 0xb0, 0xf4, 0xb2, 0xff, 0xb0, 0xdc, 0x3b, 0x6d, 0xc1, 0xd6,
+ 0x56, 0x91, 0xb9, 0xe5, 0xa2, 0x47, 0xbf, 0xed, 0x8e, 0x59, 0xbb, 0xb3,
+ 0xc1, 0x59, 0x7e, 0x31, 0xb5, 0x86, 0xac, 0xa8, 0x54, 0x0b, 0x85, 0xcc,
+ 0x48, 0xf1, 0x8e, 0x04, 0xbc, 0x43, 0xfb, 0xfe, 0xfb, 0x71, 0x82, 0x2b,
+ 0x1c, 0x2c, 0xba, 0x3a, 0x59, 0x7f, 0x47, 0xf0, 0x9f, 0x71, 0x65, 0xf8,
+ 0x02, 0x89, 0xf0, 0xc5, 0x94, 0xc8, 0xaf, 0xd1, 0xe0, 0x05, 0xc8, 0xba,
+ 0xe1, 0x40, 0xa5, 0x65, 0xff, 0x9c, 0xbb, 0xfe, 0x7b, 0xff, 0x0a, 0xca,
+ 0x63, 0xde, 0x08, 0xfd, 0xfd, 0x1a, 0x9e, 0x35, 0x3a, 0xcb, 0xe0, 0xcf,
+ 0x12, 0x59, 0x52, 0x3d, 0x2e, 0x17, 0xdf, 0xfb, 0x98, 0x5f, 0xe6, 0x49,
+ 0xbc, 0xb2, 0xfe, 0xe6, 0x6f, 0x28, 0xe9, 0x65, 0xc1, 0xf2, 0xca, 0xe2,
+ 0x20, 0xfe, 0x7b, 0xb6, 0x5f, 0x7f, 0xfd, 0x00, 0xc2, 0xd8, 0xff, 0xd9,
+ 0xec, 0x03, 0xac, 0xb8, 0xa7, 0x59, 0x50, 0x9a, 0x06, 0x42, 0x95, 0x8c,
+ 0xc9, 0x46, 0xff, 0x0f, 0x0f, 0xb3, 0x8f, 0xe5, 0x97, 0x83, 0x1c, 0x59,
+ 0x4c, 0x7a, 0x3e, 0x35, 0xbb, 0x92, 0x59, 0x7f, 0xfb, 0xd0, 0x72, 0x73,
+ 0x4b, 0x01, 0xd0, 0x16, 0x5f, 0xdb, 0xdc, 0xfe, 0x31, 0xd6, 0x5f, 0xff,
+ 0xe6, 0x8f, 0xbf, 0x85, 0xf3, 0xd8, 0x5f, 0xd8, 0x09, 0x71, 0x65, 0xff,
+ 0x31, 0x36, 0x77, 0x1f, 0xe2, 0xca, 0x92, 0x62, 0xac, 0x94, 0x46, 0x1f,
+ 0x64, 0xbd, 0xc0, 0xe9, 0x65, 0xe6, 0xf3, 0x2c, 0xbf, 0xb4, 0xe4, 0x00,
+ 0x42, 0xca, 0x84, 0xfb, 0x67, 0x21, 0xc8, 0xcb, 0x18, 0xf1, 0xc7, 0x44,
+ 0x1b, 0xbf, 0xc5, 0x9f, 0xe0, 0x1b, 0xa5, 0x97, 0xe2, 0xc1, 0x93, 0xac,
+ 0xa9, 0x1e, 0xc6, 0x19, 0xdd, 0x9b, 0xd6, 0x5f, 0xa0, 0xef, 0xd7, 0xd6,
+ 0x5d, 0x93, 0xac, 0xbf, 0xf8, 0x7c, 0xcd, 0x16, 0x03, 0x99, 0xa5, 0x95,
+ 0xe4, 0x4d, 0x70, 0x63, 0xe5, 0x01, 0x17, 0xbf, 0x67, 0x61, 0x79, 0xd6,
+ 0x57, 0x8f, 0x98, 0x8f, 0x6f, 0xff, 0xb4, 0x41, 0xe8, 0xb1, 0xb5, 0xdf,
+ 0xa3, 0x8b, 0x2f, 0xff, 0xee, 0xdf, 0xd9, 0x28, 0xd4, 0x03, 0x50, 0x23,
+ 0x92, 0xca, 0x84, 0x55, 0x62, 0x85, 0xf4, 0xee, 0x5b, 0xd6, 0x5f, 0xc0,
+ 0xc2, 0xf0, 0x49, 0x65, 0x61, 0xe8, 0x39, 0x25, 0xff, 0xff, 0xfd, 0x2d,
+ 0x9f, 0xf3, 0x47, 0x36, 0x60, 0x7b, 0x8d, 0xfb, 0x33, 0x5a, 0xcd, 0xe1,
+ 0x7f, 0x2c, 0xbe, 0xfe, 0xd0, 0x29, 0xda, 0x96, 0x54, 0x23, 0x13, 0x21,
+ 0x27, 0x7d, 0xe2, 0x7d, 0xd5, 0x97, 0xc7, 0x6d, 0xd8, 0x59, 0x50, 0xae,
+ 0xbf, 0x23, 0x21, 0xf4, 0x32, 0xc9, 0xc7, 0x90, 0xe4, 0xf9, 0x30, 0x49,
+ 0x2f, 0xf3, 0xf5, 0xc6, 0x3c, 0x76, 0xb2, 0xf6, 0x67, 0x16, 0x5d, 0x1a,
+ 0x59, 0x69, 0xc6, 0x6c, 0x5c, 0x6e, 0xf0, 0x9b, 0x6e, 0xb2, 0xff, 0xfc,
+ 0xd3, 0xf9, 0xdb, 0xf1, 0xe6, 0xff, 0x30, 0x6b, 0x2f, 0xfb, 0x66, 0x79,
+ 0x9f, 0xfe, 0x85, 0x95, 0xb8, 0x88, 0xd2, 0x54, 0xaf, 0x23, 0x49, 0xe1,
+ 0x5b, 0x4e, 0x99, 0x00, 0x61, 0xf3, 0x7f, 0xed, 0xef, 0x2c, 0x21, 0x94,
+ 0x49, 0x65, 0xd3, 0xc2, 0xca, 0xc3, 0xd5, 0x09, 0xf5, 0xf6, 0x78, 0xf0,
+ 0xb2, 0x88, 0xf0, 0xb8, 0x43, 0x79, 0x8c, 0x99, 0x65, 0xff, 0x3f, 0x9b,
+ 0x9c, 0x0b, 0x81, 0x65, 0x0c, 0xf5, 0x9c, 0x7a, 0xc2, 0xf6, 0xb7, 0x47,
+ 0x2d, 0xb5, 0x11, 0x8a, 0x4f, 0xf6, 0x83, 0x01, 0x40, 0xbc, 0x46, 0xcd,
+ 0x3c, 0x26, 0xe5, 0x0b, 0x81, 0xc7, 0x8f, 0x93, 0xc5, 0x86, 0xc2, 0xaf,
+ 0xb8, 0x65, 0xf4, 0x5e, 0xd1, 0xb5, 0xcd, 0x0b, 0x2d, 0x4a, 0xbf, 0x3c,
+ 0x68, 0x9e, 0x95, 0xec, 0xf1, 0x85, 0x82, 0x13, 0x25, 0x1d, 0x9f, 0x25,
+ 0x3e, 0xfe, 0x71, 0x8c, 0x2e, 0x7b, 0x71, 0xc2, 0x89, 0x0b, 0xfd, 0xd7,
+ 0x7b, 0xc4, 0xc6, 0x2c, 0xbe, 0xed, 0xdf, 0xb5, 0x45, 0x50, 0xbf, 0xda,
+ 0x8d, 0xfd, 0x4b, 0x3e, 0xb2, 0xb4, 0x7c, 0xc1, 0x30, 0xbf, 0xc6, 0xc7,
+ 0xf9, 0xbf, 0x06, 0xb2, 0xff, 0xcf, 0x21, 0x79, 0xae, 0xdd, 0xfb, 0x54,
+ 0x4d, 0x6b, 0xfe, 0xf4, 0x1f, 0x9c, 0x72, 0xed, 0x65, 0xf4, 0x6a, 0x3e,
+ 0xb2, 0xe7, 0xfa, 0xca, 0x19, 0xb7, 0x39, 0x0d, 0xff, 0x3f, 0x5c, 0x26,
+ 0x81, 0x0e, 0xb2, 0xff, 0x13, 0xff, 0x93, 0x79, 0x96, 0x58, 0x5c, 0x95,
+ 0x12, 0xe4, 0x20, 0x8d, 0x22, 0x39, 0xb7, 0x93, 0x9d, 0xc0, 0x04, 0x22,
+ 0x1c, 0xdf, 0xff, 0x6e, 0x30, 0xf0, 0xfb, 0x3f, 0x9b, 0x8d, 0xbf, 0x8b,
+ 0x2f, 0xda, 0xed, 0xdf, 0xb5, 0x45, 0x58, 0xbd, 0xa8, 0x3a, 0xcb, 0xfe,
+ 0x89, 0x46, 0xa7, 0x8d, 0x4e, 0xb2, 0xff, 0xe8, 0x21, 0xc6, 0xf9, 0x9b,
+ 0x79, 0x01, 0x65, 0x85, 0xc2, 0x65, 0x98, 0xb3, 0xa3, 0x62, 0x1c, 0xf9,
+ 0xd5, 0xf1, 0x60, 0x45, 0x6b, 0x2f, 0xee, 0xbf, 0x1e, 0x7d, 0xc5, 0x97,
+ 0xe7, 0xf6, 0x6b, 0x16, 0x54, 0x1e, 0xbb, 0x98, 0xdf, 0xda, 0x0c, 0xdc,
+ 0x8f, 0xac, 0xa8, 0x46, 0x5f, 0x9f, 0x02, 0x41, 0x7f, 0xf0, 0x30, 0x85,
+ 0xc8, 0x1c, 0x9d, 0xc9, 0x65, 0x0b, 0x3f, 0x58, 0x2f, 0xbf, 0x86, 0xc1,
+ 0xfe, 0x71, 0x65, 0xfc, 0xc7, 0x6f, 0xfa, 0x16, 0x5f, 0x44, 0xd1, 0xd2,
+ 0xca, 0xf1, 0xe7, 0xf0, 0xb2, 0xfd, 0xae, 0xdd, 0xfb, 0x54, 0x48, 0x8b,
+ 0xef, 0xe9, 0xba, 0x59, 0x7f, 0xec, 0xdd, 0x69, 0xfa, 0xcd, 0x69, 0xd6,
+ 0x5d, 0x21, 0x78, 0x89, 0xb6, 0x36, 0xde, 0x47, 0x7f, 0x4f, 0x1a, 0xf3,
+ 0xb2, 0xcb, 0x0b, 0xda, 0xd3, 0xa4, 0xc7, 0xc7, 0x85, 0xef, 0x0f, 0xaf,
+ 0xda, 0xed, 0xdf, 0xb5, 0x45, 0xa4, 0xbf, 0xf3, 0xc8, 0x5e, 0x6b, 0xb7,
+ 0x7e, 0xd5, 0x13, 0xea, 0xc2, 0xf1, 0x10, 0x87, 0x36, 0xbf, 0xfc, 0x2c,
+ 0xef, 0x21, 0x79, 0xae, 0xdd, 0xfb, 0x54, 0x50, 0x8b, 0xff, 0xb0, 0xc1,
+ 0x7f, 0x35, 0xf8, 0xdf, 0x85, 0x97, 0xef, 0x87, 0xb7, 0xe2, 0xcb, 0xa3,
+ 0x4b, 0x2f, 0xfe, 0x83, 0x87, 0x5d, 0xbb, 0x0e, 0x26, 0x59, 0x66, 0x9c,
+ 0xf6, 0xe6, 0x16, 0xa3, 0xa2, 0xb7, 0xd0, 0x84, 0xbf, 0x6b, 0xb7, 0x7e,
+ 0xd5, 0x14, 0x7a, 0xe1, 0xe2, 0xcb, 0xe6, 0xc0, 0x71, 0x65, 0xcf, 0xda,
+ 0xcb, 0x60, 0xcd, 0xc6, 0xe9, 0x0d, 0xff, 0x44, 0xa3, 0x53, 0xc6, 0xa7,
+ 0x59, 0x7f, 0xff, 0xff, 0x84, 0x6d, 0x4d, 0x1e, 0xd6, 0x79, 0xc4, 0xe6,
+ 0x1a, 0xe4, 0x08, 0x28, 0x9b, 0xd0, 0xb2, 0xfc, 0xfc, 0x6f, 0xc2, 0xcb,
+ 0xfe, 0x89, 0xa0, 0xa2, 0x6f, 0x42, 0xca, 0x84, 0x76, 0x9b, 0x08, 0xf2,
+ 0x26, 0xbe, 0x3c, 0xf8, 0x62, 0xcb, 0xff, 0xf0, 0xfd, 0x02, 0x0b, 0xf9,
+ 0x38, 0x39, 0xc8, 0x02, 0x4a, 0x83, 0xfc, 0xc2, 0x4b, 0xcf, 0x21, 0x70,
+ 0xab, 0x33, 0x0a, 0x26, 0x36, 0xd2, 0x71, 0x14, 0xfe, 0x32, 0x7d, 0xb8,
+ 0x58, 0x5f, 0xfd, 0x9e, 0x17, 0xf3, 0x5f, 0x8d, 0xf8, 0x59, 0x61, 0x73,
+ 0xae, 0x45, 0x9e, 0x5e, 0x07, 0xe1, 0x0b, 0x50, 0xf8, 0x6b, 0x13, 0xd3,
+ 0x3e, 0xa4, 0xe7, 0x92, 0xb1, 0x8d, 0xb4, 0x79, 0x9d, 0xce, 0x15, 0xf5,
+ 0x1d, 0x63, 0x47, 0x21, 0x34, 0x78, 0xfe, 0x86, 0x90, 0x0a, 0xbf, 0x39,
+ 0xcf, 0x7f, 0xfc, 0x67, 0x7b, 0x50, 0xa4, 0x02, 0xbd, 0x6d, 0x1b, 0x36,
+ 0x7b, 0x6d, 0x65, 0xff, 0xff, 0xb7, 0x7e, 0x28, 0x19, 0xc5, 0x04, 0xc2,
+ 0xab, 0xe2, 0xbd, 0x6d, 0x1b, 0x36, 0x7b, 0x6d, 0x65, 0x79, 0x1f, 0xc6,
+ 0x37, 0x5f, 0xfd, 0xe8, 0x6d, 0x30, 0xaf, 0xbf, 0x41, 0x8b, 0x2f, 0xfd,
+ 0xc1, 0x5b, 0x1b, 0xb3, 0x67, 0xb6, 0xc5, 0xc1, 0xf6, 0xf6, 0x49, 0x7f,
+ 0xff, 0xff, 0xb7, 0x45, 0x6c, 0x6e, 0xcd, 0x9e, 0xdb, 0x17, 0x1e, 0x33,
+ 0xbd, 0xa8, 0x52, 0x01, 0x5e, 0xb6, 0x8d, 0x9b, 0x3d, 0xb6, 0xb2, 0xfd,
+ 0xae, 0xdd, 0xfb, 0x54, 0x44, 0x4b, 0xfd, 0xc0, 0xc4, 0xdf, 0x6d, 0xeb,
+ 0x2c, 0x2f, 0x0f, 0xb2, 0x63, 0x6b, 0xfb, 0x35, 0xdb, 0xbf, 0x6a, 0x88,
+ 0xad, 0x7f, 0xdb, 0x82, 0xf3, 0x5d, 0xbb, 0xf6, 0xa8, 0xae, 0x14, 0x2d,
+ 0x10, 0xee, 0x77, 0x7d, 0xe7, 0xd3, 0x2c, 0xbf, 0x7c, 0x02, 0x14, 0x96,
+ 0x5f, 0x81, 0x05, 0xd8, 0xb8, 0x3c, 0xa7, 0x21, 0xba, 0x6d, 0xc5, 0x97,
+ 0xf1, 0x37, 0x7f, 0x89, 0x2c, 0xb0, 0xb9, 0xcf, 0x23, 0x43, 0x76, 0x6e,
+ 0x91, 0x64, 0x08, 0x43, 0xdf, 0xe1, 0x4e, 0xd4, 0x51, 0xdb, 0xf4, 0xb2,
+ 0xfb, 0x3c, 0xff, 0x59, 0x7f, 0xb1, 0xb4, 0x00, 0x07, 0x8b, 0x2c, 0x29,
+ 0x23, 0xd4, 0xe1, 0x0d, 0xff, 0xff, 0xfe, 0xda, 0xb6, 0xb1, 0x4c, 0x73,
+ 0xd8, 0x6e, 0x0c, 0xb2, 0x76, 0x97, 0x20, 0x71, 0xe2, 0x7d, 0xc5, 0x97,
+ 0xf6, 0xa3, 0xee, 0x58, 0xb2, 0xff, 0xfd, 0xc6, 0xf3, 0xb4, 0x98, 0xbe,
+ 0x1f, 0x6b, 0x16, 0x53, 0x1f, 0xf7, 0xca, 0xef, 0xe8, 0x07, 0x3e, 0x50,
+ 0xb2, 0xff, 0x3b, 0x9a, 0x63, 0xeb, 0x8b, 0x2f, 0xff, 0xde, 0xc2, 0xc3,
+ 0x7c, 0xf2, 0xf1, 0x8e, 0x21, 0xd6, 0x5f, 0x76, 0xef, 0xda, 0xa2, 0x9e,
+ 0x5f, 0xff, 0x9b, 0x5e, 0x78, 0xde, 0x59, 0xcc, 0x26, 0x3a, 0xcb, 0xff,
+ 0x14, 0x6f, 0x6f, 0xca, 0x30, 0x96, 0x54, 0x93, 0x17, 0xd2, 0xbf, 0x8c,
+ 0x3e, 0xa7, 0x7f, 0x86, 0x0d, 0x91, 0xb9, 0x12, 0x59, 0x7f, 0x8e, 0xc3,
+ 0x0b, 0xea, 0x4b, 0x2e, 0x3b, 0x2c, 0xa8, 0x3c, 0x9e, 0xcc, 0xef, 0xff,
+ 0xe8, 0xff, 0x02, 0x7e, 0xd8, 0x11, 0x9e, 0x60, 0xf6, 0xb2, 0xe6, 0xe2,
+ 0xcb, 0xfa, 0x0f, 0xc8, 0x69, 0xd6, 0x54, 0x91, 0x3f, 0x8b, 0x9f, 0x16,
+ 0xbf, 0xff, 0x9f, 0x4f, 0xee, 0xa5, 0x9f, 0xc2, 0x0f, 0xc2, 0x6a, 0xcb,
+ 0xe9, 0x46, 0x4e, 0xb2, 0xff, 0xfd, 0xa0, 0xeb, 0x50, 0x58, 0x6b, 0x7b,
+ 0xd8, 0x22, 0xcb, 0x0d, 0x65, 0xed, 0x37, 0x4b, 0x2b, 0xb4, 0xc0, 0xba,
+ 0x5c, 0xd1, 0x11, 0xd5, 0xbe, 0x23, 0x79, 0x8b, 0xeb, 0x2f, 0xfe, 0x79,
+ 0x0b, 0x71, 0xe4, 0xbd, 0x1d, 0xac, 0xbf, 0x86, 0x21, 0x09, 0xd7, 0x16,
+ 0x5f, 0xf6, 0x9e, 0x71, 0x85, 0xf5, 0x25, 0x95, 0x07, 0xd6, 0xc6, 0x37,
+ 0xfd, 0x84, 0x08, 0x3b, 0x6a, 0x4b, 0x2f, 0xf3, 0x71, 0x82, 0x2b, 0x1c,
+ 0x2c, 0xa9, 0x1f, 0x6f, 0xcd, 0xec, 0xeb, 0x2f, 0xff, 0x8f, 0x8d, 0xf0,
+ 0xfe, 0x24, 0xc3, 0xc1, 0xac, 0xa6, 0x44, 0x07, 0x88, 0x80, 0x21, 0x7e,
+ 0xd4, 0xf1, 0xa9, 0xd6, 0x5f, 0x98, 0xbe, 0x21, 0xd6, 0x54, 0x1e, 0x90,
+ 0x0a, 0xaf, 0xf6, 0xa2, 0x3f, 0xc6, 0xde, 0xb2, 0xfe, 0x89, 0xdc, 0x6f,
+ 0xf5, 0x95, 0x24, 0x41, 0x1c, 0x87, 0x74, 0xd2, 0xfb, 0x61, 0x3c, 0x96,
+ 0x5f, 0x9f, 0x3c, 0xc7, 0x59, 0x5c, 0x3c, 0x9d, 0xe4, 0x75, 0x08, 0xa0,
+ 0xc7, 0xcb, 0xf9, 0xbe, 0xe6, 0xf9, 0x96, 0x5f, 0xf6, 0xf7, 0x3e, 0xc1,
+ 0xf9, 0x8e, 0xb2, 0xff, 0x8a, 0x0f, 0x12, 0x2c, 0x3a, 0xcb, 0xff, 0xc7,
+ 0x8d, 0x4f, 0x1d, 0x60, 0x45, 0x78, 0x35, 0x97, 0xdf, 0x94, 0x1a, 0xb2,
+ 0xa4, 0x98, 0x96, 0x16, 0xb1, 0xeb, 0x9b, 0x08, 0x9f, 0x7e, 0xef, 0x18,
+ 0xa6, 0x59, 0x7f, 0x8b, 0xbc, 0xdf, 0x9f, 0xe2, 0xcb, 0xf0, 0xc3, 0x1a,
+ 0x9d, 0x65, 0xce, 0x6a, 0xca, 0x83, 0xf5, 0xc3, 0x5d, 0x14, 0xdf, 0x9e,
+ 0x78, 0xd0, 0x56, 0x56, 0xd0, 0xcc, 0x58, 0x14, 0x42, 0x44, 0x54, 0x2b,
+ 0x88, 0xc7, 0x24, 0x42, 0x32, 0xcc, 0x8d, 0x2c, 0xd3, 0xee, 0xe1, 0x03,
+ 0xd4, 0x30, 0x5a, 0x33, 0x19, 0x93, 0x4e, 0x37, 0xe8, 0x58, 0xbc, 0x61,
+ 0xa5, 0x1d, 0x1f, 0x23, 0x33, 0xfa, 0x4e, 0xf8, 0x4e, 0xed, 0x96, 0xdf,
+ 0xfe, 0x79, 0x0b, 0x19, 0x39, 0x9c, 0xe4, 0x01, 0x65, 0xff, 0xe0, 0x00,
+ 0x3c, 0x16, 0x21, 0x39, 0xca, 0x16, 0x5f, 0xfc, 0x58, 0x07, 0x20, 0x0b,
+ 0x3b, 0x1d, 0x65, 0x69, 0x12, 0x1f, 0x4c, 0xbf, 0x3f, 0xbc, 0xd3, 0x2c,
+ 0xbf, 0xfb, 0x38, 0xc4, 0x02, 0xcf, 0xfb, 0x16, 0x5f, 0xf9, 0x88, 0x05,
+ 0x9f, 0xf6, 0x0b, 0xf1, 0xf4, 0x88, 0x51, 0x42, 0xd5, 0x8f, 0x0e, 0x36,
+ 0x06, 0x86, 0xe7, 0x21, 0x19, 0x6c, 0x59, 0x7e, 0x28, 0x08, 0xaf, 0x8b,
+ 0x2f, 0xe3, 0x74, 0xe3, 0x72, 0x59, 0x43, 0x3e, 0x8c, 0x10, 0x72, 0xbb,
+ 0xff, 0x98, 0x7a, 0x7e, 0x85, 0xeb, 0x51, 0x3a, 0xca, 0x16, 0x7e, 0xbe,
+ 0x2d, 0xb4, 0x2c, 0xbf, 0xb9, 0x1d, 0x94, 0x0d, 0x65, 0x0c, 0xde, 0xb0,
+ 0x85, 0xff, 0xf4, 0x6b, 0x24, 0xcf, 0xfc, 0x1b, 0x07, 0xb4, 0x97, 0x07,
+ 0xa5, 0x95, 0xe3, 0xe6, 0x24, 0xeb, 0x76, 0xb2, 0xfd, 0x12, 0x00, 0x64,
+ 0xb2, 0xfb, 0xb7, 0x7e, 0xd5, 0x15, 0x9a, 0xe8, 0x31, 0x65, 0x62, 0x20,
+ 0x66, 0x12, 0xd1, 0x46, 0xf3, 0x0b, 0xef, 0xb1, 0xf8, 0xb2, 0xda, 0x59,
+ 0x63, 0x56, 0x53, 0x1a, 0x3e, 0x08, 0xde, 0xe0, 0x7b, 0x59, 0x46, 0x9b,
+ 0xee, 0x10, 0x58, 0x45, 0x97, 0xb5, 0x1b, 0xd6, 0x54, 0x1b, 0x0e, 0x09,
+ 0x5f, 0xdb, 0xc8, 0xa3, 0x72, 0x65, 0x97, 0xe3, 0xc1, 0x4b, 0x8b, 0x2e,
+ 0x89, 0x96, 0x54, 0x1f, 0x84, 0xe6, 0x5a, 0x27, 0xbe, 0xff, 0x04, 0xe2,
+ 0xcb, 0xee, 0x72, 0x0c, 0x59, 0x67, 0x59, 0x58, 0x7a, 0xec, 0x49, 0xc2,
+ 0x3b, 0xa7, 0x65, 0x97, 0xfb, 0x93, 0x31, 0x7b, 0x3a, 0x59, 0x50, 0x79,
+ 0x78, 0x2f, 0x73, 0xfd, 0x65, 0xf0, 0x04, 0x29, 0x2c, 0xa1, 0x9b, 0x9f,
+ 0x8b, 0x5f, 0xff, 0x41, 0xff, 0x98, 0x5f, 0xe7, 0xb0, 0x0e, 0xb2, 0xff,
+ 0x1e, 0x3a, 0xe6, 0xa3, 0x7a, 0xcb, 0x9f, 0x8b, 0x2a, 0x0f, 0x30, 0x26,
+ 0xd7, 0xfa, 0x4c, 0x1d, 0xcd, 0xa0, 0x07, 0x59, 0x7e, 0x28, 0xf3, 0x62,
+ 0xca, 0xc3, 0xe1, 0x73, 0xcb, 0x32, 0xcb, 0xf6, 0x11, 0x3f, 0xd6, 0x70,
+ 0xb0, 0xbc, 0x19, 0x0d, 0x65, 0x78, 0xf4, 0x48, 0xd2, 0xfc, 0x5f, 0xf4,
+ 0x6f, 0x59, 0x79, 0xdc, 0xeb, 0x2f, 0xd9, 0x34, 0xe1, 0x02, 0xcb, 0xfb,
+ 0xf1, 0xa0, 0x44, 0xcb, 0x2c, 0x2e, 0x17, 0xa7, 0x47, 0x08, 0x6c, 0x85,
+ 0x17, 0x47, 0xed, 0x08, 0x39, 0x94, 0xb5, 0x09, 0x03, 0xc2, 0x1b, 0xcf,
+ 0x0e, 0xb2, 0x02, 0x12, 0x84, 0xcf, 0x21, 0x05, 0xf8, 0x40, 0x84, 0x87,
+ 0x79, 0x48, 0x83, 0x7b, 0xa5, 0x57, 0xf4, 0xb0, 0xe2, 0x46, 0xe2, 0xcb,
+ 0xfd, 0xf7, 0xd4, 0xf0, 0xc3, 0x59, 0x7f, 0x7f, 0x83, 0x68, 0x25, 0x94,
+ 0xc7, 0xbe, 0xe6, 0x77, 0xf4, 0x1e, 0x70, 0xea, 0x4b, 0x2f, 0xb5, 0x86,
+ 0x7d, 0x65, 0x78, 0xfc, 0xbe, 0x41, 0xbc, 0xbe, 0xff, 0x4f, 0xec, 0xef,
+ 0xd1, 0xa5, 0x97, 0xfd, 0x05, 0x2e, 0x1d, 0xc8, 0xd5, 0x95, 0x07, 0xdb,
+ 0xf3, 0x5b, 0xa0, 0x6b, 0x2f, 0xf8, 0x27, 0xce, 0xf5, 0xd3, 0x98, 0xb2,
+ 0xa4, 0x7e, 0x7c, 0x21, 0xf8, 0xb5, 0xfe, 0xd4, 0x1b, 0x84, 0xc6, 0xac,
+ 0xbf, 0xff, 0x60, 0xfd, 0x1c, 0xd9, 0x8d, 0xa6, 0x3c, 0x1a, 0xb2, 0xff,
+ 0xf4, 0x18, 0x21, 0xcb, 0x3a, 0xfc, 0x61, 0x8b, 0x2f, 0xdf, 0x62, 0xc3,
+ 0xac, 0xbc, 0xe4, 0x2c, 0x6a, 0xcf, 0x72, 0x30, 0x2e, 0xa3, 0x11, 0xd1,
+ 0x79, 0x19, 0x88, 0xad, 0xba, 0x99, 0x7f, 0xce, 0x60, 0xb1, 0xc1, 0xfa,
+ 0x85, 0x95, 0x24, 0x61, 0x94, 0x21, 0xef, 0xfc, 0xf2, 0x17, 0x9a, 0xed,
+ 0xdf, 0xb5, 0x44, 0x8a, 0xbf, 0xff, 0x7f, 0xd8, 0x42, 0xfe, 0xef, 0xd7,
+ 0x0d, 0x35, 0xd6, 0x5f, 0xf9, 0xfe, 0x2e, 0x1b, 0x4d, 0xf0, 0xac, 0xa1,
+ 0x68, 0xe6, 0x84, 0xe7, 0x59, 0xbf, 0xed, 0x69, 0x8c, 0xc9, 0x98, 0xeb,
+ 0x2f, 0xbb, 0x8f, 0x42, 0xca, 0x63, 0xdc, 0x23, 0xab, 0xf6, 0xbb, 0x77,
+ 0xed, 0x51, 0x64, 0xaa, 0x0f, 0x5b, 0x08, 0x2f, 0x98, 0xa5, 0xc5, 0x97,
+ 0xe8, 0xe7, 0xda, 0x75, 0x95, 0x39, 0xe4, 0x9a, 0x43, 0x7f, 0x83, 0x3f,
+ 0xa3, 0xfc, 0x65, 0x97, 0xf0, 0x46, 0xda, 0x7e, 0x2c, 0xb9, 0xbe, 0xb2,
+ 0xfd, 0xfe, 0x09, 0xc1, 0x78, 0x89, 0xbd, 0x12, 0x70, 0xd3, 0xe5, 0xb4,
+ 0x2d, 0x36, 0x1c, 0x8c, 0x12, 0xff, 0xfa, 0x0e, 0xe3, 0x17, 0xf8, 0xea,
+ 0x53, 0xe1, 0x8b, 0x2f, 0xb0, 0xce, 0x79, 0x65, 0xf4, 0x1d, 0x8c, 0x59,
+ 0x7f, 0x31, 0xe3, 0xc2, 0x0d, 0x65, 0x4c, 0x7a, 0x1b, 0xa4, 0x57, 0xf7,
+ 0x9b, 0x51, 0x2e, 0x2c, 0xbf, 0x8f, 0xf6, 0xf3, 0x9d, 0x65, 0xff, 0xe6,
+ 0xff, 0xb3, 0xf8, 0x51, 0xf8, 0x1a, 0xca, 0x83, 0xf4, 0x72, 0xdb, 0xfc,
+ 0xdf, 0x0e, 0x9f, 0x82, 0xe7, 0x4d, 0x6b, 0x1c, 0xfb, 0x26, 0xf4, 0x28,
+ 0x69, 0x95, 0x0e, 0x3c, 0x75, 0xd7, 0xff, 0xfb, 0xef, 0xd0, 0x05, 0x8c,
+ 0xa3, 0xa9, 0x7d, 0x88, 0x1c, 0x59, 0x7f, 0x66, 0xbb, 0x77, 0xed, 0x51,
+ 0x6c, 0x2f, 0xff, 0xde, 0xd8, 0x59, 0xaf, 0xf3, 0xd3, 0x6c, 0xd9, 0xed,
+ 0xb5, 0x97, 0xef, 0x3e, 0x98, 0xeb, 0x28, 0x52, 0x88, 0x8e, 0xd8, 0x6f,
+ 0xd9, 0xbf, 0x4f, 0xc5, 0x97, 0xb4, 0x1f, 0x2c, 0xbb, 0xe2, 0xe0, 0xfb,
+ 0x86, 0x51, 0xa2, 0x9a, 0x16, 0x9b, 0x6b, 0x46, 0x63, 0x7b, 0x39, 0x8b,
+ 0x2f, 0xbb, 0x77, 0xed, 0x51, 0x6d, 0xae, 0x7d, 0x2c, 0xb4, 0x96, 0x5b,
+ 0x93, 0x9a, 0x70, 0x8b, 0x56, 0x8f, 0xff, 0xea, 0xf7, 0xef, 0x7d, 0x80,
+ 0x15, 0x97, 0xff, 0xa2, 0x7f, 0xb0, 0xf0, 0xa4, 0xde, 0x0a, 0xca, 0x63,
+ 0xf1, 0xf1, 0x45, 0xff, 0x44, 0xa3, 0x53, 0xc6, 0xa7, 0x59, 0x7d, 0x13,
+ 0x71, 0x96, 0x54, 0x93, 0xaa, 0xc8, 0x4d, 0x4d, 0x09, 0x32, 0x21, 0xdd,
+ 0x3a, 0xbf, 0xf0, 0xf4, 0xc1, 0x9c, 0x5f, 0x35, 0xf5, 0x94, 0x2d, 0x13,
+ 0x58, 0xaf, 0x7b, 0xd9, 0x3a, 0xcb, 0xf9, 0xc7, 0x98, 0x46, 0xac, 0xbe,
+ 0xc2, 0x00, 0xb9, 0x8f, 0x24, 0xe3, 0xb7, 0x0a, 0x09, 0x65, 0xe1, 0x47,
+ 0x86, 0xb2, 0xf4, 0xfe, 0x65, 0x97, 0xfe, 0x14, 0x0a, 0x36, 0x97, 0xfd,
+ 0x85, 0x00, 0x59, 0x78, 0x54, 0x15, 0x62, 0xa2, 0xcb, 0xf7, 0xe3, 0xcf,
+ 0x32, 0xcb, 0xf1, 0x48, 0x61, 0x3a, 0xcb, 0xf8, 0xc1, 0x36, 0xdc, 0x80,
+ 0xb2, 0xa0, 0xf6, 0xb0, 0xa2, 0xfe, 0x61, 0x26, 0xe0, 0x7a, 0x59, 0x7e,
+ 0x1f, 0x7e, 0x0e, 0x96, 0x57, 0x8f, 0x6d, 0xcc, 0x6f, 0xfb, 0x35, 0xa8,
+ 0x93, 0xf4, 0x62, 0xcb, 0xee, 0xdd, 0xfb, 0x54, 0x5e, 0x0b, 0xf7, 0xfa,
+ 0xed, 0xb4, 0xb2, 0xff, 0xcc, 0x0e, 0x6c, 0xe0, 0x1f, 0x26, 0x59, 0x7f,
+ 0xe7, 0xfc, 0x6f, 0xd6, 0xb3, 0xae, 0x2c, 0xbf, 0xf9, 0xf4, 0x27, 0xdb,
+ 0xc5, 0x9f, 0xc5, 0x95, 0xa4, 0xc7, 0xce, 0x61, 0xe2, 0xa2, 0x41, 0xde,
+ 0x83, 0x7d, 0xf1, 0x55, 0x93, 0x2c, 0xba, 0x21, 0x65, 0x68, 0xdf, 0x7c,
+ 0xa6, 0xfe, 0x89, 0xca, 0x18, 0x6b, 0x2e, 0x7e, 0x2c, 0xbd, 0xb7, 0x9e,
+ 0x59, 0x40, 0x36, 0xbf, 0x16, 0xbf, 0x1e, 0x0a, 0x4e, 0xb2, 0xfe, 0x82,
+ 0xfe, 0xf7, 0xed, 0x65, 0xfd, 0x28, 0xdf, 0x1a, 0xe9, 0x65, 0xff, 0xfc,
+ 0xf3, 0xcd, 0x28, 0xd4, 0xff, 0x96, 0x6e, 0x39, 0x01, 0x65, 0x49, 0x17,
+ 0xf8, 0x5e, 0xe6, 0x17, 0xde, 0x2c, 0x99, 0x65, 0xfd, 0xf7, 0xf6, 0xc1,
+ 0xc2, 0xcb, 0xfe, 0x7f, 0xf2, 0x18, 0x78, 0x75, 0x95, 0x07, 0xcc, 0x45,
+ 0xf7, 0xe9, 0x33, 0x79, 0xd6, 0x5f, 0x16, 0x31, 0xab, 0x2f, 0xf8, 0xfd,
+ 0x4b, 0xf8, 0x5f, 0xe2, 0xca, 0xe9, 0x10, 0x27, 0x26, 0x10, 0x86, 0xec,
+ 0x35, 0x65, 0xf9, 0xe5, 0xf6, 0x9d, 0x65, 0xff, 0xe6, 0xfc, 0x17, 0x6c,
+ 0x73, 0xb7, 0x02, 0xb2, 0xa1, 0x17, 0x58, 0x64, 0xc2, 0xee, 0x51, 0x76,
+ 0x1d, 0x65, 0xf9, 0xbc, 0x36, 0xe2, 0xcb, 0x34, 0xe6, 0xf6, 0x42, 0xd7,
+ 0xec, 0x20, 0x6e, 0xc2, 0xcb, 0x9f, 0x8b, 0x2f, 0x05, 0xf8, 0xb2, 0xbe,
+ 0x6c, 0x84, 0x16, 0xbf, 0x4d, 0xa6, 0x9c, 0xeb, 0x2a, 0x0f, 0x33, 0x08,
+ 0xae, 0x98, 0x6b, 0x2f, 0xff, 0xff, 0x88, 0x2f, 0xcc, 0x2e, 0x73, 0x3c,
+ 0xdc, 0x0c, 0xfc, 0xf6, 0x75, 0xf8, 0x59, 0x7e, 0x6d, 0x3f, 0x46, 0x2c,
+ 0xbf, 0xf4, 0x77, 0xb3, 0x08, 0x32, 0xce, 0x2c, 0xa9, 0x23, 0x9a, 0x67,
+ 0xd3, 0x94, 0xdf, 0xef, 0x31, 0x86, 0xe9, 0xcc, 0x59, 0x7e, 0xdf, 0x03,
+ 0x3f, 0x16, 0x5f, 0xd9, 0xc0, 0xfe, 0x09, 0x65, 0xff, 0xff, 0x9d, 0xbe,
+ 0xe7, 0x72, 0x07, 0x7e, 0x6d, 0x48, 0x49, 0x61, 0x2c, 0xbf, 0xb0, 0x7e,
+ 0x8e, 0x6e, 0x2c, 0xbf, 0xa3, 0xae, 0xa4, 0xfd, 0x2c, 0xa1, 0xaa, 0x86,
+ 0xc8, 0x7f, 0x76, 0x62, 0xc6, 0xd3, 0x15, 0x78, 0xb0, 0x9a, 0xc2, 0x61,
+ 0x7f, 0x9c, 0x81, 0xfd, 0xbc, 0xf2, 0xcb, 0xfe, 0xf3, 0xc8, 0xed, 0x1a,
+ 0x92, 0xcb, 0x66, 0xe1, 0xf6, 0xf8, 0xd6, 0xe3, 0xf1, 0x65, 0xf4, 0x14,
+ 0xb7, 0x16, 0x5f, 0xfc, 0x07, 0x20, 0x16, 0x6f, 0xf6, 0x0d, 0x65, 0xff,
+ 0xce, 0x0c, 0x1e, 0x79, 0xb5, 0xe7, 0x59, 0x5d, 0x22, 0x1b, 0x88, 0x97,
+ 0xff, 0x33, 0x83, 0xed, 0xcf, 0x41, 0x7d, 0x65, 0xf6, 0x7c, 0xce, 0xd6,
+ 0x5d, 0x00, 0x59, 0x52, 0x4e, 0x2f, 0x0a, 0x8d, 0x17, 0x68, 0x55, 0x78,
+ 0x93, 0x88, 0x5f, 0x24, 0xbf, 0xcf, 0xe7, 0x10, 0xf9, 0xc5, 0x96, 0xed,
+ 0x65, 0xdd, 0xc9, 0x65, 0x76, 0x6a, 0xbe, 0x25, 0x5b, 0x5b, 0x3a, 0xb0,
+ 0x52, 0x34, 0x28, 0x21, 0x15, 0x07, 0x45, 0x5a, 0x64, 0x16, 0xcf, 0x08,
+ 0x29, 0x3d, 0x8c, 0x87, 0x23, 0x59, 0x36, 0x11, 0x5d, 0x90, 0xf4, 0xc2,
+ 0xc4, 0x33, 0x43, 0x97, 0x45, 0xc7, 0x84, 0x47, 0xa3, 0x5b, 0x77, 0x60,
+ 0x13, 0x94, 0x29, 0xf9, 0x2a, 0x9b, 0xf2, 0x9b, 0xf7, 0xb4, 0xed, 0xae,
+ 0xde, 0xfc, 0x0d, 0x65, 0xf0, 0x1f, 0x5c, 0x59, 0x77, 0x42, 0xe0, 0xdf,
+ 0x60, 0xe5, 0xfe, 0x00, 0xb9, 0xa5, 0x05, 0xf5, 0x94, 0x2d, 0x52, 0x24,
+ 0x47, 0xc1, 0xa2, 0xeb, 0xe2, 0x18, 0x9d, 0x2c, 0xbb, 0x3a, 0x59, 0x7c,
+ 0xfc, 0x0c, 0xeb, 0x29, 0x8d, 0xd6, 0x85, 0xef, 0xda, 0xed, 0xdf, 0xb5,
+ 0x45, 0xe8, 0xbf, 0x67, 0xca, 0x27, 0x59, 0x7f, 0xe7, 0x6f, 0x87, 0x4f,
+ 0xbf, 0x06, 0xb2, 0xf0, 0xc3, 0xc5, 0x97, 0xe8, 0x3b, 0xfa, 0x16, 0x5e,
+ 0x3b, 0x7d, 0x65, 0xff, 0x3f, 0xe5, 0x06, 0xfd, 0xa7, 0x59, 0x5a, 0x3f,
+ 0xc3, 0x93, 0x10, 0xe5, 0xfb, 0x0f, 0xe7, 0x1a, 0xca, 0x85, 0x41, 0x03,
+ 0x5e, 0xc2, 0x0d, 0x1b, 0x78, 0x9d, 0xcf, 0xc4, 0x84, 0xce, 0xe9, 0x75,
+ 0xff, 0xd8, 0x3f, 0x61, 0xce, 0xf2, 0xc2, 0x59, 0x78, 0x30, 0x05, 0x97,
+ 0xdb, 0xf0, 0x85, 0x8c, 0xf7, 0xb4, 0x85, 0x7f, 0x85, 0xff, 0x26, 0x93,
+ 0x8d, 0x65, 0x31, 0xf9, 0x78, 0xf2, 0x85, 0xa6, 0xd5, 0x91, 0xa4, 0xd6,
+ 0xd3, 0x77, 0xf8, 0xe2, 0xad, 0x96, 0x23, 0x2b, 0x9e, 0x16, 0x32, 0x8c,
+ 0x83, 0x29, 0xf4, 0x9d, 0xc6, 0x5a, 0xd3, 0xdf, 0xd3, 0x4e, 0x94, 0xea,
+ 0x30, 0xd3, 0xca, 0x43, 0xf4, 0xa4, 0x77, 0x29, 0x04, 0x7a, 0x25, 0x29,
+ 0xbf, 0x8d, 0xa1, 0xac, 0x4a, 0xcc, 0x97, 0x57, 0x78, 0xbf, 0xc5, 0x97,
+ 0x1c, 0xeb, 0x2d, 0xe5, 0x95, 0xb5, 0x1a, 0x80, 0x8b, 0xdf, 0xfc, 0x18,
+ 0x98, 0xb3, 0x7b, 0x9c, 0xec, 0xb2, 0xfb, 0x3c, 0xff, 0x59, 0x7f, 0xb1,
+ 0xb4, 0x00, 0x07, 0x8b, 0x2c, 0x29, 0x35, 0x13, 0x24, 0x8b, 0xc2, 0x1b,
+ 0xff, 0xdf, 0xe0, 0x63, 0x99, 0xf6, 0x3b, 0xc9, 0x65, 0xe8, 0xea, 0x75,
+ 0x94, 0x47, 0xcf, 0xf4, 0x9b, 0xe6, 0xdb, 0x83, 0xac, 0xbf, 0xef, 0xf3,
+ 0x3a, 0x97, 0x82, 0x6a, 0xcb, 0xdc, 0x89, 0x96, 0x53, 0x22, 0x78, 0xe4,
+ 0x24, 0x49, 0xc3, 0xcb, 0xc4, 0xfe, 0x59, 0x7b, 0x7c, 0x49, 0x65, 0xef,
+ 0x67, 0x16, 0x5f, 0xf1, 0x31, 0xbf, 0xeb, 0xb6, 0xf2, 0xcb, 0xdc, 0x89,
+ 0xd6, 0x54, 0x22, 0x48, 0x63, 0xd8, 0x39, 0xd1, 0xdd, 0xfe, 0xff, 0x99,
+ 0xc0, 0x08, 0x59, 0x7f, 0x67, 0x5d, 0x48, 0x33, 0xac, 0xbf, 0x9f, 0x52,
+ 0x20, 0xba, 0xcb, 0x98, 0xeb, 0x2b, 0x11, 0x4b, 0xa3, 0x20, 0x98, 0xee,
+ 0x96, 0x5f, 0x1c, 0x24, 0x35, 0x97, 0xb7, 0xbf, 0x4b, 0x2f, 0x1b, 0x06,
+ 0x2c, 0xbc, 0xef, 0xda, 0xa2, 0x23, 0x5f, 0x1b, 0xdb, 0xe9, 0x65, 0x1a,
+ 0x7d, 0x7d, 0x8f, 0x31, 0x4d, 0xf8, 0x51, 0xfe, 0x38, 0x16, 0x5f, 0x99,
+ 0xcf, 0x9a, 0x59, 0x7f, 0xc1, 0x7e, 0x8b, 0x27, 0x12, 0x4b, 0x2f, 0x76,
+ 0x21, 0xd6, 0x5f, 0xff, 0xf4, 0x4d, 0xf8, 0xe6, 0xa3, 0xed, 0xdb, 0x0f,
+ 0x61, 0xa4, 0xeb, 0x2a, 0x11, 0x10, 0x43, 0xf7, 0xff, 0x37, 0x3d, 0x86,
+ 0x9a, 0xfb, 0x07, 0xd2, 0xca, 0x9d, 0x52, 0xdb, 0x11, 0x6a, 0x11, 0x47,
+ 0x30, 0xf1, 0x67, 0x09, 0xbf, 0x0c, 0x3d, 0xe4, 0x37, 0xf3, 0xf5, 0xec,
+ 0x63, 0x16, 0x5d, 0x2f, 0x2c, 0xb0, 0xf4, 0x78, 0xae, 0x5d, 0x7f, 0xf7,
+ 0x39, 0x87, 0x2c, 0xdf, 0xb2, 0x36, 0xa5, 0x96, 0xf3, 0x1f, 0x98, 0x49,
+ 0xef, 0xf4, 0xfa, 0xcf, 0xfd, 0xbe, 0xb2, 0x96, 0x5f, 0xfd, 0xec, 0xf9,
+ 0x44, 0xdb, 0x0d, 0x27, 0x59, 0x70, 0x62, 0x63, 0xd1, 0xf8, 0x5d, 0x42,
+ 0x2c, 0xf9, 0x08, 0x5b, 0xc5, 0x1d, 0x2c, 0xa9, 0x1e, 0x18, 0xc9, 0xee,
+ 0x7f, 0x2c, 0xbf, 0xda, 0xce, 0x63, 0x94, 0xeb, 0x2f, 0x69, 0xba, 0x59,
+ 0x43, 0x3e, 0x5c, 0x16, 0xf9, 0x95, 0xfe, 0x08, 0xc4, 0xf7, 0x9e, 0x4b,
+ 0x2e, 0x19, 0xd6, 0x5f, 0x9e, 0x71, 0x18, 0x6b, 0x2f, 0xfe, 0xc3, 0x03,
+ 0x13, 0xfc, 0x71, 0xfe, 0x2c, 0xa9, 0x22, 0xef, 0x0d, 0x5c, 0x5c, 0x8a,
+ 0x6f, 0xff, 0x49, 0x8d, 0x35, 0xf9, 0x0d, 0x3b, 0xfd, 0x65, 0xff, 0xfc,
+ 0xed, 0xf8, 0xf1, 0x67, 0xfc, 0xde, 0xc6, 0x31, 0x65, 0x32, 0x28, 0xfc,
+ 0x97, 0x7f, 0xff, 0xfb, 0xff, 0x63, 0xe9, 0xb3, 0xa2, 0x0f, 0xe3, 0xdb,
+ 0x37, 0xb7, 0xe6, 0x85, 0x97, 0xfb, 0x18, 0x9b, 0x5a, 0xc5, 0x97, 0xfd,
+ 0x8e, 0x40, 0xd0, 0x60, 0x0b, 0x2a, 0x13, 0x05, 0xc2, 0x2e, 0x9f, 0x34,
+ 0x61, 0x7f, 0xfe, 0x3e, 0xe3, 0x3b, 0xcd, 0xff, 0x64, 0xbc, 0xdb, 0xd6,
+ 0x5f, 0xdd, 0x4b, 0x41, 0x80, 0x2c, 0xbf, 0x7e, 0x35, 0x00, 0x59, 0x70,
+ 0x87, 0x59, 0x7e, 0xcd, 0x4a, 0x0e, 0xb2, 0xa7, 0x37, 0xe7, 0x18, 0xa8,
+ 0x4c, 0x47, 0x16, 0x98, 0xbd, 0xd9, 0xae, 0x9c, 0xe9, 0x2e, 0x30, 0xc4,
+ 0x97, 0xfe, 0x17, 0xdf, 0x9a, 0x6f, 0x44, 0xe2, 0xc0, 0x6c, 0x4c, 0x18,
+ 0xbf, 0xdc, 0x2c, 0xfe, 0xde, 0x7d, 0x65, 0xf6, 0xf8, 0xfc, 0x2c, 0xbd,
+ 0xbd, 0xf4, 0xb2, 0xfb, 0x3c, 0x58, 0xb2, 0xb0, 0xdf, 0x70, 0x7a, 0xa4,
+ 0x98, 0x9e, 0x2e, 0xb1, 0xaf, 0xd8, 0x6d, 0xba, 0xb2, 0xfc, 0xe7, 0xce,
+ 0xbe, 0xb2, 0xf7, 0x1f, 0x71, 0x65, 0xfe, 0x72, 0xef, 0x61, 0x9f, 0xe2,
+ 0xca, 0x9d, 0x12, 0x58, 0x28, 0xc5, 0x01, 0x1f, 0xbd, 0x3c, 0x6e, 0x2c,
+ 0xbf, 0xfe, 0xf3, 0x1b, 0xc6, 0xc2, 0x00, 0xf4, 0xfd, 0xac, 0xbf, 0xe0,
+ 0x34, 0xdc, 0x6f, 0x31, 0xd6, 0x5f, 0xe8, 0xf6, 0x4d, 0x27, 0x9d, 0x65,
+ 0xff, 0xc5, 0x9d, 0x4b, 0x83, 0x6d, 0xf0, 0x35, 0x95, 0x3a, 0x64, 0x63,
+ 0x20, 0x02, 0x80, 0x4e, 0x77, 0x4d, 0x2f, 0xcd, 0xf8, 0xff, 0x16, 0x5f,
+ 0xe7, 0xeb, 0x8e, 0x41, 0xc5, 0x97, 0xcd, 0xa7, 0x02, 0xca, 0x91, 0xfd,
+ 0x00, 0x9f, 0x86, 0x57, 0xf8, 0x11, 0xbd, 0xfd, 0xe6, 0x59, 0x42, 0xcf,
+ 0x8f, 0xe5, 0xf7, 0xfd, 0xc0, 0xeb, 0x4d, 0x0d, 0xa5, 0x95, 0x89, 0xc4,
+ 0x3c, 0x65, 0x9f, 0x24, 0xb6, 0xe2, 0xcb, 0xe2, 0xea, 0x68, 0x59, 0x7f,
+ 0xd1, 0x9d, 0x43, 0xc9, 0xe4, 0xb2, 0xfe, 0xc0, 0x6c, 0x2c, 0x02, 0xcb,
+ 0x8f, 0xda, 0xca, 0x19, 0xe3, 0x39, 0x75, 0xff, 0xb0, 0xcd, 0x8e, 0x36,
+ 0x99, 0xa1, 0x65, 0xfa, 0x0b, 0xf0, 0x05, 0x97, 0xbe, 0x07, 0x59, 0x5a,
+ 0x3c, 0x23, 0x93, 0x5f, 0x16, 0x3e, 0xe2, 0xcb, 0xf4, 0x18, 0x27, 0xa1,
+ 0x65, 0x6d, 0x69, 0xe2, 0xc0, 0xa0, 0xc8, 0xf1, 0xf7, 0x44, 0x2f, 0x08,
+ 0x2e, 0x11, 0x08, 0x47, 0x7e, 0x2c, 0xf3, 0xfd, 0x65, 0xed, 0x9c, 0xed,
+ 0x65, 0x6e, 0x1e, 0x37, 0x89, 0xaf, 0xf3, 0x38, 0x35, 0xa0, 0xf9, 0x65,
+ 0xfd, 0x06, 0xe1, 0x31, 0xab, 0x2f, 0xec, 0xfe, 0xef, 0xf3, 0xcb, 0x2b,
+ 0x11, 0x6b, 0xe2, 0x52, 0x33, 0xe1, 0x6d, 0xfd, 0x3c, 0xd1, 0xc0, 0xf4,
+ 0xb2, 0xff, 0x08, 0x4e, 0x6e, 0xb5, 0x0b, 0x2a, 0x0f, 0x95, 0xcc, 0x6f,
+ 0xff, 0xee, 0xc5, 0xe9, 0xc9, 0xbe, 0x2f, 0x51, 0xf2, 0x70, 0x2c, 0xbb,
+ 0x68, 0x92, 0xcb, 0xcf, 0x84, 0xb2, 0xff, 0xef, 0x94, 0x01, 0xfe, 0x01,
+ 0x0a, 0x4b, 0x2f, 0xc3, 0x69, 0x9a, 0x16, 0x5f, 0xb3, 0xfb, 0x79, 0xf5,
+ 0x97, 0xde, 0x6d, 0x6c, 0x73, 0xd1, 0x22, 0x7a, 0xda, 0xdb, 0x85, 0xdd,
+ 0xa1, 0x10, 0x51, 0x0b, 0xf8, 0x8c, 0xfe, 0x73, 0xb9, 0x42, 0xb4, 0x70,
+ 0xe1, 0xc9, 0x53, 0x5d, 0xc6, 0x6f, 0xd4, 0x63, 0xad, 0x08, 0x79, 0xa1,
+ 0xd3, 0xa8, 0xf8, 0xbd, 0x1a, 0x73, 0xc6, 0xfc, 0x08, 0x67, 0x14, 0xae,
+ 0x7e, 0x47, 0xf5, 0xf8, 0xdd, 0x43, 0x0a, 0x0d, 0xe4, 0x06, 0x2f, 0x6d,
+ 0x8e, 0x08, 0x35, 0xbb, 0x09, 0x5b, 0xc2, 0x7b, 0xcb, 0x2e, 0xdd, 0xf2,
+ 0xcb, 0xf6, 0xbb, 0x77, 0xed, 0x51, 0x17, 0x2f, 0x68, 0x3e, 0x59, 0x7e,
+ 0xf8, 0x04, 0x29, 0x24, 0xbf, 0x73, 0xfe, 0x80, 0x2c, 0xbf, 0x3c, 0xf1,
+ 0xa0, 0xac, 0xb0, 0xb8, 0x4c, 0x12, 0x71, 0xec, 0x1a, 0xd1, 0xb3, 0x8e,
+ 0x84, 0xa7, 0x6c, 0xa2, 0xfc, 0x41, 0x96, 0x71, 0x65, 0xe2, 0x21, 0xac,
+ 0xba, 0x42, 0xf0, 0xf0, 0x88, 0x9e, 0x85, 0xab, 0xb2, 0x94, 0xad, 0x4e,
+ 0xa1, 0x61, 0x7f, 0xf1, 0xde, 0x42, 0xf3, 0x5d, 0xbb, 0xf6, 0xa8, 0x99,
+ 0x97, 0xff, 0x0c, 0x59, 0x05, 0xc4, 0x1f, 0x98, 0xd5, 0x97, 0xbc, 0xdc,
+ 0x59, 0x7c, 0x29, 0xe4, 0x7d, 0x65, 0xfd, 0x1c, 0x28, 0xff, 0x16, 0x56,
+ 0xd2, 0x3d, 0x23, 0x93, 0x56, 0xd0, 0x89, 0x6d, 0xa6, 0xdd, 0x7f, 0xf6,
+ 0xd3, 0x36, 0x33, 0x5b, 0x30, 0x3a, 0x9d, 0x65, 0xf6, 0x07, 0x53, 0xac,
+ 0xbb, 0x6f, 0x6b, 0x59, 0x71, 0x9f, 0x59, 0x42, 0x83, 0xda, 0xda, 0x44,
+ 0x63, 0x1f, 0xbf, 0x85, 0x56, 0xd7, 0xb5, 0x8a, 0x79, 0x0b, 0x2d, 0x32,
+ 0xcb, 0xa3, 0x8b, 0x2b, 0x69, 0x1f, 0x54, 0xe8, 0x5d, 0x09, 0x5f, 0xfd,
+ 0xf9, 0x67, 0xbc, 0xf2, 0x66, 0x25, 0x97, 0x6d, 0xed, 0x6b, 0x2f, 0xfd,
+ 0xe6, 0xff, 0x1f, 0xa9, 0xf0, 0xc5, 0x97, 0xfe, 0xdf, 0x1e, 0x68, 0x9a,
+ 0x68, 0xed, 0x65, 0x0a, 0x51, 0xc8, 0x28, 0x42, 0xec, 0x7d, 0x90, 0x6e,
+ 0x63, 0xac, 0xbf, 0x7c, 0x9b, 0xaf, 0xac, 0xae, 0xcd, 0xf0, 0x82, 0xd7,
+ 0xfd, 0xb5, 0x80, 0xe2, 0x69, 0xa7, 0x85, 0x97, 0xc2, 0x8f, 0xb9, 0x2c,
+ 0xbe, 0xda, 0x85, 0x5f, 0x21, 0x65, 0x82, 0xb2, 0x85, 0x51, 0xbe, 0x62,
+ 0xdb, 0xb6, 0xf6, 0xb5, 0x97, 0xff, 0xff, 0xf0, 0xaf, 0xa8, 0x15, 0x36,
+ 0x90, 0xfb, 0xdf, 0xa9, 0x4d, 0xbc, 0x22, 0xab, 0x69, 0x8a, 0xc5, 0x58,
+ 0xaa, 0xd9, 0xb3, 0xdb, 0x6b, 0x2f, 0xfc, 0x51, 0x3e, 0x9f, 0xd0, 0x76,
+ 0x59, 0x7d, 0x80, 0x80, 0x2c, 0xbf, 0xb9, 0xa8, 0xcf, 0xf1, 0x65, 0x82,
+ 0xb2, 0xa0, 0xdf, 0x61, 0x6d, 0xfe, 0x71, 0xb9, 0xf5, 0x1c, 0x59, 0x7f,
+ 0xed, 0xe1, 0x7e, 0xc6, 0xdb, 0xe0, 0x6b, 0x2f, 0xe8, 0x3b, 0xca, 0x3e,
+ 0xb2, 0xff, 0xe8, 0x3b, 0xff, 0x3a, 0x01, 0xc4, 0xf2, 0xcb, 0xff, 0xdd,
+ 0xe8, 0x33, 0xf5, 0xc6, 0xd7, 0x7e, 0xc5, 0x97, 0xcd, 0xbd, 0xc0, 0xb2,
+ 0xa0, 0xfc, 0xbe, 0x9f, 0x43, 0x4d, 0xeb, 0x0c, 0x8d, 0x43, 0xf1, 0x61,
+ 0x42, 0xe2, 0xf9, 0xa7, 0x09, 0x2c, 0xbf, 0x64, 0xf8, 0x09, 0x96, 0x56,
+ 0xc3, 0xcb, 0xf9, 0x15, 0xf9, 0xb7, 0x4d, 0x6e, 0xd6, 0x5f, 0xf0, 0x65,
+ 0xc7, 0x3b, 0x90, 0x16, 0x56, 0x8f, 0x91, 0xcb, 0x2f, 0xe8, 0xe6, 0xc6,
+ 0x79, 0x96, 0x5f, 0xed, 0x98, 0x4f, 0xa0, 0x6d, 0xac, 0xb8, 0xa4, 0xb2,
+ 0xf6, 0xa0, 0xd5, 0x97, 0xff, 0xcf, 0xec, 0xe8, 0x1e, 0x31, 0xfd, 0x37,
+ 0x82, 0xb2, 0x99, 0x10, 0xd3, 0x0b, 0x1c, 0x76, 0xff, 0x0f, 0x4e, 0x07,
+ 0xcd, 0x2c, 0xbf, 0xb3, 0x90, 0x21, 0x42, 0xca, 0x1a, 0x69, 0x79, 0x0b,
+ 0xd6, 0x30, 0xf1, 0x95, 0xb1, 0x65, 0xce, 0x75, 0x95, 0xc3, 0x4d, 0xba,
+ 0x21, 0x76, 0xef, 0xd6, 0x58, 0x56, 0xb2, 0xc0, 0x83, 0x5e, 0x11, 0xab,
+ 0xc7, 0x7f, 0xac, 0xb0, 0xad, 0x65, 0x61, 0xb1, 0x21, 0xcb, 0xf6, 0xd8,
+ 0xc9, 0xcc, 0x59, 0x50, 0x79, 0x5f, 0x1f, 0xbf, 0xff, 0xbb, 0x28, 0x3e,
+ 0xc8, 0xd6, 0x9b, 0x7e, 0x9d, 0xc0, 0xb2, 0xfd, 0x27, 0xfb, 0x9a, 0xb2,
+ 0xa1, 0x10, 0xd8, 0xbd, 0x7c, 0x58, 0x08, 0x59, 0x44, 0x78, 0x3b, 0xc8,
+ 0x6f, 0xb0, 0x78, 0x35, 0x97, 0xf3, 0x18, 0xdc, 0xce, 0xd6, 0x53, 0x1f,
+ 0x96, 0x88, 0xf8, 0x43, 0x7c, 0xdf, 0x89, 0x2c, 0xbc, 0x78, 0x92, 0xcb,
+ 0xdc, 0x79, 0x96, 0x54, 0x1b, 0x9f, 0x8e, 0x5f, 0xc2, 0xe6, 0x14, 0xf9,
+ 0xc9, 0x65, 0x6d, 0x6c, 0x96, 0x9d, 0xa4, 0x3f, 0x3c, 0x31, 0xc6, 0x7b,
+ 0xda, 0xfb, 0x47, 0x33, 0x34, 0x26, 0xb5, 0x08, 0x83, 0x90, 0xfa, 0x37,
+ 0xa7, 0x67, 0x02, 0x99, 0x42, 0x87, 0xf1, 0xad, 0x6f, 0x2e, 0x11, 0x6b,
+ 0x74, 0x82, 0xfe, 0xd6, 0x9e, 0x42, 0x1d, 0x65, 0xe7, 0x2e, 0xd6, 0x5e,
+ 0xf9, 0x42, 0xcb, 0xe2, 0x2c, 0xfa, 0xca, 0x14, 0x9b, 0xb8, 0x1b, 0xae,
+ 0x1f, 0xd9, 0x8a, 0xf7, 0xcf, 0xe6, 0x99, 0x65, 0xf1, 0x4d, 0x03, 0x59,
+ 0x77, 0x5f, 0x59, 0x7d, 0xe9, 0xa0, 0x6b, 0x2f, 0xe0, 0x6a, 0x04, 0x72,
+ 0x59, 0x50, 0x9b, 0xce, 0x42, 0xab, 0xb2, 0x36, 0x22, 0x98, 0x89, 0xc6,
+ 0x02, 0x47, 0x7b, 0xd1, 0xd2, 0xcb, 0xf4, 0x1c, 0xb2, 0x65, 0x97, 0xf3,
+ 0x61, 0x0f, 0xd0, 0xb2, 0xc7, 0x59, 0x63, 0xac, 0xba, 0x09, 0x65, 0x4e,
+ 0x69, 0x8c, 0x11, 0xa1, 0xa2, 0xb3, 0xb2, 0x7d, 0xc2, 0xbe, 0x1b, 0xd2,
+ 0xcb, 0xa3, 0x8b, 0x2f, 0xed, 0x41, 0x07, 0x3c, 0xb2, 0xfb, 0x51, 0x84,
+ 0xb2, 0xf9, 0xff, 0x20, 0x2c, 0xbf, 0xc1, 0x39, 0x64, 0xcd, 0x3a, 0xcb,
+ 0x05, 0x65, 0xfe, 0x6e, 0xdf, 0x35, 0x9f, 0x59, 0x40, 0x3c, 0x3e, 0x08,
+ 0xdf, 0xe7, 0xd3, 0x46, 0xe3, 0x1d, 0x65, 0x1a, 0x9a, 0x8f, 0x62, 0xc7,
+ 0x2c, 0xf1, 0x07, 0x08, 0xbe, 0xef, 0xbc, 0x8a, 0xff, 0xb5, 0x19, 0x28,
+ 0xf4, 0x01, 0x65, 0xff, 0xed, 0x9e, 0x76, 0xf8, 0x02, 0x44, 0xf2, 0x59,
+ 0x7f, 0xc2, 0x1f, 0x38, 0xef, 0xd4, 0x96, 0x5d, 0xb5, 0x8a, 0x56, 0x5f,
+ 0xf7, 0xa1, 0x86, 0xdc, 0x9d, 0xd6, 0x50, 0xa8, 0x7b, 0x0c, 0x41, 0x52,
+ 0x5c, 0x08, 0xc8, 0x64, 0xf6, 0x82, 0xd1, 0xae, 0x69, 0xa4, 0xe6, 0xe0,
+ 0x4a, 0x28, 0x49, 0x5f, 0xff, 0xff, 0xff, 0xfe, 0x15, 0x05, 0x38, 0x2a,
+ 0x0a, 0x36, 0x96, 0xd2, 0xec, 0x57, 0x02, 0xac, 0x51, 0xa9, 0xf7, 0x70,
+ 0x23, 0x15, 0x51, 0xb7, 0xd0, 0x9e, 0x14, 0x44, 0x0a, 0x37, 0x36, 0x9f,
+ 0xf6, 0x6c, 0xf6, 0xda, 0xcb, 0xff, 0xf0, 0x3a, 0x97, 0x83, 0x1a, 0x17,
+ 0xe6, 0xed, 0xf4, 0xb2, 0xf8, 0x32, 0xd9, 0xc5, 0x97, 0xfe, 0xf6, 0x16,
+ 0x1b, 0x85, 0x83, 0x59, 0x7f, 0xf7, 0x46, 0x47, 0xc6, 0xdb, 0x9c, 0x83,
+ 0xac, 0xbe, 0xe6, 0x75, 0xf5, 0x97, 0xd9, 0x34, 0x18, 0xb2, 0xfc, 0x3f,
+ 0x41, 0x4e, 0xb2, 0xf9, 0x8b, 0xfc, 0x59, 0x7f, 0xff, 0xc7, 0x6d, 0x78,
+ 0x3c, 0x94, 0x6f, 0xd4, 0x17, 0xfd, 0x92, 0x59, 0x52, 0x44, 0x4b, 0x10,
+ 0xdf, 0xf9, 0xbe, 0xdd, 0xb0, 0xff, 0x9d, 0xac, 0xa9, 0xd5, 0x01, 0x48,
+ 0x97, 0x0f, 0x34, 0x93, 0xe2, 0x32, 0x23, 0xfc, 0x2c, 0x77, 0x48, 0xaf,
+ 0x0d, 0xb7, 0xac, 0xbf, 0xdd, 0x96, 0x7b, 0xd8, 0x05, 0x97, 0xce, 0x63,
+ 0xee, 0x2c, 0xa7, 0x3d, 0x82, 0x33, 0xbf, 0x07, 0xbf, 0x31, 0x8b, 0x2f,
+ 0xbf, 0xb7, 0x9e, 0x59, 0x7f, 0xff, 0x9c, 0xbb, 0x2c, 0x1f, 0x83, 0xb3,
+ 0xd1, 0x2d, 0x44, 0xeb, 0x2b, 0x11, 0x10, 0x12, 0x5b, 0xf8, 0x42, 0x8f,
+ 0x44, 0x96, 0x5f, 0xff, 0xc6, 0x96, 0x00, 0x3c, 0xd9, 0x26, 0xf4, 0x76,
+ 0x4e, 0xb2, 0x8e, 0x88, 0xa7, 0x2d, 0xbf, 0xe6, 0xee, 0x69, 0x7a, 0x08,
+ 0xd5, 0x97, 0xa0, 0xff, 0x59, 0x44, 0x7a, 0xe6, 0x1d, 0xdf, 0xec, 0x32,
+ 0x3e, 0x4f, 0xc5, 0x97, 0x9b, 0xcc, 0xb2, 0xa0, 0xfb, 0xd8, 0x8b, 0xe6,
+ 0x57, 0x41, 0x2c, 0xbe, 0xce, 0xc7, 0x8b, 0x2f, 0x88, 0x62, 0x74, 0xb2,
+ 0xe0, 0xfd, 0x65, 0xe7, 0xd4, 0xb6, 0x1e, 0xeb, 0x91, 0x6d, 0x92, 0x50,
+ 0xa1, 0x7f, 0x02, 0x23, 0x2b, 0xc9, 0x4b, 0x8c, 0xf5, 0xa7, 0x63, 0x90,
+ 0x7a, 0x16, 0x4f, 0x0a, 0xc2, 0x87, 0x47, 0xcb, 0x42, 0xe5, 0x7f, 0x8d,
+ 0x7d, 0xfd, 0xe7, 0x5f, 0x59, 0x76, 0xfd, 0xc5, 0x94, 0x69, 0xea, 0x39,
+ 0xc5, 0xff, 0xfb, 0x5a, 0x6c, 0xde, 0x41, 0xe6, 0xce, 0x05, 0xf8, 0xb2,
+ 0x96, 0x5f, 0xff, 0x71, 0xb6, 0xf3, 0xbf, 0x31, 0x10, 0x75, 0x3a, 0xca,
+ 0xd1, 0xef, 0x7c, 0x2e, 0xfe, 0xfe, 0x1f, 0xac, 0x3a, 0xca, 0x84, 0xc1,
+ 0xf2, 0x16, 0xec, 0x45, 0x7f, 0x8e, 0x77, 0x97, 0x1a, 0x4b, 0x2f, 0xf1,
+ 0xbb, 0x23, 0xa0, 0x6a, 0x16, 0x56, 0x1f, 0x53, 0x99, 0xd3, 0x27, 0xcd,
+ 0xe8, 0xca, 0x4a, 0x13, 0xb7, 0xff, 0xb7, 0xe0, 0xfd, 0x1b, 0xcf, 0x04,
+ 0xe2, 0x2c, 0xb4, 0xcb, 0x2b, 0x0f, 0x7c, 0x29, 0xb7, 0xfd, 0x2e, 0xfc,
+ 0xc6, 0x41, 0x0d, 0x65, 0xfc, 0x37, 0x97, 0x1a, 0x4b, 0x2b, 0x48, 0x88,
+ 0x72, 0x10, 0x9d, 0x5f, 0x04, 0xbf, 0xc5, 0x97, 0xf7, 0x02, 0xc4, 0xdc,
+ 0x59, 0x7a, 0x35, 0x0b, 0x2b, 0x61, 0xe3, 0xf8, 0xb2, 0xbb, 0x44, 0x6e,
+ 0x9a, 0x6f, 0x4b, 0x6c, 0xc5, 0x97, 0x01, 0x96, 0x5f, 0x8f, 0x2f, 0x09,
+ 0xc5, 0x96, 0xd6, 0xc3, 0xc0, 0x10, 0x5a, 0xfc, 0xe6, 0x16, 0x0d, 0x65,
+ 0x42, 0x2c, 0xd9, 0x87, 0x45, 0x77, 0xfe, 0x28, 0xec, 0xd7, 0xcd, 0x30,
+ 0x16, 0x5f, 0xdc, 0xc6, 0xd6, 0x9d, 0x65, 0xfb, 0x9b, 0x00, 0xff, 0x59,
+ 0x53, 0xa2, 0x50, 0x07, 0xdf, 0x2c, 0xba, 0x34, 0xb2, 0xff, 0xe9, 0xf3,
+ 0x8c, 0xfe, 0x16, 0x61, 0x86, 0x24, 0xb3, 0x00, 0xf8, 0x08, 0x5a, 0xff,
+ 0x82, 0xfa, 0xdb, 0x0f, 0x9b, 0x4b, 0x2a, 0x11, 0xe6, 0x38, 0x48, 0xf8,
+ 0x9a, 0xfe, 0xeb, 0x3c, 0x1e, 0x80, 0xb2, 0xde, 0x59, 0x7f, 0x1f, 0x9e,
+ 0x82, 0xfa, 0xcb, 0xd3, 0xf8, 0x2b, 0x2f, 0xfd, 0xe7, 0xe7, 0xb3, 0x7e,
+ 0x7f, 0x8b, 0x2a, 0x0f, 0x79, 0xc7, 0xa9, 0x91, 0x57, 0xe8, 0x45, 0xdf,
+ 0x98, 0x3d, 0xb4, 0xeb, 0x2b, 0x13, 0x3c, 0xec, 0xc3, 0xf0, 0xbc, 0xdb,
+ 0x27, 0xbf, 0xe2, 0xc8, 0x35, 0xfe, 0xe6, 0xac, 0xbf, 0xa4, 0x27, 0xf9,
+ 0x1f, 0x59, 0x7f, 0x8f, 0x9d, 0x93, 0xe7, 0x6b, 0x2e, 0x0c, 0xcb, 0x2e,
+ 0x97, 0x20, 0xf2, 0xc0, 0x67, 0x7c, 0x7e, 0x09, 0xc5, 0x97, 0xbb, 0x0f,
+ 0x6b, 0x2a, 0x11, 0xd5, 0xd3, 0xd3, 0x16, 0x84, 0x92, 0xff, 0xbf, 0xf8,
+ 0x3e, 0x61, 0x1a, 0xb2, 0xff, 0xfb, 0xfe, 0xcd, 0xdf, 0xe7, 0x8b, 0x3f,
+ 0xe6, 0x59, 0x5d, 0x22, 0x24, 0x8e, 0x2f, 0xe2, 0x7f, 0xca, 0x0d, 0x59,
+ 0x7f, 0xb0, 0x03, 0x0b, 0xea, 0x4b, 0x2a, 0x0f, 0x82, 0x72, 0xdb, 0xf9,
+ 0xdc, 0x7b, 0xf0, 0x6b, 0x2f, 0x3b, 0xf6, 0xa8, 0xb3, 0xd7, 0xfa, 0x08,
+ 0xdd, 0x06, 0x09, 0x65, 0xfc, 0x07, 0x29, 0x31, 0xd6, 0x54, 0x26, 0xb5,
+ 0x3c, 0x20, 0xc6, 0x45, 0xd9, 0x73, 0x14, 0x80, 0xca, 0xff, 0x7b, 0xfc,
+ 0x7e, 0x84, 0x3a, 0xcb, 0xfd, 0x12, 0x6f, 0xc7, 0xf8, 0xb2, 0xf8, 0x02,
+ 0x7a, 0x16, 0x5e, 0x18, 0xdd, 0x65, 0x78, 0xfc, 0x48, 0xcb, 0xe4, 0x77,
+ 0xf4, 0x84, 0xcf, 0x3f, 0x4b, 0x2a, 0x13, 0x04, 0x68, 0x53, 0xb9, 0x75,
+ 0xff, 0x1a, 0xe5, 0x9b, 0xcb, 0x38, 0xb2, 0xfe, 0xde, 0x59, 0xcc, 0x25,
+ 0x96, 0xdc, 0x59, 0x58, 0x78, 0x3c, 0x2d, 0xbc, 0xd2, 0x85, 0x96, 0x7d,
+ 0x86, 0xf3, 0x84, 0x36, 0xd1, 0xa8, 0xde, 0xf4, 0x2d, 0xaf, 0xf3, 0x0f,
+ 0x0e, 0x66, 0x79, 0x65, 0xa7, 0x59, 0x7f, 0xff, 0xd9, 0xfe, 0x67, 0x6e,
+ 0x40, 0xd9, 0xa8, 0x20, 0xfe, 0x3c, 0xb2, 0xfd, 0xc1, 0xb4, 0x12, 0xca,
+ 0x84, 0x69, 0x1c, 0xcc, 0x84, 0xbe, 0xcf, 0x7f, 0xf7, 0x3e, 0xd3, 0x18,
+ 0xe3, 0x8e, 0xb8, 0xb2, 0x99, 0x38, 0x37, 0x8c, 0x04, 0x27, 0x77, 0x00,
+ 0x0b, 0x2f, 0x18, 0x61, 0x89, 0x2f, 0xfa, 0x5c, 0x2c, 0xec, 0x79, 0xa4,
+ 0x82, 0xcd, 0x05, 0xa4, 0xb2, 0x99, 0x12, 0x6e, 0x6f, 0xf4, 0xbb, 0xfe,
+ 0x90, 0xfd, 0x05, 0x18, 0x62, 0xcb, 0xf6, 0xe8, 0x4f, 0x83, 0x59, 0x7f,
+ 0xfd, 0xbc, 0x83, 0x2c, 0xde, 0xdf, 0x8e, 0xf3, 0xcb, 0x2f, 0xd9, 0xbf,
+ 0x64, 0x8e, 0xb2, 0xdf, 0x83, 0xff, 0xf2, 0x9d, 0x42, 0x61, 0x38, 0x70,
+ 0x18, 0x55, 0x5f, 0xfb, 0xa9, 0x10, 0x41, 0xb3, 0xb3, 0x81, 0x65, 0xd0,
+ 0x6a, 0xcb, 0xfe, 0x1c, 0x14, 0x02, 0x5e, 0x65, 0x97, 0xc6, 0xfd, 0xa7,
+ 0x59, 0x50, 0x8b, 0x69, 0xd1, 0x18, 0x5c, 0x26, 0xf7, 0xfb, 0xcc, 0x32,
+ 0x77, 0x99, 0x65, 0xfe, 0x1f, 0x82, 0xe0, 0xdb, 0xc5, 0x97, 0xce, 0x08,
+ 0xd2, 0xca, 0x84, 0x44, 0xb1, 0x97, 0x0d, 0xaf, 0xa3, 0xf9, 0x3a, 0xcb,
+ 0xfd, 0x1b, 0x3f, 0x9c, 0xe4, 0x2c, 0xbf, 0x86, 0x20, 0xc3, 0xfe, 0x2c,
+ 0xa3, 0x51, 0x0d, 0xa2, 0x22, 0x34, 0xbf, 0xb3, 0x92, 0xf0, 0x9c, 0x59,
+ 0x4c, 0x7b, 0xe4, 0x61, 0x7a, 0x08, 0xd5, 0x95, 0x26, 0xc9, 0x48, 0x71,
+ 0x90, 0xe4, 0x2f, 0x0d, 0x86, 0xbf, 0x71, 0xda, 0xf5, 0x1b, 0x83, 0x23,
+ 0x4d, 0x19, 0x16, 0xa5, 0x0f, 0x9e, 0x36, 0x1f, 0x4a, 0x94, 0x04, 0x32,
+ 0x0a, 0x33, 0x7e, 0x43, 0xab, 0xf0, 0xc5, 0xdf, 0x18, 0x98, 0x84, 0x17,
+ 0xfd, 0x9a, 0x2c, 0xde, 0xfa, 0x92, 0xcb, 0x81, 0xc5, 0x97, 0xe2, 0xfe,
+ 0x00, 0xeb, 0x2f, 0xb4, 0xd1, 0xf5, 0x97, 0xf7, 0x0b, 0x26, 0x83, 0xac,
+ 0xa0, 0x1e, 0x77, 0xc8, 0x69, 0xd1, 0x2e, 0x17, 0x5b, 0xa3, 0xeb, 0x2f,
+ 0x80, 0xe6, 0x7d, 0x65, 0xfe, 0x73, 0x3c, 0xd1, 0xa8, 0x59, 0x7f, 0x04,
+ 0xfc, 0x0e, 0xa7, 0x59, 0x7e, 0x6d, 0xf0, 0x5f, 0x59, 0x50, 0x9e, 0x60,
+ 0xce, 0x4d, 0x85, 0x77, 0x44, 0x4c, 0x2d, 0xa2, 0x32, 0x32, 0xe1, 0x85,
+ 0xff, 0xb4, 0xdc, 0x90, 0x9e, 0x82, 0x85, 0x97, 0xda, 0x68, 0x3a, 0xcb,
+ 0xff, 0xf7, 0xcd, 0x0c, 0x60, 0xfd, 0x9c, 0xea, 0x51, 0xe5, 0x95, 0xa4,
+ 0x5b, 0x1c, 0xf8, 0x88, 0x6f, 0x80, 0x1d, 0x4e, 0xb2, 0xf4, 0xc1, 0xd2,
+ 0xcb, 0x9e, 0x4b, 0x2f, 0xe3, 0xe1, 0x7f, 0x6f, 0x16, 0x5f, 0xff, 0xec,
+ 0xf8, 0x40, 0x77, 0x93, 0x8e, 0x09, 0xf4, 0xf2, 0x59, 0x7f, 0x13, 0x99,
+ 0xfc, 0xf6, 0x22, 0x34, 0x8b, 0xef, 0xf6, 0x7b, 0xc1, 0xfb, 0x92, 0xcb,
+ 0x98, 0x6b, 0x2f, 0xef, 0x76, 0xfa, 0x79, 0x2c, 0xb7, 0x72, 0x3c, 0x4c,
+ 0x16, 0xbc, 0xd3, 0x71, 0x65, 0x41, 0xe2, 0x9c, 0xa2, 0xff, 0xef, 0xb7,
+ 0x9c, 0xfb, 0x61, 0xf3, 0x69, 0x65, 0xfc, 0xff, 0x3c, 0x67, 0xd6, 0x53,
+ 0x9f, 0x98, 0x51, 0xef, 0x7a, 0x38, 0xb2, 0x86, 0xa9, 0xca, 0x68, 0x51,
+ 0xe9, 0x0c, 0xf0, 0xbb, 0x28, 0x4a, 0x7c, 0x86, 0xfb, 0xdd, 0x3e, 0xe2,
+ 0xcb, 0xf7, 0x9c, 0xed, 0xc5, 0x94, 0x33, 0xcd, 0xec, 0x9a, 0xb1, 0x5b,
+ 0x43, 0x4a, 0x90, 0x78, 0x5a, 0xdf, 0x9b, 0xce, 0x76, 0x59, 0x79, 0xc8,
+ 0x0b, 0x2b, 0x61, 0xe0, 0xf6, 0x4d, 0x7b, 0x7e, 0x0d, 0x65, 0xb5, 0x39,
+ 0xe1, 0xcc, 0x4b, 0x73, 0xf9, 0x65, 0xf4, 0xd2, 0x72, 0x59, 0x5a, 0x37,
+ 0x1c, 0x16, 0xbf, 0xdb, 0xba, 0xcd, 0xd2, 0x09, 0x8b, 0x2a, 0x73, 0xdb,
+ 0x30, 0x86, 0xf6, 0xeb, 0x0d, 0x65, 0x61, 0xe1, 0xb9, 0x25, 0x42, 0xec,
+ 0xd3, 0x17, 0xfa, 0x5c, 0x63, 0xc2, 0xfc, 0xa3, 0x00, 0xbf, 0x8f, 0xde,
+ 0xcc, 0x3f, 0x16, 0x5f, 0xff, 0xff, 0x03, 0x99, 0x84, 0x68, 0x9a, 0x28,
+ 0xcf, 0x0b, 0xe1, 0x64, 0xe7, 0xc3, 0xac, 0xbb, 0x58, 0xb2, 0xee, 0x32,
+ 0xca, 0x9c, 0xd6, 0x68, 0x5a, 0xe1, 0x24, 0xb2, 0xf9, 0xb7, 0xb6, 0xf5,
+ 0x97, 0xd0, 0x42, 0x1d, 0x65, 0x62, 0x20, 0x4e, 0x44, 0xe3, 0x02, 0x12,
+ 0xd6, 0x26, 0xd1, 0xf8, 0xcb, 0x2e, 0x07, 0x16, 0x5f, 0x6c, 0x28, 0xed,
+ 0x65, 0xf3, 0xfa, 0x04, 0x59, 0x58, 0x7b, 0xbe, 0x17, 0xde, 0x49, 0x7d,
+ 0x06, 0x60, 0xd6, 0x5f, 0xff, 0x07, 0xa9, 0x70, 0x7e, 0x8d, 0x0d, 0xdc,
+ 0xc5, 0x97, 0x6d, 0x62, 0xa2, 0xca, 0xc4, 0xd2, 0xda, 0x10, 0xda, 0x30,
+ 0x22, 0x21, 0x14, 0xae, 0xcf, 0xac, 0xb8, 0xec, 0xb2, 0x86, 0x6b, 0x08,
+ 0x5a, 0xf8, 0xc8, 0xeb, 0x8b, 0x2f, 0x7c, 0x4c, 0x59, 0x74, 0x4e, 0xb2,
+ 0x9c, 0xda, 0x70, 0x76, 0xf0, 0xe2, 0x4b, 0x2f, 0xd3, 0x4a, 0x3a, 0xfa,
+ 0xcb, 0xfb, 0xbf, 0x36, 0xf7, 0xd2, 0xcb, 0x44, 0xe7, 0xb5, 0x85, 0x57,
+ 0x67, 0x96, 0x53, 0xa2, 0xcc, 0x9d, 0xb6, 0xc9, 0xee, 0xc1, 0xac, 0xbb,
+ 0xe2, 0xb5, 0x95, 0x3a, 0xe8, 0x5c, 0xa5, 0x72, 0x63, 0xd7, 0x88, 0x38,
+ 0xb1, 0xf8, 0x69, 0xef, 0x31, 0xdb, 0x16, 0xbf, 0x68, 0x07, 0x6e, 0x2c,
+ 0xba, 0x37, 0xac, 0xac, 0x3c, 0x0d, 0xe5, 0x17, 0xbc, 0x13, 0x16, 0x5e,
+ 0xf3, 0xce, 0xb2, 0xfd, 0xcf, 0xb4, 0x74, 0xb2, 0xe0, 0xf6, 0xb2, 0xa4,
+ 0x78, 0x00, 0x28, 0xbd, 0xfc, 0x11, 0x65, 0xfc, 0x70, 0xf3, 0xf9, 0xf5,
+ 0x97, 0xf8, 0xc7, 0xef, 0x0b, 0x06, 0xb2, 0xfc, 0xfe, 0xea, 0x5c, 0x59,
+ 0x50, 0x88, 0xae, 0x17, 0x04, 0xce, 0xfd, 0x9c, 0x04, 0x4c, 0xb2, 0xfe,
+ 0x8e, 0xb9, 0xb3, 0x50, 0xb2, 0xf4, 0xa3, 0x8b, 0x2c, 0x15, 0x95, 0x23,
+ 0x5a, 0x01, 0xcb, 0xc3, 0x0f, 0x6b, 0x2f, 0x86, 0x51, 0x25, 0x95, 0x07,
+ 0xc0, 0xc4, 0x2e, 0x3d, 0x7b, 0x18, 0x6b, 0x2f, 0xff, 0x09, 0xb3, 0xaf,
+ 0x94, 0x66, 0xcc, 0xeb, 0xeb, 0x2f, 0xfa, 0x3c, 0xd1, 0x34, 0xd1, 0xda,
+ 0xca, 0x85, 0x69, 0x83, 0x23, 0x34, 0x7b, 0xa5, 0xd6, 0x22, 0x9a, 0x14,
+ 0xfa, 0x2f, 0x39, 0x47, 0xa1, 0x7b, 0xf2, 0xc0, 0x8d, 0xef, 0x50, 0xbf,
+ 0xcd, 0x33, 0x93, 0x75, 0xc5, 0x97, 0x67, 0x6b, 0x2f, 0xf1, 0x7f, 0x85,
+ 0x1f, 0xe2, 0xcb, 0xfd, 0xe2, 0xc6, 0x04, 0x01, 0x65, 0xf9, 0xb7, 0xe1,
+ 0x71, 0x65, 0xff, 0xfd, 0x1e, 0x0f, 0x51, 0xfe, 0xfd, 0x1a, 0x0e, 0x06,
+ 0x65, 0x95, 0x88, 0xe9, 0x63, 0x2d, 0x18, 0xf8, 0xa2, 0xfd, 0xfc, 0xf0,
+ 0x77, 0x16, 0x5f, 0xfa, 0x7f, 0x31, 0xe3, 0x73, 0xd9, 0x3a, 0xca, 0xe8,
+ 0xfb, 0xb4, 0x57, 0x7f, 0x6b, 0x3d, 0xe0, 0xfd, 0x65, 0xfb, 0xc5, 0x19,
+ 0xa5, 0x17, 0xf6, 0x6a, 0x70, 0xb8, 0xd5, 0x10, 0x68, 0x59, 0xa6, 0xb6,
+ 0xa7, 0x45, 0x0c, 0x95, 0x2f, 0x8b, 0xd9, 0xd2, 0xca, 0x84, 0xc4, 0x1a,
+ 0x18, 0x8e, 0x55, 0x7e, 0x7e, 0xd8, 0xf0, 0xb2, 0xfe, 0x97, 0x89, 0xfa,
+ 0xfa, 0xca, 0xec, 0xf5, 0x48, 0x9e, 0xf8, 0x42, 0x79, 0xd6, 0x5f, 0xb8,
+ 0xda, 0x60, 0x2c, 0xac, 0x3e, 0xce, 0x11, 0x6e, 0x91, 0xdf, 0xa3, 0xfb,
+ 0x0e, 0x62, 0xcb, 0xff, 0x4f, 0xff, 0x47, 0xb3, 0x7b, 0xc9, 0x65, 0xe3,
+ 0xc7, 0x6b, 0x2f, 0x88, 0x01, 0xe2, 0xca, 0xc3, 0x7f, 0xa1, 0xda, 0x84,
+ 0x50, 0x34, 0x20, 0x2f, 0xcf, 0x39, 0x39, 0xab, 0x2f, 0xf8, 0x7c, 0xe6,
+ 0x68, 0x7e, 0xc5, 0x97, 0xfd, 0xc7, 0x28, 0x99, 0x87, 0x3a, 0xcb, 0xfd,
+ 0x26, 0x3c, 0x78, 0x41, 0xac, 0xbf, 0xfd, 0x18, 0x5d, 0x7f, 0x34, 0xd3,
+ 0xb9, 0xd6, 0x5d, 0x9e, 0xd8, 0x8b, 0x6e, 0x1c, 0xfc, 0xd2, 0xec, 0xe2,
+ 0xcb, 0x19, 0xf3, 0xd3, 0xdb, 0x3d, 0xa8, 0x4d, 0xb9, 0xe3, 0x42, 0xbf,
+ 0xec, 0x97, 0xb0, 0x9f, 0x46, 0xac, 0xb8, 0xe6, 0x2c, 0xa1, 0x67, 0xa1,
+ 0x23, 0x8b, 0xf4, 0x1f, 0xf9, 0xe5, 0x95, 0xb1, 0x7d, 0x6f, 0x68, 0x33,
+ 0x88, 0xc0, 0x25, 0x1d, 0xce, 0x43, 0xd3, 0x46, 0x3e, 0x86, 0x5b, 0x93,
+ 0x14, 0x72, 0xc1, 0x78, 0xdd, 0x24, 0xb8, 0x70, 0xb2, 0xec, 0x92, 0xcb,
+ 0xff, 0xf3, 0x76, 0xc3, 0xfc, 0x82, 0x5f, 0xe7, 0x9e, 0x4b, 0x2f, 0xff,
+ 0xbd, 0x07, 0xd9, 0xe8, 0x7d, 0x0c, 0xa2, 0x4b, 0x29, 0xd1, 0xa5, 0xc1,
+ 0x6f, 0x8b, 0x05, 0x5a, 0xec, 0x11, 0x65, 0xfe, 0x7f, 0xbe, 0x0d, 0xb7,
+ 0xac, 0xbe, 0x07, 0xa0, 0x6b, 0x2f, 0xef, 0x31, 0x85, 0x03, 0x59, 0x7f,
+ 0xd0, 0x03, 0xc6, 0x17, 0xf8, 0xb2, 0xff, 0xb9, 0x86, 0x79, 0xce, 0xdc,
+ 0x59, 0x7e, 0xcd, 0x4e, 0x1e, 0x2c, 0xae, 0xd3, 0x1b, 0x63, 0x39, 0x88,
+ 0xbc, 0x5b, 0xc3, 0x7d, 0xe7, 0x37, 0xe6, 0xea, 0x4c, 0x4b, 0x2f, 0x37,
+ 0xb1, 0x65, 0xfd, 0xf7, 0x39, 0xe0, 0xeb, 0x2b, 0x0f, 0xbf, 0xb2, 0x7e,
+ 0x86, 0xe9, 0x65, 0x1c, 0xdd, 0x98, 0x61, 0x7f, 0xc1, 0x9f, 0x66, 0x7f,
+ 0xd1, 0xf5, 0x97, 0x34, 0xcb, 0x2a, 0x0f, 0xd7, 0xb2, 0x2d, 0xd3, 0xcb,
+ 0xdc, 0x09, 0x2c, 0xbf, 0xf0, 0x4d, 0x38, 0x7f, 0xe8, 0x08, 0xad, 0x65,
+ 0x74, 0x7c, 0x24, 0x39, 0x7c, 0x78, 0xd1, 0xab, 0x2f, 0xb0, 0x00, 0x75,
+ 0x97, 0x84, 0xf3, 0xac, 0xac, 0x3e, 0x12, 0x23, 0xdb, 0x21, 0xa9, 0xd1,
+ 0x66, 0x64, 0x20, 0xef, 0x84, 0x82, 0xed, 0x65, 0xee, 0x7a, 0x16, 0x54,
+ 0x8d, 0xf8, 0xc8, 0xef, 0xc5, 0xa3, 0x1e, 0x75, 0x95, 0x08, 0xb3, 0xc6,
+ 0x97, 0x21, 0xbf, 0x16, 0x7f, 0xcc, 0xb2, 0xfb, 0xbf, 0x41, 0x8b, 0x2f,
+ 0xd9, 0xfe, 0x31, 0xd6, 0x5c, 0x12, 0x59, 0x78, 0xb2, 0x75, 0x95, 0x0b,
+ 0xb6, 0x32, 0x3c, 0xc8, 0xcc, 0x9a, 0x37, 0xad, 0x47, 0xf3, 0xe2, 0xd1,
+ 0x59, 0x31, 0x12, 0x70, 0x9c, 0x41, 0x6b, 0xfe, 0x83, 0xc7, 0xd8, 0xb2,
+ 0x4b, 0x2d, 0x25, 0x97, 0xdc, 0x0c, 0x01, 0x65, 0xc1, 0xdd, 0x59, 0x5a,
+ 0x44, 0x1f, 0x8d, 0x80, 0x22, 0x44, 0x57, 0x61, 0x2c, 0xbf, 0x70, 0x4e,
+ 0x78, 0x2b, 0x2b, 0xc6, 0xff, 0xe2, 0xb7, 0xff, 0xb4, 0xd0, 0x7c, 0xd9,
+ 0x9e, 0x6c, 0x3a, 0xcb, 0xe6, 0xe4, 0x3a, 0xca, 0xd8, 0x7d, 0x3c, 0x49,
+ 0xbf, 0xd8, 0x59, 0xd7, 0xe4, 0x75, 0x97, 0x7e, 0x16, 0x54, 0x1e, 0x4b,
+ 0x99, 0xdf, 0xf3, 0xc8, 0x6c, 0x11, 0x5b, 0x69, 0x65, 0xfb, 0x08, 0xa0,
+ 0x6b, 0x2f, 0xbc, 0xfe, 0x85, 0x97, 0xf4, 0x4e, 0x77, 0x9a, 0x16, 0x5b,
+ 0x4b, 0x2a, 0x47, 0xc1, 0x31, 0x08, 0x4b, 0xaf, 0xff, 0x9c, 0xdf, 0xc6,
+ 0x81, 0xa8, 0xf9, 0x38, 0x16, 0x5f, 0xe8, 0xec, 0x7e, 0x0b, 0xf1, 0x65,
+ 0xce, 0x6a, 0xcb, 0xfa, 0x72, 0xcf, 0xea, 0x16, 0x5f, 0x76, 0x27, 0xf8,
+ 0xb2, 0xfe, 0x2c, 0x06, 0x14, 0x96, 0x5f, 0xff, 0x1b, 0xb0, 0x42, 0x7f,
+ 0xf1, 0xba, 0xf3, 0x18, 0xb2, 0xb1, 0x10, 0x0e, 0x57, 0x7b, 0x50, 0x6a,
+ 0xca, 0x84, 0xc4, 0x18, 0xb4, 0xa1, 0x4b, 0xc2, 0x1a, 0x85, 0xc6, 0xdc,
+ 0x7b, 0x68, 0x45, 0x69, 0xb4, 0xe4, 0x1e, 0x3c, 0x78, 0x42, 0x91, 0x87,
+ 0x13, 0xfe, 0x68, 0x18, 0xc9, 0xee, 0xe6, 0xf5, 0x97, 0x37, 0xd6, 0x5f,
+ 0x31, 0x38, 0xd6, 0x5c, 0x27, 0xd6, 0x5f, 0xf8, 0xf9, 0xfe, 0x09, 0xc7,
+ 0x96, 0x2c, 0xbf, 0x72, 0x35, 0xf8, 0x58, 0x2c, 0xdf, 0xd0, 0xd1, 0x61,
+ 0xa2, 0x0e, 0x2b, 0xdc, 0xc2, 0xb5, 0x97, 0xc6, 0x64, 0x99, 0x65, 0xec,
+ 0x63, 0x56, 0x5f, 0x4c, 0xef, 0xa5, 0x94, 0xe7, 0xc0, 0x44, 0x42, 0x0e,
+ 0x5e, 0xc6, 0xde, 0xb2, 0xf4, 0x84, 0x3a, 0xca, 0xf1, 0xbb, 0x71, 0xdb,
+ 0xfb, 0x8d, 0xac, 0x0e, 0x96, 0x5f, 0xff, 0xd3, 0x6c, 0x6e, 0xc3, 0xae,
+ 0x07, 0x61, 0xdb, 0xfe, 0x65, 0x97, 0x41, 0xab, 0x2a, 0x0f, 0xe5, 0x98,
+ 0xab, 0x15, 0x6c, 0x1a, 0x32, 0xd0, 0xc6, 0x98, 0xc0, 0xef, 0x5e, 0x69,
+ 0xf9, 0x06, 0xec, 0x29, 0xae, 0x38, 0xa5, 0x51, 0x7e, 0x2f, 0xd3, 0xf5,
+ 0x28, 0x1a, 0xcb, 0xf6, 0x13, 0x75, 0x25, 0x97, 0xb5, 0x98, 0xb2, 0xb6,
+ 0xb3, 0xec, 0x62, 0xae, 0x13, 0xde, 0x28, 0x02, 0xcb, 0xcd, 0x9e, 0x59,
+ 0x71, 0x77, 0x06, 0xdb, 0x43, 0x77, 0xff, 0x4b, 0xe1, 0x94, 0x8f, 0xff,
+ 0xc1, 0xd6, 0x5f, 0xef, 0xf2, 0x27, 0xce, 0x0d, 0x65, 0xde, 0xc5, 0x97,
+ 0xff, 0xde, 0x81, 0xe7, 0x7b, 0x30, 0xb0, 0x7e, 0x85, 0x97, 0xfd, 0xa8,
+ 0xf3, 0x6f, 0xd4, 0x49, 0x65, 0xff, 0xfe, 0x04, 0x75, 0x2e, 0x0f, 0x30,
+ 0xb3, 0xbf, 0x30, 0x7e, 0xb2, 0xff, 0xe6, 0xc2, 0xcc, 0xe6, 0xc9, 0x70,
+ 0xeb, 0x2f, 0xfc, 0xf1, 0xd4, 0xb6, 0x73, 0xa1, 0xc2, 0xcb, 0xf9, 0xe7,
+ 0x2c, 0x9c, 0x2b, 0x28, 0x6a, 0xb1, 0x31, 0xa7, 0xa2, 0xc6, 0x46, 0xdc,
+ 0x34, 0x98, 0x5b, 0x4a, 0x00, 0x3a, 0xe3, 0x0f, 0xd1, 0x36, 0xd0, 0xaf,
+ 0x1b, 0x1a, 0x59, 0x7c, 0x77, 0x18, 0x56, 0x5f, 0xe1, 0x23, 0xcd, 0xc8,
+ 0x11, 0x65, 0xf0, 0x09, 0xe4, 0xb2, 0xfe, 0xf3, 0x1d, 0xdf, 0x75, 0x65,
+ 0xe0, 0xf5, 0xc5, 0x97, 0x8b, 0x37, 0x56, 0x5e, 0x3e, 0x6f, 0x59, 0x5b,
+ 0x0f, 0x6b, 0x07, 0x9c, 0x7a, 0xf6, 0x9a, 0x75, 0x97, 0xf0, 0xe0, 0x1a,
+ 0xce, 0x96, 0x5b, 0x6d, 0x65, 0x0b, 0x4e, 0xae, 0x07, 0x46, 0x44, 0x69,
+ 0xa7, 0x64, 0x33, 0x42, 0x27, 0x45, 0xe7, 0x1d, 0x15, 0x97, 0x5f, 0xf3,
+ 0x1b, 0x1a, 0x2c, 0x63, 0x56, 0x5d, 0xdc, 0xeb, 0x2f, 0xd8, 0xda, 0x9a,
+ 0x4b, 0x2f, 0x89, 0xff, 0xc5, 0x96, 0x83, 0x9e, 0x4e, 0xf2, 0x8b, 0x9a,
+ 0x65, 0x97, 0xfe, 0xc9, 0xf6, 0x7a, 0x26, 0x6e, 0xa4, 0xb2, 0xfe, 0x83,
+ 0x46, 0x51, 0xd2, 0xca, 0x83, 0xf1, 0xd2, 0x1d, 0xf1, 0x46, 0x8d, 0x59,
+ 0x7d, 0x05, 0x86, 0xac, 0xbd, 0xc8, 0x35, 0x65, 0xfe, 0x7c, 0xeb, 0xff,
+ 0x7f, 0x2c, 0xbf, 0xf8, 0x23, 0xcd, 0x44, 0x98, 0x70, 0x4b, 0x2f, 0xf8,
+ 0x9e, 0x78, 0xd6, 0x9e, 0x4b, 0x2a, 0x47, 0xf5, 0xe4, 0x2b, 0xff, 0x1f,
+ 0x39, 0xcc, 0x20, 0x6d, 0xe2, 0xcb, 0xff, 0xed, 0x3f, 0x0b, 0x27, 0x12,
+ 0x41, 0x86, 0x25, 0x95, 0x08, 0xb1, 0x72, 0x20, 0xa0, 0x57, 0x49, 0xd4,
+ 0xf8, 0x77, 0xf1, 0xaf, 0x5f, 0xff, 0xe6, 0xe0, 0x33, 0x63, 0x6f, 0x8f,
+ 0x34, 0x4d, 0x34, 0x76, 0xb2, 0xf7, 0xda, 0x75, 0x97, 0xe0, 0x3f, 0x51,
+ 0x32, 0xcb, 0xc5, 0x1d, 0xac, 0xbf, 0xf3, 0x4d, 0xe8, 0xd7, 0x52, 0x8d,
+ 0x2c, 0xbf, 0xfd, 0xff, 0x46, 0xfe, 0x13, 0xfe, 0x66, 0xde, 0xb2, 0xff,
+ 0xcc, 0x7c, 0xd6, 0x44, 0xcc, 0x75, 0x95, 0x88, 0x8b, 0xd2, 0x75, 0x0d,
+ 0x1d, 0xbc, 0x86, 0x5d, 0xf6, 0x7e, 0x06, 0xb2, 0xff, 0xf3, 0x13, 0xf5,
+ 0xce, 0x66, 0x87, 0xec, 0x59, 0x5b, 0x17, 0x44, 0xe5, 0x08, 0x8c, 0x21,
+ 0xec, 0x89, 0xa3, 0xca, 0xd1, 0xc1, 0xd9, 0x5c, 0x74, 0x8a, 0x79, 0x18,
+ 0x49, 0x85, 0x1b, 0xa4, 0x36, 0x85, 0x94, 0xb2, 0xf6, 0x60, 0x16, 0x5e,
+ 0xf3, 0x7d, 0x65, 0xb7, 0xe1, 0xe9, 0x30, 0x81, 0x05, 0x88, 0x37, 0x7e,
+ 0xd4, 0xe1, 0x71, 0xac, 0xb6, 0xda, 0xca, 0xc3, 0x7a, 0x21, 0x4d, 0xe8,
+ 0xdd, 0xe2, 0xca, 0x34, 0xf0, 0x3b, 0x21, 0xbf, 0x6b, 0x59, 0xb9, 0x32,
+ 0xcb, 0x8c, 0xe2, 0xca, 0x86, 0x75, 0xd0, 0xe1, 0x01, 0x92, 0xd6, 0x1a,
+ 0x52, 0x5e, 0xe4, 0x23, 0x0e, 0x71, 0xe6, 0x27, 0x9d, 0x3c, 0x04, 0x61,
+ 0xc1, 0x85, 0xfe, 0xf2, 0x41, 0x0b, 0x2f, 0x1d, 0xc4, 0x59, 0x7f, 0x8a,
+ 0x45, 0x87, 0x8e, 0xd6, 0x5d, 0x9b, 0x6b, 0x2b, 0x0f, 0x2f, 0xc6, 0x57,
+ 0xef, 0x36, 0xfc, 0x1a, 0xcb, 0xdb, 0x3e, 0xcb, 0x2f, 0xfc, 0x38, 0x2c,
+ 0x20, 0xcb, 0x38, 0xb2, 0xed, 0x9d, 0x2c, 0xbf, 0x39, 0xdb, 0x77, 0x16,
+ 0x5f, 0xd9, 0xe7, 0xfb, 0xcc, 0xb2, 0xe8, 0xe9, 0x65, 0x74, 0x78, 0x9f,
+ 0x2d, 0xac, 0x44, 0x83, 0xb6, 0xdf, 0xf6, 0x04, 0xb3, 0xe4, 0xe7, 0x59,
+ 0x69, 0x96, 0x5e, 0xf6, 0x01, 0x65, 0x31, 0xae, 0xf8, 0x95, 0xfe, 0xe4,
+ 0x4a, 0x27, 0x89, 0xd6, 0x5d, 0x86, 0xac, 0xbf, 0xfd, 0x86, 0xf9, 0xb9,
+ 0xec, 0xdf, 0x19, 0xd2, 0xca, 0x84, 0x5b, 0xb1, 0x07, 0x8d, 0x08, 0x5e,
+ 0xed, 0x62, 0xcb, 0xe8, 0xfc, 0x76, 0xb2, 0xed, 0xaf, 0x75, 0x65, 0x00,
+ 0xf0, 0x48, 0x8a, 0xf9, 0xb5, 0x12, 0x59, 0x7d, 0x39, 0xe3, 0x8b, 0x2a,
+ 0x73, 0xc4, 0xc2, 0x1b, 0xff, 0x47, 0xdc, 0x3f, 0x7e, 0xb3, 0xeb, 0x2f,
+ 0xfb, 0x5b, 0x20, 0x7e, 0xce, 0xe1, 0x65, 0xff, 0xd1, 0x83, 0x6e, 0x16,
+ 0x6f, 0x62, 0x59, 0x5e, 0x45, 0xdb, 0x9f, 0x04, 0xee, 0xfd, 0xdb, 0xc3,
+ 0x6d, 0xac, 0xbc, 0x59, 0xc5, 0x97, 0xff, 0xfe, 0x8f, 0x31, 0xc5, 0xcd,
+ 0x27, 0xd0, 0x9e, 0x6e, 0xb9, 0xdb, 0x4e, 0xb2, 0xa7, 0x5d, 0xac, 0x1b,
+ 0x41, 0xa4, 0x3d, 0x94, 0xb0, 0xf6, 0xe1, 0xe4, 0xd0, 0xaa, 0xd1, 0x0f,
+ 0xa3, 0x1b, 0x01, 0xd1, 0x2b, 0xf1, 0x97, 0xf0, 0xdd, 0x09, 0x78, 0x85,
+ 0x5b, 0xa3, 0x77, 0xb5, 0xc0, 0xac, 0xb7, 0x16, 0x5f, 0xee, 0xc0, 0xe0,
+ 0x62, 0xed, 0x65, 0x78, 0xf1, 0x48, 0x46, 0xb1, 0x10, 0x6c, 0xc5, 0x7f,
+ 0xa7, 0x1e, 0x7f, 0x8f, 0xd2, 0xcb, 0xed, 0x8f, 0x2d, 0xa9, 0x65, 0xf9,
+ 0xe5, 0xc1, 0x9d, 0x65, 0xff, 0xd9, 0xbf, 0x07, 0x84, 0x19, 0x67, 0x16,
+ 0x5f, 0xb5, 0x1e, 0x10, 0x6b, 0x2b, 0x47, 0xda, 0xe8, 0x96, 0x02, 0xcb,
+ 0xa7, 0x85, 0x96, 0x89, 0xcd, 0x43, 0x08, 0xdf, 0x18, 0xf9, 0xc5, 0x97,
+ 0xf0, 0xe0, 0x05, 0x9d, 0x2c, 0xbf, 0xe9, 0x1d, 0xe5, 0xfe, 0x41, 0xab,
+ 0x2a, 0x11, 0x13, 0x84, 0x4e, 0x5b, 0x7b, 0x8c, 0x4b, 0x2c, 0x05, 0x97,
+ 0xdd, 0xec, 0xe7, 0x4b, 0x2b, 0x46, 0xe0, 0x84, 0x6f, 0xf0, 0x92, 0x8d,
+ 0xec, 0x40, 0x59, 0x7c, 0xfb, 0xb8, 0x4b, 0x2b, 0x11, 0x96, 0xea, 0x64,
+ 0x41, 0xc3, 0x5a, 0xc5, 0x67, 0xdd, 0x90, 0xee, 0x1a, 0x9c, 0xa5, 0xe1,
+ 0x2a, 0x04, 0x92, 0x85, 0x78, 0x61, 0xf1, 0x7d, 0xc9, 0xc3, 0xc5, 0x97,
+ 0x4f, 0x25, 0x97, 0x9b, 0xcc, 0xb2, 0xb0, 0xf5, 0xfa, 0x24, 0xf8, 0xc5,
+ 0xff, 0xd3, 0xf7, 0xe6, 0x13, 0x46, 0xe7, 0x5f, 0x59, 0x7d, 0x9d, 0x4a,
+ 0x16, 0x5e, 0x0b, 0xf1, 0x65, 0x62, 0x22, 0x3c, 0x94, 0x21, 0x15, 0xef,
+ 0xb4, 0xeb, 0x2f, 0xf9, 0x8d, 0x81, 0xc6, 0xfc, 0xf2, 0xcb, 0xf4, 0x10,
+ 0x0f, 0xf5, 0x97, 0xf9, 0x8c, 0xea, 0x5c, 0xce, 0xd6, 0x5f, 0xd2, 0x10,
+ 0x00, 0x8e, 0x96, 0x53, 0x22, 0x37, 0xc4, 0xee, 0x6d, 0x7f, 0x07, 0x91,
+ 0x30, 0x74, 0xb2, 0xf0, 0x73, 0xa5, 0x95, 0xe3, 0xcc, 0xf9, 0x7d, 0xfd,
+ 0xfc, 0x8f, 0xe1, 0xd6, 0x5f, 0xd8, 0x7d, 0x6a, 0x06, 0xb2, 0xfd, 0xd7,
+ 0x3e, 0xd3, 0xac, 0xbf, 0x82, 0x53, 0xf1, 0xba, 0x59, 0x7f, 0xf4, 0x4e,
+ 0x63, 0xf5, 0xcc, 0x1b, 0x71, 0x65, 0x42, 0x27, 0xe4, 0x54, 0x45, 0xf7,
+ 0xec, 0x37, 0xed, 0x3a, 0xcb, 0xc0, 0xce, 0x96, 0x57, 0x47, 0x8c, 0x02,
+ 0x9b, 0xfc, 0x18, 0x9c, 0xb1, 0xa7, 0x59, 0x7f, 0xfe, 0x8d, 0x03, 0x38,
+ 0x41, 0x79, 0x78, 0x2f, 0x3a, 0xcb, 0xf7, 0xf1, 0xcb, 0xb5, 0x95, 0xe3,
+ 0xfc, 0xdd, 0x55, 0xbd, 0xd4, 0x1d, 0x65, 0xff, 0xe1, 0xfa, 0x3a, 0x91,
+ 0x61, 0xf3, 0xaf, 0xac, 0xbf, 0x1f, 0x3d, 0x84, 0xb2, 0x98, 0xfc, 0x5d,
+ 0x2e, 0xff, 0x82, 0xf2, 0x1e, 0x60, 0x38, 0xb2, 0xff, 0xec, 0xdf, 0xe7,
+ 0x96, 0xcf, 0xf9, 0xcd, 0x59, 0x7e, 0x3e, 0x69, 0xc9, 0x65, 0xff, 0xba,
+ 0x97, 0xa0, 0xef, 0xd4, 0xb1, 0x65, 0xfc, 0xdd, 0x75, 0x2c, 0xfa, 0xca,
+ 0x84, 0x4a, 0xe1, 0x30, 0x10, 0x2b, 0xc9, 0xa2, 0x11, 0xc7, 0x21, 0xbd,
+ 0x7e, 0xeb, 0x87, 0x6d, 0xc5, 0x97, 0xff, 0x79, 0xdb, 0xe0, 0x09, 0x13,
+ 0xc9, 0x65, 0xf4, 0x10, 0x45, 0x6b, 0x2e, 0xce, 0x6c, 0x3e, 0x7f, 0x21,
+ 0x54, 0x23, 0x08, 0xa1, 0x27, 0x7f, 0x3c, 0xe0, 0x72, 0x1a, 0xca, 0x9d,
+ 0x7c, 0x08, 0x70, 0xc7, 0xed, 0xeb, 0xa2, 0x26, 0x2c, 0x9a, 0x19, 0x9a,
+ 0x74, 0x39, 0x1f, 0xa1, 0x5e, 0x44, 0xbc, 0x84, 0x77, 0xe3, 0x64, 0xdf,
+ 0x0f, 0x7d, 0xb2, 0x6b, 0xf0, 0x32, 0x66, 0x3a, 0xcb, 0xfe, 0xf7, 0xb1,
+ 0xba, 0x96, 0x69, 0x65, 0x41, 0xf0, 0xb9, 0x45, 0xfe, 0xf8, 0x67, 0x8f,
+ 0xc0, 0xd6, 0x5e, 0xfe, 0x12, 0xcb, 0xde, 0x7d, 0xc5, 0x97, 0xe0, 0xcb,
+ 0x01, 0xc5, 0x97, 0xf8, 0x48, 0xef, 0x6f, 0x35, 0x0b, 0x2f, 0xf8, 0x78,
+ 0x1d, 0x4f, 0xdb, 0x4e, 0xb2, 0xff, 0xf6, 0xfc, 0x21, 0x93, 0x99, 0xce,
+ 0x40, 0x16, 0x5f, 0xff, 0xfc, 0x76, 0xe6, 0xc9, 0xa4, 0x12, 0xfe, 0xcf,
+ 0x44, 0x98, 0xb0, 0xf0, 0xb2, 0xb1, 0x18, 0x01, 0x4b, 0xbe, 0x6d, 0x41,
+ 0xd6, 0x56, 0x8f, 0x0f, 0xc4, 0x57, 0xff, 0xdd, 0xf8, 0x25, 0x9d, 0x49,
+ 0xb8, 0x59, 0xbd, 0x65, 0xfb, 0xd1, 0xe6, 0x35, 0x65, 0xcf, 0x37, 0x0f,
+ 0xeb, 0x75, 0x4a, 0xa1, 0x19, 0xbe, 0x84, 0xe5, 0xff, 0xfe, 0x6d, 0xe4,
+ 0x1e, 0x6c, 0x10, 0xa0, 0x7e, 0x79, 0x67, 0x16, 0x54, 0x95, 0x98, 0x1a,
+ 0x37, 0xa1, 0xff, 0x14, 0x39, 0xbf, 0xe5, 0x06, 0x6f, 0x27, 0xa8, 0x66,
+ 0x45, 0xce, 0x61, 0x93, 0xe3, 0xed, 0x1a, 0x4e, 0x88, 0x1e, 0x5b, 0x25,
+ 0xd3, 0x05, 0x65, 0x8e, 0xb2, 0xba, 0x35, 0x22, 0xb1, 0x8b, 0xfd, 0xf0,
+ 0x04, 0xb8, 0xc3, 0x59, 0x7e, 0x90, 0x33, 0x06, 0xb2, 0xdb, 0xd8, 0xf6,
+ 0x9c, 0xce, 0xfd, 0xe6, 0xd0, 0x02, 0xb2, 0xda, 0xc3, 0xd0, 0x98, 0xa2,
+ 0xfe, 0x33, 0x8f, 0x1d, 0x49, 0x65, 0x41, 0xeb, 0xe1, 0x45, 0xff, 0x67,
+ 0x4f, 0xf8, 0xfb, 0x81, 0x65, 0xff, 0xe9, 0x8a, 0x3f, 0xcf, 0xf5, 0xdb,
+ 0x14, 0xeb, 0x2f, 0xcc, 0x71, 0x26, 0xe2, 0xcb, 0xf8, 0xb3, 0xe1, 0x82,
+ 0x59, 0x7e, 0xea, 0x45, 0x03, 0x59, 0x47, 0x3d, 0x37, 0x2b, 0xbf, 0xa4,
+ 0xc4, 0x77, 0xfa, 0xcb, 0xfe, 0x1e, 0x6c, 0xe3, 0x17, 0x52, 0x59, 0x68,
+ 0xe8, 0xf9, 0xcc, 0x2c, 0xa8, 0x4e, 0xcd, 0x8e, 0x3c, 0x9a, 0xef, 0xa5,
+ 0x08, 0x8b, 0xf3, 0xcb, 0x27, 0x85, 0x97, 0xff, 0x47, 0x39, 0x87, 0xf9,
+ 0x41, 0xf8, 0xb2, 0xff, 0xa3, 0x46, 0xf8, 0xa3, 0x34, 0xb2, 0xfe, 0x37,
+ 0x66, 0x1e, 0x3b, 0x59, 0x7f, 0xf4, 0x75, 0x2f, 0x86, 0x27, 0x6e, 0xbe,
+ 0xb2, 0xff, 0x37, 0x9f, 0xb8, 0x21, 0xac, 0xa6, 0x45, 0x51, 0x18, 0xf1,
+ 0x1e, 0xfe, 0x8e, 0xc0, 0x70, 0x81, 0x65, 0xf6, 0xf6, 0x21, 0xac, 0xbf,
+ 0xf1, 0x40, 0xfd, 0x07, 0x2c, 0xed, 0x65, 0xe6, 0x2f, 0xac, 0xac, 0x3f,
+ 0xb9, 0x88, 0xfc, 0x7b, 0x7f, 0x87, 0xc6, 0xf7, 0xb0, 0x6b, 0x2f, 0xfe,
+ 0x68, 0xe1, 0x3c, 0xb6, 0x73, 0x34, 0xb2, 0xff, 0x0c, 0xb2, 0x5e, 0x81,
+ 0xac, 0xbc, 0x4f, 0xa5, 0x97, 0xce, 0xef, 0xba, 0xb2, 0xff, 0xfe, 0xc1,
+ 0xec, 0x60, 0x46, 0xcf, 0xfb, 0x3f, 0xe7, 0x92, 0xcb, 0xff, 0xb9, 0x3e,
+ 0x19, 0x84, 0x1d, 0xd8, 0x17, 0x88, 0x9c, 0x38, 0xde, 0xf2, 0x3a, 0x84,
+ 0xcf, 0x9a, 0x19, 0xd7, 0xfb, 0xa9, 0x72, 0x69, 0x44, 0xeb, 0x28, 0x6b,
+ 0x8c, 0xdd, 0x93, 0xcc, 0x87, 0xa8, 0x71, 0x1c, 0xbb, 0xd0, 0xaa, 0x72,
+ 0xf2, 0x33, 0xfc, 0x70, 0x41, 0x27, 0xbf, 0xff, 0xbf, 0x9d, 0x7f, 0x5a,
+ 0x8f, 0x80, 0x42, 0x97, 0xb1, 0x65, 0xcd, 0xbd, 0x65, 0xf4, 0x14, 0xb8,
+ 0xb2, 0xcd, 0xd2, 0x25, 0xa6, 0x5d, 0x00, 0xc5, 0xfe, 0xd4, 0xe5, 0x1d,
+ 0xb4, 0x96, 0x57, 0x8f, 0xad, 0xcd, 0xef, 0xde, 0x8d, 0xe3, 0x85, 0x97,
+ 0x86, 0xe4, 0xb2, 0xdb, 0xd6, 0x5f, 0xba, 0xf9, 0x47, 0x96, 0x5b, 0x50,
+ 0x6e, 0xdc, 0x4e, 0xfb, 0xa9, 0xa3, 0x4b, 0x2d, 0xa5, 0x95, 0x86, 0xd4,
+ 0x24, 0x95, 0x24, 0x7c, 0x8c, 0xa7, 0x4a, 0xdc, 0x5a, 0xbe, 0x6d, 0xf8,
+ 0x35, 0x97, 0xc5, 0xfc, 0x25, 0x97, 0x17, 0xf4, 0x78, 0x6e, 0x47, 0x7f,
+ 0xdd, 0x4b, 0x81, 0xfc, 0x7f, 0x8b, 0x2f, 0xda, 0x93, 0xf4, 0x62, 0xcb,
+ 0xfd, 0xc3, 0x1c, 0x71, 0xd7, 0x16, 0x54, 0x23, 0x1b, 0x0b, 0x18, 0xed,
+ 0xca, 0xaf, 0xdc, 0x0f, 0xe0, 0x96, 0x5f, 0xe0, 0xf5, 0x2f, 0xf0, 0x3b,
+ 0x8b, 0x2f, 0x72, 0x3a, 0x59, 0x7a, 0x3d, 0xc5, 0x97, 0x39, 0x9d, 0x1b,
+ 0x90, 0x0e, 0xd4, 0x93, 0x00, 0xc3, 0x9f, 0x13, 0x93, 0x95, 0xfe, 0xce,
+ 0xb6, 0x67, 0x9b, 0xcb, 0x2e, 0xf0, 0xd6, 0x5c, 0xdd, 0xac, 0xb9, 0xfe,
+ 0x33, 0x5d, 0xb6, 0x2f, 0x5a, 0x44, 0x93, 0xb1, 0xda, 0x16, 0x5f, 0xda,
+ 0x86, 0x93, 0xf1, 0x65, 0x0c, 0xde, 0x74, 0x21, 0x7f, 0xdf, 0xe0, 0x64,
+ 0x20, 0xdb, 0xeb, 0x2a, 0x0f, 0x75, 0xc8, 0xaf, 0xde, 0x8c, 0x93, 0xac,
+ 0xbd, 0x8d, 0xc5, 0x97, 0xef, 0xff, 0x03, 0x3a, 0xcb, 0xff, 0xe9, 0xdf,
+ 0xd8, 0x3d, 0x98, 0x45, 0x8c, 0x05, 0x95, 0x3a, 0x24, 0xfb, 0x1b, 0xd1,
+ 0x4d, 0xff, 0x7b, 0xb6, 0x7d, 0x9c, 0x7f, 0x2c, 0xa1, 0xa6, 0x4d, 0x90,
+ 0xb9, 0x73, 0x2b, 0xe2, 0x89, 0x32, 0xcb, 0xce, 0x53, 0x2c, 0xbd, 0xd4,
+ 0x99, 0x65, 0x9c, 0xe6, 0xe4, 0x87, 0x2f, 0x06, 0x09, 0x65, 0xff, 0xfe,
+ 0x6f, 0xc1, 0x3c, 0xb0, 0x7c, 0x7d, 0x37, 0x9b, 0x7a, 0xcb, 0xe8, 0x29,
+ 0x71, 0x65, 0x69, 0x31, 0x9f, 0x2c, 0x91, 0x2e, 0xf1, 0xb1, 0x17, 0xef,
+ 0xff, 0xdc, 0x2d, 0x9e, 0x76, 0xf8, 0x02, 0x44, 0xf2, 0x59, 0x7f, 0xff,
+ 0xf4, 0x6b, 0x26, 0x83, 0xe7, 0x6c, 0x3f, 0x47, 0xf8, 0x6e, 0xb3, 0x75,
+ 0x65, 0xfe, 0xf3, 0x1b, 0xb6, 0x1d, 0x1a, 0xb2, 0xff, 0x8f, 0x05, 0xdb,
+ 0x90, 0x05, 0x2b, 0x2f, 0xf3, 0x1f, 0x59, 0xb6, 0xc0, 0x59, 0x7f, 0xd0,
+ 0x0d, 0x6a, 0x0c, 0x1f, 0x4b, 0x2f, 0xf1, 0x87, 0xf4, 0x31, 0x4e, 0xb2,
+ 0xff, 0xf3, 0xc9, 0xb5, 0x9d, 0x4d, 0x28, 0xd4, 0xeb, 0x2a, 0x11, 0x00,
+ 0x03, 0x4b, 0xff, 0xe2, 0xce, 0x61, 0xe3, 0xbc, 0xfb, 0x6b, 0x16, 0x57,
+ 0x69, 0xea, 0x1c, 0xe7, 0xc7, 0x80, 0x35, 0xfc, 0x2e, 0xf7, 0x91, 0x5f,
+ 0xfa, 0x6e, 0x7c, 0x3d, 0x60, 0xdc, 0x96, 0x5c, 0x1e, 0x96, 0x5f, 0xd0,
+ 0x78, 0xce, 0xbe, 0xb2, 0xd8, 0x73, 0xc5, 0xf8, 0xc5, 0x42, 0xb5, 0x6c,
+ 0x94, 0x94, 0xec, 0x01, 0x84, 0x2d, 0xfd, 0x3e, 0x69, 0xbb, 0x85, 0x97,
+ 0xc4, 0x38, 0x3a, 0xcb, 0xff, 0xe0, 0x97, 0xf9, 0xe6, 0x98, 0xa0, 0xef,
+ 0x25, 0x97, 0xf6, 0xa1, 0xa4, 0xfc, 0x59, 0x70, 0x5d, 0x65, 0xb3, 0x61,
+ 0xe1, 0x11, 0x65, 0x1d, 0x17, 0x3b, 0xe1, 0x23, 0x7f, 0x38, 0x30, 0x6f,
+ 0x25, 0x95, 0x09, 0x98, 0x64, 0x36, 0x98, 0xaa, 0xf8, 0x1c, 0xda, 0x62,
+ 0x95, 0x97, 0xe8, 0xed, 0xf5, 0x3a, 0xca, 0x64, 0xf9, 0xfd, 0x1a, 0xf3,
+ 0x99, 0x91, 0x6d, 0xfb, 0xc0, 0x6d, 0x1a, 0xb2, 0xf7, 0x62, 0x49, 0x65,
+ 0xf4, 0x68, 0x57, 0xc5, 0x95, 0xe3, 0xc5, 0x00, 0xfd, 0xfe, 0x1f, 0xb0,
+ 0x01, 0xff, 0x16, 0x5f, 0xff, 0xff, 0xd9, 0xb9, 0x83, 0xe4, 0x0e, 0x3f,
+ 0xec, 0x0f, 0x7e, 0x8e, 0x7b, 0x38, 0xf0, 0x75, 0x97, 0xef, 0x64, 0xa4,
+ 0xeb, 0x2f, 0xff, 0xb3, 0xdd, 0xf9, 0xa6, 0x27, 0x33, 0xf9, 0xe5, 0x95,
+ 0x89, 0xe3, 0x33, 0x73, 0x91, 0x70, 0xd3, 0xf0, 0x8a, 0xdb, 0x27, 0xbd,
+ 0xc1, 0x00, 0xb2, 0xf4, 0x11, 0xab, 0x2a, 0x0d, 0xd7, 0x07, 0xaa, 0x1b,
+ 0x9a, 0xc9, 0xe3, 0x27, 0x1c, 0x7a, 0x79, 0x39, 0x65, 0xdc, 0x73, 0xed,
+ 0x18, 0xd4, 0xd2, 0x91, 0xb5, 0x0c, 0xe3, 0xc2, 0xef, 0xd1, 0xa3, 0x3c,
+ 0x69, 0xa0, 0x4d, 0x29, 0x75, 0x7f, 0x94, 0x5e, 0x19, 0x40, 0xe2, 0x42,
+ 0x5e, 0xff, 0xec, 0x20, 0x66, 0x6b, 0x9f, 0x8c, 0x59, 0x7f, 0xdd, 0x7f,
+ 0x34, 0xd3, 0xb9, 0xd6, 0x5e, 0xcd, 0xf8, 0xb2, 0xd8, 0x04, 0x4c, 0x12,
+ 0x0f, 0x0e, 0xaf, 0x0a, 0xe4, 0xcb, 0x2f, 0xa0, 0x9e, 0x4b, 0x2f, 0xd9,
+ 0xb8, 0xe4, 0x0d, 0x87, 0x81, 0xa2, 0x0b, 0xc7, 0x79, 0x96, 0x5f, 0xcc,
+ 0x78, 0xf0, 0x83, 0x59, 0x7f, 0xc2, 0x7d, 0x88, 0x32, 0xce, 0x2c, 0xa9,
+ 0x1f, 0x3b, 0x17, 0x5f, 0xbc, 0xd1, 0xae, 0x2c, 0xae, 0xd1, 0x99, 0xe8,
+ 0x42, 0x6f, 0x21, 0xbf, 0xff, 0x4b, 0x85, 0x9f, 0xe3, 0x61, 0xff, 0xac,
+ 0x31, 0x65, 0xff, 0xbc, 0xc7, 0x1e, 0x4d, 0x19, 0xa5, 0x97, 0xa5, 0x1d,
+ 0x2c, 0xbf, 0x04, 0x83, 0x1d, 0x2c, 0xbc, 0x7c, 0xfa, 0xcb, 0xe8, 0x03,
+ 0x9d, 0x65, 0xa5, 0x88, 0xc0, 0x98, 0xf8, 0xe3, 0xa0, 0x28, 0x21, 0xca,
+ 0xe9, 0x36, 0x42, 0x8c, 0x56, 0xfb, 0x8d, 0xf8, 0x59, 0x50, 0x79, 0x6e,
+ 0x55, 0x7e, 0x2c, 0x00, 0x78, 0xb2, 0xff, 0x6c, 0x27, 0x9c, 0xa3, 0xa5,
+ 0x97, 0xfe, 0xf3, 0x7f, 0xd8, 0xdf, 0x80, 0x2c, 0xbb, 0xb6, 0xc4, 0x4c,
+ 0xe8, 0x9f, 0x86, 0xb7, 0xbb, 0xe7, 0xd6, 0x5f, 0xcf, 0xf0, 0x08, 0x52,
+ 0x59, 0x53, 0x9e, 0x67, 0x87, 0xaf, 0xf0, 0x63, 0x7e, 0x7d, 0xb4, 0xb2,
+ 0xfb, 0xbf, 0x34, 0xcb, 0x2f, 0xff, 0xfb, 0x40, 0x00, 0x79, 0xe6, 0xfc,
+ 0xb3, 0xce, 0x06, 0x1c, 0x2c, 0xbf, 0xe7, 0xd6, 0x6f, 0xcd, 0xf0, 0x35,
+ 0x95, 0x88, 0xa1, 0x03, 0x35, 0xff, 0xf6, 0x1a, 0x6b, 0x0f, 0xcd, 0x37,
+ 0x9b, 0xaf, 0xac, 0xa3, 0x9f, 0xa9, 0x11, 0x54, 0x26, 0xb7, 0x91, 0x9d,
+ 0x5c, 0x1d, 0x2c, 0xbd, 0xdb, 0xe9, 0x65, 0xff, 0xa7, 0xc2, 0x3e, 0x7f,
+ 0x82, 0x71, 0x65, 0xfb, 0x9d, 0xc6, 0x8d, 0x59, 0x7f, 0x30, 0x3a, 0x96,
+ 0x7d, 0x65, 0x4e, 0x8c, 0xcf, 0x0b, 0xb8, 0xe8, 0x10, 0x37, 0x95, 0x5f,
+ 0x4b, 0xf8, 0x05, 0x97, 0xb8, 0xd3, 0x2c, 0xae, 0x8d, 0xff, 0x08, 0xaf,
+ 0xbf, 0xe0, 0xf6, 0xb2, 0xfd, 0x8c, 0x3f, 0x32, 0xca, 0x9c, 0xf2, 0xa4,
+ 0x49, 0x79, 0xf4, 0x6a, 0xcb, 0xff, 0x9e, 0x5b, 0x38, 0x59, 0xfe, 0x66,
+ 0xe2, 0xca, 0x84, 0x7a, 0x63, 0x63, 0x91, 0x84, 0x76, 0xff, 0xdd, 0x7f,
+ 0x8c, 0x50, 0x07, 0x3a, 0xca, 0x59, 0x58, 0x79, 0x3b, 0xcf, 0xaf, 0x48,
+ 0xfe, 0x59, 0x53, 0x9e, 0x07, 0xc8, 0xef, 0xff, 0xfd, 0xb7, 0x9f, 0xf3,
+ 0x8c, 0x59, 0x66, 0xf2, 0xce, 0x71, 0xba, 0xfa, 0xcb, 0x74, 0xb2, 0xfb,
+ 0x0f, 0x1b, 0x8b, 0x2d, 0xd0, 0xac, 0xdb, 0x70, 0x4a, 0xf1, 0xac, 0x62,
+ 0xcb, 0xf1, 0x8d, 0x84, 0x6a, 0xca, 0x63, 0xc6, 0x08, 0xf5, 0xfe, 0x18,
+ 0x99, 0x37, 0x9c, 0xeb, 0x2b, 0x13, 0x93, 0x62, 0x37, 0x85, 0x41, 0x39,
+ 0x04, 0x86, 0xfb, 0xcf, 0xbb, 0xc5, 0x97, 0xfe, 0xce, 0xbe, 0x66, 0x10,
+ 0xfd, 0x0b, 0x2c, 0xfd, 0x9f, 0x26, 0x89, 0x6d, 0x8b, 0x2f, 0xb5, 0x3b,
+ 0x4e, 0xb2, 0xf7, 0x9b, 0x4b, 0x2c, 0xec, 0x78, 0x13, 0x12, 0x56, 0xc3,
+ 0xf7, 0xf2, 0x85, 0xf7, 0x0a, 0x0e, 0xb2, 0xff, 0xa7, 0x8e, 0x63, 0x6f,
+ 0x73, 0xac, 0xbd, 0xbf, 0x09, 0x65, 0x42, 0x27, 0x3a, 0x24, 0x72, 0x1f,
+ 0x9d, 0x5e, 0xf4, 0x8e, 0xb2, 0xef, 0x32, 0xca, 0xc3, 0x67, 0xf1, 0xda,
+ 0x86, 0x6c, 0xf4, 0x9d, 0x32, 0x30, 0xe3, 0x63, 0xe7, 0xea, 0x17, 0x2d,
+ 0x08, 0x7d, 0x11, 0xfa, 0x38, 0xf7, 0x87, 0xa1, 0x46, 0xff, 0xc9, 0x4a,
+ 0xdf, 0x85, 0x80, 0x63, 0x3b, 0xdb, 0x6f, 0xbf, 0xd1, 0x33, 0x75, 0xc0,
+ 0x9d, 0x65, 0xcc, 0x62, 0xcb, 0x76, 0xb2, 0xb0, 0xd4, 0x9c, 0x5e, 0xf3,
+ 0xf5, 0x25, 0x95, 0x3a, 0x26, 0xc6, 0xbd, 0xf2, 0x0b, 0xfb, 0xec, 0x4c,
+ 0x0e, 0x2c, 0xbe, 0x19, 0x67, 0x96, 0x58, 0x7b, 0x0f, 0x34, 0x42, 0xcb,
+ 0xf6, 0x70, 0x3a, 0x9d, 0x65, 0xff, 0xff, 0xff, 0x74, 0x0d, 0x77, 0xcd,
+ 0xcd, 0xed, 0xb4, 0x1a, 0x26, 0xd5, 0xc9, 0x6d, 0x2d, 0x0a, 0x9b, 0x01,
+ 0xb9, 0xb3, 0x67, 0xb6, 0xd6, 0x56, 0x26, 0x30, 0x45, 0x62, 0x14, 0xde,
+ 0x3b, 0xfd, 0x65, 0xd2, 0xfa, 0xcb, 0xfb, 0xb1, 0xb6, 0xf8, 0x1a, 0xcb,
+ 0x79, 0x65, 0x80, 0xb2, 0xee, 0x49, 0x65, 0x42, 0x27, 0x06, 0x38, 0xe2,
+ 0xe0, 0x30, 0xe0, 0x88, 0x44, 0x6f, 0xe9, 0xe6, 0x90, 0xa3, 0x53, 0xac,
+ 0xba, 0x40, 0x59, 0x79, 0xf3, 0x4b, 0x2f, 0x16, 0x7d, 0x65, 0xef, 0x61,
+ 0xd6, 0x57, 0x47, 0xd3, 0xe1, 0x72, 0x1b, 0xf8, 0xdd, 0xdf, 0x25, 0x97,
+ 0xa3, 0xae, 0x2c, 0xbe, 0x62, 0x96, 0x2c, 0xbd, 0x3b, 0x92, 0xca, 0x19,
+ 0xec, 0x9c, 0x77, 0xe4, 0x17, 0x6b, 0xcb, 0x2f, 0xa0, 0x6f, 0x25, 0x97,
+ 0xec, 0xff, 0x9b, 0xeb, 0x2f, 0xcf, 0xd6, 0x75, 0xf5, 0x95, 0xe3, 0xd0,
+ 0xf9, 0x3d, 0xe7, 0xd4, 0x96, 0x5e, 0xf6, 0x1d, 0x65, 0x48, 0xdc, 0x7c,
+ 0x72, 0xff, 0x8d, 0x9b, 0x33, 0xbf, 0xc1, 0xab, 0x2f, 0x04, 0xa7, 0x59,
+ 0x5b, 0x13, 0x5c, 0x9c, 0x5c, 0xd7, 0x1e, 0x96, 0xb4, 0x43, 0xe3, 0xcb,
+ 0xe3, 0xed, 0xee, 0x0d, 0x65, 0xa7, 0x59, 0x6d, 0x2c, 0xa9, 0xcd, 0x1b,
+ 0x09, 0x5f, 0x4e, 0xef, 0xe5, 0x97, 0xe0, 0xce, 0xef, 0xe5, 0x97, 0xec,
+ 0x18, 0x1f, 0xeb, 0x2b, 0x61, 0xf8, 0xf8, 0x8b, 0x79, 0x45, 0xf8, 0x49,
+ 0x06, 0x38, 0xb2, 0xa7, 0x3d, 0xc3, 0x4c, 0xee, 0xeb, 0xeb, 0x2f, 0xff,
+ 0xe6, 0xd6, 0x1d, 0xfa, 0x16, 0x30, 0xbe, 0xa4, 0xe0, 0x59, 0x7e, 0x9b,
+ 0xcd, 0xd7, 0xd6, 0x57, 0x91, 0x0f, 0xf5, 0xdb, 0xf6, 0x10, 0xfd, 0x0b,
+ 0x2b, 0x6b, 0x5d, 0x78, 0x88, 0x4f, 0xc8, 0xf3, 0x1b, 0xda, 0x38, 0xb3,
+ 0xae, 0xf9, 0x31, 0xe1, 0xdc, 0x44, 0x81, 0x84, 0xf9, 0x84, 0x77, 0xfd,
+ 0x83, 0x1b, 0x75, 0x9d, 0x7d, 0x65, 0xf7, 0x65, 0x12, 0x59, 0x5e, 0x3d,
+ 0xc7, 0x3a, 0xbf, 0xd1, 0x9f, 0x8f, 0x38, 0xd6, 0x5f, 0xf6, 0x7e, 0x3b,
+ 0x12, 0x01, 0x8b, 0x2f, 0x47, 0x52, 0x59, 0x53, 0xa2, 0xa0, 0x64, 0x26,
+ 0x18, 0xee, 0x9c, 0xdf, 0x66, 0x17, 0xd6, 0x5f, 0xfe, 0xde, 0xc4, 0x0f,
+ 0x33, 0xcb, 0xed, 0x3a, 0xcb, 0xe0, 0xbe, 0xa4, 0xb2, 0xa0, 0xfb, 0x46,
+ 0x97, 0x7f, 0xf0, 0xe0, 0x7a, 0x8f, 0xb7, 0x6c, 0x35, 0x97, 0xc1, 0x7d,
+ 0x49, 0x65, 0xe8, 0xdd, 0x92, 0xca, 0x19, 0xe0, 0xcc, 0x45, 0x7f, 0x7f,
+ 0xb1, 0x8c, 0xfa, 0x59, 0x7e, 0xfb, 0x14, 0x01, 0x65, 0xff, 0x4d, 0xcd,
+ 0xee, 0x53, 0x84, 0x6b, 0x2f, 0xe7, 0x30, 0x00, 0x3e, 0xda, 0xcb, 0xec,
+ 0xfe, 0x1d, 0x65, 0xc4, 0x6a, 0xca, 0x73, 0x70, 0x12, 0x1a, 0x92, 0x22,
+ 0xb8, 0xd5, 0x7e, 0x91, 0x05, 0xf8, 0xb2, 0xff, 0xd0, 0x41, 0xfc, 0x82,
+ 0x5f, 0xe2, 0xca, 0xc3, 0xe5, 0xd1, 0x3d, 0xff, 0x8a, 0x3f, 0x2c, 0xdc,
+ 0x72, 0x02, 0xcb, 0xc0, 0x60, 0x2c, 0xbe, 0x9e, 0x6f, 0x32, 0xcb, 0x7b,
+ 0x0f, 0x00, 0x23, 0x97, 0x39, 0xd6, 0x5f, 0xf6, 0xe7, 0x9b, 0x61, 0xba,
+ 0xce, 0x2c, 0xae, 0xcf, 0x54, 0x22, 0xd7, 0xfe, 0x27, 0x37, 0xcf, 0x2e,
+ 0x30, 0xd6, 0x5f, 0xbc, 0xc4, 0xf3, 0xac, 0xb7, 0x6b, 0x2f, 0x83, 0x2c,
+ 0xe7, 0x66, 0xe4, 0x89, 0xe8, 0xe8, 0xaf, 0x27, 0x7b, 0xc5, 0x9f, 0x59,
+ 0x70, 0x87, 0x59, 0x4c, 0x7a, 0xa4, 0x45, 0xf1, 0xbb, 0xba, 0x1a, 0xcb,
+ 0xb7, 0xba, 0xcb, 0xfd, 0x1a, 0x8e, 0xf3, 0x7e, 0x2c, 0xa8, 0x5e, 0x11,
+ 0x9d, 0x0a, 0x50, 0x8d, 0x19, 0x0e, 0x42, 0x14, 0xd2, 0x3e, 0x8c, 0x18,
+ 0x9a, 0x68, 0x63, 0xea, 0x11, 0x07, 0x21, 0xf3, 0xf9, 0x3e, 0x7e, 0x32,
+ 0x70, 0x96, 0xef, 0x18, 0xdb, 0x18, 0xbf, 0x4d, 0x1f, 0x2d, 0xeb, 0x2f,
+ 0xa6, 0xc6, 0x02, 0xca, 0xd8, 0x79, 0x90, 0x55, 0x7f, 0xf4, 0x6f, 0xd4,
+ 0x6b, 0x1b, 0xd0, 0x35, 0x97, 0x46, 0x2c, 0xa2, 0x3d, 0x9e, 0x22, 0x5c,
+ 0xe7, 0x59, 0x74, 0xdb, 0x6b, 0x28, 0x8d, 0x8e, 0xf1, 0x6b, 0xff, 0xf3,
+ 0x1f, 0xa9, 0x73, 0x67, 0xb3, 0xfc, 0x27, 0xfa, 0xcb, 0x83, 0xf5, 0x95,
+ 0x24, 0xd7, 0xf1, 0xf1, 0x94, 0xbe, 0x45, 0xb6, 0xb1, 0x61, 0x7b, 0x5c,
+ 0x30, 0xf9, 0xb6, 0xa2, 0xe1, 0x4c, 0x2a, 0x36, 0x88, 0x51, 0x8a, 0x23,
+ 0x1b, 0xda, 0x50, 0x83, 0x15, 0x08, 0xc5, 0x52, 0x06, 0xd3, 0x63, 0x8a,
+ 0x4c, 0x7c, 0xf2, 0xa6, 0xa5, 0x38, 0xe0, 0x3a, 0x42, 0x16, 0x56, 0xa8,
+ 0x46, 0xcb, 0x0c, 0xee, 0x7b, 0x1b, 0xa9, 0xd6, 0x66, 0x9c, 0x11, 0x9a,
+ 0x90, 0x1f, 0xa9, 0xf4, 0x03, 0xce, 0xc8, 0xfa, 0xb2, 0x38, 0x79, 0xe8,
+ 0x20, 0x4e, 0x5b, 0x0a, 0xe1, 0xb4, 0x54, 0xd4, 0x2e, 0x57, 0x48, 0x5f,
+ 0xa7, 0xb5, 0x06, 0x39, 0x7d, 0xf1, 0xcb, 0x19, 0x0c, 0xcd, 0xb9, 0xdc,
+ 0xd1, 0x27, 0xf1, 0xb7, 0x65, 0x59, 0xd0, 0xb8, 0x64, 0x01, 0x32, 0xa7,
+ 0xb1, 0x89, 0x89, 0x7f, 0xf8, 0x59, 0xde, 0x42, 0xf3, 0x5d, 0xbb, 0xf6,
+ 0xa8, 0x9b, 0x17, 0xed, 0x76, 0xef, 0xda, 0xa2, 0xad, 0x5c, 0x0d, 0xeb,
+ 0x2e, 0xe6, 0xda, 0xcb, 0x0b, 0xc3, 0xe9, 0xf1, 0xb7, 0x06, 0x6e, 0xdf,
+ 0xa5, 0x97, 0x3c, 0x2c, 0xbf, 0xd2, 0x90, 0x7e, 0x51, 0x25, 0x97, 0xd9,
+ 0xe7, 0xfa, 0xcb, 0x0a, 0x70, 0xf5, 0x08, 0xce, 0xff, 0xff, 0xd2, 0x8d,
+ 0xf0, 0xda, 0xed, 0x8e, 0xf2, 0x62, 0xc1, 0xe1, 0xab, 0x2f, 0xef, 0xb6,
+ 0xce, 0x63, 0x2c, 0xbf, 0xf4, 0xb2, 0x58, 0xf2, 0x28, 0x3a, 0xcb, 0x6a,
+ 0x0f, 0xa9, 0x8b, 0xaf, 0xf6, 0xb3, 0xb8, 0x00, 0x87, 0x59, 0x7f, 0xb8,
+ 0xff, 0x17, 0xc2, 0x85, 0x97, 0xf4, 0x4f, 0xa8, 0xc1, 0xac, 0xa9, 0x1f,
+ 0x0f, 0x8d, 0x2f, 0xff, 0xd1, 0x3c, 0x6a, 0x0f, 0x11, 0xff, 0x30, 0x0e,
+ 0xb2, 0xa0, 0xfd, 0xbc, 0x45, 0x7a, 0x07, 0x32, 0xca, 0x92, 0xa4, 0x66,
+ 0x86, 0xb6, 0x89, 0xbd, 0x18, 0x67, 0xc8, 0x6f, 0xb4, 0x7f, 0x0d, 0x65,
+ 0xff, 0xda, 0x91, 0x67, 0xf9, 0x07, 0xff, 0x6b, 0x2a, 0x0f, 0xa0, 0x24,
+ 0x77, 0x87, 0x84, 0xb2, 0xff, 0xce, 0xdb, 0xb1, 0xef, 0x96, 0x49, 0x65,
+ 0xfa, 0x4d, 0xdb, 0xe9, 0x65, 0x78, 0xf9, 0xf8, 0x7f, 0x79, 0xdf, 0xb5,
+ 0x45, 0x68, 0xbf, 0x1b, 0xd7, 0x03, 0xd2, 0xca, 0x83, 0xf7, 0xec, 0x89,
+ 0x8a, 0x6f, 0xe0, 0xb1, 0xba, 0x81, 0xac, 0xbf, 0xd1, 0xa0, 0x09, 0xc8,
+ 0xc5, 0x97, 0xff, 0x9b, 0xf2, 0x8e, 0xfc, 0xdf, 0xe3, 0xf4, 0xb2, 0xb4,
+ 0x8d, 0xa3, 0x97, 0x78, 0xbb, 0x79, 0x9d, 0xfc, 0x0d, 0x99, 0xa6, 0x35,
+ 0x65, 0xff, 0x60, 0xdb, 0x93, 0x14, 0x0d, 0x65, 0x0c, 0xfa, 0x1c, 0xc2,
+ 0xff, 0xa3, 0xbc, 0x3e, 0x17, 0xf6, 0xd6, 0x5f, 0xef, 0x46, 0x81, 0xfc,
+ 0x9d, 0x65, 0xfe, 0x2c, 0x96, 0xc6, 0xf4, 0x96, 0x5d, 0xe6, 0x3a, 0x28,
+ 0xfc, 0x77, 0xf3, 0x4b, 0xff, 0x9e, 0x5b, 0x35, 0x1f, 0x6e, 0xd8, 0x6b,
+ 0x2d, 0x25, 0x96, 0x94, 0x1e, 0xbf, 0x48, 0xd7, 0x83, 0xcf, 0xac, 0xbf,
+ 0xff, 0x49, 0xc9, 0xbf, 0x1e, 0xef, 0x06, 0x51, 0xc5, 0x97, 0xff, 0xe6,
+ 0xdd, 0x82, 0x0c, 0x9b, 0x9c, 0x8d, 0x87, 0xed, 0x65, 0x32, 0x2b, 0x5d,
+ 0x4e, 0xe6, 0xe9, 0x65, 0xff, 0xf7, 0x71, 0xac, 0x03, 0x9d, 0xe5, 0x0d,
+ 0xda, 0xcb, 0xff, 0xe9, 0x73, 0x0a, 0x0e, 0xf9, 0xff, 0xc1, 0xd6, 0x54,
+ 0x22, 0x71, 0xd3, 0xeb, 0x48, 0xd4, 0xfc, 0x2c, 0xe8, 0xe9, 0xf3, 0xfa,
+ 0x19, 0x5f, 0x87, 0xad, 0xff, 0xff, 0xdb, 0xdb, 0xfc, 0xc3, 0x7b, 0xf3,
+ 0x7f, 0x26, 0x28, 0x3c, 0xf8, 0x62, 0xcb, 0xff, 0xef, 0xbe, 0x70, 0x79,
+ 0x2f, 0x46, 0xf1, 0xc2, 0xcb, 0xff, 0xff, 0xf9, 0xbe, 0x3c, 0x0f, 0x36,
+ 0x7b, 0x3b, 0xf0, 0x67, 0x6c, 0x2e, 0xa5, 0xce, 0x06, 0x16, 0x53, 0xa3,
+ 0x74, 0x94, 0x2a, 0x13, 0x75, 0x78, 0xd5, 0x2f, 0xef, 0xbf, 0xb6, 0x0e,
+ 0x16, 0x5e, 0x90, 0x66, 0x59, 0x50, 0x79, 0xae, 0x5f, 0x7d, 0x2f, 0xb4,
+ 0xeb, 0x2f, 0xdc, 0xe3, 0x94, 0xeb, 0x2f, 0xc2, 0x7c, 0xa0, 0x0b, 0x2d,
+ 0xe5, 0x95, 0xd2, 0x21, 0x0e, 0x47, 0xbc, 0xa0, 0x42, 0x8b, 0xff, 0xe0,
+ 0x3e, 0x79, 0xdb, 0x76, 0x0e, 0x4e, 0x6a, 0xcb, 0xff, 0x37, 0x30, 0x7d,
+ 0x72, 0x35, 0xc5, 0x97, 0xf9, 0xe5, 0xf6, 0x9f, 0xcc, 0xb2, 0xa1, 0x30,
+ 0x3c, 0x41, 0xed, 0x41, 0x8f, 0xef, 0xd9, 0xe6, 0xc3, 0xac, 0xbf, 0x30,
+ 0x0e, 0xda, 0x59, 0x7f, 0xe1, 0xb6, 0xf6, 0x1e, 0x19, 0x9e, 0x59, 0x7f,
+ 0xff, 0xcf, 0xf8, 0x27, 0x9e, 0x35, 0x0d, 0x28, 0x39, 0x41, 0xab, 0x2f,
+ 0xf3, 0x71, 0x82, 0x2b, 0x1c, 0x2c, 0xa2, 0x44, 0xcf, 0xd8, 0xef, 0xef,
+ 0x47, 0x64, 0xe7, 0x59, 0x7f, 0xe7, 0x6e, 0xfc, 0xe1, 0x9f, 0x4c, 0xb2,
+ 0x98, 0xfb, 0x08, 0xb6, 0xf7, 0x61, 0x85, 0x97, 0xfa, 0x78, 0xc2, 0x1f,
+ 0xa1, 0x65, 0xb1, 0x8f, 0x3d, 0xc7, 0x6a, 0x75, 0x49, 0x03, 0x26, 0xc2,
+ 0x76, 0x86, 0xcf, 0xa1, 0x1c, 0x4d, 0xf7, 0xff, 0x9f, 0xae, 0x7a, 0x39,
+ 0x9f, 0x27, 0x35, 0x65, 0xfe, 0x94, 0x6a, 0x78, 0xd4, 0xeb, 0x2f, 0xa5,
+ 0xac, 0x3a, 0xcb, 0xd9, 0xa0, 0x2c, 0xbf, 0x4d, 0x83, 0x3e, 0xe2, 0xcb,
+ 0xf8, 0xa0, 0xce, 0xa5, 0xc5, 0x95, 0xd2, 0x26, 0x58, 0x8a, 0x61, 0xcd,
+ 0xd2, 0xcb, 0xc6, 0x87, 0xb5, 0x95, 0x09, 0x97, 0x64, 0x33, 0x8d, 0x41,
+ 0xbf, 0xff, 0xff, 0x37, 0x79, 0xf8, 0x2f, 0xf3, 0x64, 0x30, 0xf0, 0xfb,
+ 0x35, 0x0d, 0x27, 0xe2, 0xcb, 0xff, 0xce, 0xdf, 0x0e, 0x9f, 0x82, 0x61,
+ 0x76, 0xb2, 0xff, 0xfb, 0x40, 0xe0, 0x3c, 0xf2, 0x6f, 0x94, 0x01, 0x65,
+ 0x62, 0x63, 0xbe, 0x84, 0x20, 0x52, 0xaf, 0xec, 0xfb, 0x90, 0x02, 0xb2,
+ 0xfe, 0xf6, 0xc6, 0x9d, 0xc9, 0x65, 0xfc, 0x7e, 0x0c, 0x9c, 0xc5, 0x97,
+ 0xe0, 0x73, 0x69, 0xed, 0x3d, 0xa6, 0xb2, 0xa0, 0xfa, 0x5c, 0xba, 0xfd,
+ 0xdb, 0x0f, 0x09, 0x65, 0xf6, 0x9a, 0x0e, 0xb2, 0xe7, 0x1a, 0xca, 0xe8,
+ 0xdb, 0x80, 0x86, 0xb1, 0x10, 0x0e, 0xbd, 0x52, 0x4e, 0x17, 0x0b, 0x0a,
+ 0x13, 0x1c, 0x85, 0x05, 0xff, 0x6a, 0x62, 0xc1, 0xfa, 0x37, 0xac, 0xbf,
+ 0xf0, 0xfc, 0x17, 0x37, 0x06, 0xf2, 0x59, 0x58, 0x7f, 0x44, 0x77, 0x5b,
+ 0x5b, 0x6b, 0x8a, 0x29, 0x19, 0x14, 0x34, 0xc4, 0xa7, 0x09, 0xe1, 0x7c,
+ 0x32, 0x1c, 0x8f, 0x4c, 0xd8, 0x53, 0xf7, 0x0c, 0x4e, 0xa1, 0x24, 0xd2,
+ 0x83, 0xf5, 0x1d, 0x81, 0xdd, 0x7d, 0x1d, 0x3b, 0xca, 0x84, 0x03, 0x09,
+ 0x46, 0xf1, 0xc8, 0xd4, 0xbf, 0x1d, 0xd0, 0x90, 0xc0, 0xbe, 0x16, 0x71,
+ 0x37, 0x16, 0x50, 0xb4, 0xe6, 0x8d, 0x8d, 0xc6, 0xfc, 0x64, 0x76, 0xdd,
+ 0xac, 0xbf, 0xff, 0x7b, 0x0b, 0x0d, 0xf3, 0xcb, 0xc6, 0x38, 0x87, 0x59,
+ 0x7d, 0xdb, 0xbf, 0x6a, 0x8b, 0x01, 0x52, 0x44, 0x3e, 0x95, 0xef, 0xf1,
+ 0xdb, 0x81, 0x8d, 0x4c, 0xb2, 0xfb, 0xb1, 0x3d, 0x32, 0xca, 0x83, 0xda,
+ 0x73, 0x4b, 0xc0, 0x10, 0x0b, 0x2f, 0xc3, 0xcc, 0x07, 0x16, 0x54, 0x27,
+ 0x27, 0x90, 0xb1, 0xe3, 0xef, 0xc8, 0x04, 0x1e, 0xbf, 0xc3, 0x81, 0x7d,
+ 0x7c, 0x30, 0xb2, 0x85, 0xa2, 0x14, 0x29, 0xf7, 0xed, 0x76, 0xef, 0xda,
+ 0xa2, 0x75, 0x5f, 0xff, 0xef, 0x44, 0xe3, 0xc3, 0x8b, 0xe7, 0x33, 0xcd,
+ 0xc0, 0xce, 0xb2, 0xfc, 0x2c, 0xef, 0x21, 0x78, 0x89, 0xb9, 0x8d, 0xaf,
+ 0xff, 0xe2, 0x0c, 0x7f, 0x98, 0x42, 0xc0, 0x08, 0xf3, 0xce, 0xb2, 0xfe,
+ 0x21, 0x73, 0x3c, 0xce, 0xb2, 0xa1, 0x11, 0x98, 0xb9, 0x78, 0xd8, 0x3a,
+ 0xcb, 0xd3, 0xc7, 0x6b, 0x2f, 0xfb, 0xc1, 0xe8, 0x6d, 0xbe, 0x06, 0xb2,
+ 0xd9, 0x39, 0xed, 0x7c, 0x7a, 0xf9, 0xfb, 0x10, 0xeb, 0x2f, 0x4b, 0x82,
+ 0xcd, 0x46, 0x19, 0x3b, 0xef, 0x28, 0xbf, 0x6b, 0xb7, 0x7e, 0xd5, 0x16,
+ 0xca, 0xff, 0xef, 0x37, 0xfc, 0x1e, 0xb0, 0xef, 0xd2, 0xcb, 0xef, 0xe9,
+ 0xba, 0x59, 0x7f, 0x7d, 0xfd, 0xb0, 0x70, 0xb2, 0xff, 0xfe, 0x90, 0xbe,
+ 0x43, 0x60, 0xdb, 0x39, 0x9f, 0x28, 0x59, 0x50, 0x88, 0x87, 0x2f, 0xbf,
+ 0x4a, 0x1b, 0x7c, 0x2c, 0xbf, 0x61, 0x00, 0xf8, 0xb2, 0xff, 0xa3, 0x82,
+ 0xfc, 0xdd, 0xbe, 0x96, 0x5f, 0xf3, 0x61, 0x1b, 0x1b, 0xdf, 0xcb, 0x2a,
+ 0x11, 0x85, 0xd9, 0x40, 0x09, 0xb6, 0xce, 0xef, 0xfa, 0x25, 0x1a, 0x9e,
+ 0x35, 0x3a, 0xcb, 0xf0, 0xfc, 0xc6, 0x0a, 0x16, 0x58, 0x5e, 0x2a, 0xb1,
+ 0xec, 0xd9, 0x91, 0x8f, 0x0a, 0xb7, 0x87, 0x19, 0x20, 0x70, 0xea, 0xff,
+ 0xc4, 0x2c, 0xe1, 0x6f, 0x93, 0xee, 0xac, 0xbf, 0x3f, 0x3c, 0xf2, 0x59,
+ 0x7f, 0x83, 0xf0, 0x68, 0x32, 0xe2, 0xca, 0xd1, 0xee, 0x11, 0x3d, 0xfc,
+ 0xfa, 0xdb, 0x72, 0x35, 0x65, 0xe0, 0xf0, 0x5e, 0x1e, 0x89, 0x10, 0xdc,
+ 0xe0, 0xc4, 0xc8, 0xc1, 0x0e, 0xfb, 0xba, 0xed, 0x65, 0xf7, 0x6e, 0xfd,
+ 0xaa, 0x2e, 0x65, 0x8e, 0xb2, 0xb4, 0x78, 0x26, 0x18, 0x5f, 0xc5, 0x9d,
+ 0x01, 0xa4, 0xb2, 0xc2, 0xb5, 0x95, 0xa3, 0xc2, 0xde, 0x5b, 0x79, 0xcf,
+ 0xc5, 0x97, 0x4c, 0x75, 0x94, 0xb2, 0xa1, 0x32, 0x2c, 0x5a, 0x66, 0x57,
+ 0x24, 0x30, 0x73, 0x6c, 0x62, 0xfe, 0x9c, 0x5e, 0xd5, 0xb5, 0xed, 0x7b,
+ 0x52, 0xcb, 0xfb, 0xa1, 0x7f, 0xe3, 0xe9, 0x65, 0x0b, 0x46, 0x7e, 0x2c,
+ 0x3a, 0x35, 0xfb, 0x5d, 0xbb, 0xf6, 0xa8, 0xbb, 0xd7, 0xfa, 0x42, 0xf9,
+ 0xad, 0x31, 0x8b, 0x2c, 0x2f, 0x0f, 0xb5, 0xcd, 0xaf, 0xf8, 0xa1, 0xe7,
+ 0xeb, 0x90, 0x35, 0x97, 0x0c, 0x0b, 0x2e, 0x8d, 0xd5, 0x97, 0x8b, 0x27,
+ 0x59, 0x61, 0x63, 0x44, 0x29, 0xa7, 0x20, 0x17, 0x21, 0x9a, 0x88, 0x76,
+ 0xef, 0x66, 0x32, 0x10, 0xfb, 0x46, 0xea, 0x18, 0xad, 0x5b, 0xca, 0xea,
+ 0x52, 0x29, 0xe1, 0x81, 0xe8, 0x68, 0x3c, 0x39, 0x01, 0x2b, 0xdc, 0xa3,
+ 0x98, 0xe4, 0xa2, 0x4f, 0xc2, 0x74, 0x48, 0x56, 0xdf, 0xf8, 0xc7, 0x29,
+ 0xf8, 0xc5, 0xd4, 0x96, 0x5f, 0xfd, 0x93, 0xe1, 0x9e, 0xce, 0x63, 0x12,
+ 0xcb, 0xff, 0x31, 0x16, 0x1b, 0xd8, 0x5c, 0x6b, 0x2f, 0xd9, 0xe1, 0xb9,
+ 0x2c, 0xb9, 0x85, 0xf9, 0x1c, 0xe4, 0x81, 0xc4, 0x31, 0x0f, 0xaf, 0xdc,
+ 0xe1, 0xde, 0x4b, 0x2f, 0xff, 0xde, 0x82, 0x9f, 0x81, 0x76, 0x97, 0x3c,
+ 0xf2, 0x59, 0x7f, 0xfe, 0xf4, 0x14, 0xfc, 0x0b, 0xb4, 0xb9, 0xe7, 0x92,
+ 0xcb, 0xff, 0xff, 0xf9, 0xa0, 0xbe, 0x4e, 0x6e, 0x7c, 0x3f, 0x6f, 0xf3,
+ 0xcd, 0xa8, 0x9d, 0xf5, 0xda, 0xcb, 0xbc, 0xc3, 0x46, 0xef, 0x95, 0x6e,
+ 0xe4, 0x2c, 0xbf, 0xfb, 0xae, 0xc2, 0xfd, 0x7f, 0x30, 0x8d, 0x59, 0x78,
+ 0x9c, 0x5c, 0x27, 0xca, 0x32, 0x8e, 0xe3, 0x32, 0xe1, 0x77, 0xc5, 0xaf,
+ 0xed, 0xaf, 0x68, 0x8e, 0xb5, 0x3a, 0xcb, 0xc7, 0x0e, 0xe2, 0xcb, 0xc1,
+ 0x73, 0xac, 0xbe, 0x0e, 0xe8, 0xe1, 0x65, 0xfb, 0x37, 0x7f, 0x06, 0xac,
+ 0xb6, 0xea, 0xca, 0x9c, 0xdf, 0xe1, 0x5d, 0xf7, 0x1b, 0xbd, 0x2c, 0xa9,
+ 0xd1, 0xc9, 0xa2, 0x0f, 0x0e, 0x13, 0x21, 0x84, 0x37, 0xfe, 0xe3, 0x9b,
+ 0xe6, 0x82, 0x0c, 0x2c, 0xbf, 0xf7, 0x9f, 0xef, 0xee, 0xa5, 0x9f, 0x59,
+ 0x58, 0x7f, 0x8c, 0x7b, 0x73, 0x81, 0x65, 0xff, 0xff, 0xe2, 0x73, 0x0b,
+ 0x3f, 0xfc, 0x9e, 0x09, 0xcd, 0xe1, 0xe3, 0x08, 0x6b, 0x2f, 0x60, 0x9c,
+ 0x59, 0x58, 0x8a, 0x8d, 0x0b, 0x6e, 0xba, 0xde, 0x69, 0xb8, 0xb2, 0xfe,
+ 0x28, 0x01, 0xde, 0x4b, 0x2f, 0xe2, 0x80, 0x1d, 0xe4, 0xb2, 0xff, 0x6d,
+ 0x7b, 0x41, 0x60, 0xfc, 0x15, 0x97, 0xec, 0xdf, 0x05, 0xfc, 0x3e, 0x9e,
+ 0x16, 0x5f, 0x88, 0x3c, 0xf3, 0x6c, 0x47, 0x86, 0x0e, 0xea, 0x12, 0xb7,
+ 0xe1, 0xb6, 0xfd, 0x62, 0xcb, 0x7a, 0x0f, 0xef, 0x14, 0xaf, 0xf3, 0xcb,
+ 0x59, 0xb6, 0xc0, 0x59, 0x7f, 0xa0, 0xa3, 0xbe, 0x00, 0xeb, 0x2f, 0xa2,
+ 0x6f, 0x32, 0xcb, 0xce, 0xfd, 0xaa, 0x25, 0x75, 0xfe, 0x35, 0xc8, 0x1f,
+ 0xcf, 0x2c, 0xa9, 0xcf, 0xfb, 0xb2, 0x26, 0x29, 0xbd, 0xec, 0xed, 0x65,
+ 0xf6, 0x00, 0x3c, 0x59, 0x73, 0xf5, 0x86, 0xfc, 0x87, 0x6f, 0xce, 0x6b,
+ 0xfe, 0x4b, 0x2f, 0xff, 0xb8, 0xcf, 0xd7, 0x9d, 0xbe, 0x1d, 0x3f, 0x16,
+ 0x5b, 0xa2, 0x3f, 0x7f, 0x94, 0x5f, 0xfd, 0xec, 0x97, 0x7e, 0x61, 0xc1,
+ 0x7d, 0x65, 0x31, 0xf6, 0x7c, 0xa2, 0xa4, 0xaa, 0xa8, 0x64, 0xdd, 0x9a,
+ 0xea, 0x16, 0x27, 0x6f, 0x28, 0xc3, 0xaf, 0xfd, 0xdb, 0x6b, 0x3c, 0xda,
+ 0xf3, 0xac, 0xbf, 0xf8, 0x3c, 0xf3, 0xcb, 0xec, 0xe4, 0x05, 0x97, 0xbc,
+ 0xdf, 0xe9, 0x10, 0x3a, 0x3e, 0xbf, 0xb4, 0xf2, 0x7e, 0xa4, 0xb2, 0xfc,
+ 0x4e, 0x60, 0x87, 0x59, 0x50, 0x7a, 0xff, 0x2e, 0xbf, 0x43, 0x01, 0x8e,
+ 0xb2, 0xf6, 0x9b, 0xa5, 0x95, 0x23, 0xc3, 0xf9, 0x35, 0xfa, 0x27, 0xfe,
+ 0x79, 0x65, 0xfd, 0x07, 0x1e, 0x9f, 0xb5, 0x95, 0xe3, 0xd6, 0x22, 0x8b,
+ 0xff, 0xc5, 0xff, 0x64, 0xba, 0xfe, 0xa3, 0x0c, 0x59, 0x7f, 0xff, 0xf9,
+ 0xc8, 0x48, 0x06, 0x4b, 0xd1, 0xbc, 0x70, 0x2f, 0x08, 0x32, 0xce, 0x2c,
+ 0xa8, 0x46, 0x26, 0x92, 0xee, 0x94, 0xeb, 0x2f, 0xbb, 0x79, 0x62, 0xcb,
+ 0xff, 0xff, 0xff, 0xf0, 0xdc, 0xe7, 0x79, 0x4a, 0x04, 0x81, 0xb6, 0x9f,
+ 0xa1, 0xfa, 0x35, 0xc6, 0x77, 0x28, 0xef, 0xd1, 0x32, 0xcb, 0xf8, 0xbe,
+ 0x1f, 0x0a, 0x61, 0x65, 0xcd, 0xf8, 0x47, 0x0b, 0x42, 0xc2, 0xb1, 0x33,
+ 0x47, 0x8c, 0x0e, 0xfe, 0x20, 0x6b, 0x4d, 0x3a, 0xcb, 0xfd, 0x9a, 0xe3,
+ 0xf6, 0x1e, 0x96, 0x5f, 0xff, 0xdd, 0x73, 0x35, 0xff, 0xbc, 0xe2, 0x1c,
+ 0x7e, 0x63, 0x56, 0x56, 0x22, 0x55, 0xcd, 0x6f, 0xf7, 0x58, 0xdc, 0xe0,
+ 0x61, 0x65, 0x82, 0xb2, 0xfb, 0xed, 0x9a, 0x59, 0x4b, 0x2f, 0xbf, 0x1f,
+ 0xe2, 0xcb, 0x9e, 0x5b, 0x51, 0xad, 0xc0, 0xba, 0x9d, 0x11, 0xfe, 0x11,
+ 0xde, 0x9d, 0x7f, 0xd8, 0xdb, 0xca, 0x33, 0x52, 0x59, 0x7f, 0xfe, 0xfc,
+ 0xb3, 0x71, 0xc8, 0x1d, 0x7f, 0x51, 0x86, 0x2c, 0x30, 0xdc, 0x5f, 0xba,
+ 0xff, 0xa0, 0x0b, 0x2b, 0x11, 0xfc, 0xed, 0x61, 0x6a, 0xbf, 0xff, 0xd8,
+ 0x36, 0xef, 0xcc, 0x31, 0xe1, 0x82, 0x4d, 0xe0, 0x9a, 0xb2, 0xff, 0xf4,
+ 0xc5, 0x1f, 0xe7, 0xfa, 0xed, 0x8a, 0x75, 0x97, 0xfc, 0xe6, 0x0f, 0xd1,
+ 0x3e, 0x18, 0xb2, 0x99, 0x11, 0x04, 0x9b, 0x7f, 0xfc, 0xc0, 0xc3, 0xb7,
+ 0xf9, 0x07, 0x7e, 0xbe, 0xb2, 0xff, 0xfe, 0xdf, 0x83, 0xd4, 0x07, 0x8d,
+ 0xbd, 0xd8, 0x61, 0x85, 0x95, 0x88, 0xac, 0x64, 0xfb, 0xff, 0xfd, 0xdb,
+ 0xe9, 0xfd, 0xd4, 0xb3, 0xf9, 0xf8, 0x08, 0xaf, 0x16, 0x5f, 0xfc, 0xfd,
+ 0x49, 0xbf, 0xe8, 0xd7, 0xe1, 0x65, 0xff, 0x41, 0xff, 0x93, 0x49, 0xbe,
+ 0xb2, 0xa4, 0x98, 0x1b, 0x10, 0x9d, 0x97, 0xe8, 0x97, 0xff, 0xfb, 0xcc,
+ 0x31, 0xe1, 0x9d, 0x7c, 0x2f, 0xcf, 0x18, 0xe3, 0x59, 0x7c, 0x17, 0xd4,
+ 0x96, 0x5f, 0xc5, 0x13, 0x81, 0xfe, 0xb2, 0xff, 0x38, 0xc4, 0xdd, 0x82,
+ 0x92, 0xcb, 0x47, 0x67, 0xc6, 0x72, 0xdb, 0xff, 0xe3, 0xb9, 0x03, 0xc6,
+ 0x39, 0x4f, 0xdb, 0x4e, 0xb2, 0xff, 0xfe, 0xd3, 0xf3, 0x0a, 0x30, 0x1c,
+ 0xc9, 0xa3, 0xae, 0x2c, 0xb9, 0xbe, 0xe8, 0xac, 0x0a, 0x95, 0x0d, 0x38,
+ 0x66, 0x84, 0x2b, 0xc3, 0x52, 0xff, 0x82, 0x03, 0xbc, 0xb9, 0xa1, 0xac,
+ 0xbf, 0xff, 0xd8, 0xc5, 0xfc, 0x2d, 0x84, 0xe3, 0x82, 0x9e, 0x34, 0xb2,
+ 0xbe, 0x89, 0x8d, 0xe7, 0x56, 0xd2, 0xcb, 0xff, 0xf7, 0x5f, 0x28, 0xf3,
+ 0xf3, 0x3b, 0x27, 0xce, 0xd6, 0x56, 0x22, 0x2f, 0xb2, 0x50, 0x88, 0xdf,
+ 0xff, 0xfe, 0xf6, 0x1c, 0x0f, 0xac, 0xdf, 0x83, 0xce, 0x05, 0xfa, 0xf1,
+ 0x8f, 0xf5, 0x97, 0xfa, 0x3c, 0xdf, 0xe3, 0xf4, 0xb2, 0xff, 0xd9, 0xd7,
+ 0xff, 0x07, 0xf6, 0x4e, 0xb2, 0xff, 0xa6, 0xef, 0xcc, 0x78, 0xd1, 0xab,
+ 0x2f, 0xf0, 0x33, 0x59, 0x9f, 0xe2, 0xca, 0xc3, 0xee, 0xe8, 0xf2, 0xa1,
+ 0x7f, 0xb8, 0x70, 0xee, 0xc8, 0xf4, 0x3b, 0x3d, 0xf4, 0x7d, 0x45, 0x1a,
+ 0xe7, 0xcc, 0x02, 0xf4, 0x61, 0x98, 0x90, 0xae, 0xbd, 0x80, 0x75, 0x97,
+ 0xb5, 0x9d, 0x2c, 0xbd, 0xe7, 0x97, 0x8d, 0xc0, 0x06, 0xef, 0xff, 0xcc,
+ 0x3f, 0x3b, 0x7e, 0x0b, 0xb6, 0x39, 0xd9, 0x65, 0xb3, 0xc8, 0x85, 0x23,
+ 0x2b, 0xfe, 0xce, 0xb8, 0x38, 0x72, 0x9d, 0x65, 0xfe, 0x7e, 0x41, 0x7f,
+ 0xcc, 0xb2, 0xfc, 0x79, 0xb8, 0xc4, 0xb2, 0xff, 0xee, 0xdb, 0x5e, 0xc9,
+ 0xbc, 0xda, 0x9d, 0x65, 0xff, 0xce, 0x0c, 0x2e, 0xbf, 0xa8, 0xc3, 0x16,
+ 0x5f, 0xf3, 0xcb, 0x9e, 0x8d, 0x08, 0x35, 0x95, 0x24, 0xdf, 0xb0, 0x9c,
+ 0xd3, 0x9e, 0xcc, 0x7a, 0x28, 0x24, 0x7f, 0xa2, 0x5f, 0x81, 0x33, 0x04,
+ 0x56, 0xb2, 0xff, 0xff, 0x7b, 0x3b, 0x2c, 0x3e, 0x16, 0x7c, 0x20, 0x3b,
+ 0xc9, 0x65, 0xfd, 0xe7, 0x39, 0x47, 0x4b, 0x2f, 0xfc, 0x59, 0xec, 0x9a,
+ 0x4d, 0xa9, 0x2c, 0xbf, 0xff, 0xfe, 0x04, 0x17, 0x6f, 0xf7, 0xe8, 0x19,
+ 0xbd, 0xbf, 0x2f, 0x37, 0xf8, 0xc3, 0x59, 0x7f, 0xe6, 0xde, 0xdf, 0x9a,
+ 0x50, 0x5f, 0x59, 0x50, 0x9d, 0xb4, 0x8b, 0x71, 0x7f, 0xb2, 0xde, 0x8f,
+ 0xbe, 0xff, 0x7f, 0xf9, 0xf2, 0x5e, 0xc6, 0x2c, 0x06, 0xde, 0x2c, 0xbc,
+ 0xf2, 0x17, 0xb4, 0x37, 0x83, 0xd1, 0x18, 0xf4, 0xa1, 0x8e, 0x38, 0x64,
+ 0x64, 0xe2, 0x3f, 0x70, 0xe5, 0xea, 0x11, 0x8c, 0xc9, 0x33, 0xc6, 0xa1,
+ 0xca, 0x72, 0x2f, 0x46, 0x98, 0xe5, 0x00, 0x86, 0x18, 0xac, 0x84, 0xa3,
+ 0xc0, 0xe5, 0x20, 0x73, 0xf2, 0xb9, 0x44, 0x94, 0x39, 0xba, 0xb1, 0x70,
+ 0xaf, 0x16, 0x5f, 0xbf, 0x01, 0x15, 0xe2, 0xcb, 0xfe, 0x96, 0x7f, 0xcd,
+ 0x1a, 0x02, 0xcb, 0xf6, 0x76, 0xf2, 0xc5, 0x97, 0xfb, 0x06, 0xc5, 0xfc,
+ 0xf2, 0xcb, 0xff, 0xf8, 0x7e, 0x82, 0x9f, 0x81, 0x76, 0x97, 0x3c, 0xf2,
+ 0x59, 0x7b, 0x3c, 0x2f, 0x69, 0xa6, 0x61, 0x83, 0x5d, 0x15, 0xf8, 0xe0,
+ 0x89, 0xf8, 0x63, 0x79, 0xa1, 0xd6, 0x5e, 0xfc, 0x0d, 0x25, 0xff, 0xef,
+ 0x3b, 0x7e, 0x24, 0xda, 0x9c, 0x20, 0x49, 0x7b, 0x42, 0xb1, 0x70, 0x7c,
+ 0xdc, 0x1c, 0xbc, 0xfd, 0x8b, 0x92, 0x2e, 0x47, 0x08, 0x0b, 0x0b, 0x1b,
+ 0xa2, 0xc4, 0xee, 0x51, 0x79, 0xeb, 0xc8, 0x1f, 0xca, 0xaf, 0xdf, 0x19,
+ 0x4d, 0xff, 0xe1, 0x67, 0x79, 0x0b, 0xcd, 0x76, 0xef, 0xda, 0xa2, 0x61,
+ 0x5f, 0x43, 0x09, 0xe5, 0x97, 0xfb, 0xb8, 0xeb, 0xe5, 0x12, 0x59, 0x7f,
+ 0xbd, 0x04, 0xe7, 0x8d, 0xd5, 0x97, 0x98, 0x4f, 0x2c, 0xbf, 0xff, 0xb3,
+ 0x7b, 0x8f, 0xd0, 0x2f, 0xfe, 0xc1, 0x87, 0xfc, 0x59, 0x76, 0x49, 0x65,
+ 0xff, 0xed, 0x38, 0x05, 0x9b, 0xf9, 0x19, 0x1c, 0x92, 0xcb, 0xb0, 0x58,
+ 0xd3, 0x6b, 0xc2, 0x27, 0x34, 0x01, 0xa1, 0x0e, 0x85, 0x7c, 0x41, 0x6b,
+ 0xb6, 0xa1, 0x51, 0x65, 0xb7, 0xac, 0xa1, 0x49, 0xb4, 0x39, 0x0d, 0xf9,
+ 0xbd, 0xec, 0x9d, 0x65, 0xe1, 0x47, 0x86, 0xb2, 0xff, 0xe1, 0x4e, 0x75,
+ 0x20, 0xbf, 0xca, 0x24, 0xb2, 0xfb, 0x69, 0x64, 0x8e, 0xb2, 0xfd, 0xb4,
+ 0x6d, 0x1b, 0x56, 0xde, 0xd6, 0xb2, 0xef, 0xed, 0x35, 0x97, 0x75, 0xb8,
+ 0xb2, 0xfd, 0xe6, 0x3c, 0x76, 0xb2, 0xec, 0x3e, 0xc3, 0xc3, 0xec, 0x6e,
+ 0xfe, 0x83, 0xe0, 0x23, 0x7a, 0xca, 0x19, 0xef, 0x78, 0xc2, 0xff, 0x6b,
+ 0x3b, 0x80, 0x08, 0x75, 0x97, 0xef, 0xbc, 0xef, 0xc5, 0x97, 0xd0, 0x76,
+ 0xd2, 0xcb, 0x44, 0xc7, 0x93, 0xa2, 0x8b, 0xe8, 0x26, 0x99, 0x65, 0xff,
+ 0xfb, 0x27, 0xd9, 0x98, 0x5f, 0xf3, 0xb7, 0x1b, 0x7a, 0xcb, 0xf7, 0xa0,
+ 0x6c, 0x6a, 0xca, 0x64, 0xda, 0x34, 0x44, 0x77, 0xe2, 0x28, 0xf9, 0x0e,
+ 0xea, 0xbd, 0xf7, 0x84, 0xe1, 0x2c, 0xbb, 0x6b, 0xfa, 0xcb, 0xe9, 0x98,
+ 0xc9, 0x96, 0x5f, 0xe8, 0x3b, 0x7a, 0x30, 0x96, 0x5c, 0xfc, 0x59, 0x47,
+ 0x3e, 0xbf, 0x92, 0xef, 0x30, 0xbf, 0xbf, 0x1b, 0xc9, 0xfa, 0x59, 0x7e,
+ 0x2e, 0xd8, 0xb1, 0x65, 0xff, 0xb8, 0x3d, 0x13, 0x99, 0x9d, 0x7d, 0x65,
+ 0xfe, 0x30, 0xb3, 0xaf, 0xe7, 0x96, 0x56, 0x1f, 0xa3, 0x20, 0x5f, 0xe8,
+ 0x79, 0xfe, 0x6b, 0xe9, 0x65, 0xf9, 0xf5, 0x27, 0x3a, 0xca, 0x1a, 0x7f,
+ 0x99, 0x08, 0x7e, 0x8c, 0x58, 0xbf, 0xd0, 0x9a, 0x22, 0x00, 0x9a, 0x58,
+ 0xeb, 0x2f, 0xf7, 0xfc, 0xed, 0xc6, 0xde, 0xb2, 0xdb, 0x5a, 0xca, 0x23,
+ 0xca, 0xdb, 0x34, 0xbf, 0xdc, 0x8c, 0x21, 0xfa, 0x16, 0x5f, 0xd1, 0x84,
+ 0x3f, 0x42, 0xcb, 0xc1, 0xd4, 0xdb, 0x0f, 0x73, 0x86, 0x37, 0xf8, 0xcd,
+ 0x98, 0x3f, 0x46, 0xf5, 0x97, 0xfe, 0x0e, 0x1b, 0x9f, 0x0c, 0x74, 0x35,
+ 0x95, 0x07, 0xf0, 0xc7, 0x17, 0xf8, 0x83, 0xfc, 0xf8, 0x93, 0xac, 0xad,
+ 0x1e, 0xaf, 0xc8, 0x2f, 0xff, 0xcd, 0xaf, 0x3e, 0xc1, 0xe4, 0xbd, 0x1b,
+ 0xc7, 0x0b, 0x2f, 0xf8, 0xc1, 0x3d, 0x1d, 0xf9, 0xa6, 0x59, 0x7c, 0x13,
+ 0xe0, 0xd6, 0x57, 0x47, 0xbf, 0xba, 0x7b, 0x7f, 0xff, 0xde, 0xc9, 0x64,
+ 0xbd, 0x85, 0x86, 0xf9, 0xe5, 0x92, 0x3a, 0xca, 0xc4, 0x45, 0xfc, 0x9a,
+ 0xfd, 0xa8, 0x97, 0x31, 0x65, 0xf3, 0x7f, 0x37, 0xac, 0xbf, 0xd8, 0x67,
+ 0xc9, 0xc1, 0xc5, 0x95, 0x07, 0xfb, 0xe2, 0x7f, 0x91, 0xd4, 0x97, 0x04,
+ 0x31, 0x6f, 0xb8, 0x40, 0x6a, 0x30, 0x4f, 0x11, 0x14, 0x68, 0x5f, 0x84,
+ 0xfd, 0xff, 0xf4, 0x17, 0xf5, 0x0d, 0x22, 0xc3, 0xbc, 0x96, 0x5f, 0xfe,
+ 0x8e, 0xf8, 0x1f, 0xb7, 0x98, 0xdf, 0x32, 0xcb, 0xf8, 0xf1, 0x85, 0xfd,
+ 0xb5, 0x97, 0xda, 0x6e, 0xa4, 0xb2, 0xdc, 0x59, 0x7e, 0x8c, 0x2f, 0xed,
+ 0xac, 0xbd, 0xc7, 0xeb, 0x62, 0x23, 0x18, 0xbe, 0x62, 0x33, 0x88, 0xd0,
+ 0xd3, 0x74, 0x3a, 0x67, 0xe1, 0xaf, 0x7f, 0xdb, 0x98, 0x3f, 0x46, 0xe1,
+ 0x42, 0xca, 0x63, 0xf3, 0x73, 0x6b, 0xfe, 0xd4, 0xfd, 0xf9, 0xbc, 0x1f,
+ 0xac, 0xaf, 0x1e, 0xe3, 0x90, 0x5f, 0xe6, 0x37, 0x59, 0x3c, 0x4e, 0xb2,
+ 0xfd, 0x07, 0xde, 0x09, 0x2c, 0xae, 0x1e, 0xff, 0xcd, 0x6e, 0xfb, 0x2c,
+ 0xb8, 0x38, 0xb2, 0xed, 0x71, 0x65, 0x48, 0xf9, 0x4d, 0x22, 0x00, 0xb6,
+ 0xd8, 0xb5, 0xff, 0xfa, 0x41, 0xd4, 0x76, 0x66, 0x37, 0xbb, 0x69, 0xf7,
+ 0x56, 0x5e, 0xd4, 0x7d, 0x65, 0xfb, 0xb6, 0xe7, 0x99, 0x65, 0xfd, 0x8c,
+ 0x5f, 0x0f, 0x96, 0x57, 0x47, 0xa9, 0xe2, 0x8b, 0xf7, 0x64, 0xdd, 0x49,
+ 0x65, 0x4c, 0x98, 0xc7, 0x17, 0x3e, 0xe0, 0x12, 0x3b, 0xc7, 0xd9, 0x8b,
+ 0x2f, 0xed, 0x63, 0x7a, 0x06, 0xb2, 0xf6, 0x83, 0xc5, 0x97, 0xff, 0xde,
+ 0x82, 0xcf, 0xfb, 0x3f, 0xe8, 0x08, 0xad, 0x65, 0xfc, 0xda, 0xd8, 0xe4,
+ 0x05, 0x97, 0xbd, 0x9d, 0x2c, 0xbf, 0xff, 0xc6, 0x6e, 0xff, 0x3d, 0xb0,
+ 0xb2, 0x76, 0xc2, 0xea, 0x5c, 0x59, 0x7e, 0x33, 0xf9, 0xee, 0xd6, 0x56,
+ 0x22, 0x45, 0xd9, 0xea, 0x13, 0xb6, 0x18, 0xf6, 0x16, 0x30, 0xef, 0x94,
+ 0x9c, 0xb8, 0xa1, 0x5d, 0x7f, 0xfb, 0xe4, 0xe0, 0xf6, 0x30, 0xc3, 0xfe,
+ 0x2c, 0xbe, 0xdf, 0x83, 0x85, 0x97, 0xd2, 0xc8, 0xe9, 0x65, 0xff, 0x44,
+ 0xe2, 0x4b, 0xc1, 0x79, 0xd6, 0x54, 0x23, 0x2b, 0x12, 0x66, 0x23, 0xd1,
+ 0x15, 0xff, 0xba, 0x96, 0xcf, 0x3f, 0x70, 0x43, 0x59, 0x7f, 0x13, 0x00,
+ 0xf1, 0xbd, 0x65, 0xed, 0x00, 0xeb, 0x29, 0x8f, 0x2c, 0x25, 0xd7, 0xf3,
+ 0x13, 0xf6, 0x58, 0xb2, 0xb1, 0x1b, 0x3c, 0x84, 0x68, 0x48, 0x6f, 0x8b,
+ 0x18, 0xd5, 0x97, 0xcd, 0x1d, 0x71, 0x65, 0xf8, 0x4f, 0x94, 0x01, 0x65,
+ 0x1c, 0xfa, 0xfe, 0x43, 0xbc, 0x8a, 0xfb, 0xff, 0xc3, 0x16, 0x5f, 0xfe,
+ 0x8f, 0x82, 0x25, 0x9d, 0x7e, 0x70, 0x98, 0xb2, 0xfd, 0x07, 0xd3, 0xcc,
+ 0xb2, 0xff, 0xf9, 0xbf, 0x2c, 0xd6, 0x72, 0x18, 0x78, 0x75, 0x97, 0xb8,
+ 0xe0, 0x59, 0x50, 0x99, 0x96, 0x18, 0xb1, 0x1f, 0x93, 0x5c, 0xa3, 0xe9,
+ 0xb4, 0xb2, 0xfa, 0x0e, 0xd2, 0x59, 0x77, 0xa2, 0x46, 0xb3, 0x41, 0x77,
+ 0xa0, 0x8d, 0x59, 0x73, 0xc9, 0x65, 0xfa, 0x3b, 0x27, 0x3a, 0xcb, 0xff,
+ 0x44, 0xb6, 0x67, 0x9b, 0x5e, 0x75, 0x96, 0x6f, 0x1f, 0x37, 0x09, 0xe8,
+ 0x68, 0xeb, 0xe8, 0xb3, 0x70, 0x73, 0xcf, 0x97, 0xe9, 0xb8, 0x30, 0xce,
+ 0xb2, 0xff, 0xff, 0xf4, 0x7b, 0xcf, 0xcd, 0x9e, 0x76, 0xe7, 0xb0, 0x1b,
+ 0x35, 0x9f, 0x7e, 0x96, 0x5f, 0xfb, 0xae, 0x77, 0xe6, 0x1b, 0x6b, 0xb5,
+ 0x97, 0xf3, 0x83, 0x5a, 0x6d, 0x2c, 0xbd, 0xfd, 0x98, 0xb2, 0xa1, 0x33,
+ 0x3d, 0x15, 0xbb, 0xd8, 0x10, 0x84, 0x2d, 0xbd, 0x8c, 0x05, 0x97, 0xde,
+ 0x0f, 0x5f, 0x59, 0x7f, 0xf7, 0xb2, 0x34, 0x58, 0x73, 0x86, 0x65, 0x97,
+ 0xf7, 0xc4, 0x00, 0x23, 0xa5, 0x97, 0xfc, 0xdf, 0x6c, 0x39, 0x64, 0xeb,
+ 0x29, 0x8f, 0x9f, 0xc6, 0x17, 0xf7, 0x18, 0xd3, 0xbf, 0xd6, 0x5f, 0xfb,
+ 0x7c, 0x1b, 0x26, 0x28, 0xd4, 0x2c, 0xbf, 0xff, 0xf6, 0xb3, 0x7c, 0x17,
+ 0xf6, 0x08, 0x51, 0xe7, 0x6f, 0xc7, 0xf8, 0xb2, 0xee, 0xc5, 0x0b, 0x2f,
+ 0x89, 0xfc, 0x6a, 0xcb, 0xd3, 0x86, 0x4b, 0x2f, 0x16, 0x73, 0x61, 0xee,
+ 0x0c, 0x73, 0x08, 0xaf, 0x9c, 0x12, 0x1a, 0xcb, 0xfd, 0x07, 0xec, 0x9f,
+ 0x3b, 0x59, 0x43, 0x55, 0x31, 0xdc, 0x2a, 0xfa, 0x21, 0x62, 0xed, 0x1f,
+ 0xef, 0x86, 0x51, 0x88, 0x02, 0x11, 0x5f, 0x6c, 0xdf, 0xbb, 0x3a, 0xca,
+ 0x1a, 0xb6, 0x9c, 0x95, 0x78, 0x6c, 0x20, 0xad, 0xb8, 0xb2, 0xdb, 0x8b,
+ 0x2f, 0x60, 0xfe, 0xb2, 0xc7, 0x63, 0x61, 0xa1, 0x4b, 0xbf, 0x8b, 0x2f,
+ 0xfc, 0xdb, 0xf0, 0x7e, 0xce, 0xf0, 0x96, 0x5f, 0xe8, 0x28, 0x03, 0xbe,
+ 0xea, 0xcb, 0xda, 0x79, 0x2c, 0xbf, 0xc3, 0xf6, 0x77, 0xe8, 0xd2, 0xca,
+ 0x1a, 0x20, 0xf4, 0x66, 0x43, 0x97, 0xee, 0x67, 0xf5, 0x0b, 0x2f, 0xff,
+ 0x0a, 0xca, 0x0e, 0xed, 0xe7, 0xff, 0xa1, 0x65, 0x42, 0x6f, 0x32, 0x16,
+ 0x68, 0x61, 0x70, 0xbc, 0x24, 0xf7, 0x3f, 0x6b, 0x2f, 0xe6, 0x99, 0xfb,
+ 0xe4, 0x96, 0x5f, 0xff, 0xf0, 0xc7, 0x9b, 0x71, 0xac, 0x21, 0xfa, 0x04,
+ 0x00, 0x23, 0xa5, 0x95, 0xda, 0x2c, 0x3c, 0x2e, 0xe5, 0xf7, 0xff, 0xb5,
+ 0x0c, 0x59, 0xfe, 0x47, 0x9c, 0xeb, 0x2f, 0xff, 0xf7, 0x98, 0x87, 0xac,
+ 0xef, 0xd1, 0xec, 0xd6, 0xa0, 0xd5, 0x97, 0xe0, 0xee, 0xb6, 0x1d, 0x65,
+ 0xfb, 0xee, 0x76, 0xfa, 0xca, 0x34, 0xf4, 0x48, 0xaa, 0xfd, 0xe8, 0xc9,
+ 0x3a, 0xcb, 0xff, 0x37, 0xc3, 0xa7, 0xe6, 0xc3, 0xfd, 0x65, 0x42, 0x22,
+ 0x46, 0x44, 0xe4, 0xd7, 0xf9, 0xb0, 0xe5, 0x93, 0xba, 0xcb, 0xfd, 0xc6,
+ 0xde, 0x38, 0x04, 0xeb, 0x2b, 0x0f, 0x9d, 0xcc, 0x6f, 0xbf, 0xc0, 0x05,
+ 0x65, 0xe6, 0x3f, 0xd6, 0x5e, 0x21, 0x3e, 0xb2, 0xfc, 0x11, 0xb9, 0x03,
+ 0x61, 0xb9, 0x71, 0xca, 0x84, 0x4d, 0x49, 0x72, 0xfe, 0xf3, 0x7c, 0xa0,
+ 0xeb, 0x2f, 0xa3, 0x79, 0x42, 0xcb, 0xcf, 0x2c, 0x59, 0x53, 0x1f, 0x49,
+ 0xcb, 0x08, 0x8a, 0xb6, 0xb5, 0xe9, 0xc8, 0x44, 0xc8, 0xe7, 0xfb, 0x87,
+ 0xf3, 0x18, 0x4c, 0x8f, 0xe8, 0xce, 0xca, 0x12, 0xbf, 0x85, 0xd0, 0x61,
+ 0x17, 0x7f, 0xfc, 0xe7, 0x1f, 0xa3, 0xd0, 0x70, 0xf5, 0x2e, 0x2c, 0xbf,
+ 0xfd, 0x9f, 0xf3, 0x67, 0x5f, 0xcd, 0xf1, 0xc5, 0x96, 0xf7, 0x91, 0x38,
+ 0x4a, 0x37, 0xcf, 0xcf, 0xce, 0xb2, 0xfc, 0xce, 0x0d, 0x9f, 0x59, 0x7f,
+ 0xf3, 0x97, 0xa1, 0x86, 0xdc, 0xc9, 0x2c, 0xbd, 0x00, 0x11, 0x65, 0xfd,
+ 0x9b, 0xfc, 0xc0, 0x99, 0x65, 0x62, 0x60, 0x46, 0x94, 0x78, 0x8d, 0xca,
+ 0x49, 0x07, 0x83, 0xb7, 0x14, 0x2c, 0xbe, 0xf4, 0x72, 0x16, 0x5e, 0x10,
+ 0x78, 0xb2, 0xf0, 0xaf, 0x82, 0x85, 0x95, 0x39, 0xfc, 0x0c, 0x55, 0xc8,
+ 0x78, 0x3b, 0x7b, 0x8d, 0xc5, 0x97, 0xdb, 0x0f, 0xb3, 0xb5, 0x97, 0xf4,
+ 0xf3, 0x48, 0x51, 0xa9, 0xd6, 0x5e, 0xce, 0xc6, 0xb2, 0xfb, 0xf8, 0x40,
+ 0x59, 0x7f, 0x39, 0x91, 0xfc, 0x9d, 0x65, 0xfd, 0x9a, 0xd4, 0x40, 0xd6,
+ 0x56, 0xd6, 0x8c, 0xec, 0x36, 0x61, 0xd2, 0x21, 0xdb, 0x2e, 0xbf, 0xfa,
+ 0x7f, 0x60, 0xc6, 0xdd, 0x67, 0x5f, 0x59, 0x7d, 0x38, 0x81, 0x9d, 0x65,
+ 0xf4, 0xd2, 0x89, 0xd6, 0x54, 0x1e, 0x56, 0x13, 0x5f, 0xcd, 0xf0, 0x08,
+ 0x52, 0x59, 0x7c, 0x64, 0xdc, 0x85, 0x97, 0xcd, 0x07, 0xc5, 0x97, 0xe8,
+ 0x37, 0x3f, 0xc5, 0x97, 0xff, 0xf6, 0x13, 0x0f, 0x99, 0xce, 0x67, 0x9b,
+ 0x81, 0x9d, 0x65, 0xfc, 0x3d, 0x3f, 0xfc, 0x15, 0x97, 0x3f, 0xe4, 0x88,
+ 0x8e, 0x2d, 0x5f, 0xcd, 0xe0, 0x9c, 0xec, 0xb2, 0xff, 0xe0, 0xcb, 0x39,
+ 0xb3, 0xed, 0xb7, 0x93, 0xac, 0xb3, 0x48, 0xfd, 0xc8, 0xb6, 0xa1, 0x54,
+ 0xf4, 0xf0, 0x91, 0x34, 0x83, 0xa2, 0xed, 0x12, 0x78, 0x80, 0xa1, 0x61,
+ 0xf8, 0x52, 0xd8, 0x5e, 0xd6, 0xea, 0xa8, 0x76, 0xa2, 0x51, 0x49, 0x40,
+ 0xa0, 0x87, 0x69, 0x24, 0x0a, 0xa2, 0x8d, 0xa6, 0x81, 0x12, 0x89, 0xa4,
+ 0xb2, 0x39, 0x43, 0xf9, 0x38, 0xfb, 0xdc, 0xab, 0xfe, 0xa1, 0xca, 0xd1,
+ 0xac, 0x4d, 0x1f, 0xae, 0xa3, 0x2f, 0x3c, 0x62, 0xbe, 0x8f, 0x45, 0xe3,
+ 0x6b, 0x04, 0x6e, 0x82, 0xb4, 0xa2, 0x97, 0x09, 0xc9, 0xed, 0xaf, 0xca,
+ 0x4f, 0x0c, 0x33, 0xb7, 0x9e, 0x18, 0x39, 0xb7, 0x0f, 0x61, 0x25, 0x76,
+ 0xdf, 0xff, 0x0a, 0x76, 0xb1, 0x4b, 0x09, 0xec, 0xea, 0x59, 0xbb, 0xc5,
+ 0x97, 0xfa, 0x66, 0xfe, 0x6b, 0xf0, 0xb2, 0xfd, 0x86, 0x67, 0x9d, 0x65,
+ 0xff, 0xf6, 0x9b, 0xa9, 0x71, 0xbf, 0xe8, 0xd7, 0xe1, 0x65, 0xfe, 0x8d,
+ 0x3c, 0xcf, 0xc9, 0x2c, 0xbc, 0xef, 0xda, 0xa2, 0xae, 0x5f, 0xce, 0x27,
+ 0xbc, 0xe7, 0x59, 0x5d, 0x9e, 0xbf, 0x8a, 0x6f, 0xe6, 0xd7, 0x9c, 0x43,
+ 0xac, 0xbe, 0x6f, 0xca, 0x16, 0x50, 0xd1, 0xf9, 0xa8, 0x45, 0x78, 0x8f,
+ 0x79, 0x75, 0xf1, 0x6e, 0xf1, 0xd6, 0x5f, 0x16, 0x4d, 0x0b, 0x2d, 0xb8,
+ 0xb2, 0xff, 0xf4, 0x4f, 0xf6, 0x1e, 0x14, 0x9b, 0xc1, 0x59, 0x58, 0x7f,
+ 0xc7, 0x21, 0xf0, 0xa5, 0xd0, 0x75, 0x97, 0x70, 0x6b, 0x2b, 0x46, 0xb5,
+ 0xc5, 0xaf, 0xf4, 0x6b, 0xf0, 0x50, 0x05, 0x97, 0xf8, 0x5e, 0x6b, 0xb7,
+ 0x7e, 0xd5, 0x11, 0xe2, 0xfd, 0xe6, 0xd7, 0x9d, 0x65, 0xe2, 0xfb, 0xac,
+ 0xbb, 0x07, 0x87, 0x85, 0xc2, 0x7a, 0x92, 0x2c, 0x4f, 0x08, 0x5b, 0xfd,
+ 0x28, 0xd4, 0xf1, 0xa9, 0xd6, 0x5f, 0xff, 0xc5, 0x9b, 0xbc, 0xd9, 0xc0,
+ 0x6f, 0xd8, 0xfc, 0x96, 0x9d, 0x65, 0xfc, 0xfe, 0x82, 0x80, 0x2c, 0xad,
+ 0xe8, 0x8f, 0xdb, 0x64, 0xbf, 0xfa, 0x78, 0xd7, 0x79, 0xce, 0x60, 0xf1,
+ 0x65, 0x42, 0x66, 0x39, 0x0c, 0x47, 0x28, 0xbf, 0xef, 0xb0, 0x45, 0x79,
+ 0x29, 0xe6, 0x59, 0x7f, 0xff, 0xda, 0x2c, 0x9f, 0x61, 0x66, 0xf2, 0xcd,
+ 0xde, 0x6c, 0xe0, 0x37, 0xac, 0xbf, 0xec, 0xff, 0x04, 0xe6, 0xce, 0xe4,
+ 0xb2, 0xfe, 0x2c, 0xff, 0x30, 0xc5, 0x95, 0x09, 0x8d, 0xe1, 0xf9, 0xdc,
+ 0x5c, 0xfa, 0xff, 0x76, 0xdc, 0xf3, 0x7d, 0x96, 0x5f, 0xb2, 0x77, 0x2e,
+ 0x96, 0x57, 0x47, 0xb6, 0x46, 0x77, 0xef, 0xff, 0x08, 0x0b, 0x2f, 0xf6,
+ 0xeb, 0x8e, 0x30, 0x6c, 0xb2, 0xc2, 0xf6, 0xb6, 0x40, 0x2c, 0x31, 0x4e,
+ 0x66, 0x32, 0x7c, 0x8d, 0x31, 0x91, 0x26, 0x85, 0x16, 0x96, 0xfc, 0x40,
+ 0xf0, 0xe2, 0x28, 0xd6, 0x79, 0x1a, 0x77, 0xe1, 0x2c, 0x21, 0x16, 0xe9,
+ 0x3d, 0xef, 0x39, 0xd6, 0x5f, 0xb5, 0xdb, 0xbf, 0x6a, 0x8b, 0x05, 0x78,
+ 0xd8, 0x9d, 0x65, 0xfc, 0xda, 0x2c, 0xdf, 0x8b, 0x2f, 0xff, 0xc1, 0x79,
+ 0xcf, 0x9b, 0x61, 0xd6, 0x6a, 0x42, 0x49, 0x65, 0x79, 0x11, 0x04, 0x5b,
+ 0x7d, 0xfd, 0x37, 0x4b, 0x2f, 0xd8, 0x59, 0xfe, 0x2c, 0xbf, 0x67, 0x02,
+ 0xfd, 0x2c, 0xbf, 0xda, 0x73, 0x89, 0xa7, 0xe9, 0x65, 0x85, 0xc2, 0x78,
+ 0x18, 0x38, 0x69, 0xb7, 0x70, 0xa6, 0x62, 0x27, 0x23, 0x22, 0x61, 0x0a,
+ 0x2f, 0xf0, 0xbc, 0xd7, 0x6e, 0xfd, 0xaa, 0x2c, 0xa5, 0xff, 0xb3, 0xf2,
+ 0xc0, 0x6d, 0xe7, 0x82, 0xb2, 0xff, 0xf6, 0x38, 0xfd, 0x9a, 0xd4, 0x6f,
+ 0x36, 0x16, 0x5f, 0x76, 0xef, 0xda, 0xa2, 0xd3, 0x56, 0xe1, 0xfd, 0xe9,
+ 0x2e, 0xfc, 0x59, 0x3b, 0x18, 0xb2, 0xff, 0x0f, 0xcf, 0x37, 0x98, 0xeb,
+ 0x29, 0x63, 0x9b, 0x4b, 0xfd, 0x07, 0xc1, 0x94, 0x74, 0xb2, 0xfc, 0x36,
+ 0x04, 0x12, 0xcb, 0xf0, 0x73, 0x4f, 0xc5, 0x96, 0x16, 0x34, 0xf5, 0xb2,
+ 0x17, 0x9d, 0x92, 0x9d, 0x73, 0xc3, 0x4e, 0x65, 0xc2, 0x6b, 0xf6, 0xd5,
+ 0xb5, 0x8a, 0x82, 0xa0, 0xa8, 0xb2, 0xf8, 0x54, 0xda, 0xf6, 0xbd, 0xa1,
+ 0x65, 0x6d, 0x47, 0xf3, 0xb4, 0x90, 0xaf, 0xf8, 0x51, 0xe6, 0x30, 0x6e,
+ 0xfd, 0xac, 0xbf, 0x6d, 0x21, 0x4f, 0x32, 0x16, 0x5f, 0xf0, 0xa9, 0xb2,
+ 0x66, 0xf1, 0x07, 0xeb, 0x2f, 0xf0, 0x87, 0xcf, 0xf1, 0xb8, 0xb2, 0xcc,
+ 0xb2, 0x85, 0x07, 0x89, 0xb6, 0x69, 0x7f, 0x0a, 0x5b, 0xb8, 0xeb, 0x8b,
+ 0x2f, 0xf4, 0x4f, 0xa7, 0x1c, 0xee, 0xb2, 0xff, 0xfd, 0xe7, 0x2f, 0xcb,
+ 0x35, 0x90, 0x45, 0x9f, 0x59, 0x52, 0x44, 0x2b, 0x1a, 0x5f, 0xff, 0x3c,
+ 0xef, 0xbf, 0x9b, 0x1f, 0x7f, 0x7e, 0x6d, 0x2c, 0xbf, 0x6f, 0x71, 0xe1,
+ 0xd6, 0x5f, 0x38, 0x36, 0xf1, 0x65, 0xff, 0x72, 0x3d, 0x03, 0xf3, 0x9a,
+ 0xb2, 0xb6, 0x1e, 0xef, 0xc9, 0x2e, 0xcd, 0xeb, 0x2d, 0xc8, 0x37, 0x84,
+ 0x49, 0x7e, 0xfc, 0x14, 0x4c, 0xb2, 0xf4, 0x75, 0xc5, 0x95, 0x87, 0x88,
+ 0x72, 0x7b, 0xf8, 0xed, 0xbb, 0x04, 0xcb, 0x2f, 0x6e, 0x8e, 0x16, 0x53,
+ 0x1e, 0x68, 0x4b, 0xaf, 0xd0, 0x5d, 0xfa, 0x16, 0x5f, 0xfd, 0x9f, 0xf3,
+ 0x1f, 0x3f, 0xc1, 0x38, 0xb2, 0xff, 0xd8, 0xe0, 0x89, 0x6a, 0x30, 0x96,
+ 0x57, 0x68, 0x80, 0x64, 0x5b, 0xe6, 0xdf, 0xed, 0xeb, 0x2f, 0xb9, 0x05,
+ 0x32, 0xcb, 0xe8, 0xdd, 0x9b, 0x16, 0x53, 0x9e, 0x39, 0x11, 0x5f, 0xed,
+ 0xd6, 0x06, 0xc7, 0xf0, 0x56, 0x54, 0x95, 0xe1, 0x0c, 0x8b, 0x15, 0xda,
+ 0x18, 0x53, 0x34, 0xf9, 0xb8, 0x04, 0x25, 0x0a, 0x7e, 0x11, 0xfd, 0xb7,
+ 0x74, 0x82, 0xff, 0x1c, 0x43, 0x80, 0xec, 0x05, 0x97, 0xed, 0x9a, 0xd0,
+ 0x7c, 0xb2, 0xfc, 0xc6, 0xc1, 0x76, 0xb2, 0xb8, 0x7a, 0x7f, 0x2b, 0xa8,
+ 0x45, 0x56, 0x42, 0x22, 0xf3, 0x64, 0xeb, 0x2f, 0xff, 0x77, 0xe6, 0xf3,
+ 0x6a, 0x26, 0x33, 0x3c, 0xb2, 0xbc, 0x7d, 0x04, 0x39, 0x78, 0x05, 0x8b,
+ 0x2e, 0x2c, 0x59, 0x5b, 0x0d, 0x80, 0x06, 0xef, 0xfd, 0xc6, 0xd9, 0xe7,
+ 0xd4, 0x6f, 0x85, 0x97, 0xfc, 0x77, 0x96, 0xd8, 0x7c, 0xda, 0x59, 0x53,
+ 0xa2, 0x83, 0x44, 0x67, 0x41, 0xbf, 0x3f, 0x3f, 0x03, 0x59, 0x50, 0x7b,
+ 0x01, 0x31, 0xbf, 0xcf, 0xa9, 0x3f, 0xdf, 0xb5, 0x97, 0xff, 0xb3, 0x0b,
+ 0x00, 0x59, 0xff, 0x64, 0x96, 0x54, 0x27, 0xc7, 0xe8, 0xd2, 0x42, 0x43,
+ 0xba, 0x67, 0x7f, 0xf1, 0xc9, 0xcd, 0x2c, 0x04, 0xf8, 0x62, 0xcb, 0xff,
+ 0xc5, 0x86, 0xf9, 0xe5, 0xe3, 0x1c, 0x43, 0xac, 0xb7, 0xa1, 0x12, 0x38,
+ 0x8b, 0x7e, 0x89, 0x70, 0xf2, 0x59, 0x7d, 0x02, 0x47, 0x96, 0x5c, 0xd3,
+ 0xac, 0xbc, 0xef, 0xda, 0xa2, 0xdc, 0x5f, 0xbf, 0xce, 0x34, 0xcb, 0x2a,
+ 0x73, 0xe9, 0xec, 0x5c, 0x42, 0x9b, 0xff, 0x36, 0xbc, 0xf9, 0xa9, 0xda,
+ 0x75, 0x97, 0xd3, 0x40, 0xf1, 0x65, 0xfc, 0x03, 0xe7, 0x02, 0x4b, 0x2f,
+ 0xf7, 0xf9, 0x1a, 0xd6, 0x18, 0xb2, 0x98, 0xf8, 0x5c, 0xb6, 0xff, 0xd9,
+ 0xac, 0x2d, 0x9e, 0xce, 0x8c, 0x59, 0x7e, 0x20, 0x3f, 0x5c, 0x59, 0x50,
+ 0x7d, 0x2e, 0x83, 0x52, 0x54, 0xee, 0x69, 0x3f, 0x45, 0x1a, 0x84, 0x5f,
+ 0x8c, 0x9c, 0xfc, 0xa1, 0x07, 0xc8, 0x44, 0xdf, 0xf9, 0xc6, 0x4f, 0xbf,
+ 0xd1, 0x37, 0x16, 0x5f, 0x6f, 0x8e, 0xc9, 0x65, 0xfc, 0x40, 0x98, 0xa0,
+ 0xeb, 0x28, 0xd4, 0x48, 0x9d, 0x01, 0xc9, 0x2f, 0x1c, 0x99, 0x65, 0x89,
+ 0x65, 0xbb, 0x59, 0x7f, 0xde, 0x0b, 0xf3, 0x30, 0x8d, 0x59, 0x7f, 0xfe,
+ 0x8e, 0xf6, 0x67, 0x9b, 0x51, 0xec, 0x21, 0xc2, 0xcb, 0xf7, 0x1f, 0xa7,
+ 0x1a, 0xcb, 0x30, 0xd1, 0x6a, 0x73, 0x8f, 0xaa, 0xdf, 0xe7, 0x16, 0x59,
+ 0x3c, 0x1a, 0xb2, 0xa1, 0x35, 0xcc, 0x1b, 0x61, 0x0f, 0x43, 0x1c, 0x8d,
+ 0x6f, 0xfa, 0x1c, 0xbd, 0x98, 0x5d, 0xac, 0xbf, 0xdf, 0xfb, 0x4e, 0x78,
+ 0x25, 0x97, 0xfc, 0x12, 0x9c, 0x9f, 0x4f, 0x25, 0x95, 0x24, 0x50, 0xe1,
+ 0xb7, 0x0c, 0xef, 0xf1, 0x04, 0xf1, 0xcf, 0xb2, 0xcb, 0xf4, 0x6b, 0x59,
+ 0xba, 0xb2, 0xf6, 0x9b, 0xa5, 0x95, 0x07, 0xf2, 0x46, 0x5f, 0x2a, 0xbf,
+ 0xc1, 0x19, 0x66, 0xf7, 0x92, 0xcb, 0xff, 0xf7, 0xa6, 0xd8, 0x70, 0xfd,
+ 0xa7, 0xcf, 0x9b, 0x9e, 0x59, 0x7f, 0x14, 0x4d, 0x36, 0x01, 0x65, 0xff,
+ 0xe8, 0x9f, 0xec, 0x3c, 0x29, 0x37, 0x82, 0xb2, 0xff, 0xa4, 0xdb, 0xf3,
+ 0xce, 0x53, 0xac, 0xbd, 0x19, 0xa5, 0x97, 0xfb, 0xd1, 0x26, 0xdb, 0xc3,
+ 0xac, 0xa1, 0x9e, 0x87, 0x06, 0xef, 0xdb, 0x3a, 0xe3, 0x1a, 0xb2, 0xa7,
+ 0x3c, 0xee, 0x88, 0xab, 0xa4, 0x7e, 0x3c, 0x36, 0x2f, 0xfd, 0x9e, 0x6d,
+ 0x0f, 0xd0, 0x5d, 0xac, 0xbf, 0xf1, 0x67, 0xf9, 0x1b, 0x3f, 0x9d, 0xac,
+ 0xbe, 0xd9, 0xfc, 0x02, 0xca, 0x92, 0x28, 0x98, 0xfb, 0xc8, 0x17, 0xfb,
+ 0xa9, 0x41, 0x7f, 0x00, 0xb2, 0xfb, 0x80, 0x6f, 0xac, 0xa9, 0x2b, 0x50,
+ 0xec, 0xd1, 0x96, 0xfc, 0x5c, 0xf1, 0xa2, 0xf2, 0x19, 0x41, 0x2f, 0x10,
+ 0xce, 0xfc, 0xfa, 0xfe, 0x79, 0x65, 0xff, 0x98, 0x11, 0x21, 0xfa, 0x0b,
+ 0xb5, 0x95, 0x23, 0xe5, 0xf9, 0x3d, 0xfd, 0xf9, 0x66, 0xb3, 0x8b, 0x29,
+ 0x65, 0xe0, 0xbf, 0xd6, 0x5c, 0x18, 0x59, 0x52, 0x36, 0x5f, 0x1c, 0xa5,
+ 0x97, 0xdd, 0x76, 0xda, 0x59, 0x71, 0xc5, 0xe2, 0x23, 0x7a, 0x3d, 0x39,
+ 0x0f, 0xc2, 0xef, 0xb0, 0x64, 0x35, 0x95, 0x07, 0xd9, 0xbd, 0x2e, 0xff,
+ 0x8b, 0xfe, 0x79, 0x05, 0xc4, 0x59, 0x50, 0x9d, 0x26, 0x11, 0x34, 0x64,
+ 0xce, 0x47, 0x7d, 0xfd, 0x82, 0xa1, 0x2c, 0xbc, 0xed, 0x3a, 0xca, 0xc3,
+ 0xc5, 0x34, 0xa6, 0xcc, 0xb2, 0xdb, 0x6b, 0x2c, 0x40, 0x34, 0x9f, 0x10,
+ 0xbd, 0xb3, 0x68, 0xda, 0x16, 0x5f, 0xf4, 0x85, 0xe6, 0xbb, 0x77, 0xed,
+ 0x51, 0x43, 0xaf, 0xd2, 0xd9, 0xbc, 0xf0, 0xb2, 0xa1, 0x30, 0xa6, 0x46,
+ 0x98, 0x99, 0xca, 0x49, 0x26, 0xf6, 0x8d, 0xed, 0x65, 0xf4, 0x77, 0x87,
+ 0x59, 0x52, 0x3c, 0x10, 0x0f, 0xdf, 0x46, 0xe0, 0x61, 0x65, 0xe9, 0xb0,
+ 0x6b, 0x2f, 0x4d, 0x1f, 0x59, 0x50, 0x6e, 0x82, 0x3b, 0x5a, 0x45, 0x00,
+ 0x08, 0xb8, 0xbd, 0x70, 0x44, 0x59, 0x7e, 0xe3, 0xfb, 0x3b, 0x59, 0x5d,
+ 0x1e, 0x07, 0x06, 0x2f, 0x0e, 0x0e, 0xb2, 0xff, 0xb2, 0x07, 0xe8, 0xdd,
+ 0x89, 0x96, 0x5f, 0xe0, 0x37, 0xbd, 0x80, 0x75, 0x94, 0x73, 0xed, 0x01,
+ 0xdd, 0xff, 0xb3, 0xfc, 0xf6, 0x6b, 0x58, 0x62, 0xcb, 0xff, 0x16, 0xeb,
+ 0x93, 0x9c, 0x78, 0x35, 0x95, 0x09, 0xde, 0x63, 0x83, 0x11, 0xbc, 0x22,
+ 0x44, 0x22, 0xdd, 0x3f, 0xbf, 0xf3, 0x8e, 0x07, 0xe6, 0x26, 0x3a, 0xcb,
+ 0xff, 0x6f, 0x7d, 0x71, 0xfd, 0xc8, 0x9d, 0x65, 0xfe, 0xe0, 0x7b, 0xcf,
+ 0x94, 0x2c, 0xa3, 0xa2, 0xc3, 0xc7, 0x9f, 0x41, 0xbd, 0xfc, 0xed, 0x65,
+ 0xd9, 0xda, 0xcb, 0x66, 0xc3, 0x69, 0xf1, 0xdb, 0xfe, 0xf3, 0xeb, 0xaf,
+ 0xc3, 0x4e, 0xb2, 0xff, 0x17, 0x7b, 0x26, 0xef, 0xd3, 0x2c, 0xa9, 0x1f,
+ 0xa3, 0x9d, 0x51, 0x22, 0xf4, 0x30, 0x9c, 0xbf, 0xd2, 0x8d, 0x4f, 0x1a,
+ 0x9d, 0x65, 0xf4, 0x3e, 0x80, 0xb2, 0xff, 0x76, 0xdc, 0xc1, 0xbf, 0x6b,
+ 0x28, 0x67, 0xab, 0xe2, 0x1b, 0xf3, 0xf3, 0x7e, 0x71, 0x65, 0xf9, 0xff,
+ 0xb2, 0x21, 0x65, 0x42, 0x3f, 0x72, 0x11, 0x40, 0x22, 0x09, 0x4d, 0xfb,
+ 0x67, 0xb0, 0x0e, 0xb2, 0xff, 0x6a, 0x3c, 0xe3, 0x91, 0xd6, 0x5f, 0xf1,
+ 0xdb, 0xfb, 0x78, 0x4e, 0x6a, 0xcb, 0xfa, 0x4f, 0xac, 0xeb, 0xeb, 0x2f,
+ 0xe1, 0xb9, 0xfc, 0xc6, 0x2c, 0xa8, 0x3d, 0xcc, 0x2e, 0xbf, 0xec, 0xff,
+ 0x04, 0xe6, 0x9f, 0x8b, 0x2f, 0x0e, 0x79, 0xd6, 0x5f, 0x9b, 0xfc, 0x76,
+ 0x59, 0x7f, 0xda, 0x06, 0x9c, 0xbf, 0x80, 0x59, 0x53, 0xa7, 0x94, 0x32,
+ 0x9c, 0x33, 0xd4, 0x25, 0xce, 0x40, 0xe7, 0x40, 0x1f, 0x09, 0x35, 0xe1,
+ 0x35, 0x25, 0x97, 0xf0, 0x9f, 0x0c, 0x64, 0xeb, 0x2f, 0xe0, 0x79, 0xdb,
+ 0xc1, 0x59, 0x52, 0x3f, 0xa9, 0x87, 0xb4, 0x5f, 0x7f, 0xf7, 0x65, 0x1f,
+ 0x2c, 0xdf, 0x9a, 0x92, 0xcb, 0xf3, 0xf3, 0x93, 0xf1, 0x65, 0xee, 0x1d,
+ 0xd6, 0x5f, 0xe2, 0x34, 0x4f, 0x78, 0x3c, 0x59, 0x53, 0x1e, 0x90, 0x47,
+ 0x2f, 0xfe, 0x0f, 0x3c, 0xf2, 0x82, 0x1e, 0x79, 0x65, 0xff, 0x09, 0x00,
+ 0x9a, 0x51, 0xa9, 0xd6, 0x5f, 0xc4, 0xff, 0x12, 0x3b, 0x59, 0x47, 0x3e,
+ 0xa2, 0x3c, 0xbe, 0x20, 0x4e, 0x05, 0x97, 0xff, 0xfa, 0x6e, 0x30, 0xf6,
+ 0x4c, 0xc5, 0xbd, 0xe6, 0x7f, 0x86, 0x16, 0x56, 0x22, 0xa9, 0x88, 0x5c,
+ 0x8e, 0xff, 0x8f, 0xcd, 0x98, 0x38, 0x2f, 0xac, 0xbf, 0xdc, 0xd9, 0xfd,
+ 0x83, 0xc2, 0x59, 0x60, 0x2c, 0xae, 0x8f, 0x23, 0x46, 0xf5, 0x08, 0xa5,
+ 0x68, 0x41, 0x5f, 0xc1, 0xef, 0xd1, 0xac, 0x59, 0x7d, 0xd7, 0x3e, 0xcb,
+ 0x2b, 0x0f, 0x45, 0xcb, 0xaa, 0x15, 0xe9, 0xe1, 0x81, 0xa8, 0xac, 0xf7,
+ 0xa2, 0x3f, 0x46, 0xae, 0x50, 0xd2, 0xe3, 0xbd, 0xf9, 0xc2, 0x6c, 0x08,
+ 0xb2, 0xfc, 0x28, 0xcd, 0x47, 0x16, 0x54, 0xc7, 0xa8, 0x45, 0x37, 0xf6,
+ 0x7d, 0x87, 0x87, 0x59, 0x7c, 0x52, 0x63, 0xac, 0xb6, 0xc9, 0x8f, 0x35,
+ 0xcb, 0x2f, 0xe6, 0x2d, 0xef, 0x30, 0xaa, 0x59, 0x7f, 0x44, 0xdd, 0x4b,
+ 0x37, 0xac, 0xa9, 0x8f, 0x9b, 0x86, 0xb4, 0x34, 0x59, 0xbc, 0x24, 0x2f,
+ 0xff, 0xc3, 0xf4, 0x08, 0x2f, 0xe4, 0xe0, 0xe7, 0x20, 0x09, 0x2e, 0x1e,
+ 0x2c, 0xbf, 0x4f, 0x13, 0xbf, 0x16, 0x56, 0x22, 0x5d, 0x96, 0x1c, 0x5a,
+ 0xfe, 0xdd, 0x70, 0x1e, 0x38, 0xb2, 0xe8, 0x02, 0xcb, 0x05, 0x60, 0x85,
+ 0xb5, 0x78, 0xf9, 0xc0, 0x8d, 0x7f, 0xee, 0x6f, 0x79, 0xa7, 0x72, 0x79,
+ 0x96, 0x5f, 0xfa, 0x37, 0x66, 0x7d, 0xef, 0xfd, 0xf0, 0xb2, 0xff, 0xd8,
+ 0x38, 0x94, 0x68, 0xff, 0xe9, 0x65, 0xfc, 0xe0, 0x98, 0xa0, 0x6b, 0x2f,
+ 0xf8, 0xb2, 0x71, 0xfb, 0x0b, 0xeb, 0x2f, 0x7d, 0xb8, 0xb2, 0xa1, 0x36,
+ 0x99, 0x88, 0xb4, 0x84, 0x74, 0x5f, 0x1f, 0x91, 0x6f, 0x0e, 0x2b, 0x6a,
+ 0x75, 0x55, 0xbb, 0x41, 0x68, 0xa8, 0x7c, 0x2a, 0x8c, 0x76, 0x9c, 0x21,
+ 0x45, 0x59, 0x4c, 0x4e, 0x3d, 0x4a, 0x34, 0xf1, 0xca, 0x71, 0xc9, 0x69,
+ 0xc6, 0xc6, 0x27, 0xdc, 0x71, 0x9d, 0x43, 0xb5, 0xa1, 0x51, 0x34, 0xb7,
+ 0xdd, 0x4a, 0x87, 0x3c, 0x71, 0xfe, 0x95, 0xca, 0xf1, 0x86, 0x82, 0x32,
+ 0x12, 0x8c, 0x93, 0x92, 0x82, 0xbf, 0x39, 0x86, 0x18, 0x67, 0xef, 0x8c,
+ 0x8b, 0x6e, 0x17, 0xc2, 0x47, 0xfb, 0x7f, 0xf6, 0xb3, 0xae, 0xfc, 0xdf,
+ 0xe3, 0xf4, 0xb2, 0xf8, 0x02, 0x14, 0x96, 0x5d, 0xd8, 0xb0, 0x1f, 0x57,
+ 0xd1, 0xe8, 0x5a, 0xab, 0x80, 0xca, 0x87, 0xbe, 0x8d, 0x48, 0xeb, 0x2f,
+ 0xba, 0xe3, 0xee, 0x2c, 0xbf, 0x60, 0xc3, 0xfe, 0x2c, 0xbf, 0xcf, 0xe7,
+ 0x10, 0xf9, 0xc5, 0x97, 0x9f, 0x46, 0xac, 0xb0, 0xb9, 0xd1, 0x80, 0xc4,
+ 0x44, 0x4d, 0xbc, 0xa0, 0xc3, 0x3b, 0xfc, 0x2f, 0x35, 0xdb, 0xbf, 0x6a,
+ 0x8b, 0xcd, 0x50, 0xfd, 0x9c, 0x72, 0x79, 0x1c, 0x78, 0xf9, 0x6a, 0xd1,
+ 0x7a, 0xa5, 0x1a, 0xea, 0x55, 0xf9, 0xdf, 0x7d, 0x28, 0x64, 0xad, 0x72,
+ 0x7f, 0x21, 0xdd, 0xbd, 0x52, 0xff, 0x0b, 0xcd, 0x76, 0xef, 0xda, 0xa2,
+ 0x96, 0x5d, 0xb5, 0xed, 0x35, 0x97, 0x7e, 0x75, 0x97, 0xe6, 0x17, 0xcc,
+ 0x65, 0x97, 0xff, 0xef, 0x61, 0x61, 0xbe, 0x79, 0x78, 0xc7, 0x10, 0xeb,
+ 0x2f, 0xbb, 0x77, 0xed, 0x51, 0x61, 0x2a, 0x48, 0x87, 0xd2, 0xbd, 0xc3,
+ 0xc5, 0x97, 0x37, 0x4b, 0x2d, 0xf8, 0x35, 0xba, 0x16, 0xbf, 0xfe, 0xc2,
+ 0x1c, 0x7a, 0x3a, 0xfe, 0x13, 0x9d, 0x65, 0xe2, 0x0f, 0x6b, 0x2a, 0x0f,
+ 0xa9, 0xd3, 0x6d, 0xc5, 0x97, 0xf0, 0x74, 0xd3, 0xb9, 0xd6, 0x58, 0x5e,
+ 0xd3, 0x54, 0x51, 0x04, 0x43, 0x18, 0xc8, 0x57, 0xb2, 0x81, 0xe1, 0x21,
+ 0xc2, 0x0d, 0xb1, 0x1b, 0xfc, 0x2f, 0x35, 0xdb, 0xbf, 0x6a, 0x8b, 0x2d,
+ 0x69, 0x2c, 0xbb, 0x46, 0xac, 0xbe, 0x16, 0x6e, 0xd3, 0xda, 0x96, 0x52,
+ 0x4b, 0xc2, 0xc4, 0x3a, 0xca, 0xec, 0xf7, 0x38, 0x62, 0x10, 0xba, 0x35,
+ 0x16, 0xa4, 0x23, 0xc7, 0x4b, 0xa3, 0xcb, 0x2c, 0x05, 0x97, 0x1b, 0x3a,
+ 0xcb, 0x6a, 0x46, 0xab, 0x04, 0x6b, 0xb3, 0xe6, 0x74, 0x0b, 0x01, 0x65,
+ 0x8d, 0x59, 0x4c, 0x68, 0xfe, 0x23, 0x7f, 0xfe, 0x1b, 0x7f, 0xd8, 0x36,
+ 0xc1, 0xbc, 0xee, 0x4b, 0x2f, 0xf9, 0xfa, 0x2c, 0xeb, 0xf0, 0x6a, 0xcb,
+ 0xfd, 0x3f, 0x5c, 0x81, 0xfd, 0x96, 0x5f, 0xa3, 0x37, 0xc7, 0x16, 0x5a,
+ 0x1c, 0xf7, 0x4c, 0x35, 0xa8, 0x4c, 0x45, 0xd4, 0xca, 0x12, 0xf7, 0xcf,
+ 0x29, 0x0d, 0x65, 0xff, 0xda, 0xf3, 0x8c, 0xa0, 0x3d, 0xf9, 0xd6, 0x5f,
+ 0xb5, 0x1f, 0x7f, 0x2c, 0xa6, 0x3e, 0xb7, 0x44, 0xbc, 0x61, 0x86, 0x24,
+ 0xbf, 0xe8, 0x97, 0x5f, 0xd4, 0x67, 0x49, 0x05, 0x9a, 0x0b, 0xfe, 0x0b,
+ 0xf5, 0x9f, 0x6e, 0x8c, 0x59, 0x74, 0x71, 0x65, 0x0d, 0x36, 0xaf, 0x42,
+ 0x34, 0x90, 0x38, 0x99, 0xbc, 0xee, 0xed, 0xa7, 0xb5, 0x2c, 0xbf, 0x99,
+ 0xf8, 0x0e, 0x05, 0x65, 0xff, 0xcd, 0x27, 0xe3, 0x90, 0x7b, 0xce, 0x24,
+ 0xbf, 0xff, 0xbc, 0xdf, 0xf6, 0x70, 0xb0, 0xe1, 0xe7, 0x9e, 0x4b, 0x2f,
+ 0xf4, 0x4b, 0xef, 0xe7, 0x1a, 0xcb, 0xe7, 0xf9, 0xbc, 0x59, 0x50, 0x8f,
+ 0x2c, 0x43, 0xd2, 0xd3, 0x99, 0x5a, 0x4b, 0x2d, 0x25, 0x96, 0x92, 0xcb,
+ 0xc6, 0x18, 0x62, 0xcb, 0x76, 0x90, 0x59, 0xa0, 0xa8, 0x3f, 0x73, 0x44,
+ 0x58, 0x44, 0x06, 0x34, 0xb2, 0xfc, 0x1e, 0x79, 0xe4, 0xb3, 0x09, 0x77,
+ 0xff, 0xdc, 0x6e, 0xf0, 0xb5, 0x05, 0x83, 0xc3, 0x56, 0x51, 0xd1, 0x07,
+ 0xf3, 0x5b, 0x74, 0xb2, 0xc6, 0xac, 0xb0, 0x56, 0x51, 0x1a, 0x3e, 0x09,
+ 0x56, 0x1f, 0xc7, 0x08, 0xfe, 0x6b, 0x77, 0x0d, 0x59, 0x6c, 0x59, 0x70,
+ 0x41, 0x06, 0xa0, 0x63, 0x17, 0x34, 0x2c, 0xbf, 0x8a, 0x0e, 0x51, 0x8b,
+ 0x2f, 0xfe, 0x87, 0xd7, 0xfd, 0x83, 0x0f, 0xf8, 0xb2, 0xe9, 0x42, 0xcb,
+ 0xdc, 0x19, 0xab, 0x2a, 0x74, 0x71, 0x8c, 0xb2, 0x61, 0x5f, 0x15, 0x05,
+ 0x10, 0x41, 0x6b, 0xff, 0xd9, 0xd7, 0xc4, 0xfb, 0x7f, 0xd8, 0x36, 0x59,
+ 0x7f, 0xff, 0xfa, 0x3f, 0xc6, 0xe7, 0x23, 0xfe, 0x68, 0xd0, 0x0e, 0xf2,
+ 0x97, 0xcd, 0x59, 0x46, 0xa3, 0x0f, 0xc9, 0x77, 0x37, 0x4b, 0x2f, 0x02,
+ 0x5e, 0x59, 0x74, 0x1d, 0x65, 0xff, 0xfa, 0x08, 0x32, 0x94, 0x7f, 0xd8,
+ 0x71, 0x20, 0x0b, 0x2f, 0xfe, 0x69, 0xe3, 0xcd, 0x1f, 0xe0, 0x78, 0xb2,
+ 0xff, 0xe0, 0xcb, 0x39, 0xa8, 0x69, 0x3f, 0x12, 0x59, 0xb4, 0x88, 0x72,
+ 0x44, 0xa9, 0x26, 0x07, 0xf8, 0x6e, 0x5d, 0xd8, 0xb8, 0x65, 0x8e, 0xcf,
+ 0x09, 0x69, 0x22, 0x8e, 0x33, 0x1c, 0x8e, 0x74, 0xd5, 0x1e, 0xc8, 0xb5,
+ 0x18, 0xfb, 0xc2, 0xc4, 0xa3, 0x41, 0xe4, 0x67, 0x3f, 0x8c, 0x77, 0x79,
+ 0x21, 0x82, 0xfb, 0x63, 0xa2, 0x46, 0x33, 0x7f, 0xf8, 0x59, 0xde, 0x42,
+ 0xf3, 0x5d, 0xbb, 0xf6, 0xa8, 0xa3, 0x17, 0xcd, 0xf7, 0xdb, 0x59, 0x7f,
+ 0x3e, 0x80, 0x78, 0x02, 0xcb, 0xe8, 0xd4, 0x01, 0x65, 0xfd, 0x03, 0x83,
+ 0xc0, 0x8b, 0x2a, 0x64, 0x4f, 0xf8, 0x93, 0x79, 0x68, 0x84, 0x37, 0xf1,
+ 0x3f, 0xfc, 0xd3, 0x2c, 0xbe, 0xcc, 0x26, 0x59, 0x7e, 0xf4, 0x4f, 0x83,
+ 0x59, 0x7e, 0x27, 0x04, 0x08, 0xb2, 0xff, 0x67, 0xf8, 0x24, 0xf1, 0x3a,
+ 0xcb, 0xff, 0x60, 0x33, 0x26, 0x31, 0xfa, 0xe2, 0xcb, 0xff, 0x37, 0x52,
+ 0xe1, 0x67, 0xfc, 0x15, 0x97, 0xfc, 0xda, 0xf6, 0x61, 0x4b, 0x8b, 0x2a,
+ 0x47, 0xed, 0xd9, 0xfd, 0xf3, 0xef, 0xc2, 0x59, 0x7f, 0xff, 0xd8, 0x7f,
+ 0x34, 0x7c, 0xb3, 0xfe, 0xc2, 0xc3, 0x1c, 0x0b, 0x2b, 0xa4, 0x54, 0x68,
+ 0x8f, 0xc4, 0x57, 0x6e, 0x6e, 0xac, 0xbf, 0xf3, 0xcb, 0xbf, 0x31, 0xe3,
+ 0x46, 0xac, 0xbf, 0xfb, 0x6d, 0xc8, 0x19, 0xf8, 0x26, 0x02, 0xcb, 0x0b,
+ 0x85, 0x68, 0x58, 0x82, 0x69, 0x6c, 0xc3, 0xfe, 0x28, 0x01, 0x39, 0x1b,
+ 0x7e, 0x35, 0xe0, 0x98, 0x98, 0x3a, 0x22, 0x05, 0x49, 0xb5, 0x17, 0xd4,
+ 0xa6, 0xb3, 0xc2, 0x2d, 0xe9, 0x82, 0xbc, 0x8c, 0x9b, 0xf3, 0x87, 0xb7,
+ 0xff, 0x0b, 0x79, 0x0b, 0xcd, 0x76, 0xef, 0xda, 0xa2, 0x39, 0x5f, 0xfe,
+ 0x16, 0x77, 0x90, 0xbc, 0xd7, 0x6e, 0xfd, 0xaa, 0x27, 0x25, 0xfe, 0x17,
+ 0x9a, 0xed, 0xdf, 0xb5, 0x45, 0x98, 0xbb, 0xe0, 0x59, 0x7e, 0xcf, 0x16,
+ 0x69, 0x65, 0xe9, 0xe3, 0x4b, 0x2f, 0xd2, 0xe3, 0x9c, 0x5f, 0x8f, 0x68,
+ 0x85, 0xf8, 0x4d, 0x7c, 0x2a, 0xf6, 0xad, 0xa8, 0x55, 0xac, 0xbf, 0xc3,
+ 0xc3, 0xc7, 0x50, 0x75, 0x95, 0xb5, 0x1f, 0x60, 0xab, 0x39, 0xb6, 0xf5,
+ 0x97, 0xfb, 0x51, 0xff, 0x3f, 0x52, 0x59, 0x7f, 0xff, 0xfd, 0x13, 0x7a,
+ 0x3f, 0x02, 0x36, 0xa6, 0x8f, 0x66, 0xfc, 0xf6, 0x0f, 0x7e, 0x2c, 0xa0,
+ 0x22, 0xd4, 0x8d, 0x2f, 0xfb, 0x38, 0xff, 0x00, 0x85, 0x25, 0x96, 0x02,
+ 0xcb, 0xfb, 0x9a, 0xd6, 0x75, 0xc5, 0x95, 0xb5, 0x1e, 0x06, 0x08, 0xde,
+ 0xd6, 0x1d, 0x65, 0xf3, 0x16, 0x71, 0x65, 0xb3, 0xe6, 0xf3, 0x74, 0x72,
+ 0xff, 0xff, 0xde, 0x82, 0x0f, 0x39, 0x02, 0x7d, 0x88, 0x32, 0xce, 0x7d,
+ 0x96, 0x5f, 0x8b, 0x37, 0xe1, 0x2c, 0xbe, 0xff, 0xdb, 0x4b, 0x2e, 0xe0,
+ 0x16, 0x54, 0x91, 0x96, 0xcd, 0x7a, 0x27, 0xf9, 0x15, 0xbe, 0xb2, 0xdb,
+ 0xab, 0x2b, 0x6c, 0xd2, 0x88, 0x23, 0x79, 0xcb, 0xb5, 0x97, 0xb9, 0x1c,
+ 0x59, 0x76, 0xdf, 0x16, 0x5f, 0x9c, 0xc9, 0xf0, 0xc5, 0x95, 0x39, 0xe2,
+ 0x10, 0xd5, 0xc2, 0x8f, 0x2c, 0xb3, 0x2c, 0xbf, 0xd1, 0xc8, 0xfc, 0xf8,
+ 0x62, 0xcb, 0x31, 0xcf, 0x10, 0x84, 0x2e, 0xee, 0x4b, 0x2f, 0xdf, 0xe1,
+ 0x44, 0x96, 0x5f, 0x19, 0xf8, 0x35, 0x65, 0x41, 0xf1, 0xe0, 0xc3, 0x13,
+ 0xdf, 0xf8, 0x87, 0xe8, 0xe7, 0x33, 0x50, 0xb2, 0xe0, 0x3a, 0xcb, 0xd1,
+ 0x84, 0xb2, 0xfb, 0xaf, 0xe4, 0x2c, 0xa1, 0x9b, 0xcc, 0x1a, 0xb0, 0x8b,
+ 0x2f, 0xff, 0x77, 0x1c, 0xe6, 0x1f, 0xaf, 0x84, 0xbe, 0xb2, 0xb6, 0x1e,
+ 0xf6, 0x09, 0x5f, 0xce, 0x5f, 0xdb, 0x73, 0x56, 0x5f, 0xbb, 0xf3, 0xb0,
+ 0xad, 0x65, 0xf8, 0x3c, 0x8e, 0x42, 0xca, 0xd1, 0xe9, 0xb9, 0x65, 0xfc,
+ 0x40, 0xf6, 0x01, 0xd6, 0x5f, 0x14, 0x6f, 0x0a, 0xca, 0x63, 0xcf, 0x72,
+ 0xcb, 0xba, 0x3a, 0xca, 0x59, 0x7f, 0xc4, 0x0c, 0xfc, 0x13, 0x01, 0x65,
+ 0xb6, 0xf0, 0xf0, 0x5c, 0x2e, 0xf1, 0x06, 0x65, 0x96, 0x17, 0xb5, 0x32,
+ 0x00, 0x05, 0x25, 0xb1, 0x0c, 0x89, 0xc8, 0xa4, 0xf2, 0x36, 0x2c, 0x87,
+ 0xa1, 0xac, 0x3d, 0x92, 0xf4, 0x39, 0x33, 0x06, 0x88, 0x8e, 0xbf, 0xe8,
+ 0x44, 0xb9, 0x60, 0xac, 0xf4, 0x94, 0xb8, 0xfd, 0xf2, 0x30, 0xc2, 0x0f,
+ 0x7b, 0x86, 0xd9, 0x00, 0x8b, 0x3b, 0xa5, 0x37, 0xed, 0x76, 0xef, 0xda,
+ 0xa2, 0xdd, 0x5b, 0x8b, 0x2b, 0x0f, 0x1c, 0x06, 0xd7, 0xe1, 0x63, 0xf4,
+ 0x69, 0x65, 0x0b, 0x3c, 0xbf, 0x10, 0xdf, 0x98, 0x1c, 0xcd, 0xd5, 0x97,
+ 0xf1, 0x38, 0xbd, 0x4f, 0xe5, 0x97, 0x9b, 0xa0, 0x2c, 0xbf, 0x75, 0x2f,
+ 0x30, 0x16, 0x5f, 0xfd, 0xa7, 0xec, 0x01, 0xe7, 0xe3, 0xa3, 0x16, 0x5c,
+ 0x46, 0xac, 0xb3, 0xac, 0xbe, 0xed, 0xdf, 0xb5, 0x45, 0x20, 0xac, 0x3d,
+ 0x79, 0x85, 0xf4, 0x21, 0x7f, 0xa5, 0xf6, 0x33, 0x80, 0x65, 0x97, 0xfe,
+ 0xcf, 0x36, 0xff, 0x66, 0x17, 0x6b, 0x2f, 0xec, 0xf6, 0x79, 0x8d, 0x59,
+ 0x7e, 0xfc, 0x6f, 0x6d, 0xeb, 0x2f, 0x3c, 0x85, 0xc2, 0x78, 0x43, 0x29,
+ 0xc8, 0x4f, 0xf4, 0x5f, 0xc3, 0x4f, 0x9f, 0xef, 0x2d, 0xbe, 0xce, 0x78,
+ 0x2b, 0x2f, 0xe8, 0x2e, 0x71, 0x8e, 0xb2, 0xb0, 0xf3, 0x98, 0x8a, 0xff,
+ 0x30, 0xc3, 0xfe, 0x1c, 0x96, 0x5f, 0x18, 0x78, 0xe2, 0xcb, 0xce, 0x52,
+ 0x59, 0x61, 0x70, 0xae, 0x5b, 0xb2, 0xad, 0x18, 0x1e, 0x3d, 0xff, 0x43,
+ 0x31, 0xc8, 0x02, 0x66, 0x61, 0x1d, 0xff, 0xc2, 0xde, 0x42, 0xf3, 0x5d,
+ 0xbb, 0xf6, 0xa8, 0x94, 0x95, 0x3b, 0x61, 0x51, 0x32, 0xb1, 0xd7, 0x1e,
+ 0x13, 0xa0, 0xa4, 0x5c, 0x94, 0xa0, 0xaf, 0xcb, 0xba, 0xdd, 0x84, 0x35,
+ 0xe1, 0x6f, 0xda, 0xcb, 0xf9, 0x8b, 0x3d, 0x9d, 0xac, 0xbf, 0x98, 0xbf,
+ 0x8c, 0x35, 0x97, 0x4b, 0xeb, 0x2f, 0x14, 0x18, 0xb2, 0xe8, 0x17, 0xa3,
+ 0x66, 0x42, 0xf5, 0x24, 0x45, 0xfd, 0x7a, 0xf7, 0x02, 0x75, 0x96, 0xda,
+ 0xd6, 0x58, 0x5c, 0x93, 0x0d, 0xea, 0x16, 0xec, 0x47, 0xb6, 0x3b, 0x78,
+ 0x9e, 0x4b, 0x2f, 0xc2, 0x81, 0x4e, 0xb9, 0xc5, 0x97, 0xff, 0x9b, 0xa0,
+ 0x6b, 0x07, 0x1a, 0x6e, 0x80, 0xb2, 0xfd, 0xae, 0xdd, 0xfb, 0x54, 0x4e,
+ 0xcb, 0xfa, 0x77, 0xd7, 0x7a, 0xc5, 0x97, 0xbc, 0xe6, 0x2c, 0xbf, 0xe2,
+ 0x79, 0x04, 0x07, 0x79, 0x2c, 0xb6, 0x0c, 0xf5, 0x7c, 0x3b, 0x79, 0xe4,
+ 0x2c, 0x55, 0x26, 0xbb, 0x06, 0x38, 0x96, 0xe6, 0xc5, 0x08, 0x4b, 0xa7,
+ 0xdc, 0x59, 0x7f, 0xfe, 0x61, 0x84, 0xf1, 0xba, 0xe3, 0x28, 0x2c, 0xed,
+ 0x65, 0xfe, 0x94, 0x6a, 0x78, 0xd4, 0xeb, 0x2f, 0xfd, 0xe2, 0x79, 0x04,
+ 0x07, 0x79, 0x2c, 0xa8, 0x3f, 0x3c, 0x35, 0xbf, 0xff, 0x67, 0x52, 0xf4,
+ 0x71, 0xf5, 0x1b, 0xbe, 0x7e, 0xd6, 0x58, 0x5e, 0x2b, 0x3a, 0x3c, 0x6f,
+ 0x1e, 0x65, 0x71, 0xb2, 0x86, 0x4e, 0xe9, 0x05, 0xf3, 0x6a, 0x37, 0xac,
+ 0xbb, 0x3c, 0xb2, 0xff, 0xed, 0xb7, 0x20, 0x67, 0xe0, 0x98, 0x0b, 0x2c,
+ 0x2f, 0x87, 0xfb, 0xb6, 0x46, 0x20, 0xb5, 0xff, 0xce, 0x7f, 0x67, 0x6f,
+ 0xe8, 0x12, 0x4b, 0x2f, 0xdf, 0xd6, 0x41, 0x8b, 0x2f, 0x30, 0xdd, 0x65,
+ 0xff, 0xc5, 0x9e, 0x79, 0xf3, 0x84, 0xfd, 0x2c, 0xbb, 0x6c, 0x58, 0xd1,
+ 0x96, 0xc8, 0xbe, 0x28, 0xe0, 0xdd, 0x42, 0xf7, 0x84, 0xa3, 0x2c, 0x3c,
+ 0xb8, 0x8e, 0x43, 0xa7, 0x6e, 0x30, 0x6b, 0xff, 0x72, 0x0b, 0xa0, 0x73,
+ 0x90, 0x05, 0x97, 0xff, 0xff, 0xfd, 0xe6, 0xfb, 0xbf, 0x5c, 0xe7, 0x20,
+ 0xf1, 0xec, 0xc9, 0xf0, 0xb3, 0xaf, 0xf2, 0x3a, 0x59, 0x7f, 0xa2, 0x4d,
+ 0xf6, 0x29, 0x2c, 0xbf, 0xff, 0xf7, 0x61, 0x9f, 0x37, 0xc7, 0x58, 0x37,
+ 0x90, 0x87, 0xe6, 0x38, 0xd6, 0x5f, 0x0d, 0xfe, 0x2f, 0x13, 0x75, 0xec,
+ 0xff, 0x50, 0x94, 0xe1, 0x8d, 0xff, 0xd3, 0x75, 0xc6, 0x3e, 0xc1, 0x35,
+ 0x93, 0xac, 0xbe, 0xed, 0xdf, 0xb5, 0x44, 0x58, 0xbf, 0x9b, 0x4e, 0x5d,
+ 0xc2, 0xca, 0xd1, 0xee, 0x78, 0xc2, 0xfb, 0x3e, 0x06, 0x59, 0x7f, 0xe7,
+ 0x90, 0xbc, 0xd7, 0x6e, 0xfd, 0xaa, 0x25, 0xd5, 0xfe, 0x71, 0xc1, 0x7a,
+ 0x38, 0xb2, 0xfb, 0x4c, 0x19, 0xd6, 0x5f, 0xff, 0xd8, 0x3f, 0x40, 0x82,
+ 0xfe, 0x4e, 0x0e, 0x72, 0x00, 0x92, 0xc2, 0xe1, 0x3e, 0x9c, 0x85, 0x3e,
+ 0x88, 0x8e, 0x43, 0xe4, 0xef, 0x98, 0xed, 0x91, 0xdf, 0xfc, 0x77, 0x90,
+ 0xbc, 0xd7, 0x6e, 0xfd, 0xaa, 0x26, 0x25, 0xfd, 0xe8, 0x2e, 0xa6, 0x75,
+ 0x97, 0xf9, 0xdb, 0x6d, 0x81, 0x83, 0x59, 0x7d, 0x9d, 0xc0, 0xb8, 0x3e,
+ 0x2f, 0x17, 0x50, 0xb4, 0x78, 0x7a, 0x16, 0xd7, 0xfb, 0xce, 0x71, 0x6e,
+ 0x11, 0xac, 0xbf, 0x6b, 0xb7, 0x7e, 0xd5, 0x15, 0x4a, 0xd8, 0xb2, 0xb0,
+ 0xf1, 0x8d, 0x36, 0xbf, 0xed, 0x69, 0x88, 0xb0, 0x3d, 0xac, 0xbf, 0xf0,
+ 0x5f, 0x52, 0x2c, 0x31, 0xc0, 0xb2, 0xff, 0xe7, 0xe6, 0x98, 0xcf, 0xf9,
+ 0xb5, 0x25, 0x97, 0xfd, 0xa7, 0xf7, 0x52, 0xcf, 0x8b, 0x84, 0x5d, 0x8c,
+ 0xe3, 0xc7, 0xd4, 0x2d, 0x33, 0xd7, 0x86, 0xed, 0xff, 0x85, 0xfa, 0x0f,
+ 0x83, 0x82, 0xfa, 0xcb, 0xdf, 0x69, 0xd6, 0x5f, 0xf9, 0xe4, 0x2f, 0x35,
+ 0xdb, 0xbf, 0x6a, 0x89, 0xd1, 0x7c, 0x1e, 0x30, 0x16, 0x5e, 0x6e, 0x8c,
+ 0x59, 0x40, 0x3c, 0x0e, 0x11, 0x51, 0xa8, 0xcd, 0x38, 0xe8, 0x21, 0x1d,
+ 0x7c, 0xe5, 0xfe, 0x2c, 0xbe, 0x9c, 0xa2, 0x75, 0x97, 0xc7, 0x83, 0x45,
+ 0x9c, 0xf1, 0x02, 0x43, 0x7f, 0xe0, 0x07, 0x82, 0xc6, 0x63, 0x94, 0x96,
+ 0x50, 0xb4, 0x7c, 0x33, 0xd0, 0x0f, 0x2f, 0xf3, 0x3e, 0xa2, 0x4f, 0xbd,
+ 0x65, 0xf3, 0x10, 0x19, 0x65, 0xfa, 0x68, 0x9a, 0x38, 0xb2, 0xfe, 0x33,
+ 0x1b, 0x7e, 0x12, 0xca, 0x63, 0xd7, 0xe1, 0x4d, 0xe6, 0xf4, 0x2c, 0x16,
+ 0x68, 0x6f, 0xfe, 0x0f, 0x3f, 0x1d, 0x0b, 0x0c, 0xcc, 0x75, 0x95, 0x24,
+ 0xc3, 0x8f, 0x09, 0x8f, 0x16, 0xdf, 0xb5, 0xdb, 0xbf, 0x6a, 0x89, 0xdd,
+ 0x7f, 0xff, 0x41, 0xc3, 0xa9, 0xa0, 0xfb, 0x0f, 0x9f, 0xe3, 0x71, 0x65,
+ 0xe7, 0x90, 0xbc, 0x44, 0xa7, 0xcd, 0xaf, 0xdf, 0x0b, 0x9d, 0x92, 0x5f,
+ 0xf8, 0xa3, 0xf9, 0xcc, 0xce, 0xa4, 0xb2, 0x86, 0xaa, 0x93, 0x23, 0x41,
+ 0x3c, 0x32, 0x9c, 0xd7, 0xe4, 0xf7, 0xfc, 0x38, 0x94, 0x0b, 0x33, 0x80,
+ 0x59, 0x7e, 0xe1, 0x40, 0x38, 0xb2, 0xf1, 0x60, 0xd6, 0x5d, 0x02, 0xe0,
+ 0xf0, 0x80, 0x4f, 0x42, 0xd3, 0x01, 0xc5, 0x52, 0x7e, 0xbf, 0x70, 0x5f,
+ 0x7f, 0x85, 0x97, 0xff, 0x85, 0x9d, 0xe4, 0x2f, 0x35, 0xdb, 0xbf, 0x6a,
+ 0x8a, 0x15, 0x7f, 0xfc, 0xff, 0x96, 0x13, 0x0c, 0x5f, 0x27, 0x8d, 0x2c,
+ 0xbe, 0x27, 0xd6, 0xf5, 0x97, 0x8e, 0xe6, 0x2c, 0xb0, 0xb8, 0x3c, 0x09,
+ 0xc8, 0xee, 0x9d, 0x96, 0x5f, 0xfe, 0xf0, 0x7f, 0x05, 0x93, 0x9a, 0x18,
+ 0x99, 0x65, 0xfc, 0x13, 0x9d, 0xe4, 0x2e, 0x0f, 0x8f, 0xb1, 0x7b, 0xff,
+ 0xff, 0x16, 0x6f, 0x6f, 0x04, 0x5f, 0x7e, 0x6f, 0x14, 0x66, 0xb0, 0xeb,
+ 0x2a, 0x49, 0xa1, 0x7a, 0x11, 0xbc, 0x47, 0xbf, 0x07, 0xaf, 0xb7, 0x6b,
+ 0x2f, 0xd8, 0x0c, 0x72, 0x59, 0x7d, 0xc6, 0x33, 0xeb, 0x2f, 0x40, 0x05,
+ 0xce, 0x7e, 0x44, 0x55, 0xf2, 0x5a, 0x64, 0x75, 0x14, 0x2a, 0x2f, 0xf8,
+ 0xef, 0xcc, 0x32, 0x08, 0x6b, 0x2f, 0xfc, 0xf2, 0x17, 0x9a, 0xed, 0xdf,
+ 0xb5, 0x45, 0x24, 0xbf, 0xd9, 0xe2, 0xc1, 0xf8, 0x2b, 0x2f, 0x41, 0x0d,
+ 0x65, 0x85, 0xe2, 0x34, 0xce, 0x71, 0xf4, 0xe3, 0x0c, 0xaf, 0xff, 0xfb,
+ 0x08, 0x3c, 0x8c, 0x2f, 0x93, 0x9b, 0x93, 0x41, 0x0d, 0x65, 0xc7, 0x25,
+ 0x97, 0xff, 0x4d, 0xe7, 0x3f, 0xfd, 0x1f, 0x09, 0xd6, 0x5f, 0x61, 0x44,
+ 0xeb, 0x2b, 0x0f, 0x9f, 0x48, 0xd7, 0xb3, 0x82, 0xc9, 0x30, 0x1e, 0x31,
+ 0x88, 0xfb, 0x50, 0xd8, 0xc3, 0x4f, 0x29, 0x16, 0x51, 0xb1, 0xe1, 0x57,
+ 0x71, 0xdc, 0x4c, 0x55, 0xa9, 0x40, 0x87, 0x97, 0xac, 0xe6, 0x20, 0x2b,
+ 0x25, 0xcf, 0xca, 0xbd, 0x0c, 0x3e, 0x76, 0xe3, 0x46, 0xbe, 0xed, 0xdf,
+ 0xb5, 0x44, 0x48, 0xbf, 0xff, 0x36, 0xbc, 0xfb, 0x26, 0xf4, 0x4e, 0x2b,
+ 0xd4, 0x6d, 0xac, 0xad, 0x22, 0x43, 0xc6, 0x17, 0xff, 0xfb, 0xd1, 0x38,
+ 0xaf, 0x51, 0xb6, 0x2f, 0x4d, 0x07, 0x9f, 0x0c, 0x59, 0x61, 0x78, 0x88,
+ 0xf9, 0x88, 0xef, 0x69, 0xf4, 0xb2, 0xff, 0xcf, 0x21, 0x79, 0xae, 0xdd,
+ 0xfb, 0x54, 0x4b, 0xcb, 0xe7, 0xfb, 0xce, 0xb2, 0xc2, 0xd9, 0x11, 0x87,
+ 0x1c, 0xdb, 0x4e, 0xbf, 0xfa, 0x37, 0xbc, 0xcd, 0xae, 0xa5, 0x13, 0x2c,
+ 0xbd, 0xb5, 0x1c, 0x0b, 0x2e, 0x98, 0x96, 0x5f, 0xf8, 0x54, 0x76, 0x18,
+ 0x60, 0xa2, 0x4b, 0x2f, 0xfb, 0x64, 0x7d, 0xb5, 0x1b, 0xe6, 0x59, 0x7f,
+ 0xfb, 0xd1, 0xc1, 0x07, 0x1a, 0x9b, 0x08, 0x0b, 0x2f, 0xb4, 0x1f, 0xf1,
+ 0x65, 0xfc, 0x36, 0x35, 0xc8, 0x0b, 0x2f, 0xd0, 0x40, 0x19, 0xd6, 0x5f,
+ 0xb4, 0x03, 0xb7, 0x16, 0x5e, 0x82, 0xe9, 0x65, 0xfb, 0xe2, 0x1c, 0xa1,
+ 0x65, 0x9b, 0xc7, 0x88, 0x43, 0x97, 0xff, 0xbd, 0xbe, 0x08, 0x1b, 0x98,
+ 0x3c, 0xd7, 0x4b, 0x2f, 0xf3, 0x69, 0xc6, 0xc4, 0x6a, 0xcb, 0xa3, 0xeb,
+ 0x2f, 0xf9, 0xe7, 0xd4, 0x75, 0x26, 0x3a, 0xcb, 0xff, 0xc1, 0x1b, 0x68,
+ 0x49, 0xb7, 0x42, 0xe5, 0x32, 0xca, 0x92, 0x68, 0xec, 0x4d, 0xe4, 0xf0,
+ 0x19, 0x10, 0xb7, 0x0e, 0xaf, 0xe0, 0x7a, 0x34, 0xc7, 0x59, 0x7f, 0xe9,
+ 0xb9, 0x1b, 0xdf, 0xd1, 0xd4, 0xcb, 0x2a, 0x0f, 0xc1, 0xcb, 0x6f, 0x6e,
+ 0x88, 0x75, 0x97, 0x78, 0x0b, 0x29, 0x8d, 0xc3, 0x90, 0xdf, 0xb2, 0x7c,
+ 0xe1, 0xd6, 0x5f, 0xb5, 0x1f, 0x6d, 0xeb, 0x2f, 0xd3, 0xbf, 0x1c, 0x0b,
+ 0x29, 0x8f, 0x45, 0xca, 0x6f, 0xfe, 0x9b, 0x60, 0x85, 0x1b, 0xdf, 0x7c,
+ 0x4c, 0xb2, 0x96, 0x5f, 0x7f, 0x35, 0x32, 0xcb, 0xdf, 0x7d, 0xeb, 0x2d,
+ 0x2c, 0x3c, 0x17, 0x23, 0xbf, 0x3f, 0x23, 0x7e, 0x2c, 0xa9, 0x8f, 0x3b,
+ 0x79, 0x35, 0x42, 0x61, 0x78, 0x98, 0xf0, 0x9a, 0xbb, 0x50, 0xb2, 0xb6,
+ 0xa5, 0xdd, 0xc9, 0x1e, 0x8d, 0x2f, 0x08, 0xfa, 0x2d, 0x62, 0x79, 0xa3,
+ 0xb3, 0xd4, 0x31, 0xbc, 0xb0, 0x43, 0xff, 0x79, 0xdf, 0x19, 0x5e, 0xe9,
+ 0x9d, 0xd8, 0x4b, 0x2f, 0xed, 0x9c, 0xf6, 0x37, 0xd6, 0x50, 0xcf, 0x11,
+ 0x85, 0x6d, 0xd2, 0xcb, 0xfe, 0x03, 0xfe, 0x70, 0xcd, 0x1b, 0x8b, 0x28,
+ 0x67, 0xa0, 0xc2, 0x57, 0xf1, 0x07, 0xf3, 0x41, 0xab, 0x2f, 0x0a, 0xdb,
+ 0x4b, 0x29, 0xcf, 0x3c, 0x25, 0xf7, 0xff, 0x63, 0x75, 0xcf, 0xc4, 0xe7,
+ 0x79, 0x2c, 0xa6, 0x3e, 0x6d, 0x10, 0xdf, 0xe0, 0xff, 0xc5, 0x19, 0xa5,
+ 0x97, 0xe2, 0xc9, 0xc4, 0xde, 0xb2, 0xfb, 0x27, 0x13, 0x7a, 0xcb, 0xf0,
+ 0xe3, 0xa1, 0xbe, 0xc3, 0xd1, 0x22, 0xbb, 0xff, 0xe6, 0xd6, 0xcf, 0x43,
+ 0x7f, 0x81, 0xec, 0x30, 0xb2, 0xf9, 0xa7, 0x06, 0xe2, 0xcb, 0x74, 0xb2,
+ 0xf3, 0xbf, 0x6a, 0x8a, 0x5d, 0x4b, 0x2b, 0x0f, 0x1b, 0xb1, 0x29, 0x8a,
+ 0x6f, 0x8b, 0xf1, 0xa5, 0x97, 0xfd, 0x9a, 0xdc, 0xc1, 0xe6, 0xba, 0x59,
+ 0x4c, 0x7b, 0xbb, 0xc8, 0x6f, 0xfd, 0x12, 0xf3, 0xb7, 0x5c, 0x83, 0x56,
+ 0x54, 0xea, 0x9c, 0x25, 0x08, 0x33, 0x50, 0x26, 0x52, 0xd3, 0x67, 0xa1,
+ 0x1a, 0x44, 0x77, 0xff, 0xcf, 0xa9, 0xf6, 0x6f, 0x0f, 0xa1, 0x8f, 0x03,
+ 0x59, 0x7a, 0x35, 0xf5, 0x97, 0xf0, 0xfa, 0x8d, 0x37, 0x4b, 0x2f, 0xbf,
+ 0x3e, 0x18, 0xb2, 0xa4, 0x7d, 0xec, 0x38, 0x45, 0xf7, 0xe6, 0x37, 0x59,
+ 0xc5, 0x97, 0xfe, 0x82, 0x8f, 0x6c, 0x09, 0x07, 0xb5, 0x97, 0x82, 0xfc,
+ 0x59, 0x7d, 0x30, 0x5e, 0x65, 0x97, 0xe8, 0x03, 0xf5, 0xc5, 0x97, 0x89,
+ 0x80, 0xb2, 0xf6, 0x7f, 0x8b, 0x2a, 0x0d, 0xbf, 0x06, 0xea, 0x49, 0x93,
+ 0x8c, 0xa2, 0x64, 0x0f, 0x0e, 0x00, 0x93, 0xeb, 0xf7, 0xed, 0xc7, 0x21,
+ 0xee, 0xac, 0xa5, 0x97, 0xee, 0x7f, 0x51, 0xc5, 0x96, 0x8e, 0x8d, 0x9f,
+ 0xc2, 0xef, 0xf8, 0x1c, 0xd4, 0x75, 0x26, 0x3a, 0xcb, 0xdf, 0x7d, 0xeb,
+ 0x2f, 0xd3, 0x86, 0x68, 0xdc, 0x59, 0x7c, 0x19, 0xa3, 0x71, 0x65, 0xcf,
+ 0x3e, 0xc3, 0xd3, 0x9c, 0xb6, 0xa1, 0x1b, 0x8e, 0x74, 0x17, 0x1b, 0xfe,
+ 0x86, 0x07, 0x20, 0xef, 0xf5, 0x97, 0xfc, 0xdc, 0x99, 0x8b, 0xf0, 0x05,
+ 0x97, 0xff, 0x17, 0xf7, 0xc6, 0xb8, 0xe5, 0x1b, 0x8b, 0x2f, 0xe7, 0x69,
+ 0xf6, 0x1f, 0x16, 0x54, 0x93, 0x13, 0xd1, 0x71, 0xcd, 0xf8, 0x71, 0xf4,
+ 0x7b, 0xfd, 0x1b, 0x9c, 0x83, 0xbf, 0xd6, 0x5c, 0xe4, 0xb2, 0xff, 0xa0,
+ 0x1b, 0x3d, 0x07, 0x72, 0x59, 0x5d, 0x1e, 0x76, 0xf1, 0x5b, 0xff, 0xec,
+ 0x18, 0x93, 0x73, 0xfe, 0xc1, 0x87, 0xfc, 0x59, 0x52, 0x47, 0xde, 0xa1,
+ 0x07, 0xe2, 0x5b, 0xfa, 0x0c, 0x6f, 0x07, 0x71, 0x65, 0xfd, 0xd4, 0xb8,
+ 0xe5, 0xd2, 0xca, 0x85, 0xc5, 0x19, 0x30, 0x64, 0xa1, 0x66, 0x8d, 0x1b,
+ 0x46, 0xa2, 0x18, 0xdf, 0xf8, 0xa6, 0xd9, 0xa8, 0xea, 0x4c, 0x75, 0x97,
+ 0xff, 0xb7, 0xc1, 0x7f, 0xfe, 0xc1, 0x87, 0xfc, 0x59, 0x74, 0x1d, 0x65,
+ 0x42, 0x29, 0x31, 0x0b, 0x49, 0x97, 0xe2, 0x9b, 0xec, 0x6a, 0xcb, 0xf3,
+ 0x0c, 0x25, 0x8b, 0x2f, 0xfe, 0xff, 0xb2, 0x5b, 0x20, 0x7e, 0x7e, 0x96,
+ 0x54, 0xc7, 0xda, 0x44, 0xd5, 0x08, 0xb8, 0x0c, 0x25, 0xaf, 0xfa, 0x59,
+ 0xa9, 0xb0, 0xa0, 0xeb, 0x2f, 0xc0, 0x8e, 0xf0, 0xeb, 0x2f, 0xf6, 0x4f,
+ 0xc8, 0x98, 0x3a, 0x59, 0x7e, 0x3e, 0x3b, 0x4e, 0xb2, 0x99, 0x17, 0x9a,
+ 0x38, 0x22, 0x8e, 0x1a, 0xdd, 0x2c, 0x59, 0x7e, 0xe1, 0xba, 0x73, 0x16,
+ 0x5e, 0x28, 0x3a, 0xca, 0x19, 0xe2, 0xe8, 0xaa, 0xfb, 0xad, 0xcc, 0x92,
+ 0xcb, 0xfc, 0xfa, 0x9b, 0x3f, 0xbb, 0xbd, 0x65, 0xe8, 0x07, 0x16, 0x54,
+ 0x26, 0x66, 0x33, 0xbc, 0x5b, 0x72, 0x20, 0x93, 0x18, 0x73, 0x7c, 0xfe,
+ 0x79, 0xd6, 0x5f, 0xbc, 0x13, 0x70, 0x96, 0x5e, 0x31, 0xe4, 0xb2, 0xff,
+ 0x18, 0x4f, 0xf9, 0x38, 0xd6, 0x5f, 0xbe, 0x24, 0xf1, 0xe5, 0x97, 0xfd,
+ 0x1e, 0xe3, 0xfe, 0x35, 0xba, 0xb2, 0xff, 0xc7, 0x71, 0x89, 0x34, 0xa0,
+ 0xba, 0x59, 0x43, 0x3f, 0xc6, 0x3b, 0xbf, 0x83, 0xe8, 0xd6, 0x01, 0x65,
+ 0xf6, 0x80, 0x26, 0xf5, 0x97, 0x98, 0xcf, 0xac, 0xa9, 0x1f, 0x87, 0x8b,
+ 0x78, 0x4d, 0x53, 0xaa, 0x00, 0x19, 0x16, 0x14, 0x74, 0x3b, 0x31, 0x9f,
+ 0xa1, 0x4d, 0xf8, 0x48, 0xdf, 0xe2, 0xfe, 0x71, 0x9f, 0xcb, 0x2f, 0xb9,
+ 0x2e, 0x3a, 0xcb, 0xfe, 0x03, 0x7b, 0x34, 0xf3, 0x71, 0x65, 0xff, 0xf4,
+ 0x8a, 0x27, 0x12, 0x6e, 0x7b, 0x37, 0x74, 0x05, 0x97, 0xa4, 0x3d, 0xeb,
+ 0x2a, 0x0f, 0xd5, 0xd5, 0xaf, 0xed, 0x87, 0xcf, 0xbf, 0xd6, 0x5f, 0xde,
+ 0x61, 0xb6, 0xbb, 0x59, 0x6e, 0xd6, 0x5b, 0x98, 0x7d, 0xfd, 0x97, 0xb9,
+ 0x75, 0xee, 0xa6, 0xe2, 0xca, 0xe8, 0xf4, 0xdc, 0xd2, 0xf4, 0x30, 0xd6,
+ 0x5f, 0xe9, 0xbc, 0xdf, 0x28, 0x3a, 0xca, 0x85, 0x4a, 0x63, 0x31, 0xe8,
+ 0x88, 0xf0, 0xae, 0x78, 0x71, 0x70, 0x88, 0x23, 0x77, 0xfb, 0x0c, 0x93,
+ 0x70, 0x27, 0x59, 0x76, 0xfe, 0x2c, 0xbf, 0x83, 0xc8, 0x98, 0x3a, 0x59,
+ 0x7e, 0xc9, 0xf3, 0xdc, 0x59, 0x50, 0x7e, 0x1e, 0x19, 0x22, 0xfb, 0xe3,
+ 0x86, 0x6d, 0x2c, 0xbd, 0x9a, 0xe2, 0xca, 0xec, 0xfb, 0x4e, 0x5b, 0xbc,
+ 0x92, 0xff, 0x81, 0x00, 0x13, 0x7c, 0x16, 0xea, 0xcb, 0xff, 0xf4, 0xf1,
+ 0xf8, 0xf3, 0x7e, 0x4d, 0xae, 0xfd, 0x0b, 0x2a, 0x13, 0xd7, 0xc8, 0xc4,
+ 0x58, 0xc9, 0xcf, 0xaf, 0xff, 0xfb, 0x5d, 0x76, 0xdd, 0x6c, 0x35, 0xf6,
+ 0x73, 0xcf, 0xdc, 0x10, 0xd6, 0x5f, 0xf3, 0xf0, 0x4f, 0xf5, 0xdb, 0x1d,
+ 0x65, 0xbd, 0x08, 0xab, 0x0b, 0x7d, 0xf3, 0x1b, 0xb7, 0x8b, 0x2f, 0xe1,
+ 0x3f, 0x13, 0x97, 0x4b, 0x2f, 0xff, 0xbb, 0xf3, 0xcc, 0x24, 0xd2, 0x62,
+ 0xc3, 0xc2, 0xcb, 0xc4, 0xc7, 0x59, 0x5a, 0x46, 0x10, 0x09, 0x48, 0xc3,
+ 0xea, 0x57, 0xff, 0x7f, 0x82, 0x73, 0x08, 0x3f, 0x8f, 0x2c, 0xbf, 0xa1,
+ 0xcb, 0xf8, 0x4b, 0x2b, 0x0f, 0xbc, 0x91, 0x6f, 0xf4, 0x75, 0xcd, 0xc8,
+ 0xd1, 0xab, 0x2f, 0xf7, 0x9e, 0x66, 0xd4, 0x4e, 0xb2, 0xfd, 0xba, 0x78,
+ 0xcf, 0xac, 0xbf, 0xf8, 0x4f, 0xca, 0x06, 0xe5, 0x9f, 0x02, 0xca, 0xc3,
+ 0xee, 0xd1, 0x55, 0xd8, 0x75, 0x94, 0x35, 0x58, 0xd9, 0x0e, 0xa3, 0xc2,
+ 0xaf, 0xc4, 0x0e, 0x70, 0x18, 0x51, 0x6f, 0x21, 0xbf, 0x6e, 0xb1, 0xe3,
+ 0x8b, 0x2f, 0xcf, 0xbf, 0x35, 0xc5, 0x97, 0xe9, 0xc4, 0xde, 0xf2, 0x59,
+ 0x43, 0x3f, 0xf3, 0x95, 0x11, 0x4d, 0x8c, 0x59, 0x7e, 0xf3, 0x93, 0x1d,
+ 0x65, 0xf1, 0xb3, 0x72, 0x16, 0x5f, 0xf4, 0x7f, 0xcf, 0x33, 0xcd, 0x8b,
+ 0x2f, 0xe0, 0x74, 0x0c, 0xd6, 0x2c, 0xbf, 0xbb, 0x86, 0xfb, 0x49, 0x65,
+ 0xe8, 0xcf, 0xac, 0xbf, 0x66, 0xb4, 0x19, 0xd6, 0x5c, 0xe0, 0x39, 0xe2,
+ 0x7c, 0x6e, 0xa1, 0x19, 0x98, 0x5c, 0xce, 0x37, 0xc3, 0xf3, 0xf4, 0xb2,
+ 0xfe, 0x07, 0x23, 0xd1, 0xc5, 0x95, 0x07, 0xa0, 0xe4, 0x77, 0xdf, 0xe6,
+ 0x4e, 0xb2, 0xff, 0xff, 0x79, 0xb7, 0xb8, 0x1a, 0x51, 0xbd, 0xcf, 0x1e,
+ 0xdd, 0x75, 0x95, 0xd2, 0x22, 0x3c, 0x47, 0x76, 0x4e, 0xb2, 0x9c, 0xdd,
+ 0x91, 0x25, 0x42, 0xb0, 0xe1, 0x97, 0x60, 0x93, 0x13, 0x4c, 0x49, 0xe8,
+ 0xc1, 0x49, 0xf7, 0x90, 0xe3, 0xbf, 0xff, 0xde, 0xed, 0xb9, 0x83, 0xef,
+ 0xcd, 0xfc, 0x98, 0xa0, 0xeb, 0x2e, 0x07, 0x6b, 0x2d, 0xc5, 0x97, 0x31,
+ 0xbc, 0x35, 0x21, 0x18, 0xbc, 0x07, 0xed, 0x65, 0xf1, 0x93, 0x72, 0x16,
+ 0x5f, 0x3c, 0xf1, 0xf5, 0x97, 0xe7, 0x26, 0xdc, 0xde, 0xb2, 0xdc, 0x23,
+ 0xcd, 0xde, 0x45, 0x7e, 0x9d, 0xf9, 0x92, 0x59, 0x7f, 0xfc, 0x3c, 0xde,
+ 0xfa, 0x98, 0x49, 0x3f, 0xdc, 0xeb, 0x2e, 0xcd, 0xc5, 0x95, 0x08, 0x94,
+ 0x62, 0x8d, 0x29, 0xdf, 0xcf, 0xd0, 0x0e, 0xdc, 0x59, 0x63, 0x56, 0x5f,
+ 0xb5, 0x9b, 0xc7, 0x0b, 0x2a, 0x13, 0xe2, 0xe8, 0x76, 0x67, 0x1d, 0x42,
+ 0xf7, 0xc5, 0xc0, 0x2e, 0xf8, 0x95, 0xfc, 0xc6, 0x3c, 0xd0, 0x75, 0x97,
+ 0xb7, 0x63, 0x8b, 0x2b, 0xe7, 0x9a, 0x12, 0xeb, 0x0b, 0x14, 0xba, 0x9c,
+ 0x4d, 0xa1, 0x20, 0x54, 0x22, 0x15, 0x62, 0xf1, 0x3c, 0x3b, 0x3c, 0x62,
+ 0x72, 0x71, 0x1c, 0x35, 0xb2, 0x54, 0x8f, 0x6e, 0x5d, 0x43, 0x0d, 0xa3,
+ 0x54, 0x9a, 0x72, 0xab, 0x51, 0x84, 0x9e, 0x1c, 0xde, 0x94, 0x2c, 0xf2,
+ 0x95, 0x81, 0x2b, 0x14, 0xa5, 0x23, 0x72, 0x5d, 0x8f, 0xe7, 0x00, 0x82,
+ 0xf7, 0xb7, 0x08, 0xb1, 0x25, 0x07, 0xee, 0xc2, 0xe2, 0xfd, 0xae, 0xdd,
+ 0xfb, 0x54, 0x53, 0x8b, 0xfb, 0xcc, 0x72, 0x73, 0x56, 0x58, 0x5e, 0x1f,
+ 0x1b, 0x1b, 0x5f, 0xd0, 0x7c, 0xdd, 0x8f, 0xac, 0xbe, 0xf4, 0x11, 0xab,
+ 0x2f, 0xa3, 0xb8, 0xf2, 0xca, 0x39, 0xf9, 0xfc, 0xbc, 0x42, 0x2b, 0xec,
+ 0xe0, 0x92, 0x59, 0x7f, 0xda, 0x7e, 0x7b, 0x30, 0xbb, 0x59, 0x7f, 0x07,
+ 0x99, 0xf1, 0x27, 0x59, 0x4c, 0x7d, 0x1e, 0x38, 0xbf, 0x1f, 0x5a, 0xce,
+ 0x2c, 0xbf, 0xff, 0x78, 0x3f, 0xd4, 0x7f, 0x99, 0xdf, 0x23, 0x5d, 0xac,
+ 0xbe, 0x0e, 0xeb, 0xcc, 0xb2, 0xff, 0x31, 0xb9, 0x28, 0x07, 0x16, 0x54,
+ 0x8f, 0x67, 0x84, 0xd7, 0x87, 0x07, 0x59, 0x7f, 0xa3, 0xed, 0xdb, 0x0e,
+ 0x16, 0x5b, 0x4b, 0x2f, 0xff, 0xa6, 0x26, 0xe7, 0xe0, 0x46, 0xd4, 0xd1,
+ 0xe5, 0x95, 0x23, 0xe2, 0xc1, 0x1a, 0x1a, 0x34, 0x74, 0x39, 0xf8, 0x4a,
+ 0x5e, 0xce, 0x32, 0xcb, 0xfd, 0x1f, 0x86, 0x21, 0x38, 0xb2, 0xb0, 0xf3,
+ 0x74, 0x37, 0x7f, 0xfe, 0xcf, 0xf0, 0x4e, 0x7d, 0xa0, 0xbe, 0x4e, 0x05,
+ 0x97, 0xf7, 0x52, 0x83, 0x86, 0x65, 0x97, 0xf1, 0xc7, 0x1c, 0x09, 0x2c,
+ 0xbd, 0x28, 0x3a, 0xcb, 0xbc, 0xcb, 0x2b, 0xa3, 0x65, 0xf1, 0xca, 0x84,
+ 0x58, 0xb1, 0x83, 0xaf, 0xdf, 0x73, 0x67, 0x04, 0x59, 0x7f, 0xf6, 0x6f,
+ 0xc1, 0xea, 0x1a, 0x4f, 0xc5, 0x96, 0x7e, 0x8f, 0xab, 0x44, 0xd7, 0xa5,
+ 0x06, 0x2c, 0xbf, 0xcd, 0x87, 0x34, 0xd7, 0xe9, 0x65, 0xbf, 0xd1, 0xe9,
+ 0x70, 0x76, 0xfe, 0x71, 0x33, 0x7c, 0x71, 0x65, 0x61, 0xec, 0x04, 0xa6,
+ 0xff, 0xef, 0x30, 0x9f, 0x62, 0x0c, 0xb3, 0x8b, 0x2f, 0xfc, 0xdd, 0x70,
+ 0xb0, 0x7e, 0x73, 0x16, 0x5f, 0xff, 0x64, 0xf9, 0xd7, 0xf8, 0xc5, 0x00,
+ 0x73, 0xac, 0xac, 0x46, 0x91, 0xa8, 0x9c, 0x3f, 0xbf, 0xf6, 0x7a, 0x35,
+ 0x82, 0xcc, 0x30, 0xc4, 0x97, 0x31, 0x8b, 0x2e, 0x9c, 0x5c, 0x2f, 0x9b,
+ 0x48, 0xc0, 0x70, 0x8b, 0xc2, 0x1e, 0xca, 0x3a, 0x85, 0x8b, 0x43, 0xce,
+ 0x68, 0x41, 0x1c, 0x87, 0xd1, 0x82, 0x82, 0x12, 0xe5, 0x0d, 0x2f, 0xc3,
+ 0xcf, 0x6c, 0xc3, 0x75, 0x0e, 0xfd, 0xae, 0xdd, 0xfb, 0x54, 0x57, 0x8b,
+ 0xef, 0xe9, 0xba, 0x59, 0x7f, 0xff, 0x60, 0xfd, 0x02, 0x0b, 0xf9, 0x38,
+ 0x39, 0xc8, 0x02, 0x4b, 0x0b, 0xc4, 0x5b, 0x31, 0xb6, 0xd9, 0x1d, 0xff,
+ 0xc2, 0xde, 0x42, 0xf3, 0x5d, 0xbb, 0xf6, 0xa8, 0x91, 0xd7, 0x61, 0xd6,
+ 0x5d, 0xfc, 0x59, 0x5d, 0x9a, 0xce, 0x85, 0xaf, 0xff, 0x1a, 0xda, 0xcd,
+ 0x4a, 0x3d, 0xe6, 0x02, 0xcb, 0xbc, 0x35, 0x97, 0xff, 0xef, 0xc0, 0xe0,
+ 0x22, 0xbd, 0x47, 0xd8, 0x11, 0x25, 0x97, 0x89, 0xc5, 0xc8, 0xfb, 0xf7,
+ 0x8b, 0xde, 0x60, 0x42, 0xcb, 0xdd, 0xe1, 0xd2, 0x0b, 0x2e, 0xef, 0xb1,
+ 0xfa, 0x02, 0xcb, 0xff, 0xf7, 0xa0, 0x83, 0xcf, 0x36, 0xb3, 0x7c, 0x17,
+ 0xd6, 0x5f, 0xfc, 0xda, 0xcd, 0x4a, 0x3d, 0xe6, 0x02, 0xcb, 0xee, 0xdd,
+ 0xfb, 0x54, 0x49, 0x0b, 0xf9, 0xf5, 0x9b, 0xfd, 0x8b, 0x2a, 0x74, 0xc6,
+ 0x24, 0x44, 0x6a, 0xae, 0x90, 0xc0, 0x61, 0x7d, 0x37, 0xf3, 0xb5, 0x97,
+ 0xe8, 0x60, 0x31, 0xd6, 0x54, 0x1e, 0x54, 0x89, 0x2f, 0xf4, 0x17, 0xca,
+ 0x0f, 0xc5, 0x97, 0xff, 0xe6, 0xd3, 0x6e, 0xc1, 0x4f, 0x1f, 0x6f, 0x3c,
+ 0xeb, 0x2f, 0xcf, 0x2f, 0xb4, 0xeb, 0x2a, 0x0f, 0xfd, 0x95, 0xef, 0xff,
+ 0x3f, 0xe6, 0xe6, 0x0c, 0x61, 0x7d, 0x49, 0x65, 0xff, 0xf3, 0xf5, 0xcc,
+ 0xf3, 0x96, 0x4e, 0x70, 0xf9, 0x65, 0xff, 0xde, 0x6e, 0xbf, 0x9d, 0x7f,
+ 0x5a, 0x85, 0x97, 0xff, 0x34, 0x1d, 0xc6, 0x26, 0xec, 0x14, 0x96, 0x56,
+ 0x23, 0x73, 0xb5, 0x0f, 0x23, 0x5f, 0xfd, 0x80, 0xdb, 0xcd, 0x44, 0xef,
+ 0xae, 0xd6, 0x5f, 0x9c, 0x1f, 0xc0, 0x2c, 0xa2, 0x3e, 0xfe, 0x24, 0x5f,
+ 0xec, 0xf3, 0x9c, 0xa3, 0xa5, 0x97, 0x48, 0x5c, 0x2e, 0x73, 0xe4, 0x68,
+ 0xcd, 0x09, 0x79, 0x88, 0x7d, 0x0b, 0x00, 0x10, 0x72, 0x32, 0x7f, 0xc2,
+ 0x7c, 0x42, 0x1b, 0xf0, 0x7a, 0xed, 0xb8, 0xb2, 0xfd, 0x9e, 0x17, 0x87,
+ 0x59, 0x7c, 0x69, 0x04, 0xeb, 0x2c, 0x2e, 0x17, 0xcc, 0xf0, 0x8f, 0xb8,
+ 0x5c, 0xbc, 0xe9, 0xc0, 0x21, 0x53, 0xf2, 0xa1, 0x0a, 0x6f, 0xfe, 0x16,
+ 0xf2, 0x17, 0x9a, 0xed, 0xdf, 0xb5, 0x44, 0x94, 0xbf, 0x6b, 0xb7, 0x7e,
+ 0xd5, 0x17, 0x8a, 0xff, 0xa4, 0x2f, 0x35, 0xdb, 0xbf, 0x6a, 0x89, 0x35,
+ 0x61, 0x78, 0x7f, 0xee, 0x6d, 0x7d, 0xdf, 0x98, 0x96, 0x5c, 0x31, 0x42,
+ 0xcb, 0xfe, 0x14, 0xed, 0x1b, 0x47, 0xb0, 0xf9, 0xc5, 0x97, 0xf6, 0xd4,
+ 0x28, 0x07, 0xff, 0xd2, 0xcb, 0xf7, 0x39, 0x85, 0x8b, 0x2f, 0xfb, 0x5d,
+ 0xc4, 0xf9, 0x85, 0xf5, 0x97, 0xf1, 0x09, 0x36, 0xa3, 0x7a, 0xcb, 0xfa,
+ 0x38, 0xc7, 0x89, 0x96, 0x5f, 0x3b, 0x75, 0xc5, 0x96, 0xf2, 0xca, 0xc4,
+ 0x78, 0x31, 0x36, 0xe1, 0xc9, 0xcc, 0x7c, 0x5a, 0x61, 0x15, 0xfe, 0x60,
+ 0x61, 0x47, 0x5c, 0x59, 0x7b, 0x7c, 0x49, 0x65, 0xfa, 0x3f, 0xcc, 0xfa,
+ 0xcb, 0xce, 0x43, 0xc3, 0xc5, 0xf0, 0xf5, 0xfe, 0x63, 0x7a, 0xe6, 0x11,
+ 0xab, 0x2f, 0xf9, 0xf5, 0x2e, 0x60, 0x75, 0x3a, 0xca, 0x64, 0x50, 0x78,
+ 0xc4, 0x26, 0xb7, 0xfd, 0x80, 0x1f, 0xa0, 0xa0, 0xc5, 0x97, 0xc0, 0xe6,
+ 0x12, 0xca, 0x83, 0xd9, 0x63, 0x8b, 0xff, 0x07, 0xbe, 0x71, 0xf5, 0xf8,
+ 0x35, 0x65, 0xfb, 0xdf, 0xe6, 0x7d, 0x65, 0x31, 0xf4, 0xba, 0x0d, 0xff,
+ 0xfb, 0xce, 0xc0, 0xe6, 0x1a, 0xe7, 0xd4, 0x61, 0x2c, 0xb9, 0x86, 0xb2,
+ 0xa0, 0xfa, 0x7c, 0xa7, 0x7d, 0x20, 0xc7, 0x4b, 0x2f, 0xfa, 0x76, 0xe7,
+ 0x1c, 0x1e, 0x0a, 0xcb, 0xf9, 0xb4, 0x32, 0x8e, 0x96, 0x5f, 0xf6, 0x1a,
+ 0x6b, 0xcb, 0x3a, 0xfa, 0xcb, 0xd3, 0xc4, 0xeb, 0x2f, 0x05, 0xfa, 0xc3,
+ 0xd9, 0x10, 0xee, 0xfe, 0xf6, 0x67, 0xfd, 0x8b, 0x2f, 0xfa, 0x25, 0xcd,
+ 0x69, 0xcb, 0xeb, 0x2a, 0x4a, 0xab, 0x87, 0x08, 0x9e, 0xe1, 0x13, 0x31,
+ 0x0e, 0x88, 0xfc, 0x75, 0xc8, 0x43, 0x7c, 0xd3, 0x79, 0x65, 0xfc, 0xd8,
+ 0x51, 0xd7, 0x16, 0x5f, 0xd9, 0xff, 0xc1, 0x4e, 0xb2, 0xfd, 0x83, 0xda,
+ 0x45, 0xb8, 0xb2, 0xfe, 0x72, 0x06, 0xd2, 0x2d, 0xc5, 0x97, 0x38, 0xf7,
+ 0x9f, 0x2e, 0xd9, 0x85, 0x1d, 0x1e, 0x1e, 0x2c, 0x0c, 0x24, 0xaf, 0x39,
+ 0x76, 0xb2, 0xf7, 0xa0, 0x45, 0x95, 0xf3, 0x72, 0x60, 0xe5, 0xff, 0xbc,
+ 0xf2, 0x6f, 0x3c, 0x9b, 0xcb, 0x2f, 0xe2, 0x70, 0x13, 0x9d, 0x65, 0xf8,
+ 0x7e, 0xdc, 0x62, 0x59, 0x7f, 0x8b, 0x0f, 0xb7, 0x9a, 0x85, 0x95, 0x07,
+ 0xbd, 0x31, 0x55, 0xe8, 0xff, 0x16, 0x5f, 0xf4, 0x1f, 0xd8, 0x31, 0xb7,
+ 0x4b, 0x2b, 0x0f, 0xdf, 0xa2, 0x26, 0x1c, 0xbe, 0xdd, 0x68, 0x35, 0x65,
+ 0xe9, 0x74, 0x6a, 0xcb, 0xf8, 0xff, 0xf0, 0x7f, 0xc5, 0x97, 0x82, 0x3e,
+ 0x96, 0x5f, 0xfc, 0xe0, 0xef, 0xcd, 0xa2, 0x6f, 0xf1, 0x65, 0xfe, 0xdf,
+ 0x92, 0xf4, 0x11, 0xab, 0x2e, 0x29, 0xd6, 0x54, 0x26, 0x42, 0x32, 0x5c,
+ 0x1f, 0x62, 0xf7, 0x1e, 0x02, 0x20, 0x86, 0xb6, 0xfa, 0xcb, 0xfe, 0x8d,
+ 0x01, 0xff, 0xb7, 0x9f, 0x59, 0x76, 0xb1, 0x65, 0xf7, 0x4d, 0xd4, 0x96,
+ 0x5c, 0x24, 0xeb, 0x29, 0x8d, 0xe8, 0x09, 0x2b, 0x48, 0xbf, 0xf0, 0x88,
+ 0x0e, 0xc9, 0x4e, 0xec, 0x3a, 0xcb, 0xda, 0xdf, 0xe5, 0x97, 0xec, 0xd3,
+ 0xc0, 0xd6, 0x54, 0x1e, 0xdb, 0x8b, 0x10, 0xfd, 0xe1, 0xe1, 0x2c, 0xbf,
+ 0xf6, 0x82, 0x7f, 0x34, 0x1d, 0xc9, 0x65, 0xff, 0x72, 0x0e, 0x59, 0x28,
+ 0x25, 0x97, 0xf9, 0x8b, 0x66, 0x1d, 0xbe, 0xb2, 0xb4, 0x8a, 0x6f, 0x9e,
+ 0xef, 0x36, 0xb8, 0xa4, 0xb2, 0xe1, 0x41, 0x8b, 0x28, 0x26, 0xcb, 0x6c,
+ 0x5a, 0xa1, 0x34, 0x9c, 0x86, 0x0e, 0xeb, 0x25, 0xff, 0xdd, 0x85, 0xc7,
+ 0xbf, 0x07, 0xb4, 0x8b, 0x71, 0x65, 0xf3, 0x7a, 0x37, 0xac, 0xad, 0x1f,
+ 0x9f, 0xd4, 0x2f, 0xf4, 0x6a, 0x3a, 0x06, 0xa1, 0x65, 0xe6, 0xdd, 0x9d,
+ 0x65, 0xa7, 0x59, 0x50, 0x6c, 0x88, 0x82, 0xf7, 0x83, 0xb8, 0xb2, 0xfe,
+ 0x28, 0xff, 0x9e, 0x4b, 0x2a, 0x0f, 0x32, 0x62, 0x0b, 0xdf, 0x8d, 0x2c,
+ 0xa8, 0x4c, 0xc2, 0x72, 0x29, 0x99, 0x5d, 0xac, 0x24, 0x57, 0x3f, 0x6b,
+ 0x2f, 0xff, 0xff, 0x61, 0x13, 0xcb, 0xcd, 0xb0, 0x4d, 0x6a, 0x24, 0xdf,
+ 0x6d, 0x38, 0x16, 0x5f, 0x86, 0x19, 0xc4, 0x3a, 0xcb, 0xfc, 0x59, 0xff,
+ 0x37, 0x52, 0x59, 0x5d, 0x9e, 0xf7, 0x8a, 0xef, 0xee, 0xb9, 0x87, 0x7e,
+ 0x2c, 0xbe, 0x1e, 0x7a, 0x16, 0x5b, 0x4b, 0x2f, 0xd3, 0xea, 0x3a, 0xd2,
+ 0xca, 0x9c, 0xdd, 0xe0, 0x8d, 0xfe, 0x08, 0xf2, 0x50, 0x0e, 0x2c, 0xa8,
+ 0x4f, 0xb6, 0x42, 0xf9, 0x0d, 0x56, 0x23, 0x72, 0xe2, 0x5c, 0xe1, 0x0d,
+ 0xff, 0xec, 0xf7, 0x7e, 0x6e, 0xbf, 0x87, 0x7e, 0x2c, 0xbe, 0x9c, 0xe1,
+ 0xdc, 0x59, 0x7e, 0xf9, 0xe6, 0x21, 0xac, 0xa7, 0x3d, 0x02, 0x27, 0xbf,
+ 0x4d, 0xce, 0x31, 0xd6, 0x5e, 0xe0, 0x7a, 0x59, 0x7f, 0xfd, 0x39, 0x8f,
+ 0x2e, 0x73, 0x34, 0x64, 0x68, 0xd5, 0x96, 0x25, 0x97, 0xf3, 0xff, 0x93,
+ 0xe1, 0x8b, 0x2f, 0xff, 0xe6, 0xe3, 0xcb, 0x8d, 0xbf, 0x81, 0x76, 0x93,
+ 0x6f, 0x59, 0x70, 0x82, 0x2c, 0xac, 0x4d, 0x42, 0x62, 0x97, 0x1e, 0x02,
+ 0xa1, 0x08, 0x7c, 0xbc, 0x45, 0xdb, 0xf6, 0x68, 0x00, 0x85, 0x97, 0x6d,
+ 0x8b, 0xda, 0xdb, 0x52, 0xc1, 0x49, 0x16, 0xd2, 0x1b, 0xda, 0x68, 0xf1,
+ 0x19, 0x4c, 0x96, 0x47, 0x18, 0xbe, 0x4b, 0x36, 0xee, 0x38, 0x3e, 0x9b,
+ 0x98, 0x8a, 0x63, 0xdd, 0x46, 0x01, 0xe8, 0xd3, 0xde, 0x32, 0x10, 0x42,
+ 0x5c, 0xa3, 0x75, 0xe4, 0x7b, 0x5f, 0x94, 0x70, 0x63, 0x2e, 0xdc, 0x26,
+ 0xc4, 0x8d, 0xc3, 0x75, 0x92, 0xff, 0x06, 0x71, 0x7b, 0xbb, 0xac, 0x6a,
+ 0xca, 0x87, 0xd7, 0x1d, 0x9e, 0x16, 0xf2, 0xb5, 0x3f, 0xc3, 0x94, 0x9a,
+ 0xd3, 0xfa, 0x33, 0x47, 0x84, 0x73, 0x9f, 0x4f, 0xda, 0xfe, 0x10, 0x01,
+ 0x86, 0xa8, 0x95, 0xaa, 0xa6, 0xec, 0x76, 0x75, 0x14, 0xc0, 0x58, 0x79,
+ 0xe7, 0x59, 0xa5, 0x4d, 0xd7, 0x1d, 0x30, 0x43, 0x33, 0xb1, 0xbc, 0x36,
+ 0x98, 0xf7, 0xde, 0x36, 0xf8, 0xfa, 0xb6, 0xb3, 0x4d, 0x5d, 0xc3, 0x6e,
+ 0x4a, 0x75, 0x9b, 0x12, 0x9d, 0x5a, 0xc5, 0x05, 0xc9, 0xf7, 0x0a, 0xc8,
+ 0xfd, 0x69, 0x03, 0x5f, 0x12, 0xc7, 0x00, 0xad, 0xd7, 0x85, 0x73, 0x90,
+ 0xe5, 0x78, 0xca, 0xfc, 0xbc, 0x22, 0x2f, 0xe6, 0x16, 0xa6, 0x1c, 0x48,
+ 0xd1, 0xef, 0xad, 0x7b, 0x8c, 0xac, 0x49, 0xb6, 0xe7, 0xe2, 0x84, 0xac,
+ 0xd8, 0xb7, 0x6f, 0x64, 0xd6, 0x80,
};
-static const unsigned kPreloadedHSTSBits = 394224;
+static const unsigned kPreloadedHSTSBits = 803081;
-static const unsigned kHSTSRootPosition = 393600;
+static const unsigned kHSTSRootPosition = 802430;
-#endif // NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
+#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 cd69dd6451a..04c1bc3d52b 100644
--- a/chromium/net/http/transport_security_state_static.json
+++ b/chromium/net/http/transport_security_state_static.json
@@ -90,7 +90,8 @@
"DigiCertEVRoot",
"DigiCertAssuredIDRoot",
"Twitter1"
- ]
+ ],
+ "report_uri": "http://l.twimg.com/i/hpkp_report"
},
{
"name": "twitterCDN",
@@ -138,7 +139,8 @@
"GlobalSignRootCA",
"GlobalSignRootCA_R2",
"GlobalSignRootCA_R3"
- ]
+ ],
+ "report_uri": "http://l.twimg.com/i/hpkp_report"
},
{
"name": "dropbox",
@@ -246,10 +248,12 @@
{ "name": "talk.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "wallet.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "xn--7xa.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "dns.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
// Other Google-related domains that must use HTTPS.
{ "name": "apis.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "build.chromium.org", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "bugs.chromium.org", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "chrome.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "chrome-devtools-frontend.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "chromiumcodereview.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
@@ -635,7 +639,6 @@
{ "name": "jitsi.org", "mode": "force-https" },
{ "name": "www.jitsi.org", "mode": "force-https" },
{ "name": "download.jitsi.org", "mode": "force-https" },
- { "name": "sol.io", "include_subdomains": true, "mode": "force-https" },
{ "name": "irccloud.com", "mode": "force-https" },
{ "name": "www.irccloud.com", "mode": "force-https" },
{ "name": "alpha.irccloud.com", "mode": "force-https" },
@@ -727,7 +730,6 @@
{ "name": "carezone.com", "mode": "force-https" },
{ "name": "conformal.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "cyphertite.com", "include_subdomains": true, "mode": "force-https" },
- { "name": "logotype.se", "include_subdomains": true, "mode": "force-https" },
{ "name": "bccx.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "launchkey.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "carlolly.co.uk", "include_subdomains": true, "mode": "force-https" },
@@ -869,8 +871,7 @@
{ "name": "z.ai", "include_subdomains": true, "mode": "force-https" },
{ "name": "wildbee.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "portal.tirol.gv.at", "include_subdomains": true, "mode": "force-https" },
- { "name": "dropbox.com", "mode": "force-https", "include_subdomains_for_pinning": true, "pins": "dropbox" },
- { "name": "www.dropbox.com", "include_subdomains": true, "mode": "force-https", "pins": "dropbox" },
+ { "name": "dropbox.com", "mode": "force-https", "include_subdomains": true, "pins": "dropbox" },
{ "name": "dropboxstatic.com", "include_subdomains_for_pinning": true, "pins": "dropbox" },
{ "name": "dropboxusercontent.com", "include_subdomains_for_pinning": true, "pins": "dropbox" },
{ "name": "code-poets.co.uk", "include_subdomains": true, "mode": "force-https" },
@@ -1627,7 +1628,6 @@
{ "name": "visionless.me", "include_subdomains": true, "mode": "force-https" },
{ "name": "vrobert.fr", "include_subdomains": true, "mode": "force-https" },
{ "name": "wbg-vs.de", "include_subdomains": true, "mode": "force-https" },
- { "name": "hstspreload.appspot.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "hg.python.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "doc.python.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "console.python.org", "include_subdomains": true, "mode": "force-https" },
@@ -2182,7 +2182,6 @@
{ "name": "pclob.gov", "include_subdomains": true, "mode": "force-https" },
{ "name": "plzenskybarcamp.cz", "include_subdomains": true, "mode": "force-https" },
{ "name": "ponythread.com", "include_subdomains": true, "mode": "force-https" },
- { "name": "popcorntime.ws", "include_subdomains": true, "mode": "force-https" },
{ "name": "ptn.moscow", "include_subdomains": true, "mode": "force-https" },
{ "name": "radiormi.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "renem.net", "include_subdomains": true, "mode": "force-https" },
@@ -3720,14 +3719,12 @@
{ "name": "mareklecian.cz", "include_subdomains": true, "mode": "force-https" },
{ "name": "maximilian-greger.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "mb-is.info", "include_subdomains": true, "mode": "force-https" },
- { "name": "mbdb.jp", "include_subdomains": true, "mode": "force-https" },
{ "name": "minecraftforum.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "mobile.eti.br", "include_subdomains": true, "mode": "force-https" },
{ "name": "mosstier.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "motd.ch", "include_subdomains": true, "mode": "force-https" },
{ "name": "mysecretcase.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "namorico.me", "include_subdomains": true, "mode": "force-https" },
- { "name": "natukusa.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "nekomimi.pl", "include_subdomains": true, "mode": "force-https" },
{ "name": "netprofile.com.au", "include_subdomains": true, "mode": "force-https" },
{ "name": "numericacu.com", "include_subdomains": true, "mode": "force-https" },
@@ -3998,7 +3995,6 @@
{ "name": "moparisthebest.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "moparscape.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "my-pawnshop.com.ua", "include_subdomains": true, "mode": "force-https" },
- { "name": "myfrm.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "mygov.scot", "include_subdomains": true, "mode": "force-https" },
{ "name": "nagb.gov", "include_subdomains": true, "mode": "force-https" },
{ "name": "nagb.org", "include_subdomains": true, "mode": "force-https" },
@@ -4609,7 +4605,6 @@
{ "name": "infinitusgaming.eu", "include_subdomains": true, "mode": "force-https" },
{ "name": "infocommsociety.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "instant.io", "include_subdomains": true, "mode": "force-https" },
- { "name": "involved-it.be", "include_subdomains": true, "mode": "force-https" },
{ "name": "ipcfg.me", "include_subdomains": true, "mode": "force-https" },
{ "name": "ipswitch.com.tw", "include_subdomains": true, "mode": "force-https" },
{ "name": "iready.ro", "include_subdomains": true, "mode": "force-https" },
@@ -4917,7 +4912,6 @@
{ "name": "holifestival-freyung.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "huaxueba.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "ideadozz.hu", "include_subdomains": true, "mode": "force-https" },
- { "name": "idealsvdr.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "ikvts.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "interaffairs.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "isitamor.pm", "include_subdomains": true, "mode": "force-https" },
@@ -5241,7 +5235,6 @@
{ "name": "legendofkrystal.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "levendwater.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "lewisjuggins.co.uk", "include_subdomains": true, "mode": "force-https" },
- { "name": "liftcannabis.ca", "include_subdomains": true, "mode": "force-https" },
{ "name": "limalama.eu", "include_subdomains": true, "mode": "force-https" },
{ "name": "listafirmelor.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "lothai.re", "include_subdomains": true, "mode": "force-https" },
@@ -5522,7 +5515,8 @@
{ "name": "genxbeats.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "gm-assicurazioni.it", "include_subdomains": true, "mode": "force-https" },
{ "name": "goggs.eu", "include_subdomains": true, "mode": "force-https" },
- { "name": "gpo.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gpo.gov", "include_subdomains": false, "mode": "force-https" },
+ { "name": "www.gpo.gov", "include_subdomains": true, "mode": "force-https" },
{ "name": "grannyshouse.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "gurom.lv", "include_subdomains": true, "mode": "force-https" },
{ "name": "haozi.me", "include_subdomains": true, "mode": "force-https" },
@@ -5593,7 +5587,6 @@
{ "name": "shukatsu-note.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "singul4rity.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "speedtest-russia.com", "include_subdomains": true, "mode": "force-https" },
- { "name": "spira.io", "include_subdomains": true, "mode": "force-https" },
{ "name": "starstreak.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "taxbench.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "temizmama.com", "include_subdomains": true, "mode": "force-https" },
@@ -5620,7 +5613,5997 @@
{ "name": "yellowcar.website", "include_subdomains": true, "mode": "force-https" },
{ "name": "youcancraft.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "yunity.org", "include_subdomains": true, "mode": "force-https" },
- { "name": "zhangyuhao.com", "include_subdomains": true, "mode": "force-https" }
+ { "name": "zhangyuhao.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "a-plus.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "achenar.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adelevie.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andrewsun.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anedot.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aosus.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "astengox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "asun.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atlantichomes.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "autokovrik-diskont.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ben.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bm-trading.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bodyblog.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bpastudies.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ceopedia.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cfetengineering.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cinefilzonen.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cirfi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codabix.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codabix.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codabix.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "creditkarma.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cryptify.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crystalchandelierservices.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cwagner.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyberkov.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyberpunk.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dadons-laserdiscs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darkag.ovh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dequehablamos.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "discofitta.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dragonisles.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eligible.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "endzeit-architekten.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "englishclub.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "esclear.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fearsomegaming.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "firevap.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gintenreiter-photography.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "graphire.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grossmann.gr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gurochan.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hastherebeenamassshooting.today", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hd-offensive.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "heartsucker.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "helloanselm.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hiphop.ren", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hmm.nyc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "homecareassociatespa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "i95.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iamokay.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "infilock.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iseulde.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jikken.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klauwd.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kle.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kleteckova.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "korobkovsky.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "krypteia.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kybi.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "levert.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "libreboot.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linuxlounge.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "litvideoserver.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liud.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lugbb.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mailer-dot.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "make-pizza.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mammothmail.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mammothmail.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mammothmail.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maowtm.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mbweir.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mfiles.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mintrak2.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mobiletraff.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moneromerchant.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "monitzer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mygreatjobs.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nearby.in.th", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netsystems.pro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neuralgic.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nolberg.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onefour.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "openxmpp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "optenhoefel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orf-digitalsatkarte.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orf-kartentausch.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oversight.garden", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plfgr.eu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "politic.org.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "potlytics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ppy3.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prelist.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ptbx.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "purplebricks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qtxh.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quchao.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "raidstone.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "raidstone.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rawoil.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "realgarant-shop.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "remodela.com.ve", "include_subdomains": true, "mode": "force-https" },
+ { "name": "restchart.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "richmondsunlight.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rightcapital.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rolemaster.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "room208.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ruanmi.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rushball.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saikarra.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sailormoonevents.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saltstack.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "samkelleher.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scicasts.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seatbeltpledge.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shv25.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "societyhilldance.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stmbgr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "streams.dyndns.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "syncserve.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomatenaufdenaugen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vitkausk.as", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wander.al", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wapjt.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webdevops.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weirdesigns.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "winpack.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "winpack.eu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wittcher.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wscales.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wss.com.ve", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wsscompany.com.ve", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ycc.wtf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yuan.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zefu.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zonglovani.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zooom.azurewebsites.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zscales.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zzw.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0p.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adams.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "akaoma.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anderslind.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aspargesgaarden.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "catnet.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chiru.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "consul.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dealpass.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "driving-lessons.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elbetech.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ernesto.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "esquonic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "falkp.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "firstchoicecandy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "furry.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gautvedt.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gorilla-gym.site", "include_subdomains": true, "mode": "force-https" },
+ { "name": "graph.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gravitation.pro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grsecurity.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hashiconf.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hashicorp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "healthiercompany.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "heyguevara.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hostgarou.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jobbkk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kakao-karten.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kitakemon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kradalby.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leinir.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lepont.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "luom.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lyx.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martinp.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "minpingvin.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mt.me.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nomadproject.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ntppool.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "omniti.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "open-bs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ottoproject.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "packer.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "perfect.in.th", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ploxel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "postal.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "puryearlaw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pwnies.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "revolt.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ruborr.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sbssoft.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schrodinger.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "serfdom.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seryo.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skou.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spillmaker.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sscd.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "terraform.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tinylan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tnes.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "travisf.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tresorsecurity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "urphp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "v0tti.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vagrantup.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vaultproject.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wegner.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wilddog.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wlzhiyin.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "womf.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wondermags.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xiaofengsky.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zqhong.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bmoattachments.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dorianharmans.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inverselink-user-content.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inverselink.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jhburton.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0knowledge.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0x52.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0x90.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0xee.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0xf00.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1011100.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1464424382.rsc.cdn77.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1972969867.rsc.cdn77.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1whw.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "2brokegirls.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "2gen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "808.lv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "911911.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "99511.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abcheck.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abilymp06.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abury.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "acabadosboston.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "actserv.co.ke", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adblockextreme.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adboos.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adopteunsiteflash.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "advancedseotool.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aether.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "afuh.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agalaxyfarfaraway.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agbremen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agevio.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aiesecarad.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aivd.lol", "include_subdomains": true, "mode": "force-https" },
+ { "name": "akhras.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "albertopimienta.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "albion2.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alecpap.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alessandro.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexhaydock.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexhd.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexismeza.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexn.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "allbenjoy.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "almeria.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "am3.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amavis.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ambiente.one", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anarchistischegroepnijmegen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ancientkarma.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andreaboero.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andrewmichaud.beer", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andrewmichaud.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "animalnet.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anitaalbersen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "annuaire-photographe.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anonboards.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anthenor.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "antimine.kr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anyprime.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aopedeure.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aperturesciencelabs.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "apolloyl.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "appart.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "approbo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aprsdroid.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aradulconteaza.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arboworks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arbu.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "argh.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arima.co.ke", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aristocrates.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "armingrodon.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "articaexports.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arzaroth.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "asasuou.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "asc16.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aserver.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "askmagicconch.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atbeckett.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "attimidesigns.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aucubin.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "auverbox.ovh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "axrec.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "baalsworld.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "backscattering.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "badhusky.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "baer.one", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bah.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "baiker.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ballotapi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bananium.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "barbaros.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "barbu.family", "include_subdomains": true, "mode": "force-https" },
+ { "name": "barrut.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bartel.ws", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bartlamboo.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bashcode.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "basnieuwenhuizen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beanjuice.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beardydave.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beframed.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beinad.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "believablebook.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bely-mishka.by", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bendemaree.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bendingtheending.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "benk.press", "include_subdomains": true, "mode": "force-https" },
+ { "name": "benno.frl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "benschnarr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "berr.yt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "betaclean.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "betulashop.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bezorg.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bieberium.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bikiniseli.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bildschirmflackern.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "billaud.eu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biosphere.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "birdfeeder.online", "include_subdomains": true, "mode": "force-https" },
+ { "name": "birminghamsunset.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitcoin.asia", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitcoin.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitcoin.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitcoin.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitcoin.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitcoin.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitcoinbitcoin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitcoinprivacy.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blackphoenix.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blastersklan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blue42.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bluescloud.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blurringexistence.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bluserv.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bnhlibrary.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bokeyy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bookofraonlinecasinos.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bootjp.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bouncourseplanner.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "br3in.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bradbrockmeyer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bran.land", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bratteng.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bregnedalsystems.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brickoo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bridholm.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bronevichok.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brunoramos.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brunoramos.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bsalyzer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bsdtips.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bsquared.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buck.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "budskap.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buettgens.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bugtrack.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bund-von-theramore.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buri.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "businessfurs.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buyinginvestmentproperty.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bypro.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "c.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "c3b.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cabsites.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cacaolalina.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "calebmorris.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "calgoty.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "calibso.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "camconn.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "canarymod.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "candratech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "capper.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "captchatheprize.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carnaticalifornia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carnildo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "casinostest.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "catsmagic.pp.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cavedroid.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ccja.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cejhon.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "celti.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cerastar.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chaos.fail", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chatear.social", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chaz6.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chejianer.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chenapartment.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chireiden.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chocotough.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "christiaandruif.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cintdirect.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cirrus0.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ciscommerce.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clarkeaward.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "classicday.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cldly.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clearkonjac.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clsimplex.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clywedogmaths.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cocaine.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cocker.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codeforce.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codelayer.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codewild.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "collies.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "com.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "comhack.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "comicspines.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "compeuphoria.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "compiledworks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "completionist.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "consciousbrand.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "core4system.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cornercircle.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coughlan.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cozmaadrian.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "craftinginredlipstick.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cravelyrics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "critical.today", "include_subdomains": true, "mode": "force-https" },
+ { "name": "criticalaim.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cryptoisnotacrime.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "csapak.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "csokolade.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cssu.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cthomas.work", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cubeserver.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cubua.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cuibonobo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cuisinezest.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "curlyroots.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "custe.rs", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyberianhusky.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "daduke.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dalingk.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dallmeier.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danaketh.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danielcowie.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danieldk.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danielverlaan.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dankim.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darkhole.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darkside.re", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darksideof.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darwinkel.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "davidandersson.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "davidreinhardt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dc585.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ddhosted.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dedicatutiempo.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dedmorozrzn.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "degeberg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deinballon.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dementiapraecox.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "demomanca.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "denniskoot.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dennogumi.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dersoundhunter.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "derwolfe.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "detoxsinutritie.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deuxsolutions.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "developfx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "devopsconnected.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dhuy.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diegerbers.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dighans.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digitalnonplus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dipconsultants.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "disconformity.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "disinclined.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dj4et.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dkds.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dlemper.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "doesmycodehavebugs.today", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dokuboard.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "domhaase.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "donzelot.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dotbox.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "doublefun.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dovecotadmin.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "downsouthweddings.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drahcro.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drdevil.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "driesjtuver.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drivenes.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drugagodba.si", "include_subdomains": true, "mode": "force-https" },
+ { "name": "duesee.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dumino.bg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "duria.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dutchwanderers.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dvbris.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dvbris.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dvorupotocnych.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "easez.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eatlowcarb.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eb7.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "echopaper.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "echosystem.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ecogen.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ecogen.net.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eduif.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "edxg.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "einsatzstellenverwaltung.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "electricant.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elektropost.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "element-43.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elite12.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elliriehl.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elnan.do", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emilyhorsman.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eminovic.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emnitech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "encredible.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "encredible.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "end.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "endlessdark.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enterprisey.enterprises", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eoldb.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "epicwalnutcreek.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "epublibre.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eq8.net.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "equate.net.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "equatetechnologies.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eressea.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erpcargo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ersindemirtas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "esko.bar", "include_subdomains": true, "mode": "force-https" },
+ { "name": "esocweb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ethanfaust.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ethlan.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eulerpi.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "euph.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "everwaking.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evilized.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evossd.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eytosh.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "f00.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fabienbaker.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fableforge.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "faeriecakes.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "failproof.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "familjenfrodlund.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fashioncare.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fastopen.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fatox.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fdj.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fecik.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "feel.aero", "include_subdomains": true, "mode": "force-https" },
+ { "name": "feirlane.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "feliwyn.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fenno.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fenteo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "feragon.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fhdhelp.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fhdhilft.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fierman.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "figuurzagers.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fiksel.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fikt.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "finfev.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "firebird.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fireorbit.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fischers.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fizz.buzz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flamingkeys.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fless.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flocktofedora.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "floridafieros.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flouartistique.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "folv.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frack.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "francevpn.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frangor.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freqlabs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fridolinka.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frippz.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fritzrepair.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frly.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frogatto.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frontmin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fumo.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "funderburg.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "furry.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "futuretechnologi.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gaichon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gam3rs.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamecollector.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamegix.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gameink.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamesurferapp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamishou.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gampenhof.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "garagegoossens.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "generic.cx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "genossen.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "genuu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geraintwhite.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gereon.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gesiwista.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gethttpsforfree.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getinternet.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getmassage.com.ng", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getremembrall.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gfm.tech", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gigacog.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gijsbertus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gjspunk.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "glentakahashi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "go.ax", "include_subdomains": true, "mode": "force-https" },
+ { "name": "go2sh.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "goalsetup.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gofigure.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gorschenin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gps.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gravitechthai.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gravito.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "greedbutt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "greenpeace.berlin", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gresak.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "griesser2.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grog.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gropp.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "groth.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "groth.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guillaumeperrin.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guntbert.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guvernalternativa.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gwtest.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hackenkunjeleren.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hackernet.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hackerpoints.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hackest.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hadleighswimmingclub.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hadzic.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haitschi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haitschi.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haitschi.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haitschi.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hallmarkestates.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haman.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hardeman.nu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hardline.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "harmonycosmetic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "has.vision", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hazcod.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hbpowell.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hcie.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hdeaves.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "heathmanners.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hec.global", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hejahanif.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "henok.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hhhdb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hhmmmm.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hiisukun.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hiphopconvention.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hittipps.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hmsseahawk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hodne.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hondart.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "honoo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hopps.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hostelite.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hostingfj.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hrobert.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hscorp.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hupp.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "husky.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huskybutt.dog", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huskyinc.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hydra.ws", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iactu.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iamveto.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "icebat.dyndns.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ictinforensics.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "idiopolis.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ies.id.lv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ifconfig.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iflare.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "igforums.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "igrivi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iirii.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iklive.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ilona.graphics", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iluvscotland.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "immaterium.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "indievelopment.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "informatik.zone", "include_subdomains": true, "mode": "force-https" },
+ { "name": "infosenior.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inios.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "insane.zone", "include_subdomains": true, "mode": "force-https" },
+ { "name": "interference.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "internetcasinos.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inton.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "investorforms.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inwestcorp.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iodu.re", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ipconsulting.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "irazimina.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iridiumflare.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iskaron.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "isreedyintheuk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "issuesofconcern.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itludens.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itsatrap.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iwalton.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iwizerunek.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jackdelik.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jahofmann.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "james.je", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jamesbradach.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jamesdoell.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jamiemagee.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jamon.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "janario.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jaqen.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jarsater.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jasonamorrow.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jastoria.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jazzanet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jazzncheese.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jbbd.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jbradaric.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jctf.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jdubya.info", "include_subdomains": true, "mode": "force-https" },
+ { "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" },
+ { "name": "jkirsche.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jkrippen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "joakimalgroy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "joepitt.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "johannes.wtf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "johnrom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "johnverkerk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jonasgroth.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jonn.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jopsens.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "josip.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jrgold.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jstore.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jugendsuenden.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jultube.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jump.wtf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "junaos.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "junkdrome.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jupp0r.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kalami.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kamixa.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kanehusky.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kantankye.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kapucini.si", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kaputt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "karguine.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "katericke.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "katyl.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kausch.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kdata.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ke7tlf.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keaysmillwork.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kekku.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kermadec.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ketosecology.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kevinapease.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kevinbusse.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kirara.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kirschbaum.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kirstin-peters.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kisalt.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kitchenpunx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klausimas.lt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kleinblogje.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "knapen.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kolaykaydet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "konata.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "koopjesnel.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "koot.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kraiwan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kraiwon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kream.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kriegskindernothilfe.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kristikala.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kroetenfuchs.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "krupa.net.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kuwago.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "labordata.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "labs.moscow", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lacledeslan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lacledeslan.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laglab.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lambdafive.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lamboo.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laminine.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "langendries.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "langhun.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "larsklene.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lavine.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lbayer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lenn1.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leolana.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lerner.moscow", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lerp.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lgts.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lhalbert.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lightpaste.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lindberg.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "link.ba", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linzgau.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "litchidova.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lithesalar.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "little.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liveforspeed.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "livnev.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "loafbox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "localchum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "logicsale.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "logicsale.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "logicsale.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "logicsale.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "loginseite.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "loli.bz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lonal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "loopstart.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lpm-uk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lubot.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lucielavickova.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lunarift.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "luther.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "luukklene.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lv0.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lzzr.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "macchaberrycream.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maddin.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maelstrom.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mahefa.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "malfait.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "managemynetsuite.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "manowarus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marcelpreuss.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marcofinke.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marcohager.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marilsnijders.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "markaconnor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matrix.ac", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matt.tf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mattandyana.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matthiasschwab.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matty.digital", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matze.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maultrom.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mbinf.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mcatnnlo.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mcl.gg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meadowviewfarms.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "medusa.wtf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meghudson.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meifrench.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "merccorp.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mereckas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "merson.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "metapeen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "metin2blog.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "michaelfitzpatrickruth.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "michasfahrschule.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "miconware.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "midwestwomenworkers.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mikepair.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mikewillia.ms", "include_subdomains": true, "mode": "force-https" },
+ { "name": "milonga.tips", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mirodasilva.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mjec.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mmucha.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "modydev.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moen.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mojaknjiznica.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mokhtarmial.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moonraptor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moov.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "morbatex.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "morbitzer.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "morenci.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mornings.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "morpork.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "morteruelo.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mozoa.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mplusm.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mremallin.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mrettich.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "msiegmund.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mvanmarketing.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mwavuli.co.ke", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mycoted.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mygate.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mysoundtalks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mytty.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mytweeps.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mziulu.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "n0psled.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "naminam.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nathanmfarrugia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "navjobs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ncrmnt.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ne1home.dyndns.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neap.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nedraconsult.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nerdjokes.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nerdydev.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neris.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netherwind.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netsight.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nettools.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nex.sx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nexlab.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nextproject.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ngine.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nichthelfer.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nickloose.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nickrickard.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nicoknibbe.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nicolaeiotcu.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nightfirec.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nikomo.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nocs.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nohup.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nojestorget.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nolaviz.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nolte.work", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nomorebytes.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "noordsee.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nopol.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "norandom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "norb.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "notadd.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ntbs.pro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nuxer.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nvlop.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nyan.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "octav.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "octothorpe.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ollie.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "omgaanmetidealen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "omskit.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onaboat.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onewebdev.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onlinekasino.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onlinespielothek.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onthebriteside.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ookjesprookje.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "openpriv.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "opentrash.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "openverse.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orbitcom.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oricejoc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oshell.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "osticketawesome.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "othercode.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "othermedia.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "otherstuff.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "otrsdemo.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "overseamusic.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ozvolvo.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "p1984.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "p1c.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pagerate.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paginapolitica.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pahae.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pakke.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pamsoft.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paneu.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "papierniak.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paranoxer.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "partijtjevoordevrijheid.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "partyhaus.ovh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "passieposse.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pataua.kiwi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paulchen.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paulyang.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pekkapikkarainen.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pelanucto.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pengi.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pennergold.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "perlwork.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "persson.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "petabits.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pgregg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "philphonic.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phoebe.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phperformances.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "picardiascr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pickr.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pippen.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pitfire.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pittonpreschool.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pixelbash.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pkgt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "playmaker.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "po.gl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pocloud.homelinux.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "polynomapp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "postcodewise.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "postpi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "povitria.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "powerxequality.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "predoiu.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "premiumzweirad.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pridoc.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "progblog.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "progreso.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "promhadan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "proustmedia.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "puikheid.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pumpgames.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "puppydns.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pypt.lt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "q2.si", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qingpei.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qinxi1992.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qop.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qorm.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qtl.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quantoras.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "queercoders.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quranserver.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qvi.st", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qwilink.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "r10n.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "r15.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "raajheshkannaa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "radicaleducation.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ramatola.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rapenroer.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rauros.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "raydan.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rbensch.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rburchell.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reachr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reactivarte.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "readonly.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redmbk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rednsx.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "regionale.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "regiovertrieb.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "regmyr.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reisyukaku.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rejo.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "renemoser.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "renkenlaw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "revello.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rgavmf.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rhering.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "richardhering.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ringingliberty.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rix.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rkmantpur.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "robertkrueger.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "robigalia.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rodehutskors.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rodney.id.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "roelf.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rohedaten.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rokki.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rrke.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rsf.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rubberfurs.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rubenschulz.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rudeotter.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ruqu.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rutgerschimmel.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rwanderlust.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rxv.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saamhorigheidsfonds.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "samifar.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "samwu.tw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sanchez.adv.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sanglierhurlant.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sarakas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sash.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "satrent.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saturne.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sc4le.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scandicom.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schlabbi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schnouki.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schoepski.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schumanandmonnet.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schwinger.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scrion.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seattlefabrication.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "securiviera.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sehenderson.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "selcusters.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "self-injury.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "semyonov.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sendmeback.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "septakkordeon.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seq.tf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "serverco.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "servercode.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sgcaccounts.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sharepic.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shaunwheelhou.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shibe.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shiona.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shortr.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "showsonar.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sidnicio.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "silentlink.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "silentundo.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "silverdragonart.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "silverhome.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "silverwind.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simonwessel.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simpleai.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simplefraud.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sin30.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skilletfood.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skullhouse.nyc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sladic.si", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slaps.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slashdesign.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slashem.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sluitkampzeist.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slycurity.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smalldata.tech", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smartwurk.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snille.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snoozedds.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snowcrestdesign.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sobotkama.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sodi.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sofabedshop.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soju.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "solidus.systems", "include_subdomains": true, "mode": "force-https" },
+ { "name": "someshit.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soph.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sortaweird.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soundtalks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sourcelair.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sown.dyndns.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spacedust.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sparelib.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sparklebastard.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sparsa.army", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spicydog.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "squatldf.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "srna.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stalder.work", "include_subdomains": true, "mode": "force-https" },
+ { "name": "standingmist.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "starsam80.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stderr.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stefanovski.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sternplastic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stichtingsticky.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stoianlawfirm.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "storefrontify.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "strobeto.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "studenttravel.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "studyhub.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stuntmen.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "suave.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sudo.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "suian.or.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "superbabysitting.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "superbart.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "supermarx.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "suprlink.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "supweb.ovh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "surveypirate.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sushifrick.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "svallee.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "svenluijten.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swedishhost.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swedishhost.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "syam.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "synatra.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "synchrocube.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sysadmins.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "systemreboot.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "szaszm.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "szongott.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "t7e.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tahf.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tailpuff.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "takeshifujimoto.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tantalos.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tartaros.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "taskulu.ir", "include_subdomains": true, "mode": "force-https" },
+ { "name": "taxaroo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tazz.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tcomms.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "techcavern.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "techtalks.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tecture.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teemperor.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tehotuotanto.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "terrab.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "testbawks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tezcam.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "the-earth-yui.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thehonorguard.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theinvisibletrailer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "themerchandiser.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theodorejones.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "therockawaysny.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thescientists.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thesled.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thetradinghall.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thetuxkeeper.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thezero.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thibautcharles.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thijsalders.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thinkcoding.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thisisforager.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thisserver.dontexist.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thkb.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thrx.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tianshili.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tiendavertigo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tikutiku.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tinastahlschmidt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "titouan.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tlach.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "toccoig.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "todo.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomaspialek.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomrei.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tonage.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "toncusters.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "toomanypillows.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tooolroc.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "topmarine.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tosteberg.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "toucedo.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "toutart.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "townhousedevelopments.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trendkraft.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trik.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trollscave.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trustmeimfancy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tsumi.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tty.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tuvalie.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tuxcall.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ty2u.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uat-activesg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ukrgadget.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unexpected.nu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unpossible.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uns.vn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "urban.melbourne", "include_subdomains": true, "mode": "force-https" },
+ { "name": "urbanmelbourne.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usbcraft.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "valkohattu.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "valsk.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vangeluwedeberlaere.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vantru.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vespacascadia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vetinte.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vikings.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vincentkooijman.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vincentkooijman.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vleij.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vleij.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "voidi.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vop.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vpl.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vumetric.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vztekloun.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "warsentech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "warsh.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wasserspucker.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wassim.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webstory.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "welteneroberer.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weltengilde.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weltenhueter.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weltmeisterschaft.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "werkplaatsoost.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "werkruimtebottendaal.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wessner.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "westcountrystalking.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wetofu.top", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wetthost.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whatnext.limited", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whereisjason.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wifimask.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wiktoriaslife.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "withmy.beer", "include_subdomains": true, "mode": "force-https" },
+ { "name": "womosale.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "woutergeraedts.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wpmetadatastandardsproject.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wpostats.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wrgms.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wxster.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "x2w.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xandocs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xbt.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xerhost.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xiaoguo.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xichtsbuch.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xiyu.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xmppwocky.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xss.ht", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xwalck.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yakmade.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yakmoo.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yanaduday.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yanwh.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yaxim.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yhaupenthal.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ymarion.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yoramvandevelde.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yorname.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "youkok2.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "youtous.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ypiresia.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "z1h.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "z4k.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zakmccrac.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zcon.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zdbl.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zebrababy.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zehntner.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "znation.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zocken.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zwerimex.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "united.com", "include_subdomains": false, "mode": "force-https" },
+ { "name": "www.united.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mobile.united.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smartphone.continental.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0513c.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0x.cx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1022996493.rsc.cdn77.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "14it.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1stcapital.com.sg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "24ip.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "28spots.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "2or3.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "35792.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "365.or.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "4project.co.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "6660111.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "7sons.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "7thheavenrestaurant.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aaronkimmig.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abacustech.co.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abou.to", "include_subdomains": true, "mode": "force-https" },
+ { "name": "achromatisch.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adayinthelifeof.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "advancedstudio.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aikido-linz.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aikido-wels.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aleax.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alela.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexandre.sh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "allinnote.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "allthethings.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alphalabs.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "altfire.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amri.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anagra.ms", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andisadhdspot.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andrewmichaud.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andrewvoce.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andrewx.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "androoz.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andyuk.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anglictinatabor.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "angrapa.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aniplus.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anomaly.ws", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anyways.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ao2.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aposke.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "armor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arrmaforum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "art2web.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "artifex21.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "artifex21.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "artmoney.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "artspac.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arvamus.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "as200753.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "as200753.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "as9178.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "assekuranzjobs.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ath0.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "audisto.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ausnah.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "azzag.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "azzorti.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "b303.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "babybee.ie", "include_subdomains": true, "mode": "force-https" },
+ { "name": "backeby.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "barcoderealty.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "barrelhead.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bcheng.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bcnx.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bedrijvenadministratie.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beinad.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "belics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "berlinleaks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "betonmoney.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "betplanning.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bfear.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blackdesertsp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blha303.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blindsexdate.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blogreen.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blumiges-fischbachtal.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blupig.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blutroyal.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "borisbesemer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bramvanaken.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "branchzero.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brandred.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bureaubolster.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "busold.ws", "include_subdomains": true, "mode": "force-https" },
+ { "name": "butchersworkshop.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buybaby.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bwear4all.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bytesofcode.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "c1yd3i.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "caesarkabalan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cajunuk.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cambridgeanalytica.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "canadiangamblingchoice.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "canyoupwn.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carthage.edu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "catinmay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cerebelo.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chaulootz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chazay.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chrishamper.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "christophheich.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cigarblogs.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cimalando.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clanthor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clockcaster.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cloudapi.vc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cloudbolin.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cloudstrike.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clvrwebdesign.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cmsbattle.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "code.fm", "include_subdomains": true, "mode": "force-https" },
+ { "name": "code67.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codyevanscomputer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cogent.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coldawn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coldfff.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "comercialtrading.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "computeremergency.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "content-api-dev.azurewebsites.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "continuumgaming.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cool110.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coronelpicanha.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "creep.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crestasantos.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cruzr.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "customd.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cvr.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyberfrancais.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyberoptic.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cybersecuritychallenge.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cygnius.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "czlx.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "d-designerin.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dachb0den.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dakrib.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danieltollot.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danjesensky.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danrl.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darkkeepers.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darrenm.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dash.rocks", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dashboard.yt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "data.haus", "include_subdomains": true, "mode": "force-https" },
+ { "name": "davidmessenger.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "davidscherzer.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deanmorgan.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deepbluecrafting.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deight.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "devb.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dewalch.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dfranke.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diddens.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digitalriver.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "directme.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dittvertshus.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dizorg.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dn42.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "doeswindowssuckforeveryoneorjustme.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dominikkulaga.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dougferris.id.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drakeluce.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dramaticpeople.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "draw.uy", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drawesome.uy", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drobniuch.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dvwc.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ebpglobal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "echosixmonkey.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ecupcafe.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "edcphenix.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eelzak.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eery.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eidolonhost.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elars.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elearningpilot.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elemenx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elgosblanc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eligrey.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elsamakhin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "end.pp.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enteente.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enveloppenopmaat.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eopugetsound.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "epanurse.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erawanarifnugroho.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erotalia.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erp-band.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erp.band", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erpband.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "errolz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "estan.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "esteam.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "etha.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "euanbaines.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eulenleben.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "everylab.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ewie.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "expertmile.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ezrefurb.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fanvoice.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fawkex.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fierman.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fierman.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "finanzkontor.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "findyour.diet", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fionamcbride.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "firstderm.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flags.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flamme-von-anor.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fletchto99.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foodiebox.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "formazioneopen.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "formini.dz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fotowolfy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frankhaala.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freeboson.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freekdevries.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freezion.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freshdns.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frob.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fromscratch.rocks", "include_subdomains": true, "mode": "force-https" },
+ { "name": "g-marketing.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gabber.scot", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamajo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "game-files.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gancedo.com.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "garyjones.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gatilagata.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gaussorgues.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gechr.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "genehome.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "georgemaschke.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "georgemaschke.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "get-asterisk.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "get-erp.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geterp.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getlolaccount.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getts.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ggx.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gheorghesarcov.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gmoes.at", "include_subdomains": true, "mode": "force-https" },
+ { "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" },
+ { "name": "groovydisk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guffr.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gussi.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "h-jo.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haktec.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "happycoder.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "happytiger.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "happyukgo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hardertimes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hauntedfishtank.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haurumcraft.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hdwallpapers.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "head.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hemdal.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "henryphan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hexicurity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hogar123.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "holofono.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "homeseller.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "homeseller.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "housingstudents.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hovie.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hpisavageforum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hsir.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "icarlos.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "id0-rsa.pub", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ideal-envelopes.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "idolf.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ikwilguidobellen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "imim.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "in-depthoutdoors.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "infcof.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inflation.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "innovaptor.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "insite-feedback.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intel.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ip-life.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ircmett.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "isincheck.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "isletech.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ispire.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "its-gutachten.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "its4living.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iwannarefill.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jagido.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jamesmorrison.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "janokacer.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jaot.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jasonrobinson.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jasperhammink.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "javalestari.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jayschulman.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jayscoaching.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jcoscia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jensenbanden.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jetsetcharge.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jetsieswerda.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jettlarue.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jie.dance", "include_subdomains": true, "mode": "force-https" },
+ { "name": "joerss.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "johnhgaunt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "joostbovee.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "joostrijneveld.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "joworld.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jr5devdoug.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jr5devdouglas.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "juliamweber.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "justchunks.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jvoice.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kackscharf.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kaileymslusser.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kalender.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kamitech.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kana.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kapseli.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kawaiiku.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kawaiiku.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keops-spine.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keops-spine.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kerksanders.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kg-rating.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kilianvalkhof.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kissart.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kjaermaxi.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kleinerarchitekturfuehrer.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klicktojob.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kmartin.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kmkz.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kojima-life.co.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kolmann.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "krasota.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "krmela.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kumachan.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kumasanda.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kummerlaender.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lacasseroy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lalaya.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "land.nrw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "langatang.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "langenbach.rocks", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lapidge.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "largescaleforums.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lasercloud.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lask.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laxatus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leedev.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lega-dental.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lesperlesdunet.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "letustravel.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lewis.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lfullerdesign.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liaillustr.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "libbitcoin.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lillepuu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linmi.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linuxbabe.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liris-beautywelt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lntu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "localbandz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lokaal.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lolpatrol.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lrhstsa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "luchscheider.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lukas.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lumiere.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lunarshark.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lunix.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "madnetwork.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mailchuck.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mainlywrenches.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mall.hr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marikafranke.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martelange.ovh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martiert.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martineve.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "massdrop.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mattandreko.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matthewohare.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mattia98.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mavisang.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mawe.red", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mce55.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mdscomp.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meap.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mediastorm.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "melnikov.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mentax.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mesmoque.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "microvb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mijcorijneveld.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mintea-noua.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mitzpettel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mlemay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mlp.ee", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mobidea.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mobilpass.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moelord.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mommel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mommelonline.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "monix.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moonloupe.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "morganino.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "morningcalculation.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moy-gorod.od.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "msmails.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mvixturismo.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nabru.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nansay.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ncc60205.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "necormansir.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nemno.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nerd42.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nestedquotes.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "network23.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netzvieh.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neutralox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "newportpropertygroup.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ninchat.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nitho.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nobly.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nocit.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nodelia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "noop.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "noxlogic.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nsweb.solutions", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nutrienti.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nyyu.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "obsydian.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oceandns.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oceandns.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oceandns.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ocotg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oftn.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oiepoie.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "okhrana.agency", "include_subdomains": true, "mode": "force-https" },
+ { "name": "okok-rent.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "okok.rent", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ols.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onehourloan.sg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onepluscamps.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oneway.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onlinepollsph.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onqproductions.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "opensrd.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "opperwall.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "opus-codium.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orangutan-appeal.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oscsdp.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ostendorf.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "p3in.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pace.car", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pajuvuo.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "palatin.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pamplona.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "panaceallc.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "panmetro.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "panni.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pantou.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "papercard.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paradoxdesigns.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "parithy.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "payfreez.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pear2pear.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "peervpn.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pennyapp.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "perot.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "petchart.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "petja.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "petravdbos.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pgmsource.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "philadelphiadancefoundation.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pindanutjes.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pinoyonlinetv.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pipenny.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pir9.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "placefade.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "placehold.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "port80.hamburg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "power-of-interest.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pr2studio.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prekladysanca.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pridetechdesign.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "privatepokertour.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "protonmail.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "protonmail.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "psxtr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pucssa.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pupboss.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pygarage.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qikan.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qtpower.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qualityology.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quantumfurball.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "r40.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rainbowbarracuda.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "razlaw.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rbhighinc.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rcnitrotalk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reallifeforums.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "realmofespionage.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "recht-freundlich.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reddit2kindle.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rememberthemilk.com", "mode": "force-https" },
+ { "name": "www.rememberthemilk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "renderloop.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reprolife.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "richsiciliano.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ring0.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rms.sexy", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rop.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rossen.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rous.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rozalisbengal.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rubbereggs.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ruderverein-gelsenkirchen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ryanmcdonough.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "safejourney.education", "include_subdomains": true, "mode": "force-https" },
+ { "name": "safeme.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saleaks.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "salud.top", "include_subdomains": true, "mode": "force-https" },
+ { "name": "santing.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sarahbeckettharpist.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "savic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schmitz.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schneids.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schwarzwaldcon.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scottstorey.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scrapings.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "screencaster.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secandtech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secure-graphic.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sedoexpert.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sedoexperts.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sendc.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sendcat.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sephr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "serveroffline.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sessionslogning.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shanesage.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shiftins.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shulan.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "siciliadigitale.pro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "siddhant.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sideshowbarker.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sig6.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sigabrt.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "signere.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simbast.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sincron.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sinneserweiterung.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sisv.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sitehost.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sizingservers.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skatn.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skhoop.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skyoy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slauber.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sliceone.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smartofficesandsmarthomes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smet.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smirkingwhorefromhighgarden.pro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smoothics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snapworks.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "socialgrowing.cl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "socialhams.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soldecom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soumikghosh.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soundforsound.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sovereignshare.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "speedy.lt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sportwette.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spot-events.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spritchard.photos", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spuffin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spydersec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "srpdb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ssworld.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stadtbauwerk.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stationaryjourney.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stefanweiser.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stefany.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stigharder.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stn.me.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stnl.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "strobeltobias.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "studlan.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stumf.si", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stygium.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sudo.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sundayfundayjapan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swansdoor.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swiss-cyber-experts.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swmd5c.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swyn.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sxbk.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sylvan.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sysmike.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "systemintegra.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "t0dd.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tankski.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tappublisher.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "taranis.re", "include_subdomains": true, "mode": "force-https" },
+ { "name": "techmatehq.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "technoparcepsilon.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tellingua.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teodio.cl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "testandroid.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "testnode.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tf-network.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tfnapps.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thekelvinliu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "themeaudit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thenocman.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thepb.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thestory.ie", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theworldsend.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thezonders.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tmitchell.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tnrsca.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "todobazar.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomask.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomwiggers.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tonsit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tonsit.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "toptranslation.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "torahanytime.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "transitpoint.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "transverify.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "treeschat.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trimage.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "triple-mmm.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trzepak.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ts2.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ulmo.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "umidev.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "undernet.uy", "include_subdomains": true, "mode": "force-https" },
+ { "name": "upboard.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ur-lauber.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usakitchensandflooring.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usbtypeccompliant.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "val-sec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "valethound.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "valshamar.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vanderkley.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vanestack.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vattulainen.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vdcomp.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vegalitarian.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "versbeton.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "versicherungskontor.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vglimg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "viciousviscosity.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "videomuz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "villenvinkit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "visiontree-beta.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "visiontree.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vmem.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vogt.tech", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vonedelmann.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vvl.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wan.pp.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wangqiliang.xn--fiqs8s", "include_subdomains": true, "mode": "force-https" },
+ { "name": "warekon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "waterfedpole.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webelement.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weberjulia.com", "include_subdomains": true, "mode": "force-https" },
+ { "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" },
+ { "name": "winecodeavocado.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wittydonut.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "womb.city", "include_subdomains": true, "mode": "force-https" },
+ { "name": "woording.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wpac.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wphostingblog.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wql.zj.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xmr.to", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--3lqp21gwna.xn--fiqs8s", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--3lqt7ir4md4tzwa.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--3lqt7ir4md4tzwa.xn--fiqs8s", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--jobbrse-d1a.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--qckss0j.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xqin.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xuri.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yamamo10.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yatesun.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yjsw.sh.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yusa.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "z33.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zelfstandigemakelaars.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zerocool.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zhaofeng.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zima.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zoomingin.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zrn.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zulu7.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zvps.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "020wifi.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "0xa.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "21.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "2programmers.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "420dongstorm.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "4ourty2.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "888sport.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "960news.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aboutmyip.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agroline.by", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amazing-gaming.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andrewtebert.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arturkohut.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atg.soy", "include_subdomains": true, "mode": "force-https" },
+ { "name": "awg-mode.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "azuxul.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "babelfisch.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bankcardoffer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "barely.sexy", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bazarstupava.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "benni1.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bexit-hosting.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bexit-security.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bexit-security.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bexithosting.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bible.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bibleonline.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biguixhe.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "binaryabstraction.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blackhelicopters.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bobiji.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bondskampeerder.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brossman.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brunix.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "burzmali.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carey.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cervejista.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cfh.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ciubotaru.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cleaningsquad.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clubmate.rocks", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cnam.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codeplay.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codewiththepros.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "compalytics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coursera.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coverduck.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crendontech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cryptearth.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "daolerp.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datascience.cafe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dbx.ovh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deeprecce.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "denisjean.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "devstaff.gr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dick.red", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dinge.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "distinctivephotography.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dnscurve.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dogespeed.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dranek.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "duuu.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "earlybirdsnacks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eauclairecommerce.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eichornenterprises.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "einaros.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "electricant.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "empleostampico.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enteente.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enteente.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eskriett.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fakeletters.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "familie-sander.rocks", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fargtorget.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "farmacialaboratorio.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fierlafijn.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "finenet.com.tw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foodacademy.capetown", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fortnine.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "franta.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "franta.email", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gaiserik.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gilcloud.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "glittersjabloon.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gmw-hannover.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gonzalosanchez.mx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gripopgriep.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grizzlys.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "groseb.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guevener.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haku.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hashru.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "healthfoam.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "herrsmith.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "highvelocitydesign.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hikariempire.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hipstercat.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hirake55.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "holmesian.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hx53.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ianix.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "idoc24.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "idontplaydarts.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "imagefu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "imjiangtao.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inchomatic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intranetsec.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inzdr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "isogen5.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "istdieweltschonuntergegangen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itsadog.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itsecurityassurance.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jayshao.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jcaicedo.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jefftickle.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jodyboucher.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kakaravaara.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kantanmt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kesteren.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kesteren.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kjellvn.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kksg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kostya.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kunstundunrat.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kyanite.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laobox.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "learntube.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lemoine.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leonmahler.consulting", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leovanna.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lesdouceursdeliyana.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "logopoeia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lovelifelovelive.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lvrsystems.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mariaolesen.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "markrego.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "markri.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marsble.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martinkus.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matspar.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "michaeltroger.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "michalkral.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mikadoe.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "morz.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moviedollars.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mpetroff.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mtamaki.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "muriburi.land", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mybeautyjobs.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "n4l.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nathancheek.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neko-system.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nekosc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nerull7.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netulo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nilrem.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nnya.cat", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nottres.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ofcourselanguages.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "olmari.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "opentrack.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "opq.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "outetc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pbscreens.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pentagram.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "perdel.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "petsittersservices.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "poussinooz.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "procensus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "professionalboundaries.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "projectblackbook.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "r0t.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rapidthunder.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "raulfraile.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reader.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redicabo.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rezosup.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rezosup.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rheocube.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rhodri.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ride-up.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rijndael.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "robinwinslow.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "robohash.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rxprep.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sawamura-rental.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scriptict.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seanholcroft.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "setfix.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sexwork.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sftool.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shannoneichorn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shome.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sighup.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skanvordoff.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skills2services.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slamdjapan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smartairkey.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snl.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soleus.nu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sowncloud.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spielcasinos.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spiet.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "starpeak.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "studer.su", "include_subdomains": true, "mode": "force-https" },
+ { "name": "subbing.work", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sublevel.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "supereight.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "svarovani.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "talktome.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "talktwincities.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tartaneagle.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tcdw.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tenyx.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tescoirelandpayslips.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thelapine.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "themostexpensiveworkofart.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thetechnical.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thinkcoding.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thomasnet.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tictactux.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tiensnet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tigerchef.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "timetab.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tit.systems", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tombrossman.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tonymanning.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uerdingen.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "utumno.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "valtoaho.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vipnettikasinoklubi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webdesigneauclaire.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webnosql.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whoclicks.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whoisapi.online", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wipply.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wolfesden.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wxukang.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yagihiro.tech", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zenithmedia.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zhendingresources.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zmy.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "3s-hosting.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "7kovrikov.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adderall.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agwa.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alanlee.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alpha-force.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anoncom.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "antocom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atletika.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "auto-anleitung.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bakaweb.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bdikaros-network.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "breitbild-beamer.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bullbits.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cat-box.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cgtx.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chriskyrouac.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chuckame.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clawe.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clickforclever.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clickphish.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cmacacias.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cmlancy.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "comodo.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crimson.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "curveweb.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "debank.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dentistglasgow.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "denverprophit.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digitalehandtekeningen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "docid.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dotbigbang.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "edesseglabor.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "edp-collaborative.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emilong.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ensured.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ensured.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geekwu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "glasschmuck-millefiori.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "goge.site", "include_subdomains": true, "mode": "force-https" },
+ { "name": "graavaapi.elasticbeanstalk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gyz.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gz-architekten.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "httpsecurityreport.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ibron.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "icewoman.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ifxor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "innovaptor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "interlun.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jamesmilazzo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jmk.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jobmob.co.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "joretapo.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kamcvicit.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kintore.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lakhesis.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "langguth.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "latitude42technology.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linuxmonitoring.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mediawikicn.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mikeg.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nalao-company.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nodi.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "number.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pekoe.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "php-tuning.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prytkov.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qapital.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "s13d.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saorsat.ie", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sazuz.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scotbirchfield.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sectia22.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shiftplanning.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shinju.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ssbrm.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sslcertificaten.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sslcheck.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "strijkshop.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "synackr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "szagun.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "techassist.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tobiasofficial.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "traffixdevices.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trusteecar.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vjirovsky.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "windscribe.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wlaws.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xolphin.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zellari.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "123plons.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1cover.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1xcess.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "2carpros.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "3r.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "91tianmi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aaron-gustafson.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abilitynet.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abmgood.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aboutmyproperty.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "acheconcursos.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "acnpacific.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "acuve.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "addaxpetroleum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adigitali.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adquisitio.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adquisitio.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adquisitio.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adquisitio.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adquisitio.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aemoria.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aeon.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "affiliateroyale.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aficotroceni.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agenda-loto.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ahd.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "airsoft.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "akelius.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alastyr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aldes.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexandra-schulze.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "all-subtitles.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "all4os.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ama.ne.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amateri.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amerigroup.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anghami.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "animesfusion.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anook.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "apeasternpower.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "applez.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "attorney.org.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ausschreibungen-suedtirol.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "babysaying.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "baiyangliu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bankersonline.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "banqingdiao.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bbdos.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bcdonadio.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bedabox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "belcompany.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "benhartmann.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "benmatthews.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beryl.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "betcafearena.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "betpamm.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bevinsco.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beyondpricing.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bfi.wien", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bhuntr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bierbaumer.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "billin.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "billpro.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bilrom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bimbo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bimbobakeriesusa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biofam.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bip.gov.sa", "include_subdomains": true, "mode": "force-https" },
+ { "name": "birkman.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bismarck.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bit8.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitshaker.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bittersweetcandybowl.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blinkenlight.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blinkenlight.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bluechilli.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "boilesen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bookmein.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "boomerang.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brd.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bunsenlabs.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cabusar.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "caizx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "calix.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cando.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "capitalquadatv.org.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cardstream.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "celec.gob.ec", "include_subdomains": true, "mode": "force-https" },
+ { "name": "centennialrewards.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "centerpereezd.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "centillien.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "centralpoint.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "centralpoint.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "centralstatecu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "centrobill.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cerfrance.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ceu.edu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cgbilling.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chamilo.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chargejuice.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "charlierogers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "checkyourmath.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chepaofen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "christianbargon.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cienbeaute-lidl.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cigarterminal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cittadesign.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "citya.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clickenergy.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clockworksms.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cmscafe.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coffee-mamenoki.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coinessa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coloringnotebook.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "comfortticket.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "comparamejor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "compareandrecycle.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "comparetravelinsurance.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "compuscan.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "connectingconcepts.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "constructdigital.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "contarkos.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cookinglife.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cookmedical.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coryadum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "countybankdel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crazydomains.ae", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crazydomains.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crazydomains.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crazydomains.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crazyhotseeds.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "criena.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crowdsupply.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cryptobin.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cryptocon.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cryptolab.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cselzer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "csvape.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cutorrent.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dalfiume.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dargasia.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darkshop.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datacalle.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datacandy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datarank.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datewon.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datortipsen.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deer.team", "include_subdomains": true, "mode": "force-https" },
+ { "name": "detutorial.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "developmentaid.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digminecraft.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dijkmanmuziek.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diodeled.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "divegearexpress.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diybook.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diycc.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dndtools.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "donnons.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dpd.com.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drakefortreasurer.sexy", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dreamtechie.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dreizwosechs.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drumbe.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dunea.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dycontrol.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ebankcbt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ebp2p.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ecco-verde.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "edati.lv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "educationunlimited.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "educator-one.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eimacs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "einheizpreis.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ekzarta.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "electricianforum.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elenoon.ir", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elglobo.com.mx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emaily.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emilyshepherd.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "energiekeurplus.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "englishforums.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enviam.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ericdiao.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "escapees.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "estilos.com.pe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eternitylove.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "euroshop.or.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "everythingkitchens.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "expo-asia.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "extracobanks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "factuursturen.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "factuursturen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "faktura.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "familiegrottendieck.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fashion.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "feard.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fexco.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fillmysuitca.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "finalgear.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "firecore.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "firexarxa.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flaemig42.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flanco.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flexport.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fly.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fnb-griffinonline.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "forextimes.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "formationseeker.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fossewaygardencentre.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freelance.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freesitemapgenerator.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frezbo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fugle.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "functions-online.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "funnyang.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "funrun.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "g2a.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamoloco.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gcsepod.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gfhgiro.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gifzilla.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "glubbforum.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "godesigner.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "goerner.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "goldmark.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "graciousmay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "greatnet.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grunex.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grytics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gtlfsonlinepay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gunwatch.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "halo.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "harmoney.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "harrisonsdirect.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hashnode.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haxo.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hdfgroup.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hellenicaward.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "helpmebuild.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "highseer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.co.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.com.hk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.com.sg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "homehunting.pt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "homeyou.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hostedbgp.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hotelmap.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "htmlacademy.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "humpteedumptee.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huren.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "idlekernel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "igotoffer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ikeyless.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ilrg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "imedikament.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "imeds.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "immigrationdirect.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "imusic.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "indusfastremit-us.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "indusfastremit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "insighti.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "insighti.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "insighti.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iprice.co.id", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iprice.hk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iprice.my", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iprice.ph", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iprice.sg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iprice.vn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ipricethailand.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iprim.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "islandhosting.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iterror.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ivpn.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jabber.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jackf.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jamesburton.london", "include_subdomains": true, "mode": "force-https" },
+ { "name": "japaniac.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jelly.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jennybeaned.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jr5proxdoug.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "juhakoho.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kairion.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kaisers.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "karmaplatform.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "katekligys.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kefaloniatoday.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kenners.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kernl.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kerrfrequencycombs.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kgxtech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kornersafe.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "krachtinverbinding.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kriegt.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "krizek.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kubik-rubik.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kuponrazzi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kynastonwedding.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lacentral.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ldarby.me.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leatherfurnitureexpo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leopotamgroup.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "libscode.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lifeinitsownway.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linkenheil.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linkmaker.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linkonaut.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linpx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liquidcomm.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "loadingdeck.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "locomotive.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "loony.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lovemomiji.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lpak.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lufthansaexperts.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lynkos.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "m.nu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "madebymagnitude.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "madtec.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mail4you.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "malwaretips.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "manueli.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marbogardenlidkoping.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "masterhaus.bg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matthewprenger.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maxserver.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mbilker.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mcdonalds.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mealgoo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "memberpress.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mhertel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mhict.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "michel-wein.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mightysounds.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mikeybot.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "miku.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mitnetz-strom.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mmonit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mobal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "monobank.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "morganino.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moveek.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "movember.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mpac.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mtg-tutor.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mtnz.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "multibit.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mutuelle.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myclientsplus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myconan.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mysmelly.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myworkinfo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myzone.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nagelfam.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "namacindia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "natuurbehangnederland.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "navstevnik.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nct.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ndbt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netmagik.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neuwal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nfo.so", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nohats.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "northcutt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nos-medias.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "notjustbitchy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "novatrucking.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "novelfeed.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nshost.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "numberoneshoes.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nyiad.edu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nyip.edu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oaic.gov.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "olafnorge.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onmarketbookbuilds.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ono.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ononpay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oost.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "openvz.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "opium.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "optumrxhealthstore.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orcamoney.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orionfcu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orlives.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "osmosis.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "outdoorproducts.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "overthinkingit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oxynux.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pagewizz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "panamaequity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "parkingpoint.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "particonpsplus.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "passwordrevelator.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "payment-network.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "payoff.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paytm.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "payupay.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pcforum.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pedicureduiven.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pedroventura.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "penablog.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pensiunealido.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "peoplesbankal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pepperworldhotshop.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pethub.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pharmgkb.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "philadelphia.com.mx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "picoauto.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "picotech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "picscare.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pincha.com.tw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pinkcasino.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pisexy.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pixelminers.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plainjs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "planete-cocoon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plexusmd.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "politologos.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "polypet.com.sg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "posylka.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ppro.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prezola.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pro-link.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "projectarmy.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "punknews.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pvcvoordeel.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qewc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quera.ir", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quire.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "racius.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reezer.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "regenbogenwald.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "renrenche.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "retrofitlab.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rheuma-online.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rhymix.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "riaucybersolution.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rk6.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "roundtheme.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "royzez.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rtd.uk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "runtondev.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "safcstore.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sakaserver.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "salesmachine.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "salon.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sampoznay.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sandviks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sardegnatirocini.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sat4all.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schont.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schwarzkopfforyou.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "selectorders.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "serveradminz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shawnh.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shoplandia.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "siriuspup.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sitsy.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sixt.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sixt.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sixt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sixt.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sixt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skyway.capital", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slotboss.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smartsparrow.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smittix.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smove.sg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snelwerk.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snoqualmiefiber.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sofort.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sofortueberweisung.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sosaka.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soundgasm.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "souyidai.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spectrosoftware.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sperrstun.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spiegels.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stalker-shop.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stephanierxo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stocktrader.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stoffelen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stolina.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stormyyd.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "strom.family", "include_subdomains": true, "mode": "force-https" },
+ { "name": "studentskydenik.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sudo.ws", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sunbritetv.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "suneilpatel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "supcro.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "superbshare.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "supersalescontest.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "svijet-medija.hr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swimming.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swite.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "syncmylife.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "talentcast.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tasmansecurity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teachercreatedmaterials.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teamtouring.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "terrastaffinggroup.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "textburst.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "texter-linz.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thebikeinsurer.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thecandidforum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thedisc.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theinitium.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theseed.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theseletarmall.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thiswebhost.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thomasbreads.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thomashunter.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thomaskliszowski.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "threedpro.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tiendschuurstraat.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tiplanet.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tkarstens.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tmprod.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomeara.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "top-stage.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "toysperiod.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trabbel.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trackchair.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tradeacademy.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tradedesk.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "transformify.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trell.co.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trineco.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trineco.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tssouthernpower.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tuxz.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "u-blox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uangteman.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ui8.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "umassfive.coop", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unicef.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unicredit.ba", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unicredit.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unicreditbank.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unicreditbank.rs", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unicreditbank.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unseen.tw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unyq.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uplinklabs.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uptic.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "us-immigration.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uscitizenship.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usd.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "useresponse.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "userify.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usimmigration.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usitcolours.bg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usparklodging.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "validbrands.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "veggiesbourg.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "velasense.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "verifikatorindonesia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "versia.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "veryhax.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "viaprinto.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vide-greniers.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vinilosdecorativos.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vitta.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vivaldi.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vivatv.com.tw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vizeat.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vorodevops.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vpn.ht", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vulners.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wail.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "walkingforhealth.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weather-and-climate.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "web.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webtobesocial.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webzanem.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weekdone.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weekly-residence.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weisse-liste.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wellacapability.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "werally.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "westsuburbanbank.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wftda.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wideboxmacau.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wienholding.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wind.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "winshiplending.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wizzley.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wkv.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wnu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "word-grabber.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wunderkarten.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ximage.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xmerak.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xotika.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xtronics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yosemo.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yufan.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zadroweb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zberger.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zizoo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zju.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zjubtv.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zoe.vc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zoznamrealit.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "10seos.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "126ium.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "2e-systems.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "a2nutrition.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aanmpc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ac-town.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "active.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexmerkel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alphatrash.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ambiq.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arbitrarion.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "auth.adult", "include_subdomains": true, "mode": "force-https" },
+ { "name": "baby-click.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "barqo.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bayden.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bckp.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bespokestraps.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "betafive.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bildiri.ci", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bmone.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "boeddhashop.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bpadvisors.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bukkenfan.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bytesystems.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "campfourpaws.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chaoswebs.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chiphell.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chorpinkpoemps.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "christianliebel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cmlachapelle.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cmplainpalais.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "collinsartworks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "combatshield.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "compareinsurance.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crosssec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crypt.guru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cryptolab.pro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crystalclassics.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dairyshrine.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "data102.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "davevelopment.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dcpower.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "degroetenvanrosaline.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "donthedragonwilson.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dragonschool.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drkmtrx.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drpetervoigt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dsol.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "durys.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dynamicnet.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "easyplane.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enecoshop.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enefan.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "envelope.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "etula.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exeria.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exno.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "extranetpuc.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "finditez.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "formula.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fpy.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "froxlor.support", "include_subdomains": true, "mode": "force-https" },
+ { "name": "g5led.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gelog-software.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "generali-worldwide.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "golocal-media.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "governorhub.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grieg.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "griegfoundation.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "griegshipbrokers.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grimneko.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hackit.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hasinase.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hegen.com.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hele.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hennymerkel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "herbandpat.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "heyfringe.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hjw-kunstwerk.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hqhost.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hugocollignon.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "husakbau.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ibarf.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "identitytheft.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "idgsupply.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "immortals-co.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "incendiary-arts.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "injigo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intimtoy.com.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intramanager.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "irgit.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "isqrl.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itechgeek.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jaitnetworking.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jenjoit.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "karateka.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kindleworth.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kirkovsky.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "km-net.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "krisstarkey.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kroodle.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kwidz.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kwikmed.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lesharris.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lightspeed.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linkages.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "loveto.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ls-a.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "luis-checa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lyness.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ma2t.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maildragon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "majesnix.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mascosolutions.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mein-gesundheitsmanager.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mikaelemilsson.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mironized.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myshirtsize.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netvizura.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neueonlinecasino2016.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nkinka.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nottheonion.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "novafreixo.pt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oneb4nk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onvori.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onvori.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "panamateakforestry.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "papeda.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pauspam.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "petplus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pj83.duckdns.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plaettliaktion.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ploup.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "portalzine.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qiwi.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qwant.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rage4.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "regalpalms.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reox.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "romaimperator.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rubysecurity.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "runway2street.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "santanderideas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sapience.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sarisonproductions.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saunas.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scrayos.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "signtul.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sikatehtaat.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "socialnous.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "socioambiental.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "softwarebetrieb.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "somebodycares.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sp.rw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spiritbionic.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stanandjerre.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stay.black", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stjohnin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "storvann.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "storvann.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "structurally.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "takuto.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "taniesianie.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tarhauskielto.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tendertool.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theamateurs.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thierryhayoz.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomaw.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomudding.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "truserve.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trustedinnovators.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tsgoc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tuingereedschappen.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "typeonejoe.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vazue.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "veil-framework.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vemokin.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vfree.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vid-immobilien.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "w4a.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whysuck.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wirc.gr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xbind.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--jp-6l5cs1yf3ivjsglphyv.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yamadaya.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yourstrongbox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yutabon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zadieheimlich.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zoeller.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gendrin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webmail.xalqbank.az", "include_subdomains": true, "mode": "force-https" },
+ { "name": "winebid.com", "include_subdomains": true, "mode": "force-https" },
+
+ // Manual additions in Chrome 51 or later that do not belong in a
+ // special section above.
+ // START OF MANUAL ADDITIONS
+ { "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" },
+ { "name": "1001.best", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1018hosting.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "123test.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "12vpn.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "12vpnchina.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1750studios.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1cover.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1hourproofreading.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1q365a.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "1st-community.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "247healthshop.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "24ip.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "24ip.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "2kgwf.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "2nains.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "300m.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "321live.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "33drugstore.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "360ds.co.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "365beautyworld.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "365healthworld.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "404.sh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "4455software.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "4500.co.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "4679.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "4d2.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "4elements.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "4w-performers.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "4winds.pt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "50millionablaze.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "50plusnet.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "57aromas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "60ych.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "6120.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "646.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "69square.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "8t8.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "8thportsmouth.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "92url.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aa-tour.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aaeblog.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aapp.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aaronsilber.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aatf.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abareplace.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abc.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abearofsoap.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aberdeenjudo.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abilitylist.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "abthorpe.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "accelerole.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "accuenergy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "acheritage.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "acisonline.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "acritelli.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "acrylicwifi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "activateplay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "activeweb.top", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adamkaminski.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adamricheimer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adams.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adastra.re", "include_subdomains": true, "mode": "force-https" },
+ { "name": "addstar.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adelaides.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adiponectinsupplement.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adiponectinsupplement.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adme.co.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "admitcard.co.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adoal.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adquisitio.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adrenaline-gaming.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aduvi.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "advelty.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adventistdeploy.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adventureforest.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adzuna.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adzuna.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adzuna.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adzuna.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adzuna.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adzuna.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adzuna.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adzuna.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adzuna.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adzuna.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "adzuna.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "afb24.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aficionados.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "africatravel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "afvallendoeje.nu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agowa338.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agro-id.gov.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ahabingo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ahmad.works", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aia.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "airlinecheckins.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aisle3.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aiwdirect.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "akerek.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "akoww.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "akropolis-ravensburg.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "akstudentsfirst.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "akutun.cl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alariel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alasta.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alertwire.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexisabarca.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexmerkel.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexmerkel.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alexsergeyev.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alienstat.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alittlebitcheeky.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "all.tf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "allforyou.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alliedfrozenstorage.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "allmbw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "allstarswithus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "allthingssquared.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "almeria-si.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alnitech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alphabuild.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alt-three.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "alterbaum.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "altopia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amcvega.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amees.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "american-truck-simulator.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "american-truck-simulator.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "americanworkwear.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "americkykongres.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amilx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amilx.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amitube.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amnesy.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "amv-crm.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "analytic-s.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ananke.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anassiriphotography.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anastasiafond.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "and-stuff.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "and.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andreastoneman.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andrepicard.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andrewhowden.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andrewthelott.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "andsat.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "annarokina.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "annetta.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "anonukradio.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ant.land", "include_subdomains": true, "mode": "force-https" },
+ { "name": "antoine-roux.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "antoinedeschenes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "antoniorequena.com.ve", "include_subdomains": true, "mode": "force-https" },
+ { "name": "antscript.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "any.pm", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ao-dev.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "apervita.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "apexitsolutions.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "api-geek.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "apmg-certified.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "apmg-cyber.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "app-arena.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "appdrinks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "appleoosa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "applic8.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "appointed.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "appraisal-comps.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "appreciationkards.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "appsdash.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aprovpn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aquapoint.kiev.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aramido.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aran.me.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arbeitskreis-asyl-eningen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arlen.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arnesolutions.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arpa.ph", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arrowgrove.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ars.toscana.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "artetrama.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "artisanhd.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "artistnetwork.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arubasunsetbeach.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arvid.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "arw.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "as.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ascamso.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ascii.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "asdpress.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "asmui.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "astromelody.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "asurepay.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atchleyjazz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atchleyjazz.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atchleylab.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ateli.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "athensbusinessresources.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "audiovisualdevices.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "augias.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "augiero.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aujapan.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aussiehq.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "authoritynutrition.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "auto-serwis.zgorzelec.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "automacity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "autotsum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "autumnwindsagility.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "avenueeyecare.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "avg.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "avinet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "avmemo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "avmoo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "avsox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "avtovokzaly.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "awanderlustadventure.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "awxg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "axeny.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ayurveda101.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "azimut.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "aztrix.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "babacasino.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "babak.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "babyhouse.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "babystep.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "back-bone.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "backmountaingas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bacula.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bad.horse", "include_subdomains": true, "mode": "force-https" },
+ { "name": "baiduaccount.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bakabt.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bakkerdesignandbuild.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "baliyano.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bankofdenton.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "barisi.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bashc.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "basicsolutionsus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "baumstark.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bazdell.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bblovess.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bbuio.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bc-bd.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bcbsmagentprofile.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bcmlu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bcweightlifting.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beavers.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bebef.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beepan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beeznest.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "befundonline.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "behere.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "beikeil.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "belliash.eu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "belly-button-piercings.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bemyvictim.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "benjaminblack.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "benzkosmetik.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bermytraq.bm", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bestbrakes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bestessayhelp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bestlashesandbrows.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bestorangeseo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "betz.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bevinco2020.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bf.am", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bgcparkstad.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bgdaddy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bhtelecom.ba", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bible-maroc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biblerhymes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biblionaut.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bielsa.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bienenblog.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biergaizi.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "big-black.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bikermusic.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "billiger-mietwagen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "billogram.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "billpro.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bingofriends.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bingostars.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biodieseldata.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bioemsan.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "biolindo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitbeans.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitbr.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitcoin-india.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitf.ly", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitfehler.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitfinder.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitfuse.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitheus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bithosting.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitmoe.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitref.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitsafe.systems", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitskins.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bivsi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bl4ckb0x.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "black-armada.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "black-armada.com.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "black-armada.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blaudev.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blogarts.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blubberladen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blucas.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blue-labs.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blue-leaf81.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blueflare.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blueliv.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blueperil.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bluepoint.foundation", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bluepoint.institute", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blusmurf.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bngsecure.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "boensou.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "boernecancerfonden.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bonfi.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "boomersurf.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "boringsmith.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "botox.bz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bourse-aux-jouets.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bourse-puericulture.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bouwbedrijfpurmerend.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brandnewdays.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "breechdepot.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brejoc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brewtrackr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brianpcurran.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brideandgroomdirect.ie", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brightonbank.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brilliantdecisionmaking.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "britishscienceweek.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "britzer-toner.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "broken-oak.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "brunn.email", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bta.lv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "btcdlc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bubblegumblog.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buchheld.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "budgetthostels.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buffalodrinkinggame.beer", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buildbox.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "built.by", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bulletpoint.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bumarkamoda.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "busindre.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "businessesdirectory.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "buyfox.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "by4cqb.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "byte.wtf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "byteshark.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bytesund.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "byteturtle.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bziaks.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bztech.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "c3w.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cachethq.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cadao.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cajapopcorn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "calltrackingreports.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "camaya.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "campaign-ad.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "campbellsoftware.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "campbrainybunch.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "camperdays.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "campermanaustralia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "candicontrols.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "caphane.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "capogna.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "captivatedbytabrett.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "capturapp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "capturethepen.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "caputo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carano-service.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "caraudio69.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cardloan-manual.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "careerstuds.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carigami.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carlandfaith.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carlgo11.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carsten.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "carstenfeuls.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "casedi.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "casinolistings.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "casinoreal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "castlejackpot.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "catalyst-ecommerce.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "catgirl.pics", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cdndepo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cdnjs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cdreporting.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ced-services.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ceilingpac.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "celti.ie.eu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "centrepoint-community.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ceritamalam.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "certnazionale.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cfcproperties.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cfoitplaybook.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cg-systems.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cgan.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chabaudparfum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "championsofregnum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chaos-inc.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "charityclear.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "charmyadesara.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "charnleyhouse.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chartpen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chateau-belvoir.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chatme.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chatup.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chebedara.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cheetah85.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cherrywoodtech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chestnut.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chiaramail.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chihiro.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chikan-beacon.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "childcaresolutionscny.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chilihosting.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "china-line.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chinternet.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chirgui.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chotu.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chris-edwards.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chris-web.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chrisandsarahinasia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chrisfaber.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chrisfinazzo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "christadelphiananswers.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "christianhoffmann.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "christiesantiques.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "chua.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cipherboy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ciscohomeanalytics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "citizensbankal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cityoflaurel.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "classicshop.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clcleaningco.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clearc.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clearsettle-admin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clientsecure.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "climatestew.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clochix.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "close.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cloudey.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cloverleaf.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "clownish.co.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cloxy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cmahy.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cni-certing.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coachingconsultancy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coam.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cocolovesdaddy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codeferm.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codefoundry.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coderhangout.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codesport.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codeyellow.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coi-verify.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coinjar-sandbox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "colisfrais.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "collada.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "collectiblebeans.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "collegepulse.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coloradolottery.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "colorbrush.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "commerciallocker.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "commoncore4kids.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "compareandrecycle.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "compliance-systeme.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "complymd.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "condepenalba.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "confirm365.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "connected-verhuurservice.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "connectfss.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "connyduck.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "consciousbrand.org.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "consciousbranding.org.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "consciousbrands.net.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "consumer.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "contactbig.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "containerstatistics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "convocatoriafundacionpepsicomexico.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coolchevy.org.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cooxa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cordlessdog.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "corepartners.com.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "corpfin.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "correctpaardbatterijnietje.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "costreportdata.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coursdeprogrammation.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "covenantbank.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "covybrat.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "coweo.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cpuvinf.eu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cracking.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cranesafe.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crazycen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "creativeplayuk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "creditproautos.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crefelder.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crowd.supply", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crufad.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crushroom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "crypticshell.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cryptojar.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cryptonit.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cryptonym.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "csbs.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "csfm.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ct-status.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ctpe.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cultiv.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cupidmentor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "curacao-license.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyberguerrilla.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyberguerrilla.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyberhouse.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyberwire.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cybozu.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyclebeads.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyfly.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cymtech.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyph.audio", "include_subdomains": true, "mode": "force-https" },
+ { "name": "czechamlp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "d-20.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "d-training.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "daallexx.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dadtheimpaler.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dag-konsult.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dah5.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dailystormerpodcasts.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "damianuv-blog.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dammekens.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "damngoodpepper.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dancerdates.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danielworthy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danijobs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danilapisarev.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dannycrichton.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danscomp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "danseressen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darkspacelab.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darkwater.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dashnimorad.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "databutlr.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datajapan.co.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datenreiter.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datenreiter.gq", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datenreiter.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "datenreiter.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "david-corry.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "davidgouveia.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "davidhunter.scot", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dccoffeeproducts.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dckd.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dcmt.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dcurt.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dd.art.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ddos-mitigation.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ddos-mitigation.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deaktualisierung.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deathy.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deco.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "decor-d.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "decoratrix.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "decoyrouting.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dedelta.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deduijventil.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deetzen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "degeberg.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "delta-data.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deltanet-production.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "delvj.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "demotops.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "denimio.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dentallaborgeraeteservice.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dentystabirmingham.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "derbyshire-language-scheme.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "derchris.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "deregowski.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "desiccantpackets.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "designgears.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "designthinking.or.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "detest.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "devcu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "devilshakerz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "devincrow.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "devmsg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "devnull.team", "include_subdomains": true, "mode": "force-https" },
+ { "name": "devuan.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dfekt.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diarbag.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "diasdasemana.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dicionariofinanceiro.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dienstplan.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dierenkruiden.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dieti.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digidroom.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digital-coach.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digital-eastside.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digitallocker.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "digitalquery.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dipl.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "directebanking.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "discipul.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "disposable.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dissectcyber.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dixiediner.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dizihocasi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "djlive.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "djxmmx.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "djz4music.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dmeevalumate.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dmi.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dna.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dnc.org.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dnshallinta.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dnslog.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "doctor-locks.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "doctorfox.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "docufiel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dogbox.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dogfi.sh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "doku-gilde.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dolarcanadense.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dolphinswithlasers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "domadillo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "donotspellitgav.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dontcageus.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "doodledraw.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "doordecor.bg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "downloadsoftwaregratisan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dr2dr.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drainagebuizen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dranderle.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drawingcode.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dreamcreator108.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dreweryinc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drhopeson.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "driftdude.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drino.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "droidboss.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drrr.chat", "include_subdomains": true, "mode": "force-https" },
+ { "name": "drycreekphoto.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dsbrowser.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dshiv.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "duijf.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "duijfathome.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "duncancmt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "duo.money", "include_subdomains": true, "mode": "force-https" },
+ { "name": "durangoenergyllc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dutch1.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dutchweballiance.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dutyfreeonboard.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dworzak.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dxa.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "dzyabchenko.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "e-mak.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "e-teacher.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "e3amn2l.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "e3kids.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eagleridgecampground.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "earga.sm", "include_subdomains": true, "mode": "force-https" },
+ { "name": "easyconstat.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "easycosmetic.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eatery.co.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eatvisor.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ebcs-solutions.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ebecs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ebermannstadt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ecchidreams.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eckro.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ecorus.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "edelblack.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "edicct.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "edk.com.tr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "edmundcelis.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ego-world.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "egretail.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ehrlichesbier.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ehuber.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eicfood.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eickemeyer.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eirastudios.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ejeff.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ekbanden.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ekokontakt.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ekostecki.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "el-soul.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elanguest.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elanguest.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elanguest.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eligibleapi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elisabeth-kostecki.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elisabethkostecki.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ella-kwikmed.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eloge.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "elternforum-birmensdorf.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eluhome.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "em-biotek.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emailfuermich.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emeldi-commerce.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emielraaijmakers.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emjainteractive.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emprego.pt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "emrenovation.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enaim.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "encfs.win", "include_subdomains": true, "mode": "force-https" },
+ { "name": "encnet.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "encryptio.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enjoy-nepal.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enlightenedhr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enloestatebank.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "enscosupply.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "epaygateway.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "epicsecure.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "epicsoft.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "epostplus.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "equilibre-yoga-jennifer-will.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "equipsupply.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erepublik-deutschland.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ergorium.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ergorium.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ericwie.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ericyl.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erigrid.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "errlytics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erudikum.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "erwinwensveen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "escritoriodearte.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "esigmbh.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "esn-ypci.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "essentialoilsimports.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "esseriumani.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "essexcosmeticdentists.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "essexghosthunters.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "estaleiro.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "estebanborges.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "etdonline.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eteesheet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "etelej.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eth0.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ethicall.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ethosinfo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "etkaddict.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "etrker.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ets2mp.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "etula.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "etyd.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "euro.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evantage.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evantageglobal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evegalaxy.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eventaro.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "everling.lu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "everymove.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evi.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evin.ml", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evites.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "evowl.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exchangeworks.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exemples-de-stands.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exoscale.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exoticads.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "expressemotion.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "extremenetworking.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exy.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exyplis.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eyeglassuniverse.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eyeonid.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ez.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "f-be.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "faber.org.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "factorable.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "factys.do", "include_subdomains": true, "mode": "force-https" },
+ { "name": "factys.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fadilus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fail4free.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "faircom.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fairlyoddtreasures.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fakturi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "falkena.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "falsum.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "familie-kupschke.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "familie-monka.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fanjoe.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fanyl.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fanyue123.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "farhood.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fasset.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fatgeekflix.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fatwin.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fawong.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fcburk.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fdt.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fedux.com.ar", "include_subdomains": true, "mode": "force-https" },
+ { "name": "feedhq.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fernandes.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ferrugem.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "festrip.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "feuerwehr-oberkotzau.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fexmen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ffmradio.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ficus.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fid.to", "include_subdomains": true, "mode": "force-https" },
+ { "name": "filemeal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "filhodohomem.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "financieringsportaal.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fingent.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "finisron.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "firehost.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "firstmall.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fish2.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fit4medien.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fitbylo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fitiapp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fitnesswerk.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fitzsim.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fivestarsitters.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fixatom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fixhotsauce.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fixmycomputerdude.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flareon.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flawcheck.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flazznetworks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flexinvesting.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flipneus.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "floless.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "florence.uk.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "florent-tatard.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "florian-thie.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "floriankeller.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "flyaces.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fndout.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fnordserver.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fokkusu.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fondanastasia.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "font-converter.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foodievenues.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foraje-profesionale.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "forbook.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "forex-dan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fortesanshop.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fortworth.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fotm.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fotocerita.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fotopasja.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fotowettbewerb.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foxbnc.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foxdev.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foxley-farm.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foxley-seeds.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foxleyseeds.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "foxtrot.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fragnic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fraho.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "francescopalazzo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "franckgirard.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frank.fyi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fransallen.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frasys.cloud", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frasys.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frasys.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freeform4u.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freematthale.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freemedforms.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freesoftwaredriver.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freetsa.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freshfind.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frickelboxx.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frizo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fromlemaytoz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frontisme.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "froot.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "frugro.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fsbpaintrock.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fsbturton.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fsm2016.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ftc.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fundacionhijosdelsol.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fundays.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "funi4u.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "funkyweddingideas.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "furgo.love", "include_subdomains": true, "mode": "force-https" },
+ { "name": "futbol11.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fx-rk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fxp.co.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fyfywka.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fyn.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fysiohaenraets.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "g-o.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gafachi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gagniard.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gagor.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gakkainavi-epsilon.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gakkainavi-epsilon.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gakkainavi.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gakkainavi.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gakkainavi4.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gakkainavi4.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gakkainavi4.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "galactic-crew.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "game7.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamecave.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamedevelopers.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamepader.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamingmedia.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gamingreinvented.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ganhonet.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gar-nich.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "garantieabschluss.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "garedtech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gasbarkenora.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gatapro.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gateworld.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ge1.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gee.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geeq.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geli-graphics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gemeentemolenwaard.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "generationnext.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "genyhitch.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geolad.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "georgesonarthurs.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "georgmayer.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "geoscan.aero", "include_subdomains": true, "mode": "force-https" },
+ { "name": "germandarknes.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getcarefirst.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getcarina.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getkai.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getlifti.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getsensibill.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getsetupfile.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getwashdaddy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gflclan.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ghcif.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "giftgofers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "giftsn.com.sg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gig.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gigawa.lt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gingali.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gipsic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gistfy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "git.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "givemyanswer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gix.net.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gixtools.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gixtools.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gixtools.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gixtools.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gjcampbell.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gjung.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "glidingshop.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "glidingshop.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "glitchsys.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "globalgivingtime.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "globalmusic.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "globalsites.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gloomyvancouver.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "goerres2014.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gogetssl.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gogold-g.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gohon.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "goldpros.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "goldsecurity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "golf18network.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "goodmengroup.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gosccs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gosharewood.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gospelvestcination.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gotgenes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gotomi.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "govillemo.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gozel.com.tr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gprs.uk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gpstuner.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grademypc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gradienthosting.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "graycell.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gresb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gretchelizartistry.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "greysolutions.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gribani.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grieg-gaarden.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "grieglogistics.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "griegshipbrokers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "groovinads.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gtamodshop.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gtldna.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gts-schulsoftware.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guava.studio", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guerrilla.technology", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gugaltika-ipb.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gulenbase.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gunnaro.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guoqiang.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gurkan.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "guts.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gypsycatdreams.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gypthecat.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gz-benz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "gz-bmw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haarkliniek.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "habanaavenue.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hackerforever.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hackmd.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haeckl.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hahayidu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hamali.bg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hancc.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "handiworker.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hansen.hn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hansvaneijsden.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hanu.la", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haomwei.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "happyandrelaxeddogs.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "harabuhouse.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "harmoney.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "harrisonsand.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hartie95.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "harvestrenewal.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "harz.cloud", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hashimah.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hashworks.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haskovec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haveforeningen-enghaven.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "havellab.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hawksguild.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hd-gaming.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hdhoang.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "heartmdinstitute.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "heavensinferno.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hebikhiv.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hedgeschool.ie", "include_subdomains": true, "mode": "force-https" },
+ { "name": "heinpost.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hellersgas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hellotandem.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "helloworldhost.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hellscanyonraft.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hennadesigns.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hentschke-bau.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hentschke-invest.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "herbertmouwen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hermes-net.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "herr-webdesign.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "herrenfahrt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "heycms.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hibilog.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hicl.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hiddendepth.ie", "include_subdomains": true, "mode": "force-https" },
+ { "name": "higgstools.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "higp.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.cl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.co.kr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.com.ar", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.ee", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.ie", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.kz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.lu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.lv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.pt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hilti.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hippies.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hitoy.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hochzeit-dana-laurens.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hoffmeister.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "homedna.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "homeprivate.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "homewatt.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "honda-centrum.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "honeybeard.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "honeycome.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hooray.beer", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hopesb.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "horvathd.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hory.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hosiet.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hosmussynergie.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hostam.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hosteasy.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hosted-service.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hostinaus.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hostmijnpagina.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hotchoc.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hotel-pension-sonnalp.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hotting.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "houser.lu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "howbehealthy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hr-intranet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "http418.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huarongdao.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huersch.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hugosleep.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huiser.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "humeurs.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "huntshomeinspections.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hup.blue", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hurd.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hxying.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hydrocloud.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hydrozone.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hyk.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "i--b.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "i-partners.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iapws.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ib-wedler.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iba.community", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ibnuwebhost.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iceloch.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "icpc2016.in.th", "include_subdomains": true, "mode": "force-https" },
+ { "name": "icreative.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ict-concept.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ictual.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "idacmedia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ideasmeetingpoint.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "idedr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "idensys.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "idexxpublicationportal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "idgard.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ieeespmb.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ies-italia.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ifasec.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "igiftcards.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "igk.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ihrnationalrat.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ihuanmeng.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ikon.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ile-kalorii.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "im2net.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "imanolbarba.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "imjad.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "immobilier-nice.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "immoprotect.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "immunicity.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "imolug.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "imperialwebsolutions.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "imu.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "in-flames.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inbox-group.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inbox.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inche-ali.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "indoorskiassen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "indredouglas.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "indusfastremit-ca.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "industreiler.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "informatiebeveiliging.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "infosec.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "infotics.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "infra-con.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inkable.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inkstory.gr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "insightera.co.th", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inspire-av.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "inspy.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "instantdev.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intelldynamics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intermedinet.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "internect.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "internetzentrale.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "internl.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "interociter-enterprises.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "interways.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intimateperrierjouet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intocities.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intramanager.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "intrasoft.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "invoicefinance.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iolife.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iompost.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iomstamps.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ionc.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ionx.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iossifovlab.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iotsms.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ip6.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ipal.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ipal.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iplabs.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ipmotion.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iptel.by", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ireef.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "isbengrumpy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ischool.co.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iseek.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "israkurort.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "istanbultravelguide.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "istheapplestoredown.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "it-go.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itb-online.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itforge.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itnota.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itos.asia", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itos.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "its-v.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "itsecguy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iwilcox.me.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "izolight.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "izoox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "izzzorgconcerten.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ja-publications.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jaclynjohnson.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jaispirit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jaketremper.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jakubtopic.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jamessan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jan27.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "janbrodda.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "janosh.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "japan-foods.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "japan4you.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "japlex.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jaredeberle.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jaredfernandez.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jartza.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "javelinsms.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jaymecd.rocks", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jazz-alliance.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jazz-alliance.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jazzinutrecht.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jcch.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jcyz.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jdh8.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jeff.forsale", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jekkt.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jennifersauer.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jensrex.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jeremye77.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jerodslay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jeroendeneef.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jessicabenedictus.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jesters-court.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jetwhiz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jfmel.com", "include_subdomains": true, "mode": "force-https" },
+ { "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" },
+ { "name": "jornadasciberdefensa2016.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "josahrens.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "joyqi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "js-online.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jsanders.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jsg-technologies.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "json-viewer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jthackery.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jualssh.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "julibear.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "julido.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "juliemaurel.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jumba.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jumbox.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jump.bg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "junge-selbsthilfe.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jungesforumkonstanz.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "junjung.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "justnaw.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "justudin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "juwairen.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jym.fit", "include_subdomains": true, "mode": "force-https" },
+ { "name": "jznet.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "k-tube.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kaangenc.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kaasbijwijn.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kabuabc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kadioglumakina.com.tr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kainz.bayern", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kainz.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kaizeronion.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kall.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kangarooislandholidayaccommodation.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "karateka.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "karsofsystems.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "karting34.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kashdash.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "katiaetdavid.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "katnunn.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "katproxy.site", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kavik.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kb3.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keeweb.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keisaku.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kekz.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kempkens.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kendra.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kenkoelectric.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kentacademiestrust.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kerangalam.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keybored.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kgm-irm.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kickerplaza.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kid-dachau.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kidbacker.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kiel-media.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kienlen.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kilerd.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "killerrobots.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kimberg.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kiocloud.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kionetworks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kirbear.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kirinas.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kis-toitoidixi.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kisstyle.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kita.id", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kitabgaul.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kittmedia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kizil.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kk-neudorf-duissern.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klas.or.id", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kleertjesvoordelig.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kleine-dingen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klimat-pro.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klunkergarten.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "klustekeningen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "knccloud.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kngk-group.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kngk.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "knot-store.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kodakit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "koerper-wie-seele.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "koezmangal.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "koi-sama.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "koketteriet.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kollabria.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "komget.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "komikito.com", "include_subdomains": true, "mode": "force-https" },
+ { "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" },
+ { "name": "kreationnext.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kromonos.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "krunut.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ksfh-mail.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kstan.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kucom.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kuehnel.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kueulangtahunanak.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kulde.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kupelne-ptacek.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kurofuku.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kurz.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kvalita-1a.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kylelaker.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kyosaku.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "l-lab.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laboiteapc.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lagalerievirtuelle.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lampl.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lan2k.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lanbyte.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "langbein.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lansinoh.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laposte.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lasnaves.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "latinphone.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lauftreff-himmelgeist.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laurel4th.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lbrt.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lcti.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ld-begunjscica.si", "include_subdomains": true, "mode": "force-https" },
+ { "name": "le-dev.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "le-hosting.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leadingsalons.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leandre.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "learnflakes.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "learnfrenchfluently.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "learningorder.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lechiennoir.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leesilvey.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "legarage.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leilonorte.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leitner.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leiyun.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lengzzz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lenovogaming.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leonard.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leopold.email", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leopoldina.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lesnet.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "letsmultiplayerplay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "letstox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lgiswa.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lgrs.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "libertas-tech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liderwalut.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lifeskillsdirect.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lifestylehunter.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lifetimemoneymachine.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lifi.digital", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lifi.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "likeaross.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lingros-test.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lingvo-svoboda.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "link2serve.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linno.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linuxeyecandy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linuxhostsupport.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "linuxwebservertips.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lislan.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "litevault.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liudon.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liverpoolmutualhomes.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lkummer.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "llamacuba.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lm-pumpen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "loadso.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "localbitcoins.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "logario.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "london-transfers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "londonlanguageexchange.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "longboarding-ulm.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "loophost.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lordjevington.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lost.host", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lotsencafe.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "louiewatch.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "love-schna.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lover-bg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lowmagnitude.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lowsidetna.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lpbk-bethel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lucaterzini.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lucidframeworks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "luke.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lukeng.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lukeng.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lungdoc.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "luno.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "luoxiao.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lustrum.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lwl.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lynero.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lynthium.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "m-edmondson.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "macaque.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "machon.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "macnemo.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maddi.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "madebyshore.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "madin.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "madreacqua.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mafiasi.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "magenx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mahrer.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mailfence.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mailhost.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mainlined.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "malerversand.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "malware.watch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mamaxi.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "manaboutahor.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "management-ethics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "managewp.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "manhattanchoralensemble.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "manningbrothers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maosensanguentadasdejesus.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marcel-preuss.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marchagen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marcontrol.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marie-elisabeth.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marinelausa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mark-a-hydrant.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marketingdesignu.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "markido.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "markt-heiligenstadt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marleyresort.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "marquiseclub.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martensmxservice.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martialc.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martin-smith.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "martinkup.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "masse.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matchneedle.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mathembedded.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "matthiasadler.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mauriciog.com.ar", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mauricioghiorzi.com.ar", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mausi.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maxbytes.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maxima.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maximiliankrieg.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maxr1998.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "maxtruxa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mbaestlein.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mbinformatik.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mbsec.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mc81.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mcdonaldwhsl.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mce.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mce.nyc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mceconferencecentre.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mcooperlaw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mdewendt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mdkr.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mdpraha.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mdwftw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mea.in.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mechanus.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "medba.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mediaburst.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mediaselection.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "medm-test.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meedoenzaanstad.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meetingmanager.ovh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "megakiste.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mehrwert.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meillard-auto-ecole.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mein-webportal.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meincenter-meinemeinung.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meine-email-im.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "melearning.university", "include_subdomains": true, "mode": "force-https" },
+ { "name": "melissaadkins.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "melody-lyrics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "melvinlow.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mensagemdaluz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "menthix.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "menudrivetest.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "menuonlineordering.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "merkel.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "metaether.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meteorapp.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "metzgerei-birkenhof.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meuemail.pro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "meyeraviation.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mghiorzi.com.ar", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mhdsyarif.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mheistermann.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "microdots.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "midair.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "midirs.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "midlgx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mijnreisoverzicht.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mijntransacties.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mikadesign.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mikeburns.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mil0.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "milatrans.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "millenniumweb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mindbodycontinuum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "miniskipper.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "minobar.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mipiaci.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mipiaci.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mireservaonline.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "misakiya.co.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "missrain.tw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mitnetz-gas.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mixposure.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "miyoshi-kikaku.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mizi.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mjcaffarattilaw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mkes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mkp-deutschland.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mktemp.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mm13.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mma-acareporting.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mmgazhomeloans.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mmmm.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mobility-events.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "modifiedmind.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moebel-nagel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moegirl.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mogry.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mona.lu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "monasterialis.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mondar.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mondopoint.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moneygo.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "monkeydust.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "montanacures.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "montenero.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moo.la", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moonagic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moonvpn.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mostwuat.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "motherbase.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "motionfreight.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "motoryz.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mountainadventureseminars.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "moviesabout.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "movinglogistics.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mpcompliance.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mplant.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mpserver12.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mpsgarage.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mrnonz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mrpopat.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "msno.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mtcgf.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mtg-esport.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mtn.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mumei.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "murfy.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "murodese.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "murrayrun.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "muzykaprzeszladoplay.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mx.org.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "my-owncloud.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myairshop.gr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mybon.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mycollab.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mydnaresults.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mydocserve.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myip.tech", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myownconference.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myownconference.com.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myownconference.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myownconference.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myownconference.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myownconference.lt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myownconference.lv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myownconference.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myownconference.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "myruststats.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mysticplumes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mystudy.me", "include_subdomains": true, "mode": "force-https" },
+ { "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" },
+ { "name": "nabankco.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nagaya.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nako.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nalifornia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nargileh.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "naro.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nartuk.com.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "natalia.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "natalt.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "natanaelys.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "natenom.name", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nathansmetana.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nationalcentereg.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "natural-progesterone.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "naturesystems.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nauck.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "navigate-it-services.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nb6.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nbp.com.pk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ncoding.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ncpw.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ncstep.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nebra.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neftebitum-kngk.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "negativecurvature.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neilgreen.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neo19.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netbank.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netbulls.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netmazk.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netwerkmanager.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "networkalarmcorp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "networking4all.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "networkingnexus.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "networkingphoenix.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "netzwerkwerk.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "neuronasdigitales.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "never-afk.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "newedivideo.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "newlooknow.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "newstone-tech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "newsyslog.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "newtnote.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "next176.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "next24.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nextgencel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ng-firewall.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nghe.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nichteinschalten.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "niconiconi.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "niduxcomercial.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nierenpraxis-dr-merkel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nierenpraxis-merkel.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nightfirecat.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nightwinds.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nikklassen.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "niklaslindblad.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nikolasgrottendieck.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nine-hells.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ninespec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nippon-oku.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nirada.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nixien.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nl-ix.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nlegall.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nmsnj.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nnqc.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "no17sifangjie.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nodespin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "noedidacticos.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "noez.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nolatepayments.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nomesbiblicos.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "noobunbox.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nord-sud.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "norskpensjon.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nosecretshop.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nossasenhoradodesterro.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "notenoughtime.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "notificami.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "notoriousdev.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "notypiesni.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "npol.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nspeaks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nufla.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nukenet.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "null.cat", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nurserybook.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nutleyeducationalfoundation.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nutleyef.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nuttyveg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nwra.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nwwc.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nyip.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nyronet.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nzbs.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "o0o.one", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oasisim.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "obsidianirc.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "occentus.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ochaken.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "octanio.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "octocat.ninja", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oddtime.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ohiohealthfortune100.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ohsocool.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oishioffice.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oke.com.tw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "okutama.in.th", "include_subdomains": true, "mode": "force-https" },
+ { "name": "olcso-vps-szerver.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oliver-pietsch.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ollehbizev.co.kr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ollies.cloud", "include_subdomains": true, "mode": "force-https" },
+ { "name": "olymp-arts.world", "include_subdomains": true, "mode": "force-https" },
+ { "name": "omniasl.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onefour.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oneminute.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oneweb.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oneworldbank.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onguardonline.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oniichan.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "online-wetten.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onlinecompliance.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onlinedeposit.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onlinelighting.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onlinetravelmoney.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onmaps.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ontras.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onyxwall.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "onyxwall.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ooyo.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "open-future.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "openblox.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "openconnect.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "openmtbmap.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "opim.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oprbox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "optometriepunt.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oracaodocredo.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orbiosales.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ordereat.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orientalart.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "orioncustompcs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oroweatorganic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "osaiyuwu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ossan-kobe-gourmet.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "osteammate.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "otpsmart.com.ua", "include_subdomains": true, "mode": "force-https" },
+ { "name": "outsider.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ovpn.to", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ovvy.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "owensmith.website", "include_subdomains": true, "mode": "force-https" },
+ { "name": "own3d.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ownit.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oxygenabsorbers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "oznamovacipovinnost.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "p-s-b.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pacelink.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "packlane.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paestbin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pagetoimage.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "painosso.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paisaone.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pajowu.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pakremit.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paperturn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paperwork.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paragon.com.sg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paragreen.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "parentinterview.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "parentmail.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "parleu2016.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "partnerbeam.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pastaenprosecco.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pastaf.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paster.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pasteros.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pastie.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "patentfamily.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paternitydnatest.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "patfs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "patientinsight.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "patralos.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "patrickschneider.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paulbdelaat.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paulinewesterman.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paxwinkel.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paypaq.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paypro.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "payroll.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "payslipview.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paytwopay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pbapp.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pc-nf.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pccentral.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pchax.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pdamsidoarjo.co.id", "include_subdomains": true, "mode": "force-https" },
+ { "name": "peaceandwool.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "peakapp.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "peername.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pekkarik.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pencepay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pentano.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pentest.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pepperhead.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "perfectseourl.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "performous.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "perspectivum.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pet-nsk.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "petpost.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pewboards.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pfarchimedes-pensioen123.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pgpm.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pgtb.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pharynks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "philipkohn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "philipmordue.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phillmoore.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phillprice.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phormance.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "photo.org.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phpdistribution.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phpsecure.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pickme.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "piekacz.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "piekacz.eu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "piekacz.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pieq.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pieq.eu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pieterjangeeroms.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "piliszek.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pinnaclelife.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pinnaclelife.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pirateproxy.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pisupp.ly", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pixelhero.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pixipics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "piyabute.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plaintech.net.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plaintray.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "planpharmacy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plasti-pac.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plhdb.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pliosoft.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plixer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ploader.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pluff.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "plumlocosoft.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pmt-documenten.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pnona.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pointaction.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pointpro.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "policeiwitness.sg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "politically-incorrect.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "politiewervingshop.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pompompoes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pontualcomp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "poolsandstuff.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "portosonline.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "portraitsystem.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "portvaletickets.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "poshpak.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "potatofrom.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "potatoheads.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "power99press.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "powerentertainment.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "powergridess.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "powerwellness-korecki.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ppipe.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prazynka.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "precedecaritas.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prego-shop.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "preparetheword.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prescotonline.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "preworkout.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prilock.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "princessmargaretlotto.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prior-it.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "privaterelay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "privatestatic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prjktruby.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prnt.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pro-zone.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "profidea.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "profivps.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prohostonline.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "proitconsulting.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "projectbenson.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "promoscuola.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "promotiongeeks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "propipesystem.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prosocialmachines.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prosoft.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "protoyou.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "proxybay.top", "include_subdomains": true, "mode": "force-https" },
+ { "name": "proxyweb.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prtpe.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "prvikvadrat.hr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "przemas.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "psb1911.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "psicologia.co.ve", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pste.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pterodactylus.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ptsoft.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "puddis.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pugliese.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pvtschlag.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pxx.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pyol.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pysays.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qccareerschool.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qcdesignschool.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qceventplanning.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qcmakeupacademy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qcstudentcenter.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qcstyleacademy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qctravelschool.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qingpat.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qonqa.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qrara.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qrlending.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "qualityofcourse.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quantacloud.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "questsandrewards.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quickpayservice.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quietapple.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quikpay.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quintessa.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quotemaster.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "quotev.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "r6-team.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "racasdecachorro.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "radyn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "raidstone.rocks", "include_subdomains": true, "mode": "force-https" },
+ { "name": "railyardurgentcare.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rainforest.engineering", "include_subdomains": true, "mode": "force-https" },
+ { "name": "raitza.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "randc.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "randomcage.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "randstaddirect.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rannseier.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rapido.nu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ratajczak.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ratd.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ratuseks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ratuseks.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ratuseks.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rautermods.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ravindran.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rawet.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rawsec.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "raymondjcox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rcafox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rcorporation.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rdh.asia", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rdns.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "readr.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "real-it.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "realwaycome.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reanimated.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reardenporn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "recapp.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redar.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redballoonsecurity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redbee.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redburn.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reddingsbrigade-zwolle.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rede-reim.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rede.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redigest.it", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redzurl.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "regaloaks.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "regalosymuestrasgratis.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "regendevices.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "register.gov.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reic.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reiki-coaching.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reimers.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reithguard-it.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "relaxhavefun.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "remambo.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rent-a-coder.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "renteater.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "replicagunsswords.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "republique.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "repustate.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reputationweaver.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "res42.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "resc.la", "include_subdomains": true, "mode": "force-https" },
+ { "name": "resist.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "restrito.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "retrotracks.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "revamed.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "revensoftware.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reverie.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "revthefox.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "revtut.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rhodenmanorcattery.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rhynl.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ribs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "righttoknow.ie", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rijschoolgevonden.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "riskmgt.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "riversideauto.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "riyono.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "robodeidentidad.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rockcanyonbank.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rocksberg.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rolandreed.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "romeoferraris.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ron2k.za.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "root.eu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rootswitch.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rotterdamjazz.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rottweil-hilft.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rout0r.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rouvray.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rowancasting.ie", "include_subdomains": true, "mode": "force-https" },
+ { "name": "royalmarinesassociation.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "royalpub.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rring.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rsampaio.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rsync.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "runcarina.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "runreport.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ruobiyi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rusempire.ru", "include_subdomains": true, "mode": "force-https" },
+ { "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" },
+ { "name": "salverainha.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saml2.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sanandreasstories.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sanasalud.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sanradon.by", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sarah-beckett-harpist.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sarahlicity.me.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sarahs-roestcafe.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sarahsweetlife.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sarindia.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saskpension.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "satrent.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "satsukii.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saucyfox.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saunasandstuff.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "saunasandstuff.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "savenet.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "savingsstoreonline.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schooltrends.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schoolze.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schreinerei-jahreis.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schritt4fit.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "schroepfglas-versand.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sculpture.support", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secboom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secondary-survivor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secondary-survivor.help", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secondary-survivor.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secondarysurvivor.help", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secondarysurvivorportal.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secondarysurvivorportal.help", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secretpanties.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sectun.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secure-server-hosting.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secure.chat", "include_subdomains": true, "mode": "force-https" },
+ { "name": "secureonline.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "securityinet.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "securityinet.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "securityinet.org.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "securityprimes.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "securitysoapbox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seedbox.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "seen.life", "include_subdomains": true, "mode": "force-https" },
+ { "name": "segitz.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "selectruckscalltrackingreports.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "selfcarecentral.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "selldorado.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "semen3325.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "semps-servers.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "semps.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "semyonov.su", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sendinvoice.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "senedirect.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sensibus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "serenitycreams.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "serverpedia.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "servious.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sesha.co.za", "include_subdomains": true, "mode": "force-https" },
+ { "name": "setphaserstostun.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "setuid.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "setuid0.kr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sevenmatches.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sexton.uk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shadoom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shadowsocks.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shadowsworldonline.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shagi29.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shakespearesolutions.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shareimg.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sharepointdrive.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sharescope.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shauncrowley.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shawcentral.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shazbots.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shellfire.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shenghaiautoparts.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shep.co.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shh.sh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shinnyosangha.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shocksrv.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shorebreaksecurity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shortpath.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "showkeeper.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shu-kin.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "shyrydan.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sichere-kartenakzeptanz.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sieh.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "signslabelstapesandmore.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "silicagelpackets.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "silver-drachenkrieger.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "silverbowflyshop.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "silvistefi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simbihaiti.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simobilklub.si", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simon-hofmann.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simoncommunity.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simongong.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simonkjellberg.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simonreich.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simonsreich.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simplepractice.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simplixos.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "simplymozzo.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "singleuse.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "singlu10.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sinosky.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sirius-lee.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sistem-maklumat.com.my", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skalender.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skaraborgsassistans.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skarrok.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skatclub-beratzhausen.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ski-insurance.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skigebiete-test.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skilldetector.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skk.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skotty.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sloancom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slotcar.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slowfood.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slxh.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "slxh.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smallplanet.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smart-ov.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smartftp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smarthdd.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smarthomedna.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smarthouse.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smartrak.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smartshiftme.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smdavis.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sme-gmbh.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smithandcanova.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smkw.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smoo.st", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smow.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smow.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "smusg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sneakpod.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snfdata.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sniderman.eu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snow-online.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snow-online.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "snughealth.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "so-healthy.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "social-events.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "socialbillboard.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "socialdevelop.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sockeye.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "softwaredesign.foundation", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sogeek.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sogravatas.net.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sokkenhoek.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sol-3.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "solar-ec.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "solidfuelappliancespares.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "solinter.com.br", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soll-i.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "solutionhoisthire.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "solved.tips", "include_subdomains": true, "mode": "force-https" },
+ { "name": "somethingnew.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sona-gaming.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sondergaard.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sonic.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sos.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sotar.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sotor.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "soulema.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sourcely.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sous-surveillance.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "southside-crew.club", "include_subdomains": true, "mode": "force-https" },
+ { "name": "southworcestershiregpservices.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spacecompute.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spacehq.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spaggel.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spauted.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spaysy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "speculor.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "speedmann.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "speedyprep.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "speidel.com.tr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spherenix.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spicydog.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spirit-dev.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spitefultowel.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "splitdna.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sqlapius.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sqr-training.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "square-src.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "squeezemetrics.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "srchub.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "srv47.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ssl247.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ssl247.com.mx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ssl247.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ssl247.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ssnc.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sss3s.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stabletoken.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stadionmanager.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stadjerspasonline.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stage-props-blank-guns.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stageirites.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stagingjobshq.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stagstickets.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stahl.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "starmusic.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stash.ai", "include_subdomains": true, "mode": "force-https" },
+ { "name": "statecover.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stateofexception.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "static.or.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stationnementdenuit.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "statuschecks.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stealsaga.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "steckregal-super.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "steidlewirt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "steigerplank.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stellanova-planeten.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sterlingtrader.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stevensononthe.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stoffe-monster.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stoick.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "storecove.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "storeden.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stqry.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "str0.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "strchr.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "streamzilla.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "strictlysudo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stroeercrm.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "studenckiemetody.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stupendous.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stuur.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stw-group.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "styleci.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "stylenda.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "su1ph3r.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "subseq.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "subtitle.rip", "include_subdomains": true, "mode": "force-https" },
+ { "name": "suncountrymarine.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "supastuds.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "super-o-blog.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "superhome.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "superiorfloridavacation.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "superkonsult.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "superswingtrainer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "superwally.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "surfone-leucate.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "surgenet.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "survature.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "susastudentenjobs.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sustainability.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sustsol.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "svenskacasino.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swaggerdile.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "swaleacademiestrust.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sycamorememphis.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sydgrabber.tk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sylvaindurand.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sylvanorder.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "synapticconsulting.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sync-it.no", "include_subdomains": true, "mode": "force-https" },
+ { "name": "syneic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "synfin.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "syriatalk.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "syriatalk.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sysmike.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "szechenyi2020.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "t-hawk.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "t-point.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "t-shirts4less.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tabla-periodica.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tacomafia.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "takusan.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "talsi.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tangiblesecurity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tante-bugil.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tapfinder.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "taquilla.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "taskforce512.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tastycake.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tatilbus.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tavoittaja.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "taxspeaker.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "team-one.racing", "include_subdomains": true, "mode": "force-https" },
+ { "name": "team3482.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tech-essential.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tech-rat.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "techmajesty.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "techpointed.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tecnogaming.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tedeh.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tedovo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teebeedee.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teemo.gg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "telefonkonferenz.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tempcraft.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tenenz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tengroup.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tennisadmin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tentations-voyages.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teos.online", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teoskanta.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tepid.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "terracloud.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "terravirtua.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "testingbot.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teuniz.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "teunstuinposters.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "texterseo.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "textoplano.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tgr.re", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thackbarth.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thai.land", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thaicyberpoint.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thaihostcool.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theberkshirescompany.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thecitizens.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thecitywarehouse.clothing", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theclementinebutchers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theclubjersey.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thedevrycommonsbrasil.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theendofzion.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thefarbeyond.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theflyingbear.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thefootballanalyst.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thefox.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thegcccoin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thegvoffice.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thehiddenbay.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thelastsurprise.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "themillerslive.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thenorthschool.org.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thepiratebay.poker", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theploughharborne.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theseoframework.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thesharepointfarm.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theshopally.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "theurbanyoga.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thevintagenews.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thewindow.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thierfreund.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thinktux.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thirdpartytrade.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thirty5.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thomwiggers.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "threatcentral.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "throwaway.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tibbitshall.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ticketoplichting.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tickettoaster.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tickreport.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tigerdile.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "timbuktutimber.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "time-river.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "timestamp.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "timmersgems.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "timwittenberg.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tippspiel.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tjenestetorvet.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tls.care", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tmi-products.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tmi-produkter.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tmpraider.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tofu.im", "include_subdomains": true, "mode": "force-https" },
+ { "name": "togelonlinecommunity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tokaido.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tokoone.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tokotimbangandigitalmurah.web.id", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tommsy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tomwilson.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tonegidoarchief.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tonkinson.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "topbrakes.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "topdevbox.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "torsten-schmitz.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "toshkov.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "totalbeauty.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "totaltriathlon.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "totem-international.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tourispo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tourpeer.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tout-art.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "towandalibrary.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tp-iryuubun.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tp-kabushiki.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tp-kyouyufudousan.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tp-law.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trade-smart.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tradeinvent.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trademan.ky", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tradinghope.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tradiz.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trakfusion.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "transacid.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "transmithe.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "transportal.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "travelinsurance.co.nz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tretkowski.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trident-online.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trim-a-slab.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trinityaffirmations.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trinnes.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tripdelta.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tripseats.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "troi.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "truckerswereld.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "truejob.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trueteaching.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "truthmessages.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "trw-reseller.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tsecy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tsgbit.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tsrstore.gq", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tubepro.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tunai.id", "include_subdomains": true, "mode": "force-https" },
+ { "name": "turbobit.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "turnik-67.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "turtle.ai", "include_subdomains": true, "mode": "force-https" },
+ { "name": "turtlementors.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tuxcloud.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twarog.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twd2.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twd2.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twelve.rocks", "include_subdomains": true, "mode": "force-https" },
+ { "name": "twogo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tx041cap.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "txclimbers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "txf.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tyl.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tylerschmidtke.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tylian.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tyroproducts.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tysye.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uber.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uberboxen.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ublox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ubuntuhot.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "udomain.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ufgaming.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uhc.gg", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ukchemicalresearch.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ukdropshipment.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ukdropshipment.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ultieme.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "umie.cc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "umisonoda.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "under30stravelinsurance.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "undo.co.il", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unfiltered.nyc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unicooo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uniform-agri.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unit7jazz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unit7jazz.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "universalcarremote.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "universalpaymentgateway.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "university4industry.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "universogay.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "unsystem.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "upani.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "upstox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uptimed.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uptimenotguaranteed.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "urbanesecurity.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "urlchomp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "urspringer.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usaab.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usbirthcertificate.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usercare.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "usleep.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "utopianhomespa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uttnetgroup.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "v2.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vakuutuskanava.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "valkyrja.xyz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "valleyridgepta.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vampirism.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vandalfsen.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vande-walle.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vanitynailworkz.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vantien.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vavai.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vbest.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vcientertainment.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vcr.re", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vdbongard.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vdrpro.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vennet.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "venturepro.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vetdnacenter.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "victorjacobs.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vide-maisons.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "videogamesartwork.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "videotogel.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vidid.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vidz.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vigilantnow.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vigilo.cf", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vigilo.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vigo-tarife.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vikasbabyworld.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "viktorsvantesson.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vincentpancol.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vincitraining.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vintageheartcoffee.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vinyculture.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vipmusic.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "virtualdesignmedia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "visioflux-premium.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vistaalmar.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vistarait.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vitagenda.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vitalita.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vitapingu.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "viviotech.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vlora.city", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vnvisa.center", "include_subdomains": true, "mode": "force-https" },
+ { "name": "voceinveste.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "volkergropp.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vonavycukor.sk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vpn-byen.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vps-szerver-berles.hu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vratny.space", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vuosaarenmontessoritalo.fi", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vux.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vxapps.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "vxstream-sandbox.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "w4xzr.top", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wa-stromerzeuger.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "waelti.xxx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "waffle.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "waka-mono.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wakamiyasumiyosi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wakened.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wallsblog.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wangql.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wangql.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "warhaggis.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "warhistoryonline.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "warmservers.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "warped.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "watchium.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wave.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wavefrontsystemstech.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wavesboardshop.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "waylaydesign.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wdt.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wealthcentral.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wealthfactory.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wealthreport.com.au", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wear2work.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wearandcare.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "web4pro.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webchat.domains", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webdesign-kronberg.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webergrillrestaurant.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webhosting4.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weblogic.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webmax.com.tr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webperformance.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webs4all.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "websectools.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webseitenserver.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webstylemedia.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webtheapp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webwit.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "webwork.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "weicn.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "welcomehelp.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wellastore.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wellensteyn.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "werbewelt-tv.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "werken-bij-inwork.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "werkenbijkfc.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "westsussexconnecttosupport.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wetoxic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whatanime.ga", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whatsstalk.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whiskynerd.ca", "include_subdomains": true, "mode": "force-https" },
+ { "name": "whitelabelcashback.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wholesomeharvestbread.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wholikes.us", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wiberg.nu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wiedu.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wijnservices.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wikiclash.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "willberg.bayern", "include_subdomains": true, "mode": "force-https" },
+ { "name": "willcipriano.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "william.si", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wimake.solutions", "include_subdomains": true, "mode": "force-https" },
+ { "name": "windrunner.se", "include_subdomains": true, "mode": "force-https" },
+ { "name": "winghill.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wingumd.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "winterschoen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wintodoor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wiretrip.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wispapp.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "witway.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wizzr.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wmcuk.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wofford-ecs.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wonder.com.mx", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wonderlandmovies.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wondy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wordxtra.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "workfone.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "woutervdb.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wow-foederation.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wowapi.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wphostingspot.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wsa.poznan.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wth.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wubocong.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wuetix.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wufu.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wvg.myds.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "www3.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "x3led.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "x509.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xa1.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xalqbank-online.az", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xbb.hk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xbb.li", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xboxdownloadthat.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xcentricmold.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xdeftor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xendo.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xg3n1us.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xichuangke.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xilef.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xinbiji.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xmpp.dk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--3lqp21gwna.cn", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--3lqp21gwna.xn--fiqz9s", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--79q87uvkclvgd56ahq5a.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xn--pbt947am3ab71g.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xnode.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xoffy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xrockx.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xsmobile.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xuc.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xxbase.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xyfun.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yacobo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yak.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yal.sh", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yameveo.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yaoidreams.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yapbreak.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yasinaydin.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ydy.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yesonline.asia", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yesonline.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yinlei.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yjsoft.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ynode.co", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ynode.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "youkaryote.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "youkaryote.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yourznc.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yuhen.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yuko.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yum.beer", "include_subdomains": true, "mode": "force-https" },
+ { "name": "z-vector.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zaalleatherwear.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zahe.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zamorano.edu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zap.yt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zbigniewgalucki.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zbp.at", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zebry.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zeedroom.be", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zehdenick-bleibt-bunt.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zeitzer-turngala.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zenvideocloud.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zerekin.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zertif.info", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zerudi.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zespia.tw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zeto365.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zetorzeszow.pl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zhangruilin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zhh.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ziin.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zimiao.moe", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zingarastore.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zionvps.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zippy-download.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zippy-download.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zjutv.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zohar.wang", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zomerschoen.nl", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zorium.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zuram.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zvncloud.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "zyf.pw", "include_subdomains": true, "mode": "force-https" },
+ // END OF MANUAL ADDITIONS
+
+ // Entries submitted through hstspreload.appspot.com in Chrome 51 or later.
+ // START OF BULK ADDITIONS
+ { "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" },
+ { "name": "meetbot.fedoraproject.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "paste.fedoraproject.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "spins.fedoraproject.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "src.fedoraproject.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "torrent.fedoraproject.org", "include_subdomains": true, "mode": "force-https" },
+ // END OF BULK ADDITIONS
+
+ // To avoid trailing comma changes from showing up in diffs, we place a
+ // single entry at the end.
+ { "name": "hstspreload.appspot.com", "include_subdomains": true, "mode": "force-https" }
],
// |ReportUMAOnPinFailure| uses these to report which domain was associated
diff --git a/chromium/net/http/transport_security_state_unittest.cc b/chromium/net/http/transport_security_state_unittest.cc
index 75c7c751904..20726e41c07 100644
--- a/chromium/net/http/transport_security_state_unittest.cc
+++ b/chromium/net/http/transport_security_state_unittest.cc
@@ -14,6 +14,7 @@
#include "base/rand_util.h"
#include "base/sha1.h"
#include "base/strings/string_piece.h"
+#include "base/test/histogram_tester.h"
#include "base/values.h"
#include "crypto/sha2.h"
#include "net/base/host_port_pair.h"
@@ -23,6 +24,7 @@
#include "net/cert/asn1_util.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/cert_verify_result.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/test_root_certs.h"
#include "net/cert/x509_cert_types.h"
#include "net/cert/x509_certificate.h"
@@ -46,6 +48,8 @@ const char kHost[] = "example.test";
const char kSubdomain[] = "foo.example.test";
const uint16_t kPort = 443;
const char kReportUri[] = "http://report-example.test/test";
+const char kExpectCTStaticHostname[] = "preloaded-expect-ct.badssl.com";
+const char kExpectCTStaticReportURI[] = "https://report.badssl.com/expect-ct";
// kGoodPath is blog.torproject.org.
const char* const kGoodPath[] = {
@@ -87,6 +91,9 @@ class MockCertificateReportSender
latest_report_ = report;
}
+ void SetErrorCallback(
+ const base::Callback<void(const GURL&, int)>& error_callback) override {}
+
void Clear() {
latest_report_uri_ = GURL();
latest_report_ = std::string();
@@ -100,6 +107,59 @@ class MockCertificateReportSender
std::string latest_report_;
};
+// A mock ReportSender that simulates a net error on every report sent.
+class MockFailingCertificateReportSender
+ : public TransportSecurityState::ReportSender {
+ public:
+ MockFailingCertificateReportSender() : net_error_(ERR_CONNECTION_FAILED) {}
+ ~MockFailingCertificateReportSender() override {}
+
+ int net_error() { return net_error_; }
+
+ // TransportSecurityState::ReportSender:
+ void Send(const GURL& report_uri, const std::string& report) override {
+ ASSERT_FALSE(error_callback_.is_null());
+ error_callback_.Run(report_uri, net_error_);
+ }
+
+ void SetErrorCallback(
+ const base::Callback<void(const GURL&, int)>& error_callback) override {
+ error_callback_ = error_callback;
+ }
+
+ private:
+ const int net_error_;
+ base::Callback<void(const GURL&, int)> error_callback_;
+};
+
+// A mock ExpectCTReporter that remembers the latest violation that was
+// reported and the number of violations reported.
+class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter {
+ public:
+ MockExpectCTReporter() : num_failures_(0) {}
+ ~MockExpectCTReporter() override {}
+
+ void OnExpectCTFailed(const HostPortPair& host_port_pair,
+ const GURL& report_uri,
+ const net::SSLInfo& ssl_info) override {
+ num_failures_++;
+ host_port_pair_ = host_port_pair;
+ report_uri_ = report_uri;
+ ssl_info_ = ssl_info;
+ }
+
+ const HostPortPair& host_port_pair() { return host_port_pair_; }
+ const GURL& report_uri() { return report_uri_; }
+ const SSLInfo& ssl_info() { return ssl_info_; }
+ uint32_t num_failures() { return num_failures_; }
+
+ private:
+ HostPortPair host_port_pair_;
+ GURL report_uri_;
+ SSLInfo ssl_info_;
+ uint32_t num_failures_;
+};
+
void CompareCertificateChainWithList(
const scoped_refptr<X509Certificate>& cert_chain,
const base::ListValue* cert_list) {
@@ -210,6 +270,12 @@ class TransportSecurityStateTest : public testing::Test {
TransportSecurityState::PKPState* pkp_result) {
return state->GetStaticDomainState(host, sts_result, pkp_result);
}
+
+ bool GetExpectCTState(TransportSecurityState* state,
+ const std::string& host,
+ TransportSecurityState::ExpectCTState* result) {
+ return state->GetStaticExpectCTState(host, result);
+ }
};
TEST_F(TransportSecurityStateTest, DomainNameOddities) {
@@ -1242,6 +1308,52 @@ TEST_F(TransportSecurityStateTest, HPKPReporting) {
good_hashes));
}
+// Tests that a histogram entry is recorded when TransportSecurityState
+// fails to send an HPKP violation report.
+TEST_F(TransportSecurityStateTest, UMAOnHPKPReportingFailure) {
+ base::HistogramTester histograms;
+ const std::string histogram_name = "Net.PublicKeyPinReportSendingFailure";
+ HostPortPair host_port_pair(kHost, kPort);
+ GURL report_uri(kReportUri);
+ // Two dummy certs to use as the server-sent and validated chains. The
+ // contents don't matter.
+ scoped_refptr<X509Certificate> cert1 =
+ ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem");
+ scoped_refptr<X509Certificate> cert2 =
+ ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
+ ASSERT_TRUE(cert1);
+ ASSERT_TRUE(cert2);
+
+ HashValueVector good_hashes, bad_hashes;
+
+ for (size_t i = 0; kGoodPath[i]; i++)
+ EXPECT_TRUE(AddHash(kGoodPath[i], &good_hashes));
+ for (size_t i = 0; kBadPath[i]; i++)
+ EXPECT_TRUE(AddHash(kBadPath[i], &bad_hashes));
+
+ // The histogram should start off empty.
+ histograms.ExpectTotalCount(histogram_name, 0);
+
+ TransportSecurityState state;
+ MockFailingCertificateReportSender mock_report_sender;
+ state.SetReportSender(&mock_report_sender);
+
+ const base::Time current_time = base::Time::Now();
+ const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
+ state.AddHPKP(kHost, expiry, true, good_hashes, report_uri);
+
+ std::string failure_log;
+ EXPECT_FALSE(state.CheckPublicKeyPins(
+ host_port_pair, true, bad_hashes, cert1.get(), cert2.get(),
+ TransportSecurityState::ENABLE_PIN_REPORTS, &failure_log));
+
+ // Check that the UMA histogram was updated when the report failed to
+ // send.
+ histograms.ExpectTotalCount(histogram_name, 1);
+ histograms.ExpectBucketCount(histogram_name, mock_report_sender.net_error(),
+ 1);
+}
+
TEST_F(TransportSecurityStateTest, HPKPReportOnly) {
HostPortPair host_port_pair(kHost, kPort);
GURL report_uri(kReportUri);
@@ -1553,16 +1665,152 @@ TEST_F(TransportSecurityStateTest, HPKPReportRateLimiting) {
// Tests that static (preloaded) expect CT state is read correctly.
TEST_F(TransportSecurityStateTest, PreloadedExpectCT) {
- const char kHostname[] = "preloaded-expect-ct.badssl.com";
TransportSecurityState state;
TransportSecurityStateTest::EnableStaticExpectCT(&state);
TransportSecurityState::ExpectCTState expect_ct_state;
- EXPECT_TRUE(state.GetStaticExpectCTState(kHostname, &expect_ct_state));
- EXPECT_EQ(kHostname, expect_ct_state.domain);
- EXPECT_EQ(GURL("https://report.badssl.com/expect-ct"),
- expect_ct_state.report_uri);
- EXPECT_FALSE(state.GetStaticExpectCTState("pinning-test.badssl.com",
- &expect_ct_state));
+ EXPECT_TRUE(
+ GetExpectCTState(&state, kExpectCTStaticHostname, &expect_ct_state));
+ EXPECT_EQ(kExpectCTStaticHostname, expect_ct_state.domain);
+ EXPECT_EQ(GURL(kExpectCTStaticReportURI), expect_ct_state.report_uri);
+ EXPECT_FALSE(
+ GetExpectCTState(&state, "pinning-test.badssl.com", &expect_ct_state));
+}
+
+// Tests that the Expect CT reporter is not notified for invalid or absent
+// header values.
+TEST_F(TransportSecurityStateTest, InvalidExpectCTHeader) {
+ HostPortPair host_port(kExpectCTStaticHostname, 443);
+ SSLInfo ssl_info;
+ ssl_info.ct_compliance_details_available = true;
+ ssl_info.ct_cert_policy_compliance =
+ ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS;
+ ssl_info.is_issued_by_known_root = true;
+
+ TransportSecurityState state;
+ TransportSecurityStateTest::EnableStaticExpectCT(&state);
+ MockExpectCTReporter reporter;
+ state.SetExpectCTReporter(&reporter);
+ state.ProcessExpectCTHeader("", host_port, ssl_info);
+ EXPECT_EQ(0u, reporter.num_failures());
+
+ state.ProcessExpectCTHeader("blah blah", host_port, ssl_info);
+ EXPECT_EQ(0u, reporter.num_failures());
+
+ state.ProcessExpectCTHeader("preload", host_port, ssl_info);
+ EXPECT_EQ(1u, reporter.num_failures());
+}
+
+// Tests that the Expect CT reporter is only notified about certificates
+// chaining to public roots.
+TEST_F(TransportSecurityStateTest, ExpectCTNonPublicRoot) {
+ HostPortPair host_port(kExpectCTStaticHostname, 443);
+ SSLInfo ssl_info;
+ ssl_info.ct_compliance_details_available = true;
+ ssl_info.ct_cert_policy_compliance =
+ ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS;
+ ssl_info.is_issued_by_known_root = false;
+
+ TransportSecurityState state;
+ TransportSecurityStateTest::EnableStaticExpectCT(&state);
+ MockExpectCTReporter reporter;
+ state.SetExpectCTReporter(&reporter);
+ state.ProcessExpectCTHeader("preload", host_port, ssl_info);
+ EXPECT_EQ(0u, reporter.num_failures());
+
+ ssl_info.is_issued_by_known_root = true;
+ state.ProcessExpectCTHeader("preload", host_port, ssl_info);
+ EXPECT_EQ(1u, reporter.num_failures());
+}
+
+// Tests that the Expect CT reporter is not notified when compliance
+// details aren't available.
+TEST_F(TransportSecurityStateTest, ExpectCTComplianceNotAvailable) {
+ HostPortPair host_port(kExpectCTStaticHostname, 443);
+ SSLInfo ssl_info;
+ ssl_info.ct_compliance_details_available = false;
+ ssl_info.ct_cert_policy_compliance =
+ ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS;
+ ssl_info.is_issued_by_known_root = true;
+
+ TransportSecurityState state;
+ TransportSecurityStateTest::EnableStaticExpectCT(&state);
+ MockExpectCTReporter reporter;
+ state.SetExpectCTReporter(&reporter);
+ state.ProcessExpectCTHeader("preload", host_port, ssl_info);
+ EXPECT_EQ(0u, reporter.num_failures());
+
+ ssl_info.ct_compliance_details_available = true;
+ state.ProcessExpectCTHeader("preload", host_port, ssl_info);
+ EXPECT_EQ(1u, reporter.num_failures());
+}
+
+// Tests that the Expect CT reporter is not notified about compliant
+// connections.
+TEST_F(TransportSecurityStateTest, ExpectCTCompliantCert) {
+ HostPortPair host_port(kExpectCTStaticHostname, 443);
+ SSLInfo ssl_info;
+ ssl_info.ct_compliance_details_available = true;
+ ssl_info.ct_cert_policy_compliance =
+ ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS;
+ ssl_info.is_issued_by_known_root = true;
+
+ TransportSecurityState state;
+ TransportSecurityStateTest::EnableStaticExpectCT(&state);
+ MockExpectCTReporter reporter;
+ state.SetExpectCTReporter(&reporter);
+ state.ProcessExpectCTHeader("preload", host_port, ssl_info);
+ EXPECT_EQ(0u, reporter.num_failures());
+
+ ssl_info.ct_cert_policy_compliance =
+ ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS;
+ state.ProcessExpectCTHeader("preload", host_port, ssl_info);
+ EXPECT_EQ(1u, reporter.num_failures());
+}
+
+// Tests that the Expect CT reporter is not notified for a site that
+// isn't preloaded.
+TEST_F(TransportSecurityStateTest, ExpectCTNotPreloaded) {
+ HostPortPair host_port("not-expect-ct-preloaded.test", 443);
+ SSLInfo ssl_info;
+ ssl_info.ct_compliance_details_available = true;
+ ssl_info.ct_cert_policy_compliance =
+ ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS;
+ ssl_info.is_issued_by_known_root = true;
+
+ TransportSecurityState state;
+ TransportSecurityStateTest::EnableStaticExpectCT(&state);
+ MockExpectCTReporter reporter;
+ state.SetExpectCTReporter(&reporter);
+ state.ProcessExpectCTHeader("preload", host_port, ssl_info);
+ EXPECT_EQ(0u, reporter.num_failures());
+
+ host_port.set_host(kExpectCTStaticHostname);
+ state.ProcessExpectCTHeader("preload", host_port, ssl_info);
+ EXPECT_EQ(1u, reporter.num_failures());
+}
+
+// Tests that the Expect CT reporter is notified for noncompliant
+// connections.
+TEST_F(TransportSecurityStateTest, ExpectCTReporter) {
+ HostPortPair host_port(kExpectCTStaticHostname, 443);
+ SSLInfo ssl_info;
+ ssl_info.ct_compliance_details_available = true;
+ ssl_info.ct_cert_policy_compliance =
+ ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS;
+ ssl_info.is_issued_by_known_root = true;
+
+ TransportSecurityState state;
+ TransportSecurityStateTest::EnableStaticExpectCT(&state);
+ MockExpectCTReporter reporter;
+ state.SetExpectCTReporter(&reporter);
+ state.ProcessExpectCTHeader("preload", host_port, ssl_info);
+ EXPECT_EQ(1u, reporter.num_failures());
+ EXPECT_TRUE(reporter.ssl_info().ct_compliance_details_available);
+ EXPECT_EQ(ssl_info.ct_cert_policy_compliance,
+ reporter.ssl_info().ct_cert_policy_compliance);
+ EXPECT_EQ(host_port.host(), reporter.host_port_pair().host());
+ EXPECT_EQ(host_port.port(), reporter.host_port_pair().port());
+ EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri());
}
} // namespace net
diff --git a/chromium/net/http/url_security_manager_win.cc b/chromium/net/http/url_security_manager_win.cc
index 19d2550784c..614fa443255 100644
--- a/chromium/net/http/url_security_manager_win.cc
+++ b/chromium/net/http/url_security_manager_win.cc
@@ -5,7 +5,6 @@
#include "net/http/url_security_manager.h"
#include <urlmon.h>
-#pragma comment(lib, "urlmon.lib")
#include "base/macros.h"
#include "base/strings/string_util.h"
diff --git a/chromium/net/log/net_log.h b/chromium/net/log/net_log.h
index 87141079e39..01b49b2a4ae 100644
--- a/chromium/net/log/net_log.h
+++ b/chromium/net/log/net_log.h
@@ -219,9 +219,6 @@ class NET_EXPORT NetLog {
// Adds an observer and sets its log capture mode. The observer must not be
// watching any NetLog, including this one, when this is called.
//
- // NetLog implementations must call NetLog::OnAddObserver to update the
- // observer's internal state.
- //
// DEPRECATED: The ability to watch the netlog stream is being phased out
// (crbug.com/472693) as it can be misused in production code. Please consult
// with a net/log OWNER before introducing a new dependency on this.
@@ -234,8 +231,7 @@ class NET_EXPORT NetLog {
void SetObserverCaptureMode(ThreadSafeObserver* observer,
NetLogCaptureMode capture_mode);
- // Removes an observer. NetLog implementations must call
- // NetLog::OnAddObserver to update the observer's internal state.
+ // Removes an observer.
//
// For thread safety reasons, it is recommended that this not be called in
// an object's destructor.
diff --git a/chromium/net/log/net_log_event_type_list.h b/chromium/net/log/net_log_event_type_list.h
index 966819eec8c..70a4ee1913b 100644
--- a/chromium/net/log/net_log_event_type_list.h
+++ b/chromium/net/log/net_log_event_type_list.h
@@ -476,12 +476,31 @@ EVENT_TYPE(SSL_PRIVATE_KEY_OPERATION)
// {
// "net_error": <Net integer error code>,
// }
+// TODO(nharper): remove this event.
EVENT_TYPE(SSL_GET_DOMAIN_BOUND_CERT)
+// The start/end of getting a Channel ID key.
+//
+// The START event contains these parameters:
+// {
+// "ephemeral": <Whether or not the Channel ID store is ephemeral>,
+// "service": <Unique identifier for the ChannelIDService used>,
+// "store": <Unique identifier for the ChannelIDStore used>,
+// }
+//
+// The END event may contain these parameters:
+// {
+// "net_error": <Net error code>,
+// "key": <Hex-encoded EC point of public key (uncompressed point format)>,
+// }
+EVENT_TYPE(SSL_GET_CHANNEL_ID)
+
// The SSL server requested a channel id.
+// TODO(nharper): Remove this event.
EVENT_TYPE(SSL_CHANNEL_ID_REQUESTED)
// A channel ID was provided to the SSL library to be sent to the SSL server.
+// TODO(nharper): Remove this event.
EVENT_TYPE(SSL_CHANNEL_ID_PROVIDED)
// A client certificate (or none) was provided to the SSL library to be sent
@@ -614,6 +633,18 @@ EVENT_TYPE(SIGNED_CERTIFICATE_TIMESTAMPS_RECEIVED)
// }
EVENT_TYPE(SIGNED_CERTIFICATE_TIMESTAMPS_CHECKED)
+// The certificate was checked for compliance with Certificate Transparency
+// requirements.
+//
+// The following parameters are attached to the event:
+// {
+// "certificate": <An X.509 certificate, same format as in
+// CERT_VERIFIER_JOB.>
+// "build_timely": <boolean>
+// "ct_compliance_status": <string describing compliance status>
+// }
+EVENT_TYPE(CERT_CT_COMPLIANCE_CHECKED)
+
// The EV certificate was checked for compliance with Certificate Transparency
// requirements.
//
@@ -1029,6 +1060,12 @@ EVENT_TYPE(HTTP_STREAM_REQUEST_PROTO)
// Job. The orphaned Job will continue to run to completion.
EVENT_TYPE(HTTP_STREAM_JOB_ORPHANED)
+// Emitted when a job is asked to resume after non-zero microseconds.
+// {
+// "resume_after_ms": <Number of milliseconds until job will be unblocked>
+// }
+EVENT_TYPE(HTTP_STREAM_JOB_DELAYED)
+
// ------------------------------------------------------------------------
// HttpNetworkTransaction
// ------------------------------------------------------------------------
@@ -1109,6 +1146,9 @@ EVENT_TYPE(HTTP_TRANSACTION_READ_BODY)
// restarting for authentication, on keep alive connections.
EVENT_TYPE(HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART)
+// Measures the time taken to look up the key used for Token Binding.
+EVENT_TYPE(HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY)
+
// This event is sent when we try to restart a transaction after an error.
// The following parameters are attached:
// {
@@ -1163,15 +1203,16 @@ EVENT_TYPE(HTTP2_SESSION_SYN_STREAM)
// }
EVENT_TYPE(HTTP2_SESSION_PUSHED_SYN_STREAM)
-// This event is sent for sending an HTTP/2 (or SPDY) HEADERS frame.
+// This event is sent for sending an HTTP/2 HEADERS frame.
// The following parameters are attached:
// {
-// "flags": <The control frame flags>,
// "headers": <The list of header:value pairs>,
// "fin": <True if this is the final data set by the peer on this stream>,
-// "unidirectional": <True if this stream is unidirectional>,
-// "priority": <The priority value of the stream>,
// "stream_id": <The stream id>,
+// "has_priority": <True if the PRIORITY flag is set>,
+// "parent_stream_id": <Optional; the stream id of the parent stream>,
+// "priority": <Optional; the priority value of the stream>,
+// "exclusive": <Optional; true if the exclusive bit is set>.
// }
EVENT_TYPE(HTTP2_SESSION_SEND_HEADERS)
@@ -1742,6 +1783,15 @@ EVENT_TYPE(QUIC_SESSION_CRYPTO_HANDSHAKE_MESSAGE_RECEIVED)
// }
EVENT_TYPE(QUIC_SESSION_CRYPTO_HANDSHAKE_MESSAGE_SENT)
+// A QUIC connection received a PUSH_PROMISE frame. The following
+// parameters are attached:
+// {
+// "headers": <The list of header:value pairs>,
+// "id": <The stream id>,
+// "promised_stream_id": <The stream id>,
+// }
+EVENT_TYPE(QUIC_SESSION_PUSH_PROMISE_RECEIVED)
+
// Session was closed, either remotely or by the peer.
// {
// "quic_error": <QuicErrorCode which caused the connection to be closed>,
@@ -1753,17 +1803,22 @@ EVENT_TYPE(QUIC_SESSION_CLOSED)
// QuicHttpStream
// ------------------------------------------------------------------------
-// The stream is sending the request headers.
+// A stream request's url matches a received push promise. The
+// promised stream can be adopted for this request once vary header
+// validation is complete (as part of response header processing).
// {
-// "headers": <The list of header:value pairs>
+// "stream_id": <The stream id>,
+// "url": <The url of the pushed resource>,
// }
-EVENT_TYPE(QUIC_HTTP_STREAM_SEND_REQUEST_HEADERS)
+EVENT_TYPE(QUIC_HTTP_STREAM_PUSH_PROMISE_RENDEZVOUS)
-// The stream has read the response headers.
+// Vary validation has succeeded, a http stream is attached to
+// a pushed QUIC stream.
// {
-// "headers": <The list of header:value pairs>
+// "stream_id": <The stream id>,
+// "url": <The url of the pushed resource>,
// }
-EVENT_TYPE(QUIC_HTTP_STREAM_READ_RESPONSE_HEADERS)
+EVENT_TYPE(QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM)
// Identifies the NetLog::Source() for the QuicSesssion that handled the stream.
// The event parameters are:
@@ -1773,6 +1828,28 @@ EVENT_TYPE(QUIC_HTTP_STREAM_READ_RESPONSE_HEADERS)
EVENT_TYPE(HTTP_STREAM_REQUEST_BOUND_TO_QUIC_SESSION)
// ------------------------------------------------------------------------
+// QuicChromiumClientStream
+// ------------------------------------------------------------------------
+
+// The stream is sending the request headers.
+// {
+// "headers": <The list of header:value pairs>
+// }
+EVENT_TYPE(QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS)
+
+// The stream has read the response headers.
+// {
+// "headers": <The list of header:value pairs>
+// }
+EVENT_TYPE(QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_HEADERS)
+
+// The stream has read the response trailers.
+// {
+// "headers": <The list of header:value pairs>
+// }
+EVENT_TYPE(QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_TRAILERS)
+
+// ------------------------------------------------------------------------
// HttpStreamParser
// ------------------------------------------------------------------------
@@ -1805,6 +1882,9 @@ EVENT_TYPE(AUTH_PROXY)
// The time spent authentication to the server.
EVENT_TYPE(AUTH_SERVER)
+// The channel bindings generated for the connection.
+EVENT_TYPE(AUTH_CHANNEL_BINDINGS)
+
// ------------------------------------------------------------------------
// HTML5 Application Cache
// ------------------------------------------------------------------------
diff --git a/chromium/net/log/net_log_util.cc b/chromium/net/log/net_log_util.cc
index f79be1797b2..a0884207408 100644
--- a/chromium/net/log/net_log_util.cc
+++ b/chromium/net/log/net_log_util.cc
@@ -274,10 +274,21 @@ scoped_ptr<base::DictionaryValue> GetNetConstants() {
// Information about how the "time ticks" values we have given it relate to
// actual system times. Time ticks are used throughout since they are stable
- // across system clock changes.
+ // across system clock changes. Note: |timeTickOffset| is only comparable to
+ // TimeTicks values in milliseconds.
+ // TODO(csharrison): This is an imprecise way to convert TimeTicks to unix
+ // time. In fact, there isn't really a good way to do this unless we log Time
+ // and TimeTicks values side by side for every event. crbug.com/593157 tracks
+ // a change where the user will be notified if a timing anomaly occured that
+ // would skew the conversion (i.e. the machine entered suspend mode while
+ // logging).
{
+ base::TimeDelta time_since_epoch =
+ base::Time::Now() - base::Time::UnixEpoch();
+ base::TimeDelta reference_time_ticks =
+ base::TimeTicks::Now() - base::TimeTicks();
int64_t tick_to_unix_time_ms =
- (base::TimeTicks() - base::TimeTicks::UnixEpoch()).InMilliseconds();
+ (time_since_epoch - reference_time_ticks).InMilliseconds();
// Pass it as a string, since it may be too large to fit in an integer.
constants_dict->SetString("timeTickOffset",
@@ -416,10 +427,15 @@ NET_EXPORT scoped_ptr<base::DictionaryValue> GetNetInfo(
if (info_sources & NET_INFO_SPDY_STATUS) {
base::DictionaryValue* status_dict = new base::DictionaryValue();
- status_dict->SetBoolean("spdy_enabled", HttpStreamFactory::spdy_enabled());
+ status_dict->SetBoolean("enable_spdy31",
+ http_network_session->params().enable_spdy31 &&
+ HttpStreamFactory::spdy_enabled());
+ status_dict->SetBoolean("enable_http2",
+ http_network_session->params().enable_http2 &&
+ HttpStreamFactory::spdy_enabled());
status_dict->SetBoolean(
"use_alternative_services",
- http_network_session->params().use_alternative_services);
+ http_network_session->params().parse_alternative_services);
NextProtoVector alpn_protos;
http_network_session->GetAlpnProtos(&alpn_protos);
@@ -449,11 +465,11 @@ NET_EXPORT scoped_ptr<base::DictionaryValue> GetNetInfo(
status_dict);
}
- if (info_sources & NET_INFO_SPDY_ALT_SVC_MAPPINGS) {
+ if (info_sources & NET_INFO_ALT_SVC_MAPPINGS) {
const HttpServerProperties& http_server_properties =
*context->http_server_properties();
net_info_dict->Set(
- NetInfoSourceToString(NET_INFO_SPDY_ALT_SVC_MAPPINGS),
+ NetInfoSourceToString(NET_INFO_ALT_SVC_MAPPINGS),
http_server_properties.GetAlternativeServiceInfoAsValue());
}
diff --git a/chromium/net/log/trace_net_log_observer.cc b/chromium/net/log/trace_net_log_observer.cc
index 6a64e506644..6fe44a8ea2e 100644
--- a/chromium/net/log/trace_net_log_observer.cc
+++ b/chromium/net/log/trace_net_log_observer.cc
@@ -62,7 +62,7 @@ void TraceNetLogObserver::OnAddEntry(const NetLog::Entry& entry) {
kNetLogTracingCategory, NetLog::EventTypeToString(entry.type()),
entry.source().id, "source_type",
NetLog::SourceTypeToString(entry.source().type), "params",
- scoped_refptr<base::trace_event::ConvertableToTraceFormat>(
+ scoped_ptr<base::trace_event::ConvertableToTraceFormat>(
new TracedValue(std::move(params))));
break;
case NetLog::PHASE_END:
@@ -70,7 +70,7 @@ void TraceNetLogObserver::OnAddEntry(const NetLog::Entry& entry) {
kNetLogTracingCategory, NetLog::EventTypeToString(entry.type()),
entry.source().id, "source_type",
NetLog::SourceTypeToString(entry.source().type), "params",
- scoped_refptr<base::trace_event::ConvertableToTraceFormat>(
+ scoped_ptr<base::trace_event::ConvertableToTraceFormat>(
new TracedValue(std::move(params))));
break;
case NetLog::PHASE_NONE:
@@ -78,7 +78,7 @@ void TraceNetLogObserver::OnAddEntry(const NetLog::Entry& entry) {
kNetLogTracingCategory, NetLog::EventTypeToString(entry.type()),
entry.source().id, "source_type",
NetLog::SourceTypeToString(entry.source().type), "params",
- scoped_refptr<base::trace_event::ConvertableToTraceFormat>(
+ scoped_ptr<base::trace_event::ConvertableToTraceFormat>(
new TracedValue(std::move(params))));
break;
}
diff --git a/chromium/net/net.gyp b/chromium/net/net.gyp
index 1a5690786ca..8c51208c157 100644
--- a/chromium/net/net.gyp
+++ b/chromium/net/net.gyp
@@ -6,8 +6,6 @@
'variables': {
'chromium_code': 1,
'linux_link_kerberos%': 0,
- # Enables BidirectionalStream; Used in cronet, disabled by default.
- 'enable_bidirectional_stream%': 0,
'conditions': [
['chromeos==1 or embedded==1 or OS=="ios"', {
# Disable Kerberos on ChromeOS and iOS, at least for now.
@@ -114,7 +112,6 @@
'../third_party/icu/icu.gyp:icuuc',
'../third_party/protobuf/protobuf.gyp:protobuf_lite',
'../url/url.gyp:url_lib',
- 'net_features',
'net_quic_proto',
],
'sources': [
@@ -125,24 +122,12 @@
'includes': [ 'net_common.gypi' ],
},
{
- # GN version: //net:features
- 'target_name': 'net_features',
- 'includes': [ '../build/buildflag_header.gypi' ],
- 'variables': {
- 'buildflag_header_path': 'net/net_features.h',
- 'buildflag_flags': [
- 'ENABLE_BIDIRECTIONAL_STREAM=<(enable_bidirectional_stream)',
- ],
- },
- },
- {
# GN version: //net:net_unittests
'target_name': 'net_unittests',
'type': '<(gtest_target_type)',
'dependencies': [
'../base/base.gyp:base',
'../base/base.gyp:base_i18n',
- '../base/base.gyp:base_prefs_test_support',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../crypto/crypto.gyp:crypto',
'../crypto/crypto.gyp:crypto_test_support',
@@ -151,7 +136,6 @@
'../third_party/zlib/zlib.gyp:zlib',
'../url/url.gyp:url_lib',
'balsa',
- 'http_server',
'net',
'net_quic_proto',
'net_derived_sources',
@@ -207,7 +191,7 @@
'../third_party/boringssl/boringssl.gyp:boringssl',
],
}],
- [ 'use_nss_certs == 1 or OS == "ios" or use_openssl == 0', {
+ [ 'use_nss_verifier == 1', {
'conditions': [
[ 'desktop_linux == 1 or chromeos == 1', {
'dependencies': [
@@ -222,15 +206,6 @@
}],
],
}],
- [ 'os_posix == 1 and OS != "mac" and OS != "android" and OS != "ios"', {
- 'conditions': [
- ['use_allocator!="none"', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
- ],
- }],
[ 'use_kerberos==1', {
'defines': [
'USE_KERBEROS',
@@ -250,13 +225,27 @@
'http/http_auth_handler_negotiate_unittest.cc',
],
}],
- [ 'use_nss_certs == 0 and OS != "ios"', {
- # Only include this test when using system NSS for cert verification
- # or on iOS (which also uses NSS for certs).
+ [ 'use_nss_verifier == 0', {
+ # Only include this test when using NSS for cert verification.
'sources!': [
'cert_net/nss_ocsp_unittest.cc',
],
}],
+ [ 'use_nss_verifier == 0 and OS == "ios"', {
+ # Only include these files on iOS when using NSS for cert
+ # verification.
+ 'sources!': [
+ 'cert/x509_util_ios.cc',
+ 'cert/x509_util_ios.h',
+ ],
+ }],
+ [ 'use_nss_verifier == 1 and OS == "ios"', {
+ 'sources!': [
+ 'cert/cert_verify_proc_ios.cc',
+ 'cert/cert_verify_proc_ios.h',
+ 'cert/x509_certificate_openssl_ios.cc',
+ ],
+ }],
[ 'use_openssl==1', {
'sources!': [
'quic/test_tools/crypto_test_utils_nss.cc',
@@ -264,7 +253,6 @@
}, { # else !use_openssl: remove the unneeded files and pull in NSS.
'sources!': [
'quic/test_tools/crypto_test_utils_openssl.cc',
- 'socket/ssl_client_socket_openssl_unittest.cc',
'ssl/ssl_client_session_cache_openssl_unittest.cc',
],
},
@@ -274,12 +262,11 @@
'ssl/openssl_client_key_store_unittest.cc',
],
}],
- [ 'enable_websockets != 1', {
- 'sources/': [
- ['exclude', '^websockets/'],
- ['exclude', '^server/'],
+ [ 'enable_websockets == 1', {
+ 'sources': [
+ '<@(net_websockets_test_sources)',
],
- 'dependencies!': [
+ 'dependencies': [
'http_server',
],
}],
@@ -287,6 +274,7 @@
'sources!': [
'base/directory_lister_unittest.cc',
'base/directory_listing_unittest.cc',
+ 'url_request/url_request_file_dir_job_unittest.cc',
'url_request/url_request_file_job_unittest.cc',
],
}],
@@ -299,12 +287,6 @@
],
},
],
- [ 'enable_bidirectional_stream!=1', {
- 'sources!': [
- 'http/bidirectional_stream_unittest.cc',
- ],
- },
- ],
[ 'enable_built_in_dns!=1', {
'sources!': [
'dns/address_sorter_posix_unittest.cc',
@@ -330,7 +312,7 @@
'net_with_v8',
'net_browser_services',
'net_utility_services',
- '../third_party/mojo/mojo_edk.gyp:mojo_system_impl',
+ '../mojo/mojo_edk.gyp:mojo_system_impl',
],
}, { # else
'sources!': [
@@ -381,11 +363,13 @@
'data/certificate_policies_unittest/',
'data/name_constraints_unittest/',
'data/parse_certificate_unittest/',
+ 'data/parse_ocsp_unittest/',
'data/ssl/certificates/',
'data/test.html',
'data/url_request_unittest/',
'data/verify_certificate_chain_unittest/',
'data/verify_name_match_unittest/names/',
+ 'data/verify_signed_data_unittest/',
],
'test_data_prefix': 'net',
},
@@ -539,6 +523,8 @@
'base/test_data_directory.h',
'cert/mock_cert_verifier.cc',
'cert/mock_cert_verifier.h',
+ 'cert/mock_client_cert_verifier.cc',
+ 'cert/mock_client_cert_verifier.h',
'cookies/cookie_monster_store_test.cc',
'cookies/cookie_monster_store_test.h',
'cookies/cookie_store_test_callbacks.cc',
@@ -633,7 +619,7 @@
'test/spawned_test_server/spawned_test_server.h',
],
}],
- ['use_nss_certs == 1 or OS == "ios"', {
+ ['use_nss_verifier == 1', {
'conditions': [
[ 'desktop_linux == 1 or chromeos == 1', {
'dependencies': [
@@ -648,15 +634,6 @@
}],
],
}],
- ['os_posix == 1 and OS != "mac" and OS != "android" and OS != "ios"', {
- 'conditions': [
- ['use_allocator!="none"', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
- ],
- }],
['OS == "android"', {
'dependencies': [
'net_test_jni_headers',
@@ -729,34 +706,6 @@
],
},
{
- 'target_name': 'net_docs',
- 'type': 'none',
- 'actions': [
- {
- 'action_name': 'net_docs',
- 'variables': {
- 'net_docs_input_dir': '.',
- },
- 'inputs': [
- '<@(net_docs_sources)',
- ],
- 'outputs': [
- '<(net_docs_output_dir)',
- ],
- 'action': [
- 'python',
- '<(net_docs_script)',
- '--input_path',
- '<(net_docs_input_dir)',
- '--output_path',
- '<(net_docs_output_dir)',
- '<@(net_docs_sources)',
- ],
- 'message': 'Rendering network stack documentation',
- }
- ],
- },
- {
'target_name': 'http_server',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
@@ -802,8 +751,6 @@
'tools/balsa/noop_balsa_visitor.h',
'tools/balsa/simple_buffer.cc',
'tools/balsa/simple_buffer.h',
- 'tools/balsa/split.cc',
- 'tools/balsa/split.h',
'tools/balsa/string_piece_utils.h',
'tools/quic/spdy_balsa_utils.cc',
'tools/quic/spdy_balsa_utils.h',
@@ -846,6 +793,7 @@
'tools/quic/quic_in_memory_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',
'tools/quic/quic_server_session_base.cc',
'tools/quic/quic_server_session_base.h',
'tools/quic/quic_simple_client.cc',
@@ -926,7 +874,7 @@
'interfaces/proxy_resolver_service.mojom',
],
'includes': [
- '../third_party/mojo/mojom_bindings_generator.gypi',
+ '../mojo/mojom_bindings_generator.gypi',
],
},
{
@@ -949,9 +897,8 @@
'net',
'net_interfaces',
'../mojo/mojo_base.gyp:mojo_common_lib',
- '../mojo/mojo_base.gyp:mojo_environment_chromium',
'../mojo/mojo_base.gyp:mojo_url_type_converters',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
# NOTE(amistry): As long as we support in-process Mojo v8 PAC, we
# need this dependency since in_process_mojo_proxy_resolver_factory
@@ -979,7 +926,7 @@
'net_interfaces',
'net_with_v8',
'../mojo/mojo_base.gyp:mojo_url_type_converters',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
],
},
{
@@ -995,7 +942,7 @@
'dependencies': [
'net',
'net_interfaces',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
],
},
],
@@ -1231,8 +1178,6 @@
'tools/flip_server/acceptor_thread.cc',
'tools/flip_server/acceptor_thread.h',
'tools/flip_server/constants.h',
- 'tools/flip_server/create_listener.cc',
- 'tools/flip_server/create_listener.h',
'tools/flip_server/flip_config.cc',
'tools/flip_server/flip_config.h',
'tools/flip_server/http_interface.cc',
@@ -1254,6 +1199,8 @@
'tools/flip_server/spdy_util.h',
'tools/flip_server/streamer_interface.cc',
'tools/flip_server/streamer_interface.h',
+ 'tools/flip_server/tcp_socket_util.cc',
+ 'tools/flip_server/tcp_socket_util.h',
'tools/flip_server/url_to_filename_encoder.cc',
'tools/flip_server/url_to_filename_encoder.h',
'tools/flip_server/url_utilities.cc',
@@ -1369,7 +1316,6 @@
},
'dependencies': [
'../url/url.gyp:url_lib_use_icu_alternatives_on_android',
- 'net_features',
],
'defines': [
'USE_ICU_ALTERNATIVES_ON_ANDROID=1',
@@ -1489,6 +1435,7 @@
'java_in_dir': 'test/android/javatests',
'java_in_dir_suffix': '/src_dummy',
'native_lib_target': 'libnet_java_test_support',
+ 'never_lint': 1,
},
'includes': [
'../build/java_apk.gypi',
@@ -1664,8 +1611,11 @@
'src_paths': [
'android/junit/',
],
+ 'test_type': 'junit',
+ 'wrapper_script_name': 'helper/<(_target_name)',
},
'includes': [
+ '../build/android/test_runner.gypi',
'../build/host_jar.gypi',
],
},
@@ -1707,6 +1657,35 @@
},
],
}],
+ ['OS == "linux"', {
+ 'targets': [
+ {
+ 'target_name': 'cachetool',
+ 'type': 'executable',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ 'net',
+ 'net_test_support',
+ ],
+ 'sources': [
+ 'tools/cachetool/cachetool.cc',
+ ],
+ },
+ {
+ 'target_name': 'content_decoder_tool',
+ 'type': 'executable',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../url/url.gyp:url_lib',
+ 'net',
+ ],
+ 'sources': [
+ 'filter/mock_filter_context.cc',
+ 'tools/content_decoder_tool/content_decoder_tool.cc',
+ ],
+ }
+ ],
+ }],
['test_isolation_mode != "noop"', {
'targets': [
{
diff --git a/chromium/net/net.gypi b/chromium/net/net.gypi
index 6214b52ace8..9e7161fc50f 100644
--- a/chromium/net/net.gypi
+++ b/chromium/net/net.gypi
@@ -47,14 +47,14 @@
'base/net_module.cc',
'base/net_module.h',
'base/net_string_util.h',
- 'base/net_util.cc',
- 'base/net_util.h',
'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',
'base/port_util.h',
'base/rand_callback.h',
@@ -62,7 +62,6 @@
'base/registry_controlled_domains/registry_controlled_domain.h',
'base/sockaddr_storage.cc',
'base/sockaddr_storage.h',
- 'base/socket_performance_watcher.cc',
'base/socket_performance_watcher.h',
'base/socket_performance_watcher_factory.h',
'base/sys_addrinfo.h',
@@ -81,6 +80,7 @@
'cert/cert_verifier.h',
'cert/cert_verify_result.cc',
'cert/cert_verify_result.h',
+ 'cert/client_cert_verifier.h',
'cert/crl_set.cc',
'cert/crl_set.h',
'cert/ct_known_logs.cc',
@@ -88,6 +88,7 @@
'cert/ct_known_logs_static.h',
'cert/ct_policy_enforcer.cc',
'cert/ct_policy_enforcer.h',
+ 'cert/ct_policy_status.h',
'cert/ct_verifier.h',
'cert/ct_verify_result.cc',
'cert/ct_verify_result.h',
@@ -99,6 +100,10 @@
'cert/internal/name_constraints.h',
'cert/internal/parse_certificate.cc',
'cert/internal/parse_certificate.h',
+ 'cert/internal/parse_name.cc',
+ 'cert/internal/parse_name.h',
+ 'cert/internal/parse_ocsp.h',
+ 'cert/internal/parse_ocsp.cc',
'cert/internal/signature_algorithm.cc',
'cert/internal/signature_algorithm.h',
'cert/internal/signature_policy.cc',
@@ -111,11 +116,14 @@
'cert/internal/verify_signed_data.h',
'cert/pem_tokenizer.cc',
'cert/pem_tokenizer.h',
- 'cert/sha256_legacy_support_win.cc',
- 'cert/sha256_legacy_support_win.h',
'cert/signed_certificate_timestamp.cc',
'cert/signed_certificate_timestamp.h',
+ 'cert/signed_tree_head.cc',
'cert/signed_tree_head.h',
+ 'cert/sth_distributor.cc',
+ 'cert/sth_distributor.h',
+ 'cert/sth_observer.h',
+ 'cert/sth_reporter.h',
'cert/x509_cert_types.cc',
'cert/x509_cert_types.h',
'cert/x509_certificate.cc',
@@ -157,7 +165,6 @@
'http/http_status_line_validator.h',
'http/http_util.cc',
'http/http_util.h',
- 'http/http_util_icu.cc',
'http/http_vary_data.cc',
'http/http_vary_data.h',
'http/transport_security_state.cc',
@@ -212,6 +219,8 @@
'ssl/ssl_private_key.h',
'ssl/ssl_server_config.cc',
'ssl/ssl_server_config.h',
+ 'ssl/token_binding.h',
+ 'ssl/token_binding_openssl.cc',
# Most files in net/quic are in net_nacl_common_sources, except for the
# files that have dependency on SPDY (net/spdy) or NSS.
@@ -233,14 +242,12 @@
'quic/congestion_control/rtt_stats.h',
'quic/congestion_control/send_algorithm_interface.cc',
'quic/congestion_control/send_algorithm_interface.h',
- 'quic/congestion_control/tcp_cubic_bytes_sender.cc',
- 'quic/congestion_control/tcp_cubic_bytes_sender.h',
- 'quic/congestion_control/tcp_cubic_sender.cc',
- 'quic/congestion_control/tcp_cubic_sender.h',
- 'quic/congestion_control/tcp_loss_algorithm.cc',
- 'quic/congestion_control/tcp_loss_algorithm.h',
- 'quic/congestion_control/time_loss_algorithm.cc',
- 'quic/congestion_control/time_loss_algorithm.h',
+ 'quic/congestion_control/tcp_cubic_sender_base.cc',
+ 'quic/congestion_control/tcp_cubic_sender_base.h',
+ 'quic/congestion_control/tcp_cubic_sender_bytes.cc',
+ 'quic/congestion_control/tcp_cubic_sender_base.h',
+ 'quic/congestion_control/tcp_cubic_sender_packets.cc',
+ 'quic/congestion_control/tcp_cubic_sender_packets.h',
'quic/crypto/aead_base_decrypter.h',
'quic/crypto/aead_base_decrypter_openssl.cc',
'quic/crypto/aead_base_encrypter.h',
@@ -249,10 +256,6 @@
'quic/crypto/aes_128_gcm_12_decrypter_openssl.cc',
'quic/crypto/aes_128_gcm_12_encrypter.h',
'quic/crypto/aes_128_gcm_12_encrypter_openssl.cc',
- 'quic/crypto/chacha20_poly1305_decrypter.h',
- 'quic/crypto/chacha20_poly1305_decrypter_openssl.cc',
- 'quic/crypto/chacha20_poly1305_encrypter.h',
- 'quic/crypto/chacha20_poly1305_encrypter_openssl.cc',
'quic/crypto/chacha20_poly1305_rfc7539_decrypter.h',
'quic/crypto/chacha20_poly1305_rfc7539_decrypter_openssl.cc',
'quic/crypto/chacha20_poly1305_rfc7539_encrypter.h',
@@ -289,6 +292,7 @@
'quic/crypto/null_encrypter.h',
'quic/crypto/p256_key_exchange.h',
'quic/crypto/p256_key_exchange_openssl.cc',
+ 'quic/crypto/proof_source.cc',
'quic/crypto/proof_source.h',
'quic/crypto/proof_verifier.h',
'quic/crypto/proof_verifier_chromium.cc',
@@ -322,11 +326,11 @@
'quic/p2p/quic_p2p_stream.h',
'quic/port_suggester.cc',
'quic/port_suggester.h',
- 'quic/quic_ack_listener_interface.h',
'quic/quic_address_mismatch.cc',
'quic/quic_address_mismatch.h',
'quic/quic_alarm.cc',
'quic/quic_alarm.h',
+ 'quic/quic_arena_scoped_ptr.h',
'quic/quic_bandwidth.cc',
'quic/quic_bandwidth.h',
'quic/quic_bug_tracker.h',
@@ -345,12 +349,14 @@
'quic/quic_crypto_stream.h',
'quic/quic_chromium_connection_helper.cc',
'quic/quic_chromium_connection_helper.h',
+ 'quic/quic_chromium_packet_reader.cc',
+ 'quic/quic_chromium_packet_reader.h',
+ 'quic/quic_chromium_packet_writer.cc',
+ 'quic/quic_chromium_packet_writer.h',
'quic/quic_data_reader.cc',
'quic/quic_data_reader.h',
'quic/quic_data_writer.cc',
'quic/quic_data_writer.h',
- 'quic/quic_default_packet_writer.cc',
- 'quic/quic_default_packet_writer.h',
'quic/quic_fec_group.cc',
'quic/quic_fec_group.h',
'quic/quic_fec_group_interface.cc',
@@ -367,12 +373,11 @@
'quic/quic_multipath_received_packet_manager.h',
'quic/quic_multipath_transmissions_map.cc',
'quic/quic_multipath_transmissions_map.h',
+ 'quic/quic_one_block_arena.h',
'quic/quic_packet_creator.cc',
'quic/quic_packet_creator.h',
'quic/quic_packet_generator.cc',
'quic/quic_packet_generator.h',
- 'quic/quic_packet_reader.cc',
- 'quic/quic_packet_reader.h',
'quic/quic_packet_writer.h',
'quic/quic_protocol.cc',
'quic/quic_protocol.h',
@@ -392,6 +397,8 @@
'quic/quic_socket_address_coder.h',
'quic/quic_stream_sequencer.cc',
'quic/quic_stream_sequencer.h',
+ 'quic/quic_stream_sequencer_buffer.cc',
+ 'quic/quic_stream_sequencer_buffer.h',
'quic/quic_stream_sequencer_buffer_interface.h',
'quic/quic_sustained_bandwidth_recorder.cc',
'quic/quic_sustained_bandwidth_recorder.h',
@@ -408,8 +415,6 @@
'quic/quic_write_blocked_list.h',
'quic/reliable_quic_stream.cc',
'quic/reliable_quic_stream.h',
- 'quic/stream_sequencer_buffer.cc',
- 'quic/stream_sequencer_buffer.h',
],
'net_non_nacl_sources': [
'android/cert_verify_result_android.cc',
@@ -564,6 +569,8 @@
'cert/cert_verify_proc.h',
'cert/cert_verify_proc_android.cc',
'cert/cert_verify_proc_android.h',
+ 'cert/cert_verify_proc_ios.cc',
+ 'cert/cert_verify_proc_ios.h',
'cert/cert_verify_proc_mac.cc',
'cert/cert_verify_proc_mac.h',
'cert/cert_verify_proc_nss.cc',
@@ -623,6 +630,7 @@
'cert/x509_certificate_ios.cc',
'cert/x509_certificate_mac.cc',
'cert/x509_certificate_nss.cc',
+ 'cert/x509_certificate_openssl_ios.cc',
'cert/x509_certificate_win.cc',
'cert/x509_util_android.cc',
'cert/x509_util_android.h',
@@ -721,8 +729,6 @@
'disk_cache/memory/mem_backend_impl.h',
'disk_cache/memory/mem_entry_impl.cc',
'disk_cache/memory/mem_entry_impl.h',
- 'disk_cache/memory/mem_rankings.cc',
- 'disk_cache/memory/mem_rankings.h',
'disk_cache/net_log_parameters.cc',
'disk_cache/net_log_parameters.h',
'disk_cache/simple/simple_backend_impl.cc',
@@ -824,10 +830,14 @@
'filter/gzip_header.h',
'filter/sdch_filter.cc',
'filter/sdch_filter.h',
+ 'http/bidirectional_stream.cc',
+ 'http/bidirectional_stream.h',
+ 'http/bidirectional_stream_impl.cc',
+ 'http/bidirectional_stream_impl.h',
+ 'http/bidirectional_stream_request_info.cc',
+ 'http/bidirectional_stream_request_info.h',
'http/des.cc',
'http/des.h',
- 'http/disk_based_cert_cache.cc',
- 'http/disk_based_cert_cache.h',
'http/disk_cache_based_quic_server_info.cc',
'http/disk_cache_based_quic_server_info.h',
'http/failing_http_transaction_factory.cc',
@@ -991,14 +1001,14 @@
'proxy/proxy_server_mac.cc',
'proxy/proxy_service.cc',
'proxy/proxy_service.h',
+ 'quic/bidirectional_stream_quic_impl.cc',
+ 'quic/bidirectional_stream_quic_impl.h',
'quic/crypto/aead_base_decrypter_nss.cc',
'quic/crypto/aead_base_encrypter_nss.cc',
'quic/crypto/aes_128_gcm_12_decrypter_nss.cc',
'quic/crypto/aes_128_gcm_12_encrypter_nss.cc',
'quic/crypto/cert_compressor.cc',
'quic/crypto/cert_compressor.h',
- 'quic/crypto/chacha20_poly1305_decrypter_nss.cc',
- 'quic/crypto/chacha20_poly1305_encrypter_nss.cc',
'quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc',
'quic/crypto/chacha20_poly1305_rfc7539_encrypter_nss.cc',
'quic/crypto/channel_id_nss.cc',
@@ -1006,6 +1016,8 @@
'quic/crypto/proof_source_chromium.h',
'quic/crypto/proof_source_chromium_nss.cc',
'quic/crypto/proof_source_chromium_openssl.cc',
+ 'quic/crypto/quic_compressed_certs_cache.cc',
+ 'quic/crypto/quic_compressed_certs_cache.h',
'quic/crypto/quic_crypto_client_config.cc',
'quic/crypto/quic_crypto_client_config.h',
'quic/crypto/quic_crypto_server_config.cc',
@@ -1018,6 +1030,10 @@
'quic/quic_chromium_client_stream.h',
'quic/quic_client_session_base.cc',
'quic/quic_client_session_base.h',
+ 'quic/quic_client_promised_info.cc',
+ 'quic/quic_client_promised_info.h',
+ 'quic/quic_client_push_promise_index.cc',
+ 'quic/quic_client_push_promise_index.h',
'quic/quic_crypto_client_stream.cc',
'quic/quic_crypto_client_stream.h',
'quic/quic_crypto_client_stream_factory.cc',
@@ -1081,6 +1097,7 @@
'socket/tcp_client_socket.h',
'socket/tcp_server_socket.cc',
'socket/tcp_server_socket.h',
+ 'socket/tcp_socket.cc',
'socket/tcp_socket.h',
'socket/tcp_socket_posix.cc',
'socket/tcp_socket_posix.h',
@@ -1098,6 +1115,8 @@
'socket/websocket_transport_client_socket_pool.h',
'socket/websocket_transport_connect_sub_job.cc',
'socket/websocket_transport_connect_sub_job.h',
+ 'spdy/bidirectional_stream_spdy_impl.cc',
+ 'spdy/bidirectional_stream_spdy_impl.h',
'spdy/buffered_spdy_framer.cc',
'spdy/buffered_spdy_framer.h',
'spdy/fuzzing/hpack_fuzz_util.cc',
@@ -1122,6 +1141,9 @@
'spdy/hpack/hpack_output_stream.h',
'spdy/hpack/hpack_static_table.cc',
'spdy/hpack/hpack_static_table.h',
+ 'spdy/http2_write_scheduler.h',
+ 'spdy/http2_priority_dependencies.h',
+ 'spdy/http2_priority_dependencies.cc',
'spdy/priority_write_scheduler.h',
'spdy/spdy_alt_svc_wire_format.cc',
'spdy/spdy_alt_svc_wire_format.h',
@@ -1149,7 +1171,6 @@
'spdy/spdy_pinnable_buffer_piece.h',
'spdy/spdy_prefixed_buffer_reader.cc',
'spdy/spdy_prefixed_buffer_reader.h',
- 'spdy/spdy_priority_tree.h',
'spdy/spdy_protocol.cc',
'spdy/spdy_protocol.h',
'spdy/spdy_proxy_client_socket.cc',
@@ -1185,8 +1206,11 @@
'ssl/ssl_platform_key_task_runner.cc',
'ssl/ssl_platform_key_task_runner.h',
'ssl/ssl_platform_key_win.cc',
+ 'ssl/test_ssl_private_key.cc',
+ 'ssl/test_ssl_private_key.h',
'ssl/threaded_ssl_private_key.cc',
'ssl/threaded_ssl_private_key.h',
+ 'ssl/token_binding_nss.cc',
'third_party/mozilla_security_manager/nsKeygenHandler.cpp',
'third_party/mozilla_security_manager/nsKeygenHandler.h',
'third_party/mozilla_security_manager/nsNSSCertificateDB.cpp',
@@ -1284,6 +1308,19 @@
'url_request/view_cache_helper.h',
'url_request/websocket_handshake_userdata_key.cc',
'url_request/websocket_handshake_userdata_key.h',
+
+ # WebSockets headers are included net/http files. Since net/http can be
+ # built without linking net/websockets code, the uses of the websockets
+ # headers from url_request are carefully written not to introduce link-
+ # time dependencies.
+ #
+ # To make "gn check" validate the header usage properly, these are the
+ # websocket headers needed by the shared net code, which are duplicated
+ # unconditionally here from the conditional websockets list below.
+ 'websockets/websocket_handshake_stream_base.h',
+ 'websockets/websocket_stream.h',
+ 'websockets/websocket_handshake_request_info.h',
+ 'websockets/websocket_handshake_response_info.h',
],
'net_extras_sources': [
'extras/sqlite/cookie_crypto_delegate.h',
@@ -1325,12 +1362,12 @@
'base/lookup_string_in_fixed_set_unittest.cc',
'base/mime_sniffer_unittest.cc',
'base/mime_util_unittest.cc',
- 'base/net_util_unittest.cc',
'base/network_activity_monitor_unittest.cc',
'base/network_change_notifier_unittest.cc',
'base/network_change_notifier_win_unittest.cc',
'base/network_interfaces_unittest.cc',
'base/network_quality_estimator_unittest.cc',
+ 'base/parse_number_unittest.cc',
'base/port_util_unittest.cc',
'base/prioritized_dispatcher_unittest.cc',
'base/priority_queue_unittest.cc',
@@ -1340,6 +1377,8 @@
'base/stale_while_revalidate_experiment_domains_unittest.cc',
'base/static_cookie_policy_unittest.cc',
'base/test_completion_callback_unittest.cc',
+ 'base/test_proxy_delegate.cc',
+ 'base/test_proxy_delegate.h',
'base/upload_bytes_element_reader_unittest.cc',
'base/upload_file_element_reader_unittest.cc',
'base/url_util_unittest.cc',
@@ -1355,11 +1394,15 @@
'cert/internal/certificate_policies_unittest.cc',
'cert/internal/extended_key_usage_unittest.cc',
'cert/internal/name_constraints_unittest.cc',
+ 'cert/internal/nist_pkits_unittest.h',
'cert/internal/parse_certificate_unittest.cc',
+ 'cert/internal/parse_name_unittest.cc',
+ 'cert/internal/parse_ocsp_unittest.cc',
'cert/internal/signature_algorithm_unittest.cc',
'cert/internal/test_helpers.cc',
'cert/internal/test_helpers.h',
'cert/internal/verify_certificate_chain_unittest.cc',
+ 'cert/internal/verify_certificate_chain_pkits_unittest.cc',
'cert/internal/verify_name_match_unittest.cc',
'cert/internal/verify_signed_data_unittest.cc',
'cert/jwk_serializer_unittest.cc',
@@ -1369,7 +1412,6 @@
'cert/nss_cert_database_unittest.cc',
'cert/nss_profile_filter_chromeos_unittest.cc',
'cert/pem_tokenizer_unittest.cc',
- 'cert/sha256_legacy_support_win_unittest.cc',
'cert/signed_certificate_timestamp_unittest.cc',
'cert/test_root_certs_unittest.cc',
'cert/x509_cert_types_unittest.cc',
@@ -1380,6 +1422,7 @@
'cookies/canonical_cookie_unittest.cc',
'cookies/cookie_constants_unittest.cc',
'cookies/cookie_monster_unittest.cc',
+ 'cookies/cookie_store_unittest.cc',
'cookies/cookie_util_unittest.cc',
'cookies/parsed_cookie_unittest.cc',
'der/input_unittest.cc',
@@ -1443,7 +1486,6 @@
'ftp/ftp_util_unittest.cc',
'http/bidirectional_stream_unittest.cc',
'http/des_unittest.cc',
- 'http/disk_based_cert_cache_unittest.cc',
'http/disk_cache_based_quic_server_info_unittest.cc',
'http/http_auth_cache_unittest.cc',
'http/http_auth_challenge_tokenizer_unittest.cc',
@@ -1525,6 +1567,7 @@
'proxy/proxy_server_unittest.cc',
'proxy/proxy_service_mojo_unittest.cc',
'proxy/proxy_service_unittest.cc',
+ 'quic/bidirectional_stream_quic_impl_unittest.cc',
'quic/congestion_control/cubic_bytes_test.cc',
'quic/congestion_control/cubic_test.cc',
'quic/congestion_control/general_loss_algorithm_test.cc',
@@ -1534,15 +1577,11 @@
'quic/congestion_control/rtt_stats_test.cc',
'quic/congestion_control/send_algorithm_simulator.cc',
'quic/congestion_control/send_algorithm_simulator.h',
- 'quic/congestion_control/tcp_cubic_bytes_sender_test.cc',
- 'quic/congestion_control/tcp_cubic_sender_test.cc',
- 'quic/congestion_control/tcp_loss_algorithm_test.cc',
- 'quic/congestion_control/time_loss_algorithm_test.cc',
+ 'quic/congestion_control/tcp_cubic_sender_bytes_test.cc',
+ 'quic/congestion_control/tcp_cubic_sender_packets_test.cc',
'quic/crypto/aes_128_gcm_12_decrypter_test.cc',
'quic/crypto/aes_128_gcm_12_encrypter_test.cc',
'quic/crypto/cert_compressor_test.cc',
- 'quic/crypto/chacha20_poly1305_decrypter_test.cc',
- 'quic/crypto/chacha20_poly1305_encrypter_test.cc',
'quic/crypto/chacha20_poly1305_rfc7539_decrypter_test.cc',
'quic/crypto/chacha20_poly1305_rfc7539_encrypter_test.cc',
'quic/crypto/channel_id_test.cc',
@@ -1560,6 +1599,7 @@
'quic/crypto/proof_test.cc',
'quic/crypto/proof_verifier_chromium_test.cc',
'quic/crypto/properties_based_quic_server_info_test.cc',
+ 'quic/crypto/quic_compressed_certs_cache_test.cc',
'quic/crypto/quic_crypto_client_config_test.cc',
'quic/crypto/quic_crypto_server_config_test.cc',
'quic/crypto/quic_random_test.cc',
@@ -1572,10 +1612,12 @@
'quic/port_suggester_unittest.cc',
'quic/quic_address_mismatch_test.cc',
'quic/quic_alarm_test.cc',
+ 'quic/quic_arena_scoped_ptr_test.cc',
'quic/quic_bandwidth_test.cc',
'quic/quic_chromium_client_session_test.cc',
'quic/quic_chromium_client_stream_test.cc',
'quic/quic_chromium_connection_helper_test.cc',
+ 'quic/quic_client_push_promise_index_test.cc',
'quic/quic_clock_test.cc',
'quic/quic_config_test.cc',
'quic/quic_connection_logger_unittest.cc',
@@ -1593,6 +1635,7 @@
'quic/quic_multipath_received_packet_manager_test.cc',
'quic/quic_multipath_transmissions_map_test.cc',
'quic/quic_network_transaction_unittest.cc',
+ 'quic/quic_one_block_arena_test.cc',
'quic/quic_packet_creator_test.cc',
'quic/quic_packet_generator_test.cc',
'quic/quic_protocol_test.cc',
@@ -1614,7 +1657,7 @@
'quic/quic_write_blocked_list_test.cc',
'quic/reliable_quic_stream_test.cc',
'quic/spdy_utils_test.cc',
- 'quic/stream_sequencer_buffer_test.cc',
+ 'quic/quic_stream_sequencer_buffer_test.cc',
'quic/test_tools/crypto_test_utils.cc',
'quic/test_tools/crypto_test_utils.h',
'quic/test_tools/crypto_test_utils_chromium.cc',
@@ -1628,8 +1671,12 @@
'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',
'quic/test_tools/mock_quic_dispatcher.h',
+ 'quic/test_tools/mock_quic_spdy_client_stream.cc',
+ 'quic/test_tools/mock_quic_spdy_client_stream.h',
'quic/test_tools/mock_random.cc',
'quic/test_tools/mock_random.h',
'quic/test_tools/quic_chromium_client_session_peer.cc',
@@ -1675,10 +1722,6 @@
'quic/test_tools/test_task_runner.cc',
'quic/test_tools/test_task_runner.h',
'sdch/sdch_owner_unittest.cc',
- 'server/http_connection_unittest.cc',
- 'server/http_server_response_info_unittest.cc',
- 'server/http_server_unittest.cc',
- 'server/web_socket_encoder_unittest.cc',
'socket/client_socket_pool_base_unittest.cc',
'socket/mock_client_socket_pool_manager.cc',
'socket/mock_client_socket_pool_manager.h',
@@ -1686,7 +1729,6 @@
'socket/socks5_client_socket_unittest.cc',
'socket/socks_client_socket_pool_unittest.cc',
'socket/socks_client_socket_unittest.cc',
- 'socket/ssl_client_socket_openssl_unittest.cc',
'socket/ssl_client_socket_pool_unittest.cc',
'socket/ssl_client_socket_unittest.cc',
'socket/ssl_server_socket_unittest.cc',
@@ -1713,6 +1755,8 @@
'spdy/hpack/hpack_output_stream_test.cc',
'spdy/hpack/hpack_round_trip_test.cc',
'spdy/hpack/hpack_static_table_test.cc',
+ 'spdy/http2_write_scheduler_test.cc',
+ 'spdy/http2_priority_dependencies_unittest.cc',
'spdy/mock_spdy_framer_visitor.cc',
'spdy/mock_spdy_framer_visitor.h',
'spdy/priority_write_scheduler_test.cc',
@@ -1728,7 +1772,6 @@
'spdy/spdy_network_transaction_unittest.cc',
'spdy/spdy_pinnable_buffer_piece_test.cc',
'spdy/spdy_prefixed_buffer_reader_test.cc',
- 'spdy/spdy_priority_tree_test.cc',
'spdy/spdy_protocol_test.cc',
'spdy/spdy_proxy_client_socket_unittest.cc',
'spdy/spdy_read_queue_unittest.cc',
@@ -1766,6 +1809,7 @@
'test/run_all_unittests.cc',
'test/scoped_disable_exit_on_dfatal.cc',
'test/scoped_disable_exit_on_dfatal.h',
+ 'third_party/nist-pkits/pkits_testcases-inl.h',
'tools/balsa/balsa_frame_test.cc',
'tools/balsa/balsa_headers_test.cc',
'tools/quic/quic_simple_client_test.cc',
@@ -1780,6 +1824,7 @@
'url_request/url_request_backoff_manager_unittest.cc',
'url_request/url_request_context_builder_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',
'url_request/url_request_filter_unittest.cc',
'url_request/url_request_ftp_job_unittest.cc',
@@ -1793,27 +1838,6 @@
'url_request/url_request_throttler_unittest.cc',
'url_request/url_request_unittest.cc',
'url_request/view_cache_helper_unittest.cc',
- 'websockets/websocket_basic_stream_test.cc',
- 'websockets/websocket_channel_test.cc',
- 'websockets/websocket_deflate_parameters_test.cc',
- 'websockets/websocket_deflate_predictor_impl_test.cc',
- 'websockets/websocket_deflate_stream_test.cc',
- 'websockets/websocket_deflater_test.cc',
- 'websockets/websocket_end_to_end_test.cc',
- 'websockets/websocket_errors_test.cc',
- 'websockets/websocket_extension_parser_test.cc',
- 'websockets/websocket_extension_test.cc',
- 'websockets/websocket_frame_parser_test.cc',
- 'websockets/websocket_frame_test.cc',
- 'websockets/websocket_handshake_challenge_test.cc',
- 'websockets/websocket_handshake_stream_create_helper_test.cc',
- 'websockets/websocket_inflater_test.cc',
- 'websockets/websocket_stream_cookie_test.cc',
- 'websockets/websocket_stream_create_test_base.cc',
- 'websockets/websocket_stream_create_test_base.h',
- 'websockets/websocket_stream_test.cc',
- 'websockets/websocket_test_util.cc',
- 'websockets/websocket_test_util.h',
],
'net_linux_test_sources': [
'quic/quic_end_to_end_unittest.cc',
@@ -1858,6 +1882,33 @@
'tools/quic/test_tools/simple_client.cc',
'tools/quic/test_tools/simple_client.h',
],
+ 'net_websockets_test_sources': [
+ 'server/http_connection_unittest.cc',
+ 'server/http_server_response_info_unittest.cc',
+ 'server/http_server_unittest.cc',
+ 'server/web_socket_encoder_unittest.cc',
+ 'websockets/websocket_basic_stream_test.cc',
+ 'websockets/websocket_channel_test.cc',
+ 'websockets/websocket_deflate_parameters_test.cc',
+ 'websockets/websocket_deflate_predictor_impl_test.cc',
+ 'websockets/websocket_deflate_stream_test.cc',
+ 'websockets/websocket_deflater_test.cc',
+ 'websockets/websocket_end_to_end_test.cc',
+ 'websockets/websocket_errors_test.cc',
+ 'websockets/websocket_extension_parser_test.cc',
+ 'websockets/websocket_extension_test.cc',
+ 'websockets/websocket_frame_parser_test.cc',
+ 'websockets/websocket_frame_test.cc',
+ 'websockets/websocket_handshake_challenge_test.cc',
+ 'websockets/websocket_handshake_stream_create_helper_test.cc',
+ 'websockets/websocket_inflater_test.cc',
+ 'websockets/websocket_stream_cookie_test.cc',
+ 'websockets/websocket_stream_create_test_base.cc',
+ 'websockets/websocket_stream_create_test_base.h',
+ 'websockets/websocket_stream_test.cc',
+ 'websockets/websocket_test_util.cc',
+ 'websockets/websocket_test_util.h',
+ ],
'net_base_mac_ios_sources': [
'base/mac/url_conversions.h',
'base/mac/url_conversions.mm',
@@ -1910,16 +1961,6 @@
"url_request/url_request_ftp_job.cc",
"url_request/url_request_ftp_job.h",
],
- 'net_bidirectional_stream_sources': [
- 'http/bidirectional_stream.cc',
- 'http/bidirectional_stream.h',
- 'http/bidirectional_stream_job.cc',
- 'http/bidirectional_stream_job.h',
- 'http/bidirectional_stream_request_info.cc',
- 'http/bidirectional_stream_request_info.h',
- 'spdy/bidirectional_stream_spdy_job.cc',
- 'spdy/bidirectional_stream_spdy_job.h',
- ],
'net_websockets_sources': [
"websockets/websocket_basic_handshake_stream.cc",
"websockets/websocket_basic_handshake_stream.h",
@@ -1963,17 +2004,5 @@
"websockets/websocket_stream.cc",
"websockets/websocket_stream.h",
],
- 'net_docs_script': 'tools/net_docs/net_docs.py',
- 'net_docs_sources': [
- 'README.md',
- 'docs/bug-triage.md',
- 'docs/bug-triage-labels.md',
- 'docs/bug-triage-suggested-workflow.md',
- 'docs/code-patterns.md',
- 'docs/crash-course-in-net-internals.md',
- 'docs/life-of-a-url-request.md',
- 'sdch/README.md',
- ],
- 'net_docs_output_dir': '<(PRODUCT_DIR)/net/docs',
}
}
diff --git a/chromium/net/net_common.gypi b/chromium/net/net_common.gypi
index a6da6a899e4..f5e56c4f4c9 100644
--- a/chromium/net/net_common.gypi
+++ b/chromium/net/net_common.gypi
@@ -8,14 +8,12 @@
'variables': { 'enable_wexit_time_destructors': 1, },
'dependencies': [
'../base/base.gyp:base',
- '../base/base.gyp:base_prefs',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../crypto/crypto.gyp:crypto',
'../sdch/sdch.gyp:sdch',
'../third_party/protobuf/protobuf.gyp:protobuf_lite',
'../third_party/zlib/zlib.gyp:zlib',
'net_derived_sources',
- 'net_features',
'net_quic_proto',
'net_resources',
],
@@ -96,9 +94,6 @@
['disable_ftp_support!=1', {
'sources': ['<@(net_ftp_support_sources)']
}],
- ['enable_bidirectional_stream==1', {
- 'sources': ['<@(net_bidirectional_stream_sources)']
- }],
['enable_built_in_dns==1', {
'defines': [
'ENABLE_BUILT_IN_DNS',
@@ -118,13 +113,12 @@
'cert/ct_objects_extractor_nss.cc',
'cert/jwk_serializer_nss.cc',
'cert/scoped_nss_types.h',
+ 'cert/x509_certificate_ios.cc',
'cert/x509_util_nss.cc',
'quic/crypto/aead_base_decrypter_nss.cc',
'quic/crypto/aead_base_encrypter_nss.cc',
'quic/crypto/aes_128_gcm_12_decrypter_nss.cc',
'quic/crypto/aes_128_gcm_12_encrypter_nss.cc',
- 'quic/crypto/chacha20_poly1305_decrypter_nss.cc',
- 'quic/crypto/chacha20_poly1305_encrypter_nss.cc',
'quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc',
'quic/crypto/chacha20_poly1305_rfc7539_encrypter_nss.cc',
'quic/crypto/channel_id_nss.cc',
@@ -136,10 +130,21 @@
'socket/ssl_client_socket_nss.h',
'socket/ssl_server_socket_nss.cc',
'socket/ssl_server_socket_nss.h',
+ 'ssl/token_binding_nss.cc',
],
'dependencies': [
'../third_party/boringssl/boringssl.gyp:boringssl',
],
+ 'conditions': [
+ ['chromecast==1 and use_nss_certs==1', {
+ 'sources': [
+ 'ssl/ssl_platform_key_chromecast.cc',
+ ],
+ 'sources!': [
+ 'ssl/ssl_platform_key_nss.cc',
+ ],
+ }],
+ ],
},
{ # else !use_openssl: remove the unneeded files and depend on NSS.
'sources!': [
@@ -152,8 +157,6 @@
'quic/crypto/aead_base_encrypter_openssl.cc',
'quic/crypto/aes_128_gcm_12_decrypter_openssl.cc',
'quic/crypto/aes_128_gcm_12_encrypter_openssl.cc',
- 'quic/crypto/chacha20_poly1305_decrypter_openssl.cc',
- 'quic/crypto/chacha20_poly1305_encrypter_openssl.cc',
'quic/crypto/chacha20_poly1305_rfc7539_decrypter_openssl.cc',
'quic/crypto/chacha20_poly1305_rfc7539_encrypter_openssl.cc',
'quic/crypto/channel_id_openssl.cc',
@@ -177,12 +180,15 @@
'ssl/ssl_platform_key_nss.cc',
'ssl/ssl_platform_key_task_runner.cc',
'ssl/ssl_platform_key_task_runner.h',
+ 'ssl/test_ssl_private_key.cc',
+ 'ssl/test_ssl_private_key.h',
'ssl/threaded_ssl_private_key.cc',
'ssl/threaded_ssl_private_key.h',
+ 'ssl/token_binding_openssl.cc',
],
},
],
- [ 'use_nss_certs == 1 or OS == "ios" or use_openssl == 0', {
+ [ 'use_nss_verifier == 1', {
'conditions': [
# Pull in the bundled or system NSS as appropriate.
[ 'desktop_linux == 1 or chromeos == 1', {
@@ -253,19 +259,13 @@
'base/crypto_module_nss.cc',
'base/keygen_handler_nss.cc',
'cert/cert_database_nss.cc',
- 'cert/cert_verify_proc_nss.cc',
- 'cert/cert_verify_proc_nss.h',
'cert/nss_cert_database.cc',
'cert/nss_cert_database.h',
'cert/nss_cert_database_chromeos.cc',
'cert/nss_cert_database_chromeos.h',
'cert/nss_profile_filter_chromeos.cc',
'cert/nss_profile_filter_chromeos.h',
- 'cert/test_root_certs_nss.cc',
'cert/x509_certificate_nss.cc',
- 'cert/x509_util_nss_certs.cc',
- 'cert_net/nss_ocsp.cc',
- 'cert_net/nss_ocsp.h',
'ssl/client_cert_store_nss.cc',
'ssl/client_cert_store_nss.h',
'ssl/client_key_store.cc',
@@ -280,6 +280,17 @@
],
},
],
+ [ 'use_nss_verifier != 1', {
+ 'sources!': [
+ 'cert/cert_verify_proc_nss.cc',
+ 'cert/cert_verify_proc_nss.h',
+ 'cert/test_root_certs_nss.cc',
+ 'cert/x509_util_nss_certs.cc',
+ 'cert_net/nss_ocsp.cc',
+ 'cert_net/nss_ocsp.h',
+ ],
+ },
+ ],
# client_cert_store_nss.c requires NSS_CmpCertChainWCANames from NSS's
# libssl, but our bundled copy is not built in OpenSSL ports. Pull that
# file in directly.
@@ -288,6 +299,19 @@
'third_party/nss/ssl/cmpcert.c',
],
}],
+ [ 'OS == "ios" and use_nss_verifier == 0', {
+ 'sources!': [
+ 'cert/x509_util_ios.cc',
+ 'cert/x509_util_ios.h',
+ ],
+ }],
+ [ 'OS == "ios" and use_nss_verifier == 1', {
+ 'sources!': [
+ 'cert/cert_verify_proc_ios.cc',
+ 'cert/cert_verify_proc_ios.h',
+ 'cert/x509_certificate_openssl_ios.cc',
+ ],
+ }],
[ 'enable_websockets == 1', {
'sources': ['<@(net_websockets_sources)']
}],
@@ -311,6 +335,34 @@
],
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [4267, ],
+ 'all_dependent_settings': {
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'AdditionalDependencies': [
+ 'crypt32.lib',
+ 'dhcpcsvc.lib',
+ 'iphlpapi.lib',
+ 'rpcrt4.lib',
+ 'secur32.lib',
+ 'urlmon.lib',
+ 'winhttp.lib',
+ ],
+ },
+ },
+ },
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'AdditionalDependencies': [
+ 'crypt32.lib',
+ 'dhcpcsvc.lib',
+ 'iphlpapi.lib',
+ 'rpcrt4.lib',
+ 'secur32.lib',
+ 'urlmon.lib',
+ 'winhttp.lib',
+ ],
+ },
+ },
}, { # else: OS != "win"
'sources!': [
'base/winsock_init.cc',
@@ -401,19 +453,14 @@
['include', '^base/network_interfaces_mac\\.cc$'],
['include', '^base/network_interfaces_mac\\.h$'],
['include', '^base/platform_mime_util_mac\\.mm$'],
- # The iOS implementation only partially uses NSS and thus does not
- # defines |use_nss_certs|. In particular the |USE_NSS_CERTS|
- # preprocessor definition is not used. The following files are needed
- # though:
- ['include', '^cert/cert_verify_proc_nss\\.cc$'],
- ['include', '^cert/cert_verify_proc_nss\\.h$'],
- ['include', '^cert/test_root_certs_nss\\.cc$'],
- ['include', '^cert/x509_util_nss_certs\\.cc$'],
- ['include', '^cert_net/nss_ocsp\\.cc$'],
- ['include', '^cert_net/nss_ocsp\\.h$'],
['include', '^proxy/proxy_resolver_mac\\.cc$'],
['include', '^proxy/proxy_server_mac\\.cc$'],
],
}],
+ ['OS == "ios" and <(use_nss_verifier) == 0', {
+ 'sources/': [
+ ['include', '^cert/test_root_certs_mac\\.cc$'],
+ ],
+ }],
],
}
diff --git a/chromium/net/net_unittests.isolate b/chromium/net/net_unittests.isolate
index 4c7733b7177..7d00f054b60 100644
--- a/chromium/net/net_unittests.isolate
+++ b/chromium/net/net_unittests.isolate
@@ -7,6 +7,8 @@
'variables': {
'files': [
'data/',
+ 'third_party/nist-pkits/certs/',
+ 'third_party/nist-pkits/crls/',
],
},
}],
diff --git a/chromium/net/net_unittests_apk.isolate b/chromium/net/net_unittests_apk.isolate
index b1e945beb95..07ef7280ca9 100644
--- a/chromium/net/net_unittests_apk.isolate
+++ b/chromium/net/net_unittests_apk.isolate
@@ -10,6 +10,7 @@
'variables': {
'command': [
'<(PRODUCT_DIR)/bin/run_net_unittests',
+ '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats',
],
'files': [
'../base/base.isolate',
diff --git a/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.cc b/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.cc
index 23c02df70fc..f4ff1e3b79f 100644
--- a/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.cc
+++ b/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.cc
@@ -8,6 +8,7 @@
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/memory/free_deleter.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task_runner.h"
@@ -20,7 +21,6 @@
#include <windows.h>
#include <winsock2.h>
#include <dhcpcsdk.h>
-#pragma comment(lib, "dhcpcsvc.lib")
namespace {
diff --git a/chromium/net/proxy/dhcp_proxy_script_fetcher_factory.h b/chromium/net/proxy/dhcp_proxy_script_fetcher_factory.h
index b017bb63c65..45734e37352 100644
--- a/chromium/net/proxy/dhcp_proxy_script_fetcher_factory.h
+++ b/chromium/net/proxy/dhcp_proxy_script_fetcher_factory.h
@@ -6,6 +6,7 @@
#define NET_PROXY_DHCP_SCRIPT_FETCHER_FACTORY_H_
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
diff --git a/chromium/net/proxy/dhcp_proxy_script_fetcher_win.cc b/chromium/net/proxy/dhcp_proxy_script_fetcher_win.cc
index 263b50f1fbc..f9463dde1c8 100644
--- a/chromium/net/proxy/dhcp_proxy_script_fetcher_win.cc
+++ b/chromium/net/proxy/dhcp_proxy_script_fetcher_win.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/memory/free_deleter.h"
#include "base/memory/scoped_ptr.h"
#include "base/profiler/scoped_tracker.h"
#include "base/threading/sequenced_worker_pool.h"
@@ -16,7 +17,6 @@
#include <winsock2.h>
#include <iphlpapi.h>
-#pragma comment(lib, "iphlpapi.lib")
namespace {
diff --git a/chromium/net/proxy/mojo_proxy_type_converters.cc b/chromium/net/proxy/mojo_proxy_type_converters.cc
index c927534d10b..2da740fa79e 100644
--- a/chromium/net/proxy/mojo_proxy_type_converters.cc
+++ b/chromium/net/proxy/mojo_proxy_type_converters.cc
@@ -15,39 +15,39 @@ namespace {
interfaces::ProxyScheme ProxySchemeToMojo(ProxyServer::Scheme scheme) {
switch (scheme) {
case ProxyServer::SCHEME_INVALID:
- return interfaces::PROXY_SCHEME_INVALID;
+ return interfaces::ProxyScheme::INVALID;
case ProxyServer::SCHEME_DIRECT:
- return interfaces::PROXY_SCHEME_DIRECT;
+ return interfaces::ProxyScheme::DIRECT;
case ProxyServer::SCHEME_HTTP:
- return interfaces::PROXY_SCHEME_HTTP;
+ return interfaces::ProxyScheme::HTTP;
case ProxyServer::SCHEME_SOCKS4:
- return interfaces::PROXY_SCHEME_SOCKS4;
+ return interfaces::ProxyScheme::SOCKS4;
case ProxyServer::SCHEME_SOCKS5:
- return interfaces::PROXY_SCHEME_SOCKS5;
+ return interfaces::ProxyScheme::SOCKS5;
case ProxyServer::SCHEME_HTTPS:
- return interfaces::PROXY_SCHEME_HTTPS;
+ return interfaces::ProxyScheme::HTTPS;
case ProxyServer::SCHEME_QUIC:
- return interfaces::PROXY_SCHEME_QUIC;
+ return interfaces::ProxyScheme::QUIC;
}
NOTREACHED();
- return interfaces::PROXY_SCHEME_INVALID;
+ return interfaces::ProxyScheme::INVALID;
}
ProxyServer::Scheme ProxySchemeFromMojo(interfaces::ProxyScheme scheme) {
switch (scheme) {
- case interfaces::PROXY_SCHEME_INVALID:
+ case interfaces::ProxyScheme::INVALID:
return ProxyServer::SCHEME_INVALID;
- case interfaces::PROXY_SCHEME_DIRECT:
+ case interfaces::ProxyScheme::DIRECT:
return ProxyServer::SCHEME_DIRECT;
- case interfaces::PROXY_SCHEME_HTTP:
+ case interfaces::ProxyScheme::HTTP:
return ProxyServer::SCHEME_HTTP;
- case interfaces::PROXY_SCHEME_SOCKS4:
+ case interfaces::ProxyScheme::SOCKS4:
return ProxyServer::SCHEME_SOCKS4;
- case interfaces::PROXY_SCHEME_SOCKS5:
+ case interfaces::ProxyScheme::SOCKS5:
return ProxyServer::SCHEME_SOCKS5;
- case interfaces::PROXY_SCHEME_HTTPS:
+ case interfaces::ProxyScheme::HTTPS:
return ProxyServer::SCHEME_HTTPS;
- case interfaces::PROXY_SCHEME_QUIC:
+ case interfaces::ProxyScheme::QUIC:
return ProxyServer::SCHEME_QUIC;
}
NOTREACHED();
@@ -65,8 +65,8 @@ TypeConverter<net::interfaces::ProxyServerPtr, net::ProxyServer>::Convert(
const net::ProxyServer& obj) {
net::interfaces::ProxyServerPtr server(net::interfaces::ProxyServer::New());
server->scheme = net::ProxySchemeToMojo(obj.scheme());
- if (server->scheme != net::interfaces::PROXY_SCHEME_DIRECT &&
- server->scheme != net::interfaces::PROXY_SCHEME_INVALID) {
+ if (server->scheme != net::interfaces::ProxyScheme::DIRECT &&
+ server->scheme != net::interfaces::ProxyScheme::INVALID) {
server->host = obj.host_port_pair().host();
server->port = obj.host_port_pair().port();
}
diff --git a/chromium/net/proxy/multi_threaded_proxy_resolver_unittest.cc b/chromium/net/proxy/multi_threaded_proxy_resolver_unittest.cc
index 29e49c34a80..5c29864acad 100644
--- a/chromium/net/proxy/multi_threaded_proxy_resolver_unittest.cc
+++ b/chromium/net/proxy/multi_threaded_proxy_resolver_unittest.cc
@@ -231,13 +231,7 @@ class MultiThreadedProxyResolverTest : public testing::Test {
scoped_ptr<ProxyResolver> resolver_;
};
-// Flaky on Android. See http://crbug.com/547786
-#if defined(OS_ANDROID)
-#define MAYBE_SingleThread_Basic DISABLED_SingleThread_Basic
-#else
-#define MAYBE_SingleThread_Basic SingleThread_Basic
-#endif
-TEST_F(MultiThreadedProxyResolverTest, MAYBE_SingleThread_Basic) {
+TEST_F(MultiThreadedProxyResolverTest, SingleThread_Basic) {
const size_t kNumThreads = 1u;
ASSERT_NO_FATAL_FAILURE(Init(kNumThreads));
diff --git a/chromium/net/proxy/parse_proxy_bypass_rules_fuzzer.cc b/chromium/net/proxy/parse_proxy_bypass_rules_fuzzer.cc
new file mode 100644
index 00000000000..1a9c63c816d
--- /dev/null
+++ b/chromium/net/proxy/parse_proxy_bypass_rules_fuzzer.cc
@@ -0,0 +1,16 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include "net/proxy/proxy_bypass_rules.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ net::ProxyBypassRules rules;
+ std::string input(data, data + size);
+ rules.ParseFromString(input);
+ return 0;
+}
diff --git a/chromium/net/proxy/parse_proxy_list_fuzzer.cc b/chromium/net/proxy/parse_proxy_list_fuzzer.cc
new file mode 100644
index 00000000000..048854966ac
--- /dev/null
+++ b/chromium/net/proxy/parse_proxy_list_fuzzer.cc
@@ -0,0 +1,16 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include "net/proxy/proxy_list.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ net::ProxyList list;
+ std::string input(data, data + size);
+ list.Set(input);
+ return 0;
+}
diff --git a/chromium/net/proxy/parse_proxy_list_pac_fuzzer.cc b/chromium/net/proxy/parse_proxy_list_pac_fuzzer.cc
new file mode 100644
index 00000000000..556773c36bd
--- /dev/null
+++ b/chromium/net/proxy/parse_proxy_list_pac_fuzzer.cc
@@ -0,0 +1,16 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include "net/proxy/proxy_list.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ net::ProxyList list;
+ std::string input(data, data + size);
+ list.SetFromPacString(input);
+ return 0;
+}
diff --git a/chromium/net/proxy/parse_proxy_rules_fuzzer.cc b/chromium/net/proxy/parse_proxy_rules_fuzzer.cc
new file mode 100644
index 00000000000..cd88cdd1a93
--- /dev/null
+++ b/chromium/net/proxy/parse_proxy_rules_fuzzer.cc
@@ -0,0 +1,16 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include "net/proxy/proxy_config.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ net::ProxyConfig::ProxyRules rules;
+ std::string input(data, data + size);
+ rules.ParseFromString(input);
+ return 0;
+}
diff --git a/chromium/net/proxy/proxy_bypass_rules.cc b/chromium/net/proxy/proxy_bypass_rules.cc
index be18edb7bb7..eafaa98cc05 100644
--- a/chromium/net/proxy/proxy_bypass_rules.cc
+++ b/chromium/net/proxy/proxy_bypass_rules.cc
@@ -6,14 +6,14 @@
#include "base/stl_util.h"
#include "base/strings/pattern.h"
-#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/base/host_port_pair.h"
-#include "net/base/ip_address_number.h"
-#include "net/base/net_util.h"
+#include "net/base/ip_address.h"
+#include "net/base/parse_number.h"
+#include "net/base/url_util.h"
namespace net {
@@ -84,13 +84,12 @@ class BypassIPBlockRule : public ProxyBypassRules::Rule {
// |ip_prefix| + |prefix_length| define the IP block to match.
BypassIPBlockRule(const std::string& description,
const std::string& optional_scheme,
- const IPAddressNumber& ip_prefix,
+ const IPAddress& ip_prefix,
size_t prefix_length_in_bits)
: description_(description),
optional_scheme_(optional_scheme),
ip_prefix_(ip_prefix),
- prefix_length_in_bits_(prefix_length_in_bits) {
- }
+ prefix_length_in_bits_(prefix_length_in_bits) {}
bool Matches(const GURL& url) const override {
if (!url.HostIsIPAddress())
@@ -100,13 +99,13 @@ class BypassIPBlockRule : public ProxyBypassRules::Rule {
return false; // Didn't match scheme expectation.
// Parse the input IP literal to a number.
- IPAddressNumber ip_number;
- if (!ParseIPLiteralToNumber(url.HostNoBrackets(), &ip_number))
+ IPAddress ip_address;
+ if (!ip_address.AssignFromIPLiteral(url.HostNoBrackets()))
return false;
// Test if it has the expected prefix.
- return IPNumberMatchesPrefix(ip_number, ip_prefix_,
- prefix_length_in_bits_);
+ return IPAddressMatchesPrefix(ip_address, ip_prefix_,
+ prefix_length_in_bits_);
}
std::string ToString() const override { return description_; }
@@ -121,7 +120,7 @@ class BypassIPBlockRule : public ProxyBypassRules::Rule {
private:
const std::string description_;
const std::string optional_scheme_;
- const IPAddressNumber ip_prefix_;
+ const IPAddress ip_prefix_;
const size_t prefix_length_in_bits_;
};
@@ -284,7 +283,7 @@ bool ProxyBypassRules::AddRuleFromStringInternal(
// If there is a forward slash in the input, it is probably a CIDR style
// mask.
if (raw.find('/') != std::string::npos) {
- IPAddressNumber ip_prefix;
+ IPAddress ip_prefix;
size_t prefix_length_in_bits;
if (!ParseCIDRBlock(raw, &ip_prefix, &prefix_length_in_bits))
@@ -301,6 +300,11 @@ bool ProxyBypassRules::AddRuleFromStringInternal(
std::string host;
int port;
if (ParseHostAndPort(raw, &host, &port)) {
+ // TODO(eroman): HostForURL() below DCHECKs() when |host| contains an
+ // embedded NULL.
+ if (host.find('\0') != std::string::npos)
+ return false;
+
// Note that HostPortPair is used to merely to convert any IPv6 literals to
// a URL-safe format that can be used by canonicalization below.
std::string bracketed_host = HostPortPair(host, 80).HostForURL();
@@ -313,13 +317,11 @@ bool ProxyBypassRules::AddRuleFromStringInternal(
// Otherwise assume we have <hostname-pattern>[:port].
std::string::size_type pos_colon = raw.rfind(':');
- host = raw;
port = -1;
if (pos_colon != std::string::npos) {
- if (!base::StringToInt(base::StringPiece(raw.begin() + pos_colon + 1,
- raw.end()),
- &port) ||
- (port < 0 || port > 0xFFFF)) {
+ if (!ParseNonNegativeDecimalInt(
+ base::StringPiece(raw.begin() + pos_colon + 1, raw.end()), &port) ||
+ port > 0xFFFF) {
return false; // Port was invalid.
}
raw = raw.substr(0, pos_colon);
diff --git a/chromium/net/proxy/proxy_bypass_rules_unittest.cc b/chromium/net/proxy/proxy_bypass_rules_unittest.cc
index c099ad62022..84cad71433c 100644
--- a/chromium/net/proxy/proxy_bypass_rules_unittest.cc
+++ b/chromium/net/proxy/proxy_bypass_rules_unittest.cc
@@ -97,6 +97,15 @@ TEST(ProxyBypassRulesTest, WildcardAtStart) {
EXPECT_FALSE(rules.Matches(GURL("https://www.google.org.com")));
}
+// Tests a codepath that parses hostnamepattern:port, where "port" is invalid
+// by containing a leading plus.
+TEST(ProxyBypassRulesTest, ParseInvalidPort) {
+ ProxyBypassRules rules;
+ EXPECT_TRUE(rules.AddRuleFromString("*.org:443"));
+ EXPECT_FALSE(rules.AddRuleFromString("*.com:+443"));
+ EXPECT_FALSE(rules.AddRuleFromString("*.com:-443"));
+}
+
TEST(ProxyBypassRulesTest, IPV4Address) {
ProxyBypassRules rules;
rules.ParseFromString("192.168.1.1");
diff --git a/chromium/net/proxy/proxy_config.cc b/chromium/net/proxy/proxy_config.cc
index 78d6ef3b9cf..ff05b63277d 100644
--- a/chromium/net/proxy/proxy_config.cc
+++ b/chromium/net/proxy/proxy_config.cc
@@ -42,6 +42,8 @@ ProxyConfig::ProxyRules::ProxyRules()
type(TYPE_NO_RULES) {
}
+ProxyConfig::ProxyRules::ProxyRules(const ProxyRules& other) = default;
+
ProxyConfig::ProxyRules::~ProxyRules() {
}
diff --git a/chromium/net/proxy/proxy_config.h b/chromium/net/proxy/proxy_config.h
index 2e91923a83c..68deafdffdb 100644
--- a/chromium/net/proxy/proxy_config.h
+++ b/chromium/net/proxy/proxy_config.h
@@ -49,6 +49,7 @@ class NET_EXPORT ProxyConfig {
// Note that the default of TYPE_NO_RULES results in direct connections
// being made when using this ProxyConfig.
ProxyRules();
+ ProxyRules(const ProxyRules& other);
~ProxyRules();
bool empty() const {
diff --git a/chromium/net/proxy/proxy_config_service_linux.cc b/chromium/net/proxy/proxy_config_service_linux.cc
index 139e30840dd..17747d96152 100644
--- a/chromium/net/proxy/proxy_config_service_linux.cc
+++ b/chromium/net/proxy/proxy_config_service_linux.cc
@@ -41,7 +41,7 @@
#include "url/url_canon.h"
#if defined(USE_GIO)
-#include "library_loaders/libgio.h"
+#include "library_loaders/libgio.h" // nogncheck
#endif // defined(USE_GIO)
namespace net {
@@ -85,7 +85,7 @@ std::string FixupProxyHostScheme(ProxyServer::Scheme scheme,
host = "socks5://" + host;
// If there is a trailing slash, remove it so |host| will parse correctly
// even if it includes a port number (since the slash is not numeric).
- if (host.length() && host[host.length() - 1] == '/')
+ if (!host.empty() && host.back() == '/')
host.resize(host.length() - 1);
return host;
}
diff --git a/chromium/net/proxy/proxy_config_service_win.cc b/chromium/net/proxy/proxy_config_service_win.cc
index 5ec2b0c261f..ef23711ad6f 100644
--- a/chromium/net/proxy/proxy_config_service_win.cc
+++ b/chromium/net/proxy/proxy_config_service_win.cc
@@ -21,8 +21,6 @@
#include "net/base/net_errors.h"
#include "net/proxy/proxy_config.h"
-#pragma comment(lib, "winhttp.lib")
-
namespace net {
namespace {
diff --git a/chromium/net/proxy/proxy_info.cc b/chromium/net/proxy/proxy_info.cc
index b659d671c22..75000791c52 100644
--- a/chromium/net/proxy/proxy_info.cc
+++ b/chromium/net/proxy/proxy_info.cc
@@ -15,6 +15,8 @@ ProxyInfo::ProxyInfo()
did_use_pac_script_(false) {
}
+ProxyInfo::ProxyInfo(const ProxyInfo& other) = default;
+
ProxyInfo::~ProxyInfo() {
}
diff --git a/chromium/net/proxy/proxy_info.h b/chromium/net/proxy/proxy_info.h
index 1dc7388b3ba..3d06a751647 100644
--- a/chromium/net/proxy/proxy_info.h
+++ b/chromium/net/proxy/proxy_info.h
@@ -22,6 +22,7 @@ namespace net {
class NET_EXPORT ProxyInfo {
public:
ProxyInfo();
+ ProxyInfo(const ProxyInfo& other);
~ProxyInfo();
// Default copy-constructor and assignment operator are OK!
diff --git a/chromium/net/proxy/proxy_list.cc b/chromium/net/proxy/proxy_list.cc
index a7b7aef82b1..5f627e0cb1e 100644
--- a/chromium/net/proxy/proxy_list.cc
+++ b/chromium/net/proxy/proxy_list.cc
@@ -19,6 +19,8 @@ namespace net {
ProxyList::ProxyList() {
}
+ProxyList::ProxyList(const ProxyList& other) = default;
+
ProxyList::~ProxyList() {
}
diff --git a/chromium/net/proxy/proxy_list.h b/chromium/net/proxy/proxy_list.h
index 82c637d0cc7..d128e18dd73 100644
--- a/chromium/net/proxy/proxy_list.h
+++ b/chromium/net/proxy/proxy_list.h
@@ -29,6 +29,7 @@ class ProxyServer;
class NET_EXPORT_PRIVATE ProxyList {
public:
ProxyList();
+ ProxyList(const ProxyList& other);
~ProxyList();
// Initializes the proxy list to a string containing one or more proxy servers
diff --git a/chromium/net/proxy/proxy_resolver_factory_mojo.cc b/chromium/net/proxy/proxy_resolver_factory_mojo.cc
index 4203eea39cd..2070cf9bef2 100644
--- a/chromium/net/proxy/proxy_resolver_factory_mojo.cc
+++ b/chromium/net/proxy/proxy_resolver_factory_mojo.cc
@@ -198,12 +198,10 @@ ProxyResolverMojo::Job::Job(ProxyResolverMojo* resolver,
results_(results),
callback_(callback),
binding_(this) {
- interfaces::ProxyResolverRequestClientPtr client_ptr;
- binding_.Bind(mojo::GetProxy(&client_ptr));
+ resolver_->mojo_proxy_resolver_ptr_->GetProxyForUrl(
+ mojo::String::From(url_), binding_.CreateInterfacePtrAndBind());
binding_.set_connection_error_handler(base::Bind(
&ProxyResolverMojo::Job::OnConnectionError, base::Unretained(this)));
- resolver_->mojo_proxy_resolver_ptr_->GetProxyForUrl(mojo::String::From(url_),
- std::move(client_ptr));
}
ProxyResolverMojo::Job::~Job() {
@@ -340,11 +338,9 @@ class ProxyResolverFactoryMojo::Job
callback_(callback),
binding_(this),
error_observer_(std::move(error_observer)) {
- interfaces::ProxyResolverFactoryRequestClientPtr client_ptr;
- binding_.Bind(mojo::GetProxy(&client_ptr));
on_delete_callback_runner_ = factory_->mojo_proxy_factory_->CreateResolver(
mojo::String::From(pac_script->utf16()), mojo::GetProxy(&resolver_ptr_),
- std::move(client_ptr));
+ binding_.CreateInterfacePtrAndBind());
resolver_ptr_.set_connection_error_handler(
base::Bind(&ProxyResolverFactoryMojo::Job::OnConnectionError,
base::Unretained(this)));
diff --git a/chromium/net/proxy/proxy_resolver_v8.cc b/chromium/net/proxy/proxy_resolver_v8.cc
index 80ae06b7e55..a0c9717baca 100644
--- a/chromium/net/proxy/proxy_resolver_v8.cc
+++ b/chromium/net/proxy/proxy_resolver_v8.cc
@@ -21,7 +21,7 @@
#include "gin/array_buffer.h"
#include "gin/public/isolate_holder.h"
#include "gin/v8_initializer.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/proxy/proxy_info.h"
#include "net/proxy/proxy_resolver_script.h"
@@ -244,26 +244,29 @@ bool GetHostnameArgument(const v8::FunctionCallbackInfo<v8::Value>& args,
return success;
}
-// Wrapper for passing around IP address strings and IPAddressNumber objects.
-struct IPAddress {
- IPAddress(const std::string& ip_string, const IPAddressNumber& ip_number)
- : string_value(ip_string),
- ip_address_number(ip_number) {
- }
+// Wrapper around an IP address that stores the original string as well as a
+// corresponding parsed IPAddress.
+
+// This struct is used as a helper for sorting IP address strings - the IP
+// literal is parsed just once and used as the sorting key, while also
+// preserving the original IP literal string.
+struct IPAddressSortingEntry {
+ IPAddressSortingEntry(const std::string& ip_string,
+ const IPAddress& ip_address)
+ : string_value(ip_string), ip_address(ip_address) {}
// Used for sorting IP addresses in ascending order in SortIpAddressList().
- // IP6 addresses are placed ahead of IPv4 addresses.
- bool operator<(const IPAddress& rhs) const {
- const IPAddressNumber& ip1 = this->ip_address_number;
- const IPAddressNumber& ip2 = rhs.ip_address_number;
+ // IPv6 addresses are placed ahead of IPv4 addresses.
+ bool operator<(const IPAddressSortingEntry& rhs) const {
+ const IPAddress& ip1 = this->ip_address;
+ const IPAddress& ip2 = rhs.ip_address;
if (ip1.size() != ip2.size())
return ip1.size() > ip2.size(); // IPv6 before IPv4.
- DCHECK(ip1.size() == ip2.size());
- return memcmp(&ip1[0], &ip2[0], ip1.size()) < 0; // Ascending order.
+ return ip1 < ip2; // Ascending order.
}
std::string string_value;
- IPAddressNumber ip_address_number;
+ IPAddress ip_address;
};
// Handler for "sortIpAddressList(IpAddressList)". |ip_address_list| is a
@@ -284,13 +287,13 @@ bool SortIpAddressList(const std::string& ip_address_list,
return false;
// Split-up IP addresses and store them in a vector.
- std::vector<IPAddress> ip_vector;
- IPAddressNumber ip_num;
+ std::vector<IPAddressSortingEntry> ip_vector;
+ IPAddress ip_address;
base::StringTokenizer str_tok(cleaned_ip_address_list, ";");
while (str_tok.GetNext()) {
- if (!ParseIPLiteralToNumber(str_tok.token(), &ip_num))
+ if (!ip_address.AssignFromIPLiteral(str_tok.token()))
return false;
- ip_vector.push_back(IPAddress(str_tok.token(), ip_num));
+ ip_vector.push_back(IPAddressSortingEntry(str_tok.token(), ip_address));
}
if (ip_vector.empty()) // Can happen if we have something like
@@ -320,11 +323,11 @@ bool SortIpAddressList(const std::string& ip_address_list,
// format, or if an address and prefix of different types are used (e.g. IPv6
// address and IPv4 prefix).
bool IsInNetEx(const std::string& ip_address, const std::string& ip_prefix) {
- IPAddressNumber address;
- if (!ParseIPLiteralToNumber(ip_address, &address))
+ IPAddress address;
+ if (!address.AssignFromIPLiteral(ip_address))
return false;
- IPAddressNumber prefix;
+ IPAddress prefix;
size_t prefix_length_in_bits;
if (!ParseCIDRBlock(ip_prefix, &prefix, &prefix_length_in_bits))
return false;
@@ -333,10 +336,10 @@ bool IsInNetEx(const std::string& ip_address, const std::string& ip_prefix) {
if (address.size() != prefix.size())
return false;
- DCHECK((address.size() == 4 && prefix.size() == 4) ||
- (address.size() == 16 && prefix.size() == 16));
+ DCHECK((address.IsIPv4() && prefix.IsIPv4()) ||
+ (address.IsIPv6() && prefix.IsIPv6()));
- return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits);
+ return IPAddressMatchesPrefix(address, prefix, prefix_length_in_bits);
}
// Consider only single component domains like 'foo' as plain host names.
@@ -346,8 +349,8 @@ bool IsPlainHostName(const std::string& hostname_utf8) {
// IPv6 literals might not contain any periods, however are not considered
// plain host names.
- IPAddressNumber unused;
- return !ParseIPLiteralToNumber(hostname_utf8, &unused);
+ IPAddress unused;
+ return !unused.AssignFromIPLiteral(hostname_utf8);
}
// All instances of ProxyResolverV8 share the same v8::Isolate. This isolate is
diff --git a/chromium/net/proxy/proxy_resolver_v8_tracing.cc b/chromium/net/proxy/proxy_resolver_v8_tracing.cc
index 94ad9f0d6c4..c21ebd77f8c 100644
--- a/chromium/net/proxy/proxy_resolver_v8_tracing.cc
+++ b/chromium/net/proxy/proxy_resolver_v8_tracing.cc
@@ -18,9 +18,10 @@
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
+#include "base/trace_event/trace_event.h"
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
+#include "net/base/network_interfaces.h"
#include "net/dns/host_resolver.h"
#include "net/proxy/proxy_info.h"
#include "net/proxy/proxy_resolver_error_observer.h"
@@ -548,6 +549,7 @@ void Job::ExecuteNonBlocking() {
}
int Job::ExecuteProxyResolver() {
+ TRACE_EVENT0("net", "Job::ExecuteProxyResolver");
int result = ERR_UNEXPECTED; // Initialized to silence warnings.
switch (operation_) {
diff --git a/chromium/net/proxy/proxy_resolver_winhttp.cc b/chromium/net/proxy/proxy_resolver_winhttp.cc
index 7dccbf0b93c..ee16ef8c237 100644
--- a/chromium/net/proxy/proxy_resolver_winhttp.cc
+++ b/chromium/net/proxy/proxy_resolver_winhttp.cc
@@ -15,8 +15,6 @@
#include "net/proxy/proxy_resolver.h"
#include "url/gurl.h"
-#pragma comment(lib, "winhttp.lib")
-
using base::TimeDelta;
using base::TimeTicks;
diff --git a/chromium/net/proxy/proxy_server.cc b/chromium/net/proxy/proxy_server.cc
index d3ba5ba1e67..76fa0d6224f 100644
--- a/chromium/net/proxy/proxy_server.cc
+++ b/chromium/net/proxy/proxy_server.cc
@@ -7,7 +7,7 @@
#include <algorithm>
#include "base/strings/string_util.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "net/http/http_util.h"
namespace net {
diff --git a/chromium/net/proxy/proxy_service.cc b/chromium/net/proxy/proxy_service.cc
index 2c30f745290..01bc3bb25db 100644
--- a/chromium/net/proxy/proxy_service.cc
+++ b/chromium/net/proxy/proxy_service.cc
@@ -5,6 +5,7 @@
#include "net/proxy/proxy_service.h"
#include <algorithm>
+#include <cmath>
#include <utility>
#include "base/bind.h"
@@ -15,6 +16,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_macros.h"
+#include "base/metrics/sparse_histogram.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/thread_task_runner_handle.h"
@@ -23,11 +25,11 @@
#include "net/base/completion_callback.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
+#include "net/base/proxy_delegate.h"
+#include "net/base/url_util.h"
#include "net/log/net_log.h"
#include "net/proxy/dhcp_proxy_script_fetcher.h"
#include "net/proxy/multi_threaded_proxy_resolver.h"
-#include "net/proxy/network_delegate_error_observer.h"
#include "net/proxy/proxy_config_service_fixed.h"
#include "net/proxy/proxy_resolver.h"
#include "net/proxy/proxy_resolver_factory.h"
@@ -765,8 +767,9 @@ class ProxyService::PacRequest
public:
PacRequest(ProxyService* service,
const GURL& url,
+ const std::string& method,
int load_flags,
- NetworkDelegate* network_delegate,
+ ProxyDelegate* proxy_delegate,
ProxyInfo* results,
const CompletionCallback& user_callback,
const BoundNetLog& net_log)
@@ -774,8 +777,9 @@ class ProxyService::PacRequest
user_callback_(user_callback),
results_(results),
url_(url),
+ method_(method),
load_flags_(load_flags),
- network_delegate_(network_delegate),
+ proxy_delegate_(proxy_delegate),
resolve_job_(NULL),
config_id_(ProxyConfig::kInvalidConfigID),
config_source_(PROXY_CONFIG_SOURCE_UNKNOWN),
@@ -807,7 +811,7 @@ class ProxyService::PacRequest
void StartAndCompleteCheckingForSynchronous() {
int rv = service_->TryToCompleteSynchronously(url_, load_flags_,
- network_delegate_, results_);
+ proxy_delegate_, results_);
if (rv == ERR_IO_PENDING)
rv = Start();
if (rv != ERR_IO_PENDING)
@@ -855,8 +859,8 @@ class ProxyService::PacRequest
// Note that DidFinishResolvingProxy might modify |results_|.
int rv = service_->DidFinishResolvingProxy(
- url_, load_flags_, network_delegate_, results_, result_code, net_log_,
- creation_time_, script_executed);
+ url_, method_, load_flags_, proxy_delegate_, results_, result_code,
+ net_log_, creation_time_, script_executed);
// Make a note in the results which configuration was in use at the
// time of the resolve.
@@ -908,8 +912,9 @@ class ProxyService::PacRequest
CompletionCallback user_callback_;
ProxyInfo* results_;
GURL url_;
+ std::string method_;
int load_flags_;
- NetworkDelegate* network_delegate_;
+ ProxyDelegate* proxy_delegate_;
ProxyResolver::RequestHandle resolve_job_;
ProxyConfig::ID config_id_; // The config id when the resolve was started.
ProxyConfigSource config_source_; // The source of proxy settings.
@@ -1007,28 +1012,25 @@ scoped_ptr<ProxyService> ProxyService::CreateFixedFromPacResult(
}
int ProxyService::ResolveProxy(const GURL& raw_url,
+ const std::string& method,
int load_flags,
ProxyInfo* result,
const CompletionCallback& callback,
PacRequest** pac_request,
- NetworkDelegate* network_delegate,
+ ProxyDelegate* proxy_delegate,
const BoundNetLog& net_log) {
DCHECK(!callback.is_null());
- return ResolveProxyHelper(raw_url,
- load_flags,
- result,
- callback,
- pac_request,
- network_delegate,
- net_log);
+ return ResolveProxyHelper(raw_url, method, load_flags, result, callback,
+ pac_request, proxy_delegate, net_log);
}
int ProxyService::ResolveProxyHelper(const GURL& raw_url,
+ const std::string& method,
int load_flags,
ProxyInfo* result,
const CompletionCallback& callback,
PacRequest** pac_request,
- NetworkDelegate* network_delegate,
+ ProxyDelegate* proxy_delegate,
const BoundNetLog& net_log) {
DCHECK(CalledOnValidThread());
@@ -1049,11 +1051,10 @@ int ProxyService::ResolveProxyHelper(const GURL& raw_url,
// Check if the request can be completed right away. (This is the case when
// using a direct connection for example).
- int rv = TryToCompleteSynchronously(url, load_flags,
- network_delegate, result);
+ int rv = TryToCompleteSynchronously(url, load_flags, proxy_delegate, result);
if (rv != ERR_IO_PENDING) {
rv = DidFinishResolvingProxy(
- url, load_flags, network_delegate, result, rv, net_log,
+ url, method, load_flags, proxy_delegate, result, rv, net_log,
callback.is_null() ? TimeTicks() : TimeTicks::Now(), false);
return rv;
}
@@ -1061,9 +1062,9 @@ int ProxyService::ResolveProxyHelper(const GURL& raw_url,
if (callback.is_null())
return ERR_IO_PENDING;
- scoped_refptr<PacRequest> req(
- new PacRequest(this, url, load_flags, network_delegate,
- result, callback, net_log));
+ scoped_refptr<PacRequest> req(new PacRequest(this, url, method, load_flags,
+ proxy_delegate, result, callback,
+ net_log));
if (current_state_ == STATE_READY) {
// Start the resolve request.
@@ -1085,25 +1086,21 @@ int ProxyService::ResolveProxyHelper(const GURL& raw_url,
return rv; // ERR_IO_PENDING
}
-bool ProxyService:: TryResolveProxySynchronously(
- const GURL& raw_url,
- int load_flags,
- ProxyInfo* result,
- NetworkDelegate* network_delegate,
- const BoundNetLog& net_log) {
+bool ProxyService::TryResolveProxySynchronously(const GURL& raw_url,
+ const std::string& method,
+ int load_flags,
+ ProxyInfo* result,
+ ProxyDelegate* proxy_delegate,
+ const BoundNetLog& net_log) {
CompletionCallback null_callback;
- return ResolveProxyHelper(raw_url,
- load_flags,
- result,
- null_callback,
- NULL /* pac_request*/,
- network_delegate,
+ return ResolveProxyHelper(raw_url, method, load_flags, result, null_callback,
+ nullptr /* pac_request*/, proxy_delegate,
net_log) == OK;
}
int ProxyService::TryToCompleteSynchronously(const GURL& url,
int load_flags,
- NetworkDelegate* network_delegate,
+ ProxyDelegate* proxy_delegate,
ProxyInfo* result) {
DCHECK_NE(STATE_NONE, current_state_);
@@ -1256,12 +1253,13 @@ void ProxyService::OnInitProxyResolverComplete(int result) {
}
int ProxyService::ReconsiderProxyAfterError(const GURL& url,
+ const std::string& method,
int load_flags,
int net_error,
ProxyInfo* result,
const CompletionCallback& callback,
PacRequest** pac_request,
- NetworkDelegate* network_delegate,
+ ProxyDelegate* proxy_delegate,
const BoundNetLog& net_log) {
DCHECK(CalledOnValidThread());
@@ -1276,8 +1274,8 @@ int ProxyService::ReconsiderProxyAfterError(const GURL& url,
// If we have a new config or the config was never tried, we delete the
// list of bad proxies and we try again.
proxy_retry_info_.clear();
- return ResolveProxy(url, load_flags, result, callback, pac_request,
- network_delegate, net_log);
+ return ResolveProxy(url, method, load_flags, result, callback, pac_request,
+ proxy_delegate, net_log);
}
DCHECK(!result->is_empty());
@@ -1304,7 +1302,7 @@ bool ProxyService::MarkProxiesAsBadUntil(
}
void ProxyService::ReportSuccess(const ProxyInfo& result,
- NetworkDelegate* network_delegate) {
+ ProxyDelegate* proxy_delegate) {
DCHECK(CalledOnValidThread());
const ProxyRetryInfoMap& new_retry_info = result.proxy_retry_info();
@@ -1316,12 +1314,11 @@ void ProxyService::ReportSuccess(const ProxyInfo& result,
ProxyRetryInfoMap::iterator existing = proxy_retry_info_.find(iter->first);
if (existing == proxy_retry_info_.end()) {
proxy_retry_info_[iter->first] = iter->second;
- if (network_delegate) {
+ if (proxy_delegate) {
const ProxyServer& bad_proxy =
ProxyServer::FromURI(iter->first, ProxyServer::SCHEME_HTTP);
const ProxyRetryInfo& proxy_retry_info = iter->second;
- network_delegate->NotifyProxyFallback(bad_proxy,
- proxy_retry_info.net_error);
+ proxy_delegate->OnFallback(bad_proxy, proxy_retry_info.net_error);
}
}
else if (existing->second.bad_until < iter->second.bad_until)
@@ -1358,8 +1355,9 @@ void ProxyService::RemovePendingRequest(PacRequest* req) {
}
int ProxyService::DidFinishResolvingProxy(const GURL& url,
+ const std::string& method,
int load_flags,
- NetworkDelegate* network_delegate,
+ ProxyDelegate* proxy_delegate,
ProxyInfo* result,
int result_code,
const BoundNetLog& net_log,
@@ -1378,6 +1376,8 @@ int ProxyService::DidFinishResolvingProxy(const GURL& url,
UMA_HISTOGRAM_CUSTOM_TIMES("Net.ProxyService.GetProxyUsingScriptTime",
diff, base::TimeDelta::FromMicroseconds(100),
base::TimeDelta::FromSeconds(20), 50);
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.ProxyService.GetProxyUsingScriptResult",
+ std::abs(result_code));
}
UMA_HISTOGRAM_BOOLEAN("Net.ProxyService.ResolvedUsingScript",
script_executed);
@@ -1388,10 +1388,10 @@ int ProxyService::DidFinishResolvingProxy(const GURL& url,
// Log the result of the proxy resolution.
if (result_code == OK) {
- // Allow the network delegate to interpose on the resolution decision,
+ // Allow the proxy delegate to interpose on the resolution decision,
// possibly modifying the ProxyInfo.
- if (network_delegate)
- network_delegate->NotifyResolveProxy(url, load_flags, *this, result);
+ if (proxy_delegate)
+ proxy_delegate->OnResolveProxy(url, method, load_flags, *this, result);
net_log.AddEvent(NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
base::Bind(&NetLogFinishedResolvingProxyCallback, result));
@@ -1420,10 +1420,10 @@ int ProxyService::DidFinishResolvingProxy(const GURL& url,
result->UseDirect();
result_code = OK;
- // Allow the network delegate to interpose on the resolution decision,
+ // Allow the proxy delegate to interpose on the resolution decision,
// possibly modifying the ProxyInfo.
- if (network_delegate)
- network_delegate->NotifyResolveProxy(url, load_flags, *this, result);
+ if (proxy_delegate)
+ proxy_delegate->OnResolveProxy(url, method, load_flags, *this, result);
} else {
result_code = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
}
diff --git a/chromium/net/proxy/proxy_service.h b/chromium/net/proxy/proxy_service.h
index e71fe9b9c0f..8cd707144dd 100644
--- a/chromium/net/proxy/proxy_service.h
+++ b/chromium/net/proxy/proxy_service.h
@@ -37,7 +37,7 @@ namespace net {
class DhcpProxyScriptFetcher;
class HostResolver;
-class NetworkDelegate;
+class ProxyDelegate;
class ProxyResolver;
class ProxyResolverFactory;
class ProxyResolverScriptData;
@@ -107,6 +107,10 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver,
// TODO(eroman): consider naming this simply "Request".
class PacRequest;
+ // Determines the appropriate proxy for |url| for a |method| request and
+ // stores the result in |results|. If |method| is empty, the caller can expect
+ // method independent resolution.
+ //
// Returns ERR_IO_PENDING if the proxy information could not be provided
// synchronously, to indicate that the result will be available when the
// callback is run. The callback is run on the thread that calls
@@ -127,19 +131,21 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver,
//
// Profiling information for the request is saved to |net_log| if non-NULL.
int ResolveProxy(const GURL& url,
+ const std::string& method,
int load_flags,
ProxyInfo* results,
const CompletionCallback& callback,
PacRequest** pac_request,
- NetworkDelegate* network_delegate,
+ ProxyDelegate* proxy_delegate,
const BoundNetLog& net_log);
// Returns true if the proxy information could be determined without spawning
// an asynchronous task. Otherwise, |result| is unmodified.
bool TryResolveProxySynchronously(const GURL& raw_url,
+ const std::string& method,
int load_flags,
ProxyInfo* result,
- NetworkDelegate* network_delegate,
+ ProxyDelegate* proxy_delegate,
const BoundNetLog& net_log);
// This method is called after a failure to connect or resolve a host name.
@@ -157,12 +163,13 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver,
//
// Profiling information for the request is saved to |net_log| if non-NULL.
int ReconsiderProxyAfterError(const GURL& url,
+ const std::string& method,
int load_flags,
int net_error,
ProxyInfo* results,
const CompletionCallback& callback,
PacRequest** pac_request,
- NetworkDelegate* network_delegate,
+ ProxyDelegate* proxy_delegate,
const BoundNetLog& net_log);
// Explicitly trigger proxy fallback for the given |results| by updating our
@@ -183,10 +190,10 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver,
// Called to report that the last proxy connection succeeded. If |proxy_info|
// has a non empty proxy_retry_info map, the proxies that have been tried (and
- // failed) for this request will be marked as bad. |network_delegate| will
+ // failed) for this request will be marked as bad. |proxy_delegate| will
// be notified of any proxy fallbacks.
void ReportSuccess(const ProxyInfo& proxy_info,
- NetworkDelegate* network_delegate);
+ ProxyDelegate* proxy_delegate);
// Call this method with a non-null |pac_request| to cancel the PAC request.
void CancelPacRequest(PacRequest* pac_request);
@@ -326,18 +333,19 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver,
// Completing synchronously means we don't need to query ProxyResolver.
int TryToCompleteSynchronously(const GURL& url,
int load_flags,
- NetworkDelegate* network_delegate,
+ ProxyDelegate* proxy_delegate,
ProxyInfo* result);
// Identical to ResolveProxy, except that |callback| is permitted to be null.
// if |callback.is_null()|, this function becomes a thin wrapper around
// |TryToCompleteSynchronously|.
int ResolveProxyHelper(const GURL& url,
+ const std::string& method,
int load_flags,
ProxyInfo* results,
const CompletionCallback& callback,
PacRequest** pac_request,
- NetworkDelegate* network_delegate,
+ ProxyDelegate* proxy_delegate,
const BoundNetLog& net_log);
// Cancels all of the requests sent to the ProxyResolver. These will be
@@ -358,8 +366,9 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver,
// asynchronously). Handles logging the result, and cleaning out
// bad entries from the results list.
int DidFinishResolvingProxy(const GURL& url,
+ const std::string& method,
int load_flags,
- NetworkDelegate* network_delegate,
+ ProxyDelegate* proxy_delegate,
ProxyInfo* result,
int result_code,
const BoundNetLog& net_log,
diff --git a/chromium/net/proxy/proxy_service_mojo_unittest.cc b/chromium/net/proxy/proxy_service_mojo_unittest.cc
index 5dd94b00cfb..6881a196fd8 100644
--- a/chromium/net/proxy/proxy_service_mojo_unittest.cc
+++ b/chromium/net/proxy/proxy_service_mojo_unittest.cc
@@ -156,9 +156,9 @@ TEST_F(ProxyServiceMojoTest, Basic) {
ProxyInfo info;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- proxy_service_->ResolveProxy(GURL("http://foo"), LOAD_NORMAL, &info,
- callback.callback(), nullptr, nullptr,
- BoundNetLog()));
+ proxy_service_->ResolveProxy(
+ GURL("http://foo"), std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr, BoundNetLog()));
// Proxy script fetcher should have a fetch triggered by the first
// |ResolveProxy()| request.
@@ -178,9 +178,9 @@ TEST_F(ProxyServiceMojoTest, DnsResolution) {
TestCompletionCallback callback;
BoundTestNetLog bound_net_log;
EXPECT_EQ(ERR_IO_PENDING,
- proxy_service_->ResolveProxy(GURL("http://foo"), LOAD_NORMAL, &info,
- callback.callback(), nullptr, nullptr,
- bound_net_log.bound()));
+ proxy_service_->ResolveProxy(
+ GURL("http://foo"), std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr, bound_net_log.bound()));
// Proxy script fetcher should have a fetch triggered by the first
// |ResolveProxy()| request.
@@ -209,9 +209,9 @@ TEST_F(ProxyServiceMojoTest, Error) {
TestCompletionCallback callback;
BoundTestNetLog bound_net_log;
EXPECT_EQ(ERR_IO_PENDING,
- proxy_service_->ResolveProxy(GURL("http://foo"), LOAD_NORMAL, &info,
- callback.callback(), nullptr, nullptr,
- bound_net_log.bound()));
+ proxy_service_->ResolveProxy(
+ GURL("http://foo"), std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr, bound_net_log.bound()));
// Proxy script fetcher should have a fetch triggered by the first
// |ResolveProxy()| request.
@@ -238,9 +238,9 @@ TEST_F(ProxyServiceMojoTest, ErrorOnInitialization) {
ProxyInfo info;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- proxy_service_->ResolveProxy(GURL("http://foo"), LOAD_NORMAL, &info,
- callback.callback(), nullptr, nullptr,
- BoundNetLog()));
+ proxy_service_->ResolveProxy(
+ GURL("http://foo"), std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr, BoundNetLog()));
// Proxy script fetcher should have a fetch triggered by the first
// |ResolveProxy()| request.
diff --git a/chromium/net/proxy/proxy_service_unittest.cc b/chromium/net/proxy/proxy_service_unittest.cc
index 3d23b583345..c595f4564c1 100644
--- a/chromium/net/proxy/proxy_service_unittest.cc
+++ b/chromium/net/proxy/proxy_service_unittest.cc
@@ -5,6 +5,7 @@
#include "net/proxy/proxy_service.h"
#include <cstdarg>
+#include <string>
#include <vector>
#include "base/format_macros.h"
@@ -14,7 +15,7 @@
#include "base/strings/utf_string_conversions.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
-#include "net/base/network_delegate_impl.h"
+#include "net/base/proxy_delegate.h"
#include "net/base/test_completion_callback.h"
#include "net/log/net_log.h"
#include "net/log/test_net_log.h"
@@ -162,19 +163,20 @@ class MockProxyConfigService: public ProxyConfigService {
};
// A test network delegate that exercises the OnResolveProxy callback.
-class TestResolveProxyNetworkDelegate : public NetworkDelegateImpl {
+class TestResolveProxyDelegate : public ProxyDelegate {
public:
- TestResolveProxyNetworkDelegate()
+ TestResolveProxyDelegate()
: on_resolve_proxy_called_(false),
add_proxy_(false),
remove_proxy_(false),
- proxy_service_(NULL) {
- }
+ proxy_service_(nullptr) {}
void OnResolveProxy(const GURL& url,
+ const std::string& method,
int load_flags,
const ProxyService& proxy_service,
ProxyInfo* result) override {
+ method_ = method;
on_resolve_proxy_called_ = true;
proxy_service_ = &proxy_service;
DCHECK(!add_proxy_ || !remove_proxy_);
@@ -189,6 +191,8 @@ class TestResolveProxyNetworkDelegate : public NetworkDelegateImpl {
return on_resolve_proxy_called_;
}
+ const std::string& method() const { return method_; }
+
void set_add_proxy(bool add_proxy) {
add_proxy_ = add_proxy;
}
@@ -201,27 +205,63 @@ class TestResolveProxyNetworkDelegate : public NetworkDelegateImpl {
return proxy_service_;
}
+ void OnTunnelConnectCompleted(const HostPortPair& endpoint,
+ const HostPortPair& proxy_server,
+ int net_error) override {}
+ void OnFallback(const ProxyServer& bad_proxy, int net_error) override {}
+ void OnBeforeSendHeaders(URLRequest* request,
+ const ProxyInfo& proxy_info,
+ HttpRequestHeaders* headers) override {}
+ void OnBeforeTunnelRequest(const HostPortPair& proxy_server,
+ HttpRequestHeaders* extra_headers) override {}
+ void OnTunnelHeadersReceived(
+ const HostPortPair& origin,
+ const HostPortPair& proxy_server,
+ const HttpResponseHeaders& response_headers) override {}
+ bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override {
+ return true;
+ }
+
private:
bool on_resolve_proxy_called_;
bool add_proxy_;
bool remove_proxy_;
+ std::string method_;
const ProxyService* proxy_service_;
};
// A test network delegate that exercises the OnProxyFallback callback.
-class TestProxyFallbackNetworkDelegate : public NetworkDelegateImpl {
+class TestProxyFallbackProxyDelegate : public ProxyDelegate {
public:
- TestProxyFallbackNetworkDelegate()
- : on_proxy_fallback_called_(false),
- proxy_fallback_net_error_(OK) {
- }
+ TestProxyFallbackProxyDelegate()
+ : on_proxy_fallback_called_(false), proxy_fallback_net_error_(OK) {}
- void OnProxyFallback(const ProxyServer& proxy_server,
- int net_error) override {
- proxy_server_ = proxy_server;
+ // ProxyDelegate implementation:
+ void OnResolveProxy(const GURL& url,
+ const std::string& method,
+ int load_flags,
+ const ProxyService& proxy_service,
+ ProxyInfo* result) override {}
+ void OnTunnelConnectCompleted(const HostPortPair& endpoint,
+ const HostPortPair& proxy_server,
+ int net_error) override {}
+ void OnFallback(const ProxyServer& bad_proxy, int net_error) override {
+ proxy_server_ = bad_proxy;
proxy_fallback_net_error_ = net_error;
on_proxy_fallback_called_ = true;
}
+ void OnBeforeSendHeaders(URLRequest* request,
+ const ProxyInfo& proxy_info,
+ HttpRequestHeaders* headers) override {}
+ void OnBeforeTunnelRequest(const HostPortPair& proxy_server,
+ HttpRequestHeaders* extra_headers) override {}
+ void OnTunnelHeadersReceived(
+ const HostPortPair& origin,
+ const HostPortPair& proxy_server,
+ const HttpResponseHeaders& response_headers) override {}
+ bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override {
+ return true;
+ }
bool on_proxy_fallback_called() const {
return on_proxy_fallback_called_;
@@ -314,15 +354,16 @@ TEST_F(ProxyServiceTest, Direct) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(
make_scoped_ptr(new MockProxyConfigService(ProxyConfig::CreateDirect())),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback;
BoundTestNetLog log;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, log.bound());
+ int rv =
+ service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr, log.bound());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(factory->pending_requests().empty());
@@ -351,7 +392,7 @@ TEST_F(ProxyServiceTest, OnResolveProxyCallbackAddProxy) {
config.proxy_rules().bypass_rules.ParseFromString("*.org");
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL url("http://www.google.com/");
GURL bypass_url("http://internet.org");
@@ -361,44 +402,47 @@ TEST_F(ProxyServiceTest, OnResolveProxyCallbackAddProxy) {
BoundTestNetLog log;
// First, warm up the ProxyService.
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, log.bound());
+ int rv =
+ service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr, log.bound());
EXPECT_EQ(OK, rv);
// Verify that network delegate is invoked.
- TestResolveProxyNetworkDelegate delegate;
- rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
- &delegate, log.bound());
+ TestResolveProxyDelegate delegate;
+ rv = service.ResolveProxy(url, "GET", LOAD_NORMAL, &info, callback.callback(),
+ nullptr, &delegate, log.bound());
EXPECT_TRUE(delegate.on_resolve_proxy_called());
EXPECT_EQ(&service, delegate.proxy_service());
+ EXPECT_EQ(delegate.method(), "GET");
- // Verify that the NetworkDelegate's behavior is stateless across
+ // Verify that the ProxyDelegate's behavior is stateless across
// invocations of ResolveProxy. Start by having the callback add a proxy
// and checking that subsequent requests are not affected.
delegate.set_add_proxy(true);
// Callback should interpose:
- rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
- &delegate, log.bound());
+ rv = service.ResolveProxy(url, "GET", LOAD_NORMAL, &info, callback.callback(),
+ nullptr, &delegate, log.bound());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ(info.proxy_server().host_port_pair().host(), "delegate_proxy.com");
delegate.set_add_proxy(false);
// Check non-bypassed URL:
- rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
- &delegate, log.bound());
+ rv = service.ResolveProxy(url, "GET", LOAD_NORMAL, &info, callback.callback(),
+ nullptr, &delegate, log.bound());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1");
// Check bypassed URL:
- rv = service.ResolveProxy(bypass_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, &delegate, log.bound());
+ rv = service.ResolveProxy(bypass_url, "GET", LOAD_NORMAL, &info,
+ callback.callback(), nullptr, &delegate,
+ log.bound());
EXPECT_TRUE(info.is_direct());
}
TEST_F(ProxyServiceTest, OnResolveProxyCallbackRemoveProxy) {
// Same as OnResolveProxyCallbackAddProxy, but verify that the
- // NetworkDelegate's behavior is stateless across invocations after it
+ // ProxyDelegate's behavior is stateless across invocations after it
// *removes* a proxy.
ProxyConfig config;
config.proxy_rules().ParseFromString("foopy1:8080");
@@ -406,7 +450,7 @@ TEST_F(ProxyServiceTest, OnResolveProxyCallbackRemoveProxy) {
config.proxy_rules().bypass_rules.ParseFromString("*.org");
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL url("http://www.google.com/");
GURL bypass_url("http://internet.org");
@@ -416,28 +460,30 @@ TEST_F(ProxyServiceTest, OnResolveProxyCallbackRemoveProxy) {
BoundTestNetLog log;
// First, warm up the ProxyService.
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, log.bound());
+ int rv =
+ service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr, log.bound());
EXPECT_EQ(OK, rv);
- TestResolveProxyNetworkDelegate delegate;
+ TestResolveProxyDelegate delegate;
delegate.set_remove_proxy(true);
// Callback should interpose:
- rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
- &delegate, log.bound());
+ rv = service.ResolveProxy(url, "GET", LOAD_NORMAL, &info, callback.callback(),
+ nullptr, &delegate, log.bound());
EXPECT_TRUE(info.is_direct());
delegate.set_remove_proxy(false);
// Check non-bypassed URL:
- rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
- &delegate, log.bound());
+ rv = service.ResolveProxy(url, "GET", LOAD_NORMAL, &info, callback.callback(),
+ nullptr, &delegate, log.bound());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1");
// Check bypassed URL:
- rv = service.ResolveProxy(bypass_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, &delegate, log.bound());
+ rv = service.ResolveProxy(bypass_url, "GET", LOAD_NORMAL, &info,
+ callback.callback(), nullptr, &delegate,
+ log.bound());
EXPECT_TRUE(info.is_direct());
}
@@ -450,7 +496,7 @@ TEST_F(ProxyServiceTest, PAC) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://www.google.com/");
@@ -459,8 +505,9 @@ TEST_F(ProxyServiceTest, PAC) {
ProxyService::PacRequest* request;
BoundTestNetLog log;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
- &request, NULL, log.bound());
+ int rv =
+ service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), &request, nullptr, log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request));
@@ -512,14 +559,15 @@ TEST_F(ProxyServiceTest, PAC_NoIdentityOrHash) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://username:password@www.google.com/?ref#hash#hash");
ProxyInfo info;
TestCompletionCallback callback;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -543,14 +591,15 @@ TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -576,12 +625,12 @@ TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) {
// Now, imagine that connecting to foopy:8080 fails: there is nothing
// left to fallback to, since our proxy list was NOT terminated by
// DIRECT.
- NetworkDelegateImpl network_delegate;
+ TestResolveProxyDelegate proxy_delegate;
TestCompletionCallback callback2;
ProxyServer expected_proxy_server = info.proxy_server();
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback2.callback(), NULL, &network_delegate, BoundNetLog());
+ url, "GET", LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback2.callback(), nullptr, &proxy_delegate, BoundNetLog());
// ReconsiderProxyAfterError returns error indicating nothing left.
EXPECT_EQ(ERR_FAILED, rv);
EXPECT_TRUE(info.is_empty());
@@ -597,14 +646,15 @@ TEST_F(ProxyServiceTest, PAC_RuntimeError) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://this-causes-js-error/");
ProxyInfo info;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -655,14 +705,15 @@ TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -683,19 +734,19 @@ TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) {
// Fallback 1.
TestCompletionCallback callback2;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback2.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("foobar:10", info.proxy_server().ToURI());
// Fallback 2.
- NetworkDelegateImpl network_delegate;
+ TestResolveProxyDelegate proxy_delegate;
ProxyServer expected_proxy_server3 = info.proxy_server();
TestCompletionCallback callback3;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback3.callback(), NULL, &network_delegate, BoundNetLog());
+ url, "GET", LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback3.callback(), nullptr, &proxy_delegate, BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(info.is_direct());
@@ -703,8 +754,8 @@ TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) {
ProxyServer expected_proxy_server4 = info.proxy_server();
TestCompletionCallback callback4;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback4.callback(), NULL, &network_delegate, BoundNetLog());
+ url, "GET", LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback4.callback(), nullptr, &proxy_delegate, BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("foobar:20", info.proxy_server().ToURI());
@@ -713,8 +764,8 @@ TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) {
ProxyServer expected_proxy_server5 = info.proxy_server();
TestCompletionCallback callback5;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback5.callback(), NULL, &network_delegate, BoundNetLog());
+ url, "GET", LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback5.callback(), nullptr, &proxy_delegate, BoundNetLog());
EXPECT_EQ(ERR_FAILED, rv);
EXPECT_TRUE(info.is_empty());
}
@@ -731,14 +782,15 @@ TEST_F(ProxyServiceTest, PAC_ConfigSourcePropagates) {
MockAsyncProxyResolverFactory* factory =
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
// Resolve something.
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
ASSERT_EQ(ERR_IO_PENDING, rv);
factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
ASSERT_EQ(1u, resolver.pending_requests().size());
@@ -769,14 +821,15 @@ TEST_F(ProxyServiceTest, ProxyResolverFails) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
// Start first resolve request.
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -802,8 +855,9 @@ TEST_F(ProxyServiceTest, ProxyResolverFails) {
// The second resolve request will try to run through the proxy resolver,
// regardless of whether the first request failed in it.
TestCompletionCallback callback2;
- rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL,
- NULL, BoundNetLog());
+ rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(1u, resolver.pending_requests().size());
@@ -837,9 +891,9 @@ TEST_F(ProxyServiceTest, ProxyResolverTerminatedDuringRequest) {
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback1.callback(),
- nullptr, nullptr, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), net::LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(1u, factory->pending_requests().size());
@@ -868,8 +922,9 @@ TEST_F(ProxyServiceTest, ProxyResolverTerminatedDuringRequest) {
EXPECT_TRUE(factory->pending_requests().empty());
TestCompletionCallback callback2;
- rv = service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback2.callback(),
- nullptr, nullptr, BoundNetLog());
+ rv = service.ResolveProxy(url, std::string(), net::LOAD_NORMAL, &info,
+ callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(1u, factory->pending_requests().size());
@@ -909,13 +964,14 @@ TEST_F(ProxyServiceTest,
GURL url2("https://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(url1, net::LOAD_NORMAL, &info, callback1.callback(),
- nullptr, nullptr, BoundNetLog());
+ int rv = service.ResolveProxy(url1, std::string(), net::LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
TestCompletionCallback callback2;
- rv = service.ResolveProxy(url2, net::LOAD_NORMAL, &info, callback2.callback(),
- nullptr, nullptr, BoundNetLog());
+ rv = service.ResolveProxy(url2, std::string(), net::LOAD_NORMAL, &info,
+ callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(1u, factory->pending_requests().size());
@@ -973,14 +1029,15 @@ TEST_F(ProxyServiceTest, ProxyScriptFetcherFailsDownloadingMandatoryPac) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
// Start first resolve request.
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -997,8 +1054,9 @@ TEST_F(ProxyServiceTest, ProxyScriptFetcherFailsDownloadingMandatoryPac) {
// As the proxy resolver factory failed the request and is configured for a
// mandatory PAC script, ProxyService must not implicitly fall-back to DIRECT.
TestCompletionCallback callback2;
- rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL,
- NULL, BoundNetLog());
+ rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, rv);
EXPECT_FALSE(info.is_direct());
}
@@ -1018,7 +1076,7 @@ TEST_F(ProxyServiceTest, ProxyResolverFailsParsingJavaScriptMandatoryPac) {
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -1028,8 +1086,9 @@ TEST_F(ProxyServiceTest, ProxyResolverFailsParsingJavaScriptMandatoryPac) {
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Check that nothing has been sent to the proxy resolver factory yet.
@@ -1068,14 +1127,15 @@ TEST_F(ProxyServiceTest, ProxyResolverFailsInJavaScriptMandatoryPac) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
// Start first resolve request.
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -1097,8 +1157,9 @@ TEST_F(ProxyServiceTest, ProxyResolverFailsInJavaScriptMandatoryPac) {
// The second resolve request will try to run through the proxy resolver,
// regardless of whether the first request failed in it.
TestCompletionCallback callback2;
- rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL,
- NULL, BoundNetLog());
+ rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(1u, resolver.pending_requests().size());
@@ -1126,15 +1187,16 @@ TEST_F(ProxyServiceTest, ProxyFallback) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://www.google.com/");
// Get the proxy information.
ProxyInfo info;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -1163,8 +1225,8 @@ TEST_F(ProxyServiceTest, ProxyFallback) {
// Fake an error on the proxy.
TestCompletionCallback callback2;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback2.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(OK, rv);
// Proxy times should not have been modified by fallback.
@@ -1175,15 +1237,16 @@ TEST_F(ProxyServiceTest, ProxyFallback) {
EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
// Report back that the second proxy worked. This will globally mark the
// first proxy as bad.
- TestProxyFallbackNetworkDelegate test_delegate;
+ TestProxyFallbackProxyDelegate test_delegate;
service.ReportSuccess(info, &test_delegate);
EXPECT_EQ("foopy1:8080", test_delegate.proxy_server().ToURI());
EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED,
test_delegate.proxy_fallback_net_error());
TestCompletionCallback callback3;
- rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback3.callback(), NULL,
- NULL, BoundNetLog());
+ rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback3.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(1u, resolver.pending_requests().size());
@@ -1210,8 +1273,8 @@ TEST_F(ProxyServiceTest, ProxyFallback) {
// We fake another error. It should now try the third one.
TestCompletionCallback callback4;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback4.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback4.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
@@ -1220,8 +1283,8 @@ TEST_F(ProxyServiceTest, ProxyFallback) {
// that was in our bad proxies map (foopy1:8080).
TestCompletionCallback callback5;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback5.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback5.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
@@ -1229,8 +1292,8 @@ TEST_F(ProxyServiceTest, ProxyFallback) {
// so there is nothing left to try.
TestCompletionCallback callback6;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback6.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback6.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_FAILED, rv);
EXPECT_FALSE(info.is_direct());
EXPECT_TRUE(info.is_empty());
@@ -1241,8 +1304,9 @@ TEST_F(ProxyServiceTest, ProxyFallback) {
// Look up proxies again
TestCompletionCallback callback7;
- rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback7.callback(), NULL,
- NULL, BoundNetLog());
+ rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback7.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(1u, resolver.pending_requests().size());
@@ -1276,15 +1340,16 @@ TEST_F(ProxyServiceTest, ProxyFallbackToDirect) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://www.google.com/");
// Get the proxy information.
ProxyInfo info;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -1307,8 +1372,8 @@ TEST_F(ProxyServiceTest, ProxyFallbackToDirect) {
// Fake an error on the proxy.
TestCompletionCallback callback2;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback2.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(OK, rv);
// Now we get back the second proxy.
@@ -1317,8 +1382,8 @@ TEST_F(ProxyServiceTest, ProxyFallbackToDirect) {
// Fake an error on this proxy as well.
TestCompletionCallback callback3;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback3.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback3.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(OK, rv);
// Finally, we get back DIRECT.
@@ -1331,8 +1396,8 @@ TEST_F(ProxyServiceTest, ProxyFallbackToDirect) {
// Now we tell the proxy service that even DIRECT failed.
TestCompletionCallback callback4;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback4.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback4.callback(), nullptr, nullptr, BoundNetLog());
// There was nothing left to try after DIRECT, so we are out of
// choices.
EXPECT_EQ(ERR_FAILED, rv);
@@ -1349,15 +1414,16 @@ TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://www.google.com/");
// Get the proxy information.
ProxyInfo info;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -1383,8 +1449,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) {
TestCompletionCallback callback2;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback2.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy-new/proxy.pac"),
@@ -1405,8 +1471,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) {
// We fake another error. It should now ignore the first one.
TestCompletionCallback callback3;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback3.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback3.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
@@ -1418,8 +1484,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) {
// We fake another error. It should go back to the first proxy.
TestCompletionCallback callback4;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback4.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback4.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"),
@@ -1452,15 +1518,16 @@ TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://www.google.com/");
// Get the proxy information.
ProxyInfo info;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -1481,8 +1548,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) {
// Fake a proxy error.
TestCompletionCallback callback2;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback2.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(OK, rv);
// The first proxy is ignored, and the second one is selected.
@@ -1492,8 +1559,9 @@ TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) {
// Fake a PAC failure.
ProxyInfo info2;
TestCompletionCallback callback3;
- rv = service.ResolveProxy(url, LOAD_NORMAL, &info2, callback3.callback(),
- NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info2,
+ callback3.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(1u, resolver.pending_requests().size());
@@ -1514,8 +1582,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) {
ProxyInfo info3;
TestCompletionCallback callback4;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info3,
- callback4.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info3,
+ callback4.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(1u, resolver.pending_requests().size());
@@ -1550,15 +1618,16 @@ TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://www.google.com/");
// Get the proxy information.
ProxyInfo info;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -1579,8 +1648,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) {
// Fake a proxy error.
TestCompletionCallback callback2;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
+ callback2.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(OK, rv);
// The first proxy is ignored, and the second one is selected.
@@ -1590,8 +1659,9 @@ TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) {
// Fake a PAC failure.
ProxyInfo info2;
TestCompletionCallback callback3;
- rv = service.ResolveProxy(url, LOAD_NORMAL, &info2, callback3.callback(),
- NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info2,
+ callback3.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(1u, resolver.pending_requests().size());
@@ -1613,8 +1683,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) {
ProxyInfo info3;
TestCompletionCallback callback4;
rv = service.ReconsiderProxyAfterError(
- url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info3,
- callback4.callback(), NULL, NULL, BoundNetLog());
+ url, std::string(), LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info3,
+ callback4.callback(), nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(1u, resolver.pending_requests().size());
@@ -1642,21 +1712,23 @@ TEST_F(ProxyServiceTest, ProxyBypassList) {
config.proxy_rules().bypass_rules.ParseFromString("*.org");
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
int rv;
GURL url1("http://www.webkit.org");
GURL url2("http://www.webkit.com");
// Request for a .org domain should bypass proxy.
- rv = service.ResolveProxy(url1, LOAD_NORMAL, &info[0], callback[0].callback(),
- NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(url1, std::string(), LOAD_NORMAL, &info[0],
+ callback[0].callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(info[0].is_direct());
// Request for a .com domain hits the proxy.
- rv = service.ResolveProxy(url2, LOAD_NORMAL, &info[1], callback[1].callback(),
- NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(url2, std::string(), LOAD_NORMAL, &info[1],
+ callback[1].callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_EQ("foopy1:8080", info[1].proxy_server().ToURI());
}
@@ -1681,7 +1753,7 @@ TEST_F(ProxyServiceTest, MarkProxiesAsBadTests) {
EXPECT_EQ(3u, additional_bad_proxies.size());
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
ProxyInfo proxy_info;
proxy_info.UseProxyList(proxy_list);
const ProxyRetryInfoMap& retry_info = service.proxy_retry_info();
@@ -1702,39 +1774,39 @@ TEST_F(ProxyServiceTest, PerProtocolProxyTests) {
config.set_auto_detect(false);
{
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL test_url("http://www.msn.com");
ProxyInfo info;
TestCompletionCallback callback;
- int rv =
- service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(test_url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
}
{
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL test_url("ftp://ftp.google.com");
ProxyInfo info;
TestCompletionCallback callback;
- int rv =
- service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(test_url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(info.is_direct());
EXPECT_EQ("direct://", info.proxy_server().ToURI());
}
{
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL test_url("https://webbranch.techcu.com");
ProxyInfo info;
TestCompletionCallback callback;
- int rv =
- service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(test_url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
@@ -1742,13 +1814,13 @@ TEST_F(ProxyServiceTest, PerProtocolProxyTests) {
{
config.proxy_rules().ParseFromString("foopy1:8080");
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL test_url("http://www.microsoft.com");
ProxyInfo info;
TestCompletionCallback callback;
- int rv =
- service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(test_url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
@@ -1764,13 +1836,13 @@ TEST_F(ProxyServiceTest, ProxyConfigSourcePropagates) {
config.set_source(PROXY_CONFIG_SOURCE_TEST);
config.proxy_rules().ParseFromString("https=foopy2:8080");
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL test_url("http://www.google.com");
ProxyInfo info;
TestCompletionCallback callback;
- int rv =
- service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(test_url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
ASSERT_EQ(OK, rv);
// Should be SOURCE_TEST, even if there are no HTTP proxies configured.
EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
@@ -1780,13 +1852,13 @@ TEST_F(ProxyServiceTest, ProxyConfigSourcePropagates) {
config.set_source(PROXY_CONFIG_SOURCE_TEST);
config.proxy_rules().ParseFromString("https=foopy2:8080");
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL test_url("https://www.google.com");
ProxyInfo info;
TestCompletionCallback callback;
- int rv =
- service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(test_url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
ASSERT_EQ(OK, rv);
// Used the HTTPS proxy. So source should be TEST.
EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
@@ -1795,13 +1867,13 @@ TEST_F(ProxyServiceTest, ProxyConfigSourcePropagates) {
ProxyConfig config;
config.set_source(PROXY_CONFIG_SOURCE_TEST);
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL test_url("http://www.google.com");
ProxyInfo info;
TestCompletionCallback callback;
- int rv =
- service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(test_url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
ASSERT_EQ(OK, rv);
// ProxyConfig is empty. Source should still be TEST.
EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
@@ -1819,52 +1891,52 @@ TEST_F(ProxyServiceTest, DefaultProxyFallbackToSOCKS) {
{
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL test_url("http://www.msn.com");
ProxyInfo info;
TestCompletionCallback callback;
- int rv =
- service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(test_url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
}
{
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL test_url("ftp://ftp.google.com");
ProxyInfo info;
TestCompletionCallback callback;
- int rv =
- service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(test_url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
}
{
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL test_url("https://webbranch.techcu.com");
ProxyInfo info;
TestCompletionCallback callback;
- int rv =
- service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(test_url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
}
{
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- nullptr, NULL);
+ nullptr, nullptr);
GURL test_url("unknown://www.microsoft.com");
ProxyInfo info;
TestCompletionCallback callback;
- int rv =
- service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(test_url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
@@ -1884,14 +1956,15 @@ TEST_F(ProxyServiceTest, CancelInProgressRequest) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
// Start 3 requests.
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url1, LOAD_NORMAL, &info1, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url1, std::string(), LOAD_NORMAL, &info1,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Successfully initialize the PAC script.
@@ -1904,16 +1977,18 @@ TEST_F(ProxyServiceTest, CancelInProgressRequest) {
ProxyInfo info2;
TestCompletionCallback callback2;
ProxyService::PacRequest* request2;
- rv = service.ResolveProxy(url2, LOAD_NORMAL, &info2, callback2.callback(),
- &request2, NULL, BoundNetLog());
+ rv = service.ResolveProxy(url2, std::string(), LOAD_NORMAL, &info2,
+ callback2.callback(), &request2, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
GetPendingRequestsForURLs(resolver, url1, url2);
ProxyInfo info3;
TestCompletionCallback callback3;
- rv = service.ResolveProxy(url3, LOAD_NORMAL, &info3, callback3.callback(),
- NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(url3, std::string(), LOAD_NORMAL, &info3,
+ callback3.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
GetPendingRequestsForURLs(resolver, url1, url2, url3);
@@ -1954,7 +2029,7 @@ TEST_F(ProxyServiceTest, InitialPACScriptDownload) {
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -1965,8 +2040,9 @@ TEST_F(ProxyServiceTest, InitialPACScriptDownload) {
ProxyInfo info1;
TestCompletionCallback callback1;
ProxyService::PacRequest* request1;
- int rv = service.ResolveProxy(url1, LOAD_NORMAL, &info1, callback1.callback(),
- &request1, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url1, std::string(), LOAD_NORMAL, &info1,
+ callback1.callback(), &request1, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// The first request should have triggered download of PAC script.
@@ -1976,15 +2052,17 @@ TEST_F(ProxyServiceTest, InitialPACScriptDownload) {
ProxyInfo info2;
TestCompletionCallback callback2;
ProxyService::PacRequest* request2;
- rv = service.ResolveProxy(url2, LOAD_NORMAL, &info2, callback2.callback(),
- &request2, NULL, BoundNetLog());
+ rv = service.ResolveProxy(url2, std::string(), LOAD_NORMAL, &info2,
+ callback2.callback(), &request2, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ProxyInfo info3;
TestCompletionCallback callback3;
ProxyService::PacRequest* request3;
- rv = service.ResolveProxy(url3, LOAD_NORMAL, &info3, callback3.callback(),
- &request3, NULL, BoundNetLog());
+ rv = service.ResolveProxy(url3, std::string(), LOAD_NORMAL, &info3,
+ callback3.callback(), &request3, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Nothing has been sent to the factory yet.
@@ -2057,7 +2135,7 @@ TEST_F(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) {
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -2067,8 +2145,9 @@ TEST_F(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) {
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url1, LOAD_NORMAL, &info1, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url1, std::string(), LOAD_NORMAL, &info1,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// The first request should have triggered download of PAC script.
@@ -2077,8 +2156,9 @@ TEST_F(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) {
ProxyInfo info2;
TestCompletionCallback callback2;
- rv = service.ResolveProxy(url2, LOAD_NORMAL, &info2, callback2.callback(),
- NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(url2, std::string(), LOAD_NORMAL, &info2,
+ callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// At this point the ProxyService should be waiting for the
@@ -2116,7 +2196,7 @@ TEST_F(ProxyServiceTest, CancelWhilePACFetching) {
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -2127,9 +2207,9 @@ TEST_F(ProxyServiceTest, CancelWhilePACFetching) {
TestCompletionCallback callback1;
ProxyService::PacRequest* request1;
BoundTestNetLog log1;
- int rv =
- service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
- callback1.callback(), &request1, NULL, log1.bound());
+ int rv = service.ResolveProxy(GURL("http://request1"), std::string(),
+ LOAD_NORMAL, &info1, callback1.callback(),
+ &request1, nullptr, log1.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
// The first request should have triggered download of PAC script.
@@ -2139,15 +2219,16 @@ TEST_F(ProxyServiceTest, CancelWhilePACFetching) {
ProxyInfo info2;
TestCompletionCallback callback2;
ProxyService::PacRequest* request2;
- rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
- callback2.callback(), &request2, NULL,
+ rv = service.ResolveProxy(GURL("http://request2"), std::string(), LOAD_NORMAL,
+ &info2, callback2.callback(), &request2, nullptr,
BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ProxyInfo info3;
TestCompletionCallback callback3;
- rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3,
- callback3.callback(), NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(GURL("http://request3"), std::string(), LOAD_NORMAL,
+ &info3, callback3.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Nothing has been sent to the factory yet.
@@ -2214,7 +2295,7 @@ TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac) {
MockAsyncProxyResolverFactory* factory =
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -2224,15 +2305,17 @@ TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac) {
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url1, LOAD_NORMAL, &info1, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url1, std::string(), LOAD_NORMAL, &info1,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ProxyInfo info2;
TestCompletionCallback callback2;
ProxyService::PacRequest* request2;
- rv = service.ResolveProxy(url2, LOAD_NORMAL, &info2, callback2.callback(),
- &request2, NULL, BoundNetLog());
+ rv = service.ResolveProxy(url2, std::string(), LOAD_NORMAL, &info2,
+ callback2.callback(), &request2, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Check that nothing has been sent to the proxy resolver factory yet.
@@ -2293,7 +2376,7 @@ TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) {
MockAsyncProxyResolverFactory* factory =
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -2303,15 +2386,17 @@ TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) {
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv = service.ResolveProxy(url1, LOAD_NORMAL, &info1, callback1.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url1, std::string(), LOAD_NORMAL, &info1,
+ callback1.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ProxyInfo info2;
TestCompletionCallback callback2;
ProxyService::PacRequest* request2;
- rv = service.ResolveProxy(url2, LOAD_NORMAL, &info2, callback2.callback(),
- &request2, NULL, BoundNetLog());
+ rv = service.ResolveProxy(url2, std::string(), LOAD_NORMAL, &info2,
+ callback2.callback(), &request2, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Check that nothing has been sent to the proxy resolver factory yet.
@@ -2365,7 +2450,7 @@ TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) {
MockAsyncProxyResolverFactory* factory =
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -2375,16 +2460,16 @@ TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) {
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
- callback1.callback(), NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(GURL("http://request1"), std::string(),
+ LOAD_NORMAL, &info1, callback1.callback(),
+ nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ProxyInfo info2;
TestCompletionCallback callback2;
ProxyService::PacRequest* request2;
- rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
- callback2.callback(), &request2, NULL,
+ rv = service.ResolveProxy(GURL("http://request2"), std::string(), LOAD_NORMAL,
+ &info2, callback2.callback(), &request2, nullptr,
BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -2427,7 +2512,7 @@ TEST_F(ProxyServiceTest, BypassDoesntApplyToPac) {
MockAsyncProxyResolverFactory* factory =
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -2437,9 +2522,9 @@ TEST_F(ProxyServiceTest, BypassDoesntApplyToPac) {
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1,
- callback1.callback(), NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(GURL("http://www.google.com"), std::string(),
+ LOAD_NORMAL, &info1, callback1.callback(),
+ nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Check that nothing has been sent to the proxy resolver factory yet.
@@ -2469,8 +2554,9 @@ TEST_F(ProxyServiceTest, BypassDoesntApplyToPac) {
// Start another request, it should pickup the bypass item.
ProxyInfo info2;
TestCompletionCallback callback2;
- rv = service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info2,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(GURL("http://www.google.com"), std::string(),
+ LOAD_NORMAL, &info2, callback2.callback(), nullptr,
+ nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(1u, resolver.pending_requests().size());
@@ -2497,7 +2583,7 @@ TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingFetch) {
MockAsyncProxyResolverFactory* factory =
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -2507,9 +2593,9 @@ TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingFetch) {
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1,
- callback1.callback(), NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(GURL("http://www.google.com"), std::string(),
+ LOAD_NORMAL, &info1, callback1.callback(),
+ nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Check that nothing has been sent to the proxy resolver factory yet.
@@ -2533,14 +2619,15 @@ TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingSet) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback;
- int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
- NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(url, std::string(), LOAD_NORMAL, &info,
+ callback.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -2552,13 +2639,13 @@ TEST_F(ProxyServiceTest, ResetProxyConfigService) {
config1.proxy_rules().ParseFromString("foopy1:8080");
config1.set_auto_detect(false);
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config1)),
- nullptr, NULL);
+ nullptr, nullptr);
ProxyInfo info;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info,
- callback1.callback(), NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(GURL("http://request1"), std::string(),
+ LOAD_NORMAL, &info, callback1.callback(),
+ nullptr, nullptr, BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
@@ -2568,8 +2655,9 @@ TEST_F(ProxyServiceTest, ResetProxyConfigService) {
service.ResetConfigService(
make_scoped_ptr(new MockProxyConfigService(config2)));
TestCompletionCallback callback2;
- rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(GURL("http://request2"), std::string(), LOAD_NORMAL,
+ &info, callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
}
@@ -2584,15 +2672,15 @@ TEST_F(ProxyServiceTest, UpdateConfigFromPACToDirect) {
MockAsyncProxyResolverFactory* factory =
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
// Start 1 request.
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1,
- callback1.callback(), NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(GURL("http://www.google.com"), std::string(),
+ LOAD_NORMAL, &info1, callback1.callback(),
+ nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Successfully set the autodetect script.
@@ -2619,8 +2707,9 @@ TEST_F(ProxyServiceTest, UpdateConfigFromPACToDirect) {
// Start another request -- the effective configuration has changed.
ProxyInfo info2;
TestCompletionCallback callback2;
- rv = service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info2,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(GURL("http://www.google.com"), std::string(),
+ LOAD_NORMAL, &info2, callback2.callback(), nullptr,
+ nullptr, BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(info2.is_direct());
@@ -2651,9 +2740,9 @@ TEST_F(ProxyServiceTest, NetworkChangeTriggersPacRefetch) {
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
- callback1.callback(), NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(GURL("http://request1"), std::string(),
+ LOAD_NORMAL, &info1, callback1.callback(),
+ nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// The first request should have triggered initial download of PAC script.
@@ -2694,8 +2783,9 @@ TEST_F(ProxyServiceTest, NetworkChangeTriggersPacRefetch) {
// Start a second request.
ProxyInfo info2;
TestCompletionCallback callback2;
- rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(GURL("http://request2"), std::string(), LOAD_NORMAL,
+ &info2, callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// This second request should have triggered the re-download of the PAC
@@ -2758,7 +2848,7 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterFailure) {
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -2768,9 +2858,9 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterFailure) {
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
- callback1.callback(), NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(GURL("http://request1"), std::string(),
+ LOAD_NORMAL, &info1, callback1.callback(),
+ nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// The first request should have triggered initial download of PAC script.
@@ -2829,8 +2919,9 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterFailure) {
// Start a second request.
ProxyInfo info2;
TestCompletionCallback callback2;
- rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(GURL("http://request2"), std::string(), LOAD_NORMAL,
+ &info2, callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Check that it was sent to the resolver.
@@ -2864,7 +2955,7 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentChange) {
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -2874,9 +2965,9 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentChange) {
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
- callback1.callback(), NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(GURL("http://request1"), std::string(),
+ LOAD_NORMAL, &info1, callback1.callback(),
+ nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// The first request should have triggered initial download of PAC script.
@@ -2941,8 +3032,9 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentChange) {
// Start a second request.
ProxyInfo info2;
TestCompletionCallback callback2;
- rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(GURL("http://request2"), std::string(), LOAD_NORMAL,
+ &info2, callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Check that it was sent to the resolver.
@@ -2976,7 +3068,7 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentUnchanged) {
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -2986,9 +3078,9 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentUnchanged) {
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
- callback1.callback(), NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(GURL("http://request1"), std::string(),
+ LOAD_NORMAL, &info1, callback1.callback(),
+ nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// The first request should have triggered initial download of PAC script.
@@ -3050,8 +3142,9 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentUnchanged) {
// Start a second request.
ProxyInfo info2;
TestCompletionCallback callback2;
- rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(GURL("http://request2"), std::string(), LOAD_NORMAL,
+ &info2, callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Check that it was sent to the resolver.
@@ -3085,7 +3178,7 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterSuccess) {
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -3095,9 +3188,9 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterSuccess) {
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
- callback1.callback(), NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(GURL("http://request1"), std::string(),
+ LOAD_NORMAL, &info1, callback1.callback(),
+ nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// The first request should have triggered initial download of PAC script.
@@ -3156,8 +3249,9 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterSuccess) {
// Start a second request.
ProxyInfo info2;
TestCompletionCallback callback2;
- rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(GURL("http://request2"), std::string(), LOAD_NORMAL,
+ &info2, callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(info2.is_direct());
}
@@ -3239,7 +3333,7 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) {
new MockAsyncProxyResolverFactory(true);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
service.SetProxyScriptFetchers(
@@ -3249,9 +3343,9 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) {
ProxyInfo info1;
TestCompletionCallback callback1;
- int rv =
- service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
- callback1.callback(), NULL, NULL, BoundNetLog());
+ int rv = service.ResolveProxy(GURL("http://request1"), std::string(),
+ LOAD_NORMAL, &info1, callback1.callback(),
+ nullptr, nullptr, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// The first request should have triggered initial download of PAC script.
@@ -3294,8 +3388,9 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) {
// Start a second request.
ProxyInfo info2;
TestCompletionCallback callback2;
- rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
- callback2.callback(), NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(GURL("http://request2"), std::string(), LOAD_NORMAL,
+ &info2, callback2.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// This request should have sent work to the resolver; complete it.
@@ -3324,8 +3419,9 @@ TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) {
// since the PAC script poller experienced a failure.
ProxyInfo info3;
TestCompletionCallback callback3;
- rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3,
- callback3.callback(), NULL, NULL, BoundNetLog());
+ rv = service.ResolveProxy(GURL("http://request3"), std::string(), LOAD_NORMAL,
+ &info3, callback3.callback(), nullptr, nullptr,
+ BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(info3.is_direct());
}
@@ -3339,7 +3435,7 @@ TEST_F(ProxyServiceTest, SynchronousWithPAC) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(config_service),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://www.google.com/");
@@ -3348,7 +3444,7 @@ TEST_F(ProxyServiceTest, SynchronousWithPAC) {
BoundTestNetLog log;
bool synchronous_success = service.TryResolveProxySynchronously(
- url, LOAD_NORMAL, &info, NULL, log.bound());
+ url, std::string(), LOAD_NORMAL, &info, nullptr, log.bound());
EXPECT_FALSE(synchronous_success);
// |info| should not have been modified.
@@ -3366,7 +3462,7 @@ TEST_F(ProxyServiceTest, SynchronousWithFixedConfiguration) {
new MockAsyncProxyResolverFactory(false);
ProxyService service(make_scoped_ptr(new MockProxyConfigService(config)),
- make_scoped_ptr(factory), NULL);
+ make_scoped_ptr(factory), nullptr);
GURL url("http://www.google.com/");
@@ -3374,7 +3470,7 @@ TEST_F(ProxyServiceTest, SynchronousWithFixedConfiguration) {
BoundTestNetLog log;
bool synchronous_success = service.TryResolveProxySynchronously(
- url, LOAD_NORMAL, &info, NULL, log.bound());
+ url, std::string(), LOAD_NORMAL, &info, nullptr, log.bound());
EXPECT_TRUE(synchronous_success);
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("foopy1", info.proxy_server().host_port_pair().host());
diff --git a/chromium/net/quic/bidirectional_stream_quic_impl.cc b/chromium/net/quic/bidirectional_stream_quic_impl.cc
new file mode 100644
index 00000000000..6e560321a6c
--- /dev/null
+++ b/chromium/net/quic/bidirectional_stream_quic_impl.cc
@@ -0,0 +1,264 @@
+// 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/bidirectional_stream_quic_impl.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/timer/timer.h"
+#include "net/http/bidirectional_stream_request_info.h"
+#include "net/socket/next_proto.h"
+#include "net/spdy/spdy_header_block.h"
+#include "net/spdy/spdy_http_utils.h"
+
+namespace net {
+
+BidirectionalStreamQuicImpl::BidirectionalStreamQuicImpl(
+ const base::WeakPtr<QuicChromiumClientSession>& session)
+ : session_(session),
+ was_handshake_confirmed_(session->IsCryptoHandshakeConfirmed()),
+ stream_(nullptr),
+ request_info_(nullptr),
+ delegate_(nullptr),
+ response_status_(OK),
+ negotiated_protocol_(kProtoUnknown),
+ read_buffer_len_(0),
+ headers_bytes_received_(0),
+ headers_bytes_sent_(0),
+ closed_stream_received_bytes_(0),
+ closed_stream_sent_bytes_(0),
+ has_sent_headers_(false),
+ has_received_headers_(false),
+ weak_factory_(this) {
+ DCHECK(session_);
+ session_->AddObserver(this);
+}
+
+BidirectionalStreamQuicImpl::~BidirectionalStreamQuicImpl() {
+ Cancel();
+ if (session_)
+ session_->RemoveObserver(this);
+}
+
+void BidirectionalStreamQuicImpl::Start(
+ const BidirectionalStreamRequestInfo* request_info,
+ const BoundNetLog& net_log,
+ BidirectionalStreamImpl::Delegate* delegate,
+ scoped_ptr<base::Timer> /* timer */) {
+ DCHECK(!stream_);
+
+ if (!session_) {
+ NotifyError(was_handshake_confirmed_ ? ERR_QUIC_PROTOCOL_ERROR
+ : ERR_QUIC_HANDSHAKE_FAILED);
+ return;
+ }
+
+ delegate_ = delegate;
+ request_info_ = request_info;
+
+ int rv = stream_request_.StartRequest(
+ session_, &stream_,
+ base::Bind(&BidirectionalStreamQuicImpl::OnStreamReady,
+ weak_factory_.GetWeakPtr()));
+ if (rv == OK) {
+ OnStreamReady(rv);
+ } else if (!was_handshake_confirmed_) {
+ NotifyError(ERR_QUIC_HANDSHAKE_FAILED);
+ }
+}
+
+int BidirectionalStreamQuicImpl::ReadData(IOBuffer* buffer, int buffer_len) {
+ DCHECK(buffer);
+ DCHECK(buffer_len);
+
+ if (!stream_) {
+ // If the stream is already closed, there is no body to read.
+ return response_status_;
+ }
+ int rv = stream_->Read(buffer, buffer_len);
+ if (rv != ERR_IO_PENDING) {
+ if (stream_->IsDoneReading()) {
+ // If the write side is closed, OnFinRead() will call
+ // BidirectionalStreamQuicImpl::OnClose().
+ stream_->OnFinRead();
+ }
+ return rv;
+ }
+ // Read will complete asynchronously and Delegate::OnReadCompleted will be
+ // called upon completion.
+ read_buffer_ = buffer;
+ read_buffer_len_ = buffer_len;
+ return ERR_IO_PENDING;
+}
+
+void BidirectionalStreamQuicImpl::SendData(IOBuffer* data,
+ int length,
+ bool end_stream) {
+ DCHECK(stream_);
+ DCHECK(length > 0 || (length == 0 && end_stream));
+
+ base::StringPiece string_data(data->data(), length);
+ int rv = stream_->WriteStreamData(
+ string_data, end_stream,
+ base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete,
+ weak_factory_.GetWeakPtr()));
+ DCHECK(rv == OK || rv == ERR_IO_PENDING);
+ if (rv == OK) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete,
+ weak_factory_.GetWeakPtr(), OK));
+ }
+}
+
+void BidirectionalStreamQuicImpl::Cancel() {
+ if (stream_) {
+ stream_->SetDelegate(nullptr);
+ stream_->Reset(QUIC_STREAM_CANCELLED);
+ ResetStream();
+ }
+}
+
+NextProto BidirectionalStreamQuicImpl::GetProtocol() const {
+ return negotiated_protocol_;
+}
+
+int64_t BidirectionalStreamQuicImpl::GetTotalReceivedBytes() const {
+ if (stream_)
+ return headers_bytes_received_ + stream_->stream_bytes_read();
+ return headers_bytes_received_ + closed_stream_received_bytes_;
+}
+
+int64_t BidirectionalStreamQuicImpl::GetTotalSentBytes() const {
+ if (stream_)
+ return headers_bytes_sent_ + stream_->stream_bytes_written();
+ return headers_bytes_sent_ + closed_stream_sent_bytes_;
+}
+
+void BidirectionalStreamQuicImpl::OnHeadersAvailable(
+ const SpdyHeaderBlock& headers,
+ size_t frame_len) {
+ headers_bytes_received_ += frame_len;
+ negotiated_protocol_ = kProtoQUIC1SPDY3;
+ if (!has_received_headers_) {
+ has_received_headers_ = true;
+ delegate_->OnHeadersReceived(headers);
+ } else {
+ if (stream_->IsDoneReading()) {
+ // If the write side is closed, OnFinRead() will call
+ // BidirectionalStreamQuicImpl::OnClose().
+ stream_->OnFinRead();
+ }
+ delegate_->OnTrailersReceived(headers);
+ }
+}
+
+void BidirectionalStreamQuicImpl::OnDataAvailable() {
+ // Return early if ReadData has not been called.
+ if (!read_buffer_)
+ return;
+
+ CHECK(read_buffer_);
+ CHECK_NE(0, read_buffer_len_);
+ int rv = ReadData(read_buffer_.get(), read_buffer_len_);
+ if (rv == ERR_IO_PENDING) {
+ // Spurrious notification. Wait for the next one.
+ return;
+ }
+ read_buffer_ = nullptr;
+ read_buffer_len_ = 0;
+ delegate_->OnDataRead(rv);
+}
+
+void BidirectionalStreamQuicImpl::OnClose(QuicErrorCode error) {
+ DCHECK(stream_);
+ if (error == QUIC_NO_ERROR &&
+ stream_->stream_error() == QUIC_STREAM_NO_ERROR) {
+ ResetStream();
+ return;
+ }
+ ResetStream();
+ NotifyError(was_handshake_confirmed_ ? ERR_QUIC_PROTOCOL_ERROR
+ : ERR_QUIC_HANDSHAKE_FAILED);
+}
+
+void BidirectionalStreamQuicImpl::OnError(int error) {
+ NotifyError(error);
+}
+
+bool BidirectionalStreamQuicImpl::HasSendHeadersComplete() {
+ return has_sent_headers_;
+}
+
+void BidirectionalStreamQuicImpl::OnCryptoHandshakeConfirmed() {
+ was_handshake_confirmed_ = true;
+}
+
+void BidirectionalStreamQuicImpl::OnSessionClosed(
+ int error,
+ bool /*port_migration_detected*/) {
+ DCHECK_NE(OK, error);
+ session_.reset();
+ NotifyError(error);
+}
+
+void BidirectionalStreamQuicImpl::OnStreamReady(int rv) {
+ DCHECK_NE(ERR_IO_PENDING, rv);
+ DCHECK(rv == OK || !stream_);
+ if (rv == OK) {
+ stream_->SetDelegate(this);
+ SendRequestHeaders();
+ } else {
+ NotifyError(rv);
+ }
+}
+
+void BidirectionalStreamQuicImpl::OnSendDataComplete(int rv) {
+ DCHECK(rv == OK || !stream_);
+ if (rv == OK) {
+ delegate_->OnDataSent();
+ } else {
+ NotifyError(rv);
+ }
+}
+
+void BidirectionalStreamQuicImpl::SendRequestHeaders() {
+ DCHECK(!has_sent_headers_);
+ DCHECK(stream_);
+
+ SpdyHeaderBlock headers;
+ HttpRequestInfo http_request_info;
+ http_request_info.url = request_info_->url;
+ http_request_info.method = request_info_->method;
+ http_request_info.extra_headers = request_info_->extra_headers;
+
+ CreateSpdyHeadersFromHttpRequest(http_request_info,
+ http_request_info.extra_headers, HTTP2, true,
+ &headers);
+ size_t frame_len = stream_->WriteHeaders(
+ headers, request_info_->end_stream_on_headers, nullptr);
+ headers_bytes_sent_ += frame_len;
+ has_sent_headers_ = true;
+ delegate_->OnHeadersSent();
+}
+
+void BidirectionalStreamQuicImpl::NotifyError(int error) {
+ DCHECK_NE(OK, error);
+ DCHECK_NE(ERR_IO_PENDING, error);
+
+ response_status_ = error;
+ ResetStream();
+ delegate_->OnFailed(error);
+}
+
+void BidirectionalStreamQuicImpl::ResetStream() {
+ if (!stream_)
+ return;
+ closed_stream_received_bytes_ = stream_->stream_bytes_read();
+ closed_stream_sent_bytes_ = stream_->stream_bytes_written();
+ stream_->SetDelegate(nullptr);
+ stream_ = nullptr;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/bidirectional_stream_quic_impl.h b/chromium/net/quic/bidirectional_stream_quic_impl.h
new file mode 100644
index 00000000000..b75c3894c86
--- /dev/null
+++ b/chromium/net/quic/bidirectional_stream_quic_impl.h
@@ -0,0 +1,114 @@
+// 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_BIDIRECTIONAL_STREAM_QUIC_IMPL_H_
+#define NET_QUIC_BIDIRECTIONAL_STREAM_QUIC_IMPL_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "net/http/bidirectional_stream_impl.h"
+#include "net/quic/quic_chromium_client_session.h"
+#include "net/quic/quic_chromium_client_stream.h"
+
+namespace base {
+class Timer;
+} // namespace base
+
+namespace net {
+
+struct BidirectionalStreamRequestInfo;
+class BoundNetLog;
+class IOBuffer;
+class SpdyHeaderBlock;
+
+class NET_EXPORT_PRIVATE BidirectionalStreamQuicImpl
+ : public BidirectionalStreamImpl,
+ public QuicChromiumClientStream::Delegate,
+ public QuicChromiumClientSession::Observer {
+ public:
+ explicit BidirectionalStreamQuicImpl(
+ const base::WeakPtr<QuicChromiumClientSession>& session);
+
+ ~BidirectionalStreamQuicImpl() override;
+
+ // BidirectionalStreamImpl implementation:
+ void Start(const BidirectionalStreamRequestInfo* request_info,
+ const BoundNetLog& net_log,
+ BidirectionalStreamImpl::Delegate* delegate,
+ scoped_ptr<base::Timer> timer) override;
+ int ReadData(IOBuffer* buffer, int buffer_len) override;
+ void SendData(IOBuffer* data, int length, bool end_stream) override;
+ void Cancel() override;
+ NextProto GetProtocol() const override;
+ int64_t GetTotalReceivedBytes() const override;
+ int64_t GetTotalSentBytes() const override;
+
+ private:
+ // QuicChromiumClientStream::Delegate implementation:
+ void OnHeadersAvailable(const SpdyHeaderBlock& headers,
+ size_t frame_len) override;
+ void OnDataAvailable() override;
+ void OnClose(QuicErrorCode error) override;
+ void OnError(int error) override;
+ bool HasSendHeadersComplete() override;
+
+ // QuicChromiumClientSession::Observer implementation:
+ void OnCryptoHandshakeConfirmed() override;
+ void OnSessionClosed(int error, bool port_migration_detected) override;
+
+ void OnStreamReady(int rv);
+ void OnSendDataComplete(int rv);
+ void OnReadDataComplete(int rv);
+
+ // Helper method to send request headers.
+ void SendRequestHeaders();
+ // Notifies the delegate of an error.
+ void NotifyError(int error);
+ // Resets the stream and ensures that |delegate_| won't be called back.
+ void ResetStream();
+
+ base::WeakPtr<QuicChromiumClientSession> session_;
+ bool was_handshake_confirmed_; // True if the crypto handshake succeeded.
+ QuicChromiumClientSession::StreamRequest stream_request_;
+ QuicChromiumClientStream* stream_; // Non-owning.
+
+ const BidirectionalStreamRequestInfo* request_info_;
+ BidirectionalStreamImpl::Delegate* delegate_;
+ // Saves the response status if the stream is explicitly closed via OnError
+ // or OnClose with an error. Once all buffered data has been returned, this
+ // will be used as the final response.
+ int response_status_;
+
+ // The protocol that is negotiated.
+ NextProto negotiated_protocol_;
+ // User provided read buffer for ReadData() response.
+ scoped_refptr<IOBuffer> read_buffer_;
+ int read_buffer_len_;
+
+ // Number of bytes received by the headers stream on behalf of this stream.
+ int64_t headers_bytes_received_;
+ // Number of bytes sent by the headers stream on behalf of this stream.
+ int64_t headers_bytes_sent_;
+ // After |stream_| has been closed, this keeps track of the total number of
+ // bytes received over the network for |stream_| while it was open.
+ int64_t closed_stream_received_bytes_;
+ // After |stream_| has been closed, this keeps track of the total number of
+ // bytes sent over the network for |stream_| while it was open.
+ int64_t closed_stream_sent_bytes_;
+ // Indicates whether initial headers have been sent.
+ bool has_sent_headers_;
+ // Indicates whether initial headers have been received.
+ bool has_received_headers_;
+
+ base::WeakPtrFactory<BidirectionalStreamQuicImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(BidirectionalStreamQuicImpl);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_BIDIRECTIONAL_STREAM_QUIC_IMPL_H_
diff --git a/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc b/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc
new file mode 100644
index 00000000000..3afdb479a7c
--- /dev/null
+++ b/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -0,0 +1,1154 @@
+// 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/bidirectional_stream_quic_impl.h"
+
+#include <stdint.h>
+#include <vector>
+
+#include "base/callback_helpers.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "net/base/ip_address.h"
+#include "net/base/net_errors.h"
+#include "net/http/bidirectional_stream_request_info.h"
+#include "net/http/transport_security_state.h"
+#include "net/log/test_net_log.h"
+#include "net/log/test_net_log_util.h"
+#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/crypto/quic_decrypter.h"
+#include "net/quic/crypto/quic_encrypter.h"
+#include "net/quic/crypto/quic_server_info.h"
+#include "net/quic/quic_chromium_client_session.h"
+#include "net/quic/quic_chromium_client_stream.h"
+#include "net/quic/quic_chromium_connection_helper.h"
+#include "net/quic/quic_chromium_packet_reader.h"
+#include "net/quic/quic_chromium_packet_writer.h"
+#include "net/quic/quic_connection.h"
+#include "net/quic/quic_http_utils.h"
+#include "net/quic/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_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace test {
+
+namespace {
+
+const char kUploadData[] = "Really nifty data!";
+const char kDefaultServerHostName[] = "www.google.com";
+const uint16_t kDefaultServerPort = 80;
+// Size of the buffer to be allocated for each read.
+const size_t kReadBufferSize = 4096;
+
+class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
+ public:
+ TestDelegateBase(IOBuffer* read_buf, int read_buf_len)
+ : TestDelegateBase(read_buf,
+ read_buf_len,
+ make_scoped_ptr(new base::Timer(false, false))) {}
+
+ TestDelegateBase(IOBuffer* read_buf,
+ int read_buf_len,
+ scoped_ptr<base::Timer> timer)
+ : read_buf_(read_buf),
+ read_buf_len_(read_buf_len),
+ timer_(std::move(timer)),
+ loop_(nullptr),
+ error_(OK),
+ on_data_read_count_(0),
+ on_data_sent_count_(0),
+ not_expect_callback_(false) {
+ loop_.reset(new base::RunLoop);
+ }
+
+ ~TestDelegateBase() override {}
+
+ void OnHeadersSent() override {
+ CHECK(!not_expect_callback_);
+ loop_->Quit();
+ }
+
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override {
+ CHECK(!not_expect_callback_);
+
+ response_headers_ = response_headers;
+ loop_->Quit();
+ }
+
+ void OnDataRead(int bytes_read) override {
+ CHECK(!not_expect_callback_);
+ CHECK(!callback_.is_null());
+
+ ++on_data_read_count_;
+ CHECK_GE(bytes_read, OK);
+ data_received_.append(read_buf_->data(), bytes_read);
+ base::ResetAndReturn(&callback_).Run(bytes_read);
+ }
+
+ void OnDataSent() override {
+ CHECK(!not_expect_callback_);
+
+ ++on_data_sent_count_;
+ loop_->Quit();
+ }
+
+ void OnTrailersReceived(const SpdyHeaderBlock& trailers) override {
+ CHECK(!not_expect_callback_);
+
+ trailers_ = trailers;
+ loop_->Quit();
+ }
+
+ void OnFailed(int error) override {
+ CHECK(!not_expect_callback_);
+ CHECK_EQ(OK, error_);
+ CHECK_NE(OK, error);
+
+ error_ = error;
+ loop_->Quit();
+ }
+
+ void Start(const BidirectionalStreamRequestInfo* request_info,
+ const BoundNetLog& net_log,
+ const base::WeakPtr<QuicChromiumClientSession> session) {
+ stream_job_.reset(new BidirectionalStreamQuicImpl(session));
+ stream_job_->Start(request_info, net_log, this, nullptr);
+ }
+
+ void SendData(IOBuffer* data, int length, bool end_of_stream) {
+ not_expect_callback_ = true;
+ stream_job_->SendData(data, length, end_of_stream);
+ not_expect_callback_ = false;
+ }
+
+ // Waits until next Delegate callback.
+ void WaitUntilNextCallback() {
+ loop_->Run();
+ loop_.reset(new base::RunLoop);
+ }
+
+ // Calls ReadData on the |stream_| and updates |data_received_|.
+ int ReadData(const CompletionCallback& callback) {
+ not_expect_callback_ = true;
+ int rv = stream_job_->ReadData(read_buf_.get(), read_buf_len_);
+ not_expect_callback_ = false;
+ if (rv > 0)
+ data_received_.append(read_buf_->data(), rv);
+ if (rv == ERR_IO_PENDING)
+ callback_ = callback;
+ return rv;
+ }
+
+ // Cancels |stream_|.
+ void CancelStream() { stream_job_->Cancel(); }
+
+ NextProto GetProtocol() const { return stream_job_->GetProtocol(); }
+
+ int64_t GetTotalReceivedBytes() const {
+ return stream_job_->GetTotalReceivedBytes();
+ }
+
+ int64_t GetTotalSentBytes() const { return stream_job_->GetTotalSentBytes(); }
+
+ // Const getters for internal states.
+ const std::string& data_received() const { return data_received_; }
+ int error() const { return error_; }
+ const SpdyHeaderBlock& response_headers() const { return response_headers_; }
+ const SpdyHeaderBlock& trailers() const { return trailers_; }
+ int on_data_read_count() const { return on_data_read_count_; }
+ int on_data_sent_count() const { return on_data_sent_count_; }
+
+ protected:
+ // Quits |loop_|.
+ void QuitLoop() { loop_->Quit(); }
+
+ // Deletes |stream_|.
+ void DeleteStream() { stream_job_.reset(); }
+
+ private:
+ scoped_ptr<BidirectionalStreamQuicImpl> stream_job_;
+ scoped_refptr<IOBuffer> read_buf_;
+ int read_buf_len_;
+ scoped_ptr<base::Timer> timer_;
+ std::string data_received_;
+ scoped_ptr<base::RunLoop> loop_;
+ SpdyHeaderBlock response_headers_;
+ SpdyHeaderBlock trailers_;
+ int error_;
+ int on_data_read_count_;
+ int on_data_sent_count_;
+ // This is to ensure that delegate callback is not invoked synchronously when
+ // calling into |stream_|.
+ bool not_expect_callback_;
+ CompletionCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestDelegateBase);
+};
+
+// A delegate that deletes the stream in a particular callback.
+class DeleteStreamDelegate : public TestDelegateBase {
+ public:
+ // Specifies in which callback the stream can be deleted.
+ enum Phase {
+ ON_HEADERS_RECEIVED,
+ ON_DATA_READ,
+ ON_TRAILERS_RECEIVED,
+ ON_FAILED,
+ };
+
+ DeleteStreamDelegate(IOBuffer* buf, int buf_len, Phase phase, bool do_cancel)
+ : TestDelegateBase(buf, buf_len), phase_(phase), do_cancel_(do_cancel) {}
+ ~DeleteStreamDelegate() override {}
+
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override {
+ if (phase_ == ON_HEADERS_RECEIVED) {
+ DeleteStream();
+ }
+ TestDelegateBase::OnHeadersReceived(response_headers);
+ }
+
+ void OnDataSent() override { NOTREACHED(); }
+
+ void OnDataRead(int bytes_read) override {
+ DCHECK_NE(ON_HEADERS_RECEIVED, phase_);
+ if (phase_ == ON_DATA_READ)
+ DeleteStream();
+ TestDelegateBase::OnDataRead(bytes_read);
+ }
+
+ void OnTrailersReceived(const SpdyHeaderBlock& trailers) override {
+ DCHECK_NE(ON_HEADERS_RECEIVED, phase_);
+ DCHECK_NE(ON_DATA_READ, phase_);
+ if (phase_ == ON_TRAILERS_RECEIVED)
+ DeleteStream();
+ TestDelegateBase::OnTrailersReceived(trailers);
+ }
+
+ void OnFailed(int error) override {
+ DCHECK_EQ(ON_FAILED, phase_);
+ DeleteStream();
+ TestDelegateBase::OnFailed(error);
+ }
+
+ private:
+ // Indicates in which callback the delegate should cancel or delete the
+ // stream.
+ Phase phase_;
+ // Indicates whether to cancel or delete the stream.
+ bool do_cancel_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeleteStreamDelegate);
+};
+
+} // namespace
+
+class BidirectionalStreamQuicImplTest
+ : public ::testing::TestWithParam<QuicVersion> {
+ protected:
+ static const bool kFin = true;
+ static const bool kIncludeVersion = true;
+ static const bool kIncludeCongestionFeedback = true;
+
+ // Holds a packet to be written to the wire, and the IO mode that should
+ // be used by the mock socket when performing the write.
+ struct PacketToWrite {
+ PacketToWrite(IoMode mode, QuicReceivedPacket* packet)
+ : mode(mode), packet(packet) {}
+ PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
+ IoMode mode;
+ QuicReceivedPacket* packet;
+ int rv;
+ };
+
+ BidirectionalStreamQuicImplTest()
+ : crypto_config_(CryptoTestUtils::ProofVerifierForTesting()),
+ read_buffer_(new IOBufferWithSize(4096)),
+ connection_id_(2),
+ stream_id_(kClientDataStreamId1),
+ maker_(GetParam(), connection_id_, &clock_, kDefaultServerHostName),
+ random_generator_(0) {
+ IPAddress ip(192, 0, 2, 33);
+ peer_addr_ = IPEndPoint(ip, 443);
+ self_addr_ = IPEndPoint(ip, 8435);
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
+ }
+
+ ~BidirectionalStreamQuicImplTest() {
+ session_->CloseSessionOnError(ERR_ABORTED, QUIC_INTERNAL_ERROR);
+ for (size_t i = 0; i < writes_.size(); i++) {
+ delete writes_[i].packet;
+ }
+ }
+
+ void TearDown() override {
+ EXPECT_TRUE(socket_data_->AllReadDataConsumed());
+ EXPECT_TRUE(socket_data_->AllWriteDataConsumed());
+ }
+
+ // Adds a packet to the list of expected writes.
+ void AddWrite(scoped_ptr<QuicReceivedPacket> packet) {
+ writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
+ }
+
+ void ProcessPacket(scoped_ptr<QuicReceivedPacket> packet) {
+ connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
+ }
+
+ // Configures the test fixture to use the list of expected writes.
+ void Initialize() {
+ mock_writes_.reset(new MockWrite[writes_.size()]);
+ for (size_t i = 0; i < writes_.size(); i++) {
+ if (writes_[i].packet == nullptr) {
+ mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
+ } else {
+ mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
+ writes_[i].packet->length());
+ }
+ };
+
+ socket_data_.reset(new StaticSocketDataProvider(
+ nullptr, 0, mock_writes_.get(), writes_.size()));
+
+ scoped_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
+ socket_data_.get(), net_log().bound().net_log()));
+ socket->Connect(peer_addr_);
+ runner_ = new TestTaskRunner(&clock_);
+ helper_.reset(new QuicChromiumConnectionHelper(runner_.get(), &clock_,
+ &random_generator_));
+ connection_ = new QuicConnection(
+ connection_id_, peer_addr_, helper_.get(),
+ new QuicChromiumPacketWriter(socket.get()), true /* owns_writer */,
+ Perspective::IS_CLIENT, SupportedVersions(GetParam()));
+
+ session_.reset(new QuicChromiumClientSession(
+ connection_, std::move(socket),
+ /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
+ &transport_security_state_, make_scoped_ptr((QuicServerInfo*)nullptr),
+ QuicServerId(kDefaultServerHostName, kDefaultServerPort,
+ PRIVACY_MODE_DISABLED),
+ kQuicYieldAfterPacketsRead,
+ QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
+ /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_,
+ "CONNECTION_UNKNOWN", base::TimeTicks::Now(), &push_promise_index_,
+ base::ThreadTaskRunnerHandle::Get().get(),
+ /*socket_performance_watcher=*/nullptr, net_log().bound().net_log()));
+ session_->Initialize();
+ session_->GetCryptoStream()->CryptoConnect();
+ EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
+ }
+
+ void SetRequest(const std::string& method,
+ const std::string& path,
+ RequestPriority priority) {
+ request_headers_ = maker_.GetRequestHeaders(method, "http", path);
+ }
+
+ SpdyHeaderBlock ConstructResponseHeaders(const std::string& response_code) {
+ return maker_.GetResponseHeaders(response_code);
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructDataPacket(
+ QuicPacketNumber packet_number,
+ bool should_include_version,
+ bool fin,
+ QuicStreamOffset offset,
+ base::StringPiece data) {
+ scoped_ptr<QuicReceivedPacket> packet(maker_.MakeDataPacket(
+ packet_number, stream_id_, should_include_version, fin, offset, data));
+ DVLOG(2) << "packet(" << packet_number << "): " << std::endl
+ << QuicUtils::StringToHexASCIIDump(packet->AsStringPiece());
+ return packet;
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructRequestHeadersPacket(
+ QuicPacketNumber packet_number,
+ bool fin,
+ RequestPriority request_priority,
+ size_t* spdy_headers_frame_length) {
+ SpdyPriority priority =
+ ConvertRequestPriorityToQuicPriority(request_priority);
+ return maker_.MakeRequestHeadersPacket(
+ packet_number, stream_id_, kIncludeVersion, fin, priority,
+ request_headers_, spdy_headers_frame_length);
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructResponseHeadersPacket(
+ QuicPacketNumber packet_number,
+ bool fin,
+ const SpdyHeaderBlock& response_headers,
+ size_t* spdy_headers_frame_length,
+ QuicStreamOffset* offset) {
+ return maker_.MakeResponseHeadersPacket(
+ packet_number, stream_id_, !kIncludeVersion, fin, response_headers,
+ spdy_headers_frame_length, offset);
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructResponseTrailersPacket(
+ QuicPacketNumber packet_number,
+ bool fin,
+ const SpdyHeaderBlock& trailers,
+ size_t* spdy_headers_frame_length,
+ QuicStreamOffset* offset) {
+ return maker_.MakeResponseHeadersPacket(packet_number, stream_id_,
+ !kIncludeVersion, fin, trailers,
+ spdy_headers_frame_length, offset);
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructRstStreamPacket(
+ QuicPacketNumber packet_number) {
+ return ConstructRstStreamCancelledPacket(packet_number, 0);
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructRstStreamCancelledPacket(
+ QuicPacketNumber packet_number,
+ size_t bytes_written) {
+ scoped_ptr<QuicReceivedPacket> packet(
+ maker_.MakeRstPacket(packet_number, !kIncludeVersion, stream_id_,
+ QUIC_STREAM_CANCELLED, bytes_written));
+ DVLOG(2) << "packet(" << packet_number << "): " << std::endl
+ << QuicUtils::StringToHexASCIIDump(packet->AsStringPiece());
+ return packet;
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructAckAndRstStreamPacket(
+ QuicPacketNumber packet_number,
+ QuicPacketNumber largest_received,
+ QuicPacketNumber ack_least_unacked,
+ QuicPacketNumber stop_least_unacked) {
+ return maker_.MakeAckAndRstPacket(
+ packet_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED,
+ largest_received, ack_least_unacked, stop_least_unacked,
+ !kIncludeCongestionFeedback);
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructAckAndDataPacket(
+ QuicPacketNumber packet_number,
+ bool should_include_version,
+ QuicPacketNumber largest_received,
+ QuicPacketNumber least_unacked,
+ bool fin,
+ QuicStreamOffset offset,
+ base::StringPiece data) {
+ scoped_ptr<QuicReceivedPacket> packet(maker_.MakeAckAndDataPacket(
+ packet_number, should_include_version, stream_id_, largest_received,
+ least_unacked, fin, offset, data));
+ DVLOG(2) << "packet(" << packet_number << "): " << std::endl
+ << QuicUtils::StringToHexASCIIDump(packet->AsStringPiece());
+ return packet;
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructAckPacket(
+ QuicPacketNumber packet_number,
+ QuicPacketNumber largest_received,
+ QuicPacketNumber least_unacked) {
+ return maker_.MakeAckPacket(packet_number, largest_received, least_unacked,
+ !kIncludeCongestionFeedback);
+ }
+
+ const BoundTestNetLog& net_log() const { return net_log_; }
+
+ QuicChromiumClientSession* session() const { return session_.get(); }
+
+ private:
+ BoundTestNetLog net_log_;
+ scoped_refptr<TestTaskRunner> runner_;
+ scoped_ptr<MockWrite[]> mock_writes_;
+ MockClock clock_;
+ QuicConnection* connection_;
+ scoped_ptr<QuicChromiumConnectionHelper> helper_;
+ TransportSecurityState transport_security_state_;
+ scoped_ptr<QuicChromiumClientSession> session_;
+ QuicCryptoClientConfig crypto_config_;
+ HttpRequestHeaders headers_;
+ HttpResponseInfo response_;
+ scoped_refptr<IOBufferWithSize> read_buffer_;
+ SpdyHeaderBlock request_headers_;
+ const QuicConnectionId connection_id_;
+ const QuicStreamId stream_id_;
+ QuicTestPacketMaker maker_;
+ IPEndPoint self_addr_;
+ IPEndPoint peer_addr_;
+ MockRandom random_generator_;
+ MockCryptoClientStreamFactory crypto_client_stream_factory_;
+ scoped_ptr<StaticSocketDataProvider> socket_data_;
+ std::vector<PacketToWrite> writes_;
+ QuicClientPushPromiseIndex push_promise_index_;
+};
+
+INSTANTIATE_TEST_CASE_P(Version,
+ BidirectionalStreamQuicImplTest,
+ ::testing::ValuesIn(QuicSupportedVersions()));
+
+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));
+
+ AddWrite(ConstructAckPacket(2, 3, 1));
+ Initialize();
+
+ BidirectionalStreamRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.end_stream_on_headers = true;
+ request.priority = DEFAULT_PRIORITY;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ scoped_ptr<TestDelegateBase> delegate(
+ new TestDelegateBase(read_buffer.get(), kReadBufferSize));
+ delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
+ delegate->WaitUntilNextCallback(); // OnHeadersSent
+
+ // Server acks the request.
+ ProcessPacket(ConstructAckPacket(1, 0, 0));
+
+ // Server sends the response headers.
+ SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
+
+ size_t spdy_response_headers_frame_length;
+ QuicStreamOffset offset = 0;
+ ProcessPacket(ConstructResponseHeadersPacket(
+ 2, !kFin, response_headers, &spdy_response_headers_frame_length,
+ &offset));
+
+ delegate->WaitUntilNextCallback(); // OnHeadersReceived
+ TestCompletionCallback cb;
+ int rv = delegate->ReadData(cb.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
+ const char kResponseBody[] = "Hello world!";
+ // Server sends data.
+ ProcessPacket(
+ ConstructDataPacket(3, !kIncludeVersion, !kFin, 0, kResponseBody));
+ EXPECT_EQ(12, cb.WaitForResult());
+
+ EXPECT_EQ(std::string(kResponseBody), delegate->data_received());
+ TestCompletionCallback cb2;
+ EXPECT_EQ(ERR_IO_PENDING, delegate->ReadData(cb2.callback()));
+
+ SpdyHeaderBlock trailers;
+ size_t spdy_trailers_frame_length;
+ trailers["foo"] = "bar";
+ trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody));
+ // Server sends trailers.
+ ProcessPacket(ConstructResponseTrailersPacket(
+ 4, kFin, trailers, &spdy_trailers_frame_length, &offset));
+
+ delegate->WaitUntilNextCallback(); // OnTrailersReceived
+ EXPECT_EQ(OK, cb2.WaitForResult());
+ trailers.erase(kFinalOffsetHeaderKey);
+ EXPECT_EQ(trailers, delegate->trailers());
+
+ EXPECT_EQ(OK, delegate->ReadData(cb2.callback()));
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(2, delegate->on_data_read_count());
+ EXPECT_EQ(0, delegate->on_data_sent_count());
+ EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol());
+ EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
+ delegate->GetTotalSentBytes());
+ EXPECT_EQ(
+ static_cast<int64_t>(spdy_response_headers_frame_length +
+ strlen(kResponseBody) + spdy_trailers_frame_length),
+ delegate->GetTotalReceivedBytes());
+ // Check that NetLog was filled as expected.
+ TestNetLogEntry::List entries;
+ net_log().GetEntries(&entries);
+ size_t pos = ExpectLogContainsSomewhere(
+ entries, /*min_offset=*/0,
+ NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
+ NetLog::PHASE_NONE);
+ pos = ExpectLogContainsSomewhere(
+ entries, /*min_offset=*/pos,
+ NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
+ NetLog::PHASE_NONE);
+ ExpectLogContainsSomewhere(
+ entries, /*min_offset=*/pos,
+ NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
+ NetLog::PHASE_NONE);
+}
+
+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));
+ AddWrite(ConstructAckPacket(3, 3, 1));
+
+ Initialize();
+
+ BidirectionalStreamRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.google.com/");
+ request.end_stream_on_headers = false;
+ request.priority = DEFAULT_PRIORITY;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ scoped_ptr<TestDelegateBase> delegate(
+ new TestDelegateBase(read_buffer.get(), kReadBufferSize));
+ delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
+ delegate->WaitUntilNextCallback(); // OnHeadersSent
+
+ // Send a DATA frame.
+ scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(kUploadData));
+
+ delegate->SendData(buf.get(), buf->size(), true);
+ delegate->WaitUntilNextCallback(); // OnDataSent
+
+ // Server acks the request.
+ ProcessPacket(ConstructAckPacket(1, 0, 0));
+
+ // Server sends the response headers.
+ SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
+ size_t spdy_response_headers_frame_length;
+ QuicStreamOffset offset = 0;
+ ProcessPacket(ConstructResponseHeadersPacket(
+ 2, !kFin, response_headers, &spdy_response_headers_frame_length,
+ &offset));
+
+ delegate->WaitUntilNextCallback(); // OnHeadersReceived
+ TestCompletionCallback cb;
+ int rv = delegate->ReadData(cb.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
+ const char kResponseBody[] = "Hello world!";
+ // Server sends data.
+ ProcessPacket(
+ ConstructDataPacket(3, !kIncludeVersion, !kFin, 0, kResponseBody));
+
+ EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), cb.WaitForResult());
+
+ size_t spdy_trailers_frame_length;
+ SpdyHeaderBlock trailers;
+ trailers["foo"] = "bar";
+ trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody));
+ // Server sends trailers.
+ ProcessPacket(ConstructResponseTrailersPacket(
+ 4, kFin, trailers, &spdy_trailers_frame_length, &offset));
+
+ delegate->WaitUntilNextCallback(); // OnTrailersReceived
+ trailers.erase(kFinalOffsetHeaderKey);
+ EXPECT_EQ(trailers, delegate->trailers());
+ EXPECT_EQ(OK, delegate->ReadData(cb.callback()));
+
+ EXPECT_EQ(1, delegate->on_data_read_count());
+ EXPECT_EQ(1, delegate->on_data_sent_count());
+ EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol());
+ EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
+ strlen(kUploadData)),
+ delegate->GetTotalSentBytes());
+ EXPECT_EQ(
+ static_cast<int64_t>(spdy_response_headers_frame_length +
+ strlen(kResponseBody) + spdy_trailers_frame_length),
+ delegate->GetTotalReceivedBytes());
+}
+
+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,
+ kUploadData));
+ AddWrite(ConstructAckAndDataPacket(3, !kIncludeVersion, 3, 3, kFin,
+ strlen(kUploadData), kUploadData));
+ Initialize();
+
+ BidirectionalStreamRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.google.com/");
+ request.end_stream_on_headers = false;
+ request.priority = DEFAULT_PRIORITY;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ scoped_ptr<TestDelegateBase> delegate(
+ new TestDelegateBase(read_buffer.get(), kReadBufferSize));
+ delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
+ delegate->WaitUntilNextCallback(); // OnHeadersSent
+
+ // Server acks the request.
+ ProcessPacket(ConstructAckPacket(1, 0, 0));
+
+ // Server sends the response headers.
+ SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
+ size_t spdy_response_headers_frame_length;
+ ProcessPacket(ConstructResponseHeadersPacket(
+ 2, !kFin, response_headers, &spdy_response_headers_frame_length, 0));
+
+ delegate->WaitUntilNextCallback(); // OnHeadersReceived
+ EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
+
+ // Client sends a data packet.
+ scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(kUploadData));
+
+ delegate->SendData(buf.get(), buf->size(), false);
+ delegate->WaitUntilNextCallback(); // OnDataSent
+
+ TestCompletionCallback cb;
+ int rv = delegate->ReadData(cb.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ const char kResponseBody[] = "Hello world!";
+
+ // Server sends a data packet.
+ ProcessPacket(ConstructAckAndDataPacket(3, !kIncludeVersion, 2, 1, !kFin, 0,
+ kResponseBody));
+
+ EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb.WaitForResult());
+ EXPECT_EQ(std::string(kResponseBody), delegate->data_received());
+
+ // Client sends a data packet.
+ delegate->SendData(buf.get(), buf->size(), true);
+ delegate->WaitUntilNextCallback(); // OnDataSent
+
+ TestCompletionCallback cb2;
+ rv = delegate->ReadData(cb2.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ ProcessPacket(ConstructAckAndDataPacket(
+ 4, !kIncludeVersion, 3, 1, kFin, strlen(kResponseBody), kResponseBody));
+
+ EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb2.WaitForResult());
+
+ std::string expected_body(kResponseBody);
+ expected_body.append(kResponseBody);
+ EXPECT_EQ(expected_body, delegate->data_received());
+
+ EXPECT_EQ(OK, delegate->ReadData(cb.callback()));
+ EXPECT_EQ(2, delegate->on_data_read_count());
+ EXPECT_EQ(2, delegate->on_data_sent_count());
+ EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol());
+ EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
+ 2 * strlen(kUploadData)),
+ delegate->GetTotalSentBytes());
+ EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
+ 2 * strlen(kResponseBody)),
+ delegate->GetTotalReceivedBytes());
+}
+
+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));
+ Initialize();
+
+ BidirectionalStreamRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.end_stream_on_headers = true;
+ request.priority = DEFAULT_PRIORITY;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ scoped_ptr<TestDelegateBase> delegate(
+ new TestDelegateBase(read_buffer.get(), kReadBufferSize));
+ delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
+ delegate->WaitUntilNextCallback(); // OnHeadersSent
+
+ // Server sends a Rst.
+ ProcessPacket(ConstructRstStreamPacket(1));
+
+ delegate->WaitUntilNextCallback(); // OnFailed
+ TestCompletionCallback cb;
+ EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, delegate->ReadData(cb.callback()));
+
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, delegate->error());
+ EXPECT_EQ(0, delegate->on_data_read_count());
+ EXPECT_EQ(0, delegate->on_data_sent_count());
+ EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
+ delegate->GetTotalSentBytes());
+ EXPECT_EQ(0, delegate->GetTotalReceivedBytes());
+}
+
+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));
+ // Why does QUIC ack Rst? Is this expected?
+ AddWrite(ConstructAckPacket(2, 3, 1));
+
+ Initialize();
+
+ BidirectionalStreamRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.end_stream_on_headers = true;
+ request.priority = DEFAULT_PRIORITY;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ scoped_ptr<TestDelegateBase> delegate(
+ new TestDelegateBase(read_buffer.get(), kReadBufferSize));
+ delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
+ delegate->WaitUntilNextCallback(); // OnHeadersSent
+
+ // Server acks the request.
+ ProcessPacket(ConstructAckPacket(1, 0, 0));
+
+ // Server sends the response headers.
+ SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
+
+ size_t spdy_response_headers_frame_length;
+ QuicStreamOffset offset = 0;
+ ProcessPacket(ConstructResponseHeadersPacket(
+ 2, !kFin, response_headers, &spdy_response_headers_frame_length,
+ &offset));
+
+ delegate->WaitUntilNextCallback(); // OnHeadersReceived
+ EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
+
+ TestCompletionCallback cb;
+ int rv = delegate->ReadData(cb.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Server sends a Rst.
+ ProcessPacket(ConstructRstStreamPacket(3));
+
+ delegate->WaitUntilNextCallback(); // OnFailed
+
+ EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, delegate->ReadData(cb.callback()));
+ EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, delegate->error());
+ EXPECT_EQ(0, delegate->on_data_read_count());
+ EXPECT_EQ(0, delegate->on_data_sent_count());
+ EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
+ delegate->GetTotalSentBytes());
+ EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
+ delegate->GetTotalReceivedBytes());
+}
+
+TEST_P(BidirectionalStreamQuicImplTest, CancelStreamAfterSendData) {
+ 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,
+ kUploadData));
+ AddWrite(ConstructRstStreamCancelledPacket(3, strlen(kUploadData)));
+
+ Initialize();
+
+ BidirectionalStreamRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.google.com/");
+ request.end_stream_on_headers = false;
+ request.priority = DEFAULT_PRIORITY;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ scoped_ptr<TestDelegateBase> delegate(
+ new TestDelegateBase(read_buffer.get(), kReadBufferSize));
+ delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
+ delegate->WaitUntilNextCallback(); // OnHeadersSent
+
+ // Server acks the request.
+ ProcessPacket(ConstructAckPacket(1, 0, 0));
+
+ // Server sends the response headers.
+ SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
+ size_t spdy_response_headers_frame_length;
+ ProcessPacket(ConstructResponseHeadersPacket(
+ 2, !kFin, response_headers, &spdy_response_headers_frame_length, 0));
+
+ delegate->WaitUntilNextCallback(); // OnHeadersReceived
+ EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
+
+ // Send a DATA frame.
+ scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(kUploadData));
+
+ delegate->SendData(buf.get(), buf->size(), false);
+ delegate->WaitUntilNextCallback(); // OnDataSent
+
+ delegate->CancelStream();
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(0, delegate->on_data_read_count());
+ EXPECT_EQ(1, delegate->on_data_sent_count());
+ EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol());
+ EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
+ strlen(kUploadData)),
+ delegate->GetTotalSentBytes());
+ EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
+ delegate->GetTotalReceivedBytes());
+}
+
+TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeReadData) {
+ SetRequest("GET", "/", DEFAULT_PRIORITY);
+ size_t spdy_request_headers_frame_length;
+ AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length));
+ Initialize();
+
+ BidirectionalStreamRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.end_stream_on_headers = true;
+ request.priority = DEFAULT_PRIORITY;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ scoped_ptr<TestDelegateBase> delegate(
+ new TestDelegateBase(read_buffer.get(), kReadBufferSize));
+ delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
+ delegate->WaitUntilNextCallback(); // OnHeadersSent
+
+ // Server acks the request.
+ ProcessPacket(ConstructAckPacket(1, 0, 0));
+
+ // Server sends the response headers.
+ SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
+
+ size_t spdy_response_headers_frame_length;
+ QuicStreamOffset offset = 0;
+ ProcessPacket(ConstructResponseHeadersPacket(
+ 2, !kFin, response_headers, &spdy_response_headers_frame_length,
+ &offset));
+
+ delegate->WaitUntilNextCallback(); // OnHeadersReceived
+ TestCompletionCallback cb;
+ int rv = delegate->ReadData(cb.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ session()->connection()->CloseConnection(
+ QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
+ delegate->WaitUntilNextCallback(); // OnFailed
+
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(ERR_UNEXPECTED, delegate->ReadData(cb.callback()));
+ EXPECT_EQ(ERR_UNEXPECTED, delegate->error());
+ EXPECT_EQ(0, delegate->on_data_read_count());
+ EXPECT_EQ(0, delegate->on_data_sent_count());
+ EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol());
+ EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
+ delegate->GetTotalSentBytes());
+ EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
+ delegate->GetTotalReceivedBytes());
+}
+
+TEST_P(BidirectionalStreamQuicImplTest, CancelStreamAfterReadData) {
+ SetRequest("POST", "/", DEFAULT_PRIORITY);
+ size_t spdy_request_headers_frame_length;
+ AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length));
+ AddWrite(ConstructAckAndRstStreamPacket(2, 2, 1, 1));
+
+ Initialize();
+
+ BidirectionalStreamRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.google.com/");
+ request.end_stream_on_headers = false;
+ request.priority = DEFAULT_PRIORITY;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ scoped_ptr<TestDelegateBase> delegate(
+ new TestDelegateBase(read_buffer.get(), kReadBufferSize));
+ delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
+ delegate->WaitUntilNextCallback(); // OnHeadersSent
+
+ // Server acks the request.
+ ProcessPacket(ConstructAckPacket(1, 0, 0));
+
+ // Server sends the response headers.
+ SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
+ size_t spdy_response_headers_frame_length;
+ ProcessPacket(ConstructResponseHeadersPacket(
+ 2, !kFin, response_headers, &spdy_response_headers_frame_length, 0));
+
+ delegate->WaitUntilNextCallback(); // OnHeadersReceived
+ EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
+
+ // Cancel the stream after ReadData returns ERR_IO_PENDING.
+ TestCompletionCallback cb;
+ EXPECT_EQ(ERR_IO_PENDING, delegate->ReadData(cb.callback()));
+ delegate->CancelStream();
+
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(0, delegate->on_data_read_count());
+ EXPECT_EQ(0, delegate->on_data_sent_count());
+ EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol());
+ EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length),
+ delegate->GetTotalSentBytes());
+ EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length),
+ delegate->GetTotalReceivedBytes());
+}
+
+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(ConstructAckAndRstStreamPacket(2, 2, 1, 1));
+
+ Initialize();
+
+ BidirectionalStreamRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.google.com/");
+ request.end_stream_on_headers = false;
+ request.priority = DEFAULT_PRIORITY;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ scoped_ptr<DeleteStreamDelegate> delegate(new DeleteStreamDelegate(
+ read_buffer.get(), kReadBufferSize,
+ DeleteStreamDelegate::ON_HEADERS_RECEIVED, true));
+ delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
+ delegate->WaitUntilNextCallback(); // OnHeadersSent
+
+ // Server acks the request.
+ ProcessPacket(ConstructAckPacket(1, 0, 0));
+
+ // Server sends the response headers.
+ SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
+
+ size_t spdy_response_headers_frame_length;
+ ProcessPacket(ConstructResponseHeadersPacket(
+ 2, !kFin, response_headers, &spdy_response_headers_frame_length,
+ nullptr));
+
+ delegate->WaitUntilNextCallback(); // OnHeadersReceived
+ EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
+
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(0, delegate->on_data_read_count());
+ EXPECT_EQ(0, delegate->on_data_sent_count());
+}
+
+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(ConstructAckPacket(2, 3, 1));
+ AddWrite(ConstructRstStreamPacket(3));
+
+ Initialize();
+
+ BidirectionalStreamRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.google.com/");
+ request.end_stream_on_headers = false;
+ request.priority = DEFAULT_PRIORITY;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ scoped_ptr<DeleteStreamDelegate> delegate(
+ new DeleteStreamDelegate(read_buffer.get(), kReadBufferSize,
+ DeleteStreamDelegate::ON_DATA_READ, true));
+ delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
+ delegate->WaitUntilNextCallback(); // OnHeadersSent
+
+ // Server acks the request.
+ ProcessPacket(ConstructAckPacket(1, 0, 0));
+
+ // Server sends the response headers.
+ SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
+
+ size_t spdy_response_headers_frame_length;
+ ProcessPacket(ConstructResponseHeadersPacket(
+ 2, !kFin, response_headers, &spdy_response_headers_frame_length,
+ nullptr));
+
+ delegate->WaitUntilNextCallback(); // OnHeadersReceived
+
+ EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
+
+ TestCompletionCallback cb;
+ int rv = delegate->ReadData(cb.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ const char kResponseBody[] = "Hello world!";
+ // Server sends data.
+ ProcessPacket(
+ ConstructDataPacket(3, !kIncludeVersion, !kFin, 0, kResponseBody));
+ EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb.WaitForResult());
+
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(1, delegate->on_data_read_count());
+ EXPECT_EQ(0, delegate->on_data_sent_count());
+}
+
+TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnTrailersReceived) {
+ SetRequest("GET", "/", DEFAULT_PRIORITY);
+ size_t spdy_request_headers_frame_length;
+ AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length));
+ AddWrite(ConstructAckPacket(2, 3, 1)); // Ack the data packet
+
+ Initialize();
+
+ BidirectionalStreamRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.end_stream_on_headers = true;
+ request.priority = DEFAULT_PRIORITY;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ scoped_ptr<DeleteStreamDelegate> delegate(new DeleteStreamDelegate(
+ read_buffer.get(), kReadBufferSize,
+ DeleteStreamDelegate::ON_TRAILERS_RECEIVED, true));
+ delegate->Start(&request, net_log().bound(), session()->GetWeakPtr());
+ delegate->WaitUntilNextCallback(); // OnHeadersSent
+
+ // Server acks the request.
+ ProcessPacket(ConstructAckPacket(1, 0, 0));
+
+ // Server sends the response headers.
+ SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
+
+ QuicStreamOffset offset = 0;
+ size_t spdy_response_headers_frame_length;
+ ProcessPacket(ConstructResponseHeadersPacket(
+ 2, !kFin, response_headers, &spdy_response_headers_frame_length,
+ &offset));
+
+ delegate->WaitUntilNextCallback(); // OnHeadersReceived
+
+ EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
+
+ TestCompletionCallback cb;
+ int rv = delegate->ReadData(cb.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ const char kResponseBody[] = "Hello world!";
+ // Server sends data.
+ ProcessPacket(
+ ConstructDataPacket(3, !kIncludeVersion, !kFin, 0, kResponseBody));
+
+ EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb.WaitForResult());
+ EXPECT_EQ(std::string(kResponseBody), delegate->data_received());
+
+ size_t spdy_trailers_frame_length;
+ SpdyHeaderBlock trailers;
+ trailers["foo"] = "bar";
+ trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody));
+ // Server sends trailers.
+ ProcessPacket(ConstructResponseTrailersPacket(
+ 4, kFin, trailers, &spdy_trailers_frame_length, &offset));
+
+ delegate->WaitUntilNextCallback(); // OnTrailersReceived
+ trailers.erase(kFinalOffsetHeaderKey);
+ EXPECT_EQ(trailers, delegate->trailers());
+
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(1, delegate->on_data_read_count());
+ EXPECT_EQ(0, delegate->on_data_sent_count());
+}
+
+} // namespace test
+
+} // namespace net
diff --git a/chromium/net/quic/congestion_control/general_loss_algorithm.cc b/chromium/net/quic/congestion_control/general_loss_algorithm.cc
index 887341f5adb..69623b0362a 100644
--- a/chromium/net/quic/congestion_control/general_loss_algorithm.cc
+++ b/chromium/net/quic/congestion_control/general_loss_algorithm.cc
@@ -5,6 +5,7 @@
#include "net/quic/congestion_control/general_loss_algorithm.h"
#include "net/quic/congestion_control/rtt_stats.h"
+#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_protocol.h"
namespace net {
@@ -32,25 +33,10 @@ LossDetectionType GeneralLossAlgorithm::GetLossDetectionType() const {
return loss_type_;
}
-PacketNumberSet GeneralLossAlgorithm::DetectLostPackets(
- const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
- QuicPacketNumber largest_observed,
- const RttStats& rtt_stats) {
- SendAlgorithmInterface::CongestionVector packets_lost;
- DetectLosses(unacked_packets, time, rtt_stats, &packets_lost);
- PacketNumberSet lost_packets;
- for (const std::pair<QuicPacketNumber, QuicPacketLength>& pair :
- packets_lost) {
- lost_packets.insert(pair.first);
- }
- return lost_packets;
-}
-
// Uses nack counts to decide when packets are lost.
void GeneralLossAlgorithm::DetectLosses(
const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
+ QuicTime time,
const RttStats& rtt_stats,
SendAlgorithmInterface::CongestionVector* packets_lost) {
const QuicPacketNumber largest_observed = unacked_packets.largest_observed();
@@ -80,9 +66,9 @@ void GeneralLossAlgorithm::DetectLosses(
}
// FACK based loss detection.
- LOG_IF(DFATAL, it->nack_count == 0 && it->sent_time.IsInitialized())
+ QUIC_BUG_IF(it->nack_count == 0 && it->sent_time.IsInitialized())
<< "All packets less than largest observed should have been nacked."
- << "packet_number:" << packet_number
+ << " packet_number:" << packet_number
<< " largest_observed:" << largest_observed;
if (it->nack_count >= kNumberOfNacksBeforeRetransmission) {
packets_lost->push_back(std::make_pair(packet_number, it->bytes_sent));
@@ -99,7 +85,7 @@ void GeneralLossAlgorithm::DetectLosses(
// Only early retransmit(RFC5827) when the last packet gets acked and
// there are retransmittable packets in flight.
// This also implements a timer-protected variant of FACK.
- if (it->retransmittable_frames &&
+ if (!it->retransmittable_frames.empty() &&
unacked_packets.largest_sent_packet() == largest_observed) {
// Early retransmit marks the packet as lost once 1.25RTTs have passed
// since the packet was sent and otherwise sets an alarm.
diff --git a/chromium/net/quic/congestion_control/general_loss_algorithm.h b/chromium/net/quic/congestion_control/general_loss_algorithm.h
index 54c170fcbca..f1a2ec4c903 100644
--- a/chromium/net/quic/congestion_control/general_loss_algorithm.h
+++ b/chromium/net/quic/congestion_control/general_loss_algorithm.h
@@ -33,16 +33,10 @@ class NET_EXPORT_PRIVATE GeneralLossAlgorithm : public LossDetectionInterface {
loss_type_ = loss_type;
}
- // Only supported for tests.
- PacketNumberSet DetectLostPackets(const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
- QuicPacketNumber largest_observed,
- const RttStats& rtt_stats) override;
-
// Uses |largest_observed| and time to decide when packets are lost.
void DetectLosses(
const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
+ QuicTime time,
const RttStats& rtt_stats,
SendAlgorithmInterface::CongestionVector* packets_lost) override;
diff --git a/chromium/net/quic/congestion_control/general_loss_algorithm_test.cc b/chromium/net/quic/congestion_control/general_loss_algorithm_test.cc
index f6ea74280fc..580ce84d12f 100644
--- a/chromium/net/quic/congestion_control/general_loss_algorithm_test.cc
+++ b/chromium/net/quic/congestion_control/general_loss_algorithm_test.cc
@@ -29,34 +29,32 @@ class GeneralLossAlgorithmTest : public ::testing::Test {
QuicTime::Delta::Zero(), clock_.Now());
}
- ~GeneralLossAlgorithmTest() override { STLDeleteElements(&packets_); }
+ ~GeneralLossAlgorithmTest() override {}
void SendDataPacket(QuicPacketNumber packet_number) {
- packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
- RetransmittableFrames* frames = new RetransmittableFrames();
QuicStreamFrame* frame = new QuicStreamFrame();
frame->stream_id = kHeadersStreamId;
- frames->AddFrame(QuicFrame(frame));
SerializedPacket packet(kDefaultPathId, packet_number,
- PACKET_1BYTE_PACKET_NUMBER, packets_.back(), 0,
- frames, false, false);
+ PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
+ 0, false, false);
+ packet.retransmittable_frames.push_back(QuicFrame(frame));
unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(),
- 1000, true);
+ true);
}
void VerifyLosses(QuicPacketNumber largest_observed,
QuicPacketNumber* losses_expected,
size_t num_losses) {
unacked_packets_.IncreaseLargestObserved(largest_observed);
- PacketNumberSet lost_packets = loss_algorithm_.DetectLostPackets(
- unacked_packets_, clock_.Now(), largest_observed, rtt_stats_);
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ loss_algorithm_.DetectLosses(unacked_packets_, clock_.Now(), rtt_stats_,
+ &lost_packets);
EXPECT_EQ(num_losses, lost_packets.size());
for (size_t i = 0; i < num_losses; ++i) {
- EXPECT_TRUE(ContainsKey(lost_packets, losses_expected[i]));
+ EXPECT_EQ(lost_packets[i].first, losses_expected[i]);
}
}
- vector<QuicEncryptedPacket*> packets_;
QuicUnackedPacketMap unacked_packets_;
GeneralLossAlgorithm loss_algorithm_;
RttStats rtt_stats_;
diff --git a/chromium/net/quic/congestion_control/hybrid_slow_start.cc b/chromium/net/quic/congestion_control/hybrid_slow_start.cc
index a5f53f967d9..5f334c74ed6 100644
--- a/chromium/net/quic/congestion_control/hybrid_slow_start.cc
+++ b/chromium/net/quic/congestion_control/hybrid_slow_start.cc
@@ -30,12 +30,11 @@ HybridSlowStart::HybridSlowStart()
rtt_sample_count_(0),
current_min_rtt_(QuicTime::Delta::Zero()) {}
-void HybridSlowStart::OnPacketAcked(QuicPacketNumber acked_packet_number,
- bool in_slow_start) {
+void HybridSlowStart::OnPacketAcked(QuicPacketNumber acked_packet_number) {
// OnPacketAcked gets invoked after ShouldExitSlowStart, so it's best to end
// the round when the final packet of the burst is received and start it on
// the next incoming ack.
- if (in_slow_start && IsEndOfRound(acked_packet_number)) {
+ if (IsEndOfRound(acked_packet_number)) {
started_ = false;
}
}
diff --git a/chromium/net/quic/congestion_control/hybrid_slow_start.h b/chromium/net/quic/congestion_control/hybrid_slow_start.h
index cf752f65464..dbd440dffb5 100644
--- a/chromium/net/quic/congestion_control/hybrid_slow_start.h
+++ b/chromium/net/quic/congestion_control/hybrid_slow_start.h
@@ -29,7 +29,7 @@ class NET_EXPORT_PRIVATE HybridSlowStart {
public:
HybridSlowStart();
- void OnPacketAcked(QuicPacketNumber acked_packet_number, bool in_slow_start);
+ void OnPacketAcked(QuicPacketNumber acked_packet_number);
void OnPacketSent(QuicPacketNumber packet_number);
diff --git a/chromium/net/quic/congestion_control/loss_detection_interface.cc b/chromium/net/quic/congestion_control/loss_detection_interface.cc
index 4db56c99435..bf894286d33 100644
--- a/chromium/net/quic/congestion_control/loss_detection_interface.cc
+++ b/chromium/net/quic/congestion_control/loss_detection_interface.cc
@@ -5,8 +5,7 @@
#include "net/quic/congestion_control/loss_detection_interface.h"
#include "net/quic/congestion_control/general_loss_algorithm.h"
-#include "net/quic/congestion_control/tcp_loss_algorithm.h"
-#include "net/quic/congestion_control/time_loss_algorithm.h"
+#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_flags.h"
namespace net {
@@ -14,17 +13,7 @@ namespace net {
// Factory for loss detection algorithm.
LossDetectionInterface* LossDetectionInterface::Create(
LossDetectionType loss_type) {
- if (FLAGS_quic_general_loss_algorithm) {
- return new GeneralLossAlgorithm(loss_type);
- }
- switch (loss_type) {
- case kNack:
- return new TCPLossAlgorithm();
- case kTime:
- return new TimeLossAlgorithm();
- }
- LOG(DFATAL) << "Unknown loss detection algorithm:" << loss_type;
- return nullptr;
+ return new GeneralLossAlgorithm(loss_type);
}
} // namespace net
diff --git a/chromium/net/quic/congestion_control/loss_detection_interface.h b/chromium/net/quic/congestion_control/loss_detection_interface.h
index d337dbe2033..323c2fd7275 100644
--- a/chromium/net/quic/congestion_control/loss_detection_interface.h
+++ b/chromium/net/quic/congestion_control/loss_detection_interface.h
@@ -26,15 +26,9 @@ class NET_EXPORT_PRIVATE LossDetectionInterface {
virtual LossDetectionType GetLossDetectionType() const = 0;
// Called when a new ack arrives or the loss alarm fires.
- virtual PacketNumberSet DetectLostPackets(
- const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
- QuicPacketNumber largest_observed,
- const RttStats& rtt_stats) = 0;
-
virtual void DetectLosses(
const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
+ QuicTime time,
const RttStats& rtt_stats,
SendAlgorithmInterface::CongestionVector* packets_lost) = 0;
diff --git a/chromium/net/quic/congestion_control/pacing_sender.cc b/chromium/net/quic/congestion_control/pacing_sender.cc
index 040310f5b90..8b1e5354bbd 100644
--- a/chromium/net/quic/congestion_control/pacing_sender.cc
+++ b/chromium/net/quic/congestion_control/pacing_sender.cc
@@ -79,7 +79,7 @@ bool PacingSender::OnPacketSent(
}
// The next packet should be sent as soon as the current packets has been
// transferred.
- QuicTime::Delta delay = PacingRate().TransferTime(bytes);
+ QuicTime::Delta delay = sender_->PacingRate().TransferTime(bytes);
// If the last send was delayed, and the alarm took a long time to get
// invoked, allow the connection to make up for lost time.
if (was_last_send_delayed_) {
@@ -111,12 +111,15 @@ void PacingSender::OnRetransmissionTimeout(bool packets_retransmitted) {
sender_->OnRetransmissionTimeout(packets_retransmitted);
}
+void PacingSender::OnConnectionMigration() {
+ sender_->OnConnectionMigration();
+}
+
QuicTime::Delta PacingSender::TimeUntilSend(
QuicTime now,
- QuicByteCount bytes_in_flight,
- HasRetransmittableData has_retransmittable_data) const {
+ QuicByteCount bytes_in_flight) const {
QuicTime::Delta time_until_send =
- sender_->TimeUntilSend(now, bytes_in_flight, has_retransmittable_data);
+ sender_->TimeUntilSend(now, bytes_in_flight);
if (burst_tokens_ > 0 || bytes_in_flight == 0) {
// Don't pace if we have burst tokens available or leaving quiescence.
return time_until_send;
@@ -128,12 +131,6 @@ QuicTime::Delta PacingSender::TimeUntilSend(
return time_until_send;
}
- if (has_retransmittable_data == NO_RETRANSMITTABLE_DATA) {
- // Don't pace ACK packets, since they do not count against CWND and do not
- // cause CWND to grow.
- return QuicTime::Delta::Zero();
- }
-
// If the next send time is within the alarm granularity, send immediately.
if (ideal_next_packet_send_time_ > now.Add(alarm_granularity_)) {
DVLOG(1) << "Delaying packet: "
diff --git a/chromium/net/quic/congestion_control/pacing_sender.h b/chromium/net/quic/congestion_control/pacing_sender.h
index 185fec435f6..3aeedd29673 100644
--- a/chromium/net/quic/congestion_control/pacing_sender.h
+++ b/chromium/net/quic/congestion_control/pacing_sender.h
@@ -54,11 +54,9 @@ class NET_EXPORT_PRIVATE PacingSender : public SendAlgorithmInterface {
QuicByteCount bytes,
HasRetransmittableData is_retransmittable) override;
void OnRetransmissionTimeout(bool packets_retransmitted) override;
- void OnConnectionMigration() override {}
- QuicTime::Delta TimeUntilSend(
- QuicTime now,
- QuicByteCount bytes_in_flight,
- HasRetransmittableData has_retransmittable_data) const override;
+ void OnConnectionMigration() override;
+ QuicTime::Delta TimeUntilSend(QuicTime now,
+ QuicByteCount bytes_in_flight) const override;
QuicBandwidth PacingRate() const override;
QuicBandwidth BandwidthEstimate() const override;
QuicTime::Delta RetransmissionDelay() const override;
diff --git a/chromium/net/quic/congestion_control/pacing_sender_test.cc b/chromium/net/quic/congestion_control/pacing_sender_test.cc
index 4320b91820c..fbbcfecbbc8 100644
--- a/chromium/net/quic/congestion_control/pacing_sender_test.cc
+++ b/chromium/net/quic/congestion_control/pacing_sender_test.cc
@@ -51,13 +51,11 @@ class PacingSenderTest : public ::testing::Test {
// In order for the packet to be sendable, the underlying sender must
// permit it to be sent immediately.
for (int i = 0; i < 2; ++i) {
- EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), bytes_in_flight,
- retransmittable_data))
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), bytes_in_flight))
.WillOnce(Return(zero_time_));
// Verify that the packet can be sent immediately.
EXPECT_EQ(zero_time_,
- pacing_sender_->TimeUntilSend(clock_.Now(), bytes_in_flight,
- retransmittable_data));
+ pacing_sender_->TimeUntilSend(clock_.Now(), bytes_in_flight));
}
// Actually send the packet.
@@ -77,22 +75,15 @@ class PacingSenderTest : public ::testing::Test {
false);
}
- void CheckAckIsSentImmediately() {
- CheckPacketIsSentImmediately(NO_RETRANSMITTABLE_DATA, kBytesInFlight,
- false);
- }
-
void CheckPacketIsDelayed(QuicTime::Delta delay) {
// In order for the packet to be sendable, the underlying sender must
// permit it to be sent immediately.
for (int i = 0; i < 2; ++i) {
- EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA))
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), kBytesInFlight))
.WillOnce(Return(zero_time_));
// Verify that the packet is delayed.
EXPECT_EQ(delay.ToMicroseconds(),
- pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA)
+ pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight)
.ToMicroseconds());
}
}
@@ -114,23 +105,19 @@ class PacingSenderTest : public ::testing::Test {
TEST_F(PacingSenderTest, NoSend) {
for (int i = 0; i < 2; ++i) {
- EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA))
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), kBytesInFlight))
.WillOnce(Return(infinite_time_));
EXPECT_EQ(infinite_time_,
- pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA));
+ pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight));
}
}
TEST_F(PacingSenderTest, SendNow) {
for (int i = 0; i < 2; ++i) {
- EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA))
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), kBytesInFlight))
.WillOnce(Return(zero_time_));
EXPECT_EQ(zero_time_,
- pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA));
+ pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight));
}
}
@@ -154,7 +141,6 @@ TEST_F(PacingSenderTest, VariousSending) {
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
- CheckAckIsSentImmediately();
// Wake up late.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(4));
@@ -324,5 +310,72 @@ TEST_F(PacingSenderTest, NoBurstInRecovery) {
CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
}
+TEST_F(PacingSenderTest, VerifyInnerSenderCalled) {
+ QuicBandwidth kBandwidth = QuicBandwidth::FromBitsPerSecond(1000);
+ QuicTime kTime = QuicTime::Infinite();
+ QuicTime::Delta kTimeDelta = QuicTime::Delta::Infinite();
+ QuicByteCount kBytes = 12345u;
+
+ EXPECT_CALL(*mock_sender_, SetFromConfig(_, Perspective::IS_SERVER));
+ QuicConfig config;
+ pacing_sender_->SetFromConfig(config, Perspective::IS_SERVER);
+
+ EXPECT_CALL(*mock_sender_, ResumeConnectionState(_, true));
+ CachedNetworkParameters cached_network_params;
+ pacing_sender_->ResumeConnectionState(cached_network_params, true);
+
+ EXPECT_CALL(*mock_sender_, SetNumEmulatedConnections(2));
+ pacing_sender_->SetNumEmulatedConnections(2);
+
+ EXPECT_CALL(*mock_sender_, SetMaxCongestionWindow(kBytes));
+ pacing_sender_->SetMaxCongestionWindow(kBytes);
+
+ SendAlgorithmInterface::CongestionVector packets;
+ EXPECT_CALL(*mock_sender_, OnCongestionEvent(true, kBytes, packets, packets));
+ pacing_sender_->OnCongestionEvent(true, kBytes, packets, packets);
+
+ EXPECT_CALL(*mock_sender_, OnPacketSent(kTime, kBytes, 123u, kBytes,
+ HAS_RETRANSMITTABLE_DATA));
+ EXPECT_CALL(*mock_sender_, PacingRate()).WillOnce(Return(kBandwidth));
+ pacing_sender_->OnPacketSent(kTime, kBytes, 123u, kBytes,
+ HAS_RETRANSMITTABLE_DATA);
+
+ EXPECT_CALL(*mock_sender_, OnRetransmissionTimeout(true));
+ pacing_sender_->OnRetransmissionTimeout(true);
+
+ EXPECT_CALL(*mock_sender_, OnConnectionMigration());
+ pacing_sender_->OnConnectionMigration();
+
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(kTime, kBytes))
+ .WillOnce(Return(kTimeDelta));
+ pacing_sender_->TimeUntilSend(kTime, kBytes);
+
+ EXPECT_CALL(*mock_sender_, PacingRate()).WillOnce(Return(kBandwidth));
+ EXPECT_EQ(kBandwidth, pacing_sender_->PacingRate());
+
+ EXPECT_CALL(*mock_sender_, BandwidthEstimate()).WillOnce(Return(kBandwidth));
+ EXPECT_EQ(kBandwidth, pacing_sender_->BandwidthEstimate());
+
+ EXPECT_CALL(*mock_sender_, RetransmissionDelay())
+ .WillOnce(Return(kTimeDelta));
+ EXPECT_EQ(kTimeDelta, pacing_sender_->RetransmissionDelay());
+
+ EXPECT_CALL(*mock_sender_, GetCongestionWindow()).WillOnce(Return(kBytes));
+ EXPECT_EQ(kBytes, pacing_sender_->GetCongestionWindow());
+
+ EXPECT_CALL(*mock_sender_, InSlowStart()).WillOnce(Return(true));
+ EXPECT_TRUE(pacing_sender_->InSlowStart());
+
+ EXPECT_CALL(*mock_sender_, InRecovery()).WillOnce(Return(true));
+ EXPECT_TRUE(pacing_sender_->InRecovery());
+
+ EXPECT_CALL(*mock_sender_, GetSlowStartThreshold()).WillOnce(Return(kBytes));
+ EXPECT_EQ(kBytes, pacing_sender_->GetSlowStartThreshold());
+
+ EXPECT_CALL(*mock_sender_, GetCongestionControlType())
+ .WillOnce(Return(kReno));
+ EXPECT_EQ(kReno, pacing_sender_->GetCongestionControlType());
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/congestion_control/rtt_stats.h b/chromium/net/quic/congestion_control/rtt_stats.h
index 0827fa3c5b0..736178e9ead 100644
--- a/chromium/net/quic/congestion_control/rtt_stats.h
+++ b/chromium/net/quic/congestion_control/rtt_stats.h
@@ -12,6 +12,7 @@
#include <algorithm>
#include "base/macros.h"
+#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_time.h"
@@ -52,7 +53,7 @@ class NET_EXPORT_PRIVATE RttStats {
// Sets an initial RTT to be used for SmoothedRtt before any RTT updates.
void set_initial_rtt_us(int64_t initial_rtt_us) {
if (initial_rtt_us <= 0) {
- LOG(DFATAL) << "Attempt to set initial rtt to <= 0.";
+ QUIC_BUG << "Attempt to set initial rtt to <= 0.";
return;
}
initial_rtt_us_ = initial_rtt_us;
diff --git a/chromium/net/quic/congestion_control/send_algorithm_interface.cc b/chromium/net/quic/congestion_control/send_algorithm_interface.cc
index d8a9c93c396..83de14f2377 100644
--- a/chromium/net/quic/congestion_control/send_algorithm_interface.cc
+++ b/chromium/net/quic/congestion_control/send_algorithm_interface.cc
@@ -4,8 +4,9 @@
#include "net/quic/congestion_control/send_algorithm_interface.h"
-#include "net/quic/congestion_control/tcp_cubic_bytes_sender.h"
-#include "net/quic/congestion_control/tcp_cubic_sender.h"
+#include "net/quic/congestion_control/tcp_cubic_sender_bytes.h"
+#include "net/quic/congestion_control/tcp_cubic_sender_packets.h"
+#include "net/quic/quic_flags.h"
#include "net/quic/quic_protocol.h"
namespace net {
@@ -24,19 +25,19 @@ SendAlgorithmInterface* SendAlgorithmInterface::Create(
kDefaultTCPMSS;
switch (congestion_control_type) {
case kCubic:
- return new TcpCubicSender(clock, rtt_stats, false /* don't use Reno */,
- initial_congestion_window,
- max_congestion_window, stats);
+ return new TcpCubicSenderPackets(
+ clock, rtt_stats, false /* don't use Reno */,
+ initial_congestion_window, max_congestion_window, stats);
case kCubicBytes:
- return new TcpCubicBytesSender(
+ return new TcpCubicSenderBytes(
clock, rtt_stats, false /* don't use Reno */,
initial_congestion_window, max_congestion_window, stats);
case kReno:
- return new TcpCubicSender(clock, rtt_stats, true /* use Reno */,
- initial_congestion_window,
- max_congestion_window, stats);
+ return new TcpCubicSenderPackets(clock, rtt_stats, true /* use Reno */,
+ initial_congestion_window,
+ max_congestion_window, stats);
case kRenoBytes:
- return new TcpCubicBytesSender(clock, rtt_stats, true /* use Reno */,
+ return new TcpCubicSenderBytes(clock, rtt_stats, true /* use Reno */,
initial_congestion_window,
max_congestion_window, stats);
case kBBR:
diff --git a/chromium/net/quic/congestion_control/send_algorithm_interface.h b/chromium/net/quic/congestion_control/send_algorithm_interface.h
index fcd9db449bd..c07aa8f017f 100644
--- a/chromium/net/quic/congestion_control/send_algorithm_interface.h
+++ b/chromium/net/quic/congestion_control/send_algorithm_interface.h
@@ -80,8 +80,7 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
// Calculate the time until we can send the next packet.
virtual QuicTime::Delta TimeUntilSend(
QuicTime now,
- QuicByteCount bytes_in_flight,
- HasRetransmittableData has_retransmittable_data) const = 0;
+ QuicByteCount bytes_in_flight) const = 0;
// The pacing rate of the send algorithm. May be zero if the rate is unknown.
virtual QuicBandwidth PacingRate() const = 0;
diff --git a/chromium/net/quic/congestion_control/send_algorithm_simulator.cc b/chromium/net/quic/congestion_control/send_algorithm_simulator.cc
index 83326f38120..46f7db364b6 100644
--- a/chromium/net/quic/congestion_control/send_algorithm_simulator.cc
+++ b/chromium/net/quic/congestion_control/send_algorithm_simulator.cc
@@ -148,7 +148,7 @@ SendAlgorithmSimulator::PacketEvent SendAlgorithmSimulator::NextSendEvent() {
QuicTime::Delta transfer_send_time = it->start_time.Subtract(clock_->Now());
if (clock_->Now() >= it->start_time) {
transfer_send_time = it->sender->send_algorithm->TimeUntilSend(
- clock_->Now(), it->bytes_in_flight, HAS_RETRANSMITTABLE_DATA);
+ clock_->Now(), it->bytes_in_flight);
}
if (transfer_send_time < next_send_time) {
next_send_time = transfer_send_time;
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_bytes_sender.cc b/chromium/net/quic/congestion_control/tcp_cubic_bytes_sender.cc
deleted file mode 100644
index ef6172a9293..00000000000
--- a/chromium/net/quic/congestion_control/tcp_cubic_bytes_sender.cc
+++ /dev/null
@@ -1,388 +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/congestion_control/tcp_cubic_bytes_sender.h"
-
-#include <algorithm>
-
-#include "net/quic/congestion_control/prr_sender.h"
-#include "net/quic/congestion_control/rtt_stats.h"
-#include "net/quic/crypto/crypto_protocol.h"
-#include "net/quic/proto/cached_network_parameters.pb.h"
-#include "net/quic/quic_flags.h"
-
-using std::max;
-using std::min;
-
-namespace net {
-
-namespace {
-// Constants based on TCP defaults.
-// The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a
-// fast retransmission.
-const QuicByteCount kDefaultMinimumCongestionWindow = 2 * kDefaultTCPMSS;
-const QuicByteCount kMaxBurstBytes = 3 * kDefaultTCPMSS;
-const float kRenoBeta = 0.7f; // Reno backoff factor.
-const uint32_t kDefaultNumConnections = 2; // N-connection emulation.
-} // namespace
-
-TcpCubicBytesSender::TcpCubicBytesSender(
- const QuicClock* clock,
- const RttStats* rtt_stats,
- bool reno,
- QuicPacketCount initial_tcp_congestion_window,
- QuicPacketCount max_congestion_window,
- QuicConnectionStats* stats)
- : cubic_(clock),
- rtt_stats_(rtt_stats),
- stats_(stats),
- reno_(reno),
- num_connections_(kDefaultNumConnections),
- num_acked_packets_(0),
- largest_sent_packet_number_(0),
- largest_acked_packet_number_(0),
- largest_sent_at_last_cutback_(0),
- congestion_window_(initial_tcp_congestion_window * kDefaultTCPMSS),
- min_congestion_window_(kDefaultMinimumCongestionWindow),
- min4_mode_(false),
- max_congestion_window_(max_congestion_window * kDefaultTCPMSS),
- slowstart_threshold_(max_congestion_window * kDefaultTCPMSS),
- last_cutback_exited_slowstart_(false),
- initial_tcp_congestion_window_(initial_tcp_congestion_window *
- kDefaultTCPMSS),
- initial_max_tcp_congestion_window_(max_congestion_window *
- kDefaultTCPMSS),
- slow_start_large_reduction_(false) {}
-
-TcpCubicBytesSender::~TcpCubicBytesSender() {}
-
-void TcpCubicBytesSender::SetFromConfig(const QuicConfig& config,
- Perspective perspective) {
- if (perspective == Perspective::IS_SERVER) {
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kIW10)) {
- // Initial window experiment.
- congestion_window_ = 10 * kDefaultTCPMSS;
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN1)) {
- // Min CWND experiment.
- min_congestion_window_ = kDefaultTCPMSS;
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN4)) {
- // Min CWND of 4 experiment.
- min4_mode_ = true;
- min_congestion_window_ = kDefaultTCPMSS;
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kSSLR)) {
- // Slow Start Fast Exit experiment.
- slow_start_large_reduction_ = true;
- }
- }
-}
-
-void TcpCubicBytesSender::ResumeConnectionState(
- const CachedNetworkParameters& cached_network_params,
- bool max_bandwidth_resumption) {
- QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond(
- max_bandwidth_resumption
- ? cached_network_params.max_bandwidth_estimate_bytes_per_second()
- : cached_network_params.bandwidth_estimate_bytes_per_second());
- QuicTime::Delta rtt_ms =
- QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms());
-
- // Make sure CWND is in appropriate range (in case of bad data).
- QuicByteCount new_congestion_window = bandwidth.ToBytesPerPeriod(rtt_ms);
- congestion_window_ =
- max(min(new_congestion_window, kMaxCongestionWindow * kDefaultTCPMSS),
- kMinCongestionWindowForBandwidthResumption * kDefaultTCPMSS);
-}
-
-void TcpCubicBytesSender::SetNumEmulatedConnections(int num_connections) {
- num_connections_ = max(1, num_connections);
- cubic_.SetNumConnections(num_connections_);
-}
-
-void TcpCubicBytesSender::SetMaxCongestionWindow(
- QuicByteCount max_congestion_window) {
- max_congestion_window_ = max_congestion_window;
-}
-
-float TcpCubicBytesSender::RenoBeta() const {
- // kNConnectionBeta is the backoff factor after loss for our N-connection
- // emulation, which emulates the effective backoff of an ensemble of N
- // TCP-Reno connections on a single loss event. The effective multiplier is
- // computed as:
- return (num_connections_ - 1 + kRenoBeta) / num_connections_;
-}
-
-void TcpCubicBytesSender::OnCongestionEvent(
- bool rtt_updated,
- QuicByteCount bytes_in_flight,
- const CongestionVector& acked_packets,
- const CongestionVector& lost_packets) {
- if (rtt_updated && InSlowStart() &&
- hybrid_slow_start_.ShouldExitSlowStart(
- rtt_stats_->latest_rtt(), rtt_stats_->min_rtt(),
- congestion_window_ / kDefaultTCPMSS)) {
- slowstart_threshold_ = congestion_window_;
- }
- for (CongestionVector::const_iterator it = lost_packets.begin();
- it != lost_packets.end(); ++it) {
- OnPacketLost(it->first, bytes_in_flight);
- }
- for (CongestionVector::const_iterator it = acked_packets.begin();
- it != acked_packets.end(); ++it) {
- OnPacketAcked(it->first, it->second, bytes_in_flight);
- }
-}
-
-void TcpCubicBytesSender::OnPacketAcked(QuicPacketNumber acked_packet_number,
- QuicByteCount acked_bytes,
- QuicByteCount bytes_in_flight) {
- largest_acked_packet_number_ =
- max(acked_packet_number, largest_acked_packet_number_);
- if (InRecovery()) {
- // PRR is used when in recovery.
- prr_.OnPacketAcked(acked_bytes);
- return;
- }
- MaybeIncreaseCwnd(acked_packet_number, acked_bytes, bytes_in_flight);
- // TODO(ianswett): Should this even be called when not in slow start?
- hybrid_slow_start_.OnPacketAcked(acked_packet_number, InSlowStart());
-}
-
-void TcpCubicBytesSender::OnPacketLost(QuicPacketNumber packet_number,
- QuicByteCount bytes_in_flight) {
- // TCP NewReno (RFC6582) says that once a loss occurs, any losses in packets
- // already sent should be treated as a single loss event, since it's expected.
- if (packet_number <= largest_sent_at_last_cutback_) {
- if (last_cutback_exited_slowstart_) {
- ++stats_->slowstart_packets_lost;
- if (slow_start_large_reduction_) {
- // Reduce congestion window by 1 MSS for every loss.
- congestion_window_ =
- max(congestion_window_ - kDefaultTCPMSS, min_congestion_window_);
- slowstart_threshold_ = congestion_window_;
- }
- }
- DVLOG(1) << "Ignoring loss for largest_missing:" << packet_number
- << " because it was sent prior to the last CWND cutback.";
- return;
- }
- ++stats_->tcp_loss_events;
- last_cutback_exited_slowstart_ = InSlowStart();
- if (InSlowStart()) {
- ++stats_->slowstart_packets_lost;
- }
-
- prr_.OnPacketLost(bytes_in_flight);
-
- // TODO(jri): Separate out all of slow start into a separate class.
- if (slow_start_large_reduction_) {
- DCHECK_LT(kDefaultTCPMSS, congestion_window_);
- congestion_window_ = congestion_window_ - kDefaultTCPMSS;
- } else if (reno_) {
- congestion_window_ = congestion_window_ * RenoBeta();
- } else {
- congestion_window_ =
- cubic_.CongestionWindowAfterPacketLoss(congestion_window_);
- }
- // Enforce TCP's minimum congestion window of 2*MSS.
- if (congestion_window_ < min_congestion_window_) {
- congestion_window_ = min_congestion_window_;
- }
- slowstart_threshold_ = congestion_window_;
- largest_sent_at_last_cutback_ = largest_sent_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_;
-}
-
-bool TcpCubicBytesSender::OnPacketSent(
- QuicTime /*sent_time*/,
- QuicByteCount /*bytes_in_flight*/,
- QuicPacketNumber packet_number,
- QuicByteCount bytes,
- HasRetransmittableData is_retransmittable) {
- if (InSlowStart()) {
- ++(stats_->slowstart_packets_sent);
- }
-
- // Only update bytes_in_flight_ for data packets.
- if (is_retransmittable != HAS_RETRANSMITTABLE_DATA) {
- return false;
- }
- if (InRecovery()) {
- // PRR is used when in recovery.
- prr_.OnPacketSent(bytes);
- }
- DCHECK_LT(largest_sent_packet_number_, packet_number);
- largest_sent_packet_number_ = packet_number;
- hybrid_slow_start_.OnPacketSent(packet_number);
- return true;
-}
-
-QuicTime::Delta TcpCubicBytesSender::TimeUntilSend(
- QuicTime /* now */,
- QuicByteCount bytes_in_flight,
- HasRetransmittableData has_retransmittable_data) const {
- if (has_retransmittable_data == NO_RETRANSMITTABLE_DATA) {
- DCHECK(!FLAGS_quic_respect_send_alarm2);
- // For TCP we can always send an ACK immediately.
- return QuicTime::Delta::Zero();
- }
- if (InRecovery()) {
- // PRR is used when in recovery.
- return prr_.TimeUntilSend(GetCongestionWindow(), bytes_in_flight,
- slowstart_threshold_);
- }
- if (GetCongestionWindow() > bytes_in_flight) {
- return QuicTime::Delta::Zero();
- }
- if (min4_mode_ && bytes_in_flight < 4 * kDefaultTCPMSS) {
- return QuicTime::Delta::Zero();
- }
- return QuicTime::Delta::Infinite();
-}
-
-QuicBandwidth TcpCubicBytesSender::PacingRate() const {
- // We pace at twice the rate of the underlying sender's bandwidth estimate
- // during slow start and 1.25x during congestion avoidance to ensure pacing
- // doesn't prevent us from filling the window.
- QuicTime::Delta srtt = rtt_stats_->smoothed_rtt();
- if (srtt.IsZero()) {
- srtt = QuicTime::Delta::FromMicroseconds(rtt_stats_->initial_rtt_us());
- }
- const QuicBandwidth bandwidth =
- QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt);
- return bandwidth.Scale(InSlowStart() ? 2 : 1.25);
-}
-
-QuicBandwidth TcpCubicBytesSender::BandwidthEstimate() const {
- QuicTime::Delta srtt = rtt_stats_->smoothed_rtt();
- if (srtt.IsZero()) {
- // If we haven't measured an rtt, the bandwidth estimate is unknown.
- return QuicBandwidth::Zero();
- }
- return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt);
-}
-
-QuicTime::Delta TcpCubicBytesSender::RetransmissionDelay() const {
- if (rtt_stats_->smoothed_rtt().IsZero()) {
- return QuicTime::Delta::Zero();
- }
- return rtt_stats_->smoothed_rtt().Add(
- rtt_stats_->mean_deviation().Multiply(4));
-}
-
-QuicByteCount TcpCubicBytesSender::GetCongestionWindow() const {
- return congestion_window_;
-}
-
-bool TcpCubicBytesSender::InSlowStart() const {
- return congestion_window_ < slowstart_threshold_;
-}
-
-QuicByteCount TcpCubicBytesSender::GetSlowStartThreshold() const {
- return slowstart_threshold_;
-}
-
-bool TcpCubicBytesSender::IsCwndLimited(QuicByteCount bytes_in_flight) const {
- if (bytes_in_flight >= congestion_window_) {
- return true;
- }
- const QuicByteCount available_bytes = congestion_window_ - bytes_in_flight;
- const bool slow_start_limited =
- InSlowStart() && bytes_in_flight > congestion_window_ / 2;
- return slow_start_limited || available_bytes <= kMaxBurstBytes;
-}
-
-bool TcpCubicBytesSender::InRecovery() const {
- return largest_acked_packet_number_ <= largest_sent_at_last_cutback_ &&
- largest_acked_packet_number_ != 0;
-}
-
-// Called when we receive an ack. Normal TCP tracks how many packets one ack
-// represents, but quic has a separate ack for each packet.
-void TcpCubicBytesSender::MaybeIncreaseCwnd(
- QuicPacketNumber acked_packet_number,
- QuicByteCount acked_bytes,
- QuicByteCount bytes_in_flight) {
- LOG_IF(DFATAL, InRecovery()) << "Never increase the CWND during recovery.";
- // Do not increase the congestion window unless the sender is close to using
- // the current window.
- if (!IsCwndLimited(bytes_in_flight)) {
- cubic_.OnApplicationLimited();
- return;
- }
- if (congestion_window_ >= max_congestion_window_) {
- return;
- }
- 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_;
- return;
- }
- // Congestion avoidance.
- if (reno_) {
- // Classic Reno congestion avoidance.
- ++num_acked_packets_;
- // Divide by num_connections to smoothly increase the CWND at a faster rate
- // than conventional Reno.
- if (num_acked_packets_ * num_connections_ >=
- congestion_window_ / kDefaultTCPMSS) {
- congestion_window_ += kDefaultTCPMSS;
- num_acked_packets_ = 0;
- }
-
- 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_;
- }
-}
-
-void TcpCubicBytesSender::OnRetransmissionTimeout(bool packets_retransmitted) {
- largest_sent_at_last_cutback_ = 0;
- if (!packets_retransmitted) {
- return;
- }
- cubic_.Reset();
- hybrid_slow_start_.Restart();
- slowstart_threshold_ = congestion_window_ / 2;
- congestion_window_ = min_congestion_window_;
-}
-
-CongestionControlType TcpCubicBytesSender::GetCongestionControlType() const {
- return reno_ ? kRenoBytes : kCubicBytes;
-}
-
-void TcpCubicBytesSender::OnConnectionMigration() {
- hybrid_slow_start_.Restart();
- cubic_.Reset();
- prr_ = PrrSender();
- num_acked_packets_ = 0;
- largest_sent_packet_number_ = 0;
- largest_acked_packet_number_ = 0;
- largest_sent_at_last_cutback_ = 0;
- congestion_window_ = initial_tcp_congestion_window_;
- max_congestion_window_ = initial_max_tcp_congestion_window_;
- slowstart_threshold_ = initial_max_tcp_congestion_window_;
- last_cutback_exited_slowstart_ = false;
-}
-
-} // namespace net
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_bytes_sender.h b/chromium/net/quic/congestion_control/tcp_cubic_bytes_sender.h
deleted file mode 100644
index e1b0185f6c1..00000000000
--- a/chromium/net/quic/congestion_control/tcp_cubic_bytes_sender.h
+++ /dev/null
@@ -1,151 +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.
-
-// TCP cubic send side congestion algorithm, emulates the behavior of TCP cubic.
-
-#ifndef NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_BYTES_SENDER_H_
-#define NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_BYTES_SENDER_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "net/base/net_export.h"
-#include "net/quic/congestion_control/cubic_bytes.h"
-#include "net/quic/congestion_control/hybrid_slow_start.h"
-#include "net/quic/congestion_control/prr_sender.h"
-#include "net/quic/congestion_control/send_algorithm_interface.h"
-#include "net/quic/quic_bandwidth.h"
-#include "net/quic/quic_connection_stats.h"
-#include "net/quic/quic_protocol.h"
-#include "net/quic/quic_time.h"
-
-namespace net {
-
-class RttStats;
-
-namespace test {
-class TcpCubicBytesSenderPeer;
-} // namespace test
-
-class NET_EXPORT_PRIVATE TcpCubicBytesSender : public SendAlgorithmInterface {
- public:
- TcpCubicBytesSender(const QuicClock* clock,
- const RttStats* rtt_stats,
- bool reno,
- QuicPacketCount initial_tcp_congestion_window,
- QuicPacketCount max_congestion_window,
- QuicConnectionStats* stats);
- ~TcpCubicBytesSender() override;
-
- // Start implementation of SendAlgorithmInterface.
- void SetFromConfig(const QuicConfig& config,
- Perspective perspective) override;
- void ResumeConnectionState(
- const CachedNetworkParameters& cached_network_params,
- bool max_bandwidth_resumption) override;
- void SetNumEmulatedConnections(int num_connections) override;
- void SetMaxCongestionWindow(QuicByteCount max_congestion_window) override;
- void OnCongestionEvent(bool rtt_updated,
- QuicByteCount bytes_in_flight,
- const CongestionVector& acked_packets,
- const CongestionVector& lost_packets) override;
- bool OnPacketSent(QuicTime sent_time,
- QuicByteCount bytes_in_flight,
- QuicPacketNumber packet_number,
- QuicByteCount bytes,
- HasRetransmittableData is_retransmittable) override;
- void OnRetransmissionTimeout(bool packets_retransmitted) override;
- void OnConnectionMigration() override;
- QuicTime::Delta TimeUntilSend(
- QuicTime now,
- QuicByteCount bytes_in_flight,
- HasRetransmittableData has_retransmittable_data) const override;
- QuicBandwidth PacingRate() const override;
- QuicBandwidth BandwidthEstimate() const override;
- QuicTime::Delta RetransmissionDelay() const override;
- QuicByteCount GetCongestionWindow() const override;
- bool InSlowStart() const override;
- bool InRecovery() const override;
- QuicByteCount GetSlowStartThreshold() const override;
- CongestionControlType GetCongestionControlType() const override;
- // End implementation of SendAlgorithmInterface.
-
- private:
- friend class test::TcpCubicBytesSenderPeer;
-
- // Compute the TCP Reno beta based on the current number of connections.
- float RenoBeta() const;
-
- // TODO(ianswett): Remove these and migrate to OnCongestionEvent.
- void OnPacketAcked(QuicPacketNumber acked_packet_number,
- QuicByteCount acked_bytes,
- QuicByteCount bytes_in_flight);
- void OnPacketLost(QuicPacketNumber largest_loss,
- QuicByteCount bytes_in_flight);
-
- void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
- QuicByteCount acked_bytes,
- QuicByteCount bytes_in_flight);
- bool IsCwndLimited(QuicByteCount bytes_in_flight) const;
-
- HybridSlowStart hybrid_slow_start_;
- CubicBytes cubic_;
- PrrSender prr_;
- const RttStats* rtt_stats_;
- QuicConnectionStats* stats_;
-
- // If true, Reno congestion control is used instead of Cubic.
- const bool reno_;
-
- // Number of connections to simulate.
- uint32_t num_connections_;
-
- // ACK counter for the Reno implementation.
- uint64_t num_acked_packets_;
-
- // Track the largest packet that has been sent.
- QuicPacketNumber largest_sent_packet_number_;
-
- // Track the largest packet that has been acked.
- QuicPacketNumber largest_acked_packet_number_;
-
- // Track the largest packet number outstanding when a CWND cutback occurs.
- QuicPacketNumber largest_sent_at_last_cutback_;
-
- // Congestion window in bytes.
- QuicByteCount congestion_window_;
-
- // Minimum congestion window in bytes.
- QuicByteCount min_congestion_window_;
-
- // Whether to use 4 packets as the actual min, but pace lower.
- bool min4_mode_;
-
- // Maximum congestion window in bytes.
- QuicByteCount max_congestion_window_;
-
- // Slow start congestion window in bytes, aka ssthresh.
- QuicByteCount slowstart_threshold_;
-
- // Whether the last loss event caused us to exit slowstart. Used for stats
- // collection of slowstart_packets_lost.
- bool last_cutback_exited_slowstart_;
-
- // Initial TCP congestion window in bytes. This variable can only be set when
- // this algorithm is created.
- const QuicByteCount initial_tcp_congestion_window_;
-
- // Initial maximum TCP congestion window in bytes. This variable can only be
- // set when this algorithm is created.
- const QuicByteCount initial_max_tcp_congestion_window_;
-
- // When true, exit slow start with large cutback of congestion window.
- bool slow_start_large_reduction_;
-
- DISALLOW_COPY_AND_ASSIGN(TcpCubicBytesSender);
-};
-
-} // namespace net
-
-#endif // NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_BYTES_SENDER_H_
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_sender.cc b/chromium/net/quic/congestion_control/tcp_cubic_sender.cc
deleted file mode 100644
index ac94217f8f2..00000000000
--- a/chromium/net/quic/congestion_control/tcp_cubic_sender.cc
+++ /dev/null
@@ -1,399 +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/congestion_control/tcp_cubic_sender.h"
-
-#include <algorithm>
-
-#include "base/metrics/histogram_macros.h"
-#include "net/quic/congestion_control/prr_sender.h"
-#include "net/quic/congestion_control/rtt_stats.h"
-#include "net/quic/crypto/crypto_protocol.h"
-#include "net/quic/proto/cached_network_parameters.pb.h"
-#include "net/quic/quic_flags.h"
-
-using std::max;
-using std::min;
-
-namespace net {
-
-namespace {
-// Constants based on TCP defaults.
-// The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a
-// fast retransmission. The cwnd after a timeout is still 1.
-const QuicPacketCount kDefaultMinimumCongestionWindow = 2;
-const QuicByteCount kMaxBurstBytes = 3 * kDefaultTCPMSS;
-const float kRenoBeta = 0.7f; // Reno backoff factor.
-const uint32_t kDefaultNumConnections = 2; // N-connection emulation.
-} // namespace
-
-TcpCubicSender::TcpCubicSender(const QuicClock* clock,
- const RttStats* rtt_stats,
- bool reno,
- QuicPacketCount initial_tcp_congestion_window,
- QuicPacketCount max_tcp_congestion_window,
- QuicConnectionStats* stats)
- : cubic_(clock),
- rtt_stats_(rtt_stats),
- stats_(stats),
- reno_(reno),
- num_connections_(kDefaultNumConnections),
- congestion_window_count_(0),
- largest_sent_packet_number_(0),
- largest_acked_packet_number_(0),
- largest_sent_at_last_cutback_(0),
- congestion_window_(initial_tcp_congestion_window),
- min_congestion_window_(kDefaultMinimumCongestionWindow),
- min4_mode_(false),
- slowstart_threshold_(max_tcp_congestion_window),
- last_cutback_exited_slowstart_(false),
- max_tcp_congestion_window_(max_tcp_congestion_window),
- initial_tcp_congestion_window_(initial_tcp_congestion_window),
- initial_max_tcp_congestion_window_(max_tcp_congestion_window),
- slow_start_large_reduction_(false) {}
-
-TcpCubicSender::~TcpCubicSender() {
- UMA_HISTOGRAM_COUNTS("Net.QuicSession.FinalTcpCwnd", congestion_window_);
-}
-
-void TcpCubicSender::SetFromConfig(const QuicConfig& config,
- Perspective perspective) {
- if (perspective == Perspective::IS_SERVER) {
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kIW03)) {
- // Initial window experiment.
- congestion_window_ = 3;
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kIW10)) {
- // Initial window experiment.
- congestion_window_ = 10;
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kIW20)) {
- // Initial window experiment.
- congestion_window_ = 20;
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kIW50)) {
- // Initial window experiment.
- congestion_window_ = 50;
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN1)) {
- // Min CWND experiment.
- min_congestion_window_ = 1;
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN4)) {
- // Min CWND of 4 experiment.
- min4_mode_ = true;
- min_congestion_window_ = 1;
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kSSLR)) {
- // Slow Start Fast Exit experiment.
- slow_start_large_reduction_ = true;
- }
- }
-}
-
-void TcpCubicSender::ResumeConnectionState(
- const CachedNetworkParameters& cached_network_params,
- bool max_bandwidth_resumption) {
- QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond(
- max_bandwidth_resumption
- ? cached_network_params.max_bandwidth_estimate_bytes_per_second()
- : cached_network_params.bandwidth_estimate_bytes_per_second());
- QuicTime::Delta rtt_ms =
- QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms());
-
- // Make sure CWND is in appropriate range (in case of bad data).
- QuicPacketCount new_congestion_window =
- bandwidth.ToBytesPerPeriod(rtt_ms) / kDefaultTCPMSS;
- congestion_window_ = max(min(new_congestion_window, kMaxCongestionWindow),
- kMinCongestionWindowForBandwidthResumption);
-}
-
-void TcpCubicSender::SetNumEmulatedConnections(int num_connections) {
- num_connections_ = max(1, num_connections);
- cubic_.SetNumConnections(num_connections_);
-}
-
-void TcpCubicSender::SetMaxCongestionWindow(
- QuicByteCount max_congestion_window) {
- max_tcp_congestion_window_ = max_congestion_window / kDefaultTCPMSS;
-}
-
-float TcpCubicSender::RenoBeta() const {
- // kNConnectionBeta is the backoff factor after loss for our N-connection
- // emulation, which emulates the effective backoff of an ensemble of N
- // TCP-Reno connections on a single loss event. The effective multiplier is
- // computed as:
- return (num_connections_ - 1 + kRenoBeta) / num_connections_;
-}
-
-void TcpCubicSender::OnCongestionEvent(bool rtt_updated,
- QuicByteCount bytes_in_flight,
- const CongestionVector& acked_packets,
- const CongestionVector& lost_packets) {
- if (rtt_updated && InSlowStart() &&
- hybrid_slow_start_.ShouldExitSlowStart(rtt_stats_->latest_rtt(),
- rtt_stats_->min_rtt(),
- congestion_window_)) {
- slowstart_threshold_ = congestion_window_;
- }
- for (CongestionVector::const_iterator it = lost_packets.begin();
- it != lost_packets.end(); ++it) {
- OnPacketLost(it->first, bytes_in_flight);
- }
- for (CongestionVector::const_iterator it = acked_packets.begin();
- it != acked_packets.end(); ++it) {
- OnPacketAcked(it->first, it->second, bytes_in_flight);
- }
-}
-
-void TcpCubicSender::OnPacketAcked(QuicPacketNumber acked_packet_number,
- QuicByteCount acked_bytes,
- QuicByteCount bytes_in_flight) {
- largest_acked_packet_number_ =
- max(acked_packet_number, largest_acked_packet_number_);
- if (InRecovery()) {
- // PRR is used when in recovery.
- prr_.OnPacketAcked(acked_bytes);
- return;
- }
- MaybeIncreaseCwnd(acked_packet_number, bytes_in_flight);
- // TODO(ianswett): Should this even be called when not in slow start?
- hybrid_slow_start_.OnPacketAcked(acked_packet_number, InSlowStart());
-}
-
-void TcpCubicSender::OnPacketLost(QuicPacketNumber packet_number,
- QuicByteCount bytes_in_flight) {
- // TCP NewReno (RFC6582) says that once a loss occurs, any losses in packets
- // already sent should be treated as a single loss event, since it's expected.
- if (packet_number <= largest_sent_at_last_cutback_) {
- if (last_cutback_exited_slowstart_) {
- ++stats_->slowstart_packets_lost;
- if (slow_start_large_reduction_) {
- // Reduce congestion window by 1 for every loss.
- congestion_window_ =
- max(congestion_window_ - 1, min_congestion_window_);
- slowstart_threshold_ = congestion_window_;
- }
- }
- DVLOG(1) << "Ignoring loss for largest_missing:" << packet_number
- << " because it was sent prior to the last CWND cutback.";
- return;
- }
- ++stats_->tcp_loss_events;
- last_cutback_exited_slowstart_ = InSlowStart();
- if (InSlowStart()) {
- ++stats_->slowstart_packets_lost;
- }
-
- prr_.OnPacketLost(bytes_in_flight);
-
- // TODO(jri): Separate out all of slow start into a separate class.
- if (slow_start_large_reduction_) {
- DCHECK_LT(1u, congestion_window_);
- congestion_window_ = congestion_window_ - 1;
- } else if (reno_) {
- congestion_window_ = congestion_window_ * RenoBeta();
- } else {
- congestion_window_ =
- cubic_.CongestionWindowAfterPacketLoss(congestion_window_);
- }
- // Enforce a minimum congestion window.
- if (congestion_window_ < min_congestion_window_) {
- congestion_window_ = min_congestion_window_;
- }
- slowstart_threshold_ = congestion_window_;
- largest_sent_at_last_cutback_ = largest_sent_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_;
-}
-
-bool TcpCubicSender::OnPacketSent(QuicTime /*sent_time*/,
- QuicByteCount /*bytes_in_flight*/,
- QuicPacketNumber packet_number,
- QuicByteCount bytes,
- HasRetransmittableData is_retransmittable) {
- if (InSlowStart()) {
- ++(stats_->slowstart_packets_sent);
- }
-
- // Only update bytes_in_flight_ for data packets.
- if (is_retransmittable != HAS_RETRANSMITTABLE_DATA) {
- return false;
- }
- if (InRecovery()) {
- // PRR is used when in recovery.
- prr_.OnPacketSent(bytes);
- }
- DCHECK_LT(largest_sent_packet_number_, packet_number);
- largest_sent_packet_number_ = packet_number;
- hybrid_slow_start_.OnPacketSent(packet_number);
- return true;
-}
-
-QuicTime::Delta TcpCubicSender::TimeUntilSend(
- QuicTime /* now */,
- QuicByteCount bytes_in_flight,
- HasRetransmittableData has_retransmittable_data) const {
- if (has_retransmittable_data == NO_RETRANSMITTABLE_DATA) {
- DCHECK(!FLAGS_quic_respect_send_alarm2);
- // For TCP we can always send an ACK immediately.
- return QuicTime::Delta::Zero();
- }
- if (InRecovery()) {
- // PRR is used when in recovery.
- return prr_.TimeUntilSend(GetCongestionWindow(), bytes_in_flight,
- slowstart_threshold_ * kDefaultTCPMSS);
- }
- if (GetCongestionWindow() > bytes_in_flight) {
- return QuicTime::Delta::Zero();
- }
- if (min4_mode_ && bytes_in_flight < 4 * kDefaultTCPMSS) {
- return QuicTime::Delta::Zero();
- }
- return QuicTime::Delta::Infinite();
-}
-
-QuicBandwidth TcpCubicSender::PacingRate() const {
- // We pace at twice the rate of the underlying sender's bandwidth estimate
- // during slow start and 1.25x during congestion avoidance to ensure pacing
- // doesn't prevent us from filling the window.
- QuicTime::Delta srtt = rtt_stats_->smoothed_rtt();
- if (srtt.IsZero()) {
- srtt = QuicTime::Delta::FromMicroseconds(rtt_stats_->initial_rtt_us());
- }
- const QuicBandwidth bandwidth =
- QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt);
- return bandwidth.Scale(InSlowStart() ? 2 : 1.25);
-}
-
-QuicBandwidth TcpCubicSender::BandwidthEstimate() const {
- QuicTime::Delta srtt = rtt_stats_->smoothed_rtt();
- if (srtt.IsZero()) {
- // If we haven't measured an rtt, the bandwidth estimate is unknown.
- return QuicBandwidth::Zero();
- }
- return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt);
-}
-
-QuicTime::Delta TcpCubicSender::RetransmissionDelay() const {
- if (rtt_stats_->smoothed_rtt().IsZero()) {
- return QuicTime::Delta::Zero();
- }
- return rtt_stats_->smoothed_rtt().Add(
- rtt_stats_->mean_deviation().Multiply(4));
-}
-
-QuicByteCount TcpCubicSender::GetCongestionWindow() const {
- return congestion_window_ * kDefaultTCPMSS;
-}
-
-bool TcpCubicSender::InSlowStart() const {
- return congestion_window_ < slowstart_threshold_;
-}
-
-QuicByteCount TcpCubicSender::GetSlowStartThreshold() const {
- return slowstart_threshold_ * kDefaultTCPMSS;
-}
-
-bool TcpCubicSender::IsCwndLimited(QuicByteCount bytes_in_flight) const {
- const QuicByteCount congestion_window_bytes = GetCongestionWindow();
- if (bytes_in_flight >= congestion_window_bytes) {
- return true;
- }
- const QuicByteCount available_bytes =
- congestion_window_bytes - bytes_in_flight;
- const bool slow_start_limited =
- InSlowStart() && bytes_in_flight > congestion_window_bytes / 2;
- return slow_start_limited || available_bytes <= kMaxBurstBytes;
-}
-
-bool TcpCubicSender::InRecovery() const {
- return largest_acked_packet_number_ <= largest_sent_at_last_cutback_ &&
- largest_acked_packet_number_ != 0;
-}
-
-// Called when we receive an ack. Normal TCP tracks how many packets one ack
-// represents, but quic has a separate ack for each packet.
-void TcpCubicSender::MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
- QuicByteCount bytes_in_flight) {
- LOG_IF(DFATAL, InRecovery()) << "Never increase the CWND during recovery.";
- // Do not increase the congestion window unless the sender is close to using
- // the current window.
- if (!IsCwndLimited(bytes_in_flight)) {
- cubic_.OnApplicationLimited();
- return;
- }
- if (congestion_window_ >= max_tcp_congestion_window_) {
- return;
- }
- 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_;
- return;
- }
- // Congestion avoidance
- if (reno_) {
- // Classic Reno congestion avoidance.
- ++congestion_window_count_;
- // Divide by num_connections to smoothly increase the CWND at a faster
- // rate than conventional Reno.
- if (congestion_window_count_ * num_connections_ >= congestion_window_) {
- ++congestion_window_;
- congestion_window_count_ = 0;
- }
-
- 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_;
- }
-}
-
-void TcpCubicSender::OnRetransmissionTimeout(bool packets_retransmitted) {
- largest_sent_at_last_cutback_ = 0;
- if (!packets_retransmitted) {
- return;
- }
- cubic_.Reset();
- hybrid_slow_start_.Restart();
- slowstart_threshold_ = congestion_window_ / 2;
- congestion_window_ = min_congestion_window_;
-}
-
-void TcpCubicSender::OnConnectionMigration() {
- hybrid_slow_start_.Restart();
- cubic_.Reset();
- prr_ = PrrSender();
- congestion_window_count_ = 0;
- largest_sent_packet_number_ = 0;
- largest_acked_packet_number_ = 0;
- largest_sent_at_last_cutback_ = 0;
- congestion_window_ = initial_tcp_congestion_window_;
- slowstart_threshold_ = initial_max_tcp_congestion_window_;
- last_cutback_exited_slowstart_ = false;
- max_tcp_congestion_window_ = initial_max_tcp_congestion_window_;
-}
-
-CongestionControlType TcpCubicSender::GetCongestionControlType() const {
- return reno_ ? kReno : kCubic;
-}
-
-} // namespace net
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_sender_base.cc b/chromium/net/quic/congestion_control/tcp_cubic_sender_base.cc
new file mode 100644
index 00000000000..5d8478a43c8
--- /dev/null
+++ b/chromium/net/quic/congestion_control/tcp_cubic_sender_base.cc
@@ -0,0 +1,261 @@
+// 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/congestion_control/tcp_cubic_sender_packets.h"
+
+#include <algorithm>
+
+#include "base/metrics/histogram_macros.h"
+#include "net/quic/congestion_control/prr_sender.h"
+#include "net/quic/congestion_control/rtt_stats.h"
+#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/proto/cached_network_parameters.pb.h"
+#include "net/quic/quic_bug_tracker.h"
+#include "net/quic/quic_flags.h"
+
+using std::max;
+using std::min;
+
+namespace net {
+
+namespace {
+// Constants based on TCP defaults.
+// The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a
+// fast retransmission. The cwnd after a timeout is still 1.
+const QuicByteCount kMaxBurstBytes = 3 * kDefaultTCPMSS;
+const float kRenoBeta = 0.7f; // Reno backoff factor.
+const uint32_t kDefaultNumConnections = 2; // N-connection emulation.
+} // namespace
+
+TcpCubicSenderBase::TcpCubicSenderBase(const QuicClock* clock,
+ const RttStats* rtt_stats,
+ bool reno,
+ QuicConnectionStats* stats)
+ : rtt_stats_(rtt_stats),
+ stats_(stats),
+ reno_(reno),
+ num_connections_(kDefaultNumConnections),
+ largest_sent_packet_number_(0),
+ largest_acked_packet_number_(0),
+ largest_sent_at_last_cutback_(0),
+ min4_mode_(false),
+ last_cutback_exited_slowstart_(false),
+ slow_start_large_reduction_(false) {}
+
+TcpCubicSenderBase::~TcpCubicSenderBase() {}
+
+void TcpCubicSenderBase::SetFromConfig(const QuicConfig& config,
+ Perspective perspective) {
+ if (perspective == Perspective::IS_SERVER) {
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kIW03)) {
+ // Initial window experiment.
+ SetCongestionWindowInPackets(3);
+ }
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kIW10)) {
+ // Initial window experiment.
+ SetCongestionWindowInPackets(10);
+ }
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kIW20)) {
+ // Initial window experiment.
+ SetCongestionWindowInPackets(20);
+ }
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kIW50)) {
+ // Initial window experiment.
+ SetCongestionWindowInPackets(50);
+ }
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN1)) {
+ // Min CWND experiment.
+ SetMinCongestionWindowInPackets(1);
+ }
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN4)) {
+ // Min CWND of 4 experiment.
+ min4_mode_ = true;
+ SetMinCongestionWindowInPackets(1);
+ }
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kSSLR)) {
+ // Slow Start Fast Exit experiment.
+ slow_start_large_reduction_ = true;
+ }
+ }
+}
+
+void TcpCubicSenderBase::ResumeConnectionState(
+ const CachedNetworkParameters& cached_network_params,
+ bool max_bandwidth_resumption) {
+ QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond(
+ max_bandwidth_resumption
+ ? cached_network_params.max_bandwidth_estimate_bytes_per_second()
+ : cached_network_params.bandwidth_estimate_bytes_per_second());
+ QuicTime::Delta rtt =
+ QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms());
+
+ SetCongestionWindowFromBandwidthAndRtt(bandwidth, rtt);
+}
+
+void TcpCubicSenderBase::SetNumEmulatedConnections(int num_connections) {
+ num_connections_ = max(1, num_connections);
+}
+
+float TcpCubicSenderBase::RenoBeta() const {
+ // kNConnectionBeta is the backoff factor after loss for our N-connection
+ // emulation, which emulates the effective backoff of an ensemble of N
+ // TCP-Reno connections on a single loss event. The effective multiplier is
+ // computed as:
+ return (num_connections_ - 1 + kRenoBeta) / num_connections_;
+}
+
+void TcpCubicSenderBase::OnCongestionEvent(
+ bool rtt_updated,
+ QuicByteCount bytes_in_flight,
+ const CongestionVector& acked_packets,
+ const CongestionVector& lost_packets) {
+ if (rtt_updated && InSlowStart() &&
+ hybrid_slow_start_.ShouldExitSlowStart(
+ rtt_stats_->latest_rtt(), rtt_stats_->min_rtt(),
+ GetCongestionWindow() / kDefaultTCPMSS)) {
+ ExitSlowstart();
+ }
+ for (CongestionVector::const_iterator it = lost_packets.begin();
+ it != lost_packets.end(); ++it) {
+ OnPacketLost(it->first, it->second, bytes_in_flight);
+ }
+ for (CongestionVector::const_iterator it = acked_packets.begin();
+ it != acked_packets.end(); ++it) {
+ OnPacketAcked(it->first, it->second, bytes_in_flight);
+ }
+}
+
+void TcpCubicSenderBase::OnPacketAcked(QuicPacketNumber acked_packet_number,
+ QuicByteCount acked_bytes,
+ QuicByteCount bytes_in_flight) {
+ largest_acked_packet_number_ =
+ max(acked_packet_number, largest_acked_packet_number_);
+ if (InRecovery()) {
+ // PRR is used when in recovery.
+ prr_.OnPacketAcked(acked_bytes);
+ return;
+ }
+ MaybeIncreaseCwnd(acked_packet_number, acked_bytes, bytes_in_flight);
+ if (InSlowStart()) {
+ hybrid_slow_start_.OnPacketAcked(acked_packet_number);
+ }
+}
+
+bool TcpCubicSenderBase::OnPacketSent(
+ QuicTime /*sent_time*/,
+ QuicByteCount /*bytes_in_flight*/,
+ QuicPacketNumber packet_number,
+ QuicByteCount bytes,
+ HasRetransmittableData is_retransmittable) {
+ if (InSlowStart()) {
+ ++(stats_->slowstart_packets_sent);
+ }
+
+ // Only update bytes_in_flight_ for data packets.
+ if (is_retransmittable != HAS_RETRANSMITTABLE_DATA) {
+ return false;
+ }
+ if (InRecovery()) {
+ // PRR is used when in recovery.
+ prr_.OnPacketSent(bytes);
+ }
+ DCHECK_LT(largest_sent_packet_number_, packet_number);
+ largest_sent_packet_number_ = packet_number;
+ hybrid_slow_start_.OnPacketSent(packet_number);
+ return true;
+}
+
+QuicTime::Delta TcpCubicSenderBase::TimeUntilSend(
+ QuicTime /* now */,
+ QuicByteCount bytes_in_flight) const {
+ if (InRecovery()) {
+ // PRR is used when in recovery.
+ return prr_.TimeUntilSend(GetCongestionWindow(), bytes_in_flight,
+ GetSlowStartThreshold());
+ }
+ if (GetCongestionWindow() > bytes_in_flight) {
+ return QuicTime::Delta::Zero();
+ }
+ if (min4_mode_ && bytes_in_flight < 4 * kDefaultTCPMSS) {
+ return QuicTime::Delta::Zero();
+ }
+ return QuicTime::Delta::Infinite();
+}
+
+QuicBandwidth TcpCubicSenderBase::PacingRate() const {
+ // We pace at twice the rate of the underlying sender's bandwidth estimate
+ // during slow start and 1.25x during congestion avoidance to ensure pacing
+ // doesn't prevent us from filling the window.
+ QuicTime::Delta srtt = rtt_stats_->smoothed_rtt();
+ if (srtt.IsZero()) {
+ srtt = QuicTime::Delta::FromMicroseconds(rtt_stats_->initial_rtt_us());
+ }
+ const QuicBandwidth bandwidth =
+ QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt);
+ return bandwidth.Scale(InSlowStart() ? 2 : 1.25);
+}
+
+QuicBandwidth TcpCubicSenderBase::BandwidthEstimate() const {
+ QuicTime::Delta srtt = rtt_stats_->smoothed_rtt();
+ if (srtt.IsZero()) {
+ // If we haven't measured an rtt, the bandwidth estimate is unknown.
+ return QuicBandwidth::Zero();
+ }
+ return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt);
+}
+
+QuicTime::Delta TcpCubicSenderBase::RetransmissionDelay() const {
+ if (rtt_stats_->smoothed_rtt().IsZero()) {
+ return QuicTime::Delta::Zero();
+ }
+ return rtt_stats_->smoothed_rtt().Add(
+ rtt_stats_->mean_deviation().Multiply(4));
+}
+
+bool TcpCubicSenderBase::InSlowStart() const {
+ return GetCongestionWindow() < GetSlowStartThreshold();
+}
+
+bool TcpCubicSenderBase::IsCwndLimited(QuicByteCount bytes_in_flight) const {
+ const QuicByteCount congestion_window = GetCongestionWindow();
+ if (bytes_in_flight >= congestion_window) {
+ return true;
+ }
+ const QuicByteCount available_bytes = congestion_window - bytes_in_flight;
+ const bool slow_start_limited =
+ InSlowStart() && bytes_in_flight > congestion_window / 2;
+ return slow_start_limited || available_bytes <= kMaxBurstBytes;
+}
+
+bool TcpCubicSenderBase::InRecovery() const {
+ return largest_acked_packet_number_ <= largest_sent_at_last_cutback_ &&
+ largest_acked_packet_number_ != 0;
+}
+
+void TcpCubicSenderBase::OnRetransmissionTimeout(bool packets_retransmitted) {
+ largest_sent_at_last_cutback_ = 0;
+ if (!packets_retransmitted) {
+ return;
+ }
+ hybrid_slow_start_.Restart();
+ HandleRetransmissionTimeout();
+}
+
+void TcpCubicSenderBase::OnConnectionMigration() {
+ hybrid_slow_start_.Restart();
+ prr_ = PrrSender();
+ largest_sent_packet_number_ = 0;
+ largest_acked_packet_number_ = 0;
+ largest_sent_at_last_cutback_ = 0;
+ last_cutback_exited_slowstart_ = false;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_sender.h b/chromium/net/quic/congestion_control/tcp_cubic_sender_base.h
index 9b253a38b17..d3f231bef4b 100644
--- a/chromium/net/quic/congestion_control/tcp_cubic_sender.h
+++ b/chromium/net/quic/congestion_control/tcp_cubic_sender_base.h
@@ -4,8 +4,8 @@
//
// TCP cubic send side congestion algorithm, emulates the behavior of TCP cubic.
-#ifndef NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_H_
-#define NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_H_
+#ifndef NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BASE_H_
+#define NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BASE_H_
#include <stdint.h>
@@ -26,19 +26,17 @@ namespace net {
class RttStats;
namespace test {
-class TcpCubicSenderPeer;
+class TcpCubicSenderBasePeer;
} // namespace test
-class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
+class NET_EXPORT_PRIVATE TcpCubicSenderBase : public SendAlgorithmInterface {
public:
// Reno option and max_tcp_congestion_window are provided for testing.
- TcpCubicSender(const QuicClock* clock,
- const RttStats* rtt_stats,
- bool reno,
- QuicPacketCount initial_tcp_congestion_window,
- QuicPacketCount max_tcp_congestion_window,
- QuicConnectionStats* stats);
- ~TcpCubicSender() override;
+ TcpCubicSenderBase(const QuicClock* clock,
+ const RttStats* rtt_stats,
+ bool reno,
+ QuicConnectionStats* stats);
+ ~TcpCubicSenderBase() override;
// Start implementation of SendAlgorithmInterface.
void SetFromConfig(const QuicConfig& config,
@@ -47,7 +45,6 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
const CachedNetworkParameters& cached_network_params,
bool max_bandwidth_resumption) override;
void SetNumEmulatedConnections(int num_connections) override;
- void SetMaxCongestionWindow(QuicByteCount max_congestion_window) override;
void OnCongestionEvent(bool rtt_updated,
QuicByteCount bytes_in_flight,
const CongestionVector& acked_packets,
@@ -59,39 +56,61 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
HasRetransmittableData is_retransmittable) override;
void OnRetransmissionTimeout(bool packets_retransmitted) override;
void OnConnectionMigration() override;
- QuicTime::Delta TimeUntilSend(
- QuicTime now,
- QuicByteCount bytes_in_flight,
- HasRetransmittableData has_retransmittable_data) const override;
+ QuicTime::Delta TimeUntilSend(QuicTime now,
+ QuicByteCount bytes_in_flight) const override;
QuicBandwidth PacingRate() const override;
QuicBandwidth BandwidthEstimate() const override;
QuicTime::Delta RetransmissionDelay() const override;
- QuicByteCount GetCongestionWindow() const override;
bool InSlowStart() const override;
bool InRecovery() const override;
- QuicByteCount GetSlowStartThreshold() const override;
- CongestionControlType GetCongestionControlType() const override;
- // End implementation of SendAlgorithmInterface.
- private:
- friend class test::TcpCubicSenderPeer;
+ protected:
+ // Called when resuming a previous bandwidth.
+ virtual void SetCongestionWindowFromBandwidthAndRtt(QuicBandwidth bandwidth,
+ QuicTime::Delta rtt) = 0;
+
+ // Called when initializing the congestion window.
+ virtual void SetCongestionWindowInPackets(
+ QuicPacketCount congestion_window) = 0;
+
+ // Called when initializing the minimum congestion window.
+ virtual void SetMinCongestionWindowInPackets(
+ QuicPacketCount congestion_window) = 0;
+
+ // Called when slow start is exited to set SSTHRESH.
+ virtual void ExitSlowstart() = 0;
+
+ // Called when a packet is lost.
+ virtual void OnPacketLost(QuicPacketNumber largest_loss,
+ QuicByteCount lost_bytes,
+ QuicByteCount bytes_in_flight) = 0;
+
+ // Called when a packet has been acked to possibly increase the congestion
+ // window.
+ virtual void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
+ QuicByteCount acked_bytes,
+ QuicByteCount bytes_in_flight) = 0;
+
+ // Called when a retransmission has occured which resulted in packets
+ // being retransmitted.
+ virtual void HandleRetransmissionTimeout() = 0;
// Compute the TCP Reno beta based on the current number of connections.
float RenoBeta() const;
+ bool IsCwndLimited(QuicByteCount bytes_in_flight) const;
+
+ private:
+ friend class test::TcpCubicSenderBasePeer;
+
// TODO(ianswett): Remove these and migrate to OnCongestionEvent.
void OnPacketAcked(QuicPacketNumber acked_packet_number,
QuicByteCount acked_bytes,
QuicByteCount bytes_in_flight);
- void OnPacketLost(QuicPacketNumber largest_loss,
- QuicByteCount bytes_in_flight);
-
- void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
- QuicByteCount bytes_in_flight);
- bool IsCwndLimited(QuicByteCount bytes_in_flight) const;
+ protected:
+ // TODO(rch): Make these private and clean up subclass access to them.
HybridSlowStart hybrid_slow_start_;
- Cubic cubic_;
PrrSender prr_;
const RttStats* rtt_stats_;
QuicConnectionStats* stats_;
@@ -102,9 +121,6 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
// Number of connections to simulate.
uint32_t num_connections_;
- // ACK counter for the Reno implementation.
- uint64_t congestion_window_count_;
-
// Track the largest packet that has been sent.
QuicPacketNumber largest_sent_packet_number_;
@@ -114,39 +130,20 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
// Track the largest packet number outstanding when a CWND cutback occurs.
QuicPacketNumber largest_sent_at_last_cutback_;
- // Congestion window in packets.
- QuicPacketCount congestion_window_;
-
- // Minimum congestion window in packets.
- QuicPacketCount min_congestion_window_;
-
// Whether to use 4 packets as the actual min, but pace lower.
bool min4_mode_;
- // Slow start congestion window in packets, aka ssthresh.
- QuicPacketCount slowstart_threshold_;
-
// Whether the last loss event caused us to exit slowstart.
// Used for stats collection of slowstart_packets_lost
bool last_cutback_exited_slowstart_;
- // Maximum number of outstanding packets for tcp.
- QuicPacketCount max_tcp_congestion_window_;
-
- // Initial TCP congestion window. This variable can only be set when this
- // algorithm is created.
- const QuicPacketCount initial_tcp_congestion_window_;
-
- // Initial maximum TCP congestion window. This variable can only be set when
- // this algorithm is created.
- const QuicPacketCount initial_max_tcp_congestion_window_;
-
// When true, exit slow start with large cutback of congestion window.
bool slow_start_large_reduction_;
- DISALLOW_COPY_AND_ASSIGN(TcpCubicSender);
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TcpCubicSenderBase);
};
} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_H_
+#endif // NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BASE_H_
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_sender_bytes.cc b/chromium/net/quic/congestion_control/tcp_cubic_sender_bytes.cc
new file mode 100644
index 00000000000..863def3b366
--- /dev/null
+++ b/chromium/net/quic/congestion_control/tcp_cubic_sender_bytes.cc
@@ -0,0 +1,209 @@
+// 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/congestion_control/tcp_cubic_sender_bytes.h"
+
+#include <algorithm>
+
+#include "net/quic/congestion_control/prr_sender.h"
+#include "net/quic/congestion_control/rtt_stats.h"
+#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/proto/cached_network_parameters.pb.h"
+#include "net/quic/quic_bug_tracker.h"
+#include "net/quic/quic_flags.h"
+
+using std::max;
+using std::min;
+
+namespace net {
+
+namespace {
+// Constants based on TCP defaults.
+// The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a
+// fast retransmission.
+const QuicByteCount kDefaultMinimumCongestionWindow = 2 * kDefaultTCPMSS;
+} // namespace
+
+TcpCubicSenderBytes::TcpCubicSenderBytes(
+ const QuicClock* clock,
+ const RttStats* rtt_stats,
+ bool reno,
+ QuicPacketCount initial_tcp_congestion_window,
+ QuicPacketCount max_congestion_window,
+ QuicConnectionStats* stats)
+ : TcpCubicSenderBase(clock, rtt_stats, reno, stats),
+ cubic_(clock),
+ num_acked_packets_(0),
+ congestion_window_(initial_tcp_congestion_window * kDefaultTCPMSS),
+ min_congestion_window_(kDefaultMinimumCongestionWindow),
+ max_congestion_window_(max_congestion_window * kDefaultTCPMSS),
+ slowstart_threshold_(max_congestion_window * kDefaultTCPMSS),
+ initial_tcp_congestion_window_(initial_tcp_congestion_window *
+ kDefaultTCPMSS),
+ initial_max_tcp_congestion_window_(max_congestion_window *
+ kDefaultTCPMSS) {}
+
+TcpCubicSenderBytes::~TcpCubicSenderBytes() {}
+
+void TcpCubicSenderBytes::SetCongestionWindowFromBandwidthAndRtt(
+ QuicBandwidth bandwidth,
+ QuicTime::Delta rtt) {
+ // Make sure CWND is in appropriate range (in case of bad data).
+ QuicByteCount new_congestion_window = bandwidth.ToBytesPerPeriod(rtt);
+ congestion_window_ =
+ max(min(new_congestion_window, kMaxCongestionWindow * kDefaultTCPMSS),
+ kMinCongestionWindowForBandwidthResumption * kDefaultTCPMSS);
+}
+
+void TcpCubicSenderBytes::SetCongestionWindowInPackets(
+ QuicPacketCount congestion_window) {
+ congestion_window_ = congestion_window * kDefaultTCPMSS;
+}
+
+void TcpCubicSenderBytes::SetMinCongestionWindowInPackets(
+ QuicPacketCount congestion_window) {
+ min_congestion_window_ = congestion_window * kDefaultTCPMSS;
+}
+
+void TcpCubicSenderBytes::SetNumEmulatedConnections(int num_connections) {
+ TcpCubicSenderBase::SetNumEmulatedConnections(num_connections);
+ cubic_.SetNumConnections(num_connections_);
+}
+
+void TcpCubicSenderBytes::SetMaxCongestionWindow(
+ QuicByteCount max_congestion_window) {
+ max_congestion_window_ = max_congestion_window;
+}
+
+void TcpCubicSenderBytes::ExitSlowstart() {
+ slowstart_threshold_ = congestion_window_;
+}
+
+void TcpCubicSenderBytes::OnPacketLost(QuicPacketNumber packet_number,
+ QuicByteCount lost_bytes,
+ QuicByteCount bytes_in_flight) {
+ // TCP NewReno (RFC6582) says that once a loss occurs, any losses in packets
+ // already sent should be treated as a single loss event, since it's expected.
+ if (packet_number <= largest_sent_at_last_cutback_) {
+ if (last_cutback_exited_slowstart_) {
+ ++stats_->slowstart_packets_lost;
+ 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_congestion_window_);
+ slowstart_threshold_ = congestion_window_;
+ }
+ }
+ DVLOG(1) << "Ignoring loss for largest_missing:" << packet_number
+ << " because it was sent prior to the last CWND cutback.";
+ return;
+ }
+ ++stats_->tcp_loss_events;
+ last_cutback_exited_slowstart_ = InSlowStart();
+ if (InSlowStart()) {
+ ++stats_->slowstart_packets_lost;
+ }
+
+ prr_.OnPacketLost(bytes_in_flight);
+
+ // TODO(jri): Separate out all of slow start into a separate class.
+ if (slow_start_large_reduction_ && InSlowStart()) {
+ DCHECK_LT(kDefaultTCPMSS, congestion_window_);
+ congestion_window_ = congestion_window_ - kDefaultTCPMSS;
+ } else if (reno_) {
+ congestion_window_ = congestion_window_ * RenoBeta();
+ } else {
+ congestion_window_ =
+ cubic_.CongestionWindowAfterPacketLoss(congestion_window_);
+ }
+ // Enforce TCP's minimum congestion window of 2*MSS.
+ if (congestion_window_ < min_congestion_window_) {
+ congestion_window_ = min_congestion_window_;
+ }
+ slowstart_threshold_ = congestion_window_;
+ largest_sent_at_last_cutback_ = largest_sent_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_;
+}
+
+QuicByteCount TcpCubicSenderBytes::GetCongestionWindow() const {
+ return congestion_window_;
+}
+
+QuicByteCount TcpCubicSenderBytes::GetSlowStartThreshold() const {
+ return slowstart_threshold_;
+}
+
+// Called when we receive an ack. Normal TCP tracks how many packets one ack
+// represents, but quic has a separate ack for each packet.
+void TcpCubicSenderBytes::MaybeIncreaseCwnd(
+ QuicPacketNumber acked_packet_number,
+ QuicByteCount acked_bytes,
+ QuicByteCount bytes_in_flight) {
+ 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.
+ if (!IsCwndLimited(bytes_in_flight)) {
+ cubic_.OnApplicationLimited();
+ return;
+ }
+ if (congestion_window_ >= max_congestion_window_) {
+ return;
+ }
+ 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_;
+ return;
+ }
+ // Congestion avoidance.
+ if (reno_) {
+ // Classic Reno congestion avoidance.
+ ++num_acked_packets_;
+ // Divide by num_connections to smoothly increase the CWND at a faster rate
+ // than conventional Reno.
+ if (num_acked_packets_ * num_connections_ >=
+ congestion_window_ / kDefaultTCPMSS) {
+ congestion_window_ += kDefaultTCPMSS;
+ num_acked_packets_ = 0;
+ }
+
+ 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_;
+ }
+}
+
+void TcpCubicSenderBytes::HandleRetransmissionTimeout() {
+ cubic_.Reset();
+ slowstart_threshold_ = congestion_window_ / 2;
+ congestion_window_ = min_congestion_window_;
+}
+
+void TcpCubicSenderBytes::OnConnectionMigration() {
+ TcpCubicSenderBase::OnConnectionMigration();
+ cubic_.Reset();
+ num_acked_packets_ = 0;
+ congestion_window_ = initial_tcp_congestion_window_;
+ max_congestion_window_ = initial_max_tcp_congestion_window_;
+ slowstart_threshold_ = initial_max_tcp_congestion_window_;
+}
+
+CongestionControlType TcpCubicSenderBytes::GetCongestionControlType() const {
+ return reno_ ? kRenoBytes : kCubicBytes;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_sender_bytes.h b/chromium/net/quic/congestion_control/tcp_cubic_sender_bytes.h
new file mode 100644
index 00000000000..d31cc1df130
--- /dev/null
+++ b/chromium/net/quic/congestion_control/tcp_cubic_sender_bytes.h
@@ -0,0 +1,99 @@
+// 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.
+
+// 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_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "net/base/net_export.h"
+#include "net/quic/congestion_control/cubic_bytes.h"
+#include "net/quic/congestion_control/hybrid_slow_start.h"
+#include "net/quic/congestion_control/prr_sender.h"
+#include "net/quic/congestion_control/tcp_cubic_sender_base.h"
+#include "net/quic/quic_bandwidth.h"
+#include "net/quic/quic_connection_stats.h"
+#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_time.h"
+
+namespace net {
+
+class RttStats;
+
+namespace test {
+class TcpCubicSenderBytesPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE TcpCubicSenderBytes : public TcpCubicSenderBase {
+ public:
+ TcpCubicSenderBytes(const QuicClock* clock,
+ const RttStats* rtt_stats,
+ bool reno,
+ QuicPacketCount initial_tcp_congestion_window,
+ QuicPacketCount max_congestion_window,
+ QuicConnectionStats* stats);
+ ~TcpCubicSenderBytes() override;
+
+ // Start implementation of SendAlgorithmInterface.
+ void SetNumEmulatedConnections(int num_connections) override;
+ void SetMaxCongestionWindow(QuicByteCount max_congestion_window) override;
+ void OnConnectionMigration() override;
+ QuicByteCount GetCongestionWindow() const override;
+ QuicByteCount GetSlowStartThreshold() const override;
+ CongestionControlType GetCongestionControlType() const override;
+ // End implementation of SendAlgorithmInterface.
+
+ protected:
+ // TcpCubicSenderBase methods
+ void SetCongestionWindowFromBandwidthAndRtt(QuicBandwidth bandwidth,
+ QuicTime::Delta rtt) override;
+ void SetCongestionWindowInPackets(QuicPacketCount congestion_window) override;
+ void SetMinCongestionWindowInPackets(
+ QuicPacketCount congestion_window) override;
+ void ExitSlowstart() override;
+ void OnPacketLost(QuicPacketNumber largest_loss,
+ QuicByteCount lost_bytes,
+ QuicByteCount bytes_in_flight) override;
+ void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
+ QuicByteCount acked_bytes,
+ QuicByteCount bytes_in_flight) override;
+ void HandleRetransmissionTimeout() override;
+
+ private:
+ friend class test::TcpCubicSenderBytesPeer;
+
+ CubicBytes cubic_;
+
+ // ACK counter for the Reno implementation.
+ uint64_t num_acked_packets_;
+
+ // Congestion window in bytes.
+ QuicByteCount congestion_window_;
+
+ // Minimum congestion window in bytes.
+ QuicByteCount min_congestion_window_;
+
+ // Maximum congestion window in bytes.
+ QuicByteCount max_congestion_window_;
+
+ // Slow start congestion window in bytes, aka ssthresh.
+ QuicByteCount slowstart_threshold_;
+
+ // Initial TCP congestion window in bytes. This variable can only be set when
+ // this algorithm is created.
+ const QuicByteCount initial_tcp_congestion_window_;
+
+ // Initial maximum TCP congestion window in bytes. This variable can only be
+ // set when this algorithm is created.
+ const QuicByteCount initial_max_tcp_congestion_window_;
+
+ DISALLOW_COPY_AND_ASSIGN(TcpCubicSenderBytes);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_BYTES_SENDER_H_
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_bytes_sender_test.cc b/chromium/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc
index 308943565dd..eaacb5bc0bb 100644
--- a/chromium/net/quic/congestion_control/tcp_cubic_bytes_sender_test.cc
+++ b/chromium/net/quic/congestion_control/tcp_cubic_sender_bytes_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/congestion_control/tcp_cubic_bytes_sender.h"
+#include "net/quic/congestion_control/tcp_cubic_sender_bytes.h"
#include <algorithm>
@@ -30,10 +30,10 @@ const uint32_t kDefaultWindowTCP =
kInitialCongestionWindowPackets * kDefaultTCPMSS;
const float kRenoBeta = 0.7f; // Reno backoff factor.
-class TcpCubicBytesSenderPeer : public TcpCubicBytesSender {
+class TcpCubicSenderBytesPeer : public TcpCubicSenderBytes {
public:
- TcpCubicBytesSenderPeer(const QuicClock* clock, bool reno)
- : TcpCubicBytesSender(clock,
+ TcpCubicSenderBytesPeer(const QuicClock* clock, bool reno)
+ : TcpCubicSenderBytes(clock,
&rtt_stats_,
reno,
kInitialCongestionWindowPackets,
@@ -50,29 +50,31 @@ class TcpCubicBytesSenderPeer : public TcpCubicBytesSender {
QuicConnectionStats stats_;
};
-class TcpCubicBytesSenderTest : public ::testing::Test {
+class TcpCubicSenderBytesTest : public ::testing::Test {
protected:
- TcpCubicBytesSenderTest()
+ TcpCubicSenderBytesTest()
: one_ms_(QuicTime::Delta::FromMilliseconds(1)),
- sender_(new TcpCubicBytesSenderPeer(&clock_, true)),
+ sender_(new TcpCubicSenderBytesPeer(&clock_, true)),
packet_number_(1),
acked_packet_number_(0),
bytes_in_flight_(0) {}
int SendAvailableSendWindow() {
+ return SendAvailableSendWindow(kDefaultTCPMSS);
+ }
+
+ int SendAvailableSendWindow(QuicPacketLength packet_length) {
// Send as long as TimeUntilSend returns Zero.
int packets_sent = 0;
- bool can_send = sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero();
+ bool can_send =
+ sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero();
while (can_send) {
sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, packet_number_++,
kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA);
++packets_sent;
bytes_in_flight_ += kDefaultTCPMSS;
- can_send = sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero();
+ can_send =
+ sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero();
}
return packets_sent;
}
@@ -94,17 +96,19 @@ class TcpCubicBytesSenderTest : public ::testing::Test {
clock_.AdvanceTime(one_ms_);
}
- void LoseNPackets(int n) {
+ void LoseNPackets(int n) { LoseNPackets(n, kDefaultTCPMSS); }
+
+ void LoseNPackets(int n, QuicPacketLength packet_length) {
SendAlgorithmInterface::CongestionVector acked_packets;
SendAlgorithmInterface::CongestionVector lost_packets;
for (int i = 0; i < n; ++i) {
++acked_packet_number_;
lost_packets.push_back(
- std::make_pair(acked_packet_number_, kDefaultTCPMSS));
+ std::make_pair(acked_packet_number_, packet_length));
}
sender_->OnCongestionEvent(false, bytes_in_flight_, acked_packets,
lost_packets);
- bytes_in_flight_ -= n * kDefaultTCPMSS;
+ bytes_in_flight_ -= n * packet_length;
}
// Does not increment acked_packet_number_.
@@ -119,41 +123,36 @@ class TcpCubicBytesSenderTest : public ::testing::Test {
const QuicTime::Delta one_ms_;
MockClock clock_;
- scoped_ptr<TcpCubicBytesSenderPeer> sender_;
+ scoped_ptr<TcpCubicSenderBytesPeer> sender_;
QuicPacketNumber packet_number_;
QuicPacketNumber acked_packet_number_;
QuicByteCount bytes_in_flight_;
};
-TEST_F(TcpCubicBytesSenderTest, SimpleSender) {
+TEST_F(TcpCubicSenderBytesTest, SimpleSender) {
// At startup make sure we are at the default.
EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
// At startup make sure we can send.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
// Make sure we can send.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
// And that window is un-affected.
EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
// Fill the send window with data, then verify that we can't send.
SendAvailableSendWindow();
- EXPECT_FALSE(sender_->TimeUntilSend(clock_.Now(),
- sender_->GetCongestionWindow(),
- HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_FALSE(
+ sender_->TimeUntilSend(clock_.Now(), sender_->GetCongestionWindow())
+ .IsZero());
}
-TEST_F(TcpCubicBytesSenderTest, ApplicationLimitedSlowStart) {
+TEST_F(TcpCubicSenderBytesTest, ApplicationLimitedSlowStart) {
// Send exactly 10 packets and ensure the CWND ends at 14 packets.
const int kNumberOfAcks = 5;
// At startup make sure we can send.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
// Make sure we can send.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
SendAvailableSendWindow();
for (int i = 0; i < kNumberOfAcks; ++i) {
@@ -165,15 +164,13 @@ TEST_F(TcpCubicBytesSenderTest, ApplicationLimitedSlowStart) {
EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * 2, bytes_to_send);
}
-TEST_F(TcpCubicBytesSenderTest, ExponentialSlowStart) {
+TEST_F(TcpCubicSenderBytesTest, ExponentialSlowStart) {
const int kNumberOfAcks = 20;
// At startup make sure we can send.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
EXPECT_EQ(QuicBandwidth::Zero(), sender_->BandwidthEstimate());
// Make sure we can send.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
for (int i = 0; i < kNumberOfAcks; ++i) {
// Send our full send window.
@@ -187,7 +184,7 @@ TEST_F(TcpCubicBytesSenderTest, ExponentialSlowStart) {
sender_->BandwidthEstimate());
}
-TEST_F(TcpCubicBytesSenderTest, SlowStartPacketLoss) {
+TEST_F(TcpCubicSenderBytesTest, SlowStartPacketLoss) {
sender_->SetNumEmulatedConnections(1);
const int kNumberOfAcks = 10;
for (int i = 0; i < kNumberOfAcks; ++i) {
@@ -232,7 +229,7 @@ TEST_F(TcpCubicBytesSenderTest, SlowStartPacketLoss) {
EXPECT_FALSE(sender_->hybrid_slow_start().started());
}
-TEST_F(TcpCubicBytesSenderTest, SlowStartPacketLossWithLargeReduction) {
+TEST_F(TcpCubicSenderBytesTest, SlowStartPacketLossWithLargeReduction) {
QuicConfig config;
QuicTagVector options;
options.push_back(kSSLR);
@@ -289,7 +286,40 @@ TEST_F(TcpCubicBytesSenderTest, SlowStartPacketLossWithLargeReduction) {
EXPECT_FALSE(sender_->hybrid_slow_start().started());
}
-TEST_F(TcpCubicBytesSenderTest, NoPRRWhenLessThanOnePacketInFlight) {
+TEST_F(TcpCubicSenderBytesTest, SlowStartHalfPacketLossWithLargeReduction) {
+ FLAGS_quic_sslr_byte_conservation = true;
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kSSLR);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ sender_->SetFromConfig(config, Perspective::IS_SERVER);
+
+ sender_->SetNumEmulatedConnections(1);
+ const int kNumberOfAcks = 10;
+ for (int i = 0; i < kNumberOfAcks; ++i) {
+ // Send our full send window in half sized packets.
+ SendAvailableSendWindow(kDefaultTCPMSS / 2);
+ AckNPackets(2);
+ }
+ SendAvailableSendWindow(kDefaultTCPMSS / 2);
+ QuicByteCount expected_send_window =
+ kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks);
+ EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
+
+ // Lose a packet to exit slow start. We should now have fallen out of
+ // slow start with a window reduced by 1.
+ LoseNPackets(1);
+ expected_send_window -= kDefaultTCPMSS;
+ EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
+
+ // Lose 10 packets in recovery and verify that congestion window is reduced
+ // by 5 packets.
+ LoseNPackets(10, kDefaultTCPMSS / 2);
+ expected_send_window -= 5 * kDefaultTCPMSS;
+ EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
+}
+
+TEST_F(TcpCubicSenderBytesTest, NoPRRWhenLessThanOnePacketInFlight) {
SendAvailableSendWindow();
LoseNPackets(kInitialCongestionWindowPackets - 1);
AckNPackets(1);
@@ -298,11 +328,10 @@ TEST_F(TcpCubicBytesSenderTest, NoPRRWhenLessThanOnePacketInFlight) {
// Simulate abandoning all packets by supplying a bytes_in_flight of 0.
// PRR should now allow a packet to be sent, even though prr's state variables
// believe it has sent enough packets.
- EXPECT_EQ(QuicTime::Delta::Zero(),
- sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA));
+ EXPECT_EQ(QuicTime::Delta::Zero(), sender_->TimeUntilSend(clock_.Now(), 0));
}
-TEST_F(TcpCubicBytesSenderTest, SlowStartPacketLossPRR) {
+TEST_F(TcpCubicSenderBytesTest, SlowStartPacketLossPRR) {
sender_->SetNumEmulatedConnections(1);
// Test based on the first example in RFC6937.
// Ack 10 packets in 5 acks to raise the CWND to 20, as in the example.
@@ -351,7 +380,7 @@ TEST_F(TcpCubicBytesSenderTest, SlowStartPacketLossPRR) {
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicBytesSenderTest, SlowStartBurstPacketLossPRR) {
+TEST_F(TcpCubicSenderBytesTest, SlowStartBurstPacketLossPRR) {
sender_->SetNumEmulatedConnections(1);
// Test based on the second example in RFC6937, though we also implement
// forward acknowledgements, so the first two incoming acks will trigger
@@ -376,9 +405,7 @@ TEST_F(TcpCubicBytesSenderTest, SlowStartBurstPacketLossPRR) {
LoseNPackets(num_packets_to_lose);
// Immediately after the loss, ensure at least one packet can be sent.
// Losses without subsequent acks can occur with timer based loss detection.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero());
AckNPackets(1);
// We should now have fallen out of slow start with a reduced window.
@@ -409,7 +436,7 @@ TEST_F(TcpCubicBytesSenderTest, SlowStartBurstPacketLossPRR) {
}
}
-TEST_F(TcpCubicBytesSenderTest, RTOCongestionWindow) {
+TEST_F(TcpCubicSenderBytesTest, RTOCongestionWindow) {
EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
// Expect the window to decrease to the minimum once the RTO fires and slow
// start threshold to be set to 1/2 of the CWND.
@@ -418,7 +445,7 @@ TEST_F(TcpCubicBytesSenderTest, RTOCongestionWindow) {
EXPECT_EQ(5u * kDefaultTCPMSS, sender_->GetSlowStartThreshold());
}
-TEST_F(TcpCubicBytesSenderTest, RTOCongestionWindowNoRetransmission) {
+TEST_F(TcpCubicSenderBytesTest, RTOCongestionWindowNoRetransmission) {
EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
// Expect the window to remain unchanged if the RTO fires but no packets are
@@ -427,7 +454,7 @@ TEST_F(TcpCubicBytesSenderTest, RTOCongestionWindowNoRetransmission) {
EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicBytesSenderTest, RetransmissionDelay) {
+TEST_F(TcpCubicSenderBytesTest, RetransmissionDelay) {
const int64_t kRttMs = 10;
const int64_t kDeviationMs = 3;
EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay());
@@ -462,7 +489,7 @@ TEST_F(TcpCubicBytesSenderTest, RetransmissionDelay) {
sender_->BandwidthEstimate().ToBytesPerSecond());
}
-TEST_F(TcpCubicBytesSenderTest, TcpCubicResetEpochOnQuiescence) {
+TEST_F(TcpCubicSenderBytesTest, TcpCubicResetEpochOnQuiescence) {
const int kMaxCongestionWindow = 50;
const QuicByteCount kMaxCongestionWindowBytes =
kMaxCongestionWindow * kDefaultTCPMSS;
@@ -501,7 +528,7 @@ TEST_F(TcpCubicBytesSenderTest, TcpCubicResetEpochOnQuiescence) {
EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicBytesSenderTest, MultipleLossesInOneWindow) {
+TEST_F(TcpCubicSenderBytesTest, MultipleLossesInOneWindow) {
SendAvailableSendWindow();
const QuicByteCount initial_window = sender_->GetCongestionWindow();
LosePacket(acked_packet_number_ + 1);
@@ -517,7 +544,7 @@ TEST_F(TcpCubicBytesSenderTest, MultipleLossesInOneWindow) {
EXPECT_GT(post_loss_window, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicBytesSenderTest, DontTrackAckPackets) {
+TEST_F(TcpCubicSenderBytesTest, DontTrackAckPackets) {
// Send a packet with no retransmittable data, and ensure it's not tracked.
EXPECT_FALSE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_,
packet_number_++, kDefaultTCPMSS,
@@ -529,7 +556,7 @@ TEST_F(TcpCubicBytesSenderTest, DontTrackAckPackets) {
HAS_RETRANSMITTABLE_DATA));
}
-TEST_F(TcpCubicBytesSenderTest, ConfigureMaxInitialWindow) {
+TEST_F(TcpCubicSenderBytesTest, ConfigureMaxInitialWindow) {
QuicConfig config;
// Verify that kCOPT: kIW10 forces the congestion window to the default of 10.
@@ -540,7 +567,7 @@ TEST_F(TcpCubicBytesSenderTest, ConfigureMaxInitialWindow) {
EXPECT_EQ(10u * kDefaultTCPMSS, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicBytesSenderTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) {
+TEST_F(TcpCubicSenderBytesTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) {
sender_->SetNumEmulatedConnections(2);
// Ack 10 packets in 5 acks to raise the CWND to 20.
const int kNumberOfAcks = 5;
@@ -596,7 +623,7 @@ TEST_F(TcpCubicBytesSenderTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) {
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicBytesSenderTest, 1ConnectionCongestionAvoidanceAtEndOfRecovery) {
+TEST_F(TcpCubicSenderBytesTest, 1ConnectionCongestionAvoidanceAtEndOfRecovery) {
sender_->SetNumEmulatedConnections(1);
// Ack 10 packets in 5 acks to raise the CWND to 20.
const int kNumberOfAcks = 5;
@@ -642,7 +669,7 @@ TEST_F(TcpCubicBytesSenderTest, 1ConnectionCongestionAvoidanceAtEndOfRecovery) {
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicBytesSenderTest, BandwidthResumption) {
+TEST_F(TcpCubicSenderBytesTest, BandwidthResumption) {
// Test that when provided with CachedNetworkParameters and opted in to the
// bandwidth resumption experiment, that the TcpCubicSender sets initial CWND
// appropriately.
@@ -683,7 +710,7 @@ TEST_F(TcpCubicBytesSenderTest, BandwidthResumption) {
sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicBytesSenderTest, PaceBelowCWND) {
+TEST_F(TcpCubicSenderBytesTest, PaceBelowCWND) {
QuicConfig config;
// Verify that kCOPT: kMIN4 forces the min CWND to 1 packet, but allows up
@@ -694,21 +721,17 @@ TEST_F(TcpCubicBytesSenderTest, PaceBelowCWND) {
sender_->SetFromConfig(config, Perspective::IS_SERVER);
sender_->OnRetransmissionTimeout(true);
EXPECT_EQ(kDefaultTCPMSS, sender_->GetCongestionWindow());
- EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero());
- EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), 2 * kDefaultTCPMSS,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero());
- EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), 3 * kDefaultTCPMSS,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero());
- EXPECT_FALSE(sender_->TimeUntilSend(QuicTime::Zero(), 4 * kDefaultTCPMSS,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(
+ sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS).IsZero());
+ EXPECT_TRUE(
+ sender_->TimeUntilSend(QuicTime::Zero(), 2 * kDefaultTCPMSS).IsZero());
+ EXPECT_TRUE(
+ sender_->TimeUntilSend(QuicTime::Zero(), 3 * kDefaultTCPMSS).IsZero());
+ EXPECT_FALSE(
+ sender_->TimeUntilSend(QuicTime::Zero(), 4 * kDefaultTCPMSS).IsZero());
}
-TEST_F(TcpCubicBytesSenderTest, ResetAfterConnectionMigration) {
+TEST_F(TcpCubicSenderBytesTest, ResetAfterConnectionMigration) {
// Starts from slow start.
sender_->SetNumEmulatedConnections(1);
const int kNumberOfAcks = 10;
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_sender_packets.cc b/chromium/net/quic/congestion_control/tcp_cubic_sender_packets.cc
new file mode 100644
index 00000000000..e1c225febb4
--- /dev/null
+++ b/chromium/net/quic/congestion_control/tcp_cubic_sender_packets.cc
@@ -0,0 +1,217 @@
+// 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/congestion_control/tcp_cubic_sender_packets.h"
+
+#include <algorithm>
+
+#include "base/metrics/histogram_macros.h"
+#include "net/quic/congestion_control/prr_sender.h"
+#include "net/quic/congestion_control/rtt_stats.h"
+#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/proto/cached_network_parameters.pb.h"
+#include "net/quic/quic_bug_tracker.h"
+#include "net/quic/quic_flags.h"
+
+using std::max;
+using std::min;
+
+namespace net {
+
+namespace {
+// Constants based on TCP defaults.
+// The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a
+// fast retransmission. The cwnd after a timeout is still 1.
+const QuicPacketCount kDefaultMinimumCongestionWindow = 2;
+} // namespace
+
+TcpCubicSenderPackets::TcpCubicSenderPackets(
+ const QuicClock* clock,
+ const RttStats* rtt_stats,
+ bool reno,
+ QuicPacketCount initial_tcp_congestion_window,
+ QuicPacketCount max_tcp_congestion_window,
+ QuicConnectionStats* stats)
+ : TcpCubicSenderBase(clock, rtt_stats, reno, stats),
+ cubic_(clock),
+ congestion_window_count_(0),
+ congestion_window_(initial_tcp_congestion_window),
+ min_congestion_window_(kDefaultMinimumCongestionWindow),
+ slowstart_threshold_(max_tcp_congestion_window),
+ max_tcp_congestion_window_(max_tcp_congestion_window),
+ initial_tcp_congestion_window_(initial_tcp_congestion_window),
+ initial_max_tcp_congestion_window_(max_tcp_congestion_window) {}
+
+TcpCubicSenderPackets::~TcpCubicSenderPackets() {}
+
+void TcpCubicSenderPackets::SetCongestionWindowFromBandwidthAndRtt(
+ QuicBandwidth bandwidth,
+ QuicTime::Delta rtt) {
+ // Make sure CWND is in appropriate range (in case of bad data).
+ QuicPacketCount new_congestion_window =
+ bandwidth.ToBytesPerPeriod(rtt) / kDefaultTCPMSS;
+ congestion_window_ = max(min(new_congestion_window, kMaxCongestionWindow),
+ kMinCongestionWindowForBandwidthResumption);
+}
+
+void TcpCubicSenderPackets::SetCongestionWindowInPackets(
+ QuicPacketCount congestion_window) {
+ congestion_window_ = congestion_window;
+}
+
+void TcpCubicSenderPackets::SetMinCongestionWindowInPackets(
+ QuicPacketCount congestion_window) {
+ min_congestion_window_ = congestion_window;
+}
+
+void TcpCubicSenderPackets::SetNumEmulatedConnections(int num_connections) {
+ TcpCubicSenderBase::SetNumEmulatedConnections(num_connections);
+ cubic_.SetNumConnections(num_connections_);
+}
+
+void TcpCubicSenderPackets::SetMaxCongestionWindow(
+ QuicByteCount max_congestion_window) {
+ max_tcp_congestion_window_ = max_congestion_window / kDefaultTCPMSS;
+}
+
+void TcpCubicSenderPackets::ExitSlowstart() {
+ slowstart_threshold_ = congestion_window_;
+}
+
+void TcpCubicSenderPackets::OnPacketLost(QuicPacketNumber packet_number,
+ QuicByteCount lost_bytes,
+ QuicByteCount bytes_in_flight) {
+ // TCP NewReno (RFC6582) says that once a loss occurs, any losses in packets
+ // already sent should be treated as a single loss event, since it's expected.
+ if (packet_number <= largest_sent_at_last_cutback_) {
+ if (last_cutback_exited_slowstart_) {
+ ++stats_->slowstart_packets_lost;
+ stats_->slowstart_bytes_lost += lost_bytes;
+ if (slow_start_large_reduction_) {
+ if (FLAGS_quic_sslr_byte_conservation) {
+ if (stats_->slowstart_packets_lost == 1 ||
+ (stats_->slowstart_bytes_lost / kDefaultTCPMSS) >
+ (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_congestion_window_);
+ }
+ } else {
+ // Reduce congestion window by 1 for every loss.
+ congestion_window_ =
+ max(congestion_window_ - 1, min_congestion_window_);
+ }
+ slowstart_threshold_ = congestion_window_;
+ }
+ }
+ DVLOG(1) << "Ignoring loss for largest_missing:" << packet_number
+ << " because it was sent prior to the last CWND cutback.";
+ return;
+ }
+ ++stats_->tcp_loss_events;
+ last_cutback_exited_slowstart_ = InSlowStart();
+ if (InSlowStart()) {
+ ++stats_->slowstart_packets_lost;
+ }
+
+ prr_.OnPacketLost(bytes_in_flight);
+
+ // TODO(jri): Separate out all of slow start into a separate class.
+ if (slow_start_large_reduction_ && InSlowStart()) {
+ DCHECK_LT(1u, congestion_window_);
+ congestion_window_ = congestion_window_ - 1;
+ } else if (reno_) {
+ congestion_window_ = congestion_window_ * RenoBeta();
+ } else {
+ congestion_window_ =
+ cubic_.CongestionWindowAfterPacketLoss(congestion_window_);
+ }
+ // Enforce a minimum congestion window.
+ if (congestion_window_ < min_congestion_window_) {
+ congestion_window_ = min_congestion_window_;
+ }
+ slowstart_threshold_ = congestion_window_;
+ largest_sent_at_last_cutback_ = largest_sent_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_;
+}
+
+QuicByteCount TcpCubicSenderPackets::GetCongestionWindow() const {
+ return congestion_window_ * kDefaultTCPMSS;
+}
+
+QuicByteCount TcpCubicSenderPackets::GetSlowStartThreshold() const {
+ return slowstart_threshold_ * kDefaultTCPMSS;
+}
+
+// Called when we receive an ack. Normal TCP tracks how many packets one ack
+// represents, but quic has a separate ack for each packet.
+void TcpCubicSenderPackets::MaybeIncreaseCwnd(
+ QuicPacketNumber acked_packet_number,
+ QuicByteCount /*acked_bytes*/,
+ QuicByteCount bytes_in_flight) {
+ 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.
+ if (!IsCwndLimited(bytes_in_flight)) {
+ cubic_.OnApplicationLimited();
+ return;
+ }
+ if (congestion_window_ >= max_tcp_congestion_window_) {
+ return;
+ }
+ 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_;
+ return;
+ }
+ // Congestion avoidance
+ if (reno_) {
+ // Classic Reno congestion avoidance.
+ ++congestion_window_count_;
+ // Divide by num_connections to smoothly increase the CWND at a faster
+ // rate than conventional Reno.
+ if (congestion_window_count_ * num_connections_ >= congestion_window_) {
+ ++congestion_window_;
+ congestion_window_count_ = 0;
+ }
+
+ 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_;
+ }
+}
+
+void TcpCubicSenderPackets::HandleRetransmissionTimeout() {
+ cubic_.Reset();
+ slowstart_threshold_ = congestion_window_ / 2;
+ congestion_window_ = min_congestion_window_;
+}
+
+void TcpCubicSenderPackets::OnConnectionMigration() {
+ TcpCubicSenderBase::OnConnectionMigration();
+ cubic_.Reset();
+ congestion_window_count_ = 0;
+ congestion_window_ = initial_tcp_congestion_window_;
+ slowstart_threshold_ = initial_max_tcp_congestion_window_;
+ max_tcp_congestion_window_ = initial_max_tcp_congestion_window_;
+}
+
+CongestionControlType TcpCubicSenderPackets::GetCongestionControlType() const {
+ return reno_ ? kReno : kCubic;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_sender_packets.h b/chromium/net/quic/congestion_control/tcp_cubic_sender_packets.h
new file mode 100644
index 00000000000..5a89df83675
--- /dev/null
+++ b/chromium/net/quic/congestion_control/tcp_cubic_sender_packets.h
@@ -0,0 +1,101 @@
+// 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.
+//
+// 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_
+
+#include <stdint.h>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "net/base/net_export.h"
+#include "net/quic/congestion_control/cubic.h"
+#include "net/quic/congestion_control/hybrid_slow_start.h"
+#include "net/quic/congestion_control/prr_sender.h"
+#include "net/quic/congestion_control/tcp_cubic_sender_base.h"
+#include "net/quic/quic_bandwidth.h"
+#include "net/quic/quic_connection_stats.h"
+#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_time.h"
+
+namespace net {
+
+class RttStats;
+
+namespace test {
+class TcpCubicSenderPacketsPeer;
+} // namespace test
+
+class NET_EXPORT_PRIVATE TcpCubicSenderPackets : public TcpCubicSenderBase {
+ public:
+ // Reno option and max_tcp_congestion_window are provided for testing.
+ TcpCubicSenderPackets(const QuicClock* clock,
+ const RttStats* rtt_stats,
+ bool reno,
+ QuicPacketCount initial_tcp_congestion_window,
+ QuicPacketCount max_tcp_congestion_window,
+ QuicConnectionStats* stats);
+ ~TcpCubicSenderPackets() override;
+
+ // Start implementation of SendAlgorithmInterface.
+ void SetNumEmulatedConnections(int num_connections) override;
+ void SetMaxCongestionWindow(QuicByteCount max_congestion_window) override;
+ void OnConnectionMigration() override;
+ QuicByteCount GetCongestionWindow() const override;
+ QuicByteCount GetSlowStartThreshold() const override;
+ CongestionControlType GetCongestionControlType() const override;
+ // End implementation of SendAlgorithmInterface.
+
+ protected:
+ // TcpCubicSenderBase methods
+ void SetCongestionWindowFromBandwidthAndRtt(QuicBandwidth bandwidth,
+ QuicTime::Delta rtt) override;
+ void SetCongestionWindowInPackets(QuicPacketCount congestion_window) override;
+ void SetMinCongestionWindowInPackets(
+ QuicPacketCount congestion_window) override;
+ void ExitSlowstart() override;
+ void OnPacketLost(QuicPacketNumber largest_loss,
+ QuicByteCount lost_bytes,
+ QuicByteCount bytes_in_flight) override;
+ void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
+ QuicByteCount acked_bytes,
+ QuicByteCount bytes_in_flight) override;
+ void HandleRetransmissionTimeout() override;
+
+ private:
+ friend class test::TcpCubicSenderPacketsPeer;
+
+ Cubic cubic_;
+
+ // ACK counter for the Reno implementation.
+ uint64_t congestion_window_count_;
+
+ // Congestion window in packets.
+ QuicPacketCount congestion_window_;
+
+ // Minimum congestion window in packets.
+ QuicPacketCount min_congestion_window_;
+
+ // Slow start congestion window in packets, aka ssthresh.
+ QuicPacketCount slowstart_threshold_;
+
+ // Maximum number of outstanding packets for tcp.
+ QuicPacketCount max_tcp_congestion_window_;
+
+ // Initial TCP congestion window. This variable can only be set when this
+ // algorithm is created.
+ const QuicPacketCount initial_tcp_congestion_window_;
+
+ // Initial maximum TCP congestion window. This variable can only be set when
+ // this algorithm is created.
+ const QuicPacketCount initial_max_tcp_congestion_window_;
+
+ DISALLOW_COPY_AND_ASSIGN(TcpCubicSenderPackets);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_H_
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_sender_test.cc b/chromium/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc
index 13ae6c1c2f8..f4a4227eabe 100644
--- a/chromium/net/quic/congestion_control/tcp_cubic_sender_test.cc
+++ b/chromium/net/quic/congestion_control/tcp_cubic_sender_packets_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/congestion_control/tcp_cubic_sender.h"
+#include "net/quic/congestion_control/tcp_cubic_sender_packets.h"
#include <algorithm>
@@ -32,17 +32,17 @@ const uint32_t kDefaultWindowTCP =
kInitialCongestionWindowPackets * kDefaultTCPMSS;
const float kRenoBeta = 0.7f; // Reno backoff factor.
-class TcpCubicSenderPeer : public TcpCubicSender {
+class TcpCubicSenderPacketsPeer : public TcpCubicSenderPackets {
public:
- TcpCubicSenderPeer(const QuicClock* clock,
- bool reno,
- QuicPacketCount max_tcp_congestion_window)
- : TcpCubicSender(clock,
- &rtt_stats_,
- reno,
- kInitialCongestionWindowPackets,
- max_tcp_congestion_window,
- &stats_) {}
+ TcpCubicSenderPacketsPeer(const QuicClock* clock,
+ bool reno,
+ QuicPacketCount max_tcp_congestion_window)
+ : TcpCubicSenderPackets(clock,
+ &rtt_stats_,
+ reno,
+ kInitialCongestionWindowPackets,
+ max_tcp_congestion_window,
+ &stats_) {}
QuicPacketCount congestion_window() { return congestion_window_; }
@@ -58,29 +58,32 @@ class TcpCubicSenderPeer : public TcpCubicSender {
QuicConnectionStats stats_;
};
-class TcpCubicSenderTest : public ::testing::Test {
+class TcpCubicSenderPacketsTest : public ::testing::Test {
protected:
- TcpCubicSenderTest()
+ TcpCubicSenderPacketsTest()
: one_ms_(QuicTime::Delta::FromMilliseconds(1)),
- sender_(new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindow)),
+ sender_(
+ new TcpCubicSenderPacketsPeer(&clock_, true, kMaxCongestionWindow)),
packet_number_(1),
acked_packet_number_(0),
bytes_in_flight_(0) {}
int SendAvailableSendWindow() {
+ return SendAvailableSendWindow(kDefaultTCPMSS);
+ }
+
+ int SendAvailableSendWindow(QuicPacketLength packet_length) {
// Send as long as TimeUntilSend returns Zero.
int packets_sent = 0;
- bool can_send = sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero();
+ bool can_send =
+ sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero();
while (can_send) {
sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, packet_number_++,
kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA);
++packets_sent;
bytes_in_flight_ += kDefaultTCPMSS;
- can_send = sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero();
+ can_send =
+ sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero();
}
return packets_sent;
}
@@ -102,17 +105,19 @@ class TcpCubicSenderTest : public ::testing::Test {
clock_.AdvanceTime(one_ms_);
}
- void LoseNPackets(int n) {
+ void LoseNPackets(int n) { LoseNPackets(n, kDefaultTCPMSS); }
+
+ void LoseNPackets(int n, QuicPacketLength packet_length) {
SendAlgorithmInterface::CongestionVector acked_packets;
SendAlgorithmInterface::CongestionVector lost_packets;
for (int i = 0; i < n; ++i) {
++acked_packet_number_;
lost_packets.push_back(
- std::make_pair(acked_packet_number_, kDefaultTCPMSS));
+ std::make_pair(acked_packet_number_, packet_length));
}
sender_->OnCongestionEvent(false, bytes_in_flight_, acked_packets,
lost_packets);
- bytes_in_flight_ -= n * kDefaultTCPMSS;
+ bytes_in_flight_ -= n * packet_length;
}
// Does not increment acked_packet_number_.
@@ -127,41 +132,36 @@ class TcpCubicSenderTest : public ::testing::Test {
const QuicTime::Delta one_ms_;
MockClock clock_;
- scoped_ptr<TcpCubicSenderPeer> sender_;
+ scoped_ptr<TcpCubicSenderPacketsPeer> sender_;
QuicPacketNumber packet_number_;
QuicPacketNumber acked_packet_number_;
QuicByteCount bytes_in_flight_;
};
-TEST_F(TcpCubicSenderTest, SimpleSender) {
+TEST_F(TcpCubicSenderPacketsTest, SimpleSender) {
// At startup make sure we are at the default.
EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
// At startup make sure we can send.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
// Make sure we can send.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
// And that window is un-affected.
EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
// Fill the send window with data, then verify that we can't send.
SendAvailableSendWindow();
- EXPECT_FALSE(sender_->TimeUntilSend(clock_.Now(),
- sender_->GetCongestionWindow(),
- HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_FALSE(
+ sender_->TimeUntilSend(clock_.Now(), sender_->GetCongestionWindow())
+ .IsZero());
}
-TEST_F(TcpCubicSenderTest, ApplicationLimitedSlowStart) {
+TEST_F(TcpCubicSenderPacketsTest, ApplicationLimitedSlowStart) {
// Send exactly 10 packets and ensure the CWND ends at 14 packets.
const int kNumberOfAcks = 5;
// At startup make sure we can send.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
// Make sure we can send.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
SendAvailableSendWindow();
for (int i = 0; i < kNumberOfAcks; ++i) {
@@ -173,15 +173,13 @@ TEST_F(TcpCubicSenderTest, ApplicationLimitedSlowStart) {
EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * 2, bytes_to_send);
}
-TEST_F(TcpCubicSenderTest, ExponentialSlowStart) {
+TEST_F(TcpCubicSenderPacketsTest, ExponentialSlowStart) {
const int kNumberOfAcks = 20;
// At startup make sure we can send.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
EXPECT_EQ(QuicBandwidth::Zero(), sender_->BandwidthEstimate());
// Make sure we can send.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
for (int i = 0; i < kNumberOfAcks; ++i) {
// Send our full send window.
@@ -195,7 +193,7 @@ TEST_F(TcpCubicSenderTest, ExponentialSlowStart) {
sender_->BandwidthEstimate());
}
-TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
+TEST_F(TcpCubicSenderPacketsTest, SlowStartPacketLoss) {
sender_->SetNumEmulatedConnections(1);
const int kNumberOfAcks = 10;
for (int i = 0; i < kNumberOfAcks; ++i) {
@@ -240,7 +238,7 @@ TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
EXPECT_FALSE(sender_->hybrid_slow_start().started());
}
-TEST_F(TcpCubicSenderTest, SlowStartPacketLossWithLargeReduction) {
+TEST_F(TcpCubicSenderPacketsTest, SlowStartPacketLossWithLargeReduction) {
QuicConfig config;
QuicTagVector options;
options.push_back(kSSLR);
@@ -297,7 +295,40 @@ TEST_F(TcpCubicSenderTest, SlowStartPacketLossWithLargeReduction) {
EXPECT_FALSE(sender_->hybrid_slow_start().started());
}
-TEST_F(TcpCubicSenderTest, NoPRRWhenLessThanOnePacketInFlight) {
+TEST_F(TcpCubicSenderPacketsTest, SlowStartHalfPacketLossWithLargeReduction) {
+ FLAGS_quic_sslr_byte_conservation = true;
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kSSLR);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ sender_->SetFromConfig(config, Perspective::IS_SERVER);
+
+ sender_->SetNumEmulatedConnections(1);
+ const int kNumberOfAcks = 10;
+ for (int i = 0; i < kNumberOfAcks; ++i) {
+ // Send our full send window in half sized packets.
+ SendAvailableSendWindow(kDefaultTCPMSS / 2);
+ AckNPackets(2);
+ }
+ SendAvailableSendWindow(kDefaultTCPMSS / 2);
+ QuicByteCount expected_send_window =
+ kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks);
+ EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
+
+ // Lose a packet to exit slow start. We should now have fallen out of
+ // slow start with a window reduced by 1.
+ LoseNPackets(1);
+ expected_send_window -= kDefaultTCPMSS;
+ EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
+
+ // Lose 10 packets in recovery and verify that congestion window is reduced
+ // by 5 packets.
+ LoseNPackets(10, kDefaultTCPMSS / 2);
+ expected_send_window -= 5 * kDefaultTCPMSS;
+ EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
+}
+
+TEST_F(TcpCubicSenderPacketsTest, NoPRRWhenLessThanOnePacketInFlight) {
SendAvailableSendWindow();
LoseNPackets(kInitialCongestionWindowPackets - 1);
AckNPackets(1);
@@ -306,11 +337,10 @@ TEST_F(TcpCubicSenderTest, NoPRRWhenLessThanOnePacketInFlight) {
// Simulate abandoning all packets by supplying a bytes_in_flight of 0.
// PRR should now allow a packet to be sent, even though prr's state
// variables believe it has sent enough packets.
- EXPECT_EQ(QuicTime::Delta::Zero(),
- sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA));
+ EXPECT_EQ(QuicTime::Delta::Zero(), sender_->TimeUntilSend(clock_.Now(), 0));
}
-TEST_F(TcpCubicSenderTest, SlowStartPacketLossPRR) {
+TEST_F(TcpCubicSenderPacketsTest, SlowStartPacketLossPRR) {
sender_->SetNumEmulatedConnections(1);
// Test based on the first example in RFC6937.
// Ack 10 packets in 5 acks to raise the CWND to 20, as in the example.
@@ -359,7 +389,7 @@ TEST_F(TcpCubicSenderTest, SlowStartPacketLossPRR) {
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicSenderTest, SlowStartBurstPacketLossPRR) {
+TEST_F(TcpCubicSenderPacketsTest, SlowStartBurstPacketLossPRR) {
sender_->SetNumEmulatedConnections(1);
// Test based on the second example in RFC6937, though we also implement
// forward acknowledgements, so the first two incoming acks will trigger
@@ -384,9 +414,7 @@ TEST_F(TcpCubicSenderTest, SlowStartBurstPacketLossPRR) {
LoseNPackets(num_packets_to_lose);
// Immediately after the loss, ensure at least one packet can be sent.
// Losses without subsequent acks can occur with timer based loss detection.
- EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero());
AckNPackets(1);
// We should now have fallen out of slow start with a reduced window.
@@ -417,7 +445,7 @@ TEST_F(TcpCubicSenderTest, SlowStartBurstPacketLossPRR) {
}
}
-TEST_F(TcpCubicSenderTest, RTOCongestionWindow) {
+TEST_F(TcpCubicSenderPacketsTest, RTOCongestionWindow) {
EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
EXPECT_EQ(kMaxCongestionWindow, sender_->slowstart_threshold());
@@ -428,7 +456,7 @@ TEST_F(TcpCubicSenderTest, RTOCongestionWindow) {
EXPECT_EQ(5u, sender_->slowstart_threshold());
}
-TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) {
+TEST_F(TcpCubicSenderPacketsTest, RTOCongestionWindowNoRetransmission) {
EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
// Expect the window to remain unchanged if the RTO fires but no
@@ -437,7 +465,7 @@ TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) {
EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicSenderTest, RetransmissionDelay) {
+TEST_F(TcpCubicSenderPacketsTest, RetransmissionDelay) {
const int64_t kRttMs = 10;
const int64_t kDeviationMs = 3;
EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay());
@@ -472,11 +500,11 @@ TEST_F(TcpCubicSenderTest, RetransmissionDelay) {
sender_->BandwidthEstimate().ToBytesPerSecond());
}
-TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) {
+TEST_F(TcpCubicSenderPacketsTest, SlowStartMaxSendWindow) {
const QuicPacketCount kMaxCongestionWindowTCP = 50;
const int kNumberOfAcks = 100;
sender_.reset(
- new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));
+ new TcpCubicSenderPacketsPeer(&clock_, false, kMaxCongestionWindowTCP));
for (int i = 0; i < kNumberOfAcks; ++i) {
// Send our full send window.
@@ -487,10 +515,11 @@ TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) {
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) {
+TEST_F(TcpCubicSenderPacketsTest, TcpRenoMaxCongestionWindow) {
const QuicPacketCount kMaxCongestionWindowTCP = 50;
const int kNumberOfAcks = 1000;
- sender_.reset(new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindowTCP));
+ sender_.reset(
+ new TcpCubicSenderPacketsPeer(&clock_, true, kMaxCongestionWindowTCP));
SendAvailableSendWindow();
AckNPackets(2);
@@ -507,13 +536,13 @@ TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) {
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) {
+TEST_F(TcpCubicSenderPacketsTest, TcpCubicMaxCongestionWindow) {
const QuicPacketCount kMaxCongestionWindowTCP = 50;
// Set to 10000 to compensate for small cubic alpha.
const int kNumberOfAcks = 10000;
sender_.reset(
- new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));
+ new TcpCubicSenderPacketsPeer(&clock_, false, kMaxCongestionWindowTCP));
SendAvailableSendWindow();
AckNPackets(2);
@@ -530,11 +559,12 @@ TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) {
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicSenderTest, TcpCubicResetEpochOnQuiescence) {
+TEST_F(TcpCubicSenderPacketsTest, TcpCubicResetEpochOnQuiescence) {
const int kMaxCongestionWindow = 50;
const QuicByteCount kMaxCongestionWindowBytes =
kMaxCongestionWindow * kDefaultTCPMSS;
- sender_.reset(new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindow));
+ sender_.reset(
+ new TcpCubicSenderPacketsPeer(&clock_, false, kMaxCongestionWindow));
int num_sent = SendAvailableSendWindow();
@@ -571,13 +601,14 @@ TEST_F(TcpCubicSenderTest, TcpCubicResetEpochOnQuiescence) {
EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicSenderTest, TcpCubicShiftedEpochOnQuiescence) {
+TEST_F(TcpCubicSenderPacketsTest, TcpCubicShiftedEpochOnQuiescence) {
ValueRestore<bool> old_flag(&FLAGS_shift_quic_cubic_epoch_when_app_limited,
true);
const int kMaxCongestionWindow = 50;
const QuicByteCount kMaxCongestionWindowBytes =
kMaxCongestionWindow * kDefaultTCPMSS;
- sender_.reset(new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindow));
+ sender_.reset(
+ new TcpCubicSenderPacketsPeer(&clock_, false, kMaxCongestionWindow));
int num_sent = SendAvailableSendWindow();
@@ -614,7 +645,7 @@ TEST_F(TcpCubicSenderTest, TcpCubicShiftedEpochOnQuiescence) {
EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicSenderTest, MultipleLossesInOneWindow) {
+TEST_F(TcpCubicSenderPacketsTest, MultipleLossesInOneWindow) {
SendAvailableSendWindow();
const QuicByteCount initial_window = sender_->GetCongestionWindow();
LosePacket(acked_packet_number_ + 1);
@@ -630,7 +661,7 @@ TEST_F(TcpCubicSenderTest, MultipleLossesInOneWindow) {
EXPECT_GT(post_loss_window, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicSenderTest, DontTrackAckPackets) {
+TEST_F(TcpCubicSenderPacketsTest, DontTrackAckPackets) {
// Send a packet with no retransmittable data, and ensure it's not tracked.
EXPECT_FALSE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_,
packet_number_++, kDefaultTCPMSS,
@@ -642,7 +673,7 @@ TEST_F(TcpCubicSenderTest, DontTrackAckPackets) {
HAS_RETRANSMITTABLE_DATA));
}
-TEST_F(TcpCubicSenderTest, ConfigureInitialWindow) {
+TEST_F(TcpCubicSenderPacketsTest, ConfigureInitialWindow) {
QuicConfig config;
QuicTagVector options;
@@ -670,7 +701,7 @@ TEST_F(TcpCubicSenderTest, ConfigureInitialWindow) {
EXPECT_EQ(50u, sender_->congestion_window());
}
-TEST_F(TcpCubicSenderTest, ConfigureMinimumWindow) {
+TEST_F(TcpCubicSenderPacketsTest, ConfigureMinimumWindow) {
QuicConfig config;
// Verify that kCOPT: kMIN1 forces the min CWND to 1 packet.
@@ -682,7 +713,8 @@ TEST_F(TcpCubicSenderTest, ConfigureMinimumWindow) {
EXPECT_EQ(1u, sender_->congestion_window());
}
-TEST_F(TcpCubicSenderTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) {
+TEST_F(TcpCubicSenderPacketsTest,
+ 2ConnectionCongestionAvoidanceAtEndOfRecovery) {
sender_->SetNumEmulatedConnections(2);
// Ack 10 packets in 5 acks to raise the CWND to 20.
const int kNumberOfAcks = 5;
@@ -738,7 +770,8 @@ TEST_F(TcpCubicSenderTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) {
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicSenderTest, 1ConnectionCongestionAvoidanceAtEndOfRecovery) {
+TEST_F(TcpCubicSenderPacketsTest,
+ 1ConnectionCongestionAvoidanceAtEndOfRecovery) {
sender_->SetNumEmulatedConnections(1);
// Ack 10 packets in 5 acks to raise the CWND to 20.
const int kNumberOfAcks = 5;
@@ -784,10 +817,10 @@ TEST_F(TcpCubicSenderTest, 1ConnectionCongestionAvoidanceAtEndOfRecovery) {
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicSenderTest, BandwidthResumption) {
+TEST_F(TcpCubicSenderPacketsTest, BandwidthResumption) {
// Test that when provided with CachedNetworkParameters and opted in to the
- // bandwidth resumption experiment, that the TcpCubicSender sets initial CWND
- // appropriately.
+ // bandwidth resumption experiment, that the TcpCubicSenderPackets sets
+ // initial CWND appropriately.
// Set some common values.
CachedNetworkParameters cached_network_params;
@@ -824,7 +857,7 @@ TEST_F(TcpCubicSenderTest, BandwidthResumption) {
sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicSenderTest, PaceBelowCWND) {
+TEST_F(TcpCubicSenderPacketsTest, PaceBelowCWND) {
QuicConfig config;
// Verify that kCOPT: kMIN4 forces the min CWND to 1 packet, but allows up
@@ -835,21 +868,17 @@ TEST_F(TcpCubicSenderTest, PaceBelowCWND) {
sender_->SetFromConfig(config, Perspective::IS_SERVER);
sender_->OnRetransmissionTimeout(true);
EXPECT_EQ(1u, sender_->congestion_window());
- EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero());
- EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), 2 * kDefaultTCPMSS,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero());
- EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), 3 * kDefaultTCPMSS,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero());
- EXPECT_FALSE(sender_->TimeUntilSend(QuicTime::Zero(), 4 * kDefaultTCPMSS,
- HAS_RETRANSMITTABLE_DATA)
- .IsZero());
+ EXPECT_TRUE(
+ sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS).IsZero());
+ EXPECT_TRUE(
+ sender_->TimeUntilSend(QuicTime::Zero(), 2 * kDefaultTCPMSS).IsZero());
+ EXPECT_TRUE(
+ sender_->TimeUntilSend(QuicTime::Zero(), 3 * kDefaultTCPMSS).IsZero());
+ EXPECT_FALSE(
+ sender_->TimeUntilSend(QuicTime::Zero(), 4 * kDefaultTCPMSS).IsZero());
}
-TEST_F(TcpCubicSenderTest, ResetAfterConnectionMigration) {
+TEST_F(TcpCubicSenderPacketsTest, ResetAfterConnectionMigration) {
EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
EXPECT_EQ(kMaxCongestionWindow, sender_->slowstart_threshold());
diff --git a/chromium/net/quic/congestion_control/tcp_loss_algorithm.cc b/chromium/net/quic/congestion_control/tcp_loss_algorithm.cc
deleted file mode 100644
index f493d961ef1..00000000000
--- a/chromium/net/quic/congestion_control/tcp_loss_algorithm.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2014 The Chromium 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/congestion_control/tcp_loss_algorithm.h"
-
-#include "net/quic/congestion_control/rtt_stats.h"
-#include "net/quic/quic_protocol.h"
-
-namespace net {
-
-namespace {
-
-// The minimum delay before a packet will be considered lost,
-// regardless of SRTT. Half of the minimum TLP, since the loss algorithm only
-// triggers when a nack has been receieved for the packet.
-static const size_t kMinLossDelayMs = 5;
-
-// How many RTTs the algorithm waits before determining a packet is lost due
-// to early retransmission.
-static const double kEarlyRetransmitLossDelayMultiplier = 1.25;
-
-} // namespace
-
-TCPLossAlgorithm::TCPLossAlgorithm()
- : loss_detection_timeout_(QuicTime::Zero()) {}
-
-LossDetectionType TCPLossAlgorithm::GetLossDetectionType() const {
- return kNack;
-}
-
-// Uses nack counts to decide when packets are lost.
-PacketNumberSet TCPLossAlgorithm::DetectLostPackets(
- const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
- QuicPacketNumber largest_observed,
- const RttStats& rtt_stats) {
- PacketNumberSet lost_packets;
- loss_detection_timeout_ = QuicTime::Zero();
- QuicTime::Delta early_retransmit_delay = QuicTime::Delta::Max(
- QuicTime::Delta::FromMilliseconds(kMinLossDelayMs),
- rtt_stats.smoothed_rtt().Multiply(kEarlyRetransmitLossDelayMultiplier));
-
- QuicPacketNumber packet_number = unacked_packets.GetLeastUnacked();
- for (QuicUnackedPacketMap::const_iterator it = unacked_packets.begin();
- it != unacked_packets.end() && packet_number <= largest_observed;
- ++it, ++packet_number) {
- if (!it->in_flight) {
- continue;
- }
-
- LOG_IF(DFATAL, it->nack_count == 0 && it->sent_time.IsInitialized())
- << "All packets less than largest observed should have been nacked."
- << "packet_number:" << packet_number
- << " largest_observed:" << largest_observed;
- if (it->nack_count >= kNumberOfNacksBeforeRetransmission) {
- lost_packets.insert(packet_number);
- continue;
- }
-
- // Immediately lose the packet if it's been an srtt between the sent time
- // of it and the largest observed. This speeds recovery from timer based
- // retransmissions, such as TLP and RTO, when there may be fewer than
- // kNumberOfNacksBeforeRetransmission nacks.
- if (it->sent_time.Add(rtt_stats.smoothed_rtt()) <
- unacked_packets.GetTransmissionInfo(largest_observed).sent_time) {
- lost_packets.insert(packet_number);
- continue;
- }
-
- // Only early retransmit(RFC5827) when the last packet gets acked and
- // there are retransmittable packets in flight.
- // This also implements a timer-protected variant of FACK.
- if (it->retransmittable_frames &&
- unacked_packets.largest_sent_packet() == largest_observed) {
- // Early retransmit marks the packet as lost once 1.25RTTs have passed
- // since the packet was sent and otherwise sets an alarm.
- if (time >= it->sent_time.Add(early_retransmit_delay)) {
- lost_packets.insert(packet_number);
- } else {
- // Set the timeout for the earliest retransmittable packet where early
- // retransmit applies.
- loss_detection_timeout_ = it->sent_time.Add(early_retransmit_delay);
- break;
- }
- }
- }
-
- return lost_packets;
-}
-
-void TCPLossAlgorithm::DetectLosses(
- const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
- const RttStats& rtt_stats,
- SendAlgorithmInterface::CongestionVector* packets_lost) {
- LOG(DFATAL) << "DetectLoss is unsupported by TCPLossAlgorithm.";
-}
-
-QuicTime TCPLossAlgorithm::GetLossTimeout() const {
- return loss_detection_timeout_;
-}
-
-} // namespace net
diff --git a/chromium/net/quic/congestion_control/tcp_loss_algorithm.h b/chromium/net/quic/congestion_control/tcp_loss_algorithm.h
deleted file mode 100644
index 35f04ce7945..00000000000
--- a/chromium/net/quic/congestion_control/tcp_loss_algorithm.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2014 The Chromium 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_CONGESTION_CONTROL_TCP_LOSS_ALGORITHM_H_
-#define NET_QUIC_CONGESTION_CONTROL_TCP_LOSS_ALGORITHM_H_
-
-#include <algorithm>
-#include <map>
-
-#include "base/macros.h"
-#include "net/quic/congestion_control/loss_detection_interface.h"
-#include "net/quic/quic_protocol.h"
-#include "net/quic/quic_time.h"
-#include "net/quic/quic_unacked_packet_map.h"
-
-namespace net {
-
-// Class which implement's TCP's approach of detecting loss when 3 nacks have
-// been received for a packet. Also implements TCP's early retransmit(RFC5827).
-class NET_EXPORT_PRIVATE TCPLossAlgorithm : public LossDetectionInterface {
- public:
- // TCP retransmits after 3 nacks.
- static const QuicPacketCount kNumberOfNacksBeforeRetransmission = 3;
-
- TCPLossAlgorithm();
- ~TCPLossAlgorithm() override {}
-
- LossDetectionType GetLossDetectionType() const override;
-
- // Uses nack counts to decide when packets are lost.
- PacketNumberSet DetectLostPackets(const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
- QuicPacketNumber largest_observed,
- const RttStats& rtt_stats) override;
- // Unsupported.
- void DetectLosses(
- const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
- const RttStats& rtt_stats,
- SendAlgorithmInterface::CongestionVector* packets_lost) override;
-
- // Returns a non-zero value when the early retransmit timer is active.
- QuicTime GetLossTimeout() const override;
-
- private:
- QuicTime loss_detection_timeout_;
-
- DISALLOW_COPY_AND_ASSIGN(TCPLossAlgorithm);
-};
-
-} // namespace net
-
-#endif // NET_QUIC_CONGESTION_CONTROL_TCP_LOSS_ALGORITHM_H_
diff --git a/chromium/net/quic/congestion_control/tcp_loss_algorithm_test.cc b/chromium/net/quic/congestion_control/tcp_loss_algorithm_test.cc
deleted file mode 100644
index da51adfd762..00000000000
--- a/chromium/net/quic/congestion_control/tcp_loss_algorithm_test.cc
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright 2014 The Chromium 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/congestion_control/tcp_loss_algorithm.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "net/quic/congestion_control/rtt_stats.h"
-#include "net/quic/quic_unacked_packet_map.h"
-#include "net/quic/test_tools/mock_clock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using std::vector;
-
-namespace net {
-namespace test {
-namespace {
-
-// Default packet length.
-const uint32_t kDefaultLength = 1000;
-
-class TcpLossAlgorithmTest : public ::testing::Test {
- protected:
- TcpLossAlgorithmTest() {
- rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
- QuicTime::Delta::Zero(), clock_.Now());
- }
-
- ~TcpLossAlgorithmTest() override { STLDeleteElements(&packets_); }
-
- void SendDataPacket(QuicPacketNumber packet_number) {
- packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
- RetransmittableFrames* frames = new RetransmittableFrames();
- QuicStreamFrame* frame = new QuicStreamFrame();
- frame->stream_id = kHeadersStreamId;
- frames->AddFrame(QuicFrame(frame));
- SerializedPacket packet(kDefaultPathId, packet_number,
- PACKET_1BYTE_PACKET_NUMBER, packets_.back(), 0,
- frames, false, false);
- unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(),
- 1000, true);
- }
-
- void VerifyLosses(QuicPacketNumber largest_observed,
- QuicPacketNumber* losses_expected,
- size_t num_losses) {
- PacketNumberSet lost_packets = loss_algorithm_.DetectLostPackets(
- unacked_packets_, clock_.Now(), largest_observed, rtt_stats_);
- EXPECT_EQ(num_losses, lost_packets.size());
- for (size_t i = 0; i < num_losses; ++i) {
- EXPECT_TRUE(ContainsKey(lost_packets, losses_expected[i]));
- }
- }
-
- vector<QuicEncryptedPacket*> packets_;
- QuicUnackedPacketMap unacked_packets_;
- TCPLossAlgorithm loss_algorithm_;
- RttStats rtt_stats_;
- MockClock clock_;
-};
-
-TEST_F(TcpLossAlgorithmTest, NackRetransmit1Packet) {
- const size_t kNumSentPackets = 5;
- // Transmit 5 packets.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
- // No loss on one ack.
- unacked_packets_.RemoveFromInFlight(2);
- unacked_packets_.NackPacket(1, 1);
- VerifyLosses(2, nullptr, 0);
- // No loss on two acks.
- unacked_packets_.RemoveFromInFlight(3);
- unacked_packets_.NackPacket(1, 2);
- VerifyLosses(3, nullptr, 0);
- // Loss on three acks.
- unacked_packets_.RemoveFromInFlight(4);
- unacked_packets_.NackPacket(1, 3);
- QuicPacketNumber lost[] = {1};
- VerifyLosses(4, lost, arraysize(lost));
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-// A stretch ack is an ack that covers more than 1 packet of previously
-// unacknowledged data.
-TEST_F(TcpLossAlgorithmTest, NackRetransmit1PacketWith1StretchAck) {
- const size_t kNumSentPackets = 10;
- // Transmit 10 packets.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
-
- // Nack the first packet 3 times in a single StretchAck.
- unacked_packets_.NackPacket(1, 3);
- unacked_packets_.RemoveFromInFlight(2);
- unacked_packets_.RemoveFromInFlight(3);
- unacked_packets_.RemoveFromInFlight(4);
- QuicPacketNumber lost[] = {1};
- VerifyLosses(4, lost, arraysize(lost));
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-// Ack a packet 3 packets ahead, causing a retransmit.
-TEST_F(TcpLossAlgorithmTest, NackRetransmit1PacketSingleAck) {
- const size_t kNumSentPackets = 10;
- // Transmit 10 packets.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
-
- // Nack the first packet 3 times in an AckFrame with three missing packets.
- unacked_packets_.NackPacket(1, 3);
- unacked_packets_.NackPacket(2, 2);
- unacked_packets_.NackPacket(3, 1);
- unacked_packets_.RemoveFromInFlight(4);
- QuicPacketNumber lost[] = {1};
- VerifyLosses(4, lost, arraysize(lost));
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-TEST_F(TcpLossAlgorithmTest, EarlyRetransmit1Packet) {
- const size_t kNumSentPackets = 2;
- // Transmit 2 packets.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
- // Early retransmit when the final packet gets acked and the first is nacked.
- unacked_packets_.RemoveFromInFlight(2);
- unacked_packets_.NackPacket(1, 1);
- VerifyLosses(2, nullptr, 0);
- EXPECT_EQ(clock_.Now().Add(rtt_stats_.smoothed_rtt().Multiply(1.25)),
- loss_algorithm_.GetLossTimeout());
-
- clock_.AdvanceTime(rtt_stats_.latest_rtt().Multiply(1.25));
- QuicPacketNumber lost[] = {1};
- VerifyLosses(2, lost, arraysize(lost));
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-TEST_F(TcpLossAlgorithmTest, EarlyRetransmitAllPackets) {
- const size_t kNumSentPackets = 5;
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- // Advance the time 1/4 RTT between 3 and 4.
- if (i == 3) {
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.25));
- }
- }
-
- // Early retransmit when the final packet gets acked and 1.25 RTTs have
- // elapsed since the packets were sent.
- unacked_packets_.RemoveFromInFlight(kNumSentPackets);
- // This simulates a single ack following multiple missing packets with FACK.
- for (size_t i = 1; i < kNumSentPackets; ++i) {
- unacked_packets_.NackPacket(i, static_cast<uint16_t>(kNumSentPackets - i));
- }
- QuicPacketNumber lost[] = {1, 2};
- VerifyLosses(kNumSentPackets, lost, arraysize(lost));
- // The time has already advanced 1/4 an RTT, so ensure the timeout is set
- // 1.25 RTTs after the earliest pending packet(3), not the last(4).
- EXPECT_EQ(clock_.Now().Add(rtt_stats_.smoothed_rtt()),
- loss_algorithm_.GetLossTimeout());
-
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
- QuicPacketNumber lost2[] = {1, 2, 3};
- VerifyLosses(kNumSentPackets, lost2, arraysize(lost2));
- EXPECT_EQ(clock_.Now().Add(rtt_stats_.smoothed_rtt().Multiply(0.25)),
- loss_algorithm_.GetLossTimeout());
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.25));
- QuicPacketNumber lost3[] = {1, 2, 3, 4};
- VerifyLosses(kNumSentPackets, lost3, arraysize(lost3));
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-TEST_F(TcpLossAlgorithmTest, DontEarlyRetransmitNeuteredPacket) {
- const size_t kNumSentPackets = 2;
- // Transmit 2 packets.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
- // Neuter packet 1.
- unacked_packets_.RemoveRetransmittability(1);
-
- // Early retransmit when the final packet gets acked and the first is nacked.
- unacked_packets_.IncreaseLargestObserved(2);
- unacked_packets_.RemoveFromInFlight(2);
- unacked_packets_.NackPacket(1, 1);
- VerifyLosses(2, nullptr, 0);
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-TEST_F(TcpLossAlgorithmTest, AlwaysLosePacketSent1RTTEarlier) {
- // Transmit 1 packet and then wait an rtt plus 1ms.
- SendDataPacket(1);
- clock_.AdvanceTime(
- rtt_stats_.smoothed_rtt().Add(QuicTime::Delta::FromMilliseconds(1)));
-
- // Transmit 2 packets.
- SendDataPacket(2);
- SendDataPacket(3);
-
- // Wait another RTT and ack 2.
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
- unacked_packets_.IncreaseLargestObserved(2);
- unacked_packets_.RemoveFromInFlight(2);
- unacked_packets_.NackPacket(1, 1);
- QuicPacketNumber lost[] = {1};
- VerifyLosses(2, lost, arraysize(lost));
-}
-
-} // namespace
-} // namespace test
-} // namespace net
diff --git a/chromium/net/quic/congestion_control/time_loss_algorithm.cc b/chromium/net/quic/congestion_control/time_loss_algorithm.cc
deleted file mode 100644
index fbca9da99e7..00000000000
--- a/chromium/net/quic/congestion_control/time_loss_algorithm.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2014 The Chromium 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/congestion_control/time_loss_algorithm.h"
-
-#include "net/quic/congestion_control/rtt_stats.h"
-#include "net/quic/quic_protocol.h"
-
-namespace net {
-namespace {
-
-// The minimum delay before a packet will be considered lost,
-// regardless of SRTT. Half of the minimum TLP, since the loss algorithm only
-// triggers when a nack has been receieved for the packet.
-static const size_t kMinLossDelayMs = 5;
-
-// How many RTTs the algorithm waits before determining a packet is lost.
-static const double kLossDelayMultiplier = 1.25;
-
-} // namespace
-
-TimeLossAlgorithm::TimeLossAlgorithm()
- : loss_detection_timeout_(QuicTime::Zero()) {}
-
-LossDetectionType TimeLossAlgorithm::GetLossDetectionType() const {
- return kTime;
-}
-
-PacketNumberSet TimeLossAlgorithm::DetectLostPackets(
- const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
- QuicPacketNumber largest_observed,
- const RttStats& rtt_stats) {
- PacketNumberSet lost_packets;
- loss_detection_timeout_ = QuicTime::Zero();
- QuicTime::Delta loss_delay = QuicTime::Delta::Max(
- QuicTime::Delta::FromMilliseconds(kMinLossDelayMs),
- QuicTime::Delta::Max(rtt_stats.smoothed_rtt(), rtt_stats.latest_rtt())
- .Multiply(kLossDelayMultiplier));
-
- QuicPacketNumber packet_number = unacked_packets.GetLeastUnacked();
- for (QuicUnackedPacketMap::const_iterator it = unacked_packets.begin();
- it != unacked_packets.end() && packet_number <= largest_observed;
- ++it, ++packet_number) {
- if (!it->in_flight) {
- continue;
- }
- LOG_IF(DFATAL, it->nack_count == 0 && it->sent_time.IsInitialized())
- << "All packets less than largest observed should have been nacked."
- << "packet_number:" << packet_number
- << " largest_observed:" << largest_observed;
-
- // Packets are sent in order, so break when we haven't waited long enough
- // to lose any more packets and leave the loss_time_ set for the timeout.
- QuicTime when_lost = it->sent_time.Add(loss_delay);
- if (time < when_lost) {
- loss_detection_timeout_ = when_lost;
- break;
- }
- lost_packets.insert(packet_number);
- }
-
- return lost_packets;
-}
-
-void TimeLossAlgorithm::DetectLosses(
- const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
- const RttStats& rtt_stats,
- SendAlgorithmInterface::CongestionVector* packets_lost) {
- LOG(DFATAL) << "DetectLoss is unsupported by TimeLossAlgorithm.";
-}
-
-// loss_time_ is updated in DetectLostPackets, which must be called every time
-// an ack is received or the timeout expires.
-QuicTime TimeLossAlgorithm::GetLossTimeout() const {
- return loss_detection_timeout_;
-}
-
-} // namespace net
diff --git a/chromium/net/quic/congestion_control/time_loss_algorithm.h b/chromium/net/quic/congestion_control/time_loss_algorithm.h
deleted file mode 100644
index 6c1359eda2d..00000000000
--- a/chromium/net/quic/congestion_control/time_loss_algorithm.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2014 The Chromium 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_CONGESTION_CONTROL_TIME_LOSS_ALGORITHM_H_
-#define NET_QUIC_CONGESTION_CONTROL_TIME_LOSS_ALGORITHM_H_
-
-#include <algorithm>
-#include <map>
-
-#include "base/macros.h"
-#include "net/quic/congestion_control/loss_detection_interface.h"
-#include "net/quic/quic_protocol.h"
-#include "net/quic/quic_time.h"
-#include "net/quic/quic_unacked_packet_map.h"
-
-namespace net {
-
-// A loss detection algorithm which avoids spurious losses and retransmissions
-// by waiting 1.25 RTTs after a packet was sent instead of nack count.
-class NET_EXPORT_PRIVATE TimeLossAlgorithm : public LossDetectionInterface {
- public:
- TimeLossAlgorithm();
- ~TimeLossAlgorithm() override {}
-
- LossDetectionType GetLossDetectionType() const override;
-
- // Declares pending packets less than the largest observed lost when it has
- // been 1.25 RTT since they were sent. Packets larger than the largest
- // observed are retransmitted via TLP.
- PacketNumberSet DetectLostPackets(const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
- QuicPacketNumber largest_observed,
- const RttStats& rtt_stats) override;
-
- // Unsupported.
- void DetectLosses(
- const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
- const RttStats& rtt_stats,
- SendAlgorithmInterface::CongestionVector* packets_lost) override;
-
- // Returns the time the next packet will be lost, or zero if there
- // are no nacked pending packets outstanding.
- // TODO(ianswett): Ideally the RTT variance and the RTT would be used to
- // determine the time a packet is considered lost.
- // TODO(ianswett): Consider using Max(1.25 * srtt, 1.125 * last_rtt).
- QuicTime GetLossTimeout() const override;
-
- private:
- QuicTime loss_detection_timeout_;
-
- DISALLOW_COPY_AND_ASSIGN(TimeLossAlgorithm);
-};
-
-} // namespace net
-
-#endif // NET_QUIC_CONGESTION_CONTROL_TIME_LOSS_ALGORITHM_H_
diff --git a/chromium/net/quic/congestion_control/time_loss_algorithm_test.cc b/chromium/net/quic/congestion_control/time_loss_algorithm_test.cc
deleted file mode 100644
index cbdc794611e..00000000000
--- a/chromium/net/quic/congestion_control/time_loss_algorithm_test.cc
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2014 The Chromium 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/congestion_control/time_loss_algorithm.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "net/quic/congestion_control/rtt_stats.h"
-#include "net/quic/quic_unacked_packet_map.h"
-#include "net/quic/test_tools/mock_clock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using std::vector;
-
-namespace net {
-namespace test {
-namespace {
-
-// Default packet length.
-const uint32_t kDefaultLength = 1000;
-
-class TimeLossAlgorithmTest : public ::testing::Test {
- protected:
- TimeLossAlgorithmTest() {
- rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
- QuicTime::Delta::Zero(), clock_.Now());
- }
-
- ~TimeLossAlgorithmTest() override { STLDeleteElements(&packets_); }
-
- void SendDataPacket(QuicPacketNumber packet_number) {
- packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
- SerializedPacket packet(kDefaultPathId, packet_number,
- PACKET_1BYTE_PACKET_NUMBER, packets_.back(), 0,
- new RetransmittableFrames(), false, false);
- unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(),
- 1000, true);
- }
-
- void VerifyLosses(QuicPacketNumber largest_observed,
- QuicPacketNumber* losses_expected,
- size_t num_losses) {
- PacketNumberSet lost_packets = loss_algorithm_.DetectLostPackets(
- unacked_packets_, clock_.Now(), largest_observed, rtt_stats_);
- EXPECT_EQ(num_losses, lost_packets.size());
- for (size_t i = 0; i < num_losses; ++i) {
- EXPECT_TRUE(ContainsKey(lost_packets, losses_expected[i]));
- }
- }
-
- vector<QuicEncryptedPacket*> packets_;
- QuicUnackedPacketMap unacked_packets_;
- TimeLossAlgorithm loss_algorithm_;
- RttStats rtt_stats_;
- MockClock clock_;
-};
-
-TEST_F(TimeLossAlgorithmTest, NoLossFor500Nacks) {
- const size_t kNumSentPackets = 5;
- // Transmit 5 packets.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
- unacked_packets_.RemoveFromInFlight(2);
- for (uint16_t i = 1; i < 500; ++i) {
- unacked_packets_.NackPacket(1, i);
- VerifyLosses(2, nullptr, 0);
- }
- EXPECT_EQ(rtt_stats_.smoothed_rtt().Multiply(1.25),
- loss_algorithm_.GetLossTimeout().Subtract(clock_.Now()));
-}
-
-TEST_F(TimeLossAlgorithmTest, NoLossUntilTimeout) {
- const size_t kNumSentPackets = 10;
- // Transmit 10 packets at 1/10th an RTT interval.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.1));
- }
- // Expect the timer to not be set.
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- // The packet should not be lost until 1.25 RTTs pass.
- unacked_packets_.NackPacket(1, 1);
- unacked_packets_.RemoveFromInFlight(2);
- VerifyLosses(2, nullptr, 0);
- // Expect the timer to be set to 0.25 RTT's in the future.
- EXPECT_EQ(rtt_stats_.smoothed_rtt().Multiply(0.25),
- loss_algorithm_.GetLossTimeout().Subtract(clock_.Now()));
- unacked_packets_.NackPacket(1, 5);
- VerifyLosses(2, nullptr, 0);
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.25));
- QuicPacketNumber lost[] = {1};
- VerifyLosses(2, lost, arraysize(lost));
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-TEST_F(TimeLossAlgorithmTest, NoLossWithoutNack) {
- const size_t kNumSentPackets = 10;
- // Transmit 10 packets at 1/10th an RTT interval.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.1));
- }
- // Expect the timer to not be set.
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- // The packet should not be lost without a nack.
- unacked_packets_.RemoveFromInFlight(1);
- VerifyLosses(1, nullptr, 0);
- // The timer should still not be set.
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.25));
- VerifyLosses(1, nullptr, 0);
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
- VerifyLosses(1, nullptr, 0);
-
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-TEST_F(TimeLossAlgorithmTest, MultipleLossesAtOnce) {
- const size_t kNumSentPackets = 10;
- // Transmit 10 packets at once and then go forward an RTT.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
- // Expect the timer to not be set.
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- // The packet should not be lost until 1.25 RTTs pass.
- for (size_t i = 1; i < kNumSentPackets; ++i) {
- unacked_packets_.NackPacket(i, 1);
- }
- unacked_packets_.RemoveFromInFlight(10);
- VerifyLosses(10, nullptr, 0);
- // Expect the timer to be set to 0.25 RTT's in the future.
- EXPECT_EQ(rtt_stats_.smoothed_rtt().Multiply(0.25),
- loss_algorithm_.GetLossTimeout().Subtract(clock_.Now()));
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.25));
- QuicPacketNumber lost[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- VerifyLosses(10, lost, arraysize(lost));
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-} // namespace
-} // namespace test
-} // namespace net
diff --git a/chromium/net/quic/crypto/aead_base_decrypter.h b/chromium/net/quic/crypto/aead_base_decrypter.h
index 39cc555fb52..c76f11f6c6e 100644
--- a/chromium/net/quic/crypto/aead_base_decrypter.h
+++ b/chromium/net/quic/crypto/aead_base_decrypter.h
@@ -38,9 +38,10 @@ class NET_EXPORT_PRIVATE AeadBaseDecrypter : public QuicDecrypter {
// QuicDecrypter implementation
bool SetKey(base::StringPiece key) override;
bool SetNoncePrefix(base::StringPiece nonce_prefix) override;
- bool DecryptPacket(QuicPacketNumber packet_number,
- const base::StringPiece& associated_data,
- const base::StringPiece& ciphertext,
+ bool DecryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
+ base::StringPiece associated_data,
+ base::StringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) override;
@@ -64,7 +65,7 @@ class NET_EXPORT_PRIVATE AeadBaseDecrypter : public QuicDecrypter {
};
virtual void FillAeadParams(base::StringPiece nonce,
- const base::StringPiece& associated_data,
+ base::StringPiece associated_data,
size_t auth_tag_size,
AeadParams* aead_params) const = 0;
#endif // !defined(USE_OPENSSL)
diff --git a/chromium/net/quic/crypto/aead_base_decrypter_nss.cc b/chromium/net/quic/crypto/aead_base_decrypter_nss.cc
index 9036681a1d6..47878609c09 100644
--- a/chromium/net/quic/crypto/aead_base_decrypter_nss.cc
+++ b/chromium/net/quic/crypto/aead_base_decrypter_nss.cc
@@ -8,6 +8,8 @@
#include "base/memory/scoped_ptr.h"
#include "crypto/scoped_nss_types.h"
+#include "net/quic/quic_flags.h"
+#include "net/quic/quic_utils.h"
using base::StringPiece;
@@ -45,9 +47,10 @@ bool AeadBaseDecrypter::SetNoncePrefix(StringPiece nonce_prefix) {
return true;
}
-bool AeadBaseDecrypter::DecryptPacket(QuicPacketNumber packet_number,
- const StringPiece& associated_data,
- const StringPiece& ciphertext,
+bool AeadBaseDecrypter::DecryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
+ StringPiece associated_data,
+ StringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) {
@@ -59,7 +62,10 @@ bool AeadBaseDecrypter::DecryptPacket(QuicPacketNumber packet_number,
const size_t nonce_size = nonce_prefix_size_ + sizeof(packet_number);
DCHECK_LE(nonce_size, sizeof(nonce));
memcpy(nonce, nonce_prefix_, nonce_prefix_size_);
- memcpy(nonce + nonce_prefix_size_, &packet_number, sizeof(packet_number));
+ uint64_t path_id_packet_number =
+ QuicUtils::PackPathIdAndPacketNumber(path_id, packet_number);
+ memcpy(nonce + nonce_prefix_size_, &path_id_packet_number,
+ sizeof(path_id_packet_number));
// NSS 3.14.x incorrectly requires an output buffer at least as long as
// the ciphertext (NSS bug
diff --git a/chromium/net/quic/crypto/aead_base_decrypter_openssl.cc b/chromium/net/quic/crypto/aead_base_decrypter_openssl.cc
index 3a4e4648fa8..cb91a6906d6 100644
--- a/chromium/net/quic/crypto/aead_base_decrypter_openssl.cc
+++ b/chromium/net/quic/crypto/aead_base_decrypter_openssl.cc
@@ -8,6 +8,8 @@
#include <openssl/evp.h>
#include "base/memory/scoped_ptr.h"
+#include "net/quic/quic_flags.h"
+#include "net/quic/quic_utils.h"
using base::StringPiece;
@@ -77,9 +79,10 @@ bool AeadBaseDecrypter::SetNoncePrefix(StringPiece nonce_prefix) {
return true;
}
-bool AeadBaseDecrypter::DecryptPacket(QuicPacketNumber packet_number,
- const StringPiece& associated_data,
- const StringPiece& ciphertext,
+bool AeadBaseDecrypter::DecryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
+ StringPiece associated_data,
+ StringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) {
@@ -90,7 +93,10 @@ bool AeadBaseDecrypter::DecryptPacket(QuicPacketNumber packet_number,
uint8_t nonce[sizeof(nonce_prefix_) + sizeof(packet_number)];
const size_t nonce_size = nonce_prefix_size_ + sizeof(packet_number);
memcpy(nonce, nonce_prefix_, nonce_prefix_size_);
- memcpy(nonce + nonce_prefix_size_, &packet_number, sizeof(packet_number));
+ uint64_t path_id_packet_number =
+ QuicUtils::PackPathIdAndPacketNumber(path_id, packet_number);
+ memcpy(nonce + nonce_prefix_size_, &path_id_packet_number,
+ sizeof(path_id_packet_number));
if (!EVP_AEAD_CTX_open(
ctx_.get(), reinterpret_cast<uint8_t*>(output), output_length,
max_output_length, reinterpret_cast<const uint8_t*>(nonce),
diff --git a/chromium/net/quic/crypto/aead_base_encrypter.h b/chromium/net/quic/crypto/aead_base_encrypter.h
index 74219d67546..333018997bc 100644
--- a/chromium/net/quic/crypto/aead_base_encrypter.h
+++ b/chromium/net/quic/crypto/aead_base_encrypter.h
@@ -38,7 +38,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(QuicPacketNumber packet_number,
+ bool EncryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
base::StringPiece associated_data,
base::StringPiece plaintext,
char* output,
diff --git a/chromium/net/quic/crypto/aead_base_encrypter_nss.cc b/chromium/net/quic/crypto/aead_base_encrypter_nss.cc
index b586a1d3301..4fb1349d548 100644
--- a/chromium/net/quic/crypto/aead_base_encrypter_nss.cc
+++ b/chromium/net/quic/crypto/aead_base_encrypter_nss.cc
@@ -8,6 +8,8 @@
#include "base/memory/scoped_ptr.h"
#include "crypto/scoped_nss_types.h"
+#include "net/quic/quic_flags.h"
+#include "net/quic/quic_utils.h"
using base::StringPiece;
@@ -117,7 +119,8 @@ bool AeadBaseEncrypter::Encrypt(StringPiece nonce,
return true;
}
-bool AeadBaseEncrypter::EncryptPacket(QuicPacketNumber packet_number,
+bool AeadBaseEncrypter::EncryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
StringPiece associated_data,
StringPiece plaintext,
char* output,
@@ -132,8 +135,10 @@ bool AeadBaseEncrypter::EncryptPacket(QuicPacketNumber packet_number,
const size_t nonce_size = nonce_prefix_size_ + sizeof(packet_number);
ALIGNAS(4) char nonce_buffer[kMaxNonceSize];
memcpy(nonce_buffer, nonce_prefix_, nonce_prefix_size_);
- memcpy(nonce_buffer + nonce_prefix_size_, &packet_number,
- sizeof(packet_number));
+ uint64_t path_id_packet_number =
+ QuicUtils::PackPathIdAndPacketNumber(path_id, packet_number);
+ memcpy(nonce_buffer + nonce_prefix_size_, &path_id_packet_number,
+ sizeof(path_id_packet_number));
if (!Encrypt(StringPiece(nonce_buffer, nonce_size), associated_data,
plaintext, reinterpret_cast<unsigned char*>(output))) {
return false;
diff --git a/chromium/net/quic/crypto/aead_base_encrypter_openssl.cc b/chromium/net/quic/crypto/aead_base_encrypter_openssl.cc
index 2408cecc955..92856a6c070 100644
--- a/chromium/net/quic/crypto/aead_base_encrypter_openssl.cc
+++ b/chromium/net/quic/crypto/aead_base_encrypter_openssl.cc
@@ -9,6 +9,8 @@
#include <string.h>
#include "base/memory/scoped_ptr.h"
+#include "net/quic/quic_flags.h"
+#include "net/quic/quic_utils.h"
using base::StringPiece;
@@ -102,7 +104,8 @@ bool AeadBaseEncrypter::Encrypt(StringPiece nonce,
return true;
}
-bool AeadBaseEncrypter::EncryptPacket(QuicPacketNumber packet_number,
+bool AeadBaseEncrypter::EncryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
StringPiece associated_data,
StringPiece plaintext,
char* output,
@@ -117,8 +120,11 @@ bool AeadBaseEncrypter::EncryptPacket(QuicPacketNumber packet_number,
const size_t nonce_size = nonce_prefix_size_ + sizeof(packet_number);
ALIGNAS(4) char nonce_buffer[kMaxNonceSize];
memcpy(nonce_buffer, nonce_prefix_, nonce_prefix_size_);
- memcpy(nonce_buffer + nonce_prefix_size_, &packet_number,
- sizeof(packet_number));
+ uint64_t path_id_packet_number =
+ QuicUtils::PackPathIdAndPacketNumber(path_id, packet_number);
+ memcpy(nonce_buffer + nonce_prefix_size_, &path_id_packet_number,
+ sizeof(path_id_packet_number));
+
if (!Encrypt(StringPiece(nonce_buffer, nonce_size), associated_data,
plaintext, reinterpret_cast<unsigned char*>(output))) {
return false;
diff --git a/chromium/net/quic/crypto/aes_128_gcm_12_decrypter.h b/chromium/net/quic/crypto/aes_128_gcm_12_decrypter.h
index d0d305ab3d5..f8b1196f465 100644
--- a/chromium/net/quic/crypto/aes_128_gcm_12_decrypter.h
+++ b/chromium/net/quic/crypto/aes_128_gcm_12_decrypter.h
@@ -33,7 +33,7 @@ class NET_EXPORT_PRIVATE Aes128Gcm12Decrypter : public AeadBaseDecrypter {
protected:
// AeadBaseDecrypter methods:
void FillAeadParams(base::StringPiece nonce,
- const base::StringPiece& associated_data,
+ base::StringPiece associated_data,
size_t auth_tag_size,
AeadParams* aead_params) const override;
#endif
diff --git a/chromium/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc b/chromium/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc
index abbc5658672..d4480f49b2c 100644
--- a/chromium/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc
+++ b/chromium/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc
@@ -28,7 +28,7 @@ Aes128Gcm12Decrypter::Aes128Gcm12Decrypter()
Aes128Gcm12Decrypter::~Aes128Gcm12Decrypter() {}
void Aes128Gcm12Decrypter::FillAeadParams(StringPiece nonce,
- const StringPiece& associated_data,
+ StringPiece associated_data,
size_t auth_tag_size,
AeadParams* aead_params) const {
aead_params->len = sizeof(aead_params->data.gcm_params);
diff --git a/chromium/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc b/chromium/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc
index 27afc290ec7..d0e5304e977 100644
--- a/chromium/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc
+++ b/chromium/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc
@@ -4,6 +4,7 @@
#include "net/quic/crypto/aes_128_gcm_12_decrypter.h"
+#include "net/quic/quic_flags.h"
#include "net/quic/test_tools/quic_test_utils.h"
using base::StringPiece;
@@ -199,16 +200,20 @@ QuicData* DecryptWithNonce(Aes128Gcm12Decrypter* decrypter,
StringPiece nonce,
StringPiece associated_data,
StringPiece ciphertext) {
+ QuicPathId path_id = kDefaultPathId;
QuicPacketNumber packet_number;
StringPiece nonce_prefix(nonce.data(), nonce.size() - sizeof(packet_number));
decrypter->SetNoncePrefix(nonce_prefix);
memcpy(&packet_number, nonce.data() + nonce_prefix.size(),
sizeof(packet_number));
+ path_id = static_cast<QuicPathId>(
+ packet_number >> 8 * (sizeof(packet_number) - sizeof(path_id)));
+ packet_number &= UINT64_C(0x00FFFFFFFFFFFFFF);
scoped_ptr<char[]> output(new char[ciphertext.length()]);
size_t output_length = 0;
const bool success = decrypter->DecryptPacket(
- packet_number, associated_data, ciphertext, output.get(), &output_length,
- ciphertext.length());
+ path_id, packet_number, associated_data, ciphertext, output.get(),
+ &output_length, ciphertext.length());
if (!success) {
return nullptr;
}
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_decrypter.h b/chromium/net/quic/crypto/chacha20_poly1305_decrypter.h
index fad9bbbe5fb..1e0fd05f2c5 100644
--- a/chromium/net/quic/crypto/chacha20_poly1305_decrypter.h
+++ b/chromium/net/quic/crypto/chacha20_poly1305_decrypter.h
@@ -34,7 +34,7 @@ class NET_EXPORT_PRIVATE ChaCha20Poly1305Decrypter : public AeadBaseDecrypter {
protected:
// AeadBaseDecrypter methods:
void FillAeadParams(base::StringPiece nonce,
- const base::StringPiece& associated_data,
+ base::StringPiece associated_data,
size_t auth_tag_size,
AeadParams* aead_params) const override;
#endif
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc b/chromium/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc
deleted file mode 100644
index 893f8a7cdb8..00000000000
--- a/chromium/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2014 The Chromium 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/crypto/chacha20_poly1305_decrypter.h"
-
-#include <pk11pub.h>
-
-using base::StringPiece;
-
-namespace net {
-
-namespace {
-
-const size_t kKeySize = 32;
-const size_t kNoncePrefixSize = 0;
-
-} // namespace
-
-ChaCha20Poly1305Decrypter::ChaCha20Poly1305Decrypter()
- : AeadBaseDecrypter(CKM_NSS_CHACHA20_POLY1305,
- kKeySize,
- kAuthTagSize,
- kNoncePrefixSize) {
- static_assert(kKeySize <= kMaxKeySize, "key size too big");
- static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
- "nonce prefix size too big");
-}
-
-ChaCha20Poly1305Decrypter::~ChaCha20Poly1305Decrypter() {}
-
-void ChaCha20Poly1305Decrypter::FillAeadParams(
- StringPiece nonce,
- const StringPiece& associated_data,
- size_t auth_tag_size,
- AeadParams* aead_params) const {
- aead_params->len = sizeof(aead_params->data.nss_aead_params);
- CK_NSS_AEAD_PARAMS* nss_aead_params = &aead_params->data.nss_aead_params;
- nss_aead_params->pIv =
- reinterpret_cast<CK_BYTE*>(const_cast<char*>(nonce.data()));
- nss_aead_params->ulIvLen = nonce.size();
- nss_aead_params->pAAD =
- reinterpret_cast<CK_BYTE*>(const_cast<char*>(associated_data.data()));
- nss_aead_params->ulAADLen = associated_data.size();
- nss_aead_params->ulTagLen = auth_tag_size;
-}
-
-const char* ChaCha20Poly1305Decrypter::cipher_name() const {
- // TODO(rtenneti): Use TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 instead of
- // hard coded string.
- // return TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305;
- return "ECDHE-RSA-CHACHA20-POLY1305";
-}
-
-uint32_t ChaCha20Poly1305Decrypter::cipher_id() const {
- // TODO(rtenneti): when Chromium requires NSS 3.15.2 or later, use
- // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 instead of 0xCC13.
- // "OR" 0x03000000 to match OpenSSL/BoringSSL implementations.
- return 0x03000000 | 0xCC13;
-}
-
-} // namespace net
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_decrypter_openssl.cc b/chromium/net/quic/crypto/chacha20_poly1305_decrypter_openssl.cc
deleted file mode 100644
index 683f13b763e..00000000000
--- a/chromium/net/quic/crypto/chacha20_poly1305_decrypter_openssl.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2014 The Chromium 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/crypto/chacha20_poly1305_decrypter.h"
-
-#include <openssl/evp.h>
-#include <openssl/tls1.h>
-
-namespace net {
-
-namespace {
-
-const size_t kKeySize = 32;
-const size_t kNoncePrefixSize = 0;
-
-} // namespace
-
-// QUIC currently uses the draft-agl-tls-chacha20poly1305-04 ChaCha20-Poly1305
-// construction rather than RFC 7539.
-ChaCha20Poly1305Decrypter::ChaCha20Poly1305Decrypter()
- : AeadBaseDecrypter(EVP_aead_chacha20_poly1305_old(),
- kKeySize,
- kAuthTagSize,
- kNoncePrefixSize) {
- static_assert(kKeySize <= kMaxKeySize, "key size too big");
- static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
- "nonce prefix size too big");
-}
-
-ChaCha20Poly1305Decrypter::~ChaCha20Poly1305Decrypter() {}
-
-const char* ChaCha20Poly1305Decrypter::cipher_name() const {
- return TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_OLD;
-}
-
-uint32_t ChaCha20Poly1305Decrypter::cipher_id() const {
- return TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD;
-}
-
-} // namespace net
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_decrypter_test.cc b/chromium/net/quic/crypto/chacha20_poly1305_decrypter_test.cc
deleted file mode 100644
index 665595dd7f5..00000000000
--- a/chromium/net/quic/crypto/chacha20_poly1305_decrypter_test.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2014 The Chromium 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/crypto/chacha20_poly1305_decrypter.h"
-
-#include "net/quic/test_tools/quic_test_utils.h"
-
-using base::StringPiece;
-using std::string;
-
-namespace {
-
-// The test vectors come from draft-agl-tls-chacha20poly1305-04 Section 7.
-
-// Each test vector consists of six strings of lowercase hexadecimal digits.
-// The strings may be empty (zero length). A test vector with a nullptr |key|
-// marks the end of an array of test vectors.
-struct TestVector {
- // Input:
- const char* key;
- const char* iv;
- const char* aad;
- const char* ct;
-
- // Expected output:
- const char* pt; // An empty string "" means decryption succeeded and
- // the plaintext is zero-length. NULL means decryption
- // failed.
-};
-
-const TestVector test_vectors[] = {
- {"4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd110"
- "0a1007",
- "cd7cf67be39c794a", "87e229d4500845a079c0",
- "e3e446f7ede9a19b62a4677dabf4e3d24b876bb28475", // "3896e1d6" truncated.
- "86d09974840bded2a5ca"},
- // Modify the ciphertext (ChaCha20 encryption output).
- {
- "4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd110"
- "0a1007",
- "cd7cf67be39c794a", "87e229d4500845a079c0",
- "f3e446f7ede9a19b62a4677dabf4e3d24b876bb28475", // "3896e1d6"
- // truncated.
- nullptr // FAIL
- },
- // Modify the ciphertext (Poly1305 authenticator).
- {
- "4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd110"
- "0a1007",
- "cd7cf67be39c794a", "87e229d4500845a079c0",
- "e3e446f7ede9a19b62a4677dabf4e3d24b876bb28476", // "3896e1d6"
- // truncated.
- nullptr // FAIL
- },
- // Modify the associated data.
- {
- "4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd110"
- "0a1007",
- "dd7cf67be39c794a", "87e229d4500845a079c0",
- "e3e446f7ede9a19b62a4677dabf4e3d24b876bb28475", // "3896e1d6"
- // truncated.
- nullptr // FAIL
- },
- {nullptr}};
-
-} // namespace
-
-namespace net {
-namespace test {
-
-// DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing
-// in an nonce and also to allocate the buffer needed for the plaintext.
-QuicData* DecryptWithNonce(ChaCha20Poly1305Decrypter* decrypter,
- StringPiece nonce,
- StringPiece associated_data,
- StringPiece ciphertext) {
- QuicPacketNumber packet_number;
- StringPiece nonce_prefix(nonce.data(), nonce.size() - sizeof(packet_number));
- decrypter->SetNoncePrefix(nonce_prefix);
- memcpy(&packet_number, nonce.data() + nonce_prefix.size(),
- sizeof(packet_number));
- scoped_ptr<char[]> output(new char[ciphertext.length()]);
- size_t output_length = 0;
- const bool success = decrypter->DecryptPacket(
- packet_number, associated_data, ciphertext, output.get(), &output_length,
- ciphertext.length());
- if (!success) {
- return nullptr;
- }
- return new QuicData(output.release(), output_length, true);
-}
-
-TEST(ChaCha20Poly1305DecrypterTest, Decrypt) {
- for (size_t i = 0; test_vectors[i].key != nullptr; i++) {
- // If not present then decryption is expected to fail.
- bool has_pt = test_vectors[i].pt;
-
- // Decode the test vector.
- string key;
- string iv;
- string aad;
- string ct;
- string pt;
- ASSERT_TRUE(DecodeHexString(test_vectors[i].key, &key));
- ASSERT_TRUE(DecodeHexString(test_vectors[i].iv, &iv));
- ASSERT_TRUE(DecodeHexString(test_vectors[i].aad, &aad));
- ASSERT_TRUE(DecodeHexString(test_vectors[i].ct, &ct));
- if (has_pt) {
- ASSERT_TRUE(DecodeHexString(test_vectors[i].pt, &pt));
- }
-
- ChaCha20Poly1305Decrypter decrypter;
- ASSERT_TRUE(decrypter.SetKey(key));
- scoped_ptr<QuicData> decrypted(DecryptWithNonce(
- &decrypter, iv,
- // This deliberately tests that the decrypter can handle an AAD that
- // is set to nullptr, as opposed to a zero-length, non-nullptr pointer.
- StringPiece(aad.length() ? aad.data() : nullptr, aad.length()), ct));
- if (!decrypted.get()) {
- EXPECT_FALSE(has_pt);
- continue;
- }
- EXPECT_TRUE(has_pt);
-
- ASSERT_EQ(pt.length(), decrypted->length());
- test::CompareCharArraysWithHexError("plaintext", decrypted->data(),
- pt.length(), pt.data(), pt.length());
- }
-}
-
-} // namespace test
-} // namespace net
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_encrypter_nss.cc b/chromium/net/quic/crypto/chacha20_poly1305_encrypter_nss.cc
deleted file mode 100644
index 9b0e9bfb3d8..00000000000
--- a/chromium/net/quic/crypto/chacha20_poly1305_encrypter_nss.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2014 The Chromium 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/crypto/chacha20_poly1305_encrypter.h"
-
-#include <pk11pub.h>
-
-using base::StringPiece;
-
-namespace net {
-
-namespace {
-
-const size_t kKeySize = 32;
-const size_t kNoncePrefixSize = 0;
-
-} // namespace
-
-ChaCha20Poly1305Encrypter::ChaCha20Poly1305Encrypter()
- : AeadBaseEncrypter(CKM_NSS_CHACHA20_POLY1305,
- kKeySize,
- kAuthTagSize,
- kNoncePrefixSize) {
- static_assert(kKeySize <= kMaxKeySize, "key size too big");
- static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
- "nonce prefix size too big");
-}
-
-ChaCha20Poly1305Encrypter::~ChaCha20Poly1305Encrypter() {}
-
-void ChaCha20Poly1305Encrypter::FillAeadParams(StringPiece nonce,
- StringPiece associated_data,
- size_t auth_tag_size,
- AeadParams* aead_params) const {
- aead_params->len = sizeof(aead_params->data.nss_aead_params);
- CK_NSS_AEAD_PARAMS* nss_aead_params = &aead_params->data.nss_aead_params;
- nss_aead_params->pIv =
- reinterpret_cast<CK_BYTE*>(const_cast<char*>(nonce.data()));
- nss_aead_params->ulIvLen = nonce.size();
- nss_aead_params->pAAD =
- reinterpret_cast<CK_BYTE*>(const_cast<char*>(associated_data.data()));
- nss_aead_params->ulAADLen = associated_data.size();
- nss_aead_params->ulTagLen = auth_tag_size;
-}
-
-} // namespace net
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_encrypter_openssl.cc b/chromium/net/quic/crypto/chacha20_poly1305_encrypter_openssl.cc
deleted file mode 100644
index 9a75eec135f..00000000000
--- a/chromium/net/quic/crypto/chacha20_poly1305_encrypter_openssl.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 The Chromium 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/crypto/chacha20_poly1305_encrypter.h"
-
-#include <openssl/evp.h>
-
-namespace net {
-
-namespace {
-
-const size_t kKeySize = 32;
-const size_t kNoncePrefixSize = 0;
-
-} // namespace
-
-// QUIC currently uses the draft-agl-tls-chacha20poly1305-04 ChaCha20-Poly1305
-// construction rather than RFC 7539.
-ChaCha20Poly1305Encrypter::ChaCha20Poly1305Encrypter()
- : AeadBaseEncrypter(EVP_aead_chacha20_poly1305_old(),
- kKeySize,
- kAuthTagSize,
- kNoncePrefixSize) {
- static_assert(kKeySize <= kMaxKeySize, "key size too big");
- static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
- "nonce prefix size too big");
-}
-
-ChaCha20Poly1305Encrypter::~ChaCha20Poly1305Encrypter() {}
-
-} // namespace net
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_encrypter_test.cc b/chromium/net/quic/crypto/chacha20_poly1305_encrypter_test.cc
deleted file mode 100644
index 0c4918208e1..00000000000
--- a/chromium/net/quic/crypto/chacha20_poly1305_encrypter_test.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2014 The Chromium 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/crypto/chacha20_poly1305_encrypter.h"
-
-#include "net/quic/test_tools/quic_test_utils.h"
-
-using base::StringPiece;
-using std::string;
-
-namespace {
-
-// The test vectors come from draft-agl-tls-chacha20poly1305-04 Section 7.
-
-// Each test vector consists of five strings of lowercase hexadecimal digits.
-// The strings may be empty (zero length). A test vector with a nullptr |key|
-// marks the end of an array of test vectors.
-struct TestVector {
- const char* key;
- const char* pt;
- const char* iv;
- const char* aad;
- const char* ct;
-};
-
-const TestVector test_vectors[] = {
- {
- "4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd110"
- "0a1007",
- "86d09974840bded2a5ca", "cd7cf67be39c794a", "87e229d4500845a079c0",
- "e3e446f7ede9a19b62a4677dabf4e3d24b876bb28475" // "3896e1d6" truncated.
- },
- {nullptr}};
-
-} // namespace
-
-namespace net {
-namespace test {
-
-// EncryptWithNonce wraps the |Encrypt| method of |encrypter| to allow passing
-// in an nonce and also to allocate the buffer needed for the ciphertext.
-QuicData* EncryptWithNonce(ChaCha20Poly1305Encrypter* encrypter,
- StringPiece nonce,
- StringPiece associated_data,
- StringPiece plaintext) {
- size_t ciphertext_size = encrypter->GetCiphertextSize(plaintext.length());
- scoped_ptr<char[]> ciphertext(new char[ciphertext_size]);
-
- if (!encrypter->Encrypt(nonce, associated_data, plaintext,
- reinterpret_cast<unsigned char*>(ciphertext.get()))) {
- return nullptr;
- }
-
- return new QuicData(ciphertext.release(), ciphertext_size, true);
-}
-
-TEST(ChaCha20Poly1305EncrypterTest, Encrypt) {
- for (size_t i = 0; test_vectors[i].key != nullptr; i++) {
- // Decode the test vector.
- string key;
- string pt;
- string iv;
- string aad;
- string ct;
- ASSERT_TRUE(DecodeHexString(test_vectors[i].key, &key));
- ASSERT_TRUE(DecodeHexString(test_vectors[i].pt, &pt));
- ASSERT_TRUE(DecodeHexString(test_vectors[i].iv, &iv));
- ASSERT_TRUE(DecodeHexString(test_vectors[i].aad, &aad));
- ASSERT_TRUE(DecodeHexString(test_vectors[i].ct, &ct));
-
- ChaCha20Poly1305Encrypter encrypter;
- ASSERT_TRUE(encrypter.SetKey(key));
- scoped_ptr<QuicData> encrypted(EncryptWithNonce(
- &encrypter, iv,
- // This deliberately tests that the encrypter can handle an AAD that
- // is set to nullptr, as opposed to a zero-length, non-nullptr pointer.
- StringPiece(aad.length() ? aad.data() : nullptr, aad.length()), pt));
- ASSERT_TRUE(encrypted.get());
-
- test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
- encrypted->length(), ct.data(),
- ct.length());
- }
-}
-
-TEST(ChaCha20Poly1305EncrypterTest, GetMaxPlaintextSize) {
- ChaCha20Poly1305Encrypter encrypter;
- EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1012));
- EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(112));
- EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(22));
-}
-
-TEST(ChaCha20Poly1305EncrypterTest, GetCiphertextSize) {
- ChaCha20Poly1305Encrypter encrypter;
- EXPECT_EQ(1012u, encrypter.GetCiphertextSize(1000));
- EXPECT_EQ(112u, encrypter.GetCiphertextSize(100));
- EXPECT_EQ(22u, encrypter.GetCiphertextSize(10));
-}
-
-} // namespace test
-} // namespace net
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h b/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h
index 3889216226a..57609d09da1 100644
--- a/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h
+++ b/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h
@@ -42,7 +42,7 @@ class NET_EXPORT_PRIVATE ChaCha20Poly1305Rfc7539Decrypter
protected:
// AeadBaseDecrypter methods:
void FillAeadParams(base::StringPiece nonce,
- const base::StringPiece& associated_data,
+ base::StringPiece associated_data,
size_t auth_tag_size,
AeadParams* aead_params) const override;
#endif
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc b/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc
index 8c830e93c60..799a2c5a545 100644
--- a/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc
+++ b/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc
@@ -43,7 +43,7 @@ uint32_t ChaCha20Poly1305Rfc7539Decrypter::cipher_id() const {
void ChaCha20Poly1305Rfc7539Decrypter::FillAeadParams(
base::StringPiece nonce,
- const base::StringPiece& associated_data,
+ base::StringPiece associated_data,
size_t auth_tag_size,
AeadParams* aead_params) const {}
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_openssl.cc b/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_openssl.cc
index 2c85aa2a9a6..9a1aa4c8249 100644
--- a/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_openssl.cc
+++ b/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_openssl.cc
@@ -17,7 +17,7 @@ const size_t kNoncePrefixSize = 4;
} // namespace
ChaCha20Poly1305Rfc7539Decrypter::ChaCha20Poly1305Rfc7539Decrypter()
- : AeadBaseDecrypter(EVP_aead_chacha20_poly1305_rfc7539(),
+ : AeadBaseDecrypter(EVP_aead_chacha20_poly1305(),
kKeySize,
kAuthTagSize,
kNoncePrefixSize) {
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_test.cc b/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_test.cc
index 0cee4b407b8..3acc1fcb518 100644
--- a/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_test.cc
+++ b/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_test.cc
@@ -4,6 +4,7 @@
#include "net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h"
+#include "net/quic/quic_flags.h"
#include "net/quic/test_tools/quic_test_utils.h"
using base::StringPiece;
@@ -113,16 +114,20 @@ QuicData* DecryptWithNonce(ChaCha20Poly1305Rfc7539Decrypter* decrypter,
StringPiece nonce,
StringPiece associated_data,
StringPiece ciphertext) {
+ QuicPathId path_id = kDefaultPathId;
QuicPacketNumber packet_number;
StringPiece nonce_prefix(nonce.data(), nonce.size() - sizeof(packet_number));
decrypter->SetNoncePrefix(nonce_prefix);
memcpy(&packet_number, nonce.data() + nonce_prefix.size(),
sizeof(packet_number));
+ path_id = static_cast<QuicPathId>(
+ packet_number >> 8 * (sizeof(packet_number) - sizeof(path_id)));
+ packet_number &= UINT64_C(0x00FFFFFFFFFFFFFF);
scoped_ptr<char[]> output(new char[ciphertext.length()]);
size_t output_length = 0;
const bool success = decrypter->DecryptPacket(
- packet_number, associated_data, ciphertext, output.get(), &output_length,
- ciphertext.length());
+ path_id, packet_number, associated_data, ciphertext, output.get(),
+ &output_length, ciphertext.length());
if (!success) {
return nullptr;
}
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_openssl.cc b/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_openssl.cc
index 6912f9256e0..a2219ae5fa9 100644
--- a/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_openssl.cc
+++ b/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_openssl.cc
@@ -16,7 +16,7 @@ const size_t kNoncePrefixSize = 4;
} // namespace
ChaCha20Poly1305Rfc7539Encrypter::ChaCha20Poly1305Rfc7539Encrypter()
- : AeadBaseEncrypter(EVP_aead_chacha20_poly1305_rfc7539(),
+ : AeadBaseEncrypter(EVP_aead_chacha20_poly1305(),
kKeySize,
kAuthTagSize,
kNoncePrefixSize) {
diff --git a/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_test.cc b/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_test.cc
index 1654ea35a96..9e246f95c1c 100644
--- a/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_test.cc
+++ b/chromium/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_test.cc
@@ -98,16 +98,18 @@ TEST(ChaCha20Poly1305Rfc7539EncrypterTest, EncryptThenDecrypt) {
ASSERT_TRUE(encrypter.SetNoncePrefix("abcd"));
ASSERT_TRUE(decrypter.SetNoncePrefix("abcd"));
+ QuicPathId path_id = 0x42;
QuicPacketNumber packet_number = UINT64_C(0x123456789ABC);
string associated_data = "associated_data";
string plaintext = "plaintext";
char encrypted[1024];
size_t len;
- ASSERT_TRUE(encrypter.EncryptPacket(packet_number, associated_data, plaintext,
- encrypted, &len, arraysize(encrypted)));
+ ASSERT_TRUE(encrypter.EncryptPacket(path_id, packet_number, associated_data,
+ plaintext, encrypted, &len,
+ arraysize(encrypted)));
StringPiece ciphertext(encrypted, len);
char decrypted[1024];
- ASSERT_TRUE(decrypter.DecryptPacket(packet_number, associated_data,
+ ASSERT_TRUE(decrypter.DecryptPacket(path_id, packet_number, associated_data,
ciphertext, decrypted, &len,
arraysize(decrypted)));
}
diff --git a/chromium/net/quic/crypto/channel_id_chromium.cc b/chromium/net/quic/crypto/channel_id_chromium.cc
index 3f50b768302..1aec7e7b8a0 100644
--- a/chromium/net/quic/crypto/channel_id_chromium.cc
+++ b/chromium/net/quic/crypto/channel_id_chromium.cc
@@ -190,14 +190,9 @@ int ChannelIDSourceChromium::Job::DoGetChannelIDKeyComplete(int result) {
return result;
}
- if (!channel_id_crypto_key_) {
- // TODO(wtc): use the new error code ERR_CHANNEL_ID_IMPORT_FAILED to be
- // added in https://codereview.chromium.org/338093012/.
- return ERR_UNEXPECTED;
- }
+ DCHECK(channel_id_crypto_key_);
channel_id_key_.reset(
new ChannelIDKeyChromium(std::move(channel_id_crypto_key_)));
-
return result;
}
diff --git a/chromium/net/quic/crypto/common_cert_set.cc b/chromium/net/quic/crypto/common_cert_set.cc
index b771fa002f6..b469b68a7f7 100644
--- a/chromium/net/quic/crypto/common_cert_set.cc
+++ b/chromium/net/quic/crypto/common_cert_set.cc
@@ -4,6 +4,8 @@
#include "net/quic/crypto/common_cert_set.h"
+#include <cstddef>
+
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
diff --git a/chromium/net/quic/crypto/common_cert_set.h b/chromium/net/quic/crypto/common_cert_set.h
index b4fbfac0a11..6d152054cc4 100644
--- a/chromium/net/quic/crypto/common_cert_set.h
+++ b/chromium/net/quic/crypto/common_cert_set.h
@@ -5,7 +5,7 @@
#ifndef NET_QUIC_CRYPTO_COMMON_CERT_SET_H_
#define NET_QUIC_CRYPTO_COMMON_CERT_SET_H_
-#include <stdint.h>
+#include <cstdint>
#include "base/compiler_specific.h"
#include "base/strings/string_piece.h"
diff --git a/chromium/net/quic/crypto/crypto_handshake.cc b/chromium/net/quic/crypto/crypto_handshake.cc
index afe599160f0..23f64afdb4a 100644
--- a/chromium/net/quic/crypto/crypto_handshake.cc
+++ b/chromium/net/quic/crypto/crypto_handshake.cc
@@ -21,9 +21,6 @@ QuicCryptoNegotiatedParameters::QuicCryptoNegotiatedParameters()
QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() {}
-QuicCryptoProof::QuicCryptoProof() : certs(nullptr) {}
-QuicCryptoProof::~QuicCryptoProof() {}
-
CrypterPair::CrypterPair() {}
CrypterPair::~CrypterPair() {}
diff --git a/chromium/net/quic/crypto/crypto_handshake.h b/chromium/net/quic/crypto/crypto_handshake.h
index 71792bac58a..d9d51e315cc 100644
--- a/chromium/net/quic/crypto/crypto_handshake.h
+++ b/chromium/net/quic/crypto/crypto_handshake.h
@@ -87,8 +87,7 @@ enum HandshakeFailureReason {
};
// These errors will be packed into an uint32_t and we don't want to set the
-// most
-// significant bit, which may be misinterpreted as the sign bit.
+// most significant bit, which may be misinterpreted as the sign bit.
static_assert(MAX_FAILURE_REASON <= 32, "failure reason out of sync");
// A CrypterPair contains the encrypter and decrypter for an encryption level.
@@ -109,6 +108,10 @@ struct NET_EXPORT_PRIVATE QuicCryptoNegotiatedParameters {
QuicTag aead;
std::string initial_premaster_secret;
std::string forward_secure_premaster_secret;
+ // initial_subkey_secret is used as the PRK input to the HKDF used when
+ // performing key extraction that needs to happen before forward-secure keys
+ // are available.
+ std::string initial_subkey_secret;
// subkey_secret is used as the PRK input to the HKDF used for key extraction.
std::string subkey_secret;
CrypterPair initial_crypters;
@@ -148,18 +151,6 @@ struct NET_EXPORT_PRIVATE QuicCryptoNegotiatedParameters {
bool sct_supported_by_client;
};
-struct NET_EXPORT_PRIVATE QuicCryptoProof {
- QuicCryptoProof();
- ~QuicCryptoProof();
-
- std::string signature;
- // QuicCryptoProof does not take ownership of |certs|.
- const std::vector<std::string>* certs;
- std::string cert_sct;
- // The SCID of the server config whose signature is |signature|.
- std::string primary_scid;
-};
-
// QuicCryptoConfig contains common configuration between clients and servers.
class NET_EXPORT_PRIVATE QuicCryptoConfig {
public:
diff --git a/chromium/net/quic/crypto/crypto_handshake_message.cc b/chromium/net/quic/crypto/crypto_handshake_message.cc
index b81b4629c7b..5e4e48dd195 100644
--- a/chromium/net/quic/crypto/crypto_handshake_message.cc
+++ b/chromium/net/quic/crypto/crypto_handshake_message.cc
@@ -248,6 +248,15 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
done = true;
}
break;
+ case kRCID:
+ // uint64_t value
+ if (it->second.size() == 8) {
+ uint64_t value;
+ memcpy(&value, it->second.data(), sizeof(value));
+ ret += base::Uint64ToString(value);
+ done = true;
+ }
+ break;
case kTBKP:
case kKEXS:
case kAEAD:
diff --git a/chromium/net/quic/crypto/crypto_handshake_message_test.cc b/chromium/net/quic/crypto/crypto_handshake_message_test.cc
index 1bda50f0b2c..a4fae52946b 100644
--- a/chromium/net/quic/crypto/crypto_handshake_message_test.cc
+++ b/chromium/net/quic/crypto/crypto_handshake_message_test.cc
@@ -39,6 +39,13 @@ TEST(CryptoHandshakeMessageTest, DebugStringWithTagVector) {
EXPECT_EQ("CHLO<\n COPT: 'TBBR','PAD ','BYTE'\n>", message.DebugString());
}
+TEST(CryptoHandshakeMessageTest, ServerDesignatedConnectionId) {
+ CryptoHandshakeMessage message;
+ message.set_tag(kSREJ);
+ message.SetValue(kRCID, UINT64_C(18364758544493064720));
+ EXPECT_EQ("SREJ<\n RCID: 18364758544493064720\n>", message.DebugString());
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/crypto/crypto_protocol.h b/chromium/net/quic/crypto/crypto_protocol.h
index 1e0fcb963ea..532f80356ad 100644
--- a/chromium/net/quic/crypto/crypto_protocol.h
+++ b/chromium/net/quic/crypto/crypto_protocol.h
@@ -47,7 +47,6 @@ 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 kCC12 = TAG('C', 'C', '1', '2'); // ChaCha20 + Poly1305
const QuicTag kCC20 = TAG('C', 'C', '2', '0'); // ChaCha20 + Poly1305 RFC7539
// Socket receive buffer
@@ -89,7 +88,12 @@ const QuicTag kMIN4 = TAG('M', 'I', 'N', '4'); // Min CWND of 4 packets,
const QuicTag kTLPR = TAG('T', 'L', 'P', 'R'); // Tail loss probe delay of
// 0.5RTT.
const QuicTag kACKD = TAG('A', 'C', 'K', 'D'); // Ack decimation style acking.
+const QuicTag kAKD2 = TAG('A', 'K', 'D', '2'); // Ack decimation tolerating
+ // out of order packets.
const QuicTag kSSLR = TAG('S', 'S', 'L', 'R'); // Slow Start Large Reduction.
+const QuicTag k5RTO = TAG('5', 'R', 'T', 'O'); // Close connection on 5 RTOs
+const QuicTag kCTIM = TAG('C', 'T', 'I', 'M'); // Client timestamp in seconds
+ // since UNIX epoch.
// 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
@@ -99,14 +103,8 @@ const QuicTag kTCID = TAG('T', 'C', 'I', 'D'); // Connection ID truncation.
// Multipath option.
const QuicTag kMPTH = TAG('M', 'P', 'T', 'H'); // Enable multipath.
-// FEC options
-const QuicTag kFHDR = TAG('F', 'H', 'D', 'R'); // FEC protect headers
-const QuicTag kFSTR = TAG('F', 'S', 'T', 'R'); // FEC protect all streams
-// Set FecSendPolicy for sending FEC packet only when FEC alarm goes off.
-const QuicTag kFSPA = TAG('F', 'S', 'P', 'A');
-// Run an experiment that sets FecTimeOut alarm to 0.25RTT.
-// TODO(rtenneti): Delete it after the experiment.
-const QuicTag kFRTT = TAG('F', 'R', 'T', 'T');
+const QuicTag kNCMR = TAG('N', 'C', 'M', 'R'); // Do not attempt connection
+ // migration.
// Enable bandwidth resumption experiment.
const QuicTag kBWRE = TAG('B', 'W', 'R', 'E'); // Bandwidth resumption.
@@ -129,6 +127,7 @@ const QuicTag kCHID = TAG('C', 'H', 'I', 'D'); // Channel ID.
// Client hello tags
const QuicTag kVER = TAG('V', 'E', 'R', '\0'); // Version
const QuicTag kNONC = TAG('N', 'O', 'N', 'C'); // The client's nonce
+const QuicTag kNONP = TAG('N', 'O', 'N', 'P'); // The client's proof nonce
const QuicTag kKEXS = TAG('K', 'E', 'X', 'S'); // Key exchange methods
const QuicTag kAEAD = TAG('A', 'E', 'A', 'D'); // Authenticated
// encryption algorithms
@@ -212,7 +211,12 @@ const size_t kOrbitSize = 8; // Number of bytes in an orbit value.
// kProofSignatureLabel is prepended to server configs before signing to avoid
// any cross-protocol attacks on the signature.
-const char kProofSignatureLabel[] = "QUIC server config signature";
+// TODO(rch): Remove this when QUIC_VERSION_30 is removed.
+const char kProofSignatureLabelOld[] = "QUIC server config signature";
+
+// kProofSignatureLabel is prepended to the CHLO hash and server configs before
+// signing to avoid any cross-protocol attacks on the signature.
+const char kProofSignatureLabel[] = "QUIC CHLO and server config signature";
// kClientHelloMinimumSize is the minimum size of a client hello. Client hellos
// will have PAD tags added in order to ensure this minimum is met and client
diff --git a/chromium/net/quic/crypto/crypto_secret_boxer.cc b/chromium/net/quic/crypto/crypto_secret_boxer.cc
index 6a7eecbb56c..08a431745fd 100644
--- a/chromium/net/quic/crypto/crypto_secret_boxer.cc
+++ b/chromium/net/quic/crypto/crypto_secret_boxer.cc
@@ -15,6 +15,7 @@
using base::StringPiece;
using std::string;
+using std::vector;
namespace net {
@@ -34,21 +35,34 @@ static const size_t kKeySize = 16;
// It's not terrible, but it's not a "forget about it" margin.
static const size_t kBoxNonceSize = 12;
+CryptoSecretBoxer::CryptoSecretBoxer() {}
+
+CryptoSecretBoxer::~CryptoSecretBoxer() {}
+
// static
size_t CryptoSecretBoxer::GetKeySize() {
return kKeySize;
}
-void CryptoSecretBoxer::SetKey(StringPiece key) {
- DCHECK_EQ(kKeySize, key.size());
- key_ = key.as_string();
+void CryptoSecretBoxer::SetKeys(const vector<string>& keys) {
+ DCHECK(!keys.empty());
+ vector<string> copy = keys;
+ for (const string& key : keys) {
+ DCHECK_EQ(kKeySize, key.size());
+ }
+ base::AutoLock l(lock_);
+ keys_.swap(copy);
}
string CryptoSecretBoxer::Box(QuicRandom* rand, StringPiece plaintext) const {
scoped_ptr<Aes128Gcm12Encrypter> encrypter(new Aes128Gcm12Encrypter());
- if (!encrypter->SetKey(key_)) {
- DLOG(DFATAL) << "CryptoSecretBoxer's encrypter->SetKey failed.";
- return string();
+ {
+ base::AutoLock l(lock_);
+ DCHECK_EQ(kKeySize, keys_[0].size());
+ if (!encrypter->SetKey(keys_[0])) {
+ DLOG(DFATAL) << "CryptoSecretBoxer's encrypter->SetKey failed.";
+ return string();
+ }
}
size_t ciphertext_size = encrypter->GetCiphertextSize(plaintext.length());
@@ -86,17 +100,25 @@ bool CryptoSecretBoxer::Unbox(StringPiece ciphertext,
sizeof(packet_number));
scoped_ptr<Aes128Gcm12Decrypter> decrypter(new Aes128Gcm12Decrypter());
- if (!decrypter->SetKey(key_)) {
- DLOG(DFATAL) << "CryptoSecretBoxer's decrypter->SetKey failed.";
- return false;
- }
- decrypter->SetNoncePrefix(nonce_prefix);
char plaintext[kMaxPacketSize];
size_t plaintext_length = 0;
- const bool success = decrypter->DecryptPacket(
- packet_number, StringPiece() /* associated data */, ciphertext, plaintext,
- &plaintext_length, kMaxPacketSize);
- if (!success) {
+ bool ok = false;
+ {
+ base::AutoLock 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)) {
+ ok = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!ok) {
return false;
}
diff --git a/chromium/net/quic/crypto/crypto_secret_boxer.h b/chromium/net/quic/crypto/crypto_secret_boxer.h
index 266b34a5631..09ec23c3613 100644
--- a/chromium/net/quic/crypto/crypto_secret_boxer.h
+++ b/chromium/net/quic/crypto/crypto_secret_boxer.h
@@ -8,9 +8,11 @@
#include <stddef.h>
#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"
namespace net {
@@ -22,31 +24,37 @@ class QuicRandom;
// thread-safe.
class NET_EXPORT_PRIVATE CryptoSecretBoxer {
public:
- CryptoSecretBoxer() {}
+ CryptoSecretBoxer();
+ ~CryptoSecretBoxer();
// GetKeySize returns the number of bytes in a key.
static size_t GetKeySize();
- // SetKey sets the key for this object. This must be done before |Box| or
- // |Unbox| are called. |key| must be |GetKeySize()| bytes long.
- void SetKey(base::StringPiece key);
+ // SetKeys sets a std::list of encryption keys. The first key in the std::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.
+ void SetKeys(const std::vector<std::string>& keys);
// 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|.
+ // included, the result will be slightly larger than |plaintext|. The first
+ // key in the std::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
- // authenticates+decrypts it. If |ciphertext| is not authentic then it
- // returns false. Otherwise, |out_storage| is used to store the result and
- // |out| is set to point into |out_storage| and contains the original
- // plaintext.
+ // authenticates+decrypts it. If |ciphertext| cannot be decrypted with any of
+ // the supplied keys, the function returns false. Otherwise, |out_storage| is
+ // used to store the result and |out| is set to point into |out_storage| and
+ // contains the original plaintext.
bool Unbox(base::StringPiece ciphertext,
std::string* out_storage,
base::StringPiece* out) const;
private:
- std::string key_;
+ mutable base::Lock lock_;
+ // GUARDED_BY(lock_).
+ std::vector<std::string> keys_;
DISALLOW_COPY_AND_ASSIGN(CryptoSecretBoxer);
};
diff --git a/chromium/net/quic/crypto/crypto_secret_boxer_test.cc b/chromium/net/quic/crypto/crypto_secret_boxer_test.cc
index 185e0a70141..c73c581c6d4 100644
--- a/chromium/net/quic/crypto/crypto_secret_boxer_test.cc
+++ b/chromium/net/quic/crypto/crypto_secret_boxer_test.cc
@@ -16,12 +16,9 @@ namespace test {
TEST(CryptoSecretBoxerTest, BoxAndUnbox) {
StringPiece message("hello world");
- const size_t key_size = CryptoSecretBoxer::GetKeySize();
- scoped_ptr<uint8_t[]> key(new uint8_t[key_size]);
- memset(key.get(), 0x11, key_size);
CryptoSecretBoxer boxer;
- boxer.SetKey(StringPiece(reinterpret_cast<char*>(key.get()), key_size));
+ boxer.SetKeys({string(CryptoSecretBoxer::GetKeySize(), 0x11)});
const string box = boxer.Box(QuicRandom::GetInstance(), message);
@@ -38,5 +35,46 @@ TEST(CryptoSecretBoxerTest, BoxAndUnbox) {
&storage, &result));
}
+// Helper function to test whether one boxer can decode the output of another.
+static bool CanDecode(const CryptoSecretBoxer& decoder,
+ const CryptoSecretBoxer& encoder) {
+ StringPiece message("hello world");
+ const string boxed = encoder.Box(QuicRandom::GetInstance(), message);
+ string storage;
+ StringPiece result;
+ bool ok = decoder.Unbox(boxed, &storage, &result);
+ if (ok) {
+ EXPECT_EQ(result, message);
+ }
+ return ok;
+}
+
+TEST(CryptoSecretBoxerTest, MultipleKeys) {
+ string key_11(CryptoSecretBoxer::GetKeySize(), 0x11);
+ string key_12(CryptoSecretBoxer::GetKeySize(), 0x12);
+
+ CryptoSecretBoxer boxer_11, boxer_12, boxer;
+ boxer_11.SetKeys({key_11});
+ boxer_12.SetKeys({key_12});
+ boxer.SetKeys({key_12, key_11});
+
+ // Neither single-key boxer can decode the other's tokens.
+ EXPECT_FALSE(CanDecode(boxer_11, boxer_12));
+ EXPECT_FALSE(CanDecode(boxer_12, boxer_11));
+
+ // |boxer| encodes with the first key, which is key_12.
+ EXPECT_TRUE(CanDecode(boxer_12, boxer));
+ EXPECT_FALSE(CanDecode(boxer_11, boxer));
+
+ // The boxer with both keys can decode tokens from either single-key boxer.
+ EXPECT_TRUE(CanDecode(boxer, boxer_11));
+ EXPECT_TRUE(CanDecode(boxer, boxer_12));
+
+ // After we flush key_11 from |boxer|, it can no longer decode tokens from
+ // |boxer_11|.
+ boxer.SetKeys({key_12});
+ EXPECT_FALSE(CanDecode(boxer, boxer_11));
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/crypto/crypto_server_test.cc b/chromium/net/quic/crypto/crypto_server_test.cc
index b2fa3472e18..d2fd4c5cf53 100644
--- a/chromium/net/quic/crypto/crypto_server_test.cc
+++ b/chromium/net/quic/crypto/crypto_server_test.cc
@@ -129,7 +129,9 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
client_address_(Loopback4(), 1234),
config_(QuicCryptoServerConfig::TESTING,
rand_,
- CryptoTestUtils::ProofSourceForTesting()) {
+ CryptoTestUtils::ProofSourceForTesting()),
+ compressed_certs_cache_(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
supported_versions_ = GetParam().supported_versions;
config_.set_enable_serving_sct(true);
@@ -199,6 +201,8 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
StringPiece scid;
ASSERT_TRUE(server_config_->GetStringPiece(kSCID, &scid));
scid_hex_ = "#" + base::HexEncode(scid.data(), scid.size());
+ crypto_proof_ = QuicCryptoProof();
+ DCHECK(crypto_proof_.chain.get() == nullptr);
}
// Helper used to accept the result of ValidateClientHello and pass
@@ -259,7 +263,7 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
void ShouldSucceed(const CryptoHandshakeMessage& message) {
bool called = false;
- IPAddressNumber server_ip;
+ IPAddress server_ip;
config_.ValidateClientHello(message, client_address_.address(), server_ip,
supported_versions_.front(), &clock_,
&crypto_proof_,
@@ -277,7 +281,7 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
void ShouldFailMentioning(const char* error_substr,
const CryptoHandshakeMessage& message,
bool* called) {
- IPAddressNumber server_ip;
+ IPAddress server_ip;
config_.ValidateClientHello(
message, client_address_.address(), server_ip,
supported_versions_.front(), &clock_, &crypto_proof_,
@@ -288,7 +292,7 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
const ValidateCallback::Result& result,
bool should_succeed,
const char* error_substr) {
- IPAddressNumber server_ip;
+ IPAddress server_ip;
string error_details;
QuicConnectionId server_designated_connection_id =
rand_for_id_generation_.RandUint64();
@@ -296,7 +300,8 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
result, 1 /* ConnectionId */, server_ip, client_address_,
supported_versions_.front(), supported_versions_,
use_stateless_rejects_, server_designated_connection_id, &clock_, rand_,
- &params_, &crypto_proof_, &out_, &error_details);
+ &compressed_certs_cache_, &params_, &crypto_proof_, &out_,
+ &error_details);
if (should_succeed) {
ASSERT_EQ(error, QUIC_NO_ERROR) << "Message failed with error "
@@ -371,21 +376,22 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
}
string XlctHexString() {
- const vector<string>* certs;
- IPAddressNumber server_ip;
+ scoped_refptr<ProofSource::Chain> chain;
+ IPAddress server_ip;
string sig;
string cert_sct;
scoped_ptr<ProofSource> proof_source(
CryptoTestUtils::ProofSourceForTesting());
- if (!proof_source->GetProof(server_ip, "", "", false, &certs, &sig,
- &cert_sct) ||
- certs->empty()) {
+ if (!proof_source->GetProof(server_ip, "", "", client_version_, "", false,
+ &chain, &sig, &cert_sct) ||
+ chain->certs.empty()) {
return "#0100000000000000";
}
std::ostringstream xlct_stream;
- uint64_t xlct =
- QuicUtils::FNV1a_64_Hash(certs->at(0).c_str(), certs->at(0).length());
+ uint64_t xlct = QuicUtils::FNV1a_64_Hash(chain->certs.at(0).c_str(),
+ chain->certs.at(0).length());
+
return "#" + base::HexEncode(reinterpret_cast<char*>(&xlct), sizeof(xlct));
}
@@ -398,6 +404,7 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
QuicVersion client_version_;
string client_version_string_;
QuicCryptoServerConfig config_;
+ QuicCompressedCertsCache compressed_certs_cache_;
QuicCryptoServerConfig::ConfigOptions config_options_;
QuicCryptoNegotiatedParameters params_;
QuicCryptoProof crypto_proof_;
@@ -506,7 +513,6 @@ TEST_P(CryptoServerTest, RejectTooLarge) {
}
TEST_P(CryptoServerTest, RejectTooLargeButValidSTK) {
- ValueRestore<bool> old_flag(&FLAGS_quic_validate_stk_without_scid, true);
// Check that the server replies with no certificate when a CHLO is
// constructed with a PDMD but no SKT when the REJ would be too large.
// clang-format off
@@ -539,37 +545,6 @@ TEST_P(CryptoServerTest, RejectTooLargeButValidSTK) {
CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
}
-TEST_P(CryptoServerTest, RejectTooLargeButValidSTKWithoutFlag) {
- ValueRestore<bool> old_flag(&FLAGS_quic_validate_stk_without_scid, false);
- // Check that the server replies with no certificate when a CHLO is
- // constructed with a PDMD but no SKT when the REJ would be too large.
- // clang-format off
- CryptoHandshakeMessage msg = CryptoTestUtils::Message(
- "CHLO",
- "AEAD", "AESG",
- "KEXS", "C255",
- "PUBS", pub_hex_.c_str(),
- "NONC", nonce_hex_.c_str(),
- "#004b5453", srct_hex_.c_str(),
- "PDMD", "X509",
- "VER\0", client_version_string_.c_str(),
- "$padding", static_cast<int>(kClientHelloMinimumSize),
- nullptr);
- // clang-format on
-
- // The REJ will be larger than the CHLO so no PROF or CRT will be sent.
- config_.set_chlo_multiplier(1);
-
- ShouldSucceed(msg);
- StringPiece cert, proof, cert_sct;
- EXPECT_FALSE(out_.GetStringPiece(kCertificateTag, &cert));
- EXPECT_FALSE(out_.GetStringPiece(kPROF, &proof));
- EXPECT_FALSE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
- const HandshakeFailureReason kRejectReasons[] = {
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
-}
-
TEST_P(CryptoServerTest, TooSmall) {
// clang-format off
ShouldFailMentioning("too small", CryptoTestUtils::Message(
@@ -609,7 +584,6 @@ TEST_P(CryptoServerTest, BadSourceAddressToken) {
}
TEST_P(CryptoServerTest, BadClientNonce) {
- // Invalid nonces should be ignored.
// clang-format off
static const char* const kBadNonces[] = {
"",
@@ -619,6 +593,7 @@ TEST_P(CryptoServerTest, BadClientNonce) {
// clang-format on
for (size_t i = 0; i < arraysize(kBadNonces); i++) {
+ // Invalid nonces should be ignored, in an inchoate CHLO.
// clang-format off
CryptoHandshakeMessage msg = CryptoTestUtils::Message(
"CHLO",
@@ -631,9 +606,69 @@ TEST_P(CryptoServerTest, BadClientNonce) {
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
+
+ // Invalid nonces should result in CLIENT_NONCE_INVALID_FAILURE.
+ // clang-format off
+ CryptoHandshakeMessage msg1 = CryptoTestUtils::Message(
+ "CHLO",
+ "AEAD", "AESG",
+ "KEXS", "C255",
+ "SCID", scid_hex_.c_str(),
+ "#004b5453", srct_hex_.c_str(),
+ "PUBS", pub_hex_.c_str(),
+ "NONC", kBadNonces[i],
+ "NONP", kBadNonces[i],
+ "XLCT", XlctHexString().c_str(),
+ "VER\0", client_version_string_.c_str(),
+ "$padding", static_cast<int>(kClientHelloMinimumSize),
+ nullptr);
+ // clang-format on
+
+ ShouldSucceed(msg1);
+
+ CheckRejectTag();
+ const HandshakeFailureReason kRejectReasons1[] = {
+ CLIENT_NONCE_INVALID_FAILURE};
+ CheckRejectReasons(kRejectReasons1, arraysize(kRejectReasons1));
}
}
+TEST_P(CryptoServerTest, NoClientNonce) {
+ // No client nonces should result in INCHOATE_HELLO_FAILURE.
+ // clang-format off
+ CryptoHandshakeMessage msg = CryptoTestUtils::Message(
+ "CHLO",
+ "VER\0", client_version_string_.c_str(),
+ "$padding", static_cast<int>(kClientHelloMinimumSize),
+ nullptr);
+ // clang-format on
+
+ ShouldSucceed(msg);
+ const HandshakeFailureReason kRejectReasons[] = {
+ SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
+
+ // clang-format off
+ CryptoHandshakeMessage msg1 = CryptoTestUtils::Message(
+ "CHLO",
+ "AEAD", "AESG",
+ "KEXS", "C255",
+ "SCID", scid_hex_.c_str(),
+ "#004b5453", srct_hex_.c_str(),
+ "PUBS", pub_hex_.c_str(),
+ "XLCT", XlctHexString().c_str(),
+ "VER\0", client_version_string_.c_str(),
+ "$padding", static_cast<int>(kClientHelloMinimumSize),
+ nullptr);
+ // clang-format on
+
+ ShouldSucceed(msg1);
+ CheckRejectTag();
+ const HandshakeFailureReason kRejectReasons1[] = {
+ SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
+ CheckRejectReasons(kRejectReasons1, arraysize(kRejectReasons1));
+}
+
TEST_P(CryptoServerTest, DowngradeAttack) {
if (supported_versions_.size() == 1) {
// No downgrade attack is possible if the server only supports one version.
@@ -736,6 +771,7 @@ TEST_P(CryptoServerTest, CorruptMultipleTags) {
"#004b5453", (string(1, 'X') + srct_hex_).c_str(),
"PUBS", pub_hex_.c_str(),
"NONC", (string(1, 'X') + nonce_hex_).c_str(),
+ "NONP", (string(1, 'X') + nonce_hex_).c_str(),
"SNO\0", (string(1, 'X') + nonce_hex_).c_str(),
"XLCT", XlctHexString().c_str(),
"VER\0", client_version_string_.c_str(),
@@ -745,7 +781,7 @@ TEST_P(CryptoServerTest, CorruptMultipleTags) {
ShouldSucceed(msg);
CheckRejectTag();
- if (client_version_ <= QUIC_VERSION_30) {
+ if (client_version_ <= QUIC_VERSION_32) {
const HandshakeFailureReason kRejectReasons[] = {
SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE,
SERVER_NONCE_DECRYPTION_FAILURE};
@@ -757,50 +793,7 @@ TEST_P(CryptoServerTest, CorruptMultipleTags) {
};
}
-TEST_P(CryptoServerTest, ReplayProtection) {
- if (client_version_ > QUIC_VERSION_30) {
- return;
- }
- FLAGS_require_strike_register_or_server_nonce = false;
- // This tests that disabling replay protection works.
- // clang-format off
- CryptoHandshakeMessage msg = CryptoTestUtils::Message(
- "CHLO",
- "AEAD", "AESG",
- "KEXS", "C255",
- "SCID", scid_hex_.c_str(),
- "#004b5453", srct_hex_.c_str(),
- "PUBS", pub_hex_.c_str(),
- "NONC", nonce_hex_.c_str(),
- "XLCT", XlctHexString().c_str(),
- "VER\0", client_version_string_.c_str(),
- "$padding", static_cast<int>(kClientHelloMinimumSize),
- nullptr);
- // clang-format on
- ShouldSucceed(msg);
- // The message should be rejected because the strike-register is still
- // quiescent.
- CheckRejectTag();
-
- const HandshakeFailureReason kRejectReasons[] = {
- CLIENT_NONCE_INVALID_TIME_FAILURE};
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
-
- config_.set_replay_protection(false);
-
- ShouldSucceed(msg);
- // The message should be accepted now.
- ASSERT_EQ(kSHLO, out_.tag());
- CheckServerHello(out_);
-
- ShouldSucceed(msg);
- // The message should accepted twice when replay protection is off.
- ASSERT_EQ(kSHLO, out_.tag());
- CheckServerHello(out_);
-}
-
TEST_P(CryptoServerTest, NoServerNonce) {
- FLAGS_require_strike_register_or_server_nonce = true;
// When no server nonce is present and no strike register is configured,
// the CHLO should be rejected.
// clang-format off
@@ -812,6 +805,7 @@ TEST_P(CryptoServerTest, NoServerNonce) {
"#004b5453", srct_hex_.c_str(),
"PUBS", pub_hex_.c_str(),
"NONC", nonce_hex_.c_str(),
+ "NONP", nonce_hex_.c_str(),
"XLCT", XlctHexString().c_str(),
"VER\0", client_version_string_.c_str(),
"$padding", static_cast<int>(kClientHelloMinimumSize),
@@ -827,7 +821,6 @@ TEST_P(CryptoServerTest, NoServerNonce) {
}
TEST_P(CryptoServerTest, ProofForSuppliedServerConfig) {
- ValueRestore<bool> old_flag(&FLAGS_quic_use_primary_config_for_proof, true);
client_address_ = IPEndPoint(Loopback6(), 1234);
// clang-format off
CryptoHandshakeMessage msg = CryptoTestUtils::Message(
@@ -877,10 +870,13 @@ TEST_P(CryptoServerTest, ProofForSuppliedServerConfig) {
scoped_ptr<ProofVerifyDetails> details;
string error_details;
DummyProofVerifierCallback callback;
- EXPECT_EQ(QUIC_SUCCESS, proof_verifier->VerifyProof(
- "test.example.com", scfg_str.as_string(), certs,
- "", proof.as_string(), verify_context.get(),
- &error_details, &details, &callback));
+ string chlo_hash;
+ CryptoUtils::HashHandshakeMessage(msg, &chlo_hash);
+ EXPECT_EQ(QUIC_SUCCESS,
+ proof_verifier->VerifyProof(
+ "test.example.com", 443, scfg_str.as_string(), client_version_,
+ chlo_hash, certs, "", proof.as_string(), verify_context.get(),
+ &error_details, &details, &callback));
}
TEST_P(CryptoServerTest, RejectInvalidXlct) {
@@ -926,6 +922,7 @@ 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),
@@ -1139,7 +1136,7 @@ class AsyncStrikeServerVerificationTest : public CryptoServerTest {
reinterpret_cast<const uint8_t*>(kOrbit.c_str()),
StrikeRegister::NO_STARTUP_PERIOD_NEEDED);
config_.SetStrikeRegisterClient(strike_register_client_);
- CryptoServerTest::SetUp();
+ ASSERT_NO_FATAL_FAILURE(CryptoServerTest::SetUp());
strike_register_client_->StartDelayingVerification();
}
@@ -1166,7 +1163,7 @@ TEST_P(AsyncStrikeServerVerificationTest, AsyncReplayProtection) {
out_.set_tag(0);
bool called = false;
- IPAddressNumber server_ip;
+ IPAddress server_ip;
config_.ValidateClientHello(msg, client_address_.address(), server_ip,
client_version_, &clock_, &crypto_proof_,
new ValidateCallback(this, true, "", &called));
diff --git a/chromium/net/quic/crypto/crypto_utils.cc b/chromium/net/quic/crypto/crypto_utils.cc
index 0c6a4a742f6..2b22acd9930 100644
--- a/chromium/net/quic/crypto/crypto_utils.cc
+++ b/chromium/net/quic/crypto/crypto_utils.cc
@@ -5,7 +5,8 @@
#include "net/quic/crypto/crypto_utils.h"
#include "crypto/hkdf.h"
-#include "net/base/net_util.h"
+#include "crypto/secure_hash.h"
+#include "net/base/url_util.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/crypto/quic_decrypter.h"
@@ -274,4 +275,16 @@ const char* CryptoUtils::HandshakeFailureReasonToString(
return "INVALID_HANDSHAKE_FAILURE_REASON";
}
+// static
+void CryptoUtils::HashHandshakeMessage(const CryptoHandshakeMessage& message,
+ string* output) {
+ const QuicData& serialized = message.GetSerialized();
+ scoped_ptr<crypto::SecureHash> hash(
+ crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+ hash->Update(serialized.data(), serialized.length());
+ uint8_t digest[32];
+ hash->Finish(digest, sizeof(digest));
+ output->assign(reinterpret_cast<const char*>(&digest), sizeof(digest));
+}
+
} // namespace net
diff --git a/chromium/net/quic/crypto/crypto_utils.h b/chromium/net/quic/crypto/crypto_utils.h
index b4e40e9043c..f51123bb3e7 100644
--- a/chromium/net/quic/crypto/crypto_utils.h
+++ b/chromium/net/quic/crypto/crypto_utils.h
@@ -105,6 +105,10 @@ class NET_EXPORT_PRIVATE CryptoUtils {
static const char* HandshakeFailureReasonToString(
HandshakeFailureReason reason);
+ // Writes a hash of the serialized |message| into |output|.
+ static void HashHandshakeMessage(const CryptoHandshakeMessage& message,
+ std::string* output);
+
private:
DISALLOW_COPY_AND_ASSIGN(CryptoUtils);
};
diff --git a/chromium/net/quic/crypto/curve25519_key_exchange.cc b/chromium/net/quic/crypto/curve25519_key_exchange.cc
index cf97addb50a..6545d21bc2f 100644
--- a/chromium/net/quic/crypto/curve25519_key_exchange.cc
+++ b/chromium/net/quic/crypto/curve25519_key_exchange.cc
@@ -18,8 +18,7 @@ Curve25519KeyExchange::Curve25519KeyExchange() {}
Curve25519KeyExchange::~Curve25519KeyExchange() {}
// static
-Curve25519KeyExchange* Curve25519KeyExchange::New(
- const StringPiece& private_key) {
+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
@@ -58,9 +57,8 @@ KeyExchange* Curve25519KeyExchange::NewKeyPair(QuicRandom* rand) const {
return Curve25519KeyExchange::New(private_value);
}
-bool Curve25519KeyExchange::CalculateSharedKey(
- const StringPiece& peer_public_value,
- string* out_result) const {
+bool Curve25519KeyExchange::CalculateSharedKey(StringPiece peer_public_value,
+ string* out_result) const {
if (peer_public_value.size() != crypto::curve25519::kBytes) {
return false;
}
diff --git a/chromium/net/quic/crypto/curve25519_key_exchange.h b/chromium/net/quic/crypto/curve25519_key_exchange.h
index 1637bbb481d..a95cf7f6ce6 100644
--- a/chromium/net/quic/crypto/curve25519_key_exchange.h
+++ b/chromium/net/quic/crypto/curve25519_key_exchange.h
@@ -26,7 +26,7 @@ class NET_EXPORT_PRIVATE Curve25519KeyExchange : public KeyExchange {
// New creates a new object from a private key. If the private key is
// invalid, nullptr is returned.
- static Curve25519KeyExchange* New(const base::StringPiece& private_key);
+ static Curve25519KeyExchange* New(base::StringPiece private_key);
// NewPrivateKey returns a private key, generated from |rand|, suitable for
// passing to |New|.
@@ -34,7 +34,7 @@ class NET_EXPORT_PRIVATE Curve25519KeyExchange : public KeyExchange {
// KeyExchange interface.
KeyExchange* NewKeyPair(QuicRandom* rand) const override;
- bool CalculateSharedKey(const base::StringPiece& peer_public_value,
+ bool CalculateSharedKey(base::StringPiece peer_public_value,
std::string* shared_key) const override;
base::StringPiece public_value() const override;
QuicTag tag() const override;
diff --git a/chromium/net/quic/crypto/key_exchange.h b/chromium/net/quic/crypto/key_exchange.h
index 8690f0eff2c..a6de1c39dfd 100644
--- a/chromium/net/quic/crypto/key_exchange.h
+++ b/chromium/net/quic/crypto/key_exchange.h
@@ -29,7 +29,7 @@ class NET_EXPORT_PRIVATE KeyExchange {
// CalculateSharedKey computes the shared key between the local private key
// (which is implicitly known by a KeyExchange object) and a public value
// from the peer.
- virtual bool CalculateSharedKey(const base::StringPiece& peer_public_value,
+ virtual bool CalculateSharedKey(base::StringPiece peer_public_value,
std::string* shared_key) const = 0;
// public_value returns the local public key which can be sent to a peer in
diff --git a/chromium/net/quic/crypto/null_decrypter.cc b/chromium/net/quic/crypto/null_decrypter.cc
index 67709c3d51c..43adb67958b 100644
--- a/chromium/net/quic/crypto/null_decrypter.cc
+++ b/chromium/net/quic/crypto/null_decrypter.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_data_reader.h"
#include "net/quic/quic_utils.h"
@@ -24,9 +25,10 @@ bool NullDecrypter::SetNoncePrefix(StringPiece nonce_prefix) {
return nonce_prefix.empty();
}
-bool NullDecrypter::DecryptPacket(QuicPacketNumber /*packet_number*/,
- const StringPiece& associated_data,
- const StringPiece& ciphertext,
+bool NullDecrypter::DecryptPacket(QuicPathId /*path_id*/,
+ QuicPacketNumber /*packet_number*/,
+ StringPiece associated_data,
+ StringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) {
@@ -39,7 +41,7 @@ bool NullDecrypter::DecryptPacket(QuicPacketNumber /*packet_number*/,
StringPiece plaintext = reader.ReadRemainingPayload();
if (plaintext.length() > max_output_length) {
- LOG(DFATAL) << "Output buffer must be larger than the plaintext.";
+ QUIC_BUG << "Output buffer must be larger than the plaintext.";
return false;
}
if (hash != ComputeHash(associated_data, plaintext)) {
diff --git a/chromium/net/quic/crypto/null_decrypter.h b/chromium/net/quic/crypto/null_decrypter.h
index 64a6a19b20a..e5e15b2c913 100644
--- a/chromium/net/quic/crypto/null_decrypter.h
+++ b/chromium/net/quic/crypto/null_decrypter.h
@@ -28,9 +28,10 @@ class NET_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
// QuicDecrypter implementation
bool SetKey(base::StringPiece key) override;
bool SetNoncePrefix(base::StringPiece nonce_prefix) override;
- bool DecryptPacket(QuicPacketNumber packet_number,
- const base::StringPiece& associated_data,
- const base::StringPiece& ciphertext,
+ bool DecryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
+ base::StringPiece associated_data,
+ base::StringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) override;
@@ -42,8 +43,7 @@ class NET_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
private:
bool ReadHash(QuicDataReader* reader, uint128* hash);
- uint128 ComputeHash(const base::StringPiece data1,
- const base::StringPiece data2) const;
+ uint128 ComputeHash(base::StringPiece data1, base::StringPiece data2) const;
DISALLOW_COPY_AND_ASSIGN(NullDecrypter);
};
diff --git a/chromium/net/quic/crypto/null_decrypter_test.cc b/chromium/net/quic/crypto/null_decrypter_test.cc
index 4e533755357..43d980084c6 100644
--- a/chromium/net/quic/crypto/null_decrypter_test.cc
+++ b/chromium/net/quic/crypto/null_decrypter_test.cc
@@ -24,8 +24,9 @@ TEST_F(NullDecrypterTest, Decrypt) {
NullDecrypter decrypter;
char buffer[256];
size_t length = 0;
- ASSERT_TRUE(decrypter.DecryptPacket(0, "hello world!", StringPiece(data, len),
- buffer, &length, 256));
+ ASSERT_TRUE(decrypter.DecryptPacket(kDefaultPathId, 0, "hello world!",
+ StringPiece(data, len), buffer, &length,
+ 256));
EXPECT_LT(0u, length);
EXPECT_EQ("goodbye!", StringPiece(buffer, length));
}
@@ -42,8 +43,9 @@ TEST_F(NullDecrypterTest, BadHash) {
NullDecrypter decrypter;
char buffer[256];
size_t length = 0;
- ASSERT_FALSE(decrypter.DecryptPacket(
- 0, "hello world!", StringPiece(data, len), buffer, &length, 256));
+ ASSERT_FALSE(decrypter.DecryptPacket(kDefaultPathId, 0, "hello world!",
+ StringPiece(data, len), buffer, &length,
+ 256));
}
TEST_F(NullDecrypterTest, ShortInput) {
@@ -56,8 +58,9 @@ TEST_F(NullDecrypterTest, ShortInput) {
NullDecrypter decrypter;
char buffer[256];
size_t length = 0;
- ASSERT_FALSE(decrypter.DecryptPacket(
- 0, "hello world!", StringPiece(data, len), buffer, &length, 256));
+ ASSERT_FALSE(decrypter.DecryptPacket(kDefaultPathId, 0, "hello world!",
+ StringPiece(data, len), buffer, &length,
+ 256));
}
} // namespace test
diff --git a/chromium/net/quic/crypto/null_encrypter.cc b/chromium/net/quic/crypto/null_encrypter.cc
index 470674b1e5c..6d7ef809e16 100644
--- a/chromium/net/quic/crypto/null_encrypter.cc
+++ b/chromium/net/quic/crypto/null_encrypter.cc
@@ -24,7 +24,8 @@ bool NullEncrypter::SetNoncePrefix(StringPiece nonce_prefix) {
return nonce_prefix.empty();
}
-bool NullEncrypter::EncryptPacket(QuicPacketNumber /*packet_number*/,
+bool NullEncrypter::EncryptPacket(QuicPathId /*path_id*/,
+ QuicPacketNumber /*packet_number*/,
StringPiece associated_data,
StringPiece plaintext,
char* output,
diff --git a/chromium/net/quic/crypto/null_encrypter.h b/chromium/net/quic/crypto/null_encrypter.h
index c07495e7b51..77d6e91e388 100644
--- a/chromium/net/quic/crypto/null_encrypter.h
+++ b/chromium/net/quic/crypto/null_encrypter.h
@@ -25,7 +25,8 @@ class NET_EXPORT_PRIVATE NullEncrypter : public QuicEncrypter {
// QuicEncrypter implementation
bool SetKey(base::StringPiece key) override;
bool SetNoncePrefix(base::StringPiece nonce_prefix) override;
- bool EncryptPacket(QuicPacketNumber packet_number,
+ bool EncryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
base::StringPiece associated_data,
base::StringPiece plaintext,
char* output,
diff --git a/chromium/net/quic/crypto/null_encrypter_test.cc b/chromium/net/quic/crypto/null_encrypter_test.cc
index 02a2f73a0df..b6b1e303fa5 100644
--- a/chromium/net/quic/crypto/null_encrypter_test.cc
+++ b/chromium/net/quic/crypto/null_encrypter_test.cc
@@ -22,8 +22,9 @@ TEST_F(NullEncrypterTest, Encrypt) {
NullEncrypter encrypter;
char encrypted[256];
size_t encrypted_len = 0;
- ASSERT_TRUE(encrypter.EncryptPacket(0, "hello world!", "goodbye!", encrypted,
- &encrypted_len, 256));
+ ASSERT_TRUE(encrypter.EncryptPacket(kDefaultPathId, 0, "hello world!",
+ "goodbye!", encrypted, &encrypted_len,
+ 256));
test::CompareCharArraysWithHexError(
"encrypted data", encrypted, encrypted_len,
reinterpret_cast<const char*>(expected), arraysize(expected));
diff --git a/chromium/net/quic/crypto/p256_key_exchange.h b/chromium/net/quic/crypto/p256_key_exchange.h
index e6855aa31a5..197adfe557c 100644
--- a/chromium/net/quic/crypto/p256_key_exchange.h
+++ b/chromium/net/quic/crypto/p256_key_exchange.h
@@ -42,7 +42,7 @@ class NET_EXPORT_PRIVATE P256KeyExchange : public KeyExchange {
// KeyExchange interface.
KeyExchange* NewKeyPair(QuicRandom* rand) const override;
- bool CalculateSharedKey(const base::StringPiece& peer_public_value,
+ bool CalculateSharedKey(base::StringPiece peer_public_value,
std::string* shared_key) const override;
base::StringPiece public_value() const override;
QuicTag tag() const override;
diff --git a/chromium/net/quic/crypto/p256_key_exchange_nss.cc b/chromium/net/quic/crypto/p256_key_exchange_nss.cc
index 576825f96f3..c5529ab5821 100644
--- a/chromium/net/quic/crypto/p256_key_exchange_nss.cc
+++ b/chromium/net/quic/crypto/p256_key_exchange_nss.cc
@@ -153,7 +153,7 @@ KeyExchange* P256KeyExchange::NewKeyPair(QuicRandom* /*rand*/) const {
return P256KeyExchange::New(private_value);
}
-bool P256KeyExchange::CalculateSharedKey(const StringPiece& peer_public_value,
+bool P256KeyExchange::CalculateSharedKey(StringPiece peer_public_value,
string* out_result) const {
if (peer_public_value.size() != kUncompressedP256PointBytes ||
peer_public_value[0] != kUncompressedECPointForm) {
diff --git a/chromium/net/quic/crypto/p256_key_exchange_openssl.cc b/chromium/net/quic/crypto/p256_key_exchange_openssl.cc
index 7a9707e308d..9703a2e9f64 100644
--- a/chromium/net/quic/crypto/p256_key_exchange_openssl.cc
+++ b/chromium/net/quic/crypto/p256_key_exchange_openssl.cc
@@ -77,7 +77,7 @@ KeyExchange* P256KeyExchange::NewKeyPair(QuicRandom* /*rand*/) const {
return P256KeyExchange::New(private_value);
}
-bool P256KeyExchange::CalculateSharedKey(const StringPiece& peer_public_value,
+bool P256KeyExchange::CalculateSharedKey(StringPiece peer_public_value,
string* out_result) const {
if (peer_public_value.size() != kUncompressedP256PointBytes) {
DVLOG(1) << "Peer public value is invalid";
diff --git a/chromium/net/quic/crypto/proof_source.cc b/chromium/net/quic/crypto/proof_source.cc
new file mode 100644
index 00000000000..b695725ae7c
--- /dev/null
+++ b/chromium/net/quic/crypto/proof_source.cc
@@ -0,0 +1,14 @@
+// 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/crypto/proof_source.h"
+
+namespace net {
+
+ProofSource::Chain::Chain(const std::vector<std::string>& certs)
+ : certs(certs) {}
+
+ProofSource::Chain::~Chain() {}
+
+} // namespace net
diff --git a/chromium/net/quic/crypto/proof_source.h b/chromium/net/quic/crypto/proof_source.h
index 235b972b898..74b9df3c7e0 100644
--- a/chromium/net/quic/crypto/proof_source.h
+++ b/chromium/net/quic/crypto/proof_source.h
@@ -8,15 +8,33 @@
#include <string>
#include <vector>
-#include "net/base/ip_address_number.h"
+#include "base/memory/ref_counted.h"
#include "net/base/net_export.h"
+#include "net/quic/quic_protocol.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 {
public:
+ // Chain is a reference-counted wrapper for a std::vector of std::stringified
+ // certificates.
+ struct NET_EXPORT_PRIVATE Chain : public base::RefCounted<Chain> {
+ explicit Chain(const std::vector<std::string>& certs);
+
+ const std::vector<std::string> certs;
+
+ private:
+ friend class base::RefCounted<Chain>;
+
+ virtual ~Chain();
+
+ DISALLOW_COPY_AND_ASSIGN(Chain);
+ };
+
virtual ~ProofSource() {}
// GetProof finds a certificate chain for |hostname|, sets |out_certs| to
@@ -31,16 +49,21 @@ class NET_EXPORT_PRIVATE ProofSource {
// If |ecdsa_ok| is true, the signature may use an ECDSA key. Otherwise, the
// signature must use an RSA key.
//
- // |out_certs| is a pointer to a pointer, not a pointer to an array.
+ // |out_chain| is reference counted to avoid the (assumed) expense of copying
+ // out the certificates.
//
// The number of certificate chains is expected to be small and fixed thus
// the ProofSource retains ownership of the contents of |out_certs|. The
// expectation is that they will be cached forever.
//
- // The signature values should be cached because |server_config| will be
- // somewhat static. However, since they aren't bounded, the ProofSource may
- // wish to evicit entries from that cache, thus the caller takes ownership of
- // |*out_signature|.
+ // For version before QUIC_VERSION_30, the signature values should be cached
+ // because |server_config| will be somewhat static. However, since they aren't
+ // bounded, the ProofSource may wish to evicit entries from that cache, thus
+ // the caller takes ownership of |*out_signature|.
+ //
+ // For QUIC_VERSION_30 and later, the signature depends on |chlo_hash|
+ // which means that the signature can not be cached. The caller takes
+ // ownership of |*out_signature|.
//
// |hostname| may be empty to signify that a default certificate should be
// used.
@@ -48,11 +71,13 @@ class NET_EXPORT_PRIVATE ProofSource {
// |out_leaf_cert_sct| points to the signed timestamp (RFC6962) of the leaf
// cert.
// This function may be called concurrently.
- virtual bool GetProof(const IPAddressNumber& server_ip,
+ virtual bool GetProof(const IPAddress& server_ip,
const std::string& hostname,
const std::string& server_config,
+ QuicVersion quic_version,
+ base::StringPiece chlo_hash,
bool ecdsa_ok,
- const std::vector<std::string>** out_certs,
+ scoped_refptr<Chain>* out_chain,
std::string* out_signature,
std::string* out_leaf_cert_sct) = 0;
};
diff --git a/chromium/net/quic/crypto/proof_source_chromium.h b/chromium/net/quic/crypto/proof_source_chromium.h
index cfed05f4185..70b8ea18ccb 100644
--- a/chromium/net/quic/crypto/proof_source_chromium.h
+++ b/chromium/net/quic/crypto/proof_source_chromium.h
@@ -33,17 +33,19 @@ class NET_EXPORT_PRIVATE ProofSourceChromium : public ProofSource {
const base::FilePath& sct_path);
// ProofSource interface
- bool GetProof(const IPAddressNumber& server_ip,
+ bool GetProof(const IPAddress& server_ip,
const std::string& hostname,
const std::string& server_config,
+ QuicVersion quic_version,
+ base::StringPiece chlo_hash,
bool ecdsa_ok,
- const std::vector<std::string>** out_certs,
+ scoped_refptr<ProofSource::Chain>* out_chain,
std::string* out_signature,
std::string* out_leaf_cert_sct) override;
private:
scoped_ptr<crypto::RSAPrivateKey> private_key_;
- std::vector<std::string> certificates_;
+ scoped_refptr<ProofSource::Chain> chain_;
std::string signed_certificate_timestamp_;
DISALLOW_COPY_AND_ASSIGN(ProofSourceChromium);
diff --git a/chromium/net/quic/crypto/proof_source_chromium_nss.cc b/chromium/net/quic/crypto/proof_source_chromium_nss.cc
index 407089a87b9..8ab7cc363de 100644
--- a/chromium/net/quic/crypto/proof_source_chromium_nss.cc
+++ b/chromium/net/quic/crypto/proof_source_chromium_nss.cc
@@ -19,11 +19,13 @@ bool ProofSourceChromium::Initialize(const base::FilePath& cert_path,
return false;
}
-bool ProofSourceChromium::GetProof(const IPAddressNumber& server_ip,
+bool ProofSourceChromium::GetProof(const IPAddress& server_ip,
const string& hostname,
const string& server_config,
+ QuicVersion quic_version,
+ base::StringPiece chlo_hash,
bool ecdsa_ok,
- const vector<string>** out_certs,
+ scoped_refptr<ProofSource::Chain>* out_chain,
string* out_signature,
string* out_leaf_cert_sct) {
return false;
diff --git a/chromium/net/quic/crypto/proof_source_chromium_openssl.cc b/chromium/net/quic/crypto/proof_source_chromium_openssl.cc
index ec0bdea9d56..b03c05d5c49 100644
--- a/chromium/net/quic/crypto/proof_source_chromium_openssl.cc
+++ b/chromium/net/quic/crypto/proof_source_chromium_openssl.cc
@@ -42,14 +42,16 @@ bool ProofSourceChromium::Initialize(const base::FilePath& cert_path,
return false;
}
+ vector<string> certs;
for (const scoped_refptr<X509Certificate>& cert : certs_in_file) {
std::string der_encoded_cert;
if (!X509Certificate::GetDEREncoded(cert->os_cert_handle(),
&der_encoded_cert)) {
return false;
}
- certificates_.push_back(der_encoded_cert);
+ certs.push_back(der_encoded_cert);
}
+ chain_ = new ProofSource::Chain(certs);
std::string key_data;
if (!base::ReadFileToString(key_path, &key_data)) {
@@ -77,11 +79,13 @@ bool ProofSourceChromium::Initialize(const base::FilePath& cert_path,
return true;
}
-bool ProofSourceChromium::GetProof(const IPAddressNumber& server_ip,
+bool ProofSourceChromium::GetProof(const IPAddress& server_ip,
const string& hostname,
const string& server_config,
+ QuicVersion quic_version,
+ base::StringPiece chlo_hash,
bool ecdsa_ok,
- const vector<string>** out_certs,
+ scoped_refptr<ProofSource::Chain>* out_chain,
string* out_signature,
string* out_leaf_cert_sct) {
DCHECK(private_key_.get()) << " this: " << this;
@@ -89,18 +93,41 @@ bool ProofSourceChromium::GetProof(const IPAddressNumber& server_ip,
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
crypto::ScopedEVP_MD_CTX sign_context(EVP_MD_CTX_create());
EVP_PKEY_CTX* pkey_ctx;
- if (!EVP_DigestSignInit(sign_context.get(), &pkey_ctx, EVP_sha256(), nullptr,
- private_key_->key()) ||
- !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) ||
- !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1) ||
- !EVP_DigestSignUpdate(
- sign_context.get(),
- reinterpret_cast<const uint8_t*>(kProofSignatureLabel),
- sizeof(kProofSignatureLabel)) ||
- !EVP_DigestSignUpdate(
- sign_context.get(),
- reinterpret_cast<const uint8_t*>(server_config.data()),
- server_config.size())) {
+
+ if (quic_version > QUIC_VERSION_30) {
+ uint32_t len = chlo_hash.length();
+ if (!EVP_DigestSignInit(sign_context.get(), &pkey_ctx, EVP_sha256(),
+ nullptr, private_key_->key()) ||
+ !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) ||
+ !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1) ||
+ !EVP_DigestSignUpdate(
+ sign_context.get(),
+ reinterpret_cast<const uint8_t*>(kProofSignatureLabel),
+ sizeof(kProofSignatureLabel)) ||
+ !EVP_DigestSignUpdate(sign_context.get(),
+ reinterpret_cast<const uint8_t*>(&len),
+ sizeof(len)) ||
+ !EVP_DigestSignUpdate(
+ sign_context.get(),
+ reinterpret_cast<const uint8_t*>(chlo_hash.data()), len) ||
+ !EVP_DigestSignUpdate(
+ sign_context.get(),
+ reinterpret_cast<const uint8_t*>(server_config.data()),
+ server_config.size())) {
+ return false;
+ }
+ } else if (!EVP_DigestSignInit(sign_context.get(), &pkey_ctx, EVP_sha256(),
+ nullptr, private_key_->key()) ||
+ !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) ||
+ !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1) ||
+ !EVP_DigestSignUpdate(
+ sign_context.get(),
+ reinterpret_cast<const uint8_t*>(kProofSignatureLabelOld),
+ sizeof(kProofSignatureLabelOld)) ||
+ !EVP_DigestSignUpdate(
+ sign_context.get(),
+ reinterpret_cast<const uint8_t*>(server_config.data()),
+ server_config.size())) {
return false;
}
@@ -117,7 +144,7 @@ bool ProofSourceChromium::GetProof(const IPAddressNumber& server_ip,
signature.resize(len);
out_signature->assign(reinterpret_cast<const char*>(signature.data()),
signature.size());
- *out_certs = &certificates_;
+ *out_chain = chain_;
VLOG(1) << "signature: "
<< base::HexEncode(out_signature->data(), out_signature->size());
*out_leaf_cert_sct = signed_certificate_timestamp_;
diff --git a/chromium/net/quic/crypto/proof_test.cc b/chromium/net/quic/crypto/proof_test.cc
index 3ee3781aa44..cdca324ebb9 100644
--- a/chromium/net/quic/crypto/proof_test.cc
+++ b/chromium/net/quic/crypto/proof_test.cc
@@ -56,7 +56,10 @@ class TestProofVerifierCallback : public ProofVerifierCallback {
// matches |expected_ok|.
void RunVerification(ProofVerifier* verifier,
const string& hostname,
+ const uint16_t port,
const string& server_config,
+ QuicVersion quic_version,
+ StringPiece chlo_hash,
const vector<string>& certs,
const string& proof,
bool expected_ok) {
@@ -70,8 +73,8 @@ void RunVerification(ProofVerifier* verifier,
new TestProofVerifierCallback(&comp_callback, &ok, &error_details);
QuicAsyncStatus status = verifier->VerifyProof(
- hostname, server_config, certs, "", proof, verify_context.get(),
- &error_details, &details, callback);
+ hostname, port, server_config, quic_version, chlo_hash, certs, "", proof,
+ verify_context.get(), &error_details, &details, callback);
switch (status) {
case QUIC_FAILURE:
@@ -104,57 +107,103 @@ string LoadTestCert(const string& file_name) {
return der_bytes;
}
+class ProofTest : public ::testing::TestWithParam<QuicVersion> {};
+
} // namespace
+INSTANTIATE_TEST_CASE_P(QuicVersion,
+ ProofTest,
+ ::testing::ValuesIn(QuicSupportedVersions()));
+
// TODO(rtenneti): Enable testing of ProofVerifier. See http://crbug.com/514468.
-TEST(ProofTest, DISABLED_Verify) {
+TEST_P(ProofTest, DISABLED_Verify) {
scoped_ptr<ProofSource> source(CryptoTestUtils::ProofSourceForTesting());
scoped_ptr<ProofVerifier> verifier(
CryptoTestUtils::ProofVerifierForTesting());
const string server_config = "server config bytes";
const string hostname = "test.example.com";
- const vector<string>* certs;
- const vector<string>* first_certs;
+ const uint16_t port = 8443;
+ const string first_chlo_hash = "first chlo hash bytes";
+ 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;
- IPAddressNumber server_ip;
+ IPAddress server_ip;
- ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config,
- false /* no ECDSA */, &first_certs,
- &first_signature, &first_cert_sct));
- ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config,
- false /* no ECDSA */, &certs, &signature,
- &cert_sct));
+ ASSERT_TRUE(source->GetProof(
+ server_ip, hostname, server_config, quic_version, first_chlo_hash,
+ false /* no ECDSA */, &first_chain, &first_signature, &first_cert_sct));
+ ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config, quic_version,
+ second_chlo_hash, false /* no ECDSA */, &chain,
+ &signature, &cert_sct));
// Check that the proof source is caching correctly:
- ASSERT_EQ(first_certs, certs);
- ASSERT_EQ(signature, first_signature);
+ ASSERT_EQ(first_chain->certs, chain->certs);
+ if (GetParam() < QUIC_VERSION_31) {
+ ASSERT_EQ(signature, first_signature);
+ } else {
+ // QUIC 31 includes the CHLO hash.
+ ASSERT_NE(signature, first_signature);
+ }
ASSERT_EQ(first_cert_sct, cert_sct);
- RunVerification(verifier.get(), hostname, server_config, *certs, signature,
- true);
+ RunVerification(verifier.get(), hostname, port, server_config, quic_version,
+ first_chlo_hash, chain->certs, signature, true);
- RunVerification(verifier.get(), "foo.com", server_config, *certs, signature,
- false);
+ RunVerification(verifier.get(), "foo.com", port, server_config, quic_version,
+ first_chlo_hash, chain->certs, signature, false);
- RunVerification(verifier.get(), server_config.substr(1, string::npos),
- server_config, *certs, signature, false);
+ RunVerification(verifier.get(), server_config.substr(1, string::npos), port,
+ server_config, quic_version, first_chlo_hash, chain->certs,
+ signature, false);
const string corrupt_signature = "1" + signature;
- RunVerification(verifier.get(), hostname, server_config, *certs,
- corrupt_signature, false);
+ RunVerification(verifier.get(), hostname, port, server_config, quic_version,
+ first_chlo_hash, chain->certs, corrupt_signature, false);
vector<string> wrong_certs;
- for (size_t i = 1; i < certs->size(); i++) {
- wrong_certs.push_back((*certs)[i]);
+ for (size_t i = 1; i < chain->certs.size(); i++) {
+ wrong_certs.push_back(chain->certs[i]);
+ }
+
+ RunVerification(verifier.get(), "foo.com", port, server_config, quic_version,
+ first_chlo_hash, wrong_certs, corrupt_signature, false);
+}
+
+TEST_P(ProofTest, UseAfterFree) {
+ ProofSource* source = CryptoTestUtils::ProofSourceForTesting();
+
+ 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;
+
+ ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config, GetParam(),
+ chlo_hash, false /* no ECDSA */, &chain,
+ &signature, &cert_sct));
+
+ // Make sure we can safely access results after deleting where they came from.
+ EXPECT_FALSE(chain->HasOneRef());
+ delete source;
+ EXPECT_TRUE(chain->HasOneRef());
+
+ EXPECT_FALSE(chain->certs.empty());
+ for (const string& cert : chain->certs) {
+ EXPECT_FALSE(cert.empty());
}
- RunVerification(verifier.get(), "foo.com", server_config, wrong_certs,
- corrupt_signature, false);
}
// A known answer test that allows us to test ProofVerifier without a working
// ProofSource.
-TEST(ProofTest, VerifyRSAKnownAnswerTest) {
+TEST_P(ProofTest, VerifyRSAKnownAnswerTest) {
+ if (GetParam() > QUIC_VERSION_30) {
+ return;
+ }
// These sample signatures were generated by running the Proof.Verify test
// and dumping the bytes of the |signature| output of ProofSource::GetProof().
static const unsigned char signature_data_0[] = {
@@ -235,6 +284,9 @@ TEST(ProofTest, VerifyRSAKnownAnswerTest) {
const string server_config = "server config bytes";
const string hostname = "test.example.com";
+ const uint16_t port = 8443;
+ const string chlo_hash = "proof nonce bytes";
+ const QuicVersion quic_version = GetParam();
vector<string> certs(2);
certs[0] = LoadTestCert("test.example.com.crt");
@@ -253,30 +305,37 @@ TEST(ProofTest, VerifyRSAKnownAnswerTest) {
for (size_t i = 0; i < signatures.size(); i++) {
const string& signature = signatures[i];
- RunVerification(verifier.get(), hostname, server_config, certs, signature,
- true);
- RunVerification(verifier.get(), "foo.com", server_config, certs, signature,
- false);
- RunVerification(verifier.get(), hostname,
- server_config.substr(1, string::npos), certs, signature,
- false);
+ RunVerification(verifier.get(), hostname, port, server_config, quic_version,
+ chlo_hash, certs, signature, true);
+ RunVerification(verifier.get(), "foo.com", port, server_config,
+ quic_version, chlo_hash, certs, signature, false);
+ RunVerification(verifier.get(), hostname, port,
+ server_config.substr(1, string::npos), quic_version,
+ chlo_hash, certs, signature, false);
const string corrupt_signature = "1" + signature;
- RunVerification(verifier.get(), hostname, server_config, certs,
- corrupt_signature, false);
+ RunVerification(verifier.get(), hostname, port, server_config, quic_version,
+ chlo_hash, certs, corrupt_signature, false);
vector<string> wrong_certs;
for (size_t i = 1; i < certs.size(); i++) {
wrong_certs.push_back(certs[i]);
}
- RunVerification(verifier.get(), hostname, server_config, wrong_certs,
- signature, false);
+ RunVerification(verifier.get(), hostname, port, server_config, quic_version,
+ chlo_hash, wrong_certs, signature, false);
}
}
// A known answer test that allows us to test ProofVerifier without a working
// ProofSource.
-TEST(ProofTest, VerifyECDSAKnownAnswerTest) {
+TEST_P(ProofTest, VerifyECDSAKnownAnswerTest) {
+ if (GetParam() > QUIC_VERSION_30) {
+ return;
+ }
+// These sample signatures were generated by running the Proof.Verify test
+// (modified to use ECDSA for signing proofs) and dumping the bytes of the
+// |signature| output of ProofSource::GetProof().
+
// Disable this test on platforms that do not support ECDSA certificates.
#if defined(OS_WIN)
if (base::win::GetVersion() < base::win::VERSION_VISTA)
@@ -316,6 +375,9 @@ TEST(ProofTest, VerifyECDSAKnownAnswerTest) {
const string server_config = "server config bytes";
const string hostname = "test.example.com";
+ const uint16_t port = 8443;
+ const string chlo_hash = "chlo_hash nonce bytes";
+ const QuicVersion quic_version = GetParam();
vector<string> certs(2);
certs[0] = LoadTestCert("test_ecc.example.com.crt");
@@ -332,34 +394,41 @@ TEST(ProofTest, VerifyECDSAKnownAnswerTest) {
sizeof(signature_data_2));
for (size_t i = 0; i < signatures.size(); i++) {
+ LOG(ERROR) << "====================" << i << "======================";
const string& signature = signatures[i];
- RunVerification(verifier.get(), hostname, server_config, certs, signature,
- true);
- RunVerification(verifier.get(), "foo.com", server_config, certs, signature,
- false);
- RunVerification(verifier.get(), hostname,
- server_config.substr(1, string::npos), certs, signature,
- false);
+ LOG(ERROR) << "=================== expect ok =====================";
+ RunVerification(verifier.get(), hostname, port, server_config, quic_version,
+ chlo_hash, certs, signature, true);
+ LOG(ERROR) << "=================== hose_name = foo.com =============";
+ RunVerification(verifier.get(), "foo.com", port, server_config,
+ quic_version, chlo_hash, certs, signature, false);
+ LOG(ERROR) << "================== server_config ====================";
+ RunVerification(verifier.get(), hostname, port,
+ server_config.substr(1, string::npos), quic_version,
+ chlo_hash, certs, signature, false);
// An ECDSA signature is DER-encoded. Corrupt the last byte so that the
// signature can still be DER-decoded correctly.
string corrupt_signature = signature;
corrupt_signature[corrupt_signature.size() - 1] += 1;
- RunVerification(verifier.get(), hostname, server_config, certs,
- corrupt_signature, false);
+ LOG(ERROR) << "================= corrupt signature =======================";
+ RunVerification(verifier.get(), hostname, port, server_config, quic_version,
+ chlo_hash, certs, corrupt_signature, false);
// Prepending a "1" makes the DER invalid.
const string bad_der_signature1 = "1" + signature;
- RunVerification(verifier.get(), hostname, server_config, certs,
- bad_der_signature1, false);
+ LOG(ERROR) << "=========================bad der signature ===============";
+ RunVerification(verifier.get(), hostname, port, server_config, quic_version,
+ chlo_hash, certs, bad_der_signature1, false);
vector<string> wrong_certs;
for (size_t i = 1; i < certs.size(); i++) {
wrong_certs.push_back(certs[i]);
}
- RunVerification(verifier.get(), hostname, server_config, wrong_certs,
- signature, false);
+ LOG(ERROR) << "==================== wrong certs =========================";
+ RunVerification(verifier.get(), hostname, port, server_config, quic_version,
+ chlo_hash, wrong_certs, signature, false);
}
}
diff --git a/chromium/net/quic/crypto/proof_verifier.h b/chromium/net/quic/crypto/proof_verifier.h
index 0ec346aeb13..be6f9e7c720 100644
--- a/chromium/net/quic/crypto/proof_verifier.h
+++ b/chromium/net/quic/crypto/proof_verifier.h
@@ -10,6 +10,7 @@
#include "base/memory/scoped_ptr.h"
#include "net/base/net_export.h"
+#include "net/quic/quic_protocol.h"
#include "net/quic/quic_types.h"
namespace net {
@@ -74,7 +75,10 @@ class NET_EXPORT_PRIVATE ProofVerifier {
// The signature uses SHA-256 as the hash function and PSS padding in the
// case of RSA.
virtual QuicAsyncStatus VerifyProof(const std::string& hostname,
+ const uint16_t port,
const std::string& server_config,
+ QuicVersion quic_version,
+ base::StringPiece chlo_hash,
const std::vector<std::string>& certs,
const std::string& cert_sct,
const std::string& signature,
diff --git a/chromium/net/quic/crypto/proof_verifier_chromium.cc b/chromium/net/quic/crypto/proof_verifier_chromium.cc
index e9191a76c2b..044c694b0ab 100644
--- a/chromium/net/quic/crypto/proof_verifier_chromium.cc
+++ b/chromium/net/quic/crypto/proof_verifier_chromium.cc
@@ -23,6 +23,7 @@
#include "net/cert/cert_verifier.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verifier.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
@@ -62,7 +63,10 @@ class ProofVerifierChromium::Job {
// Starts the proof verification. If |QUIC_PENDING| is returned, then
// |callback| will be invoked asynchronously when the verification completes.
QuicAsyncStatus VerifyProof(const std::string& hostname,
+ const uint16_t port,
const std::string& server_config,
+ QuicVersion quic_version,
+ base::StringPiece chlo_hash,
const std::vector<std::string>& certs,
const std::string& cert_sct,
const std::string& signature,
@@ -83,6 +87,8 @@ class ProofVerifierChromium::Job {
int DoVerifyCertComplete(int result);
bool VerifySignature(const std::string& signed_data,
+ QuicVersion quic_version,
+ StringPiece chlo_hash,
const std::string& signature,
const std::string& cert);
@@ -101,6 +107,8 @@ class ProofVerifierChromium::Job {
// |hostname| specifies the hostname for which |certs| is a valid chain.
std::string hostname_;
+ // |port| specifies the target port for the connection.
+ uint16_t port_;
scoped_ptr<ProofVerifierCallback> callback_;
scoped_ptr<ProofVerifyDetailsChromium> verify_details_;
@@ -153,7 +161,10 @@ ProofVerifierChromium::Job::~Job() {
QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof(
const string& hostname,
+ const uint16_t port,
const string& server_config,
+ QuicVersion quic_version,
+ StringPiece chlo_hash,
const vector<string>& certs,
const std::string& cert_sct,
const string& signature,
@@ -207,7 +218,8 @@ QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof(
// We call VerifySignature first to avoid copying of server_config and
// signature.
- if (!VerifySignature(server_config, signature, certs[0])) {
+ if (!VerifySignature(server_config, quic_version, chlo_hash, signature,
+ certs[0])) {
*error_details = "Failed to verify signature of server config";
DLOG(WARNING) << *error_details;
verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
@@ -216,6 +228,7 @@ QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof(
}
hostname_ = hostname;
+ port_ = port;
next_state_ = STATE_VERIFY_CERT;
switch (DoLoop(OK)) {
@@ -284,24 +297,42 @@ int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) {
const CertVerifyResult& cert_verify_result =
verify_details_->cert_verify_result;
const CertStatus cert_status = cert_verify_result.cert_status;
- if (result == OK && policy_enforcer_ &&
- (cert_verify_result.cert_status & CERT_STATUS_IS_EV)) {
- if (!policy_enforcer_->DoesConformToCTEVPolicy(
- cert_verify_result.verified_cert.get(),
- SSLConfigService::GetEVCertsWhitelist().get(),
- verify_details_->ct_verify_result, net_log_)) {
- verify_details_->cert_verify_result.cert_status |=
- CERT_STATUS_CT_COMPLIANCE_FAILED;
- verify_details_->cert_verify_result.cert_status &= ~CERT_STATUS_IS_EV;
+ verify_details_->ct_verify_result.ct_policies_applied =
+ (result == OK && policy_enforcer_ != nullptr);
+ verify_details_->ct_verify_result.ev_policy_compliance =
+ ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
+ if (result == OK && policy_enforcer_) {
+ if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) {
+ ct::EVPolicyCompliance ev_policy_compliance =
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ cert_verify_result.verified_cert.get(),
+ SSLConfigService::GetEVCertsWhitelist().get(),
+ verify_details_->ct_verify_result.verified_scts, net_log_);
+ verify_details_->ct_verify_result.ev_policy_compliance =
+ ev_policy_compliance;
+ if (ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY &&
+ ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST &&
+ ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS) {
+ verify_details_->cert_verify_result.cert_status |=
+ CERT_STATUS_CT_COMPLIANCE_FAILED;
+ verify_details_->cert_verify_result.cert_status &= ~CERT_STATUS_IS_EV;
+ }
}
+
+ verify_details_->ct_verify_result.cert_policy_compliance =
+ policy_enforcer_->DoesConformToCertPolicy(
+ cert_verify_result.verified_cert.get(),
+ verify_details_->ct_verify_result.verified_scts, net_log_);
}
- // TODO(estark): replace 0 below with the port of the connection.
if (transport_security_state_ &&
(result == OK ||
(IsCertificateError(result) && IsCertStatusMinorError(cert_status))) &&
!transport_security_state_->CheckPublicKeyPins(
- HostPortPair(hostname_, 0),
+ HostPortPair(hostname_, port_),
cert_verify_result.is_issued_by_known_root,
cert_verify_result.public_key_hashes, cert_.get(),
cert_verify_result.verified_cert.get(),
@@ -323,6 +354,8 @@ int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) {
}
bool ProofVerifierChromium::Job::VerifySignature(const string& signed_data,
+ QuicVersion quic_version,
+ StringPiece chlo_hash,
const string& signature,
const string& cert) {
StringPiece spki;
@@ -351,27 +384,11 @@ bool ProofVerifierChromium::Job::VerifySignature(const string& signed_data,
return false;
}
} else if (type == X509Certificate::kPublicKeyTypeECDSA) {
- // This is the algorithm ID for ECDSA with SHA-256. Parameters are ABSENT.
- // RFC 5758:
- // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
- // ...
- // When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or
- // ecdsa-with-SHA512 algorithm identifier appears in the algorithm field
- // as an AlgorithmIdentifier, the encoding MUST omit the parameters
- // field. That is, the AlgorithmIdentifier SHALL be a SEQUENCE of one
- // component, the OID ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-
- // SHA384, or ecdsa-with-SHA512.
- // See also RFC 5480, Appendix A.
- static const uint8_t kECDSAWithSHA256AlgorithmID[] = {
- 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
- };
-
- if (!verifier.VerifyInit(
- kECDSAWithSHA256AlgorithmID, sizeof(kECDSAWithSHA256AlgorithmID),
- reinterpret_cast<const uint8_t*>(signature.data()),
- signature.size(), reinterpret_cast<const uint8_t*>(spki.data()),
- spki.size())) {
+ if (!verifier.VerifyInit(crypto::SignatureVerifier::ECDSA_SHA256,
+ reinterpret_cast<const uint8_t*>(signature.data()),
+ signature.size(),
+ reinterpret_cast<const uint8_t*>(spki.data()),
+ spki.size())) {
DLOG(WARNING) << "VerifyInit failed";
return false;
}
@@ -380,8 +397,20 @@ bool ProofVerifierChromium::Job::VerifySignature(const string& signed_data,
return false;
}
- verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(kProofSignatureLabel),
- sizeof(kProofSignatureLabel));
+ if (quic_version <= QUIC_VERSION_30) {
+ verifier.VerifyUpdate(
+ reinterpret_cast<const uint8_t*>(kProofSignatureLabelOld),
+ sizeof(kProofSignatureLabelOld));
+ } else {
+ verifier.VerifyUpdate(
+ reinterpret_cast<const uint8_t*>(kProofSignatureLabel),
+ sizeof(kProofSignatureLabel));
+ uint32_t len = chlo_hash.length();
+ verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(&len), sizeof(len));
+ verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(chlo_hash.data()),
+ len);
+ }
+
verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(signed_data.data()),
signed_data.size());
@@ -410,7 +439,10 @@ ProofVerifierChromium::~ProofVerifierChromium() {
QuicAsyncStatus ProofVerifierChromium::VerifyProof(
const std::string& hostname,
+ const uint16_t port,
const std::string& server_config,
+ QuicVersion quic_version,
+ base::StringPiece chlo_hash,
const std::vector<std::string>& certs,
const std::string& cert_sct,
const std::string& signature,
@@ -428,9 +460,9 @@ QuicAsyncStatus ProofVerifierChromium::VerifyProof(
new Job(this, cert_verifier_, ct_policy_enforcer_,
transport_security_state_, cert_transparency_verifier_,
chromium_context->cert_verify_flags, chromium_context->net_log));
- QuicAsyncStatus status =
- job->VerifyProof(hostname, server_config, certs, cert_sct, signature,
- error_details, verify_details, callback);
+ QuicAsyncStatus status = job->VerifyProof(
+ hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct,
+ signature, error_details, verify_details, callback);
if (status == QUIC_PENDING) {
active_jobs_.insert(job.release());
}
diff --git a/chromium/net/quic/crypto/proof_verifier_chromium.h b/chromium/net/quic/crypto/proof_verifier_chromium.h
index fd7f345a705..eef604d2f2b 100644
--- a/chromium/net/quic/crypto/proof_verifier_chromium.h
+++ b/chromium/net/quic/crypto/proof_verifier_chromium.h
@@ -66,7 +66,10 @@ class NET_EXPORT_PRIVATE ProofVerifierChromium : public ProofVerifier {
// ProofVerifier interface
QuicAsyncStatus VerifyProof(const std::string& hostname,
+ const uint16_t port,
const std::string& server_config,
+ QuicVersion quic_version,
+ base::StringPiece chlo_hash,
const std::vector<std::string>& certs,
const std::string& cert_sct,
const std::string& signature,
diff --git a/chromium/net/quic/crypto/proof_verifier_chromium_test.cc b/chromium/net/quic/crypto/proof_verifier_chromium_test.cc
index 96c40138080..bc2d27ff64e 100644
--- a/chromium/net/quic/crypto/proof_verifier_chromium_test.cc
+++ b/chromium/net/quic/crypto/proof_verifier_chromium_test.cc
@@ -12,6 +12,7 @@
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_log_verifier.h"
#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_serialization.h"
#include "net/cert/ct_verify_result.h"
#include "net/cert/mock_cert_verifier.h"
@@ -56,13 +57,14 @@ class FailsTestCTPolicyEnforcer : public CTPolicyEnforcer {
FailsTestCTPolicyEnforcer() {}
~FailsTestCTPolicyEnforcer() override {}
- bool DoesConformToCTEVPolicy(X509Certificate* cert,
- const ct::EVCertsWhitelist* ev_whitelist,
- const ct::CTVerifyResult& ct_result,
- const BoundNetLog& net_log) override {
+ ct::EVPolicyCompliance DoesConformToCTEVPolicy(
+ X509Certificate* cert,
+ const ct::EVCertsWhitelist* ev_whitelist,
+ const ct::SCTList& verified_scts,
+ const BoundNetLog& net_log) override {
ADD_FAILURE() << "CTPolicyEnforcer::DoesConformToCTEVPolicy() should "
<< "not be called";
- return false;
+ return ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
}
};
@@ -73,11 +75,13 @@ class MockCTPolicyEnforcer : public CTPolicyEnforcer {
MockCTPolicyEnforcer(bool is_ev) : is_ev_(is_ev) {}
~MockCTPolicyEnforcer() override {}
- bool DoesConformToCTEVPolicy(X509Certificate* cert,
- const ct::EVCertsWhitelist* ev_whitelist,
- const ct::CTVerifyResult& ct_result,
- const BoundNetLog& net_log) override {
- return is_ev_;
+ ct::EVPolicyCompliance DoesConformToCTEVPolicy(
+ X509Certificate* cert,
+ const ct::EVCertsWhitelist* ev_whitelist,
+ const ct::SCTList& verified_scts,
+ const BoundNetLog& net_log) override {
+ return is_ev_ ? ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS
+ : ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS;
}
private:
@@ -97,6 +101,7 @@ class DummyProofVerifierCallback : public ProofVerifierCallback {
};
const char kTestHostname[] = "test.example.com";
+const uint16_t kTestPort = 8443;
const char kTestConfig[] = "server config bytes";
const char kLogDescription[] = "somelog";
@@ -183,41 +188,15 @@ class ProofVerifierChromiumTest : public ::testing::Test {
certs->push_back(der_bytes);
}
- std::string GetSCTListForTesting() {
- const std::string sct = ct::GetTestSignedCertificateTimestamp();
- std::string sct_list;
- ct::EncodeSCTListForTesting(sct, &sct_list);
- return sct_list;
- }
-
- std::string GetCorruptSCTListForTesting() {
- std::string sct = ct::GetTestSignedCertificateTimestamp();
- sct[15] = 't'; // Corrupt a byte inside SCT.
- std::string sct_list;
- ct::EncodeSCTListForTesting(sct, &sct_list);
- return sct_list;
- }
-
- bool CheckForSingleVerifiedSCTInResult(const ct::CTVerifyResult& result) {
- return (result.verified_scts.size() == 1U) && result.invalid_scts.empty() &&
- result.unknown_logs_scts.empty() &&
- result.verified_scts[0]->log_description == kLogDescription;
- }
-
- bool CheckForSCTOrigin(const ct::CTVerifyResult& result,
- ct::SignedCertificateTimestamp::Origin origin) {
- return (result.verified_scts.size() > 0) &&
- (result.verified_scts[0]->origin == origin);
- }
-
void CheckSCT(bool sct_expected_ok) {
ProofVerifyDetailsChromium* proof_details =
reinterpret_cast<ProofVerifyDetailsChromium*>(details_.get());
const ct::CTVerifyResult& ct_verify_result =
proof_details->ct_verify_result;
if (sct_expected_ok) {
- ASSERT_TRUE(CheckForSingleVerifiedSCTInResult(ct_verify_result));
- ASSERT_TRUE(CheckForSCTOrigin(
+ ASSERT_TRUE(ct::CheckForSingleVerifiedSCTInResult(ct_verify_result,
+ kLogDescription));
+ ASSERT_TRUE(ct::CheckForSCTOrigin(
ct_verify_result,
ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION));
} else {
@@ -244,8 +223,9 @@ TEST_F(ProofVerifierChromiumTest, FailsIfCertFails) {
scoped_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestConfig, certs_, "", GetTestSignature(),
- verify_context_.get(), &error_details_, &details_, callback.get());
+ kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "",
+ GetTestSignature(), verify_context_.get(), &error_details_, &details_,
+ callback.get());
ASSERT_EQ(QUIC_FAILURE, status);
}
@@ -261,8 +241,9 @@ TEST_F(ProofVerifierChromiumTest, ValidSCTList) {
scoped_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestConfig, certs_, GetSCTListForTesting(), "",
- verify_context_.get(), &error_details_, &details_, callback.get());
+ kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_,
+ ct::GetSCTListForTesting(), "", verify_context_.get(), &error_details_,
+ &details_, callback.get());
ASSERT_EQ(QUIC_FAILURE, status);
CheckSCT(/*sct_expected_ok=*/true);
}
@@ -279,8 +260,9 @@ TEST_F(ProofVerifierChromiumTest, InvalidSCTList) {
scoped_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestConfig, certs_, GetCorruptSCTListForTesting(), "",
- verify_context_.get(), &error_details_, &details_, callback.get());
+ kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_,
+ ct::GetSCTListWithInvalidSCT(), "", verify_context_.get(),
+ &error_details_, &details_, callback.get());
ASSERT_EQ(QUIC_FAILURE, status);
CheckSCT(/*sct_expected_ok=*/false);
}
@@ -295,8 +277,9 @@ TEST_F(ProofVerifierChromiumTest, FailsIfSignatureFails) {
scoped_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestConfig, certs_, "", kTestConfig,
- verify_context_.get(), &error_details_, &details_, callback.get());
+ kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "",
+ kTestConfig, verify_context_.get(), &error_details_, &details_,
+ callback.get());
ASSERT_EQ(QUIC_FAILURE, status);
}
@@ -319,8 +302,9 @@ TEST_F(ProofVerifierChromiumTest, PreservesEVIfNoPolicy) {
scoped_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestConfig, certs_, "", GetTestSignature(),
- verify_context_.get(), &error_details_, &details_, callback.get());
+ kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "",
+ GetTestSignature(), verify_context_.get(), &error_details_, &details_,
+ callback.get());
ASSERT_EQ(QUIC_SUCCESS, status);
ASSERT_TRUE(details_.get());
@@ -351,8 +335,9 @@ TEST_F(ProofVerifierChromiumTest, PreservesEVIfAllowed) {
scoped_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestConfig, certs_, "", GetTestSignature(),
- verify_context_.get(), &error_details_, &details_, callback.get());
+ kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "",
+ GetTestSignature(), verify_context_.get(), &error_details_, &details_,
+ callback.get());
ASSERT_EQ(QUIC_SUCCESS, status);
ASSERT_TRUE(details_.get());
@@ -383,8 +368,9 @@ TEST_F(ProofVerifierChromiumTest, StripsEVIfNotAllowed) {
scoped_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestConfig, certs_, "", GetTestSignature(),
- verify_context_.get(), &error_details_, &details_, callback.get());
+ kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "",
+ GetTestSignature(), verify_context_.get(), &error_details_, &details_,
+ callback.get());
ASSERT_EQ(QUIC_SUCCESS, status);
ASSERT_TRUE(details_.get());
@@ -416,8 +402,9 @@ TEST_F(ProofVerifierChromiumTest, IgnoresPolicyEnforcerIfNotEV) {
scoped_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestConfig, certs_, "", GetTestSignature(),
- verify_context_.get(), &error_details_, &details_, callback.get());
+ kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "",
+ GetTestSignature(), verify_context_.get(), &error_details_, &details_,
+ callback.get());
ASSERT_EQ(QUIC_SUCCESS, status);
ASSERT_TRUE(details_.get());
diff --git a/chromium/net/quic/crypto/properties_based_quic_server_info_test.cc b/chromium/net/quic/crypto/properties_based_quic_server_info_test.cc
index 2e9c2d371a2..f9cb681310e 100644
--- a/chromium/net/quic/crypto/properties_based_quic_server_info_test.cc
+++ b/chromium/net/quic/crypto/properties_based_quic_server_info_test.cc
@@ -18,6 +18,8 @@ namespace test {
namespace {
const std::string kServerConfigA("server_config_a");
const std::string kSourceAddressTokenA("source_address_token_a");
+const std::string kCertSCTA("cert_sct_a");
+const std::string kChloHashA("chlo_hash_a");
const std::string kServerConfigSigA("server_config_sig_a");
const std::string kCertA("cert_a");
const std::string kCertB("cert_b");
@@ -39,6 +41,8 @@ class PropertiesBasedQuicServerInfoTest : public ::testing::Test {
state->server_config = kServerConfigA;
state->source_address_token = kSourceAddressTokenA;
state->server_config_sig = kServerConfigSigA;
+ state->cert_sct = kCertSCTA;
+ state->chlo_hash = kChloHashA;
state->certs.push_back(kCertA);
EXPECT_TRUE(server_info_.IsReadyToPersist());
server_info_.Persist();
@@ -51,6 +55,8 @@ class PropertiesBasedQuicServerInfoTest : public ::testing::Test {
void VerifyInitialData(const QuicServerInfo::State& state) {
EXPECT_EQ(kServerConfigA, state.server_config);
EXPECT_EQ(kSourceAddressTokenA, state.source_address_token);
+ EXPECT_EQ(kCertSCTA, state.cert_sct);
+ EXPECT_EQ(kChloHashA, state.chlo_hash);
EXPECT_EQ(kServerConfigSigA, state.server_config_sig);
EXPECT_EQ(kCertA, state.certs[0]);
}
diff --git a/chromium/net/quic/crypto/quic_compressed_certs_cache.cc b/chromium/net/quic/crypto/quic_compressed_certs_cache.cc
new file mode 100644
index 00000000000..92d66d2cad4
--- /dev/null
+++ b/chromium/net/quic/crypto/quic_compressed_certs_cache.cc
@@ -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.
+
+#include "net/quic/crypto/quic_compressed_certs_cache.h"
+
+using std::string;
+
+namespace net {
+
+namespace {
+
+// Inline helper function for extending a 64-bit |seed| in-place with a 64-bit
+// |value|. Based on Boost's hash_combine function.
+inline void hash_combine(uint64_t* seed, const uint64_t& val) {
+ (*seed) ^= val + 0x9e3779b9 + ((*seed) << 6) + ((*seed) >> 2);
+}
+
+} // namespace
+
+QuicCompressedCertsCache::UncompressedCerts::UncompressedCerts() {}
+
+QuicCompressedCertsCache::UncompressedCerts::UncompressedCerts(
+ const scoped_refptr<ProofSource::Chain>& chain,
+ const string* client_common_set_hashes,
+ const string* client_cached_cert_hashes)
+ : chain(chain),
+ client_common_set_hashes(client_common_set_hashes),
+ client_cached_cert_hashes(client_cached_cert_hashes) {}
+
+QuicCompressedCertsCache::UncompressedCerts::~UncompressedCerts() {}
+
+QuicCompressedCertsCache::CachedCerts::CachedCerts() {}
+
+QuicCompressedCertsCache::CachedCerts::CachedCerts(
+ const UncompressedCerts& uncompressed_certs,
+ const string& compressed_cert)
+ : chain_(uncompressed_certs.chain),
+ client_common_set_hashes_(*uncompressed_certs.client_common_set_hashes),
+ client_cached_cert_hashes_(*uncompressed_certs.client_cached_cert_hashes),
+ compressed_cert_(compressed_cert) {}
+
+QuicCompressedCertsCache::CachedCerts::CachedCerts(const CachedCerts& other) =
+ default;
+
+QuicCompressedCertsCache::CachedCerts::~CachedCerts() {}
+
+bool QuicCompressedCertsCache::CachedCerts::MatchesUncompressedCerts(
+ const UncompressedCerts& uncompressed_certs) const {
+ return (client_common_set_hashes_ ==
+ *uncompressed_certs.client_common_set_hashes &&
+ client_cached_cert_hashes_ ==
+ *uncompressed_certs.client_cached_cert_hashes &&
+ chain_ == uncompressed_certs.chain);
+}
+
+const string* QuicCompressedCertsCache::CachedCerts::compressed_cert() const {
+ return &compressed_cert_;
+}
+
+QuicCompressedCertsCache::QuicCompressedCertsCache(int64_t max_num_certs)
+ : certs_cache_(max_num_certs) {}
+
+QuicCompressedCertsCache::~QuicCompressedCertsCache() {
+ // Underlying cache must be cleared before destruction.
+ certs_cache_.Clear();
+}
+
+const string* QuicCompressedCertsCache::GetCompressedCert(
+ const scoped_refptr<ProofSource::Chain>& chain,
+ const string& client_common_set_hashes,
+ const string& client_cached_cert_hashes) {
+ UncompressedCerts uncompressed_certs(chain, &client_common_set_hashes,
+ &client_cached_cert_hashes);
+
+ 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();
+ }
+ }
+ return nullptr;
+}
+
+void QuicCompressedCertsCache::Insert(
+ const scoped_refptr<ProofSource::Chain>& chain,
+ const string& client_common_set_hashes,
+ const string& client_cached_cert_hashes,
+ const string& compressed_cert) {
+ UncompressedCerts uncompressed_certs(chain, &client_common_set_hashes,
+ &client_cached_cert_hashes);
+
+ uint64_t key = ComputeUncompressedCertsHash(uncompressed_certs);
+
+ // Insert one unit to the cache.
+ certs_cache_.Put(key, CachedCerts(uncompressed_certs, compressed_cert));
+}
+
+size_t QuicCompressedCertsCache::MaxSize() {
+ return certs_cache_.max_size();
+}
+
+size_t QuicCompressedCertsCache::Size() {
+ return certs_cache_.size();
+}
+
+uint64_t QuicCompressedCertsCache::ComputeUncompressedCertsHash(
+ const UncompressedCerts& uncompressed_certs) {
+ uint64_t hash =
+ std::hash<string>()(*uncompressed_certs.client_common_set_hashes);
+ uint64_t h =
+ std::hash<string>()(*uncompressed_certs.client_cached_cert_hashes);
+ hash_combine(&hash, h);
+
+ hash_combine(&hash,
+ reinterpret_cast<uint64_t>(uncompressed_certs.chain.get()));
+ return hash;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/crypto/quic_compressed_certs_cache.h b/chromium/net/quic/crypto/quic_compressed_certs_cache.h
new file mode 100644
index 00000000000..fe120f6bff6
--- /dev/null
+++ b/chromium/net/quic/crypto/quic_compressed_certs_cache.h
@@ -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.
+
+#ifndef NET_QUIC_CRYPTO_QUIC_COMPRESSED_CERTS_CACHE_H_
+#define NET_QUIC_CRYPTO_QUIC_COMPRESSED_CERTS_CACHE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/containers/mru_cache.h"
+#include "base/memory/ref_counted.h"
+#include "net/quic/crypto/proof_source.h"
+
+namespace net {
+
+// QuicCompressedCertsCache is a cache to track most recently compressed certs.
+class NET_EXPORT_PRIVATE QuicCompressedCertsCache {
+ public:
+ explicit QuicCompressedCertsCache(int64_t max_num_certs);
+ ~QuicCompressedCertsCache();
+
+ // Returns the pointer to the cached compressed cert if
+ // |chain, client_common_set_hashes, client_cached_cert_hashes| hits cache.
+ // 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 std::string& client_common_set_hashes,
+ const std::string& client_cached_cert_hashes);
+
+ // Inserts the specified
+ // |chain, client_common_set_hashes,
+ // 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,
+ const std::string& client_common_set_hashes,
+ const std::string& client_cached_cert_hashes,
+ const std::string& compressed_cert);
+
+ // Returns max number of cache entries the cache can carry.
+ size_t MaxSize();
+
+ // Returns current number of cache entries in the cache.
+ size_t Size();
+
+ // Default size of the QuicCompressedCertsCache per server side investigation.
+ static const size_t kQuicCompressedCertsCacheSize = 225;
+
+ private:
+ // A wrapper of the tuple:
+ // |chain, client_common_set_hashes, client_cached_cert_hashes|
+ // 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 scoped_refptr<ProofSource::Chain> chain;
+ const std::string* client_common_set_hashes;
+ const std::string* client_cached_cert_hashes;
+ };
+
+ // Certs stored by QuicCompressedCertsCache where uncompressed certs data is
+ // used to identify the uncompressed representation of certs and
+ // |compressed_cert| is the cached compressed representation.
+ class CachedCerts {
+ public:
+ CachedCerts();
+ CachedCerts(const UncompressedCerts& uncompressed_certs,
+ const std::string& compressed_cert);
+ CachedCerts(const CachedCerts& other);
+
+ ~CachedCerts();
+
+ // Returns true if the |uncompressed_certs| matches uncompressed
+ // representation of this cert.
+ bool MatchesUncompressedCerts(
+ const UncompressedCerts& uncompressed_certs) const;
+
+ const std::string* compressed_cert() const;
+
+ private:
+ // Uncompressed certs data.
+ scoped_refptr<ProofSource::Chain> chain_;
+ const std::string client_common_set_hashes_;
+ const std::string client_cached_cert_hashes_;
+
+ // Cached compressed representation derived from uncompressed certs.
+ const std::string compressed_cert_;
+ };
+
+ // Computes a uint64_t hash for |uncompressed_certs|.
+ uint64_t ComputeUncompressedCertsHash(
+ const UncompressedCerts& uncompressed_certs);
+
+ // 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_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CRYPTO_QUIC_COMPRESSED_CERTS_CACHE_H_
diff --git a/chromium/net/quic/crypto/quic_compressed_certs_cache_test.cc b/chromium/net/quic/crypto/quic_compressed_certs_cache_test.cc
new file mode 100644
index 00000000000..d444c49d4ca
--- /dev/null
+++ b/chromium/net/quic/crypto/quic_compressed_certs_cache_test.cc
@@ -0,0 +1,91 @@
+// 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/crypto/quic_compressed_certs_cache.h"
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "net/quic/crypto/cert_compressor.h"
+#include "net/quic/test_tools/crypto_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+using std::vector;
+
+namespace net {
+
+namespace test {
+
+namespace {
+
+class QuicCompressedCertsCacheTest : public testing::Test {
+ public:
+ QuicCompressedCertsCacheTest()
+ : certs_cache_(QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {}
+
+ protected:
+ QuicCompressedCertsCache certs_cache_;
+};
+
+TEST_F(QuicCompressedCertsCacheTest, CacheHit) {
+ vector<string> certs = {"leaf cert", "intermediate cert", "root cert"};
+ scoped_refptr<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);
+
+ const string* cached_value =
+ certs_cache_.GetCompressedCert(chain, common_certs, cached_certs);
+ ASSERT_NE(nullptr, cached_value);
+ EXPECT_EQ(*cached_value, compressed);
+}
+
+TEST_F(QuicCompressedCertsCacheTest, CacheMiss) {
+ vector<string> certs = {"leaf cert", "intermediate cert", "root cert"};
+ scoped_refptr<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(chain2, common_certs, cached_certs));
+}
+
+TEST_F(QuicCompressedCertsCacheTest, CacheMissDueToEviction) {
+ // Test cache returns a miss when a queried uncompressed certs was cached but
+ // then evicted.
+ vector<string> certs = {"leaf cert", "intermediate cert", "root cert"};
+ scoped_refptr<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);
+
+ // Insert another kQuicCompressedCertsCacheSize certs to evict the first
+ // cached cert.
+ 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));
+ }
+ EXPECT_EQ(certs_cache_.MaxSize(), certs_cache_.Size());
+
+ EXPECT_EQ(nullptr,
+ certs_cache_.GetCompressedCert(chain, common_certs, cached_certs));
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/crypto/quic_crypto_client_config.cc b/chromium/net/quic/crypto/quic_crypto_client_config.cc
index febb1a0e6da..a6906a76672 100644
--- a/chromium/net/quic/crypto/quic_crypto_client_config.cc
+++ b/chromium/net/quic/crypto/quic_crypto_client_config.cc
@@ -18,7 +18,9 @@
#include "net/quic/crypto/p256_key_exchange.h"
#include "net/quic/crypto/proof_verifier.h"
#include "net/quic/crypto/quic_encrypter.h"
+#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_bug_tracker.h"
+#include "net/quic/quic_flags.h"
#include "net/quic/quic_utils.h"
using base::StringPiece;
@@ -189,9 +191,10 @@ void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() {
void QuicCryptoClientConfig::CachedState::SetProof(const vector<string>& certs,
StringPiece cert_sct,
+ StringPiece chlo_hash,
StringPiece signature) {
- bool has_changed =
- signature != server_config_sig_ || certs_.size() != certs.size();
+ bool has_changed = signature != server_config_sig_ ||
+ chlo_hash != chlo_hash_ || certs_.size() != certs.size();
if (!has_changed) {
for (size_t i = 0; i < certs_.size(); i++) {
@@ -210,6 +213,7 @@ void QuicCryptoClientConfig::CachedState::SetProof(const vector<string>& certs,
SetProofInvalid();
certs_ = certs;
cert_sct_ = cert_sct.as_string();
+ chlo_hash_ = chlo_hash.as_string();
server_config_sig_ = signature.as_string();
}
@@ -218,6 +222,7 @@ void QuicCryptoClientConfig::CachedState::Clear() {
source_address_token_.clear();
certs_.clear();
cert_sct_.clear();
+ chlo_hash_.clear();
server_config_sig_.clear();
server_config_valid_ = false;
proof_verify_details_.reset();
@@ -231,6 +236,7 @@ void QuicCryptoClientConfig::CachedState::ClearProof() {
SetProofInvalid();
certs_.clear();
cert_sct_.clear();
+ chlo_hash_.clear();
server_config_sig_.clear();
}
@@ -247,7 +253,8 @@ bool QuicCryptoClientConfig::CachedState::Initialize(
StringPiece server_config,
StringPiece source_address_token,
const vector<string>& certs,
- const string& cert_sct,
+ StringPiece cert_sct,
+ StringPiece chlo_hash,
StringPiece signature,
QuicWallTime now) {
DCHECK(server_config_.empty());
@@ -267,8 +274,9 @@ bool QuicCryptoClientConfig::CachedState::Initialize(
signature.CopyToString(&server_config_sig_);
source_address_token.CopyToString(&source_address_token_);
+ cert_sct.CopyToString(&cert_sct_);
+ chlo_hash.CopyToString(&chlo_hash_);
certs_ = certs;
- cert_sct_ = cert_sct;
return true;
}
@@ -289,6 +297,10 @@ const string& QuicCryptoClientConfig::CachedState::cert_sct() const {
return cert_sct_;
}
+const string& QuicCryptoClientConfig::CachedState::chlo_hash() const {
+ return chlo_hash_;
+}
+
const string& QuicCryptoClientConfig::CachedState::signature() const {
return server_config_sig_;
}
@@ -328,6 +340,7 @@ void QuicCryptoClientConfig::CachedState::InitializeFrom(
source_address_token_ = other.source_address_token_;
certs_ = other.certs_;
cert_sct_ = other.cert_sct_;
+ chlo_hash_ = other.chlo_hash_;
server_config_sig_ = other.server_config_sig_;
server_config_valid_ = other.server_config_valid_;
server_designated_connection_ids_ = other.server_designated_connection_ids_;
@@ -371,7 +384,6 @@ void QuicCryptoClientConfig::SetDefaults() {
if (ChaCha20Poly1305Rfc7539Encrypter::IsSupported()) {
aead.push_back(kCC20);
}
- aead.push_back(kCC12);
aead.push_back(kAESG);
disable_ecdsa_ = false;
@@ -404,6 +416,7 @@ void QuicCryptoClientConfig::FillInchoateClientHello(
const QuicServerId& server_id,
const QuicVersion preferred_version,
const CachedState* cached,
+ QuicRandom* rand,
QuicCryptoNegotiatedParameters* out_params,
CryptoHandshakeMessage* out) const {
out->set_tag(kCHLO);
@@ -420,6 +433,10 @@ void QuicCryptoClientConfig::FillInchoateClientHello(
out->SetStringPiece(kUAID, user_agent_id_);
}
+ char proof_nonce[32];
+ rand->RandBytes(proof_nonce, arraysize(proof_nonce));
+ out->SetStringPiece(kNONP, StringPiece(proof_nonce, arraysize(proof_nonce)));
+
// Even though this is an inchoate CHLO, send the SCID so that
// the STK can be validated by the server.
const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
@@ -478,8 +495,8 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
string* error_details) const {
DCHECK(error_details != nullptr);
- FillInchoateClientHello(server_id, preferred_version, cached, out_params,
- out);
+ FillInchoateClientHello(server_id, preferred_version, cached, rand,
+ out_params, out);
const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
if (!scfg) {
@@ -645,9 +662,9 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
scoped_ptr<char[]> output(new char[encrypted_len]);
size_t output_size = 0;
if (!crypters.encrypter->EncryptPacket(
- 0 /* packet number */, StringPiece() /* associated data */,
- cetv_plaintext.AsStringPiece(), output.get(), &output_size,
- encrypted_len)) {
+ 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;
}
@@ -683,11 +700,12 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
hkdf_input.append(out_params->hkdf_input_suffix);
- if (!CryptoUtils::DeriveKeys(
- out_params->initial_premaster_secret, out_params->aead,
- out_params->client_nonce, out_params->server_nonce, hkdf_input,
- Perspective::IS_CLIENT, &out_params->initial_crypters,
- nullptr /* subkey secret */)) {
+ string* subkey_secret = &out_params->initial_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,
+ &out_params->initial_crypters, subkey_secret)) {
*error_details = "Symmetric key setup failed";
return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
}
@@ -698,7 +716,8 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
QuicErrorCode QuicCryptoClientConfig::CacheNewServerConfig(
const CryptoHandshakeMessage& message,
QuicWallTime now,
- const QuicVersion version,
+ QuicVersion version,
+ StringPiece chlo_hash,
const vector<string>& cached_certs,
CachedState* cached,
string* error_details) {
@@ -740,7 +759,7 @@ QuicErrorCode QuicCryptoClientConfig::CacheNewServerConfig(
if (version > QUIC_VERSION_29) {
message.GetStringPiece(kCertificateSCTTag, &cert_sct);
}
- cached->SetProof(certs, cert_sct, proof);
+ cached->SetProof(certs, cert_sct, chlo_hash, proof);
} else {
// Secure QUIC: clear existing proof as we have been sent a new SCFG
// without matching proof/certs.
@@ -764,6 +783,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
const CryptoHandshakeMessage& rej,
QuicWallTime now,
const QuicVersion version,
+ StringPiece chlo_hash,
CachedState* cached,
QuicCryptoNegotiatedParameters* out_params,
string* error_details) {
@@ -774,8 +794,9 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
return QUIC_CRYPTO_INTERNAL_ERROR;
}
- QuicErrorCode error = CacheNewServerConfig(
- rej, now, version, out_params->cached_certs, cached, error_details);
+ QuicErrorCode error =
+ CacheNewServerConfig(rej, now, version, chlo_hash,
+ out_params->cached_certs, cached, error_details);
if (error != QUIC_NO_ERROR) {
return error;
}
@@ -868,6 +889,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessServerConfigUpdate(
const CryptoHandshakeMessage& server_config_update,
QuicWallTime now,
const QuicVersion version,
+ StringPiece chlo_hash,
CachedState* cached,
QuicCryptoNegotiatedParameters* out_params,
string* error_details) {
@@ -877,7 +899,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessServerConfigUpdate(
*error_details = "ServerConfigUpdate must have kSCUP tag.";
return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
}
- return CacheNewServerConfig(server_config_update, now, version,
+ return CacheNewServerConfig(server_config_update, now, version, chlo_hash,
out_params->cached_certs, cached, error_details);
}
diff --git a/chromium/net/quic/crypto/quic_crypto_client_config.h b/chromium/net/quic/crypto/quic_crypto_client_config.h
index 34be5484c07..a0c35360da3 100644
--- a/chromium/net/quic/crypto/quic_crypto_client_config.h
+++ b/chromium/net/quic/crypto/quic_crypto_client_config.h
@@ -86,6 +86,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// SetProof stores a certificate chain and signature.
void SetProof(const std::vector<std::string>& certs,
base::StringPiece cert_sct,
+ base::StringPiece chlo_hash,
base::StringPiece signature);
// Clears all the data.
@@ -108,6 +109,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
const std::string& source_address_token() const;
const std::vector<std::string>& certs() const;
const std::string& cert_sct() const;
+ const std::string& chlo_hash() const;
const std::string& signature() const;
bool proof_valid() const;
uint64_t generation_counter() const;
@@ -146,10 +148,10 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// SetProofVerifyDetails takes ownership of |details|.
void SetProofVerifyDetails(ProofVerifyDetails* details);
- // Copy the |server_config_|, |source_address_token_|, |certs_| and
- // |server_config_sig_| from the |other|. The remaining fields,
- // |generation_counter_|, |proof_verify_details_|, and |scfg_| remain
- // unchanged.
+ // Copy the |server_config_|, |source_address_token_|, |certs_|,
+ // |cert_sct_|, |chlo_hash_| and |server_config_sig_| from the |other|. The
+ // remaining fields, |generation_counter_|, |proof_verify_details_|, and
+ // |scfg_| remain unchanged.
void InitializeFrom(const CachedState& other);
// Initializes this cached state based on the arguments provided.
@@ -157,7 +159,8 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
bool Initialize(base::StringPiece server_config,
base::StringPiece source_address_token,
const std::vector<std::string>& certs,
- const std::string& cert_sct,
+ base::StringPiece cert_sct,
+ base::StringPiece chlo_hash,
base::StringPiece signature,
QuicWallTime now);
@@ -167,6 +170,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
std::vector<std::string> certs_; // A list of certificates in leaf-first
// order.
std::string cert_sct_; // Signed timestamp of the leaf cert.
+ std::string chlo_hash_; // Hash of the CHLO message.
std::string server_config_sig_; // A signature of |server_config_|.
bool server_config_valid_; // True if |server_config_| is correctly
// signed and |certs_| has been
@@ -210,6 +214,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
void FillInchoateClientHello(const QuicServerId& server_id,
const QuicVersion preferred_version,
const CachedState* cached,
+ QuicRandom* rand,
QuicCryptoNegotiatedParameters* out_params,
CryptoHandshakeMessage* out) const;
@@ -247,6 +252,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
QuicErrorCode ProcessRejection(const CryptoHandshakeMessage& rej,
QuicWallTime now,
QuicVersion version,
+ base::StringPiece chlo_hash,
CachedState* cached,
QuicCryptoNegotiatedParameters* out_params,
std::string* error_details);
@@ -277,6 +283,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
const CryptoHandshakeMessage& server_update,
QuicWallTime now,
const QuicVersion version,
+ base::StringPiece chlo_hash,
CachedState* cached,
QuicCryptoNegotiatedParameters* out_params,
std::string* error_details);
@@ -333,6 +340,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
const CryptoHandshakeMessage& message,
QuicWallTime now,
const QuicVersion version,
+ base::StringPiece chlo_hash,
const std::vector<std::string>& cached_certs,
CachedState* cached,
std::string* error_details);
diff --git a/chromium/net/quic/crypto/quic_crypto_client_config_test.cc b/chromium/net/quic/crypto/quic_crypto_client_config_test.cc
index 2e6866ccb64..ec727e4a024 100644
--- a/chromium/net/quic/crypto/quic_crypto_client_config_test.cc
+++ b/chromium/net/quic/crypto/quic_crypto_client_config_test.cc
@@ -155,13 +155,17 @@ TEST(QuicCryptoClientConfigTest, InchoateChlo) {
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
QuicCryptoNegotiatedParameters params;
CryptoHandshakeMessage msg;
- QuicServerId server_id("www.google.com", 80, PRIVACY_MODE_DISABLED);
- config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &params,
- &msg);
+ QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
+ MockRandom rand;
+ config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
+ &params, &msg);
QuicTag cver;
EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kVER, &cver));
EXPECT_EQ(QuicVersionToQuicTag(QuicVersionMax()), cver);
+ StringPiece proof_nonce;
+ EXPECT_TRUE(msg.GetStringPiece(kNONP, &proof_nonce));
+ EXPECT_EQ(string(32, 'r'), proof_nonce);
}
TEST(QuicCryptoClientConfigTest, PreferAesGcm) {
@@ -178,8 +182,9 @@ TEST(QuicCryptoClientConfigTest, InchoateChloSecure) {
QuicCryptoNegotiatedParameters params;
CryptoHandshakeMessage msg;
QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
- config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &params,
- &msg);
+ MockRandom rand;
+ config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
+ &params, &msg);
QuicTag pdmd;
EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kPDMD, &pdmd));
@@ -203,8 +208,9 @@ TEST(QuicCryptoClientConfigTest, InchoateChloSecureWithSCID) {
QuicCryptoNegotiatedParameters params;
CryptoHandshakeMessage msg;
QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
- config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &params,
- &msg);
+ MockRandom rand;
+ config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
+ &params, &msg);
StringPiece scid;
EXPECT_TRUE(msg.GetStringPiece(kSCID, &scid));
@@ -218,8 +224,9 @@ TEST(QuicCryptoClientConfigTest, InchoateChloSecureNoEcdsa) {
QuicCryptoNegotiatedParameters params;
CryptoHandshakeMessage msg;
QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
- config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &params,
- &msg);
+ MockRandom rand;
+ config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
+ &params, &msg);
QuicTag pdmd;
EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kPDMD, &pdmd));
@@ -234,7 +241,7 @@ TEST(QuicCryptoClientConfigTest, FillClientHello) {
string error_details;
MockRandom rand;
CryptoHandshakeMessage chlo;
- QuicServerId server_id("www.google.com", 80, PRIVACY_MODE_DISABLED);
+ QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
config.FillClientHello(server_id, kConnectionId, QuicVersionMax(), &state,
QuicWallTime::Zero(), &rand,
nullptr, // channel_id_key
@@ -274,14 +281,15 @@ TEST(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) {
TEST(QuicCryptoClientConfigTest, InitializeFrom) {
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
- QuicServerId canonical_server_id("www.google.com", 80, PRIVACY_MODE_DISABLED);
+ QuicServerId canonical_server_id("www.google.com", 443,
+ PRIVACY_MODE_DISABLED);
QuicCryptoClientConfig::CachedState* state =
config.LookupOrCreate(canonical_server_id);
// TODO(rch): Populate other fields of |state|.
state->set_source_address_token("TOKEN");
state->SetProofValid();
- QuicServerId other_server_id("mail.google.com", 80, PRIVACY_MODE_DISABLED);
+ QuicServerId other_server_id("mail.google.com", 443, PRIVACY_MODE_DISABLED);
config.InitializeFrom(other_server_id, canonical_server_id, &config);
QuicCryptoClientConfig::CachedState* other =
config.LookupOrCreate(other_server_id);
@@ -295,8 +303,8 @@ TEST(QuicCryptoClientConfigTest, InitializeFrom) {
TEST(QuicCryptoClientConfigTest, Canonical) {
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
config.AddCanonicalSuffix(".google.com");
- QuicServerId canonical_id1("www.google.com", 80, PRIVACY_MODE_DISABLED);
- QuicServerId canonical_id2("mail.google.com", 80, PRIVACY_MODE_DISABLED);
+ QuicServerId canonical_id1("www.google.com", 443, PRIVACY_MODE_DISABLED);
+ QuicServerId canonical_id2("mail.google.com", 443, PRIVACY_MODE_DISABLED);
QuicCryptoClientConfig::CachedState* state =
config.LookupOrCreate(canonical_id1);
// TODO(rch): Populate other fields of |state|.
@@ -312,15 +320,15 @@ TEST(QuicCryptoClientConfigTest, Canonical) {
EXPECT_EQ(state->certs(), other->certs());
EXPECT_EQ(1u, other->generation_counter());
- QuicServerId different_id("mail.google.org", 80, PRIVACY_MODE_DISABLED);
+ QuicServerId different_id("mail.google.org", 443, PRIVACY_MODE_DISABLED);
EXPECT_TRUE(config.LookupOrCreate(different_id)->IsEmpty());
}
TEST(QuicCryptoClientConfigTest, CanonicalNotUsedIfNotValid) {
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
config.AddCanonicalSuffix(".google.com");
- QuicServerId canonical_id1("www.google.com", 80, PRIVACY_MODE_DISABLED);
- QuicServerId canonical_id2("mail.google.com", 80, PRIVACY_MODE_DISABLED);
+ QuicServerId canonical_id1("www.google.com", 443, PRIVACY_MODE_DISABLED);
+ QuicServerId canonical_id2("mail.google.com", 443, PRIVACY_MODE_DISABLED);
QuicCryptoClientConfig::CachedState* state =
config.LookupOrCreate(canonical_id1);
// TODO(rch): Populate other fields of |state|.
@@ -333,12 +341,12 @@ TEST(QuicCryptoClientConfigTest, CanonicalNotUsedIfNotValid) {
TEST(QuicCryptoClientConfigTest, ClearCachedStates) {
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
- QuicServerId server_id("www.google.com", 80, PRIVACY_MODE_DISABLED);
+ QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
QuicCryptoClientConfig::CachedState* state = config.LookupOrCreate(server_id);
// TODO(rch): Populate other fields of |state|.
vector<string> certs(1);
certs[0] = "Hello Cert";
- state->SetProof(certs, "cert_sct", "signature");
+ state->SetProof(certs, "cert_sct", "chlo_hash", "signature");
state->set_source_address_token("TOKEN");
state->SetProofValid();
EXPECT_EQ(1u, state->generation_counter());
@@ -376,8 +384,8 @@ TEST(QuicCryptoClientConfigTest, ProcessReject) {
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
EXPECT_EQ(QUIC_NO_ERROR,
config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
- QuicSupportedVersions().front(), &cached,
- &out_params, &error));
+ QuicSupportedVersions().front(), "",
+ &cached, &out_params, &error));
EXPECT_FALSE(cached.has_server_designated_connection_id());
EXPECT_FALSE(cached.has_server_nonce());
}
@@ -398,8 +406,8 @@ TEST(QuicCryptoClientConfigTest, ProcessStatelessReject) {
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
EXPECT_EQ(QUIC_NO_ERROR,
config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
- QuicSupportedVersions().front(), &cached,
- &out_params, &error));
+ QuicSupportedVersions().front(), "",
+ &cached, &out_params, &error));
EXPECT_TRUE(cached.has_server_designated_connection_id());
EXPECT_EQ(kConnectionId, cached.GetNextServerDesignatedConnectionId());
EXPECT_EQ(server_nonce, cached.GetNextServerNonce());
@@ -418,8 +426,8 @@ TEST(QuicCryptoClientConfigTest, BadlyFormattedStatelessReject) {
QuicCryptoClientConfig config(CryptoTestUtils::ProofVerifierForTesting());
EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND,
config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
- QuicSupportedVersions().front(), &cached,
- &out_params, &error));
+ QuicSupportedVersions().front(), "",
+ &cached, &out_params, &error));
EXPECT_FALSE(cached.has_server_designated_connection_id());
EXPECT_EQ("Missing kRCID", error);
}
diff --git a/chromium/net/quic/crypto/quic_crypto_server_config.cc b/chromium/net/quic/crypto/quic_crypto_server_config.cc
index f2475bad3cb..2d0c664974d 100644
--- a/chromium/net/quic/crypto/quic_crypto_server_config.cc
+++ b/chromium/net/quic/crypto/quic_crypto_server_config.cc
@@ -9,11 +9,12 @@
#include <algorithm>
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "crypto/hkdf.h"
#include "crypto/secure_hash.h"
-#include "net/base/net_util.h"
+#include "net/base/ip_address.h"
#include "net/quic/crypto/aes_128_gcm_12_decrypter.h"
#include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
#include "net/quic/crypto/cert_compressor.h"
@@ -35,6 +36,7 @@
#include "net/quic/crypto/strike_register.h"
#include "net/quic/crypto/strike_register_client.h"
#include "net/quic/proto/source_address_token.pb.h"
+#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_clock.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_protocol.h"
@@ -68,9 +70,9 @@ string DeriveSourceAddressTokenKey(StringPiece source_address_token_secret) {
return hkdf.server_write_key().as_string();
}
-IPAddressNumber DualstackIPAddress(const IPAddressNumber& ip) {
- if (ip.size() == kIPv4AddressSize) {
- return ConvertIPv4NumberToIPv6Number(ip);
+IPAddress DualstackIPAddress(const IPAddress& ip) {
+ if (ip.IsIPv4()) {
+ return ConvertIPv4ToIPv4MappedIPv6(ip);
}
return ip;
}
@@ -84,7 +86,7 @@ class ValidateClientHelloHelper {
: result_(result), done_cb_(done_cb) {}
~ValidateClientHelloHelper() {
- LOG_IF(DFATAL, done_cb_ != nullptr)
+ QUIC_BUG_IF(done_cb_ != nullptr)
<< "Deleting ValidateClientHelloHelper with a pending callback.";
}
@@ -99,7 +101,7 @@ class ValidateClientHelloHelper {
private:
void DetachCallback() {
- LOG_IF(DFATAL, done_cb_ == nullptr) << "Callback already detached.";
+ QUIC_BUG_IF(done_cb_ == nullptr) << "Callback already detached.";
done_cb_ = nullptr;
}
@@ -148,7 +150,7 @@ class VerifyNonceIsValidAndUniqueCallback
break;
case NONCE_OK:
default:
- LOG(DFATAL) << "Unexpected client nonce error: " << nonce_error;
+ QUIC_BUG << "Unexpected client nonce error: " << nonce_error;
client_nonce_error = CLIENT_NONCE_UNKNOWN_FAILURE;
break;
}
@@ -167,7 +169,7 @@ class VerifyNonceIsValidAndUniqueCallback
// static
const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
-ClientHelloInfo::ClientHelloInfo(const IPAddressNumber& in_client_ip,
+ClientHelloInfo::ClientHelloInfo(const IPAddress& in_client_ip,
QuicWallTime in_now)
: client_ip(in_client_ip), now(in_now), valid_source_address_token(false) {}
@@ -179,7 +181,7 @@ PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() {}
ValidateClientHelloResultCallback::Result::Result(
const CryptoHandshakeMessage& in_client_hello,
- IPAddressNumber in_client_ip,
+ IPAddress in_client_ip,
QuicWallTime in_now)
: client_hello(in_client_hello),
info(in_client_ip, in_now),
@@ -203,6 +205,9 @@ QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
token_binding_enabled(false),
p256(false) {}
+QuicCryptoServerConfig::ConfigOptions::ConfigOptions(
+ const ConfigOptions& other) = default;
+
QuicCryptoServerConfig::QuicCryptoServerConfig(
StringPiece source_address_token_secret,
QuicRandom* server_nonce_entropy,
@@ -223,8 +228,8 @@ QuicCryptoServerConfig::QuicCryptoServerConfig(
server_nonce_strike_register_window_secs_(120),
enable_serving_sct_(false) {
DCHECK(proof_source_.get());
- default_source_address_token_boxer_.SetKey(
- DeriveSourceAddressTokenKey(source_address_token_secret));
+ default_source_address_token_boxer_.SetKeys(
+ {DeriveSourceAddressTokenKey(source_address_token_secret)});
// Generate a random key and orbit for server nonces.
server_nonce_entropy->RandBytes(server_nonce_orbit_,
@@ -233,8 +238,8 @@ QuicCryptoServerConfig::QuicCryptoServerConfig(
scoped_ptr<uint8_t[]> key_bytes(new uint8_t[key_size]);
server_nonce_entropy->RandBytes(key_bytes.get(), key_size);
- server_nonce_boxer_.SetKey(
- StringPiece(reinterpret_cast<char*>(key_bytes.get()), key_size));
+ server_nonce_boxer_.SetKeys(
+ {string(reinterpret_cast<char*>(key_bytes.get()), key_size)});
}
QuicCryptoServerConfig::~QuicCryptoServerConfig() {
@@ -289,11 +294,11 @@ QuicServerConfigProtobuf* QuicCryptoServerConfig::GenerateConfig(
} else {
msg.SetTaglist(kKEXS, kC255, 0);
}
- if (FLAGS_quic_use_rfc7539 &&
+ if (FLAGS_quic_crypto_server_config_default_has_chacha20 &&
ChaCha20Poly1305Rfc7539Encrypter::IsSupported()) {
- msg.SetTaglist(kAEAD, kAESG, kCC12, kCC20, 0);
+ msg.SetTaglist(kAEAD, kAESG, kCC20, 0);
} else {
- msg.SetTaglist(kAEAD, kAESG, kCC12, 0);
+ msg.SetTaglist(kAEAD, kAESG, 0);
}
msg.SetStringPiece(kPUBS, encoded_public_values);
@@ -474,6 +479,11 @@ bool QuicCryptoServerConfig::SetConfigs(
return ok;
}
+void QuicCryptoServerConfig::SetDefaultSourceAddressTokenKeys(
+ const vector<string>& keys) {
+ default_source_address_token_boxer_.SetKeys(keys);
+}
+
void QuicCryptoServerConfig::GetConfigIds(vector<string>* scids) const {
base::AutoLock locked(configs_lock_);
for (ConfigMap::const_iterator it = configs_.begin(); it != configs_.end();
@@ -484,8 +494,8 @@ void QuicCryptoServerConfig::GetConfigIds(vector<string>* scids) const {
void QuicCryptoServerConfig::ValidateClientHello(
const CryptoHandshakeMessage& client_hello,
- const IPAddressNumber& client_ip,
- const IPAddressNumber& server_ip,
+ const IPAddress& client_ip,
+ const IPAddress& server_ip,
QuicVersion version,
const QuicClock* clock,
QuicCryptoProof* crypto_proof,
@@ -521,7 +531,7 @@ void QuicCryptoServerConfig::ValidateClientHello(
requested_config = GetConfigWithScid(requested_scid);
primary_config = primary_config_;
- crypto_proof->primary_scid = primary_config->id;
+ crypto_proof->config = primary_config_;
}
if (result->error_code == QUIC_NO_ERROR) {
@@ -535,7 +545,7 @@ void QuicCryptoServerConfig::ValidateClientHello(
QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
const ValidateClientHelloResultCallback::Result& validate_chlo_result,
QuicConnectionId connection_id,
- const IPAddressNumber& server_ip,
+ const IPAddress& server_ip,
const IPEndPoint& client_address,
QuicVersion version,
const QuicVersionVector& supported_versions,
@@ -543,6 +553,7 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
QuicConnectionId server_designated_connection_id,
const QuicClock* clock,
QuicRandom* rand,
+ QuicCompressedCertsCache* compressed_certs_cache,
QuicCryptoNegotiatedParameters* params,
QuicCryptoProof* crypto_proof,
CryptoHandshakeMessage* out,
@@ -579,20 +590,9 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
}
- // We'll use the config that the client requested in order to do
- // key-agreement. Otherwise we'll give it a copy of |primary_config_|
- // to use.
- if (FLAGS_quic_use_primary_config_for_proof) {
- primary_config = GetConfigWithScid(crypto_proof->primary_scid);
- if (!primary_config) {
- *error_details = "Configuration not found";
- LOG(DFATAL) << "Primary config not found";
- return QUIC_CRYPTO_INTERNAL_ERROR;
- }
- } else {
- primary_config = primary_config_;
- }
-
+ // 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;
requested_config = GetConfigWithScid(requested_scid);
}
@@ -607,11 +607,13 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
bool x509_ecdsa_supported = false;
ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported);
DCHECK(proof_source_.get());
- if (!crypto_proof->certs &&
- !proof_source_->GetProof(server_ip, info.sni.as_string(),
- primary_config->serialized, x509_ecdsa_supported,
- &crypto_proof->certs, &crypto_proof->signature,
- &crypto_proof->cert_sct)) {
+ string chlo_hash;
+ CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash);
+ if (!crypto_proof->chain &&
+ !proof_source_->GetProof(
+ server_ip, info.sni.as_string(), primary_config->serialized, version,
+ chlo_hash, x509_ecdsa_supported, &crypto_proof->chain,
+ &crypto_proof->signature, &crypto_proof->cert_sct)) {
return QUIC_HANDSHAKE_FAILED;
}
@@ -627,7 +629,7 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
BuildRejection(version, *primary_config, client_hello, info,
validate_chlo_result.cached_network_params,
use_stateless_rejects, server_designated_connection_id, rand,
- params, *crypto_proof, out);
+ compressed_certs_cache, params, *crypto_proof, out);
return QUIC_NO_ERROR;
}
@@ -706,11 +708,11 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
hkdf_suffix.append(requested_config->serialized);
DCHECK(proof_source_.get());
if (version > QUIC_VERSION_25) {
- if (crypto_proof->certs->empty()) {
+ if (crypto_proof->chain->certs.empty()) {
*error_details = "Failed to get certs";
return QUIC_CRYPTO_INTERNAL_ERROR;
}
- hkdf_suffix.append(crypto_proof->certs->at(0));
+ hkdf_suffix.append(crypto_proof->chain->certs.at(0));
}
StringPiece cetv_ciphertext;
@@ -743,11 +745,12 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
char plaintext[kMaxPacketSize];
size_t plaintext_length = 0;
const bool success = crypters.decrypter->DecryptPacket(
- 0 /* packet number */, StringPiece() /* associated data */,
- cetv_ciphertext, plaintext, &plaintext_length, kMaxPacketSize);
+ kDefaultPathId, 0 /* packet number */,
+ StringPiece() /* associated data */, cetv_ciphertext, plaintext,
+ &plaintext_length, kMaxPacketSize);
if (!success) {
*error_details = "CETV decryption failure";
- return QUIC_PACKET_TOO_LARGE;
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
scoped_ptr<CryptoHandshakeMessage> cetv(
CryptoFramer::ParseMessage(StringPiece(plaintext, plaintext_length)));
@@ -774,10 +777,11 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
hkdf_input.append(hkdf_suffix);
- if (!CryptoUtils::DeriveKeys(
- params->initial_premaster_secret, params->aead, info.client_nonce,
- info.server_nonce, hkdf_input, Perspective::IS_SERVER,
- &params->initial_crypters, nullptr /* subkey secret */)) {
+ string* subkey_secret = &params->initial_subkey_secret;
+ if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
+ info.client_nonce, info.server_nonce, hkdf_input,
+ Perspective::IS_SERVER,
+ &params->initial_crypters, subkey_secret)) {
*error_details = "Symmetric key setup failed";
return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
}
@@ -890,9 +894,9 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
if (configs.empty()) {
if (primary_config_.get()) {
- LOG(DFATAL) << "No valid QUIC server config. Keeping the current config.";
+ QUIC_BUG << "No valid QUIC server config. Keeping the current config.";
} else {
- LOG(DFATAL) << "No valid QUIC server config.";
+ QUIC_BUG << "No valid QUIC server config.";
}
return;
}
@@ -962,7 +966,7 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
}
void QuicCryptoServerConfig::EvaluateClientHello(
- const IPAddressNumber& server_ip,
+ const IPAddress& server_ip,
QuicVersion version,
const uint8_t* primary_orbit,
scoped_refptr<Config> requested_config,
@@ -992,23 +996,21 @@ void QuicCryptoServerConfig::EvaluateClientHello(
HandshakeFailureReason source_address_token_error = MAX_FAILURE_REASON;
StringPiece srct;
- if (FLAGS_quic_validate_stk_without_scid) {
- if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
- Config& config =
- requested_config != nullptr ? *requested_config : *primary_config;
- source_address_token_error =
- ParseSourceAddressToken(config, srct, &info->source_address_tokens);
-
- if (source_address_token_error == HANDSHAKE_OK) {
- source_address_token_error = ValidateSourceAddressTokens(
- info->source_address_tokens, info->client_ip, info->now,
- &client_hello_state->cached_network_params);
- }
- info->valid_source_address_token =
- (source_address_token_error == HANDSHAKE_OK);
- } else {
- source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
+ if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
+ Config& config =
+ requested_config != nullptr ? *requested_config : *primary_config;
+ source_address_token_error =
+ ParseSourceAddressToken(config, srct, &info->source_address_tokens);
+
+ if (source_address_token_error == HANDSHAKE_OK) {
+ source_address_token_error = ValidateSourceAddressTokens(
+ info->source_address_tokens, info->client_ip, info->now,
+ &client_hello_state->cached_network_params);
}
+ info->valid_source_address_token =
+ (source_address_token_error == HANDSHAKE_OK);
+ } else {
+ source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
}
if (!requested_config.get()) {
@@ -1023,21 +1025,11 @@ void QuicCryptoServerConfig::EvaluateClientHello(
return;
}
- if (!FLAGS_quic_validate_stk_without_scid) {
- if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
- source_address_token_error = ParseSourceAddressToken(
- *requested_config, srct, &info->source_address_tokens);
-
- if (source_address_token_error == HANDSHAKE_OK) {
- source_address_token_error = ValidateSourceAddressTokens(
- info->source_address_tokens, info->client_ip, info->now,
- &client_hello_state->cached_network_params);
- }
- info->valid_source_address_token =
- (source_address_token_error == HANDSHAKE_OK);
- } else {
- source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
- }
+ if (!client_hello.GetStringPiece(kNONC, &info->client_nonce)) {
+ info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
+ // Report no client nonce as INCHOATE_HELLO_FAILURE.
+ helper.ValidationComplete(QUIC_NO_ERROR, "");
+ return;
}
bool found_error = false;
@@ -1055,16 +1047,13 @@ void QuicCryptoServerConfig::EvaluateClientHello(
bool x509_supported = false;
bool x509_ecdsa_supported = false;
ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported);
- string serialized_config;
- if (FLAGS_quic_use_primary_config_for_proof) {
- serialized_config = primary_config->serialized;
- } else {
- serialized_config = requested_config->serialized;
- }
- if (!proof_source_->GetProof(server_ip, info->sni.as_string(),
- serialized_config, x509_ecdsa_supported,
- &crypto_proof->certs, &crypto_proof->signature,
- &crypto_proof->cert_sct)) {
+ string serialized_config = primary_config->serialized;
+ string chlo_hash;
+ CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash);
+ if (!proof_source_->GetProof(
+ server_ip, info->sni.as_string(), serialized_config, version,
+ chlo_hash, x509_ecdsa_supported, &crypto_proof->chain,
+ &crypto_proof->signature, &crypto_proof->cert_sct)) {
found_error = true;
info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
}
@@ -1075,10 +1064,10 @@ void QuicCryptoServerConfig::EvaluateClientHello(
}
}
- if (!client_hello.GetStringPiece(kNONC, &info->client_nonce) ||
- info->client_nonce.size() != kNonceSize) {
+ 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.";
if (FLAGS_use_early_return_when_verifying_chlo) {
helper.ValidationComplete(QUIC_NO_ERROR, "");
@@ -1090,8 +1079,8 @@ void QuicCryptoServerConfig::EvaluateClientHello(
// Server nonce is optional, and used for key derivation if present.
client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
- if (version > QUIC_VERSION_30) {
- DVLOG(1) << "No 0-RTT replay protection in QUIC_VERSION_31 and higher.";
+ 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 &&
@@ -1140,18 +1129,6 @@ void QuicCryptoServerConfig::EvaluateClientHello(
StrikeRegisterClient* strike_register_client;
{
base::AutoLock locked(strike_register_client_lock_);
-
- if (strike_register_client_.get() == nullptr) {
- if (!FLAGS_require_strike_register_or_server_nonce) {
- strike_register_client_.reset(new LocalStrikeRegisterClient(
- strike_register_max_entries_,
- static_cast<uint32_t>(info->now.ToUNIXSeconds()),
- strike_register_window_secs_, primary_orbit,
- strike_register_no_startup_period_
- ? StrikeRegister::NO_STARTUP_PERIOD_NEEDED
- : StrikeRegister::DENY_REQUESTS_AT_STARTUP));
- }
- }
strike_register_client = strike_register_client_.get();
}
@@ -1173,10 +1150,11 @@ void QuicCryptoServerConfig::EvaluateClientHello(
bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
QuicVersion version,
const SourceAddressTokens& previous_source_address_tokens,
- const IPAddressNumber& server_ip,
- const IPAddressNumber& client_ip,
+ const IPAddress& server_ip,
+ const IPAddress& client_ip,
const QuicClock* clock,
QuicRandom* rand,
+ QuicCompressedCertsCache* compressed_certs_cache,
const QuicCryptoNegotiatedParameters& params,
const CachedNetworkParameters* cached_network_params,
CryptoHandshakeMessage* out) const {
@@ -1189,19 +1167,20 @@ bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
previous_source_address_tokens, client_ip, rand,
clock->WallNow(), cached_network_params));
- const vector<string>* certs;
+ scoped_refptr<ProofSource::Chain> chain;
string signature;
string cert_sct;
- if (!proof_source_->GetProof(
- server_ip, params.sni, primary_config_->serialized,
- params.x509_ecdsa_supported, &certs, &signature, &cert_sct)) {
+ if (!proof_source_->GetProof(server_ip, params.sni,
+ primary_config_->serialized, version,
+ params.client_nonce, params.x509_ecdsa_supported,
+ &chain, &signature, &cert_sct)) {
DVLOG(1) << "Server: failed to get proof.";
return false;
}
- const string compressed = CertCompressor::CompressChain(
- *certs, params.client_common_set_hashes, params.client_cached_cert_hashes,
- primary_config_->common_cert_sets);
+ const string compressed = CompressChain(
+ compressed_certs_cache, chain, params.client_common_set_hashes,
+ params.client_cached_cert_hashes, primary_config_->common_cert_sets);
out->SetStringPiece(kCertificateTag, compressed);
out->SetStringPiece(kPROF, signature);
@@ -1225,6 +1204,7 @@ void QuicCryptoServerConfig::BuildRejection(
bool use_stateless_rejects,
QuicConnectionId server_designated_connection_id,
QuicRandom* rand,
+ QuicCompressedCertsCache* compressed_certs_cache,
QuicCryptoNegotiatedParameters* params,
const QuicCryptoProof& crypto_proof,
CryptoHandshakeMessage* out) const {
@@ -1268,9 +1248,10 @@ void QuicCryptoServerConfig::BuildRejection(
params->client_cached_cert_hashes = client_cached_cert_hashes.as_string();
}
- const string compressed = CertCompressor::CompressChain(
- *crypto_proof.certs, params->client_common_set_hashes,
- params->client_cached_cert_hashes, config.common_cert_sets);
+ const string compressed =
+ CompressChain(compressed_certs_cache, crypto_proof.chain,
+ params->client_common_set_hashes,
+ params->client_cached_cert_hashes, config.common_cert_sets);
// kREJOverheadBytes is a very rough estimate of how much of a REJ
// message is taken up by things other than the certificates.
@@ -1305,6 +1286,34 @@ void QuicCryptoServerConfig::BuildRejection(
}
}
+const string QuicCryptoServerConfig::CompressChain(
+ QuicCompressedCertsCache* compressed_certs_cache,
+ const scoped_refptr<ProofSource::Chain>& chain,
+ const string& client_common_set_hashes,
+ const string& client_cached_cert_hashes,
+ const CommonCertSets* common_sets) const {
+ // Check whether the compressed certs is available in the cache.
+ if (FLAGS_quic_use_cached_compressed_certs) {
+ DCHECK(compressed_certs_cache);
+ const string* cached_value = compressed_certs_cache->GetCompressedCert(
+ chain, client_common_set_hashes, client_cached_cert_hashes);
+ if (cached_value) {
+ return *cached_value;
+ }
+ }
+
+ const string compressed =
+ CertCompressor::CompressChain(chain->certs, client_common_set_hashes,
+ client_common_set_hashes, common_sets);
+
+ // Insert the newly compressed cert to cache.
+ if (FLAGS_quic_use_cached_compressed_certs) {
+ compressed_certs_cache->Insert(chain, client_common_set_hashes,
+ client_cached_cert_hashes, compressed);
+ }
+ return compressed;
+}
+
scoped_refptr<QuicCryptoServerConfig::Config>
QuicCryptoServerConfig::ParseConfigProtobuf(
QuicServerConfigProtobuf* protobuf) {
@@ -1326,8 +1335,8 @@ QuicCryptoServerConfig::ParseConfigProtobuf(
} else {
// Create override boxer instance.
CryptoSecretBoxer* boxer = new CryptoSecretBoxer;
- boxer->SetKey(DeriveSourceAddressTokenKey(
- protobuf->source_address_token_secret_override()));
+ boxer->SetKeys({DeriveSourceAddressTokenKey(
+ protobuf->source_address_token_secret_override())});
config->source_address_token_boxer_storage.reset(boxer);
config->source_address_token_boxer = boxer;
}
@@ -1557,7 +1566,7 @@ void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
string QuicCryptoServerConfig::NewSourceAddressToken(
const Config& config,
const SourceAddressTokens& previous_tokens,
- const IPAddressNumber& ip,
+ const IPAddress& ip,
QuicRandom* rand,
QuicWallTime now,
const CachedNetworkParameters* cached_network_params) const {
@@ -1624,7 +1633,7 @@ HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressTokens(
const SourceAddressTokens& source_address_tokens,
- const IPAddressNumber& ip,
+ const IPAddress& ip,
QuicWallTime now,
CachedNetworkParameters* cached_network_params) const {
HandshakeFailureReason reason =
@@ -1643,7 +1652,7 @@ HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressTokens(
HandshakeFailureReason QuicCryptoServerConfig::ValidateSingleSourceAddressToken(
const SourceAddressToken& source_address_token,
- const IPAddressNumber& ip,
+ const IPAddress& ip,
QuicWallTime now) const {
if (source_address_token.ip() !=
IPAddressToPackedString(DualstackIPAddress(ip))) {
@@ -1713,7 +1722,7 @@ HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce(
if (plaintext.size() != kServerNoncePlaintextSize) {
// This should never happen because the value decrypted correctly.
- LOG(DFATAL) << "Seemingly valid server nonce had incorrect length.";
+ QUIC_BUG << "Seemingly valid server nonce had incorrect length.";
return SERVER_NONCE_INVALID_FAILURE;
}
@@ -1753,7 +1762,7 @@ HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce(
case STRIKE_REGISTER_TIMEOUT:
case STRIKE_REGISTER_FAILURE:
default:
- LOG(DFATAL) << "Unexpected server nonce error: " << nonce_error;
+ QUIC_BUG << "Unexpected server nonce error: " << nonce_error;
return SERVER_NONCE_NOT_UNIQUE_FAILURE;
}
}
@@ -1761,7 +1770,7 @@ HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce(
bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate(
const CryptoHandshakeMessage& client_hello,
const QuicCryptoProof& crypto_proof) const {
- if (crypto_proof.certs->empty()) {
+ if (crypto_proof.chain->certs.empty()) {
return false;
}
@@ -1769,7 +1778,7 @@ bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate(
if (client_hello.GetUint64(kXLCT, &hash_from_client) != QUIC_NO_ERROR) {
return false;
}
- return CryptoUtils::ComputeLeafCertHash(crypto_proof.certs->at(0)) ==
+ return CryptoUtils::ComputeLeafCertHash(crypto_proof.chain->certs.at(0)) ==
hash_from_client;
}
@@ -1810,4 +1819,6 @@ QuicCryptoServerConfig::Config::~Config() {
STLDeleteElements(&key_exchanges);
}
+QuicCryptoProof::QuicCryptoProof() {}
+QuicCryptoProof::~QuicCryptoProof() {}
} // namespace net
diff --git a/chromium/net/quic/crypto/quic_crypto_server_config.h b/chromium/net/quic/crypto/quic_crypto_server_config.h
index 0aba62e2253..33f088d864e 100644
--- a/chromium/net/quic/crypto/quic_crypto_server_config.h
+++ b/chromium/net/quic/crypto/quic_crypto_server_config.h
@@ -17,13 +17,15 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
#include "base/synchronization/lock.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_export.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/crypto_handshake_message.h"
#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/crypto/crypto_secret_boxer.h"
+#include "net/quic/crypto/proof_source.h"
+#include "net/quic/crypto/quic_compressed_certs_cache.h"
#include "net/quic/proto/cached_network_parameters.pb.h"
#include "net/quic/proto/source_address_token.pb.h"
#include "net/quic/quic_time.h"
@@ -41,15 +43,16 @@ class QuicRandom;
class QuicServerConfigProtobuf;
class StrikeRegister;
class StrikeRegisterClient;
+struct QuicCryptoProof;
// ClientHelloInfo contains information about a client hello message that is
// only kept for as long as it's being processed.
struct ClientHelloInfo {
- ClientHelloInfo(const IPAddressNumber& in_client_ip, QuicWallTime in_now);
+ ClientHelloInfo(const IPAddress& in_client_ip, QuicWallTime in_now);
~ClientHelloInfo();
// Inputs to EvaluateClientHello.
- const IPAddressNumber client_ip;
+ const IPAddress client_ip;
const QuicWallTime now;
// Outputs from EvaluateClientHello.
@@ -87,7 +90,7 @@ class NET_EXPORT_PRIVATE ValidateClientHelloResultCallback {
// its validity. Can be interpreted by calling ProcessClientHello.
struct Result {
Result(const CryptoHandshakeMessage& in_client_hello,
- IPAddressNumber in_client_ip,
+ IPAddress in_client_ip,
QuicWallTime in_now);
~Result();
@@ -122,6 +125,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// ConfigOptions contains options for generating server configs.
struct NET_EXPORT_PRIVATE ConfigOptions {
ConfigOptions();
+ ConfigOptions(const ConfigOptions& other);
// expiry_time is the time, in UNIX seconds, when the server config will
// expire. If unset, it defaults to the current time plus six months.
@@ -192,6 +196,14 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
bool SetConfigs(const std::vector<QuicServerConfigProtobuf*>& protobufs,
QuicWallTime now);
+ // SetDefaultSourceAddressTokenKeys sets the keys to be tried, in order,
+ // when decrypting a source address token. This modifies only the default
+ // boxer, which is to say, it is a no-op if a key was specified in the Config.
+ // Note that these keys are used *without* passing them through a KDF, in
+ // contradistinction to the |source_address_token_secret| argument to the
+ // constructor.
+ void SetDefaultSourceAddressTokenKeys(const std::vector<std::string>& keys);
+
// Get the server config ids for all known configs.
void GetConfigIds(std::vector<std::string>* scids) const;
@@ -219,8 +231,8 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// once, either under the current call stack, or after the
// completion of an asynchronous operation.
void ValidateClientHello(const CryptoHandshakeMessage& client_hello,
- const IPAddressNumber& client_ip,
- const IPAddressNumber& server_ip,
+ const IPAddress& client_ip,
+ const IPAddress& server_ip,
QuicVersion version,
const QuicClock* clock,
QuicCryptoProof* crypto_proof,
@@ -246,6 +258,8 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// supports.
// clock: used to validate client nonces and ephemeral keys.
// rand: an entropy source
+ // compressed_certs_cache: the cache that caches a set of most recently used
+ // certs. Owned by QuicDispatcher.
// params: the state of the handshake. This may be updated with a server
// nonce when we send a rejection. After a successful handshake, this will
// contain the state of the connection.
@@ -256,7 +270,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
QuicErrorCode ProcessClientHello(
const ValidateClientHelloResultCallback::Result& validate_chlo_result,
QuicConnectionId connection_id,
- const IPAddressNumber& server_ip,
+ const IPAddress& server_ip,
const IPEndPoint& client_address,
QuicVersion version,
const QuicVersionVector& supported_versions,
@@ -264,6 +278,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
QuicConnectionId server_designated_connection_id,
const QuicClock* clock,
QuicRandom* rand,
+ QuicCompressedCertsCache* compressed_certs_cache,
QuicCryptoNegotiatedParameters* params,
QuicCryptoProof* crypto_proof,
CryptoHandshakeMessage* out,
@@ -278,10 +293,11 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
bool BuildServerConfigUpdateMessage(
QuicVersion version,
const SourceAddressTokens& previous_source_address_tokens,
- const IPAddressNumber& server_ip,
- const IPAddressNumber& client_ip,
+ const IPAddress& server_ip,
+ const IPAddress& client_ip,
const QuicClock* clock,
QuicRandom* rand,
+ QuicCompressedCertsCache* compressed_certs_cache,
const QuicCryptoNegotiatedParameters& params,
const CachedNetworkParameters* cached_network_params,
CryptoHandshakeMessage* out) const;
@@ -361,6 +377,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
private:
friend class test::QuicCryptoServerConfigPeer;
+ friend struct QuicCryptoProof;
// Config represents a server config: a collection of preferences and
// Diffie-Hellman public values.
@@ -444,7 +461,7 @@ 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 IPAddressNumber& server_ip,
+ const IPAddress& server_ip,
QuicVersion version,
const uint8_t* primary_orbit,
scoped_refptr<Config> requested_config,
@@ -462,10 +479,23 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
bool use_stateless_rejects,
QuicConnectionId server_designated_connection_id,
QuicRandom* rand,
+ QuicCompressedCertsCache* compressed_certs_cache,
QuicCryptoNegotiatedParameters* params,
const QuicCryptoProof& crypto_proof,
CryptoHandshakeMessage* out) const;
+ // CompressChain compresses the certificates in |chain->certs| and returns a
+ // compressed representation. |common_sets| contains the common certificate
+ // sets known locally and |client_common_set_hashes| contains the hashes of
+ // the common sets known to the peer. |client_cached_cert_hashes| contains
+ // 64-bit, FNV-1a hashes of certificates that the peer already possesses.
+ const std::string CompressChain(
+ QuicCompressedCertsCache* compressed_certs_cache,
+ const scoped_refptr<ProofSource::Chain>& chain,
+ const std::string& client_common_set_hashes,
+ const std::string& client_cached_cert_hashes,
+ const CommonCertSets* common_sets) const;
+
// 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.
@@ -476,7 +506,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
std::string NewSourceAddressToken(
const Config& config,
const SourceAddressTokens& previous_tokens,
- const IPAddressNumber& ip,
+ const IPAddress& ip,
QuicRandom* rand,
QuicWallTime now,
const CachedNetworkParameters* cached_network_params) const;
@@ -497,7 +527,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// token contains a CachedNetworkParameters proto.
HandshakeFailureReason ValidateSourceAddressTokens(
const SourceAddressTokens& tokens,
- const IPAddressNumber& ip,
+ const IPAddress& ip,
QuicWallTime now,
CachedNetworkParameters* cached_network_params) const;
@@ -507,7 +537,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// for failure.
HandshakeFailureReason ValidateSingleSourceAddressToken(
const SourceAddressToken& token,
- const IPAddressNumber& ip,
+ const IPAddress& ip,
QuicWallTime now) const;
// Returns HANDSHAKE_OK if the source address token in |token| is a timely
@@ -621,6 +651,19 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerConfig);
};
+struct NET_EXPORT_PRIVATE QuicCryptoProof {
+ QuicCryptoProof();
+ ~QuicCryptoProof();
+
+ std::string signature;
+ scoped_refptr<ProofSource::Chain> chain;
+ std::string cert_sct;
+ // The server config that is used for this proof (and the rest of the
+ // request).
+ scoped_refptr<QuicCryptoServerConfig::Config> config;
+ std::string primary_scid;
+};
+
} // namespace net
#endif // NET_QUIC_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
diff --git a/chromium/net/quic/crypto/quic_crypto_server_config_test.cc b/chromium/net/quic/crypto/quic_crypto_server_config_test.cc
index d7a887ed837..270cd9a22c5 100644
--- a/chromium/net/quic/crypto/quic_crypto_server_config_test.cc
+++ b/chromium/net/quic/crypto/quic_crypto_server_config_test.cc
@@ -8,6 +8,8 @@
#include "base/stl_util.h"
#include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
+#include "net/quic/crypto/cert_compressor.h"
+#include "net/quic/crypto/chacha20_poly1305_rfc7539_encrypter.h"
#include "net/quic/crypto/crypto_handshake_message.h"
#include "net/quic/crypto/crypto_secret_boxer.h"
#include "net/quic/crypto/crypto_server_config_protobuf.h"
@@ -47,7 +49,7 @@ class QuicCryptoServerConfigPeer {
string NewSourceAddressToken(string config_id,
SourceAddressTokens previous_tokens,
- const IPAddressNumber& ip,
+ const IPAddress& ip,
QuicRandom* rand,
QuicWallTime now,
CachedNetworkParameters* cached_network_params) {
@@ -59,7 +61,7 @@ class QuicCryptoServerConfigPeer {
HandshakeFailureReason ValidateSourceAddressTokens(
string config_id,
StringPiece srct,
- const IPAddressNumber& ip,
+ const IPAddress& ip,
QuicWallTime now,
CachedNetworkParameters* cached_network_params) {
SourceAddressTokens tokens;
@@ -145,7 +147,8 @@ class QuicCryptoServerConfigPeer {
}
ASSERT_TRUE(found) << "Failed to find match for " << i.first
- << " in configs:\n" << ConfigsDebug();
+ << " in configs:\n"
+ << ConfigsDebug();
}
}
@@ -180,6 +183,16 @@ class QuicCryptoServerConfigPeer {
QuicWallTime::FromUNIXSeconds(seconds));
}
+ const string CompressChain(QuicCompressedCertsCache* compressed_certs_cache,
+ const scoped_refptr<ProofSource::Chain>& chain,
+ const string& client_common_set_hashes,
+ const string& client_cached_cert_hashes,
+ const CommonCertSets* common_sets) {
+ return server_config_->CompressChain(
+ compressed_certs_cache, chain, client_common_set_hashes,
+ client_cached_cert_hashes, common_sets);
+ }
+
private:
const QuicCryptoServerConfig* server_config_;
};
@@ -221,8 +234,41 @@ TEST(QuicCryptoServerConfigTest, ServerConfig) {
CryptoTestUtils::ProofSourceForTesting());
MockClock clock;
- scoped_ptr<CryptoHandshakeMessage>(server.AddDefaultConfig(
+ scoped_ptr<CryptoHandshakeMessage> message(server.AddDefaultConfig(
+ rand, &clock, QuicCryptoServerConfig::ConfigOptions()));
+
+ // The default configuration should have AES-GCM and at least one ChaCha20
+ // cipher.
+ 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);
+ EXPECT_THAT(aead, ::testing::Contains(kAESG));
+ if (ChaCha20Poly1305Rfc7539Encrypter::IsSupported()) {
+ EXPECT_LE(2u, aead.size());
+ } else {
+ EXPECT_LE(1u, aead.size());
+ }
+}
+
+TEST(QuicCryptoServerConfigTest, ServerConfigDisableChaCha) {
+ ValueRestore<bool> old_flag(
+ &FLAGS_quic_crypto_server_config_default_has_chacha20, false);
+ QuicRandom* rand = QuicRandom::GetInstance();
+ QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand,
+ CryptoTestUtils::ProofSourceForTesting());
+ MockClock clock;
+
+ scoped_ptr<CryptoHandshakeMessage> message(server.AddDefaultConfig(
rand, &clock, QuicCryptoServerConfig::ConfigOptions()));
+
+ // The default configuration should only contain AES-GCM when ChaCha20 has
+ // been disabled.
+ 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);
+ EXPECT_THAT(aead, ::testing::ElementsAre(kAESG));
}
TEST(QuicCryptoServerConfigTest, GetOrbitIsCalledWithoutTheStrikeRegisterLock) {
@@ -241,11 +287,108 @@ TEST(QuicCryptoServerConfigTest, GetOrbitIsCalledWithoutTheStrikeRegisterLock) {
EXPECT_TRUE(strike_register->is_known_orbit_called());
}
+TEST(QuicCryptoServerConfigTest, CompressCerts) {
+ QuicCompressedCertsCache compressed_certs_cache(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
+
+ QuicRandom* rand = QuicRandom::GetInstance();
+ QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand,
+ CryptoTestUtils::ProofSourceForTesting());
+ QuicCryptoServerConfigPeer peer(&server);
+
+ vector<string> certs = {"testcert"};
+ scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs));
+
+ string compressed =
+ peer.CompressChain(&compressed_certs_cache, chain, "", "", nullptr);
+
+ if (FLAGS_quic_use_cached_compressed_certs) {
+ EXPECT_EQ(compressed_certs_cache.Size(), 1u);
+ } else {
+ EXPECT_EQ(compressed_certs_cache.Size(), 0u);
+ }
+}
+
+TEST(QuicCryptoServerConfigTest, CompressSameCertsTwice) {
+ QuicCompressedCertsCache compressed_certs_cache(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
+
+ QuicRandom* rand = QuicRandom::GetInstance();
+ QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand,
+ CryptoTestUtils::ProofSourceForTesting());
+ QuicCryptoServerConfigPeer peer(&server);
+
+ // Compress the certs for the first time.
+ vector<string> certs = {"testcert"};
+ scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs));
+ string common_certs = "";
+ string cached_certs = "";
+
+ string compressed = peer.CompressChain(&compressed_certs_cache, chain,
+ common_certs, cached_certs, nullptr);
+ if (FLAGS_quic_use_cached_compressed_certs) {
+ EXPECT_EQ(compressed_certs_cache.Size(), 1u);
+ }
+
+ // Compress the same certs, should use cache if available.
+ string compressed2 = peer.CompressChain(&compressed_certs_cache, chain,
+ common_certs, cached_certs, nullptr);
+ EXPECT_EQ(compressed, compressed2);
+ if (FLAGS_quic_use_cached_compressed_certs) {
+ EXPECT_EQ(compressed_certs_cache.Size(), 1u);
+ }
+}
+
+TEST(QuicCryptoServerConfigTest, CompressDifferentCerts) {
+ // This test compresses a set of similar but not identical certs. Cache if
+ // used should return cache miss and add all the compressed certs.
+ QuicCompressedCertsCache compressed_certs_cache(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
+
+ QuicRandom* rand = QuicRandom::GetInstance();
+ QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand,
+ CryptoTestUtils::ProofSourceForTesting());
+ QuicCryptoServerConfigPeer peer(&server);
+
+ vector<string> certs = {"testcert"};
+ scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs));
+ string common_certs = "";
+ string cached_certs = "";
+
+ string compressed = peer.CompressChain(&compressed_certs_cache, chain,
+ common_certs, cached_certs, nullptr);
+ if (FLAGS_quic_use_cached_compressed_certs) {
+ 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));
+
+ string compressed2 = peer.CompressChain(&compressed_certs_cache, chain2,
+ common_certs, cached_certs, nullptr);
+ if (FLAGS_quic_use_cached_compressed_certs) {
+ EXPECT_EQ(compressed_certs_cache.Size(), 2u);
+ }
+
+ // Compress a similar certs which only differs in common certs field.
+ static const uint64_t set_hash = 42;
+ scoped_ptr<CommonCertSets> common_sets(
+ CryptoTestUtils::MockCommonCertSets(certs[0], set_hash, 1));
+ StringPiece different_common_certs(reinterpret_cast<const char*>(&set_hash),
+ sizeof(set_hash));
+ string compressed3 = peer.CompressChain(&compressed_certs_cache, chain,
+ different_common_certs.as_string(),
+ cached_certs, common_sets.get());
+ if (FLAGS_quic_use_cached_compressed_certs) {
+ EXPECT_EQ(compressed_certs_cache.Size(), 3u);
+ }
+}
+
class SourceAddressTokenTest : public ::testing::Test {
public:
SourceAddressTokenTest()
: ip4_(Loopback4()),
- ip4_dual_(ConvertIPv4NumberToIPv6Number(ip4_)),
+ ip4_dual_(ConvertIPv4ToIPv4MappedIPv6(ip4_)),
ip6_(Loopback6()),
original_time_(QuicWallTime::Zero()),
rand_(QuicRandom::GetInstance()),
@@ -273,36 +416,35 @@ class SourceAddressTokenTest : public ::testing::Test {
server_.AddConfig(override_config_protobuf_.get(), original_time_));
}
- string NewSourceAddressToken(string config_id, const IPAddressNumber& ip) {
+ string NewSourceAddressToken(string config_id, const IPAddress& ip) {
return NewSourceAddressToken(config_id, ip, nullptr);
}
string NewSourceAddressToken(string config_id,
- const IPAddressNumber& ip,
+ const IPAddress& ip,
const SourceAddressTokens& previous_tokens) {
return peer_.NewSourceAddressToken(config_id, previous_tokens, ip, rand_,
clock_.WallNow(), nullptr);
}
string NewSourceAddressToken(string config_id,
- const IPAddressNumber& ip,
+ const IPAddress& ip,
CachedNetworkParameters* cached_network_params) {
SourceAddressTokens previous_tokens;
return peer_.NewSourceAddressToken(config_id, previous_tokens, ip, rand_,
clock_.WallNow(), cached_network_params);
}
- HandshakeFailureReason ValidateSourceAddressTokens(
- string config_id,
- StringPiece srct,
- const IPAddressNumber& ip) {
+ HandshakeFailureReason ValidateSourceAddressTokens(string config_id,
+ StringPiece srct,
+ const IPAddress& ip) {
return ValidateSourceAddressTokens(config_id, srct, ip, nullptr);
}
HandshakeFailureReason ValidateSourceAddressTokens(
string config_id,
StringPiece srct,
- const IPAddressNumber& ip,
+ const IPAddress& ip,
CachedNetworkParameters* cached_network_params) {
return peer_.ValidateSourceAddressTokens(
config_id, srct, ip, clock_.WallNow(), cached_network_params);
@@ -311,9 +453,9 @@ class SourceAddressTokenTest : public ::testing::Test {
const string kPrimary = "<primary>";
const string kOverride = "Config with custom source address token key";
- IPAddressNumber ip4_;
- IPAddressNumber ip4_dual_;
- IPAddressNumber ip6_;
+ IPAddress ip4_;
+ IPAddress ip4_dual_;
+ IPAddress ip6_;
MockClock clock_;
QuicWallTime original_time_;
@@ -405,9 +547,9 @@ TEST_F(SourceAddressTokenTest, SourceAddressTokenMultipleAddresses) {
// Now create a token which is usable for both addresses.
SourceAddressToken previous_token;
- IPAddressNumber ip_address = ip6_;
- if (ip6_.size() == kIPv4AddressSize) {
- ip_address = ConvertIPv4NumberToIPv6Number(ip_address);
+ IPAddress ip_address = ip6_;
+ if (ip6_.IsIPv4()) {
+ ip_address = ConvertIPv4ToIPv4MappedIPv6(ip_address);
}
previous_token.set_ip(IPAddressToPackedString(ip_address));
previous_token.set_timestamp(now.ToUNIXSeconds());
@@ -434,7 +576,7 @@ TEST(QuicCryptoServerConfigTest, ValidateServerNonce) {
memset(key.get(), 0x11, key_size);
CryptoSecretBoxer boxer;
- boxer.SetKey(StringPiece(reinterpret_cast<char*>(key.get()), key_size));
+ boxer.SetKeys({string(reinterpret_cast<char*>(key.get()), key_size)});
const string box = boxer.Box(rand, message);
MockClock clock;
QuicWallTime now = clock.WallNow();
diff --git a/chromium/net/quic/crypto/quic_decrypter.cc b/chromium/net/quic/crypto/quic_decrypter.cc
index 1253b872b38..eae1f8fcf6d 100644
--- a/chromium/net/quic/crypto/quic_decrypter.cc
+++ b/chromium/net/quic/crypto/quic_decrypter.cc
@@ -5,7 +5,6 @@
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/aes_128_gcm_12_decrypter.h"
-#include "net/quic/crypto/chacha20_poly1305_decrypter.h"
#include "net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h"
#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/crypto/null_decrypter.h"
@@ -17,8 +16,6 @@ QuicDecrypter* QuicDecrypter::Create(QuicTag algorithm) {
switch (algorithm) {
case kAESG:
return new Aes128Gcm12Decrypter();
- case kCC12:
- return new ChaCha20Poly1305Decrypter();
case kCC20:
return new ChaCha20Poly1305Rfc7539Decrypter();
case kNULL:
diff --git a/chromium/net/quic/crypto/quic_decrypter.h b/chromium/net/quic/crypto/quic_decrypter.h
index 4363e709df0..4f2be96ff19 100644
--- a/chromium/net/quic/crypto/quic_decrypter.h
+++ b/chromium/net/quic/crypto/quic_decrypter.h
@@ -50,9 +50,10 @@ 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(QuicPacketNumber packet_number,
- const base::StringPiece& associated_data,
- const base::StringPiece& ciphertext,
+ virtual bool DecryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
+ base::StringPiece associated_data,
+ base::StringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) = 0;
diff --git a/chromium/net/quic/crypto/quic_encrypter.cc b/chromium/net/quic/crypto/quic_encrypter.cc
index 0cd727b0940..e483b6f48c7 100644
--- a/chromium/net/quic/crypto/quic_encrypter.cc
+++ b/chromium/net/quic/crypto/quic_encrypter.cc
@@ -5,7 +5,6 @@
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
-#include "net/quic/crypto/chacha20_poly1305_encrypter.h"
#include "net/quic/crypto/chacha20_poly1305_rfc7539_encrypter.h"
#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/crypto/null_encrypter.h"
@@ -17,8 +16,6 @@ QuicEncrypter* QuicEncrypter::Create(QuicTag algorithm) {
switch (algorithm) {
case kAESG:
return new Aes128Gcm12Encrypter();
- case kCC12:
- return new ChaCha20Poly1305Encrypter();
case kCC20:
return new ChaCha20Poly1305Rfc7539Encrypter();
case kNULL:
diff --git a/chromium/net/quic/crypto/quic_encrypter.h b/chromium/net/quic/crypto/quic_encrypter.h
index 72701743c80..a4cc9efe8eb 100644
--- a/chromium/net/quic/crypto/quic_encrypter.h
+++ b/chromium/net/quic/crypto/quic_encrypter.h
@@ -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(QuicPacketNumber packet_number,
+ virtual bool EncryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
base::StringPiece associated_data,
base::StringPiece plaintext,
char* output,
diff --git a/chromium/net/quic/crypto/quic_random.cc b/chromium/net/quic/crypto/quic_random.cc
index ad130a0858d..cc8ef2768f7 100644
--- a/chromium/net/quic/crypto/quic_random.cc
+++ b/chromium/net/quic/crypto/quic_random.cc
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "crypto/random.h"
+#include "net/quic/quic_bug_tracker.h"
namespace net {
diff --git a/chromium/net/quic/crypto/quic_server_info.cc b/chromium/net/quic/crypto/quic_server_info.cc
index 2627fb48609..24edb9bd622 100644
--- a/chromium/net/quic/crypto/quic_server_info.cc
+++ b/chromium/net/quic/crypto/quic_server_info.cc
@@ -12,7 +12,10 @@ using std::string;
namespace {
-const int kQuicCryptoConfigVersion = 1;
+// TODO(rtenneti): Delete kQuicCryptoConfigVersionNoChloHash after
+// QUIC_VERSION_31 becomes the default.
+const int kQuicCryptoConfigVersionNoChloHash = 1;
+const int kQuicCryptoConfigVersion = 2;
} // namespace
@@ -25,6 +28,8 @@ QuicServerInfo::State::~State() {}
void QuicServerInfo::State::Clear() {
server_config.clear();
source_address_token.clear();
+ cert_sct.clear();
+ chlo_hash.clear();
server_config_sig.clear();
certs.clear();
}
@@ -70,7 +75,10 @@ bool QuicServerInfo::ParseInner(const string& data) {
return false;
}
- if (version != kQuicCryptoConfigVersion) {
+ // TODO(rtenneti): Delete kQuicCryptoConfigVersionNoChloHash after
+ // QUIC_VERSION_31 becomes the default.
+ if (!(version == kQuicCryptoConfigVersionNoChloHash ||
+ version == kQuicCryptoConfigVersion)) {
DVLOG(1) << "Unsupported version";
return false;
}
@@ -83,6 +91,21 @@ bool QuicServerInfo::ParseInner(const string& data) {
DVLOG(1) << "Malformed source_address_token";
return false;
}
+ // TODO(rtenneti): Delete kQuicCryptoConfigVersionNoChloHash after
+ // QUIC_VERSION_31 becomes the default.
+ if (version == kQuicCryptoConfigVersionNoChloHash) {
+ state->cert_sct.clear();
+ state->chlo_hash.clear();
+ } else {
+ if (!iter.ReadString(&state->cert_sct)) {
+ DVLOG(1) << "Malformed cert_sct";
+ return false;
+ }
+ if (!iter.ReadString(&state->chlo_hash)) {
+ DVLOG(1) << "Malformed chlo_hash";
+ return false;
+ }
+ }
if (!iter.ReadString(&state->server_config_sig)) {
DVLOG(1) << "Malformed server_config_sig";
return false;
@@ -119,6 +142,7 @@ string QuicServerInfo::SerializeInner() const {
if (!p.WriteInt(kQuicCryptoConfigVersion) ||
!p.WriteString(state_.server_config) ||
!p.WriteString(state_.source_address_token) ||
+ !p.WriteString(state_.cert_sct) || !p.WriteString(state_.chlo_hash) ||
!p.WriteString(state_.server_config_sig) ||
state_.certs.size() > std::numeric_limits<uint32_t>::max() ||
!p.WriteUInt32(state_.certs.size())) {
diff --git a/chromium/net/quic/crypto/quic_server_info.h b/chromium/net/quic/crypto/quic_server_info.h
index be15240805f..5032e38a9e9 100644
--- a/chromium/net/quic/crypto/quic_server_info.h
+++ b/chromium/net/quic/crypto/quic_server_info.h
@@ -81,6 +81,8 @@ class NET_EXPORT_PRIVATE QuicServerInfo {
// This class matches QuicClientCryptoConfig::CachedState.
std::string server_config; // A serialized handshake message.
std::string source_address_token; // An opaque proof of IP ownership.
+ std::string cert_sct; // Signed timestamp of the leaf cert.
+ std::string chlo_hash; // Hash of the CHLO message.
std::vector<std::string> certs; // A list of certificates in leaf-first
// order.
std::string server_config_sig; // A signature of |server_config_|.
diff --git a/chromium/net/quic/iovector.cc b/chromium/net/quic/iovector.cc
index a6d2c617fc8..effa52d419e 100644
--- a/chromium/net/quic/iovector.cc
+++ b/chromium/net/quic/iovector.cc
@@ -8,6 +8,8 @@ namespace net {
IOVector::IOVector() {}
+IOVector::IOVector(const IOVector& other) = default;
+
IOVector::~IOVector() {}
} // namespace net
diff --git a/chromium/net/quic/iovector.h b/chromium/net/quic/iovector.h
index 0ea57bb05c1..cf77a9acc26 100644
--- a/chromium/net/quic/iovector.h
+++ b/chromium/net/quic/iovector.h
@@ -62,6 +62,7 @@ class NET_EXPORT_PRIVATE IOVector {
// Provide a default constructor so it'll never be inhibited by adding other
// constructors.
IOVector();
+ IOVector(const IOVector& other);
~IOVector();
// Provides a way to convert system call-like iovec representation to
diff --git a/chromium/net/quic/p2p/quic_p2p_session.cc b/chromium/net/quic/p2p/quic_p2p_session.cc
index e326a011a2a..7b411e02138 100644
--- a/chromium/net/quic/p2p/quic_p2p_session.cc
+++ b/chromium/net/quic/p2p/quic_p2p_session.cc
@@ -8,6 +8,7 @@
#include "base/callback_helpers.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/quic/p2p/quic_p2p_crypto_stream.h"
#include "net/quic/p2p/quic_p2p_stream.h"
@@ -19,19 +20,18 @@ namespace net {
QuicP2PSession::QuicP2PSession(const QuicConfig& config,
const QuicP2PCryptoConfig& crypto_config,
scoped_ptr<QuicConnection> connection,
- scoped_ptr<net::Socket> socket)
+ scoped_ptr<Socket> socket)
: QuicSession(connection.release(), config),
socket_(std::move(socket)),
crypto_stream_(new QuicP2PCryptoStream(this, crypto_config)),
- read_buffer_(new net::IOBuffer(static_cast<size_t>(kMaxPacketSize))) {
+ read_buffer_(new IOBuffer(static_cast<size_t>(kMaxPacketSize))) {
DCHECK(config.negotiated());
// Non-null IP address needs to be passed here because QuicConnection uses
// ToString() to format addresses for logging and ToString() is not allowed
// for empty addresses.
// TODO(sergeyu): Fix QuicConnection and remove SetSelfAddress() call below.
- net::IPAddressNumber ip(net::kIPv4AddressSize, 0);
- this->connection()->SetSelfAddress(net::IPEndPoint(ip, 0));
+ this->connection()->SetSelfAddress(IPEndPoint(IPAddress::IPv4AllZeros(), 0));
}
QuicP2PSession::~QuicP2PSession() {}
@@ -55,11 +55,12 @@ QuicP2PStream* QuicP2PSession::CreateIncomingDynamicStream(QuicStreamId id) {
if (delegate_) {
delegate_->OnIncomingStream(stream);
}
+ ActivateStream(stream);
return stream;
}
QuicP2PStream* QuicP2PSession::CreateOutgoingDynamicStream(
- net::SpdyPriority priority) {
+ SpdyPriority priority) {
QuicP2PStream* stream = new QuicP2PStream(GetNextOutgoingStreamId(), this);
if (stream) {
ActivateStream(stream);
@@ -67,8 +68,10 @@ QuicP2PStream* QuicP2PSession::CreateOutgoingDynamicStream(
return stream;
}
-void QuicP2PSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) {
- QuicSession::OnConnectionClosed(error, from_peer);
+void QuicP2PSession::OnConnectionClosed(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) {
+ QuicSession::OnConnectionClosed(error, error_details, source);
socket_.reset();
@@ -80,7 +83,7 @@ void QuicP2PSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) {
}
void QuicP2PSession::DoReadLoop(int result) {
- while (error() == net::QUIC_NO_ERROR) {
+ while (error() == QUIC_NO_ERROR) {
switch (read_state_) {
case READ_STATE_DO_READ:
CHECK_EQ(result, OK);
@@ -104,7 +107,7 @@ int QuicP2PSession::DoRead() {
read_state_ = READ_STATE_DO_READ_COMPLETE;
if (!socket_) {
- return net::ERR_SOCKET_NOT_CONNECTED;
+ return ERR_SOCKET_NOT_CONNECTED;
}
return socket_->Read(
@@ -117,11 +120,12 @@ int QuicP2PSession::DoReadComplete(int result) {
read_state_ = READ_STATE_DO_READ;
if (result <= 0) {
- connection()->CloseConnection(net::QUIC_PACKET_READ_ERROR, false);
+ connection()->CloseConnection(QUIC_PACKET_READ_ERROR, "packet read error",
+ ConnectionCloseBehavior::SILENT_CLOSE);
return result;
}
- QuicEncryptedPacket packet(read_buffer_->data(), result);
+ QuicReceivedPacket packet(read_buffer_->data(), result, clock_.Now());
connection()->ProcessUdpPacket(connection()->self_address(),
connection()->peer_address(), packet);
return OK;
diff --git a/chromium/net/quic/p2p/quic_p2p_session.h b/chromium/net/quic/p2p/quic_p2p_session.h
index 697f6006317..ce02958905a 100644
--- a/chromium/net/quic/p2p/quic_p2p_session.h
+++ b/chromium/net/quic/p2p/quic_p2p_session.h
@@ -10,6 +10,7 @@
#include "base/strings/string_piece.h"
#include "net/quic/p2p/quic_p2p_stream.h"
#include "net/quic/quic_client_session_base.h"
+#include "net/quic/quic_clock.h"
#include "net/quic/quic_protocol.h"
namespace net {
@@ -52,7 +53,9 @@ class NET_EXPORT QuicP2PSession : public QuicSession {
net::SpdyPriority priority) override;
// QuicConnectionVisitorInterface overrides.
- void OnConnectionClosed(QuicErrorCode error, bool from_peer) override;
+ void OnConnectionClosed(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) override;
void SetDelegate(Delegate* delegate);
@@ -81,6 +84,9 @@ class NET_EXPORT QuicP2PSession : public QuicSession {
ReadState read_state_ = READ_STATE_DO_READ;
scoped_refptr<IOBuffer> read_buffer_;
+ // For recording receipt time
+ QuicClock clock_;
+
DISALLOW_COPY_AND_ASSIGN(QuicP2PSession);
};
diff --git a/chromium/net/quic/p2p/quic_p2p_session_test.cc b/chromium/net/quic/p2p/quic_p2p_session_test.cc
index 544c082d6c2..c9f248e259f 100644
--- a/chromium/net/quic/p2p/quic_p2p_session_test.cc
+++ b/chromium/net/quic/p2p/quic_p2p_session_test.cc
@@ -19,7 +19,8 @@
#include "net/quic/p2p/quic_p2p_crypto_config.h"
#include "net/quic/p2p/quic_p2p_stream.h"
#include "net/quic/quic_chromium_connection_helper.h"
-#include "net/quic/quic_default_packet_writer.h"
+#include "net/quic/quic_chromium_packet_writer.h"
+#include "net/quic/test_tools/quic_session_peer.h"
#include "net/socket/socket.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -197,7 +198,7 @@ class QuicP2PSessionTest : public ::testing::Test {
QuicP2PSessionTest()
: quic_helper_(base::ThreadTaskRunnerHandle::Get().get(),
&quic_clock_,
- net::QuicRandom::GetInstance()) {
+ QuicRandom::GetInstance()) {
// Simulate out-of-bound config handshake.
CryptoHandshakeMessage hello_message;
config_.ToHandshakeMessage(&hello_message);
@@ -225,11 +226,10 @@ class QuicP2PSessionTest : public ::testing::Test {
scoped_ptr<QuicP2PSession> CreateP2PSession(scoped_ptr<Socket> socket,
QuicP2PCryptoConfig crypto_config,
Perspective perspective) {
- net::QuicDefaultPacketWriter* writer =
- new net::QuicDefaultPacketWriter(socket.get());
- net::IPAddressNumber ip(net::kIPv4AddressSize, 0);
+ QuicChromiumPacketWriter* writer =
+ new QuicChromiumPacketWriter(socket.get());
scoped_ptr<QuicConnection> quic_connection1(new QuicConnection(
- 0, net::IPEndPoint(ip, 0), &quic_helper_, writer,
+ 0, IPEndPoint(IPAddress::IPv4AllZeros(), 0), &quic_helper_, writer,
true /* owns_writer */, perspective, QuicSupportedVersions()));
writer->SetConnection(quic_connection1.get());
@@ -269,6 +269,14 @@ void QuicP2PSessionTest::TestStreamConnection(QuicP2PSession* from_session,
outgoing_stream->SetDelegate(&outgoing_stream_delegate);
EXPECT_EQ(expected_stream_id, outgoing_stream->id());
+ // Add streams to write_blocked_lists of both QuicSession objects.
+ QuicWriteBlockedList* write_blocked_list1 =
+ test::QuicSessionPeer::GetWriteBlockedStreams(from_session);
+ write_blocked_list1->RegisterStream(expected_stream_id, kV3HighestPriority);
+ QuicWriteBlockedList* write_blocked_list2 =
+ test::QuicSessionPeer::GetWriteBlockedStreams(to_session);
+ write_blocked_list2->RegisterStream(expected_stream_id, kV3HighestPriority);
+
// Send a test message to the client.
const char kTestMessage[] = "Hi";
const char kTestResponse[] = "Response";
@@ -320,7 +328,8 @@ TEST_F(QuicP2PSessionTest, DestroySocketWhenClosed) {
// The socket must be destroyed when connection is closed.
EXPECT_TRUE(socket1_);
- session1_->connection()->CloseConnection(net::QUIC_NO_ERROR, false);
+ session1_->connection()->CloseConnection(
+ QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
EXPECT_FALSE(socket1_);
}
@@ -337,6 +346,11 @@ TEST_F(QuicP2PSessionTest, TransportWriteError) {
stream->SetDelegate(&stream_delegate);
EXPECT_EQ(2U, stream->id());
+ // Add stream to write_blocked_list.
+ QuicWriteBlockedList* write_blocked_list =
+ test::QuicSessionPeer::GetWriteBlockedStreams(session1_.get());
+ write_blocked_list->RegisterStream(stream->id(), kV3HighestPriority);
+
socket1_->SetWriteError(ERR_INTERNET_DISCONNECTED);
const char kTestMessage[] = "Hi";
diff --git a/chromium/net/quic/p2p/quic_p2p_stream.cc b/chromium/net/quic/p2p/quic_p2p_stream.cc
index a8e00c6313c..da01019674b 100644
--- a/chromium/net/quic/p2p/quic_p2p_stream.cc
+++ b/chromium/net/quic/p2p/quic_p2p_stream.cc
@@ -49,10 +49,6 @@ void QuicP2PStream::OnCanWrite() {
}
}
-SpdyPriority QuicP2PStream::Priority() const {
- return priority_;
-}
-
void QuicP2PStream::WriteHeader(base::StringPiece data) {
WriteOrBufferData(data, false, nullptr);
}
diff --git a/chromium/net/quic/p2p/quic_p2p_stream.h b/chromium/net/quic/p2p/quic_p2p_stream.h
index a2747e8e4cb..4e456b20d3a 100644
--- a/chromium/net/quic/p2p/quic_p2p_stream.h
+++ b/chromium/net/quic/p2p/quic_p2p_stream.h
@@ -41,7 +41,6 @@ class NET_EXPORT QuicP2PStream : public ReliableQuicStream {
void OnDataAvailable() override;
void OnClose() override;
void OnCanWrite() override;
- SpdyPriority Priority() const override;
void WriteHeader(base::StringPiece data);
@@ -53,8 +52,6 @@ class NET_EXPORT QuicP2PStream : public ReliableQuicStream {
private:
Delegate* delegate_ = nullptr;
- SpdyPriority priority_ = 0;
-
CompletionCallback write_callback_;
int last_write_size_ = 0;
diff --git a/chromium/net/quic/quic_ack_listener_interface.h b/chromium/net/quic/quic_ack_listener_interface.h
deleted file mode 100644
index c2bd6fee97b..00000000000
--- a/chromium/net/quic/quic_ack_listener_interface.h
+++ /dev/null
@@ -1,38 +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_QUIC_ACK_LISTENER_INTERFACE_H_
-#define NET_QUIC_QUIC_ACK_LISTENER_INTERFACE_H_
-
-#include "base/memory/ref_counted.h"
-#include "net/quic/quic_protocol.h"
-#include "net/quic/quic_time.h"
-
-namespace net {
-
-// 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 delta_largest_observed) = 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() {}
-};
-
-} // namespace net
-
-#endif // NET_QUIC_QUIC_ACK_LISTENER_INTERFACE_H_
diff --git a/chromium/net/quic/quic_address_mismatch.cc b/chromium/net/quic/quic_address_mismatch.cc
index 96aaef41030..3a5213865d4 100644
--- a/chromium/net/quic/quic_address_mismatch.cc
+++ b/chromium/net/quic/quic_address_mismatch.cc
@@ -5,6 +5,7 @@
#include "net/quic/quic_address_mismatch.h"
#include "base/logging.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
namespace net {
@@ -14,13 +15,13 @@ int GetAddressMismatch(const IPEndPoint& first_address,
if (first_address.address().empty() || second_address.address().empty()) {
return -1;
}
- IPAddressNumber first_ip_address = first_address.address();
- if (IsIPv4Mapped(first_ip_address)) {
- first_ip_address = ConvertIPv4MappedToIPv4(first_ip_address);
+ IPAddress first_ip_address = first_address.address();
+ if (first_ip_address.IsIPv4MappedIPv6()) {
+ first_ip_address = ConvertIPv4MappedIPv6ToIPv4(first_ip_address);
}
- IPAddressNumber second_ip_address = second_address.address();
- if (IsIPv4Mapped(second_ip_address)) {
- second_ip_address = ConvertIPv4MappedToIPv4(second_ip_address);
+ IPAddress second_ip_address = second_address.address();
+ if (second_ip_address.IsIPv4MappedIPv6()) {
+ second_ip_address = ConvertIPv4MappedIPv6ToIPv4(second_ip_address);
}
int sample;
@@ -37,9 +38,8 @@ int GetAddressMismatch(const IPEndPoint& first_address,
// V6_V6: add 1
// V4_V6: add 2
// V6_V4: add 3
- bool first_ipv4 = (first_ip_address.size() == kIPv4AddressSize);
- bool second_ipv4 = (second_ip_address.size() == kIPv4AddressSize);
- if (first_ipv4 != second_ipv4) {
+ bool first_ipv4 = first_ip_address.IsIPv4();
+ if (first_ipv4 != second_ip_address.IsIPv4()) {
CHECK_EQ(sample, QUIC_ADDRESS_MISMATCH_BASE);
sample += 2;
}
diff --git a/chromium/net/quic/quic_address_mismatch_test.cc b/chromium/net/quic/quic_address_mismatch_test.cc
index 02f3dcc0653..1946bafb0d5 100644
--- a/chromium/net/quic/quic_address_mismatch_test.cc
+++ b/chromium/net/quic/quic_address_mismatch_test.cc
@@ -5,7 +5,6 @@
#include "net/quic/quic_address_mismatch.h"
#include "net/base/ip_endpoint.h"
-#include "net/base/net_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -13,18 +12,18 @@ namespace test {
// Test all cases of the GetAddressMismatch function.
TEST(QuicAddressMismatchTest, GetAddressMismatch) {
- IPAddressNumber ip4_1;
- IPAddressNumber ip4_2;
- IPAddressNumber ip6_1;
- IPAddressNumber ip6_2;
- IPAddressNumber ip4_mapped_1;
- IPAddressNumber ip4_mapped_2;
- ASSERT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &ip4_1));
- ASSERT_TRUE(ParseIPLiteralToNumber("5.6.7.8", &ip4_2));
- ASSERT_TRUE(ParseIPLiteralToNumber("1234::1", &ip6_1));
- ASSERT_TRUE(ParseIPLiteralToNumber("1234::2", &ip6_2));
- ip4_mapped_1 = ConvertIPv4NumberToIPv6Number(ip4_1);
- ip4_mapped_2 = ConvertIPv4NumberToIPv6Number(ip4_2);
+ IPAddress ip4_1;
+ IPAddress ip4_2;
+ IPAddress ip6_1;
+ IPAddress ip6_2;
+ IPAddress ip4_mapped_1;
+ IPAddress ip4_mapped_2;
+ ASSERT_TRUE(ip4_1.AssignFromIPLiteral("1.2.3.4"));
+ ASSERT_TRUE(ip4_2.AssignFromIPLiteral("5.6.7.8"));
+ ASSERT_TRUE(ip6_1.AssignFromIPLiteral("1234::1"));
+ ASSERT_TRUE(ip6_2.AssignFromIPLiteral("1234::2"));
+ ip4_mapped_1 = ConvertIPv4ToIPv4MappedIPv6(ip4_1);
+ ip4_mapped_2 = ConvertIPv4ToIPv4MappedIPv6(ip4_2);
ASSERT_NE(ip4_1, ip4_2);
ASSERT_NE(ip6_1, ip6_2);
ASSERT_NE(ip4_mapped_1, ip4_mapped_2);
diff --git a/chromium/net/quic/quic_alarm.cc b/chromium/net/quic/quic_alarm.cc
index 6df6492698d..30edcaa4423 100644
--- a/chromium/net/quic/quic_alarm.cc
+++ b/chromium/net/quic/quic_alarm.cc
@@ -5,37 +5,42 @@
#include "net/quic/quic_alarm.h"
#include "base/logging.h"
+#include "net/quic/quic_flags.h"
namespace net {
-QuicAlarm::QuicAlarm(Delegate* delegate)
- : delegate_(delegate), deadline_(QuicTime::Zero()) {}
+QuicAlarm::QuicAlarm(QuicArenaScopedPtr<Delegate> delegate)
+ : delegate_(std::move(delegate)), deadline_(QuicTime::Zero()) {}
QuicAlarm::~QuicAlarm() {}
-void QuicAlarm::Set(QuicTime deadline) {
+void QuicAlarm::Set(QuicTime new_deadline) {
DCHECK(!IsSet());
- DCHECK(deadline.IsInitialized());
- deadline_ = deadline;
+ DCHECK(new_deadline.IsInitialized());
+ deadline_ = new_deadline;
SetImpl();
}
void QuicAlarm::Cancel() {
+ if (!IsSet()) {
+ // Don't try to cancel an alarm that hasn't been set.
+ return;
+ }
deadline_ = QuicTime::Zero();
CancelImpl();
}
-void QuicAlarm::Update(QuicTime deadline, QuicTime::Delta granularity) {
- if (!deadline.IsInitialized()) {
+void QuicAlarm::Update(QuicTime new_deadline, QuicTime::Delta granularity) {
+ if (!new_deadline.IsInitialized()) {
Cancel();
return;
}
- if (std::abs(deadline.Subtract(deadline_).ToMicroseconds()) <
+ if (std::abs(new_deadline.Subtract(deadline_).ToMicroseconds()) <
granularity.ToMicroseconds()) {
return;
}
Cancel();
- Set(deadline);
+ Set(new_deadline);
}
bool QuicAlarm::IsSet() const {
@@ -43,17 +48,12 @@ bool QuicAlarm::IsSet() const {
}
void QuicAlarm::Fire() {
- if (!deadline_.IsInitialized()) {
+ if (!IsSet()) {
return;
}
deadline_ = QuicTime::Zero();
- QuicTime deadline = delegate_->OnAlarm();
- // delegate_->OnAlarm() might call Set(), in which case deadline_ will
- // already contain the new value, so don't overwrite it.
- if (!deadline_.IsInitialized() && deadline.IsInitialized()) {
- Set(deadline);
- }
+ delegate_->OnAlarm();
}
} // namespace net
diff --git a/chromium/net/quic/quic_alarm.h b/chromium/net/quic/quic_alarm.h
index 48cd5ef0b3f..53a823fd425 100644
--- a/chromium/net/quic/quic_alarm.h
+++ b/chromium/net/quic/quic_alarm.h
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/net_export.h"
+#include "net/quic/quic_arena_scoped_ptr.h"
#include "net/quic/quic_time.h"
namespace net {
@@ -23,19 +24,17 @@ class NET_EXPORT_PRIVATE QuicAlarm {
public:
virtual ~Delegate() {}
- // Invoked when the alarm fires. If the return value is not
- // infinite, then the alarm will be rescheduled at the
- // specified time.
- virtual QuicTime OnAlarm() = 0;
+ // Invoked when the alarm fires.
+ virtual void OnAlarm() = 0;
};
- explicit QuicAlarm(Delegate* delegate);
+ explicit QuicAlarm(QuicArenaScopedPtr<Delegate> delegate);
virtual ~QuicAlarm();
// Sets the alarm to fire at |deadline|. Must not be called while
// the alarm is set. To reschedule an alarm, call Cancel() first,
// then Set().
- void Set(QuicTime deadline);
+ void Set(QuicTime new_deadline);
// Cancels the alarm. May be called repeatedly. Does not
// guarantee that the underlying scheduling system will remove
@@ -46,8 +45,9 @@ class NET_EXPORT_PRIVATE QuicAlarm {
// Cancels and sets the alarm if the |deadline| is farther from the current
// deadline than |granularity|, and otherwise does nothing. If |deadline| is
// not initialized, the alarm is cancelled.
- void Update(QuicTime deadline, QuicTime::Delta granularity);
+ void Update(QuicTime new_deadline, QuicTime::Delta granularity);
+ // Returns true if |deadline_| has been set to a non-zero time.
bool IsSet() const;
QuicTime deadline() const { return deadline_; }
@@ -72,7 +72,7 @@ class NET_EXPORT_PRIVATE QuicAlarm {
void Fire();
private:
- scoped_ptr<Delegate> delegate_;
+ QuicArenaScopedPtr<Delegate> delegate_;
QuicTime deadline_;
DISALLOW_COPY_AND_ASSIGN(QuicAlarm);
diff --git a/chromium/net/quic/quic_alarm_test.cc b/chromium/net/quic/quic_alarm_test.cc
index 42d44a2042b..0509090e747 100644
--- a/chromium/net/quic/quic_alarm_test.cc
+++ b/chromium/net/quic/quic_alarm_test.cc
@@ -17,12 +17,28 @@ namespace {
class MockDelegate : public QuicAlarm::Delegate {
public:
- MOCK_METHOD0(OnAlarm, QuicTime());
+ MOCK_METHOD0(OnAlarm, void());
+};
+
+class DestructiveDelegate : public QuicAlarm::Delegate {
+ public:
+ DestructiveDelegate() : alarm_(nullptr) {}
+
+ void set_alarm(QuicAlarm* alarm) { alarm_ = alarm; }
+
+ void OnAlarm() override {
+ DCHECK(alarm_);
+ delete alarm_;
+ }
+
+ private:
+ QuicAlarm* alarm_;
};
class TestAlarm : public QuicAlarm {
public:
- explicit TestAlarm(QuicAlarm::Delegate* delegate) : QuicAlarm(delegate) {}
+ explicit TestAlarm(QuicAlarm::Delegate* delegate)
+ : QuicAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate)) {}
bool scheduled() const { return scheduled_; }
@@ -46,6 +62,19 @@ class TestAlarm : public QuicAlarm {
bool scheduled_;
};
+class DestructiveAlarm : public QuicAlarm {
+ public:
+ explicit DestructiveAlarm(DestructiveDelegate* delegate)
+ : QuicAlarm(QuicArenaScopedPtr<DestructiveDelegate>(delegate)) {}
+
+ void FireAlarm() { Fire(); }
+
+ protected:
+ void SetImpl() override {}
+
+ void CancelImpl() override {}
+};
+
class QuicAlarmTest : public ::testing::Test {
public:
QuicAlarmTest()
@@ -107,34 +136,33 @@ TEST_F(QuicAlarmTest, UpdateWithZero) {
TEST_F(QuicAlarmTest, Fire) {
QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7));
alarm_.Set(deadline);
- EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Return(QuicTime::Zero()));
alarm_.FireAlarm();
EXPECT_FALSE(alarm_.IsSet());
EXPECT_FALSE(alarm_.scheduled());
EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
}
-TEST_F(QuicAlarmTest, FireAndResetViaReturn) {
- alarm_.Set(deadline_);
- EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Return(deadline2_));
- alarm_.FireAlarm();
- EXPECT_TRUE(alarm_.IsSet());
- EXPECT_TRUE(alarm_.scheduled());
- EXPECT_EQ(deadline2_, alarm_.deadline());
-}
-
TEST_F(QuicAlarmTest, FireAndResetViaSet) {
alarm_.Set(deadline_);
new_deadline_ = deadline2_;
EXPECT_CALL(*delegate_, OnAlarm())
- .WillOnce(DoAll(Invoke(this, &QuicAlarmTest::ResetAlarm),
- Return(QuicTime::Zero())));
+ .WillOnce(Invoke(this, &QuicAlarmTest::ResetAlarm));
alarm_.FireAlarm();
EXPECT_TRUE(alarm_.IsSet());
EXPECT_TRUE(alarm_.scheduled());
EXPECT_EQ(deadline2_, alarm_.deadline());
}
+TEST_F(QuicAlarmTest, FireDestroysAlarm) {
+ DestructiveDelegate* delegate(new DestructiveDelegate);
+ DestructiveAlarm* alarm = new DestructiveAlarm(delegate);
+ delegate->set_alarm(alarm);
+ QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7));
+ alarm->Set(deadline);
+ // This should not crash, even though it will destroy alarm.
+ alarm->FireAlarm();
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_arena_scoped_ptr.h b/chromium/net/quic/quic_arena_scoped_ptr.h
new file mode 100644
index 00000000000..5083036f907
--- /dev/null
+++ b/chromium/net/quic/quic_arena_scoped_ptr.h
@@ -0,0 +1,210 @@
+// 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.
+
+// unique_ptr-style pointer that stores values that may be from an arena. Takes
+// up the same storage as the platform's native pointer type. Takes ownership
+// of the value it's constructed with; if holding a value in an arena, and the
+// 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_
+
+#include <cstdint> // for uintptr_t
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "net/quic/quic_utils.h"
+
+namespace net {
+
+template <typename T>
+class QuicArenaScopedPtr {
+ static_assert(QUIC_ALIGN_OF(T*) > 1,
+ "QuicArenaScopedPtr can only store objects that are aligned to "
+ "greater than 1 byte.");
+
+ public:
+ // Constructs an empty QuicArenaScopedPtr.
+ QuicArenaScopedPtr();
+
+ // Constructs a QuicArenaScopedPtr referencing the heap-allocated memory
+ // provided.
+ explicit QuicArenaScopedPtr(T* value);
+
+ template <typename U>
+ QuicArenaScopedPtr(QuicArenaScopedPtr<U>&& other); // NOLINT
+ template <typename U>
+ QuicArenaScopedPtr& operator=(QuicArenaScopedPtr<U>&& other);
+ ~QuicArenaScopedPtr();
+
+ // Returns a pointer to the value.
+ T* get() const;
+
+ // Returns a reference to the value.
+ T& operator*() const;
+
+ // Returns a pointer to the value.
+ T* operator->() const;
+
+ // Swaps the value of this pointer with |other|.
+ void swap(QuicArenaScopedPtr& other);
+
+ // Resets the held value to |value|.
+ void reset(T* value = nullptr);
+
+ // Returns true if |this| came from an arena. Primarily exposed for testing
+ // and assertions.
+ bool is_from_arena();
+
+ private:
+ // Friends with other derived types of QuicArenaScopedPtr, to support the
+ // derived-types case.
+ template <typename U>
+ friend class QuicArenaScopedPtr;
+ // Also befriend all known arenas, only to prevent misuse.
+ template <uint32_t ArenaSize>
+ friend class QuicOneBlockArena;
+
+ // Tag to denote that a QuicArenaScopedPtr is being explicitly created by an
+ // arena.
+ enum class ConstructFrom { kHeap, kArena };
+
+ // Constructs a QuicArenaScopedPtr with the given representation.
+ QuicArenaScopedPtr(void* value, ConstructFrom from);
+
+ // Low-order bits of value_ that determine if the pointer came from an arena.
+ static const uintptr_t kFromArenaMask = 0x1;
+
+ // Every platform we care about has at least 4B aligned integers, so store the
+ // is_from_arena bit in the least significant bit.
+ void* value_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicArenaScopedPtr);
+};
+
+template <typename T>
+bool operator==(const QuicArenaScopedPtr<T>& left,
+ const QuicArenaScopedPtr<T>& right) {
+ return left.get() == right.get();
+}
+
+template <typename T>
+bool operator!=(const QuicArenaScopedPtr<T>& left,
+ const QuicArenaScopedPtr<T>& right) {
+ return left.get() != right.get();
+}
+
+template <typename T>
+bool operator==(std::nullptr_t, const QuicArenaScopedPtr<T>& right) {
+ return nullptr == right.get();
+}
+
+template <typename T>
+bool operator!=(std::nullptr_t, const QuicArenaScopedPtr<T>& right) {
+ return nullptr != right.get();
+}
+
+template <typename T>
+bool operator==(const QuicArenaScopedPtr<T>& left, std::nullptr_t) {
+ return left.get() == nullptr;
+}
+
+template <typename T>
+bool operator!=(const QuicArenaScopedPtr<T>& left, std::nullptr_t) {
+ return left.get() != nullptr;
+}
+
+template <typename T>
+QuicArenaScopedPtr<T>::QuicArenaScopedPtr()
+ : value_(nullptr) {}
+
+template <typename T>
+QuicArenaScopedPtr<T>::QuicArenaScopedPtr(T* value)
+ : QuicArenaScopedPtr(value, ConstructFrom::kHeap) {}
+
+template <typename T>
+template <typename U>
+QuicArenaScopedPtr<T>::QuicArenaScopedPtr(QuicArenaScopedPtr<U>&& other)
+ : value_(other.value_) {
+ static_assert(
+ std::is_base_of<T, U>::value || std::is_same<T, U>::value,
+ "Cannot construct QuicArenaScopedPtr; type is not derived or same.");
+ other.value_ = nullptr;
+}
+
+template <typename T>
+template <typename U>
+QuicArenaScopedPtr<T>& QuicArenaScopedPtr<T>::operator=(
+ QuicArenaScopedPtr<U>&& other) {
+ static_assert(
+ std::is_base_of<T, U>::value || std::is_same<T, U>::value,
+ "Cannot assign QuicArenaScopedPtr; type is not derived or same.");
+ swap(other);
+ return *this;
+}
+
+template <typename T>
+QuicArenaScopedPtr<T>::~QuicArenaScopedPtr() {
+ reset();
+}
+
+template <typename T>
+T* QuicArenaScopedPtr<T>::get() const {
+ return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(value_) &
+ ~kFromArenaMask);
+}
+
+template <typename T>
+T& QuicArenaScopedPtr<T>::operator*() const {
+ return *get();
+}
+
+template <typename T>
+T* QuicArenaScopedPtr<T>::operator->() const {
+ return get();
+}
+
+template <typename T>
+void QuicArenaScopedPtr<T>::swap(QuicArenaScopedPtr& other) {
+ using std::swap;
+ swap(value_, other.value_);
+}
+
+template <typename T>
+bool QuicArenaScopedPtr<T>::is_from_arena() {
+ return (reinterpret_cast<uintptr_t>(value_) & kFromArenaMask) != 0;
+}
+
+template <typename T>
+void QuicArenaScopedPtr<T>::reset(T* value) {
+ if (value_ != nullptr) {
+ if (is_from_arena()) {
+ // Manually invoke the destructor.
+ get()->~T();
+ } else {
+ delete get();
+ }
+ }
+ DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(value) & kFromArenaMask);
+ value_ = value;
+}
+
+template <typename T>
+QuicArenaScopedPtr<T>::QuicArenaScopedPtr(void* value, ConstructFrom from_arena)
+ : value_(value) {
+ DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(value_) & kFromArenaMask);
+ switch (from_arena) {
+ case ConstructFrom::kHeap:
+ break;
+ case ConstructFrom::kArena:
+ value_ = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(value_) |
+ QuicArenaScopedPtr<T>::kFromArenaMask);
+ break;
+ }
+}
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_ARENA_SCOPED_PTR_H_
diff --git a/chromium/net/quic/quic_arena_scoped_ptr_test.cc b/chromium/net/quic/quic_arena_scoped_ptr_test.cc
new file mode 100644
index 00000000000..22c9ebb8bcb
--- /dev/null
+++ b/chromium/net/quic/quic_arena_scoped_ptr_test.cc
@@ -0,0 +1,102 @@
+// 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/quic_arena_scoped_ptr.h"
+
+#include "net/quic/quic_one_block_arena.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace {
+
+enum class TestParam { kFromHeap, kFromArena };
+
+struct TestObject {
+ explicit TestObject(uintptr_t value) : value(value) { buffer.resize(1024); }
+ uintptr_t value;
+
+ // Ensure that we have a non-trivial destructor that will leak memory if it's
+ // not called.
+ std::vector<char> buffer;
+};
+
+class QuicArenaScopedPtrParamTest : public ::testing::TestWithParam<TestParam> {
+ protected:
+ QuicArenaScopedPtr<TestObject> CreateObject(uintptr_t value) {
+ QuicArenaScopedPtr<TestObject> ptr;
+ switch (GetParam()) {
+ case TestParam::kFromHeap:
+ ptr = QuicArenaScopedPtr<TestObject>(new TestObject(value));
+ CHECK(!ptr.is_from_arena());
+ break;
+ case TestParam::kFromArena:
+ ptr = arena_.New<TestObject>(value);
+ CHECK(ptr.is_from_arena());
+ break;
+ }
+ return ptr;
+ }
+
+ private:
+ QuicOneBlockArena<1024> arena_;
+};
+
+INSTANTIATE_TEST_CASE_P(QuicArenaScopedPtrParamTest,
+ QuicArenaScopedPtrParamTest,
+ testing::Values(TestParam::kFromHeap,
+ TestParam::kFromArena));
+
+TEST(QuicArenaScopedPtrTest, NullObjects) {
+ QuicArenaScopedPtr<TestObject> def;
+ QuicArenaScopedPtr<TestObject> null(nullptr);
+ EXPECT_EQ(def, null);
+ EXPECT_EQ(def, nullptr);
+ EXPECT_EQ(null, nullptr);
+}
+
+TEST(QuicArenaScopedPtrTest, FromArena) {
+ QuicOneBlockArena<1024> arena_;
+ EXPECT_TRUE(arena_.New<TestObject>(0).is_from_arena());
+ EXPECT_FALSE(
+ QuicArenaScopedPtr<TestObject>(new TestObject(0)).is_from_arena());
+}
+
+TEST_P(QuicArenaScopedPtrParamTest, Assign) {
+ QuicArenaScopedPtr<TestObject> ptr = CreateObject(12345);
+ ptr = CreateObject(54321);
+ EXPECT_EQ(54321u, ptr->value);
+}
+
+TEST_P(QuicArenaScopedPtrParamTest, MoveConstruct) {
+ QuicArenaScopedPtr<TestObject> ptr1 = CreateObject(12345);
+ QuicArenaScopedPtr<TestObject> ptr2(std::move(ptr1));
+ EXPECT_EQ(nullptr, ptr1);
+ EXPECT_EQ(12345u, ptr2->value);
+}
+
+TEST_P(QuicArenaScopedPtrParamTest, Accessors) {
+ QuicArenaScopedPtr<TestObject> ptr = CreateObject(12345);
+ EXPECT_EQ(12345u, (*ptr).value);
+ EXPECT_EQ(12345u, ptr->value);
+ // We explicitly want to test that get() returns a valid pointer to the data,
+ // but the call looks redundant.
+ EXPECT_EQ(12345u, ptr.get()->value); // NOLINT
+}
+
+TEST_P(QuicArenaScopedPtrParamTest, Reset) {
+ QuicArenaScopedPtr<TestObject> ptr = CreateObject(12345);
+ ptr.reset(new TestObject(54321));
+ EXPECT_EQ(54321u, ptr->value);
+}
+
+TEST_P(QuicArenaScopedPtrParamTest, Swap) {
+ QuicArenaScopedPtr<TestObject> ptr1 = CreateObject(12345);
+ QuicArenaScopedPtr<TestObject> ptr2 = CreateObject(54321);
+ ptr1.swap(ptr2);
+ EXPECT_EQ(12345u, ptr2->value);
+ EXPECT_EQ(54321u, ptr1->value);
+}
+
+} // namespace
+} // namespace net
diff --git a/chromium/net/quic/quic_bandwidth.cc b/chromium/net/quic/quic_bandwidth.cc
index b7fe66dfd23..734858d5bbb 100644
--- a/chromium/net/quic/quic_bandwidth.cc
+++ b/chromium/net/quic/quic_bandwidth.cc
@@ -7,6 +7,7 @@
#include <stdint.h>
#include "base/logging.h"
+#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_time.h"
#include "net/quic/quic_types.h"
@@ -55,7 +56,12 @@ QuicBandwidth QuicBandwidth::FromBytesAndTimeDelta(QuicByteCount bytes,
QuicBandwidth::QuicBandwidth(int64_t bits_per_second)
: bits_per_second_(bits_per_second) {
- DCHECK_GE(bits_per_second, 0);
+ if (bits_per_second < 0) {
+ QUIC_BUG << "Can't set negative bandwidth " << bits_per_second;
+ bits_per_second_ = 0;
+ return;
+ }
+ bits_per_second_ = bits_per_second;
}
int64_t QuicBandwidth::ToBitsPerSecond() const {
@@ -89,11 +95,11 @@ bool QuicBandwidth::IsZero() const {
return (bits_per_second_ == 0);
}
-QuicBandwidth QuicBandwidth::Add(const QuicBandwidth& delta) const {
+QuicBandwidth QuicBandwidth::Add(QuicBandwidth delta) const {
return QuicBandwidth(bits_per_second_ + delta.bits_per_second_);
}
-QuicBandwidth QuicBandwidth::Subtract(const QuicBandwidth& delta) const {
+QuicBandwidth QuicBandwidth::Subtract(QuicBandwidth delta) const {
return QuicBandwidth(bits_per_second_ - delta.bits_per_second_);
}
diff --git a/chromium/net/quic/quic_bandwidth.h b/chromium/net/quic/quic_bandwidth.h
index 8c092beeeda..215ee25fc04 100644
--- a/chromium/net/quic/quic_bandwidth.h
+++ b/chromium/net/quic/quic_bandwidth.h
@@ -52,9 +52,9 @@ class NET_EXPORT_PRIVATE QuicBandwidth {
bool IsZero() const;
- QuicBandwidth Add(const QuicBandwidth& delta) const WARN_UNUSED_RESULT;
+ QuicBandwidth Add(QuicBandwidth delta) const WARN_UNUSED_RESULT;
- QuicBandwidth Subtract(const QuicBandwidth& delta) const WARN_UNUSED_RESULT;
+ QuicBandwidth Subtract(QuicBandwidth delta) const WARN_UNUSED_RESULT;
QuicBandwidth Scale(float scale_factor) const WARN_UNUSED_RESULT;
diff --git a/chromium/net/quic/quic_blocked_writer_interface.h b/chromium/net/quic/quic_blocked_writer_interface.h
index 78a270af12f..a3a2622a599 100644
--- a/chromium/net/quic/quic_blocked_writer_interface.h
+++ b/chromium/net/quic/quic_blocked_writer_interface.h
@@ -24,20 +24,15 @@ class NET_EXPORT_PRIVATE QuicBlockedWriterInterface {
virtual void OnCanWrite() = 0;
};
-} // namespace net
-
-#if defined(COMPILER_GCC)
-namespace BASE_HASH_NAMESPACE {
// Hash pointers as if they were int's, but bring more entropy to the lower
// bits.
-template <>
-struct hash<net::QuicBlockedWriterInterface*> {
+struct QuicBlockedWriterInterfacePtrHash {
std::size_t operator()(const net::QuicBlockedWriterInterface* ptr) const {
size_t k = reinterpret_cast<size_t>(ptr);
return k + (k >> 6);
}
};
-}
-#endif
+
+} // namespace net
#endif // NET_QUIC_QUIC_BLOCKED_WRITER_INTERFACE_H_
diff --git a/chromium/net/quic/quic_bug_tracker.h b/chromium/net/quic/quic_bug_tracker.h
index bbec94bd09d..280a537d0e7 100644
--- a/chromium/net/quic/quic_bug_tracker.h
+++ b/chromium/net/quic/quic_bug_tracker.h
@@ -4,7 +4,10 @@
#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) as client-side
-// log rate limiting is less important and chrome doesn't LOG_FIRST_N anyway.
+// 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/quic_chromium_client_session.cc b/chromium/net/quic/quic_chromium_client_session.cc
index c30b69fc6c1..afb07468ecf 100644
--- a/chromium/net/quic/quic_chromium_client_session.cc
+++ b/chromium/net/quic/quic_chromium_client_session.cc
@@ -18,17 +18,21 @@
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/network_activity_monitor.h"
+#include "net/http/http_log_util.h"
#include "net/http/transport_security_state.h"
#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/quic/crypto/quic_server_info.h"
#include "net/quic/quic_chromium_connection_helper.h"
+#include "net/quic/quic_client_promised_info.h"
#include "net/quic/quic_crypto_client_stream_factory.h"
+#include "net/quic/quic_protocol.h"
#include "net/quic/quic_server_id.h"
#include "net/quic/quic_stream_factory.h"
#include "net/spdy/spdy_session.h"
#include "net/ssl/channel_id_service.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_info.h"
+#include "net/ssl/token_binding.h"
#include "net/udp/datagram_client_socket.h"
namespace net {
@@ -47,6 +51,12 @@ const size_t kAdditionalOverheadForIPv6 = 20;
// IP address changes.
const size_t kMaxReadersPerQuicSession = 5;
+// Size of the MRU cache of Token Binding signatures. Since the material being
+// signed is constant and there aren't many keys being used to sign, a fairly
+// small number was chosen, somewhat arbitrarily, and to match
+// SSLClientSocketOpenssl.
+const size_t kTokenBindingSignatureMapSize = 10;
+
// Histograms for tracking down the crashes from http://crbug.com/354669
// Note: these values must be kept in sync with the corresponding values in:
// tools/metrics/histograms/histograms.xml
@@ -120,6 +130,31 @@ scoped_ptr<base::Value> NetLogQuicClientSessionCallback(
return std::move(dict);
}
+scoped_ptr<base::ListValue> SpdyHeaderBlockToListValue(
+ const SpdyHeaderBlock& headers,
+ NetLogCaptureMode capture_mode) {
+ scoped_ptr<base::ListValue> headers_list(new base::ListValue());
+ for (const auto& it : headers) {
+ headers_list->AppendString(
+ it.first.as_string() + ": " +
+ ElideHeaderValueForNetLog(capture_mode, it.first.as_string(),
+ it.second.as_string()));
+ }
+ return headers_list;
+}
+
+scoped_ptr<base::Value> NetLogQuicPushPromiseReceivedCallback(
+ const SpdyHeaderBlock* headers,
+ SpdyStreamId stream_id,
+ SpdyStreamId promised_stream_id,
+ NetLogCaptureMode capture_mode) {
+ scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ dict->Set("headers", SpdyHeaderBlockToListValue(*headers, capture_mode));
+ dict->SetInteger("id", stream_id);
+ dict->SetInteger("promised_stream_id", promised_stream_id);
+ return std::move(dict);
+}
+
} // namespace
QuicChromiumClientSession::StreamRequest::StreamRequest() : stream_(nullptr) {}
@@ -153,13 +188,13 @@ void QuicChromiumClientSession::StreamRequest::OnRequestCompleteSuccess(
QuicChromiumClientStream* stream) {
session_.reset();
*stream_ = stream;
- ResetAndReturn(&callback_).Run(OK);
+ base::ResetAndReturn(&callback_).Run(OK);
}
void QuicChromiumClientSession::StreamRequest::OnRequestCompleteFailure(
int rv) {
session_.reset();
- ResetAndReturn(&callback_).Run(rv);
+ base::ResetAndReturn(&callback_).Run(rv);
}
QuicChromiumClientSession::QuicChromiumClientSession(
@@ -178,10 +213,11 @@ QuicChromiumClientSession::QuicChromiumClientSession(
QuicCryptoClientConfig* crypto_config,
const char* const connection_description,
base::TimeTicks dns_resolution_end_time,
+ QuicClientPushPromiseIndex* push_promise_index,
base::TaskRunner* task_runner,
scoped_ptr<SocketPerformanceWatcher> socket_performance_watcher,
NetLog* net_log)
- : QuicClientSessionBase(connection, config),
+ : QuicClientSessionBase(connection, push_promise_index, config),
server_id_(server_id),
require_confirmation_(false),
stream_factory_(stream_factory),
@@ -196,10 +232,14 @@ QuicChromiumClientSession::QuicChromiumClientSession(
std::move(socket_performance_watcher),
net_log_)),
going_away_(false),
+ port_migration_detected_(false),
disabled_reason_(QUIC_DISABLED_NOT),
+ token_binding_signatures_(kTokenBindingSignatureMapSize),
+ streams_pushed_count_(0),
+ streams_pushed_and_claimed_count_(0),
weak_factory_(this) {
sockets_.push_back(std::move(socket));
- packet_readers_.push_back(make_scoped_ptr(new QuicPacketReader(
+ packet_readers_.push_back(make_scoped_ptr(new QuicChromiumPacketReader(
sockets_.back().get(), clock, this, yield_after_packets,
yield_after_duration, net_log_)));
crypto_stream_.reset(
@@ -208,6 +248,7 @@ QuicChromiumClientSession::QuicChromiumClientSession(
cert_verify_flags, net_log_)),
crypto_config));
connection->set_debug_visitor(logger_.get());
+ connection->set_creator_debug_delegate(logger_.get());
net_log_.BeginEvent(NetLog::TYPE_QUIC_SESSION,
base::Bind(NetLogQuicClientSessionCallback, &server_id,
cert_verify_flags, require_confirmation_));
@@ -248,7 +289,8 @@ QuicChromiumClientSession::~QuicChromiumClientSession() {
if (connection()->connected()) {
// Ensure that the connection is closed by the time the session is
// destroyed.
- connection()->CloseConnection(QUIC_INTERNAL_ERROR, false);
+ connection()->CloseConnection(QUIC_INTERNAL_ERROR, "session torn down",
+ ConnectionCloseBehavior::SILENT_CLOSE);
}
if (IsEncryptionEstablished())
@@ -261,6 +303,9 @@ QuicChromiumClientSession::~QuicChromiumClientSession() {
UMA_HISTOGRAM_COUNTS("Net.QuicSession.NumTotalStreams", num_total_streams_);
UMA_HISTOGRAM_COUNTS("Net.QuicNumSentClientHellos",
crypto_stream_->num_sent_client_hellos());
+ UMA_HISTOGRAM_COUNTS("Net.QuicSession.Pushed", streams_pushed_count_);
+ UMA_HISTOGRAM_COUNTS("Net.QuicSession.PushedAndClaimed",
+ streams_pushed_and_claimed_count_);
if (!IsCryptoHandshakeConfirmed())
return;
@@ -358,7 +403,7 @@ void QuicChromiumClientSession::OnStreamFrame(const QuicStreamFrame& frame) {
void QuicChromiumClientSession::AddObserver(Observer* observer) {
if (going_away_) {
RecordUnexpectedObservers(ADD_OBSERVER);
- observer->OnSessionClosed(ERR_UNEXPECTED);
+ observer->OnSessionClosed(ERR_UNEXPECTED, port_migration_detected_);
return;
}
@@ -394,7 +439,7 @@ int QuicChromiumClientSession::TryCreateStream(
return ERR_CONNECTION_CLOSED;
}
- if (GetNumOpenOutgoingStreams() < get_max_open_streams()) {
+ if (GetNumOpenOutgoingStreams() < max_open_outgoing_streams()) {
*stream = CreateOutgoingReliableStreamImpl();
return OK;
}
@@ -413,24 +458,31 @@ void QuicChromiumClientSession::CancelRequest(StreamRequest* request) {
}
}
-QuicChromiumClientStream*
-QuicChromiumClientSession::CreateOutgoingDynamicStream(SpdyPriority priority) {
+bool QuicChromiumClientSession::ShouldCreateOutgoingDynamicStream() {
if (!crypto_stream_->encryption_established()) {
DVLOG(1) << "Encryption not active so no outgoing stream created.";
- return nullptr;
+ return false;
}
- if (GetNumOpenOutgoingStreams() >= get_max_open_streams()) {
+ if (GetNumOpenOutgoingStreams() >= max_open_outgoing_streams()) {
DVLOG(1) << "Failed to create a new outgoing stream. "
<< "Already " << GetNumOpenOutgoingStreams() << " open.";
- return nullptr;
+ return false;
}
if (goaway_received()) {
DVLOG(1) << "Failed to create a new outgoing stream. "
<< "Already received goaway.";
- return nullptr;
+ return false;
}
if (going_away_) {
RecordUnexpectedOpenStreams(CREATE_OUTGOING_RELIABLE_STREAM);
+ return false;
+ }
+ return true;
+}
+
+QuicChromiumClientStream*
+QuicChromiumClientSession::CreateOutgoingDynamicStream(SpdyPriority priority) {
+ if (!ShouldCreateOutgoingDynamicStream()) {
return nullptr;
}
return CreateOutgoingReliableStreamImpl();
@@ -478,10 +530,6 @@ bool QuicChromiumClientSession::GetSSLInfo(SSLInfo* ssl_info) const {
cipher_suite = 0xc02f; // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
security_bits = 128;
break;
- case kCC12:
- cipher_suite = 0xcc13; // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- security_bits = 256;
- break;
case kCC20:
cipher_suite = 0xcc13; // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
security_bits = 256;
@@ -507,11 +555,41 @@ bool QuicChromiumClientSession::GetSSLInfo(SSLInfo* ssl_info) const {
ssl_info->handshake_type = SSLInfo::HANDSHAKE_FULL;
ssl_info->pinning_failure_log = pinning_failure_log_;
- ssl_info->UpdateSignedCertificateTimestamps(*ct_verify_result_);
+ ssl_info->UpdateCertificateTransparencyInfo(*ct_verify_result_);
+
+ if (crypto_stream_->crypto_negotiated_params().token_binding_key_param ==
+ kP256) {
+ ssl_info->token_binding_negotiated = true;
+ ssl_info->token_binding_key_param = TB_PARAM_ECDSAP256;
+ }
return true;
}
+Error QuicChromiumClientSession::GetTokenBindingSignature(
+ crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ // The same key will be used across multiple requests to sign the same value,
+ // so the signature is cached.
+ std::string raw_public_key;
+ if (!key->ExportRawPublicKey(&raw_public_key))
+ return ERR_FAILED;
+ TokenBindingSignatureMap::iterator it =
+ token_binding_signatures_.Get(raw_public_key);
+ if (it != token_binding_signatures_.end()) {
+ *out = it->second;
+ return OK;
+ }
+
+ std::string key_material;
+ if (!crypto_stream_->ExportTokenBindingKeyingMaterial(&key_material))
+ return ERR_FAILED;
+ if (!SignTokenBindingEkm(key_material, key, out))
+ return ERR_FAILED;
+ token_binding_signatures_.Put(raw_public_key, *out);
+ return OK;
+}
+
int QuicChromiumClientSession::CryptoConnect(
bool require_confirmation,
const CompletionCallback& callback) {
@@ -573,10 +651,47 @@ bool QuicChromiumClientSession::CanPool(const std::string& hostname,
server_id_.host(), hostname);
}
-QuicSpdyStream* QuicChromiumClientSession::CreateIncomingDynamicStream(
+bool QuicChromiumClientSession::ShouldCreateIncomingDynamicStream(
QuicStreamId id) {
- DLOG(ERROR) << "Server push not supported";
- return nullptr;
+ if (!connection()->connected()) {
+ LOG(DFATAL) << "ShouldCreateIncomingDynamicStream called when disconnected";
+ return false;
+ }
+ if (goaway_received()) {
+ DVLOG(1) << "Cannot create a new outgoing stream. "
+ << "Already received goaway.";
+ return false;
+ }
+ if (going_away_) {
+ return false;
+ }
+ if (id % 2 != 0) {
+ LOG(WARNING) << "Received invalid push stream id " << id;
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Server created odd numbered stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ return true;
+}
+
+QuicChromiumClientStream*
+QuicChromiumClientSession::CreateIncomingDynamicStream(QuicStreamId id) {
+ if (!ShouldCreateIncomingDynamicStream(id)) {
+ return nullptr;
+ }
+ return CreateIncomingReliableStreamImpl(id);
+}
+
+QuicChromiumClientStream*
+QuicChromiumClientSession::CreateIncomingReliableStreamImpl(QuicStreamId id) {
+ DCHECK(connection()->connected());
+ QuicChromiumClientStream* stream =
+ new QuicChromiumClientStream(id, this, net_log_);
+ stream->CloseWriteSide();
+ ActivateStream(stream);
+ ++num_total_streams_;
+ return stream;
}
void QuicChromiumClientSession::CloseStream(QuicStreamId stream_id) {
@@ -597,7 +712,7 @@ void QuicChromiumClientSession::SendRstStream(QuicStreamId id,
}
void QuicChromiumClientSession::OnClosedStream() {
- if (GetNumOpenOutgoingStreams() < get_max_open_streams() &&
+ if (GetNumOpenOutgoingStreams() < max_open_outgoing_streams() &&
!stream_requests_.empty() && crypto_stream_->encryption_established() &&
!goaway_received() && !going_away_ && connection()->connected()) {
StreamRequest* request = stream_requests_.front();
@@ -683,6 +798,7 @@ void QuicChromiumClientSession::OnCryptoHandshakeMessageReceived(
void QuicChromiumClientSession::OnGoAway(const QuicGoAwayFrame& frame) {
QuicSession::OnGoAway(frame);
NotifyFactoryOfSessionGoingAway();
+ port_migration_detected_ = frame.error_code == QUIC_ERROR_MIGRATING_PORT;
}
void QuicChromiumClientSession::OnRstStream(const QuicRstStreamFrame& frame) {
@@ -690,11 +806,13 @@ void QuicChromiumClientSession::OnRstStream(const QuicRstStreamFrame& frame) {
OnClosedStream();
}
-void QuicChromiumClientSession::OnConnectionClosed(QuicErrorCode error,
- bool from_peer) {
+void QuicChromiumClientSession::OnConnectionClosed(
+ QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) {
DCHECK(!connection()->connected());
- logger_->OnConnectionClosed(error, from_peer);
- if (from_peer) {
+ logger_->OnConnectionClosed(error, error_details, source);
+ if (source == ConnectionCloseSource::FROM_PEER) {
if (IsCryptoHandshakeConfirmed()) {
UMA_HISTOGRAM_SPARSE_SLOWLY(
"Net.QuicSession.ConnectionCloseErrorCodeServer.HandshakeConfirmed",
@@ -712,7 +830,7 @@ void QuicChromiumClientSession::OnConnectionClosed(QuicErrorCode error,
"Net.QuicSession.ConnectionCloseErrorCodeClient", error);
}
- if (error == QUIC_CONNECTION_TIMED_OUT) {
+ if (error == QUIC_NETWORK_IDLE_TIMEOUT) {
UMA_HISTOGRAM_COUNTS(
"Net.QuicSession.ConnectionClose.NumOpenStreams.TimedOut",
GetNumOpenOutgoingStreams());
@@ -772,6 +890,8 @@ void QuicChromiumClientSession::OnConnectionClosed(QuicErrorCode error,
UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.QuicVersion",
connection()->version());
NotifyFactoryOfSessionGoingAway();
+ QuicSession::OnConnectionClosed(error, error_details, source);
+
if (!callback_.is_null()) {
base::ResetAndReturn(&callback_).Run(ERR_QUIC_PROTOCOL_ERROR);
}
@@ -779,7 +899,6 @@ void QuicChromiumClientSession::OnConnectionClosed(QuicErrorCode error,
for (auto& socket : sockets_) {
socket->Close();
}
- QuicSession::OnConnectionClosed(error, from_peer);
DCHECK(dynamic_streams().empty());
CloseAllStreams(ERR_UNEXPECTED);
CloseAllObservers(ERR_UNEXPECTED);
@@ -792,6 +911,10 @@ void QuicChromiumClientSession::OnSuccessfulVersionNegotiation(
QuicSpdySession::OnSuccessfulVersionNegotiation(version);
}
+void QuicChromiumClientSession::OnPathDegrading() {
+ stream_factory_->MaybeMigrateSessionEarly(this);
+}
+
void QuicChromiumClientSession::OnProofValid(
const QuicCryptoClientConfig::CachedState& cached) {
DCHECK(cached.proof_valid());
@@ -804,6 +927,8 @@ void QuicChromiumClientSession::OnProofValid(
state->server_config = cached.server_config();
state->source_address_token = cached.source_address_token();
+ state->cert_sct = cached.cert_sct();
+ state->chlo_hash = cached.chlo_hash();
state->server_config_sig = cached.signature();
state->certs = cached.certs();
@@ -861,7 +986,8 @@ void QuicChromiumClientSession::CloseSessionOnErrorInner(
NetLog::IntCallback("net_error", net_error));
if (connection()->connected())
- connection()->CloseConnection(quic_error, false);
+ connection()->CloseConnection(quic_error, "net error",
+ ConnectionCloseBehavior::SILENT_CLOSE);
DCHECK(!connection()->connected());
}
@@ -878,7 +1004,7 @@ void QuicChromiumClientSession::CloseAllObservers(int net_error) {
while (!observers_.empty()) {
Observer* observer = *observers_.begin();
observers_.erase(observer);
- observer->OnSessionClosed(net_error);
+ observer->OnSessionClosed(net_error, port_migration_detected_);
}
}
@@ -888,8 +1014,7 @@ scoped_ptr<base::Value> QuicChromiumClientSession::GetInfoAsValue(
dict->SetString("version", QuicVersionToString(connection()->version()));
dict->SetInteger("open_streams", GetNumOpenOutgoingStreams());
scoped_ptr<base::ListValue> stream_list(new base::ListValue());
- for (base::hash_map<QuicStreamId, ReliableQuicStream*>::const_iterator it =
- dynamic_streams().begin();
+ for (StreamMap::const_iterator it = dynamic_streams().begin();
it != dynamic_streams().end(); ++it) {
stream_list->Append(
new base::StringValue(base::UintToString(it->second->id())));
@@ -938,10 +1063,10 @@ void QuicChromiumClientSession::OnReadError(
NotifyFactoryOfSessionClosedLater();
}
-bool QuicChromiumClientSession::OnPacket(const QuicEncryptedPacket& packet,
+bool QuicChromiumClientSession::OnPacket(const QuicReceivedPacket& packet,
IPEndPoint local_address,
IPEndPoint peer_address) {
- connection()->ProcessUdpPacket(local_address, peer_address, packet);
+ ProcessUdpPacket(local_address, peer_address, packet);
if (!connection()->connected()) {
NotifyFactoryOfSessionClosedLater();
return false;
@@ -1001,7 +1126,7 @@ void QuicChromiumClientSession::OnConnectTimeout() {
bool QuicChromiumClientSession::MigrateToSocket(
scoped_ptr<DatagramClientSocket> socket,
- scoped_ptr<QuicPacketReader> reader,
+ scoped_ptr<QuicChromiumPacketReader> reader,
scoped_ptr<QuicPacketWriter> writer) {
DCHECK_EQ(sockets_.size(), packet_readers_.size());
if (sockets_.size() >= kMaxReadersPerQuicSession) {
@@ -1016,6 +1141,11 @@ bool QuicChromiumClientSession::MigrateToSocket(
return true;
}
+void QuicChromiumClientSession::PopulateNetErrorDetails(
+ NetErrorDetails* details) {
+ details->quic_port_migration_detected = port_migration_detected_;
+}
+
const DatagramClientSocket* QuicChromiumClientSession::GetDefaultSocket()
const {
DCHECK(sockets_.back().get() != nullptr);
@@ -1023,4 +1153,35 @@ const DatagramClientSocket* QuicChromiumClientSession::GetDefaultSocket()
return sockets_.back().get();
}
+bool QuicChromiumClientSession::IsAuthorized(const std::string& hostname) {
+ bool result = CanPool(hostname, server_id_.privacy_mode());
+ if (result)
+ streams_pushed_count_++;
+ return result;
+}
+
+bool QuicChromiumClientSession::HasNonMigratableStreams() const {
+ for (const auto& stream : dynamic_streams()) {
+ if (!static_cast<QuicChromiumClientStream*>(stream.second)->can_migrate())
+ return true;
+ }
+ return false;
+}
+
+void QuicChromiumClientSession::HandlePromised(QuicStreamId id,
+ QuicStreamId promised_id,
+ const SpdyHeaderBlock& headers) {
+ QuicClientSessionBase::HandlePromised(id, promised_id, headers);
+ net_log_.AddEvent(NetLog::TYPE_QUIC_SESSION_PUSH_PROMISE_RECEIVED,
+ base::Bind(&NetLogQuicPushPromiseReceivedCallback, &headers,
+ id, promised_id));
+}
+
+void QuicChromiumClientSession::DeletePromised(
+ QuicClientPromisedInfo* promised) {
+ if (IsOpenStream(promised->id()))
+ streams_pushed_and_claimed_count_++;
+ QuicClientSessionBase::DeletePromised(promised);
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_chromium_client_session.h b/chromium/net/quic/quic_chromium_client_session.h
index e47f4146788..a9e636b6f50 100644
--- a/chromium/net/quic/quic_chromium_client_session.h
+++ b/chromium/net/quic/quic_chromium_client_session.h
@@ -14,19 +14,20 @@
#include <string>
-#include "base/containers/hash_tables.h"
+#include "base/containers/mru_cache.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "net/base/completion_callback.h"
+#include "net/base/net_error_details.h"
#include "net/base/socket_performance_watcher.h"
#include "net/cert/ct_verify_result.h"
#include "net/proxy/proxy_server.h"
#include "net/quic/quic_chromium_client_stream.h"
+#include "net/quic/quic_chromium_packet_reader.h"
#include "net/quic/quic_client_session_base.h"
#include "net/quic/quic_connection_logger.h"
#include "net/quic/quic_crypto_client_stream.h"
-#include "net/quic/quic_packet_reader.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_time.h"
@@ -42,13 +43,16 @@ class QuicStreamFactory;
class SSLInfo;
class TransportSecurityState;
+using TokenBindingSignatureMap =
+ base::MRUCache<std::string, std::vector<uint8_t>>;
+
namespace test {
class QuicChromiumClientSessionPeer;
} // namespace test
class NET_EXPORT_PRIVATE QuicChromiumClientSession
: public QuicClientSessionBase,
- public QuicPacketReader::Visitor {
+ public QuicChromiumPacketReader::Visitor {
public:
// Reasons to disable QUIC, that is under certain pathological
// connection errors. Note: these values must be kept in sync with
@@ -67,7 +71,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
public:
virtual ~Observer() {}
virtual void OnCryptoHandshakeConfirmed() = 0;
- virtual void OnSessionClosed(int error) = 0;
+ virtual void OnSessionClosed(int error, bool port_migration_detected) = 0;
};
// A helper class used to manage a request to create a stream.
@@ -126,6 +130,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
QuicCryptoClientConfig* crypto_config,
const char* const connection_description,
base::TimeTicks dns_resolution_end_time,
+ QuicClientPushPromiseIndex* push_promise_index,
base::TaskRunner* task_runner,
scoped_ptr<SocketPerformanceWatcher> socket_performance_watcher,
NetLog* net_log);
@@ -173,18 +178,26 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
const ProofVerifyDetails& verify_details) override;
// QuicConnectionVisitorInterface methods:
- void OnConnectionClosed(QuicErrorCode error, bool from_peer) override;
+ void OnConnectionClosed(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) override;
void OnSuccessfulVersionNegotiation(const QuicVersion& version) override;
+ void OnPathDegrading() override;
- // QuicPacketReader::Visitor methods:
+ // QuicChromiumPacketReader::Visitor methods:
void OnReadError(int result, const DatagramClientSocket* socket) override;
- bool OnPacket(const QuicEncryptedPacket& packet,
+ bool OnPacket(const QuicReceivedPacket& packet,
IPEndPoint local_address,
IPEndPoint peer_address) override;
// Gets the SSL connection information.
bool GetSSLInfo(SSLInfo* ssl_info) const;
+ // Signs the exported keying material used for Token Binding using key |*key|
+ // and puts the signature in |*out|. Returns a net error code.
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out);
+
// Performs a crypto handshake with the server.
int CryptoConnect(bool require_confirmation,
const CompletionCallback& callback);
@@ -232,17 +245,35 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// Returns false if number of migrations exceeds kMaxReadersPerQuicSession.
// Takes ownership of |socket|, |reader|, and |writer|.
bool MigrateToSocket(scoped_ptr<DatagramClientSocket> socket,
- scoped_ptr<QuicPacketReader> reader,
+ scoped_ptr<QuicChromiumPacketReader> reader,
scoped_ptr<QuicPacketWriter> writer);
+ // Populates network error details for this session.
+ void PopulateNetErrorDetails(NetErrorDetails* details);
+
// Returns current default socket. This is the socket over which all
// QUIC packets are sent. This default socket can change, so do not store the
// returned socket.
const DatagramClientSocket* GetDefaultSocket() const;
+ bool IsAuthorized(const std::string& hostname) override;
+
+ // Returns true if session has one ore more streams marked as non-migratable.
+ bool HasNonMigratableStreams() const;
+
+ void HandlePromised(QuicStreamId associated_id,
+ QuicStreamId promised_id,
+ const SpdyHeaderBlock& headers) override;
+
+ void DeletePromised(QuicClientPromisedInfo* promised) override;
+
protected:
// QuicSession methods:
- QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override;
+ bool ShouldCreateIncomingDynamicStream(QuicStreamId id) override;
+ bool ShouldCreateOutgoingDynamicStream() override;
+
+ QuicChromiumClientStream* CreateIncomingDynamicStream(
+ QuicStreamId id) override;
private:
friend class test::QuicChromiumClientSessionPeer;
@@ -251,6 +282,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
typedef std::list<StreamRequest*> StreamRequestQueue;
QuicChromiumClientStream* CreateOutgoingReliableStreamImpl();
+ QuicChromiumClientStream* CreateIncomingReliableStreamImpl(QuicStreamId id);
// A completion callback invoked when a read completes.
void OnReadComplete(int result);
@@ -301,14 +333,20 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
size_t num_total_streams_;
base::TaskRunner* task_runner_;
BoundNetLog net_log_;
- std::vector<scoped_ptr<QuicPacketReader>> packet_readers_;
+ std::vector<scoped_ptr<QuicChromiumPacketReader>> packet_readers_;
base::TimeTicks dns_resolution_end_time_;
base::TimeTicks handshake_start_; // Time the handshake was started.
scoped_ptr<QuicConnectionLogger> logger_;
// True when the session is going away, and streams may no longer be created
// on this session. Existing stream will continue to be processed.
bool going_away_;
+ // True when the session receives a go away from server due to port migration.
+ bool port_migration_detected_;
QuicDisabledReason disabled_reason_;
+ TokenBindingSignatureMap token_binding_signatures_;
+ // UMA histogram counters for streams pushed to this session.
+ int streams_pushed_count_;
+ int streams_pushed_and_claimed_count_;
base::WeakPtrFactory<QuicChromiumClientSession> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(QuicChromiumClientSession);
diff --git a/chromium/net/quic/quic_chromium_client_session_test.cc b/chromium/net/quic/quic_chromium_client_session_test.cc
index 6d0288a703f..40f40e27ccd 100644
--- a/chromium/net/quic/quic_chromium_client_session_test.cc
+++ b/chromium/net/quic/quic_chromium_client_session_test.cc
@@ -23,11 +23,11 @@
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/crypto/quic_server_info.h"
#include "net/quic/quic_chromium_connection_helper.h"
+#include "net/quic/quic_chromium_packet_reader.h"
+#include "net/quic/quic_chromium_packet_writer.h"
#include "net/quic/quic_crypto_client_stream_factory.h"
-#include "net/quic/quic_default_packet_writer.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_http_utils.h"
-#include "net/quic/quic_packet_reader.h"
#include "net/quic/quic_packet_writer.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/test_tools/crypto_test_utils.h"
@@ -48,7 +48,7 @@ namespace net {
namespace test {
namespace {
-const IPEndPoint kIpEndPoint(IPAddressNumber(kIPv4AddressSize, 0), 0);
+const IPEndPoint kIpEndPoint = IPEndPoint(IPAddress::IPv4AllZeros(), 0);
const char kServerHostname[] = "test.example.com";
const uint16_t kServerPort = 443;
const size_t kMaxReadersPerQuicSession = 5;
@@ -63,7 +63,10 @@ class QuicChromiumClientSessionTest
new SequencedSocketData(default_read_.get(), 1, nullptr, 0)),
random_(0),
helper_(base::ThreadTaskRunnerHandle::Get().get(), &clock_, &random_),
- maker_(GetParam(), 0, &clock_, kServerHostname) {}
+ maker_(GetParam(), 0, &clock_, kServerHostname) {
+ // Advance the time, because timers do not like uninitialized times.
+ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
+ }
void Initialize() {
socket_factory_.AddSocketDataProvider(socket_data_.get());
@@ -72,8 +75,8 @@ class QuicChromiumClientSessionTest
base::Bind(&base::RandInt),
&net_log_, NetLog::Source());
socket->Connect(kIpEndPoint);
- QuicDefaultPacketWriter* writer =
- new net::QuicDefaultPacketWriter(socket.get());
+ QuicChromiumPacketWriter* writer =
+ new net::QuicChromiumPacketWriter(socket.get());
QuicConnection* connection = new QuicConnection(
0, kIpEndPoint, &helper_, writer, true, Perspective::IS_CLIENT,
SupportedVersions(GetParam()));
@@ -86,7 +89,7 @@ class QuicChromiumClientSessionTest
kQuicYieldAfterPacketsRead,
QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
/*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_,
- "CONNECTION_UNKNOWN", base::TimeTicks::Now(),
+ "CONNECTION_UNKNOWN", base::TimeTicks::Now(), &push_promise_index_,
base::ThreadTaskRunnerHandle::Get().get(),
/*socket_performance_watcher=*/nullptr, &net_log_));
@@ -94,8 +97,6 @@ class QuicChromiumClientSessionTest
ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"));
verify_details_.cert_verify_result.verified_cert = cert;
verify_details_.cert_verify_result.is_issued_by_known_root = true;
- // Advance the time, because timers do not like uninitialized times.
- clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
session_->Initialize();
session_->StartReading();
}
@@ -110,8 +111,8 @@ class QuicChromiumClientSessionTest
QuicPacketWriter* CreateQuicPacketWriter(DatagramClientSocket* socket,
QuicConnection* connection) const {
- scoped_ptr<QuicDefaultPacketWriter> writer(
- new QuicDefaultPacketWriter(socket));
+ scoped_ptr<QuicChromiumPacketWriter> writer(
+ new QuicChromiumPacketWriter(socket));
writer->SetConnection(connection);
return writer.release();
}
@@ -132,6 +133,7 @@ class QuicChromiumClientSessionTest
TestCompletionCallback callback_;
QuicTestPacketMaker maker_;
ProofVerifyDetailsChromium verify_details_;
+ QuicClientPushPromiseIndex push_promise_index_;
};
INSTANTIATE_TEST_CASE_P(Tests,
@@ -154,7 +156,7 @@ TEST_P(QuicChromiumClientSessionTest, MaxNumStreams) {
Initialize();
CompleteCryptoHandshake();
- const size_t kMaxOpenStreams = session_->get_max_open_streams();
+ const size_t kMaxOpenStreams = session_->max_open_outgoing_streams();
std::vector<QuicChromiumClientStream*> streams;
for (size_t i = 0; i < kMaxOpenStreams; i++) {
@@ -189,7 +191,7 @@ TEST_P(QuicChromiumClientSessionTest, MaxNumStreamsViaRequest) {
Initialize();
CompleteCryptoHandshake();
- const size_t kMaxOpenStreams = session_->get_max_open_streams();
+ const size_t kMaxOpenStreams = session_->max_open_outgoing_streams();
std::vector<QuicChromiumClientStream*> streams;
for (size_t i = 0; i < kMaxOpenStreams; i++) {
@@ -349,7 +351,7 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
EXPECT_EQ(OK, new_socket->Connect(kIpEndPoint));
// Create reader and writer.
- scoped_ptr<QuicPacketReader> new_reader(new QuicPacketReader(
+ scoped_ptr<QuicChromiumPacketReader> new_reader(new QuicChromiumPacketReader(
new_socket.get(), &clock_, session_.get(), kQuicYieldAfterPacketsRead,
QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
bound_net_log_.bound()));
@@ -365,7 +367,7 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
iov[0].iov_base = data;
iov[0].iov_len = 4;
session_->WritevData(5, QuicIOVector(iov, arraysize(iov), 4), 0, false,
- MAY_FEC_PROTECT, nullptr);
+ nullptr);
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -393,10 +395,12 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocketMaxReaders) {
EXPECT_EQ(OK, new_socket->Connect(kIpEndPoint));
// Create reader and writer.
- scoped_ptr<QuicPacketReader> new_reader(new QuicPacketReader(
- new_socket.get(), &clock_, session_.get(), kQuicYieldAfterPacketsRead,
- QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
- bound_net_log_.bound()));
+ scoped_ptr<QuicChromiumPacketReader> new_reader(
+ new QuicChromiumPacketReader(new_socket.get(), &clock_, session_.get(),
+ kQuicYieldAfterPacketsRead,
+ QuicTime::Delta::FromMilliseconds(
+ kQuicYieldAfterDurationMilliseconds),
+ bound_net_log_.bound()));
scoped_ptr<QuicPacketWriter> new_writer(
CreateQuicPacketWriter(new_socket.get(), session_->connection()));
@@ -449,7 +453,7 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) {
EXPECT_EQ(OK, new_socket->Connect(kIpEndPoint));
// Create reader and writer.
- scoped_ptr<QuicPacketReader> new_reader(new QuicPacketReader(
+ scoped_ptr<QuicChromiumPacketReader> new_reader(new QuicChromiumPacketReader(
new_socket.get(), &clock_, session_.get(), kQuicYieldAfterPacketsRead,
QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
bound_net_log_.bound()));
@@ -500,7 +504,7 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocketWriteError) {
EXPECT_EQ(OK, new_socket->Connect(kIpEndPoint));
// Create reader and writer.
- scoped_ptr<QuicPacketReader> new_reader(new QuicPacketReader(
+ scoped_ptr<QuicChromiumPacketReader> new_reader(new QuicChromiumPacketReader(
new_socket.get(), &clock_, session_.get(), kQuicYieldAfterPacketsRead,
QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
bound_net_log_.bound()));
diff --git a/chromium/net/quic/quic_chromium_client_stream.cc b/chromium/net/quic/quic_chromium_client_stream.cc
index 2c558e55369..06ec9426df6 100644
--- a/chromium/net/quic/quic_chromium_client_stream.cc
+++ b/chromium/net/quic/quic_chromium_client_stream.cc
@@ -9,19 +9,24 @@
#include "base/thread_task_runner_handle.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/quic/quic_chromium_client_session.h"
+#include "net/quic/quic_http_utils.h"
#include "net/quic/quic_spdy_session.h"
#include "net/quic/quic_write_blocked_list.h"
#include "net/quic/spdy_utils.h"
namespace net {
-QuicChromiumClientStream::QuicChromiumClientStream(QuicStreamId id,
- QuicSpdySession* session,
- const BoundNetLog& net_log)
+QuicChromiumClientStream::QuicChromiumClientStream(
+ QuicStreamId id,
+ QuicClientSessionBase* session,
+ const BoundNetLog& net_log)
: QuicSpdyStream(id, session),
net_log_(net_log),
delegate_(nullptr),
headers_delivered_(false),
+ session_(session),
+ can_migrate_(true),
weak_factory_(this) {}
QuicChromiumClientStream::~QuicChromiumClientStream() {
@@ -32,18 +37,47 @@ QuicChromiumClientStream::~QuicChromiumClientStream() {
void QuicChromiumClientStream::OnStreamHeadersComplete(bool fin,
size_t frame_len) {
QuicSpdyStream::OnStreamHeadersComplete(fin, frame_len);
- // The delegate will read the headers via a posted task.
- NotifyDelegateOfHeadersCompleteLater(frame_len);
+ if (decompressed_headers().empty() && !decompressed_trailers().empty()) {
+ DCHECK(trailers_decompressed());
+ // The delegate will read the trailers via a posted task.
+ NotifyDelegateOfHeadersCompleteLater(received_trailers(), frame_len);
+ } else {
+ DCHECK(!headers_delivered_);
+ SpdyHeaderBlock headers;
+ SpdyFramer framer(HTTP2);
+ size_t headers_len = decompressed_headers().length();
+ const char* header_data = decompressed_headers().data();
+ if (!framer.ParseHeaderBlockInBuffer(header_data, headers_len, &headers)) {
+ DLOG(WARNING) << "Invalid headers";
+ Reset(QUIC_BAD_APPLICATION_PAYLOAD);
+ return;
+ }
+ MarkHeadersConsumed(headers_len);
+ session_->OnInitialHeadersComplete(id(), headers);
+
+ // The delegate will read the headers via a posted task.
+ NotifyDelegateOfHeadersCompleteLater(headers, frame_len);
+ }
}
-void QuicChromiumClientStream::OnDataAvailable() {
- // TODO(rch): buffer data if we don't have a delegate.
- if (!delegate_) {
- DLOG(ERROR) << "Missing delegate";
- Reset(QUIC_STREAM_CANCELLED);
+void QuicChromiumClientStream::OnPromiseHeadersComplete(
+ QuicStreamId promised_id,
+ size_t frame_len) {
+ size_t headers_len = decompressed_headers().length();
+ SpdyHeaderBlock headers;
+ SpdyFramer framer(HTTP2);
+ if (!framer.ParseHeaderBlockInBuffer(decompressed_headers().data(),
+ headers_len, &headers)) {
+ DLOG(WARNING) << "Invalid headers";
+ Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return;
}
+ MarkHeadersConsumed(headers_len);
+
+ session_->HandlePromised(id(), promised_id, headers);
+}
+void QuicChromiumClientStream::OnDataAvailable() {
if (!FinishedReadingHeaders() || !headers_delivered_) {
// Buffer the data in the sequencer until the headers have been read.
return;
@@ -58,6 +92,7 @@ void QuicChromiumClientStream::OnClose() {
if (delegate_) {
delegate_->OnClose(connection_error());
delegate_ = nullptr;
+ delegate_tasks_.clear();
}
ReliableQuicStream::OnClose();
}
@@ -70,9 +105,20 @@ void QuicChromiumClientStream::OnCanWrite() {
}
}
-SpdyPriority QuicChromiumClientStream::Priority() const {
+size_t QuicChromiumClientStream::WriteHeaders(
+ const SpdyHeaderBlock& header_block,
+ bool fin,
+ QuicAckListenerInterface* ack_notifier_delegate) {
+ net_log_.AddEvent(
+ NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
+ base::Bind(&QuicRequestNetLogCallback, id(), &header_block,
+ QuicSpdyStream::priority()));
+ return QuicSpdyStream::WriteHeaders(header_block, fin, ack_notifier_delegate);
+}
+
+SpdyPriority QuicChromiumClientStream::priority() const {
if (delegate_ && delegate_->HasSendHeadersComplete()) {
- return QuicSpdyStream::Priority();
+ return QuicSpdyStream::priority();
}
return net::kV3HighestPriority;
}
@@ -97,6 +143,11 @@ void QuicChromiumClientStream::SetDelegate(
QuicChromiumClientStream::Delegate* delegate) {
DCHECK(!(delegate_ && delegate));
delegate_ = delegate;
+ while (!delegate_tasks_.empty()) {
+ base::Closure closure = delegate_tasks_.front();
+ delegate_tasks_.pop_front();
+ closure.Run();
+ }
if (delegate == nullptr && sequencer()->IsClosed()) {
OnFinRead();
}
@@ -106,6 +157,7 @@ void QuicChromiumClientStream::OnError(int error) {
if (delegate_) {
QuicChromiumClientStream::Delegate* delegate = delegate_;
delegate_ = nullptr;
+ delegate_tasks_.clear();
delegate->OnError(error);
}
}
@@ -126,7 +178,7 @@ int QuicChromiumClientStream::Read(IOBuffer* buf, int buf_len) {
bool QuicChromiumClientStream::CanWrite(const CompletionCallback& callback) {
bool can_write = session()->connection()->CanWrite(HAS_RETRANSMITTABLE_DATA);
if (!can_write) {
- session()->MarkConnectionLevelWriteBlocked(id(), Priority());
+ session()->MarkConnectionLevelWriteBlocked(id());
DCHECK(callback_.is_null());
callback_ = callback;
}
@@ -134,38 +186,36 @@ bool QuicChromiumClientStream::CanWrite(const CompletionCallback& callback) {
}
void QuicChromiumClientStream::NotifyDelegateOfHeadersCompleteLater(
+ const SpdyHeaderBlock& headers,
size_t frame_len) {
- DCHECK(delegate_);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
+ RunOrBuffer(
base::Bind(&QuicChromiumClientStream::NotifyDelegateOfHeadersComplete,
- weak_factory_.GetWeakPtr(), frame_len));
+ weak_factory_.GetWeakPtr(), headers, frame_len));
}
void QuicChromiumClientStream::NotifyDelegateOfHeadersComplete(
+ SpdyHeaderBlock headers,
size_t frame_len) {
if (!delegate_)
return;
-
- size_t headers_len = decompressed_headers().length();
- SpdyHeaderBlock headers;
- SpdyFramer framer(HTTP2);
- if (!framer.ParseHeaderBlockInBuffer(decompressed_headers().data(),
- headers_len, &headers)) {
- DLOG(WARNING) << "Invalid headers";
- Reset(QUIC_BAD_APPLICATION_PAYLOAD);
- return;
+ // Only mark trailers consumed when we are about to notify delegate.
+ if (headers_delivered_) {
+ MarkTrailersConsumed(decompressed_trailers().length());
+ net_log_.AddEvent(
+ NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_TRAILERS,
+ base::Bind(&SpdyHeaderBlockNetLogCallback, &headers));
+ } else {
+ headers_delivered_ = true;
+ net_log_.AddEvent(
+ NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_HEADERS,
+ base::Bind(&SpdyHeaderBlockNetLogCallback, &headers));
}
- MarkHeadersConsumed(headers_len);
- headers_delivered_ = true;
delegate_->OnHeadersAvailable(headers, frame_len);
}
void QuicChromiumClientStream::NotifyDelegateOfDataAvailableLater() {
- DCHECK(delegate_);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
+ RunOrBuffer(
base::Bind(&QuicChromiumClientStream::NotifyDelegateOfDataAvailable,
weak_factory_.GetWeakPtr()));
}
@@ -175,4 +225,16 @@ void QuicChromiumClientStream::NotifyDelegateOfDataAvailable() {
delegate_->OnDataAvailable();
}
+void QuicChromiumClientStream::RunOrBuffer(base::Closure closure) {
+ if (delegate_) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure);
+ } else {
+ delegate_tasks_.push_back(closure);
+ }
+}
+
+void QuicChromiumClientStream::DisableConnectionMigration() {
+ can_migrate_ = false;
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_chromium_client_stream.h b/chromium/net/quic/quic_chromium_client_stream.h
index 5a8ddf55cc6..41738956b91 100644
--- a/chromium/net/quic/quic_chromium_client_stream.h
+++ b/chromium/net/quic/quic_chromium_client_stream.h
@@ -9,6 +9,7 @@
#include <stddef.h>
+#include "base/callback_forward.h"
#include "base/macros.h"
#include "net/base/ip_endpoint.h"
#include "net/base/upload_data_stream.h"
@@ -19,7 +20,7 @@
namespace net {
-class QuicSpdySession;
+class QuicClientSessionBase;
// A client-initiated ReliableQuicStream. Instances of this class
// are owned by the QuicClientSession which created them.
@@ -54,17 +55,22 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream : public QuicSpdyStream {
};
QuicChromiumClientStream(QuicStreamId id,
- QuicSpdySession* session,
+ QuicClientSessionBase* session,
const BoundNetLog& net_log);
~QuicChromiumClientStream() override;
// QuicSpdyStream
void OnStreamHeadersComplete(bool fin, size_t frame_len) override;
+ void OnPromiseHeadersComplete(QuicStreamId promised_stream_id,
+ size_t frame_len) override;
void OnDataAvailable() override;
void OnClose() override;
void OnCanWrite() override;
- SpdyPriority Priority() const override;
+ size_t WriteHeaders(const SpdyHeaderBlock& header_block,
+ bool fin,
+ QuicAckListenerInterface* ack_notifier_delegate) override;
+ SpdyPriority priority() const override;
// While the server's set_priority shouldn't be called externally, the creator
// of client-side streams should be able to set the priority.
@@ -91,13 +97,22 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream : public QuicSpdyStream {
const BoundNetLog& net_log() const { return net_log_; }
+ // Prevents this stream from migrating to a new network. May cause other
+ // concurrent streams within the session to also not migrate.
+ void DisableConnectionMigration();
+
+ bool can_migrate() { return can_migrate_; }
+
using QuicSpdyStream::HasBufferedData;
private:
- void NotifyDelegateOfHeadersCompleteLater(size_t frame_len);
- void NotifyDelegateOfHeadersComplete(size_t frame_len);
+ void NotifyDelegateOfHeadersCompleteLater(const SpdyHeaderBlock& headers,
+ size_t frame_len);
+ void NotifyDelegateOfHeadersComplete(SpdyHeaderBlock headers,
+ size_t frame_len);
void NotifyDelegateOfDataAvailableLater();
void NotifyDelegateOfDataAvailable();
+ void RunOrBuffer(base::Closure closure);
BoundNetLog net_log_;
Delegate* delegate_;
@@ -106,6 +121,14 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream : public QuicSpdyStream {
CompletionCallback callback_;
+ QuicClientSessionBase* session_;
+
+ // Set to false if this stream to not be migrated during connection migration.
+ bool can_migrate_;
+
+ // Holds notifications generated before delegate_ is set.
+ std::deque<base::Closure> delegate_tasks_;
+
base::WeakPtrFactory<QuicChromiumClientStream> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(QuicChromiumClientStream);
diff --git a/chromium/net/quic/quic_chromium_client_stream_test.cc b/chromium/net/quic/quic_chromium_client_stream_test.cc
index b8ea0527930..94d20a9a0bf 100644
--- a/chromium/net/quic/quic_chromium_client_stream_test.cc
+++ b/chromium/net/quic/quic_chromium_client_stream_test.cc
@@ -5,9 +5,12 @@
#include "net/quic/quic_chromium_client_stream.h"
#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/quic/quic_chromium_client_session.h"
+#include "net/quic/quic_client_session_base.h"
#include "net/quic/quic_utils.h"
#include "net/quic/spdy_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
@@ -34,7 +37,8 @@ class MockDelegate : public QuicChromiumClientStream::Delegate {
MOCK_METHOD0(OnSendData, int());
MOCK_METHOD2(OnSendDataComplete, int(int, bool*));
- MOCK_METHOD2(OnHeadersAvailable, void(const SpdyHeaderBlock&, size_t));
+ MOCK_METHOD2(OnHeadersAvailable,
+ void(const SpdyHeaderBlock& headers, size_t frame_len));
MOCK_METHOD2(OnDataReceived, int(const char*, int));
MOCK_METHOD0(OnDataAvailable, void());
MOCK_METHOD1(OnClose, void(QuicErrorCode));
@@ -45,6 +49,95 @@ class MockDelegate : public QuicChromiumClientStream::Delegate {
DISALLOW_COPY_AND_ASSIGN(MockDelegate);
};
+class MockQuicClientSessionBase : public QuicClientSessionBase {
+ public:
+ explicit MockQuicClientSessionBase(QuicConnection* connection,
+ QuicClientPushPromiseIndex* index);
+ ~MockQuicClientSessionBase() override;
+
+ QuicCryptoStream* GetCryptoStream() override { return crypto_stream_.get(); }
+
+ // From QuicSession.
+ MOCK_METHOD3(OnConnectionClosed,
+ void(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source));
+ MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id));
+ MOCK_METHOD1(CreateOutgoingDynamicStream,
+ QuicChromiumClientStream*(SpdyPriority priority));
+ MOCK_METHOD5(WritevData,
+ QuicConsumedData(QuicStreamId id,
+ QuicIOVector data,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicAckListenerInterface*));
+ MOCK_METHOD3(SendRstStream,
+ void(QuicStreamId stream_id,
+ QuicRstStreamErrorCode error,
+ QuicStreamOffset bytes_written));
+
+ MOCK_METHOD2(OnStreamHeaders,
+ void(QuicStreamId stream_id, base::StringPiece headers_data));
+ MOCK_METHOD2(OnStreamHeadersPriority,
+ void(QuicStreamId stream_id, SpdyPriority priority));
+ MOCK_METHOD3(OnStreamHeadersComplete,
+ void(QuicStreamId stream_id, bool fin, size_t frame_len));
+ MOCK_METHOD2(OnPromiseHeaders,
+ void(QuicStreamId stream_id, StringPiece headers_data));
+ MOCK_METHOD3(OnPromiseHeadersComplete,
+ void(QuicStreamId stream_id,
+ QuicStreamId promised_stream_id,
+ size_t frame_len));
+ MOCK_METHOD0(IsCryptoHandshakeConfirmed, bool());
+ MOCK_METHOD5(WriteHeaders,
+ size_t(QuicStreamId id,
+ const SpdyHeaderBlock& headers,
+ bool fin,
+ SpdyPriority priority,
+ QuicAckListenerInterface* ack_notifier_delegate));
+ MOCK_METHOD1(OnHeadersHeadOfLineBlocking, void(QuicTime::Delta delta));
+
+ using QuicSession::ActivateStream;
+
+ // Returns a QuicConsumedData that indicates all of |data| (and |fin| if set)
+ // has been consumed.
+ static QuicConsumedData ConsumeAllData(
+ QuicStreamId id,
+ const QuicIOVector& data,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicAckListenerInterface* ack_notifier_delegate);
+
+ void OnProofValid(
+ const QuicCryptoClientConfig::CachedState& cached) override {}
+ void OnProofVerifyDetailsAvailable(
+ const ProofVerifyDetails& verify_details) override {}
+ bool IsAuthorized(const std::string& hostname) override { return true; }
+
+ protected:
+ MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id));
+ MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool());
+
+ private:
+ scoped_ptr<QuicCryptoStream> crypto_stream_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockQuicClientSessionBase);
+};
+
+MockQuicClientSessionBase::MockQuicClientSessionBase(
+ QuicConnection* connection,
+ QuicClientPushPromiseIndex* push_promise_index)
+ : QuicClientSessionBase(connection,
+ push_promise_index,
+ DefaultQuicConfig()) {
+ crypto_stream_.reset(new QuicCryptoStream(this));
+ Initialize();
+ ON_CALL(*this, WritevData(_, _, _, _, _))
+ .WillByDefault(testing::Return(QuicConsumedData(0, false)));
+}
+
+MockQuicClientSessionBase::~MockQuicClientSessionBase() {}
+
class QuicChromiumClientStreamTest
: public ::testing::TestWithParam<QuicVersion> {
public:
@@ -52,7 +145,8 @@ class QuicChromiumClientStreamTest
: crypto_config_(CryptoTestUtils::ProofVerifierForTesting()),
session_(new MockConnection(&helper_,
Perspective::IS_CLIENT,
- SupportedVersions(GetParam()))) {
+ SupportedVersions(GetParam())),
+ &push_promise_index_) {
stream_ =
new QuicChromiumClientStream(kTestStreamId, &session_, BoundNetLog());
session_.ActivateStream(stream_);
@@ -100,9 +194,10 @@ class QuicChromiumClientStreamTest
QuicCryptoClientConfig crypto_config_;
testing::StrictMock<MockDelegate> delegate_;
MockConnectionHelper helper_;
- MockQuicSpdySession session_;
+ MockQuicClientSessionBase session_;
QuicChromiumClientStream* stream_;
SpdyHeaderBlock headers_;
+ QuicClientPushPromiseIndex push_promise_index_;
};
INSTANTIATE_TEST_CASE_P(Version,
@@ -152,7 +247,8 @@ TEST_P(QuicChromiumClientStreamTest, OnDataAvailable) {
EXPECT_CALL(delegate_, OnDataAvailable())
.WillOnce(testing::Invoke(
- CreateFunctor(this, &QuicChromiumClientStreamTest::ReadData,
+ CreateFunctor(&QuicChromiumClientStreamTest::ReadData,
+ base::Unretained(this),
StringPiece(data, arraysize(data) - 1))));
base::MessageLoop::current()->RunUntilIdle();
@@ -161,11 +257,12 @@ TEST_P(QuicChromiumClientStreamTest, OnDataAvailable) {
TEST_P(QuicChromiumClientStreamTest, ProcessHeadersWithError) {
std::string bad_headers = "...";
+ EXPECT_CALL(session_,
+ SendRstStream(kTestStreamId, QUIC_BAD_APPLICATION_PAYLOAD, 0));
+
stream_->OnStreamHeaders(StringPiece(bad_headers));
stream_->OnStreamHeadersComplete(false, bad_headers.length());
- EXPECT_CALL(session_,
- SendRstStream(kTestStreamId, QUIC_BAD_APPLICATION_PAYLOAD, 0));
base::MessageLoop::current()->RunUntilIdle();
EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR));
@@ -188,7 +285,8 @@ TEST_P(QuicChromiumClientStreamTest, OnDataAvailableWithError) {
/*offset=*/0, data));
EXPECT_CALL(delegate_, OnDataAvailable())
.WillOnce(testing::Invoke(CreateFunctor(
- stream_, &QuicChromiumClientStream::Reset, QUIC_STREAM_CANCELLED)));
+ &QuicChromiumClientStream::Reset,
+ base::Unretained(stream_), QUIC_STREAM_CANCELLED)));
base::MessageLoop::current()->RunUntilIdle();
EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR));
@@ -201,6 +299,131 @@ TEST_P(QuicChromiumClientStreamTest, OnError) {
EXPECT_FALSE(stream_->GetDelegate());
}
+TEST_P(QuicChromiumClientStreamTest, OnTrailers) {
+ InitializeHeaders();
+ std::string uncompressed_headers =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+ stream_->OnStreamHeaders(uncompressed_headers);
+ stream_->OnStreamHeadersComplete(false, uncompressed_headers.length());
+
+ EXPECT_CALL(delegate_,
+ OnHeadersAvailable(headers_, uncompressed_headers.length()));
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_TRUE(stream_->decompressed_headers().empty());
+
+ const char data[] = "hello world!";
+ stream_->OnStreamFrame(QuicStreamFrame(kTestStreamId, /*fin=*/false,
+ /*offset=*/0, data));
+
+ EXPECT_CALL(delegate_, OnDataAvailable())
+ .WillOnce(testing::Invoke(CreateFunctor(
+ &QuicChromiumClientStreamTest::ReadData, base::Unretained(this),
+ StringPiece(data, arraysize(data) - 1))));
+
+ SpdyHeaderBlock trailers;
+ trailers["bar"] = "foo";
+ trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(data));
+ std::string uncompressed_trailers =
+ SpdyUtils::SerializeUncompressedHeaders(trailers);
+
+ stream_->OnStreamHeaders(uncompressed_trailers);
+ stream_->OnStreamHeadersComplete(true, uncompressed_trailers.length());
+
+ SpdyHeaderBlock actual_trailers;
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(delegate_, OnHeadersAvailable(_, uncompressed_trailers.length()))
+ .WillOnce(testing::DoAll(
+ testing::SaveArg<0>(&actual_trailers),
+ testing::InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })));
+
+ run_loop.Run();
+ // Make sure kFinalOffsetHeaderKey is gone from the delivered actual trailers.
+ trailers.erase(kFinalOffsetHeaderKey);
+ EXPECT_EQ(trailers, actual_trailers);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR));
+}
+
+// Tests that trailers are marked as consumed only before delegate is to be
+// immediately notified about trailers.
+TEST_P(QuicChromiumClientStreamTest, MarkTrailersConsumedWhenNotifyDelegate) {
+ InitializeHeaders();
+ std::string uncompressed_headers =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+ stream_->OnStreamHeaders(uncompressed_headers);
+ stream_->OnStreamHeadersComplete(false, uncompressed_headers.length());
+
+ EXPECT_CALL(delegate_,
+ OnHeadersAvailable(headers_, uncompressed_headers.length()));
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_TRUE(stream_->decompressed_headers().empty());
+
+ const char data[] = "hello world!";
+ stream_->OnStreamFrame(QuicStreamFrame(kTestStreamId, /*fin=*/false,
+ /*offset=*/0, data));
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(delegate_, OnDataAvailable())
+ .Times(1)
+ .WillOnce(testing::DoAll(
+ testing::Invoke(CreateFunctor(
+ &QuicChromiumClientStreamTest::ReadData, base::Unretained(this),
+ StringPiece(data, arraysize(data) - 1))),
+ testing::Invoke([&run_loop]() { run_loop.Quit(); })));
+
+ // Wait for the read to complete.
+ run_loop.Run();
+
+ // Read again, and it will be pending.
+ scoped_refptr<IOBuffer> buffer(new IOBuffer(1));
+ EXPECT_EQ(ERR_IO_PENDING, stream_->Read(buffer.get(), 1));
+
+ SpdyHeaderBlock trailers;
+ trailers["bar"] = "foo";
+ trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(data));
+ std::string uncompressed_trailers =
+ SpdyUtils::SerializeUncompressedHeaders(trailers);
+
+ stream_->OnStreamHeaders(uncompressed_trailers);
+ stream_->OnStreamHeadersComplete(true, uncompressed_trailers.length());
+ EXPECT_FALSE(stream_->IsDoneReading());
+
+ // Now the pending should complete. Make sure that IsDoneReading() is false
+ // even though ReadData returns 0 byte, because OnHeadersAvailable callback
+ // comes after this OnDataAvailable callback.
+ base::RunLoop run_loop2;
+ EXPECT_CALL(delegate_, OnDataAvailable())
+ .Times(1)
+ .WillOnce(testing::DoAll(
+ testing::Invoke(CreateFunctor(&QuicChromiumClientStreamTest::ReadData,
+ base::Unretained(this), StringPiece())),
+ testing::InvokeWithoutArgs([&run_loop2]() { run_loop2.Quit(); })));
+ run_loop2.Run();
+ // Make sure that the stream is not closed, even though ReadData returns 0.
+ EXPECT_FALSE(stream_->IsDoneReading());
+
+ // The OnHeadersAvailable call should follow.
+ base::RunLoop run_loop3;
+ SpdyHeaderBlock actual_trailers;
+ EXPECT_CALL(delegate_,
+ OnHeadersAvailable(trailers, uncompressed_trailers.length()))
+ .WillOnce(testing::DoAll(
+ testing::SaveArg<0>(&actual_trailers),
+ testing::InvokeWithoutArgs([&run_loop3]() { run_loop3.Quit(); })));
+
+ run_loop3.Run();
+ // Make sure the stream is properly closed since trailers and data are all
+ // consumed.
+ EXPECT_TRUE(stream_->IsDoneReading());
+ // Make sure kFinalOffsetHeaderKey is gone from the delivered actual trailers.
+ trailers.erase(kFinalOffsetHeaderKey);
+ EXPECT_EQ(trailers, actual_trailers);
+
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR));
+}
+
TEST_P(QuicChromiumClientStreamTest, WriteStreamData) {
EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR));
@@ -208,7 +431,7 @@ TEST_P(QuicChromiumClientStreamTest, WriteStreamData) {
const size_t kDataLen = arraysize(kData1);
// All data written.
- EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _))
.WillOnce(Return(QuicConsumedData(kDataLen, true)));
TestCompletionCallback callback;
EXPECT_EQ(OK, stream_->WriteStreamData(base::StringPiece(kData1, kDataLen),
@@ -223,7 +446,7 @@ TEST_P(QuicChromiumClientStreamTest, WriteStreamDataAsync) {
const size_t kDataLen = arraysize(kData1);
// No data written.
- EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _))
.WillOnce(Return(QuicConsumedData(0, false)));
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
@@ -232,13 +455,36 @@ TEST_P(QuicChromiumClientStreamTest, WriteStreamDataAsync) {
ASSERT_FALSE(callback.have_result());
// All data written.
- EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _))
.WillOnce(Return(QuicConsumedData(kDataLen, true)));
stream_->OnCanWrite();
ASSERT_TRUE(callback.have_result());
EXPECT_EQ(OK, callback.WaitForResult());
}
+TEST_P(QuicChromiumClientStreamTest, HeadersBeforeDelegate) {
+ // We don't use stream_ because we want an incoming server push
+ // stream.
+ QuicChromiumClientStream* stream = new QuicChromiumClientStream(
+ kServerDataStreamId1, &session_, BoundNetLog());
+ session_.ActivateStream(stream);
+
+ InitializeHeaders();
+ std::string uncompressed_headers =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+ stream->OnStreamHeaders(uncompressed_headers);
+ stream->OnStreamHeadersComplete(false, uncompressed_headers.length());
+ EXPECT_TRUE(stream->decompressed_headers().empty());
+
+ EXPECT_CALL(delegate_,
+ OnHeadersAvailable(headers_, uncompressed_headers.length()));
+ stream->SetDelegate(&delegate_);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Times(2) because OnClose will be called for stream and stream_.
+ EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR)).Times(2);
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_chromium_connection_helper.cc b/chromium/net/quic/quic_chromium_connection_helper.cc
index 68c0a105061..d88648f1d03 100644
--- a/chromium/net/quic/quic_chromium_connection_helper.cc
+++ b/chromium/net/quic/quic_chromium_connection_helper.cc
@@ -21,8 +21,8 @@ class QuicChromeAlarm : public QuicAlarm {
public:
QuicChromeAlarm(const QuicClock* clock,
base::TaskRunner* task_runner,
- QuicAlarm::Delegate* delegate)
- : QuicAlarm(delegate),
+ QuicArenaScopedPtr<QuicAlarm::Delegate> delegate)
+ : QuicAlarm(std::move(delegate)),
clock_(clock),
task_runner_(task_runner),
task_deadline_(QuicTime::Zero()),
@@ -110,9 +110,22 @@ QuicRandom* QuicChromiumConnectionHelper::GetRandomGenerator() {
return random_generator_;
}
+QuicArenaScopedPtr<QuicAlarm> QuicChromiumConnectionHelper::CreateAlarm(
+ QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+ QuicConnectionArena* arena) {
+ if (arena != nullptr) {
+ return arena->New<QuicChromeAlarm>(clock_, task_runner_,
+ std::move(delegate));
+ } else {
+ return QuicArenaScopedPtr<QuicAlarm>(
+ new QuicChromeAlarm(clock_, task_runner_, std::move(delegate)));
+ }
+}
+
QuicAlarm* QuicChromiumConnectionHelper::CreateAlarm(
QuicAlarm::Delegate* delegate) {
- return new QuicChromeAlarm(clock_, task_runner_, delegate);
+ return new QuicChromeAlarm(clock_, task_runner_,
+ QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate));
}
QuicBufferAllocator* QuicChromiumConnectionHelper::GetBufferAllocator() {
diff --git a/chromium/net/quic/quic_chromium_connection_helper.h b/chromium/net/quic/quic_chromium_connection_helper.h
index 2b0464945d9..281a3f365f7 100644
--- a/chromium/net/quic/quic_chromium_connection_helper.h
+++ b/chromium/net/quic/quic_chromium_connection_helper.h
@@ -40,6 +40,9 @@ class NET_EXPORT_PRIVATE QuicChromiumConnectionHelper
const QuicClock* GetClock() const override;
QuicRandom* GetRandomGenerator() override;
QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override;
+ QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
+ QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+ QuicConnectionArena* arena) override;
QuicBufferAllocator* GetBufferAllocator() override;
private:
diff --git a/chromium/net/quic/quic_chromium_connection_helper_test.cc b/chromium/net/quic/quic_chromium_connection_helper_test.cc
index aefa22ac90e..9fab8fb50d1 100644
--- a/chromium/net/quic/quic_chromium_connection_helper_test.cc
+++ b/chromium/net/quic/quic_chromium_connection_helper_test.cc
@@ -17,10 +17,7 @@ class TestDelegate : public QuicAlarm::Delegate {
public:
TestDelegate() : fired_(false) {}
- QuicTime OnAlarm() override {
- fired_ = true;
- return QuicTime::Zero();
- }
+ void OnAlarm() override { fired_ = true; }
bool fired() const { return fired_; }
void Clear() { fired_ = false; }
diff --git a/chromium/net/quic/quic_packet_reader.cc b/chromium/net/quic/quic_chromium_packet_reader.cc
index c3e37edafdd..4a57ecbcf83 100644
--- a/chromium/net/quic/quic_packet_reader.cc
+++ b/chromium/net/quic/quic_chromium_packet_reader.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/quic_packet_reader.h"
+#include "net/quic/quic_chromium_packet_reader.h"
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
@@ -14,12 +14,13 @@
namespace net {
-QuicPacketReader::QuicPacketReader(DatagramClientSocket* socket,
- QuicClock* clock,
- Visitor* visitor,
- int yield_after_packets,
- QuicTime::Delta yield_after_duration,
- const BoundNetLog& net_log)
+QuicChromiumPacketReader::QuicChromiumPacketReader(
+ DatagramClientSocket* socket,
+ QuicClock* clock,
+ Visitor* visitor,
+ int yield_after_packets,
+ QuicTime::Delta yield_after_duration,
+ const BoundNetLog& net_log)
: socket_(socket),
visitor_(visitor),
read_pending_(false),
@@ -32,9 +33,9 @@ QuicPacketReader::QuicPacketReader(DatagramClientSocket* socket,
net_log_(net_log),
weak_factory_(this) {}
-QuicPacketReader::~QuicPacketReader() {}
+QuicChromiumPacketReader::~QuicChromiumPacketReader() {}
-void QuicPacketReader::StartReading() {
+void QuicChromiumPacketReader::StartReading() {
if (read_pending_)
return;
@@ -44,7 +45,7 @@ void QuicPacketReader::StartReading() {
DCHECK(socket_);
read_pending_ = true;
int rv = socket_->Read(read_buffer_.get(), read_buffer_->size(),
- base::Bind(&QuicPacketReader::OnReadComplete,
+ base::Bind(&QuicChromiumPacketReader::OnReadComplete,
weak_factory_.GetWeakPtr()));
UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.AsyncRead", rv == ERR_IO_PENDING);
if (rv == ERR_IO_PENDING) {
@@ -59,14 +60,14 @@ void QuicPacketReader::StartReading() {
// Schedule the work through the message loop to 1) prevent infinite
// recursion and 2) avoid blocking the thread for too long.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&QuicPacketReader::OnReadComplete,
+ FROM_HERE, base::Bind(&QuicChromiumPacketReader::OnReadComplete,
weak_factory_.GetWeakPtr(), rv));
} else {
OnReadComplete(rv);
}
}
-void QuicPacketReader::OnReadComplete(int result) {
+void QuicChromiumPacketReader::OnReadComplete(int result) {
read_pending_ = false;
if (result == 0)
result = ERR_CONNECTION_CLOSED;
@@ -76,7 +77,7 @@ void QuicPacketReader::OnReadComplete(int result) {
return;
}
- QuicEncryptedPacket packet(read_buffer_->data(), result);
+ QuicReceivedPacket packet(read_buffer_->data(), result, clock_->Now());
IPEndPoint local_address;
IPEndPoint peer_address;
socket_->GetLocalAddress(&local_address);
diff --git a/chromium/net/quic/quic_packet_reader.h b/chromium/net/quic/quic_chromium_packet_reader.h
index 56630346c03..1f0aaedd74b 100644
--- a/chromium/net/quic/quic_packet_reader.h
+++ b/chromium/net/quic/quic_chromium_packet_reader.h
@@ -20,30 +20,30 @@ class QuicClock;
class QuicTime;
// If more than this many packets have been read or more than that many
-// milliseconds have passed, QuicPacketReader::StartReading() yields by doing a
-// QuicPacketReader::PostTask().
+// milliseconds have passed, QuicChromiumPacketReader::StartReading() yields by
+// doing a QuicChromiumPacketReader::PostTask().
const int kQuicYieldAfterPacketsRead = 32;
const int kQuicYieldAfterDurationMilliseconds = 20;
-class NET_EXPORT_PRIVATE QuicPacketReader {
+class NET_EXPORT_PRIVATE QuicChromiumPacketReader {
public:
class NET_EXPORT_PRIVATE Visitor {
public:
virtual ~Visitor(){};
virtual void OnReadError(int result,
const DatagramClientSocket* socket) = 0;
- virtual bool OnPacket(const QuicEncryptedPacket& packet,
+ virtual bool OnPacket(const QuicReceivedPacket& packet,
IPEndPoint local_address,
IPEndPoint peer_address) = 0;
};
- QuicPacketReader(DatagramClientSocket* socket,
- QuicClock* clock,
- Visitor* visitor,
- int yield_after_packets,
- QuicTime::Delta yield_after_duration,
- const BoundNetLog& net_log);
- virtual ~QuicPacketReader();
+ QuicChromiumPacketReader(DatagramClientSocket* socket,
+ QuicClock* clock,
+ Visitor* visitor,
+ int yield_after_packets,
+ QuicTime::Delta yield_after_duration,
+ const BoundNetLog& net_log);
+ virtual ~QuicChromiumPacketReader();
// Causes the QuicConnectionHelper to start reading from the socket
// and passing the data along to the QuicConnection.
@@ -64,9 +64,9 @@ class NET_EXPORT_PRIVATE QuicPacketReader {
scoped_refptr<IOBufferWithSize> read_buffer_;
BoundNetLog net_log_;
- base::WeakPtrFactory<QuicPacketReader> weak_factory_;
+ base::WeakPtrFactory<QuicChromiumPacketReader> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(QuicPacketReader);
+ DISALLOW_COPY_AND_ASSIGN(QuicChromiumPacketReader);
};
} // namespace net
diff --git a/chromium/net/quic/quic_default_packet_writer.cc b/chromium/net/quic/quic_chromium_packet_writer.cc
index a8baf1bcd95..1587859ae53 100644
--- a/chromium/net/quic/quic_default_packet_writer.cc
+++ b/chromium/net/quic/quic_chromium_packet_writer.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/quic_default_packet_writer.h"
+#include "net/quic/quic_chromium_packet_writer.h"
#include "base/location.h"
#include "base/logging.h"
@@ -13,24 +13,25 @@
namespace net {
-QuicDefaultPacketWriter::QuicDefaultPacketWriter() : weak_factory_(this) {}
+QuicChromiumPacketWriter::QuicChromiumPacketWriter() : weak_factory_(this) {}
-QuicDefaultPacketWriter::QuicDefaultPacketWriter(Socket* socket)
+QuicChromiumPacketWriter::QuicChromiumPacketWriter(Socket* socket)
: socket_(socket), write_blocked_(false), weak_factory_(this) {}
-QuicDefaultPacketWriter::~QuicDefaultPacketWriter() {}
+QuicChromiumPacketWriter::~QuicChromiumPacketWriter() {}
-WriteResult QuicDefaultPacketWriter::WritePacket(
+WriteResult QuicChromiumPacketWriter::WritePacket(
const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) {
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* /*options*/) {
scoped_refptr<StringIOBuffer> buf(
new StringIOBuffer(std::string(buffer, buf_len)));
DCHECK(!IsWriteBlocked());
base::TimeTicks now = base::TimeTicks::Now();
int rv = socket_->Write(buf.get(), buf_len,
- base::Bind(&QuicDefaultPacketWriter::OnWriteComplete,
+ base::Bind(&QuicChromiumPacketWriter::OnWriteComplete,
weak_factory_.GetWeakPtr()));
WriteStatus status = WRITE_STATUS_OK;
if (rv < 0) {
@@ -53,21 +54,21 @@ WriteResult QuicDefaultPacketWriter::WritePacket(
return WriteResult(status, rv);
}
-bool QuicDefaultPacketWriter::IsWriteBlockedDataBuffered() const {
+bool QuicChromiumPacketWriter::IsWriteBlockedDataBuffered() const {
// Chrome sockets' Write() methods buffer the data until the Write is
// permitted.
return true;
}
-bool QuicDefaultPacketWriter::IsWriteBlocked() const {
+bool QuicChromiumPacketWriter::IsWriteBlocked() const {
return write_blocked_;
}
-void QuicDefaultPacketWriter::SetWritable() {
+void QuicChromiumPacketWriter::SetWritable() {
write_blocked_ = false;
}
-void QuicDefaultPacketWriter::OnWriteComplete(int rv) {
+void QuicChromiumPacketWriter::OnWriteComplete(int rv) {
DCHECK_NE(rv, ERR_IO_PENDING);
write_blocked_ = false;
if (rv < 0) {
@@ -76,7 +77,7 @@ void QuicDefaultPacketWriter::OnWriteComplete(int rv) {
connection_->OnCanWrite();
}
-QuicByteCount QuicDefaultPacketWriter::GetMaxPacketSize(
+QuicByteCount QuicChromiumPacketWriter::GetMaxPacketSize(
const IPEndPoint& peer_address) const {
return kMaxPacketSize;
}
diff --git a/chromium/net/quic/quic_default_packet_writer.h b/chromium/net/quic/quic_chromium_packet_writer.h
index 7d03a049d8e..bbe36c07991 100644
--- a/chromium/net/quic/quic_default_packet_writer.h
+++ b/chromium/net/quic/quic_chromium_packet_writer.h
@@ -20,17 +20,18 @@ namespace net {
struct WriteResult;
// Chrome specific packet writer which uses a datagram Socket for writing data.
-class NET_EXPORT_PRIVATE QuicDefaultPacketWriter : public QuicPacketWriter {
+class NET_EXPORT_PRIVATE QuicChromiumPacketWriter : public QuicPacketWriter {
public:
- QuicDefaultPacketWriter();
- explicit QuicDefaultPacketWriter(Socket* socket);
- ~QuicDefaultPacketWriter() override;
+ QuicChromiumPacketWriter();
+ explicit QuicChromiumPacketWriter(Socket* socket);
+ ~QuicChromiumPacketWriter() override;
// QuicPacketWriter
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) override;
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) override;
bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
@@ -49,9 +50,9 @@ class NET_EXPORT_PRIVATE QuicDefaultPacketWriter : public QuicPacketWriter {
// Whether a write is currently in flight.
bool write_blocked_;
- base::WeakPtrFactory<QuicDefaultPacketWriter> weak_factory_;
+ base::WeakPtrFactory<QuicChromiumPacketWriter> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(QuicDefaultPacketWriter);
+ DISALLOW_COPY_AND_ASSIGN(QuicChromiumPacketWriter);
};
} // namespace net
diff --git a/chromium/net/quic/quic_client_promised_info.cc b/chromium/net/quic/quic_client_promised_info.cc
new file mode 100644
index 00000000000..f4bef0bc0eb
--- /dev/null
+++ b/chromium/net/quic/quic_client_promised_info.cc
@@ -0,0 +1,123 @@
+// 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/quic_client_promised_info.h"
+
+#include "base/logging.h"
+#include "net/quic/spdy_utils.h"
+
+using net::SpdyHeaderBlock;
+using net::kPushPromiseTimeoutSecs;
+using std::string;
+
+namespace net {
+
+QuicClientPromisedInfo::QuicClientPromisedInfo(QuicClientSessionBase* session,
+ QuicStreamId id,
+ string url)
+ : session_(session),
+ helper_(session->connection()->helper()),
+ id_(id),
+ url_(url),
+ client_request_delegate_(nullptr) {}
+
+QuicClientPromisedInfo::~QuicClientPromisedInfo() {}
+
+void QuicClientPromisedInfo::CleanupAlarm::OnAlarm() {
+ DVLOG(1) << "self GC alarm for stream " << promised_->id_;
+ promised_->Reset(QUIC_STREAM_CANCELLED);
+}
+
+void QuicClientPromisedInfo::Init() {
+ cleanup_alarm_.reset(
+ helper_->CreateAlarm(new QuicClientPromisedInfo::CleanupAlarm(this)));
+ cleanup_alarm_->Set(helper_->GetClock()->ApproximateNow().Add(
+ QuicTime::Delta::FromSeconds(kPushPromiseTimeoutSecs)));
+}
+
+void QuicClientPromisedInfo::OnPromiseHeaders(const SpdyHeaderBlock& headers) {
+ // RFC7540, Section 8.2, requests MUST be safe [RFC7231], Section
+ // 4.2.1. GET and HEAD are the methods that are safe and required.
+ 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;
+ Reset(QUIC_INVALID_PROMISE_METHOD);
+ return;
+ }
+ if (!SpdyUtils::UrlIsValid(headers)) {
+ DVLOG(1) << "Promise for stream " << id_ << " has invalid URL " << url_;
+ Reset(QUIC_INVALID_PROMISE_URL);
+ return;
+ }
+ if (!session_->IsAuthorized(SpdyUtils::GetHostNameFromHeaderBlock(headers))) {
+ Reset(QUIC_UNAUTHORIZED_PROMISE_URL);
+ return;
+ }
+ request_headers_.reset(new SpdyHeaderBlock(headers));
+}
+
+void QuicClientPromisedInfo::OnResponseHeaders(const SpdyHeaderBlock& headers) {
+ response_headers_.reset(new SpdyHeaderBlock(headers));
+ if (client_request_delegate_) {
+ // We already have a client request waiting.
+ FinalValidation();
+ }
+}
+
+void QuicClientPromisedInfo::Reset(QuicRstStreamErrorCode error_code) {
+ QuicClientPushPromiseIndex::Delegate* delegate = client_request_delegate_;
+ session_->ResetPromised(id_, error_code);
+ session_->DeletePromised(this);
+ if (delegate) {
+ delegate->OnRendezvousResult(nullptr);
+ }
+}
+
+QuicAsyncStatus QuicClientPromisedInfo::FinalValidation() {
+ if (!client_request_delegate_->CheckVary(
+ *client_request_headers_, *request_headers_, *response_headers_)) {
+ Reset(QUIC_PROMISE_VARY_MISMATCH);
+ return QUIC_FAILURE;
+ }
+ QuicSpdyStream* stream = session_->GetPromisedStream(id_);
+ if (!stream) {
+ // This shouldn't be possible, as |ClientRequest| guards against
+ // closed stream for the synchronous case. And in the
+ // asynchronous case, a RST can only be caught by |OnAlarm()|.
+ QUIC_BUG << "missing promised stream" << id_;
+ }
+ QuicClientPushPromiseIndex::Delegate* delegate = client_request_delegate_;
+ session_->DeletePromised(this);
+ // Stream can start draining now
+ if (delegate) {
+ delegate->OnRendezvousResult(stream);
+ }
+ return QUIC_SUCCESS;
+}
+
+QuicAsyncStatus QuicClientPromisedInfo::HandleClientRequest(
+ const SpdyHeaderBlock& request_headers,
+ QuicClientPushPromiseIndex::Delegate* delegate) {
+ if (session_->IsClosedStream(id_)) {
+ // There was a RST on the response stream.
+ session_->DeletePromised(this);
+ return QUIC_FAILURE;
+ }
+ client_request_delegate_ = delegate;
+ client_request_headers_.reset(new SpdyHeaderBlock(request_headers));
+ if (!response_headers_) {
+ return QUIC_PENDING;
+ }
+ return FinalValidation();
+}
+
+void QuicClientPromisedInfo::Cancel() {
+ // Don't fire OnRendezvousResult() for client initiated cancel.
+ client_request_delegate_ = nullptr;
+ Reset(QUIC_STREAM_CANCELLED);
+}
+
+} // namespace net
diff --git a/chromium/net/quic/quic_client_promised_info.h b/chromium/net/quic/quic_client_promised_info.h
new file mode 100644
index 00000000000..f4bb50f28ce
--- /dev/null
+++ b/chromium/net/quic/quic_client_promised_info.h
@@ -0,0 +1,113 @@
+// 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_CLIENT_PROMISED_INFO_H_
+#define NET_QUIC_QUIC_CLIENT_PROMISED_INFO_H_
+
+#include <sys/types.h>
+#include <string>
+
+#include "net/quic/quic_alarm.h"
+#include "net/quic/quic_client_push_promise_index.h"
+#include "net/quic/quic_client_session_base.h"
+#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_spdy_stream.h"
+#include "net/spdy/spdy_framer.h"
+
+namespace net {
+
+class QuicClientSessionBase;
+class QuicDataToResend;
+class QuicConnectionHelperInterface;
+
+namespace test {
+class QuicClientPromisedInfoPeer;
+} // namespace test
+
+// QuicClientPromisedInfo tracks the client state of a server push
+// 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
+ : public QuicClientPushPromiseIndex::TryHandle {
+ public:
+ // Interface to QuicSpdyClientStream
+ QuicClientPromisedInfo(QuicClientSessionBase* session,
+ QuicStreamId id,
+ std::string url);
+ virtual ~QuicClientPromisedInfo();
+
+ void Init();
+
+ // Validate promise headers etc.
+ void OnPromiseHeaders(const SpdyHeaderBlock& request_headers);
+
+ // Store response, possibly proceed with final validation.
+ void OnResponseHeaders(const SpdyHeaderBlock& response_headers);
+
+ // Rendezvous between this promised stream and a client request that
+ // has a matching URL.
+ virtual QuicAsyncStatus HandleClientRequest(
+ const SpdyHeaderBlock& headers,
+ QuicClientPushPromiseIndex::Delegate* delegate);
+
+ void Cancel() override;
+
+ // Client requests are initially associated to promises by matching
+ // URL in the client request against the URL in the promise headers,
+ // uing the |promised_by_url| map. The push can be cross-origin, so
+ // the client should validate that the session is authoritative for
+ // the promised URL. If not, it should call |RejectUnauthorized|.
+ QuicClientSessionBase* session() { return session_; }
+
+ // If the promised response contains Vary header, then the fields
+ // specified by Vary must match between the client request header
+ // and the promise headers (see https://crbug.com//554220). Vary
+ // validation requires the response headers (for the actual Vary
+ // field list), the promise headers (taking the role of the "cached"
+ // request), and the client request headers.
+ SpdyHeaderBlock* request_headers() { return request_headers_.get(); }
+
+ SpdyHeaderBlock* response_headers() { return response_headers_.get(); }
+
+ QuicStreamId id() const { return id_; }
+
+ const std::string url() const { return url_; }
+
+ private:
+ friend class test::QuicClientPromisedInfoPeer;
+
+ class CleanupAlarm : public QuicAlarm::Delegate {
+ public:
+ explicit CleanupAlarm(QuicClientPromisedInfo* promised)
+ : promised_(promised) {}
+
+ void OnAlarm() override;
+
+ QuicClientPromisedInfo* promised_;
+ };
+
+ void Reset(QuicRstStreamErrorCode error_code);
+
+ QuicAsyncStatus FinalValidation();
+
+ QuicClientSessionBase* session_;
+ QuicConnectionHelperInterface* helper_;
+ QuicStreamId id_;
+ std::string url_;
+ std::unique_ptr<SpdyHeaderBlock> request_headers_;
+ std::unique_ptr<SpdyHeaderBlock> response_headers_;
+ std::unique_ptr<SpdyHeaderBlock> client_request_headers_;
+ QuicClientPushPromiseIndex::Delegate* client_request_delegate_;
+
+ // The promise will commit suicide eventually if it is not claimed
+ // by a GET first.
+ std::unique_ptr<QuicAlarm> cleanup_alarm_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicClientPromisedInfo);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_CLIENT_PROMISED_INFO_H_
diff --git a/chromium/net/quic/quic_client_promised_info_test.cc b/chromium/net/quic/quic_client_promised_info_test.cc
new file mode 100644
index 00000000000..1084cae16ba
--- /dev/null
+++ b/chromium/net/quic/quic_client_promised_info_test.cc
@@ -0,0 +1,376 @@
+// 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/quic_client_promised_info.h"
+
+#include "base/macros.h"
+#include "base/scoped_ptr.h"
+#include "net/gfe2/balsa_headers.h"
+#include "net/quic/quic_client.h"
+#include "net/quic/quic_client_session.h"
+#include "net/quic/quic_spdy_client_stream.h"
+#include "net/quic/quic_utils.h"
+#include "net/quic/spdy_balsa_utils.h"
+#include "net/quic/spdy_utils.h"
+#include "net/quic/test_tools/crypto_test_utils.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/util/ipaddress.h"
+#include "testing/base/public/gunit.h"
+
+using SpdyHeaderBlock;
+using BalsaHeaders;
+using testing::StrictMock;
+
+namespace net {
+namespace test {
+
+class QuicClientPromisedInfoPeer {
+ public:
+ static QuicAlarm* GetAlarm(QuicClientPromisedInfo* promised_stream) {
+ return promised_stream->cleanup_alarm_.get();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuicClientPromisedInfoPeer);
+};
+
+namespace {
+
+class MockQuicClientSession : public QuicClientSession {
+ public:
+ explicit MockQuicClientSession(QuicConnection* connection,
+ QuicClientPushPromiseIndex* push_promise_index)
+ : QuicClientSession(
+ DefaultQuicConfig(),
+ connection,
+ QuicServerId("example.com", 443, PRIVACY_MODE_DISABLED),
+ &crypto_config_,
+ push_promise_index),
+ crypto_config_(CryptoTestUtils::ProofVerifierForTesting()),
+ authorized_(true) {}
+ ~MockQuicClientSession() override {}
+
+ bool IsAuthorized(const string& authority) override { return authorized_; }
+
+ void set_authorized(bool authorized) { authorized_ = authorized; }
+
+ MOCK_METHOD1(CloseStream, void(QuicStreamId stream_id));
+
+ private:
+ QuicCryptoClientConfig crypto_config_;
+
+ bool authorized_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockQuicClientSession);
+};
+
+class QuicClientPromisedInfoTest : public ::testing::Test {
+ public:
+ class StreamVisitor;
+
+ QuicClientPromisedInfoTest()
+ : connection_(
+ new StrictMock<MockConnection>(&helper_, Perspective::IS_CLIENT)),
+ session_(connection_, &push_promise_index_),
+ body_("hello world"),
+ promise_id_(gfe_quic::test::kServerDataStreamId1) {
+ FLAGS_quic_supports_push_promise = true;
+
+ session_.Initialize();
+
+ headers_.SetResponseFirstline("HTTP/1.1", 200, "Ok");
+ headers_.ReplaceOrAppendHeader("content-length", "11");
+ headers_string_ = SpdyBalsaUtils::SerializeResponseHeaders(headers_);
+
+ stream_.reset(new QuicSpdyClientStream(gfe_quic::test::kClientDataStreamId1,
+ &session_));
+ stream_visitor_.reset(new StreamVisitor());
+ stream_->set_visitor(stream_visitor_.get());
+
+ push_promise_[":path"] = "/bar";
+ push_promise_[":authority"] = "www.google.com";
+ push_promise_[":version"] = "HTTP/1.1";
+ push_promise_[":method"] = "GET";
+ push_promise_[":scheme"] = "https";
+
+ promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
+ serialized_push_promise_ =
+ SpdyUtils::SerializeUncompressedHeaders(push_promise_);
+
+ client_request_ = SpdyHeaderBlock(push_promise_);
+ }
+
+ class StreamVisitor : public QuicSpdyClientStream::Visitor {
+ void OnClose(QuicSpdyStream* stream) override {
+ DVLOG(1) << "stream " << stream->id();
+ }
+ };
+
+ class PushPromiseDelegate : public QuicClientPushPromiseIndex::Delegate {
+ public:
+ explicit PushPromiseDelegate(bool match)
+ : match_(match),
+ rendezvous_fired_(false),
+ rendezvous_stream_(nullptr) {}
+
+ bool CheckVary(const SpdyHeaderBlock& client_request,
+ const SpdyHeaderBlock& promise_request,
+ const SpdyHeaderBlock& promise_response) override {
+ DVLOG(1) << "match " << match_;
+ return match_;
+ }
+
+ void OnRendezvousResult(QuicSpdyClientStream* stream) override {
+ rendezvous_fired_ = true;
+ rendezvous_stream_ = stream;
+ }
+
+ QuicSpdyClientStream* rendezvous_stream() { return rendezvous_stream_; }
+ bool rendezvous_fired() { return rendezvous_fired_; }
+
+ private:
+ bool match_;
+ bool rendezvous_fired_;
+ QuicSpdyClientStream* rendezvous_stream_;
+ };
+
+ void ReceivePromise(QuicStreamId id) {
+ stream_->OnStreamHeaders(serialized_push_promise_);
+
+ stream_->OnPromiseHeadersComplete(id, serialized_push_promise_.size());
+ }
+
+ MockConnectionHelper helper_;
+ StrictMock<MockConnection>* connection_;
+ QuicClientPushPromiseIndex push_promise_index_;
+
+ MockQuicClientSession session_;
+ scoped_ptr<QuicSpdyClientStream> stream_;
+ scoped_ptr<StreamVisitor> stream_visitor_;
+ scoped_ptr<QuicSpdyClientStream> promised_stream_;
+ BalsaHeaders headers_;
+ string headers_string_;
+ string body_;
+ SpdyHeaderBlock push_promise_;
+ QuicStreamId promise_id_;
+ string promise_url_;
+ string serialized_push_promise_;
+ SpdyHeaderBlock client_request_;
+};
+
+TEST_F(QuicClientPromisedInfoTest, PushPromise) {
+ ReceivePromise(promise_id_);
+
+ // Verify that the promise is in the unclaimed streams map.
+ EXPECT_NE(session_.GetPromisedById(promise_id_), nullptr);
+}
+
+TEST_F(QuicClientPromisedInfoTest, PushPromiseCleanupAlarm) {
+ ReceivePromise(promise_id_);
+
+ // Verify that the promise is in the unclaimed streams map.
+ QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
+ ASSERT_NE(promised, nullptr);
+
+ // Fire the alarm that will cancel the promised stream.
+ EXPECT_CALL(*connection_,
+ SendRstStream(promise_id_, QUIC_STREAM_CANCELLED, 0));
+ helper_.FireAlarm(QuicClientPromisedInfoPeer::GetAlarm(promised));
+
+ // Verify that the promise is gone after the alarm fires.
+ EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
+ EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr);
+}
+
+TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidMethod) {
+ // Promise with an unsafe method
+ push_promise_[":method"] = "PUT";
+ serialized_push_promise_ =
+ SpdyUtils::SerializeUncompressedHeaders(push_promise_);
+
+ EXPECT_CALL(*connection_,
+ SendRstStream(promise_id_, QUIC_INVALID_PROMISE_METHOD, 0));
+ ReceivePromise(promise_id_);
+
+ // Verify that the promise headers were ignored
+ EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
+ EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr);
+}
+
+TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidUrl) {
+ // Remove required header field to make URL invalid
+ push_promise_.erase(":authority");
+ serialized_push_promise_ =
+ SpdyUtils::SerializeUncompressedHeaders(push_promise_);
+
+ EXPECT_CALL(*connection_,
+ SendRstStream(promise_id_, QUIC_INVALID_PROMISE_URL, 0));
+ ReceivePromise(promise_id_);
+
+ // Verify that the promise headers were ignored
+ EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
+ EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr);
+}
+
+TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidUrl) {
+ // Promise with an unsafe method
+ push_promise_[":method"] = "PUT";
+ serialized_push_promise_ =
+ SpdyUtils::SerializeUncompressedHeaders(push_promise_);
+
+ EXPECT_CALL(*connection_,
+ SendRstStream(promise_id_, QUIC_INVALID_PROMISE_METHOD, 0));
+ ReceivePromise(promise_id_);
+
+ // Verify that the promise headers were ignored
+ EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
+ EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr);
+}
+
+TEST_F(QuicClientPromisedInfoTest, PushPromiseUnauthorizedUrl) {
+ session_.set_authorized(false);
+
+ EXPECT_CALL(*connection_,
+ SendRstStream(promise_id_, QUIC_UNAUTHORIZED_PROMISE_URL, 0));
+
+ ReceivePromise(promise_id_);
+
+ QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
+ ASSERT_EQ(promised, nullptr);
+}
+
+TEST_F(QuicClientPromisedInfoTest, PushPromiseMismatch) {
+ ReceivePromise(promise_id_);
+
+ QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
+ ASSERT_NE(promised, nullptr);
+
+ // Need to send the promised response headers and initiate the
+ // rendezvous for secondary validation to proceed.
+ QuicSpdyClientStream* promise_stream =
+ static_cast<QuicSpdyClientStream*>(session_.GetStream(promise_id_));
+ promise_stream->OnStreamHeaders(headers_string_);
+ promise_stream->OnStreamHeadersComplete(false, headers_string_.size());
+
+ PushPromiseDelegate delegate(/*match=*/false);
+ EXPECT_CALL(*connection_,
+ SendRstStream(promise_id_, QUIC_PROMISE_VARY_MISMATCH, 0));
+ EXPECT_CALL(session_, CloseStream(promise_id_));
+
+ promised->HandleClientRequest(client_request_, &delegate);
+}
+
+TEST_F(QuicClientPromisedInfoTest, PushPromiseVaryWaits) {
+ ReceivePromise(promise_id_);
+
+ QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
+ ASSERT_NE(promised, nullptr);
+
+ // Now initiate rendezvous.
+ PushPromiseDelegate delegate(/*match=*/true);
+ promised->HandleClientRequest(std::move(client_request_), &delegate);
+
+ // Promise is still there, waiting for response.
+ EXPECT_NE(session_.GetPromisedById(promise_id_), nullptr);
+
+ // Send Response, should trigger promise validation and complete rendezvous
+ QuicSpdyClientStream* promise_stream =
+ static_cast<QuicSpdyClientStream*>(session_.GetStream(promise_id_));
+ ASSERT_NE(promise_stream, nullptr);
+ promise_stream->OnStreamHeaders(headers_string_);
+ promise_stream->OnStreamHeadersComplete(false, headers_string_.size());
+
+ // Promise is gone
+ EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
+}
+
+TEST_F(QuicClientPromisedInfoTest, PushPromiseVaryNoWait) {
+ ReceivePromise(promise_id_);
+
+ QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
+ ASSERT_NE(promised, nullptr);
+
+ QuicSpdyClientStream* promise_stream =
+ static_cast<QuicSpdyClientStream*>(session_.GetStream(promise_id_));
+ ASSERT_NE(promise_stream, nullptr);
+
+ // Send Response, should trigger promise validation and complete rendezvous
+ promise_stream->OnStreamHeaders(headers_string_);
+ promise_stream->OnStreamHeadersComplete(false, headers_string_.size());
+
+ // Now initiate rendezvous.
+ PushPromiseDelegate delegate(/*match=*/true);
+ promised->HandleClientRequest(std::move(client_request_), &delegate);
+
+ // Promise is gone
+ EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
+ // Have a push stream
+ EXPECT_TRUE(delegate.rendezvous_fired());
+
+ EXPECT_NE(delegate.rendezvous_stream(), nullptr);
+}
+
+TEST_F(QuicClientPromisedInfoTest, PushPromiseWaitCancels) {
+ ReceivePromise(promise_id_);
+
+ QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
+ ASSERT_NE(promised, nullptr);
+
+ // Now initiate rendezvous.
+ PushPromiseDelegate delegate(/*match=*/true);
+ promised->HandleClientRequest(std::move(client_request_), &delegate);
+
+ // Promise is still there, waiting for response.
+ EXPECT_NE(session_.GetPromisedById(promise_id_), nullptr);
+
+ // Create response stream, but no data yet.
+ session_.GetStream(promise_id_);
+
+ // Fire the alarm that will cancel the promised stream.
+ EXPECT_CALL(session_, CloseStream(promise_id_));
+ EXPECT_CALL(*connection_,
+ SendRstStream(promise_id_, QUIC_STREAM_CANCELLED, 0));
+ promised->Cancel();
+
+ // Promise is gone
+ EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
+}
+
+TEST_F(QuicClientPromisedInfoTest, PushPromiseDataClosed) {
+ ReceivePromise(promise_id_);
+
+ QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
+ ASSERT_NE(promised, nullptr);
+
+ QuicSpdyClientStream* promise_stream =
+ static_cast<QuicSpdyClientStream*>(session_.GetStream(promise_id_));
+ ASSERT_NE(promise_stream, nullptr);
+
+ // Send response, rendezvous will be able to finish synchronously.
+ promise_stream->OnStreamHeaders(headers_string_);
+ promise_stream->OnStreamHeadersComplete(false, headers_string_.size());
+
+ EXPECT_CALL(session_, CloseStream(promise_id_));
+ EXPECT_CALL(*connection_,
+ SendRstStream(promise_id_, QUIC_STREAM_PEER_GOING_AWAY, 0));
+ session_.SendRstStream(promise_id_, QUIC_STREAM_PEER_GOING_AWAY, 0);
+
+ // Now initiate rendezvous.
+ PushPromiseDelegate delegate(/*match=*/true);
+ EXPECT_EQ(
+ promised->HandleClientRequest(std::move(client_request_), &delegate),
+ QUIC_FAILURE);
+
+ // Got an indication of the stream failure, client should retry
+ // request.
+ EXPECT_FALSE(delegate.rendezvous_fired());
+ EXPECT_EQ(delegate.rendezvous_stream(), nullptr);
+
+ // Promise is gone
+ EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/quic_client_push_promise_index.cc b/chromium/net/quic/quic_client_push_promise_index.cc
new file mode 100644
index 00000000000..e62f1f07c38
--- /dev/null
+++ b/chromium/net/quic/quic_client_push_promise_index.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 "net/quic/quic_client_push_promise_index.h"
+
+#include <string>
+
+#include "net/quic/quic_client_promised_info.h"
+#include "net/quic/spdy_utils.h"
+
+using net::SpdyHeaderBlock;
+using std::string;
+
+namespace net {
+
+QuicClientPushPromiseIndex::QuicClientPushPromiseIndex() {}
+
+QuicClientPushPromiseIndex::~QuicClientPushPromiseIndex() {}
+
+QuicClientPushPromiseIndex::TryHandle::~TryHandle() {}
+
+QuicClientPromisedInfo* QuicClientPushPromiseIndex::GetPromised(
+ const string& url) {
+ QuicPromisedByUrlMap::iterator it = promised_by_url_.find(url);
+ if (it == promised_by_url_.end()) {
+ return nullptr;
+ }
+ return it->second;
+}
+
+QuicAsyncStatus QuicClientPushPromiseIndex::Try(
+ const SpdyHeaderBlock& request,
+ QuicClientPushPromiseIndex::Delegate* delegate,
+ TryHandle** handle) {
+ string url(SpdyUtils::GetUrlFromHeaderBlock(request));
+ QuicPromisedByUrlMap::iterator it = promised_by_url_.find(url);
+ if (it != promised_by_url_.end()) {
+ QuicClientPromisedInfo* promised = it->second;
+ QuicAsyncStatus rv = promised->HandleClientRequest(request, delegate);
+ if (rv == QUIC_PENDING) {
+ *handle = promised;
+ }
+ return rv;
+ }
+ return QUIC_FAILURE;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/quic_client_push_promise_index.h b/chromium/net/quic/quic_client_push_promise_index.h
new file mode 100644
index 00000000000..f8167ae01af
--- /dev/null
+++ b/chromium/net/quic/quic_client_push_promise_index.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_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
+#define NET_QUIC_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
+
+#include <string>
+
+#include "net/quic/quic_client_session_base.h"
+#include "net/quic/quic_types.h"
+
+namespace net {
+
+// QuicClientPushPromiseIndex is the interface to support rendezvous
+// between client requests and resources delivered via server push.
+// The same index can be shared across multiple sessions (e.g. for the
+// same browser users profile), since cross-origin pushes are allowed
+// (subject to authority constraints).
+
+class NET_EXPORT_PRIVATE QuicClientPushPromiseIndex {
+ public:
+ // Delegate is used to complete the rendezvous that began with
+ // |Try()|.
+ class NET_EXPORT_PRIVATE Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ // The primary lookup matched request with push promise by URL. A
+ // secondary match is necessary to ensure Vary (RFC 2616, 14.14)
+ // is honored. If Vary is not present, return true. If Vary is
+ // present, return whether designated header fields of
+ // |promise_request| and |client_request| match.
+ virtual bool CheckVary(const SpdyHeaderBlock& client_request,
+ const SpdyHeaderBlock& promise_request,
+ const SpdyHeaderBlock& promise_response) = 0;
+
+ // On rendezvous success, provides the promised |stream|. Callee
+ // does not inherit ownership of |stream|. On rendezvous failure,
+ // |stream| is |nullptr| and the client should retry the request.
+ // Rendezvous can fail due to promise validation failure or RST on
+ // promised stream. |url| will have been removed from the index
+ // before |OnRendezvousResult()| is invoked, so a recursive call to
+ // |Try()| will return |QUIC_FAILURE|, which may be convenient for
+ // retry purposes.
+ virtual void OnRendezvousResult(QuicSpdyStream* stream) = 0;
+ };
+
+ class NET_EXPORT_PRIVATE TryHandle {
+ public:
+ // Cancel the request.
+ virtual void Cancel() = 0;
+
+ protected:
+ TryHandle() {}
+ ~TryHandle();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TryHandle);
+ };
+
+ QuicClientPushPromiseIndex();
+ virtual ~QuicClientPushPromiseIndex();
+
+ // Called by client code, used to enforce affinity between requests
+ // for promised streams and the session the promise came from.
+ QuicClientPromisedInfo* GetPromised(const std::string& url);
+
+ // Called by client code, to initiate rendezvous between a request
+ // and a server push stream. If |request|'s url is in the index,
+ // rendezvous will be attempted and may complete immediately or
+ // asynchronously. If the matching promise and response headers
+ // have already arrived, the delegate's methods will fire
+ // recursively from within |Try()|. Returns |QUIC_SUCCESS| if the
+ // rendezvous was a success. Returns |QUIC_FAILURE| if there was no
+ // matching promise, or if there was but the rendezvous has failed.
+ // Returns QUIC_PENDING if a matching promise was found, but the
+ // rendezvous needs to complete asynchronously because the promised
+ // response headers are not yet available. If result is
+ // QUIC_PENDING, then |*handle| will set so that the caller may
+ // cancel the request if need be. The caller does not inherit
+ // ownership of |*handle|, and it ceases to be valid if the caller
+ // invokes |handle->Cancel()| or if |delegate->OnReponse()| fires.
+ QuicAsyncStatus Try(const SpdyHeaderBlock& request,
+ Delegate* delegate,
+ TryHandle** handle);
+
+ QuicPromisedByUrlMap* promised_by_url() { return &promised_by_url_; }
+
+ private:
+ QuicPromisedByUrlMap promised_by_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicClientPushPromiseIndex);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
diff --git a/chromium/net/quic/quic_client_push_promise_index_test.cc b/chromium/net/quic/quic_client_push_promise_index_test.cc
new file mode 100644
index 00000000000..85c7f0cbc48
--- /dev/null
+++ b/chromium/net/quic/quic_client_push_promise_index_test.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/quic/quic_client_push_promise_index.h"
+
+#include <string>
+
+#include "net/quic/spdy_utils.h"
+#include "net/quic/test_tools/crypto_test_utils.h"
+#include "net/quic/test_tools/mock_quic_client_promised_info.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/tools/quic/quic_client_session.h"
+
+using testing::_;
+using testing::Return;
+using testing::StrictMock;
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+class MockQuicClientSession : public QuicClientSession {
+ public:
+ explicit MockQuicClientSession(QuicConnection* connection,
+ QuicClientPushPromiseIndex* push_promise_index)
+ : QuicClientSession(
+ DefaultQuicConfig(),
+ connection,
+ QuicServerId("example.com", 443, PRIVACY_MODE_DISABLED),
+ &crypto_config_,
+ push_promise_index),
+ crypto_config_(CryptoTestUtils::ProofVerifierForTesting()) {}
+ ~MockQuicClientSession() override {}
+
+ MOCK_METHOD1(CloseStream, void(QuicStreamId stream_id));
+
+ private:
+ QuicCryptoClientConfig crypto_config_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockQuicClientSession);
+};
+
+class QuicClientPushPromiseIndexTest : public ::testing::Test {
+ public:
+ QuicClientPushPromiseIndexTest()
+ : connection_(
+ new StrictMock<MockConnection>(&helper_, Perspective::IS_CLIENT)),
+ session_(connection_, &index_),
+ promised_(&session_, kServerDataStreamId1, url_) {
+ FLAGS_quic_supports_push_promise = true;
+ request_[":path"] = "/bar";
+ request_[":authority"] = "www.google.com";
+ request_[":version"] = "HTTP/1.1";
+ request_[":method"] = "GET";
+ request_[":scheme"] = "https";
+ url_ = SpdyUtils::GetUrlFromHeaderBlock(request_);
+ }
+
+ MockConnectionHelper helper_;
+ StrictMock<MockConnection>* connection_;
+ MockQuicClientSession session_;
+ QuicClientPushPromiseIndex index_;
+ SpdyHeaderBlock request_;
+ string url_;
+ MockQuicClientPromisedInfo promised_;
+ QuicClientPushPromiseIndex::TryHandle* handle_;
+};
+
+TEST_F(QuicClientPushPromiseIndexTest, TryRequestSuccess) {
+ (*index_.promised_by_url())[url_] = &promised_;
+ EXPECT_CALL(promised_, HandleClientRequest(_, _))
+ .WillOnce(Return(QUIC_SUCCESS));
+ EXPECT_EQ(index_.Try(request_, nullptr, &handle_), QUIC_SUCCESS);
+}
+
+TEST_F(QuicClientPushPromiseIndexTest, TryRequestPending) {
+ (*index_.promised_by_url())[url_] = &promised_;
+ EXPECT_CALL(promised_, HandleClientRequest(_, _))
+ .WillOnce(Return(QUIC_PENDING));
+ EXPECT_EQ(index_.Try(request_, nullptr, &handle_), QUIC_PENDING);
+}
+
+TEST_F(QuicClientPushPromiseIndexTest, TryRequestFailure) {
+ (*index_.promised_by_url())[url_] = &promised_;
+ EXPECT_CALL(promised_, HandleClientRequest(_, _))
+ .WillOnce(Return(QUIC_FAILURE));
+ EXPECT_EQ(index_.Try(request_, nullptr, &handle_), QUIC_FAILURE);
+}
+
+TEST_F(QuicClientPushPromiseIndexTest, TryNoPromise) {
+ EXPECT_EQ(index_.Try(request_, nullptr, &handle_), QUIC_FAILURE);
+}
+
+TEST_F(QuicClientPushPromiseIndexTest, GetNoPromise) {
+ EXPECT_EQ(index_.GetPromised(url_), nullptr);
+}
+
+TEST_F(QuicClientPushPromiseIndexTest, GetPromise) {
+ (*index_.promised_by_url())[url_] = &promised_;
+ EXPECT_EQ(index_.GetPromised(url_), &promised_);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/quic_client_session_base.cc b/chromium/net/quic/quic_client_session_base.cc
index 5ff7d12aa60..dd9974aa77c 100644
--- a/chromium/net/quic/quic_client_session_base.cc
+++ b/chromium/net/quic/quic_client_session_base.cc
@@ -4,28 +4,32 @@
#include "net/quic/quic_client_session_base.h"
+#include "net/quic/quic_client_promised_info.h"
#include "net/quic/quic_flags.h"
+#include "net/quic/spdy_utils.h"
+
+using std::string;
namespace net {
-QuicClientSessionBase::QuicClientSessionBase(QuicConnection* connection,
- const QuicConfig& config)
- : QuicSpdySession(connection, config) {}
+QuicClientSessionBase::QuicClientSessionBase(
+ QuicConnection* connection,
+ QuicClientPushPromiseIndex* push_promise_index,
+ const QuicConfig& config)
+ : QuicSpdySession(connection, config),
+ push_promise_index_(push_promise_index),
+ largest_promised_stream_id_(kInvalidStreamId) {}
-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();
+ push_promise_index_->promised_by_url()->erase(it.second->url());
+ }
+}
void QuicClientSessionBase::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
QuicSession::OnCryptoHandshakeEvent(event);
- // Set FEC policy for streams immediately after sending CHLO and before any
- // more data is sent.
- if (!FLAGS_enable_quic_fec || event != ENCRYPTION_FIRST_ESTABLISHED ||
- !config()->HasSendConnectionOptions() ||
- !ContainsQuicTag(config()->SendConnectionOptions(), kFHDR)) {
- return;
- }
- // kFHDR config maps to FEC protection always for headers stream.
- // TODO(jri): Add crypto stream in addition to headers for kHDR.
- headers_stream()->set_fec_policy(FEC_PROTECT_ALWAYS);
}
void QuicClientSessionBase::OnPromiseHeaders(QuicStreamId stream_id,
@@ -38,15 +42,32 @@ void QuicClientSessionBase::OnPromiseHeaders(QuicStreamId stream_id,
stream->OnPromiseHeaders(headers_data);
}
+void QuicClientSessionBase::OnInitialHeadersComplete(
+ QuicStreamId stream_id,
+ const SpdyHeaderBlock& response_headers) {
+ // Note that the strong ordering of the headers stream means that
+ // QuicSpdyClientStream::OnPromiseHeadersComplete must have already
+ // been called (on the associated stream) if this is a promised
+ // stream. However, this stream may not have existed at this time,
+ // hence the need to query the session.
+ QuicClientPromisedInfo* promised = GetPromisedById(stream_id);
+ if (!promised)
+ return;
+
+ promised->OnResponseHeaders(response_headers);
+}
+
void QuicClientSessionBase::OnPromiseHeadersComplete(
QuicStreamId stream_id,
QuicStreamId promised_stream_id,
size_t frame_len) {
if (promised_stream_id != kInvalidStreamId &&
promised_stream_id <= largest_promised_stream_id_) {
- CloseConnectionWithDetails(QUIC_INVALID_STREAM_ID,
- "Received push stream id lesser or equal to the"
- " last accepted before");
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID,
+ "Received push stream id lesser or equal to the"
+ " last accepted before",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
largest_promised_stream_id_ = promised_stream_id;
@@ -59,4 +80,97 @@ void QuicClientSessionBase::OnPromiseHeadersComplete(
stream->OnPromiseHeadersComplete(promised_stream_id, frame_len);
}
+void QuicClientSessionBase::HandlePromised(QuicStreamId /* associated_id */,
+ QuicStreamId id,
+ const SpdyHeaderBlock& headers) {
+ // Due to pathalogical packet re-ordering, it is possible that
+ // frames for the promised stream have already arrived, and the
+ // promised stream could be active or closed.
+ 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";
+ return;
+ }
+
+ if (push_promise_index_->promised_by_url()->size() >= get_max_promises()) {
+ DVLOG(1) << "Too many promises, rejecting promise for stream " << id;
+ ResetPromised(id, QUIC_REFUSED_STREAM);
+ return;
+ }
+
+ 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();
+ ResetPromised(id, QUIC_DUPLICATE_PROMISE_URL);
+ return;
+ }
+
+ if (GetPromisedById(id)) {
+ // OnPromiseHeadersComplete() would have closed the connection if
+ // promised id is a duplicate.
+ QUIC_BUG << "Duplicate promise for id " << id;
+ return;
+ }
+
+ QuicClientPromisedInfo* promised = new QuicClientPromisedInfo(this, id, url);
+ std::unique_ptr<QuicClientPromisedInfo> promised_owner(promised);
+ promised->Init();
+ 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);
+}
+
+QuicClientPromisedInfo* QuicClientSessionBase::GetPromisedByUrl(
+ const string& url) {
+ QuicPromisedByUrlMap::iterator it =
+ push_promise_index_->promised_by_url()->find(url);
+ if (it != push_promise_index_->promised_by_url()->end()) {
+ return it->second;
+ }
+ return nullptr;
+}
+
+QuicClientPromisedInfo* QuicClientSessionBase::GetPromisedById(
+ const QuicStreamId id) {
+ QuicPromisedByIdMap::iterator it = promised_by_id_.find(id);
+ if (it != promised_by_id_.end()) {
+ return it->second.get();
+ }
+ return nullptr;
+}
+
+QuicSpdyStream* QuicClientSessionBase::GetPromisedStream(
+ const QuicStreamId id) {
+ if (IsClosedStream(id)) {
+ return nullptr;
+ }
+ StreamMap::iterator it = dynamic_streams().find(id);
+ if (it != dynamic_streams().end()) {
+ return static_cast<QuicSpdyStream*>(it->second);
+ }
+ QUIC_BUG << "Open promised stream " << id << " is missing!";
+ return nullptr;
+}
+
+void QuicClientSessionBase::DeletePromised(QuicClientPromisedInfo* promised) {
+ push_promise_index_->promised_by_url()->erase(promised->url());
+ // Since promised_by_id_ contains the unique_ptr, this will destroy
+ // promised.
+ promised_by_id_.erase(promised->id());
+}
+
+void QuicClientSessionBase::ResetPromised(QuicStreamId id,
+ QuicRstStreamErrorCode error_code) {
+ SendRstStream(id, error_code, 0);
+ if (!IsOpenStream(id)) {
+ MaybeIncreaseLargestPeerStreamId(id);
+ InsertLocallyClosedStreamsHighestOffset(id, 0);
+ }
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_client_session_base.h b/chromium/net/quic/quic_client_session_base.h
index ae65ab01aa4..d1dfc3180fe 100644
--- a/chromium/net/quic/quic_client_session_base.h
+++ b/chromium/net/quic/quic_client_session_base.h
@@ -5,31 +5,43 @@
#ifndef NET_QUIC_QUIC_CLIENT_SESSION_BASE_H_
#define NET_QUIC_QUIC_CLIENT_SESSION_BASE_H_
+#include <string>
+
#include "base/macros.h"
#include "net/quic/quic_crypto_client_stream.h"
#include "net/quic/quic_spdy_session.h"
namespace net {
+class QuicClientPromisedInfo;
+class QuicClientPushPromiseIndex;
+class QuicSpdyClientStream;
+
+// For client/http layer code. Lookup promised streams based on
+// matching promised request url. The same map can be shared across
+// multiple sessions, since cross-origin pushes are allowed (subject
+// to authority constraints). Clients should use this map to enforce
+// session affinity for requests corresponding to cross-origin push
+// promised streams.
+using QuicPromisedByUrlMap =
+ std::unordered_map<std::string, QuicClientPromisedInfo*>;
+
+// The maximum time a promises stream can be reserved without being
+// claimed by a client request.
+const int64_t kPushPromiseTimeoutSecs = 60;
+
// Base class for all client-specific QuicSession subclasses.
-class NET_EXPORT_PRIVATE QuicClientSessionBase : public QuicSpdySession {
+class NET_EXPORT_PRIVATE QuicClientSessionBase
+ : public QuicSpdySession,
+ public QuicCryptoClientStream::ProofHandler {
public:
- QuicClientSessionBase(QuicConnection* connection, const QuicConfig& config);
+ // Caller retains ownership of |promised_by_url|.
+ QuicClientSessionBase(QuicConnection* connection,
+ QuicClientPushPromiseIndex* push_promise_index,
+ const QuicConfig& config);
~QuicClientSessionBase() override;
- // Called when the proof in |cached| is marked valid. If this is a secure
- // QUIC session, then this will happen only after the proof verifier
- // completes.
- virtual void OnProofValid(
- const QuicCryptoClientConfig::CachedState& cached) = 0;
-
- // Called when proof verification details become available, either because
- // proof verification is complete, or when cached details are used. This
- // will only be called for secure QUIC connections.
- virtual void OnProofVerifyDetailsAvailable(
- const ProofVerifyDetails& verify_details) = 0;
-
// Override base class to set FEC policy before any data is sent by client.
void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
@@ -45,7 +57,69 @@ class NET_EXPORT_PRIVATE QuicClientSessionBase : public QuicSpdySession {
QuicStreamId promised_stream_id,
size_t frame_len) override;
+ // Called by |QuicSpdyClientStream| on receipt of response headers,
+ // needed to detect promised server push streams, as part of
+ // client-request to push-stream rendezvous.
+ void OnInitialHeadersComplete(QuicStreamId stream_id,
+ const SpdyHeaderBlock& response_headers);
+
+ // Called by |QuicSpdyClientStream| on receipt of PUSH_PROMISE, does
+ // some session level validation and creates the
+ // |QuicClientPromisedInfo| inserting into maps by (promised) id and
+ // url.
+ virtual void HandlePromised(QuicStreamId associated_id,
+ QuicStreamId promised_id,
+ const SpdyHeaderBlock& headers);
+
+ // For cross-origin server push, this should verify the server is
+ // authoritative per [RFC2818], Section 3. Roughly, subjectAltName
+ // std::list in the certificate should contain a matching DNS name, or IP
+ // address. |hostname| is derived from the ":authority" header field of
+ // the PUSH_PROMISE frame, port if present there will be dropped.
+ virtual bool IsAuthorized(const std::string& hostname) = 0;
+
+ // Session retains ownership.
+ QuicClientPromisedInfo* GetPromisedByUrl(const std::string& url);
+ // Session retains ownership.
+ QuicClientPromisedInfo* GetPromisedById(const QuicStreamId id);
+
+ //
+ QuicSpdyStream* GetPromisedStream(const QuicStreamId id);
+
+ // Removes |promised| from the maps by url.
+ void ErasePromisedByUrl(QuicClientPromisedInfo* promised);
+
+ // Removes |promised| from the maps by url and id and destroys
+ // promised.
+ virtual void DeletePromised(QuicClientPromisedInfo* promised);
+
+ // Sends Rst for the stream, and makes sure that future calls to
+ // IsClosedStream(id) return true, which ensures that any subsequent
+ // frames related to this stream will be ignored (modulo flow
+ // control accounting).
+ void ResetPromised(QuicStreamId id, QuicRstStreamErrorCode error_code);
+
+ size_t get_max_promises() const {
+ return max_open_incoming_streams() * kMaxPromisedStreamsMultiplier;
+ }
+
+ QuicClientPushPromiseIndex* push_promise_index() {
+ return push_promise_index_;
+ }
+
private:
+ // For QuicSpdyClientStream to detect that a response corresponds to a
+ // promise.
+ using QuicPromisedByIdMap =
+ std::unordered_map<QuicStreamId, std::unique_ptr<QuicClientPromisedInfo>>;
+
+ // As per rfc7540, section 10.5: track promise streams in "reserved
+ // (remote)". The primary key is URL from he promise request
+ // headers. The promised stream id is a secondary key used to get
+ // promise info when the response headers of the promised stream
+ // arrive.
+ QuicClientPushPromiseIndex* push_promise_index_;
+ QuicPromisedByIdMap promised_by_id_;
QuicStreamId largest_promised_stream_id_;
DISALLOW_COPY_AND_ASSIGN(QuicClientSessionBase);
diff --git a/chromium/net/quic/quic_config.cc b/chromium/net/quic/quic_config.cc
index 7dc93e5fc7c..9083ca641ac 100644
--- a/chromium/net/quic/quic_config.cc
+++ b/chromium/net/quic/quic_config.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "net/quic/crypto/crypto_handshake_message.h"
#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_utils.h"
using std::min;
@@ -203,8 +204,8 @@ bool QuicFixedUint32::HasSendValue() const {
}
uint32_t QuicFixedUint32::GetSendValue() const {
- LOG_IF(DFATAL, !has_send_value_) << "No send value to get for tag:"
- << QuicUtils::TagToString(tag_);
+ QUIC_BUG_IF(!has_send_value_) << "No send value to get for tag:"
+ << QuicUtils::TagToString(tag_);
return send_value_;
}
@@ -218,8 +219,8 @@ bool QuicFixedUint32::HasReceivedValue() const {
}
uint32_t QuicFixedUint32::GetReceivedValue() const {
- LOG_IF(DFATAL, !has_receive_value_) << "No receive value to get for tag:"
- << QuicUtils::TagToString(tag_);
+ QUIC_BUG_IF(!has_receive_value_) << "No receive value to get for tag:"
+ << QuicUtils::TagToString(tag_);
return receive_value_;
}
@@ -263,6 +264,9 @@ QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
has_send_values_(false),
has_receive_values_(false) {}
+QuicFixedTagVector::QuicFixedTagVector(const QuicFixedTagVector& other) =
+ default;
+
QuicFixedTagVector::~QuicFixedTagVector() {}
bool QuicFixedTagVector::HasSendValues() const {
@@ -270,8 +274,8 @@ bool QuicFixedTagVector::HasSendValues() const {
}
QuicTagVector QuicFixedTagVector::GetSendValues() const {
- LOG_IF(DFATAL, !has_send_values_) << "No send values to get for tag:"
- << QuicUtils::TagToString(tag_);
+ QUIC_BUG_IF(!has_send_values_) << "No send values to get for tag:"
+ << QuicUtils::TagToString(tag_);
return send_values_;
}
@@ -285,8 +289,8 @@ bool QuicFixedTagVector::HasReceivedValues() const {
}
QuicTagVector QuicFixedTagVector::GetReceivedValues() const {
- LOG_IF(DFATAL, !has_receive_values_) << "No receive value to get for tag:"
- << QuicUtils::TagToString(tag_);
+ QUIC_BUG_IF(!has_receive_values_) << "No receive value to get for tag:"
+ << QuicUtils::TagToString(tag_);
return receive_values_;
}
@@ -344,10 +348,13 @@ QuicConfig::QuicConfig()
initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL),
socket_receive_buffer_(kSRBF, PRESENCE_OPTIONAL),
- multipath_enabled_(kMPTH, PRESENCE_OPTIONAL) {
+ multipath_enabled_(kMPTH, PRESENCE_OPTIONAL),
+ connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL) {
SetDefaults();
}
+QuicConfig::QuicConfig(const QuicConfig& other) = default;
+
QuicConfig::~QuicConfig() {}
bool QuicConfig::SetInitialReceivedConnectionOptions(
@@ -466,9 +473,9 @@ uint32_t QuicConfig::GetInitialRoundTripTimeUsToSend() const {
void QuicConfig::SetInitialStreamFlowControlWindowToSend(
uint32_t window_bytes) {
if (window_bytes < kMinimumFlowControlSendWindow) {
- LOG(DFATAL) << "Initial stream flow control receive window ("
- << window_bytes << ") cannot be set lower than default ("
- << kMinimumFlowControlSendWindow << ").";
+ QUIC_BUG << "Initial stream flow control receive window (" << window_bytes
+ << ") cannot be set lower than default ("
+ << kMinimumFlowControlSendWindow << ").";
window_bytes = kMinimumFlowControlSendWindow;
}
initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes);
@@ -489,9 +496,9 @@ uint32_t QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
void QuicConfig::SetInitialSessionFlowControlWindowToSend(
uint32_t window_bytes) {
if (window_bytes < kMinimumFlowControlSendWindow) {
- LOG(DFATAL) << "Initial session flow control receive window ("
- << window_bytes << ") cannot be set lower than default ("
- << kMinimumFlowControlSendWindow << ").";
+ QUIC_BUG << "Initial session flow control receive window (" << window_bytes
+ << ") cannot be set lower than default ("
+ << kMinimumFlowControlSendWindow << ").";
window_bytes = kMinimumFlowControlSendWindow;
}
initial_session_flow_control_window_bytes_.SetSendValue(window_bytes);
@@ -530,6 +537,14 @@ bool QuicConfig::MultipathEnabled() const {
return multipath_enabled_.GetUint32() > 0;
}
+void QuicConfig::SetDisableConnectionMigration() {
+ connection_migration_disabled_.SetSendValue(1);
+}
+
+bool QuicConfig::DisableConnectionMigration() const {
+ return connection_migration_disabled_.HasReceivedValue();
+}
+
bool QuicConfig::negotiated() const {
// TODO(ianswett): Add the negotiated parameters once and iterate over all
// of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
@@ -563,6 +578,7 @@ void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
initial_session_flow_control_window_bytes_.ToHandshakeMessage(out);
socket_receive_buffer_.ToHandshakeMessage(out);
+ connection_migration_disabled_.ToHandshakeMessage(out);
connection_options_.ToHandshakeMessage(out);
}
@@ -606,6 +622,10 @@ QuicErrorCode QuicConfig::ProcessPeerHello(
error_details);
}
if (error == QUIC_NO_ERROR) {
+ error = connection_migration_disabled_.ProcessPeerHello(
+ peer_hello, hello_type, error_details);
+ }
+ if (error == QUIC_NO_ERROR) {
error = connection_options_.ProcessPeerHello(peer_hello, hello_type,
error_details);
}
diff --git a/chromium/net/quic/quic_config.h b/chromium/net/quic/quic_config.h
index 1fbb4b73ceb..6650f7434dd 100644
--- a/chromium/net/quic/quic_config.h
+++ b/chromium/net/quic/quic_config.h
@@ -183,6 +183,7 @@ class NET_EXPORT_PRIVATE QuicFixedUint32 : public QuicConfigValue {
class NET_EXPORT_PRIVATE QuicFixedTagVector : public QuicConfigValue {
public:
QuicFixedTagVector(QuicTag name, QuicConfigPresence presence);
+ QuicFixedTagVector(const QuicFixedTagVector& other);
~QuicFixedTagVector() override;
bool HasSendValues() const;
@@ -219,6 +220,7 @@ class NET_EXPORT_PRIVATE QuicFixedTagVector : public QuicConfigValue {
class NET_EXPORT_PRIVATE QuicConfig {
public:
QuicConfig();
+ QuicConfig(const QuicConfig& other);
~QuicConfig();
void SetConnectionOptionsToSend(const QuicTagVector& connection_options);
@@ -333,6 +335,10 @@ class NET_EXPORT_PRIVATE QuicConfig {
bool MultipathEnabled() const;
+ void SetDisableConnectionMigration();
+
+ bool DisableConnectionMigration() const;
+
bool negotiated() const;
// ToHandshakeMessage serialises the settings in this object as a series of
@@ -382,6 +388,9 @@ class NET_EXPORT_PRIVATE QuicConfig {
// Whether to support multipath for this connection.
QuicNegotiableUint32 multipath_enabled_;
+
+ // Whether tell peer not to attempt connection migration.
+ QuicFixedUint32 connection_migration_disabled_;
};
} // namespace net
diff --git a/chromium/net/quic/quic_config_test.cc b/chromium/net/quic/quic_config_test.cc
index ec1c6aa38fb..b18673e0c5e 100644
--- a/chromium/net/quic/quic_config_test.cc
+++ b/chromium/net/quic/quic_config_test.cc
@@ -77,7 +77,6 @@ TEST_F(QuicConfigTest, ProcessClientHello) {
client_config.SetSocketReceiveBufferToSend(kDefaultSocketReceiveBuffer);
QuicTagVector copt;
copt.push_back(kTBBR);
- copt.push_back(kFHDR);
client_config.SetConnectionOptionsToSend(copt);
CryptoHandshakeMessage msg;
client_config.ToHandshakeMessage(&msg);
@@ -102,10 +101,9 @@ TEST_F(QuicConfigTest, ProcessClientHello) {
EXPECT_EQ(kDefaultMaxStreamsPerConnection, config_.MaxStreamsPerConnection());
EXPECT_EQ(10 * kNumMicrosPerMilli, config_.ReceivedInitialRoundTripTimeUs());
EXPECT_TRUE(config_.HasReceivedConnectionOptions());
- EXPECT_EQ(3u, config_.ReceivedConnectionOptions().size());
+ EXPECT_EQ(2u, config_.ReceivedConnectionOptions().size());
EXPECT_EQ(config_.ReceivedConnectionOptions()[0], kIW50);
EXPECT_EQ(config_.ReceivedConnectionOptions()[1], kTBBR);
- EXPECT_EQ(config_.ReceivedConnectionOptions()[2], kFHDR);
EXPECT_EQ(config_.ReceivedInitialStreamFlowControlWindowBytes(),
2 * kInitialStreamFlowControlWindowForTest);
EXPECT_EQ(config_.ReceivedInitialSessionFlowControlWindowBytes(),
@@ -228,12 +226,9 @@ TEST_F(QuicConfigTest, HasClientSentConnectionOption) {
QuicConfig client_config;
QuicTagVector copt;
copt.push_back(kTBBR);
- copt.push_back(kFHDR);
client_config.SetConnectionOptionsToSend(copt);
EXPECT_TRUE(client_config.HasClientSentConnectionOption(
kTBBR, Perspective::IS_CLIENT));
- EXPECT_TRUE(client_config.HasClientSentConnectionOption(
- kFHDR, Perspective::IS_CLIENT));
CryptoHandshakeMessage msg;
client_config.ToHandshakeMessage(&msg);
@@ -245,11 +240,9 @@ TEST_F(QuicConfigTest, HasClientSentConnectionOption) {
EXPECT_TRUE(config_.negotiated());
EXPECT_TRUE(config_.HasReceivedConnectionOptions());
- EXPECT_EQ(2u, config_.ReceivedConnectionOptions().size());
+ EXPECT_EQ(1u, config_.ReceivedConnectionOptions().size());
EXPECT_TRUE(
config_.HasClientSentConnectionOption(kTBBR, Perspective::IS_SERVER));
- EXPECT_TRUE(
- config_.HasClientSentConnectionOption(kFHDR, Perspective::IS_SERVER));
}
} // namespace
diff --git a/chromium/net/quic/quic_connection.cc b/chromium/net/quic/quic_connection.cc
index 75c761a3e1f..7ce76a82701 100644
--- a/chromium/net/quic/quic_connection.cc
+++ b/chromium/net/quic/quic_connection.cc
@@ -20,7 +20,10 @@
#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"
#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/crypto/quic_decrypter.h"
@@ -29,15 +32,12 @@
#include "net/quic/quic_bandwidth.h"
#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_config.h"
-#include "net/quic/quic_fec_group.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_packet_generator.h"
#include "net/quic/quic_utils.h"
using base::StringPiece;
using base::StringPrintf;
-using base::hash_map;
-using base::hash_set;
using std::list;
using std::make_pair;
using std::max;
@@ -58,10 +58,6 @@ namespace {
// This will likely have to be tuned.
const QuicPacketNumber kMaxPacketGap = 5000;
-// Limit the number of FEC groups to two. If we get enough out of order packets
-// that this becomes limiting, we can revisit.
-const size_t kMaxFecGroups = 2;
-
// Maximum number of acks received before sending an ack in response.
const QuicPacketCount kMaxPacketsReceivedBeforeAckSend = 20;
@@ -79,15 +75,20 @@ 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 AckAlarm : public QuicAlarm::Delegate {
public:
explicit AckAlarm(QuicConnection* connection) : connection_(connection) {}
- QuicTime OnAlarm() override {
+ void OnAlarm() override {
DCHECK(connection_->ack_frame_updated());
- connection_->SendAck();
- return QuicTime::Zero();
+ QuicConnection::ScopedPacketBundler bundler(connection_,
+ QuicConnection::SEND_ACK);
}
private:
@@ -104,10 +105,7 @@ class RetransmissionAlarm : public QuicAlarm::Delegate {
explicit RetransmissionAlarm(QuicConnection* connection)
: connection_(connection) {}
- QuicTime OnAlarm() override {
- connection_->OnRetransmissionTimeout();
- return QuicTime::Zero();
- }
+ void OnAlarm() override { connection_->OnRetransmissionTimeout(); }
private:
QuicConnection* connection_;
@@ -121,11 +119,7 @@ class SendAlarm : public QuicAlarm::Delegate {
public:
explicit SendAlarm(QuicConnection* connection) : connection_(connection) {}
- QuicTime OnAlarm() override {
- connection_->WriteIfNotBlocked();
- // Never reschedule the alarm, since CanWrite does that.
- return QuicTime::Zero();
- }
+ void OnAlarm() override { connection_->WriteAndBundleAcksIfNotBlocked(); }
private:
QuicConnection* connection_;
@@ -137,11 +131,7 @@ class TimeoutAlarm : public QuicAlarm::Delegate {
public:
explicit TimeoutAlarm(QuicConnection* connection) : connection_(connection) {}
- QuicTime OnAlarm() override {
- connection_->CheckForTimeout();
- // Never reschedule the alarm, since CheckForTimeout does that.
- return QuicTime::Zero();
- }
+ void OnAlarm() override { connection_->CheckForTimeout(); }
private:
QuicConnection* connection_;
@@ -153,10 +143,7 @@ class PingAlarm : public QuicAlarm::Delegate {
public:
explicit PingAlarm(QuicConnection* connection) : connection_(connection) {}
- QuicTime OnAlarm() override {
- connection_->OnPingTimeout();
- return QuicTime::Zero();
- }
+ void OnAlarm() override { connection_->OnPingTimeout(); }
private:
QuicConnection* connection_;
@@ -169,11 +156,7 @@ class MtuDiscoveryAlarm : public QuicAlarm::Delegate {
explicit MtuDiscoveryAlarm(QuicConnection* connection)
: connection_(connection) {}
- QuicTime OnAlarm() override {
- connection_->DiscoverMtu();
- // DiscoverMtu() handles rescheduling the alarm by itself.
- return QuicTime::Zero();
- }
+ void OnAlarm() override { connection_->DiscoverMtu(); }
private:
QuicConnection* connection_;
@@ -181,23 +164,6 @@ class MtuDiscoveryAlarm : public QuicAlarm::Delegate {
DISALLOW_COPY_AND_ASSIGN(MtuDiscoveryAlarm);
};
-// This alarm may be scheduled when an FEC protected packet is sent out.
-class FecAlarm : public QuicAlarm::Delegate {
- public:
- explicit FecAlarm(QuicPacketGenerator* packet_generator)
- : packet_generator_(packet_generator) {}
-
- QuicTime OnAlarm() override {
- packet_generator_->OnFecTimeout();
- return QuicTime::Zero();
- }
-
- private:
- QuicPacketGenerator* packet_generator_;
-
- DISALLOW_COPY_AND_ASSIGN(FecAlarm);
-};
-
// Listens for acks of MTU discovery packets and raises the maximum packet size
// of the connection if the probe succeeds.
class MtuDiscoveryAckListener : public QuicAckListenerInterface {
@@ -206,7 +172,7 @@ class MtuDiscoveryAckListener : public QuicAckListenerInterface {
: connection_(connection), probe_size_(probe_size) {}
void OnPacketAcked(int /*acked_bytes*/,
- QuicTime::Delta /*delta_largest_observed*/) override {
+ QuicTime::Delta /*ack delay time*/) override {
// MTU discovery packets are not retransmittable, so it must be acked.
MaybeIncreaseMtu();
}
@@ -246,6 +212,7 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id,
helper->GetClock()->ApproximateNow(),
perspective),
helper_(helper),
+ per_packet_options_(nullptr),
writer_(writer),
owns_writer_(owns_writer),
encryption_level_(ENCRYPTION_NONE),
@@ -255,10 +222,11 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id,
random_generator_(helper->GetRandomGenerator()),
connection_id_(connection_id),
peer_address_(address),
- migrating_peer_port_(0),
+ active_peer_migration_type_(NO_CHANGE),
+ highest_packet_sent_before_peer_migration_(0),
last_packet_decrypted_(false),
- last_packet_revived_(false),
last_size_(0),
+ current_packet_data_(nullptr),
last_decrypted_packet_level_(ENCRYPTION_NONE),
should_last_packet_instigate_acks_(false),
largest_seen_packet_with_ack_(0),
@@ -266,22 +234,31 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id,
max_undecryptable_packets_(0),
pending_version_negotiation_packet_(false),
save_crypto_packets_as_termination_packets_(false),
- silent_close_enabled_(false),
+ idle_timeout_connection_close_behavior_(
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET),
+ close_connection_after_five_rtos_(false),
received_packet_manager_(&stats_),
ack_queued_(false),
num_retransmittable_packets_received_since_last_ack_sent_(0),
+ last_ack_had_missing_packets_(false),
num_packets_received_since_last_ack_sent_(0),
stop_waiting_count_(0),
- ack_decimation_enabled_(false),
+ ack_mode_(TCP_ACKING),
delay_setting_retransmission_alarm_(false),
pending_retransmission_alarm_(false),
- ack_alarm_(helper->CreateAlarm(new AckAlarm(this))),
- retransmission_alarm_(helper->CreateAlarm(new RetransmissionAlarm(this))),
- send_alarm_(helper->CreateAlarm(new SendAlarm(this))),
- resume_writes_alarm_(helper->CreateAlarm(new SendAlarm(this))),
- timeout_alarm_(helper->CreateAlarm(new TimeoutAlarm(this))),
- ping_alarm_(helper->CreateAlarm(new PingAlarm(this))),
- mtu_discovery_alarm_(helper->CreateAlarm(new MtuDiscoveryAlarm(this))),
+ defer_send_in_response_to_packets_(false),
+ arena_(),
+ ack_alarm_(helper->CreateAlarm(arena_.New<AckAlarm>(this), &arena_)),
+ retransmission_alarm_(
+ helper->CreateAlarm(arena_.New<RetransmissionAlarm>(this), &arena_)),
+ send_alarm_(helper->CreateAlarm(arena_.New<SendAlarm>(this), &arena_)),
+ resume_writes_alarm_(
+ helper->CreateAlarm(arena_.New<SendAlarm>(this), &arena_)),
+ timeout_alarm_(
+ helper->CreateAlarm(arena_.New<TimeoutAlarm>(this), &arena_)),
+ ping_alarm_(helper->CreateAlarm(arena_.New<PingAlarm>(this), &arena_)),
+ mtu_discovery_alarm_(
+ helper->CreateAlarm(arena_.New<MtuDiscoveryAlarm>(this), &arena_)),
visitor_(nullptr),
debug_visitor_(nullptr),
packet_generator_(connection_id_,
@@ -289,9 +266,8 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id,
random_generator_,
helper->GetBufferAllocator(),
this),
- fec_alarm_(helper->CreateAlarm(new FecAlarm(&packet_generator_))),
idle_network_timeout_(QuicTime::Delta::Infinite()),
- overall_connection_timeout_(QuicTime::Delta::Infinite()),
+ handshake_timeout_(QuicTime::Delta::Infinite()),
time_of_last_received_packet_(clock_->ApproximateNow()),
time_of_last_sent_new_packet_(clock_->ApproximateNow()),
last_send_for_timeout_(clock_->ApproximateNow()),
@@ -302,14 +278,11 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id,
clock_,
&stats_,
FLAGS_quic_use_bbr_congestion_control ? kBBR : kCubic,
- FLAGS_quic_use_time_loss_detection ? kTime : kNack),
+ FLAGS_quic_use_time_loss_detection ? kTime : kNack,
+ /*delegate=*/nullptr),
version_negotiation_state_(START_NEGOTIATION),
perspective_(perspective),
connected_(true),
- peer_ip_changed_(false),
- peer_port_changed_(false),
- self_ip_changed_(false),
- self_port_changed_(false),
can_truncate_connection_ids_(true),
mtu_discovery_target_(0),
mtu_probe_count_(0),
@@ -341,25 +314,28 @@ QuicConnection::~QuicConnection() {
if (termination_packets_.get() != nullptr) {
STLDeleteElements(termination_packets_.get());
}
- STLDeleteValues(&group_map_);
ClearQueuedPackets();
}
void QuicConnection::ClearQueuedPackets() {
for (QueuedPacketList::iterator it = queued_packets_.begin();
it != queued_packets_.end(); ++it) {
- delete it->retransmittable_frames;
- delete it->packet;
+ // Delete the buffer before calling ClearSerializedPacket, which sets
+ // encrypted_buffer to nullptr.
+ delete[] it->encrypted_buffer;
+ QuicUtils::ClearSerializedPacket(&(*it));
}
queued_packets_.clear();
}
void QuicConnection::SetFromConfig(const QuicConfig& config) {
if (config.negotiated()) {
+ // Handshake complete, set handshake timeout to Infinite.
SetNetworkTimeouts(QuicTime::Delta::Infinite(),
config.IdleConnectionStateLifetime());
if (config.SilentClose()) {
- silent_close_enabled_ = true;
+ idle_timeout_connection_close_behavior_ =
+ ConnectionCloseBehavior::SILENT_CLOSE;
}
if (FLAGS_quic_enable_multipath && config.MultipathEnabled()) {
multipath_enabled_ = true;
@@ -377,16 +353,6 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
}
max_undecryptable_packets_ = config.max_undecryptable_packets();
- if (config.HasClientSentConnectionOption(kFSPA, perspective_)) {
- packet_generator_.set_fec_send_policy(FecSendPolicy::FEC_ALARM_TRIGGER);
- }
- if (config.HasClientSentConnectionOption(kFRTT, perspective_)) {
- // TODO(rtenneti): Delete this code after the 0.25 RTT FEC experiment.
- const float kFecTimeoutRttMultiplier = 0.25;
- packet_generator_.set_rtt_multiplier_for_fec_timeout(
- kFecTimeoutRttMultiplier);
- }
-
if (config.HasClientSentConnectionOption(kMTUH, perspective_)) {
SetMtuDiscoveryTarget(kMtuDiscoveryTargetPacketSizeHigh);
}
@@ -396,9 +362,16 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnSetFromConfig(config);
}
- if (FLAGS_quic_ack_decimation &&
- config.HasClientSentConnectionOption(kACKD, perspective_)) {
- ack_decimation_enabled_ = true;
+ if (config.HasClientSentConnectionOption(kACKD, perspective_)) {
+ ack_mode_ = ACK_DECIMATION;
+ }
+ if (FLAGS_quic_ack_decimation2 &&
+ config.HasClientSentConnectionOption(kAKD2, perspective_)) {
+ ack_mode_ = ACK_DECIMATION_WITH_REORDERING;
+ }
+ if (FLAGS_quic_enable_rto_timeout &&
+ config.HasClientSentConnectionOption(k5RTO, perspective_)) {
+ close_connection_after_five_rtos_ = true;
}
}
@@ -409,12 +382,16 @@ void QuicConnection::OnSendConnectionState(
}
}
+void QuicConnection::OnReceiveConnectionState(
+ const CachedNetworkParameters& cached_network_params) {
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnReceiveConnectionState(cached_network_params);
+ }
+}
+
void QuicConnection::ResumeConnectionState(
const CachedNetworkParameters& cached_network_params,
bool max_bandwidth_resumption) {
- if (debug_visitor_ != nullptr) {
- debug_visitor_->OnResumeConnectionState(cached_network_params);
- }
sent_packet_manager_.ResumeConnectionState(cached_network_params,
max_bandwidth_resumption);
}
@@ -446,23 +423,12 @@ void QuicConnection::OnError(QuicFramer* framer) {
if (!connected_ || last_packet_decrypted_ == false) {
return;
}
- SendConnectionCloseWithDetails(framer->error(), framer->detailed_error());
-}
-
-void QuicConnection::MaybeSetFecAlarm(QuicPacketNumber packet_number) {
- if (fec_alarm_->IsSet()) {
- return;
- }
- QuicTime::Delta timeout = packet_generator_.GetFecTimeout(packet_number);
- if (!timeout.IsInfinite()) {
- fec_alarm_->Update(clock_->ApproximateNow().Add(timeout),
- QuicTime::Delta::FromMilliseconds(1));
- }
+ CloseConnection(framer->error(), framer->detailed_error(),
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
void QuicConnection::OnPacket() {
last_packet_decrypted_ = false;
- last_packet_revived_ = false;
}
void QuicConnection::OnPublicResetPacket(const QuicPublicResetPacket& packet) {
@@ -473,10 +439,10 @@ void QuicConnection::OnPublicResetPacket(const QuicPublicResetPacket& packet) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPublicResetPacket(packet);
}
- CloseConnection(QUIC_PUBLIC_RESET, true);
-
- DVLOG(1) << ENDPOINT << "Connection " << connection_id()
- << " closed via QUIC_PUBLIC_RESET from peer.";
+ const string error_details = "Received public reset.";
+ DVLOG(1) << ENDPOINT << error_details;
+ TearDownLocalConnectionState(QUIC_PUBLIC_RESET, error_details,
+ ConnectionCloseSource::FROM_PEER);
}
bool QuicConnection::OnProtocolVersionMismatch(QuicVersion received_version) {
@@ -484,9 +450,10 @@ bool QuicConnection::OnProtocolVersionMismatch(QuicVersion received_version) {
<< received_version;
// TODO(satyamshekhar): Implement no server state in this mode.
if (perspective_ == Perspective::IS_CLIENT) {
- LOG(DFATAL) << ENDPOINT << "Framer called OnProtocolVersionMismatch. "
- << "Closing connection.";
- CloseConnection(QUIC_INTERNAL_ERROR, false);
+ const string error_details = "Protocol version mismatch.";
+ QUIC_BUG << ENDPOINT << error_details;
+ TearDownLocalConnectionState(QUIC_INTERNAL_ERROR, error_details,
+ ConnectionCloseSource::FROM_SELF);
return false;
}
DCHECK_NE(version(), received_version);
@@ -544,9 +511,10 @@ void QuicConnection::OnVersionNegotiationPacket(
// here. (Check for a bug regression.)
DCHECK_EQ(connection_id_, packet.connection_id);
if (perspective_ == Perspective::IS_SERVER) {
- LOG(DFATAL) << ENDPOINT << "Framer parsed VersionNegotiationPacket."
- << " Closing connection.";
- CloseConnection(QUIC_INTERNAL_ERROR, false);
+ const string error_details = "Server receieved version negotiation packet.";
+ QUIC_BUG << error_details;
+ TearDownLocalConnectionState(QUIC_INTERNAL_ERROR, error_details,
+ ConnectionCloseSource::FROM_SELF);
return;
}
if (debug_visitor_ != nullptr) {
@@ -559,16 +527,19 @@ void QuicConnection::OnVersionNegotiationPacket(
}
if (ContainsValue(packet.versions, version())) {
- DLOG(WARNING) << ENDPOINT << "The server already supports our version. "
- << "It should have accepted our connection.";
- // Just drop the connection.
- CloseConnection(QUIC_INVALID_VERSION_NEGOTIATION_PACKET, false);
+ const string error_details =
+ "Server already supports client's version and should have accepted the "
+ "connection.";
+ DLOG(WARNING) << error_details;
+ TearDownLocalConnectionState(QUIC_INVALID_VERSION_NEGOTIATION_PACKET,
+ error_details,
+ ConnectionCloseSource::FROM_SELF);
return;
}
if (!SelectMutualVersion(packet.versions)) {
- SendConnectionCloseWithDetails(QUIC_INVALID_VERSION,
- "no common version found");
+ CloseConnection(QUIC_INVALID_VERSION, "No common version found.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
@@ -579,8 +550,6 @@ void QuicConnection::OnVersionNegotiationPacket(
RetransmitUnackedPackets(ALL_UNACKED_RETRANSMISSION);
}
-void QuicConnection::OnRevivedPacket() {}
-
bool QuicConnection::OnUnauthenticatedPublicHeader(
const QuicPacketPublicHeader& header) {
if (header.connection_id == connection_id_) {
@@ -610,10 +579,29 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
// here.
DCHECK_EQ(connection_id_, header.public_header.connection_id);
+ // Multipath is not enabled, but a packet with multipath flag on is received.
+ if (!multipath_enabled_ && header.public_header.multipath_flag) {
+ const string error_details =
+ "Received a packet with multipath flag but multipath is not enabled.";
+ QUIC_BUG << error_details;
+ CloseConnection(QUIC_BAD_MULTIPATH_FLAG, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ if (!packet_generator_.IsPendingPacketEmpty()) {
+ // Incoming packets may change a queued ACK frame.
+ const string error_details =
+ "Pending frames must be serialized before incoming packets are "
+ "processed.";
+ QUIC_BUG << error_details;
+ CloseConnection(QUIC_INTERNAL_ERROR, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+
// 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 (FLAGS_quic_drop_non_awaited_packets &&
- !received_packet_manager_.IsAwaitingPacket(header.packet_number)) {
+ if (!received_packet_manager_.IsAwaitingPacket(header.packet_number)) {
DVLOG(1) << ENDPOINT << "Packet " << header.packet_number
<< " no longer being waited for. Discarding.";
if (debug_visitor_ != nullptr) {
@@ -649,6 +637,15 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
return false;
}
+ // Only migrate connection to a new peer address if a change is not underway.
+ PeerAddressChangeType peer_migration_type =
+ QuicUtils::DetermineAddressChangeType(peer_address_,
+ last_packet_source_address_);
+ if (active_peer_migration_type_ == NO_CHANGE &&
+ peer_migration_type != NO_CHANGE) {
+ StartPeerMigration(peer_migration_type);
+ }
+
--stats_.packets_dropped;
DVLOG(1) << ENDPOINT << "Received packet header: " << header;
last_header_ = header;
@@ -656,15 +653,6 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
return true;
}
-void QuicConnection::OnFecProtectedPayload(StringPiece payload) {
- DCHECK_EQ(IN_FEC_GROUP, last_header_.is_in_fec_group);
- DCHECK_NE(0u, last_header_.fec_group);
- QuicFecGroup* group = GetFecGroup();
- if (group != nullptr) {
- group->Update(last_decrypted_packet_level_, last_header_, payload);
- }
-}
-
bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) {
DCHECK(connected_);
if (debug_visitor_ != nullptr) {
@@ -672,13 +660,18 @@ bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) {
}
if (frame.stream_id != kCryptoStreamId &&
last_decrypted_packet_level_ == ENCRYPTION_NONE) {
- DLOG(WARNING) << ENDPOINT
- << "Received an unencrypted data frame: closing connection";
- SendConnectionCloseWithDetails(QUIC_UNENCRYPTED_STREAM_DATA,
- "Unencrypted stream data seen");
+ QUIC_BUG << ENDPOINT
+ << "Received an unencrypted data frame: closing connection"
+ << " packet_number:" << last_header_.packet_number
+ << " stream_id:" << frame.stream_id
+ << " received_packets:" << received_packet_manager_.ack_frame();
+ CloseConnection(QUIC_UNENCRYPTED_STREAM_DATA,
+ "Unencrypted stream data seen.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
visitor_->OnStreamFrame(frame);
+ visitor_->PostProcessAfterData();
stats_.stream_bytes_received += frame.frame_length;
should_last_packet_instigate_acks_ = true;
return connected_;
@@ -698,11 +691,12 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
const char* error = ValidateAckFrame(incoming_ack);
if (error != nullptr) {
- SendConnectionCloseWithDetails(QUIC_INVALID_ACK_DATA, error);
+ CloseConnection(QUIC_INVALID_ACK_DATA, error,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
- if (FLAGS_quic_respect_send_alarm2 && send_alarm_->IsSet()) {
+ if (send_alarm_->IsSet()) {
send_alarm_->Cancel();
}
ProcessAckFrame(incoming_ack);
@@ -737,8 +731,6 @@ void QuicConnection::ProcessStopWaitingFrame(
const QuicStopWaitingFrame& stop_waiting) {
largest_seen_packet_with_stop_waiting_ = last_header_.packet_number;
received_packet_manager_.UpdatePacketInformationSentByPeer(stop_waiting);
- // Possibly close any FecGroups which are now irrelevant.
- CloseFecGroupsBefore(stop_waiting.least_unacked + 1);
}
bool QuicConnection::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) {
@@ -751,7 +743,8 @@ bool QuicConnection::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) {
const char* error = ValidateStopWaitingFrame(frame);
if (error != nullptr) {
- SendConnectionCloseWithDetails(QUIC_INVALID_STOP_WAITING_DATA, error);
+ CloseConnection(QUIC_INVALID_STOP_WAITING_DATA, error,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
@@ -778,16 +771,19 @@ const char* QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) {
<< 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";
+ return "Largest observed too high.";
}
if (incoming_ack.largest_observed < sent_packet_manager_.largest_observed()) {
LOG(WARNING) << ENDPOINT << "Peer's largest_observed packet decreased:"
<< incoming_ack.largest_observed << " vs "
- << sent_packet_manager_.largest_observed();
+ << sent_packet_manager_.largest_observed()
+ << " 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";
+ return "Largest observed too low.";
}
if (!incoming_ack.missing_packets.Empty() &&
@@ -796,7 +792,7 @@ const char* QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) {
<< incoming_ack.missing_packets.Max()
<< " which is greater than largest observed: "
<< incoming_ack.largest_observed;
- return "Missing packet higher than largest observed";
+ return "Missing packet higher than largest observed.";
}
if (!incoming_ack.missing_packets.Empty() &&
@@ -806,23 +802,18 @@ const char* QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) {
<< incoming_ack.missing_packets.Min()
<< " which is smaller than least_packet_awaited_by_peer_: "
<< sent_packet_manager_.least_packet_awaited_by_peer();
- return "Missing packet smaller than least awaited";
+ return "Missing packet smaller than least awaited.";
}
if (!sent_entropy_manager_.IsValidEntropy(incoming_ack.largest_observed,
incoming_ack.missing_packets,
incoming_ack.entropy_hash)) {
- LOG(WARNING) << ENDPOINT << "Peer sent invalid entropy.";
- return "Invalid entropy";
+ LOG(WARNING) << ENDPOINT << "Peer sent invalid entropy."
+ << " largest_observed:" << incoming_ack.largest_observed
+ << " last_received:" << last_header_.packet_number;
+ return "Invalid entropy.";
}
- if (incoming_ack.latest_revived_packet != 0 &&
- !incoming_ack.missing_packets.Contains(
- incoming_ack.latest_revived_packet)) {
- LOG(WARNING) << ENDPOINT
- << "Peer specified revived packet which was not missing.";
- return "Invalid revived packet";
- }
return nullptr;
}
@@ -834,7 +825,7 @@ const char* QuicConnection::ValidateStopWaitingFrame(
<< 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";
+ return "Least unacked too small.";
}
if (stop_waiting.least_unacked > last_header_.packet_number) {
@@ -842,21 +833,12 @@ const char* QuicConnection::ValidateStopWaitingFrame(
<< "Peer sent least_unacked:" << stop_waiting.least_unacked
<< " greater than the enclosing packet number:"
<< last_header_.packet_number;
- return "Least unacked too large";
+ return "Least unacked too large.";
}
return nullptr;
}
-void QuicConnection::OnFecData(StringPiece redundancy) {
- DCHECK_EQ(IN_FEC_GROUP, last_header_.is_in_fec_group);
- DCHECK_NE(0u, last_header_.fec_group);
- QuicFecGroup* group = GetFecGroup();
- if (group != nullptr) {
- group->UpdateFec(last_decrypted_packet_level_, last_header_, redundancy);
- }
-}
-
bool QuicConnection::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
DCHECK(connected_);
if (debug_visitor_ != nullptr) {
@@ -867,6 +849,7 @@ bool QuicConnection::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
<< " with error: "
<< QuicUtils::StreamErrorToString(frame.error_code);
visitor_->OnRstStream(frame);
+ visitor_->PostProcessAfterData();
should_last_packet_instigate_acks_ = true;
return connected_;
}
@@ -877,11 +860,12 @@ bool QuicConnection::OnConnectionCloseFrame(
if (debug_visitor_ != nullptr) {
debug_visitor_->OnConnectionCloseFrame(frame);
}
- DVLOG(1) << ENDPOINT << "CONNECTION_CLOSE_FRAME received for connection: "
- << connection_id()
- << " with error: " << QuicUtils::ErrorToString(frame.error_code)
- << " " << frame.error_details;
- CloseConnection(frame.error_code, true);
+ DVLOG(1) << ENDPOINT
+ << "Received ConnectionClose for connection: " << connection_id()
+ << ", with error: " << QuicUtils::ErrorToString(frame.error_code)
+ << " (" << frame.error_details << ")";
+ TearDownLocalConnectionState(frame.error_code, frame.error_details,
+ ConnectionCloseSource::FROM_PEER);
return connected_;
}
@@ -897,6 +881,7 @@ bool QuicConnection::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
goaway_received_ = true;
visitor_->OnGoAway(frame);
+ visitor_->PostProcessAfterData();
should_last_packet_instigate_acks_ = true;
return connected_;
}
@@ -910,6 +895,7 @@ bool QuicConnection::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
<< "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;
return connected_;
}
@@ -922,10 +908,22 @@ bool QuicConnection::OnBlockedFrame(const QuicBlockedFrame& frame) {
DVLOG(1) << ENDPOINT
<< "BLOCKED_FRAME received for stream: " << frame.stream_id;
visitor_->OnBlockedFrame(frame);
+ visitor_->PostProcessAfterData();
should_last_packet_instigate_acks_ = true;
return connected_;
}
+bool QuicConnection::OnPathCloseFrame(const QuicPathCloseFrame& frame) {
+ DCHECK(connected_);
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnPathCloseFrame(frame);
+ }
+ DVLOG(1) << ENDPOINT
+ << "PATH_CLOSE_FRAME received for path: " << frame.path_id;
+ OnPathClosed(frame.path_id);
+ return connected_;
+}
+
void QuicConnection::OnPacketComplete() {
// Don't do anything if this packet closed the connection.
if (!connected_) {
@@ -933,8 +931,7 @@ void QuicConnection::OnPacketComplete() {
return;
}
- DVLOG(1) << ENDPOINT << (last_packet_revived_ ? "Revived" : "Got")
- << " packet " << last_header_.packet_number << " for "
+ DVLOG(1) << ENDPOINT << "Got packet " << last_header_.packet_number << " for "
<< last_header_.public_header.connection_id;
// An ack will be sent if a missing retransmittable packet was received;
@@ -942,15 +939,11 @@ void QuicConnection::OnPacketComplete() {
should_last_packet_instigate_acks_ &&
received_packet_manager_.IsMissing(last_header_.packet_number);
- // Record received or revived packet to populate ack info correctly before
- // processing stream frames, since the processing may result in a response
- // packet with a bundled ack.
- if (last_packet_revived_) {
- received_packet_manager_.RecordPacketRevived(last_header_.packet_number);
- } else {
- received_packet_manager_.RecordPacketReceived(
- last_size_, last_header_, time_of_last_received_packet_);
- }
+ // Record received to populate ack info correctly before processing stream
+ // frames, since the processing may result in a response packet with a bundled
+ // ack.
+ received_packet_manager_.RecordPacketReceived(last_size_, last_header_,
+ time_of_last_received_packet_);
// Process stop waiting frames here, instead of inline, because the packet
// needs to be considered 'received' before the entropy can be updated.
@@ -965,7 +958,6 @@ void QuicConnection::OnPacketComplete() {
ClearLastFrames();
MaybeCloseIfTooManyOutstandingPackets();
- MaybeProcessRevivedPacket();
}
void QuicConnection::MaybeQueueAck(bool was_missing) {
@@ -979,13 +971,16 @@ void QuicConnection::MaybeQueueAck(bool was_missing) {
// Determine whether the newly received packet was missing before recording
// the received packet.
- if (was_missing) {
+ // Ack decimation with reordering relies on the timer to send an ack, but if
+ // missing packets we reported in the previous ack, send an ack immediately.
+ if (was_missing && (ack_mode_ != ACK_DECIMATION_WITH_REORDERING ||
+ last_ack_had_missing_packets_)) {
ack_queued_ = true;
}
if (should_last_packet_instigate_acks_ && !ack_queued_) {
++num_retransmittable_packets_received_since_last_ack_sent_;
- if (ack_decimation_enabled_ &&
+ if (ack_mode_ != TCP_ACKING &&
last_header_.packet_number > kMinReceivedBeforeAckDecimation) {
// Ack up to 10 packets at once.
if (num_retransmittable_packets_received_since_last_ack_sent_ >=
@@ -1010,10 +1005,18 @@ void QuicConnection::MaybeQueueAck(bool was_missing) {
}
// If there are new missing packets to report, send an ack immediately.
- // TODO(ianswett): Consider allowing 1ms of reordering for the
- // ack decimation experiment.
if (received_packet_manager_.HasNewMissingPackets()) {
- ack_queued_ = true;
+ if (ack_mode_ == ACK_DECIMATION_WITH_REORDERING) {
+ // Wait the minimum of an eighth min_rtt and the existing ack time.
+ QuicTime ack_time = clock_->ApproximateNow().Add(
+ sent_packet_manager_.GetRttStats()->min_rtt().Multiply(0.125));
+ if (!ack_alarm_->IsSet() || ack_alarm_->deadline() > ack_time) {
+ ack_alarm_->Cancel();
+ ack_alarm_->Set(ack_time);
+ }
+ } else {
+ ack_queued_ = true;
+ }
}
}
@@ -1032,22 +1035,23 @@ void QuicConnection::MaybeCloseIfTooManyOutstandingPackets() {
// It's possible largest observed is less than least unacked.
if (sent_packet_manager_.largest_observed() >
(sent_packet_manager_.GetLeastUnacked() + kMaxTrackedPackets)) {
- SendConnectionCloseWithDetails(
+ CloseConnection(
QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS,
- StringPrintf("More than %" PRIu64 " outstanding.", kMaxTrackedPackets));
+ 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) {
- SendConnectionCloseWithDetails(
+ CloseConnection(
QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS,
- StringPrintf("More than %" PRIu64 " outstanding.", kMaxTrackedPackets));
+ StringPrintf("More than %" PRIu64 " outstanding.", kMaxTrackedPackets),
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
}
-void QuicConnection::PopulateAckFrame(QuicAckFrame* ack) {
- received_packet_manager_.UpdateReceivedPacketInfo(ack,
- clock_->ApproximateNow());
+const QuicFrame QuicConnection::GetUpdatedAckFrame() {
+ return received_packet_manager_.GetUpdatedAckFrame(clock_->ApproximateNow());
}
void QuicConnection::PopulateStopWaitingFrame(
@@ -1065,11 +1069,14 @@ void QuicConnection::MaybeSendInResponseToPacket() {
if (!connected_) {
return;
}
- ScopedPacketBundler bundler(this, ack_queued_ ? SEND_ACK : NO_ACK);
-
// Now that we have received an ack, we might be able to send packets which
// are queued locally, or drain streams which are blocked.
- WriteIfNotBlocked();
+ if (defer_send_in_response_to_packets_) {
+ send_alarm_->Cancel();
+ send_alarm_->Set(clock_->ApproximateNow());
+ } else {
+ WriteAndBundleAcksIfNotBlocked();
+ }
}
void QuicConnection::SendVersionNegotiationPacket() {
@@ -1084,9 +1091,9 @@ void QuicConnection::SendVersionNegotiationPacket() {
scoped_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());
+ WriteResult result = writer_->WritePacket(
+ version_packet->data(), version_packet->length(),
+ self_address().address(), peer_address(), per_packet_options_);
if (result.status == WRITE_STATUS_ERROR) {
OnWriteError(result.error_code);
@@ -1108,7 +1115,6 @@ QuicConsumedData QuicConnection::SendStreamData(
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- FecProtection fec_protection,
QuicAckListenerInterface* listener) {
if (!fin && iov.total_length == 0) {
QUIC_BUG << "Attempt to send empty stream frame";
@@ -1129,16 +1135,15 @@ QuicConsumedData QuicConnection::SendStreamData(
// also if there is possibility of revival. Only bundle an ack if there's no
// processing left that may cause received_info_ to change.
ScopedRetransmissionScheduler alarm_delayer(this);
- ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK);
- return packet_generator_.ConsumeData(id, iov, offset, fin, fec_protection,
- listener);
+ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
+ return packet_generator_.ConsumeData(id, iov, offset, fin, listener);
}
void QuicConnection::SendRstStream(QuicStreamId id,
QuicRstStreamErrorCode error,
QuicStreamOffset bytes_written) {
// Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK);
+ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(QuicFrame(new QuicRstStreamFrame(
id, AdjustErrorForVersion(error, version()), bytes_written)));
@@ -1152,21 +1157,19 @@ void QuicConnection::SendRstStream(QuicStreamId 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()) {
- RetransmittableFrames* retransmittable_frames =
- packet_iterator->retransmittable_frames;
- if (!retransmittable_frames) {
+ QuicFrames* retransmittable_frames =
+ &packet_iterator->retransmittable_frames;
+ if (retransmittable_frames->empty()) {
++packet_iterator;
continue;
}
- retransmittable_frames->RemoveFramesForStream(id);
- if (!retransmittable_frames->frames().empty()) {
+ QuicUtils::RemoveFramesForStream(retransmittable_frames, id);
+ if (!retransmittable_frames->empty()) {
++packet_iterator;
continue;
}
- delete packet_iterator->retransmittable_frames;
- delete packet_iterator->packet;
- packet_iterator->retransmittable_frames = nullptr;
- packet_iterator->packet = nullptr;
+ delete[] packet_iterator->encrypted_buffer;
+ QuicUtils::ClearSerializedPacket(&(*packet_iterator));
packet_iterator = queued_packets_.erase(packet_iterator);
}
}
@@ -1174,17 +1177,24 @@ void QuicConnection::SendRstStream(QuicStreamId id,
void QuicConnection::SendWindowUpdate(QuicStreamId id,
QuicStreamOffset byte_offset) {
// Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK);
+ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(
QuicFrame(new QuicWindowUpdateFrame(id, byte_offset)));
}
void QuicConnection::SendBlocked(QuicStreamId id) {
// Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK);
+ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(QuicFrame(new QuicBlockedFrame(id)));
}
+void QuicConnection::SendPathClose(QuicPathId path_id) {
+ // Opportunistically bundle an ack with this outgoing packet.
+ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
+ packet_generator_.AddControlFrame(QuicFrame(new QuicPathCloseFrame(path_id)));
+ OnPathClosed(path_id);
+}
+
const QuicConnectionStats& QuicConnection::GetStats() {
const RttStats* rtt_stats = sent_packet_manager_.GetRttStats();
@@ -1204,14 +1214,14 @@ const QuicConnectionStats& QuicConnection::GetStats() {
stats_.srtt_us = srtt.ToMicroseconds();
stats_.estimated_bandwidth = sent_packet_manager_.BandwidthEstimate();
- stats_.max_packet_size = packet_generator_.GetMaxPacketLength();
+ 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,
- const QuicEncryptedPacket& packet) {
+ const QuicReceivedPacket& packet) {
if (!connected_) {
return;
}
@@ -1219,12 +1229,26 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
debug_visitor_->OnPacketReceived(self_address, peer_address, packet);
}
last_size_ = packet.length();
+ current_packet_data_ = packet.data();
- CheckForAddressMigration(self_address, peer_address);
+ last_packet_destination_address_ = self_address;
+ last_packet_source_address_ = peer_address;
+ if (!IsInitializedIPEndPoint(self_address_)) {
+ self_address_ = last_packet_destination_address_;
+ }
+ if (!IsInitializedIPEndPoint(peer_address_)) {
+ peer_address_ = last_packet_source_address_;
+ }
stats_.bytes_received += packet.length();
++stats_.packets_received;
+ if (FLAGS_quic_use_socket_timestamp) {
+ time_of_last_received_packet_ = packet.receipt_time();
+ DVLOG(1) << ENDPOINT << "time of last received packet: "
+ << time_of_last_received_packet_.ToDebuggingValue();
+ }
+
ScopedRetransmissionScheduler alarm_delayer(this);
if (!framer_.ProcessPacket(packet)) {
// If we are unable to decrypt this packet, it might be
@@ -1239,50 +1263,20 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
}
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_.largest_observed() >
+ highest_packet_sent_before_peer_migration_) {
+ OnPeerMigrationValidated();
+ }
MaybeProcessUndecryptablePackets();
MaybeSendInResponseToPacket();
SetPingAlarm();
-}
-
-void QuicConnection::CheckForAddressMigration(const IPEndPoint& self_address,
- const IPEndPoint& peer_address) {
- peer_ip_changed_ = false;
- peer_port_changed_ = false;
- self_ip_changed_ = false;
- self_port_changed_ = false;
-
- if (peer_address_.address().empty()) {
- peer_address_ = peer_address;
- }
- if (self_address_.address().empty()) {
- self_address_ = self_address;
- }
-
- if (!peer_address.address().empty() && !peer_address_.address().empty()) {
- peer_ip_changed_ = (peer_address.address() != peer_address_.address());
- peer_port_changed_ = (peer_address.port() != peer_address_.port());
-
- // Store in case we want to migrate connection in ProcessValidatedPacket.
- migrating_peer_ip_ = peer_address.address();
- migrating_peer_port_ = peer_address.port();
- }
-
- if (!self_address.address().empty() && !self_address_.address().empty()) {
- self_ip_changed_ = (self_address.address() != self_address_.address());
- self_port_changed_ = (self_address.port() != self_address_.port());
- }
-
- // TODO(vasilvv): reset maximum packet size on connection migration. Whenever
- // the connection is migrated, it usually ends up being on a different path,
- // with possibly smaller MTU. This means the max packet size has to be reset
- // and MTU discovery mechanism re-initialized. The main reason the code does
- // not do it now is that the retransmission code currently cannot deal with
- // the case when it needs to resend a packet created with larger MTU (see
- // b/22172803).
+ current_packet_data_ = nullptr;
}
void QuicConnection::OnCanWrite() {
@@ -1299,9 +1293,10 @@ void QuicConnection::OnCanWrite() {
return;
}
- { // Limit the scope of the bundler. ACK inclusion happens elsewhere.
- ScopedPacketBundler bundler(this, NO_ACK);
+ {
+ ScopedPacketBundler bundler(this, SEND_ACK_IF_QUEUED);
visitor_->OnCanWrite();
+ visitor_->PostProcessAfterData();
}
// After the visitor writes, it may have caused the socket to become write
@@ -1321,53 +1316,49 @@ void QuicConnection::WriteIfNotBlocked() {
}
}
+void QuicConnection::WriteAndBundleAcksIfNotBlocked() {
+ if (!writer_->IsWriteBlocked()) {
+ ScopedPacketBundler bundler(this, SEND_ACK_IF_QUEUED);
+ OnCanWrite();
+ }
+}
+
bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
- if (self_ip_changed_ || self_port_changed_) {
- SendConnectionCloseWithDetails(QUIC_ERROR_MIGRATING_ADDRESS,
- "Self address migration is not supported.");
+ if (header.fec_flag) {
+ // Drop any FEC packet.
return false;
}
- PeerAddressChangeType type = NO_CHANGE;
- if (peer_ip_changed_ || peer_port_changed_) {
- type = DeterminePeerAddressChangeType();
- if (type != NO_CHANGE && type != UNKNOWN &&
- (FLAGS_quic_disable_non_nat_address_migration &&
- type != NAT_PORT_REBINDING && type != IPV4_SUBNET_REBINDING)) {
- SendConnectionCloseWithDetails(QUIC_ERROR_MIGRATING_ADDRESS,
- "Invalid peer address migration.");
- return false;
- }
+ if (perspective_ == Perspective::IS_SERVER &&
+ IsInitializedIPEndPoint(self_address_) &&
+ IsInitializedIPEndPoint(last_packet_destination_address_) &&
+ (!(self_address_ == last_packet_destination_address_))) {
+ CloseConnection(QUIC_ERROR_MIGRATING_ADDRESS,
+ "Self address migration is not supported at the server.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
}
if (!Near(header.packet_number, last_header_.packet_number)) {
DVLOG(1) << ENDPOINT << "Packet " << header.packet_number
<< " out of bounds. Discarding";
- SendConnectionCloseWithDetails(QUIC_INVALID_PACKET_HEADER,
- "packet number out of bounds");
- return false;
- }
-
- // 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 (!FLAGS_quic_drop_non_awaited_packets &&
- !received_packet_manager_.IsAwaitingPacket(header.packet_number)) {
- DVLOG(1) << ENDPOINT << "Packet " << header.packet_number
- << " no longer being waited for. Discarding.";
- if (debug_visitor_ != nullptr) {
- debug_visitor_->OnDuplicatePacket(header.packet_number);
- }
+ CloseConnection(QUIC_INVALID_PACKET_HEADER, "packet number out of bounds.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
if (version_negotiation_state_ != NEGOTIATED_VERSION) {
if (perspective_ == Perspective::IS_SERVER) {
if (!header.public_header.version_flag) {
- DLOG(WARNING) << ENDPOINT << "Packet " << header.packet_number
- << " without version flag before version negotiated.";
// Packets should have the version flag till version negotiation is
// done.
- CloseConnection(QUIC_INVALID_VERSION, false);
+ string error_details =
+ StringPrintf("%s Packet %" PRIu64
+ " without version flag before version negotiated.",
+ ENDPOINT, header.packet_number);
+ DLOG(WARNING) << error_details;
+ CloseConnection(QUIC_INVALID_VERSION, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
} else {
DCHECK_EQ(1u, header.public_header.versions.size());
@@ -1393,32 +1384,19 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
DCHECK_EQ(NEGOTIATED_VERSION, version_negotiation_state_);
- if (peer_ip_changed_ || peer_port_changed_) {
- IPEndPoint old_peer_address = peer_address_;
- peer_address_ = IPEndPoint(
- peer_ip_changed_ ? migrating_peer_ip_ : peer_address_.address(),
- peer_port_changed_ ? migrating_peer_port_ : peer_address_.port());
-
- DVLOG(1) << ENDPOINT << "Peer's ip:port changed from "
- << old_peer_address.ToString() << " to "
- << peer_address_.ToString() << ", migrating connection.";
-
- visitor_->OnConnectionMigration();
- DCHECK_NE(type, NO_CHANGE);
- sent_packet_manager_.OnConnectionMigration(type);
+ if (!FLAGS_quic_use_socket_timestamp) {
+ time_of_last_received_packet_ = clock_->Now();
+ DVLOG(1) << ENDPOINT << "time of last received packet: "
+ << time_of_last_received_packet_.ToDebuggingValue();
}
- time_of_last_received_packet_ = clock_->Now();
- DVLOG(1) << ENDPOINT << "time of last received packet: "
- << time_of_last_received_packet_.ToDebuggingValue();
-
if (last_size_ > largest_received_packet_size_) {
largest_received_packet_size_ = last_size_;
}
if (perspective_ == Perspective::IS_SERVER &&
encryption_level_ == ENCRYPTION_NONE &&
- last_size_ > packet_generator_.GetMaxPacketLength()) {
+ last_size_ > packet_generator_.GetCurrentMaxPacketLength()) {
SetMaxPacketLength(last_size_);
}
return true;
@@ -1434,6 +1412,8 @@ void QuicConnection::WriteQueuedPackets() {
QueuedPacketList::iterator packet_iterator = queued_packets_.begin();
while (packet_iterator != queued_packets_.end() &&
WritePacket(&(*packet_iterator))) {
+ delete[] packet_iterator->encrypted_buffer;
+ QuicUtils::ClearSerializedPacket(&(*packet_iterator));
packet_iterator = queued_packets_.erase(packet_iterator);
}
}
@@ -1442,14 +1422,13 @@ void QuicConnection::WritePendingRetransmissions() {
// Keep writing as long as there's a pending retransmission which can be
// written.
while (sent_packet_manager_.HasPendingRetransmissions()) {
- const QuicSentPacketManager::PendingRetransmission pending =
+ const PendingRetransmission pending =
sent_packet_manager_.NextPendingRetransmission();
if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) {
break;
}
// Re-packetize the frames with a new packet number for retransmission.
- // Retransmitted data packets do not use FEC, even when it's enabled.
// Retransmitted packets use the same packet number length as the
// original.
// Flush the packet generator before making a new packet.
@@ -1457,23 +1436,7 @@ void QuicConnection::WritePendingRetransmissions() {
// does not require the creator to be flushed.
packet_generator_.FlushAllQueuedFrames();
char buffer[kMaxPacketSize];
- SerializedPacket serialized_packet = packet_generator_.ReserializeAllFrames(
- pending.retransmittable_frames, pending.encryption_level,
- pending.packet_number_length, buffer, kMaxPacketSize);
- if (serialized_packet.packet == nullptr) {
- // We failed to serialize the packet, so close the connection.
- // CloseConnection does not send close packet, so no infinite loop here.
- // TODO(ianswett): This is actually an internal error, not an encryption
- // failure.
- CloseConnection(QUIC_ENCRYPTION_FAILURE, false);
- return;
- }
-
- DVLOG(1) << ENDPOINT << "Retransmitting " << pending.packet_number << " as "
- << serialized_packet.packet_number;
- serialized_packet.original_packet_number = pending.packet_number;
- serialized_packet.transmission_type = pending.transmission_type;
- SendOrQueuePacket(&serialized_packet);
+ packet_generator_.ReserializeAllFrames(pending, buffer, kMaxPacketSize);
}
}
@@ -1512,17 +1475,15 @@ bool QuicConnection::CanWrite(HasRetransmittableData retransmittable) {
return false;
}
- if (FLAGS_quic_respect_send_alarm2) {
- // Allow acks to be sent immediately.
- // TODO(ianswett): Remove retransmittable from
- // SendAlgorithmInterface::TimeUntilSend.
- if (retransmittable == NO_RETRANSMITTABLE_DATA) {
- return true;
- }
- // If the send alarm is set, wait for it to fire.
- if (send_alarm_->IsSet()) {
- return false;
- }
+ // Allow acks to be sent immediately.
+ // TODO(ianswett): Remove retransmittable from
+ // SendAlgorithmInterface::TimeUntilSend.
+ if (retransmittable == NO_RETRANSMITTABLE_DATA) {
+ return true;
+ }
+ // If the send alarm is set, wait for it to fire.
+ if (send_alarm_->IsSet()) {
+ return false;
}
QuicTime now = clock_->Now();
@@ -1540,29 +1501,15 @@ bool QuicConnection::CanWrite(HasRetransmittableData retransmittable) {
<< "ms";
return false;
}
- if (!FLAGS_quic_respect_send_alarm2) {
- send_alarm_->Cancel();
- }
return true;
}
bool QuicConnection::WritePacket(SerializedPacket* packet) {
- if (!WritePacketInner(packet)) {
- return false;
- }
- delete packet->retransmittable_frames;
- delete packet->packet;
- packet->retransmittable_frames = nullptr;
- packet->packet = nullptr;
- return true;
-}
-
-bool QuicConnection::WritePacketInner(SerializedPacket* packet) {
if (packet->packet_number < sent_packet_manager_.largest_sent_packet()) {
QUIC_BUG << "Attempt to write packet:" << packet->packet_number
<< " after:" << sent_packet_manager_.largest_sent_packet();
- SendConnectionCloseWithDetails(QUIC_INTERNAL_ERROR,
- "Packet written out of order.");
+ CloseConnection(QUIC_INTERNAL_ERROR, "Packet written out of order.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return true;
}
if (ShouldDiscardPacket(*packet)) {
@@ -1579,15 +1526,17 @@ bool QuicConnection::WritePacketInner(SerializedPacket* packet) {
DCHECK_LE(packet_number_of_last_sent_packet_, packet_number);
packet_number_of_last_sent_packet_ = packet_number;
- QuicEncryptedPacket* encrypted = packet->packet;
+ QuicPacketLength encrypted_length = packet->encrypted_length;
// Termination packets are eventually owned by TimeWaitListManager.
// Others are deleted at the end of this call.
if (is_termination_packet) {
if (termination_packets_.get() == nullptr) {
termination_packets_.reset(new std::vector<QuicEncryptedPacket*>);
}
- // Clone the packet so it's owned in the future.
- termination_packets_->push_back(encrypted->Clone());
+ // Copy the buffer so it's owned in the future.
+ char* buffer_copy = QuicUtils::CopyBuffer(*packet);
+ termination_packets_->push_back(
+ new QuicEncryptedPacket(buffer_copy, encrypted_length, true));
// This assures we won't try to write *forced* packets when blocked.
// Return true to stop processing.
if (writer_->IsWriteBlocked()) {
@@ -1596,27 +1545,26 @@ bool QuicConnection::WritePacketInner(SerializedPacket* packet) {
}
}
- DCHECK_LE(encrypted->length(), kMaxPacketSize);
- DCHECK_LE(encrypted->length(), packet_generator_.GetMaxPacketLength());
+ DCHECK_LE(encrypted_length, kMaxPacketSize);
+ DCHECK_LE(encrypted_length, packet_generator_.GetCurrentMaxPacketLength());
DVLOG(1) << ENDPOINT << "Sending packet " << packet_number << " : "
- << (packet->is_fec_packet
- ? "FEC "
- : (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA
- ? "data bearing "
- : " ack only "))
+ << (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA
+ ? "data bearing "
+ : " ack only ")
<< ", encryption level: "
<< QuicUtils::EncryptionLevelToString(packet->encryption_level)
- << ", encrypted length:" << encrypted->length();
+ << ", encrypted length:" << encrypted_length;
DVLOG(2) << ENDPOINT << "packet(" << packet_number << "): " << std::endl
- << QuicUtils::StringToHexASCIIDump(encrypted->AsStringPiece());
+ << QuicUtils::StringToHexASCIIDump(
+ 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(encrypted->data(), encrypted->length(),
- self_address().address(), peer_address());
+ WriteResult result = writer_->WritePacket(
+ packet->encrypted_buffer, encrypted_length, self_address().address(),
+ peer_address(), per_packet_options_);
if (result.error_code == ERR_IO_PENDING) {
DCHECK_EQ(WRITE_STATUS_BLOCKED, result.status);
}
@@ -1634,8 +1582,7 @@ bool QuicConnection::WritePacketInner(SerializedPacket* packet) {
if (result.status != WRITE_STATUS_ERROR && debug_visitor_ != nullptr) {
// Pass the write result to the visitor.
debug_visitor_->OnPacketSent(*packet, packet->original_packet_number,
- packet->transmission_type, encrypted->length(),
- packet_send_time);
+ packet->transmission_type, packet_send_time);
}
if (packet->transmission_type == NOT_RETRANSMISSION) {
time_of_last_sent_new_packet_ = packet_send_time;
@@ -1645,7 +1592,6 @@ bool QuicConnection::WritePacketInner(SerializedPacket* packet) {
}
}
SetPingAlarm();
- MaybeSetFecAlarm(packet_number);
MaybeSetMtuAlarm();
DVLOG(1) << ENDPOINT << "time we began writing last sent packet: "
<< packet_send_time.ToDebuggingValue();
@@ -1659,8 +1605,7 @@ bool QuicConnection::WritePacketInner(SerializedPacket* packet) {
bool reset_retransmission_alarm = sent_packet_manager_.OnPacketSent(
packet, packet->original_packet_number, packet_send_time,
- encrypted->length(), packet->transmission_type,
- IsRetransmittable(*packet));
+ packet->transmission_type, IsRetransmittable(*packet));
if (reset_retransmission_alarm || !retransmission_alarm_->IsSet()) {
SetRetransmissionAlarm();
@@ -1675,7 +1620,7 @@ bool QuicConnection::WritePacketInner(SerializedPacket* packet) {
if (result.status == WRITE_STATUS_ERROR) {
OnWriteError(result.error_code);
- DLOG(ERROR) << ENDPOINT << "failed writing " << encrypted->length()
+ DLOG(ERROR) << ENDPOINT << "failed writing " << encrypted_length
<< " bytes "
<< " from host " << (self_address().address().empty()
? " empty address "
@@ -1718,40 +1663,41 @@ bool QuicConnection::ShouldDiscardPacket(const SerializedPacket& packet) {
}
void QuicConnection::OnWriteError(int error_code) {
- DVLOG(1) << ENDPOINT << "Write failed with error: " << error_code << " ("
- << ErrorToString(error_code) << ")";
+ const string error_details = "Write failed with error: " +
+ base::IntToString(error_code) + " (" +
+ ErrorToString(error_code) + ")";
+ DVLOG(1) << ENDPOINT << error_details;
// We can't send an error as the socket is presumably borked.
- CloseConnection(QUIC_PACKET_WRITE_ERROR, false);
+ TearDownLocalConnectionState(QUIC_PACKET_WRITE_ERROR, error_details,
+ ConnectionCloseSource::FROM_SELF);
}
void QuicConnection::OnSerializedPacket(SerializedPacket* serialized_packet) {
DCHECK_NE(kInvalidPathId, serialized_packet->path_id);
- if (serialized_packet->packet == nullptr) {
+ if (serialized_packet->encrypted_buffer == nullptr) {
// We failed to serialize the packet, so close the connection.
- // CloseConnection does not send close packet, so no infinite loop here.
- // TODO(ianswett): This is actually an internal error, not an encryption
- // failure.
- CloseConnection(QUIC_ENCRYPTION_FAILURE, false);
+ // TearDownLocalConnectionState does not send close packet, so no infinite
+ // loop here.
+ // TODO(ianswett): This is actually an internal error, not an
+ // encryption failure.
+ TearDownLocalConnectionState(
+ QUIC_ENCRYPTION_FAILURE,
+ "Serialized packet does not have an encrypted buffer.",
+ ConnectionCloseSource::FROM_SELF);
return;
}
- if (serialized_packet->is_fec_packet && fec_alarm_->IsSet()) {
- // If an FEC packet is serialized with the FEC alarm set, cancel the alarm.
- fec_alarm_->Cancel();
- }
SendOrQueuePacket(serialized_packet);
}
-void QuicConnection::OnResetFecGroup() {
- if (!fec_alarm_->IsSet()) {
- return;
- }
- // If an FEC Group is closed with the FEC alarm set, cancel the alarm.
- fec_alarm_->Cancel();
+void QuicConnection::OnUnrecoverableError(QuicErrorCode error,
+ const string& error_details,
+ ConnectionCloseSource source) {
+ // The packet creator or generator encountered an unrecoverable error: tear
+ // down local connection state immediately.
+ TearDownLocalConnectionState(error, error_details, source);
}
void QuicConnection::OnCongestionWindowChange() {
- packet_generator_.OnCongestionWindowChange(
- sent_packet_manager_.EstimateMaxPacketsInFlight(max_packet_length()));
visitor_->OnCongestionWindowChange(clock_->ApproximateNow());
}
@@ -1762,9 +1708,13 @@ void QuicConnection::OnRttChange() {
rtt = QuicTime::Delta::FromMicroseconds(
sent_packet_manager_.GetRttStats()->initial_rtt_us());
}
+
if (debug_visitor_)
debug_visitor_->OnRttChanged(rtt);
- packet_generator_.OnRttChange(rtt);
+}
+
+void QuicConnection::OnPathDegrading() {
+ visitor_->OnPathDegrading();
}
void QuicConnection::OnHandshakeComplete() {
@@ -1780,8 +1730,8 @@ void QuicConnection::OnHandshakeComplete() {
void QuicConnection::SendOrQueuePacket(SerializedPacket* packet) {
// The caller of this function is responsible for checking CanWrite().
- if (packet->packet == nullptr) {
- QUIC_BUG << "packet.packet == nullptr in to SendOrQueuePacket";
+ if (packet->encrypted_buffer == nullptr) {
+ QUIC_BUG << "packet.encrypted_buffer == nullptr in to SendOrQueuePacket";
return;
}
@@ -1791,13 +1741,12 @@ void QuicConnection::SendOrQueuePacket(SerializedPacket* packet) {
// it's written in sequence number order.
if (!queued_packets_.empty() || !WritePacket(packet)) {
// Take ownership of the underlying encrypted packet.
- if (!packet->packet->owns_buffer()) {
- scoped_ptr<QuicEncryptedPacket> encrypted_deleter(packet->packet);
- packet->packet = packet->packet->Clone();
- }
+ packet->encrypted_buffer = QuicUtils::CopyBuffer(*packet);
queued_packets_.push_back(*packet);
+ packet->retransmittable_frames.clear();
}
+ QuicUtils::ClearSerializedPacket(packet);
// If a forward-secure encrypter is available but is not being used and the
// next packet number is the first packet which requires
// forward security, start using the forward-secure encrypter.
@@ -1808,10 +1757,6 @@ void QuicConnection::SendOrQueuePacket(SerializedPacket* packet) {
}
}
-PeerAddressChangeType QuicConnection::DeterminePeerAddressChangeType() {
- return UNKNOWN;
-}
-
void QuicConnection::OnPingTimeout() {
if (!retransmission_alarm_->IsSet()) {
SendPing();
@@ -1819,7 +1764,10 @@ void QuicConnection::OnPingTimeout() {
}
void QuicConnection::SendPing() {
+ ScopedPacketBundler bundler(this, SEND_ACK_IF_QUEUED);
packet_generator_.AddControlFrame(QuicFrame(QuicPingFrame()));
+ // Send PING frame immediately, without checking for congestion window bounds.
+ packet_generator_.FlushAllQueuedFrames();
}
void QuicConnection::SendAck() {
@@ -1827,6 +1775,7 @@ void QuicConnection::SendAck() {
ack_queued_ = false;
stop_waiting_count_ = 0;
num_retransmittable_packets_received_since_last_ack_sent_ = 0;
+ last_ack_had_missing_packets_ = received_packet_manager_.HasMissingPackets();
num_packets_received_since_last_ack_sent_ = 0;
packet_generator_.SetShouldSendAck(true);
@@ -1837,6 +1786,14 @@ void QuicConnection::OnRetransmissionTimeout() {
return;
}
+ if (close_connection_after_five_rtos_ &&
+ sent_packet_manager_.consecutive_rto_count() >= 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();
WriteIfNotBlocked();
@@ -1943,88 +1900,32 @@ void QuicConnection::MaybeProcessUndecryptablePackets() {
}
}
-void QuicConnection::MaybeProcessRevivedPacket() {
- QuicFecGroup* group = GetFecGroup();
- if (!connected_ || group == nullptr || !group->CanRevive()) {
+void QuicConnection::CloseConnection(
+ QuicErrorCode error,
+ const string& error_details,
+ ConnectionCloseBehavior connection_close_behavior) {
+ DCHECK(!error_details.empty());
+ if (!connected_) {
+ DVLOG(1) << "Connection is already closed.";
return;
}
- QuicPacketHeader revived_header;
- char revived_payload[kMaxPacketSize];
- size_t len = group->Revive(&revived_header, revived_payload, kMaxPacketSize);
- revived_header.public_header.connection_id = connection_id_;
- revived_header.public_header.connection_id_length =
- last_header_.public_header.connection_id_length;
- revived_header.public_header.version_flag = false;
- revived_header.public_header.reset_flag = false;
- revived_header.public_header.packet_number_length =
- last_header_.public_header.packet_number_length;
- revived_header.fec_flag = false;
- revived_header.is_in_fec_group = NOT_IN_FEC_GROUP;
- revived_header.fec_group = 0;
- group_map_.erase(last_header_.fec_group);
- last_decrypted_packet_level_ = group->EffectiveEncryptionLevel();
- DCHECK_LT(last_decrypted_packet_level_, NUM_ENCRYPTION_LEVELS);
- delete group;
-
- last_packet_revived_ = true;
- if (debug_visitor_ != nullptr) {
- debug_visitor_->OnRevivedPacket(revived_header,
- StringPiece(revived_payload, len));
- }
-
- ++stats_.packets_revived;
- framer_.ProcessRevivedPacket(&revived_header,
- StringPiece(revived_payload, len));
-}
-
-QuicFecGroup* QuicConnection::GetFecGroup() {
- QuicFecGroupNumber fec_group_num = last_header_.fec_group;
- if (fec_group_num == 0 ||
- (FLAGS_quic_drop_non_awaited_packets &&
- fec_group_num <
- received_packet_manager_.peer_least_packet_awaiting_ack() &&
- !ContainsKey(group_map_, fec_group_num))) {
- // If the group number is below peer_least_packet_awaiting_ack and this
- // group does not exist, which means this group has missing packets below
- // |peer_least_packet_awaiting_ack| which we would never receive, so return
- // nullptr.
- return nullptr;
- }
- if (!ContainsKey(group_map_, fec_group_num)) {
- if (group_map_.size() >= kMaxFecGroups) { // Too many groups
- if (fec_group_num < group_map_.begin()->first) {
- // The group being requested is a group we've seen before and deleted.
- // Don't recreate it.
- return nullptr;
- }
- // Clear the lowest group number.
- delete group_map_.begin()->second;
- group_map_.erase(group_map_.begin());
- }
- group_map_[fec_group_num] = new QuicFecGroup(fec_group_num);
+
+ DVLOG(1) << ENDPOINT << "Closing connection: " << connection_id()
+ << ", with error: " << QuicUtils::ErrorToString(error) << " ("
+ << error << "), and details: " << error_details;
+
+ if (connection_close_behavior ==
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET) {
+ SendConnectionClosePacket(error, error_details);
}
- return group_map_[fec_group_num];
-}
-void QuicConnection::SendConnectionCloseWithDetails(QuicErrorCode error,
- const string& details) {
- // If we're write blocked, WritePacket() will not send, but will capture the
- // serialized packet.
- SendConnectionClosePacket(error, details);
- CloseConnection(error, false);
+ TearDownLocalConnectionState(error, error_details,
+ ConnectionCloseSource::FROM_SELF);
}
void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
const string& details) {
- DVLOG(1) << ENDPOINT << "Force closing " << connection_id() << " with error "
- << QuicUtils::ErrorToString(error) << " (" << error << ") "
- << details;
- // Don't send explicit connection close packets for timeouts.
- // This is particularly important on mobile, where connections are short.
- if (silent_close_enabled_ &&
- error == QuicErrorCode::QUIC_CONNECTION_TIMED_OUT) {
- return;
- }
+ DVLOG(1) << ENDPOINT << "Sending connection close packet.";
ClearQueuedPackets();
ScopedPacketBundler ack_bundler(this, SEND_ACK);
QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame();
@@ -2034,7 +1935,10 @@ void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
packet_generator_.FlushAllQueuedFrames();
}
-void QuicConnection::CloseConnection(QuicErrorCode error, bool from_peer) {
+void QuicConnection::TearDownLocalConnectionState(
+ QuicErrorCode error,
+ const string& error_details,
+ ConnectionCloseSource source) {
if (!connected_) {
DVLOG(1) << "Connection is already closed.";
return;
@@ -2044,19 +1948,18 @@ void QuicConnection::CloseConnection(QuicErrorCode error, bool from_peer) {
// TODO(rtenneti): crbug.com/546668. A temporary fix. Added a check for null
// |visitor_| to fix crash bug. Delete |visitor_| check and histogram after
// fix is merged.
- if (visitor_) {
- visitor_->OnConnectionClosed(error, from_peer);
+ if (visitor_ != nullptr) {
+ visitor_->OnConnectionClosed(error, error_details, source);
} else {
UMA_HISTOGRAM_BOOLEAN("Net.QuicCloseConnection.NullVisitor", true);
}
if (debug_visitor_ != nullptr) {
- debug_visitor_->OnConnectionClosed(error, from_peer);
+ debug_visitor_->OnConnectionClosed(error, error_details, source);
}
// Cancel the alarms so they don't trigger any action now that the
// connection is closed.
ack_alarm_->Cancel();
ping_alarm_->Cancel();
- fec_alarm_->Cancel();
resume_writes_alarm_->Cancel();
retransmission_alarm_->Cancel();
send_alarm_->Cancel();
@@ -2076,38 +1979,17 @@ void QuicConnection::SendGoAway(QuicErrorCode error,
<< QuicUtils::ErrorToString(error) << " (" << error << ")";
// Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK);
+ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(
QuicFrame(new QuicGoAwayFrame(error, last_good_stream_id, reason)));
}
-void QuicConnection::CloseFecGroupsBefore(QuicPacketNumber packet_number) {
- FecGroupMap::iterator it = group_map_.begin();
- while (it != group_map_.end()) {
- // If the group doesn't protect this packet we can ignore it.
- if ((!FLAGS_quic_drop_non_awaited_packets &&
- last_header_.fec_group == it->first) ||
- !it->second->IsWaitingForPacketBefore(packet_number)) {
- ++it;
- continue;
- }
- QuicFecGroup* fec_group = it->second;
- DCHECK(!fec_group->CanRevive());
- FecGroupMap::iterator next = it;
- ++next;
- group_map_.erase(it);
- delete fec_group;
- it = next;
- }
-}
-
QuicByteCount QuicConnection::max_packet_length() const {
- return packet_generator_.GetMaxPacketLength();
+ return packet_generator_.GetCurrentMaxPacketLength();
}
void QuicConnection::SetMaxPacketLength(QuicByteCount length) {
- return packet_generator_.SetMaxPacketLength(LimitMaxPacketSize(length),
- /*force=*/false);
+ return packet_generator_.SetMaxPacketLength(LimitMaxPacketSize(length));
}
bool QuicConnection::HasQueuedData() const {
@@ -2135,11 +2017,11 @@ bool QuicConnection::CanWriteStreamData() {
return ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA, pending_handshake);
}
-void QuicConnection::SetNetworkTimeouts(QuicTime::Delta overall_timeout,
+void QuicConnection::SetNetworkTimeouts(QuicTime::Delta handshake_timeout,
QuicTime::Delta idle_timeout) {
- LOG_IF(DFATAL, idle_timeout > overall_timeout)
+ QUIC_BUG_IF(idle_timeout > handshake_timeout)
<< "idle_timeout:" << idle_timeout.ToMilliseconds()
- << " overall_timeout:" << overall_timeout.ToMilliseconds();
+ << " handshake_timeout:" << handshake_timeout.ToMilliseconds();
// Adjust the idle timeout on client and server to prevent clients from
// sending requests to servers which have already closed the connection.
if (perspective_ == Perspective::IS_SERVER) {
@@ -2147,7 +2029,7 @@ void QuicConnection::SetNetworkTimeouts(QuicTime::Delta overall_timeout,
} else if (idle_timeout > QuicTime::Delta::FromSeconds(1)) {
idle_timeout = idle_timeout.Subtract(QuicTime::Delta::FromSeconds(1));
}
- overall_connection_timeout_ = overall_timeout;
+ handshake_timeout_ = handshake_timeout;
idle_network_timeout_ = idle_timeout;
SetTimeoutAlarm();
@@ -2155,14 +2037,8 @@ void QuicConnection::SetNetworkTimeouts(QuicTime::Delta overall_timeout,
void QuicConnection::CheckForTimeout() {
QuicTime now = clock_->ApproximateNow();
- QuicTime time_of_last_packet = QuicTime::Zero();
- if (!FLAGS_quic_use_new_idle_timeout) {
- time_of_last_packet =
- max(time_of_last_received_packet_, time_of_last_sent_new_packet_);
- } else {
- time_of_last_packet =
- max(time_of_last_received_packet_, last_send_for_timeout_);
- }
+ QuicTime time_of_last_packet =
+ 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
@@ -2175,24 +2051,24 @@ void QuicConnection::CheckForTimeout() {
<< " idle_network_timeout: "
<< idle_network_timeout_.ToMicroseconds();
if (idle_duration >= idle_network_timeout_) {
- DVLOG(1) << ENDPOINT << "Connection timedout due to no network activity.";
- SendConnectionCloseWithDetails(QUIC_CONNECTION_TIMED_OUT,
- "No recent network activity");
+ const string error_details = "No recent network activity.";
+ DVLOG(1) << ENDPOINT << error_details;
+ CloseConnection(QUIC_NETWORK_IDLE_TIMEOUT, error_details,
+ idle_timeout_connection_close_behavior_);
return;
}
- if (!overall_connection_timeout_.IsInfinite()) {
+ if (!handshake_timeout_.IsInfinite()) {
QuicTime::Delta connected_duration =
now.Subtract(stats_.connection_creation_time);
DVLOG(1) << ENDPOINT
<< "connection time: " << connected_duration.ToMicroseconds()
- << " overall timeout: "
- << overall_connection_timeout_.ToMicroseconds();
- if (connected_duration >= overall_connection_timeout_) {
- DVLOG(1) << ENDPOINT
- << "Connection timedout due to overall connection timeout.";
- SendConnectionCloseWithDetails(QUIC_CONNECTION_OVERALL_TIMED_OUT,
- "Overall timeout expired");
+ << " handshake timeout: " << handshake_timeout_.ToMicroseconds();
+ if (connected_duration >= handshake_timeout_) {
+ const string error_details = "Handshake timeout expired.";
+ DVLOG(1) << ENDPOINT << error_details;
+ CloseConnection(QUIC_HANDSHAKE_TIMEOUT, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
}
@@ -2205,10 +2081,9 @@ void QuicConnection::SetTimeoutAlarm() {
max(time_of_last_received_packet_, time_of_last_sent_new_packet_);
QuicTime deadline = time_of_last_packet.Add(idle_network_timeout_);
- if (!overall_connection_timeout_.IsInfinite()) {
+ if (!handshake_timeout_.IsInfinite()) {
deadline =
- min(deadline,
- stats_.connection_creation_time.Add(overall_connection_timeout_));
+ min(deadline, stats_.connection_creation_time.Add(handshake_timeout_));
}
timeout_alarm_->Cancel();
@@ -2265,7 +2140,7 @@ void QuicConnection::MaybeSetMtuAlarm() {
QuicConnection::ScopedPacketBundler::ScopedPacketBundler(
QuicConnection* connection,
- AckBundling send_ack)
+ AckBundling ack_mode)
: connection_(connection),
already_in_batch_mode_(connection != nullptr &&
connection->packet_generator_.InBatchMode()) {
@@ -2278,18 +2153,30 @@ QuicConnection::ScopedPacketBundler::ScopedPacketBundler(
DVLOG(1) << "Entering Batch Mode.";
connection_->packet_generator_.StartBatchOperations();
}
- // Bundle an ack if the alarm is set or with every second packet if we need to
- // raise the peer's least unacked.
- bool ack_pending =
- connection_->ack_alarm_->IsSet() || connection_->stop_waiting_count_ > 1;
- if (send_ack == SEND_ACK || (send_ack == BUNDLE_PENDING_ACK && ack_pending)) {
+ if (ShouldSendAck(ack_mode)) {
DVLOG(1) << "Bundling ack with outgoing packet.";
- DCHECK(send_ack == SEND_ACK || connection_->ack_frame_updated() ||
+ DCHECK(ack_mode == SEND_ACK || connection_->ack_frame_updated() ||
connection_->stop_waiting_count_ > 1);
connection_->SendAck();
}
}
+bool QuicConnection::ScopedPacketBundler::ShouldSendAck(
+ AckBundling ack_mode) const {
+ switch (ack_mode) {
+ case SEND_ACK:
+ return true;
+ case SEND_ACK_IF_QUEUED:
+ return connection_->ack_queued();
+ case SEND_ACK_IF_PENDING:
+ return connection_->ack_alarm_->IsSet() ||
+ connection_->stop_waiting_count_ > 1;
+ default:
+ QUIC_BUG << "Unsupported ack_mode.";
+ return true;
+ }
+}
+
QuicConnection::ScopedPacketBundler::~ScopedPacketBundler() {
if (connection_ == nullptr) {
return;
@@ -2327,7 +2214,7 @@ HasRetransmittableData QuicConnection::IsRetransmittable(
// Retransmitted packets retransmittable frames are owned by the unacked
// packet map, but are not present in the serialized packet.
if (packet.transmission_type != NOT_RETRANSMISSION ||
- packet.retransmittable_frames != nullptr) {
+ !packet.retransmittable_frames.empty()) {
return HAS_RETRANSMITTABLE_DATA;
} else {
return NO_RETRANSMITTABLE_DATA;
@@ -2335,10 +2222,10 @@ HasRetransmittableData QuicConnection::IsRetransmittable(
}
bool QuicConnection::IsTerminationPacket(const SerializedPacket& packet) {
- if (packet.retransmittable_frames == nullptr) {
+ if (packet.retransmittable_frames.empty()) {
return false;
}
- for (const QuicFrame& frame : packet.retransmittable_frames->frames()) {
+ for (const QuicFrame& frame : packet.retransmittable_frames) {
if (frame.type == CONNECTION_CLOSE_FRAME) {
return true;
}
@@ -2358,7 +2245,7 @@ void QuicConnection::SetMtuDiscoveryTarget(QuicByteCount target) {
QuicByteCount QuicConnection::LimitMaxPacketSize(
QuicByteCount suggested_max_packet_size) {
if (peer_address_.address().empty()) {
- LOG(DFATAL) << "Attempted to use a connection without a valid peer address";
+ QUIC_BUG << "Attempted to use a connection without a valid peer address";
return suggested_max_packet_size;
}
@@ -2413,8 +2300,59 @@ void QuicConnection::DiscoverMtu() {
DCHECK(!mtu_discovery_alarm_->IsSet());
}
+void QuicConnection::OnPeerMigrationValidated() {
+ if (active_peer_migration_type_ == NO_CHANGE) {
+ QUIC_BUG << "No migration underway.";
+ return;
+ }
+ highest_packet_sent_before_peer_migration_ = 0;
+ active_peer_migration_type_ = NO_CHANGE;
+}
+
+// TODO(jri): Modify method to start migration whenever a new IP address is seen
+// from a packet with sequence number > the one that triggered the previous
+// 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(
+ PeerAddressChangeType peer_migration_type) {
+ // TODO(fayang): Currently, all peer address change type are allowed. Need to
+ // add a method ShouldAllowPeerAddressChange(PeerAddressChangeType type) to
+ // determine whether |type| is allowed.
+ if (active_peer_migration_type_ != NO_CHANGE ||
+ peer_migration_type == NO_CHANGE) {
+ 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.";
+
+ highest_packet_sent_before_peer_migration_ =
+ packet_number_of_last_sent_packet_;
+ peer_address_ = last_packet_source_address_;
+ active_peer_migration_type_ = peer_migration_type;
+
+ // TODO(jri): Move these calls to OnPeerMigrationValidated. Rename
+ // OnConnectionMigration methods to OnPeerMigration.
+ visitor_->OnConnectionMigration(peer_migration_type);
+ sent_packet_manager_.OnConnectionMigration(peer_migration_type);
+}
+
+void QuicConnection::OnPathClosed(QuicPathId path_id) {
+ // Stop receiving packets on this path.
+ framer_.OnPathClosed(path_id);
+}
+
bool QuicConnection::ack_frame_updated() const {
return received_packet_manager_.ack_frame_updated();
}
+StringPiece QuicConnection::GetCurrentPacket() {
+ if (current_packet_data_ == nullptr) {
+ return StringPiece();
+ }
+ return StringPiece(current_packet_data_, last_size_);
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_connection.h b/chromium/net/quic/quic_connection.h
index 8a69f77c947..5baff2ead02 100644
--- a/chromium/net/quic/quic_connection.h
+++ b/chromium/net/quic/quic_connection.h
@@ -30,12 +30,14 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/quic_alarm.h"
#include "net/quic/quic_blocked_writer_interface.h"
#include "net/quic/quic_fec_group.h"
#include "net/quic/quic_framer.h"
+#include "net/quic/quic_one_block_arena.h"
#include "net/quic/quic_packet_creator.h"
#include "net/quic/quic_packet_generator.h"
#include "net/quic/quic_packet_writer.h"
@@ -52,7 +54,6 @@ class QuicClock;
class QuicConfig;
class QuicConnection;
class QuicEncrypter;
-class QuicFecGroup;
class QuicRandom;
namespace test {
@@ -114,7 +115,9 @@ class NET_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// Called when the connection is closed either locally by the framer, or
// remotely by the peer.
- virtual void OnConnectionClosed(QuicErrorCode error, bool from_peer) = 0;
+ virtual void OnConnectionClosed(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) = 0;
// Called when the connection failed to write because the socket was blocked.
virtual void OnWriteBlocked() = 0;
@@ -129,7 +132,15 @@ class NET_EXPORT_PRIVATE QuicConnectionVisitorInterface {
virtual void OnCongestionWindowChange(QuicTime now) = 0;
// Called when the connection receives a packet from a migrated client.
- virtual void OnConnectionMigration() = 0;
+ virtual void OnConnectionMigration(PeerAddressChangeType type) = 0;
+
+ // Called when the peer seems unreachable over the current path.
+ virtual void OnPathDegrading() = 0;
+
+ // Called after OnStreamFrame, OnRstStream, OnGoAway, OnWindowUpdateFrame,
+ // OnBlockedFrame, and OnCanWrite to allow post-processing once the work has
+ // been done.
+ virtual void PostProcessAfterData() = 0;
// Called to ask if the visitor wants to schedule write resumption as it both
// has pending data to write, and is able to write (e.g. based on flow control
@@ -150,8 +161,7 @@ class NET_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// points. Implementations must not mutate the state of the connection
// as a result of these callbacks.
class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor
- : public QuicPacketCreator::DebugDelegate,
- public QuicSentPacketManager::DebugDelegate {
+ : public QuicSentPacketManager::DebugDelegate {
public:
~QuicConnectionDebugVisitor() override {}
@@ -159,7 +169,6 @@ class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor
virtual void OnPacketSent(const SerializedPacket& serialized_packet,
QuicPacketNumber original_packet_number,
TransmissionType transmission_type,
- size_t encrypted_length,
QuicTime sent_time) {}
// Called when a packet has been received, but before it is
@@ -215,6 +224,9 @@ class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor
// Called when a BlockedFrame has been parsed.
virtual void OnBlockedFrame(const QuicBlockedFrame& frame) {}
+ // Called when a PathCloseFrame has been parsed.
+ virtual void OnPathCloseFrame(const QuicPathCloseFrame& frame) {}
+
// Called when a public reset packet has been received.
virtual void OnPublicResetPacket(const QuicPublicResetPacket& packet) {}
@@ -222,13 +234,10 @@ class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor
virtual void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) {}
- // Called after a packet has been successfully parsed which results
- // in the revival of a packet via FEC.
- virtual void OnRevivedPacket(const QuicPacketHeader& revived_header,
- base::StringPiece payload) {}
-
// Called when the connection is closed.
- virtual void OnConnectionClosed(QuicErrorCode error, bool from_peer) {}
+ virtual void OnConnectionClosed(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) {}
// Called when the version negotiation is successful.
virtual void OnSuccessfulVersionNegotiation(const QuicVersion& version) {}
@@ -237,8 +246,8 @@ class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor
virtual void OnSendConnectionState(
const CachedNetworkParameters& cached_network_params) {}
- // Called when resuming previous connection state.
- virtual void OnResumeConnectionState(
+ // Called when a CachedNetworkParameters are recieved from the client.
+ virtual void OnReceiveConnectionState(
const CachedNetworkParameters& cached_network_params) {}
// Called when the connection parameters are set from the supplied
@@ -250,6 +259,10 @@ class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor
virtual void OnRttChanged(QuicTime::Delta rtt) const {}
};
+// QuicConnections currently use around 1KB of polymorphic types which would
+// ordinarily be on the heap. Instead, store them inline in an arena.
+using QuicConnectionArena = QuicOneBlockArena<1024>;
+
class NET_EXPORT_PRIVATE QuicConnectionHelperInterface {
public:
virtual ~QuicConnectionHelperInterface() {}
@@ -260,11 +273,20 @@ class NET_EXPORT_PRIVATE QuicConnectionHelperInterface {
// Returns a QuicRandom to be used for all random number related functions.
virtual QuicRandom* GetRandomGenerator() = 0;
- // Creates a new platform-specific alarm which will be configured to
- // notify |delegate| when the alarm fires. Caller takes ownership
- // of the new alarm, which will not yet be "set" to fire.
+ // Creates a new platform-specific alarm which will be configured to notify
+ // |delegate| when the alarm fires. Returns an alarm allocated on the heap.
+ // Caller takes ownership of the new alarm, which will not yet be "set" to
+ // fire.
virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) = 0;
+ // Creates a new platform-specific alarm which will be configured to notify
+ // |delegate| when the alarm fires. Caller takes ownership of the new alarm,
+ // which will not yet be "set" to fire. If |arena| is null, then the alarm
+ // will be created on the heap. Otherwise, it will be created in |arena|.
+ virtual QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
+ QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+ QuicConnectionArena* arena) = 0;
+
// Returns a QuicBufferAllocator to be used for all stream frame buffers.
virtual QuicBufferAllocator* GetBufferAllocator() = 0;
};
@@ -276,11 +298,16 @@ class NET_EXPORT_PRIVATE QuicConnection
public QuicSentPacketManager::NetworkChangeVisitor {
public:
enum AckBundling {
- NO_ACK = 0,
- SEND_ACK = 1,
- BUNDLE_PENDING_ACK = 2,
+ // Send an ack if it's already queued in the connection.
+ SEND_ACK_IF_QUEUED,
+ // Always send an ack.
+ SEND_ACK,
+ // Bundle an ack with outgoing data.
+ SEND_ACK_IF_PENDING,
};
+ enum AckMode { TCP_ACKING, ACK_DECIMATION, ACK_DECIMATION_WITH_REORDERING };
+
// Constructs a new QuicConnection for |connection_id| and |address| using
// |writer| to write packets. |owns_writer| specifies whether the connection
// takes ownership of |writer|. |helper| must outlive this connection.
@@ -300,6 +327,10 @@ class NET_EXPORT_PRIVATE QuicConnection
virtual void OnSendConnectionState(
const CachedNetworkParameters& cached_network_params);
+ // Called by the session when receiving connection state from the client.
+ virtual void OnReceiveConnectionState(
+ const CachedNetworkParameters& cached_network_params);
+
// Called by the Session when the client has provided CachedNetworkParameters.
virtual void ResumeConnectionState(
const CachedNetworkParameters& cached_network_params,
@@ -312,10 +343,7 @@ class NET_EXPORT_PRIVATE QuicConnection
// Returns a pair with the number of bytes consumed from data, and a boolean
// indicating if the fin bit was consumed. This does not indicate the data
// has been sent on the wire: it may have been turned into a packet and queued
- // if the socket was unexpectedly blocked. |fec_protection| indicates if
- // data is to be FEC protected. Note that data that is sent immediately
- // following MUST_FEC_PROTECT data may get protected by falling within the
- // same FEC group.
+ // if the socket was unexpectedly blocked.
// 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.
@@ -323,7 +351,6 @@ class NET_EXPORT_PRIVATE QuicConnection
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- FecProtection fec_protection,
QuicAckListenerInterface* listener);
// Send a RST_STREAM frame to the peer.
@@ -337,18 +364,16 @@ class NET_EXPORT_PRIVATE QuicConnection
// Send a WINDOW_UPDATE frame to the peer.
virtual void SendWindowUpdate(QuicStreamId id, QuicStreamOffset byte_offset);
- // Sends the connection close packet without affecting the state of the
- // connection. This should only be called if the session is actively being
- // destroyed: otherwise call SendConnectionCloseWithDetails instead.
- virtual void SendConnectionClosePacket(QuicErrorCode error,
- const std::string& details);
+ // Send a PATH_CLOSE frame to the peer.
+ virtual void SendPathClose(QuicPathId path_id);
- // Sends a connection close frame to the peer, and closes the connection by
- // calling CloseConnection(notifying the visitor as it does so).
- virtual void SendConnectionCloseWithDetails(QuicErrorCode error,
- const std::string& details);
- // Notifies the visitor of the close and marks the connection as disconnected.
- void CloseConnection(QuicErrorCode error, bool from_peer) override;
+ // Closes the connection.
+ // |connection_close_behavior| determines whether or not a connection close
+ // packet is sent to the peer.
+ virtual void CloseConnection(
+ QuicErrorCode error,
+ const std::string& details,
+ ConnectionCloseBehavior connection_close_behavior);
// Sends a GOAWAY frame. Does nothing if a GOAWAY frame has already been sent.
virtual void SendGoAway(QuicErrorCode error,
@@ -359,13 +384,12 @@ class NET_EXPORT_PRIVATE QuicConnection
const QuicConnectionStats& GetStats();
// Processes an incoming UDP packet (consisting of a QuicEncryptedPacket) from
- // the peer. If processing this packet permits a packet to be revived from
- // its FEC group that packet will be revived and processed.
+ // 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,
- const QuicEncryptedPacket& packet);
+ const QuicReceivedPacket& packet);
// QuicBlockedWriterInterface
// Called when the underlying connection becomes writable to allow queued
@@ -379,6 +403,10 @@ class NET_EXPORT_PRIVATE QuicConnection
// If the socket is not blocked, writes queued packets.
void WriteIfNotBlocked();
+ // If the socket is not blocked, writes queued packets and bundles any pending
+ // ACKs.
+ void WriteAndBundleAcksIfNotBlocked();
+
// Set the packet writer.
void SetQuicPacketWriter(QuicPacketWriter* writer, bool owns_writer) {
DCHECK(writer != nullptr);
@@ -407,13 +435,11 @@ class NET_EXPORT_PRIVATE QuicConnection
void OnPublicResetPacket(const QuicPublicResetPacket& packet) override;
void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) override;
- void OnRevivedPacket() override;
bool OnUnauthenticatedPublicHeader(
const QuicPacketPublicHeader& header) override;
bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
void OnDecryptedPacket(EncryptionLevel level) override;
bool OnPacketHeader(const QuicPacketHeader& header) override;
- void OnFecProtectedPayload(base::StringPiece payload) override;
bool OnStreamFrame(const QuicStreamFrame& frame) override;
bool OnAckFrame(const QuicAckFrame& frame) override;
bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override;
@@ -423,22 +449,25 @@ class NET_EXPORT_PRIVATE QuicConnection
bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
- void OnFecData(base::StringPiece redundnancy) override;
+ bool OnPathCloseFrame(const QuicPathCloseFrame& frame) override;
void OnPacketComplete() override;
// QuicPacketGenerator::DelegateInterface
bool ShouldGeneratePacket(HasRetransmittableData retransmittable,
IsHandshake handshake) override;
- void PopulateAckFrame(QuicAckFrame* ack) override;
+ const QuicFrame GetUpdatedAckFrame() override;
void PopulateStopWaitingFrame(QuicStopWaitingFrame* stop_waiting) override;
// QuicPacketCreator::DelegateInterface
void OnSerializedPacket(SerializedPacket* packet) override;
- void OnResetFecGroup() override;
+ void OnUnrecoverableError(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) override;
// QuicSentPacketManager::NetworkChangeVisitor
void OnCongestionWindowChange() override;
void OnRttChange() override;
+ void OnPathDegrading() override;
// Called by the crypto stream when the handshake completes. In the server's
// case this is when the SHLO has been ACKed. Clients call this on receipt of
@@ -451,9 +480,12 @@ class NET_EXPORT_PRIVATE QuicConnection
}
void set_debug_visitor(QuicConnectionDebugVisitor* debug_visitor) {
debug_visitor_ = debug_visitor;
- packet_generator_.set_debug_delegate(debug_visitor);
sent_packet_manager_.set_debug_delegate(debug_visitor);
}
+ // Used in Chromium, but not internally.
+ 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_; }
QuicConnectionId connection_id() const { return connection_id_; }
@@ -476,8 +508,6 @@ class NET_EXPORT_PRIVATE QuicConnection
return server_supported_versions_;
}
- size_t NumFecGroups() const { return group_map_.size(); }
-
// Testing only.
size_t NumQueuedPackets() const { return queued_packets_.size(); }
@@ -493,8 +523,8 @@ class NET_EXPORT_PRIVATE QuicConnection
// Returns true if the connection has queued packets or frames.
bool HasQueuedData() const;
- // Sets the overall and idle state connection timeouts.
- void SetNetworkTimeouts(QuicTime::Delta overall_timeout,
+ // Sets the handshake and idle state connection timeouts.
+ void SetNetworkTimeouts(QuicTime::Delta handshake_timeout,
QuicTime::Delta idle_timeout);
// If the connection has timed out, this will close the connection.
@@ -515,10 +545,6 @@ class NET_EXPORT_PRIVATE QuicConnection
// remaining unacked packets.
void OnRetransmissionTimeout();
- // Called when a data packet is sent. Starts an alarm if the data sent in
- // |packet_number| was FEC protected.
- void MaybeSetFecAlarm(QuicPacketNumber packet_number);
-
// Retransmits all unacked packets with retransmittable frames if
// |retransmission_type| is ALL_UNACKED_PACKETS, otherwise retransmits only
// initially encrypted packets. Used when the negotiated protocol version is
@@ -588,6 +614,8 @@ class NET_EXPORT_PRIVATE QuicConnection
~ScopedPacketBundler();
private:
+ bool ShouldSendAck(AckBundling ack_mode) const;
+
QuicConnection* connection_;
bool already_in_batch_mode_;
};
@@ -632,43 +660,76 @@ class NET_EXPORT_PRIVATE QuicConnection
return termination_packets_.get();
}
+ bool ack_queued() const { return ack_queued_; }
+
bool ack_frame_updated() const;
- protected:
- // Do any work which logically would be done in OnPacket but can not be
- // safely done until the packet is validated. Returns true if the packet
- // can be handled, false otherwise. Also migrates the connection if the packet
- // can be handled and peer address changes.
- virtual bool ProcessValidatedPacket(const QuicPacketHeader& header);
+ QuicConnectionHelperInterface* helper() { return helper_; }
+
+ base::StringPiece GetCurrentPacket();
+
+ const QuicPacketGenerator& packet_generator() const {
+ return packet_generator_;
+ }
+
+ EncryptionLevel encryption_level() const { return encryption_level_; }
+ protected:
// Send a packet to the peer, and takes ownership of the packet if the packet
// cannot be written immediately.
virtual void SendOrQueuePacket(SerializedPacket* packet);
- QuicConnectionHelperInterface* helper() { return helper_; }
+ // 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);
- // On peer address changes, determine and return the change type.
- virtual PeerAddressChangeType DeterminePeerAddressChangeType();
+ // Called when a peer 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
// such a version exists, false otherwise.
bool SelectMutualVersion(const QuicVersionVector& available_versions);
- bool peer_ip_changed() const { return peer_ip_changed_; }
+ const IPEndPoint& last_packet_source_address() const {
+ return last_packet_source_address_;
+ }
+
+ // Returns the current per-packet options for the connection.
+ PerPacketOptions* per_packet_options() { return per_packet_options_; }
+ // Sets the current per-packet options for the connection. The QuicConnection
+ // does not take ownership of |options|; |options| must live for as long as
+ // the QuicConnection is in use.
+ void set_per_packet_options(PerPacketOptions* options) {
+ per_packet_options_ = options;
+ }
- bool peer_port_changed() const { return peer_port_changed_; }
+ // If |defer| is true, configures the connection to defer sending packets in
+ // response to an ACK to the SendAlarm. If |defer| is false, packets may be
+ // sent immediately after receiving an ACK.
+ void set_defer_send_in_response_to_packets(bool defer) {
+ defer_send_in_response_to_packets_ = defer;
+ }
- const IPAddressNumber& migrating_peer_ip() const {
- return migrating_peer_ip_;
+ PeerAddressChangeType active_peer_migration_type() {
+ return active_peer_migration_type_;
}
+ // Sends the connection close packet to the peer.
+ virtual void SendConnectionClosePacket(QuicErrorCode error,
+ const std::string& details);
+
private:
friend class test::QuicConnectionPeer;
friend class test::PacketSavingConnection;
typedef std::list<SerializedPacket> QueuedPacketList;
- typedef std::map<QuicFecGroupNumber, QuicFecGroup*> FecGroupMap;
+
+ // Notifies the visitor of the close and marks the connection as disconnected.
+ // Does not send a connection close frame to the peer.
+ void TearDownLocalConnectionState(QuicErrorCode error,
+ const std::string& details,
+ ConnectionCloseSource source);
// Writes the given packet to socket, encrypted with packet's
// encryption_level. Returns true on successful write, and false if the writer
@@ -679,10 +740,6 @@ class NET_EXPORT_PRIVATE QuicConnection
// writer is write blocked.
bool WritePacket(SerializedPacket* packet);
- // Does the main work of WritePacket, but does not delete the packet or
- // retransmittable frames upon success.
- bool WritePacketInner(SerializedPacket* packet);
-
// Make sure an ack we got from our peer is sane.
// Returns nullptr for valid acks or an error std::string if it was invalid.
const char* ValidateAckFrame(const QuicAckFrame& incoming_ack);
@@ -723,10 +780,6 @@ class NET_EXPORT_PRIVATE QuicConnection
// Attempts to process any queued undecryptable packets.
void MaybeProcessUndecryptablePackets();
- // If a packet can be revived from the current FEC group, then
- // revive and process the packet.
- void MaybeProcessRevivedPacket();
-
void ProcessAckFrame(const QuicAckFrame& incoming_ack);
void ProcessStopWaitingFrame(const QuicStopWaitingFrame& stop_waiting);
@@ -743,13 +796,6 @@ class NET_EXPORT_PRIVATE QuicConnection
// to be sent if there are no outstanding packets.
QuicPacketNumber GetLeastUnacked() const;
- // Get the FEC group associate with the last processed packet or nullptr, if
- // the group has already been deleted.
- QuicFecGroup* GetFecGroup();
-
- // Closes any FEC groups protecting packets before |packet_number|.
- void CloseFecGroupsBefore(QuicPacketNumber packet_number);
-
// Sets the timeout alarm to the appropriate value, if any.
void SetTimeoutAlarm();
@@ -777,8 +823,23 @@ class NET_EXPORT_PRIVATE QuicConnection
// the largest supported by the protocol or the packet writer.
QuicByteCount LimitMaxPacketSize(QuicByteCount suggested_max_packet_size);
+ // Called when |path_id| is considered as closed because either a PATH_CLOSE
+ // frame is sent or received. Stops receiving packets on closed path. 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.
+ // TODO(fayang): complete OnPathClosed once QuicMultipathSentPacketManager and
+ // QuicMultipathReceivedPacketManager are landed in QuicConnection.
+ void OnPathClosed(QuicPathId path_id);
+
+ // Do any work which logically would be done in OnPacket but can not be
+ // safely done until the packet is validated. Returns true if packet can be
+ // handled, false otherwise.
+ bool ProcessValidatedPacket(const QuicPacketHeader& header);
+
QuicFramer framer_;
QuicConnectionHelperInterface* helper_; // Not owned.
+ PerPacketOptions* per_packet_options_; // Not owned.
QuicPacketWriter* writer_; // Owned or not depending on |owns_writer_|.
bool owns_writer_;
// Encryption level for new packets. Should only be changed via
@@ -798,16 +859,20 @@ class NET_EXPORT_PRIVATE QuicConnection
IPEndPoint self_address_;
IPEndPoint peer_address_;
- // Used to store latest peer IP address for IP address migration.
- IPAddressNumber migrating_peer_ip_;
- // Used to store latest peer port to possibly migrate to later.
- uint16_t migrating_peer_port_;
+ // Records change type when the peer initiates migration to a new peer
+ // address. Reset to NO_CHANGE after peer migration is validated.
+ PeerAddressChangeType active_peer_migration_type_;
+
+ // Records highest sent packet number when peer migration is started.
+ QuicPacketNumber highest_packet_sent_before_peer_migration_;
// True if the last packet has gotten far enough in the framer to be
// decrypted.
bool last_packet_decrypted_;
- bool last_packet_revived_; // True if the last packet was revived from FEC.
- QuicByteCount last_size_; // Size of the last received packet.
+ QuicByteCount last_size_; // Size of the last received packet.
+ // TODO(rch): remove this when b/27221014 is fixed.
+ const char* current_packet_data_; // UDP payload of packet currently being
+ // parsed or nullptr.
EncryptionLevel last_decrypted_packet_level_;
QuicPacketHeader last_header_;
QuicStopWaitingFrame last_stop_waiting_frame_;
@@ -834,8 +899,10 @@ class NET_EXPORT_PRIVATE QuicConnection
bool pending_version_negotiation_packet_;
// When packets could not be sent because the socket was not writable,
- // they are added to this list. All corresponding frames are in
- // unacked_packets_ if they are to be retransmitted.
+ // they are added to this std::list. All corresponding frames are in
+ // unacked_packets_ if they are to be retransmitted. Packets encrypted_buffer
+ // fields are owned by the QueuedPacketList, in order to ensure they outlast
+ // the original scope of the SerializedPacket.
QueuedPacketList queued_packets_;
// If true, then crypto packets will be saved as termination packets.
@@ -844,10 +911,15 @@ class NET_EXPORT_PRIVATE QuicConnection
// Contains the connection close packets if the connection has been closed.
scoped_ptr<std::vector<QuicEncryptedPacket*>> termination_packets_;
- // When true, the connection does not send a close packet on timeout.
- bool silent_close_enabled_;
+ // Determines whether or not a connection close packet is sent to the peer
+ // after idle timeout due to lack of network activity.
+ // This is particularly important on mobile, where waking up the radio is
+ // undesirable.
+ ConnectionCloseBehavior idle_timeout_connection_close_behavior_;
- FecGroupMap group_map_;
+ // When true, close the QUIC connection after 5 RTOs. Due to the min rto of
+ // 200ms, this is over 5 seconds.
+ bool close_connection_after_five_rtos_;
QuicReceivedPacketManager received_packet_manager_;
QuicSentEntropyManager sent_entropy_manager_;
@@ -856,13 +928,15 @@ class NET_EXPORT_PRIVATE QuicConnection
bool ack_queued_;
// How many retransmittable packets have arrived without sending an ack.
QuicPacketCount num_retransmittable_packets_received_since_last_ack_sent_;
+ // Whether there were missing packets in the last sent ack.
+ bool last_ack_had_missing_packets_;
// How many consecutive packets have arrived without sending an ack.
QuicPacketCount num_packets_received_since_last_ack_sent_;
// Indicates how many consecutive times an ack has arrived which indicates
// the peer needs to stop waiting for some packets.
int stop_waiting_count_;
- // When true, ack only every 10 packets as long as they arrive close together.
- bool ack_decimation_enabled_;
+ // Indicates the current ack mode, defaults to acking every 2 packets.
+ AckMode ack_mode_;
// Indicates the retransmit alarm is going to be set by the
// ScopedRetransmitAlarmDelayer
@@ -870,22 +944,29 @@ class NET_EXPORT_PRIVATE QuicConnection
// Indicates the retransmission alarm needs to be set.
bool pending_retransmission_alarm_;
+ // If true, defer sending data in response to received packets to the
+ // SendAlarm.
+ bool defer_send_in_response_to_packets_;
+
+ // Arena to store class implementations within the QuicConnection.
+ QuicConnectionArena arena_;
+
// An alarm that fires when an ACK should be sent to the peer.
- scoped_ptr<QuicAlarm> ack_alarm_;
+ QuicArenaScopedPtr<QuicAlarm> ack_alarm_;
// An alarm that fires when a packet needs to be retransmitted.
- scoped_ptr<QuicAlarm> retransmission_alarm_;
+ QuicArenaScopedPtr<QuicAlarm> retransmission_alarm_;
// An alarm that is scheduled when the SentPacketManager requires a delay
// before sending packets and fires when the packet may be sent.
- scoped_ptr<QuicAlarm> send_alarm_;
+ QuicArenaScopedPtr<QuicAlarm> send_alarm_;
// An alarm that is scheduled when the connection can still write and there
// may be more data to send.
- scoped_ptr<QuicAlarm> resume_writes_alarm_;
+ QuicArenaScopedPtr<QuicAlarm> resume_writes_alarm_;
// An alarm that fires when the connection may have timed out.
- scoped_ptr<QuicAlarm> timeout_alarm_;
+ QuicArenaScopedPtr<QuicAlarm> timeout_alarm_;
// An alarm that fires when a ping should be sent.
- scoped_ptr<QuicAlarm> ping_alarm_;
+ QuicArenaScopedPtr<QuicAlarm> ping_alarm_;
// An alarm that fires when an MTU probe should be sent.
- scoped_ptr<QuicAlarm> mtu_discovery_alarm_;
+ QuicArenaScopedPtr<QuicAlarm> mtu_discovery_alarm_;
// Neither visitor is owned by this class.
QuicConnectionVisitorInterface* visitor_;
@@ -893,13 +974,10 @@ class NET_EXPORT_PRIVATE QuicConnection
QuicPacketGenerator packet_generator_;
- // An alarm that fires when an FEC packet should be sent.
- scoped_ptr<QuicAlarm> fec_alarm_;
-
- // Network idle time before we kill of this connection.
+ // Network idle time before this connection is closed.
QuicTime::Delta idle_network_timeout_;
- // Overall connection timeout.
- QuicTime::Delta overall_connection_timeout_;
+ // The connection will wait this long for the handshake to complete.
+ QuicTime::Delta handshake_timeout_;
// Statistics for this session.
QuicConnectionStats stats_;
@@ -935,19 +1013,11 @@ class NET_EXPORT_PRIVATE QuicConnection
// close.
bool connected_;
- // Set to true if the UDP packet headers have a new IP address for the peer.
- bool peer_ip_changed_;
-
- // Set to true if the UDP packet headers have a new port for the peer.
- bool peer_port_changed_;
-
- // Set to true if the UDP packet headers are addressed to a different IP.
- // We do not support connection migration when the self IP changed.
- bool self_ip_changed_;
+ // Destination address of the last received packet.
+ IPEndPoint last_packet_destination_address_;
- // Set to true if the UDP packet headers are addressed to a different port.
- // We do not support connection migration when the self port changed.
- bool self_port_changed_;
+ // Source address of the last received packet.
+ IPEndPoint 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.
diff --git a/chromium/net/quic/quic_connection_logger.cc b/chromium/net/quic/quic_connection_logger.cc
index 33fa4e0c68b..b9cb00e3223 100644
--- a/chromium/net/quic/quic_connection_logger.cc
+++ b/chromium/net/quic/quic_connection_logger.cc
@@ -15,12 +15,14 @@
#include "base/profiler/scoped_tracker.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
+#include "net/base/ip_address.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/x509_certificate.h"
#include "net/log/net_log.h"
#include "net/quic/crypto/crypto_handshake_message.h"
#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/quic_address_mismatch.h"
+#include "net/quic/quic_protocol.h"
#include "net/quic/quic_socket_address_coder.h"
#include "net/quic/quic_time.h"
@@ -51,14 +53,12 @@ scoped_ptr<base::Value> NetLogQuicPacketCallback(
scoped_ptr<base::Value> NetLogQuicPacketSentCallback(
const SerializedPacket& serialized_packet,
TransmissionType transmission_type,
- size_t packet_size,
QuicTime sent_time,
NetLogCaptureMode /* capture_mode */) {
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->SetInteger("transmission_type", transmission_type);
dict->SetString("packet_number",
base::Uint64ToString(serialized_packet.packet_number));
- dict->SetInteger("size", packet_size);
dict->SetString("sent_time_us",
base::Int64ToString(sent_time.ToDebuggingValue()));
return std::move(dict);
@@ -114,9 +114,8 @@ scoped_ptr<base::Value> NetLogQuicAckFrameCallback(
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->SetString("largest_observed",
base::Uint64ToString(frame->largest_observed));
- dict->SetString(
- "delta_time_largest_observed_us",
- base::Int64ToString(frame->delta_time_largest_observed.ToMicroseconds()));
+ dict->SetString("delta_time_largest_observed_us",
+ base::Int64ToString(frame->ack_delay_time.ToMicroseconds()));
dict->SetInteger("entropy_hash", frame->entropy_hash);
dict->SetBoolean("truncated", frame->is_truncated);
@@ -125,9 +124,6 @@ scoped_ptr<base::Value> NetLogQuicAckFrameCallback(
for (QuicPacketNumber packet : frame->missing_packets)
missing->AppendString(base::Uint64ToString(packet));
- dict->SetString("latest_revived_packet",
- base::Int64ToString(frame->latest_revived_packet));
-
base::ListValue* received = new base::ListValue();
dict->Set("received_packet_times", received);
const PacketTimeVector& received_times = frame->received_packet_times;
@@ -222,11 +218,12 @@ scoped_ptr<base::Value> NetLogQuicCryptoHandshakeMessageCallback(
scoped_ptr<base::Value> NetLogQuicOnConnectionClosedCallback(
QuicErrorCode error,
- bool from_peer,
+ ConnectionCloseSource source,
NetLogCaptureMode /* capture_mode */) {
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->SetInteger("quic_error", error);
- dict->SetBoolean("from_peer", from_peer);
+ dict->SetBoolean("from_peer",
+ source == ConnectionCloseSource::FROM_PEER ? true : false);
return std::move(dict);
}
@@ -267,9 +264,9 @@ void UpdatePublicResetAddressMismatchHistogram(
// If |address| is an IPv4-mapped IPv6 address, returns ADDRESS_FAMILY_IPV4
// instead of ADDRESS_FAMILY_IPV6. Othewise, behaves like GetAddressFamily().
-AddressFamily GetRealAddressFamily(const IPAddressNumber& address) {
- return IsIPv4Mapped(address) ? ADDRESS_FAMILY_IPV4
- : GetAddressFamily(address);
+AddressFamily GetRealAddressFamily(const IPAddress& address) {
+ return address.IsIPv4MappedIPv6() ? ADDRESS_FAMILY_IPV4
+ : GetAddressFamily(address);
}
} // namespace
@@ -429,13 +426,12 @@ void QuicConnectionLogger::OnPacketSent(
const SerializedPacket& serialized_packet,
QuicPacketNumber original_packet_number,
TransmissionType transmission_type,
- size_t encrypted_length,
QuicTime sent_time) {
if (original_packet_number == 0) {
net_log_.AddEvent(
NetLog::TYPE_QUIC_SESSION_PACKET_SENT,
base::Bind(&NetLogQuicPacketSentCallback, serialized_packet,
- transmission_type, encrypted_length, sent_time));
+ transmission_type, sent_time));
} else {
net_log_.AddEvent(
NetLog::TYPE_QUIC_SESSION_PACKET_RETRANSMITTED,
@@ -615,6 +611,9 @@ void QuicConnectionLogger::OnBlockedFrame(const QuicBlockedFrame& frame) {
}
void QuicConnectionLogger::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
+ UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.GoAwayReceivedForConnectionMigration",
+ frame.error_code == QUIC_ERROR_MIGRATING_PORT);
+
net_log_.AddEvent(NetLog::TYPE_QUIC_SESSION_GOAWAY_FRAME_RECEIVED,
base::Bind(&NetLogQuicGoAwayFrameCallback, &frame));
}
@@ -638,14 +637,6 @@ void QuicConnectionLogger::OnVersionNegotiationPacket(
base::Bind(&NetLogQuicVersionNegotiationPacketCallback, &packet));
}
-void QuicConnectionLogger::OnRevivedPacket(
- const QuicPacketHeader& revived_header,
- base::StringPiece payload) {
- net_log_.AddEvent(
- NetLog::TYPE_QUIC_SESSION_PACKET_HEADER_REVIVED,
- base::Bind(&NetLogQuicPacketHeaderCallback, &revived_header));
-}
-
void QuicConnectionLogger::OnCryptoHandshakeMessageReceived(
const CryptoHandshakeMessage& message) {
net_log_.AddEvent(
@@ -674,10 +665,11 @@ void QuicConnectionLogger::OnCryptoHandshakeMessageSent(
}
void QuicConnectionLogger::OnConnectionClosed(QuicErrorCode error,
- bool from_peer) {
+ const string& error_details,
+ ConnectionCloseSource source) {
net_log_.AddEvent(
NetLog::TYPE_QUIC_SESSION_CLOSED,
- base::Bind(&NetLogQuicOnConnectionClosedCallback, error, from_peer));
+ base::Bind(&NetLogQuicOnConnectionClosedCallback, error, source));
}
void QuicConnectionLogger::OnSuccessfulVersionNegotiation(
diff --git a/chromium/net/quic/quic_connection_logger.h b/chromium/net/quic/quic_connection_logger.h
index 6d414905f9e..ff2c9173e1a 100644
--- a/chromium/net/quic/quic_connection_logger.h
+++ b/chromium/net/quic/quic_connection_logger.h
@@ -29,7 +29,8 @@ class CertVerifyResult;
// This class is a debug visitor of a QuicConnection which logs
// events to |net_log|.
class NET_EXPORT_PRIVATE QuicConnectionLogger
- : public QuicConnectionDebugVisitor {
+ : public QuicConnectionDebugVisitor,
+ public QuicPacketCreator::DebugDelegate {
public:
QuicConnectionLogger(
QuicSpdySession* session,
@@ -39,14 +40,13 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger
~QuicConnectionLogger() override;
- // QuicPacketGenerator::DebugDelegateInterface
+ // QuicPacketCreator::DebugDelegateInterface
void OnFrameAddedToPacket(const QuicFrame& frame) override;
// QuicConnectionDebugVisitorInterface
void OnPacketSent(const SerializedPacket& serialized_packet,
QuicPacketNumber original_packet_number,
TransmissionType transmission_type,
- size_t encrypted_length,
QuicTime sent_time) override;
void OnPacketReceived(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
@@ -69,9 +69,9 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger
void OnPublicResetPacket(const QuicPublicResetPacket& packet) override;
void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) override;
- void OnRevivedPacket(const QuicPacketHeader& revived_header,
- base::StringPiece payload) override;
- void OnConnectionClosed(QuicErrorCode error, bool from_peer) override;
+ void OnConnectionClosed(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) override;
void OnSuccessfulVersionNegotiation(const QuicVersion& version) override;
void OnRttChanged(QuicTime::Delta rtt) const override;
diff --git a/chromium/net/quic/quic_connection_stats.cc b/chromium/net/quic/quic_connection_stats.cc
index 2c98fcca57d..df6e643d28c 100644
--- a/chromium/net/quic/quic_connection_stats.cc
+++ b/chromium/net/quic/quic_connection_stats.cc
@@ -24,7 +24,7 @@ QuicConnectionStats::QuicConnectionStats()
packets_lost(0),
slowstart_packets_sent(0),
slowstart_packets_lost(0),
- packets_revived(0),
+ slowstart_bytes_lost(0),
packets_dropped(0),
crypto_retransmit_count(0),
loss_timeout_count(0),
@@ -41,6 +41,9 @@ QuicConnectionStats::QuicConnectionStats()
tcp_loss_events(0),
connection_creation_time(QuicTime::Zero()) {}
+QuicConnectionStats::QuicConnectionStats(const QuicConnectionStats& other) =
+ default;
+
QuicConnectionStats::~QuicConnectionStats() {}
} // namespace net
diff --git a/chromium/net/quic/quic_connection_stats.h b/chromium/net/quic/quic_connection_stats.h
index 655ab321f83..2f491ae832a 100644
--- a/chromium/net/quic/quic_connection_stats.h
+++ b/chromium/net/quic/quic_connection_stats.h
@@ -19,13 +19,14 @@ namespace net {
// Structure to hold stats for a QuicConnection.
struct NET_EXPORT_PRIVATE QuicConnectionStats {
QuicConnectionStats();
+ QuicConnectionStats(const QuicConnectionStats& other);
~QuicConnectionStats();
NET_EXPORT_PRIVATE friend std::ostream& operator<<(
std::ostream& os,
const QuicConnectionStats& s);
- QuicByteCount bytes_sent; // Includes retransmissions, fec.
+ QuicByteCount bytes_sent; // Includes retransmissions.
QuicPacketCount packets_sent;
// Non-retransmitted bytes sent in a stream frame.
QuicByteCount stream_bytes_sent;
@@ -34,7 +35,7 @@ struct NET_EXPORT_PRIVATE QuicConnectionStats {
// These include version negotiation and public reset packets, which do not
// have packet numbers or frame data.
- QuicByteCount bytes_received; // Includes duplicate data for a stream, fec.
+ QuicByteCount bytes_received; // Includes duplicate data for a stream.
// Includes packets which were not processable.
QuicPacketCount packets_received;
// Excludes packets which were not processable.
@@ -53,8 +54,9 @@ struct NET_EXPORT_PRIVATE QuicConnectionStats {
QuicPacketCount slowstart_packets_sent;
// Number of packets lost exiting slow start.
QuicPacketCount slowstart_packets_lost;
+ // Number of bytes lost exiting slow start.
+ QuicByteCount slowstart_bytes_lost;
- QuicPacketCount packets_revived;
QuicPacketCount packets_dropped; // Duplicate or less than least unacked.
size_t crypto_retransmit_count;
// Count of times the loss detection alarm fired. At least one packet should
diff --git a/chromium/net/quic/quic_connection_test.cc b/chromium/net/quic/quic_connection_test.cc
index c29ded9c9ff..ee2ab97d0c3 100644
--- a/chromium/net/quic/quic_connection_test.cc
+++ b/chromium/net/quic/quic_connection_test.cc
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/quic/congestion_control/loss_detection_interface.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
@@ -83,7 +84,8 @@ class TaggingEncrypter : public QuicEncrypter {
bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; }
- bool EncryptPacket(QuicPacketNumber packet_number,
+ bool EncryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
StringPiece associated_data,
StringPiece plaintext,
char* output,
@@ -93,6 +95,7 @@ class TaggingEncrypter : public QuicEncrypter {
if (max_output_length < len) {
return false;
}
+ // Memmove is safe for inplace encryption.
memmove(output, plaintext.data(), plaintext.size());
output += plaintext.size();
memset(output, tag_, kTagSize);
@@ -136,9 +139,10 @@ class TaggingDecrypter : public QuicDecrypter {
bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; }
- bool DecryptPacket(QuicPacketNumber packet_number,
- const StringPiece& associated_data,
- const StringPiece& ciphertext,
+ bool DecryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
+ StringPiece associated_data,
+ StringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) override {
@@ -202,7 +206,8 @@ class TestConnectionHelper : public QuicConnectionHelperInterface {
public:
class TestAlarm : public QuicAlarm {
public:
- explicit TestAlarm(QuicAlarm::Delegate* delegate) : QuicAlarm(delegate) {}
+ explicit TestAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate> delegate)
+ : QuicAlarm(std::move(delegate)) {}
void SetImpl() override {}
void CancelImpl() override {}
@@ -220,7 +225,13 @@ class TestConnectionHelper : public QuicConnectionHelperInterface {
QuicRandom* GetRandomGenerator() override { return random_generator_; }
QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override {
- return new TestAlarm(delegate);
+ return new TestAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate));
+ }
+
+ QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
+ QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+ QuicConnectionArena* arena) override {
+ return arena->New<TestAlarm>(std::move(delegate));
}
QuicBufferAllocator* GetBufferAllocator() override {
@@ -256,8 +267,9 @@ class TestPacketWriter : public QuicPacketWriter {
// QuicPacketWriter interface
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) override {
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) override {
QuicEncryptedPacket packet(buffer, buf_len);
++packets_write_attempts_;
@@ -423,9 +435,6 @@ class TestConnection : public QuicConnection {
/* owns_writer= */ false,
perspective,
SupportedVersions(version)) {
- // Disable tail loss probes for most tests.
- QuicSentPacketManagerPeer::SetMaxTailLossProbes(
- QuicConnectionPeer::GetSentPacketManager(this), 0);
writer->set_perspective(perspective);
}
@@ -441,25 +450,26 @@ class TestConnection : public QuicConnection {
}
void SendPacket(EncryptionLevel level,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
QuicPacket* packet,
QuicPacketEntropyHash entropy_hash,
HasRetransmittableData retransmittable,
bool has_ack,
bool has_pending_frames) {
- RetransmittableFrames* retransmittable_frames =
- retransmittable == HAS_RETRANSMITTABLE_DATA
- ? new RetransmittableFrames()
- : nullptr;
char buffer[kMaxPacketSize];
size_t encrypted_length =
QuicConnectionPeer::GetFramer(this)->EncryptPayload(
- ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize);
+ ENCRYPTION_NONE, path_id, packet_number, *packet, buffer,
+ kMaxPacketSize);
delete packet;
SerializedPacket serialized_packet(
kDefaultPathId, packet_number, PACKET_6BYTE_PACKET_NUMBER, buffer,
- encrypted_length, false, entropy_hash, retransmittable_frames, has_ack,
- has_pending_frames, ENCRYPTION_NONE);
+ encrypted_length, entropy_hash, has_ack, has_pending_frames);
+ if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
+ serialized_packet.retransmittable_frames.push_back(
+ QuicFrame(new QuicStreamFrame()));
+ }
OnSerializedPacket(&serialized_packet);
}
@@ -469,31 +479,9 @@ class TestConnection : public QuicConnection {
QuicStreamOffset offset,
bool fin,
QuicAckListenerInterface* listener) {
- return SendStreamDataWithStringHelper(id, data, offset, fin,
- MAY_FEC_PROTECT, listener);
- }
-
- QuicConsumedData SendStreamDataWithStringWithFec(
- QuicStreamId id,
- StringPiece data,
- QuicStreamOffset offset,
- bool fin,
- QuicAckListenerInterface* listener) {
- return SendStreamDataWithStringHelper(id, data, offset, fin,
- MUST_FEC_PROTECT, listener);
- }
-
- QuicConsumedData SendStreamDataWithStringHelper(
- QuicStreamId id,
- StringPiece data,
- QuicStreamOffset offset,
- bool fin,
- FecProtection fec_protection,
- QuicAckListenerInterface* listener) {
struct iovec iov;
QuicIOVector data_iov(MakeIOVector(data, &iov));
- return QuicConnection::SendStreamData(id, data_iov, offset, fin,
- fec_protection, listener);
+ return QuicConnection::SendStreamData(id, data_iov, offset, fin, listener);
}
QuicConsumedData SendStreamData3() {
@@ -501,20 +489,11 @@ class TestConnection : public QuicConnection {
nullptr);
}
- QuicConsumedData SendStreamData3WithFec() {
- return SendStreamDataWithStringWithFec(kClientDataStreamId1, "food", 0,
- !kFin, nullptr);
- }
-
QuicConsumedData SendStreamData5() {
return SendStreamDataWithString(kClientDataStreamId2, "food2", 0, !kFin,
nullptr);
}
- QuicConsumedData SendStreamData5WithFec() {
- return SendStreamDataWithStringWithFec(kClientDataStreamId2, "food2", 0,
- !kFin, nullptr);
- }
// Ensures the connection can write stream data before writing.
QuicConsumedData EnsureWritableAndSendStreamData5() {
EXPECT_TRUE(CanWriteStreamData());
@@ -573,11 +552,6 @@ class TestConnection : public QuicConnection {
QuicConnectionPeer::GetPingAlarm(this));
}
- TestConnectionHelper::TestAlarm* GetFecAlarm() {
- return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
- QuicConnectionPeer::GetFecAlarm(this));
- }
-
TestConnectionHelper::TestAlarm* GetResumeWritesAlarm() {
return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
QuicConnectionPeer::GetResumeWritesAlarm(this));
@@ -603,7 +577,13 @@ class TestConnection : public QuicConnection {
QuicConnectionPeer::GetMtuDiscoveryAlarm(this));
}
+ void DisableTailLossProbe() {
+ QuicSentPacketManagerPeer::SetMaxTailLossProbes(
+ QuicConnectionPeer::GetSentPacketManager(this), 0);
+ }
+
using QuicConnection::SelectMutualVersion;
+ using QuicConnection::set_defer_send_in_response_to_packets;
private:
TestPacketWriter* writer() {
@@ -613,34 +593,23 @@ class TestConnection : public QuicConnection {
DISALLOW_COPY_AND_ASSIGN(TestConnection);
};
-// Used for testing packets revived from FEC packets.
-class FecQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor {
- public:
- void OnRevivedPacket(const QuicPacketHeader& header,
- StringPiece data) override {
- revived_header_ = header;
- }
-
- // Public accessor method.
- QuicPacketHeader revived_header() const { return revived_header_; }
-
- private:
- QuicPacketHeader revived_header_;
-};
+enum class AckResponse { kDefer, kImmediate };
-// Run tests with combinations of {QuicVersion, fec_send_policy}.
+// Run tests with combinations of {QuicVersion, AckResponse}.
struct TestParams {
- TestParams(QuicVersion version, FecSendPolicy fec_send_policy)
- : version(version), fec_send_policy(fec_send_policy) {}
+ TestParams(QuicVersion version, AckResponse ack_response)
+ : version(version), ack_response(ack_response) {}
friend ostream& operator<<(ostream& os, const TestParams& p) {
os << "{ client_version: " << QuicVersionToString(p.version)
- << " fec_send_policy: " << p.fec_send_policy << " }";
+ << " ack_response: "
+ << (p.ack_response == AckResponse::kDefer ? "defer" : "immediate")
+ << " }";
return os;
}
QuicVersion version;
- FecSendPolicy fec_send_policy;
+ AckResponse ack_response;
};
// Constructs various test permutations.
@@ -648,8 +617,10 @@ vector<TestParams> GetTestParams() {
vector<TestParams> params;
QuicVersionVector all_supported_versions = QuicSupportedVersions();
for (size_t i = 0; i < all_supported_versions.size(); ++i) {
- params.push_back(TestParams(all_supported_versions[i], FEC_ANY_TRIGGER));
- params.push_back(TestParams(all_supported_versions[i], FEC_ALARM_TRIGGER));
+ for (AckResponse ack_response :
+ {AckResponse::kDefer, AckResponse::kImmediate}) {
+ params.push_back(TestParams(all_supported_versions[i], ack_response));
+ }
}
return params;
}
@@ -683,13 +654,14 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
frame2_(1, false, 3, StringPiece(data2)),
packet_number_length_(PACKET_6BYTE_PACKET_NUMBER),
connection_id_length_(PACKET_8BYTE_CONNECTION_ID) {
+ connection_.set_defer_send_in_response_to_packets(GetParam().ack_response ==
+ AckResponse::kDefer);
FLAGS_quic_always_log_bugs_for_tests = true;
connection_.set_visitor(&visitor_);
connection_.SetSendAlgorithm(send_algorithm_);
connection_.SetLossAlgorithm(loss_algorithm_);
framer_.set_received_entropy_calculator(&entropy_calculator_);
- generator_->set_fec_send_policy(GetParam().fec_send_policy);
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillRepeatedly(Return(QuicTime::Delta::Zero()));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
.Times(AnyNumber());
@@ -711,29 +683,24 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
EXPECT_CALL(visitor_, WillingAndAbleToWrite()).Times(AnyNumber());
EXPECT_CALL(visitor_, HasPendingHandshake()).Times(AnyNumber());
EXPECT_CALL(visitor_, OnCanWrite()).Times(AnyNumber());
+ EXPECT_CALL(visitor_, PostProcessAfterData()).Times(AnyNumber());
EXPECT_CALL(visitor_, HasOpenDynamicStreams())
.WillRepeatedly(Return(false));
EXPECT_CALL(visitor_, OnCongestionWindowChange(_)).Times(AnyNumber());
EXPECT_CALL(*loss_algorithm_, GetLossTimeout())
.WillRepeatedly(Return(QuicTime::Zero()));
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .Times(AnyNumber());
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillRepeatedly(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _)).Times(AnyNumber());
// TODO(ianswett): Fix QuicConnectionTests so they don't attempt to write
// non-crypto stream data at ENCRYPTION_NONE.
FLAGS_quic_never_write_unencrypted_data = false;
- FLAGS_quic_no_unencrypted_fec = false;
}
QuicVersion version() { return GetParam().version; }
QuicAckFrame* outgoing_ack() {
- QuicConnectionPeer::PopulateAckFrame(&connection_, &ack_);
+ QuicFrame ack_frame = QuicConnectionPeer::GetUpdatedAckFrame(&connection_);
+ ack_ = *ack_frame.ack_frame;
return &ack_;
}
@@ -751,12 +718,22 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
void use_tagging_decrypter() { writer_->use_tagging_decrypter(); }
- void ProcessPacket(QuicPacketNumber number) {
+ void ProcessPacket(QuicPathId path_id, QuicPacketNumber number) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacket(number, 0, !kEntropyFlag);
+ ProcessDataPacket(path_id, number, !kEntropyFlag);
+ if (connection_.GetSendAlarm()->IsSet()) {
+ connection_.GetSendAlarm()->Fire();
+ }
}
QuicPacketEntropyHash ProcessFramePacket(QuicFrame frame) {
+ return ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
+ }
+
+ QuicPacketEntropyHash ProcessFramePacketWithAddresses(
+ QuicFrame frame,
+ IPEndPoint self_address,
+ IPEndPoint peer_address) {
QuicFrames frames;
frames.push_back(QuicFrame(frame));
QuicPacketCreatorPeer::SetSendVersionInPacket(
@@ -764,157 +741,76 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
char buffer[kMaxPacketSize];
SerializedPacket serialized_packet =
- peer_creator_.SerializeAllFrames(frames, buffer, kMaxPacketSize);
- scoped_ptr<QuicEncryptedPacket> encrypted(serialized_packet.packet);
- connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted);
+ QuicPacketCreatorPeer::SerializeAllFrames(&peer_creator_, frames,
+ buffer, kMaxPacketSize);
+ connection_.ProcessUdpPacket(
+ self_address, peer_address,
+ QuicReceivedPacket(serialized_packet.encrypted_buffer,
+ serialized_packet.encrypted_length, clock_.Now()));
+ if (connection_.GetSendAlarm()->IsSet()) {
+ connection_.GetSendAlarm()->Fire();
+ }
return serialized_packet.entropy_hash;
}
- QuicPacketEntropyHash ProcessFramePacketAtLevel(QuicPacketNumber number,
+ QuicPacketEntropyHash 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_;
header.public_header.connection_id_length = connection_id_length_;
+ header.public_header.multipath_flag = path_id != kDefaultPathId;
+ header.path_id = path_id;
header.packet_number = number;
QuicFrames frames;
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_length =
- framer_.EncryptPayload(level, number, *packet, buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ level, path_id, number, *packet, buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
return base::checked_cast<QuicPacketEntropyHash>(encrypted_length);
}
- size_t ProcessDataPacket(QuicPacketNumber number,
- QuicFecGroupNumber fec_group,
+ size_t ProcessDataPacket(QuicPathId path_id,
+ QuicPacketNumber number,
bool entropy_flag) {
- return ProcessDataPacketAtLevel(number, fec_group, entropy_flag, false,
+ return ProcessDataPacketAtLevel(path_id, number, entropy_flag, false,
ENCRYPTION_NONE);
}
- size_t ProcessDataPacketAtLevel(QuicPacketNumber number,
- QuicFecGroupNumber fec_group,
+ size_t ProcessDataPacketAtLevel(QuicPathId path_id,
+ QuicPacketNumber number,
bool entropy_flag,
bool has_stop_waiting,
EncryptionLevel level) {
scoped_ptr<QuicPacket> packet(
- ConstructDataPacket(number, fec_group, entropy_flag, has_stop_waiting));
+ ConstructDataPacket(path_id, number, entropy_flag, has_stop_waiting));
char buffer[kMaxPacketSize];
- size_t encrypted_length =
- framer_.EncryptPayload(level, number, *packet, buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ level, path_id, number, *packet, buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
+ if (connection_.GetSendAlarm()->IsSet()) {
+ connection_.GetSendAlarm()->Fire();
+ }
return encrypted_length;
}
- void ProcessClosePacket(QuicPacketNumber number,
- QuicFecGroupNumber fec_group) {
- scoped_ptr<QuicPacket> packet(ConstructClosePacket(number, fec_group));
+ void ProcessClosePacket(QuicPathId path_id, QuicPacketNumber number) {
+ scoped_ptr<QuicPacket> packet(ConstructClosePacket(number));
char buffer[kMaxPacketSize];
size_t encrypted_length = framer_.EncryptPayload(
- ENCRYPTION_NONE, number, *packet, buffer, kMaxPacketSize);
+ ENCRYPTION_NONE, path_id, number, *packet, buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
- }
-
- size_t ProcessFecProtectedPacket(QuicPacketNumber number,
- bool expect_revival,
- bool entropy_flag,
- bool has_stop_waiting) {
- return ProcessFecProtectedPacketAtLevel(number, 1, expect_revival,
- entropy_flag, has_stop_waiting,
- ENCRYPTION_NONE);
- }
-
- size_t ProcessFecProtectedPacketAtLevel(QuicPacketNumber number,
- QuicFecGroupNumber fec_group,
- bool expect_revival,
- bool entropy_flag,
- bool has_stop_waiting,
- EncryptionLevel level) {
- if (expect_revival) {
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- }
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1).RetiresOnSaturation();
- return ProcessDataPacketAtLevel(number, fec_group, entropy_flag,
- has_stop_waiting, level);
- }
-
- // Processes an FEC packet that covers the packets that would have been
- // received.
- size_t ProcessFecPacket(QuicPacketNumber number,
- QuicPacketNumber min_protected_packet,
- bool expect_revival,
- bool entropy_flag,
- QuicPacket* packet) {
- return ProcessFecPacketAtLevel(number, min_protected_packet, expect_revival,
- entropy_flag, packet, ENCRYPTION_NONE);
- }
-
- // Processes an FEC packet that covers the packets that would have been
- // received.
- size_t ProcessFecPacketAtLevel(QuicPacketNumber number,
- QuicPacketNumber min_protected_packet,
- bool expect_revival,
- bool entropy_flag,
- QuicPacket* packet,
- EncryptionLevel level) {
- if (expect_revival) {
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- }
-
- // Construct the decrypted data packet so we can compute the correct
- // redundancy. If |packet| has been provided then use that, otherwise
- // construct a default data packet.
- scoped_ptr<QuicPacket> data_packet;
- if (packet) {
- data_packet.reset(packet);
- } else {
- data_packet.reset(
- ConstructDataPacket(number, 1, !kEntropyFlag, !kHasStopWaiting));
- }
-
- 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.packet_number = number;
- header.entropy_flag = entropy_flag;
- header.fec_flag = true;
- header.is_in_fec_group = IN_FEC_GROUP;
- header.fec_group = min_protected_packet;
-
- // Since all data packets in this test have the same payload, the
- // redundancy is either equal to that payload or the xor of that payload
- // with itself, depending on the number of packets.
- if (((number - min_protected_packet) % 2) == 0) {
- for (size_t i = GetStartOfFecProtectedData(
- header.public_header.connection_id_length,
- header.public_header.version_flag,
- header.public_header.packet_number_length);
- i < data_packet->length(); ++i) {
- data_packet->mutable_data()[i] ^= data_packet->data()[i];
- }
- }
-
- scoped_ptr<QuicPacket> fec_packet(
- framer_.BuildFecPacket(header, data_packet->FecProtectedData()));
- char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(level, number, *fec_packet,
- buffer, kMaxPacketSize);
-
- connection_.ProcessUdpPacket(
- kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
- return encrypted_length;
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
}
QuicByteCount SendStreamDataToPeer(QuicStreamId id,
@@ -955,10 +851,11 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
}
QuicPacketEntropyHash ProcessStopWaitingPacketAtLevel(
+ QuicPathId path_id,
QuicPacketNumber number,
QuicStopWaitingFrame* frame,
EncryptionLevel level) {
- return ProcessFramePacketAtLevel(number, QuicFrame(frame),
+ return ProcessFramePacketAtLevel(path_id, number, QuicFrame(frame),
ENCRYPTION_INITIAL);
}
@@ -966,6 +863,10 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
return ProcessFramePacket(QuicFrame(frame));
}
+ QuicPacketEntropyHash ProcessPathClosePacket(QuicPathCloseFrame* frame) {
+ return ProcessFramePacket(QuicFrame(frame));
+ }
+
bool IsMissing(QuicPacketNumber number) {
return IsAwaitingPacket(*outgoing_ack(), number);
}
@@ -976,18 +877,20 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
return packet;
}
- QuicPacket* ConstructDataPacket(QuicPacketNumber number,
- QuicFecGroupNumber fec_group,
+ 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;
- header.is_in_fec_group = fec_group == 0u ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
- header.fec_group = fec_group;
+ header.is_in_fec_group = NOT_IN_FEC_GROUP;
+ header.fec_group = 0;
QuicFrames frames;
frames.push_back(QuicFrame(&frame1_));
@@ -997,13 +900,12 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
return ConstructPacket(header, frames);
}
- QuicPacket* ConstructClosePacket(QuicPacketNumber number,
- QuicFecGroupNumber fec_group) {
+ QuicPacket* ConstructClosePacket(QuicPacketNumber number) {
QuicPacketHeader header;
header.public_header.connection_id = connection_id_;
header.packet_number = number;
- header.is_in_fec_group = fec_group == 0u ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
- header.fec_group = fec_group;
+ header.is_in_fec_group = NOT_IN_FEC_GROUP;
+ header.fec_group = 0;
QuicConnectionCloseFrame qccf;
qccf.error_code = QUIC_PEER_GOING_AWAY;
@@ -1055,11 +957,11 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
void TriggerConnectionClose() {
// Send an erroneous packet to close the connection.
- EXPECT_CALL(visitor_,
- OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, _,
+ ConnectionCloseSource::FROM_SELF));
// Call ProcessDataPacket rather than ProcessPacket, as we should not get a
// packet call to the visitor.
- ProcessDataPacket(6000, 0, !kEntropyFlag);
+ ProcessDataPacket(kDefaultPathId, 6000, !kEntropyFlag);
EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) ==
nullptr);
}
@@ -1074,12 +976,12 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
}
void CongestionBlockWrites() {
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillRepeatedly(testing::Return(QuicTime::Delta::FromSeconds(1)));
}
void CongestionUnblockWrites() {
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
}
@@ -1117,6 +1019,45 @@ INSTANTIATE_TEST_CASE_P(SupportedVersion,
QuicConnectionTest,
::testing::ValuesIn(GetTestParams()));
+TEST_P(QuicConnectionTest, SelfAddressChangeAtClient) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+
+ EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
+ EXPECT_TRUE(connection_.connected());
+
+ QuicStreamFrame stream_frame(1u, false, 0u, StringPiece());
+ EXPECT_CALL(visitor_, OnStreamFrame(_));
+ ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
+ kPeerAddress);
+ // Cause change in self_address.
+ IPEndPoint self_address(IPAddress(1, 1, 1, 1), 123);
+ EXPECT_CALL(visitor_, OnStreamFrame(_));
+ ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), self_address,
+ kPeerAddress);
+ EXPECT_TRUE(connection_.connected());
+}
+
+TEST_P(QuicConnectionTest, SelfAddressChangeAtServer) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+
+ connection_.set_perspective(Perspective::IS_SERVER);
+ QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
+
+ EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
+ EXPECT_TRUE(connection_.connected());
+
+ QuicStreamFrame stream_frame(1u, false, 0u, StringPiece());
+ EXPECT_CALL(visitor_, OnStreamFrame(_));
+ ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
+ kPeerAddress);
+ // Cause change in self_address.
+ IPEndPoint self_address(IPAddress(1, 1, 1, 1), 123);
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_ERROR_MIGRATING_ADDRESS, _, _));
+ ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), self_address,
+ kPeerAddress);
+ EXPECT_FALSE(connection_.connected());
+}
+
TEST_P(QuicConnectionTest, MaxPacketSize) {
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
EXPECT_EQ(1350u, connection_.max_packet_length());
@@ -1139,6 +1080,7 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) {
QuicPacketHeader header;
header.public_header.connection_id = connection_id_;
header.public_header.version_flag = true;
+ header.path_id = kDefaultPathId;
header.packet_number = 1;
QuicFrames frames;
@@ -1147,15 +1089,15 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) {
frames.push_back(QuicFrame(padding));
scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet,
- buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, kDefaultPathId, 12, *packet, buffer, kMaxPacketSize);
EXPECT_EQ(kMaxPacketSize, encrypted_length);
framer_.set_version(version());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
EXPECT_EQ(kMaxPacketSize, connection_.max_packet_length());
}
@@ -1172,6 +1114,7 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSizeWhileWriterLimited) {
QuicPacketHeader header;
header.public_header.connection_id = connection_id_;
header.public_header.version_flag = true;
+ header.path_id = kDefaultPathId;
header.packet_number = 1;
QuicFrames frames;
@@ -1180,15 +1123,15 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSizeWhileWriterLimited) {
frames.push_back(QuicFrame(padding));
scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet,
- buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, kDefaultPathId, 12, *packet, buffer, kMaxPacketSize);
EXPECT_EQ(kMaxPacketSize, encrypted_length);
framer_.set_version(version());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
// Here, the limit imposed by the writer is lower than the size of the packet
// received, so the writer max packet size is used.
@@ -1219,15 +1162,15 @@ TEST_P(QuicConnectionTest, LimitMaxPacketSizeByWriterForNewConnection) {
TEST_P(QuicConnectionTest, PacketsInOrder) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(1);
+ ProcessPacket(kDefaultPathId, 1);
EXPECT_EQ(1u, outgoing_ack()->largest_observed);
EXPECT_TRUE(outgoing_ack()->missing_packets.Empty());
- ProcessPacket(2);
+ ProcessPacket(kDefaultPathId, 2);
EXPECT_EQ(2u, outgoing_ack()->largest_observed);
EXPECT_TRUE(outgoing_ack()->missing_packets.Empty());
- ProcessPacket(3);
+ ProcessPacket(kDefaultPathId, 3);
EXPECT_EQ(3u, outgoing_ack()->largest_observed);
EXPECT_TRUE(outgoing_ack()->missing_packets.Empty());
}
@@ -1235,17 +1178,17 @@ TEST_P(QuicConnectionTest, PacketsInOrder) {
TEST_P(QuicConnectionTest, PacketsOutOfOrder) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(3);
+ ProcessPacket(kDefaultPathId, 3);
EXPECT_EQ(3u, outgoing_ack()->largest_observed);
EXPECT_TRUE(IsMissing(2));
EXPECT_TRUE(IsMissing(1));
- ProcessPacket(2);
+ ProcessPacket(kDefaultPathId, 2);
EXPECT_EQ(3u, outgoing_ack()->largest_observed);
EXPECT_FALSE(IsMissing(2));
EXPECT_TRUE(IsMissing(1));
- ProcessPacket(1);
+ ProcessPacket(kDefaultPathId, 1);
EXPECT_EQ(3u, outgoing_ack()->largest_observed);
EXPECT_FALSE(IsMissing(2));
EXPECT_FALSE(IsMissing(1));
@@ -1254,14 +1197,14 @@ TEST_P(QuicConnectionTest, PacketsOutOfOrder) {
TEST_P(QuicConnectionTest, DuplicatePacket) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(3);
+ ProcessPacket(kDefaultPathId, 3);
EXPECT_EQ(3u, outgoing_ack()->largest_observed);
EXPECT_TRUE(IsMissing(2));
EXPECT_TRUE(IsMissing(1));
// Send packet 3 again, but do not set the expectation that
// the visitor OnStreamFrame() will be called.
- ProcessDataPacket(3, 0, !kEntropyFlag);
+ ProcessDataPacket(kDefaultPathId, 3, !kEntropyFlag);
EXPECT_EQ(3u, outgoing_ack()->largest_observed);
EXPECT_TRUE(IsMissing(2));
EXPECT_TRUE(IsMissing(1));
@@ -1270,16 +1213,16 @@ TEST_P(QuicConnectionTest, DuplicatePacket) {
TEST_P(QuicConnectionTest, PacketsOutOfOrderWithAdditionsAndLeastAwaiting) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(3);
+ ProcessPacket(kDefaultPathId, 3);
EXPECT_EQ(3u, outgoing_ack()->largest_observed);
EXPECT_TRUE(IsMissing(2));
EXPECT_TRUE(IsMissing(1));
- ProcessPacket(2);
+ ProcessPacket(kDefaultPathId, 2);
EXPECT_EQ(3u, outgoing_ack()->largest_observed);
EXPECT_TRUE(IsMissing(1));
- ProcessPacket(5);
+ ProcessPacket(kDefaultPathId, 5);
EXPECT_EQ(5u, outgoing_ack()->largest_observed);
EXPECT_TRUE(IsMissing(1));
EXPECT_TRUE(IsMissing(4));
@@ -1298,10 +1241,11 @@ TEST_P(QuicConnectionTest, PacketsOutOfOrderWithAdditionsAndLeastAwaiting) {
}
TEST_P(QuicConnectionTest, RejectPacketTooFarOut) {
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, _,
+ ConnectionCloseSource::FROM_SELF));
// Call ProcessDataPacket rather than ProcessPacket, as we should not get a
// packet call to the visitor.
- ProcessDataPacket(6000, 0, !kEntropyFlag);
+ ProcessDataPacket(kDefaultPathId, 6000, !kEntropyFlag);
EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) ==
nullptr);
}
@@ -1310,9 +1254,9 @@ TEST_P(QuicConnectionTest, RejectUnencryptedStreamData) {
// Process an unencrypted packet from the non-crypto stream.
frame1_.stream_id = 3;
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(visitor_,
- OnConnectionClosed(QUIC_UNENCRYPTED_STREAM_DATA, false));
- ProcessDataPacket(1, 0, !kEntropyFlag);
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_UNENCRYPTED_STREAM_DATA, _,
+ ConnectionCloseSource::FROM_SELF));
+ EXPECT_DFATAL(ProcessDataPacket(kDefaultPathId, 1, !kEntropyFlag), "");
EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) ==
nullptr);
const vector<QuicConnectionCloseFrame>& connection_close_frames =
@@ -1338,12 +1282,7 @@ TEST_P(QuicConnectionTest, TruncatedAck) {
lost_packets.insert(i * 2);
}
}
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
EXPECT_CALL(entropy_calculator_, EntropyHash(511))
.WillOnce(Return(static_cast<QuicPacketEntropyHash>(0)));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
@@ -1356,12 +1295,7 @@ TEST_P(QuicConnectionTest, TruncatedAck) {
// 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.
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
ProcessAckPacket(&frame);
EXPECT_EQ(num_packets, manager_->largest_observed());
@@ -1370,17 +1304,13 @@ TEST_P(QuicConnectionTest, TruncatedAck) {
TEST_P(QuicConnectionTest, AckReceiptCausesAckSendBadEntropy) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(1);
+ ProcessPacket(kDefaultPathId, 1);
// Delay sending, then queue up an ack.
- if (!FLAGS_quic_respect_send_alarm2) {
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
- .WillOnce(testing::Return(QuicTime::Delta::FromMicroseconds(1)));
- }
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(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
// Skip a packet and then record an ack.
QuicAckFrame frame = InitAckFrame(0);
@@ -1390,19 +1320,19 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSendBadEntropy) {
TEST_P(QuicConnectionTest, OutOfOrderReceiptCausesAckSend) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(3);
+ ProcessPacket(kDefaultPathId, 3);
// Should ack immediately since we have missing packets.
EXPECT_EQ(1u, writer_->packets_write_attempts());
- ProcessPacket(2);
+ ProcessPacket(kDefaultPathId, 2);
// Should ack immediately since we have missing packets.
EXPECT_EQ(2u, writer_->packets_write_attempts());
- ProcessPacket(1);
+ ProcessPacket(kDefaultPathId, 1);
// Should ack immediately, since this fills the last hole.
EXPECT_EQ(3u, writer_->packets_write_attempts());
- ProcessPacket(4);
+ ProcessPacket(kDefaultPathId, 4);
// Should not cause an ack.
EXPECT_EQ(3u, writer_->packets_write_attempts());
}
@@ -1438,17 +1368,10 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) {
QuicAckFrame frame = InitAckFrame(original);
NackPacket(original, &frame);
// First nack triggers early retransmit.
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(1);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
+ .WillOnce(SetArgPointee<3>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
QuicPacketNumber retransmission;
EXPECT_CALL(*send_algorithm_,
@@ -1460,12 +1383,7 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) {
QuicAckFrame frame2 = InitAckFrame(retransmission);
NackPacket(original, &frame2);
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
ProcessAckPacket(&frame2);
// Now if the peer sends an ack which still reports the retransmitted packet
@@ -1479,12 +1397,7 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) {
EXPECT_EQ(1u, writer_->stream_frames().size());
// No more packet loss for the rest of the test.
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _)).Times(AnyNumber());
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillRepeatedly(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _)).Times(AnyNumber());
ProcessAckPacket(&frame2);
EXPECT_CALL(*send_algorithm_,
OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA));
@@ -1544,8 +1457,8 @@ TEST_P(QuicConnectionTest, LeastUnackedLower) {
// one. This should cause a connection error.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 7);
- EXPECT_CALL(visitor_,
- OnConnectionClosed(QUIC_INVALID_STOP_WAITING_DATA, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_STOP_WAITING_DATA, _,
+ ConnectionCloseSource::FROM_SELF));
QuicStopWaitingFrame frame3 = InitStopWaitingFrame(1);
ProcessStopWaitingPacket(&frame3);
}
@@ -1560,8 +1473,9 @@ TEST_P(QuicConnectionTest, TooManySentPackets) {
// Ack packet 1, which leaves more than the limit outstanding.
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
- EXPECT_CALL(visitor_, OnConnectionClosed(
- QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS, false));
+ 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);
@@ -1573,12 +1487,13 @@ TEST_P(QuicConnectionTest, TooManySentPackets) {
TEST_P(QuicConnectionTest, TooManyReceivedPackets) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(visitor_, OnConnectionClosed(
- QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS, false));
+ 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(i);
+ ProcessPacket(kDefaultPathId, i);
if (!connection_.connected()) {
break;
}
@@ -1599,14 +1514,16 @@ TEST_P(QuicConnectionTest, LargestObservedLower) {
ProcessAckPacket(&frame2);
// Now change it to 1, and it should cause a connection error.
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_ACK_DATA, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_ACK_DATA, _,
+ ConnectionCloseSource::FROM_SELF));
EXPECT_CALL(visitor_, OnCanWrite()).Times(0);
ProcessAckPacket(&frame1);
}
TEST_P(QuicConnectionTest, AckUnsentData) {
// Ack a packet which has not been sent.
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_ACK_DATA, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_ACK_DATA, _,
+ ConnectionCloseSource::FROM_SELF));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
QuicAckFrame frame(MakeAckFrame(1));
@@ -1616,7 +1533,7 @@ TEST_P(QuicConnectionTest, AckUnsentData) {
TEST_P(QuicConnectionTest, AckAll) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(1);
+ ProcessPacket(kDefaultPathId, 1);
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 1);
QuicAckFrame frame1 = InitAckFrame(0);
@@ -1804,430 +1721,6 @@ TEST_P(QuicConnectionTest, RecordSentTimeBeforePacketSent) {
<< ". Actual time = " << actual_recorded_send_time.ToDebuggingValue();
}
-TEST_P(QuicConnectionTest, FECSending) {
- // All packets carry version info till version is negotiated.
- size_t payload_length;
- // GetPacketLengthForOneStream() assumes a stream offset of 0 in determining
- // packet length. The size of the offset field in a stream frame is 0 for
- // offset 0, and 2 for non-zero offsets up through 64K. Increase
- // max_packet_length by 2 so that subsequent packets containing subsequent
- // stream frames with non-zero offets will fit within the packet length.
- size_t length =
- 2 + GetPacketLengthForOneStream(connection_.version(), kIncludeVersion,
- PACKET_8BYTE_CONNECTION_ID,
- PACKET_1BYTE_PACKET_NUMBER, IN_FEC_GROUP,
- &payload_length);
- connection_.SetMaxPacketLength(length);
-
- if (generator_->fec_send_policy() == FEC_ALARM_TRIGGER) {
- // Send 4 protected data packets. FEC packet is not sent.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA))
- .Times(4);
- } else {
- // Send 4 protected data packets, which should also trigger 1 FEC packet.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA))
- .Times(5);
- }
- // The first stream frame will have 2 fewer overhead bytes than the other 3.
- const string payload(payload_length * 4 + 2, 'a');
- connection_.SendStreamDataWithStringWithFec(1, payload, 0, !kFin, nullptr);
- // Expect the FEC group to be closed after SendStreamDataWithString.
- EXPECT_FALSE(creator_->IsFecGroupOpen());
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-}
-
-TEST_P(QuicConnectionTest, FECQueueing) {
- // All packets carry version info till version is negotiated.
- size_t payload_length;
- size_t length = GetPacketLengthForOneStream(
- connection_.version(), kIncludeVersion, PACKET_8BYTE_CONNECTION_ID,
- PACKET_1BYTE_PACKET_NUMBER, IN_FEC_GROUP, &payload_length);
- connection_.SetMaxPacketLength(length);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_));
-
- EXPECT_EQ(0u, connection_.NumQueuedPackets());
- BlockOnNextWrite();
- const string payload(payload_length, 'a');
- connection_.SendStreamDataWithStringWithFec(1, payload, 0, !kFin, nullptr);
- EXPECT_FALSE(creator_->IsFecGroupOpen());
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
- if (generator_->fec_send_policy() == FEC_ALARM_TRIGGER) {
- // Expect the first data packet to be queued and not the FEC packet.
- EXPECT_EQ(1u, connection_.NumQueuedPackets());
- } else {
- // Expect the first data packet and the fec packet to be queued.
- EXPECT_EQ(2u, connection_.NumQueuedPackets());
- }
-}
-
-TEST_P(QuicConnectionTest, FECAlarmStoppedWhenFECPacketSent) {
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_));
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
-
- creator_->set_max_packets_per_fec_group(2);
-
- // 1 Data packet. FEC alarm should be set.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.SendStreamDataWithStringWithFec(3, "foo", 0, true, nullptr);
- EXPECT_TRUE(connection_.GetFecAlarm()->IsSet());
-
- if (generator_->fec_send_policy() == FEC_ALARM_TRIGGER) {
- // If FEC send policy is FEC_ALARM_TRIGGER, FEC packet is not sent.
- // FEC alarm should not be set.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- } else {
- // Second data packet triggers FEC packet out. FEC alarm should not be set.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA))
- .Times(2);
- }
- connection_.SendStreamDataWithStringWithFec(5, "foo", 0, true, nullptr);
- if (generator_->fec_send_policy() == FEC_ANY_TRIGGER) {
- EXPECT_TRUE(writer_->header().fec_flag);
- }
- EXPECT_FALSE(creator_->IsFecGroupOpen());
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
-}
-
-TEST_P(QuicConnectionTest, FECAlarmStoppedOnConnectionClose) {
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_));
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
- creator_->set_max_packets_per_fec_group(100);
-
- // 1 Data packet. FEC alarm should be set.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.SendStreamDataWithStringWithFec(3, "foo", 0, kFin, nullptr);
- EXPECT_TRUE(connection_.GetFecAlarm()->IsSet());
-
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_NO_ERROR, false));
- // Closing connection should stop the FEC alarm.
- connection_.CloseConnection(QUIC_NO_ERROR, /*from_peer=*/false);
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
-}
-
-TEST_P(QuicConnectionTest, RemoveFECFromInflightOnRetransmissionTimeout) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_));
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
-
- // 1 Data packet. FEC alarm should be set.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr);
- EXPECT_TRUE(connection_.GetFecAlarm()->IsSet());
- size_t protected_packet =
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_);
-
- // Force FEC timeout to send FEC packet out.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, 2u, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.GetFecAlarm()->Fire();
- EXPECT_TRUE(writer_->header().fec_flag);
-
- size_t fec_packet = protected_packet;
- EXPECT_EQ(protected_packet + fec_packet,
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
- clock_.AdvanceTime(DefaultRetransmissionTime());
-
- // On RTO, both data and FEC packets are removed from inflight, only the data
- // packet is retransmitted, and this retransmission (but not FEC) gets added
- // back into the inflight.
- EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- connection_.GetRetransmissionAlarm()->Fire();
-
- // The retransmission of packet 1 will be 3 bytes smaller than packet 1, since
- // the first transmission will have 1 byte for FEC group number and 2 bytes of
- // stream frame size, which are absent in the retransmission.
- size_t retransmitted_packet = protected_packet - 3;
- EXPECT_EQ(protected_packet + retransmitted_packet,
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
-
- // Receive ack for the retransmission. No data should be outstanding.
- QuicAckFrame ack = InitAckFrame(3);
- NackPacket(1, &ack);
- NackPacket(2, &ack);
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(1);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
- ProcessAckPacket(&ack);
-
- // Ensure the alarm is not set since all packets have been acked or abandoned.
- EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
-}
-
-TEST_P(QuicConnectionTest, RemoveFECFromInflightOnLossRetransmission) {
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_));
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
-
- // 1 FEC-protected data packet. FEC alarm should be set.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.SendStreamDataWithStringWithFec(3, "foo", 0, kFin, nullptr);
- EXPECT_TRUE(connection_.GetFecAlarm()->IsSet());
- size_t protected_packet =
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_);
-
- // Force FEC timeout to send FEC packet out.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.GetFecAlarm()->Fire();
- EXPECT_TRUE(writer_->header().fec_flag);
- size_t fec_packet = protected_packet;
- EXPECT_EQ(protected_packet + fec_packet,
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
-
- // Send more data to trigger NACKs. Note that all data starts at stream offset
- // 0 to ensure the same packet size, for ease of testing.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA))
- .Times(4);
- connection_.SendStreamDataWithString(5, "foo", 0, kFin, nullptr);
- connection_.SendStreamDataWithString(7, "foo", 0, kFin, nullptr);
- connection_.SendStreamDataWithString(9, "foo", 0, kFin, nullptr);
- connection_.SendStreamDataWithString(11, "foo", 0, kFin, nullptr);
-
- // An unprotected packet will be 3 bytes smaller than an FEC-protected packet,
- // since the protected packet will have 1 byte for FEC group number and
- // 2 bytes of stream frame size, which are absent in the unprotected packet.
- size_t unprotected_packet = protected_packet - 3;
- EXPECT_EQ(protected_packet + fec_packet + 4 * unprotected_packet,
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
-
- // Ack data packets, and NACK FEC packet and one data packet. Triggers
- // NACK-based loss detection of both packets, but only data packet is
- // retransmitted and considered outstanding.
- QuicAckFrame ack = InitAckFrame(6);
- NackPacket(2, &ack);
- NackPacket(3, &ack);
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
- lost_packets.push_back(std::make_pair(3, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(2);
- lost_packets.insert(3);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessAckPacket(&ack);
- // On receiving this ack from the server, the client will no longer send
- // version number in subsequent packets, including in this retransmission.
- size_t unprotected_packet_no_version = unprotected_packet - 4;
- EXPECT_EQ(unprotected_packet_no_version,
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
-
- // Receive ack for the retransmission. No data should be outstanding.
- QuicAckFrame ack2 = InitAckFrame(7);
- NackPacket(2, &ack2);
- NackPacket(3, &ack2);
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(PacketNumberSet()));
- }
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
- ProcessAckPacket(&ack2);
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
-}
-
-TEST_P(QuicConnectionTest, FECRemainsInflightOnTLPOfEarlierData) {
- // This test checks if TLP is sent correctly when a data and an FEC packet
- // are outstanding. TLP should be sent for the data packet when the
- // retransmission alarm fires.
- // Turn on TLP for this test.
- QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 1);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_));
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
-
- // 1 Data packet. FEC alarm should be set.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.SendStreamDataWithStringWithFec(3, "foo", 0, kFin, nullptr);
- EXPECT_TRUE(connection_.GetFecAlarm()->IsSet());
- size_t protected_packet =
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_);
- EXPECT_LT(0u, protected_packet);
-
- // Force FEC timeout to send FEC packet out.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, 2u, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.GetFecAlarm()->Fire();
- EXPECT_TRUE(writer_->header().fec_flag);
- size_t fec_packet = protected_packet;
- EXPECT_EQ(protected_packet + fec_packet,
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
-
- // TLP alarm should be set.
- QuicTime retransmission_time =
- connection_.GetRetransmissionAlarm()->deadline();
- EXPECT_NE(QuicTime::Zero(), retransmission_time);
- // Simulate the retransmission alarm firing and sending a TLP, so send
- // algorithm's OnRetransmissionTimeout is not called.
- clock_.AdvanceTime(retransmission_time.Subtract(clock_.Now()));
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, 3u, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.GetRetransmissionAlarm()->Fire();
- // The TLP retransmission of packet 1 will be 3 bytes smaller than packet 1,
- // since packet 1 will have 1 byte for FEC group number and 2 bytes of stream
- // frame size, which are absent in the the TLP retransmission.
- size_t tlp_packet = protected_packet - 3;
- EXPECT_EQ(protected_packet + fec_packet + tlp_packet,
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
-}
-
-TEST_P(QuicConnectionTest, FECRemainsInflightOnTLPOfLaterData) {
- // Tests if TLP is sent correctly when data packet 1 and an FEC packet are
- // sent followed by data packet 2, and data packet 1 is acked. TLP should be
- // sent for data packet 2 when the retransmission alarm fires. Turn on TLP for
- // this test.
- QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 1);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_));
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
-
- // 1 Data packet. FEC alarm should be set.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.SendStreamDataWithStringWithFec(3, "foo", 0, kFin, nullptr);
- EXPECT_TRUE(connection_.GetFecAlarm()->IsSet());
- size_t protected_packet =
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_);
- EXPECT_LT(0u, protected_packet);
-
- // Force FEC timeout to send FEC packet out.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, 2u, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.GetFecAlarm()->Fire();
- EXPECT_TRUE(writer_->header().fec_flag);
- // Protected data packet and FEC packet oustanding.
- size_t fec_packet = protected_packet;
- EXPECT_EQ(protected_packet + fec_packet,
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
-
- // Send 1 unprotected data packet. No FEC alarm should be set.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, 3u, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.SendStreamDataWithString(5, "foo", 0, kFin, nullptr);
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
- // Protected data packet, FEC packet, and unprotected data packet oustanding.
- // An unprotected packet will be 3 bytes smaller than an FEC-protected packet,
- // since the protected packet will have 1 byte for FEC group number and
- // 2 bytes of stream frame size, which are absent in the unprotected packet.
- size_t unprotected_packet = protected_packet - 3;
- EXPECT_EQ(protected_packet + fec_packet + unprotected_packet,
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
-
- // Receive ack for first data packet. FEC and second data packet are still
- // outstanding.
- QuicAckFrame ack = InitAckFrame(1);
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessAckPacket(&ack);
- // FEC packet and unprotected data packet oustanding.
- EXPECT_EQ(fec_packet + unprotected_packet,
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
-
- // TLP alarm should be set.
- QuicTime retransmission_time =
- connection_.GetRetransmissionAlarm()->deadline();
- EXPECT_NE(QuicTime::Zero(), retransmission_time);
- // Simulate the retransmission alarm firing and sending a TLP, so send
- // algorithm's OnRetransmissionTimeout is not called.
- clock_.AdvanceTime(retransmission_time.Subtract(clock_.Now()));
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, 4u, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.GetRetransmissionAlarm()->Fire();
-
- // Having received an ack from the server, the client will no longer send
- // version number in subsequent packets, including in this retransmission.
- size_t tlp_packet_no_version = unprotected_packet - 4;
- EXPECT_EQ(fec_packet + unprotected_packet + tlp_packet_no_version,
- QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
-}
-
-TEST_P(QuicConnectionTest, NoTLPForFECPacket) {
- // Turn on TLP for this test.
- QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 1);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_));
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- // Send 1 FEC-protected data packet. FEC alarm should be set.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr);
- EXPECT_TRUE(connection_.GetFecAlarm()->IsSet());
- // Force FEC timeout to send FEC packet out.
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA))
- .Times(1);
- connection_.GetFecAlarm()->Fire();
- EXPECT_TRUE(writer_->header().fec_flag);
-
- // Ack data packet, but not FEC packet.
- QuicAckFrame ack = InitAckFrame(1);
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
- ProcessAckPacket(&ack);
-
- // No TLP alarm for FEC, but retransmission alarm should be set for an RTO.
- EXPECT_LT(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
- EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
- QuicTime rto_time = connection_.GetRetransmissionAlarm()->deadline();
- EXPECT_NE(QuicTime::Zero(), rto_time);
-
- // Simulate the retransmission alarm firing. FEC packet is no longer
- // outstanding.
- clock_.AdvanceTime(rto_time.Subtract(clock_.Now()));
- connection_.GetRetransmissionAlarm()->Fire();
-
- EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
-}
-
TEST_P(QuicConnectionTest, FramePacking) {
// Send an ack and two stream frames in 1 packet by queueing them.
{
@@ -2288,34 +1781,11 @@ TEST_P(QuicConnectionTest, FramePackingCryptoThenNonCrypto) {
EXPECT_EQ(kClientDataStreamId1, writer_->stream_frames()[0]->stream_id);
}
-TEST_P(QuicConnectionTest, FramePackingFEC) {
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_));
-
- // Queue an ack and two stream frames. Ack gets flushed when FEC is turned on
- // for sending protected data; two stream frames are packed in 1 packet.
- {
- QuicConnection::ScopedPacketBundler bundler(&connection_,
- QuicConnection::SEND_ACK);
- connection_.SendStreamData3WithFec();
- connection_.SendStreamData5WithFec();
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- }
- EXPECT_EQ(0u, connection_.NumQueuedPackets());
- EXPECT_FALSE(connection_.HasQueuedData());
-
- // Parse the last packet and ensure it's in an fec group.
- EXPECT_EQ(2u, writer_->header().fec_group);
- EXPECT_EQ(2u, writer_->frame_count());
-
- // FEC alarm should be set.
- EXPECT_TRUE(connection_.GetFecAlarm()->IsSet());
-}
-
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(1, 1, kEntropyFlag);
+ ProcessDataPacket(kDefaultPathId, 1, kEntropyFlag);
EXPECT_CALL(visitor_, OnCanWrite())
.WillOnce(DoAll(IgnoreResult(InvokeWithoutArgs(
@@ -2353,8 +1823,7 @@ TEST_P(QuicConnectionTest, FramePackingSendv) {
iov[0].iov_len = 2;
iov[1].iov_base = data + 2;
iov[1].iov_len = 2;
- connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, !kFin,
- MAY_FEC_PROTECT, nullptr);
+ connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, !kFin, nullptr);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
@@ -2379,8 +1848,7 @@ TEST_P(QuicConnectionTest, FramePackingSendvQueued) {
iov[0].iov_len = 2;
iov[1].iov_base = data + 2;
iov[1].iov_len = 2;
- connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, !kFin,
- MAY_FEC_PROTECT, nullptr);
+ connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, !kFin, nullptr);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
EXPECT_TRUE(connection_.HasQueuedData());
@@ -2400,7 +1868,7 @@ TEST_P(QuicConnectionTest, SendingZeroBytes) {
// Send a zero byte write with a fin using writev.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
QuicIOVector empty_iov(nullptr, 0, 0);
- connection_.SendStreamData(1, empty_iov, 0, kFin, MAY_FEC_PROTECT, nullptr);
+ connection_.SendStreamData(1, empty_iov, 0, kFin, nullptr);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
@@ -2420,7 +1888,7 @@ TEST_P(QuicConnectionTest, OnCanWrite) {
IgnoreResult(InvokeWithoutArgs(
&connection_, &TestConnection::SendStreamData5))));
EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillOnce(Return(true));
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
connection_.OnCanWrite();
@@ -2451,17 +1919,10 @@ TEST_P(QuicConnectionTest, RetransmitOnNack) {
// Lose a packet and ensure it triggers retransmission.
QuicAckFrame nack_two = InitAckFrame(3);
NackPacket(2, &nack_two);
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(2);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
+ .WillOnce(SetArgPointee<3>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
EXPECT_CALL(*send_algorithm_,
OnPacketSent(_, _, _, second_packet_size - kQuicVersionSize, _))
@@ -2525,14 +1986,7 @@ TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnNack) {
QuicAckFrame nack_two = InitAckFrame(last_packet);
NackPacket(last_packet - 1, &nack_two);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(last_packet - 1);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
ProcessAckPacket(&nack_two);
@@ -2553,17 +2007,10 @@ TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnNack) {
QuicAckFrame nack_two = InitAckFrame(last_packet);
NackPacket(last_packet - 1, &nack_two);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(last_packet - 1, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(last_packet - 1);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ lost_packets.push_back(std::make_pair(last_packet - 1, kMaxPacketSize));
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
+ .WillOnce(SetArgPointee<3>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
if (version() > QUIC_VERSION_28) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
@@ -2592,6 +2039,8 @@ TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnRTO) {
}
TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnRTO) {
+ connection_.DisableTailLossProbe();
+
QuicStreamId stream_id = 2;
QuicPacketNumber last_packet;
SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet);
@@ -2610,7 +2059,7 @@ TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnRTO) {
clock_.AdvanceTime(DefaultRetransmissionTime());
connection_.GetRetransmissionAlarm()->Fire();
EXPECT_EQ(1u, writer_->frame_count());
- EXPECT_EQ(1u, writer_->rst_stream_frames().size());
+ ASSERT_EQ(1u, writer_->rst_stream_frames().size());
EXPECT_EQ(stream_id, writer_->rst_stream_frames().front().stream_id);
}
@@ -2628,12 +2077,7 @@ TEST_P(QuicConnectionTest, DoNotSendPendingRetransmissionForResetStream) {
PacketNumberSet lost_packets;
lost_packets.insert(last_packet - 1);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
ProcessAckPacket(&ack);
@@ -2662,17 +2106,10 @@ TEST_P(QuicConnectionTest, SendPendingRetransmissionForQuicRstStreamNoError) {
QuicAckFrame ack = InitAckFrame(last_packet);
NackPacket(last_packet - 1, &ack);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(last_packet - 1, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(last_packet - 1);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ lost_packets.push_back(std::make_pair(last_packet - 1, kMaxPacketSize));
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
+ .WillOnce(SetArgPointee<3>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
ProcessAckPacket(&ack);
@@ -2714,28 +2151,16 @@ TEST_P(QuicConnectionTest, DiscardRetransmit) {
// write blocked, so the packet will be queued.
BlockOnNextWrite();
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(2);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
+ .WillOnce(SetArgPointee<3>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
ProcessAckPacket(&nack_two);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
// Now, ack the previous transmission.
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
QuicAckFrame ack_all = InitAckFrame(3);
ProcessAckPacket(&ack_all);
@@ -2762,17 +2187,10 @@ TEST_P(QuicConnectionTest, RetransmitNackedLargestObserved) {
QuicAckFrame frame = InitAckFrame(1);
NackPacket(largest_observed, &frame);
// The first nack should retransmit the largest observed packet.
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(1);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
+ .WillOnce(SetArgPointee<3>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
EXPECT_CALL(*send_algorithm_,
OnPacketSent(_, _, _, packet_size - kQuicVersionSize, _));
@@ -2780,6 +2198,8 @@ TEST_P(QuicConnectionTest, RetransmitNackedLargestObserved) {
}
TEST_P(QuicConnectionTest, QueueAfterTwoRTOs) {
+ connection_.DisableTailLossProbe();
+
for (int i = 0; i < 10; ++i) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.SendStreamDataWithString(3, "foo", i * 3, !kFin, nullptr);
@@ -2892,21 +2312,12 @@ TEST_P(QuicConnectionTest, NoLimitPacketsPerNack) {
}
// 14 packets have been NACK'd and lost.
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- for (int i = 1; i < 15; ++i) {
- lost_packets.push_back(std::make_pair(i, kMaxPacketSize));
- }
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- for (int i = 1; i < 15; ++i) {
- lost_packets.insert(i);
- }
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ for (int i = 1; i < 15; ++i) {
+ lost_packets.push_back(std::make_pair(i, kMaxPacketSize));
}
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
+ .WillOnce(SetArgPointee<3>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(14);
ProcessAckPacket(&nack);
@@ -3001,118 +2412,6 @@ TEST_P(QuicConnectionTest, DontLatchUnackedPacket) {
EXPECT_EQ(6u, stop_waiting()->least_unacked);
}
-TEST_P(QuicConnectionTest, ReviveMissingPacketAfterFecPacket) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- // Don't send missing packet 1.
- ProcessFecPacket(2, 1, true, !kEntropyFlag, nullptr);
- // Entropy flag should be false, so entropy should be 0.
- EXPECT_EQ(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 2));
-}
-
-TEST_P(QuicConnectionTest, ReviveMissingPacketWithVaryingSeqNumLengths) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- // Set up a debug visitor to the connection.
- scoped_ptr<FecQuicConnectionDebugVisitor> fec_visitor(
- new FecQuicConnectionDebugVisitor());
- connection_.set_debug_visitor(fec_visitor.get());
-
- QuicPacketNumber fec_packet = 0;
- // clang-format off
- QuicPacketNumberLength lengths[] = {
- PACKET_6BYTE_PACKET_NUMBER, PACKET_4BYTE_PACKET_NUMBER,
- PACKET_2BYTE_PACKET_NUMBER, PACKET_1BYTE_PACKET_NUMBER};
- // clang-format on
- // For each packet number length size, revive a packet and check sequence
- // number length in the revived packet.
- for (size_t i = 0; i < arraysize(lengths); ++i) {
- // Set packet_number_length_ (for data and FEC packets).
- packet_number_length_ = lengths[i];
- fec_packet += 2;
- // Don't send missing packet, but send fec packet right after it.
- ProcessFecPacket(fec_packet, fec_packet - 1, true, !kEntropyFlag, nullptr);
- // packet number length in the revived header should be the same as
- // in the original data/fec packet headers.
- EXPECT_EQ(packet_number_length_,
- fec_visitor->revived_header().public_header.packet_number_length);
- }
-}
-
-TEST_P(QuicConnectionTest, ReviveMissingPacketWithVaryingConnectionIdLengths) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- // Set up a debug visitor to the connection.
- scoped_ptr<FecQuicConnectionDebugVisitor> fec_visitor(
- new FecQuicConnectionDebugVisitor());
- connection_.set_debug_visitor(fec_visitor.get());
-
- QuicPacketNumber fec_packet = 0;
- QuicConnectionIdLength lengths[] = {
- PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_CONNECTION_ID,
- PACKET_1BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID};
- // For each connection id length size, revive a packet and check connection
- // id length in the revived packet.
- for (size_t i = 0; i < arraysize(lengths); ++i) {
- // Set connection id length (for data and FEC packets).
- connection_id_length_ = lengths[i];
- fec_packet += 2;
- // Don't send missing packet, but send fec packet right after it.
- ProcessFecPacket(fec_packet, fec_packet - 1, true, !kEntropyFlag, nullptr);
- // Connection id length in the revived header should be the same as
- // in the original data/fec packet headers.
- EXPECT_EQ(connection_id_length_,
- fec_visitor->revived_header().public_header.connection_id_length);
- }
-}
-
-TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacketThenFecPacket) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- ProcessFecProtectedPacket(1, false, kEntropyFlag, !kHasStopWaiting);
- // Don't send missing packet 2.
- ProcessFecPacket(3, 1, true, !kEntropyFlag, nullptr);
- // Entropy flag should be true, so entropy should not be 0.
- EXPECT_NE(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 2));
-}
-
-TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacketsThenFecPacket) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- ProcessFecProtectedPacket(1, false, !kEntropyFlag, !kHasStopWaiting);
- // Don't send missing packet 2.
- ProcessFecProtectedPacket(3, false, !kEntropyFlag, !kHasStopWaiting);
- ProcessFecPacket(4, 1, true, kEntropyFlag, nullptr);
- // Ensure QUIC no longer revives entropy for lost packets.
- EXPECT_EQ(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 2));
- EXPECT_NE(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 4));
-}
-
-TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacket) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- // Don't send missing packet 1.
- ProcessFecPacket(3, 1, false, !kEntropyFlag, nullptr);
- // Out of order.
- ProcessFecProtectedPacket(2, true, !kEntropyFlag, !kHasStopWaiting);
- // Entropy flag should be false, so entropy should be 0.
- EXPECT_EQ(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 2));
-}
-
-TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPackets) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- ProcessFecProtectedPacket(1, false, !kEntropyFlag, !kHasStopWaiting);
- // Don't send missing packet 2.
- ProcessFecPacket(6, 1, false, kEntropyFlag, nullptr);
- ProcessFecProtectedPacket(3, false, kEntropyFlag, !kHasStopWaiting);
- ProcessFecProtectedPacket(4, false, kEntropyFlag, !kHasStopWaiting);
- ProcessFecProtectedPacket(5, true, !kEntropyFlag, !kHasStopWaiting);
- // Ensure entropy is not revived for the missing packet.
- EXPECT_EQ(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 2));
- EXPECT_NE(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 3));
-}
-
TEST_P(QuicConnectionTest, TLP) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 1);
@@ -3134,6 +2433,8 @@ TEST_P(QuicConnectionTest, TLP) {
}
TEST_P(QuicConnectionTest, RTO) {
+ connection_.DisableTailLossProbe();
+
QuicTime default_retransmission_time =
clock_.ApproximateNow().Add(DefaultRetransmissionTime());
SendStreamDataToPeer(3, "foo", 0, !kFin, nullptr);
@@ -3152,6 +2453,8 @@ TEST_P(QuicConnectionTest, RTO) {
}
TEST_P(QuicConnectionTest, RTOWithSameEncryptionLevel) {
+ connection_.DisableTailLossProbe();
+
QuicTime default_retransmission_time =
clock_.ApproximateNow().Add(DefaultRetransmissionTime());
use_tagging_decrypter();
@@ -3193,7 +2496,7 @@ TEST_P(QuicConnectionTest, SendHandshakeMessages) {
connection_.SetEncrypter(ENCRYPTION_NONE, new TaggingEncrypter(0x01));
// Attempt to send a handshake message and have the socket block.
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
BlockOnNextWrite();
connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr);
@@ -3321,7 +2624,7 @@ TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) {
// Process an encrypted packet which can not yet be decrypted which should
// result in the packet being buffered.
- ProcessDataPacketAtLevel(1, 0, kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, 1, kEntropyFlag, !kHasStopWaiting,
ENCRYPTION_INITIAL);
// Transition to the new encryption state and process another encrypted packet
@@ -3330,52 +2633,14 @@ TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) {
connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(2);
- ProcessDataPacketAtLevel(2, 0, kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, 2, kEntropyFlag, !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(3, 0, kEntropyFlag, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
-}
-
-TEST_P(QuicConnectionTest, ProcessBufferedFECGroup) {
- // SetFromConfig is always called after construction from InitializeSession.
- EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
- QuicConfig config;
- config.set_max_undecryptable_packets(100);
- connection_.SetFromConfig(config);
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- use_tagging_decrypter();
-
- const uint8_t tag = 0x07;
- framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
-
- // Don't send packet 1 and buffer initially encrypted packets.
- ProcessFecProtectedPacketAtLevel(2, 1, false, !kEntropyFlag, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
- ProcessFecPacketAtLevel(3, 1, false, kEntropyFlag, nullptr,
- ENCRYPTION_INITIAL);
- // Since the packets were buffered, no FEC group should be open.
- ASSERT_EQ(0u, connection_.NumFecGroups());
-
- // Now send non-fec protected ack packet and close the group.
- QuicStopWaitingFrame frame = InitStopWaitingFrame(4);
- ProcessStopWaitingPacketAtLevel(4, &frame, ENCRYPTION_INITIAL);
-
- // Transition to the new encryption state and process another encrypted packet
- // which should result in the original packets being processed. The missing
- // packet should be revived before the STOP_WAITING packet is processed.
- connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
- connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
-
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(2).RetiresOnSaturation();
- ProcessDataPacketAtLevel(5, 0, kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, 3, kEntropyFlag, !kHasStopWaiting,
ENCRYPTION_INITIAL);
- const QuicConnectionStats& stats = connection_.GetStats();
- EXPECT_EQ(1u, stats.packets_revived);
}
TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) {
@@ -3393,7 +2658,7 @@ TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) {
// 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(i, 0, kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, i, kEntropyFlag, !kHasStopWaiting,
ENCRYPTION_INITIAL);
}
@@ -3403,17 +2668,19 @@ TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) {
connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(101);
- ProcessDataPacketAtLevel(101, 0, kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, 101, kEntropyFlag, !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(102, 0, kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, 102, kEntropyFlag, !kHasStopWaiting,
ENCRYPTION_INITIAL);
}
TEST_P(QuicConnectionTest, TestRetransmitOrder) {
+ connection_.DisableTailLossProbe();
+
QuicByteCount first_packet_size;
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
.WillOnce(DoAll(SaveArg<3>(&first_packet_size), Return(true)));
@@ -3437,6 +2704,7 @@ TEST_P(QuicConnectionTest, TestRetransmitOrder) {
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(20));
{
InSequence s;
+ EXPECT_CALL(visitor_, OnPathDegrading());
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, first_packet_size, _));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, second_packet_size, _));
}
@@ -3456,6 +2724,8 @@ TEST_P(QuicConnectionTest, SetRTOAfterWritingToSocket) {
}
TEST_P(QuicConnectionTest, DelayRTOWithAckReceipt) {
+ connection_.DisableTailLossProbe();
+
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
connection_.SendStreamDataWithString(2, "foo", 0, !kFin, nullptr);
@@ -3494,6 +2764,8 @@ TEST_P(QuicConnectionTest, DelayRTOWithAckReceipt) {
}
TEST_P(QuicConnectionTest, TestQueued) {
+ connection_.DisableTailLossProbe();
+
EXPECT_EQ(0u, connection_.NumQueuedPackets());
BlockOnNextWrite();
connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr);
@@ -3505,61 +2777,6 @@ TEST_P(QuicConnectionTest, TestQueued) {
EXPECT_EQ(0u, connection_.NumQueuedPackets());
}
-TEST_P(QuicConnectionTest, CloseFecGroup) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- // Don't send missing packet 1.
- // Don't send missing packet 2.
- ProcessFecProtectedPacket(3, false, !kEntropyFlag, !kHasStopWaiting);
- // Don't send missing FEC packet 3.
- ASSERT_EQ(1u, connection_.NumFecGroups());
-
- // Now send non-fec protected ack packet and close the group.
- QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 4);
- QuicStopWaitingFrame frame = InitStopWaitingFrame(5);
- ProcessStopWaitingPacket(&frame);
- ASSERT_EQ(0u, connection_.NumFecGroups());
-}
-
-TEST_P(QuicConnectionTest, FailedToCloseFecGroupWithFecProtectedStopWaiting) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ValueRestore<bool> old_flag(&FLAGS_quic_drop_non_awaited_packets, false);
- // Don't send missing packet 1.
- ProcessFecProtectedPacket(2, false, !kEntropyFlag, !kHasStopWaiting);
- EXPECT_EQ(1u, connection_.NumFecGroups());
- stop_waiting_ = InitStopWaitingFrame(3);
- ProcessFecProtectedPacket(3, false, !kEntropyFlag, kHasStopWaiting);
- // This Fec group would be closed but created again.
- EXPECT_EQ(1u, connection_.NumFecGroups());
-}
-
-TEST_P(QuicConnectionTest,
- CloseFecGroupUnderStopWaitingAndWaitingForPacketsBelowStopWaiting) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ValueRestore<bool> old_flag(&FLAGS_quic_drop_non_awaited_packets, true);
- // Don't send missing packet 1.
- ProcessFecProtectedPacket(2, false, !kEntropyFlag, !kHasStopWaiting);
- EXPECT_EQ(1u, connection_.NumFecGroups());
- stop_waiting_ = InitStopWaitingFrame(2);
- ProcessFecProtectedPacket(3, false, !kEntropyFlag, kHasStopWaiting);
- // This Fec group would be closed.
- EXPECT_EQ(0u, connection_.NumFecGroups());
-}
-
-TEST_P(QuicConnectionTest,
- DoNotCloseFecGroupUnderStopWaitingButNotWaitingForPacketsBelow) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ValueRestore<bool> old_flag(&FLAGS_quic_drop_non_awaited_packets, true);
- ProcessFecProtectedPacket(1, false, !kEntropyFlag, !kHasStopWaiting);
- ProcessFecProtectedPacket(2, false, !kEntropyFlag, !kHasStopWaiting);
- // Don't send missing packet 3.
- EXPECT_EQ(1u, connection_.NumFecGroups());
- stop_waiting_ = InitStopWaitingFrame(2);
- ProcessFecProtectedPacket(3, false, !kEntropyFlag, kHasStopWaiting);
- // This group will not be closed because this group is not waiting for packets
- // below stop waiting.
- EXPECT_EQ(1u, connection_.NumFecGroups());
-}
-
TEST_P(QuicConnectionTest, InitialTimeout) {
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
@@ -3574,7 +2791,8 @@ TEST_P(QuicConnectionTest, InitialTimeout) {
QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1));
EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_NETWORK_IDLE_TIMEOUT, _,
+ ConnectionCloseSource::FROM_SELF));
// Simulate the timeout alarm firing.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1));
connection_.GetTimeoutAlarm()->Fire();
@@ -3584,23 +2802,22 @@ TEST_P(QuicConnectionTest, InitialTimeout) {
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
EXPECT_FALSE(connection_.GetPingAlarm()->IsSet());
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
EXPECT_FALSE(connection_.GetResumeWritesAlarm()->IsSet());
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
EXPECT_FALSE(connection_.GetSendAlarm()->IsSet());
EXPECT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet());
}
-TEST_P(QuicConnectionTest, OverallTimeout) {
- // Use a shorter overall connection timeout than idle timeout for this test.
+TEST_P(QuicConnectionTest, HandshakeTimeout) {
+ // Use a shorter handshake timeout than idle timeout for this test.
const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
connection_.SetNetworkTimeouts(timeout, timeout);
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
- QuicTime overall_timeout = clock_.ApproximateNow().Add(timeout).Subtract(
+ QuicTime handshake_timeout = clock_.ApproximateNow().Add(timeout).Subtract(
QuicTime::Delta::FromSeconds(1));
- EXPECT_EQ(overall_timeout, connection_.GetTimeoutAlarm()->deadline());
+ EXPECT_EQ(handshake_timeout, connection_.GetTimeoutAlarm()->deadline());
EXPECT_TRUE(connection_.connected());
// Send and ack new data 3 seconds later to lengthen the idle timeout.
@@ -3618,8 +2835,8 @@ TEST_P(QuicConnectionTest, OverallTimeout) {
clock_.AdvanceTime(timeout.Subtract(QuicTime::Delta::FromSeconds(2)));
- EXPECT_CALL(visitor_,
- OnConnectionClosed(QUIC_CONNECTION_OVERALL_TIMED_OUT, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_HANDSHAKE_TIMEOUT, _,
+ ConnectionCloseSource::FROM_SELF));
// Simulate the timeout alarm firing.
connection_.GetTimeoutAlarm()->Fire();
@@ -3628,7 +2845,6 @@ TEST_P(QuicConnectionTest, OverallTimeout) {
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
EXPECT_FALSE(connection_.GetPingAlarm()->IsSet());
- EXPECT_FALSE(connection_.GetFecAlarm()->IsSet());
EXPECT_FALSE(connection_.GetResumeWritesAlarm()->IsSet());
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
EXPECT_FALSE(connection_.GetSendAlarm()->IsSet());
@@ -3903,113 +3119,13 @@ TEST_P(QuicConnectionTest, NoMtuDiscoveryAfterConnectionClosed) {
/*fin=*/false, nullptr);
EXPECT_TRUE(connection_.GetMtuDiscoveryAlarm()->IsSet());
- EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
- connection_.CloseConnection(QUIC_INTERNAL_ERROR, /*from_peer=*/false);
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _));
+ connection_.CloseConnection(QUIC_PEER_GOING_AWAY, "no reason",
+ ConnectionCloseBehavior::SILENT_CLOSE);
EXPECT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet());
}
-TEST_P(QuicConnectionTest, OldTimeoutAfterSend) {
- ValueRestore<bool> old_flags(&FLAGS_quic_use_new_idle_timeout, false);
- EXPECT_TRUE(connection_.connected());
- EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
- QuicConfig config;
- connection_.SetFromConfig(config);
- EXPECT_FALSE(QuicConnectionPeer::IsSilentCloseEnabled(&connection_));
-
- const QuicTime::Delta initial_idle_timeout =
- QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1);
- const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5);
- QuicTime default_timeout = clock_.ApproximateNow().Add(initial_idle_timeout);
-
- // When we send a packet, the timeout will change to 5ms +
- // kInitialIdleTimeoutSecs.
- clock_.AdvanceTime(five_ms);
-
- // Send an ack so we don't set the retransmission alarm.
- SendAckPacketToPeer();
- EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
-
- // The original alarm will fire. We should not time out because we had a
- // network event at t=5ms. The alarm will reregister.
- clock_.AdvanceTime(initial_idle_timeout.Subtract(five_ms));
- EXPECT_EQ(default_timeout, clock_.ApproximateNow());
- connection_.GetTimeoutAlarm()->Fire();
- EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
- EXPECT_TRUE(connection_.connected());
- EXPECT_EQ(default_timeout.Add(five_ms),
- connection_.GetTimeoutAlarm()->deadline());
-
- // This time, we should time out.
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
- clock_.AdvanceTime(five_ms);
- EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow());
- connection_.GetTimeoutAlarm()->Fire();
- EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
- EXPECT_FALSE(connection_.connected());
-}
-
-TEST_P(QuicConnectionTest, OldTimeoutAfterSendSilentClose) {
- ValueRestore<bool> old_flags(&FLAGS_quic_use_new_idle_timeout, false);
- // Same test as above, but complete a handshake which enables silent close,
- // causing no connection close packet to be sent.
- EXPECT_TRUE(connection_.connected());
- EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
- QuicConfig config;
-
- // Create a handshake message that also enables silent close.
- CryptoHandshakeMessage msg;
- string error_details;
- QuicConfig client_config;
- client_config.SetInitialStreamFlowControlWindowToSend(
- kInitialStreamFlowControlWindowForTest);
- client_config.SetInitialSessionFlowControlWindowToSend(
- kInitialSessionFlowControlWindowForTest);
- client_config.SetIdleConnectionStateLifetime(
- QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs),
- QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs));
- client_config.ToHandshakeMessage(&msg);
- const QuicErrorCode error =
- config.ProcessPeerHello(msg, CLIENT, &error_details);
- EXPECT_EQ(QUIC_NO_ERROR, error);
-
- connection_.SetFromConfig(config);
- EXPECT_TRUE(QuicConnectionPeer::IsSilentCloseEnabled(&connection_));
-
- const QuicTime::Delta default_idle_timeout =
- QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs - 1);
- const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5);
- QuicTime default_timeout = clock_.ApproximateNow().Add(default_idle_timeout);
-
- // When we send a packet, the timeout will change to 5ms +
- // kInitialIdleTimeoutSecs.
- clock_.AdvanceTime(five_ms);
-
- // Send an ack so we don't set the retransmission alarm.
- SendAckPacketToPeer();
- EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
-
- // The original alarm will fire. We should not time out because we had a
- // network event at t=5ms. The alarm will reregister.
- clock_.AdvanceTime(default_idle_timeout.Subtract(five_ms));
- EXPECT_EQ(default_timeout, clock_.ApproximateNow());
- connection_.GetTimeoutAlarm()->Fire();
- EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
- EXPECT_TRUE(connection_.connected());
- EXPECT_EQ(default_timeout.Add(five_ms),
- connection_.GetTimeoutAlarm()->deadline());
-
- // This time, we should time out.
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
- clock_.AdvanceTime(five_ms);
- EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow());
- connection_.GetTimeoutAlarm()->Fire();
- EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
- EXPECT_FALSE(connection_.connected());
-}
-
TEST_P(QuicConnectionTest, TimeoutAfterSend) {
- ValueRestore<bool> old_flags(&FLAGS_quic_use_new_idle_timeout, true);
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
QuicConfig config;
@@ -4044,7 +3160,8 @@ TEST_P(QuicConnectionTest, TimeoutAfterSend) {
connection_.GetTimeoutAlarm()->deadline());
// This time, we should time out.
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_NETWORK_IDLE_TIMEOUT, _,
+ ConnectionCloseSource::FROM_SELF));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
clock_.AdvanceTime(five_ms);
EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow());
@@ -4054,7 +3171,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterSend) {
}
TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) {
- ValueRestore<bool> old_flags(&FLAGS_quic_use_new_idle_timeout, true);
// Same test as above, but complete a handshake which enables silent close,
// causing no connection close packet to be sent.
EXPECT_TRUE(connection_.connected());
@@ -4108,7 +3224,8 @@ TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) {
connection_.GetTimeoutAlarm()->deadline());
// This time, we should time out.
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_NETWORK_IDLE_TIMEOUT, _,
+ ConnectionCloseSource::FROM_SELF));
clock_.AdvanceTime(five_ms);
EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow());
connection_.GetTimeoutAlarm()->Fire();
@@ -4154,7 +3271,8 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceive) {
connection_.GetTimeoutAlarm()->deadline());
// This time, we should time out.
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_NETWORK_IDLE_TIMEOUT, _,
+ ConnectionCloseSource::FROM_SELF));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
clock_.AdvanceTime(five_ms);
EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow());
@@ -4164,7 +3282,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceive) {
}
TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) {
- ValueRestore<bool> old_flags(&FLAGS_quic_use_new_idle_timeout, true);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
@@ -4209,7 +3326,8 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) {
// Now, send packets while advancing the time and verify that the connection
// eventually times out.
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_NETWORK_IDLE_TIMEOUT, _,
+ ConnectionCloseSource::FROM_SELF));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
for (int i = 0; i < 100 && connection_.connected(); ++i) {
VLOG(1) << "sending data packet";
@@ -4222,34 +3340,71 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) {
EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
}
+TEST_P(QuicConnectionTest, TimeoutAfter5RTOs) {
+ FLAGS_quic_enable_rto_timeout = true;
+ QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 2);
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ QuicConfig config;
+ QuicTagVector connection_options;
+ connection_options.push_back(k5RTO);
+ config.SetConnectionOptionsToSend(connection_options);
+ connection_.SetFromConfig(config);
+
+ // Send stream data.
+ SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr);
+
+ EXPECT_CALL(visitor_, OnPathDegrading());
+ // Fire the retransmission alarm 6 times, twice for TLP and 4 times for RTO.
+ for (int i = 0; i < 6; ++i) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ connection_.GetRetransmissionAlarm()->Fire();
+ EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
+ EXPECT_TRUE(connection_.connected());
+ }
+
+ EXPECT_EQ(2u, connection_.sent_packet_manager().consecutive_tlp_count());
+ EXPECT_EQ(4u, connection_.sent_packet_manager().consecutive_rto_count());
+ // This time, we should time out.
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_TOO_MANY_RTOS, _,
+ ConnectionCloseSource::FROM_SELF));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ connection_.GetRetransmissionAlarm()->Fire();
+ EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
+ EXPECT_FALSE(connection_.connected());
+}
+
TEST_P(QuicConnectionTest, SendScheduler) {
// Test that if we send a packet without delay, it is not queued.
QuicPacket* packet =
- ConstructDataPacket(1, 0, !kEntropyFlag, !kHasStopWaiting);
+ ConstructDataPacket(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
- connection_.SendPacket(ENCRYPTION_NONE, 1, packet, kTestEntropyHash,
- HAS_RETRANSMITTABLE_DATA, false, false);
+ connection_.SendPacket(ENCRYPTION_NONE, kDefaultPathId, 1, packet,
+ kTestEntropyHash, HAS_RETRANSMITTABLE_DATA, false,
+ false);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
}
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);
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(1);
QuicPacket* packet =
- ConstructDataPacket(1, 0, !kEntropyFlag, !kHasStopWaiting);
+ ConstructDataPacket(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting);
writer_->SetShouldWriteFail();
- connection_.SendPacket(ENCRYPTION_NONE, 1, packet, kTestEntropyHash,
- HAS_RETRANSMITTABLE_DATA, false, false);
+ connection_.SendPacket(ENCRYPTION_NONE, kDefaultPathId, 1, packet,
+ kTestEntropyHash, HAS_RETRANSMITTABLE_DATA, false,
+ false);
}
TEST_P(QuicConnectionTest, SendSchedulerEAGAIN) {
QuicPacket* packet =
- ConstructDataPacket(1, 0, !kEntropyFlag, !kHasStopWaiting);
+ ConstructDataPacket(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting);
BlockOnNextWrite();
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0);
- connection_.SendPacket(ENCRYPTION_NONE, 1, packet, kTestEntropyHash,
- HAS_RETRANSMITTABLE_DATA, false, false);
+ connection_.SendPacket(ENCRYPTION_NONE, kDefaultPathId, 1, packet,
+ kTestEntropyHash, HAS_RETRANSMITTABLE_DATA, false,
+ false);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
}
@@ -4257,12 +3412,12 @@ TEST_P(QuicConnectionTest, TestQueueLimitsOnSendStreamData) {
// All packets carry version info till version is negotiated.
size_t payload_length;
size_t length = GetPacketLengthForOneStream(
- connection_.version(), kIncludeVersion, PACKET_8BYTE_CONNECTION_ID,
- PACKET_1BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP, &payload_length);
+ connection_.version(), kIncludeVersion, !kIncludePathId,
+ PACKET_8BYTE_CONNECTION_ID, PACKET_1BYTE_PACKET_NUMBER, &payload_length);
connection_.SetMaxPacketLength(length);
// Queue the first packet.
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(testing::Return(QuicTime::Delta::FromMicroseconds(10)));
const string payload(payload_length, 'a');
EXPECT_EQ(0u,
@@ -4279,11 +3434,10 @@ TEST_P(QuicConnectionTest, LoopThroughSendingPackets) {
// offset 0, and 2 for non-zero offsets up through 16K. Increase
// max_packet_length by 2 so that subsequent packets containing subsequent
// stream frames with non-zero offets will fit within the packet length.
- size_t length =
- 2 + GetPacketLengthForOneStream(connection_.version(), kIncludeVersion,
- PACKET_8BYTE_CONNECTION_ID,
- PACKET_1BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP, &payload_length);
+ size_t length = 2 + GetPacketLengthForOneStream(
+ connection_.version(), kIncludeVersion,
+ !kIncludePathId, PACKET_8BYTE_CONNECTION_ID,
+ PACKET_1BYTE_PACKET_NUMBER, &payload_length);
connection_.SetMaxPacketLength(length);
// Queue the first packet.
@@ -4356,7 +3510,7 @@ TEST_P(QuicConnectionTest, SendDelayedAck) {
// The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1, 0, !kEntropyFlag, !kHasStopWaiting,
+ ProcessDataPacketAtLevel(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting,
ENCRYPTION_INITIAL);
// Check if delayed ack timer is running for the expected interval.
@@ -4372,7 +3526,7 @@ TEST_P(QuicConnectionTest, SendDelayedAck) {
}
TEST_P(QuicConnectionTest, SendDelayedAckDecimation) {
- QuicConnectionPeer::EnableAckDecimation(&connection_);
+ QuicConnectionPeer::SetAckMode(&connection_, QuicConnection::ACK_DECIMATION);
const size_t kMinRttMs = 40;
RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager_);
@@ -4394,14 +3548,14 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimation) {
QuicPacketNumber kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1 + i, 0, !kEntropyFlag, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kEntropyFlag,
+ !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(kFirstDecimatedPacket, 0, !kEntropyFlag,
+ ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket, !kEntropyFlag,
!kHasStopWaiting, ENCRYPTION_INITIAL);
// Check if delayed ack timer is running for the expected interval.
@@ -4412,9 +3566,146 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimation) {
for (int i = 0; i < 9; ++i) {
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(kFirstDecimatedPacket + 1 + i, 0, !kEntropyFlag,
+ ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i,
+ !kEntropyFlag, !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());
+ EXPECT_FALSE(writer_->ack_frames().empty());
+ EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+}
+
+TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) {
+ FLAGS_quic_ack_decimation2 = true;
+ QuicConnectionPeer::SetAckMode(
+ &connection_, QuicConnection::ACK_DECIMATION_WITH_REORDERING);
+
+ const size_t kMinRttMs = 40;
+ RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager_);
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kMinRttMs),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ // The ack time should be based on min_rtt/4, since it's less than the
+ // default delayed ack time.
+ QuicTime ack_time = clock_.ApproximateNow().Add(
+ QuicTime::Delta::FromMilliseconds(kMinRttMs / 4));
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+ const uint8_t tag = 0x07;
+ connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
+ framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ // Process a packet from the non-crypto stream.
+ frame1_.stream_id = 3;
+
+ // Process all the initial packets in order so there aren't missing packets.
+ 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);
+ }
+ 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,
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
+
+ // Check if delayed ack timer is running for the expected interval.
+ EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+ EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
+
+ // 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);
+ ack_time = clock_.ApproximateNow().Add(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+ EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
+
+ // The 10th received packet causes an ack to be sent.
+ for (int i = 0; i < 8; ++i) {
+ EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i,
+ !kEntropyFlag, !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());
+ EXPECT_FALSE(writer_->ack_frames().empty());
+ EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+}
+
+TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
+ FLAGS_quic_ack_decimation2 = true;
+ QuicConnectionPeer::SetAckMode(
+ &connection_, QuicConnection::ACK_DECIMATION_WITH_REORDERING);
+
+ const size_t kMinRttMs = 40;
+ RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager_);
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kMinRttMs),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ // The ack time should be based on min_rtt/4, since it's less than the
+ // default delayed ack time.
+ QuicTime ack_time = clock_.ApproximateNow().Add(
+ QuicTime::Delta::FromMilliseconds(kMinRttMs / 4));
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+ const uint8_t tag = 0x07;
+ connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
+ framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ // Process a packet from the non-crypto stream.
+ frame1_.stream_id = 3;
+
+ // Process all the initial packets in order so there aren't missing packets.
+ 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);
}
+ 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,
+ !kHasStopWaiting, ENCRYPTION_INITIAL);
+
+ // Check if delayed ack timer is running for the expected interval.
+ EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+ EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
+
+ // 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);
+ ack_time = clock_.ApproximateNow().Add(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+ EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
+
+ // The 10th received packet causes an ack to be sent.
+ for (int i = 0; i < 8; ++i) {
+ EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i,
+ !kEntropyFlag, !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());
+ EXPECT_FALSE(writer_->ack_frames().empty());
+ EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+
+ // The next packet received in order will cause an immediate ack,
+ // because it fills a hole.
+ EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 10,
+ !kEntropyFlag, !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());
@@ -4424,7 +3715,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimation) {
TEST_P(QuicConnectionTest, SendDelayedAckOnHandshakeConfirmed) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(1);
+ ProcessPacket(kDefaultPathId, 1);
// Check that ack is sent and that delayed ack alarm is set.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
QuicTime ack_time = clock_.ApproximateNow().Add(DefaultDelayedAckTime());
@@ -4445,8 +3736,8 @@ TEST_P(QuicConnectionTest, SendDelayedAckOnHandshakeConfirmed) {
TEST_P(QuicConnectionTest, SendDelayedAckOnSecondPacket) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(1);
- ProcessPacket(2);
+ ProcessPacket(kDefaultPathId, 1);
+ ProcessPacket(kDefaultPathId, 2);
// 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());
@@ -4457,32 +3748,32 @@ TEST_P(QuicConnectionTest, SendDelayedAckOnSecondPacket) {
TEST_P(QuicConnectionTest, NoAckOnOldNacks) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Drop one packet, triggering a sequence of acks.
- ProcessPacket(2);
+ ProcessPacket(kDefaultPathId, 2);
size_t frames_per_ack = 2;
EXPECT_EQ(frames_per_ack, writer_->frame_count());
EXPECT_FALSE(writer_->ack_frames().empty());
writer_->Reset();
- ProcessPacket(3);
+ ProcessPacket(kDefaultPathId, 3);
EXPECT_EQ(frames_per_ack, writer_->frame_count());
EXPECT_FALSE(writer_->ack_frames().empty());
writer_->Reset();
- ProcessPacket(4);
+ ProcessPacket(kDefaultPathId, 4);
EXPECT_EQ(frames_per_ack, writer_->frame_count());
EXPECT_FALSE(writer_->ack_frames().empty());
writer_->Reset();
- ProcessPacket(5);
+ ProcessPacket(kDefaultPathId, 5);
EXPECT_EQ(frames_per_ack, writer_->frame_count());
EXPECT_FALSE(writer_->ack_frames().empty());
writer_->Reset();
// Now only set the timer on the 6th packet, instead of sending another ack.
- ProcessPacket(6);
+ ProcessPacket(kDefaultPathId, 6);
EXPECT_EQ(0u, writer_->frame_count());
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
}
TEST_P(QuicConnectionTest, SendDelayedAckOnOutgoingPacket) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(1);
+ ProcessPacket(kDefaultPathId, 1);
connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin,
nullptr);
// Check that ack is bundled with outgoing data and that delayed ack
@@ -4495,7 +3786,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckOnOutgoingPacket) {
TEST_P(QuicConnectionTest, SendDelayedAckOnOutgoingCryptoPacket) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(1);
+ ProcessPacket(kDefaultPathId, 1);
connection_.SendStreamDataWithString(kCryptoStreamId, "foo", 0, !kFin,
nullptr);
// Check that ack is bundled with outgoing crypto data.
@@ -4506,7 +3797,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckOnOutgoingCryptoPacket) {
TEST_P(QuicConnectionTest, BlockAndBufferOnFirstCHLOPacketOfTwo) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(1);
+ ProcessPacket(kDefaultPathId, 1);
BlockOnNextWrite();
writer_->set_is_write_blocked_data_buffered(true);
connection_.SendStreamDataWithString(kCryptoStreamId, "foo", 0, !kFin,
@@ -4528,7 +3819,7 @@ TEST_P(QuicConnectionTest, BundleAckForSecondCHLO) {
// Process a packet from the crypto stream, which is frame1_'s default.
// Receiving the CHLO as packet 2 first will cause the connection to
// immediately send an ack, due to the packet gap.
- ProcessPacket(2);
+ ProcessPacket(kDefaultPathId, 2);
// Check that ack is sent and that delayed ack alarm is reset.
EXPECT_EQ(3u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
@@ -4546,17 +3837,10 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) {
// Ack the second packet, which will retransmit the first packet.
QuicAckFrame ack = InitAckFrame(2);
NackPacket(1, &ack);
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(1);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
+ .WillOnce(SetArgPointee<3>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
ProcessAckPacket(&ack);
EXPECT_EQ(1u, writer_->frame_count());
@@ -4567,12 +3851,7 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) {
// and see if there is more data to send.
ack = InitAckFrame(3);
NackPacket(1, &ack);
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
ProcessAckPacket(&ack);
@@ -4584,12 +3863,7 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) {
// Send the same ack, but send both data and an ack together.
ack = InitAckFrame(3);
NackPacket(1, &ack);
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
EXPECT_CALL(visitor_, OnCanWrite())
.WillOnce(IgnoreResult(InvokeWithoutArgs(
&connection_, &TestConnection::EnsureWritableAndSendStreamData5)));
@@ -4606,23 +3880,27 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) {
TEST_P(QuicConnectionTest, NoAckSentForClose) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(1);
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, true));
+ ProcessPacket(kDefaultPathId, 1);
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, _,
+ ConnectionCloseSource::FROM_PEER));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- ProcessClosePacket(2, 0);
+ ProcessClosePacket(kDefaultPathId, 2);
}
TEST_P(QuicConnectionTest, SendWhenDisconnected) {
EXPECT_TRUE(connection_.connected());
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, false));
- connection_.CloseConnection(QUIC_PEER_GOING_AWAY, false);
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, _,
+ ConnectionCloseSource::FROM_SELF));
+ connection_.CloseConnection(QUIC_PEER_GOING_AWAY, "no reason",
+ ConnectionCloseBehavior::SILENT_CLOSE);
EXPECT_FALSE(connection_.connected());
EXPECT_FALSE(connection_.CanWriteStreamData());
QuicPacket* packet =
- ConstructDataPacket(1, 0, !kEntropyFlag, !kHasStopWaiting);
+ ConstructDataPacket(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0);
- connection_.SendPacket(ENCRYPTION_NONE, 1, packet, kTestEntropyHash,
- HAS_RETRANSMITTABLE_DATA, false, false);
+ connection_.SendPacket(ENCRYPTION_NONE, kDefaultPathId, 1, packet,
+ kTestEntropyHash, HAS_RETRANSMITTABLE_DATA, false,
+ false);
}
TEST_P(QuicConnectionTest, PublicReset) {
@@ -4633,8 +3911,11 @@ TEST_P(QuicConnectionTest, PublicReset) {
header.rejected_packet_number = 10101;
scoped_ptr<QuicEncryptedPacket> packet(
framer_.BuildPublicResetPacket(header));
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PUBLIC_RESET, true));
- connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *packet);
+ scoped_ptr<QuicReceivedPacket> received(
+ ConstructReceivedPacket(*packet, QuicTime::Zero()));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PUBLIC_RESET, _,
+ ConnectionCloseSource::FROM_PEER));
+ connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
}
TEST_P(QuicConnectionTest, GoAway) {
@@ -4667,10 +3948,19 @@ TEST_P(QuicConnectionTest, Blocked) {
ProcessFramePacket(QuicFrame(&blocked));
}
+TEST_P(QuicConnectionTest, PathClose) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+
+ QuicPathCloseFrame path_close = QuicPathCloseFrame(1);
+ ProcessPathClosePacket(&path_close);
+ EXPECT_TRUE(QuicFramerPeer::IsPathClosed(
+ QuicConnectionPeer::GetFramer(&connection_), 1));
+}
+
TEST_P(QuicConnectionTest, ZeroBytePacket) {
// Don't close the connection for zero byte packets.
- EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(0);
- QuicEncryptedPacket encrypted(nullptr, 0);
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(0);
+ QuicReceivedPacket encrypted(nullptr, 0, QuicTime::Zero());
connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, encrypted);
}
@@ -4686,30 +3976,19 @@ TEST_P(QuicConnectionTest, MissingPacketsBeforeLeastUnacked) {
TEST_P(QuicConnectionTest, ReceivedEntropyHashCalculation) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AtLeast(1));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessDataPacket(1, 1, kEntropyFlag);
- ProcessDataPacket(4, 1, kEntropyFlag);
- ProcessDataPacket(3, 1, !kEntropyFlag);
- ProcessDataPacket(7, 1, kEntropyFlag);
- EXPECT_EQ(146u, outgoing_ack()->entropy_hash);
-}
-
-TEST_P(QuicConnectionTest, ReceivedEntropyHashCalculationHalfFEC) {
- // FEC packets should not change the entropy hash calculation.
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AtLeast(1));
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessDataPacket(1, 1, kEntropyFlag);
- ProcessFecPacket(4, 1, false, kEntropyFlag, nullptr);
- ProcessDataPacket(3, 3, !kEntropyFlag);
- ProcessFecPacket(7, 3, false, kEntropyFlag, nullptr);
+ 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) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AtLeast(1));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessDataPacket(1, 1, kEntropyFlag);
- ProcessDataPacket(5, 1, kEntropyFlag);
- ProcessDataPacket(4, 1, !kEntropyFlag);
+ 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);
@@ -4728,9 +4007,9 @@ TEST_P(QuicConnectionTest, UpdateEntropyForReceivedPackets) {
TEST_P(QuicConnectionTest, UpdateEntropyHashUptoCurrentPacket) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AtLeast(1));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessDataPacket(1, 1, kEntropyFlag);
- ProcessDataPacket(5, 1, !kEntropyFlag);
- ProcessDataPacket(22, 1, kEntropyFlag);
+ 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;
@@ -4741,7 +4020,7 @@ TEST_P(QuicConnectionTest, UpdateEntropyHashUptoCurrentPacket) {
ack_entropy_hash = ProcessStopWaitingPacket(&frame);
EXPECT_EQ((random_entropy_hash + ack_entropy_hash),
outgoing_ack()->entropy_hash);
- ProcessDataPacket(25, 1, kEntropyFlag);
+ ProcessDataPacket(kDefaultPathId, 25, kEntropyFlag);
EXPECT_EQ((random_entropy_hash + ack_entropy_hash + (1 << (25 % 8))),
outgoing_ack()->entropy_hash);
}
@@ -4763,7 +4042,7 @@ TEST_P(QuicConnectionTest, EntropyCalculationForTruncatedAck) {
} else {
entropy[i] = entropy[i - 1];
}
- ProcessDataPacket(i, 1, entropy_flag);
+ ProcessDataPacket(kDefaultPathId, i, entropy_flag);
}
for (int i = 1; i < 50; ++i) {
EXPECT_EQ(entropy[i],
@@ -4778,20 +4057,21 @@ TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacket) {
QuicPacketHeader header;
header.public_header.connection_id = connection_id_;
header.public_header.version_flag = true;
+ header.path_id = kDefaultPathId;
header.packet_number = 12;
QuicFrames frames;
frames.push_back(QuicFrame(&frame1_));
scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet,
- buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, kDefaultPathId, 12, *packet, buffer, kMaxPacketSize);
framer_.set_version(version());
connection_.set_perspective(Perspective::IS_SERVER);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
EXPECT_TRUE(writer_->version_negotiation_packet() != nullptr);
size_t num_versions = arraysize(kSupportedQuicVersions);
@@ -4819,15 +4099,15 @@ TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacketSocketBlocked) {
frames.push_back(QuicFrame(&frame1_));
scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet,
- buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, kDefaultPathId, 12, *packet, buffer, kMaxPacketSize);
framer_.set_version(version());
connection_.set_perspective(Perspective::IS_SERVER);
BlockOnNextWrite();
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
EXPECT_EQ(0u, writer_->last_packet_size());
EXPECT_TRUE(connection_.HasQueuedData());
@@ -4861,8 +4141,8 @@ TEST_P(QuicConnectionTest,
frames.push_back(QuicFrame(&frame1_));
scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encryped_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet,
- buffer, kMaxPacketSize);
+ size_t encryped_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, kDefaultPathId, 12, *packet, buffer, kMaxPacketSize);
framer_.set_version(version());
connection_.set_perspective(Perspective::IS_SERVER);
@@ -4870,7 +4150,7 @@ TEST_P(QuicConnectionTest,
writer_->set_is_write_blocked_data_buffered(true);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encryped_length, false));
+ QuicReceivedPacket(buffer, encryped_length, QuicTime::Zero(), false));
EXPECT_EQ(0u, writer_->last_packet_size());
EXPECT_FALSE(connection_.HasQueuedData());
}
@@ -4884,26 +4164,29 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.BuildVersionNegotiationPacket(connection_id_,
QuicSupportedVersions()));
- connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted);
+ scoped_ptr<QuicReceivedPacket> received(
+ ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
+ connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
// Now force another packet. The connection should transition into
// NEGOTIATED_VERSION state and tell the packet creator to StopSendingVersion.
QuicPacketHeader header;
header.public_header.connection_id = connection_id_;
+ header.path_id = kDefaultPathId;
header.packet_number = 12;
header.public_header.version_flag = false;
QuicFrames frames;
frames.push_back(QuicFrame(&frame1_));
scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet,
- buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, kDefaultPathId, 12, *packet, buffer, kMaxPacketSize);
ASSERT_NE(0u, encrypted_length);
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
ASSERT_FALSE(QuicPacketCreatorPeer::SendVersionInPacket(creator_));
}
@@ -4911,15 +4194,20 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
TEST_P(QuicConnectionTest, BadVersionNegotiation) {
// Send a version negotiation packet with the version the client started with.
// It should be rejected.
- EXPECT_CALL(visitor_, OnConnectionClosed(
- QUIC_INVALID_VERSION_NEGOTIATION_PACKET, false));
+ EXPECT_CALL(visitor_,
+ OnConnectionClosed(QUIC_INVALID_VERSION_NEGOTIATION_PACKET, _,
+ ConnectionCloseSource::FROM_SELF));
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.BuildVersionNegotiationPacket(connection_id_,
QuicSupportedVersions()));
- connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted);
+ scoped_ptr<QuicReceivedPacket> received(
+ ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
+ connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
}
TEST_P(QuicConnectionTest, CheckSendStats) {
+ connection_.DisableTailLossProbe();
+
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
connection_.SendStreamDataWithString(3, "first", 0, !kFin, nullptr);
size_t first_packet_size = writer_->last_packet_size();
@@ -4940,19 +4228,11 @@ TEST_P(QuicConnectionTest, CheckSendStats) {
QuicAckFrame nack_three = InitAckFrame(4);
NackPacket(3, &nack_three);
NackPacket(1, &nack_three);
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
- lost_packets.push_back(std::make_pair(3, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(1);
- lost_packets.insert(3);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
+ lost_packets.push_back(std::make_pair(3, kMaxPacketSize));
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
+ .WillOnce(SetArgPointee<3>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
EXPECT_CALL(visitor_, OnCanWrite());
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -4972,51 +4252,6 @@ TEST_P(QuicConnectionTest, CheckSendStats) {
EXPECT_EQ(kDefaultMaxPacketSize, stats.max_packet_size);
}
-TEST_P(QuicConnectionTest, CheckReceiveStats) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- size_t received_bytes = 0;
- received_bytes +=
- ProcessFecProtectedPacket(1, false, !kEntropyFlag, !kHasStopWaiting);
- received_bytes +=
- ProcessFecProtectedPacket(3, false, !kEntropyFlag, !kHasStopWaiting);
- // Should be counted against dropped packets.
- received_bytes += ProcessDataPacket(3, 1, !kEntropyFlag);
- received_bytes += ProcessFecPacket(4, 1, true, !kEntropyFlag, nullptr);
-
- EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
- .WillOnce(Return(QuicBandwidth::Zero()));
-
- const QuicConnectionStats& stats = connection_.GetStats();
- EXPECT_EQ(received_bytes, stats.bytes_received);
- EXPECT_EQ(4u, stats.packets_received);
-
- EXPECT_EQ(1u, stats.packets_revived);
- EXPECT_EQ(1u, stats.packets_dropped);
-}
-
-TEST_P(QuicConnectionTest, TestFecGroupLimits) {
- // Create and return a group for 1.
- ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 1) != nullptr);
-
- // Create and return a group for 2.
- ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 2) != nullptr);
-
- // Create and return a group for 4. This should remove 1 but not 2.
- ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 4) != nullptr);
- ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 1) == nullptr);
- ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 2) != nullptr);
-
- // Create and return a group for 3. This will kill off 2.
- ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 3) != nullptr);
- ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 2) == nullptr);
-
- // Verify that adding 5 kills off 3, despite 4 being created before 3.
- ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 5) != nullptr);
- ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 4) != nullptr);
- ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 3) == nullptr);
-}
-
TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) {
// Construct a packet with stream frame and connection close frame.
QuicPacketHeader header;
@@ -5033,16 +4268,17 @@ TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) {
scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames));
EXPECT_TRUE(nullptr != packet.get());
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 1, *packet,
- buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, kDefaultPathId, 1, *packet, buffer, kMaxPacketSize);
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, true));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, _,
+ ConnectionCloseSource::FROM_PEER));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
}
TEST_P(QuicConnectionTest, SelectMutualVersion) {
@@ -5139,17 +4375,10 @@ TEST_P(QuicConnectionTest, AckNotifierFailToTriggerCallback) {
// which we registered to be notified about.
QuicAckFrame frame = InitAckFrame(3);
NackPacket(1, &frame);
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(1);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
+ .WillOnce(SetArgPointee<3>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
ProcessAckPacket(&frame);
}
@@ -5171,29 +4400,17 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) {
// Now we receive ACK for packets 1, 3, and 4 and lose 2.
QuicAckFrame frame = InitAckFrame(4);
NackPacket(2, &frame);
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(2);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
+ .WillOnce(SetArgPointee<3>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
ProcessAckPacket(&frame);
// Now we get an ACK for packet 5 (retransmitted packet 2), which should
// trigger the callback.
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
QuicAckFrame second_ack_frame = InitAckFrame(5);
ProcessAckPacket(&second_ack_frame);
@@ -5203,6 +4420,8 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) {
// out and was retransmitted, even though the retransmission has a
// different packet number.
TEST_P(QuicConnectionTest, AckNotifierCallbackForAckAfterRTO) {
+ connection_.DisableTailLossProbe();
+
// Create a listener which we expect to be called.
scoped_refptr<MockAckListener> listener(new StrictMock<MockAckListener>);
@@ -5254,155 +4473,28 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackForAckOfNackedPacket) {
NackPacket(2, &frame);
EXPECT_CALL(*listener, OnPacketRetransmitted(_));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- if (FLAGS_quic_general_loss_algorithm) {
- SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
- .WillOnce(SetArgPointee<3>(lost_packets));
- } else {
- PacketNumberSet lost_packets;
- lost_packets.insert(2);
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(lost_packets));
- }
+ SendAlgorithmInterface::CongestionVector lost_packets;
+ lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _))
+ .WillOnce(SetArgPointee<3>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
ProcessAckPacket(&frame);
// Now we get an ACK for packet 2, which was previously nacked.
EXPECT_CALL(*listener, OnPacketAcked(3, _));
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
QuicAckFrame second_ack_frame = InitAckFrame(4);
ProcessAckPacket(&second_ack_frame);
// Verify that the listener is not notified again when the
// retransmit is acked.
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
QuicAckFrame third_ack_frame = InitAckFrame(5);
ProcessAckPacket(&third_ack_frame);
}
-TEST_P(QuicConnectionTest, AckNotifierFECTriggerCallback) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- // Create a listener which we expect to be called.
- scoped_refptr<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(2, "bar", 0, !kFin, nullptr);
-
- // Process an ACK from the server with a revived packet, which should trigger
- // the callback.
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
- QuicAckFrame frame = InitAckFrame(2);
- NackPacket(1, &frame);
- frame.latest_revived_packet = 1;
- ProcessAckPacket(&frame);
- // If the ack is processed again, the notifier should not be called again.
- ProcessAckPacket(&frame);
-}
-
-TEST_P(QuicConnectionTest, AckNotifierCallbackAfterFECRecovery) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(visitor_, OnCanWrite());
-
- // Create a listener which we expect to be called.
- scoped_refptr<MockAckListener> listener(new MockAckListener);
- EXPECT_CALL(*listener, OnPacketAcked(_, _)).Times(1);
-
- // Expect ACKs for 1 packet.
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
-
- // Send one packet, and register to be notified on ACK.
- connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener.get());
-
- // Ack packet gets dropped, but we receive an FEC packet that covers it.
- // Should recover the Ack packet and trigger the notification callback.
- QuicFrames frames;
-
- QuicAckFrame ack_frame = InitAckFrame(1);
- frames.push_back(QuicFrame(&ack_frame));
-
- // Dummy stream frame to satisfy expectations set elsewhere.
- frames.push_back(QuicFrame(&frame1_));
-
- QuicPacketHeader ack_header;
- ack_header.public_header.connection_id = connection_id_;
- ack_header.public_header.reset_flag = false;
- ack_header.public_header.version_flag = false;
- ack_header.entropy_flag = !kEntropyFlag;
- ack_header.fec_flag = true;
- ack_header.packet_number = 1;
- ack_header.is_in_fec_group = IN_FEC_GROUP;
- ack_header.fec_group = 1;
-
- QuicPacket* packet = BuildUnsizedDataPacket(&framer_, ack_header, frames);
-
- // Take the packet which contains the ACK frame, and construct and deliver an
- // FEC packet which allows the ACK packet to be recovered.
- ProcessFecPacket(2, 1, true, !kEntropyFlag, packet);
-}
-
-TEST_P(QuicConnectionTest, NetworkChangeVisitorCwndCallbackChangesFecState) {
- size_t max_packets_per_fec_group = creator_->max_packets_per_fec_group();
-
- QuicSentPacketManager::NetworkChangeVisitor* visitor =
- QuicSentPacketManagerPeer::GetNetworkChangeVisitor(manager_);
- EXPECT_TRUE(visitor);
-
- // Increase FEC group size by increasing congestion window to a large number.
- EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
- .WillRepeatedly(Return(1000 * kDefaultTCPMSS));
- visitor->OnCongestionWindowChange();
- EXPECT_LT(max_packets_per_fec_group, creator_->max_packets_per_fec_group());
-}
-
-TEST_P(QuicConnectionTest, NetworkChangeVisitorConfigCallbackChangesFecState) {
- QuicSentPacketManager::NetworkChangeVisitor* visitor =
- QuicSentPacketManagerPeer::GetNetworkChangeVisitor(manager_);
- EXPECT_TRUE(visitor);
- EXPECT_EQ(QuicTime::Delta::Zero(),
- QuicPacketCreatorPeer::GetFecTimeout(creator_));
-
- // Verify that sending a config with a new initial rtt changes fec timeout.
- // Create and process a config with a non-zero initial RTT.
- EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
- QuicConfig config;
- config.SetInitialRoundTripTimeUsToSend(300000);
- connection_.SetFromConfig(config);
- EXPECT_LT(QuicTime::Delta::Zero(),
- QuicPacketCreatorPeer::GetFecTimeout(creator_));
-}
-
-TEST_P(QuicConnectionTest, NetworkChangeVisitorRttCallbackChangesFecState) {
- // Verify that sending a config with a new initial rtt changes fec timeout.
- QuicSentPacketManager::NetworkChangeVisitor* visitor =
- QuicSentPacketManagerPeer::GetNetworkChangeVisitor(manager_);
- EXPECT_TRUE(visitor);
- EXPECT_EQ(QuicTime::Delta::Zero(),
- QuicPacketCreatorPeer::GetFecTimeout(creator_));
-
- // Increase FEC timeout by increasing RTT.
- RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager_);
- rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(300),
- QuicTime::Delta::Zero(), QuicTime::Zero());
- visitor->OnRttChange();
- EXPECT_LT(QuicTime::Delta::Zero(),
- QuicPacketCreatorPeer::GetFecTimeout(creator_));
-}
-
TEST_P(QuicConnectionTest, OnPacketHeaderDebugVisitor) {
QuicPacketHeader header;
@@ -5410,10 +4502,8 @@ TEST_P(QuicConnectionTest, OnPacketHeaderDebugVisitor) {
new MockQuicConnectionDebugVisitor());
connection_.set_debug_visitor(debug_visitor.get());
EXPECT_CALL(*debug_visitor, OnPacketHeader(Ref(header))).Times(1);
- if (FLAGS_quic_drop_non_awaited_packets) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(1);
- EXPECT_CALL(*debug_visitor, OnSuccessfulVersionNegotiation(_)).Times(1);
- }
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(1);
+ EXPECT_CALL(*debug_visitor, OnSuccessfulVersionNegotiation(_)).Times(1);
connection_.OnPacketHeader(header);
}
@@ -5465,43 +4555,6 @@ TEST_P(QuicConnectionTest, NoDataNoFin) {
"Attempt to send empty stream frame");
}
-TEST_P(QuicConnectionTest, FecSendPolicyReceivedConnectionOption) {
- // Test sending SetReceivedConnectionOptions when FEC send policy is
- // FEC_ANY_TRIGGER.
- if (GetParam().fec_send_policy == FEC_ALARM_TRIGGER) {
- return;
- }
- connection_.set_perspective(Perspective::IS_SERVER);
-
- // Test ReceivedConnectionOptions.
- EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
- QuicConfig config;
- QuicTagVector copt;
- copt.push_back(kFSPA);
- QuicConfigPeer::SetReceivedConnectionOptions(&config, copt);
- EXPECT_EQ(FEC_ANY_TRIGGER, generator_->fec_send_policy());
- connection_.SetFromConfig(config);
- EXPECT_EQ(FEC_ALARM_TRIGGER, generator_->fec_send_policy());
-}
-
-// TODO(rtenneti): Delete this code after the 0.25 RTT FEC experiment.
-TEST_P(QuicConnectionTest, FecRTTMultiplierReceivedConnectionOption) {
- connection_.set_perspective(Perspective::IS_SERVER);
-
- // Test ReceivedConnectionOptions.
- EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
- QuicConfig config;
- QuicTagVector copt;
- copt.push_back(kFRTT);
- QuicConfigPeer::SetReceivedConnectionOptions(&config, copt);
- float rtt_multiplier_for_fec_timeout =
- QuicPacketCreatorPeer::GetRttMultiplierForFecTimeout(creator_);
- connection_.SetFromConfig(config);
- // New RTT multiplier is half of the old RTT multiplier.
- EXPECT_EQ(rtt_multiplier_for_fec_timeout,
- QuicPacketCreatorPeer::GetRttMultiplierForFecTimeout(creator_) * 2);
-}
-
TEST_P(QuicConnectionTest, DoNotSendGoAwayTwice) {
EXPECT_FALSE(connection_.goaway_sent());
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
@@ -5512,13 +4565,12 @@ TEST_P(QuicConnectionTest, DoNotSendGoAwayTwice) {
}
TEST_P(QuicConnectionTest, ReevaluateTimeUntilSendOnAck) {
- ValueRestore<bool> old_flag(&FLAGS_quic_respect_send_alarm2, true);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin,
nullptr);
// Evaluate CanWrite, and have it return a non-Zero value.
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(1)));
connection_.OnCanWrite();
EXPECT_TRUE(connection_.GetSendAlarm()->IsSet());
@@ -5527,14 +4579,9 @@ TEST_P(QuicConnectionTest, ReevaluateTimeUntilSendOnAck) {
// Process an ack and the send alarm will be set to the new 2ms delay.
QuicAckFrame ack = InitAckFrame(1);
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _));
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(2)));
ProcessAckPacket(&ack);
EXPECT_EQ(1u, writer_->frame_count());
@@ -5546,15 +4593,22 @@ TEST_P(QuicConnectionTest, ReevaluateTimeUntilSendOnAck) {
}
TEST_P(QuicConnectionTest, SendAcksImmediately) {
- FLAGS_quic_respect_send_alarm2 = true;
CongestionBlockWrites();
SendAckPacketToPeer();
}
+TEST_P(QuicConnectionTest, SendPingImmediately) {
+ CongestionBlockWrites();
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+ connection_.SendPing();
+ EXPECT_FALSE(connection_.HasQueuedData());
+}
+
TEST_P(QuicConnectionTest, SendingUnencryptedStreamDataFails) {
FLAGS_quic_never_write_unencrypted_data = true;
EXPECT_CALL(visitor_,
- OnConnectionClosed(QUIC_UNENCRYPTED_STREAM_DATA, false));
+ OnConnectionClosed(QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA,
+ _, ConnectionCloseSource::FROM_SELF));
EXPECT_DFATAL(connection_.SendStreamDataWithString(3, "", 0, kFin, nullptr),
"Cannot send stream data without encryption.");
EXPECT_FALSE(connection_.connected());
@@ -5586,6 +4640,67 @@ TEST_P(QuicConnectionTest, EnableMultipathNegotiation) {
EXPECT_TRUE(QuicConnectionPeer::IsMultipathEnabled(&connection_));
}
+TEST_P(QuicConnectionTest, ClosePath) {
+ QuicPathId kTestPathId = 1;
+ connection_.SendPathClose(kTestPathId);
+ EXPECT_TRUE(QuicFramerPeer::IsPathClosed(
+ QuicConnectionPeer::GetFramer(&connection_), kTestPathId));
+}
+
+TEST_P(QuicConnectionTest, BadMultipathFlag) {
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_BAD_MULTIPATH_FLAG, _,
+ ConnectionCloseSource::FROM_SELF));
+
+ // Receieve a packet with multipath flag on when multipath is not enabled.
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_FALSE(QuicConnectionPeer::IsMultipathEnabled(&connection_));
+ peer_creator_.SetCurrentPath(/*path_id=*/1u, 1u, 10u);
+ QuicStreamFrame stream_frame(1u, false, 0u, StringPiece());
+ EXPECT_DFATAL(
+ ProcessFramePacket(QuicFrame(&stream_frame)),
+ "Received a packet with multipath flag but multipath is not enabled.");
+ EXPECT_FALSE(connection_.connected());
+}
+
+TEST_P(QuicConnectionTest, OnPathDegrading) {
+ QuicByteCount packet_size;
+ const size_t kMinTimeoutsBeforePathDegrading = 2;
+
+ 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_));
+ for (size_t i = 1; i < num_timeouts; ++i) {
+ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10 * i));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, packet_size, _));
+ connection_.GetRetransmissionAlarm()->Fire();
+ }
+ // Next RTO should cause OnPathDegrading to be called before the
+ // retransmission is sent out.
+ clock_.AdvanceTime(
+ QuicTime::Delta::FromSeconds(kMinTimeoutsBeforePathDegrading * 10));
+ {
+ InSequence s;
+ EXPECT_CALL(visitor_, OnPathDegrading());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, packet_size, _));
+ }
+ connection_.GetRetransmissionAlarm()->Fire();
+}
+
+TEST_P(QuicConnectionTest, MultipleCallsToCloseConnection) {
+ // Verifies that multiple calls to CloseConnection do not
+ // result in multiple attempts to close the connection - it will be marked as
+ // disconnected after the first call.
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(1);
+ connection_.CloseConnection(QUIC_NO_ERROR, "no reason",
+ ConnectionCloseBehavior::SILENT_CLOSE);
+ connection_.CloseConnection(QUIC_NO_ERROR, "no reason",
+ ConnectionCloseBehavior::SILENT_CLOSE);
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_crypto_client_stream.cc b/chromium/net/quic/quic_crypto_client_stream.cc
index 1b9e20d97f6..f91d8946dc1 100644
--- a/chromium/net/quic/quic_crypto_client_stream.cc
+++ b/chromium/net/quic/quic_crypto_client_stream.cc
@@ -12,10 +12,10 @@
#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/crypto/crypto_utils.h"
#include "net/quic/crypto/null_encrypter.h"
-#include "net/quic/quic_client_session_base.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_session.h"
+#include "net/quic/quic_utils.h"
using std::string;
using std::vector;
@@ -42,8 +42,7 @@ void AppendFixed(CryptoHandshakeMessage* message) {
} // namespace
-QuicCryptoClientStreamBase::QuicCryptoClientStreamBase(
- QuicClientSessionBase* session)
+QuicCryptoClientStreamBase::QuicCryptoClientStreamBase(QuicSession* session)
: QuicCryptoStream(session) {}
QuicCryptoClientStream::ChannelIDSourceCallbackImpl::
@@ -103,9 +102,10 @@ void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() {
QuicCryptoClientStream::QuicCryptoClientStream(
const QuicServerId& server_id,
- QuicClientSessionBase* session,
+ QuicSession* session,
ProofVerifyContext* verify_context,
- QuicCryptoClientConfig* crypto_config)
+ QuicCryptoClientConfig* crypto_config,
+ ProofHandler* proof_handler)
: QuicCryptoClientStreamBase(session),
next_state_(STATE_IDLE),
num_client_hellos_(0),
@@ -117,7 +117,9 @@ QuicCryptoClientStream::QuicCryptoClientStream(
channel_id_source_callback_(nullptr),
verify_context_(verify_context),
proof_verify_callback_(nullptr),
- stateless_reject_received_(false) {
+ proof_handler_(proof_handler),
+ stateless_reject_received_(false),
+ num_scup_messages_received_(0) {
DCHECK_EQ(Perspective::IS_CLIENT, session->connection()->perspective());
}
@@ -144,6 +146,7 @@ void QuicCryptoClientStream::OnHandshakeMessage(
// |message| is an update from the server, so we treat it differently from a
// handshake message.
HandleServerConfigUpdateMessage(message);
+ num_scup_messages_received_++;
return;
}
@@ -166,6 +169,10 @@ int QuicCryptoClientStream::num_sent_client_hellos() const {
return num_client_hellos_;
}
+int QuicCryptoClientStream::num_scup_messages_received() const {
+ return num_scup_messages_received_;
+}
+
// Used in Chromium, but not in the server.
bool QuicCryptoClientStream::WasChannelIDSent() const {
return channel_id_sent_;
@@ -183,8 +190,8 @@ void QuicCryptoClientStream::HandleServerConfigUpdateMessage(
crypto_config_->LookupOrCreate(server_id_);
QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate(
server_config_update, session()->connection()->clock()->WallNow(),
- session()->connection()->version(), cached, &crypto_negotiated_params_,
- &error_details);
+ session()->connection()->version(), cached->chlo_hash(), cached,
+ &crypto_negotiated_params_, &error_details);
if (error != QUIC_NO_ERROR) {
CloseConnectionWithDetails(
@@ -260,6 +267,7 @@ void QuicCryptoClientStream::DoInitialize(
DCHECK(crypto_config_->proof_verifier());
// Track proof verification time when cached server config is used.
proof_verify_start_time_ = base::TimeTicks::Now();
+ chlo_hash_ = cached->chlo_hash();
// If the cached state needs to be verified, do it now.
next_state_ = STATE_VERIFY_PROOF;
} else {
@@ -277,7 +285,8 @@ void QuicCryptoClientStream::DoSendCHLO(
next_state_ = STATE_NONE;
if (session()->connection()->connected()) {
session()->connection()->CloseConnection(
- QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, false);
+ QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject received",
+ ConnectionCloseBehavior::SILENT_CLOSE);
}
return;
}
@@ -303,10 +312,15 @@ void QuicCryptoClientStream::DoSendCHLO(
// This call and function should be removed after removing QUIC_VERSION_25.
AppendFixed(&out);
+ // Send a local timestamp to the server.
+ out.SetValue(kCTIM,
+ session()->connection()->clock()->WallNow().ToUNIXSeconds());
+
if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
crypto_config_->FillInchoateClientHello(
server_id_, session()->connection()->supported_versions().front(),
- cached, &crypto_negotiated_params_, &out);
+ cached, session()->connection()->random_generator(),
+ &crypto_negotiated_params_, &out);
// Pad the inchoate client hello to fill up a packet.
const QuicByteCount kFramingOverhead = 50; // A rough estimate.
const QuicByteCount max_packet_size =
@@ -326,6 +340,7 @@ void QuicCryptoClientStream::DoSendCHLO(
out.set_minimum_size(
static_cast<size_t>(max_packet_size - kFramingOverhead));
next_state_ = STATE_RECV_REJ;
+ CryptoUtils::HashHandshakeMessage(out, &chlo_hash_);
SendHandshakeMessage(out);
return;
}
@@ -346,7 +361,6 @@ void QuicCryptoClientStream::DoSendCHLO(
session()->connection()->clock()->WallNow(),
session()->connection()->random_generator(), channel_id_key_.get(),
&crypto_negotiated_params_, &out, &error_details);
-
if (error != QUIC_NO_ERROR) {
// Flush the cached config so that, if it's bad, the server has a
// chance to send us another in the future.
@@ -354,9 +368,10 @@ void QuicCryptoClientStream::DoSendCHLO(
CloseConnectionWithDetails(error, error_details);
return;
}
+ CryptoUtils::HashHandshakeMessage(out, &chlo_hash_);
channel_id_sent_ = (channel_id_key_.get() != nullptr);
if (cached->proof_verify_details()) {
- client_session()->OnProofVerifyDetailsAvailable(
+ proof_handler_->OnProofVerifyDetailsAvailable(
*cached->proof_verify_details());
}
next_state_ = STATE_RECV_SHLO;
@@ -372,12 +387,20 @@ void QuicCryptoClientStream::DoSendCHLO(
ENCRYPTION_INITIAL,
crypto_negotiated_params_.initial_crypters.encrypter.release());
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
- if (!encryption_established_) {
+
+ if (FLAGS_quic_reply_to_rej) {
+ // TODO(ianswett): Merge ENCRYPTION_REESTABLISHED and
+ // ENCRYPTION_FIRST_ESTABLSIHED.
encryption_established_ = true;
- session()->OnCryptoHandshakeEvent(
- QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
- } else {
session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_REESTABLISHED);
+ } else {
+ if (!encryption_established_) {
+ encryption_established_ = true;
+ session()->OnCryptoHandshakeEvent(
+ QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
+ } else {
+ session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_REESTABLISHED);
+ }
}
}
@@ -423,8 +446,8 @@ void QuicCryptoClientStream::DoReceiveREJ(
string error_details;
QuicErrorCode error = crypto_config_->ProcessRejection(
*in, session()->connection()->clock()->WallNow(),
- session()->connection()->version(), cached, &crypto_negotiated_params_,
- &error_details);
+ session()->connection()->version(), chlo_hash_, cached,
+ &crypto_negotiated_params_, &error_details);
if (error != QUIC_NO_ERROR) {
next_state_ = STATE_NONE;
@@ -458,7 +481,8 @@ QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof(
verify_ok_ = false;
QuicAsyncStatus status = verifier->VerifyProof(
- server_id_.host(), cached->server_config(), cached->certs(),
+ server_id_.host(), server_id_.port(), cached->server_config(),
+ session()->connection()->version(), chlo_hash_, cached->certs(),
cached->cert_sct(), cached->signature(), verify_context_.get(),
&verify_error_details_, &verify_details_, proof_verify_callback);
@@ -486,7 +510,7 @@ void QuicCryptoClientStream::DoVerifyProofComplete(
}
if (!verify_ok_) {
if (verify_details_.get()) {
- client_session()->OnProofVerifyDetailsAvailable(*verify_details_);
+ proof_handler_->OnProofVerifyDetailsAvailable(*verify_details_);
}
if (num_client_hellos_ == 0) {
cached->Clear();
@@ -649,7 +673,7 @@ void QuicCryptoClientStream::DoInitializeServerConfigUpdate(
void QuicCryptoClientStream::SetCachedProofValid(
QuicCryptoClientConfig::CachedState* cached) {
cached->SetProofValid();
- client_session()->OnProofValid(*cached);
+ proof_handler_->OnProofValid(*cached);
}
bool QuicCryptoClientStream::RequiresChannelID(
@@ -676,8 +700,4 @@ bool QuicCryptoClientStream::RequiresChannelID(
return false;
}
-QuicClientSessionBase* QuicCryptoClientStream::client_session() {
- return reinterpret_cast<QuicClientSessionBase*>(session());
-}
-
} // namespace net
diff --git a/chromium/net/quic/quic_crypto_client_stream.h b/chromium/net/quic/quic_crypto_client_stream.h
index cd2e7da23d3..30eb0754f1b 100644
--- a/chromium/net/quic/quic_crypto_client_stream.h
+++ b/chromium/net/quic/quic_crypto_client_stream.h
@@ -19,8 +19,6 @@
namespace net {
-class QuicClientSessionBase;
-
namespace test {
class CryptoTestUtils;
class QuicChromiumClientSessionPeer;
@@ -28,7 +26,7 @@ class QuicChromiumClientSessionPeer;
class NET_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream {
public:
- explicit QuicCryptoClientStreamBase(QuicClientSessionBase* session);
+ explicit QuicCryptoClientStreamBase(QuicSession* session);
~QuicCryptoClientStreamBase() override{};
@@ -39,6 +37,11 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream {
// have been sent. If the handshake has completed then this is one greater
// than the number of round-trips needed for the handshake.
virtual int num_sent_client_hellos() const = 0;
+
+ // The number of server config update messages received by the
+ // client. Does not count update messages that were received prior
+ // to handshake confirmation.
+ virtual int num_scup_messages_received() const = 0;
};
class NET_EXPORT_PRIVATE QuicCryptoClientStream
@@ -51,10 +54,31 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream
// the server being unwilling to send it without a valid source-address
// token.
static const int kMaxClientHellos = 3;
+
+ // 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 {
+ public:
+ virtual ~ProofHandler() {}
+
+ // Called when the proof in |cached| is marked valid. If this is a secure
+ // QUIC session, then this will happen only after the proof verifier
+ // completes.
+ virtual void OnProofValid(
+ const QuicCryptoClientConfig::CachedState& cached) = 0;
+
+ // Called when proof verification details become available, either because
+ // proof verification is complete, or when cached details are used. This
+ // will only be called for secure QUIC connections.
+ virtual void OnProofVerifyDetailsAvailable(
+ const ProofVerifyDetails& verify_details) = 0;
+ };
+
QuicCryptoClientStream(const QuicServerId& server_id,
- QuicClientSessionBase* session,
+ QuicSession* session,
ProofVerifyContext* verify_context,
- QuicCryptoClientConfig* crypto_config);
+ QuicCryptoClientConfig* crypto_config,
+ ProofHandler* proof_handler);
~QuicCryptoClientStream() override;
@@ -62,6 +86,8 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream
void CryptoConnect() override;
int num_sent_client_hellos() const override;
+ int num_scup_messages_received() const override;
+
// CryptoFramerVisitorInterface implementation
void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
@@ -183,8 +209,6 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream
// and the client config settings also allow sending a ChannelID.
bool RequiresChannelID(QuicCryptoClientConfig::CachedState* cached);
- QuicClientSessionBase* client_session();
-
State next_state_;
// num_client_hellos_ contains the number of client hello messages that this
// connection has sent.
@@ -192,8 +216,9 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream
QuicCryptoClientConfig* const crypto_config_;
- // Client's connection nonce (4-byte timestamp + 28 random bytes)
- std::string nonce_;
+ // SHA-256 hash of the most recently sent CHLO.
+ std::string chlo_hash_;
+
// Server's (hostname, port, is_https, privacy_mode) tuple.
const QuicServerId server_id_;
@@ -223,6 +248,9 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream
// proof_verify_callback_ contains the callback object that we passed to an
// asynchronous proof verification. The ProofVerifier owns this object.
ProofVerifierCallbackImpl* proof_verify_callback_;
+ // proof_handler_ contains the callback object used by a quic client
+ // for proof verification. It is not owned by this class.
+ ProofHandler* proof_handler_;
// These members are used to store the result of an asynchronous proof
// verification. These members must not be used after
@@ -238,6 +266,8 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream
base::TimeTicks proof_verify_start_time_;
+ int num_scup_messages_received_;
+
DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientStream);
};
diff --git a/chromium/net/quic/quic_crypto_client_stream_factory.cc b/chromium/net/quic/quic_crypto_client_stream_factory.cc
index 03565bae84f..41ca05b922c 100644
--- a/chromium/net/quic/quic_crypto_client_stream_factory.cc
+++ b/chromium/net/quic/quic_crypto_client_stream_factory.cc
@@ -20,8 +20,9 @@ class DefaultCryptoStreamFactory : public QuicCryptoClientStreamFactory {
QuicChromiumClientSession* session,
scoped_ptr<ProofVerifyContext> proof_verify_context,
QuicCryptoClientConfig* crypto_config) override {
- return new QuicCryptoClientStream(
- server_id, session, proof_verify_context.release(), crypto_config);
+ return new QuicCryptoClientStream(server_id, session,
+ proof_verify_context.release(),
+ crypto_config, session);
}
};
diff --git a/chromium/net/quic/quic_crypto_client_stream_test.cc b/chromium/net/quic/quic_crypto_client_stream_test.cc
index e95582c962d..2909e3780f5 100644
--- a/chromium/net/quic/quic_crypto_client_stream_test.cc
+++ b/chromium/net/quic/quic_crypto_client_stream_test.cc
@@ -84,9 +84,9 @@ TEST_F(QuicCryptoClientStreamTest, ConnectedAfterSHLO) {
TEST_F(QuicCryptoClientStreamTest, MessageAfterHandshake) {
CompleteCryptoHandshake();
- EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(
- QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE, _));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE, _, _));
message_.set_tag(kCHLO);
ConstructHandshakeMessage();
stream()->OnStreamFrame(QuicStreamFrame(kCryptoStreamId, /*fin=*/false,
@@ -100,16 +100,14 @@ TEST_F(QuicCryptoClientStreamTest, BadMessageType) {
message_.set_tag(kCHLO);
ConstructHandshakeMessage();
- EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
- "Expected REJ"));
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
+ "Expected REJ", _));
stream()->OnStreamFrame(QuicStreamFrame(kCryptoStreamId, /*fin=*/false,
/*offset=*/0,
message_data_->AsStringPiece()));
}
TEST_F(QuicCryptoClientStreamTest, NegotiatedParameters) {
- FLAGS_quic_use_rfc7539 = true;
CompleteCryptoHandshake();
const QuicConfig* config = session_->config();
@@ -153,7 +151,8 @@ TEST_F(QuicCryptoClientStreamTest, InvalidCachedServerConfig) {
vector<string> certs = state->certs();
string cert_sct = state->cert_sct();
string signature = state->signature();
- state->SetProof(certs, cert_sct, signature + signature);
+ string chlo_hash = state->chlo_hash();
+ state->SetProof(certs, cert_sct, chlo_hash, signature + signature);
stream()->CryptoConnect();
// Check that a client hello was sent.
@@ -209,9 +208,9 @@ TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdate) {
}
TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateBeforeHandshake) {
- EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(
- QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE, _));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE, _, _));
CryptoHandshakeMessage server_config_update;
server_config_update.set_tag(kSCUP);
scoped_ptr<QuicData> data(
@@ -263,6 +262,8 @@ class QuicCryptoClientStreamStatelessTest : public ::testing::Test {
server_crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance(),
CryptoTestUtils::ProofSourceForTesting()),
+ server_compressed_certs_cache_(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
server_id_(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED) {
TestQuicSpdyClientSession* client_session = nullptr;
CreateClientSessionForTest(
@@ -288,10 +289,10 @@ class QuicCryptoClientStreamStatelessTest : public ::testing::Test {
// Initializes the server_stream_ for stateless rejects.
void InitializeFakeStatelessRejectServer() {
TestQuicSpdyServerSession* server_session = nullptr;
- CreateServerSessionForTest(server_id_, QuicTime::Delta::FromSeconds(100000),
- QuicSupportedVersions(), &helper_,
- &server_crypto_config_, &server_connection_,
- &server_session);
+ CreateServerSessionForTest(
+ server_id_, QuicTime::Delta::FromSeconds(100000),
+ QuicSupportedVersions(), &helper_, &server_crypto_config_,
+ &server_compressed_certs_cache_, &server_connection_, &server_session);
CHECK(server_session);
server_session_.reset(server_session);
CryptoTestUtils::FakeServerOptions options;
@@ -312,6 +313,7 @@ class QuicCryptoClientStreamStatelessTest : public ::testing::Test {
PacketSavingConnection* server_connection_;
scoped_ptr<TestQuicSpdyServerSession> server_session_;
QuicCryptoServerConfig server_crypto_config_;
+ QuicCompressedCertsCache server_compressed_certs_cache_;
QuicServerId server_id_;
};
diff --git a/chromium/net/quic/quic_crypto_framer_parse_message_fuzzer.cc b/chromium/net/quic/quic_crypto_framer_parse_message_fuzzer.cc
new file mode 100644
index 00000000000..47dad64d6cf
--- /dev/null
+++ b/chromium/net/quic/quic_crypto_framer_parse_message_fuzzer.cc
@@ -0,0 +1,18 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include "base/strings/string_piece.h"
+#include "net/quic/crypto/crypto_framer.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ base::StringPiece crypto_input(reinterpret_cast<const char*>(data), size);
+ std::unique_ptr<net::CryptoHandshakeMessage> handshake_message(
+ net::CryptoFramer::ParseMessage(crypto_input));
+
+ return 0;
+}
diff --git a/chromium/net/quic/quic_crypto_server_stream.cc b/chromium/net/quic/quic_crypto_server_stream.cc
index fc8281ead91..7671c06fe7e 100644
--- a/chromium/net/quic/quic_crypto_server_stream.cc
+++ b/chromium/net/quic/quic_crypto_server_stream.cc
@@ -38,9 +38,8 @@ bool HasFixedTag(const CryptoHandshakeMessage& message) {
}
} // namespace
-void ServerHelloNotifier::OnPacketAcked(
- int acked_bytes,
- QuicTime::Delta delta_largest_observed) {
+void ServerHelloNotifier::OnPacketAcked(int acked_bytes,
+ QuicTime::Delta ack_delay_time) {
// The SHLO is sent in one packet.
server_stream_->OnServerHelloAcked();
}
@@ -49,15 +48,18 @@ void ServerHelloNotifier::OnPacketRetransmitted(int /*retransmitted_bytes*/) {}
QuicCryptoServerStream::QuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ bool use_stateless_rejects_if_peer_supported,
QuicSession* session)
: QuicCryptoServerStreamBase(session),
crypto_config_(crypto_config),
+ compressed_certs_cache_(compressed_certs_cache),
validate_client_hello_cb_(nullptr),
num_handshake_messages_(0),
num_handshake_messages_with_server_nonces_(0),
num_server_config_update_messages_sent_(0),
use_stateless_rejects_if_peer_supported_(
- FLAGS_enable_quic_stateless_reject_support),
+ use_stateless_rejects_if_peer_supported),
peer_supports_stateless_rejects_(false) {
DCHECK_EQ(Perspective::IS_SERVER, session->connection()->perspective());
}
@@ -70,9 +72,7 @@ void QuicCryptoServerStream::CancelOutstandingCallbacks() {
// Detach from the validation callback. Calling this multiple times is safe.
if (validate_client_hello_cb_ != nullptr) {
validate_client_hello_cb_->Cancel();
- if (FLAGS_quic_set_client_hello_cb_nullptr) {
- validate_client_hello_cb_ = nullptr;
- }
+ validate_client_hello_cb_ = nullptr;
}
}
@@ -159,7 +159,8 @@ void QuicCryptoServerStream::FinishProcessingHandshakeMessage(
<< session()->connection()->connection_id()
<< " because of a stateless reject.";
session()->connection()->CloseConnection(
- QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, /* from_peer */ false);
+ QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject",
+ ConnectionCloseBehavior::SILENT_CLOSE);
}
return;
}
@@ -225,7 +226,7 @@ void QuicCryptoServerStream::SendServerConfigUpdate(
session()->connection()->self_address().address(),
session()->connection()->peer_address().address(),
session()->connection()->clock(),
- session()->connection()->random_generator(),
+ session()->connection()->random_generator(), compressed_certs_cache_,
crypto_negotiated_params_, cached_network_params,
&server_config_update_message)) {
DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
@@ -338,7 +339,8 @@ QuicErrorCode QuicCryptoServerStream::ProcessClientHello(
connection->peer_address(), version(), connection->supported_versions(),
use_stateless_rejects_in_crypto_config, server_designated_connection_id,
connection->clock(), connection->random_generator(),
- &crypto_negotiated_params_, &crypto_proof_, reply, error_details);
+ compressed_certs_cache_, &crypto_negotiated_params_, &crypto_proof_,
+ reply, error_details);
}
void QuicCryptoServerStream::OverrideQuicConfigDefaults(QuicConfig* config) {}
diff --git a/chromium/net/quic/quic_crypto_server_stream.h b/chromium/net/quic/quic_crypto_server_stream.h
index e8e708a5a2d..b78e8881354 100644
--- a/chromium/net/quic/quic_crypto_server_stream.h
+++ b/chromium/net/quic/quic_crypto_server_stream.h
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "net/quic/crypto/crypto_handshake.h"
+#include "net/quic/crypto/quic_compressed_certs_cache.h"
#include "net/quic/crypto/quic_crypto_server_config.h"
#include "net/quic/proto/source_address_token.pb.h"
#include "net/quic/quic_config.h"
@@ -36,8 +37,7 @@ class NET_EXPORT_PRIVATE ServerHelloNotifier : public QuicAckListenerInterface {
explicit ServerHelloNotifier(QuicCryptoServerStreamBase* stream)
: server_stream_(stream) {}
- void OnPacketAcked(int acked_bytes,
- QuicTime::Delta delta_largest_observed) override;
+ void OnPacketAcked(int acked_bytes, QuicTime::Delta ack_delay_time) override;
void OnPacketRetransmitted(int retransmitted_bytes) override;
@@ -53,7 +53,6 @@ class NET_EXPORT_PRIVATE ServerHelloNotifier : public QuicAckListenerInterface {
// various code and test refactoring.
class NET_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream {
public:
- // |crypto_config| must outlive the stream.
explicit QuicCryptoServerStreamBase(QuicSession* session)
: QuicCryptoStream(session) {}
~QuicCryptoServerStreamBase() override {}
@@ -94,6 +93,8 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream
public:
// |crypto_config| must outlive the stream.
QuicCryptoServerStream(const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ bool use_stateless_rejects_if_peer_supported,
QuicSession* session);
~QuicCryptoServerStream() override;
@@ -166,6 +167,10 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream
// crypto_config_ contains crypto parameters for the handshake.
const QuicCryptoServerConfig* crypto_config_;
+ // compressed_certs_cache_ contains a set of most recently compressed certs.
+ // Owned by QuicDispatcher.
+ QuicCompressedCertsCache* compressed_certs_cache_;
+
// Server's certificate chain and signature of the server config, as provided
// by ProofSource::GetProof.
QuicCryptoProof crypto_proof_;
diff --git a/chromium/net/quic/quic_crypto_server_stream_test.cc b/chromium/net/quic/quic_crypto_server_stream_test.cc
index f783bef5fe7..da3eba03671 100644
--- a/chromium/net/quic/quic_crypto_server_stream_test.cc
+++ b/chromium/net/quic/quic_crypto_server_stream_test.cc
@@ -70,6 +70,8 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
: server_crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance(),
CryptoTestUtils::ProofSourceForTesting()),
+ server_compressed_certs_cache_(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
server_id_(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED),
client_crypto_config_(CryptoTestUtils::ProofVerifierForTesting()) {
FLAGS_enable_quic_stateless_reject_support = false;
@@ -107,11 +109,10 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
void InitializeServer() {
TestQuicSpdyServerSession* server_session = nullptr;
helpers_.push_back(new MockConnectionHelper);
-
- CreateServerSessionForTest(server_id_, QuicTime::Delta::FromSeconds(100000),
- supported_versions_, helpers_.back(),
- &server_crypto_config_, &server_connection_,
- &server_session);
+ CreateServerSessionForTest(
+ server_id_, QuicTime::Delta::FromSeconds(100000), supported_versions_,
+ helpers_.back(), &server_crypto_config_,
+ &server_compressed_certs_cache_, &server_connection_, &server_session);
CHECK(server_session);
server_session_.reset(server_session);
CryptoTestUtils::FakeServerOptions options;
@@ -145,7 +146,7 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
}
bool AsyncStrikeRegisterVerification() {
- if (server_connection_->version() > QUIC_VERSION_30) {
+ if (server_connection_->version() > QUIC_VERSION_32) {
return false;
}
return GetParam();
@@ -186,6 +187,7 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
PacketSavingConnection* server_connection_;
scoped_ptr<TestQuicSpdyServerSession> server_session_;
QuicCryptoServerConfig server_crypto_config_;
+ QuicCompressedCertsCache server_compressed_certs_cache_;
QuicServerId server_id_;
// Client state
@@ -232,6 +234,9 @@ TEST_P(QuicCryptoServerStreamTest, StatelessRejectAfterCHLO) {
true);
Initialize();
+ EXPECT_CALL(*server_connection_,
+ CloseConnection(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, _, _));
+
InitializeFakeClient(/* supports_stateless_rejects= */ true);
AdvanceHandshakeWithFakeClient();
@@ -256,7 +261,6 @@ TEST_P(QuicCryptoServerStreamTest, StatelessRejectAfterCHLO) {
EXPECT_EQ(expected_id, server_designated_connection_id);
EXPECT_FALSE(client_state->has_server_designated_connection_id());
ASSERT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
- EXPECT_FALSE(server_connection_->connected());
}
TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) {
@@ -292,8 +296,6 @@ TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) {
InitializeFakeClient(/* supports_stateless_rejects= */ true);
- client_stream()->CryptoConnect();
-
// In the stateless case, the second handshake contains a server-nonce, so the
// AsyncStrikeRegisterVerification() case will still succeed (unlike a 0-RTT
// handshake).
@@ -302,7 +304,7 @@ TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) {
// On the second round, encryption will be established.
EXPECT_TRUE(server_stream()->encryption_established());
EXPECT_TRUE(server_stream()->handshake_confirmed());
- EXPECT_EQ(2, server_stream()->NumHandshakeMessages());
+ EXPECT_EQ(1, server_stream()->NumHandshakeMessages());
EXPECT_EQ(1, server_stream()->NumHandshakeMessagesWithServerNonces());
}
@@ -377,11 +379,10 @@ TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
server_stream());
}
- if (FLAGS_require_strike_register_or_server_nonce &&
- !AsyncStrikeRegisterVerification()) {
- EXPECT_EQ(2, client_stream()->num_sent_client_hellos());
- } else {
+ if (AsyncStrikeRegisterVerification()) {
EXPECT_EQ(1, client_stream()->num_sent_client_hellos());
+ } else {
+ EXPECT_EQ(2, client_stream()->num_sent_client_hellos());
}
}
@@ -389,9 +390,9 @@ TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) {
FLAGS_quic_require_fix = false;
Initialize();
CompleteCryptoHandshake();
- EXPECT_CALL(*server_connection_,
- SendConnectionCloseWithDetails(
- QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE, _));
+ EXPECT_CALL(
+ *server_connection_,
+ CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE, _, _));
message_.set_tag(kCHLO);
ConstructHandshakeMessage();
server_stream()->OnStreamFrame(
@@ -405,8 +406,8 @@ TEST_P(QuicCryptoServerStreamTest, BadMessageType) {
message_.set_tag(kSHLO);
ConstructHandshakeMessage();
- EXPECT_CALL(*server_connection_, SendConnectionCloseWithDetails(
- QUIC_INVALID_CRYPTO_MESSAGE_TYPE, _));
+ EXPECT_CALL(*server_connection_,
+ CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE, _, _));
server_stream()->OnStreamFrame(
QuicStreamFrame(kCryptoStreamId, /*fin=*/false, /*offset=*/0,
message_data_->AsStringPiece()));
@@ -485,7 +486,6 @@ TEST_P(QuicCryptoServerStreamTest, NoTokenBindingWithoutClientSupport) {
TEST_P(QuicCryptoServerStreamTest, CancelRPCBeforeVerificationCompletes) {
// Tests that the client can close the connection while the remote strike
// register verification RPC is still pending.
- ValueRestore<bool> old_flag(&FLAGS_quic_set_client_hello_cb_nullptr, true);
// Set version to QUIC_VERSION_25 as QUIC_VERSION_26 and later don't support
// asynchronous strike register RPCs.
@@ -518,8 +518,8 @@ TEST_P(QuicCryptoServerStreamTest, CancelRPCBeforeVerificationCompletes) {
// While waiting for the asynchronous verification to complete, the client
// decides to close the connection.
- server_session_->connection()->CloseConnection(QUIC_NO_ERROR,
- /*from_peer=*/true);
+ server_session_->connection()->CloseConnection(
+ QUIC_NO_ERROR, "", ConnectionCloseBehavior::SILENT_CLOSE);
// The outstanding nonce verification RPC now completes.
strike_register_client_->RunPendingVerifications();
diff --git a/chromium/net/quic/quic_crypto_stream.cc b/chromium/net/quic/quic_crypto_stream.cc
index be4a3ca8882..ee44b6cd222 100644
--- a/chromium/net/quic/quic_crypto_stream.cc
+++ b/chromium/net/quic/quic_crypto_stream.cc
@@ -60,10 +60,6 @@ void QuicCryptoStream::OnDataAvailable() {
}
}
-SpdyPriority QuicCryptoStream::Priority() const {
- return net::kV3HighestPriority;
-}
-
void QuicCryptoStream::SendHandshakeMessage(
const CryptoHandshakeMessage& message) {
SendHandshakeMessage(message, nullptr);
@@ -93,6 +89,17 @@ bool QuicCryptoStream::ExportKeyingMaterial(StringPiece label,
result);
}
+bool QuicCryptoStream::ExportTokenBindingKeyingMaterial(string* result) const {
+ if (!encryption_established()) {
+ QUIC_BUG << "ExportTokenBindingKeyingMaterial was called before initial"
+ << "encryption was established.";
+ return false;
+ }
+ return CryptoUtils::ExportKeyingMaterial(
+ crypto_negotiated_params_.initial_subkey_secret, "EXPORTER-Token-Binding",
+ /* context= */ "", 32, result);
+}
+
const QuicCryptoNegotiatedParameters&
QuicCryptoStream::crypto_negotiated_params() const {
return crypto_negotiated_params_;
diff --git a/chromium/net/quic/quic_crypto_stream.h b/chromium/net/quic/quic_crypto_stream.h
index e794cb8025b..a5bf812ab5e 100644
--- a/chromium/net/quic/quic_crypto_stream.h
+++ b/chromium/net/quic/quic_crypto_stream.h
@@ -41,7 +41,6 @@ class NET_EXPORT_PRIVATE QuicCryptoStream
// ReliableQuicStream implementation
void OnDataAvailable() override;
- SpdyPriority Priority() const override;
// Sends |message| to the peer.
// TODO(wtc): return a success/failure status.
@@ -60,6 +59,16 @@ class NET_EXPORT_PRIVATE QuicCryptoStream
size_t result_len,
std::string* result) const;
+ // Performs key extraction for Token Binding. Unlike ExportKeyingMaterial,
+ // this function can be called before forward-secure encryption is
+ // established. Returns false if initial encryption has not been established,
+ // and true on success.
+ //
+ // Since this depends only on the initial keys, a signature over it can be
+ // repurposed by an attacker who obtains the client's or server's DH private
+ // value.
+ bool ExportTokenBindingKeyingMaterial(std::string* result) const;
+
bool encryption_established() const { return encryption_established_; }
bool handshake_confirmed() const { return handshake_confirmed_; }
diff --git a/chromium/net/quic/quic_crypto_stream_test.cc b/chromium/net/quic/quic_crypto_stream_test.cc
index 0677a54d23a..69d09d2401e 100644
--- a/chromium/net/quic/quic_crypto_stream_test.cc
+++ b/chromium/net/quic/quic_crypto_stream_test.cc
@@ -95,8 +95,8 @@ TEST_F(QuicCryptoStreamTest, ProcessBadData) {
EXPECT_EQ(1, bad[kFirstTagIndex]);
bad[kFirstTagIndex] = 0x7F; // out of order tag
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_CRYPTO_TAGS_OUT_OF_ORDER, testing::_));
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_CRYPTO_TAGS_OUT_OF_ORDER,
+ testing::_, testing::_));
stream_.OnStreamFrame(
QuicStreamFrame(kCryptoStreamId, /*fin=*/false, /*offset=*/0, bad));
}
diff --git a/chromium/net/quic/quic_end_to_end_unittest.cc b/chromium/net/quic/quic_end_to_end_unittest.cc
index a37895bcef1..7441c7f36f1 100644
--- a/chromium/net/quic/quic_end_to_end_unittest.cc
+++ b/chromium/net/quic/quic_end_to_end_unittest.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 <ostream>
#include <utility>
#include <vector>
@@ -10,6 +11,7 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/base/elements_upload_data_stream.h"
+#include "net/base/ip_address.h"
#include "net/base/test_completion_callback.h"
#include "net/base/test_data_directory.h"
#include "net/base/upload_bytes_element_reader.h"
@@ -27,6 +29,7 @@
#include "net/proxy/proxy_service.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/ssl/default_channel_id_store.h"
#include "net/ssl/ssl_config_service_defaults.h"
#include "net/test/cert_test_util.h"
#include "net/tools/quic/quic_in_memory_cache.h"
@@ -40,10 +43,8 @@ using base::StringPiece;
namespace net {
-using tools::QuicInMemoryCache;
-using tools::QuicServer;
-using tools::test::QuicInMemoryCachePeer;
-using tools::test::ServerThread;
+using test::QuicInMemoryCachePeer;
+using test::ServerThread;
namespace test {
@@ -74,9 +75,24 @@ class TestTransactionFactory : public HttpTransactionFactory {
scoped_ptr<HttpNetworkSession> session_;
};
+struct TestParams {
+ explicit TestParams(bool use_stateless_rejects)
+ : use_stateless_rejects(use_stateless_rejects) {}
+
+ friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
+ os << "{ use_stateless_rejects: " << p.use_stateless_rejects << " }";
+ return os;
+ }
+ bool use_stateless_rejects;
+};
+
+std::vector<TestParams> GetTestParams() {
+ return std::vector<TestParams>{TestParams(true), TestParams(false)};
+}
+
} // namespace
-class QuicEndToEndTest : public PlatformTest {
+class QuicEndToEndTest : public ::testing::TestWithParam<TestParams> {
protected:
QuicEndToEndTest()
: host_resolver_impl_(CreateResolverImpl()),
@@ -94,6 +110,9 @@ class QuicEndToEndTest : public PlatformTest {
params_.enable_quic = true;
params_.quic_clock = nullptr;
params_.quic_random = nullptr;
+ if (GetParam().use_stateless_rejects) {
+ params_.quic_connection_options.push_back(kSREJ);
+ }
params_.host_resolver = &host_resolver_;
params_.cert_verifier = &cert_verifier_;
params_.transport_security_state = &transport_security_state_;
@@ -102,8 +121,12 @@ class QuicEndToEndTest : public PlatformTest {
params_.ssl_config_service = ssl_config_service_.get();
params_.http_auth_handler_factory = auth_handler_factory_.get();
params_.http_server_properties = http_server_properties.GetWeakPtr();
+ channel_id_service_.reset(
+ new ChannelIDService(new DefaultChannelIDStore(nullptr),
+ base::ThreadTaskRunnerHandle::Get()));
+ params_.channel_id_service = channel_id_service_.get();
- net::CertVerifyResult verify_result;
+ CertVerifyResult verify_result;
verify_result.verified_cert = ImportCertFromFile(
GetTestCertsDirectory(), "quic_test.example.com.crt");
cert_verifier_.AddResultForCertAndHost(verify_result.verified_cert.get(),
@@ -136,8 +159,8 @@ class QuicEndToEndTest : public PlatformTest {
// To simplify the test, and avoid the race with the HTTP request, we force
// QUIC for these requests.
- params_.origin_to_force_quic_on =
- HostPortPair::FromString("test.example.com:443");
+ params_.origins_to_force_quic_on.insert(
+ HostPortPair::FromString("test.example.com:443"));
transaction_factory_.reset(new TestTransactionFactory(params_));
}
@@ -149,16 +172,15 @@ class QuicEndToEndTest : public PlatformTest {
// Starts the QUIC server listening on a random port.
void StartServer() {
- IPAddressNumber ip;
- CHECK(ParseIPLiteralToNumber("127.0.0.1", &ip));
- server_address_ = IPEndPoint(ip, 0);
+ server_address_ = IPEndPoint(IPAddress(127, 0, 0, 1), 0);
server_config_.SetInitialStreamFlowControlWindowToSend(
kInitialStreamFlowControlWindowForTest);
server_config_.SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
+ server_config_options_.token_binding_enabled = true;
QuicServer* server =
new QuicServer(CryptoTestUtils::ProofSourceForTesting(), server_config_,
- QuicSupportedVersions());
+ server_config_options_, QuicSupportedVersions());
server_thread_.reset(new ServerThread(server, server_address_,
strike_register_no_startup_period_));
server_thread_->Initialize();
@@ -225,6 +247,7 @@ class QuicEndToEndTest : public PlatformTest {
scoped_ptr<MockHostResolver> host_resolver_impl_;
MappedHostResolver host_resolver_;
MockCertVerifier cert_verifier_;
+ scoped_ptr<ChannelIDService> channel_id_service_;
TransportSecurityState transport_security_state_;
scoped_ptr<CTVerifier> cert_transparency_verifier_;
scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
@@ -240,11 +263,16 @@ class QuicEndToEndTest : public PlatformTest {
IPEndPoint server_address_;
std::string server_hostname_;
QuicConfig server_config_;
+ QuicCryptoServerConfig::ConfigOptions server_config_options_;
bool server_started_;
bool strike_register_no_startup_period_;
};
-TEST_F(QuicEndToEndTest, LargeGetWithNoPacketLoss) {
+INSTANTIATE_TEST_CASE_P(Tests,
+ QuicEndToEndTest,
+ ::testing::ValuesIn(GetTestParams()));
+
+TEST_P(QuicEndToEndTest, LargeGetWithNoPacketLoss) {
std::string response(10 * 1024, 'x');
AddToCache(request_.url.PathForRequest(), 200, "OK", response);
@@ -259,13 +287,32 @@ TEST_F(QuicEndToEndTest, LargeGetWithNoPacketLoss) {
CheckResponse(consumer, "HTTP/1.1 200", response);
}
+TEST_P(QuicEndToEndTest, TokenBinding) {
+ // Enable token binding and re-initialize the TestTransactionFactory.
+ params_.enable_token_binding = true;
+ transaction_factory_.reset(new TestTransactionFactory(params_));
+
+ AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
+
+ TestTransactionConsumer consumer(DEFAULT_PRIORITY,
+ transaction_factory_.get());
+ consumer.Start(&request_, BoundNetLog());
+
+ // Will terminate when the last consumer completes.
+ base::MessageLoop::current()->Run();
+
+ CheckResponse(consumer, "HTTP/1.1 200", kResponseBody);
+ HttpRequestHeaders headers;
+ ASSERT_TRUE(consumer.transaction()->GetFullRequestHeaders(&headers));
+ EXPECT_TRUE(headers.HasHeader(HttpRequestHeaders::kTokenBinding));
+}
+
// crbug.com/559173
#if defined(THREAD_SANITIZER)
-#define MAYBE_LargePostWithNoPacketLoss DISABLED_LargePostWithNoPacketLoss
+TEST_P(QuicEndToEndTest, DISABLED_LargePostWithNoPacketLoss) {
#else
-#define MAYBE_LargePostWithNoPacketLoss LargePostWithNoPacketLoss
+TEST_P(QuicEndToEndTest, LargePostWithNoPacketLoss) {
#endif
-TEST_F(QuicEndToEndTest, MAYBE_LargePostWithNoPacketLoss) {
InitializePostRequest(1024 * 1024);
AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
@@ -282,11 +329,10 @@ TEST_F(QuicEndToEndTest, MAYBE_LargePostWithNoPacketLoss) {
// crbug.com/559173
#if defined(THREAD_SANITIZER)
-#define MAYBE_LargePostWithPacketLoss DISABLED_LargePostWithPacketLoss
+TEST_P(QuicEndToEndTest, DISABLED_LargePostWithPacketLoss) {
#else
-#define MAYBE_LargePostWithPacketLoss LargePostWithPacketLoss
+TEST_P(QuicEndToEndTest, LargePostWithPacketLoss) {
#endif
-TEST_F(QuicEndToEndTest, MAYBE_LargePostWithPacketLoss) {
// FLAGS_fake_packet_loss_percentage = 30;
InitializePostRequest(1024 * 1024);
@@ -305,11 +351,10 @@ TEST_F(QuicEndToEndTest, MAYBE_LargePostWithPacketLoss) {
// crbug.com/536845
#if defined(THREAD_SANITIZER)
-#define MAYBE_UberTest DISABLED_UberTest
+TEST_P(QuicEndToEndTest, DISABLED_UberTest) {
#else
-#define MAYBE_UberTest UberTest
+TEST_P(QuicEndToEndTest, UberTest) {
#endif
-TEST_F(QuicEndToEndTest, MAYBE_UberTest) {
// FLAGS_fake_packet_loss_percentage = 30;
const char kResponseBody[] = "some really big response body";
diff --git a/chromium/net/quic/quic_flags.cc b/chromium/net/quic/quic_flags.cc
index 86707d641bf..94dcb1da471 100644
--- a/chromium/net/quic/quic_flags.cc
+++ b/chromium/net/quic/quic_flags.cc
@@ -11,11 +11,6 @@ bool FLAGS_quic_use_time_loss_detection = false;
// CHLO.
bool FLAGS_use_early_return_when_verifying_chlo = true;
-// If true, QUIC connections will support FEC protection of data while sending
-// packets, to reduce latency of data delivery to the application. The client
-// must also request FEC protection for the server to use FEC.
-bool FLAGS_enable_quic_fec = true;
-
// When true, defaults to BBR congestion control instead of Cubic.
bool FLAGS_quic_use_bbr_congestion_control = false;
@@ -41,10 +36,6 @@ int64_t FLAGS_quic_time_wait_list_max_connections = 600000;
// Enables server-side support for QUIC stateless rejects.
bool FLAGS_enable_quic_stateless_reject_support = true;
-// If ture, allow Ack Decimation to be used for QUIC when requested by the
-// client connection option ACKD.
-bool FLAGS_quic_ack_decimation = true;
-
// This flag is not in use, just to keep consistency for shared code.
bool FLAGS_quic_always_log_bugs_for_tests = false;
@@ -54,9 +45,6 @@ bool FLAGS_quic_auto_tune_receive_window = true;
// If true, multipath is enabled for the connection.
bool FLAGS_quic_enable_multipath = false;
-// Limits QUIC's max CWND to 200 packets.
-bool FLAGS_quic_limit_max_cwnd = true;
-
// If true, require handshake confirmation for QUIC connections, functionally
// disabling 0-rtt handshakes.
// TODO(rtenneti): Enable this flag after CryptoServerTest's are fixed.
@@ -74,82 +62,65 @@ bool FLAGS_quic_measure_headers_hol_blocking_time = true;
// Disable QUIC's userspace pacing.
bool FLAGS_quic_disable_pacing = false;
-// If true, Use QUIC's GeneralLossAlgorithm implementation instead of
-// TcpLossAlgorithm or TimeLossAlgorithm.
-bool FLAGS_quic_general_loss_algorithm = true;
-
-// If true, only migrate QUIC connections when client address changes are
-// considered to be caused by NATs.
-bool FLAGS_quic_disable_non_nat_address_migration = true;
-
-// If true, QUIC connections will timeout when packets are not being recieved,
-// even if they are being sent.
-bool FLAGS_quic_use_new_idle_timeout = true;
-
-// If true, replace QuicFrameList with StreamSequencerBuffer as underlying data
-// structure for QuicStreamSequencer bufferring.
-bool FLAGS_quic_use_stream_sequencer_buffer = true;
-
-// If true, don't send QUIC packets if the send alarm is set.
-bool FLAGS_quic_respect_send_alarm2 = true;
-
-// If ture, sets callback pointer to nullptr after calling Cancel() in
-// QuicCryptoServerStream::CancelOutstandingCallbacks.
-bool FLAGS_quic_set_client_hello_cb_nullptr = true;
+// If true, Close the connection instead of writing unencrypted stream data.
+bool FLAGS_quic_never_write_unencrypted_data = true;
-// If treu, Only track a single retransmission in QUIC's TransmissionInfo
-// struct.
-bool FLAGS_quic_track_single_retransmission = true;
+// If true, reject any incoming QUIC which does not have the FIXD tag.
+bool FLAGS_quic_require_fix = true;
-// If true, allow each quic stream to write 16k blocks rather than doing a round
-// robin of one packet per session when ack clocked or paced.
-bool FLAGS_quic_batch_writes = true;
+// If true, headers stream will support receiving PUSH_PROMISE frames.
+bool FLAGS_quic_supports_push_promise = true;
-// If true, QUIC sessions will write block streams that attempt to write
-// unencrypted data.
-bool FLAGS_quic_block_unencrypted_writes = true;
+// If true, make sure new incoming streams correctly cede to higher
+// priority (or batch) streams when doing QUIC writes.
+bool FLAGS_quic_cede_correctly = true;
-// If true, Close the connection instead of writing unencrypted stream data.
-bool FLAGS_quic_never_write_unencrypted_data = true;
+// If true, QUIC should correctly report if it supports ChaCha20. Otherwise,
+// QUIC will lie and claim that it does not support ChaCha20. The primary use
+// case for this is places where ChaCha20 is prohibitively expensive compared to
+// AES-GCM.
+bool FLAGS_quic_crypto_server_config_default_has_chacha20 = true;
-// If true, clear the FEC group instead of sending it with ENCRYPTION_NONE.
-// Close the connection if we ever try to serialized unencrypted FEC.
-bool FLAGS_quic_no_unencrypted_fec = true;
+// If true, always log the cached network parameters, regardless of whether
+// bandwidth-resumption has been enabled.
+bool FLAGS_quic_log_received_parameters = true;
-// If true, reject any incoming QUIC which does not have the FIXD tag.
-bool FLAGS_quic_require_fix = true;
+// If true, QUIC will use newly refactored TCP sender code.
+bool FLAGS_quic_use_new_tcp_sender = true;
-// If true, QUIC supports sending trailers from Server to Client.
-bool FLAGS_quic_supports_trailers = true;
+// If true, the QUIC dispatcher will directly send version negotiation packets
+// without needing to create a QUIC session first.
+bool FLAGS_quic_stateless_version_negotiation = false;
-// If true, headers stream will support receiving PUSH_PROMISE frames.
-bool FLAGS_quic_supports_push_promise = false;
+// QUIC Ack Decimation with tolerance for packet reordering.
+bool FLAGS_quic_ack_decimation2 = true;
-// Fixes a bug in QUIC_VERSION_26 by always using the primary config when
-// getting the proof of possession.
-bool FLAGS_quic_use_primary_config_for_proof = true;
+// If true, QUIC connections will defer responding to ACKs to their send alarms.
+bool FLAGS_quic_connection_defer_ack_response = true;
-// Enable counters for incoming/outgoing streams which are used as condition
-// check while creating a new stream.
-bool FLAGS_quic_distinguish_incoming_outgoing_streams = true;
+// If true, SpdyFramer will call OnStreamEnd from SpdyFramerVisitorInterface
+// instead of empty-data sentinel calls when the stream is to be ended.
+bool FLAGS_spdy_on_stream_end = true;
-// If true, QUIC servers will attempt to validate a client's source
-// address token using the primary config, even if no server config id
-// is present in the client hello.
-bool FLAGS_quic_validate_stk_without_scid = true;
+// If true, QuicCryptoServerConfig will use cached compressed certificates
+// if the uncompressed certs to be compressed hits the cache.
+bool FLAGS_quic_use_cached_compressed_certs = true;
-// If true, use the new write blocked list for QUIC.
-bool FLAGS_quic_new_blocked_list = true;
+// Enable a connection option allowing connections to time out if more than 5
+// consecutive RTOs are sent.
+bool FLAGS_quic_enable_rto_timeout = true;
-// If true, QUIC will support RFC 7539 variants of ChaCha20 Poly1305.
-bool FLAGS_quic_use_rfc7539 = true;
+// Use a byte conservation approach instead of packet conservation in the
+// Slow Start Large Reduction experiment.
+bool FLAGS_quic_sslr_byte_conservation = true;
-// If true, drop not awaited QUIC packets before decrypting them.
-bool FLAGS_quic_drop_non_awaited_packets = false;
+// Try to use the socket timestamp to determine the time a packet was
+// received instead of Now().
+bool FLAGS_quic_use_socket_timestamp = true;
-// If true, use the fast implementation of IncrementalHash/FNV1a_128_Hash.
-bool FLAGS_quic_utils_use_fast_incremental_hash = true;
+// If true, handling of errors from invalid stream frames is done in
+// one place in QuicStreamSequencer::OnStreamFrame.
+bool FLAGS_quic_consolidate_onstreamframe_errors = true;
-// If true, require QUIC connections to use a valid server nonce or a non-local
-// strike register.
-bool FLAGS_require_strike_register_or_server_nonce = true;
+// Resend 0RTT requests in response to an REJ that re-establishes encryption.
+bool FLAGS_quic_reply_to_rej = true;
diff --git a/chromium/net/quic/quic_flags.h b/chromium/net/quic/quic_flags.h
index 93da375ad53..e5c635ed57a 100644
--- a/chromium/net/quic/quic_flags.h
+++ b/chromium/net/quic/quic_flags.h
@@ -11,41 +11,36 @@
NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_time_loss_detection;
NET_EXPORT_PRIVATE extern bool FLAGS_use_early_return_when_verifying_chlo;
-NET_EXPORT_PRIVATE extern bool FLAGS_enable_quic_fec;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_bbr_congestion_control;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_allow_bbr;
NET_EXPORT_PRIVATE extern int64_t FLAGS_quic_time_wait_list_seconds;
NET_EXPORT_PRIVATE extern int64_t FLAGS_quic_time_wait_list_max_connections;
NET_EXPORT_PRIVATE extern bool FLAGS_enable_quic_stateless_reject_support;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_ack_decimation;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_always_log_bugs_for_tests;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_auto_tune_receive_window;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_multipath;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_limit_max_cwnd;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_require_handshake_confirmation;
NET_EXPORT_PRIVATE extern bool FLAGS_shift_quic_cubic_epoch_when_app_limited;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_measure_headers_hol_blocking_time;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_disable_pacing;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_general_loss_algorithm;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_disable_non_nat_address_migration;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_new_idle_timeout;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_stream_sequencer_buffer;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_respect_send_alarm2;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_set_client_hello_cb_nullptr;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_track_single_retransmission;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_batch_writes;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_block_unencrypted_writes;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_never_write_unencrypted_data;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_no_unencrypted_fec;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_require_fix;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_supports_trailers;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_stateless_version_negotiation;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_supports_push_promise;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_primary_config_for_proof;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_distinguish_incoming_outgoing_streams;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_validate_stk_without_scid;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_new_blocked_list;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_rfc7539;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_drop_non_awaited_packets;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_utils_use_fast_incremental_hash;
-NET_EXPORT_PRIVATE extern bool FLAGS_require_strike_register_or_server_nonce;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_supports_push_promise;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_cede_correctly;
+NET_EXPORT_PRIVATE extern bool
+ FLAGS_quic_crypto_server_config_default_has_chacha20;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_log_received_parameters;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_new_tcp_sender;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_ack_decimation2;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_connection_defer_ack_response;
+NET_EXPORT_PRIVATE extern bool FLAGS_spdy_on_stream_end;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_cached_compressed_certs;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_rto_timeout;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_sslr_byte_conservation;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_socket_timestamp;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_consolidate_onstreamframe_errors;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_reply_to_rej;
+
#endif // NET_QUIC_QUIC_FLAGS_H_
diff --git a/chromium/net/quic/quic_flow_controller.cc b/chromium/net/quic/quic_flow_controller.cc
index 020261d893a..30c5386f53a 100644
--- a/chromium/net/quic/quic_flow_controller.cc
+++ b/chromium/net/quic/quic_flow_controller.cc
@@ -68,19 +68,20 @@ bool QuicFlowController::UpdateHighestReceivedOffset(
void QuicFlowController::AddBytesSent(QuicByteCount bytes_sent) {
if (bytes_sent_ + bytes_sent > send_window_offset_) {
- LOG(DFATAL) << ENDPOINT << "Stream " << id_ << " Trying to send an extra "
- << bytes_sent << " bytes, when bytes_sent = " << bytes_sent_
- << ", and send_window_offset_ = " << send_window_offset_;
+ QUIC_BUG << ENDPOINT << "Stream " << id_ << " Trying to send an extra "
+ << bytes_sent << " bytes, when bytes_sent = " << bytes_sent_
+ << ", and send_window_offset_ = " << send_window_offset_;
bytes_sent_ = send_window_offset_;
// This is an error on our side, close the connection as soon as possible.
- connection_->SendConnectionCloseWithDetails(
+ 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());
+ .c_str(),
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
diff --git a/chromium/net/quic/quic_flow_controller_test.cc b/chromium/net/quic/quic_flow_controller_test.cc
index 877175f595e..96b157dd525 100644
--- a/chromium/net/quic/quic_flow_controller_test.cc
+++ b/chromium/net/quic/quic_flow_controller_test.cc
@@ -77,8 +77,8 @@ TEST_F(QuicFlowControllerTest, SendingBytes) {
EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
// Try to send more bytes, violating flow control.
- EXPECT_CALL(connection_, SendConnectionCloseWithDetails(
- QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA, _));
+ EXPECT_CALL(connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA, _, _));
EXPECT_DFATAL(flow_controller_->AddBytesSent(send_window_ * 10),
base::StringPrintf("Trying to send an extra %" PRIu64 " bytes",
send_window_ * 10));
diff --git a/chromium/net/quic/quic_frame_list.cc b/chromium/net/quic/quic_frame_list.cc
index 862e34f7ced..92670746aeb 100644
--- a/chromium/net/quic/quic_frame_list.cc
+++ b/chromium/net/quic/quic_frame_list.cc
@@ -4,8 +4,13 @@
#include "net/quic/quic_frame_list.h"
+#include <algorithm>
+
#include "base/logging.h"
+using std::list;
+using std::string;
+
namespace net {
QuicFrameList::FrameData::FrameData(QuicStreamOffset offset,
@@ -29,7 +34,7 @@ bool QuicFrameList::Empty() const {
}
QuicErrorCode QuicFrameList::OnStreamData(QuicStreamOffset offset,
- StringPiece data,
+ base::StringPiece data,
QuicTime timestamp,
size_t* const bytes_buffered) {
*bytes_buffered = 0;
@@ -246,4 +251,4 @@ size_t QuicFrameList::BytesBuffered() const {
return num_bytes_buffered_;
}
-} // namespace net_quic
+} // namespace net
diff --git a/chromium/net/quic/quic_frame_list.h b/chromium/net/quic/quic_frame_list.h
index a6235972a2c..f529016f66a 100644
--- a/chromium/net/quic/quic_frame_list.h
+++ b/chromium/net/quic/quic_frame_list.h
@@ -6,14 +6,13 @@
#define NET_QUIC_QUIC_FRAME_LIST_H_
#include <stddef.h>
+#include <list>
+#include <string>
+#include "base/strings/string_piece.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_stream_sequencer_buffer_interface.h"
-using base::StringPiece;
-using std::string;
-using std::list;
-
namespace net {
namespace test {
@@ -26,15 +25,15 @@ class NET_EXPORT_PRIVATE QuicFrameList
// A contiguous segment received by a QUIC stream.
struct FrameData {
FrameData(QuicStreamOffset offset,
- string segment,
+ std::string segment,
const QuicTime timestamp);
const QuicStreamOffset offset;
- string segment;
+ std::string segment;
const QuicTime timestamp;
};
- explicit QuicFrameList();
+ QuicFrameList();
~QuicFrameList() override;
@@ -42,7 +41,7 @@ class NET_EXPORT_PRIVATE QuicFrameList
void Clear() override;
bool Empty() const override;
QuicErrorCode OnStreamData(QuicStreamOffset offset,
- StringPiece data,
+ base::StringPiece data,
QuicTime timestamp,
size_t* bytes_buffered) override;
size_t Readv(const struct iovec* iov, size_t iov_len) override;
@@ -57,19 +56,19 @@ class NET_EXPORT_PRIVATE QuicFrameList
private:
friend class test::QuicStreamSequencerPeer;
- list<FrameData>::iterator FindInsertionPoint(QuicStreamOffset offset,
- size_t len);
+ std::list<FrameData>::iterator FindInsertionPoint(QuicStreamOffset offset,
+ size_t len);
bool FrameOverlapsBufferedData(
QuicStreamOffset offset,
size_t data_len,
- list<FrameData>::const_iterator insertion_point) const;
+ std::list<FrameData>::const_iterator insertion_point) const;
bool IsDuplicate(QuicStreamOffset offset,
size_t data_len,
- list<FrameData>::const_iterator insertion_point) const;
+ std::list<FrameData>::const_iterator insertion_point) const;
- list<FrameData> frame_list_;
+ std::list<FrameData> frame_list_;
// Number of bytes in buffer.
size_t num_bytes_buffered_ = 0;
diff --git a/chromium/net/quic/quic_framer.cc b/chromium/net/quic/quic_framer.cc
index 1370350cf17..3d3e36f2c23 100644
--- a/chromium/net/quic/quic_framer.cc
+++ b/chromium/net/quic/quic_framer.cc
@@ -159,13 +159,10 @@ QuicFramer::~QuicFramer() {}
// static
size_t QuicFramer::GetMinStreamFrameSize(QuicStreamId stream_id,
QuicStreamOffset offset,
- bool last_frame_in_packet,
- InFecGroup is_in_fec_group) {
- bool no_stream_frame_length =
- last_frame_in_packet && is_in_fec_group == NOT_IN_FEC_GROUP;
+ bool last_frame_in_packet) {
return kQuicFrameTypeSize + GetStreamIdSize(stream_id) +
GetStreamOffsetSize(offset) +
- (no_stream_frame_length ? 0 : kQuicStreamPayloadLengthSize);
+ (last_frame_in_packet ? 0 : kQuicStreamPayloadLengthSize);
}
// static
@@ -215,6 +212,11 @@ size_t QuicFramer::GetBlockedFrameSize() {
}
// static
+size_t QuicFramer::GetPathCloseFrameSize() {
+ return kQuicFrameTypeSize + kQuicPathIdSize;
+}
+
+// static
size_t QuicFramer::GetStreamIdSize(QuicStreamId stream_id) {
// Sizes are 1 through 4 bytes.
for (int i = 1; i <= 4; ++i) {
@@ -265,7 +267,6 @@ size_t QuicFramer::GetSerializedFrameLength(
size_t free_bytes,
bool first_frame,
bool last_frame,
- InFecGroup is_in_fec_group,
QuicPacketNumberLength packet_number_length) {
// Prevent a rare crash reported in b/19458523.
if ((frame.type == STREAM_FRAME || frame.type == ACK_FRAME) &&
@@ -273,7 +274,6 @@ size_t QuicFramer::GetSerializedFrameLength(
QUIC_BUG << "Cannot compute the length of a null frame. "
<< "type:" << frame.type << "free_bytes:" << free_bytes
<< " first_frame:" << first_frame << " last_frame:" << last_frame
- << " is_in_fec:" << is_in_fec_group
<< " seq num length:" << packet_number_length;
set_error(QUIC_INTERNAL_ERROR);
visitor_->OnError(this);
@@ -283,8 +283,8 @@ size_t QuicFramer::GetSerializedFrameLength(
// PADDING implies end of packet.
return free_bytes;
}
- size_t frame_len = ComputeFrameLength(frame, last_frame, is_in_fec_group,
- packet_number_length);
+ size_t frame_len =
+ ComputeFrameLength(frame, last_frame, packet_number_length);
if (frame_len <= free_bytes) {
// Frame fits within packet. Note that acks may be truncated.
return frame_len;
@@ -308,6 +308,8 @@ size_t QuicFramer::GetSerializedFrameLength(
QuicFramer::AckFrameInfo::AckFrameInfo() : max_delta(0) {}
+QuicFramer::AckFrameInfo::AckFrameInfo(const AckFrameInfo& other) = default;
+
QuicFramer::AckFrameInfo::~AckFrameInfo() {}
// static
@@ -329,9 +331,7 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
size_t i = 0;
for (const QuicFrame& frame : frames) {
// Determine if we should write stream frame length in header.
- const bool no_stream_frame_length =
- (header.is_in_fec_group == NOT_IN_FEC_GROUP) &&
- (i == frames.size() - 1);
+ const bool no_stream_frame_length = i == frames.size() - 1;
if (!AppendTypeByte(frame, no_stream_frame_length, &writer)) {
QUIC_BUG << "AppendTypeByte failed";
return 0;
@@ -397,6 +397,12 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
return 0;
}
break;
+ case PATH_CLOSE_FRAME:
+ if (!AppendPathCloseFrame(*frame.path_close_frame, &writer)) {
+ QUIC_BUG << "AppendPathCloseFrame failed";
+ return 0;
+ }
+ break;
default:
RaiseError(QUIC_INVALID_FRAME_DATA);
QUIC_BUG << "QUIC_INVALID_FRAME_DATA";
@@ -408,31 +414,6 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
return writer.length();
}
-QuicPacket* QuicFramer::BuildFecPacket(const QuicPacketHeader& header,
- StringPiece redundancy) {
- DCHECK_EQ(IN_FEC_GROUP, header.is_in_fec_group);
- DCHECK_NE(0u, header.fec_group);
- size_t len = GetPacketHeaderSize(header);
- len += redundancy.length();
-
- scoped_ptr<char[]> buffer(new char[len]);
- QuicDataWriter writer(len, buffer.get());
- if (!AppendPacketHeader(header, &writer)) {
- QUIC_BUG << "AppendPacketHeader failed";
- return nullptr;
- }
-
- if (!writer.WriteBytes(redundancy.data(), redundancy.length())) {
- QUIC_BUG << "Failed to add FEC";
- return nullptr;
- }
-
- return new QuicPacket(buffer.release(), len, true,
- header.public_header.connection_id_length,
- header.public_header.version_flag,
- header.public_header.packet_number_length);
-}
-
// static
QuicEncryptedPacket* QuicFramer::BuildPublicResetPacket(
const QuicPublicResetPacket& packet) {
@@ -546,9 +527,8 @@ bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
scoped_ptr<char[]> large_buffer(new char[packet.length()]);
rv = ProcessDataPacket(&reader, public_header, packet, large_buffer.get(),
packet.length());
- LOG_IF(DFATAL, rv) << "QUIC should never successfully process packets "
- << "larger than kMaxPacketSize. packet size:"
- << packet.length();
+ QUIC_BUG_IF(rv) << "QUIC should never successfully process packets larger"
+ << "than kMaxPacketSize. packet size:" << packet.length();
}
return rv;
@@ -603,23 +583,16 @@ bool QuicFramer::ProcessDataPacket(QuicDataReader* encrypted_reader,
if (packet.length() > kMaxPacketSize) {
// If the packet has gotten this far, it should not be too large.
- LOG(DFATAL) << "Packet too large:" << packet.length();
+ QUIC_BUG << "Packet too large:" << packet.length();
return RaiseError(QUIC_PACKET_TOO_LARGE);
}
+ DCHECK(!header.fec_flag);
// Handle the payload.
- if (!header.fec_flag) {
- if (header.is_in_fec_group == IN_FEC_GROUP) {
- StringPiece payload = reader.PeekRemainingPayload();
- visitor_->OnFecProtectedPayload(payload);
- }
- if (!ProcessFrameData(&reader, header)) {
- DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error.
- DLOG(WARNING) << "Unable to process frame data.";
- return false;
- }
- } else {
- visitor_->OnFecData(reader.ReadRemainingPayload());
+ if (!ProcessFrameData(&reader, header)) {
+ DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error.
+ DLOG(WARNING) << "Unable to process frame data.";
+ return false;
}
visitor_->OnPacketComplete();
@@ -648,12 +621,6 @@ bool QuicFramer::ProcessPublicResetPacket(
}
// TODO(satyamshekhar): validate nonce to protect against DoS.
- if (reset->GetUint64(kRSEQ, &packet.rejected_packet_number) !=
- QUIC_NO_ERROR) {
- set_detailed_error("Unable to read rejected packet number.");
- return RaiseError(QUIC_INVALID_PUBLIC_RST_PACKET);
- }
-
StringPiece address;
if (reset->GetStringPiece(kCADR, &address)) {
QuicSocketAddressCoder address_coder;
@@ -667,36 +634,9 @@ bool QuicFramer::ProcessPublicResetPacket(
return true;
}
-bool QuicFramer::ProcessRevivedPacket(QuicPacketHeader* header,
- StringPiece payload) {
- visitor_->OnRevivedPacket();
-
- header->entropy_hash = GetPacketEntropyHash(*header);
-
- if (!visitor_->OnPacketHeader(*header)) {
- return true;
- }
-
- if (payload.length() > kMaxPacketSize) {
- set_detailed_error("Revived packet too large.");
- return RaiseError(QUIC_PACKET_TOO_LARGE);
- }
-
- QuicDataReader reader(payload.data(), payload.length());
- if (!ProcessFrameData(&reader, *header)) {
- DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error.
- DLOG(WARNING) << "Unable to process frame data.";
- return false;
- }
-
- visitor_->OnPacketComplete();
- return true;
-}
-
bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
QuicDataWriter* writer) {
DVLOG(1) << "Appending header: " << header;
- DCHECK(header.fec_group > 0 || header.is_in_fec_group == NOT_IN_FEC_GROUP);
uint8_t public_flags = 0;
if (header.public_header.reset_flag) {
public_flags |= PACKET_PUBLIC_FLAGS_RST;
@@ -773,30 +713,10 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
if (header.entropy_flag) {
private_flags |= PACKET_PRIVATE_FLAGS_ENTROPY;
}
- if (header.is_in_fec_group == IN_FEC_GROUP) {
- private_flags |= PACKET_PRIVATE_FLAGS_FEC_GROUP;
- }
- if (header.fec_flag) {
- private_flags |= PACKET_PRIVATE_FLAGS_FEC;
- }
if (!writer->WriteUInt8(private_flags)) {
return false;
}
- // The FEC group number is the packet number of the first fec
- // protected packet, or 0 if this packet is not protected.
- if (header.is_in_fec_group == IN_FEC_GROUP) {
- DCHECK_LE(header.fec_group, header.packet_number);
- DCHECK_LT(header.packet_number - header.fec_group, 255u);
- // Offset from the current packet number to the first fec
- // protected packet.
- uint8_t first_fec_protected_packet_offset =
- static_cast<uint8_t>(header.packet_number - header.fec_group);
- if (!writer->WriteBytes(&first_fec_protected_packet_offset, 1)) {
- return false;
- }
- }
-
return true;
}
@@ -963,6 +883,7 @@ bool QuicFramer::ProcessPublicHeader(QuicDataReader* reader,
// If the version from the new packet is the same as the version of this
// framer, then the public flags should be set to something we understand.
// If not, this raises an error.
+ last_version_tag_ = version_tag;
QuicVersion version = QuicTagToQuicVersion(version_tag);
if (version == quic_version_ && public_flags > PACKET_PUBLIC_FLAGS_MAX) {
set_detailed_error("Illegal public flags value.");
@@ -1042,6 +963,7 @@ QuicFramer::AckFrameInfo QuicFramer::GetAckFrameInfo(
bool QuicFramer::ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader,
QuicPacketHeader* header) {
+ header->path_id = kDefaultPathId;
if (header->public_header.multipath_flag &&
!ProcessPathId(encrypted_reader, &header->path_id)) {
set_detailed_error("Unable to read path id.");
@@ -1081,9 +1003,16 @@ bool QuicFramer::ProcessAuthenticatedHeader(QuicDataReader* reader,
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);
+ if (quic_version_ > QUIC_VERSION_31) {
+ if (private_flags > PACKET_PRIVATE_FLAGS_MAX_VERSION_32) {
+ set_detailed_error("Illegal private flags value.");
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
+ } else {
+ 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;
@@ -1289,6 +1218,18 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
}
continue;
}
+ case PATH_CLOSE_FRAME: {
+ QuicPathCloseFrame path_close_frame;
+ if (!ProcessPathCloseFrame(reader, &path_close_frame)) {
+ return RaiseError(QUIC_INVALID_PATH_CLOSE_DATA);
+ }
+ if (!visitor_->OnPathCloseFrame(path_close_frame)) {
+ DVLOG(1) << "Visitor asked to stop further processing.";
+ // Returning true since there was no parsing error.
+ return true;
+ }
+ continue;
+ }
default:
set_detailed_error("Illegal frame type.");
@@ -1381,17 +1322,17 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader,
return false;
}
- uint64_t delta_time_largest_observed_us;
- if (!reader->ReadUFloat16(&delta_time_largest_observed_us)) {
- set_detailed_error("Unable to read delta time largest observed.");
+ 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 (delta_time_largest_observed_us == kUFloat16MaxValue) {
- ack_frame->delta_time_largest_observed = QuicTime::Delta::Infinite();
+ if (ack_delay_time_us == kUFloat16MaxValue) {
+ ack_frame->ack_delay_time = QuicTime::Delta::Infinite();
} else {
- ack_frame->delta_time_largest_observed =
- QuicTime::Delta::FromMicroseconds(delta_time_largest_observed_us);
+ ack_frame->ack_delay_time =
+ QuicTime::Delta::FromMicroseconds(ack_delay_time_us);
}
if (!ProcessTimestampsInAckFrame(reader, ack_frame)) {
@@ -1429,6 +1370,10 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader,
last_packet_number -= (range_length + 1);
}
+ if (quic_version_ > QUIC_VERSION_31) {
+ return true;
+ }
+
// Parse the revived packets list.
// TODO(ianswett): Change the ack frame so it only expresses one revived.
uint8_t num_revived_packets;
@@ -1444,7 +1389,6 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader,
set_detailed_error("Unable to read revived packet.");
return false;
}
- ack_frame->latest_revived_packet = revived_packet;
}
return true;
@@ -1462,6 +1406,7 @@ bool QuicFramer::ProcessTimestampsInAckFrame(QuicDataReader* reader,
}
if (num_received_packets > 0) {
+ ack_frame->received_packet_times.reserve(num_received_packets);
uint8_t delta_from_largest_observed;
if (!reader->ReadBytes(&delta_from_largest_observed,
PACKET_1BYTE_PACKET_NUMBER)) {
@@ -1638,17 +1583,28 @@ bool QuicFramer::ProcessBlockedFrame(QuicDataReader* reader,
return true;
}
+bool QuicFramer::ProcessPathCloseFrame(QuicDataReader* reader,
+ QuicPathCloseFrame* frame) {
+ if (!reader->ReadBytes(&frame->path_id, 1)) {
+ set_detailed_error("Unable to read path_id.");
+ return false;
+ }
+
+ return true;
+}
+
// static
StringPiece QuicFramer::GetAssociatedDataFromEncryptedPacket(
const QuicEncryptedPacket& encrypted,
QuicConnectionIdLength connection_id_length,
bool includes_version,
+ bool includes_path_id,
QuicPacketNumberLength packet_number_length) {
// TODO(ianswett): This is identical to QuicData::AssociatedData.
return StringPiece(
encrypted.data(),
GetStartOfEncryptedData(connection_id_length, includes_version,
- packet_number_length));
+ includes_path_id, packet_number_length));
}
void QuicFramer::SetDecrypter(EncryptionLevel level, QuicDecrypter* decrypter) {
@@ -1680,7 +1636,29 @@ void QuicFramer::SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter) {
encrypter_[level].reset(encrypter);
}
+size_t QuicFramer::EncryptInPlace(EncryptionLevel level,
+ QuicPathId path_id,
+ QuicPacketNumber packet_number,
+ size_t ad_len,
+ size_t total_len,
+ size_t buffer_len,
+ char* buffer) {
+ size_t output_length = 0;
+ if (!encrypter_[level]->EncryptPacket(
+ path_id, packet_number,
+ StringPiece(buffer, ad_len), // Associated data
+ StringPiece(buffer + ad_len, total_len - ad_len), // Plaintext
+ buffer + ad_len, // Destination buffer
+ &output_length, buffer_len - ad_len)) {
+ RaiseError(QUIC_ENCRYPTION_FAILURE);
+ return 0;
+ }
+
+ return ad_len + output_length;
+}
+
size_t QuicFramer::EncryptPayload(EncryptionLevel level,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
const QuicPacket& packet,
char* buffer,
@@ -1694,7 +1672,7 @@ 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(packet_number, associated_data,
+ if (!encrypter_[level]->EncryptPacket(path_id, packet_number, associated_data,
packet.Plaintext(), buffer + ad_len,
&output_length, buffer_len - ad_len)) {
RaiseError(QUIC_ENCRYPTION_FAILURE);
@@ -1729,19 +1707,19 @@ bool QuicFramer::DecryptPayload(QuicDataReader* encrypted_reader,
size_t* decrypted_length) {
StringPiece encrypted = encrypted_reader->ReadRemainingPayload();
DCHECK(decrypter_.get() != nullptr);
- const StringPiece& associated_data = GetAssociatedDataFromEncryptedPacket(
+ StringPiece associated_data = GetAssociatedDataFromEncryptedPacket(
packet, header.public_header.connection_id_length,
- header.public_header.version_flag,
+ header.public_header.version_flag, header.public_header.multipath_flag,
header.public_header.packet_number_length);
bool success = decrypter_->DecryptPacket(
- header.packet_number, associated_data, encrypted, decrypted_buffer,
- decrypted_length, buffer_length);
+ 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) {
success = alternative_decrypter_->DecryptPacket(
- header.packet_number, associated_data, encrypted, decrypted_buffer,
- decrypted_length, buffer_length);
+ 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_) {
@@ -1780,12 +1758,12 @@ size_t QuicFramer::GetAckFrameSize(
size_t ack_size = GetMinAckFrameSize(largest_observed_length);
if (!ack_info.nack_ranges.empty()) {
- ack_size += kNumberOfNackRangesSize + kNumberOfRevivedPacketsSize;
+ ack_size += kNumberOfNackRangesSize;
+ if (quic_version_ <= QUIC_VERSION_31) {
+ ack_size += kNumberOfRevivedPacketsSize;
+ }
ack_size += min(ack_info.nack_ranges.size(), kMaxNackRanges) *
(missing_packet_number_length + PACKET_1BYTE_PACKET_NUMBER);
- if (ack.latest_revived_packet != 0) {
- ack_size += largest_observed_length;
- }
}
// In version 23, if the ack will be truncated due to too many nack ranges,
@@ -1810,13 +1788,12 @@ size_t QuicFramer::GetAckFrameSize(
size_t QuicFramer::ComputeFrameLength(
const QuicFrame& frame,
bool last_frame_in_packet,
- InFecGroup is_in_fec_group,
QuicPacketNumberLength packet_number_length) {
switch (frame.type) {
case STREAM_FRAME:
return GetMinStreamFrameSize(frame.stream_frame->stream_id,
frame.stream_frame->offset,
- last_frame_in_packet, is_in_fec_group) +
+ last_frame_in_packet) +
frame.stream_frame->frame_length;
case ACK_FRAME: {
return GetAckFrameSize(*frame.ack_frame, packet_number_length);
@@ -1839,6 +1816,8 @@ size_t QuicFramer::ComputeFrameLength(
return GetWindowUpdateFrameSize();
case BLOCKED_FRAME:
return GetBlockedFrameSize();
+ case PATH_CLOSE_FRAME:
+ return GetPathCloseFrameSize();
case PADDING_FRAME:
DCHECK(false);
return 0;
@@ -1964,9 +1943,12 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicPacketHeader& header,
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() - kNumberOfRevivedPacketsSize -
- kNumberOfNackRangesSize - GetMinAckFrameSize(largest_observed_length);
+ size_t available_range_bytes = writer->capacity() - writer->length() -
+ kNumberOfNackRangesSize -
+ GetMinAckFrameSize(largest_observed_length);
+ if (quic_version_ <= QUIC_VERSION_31) {
+ available_range_bytes -= kNumberOfRevivedPacketsSize;
+ }
size_t max_num_ranges =
available_range_bytes /
(missing_packet_number_length + PACKET_1BYTE_PACKET_NUMBER);
@@ -2025,14 +2007,13 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicPacketHeader& header,
return false;
}
- uint64_t delta_time_largest_observed_us = kUFloat16MaxValue;
- if (!frame.delta_time_largest_observed.IsInfinite()) {
- DCHECK_LE(0u, frame.delta_time_largest_observed.ToMicroseconds());
- delta_time_largest_observed_us =
- frame.delta_time_largest_observed.ToMicroseconds();
+ 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(delta_time_largest_observed_us)) {
+ if (!writer->WriteUFloat16(ack_delay_time_us)) {
return false;
}
@@ -2073,26 +2054,17 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicPacketHeader& header,
}
DCHECK_EQ(num_missing_ranges, num_ranges_written);
- // Append revived packets.
- // If not all the revived packets fit, only mention the ones that do.
- uint8_t num_revived_packets = frame.latest_revived_packet == 0 ? 0 : 1;
- if (((writer->capacity() - writer->length()) / largest_observed_length) ==
- 0) {
- num_revived_packets = 0;
+ if (quic_version_ > QUIC_VERSION_31) {
+ return true;
}
+
+ // Append revived packets.
+ // FEC is not supported.
+ uint8_t num_revived_packets = 0;
if (!writer->WriteBytes(&num_revived_packets, 1)) {
return false;
}
- if (num_revived_packets > 0) {
- LOG_IF(DFATAL,
- !frame.missing_packets.Contains(frame.latest_revived_packet));
- if (!AppendPacketSequenceNumber(largest_observed_length,
- frame.latest_revived_packet, writer)) {
- return false;
- }
- }
-
return true;
}
@@ -2258,6 +2230,15 @@ bool QuicFramer::AppendBlockedFrame(const QuicBlockedFrame& frame,
return true;
}
+bool QuicFramer::AppendPathCloseFrame(const QuicPathCloseFrame& frame,
+ QuicDataWriter* writer) {
+ uint8_t path_id = static_cast<uint8_t>(frame.path_id);
+ if (!writer->WriteUInt8(path_id)) {
+ return false;
+ }
+ return true;
+}
+
bool QuicFramer::RaiseError(QuicErrorCode error) {
DVLOG(1) << "Error: " << QuicUtils::ErrorToString(error)
<< " detail: " << detailed_error_;
diff --git a/chromium/net/quic/quic_framer.h b/chromium/net/quic/quic_framer.h
index a7fd9fa3662..a0a0db1afeb 100644
--- a/chromium/net/quic/quic_framer.h
+++ b/chromium/net/quic/quic_framer.h
@@ -9,6 +9,8 @@
#include <stdint.h>
#include <string>
+#include <unordered_map>
+#include <unordered_set>
#include <vector>
#include "base/logging.h"
@@ -89,10 +91,6 @@ class NET_EXPORT_PRIVATE QuicFramerVisitorInterface {
virtual void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) = 0;
- // Called when a lost packet has been recovered via FEC,
- // before it has been processed.
- virtual void OnRevivedPacket() = 0;
-
// Called when the public header has been parsed, but has not been
// authenticated. If it returns false, framing for this packet will cease.
virtual bool OnUnauthenticatedPublicHeader(
@@ -111,10 +109,6 @@ class NET_EXPORT_PRIVATE QuicFramerVisitorInterface {
// If OnPacketHeader returns false, framing for this packet will cease.
virtual bool OnPacketHeader(const QuicPacketHeader& header) = 0;
- // Called when a data packet is parsed that is part of an FEC group.
- // |payload| is the non-encrypted FEC protected payload of the packet.
- virtual void OnFecProtectedPayload(base::StringPiece payload) = 0;
-
// Called when a StreamFrame has been parsed.
virtual bool OnStreamFrame(const QuicStreamFrame& frame) = 0;
@@ -144,8 +138,8 @@ class NET_EXPORT_PRIVATE QuicFramerVisitorInterface {
// Called when a BlockedFrame has been parsed.
virtual bool OnBlockedFrame(const QuicBlockedFrame& frame) = 0;
- // Called when FEC data has been parsed.
- virtual void OnFecData(base::StringPiece redundancy) = 0;
+ // Called when a PathCloseFrame has been parsed.
+ virtual bool OnPathCloseFrame(const QuicPathCloseFrame& frame) = 0;
// Called when a packet has been completely processed.
virtual void OnPacketComplete() = 0;
@@ -168,8 +162,6 @@ class NET_EXPORT_PRIVATE QuicReceivedEntropyHashCalculatorInterface {
// Class for parsing and constructing QUIC packets. It has a
// QuicFramerVisitorInterface that is called when packets are parsed.
-// It also has a QuicFecBuilder that is called when packets are constructed
-// in order to generate FEC data for subsequently building FEC packets.
class NET_EXPORT_PRIVATE QuicFramer {
public:
// Constructs a new framer that installs a kNULL QuicEncrypter and
@@ -223,18 +215,10 @@ class NET_EXPORT_PRIVATE QuicFramer {
// ignored.
bool ProcessPacket(const QuicEncryptedPacket& packet);
- // Pass a data packet that was revived from FEC data into the framer
- // for parsing.
- // Return true if the packet was processed succesfully. |payload| must be
- // the complete DECRYPTED payload of the revived packet.
- bool ProcessRevivedPacket(QuicPacketHeader* header,
- base::StringPiece payload);
-
// Largest size in bytes of all stream frame fields without the payload.
static size_t GetMinStreamFrameSize(QuicStreamId stream_id,
QuicStreamOffset offset,
- bool last_frame_in_packet,
- InFecGroup is_in_fec_group);
+ bool last_frame_in_packet);
// Size in bytes of all ack frame fields without the missing packets.
static size_t GetMinAckFrameSize(
QuicPacketNumberLength largest_observed_length);
@@ -255,6 +239,8 @@ class NET_EXPORT_PRIVATE QuicFramer {
static size_t GetWindowUpdateFrameSize();
// Size in bytes of all Blocked frame fields.
static size_t GetBlockedFrameSize();
+ // Size in bytes of all PathClose frame fields.
+ static size_t GetPathCloseFrameSize();
// Size in bytes required to serialize the stream id.
static size_t GetStreamIdSize(QuicStreamId stream_id);
// Size in bytes required to serialize the stream offset.
@@ -269,7 +255,6 @@ class NET_EXPORT_PRIVATE QuicFramer {
size_t free_bytes,
bool first_frame_in_packet,
bool last_frame_in_packet,
- InFecGroup is_in_fec_group,
QuicPacketNumberLength packet_number_length);
// Returns the associated data from the encrypted packet |encrypted| as a
@@ -278,6 +263,7 @@ class NET_EXPORT_PRIVATE QuicFramer {
const QuicEncryptedPacket& encrypted,
QuicConnectionIdLength connection_id_length,
bool includes_version,
+ bool includes_path_id,
QuicPacketNumberLength packet_number_length);
// Serializes a packet containing |frames| into |buffer|.
@@ -288,12 +274,6 @@ class NET_EXPORT_PRIVATE QuicFramer {
char* buffer,
size_t packet_length);
- // Returns a QuicPacket* that is owned by the caller, and is populated with
- // the fields in |header| and |fec|. Returns nullptr if the packet could
- // not be created.
- QuicPacket* BuildFecPacket(const QuicPacketHeader& header,
- base::StringPiece redundancy);
-
// Returns a new public reset packet, owned by the caller.
static QuicEncryptedPacket* BuildPublicResetPacket(
const QuicPublicResetPacket& packet);
@@ -327,9 +307,21 @@ class NET_EXPORT_PRIVATE QuicFramer {
// takes ownership of |encrypter|.
void SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter);
+ // Encrypts a payload in |buffer|. |ad_len| is the length of the associated
+ // data. |total_len| is the length of the associated data plus plaintext.
+ // |buffer_len| is the full length of the allocated buffer.
+ size_t EncryptInPlace(EncryptionLevel level,
+ QuicPathId path_id,
+ QuicPacketNumber packet_number,
+ size_t ad_len,
+ size_t total_len,
+ size_t buffer_len,
+ char* buffer);
+
// Returns the length of the data encrypted into |buffer| if |buffer_len| is
// long enough, and otherwise 0.
size_t EncryptPayload(EncryptionLevel level,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
const QuicPacket& packet,
char* buffer,
@@ -360,6 +352,8 @@ class NET_EXPORT_PRIVATE QuicFramer {
// Called when a PATH_CLOSED frame has been sent/received on |path_id|.
void OnPathClosed(QuicPathId path_id);
+ QuicTag last_version_tag() { return last_version_tag_; }
+
private:
friend class test::QuicFramerPeer;
@@ -367,6 +361,7 @@ class NET_EXPORT_PRIVATE QuicFramer {
struct AckFrameInfo {
AckFrameInfo();
+ AckFrameInfo(const AckFrameInfo& other);
~AckFrameInfo();
// The maximum delta between ranges.
@@ -423,6 +418,7 @@ class NET_EXPORT_PRIVATE QuicFramer {
bool ProcessWindowUpdateFrame(QuicDataReader* reader,
QuicWindowUpdateFrame* frame);
bool ProcessBlockedFrame(QuicDataReader* reader, QuicBlockedFrame* frame);
+ bool ProcessPathCloseFrame(QuicDataReader* reader, QuicPathCloseFrame* frame);
bool DecryptPayload(QuicDataReader* encrypted_reader,
const QuicPacketHeader& header,
@@ -454,7 +450,6 @@ class NET_EXPORT_PRIVATE QuicFramer {
// Computes the wire size in bytes of the payload of |frame|.
size_t ComputeFrameLength(const QuicFrame& frame,
bool last_frame_in_packet,
- InFecGroup is_in_fec_group,
QuicPacketNumberLength packet_number_length);
static bool AppendPacketSequenceNumber(
@@ -498,6 +493,8 @@ class NET_EXPORT_PRIVATE QuicFramer {
QuicDataWriter* writer);
bool AppendBlockedFrame(const QuicBlockedFrame& frame,
QuicDataWriter* writer);
+ bool AppendPathCloseFrame(const QuicPathCloseFrame& frame,
+ QuicDataWriter* writer);
bool RaiseError(QuicErrorCode error);
@@ -513,16 +510,18 @@ class NET_EXPORT_PRIVATE QuicFramer {
// has been sent/received.
// TODO(fayang): this set is never cleaned up. A possible improvement is to
// use intervals.
- base::hash_set<QuicPathId> closed_paths_;
- // Map mapping path id to packet number of last successfully decrypted/revived
+ std::unordered_set<QuicPathId> closed_paths_;
+ // Map mapping path id to packet number of last successfully decrypted
// received packet.
- base::hash_map<QuicPathId, QuicPacketNumber> last_packet_numbers_;
+ std::unordered_map<QuicPathId, QuicPacketNumber> last_packet_numbers_;
// Updated by ProcessPacketHeader when it succeeds.
QuicPacketNumber last_packet_number_;
- // The path on which last successfully decrypted/revived packet was received.
+ // The path on which last successfully decrypted packet was received.
QuicPathId last_path_id_;
// Updated by WritePacketHeader.
QuicConnectionId last_serialized_connection_id_;
+ // The last QUIC version tag received.
+ QuicTag last_version_tag_;
// Version of the protocol being used.
QuicVersion quic_version_;
// This vector contains QUIC versions which we currently support.
diff --git a/chromium/net/quic/quic_framer_test.cc b/chromium/net/quic/quic_framer_test.cc
index da33b641eb3..07ad2763a7b 100644
--- a/chromium/net/quic/quic_framer_test.cc
+++ b/chromium/net/quic/quic_framer_test.cc
@@ -10,7 +10,6 @@
#include <string>
#include <vector>
-#include "base/containers/hash_tables.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
@@ -22,7 +21,6 @@
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/test/gtest_util.h"
-using base::hash_set;
using base::StringPiece;
using std::make_pair;
using std::map;
@@ -106,29 +104,6 @@ size_t GetPrivateFlagsOffset(bool include_version,
packet_number_length;
}
-// Index into the fec group offset in the header.
-size_t GetFecGroupOffset(QuicConnectionIdLength connection_id_length,
- bool include_version,
- bool include_path_id) {
- return GetPrivateFlagsOffset(connection_id_length, include_version,
- include_path_id) +
- kPrivateFlagsSize;
-}
-
-size_t GetFecGroupOffset(bool include_version, bool include_path_id) {
- return GetPrivateFlagsOffset(PACKET_8BYTE_CONNECTION_ID, include_version,
- include_path_id) +
- kPrivateFlagsSize;
-}
-
-size_t GetFecGroupOffset(bool include_version,
- bool include_path_id,
- QuicPacketNumberLength packet_number_length) {
- return GetPrivateFlagsOffset(include_version, include_path_id,
- packet_number_length) +
- kPrivateFlagsSize;
-}
-
// Index into the message tag of the public reset packet.
// Public resets always have full connection_ids.
const size_t kPublicResetPacketMessageTagOffset =
@@ -139,12 +114,14 @@ class TestEncrypter : public QuicEncrypter {
~TestEncrypter() override {}
bool SetKey(StringPiece key) override { return true; }
bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; }
- bool EncryptPacket(QuicPacketNumber packet_number,
+ bool EncryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
StringPiece associated_data,
StringPiece plaintext,
char* output,
size_t* output_length,
size_t max_output_length) override {
+ path_id_ = path_id;
packet_number_ = packet_number;
associated_data_ = associated_data.as_string();
plaintext_ = plaintext.as_string();
@@ -162,6 +139,7 @@ class TestEncrypter : public QuicEncrypter {
}
StringPiece GetKey() const override { return StringPiece(); }
StringPiece GetNoncePrefix() const override { return StringPiece(); }
+ QuicPathId path_id_;
QuicPacketNumber packet_number_;
string associated_data_;
string plaintext_;
@@ -172,12 +150,14 @@ class TestDecrypter : public QuicDecrypter {
~TestDecrypter() override {}
bool SetKey(StringPiece key) override { return true; }
bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; }
- bool DecryptPacket(QuicPacketNumber packet_number,
- const StringPiece& associated_data,
- const StringPiece& ciphertext,
+ bool DecryptPacket(QuicPathId path_id,
+ QuicPacketNumber packet_number,
+ StringPiece associated_data,
+ StringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) override {
+ path_id_ = path_id;
packet_number_ = packet_number;
associated_data_ = associated_data.as_string();
ciphertext_ = ciphertext.as_string();
@@ -190,6 +170,7 @@ 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; }
+ QuicPathId path_id_;
QuicPacketNumber packet_number_;
string associated_data_;
string ciphertext_;
@@ -202,9 +183,7 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
version_mismatch_(0),
packet_count_(0),
frame_count_(0),
- fec_count_(0),
complete_packets_(0),
- revived_packets_(0),
accept_packet_(true),
accept_public_header_(true) {}
@@ -233,8 +212,6 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
version_negotiation_packet_.reset(new QuicVersionNegotiationPacket(packet));
}
- void OnRevivedPacket() override { ++revived_packets_; }
-
bool OnProtocolVersionMismatch(QuicVersion version) override {
DVLOG(1) << "QuicFramer Version Mismatch, version: " << version;
++version_mismatch_;
@@ -254,6 +231,10 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
void OnDecryptedPacket(EncryptionLevel level) override {}
bool OnPacketHeader(const QuicPacketHeader& header) override {
+ if (header.fec_flag) {
+ // Drop any FEC packet.
+ return false;
+ }
++packet_count_;
header_.reset(new QuicPacketHeader(header));
return accept_packet_;
@@ -271,10 +252,6 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
return true;
}
- void OnFecProtectedPayload(StringPiece payload) override {
- fec_protected_payload_ = payload.as_string();
- }
-
bool OnAckFrame(const QuicAckFrame& frame) override {
++frame_count_;
ack_frames_.push_back(new QuicAckFrame(frame));
@@ -293,11 +270,6 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
return true;
}
- void OnFecData(StringPiece redundancy) override {
- ++fec_count_;
- fec_data_redundancy_.push_back(redundancy.as_string());
- }
-
void OnPacketComplete() override { ++complete_packets_; }
bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override {
@@ -325,14 +297,17 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
return true;
}
+ bool OnPathCloseFrame(const QuicPathCloseFrame& frame) override {
+ path_close_frame_ = frame;
+ return true;
+ }
+
// Counters from the visitor_ callbacks.
int error_count_;
int version_mismatch_;
int packet_count_;
int frame_count_;
- int fec_count_;
int complete_packets_;
- int revived_packets_;
bool accept_packet_;
bool accept_public_header_;
@@ -344,14 +319,13 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
vector<QuicAckFrame*> ack_frames_;
vector<QuicStopWaitingFrame*> stop_waiting_frames_;
vector<QuicPingFrame*> ping_frames_;
- string fec_protected_payload_;
QuicRstStreamFrame rst_stream_frame_;
QuicConnectionCloseFrame connection_close_frame_;
QuicGoAwayFrame goaway_frame_;
QuicWindowUpdateFrame window_update_frame_;
QuicBlockedFrame blocked_frame_;
+ QuicPathCloseFrame path_close_frame_;
vector<string*> stream_data_;
- vector<string> fec_data_redundancy_;
};
class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
@@ -381,7 +355,9 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
return static_cast<unsigned char>('0' + (version_ / 10) % 10);
}
- bool CheckEncryption(QuicPacketNumber packet_number, QuicPacket* packet) {
+ bool CheckEncryption(QuicPathId path_id,
+ QuicPacketNumber packet_number,
+ QuicPacket* packet) {
if (packet_number != encrypter_->packet_number_) {
LOG(ERROR) << "Encrypted incorrect packet number. expected "
<< packet_number << " actual: " << encrypter_->packet_number_;
@@ -403,7 +379,8 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
}
bool CheckDecryption(const QuicEncryptedPacket& encrypted,
- bool includes_version) {
+ bool includes_version,
+ bool includes_path_id) {
if (visitor_.header_->packet_number != decrypter_->packet_number_) {
LOG(ERROR) << "Decrypted incorrect packet number. expected "
<< visitor_.header_->packet_number
@@ -412,17 +389,18 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
}
if (QuicFramer::GetAssociatedDataFromEncryptedPacket(
encrypted, PACKET_8BYTE_CONNECTION_ID, includes_version,
+ includes_path_id,
PACKET_6BYTE_PACKET_NUMBER) != decrypter_->associated_data_) {
LOG(ERROR) << "Decrypted incorrect associated data. expected "
<< QuicFramer::GetAssociatedDataFromEncryptedPacket(
encrypted, PACKET_8BYTE_CONNECTION_ID, includes_version,
- PACKET_6BYTE_PACKET_NUMBER)
+ includes_path_id, PACKET_6BYTE_PACKET_NUMBER)
<< " actual: " << decrypter_->associated_data_;
return false;
}
StringPiece ciphertext(encrypted.AsStringPiece().substr(
GetStartOfEncryptedData(PACKET_8BYTE_CONNECTION_ID, includes_version,
- PACKET_6BYTE_PACKET_NUMBER)));
+ includes_path_id, PACKET_6BYTE_PACKET_NUMBER)));
if (ciphertext != decrypter_->ciphertext_) {
LOG(ERROR) << "Decrypted incorrect ciphertext data. expected "
<< ciphertext << " actual: " << decrypter_->ciphertext_;
@@ -465,8 +443,7 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
CheckProcessingFails(
packet,
i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, include_version,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
expected_error, QUIC_INVALID_STREAM_DATA);
}
}
@@ -632,10 +609,10 @@ TEST_P(QuicFramerTest, LargePacket) {
memset(packet + GetPacketHeaderSize(
PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId,
- PACKET_6BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP), 0,
+ PACKET_6BYTE_PACKET_NUMBER), 0,
kMaxPacketSize - GetPacketHeaderSize(
PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId,
- PACKET_6BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP) + 1);
+ PACKET_6BYTE_PACKET_NUMBER) + 1);
// clang-format on
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
@@ -680,8 +657,7 @@ TEST_P(QuicFramerTest, PacketHeader) {
// Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP);
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER);
++i) {
string expected_error;
if (i < kConnectionIdOffset) {
@@ -690,10 +666,8 @@ TEST_P(QuicFramerTest, PacketHeader) {
expected_error = "Unable to read ConnectionId.";
} else if (i < GetPrivateFlagsOffset(!kIncludeVersion, !kIncludePathId)) {
expected_error = "Unable to read packet number.";
- } else if (i < GetFecGroupOffset(!kIncludeVersion, !kIncludePathId)) {
- expected_error = "Unable to read private flags.";
} else {
- expected_error = "Unable to read first fec protected packet offset.";
+ expected_error = "Unable to read private flags.";
}
CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
@@ -733,8 +707,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith4ByteConnectionId) {
// Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_4BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP);
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER);
++i) {
string expected_error;
if (i < kConnectionIdOffset) {
@@ -745,11 +718,8 @@ TEST_P(QuicFramerTest, PacketHeaderWith4ByteConnectionId) {
} else if (i < GetPrivateFlagsOffset(PACKET_4BYTE_CONNECTION_ID,
!kIncludeVersion, !kIncludePathId)) {
expected_error = "Unable to read packet number.";
- } else if (i < GetFecGroupOffset(PACKET_4BYTE_CONNECTION_ID,
- !kIncludeVersion, !kIncludePathId)) {
- expected_error = "Unable to read private flags.";
} else {
- expected_error = "Unable to read first fec protected packet offset.";
+ expected_error = "Unable to read private flags.";
}
CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
@@ -789,8 +759,7 @@ TEST_P(QuicFramerTest, PacketHeader1ByteConnectionId) {
// Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_1BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP);
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER);
++i) {
string expected_error;
if (i < kConnectionIdOffset) {
@@ -801,11 +770,8 @@ TEST_P(QuicFramerTest, PacketHeader1ByteConnectionId) {
} else if (i < GetPrivateFlagsOffset(PACKET_1BYTE_CONNECTION_ID,
!kIncludeVersion, !kIncludePathId)) {
expected_error = "Unable to read packet number.";
- } else if (i < GetFecGroupOffset(PACKET_1BYTE_CONNECTION_ID,
- !kIncludeVersion, !kIncludePathId)) {
- expected_error = "Unable to read private flags.";
} else {
- expected_error = "Unable to read first fec protected packet offset.";
+ expected_error = "Unable to read private flags.";
}
CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
@@ -845,8 +811,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
// Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_0BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP);
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER);
++i) {
string expected_error;
if (i < kConnectionIdOffset) {
@@ -857,11 +822,8 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
} else if (i < GetPrivateFlagsOffset(PACKET_0BYTE_CONNECTION_ID,
!kIncludeVersion, !kIncludePathId)) {
expected_error = "Unable to read packet number.";
- } else if (i < GetFecGroupOffset(PACKET_0BYTE_CONNECTION_ID,
- !kIncludeVersion, !kIncludePathId)) {
- expected_error = "Unable to read private flags.";
} else {
- expected_error = "Unable to read first fec protected packet offset.";
+ expected_error = "Unable to read private flags.";
}
CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
@@ -902,8 +864,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) {
// Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP);
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER);
++i) {
string expected_error;
if (i < kConnectionIdOffset) {
@@ -914,10 +875,8 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) {
expected_error = "Unable to read protocol version.";
} else if (i < GetPrivateFlagsOffset(kIncludeVersion, !kIncludePathId)) {
expected_error = "Unable to read packet number.";
- } else if (i < GetFecGroupOffset(kIncludeVersion, !kIncludePathId)) {
- expected_error = "Unable to read private flags.";
} else {
- expected_error = "Unable to read first fec protected packet offset.";
+ expected_error = "Unable to read private flags.";
}
CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
@@ -943,6 +902,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithMultipathFlag) {
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, kIncludePathId));
EXPECT_EQ(kConnectionId, visitor_.header_->public_header.connection_id);
EXPECT_TRUE(visitor_.header_->public_header.multipath_flag);
EXPECT_FALSE(visitor_.header_->public_header.reset_flag);
@@ -958,8 +918,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithMultipathFlag) {
// Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP);
+ kIncludePathId, PACKET_6BYTE_PACKET_NUMBER);
++i) {
string expected_error;
if (i < kConnectionIdOffset) {
@@ -971,10 +930,8 @@ TEST_P(QuicFramerTest, PacketHeaderWithMultipathFlag) {
expected_error = "Unable to read path id.";
} else if (i < GetPrivateFlagsOffset(!kIncludeVersion, kIncludePathId)) {
expected_error = "Unable to read packet number.";
- } else if (i < GetFecGroupOffset(!kIncludeVersion, kIncludePathId)) {
- expected_error = "Unable to read private flags.";
} else {
- expected_error = "Unable to read first fec protected packet offset.";
+ expected_error = "Unable to read private flags.";
}
CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
@@ -1002,6 +959,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithBothVersionFlagAndMultipathFlag) {
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(encrypted, kIncludeVersion, kIncludePathId));
EXPECT_EQ(kConnectionId, visitor_.header_->public_header.connection_id);
EXPECT_TRUE(visitor_.header_->public_header.multipath_flag);
EXPECT_FALSE(visitor_.header_->public_header.reset_flag);
@@ -1018,8 +976,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithBothVersionFlagAndMultipathFlag) {
// Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP);
+ kIncludePathId, PACKET_6BYTE_PACKET_NUMBER);
++i) {
string expected_error;
if (i < kConnectionIdOffset) {
@@ -1033,10 +990,8 @@ TEST_P(QuicFramerTest, PacketHeaderWithBothVersionFlagAndMultipathFlag) {
expected_error = "Unable to read path id.";
} else if (i < GetPrivateFlagsOffset(kIncludeVersion, kIncludePathId)) {
expected_error = "Unable to read packet number.";
- } else if (i < GetFecGroupOffset(kIncludeVersion, kIncludePathId)) {
- expected_error = "Unable to read private flags.";
} else {
- expected_error = "Unable to read first fec protected packet offset.";
+ expected_error = "Unable to read private flags.";
}
CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
@@ -1183,8 +1138,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) {
// Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_4BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP);
+ !kIncludePathId, PACKET_4BYTE_PACKET_NUMBER);
++i) {
string expected_error;
if (i < kConnectionIdOffset) {
@@ -1194,11 +1148,8 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) {
} else if (i < GetPrivateFlagsOffset(!kIncludeVersion, !kIncludePathId,
PACKET_4BYTE_PACKET_NUMBER)) {
expected_error = "Unable to read packet number.";
- } else if (i < GetFecGroupOffset(!kIncludeVersion, !kIncludePathId,
- PACKET_4BYTE_PACKET_NUMBER)) {
- expected_error = "Unable to read private flags.";
} else {
- expected_error = "Unable to read first fec protected packet offset.";
+ expected_error = "Unable to read private flags.";
}
CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
@@ -1238,8 +1189,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) {
// Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_2BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP);
+ !kIncludePathId, PACKET_2BYTE_PACKET_NUMBER);
++i) {
string expected_error;
if (i < kConnectionIdOffset) {
@@ -1249,11 +1199,8 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) {
} else if (i < GetPrivateFlagsOffset(!kIncludeVersion, !kIncludePathId,
PACKET_2BYTE_PACKET_NUMBER)) {
expected_error = "Unable to read packet number.";
- } else if (i < GetFecGroupOffset(!kIncludeVersion, !kIncludePathId,
- PACKET_2BYTE_PACKET_NUMBER)) {
- expected_error = "Unable to read private flags.";
} else {
- expected_error = "Unable to read first fec protected packet offset.";
+ expected_error = "Unable to read private flags.";
}
CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
@@ -1293,8 +1240,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) {
// Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_1BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP);
+ !kIncludePathId, PACKET_1BYTE_PACKET_NUMBER);
++i) {
string expected_error;
if (i < kConnectionIdOffset) {
@@ -1304,11 +1250,8 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) {
} else if (i < GetPrivateFlagsOffset(!kIncludeVersion, !kIncludePathId,
PACKET_1BYTE_PACKET_NUMBER)) {
expected_error = "Unable to read packet number.";
- } else if (i < GetFecGroupOffset(!kIncludeVersion, !kIncludePathId,
- PACKET_1BYTE_PACKET_NUMBER)) {
- expected_error = "Unable to read private flags.";
} else {
- expected_error = "Unable to read first fec protected packet offset.";
+ expected_error = "Unable to read private flags.";
}
CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
@@ -1436,10 +1379,16 @@ TEST_P(QuicFramerTest, InvalidFECGroupOffset) {
0x10
};
// clang-format on
- CheckProcessingFails(packet, arraysize(packet),
- "First fec protected packet offset must be less "
- "than the packet number.",
- QUIC_INVALID_PACKET_HEADER);
+ if (framer_.version() > QUIC_VERSION_31) {
+ CheckProcessingFails(packet, arraysize(packet),
+ "Illegal private flags value.",
+ QUIC_INVALID_PACKET_HEADER);
+ } else {
+ CheckProcessingFails(packet, arraysize(packet),
+ "First fec protected packet offset must be less "
+ "than the packet number.",
+ QUIC_INVALID_PACKET_HEADER);
+ }
};
TEST_P(QuicFramerTest, PaddingFrame) {
@@ -1479,15 +1428,14 @@ TEST_P(QuicFramerTest, PaddingFrame) {
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
ASSERT_EQ(0u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
// A packet with no frames is not acceptable.
CheckProcessingFails(
packet, GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
"Packet has no frames.", QUIC_MISSING_PAYLOAD);
}
@@ -1526,7 +1474,7 @@ TEST_P(QuicFramerTest, StreamFrame) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
@@ -1574,7 +1522,7 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
@@ -1624,7 +1572,7 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
@@ -1674,7 +1622,7 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
@@ -1728,7 +1676,7 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) {
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(visitor_.header_->public_header.version_flag);
EXPECT_EQ(GetParam(), visitor_.header_->public_header.versions[0]);
- EXPECT_TRUE(CheckDecryption(encrypted, kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, kIncludeVersion, !kIncludePathId));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
@@ -1778,7 +1726,7 @@ TEST_P(QuicFramerTest, RejectPacket) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
ASSERT_EQ(0u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
@@ -1805,114 +1753,131 @@ TEST_P(QuicFramerTest, RejectPublicHeader) {
ASSERT_FALSE(visitor_.header_.get());
}
-TEST_P(QuicFramerTest, RevivedStreamFrame) {
- // clang-format off
- unsigned char payload[] = {
- // 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', '!',
- };
- // clang-format on
-
- QuicPacketHeader header;
- header.public_header.connection_id = kConnectionId;
- header.public_header.reset_flag = false;
- header.public_header.version_flag = false;
- header.fec_flag = true;
- header.entropy_flag = true;
- header.packet_number = kPacketNumber;
- header.fec_group = 0;
-
- // Do not encrypt the payload because the revived payload is post-encryption.
- EXPECT_TRUE(framer_.ProcessRevivedPacket(
- &header, StringPiece(AsChars(payload), arraysize(payload))));
-
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
- ASSERT_EQ(1, visitor_.revived_packets_);
- ASSERT_TRUE(visitor_.header_.get());
- EXPECT_EQ(kConnectionId, visitor_.header_->public_header.connection_id);
- EXPECT_FALSE(visitor_.header_->public_header.reset_flag);
- EXPECT_FALSE(visitor_.header_->public_header.version_flag);
- EXPECT_TRUE(visitor_.header_->fec_flag);
- EXPECT_TRUE(visitor_.header_->entropy_flag);
- EXPECT_EQ(1 << (header.packet_number % 8), visitor_.header_->entropy_hash);
- EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
- EXPECT_EQ(NOT_IN_FEC_GROUP, visitor_.header_->is_in_fec_group);
- EXPECT_EQ(0u, visitor_.header_->fec_group);
-
- ASSERT_EQ(1u, visitor_.stream_frames_.size());
- EXPECT_EQ(0u, visitor_.ack_frames_.size());
- EXPECT_EQ(kStreamId, visitor_.stream_frames_[0]->stream_id);
- EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
- EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
- CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
-}
-
-TEST_P(QuicFramerTest, StreamFrameInFecGroup) {
+TEST_P(QuicFramerTest, AckFrameTwoTimestamp) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
0x3C,
// connection_id
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags (fec group)
+ 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,
- // first fec protected packet offset
+ // Delta from largest observed.
+ 0x01,
+ // Delta time.
+ 0x10, 0x32, 0x54, 0x76,
+ // Delta from largest observed.
0x02,
-
- // 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', '!',
+ // Delta time.
+ 0x10, 0x32,
+ // num missing packets
+ 0x01,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
+ // Number of revived packets.
+ 0x00,
};
// clang-format on
+ if (framer_.version() > QUIC_VERSION_31) {
+ 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));
- EXPECT_EQ(IN_FEC_GROUP, visitor_.header_->is_in_fec_group);
- EXPECT_EQ(kPacketNumber - 2, visitor_.header_->fec_group);
- const size_t fec_offset = GetStartOfFecProtectedData(
- PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_PACKET_NUMBER);
- EXPECT_EQ(
- string(AsChars(packet) + fec_offset, arraysize(packet) - fec_offset),
- visitor_.fec_protected_payload_);
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
- ASSERT_EQ(1u, visitor_.stream_frames_.size());
- EXPECT_EQ(0u, visitor_.ack_frames_.size());
- EXPECT_EQ(kStreamId, visitor_.stream_frames_[0]->stream_id);
- EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
- EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
- CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ const QuicAckFrame& frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame.entropy_hash);
+ EXPECT_EQ(kLargestObserved, frame.largest_observed);
+ ASSERT_EQ(1u, frame.missing_packets.NumPacketsSlow());
+ ASSERT_EQ(2u, frame.received_packet_times.size());
+ EXPECT_EQ(kMissingPacket, frame.missing_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;
+ const size_t kMissingPacketsRange =
+ kMissingPacketsOffset + PACKET_1BYTE_PACKET_NUMBER;
+ const size_t kRevivedPacketsLength =
+ kMissingPacketsRange + PACKET_1BYTE_PACKET_NUMBER;
+ // Now test framing boundaries.
+ const size_t ack_frame_size =
+ kRevivedPacketsLength + 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 if (i < kMissingPacketsRange) {
+ expected_error = "Unable to read missing packet number delta.";
+ } else if (i < kRevivedPacketsLength) {
+ expected_error = "Unable to read missing packet number range.";
+ } else {
+ expected_error = "Unable to read num revived packets.";
+ }
+ CheckProcessingFails(
+ packet,
+ i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
+ expected_error, QUIC_INVALID_ACK_DATA);
+ }
}
-TEST_P(QuicFramerTest, AckFrameTwoTimestamp) {
+TEST_P(QuicFramerTest, AckFrameTwoTimestampVersion32) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
@@ -1949,17 +1914,19 @@ TEST_P(QuicFramerTest, AckFrameTwoTimestamp) {
0x01,
// 0 more missing packets in range.
0x00,
- // Number of revived packets.
- 0x00,
};
// clang-format on
+ if (framer_.version() <= QUIC_VERSION_31) {
+ 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));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(0u, visitor_.stream_frames_.size());
ASSERT_EQ(1u, visitor_.ack_frames_.size());
@@ -1989,13 +1956,8 @@ TEST_P(QuicFramerTest, AckFrameTwoTimestamp) {
kTimestampTimeDeltaLargestObserved2 + 2;
const size_t kMissingPacketsOffset =
kNumMissingPacketOffset + kNumberOfNackRangesSize;
- const size_t kMissingPacketsRange =
- kMissingPacketsOffset + PACKET_1BYTE_PACKET_NUMBER;
- const size_t kRevivedPacketsLength =
- kMissingPacketsRange + PACKET_1BYTE_PACKET_NUMBER;
// Now test framing boundaries.
- const size_t ack_frame_size =
- kRevivedPacketsLength + PACKET_1BYTE_PACKET_NUMBER;
+ 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) {
@@ -2003,7 +1965,7 @@ TEST_P(QuicFramerTest, AckFrameTwoTimestamp) {
} else if (i < kMissingDeltaTimeOffset) {
expected_error = "Unable to read largest observed.";
} else if (i < kNumTimestampsOffset) {
- expected_error = "Unable to read delta time largest observed.";
+ expected_error = "Unable to read ack delay time.";
} else if (i < kTimestampDeltaLargestObserved1) {
expected_error = "Unable to read num received packets.";
} else if (i < kTimestampTimeDeltaLargestObserved1) {
@@ -2017,18 +1979,13 @@ TEST_P(QuicFramerTest, AckFrameTwoTimestamp) {
"Unable to read incremental time delta in received packets.";
} else if (i < kMissingPacketsOffset) {
expected_error = "Unable to read num missing packet ranges.";
- } else if (i < kMissingPacketsRange) {
- expected_error = "Unable to read missing packet number delta.";
- } else if (i < kRevivedPacketsLength) {
- expected_error = "Unable to read missing packet number range.";
} else {
- expected_error = "Unable to read num revived packets.";
+ expected_error = "Unable to read missing packet number delta.";
}
CheckProcessingFails(
packet,
i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
expected_error, QUIC_INVALID_ACK_DATA);
}
}
@@ -2071,12 +2028,16 @@ TEST_P(QuicFramerTest, AckFrameOneTimestamp) {
};
// clang-format on
+ if (framer_.version() > QUIC_VERSION_31) {
+ 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));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(0u, visitor_.stream_frames_.size());
ASSERT_EQ(1u, visitor_.ack_frames_.size());
@@ -2115,7 +2076,7 @@ TEST_P(QuicFramerTest, AckFrameOneTimestamp) {
} else if (i < kMissingDeltaTimeOffset) {
expected_error = "Unable to read largest observed.";
} else if (i < kNumTimestampsOffset) {
- expected_error = "Unable to read delta time largest observed.";
+ expected_error = "Unable to read ack delay time.";
} else if (i < kTimestampDeltaLargestObserved) {
expected_error = "Unable to read num received packets.";
} else if (i < kTimestampTimeDeltaLargestObserved) {
@@ -2134,8 +2095,106 @@ TEST_P(QuicFramerTest, AckFrameOneTimestamp) {
CheckProcessingFails(
packet,
i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ !kIncludePathId, 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_31) {
+ 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));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ const QuicAckFrame& frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame.entropy_hash);
+ EXPECT_EQ(kLargestObserved, frame.largest_observed);
+ ASSERT_EQ(1u, frame.missing_packets.NumPacketsSlow());
+ ASSERT_EQ(1u, frame.received_packet_times.size());
+ EXPECT_EQ(kMissingPacket, frame.missing_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(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
expected_error, QUIC_INVALID_ACK_DATA);
}
}
@@ -2174,12 +2233,16 @@ TEST_P(QuicFramerTest, AckFrame) {
};
// clang-format on
+ if (framer_.version() > QUIC_VERSION_31) {
+ 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));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(0u, visitor_.stream_frames_.size());
ASSERT_EQ(1u, visitor_.ack_frames_.size());
@@ -2214,7 +2277,7 @@ TEST_P(QuicFramerTest, AckFrame) {
} else if (i < kMissingDeltaTimeOffset) {
expected_error = "Unable to read largest observed.";
} else if (i < kNumTimestampsOffset) {
- expected_error = "Unable to read delta time largest observed.";
+ expected_error = "Unable to read ack delay time.";
} else if (i < kNumMissingPacketOffset) {
expected_error = "Unable to read num received packets.";
} else if (i < kMissingPacketsOffset) {
@@ -2229,8 +2292,94 @@ TEST_P(QuicFramerTest, AckFrame) {
CheckProcessingFails(
packet,
i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
+ expected_error, QUIC_INVALID_ACK_DATA);
+ }
+}
+
+TEST_P(QuicFramerTest, AckFrameVersion32) {
+ // 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.
+ 0x00,
+ // num missing packets
+ 0x01,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
+ };
+ // clang-format on
+
+ if (framer_.version() <= QUIC_VERSION_31) {
+ 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));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ const QuicAckFrame& frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame.entropy_hash);
+ EXPECT_EQ(kLargestObserved, frame.largest_observed);
+ ASSERT_EQ(1u, frame.missing_packets.NumPacketsSlow());
+ EXPECT_EQ(kMissingPacket, frame.missing_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(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
expected_error, QUIC_INVALID_ACK_DATA);
}
}
@@ -2273,12 +2422,16 @@ TEST_P(QuicFramerTest, AckFrameRevivedPackets) {
};
// clang-format on
+ if (framer_.version() > QUIC_VERSION_31) {
+ 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));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(0u, visitor_.stream_frames_.size());
ASSERT_EQ(1u, visitor_.ack_frames_.size());
@@ -2317,7 +2470,7 @@ TEST_P(QuicFramerTest, AckFrameRevivedPackets) {
} else if (i < kMissingDeltaTimeOffset) {
expected_error = "Unable to read largest observed.";
} else if (i < kNumTimestampsOffset) {
- expected_error = "Unable to read delta time largest observed.";
+ expected_error = "Unable to read ack delay time.";
} else if (i < kNumMissingPacketOffset) {
expected_error = "Unable to read num received packets.";
} else if (i < kMissingPacketsOffset) {
@@ -2334,8 +2487,7 @@ TEST_P(QuicFramerTest, AckFrameRevivedPackets) {
CheckProcessingFails(
packet,
i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
expected_error, QUIC_INVALID_ACK_DATA);
}
}
@@ -2371,7 +2523,7 @@ TEST_P(QuicFramerTest, AckFrameNoNacks) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(0u, visitor_.stream_frames_.size());
ASSERT_EQ(1u, visitor_.ack_frames_.size());
@@ -2431,19 +2583,91 @@ TEST_P(QuicFramerTest, AckFrame500Nacks) {
};
// clang-format on
+ if (framer_.version() > QUIC_VERSION_31) {
+ 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));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ QuicAckFrame* frame = visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame->entropy_hash);
+ EXPECT_EQ(kLargestObserved, frame->largest_observed);
+ ASSERT_EQ(500u, frame->missing_packets.NumPacketsSlow());
+ EXPECT_EQ(kMissingPacket - 499, frame->missing_packets.Min());
+ EXPECT_EQ(kMissingPacket, frame->missing_packets.Max());
+
+ // Verify that the packet re-serializes identically.
+ QuicFrames frames;
+ frames.push_back(QuicFrame(frame));
+ scoped_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, AckFrame500NacksVersion32) {
+ // 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,
+ // 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_31) {
+ 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));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(0u, visitor_.stream_frames_.size());
ASSERT_EQ(1u, visitor_.ack_frames_.size());
QuicAckFrame* frame = visitor_.ack_frames_[0];
EXPECT_EQ(0xBA, frame->entropy_hash);
EXPECT_EQ(kLargestObserved, frame->largest_observed);
- EXPECT_EQ(0u, frame->latest_revived_packet);
ASSERT_EQ(500u, frame->missing_packets.NumPacketsSlow());
EXPECT_EQ(kMissingPacket - 499, frame->missing_packets.Min());
EXPECT_EQ(kMissingPacket, frame->missing_packets.Max());
@@ -2489,7 +2713,7 @@ TEST_P(QuicFramerTest, StopWaitingFrame) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(0u, visitor_.stream_frames_.size());
ASSERT_EQ(1u, visitor_.stop_waiting_frames_.size());
@@ -2510,8 +2734,7 @@ TEST_P(QuicFramerTest, StopWaitingFrame) {
CheckProcessingFails(
packet,
i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
expected_error, QUIC_INVALID_STOP_WAITING_DATA);
}
}
@@ -2549,7 +2772,7 @@ TEST_P(QuicFramerTest, RstStreamFrameQuic) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(kStreamId, visitor_.rst_stream_frame_.stream_id);
EXPECT_EQ(0x01, visitor_.rst_stream_frame_.error_code);
@@ -2571,8 +2794,7 @@ TEST_P(QuicFramerTest, RstStreamFrameQuic) {
CheckProcessingFails(
packet,
i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
expected_error, QUIC_INVALID_RST_STREAM_DATA);
}
}
@@ -2611,7 +2833,7 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(0u, visitor_.stream_frames_.size());
@@ -2632,8 +2854,7 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) {
CheckProcessingFails(
packet,
i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
expected_error, QUIC_INVALID_CONNECTION_CLOSE_DATA);
}
}
@@ -2673,7 +2894,7 @@ TEST_P(QuicFramerTest, GoAwayFrame) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(kStreamId, visitor_.goaway_frame_.last_good_stream_id);
EXPECT_EQ(0x9, visitor_.goaway_frame_.error_code);
@@ -2695,8 +2916,7 @@ TEST_P(QuicFramerTest, GoAwayFrame) {
CheckProcessingFails(
packet,
i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
expected_error, QUIC_INVALID_GOAWAY_DATA);
}
}
@@ -2731,7 +2951,7 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(kStreamId, visitor_.window_update_frame_.stream_id);
EXPECT_EQ(kStreamOffset, visitor_.window_update_frame_.byte_offset);
@@ -2748,8 +2968,7 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) {
CheckProcessingFails(
packet,
i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
expected_error, QUIC_INVALID_WINDOW_UPDATE_DATA);
}
}
@@ -2781,7 +3000,7 @@ TEST_P(QuicFramerTest, BlockedFrame) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(kStreamId, visitor_.blocked_frame_.stream_id);
@@ -2792,8 +3011,7 @@ TEST_P(QuicFramerTest, BlockedFrame) {
CheckProcessingFails(
packet,
i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
expected_error, QUIC_INVALID_BLOCKED_DATA);
}
}
@@ -2822,13 +3040,57 @@ TEST_P(QuicFramerTest, PingFrame) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
EXPECT_EQ(1u, visitor_.ping_frames_.size());
// No need to check the PING frame boundaries because it has no payload.
}
+TEST_P(QuicFramerTest, PathCloseFrame) {
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (version)
+ 0x7C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
+ // path_id
+ 0x00,
+ // packet number
+ 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // private flags
+ 0x00,
+
+ // frame type (path_close_frame)
+ 0x08,
+ // path id
+ 0x42,
+ };
+ // 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());
+ // TODO(fayang): CheckDecryption after cl/110553865 is landed.
+ EXPECT_EQ(kPathId, visitor_.path_close_frame_.path_id);
+
+ // Now test framing boundaries.
+ for (size_t i = kQuicFrameTypeSize; i < QuicFramer::GetPathCloseFrameSize();
+ ++i) {
+ string expected_error;
+ if (i < kQuicFrameTypeSize + kQuicPathIdSize) {
+ expected_error = "Unable to read path_id.";
+ }
+ CheckProcessingFails(
+ packet,
+ i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
+ expected_error, QUIC_INVALID_PATH_CLOSE_DATA);
+ }
+}
+
TEST_P(QuicFramerTest, PublicResetPacket) {
// clang-format off
unsigned char packet[] = {
@@ -2867,8 +3129,7 @@ TEST_P(QuicFramerTest, PublicResetPacket) {
EXPECT_TRUE(visitor_.public_reset_packet_->public_header.reset_flag);
EXPECT_FALSE(visitor_.public_reset_packet_->public_header.version_flag);
EXPECT_EQ(kNonceProof, visitor_.public_reset_packet_->nonce_proof);
- EXPECT_EQ(kPacketNumber,
- visitor_.public_reset_packet_->rejected_packet_number);
+ EXPECT_EQ(0u, visitor_.public_reset_packet_->rejected_packet_number);
EXPECT_EQ(ADDRESS_FAMILY_UNSPECIFIED,
visitor_.public_reset_packet_->client_address.GetFamily());
@@ -2974,11 +3235,9 @@ TEST_P(QuicFramerTest, PublicResetPacketWithClientAddress) {
EXPECT_TRUE(visitor_.public_reset_packet_->public_header.reset_flag);
EXPECT_FALSE(visitor_.public_reset_packet_->public_header.version_flag);
EXPECT_EQ(kNonceProof, visitor_.public_reset_packet_->nonce_proof);
- EXPECT_EQ(kPacketNumber,
- visitor_.public_reset_packet_->rejected_packet_number);
+ EXPECT_EQ(0u, visitor_.public_reset_packet_->rejected_packet_number);
EXPECT_EQ("4.31.198.44",
- IPAddressToString(
- visitor_.public_reset_packet_->client_address.address()));
+ visitor_.public_reset_packet_->client_address.address().ToString());
EXPECT_EQ(443, visitor_.public_reset_packet_->client_address.port());
// Now test framing boundaries.
@@ -3039,7 +3298,7 @@ TEST_P(QuicFramerTest, VersionNegotiationPacket) {
}
}
-TEST_P(QuicFramerTest, FecPacket) {
+TEST_P(QuicFramerTest, DropFecPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
@@ -3064,16 +3323,14 @@ TEST_P(QuicFramerTest, FecPacket) {
// 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));
-
- EXPECT_EQ(0u, visitor_.stream_frames_.size());
- EXPECT_EQ(0u, visitor_.ack_frames_.size());
- ASSERT_EQ(1, visitor_.fec_count_);
- EXPECT_EQ("abcdefghijklmnop", visitor_.fec_data_redundancy_[0]);
+ if (framer_.version() <= QUIC_VERSION_31) {
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ } else {
+ EXPECT_FALSE(framer_.ProcessPacket(encrypted));
+ EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ }
+ EXPECT_FALSE(visitor_.header_.get());
}
TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
@@ -3110,9 +3367,9 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
};
// clang-format on
- uint64_t header_size = GetPacketHeaderSize(
- PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId,
- PACKET_6BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP);
+ uint64_t header_size =
+ GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER);
memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
@@ -3157,9 +3414,9 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
};
// clang-format on
- uint64_t header_size = GetPacketHeaderSize(
- PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId,
- PACKET_4BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP);
+ uint64_t header_size =
+ GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ !kIncludePathId, PACKET_4BYTE_PACKET_NUMBER);
memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
@@ -3204,9 +3461,9 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
};
// clang-format on
- uint64_t header_size = GetPacketHeaderSize(
- PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId,
- PACKET_2BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP);
+ uint64_t header_size =
+ GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ !kIncludePathId, PACKET_2BYTE_PACKET_NUMBER);
memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
@@ -3251,9 +3508,9 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
};
// clang-format on
- uint64_t header_size = GetPacketHeaderSize(
- PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId,
- PACKET_1BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP);
+ uint64_t header_size =
+ GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ !kIncludePathId, PACKET_1BYTE_PACKET_NUMBER);
memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
@@ -3315,55 +3572,6 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) {
arraysize(packet));
}
-TEST_P(QuicFramerTest, BuildStreamFramePacketInFecGroup) {
- QuicPacketHeader header;
- header.public_header.connection_id = kConnectionId;
- header.public_header.reset_flag = false;
- header.public_header.version_flag = false;
- header.fec_flag = false;
- header.entropy_flag = true;
- header.packet_number = kPacketNumber;
- header.is_in_fec_group = IN_FEC_GROUP;
- header.fec_group = kPacketNumber;
-
- QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
- StringPiece("hello world!"));
-
- QuicFrames frames;
- frames.push_back(QuicFrame(&stream_frame));
- // 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
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
- // private flags (entropy, is_in_fec_group)
- 0x03,
- // FEC group
- 0x00,
- // frame type (stream frame with fin and data length field)
- 0xFF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32, 0xDC, 0xFE, 0x98, 0xBA,
- // data length (since packet is in an FEC group)
- 0x0C, 0x00,
- // data
- 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!',
- };
- // clang-format on
-
- scoped_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, BuildStreamFramePacketWithVersionFlag) {
QuicPacketHeader header;
header.public_header.connection_id = kConnectionId;
@@ -3559,7 +3767,7 @@ TEST_P(QuicFramerTest, BuildAckFramePacket) {
QuicAckFrame ack_frame;
ack_frame.entropy_hash = 0x43;
ack_frame.largest_observed = kLargestObserved;
- ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero();
+ ack_frame.ack_delay_time = QuicTime::Delta::Zero();
ack_frame.missing_packets.Add(kMissingPacket);
QuicFrames frames;
@@ -3598,12 +3806,49 @@ TEST_P(QuicFramerTest, BuildAckFramePacket) {
};
// clang-format on
+ // clang-format off
+ unsigned char packet_version32[] = {
+ // public flags (8 byte connection_id)
+ 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
+
scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- arraysize(packet));
+ if (framer_.version() <= QUIC_VERSION_31) {
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
+ } else {
+ test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(),
+ AsChars(packet_version32), arraysize(packet_version32));
+ }
}
// TODO(jri): Add test for tuncated packets in which the original ack frame had
@@ -3625,7 +3870,7 @@ TEST_P(QuicFramerTest, BuildTruncatedAckFrameLargePacket) {
// TestEntropyCalculator for this test.)
ack_frame.entropy_hash = 0x43;
ack_frame.largest_observed = 2 * 300;
- ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero();
+ ack_frame.ack_delay_time = QuicTime::Delta::Zero();
for (size_t i = 1; i < 2 * 300; i += 2) {
ack_frame.missing_packets.Add(i);
}
@@ -3712,12 +3957,94 @@ TEST_P(QuicFramerTest, BuildTruncatedAckFrameLargePacket) {
};
// clang-format on
+ // clang-format off
+ unsigned char packet_version32[] = {
+ // public flags (8 byte connection_id)
+ 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
+
scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- arraysize(packet));
+ if (framer_.version() <= QUIC_VERSION_31) {
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
+ } else {
+ test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(),
+ AsChars(packet_version32), arraysize(packet_version32));
+ }
}
TEST_P(QuicFramerTest, BuildTruncatedAckFrameSmallPacket) {
@@ -3736,7 +4063,7 @@ TEST_P(QuicFramerTest, BuildTruncatedAckFrameSmallPacket) {
// TestEntropyCalculator for this test.)
ack_frame.entropy_hash = 0x43;
ack_frame.largest_observed = 2 * 300;
- ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero();
+ ack_frame.ack_delay_time = QuicTime::Delta::Zero();
for (size_t i = 1; i < 2 * 300; i += 2) {
ack_frame.missing_packets.Add(i);
}
@@ -3776,13 +4103,53 @@ TEST_P(QuicFramerTest, BuildTruncatedAckFrameSmallPacket) {
};
// clang-format on
- scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames, 37u));
- ASSERT_TRUE(data != nullptr);
- // Expect 1 byte unused since at least 2 bytes are needed to fit more nacks.
- EXPECT_EQ(36u, data->length());
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- arraysize(packet));
+ // clang-format off
+ unsigned char packet_version32[] = {
+ // public flags (8 byte connection_id)
+ 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
+
+ if (framer_.version() <= QUIC_VERSION_31) {
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames, 37u));
+ ASSERT_TRUE(data != nullptr);
+ // Expect 1 byte unused since at least 2 bytes are needed to fit more nacks.
+ EXPECT_EQ(36u, data->length());
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
+ } else {
+ scoped_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_version32), arraysize(packet_version32));
+ }
}
TEST_P(QuicFramerTest, BuildStopWaitingPacket) {
@@ -4123,6 +4490,51 @@ TEST_P(QuicFramerTest, BuildPingPacket) {
arraysize(packet));
}
+TEST_P(QuicFramerTest, BuildPathClosePacket) {
+ QuicPacketHeader header;
+ header.public_header.connection_id = kConnectionId;
+ header.public_header.multipath_flag = true;
+ header.public_header.reset_flag = false;
+ header.public_header.version_flag = false;
+ header.fec_flag = false;
+ header.entropy_flag = true;
+ header.path_id = kDefaultPathId;
+ header.packet_number = kPacketNumber;
+ header.fec_group = 0;
+
+ QuicPathCloseFrame path_close;
+ path_close.path_id = kPathId;
+ QuicFrames frames;
+ frames.push_back(QuicFrame(&path_close));
+
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (version)
+ 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,
+ };
+ // clang-format on
+
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
+ ASSERT_TRUE(data != nullptr);
+
+ 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.
TEST_P(QuicFramerTest, BuildMtuDiscoveryPacket) {
QuicPacketHeader header;
@@ -4264,19 +4676,8 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketWithClientAddress) {
arraysize(packet));
}
-TEST_P(QuicFramerTest, BuildFecPacket) {
- QuicPacketHeader header;
- header.public_header.connection_id = kConnectionId;
- header.public_header.reset_flag = false;
- header.public_header.version_flag = false;
- header.fec_flag = true;
- header.entropy_flag = true;
- header.packet_number = kPacketNumber;
- header.is_in_fec_group = IN_FEC_GROUP;
- header.fec_group = kPacketNumber - 1;
-
- string redundancy = "abcdefghijklmnop";
-
+TEST_P(QuicFramerTest, EncryptPacket) {
+ QuicPacketNumber packet_number = kPacketNumber;
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
@@ -4287,10 +4688,8 @@ TEST_P(QuicFramerTest, BuildFecPacket) {
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags (entropy & fec group & fec packet)
- 0x07,
- // first fec protected packet offset
- 0x01,
+ // private flags
+ 0x00,
// redundancy
'a', 'b', 'c', 'd',
@@ -4300,30 +4699,34 @@ TEST_P(QuicFramerTest, BuildFecPacket) {
};
// clang-format on
- scoped_ptr<QuicPacket> data(framer_.BuildFecPacket(header, redundancy));
- ASSERT_TRUE(data != nullptr);
+ scoped_ptr<QuicPacket> raw(new QuicPacket(
+ AsChars(packet), arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID,
+ !kIncludeVersion, !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER));
+ char buffer[kMaxPacketSize];
+ size_t encrypted_length =
+ framer_.EncryptPayload(ENCRYPTION_NONE, kDefaultPathId, packet_number,
+ *raw, buffer, kMaxPacketSize);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- arraysize(packet));
+ ASSERT_NE(0u, encrypted_length);
+ EXPECT_TRUE(CheckEncryption(kDefaultPathId, packet_number, raw.get()));
}
-TEST_P(QuicFramerTest, EncryptPacket) {
+TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) {
QuicPacketNumber packet_number = kPacketNumber;
// clang-format off
unsigned char packet[] = {
- // public flags (8 byte connection_id)
- 0x3C,
+ // public flags (version, 8 byte connection_id)
+ 0x3D,
// connection_id
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
+ // version tag
+ 'Q', '.', '1', '0',
// packet number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags (fec group & fec packet)
- 0x06,
- // first fec protected packet offset
- 0x01,
+ // private flags
+ 0x00,
// redundancy
'a', 'b', 'c', 'd',
@@ -4335,33 +4738,70 @@ TEST_P(QuicFramerTest, EncryptPacket) {
scoped_ptr<QuicPacket> raw(new QuicPacket(
AsChars(packet), arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID,
- !kIncludeVersion, PACKET_6BYTE_PACKET_NUMBER));
+ kIncludeVersion, !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER));
+ char buffer[kMaxPacketSize];
+ size_t encrypted_length =
+ framer_.EncryptPayload(ENCRYPTION_NONE, kDefaultPathId, packet_number,
+ *raw, buffer, kMaxPacketSize);
+
+ ASSERT_NE(0u, encrypted_length);
+ EXPECT_TRUE(CheckEncryption(kDefaultPathId, packet_number, raw.get()));
+}
+
+TEST_P(QuicFramerTest, EncryptPacketWithMultipathFlag) {
+ QuicPacketNumber packet_number = kPacketNumber;
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (version, 8 byte connection_id)
+ 0x7C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // path_id
+ 0x42,
+ // 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',
+ };
+ // clang-format on
+
+ scoped_ptr<QuicPacket> raw(new QuicPacket(
+ AsChars(packet), arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID,
+ !kIncludeVersion, kIncludePathId, PACKET_6BYTE_PACKET_NUMBER));
char buffer[kMaxPacketSize];
size_t encrypted_length = framer_.EncryptPayload(
- ENCRYPTION_NONE, packet_number, *raw, buffer, kMaxPacketSize);
+ ENCRYPTION_NONE, kPathId, packet_number, *raw, buffer, kMaxPacketSize);
ASSERT_NE(0u, encrypted_length);
- EXPECT_TRUE(CheckEncryption(packet_number, raw.get()));
+ EXPECT_TRUE(CheckEncryption(kPathId, packet_number, raw.get()));
}
-TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) {
+TEST_P(QuicFramerTest, EncryptPacketWithBothVersionFlagAndMultipathFlag) {
QuicPacketNumber packet_number = kPacketNumber;
// clang-format off
unsigned char packet[] = {
// public flags (version, 8 byte connection_id)
- 0x3D,
+ 0x7D,
// 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,
- // private flags (fec group & fec flags)
- 0x06,
- // first fec protected packet offset
- 0x01,
+ // private flags
+ 0x00,
// redundancy
'a', 'b', 'c', 'd',
@@ -4373,13 +4813,13 @@ TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) {
scoped_ptr<QuicPacket> raw(new QuicPacket(
AsChars(packet), arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID,
- kIncludeVersion, PACKET_6BYTE_PACKET_NUMBER));
+ kIncludeVersion, kIncludePathId, PACKET_6BYTE_PACKET_NUMBER));
char buffer[kMaxPacketSize];
size_t encrypted_length = framer_.EncryptPayload(
- ENCRYPTION_NONE, packet_number, *raw, buffer, kMaxPacketSize);
+ ENCRYPTION_NONE, kPathId, packet_number, *raw, buffer, kMaxPacketSize);
ASSERT_NE(0u, encrypted_length);
- EXPECT_TRUE(CheckEncryption(packet_number, raw.get()));
+ EXPECT_TRUE(CheckEncryption(kPathId, packet_number, raw.get()));
}
TEST_P(QuicFramerTest, AckTruncationLargePacket) {
@@ -4404,9 +4844,9 @@ TEST_P(QuicFramerTest, AckTruncationLargePacket) {
scoped_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames));
ASSERT_TRUE(raw_ack_packet != nullptr);
char buffer[kMaxPacketSize];
- size_t encrypted_length =
- framer_.EncryptPayload(ENCRYPTION_NONE, header.packet_number,
- *raw_ack_packet, buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, kDefaultPathId, header.packet_number, *raw_ack_packet,
+ buffer, kMaxPacketSize);
ASSERT_NE(0u, encrypted_length);
// Now make sure we can turn our ack packet back into an ack frame.
ASSERT_TRUE(framer_.ProcessPacket(
@@ -4442,9 +4882,9 @@ TEST_P(QuicFramerTest, AckTruncationSmallPacket) {
scoped_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames, 500));
ASSERT_TRUE(raw_ack_packet != nullptr);
char buffer[kMaxPacketSize];
- size_t encrypted_length =
- framer_.EncryptPayload(ENCRYPTION_NONE, header.packet_number,
- *raw_ack_packet, buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, kDefaultPathId, header.packet_number, *raw_ack_packet,
+ buffer, kMaxPacketSize);
ASSERT_NE(0u, encrypted_length);
// Now make sure we can turn our ack packet back into an ack frame.
ASSERT_TRUE(framer_.ProcessPacket(
@@ -4483,9 +4923,9 @@ TEST_P(QuicFramerTest, CleanTruncation) {
ASSERT_TRUE(raw_ack_packet != nullptr);
char buffer[kMaxPacketSize];
- size_t encrypted_length =
- framer_.EncryptPayload(ENCRYPTION_NONE, header.packet_number,
- *raw_ack_packet, buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, kDefaultPathId, header.packet_number, *raw_ack_packet,
+ buffer, kMaxPacketSize);
ASSERT_NE(0u, encrypted_length);
// Now make sure we can turn our ack packet back into an ack frame.
@@ -4543,45 +4983,6 @@ TEST_P(QuicFramerTest, EntropyFlagTest) {
EXPECT_FALSE(visitor_.header_->fec_flag);
};
-TEST_P(QuicFramerTest, FecEntropyTest) {
- // 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
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags (Entropy & fec group & FEC)
- 0x07,
- // first fec protected packet offset
- 0xFF,
-
- // 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_->fec_flag);
- EXPECT_TRUE(visitor_.header_->entropy_flag);
- EXPECT_EQ(1 << 4, visitor_.header_->entropy_hash);
-};
-
TEST_P(QuicFramerTest, StopPacketProcessing) {
// clang-format off
unsigned char packet[] = {
@@ -4665,7 +5066,7 @@ TEST_P(QuicFramerTest, ConstructEncryptedPacket) {
framer_.SetEncrypter(ENCRYPTION_NONE, QuicEncrypter::Create(kNULL));
scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
- 42, false, false, kTestQuicStreamId, kTestString,
+ 42, false, false, false, kDefaultPathId, kTestQuicStreamId, kTestString,
PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER));
MockFramerVisitor visitor;
@@ -4698,7 +5099,7 @@ TEST_P(QuicFramerTest, ConstructMisFramedEncryptedPacket) {
framer_.SetEncrypter(ENCRYPTION_NONE, QuicEncrypter::Create(kNULL));
scoped_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket(
- 42, false, false, kTestQuicStreamId, kTestString,
+ 42, false, false, false, kDefaultPathId, kTestQuicStreamId, kTestString,
PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, nullptr));
MockFramerVisitor visitor;
diff --git a/chromium/net/quic/quic_headers_stream.cc b/chromium/net/quic/quic_headers_stream.cc
index abcaa719448..9f439272ba7 100644
--- a/chromium/net/quic/quic_headers_stream.cc
+++ b/chromium/net/quic/quic_headers_stream.cc
@@ -65,6 +65,11 @@ class QuicHeadersStream::SpdyFramerVisitor
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.");
}
@@ -218,11 +223,10 @@ size_t QuicHeadersStream::WriteHeaders(QuicStreamId stream_id,
headers_frame.set_has_priority(true);
headers_frame.set_priority(priority);
}
- scoped_ptr<SpdySerializedFrame> frame(
- spdy_framer_.SerializeFrame(headers_frame));
- WriteOrBufferData(StringPiece(frame->data(), frame->size()), false,
+ SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
+ WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
ack_listener);
- return frame->size();
+ return frame.size();
}
size_t QuicHeadersStream::WritePushPromise(
@@ -241,11 +245,10 @@ size_t QuicHeadersStream::WritePushPromise(
// response headers.
push_promise.set_fin(false);
- scoped_ptr<SpdySerializedFrame> frame(
- spdy_framer_.SerializeFrame(push_promise));
- WriteOrBufferData(StringPiece(frame->data(), frame->size()), false,
+ SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
+ WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
ack_listener);
- return frame->size();
+ return frame.size();
}
void QuicHeadersStream::OnDataAvailable() {
@@ -277,10 +280,6 @@ void QuicHeadersStream::OnDataAvailable() {
}
}
-SpdyPriority QuicHeadersStream::Priority() const {
- return net::kV3HighestPriority;
-}
-
void QuicHeadersStream::OnHeaders(SpdyStreamId stream_id,
bool has_priority,
SpdyPriority priority,
@@ -308,11 +307,6 @@ void QuicHeadersStream::OnHeaders(SpdyStreamId stream_id,
void QuicHeadersStream::OnPushPromise(SpdyStreamId stream_id,
SpdyStreamId promised_stream_id,
bool end) {
- if (!supports_push_promise_) {
- CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
- "SPDY PUSH_PROMISE not supported.");
- return;
- }
DCHECK_EQ(kInvalidStreamId, stream_id_);
DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
stream_id_ = stream_id;
diff --git a/chromium/net/quic/quic_headers_stream.h b/chromium/net/quic/quic_headers_stream.h
index a8b466cd553..282a9ea5bac 100644
--- a/chromium/net/quic/quic_headers_stream.h
+++ b/chromium/net/quic/quic_headers_stream.h
@@ -46,7 +46,6 @@ class NET_EXPORT_PRIVATE QuicHeadersStream : public ReliableQuicStream {
// ReliableQuicStream implementation
void OnDataAvailable() override;
- SpdyPriority Priority() const override;
bool supports_push_promise() { return supports_push_promise_; }
diff --git a/chromium/net/quic/quic_headers_stream_test.cc b/chromium/net/quic/quic_headers_stream_test.cc
index 2425683a5b4..e02f5307708 100644
--- a/chromium/net/quic/quic_headers_stream_test.cc
+++ b/chromium/net/quic/quic_headers_stream_test.cc
@@ -42,6 +42,7 @@ class MockVisitor : public SpdyFramerVisitorInterface {
MOCK_METHOD4(
OnStreamFrameData,
void(SpdyStreamId stream_id, const char* data, size_t len, bool fin));
+ MOCK_METHOD1(OnStreamEnd, void(SpdyStreamId stream_id));
MOCK_METHOD2(OnStreamPadding, void(SpdyStreamId stream_id, size_t len));
MOCK_METHOD1(OnHeaderFrameStart,
SpdyHeadersHandlerInterface*(SpdyStreamId stream_id));
@@ -92,19 +93,26 @@ class MockVisitor : public SpdyFramerVisitorInterface {
MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type));
};
-// Run all tests with each version, and client or server
+// Run all tests with each version, perspective (client or server),
+// and relevant flag options (false or true)
struct TestParams {
- TestParams(QuicVersion version, Perspective perspective)
- : version(version), perspective(perspective) {}
+ TestParams(QuicVersion version,
+ Perspective perspective,
+ bool spdy_on_stream_end)
+ : version(version),
+ perspective(perspective),
+ spdy_on_stream_end(spdy_on_stream_end) {}
friend ostream& operator<<(ostream& os, const TestParams& p) {
os << "{ version: " << QuicVersionToString(p.version);
- os << ", perspective: " << p.perspective << " }";
+ os << ", perspective: " << p.perspective;
+ os << ", spdy_on_stream_end: " << p.spdy_on_stream_end << " }";
return os;
}
QuicVersion version;
Perspective perspective;
+ bool spdy_on_stream_end;
};
// Constructs various test permutations.
@@ -112,8 +120,10 @@ vector<TestParams> GetTestParams() {
vector<TestParams> params;
QuicVersionVector all_supported_versions = QuicSupportedVersions();
for (const QuicVersion version : all_supported_versions) {
- params.push_back(TestParams(version, Perspective::IS_CLIENT));
- params.push_back(TestParams(version, Perspective::IS_SERVER));
+ params.push_back(TestParams(version, Perspective::IS_CLIENT, true));
+ params.push_back(TestParams(version, Perspective::IS_SERVER, true));
+ params.push_back(TestParams(version, Perspective::IS_CLIENT, false));
+ params.push_back(TestParams(version, Perspective::IS_SERVER, false));
}
FLAGS_quic_supports_push_promise = true;
return params;
@@ -128,14 +138,15 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> {
session_(connection_),
headers_stream_(QuicSpdySessionPeer::GetHeadersStream(&session_)),
body_("hello world"),
- framer_(HTTP2),
stream_frame_(kHeadersStreamId, /*fin=*/false, /*offset=*/0, ""),
next_promised_stream_id_(2) {
FLAGS_quic_always_log_bugs_for_tests = true;
headers_[":version"] = "HTTP/1.1";
headers_[":status"] = "200 Ok";
headers_["content-length"] = "11";
- framer_.set_visitor(&visitor_);
+ FLAGS_spdy_on_stream_end = GetParam().spdy_on_stream_end;
+ framer_ = std::unique_ptr<SpdyFramer>(new SpdyFramer(HTTP2));
+ framer_->set_visitor(&visitor_);
EXPECT_EQ(version(), session_.connection()->version());
EXPECT_TRUE(headers_stream_ != nullptr);
VLOG(1) << GetParam();
@@ -175,7 +186,7 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> {
SpdyPriority priority,
SpdyFrameType type) {
// Write the headers and capture the outgoing data
- EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, _, nullptr))
+ EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, nullptr))
.WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
headers_stream_->WriteHeaders(stream_id, headers_, fin, priority, nullptr);
@@ -196,11 +207,15 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> {
.WillRepeatedly(WithArgs<1, 2>(
Invoke(this, &QuicHeadersStreamTest::SaveHeaderData)));
if (fin) {
- EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, nullptr, 0, true));
+ if (FLAGS_spdy_on_stream_end) {
+ EXPECT_CALL(visitor_, OnStreamEnd(stream_id));
+ } else {
+ EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, nullptr, 0, true));
+ }
}
- framer_.ProcessInput(saved_data_.data(), saved_data_.length());
- EXPECT_FALSE(framer_.HasError())
- << SpdyFramer::ErrorCodeToString(framer_.error_code());
+ framer_->ProcessInput(saved_data_.data(), saved_data_.length());
+ EXPECT_FALSE(framer_->HasError())
+ << SpdyFramer::ErrorCodeToString(framer_->error_code());
CheckHeaders();
saved_data_.clear();
@@ -208,7 +223,7 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> {
void CheckHeaders() {
SpdyHeaderBlock headers;
- EXPECT_TRUE(framer_.ParseHeaderBlockInBuffer(
+ EXPECT_TRUE(framer_->ParseHeaderBlockInBuffer(
saved_header_data_.data(), saved_header_data_.length(), &headers));
EXPECT_EQ(headers_, headers);
saved_header_data_.clear();
@@ -224,7 +239,9 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> {
return versions;
}
- void CloseConnection() { QuicConnectionPeer::CloseConnection(connection_); }
+ void TearDownLocalConnectionState() {
+ QuicConnectionPeer::TearDownLocalConnectionState(connection_);
+ }
QuicStreamId NextPromisedStreamId() { return next_promised_stream_id_ += 2; }
@@ -239,7 +256,7 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> {
string body_;
string saved_data_;
string saved_header_data_;
- SpdyFramer framer_;
+ std::unique_ptr<SpdyFramer> framer_;
StrictMock<MockVisitor> visitor_;
QuicStreamFrame stream_frame_;
QuicStreamId next_promised_stream_id_;
@@ -253,10 +270,6 @@ TEST_P(QuicHeadersStreamTest, StreamId) {
EXPECT_EQ(3u, headers_stream_->id());
}
-TEST_P(QuicHeadersStreamTest, Priority) {
- EXPECT_EQ(0u, headers_stream_->Priority());
-}
-
TEST_P(QuicHeadersStreamTest, WriteHeaders) {
for (QuicStreamId stream_id = kClientDataStreamId1;
stream_id < kClientDataStreamId3; stream_id += 2) {
@@ -279,8 +292,7 @@ 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(kHeadersStreamId, _, _, false, _, nullptr))
+ EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, nullptr))
.WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
headers_stream_->WritePushPromise(stream_id, promised_stream_id, headers_,
nullptr);
@@ -291,9 +303,9 @@ TEST_P(QuicHeadersStreamTest, WritePushPromises) {
EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _))
.WillRepeatedly(WithArgs<1, 2>(
Invoke(this, &QuicHeadersStreamTest::SaveHeaderData)));
- framer_.ProcessInput(saved_data_.data(), saved_data_.length());
- EXPECT_FALSE(framer_.HasError())
- << SpdyFramer::ErrorCodeToString(framer_.error_code());
+ framer_->ProcessInput(saved_data_.data(), saved_data_.length());
+ EXPECT_FALSE(framer_->HasError())
+ << SpdyFramer::ErrorCodeToString(framer_->error_code());
CheckHeaders();
saved_data_.clear();
} else {
@@ -310,29 +322,29 @@ TEST_P(QuicHeadersStreamTest, ProcessRawData) {
for (bool fin : {false, true}) {
for (SpdyPriority priority = 0; priority < 7; ++priority) {
// Replace with "WriteHeadersAndSaveData"
- scoped_ptr<SpdySerializedFrame> frame;
+ SpdySerializedFrame frame;
if (perspective() == Perspective::IS_SERVER) {
SpdyHeadersIR headers_frame(stream_id);
headers_frame.set_header_block(headers_);
headers_frame.set_fin(fin);
headers_frame.set_has_priority(true);
- frame.reset(framer_.SerializeFrame(headers_frame));
+ frame = framer_->SerializeFrame(headers_frame);
EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
} else {
SpdyHeadersIR headers_frame(stream_id);
headers_frame.set_header_block(headers_);
headers_frame.set_fin(fin);
- frame.reset(framer_.SerializeFrame(headers_frame));
+ frame = framer_->SerializeFrame(headers_frame);
}
EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
.WillRepeatedly(WithArgs<1>(Invoke(
this, &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
EXPECT_CALL(session_,
- OnStreamHeadersComplete(stream_id, fin, frame->size()));
- stream_frame_.frame_buffer = frame->data();
- stream_frame_.frame_length = frame->size();
+ OnStreamHeadersComplete(stream_id, fin, frame.size()));
+ stream_frame_.frame_buffer = frame.data();
+ stream_frame_.frame_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
- stream_frame_.offset += frame->size();
+ stream_frame_.offset += frame.size();
CheckHeaders();
}
}
@@ -345,76 +357,32 @@ TEST_P(QuicHeadersStreamTest, ProcessPushPromise) {
for (QuicStreamId stream_id = kClientDataStreamId1;
stream_id < kClientDataStreamId3; stream_id += 2) {
QuicStreamId promised_stream_id = NextPromisedStreamId();
- scoped_ptr<SpdySerializedFrame> frame;
SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
push_promise.set_header_block(headers_);
- frame.reset(framer_.SerializeFrame(push_promise));
+ SpdySerializedFrame frame(framer_->SerializeFrame(push_promise));
if (perspective() == Perspective::IS_SERVER) {
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_INVALID_HEADERS_STREAM_DATA,
- "PUSH_PROMISE not supported."))
- .WillRepeatedly(
- InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection));
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "PUSH_PROMISE not supported.", _))
+ .WillRepeatedly(InvokeWithoutArgs(
+ this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
} else {
EXPECT_CALL(session_, OnPromiseHeaders(stream_id, _))
.WillRepeatedly(WithArgs<1>(
Invoke(this, &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
EXPECT_CALL(session_, OnPromiseHeadersComplete(
- stream_id, promised_stream_id, frame->size()));
+ stream_id, promised_stream_id, frame.size()));
}
- stream_frame_.frame_buffer = frame->data();
- stream_frame_.frame_length = frame->size();
+ stream_frame_.frame_buffer = frame.data();
+ stream_frame_.frame_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
if (perspective() == Perspective::IS_CLIENT) {
- stream_frame_.offset += frame->size();
+ stream_frame_.offset += frame.size();
CheckHeaders();
}
}
}
-TEST_P(QuicHeadersStreamTest, PushPromiseOutOfOrder) {
- if (perspective() == Perspective::IS_SERVER)
- return;
-
- QuicStreamId promised_stream_id = NextPromisedStreamId();
- QuicStreamId stream_id = kClientDataStreamId1;
-
- scoped_ptr<SpdySerializedFrame> frame;
- SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
- push_promise.set_header_block(headers_);
- frame.reset(framer_.SerializeFrame(push_promise));
- EXPECT_CALL(session_, OnPromiseHeaders(stream_id, _))
- .WillRepeatedly(WithArgs<1>(
- Invoke(this, &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
- EXPECT_CALL(session_, OnPromiseHeadersComplete(stream_id, promised_stream_id,
- frame->size()));
- stream_frame_.frame_buffer = frame->data();
- stream_frame_.frame_length = frame->size();
- headers_stream_->OnStreamFrame(stream_frame_);
- if (perspective() == Perspective::IS_CLIENT) {
- stream_frame_.offset += frame->size();
- CheckHeaders();
- }
-
- stream_id += 2;
- push_promise.set_stream_id(stream_id);
- frame.reset(framer_.SerializeFrame(push_promise));
- EXPECT_CALL(session_, OnPromiseHeaders(stream_id, _))
- .WillRepeatedly(WithArgs<1>(
- Invoke(this, &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
- EXPECT_CALL(session_, OnPromiseHeadersComplete(stream_id, promised_stream_id,
- frame->size()));
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_INVALID_STREAM_ID,
- "Received push stream id lesser or equal to the"
- " last accepted before"))
- .WillRepeatedly(
- InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection));
- stream_frame_.frame_buffer = frame->data();
- stream_frame_.frame_length = frame->size();
- headers_stream_->OnStreamFrame(stream_frame_);
-}
-
TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) {
EXPECT_CALL(session_, OnHeadersHeadOfLineBlocking(_)).Times(0);
testing::InSequence seq;
@@ -422,28 +390,28 @@ TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) {
for (int stream_num = 0; stream_num < 10; stream_num++) {
QuicStreamId stream_id = QuicClientDataStreamId(stream_num);
// Replace with "WriteHeadersAndSaveData"
- scoped_ptr<SpdySerializedFrame> frame;
+ SpdySerializedFrame frame;
if (perspective() == Perspective::IS_SERVER) {
SpdyHeadersIR headers_frame(stream_id);
headers_frame.set_header_block(headers_);
headers_frame.set_fin(fin);
headers_frame.set_has_priority(true);
- frame.reset(framer_.SerializeFrame(headers_frame));
+ frame = framer_->SerializeFrame(headers_frame);
EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
} else {
SpdyHeadersIR headers_frame(stream_id);
headers_frame.set_header_block(headers_);
headers_frame.set_fin(fin);
- frame.reset(framer_.SerializeFrame(headers_frame));
+ frame = framer_->SerializeFrame(headers_frame);
}
EXPECT_CALL(session_, OnStreamHeaders(stream_id, _));
EXPECT_CALL(session_,
- OnStreamHeadersComplete(stream_id, fin, frame->size()));
- stream_frame_.frame_buffer = frame->data();
- stream_frame_.frame_length = frame->size();
+ OnStreamHeadersComplete(stream_id, fin, frame.size()));
+ stream_frame_.frame_buffer = frame.data();
+ stream_frame_.frame_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
- stream_frame_.offset += frame->size();
+ stream_frame_.offset += frame.size();
}
}
@@ -451,7 +419,7 @@ TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) {
QuicStreamId stream_id;
bool fin = true;
QuicStreamFrame stream_frames[10];
- scoped_ptr<SpdySerializedFrame> frames[10];
+ SpdySerializedFrame frames[10];
// First create all the frames in order
{
InSequence seq;
@@ -462,21 +430,21 @@ TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) {
headers_frame.set_header_block(headers_);
headers_frame.set_fin(fin);
headers_frame.set_has_priority(true);
- frames[stream_num].reset(framer_.SerializeFrame(headers_frame));
+ frames[stream_num] = framer_->SerializeFrame(headers_frame);
EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)).Times(1);
} else {
SpdyHeadersIR headers_frame(stream_id);
headers_frame.set_header_block(headers_);
headers_frame.set_fin(fin);
- frames[stream_num].reset(framer_.SerializeFrame(headers_frame));
+ frames[stream_num] = framer_->SerializeFrame(headers_frame);
}
stream_frames[stream_num].stream_id = stream_frame_.stream_id;
stream_frames[stream_num].offset = stream_frame_.offset;
- stream_frames[stream_num].frame_buffer = frames[stream_num]->data();
- stream_frames[stream_num].frame_length = frames[stream_num]->size();
+ stream_frames[stream_num].frame_buffer = frames[stream_num].data();
+ stream_frames[stream_num].frame_length = frames[stream_num].size();
DVLOG(1) << "make frame for stream " << stream_num << " offset "
<< stream_frames[stream_num].offset;
- stream_frame_.offset += frames[stream_num]->size();
+ stream_frame_.offset += frames[stream_num].size();
EXPECT_CALL(session_, OnStreamHeaders(stream_id, _)).Times(1);
EXPECT_CALL(session_, OnStreamHeadersComplete(stream_id, fin, _))
.Times(1);
@@ -506,29 +474,29 @@ TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
for (bool fin : {false, true}) {
for (SpdyPriority priority = 0; priority < 7; ++priority) {
// Replace with "WriteHeadersAndSaveData"
- scoped_ptr<SpdySerializedFrame> frame;
+ SpdySerializedFrame frame;
if (perspective() == Perspective::IS_SERVER) {
SpdyHeadersIR headers_frame(stream_id);
headers_frame.set_header_block(headers_);
headers_frame.set_fin(fin);
headers_frame.set_has_priority(true);
- frame.reset(framer_.SerializeFrame(headers_frame));
+ frame = framer_->SerializeFrame(headers_frame);
EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
} else {
SpdyHeadersIR headers_frame(stream_id);
headers_frame.set_header_block(headers_);
headers_frame.set_fin(fin);
- frame.reset(framer_.SerializeFrame(headers_frame));
+ frame = framer_->SerializeFrame(headers_frame);
}
EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
.WillRepeatedly(WithArgs<1>(Invoke(
this, &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
EXPECT_CALL(session_,
- OnStreamHeadersComplete(stream_id, fin, frame->size()));
- stream_frame_.frame_buffer = frame->data();
- stream_frame_.frame_length = frame->size();
+ OnStreamHeadersComplete(stream_id, fin, frame.size()));
+ stream_frame_.frame_buffer = frame.data();
+ stream_frame_.frame_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
- stream_frame_.offset += frame->size();
+ stream_frame_.offset += frame.size();
CheckHeaders();
}
}
@@ -537,8 +505,8 @@ TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
TEST_P(QuicHeadersStreamTest, ProcessBadData) {
const char kBadData[] = "blah blah blah";
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_INVALID_HEADERS_STREAM_DATA, _))
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
.Times(::testing::AnyNumber());
stream_frame_.frame_buffer = kBadData;
stream_frame_.frame_length = strlen(kBadData);
@@ -547,80 +515,76 @@ TEST_P(QuicHeadersStreamTest, ProcessBadData) {
TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
SpdyDataIR data(2, "");
- scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
- EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
- "SPDY DATA frame received."))
- .WillOnce(
- InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection));
- stream_frame_.frame_buffer = frame->data();
- stream_frame_.frame_length = frame->size();
+ SpdySerializedFrame frame(framer_->SerializeFrame(data));
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "SPDY DATA frame received.", _))
+ .WillOnce(InvokeWithoutArgs(
+ this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
+ stream_frame_.frame_buffer = frame.data();
+ stream_frame_.frame_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
}
TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR);
- scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
+ SpdySerializedFrame frame(framer_->SerializeFrame(data));
EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
- "SPDY RST_STREAM frame received."))
- .WillOnce(
- InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection));
- stream_frame_.frame_buffer = frame->data();
- stream_frame_.frame_length = frame->size();
+ CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "SPDY RST_STREAM frame received.", _))
+ .WillOnce(InvokeWithoutArgs(
+ this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
+ stream_frame_.frame_buffer = frame.data();
+ stream_frame_.frame_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
}
TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
SpdySettingsIR data;
data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, 0);
- scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
- EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
- "SPDY SETTINGS frame received."))
- .WillOnce(
- InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection));
- stream_frame_.frame_buffer = frame->data();
- stream_frame_.frame_length = frame->size();
+ SpdySerializedFrame frame(framer_->SerializeFrame(data));
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "SPDY SETTINGS frame received.", _))
+ .WillOnce(InvokeWithoutArgs(
+ this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
+ stream_frame_.frame_buffer = frame.data();
+ stream_frame_.frame_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
}
TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
SpdyPingIR data(1);
- scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
- EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
- "SPDY PING frame received."))
- .WillOnce(
- InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection));
- stream_frame_.frame_buffer = frame->data();
- stream_frame_.frame_length = frame->size();
+ SpdySerializedFrame frame(framer_->SerializeFrame(data));
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "SPDY PING frame received.", _))
+ .WillOnce(InvokeWithoutArgs(
+ this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
+ stream_frame_.frame_buffer = frame.data();
+ stream_frame_.frame_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
}
TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away");
- scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
- EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
- "SPDY GOAWAY frame received."))
- .WillOnce(
- InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection));
- stream_frame_.frame_buffer = frame->data();
- stream_frame_.frame_length = frame->size();
+ SpdySerializedFrame frame(framer_->SerializeFrame(data));
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "SPDY GOAWAY frame received.", _))
+ .WillOnce(InvokeWithoutArgs(
+ this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
+ stream_frame_.frame_buffer = frame.data();
+ stream_frame_.frame_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
}
TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
SpdyWindowUpdateIR data(1, 1);
- scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_INVALID_HEADERS_STREAM_DATA,
- "SPDY WINDOW_UPDATE frame received."))
- .WillOnce(
- InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection));
- stream_frame_.frame_buffer = frame->data();
- stream_frame_.frame_length = frame->size();
+ SpdySerializedFrame frame(framer_->SerializeFrame(data));
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "SPDY WINDOW_UPDATE frame received.", _))
+ .WillOnce(InvokeWithoutArgs(
+ this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
+ stream_frame_.frame_buffer = frame.data();
+ stream_frame_.frame_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
}
diff --git a/chromium/net/quic/quic_http_stream.cc b/chromium/net/quic/quic_http_stream.cc
index ce3bb7c5b32..591f3cefb15 100644
--- a/chromium/net/quic/quic_http_stream.cc
+++ b/chromium/net/quic/quic_http_stream.cc
@@ -6,13 +6,16 @@
#include "base/callback_helpers.h"
#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "net/base/io_buffer.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/quic/quic_chromium_client_session.h"
#include "net/quic/quic_chromium_client_stream.h"
+#include "net/quic/quic_client_promised_info.h"
#include "net/quic/quic_http_utils.h"
#include "net/quic/quic_utils.h"
#include "net/quic/spdy_utils.h"
@@ -24,6 +27,20 @@
namespace net {
+namespace {
+
+scoped_ptr<base::Value> NetLogQuicPushStreamCallback(
+ QuicStreamId stream_id,
+ const GURL* url,
+ NetLogCaptureMode capture_mode) {
+ scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ dict->SetInteger("stream_id", stream_id);
+ dict->SetString("url", url->spec());
+ return std::move(dict);
+}
+
+} // namespace
+
QuicHttpStream::QuicHttpStream(
const base::WeakPtr<QuicChromiumClientSession>& session)
: next_state_(STATE_NONE),
@@ -43,6 +60,9 @@ QuicHttpStream::QuicHttpStream(
closed_stream_sent_bytes_(0),
user_buffer_len_(0),
quic_connection_error_(QUIC_NO_ERROR),
+ port_migration_detected_(false),
+ found_promise_(false),
+ push_handle_(nullptr),
weak_factory_(this) {
DCHECK(session_);
session_->AddObserver(this);
@@ -54,6 +74,63 @@ QuicHttpStream::~QuicHttpStream() {
session_->RemoveObserver(this);
}
+bool QuicHttpStream::CheckVary(const SpdyHeaderBlock& client_request,
+ const SpdyHeaderBlock& promise_request,
+ const SpdyHeaderBlock& promise_response) {
+ HttpResponseInfo promise_response_info;
+
+ HttpRequestInfo promise_request_info;
+ ConvertHeaderBlockToHttpRequestHeaders(promise_request,
+ &promise_request_info.extra_headers);
+ HttpRequestInfo client_request_info;
+ ConvertHeaderBlockToHttpRequestHeaders(client_request,
+ &client_request_info.extra_headers);
+
+ if (!SpdyHeadersToHttpResponse(promise_response, HTTP2,
+ &promise_response_info)) {
+ DLOG(WARNING) << "Invalid headers";
+ return false;
+ }
+
+ HttpVaryData vary_data;
+ if (!vary_data.Init(promise_request_info,
+ *promise_response_info.headers.get())) {
+ // Promise didn't contain valid vary info, so URL match was sufficient.
+ return true;
+ }
+ // Now compare the client request for matching.
+ return vary_data.MatchesRequest(client_request_info,
+ *promise_response_info.headers.get());
+}
+
+void QuicHttpStream::OnRendezvousResult(QuicSpdyStream* stream) {
+ push_handle_ = nullptr;
+ if (stream) {
+ stream_ = static_cast<QuicChromiumClientStream*>(stream);
+ stream_->SetDelegate(this);
+ }
+ // callback_ should be non-null in the case of asynchronous
+ // rendezvous; i.e. |Try()| returned QUIC_PENDING.
+ if (!callback_.is_null()) {
+ if (stream) {
+ next_state_ = STATE_OPEN;
+ stream_net_log_.AddEvent(
+ NetLog::TYPE_QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM,
+ base::Bind(&NetLogQuicPushStreamCallback, stream_->id(),
+ &request_info_->url));
+ session_->net_log().AddEvent(
+ NetLog::TYPE_QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM,
+ base::Bind(&NetLogQuicPushStreamCallback, stream_->id(),
+ &request_info_->url));
+ DoCallback(OK);
+ return;
+ }
+ // rendezvous has failed so proceed as with a non-push request.
+ next_state_ = STATE_REQUEST_STREAM;
+ OnIOComplete(OK);
+ }
+}
+
int QuicHttpStream::InitializeStream(const HttpRequestInfo* request_info,
RequestPriority priority,
const BoundNetLog& stream_net_log,
@@ -72,29 +149,132 @@ 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());
+
+ std::string url(request_info->url.spec());
+ QuicClientPromisedInfo* promised =
+ session_->push_promise_index()->GetPromised(url);
+ if (promised) {
+ found_promise_ = true;
+ stream_net_log_.AddEvent(
+ NetLog::TYPE_QUIC_HTTP_STREAM_PUSH_PROMISE_RENDEZVOUS,
+ base::Bind(&NetLogQuicPushStreamCallback, promised->id(),
+ &request_info_->url));
+ session_->net_log().AddEvent(
+ NetLog::TYPE_QUIC_HTTP_STREAM_PUSH_PROMISE_RENDEZVOUS,
+ base::Bind(&NetLogQuicPushStreamCallback, promised->id(),
+ &request_info_->url));
+ return OK;
+ }
+
+ next_state_ = STATE_REQUEST_STREAM;
+ int rv = DoLoop(OK);
+ if (rv == ERR_IO_PENDING)
+ callback_ = callback;
+
+ return rv;
+}
+
+int QuicHttpStream::DoStreamRequest() {
int rv = stream_request_.StartRequest(
session_, &stream_,
base::Bind(&QuicHttpStream::OnStreamReady, weak_factory_.GetWeakPtr()));
- if (rv == ERR_IO_PENDING) {
- callback_ = callback;
- } else if (rv == OK) {
+ if (rv == OK) {
stream_->SetDelegate(this);
- } else if (!was_handshake_confirmed_) {
+ if (request_info_->load_flags & LOAD_DISABLE_CONNECTION_MIGRATION) {
+ stream_->DisableConnectionMigration();
+ }
+ if (response_info_) {
+ next_state_ = STATE_SET_REQUEST_PRIORITY;
+ }
+ } else if (rv != ERR_IO_PENDING && !was_handshake_confirmed_) {
rv = ERR_QUIC_HANDSHAKE_FAILED;
}
-
return rv;
}
+int QuicHttpStream::DoSetRequestPriority() {
+ // Set priority according to request and, and advance to
+ // STATE_SEND_HEADERS.
+ DCHECK(stream_);
+ DCHECK(response_info_);
+ SpdyPriority priority = ConvertRequestPriorityToQuicPriority(priority_);
+ stream_->SetPriority(priority);
+ next_state_ = STATE_SEND_HEADERS;
+ return OK;
+}
+
void QuicHttpStream::OnStreamReady(int rv) {
DCHECK(rv == OK || !stream_);
if (rv == OK) {
stream_->SetDelegate(this);
+ if (request_info_->load_flags & LOAD_DISABLE_CONNECTION_MIGRATION) {
+ stream_->DisableConnectionMigration();
+ }
+ if (response_info_) {
+ // This happens in the case of a asynchronous push rendezvous
+ // that ultimately fails (e.g. vary failure). |response_info_|
+ // non-null implies that |DoStreamRequest()| was called via
+ // |SendRequest()|.
+ next_state_ = STATE_SET_REQUEST_PRIORITY;
+ rv = DoLoop(OK);
+ }
} else if (!was_handshake_confirmed_) {
rv = ERR_QUIC_HANDSHAKE_FAILED;
}
+ if (rv != ERR_IO_PENDING) {
+ DoCallback(rv);
+ }
+}
- ResetAndReturn(&callback_).Run(rv);
+bool QuicHttpStream::CancelPromiseIfHasBody() {
+ if (!request_body_stream_)
+ return false;
+ // Method type or request with body ineligble for push.
+ this->push_handle_->Cancel();
+ this->push_handle_ = nullptr;
+ next_state_ = STATE_REQUEST_STREAM;
+ return true;
+}
+
+int QuicHttpStream::HandlePromise() {
+ QuicAsyncStatus push_status = session_->push_promise_index()->Try(
+ request_headers_, this, &this->push_handle_);
+
+ switch (push_status) {
+ case QUIC_FAILURE:
+ // Push rendezvous failed.
+ next_state_ = STATE_REQUEST_STREAM;
+ break;
+ case QUIC_SUCCESS:
+ next_state_ = STATE_OPEN;
+ if (!CancelPromiseIfHasBody()) {
+ stream_net_log_.AddEvent(
+ NetLog::TYPE_QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM,
+ base::Bind(&NetLogQuicPushStreamCallback, stream_->id(),
+ &request_info_->url));
+ session_->net_log().AddEvent(
+ NetLog::TYPE_QUIC_HTTP_STREAM_ADOPTED_PUSH_STREAM,
+ base::Bind(&NetLogQuicPushStreamCallback, stream_->id(),
+ &request_info_->url));
+ // Avoid the call to |DoLoop()| below, which would reset
+ // next_state_ to STATE_NONE.
+ return OK;
+ }
+
+ break;
+ case QUIC_PENDING:
+ if (!CancelPromiseIfHasBody()) {
+ // Have a promise but the promised stream doesn't exist yet.
+ // Still have to do validation before accepting the promised
+ // stream for sure.
+ return ERR_IO_PENDING;
+ }
+ break;
+ }
+ return DoLoop(OK);
}
int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
@@ -110,19 +290,14 @@ 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;
- bool secure_session =
- session_->GetSSLInfo(&ssl_info) && ssl_info.cert.get();
- DCHECK(secure_session);
UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.CookieSentToAccountsOverChannelId",
- ssl_info.channel_id_sent);
+ ssl_info_.channel_id_sent);
}
- if (!stream_) {
- return ERR_CONNECTION_CLOSED;
+ if ((!found_promise_ && !stream_) || !session_) {
+ return was_handshake_confirmed_ ? ERR_CONNECTION_CLOSED
+ : ERR_QUIC_HANDSHAKE_FAILED;
}
- SpdyPriority priority = ConvertRequestPriorityToQuicPriority(priority_);
- stream_->SetPriority(priority);
// Store the serialized request headers.
CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, HTTP2,
/*direct=*/true, &request_headers_);
@@ -146,8 +321,15 @@ int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
// Store the response info.
response_info_ = response;
- next_state_ = STATE_SEND_HEADERS;
- int rv = DoLoop(OK);
+ int rv;
+
+ if (found_promise_) {
+ rv = HandlePromise();
+ } else {
+ next_state_ = STATE_SET_REQUEST_PRIORITY;
+ rv = DoLoop(OK);
+ }
+
if (rv == ERR_IO_PENDING)
callback_ = callback;
@@ -263,8 +445,7 @@ bool QuicHttpStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
}
void QuicHttpStream::GetSSLInfo(SSLInfo* ssl_info) {
- DCHECK(stream_);
- session_->GetSSLInfo(ssl_info);
+ *ssl_info = ssl_info_;
}
void QuicHttpStream::GetSSLCertRequestInfo(
@@ -281,6 +462,11 @@ bool QuicHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
return true;
}
+Error QuicHttpStream::GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ return session_->GetTokenBindingSignature(key, out);
+}
+
void QuicHttpStream::Drain(HttpNetworkSession* session) {
NOTREACHED();
Close(false);
@@ -288,8 +474,14 @@ void QuicHttpStream::Drain(HttpNetworkSession* session) {
}
void QuicHttpStream::PopulateNetErrorDetails(NetErrorDetails* details) {
+ details->connection_info = HttpResponseInfo::CONNECTION_INFO_QUIC1_SPDY3;
if (was_handshake_confirmed_)
details->quic_connection_error = quic_connection_error_;
+ if (session_) {
+ session_->PopulateNetErrorDetails(details);
+ } else {
+ details->quic_port_migration_detected = port_migration_detected_;
+ }
}
void QuicHttpStream::SetPriority(RequestPriority priority) {
@@ -300,6 +492,16 @@ void QuicHttpStream::OnHeadersAvailable(const SpdyHeaderBlock& headers,
size_t frame_len) {
headers_bytes_received_ += frame_len;
+ // QuicHttpStream ignores trailers.
+ if (response_headers_received_) {
+ if (stream_->IsDoneReading()) {
+ // Close the read side. If the write side has been closed, this will
+ // invoke QuicHttpStream::OnClose to reset the stream.
+ stream_->OnFinRead();
+ }
+ return;
+ }
+
int rv = ProcessResponseHeaders(headers);
if (rv != ERR_IO_PENDING && !callback_.is_null()) {
DoCallback(rv);
@@ -357,9 +559,10 @@ void QuicHttpStream::OnCryptoHandshakeConfirmed() {
was_handshake_confirmed_ = true;
}
-void QuicHttpStream::OnSessionClosed(int error) {
+void QuicHttpStream::OnSessionClosed(int error, bool port_migration_detected) {
Close(false);
session_error_ = error;
+ port_migration_detected_ = port_migration_detected;
session_.reset();
}
@@ -385,6 +588,12 @@ int QuicHttpStream::DoLoop(int rv) {
State state = next_state_;
next_state_ = STATE_NONE;
switch (state) {
+ case STATE_REQUEST_STREAM:
+ rv = DoStreamRequest();
+ break;
+ case STATE_SET_REQUEST_PRIORITY:
+ rv = DoSetRequestPriority();
+ break;
case STATE_SEND_HEADERS:
CHECK_EQ(OK, rv);
rv = DoSendHeaders();
@@ -428,12 +637,6 @@ int QuicHttpStream::DoSendHeaders() {
NetLog::TYPE_HTTP_TRANSACTION_QUIC_SEND_REQUEST_HEADERS,
base::Bind(&QuicRequestNetLogCallback, stream_->id(), &request_headers_,
priority_));
- // Also log to the QuicSession's net log.
- stream_->net_log().AddEvent(
- NetLog::TYPE_QUIC_HTTP_STREAM_SEND_REQUEST_HEADERS,
- base::Bind(&QuicRequestNetLogCallback, stream_->id(), &request_headers_,
- priority_));
-
bool has_upload_data = request_body_stream_ != nullptr;
next_state_ = STATE_SEND_HEADERS_COMPLETE;
@@ -524,12 +727,6 @@ int QuicHttpStream::DoSendBodyComplete(int rv) {
}
int QuicHttpStream::ProcessResponseHeaders(const SpdyHeaderBlock& headers) {
- // The URLRequest logs these headers, so only log to the QuicSession's
- // net log.
- stream_->net_log().AddEvent(
- NetLog::TYPE_QUIC_HTTP_STREAM_READ_RESPONSE_HEADERS,
- base::Bind(&SpdyHeaderBlockNetLogCallback, &headers));
-
if (!SpdyHeadersToHttpResponse(headers, HTTP2, response_info_)) {
DLOG(WARNING) << "Invalid headers";
return ERR_QUIC_PROTOCOL_ERROR;
@@ -568,6 +765,10 @@ int QuicHttpStream::ReadAvailableData(IOBuffer* buf, int buf_len) {
}
void QuicHttpStream::ResetStream() {
+ if (push_handle_) {
+ push_handle_->Cancel();
+ push_handle_ = nullptr;
+ }
if (!stream_)
return;
closed_stream_received_bytes_ = stream_->stream_bytes_read();
diff --git a/chromium/net/quic/quic_http_stream.h b/chromium/net/quic/quic_http_stream.h
index 7abdf8b646e..01c07606c27 100644
--- a/chromium/net/quic/quic_http_stream.h
+++ b/chromium/net/quic/quic_http_stream.h
@@ -9,6 +9,8 @@
#include <stdint.h>
#include <list>
+#include <string>
+#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -16,6 +18,7 @@
#include "net/http/http_stream.h"
#include "net/quic/quic_chromium_client_session.h"
#include "net/quic/quic_chromium_client_stream.h"
+#include "net/quic/quic_client_push_promise_index.h"
namespace net {
@@ -29,6 +32,7 @@ class QuicHttpStreamPeer;
class NET_EXPORT_PRIVATE QuicHttpStream
: public QuicChromiumClientSession::Observer,
public QuicChromiumClientStream::Delegate,
+ public QuicClientPushPromiseIndex::Delegate,
public HttpStream {
public:
explicit QuicHttpStream(
@@ -61,6 +65,8 @@ class NET_EXPORT_PRIVATE QuicHttpStream
void GetSSLInfo(SSLInfo* ssl_info) override;
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override;
void Drain(HttpNetworkSession* session) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
void SetPriority(RequestPriority priority) override;
@@ -75,13 +81,21 @@ class NET_EXPORT_PRIVATE QuicHttpStream
// QuicChromiumClientSession::Observer implementation
void OnCryptoHandshakeConfirmed() override;
- void OnSessionClosed(int error) override;
+ void OnSessionClosed(int error, bool port_migration_detected) override;
+
+ // QuicClientPushPromiseIndex::Delegate implementation
+ bool CheckVary(const SpdyHeaderBlock& client_request,
+ const SpdyHeaderBlock& promise_request,
+ const SpdyHeaderBlock& promise_response) override;
+ void OnRendezvousResult(QuicSpdyStream* stream) override;
private:
friend class test::QuicHttpStreamPeer;
enum State {
STATE_NONE,
+ STATE_REQUEST_STREAM,
+ STATE_SET_REQUEST_PRIORITY,
STATE_SEND_HEADERS,
STATE_SEND_HEADERS_COMPLETE,
STATE_READ_REQUEST_BODY,
@@ -95,7 +109,9 @@ class NET_EXPORT_PRIVATE QuicHttpStream
void OnIOComplete(int rv);
void DoCallback(int rv);
- int DoLoop(int);
+ int DoLoop(int rv);
+ int DoStreamRequest();
+ int DoSetRequestPriority();
int DoSendHeaders();
int DoSendHeadersComplete(int rv);
int DoReadRequestBody();
@@ -108,8 +124,11 @@ class NET_EXPORT_PRIVATE QuicHttpStream
int ProcessResponseHeaders(const SpdyHeaderBlock& headers);
int ReadAvailableData(IOBuffer* buf, int buf_len);
+ void EnterStateSendHeaders();
+ int HandlePromise();
void ResetStream();
+ bool CancelPromiseIfHasBody();
State next_state_;
@@ -173,6 +192,19 @@ 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_;
+
+ bool found_promise_;
+ // |QuicClientPromisedInfo| owns this. It will be set when |Try()|
+ // is asynchronous, i.e. it returned QUIC_PENDING, and remains valid
+ // until |OnRendezvouResult()| fires or |push_handle_->Cancel()| is
+ // invoked.
+ QuicClientPushPromiseIndex::TryHandle* push_handle_;
+
base::WeakPtrFactory<QuicHttpStream> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(QuicHttpStream);
diff --git a/chromium/net/quic/quic_http_stream_test.cc b/chromium/net/quic/quic_http_stream_test.cc
index be3364c59aa..afd0f9554de 100644
--- a/chromium/net/quic/quic_http_stream_test.cc
+++ b/chromium/net/quic/quic_http_stream_test.cc
@@ -9,27 +9,32 @@
#include <vector>
#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "net/base/chunked_upload_data_stream.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/net_errors.h"
#include "net/base/socket_performance_watcher.h"
#include "net/base/test_completion_callback.h"
+#include "net/base/test_data_directory.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/http/http_response_headers.h"
#include "net/http/transport_security_state.h"
+#include "net/log/test_net_log.h"
+#include "net/log/test_net_log_util.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/crypto/quic_server_info.h"
#include "net/quic/quic_chromium_client_session.h"
#include "net/quic/quic_chromium_client_stream.h"
#include "net/quic/quic_chromium_connection_helper.h"
+#include "net/quic/quic_chromium_packet_reader.h"
+#include "net/quic/quic_chromium_packet_writer.h"
#include "net/quic/quic_connection.h"
-#include "net/quic/quic_default_packet_writer.h"
#include "net/quic/quic_http_utils.h"
-#include "net/quic/quic_packet_reader.h"
#include "net/quic/quic_write_blocked_list.h"
#include "net/quic/spdy_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
@@ -45,9 +50,11 @@
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_http_utils.h"
#include "net/spdy/spdy_protocol.h"
+#include "net/test/cert_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using std::string;
using testing::_;
using testing::AnyNumber;
using testing::Return;
@@ -57,7 +64,7 @@ namespace test {
namespace {
const char kUploadData[] = "Really nifty data!";
-const char kDefaultServerHostName[] = "www.google.com";
+const char kDefaultServerHostName[] = "www.example.org";
const uint16_t kDefaultServerPort = 80;
class TestQuicConnection : public QuicConnection {
@@ -123,25 +130,25 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
// Holds a packet to be written to the wire, and the IO mode that should
// be used by the mock socket when performing the write.
struct PacketToWrite {
- PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
+ PacketToWrite(IoMode mode, QuicReceivedPacket* packet)
: mode(mode), packet(packet) {}
PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
IoMode mode;
- QuicEncryptedPacket* packet;
+ QuicReceivedPacket* packet;
int rv;
};
QuicHttpStreamTest()
- : net_log_(BoundNetLog()),
- use_closing_stream_(false),
+ : use_closing_stream_(false),
crypto_config_(CryptoTestUtils::ProofVerifierForTesting()),
read_buffer_(new IOBufferWithSize(4096)),
- connection_id_(2),
+ promise_id_(kServerDataStreamId1),
stream_id_(kClientDataStreamId1),
+ connection_id_(2),
maker_(GetParam(), connection_id_, &clock_, kDefaultServerHostName),
- random_generator_(0) {
- IPAddressNumber ip;
- CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
+ random_generator_(0),
+ response_offset_(0) {
+ IPAddress ip(192, 0, 2, 33);
peer_addr_ = IPEndPoint(ip, 443);
self_addr_ = IPEndPoint(ip, 8435);
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
@@ -155,7 +162,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
}
// Adds a packet to the list of expected writes.
- void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
+ void AddWrite(scoped_ptr<QuicReceivedPacket> packet) {
writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
}
@@ -164,14 +171,14 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
}
// Returns the packet to be written at position |pos|.
- QuicEncryptedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
+ QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
bool AtEof() {
return socket_data_->AllReadDataConsumed() &&
socket_data_->AllWriteDataConsumed();
}
- void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
+ void ProcessPacket(scoped_ptr<QuicReceivedPacket> packet) {
connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
}
@@ -185,13 +192,13 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
writes_[i].packet->length());
}
- };
+ }
socket_data_.reset(new StaticSocketDataProvider(
nullptr, 0, mock_writes_.get(), writes_.size()));
- MockUDPClientSocket* socket =
- new MockUDPClientSocket(socket_data_.get(), net_log_.net_log());
+ scoped_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
+ socket_data_.get(), net_log_.bound().net_log()));
socket->Connect(peer_addr_);
runner_ = new TestTaskRunner(&clock_);
send_algorithm_ = new MockSendAlgorithm();
@@ -205,7 +212,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
.WillRepeatedly(Return(kMaxPacketSize));
EXPECT_CALL(*send_algorithm_, PacingRate())
.WillRepeatedly(Return(QuicBandwidth::Zero()));
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillRepeatedly(Return(QuicTime::Delta::Zero()));
EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
.WillRepeatedly(Return(QuicBandwidth::Zero()));
@@ -214,92 +221,190 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
&random_generator_));
connection_ = new TestQuicConnection(
SupportedVersions(GetParam()), connection_id_, peer_addr_,
- helper_.get(), new QuicDefaultPacketWriter(socket));
+ helper_.get(), new QuicChromiumPacketWriter(socket.get()));
connection_->set_visitor(&visitor_);
connection_->SetSendAlgorithm(send_algorithm_);
+
+ // Load a certificate that is valid for *.example.org
+ scoped_refptr<X509Certificate> test_cert(
+ ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
+ EXPECT_TRUE(test_cert.get());
+
+ verify_details_.cert_verify_result.verified_cert = test_cert;
+ verify_details_.cert_verify_result.is_issued_by_known_root = true;
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
+
session_.reset(new QuicChromiumClientSession(
- connection_, scoped_ptr<DatagramClientSocket>(socket),
+ connection_, std::move(socket),
/*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
- &transport_security_state_, make_scoped_ptr((QuicServerInfo*)nullptr),
+ &transport_security_state_,
+ make_scoped_ptr(static_cast<QuicServerInfo*>(nullptr)),
QuicServerId(kDefaultServerHostName, kDefaultServerPort,
PRIVACY_MODE_DISABLED),
kQuicYieldAfterPacketsRead,
QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
/*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_,
- "CONNECTION_UNKNOWN", base::TimeTicks::Now(),
+ "CONNECTION_UNKNOWN", base::TimeTicks::Now(), &push_promise_index_,
base::ThreadTaskRunnerHandle::Get().get(),
- /*socket_performance_watcher=*/nullptr, nullptr));
+ /*socket_performance_watcher=*/nullptr, net_log_.bound().net_log()));
session_->Initialize();
session_->GetCryptoStream()->CryptoConnect();
EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
stream_.reset(use_closing_stream_
? new AutoClosingStream(session_->GetWeakPtr())
: new QuicHttpStream(session_->GetWeakPtr()));
+
+ promised_stream_.reset(use_closing_stream_
+ ? new AutoClosingStream(session_->GetWeakPtr())
+ : new QuicHttpStream(session_->GetWeakPtr()));
+
+ push_promise_[":path"] = "/bar";
+ push_promise_[":authority"] = "www.example.org";
+ push_promise_[":version"] = "HTTP/1.1";
+ push_promise_[":method"] = "GET";
+ push_promise_[":scheme"] = "https";
+
+ promised_response_[":status"] = "200 OK";
+ promised_response_[":version"] = "HTTP/1.1";
+ promised_response_["content-type"] = "text/plain";
+
+ promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
+
+ serialized_push_promise_ =
+ SpdyUtils::SerializeUncompressedHeaders(push_promise_);
}
- void SetRequest(const std::string& method,
- const std::string& path,
+ void SetRequest(const string& method,
+ const string& path,
RequestPriority priority) {
request_headers_ = maker_.GetRequestHeaders(method, "http", path);
}
- void SetResponse(const std::string& status, const std::string& body) {
+ void SetResponse(const string& status, const string& body) {
response_headers_ = maker_.GetResponseHeaders(status);
response_data_ = body;
}
- scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
+ scoped_ptr<QuicReceivedPacket> InnerConstructDataPacket(
QuicPacketNumber packet_number,
+ QuicStreamId stream_id,
bool should_include_version,
bool fin,
QuicStreamOffset offset,
base::StringPiece data) {
- return maker_.MakeDataPacket(packet_number, stream_id_,
+ return maker_.MakeDataPacket(packet_number, stream_id,
should_include_version, fin, offset, data);
}
- scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructDataPacket(
QuicPacketNumber packet_number,
+ bool should_include_version,
+ bool fin,
+ QuicStreamOffset offset,
+ base::StringPiece data) {
+ return InnerConstructDataPacket(packet_number, stream_id_,
+ should_include_version, fin, offset, data);
+ }
+
+ scoped_ptr<QuicReceivedPacket> InnerConstructRequestHeadersPacket(
+ QuicPacketNumber packet_number,
+ QuicStreamId stream_id,
+ bool should_include_version,
bool fin,
RequestPriority request_priority,
size_t* spdy_headers_frame_length) {
SpdyPriority priority =
ConvertRequestPriorityToQuicPriority(request_priority);
return maker_.MakeRequestHeadersPacket(
- packet_number, stream_id_, kIncludeVersion, fin, priority,
+ packet_number, stream_id, should_include_version, fin, priority,
request_headers_, spdy_headers_frame_length);
}
- scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructRequestHeadersPacket(
QuicPacketNumber packet_number,
bool fin,
+ RequestPriority request_priority,
+ size_t* spdy_headers_frame_length) {
+ return InnerConstructRequestHeadersPacket(
+ packet_number, stream_id_, kIncludeVersion, fin, request_priority,
+ spdy_headers_frame_length);
+ }
+
+ scoped_ptr<QuicReceivedPacket> InnerConstructResponseHeadersPacket(
+ QuicPacketNumber packet_number,
+ QuicStreamId stream_id,
+ bool fin,
size_t* spdy_headers_frame_length) {
return maker_.MakeResponseHeadersPacket(
+ packet_number, stream_id, !kIncludeVersion, fin, response_headers_,
+ spdy_headers_frame_length, &response_offset_);
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructResponseHeadersPacket(
+ QuicPacketNumber packet_number,
+ bool fin,
+ size_t* spdy_headers_frame_length) {
+ return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
+ spdy_headers_frame_length);
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructResponseHeadersPacketWithOffset(
+ QuicPacketNumber packet_number,
+ bool fin,
+ size_t* spdy_headers_frame_length,
+ QuicStreamOffset* offset) {
+ return maker_.MakeResponseHeadersPacket(
packet_number, stream_id_, !kIncludeVersion, fin, response_headers_,
- spdy_headers_frame_length);
+ spdy_headers_frame_length, offset);
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructResponseTrailersPacket(
+ QuicPacketNumber packet_number,
+ bool fin,
+ const SpdyHeaderBlock& trailers,
+ size_t* spdy_headers_frame_length,
+ QuicStreamOffset* offset) {
+ return maker_.MakeResponseHeadersPacket(packet_number, stream_id_,
+ !kIncludeVersion, fin, trailers,
+ spdy_headers_frame_length, offset);
}
- scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructRstStreamPacket(
QuicPacketNumber packet_number) {
return maker_.MakeRstPacket(
packet_number, true, stream_id_,
AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT, GetParam()));
}
- scoped_ptr<QuicEncryptedPacket> ConstructRstStreamCancelledPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructRstStreamCancelledPacket(
QuicPacketNumber packet_number) {
return maker_.MakeRstPacket(packet_number, !kIncludeVersion, stream_id_,
QUIC_STREAM_CANCELLED);
}
- scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructRstStreamVaryMismatchPacket(
+ QuicPacketNumber packet_number) {
+ return maker_.MakeRstPacket(packet_number, !kIncludeVersion, promise_id_,
+ QUIC_PROMISE_VARY_MISMATCH);
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructAckAndRstStreamPacket(
+ QuicPacketNumber packet_number,
+ QuicPacketNumber largest_received,
+ QuicPacketNumber ack_least_unacked,
+ QuicPacketNumber stop_least_unacked) {
+ return maker_.MakeAckAndRstPacket(
+ packet_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED,
+ largest_received, ack_least_unacked, stop_least_unacked,
+ !kIncludeCongestionFeedback);
+ }
+
+ scoped_ptr<QuicReceivedPacket> ConstructAckAndRstStreamPacket(
QuicPacketNumber packet_number) {
- return maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion,
- stream_id_, QUIC_STREAM_CANCELLED, 2, 1,
- !kIncludeCongestionFeedback);
+ return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 1);
}
- scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructAckPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber least_unacked) {
@@ -307,7 +412,15 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
!kIncludeCongestionFeedback);
}
- BoundNetLog net_log_;
+ void ReceivePromise(QuicStreamId id) {
+ QuicChromiumClientStream* stream =
+ QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
+ stream->OnStreamHeaders(serialized_push_promise_);
+
+ stream->OnPromiseHeadersComplete(id, serialized_push_promise_.size());
+ }
+
+ BoundTestNetLog net_log_;
bool use_closing_stream_;
MockSendAlgorithm* send_algorithm_;
scoped_refptr<TestTaskRunner> runner_;
@@ -327,19 +440,30 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
scoped_refptr<IOBufferWithSize> read_buffer_;
SpdyHeaderBlock request_headers_;
SpdyHeaderBlock response_headers_;
- std::string request_data_;
- std::string response_data_;
+ string request_data_;
+ string response_data_;
+ QuicClientPushPromiseIndex push_promise_index_;
+
+ // For server push testing
+ scoped_ptr<QuicHttpStream> promised_stream_;
+ SpdyHeaderBlock push_promise_;
+ SpdyHeaderBlock promised_response_;
+ const QuicStreamId promise_id_;
+ string promise_url_;
+ string serialized_push_promise_;
+ const QuicStreamId stream_id_;
private:
const QuicConnectionId connection_id_;
- const QuicStreamId stream_id_;
QuicTestPacketMaker maker_;
IPEndPoint self_addr_;
IPEndPoint peer_addr_;
MockRandom random_generator_;
+ ProofVerifyDetailsChromium verify_details_;
MockCryptoClientStreamFactory crypto_client_stream_factory_;
scoped_ptr<StaticSocketDataProvider> socket_data_;
std::vector<PacketToWrite> writes_;
+ QuicStreamOffset response_offset_;
};
INSTANTIATE_TEST_CASE_P(Version,
@@ -356,6 +480,17 @@ TEST_P(QuicHttpStreamTest, CanReuseConnection) {
EXPECT_FALSE(stream_->CanReuseConnection());
}
+TEST_P(QuicHttpStreamTest, DisableConnectionMigrationForStream) {
+ request_.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION;
+ Initialize();
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
+ QuicChromiumClientStream* client_stream =
+ QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
+ EXPECT_FALSE(client_stream->can_migrate());
+}
+
TEST_P(QuicHttpStreamTest, GetRequest) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_header_frame_length;
@@ -364,10 +499,11 @@ TEST_P(QuicHttpStreamTest, GetRequest) {
Initialize();
request_.method = "GET";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
- EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
EXPECT_EQ(OK,
stream_->SendRequest(headers_, &response_, callback_.callback()));
@@ -376,7 +512,7 @@ TEST_P(QuicHttpStreamTest, GetRequest) {
EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
- SetResponse("404 Not Found", std::string());
+ SetResponse("404 Not Found", string());
size_t spdy_response_header_frame_length;
ProcessPacket(ConstructResponseHeadersPacket(
2, kFin, &spdy_response_header_frame_length));
@@ -404,6 +540,98 @@ TEST_P(QuicHttpStreamTest, GetRequest) {
stream_->GetTotalReceivedBytes());
}
+// QuicHttpStream does not currently support trailers. It should ignore
+// trailers upon receiving them.
+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(ConstructAckPacket(2, 3, 1)); // Ack the data packet.
+
+ Initialize();
+
+ request_.method = "GET";
+ request_.url = GURL("http://www.example.org/");
+
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
+
+ EXPECT_EQ(OK,
+ stream_->SendRequest(headers_, &response_, callback_.callback()));
+
+ // Ack the request.
+ ProcessPacket(ConstructAckPacket(1, 0, 0));
+
+ EXPECT_EQ(ERR_IO_PENDING, stream_->ReadResponseHeaders(callback_.callback()));
+
+ SetResponse("200 OK", string());
+
+ // Send the response headers.
+ size_t spdy_response_header_frame_length;
+ QuicStreamOffset offset = 0;
+ ProcessPacket(ConstructResponseHeadersPacketWithOffset(
+ 2, !kFin, &spdy_response_header_frame_length, &offset));
+ // Now that the headers have been processed, the callback will return.
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ ASSERT_TRUE(response_.headers.get());
+ EXPECT_EQ(200, response_.headers->response_code());
+ EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
+ EXPECT_FALSE(response_.response_time.is_null());
+ EXPECT_FALSE(response_.request_time.is_null());
+
+ // Send the response body.
+ const char kResponseBody[] = "Hello world!";
+ ProcessPacket(
+ ConstructDataPacket(3, false, !kFin, /*offset=*/0, kResponseBody));
+ SpdyHeaderBlock trailers;
+ size_t spdy_trailers_frame_length;
+ trailers["foo"] = "bar";
+ trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody));
+ ProcessPacket(ConstructResponseTrailersPacket(
+ 4, kFin, trailers, &spdy_trailers_frame_length, &offset));
+
+ // Make sure trailers are processed.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
+ stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
+ callback_.callback()));
+ EXPECT_TRUE(stream_->IsResponseBodyComplete());
+
+ EXPECT_EQ(OK,
+ stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
+ callback_.callback()));
+
+ EXPECT_TRUE(stream_->IsResponseBodyComplete());
+ EXPECT_TRUE(AtEof());
+
+ // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
+ // headers and payload.
+ EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
+ stream_->GetTotalSentBytes());
+ EXPECT_EQ(
+ static_cast<int64_t>(spdy_response_header_frame_length +
+ strlen(kResponseBody) + +spdy_trailers_frame_length),
+ stream_->GetTotalReceivedBytes());
+ // Check that NetLog was filled as expected.
+ TestNetLogEntry::List entries;
+ net_log_.GetEntries(&entries);
+ size_t pos = ExpectLogContainsSomewhere(
+ entries, /*min_offset=*/0,
+ NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
+ NetLog::PHASE_NONE);
+ pos = ExpectLogContainsSomewhere(
+ entries, /*min_offset=*/pos,
+ NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
+ NetLog::PHASE_NONE);
+ ExpectLogContainsSomewhere(
+ entries, /*min_offset=*/pos,
+ NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS,
+ NetLog::PHASE_NONE);
+}
+
// Regression test for http://crbug.com/288128
TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
@@ -413,10 +641,11 @@ TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
Initialize();
request_.method = "GET";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
- EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
EXPECT_EQ(OK,
stream_->SendRequest(headers_, &response_, callback_.callback()));
@@ -429,7 +658,7 @@ TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
headers[":status"] = "200 OK";
headers[":version"] = "HTTP/1.1";
headers["content-type"] = "text/plain";
- headers["big6"] = std::string(1000, 'x'); // Lots of x's.
+ headers["big6"] = string(1000, 'x'); // Lots of x's.
response_headers_ = headers;
size_t spdy_response_headers_frame_length;
@@ -463,12 +692,14 @@ TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
Initialize();
request_.method = "GET";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
- EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
- session_->connection()->CloseConnection(QUIC_NO_ERROR, true);
+ session_->connection()->CloseConnection(
+ QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
EXPECT_EQ(ERR_CONNECTION_CLOSED,
stream_->SendRequest(headers_, &response_, callback_.callback()));
@@ -477,6 +708,31 @@ TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendRequest) {
EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
}
+// Regression test for http://crbug.com/584441
+TEST_P(QuicHttpStreamTest, GetSSLInfoAfterSessionClosed) {
+ SetRequest("GET", "/", DEFAULT_PRIORITY);
+ Initialize();
+
+ request_.method = "GET";
+ request_.url = GURL("http://www.example.org/");
+
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
+
+ SSLInfo ssl_info;
+ EXPECT_FALSE(ssl_info.is_valid());
+ stream_->GetSSLInfo(&ssl_info);
+ EXPECT_TRUE(ssl_info.is_valid());
+
+ session_->connection()->CloseConnection(
+ QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
+
+ SSLInfo ssl_info2;
+ stream_->GetSSLInfo(&ssl_info2);
+ EXPECT_TRUE(ssl_info2.is_valid());
+}
+
TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
@@ -487,10 +743,11 @@ TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
Initialize();
request_.method = "GET";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
- EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
EXPECT_EQ(OK,
stream_->SendRequest(headers_, &response_, callback_.callback()));
@@ -517,10 +774,11 @@ TEST_P(QuicHttpStreamTest, DoNotLogGranularQuicErrorIfHandshakeNotConfirmed) {
Initialize();
request_.method = "GET";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
- EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
EXPECT_EQ(OK,
stream_->SendRequest(headers_, &response_, callback_.callback()));
@@ -551,15 +809,17 @@ TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
Initialize();
request_.method = "GET";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
- EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
EXPECT_EQ(OK,
stream_->SendRequest(headers_, &response_, callback_.callback()));
- session_->connection()->CloseConnection(QUIC_NO_ERROR, true);
+ session_->connection()->CloseConnection(
+ QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
EXPECT_NE(OK, stream_->ReadResponseHeaders(callback_.callback()));
@@ -585,12 +845,13 @@ TEST_P(QuicHttpStreamTest, SendPostRequest) {
new UploadBytesElementReader(kUploadData, strlen(kUploadData))));
ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
request_.method = "POST";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
request_.upload_data_stream = &upload_data_stream;
ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
- EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
EXPECT_EQ(OK,
stream_->SendRequest(headers_, &response_, callback_.callback()));
@@ -598,7 +859,7 @@ TEST_P(QuicHttpStreamTest, SendPostRequest) {
ProcessPacket(ConstructAckPacket(1, 0, 0));
// Send the response headers (but not the body).
- SetResponse("200 OK", std::string());
+ SetResponse("200 OK", string());
size_t spdy_response_headers_frame_length;
ProcessPacket(ConstructResponseHeadersPacket(
2, !kFin, &spdy_response_headers_frame_length));
@@ -647,13 +908,14 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
upload_data_stream.AppendData(kUploadData, chunk_size, false);
request_.method = "POST";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
request_.upload_data_stream = &upload_data_stream;
ASSERT_EQ(OK, request_.upload_data_stream->Init(
TestCompletionCallback().callback()));
- ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ ASSERT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
ASSERT_EQ(ERR_IO_PENDING,
stream_->SendRequest(headers_, &response_, callback_.callback()));
@@ -664,7 +926,7 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
ProcessPacket(ConstructAckPacket(1, 0, 0));
// Send the response headers (but not the body).
- SetResponse("200 OK", std::string());
+ SetResponse("200 OK", string());
size_t spdy_response_headers_frame_length;
ProcessPacket(ConstructResponseHeadersPacket(
2, !kFin, &spdy_response_headers_frame_length));
@@ -714,13 +976,14 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
upload_data_stream.AppendData(kUploadData, chunk_size, false);
request_.method = "POST";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
request_.upload_data_stream = &upload_data_stream;
ASSERT_EQ(OK, request_.upload_data_stream->Init(
TestCompletionCallback().callback()));
- ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ ASSERT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
ASSERT_EQ(ERR_IO_PENDING,
stream_->SendRequest(headers_, &response_, callback_.callback()));
@@ -730,7 +993,7 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
ProcessPacket(ConstructAckPacket(1, 0, 0));
// Send the response headers (but not the body).
- SetResponse("200 OK", std::string());
+ SetResponse("200 OK", string());
size_t spdy_response_headers_frame_length;
ProcessPacket(ConstructResponseHeadersPacket(
2, !kFin, &spdy_response_headers_frame_length));
@@ -776,13 +1039,14 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
ChunkedUploadDataStream upload_data_stream(0);
request_.method = "POST";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
request_.upload_data_stream = &upload_data_stream;
ASSERT_EQ(OK, request_.upload_data_stream->Init(
TestCompletionCallback().callback()));
- ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ ASSERT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
ASSERT_EQ(ERR_IO_PENDING,
stream_->SendRequest(headers_, &response_, callback_.callback()));
@@ -792,7 +1056,7 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
ProcessPacket(ConstructAckPacket(1, 0, 0));
// Send the response headers (but not the body).
- SetResponse("200 OK", std::string());
+ SetResponse("200 OK", string());
size_t spdy_response_headers_frame_length;
ProcessPacket(ConstructResponseHeadersPacket(
2, !kFin, &spdy_response_headers_frame_length));
@@ -836,10 +1100,11 @@ TEST_P(QuicHttpStreamTest, DestroyedEarly) {
Initialize();
request_.method = "GET";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
- EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
EXPECT_EQ(OK,
stream_->SendRequest(headers_, &response_, callback_.callback()));
@@ -874,23 +1139,23 @@ TEST_P(QuicHttpStreamTest, Priority) {
Initialize();
request_.method = "GET";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
- EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, net_log_,
+ EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, net_log_.bound(),
callback_.callback()));
// Check that priority is highest.
QuicChromiumClientStream* reliable_stream =
QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
DCHECK(reliable_stream);
- DCHECK_EQ(kV3HighestPriority, reliable_stream->Priority());
+ DCHECK_EQ(kV3HighestPriority, reliable_stream->priority());
EXPECT_EQ(OK,
stream_->SendRequest(headers_, &response_, callback_.callback()));
// Check that priority has now dropped back to MEDIUM.
DCHECK_EQ(MEDIUM,
- ConvertQuicPriorityToRequestPriority(reliable_stream->Priority()));
+ ConvertQuicPriorityToRequestPriority(reliable_stream->priority()));
// Ack the request.
ProcessPacket(ConstructAckPacket(1, 0, 0));
@@ -923,9 +1188,9 @@ TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
Initialize();
request_.method = "GET";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
- EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, net_log_,
+ EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM, net_log_.bound(),
callback_.callback()));
// Check that priority is highest.
@@ -934,12 +1199,12 @@ TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
DCHECK(reliable_stream);
QuicChromiumClientStream::Delegate* delegate = reliable_stream->GetDelegate();
DCHECK(delegate);
- DCHECK_EQ(kV3HighestPriority, reliable_stream->Priority());
+ DCHECK_EQ(kV3HighestPriority, reliable_stream->priority());
// Set Delegate to nullptr and make sure Priority returns highest
// priority.
reliable_stream->SetDelegate(nullptr);
- DCHECK_EQ(kV3HighestPriority, reliable_stream->Priority());
+ DCHECK_EQ(kV3HighestPriority, reliable_stream->priority());
reliable_stream->SetDelegate(delegate);
EXPECT_EQ(0, stream_->GetTotalSentBytes());
@@ -954,13 +1219,14 @@ TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
ChunkedUploadDataStream upload_data_stream(0);
request_.method = "POST";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
request_.upload_data_stream = &upload_data_stream;
ASSERT_EQ(OK, request_.upload_data_stream->Init(
TestCompletionCallback().callback()));
- ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ ASSERT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
stream_->SendRequest(headers_, &response_, callback_.callback()));
}
@@ -978,16 +1244,443 @@ TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
upload_data_stream.AppendData(kUploadData, chunk_size, false);
request_.method = "POST";
- request_.url = GURL("http://www.google.com/");
+ request_.url = GURL("http://www.example.org/");
request_.upload_data_stream = &upload_data_stream;
ASSERT_EQ(OK, request_.upload_data_stream->Init(
TestCompletionCallback().callback()));
- ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
- callback_.callback()));
+ ASSERT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
stream_->SendRequest(headers_, &response_, callback_.callback()));
}
+TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
+ SetRequest("GET", "/", DEFAULT_PRIORITY);
+ Initialize();
+
+ // Initialize the first stream, for receiving the promise on.
+ request_.method = "GET";
+ request_.url = GURL("http://www.example.org/");
+
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
+
+ // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
+ // packet, but does it matter?
+ ReceivePromise(promise_id_);
+ EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
+
+ request_.url = GURL(promise_url_);
+
+ // Make the second stream that will exercise the first step of the
+ // server push rendezvous mechanism.
+ EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(),
+ callback_.callback()));
+
+ // Receive the promised response headers.
+ response_headers_ = promised_response_;
+ size_t spdy_response_headers_frame_length;
+ ProcessPacket(InnerConstructResponseHeadersPacket(
+ 1, promise_id_, false, &spdy_response_headers_frame_length));
+
+ // Receive the promised response body.
+ const char kResponseBody[] = "Hello world!";
+ ProcessPacket(
+ InnerConstructDataPacket(2, promise_id_, false, kFin, 0, kResponseBody));
+
+ // Now sending a matching request will have successful rendezvous
+ // with the promised stream.
+ EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
+ callback_.callback()));
+
+ EXPECT_EQ(
+ QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
+ ->id(),
+ promise_id_);
+
+ // The headers will be immediately available.
+ EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
+
+ // As will be the body.
+ EXPECT_EQ(
+ static_cast<int>(strlen(kResponseBody)),
+ promised_stream_->ReadResponseBody(
+ read_buffer_.get(), read_buffer_->size(), callback_.callback()));
+ EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
+ EXPECT_TRUE(AtEof());
+
+ EXPECT_EQ(0, stream_->GetTotalSentBytes());
+ EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
+ EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
+ EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
+ strlen(kResponseBody)),
+ promised_stream_->GetTotalReceivedBytes());
+}
+
+TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
+ SetRequest("GET", "/", DEFAULT_PRIORITY);
+ Initialize();
+
+ // Initialize the first stream, for receiving the promise on.
+ request_.method = "GET";
+ request_.url = GURL("http://www.example.org/");
+
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
+
+ // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
+ // packet, but does it matter?
+ ReceivePromise(promise_id_);
+ EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
+
+ request_.url = GURL(promise_url_);
+
+ // Make the second stream that will exercise the first step of the
+ // server push rendezvous mechanism.
+ EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(),
+ callback_.callback()));
+
+ // Now sending a matching request will rendezvous with the promised
+ // stream, but pending secondary validation.
+ EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
+ headers_, &response_, callback_.callback()));
+
+ // Receive the promised response headers.
+ response_headers_ = promised_response_;
+ size_t spdy_response_headers_frame_length;
+ ProcessPacket(InnerConstructResponseHeadersPacket(
+ 1, promise_id_, false, &spdy_response_headers_frame_length));
+
+ // Receive the promised response body.
+ const char kResponseBody[] = "Hello world!";
+ ProcessPacket(
+ InnerConstructDataPacket(2, promise_id_, false, kFin, 0, kResponseBody));
+
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Rendezvous should have succeeded now, so the promised stream
+ // should point at our push stream, and we should be able read
+ // headers and data from it.
+ EXPECT_EQ(OK, callback_.WaitForResult());
+
+ EXPECT_EQ(
+ QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
+ ->id(),
+ promise_id_);
+
+ EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
+
+ EXPECT_EQ(
+ static_cast<int>(strlen(kResponseBody)),
+ promised_stream_->ReadResponseBody(
+ read_buffer_.get(), read_buffer_->size(), callback_.callback()));
+
+ // Callback should return
+ EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
+ EXPECT_TRUE(AtEof());
+
+ EXPECT_EQ(0, stream_->GetTotalSentBytes());
+ EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
+ EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
+ EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
+ strlen(kResponseBody)),
+ promised_stream_->GetTotalReceivedBytes());
+}
+
+TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
+ SetRequest("GET", "/", DEFAULT_PRIORITY);
+ Initialize();
+
+ // Initialize the first stream, for receiving the promise on.
+ request_.method = "GET";
+ request_.url = GURL("http://www.example.org/");
+
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
+
+ // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
+ // packet, but does it matter?
+
+ push_promise_[":authority"] = "mail.example.org";
+ promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
+ serialized_push_promise_ =
+ SpdyUtils::SerializeUncompressedHeaders(push_promise_);
+
+ ReceivePromise(promise_id_);
+ EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
+
+ request_.url = GURL(promise_url_);
+
+ // Make the second stream that will exercise the first step of the
+ // server push rendezvous mechanism.
+ EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(),
+ callback_.callback()));
+
+ // Receive the promised response headers.
+ response_headers_ = promised_response_;
+ size_t spdy_response_headers_frame_length;
+ ProcessPacket(InnerConstructResponseHeadersPacket(
+ 1, promise_id_, false, &spdy_response_headers_frame_length));
+
+ // Receive the promised response body.
+ const char kResponseBody[] = "Hello world!";
+ ProcessPacket(
+ InnerConstructDataPacket(2, promise_id_, false, kFin, 0, kResponseBody));
+
+ // Now sending a matching request will have successful rendezvous
+ // with the promised stream.
+ EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
+ callback_.callback()));
+
+ EXPECT_EQ(
+ QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
+ ->id(),
+ promise_id_);
+
+ // The headers will be immediately available.
+ EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
+
+ // As will be the body.
+ EXPECT_EQ(
+ static_cast<int>(strlen(kResponseBody)),
+ promised_stream_->ReadResponseBody(
+ read_buffer_.get(), read_buffer_->size(), callback_.callback()));
+ EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
+ EXPECT_TRUE(AtEof());
+
+ EXPECT_EQ(0, stream_->GetTotalSentBytes());
+ EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
+ EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
+ EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
+ strlen(kResponseBody)),
+ promised_stream_->GetTotalReceivedBytes());
+}
+
+TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
+ SetRequest("GET", "/", DEFAULT_PRIORITY);
+ Initialize();
+
+ // Initialize the first stream, for receiving the promise on.
+ request_.method = "GET";
+ request_.url = GURL("http://www.example.org/");
+
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
+
+ // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
+ // packet, but does it matter?
+ push_promise_[":authority"] = "www.notexample.org";
+ promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
+ serialized_push_promise_ =
+ SpdyUtils::SerializeUncompressedHeaders(push_promise_);
+
+ ReceivePromise(promise_id_);
+ // The promise will have been rejected because the cert doesn't
+ // match.
+ EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
+}
+
+TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
+ SetRequest("GET", "/", DEFAULT_PRIORITY);
+ Initialize();
+
+ // Initialize the first stream, for receiving the promise on.
+ request_.method = "GET";
+ request_.url = GURL("http://www.example.org/");
+
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
+
+ push_promise_["accept-encoding"] = "gzip";
+ serialized_push_promise_ =
+ SpdyUtils::SerializeUncompressedHeaders(push_promise_);
+
+ // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
+ // packet, but does it matter?
+ ReceivePromise(promise_id_);
+ EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
+
+ request_.url = GURL(promise_url_);
+
+ // Make the second stream that will exercise the first step of the
+ // server push rendezvous mechanism.
+ EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(),
+ callback_.callback()));
+
+ headers_.SetHeader("accept-encoding", "gzip");
+
+ // Now sending a matching request will rendezvous with the promised
+ // stream, but pending secondary validation.
+ EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
+ headers_, &response_, callback_.callback()));
+
+ // Receive the promised response headers.
+ promised_response_["vary"] = "accept-encoding";
+ response_headers_ = promised_response_;
+ size_t spdy_response_headers_frame_length;
+ ProcessPacket(InnerConstructResponseHeadersPacket(
+ 1, promise_id_, false, &spdy_response_headers_frame_length));
+
+ // Receive the promised response body.
+ const char kResponseBody[] = "Hello world!";
+ ProcessPacket(
+ InnerConstructDataPacket(2, promise_id_, false, kFin, 0, kResponseBody));
+
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Rendezvous should have succeeded now, so the promised stream
+ // should point at our push stream, and we should be able read
+ // headers and data from it.
+ EXPECT_EQ(OK, callback_.WaitForResult());
+
+ EXPECT_EQ(
+ QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
+ ->id(),
+ promise_id_);
+
+ EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
+
+ EXPECT_EQ(
+ static_cast<int>(strlen(kResponseBody)),
+ promised_stream_->ReadResponseBody(
+ read_buffer_.get(), read_buffer_->size(), callback_.callback()));
+
+ // Callback should return
+ EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
+ EXPECT_TRUE(AtEof());
+
+ EXPECT_EQ(0, stream_->GetTotalSentBytes());
+ EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
+ EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
+ EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
+ strlen(kResponseBody)),
+ promised_stream_->GetTotalReceivedBytes());
+}
+
+TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
+ SetRequest("GET", "/", DEFAULT_PRIORITY);
+ request_headers_[":scheme"] = "https";
+ request_headers_[":path"] = "/bar";
+ request_headers_["accept-encoding"] = "sdch";
+
+ size_t spdy_request_header_frame_length;
+ AddWrite(ConstructRstStreamVaryMismatchPacket(1));
+ AddWrite(InnerConstructRequestHeadersPacket(
+ 2, stream_id_ + 2, !kIncludeVersion, kFin, DEFAULT_PRIORITY,
+ &spdy_request_header_frame_length));
+ AddWrite(ConstructAckPacket(3, 3, 1));
+ AddWrite(ConstructRstStreamCancelledPacket(4));
+ Initialize();
+
+ // Initialize the first stream, for receiving the promise on.
+ request_.method = "GET";
+ request_.url = GURL("http://www.example.org/");
+
+ EXPECT_EQ(OK,
+ stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
+
+ push_promise_["accept-encoding"] = "gzip";
+ serialized_push_promise_ =
+ SpdyUtils::SerializeUncompressedHeaders(push_promise_);
+
+ // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
+ // packet, but does it matter?
+ ReceivePromise(promise_id_);
+ EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
+
+ request_.url = GURL(promise_url_);
+
+ // Make the second stream that will exercise the first step of the
+ // server push rendezvous mechanism.
+ EXPECT_EQ(OK, promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+ net_log_.bound(),
+ callback_.callback()));
+
+ headers_.SetHeader("accept-encoding", "sdch");
+
+ // Now sending a matching request will rendezvous with the promised
+ // stream, but pending secondary validation.
+ EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
+ headers_, &response_, callback_.callback()));
+
+ // Receive the promised response headers.
+ promised_response_["vary"] = "accept-encoding";
+ response_headers_ = promised_response_;
+ size_t spdy_response_headers_frame_length;
+ ProcessPacket(InnerConstructResponseHeadersPacket(
+ 1, promise_id_, false, &spdy_response_headers_frame_length));
+
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Rendezvous should have failed due to vary mismatch, so the
+ // promised stream should have been aborted, and instead we have a
+ // new, regular client initiated stream.
+ EXPECT_EQ(OK, callback_.WaitForResult());
+
+ // Not a server-initiated stream.
+ EXPECT_NE(
+ QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
+ ->id(),
+ promise_id_);
+
+ // Instead, a new client-initiated stream.
+ EXPECT_EQ(
+ QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
+ ->id(),
+ stream_id_ + 2);
+
+ // After rendezvous failure, the push stream has been cancelled.
+ EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
+
+ // The rest of the test verifies that the retried as
+ // client-initiated version of |promised_stream_| works as intended.
+
+ // Ack the request.
+ ProcessPacket(ConstructAckPacket(2, 0, 0));
+
+ SetResponse("404 Not Found", string());
+ size_t spdy_response_header_frame_length;
+ ProcessPacket(InnerConstructResponseHeadersPacket(
+ 3, stream_id_ + 2, kFin, &spdy_response_header_frame_length));
+
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
+ ASSERT_TRUE(response_.headers.get());
+ EXPECT_EQ(404, response_.headers->response_code());
+ EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
+ EXPECT_FALSE(response_.response_time.is_null());
+ EXPECT_FALSE(response_.request_time.is_null());
+
+ // There is no body, so this should return immediately.
+ EXPECT_EQ(
+ 0, promised_stream_->ReadResponseBody(
+ read_buffer_.get(), read_buffer_->size(), callback_.callback()));
+ EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
+
+ stream_->Close(true);
+
+ EXPECT_TRUE(AtEof());
+
+ // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
+ // headers and payload.
+ EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
+ promised_stream_->GetTotalSentBytes());
+ EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
+ promised_stream_->GetTotalReceivedBytes());
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_multipath_received_packet_manager.cc b/chromium/net/quic/quic_multipath_received_packet_manager.cc
index 0dc45c09e64..fd2898f0a67 100644
--- a/chromium/net/quic/quic_multipath_received_packet_manager.cc
+++ b/chromium/net/quic/quic_multipath_received_packet_manager.cc
@@ -6,6 +6,8 @@
#include "base/stl_util.h"
+#include "net/quic/quic_bug_tracker.h"
+
namespace net {
QuicMultipathReceivedPacketManager::QuicMultipathReceivedPacketManager(
@@ -21,8 +23,8 @@ void QuicMultipathReceivedPacketManager::OnPathCreated(
QuicPathId path_id,
QuicConnectionStats* stats) {
if (path_managers_[path_id] != nullptr) {
- LOG(DFATAL) << "Received packet manager of path already exists: "
- << static_cast<uint32_t>(path_id);
+ QUIC_BUG << "Received packet manager of path already exists: "
+ << static_cast<uint32_t>(path_id);
return;
}
@@ -32,8 +34,8 @@ void QuicMultipathReceivedPacketManager::OnPathCreated(
void QuicMultipathReceivedPacketManager::OnPathClosed(QuicPathId path_id) {
QuicReceivedPacketManager* manager = path_managers_[path_id];
if (manager == nullptr) {
- LOG(DFATAL) << "Received packet manager of path does not exist: "
- << static_cast<uint32_t>(path_id);
+ QUIC_BUG << "Received packet manager of path does not exist: "
+ << static_cast<uint32_t>(path_id);
return;
}
@@ -48,31 +50,19 @@ void QuicMultipathReceivedPacketManager::RecordPacketReceived(
QuicTime receipt_time) {
QuicReceivedPacketManager* manager = path_managers_[path_id];
if (manager == nullptr) {
- LOG(DFATAL) << "Received a packet on a non-existent path.";
+ QUIC_BUG << "Received a packet on a non-existent path.";
return;
}
manager->RecordPacketReceived(bytes, header, receipt_time);
}
-void QuicMultipathReceivedPacketManager::RecordPacketRevived(
- QuicPathId path_id,
- QuicPacketNumber packet_number) {
- QuicReceivedPacketManager* manager = path_managers_[path_id];
- if (manager == nullptr) {
- LOG(DFATAL) << "Revived a packet on a non-existent path.";
- return;
- }
-
- manager->RecordPacketRevived(packet_number);
-}
-
bool QuicMultipathReceivedPacketManager::IsMissing(
QuicPathId path_id,
QuicPacketNumber packet_number) {
QuicReceivedPacketManager* manager = path_managers_[path_id];
if (manager == nullptr) {
- LOG(DFATAL) << "Check whether a packet is missing on a non-existent path.";
+ QUIC_BUG << "Check whether a packet is missing on a non-existent path.";
return true;
}
@@ -84,30 +74,13 @@ bool QuicMultipathReceivedPacketManager::IsAwaitingPacket(
QuicPacketNumber packet_number) {
QuicReceivedPacketManager* manager = path_managers_[path_id];
if (manager == nullptr) {
- LOG(DFATAL) << "Check whether a packet is awaited on a non-existent path.";
+ QUIC_BUG << "Check whether a packet is awaited on a non-existent path.";
return false;
}
return manager->IsAwaitingPacket(packet_number);
}
-void QuicMultipathReceivedPacketManager::UpdateReceivedPacketInfo(
- std::vector<QuicAckFrame>* ack_frames,
- QuicTime approximate_now,
- bool force_all_paths) {
- QuicAckFrame ack_frame;
- for (std::pair<QuicPathId, QuicReceivedPacketManager*>
- per_path_received_packet_manager : path_managers_) {
- if (!force_all_paths &&
- !per_path_received_packet_manager.second->ack_frame_updated()) {
- continue;
- }
- per_path_received_packet_manager.second->UpdateReceivedPacketInfo(
- &ack_frame, approximate_now);
- ack_frames->push_back(ack_frame);
- }
-}
-
void QuicMultipathReceivedPacketManager::UpdatePacketInformationSentByPeer(
const std::vector<QuicStopWaitingFrame>& stop_waitings) {
for (QuicStopWaitingFrame stop_waiting : stop_waitings) {
@@ -123,8 +96,7 @@ bool QuicMultipathReceivedPacketManager::HasNewMissingPackets(
MultipathReceivedPacketManagerMap::const_iterator it =
path_managers_.find(path_id);
if (it == path_managers_.end()) {
- LOG(DFATAL)
- << "Check whether has new missing packets on a non-existent path.";
+ QUIC_BUG << "Check whether has new missing packets on a non-existent path.";
return false;
}
@@ -136,7 +108,7 @@ QuicMultipathReceivedPacketManager::GetPeerLeastPacketAwaitingAck(
QuicPathId path_id) {
QuicReceivedPacketManager* manager = path_managers_[path_id];
if (manager == nullptr) {
- LOG(DFATAL)
+ QUIC_BUG
<< "Try to get peer_least_packet_awaiting_ack of a non-existent path.";
return false;
}
diff --git a/chromium/net/quic/quic_multipath_received_packet_manager.h b/chromium/net/quic/quic_multipath_received_packet_manager.h
index e33c5fccdb6..5f1f3a3fa7e 100644
--- a/chromium/net/quic/quic_multipath_received_packet_manager.h
+++ b/chromium/net/quic/quic_multipath_received_packet_manager.h
@@ -8,6 +8,7 @@
#ifndef NET_QUIC_QUIC_MULTIPATH_RECEIVED_PACKET_MANAGER_H_
#define NET_QUIC_QUIC_MULTIPATH_RECEIVED_PACKET_MANAGER_H_
+#include <unordered_map>
#include <vector>
#include "net/quic/quic_protocol.h"
@@ -21,7 +22,7 @@ class QuicMultipathReceivedPacketManagerPeer;
class NET_EXPORT_PRIVATE QuicMultipathReceivedPacketManager {
public:
- typedef base::hash_map<QuicPathId, QuicReceivedPacketManager*>
+ typedef std::unordered_map<QuicPathId, QuicReceivedPacketManager*>
MultipathReceivedPacketManagerMap;
explicit QuicMultipathReceivedPacketManager(QuicConnectionStats* stats);
@@ -39,9 +40,6 @@ class NET_EXPORT_PRIVATE QuicMultipathReceivedPacketManager {
const QuicPacketHeader& header,
QuicTime receipt_time);
- // Called when packet with |packet_number| is revived on path with |path_id|.
- void RecordPacketRevived(QuicPathId path_id, QuicPacketNumber packet_number);
-
// Checks whether |packet_number| is missing on path with |path_id|.
bool IsMissing(QuicPathId path_id, QuicPacketNumber packet_number);
diff --git a/chromium/net/quic/quic_multipath_received_packet_manager_test.cc b/chromium/net/quic/quic_multipath_received_packet_manager_test.cc
index e342ae86f55..e03a28a0de7 100644
--- a/chromium/net/quic/quic_multipath_received_packet_manager_test.cc
+++ b/chromium/net/quic/quic_multipath_received_packet_manager_test.cc
@@ -5,6 +5,7 @@
#include "net/quic/quic_multipath_received_packet_manager.h"
#include "net/quic/quic_connection_stats.h"
+#include "net/quic/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"
@@ -100,14 +101,6 @@ TEST_F(QuicMultipathReceivedPacketManagerTest, RecordPacketReceived) {
"Received a packet on a non-existent path");
}
-TEST_F(QuicMultipathReceivedPacketManagerTest, RecordPacketRevived) {
- EXPECT_CALL(*manager_0_, RecordPacketRevived(_)).Times(1);
- multipath_manager_.RecordPacketRevived(kDefaultPathId, header_.packet_number);
- EXPECT_DFATAL(
- multipath_manager_.RecordPacketRevived(kPathId2, header_.packet_number),
- "Revived a packet on a non-existent path");
-}
-
TEST_F(QuicMultipathReceivedPacketManagerTest, IsMissing) {
EXPECT_CALL(*manager_0_, IsMissing(header_.packet_number))
.WillOnce(Return(true));
@@ -134,25 +127,6 @@ TEST_F(QuicMultipathReceivedPacketManagerTest, IsAwaitingPacket) {
"Check whether a packet is awaited on a non-existent path");
}
-TEST_F(QuicMultipathReceivedPacketManagerTest, UpdateReceivedPacketInfo) {
- std::vector<QuicAckFrame> ack_frames;
- EXPECT_EQ(static_cast<size_t>(0), ack_frames.size());
- EXPECT_CALL(*manager_0_, ack_frame_updated()).WillOnce(Return(false));
- EXPECT_CALL(*manager_1_, ack_frame_updated()).WillRepeatedly(Return(false));
- multipath_manager_.UpdateReceivedPacketInfo(&ack_frames, QuicTime::Zero(),
- /*force_all_paths=*/false);
- EXPECT_EQ(static_cast<size_t>(0), ack_frames.size());
- EXPECT_CALL(*manager_0_, ack_frame_updated()).WillOnce(Return(true));
- multipath_manager_.UpdateReceivedPacketInfo(&ack_frames, QuicTime::Zero(),
- /*force_all_paths=*/false);
- EXPECT_EQ(static_cast<size_t>(1), ack_frames.size());
-
- std::vector<QuicAckFrame> ack_frames_all;
- multipath_manager_.UpdateReceivedPacketInfo(&ack_frames_all, QuicTime::Zero(),
- /*force_all_paths=*/true);
- EXPECT_EQ(static_cast<size_t>(2), ack_frames_all.size());
-}
-
TEST_F(QuicMultipathReceivedPacketManagerTest,
UpdatePacketInformationSentByPeer) {
std::vector<QuicStopWaitingFrame> stop_waitings;
diff --git a/chromium/net/quic/quic_multipath_transmissions_map.cc b/chromium/net/quic/quic_multipath_transmissions_map.cc
index 14655e375da..a960e5a64c7 100644
--- a/chromium/net/quic/quic_multipath_transmissions_map.cc
+++ b/chromium/net/quic/quic_multipath_transmissions_map.cc
@@ -4,7 +4,7 @@
#include "net/quic/quic_multipath_transmissions_map.h"
-namespace net_quic {
+namespace net {
QuicMultipathTransmissionsMap::QuicMultipathTransmissionsMap() {}
@@ -67,4 +67,4 @@ void QuicMultipathTransmissionsMap::OnPacketHandled(
delete transmission_list;
}
-} // namespace net_quic
+} // namespace net
diff --git a/chromium/net/quic/quic_multipath_transmissions_map.h b/chromium/net/quic/quic_multipath_transmissions_map.h
index 121e63ee6a5..203fb285328 100644
--- a/chromium/net/quic/quic_multipath_transmissions_map.h
+++ b/chromium/net/quic/quic_multipath_transmissions_map.h
@@ -13,20 +13,28 @@
#define NET_QUIC_QUIC_MULTIPATH_TRANSMISSIONS_MAP_H_
#include <deque>
+#include <unordered_map>
-#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_utils.h"
-namespace net_quic {
+namespace net {
-typedef std::pair<net::QuicPathId, net::QuicPacketNumber>
- QuicPathIdPacketNumber;
+typedef std::pair<QuicPathId, QuicPacketNumber> QuicPathIdPacketNumber;
class NET_EXPORT_PRIVATE QuicMultipathTransmissionsMap {
public:
+ struct QuicPathIdPacketNumberHash {
+ size_t operator()(std::pair<QuicPathId, QuicPacketNumber> value) const {
+ return QuicUtils::PackPathIdAndPacketNumber(value.first, value.second);
+ }
+ };
+
typedef std::deque<QuicPathIdPacketNumber> MultipathTransmissionsList;
- typedef base::hash_map<QuicPathIdPacketNumber, MultipathTransmissionsList*>
+ typedef std::unordered_map<QuicPathIdPacketNumber,
+ MultipathTransmissionsList*,
+ QuicPathIdPacketNumberHash>
MultipathTransmissionsMap;
QuicMultipathTransmissionsMap();
@@ -60,6 +68,6 @@ class NET_EXPORT_PRIVATE QuicMultipathTransmissionsMap {
MultipathTransmissionsMap transmission_map_;
};
-} // namespace net_quic
+} // namespace net
#endif // NET_QUIC_QUIC_MULTIPATH_TRANSMISSIONS_MAP_H_
diff --git a/chromium/net/quic/quic_multipath_transmissions_map_test.cc b/chromium/net/quic/quic_multipath_transmissions_map_test.cc
index fcae200772c..ec31910ba75 100644
--- a/chromium/net/quic/quic_multipath_transmissions_map_test.cc
+++ b/chromium/net/quic/quic_multipath_transmissions_map_test.cc
@@ -5,7 +5,7 @@
#include "net/quic/quic_multipath_transmissions_map.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace net_quic {
+namespace net {
namespace test {
namespace {
@@ -111,4 +111,4 @@ TEST(QuicAcrossPathsTransmissionMapTest, OnPacketHandled) {
} // namespace
} // namespace test
-} // namespace net_quic
+} // namespace net
diff --git a/chromium/net/quic/quic_network_transaction_unittest.cc b/chromium/net/quic/quic_network_transaction_unittest.cc
index d6f5c3c2c46..4774b5bf552 100644
--- a/chromium/net/quic/quic_network_transaction_unittest.cc
+++ b/chromium/net/quic/quic_network_transaction_unittest.cc
@@ -11,8 +11,8 @@
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "net/base/chunked_upload_data_stream.h"
-#include "net/base/network_quality_estimator.h"
#include "net/base/socket_performance_watcher.h"
+#include "net/base/socket_performance_watcher_factory.h"
#include "net/base/test_completion_callback.h"
#include "net/base/test_data_directory.h"
#include "net/cert/mock_cert_verifier.h"
@@ -61,18 +61,18 @@ namespace {
static const char kQuicAlternateProtocolHeader[] =
"Alternate-Protocol: 443:quic\r\n\r\n";
-static const char kQuicAlternateProtocol50pctHeader[] =
+static const char kQuicAlternateProtocolWithProbabilityHeader[] =
"Alternate-Protocol: 443:quic,p=.5\r\n\r\n";
static const char kQuicAlternateProtocolDifferentPortHeader[] =
"Alternate-Protocol: 137:quic\r\n\r\n";
static const char kQuicAlternativeServiceHeader[] =
"Alt-Svc: quic=\":443\"\r\n\r\n";
-static const char kQuicAlternativeService50pctHeader[] =
+static const char kQuicAlternativeServiceWithProbabilityHeader[] =
"Alt-Svc: quic=\":443\";p=\".5\"\r\n\r\n";
static const char kQuicAlternativeServiceDifferentPortHeader[] =
"Alt-Svc: quic=\":137\"\r\n\r\n";
-const char kDefaultServerHostName[] = "mail.example.com";
+const char kDefaultServerHostName[] = "mail.example.org";
} // namespace
@@ -139,47 +139,53 @@ class ProxyHeadersHandler {
bool was_called_;
};
-class TestNetworkQualityEstimator : public NetworkQualityEstimator {
+class TestSocketPerformanceWatcher : public SocketPerformanceWatcher {
public:
- TestNetworkQualityEstimator()
- : NetworkQualityEstimator(scoped_ptr<net::ExternalEstimateProvider>(),
- std::map<std::string, std::string>()),
- watcher_count_(0) {}
+ explicit TestSocketPerformanceWatcher(bool* rtt_notification_received)
+ : rtt_notification_received_(rtt_notification_received) {}
+ ~TestSocketPerformanceWatcher() override {}
- ~TestNetworkQualityEstimator() override {}
+ bool ShouldNotifyUpdatedRTT() const override { return true; }
+ void OnUpdatedRTTAvailable(const base::TimeDelta& rtt) override {
+ *rtt_notification_received_ = true;
+ }
+
+ void OnConnectionChanged() override {}
+
+ private:
+ bool* rtt_notification_received_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSocketPerformanceWatcher);
+};
+
+class TestSocketPerformanceWatcherFactory
+ : public SocketPerformanceWatcherFactory {
+ public:
+ TestSocketPerformanceWatcherFactory()
+ : watcher_count_(0u), rtt_notification_received_(false) {}
+ ~TestSocketPerformanceWatcherFactory() override {}
+
+ // SocketPerformanceWatcherFactory implementation:
scoped_ptr<SocketPerformanceWatcher> CreateSocketPerformanceWatcher(
const Protocol protocol) override {
if (protocol != PROTOCOL_QUIC) {
- NOTIMPLEMENTED();
+ return nullptr;
}
++watcher_count_;
- return NetworkQualityEstimator::CreateSocketPerformanceWatcher(protocol);
+ return scoped_ptr<SocketPerformanceWatcher>(
+ new TestSocketPerformanceWatcher(&rtt_notification_received_));
}
size_t watcher_count() const { return watcher_count_; }
- private:
- size_t watcher_count_;
- DISALLOW_COPY_AND_ASSIGN(TestNetworkQualityEstimator);
-};
-
-class TestRTTObserver : public NetworkQualityEstimator::RTTObserver {
- public:
- TestRTTObserver() : rtt_notification_received_(false) {}
-
bool rtt_notification_received() const { return rtt_notification_received_; }
- // NetworkQualityEstimator::RttObserver implementation:
- void OnRTTObservation(
- int32_t rtt_ms,
- const base::TimeTicks& timestamp,
- net::NetworkQualityEstimator::ObservationSource source) override {
- rtt_notification_received_ = true;
- }
-
private:
+ size_t watcher_count_;
bool rtt_notification_received_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSocketPerformanceWatcherFactory);
};
class QuicNetworkTransactionTest
@@ -190,7 +196,6 @@ class QuicNetworkTransactionTest
: clock_(new MockClock),
maker_(GetParam(), 0, clock_, kDefaultServerHostName),
cert_transparency_verifier_(new MultiLogCTVerifier()),
- test_network_quality_estimator_(new TestNetworkQualityEstimator()),
ssl_config_service_(new SSLConfigServiceDefaults),
proxy_service_(ProxyService::CreateDirect()),
auth_handler_factory_(
@@ -204,8 +209,11 @@ class QuicNetworkTransactionTest
request_.load_flags = 0;
clock_->AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
+ params_.parse_alternative_services = true;
+ params_.enable_alternative_service_with_different_host = true;
+
scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"));
+ ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
verify_details_.cert_verify_result.verified_cert = cert;
verify_details_.cert_verify_result.is_issued_by_known_root = true;
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
@@ -230,6 +238,13 @@ class QuicNetworkTransactionTest
return maker_.MakeConnectionClosePacket(num);
}
+ scoped_ptr<QuicEncryptedPacket> ConstructGoAwayPacket(
+ QuicPacketNumber num,
+ QuicErrorCode error_code,
+ std::string reason_phrase) {
+ return maker_.MakeGoAwayPacket(num, error_code, reason_phrase);
+ }
+
scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
QuicPacketNumber largest_received,
QuicPacketNumber least_unacked) {
@@ -237,6 +252,18 @@ class QuicNetworkTransactionTest
least_unacked, true);
}
+ scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstPacket(
+ QuicPacketNumber num,
+ QuicStreamId stream_id,
+ QuicRstStreamErrorCode error_code,
+ QuicPacketNumber largest_received,
+ QuicPacketNumber ack_least_unacked,
+ QuicPacketNumber stop_least_unacked) {
+ return maker_.MakeAckAndRstPacket(num, false, stream_id, error_code,
+ largest_received, ack_least_unacked,
+ stop_least_unacked, true);
+ }
+
scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
QuicPacketNumber largest_received,
QuicPacketNumber least_unacked,
@@ -407,15 +434,9 @@ class QuicNetworkTransactionTest
packet_number, stream_id, should_include_version, fin, headers, offset);
}
- void CreateSession() { CreateSessionWithFactory(&socket_factory_, false); }
-
- void CreateSessionWithNextProtos() {
- CreateSessionWithFactory(&socket_factory_, true);
- }
+ void CreateSession() { CreateSessionWithFactory(&socket_factory_); }
- // If |use_next_protos| is true, enables SPDY and QUIC.
- void CreateSessionWithFactory(ClientSocketFactory* socket_factory,
- bool use_next_protos) {
+ void CreateSessionWithFactory(ClientSocketFactory* socket_factory) {
params_.enable_quic = true;
params_.quic_clock = clock_;
params_.quic_random = &random_generator_;
@@ -426,26 +447,19 @@ class QuicNetworkTransactionTest
params_.transport_security_state = &transport_security_state_;
params_.cert_transparency_verifier = cert_transparency_verifier_.get();
params_.socket_performance_watcher_factory =
- test_network_quality_estimator_.get();
+ &test_socket_performance_watcher_factory_;
params_.proxy_service = proxy_service_.get();
params_.ssl_config_service = ssl_config_service_.get();
params_.http_auth_handler_factory = auth_handler_factory_.get();
params_.http_server_properties = http_server_properties_.GetWeakPtr();
params_.quic_supported_versions = SupportedVersions(GetParam());
for (const char* host :
- {kDefaultServerHostName, "www.example.com", "news.example.com",
- "bar.example.com", "foo.example.com", "www.example.org",
- "invalid.example.org", "docs.example.org"}) {
+ {kDefaultServerHostName, "www.example.org", "news.example.org",
+ "bar.example.org", "foo.example.org", "invalid.example.org",
+ "mail.example.com"}) {
params_.quic_host_whitelist.insert(host);
}
- test_network_quality_estimator_->AddRTTObserver(&rtt_observer_);
-
- if (use_next_protos) {
- params_.use_alternative_services = true;
- params_.next_protos = NextProtosWithSpdyAndQuic(true, true);
- }
-
session_.reset(new HttpNetworkSession(params_));
session_->quic_stream_factory()->set_require_confirmation(false);
ASSERT_EQ(params_.quic_socket_receive_buffer_size,
@@ -525,7 +539,19 @@ class QuicNetworkTransactionTest
AlternativeService alternative_service(QUIC, host_port_pair.host(), 443);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
http_server_properties_.SetAlternativeService(
- host_port_pair, alternative_service, 1.0, expiration);
+ host_port_pair, alternative_service, expiration);
+ }
+
+ void AddQuicRemoteAlternativeServiceMapping(
+ MockCryptoClientStream::HandshakeMode handshake_mode,
+ const HostPortPair& alternative) {
+ crypto_client_stream_factory_.set_handshake_mode(handshake_mode);
+ HostPortPair host_port_pair = HostPortPair::FromURL(request_.url);
+ AlternativeService alternative_service(QUIC, alternative.host(),
+ alternative.port());
+ base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
+ http_server_properties_.SetAlternativeService(
+ host_port_pair, alternative_service, expiration);
}
void ExpectBrokenAlternateProtocolMapping() {
@@ -565,8 +591,7 @@ class QuicNetworkTransactionTest
MockCertVerifier cert_verifier_;
TransportSecurityState transport_security_state_;
scoped_ptr<CTVerifier> cert_transparency_verifier_;
- scoped_ptr<TestNetworkQualityEstimator> test_network_quality_estimator_;
- TestRTTObserver rtt_observer_;
+ TestSocketPerformanceWatcherFactory test_socket_performance_watcher_factory_;
scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
scoped_ptr<ProxyService> proxy_service_;
scoped_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
@@ -602,8 +627,8 @@ INSTANTIATE_TEST_CASE_P(Version,
::testing::ValuesIn(QuicSupportedVersions()));
TEST_P(QuicNetworkTransactionTest, ForceQuic) {
- params_.origin_to_force_quic_on =
- HostPortPair::FromString("mail.example.com:443");
+ params_.origins_to_force_quic_on.insert(
+ HostPortPair::FromString("mail.example.org:443"));
MockQuicData mock_quic_data;
mock_quic_data.AddWrite(
@@ -622,11 +647,15 @@ TEST_P(QuicNetworkTransactionTest, ForceQuic) {
// the alternate-protocol job will "win".
AddHangingNonAlternateProtocolSocketData();
+ params_.parse_alternative_services = false;
+ params_.enable_alternative_service_with_different_host = false;
CreateSession();
- EXPECT_FALSE(rtt_observer_.rtt_notification_received());
+ EXPECT_FALSE(
+ test_socket_performance_watcher_factory_.rtt_notification_received());
SendRequestAndExpectQuicResponse("hello!");
- EXPECT_TRUE(rtt_observer_.rtt_notification_received());
+ EXPECT_TRUE(
+ test_socket_performance_watcher_factory_.rtt_notification_received());
// Check that the NetLog was filled reasonably.
TestNetLogEntry::List entries;
@@ -670,7 +699,7 @@ TEST_P(QuicNetworkTransactionTest, ForceQuic) {
TEST_P(QuicNetworkTransactionTest, QuicProxy) {
params_.enable_quic_for_proxies = true;
proxy_service_ =
- ProxyService::CreateFixedFromPacResult("QUIC mail.example.com:70");
+ ProxyService::CreateFixedFromPacResult("QUIC mail.example.org:70");
MockQuicData mock_quic_data;
mock_quic_data.AddWrite(
@@ -686,22 +715,26 @@ TEST_P(QuicNetworkTransactionTest, QuicProxy) {
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
- EXPECT_FALSE(rtt_observer_.rtt_notification_received());
+ EXPECT_FALSE(
+ test_socket_performance_watcher_factory_.rtt_notification_received());
// There is no need to set up an alternate protocol job, because
// no attempt will be made to speak to the proxy over TCP.
- request_.url = GURL("http://mail.example.com/");
+ request_.url = GURL("http://mail.example.org/");
+ params_.parse_alternative_services = false;
+ params_.enable_alternative_service_with_different_host = false;
CreateSession();
SendRequestAndExpectQuicResponseFromProxyOnPort("hello!", 70);
- EXPECT_TRUE(rtt_observer_.rtt_notification_received());
+ EXPECT_TRUE(
+ test_socket_performance_watcher_factory_.rtt_notification_received());
}
// Regression test for https://crbug.com/492458. Test that for an HTTP
// connection through a QUIC proxy, the certificate exhibited by the proxy is
// checked against the proxy hostname, not the origin hostname.
TEST_P(QuicNetworkTransactionTest, QuicProxyWithCert) {
- const std::string origin_host = "news.example.com";
+ const std::string origin_host = "mail.example.com";
const std::string proxy_host = "www.example.org";
params_.enable_quic_for_proxies = true;
@@ -723,7 +756,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyWithCert) {
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"));
+ ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
ASSERT_TRUE(cert.get());
// This certificate is valid for the proxy, but not for the origin.
bool common_name_fallback_used;
@@ -738,14 +771,56 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyWithCert) {
request_.url = GURL("http://" + origin_host);
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::CONFIRM_HANDSHAKE);
SendRequestAndExpectQuicResponseFromProxyOnPort("hello!", 70);
}
+TEST_P(QuicNetworkTransactionTest, AlternativeServicesDifferentHost) {
+ params_.enable_alternative_service_with_different_host = true;
+ HostPortPair origin("www.example.org", 443);
+ HostPortPair alternative("mail.example.org", 443);
+
+ base::FilePath certs_dir = GetTestCertsDirectory();
+ scoped_refptr<X509Certificate> cert(
+ ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
+ ASSERT_TRUE(cert.get());
+ // TODO(rch): the connection should be "to" the origin, so if the cert is
+ // valid for the origin but not the alternative, that should work too.
+ bool common_name_fallback_used;
+ EXPECT_TRUE(cert->VerifyNameMatch(origin.host(), &common_name_fallback_used));
+ EXPECT_TRUE(
+ cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used));
+ ProofVerifyDetailsChromium verify_details;
+ verify_details.cert_verify_result.verified_cert = cert;
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ maker_.set_hostname(origin.host());
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/")));
+ mock_quic_data.AddRead(ConstructResponseHeadersPacket(
+ 1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructAckPacket(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_);
+
+ request_.url = GURL("https://" + origin.host());
+ AddQuicRemoteAlternativeServiceMapping(
+ MockCryptoClientStream::CONFIRM_HANDSHAKE, alternative);
+ AddHangingNonAlternateProtocolSocketData();
+ CreateSession();
+
+ SendRequestAndExpectQuicResponse("hello!");
+}
+
TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
- params_.origin_to_force_quic_on =
- HostPortPair::FromString("mail.example.com:443");
+ params_.origins_to_force_quic_on.insert(
+ HostPortPair::FromString("mail.example.org:443"));
MockQuicData mock_quic_data1;
mock_quic_data1.AddRead(ASYNC, ERR_SOCKET_NOT_CONNECTED);
@@ -758,9 +833,11 @@ TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
mock_quic_data1.AddSocketDataToFactory(&socket_factory_);
mock_quic_data2.AddSocketDataToFactory(&socket_factory_);
+ params_.parse_alternative_services = false;
+ params_.enable_alternative_service_with_different_host = false;
CreateSession();
- EXPECT_EQ(0U, test_network_quality_estimator_->watcher_count());
+ EXPECT_EQ(0U, test_socket_performance_watcher_factory_.watcher_count());
for (size_t i = 0; i < 2; ++i) {
scoped_ptr<HttpNetworkTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
@@ -768,14 +845,14 @@ TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
int rv = trans->Start(&request_, callback.callback(), net_log_.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
- EXPECT_EQ(1 + i, test_network_quality_estimator_->watcher_count());
+ EXPECT_EQ(1 + i, test_socket_performance_watcher_factory_.watcher_count());
}
}
TEST_P(QuicNetworkTransactionTest, DoNotForceQuicForHttps) {
// Attempt to "force" quic on 443, which will not be honored.
- params_.origin_to_force_quic_on =
- HostPortPair::FromString("www.google.com:443");
+ params_.origins_to_force_quic_on.insert(
+ HostPortPair::FromString("www.google.com:443"));
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
@@ -787,10 +864,12 @@ TEST_P(QuicNetworkTransactionTest, DoNotForceQuicForHttps) {
SSLSocketDataProvider ssl(ASYNC, OK);
socket_factory_.AddSSLSocketDataProvider(&ssl);
+ params_.parse_alternative_services = false;
+ params_.enable_alternative_service_with_different_host = false;
CreateSession();
SendRequestAndExpectHttpResponse("hello world");
- EXPECT_EQ(0U, test_network_quality_estimator_->watcher_count());
+ EXPECT_EQ(0U, test_socket_performance_watcher_factory_.watcher_count());
}
TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceForQuic) {
@@ -820,7 +899,42 @@ TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceForQuic) {
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ CreateSession();
+
+ SendRequestAndExpectHttpResponse("hello world");
+ SendRequestAndExpectQuicResponse("hello!");
+}
+
+TEST_P(QuicNetworkTransactionTest,
+ UseAlternativeServiceWithProbabilityForQuic) {
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead(kQuicAlternativeServiceWithProbabilityHeader),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+ MockRead(ASYNC, OK)};
+
+ StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
+ 0);
+ socket_factory_.AddSocketDataProvider(&http_data);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/")));
+ mock_quic_data.AddRead(ConstructResponseHeadersPacket(
+ 1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructAckPacket(2, 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_);
+
+ AddHangingNonAlternateProtocolSocketData();
+ CreateSession();
SendRequestAndExpectHttpResponse("hello world");
SendRequestAndExpectQuicResponse("hello!");
@@ -855,12 +969,73 @@ TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceQuicSupportedVersion) {
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ CreateSession();
SendRequestAndExpectHttpResponse("hello world");
SendRequestAndExpectQuicResponse("hello!");
}
+TEST_P(QuicNetworkTransactionTest, GoAwayWithConnectionMigrationOnPortsOnly) {
+ MockQuicData mock_quic_data;
+ mock_quic_data.AddWrite(
+ ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "https", "/")));
+ mock_quic_data.AddRead(ConstructResponseHeadersPacket(
+ 1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
+ // Read a GoAway packet with
+ // QuicErrorCode: QUIC_ERROR_MIGRATING_PORT from the peer.
+ mock_quic_data.AddRead(
+ ConstructGoAwayPacket(2, QUIC_ERROR_MIGRATING_PORT,
+ "connection migration with port change only"));
+ mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
+ mock_quic_data.AddRead(
+ ConstructDataPacket(3, kClientDataStreamId1, false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructAckAndRstPacket(
+ 3, 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
+
+ mock_quic_data.AddSocketDataToFactory(&socket_factory_);
+
+ // The non-alternate protocol job needs to hang in order to guarantee that
+ // the alternate-protocol job will "win".
+ AddHangingNonAlternateProtocolSocketData();
+
+ // In order for a new QUIC session to be established via alternate-protocol
+ // without racing an HTTP connection, we need the host resolution to happen
+ // synchronously. Of course, even though QUIC *could* perform a 0-RTT
+ // connection to the the server, in this test we require confirmation
+ // before encrypting so the HTTP job will still start.
+ host_resolver_.set_synchronous_mode(true);
+ host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1",
+ "");
+ HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443));
+ AddressList address;
+ host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, CompletionCallback(),
+ nullptr, net_log_.bound());
+
+ CreateSession();
+ session_->quic_stream_factory()->set_require_confirmation(true);
+ AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
+
+ scoped_ptr<HttpNetworkTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
+ TestCompletionCallback callback;
+ int rv = trans->Start(&request_, callback.callback(), net_log_.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent(
+ QuicSession::HANDSHAKE_CONFIRMED);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ // Check whether this transaction is correctly marked as received a go-away
+ // because of migrating port.
+ NetErrorDetails details;
+ EXPECT_FALSE(details.quic_port_migration_detected);
+ trans->PopulateNetErrorDetails(&details);
+ EXPECT_TRUE(details.quic_port_migration_detected);
+}
+
TEST_P(QuicNetworkTransactionTest,
DoNotUseAlternativeServiceQuicUnsupportedVersion) {
std::string altsvc_header = base::StringPrintf(
@@ -878,7 +1053,7 @@ TEST_P(QuicNetworkTransactionTest,
socket_factory_.AddSocketDataProvider(&http_data);
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
- CreateSessionWithNextProtos();
+ CreateSession();
SendRequestAndExpectHttpResponse("hello world");
SendRequestAndExpectHttpResponse("hello world");
@@ -891,7 +1066,7 @@ TEST_P(QuicNetworkTransactionTest,
TEST_P(QuicNetworkTransactionTest, UseExistingAlternativeServiceForQuic) {
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead("Alt-Svc: quic=\"foo.example.com:443\", quic=\":444\"\r\n\r\n"),
+ MockRead("Alt-Svc: quic=\"foo.example.org:443\", quic=\":444\"\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK)};
@@ -904,7 +1079,7 @@ TEST_P(QuicNetworkTransactionTest, UseExistingAlternativeServiceForQuic) {
QuicStreamOffset request_header_offset = 0;
QuicStreamOffset response_header_offset = 0;
// First QUIC request data.
- // Open a session to foo.example.com:443 using the first entry of the
+ // 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(ConstructRequestHeadersPacket(
@@ -912,8 +1087,8 @@ TEST_P(QuicNetworkTransactionTest, UseExistingAlternativeServiceForQuic) {
GetRequestHeaders("GET", "https", "/"), &request_header_offset));
std::string alt_svc_list =
- "quic=\"mail.example.com:444\", quic=\"foo.example.com:443\", "
- "quic=\"bar.example.com:445\"";
+ "quic=\"mail.example.org:444\", quic=\"foo.example.org:443\", "
+ "quic=\"bar.example.org:445\"";
mock_quic_data.AddRead(ConstructResponseHeadersPacket(
1, kClientDataStreamId1, false, false,
GetResponseHeaders("200 OK", alt_svc_list), &response_header_offset));
@@ -939,7 +1114,7 @@ TEST_P(QuicNetworkTransactionTest, UseExistingAlternativeServiceForQuic) {
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ CreateSession();
SendRequestAndExpectHttpResponse("hello world");
@@ -953,7 +1128,7 @@ TEST_P(QuicNetworkTransactionTest, UseExistingAlternativeServiceForQuic) {
TEST_P(QuicNetworkTransactionTest, UseFirstExistingAlternativeServiceForQuic) {
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead("Alt-Svc: quic=\"foo.example.com:443\", quic=\":446\"\r\n\r\n"),
+ MockRead("Alt-Svc: quic=\"foo.example.org:443\", quic=\":446\"\r\n\r\n"),
MockRead("hello world"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK)};
@@ -972,14 +1147,14 @@ TEST_P(QuicNetworkTransactionTest, UseFirstExistingAlternativeServiceForQuic) {
MockQuicData mock_quic_data2;
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
// First QUIC request data.
- // Open a QUIC session to foo.example.com:443.
+ // Open a QUIC session to foo.example.org:443.
mock_quic_data.AddWrite(ConstructRequestHeadersPacket(
1, kClientDataStreamId1, true, true,
GetRequestHeaders("GET", "https", "/"), &request_header_offset));
std::string alt_svc_list =
- "quic=\"bar.example.com:444\", quic=\"frog.example.com:445\", "
- "quic=\"mail.example.com:446\"";
+ "quic=\"bar.example.org:444\", quic=\"frog.example.org:445\", "
+ "quic=\"mail.example.org:446\"";
// Response header from the server resets the alt_svc list for the origin.
mock_quic_data.AddRead(ConstructResponseHeadersPacket(
1, kClientDataStreamId1, false, false,
@@ -989,15 +1164,15 @@ TEST_P(QuicNetworkTransactionTest, UseFirstExistingAlternativeServiceForQuic) {
mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
// Second QUIC request data.
- // Existing QUIC session to foo.example.com is not viable from the updated
+ // Existing QUIC session to foo.example.org is not viable from the updated
// alt_svc. Unable to pool the existing QUIC session.
- // Open a new QUIC session to bar.example.com:443.
+ // Open a new QUIC session to bar.example.org:443.
mock_quic_data2.AddWrite(ConstructRequestHeadersPacket(
1, kClientDataStreamId1, true, true,
GetRequestHeaders("GET", "https", "/"), &maker));
alt_svc_list =
- "quic=\"foo.example.com:443\", quic=\"mail.example.com:446\", "
- "quic=\"bar.example.com:444\"";
+ "quic=\"foo.example.org:443\", quic=\"mail.example.org:446\", "
+ "quic=\"bar.example.org:444\"";
// Response header from the server resets the alt_svc list for the origin.
mock_quic_data2.AddRead(ConstructResponseHeadersPacket(
1, kClientDataStreamId1, false, false,
@@ -1009,7 +1184,7 @@ TEST_P(QuicNetworkTransactionTest, UseFirstExistingAlternativeServiceForQuic) {
mock_quic_data2.AddRead(ASYNC, 0); // EOF
// Third QUIC request data.
- // Connection pooling, using the first existing session to foo.example.com
+ // Connection pooling, using the first existing session to foo.example.org
mock_quic_data.AddWrite(ConstructRequestHeadersPacket(
3, kClientDataStreamId2, false, true,
GetRequestHeaders("GET", "https", "/"), &request_header_offset));
@@ -1029,7 +1204,7 @@ TEST_P(QuicNetworkTransactionTest, UseFirstExistingAlternativeServiceForQuic) {
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ CreateSession();
SendRequestAndExpectHttpResponse("hello world");
SendRequestAndExpectQuicResponseOnPort("hello from foo!", 443);
@@ -1043,14 +1218,13 @@ TEST_P(QuicNetworkTransactionTest, UseFirstExistingAlternativeServiceForQuic) {
// if this is also the first existing QUIC session.
TEST_P(QuicNetworkTransactionTest,
UseSharedExistingAlternativeServiceForQuicWithValidCert) {
- // Default cert is valid for the following origins:
- // mail.example.com, mail.example.org, and www.example.org.
+ // Default cert is valid for *.example.org
- // HTTP data for request to mail.example.com.
+ // HTTP data for request to www.example.org.
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Alt-Svc: quic=\":443\"\r\n\r\n"),
- MockRead("hello world from mail.example.com"),
+ MockRead("hello world from www.example.org"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK)};
@@ -1062,7 +1236,7 @@ TEST_P(QuicNetworkTransactionTest,
// HTTP data for request to mail.example.org.
MockRead http_reads2[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead("Alt-Svc: quic=\":444\", quic=\"mail.example.com:443\"\r\n\r\n"),
+ MockRead("Alt-Svc: quic=\":444\", quic=\"www.example.org:443\"\r\n\r\n"),
MockRead("hello world from mail.example.org"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK)};
@@ -1075,8 +1249,8 @@ TEST_P(QuicNetworkTransactionTest,
QuicStreamOffset request_header_offset = 0;
QuicStreamOffset response_header_offset = 0;
- QuicTestPacketMaker maker(GetParam(), 0, clock_, kDefaultServerHostName);
- maker.set_hostname("mail.example.org");
+ QuicTestPacketMaker maker(GetParam(), 0, clock_, "mail.example.org");
+ maker_.set_hostname("www.example.org");
MockQuicData mock_quic_data;
// First QUIC request data.
@@ -1090,7 +1264,6 @@ TEST_P(QuicNetworkTransactionTest,
mock_quic_data.AddRead(ConstructDataPacket(2, kClientDataStreamId1, false,
true, 0, "hello from mail QUIC!"));
mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
-
// Second QUIC request data.
mock_quic_data.AddWrite(ConstructRequestHeadersPacket(
3, kClientDataStreamId2, false, true,
@@ -1108,19 +1281,20 @@ TEST_P(QuicNetworkTransactionTest,
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ CreateSession();
// Send two HTTP requests, responses set up alt-svc lists for the origins.
- SendRequestAndExpectHttpResponse("hello world from mail.example.com");
+ request_.url = GURL("https://www.example.org/");
+ SendRequestAndExpectHttpResponse("hello world from www.example.org");
request_.url = GURL("https://mail.example.org/");
SendRequestAndExpectHttpResponse("hello world from mail.example.org");
- // Open a QUIC session to mail.example.com:443 when making request
- // to mail.example.com.
- request_.url = GURL("https://mail.example.com/");
+ // Open a QUIC session to mail.example.org:443 when making request
+ // to mail.example.org.
+ request_.url = GURL("https://www.example.org/");
SendRequestAndExpectQuicResponseOnPort("hello from mail QUIC!", 443);
- // Uses the existing QUIC session when making request to mail.example.org.
+ // Uses the existing QUIC session when making request to www.example.org.
request_.url = GURL("https://mail.example.org/");
SendRequestAndExpectQuicResponseOnPort("hello from mail QUIC!", 443);
}
@@ -1130,15 +1304,14 @@ TEST_P(QuicNetworkTransactionTest,
// if the cert is NOT valid, should ignore this QUIC session.
TEST_P(QuicNetworkTransactionTest,
DoNotUseSharedExistingAlternativeServiceForQuicWithInvalidCert) {
- // Default cert is only valid for the following origins:
- // mail.example.com, mail.example.org, and www.example.org.
- // NOT valid for docs.example.org.
+ // Default cert is valid *.example.org
+ // NOT valid for mail.example.com.
- // HTTP data for request to mail.example.com.
+ // HTTP data for request to mail.example.org.
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
MockRead("Alt-Svc: quic=\":443\"\r\n\r\n"),
- MockRead("hello world from mail.example.com"),
+ MockRead("hello world from mail.example.org"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK)};
@@ -1147,11 +1320,11 @@ TEST_P(QuicNetworkTransactionTest,
socket_factory_.AddSocketDataProvider(&http_data);
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
- // HTTP data for request to docs.example.org.
+ // HTTP data for request to mail.example.com.
MockRead http_reads2[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead("Alt-Svc: quic=\":444\", quic=\"mail.example.com:443\"\r\n\r\n"),
- MockRead("hello world from docs.example.org"),
+ MockRead("Alt-Svc: quic=\":444\", quic=\"mail.example.org:443\"\r\n\r\n"),
+ MockRead("hello world from mail.example.com"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK)};
@@ -1160,15 +1333,15 @@ TEST_P(QuicNetworkTransactionTest,
socket_factory_.AddSocketDataProvider(&http_data2);
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
- QuicTestPacketMaker maker(GetParam(), 0, clock_, kDefaultServerHostName);
- maker.set_hostname("docs.example.org");
+ QuicTestPacketMaker maker(GetParam(), 0, clock_, "mail.example.org");
+ maker.set_hostname("mail.example.com");
MockQuicData mock_quic_data;
MockQuicData mock_quic_data2;
// Adding a valid cert for *.example.org but not mail.example.com.
ProofVerifyDetailsChromium verify_details;
scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
+ ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"));
verify_details.cert_verify_result.verified_cert = cert;
verify_details.cert_verify_result.is_issued_by_known_root = true;
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
@@ -1204,20 +1377,20 @@ TEST_P(QuicNetworkTransactionTest,
mock_quic_data2.AddSocketDataToFactory(&socket_factory_);
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ CreateSession();
// Send HTTP requests, responses set up the alt-svc lists for the origins.
+ SendRequestAndExpectHttpResponse("hello world from mail.example.org");
+ request_.url = GURL("https://mail.example.com/");
SendRequestAndExpectHttpResponse("hello world from mail.example.com");
- request_.url = GURL("https://docs.example.org/");
- SendRequestAndExpectHttpResponse("hello world from docs.example.org");
- // Open a QUIC session to mail.example.com:443 when making request
- // to mail.example.com.
- request_.url = GURL("https://mail.example.com/");
+ // Open a QUIC session to mail.example.org:443 when making request
+ // to mail.example.org.
+ request_.url = GURL("https://mail.example.org/");
SendRequestAndExpectQuicResponseOnPort("hello from mail QUIC!", 443);
- // Open another new QUIC session to docs.example.org:444.
- request_.url = GURL("https://docs.example.org/");
+ // Open another new QUIC session to mail.example.com:444.
+ request_.url = GURL("https://mail.example.com/");
SendRequestAndExpectQuicResponseOnPort("hello from docs QUIC!", 444);
}
@@ -1249,7 +1422,7 @@ TEST_P(QuicNetworkTransactionTest, AlternativeServiceDifferentPort) {
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ CreateSession();
SendRequestAndExpectHttpResponse("hello world");
SendRequestAndExpectQuicResponseOnPort("hello!", 137);
@@ -1282,7 +1455,7 @@ TEST_P(QuicNetworkTransactionTest, ConfirmAlternativeService) {
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ CreateSession();
AlternativeService alternative_service(QUIC,
HostPortPair::FromURL(request_.url));
@@ -1300,10 +1473,10 @@ TEST_P(QuicNetworkTransactionTest, ConfirmAlternativeService) {
alternative_service));
}
-TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceProbabilityForQuic) {
+TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceForQuicForHttps) {
MockRead http_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead(kQuicAlternativeService50pctHeader), MockRead("hello world"),
+ MockRead("HTTP/1.1 200 OK\r\n"), MockRead(kQuicAlternativeServiceHeader),
+ MockRead("hello world"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK)};
@@ -1321,66 +1494,20 @@ TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceProbabilityForQuic) {
mock_quic_data.AddRead(
ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
- mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
- mock_quic_data.AddRead(ASYNC, 0); // EOF
+ mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
AddHangingNonAlternateProtocolSocketData();
- params_.alternative_service_probability_threshold = 0.25;
- CreateSessionWithNextProtos();
-
- SendRequestAndExpectHttpResponse("hello world");
- SendRequestAndExpectQuicResponse("hello!");
-}
-
-TEST_P(QuicNetworkTransactionTest,
- DontUseAlternativeServiceProbabilityForQuic) {
- MockRead http_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead(kQuicAlternativeService50pctHeader), MockRead("hello world"),
- MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
- MockRead(ASYNC, OK)};
-
- StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
- 0);
- socket_factory_.AddSocketDataProvider(&http_data);
- socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
- socket_factory_.AddSocketDataProvider(&http_data);
- socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
-
- params_.alternative_service_probability_threshold = 0.75;
- CreateSessionWithNextProtos();
-
- SendRequestAndExpectHttpResponse("hello world");
- SendRequestAndExpectHttpResponse("hello world");
-}
-
-TEST_P(QuicNetworkTransactionTest,
- DontUseAlternativeServiceWithBadProbabilityForQuic) {
- MockRead http_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead("Alt-Svc: quic=\":443\";p=2\r\n\r\n"), MockRead("hello world"),
- MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
- MockRead(ASYNC, OK)};
-
- StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
- 0);
- socket_factory_.AddSocketDataProvider(&http_data);
- socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
- socket_factory_.AddSocketDataProvider(&http_data);
- socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
-
- params_.alternative_service_probability_threshold = 0.75;
- CreateSessionWithNextProtos();
+ CreateSession();
- SendRequestAndExpectHttpResponse("hello world");
+ // TODO(rtenneti): Test QUIC over HTTPS, GetSSLInfo().
SendRequestAndExpectHttpResponse("hello world");
}
-TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceForQuicForHttps) {
+TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
MockRead http_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"), MockRead(kQuicAlternativeServiceHeader),
+ MockRead("HTTP/1.1 200 OK\r\n"), MockRead(kQuicAlternateProtocolHeader),
MockRead("hello world"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK)};
@@ -1399,20 +1526,27 @@ TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceForQuicForHttps) {
mock_quic_data.AddRead(
ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
mock_quic_data.AddWrite(ConstructAckPacket(2, 1));
- mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF
+ 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_);
+ // The non-alternate protocol job needs to hang in order to guarantee that
+ // the alternate-protocol job will "win".
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
- // TODO(rtenneti): Test QUIC over HTTPS, GetSSLInfo().
+ params_.parse_alternative_services = false;
+ params_.parse_alternative_services = false;
+ CreateSession();
+
SendRequestAndExpectHttpResponse("hello world");
+ SendRequestAndExpectQuicResponse("hello!");
}
-TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
+TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolWithProbabilityForQuic) {
MockRead http_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"), MockRead(kQuicAlternateProtocolHeader),
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead(kQuicAlternateProtocolWithProbabilityHeader),
MockRead("hello world"),
MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
MockRead(ASYNC, OK)};
@@ -1440,7 +1574,9 @@ TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
// the alternate-protocol job will "win".
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ params_.parse_alternative_services = false;
+ params_.parse_alternative_services = false;
+ CreateSession();
SendRequestAndExpectHttpResponse("hello world");
SendRequestAndExpectQuicResponse("hello!");
@@ -1477,7 +1613,8 @@ TEST_P(QuicNetworkTransactionTest, AlternateProtocolDifferentPort) {
// the alternate-protocol job will "win".
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ params_.parse_alternative_services = false;
+ CreateSession();
SendRequestAndExpectHttpResponse("hello world");
SendRequestAndExpectQuicResponseOnPort("hello!", 137);
@@ -1513,7 +1650,8 @@ TEST_P(QuicNetworkTransactionTest, ConfirmAlternateProtocol) {
// the alternate-protocol job will "win".
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ params_.parse_alternative_services = false;
+ CreateSession();
AlternativeService alternative_service(QUIC,
HostPortPair::FromURL(request_.url));
@@ -1531,87 +1669,8 @@ TEST_P(QuicNetworkTransactionTest, ConfirmAlternateProtocol) {
alternative_service));
}
-TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolProbabilityForQuic) {
- MockRead http_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead(kQuicAlternateProtocol50pctHeader), MockRead("hello world"),
- MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
- MockRead(ASYNC, OK)};
-
- StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
- 0);
- socket_factory_.AddSocketDataProvider(&http_data);
-
- MockQuicData mock_quic_data;
- mock_quic_data.AddWrite(
- ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
- GetRequestHeaders("GET", "https", "/")));
- mock_quic_data.AddRead(ConstructResponseHeadersPacket(
- 1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
- mock_quic_data.AddRead(
- ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructAckPacket(2, 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_);
-
- // The non-alternate protocol job needs to hang in order to guarantee that
- // the alternate-protocol job will "win".
- AddHangingNonAlternateProtocolSocketData();
-
- params_.alternative_service_probability_threshold = .25;
- CreateSessionWithNextProtos();
-
- SendRequestAndExpectHttpResponse("hello world");
- SendRequestAndExpectQuicResponse("hello!");
-}
-
-TEST_P(QuicNetworkTransactionTest, DontUseAlternateProtocolProbabilityForQuic) {
- MockRead http_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead(kQuicAlternateProtocol50pctHeader), MockRead("hello world"),
- MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
- MockRead(ASYNC, OK)};
-
- StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
- 0);
- socket_factory_.AddSocketDataProvider(&http_data);
- socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
- socket_factory_.AddSocketDataProvider(&http_data);
- socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
-
- params_.alternative_service_probability_threshold = .75;
- CreateSessionWithNextProtos();
-
- SendRequestAndExpectHttpResponse("hello world");
- SendRequestAndExpectHttpResponse("hello world");
-}
-
-TEST_P(QuicNetworkTransactionTest,
- DontUseAlternateProtocolWithBadProbabilityForQuic) {
- MockRead http_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead("Alternate-Protocol: 443:quic,p=2\r\n\r\n"),
- MockRead("hello world"),
- MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
- MockRead(ASYNC, OK)};
-
- StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), nullptr,
- 0);
- socket_factory_.AddSocketDataProvider(&http_data);
- socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
- socket_factory_.AddSocketDataProvider(&http_data);
- socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
-
- params_.alternative_service_probability_threshold = .75;
- CreateSessionWithNextProtos();
-
- SendRequestAndExpectHttpResponse("hello world");
- SendRequestAndExpectHttpResponse("hello world");
-}
-
TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) {
+ params_.parse_alternative_services = false;
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"), MockRead(kQuicAlternateProtocolHeader),
MockRead("hello world"),
@@ -1640,7 +1699,7 @@ TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) {
// the alternate-protocol job will "win".
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ CreateSession();
// TODO(rtenneti): Test QUIC over HTTPS, GetSSLInfo().
SendRequestAndExpectHttpResponse("hello world");
@@ -1650,8 +1709,7 @@ class QuicAltSvcCertificateVerificationTest
: public QuicNetworkTransactionTest {
public:
void Run(bool valid) {
- HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org",
- 443);
+ HostPortPair origin(valid ? "mail.example.org" : "mail.example.com", 443);
HostPortPair alternative("www.example.org", 443);
std::string url("https://");
url.append(origin.host());
@@ -1672,7 +1730,7 @@ class QuicAltSvcCertificateVerificationTest
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"));
+ ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
ASSERT_TRUE(cert.get());
bool common_name_fallback_used;
EXPECT_EQ(valid,
@@ -1693,11 +1751,11 @@ class QuicAltSvcCertificateVerificationTest
refused_data.set_connect_data(refused_connect);
socket_factory_.AddSocketDataProvider(&refused_data);
- CreateSessionWithNextProtos();
+ CreateSession();
AlternativeService alternative_service(QUIC, alternative);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
session_->http_server_properties()->SetAlternativeService(
- origin, alternative_service, 1.0, expiration);
+ origin, alternative_service, expiration);
scoped_ptr<HttpNetworkTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
TestCompletionCallback callback;
@@ -1730,12 +1788,13 @@ TEST_P(QuicAltSvcCertificateVerificationTest,
}
TEST_P(QuicNetworkTransactionTest, HungAlternateProtocol) {
+ params_.parse_alternative_services = false;
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::COLD_START);
MockWrite http_writes[] = {
MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"),
- MockWrite(SYNCHRONOUS, 1, "Host: mail.example.com\r\n"),
+ MockWrite(SYNCHRONOUS, 1, "Host: mail.example.org\r\n"),
MockWrite(SYNCHRONOUS, 2, "Connection: keep-alive\r\n\r\n")};
MockRead http_reads[] = {
@@ -1765,7 +1824,7 @@ TEST_P(QuicNetworkTransactionTest, HungAlternateProtocol) {
socket_factory.AddSocketDataProvider(&http_data2);
socket_factory.AddSSLSocketDataProvider(&ssl_data_);
- CreateSessionWithFactory(&socket_factory, true);
+ CreateSessionWithFactory(&socket_factory);
// Run the first request.
SendRequestAndExpectHttpResponse("hello world");
@@ -1801,7 +1860,7 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
// the alternate-protocol job will "win".
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
SendRequestAndExpectQuicResponse("hello!");
}
@@ -1824,14 +1883,14 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
// without racing an HTTP connection, we need the host resolution to happen
// synchronously.
host_resolver_.set_synchronous_mode(true);
- host_resolver_.rules()->AddIPLiteralRule("mail.example.com", "192.168.0.1",
+ host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1",
"");
- HostResolver::RequestInfo info(HostPortPair("mail.example.com", 443));
+ HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443));
AddressList address;
host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, CompletionCallback(),
nullptr, net_log_.bound());
- CreateSessionWithNextProtos();
+ CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
SendRequestAndExpectQuicResponse("hello!");
}
@@ -1841,8 +1900,8 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) {
// Since we are using a proxy, the QUIC job will not succeed.
MockWrite http_writes[] = {
- MockWrite(SYNCHRONOUS, 0, "GET http://mail.example.com/ HTTP/1.1\r\n"),
- MockWrite(SYNCHRONOUS, 1, "Host: mail.example.com\r\n"),
+ MockWrite(SYNCHRONOUS, 0, "GET http://mail.example.org/ HTTP/1.1\r\n"),
+ MockWrite(SYNCHRONOUS, 1, "Host: mail.example.org\r\n"),
MockWrite(SYNCHRONOUS, 2, "Proxy-Connection: keep-alive\r\n\r\n")};
MockRead http_reads[] = {
@@ -1858,15 +1917,15 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) {
// without racing an HTTP connection, we need the host resolution to happen
// synchronously.
host_resolver_.set_synchronous_mode(true);
- host_resolver_.rules()->AddIPLiteralRule("mail.example.com", "192.168.0.1",
+ host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1",
"");
- HostResolver::RequestInfo info(HostPortPair("mail.example.com", 443));
+ HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443));
AddressList address;
host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, CompletionCallback(),
nullptr, net_log_.bound());
- request_.url = GURL("http://mail.example.com/");
- CreateSessionWithNextProtos();
+ request_.url = GURL("http://mail.example.org/");
+ CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
SendRequestAndExpectHttpResponse("hello world");
}
@@ -1894,14 +1953,14 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
// connection to the the server, in this test we require confirmation
// before encrypting so the HTTP job will still start.
host_resolver_.set_synchronous_mode(true);
- host_resolver_.rules()->AddIPLiteralRule("mail.example.com", "192.168.0.1",
+ host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1",
"");
- HostResolver::RequestInfo info(HostPortPair("mail.example.com", 443));
+ HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443));
AddressList address;
host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, CompletionCallback(),
nullptr, net_log_.bound());
- CreateSessionWithNextProtos();
+ CreateSession();
session_->quic_stream_factory()->set_require_confirmation(true);
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
@@ -1940,14 +1999,14 @@ TEST_P(QuicNetworkTransactionTest,
// connection to the the server, in this test we require confirmation
// before encrypting so the HTTP job will still start.
host_resolver_.set_synchronous_mode(true);
- host_resolver_.rules()->AddIPLiteralRule("mail.example.com", "192.168.0.1",
+ host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1",
"");
- HostResolver::RequestInfo info(HostPortPair("mail.example.com", 443));
+ HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443));
AddressList address;
host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, CompletionCallback(),
nullptr, net_log_.bound());
- CreateSessionWithNextProtos();
+ CreateSession();
session_->quic_stream_factory()->set_require_confirmation(true);
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
@@ -1995,14 +2054,14 @@ TEST_P(QuicNetworkTransactionTest,
// connection to the the server, in this test we require confirmation
// before encrypting so the HTTP job will still start.
host_resolver_.set_synchronous_mode(true);
- host_resolver_.rules()->AddIPLiteralRule("mail.example.com", "192.168.0.1",
+ host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1",
"");
- HostResolver::RequestInfo info(HostPortPair("mail.example.com", 443));
+ HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443));
AddressList address;
host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, CompletionCallback(),
nullptr, net_log_.bound());
- CreateSessionWithNextProtos();
+ CreateSession();
session_->quic_stream_factory()->set_require_confirmation(true);
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
@@ -2045,7 +2104,7 @@ TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocol) {
socket_factory_.AddSocketDataProvider(&http_data);
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
- CreateSessionWithNextProtos();
+ CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
SendRequestAndExpectHttpResponse("hello from http");
ExpectBrokenAlternateProtocolMapping();
@@ -2071,7 +2130,7 @@ TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {
socket_factory_.AddSocketDataProvider(&http_data);
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
- CreateSessionWithNextProtos();
+ CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
SendRequestAndExpectHttpResponse("hello from http");
@@ -2098,7 +2157,7 @@ TEST_P(QuicNetworkTransactionTest, NoBrokenAlternateProtocolIfTcpFails) {
socket_factory_.AddSocketDataProvider(&http_data);
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
- CreateSessionWithNextProtos();
+ CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
scoped_ptr<HttpNetworkTransaction> trans(
@@ -2137,7 +2196,7 @@ TEST_P(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
socket_factory_.AddSocketDataProvider(&http_data);
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
- CreateSessionWithNextProtos();
+ CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
@@ -2168,7 +2227,7 @@ TEST_P(QuicNetworkTransactionTest, DISABLED_HangingZeroRttFallback) {
0);
socket_factory_.AddSocketDataProvider(&http_data);
- CreateSessionWithNextProtos();
+ CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
@@ -2193,7 +2252,7 @@ TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolOnConnectFailure) {
socket_factory_.AddSocketDataProvider(&http_data);
socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
- CreateSessionWithNextProtos();
+ CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
SendRequestAndExpectHttpResponse("hello from http");
@@ -2225,21 +2284,22 @@ TEST_P(QuicNetworkTransactionTest, ConnectionCloseDuringConnect) {
// without racing an HTTP connection, we need the host resolution to happen
// synchronously.
host_resolver_.set_synchronous_mode(true);
- host_resolver_.rules()->AddIPLiteralRule("mail.example.com", "192.168.0.1",
+ host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1",
"");
- HostResolver::RequestInfo info(HostPortPair("mail.example.com", 443));
+ HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443));
AddressList address;
host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, CompletionCallback(),
nullptr, net_log_.bound());
- CreateSessionWithNextProtos();
+ CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
SendRequestAndExpectHttpResponse("hello world");
}
TEST_P(QuicNetworkTransactionTest, SecureResourceOverSecureQuic) {
maker_.set_hostname("www.example.org");
- EXPECT_FALSE(rtt_observer_.rtt_notification_received());
+ EXPECT_FALSE(
+ test_socket_performance_watcher_factory_.rtt_notification_received());
MockQuicData mock_quic_data;
mock_quic_data.AddWrite(
ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
@@ -2254,15 +2314,16 @@ TEST_P(QuicNetworkTransactionTest, SecureResourceOverSecureQuic) {
request_.url = GURL("https://www.example.org:443");
AddHangingNonAlternateProtocolSocketData();
- CreateSessionWithNextProtos();
+ CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::CONFIRM_HANDSHAKE);
SendRequestAndExpectQuicResponse("hello!");
- EXPECT_TRUE(rtt_observer_.rtt_notification_received());
+ EXPECT_TRUE(
+ test_socket_performance_watcher_factory_.rtt_notification_received());
}
TEST_P(QuicNetworkTransactionTest, QuicUpload) {
- params_.origin_to_force_quic_on =
- HostPortPair::FromString("mail.example.com:443");
+ params_.origins_to_force_quic_on.insert(
+ HostPortPair::FromString("mail.example.org:443"));
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
MockWrite writes[] = {MockWrite(SYNCHRONOUS, ERR_FAILED, 1)};
@@ -2274,6 +2335,8 @@ TEST_P(QuicNetworkTransactionTest, QuicUpload) {
// the alternate-protocol job will "win".
AddHangingNonAlternateProtocolSocketData();
+ params_.parse_alternative_services = false;
+ params_.enable_alternative_service_with_different_host = false;
CreateSession();
request_.method = "POST";
ChunkedUploadDataStream upload_data(0);
diff --git a/chromium/net/quic/quic_one_block_arena.h b/chromium/net/quic/quic_one_block_arena.h
new file mode 100644
index 00000000000..37fc7307902
--- /dev/null
+++ b/chromium/net/quic/quic_one_block_arena.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.
+
+// An arena that consists of a single inlined block of |ArenaSize|. Useful to
+// avoid repeated calls to malloc/new and to improve memory locality. DCHECK's
+// 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_
+
+#include "net/quic/quic_arena_scoped_ptr.h"
+#include "net/quic/quic_flags.h"
+#include "net/quic/quic_utils.h"
+
+#define PREDICT_FALSE(x) x
+
+namespace net {
+
+template <uint32_t ArenaSize>
+class QuicOneBlockArena {
+ static const uint32_t kMaxAlign = 8;
+
+ public:
+ QuicOneBlockArena();
+
+ // Instantiates an object of type |T| with |args|. |args| are perfectly
+ // forwarded to |T|'s constructor. The returned pointer's lifetime is
+ // controlled by QuicArenaScopedPtr.
+ template <typename T, typename... Args>
+ QuicArenaScopedPtr<T> New(Args&&... args);
+
+ private:
+ // Returns the size of |T| aligned up to |kMaxAlign|.
+ template <typename T>
+ static inline uint32_t AlignedSize() {
+ return ((sizeof(T) + (kMaxAlign - 1)) / kMaxAlign) * kMaxAlign;
+ }
+
+ // Actual storage.
+ // Subtle/annoying: the value '8' must be coded explicitly into the alignment
+ // declaration for MSVC.
+ QUIC_ALIGNED(8) char storage_[ArenaSize];
+ // Current offset into the storage.
+ uint32_t offset_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicOneBlockArena);
+};
+
+template <uint32_t ArenaSize>
+QuicOneBlockArena<ArenaSize>::QuicOneBlockArena() : offset_(0) {}
+
+template <uint32_t ArenaSize>
+template <typename T, typename... Args>
+QuicArenaScopedPtr<T> QuicOneBlockArena<ArenaSize>::New(Args&&... args) {
+ DCHECK_LT(AlignedSize<T>(), ArenaSize)
+ << "Object is too large for the arena.";
+ 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_;
+ return QuicArenaScopedPtr<T>(new T(std::forward<Args>(args)...));
+ }
+
+ void* buf = &storage_[offset_];
+ new (buf) T(std::forward<Args>(args)...);
+ offset_ += AlignedSize<T>();
+ return QuicArenaScopedPtr<T>(buf,
+ QuicArenaScopedPtr<T>::ConstructFrom::kArena);
+}
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_ONE_BLOCK_ARENA_H_
diff --git a/chromium/net/quic/quic_one_block_arena_test.cc b/chromium/net/quic/quic_one_block_arena_test.cc
new file mode 100644
index 00000000000..39e7767c356
--- /dev/null
+++ b/chromium/net/quic/quic_one_block_arena_test.cc
@@ -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.
+
+#include "net/quic/quic_one_block_arena.h"
+
+#include "net/quic/interval_set.h"
+#include "net/quic/quic_flags.h"
+#include "net/quic/quic_utils.h"
+#include "net/test/gtest_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace {
+
+static const uint32_t kMaxAlign = 8;
+
+struct TestObject {
+ uint32_t value;
+};
+
+TEST(QuicOneBlockArenaTest, AllocateSuccess) {
+ QuicOneBlockArena<1024> arena;
+ QuicArenaScopedPtr<TestObject> ptr = arena.New<TestObject>();
+ EXPECT_TRUE(ptr.is_from_arena());
+}
+
+TEST(QuicOneBlockArenaTest, Exhaust) {
+ QuicOneBlockArena<1024> arena;
+ for (size_t i = 0; i < 1024 / kMaxAlign; ++i) {
+ QuicArenaScopedPtr<TestObject> ptr = arena.New<TestObject>();
+ EXPECT_TRUE(ptr.is_from_arena());
+ }
+ QuicArenaScopedPtr<TestObject> ptr;
+ EXPECT_DFATAL(ptr = arena.New<TestObject>(),
+ "Ran out of space in QuicOneBlockArena");
+ EXPECT_FALSE(ptr.is_from_arena());
+}
+
+TEST(QuicOneBlockArenaTest, NoOverlaps) {
+ QuicOneBlockArena<1024> arena;
+ std::vector<QuicArenaScopedPtr<TestObject>> objects;
+ IntervalSet<uintptr_t> used;
+ for (size_t i = 0; i < 1024 / kMaxAlign; ++i) {
+ QuicArenaScopedPtr<TestObject> ptr = arena.New<TestObject>();
+ EXPECT_TRUE(ptr.is_from_arena());
+
+ uintptr_t begin = reinterpret_cast<uintptr_t>(ptr.get());
+ uintptr_t end = begin + sizeof(TestObject);
+ EXPECT_FALSE(used.Contains(begin));
+ EXPECT_FALSE(used.Contains(end - 1));
+ used.Add(begin, end);
+ }
+}
+
+} // namespace
+} // namespace net
diff --git a/chromium/net/quic/quic_packet_creator.cc b/chromium/net/quic/quic_packet_creator.cc
index 35072e9de66..5147b09e672 100644
--- a/chromium/net/quic/quic_packet_creator.cc
+++ b/chromium/net/quic/quic_packet_creator.cc
@@ -11,7 +11,6 @@
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_data_writer.h"
-#include "net/quic/quic_fec_group.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_utils.h"
@@ -20,33 +19,11 @@ using std::make_pair;
using std::max;
using std::min;
using std::pair;
+using std::string;
using std::vector;
namespace net {
-namespace {
-
-// Default max packets in an FEC group.
-static const size_t kDefaultMaxPacketsPerFecGroup = 10;
-// Lowest max packets in an FEC group.
-static const size_t kLowestMaxPacketsPerFecGroup = 2;
-
-// We want to put some space between a protected packet and the FEC packet to
-// avoid losing them both within the same loss episode. On the other hand, we
-// expect to be able to recover from any loss in about an RTT. We resolve this
-// tradeoff by sending an FEC packet atmost half an RTT, or equivalently, half
-// the max number of in-flight packets, the first protected packet. Since we
-// don't want to delay an FEC packet past half an RTT, we set the max FEC group
-// size to be half the current congestion window.
-const float kMaxPacketsInFlightMultiplierForFecGroupSize = 0.5;
-const float kRttMultiplierForFecTimeout = 0.5;
-
-// Minimum timeout for FEC alarm, set to half the minimum Tail Loss Probe
-// timeout of 10ms.
-const int64_t kMinFecTimeoutMs = 5u;
-
-} // namespace
-
// 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.
@@ -87,40 +64,29 @@ QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id,
DelegateInterface* delegate)
: delegate_(delegate),
debug_delegate_(nullptr),
- connection_id_(connection_id),
- encryption_level_(ENCRYPTION_NONE),
- has_ack_(false),
- has_stop_waiting_(false),
framer_(framer),
random_bool_source_(new QuicRandomBoolSource(random_generator)),
- current_path_(kDefaultPathId),
buffer_allocator_(buffer_allocator),
- packet_number_(0),
- should_fec_protect_next_packet_(false),
- fec_protect_(false),
send_version_in_packet_(framer->perspective() == Perspective::IS_CLIENT),
+ send_path_id_in_packet_(false),
+ next_packet_number_length_(PACKET_1BYTE_PACKET_NUMBER),
max_packet_length_(0),
- max_packets_per_fec_group_(kDefaultMaxPacketsPerFecGroup),
connection_id_length_(PACKET_8BYTE_CONNECTION_ID),
- next_packet_number_length_(PACKET_1BYTE_PACKET_NUMBER),
- packet_number_length_(next_packet_number_length_),
packet_size_(0),
- needs_padding_(false),
- fec_send_policy_(FEC_ANY_TRIGGER),
- fec_timeout_(QuicTime::Delta::Zero()),
- rtt_multiplier_for_fec_timeout_(kRttMultiplierForFecTimeout) {
+ connection_id_(connection_id),
+ packet_(kDefaultPathId,
+ 0,
+ next_packet_number_length_,
+ nullptr,
+ 0,
+ 0,
+ false,
+ false) {
SetMaxPacketLength(kDefaultMaxPacketSize);
}
-QuicPacketCreator::~QuicPacketCreator() {}
-
-void QuicPacketCreator::OnBuiltFecProtectedPayload(
- const QuicPacketHeader& header,
- StringPiece payload) {
- if (fec_group_.get() != nullptr) {
- DCHECK_NE(0u, header.fec_group);
- fec_group_->Update(encryption_level_, header, payload);
- }
+QuicPacketCreator::~QuicPacketCreator() {
+ QuicUtils::DeleteFrames(&packet_.retransmittable_frames);
}
void QuicPacketCreator::SetEncrypter(EncryptionLevel level,
@@ -130,8 +96,8 @@ void QuicPacketCreator::SetEncrypter(EncryptionLevel level,
}
bool QuicPacketCreator::CanSetMaxPacketLength() const {
- // |max_packet_length_| should not be changed mid-packet or mid-FEC group.
- return fec_group_.get() == nullptr && queued_frames_.empty();
+ // |max_packet_length_| should not be changed mid-packet.
+ return queued_frames_.empty();
}
void QuicPacketCreator::SetMaxPacketLength(QuicByteCount length) {
@@ -147,81 +113,14 @@ void QuicPacketCreator::SetMaxPacketLength(QuicByteCount length) {
max_plaintext_size_ = framer_->GetMaxPlaintextSize(max_packet_length_);
}
-void QuicPacketCreator::set_max_packets_per_fec_group(
- size_t max_packets_per_fec_group) {
- max_packets_per_fec_group_ =
- max(kLowestMaxPacketsPerFecGroup, max_packets_per_fec_group);
- DCHECK_LT(0u, max_packets_per_fec_group_);
-}
-
-bool QuicPacketCreator::ShouldSendFec(bool force_close) const {
- return !HasPendingFrames() && fec_group_.get() != nullptr &&
- fec_group_->NumReceivedPackets() > 0 &&
- (force_close ||
- fec_group_->NumReceivedPackets() >= max_packets_per_fec_group_);
-}
-
-void QuicPacketCreator::ResetFecGroup() {
- if (HasPendingFrames()) {
- LOG_IF(DFATAL, packet_size_ != 0)
- << "Cannot reset FEC group with pending frames.";
- return;
- }
- fec_group_.reset(nullptr);
-}
-
-bool QuicPacketCreator::IsFecGroupOpen() const {
- return fec_group_.get() != nullptr;
-}
-
-void QuicPacketCreator::StartFecProtectingPackets() {
- if (max_packets_per_fec_group_ == 0) {
- QUIC_BUG << "Cannot start FEC protection when FEC is not enabled.";
- return;
- }
- // TODO(jri): This currently requires that the generator flush out any
- // pending frames when FEC protection is turned on. If current packet can be
- // converted to an FEC protected packet, do it. This will require the
- // generator to check if the resulting expansion still allows the incoming
- // frame to be added to the packet.
- if (HasPendingFrames()) {
- QUIC_BUG << "Cannot start FEC protection with pending frames.";
- return;
- }
- DCHECK(!fec_protect_);
- fec_protect_ = true;
-}
-
-void QuicPacketCreator::StopFecProtectingPackets() {
- if (fec_group_.get() != nullptr) {
- QUIC_BUG << "Cannot stop FEC protection with open FEC group.";
- return;
- }
- DCHECK(fec_protect_);
- fec_protect_ = false;
-}
-
-InFecGroup QuicPacketCreator::MaybeUpdateLengthsAndStartFec() {
- if (fec_group_.get() != nullptr) {
- // Don't update any lengths when an FEC group is open, to ensure same
- // packet header size in all packets within a group.
- return IN_FEC_GROUP;
- }
+void QuicPacketCreator::MaybeUpdatePacketNumberLength() {
if (!queued_frames_.empty()) {
// Don't change creator state if there are frames queued.
- return NOT_IN_FEC_GROUP;
+ return;
}
- // Update packet number length only on packet and FEC group boundaries.
- packet_number_length_ = next_packet_number_length_;
-
- if (!fec_protect_) {
- return NOT_IN_FEC_GROUP;
- }
- // Start a new FEC group since protection is on. Set the fec group number to
- // the packet number of the next packet.
- fec_group_.reset(new QuicFecGroup(packet_number_ + 1));
- return IN_FEC_GROUP;
+ // Update packet number length only on packet boundary.
+ packet_.packet_number_length = next_packet_number_length_;
}
// Stops serializing version of the protocol in packets sent after this call.
@@ -239,12 +138,9 @@ void QuicPacketCreator::StopSendingVersion() {
void QuicPacketCreator::UpdatePacketNumberLength(
QuicPacketNumber least_packet_awaited_by_peer,
QuicPacketCount max_packets_in_flight) {
- DCHECK_LE(least_packet_awaited_by_peer, packet_number_ + 1);
- // Since the packet creator will not change packet number length mid FEC
- // group, include the size of an FEC group to be safe.
- const QuicPacketNumber current_delta = max_packets_per_fec_group_ +
- packet_number_ + 1 -
- least_packet_awaited_by_peer;
+ 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);
next_packet_number_length_ =
QuicFramer::GetMinSequenceNumberLength(delta * 4);
@@ -256,15 +152,10 @@ bool QuicPacketCreator::ConsumeData(QuicStreamId id,
QuicStreamOffset offset,
bool fin,
bool needs_padding,
- QuicFrame* frame,
- FecProtection fec_protection) {
+ QuicFrame* frame) {
if (!HasRoomForStreamFrame(id, offset)) {
return false;
}
- if (fec_protection == MUST_FEC_PROTECT) {
- should_fec_protect_next_packet_ = true;
- MaybeStartFecProtection();
- }
CreateStreamFrame(id, iov, iov_offset, offset, fin, frame);
if (!AddFrame(*frame, /*save_retransmittable_frames=*/true)) {
// Fails if we try to write unencrypted stream data.
@@ -272,39 +163,27 @@ bool QuicPacketCreator::ConsumeData(QuicStreamId id,
return false;
}
if (needs_padding) {
- needs_padding_ = true;
- }
- if (fec_protection == MUST_FEC_PROTECT &&
- iov_offset + frame->stream_frame->frame_length == iov.total_length) {
- // Turn off FEC protection when we're done writing protected data.
- DVLOG(1) << "Turning FEC protection OFF";
- should_fec_protect_next_packet_ = false;
+ packet_.needs_padding = true;
}
return true;
}
bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id,
- QuicStreamOffset offset) const {
- // TODO(jri): This is a simple safe decision for now, but make
- // is_in_fec_group a parameter. Same as with all public methods in
- // QuicPacketCreator.
- return BytesFree() >
- QuicFramer::GetMinStreamFrameSize(
- id, offset, true, fec_protect_ ? IN_FEC_GROUP : NOT_IN_FEC_GROUP);
+ QuicStreamOffset offset) {
+ return BytesFree() > QuicFramer::GetMinStreamFrameSize(id, offset, true);
}
// static
size_t QuicPacketCreator::StreamFramePacketOverhead(
QuicConnectionIdLength connection_id_length,
bool include_version,
+ bool include_path_id,
QuicPacketNumberLength packet_number_length,
- QuicStreamOffset offset,
- InFecGroup is_in_fec_group) {
+ QuicStreamOffset offset) {
return GetPacketHeaderSize(connection_id_length, include_version,
- /*include_path_id=*/false, packet_number_length,
- is_in_fec_group) +
+ include_path_id, packet_number_length) +
// Assumes this is a stream with a single lone packet.
- QuicFramer::GetMinStreamFrameSize(1u, offset, true, is_in_fec_group);
+ QuicFramer::GetMinStreamFrameSize(1u, offset, true);
}
size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
@@ -315,18 +194,18 @@ size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
QuicFrame* frame) {
DCHECK_GT(max_packet_length_,
StreamFramePacketOverhead(connection_id_length_, kIncludeVersion,
- PACKET_6BYTE_PACKET_NUMBER, offset,
- IN_FEC_GROUP));
+ kIncludePathId,
+ PACKET_6BYTE_PACKET_NUMBER, offset));
- InFecGroup is_in_fec_group = MaybeUpdateLengthsAndStartFec();
+ MaybeUpdatePacketNumberLength();
LOG_IF(DFATAL, !HasRoomForStreamFrame(id, offset))
<< "No room for Stream frame, BytesFree: " << BytesFree()
<< " MinStreamFrameSize: "
- << QuicFramer::GetMinStreamFrameSize(id, offset, true, is_in_fec_group);
+ << QuicFramer::GetMinStreamFrameSize(id, offset, true);
if (iov_offset == iov.total_length) {
- LOG_IF(DFATAL, !fin) << "Creating a stream frame with no data or fin.";
+ QUIC_BUG_IF(!fin) << "Creating a stream frame with no data or fin.";
// Create a new packet for the fin, if necessary.
*frame = QuicFrame(new QuicStreamFrame(id, true, offset, StringPiece()));
return 0;
@@ -334,7 +213,7 @@ size_t 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, is_in_fec_group);
+ id, offset, /* last_frame_in_packet= */ true);
size_t bytes_consumed = min<size_t>(BytesFree() - min_frame_size, data_size);
bool set_fin = fin && bytes_consumed == data_size; // Last frame.
@@ -396,59 +275,45 @@ void QuicPacketCreator::CopyToBuffer(QuicIOVector iov,
src = static_cast<char*>(iov.iov[iovnum].iov_base);
copy_len = min(length, iov.iov[iovnum].iov_len);
}
- LOG_IF(DFATAL, length > 0) << "Failed to copy entire length to buffer.";
+ QUIC_BUG_IF(length > 0) << "Failed to copy entire length to buffer.";
}
-SerializedPacket QuicPacketCreator::ReserializeAllFrames(
- const RetransmittableFrames& frames,
- EncryptionLevel original_encryption_level,
- QuicPacketNumberLength original_length,
+void QuicPacketCreator::ReserializeAllFrames(
+ const PendingRetransmission& retransmission,
char* buffer,
size_t buffer_len) {
- DCHECK(fec_group_.get() == nullptr);
- const QuicPacketNumberLength saved_length = packet_number_length_;
+ DCHECK(queued_frames_.empty());
+ DCHECK(!packet_.needs_padding);
+ QUIC_BUG_IF(retransmission.retransmittable_frames.empty())
+ << "Attempt to serialize empty packet";
+ const QuicPacketNumberLength saved_length = packet_.packet_number_length;
const QuicPacketNumberLength saved_next_length = next_packet_number_length_;
- const bool saved_should_fec_protect = fec_protect_;
- const bool needs_padding = needs_padding_;
- const EncryptionLevel default_encryption_level = encryption_level_;
-
- // Temporarily set the packet number length, stop FEC protection,
- // and change the encryption level.
- packet_number_length_ = original_length;
- next_packet_number_length_ = original_length;
- fec_protect_ = false;
- needs_padding_ = frames.needs_padding();
+ const EncryptionLevel default_encryption_level = packet_.encryption_level;
+
+ // Temporarily set the packet number length and change the encryption level.
+ packet_.packet_number_length = retransmission.packet_number_length;
+ next_packet_number_length_ = retransmission.packet_number_length;
+ packet_.needs_padding = retransmission.needs_padding;
// Only preserve the original encryption level if it's a handshake packet or
// if we haven't gone forward secure.
- if (frames.HasCryptoHandshake() ||
- encryption_level_ != ENCRYPTION_FORWARD_SECURE) {
- encryption_level_ = original_encryption_level;
+ if (retransmission.has_crypto_handshake ||
+ packet_.encryption_level != ENCRYPTION_FORWARD_SECURE) {
+ packet_.encryption_level = retransmission.encryption_level;
}
- // Serialize the packet and restore the FEC and packet number length state.
- SerializedPacket serialized_packet =
- SerializeAllFrames(frames.frames(), buffer, buffer_len);
- packet_number_length_ = saved_length;
- next_packet_number_length_ = saved_next_length;
- fec_protect_ = saved_should_fec_protect;
- needs_padding_ = needs_padding;
- encryption_level_ = default_encryption_level;
-
- return serialized_packet;
-}
-
-SerializedPacket QuicPacketCreator::SerializeAllFrames(const QuicFrames& frames,
- char* buffer,
- size_t buffer_len) {
- LOG_IF(DFATAL, !queued_frames_.empty()) << "Frames already queued.";
- LOG_IF(DFATAL, frames.empty()) << "Attempt to serialize empty packet";
- for (const QuicFrame& frame : frames) {
+ // Serialize the packet and restore packet number length state.
+ for (const QuicFrame& frame : retransmission.retransmittable_frames) {
bool success = AddFrame(frame, false);
DCHECK(success);
}
- SerializedPacket packet = SerializePacket(buffer, buffer_len);
- DCHECK(packet.retransmittable_frames == nullptr);
- return packet;
+ SerializePacket(buffer, buffer_len);
+ packet_.original_packet_number = retransmission.packet_number;
+ packet_.transmission_type = retransmission.transmission_type;
+ OnSerializedPacket();
+ // Restore old values.
+ packet_.packet_number_length = saved_length;
+ next_packet_number_length_ = saved_next_length;
+ packet_.encryption_level = default_encryption_level;
}
void QuicPacketCreator::Flush() {
@@ -459,26 +324,22 @@ void QuicPacketCreator::Flush() {
// TODO(rtenneti): Change the default 64 alignas value (used the default
// value from CACHELINE_SIZE).
ALIGNAS(64) char seralized_packet_buffer[kMaxPacketSize];
- SerializedPacket serialized_packet =
- SerializePacket(seralized_packet_buffer, kMaxPacketSize);
- OnSerializedPacket(&serialized_packet);
+ SerializePacket(seralized_packet_buffer, kMaxPacketSize);
+ OnSerializedPacket();
}
-void QuicPacketCreator::OnSerializedPacket(SerializedPacket* packet) {
- if (packet->packet == nullptr) {
- QUIC_BUG << "Failed to SerializePacket. fec_policy:" << fec_send_policy()
- << " should_fec_protect_:" << should_fec_protect_next_packet_;
- delegate_->CloseConnection(QUIC_FAILED_TO_SERIALIZE_PACKET, false);
+void QuicPacketCreator::OnSerializedPacket() {
+ if (packet_.encrypted_buffer == nullptr) {
+ const string error_details = "Failed to SerializePacket.";
+ QUIC_BUG << error_details;
+ delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
+ error_details,
+ ConnectionCloseSource::FROM_SELF);
return;
}
- // There may be AckListeners interested in this packet.
- packet->listeners.swap(ack_listeners_);
- DCHECK(ack_listeners_.empty());
- delegate_->OnSerializedPacket(packet);
- has_ack_ = false;
- has_stop_waiting_ = false;
- MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/false,
- /*is_fec_timeout=*/false);
+
+ 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()) {
@@ -486,20 +347,28 @@ void QuicPacketCreator::OnSerializedPacket(SerializedPacket* packet) {
}
}
+void QuicPacketCreator::ClearPacket() {
+ packet_.has_ack = false;
+ packet_.has_stop_waiting = false;
+ packet_.has_crypto_handshake = NOT_HANDSHAKE;
+ packet_.needs_padding = false;
+ packet_.original_packet_number = 0;
+ packet_.transmission_type = NOT_RETRANSMISSION;
+ packet_.encrypted_buffer = nullptr;
+ packet_.encrypted_length = 0;
+ DCHECK(packet_.retransmittable_frames.empty());
+ packet_.listeners.clear();
+}
+
bool QuicPacketCreator::HasPendingFrames() const {
return !queued_frames_.empty();
}
bool QuicPacketCreator::HasPendingRetransmittableFrames() const {
- return queued_retransmittable_frames_.get() != nullptr &&
- !queued_retransmittable_frames_->frames().empty();
+ return !packet_.retransmittable_frames.empty();
}
size_t QuicPacketCreator::ExpansionOnNewFrame() const {
- // If packet is FEC protected, there's no expansion.
- if (fec_protect_) {
- return 0;
- }
// If the last frame in the packet is a stream frame, then it will expand to
// include the stream_length field when a new frame is added.
bool has_trailing_stream_frame =
@@ -507,23 +376,21 @@ size_t QuicPacketCreator::ExpansionOnNewFrame() const {
return has_trailing_stream_frame ? kQuicStreamPayloadLengthSize : 0;
}
-size_t QuicPacketCreator::BytesFree() const {
+size_t QuicPacketCreator::BytesFree() {
DCHECK_GE(max_plaintext_size_, PacketSize());
return max_plaintext_size_ -
min(max_plaintext_size_, PacketSize() + ExpansionOnNewFrame());
}
-size_t QuicPacketCreator::PacketSize() const {
+size_t QuicPacketCreator::PacketSize() {
if (!queued_frames_.empty()) {
return packet_size_;
}
- if (fec_group_.get() == nullptr) {
- // Update packet number length on packet and FEC boundary.
- packet_number_length_ = next_packet_number_length_;
- }
+ // Update packet number length on packet boundary.
+ packet_.packet_number_length = next_packet_number_length_;
packet_size_ = GetPacketHeaderSize(
- connection_id_length_, send_version_in_packet_, /*include_path_id=*/false,
- packet_number_length_, fec_protect_ ? IN_FEC_GROUP : NOT_IN_FEC_GROUP);
+ connection_id_length_, send_version_in_packet_, send_path_id_in_packet_,
+ packet_.packet_number_length);
return packet_size_;
}
@@ -533,7 +400,7 @@ bool QuicPacketCreator::AddSavedFrame(const QuicFrame& frame) {
bool QuicPacketCreator::AddPaddedSavedFrame(const QuicFrame& frame) {
if (AddFrame(frame, /*save_retransmittable_frames=*/true)) {
- needs_padding_ = true;
+ packet_.needs_padding = true;
return true;
}
return false;
@@ -542,124 +409,55 @@ bool QuicPacketCreator::AddPaddedSavedFrame(const QuicFrame& frame) {
void QuicPacketCreator::AddAckListener(QuicAckListenerInterface* listener,
QuicPacketLength length) {
DCHECK(!queued_frames_.empty());
- ack_listeners_.push_back(AckListenerWrapper(listener, length));
+ packet_.listeners.emplace_back(listener, length);
}
-SerializedPacket QuicPacketCreator::SerializePacket(
- char* encrypted_buffer,
- size_t encrypted_buffer_len) {
+void QuicPacketCreator::SerializePacket(char* encrypted_buffer,
+ size_t encrypted_buffer_len) {
DCHECK_LT(0u, encrypted_buffer_len);
- LOG_IF(DFATAL, queued_frames_.empty()) << "Attempt to serialize empty packet";
- if (fec_group_.get() != nullptr) {
- DCHECK_GE(packet_number_ + 1, fec_group_->FecGroupNumber());
- }
+ QUIC_BUG_IF(queued_frames_.empty()) << "Attempt to serialize empty packet";
QuicPacketHeader header;
// FillPacketHeader increments packet_number_.
- FillPacketHeader(fec_group_ != nullptr ? fec_group_->FecGroupNumber() : 0,
- false, &header);
+ FillPacketHeader(&header);
MaybeAddPadding();
DCHECK_GE(max_plaintext_size_, packet_size_);
- // ACK Frames will be truncated due to length only if they're the only frame
- // in the packet, and if packet_size_ was set to max_plaintext_size_. If
- // truncation due to length occurred, then GetSerializedFrameLength will have
- // returned all bytes free.
- bool possibly_truncated_by_length = packet_size_ == max_plaintext_size_ &&
- queued_frames_.size() == 1 &&
- queued_frames_.back().type == ACK_FRAME;
// Use the packet_size_ instead of the buffer size to ensure smaller
// packet sizes are properly used.
size_t length = framer_->BuildDataPacket(header, queued_frames_,
encrypted_buffer, packet_size_);
if (length == 0) {
QUIC_BUG << "Failed to serialize " << queued_frames_.size() << " frames.";
- return NoPacket();
+ return;
}
- // TODO(ianswett) Consider replacing QuicPacket with something else, since
- // it's only used to provide convenience methods to FEC and encryption.
- QuicPacket packet(encrypted_buffer, length,
- /* owns_buffer */ false,
- header.public_header.connection_id_length,
- header.public_header.version_flag,
- header.public_header.packet_number_length);
- OnBuiltFecProtectedPayload(header, packet.FecProtectedData());
-
+ // ACK Frames will be truncated due to length only if they're the only frame
+ // in the packet, and if packet_size_ was set to max_plaintext_size_. If
+ // truncation due to length occurred, then GetSerializedFrameLength will have
+ // returned all bytes free.
+ bool possibly_truncated_by_length = packet_size_ == max_plaintext_size_ &&
+ queued_frames_.size() == 1 &&
+ queued_frames_.back().type == ACK_FRAME;
// Because of possible truncation, we can't be confident that our
// packet size calculation worked correctly.
if (!possibly_truncated_by_length) {
DCHECK_EQ(packet_size_, length);
}
- // Immediately encrypt the packet, to ensure we don't encrypt the same
- // packet number multiple times.
- size_t encrypted_length =
- framer_->EncryptPayload(encryption_level_, packet_number_, packet,
- encrypted_buffer, encrypted_buffer_len);
+ const size_t encrypted_length = framer_->EncryptInPlace(
+ packet_.encryption_level, packet_.path_id, packet_.packet_number,
+ GetStartOfEncryptedData(header), length, encrypted_buffer_len,
+ encrypted_buffer);
if (encrypted_length == 0) {
- QUIC_BUG << "Failed to encrypt packet number " << packet_number_;
- return NoPacket();
- }
-
- // Update |needs_padding_| flag of |queued_retransmittable_frames_| here, and
- // not in AddFrame, because when the first padded frame is added to the queue,
- // it might not be retransmittable, and hence the flag would end up being not
- // set.
- if (queued_retransmittable_frames_.get() != nullptr) {
- queued_retransmittable_frames_->set_needs_padding(needs_padding_);
+ QUIC_BUG << "Failed to encrypt packet number " << packet_.packet_number;
+ return;
}
packet_size_ = 0;
queued_frames_.clear();
- needs_padding_ = false;
- return SerializedPacket(current_path_, header.packet_number,
- header.public_header.packet_number_length,
- encrypted_buffer, encrypted_length,
- /* owns_buffer*/ false,
- QuicFramer::GetPacketEntropyHash(header),
- queued_retransmittable_frames_.release(), has_ack_,
- has_stop_waiting_, encryption_level_);
-}
-
-SerializedPacket QuicPacketCreator::SerializeFec(char* buffer,
- size_t buffer_len) {
- DCHECK_LT(0u, buffer_len);
- if (fec_group_.get() == nullptr || fec_group_->NumReceivedPackets() <= 0) {
- QUIC_BUG << "SerializeFEC called but no group or zero packets in group.";
- // TODO(jri): Make this a public method of framer?
- return NoPacket();
- }
- if (FLAGS_quic_no_unencrypted_fec && encryption_level_ == ENCRYPTION_NONE) {
- LOG(DFATAL) << "SerializeFEC must be called with encryption.";
- delegate_->CloseConnection(QUIC_UNENCRYPTED_FEC_DATA, false);
- return NoPacket();
- }
- DCHECK_EQ(0u, queued_frames_.size());
- QuicPacketHeader header;
- FillPacketHeader(fec_group_->FecGroupNumber(), true, &header);
- scoped_ptr<QuicPacket> packet(
- framer_->BuildFecPacket(header, fec_group_->PayloadParity()));
- fec_group_.reset(nullptr);
- packet_size_ = 0;
- LOG_IF(DFATAL, packet == nullptr)
- << "Failed to serialize fec packet for group:"
- << fec_group_->FecGroupNumber();
- DCHECK_GE(max_packet_length_, packet->length());
- // Immediately encrypt the packet, to ensure we don't encrypt the same packet
- // packet number multiple times.
- size_t encrypted_length = framer_->EncryptPayload(
- encryption_level_, packet_number_, *packet, buffer, buffer_len);
- if (encrypted_length == 0) {
- QUIC_BUG << "Failed to encrypt packet number " << packet_number_;
- return NoPacket();
- }
- SerializedPacket serialized(current_path_, header.packet_number,
- header.public_header.packet_number_length, buffer,
- encrypted_length, /* owns_buffer */ false,
- QuicFramer::GetPacketEntropyHash(header), nullptr,
- false, false, encryption_level_);
- serialized.is_fec_packet = true;
- return serialized;
+ packet_.entropy_hash = QuicFramer::GetPacketEntropyHash(header);
+ packet_.encrypted_buffer = encrypted_buffer;
+ packet_.encrypted_length = encrypted_length;
}
QuicEncryptedPacket* QuicPacketCreator::SerializeVersionNegotiationPacket(
@@ -672,24 +470,25 @@ QuicEncryptedPacket* QuicPacketCreator::SerializeVersionNegotiationPacket(
return encrypted;
}
+// TODO(jri): Make this a public method of framer?
SerializedPacket QuicPacketCreator::NoPacket() {
return SerializedPacket(kInvalidPathId, 0, PACKET_1BYTE_PACKET_NUMBER,
- nullptr, 0, nullptr, false, false);
+ nullptr, 0, 0, false, false);
}
-void QuicPacketCreator::FillPacketHeader(QuicFecGroupNumber fec_group,
- bool fec_flag,
- QuicPacketHeader* header) {
+void QuicPacketCreator::FillPacketHeader(QuicPacketHeader* header) {
header->public_header.connection_id = connection_id_;
header->public_header.connection_id_length = connection_id_length_;
+ header->public_header.multipath_flag = send_path_id_in_packet_;
header->public_header.reset_flag = false;
header->public_header.version_flag = send_version_in_packet_;
- header->fec_flag = fec_flag;
- header->packet_number = ++packet_number_;
- header->public_header.packet_number_length = packet_number_length_;
+ header->fec_flag = false;
+ 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();
- header->is_in_fec_group = fec_group == 0 ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
- header->fec_group = fec_group;
+ header->is_in_fec_group = NOT_IN_FEC_GROUP;
+ header->fec_group = 0;
}
bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) {
@@ -709,16 +508,19 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
DVLOG(1) << "Adding frame: " << frame;
if (FLAGS_quic_never_write_unencrypted_data && frame.type == STREAM_FRAME &&
frame.stream_frame->stream_id != kCryptoStreamId &&
- encryption_level_ == ENCRYPTION_NONE) {
- QUIC_BUG << "Cannot send stream data without encryption.";
- delegate_->CloseConnection(QUIC_UNENCRYPTED_STREAM_DATA, false);
+ packet_.encryption_level == ENCRYPTION_NONE) {
+ const string error_details = "Cannot send stream data without encryption.";
+ QUIC_BUG << error_details;
+ delegate_->OnUnrecoverableError(
+ QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA, error_details,
+ ConnectionCloseSource::FROM_SELF);
return false;
}
- InFecGroup is_in_fec_group = MaybeUpdateLengthsAndStartFec();
+ MaybeUpdatePacketNumberLength();
size_t frame_len = framer_->GetSerializedFrameLength(
- frame, BytesFree(), queued_frames_.empty(), true, is_in_fec_group,
- packet_number_length_);
+ frame, BytesFree(), queued_frames_.empty(), true,
+ packet_.packet_number_length);
if (frame_len == 0) {
// Current open packet is full.
Flush();
@@ -728,19 +530,24 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
packet_size_ += ExpansionOnNewFrame() + frame_len;
if (save_retransmittable_frames && ShouldRetransmit(frame)) {
- if (queued_retransmittable_frames_.get() == nullptr) {
- queued_retransmittable_frames_.reset(new RetransmittableFrames());
+ if (packet_.retransmittable_frames.empty()) {
+ packet_.retransmittable_frames.reserve(2);
+ }
+ packet_.retransmittable_frames.push_back(frame);
+ queued_frames_.push_back(frame);
+ if (frame.type == STREAM_FRAME &&
+ frame.stream_frame->stream_id == kCryptoStreamId) {
+ packet_.has_crypto_handshake = IS_HANDSHAKE;
}
- queued_frames_.push_back(queued_retransmittable_frames_->AddFrame(frame));
} else {
queued_frames_.push_back(frame);
}
if (frame.type == ACK_FRAME) {
- has_ack_ = true;
+ packet_.has_ack = true;
}
if (frame.type == STOP_WAITING_FRAME) {
- has_stop_waiting_ = true;
+ packet_.has_stop_waiting = true;
}
if (debug_delegate_ != nullptr) {
debug_delegate_->OnFrameAddedToPacket(frame);
@@ -750,7 +557,7 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
}
void QuicPacketCreator::MaybeAddPadding() {
- if (!needs_padding_) {
+ if (!packet_.needs_padding) {
return;
}
@@ -763,70 +570,11 @@ void QuicPacketCreator::MaybeAddPadding() {
DCHECK(success);
}
-void QuicPacketCreator::MaybeStartFecProtection() {
- if (max_packets_per_fec_group_ == 0 || fec_protect_) {
- // Do not start FEC protection when FEC protection is not enabled or FEC
- // protection is already on.
- return;
- }
- DVLOG(1) << "Turning FEC protection ON";
- // Flush current open packet.
- Flush();
-
- StartFecProtectingPackets();
- DCHECK(fec_protect_);
-}
-
-void QuicPacketCreator::MaybeSendFecPacketAndCloseGroup(bool force_send_fec,
- bool is_fec_timeout) {
- if (ShouldSendFec(force_send_fec)) {
- if ((FLAGS_quic_no_unencrypted_fec &&
- encryption_level_ == ENCRYPTION_NONE) ||
- (fec_send_policy_ == FEC_ALARM_TRIGGER && !is_fec_timeout)) {
- ResetFecGroup();
- delegate_->OnResetFecGroup();
- } else {
- // TODO(zhongyi): Change the default 64 alignas value (used the default
- // value from CACHELINE_SIZE).
- ALIGNAS(64) char seralized_fec_buffer[kMaxPacketSize];
- SerializedPacket serialized_fec =
- SerializeFec(seralized_fec_buffer, kMaxPacketSize);
- OnSerializedPacket(&serialized_fec);
- }
- }
-
- if (!should_fec_protect_next_packet_ && fec_protect_ && !IsFecGroupOpen()) {
- StopFecProtectingPackets();
- }
-}
-
-QuicTime::Delta QuicPacketCreator::GetFecTimeout(
- QuicPacketNumber packet_number) {
- // Do not set up FEC alarm for |packet_number| it is not the first packet in
- // the current group.
- if (fec_group_.get() != nullptr &&
- (packet_number == fec_group_->FecGroupNumber())) {
- return QuicTime::Delta::Max(
- fec_timeout_, QuicTime::Delta::FromMilliseconds(kMinFecTimeoutMs));
- }
- return QuicTime::Delta::Infinite();
-}
-
-void QuicPacketCreator::OnCongestionWindowChange(
- QuicPacketCount max_packets_in_flight) {
- set_max_packets_per_fec_group(static_cast<size_t>(
- kMaxPacketsInFlightMultiplierForFecGroupSize * max_packets_in_flight));
-}
-
-void QuicPacketCreator::OnRttChange(QuicTime::Delta rtt) {
- fec_timeout_ = rtt.Multiply(rtt_multiplier_for_fec_timeout_);
-}
-
void QuicPacketCreator::SetCurrentPath(
QuicPathId path_id,
QuicPacketNumber least_packet_awaited_by_peer,
QuicPacketCount max_packets_in_flight) {
- if (current_path_ == path_id) {
+ if (packet_.path_id == path_id) {
return;
}
@@ -834,17 +582,16 @@ void QuicPacketCreator::SetCurrentPath(
QUIC_BUG << "Unable to change paths when a packet is under construction.";
return;
}
-
- // Send FEC packet and close FEC group.
- MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true,
- /*is_fec_timeout=*/false);
// Save current packet number and load switching path's packet number.
- multipath_packet_number_[current_path_] = packet_number_;
- hash_map<QuicPathId, QuicPacketNumber>::iterator it =
+ multipath_packet_number_[packet_.path_id] = packet_.packet_number;
+ std::unordered_map<QuicPathId, QuicPacketNumber>::iterator it =
multipath_packet_number_.find(path_id);
// If path_id is not in the map, it's a new path. Set packet_number to 0.
- packet_number_ = it == multipath_packet_number_.end() ? 0 : it->second;
- current_path_ = path_id;
+ packet_.packet_number = it == multipath_packet_number_.end() ? 0 : it->second;
+ packet_.path_id = path_id;
+ DCHECK(packet_.path_id != kInvalidPathId);
+ // Send path in packet if current path is not the default path.
+ send_path_id_in_packet_ = packet_.path_id != kDefaultPathId ? true : false;
// Switching path needs to update packet number length.
UpdatePacketNumberLength(least_packet_awaited_by_peer, max_packets_in_flight);
}
diff --git a/chromium/net/quic/quic_packet_creator.h b/chromium/net/quic/quic_packet_creator.h
index ded7678a16d..f74244f2829 100644
--- a/chromium/net/quic/quic_packet_creator.h
+++ b/chromium/net/quic/quic_packet_creator.h
@@ -3,10 +3,9 @@
// found in the LICENSE file.
//
// Accumulates frames for the next packet until more frames no longer fit or
-// it's time to create a packet from them. Also provides packet creation of
-// FEC packets based on previously created packets. If multipath enabled, only
-// creates packets on one path at the same time. Currently, next packet number
-// is tracked per-path.
+// it's time to create a packet from them. If multipath enabled, only creates
+// 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_
@@ -14,18 +13,16 @@
#include <stddef.h>
#include <string>
+#include <unordered_map>
#include <utility>
#include <vector>
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
-#include "net/quic/quic_fec_group.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_protocol.h"
-using base::hash_map;
-
namespace net {
namespace test {
class QuicPacketCreatorPeer;
@@ -45,9 +42,11 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
// and |packet.retransmittable_frames|. If it does so, they must be set
// to nullptr.
virtual void OnSerializedPacket(SerializedPacket* serialized_packet) = 0;
- virtual void CloseConnection(QuicErrorCode error, bool from_peer) = 0;
- // Called when current FEC group is reset (closed).
- virtual void OnResetFecGroup() = 0;
+
+ // Called when an unrecoverable error is encountered.
+ virtual void OnUnrecoverableError(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) = 0;
};
// Interface which gets callbacks from the QuicPacketCreator at interesting
@@ -70,27 +69,6 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
~QuicPacketCreator();
- // Checks if it's time to send an FEC packet. |force_close| forces this to
- // return true if an FEC group is open.
- bool ShouldSendFec(bool force_close) const;
-
- // If ShouldSendFec returns true, serializes currently constructed FEC packet
- // and calls the delegate on the packet. Resets current FEC group if FEC
- // protection policy is FEC_ALARM_TRIGGER but |is_fec_timeout| is false.
- // Also tries to turn off FEC protection if should_fec_protect_next_packet is
- // false.
- void MaybeSendFecPacketAndCloseGroup(bool force_send_fec,
- bool is_fec_timeout);
-
- // Returns true if an FEC packet is under construction.
- bool IsFecGroupOpen() const;
-
- // Called after sending |packet_number| to determine whether an FEC alarm
- // should be set for sending out an FEC packet. Returns a positive and finite
- // timeout if an FEC alarm should be set, and infinite if no alarm should be
- // set.
- QuicTime::Delta GetFecTimeout(QuicPacketNumber packet_number);
-
// Makes the framer not serialize the protocol version in sent packets.
void StopSendingVersion();
@@ -105,47 +83,32 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
static size_t StreamFramePacketOverhead(
QuicConnectionIdLength connection_id_length,
bool include_version,
+ bool include_path_id,
QuicPacketNumberLength packet_number_length,
- QuicStreamOffset offset,
- InFecGroup is_in_fec_group);
+ QuicStreamOffset offset);
// Returns false and flushes all pending frames if current open packet is
// full.
// If current packet is not full, converts a raw payload into a stream frame
// that fits into the open packet and adds it to the packet.
// The payload begins at |iov_offset| into the |iov|.
- // Also tries to start FEC protection depends on |fec_protection|.
bool ConsumeData(QuicStreamId id,
QuicIOVector iov,
size_t iov_offset,
QuicStreamOffset offset,
bool fin,
bool needs_padding,
- QuicFrame* frame,
- FecProtection fec_protection);
+ QuicFrame* frame);
// Returns true if current open packet can accommodate more stream frames of
// stream |id| at |offset|, false otherwise.
- bool HasRoomForStreamFrame(QuicStreamId id, QuicStreamOffset offset) const;
-
- // Serializes all frames into a single packet. All frames must fit into a
- // single packet. Also, sets the entropy hash of the serialized packet to a
- // random bool and returns that value as a member of SerializedPacket.
- // Never returns a RetransmittableFrames in SerializedPacket.
- SerializedPacket SerializeAllFrames(const QuicFrames& frames,
- char* buffer,
- size_t buffer_len);
+ bool HasRoomForStreamFrame(QuicStreamId id, QuicStreamOffset offset);
// Re-serializes frames with the original packet's packet number length.
// Used for retransmitting packets to ensure they aren't too long.
- // Caller must ensure that any open FEC group is closed before calling this
- // method.
- SerializedPacket ReserializeAllFrames(
- const RetransmittableFrames& frames,
- EncryptionLevel original_encryption_level,
- QuicPacketNumberLength original_length,
- char* buffer,
- size_t buffer_len);
+ void ReserializeAllFrames(const PendingRetransmission& retransmission,
+ char* buffer,
+ size_t buffer_len);
// Serializes all added frames into a single packet and invokes the delegate_
// to further process the SerializedPacket.
@@ -161,20 +124,19 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
// frames in the packet. Since stream frames are slightly smaller when they
// are the last frame in a packet, this method will return a different
// value than max_packet_size - PacketSize(), in this case.
- size_t BytesFree() const;
+ size_t BytesFree();
// Returns the number of bytes that the packet will expand by if a new frame
// is added to the packet. If the last frame was a stream frame, it will
// expand slightly when a new frame is added, and this method returns the
- // amount of expected expansion. If the packet is in an FEC group, no
- // expansion happens and this method always returns zero.
+ // amount of expected expansion.
size_t ExpansionOnNewFrame() const;
// Returns the number of bytes in the current packet, including the header,
// if serialized with the current frames. Adding a frame to the packet
// may change the serialized length of existing frames, as per the comment
// in BytesFree.
- size_t PacketSize() const;
+ size_t PacketSize();
// Tries to add |frame| to the packet creator's list of frames to be
// serialized. If the frame does not fit into the current packet, flushes the
@@ -185,8 +147,7 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
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.
+ // std::listener with |length| as the number of acked bytes.
void AddAckListener(QuicAckListenerInterface* listener,
QuicPacketLength length);
@@ -200,20 +161,14 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
// Returns a dummy packet that is valid but contains no useful information.
static SerializedPacket NoPacket();
- // Called when the congestion window has changed.
- void OnCongestionWindowChange(QuicPacketCount max_packets_in_flight);
-
- // Called when the RTT may have changed.
- void OnRttChange(QuicTime::Delta rtt);
-
// Sets the encryption level that will be applied to new packets.
void set_encryption_level(EncryptionLevel level) {
- encryption_level_ = level;
+ packet_.encryption_level = level;
}
// packet number of the last created packet, or 0 if no packets have been
// created.
- QuicPacketNumber packet_number() const { return packet_number_; }
+ QuicPacketNumber packet_number() const { return packet_.packet_number; }
QuicConnectionIdLength connection_id_length() const {
return connection_id_length_;
@@ -225,9 +180,9 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
QuicByteCount max_packet_length() const { return max_packet_length_; }
- bool has_ack() const { return has_ack_; }
+ bool has_ack() const { return packet_.has_ack; }
- bool has_stop_waiting() const { return has_stop_waiting_; }
+ bool has_stop_waiting() const { return packet_.has_stop_waiting; }
// Sets the encrypter to use for the encryption level and updates the max
// plaintext size.
@@ -242,35 +197,12 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
// Sets the path on which subsequent packets will be created. It is the
// caller's responsibility to guarantee no packet is under construction before
- // calling this function. If |path_id| is different from current_path_, the
- // FEC packet (if exists) will be sent and next_packet_number_length_ is
- // recalculated.
+ // calling this function. If |path_id| is different from current_path_,
+ // next_packet_number_length_ is recalculated.
void SetCurrentPath(QuicPathId path_id,
QuicPacketNumber least_packet_awaited_by_peer,
QuicPacketCount max_packets_in_flight);
- // Returns current max number of packets covered by an FEC group.
- size_t max_packets_per_fec_group() const {
- return max_packets_per_fec_group_;
- }
-
- // Sets creator's max number of packets covered by an FEC group.
- // Note: While there are no constraints on |max_packets_per_fec_group|,
- // this setter enforces a min value of kLowestMaxPacketsPerFecGroup.
- // To turn off FEC protection, use StopFecProtectingPackets().
- void set_max_packets_per_fec_group(size_t max_packets_per_fec_group);
-
- FecSendPolicy fec_send_policy() { return fec_send_policy_; }
-
- void set_fec_send_policy(FecSendPolicy fec_send_policy) {
- fec_send_policy_ = fec_send_policy;
- }
-
- void set_rtt_multiplier_for_fec_timeout(
- float rtt_multiplier_for_fec_timeout) {
- rtt_multiplier_for_fec_timeout_ = rtt_multiplier_for_fec_timeout;
- }
-
void set_debug_delegate(DebugDelegate* debug_delegate) {
debug_delegate_ = debug_delegate;
}
@@ -301,18 +233,10 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
size_t length,
char* buffer);
- // Updates lengths and also starts an FEC group if FEC protection is on and
- // there is not already an FEC group open.
- InFecGroup MaybeUpdateLengthsAndStartFec();
-
- // Called when a data packet is constructed that is part of an FEC group.
- // |payload| is the non-encrypted FEC protected payload of the packet.
- void OnBuiltFecProtectedPayload(const QuicPacketHeader& header,
- base::StringPiece payload);
+ // Updates packet number length on packet boundary.
+ void MaybeUpdatePacketNumberLength();
- void FillPacketHeader(QuicFecGroupNumber fec_group,
- bool fec_flag,
- QuicPacketHeader* header);
+ void FillPacketHeader(QuicPacketHeader* header);
// Adds a |frame| if there is space and returns false and flushes all pending
// frames if there isn't room. If |save_retransmittable_frames| is true,
@@ -325,109 +249,56 @@ class NET_EXPORT_PRIVATE QuicPacketCreator {
void MaybeAddPadding();
// Serializes all frames which have been added and adds any which should be
- // retransmitted to queued_retransmittable_frames_ if it's not nullptr. All
- // frames must fit into a single packet. Sets the entropy hash of the
- // serialized packet to a random bool and returns that value as a member of
- // SerializedPacket. Also, sets |serialized_frames| in the SerializedPacket to
- // the corresponding RetransmittableFrames if any frames are to be
- // retransmitted.
+ // 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.
// Fails if |buffer_len| isn't long enough for the encrypted packet.
- SerializedPacket SerializePacket(char* encrypted_buffer, size_t buffer_len);
+ void SerializePacket(char* encrypted_buffer, size_t buffer_len);
// Called after a new SerialiedPacket is created to call the delegate's
- // OnSerializedPacket, reset state, and potentially flush FEC groups.
- void OnSerializedPacket(SerializedPacket* packet);
-
- // Turn on FEC protection for subsequent packets. If no FEC group is currently
- // open, this method flushes current open packet and then turns FEC on.
- void MaybeStartFecProtection();
-
- // Turn on FEC protection for subsequently created packets. FEC should be
- // enabled first (max_packets_per_fec_group should be non-zero) for FEC
- // protection to start.
- void StartFecProtectingPackets();
-
- // Turn off FEC protection for subsequently created packets. If the creator
- // has any open FEC group, call will fail. It is the caller's responsibility
- // to flush out FEC packets in generation, and to verify with ShouldSendFec()
- // that there is no open FEC group.
- void StopFecProtectingPackets();
-
- // Resets (closes) the FEC group. This method should only be called on a
- // packet boundary.
- void ResetFecGroup();
-
- // Packetize FEC data. All frames must fit into a single packet. Also, sets
- // the entropy hash of the serialized packet to a random bool and returns
- // that value as a member of SerializedPacket.
- // Fails if |buffer_len| isn't long enough for the encrypted packet.
- SerializedPacket SerializeFec(char* buffer, size_t buffer_len);
+ // OnSerializedPacket and reset state.
+ void OnSerializedPacket();
- // Does not own these delegates.
+ // Clears all fields of packet_ that should be cleared between serializations.
+ void ClearPacket();
+
+ // Does not own these delegates or the framer.
DelegateInterface* delegate_;
DebugDelegate* debug_delegate_;
-
- QuicConnectionId connection_id_;
- EncryptionLevel encryption_level_;
- // True if an ack is queued in queued_frames_.
- bool has_ack_;
- // True if a stop waiting frame is queued in queued_frames_.
- bool has_stop_waiting_;
QuicFramer* framer_;
+
scoped_ptr<QuicRandomBoolSource> random_bool_source_;
- // Map mapping path_id to last sent packet number on the path.
- hash_map<QuicPathId, QuicPacketNumber> multipath_packet_number_;
- // The path which current constructed packet will be sent on.
- QuicPathId current_path_;
QuicBufferAllocator* const buffer_allocator_;
- QuicPacketNumber packet_number_;
- // True when creator is requested to turn on FEC protection. False otherwise.
- // There is a time difference between should_fec_protect_next_packet is
- // true/false and FEC is actually turned on/off (e.g., The creator may have an
- // open FEC group even if this variable is false).
- bool should_fec_protect_next_packet_;
- // If true, any created packets will be FEC protected.
- // TODO(fayang): Combine should_fec_protect_next_packet and fec_protect_ to
- // one variable.
- bool fec_protect_;
- scoped_ptr<QuicFecGroup> fec_group_;
- // Controls whether protocol version should be included while serializing the
- // packet.
+
+ // Controls whether version should be included while serializing the packet.
bool send_version_in_packet_;
+ // Controls whether path id should be included while serializing the packet.
+ bool send_path_id_in_packet_;
+ // Staging variable to hold next packet number length. When sequence
+ // number length is to be changed, this variable holds the new length until
+ // a packet boundary, when the creator's packet_number_length_ can be changed
+ // to this new value.
+ QuicPacketNumberLength next_packet_number_length_;
// Maximum length including headers and encryption (UDP payload length.)
QuicByteCount max_packet_length_;
- // 0 indicates FEC is disabled.
- size_t max_packets_per_fec_group_;
+ size_t max_plaintext_size_;
// Length of connection_id to send over the wire.
QuicConnectionIdLength connection_id_length_;
- // Staging variable to hold next packet number length. When sequence
- // number length is to be changed, this variable holds the new length until
- // a packet or FEC group boundary, when the creator's packet_number_length_
- // can be changed to this new value.
- QuicPacketNumberLength next_packet_number_length_;
- // packet number length for the current packet and for the current FEC group
- // when FEC is enabled. Mutable so PacketSize() can adjust it when the packet
- // is empty.
- mutable QuicPacketNumberLength packet_number_length_;
- // packet_size_ is mutable because it's just a cache of the current size.
- // packet_size should never be read directly, use PacketSize() instead.
- mutable size_t packet_size_;
- mutable size_t max_plaintext_size_;
+
+ // Frames to be added to the next SerializedPacket
QuicFrames queued_frames_;
- scoped_ptr<RetransmittableFrames> queued_retransmittable_frames_;
- // If true, the packet will be padded up to |max_packet_length_|.
- bool needs_padding_;
- // Stores ack std::listeners that should be attached to the next packet.
- std::list<AckListenerWrapper> ack_listeners_;
-
- // FEC policy that specifies when to send FEC packet.
- FecSendPolicy fec_send_policy_;
- // Timeout used for FEC alarm. Can be set to zero initially or if the SRTT has
- // not yet been set.
- QuicTime::Delta fec_timeout_;
- // The multiplication factor for FEC timeout based on RTT.
- // TODO(rtenneti): Delete this code after the 0.25 RTT FEC experiment.
- float rtt_multiplier_for_fec_timeout_;
+
+ // packet_size should never be read directly, use PacketSize() instead.
+ // TODO(ianswett): Move packet_size_ into SerializedPacket once
+ // QuicEncryptedPacket has been flattened into SerializedPacket.
+ size_t packet_size_;
+ QuicConnectionId connection_id_;
+
+ // Packet used to invoke OnSerializedPacket.
+ SerializedPacket packet_;
+
+ // Map mapping path_id to last sent packet number on the path.
+ std::unordered_map<QuicPathId, QuicPacketNumber> multipath_packet_number_;
DISALLOW_COPY_AND_ASSIGN(QuicPacketCreator);
};
diff --git a/chromium/net/quic/quic_packet_creator_test.cc b/chromium/net/quic/quic_packet_creator_test.cc
index 2a1c4ea6152..fc649ba9598 100644
--- a/chromium/net/quic/quic_packet_creator_test.cc
+++ b/chromium/net/quic/quic_packet_creator_test.cc
@@ -82,8 +82,10 @@ class MockDelegate : public QuicPacketCreator::DelegateInterface {
~MockDelegate() override {}
MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet));
- MOCK_METHOD0(OnResetFecGroup, void());
- MOCK_METHOD2(CloseConnection, void(QuicErrorCode, bool));
+ MOCK_METHOD3(OnUnrecoverableError,
+ void(QuicErrorCode,
+ const string&,
+ ConnectionCloseSource source));
private:
DISALLOW_COPY_AND_ASSIGN(MockDelegate);
@@ -95,19 +97,24 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> {
if (serialized_packet == nullptr) {
return;
}
-
- delete serialized_packet->retransmittable_frames;
- delete serialized_packet->packet;
+ QuicUtils::ClearSerializedPacket(serialized_packet);
}
void SaveSerializedPacket(SerializedPacket* serialized_packet) {
if (serialized_packet == nullptr) {
return;
}
-
+ delete[] serialized_packet_.encrypted_buffer;
serialized_packet_ = *serialized_packet;
- serialized_packet_.packet = serialized_packet->packet->Clone();
- delete serialized_packet->packet;
+ serialized_packet_.encrypted_buffer =
+ QuicUtils::CopyBuffer(*serialized_packet);
+ serialized_packet->retransmittable_frames.clear();
+ }
+
+ void DeleteSerializedPacket() {
+ delete[] serialized_packet_.encrypted_buffer;
+ serialized_packet_.encrypted_buffer = nullptr;
+ ClearSerializedPacket(&serialized_packet_);
}
protected:
@@ -136,21 +143,25 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> {
server_framer_.set_visitor(&framer_visitor_);
// TODO(ianswett): Fix this test so it uses a non-null encrypter.
FLAGS_quic_never_write_unencrypted_data = false;
- FLAGS_quic_no_unencrypted_fec = false;
}
- ~QuicPacketCreatorTest() override {}
+ ~QuicPacketCreatorTest() override {
+ delete[] serialized_packet_.encrypted_buffer;
+ ClearSerializedPacket(&serialized_packet_);
+ }
SerializedPacket SerializeAllFrames(const QuicFrames& frames) {
- SerializedPacket packet =
- creator_.SerializeAllFrames(frames, buffer_, kMaxPacketSize);
+ SerializedPacket packet = QuicPacketCreatorPeer::SerializeAllFrames(
+ &creator_, frames, buffer_, kMaxPacketSize);
EXPECT_EQ(QuicPacketCreatorPeer::GetEncryptionLevel(&creator_),
packet.encryption_level);
return packet;
}
- void ProcessPacket(QuicEncryptedPacket* encrypted) {
- server_framer_.ProcessPacket(*encrypted);
+ void ProcessPacket(const SerializedPacket& packet) {
+ QuicEncryptedPacket encrypted_packet(packet.encrypted_buffer,
+ packet.encrypted_length);
+ server_framer_.ProcessPacket(encrypted_packet);
}
void CheckStreamFrame(const QuicFrame& frame,
@@ -169,11 +180,10 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> {
// Returns the number of bytes consumed by the header of packet, including
// the version.
- size_t GetPacketHeaderOverhead(InFecGroup is_in_fec_group) {
+ size_t GetPacketHeaderOverhead() {
return GetPacketHeaderSize(
creator_.connection_id_length(), kIncludeVersion, !kIncludePathId,
- QuicPacketCreatorPeer::NextPacketNumberLength(&creator_),
- is_in_fec_group);
+ QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
}
// Returns the number of bytes of overhead that will be added to a packet
@@ -185,15 +195,27 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> {
// Returns the number of bytes consumed by the non-data fields of a stream
// frame, assuming it is the last frame in the packet
- size_t GetStreamFrameOverhead(InFecGroup is_in_fec_group) {
+ size_t GetStreamFrameOverhead() {
return QuicFramer::GetMinStreamFrameSize(kClientDataStreamId1, kOffset,
- true, is_in_fec_group);
+ true);
}
QuicIOVector MakeIOVector(StringPiece s) {
return ::net::MakeIOVector(s, &iov_);
}
+ PendingRetransmission CreateRetransmission(
+ const QuicFrames& retransmittable_frames,
+ bool has_crypto_handshake,
+ bool needs_padding,
+ EncryptionLevel encryption_level,
+ QuicPacketNumberLength packet_number_length) {
+ return PendingRetransmission(1u, 1u, NOT_RETRANSMISSION,
+ retransmittable_frames, has_crypto_handshake,
+ needs_padding, encryption_level,
+ packet_number_length);
+ }
+
static const QuicStreamOffset kOffset = 1u;
char buffer_[kMaxPacketSize];
@@ -247,67 +269,10 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) {
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
}
- ProcessPacket(serialized.packet);
- delete serialized.packet;
+ ProcessPacket(serialized);
}
}
-TEST_P(QuicPacketCreatorTest, SerializeWithFEC) {
- // Send FEC packet every 6 packets.
- creator_.set_max_packets_per_fec_group(6);
- // Should return false since we do not have enough packets in the FEC group to
- // trigger an FEC packet.
- ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false));
- // Turn on FEC protection.
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
- // Serialize the packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.Flush();
-
- {
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket());
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
- EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnFecProtectedPayload(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
- }
- ProcessPacket(serialized_packet_.packet);
- ClearSerializedPacket(&serialized_packet_);
-
- // Should return false since we do not have enough packets in the FEC group to
- // trigger an FEC packet.
- ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false));
- // Should return true since there are packets in the FEC group.
- ASSERT_TRUE(creator_.ShouldSendFec(/*force_close=*/true));
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true,
- /*is_fec_timeout=*/false);
- ASSERT_EQ(2u, serialized_packet_.packet_number);
- {
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket());
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
- EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnFecData(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
- }
- ProcessPacket(serialized_packet_.packet);
- ClearSerializedPacket(&serialized_packet_);
-}
-
TEST_P(QuicPacketCreatorTest, SerializeChangingSequenceNumberLength) {
frames_.push_back(QuicFrame(new QuicAckFrame(MakeAckFrame(0u))));
creator_.AddSavedFrame(frames_[0]);
@@ -332,8 +297,8 @@ TEST_P(QuicPacketCreatorTest, SerializeChangingSequenceNumberLength) {
EXPECT_CALL(framer_visitor_, OnAckFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
}
- ProcessPacket(serialized_packet_.packet);
- ClearSerializedPacket(&serialized_packet_);
+ ProcessPacket(serialized_packet_);
+ DeleteSerializedPacket();
creator_.AddSavedFrame(frames_[0]);
creator_.Flush();
@@ -352,8 +317,8 @@ TEST_P(QuicPacketCreatorTest, SerializeChangingSequenceNumberLength) {
EXPECT_CALL(framer_visitor_, OnAckFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
}
- ProcessPacket(serialized_packet_.packet);
- ClearSerializedPacket(&serialized_packet_);
+ ProcessPacket(serialized_packet_);
+ DeleteSerializedPacket();
}
TEST_P(QuicPacketCreatorTest, ChangeSequenceNumberLengthMidPacket) {
@@ -382,7 +347,7 @@ TEST_P(QuicPacketCreatorTest, ChangeSequenceNumberLengthMidPacket) {
.WillRepeatedly(
Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
creator_.Flush();
- ASSERT_TRUE(serialized_packet_.packet);
+ ASSERT_TRUE(serialized_packet_.encrypted_buffer);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
serialized_packet_.packet_number_length);
@@ -400,10 +365,10 @@ TEST_P(QuicPacketCreatorTest, ChangeSequenceNumberLengthMidPacket) {
EXPECT_CALL(framer_visitor_, OnStopWaitingFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
}
- ProcessPacket(serialized_packet_.packet);
+ ProcessPacket(serialized_packet_);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
header.public_header.packet_number_length);
- ClearSerializedPacket(&serialized_packet_);
+ DeleteSerializedPacket();
// Packet 2.
EXPECT_FALSE(creator_.HasPendingFrames());
@@ -414,7 +379,7 @@ TEST_P(QuicPacketCreatorTest, ChangeSequenceNumberLengthMidPacket) {
// Ensure the packet is successfully created.
creator_.Flush();
- ASSERT_TRUE(serialized_packet_.packet);
+ ASSERT_TRUE(serialized_packet_.encrypted_buffer);
EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
serialized_packet_.packet_number_length);
@@ -430,117 +395,14 @@ TEST_P(QuicPacketCreatorTest, ChangeSequenceNumberLengthMidPacket) {
EXPECT_CALL(framer_visitor_, OnStopWaitingFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
}
- ProcessPacket(serialized_packet_.packet);
+ ProcessPacket(serialized_packet_);
EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
header.public_header.packet_number_length);
- ClearSerializedPacket(&serialized_packet_);
+ DeleteSerializedPacket();
delete ack_frame.ack_frame;
}
-TEST_P(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) {
- // Test goal is to test the following sequence (P1 => generate Packet 1):
- // P1 <change seq num length> P2 FEC,
- // and we expect that packet number length should not change until the end
- // of the open FEC group.
-
- // Send FEC packet every 6 packets.
- creator_.set_max_packets_per_fec_group(6);
- // Should return false since we do not have enough packets in the FEC group to
- // trigger an FEC packet.
- ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false));
-
- // Generate Packet 1.
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- // Change the packet number length mid-FEC group and it should not change.
- QuicPacketCreatorPeer::SetNextPacketNumberLength(&creator_,
- PACKET_4BYTE_PACKET_NUMBER);
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(
- Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.Flush();
- EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
- serialized_packet_.packet_number_length);
-
- {
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket());
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
- EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnFecProtectedPayload(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
- }
- ProcessPacket(serialized_packet_.packet);
- ClearSerializedPacket(&serialized_packet_);
-
- // Generate Packet 2.
- ASSERT_TRUE(creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- creator_.Flush();
- EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
- serialized_packet_.packet_number_length);
-
- {
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket());
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
- EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnFecProtectedPayload(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
- }
- ProcessPacket(serialized_packet_.packet);
- ClearSerializedPacket(&serialized_packet_);
-
- // Should return false since we do not have enough packets in the FEC group to
- // trigger an FEC packet.
- ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false));
- // Should return true since there are packets in the FEC group.
- ASSERT_TRUE(creator_.ShouldSendFec(/*force_close=*/true));
-
- // Force generation of FEC packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- // Turn off FEC protection.
- creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true,
- /*is_fec_timeout=*/false);
- EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
- serialized_packet_.packet_number_length);
- ASSERT_EQ(3u, serialized_packet_.packet_number);
-
- {
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket());
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
- EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnFecData(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
- }
- ProcessPacket(serialized_packet_.packet);
- ClearSerializedPacket(&serialized_packet_);
-
- // Ensure the next FEC group starts using the new packet number length.
- ASSERT_TRUE(creator_.ConsumeData(3u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.Flush();
- EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
- serialized_packet_.packet_number_length);
- ClearSerializedPacket(&serialized_packet_);
-}
-
TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) {
// If the original packet number length, the current packet number
// length, and the configured send packet number length are different, the
@@ -551,17 +413,21 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) {
PACKET_2BYTE_PACKET_NUMBER);
QuicStreamFrame* stream_frame =
new QuicStreamFrame(kCryptoStreamId, /*fin=*/false, 0u, StringPiece());
- RetransmittableFrames frames;
- frames.AddFrame(QuicFrame(stream_frame));
+ QuicFrames frames;
+ frames.push_back(QuicFrame(stream_frame));
char buffer[kMaxPacketSize];
- SerializedPacket serialized = creator_.ReserializeAllFrames(
- frames, ENCRYPTION_NONE, PACKET_1BYTE_PACKET_NUMBER, buffer,
- kMaxPacketSize);
+ PendingRetransmission retransmission(CreateRetransmission(
+ frames, true /* has_crypto_handshake */, true /* needs padding */,
+ ENCRYPTION_NONE, PACKET_1BYTE_PACKET_NUMBER));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
+ creator_.ReserializeAllFrames(retransmission, buffer, kMaxPacketSize);
EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
- EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, serialized.packet_number_length);
+ EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
+ serialized_packet_.packet_number_length);
{
InSequence s;
@@ -573,38 +439,44 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) {
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
}
- ProcessPacket(serialized.packet);
- delete serialized.packet;
+ ProcessPacket(serialized_packet_);
+ delete stream_frame;
}
TEST_P(QuicPacketCreatorTest, ReserializeCryptoFrameWithForwardSecurity) {
QuicStreamFrame* stream_frame =
new QuicStreamFrame(kCryptoStreamId, /*fin=*/false, 0u, StringPiece());
- RetransmittableFrames frames;
- frames.AddFrame(QuicFrame(stream_frame));
+ QuicFrames frames;
+ frames.push_back(QuicFrame(stream_frame));
creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
char buffer[kMaxPacketSize];
- SerializedPacket serialized = creator_.ReserializeAllFrames(
- frames, ENCRYPTION_NONE,
- QuicPacketCreatorPeer::NextPacketNumberLength(&creator_), buffer,
- kMaxPacketSize);
- EXPECT_EQ(ENCRYPTION_NONE, serialized.encryption_level);
- delete serialized.packet;
+ PendingRetransmission retransmission(CreateRetransmission(
+ frames, true /* has_crypto_handshake */, true /* needs padding */,
+ ENCRYPTION_NONE,
+ QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
+ creator_.ReserializeAllFrames(retransmission, buffer, kMaxPacketSize);
+ EXPECT_EQ(ENCRYPTION_NONE, serialized_packet_.encryption_level);
+ delete stream_frame;
}
TEST_P(QuicPacketCreatorTest, ReserializeFrameWithForwardSecurity) {
QuicStreamFrame* stream_frame =
new QuicStreamFrame(0u, /*fin=*/false, 0u, StringPiece());
- RetransmittableFrames frames;
- frames.AddFrame(QuicFrame(stream_frame));
+ QuicFrames frames;
+ frames.push_back(QuicFrame(stream_frame));
creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
char buffer[kMaxPacketSize];
- SerializedPacket serialized = creator_.ReserializeAllFrames(
- frames, ENCRYPTION_NONE,
- QuicPacketCreatorPeer::NextPacketNumberLength(&creator_), buffer,
- kMaxPacketSize);
- EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, serialized.encryption_level);
- delete serialized.packet;
+ PendingRetransmission retransmission(CreateRetransmission(
+ frames, false /* has_crypto_handshake */, false /* needs padding */,
+ ENCRYPTION_NONE,
+ QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
+ creator_.ReserializeAllFrames(retransmission, buffer, kMaxPacketSize);
+ EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, serialized_packet_.encryption_level);
+ delete stream_frame;
}
TEST_P(QuicPacketCreatorTest, ReserializeFramesWithPadding) {
@@ -612,22 +484,23 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithPadding) {
QuicIOVector io_vector(MakeIOVector("fake handshake message data"));
QuicPacketCreatorPeer::CreateStreamFrame(&creator_, kCryptoStreamId,
io_vector, 0u, 0u, false, &frame);
- RetransmittableFrames frames;
- frames.AddFrame(frame);
- frames.set_needs_padding(true);
+ QuicFrames frames;
+ frames.push_back(frame);
char buffer[kMaxPacketSize];
- SerializedPacket serialized = creator_.ReserializeAllFrames(
- frames, ENCRYPTION_NONE,
- QuicPacketCreatorPeer::NextPacketNumberLength(&creator_), buffer,
- kMaxPacketSize);
- EXPECT_EQ(kDefaultMaxPacketSize, serialized.packet->length());
- delete serialized.packet;
+ PendingRetransmission retransmission(CreateRetransmission(
+ frames, true /* has_crypto_handshake */, true /* needs padding */,
+ ENCRYPTION_NONE,
+ QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
+ creator_.ReserializeAllFrames(retransmission, buffer, kMaxPacketSize);
+ EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.encrypted_length);
+ delete frame.stream_frame;
}
TEST_P(QuicPacketCreatorTest, ReserializeFramesWithFullPacketAndPadding) {
- const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) +
- GetEncryptionOverhead() +
- GetStreamFrameOverhead(NOT_IN_FEC_GROUP);
+ const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead() +
+ GetStreamFrameOverhead();
size_t capacity = kDefaultMaxPacketSize - overhead;
for (int delta = -5; delta <= 0; ++delta) {
string data(capacity + delta, 'A');
@@ -638,26 +511,28 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithFullPacketAndPadding) {
UniqueStreamBuffer stream_buffer;
QuicPacketCreatorPeer::CreateStreamFrame(
&creator_, kCryptoStreamId, io_vector, 0, kOffset, false, &frame);
- RetransmittableFrames frames;
- frames.AddFrame(frame);
- frames.set_needs_padding(true);
+ QuicFrames frames;
+ frames.push_back(frame);
char buffer[kMaxPacketSize];
- SerializedPacket serialized = creator_.ReserializeAllFrames(
- frames, ENCRYPTION_NONE,
- QuicPacketCreatorPeer::NextPacketNumberLength(&creator_), buffer,
- kMaxPacketSize);
+ PendingRetransmission retransmission(CreateRetransmission(
+ frames, true /* has_crypto_handshake */, true /* needs padding */,
+ ENCRYPTION_NONE,
+ QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
+ creator_.ReserializeAllFrames(retransmission, buffer, kMaxPacketSize);
// If there is not enough space in the packet to fit a padding frame
// (1 byte) and to expand the stream frame (another 2 bytes) the packet
// will not be padded.
if (bytes_free < 3) {
EXPECT_EQ(kDefaultMaxPacketSize - bytes_free,
- serialized.packet->length());
+ serialized_packet_.encrypted_length);
} else {
- EXPECT_EQ(kDefaultMaxPacketSize, serialized.packet->length());
+ EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.encrypted_length);
}
- delete serialized.packet;
+ delete frame.stream_frame;
frames_.clear();
}
}
@@ -683,79 +558,14 @@ TEST_P(QuicPacketCreatorTest, SerializeConnectionClose) {
EXPECT_CALL(framer_visitor_, OnConnectionCloseFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
- ProcessPacket(serialized.packet);
- delete serialized.packet;
-}
-
-TEST_P(QuicPacketCreatorTest, SwitchFecOnOffWithGroupInProgress) {
- // Send FEC packet every 6 packets.
- creator_.set_max_packets_per_fec_group(6);
- // Turn on FEC protection.
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
- creator_.Flush();
- // We do not have enough packets in the FEC group to trigger an FEC packet.
- EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/false));
- // Should return true since there are packets in the FEC group.
- EXPECT_TRUE(creator_.ShouldSendFec(/*force_close=*/true));
-
- // Switching FEC off should not change creator state, since there is an
- // FEC packet under construction.
- EXPECT_DFATAL(QuicPacketCreatorPeer::StopFecProtectingPackets(&creator_),
- "Cannot stop FEC protection with open FEC group.");
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
- // Confirm that FEC packet is still under construction.
- EXPECT_TRUE(creator_.ShouldSendFec(/*force_close=*/true));
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
- // Turn off FEC protection.
- creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true,
- /*is_fec_timeout=*/false);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
-}
-
-TEST_P(QuicPacketCreatorTest, SwitchFecOnWithStreamFrameQueued) {
- // Add a stream frame to the creator.
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MAY_FEC_PROTECT));
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
- ASSERT_TRUE(frame.stream_frame);
- size_t consumed = frame.stream_frame->frame_length;
- EXPECT_EQ(4u, consumed);
- EXPECT_TRUE(creator_.HasPendingFrames());
-
- // Enable FEC protection, and send FEC packet every 6 packets.
- creator_.set_max_packets_per_fec_group(6);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(&creator_));
- EXPECT_DFATAL(QuicPacketCreatorPeer::StartFecProtectingPackets(&creator_),
- "Cannot start FEC protection with pending frames.");
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
-
- // Start FEC protection after current open packet is flushed.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
- ASSERT_TRUE(creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- ASSERT_TRUE(frame.stream_frame);
- consumed = frame.stream_frame->frame_length;
- EXPECT_EQ(4u, consumed);
- EXPECT_TRUE(creator_.HasPendingFrames());
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
+ ProcessPacket(serialized);
}
TEST_P(QuicPacketCreatorTest, ConsumeData) {
QuicFrame frame;
QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MAY_FEC_PROTECT));
+ ASSERT_TRUE(
+ creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame));
ASSERT_TRUE(frame.stream_frame);
size_t consumed = frame.stream_frame->frame_length;
EXPECT_EQ(4u, consumed);
@@ -766,8 +576,8 @@ TEST_P(QuicPacketCreatorTest, ConsumeData) {
TEST_P(QuicPacketCreatorTest, ConsumeDataFin) {
QuicFrame frame;
QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 10u, true, false, &frame,
- MAY_FEC_PROTECT));
+ ASSERT_TRUE(
+ creator_.ConsumeData(1u, io_vector, 0u, 10u, true, false, &frame));
ASSERT_TRUE(frame.stream_frame);
size_t consumed = frame.stream_frame->frame_length;
EXPECT_EQ(4u, consumed);
@@ -778,8 +588,7 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataFin) {
TEST_P(QuicPacketCreatorTest, ConsumeDataFinOnly) {
QuicFrame frame;
QuicIOVector io_vector(nullptr, 0, 0);
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame,
- MAY_FEC_PROTECT));
+ ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame));
ASSERT_TRUE(frame.stream_frame);
size_t consumed = frame.stream_frame->frame_length;
EXPECT_EQ(0u, consumed);
@@ -787,28 +596,11 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataFinOnly) {
EXPECT_TRUE(creator_.HasPendingFrames());
}
-TEST_P(QuicPacketCreatorTest, ConsumeDataWithFecProtect) {
- creator_.set_max_packets_per_fec_group(6);
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- ASSERT_TRUE(frame.stream_frame);
- size_t consumed = frame.stream_frame->frame_length;
- EXPECT_EQ(4u, consumed);
- CheckStreamFrame(frame, 1u, "test", 0u, false);
- EXPECT_TRUE(creator_.HasPendingFrames());
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
-}
-
TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) {
- const size_t overhead =
- GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) + GetEncryptionOverhead();
+ const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead();
for (size_t i = overhead; i < overhead + 100; ++i) {
creator_.SetMaxPacketLength(i);
- const bool should_have_room =
- i > overhead + GetStreamFrameOverhead(NOT_IN_FEC_GROUP);
+ const bool should_have_room = i > overhead + GetStreamFrameOverhead();
ASSERT_EQ(should_have_room,
creator_.HasRoomForStreamFrame(kClientDataStreamId1, kOffset));
if (should_have_room) {
@@ -818,8 +610,7 @@ TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) {
.WillRepeatedly(
Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u,
- kOffset, false, false, &frame,
- MAY_FEC_PROTECT));
+ kOffset, false, false, &frame));
ASSERT_TRUE(frame.stream_frame);
size_t bytes_consumed = frame.stream_frame->frame_length;
EXPECT_LT(0u, bytes_consumed);
@@ -830,9 +621,8 @@ TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) {
TEST_P(QuicPacketCreatorTest, StreamFrameConsumption) {
// Compute the total overhead for a single frame in packet.
- const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) +
- GetEncryptionOverhead() +
- GetStreamFrameOverhead(NOT_IN_FEC_GROUP);
+ const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead() +
+ GetStreamFrameOverhead();
size_t capacity = kDefaultMaxPacketSize - overhead;
// Now, test various sizes around this size.
for (int delta = -5; delta <= 5; ++delta) {
@@ -841,8 +631,7 @@ TEST_P(QuicPacketCreatorTest, StreamFrameConsumption) {
QuicFrame frame;
QuicIOVector io_vector(MakeIOVector(data));
ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u,
- kOffset, false, false, &frame,
- MAY_FEC_PROTECT));
+ kOffset, false, false, &frame));
ASSERT_TRUE(frame.stream_frame);
// BytesFree() returns bytes available for the next frame, which will
@@ -853,68 +642,15 @@ TEST_P(QuicPacketCreatorTest, StreamFrameConsumption) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
creator_.Flush();
- ASSERT_TRUE(serialized_packet_.packet);
- ClearSerializedPacket(&serialized_packet_);
- }
-}
-
-TEST_P(QuicPacketCreatorTest, StreamFrameConsumptionWithFec) {
- // Send FEC packet every 6 packets.
- creator_.set_max_packets_per_fec_group(6);
- // Turn on FEC protection.
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
-
- // Serialize the packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
- creator_.Flush();
- // Compute the total overhead for a single frame in packet.
- const size_t overhead = GetPacketHeaderOverhead(IN_FEC_GROUP) +
- GetEncryptionOverhead() +
- GetStreamFrameOverhead(IN_FEC_GROUP);
- size_t capacity = kDefaultMaxPacketSize - overhead;
- // Now, test various sizes around this size.
- for (int delta = -5; delta <= 5; ++delta) {
- string data(capacity + delta, 'A');
- size_t bytes_free = delta > 0 ? 0 : 0 - delta;
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector(data));
- ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u,
- kOffset, false, false, &frame,
- MUST_FEC_PROTECT));
- ASSERT_TRUE(frame.stream_frame);
- // BytesFree() returns bytes available for the next frame. Since stream
- // frame does not grow for FEC protected packets, this should be the same
- // as bytes_free (bound by 0).
- EXPECT_EQ(0u, creator_.ExpansionOnNewFrame());
- size_t expected_bytes_free = bytes_free > 0 ? bytes_free : 0;
- EXPECT_EQ(expected_bytes_free, creator_.BytesFree()) << "delta: " << delta;
- {
- InSequence s;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- // Every 6th packet will generate an extra FEC packet.
- if (delta == -1 || delta == 5) {
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(
- Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
- }
- }
- creator_.Flush();
- ASSERT_TRUE(serialized_packet_.packet);
- ClearSerializedPacket(&serialized_packet_);
+ ASSERT_TRUE(serialized_packet_.encrypted_buffer);
+ DeleteSerializedPacket();
}
}
TEST_P(QuicPacketCreatorTest, CryptoStreamFramePacketPadding) {
// Compute the total overhead for a single frame in packet.
- const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) +
- GetEncryptionOverhead() +
- GetStreamFrameOverhead(NOT_IN_FEC_GROUP);
+ const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead() +
+ GetStreamFrameOverhead();
ASSERT_GT(kMaxPacketSize, overhead);
size_t capacity = kDefaultMaxPacketSize - overhead;
// Now, test various sizes around this size.
@@ -928,30 +664,29 @@ TEST_P(QuicPacketCreatorTest, CryptoStreamFramePacketPadding) {
.WillRepeatedly(
Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
ASSERT_TRUE(creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, kOffset,
- false, true, &frame, MAY_FEC_PROTECT));
+ false, true, &frame));
ASSERT_TRUE(frame.stream_frame);
size_t bytes_consumed = frame.stream_frame->frame_length;
EXPECT_LT(0u, bytes_consumed);
creator_.Flush();
- ASSERT_TRUE(serialized_packet_.packet);
+ ASSERT_TRUE(serialized_packet_.encrypted_buffer);
// If there is not enough space in the packet to fit a padding frame
// (1 byte) and to expand the stream frame (another 2 bytes) the packet
// will not be padded.
if (bytes_free < 3) {
EXPECT_EQ(kDefaultMaxPacketSize - bytes_free,
- serialized_packet_.packet->length());
+ serialized_packet_.encrypted_length);
} else {
- EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.packet->length());
+ EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.encrypted_length);
}
- ClearSerializedPacket(&serialized_packet_);
+ DeleteSerializedPacket();
}
}
TEST_P(QuicPacketCreatorTest, NonCryptoStreamFramePacketNonPadding) {
// Compute the total overhead for a single frame in packet.
- const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) +
- GetEncryptionOverhead() +
- GetStreamFrameOverhead(NOT_IN_FEC_GROUP);
+ const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead() +
+ GetStreamFrameOverhead();
ASSERT_GT(kDefaultMaxPacketSize, overhead);
size_t capacity = kDefaultMaxPacketSize - overhead;
// Now, test various sizes around this size.
@@ -964,20 +699,19 @@ TEST_P(QuicPacketCreatorTest, NonCryptoStreamFramePacketNonPadding) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u,
- kOffset, false, false, &frame,
- MAY_FEC_PROTECT));
+ kOffset, false, false, &frame));
ASSERT_TRUE(frame.stream_frame);
size_t bytes_consumed = frame.stream_frame->frame_length;
EXPECT_LT(0u, bytes_consumed);
creator_.Flush();
- ASSERT_TRUE(serialized_packet_.packet);
+ ASSERT_TRUE(serialized_packet_.encrypted_buffer);
if (bytes_free > 0) {
EXPECT_EQ(kDefaultMaxPacketSize - bytes_free,
- serialized_packet_.packet->length());
+ serialized_packet_.encrypted_length);
} else {
- EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.packet->length());
+ EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.encrypted_length);
}
- ClearSerializedPacket(&serialized_packet_);
+ DeleteSerializedPacket();
}
}
@@ -1002,29 +736,23 @@ TEST_P(QuicPacketCreatorTest, UpdatePacketSequenceNumberLengthLeastAwaiting) {
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
- size_t max_packets_per_fec_group = 10;
- creator_.set_max_packets_per_fec_group(max_packets_per_fec_group);
- QuicPacketCreatorPeer::SetPacketNumber(&creator_,
- 64 - max_packets_per_fec_group);
+ QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64);
creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
- QuicPacketCreatorPeer::SetPacketNumber(&creator_,
- 64 * 256 - max_packets_per_fec_group);
+ QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64 * 256);
creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
- QuicPacketCreatorPeer::SetPacketNumber(
- &creator_, 64 * 256 * 256 - max_packets_per_fec_group);
+ QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64 * 256 * 256);
creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
- QuicPacketCreatorPeer::SetPacketNumber(
- &creator_,
- UINT64_C(64) * 256 * 256 * 256 * 256 - max_packets_per_fec_group);
+ QuicPacketCreatorPeer::SetPacketNumber(&creator_,
+ UINT64_C(64) * 256 * 256 * 256 * 256);
creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_6BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
@@ -1074,10 +802,9 @@ TEST_P(QuicPacketCreatorTest, SerializeFrame) {
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
}
- ProcessPacket(serialized.packet);
+ ProcessPacket(serialized);
EXPECT_EQ(GetParam().version_serialization,
header.public_header.version_flag);
- delete serialized.packet;
}
TEST_P(QuicPacketCreatorTest, ConsumeDataLargerThanOneStreamFrame) {
@@ -1089,22 +816,22 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataLargerThanOneStreamFrame) {
creator_.SetMaxPacketLength(GetPacketLengthForOneStream(
client_framer_.version(),
QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
+ QuicPacketCreatorPeer::SendPathIdInPacket(&creator_),
creator_.connection_id_length(), PACKET_1BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP, &payload_length));
+ &payload_length));
QuicFrame frame;
const string too_long_payload(payload_length * 2, 'a');
QuicIOVector io_vector(MakeIOVector(too_long_payload));
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame,
- MAY_FEC_PROTECT));
+ ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame));
ASSERT_TRUE(frame.stream_frame);
size_t consumed = frame.stream_frame->frame_length;
EXPECT_EQ(payload_length, consumed);
const string payload(payload_length, 'a');
CheckStreamFrame(frame, 1u, payload, 0u, false);
creator_.Flush();
- ClearSerializedPacket(&serialized_packet_);
+ DeleteSerializedPacket();
}
TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) {
@@ -1118,8 +845,8 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) {
GetPacketHeaderSize(
creator_.connection_id_length(),
QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
- /*include_path_id=*/false, PACKET_1BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ QuicPacketCreatorPeer::SendPathIdInPacket(&creator_),
+ PACKET_1BYTE_PACKET_NUMBER),
creator_.BytesFree());
// Add a variety of frame types and then a padding frame.
@@ -1129,8 +856,8 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) {
QuicFrame frame;
QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MAY_FEC_PROTECT));
+ ASSERT_TRUE(
+ creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame));
ASSERT_TRUE(frame.stream_frame);
size_t consumed = frame.stream_frame->frame_length;
EXPECT_EQ(4u, consumed);
@@ -1147,22 +874,20 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) {
EXPECT_FALSE(creator_.AddSavedFrame(QuicFrame(&ack_frame)));
// Ensure the packet is successfully created.
- ASSERT_TRUE(serialized_packet_.packet);
- ASSERT_TRUE(serialized_packet_.retransmittable_frames);
- RetransmittableFrames* retransmittable =
- serialized_packet_.retransmittable_frames;
- ASSERT_EQ(1u, retransmittable->frames().size());
- EXPECT_EQ(STREAM_FRAME, retransmittable->frames()[0].type);
- ASSERT_TRUE(retransmittable->frames()[0].stream_frame);
- ClearSerializedPacket(&serialized_packet_);
+ ASSERT_TRUE(serialized_packet_.encrypted_buffer);
+ ASSERT_FALSE(serialized_packet_.retransmittable_frames.empty());
+ const QuicFrames& retransmittable = serialized_packet_.retransmittable_frames;
+ ASSERT_EQ(1u, retransmittable.size());
+ EXPECT_EQ(STREAM_FRAME, retransmittable[0].type);
+ ASSERT_TRUE(retransmittable[0].stream_frame);
+ DeleteSerializedPacket();
EXPECT_FALSE(creator_.HasPendingFrames());
EXPECT_EQ(max_plaintext_size -
GetPacketHeaderSize(
creator_.connection_id_length(),
QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
- /*include_path_id=*/false, PACKET_1BYTE_PACKET_NUMBER,
- NOT_IN_FEC_GROUP),
+ /*include_path_id=*/false, PACKET_1BYTE_PACKET_NUMBER),
creator_.BytesFree());
}
@@ -1176,7 +901,7 @@ TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithLargePacketSize) {
// 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, NOT_IN_FEC_GROUP,
+ 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());
@@ -1190,8 +915,8 @@ TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithLargePacketSize) {
// 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,
- MAY_FEC_PROTECT));
+ ASSERT_TRUE(
+ creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame));
ASSERT_TRUE(frame.stream_frame);
size_t consumed = frame.stream_frame->frame_length;
EXPECT_EQ(4u, consumed);
@@ -1204,10 +929,10 @@ TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithLargePacketSize) {
.WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
size_t est_packet_size = creator_.PacketSize();
creator_.Flush();
- ASSERT_TRUE(serialized_packet_.packet);
+ ASSERT_TRUE(serialized_packet_.encrypted_buffer);
EXPECT_EQ(est_packet_size, client_framer_.GetMaxPlaintextSize(
- serialized_packet_.packet->length()));
- ClearSerializedPacket(&serialized_packet_);
+ serialized_packet_.encrypted_length));
+ DeleteSerializedPacket();
}
TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithSmallPacketSize) {
@@ -1224,7 +949,7 @@ TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithSmallPacketSize) {
// the packet size.
QuicAckFrame ack_frame = MakeAckFrameWithNackRanges(2000u, 0u);
size_t frame_len = client_framer_.GetSerializedFrameLength(
- QuicFrame(&ack_frame), creator_.BytesFree(), true, true, NOT_IN_FEC_GROUP,
+ QuicFrame(&ack_frame), creator_.BytesFree(), true, true,
PACKET_1BYTE_PACKET_NUMBER);
EXPECT_EQ(creator_.BytesFree(), frame_len);
@@ -1242,10 +967,10 @@ TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithSmallPacketSize) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
creator_.Flush();
- ASSERT_TRUE(serialized_packet_.packet);
+ ASSERT_TRUE(serialized_packet_.encrypted_buffer);
EXPECT_GE(est_packet_size, client_framer_.GetMaxPlaintextSize(
- serialized_packet_.packet->length()));
- ClearSerializedPacket(&serialized_packet_);
+ serialized_packet_.encrypted_length));
+ DeleteSerializedPacket();
}
TEST_P(QuicPacketCreatorTest, EntropyFlag) {
@@ -1263,7 +988,6 @@ TEST_P(QuicPacketCreatorTest, EntropyFlag) {
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);
- delete serialized.packet;
}
// After 64 calls, BoolSource will refresh the bucket - make sure it does.
mock_random_.ChangeValue();
@@ -1272,103 +996,6 @@ TEST_P(QuicPacketCreatorTest, EntropyFlag) {
delete frames_[0].stream_frame;
}
-TEST_P(QuicPacketCreatorTest, ResetFecGroup) {
- // Send FEC packet every 6 packets.
- creator_.set_max_packets_per_fec_group(6);
- // Add a stream frame and turn on FEC protection.
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- // Serialize the packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
- creator_.Flush();
-
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
- EXPECT_TRUE(creator_.IsFecGroupOpen());
- // We do not have enough packets in the FEC group to trigger an FEC packet.
- EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/false));
- // Should return true since there are packets in the FEC group.
- EXPECT_TRUE(creator_.ShouldSendFec(/*force_close=*/true));
-
- // FEC group will be reset if FEC police is alarm trigger but FEC alarm does
- // not fire.
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
- creator_.set_fec_send_policy(FEC_ALARM_TRIGGER);
- creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true,
- /*is_fec_timeout=*/false);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
- EXPECT_FALSE(creator_.IsFecGroupOpen());
- // We do not have enough packets in the FEC group to trigger an FEC packet.
- EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/false));
- // Confirm that there is no FEC packet under construction.
- EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/true));
-
- char buffer[kMaxPacketSize];
- EXPECT_DFATAL(
- QuicPacketCreatorPeer::SerializeFec(&creator_, buffer, kMaxPacketSize),
- "SerializeFEC called but no group or zero packets in group.");
-
- // Create and send a new FEC protected packet.
- ASSERT_TRUE(creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
- creator_.Flush();
-
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
- EXPECT_TRUE(creator_.IsFecGroupOpen());
- // We do not have enough packets in the FEC group to trigger an FEC packet.
- EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/false));
- // Should return true since there are packets in the FEC group.
- EXPECT_TRUE(creator_.ShouldSendFec(/*force_close=*/true));
-
- // Should return false since we do not have enough packets in the FEC group to
- // trigger an FEC packet.
- ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false));
- // Should return true since there are packets in the FEC group.
- ASSERT_TRUE(creator_.ShouldSendFec(/*force_close=*/true));
-
- // Change FEC policy, send FEC packet and close FEC group.
- creator_.set_fec_send_policy(FEC_ANY_TRIGGER);
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true,
- /*is_fec_timeout=*/false);
- ASSERT_EQ(3u, serialized_packet_.packet_number);
- ClearSerializedPacket(&serialized_packet_);
-}
-
-TEST_P(QuicPacketCreatorTest, ResetFecGroupWithQueuedFrames) {
- // Send FEC packet every 6 packets.
- creator_.set_max_packets_per_fec_group(6);
- // Add a stream frame to the creator and turn on FEC protection.
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- ASSERT_TRUE(frame.stream_frame);
- size_t consumed = frame.stream_frame->frame_length;
- EXPECT_EQ(4u, consumed);
- EXPECT_TRUE(creator_.HasPendingFrames());
- EXPECT_DFATAL(QuicPacketCreatorPeer::ResetFecGroup(&creator_),
- "Cannot reset FEC group with pending frames.");
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
- creator_.Flush();
- EXPECT_FALSE(creator_.HasPendingFrames());
-
- // FEC group will be reset if FEC police is alarm trigger but FEC alarm does
- // not fire.
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
- creator_.set_fec_send_policy(FEC_ALARM_TRIGGER);
- creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true,
- /*is_fec_timeout=*/false);
- EXPECT_FALSE(creator_.IsFecGroupOpen());
-}
-
TEST_P(QuicPacketCreatorTest, SetCurrentPath) {
// Current path is the default path.
EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(&creator_));
@@ -1378,8 +1005,8 @@ TEST_P(QuicPacketCreatorTest, SetCurrentPath) {
// Add a stream frame to the creator.
QuicFrame frame;
QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MAY_FEC_PROTECT));
+ ASSERT_TRUE(
+ creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame));
ASSERT_TRUE(frame.stream_frame);
size_t consumed = frame.stream_frame->frame_length;
EXPECT_EQ(4u, consumed);
@@ -1410,8 +1037,8 @@ TEST_P(QuicPacketCreatorTest, SetCurrentPath) {
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
// Add a stream frame to the creator.
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MAY_FEC_PROTECT));
+ ASSERT_TRUE(
+ creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame));
ASSERT_TRUE(frame.stream_frame);
consumed = frame.stream_frame->frame_length;
EXPECT_EQ(4u, consumed);
@@ -1426,95 +1053,24 @@ TEST_P(QuicPacketCreatorTest, SetCurrentPath) {
QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
}
-TEST_P(QuicPacketCreatorTest, SetCurrentPathWithFec) {
- // Send FEC packet every 6 packets.
- creator_.set_max_packets_per_fec_group(6);
- // Current path is the default path.
- EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(&creator_));
- EXPECT_EQ(0u, creator_.packet_number());
- EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
- QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
- // Add a stream frame to the creator.
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- ASSERT_TRUE(frame.stream_frame);
- size_t consumed = frame.stream_frame->frame_length;
- EXPECT_EQ(4u, consumed);
- EXPECT_TRUE(creator_.HasPendingFrames());
- EXPECT_EQ(0u, creator_.packet_number());
- EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
- QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
-
- // Change current path.
- QuicPathId kPathId1 = 1;
- EXPECT_DFATAL(creator_.SetCurrentPath(kPathId1, 1, 0),
- "Unable to change paths when a packet is under construction");
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .Times(2)
- .WillRepeatedly(
- Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
- creator_.Flush();
- EXPECT_FALSE(creator_.HasPendingFrames());
- creator_.SetCurrentPath(kPathId1, 1, 0);
- EXPECT_EQ(kPathId1, QuicPacketCreatorPeer::GetCurrentPath(&creator_));
- EXPECT_FALSE(creator_.HasPendingFrames());
- EXPECT_EQ(0u, creator_.packet_number());
- EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
- QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
-
- // Change current path back.
- creator_.SetCurrentPath(kDefaultPathId, 3, 2);
- EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(&creator_));
- // FEC packet consumes a packet number.
- EXPECT_EQ(2u, creator_.packet_number());
- EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
- QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
- // Add a stream frame to the creator.
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
- ASSERT_TRUE(frame.stream_frame);
- consumed = frame.stream_frame->frame_length;
- EXPECT_EQ(4u, consumed);
- EXPECT_TRUE(creator_.HasPendingFrames());
-
- // Does not change current path.
- creator_.SetCurrentPath(kDefaultPathId, 3, 0);
- EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(&creator_));
- EXPECT_TRUE(creator_.HasPendingFrames());
- // FEC packet consumes a packet number.
- EXPECT_EQ(2u, creator_.packet_number());
- EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
- QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
-}
-
TEST_P(QuicPacketCreatorTest,
- SetCurrentPathWithFecAndUpdatePacketSequenceNumberLength) {
- // Send FEC packet every 10 packets.
- size_t max_packets_per_fec_group = 10;
- creator_.set_max_packets_per_fec_group(max_packets_per_fec_group);
+ SetCurrentPathAndUpdatePacketSequenceNumberLength) {
// Current path is the default path.
EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(&creator_));
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
- QuicPacketCreatorPeer::SetPacketNumber(
- &creator_, 64 * 256 - max_packets_per_fec_group - 2);
+ QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64 * 256 - 2);
// Add a stream frame to the creator and send the packet.
QuicFrame frame;
QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MUST_FEC_PROTECT));
+ ASSERT_TRUE(
+ creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame));
EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .Times(2)
+ .Times(1)
.WillRepeatedly(
Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
creator_.Flush();
- EXPECT_EQ(64 * 256 - max_packets_per_fec_group - 1, creator_.packet_number());
+ EXPECT_EQ(UINT64_C(64 * 256 - 1), creator_.packet_number());
creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
@@ -1528,8 +1084,7 @@ TEST_P(QuicPacketCreatorTest,
// Change current path back.
creator_.SetCurrentPath(kDefaultPathId, 2, 10000 / kDefaultMaxPacketSize);
- // FEC packet consumes a packet number.
- EXPECT_EQ(64 * 256 - max_packets_per_fec_group, creator_.packet_number());
+ EXPECT_EQ(UINT64_C(64 * 256 - 1), creator_.packet_number());
EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
}
@@ -1541,8 +1096,8 @@ TEST_P(QuicPacketCreatorTest, SerializePacketOnDifferentPath) {
// Add a stream frame to the creator and flush the packet.
QuicFrame frame;
QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MAY_FEC_PROTECT));
+ ASSERT_TRUE(
+ creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame));
ASSERT_TRUE(frame.stream_frame);
size_t consumed = frame.stream_frame->frame_length;
EXPECT_EQ(4u, consumed);
@@ -1556,7 +1111,7 @@ TEST_P(QuicPacketCreatorTest, SerializePacketOnDifferentPath) {
EXPECT_EQ(1u, creator_.packet_number());
// Verify serialized data packet's path id.
EXPECT_EQ(kDefaultPathId, serialized_packet_.path_id);
- ClearSerializedPacket(&serialized_packet_);
+ DeleteSerializedPacket();
// Change to path 1.
QuicPathId kPathId1 = 1;
@@ -1568,8 +1123,8 @@ TEST_P(QuicPacketCreatorTest, SerializePacketOnDifferentPath) {
QuicPacketCreatorPeer::NextPacketNumberLength(&creator_));
// Add a stream frame to the creator and flush the packet.
- ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame,
- MAY_FEC_PROTECT));
+ ASSERT_TRUE(
+ creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame));
ASSERT_TRUE(frame.stream_frame);
consumed = frame.stream_frame->frame_length;
EXPECT_EQ(4u, consumed);
@@ -1577,68 +1132,18 @@ TEST_P(QuicPacketCreatorTest, SerializePacketOnDifferentPath) {
creator_.Flush();
// Verify serialized data packet's path id.
EXPECT_EQ(kPathId1, serialized_packet_.path_id);
- ClearSerializedPacket(&serialized_packet_);
+ DeleteSerializedPacket();
}
TEST_P(QuicPacketCreatorTest, AddUnencryptedStreamDataClosesConnection) {
FLAGS_quic_never_write_unencrypted_data = true;
- EXPECT_CALL(delegate_, CloseConnection(_, _));
+ EXPECT_CALL(delegate_, OnUnrecoverableError(_, _, _));
QuicStreamFrame stream_frame(kHeadersStreamId, /*fin=*/false, 0u,
StringPiece());
EXPECT_DFATAL(creator_.AddSavedFrame(QuicFrame(&stream_frame)),
"Cannot send stream data without encryption.");
}
-TEST_P(QuicPacketCreatorTest, DontSendUnencryptedFec) {
- ValueRestore<bool> old_flag(&FLAGS_quic_no_unencrypted_fec, true);
- // Send FEC packet every 6 packets.
- creator_.set_max_packets_per_fec_group(6);
- // Send stream data encrypted with FEC protection.
- creator_.set_encryption_level(ENCRYPTION_INITIAL);
- // Turn on FEC protection.
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(kHeadersStreamId, io_vector, 0u, 0u, false,
- false, &frame, MUST_FEC_PROTECT));
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
- // Serialize the packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
- creator_.Flush();
-
- // The creator will clear the FEC group rather than try to send without
- // encryption.
- creator_.set_encryption_level(ENCRYPTION_NONE);
- EXPECT_CALL(delegate_, OnResetFecGroup());
- creator_.MaybeSendFecPacketAndCloseGroup(true, false);
-}
-
-TEST_P(QuicPacketCreatorTest, SerializeUnencryptedFecClosesConnection) {
- ValueRestore<bool> old_flag(&FLAGS_quic_no_unencrypted_fec, true);
- // Send FEC packet every 6 packets.
- creator_.set_max_packets_per_fec_group(6);
- // Send stream data encrypted with FEC protection.
- creator_.set_encryption_level(ENCRYPTION_INITIAL);
- // Turn on FEC protection.
- QuicFrame frame;
- QuicIOVector io_vector(MakeIOVector("test"));
- ASSERT_TRUE(creator_.ConsumeData(kHeadersStreamId, io_vector, 0u, 0u, false,
- false, &frame, MUST_FEC_PROTECT));
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_));
- // Serialize the packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket));
- creator_.Flush();
-
- // Try to send an FEC packet unencrypted.
- creator_.set_encryption_level(ENCRYPTION_NONE);
- EXPECT_CALL(delegate_, CloseConnection(QUIC_UNENCRYPTED_FEC_DATA, _));
- char seralized_fec_buffer[kMaxPacketSize];
- EXPECT_DFATAL(QuicPacketCreatorPeer::SerializeFec(
- &creator_, seralized_fec_buffer, kMaxPacketSize),
- "SerializeFEC must be called with encryption.");
-}
-
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_packet_generator.cc b/chromium/net/quic/quic_packet_generator.cc
index 50d6af11eb0..f83dfb63b9b 100644
--- a/chromium/net/quic/quic_packet_generator.cc
+++ b/chromium/net/quic/quic_packet_generator.cc
@@ -6,7 +6,6 @@
#include "base/logging.h"
#include "net/quic/quic_bug_tracker.h"
-#include "net/quic/quic_fec_group.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_utils.h"
@@ -14,8 +13,6 @@ using base::StringPiece;
namespace net {
-class QuicAckNotifier;
-
QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id,
QuicFramer* framer,
QuicRandom* random_generator,
@@ -29,53 +26,10 @@ QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id,
delegate),
batch_mode_(false),
should_send_ack_(false),
- should_send_stop_waiting_(false),
- max_packet_length_(kDefaultMaxPacketSize) {}
+ should_send_stop_waiting_(false) {}
QuicPacketGenerator::~QuicPacketGenerator() {
- for (QuicFrame& frame : queued_control_frames_) {
- switch (frame.type) {
- 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 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 WINDOW_UPDATE_FRAME:
- delete frame.window_update_frame;
- break;
- case BLOCKED_FRAME:
- delete frame.blocked_frame;
- break;
- case STOP_WAITING_FRAME:
- delete frame.stop_waiting_frame;
- break;
- case NUM_FRAME_TYPES:
- DCHECK(false) << "Cannot delete type: " << frame.type;
- }
- }
-}
-
-void QuicPacketGenerator::OnCongestionWindowChange(
- QuicPacketCount max_packets_in_flight) {
- packet_creator_.OnCongestionWindowChange(max_packets_in_flight);
-}
-
-void QuicPacketGenerator::OnRttChange(QuicTime::Delta rtt) {
- packet_creator_.OnRttChange(rtt);
+ QuicUtils::DeleteFrames(&queued_control_frames_);
}
void QuicPacketGenerator::SetShouldSendAck(bool also_send_stop_waiting) {
@@ -91,12 +45,12 @@ void QuicPacketGenerator::SetShouldSendAck(bool also_send_stop_waiting) {
should_send_ack_ = true;
should_send_stop_waiting_ = also_send_stop_waiting;
- SendQueuedFrames(/*flush=*/false, /*is_fec_timeout=*/false);
+ SendQueuedFrames(/*flush=*/false);
}
void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) {
queued_control_frames_.push_back(frame);
- SendQueuedFrames(/*flush=*/false, /*is_fec_timeout=*/false);
+ SendQueuedFrames(/*flush=*/false);
}
QuicConsumedData QuicPacketGenerator::ConsumeData(
@@ -104,14 +58,13 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- FecProtection fec_protection,
QuicAckListenerInterface* listener) {
bool has_handshake = id == kCryptoStreamId;
// To make reasoning about crypto frames easier, we don't combine them with
// other retransmittable frames in a single packet.
const bool flush =
has_handshake && packet_creator_.HasPendingRetransmittableFrames();
- SendQueuedFrames(flush, /*is_fec_timeout=*/false);
+ SendQueuedFrames(flush);
size_t total_bytes_consumed = 0;
bool fin_consumed = false;
@@ -130,7 +83,7 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(
QuicFrame frame;
if (!packet_creator_.ConsumeData(id, iov, total_bytes_consumed,
offset + total_bytes_consumed, fin,
- has_handshake, &frame, fec_protection)) {
+ has_handshake, &frame)) {
// The creator is always flushed if there's not enough room for a new
// stream frame before ConsumeData, so ConsumeData should always succeed.
QUIC_BUG << "Failed to ConsumeData, stream:" << id;
@@ -148,9 +101,6 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(
(bytes_consumed > 0 && packet_creator_.HasPendingFrames()));
if (!InBatchMode()) {
- // TODO(rtenneti): remove MaybeSendFecPacketAndCloseGroup() from inside
- // SerializeAndSendPacket() and make it an explicit call here (and
- // elsewhere where we call SerializeAndSendPacket?).
packet_creator_.Flush();
}
@@ -166,14 +116,9 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(
// Don't allow the handshake to be bundled with other retransmittable frames.
if (has_handshake) {
- SendQueuedFrames(/*flush=*/true, /*is_fec_timeout=*/false);
+ SendQueuedFrames(/*flush=*/true);
}
- // Try to close FEC group since we've either run out of data to send or we're
- // blocked.
- packet_creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/false,
- /*is_fec_timeout=*/false);
-
DCHECK(InBatchMode() || !packet_creator_.HasPendingFrames());
return QuicConsumedData(total_bytes_consumed, fin_consumed);
}
@@ -182,8 +127,12 @@ void QuicPacketGenerator::GenerateMtuDiscoveryPacket(
QuicByteCount target_mtu,
QuicAckListenerInterface* listener) {
// MTU discovery frames must be sent by themselves.
- DCHECK(!InBatchMode() && !packet_creator_.HasPendingFrames());
- const QuicByteCount current_mtu = GetMaxPacketLength();
+ if (!packet_creator_.CanSetMaxPacketLength()) {
+ QUIC_BUG << "MTU discovery packets should only be sent when no other "
+ << "frames needs to be sent.";
+ return;
+ }
+ const QuicByteCount current_mtu = GetCurrentMaxPacketLength();
// The MTU discovery frame is allocated on the stack, since it is going to be
// serialized within this function.
@@ -191,7 +140,7 @@ void QuicPacketGenerator::GenerateMtuDiscoveryPacket(
QuicFrame frame(mtu_discovery_frame);
// Send the probe packet with the new length.
- SetMaxPacketLength(target_mtu, /*force=*/true);
+ SetMaxPacketLength(target_mtu);
const bool success = packet_creator_.AddPaddedSavedFrame(frame);
if (listener != nullptr) {
packet_creator_.AddAckListener(listener, 0);
@@ -202,7 +151,7 @@ void QuicPacketGenerator::GenerateMtuDiscoveryPacket(
DCHECK(success);
// Reset the packet length back.
- SetMaxPacketLength(current_mtu, /*force=*/true);
+ SetMaxPacketLength(current_mtu);
}
bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const {
@@ -217,7 +166,7 @@ bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const {
return delegate_->ShouldGeneratePacket(retransmittable, NOT_HANDSHAKE);
}
-void QuicPacketGenerator::SendQueuedFrames(bool flush, bool is_fec_timeout) {
+void QuicPacketGenerator::SendQueuedFrames(bool flush) {
// Only add pending frames if we are SURE we can then send the whole packet.
while (HasPendingFrames() &&
(flush || CanSendWithNextPendingFrameAddition())) {
@@ -226,23 +175,6 @@ void QuicPacketGenerator::SendQueuedFrames(bool flush, bool is_fec_timeout) {
if (flush || !InBatchMode()) {
packet_creator_.Flush();
}
- packet_creator_.MaybeSendFecPacketAndCloseGroup(flush, is_fec_timeout);
-}
-
-void QuicPacketGenerator::OnFecTimeout() {
- DCHECK(!InBatchMode());
- if (!packet_creator_.ShouldSendFec(true)) {
- QUIC_BUG << "No FEC packet to send on FEC timeout.";
- return;
- }
- // Flush out any pending frames in the generator and the creator, and then
- // send out FEC packet.
- SendQueuedFrames(/*flush=*/true, /*is_fec_timeout=*/true);
-}
-
-QuicTime::Delta QuicPacketGenerator::GetFecTimeout(
- QuicPacketNumber packet_number) {
- return packet_creator_.GetFecTimeout(packet_number);
}
bool QuicPacketGenerator::InBatchMode() {
@@ -255,17 +187,21 @@ void QuicPacketGenerator::StartBatchOperations() {
void QuicPacketGenerator::FinishBatchOperations() {
batch_mode_ = false;
- SendQueuedFrames(/*flush=*/false, /*is_fec_timeout=*/false);
+ SendQueuedFrames(/*flush=*/false);
}
void QuicPacketGenerator::FlushAllQueuedFrames() {
- SendQueuedFrames(/*flush=*/true, /*is_fec_timeout=*/false);
+ SendQueuedFrames(/*flush=*/true);
}
bool QuicPacketGenerator::HasQueuedFrames() const {
return packet_creator_.HasPendingFrames() || HasPendingFrames();
}
+bool QuicPacketGenerator::IsPendingPacketEmpty() const {
+ return !packet_creator_.HasPendingFrames();
+}
+
bool QuicPacketGenerator::HasPendingFrames() const {
return should_send_ack_ || should_send_stop_waiting_ ||
!queued_control_frames_.empty();
@@ -273,12 +209,8 @@ bool QuicPacketGenerator::HasPendingFrames() const {
bool QuicPacketGenerator::AddNextPendingFrame() {
if (should_send_ack_) {
- delegate_->PopulateAckFrame(&pending_ack_frame_);
- // If we can't this add the frame now, then we still need to do so later.
should_send_ack_ =
- !packet_creator_.AddSavedFrame(QuicFrame(&pending_ack_frame_));
- // Return success if we have cleared out this flag (i.e., added the frame).
- // If we still need to send, then the frame is full, and we have failed.
+ !packet_creator_.AddSavedFrame(delegate_->GetUpdatedAckFrame());
return !should_send_ack_;
}
@@ -292,7 +224,7 @@ bool QuicPacketGenerator::AddNextPendingFrame() {
return !should_send_stop_waiting_;
}
- LOG_IF(DFATAL, queued_control_frames_.empty())
+ QUIC_BUG_IF(queued_control_frames_.empty())
<< "AddNextPendingFrame called with no queued control frames.";
if (!packet_creator_.AddSavedFrame(queued_control_frames_.back())) {
// Packet was full.
@@ -310,29 +242,13 @@ QuicPacketNumber QuicPacketGenerator::packet_number() const {
return packet_creator_.packet_number();
}
-QuicByteCount QuicPacketGenerator::GetMaxPacketLength() const {
- return max_packet_length_;
-}
-
QuicByteCount QuicPacketGenerator::GetCurrentMaxPacketLength() const {
return packet_creator_.max_packet_length();
}
-void QuicPacketGenerator::SetMaxPacketLength(QuicByteCount length, bool force) {
- // If we cannot immediately set new maximum packet length, and the |force|
- // flag is set, we have to flush the contents of the queue and close existing
- // FEC group.
- if (!packet_creator_.CanSetMaxPacketLength() && force) {
- SendQueuedFrames(/*flush=*/true, /*is_fec_timeout=*/false);
- packet_creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true,
- /*is_fec_timeout=*/false);
- DCHECK(packet_creator_.CanSetMaxPacketLength());
- }
-
- max_packet_length_ = length;
- if (packet_creator_.CanSetMaxPacketLength()) {
- packet_creator_.SetMaxPacketLength(length);
- }
+void QuicPacketGenerator::SetMaxPacketLength(QuicByteCount length) {
+ DCHECK(packet_creator_.CanSetMaxPacketLength());
+ packet_creator_.SetMaxPacketLength(length);
}
QuicEncryptedPacket* QuicPacketGenerator::SerializeVersionNegotiationPacket(
@@ -340,14 +256,11 @@ QuicEncryptedPacket* QuicPacketGenerator::SerializeVersionNegotiationPacket(
return packet_creator_.SerializeVersionNegotiationPacket(supported_versions);
}
-SerializedPacket QuicPacketGenerator::ReserializeAllFrames(
- const RetransmittableFrames& frames,
- EncryptionLevel original_encryption_level,
- QuicPacketNumberLength original_length,
+void QuicPacketGenerator::ReserializeAllFrames(
+ const PendingRetransmission& retransmission,
char* buffer,
size_t buffer_len) {
- return packet_creator_.ReserializeAllFrames(
- frames, original_encryption_level, original_length, buffer, buffer_len);
+ packet_creator_.ReserializeAllFrames(retransmission, buffer, buffer_len);
}
void QuicPacketGenerator::UpdateSequenceNumberLength(
@@ -386,18 +299,4 @@ void QuicPacketGenerator::SetCurrentPath(
max_packets_in_flight);
}
-void QuicPacketGenerator::set_rtt_multiplier_for_fec_timeout(
- float rtt_multiplier_for_fec_timeout) {
- packet_creator_.set_rtt_multiplier_for_fec_timeout(
- rtt_multiplier_for_fec_timeout);
-}
-
-FecSendPolicy QuicPacketGenerator::fec_send_policy() {
- return packet_creator_.fec_send_policy();
-}
-
-void QuicPacketGenerator::set_fec_send_policy(FecSendPolicy fec_send_policy) {
- packet_creator_.set_fec_send_policy(fec_send_policy);
-}
-
} // namespace net
diff --git a/chromium/net/quic/quic_packet_generator.h b/chromium/net/quic/quic_packet_generator.h
index 8f3182d839e..cb366c90fdf 100644
--- a/chromium/net/quic/quic_packet_generator.h
+++ b/chromium/net/quic/quic_packet_generator.h
@@ -36,19 +36,6 @@
// full, it will be serialized and sent to the packet. When batch
// mode is ended via |FinishBatchOperations|, the current packet
// will be serialzied, even if it is not full.
-//
-// FEC behavior also depends on batch mode. In batch mode, FEC packets
-// will be sent after |max_packets_per_group| have been sent, as well
-// as after batch operations are complete. When not in batch mode,
-// an FEC packet will be sent after each write call completes.
-//
-// TODO(rch): This behavior should probably be tuned. When not in batch
-// mode, we should probably set a timer so that several independent
-// operations can be grouped into the same FEC group.
-//
-// When an FEC packet is generated, it will be send to the Delegate,
-// even if the Delegate has become unwritable after handling the
-// data packet immediately proceeding the FEC packet.
#ifndef NET_QUIC_QUIC_PACKET_GENERATOR_H_
#define NET_QUIC_QUIC_PACKET_GENERATOR_H_
@@ -78,7 +65,7 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
// Consults delegate whether a packet should be generated.
virtual bool ShouldGeneratePacket(HasRetransmittableData retransmittable,
IsHandshake handshake) = 0;
- virtual void PopulateAckFrame(QuicAckFrame* ack) = 0;
+ virtual const QuicFrame GetUpdatedAckFrame() = 0;
virtual void PopulateStopWaitingFrame(
QuicStopWaitingFrame* stop_waiting) = 0;
};
@@ -91,12 +78,6 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
~QuicPacketGenerator();
- // Called by the connection in the event of the congestion window changing.
- void OnCongestionWindowChange(QuicPacketCount max_packets_in_flight);
-
- // Called by the connection when the RTT may have changed.
- void OnRttChange(QuicTime::Delta rtt);
-
// Indicates that an ACK frame should be sent.
// If |also_send_stop_waiting| is true, then it also indicates that a
// STOP_WAITING frame should be sent as well.
@@ -115,7 +96,6 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- FecProtection fec_protection,
QuicAckListenerInterface* listener);
// Generates an MTU discovery packet of specified size.
@@ -134,6 +114,9 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
bool HasQueuedFrames() const;
+ // Whether the pending packet has no frames in it at the moment.
+ bool IsPendingPacketEmpty() const;
+
// Makes the framer not serialize the protocol version in sent packets.
void StopSendingVersion();
@@ -146,14 +129,9 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
// Re-serializes frames with the original packet's packet number length.
// Used for retransmitting packets to ensure they aren't too long.
- // Caller must ensure that any open FEC group is closed before calling this
- // method.
- SerializedPacket ReserializeAllFrames(
- const RetransmittableFrames& frames,
- EncryptionLevel original_encryption_level,
- QuicPacketNumberLength original_length,
- char* buffer,
- size_t buffer_len);
+ void ReserializeAllFrames(const PendingRetransmission& retransmission,
+ char* buffer,
+ size_t buffer_len);
// Update the packet number length to use in future packets as soon as it
// can be safely changed.
@@ -163,16 +141,6 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
// Set the minimum number of bytes for the connection id length;
void SetConnectionIdLength(uint32_t length);
- // Called when the FEC alarm fires.
- void OnFecTimeout();
-
- // Called after sending |packet_number| to determine whether an FEC alarm
- // should be set for sending out an FEC packet. Returns a positive and finite
- // timeout if an FEC alarm should be set, and infinite if no alarm should be
- // set. OnFecTimeout should be called to send the FEC packet when the alarm
- // fires.
- QuicTime::Delta GetFecTimeout(QuicPacketNumber packet_number);
-
// Sets the encrypter to use for the encryption level.
void SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter);
@@ -183,18 +151,12 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
// created.
QuicPacketNumber packet_number() const;
- // Returns the maximum packet length. Note that this is the long-term maximum
- // packet length, and it may not be the maximum length of the current packet,
- // if the generator is in the middle of the packet (in batch mode) or FEC
- // group.
- QuicByteCount GetMaxPacketLength() const;
- // Returns the maximum length current packet can actually have.
+ // Returns the maximum length a current packet can actually have.
QuicByteCount GetCurrentMaxPacketLength() const;
- // Set maximum packet length sent. If |force| is set to true, all pending
- // unfinished packets and FEC groups are closed, and the change is enacted
- // immediately. Otherwise, it is enacted at the next opportunity.
- void SetMaxPacketLength(QuicByteCount length, bool force);
+ // Set maximum packet length in the creator immediately. May not be called
+ // when there are frames queued in the creator.
+ void SetMaxPacketLength(QuicByteCount length);
// Sets |path_id| to be the path on which next packet is generated.
void SetCurrentPath(QuicPathId path_id,
@@ -205,15 +167,12 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
packet_creator_.set_debug_delegate(debug_delegate);
}
- void set_rtt_multiplier_for_fec_timeout(float rtt_multiplier_for_fec_timeout);
-
- FecSendPolicy fec_send_policy();
- void set_fec_send_policy(FecSendPolicy fec_send_policy);
+ const QuicAckFrame& pending_ack_frame() const { return pending_ack_frame_; }
private:
friend class test::QuicPacketGeneratorPeer;
- void SendQueuedFrames(bool flush, bool is_fec_timeout);
+ void SendQueuedFrames(bool flush);
// Test to see if we have pending ack, or control frames.
bool HasPendingFrames() const;
@@ -244,11 +203,6 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
QuicAckFrame pending_ack_frame_;
QuicStopWaitingFrame pending_stop_waiting_frame_;
- // Stores the maximum packet size we are allowed to send. This might not be
- // the maximum size we are actually using now, if we are in the middle of the
- // packet.
- QuicByteCount max_packet_length_;
-
DISALLOW_COPY_AND_ASSIGN(QuicPacketGenerator);
};
diff --git a/chromium/net/quic/quic_packet_generator_test.cc b/chromium/net/quic/quic_packet_generator_test.cc
index 4bd81a791c5..0adbfe904d6 100644
--- a/chromium/net/quic/quic_packet_generator_test.cc
+++ b/chromium/net/quic/quic_packet_generator_test.cc
@@ -34,12 +34,6 @@ namespace net {
namespace test {
namespace {
-const int64_t kMinFecTimeoutMs = 5u;
-
-static const FecSendPolicy kFecSendPolicyList[] = {
- FEC_ANY_TRIGGER, FEC_ALARM_TRIGGER,
-};
-
class MockDelegate : public QuicPacketGenerator::DelegateInterface {
public:
MockDelegate() {}
@@ -48,11 +42,11 @@ class MockDelegate : public QuicPacketGenerator::DelegateInterface {
MOCK_METHOD2(ShouldGeneratePacket,
bool(HasRetransmittableData retransmittable,
IsHandshake handshake));
- MOCK_METHOD1(PopulateAckFrame, void(QuicAckFrame*));
+ MOCK_METHOD0(GetUpdatedAckFrame, const QuicFrame());
MOCK_METHOD1(PopulateStopWaitingFrame, void(QuicStopWaitingFrame*));
MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet));
- MOCK_METHOD2(CloseConnection, void(QuicErrorCode, bool));
- MOCK_METHOD0(OnResetFecGroup, void());
+ MOCK_METHOD3(OnUnrecoverableError,
+ void(QuicErrorCode, const string&, ConnectionCloseSource));
void SetCanWriteAnything() {
EXPECT_CALL(*this, ShouldGeneratePacket(_, _)).WillRepeatedly(Return(true));
@@ -91,8 +85,7 @@ struct PacketContents {
num_stop_waiting_frames(0),
num_stream_frames(0),
num_ping_frames(0),
- num_mtu_discovery_frames(0),
- fec_group(0) {}
+ num_mtu_discovery_frames(0) {}
size_t num_ack_frames;
size_t num_connection_close_frames;
@@ -102,13 +95,11 @@ struct PacketContents {
size_t num_stream_frames;
size_t num_ping_frames;
size_t num_mtu_discovery_frames;
-
- QuicFecGroupNumber fec_group;
};
} // namespace
-class QuicPacketGeneratorTest : public ::testing::TestWithParam<FecSendPolicy> {
+class QuicPacketGeneratorTest : public ::testing::Test {
public:
QuicPacketGeneratorTest()
: framer_(QuicSupportedVersions(),
@@ -116,24 +107,22 @@ class QuicPacketGeneratorTest : public ::testing::TestWithParam<FecSendPolicy> {
Perspective::IS_CLIENT),
generator_(42, &framer_, &random_, &buffer_allocator_, &delegate_),
creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)) {
- generator_.set_fec_send_policy(GetParam());
// TODO(ianswett): Fix this test so it uses a non-null encrypter.
FLAGS_quic_never_write_unencrypted_data = false;
- FLAGS_quic_no_unencrypted_fec = false;
}
~QuicPacketGeneratorTest() override {
for (SerializedPacket& packet : packets_) {
- delete packet.packet;
- delete packet.retransmittable_frames;
+ delete[] packet.encrypted_buffer;
+ QuicUtils::ClearSerializedPacket(&packet);
}
}
void SavePacket(SerializedPacket* packet) {
+ packet->encrypted_buffer = QuicUtils::CopyBuffer(*packet);
packets_.push_back(*packet);
- ASSERT_FALSE(packet->packet->owns_buffer());
- scoped_ptr<QuicEncryptedPacket> encrypted_deleter(packets_.back().packet);
- packets_.back().packet = packets_.back().packet->Clone();
+ packet->encrypted_buffer = nullptr;
+ packet->retransmittable_frames.clear();
}
protected:
@@ -158,15 +147,16 @@ class QuicPacketGeneratorTest : public ::testing::TestWithParam<FecSendPolicy> {
contents.num_mtu_discovery_frames + num_retransmittable_frames;
if (num_retransmittable_frames == 0) {
- ASSERT_TRUE(packet.retransmittable_frames == nullptr);
+ ASSERT_TRUE(packet.retransmittable_frames.empty());
} else {
- ASSERT_TRUE(packet.retransmittable_frames != nullptr);
+ ASSERT_FALSE(packet.retransmittable_frames.empty());
EXPECT_EQ(num_retransmittable_frames,
- packet.retransmittable_frames->frames().size());
+ packet.retransmittable_frames.size());
}
- ASSERT_TRUE(packet.packet != nullptr);
- ASSERT_TRUE(simple_framer_.ProcessPacket(*packet.packet));
+ ASSERT_TRUE(packet.encrypted_buffer != nullptr);
+ ASSERT_TRUE(simple_framer_.ProcessPacket(
+ QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length)));
EXPECT_EQ(num_frames, simple_framer_.num_frames());
EXPECT_EQ(contents.num_ack_frames, simple_framer_.ack_frames().size());
EXPECT_EQ(contents.num_connection_close_frames,
@@ -179,7 +169,6 @@ class QuicPacketGeneratorTest : public ::testing::TestWithParam<FecSendPolicy> {
simple_framer_.stream_frames().size());
EXPECT_EQ(contents.num_stop_waiting_frames,
simple_framer_.stop_waiting_frames().size());
- EXPECT_EQ(contents.fec_group, simple_framer_.header().fec_group);
// From the receiver's perspective, MTU discovery frames are ping frames.
EXPECT_EQ(contents.num_ping_frames + contents.num_mtu_discovery_frames,
@@ -189,10 +178,11 @@ class QuicPacketGeneratorTest : public ::testing::TestWithParam<FecSendPolicy> {
void CheckPacketHasSingleStreamFrame(size_t packet_index) {
ASSERT_GT(packets_.size(), packet_index);
const SerializedPacket& packet = packets_[packet_index];
- ASSERT_TRUE(packet.retransmittable_frames != nullptr);
- EXPECT_EQ(1u, packet.retransmittable_frames->frames().size());
- ASSERT_TRUE(packet.packet != nullptr);
- ASSERT_TRUE(simple_framer_.ProcessPacket(*packet.packet));
+ ASSERT_FALSE(packet.retransmittable_frames.empty());
+ EXPECT_EQ(1u, packet.retransmittable_frames.size());
+ ASSERT_TRUE(packet.encrypted_buffer != nullptr);
+ ASSERT_TRUE(simple_framer_.ProcessPacket(
+ QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length)));
EXPECT_EQ(1u, simple_framer_.num_frames());
EXPECT_EQ(1u, simple_framer_.stream_frames().size());
}
@@ -203,15 +193,6 @@ class QuicPacketGeneratorTest : public ::testing::TestWithParam<FecSendPolicy> {
}
}
- void CheckPacketIsFec(size_t packet_index, QuicPacketNumber fec_group) {
- ASSERT_GT(packets_.size(), packet_index);
- const SerializedPacket& packet = packets_[packet_index];
- ASSERT_TRUE(packet.retransmittable_frames == nullptr);
- ASSERT_TRUE(packet.packet != nullptr);
- ASSERT_TRUE(simple_framer_.ProcessPacket(*packet.packet));
- EXPECT_TRUE(simple_framer_.header().fec_flag);
- }
-
QuicIOVector CreateData(size_t len) {
data_array_.reset(new char[len]);
memset(data_array_.get(), '?', len);
@@ -232,6 +213,7 @@ class QuicPacketGeneratorTest : public ::testing::TestWithParam<FecSendPolicy> {
QuicPacketCreator* creator_;
SimpleQuicFramer simple_framer_;
vector<SerializedPacket> packets_;
+ QuicAckFrame ack_frame_;
private:
scoped_ptr<char[]> data_array_;
@@ -243,36 +225,33 @@ class MockDebugDelegate : public QuicPacketCreator::DebugDelegate {
MOCK_METHOD1(OnFrameAddedToPacket, void(const QuicFrame&));
};
-// Run all end to end tests with all supported FEC send polocies.
-INSTANTIATE_TEST_CASE_P(FecSendPolicy,
- QuicPacketGeneratorTest,
- ::testing::ValuesIn(kFecSendPolicyList));
-
-TEST_P(QuicPacketGeneratorTest, ShouldSendAck_NotWritable) {
+TEST_F(QuicPacketGeneratorTest, ShouldSendAck_NotWritable) {
delegate_.SetCanNotWrite();
generator_.SetShouldSendAck(false);
EXPECT_TRUE(generator_.HasQueuedFrames());
}
-TEST_P(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldNotFlush) {
+TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldNotFlush) {
StrictMock<MockDebugDelegate> debug_delegate;
generator_.set_debug_delegate(&debug_delegate);
delegate_.SetCanWriteOnlyNonRetransmittable();
generator_.StartBatchOperations();
- EXPECT_CALL(delegate_, PopulateAckFrame(_));
+ EXPECT_CALL(delegate_, GetUpdatedAckFrame())
+ .WillOnce(Return(QuicFrame(&ack_frame_)));
EXPECT_CALL(debug_delegate, OnFrameAddedToPacket(_)).Times(1);
generator_.SetShouldSendAck(false);
EXPECT_TRUE(generator_.HasQueuedFrames());
}
-TEST_P(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldFlush) {
+TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldFlush) {
delegate_.SetCanWriteOnlyNonRetransmittable();
- EXPECT_CALL(delegate_, PopulateAckFrame(_));
+ EXPECT_CALL(delegate_, GetUpdatedAckFrame())
+ .WillOnce(Return(QuicFrame(&ack_frame_)));
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
@@ -284,7 +263,7 @@ TEST_P(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldFlush) {
CheckPacketContains(contents, 0);
}
-TEST_P(QuicPacketGeneratorTest, ShouldSendAck_MultipleCalls) {
+TEST_F(QuicPacketGeneratorTest, ShouldSendAck_MultipleCalls) {
// Make sure that calling SetShouldSendAck multiple times does not result in a
// crash. Previously this would result in multiple QuicFrames queued in the
// packet generator, with all but the last with internal pointers to freed
@@ -292,7 +271,8 @@ TEST_P(QuicPacketGeneratorTest, ShouldSendAck_MultipleCalls) {
delegate_.SetCanWriteAnything();
// Only one AckFrame should be created.
- EXPECT_CALL(delegate_, PopulateAckFrame(_)).Times(1);
+ EXPECT_CALL(delegate_, GetUpdatedAckFrame())
+ .WillOnce(Return(QuicFrame(&ack_frame_)));
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.Times(1)
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
@@ -303,21 +283,21 @@ TEST_P(QuicPacketGeneratorTest, ShouldSendAck_MultipleCalls) {
generator_.FinishBatchOperations();
}
-TEST_P(QuicPacketGeneratorTest, AddControlFrame_NotWritable) {
+TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritable) {
delegate_.SetCanNotWrite();
generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()));
EXPECT_TRUE(generator_.HasQueuedFrames());
}
-TEST_P(QuicPacketGeneratorTest, AddControlFrame_OnlyAckWritable) {
+TEST_F(QuicPacketGeneratorTest, AddControlFrame_OnlyAckWritable) {
delegate_.SetCanWriteOnlyNonRetransmittable();
generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()));
EXPECT_TRUE(generator_.HasQueuedFrames());
}
-TEST_P(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) {
+TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) {
delegate_.SetCanWriteAnything();
generator_.StartBatchOperations();
@@ -325,7 +305,7 @@ TEST_P(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) {
EXPECT_TRUE(generator_.HasQueuedFrames());
}
-TEST_P(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) {
+TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) {
delegate_.SetCanNotWrite();
generator_.StartBatchOperations();
@@ -344,7 +324,7 @@ TEST_P(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) {
CheckPacketContains(contents, 0);
}
-TEST_P(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) {
+TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) {
delegate_.SetCanWriteAnything();
EXPECT_CALL(delegate_, OnSerializedPacket(_))
@@ -358,34 +338,34 @@ TEST_P(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) {
CheckPacketContains(contents, 0);
}
-TEST_P(QuicPacketGeneratorTest, ConsumeData_NotWritable) {
+TEST_F(QuicPacketGeneratorTest, ConsumeData_NotWritable) {
delegate_.SetCanNotWrite();
QuicConsumedData consumed = generator_.ConsumeData(
- kHeadersStreamId, MakeIOVector("foo"), 2, true, MAY_FEC_PROTECT, nullptr);
+ kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr);
EXPECT_EQ(0u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
}
-TEST_P(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) {
+TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) {
delegate_.SetCanWriteAnything();
generator_.StartBatchOperations();
QuicConsumedData consumed = generator_.ConsumeData(
- kHeadersStreamId, MakeIOVector("foo"), 2, true, MAY_FEC_PROTECT, nullptr);
+ kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
}
-TEST_P(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) {
+TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) {
delegate_.SetCanWriteAnything();
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
QuicConsumedData consumed = generator_.ConsumeData(
- kHeadersStreamId, MakeIOVector("foo"), 2, true, MAY_FEC_PROTECT, nullptr);
+ kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -398,14 +378,14 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) {
// Test the behavior of ConsumeData when the data consumed is for the crypto
// handshake stream. Ensure that the packet is always sent and padded even if
// the generator operates in batch mode.
-TEST_P(QuicPacketGeneratorTest, ConsumeData_Handshake) {
+TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake) {
delegate_.SetCanWriteAnything();
generator_.StartBatchOperations();
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
QuicConsumedData consumed = generator_.ConsumeData(
- kCryptoStreamId, MakeIOVector("foo"), 0, false, MAY_FEC_PROTECT, nullptr);
+ kCryptoStreamId, MakeIOVector("foo"), 0, false, nullptr);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -414,38 +394,38 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_Handshake) {
CheckPacketContains(contents, 0);
ASSERT_EQ(1u, packets_.size());
- ASSERT_EQ(kDefaultMaxPacketSize, generator_.GetMaxPacketLength());
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].packet->length());
+ ASSERT_EQ(kDefaultMaxPacketSize, generator_.GetCurrentMaxPacketLength());
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
}
-TEST_P(QuicPacketGeneratorTest, ConsumeData_EmptyData) {
+TEST_F(QuicPacketGeneratorTest, ConsumeData_EmptyData) {
EXPECT_DFATAL(generator_.ConsumeData(kHeadersStreamId, MakeIOVector(""), 0,
- false, MAY_FEC_PROTECT, nullptr),
+ false, nullptr),
"Attempt to consume empty data without FIN.");
}
-TEST_P(QuicPacketGeneratorTest,
+TEST_F(QuicPacketGeneratorTest,
ConsumeDataMultipleTimes_WritableAndShouldNotFlush) {
delegate_.SetCanWriteAnything();
generator_.StartBatchOperations();
generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 2, true,
- MAY_FEC_PROTECT, nullptr);
- QuicConsumedData consumed = generator_.ConsumeData(
- 3, MakeIOVector("quux"), 7, false, MAY_FEC_PROTECT, nullptr);
+ nullptr);
+ QuicConsumedData consumed =
+ generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, nullptr);
EXPECT_EQ(4u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
}
-TEST_P(QuicPacketGeneratorTest, ConsumeData_BatchOperations) {
+TEST_F(QuicPacketGeneratorTest, ConsumeData_BatchOperations) {
delegate_.SetCanWriteAnything();
generator_.StartBatchOperations();
generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 2, true,
- MAY_FEC_PROTECT, nullptr);
- QuicConsumedData consumed = generator_.ConsumeData(
- 3, MakeIOVector("quux"), 7, false, MAY_FEC_PROTECT, nullptr);
+ nullptr);
+ QuicConsumedData consumed =
+ generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, nullptr);
EXPECT_EQ(4u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -461,246 +441,19 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_BatchOperations) {
CheckPacketContains(contents, 0);
}
-TEST_P(QuicPacketGeneratorTest, ConsumeDataFecOnMaxGroupSize) {
- delegate_.SetCanWriteAnything();
-
- // Send FEC every two packets.
- creator_->set_max_packets_per_fec_group(2);
-
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER, but FEC
- // group is closed.
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
- } else {
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
-
- // Send enough data to create 3 packets: two full and one partial. Send with
- // MUST_FEC_PROTECT flag.
- size_t data_len = 2 * kDefaultMaxPacketSize + 100;
- QuicConsumedData consumed = generator_.ConsumeData(
- 3, CreateData(data_len), 0, true, MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasQueuedFrames());
-
- CheckPacketHasSingleStreamFrame(0);
- CheckPacketHasSingleStreamFrame(1);
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER.
- CheckPacketHasSingleStreamFrame(2);
- } else {
- CheckPacketIsFec(2, 1);
- CheckPacketHasSingleStreamFrame(3);
- }
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // If FEC send policy is FEC_ANY_TRIGGER, then the FEC packet under
- // construction will be sent when one more packet is sent (since FEC group
- // size is 2), or when OnFecTimeout is called. Send more data with
- // MAY_FEC_PROTECT. This packet should also be protected, and FEC packet is
- // sent since FEC group size is reached.
- //
- // If FEC send policy is FEC_ALARM_TRIGGER, FEC group is closed when the group
- // size is reached. FEC packet is not sent.
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
- } else {
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- }
- consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT,
- nullptr);
- EXPECT_EQ(1u, consumed.bytes_consumed);
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- CheckPacketHasSingleStreamFrame(3);
- } else {
- CheckPacketHasSingleStreamFrame(4);
- CheckPacketIsFec(5, 4);
- }
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-}
-
-TEST_P(QuicPacketGeneratorTest, ConsumeDataSendsFecOnTimeout) {
- delegate_.SetCanWriteAnything();
- creator_->set_max_packets_per_fec_group(1000);
-
- // Send data with MUST_FEC_PROTECT flag. No FEC packet is emitted, but the
- // creator FEC protects all data.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- QuicConsumedData consumed = generator_.ConsumeData(3, CreateData(1u), 0, true,
- MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(1u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- CheckPacketHasSingleStreamFrame(0);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Send more data with MAY_FEC_PROTECT. This packet should also be protected,
- // and FEC packet is not yet sent.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT,
- nullptr);
- EXPECT_EQ(1u, consumed.bytes_consumed);
- CheckPacketHasSingleStreamFrame(1);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Calling OnFecTimeout should cause the FEC packet to be emitted.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.OnFecTimeout();
- CheckPacketIsFec(2, 1);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Subsequent data is protected under the next FEC group. Send enough data to
- // create 2 more packets: one full and one partial.
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- size_t data_len = kDefaultMaxPacketSize + 1;
- consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true,
- MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- CheckPacketHasSingleStreamFrame(3);
- CheckPacketHasSingleStreamFrame(4);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Calling OnFecTimeout should cause the FEC packet to be emitted.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.OnFecTimeout();
- CheckPacketIsFec(5, 4);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-}
-
-TEST_P(QuicPacketGeneratorTest, GetFecTimeoutFiniteOnlyOnFirstPacketInGroup) {
- delegate_.SetCanWriteAnything();
- creator_->set_max_packets_per_fec_group(6);
-
- // Send enough data to create 2 packets: one full and one partial. Send with
- // MUST_FEC_PROTECT flag. No FEC packet is emitted yet, but the creator FEC
- // protects all data.
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- size_t data_len = 1 * kDefaultMaxPacketSize + 100;
- QuicConsumedData consumed = generator_.ConsumeData(
- 3, CreateData(data_len), 0, true, MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasQueuedFrames());
- CheckPacketHasSingleStreamFrame(0);
- CheckPacketHasSingleStreamFrame(1);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // GetFecTimeout returns finite timeout only for first packet in group.
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(kMinFecTimeoutMs),
- generator_.GetFecTimeout(/*packet_number=*/1u));
- EXPECT_EQ(QuicTime::Delta::Infinite(),
- generator_.GetFecTimeout(/*packet_number=*/2u));
-
- // Send more data with MAY_FEC_PROTECT. This packet should also be protected,
- // and FEC packet is not yet sent.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT,
- nullptr);
- CheckPacketHasSingleStreamFrame(2);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // GetFecTimeout returns finite timeout only for first packet in group.
- EXPECT_EQ(QuicTime::Delta::Infinite(),
- generator_.GetFecTimeout(/*packet_number=*/3u));
-
- // Calling OnFecTimeout should cause the FEC packet to be emitted.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.OnFecTimeout();
- CheckPacketIsFec(3, /*fec_group=*/1u);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Subsequent data is protected under the next FEC group. Send enough data to
- // create 2 more packets: one full and one partial.
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- data_len = kDefaultMaxPacketSize + 1u;
- consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true,
- MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- CheckPacketHasSingleStreamFrame(4);
- CheckPacketHasSingleStreamFrame(5);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // GetFecTimeout returns finite timeout for first packet in the new group.
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(kMinFecTimeoutMs),
- generator_.GetFecTimeout(/*packet_number=*/5u));
- EXPECT_EQ(QuicTime::Delta::Infinite(),
- generator_.GetFecTimeout(/*packet_number=*/6u));
-
- // Calling OnFecTimeout should cause the FEC packet to be emitted.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.OnFecTimeout();
- CheckPacketIsFec(6, /*fec_group=*/5u);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Send more data with MAY_FEC_PROTECT. No FEC protection, so GetFecTimeout
- // returns infinite.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- consumed = generator_.ConsumeData(9, CreateData(1u), 0, true, MAY_FEC_PROTECT,
- nullptr);
- CheckPacketHasSingleStreamFrame(7);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
- EXPECT_EQ(QuicTime::Delta::Infinite(),
- generator_.GetFecTimeout(/*packet_number=*/8u));
-}
-
-TEST_P(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
+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) +
GetPacketHeaderSize(
- creator_->connection_id_length(), true, /*include_path_id=*/false,
- QuicPacketCreatorPeer::NextPacketNumberLength(creator_),
- NOT_IN_FEC_GROUP) +
+ creator_->connection_id_length(), kIncludeVersion, !kIncludePathId,
+ QuicPacketCreatorPeer::NextPacketNumberLength(creator_)) +
// Add an extra 3 bytes for the payload and 1 byte so BytesFree is larger
// than the GetMinStreamFrameSize.
- QuicFramer::GetMinStreamFrameSize(1, 0, false, NOT_IN_FEC_GROUP) + 3 +
- QuicFramer::GetMinStreamFrameSize(1, 0, true, NOT_IN_FEC_GROUP) + 1;
- generator_.SetMaxPacketLength(length, /*force=*/false);
+ QuicFramer::GetMinStreamFrameSize(1, 0, false) + 3 +
+ QuicFramer::GetMinStreamFrameSize(1, 0, true) + 1;
+ generator_.SetMaxPacketLength(length);
delegate_.SetCanWriteAnything();
{
InSequence dummy;
@@ -712,9 +465,8 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
generator_.StartBatchOperations();
// Queue enough data to prevent a stream frame with a non-zero offset from
// fitting.
- QuicConsumedData consumed =
- generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 0, false,
- MAY_FEC_PROTECT, nullptr);
+ QuicConsumedData consumed = generator_.ConsumeData(
+ kHeadersStreamId, MakeIOVector("foo"), 0, false, nullptr);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -722,7 +474,7 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
// 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, MAY_FEC_PROTECT, nullptr);
+ true, nullptr);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -736,554 +488,7 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
CheckPacketContains(contents, 1);
}
-TEST_P(QuicPacketGeneratorTest, NoFecPacketSentWhenBatchEnds) {
- delegate_.SetCanWriteAnything();
- creator_->set_max_packets_per_fec_group(6);
-
- generator_.StartBatchOperations();
-
- generator_.ConsumeData(3, MakeIOVector("foo"), 2, true, MUST_FEC_PROTECT,
- nullptr);
- QuicConsumedData consumed = generator_.ConsumeData(
- 5, MakeIOVector("quux"), 7, false, MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(4u, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasQueuedFrames());
-
- // Now both frames will be flushed out, but FEC packet is not yet sent.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.FinishBatchOperations();
- EXPECT_FALSE(generator_.HasQueuedFrames());
-
- PacketContents contents;
- contents.num_stream_frames = 2u;
- contents.fec_group = 1u;
- CheckPacketContains(contents, 0);
-
- // Forcing FEC timeout causes FEC packet to be emitted.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.OnFecTimeout();
- CheckPacketIsFec(1, /*fec_group=*/1u);
-}
-
-TEST_P(QuicPacketGeneratorTest, FecTimeoutOnRttChange) {
- EXPECT_EQ(QuicTime::Delta::Zero(),
- QuicPacketCreatorPeer::GetFecTimeout(creator_));
- generator_.OnRttChange(QuicTime::Delta::FromMilliseconds(300));
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(150),
- QuicPacketCreatorPeer::GetFecTimeout(creator_));
-}
-
-TEST_P(QuicPacketGeneratorTest, FecGroupSizeOnCongestionWindowChange) {
- delegate_.SetCanWriteAnything();
- creator_->set_max_packets_per_fec_group(50);
- EXPECT_EQ(50u, creator_->max_packets_per_fec_group());
- EXPECT_FALSE(creator_->IsFecGroupOpen());
-
- // On reduced cwnd.
- generator_.OnCongestionWindowChange(7);
- EXPECT_EQ(3u, creator_->max_packets_per_fec_group());
-
- // On increased cwnd.
- generator_.OnCongestionWindowChange(100);
- EXPECT_EQ(50u, creator_->max_packets_per_fec_group());
-
- // On collapsed cwnd.
- generator_.OnCongestionWindowChange(1);
- EXPECT_EQ(2u, creator_->max_packets_per_fec_group());
-}
-
-TEST_P(QuicPacketGeneratorTest, FecGroupSizeChangeWithOpenGroup) {
- delegate_.SetCanWriteAnything();
- generator_.StartBatchOperations();
- creator_->set_max_packets_per_fec_group(50);
- EXPECT_EQ(50u, creator_->max_packets_per_fec_group());
- EXPECT_FALSE(creator_->IsFecGroupOpen());
-
- // Send enough data to create 4 packets with MUST_FEC_PROTECT flag. 3 packets
- // are sent, one is queued in the creator.
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- size_t data_len = 3 * kDefaultMaxPacketSize + 1;
- QuicConsumedData consumed = generator_.ConsumeData(
- 7, CreateData(data_len), 0, true, MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(creator_->IsFecGroupOpen());
-
- // Change FEC groupsize.
- generator_.OnCongestionWindowChange(2);
- EXPECT_EQ(2u, creator_->max_packets_per_fec_group());
-
- // If FEC send policy is FEC_ANY_TRIGGER, then send enough data to trigger one
- // unprotected data packet, causing the FEC packet to also be sent.
- //
- // If FEC send policy is FEC_ALARM_TRIGGER, FEC group is closed and FEC packet
- // is not sent.
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
- } else {
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- }
- consumed = generator_.ConsumeData(7, CreateData(kDefaultMaxPacketSize), 0,
- true, MAY_FEC_PROTECT, nullptr);
- EXPECT_EQ(kDefaultMaxPacketSize, consumed.bytes_consumed);
- if (generator_.fec_send_policy() == FEC_ANY_TRIGGER) {
- // Verify that one FEC packet was sent.
- CheckPacketIsFec(4, /*fec_group=*/1u);
- }
- EXPECT_FALSE(creator_->IsFecGroupOpen());
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-}
-
-TEST_P(QuicPacketGeneratorTest, SwitchFecOnOff) {
- delegate_.SetCanWriteAnything();
- creator_->set_max_packets_per_fec_group(2);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Send one unprotected data packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- QuicConsumedData consumed = generator_.ConsumeData(5, CreateData(1u), 0, true,
- MAY_FEC_PROTECT, nullptr);
- EXPECT_EQ(1u, consumed.bytes_consumed);
- EXPECT_FALSE(generator_.HasQueuedFrames());
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
- // Verify that one data packet was sent.
- PacketContents contents;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
-
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- // If FEC send policy is FEC_ALARM_TRIGGER, FEC group is closed.
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
- } else {
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- // Send enough data to create 3 packets with MUST_FEC_PROTECT flag.
- size_t data_len = 2 * kDefaultMaxPacketSize + 100;
- consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true,
- MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_FALSE(generator_.HasQueuedFrames());
-
- // If FEC send policy is FEC_ANY_TRIGGER, verify that packets sent were 3 data
- // and 1 FEC.
- //
- // If FEC send policy is FEC_ALARM_TRIGGER, verify that packets sent were 3
- // data and FEC group is closed.
- CheckPacketHasSingleStreamFrame(1);
- CheckPacketHasSingleStreamFrame(2);
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- CheckPacketHasSingleStreamFrame(3);
- } else {
- CheckPacketIsFec(3, /*fec_group=*/2u);
- CheckPacketHasSingleStreamFrame(4);
- }
-
- // Calling OnFecTimeout should emit the pending FEC packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.OnFecTimeout();
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- CheckPacketIsFec(4, /*fec_group=*/4u);
- } else {
- CheckPacketIsFec(5, /*fec_group=*/5u);
- }
-
- // Send one unprotected data packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- consumed = generator_.ConsumeData(7, CreateData(1u), 0, true, MAY_FEC_PROTECT,
- nullptr);
- EXPECT_EQ(1u, consumed.bytes_consumed);
- EXPECT_FALSE(generator_.HasQueuedFrames());
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
- // Verify that one unprotected data packet was sent.
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- CheckPacketContains(contents, 5);
- } else {
- CheckPacketContains(contents, 6);
- }
-}
-
-TEST_P(QuicPacketGeneratorTest, SwitchFecOnWithPendingFrameInCreator) {
- delegate_.SetCanWriteAnything();
- // Enable FEC.
- creator_->set_max_packets_per_fec_group(2);
-
- generator_.StartBatchOperations();
- // Queue enough data to prevent a stream frame with a non-zero offset from
- // fitting.
- QuicConsumedData consumed = generator_.ConsumeData(7, CreateData(1u), 0, true,
- MAY_FEC_PROTECT, nullptr);
- EXPECT_EQ(1u, consumed.bytes_consumed);
- EXPECT_TRUE(creator_->HasPendingFrames());
-
- // Queue protected data for sending. Should cause queued frames to be flushed.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
- consumed = generator_.ConsumeData(7, CreateData(1u), 0, true,
- MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(1u, consumed.bytes_consumed);
- PacketContents contents;
- contents.num_stream_frames = 1;
- // Transmitted packet was not FEC protected.
- CheckPacketContains(contents, 0);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
- EXPECT_TRUE(creator_->HasPendingFrames());
-}
-
-TEST_P(QuicPacketGeneratorTest, SwitchFecOnWithPendingFramesInGenerator) {
- // Enable FEC.
- creator_->set_max_packets_per_fec_group(2);
-
- // Queue control frames in generator.
- delegate_.SetCanNotWrite();
- generator_.SetShouldSendAck(true);
- delegate_.SetCanWriteAnything();
- generator_.StartBatchOperations();
-
- // Set up frames to write into the creator when control frames are written.
- EXPECT_CALL(delegate_, PopulateAckFrame(_));
- EXPECT_CALL(delegate_, PopulateStopWaitingFrame(_));
-
- // Generator should have queued control frames, and creator should be empty.
- EXPECT_TRUE(generator_.HasQueuedFrames());
- EXPECT_FALSE(creator_->HasPendingFrames());
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Queue protected data for sending. Should cause queued frames to be flushed.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- QuicConsumedData consumed = generator_.ConsumeData(7, CreateData(1u), 0, true,
- MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(1u, consumed.bytes_consumed);
- PacketContents contents;
- contents.num_ack_frames = 1;
- contents.num_stop_waiting_frames = 1;
- CheckPacketContains(contents, 0);
-
- // FEC protection should be on in creator.
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-}
-
-TEST_P(QuicPacketGeneratorTest, SwitchFecOnOffWithSubsequentFramesProtected) {
- delegate_.SetCanWriteAnything();
-
- // Enable FEC.
- creator_->set_max_packets_per_fec_group(2);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Queue stream frame to be protected in creator.
- generator_.StartBatchOperations();
- QuicConsumedData consumed = generator_.ConsumeData(5, CreateData(1u), 0, true,
- MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(1u, consumed.bytes_consumed);
- // Creator has a pending protected frame.
- EXPECT_TRUE(creator_->HasPendingFrames());
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Add enough unprotected data to exceed size of current packet, so that
- // current packet is sent. Both frames will be sent out in a single packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- size_t data_len = kDefaultMaxPacketSize;
- consumed = generator_.ConsumeData(5, CreateData(data_len), 0, true,
- MAY_FEC_PROTECT, nullptr);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- PacketContents contents;
- contents.num_stream_frames = 2u;
- contents.fec_group = 1u;
- CheckPacketContains(contents, 0);
- // FEC protection should still be on in creator.
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-}
-
-TEST_P(QuicPacketGeneratorTest, SwitchFecOnOffWithSubsequentPacketsProtected) {
- delegate_.SetCanWriteAnything();
-
- // Enable FEC.
- creator_->set_max_packets_per_fec_group(2);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Send first packet, FEC protected.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- QuicConsumedData consumed = generator_.ConsumeData(5, CreateData(1u), 0, true,
- MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(1u, consumed.bytes_consumed);
- PacketContents contents;
- contents.num_stream_frames = 1u;
- contents.fec_group = 1u;
- CheckPacketContains(contents, 0);
-
- // FEC should still be on in creator.
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Send unprotected data to cause second packet to be sent, which gets
- // protected because it happens to fall within an open FEC group. Data packet
- // will be followed by FEC packet.
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
- } else {
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- }
- consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT,
- nullptr);
- EXPECT_EQ(1u, consumed.bytes_consumed);
- contents.num_stream_frames = 1u;
- CheckPacketContains(contents, 1);
- if (generator_.fec_send_policy() == FEC_ANY_TRIGGER) {
- // FEC packet is sent when send policy is FEC_ANY_TRIGGER.
- CheckPacketIsFec(2, /*fec_group=*/1u);
- }
-
- // FEC protection should be off in creator.
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-}
-
-TEST_P(QuicPacketGeneratorTest, SwitchFecOnOffThenOnWithCreatorProtectionOn) {
- delegate_.SetCanWriteAnything();
- generator_.StartBatchOperations();
-
- // Enable FEC.
- creator_->set_max_packets_per_fec_group(2);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Queue one byte of FEC protected data.
- QuicConsumedData consumed = generator_.ConsumeData(5, CreateData(1u), 0, true,
- MUST_FEC_PROTECT, nullptr);
- EXPECT_TRUE(creator_->HasPendingFrames());
-
- // Add more unprotected data causing first packet to be sent, FEC protected.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- size_t data_len = kDefaultMaxPacketSize;
- consumed = generator_.ConsumeData(5, CreateData(data_len), 0, true,
- MAY_FEC_PROTECT, nullptr);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- PacketContents contents;
- contents.num_stream_frames = 2u;
- contents.fec_group = 1u;
- CheckPacketContains(contents, 0);
-
- // FEC group is still open in creator.
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Add data that should be protected, large enough to cause second packet to
- // be sent. Data packet should be followed by FEC packet.
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
- } else {
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- }
- consumed = generator_.ConsumeData(5, CreateData(data_len), 0, true,
- MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- CheckPacketContains(contents, 1);
- if (generator_.fec_send_policy() == FEC_ANY_TRIGGER) {
- // FEC packet is sent when send policy is FEC_ANY_TRIGGER.
- CheckPacketIsFec(2, /*fec_group=*/1u);
- }
-
- // FEC protection should remain on in creator.
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-}
-
-TEST_P(QuicPacketGeneratorTest, ResetFecGroupNoTimeout) {
- delegate_.SetCanWriteAnything();
- // Send FEC packet after 2 packets.
- creator_->set_max_packets_per_fec_group(2);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Send two packets so that when this data is consumed, two packets are sent
- // out. In FEC_TRIGGER_ANY, this will cause an FEC packet to be sent out and
- // with FEC_TRIGGER_ALARM, this will cause a Reset to be called. In both
- // cases, the creator's fec protection will be turned off afterwards.
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER, but FEC
- // group is closed.
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
- } else {
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- // Fin Packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- size_t data_len = 2 * kDefaultMaxPacketSize;
- QuicConsumedData consumed = generator_.ConsumeData(
- 5, CreateData(data_len), 0, true, MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasQueuedFrames());
- CheckPacketHasSingleStreamFrame(0);
- CheckPacketHasSingleStreamFrame(1);
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER.
- CheckPacketHasSingleStreamFrame(2);
- } else {
- // FEC packet is sent after 2 packets and when send policy is
- // FEC_ANY_TRIGGER.
- CheckPacketIsFec(2, 1);
- CheckPacketHasSingleStreamFrame(3);
- }
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Do the same send (with MUST_FEC_PROTECT) on a different stream id.
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- // FEC packet is sent after 2 packets and when send policy is
- // FEC_ANY_TRIGGER. When policy is FEC_ALARM_TRIGGER, FEC group is closed
- // and FEC packet is not sent.
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
- } else {
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- // FEC packet is sent after 2 packets and when send policy is
- // FEC_ANY_TRIGGER. When policy is FEC_ALARM_TRIGGER, FEC group is closed
- // and FEC packet is not sent.
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
- } else {
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- }
- consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true,
- MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasQueuedFrames());
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- CheckPacketHasSingleStreamFrame(3);
- CheckPacketHasSingleStreamFrame(4);
- CheckPacketHasSingleStreamFrame(5);
- } else {
- CheckPacketHasSingleStreamFrame(4);
- // FEC packet is sent after 2 packets and when send policy is
- // FEC_ANY_TRIGGER.
- CheckPacketIsFec(5, 4);
- CheckPacketHasSingleStreamFrame(6);
- CheckPacketHasSingleStreamFrame(7);
- // FEC packet is sent after 2 packets and when send policy is
- // FEC_ANY_TRIGGER.
- CheckPacketIsFec(8, 7);
- }
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Do the another send (with MAY_FEC_PROTECT) on a different stream id, which
- // should not produce an FEC packet because the last FEC group has been
- // closed.
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- consumed = generator_.ConsumeData(9, CreateData(data_len), 0, true,
- MAY_FEC_PROTECT, nullptr);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasQueuedFrames());
- if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) {
- CheckPacketHasSingleStreamFrame(6);
- CheckPacketHasSingleStreamFrame(7);
- CheckPacketHasSingleStreamFrame(8);
- } else {
- CheckPacketHasSingleStreamFrame(9);
- CheckPacketHasSingleStreamFrame(10);
- CheckPacketHasSingleStreamFrame(11);
- }
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-}
-
-// 1. Create and send one packet with MUST_FEC_PROTECT.
-// 2. Call FecTimeout, expect FEC packet is sent.
-// 3. Do the same thing over again, with a different stream id.
-TEST_P(QuicPacketGeneratorTest, FecPacketSentOnFecTimeout) {
- delegate_.SetCanWriteAnything();
- creator_->set_max_packets_per_fec_group(1000);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- for (int i = 1; i < 4; i = i + 2) {
- // Send data with MUST_FEC_PROTECT flag. No FEC packet is emitted, but the
- // creator FEC protects all data.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- QuicConsumedData consumed = generator_.ConsumeData(
- i + 2, CreateData(1u), 0, true, MUST_FEC_PROTECT, nullptr);
- EXPECT_EQ(1u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- CheckPacketHasSingleStreamFrame(0);
- EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_));
-
- // Calling OnFecTimeout should cause the FEC packet to be emitted.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.OnFecTimeout();
- CheckPacketIsFec(i, i);
- EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_));
- }
-}
-
-TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
+TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
delegate_.SetCanNotWrite();
generator_.SetShouldSendAck(false);
@@ -1295,11 +500,11 @@ TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
generator_.StartBatchOperations();
// When the first write operation is invoked, the ack frame will be returned.
- EXPECT_CALL(delegate_, PopulateAckFrame(_));
+ EXPECT_CALL(delegate_, GetUpdatedAckFrame())
+ .WillOnce(Return(QuicFrame(&ack_frame_)));
// Send some data and a control frame
- generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, MAY_FEC_PROTECT,
- nullptr);
+ generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, nullptr);
generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()));
// All five frames will be flushed out in a single packet.
@@ -1316,7 +521,7 @@ TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
CheckPacketContains(contents, 0);
}
-TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
+TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
delegate_.SetCanNotWrite();
generator_.SetShouldSendAck(false);
@@ -1328,7 +533,8 @@ TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
generator_.StartBatchOperations();
// When the first write operation is invoked, the ack frame will be returned.
- EXPECT_CALL(delegate_, PopulateAckFrame(_));
+ EXPECT_CALL(delegate_, GetUpdatedAckFrame())
+ .WillOnce(Return(QuicFrame(&ack_frame_)));
{
InSequence dummy;
@@ -1341,8 +547,8 @@ TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
// Send enough data to exceed one packet
size_t data_len = kDefaultMaxPacketSize + 100;
- QuicConsumedData consumed = generator_.ConsumeData(
- 3, CreateData(data_len), 0, true, MAY_FEC_PROTECT, nullptr);
+ QuicConsumedData consumed =
+ generator_.ConsumeData(3, CreateData(data_len), 0, true, nullptr);
EXPECT_EQ(data_len, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()));
@@ -1364,7 +570,7 @@ TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
CheckPacketContains(contents2, 1);
}
-TEST_P(QuicPacketGeneratorTest, TestConnectionIdLength) {
+TEST_F(QuicPacketGeneratorTest, TestConnectionIdLength) {
generator_.SetConnectionIdLength(0);
EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID, creator_->connection_id_length());
generator_.SetConnectionIdLength(1);
@@ -1389,14 +595,14 @@ TEST_P(QuicPacketGeneratorTest, TestConnectionIdLength) {
// Test whether SetMaxPacketLength() works in the situation when the queue is
// empty, and we send three packets worth of data.
-TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Initial) {
+TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Initial) {
delegate_.SetCanWriteAnything();
// Send enough data for three packets.
size_t data_len = 3 * kDefaultMaxPacketSize + 1;
size_t packet_len = kDefaultMaxPacketSize + 100;
ASSERT_LE(packet_len, kMaxPacketSize);
- generator_.SetMaxPacketLength(packet_len, /*force=*/false);
+ generator_.SetMaxPacketLength(packet_len);
EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength());
EXPECT_CALL(delegate_, OnSerializedPacket(_))
@@ -1405,7 +611,7 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Initial) {
QuicConsumedData consumed =
generator_.ConsumeData(kHeadersStreamId, CreateData(data_len),
/*offset=*/2,
- /*fin=*/true, MAY_FEC_PROTECT, nullptr);
+ /*fin=*/true, nullptr);
EXPECT_EQ(data_len, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -1415,14 +621,14 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Initial) {
// ensure that |max_packet_length_| does not get changed incorrectly by the
// generator after first packet is serialized.
ASSERT_EQ(3u, packets_.size());
- EXPECT_EQ(packet_len, packets_[0].packet->length());
- EXPECT_EQ(packet_len, packets_[1].packet->length());
+ EXPECT_EQ(packet_len, packets_[0].encrypted_length);
+ EXPECT_EQ(packet_len, packets_[1].encrypted_length);
CheckAllPacketsHaveSingleStreamFrame();
}
// Test whether SetMaxPacketLength() works in the situation when we first write
// data, then change packet size, then write data again.
-TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) {
+TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) {
delegate_.SetCanWriteAnything();
// We send enough data to overflow default packet length, but not the altered
@@ -1440,7 +646,7 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) {
QuicConsumedData consumed =
generator_.ConsumeData(kHeadersStreamId, CreateData(data_len),
/*offset=*/2,
- /*fin=*/false, MAY_FEC_PROTECT, nullptr);
+ /*fin=*/false, nullptr);
EXPECT_EQ(data_len, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -1449,13 +655,13 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) {
ASSERT_EQ(2u, packets_.size());
// Increase packet size.
- generator_.SetMaxPacketLength(packet_len, /*force=*/false);
+ generator_.SetMaxPacketLength(packet_len);
EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength());
// Send a packet after packet size change.
consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len),
2 + data_len,
- /*fin=*/true, MAY_FEC_PROTECT, nullptr);
+ /*fin=*/true, nullptr);
EXPECT_EQ(data_len, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -1463,68 +669,14 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) {
// We expect first data chunk to get fragmented, but the second one to fit
// into a single packet.
ASSERT_EQ(3u, packets_.size());
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].packet->length());
- EXPECT_LE(kDefaultMaxPacketSize, packets_[2].packet->length());
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
+ EXPECT_LE(kDefaultMaxPacketSize, packets_[2].encrypted_length);
CheckAllPacketsHaveSingleStreamFrame();
}
-// Test whether SetMaxPacketLength() works correctly when we change the packet
-// size in the middle of the batched packet.
-TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Midpacket) {
- delegate_.SetCanWriteAnything();
- generator_.StartBatchOperations();
-
- size_t first_write_len = kDefaultMaxPacketSize / 2;
- size_t second_write_len = kDefaultMaxPacketSize;
- size_t packet_len = kDefaultMaxPacketSize + 100;
- ASSERT_LE(packet_len, kMaxPacketSize);
-
- // First send half of the packet worth of data. We are in the batch mode, so
- // should not cause packet serialization.
- QuicConsumedData consumed =
- generator_.ConsumeData(kHeadersStreamId, CreateData(first_write_len),
- /*offset=*/2,
- /*fin=*/false, MAY_FEC_PROTECT, nullptr);
- EXPECT_EQ(first_write_len, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasQueuedFrames());
-
- // Make sure we have no packets so far.
- ASSERT_EQ(0u, packets_.size());
-
- // Increase packet size. Ensure it's not immediately enacted.
- generator_.SetMaxPacketLength(packet_len, /*force=*/false);
- EXPECT_EQ(packet_len, generator_.GetMaxPacketLength());
- EXPECT_EQ(kDefaultMaxPacketSize, generator_.GetCurrentMaxPacketLength());
-
- // We expect to see exactly one packet serialized after that, since we are in
- // batch mode and we have sent approximately 3/2 of our MTU.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- // Send a packet worth of data to the same stream. This should trigger
- // serialization of other packet.
- consumed =
- generator_.ConsumeData(kHeadersStreamId, CreateData(second_write_len),
- /*offset=*/2 + first_write_len,
- /*fin=*/true, MAY_FEC_PROTECT, nullptr);
- EXPECT_EQ(second_write_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasQueuedFrames());
-
- // We expect the first packet to contain two frames, and to not reflect the
- // packet size change.
- ASSERT_EQ(1u, packets_.size());
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].packet->length());
-
- PacketContents contents;
- contents.num_stream_frames = 2;
- CheckPacketContains(contents, 0);
-}
-
// Test whether SetMaxPacketLength() works correctly when we force the change of
// the packet size in the middle of the batched packet.
-TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) {
+TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) {
delegate_.SetCanWriteAnything();
generator_.StartBatchOperations();
@@ -1538,7 +690,7 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) {
QuicConsumedData consumed =
generator_.ConsumeData(kHeadersStreamId, CreateData(first_write_len),
/*offset=*/2,
- /*fin=*/false, MAY_FEC_PROTECT, nullptr);
+ /*fin=*/false, nullptr);
EXPECT_EQ(first_write_len, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -1550,9 +702,10 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- // Increase packet size. Ensure it's immediately enacted.
- generator_.SetMaxPacketLength(packet_len, /*force=*/true);
- EXPECT_EQ(packet_len, generator_.GetMaxPacketLength());
+ // Increase packet size after flushing all frames.
+ // Ensure it's immediately enacted.
+ generator_.FlushAllQueuedFrames();
+ generator_.SetMaxPacketLength(packet_len);
EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength());
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -1567,7 +720,7 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) {
consumed =
generator_.ConsumeData(kHeadersStreamId, CreateData(second_write_len),
/*offset=*/2 + first_write_len,
- /*fin=*/true, MAY_FEC_PROTECT, nullptr);
+ /*fin=*/true, nullptr);
EXPECT_EQ(second_write_len, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -1575,14 +728,14 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) {
// We expect the first packet to be underfilled, and the second packet be up
// to the new max packet size.
ASSERT_EQ(2u, packets_.size());
- EXPECT_GT(kDefaultMaxPacketSize, packets_[0].packet->length());
- EXPECT_EQ(packet_len, packets_[1].packet->length());
+ EXPECT_GT(kDefaultMaxPacketSize, packets_[0].encrypted_length);
+ EXPECT_EQ(packet_len, packets_[1].encrypted_length);
CheckAllPacketsHaveSingleStreamFrame();
}
// Test sending an MTU probe, without any surrounding data.
-TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_Simple) {
+TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_Simple) {
delegate_.SetCanWriteAnything();
const size_t target_mtu = kDefaultMaxPacketSize + 100;
@@ -1596,7 +749,7 @@ TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_Simple) {
EXPECT_FALSE(generator_.HasQueuedFrames());
ASSERT_EQ(1u, packets_.size());
- EXPECT_EQ(target_mtu, packets_[0].packet->length());
+ EXPECT_EQ(target_mtu, packets_[0].encrypted_length);
PacketContents contents;
contents.num_mtu_discovery_frames = 1;
@@ -1605,7 +758,7 @@ TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_Simple) {
// Test sending an MTU probe. Surround it with data, to ensure that it resets
// the MTU to the value before the probe was sent.
-TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) {
+TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) {
delegate_.SetCanWriteAnything();
const size_t target_mtu = kDefaultMaxPacketSize + 100;
@@ -1625,7 +778,7 @@ TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) {
QuicConsumedData consumed =
generator_.ConsumeData(kHeadersStreamId, CreateData(data_len),
/*offset=*/2,
- /*fin=*/false, MAY_FEC_PROTECT, nullptr);
+ /*fin=*/false, nullptr);
EXPECT_EQ(data_len, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -1637,15 +790,15 @@ TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) {
// Send data after the MTU probe.
consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len),
/*offset=*/2 + data_len,
- /*fin=*/true, MAY_FEC_PROTECT, nullptr);
+ /*fin=*/true, nullptr);
EXPECT_EQ(data_len, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
ASSERT_EQ(5u, packets_.size());
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].packet->length());
- EXPECT_EQ(target_mtu, packets_[2].packet->length());
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[3].packet->length());
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
+ EXPECT_EQ(target_mtu, packets_[2].encrypted_length);
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[3].encrypted_length);
PacketContents probe_contents;
probe_contents.num_mtu_discovery_frames = 1;
@@ -1657,7 +810,7 @@ TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) {
CheckPacketHasSingleStreamFrame(4);
}
-TEST_P(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) {
+TEST_F(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) {
// Test added to ensure the generator does not crash when an invalid frame is
// added. Because this is an indication of internal programming errors,
// DFATALs are expected.
@@ -1670,7 +823,8 @@ TEST_P(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) {
generator_.StartBatchOperations();
// Set up frames to write into the creator when control frames are written.
- EXPECT_CALL(delegate_, PopulateAckFrame(_));
+ EXPECT_CALL(delegate_, GetUpdatedAckFrame())
+ .WillOnce(Return(QuicFrame(&ack_frame_)));
EXPECT_CALL(delegate_, PopulateStopWaitingFrame(_));
// Generator should have queued control frames, and creator should be empty.
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -1678,18 +832,19 @@ TEST_P(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) {
// This will not serialize any packets, because of the invalid frame.
EXPECT_CALL(delegate_,
- CloseConnection(QUIC_FAILED_TO_SERIALIZE_PACKET, false));
+ OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET, _,
+ ConnectionCloseSource::FROM_SELF));
EXPECT_DFATAL(generator_.FinishBatchOperations(),
"packet_number_length 1 is too small "
"for least_unacked_delta: 1001");
}
-TEST_P(QuicPacketGeneratorTest, SetCurrentPath) {
+TEST_F(QuicPacketGeneratorTest, SetCurrentPath) {
delegate_.SetCanWriteAnything();
generator_.StartBatchOperations();
QuicConsumedData consumed = generator_.ConsumeData(
- kHeadersStreamId, MakeIOVector("foo"), 2, true, MAY_FEC_PROTECT, nullptr);
+ kHeadersStreamId, MakeIOVector("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/quic_packet_writer.h b/chromium/net/quic/quic_packet_writer.h
index 4c9963adc0c..de6804b9f72 100644
--- a/chromium/net/quic/quic_packet_writer.h
+++ b/chromium/net/quic/quic_packet_writer.h
@@ -12,8 +12,24 @@
namespace net {
+class IPAddress;
struct WriteResult;
+class NET_EXPORT_PRIVATE PerPacketOptions {
+ public:
+ PerPacketOptions() = default;
+ virtual ~PerPacketOptions() {}
+
+ // Returns a heap-allocated copy of |this|.
+ virtual PerPacketOptions* Clone() const = 0;
+
+ private:
+ PerPacketOptions(PerPacketOptions&& other) = delete;
+ PerPacketOptions& operator=(PerPacketOptions&& other) = delete;
+
+ DISALLOW_COPY_AND_ASSIGN(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.
@@ -21,14 +37,17 @@ class NET_EXPORT_PRIVATE QuicPacketWriter {
public:
virtual ~QuicPacketWriter() {}
- // Sends the packet out to the peer. If the write succeeded, the result's
- // status is WRITE_STATUS_OK and bytes_written is populated. If the write
- // failed, the result's status is WRITE_STATUS_BLOCKED or WRITE_STATUS_ERROR
- // and error_code is populated.
+ // Sends the packet out to the peer, with some optional per-packet options.
+ // If the write succeeded, the result's status is WRITE_STATUS_OK and
+ // bytes_written is populated. If the write failed, the result's status is
+ // WRITE_STATUS_BLOCKED or WRITE_STATUS_ERROR and error_code is populated.
+ // Options must be either null, or created for the particular QuicPacketWriter
+ // implementation. Options may be ignored, depending on the implementation.
virtual WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) = 0;
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) = 0;
// Returns true if the writer buffers and subsequently rewrites data
// when an attempt to write results in the underlying socket becoming
diff --git a/chromium/net/quic/quic_protocol.cc b/chromium/net/quic/quic_protocol.cc
index a5fb29cf2dd..2da013e829e 100644
--- a/chromium/net/quic/quic_protocol.cc
+++ b/chromium/net/quic/quic_protocol.cc
@@ -19,39 +19,33 @@ namespace net {
const char* const kFinalOffsetHeaderKey = ":final-offset";
size_t GetPacketHeaderSize(const QuicPacketHeader& header) {
- return GetPacketHeaderSize(
- header.public_header.connection_id_length,
- header.public_header.version_flag, header.public_header.multipath_flag,
- header.public_header.packet_number_length, header.is_in_fec_group);
+ return GetPacketHeaderSize(header.public_header.connection_id_length,
+ header.public_header.version_flag,
+ header.public_header.multipath_flag,
+ header.public_header.packet_number_length);
}
size_t GetPacketHeaderSize(QuicConnectionIdLength connection_id_length,
bool include_version,
bool include_path_id,
- QuicPacketNumberLength packet_number_length,
- InFecGroup is_in_fec_group) {
+ QuicPacketNumberLength packet_number_length) {
return kPublicFlagsSize + connection_id_length +
(include_version ? kQuicVersionSize : 0) +
(include_path_id ? kQuicPathIdSize : 0) + packet_number_length +
- kPrivateFlagsSize +
- (is_in_fec_group == IN_FEC_GROUP ? kFecGroupSize : 0);
+ kPrivateFlagsSize;
}
-size_t GetStartOfFecProtectedData(QuicConnectionIdLength connection_id_length,
- bool include_version,
- QuicPacketNumberLength packet_number_length) {
- return GetPacketHeaderSize(connection_id_length, include_version,
- /*include_path_id=*/false, packet_number_length,
- IN_FEC_GROUP);
+size_t GetStartOfEncryptedData(const QuicPacketHeader& header) {
+ return GetPacketHeaderSize(header) - kPrivateFlagsSize;
}
size_t GetStartOfEncryptedData(QuicConnectionIdLength connection_id_length,
bool include_version,
+ bool include_path_id,
QuicPacketNumberLength packet_number_length) {
- // Don't include the fec size, since encryption starts before private flags.
+ // Encryption starts before private flags.
return GetPacketHeaderSize(connection_id_length, include_version,
- /*include_path_id=*/false, packet_number_length,
- NOT_IN_FEC_GROUP) -
+ include_path_id, packet_number_length) -
kPrivateFlagsSize;
}
@@ -76,24 +70,26 @@ QuicPacketPublicHeader::QuicPacketPublicHeader(
QuicPacketPublicHeader::~QuicPacketPublicHeader() {}
QuicPacketHeader::QuicPacketHeader()
- : path_id(kDefaultPathId),
- packet_number(0),
- fec_flag(false),
+ : packet_number(0),
+ path_id(kDefaultPathId),
entropy_flag(false),
entropy_hash(0),
+ fec_flag(false),
is_in_fec_group(NOT_IN_FEC_GROUP),
fec_group(0) {}
QuicPacketHeader::QuicPacketHeader(const QuicPacketPublicHeader& header)
: public_header(header),
- path_id(kDefaultPathId),
packet_number(0),
- fec_flag(false),
+ path_id(kDefaultPathId),
entropy_flag(false),
entropy_hash(0),
+ fec_flag(false),
is_in_fec_group(NOT_IN_FEC_GROUP),
fec_group(0) {}
+QuicPacketHeader::QuicPacketHeader(const QuicPacketHeader& other) = default;
+
QuicPublicResetPacket::QuicPublicResetPacket()
: nonce_proof(0), rejected_packet_number(0) {}
@@ -196,6 +192,10 @@ QuicTag QuicVersionToQuicTag(const QuicVersion version) {
return MakeQuicTag('Q', '0', '2', '9');
case QUIC_VERSION_30:
return MakeQuicTag('Q', '0', '3', '0');
+ case QUIC_VERSION_31:
+ return MakeQuicTag('Q', '0', '3', '1');
+ case QUIC_VERSION_32:
+ return MakeQuicTag('Q', '0', '3', '2');
default:
// This shold be an ERROR because we should never attempt to convert an
// invalid QuicVersion to be written to the wire.
@@ -228,6 +228,8 @@ string QuicVersionToString(const QuicVersion version) {
RETURN_STRING_LITERAL(QUIC_VERSION_28);
RETURN_STRING_LITERAL(QUIC_VERSION_29);
RETURN_STRING_LITERAL(QUIC_VERSION_30);
+ RETURN_STRING_LITERAL(QUIC_VERSION_31);
+ RETURN_STRING_LITERAL(QUIC_VERSION_32);
default:
return "QUIC_VERSION_UNSUPPORTED";
}
@@ -292,8 +294,9 @@ QuicAckFrame::QuicAckFrame()
entropy_hash(0),
is_truncated(false),
largest_observed(0),
- delta_time_largest_observed(QuicTime::Delta::Infinite()),
- latest_revived_packet(0) {}
+ ack_delay_time(QuicTime::Delta::Infinite()) {}
+
+QuicAckFrame::QuicAckFrame(const QuicAckFrame& other) = default;
QuicAckFrame::~QuicAckFrame() {}
@@ -349,9 +352,12 @@ QuicFrame::QuicFrame(QuicWindowUpdateFrame* 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;
+ << " least_unacked: " << sent_info.least_unacked << "\n";
return os;
}
@@ -359,7 +365,9 @@ PacketNumberQueue::const_iterator::const_iterator(
IntervalSet<QuicPacketNumber>::const_iterator interval_set_iter,
QuicPacketNumber first,
QuicPacketNumber last)
- : interval_set_iter_(interval_set_iter), current_(first), last_(last) {}
+ : interval_set_iter_(std::move(interval_set_iter)),
+ current_(first),
+ last_(last) {}
PacketNumberQueue::const_iterator::const_iterator(const const_iterator& other) =
default;
@@ -386,8 +394,7 @@ bool PacketNumberQueue::const_iterator::operator==(
}
PacketNumberQueue::const_iterator::value_type
- PacketNumberQueue::const_iterator::
- operator*() const {
+ PacketNumberQueue::const_iterator::operator*() const {
return current_;
}
@@ -520,17 +527,15 @@ ostream& operator<<(ostream& os, const PacketNumberQueue& q) {
ostream& operator<<(ostream& os, const QuicAckFrame& ack_frame) {
os << "entropy_hash: " << static_cast<int>(ack_frame.entropy_hash)
<< " largest_observed: " << ack_frame.largest_observed
- << " delta_time_largest_observed: "
- << ack_frame.delta_time_largest_observed.ToMicroseconds()
+ << " ack_delay_time: " << ack_frame.ack_delay_time.ToMicroseconds()
<< " missing_packets: [ " << ack_frame.missing_packets
<< " ] is_truncated: " << ack_frame.is_truncated
- << " revived_packet: " << ack_frame.latest_revived_packet
<< " received_packets: [ ";
for (const std::pair<QuicPacketNumber, QuicTime>& p :
ack_frame.received_packet_times) {
os << p.first << " at " << p.second.ToDebuggingValue() << " ";
}
- os << " ]";
+ os << " ]\n";
return os;
}
@@ -581,6 +586,10 @@ ostream& operator<<(ostream& os, const QuicFrame& 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;
@@ -621,6 +630,11 @@ ostream& operator<<(ostream& os, const QuicBlockedFrame& blocked_frame) {
return os;
}
+ostream& operator<<(ostream& os, const QuicPathCloseFrame& path_close_frame) {
+ os << "path_id { " << 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 << " } "
@@ -660,16 +674,20 @@ QuicWindowUpdateFrame::QuicWindowUpdateFrame(QuicStreamId stream_id,
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,
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),
packet_number_length_(packet_number_length) {}
QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer, size_t length)
@@ -680,89 +698,52 @@ QuicEncryptedPacket::QuicEncryptedPacket(char* buffer,
bool owns_buffer)
: QuicData(buffer, length, owns_buffer) {}
-StringPiece QuicPacket::FecProtectedData() const {
- const size_t start_of_fec = GetStartOfFecProtectedData(
- connection_id_length_, includes_version_, packet_number_length_);
- return StringPiece(data() + start_of_fec, length() - start_of_fec);
+QuicEncryptedPacket* QuicEncryptedPacket::Clone() const {
+ char* buffer = new char[this->length()];
+ memcpy(buffer, this->data(), this->length());
+ return new QuicEncryptedPacket(buffer, this->length(), true);
}
-StringPiece QuicPacket::AssociatedData() const {
- return StringPiece(
- data(), GetStartOfEncryptedData(connection_id_length_, includes_version_,
- packet_number_length_));
+ostream& operator<<(ostream& os, const QuicEncryptedPacket& s) {
+ os << s.length() << "-byte data";
+ return os;
}
-StringPiece QuicPacket::Plaintext() const {
- const size_t start_of_encrypted_data = GetStartOfEncryptedData(
- connection_id_length_, includes_version_, packet_number_length_);
- return StringPiece(data() + start_of_encrypted_data,
- length() - start_of_encrypted_data);
+QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
+ size_t length,
+ QuicTime receipt_time)
+ : QuicEncryptedPacket(buffer, length), receipt_time_(receipt_time) {}
+
+QuicReceivedPacket::QuicReceivedPacket(char* buffer,
+ size_t length,
+ QuicTime receipt_time,
+ bool owns_buffer)
+ : QuicEncryptedPacket(buffer, length, owns_buffer),
+ receipt_time_(receipt_time) {}
+
+QuicReceivedPacket* QuicReceivedPacket::Clone() const {
+ char* buffer = new char[this->length()];
+ memcpy(buffer, this->data(), this->length());
+ return new QuicReceivedPacket(buffer, this->length(), receipt_time(), true);
}
-RetransmittableFrames::RetransmittableFrames()
- : has_crypto_handshake_(NOT_HANDSHAKE), needs_padding_(false) {
- // TODO(ianswett): Consider using an inlined vector instead, since this
- // is very frequently a single frame.
- frames_.reserve(2);
-}
-
-RetransmittableFrames::~RetransmittableFrames() {
- 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 WINDOW_UPDATE_FRAME:
- delete frame.window_update_frame;
- break;
- case BLOCKED_FRAME:
- delete frame.blocked_frame;
- break;
- case NUM_FRAME_TYPES:
- DCHECK(false) << "Cannot delete type: " << frame.type;
- }
- }
+ostream& operator<<(ostream& os, const QuicReceivedPacket& s) {
+ os << s.length() << "-byte data";
+ return os;
}
-const QuicFrame& RetransmittableFrames::AddFrame(const QuicFrame& frame) {
- if (frame.type == STREAM_FRAME &&
- frame.stream_frame->stream_id == kCryptoStreamId) {
- has_crypto_handshake_ = IS_HANDSHAKE;
- }
- frames_.push_back(frame);
- return frame;
+StringPiece QuicPacket::AssociatedData() const {
+ return StringPiece(data(), GetStartOfEncryptedData(
+ connection_id_length_, includes_version_,
+ includes_path_id_, packet_number_length_));
}
-void RetransmittableFrames::RemoveFramesForStream(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);
- }
+StringPiece QuicPacket::Plaintext() const {
+ const size_t start_of_encrypted_data =
+ GetStartOfEncryptedData(connection_id_length_, includes_version_,
+ includes_path_id_, packet_number_length_);
+ return StringPiece(data() + start_of_encrypted_data,
+ length() - start_of_encrypted_data);
}
AckListenerWrapper::AckListenerWrapper(QuicAckListenerInterface* listener,
@@ -771,73 +752,39 @@ AckListenerWrapper::AckListenerWrapper(QuicAckListenerInterface* listener,
DCHECK(listener != nullptr);
}
+AckListenerWrapper::AckListenerWrapper(const AckListenerWrapper& other) =
+ default;
+
AckListenerWrapper::~AckListenerWrapper() {}
-SerializedPacket::SerializedPacket(
- QuicPathId path_id,
- QuicPacketNumber packet_number,
- QuicPacketNumberLength packet_number_length,
- QuicEncryptedPacket* packet,
- QuicPacketEntropyHash entropy_hash,
- RetransmittableFrames* retransmittable_frames,
- bool has_ack,
- bool has_stop_waiting)
- : packet(packet),
- retransmittable_frames(retransmittable_frames),
+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),
+ needs_padding(false),
path_id(path_id),
packet_number(packet_number),
packet_number_length(packet_number_length),
encryption_level(ENCRYPTION_NONE),
entropy_hash(entropy_hash),
- is_fec_packet(false),
has_ack(has_ack),
has_stop_waiting(has_stop_waiting),
original_packet_number(0),
transmission_type(NOT_RETRANSMISSION) {}
-SerializedPacket::SerializedPacket(
- QuicPathId path_id,
- QuicPacketNumber packet_number,
- QuicPacketNumberLength packet_number_length,
- char* encrypted_buffer,
- size_t encrypted_length,
- bool owns_buffer,
- QuicPacketEntropyHash entropy_hash,
- RetransmittableFrames* retransmittable_frames,
- bool has_ack,
- bool has_stop_waiting,
- EncryptionLevel level)
- : SerializedPacket(path_id,
- packet_number,
- packet_number_length,
- new QuicEncryptedPacket(encrypted_buffer,
- encrypted_length,
- owns_buffer),
- entropy_hash,
- retransmittable_frames,
- has_ack,
- has_stop_waiting) {
- // TODO(ianswett): Move into the initializer list once SerializedPacket
- // no longer contains an encrypted packet.
- encryption_level = level;
-}
+SerializedPacket::SerializedPacket(const SerializedPacket& other) = default;
SerializedPacket::~SerializedPacket() {}
-QuicEncryptedPacket* QuicEncryptedPacket::Clone() const {
- char* buffer = new char[this->length()];
- memcpy(buffer, this->data(), this->length());
- return new QuicEncryptedPacket(buffer, this->length(), true);
-}
-
-ostream& operator<<(ostream& os, const QuicEncryptedPacket& s) {
- os << s.length() << "-byte data";
- return os;
-}
-
TransmissionInfo::TransmissionInfo()
- : retransmittable_frames(nullptr),
- encryption_level(ENCRYPTION_NONE),
+ : encryption_level(ENCRYPTION_NONE),
packet_number_length(PACKET_1BYTE_PACKET_NUMBER),
bytes_sent(0),
nack_count(0),
@@ -845,20 +792,18 @@ TransmissionInfo::TransmissionInfo()
transmission_type(NOT_RETRANSMISSION),
in_flight(false),
is_unackable(false),
- is_fec_packet(false),
- all_transmissions(nullptr),
+ has_crypto_handshake(false),
+ needs_padding(false),
retransmission(0) {}
-TransmissionInfo::TransmissionInfo(
- RetransmittableFrames* retransmittable_frames,
- EncryptionLevel level,
- QuicPacketNumberLength packet_number_length,
- TransmissionType transmission_type,
- QuicTime sent_time,
- QuicPacketLength bytes_sent,
- bool is_fec_packet)
- : retransmittable_frames(retransmittable_frames),
- encryption_level(level),
+TransmissionInfo::TransmissionInfo(EncryptionLevel level,
+ QuicPacketNumberLength packet_number_length,
+ TransmissionType transmission_type,
+ QuicTime sent_time,
+ QuicPacketLength bytes_sent,
+ bool has_crypto_handshake,
+ bool needs_padding)
+ : encryption_level(level),
packet_number_length(packet_number_length),
bytes_sent(bytes_sent),
nack_count(0),
@@ -866,10 +811,12 @@ TransmissionInfo::TransmissionInfo(
transmission_type(transmission_type),
in_flight(false),
is_unackable(false),
- is_fec_packet(is_fec_packet),
- all_transmissions(nullptr),
+ has_crypto_handshake(has_crypto_handshake),
+ needs_padding(needs_padding),
retransmission(0) {}
+TransmissionInfo::TransmissionInfo(const TransmissionInfo& other) = default;
+
TransmissionInfo::~TransmissionInfo() {}
} // namespace net
diff --git a/chromium/net/quic/quic_protocol.h b/chromium/net/quic/quic_protocol.h
index 29214034c0e..44bcbac1ffd 100644
--- a/chromium/net/quic/quic_protocol.h
+++ b/chromium/net/quic/quic_protocol.h
@@ -17,7 +17,6 @@
#include <utility>
#include <vector>
-#include "base/containers/hash_tables.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -28,7 +27,6 @@
#include "net/base/ip_endpoint.h"
#include "net/base/net_export.h"
#include "net/quic/interval_set.h"
-#include "net/quic/quic_ack_listener_interface.h"
#include "net/quic/quic_bandwidth.h"
#include "net/quic/quic_time.h"
#include "net/quic/quic_types.h"
@@ -141,6 +139,9 @@ 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.
@@ -180,6 +181,12 @@ const int kMaxStreamsMinimumIncrement = 10;
// 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;
+
// 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
@@ -202,7 +209,7 @@ const QuicPathId kDefaultPathId = 0;
// Invalid path ID.
const QuicPathId kInvalidPathId = 0xff;
-enum TransmissionType {
+enum TransmissionType : int8_t {
NOT_RETRANSMISSION,
FIRST_TRANSMISSION_TYPE = NOT_RETRANSMISSION,
HANDSHAKE_RETRANSMISSION, // Retransmits due to handshake timeouts.
@@ -214,38 +221,26 @@ enum TransmissionType {
LAST_TRANSMISSION_TYPE = TLP_RETRANSMISSION,
};
-enum HasRetransmittableData {
+enum HasRetransmittableData : int8_t {
NO_RETRANSMITTABLE_DATA,
HAS_RETRANSMITTABLE_DATA,
};
-enum IsHandshake { NOT_HANDSHAKE, IS_HANDSHAKE };
+enum IsHandshake : int8_t { NOT_HANDSHAKE, IS_HANDSHAKE };
enum class Perspective { IS_SERVER, IS_CLIENT };
-NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
- const Perspective& s);
-
-// Indicates FEC protection level for data being written.
-enum FecProtection {
- MUST_FEC_PROTECT, // Callee must FEC protect this data.
- MAY_FEC_PROTECT // Callee does not have to but may FEC protect this data.
-};
-
-// Indicates FEC policy.
-enum FecPolicy {
- FEC_PROTECT_ALWAYS, // All data in the stream should be FEC protected.
- FEC_PROTECT_OPTIONAL // Data in the stream does not need FEC protection.
-};
+// Describes whether a ConnectionClose was originated by the peer.
+enum class ConnectionCloseSource { FROM_PEER, FROM_SELF };
-// Indicates FEC policy about when to send FEC packet.
-enum FecSendPolicy {
- // Send FEC packet when FEC group is full or when FEC alarm goes off.
- FEC_ANY_TRIGGER,
- // Send FEC packet only when FEC alarm goes off.
- FEC_ALARM_TRIGGER
+// Should a connection be closed silently or not.
+enum class ConnectionCloseBehavior {
+ SILENT_CLOSE,
+ SEND_CONNECTION_CLOSE_PACKET
};
+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.
@@ -257,6 +252,7 @@ enum QuicFrameType {
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.
@@ -279,7 +275,7 @@ enum InFecGroup {
IN_FEC_GROUP,
};
-enum QuicPacketNumberLength {
+enum QuicPacketNumberLength : int8_t {
PACKET_1BYTE_PACKET_NUMBER = 1,
PACKET_2BYTE_PACKET_NUMBER = 2,
PACKET_4BYTE_PACKET_NUMBER = 4,
@@ -327,7 +323,7 @@ enum QuicPacketPublicFlags {
// Bit 6: Does the packet header contain a path id?
PACKET_PUBLIC_FLAGS_MULTIPATH = 1 << 6,
- // All bits set (bit7 are not currently used): 01111111
+ // All bits set (bit 7 is not currently used): 01111111
PACKET_PUBLIC_FLAGS_MAX = (1 << 7) - 1,
};
@@ -345,7 +341,10 @@ enum QuicPacketPrivateFlags {
PACKET_PRIVATE_FLAGS_FEC = 1 << 2,
// All bits set (bits 3-7 are not currently used): 00000111
- PACKET_PRIVATE_FLAGS_MAX = (1 << 3) - 1
+ PACKET_PRIVATE_FLAGS_MAX = (1 << 3) - 1,
+
+ // For version 32 (bits 1-7 are not used): 00000001
+ PACKET_PRIVATE_FLAGS_MAX_VERSION_32 = (1 << 1) - 1
};
// The available versions of QUIC. Guaranteed that the integer value of the enum
@@ -365,6 +364,8 @@ enum QuicVersion {
QUIC_VERSION_28 = 28, // Receiver can refuse to create a requested stream.
QUIC_VERSION_29 = 29, // Server and client honor QUIC_STREAM_NO_ERROR.
QUIC_VERSION_30 = 30, // Add server side support of cert transparency.
+ QUIC_VERSION_31 = 31, // Adds a hash of the client hello to crypto proof.
+ QUIC_VERSION_32 = 32, // FEC related fields are removed from wire format.
};
// This vector contains QUIC versions which we currently support.
@@ -375,8 +376,8 @@ enum QuicVersion {
// 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_30, QUIC_VERSION_29, QUIC_VERSION_28,
- QUIC_VERSION_27, QUIC_VERSION_26, QUIC_VERSION_25};
+ QUIC_VERSION_32, QUIC_VERSION_31, QUIC_VERSION_30, QUIC_VERSION_29,
+ QUIC_VERSION_28, QUIC_VERSION_27, QUIC_VERSION_26, QUIC_VERSION_25};
typedef std::vector<QuicVersion> QuicVersionVector;
@@ -417,25 +418,23 @@ NET_EXPORT_PRIVATE QuicTag MakeQuicTag(char a, char b, char c, char d);
NET_EXPORT_PRIVATE bool ContainsQuicTag(const QuicTagVector& tag_vector,
QuicTag tag);
-// Size in bytes of the data or fec packet header.
+// Size in bytes of the data packet header.
NET_EXPORT_PRIVATE size_t GetPacketHeaderSize(const QuicPacketHeader& header);
NET_EXPORT_PRIVATE size_t
GetPacketHeaderSize(QuicConnectionIdLength connection_id_length,
bool include_version,
bool include_path_id,
- QuicPacketNumberLength packet_number_length,
- InFecGroup is_in_fec_group);
+ QuicPacketNumberLength packet_number_length);
-// Index of the first byte in a QUIC packet of FEC protected data.
-NET_EXPORT_PRIVATE size_t
-GetStartOfFecProtectedData(QuicConnectionIdLength connection_id_length,
- bool include_version,
- QuicPacketNumberLength packet_number_length);
// Index of the first byte in a QUIC packet of encrypted data.
NET_EXPORT_PRIVATE size_t
+GetStartOfEncryptedData(const QuicPacketHeader& header);
+
+NET_EXPORT_PRIVATE size_t
GetStartOfEncryptedData(QuicConnectionIdLength connection_id_length,
bool include_version,
+ bool include_path_id,
QuicPacketNumberLength packet_number_length);
enum QuicRstStreamErrorCode {
@@ -463,7 +462,16 @@ enum QuicRstStreamErrorCode {
// 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,
// No error. Used as bound while iterating.
QUIC_STREAM_LAST_ERROR,
};
@@ -477,7 +485,6 @@ AdjustErrorForVersion(QuicRstStreamErrorCode error_code, QuicVersion version);
// 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.
-// last value = 78
enum QuicErrorCode {
QUIC_NO_ERROR = 0,
@@ -495,8 +502,12 @@ enum QuicErrorCode {
QUIC_INVALID_FEC_DATA = 5,
// STREAM frame data is malformed.
QUIC_INVALID_STREAM_DATA = 46,
- // STREAM frame data is not encrypted.
+ // 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,
// FEC frame data is not encrypted.
QUIC_UNENCRYPTED_FEC_DATA = 77,
// RST_STREAM frame data is malformed.
@@ -511,6 +522,8 @@ enum QuicErrorCode {
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,
@@ -545,18 +558,20 @@ enum QuicErrorCode {
QUIC_INVALID_NEGOTIATED_VALUE = 23,
// There was an error decompressing data.
QUIC_DECOMPRESSION_FAILURE = 24,
- // We hit our prenegotiated (or default) timeout
- QUIC_CONNECTION_TIMED_OUT = 25,
- // We hit our overall connection timeout
- QUIC_CONNECTION_OVERALL_TIMED_OUT = 67,
- // There was an error encountered migrating addresses
+ // 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_INVALID_STREAM_FRAME = 50,
+ 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.
@@ -571,7 +586,7 @@ enum QuicErrorCode {
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 job to load server config is cancelled.
+ // The quic connection has been cancelled.
QUIC_CONNECTION_CANCELLED = 70,
// Disabled QUIC because of high packet loss rate.
QUIC_BAD_PACKET_LOSS_RATE = 71,
@@ -581,6 +596,8 @@ enum QuicErrorCode {
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.
@@ -639,20 +656,25 @@ enum QuicErrorCode {
// tampered with.
QUIC_VERSION_NEGOTIATION_MISMATCH = 55,
+ // Multipath is not enabled, but a packet with multipath flag on is received.
+ QUIC_BAD_MULTIPATH_FLAG = 79,
+
// IP address changed causing connection close.
- QUIC_IP_ADDRESS_CHANGED = 78,
+ QUIC_IP_ADDRESS_CHANGED = 80,
// Connection migration errors.
// Network changed, but connection had no migratable streams.
- QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS = 79,
+ QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS = 81,
// Connection changed networks too many times.
- QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES = 80,
+ 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 = 81,
+ 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,
// No error. Used as bound while iterating.
- QUIC_LAST_ERROR = 82,
+ QUIC_LAST_ERROR = 89,
};
// Must be updated any time a QuicErrorCode is deprecated.
@@ -678,20 +700,21 @@ struct NET_EXPORT_PRIVATE QuicPacketPublicHeader {
// An integer which cannot be a packet number.
const QuicPacketNumber kInvalidPacketNumber = 0;
-// Header for Data or FEC packets.
+// 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;
- QuicPathId path_id;
QuicPacketNumber packet_number;
- bool fec_flag;
+ QuicPathId path_id;
bool entropy_flag;
QuicPacketEntropyHash entropy_hash;
+ bool fec_flag;
InFecGroup is_in_fec_group;
QuicFecGroupNumber fec_group;
};
@@ -740,8 +763,17 @@ class NET_EXPORT_PRIVATE 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
@@ -832,8 +864,8 @@ struct NET_EXPORT_PRIVATE QuicStopWaitingFrame {
// larger new packet numbers are added, with the occasional random access.
class NET_EXPORT_PRIVATE PacketNumberQueue {
public:
- // TODO(jdorfman): remove const_iterator and change the callers to
- // iterate over the intervals.
+ // TODO(jdorfman): remove const_iterator and change the callers to iterate
+ // over the intervals.
class NET_EXPORT_PRIVATE const_iterator
: public std::iterator<std::input_iterator_tag,
QuicPacketNumber,
@@ -922,6 +954,7 @@ class NET_EXPORT_PRIVATE PacketNumberQueue {
struct NET_EXPORT_PRIVATE QuicAckFrame {
QuicAckFrame();
+ QuicAckFrame(const QuicAckFrame& other);
~QuicAckFrame();
NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
@@ -949,17 +982,13 @@ struct NET_EXPORT_PRIVATE QuicAckFrame {
// Time elapsed since largest_observed was received until this Ack frame was
// sent.
- QuicTime::Delta delta_time_largest_observed;
+ QuicTime::Delta ack_delay_time;
// Vector of <packet_number, time> for when packets arrived.
PacketTimeVector received_packet_times;
// The set of packets which we're expecting and have not received.
PacketNumberQueue missing_packets;
-
- // Packet most recently revived via FEC, 0 if no packet was revived by FEC.
- // If non-zero, must be present in missing_packets.
- QuicPacketNumber latest_revived_packet;
};
// True if the packet number is greater than largest_observed or is listed
@@ -1068,11 +1097,28 @@ struct NET_EXPORT_PRIVATE QuicBlockedFrame {
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 {
+enum EncryptionLevel : int8_t {
ENCRYPTION_NONE = 0,
ENCRYPTION_INITIAL = 1,
ENCRYPTION_FORWARD_SECURE = 2,
@@ -1081,20 +1127,20 @@ enum EncryptionLevel {
};
enum PeerAddressChangeType {
+ // IP address and port remain unchanged.
NO_CHANGE,
- // Peer address changes which are considered to be cause by NATs. Currently,
- // IPv4 address change with /24 does not change is considered to be cause by
- // NATs.
- NAT_PORT_REBINDING,
- IPV4_SUBNET_REBINDING,
- // IPv6 related address changes.
- IPV4_TO_IPV6,
- IPV6_TO_IPV4,
- IPV6_TO_IPV6,
- // This type is used when we always allow peer address changes.
- UNKNOWN,
- // All other peer address change types.
- UNSPECIFIED,
+ // Port changed, but IP address remains unchanged.
+ PORT_CHANGE,
+ // IPv4 address changed, but within the /24 subnet (port may have changed.)
+ IPV4_SUBNET_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,
+ // All other peer address changes.
+ UNSPECIFIED_CHANGE,
};
struct NET_EXPORT_PRIVATE QuicFrame {
@@ -1111,6 +1157,7 @@ struct NET_EXPORT_PRIVATE QuicFrame {
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);
@@ -1131,6 +1178,7 @@ struct NET_EXPORT_PRIVATE QuicFrame {
QuicGoAwayFrame* goaway_frame;
QuicWindowUpdateFrame* window_update_frame;
QuicBlockedFrame* blocked_frame;
+ QuicPathCloseFrame* path_close_frame;
};
};
// QuicFrameType consumes 8 bytes with padding.
@@ -1163,14 +1211,17 @@ class NET_EXPORT_PRIVATE 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,
QuicPacketNumberLength packet_number_length);
- base::StringPiece FecProtectedData() const;
base::StringPiece AssociatedData() const;
base::StringPiece Plaintext() const;
@@ -1180,6 +1231,7 @@ class NET_EXPORT_PRIVATE QuicPacket : public QuicData {
char* buffer_;
const QuicConnectionIdLength connection_id_length_;
const bool includes_version_;
+ const bool includes_path_id_;
const QuicPacketNumberLength packet_number_length_;
DISALLOW_COPY_AND_ASSIGN(QuicPacket);
@@ -1205,35 +1257,61 @@ class NET_EXPORT_PRIVATE QuicEncryptedPacket : public QuicData {
DISALLOW_COPY_AND_ASSIGN(QuicEncryptedPacket);
};
-class NET_EXPORT_PRIVATE RetransmittableFrames {
+// A received encrypted QUIC packet, with a recorded time of receipt.
+class NET_EXPORT_PRIVATE QuicReceivedPacket : public QuicEncryptedPacket {
public:
- RetransmittableFrames();
- ~RetransmittableFrames();
+ QuicReceivedPacket(const char* buffer, size_t length, QuicTime receipt_time);
+ QuicReceivedPacket(char* buffer,
+ size_t length,
+ QuicTime receipt_time,
+ bool owns_buffer);
+
+ // Clones the packet into a new packet which owns the buffer.
+ QuicReceivedPacket* Clone() const;
+
+ // Returns the time at which the packet was received.
+ QuicTime receipt_time() const { return receipt_time_; }
- // Takes ownership of the frame inside |frame|.
- const QuicFrame& AddFrame(const QuicFrame& frame);
- // Removes all stream frames associated with |stream_id|.
- void RemoveFramesForStream(QuicStreamId stream_id);
+ // 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);
- const QuicFrames& frames() const { return frames_; }
+ private:
+ const QuicTime receipt_time_;
- IsHandshake HasCryptoHandshake() const { return has_crypto_handshake_; }
+ DISALLOW_COPY_AND_ASSIGN(QuicReceivedPacket);
+};
- bool needs_padding() const { return needs_padding_; }
+// Pure virtual class to listen for packet acknowledgements.
+class NET_EXPORT_PRIVATE QuicAckListenerInterface
+ : public base::RefCounted<QuicAckListenerInterface> {
+ public:
+ QuicAckListenerInterface() {}
- void set_needs_padding(bool needs_padding) { needs_padding_ = needs_padding; }
+ // 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;
- private:
- QuicFrames frames_;
- IsHandshake has_crypto_handshake_;
- bool needs_padding_;
+ // 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;
- DISALLOW_COPY_AND_ASSIGN(RetransmittableFrames);
+ protected:
+ friend class base::RefCounted<QuicAckListenerInterface>;
+
+ // Delegates are ref counted.
+ virtual ~QuicAckListenerInterface() {}
};
struct NET_EXPORT_PRIVATE AckListenerWrapper {
AckListenerWrapper(QuicAckListenerInterface* listener,
QuicPacketLength data_length);
+ AckListenerWrapper(const AckListenerWrapper& other);
~AckListenerWrapper();
scoped_refptr<QuicAckListenerInterface> ack_listener;
@@ -1244,32 +1322,25 @@ struct NET_EXPORT_PRIVATE SerializedPacket {
SerializedPacket(QuicPathId path_id,
QuicPacketNumber packet_number,
QuicPacketNumberLength packet_number_length,
- QuicEncryptedPacket* packet,
+ const char* encrypted_buffer,
+ QuicPacketLength encrypted_length,
QuicPacketEntropyHash entropy_hash,
- RetransmittableFrames* retransmittable_frames,
bool has_ack,
bool has_stop_waiting);
- SerializedPacket(QuicPathId path_id,
- QuicPacketNumber packet_number,
- QuicPacketNumberLength packet_number_length,
- char* encrypted_buffer,
- size_t encrypted_length,
- bool owns_buffer,
- QuicPacketEntropyHash entropy_hash,
- RetransmittableFrames* retransmittable_frames,
- bool has_ack,
- bool has_stop_waiting,
- EncryptionLevel level);
+ SerializedPacket(const SerializedPacket& other);
~SerializedPacket();
- QuicEncryptedPacket* packet;
- RetransmittableFrames* retransmittable_frames;
+ // Not owned.
+ const char* encrypted_buffer;
+ QuicPacketLength encrypted_length;
+ QuicFrames retransmittable_frames;
+ IsHandshake has_crypto_handshake;
+ bool needs_padding;
QuicPathId path_id;
QuicPacketNumber packet_number;
QuicPacketNumberLength packet_number_length;
EncryptionLevel encryption_level;
QuicPacketEntropyHash entropy_hash;
- bool is_fec_packet;
bool has_ack;
bool has_stop_waiting;
QuicPacketNumber original_packet_number;
@@ -1283,19 +1354,21 @@ struct NET_EXPORT_PRIVATE TransmissionInfo {
// Used by STL when assigning into a map.
TransmissionInfo();
- // Constructs a Transmission with a new all_tranmissions set
+ // Constructs a Transmission with a new all_transmissions set
// containing |packet_number|.
- TransmissionInfo(RetransmittableFrames* retransmittable_frames,
- EncryptionLevel level,
+ TransmissionInfo(EncryptionLevel level,
QuicPacketNumberLength packet_number_length,
TransmissionType transmission_type,
QuicTime sent_time,
QuicPacketLength bytes_sent,
- bool is_fec_packet);
+ bool has_crypto_handshake,
+ bool needs_padding);
+
+ TransmissionInfo(const TransmissionInfo& other);
~TransmissionInfo();
- RetransmittableFrames* retransmittable_frames;
+ QuicFrames retransmittable_frames;
EncryptionLevel encryption_level;
QuicPacketNumberLength packet_number_length;
QuicPacketLength bytes_sent;
@@ -1307,20 +1380,47 @@ struct NET_EXPORT_PRIVATE TransmissionInfo {
bool in_flight;
// True if the packet can never be acked, so it can be removed.
bool is_unackable;
- // True if the packet is an FEC packet.
- bool is_fec_packet;
- // Stores the packet numbers of all transmissions of this packet.
- // Must always be nullptr or have multiple elements.
- // TODO(ianswett): Deprecate with quic_track_single_retransmission.
- PacketNumberList* all_transmissions;
+ // True if the packet contains stream data from the crypto stream.
+ bool has_crypto_handshake;
+ // True if the packet needs padding if it's retransmitted.
+ bool needs_padding;
// 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;
};
-static_assert(sizeof(QuicFrame) <= 64,
- "Keep the TransmissionInfo size to a cacheline.");
+static_assert(sizeof(TransmissionInfo) <= 128,
+ "TODO(ianswett): Keep the TransmissionInfo size to a cacheline.");
+
+// 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,
+ bool needs_padding,
+ 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),
+ needs_padding(needs_padding),
+ 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;
+ bool needs_padding;
+ 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.
diff --git a/chromium/net/quic/quic_protocol_test.cc b/chromium/net/quic/quic_protocol_test.cc
index 7f9aaa6aa2a..6a34620c4ec 100644
--- a/chromium/net/quic/quic_protocol_test.cc
+++ b/chromium/net/quic/quic_protocol_test.cc
@@ -15,7 +15,7 @@ namespace test {
namespace {
TEST(QuicProtocolTest, AdjustErrorForVersion) {
- ASSERT_EQ(9, QUIC_STREAM_LAST_ERROR)
+ ASSERT_EQ(14, QUIC_STREAM_LAST_ERROR)
<< "Any additions to QuicRstStreamErrorCode require an addition to "
<< "AdjustErrorForVersion and this associated test.";
@@ -92,7 +92,8 @@ TEST(QuicProtocolTest, QuicVersionToQuicTagUnsupported) {
// 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(ERROR, _, "Unsupported QuicVersion: 0")).Times(1);
+ EXPECT_CALL(log, Log(base_logging::ERROR, _, "Unsupported QuicVersion: 0"))
+ .Times(1);
log.StartCapturingLogs();
#endif
@@ -134,7 +135,9 @@ TEST(QuicProtocolTest, QuicTagToQuicVersionUnsupported) {
#if 0
ScopedMockLog log(kDoNotCaptureLogsYet);
#ifndef NDEBUG
- EXPECT_CALL(log, Log(INFO, _, "Unsupported QuicTag version: FAKE")).Times(1);
+ EXPECT_CALL(log,
+ Log(base_logging::INFO, _, "Unsupported QuicTag version: FAKE"))
+ .Times(1);
#endif
log.StartCapturingLogs();
#endif
diff --git a/chromium/net/quic/quic_received_packet_manager.cc b/chromium/net/quic/quic_received_packet_manager.cc
index 81e94de3be3..9e7a9e5dbae 100644
--- a/chromium/net/quic/quic_received_packet_manager.cc
+++ b/chromium/net/quic/quic_received_packet_manager.cc
@@ -9,9 +9,12 @@
#include "base/logging.h"
#include "base/stl_util.h"
+#include "base/strings/stringprintf.h"
#include "net/base/linked_hash_map.h"
#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_connection_stats.h"
+#include "net/quic/quic_flags.h"
using std::max;
using std::min;
@@ -144,8 +147,10 @@ void QuicReceivedPacketManager::RecordPacketReceived(
QuicTime receipt_time) {
QuicPacketNumber packet_number = header.packet_number;
DCHECK(IsAwaitingPacket(packet_number));
+ if (!ack_frame_updated_) {
+ ack_frame_.received_packet_times.clear();
+ }
ack_frame_updated_ = true;
-
// Adds the range of packet numbers from max(largest observed + 1, least
// awaiting ack) up to packet_number not including packet_number.
ack_frame_.missing_packets.Add(
@@ -176,17 +181,6 @@ void QuicReceivedPacketManager::RecordPacketReceived(
ack_frame_.received_packet_times.push_back(
std::make_pair(packet_number, receipt_time));
-
- if (ack_frame_.latest_revived_packet == packet_number) {
- ack_frame_.latest_revived_packet = 0;
- }
-}
-
-void QuicReceivedPacketManager::RecordPacketRevived(
- QuicPacketNumber packet_number) {
- LOG_IF(DFATAL, !IsAwaitingPacket(packet_number));
- ack_frame_updated_ = true;
- ack_frame_.latest_revived_packet = packet_number;
}
bool QuicReceivedPacketManager::IsMissing(QuicPacketNumber packet_number) {
@@ -211,25 +205,22 @@ struct isTooLarge {
};
} // namespace
-void QuicReceivedPacketManager::UpdateReceivedPacketInfo(
- QuicAckFrame* ack_frame,
+const QuicFrame QuicReceivedPacketManager::GetUpdatedAckFrame(
QuicTime approximate_now) {
ack_frame_updated_ = false;
- *ack_frame = ack_frame_;
- ack_frame->entropy_hash = EntropyHash(ack_frame_.largest_observed);
+ ack_frame_.entropy_hash = EntropyHash(ack_frame_.largest_observed);
if (time_largest_observed_ == QuicTime::Zero()) {
// We have received no packets.
- ack_frame->delta_time_largest_observed = QuicTime::Delta::Infinite();
- return;
+ ack_frame_.ack_delay_time = QuicTime::Delta::Infinite();
+ } else {
+ // Ensure the delta is zero if approximate now is "in the past".
+ ack_frame_.ack_delay_time =
+ approximate_now < time_largest_observed_
+ ? QuicTime::Delta::Zero()
+ : approximate_now.Subtract(time_largest_observed_);
}
- // Ensure the delta is zero if approximate now is "in the past".
- ack_frame->delta_time_largest_observed =
- approximate_now < time_largest_observed_
- ? QuicTime::Delta::Zero()
- : approximate_now.Subtract(time_largest_observed_);
-
// Clear all packet times if any are too far from largest observed.
// It's expected this is extremely rare.
for (PacketTimeVector::iterator it = ack_frame_.received_packet_times.begin();
@@ -242,11 +233,7 @@ void QuicReceivedPacketManager::UpdateReceivedPacketInfo(
}
}
- // TODO(ianswett): Instead of transferring all the information over,
- // consider giving the QuicPacketGenerator a reference to this ack frame
- // and clear it afterwards.
- ack_frame->received_packet_times.clear();
- ack_frame->received_packet_times.swap(ack_frame_.received_packet_times);
+ return QuicFrame(&ack_frame_);
}
QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash(
@@ -256,9 +243,6 @@ QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash(
bool QuicReceivedPacketManager::DontWaitForPacketsBefore(
QuicPacketNumber least_unacked) {
- if (ack_frame_.latest_revived_packet < least_unacked) {
- ack_frame_.latest_revived_packet = 0;
- }
return ack_frame_.missing_packets.RemoveUpTo(least_unacked);
}
@@ -284,6 +268,10 @@ void QuicReceivedPacketManager::UpdatePacketInformationSentByPeer(
ack_frame_.missing_packets.Min() >= peer_least_packet_awaiting_ack_);
}
+bool QuicReceivedPacketManager::HasMissingPackets() const {
+ return !ack_frame_.missing_packets.Empty();
+}
+
bool QuicReceivedPacketManager::HasNewMissingPackets() const {
return !ack_frame_.missing_packets.Empty() &&
(ack_frame_.largest_observed - ack_frame_.missing_packets.Max()) <=
diff --git a/chromium/net/quic/quic_received_packet_manager.h b/chromium/net/quic/quic_received_packet_manager.h
index c037aed354d..99f0a5cd255 100644
--- a/chromium/net/quic/quic_received_packet_manager.h
+++ b/chromium/net/quic/quic_received_packet_manager.h
@@ -109,17 +109,16 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager
const QuicPacketHeader& header,
QuicTime receipt_time);
- virtual void RecordPacketRevived(QuicPacketNumber packet_number);
-
// Checks whether |packet_number| is missing and less than largest observed.
virtual bool IsMissing(QuicPacketNumber packet_number);
// Checks if we're still waiting for the packet with |packet_number|.
virtual bool IsAwaitingPacket(QuicPacketNumber packet_number);
- // Update the |ack_frame| for an outgoing ack.
- void UpdateReceivedPacketInfo(QuicAckFrame* ack_frame,
- QuicTime approximate_now);
+ // Retrieves a frame containing a QuicAckFrame. The ack frame may not be
+ // changed outside QuicReceivedPacketManager and must be serialized before
+ // 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
@@ -131,6 +130,9 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager
virtual void UpdatePacketInformationSentByPeer(
const QuicStopWaitingFrame& stop_waiting);
+ // Returns true if there are any missing packets.
+ bool HasMissingPackets() const;
+
// Returns true when there are new missing packets to be reported within 3
// packets of the largest observed.
virtual bool HasNewMissingPackets() const;
@@ -144,6 +146,9 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager
virtual bool ack_frame_updated() const;
+ // For logging purposes.
+ const QuicAckFrame& ack_frame() const { return ack_frame_; }
+
private:
friend class test::QuicConnectionPeer;
friend class test::QuicReceivedPacketManagerPeer;
@@ -170,7 +175,7 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager
// The time we received the largest_observed packet number, or zero if
// no packet numbers have been received since UpdateReceivedPacketInfo.
- // Needed for calculating delta_time_largest_observed.
+ // Needed for calculating ack_delay_time.
QuicTime time_largest_observed_;
QuicConnectionStats* stats_;
diff --git a/chromium/net/quic/quic_received_packet_manager_test.cc b/chromium/net/quic/quic_received_packet_manager_test.cc
index 926fcfb5f47..8016fbd3a4d 100644
--- a/chromium/net/quic/quic_received_packet_manager_test.cc
+++ b/chromium/net/quic/quic_received_packet_manager_test.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "net/quic/quic_connection_stats.h"
+#include "net/quic/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"
@@ -203,10 +204,6 @@ class QuicReceivedPacketManagerTest : public ::testing::Test {
received_manager_.RecordPacketReceived(0u, header, receipt_time);
}
- void RecordPacketRevived(QuicPacketNumber packet_number) {
- received_manager_.RecordPacketRevived(packet_number);
- }
-
QuicConnectionStats stats_;
QuicReceivedPacketManager received_manager_;
};
@@ -303,7 +300,7 @@ TEST_F(QuicReceivedPacketManagerTest, DontWaitForPacketsBefore) {
EXPECT_TRUE(received_manager_.IsAwaitingPacket(6u));
}
-TEST_F(QuicReceivedPacketManagerTest, UpdateReceivedPacketInfo) {
+TEST_F(QuicReceivedPacketManagerTest, GetUpdatedAckFrame) {
QuicPacketHeader header;
header.packet_number = 2u;
QuicTime two_ms = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(2));
@@ -311,22 +308,22 @@ TEST_F(QuicReceivedPacketManagerTest, UpdateReceivedPacketInfo) {
received_manager_.RecordPacketReceived(0u, header, two_ms);
EXPECT_TRUE(received_manager_.ack_frame_updated());
- QuicAckFrame ack;
- received_manager_.UpdateReceivedPacketInfo(&ack, QuicTime::Zero());
+ QuicFrame ack = received_manager_.GetUpdatedAckFrame(QuicTime::Zero());
EXPECT_FALSE(received_manager_.ack_frame_updated());
// When UpdateReceivedPacketInfo with a time earlier than the time of the
// largest observed packet, make sure that the delta is 0, not negative.
- EXPECT_EQ(QuicTime::Delta::Zero(), ack.delta_time_largest_observed);
- EXPECT_EQ(1ul, ack.received_packet_times.size());
+ EXPECT_EQ(QuicTime::Delta::Zero(), ack.ack_frame->ack_delay_time);
+ EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size());
QuicTime four_ms = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(4));
- received_manager_.UpdateReceivedPacketInfo(&ack, four_ms);
+ ack = received_manager_.GetUpdatedAckFrame(four_ms);
EXPECT_FALSE(received_manager_.ack_frame_updated());
// When UpdateReceivedPacketInfo after not having received a new packet,
// the delta should still be accurate.
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(2),
- ack.delta_time_largest_observed);
- EXPECT_EQ(0ul, ack.received_packet_times.size());
+ ack.ack_frame->ack_delay_time);
+ // And received packet times won't have change.
+ EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size());
header.packet_number = 999u;
received_manager_.RecordPacketReceived(0u, header, two_ms);
@@ -335,11 +332,11 @@ TEST_F(QuicReceivedPacketManagerTest, UpdateReceivedPacketInfo) {
header.packet_number = 1000u;
received_manager_.RecordPacketReceived(0u, header, two_ms);
EXPECT_TRUE(received_manager_.ack_frame_updated());
- received_manager_.UpdateReceivedPacketInfo(&ack, two_ms);
+ ack = received_manager_.GetUpdatedAckFrame(two_ms);
EXPECT_FALSE(received_manager_.ack_frame_updated());
// UpdateReceivedPacketInfo should discard any times which can't be
// expressed on the wire.
- EXPECT_EQ(2ul, ack.received_packet_times.size());
+ EXPECT_EQ(2u, ack.ack_frame->received_packet_times.size());
}
TEST_F(QuicReceivedPacketManagerTest, UpdateReceivedConnectionStats) {
@@ -355,57 +352,6 @@ TEST_F(QuicReceivedPacketManagerTest, UpdateReceivedConnectionStats) {
EXPECT_EQ(1u, stats_.packets_reordered);
}
-TEST_F(QuicReceivedPacketManagerTest, RevivedPacket) {
- EXPECT_FALSE(received_manager_.ack_frame_updated());
- RecordPacketReceipt(1, 0);
- EXPECT_TRUE(received_manager_.ack_frame_updated());
- RecordPacketReceipt(3, 0);
- RecordPacketRevived(2);
-
- QuicAckFrame ack;
- received_manager_.UpdateReceivedPacketInfo(&ack, QuicTime::Zero());
- EXPECT_FALSE(received_manager_.ack_frame_updated());
- EXPECT_EQ(1u, ack.missing_packets.NumPacketsSlow());
- EXPECT_EQ(2u, ack.missing_packets.Min());
- EXPECT_EQ(2u, ack.latest_revived_packet);
-}
-
-TEST_F(QuicReceivedPacketManagerTest, PacketRevivedThenReceived) {
- EXPECT_FALSE(received_manager_.ack_frame_updated());
- RecordPacketReceipt(1, 0);
- EXPECT_TRUE(received_manager_.ack_frame_updated());
- RecordPacketReceipt(3, 0);
- RecordPacketRevived(2);
- RecordPacketReceipt(2, 0);
-
- QuicAckFrame ack;
- received_manager_.UpdateReceivedPacketInfo(&ack, QuicTime::Zero());
- EXPECT_TRUE(ack.missing_packets.Empty());
- EXPECT_EQ(0u, ack.latest_revived_packet);
-}
-
-TEST_F(QuicReceivedPacketManagerTest, RevivedPacketAckFrameUpdated) {
- EXPECT_FALSE(received_manager_.ack_frame_updated());
- RecordPacketReceipt(1, 0);
- RecordPacketReceipt(3, 0);
- EXPECT_TRUE(received_manager_.ack_frame_updated());
-
- QuicAckFrame ack;
- received_manager_.UpdateReceivedPacketInfo(&ack, QuicTime::Zero());
- EXPECT_FALSE(received_manager_.ack_frame_updated());
- EXPECT_EQ(1u, ack.missing_packets.NumPacketsSlow());
- EXPECT_EQ(2u, ack.missing_packets.Min());
- EXPECT_EQ(0u, ack.latest_revived_packet);
-
- RecordPacketRevived(2);
- EXPECT_TRUE(received_manager_.ack_frame_updated());
- received_manager_.UpdateReceivedPacketInfo(&ack, QuicTime::Zero());
- EXPECT_FALSE(received_manager_.ack_frame_updated());
- EXPECT_EQ(1u, ack.missing_packets.NumPacketsSlow());
- EXPECT_EQ(2u, ack.missing_packets.Min());
- EXPECT_EQ(2u, ack.latest_revived_packet);
-}
-
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_sent_packet_manager.cc b/chromium/net/quic/quic_sent_packet_manager.cc
index 6b71c70f4db..bed16fe8e7a 100644
--- a/chromium/net/quic/quic_sent_packet_manager.cc
+++ b/chromium/net/quic/quic_sent_packet_manager.cc
@@ -18,6 +18,7 @@
using std::max;
using std::min;
+using std::pair;
namespace net {
@@ -36,6 +37,8 @@ static const int64_t kMaxRetransmissionTimeMs = 60000;
static const size_t kMaxRetransmissions = 10;
// Maximum number of packets retransmitted upon an RTO.
static const size_t kMaxRetransmissionsOnTimeout = 2;
+// Minimum number of consecutive RTOs before path is considered to be degrading.
+const size_t kMinTimeoutsBeforePathDegrading = 2;
// Ensure the handshake timer isnt't faster than 10ms.
// This limits the tenth retransmitted packet to 10s after the initial CHLO.
@@ -44,17 +47,14 @@ static const int64_t kMinHandshakeTimeoutMs = 10;
// Sends up to two tail loss probes before firing an RTO,
// per draft RFC draft-dukkipati-tcpm-tcp-loss-probe.
static const size_t kDefaultMaxTailLossProbes = 2;
-static const int64_t kMinTailLossProbeTimeoutMs = 10;
// Number of unpaced packets to send after quiescence.
static const size_t kInitialUnpacedBurst = 10;
bool HasCryptoHandshake(const TransmissionInfo& transmission_info) {
- if (transmission_info.retransmittable_frames == nullptr) {
- return false;
- }
- return transmission_info.retransmittable_frames->HasCryptoHandshake() ==
- IS_HANDSHAKE;
+ DCHECK(!transmission_info.has_crypto_handshake ||
+ !transmission_info.retransmittable_frames.empty());
+ return transmission_info.has_crypto_handshake;
}
} // namespace
@@ -68,12 +68,14 @@ QuicSentPacketManager::QuicSentPacketManager(
const QuicClock* clock,
QuicConnectionStats* stats,
CongestionControlType congestion_control_type,
- LossDetectionType loss_type)
+ LossDetectionType loss_type,
+ MultipathDelegateInterface* delegate)
: 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),
@@ -96,8 +98,7 @@ QuicSentPacketManager::QuicSentPacketManager(
enable_half_rtt_tail_loss_probe_(false),
using_pacing_(false),
use_new_rto_(false),
- handshake_confirmed_(false),
- use_general_loss_algorithm_(FLAGS_quic_general_loss_algorithm) {}
+ handshake_confirmed_(false) {}
QuicSentPacketManager::~QuicSentPacketManager() {}
@@ -172,10 +173,6 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
static_cast<QuicByteCount>(config.ReceivedSocketReceiveBuffer()));
QuicByteCount max_cwnd_bytes = static_cast<QuicByteCount>(
receive_buffer_bytes_ * kConservativeReceiveBufferFraction);
- if (FLAGS_quic_limit_max_cwnd) {
- max_cwnd_bytes =
- min(max_cwnd_bytes, kMaxCongestionWindow * kDefaultTCPMSS);
- }
send_algorithm_->SetMaxCongestionWindow(max_cwnd_bytes);
}
send_algorithm_->SetFromConfig(config, perspective_);
@@ -287,8 +284,7 @@ void QuicSentPacketManager::HandleAckForSentPackets(
const QuicAckFrame& ack_frame) {
// Go through the packets we have not received an ack for and see if this
// incoming_ack shows they've been seen by the peer.
- QuicTime::Delta delta_largest_observed =
- ack_frame.delta_time_largest_observed;
+ QuicTime::Delta ack_delay_time = ack_frame.ack_delay_time;
QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked();
for (QuicUnackedPacketMap::iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
@@ -322,12 +318,7 @@ void QuicSentPacketManager::HandleAckForSentPackets(
if (it->in_flight) {
packets_acked_.push_back(std::make_pair(packet_number, it->bytes_sent));
}
- MarkPacketHandled(packet_number, &(*it), delta_largest_observed);
- }
-
- // Discard any retransmittable frames associated with revived packets.
- if (ack_frame.latest_revived_packet != 0) {
- MarkPacketRevived(ack_frame.latest_revived_packet, delta_largest_observed);
+ MarkPacketHandled(packet_number, &(*it), ack_delay_time);
}
}
@@ -343,14 +334,10 @@ void QuicSentPacketManager::RetransmitUnackedPackets(
QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked();
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
- const RetransmittableFrames* frames = it->retransmittable_frames;
- if (frames != nullptr &&
+ if (!it->retransmittable_frames.empty() &&
(retransmission_type == ALL_UNACKED_RETRANSMISSION ||
it->encryption_level == ENCRYPTION_INITIAL)) {
MarkForRetransmission(packet_number, retransmission_type);
- } else if (it->is_fec_packet) {
- // Remove FEC packets from the packet map, since we can't retransmit them.
- unacked_packets_.RemoveFromInFlight(packet_number);
}
}
}
@@ -359,13 +346,17 @@ void QuicSentPacketManager::NeuterUnencryptedPackets() {
QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked();
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
- if (it->retransmittable_frames != nullptr &&
+ if (!it->retransmittable_frames.empty() &&
it->encryption_level == ENCRYPTION_NONE) {
// Once you're forward secure, no unencrypted packets will be sent, crypto
// or otherwise. Unencrypted packets are neutered and abandoned, to ensure
// they are not retransmitted or considered lost from a congestion control
// perspective.
- pending_retransmissions_.erase(packet_number);
+ if (delegate_ != nullptr) {
+ delegate_->OnUnencryptedPacketsNeutered(path_id_, packet_number);
+ } else {
+ pending_retransmissions_.erase(packet_number);
+ }
unacked_packets_.RemoveFromInFlight(packet_number);
unacked_packets_.RemoveRetransmittability(packet_number);
}
@@ -377,20 +368,25 @@ void QuicSentPacketManager::MarkForRetransmission(
TransmissionType transmission_type) {
const TransmissionInfo& transmission_info =
unacked_packets_.GetTransmissionInfo(packet_number);
- LOG_IF(DFATAL, transmission_info.retransmittable_frames == nullptr);
+ QUIC_BUG_IF(transmission_info.retransmittable_frames.empty());
// Both TLP and the new RTO leave the packets in flight and let the loss
// detection decide if packets are lost.
if (transmission_type != TLP_RETRANSMISSION &&
transmission_type != RTO_RETRANSMISSION) {
unacked_packets_.RemoveFromInFlight(packet_number);
}
- // TODO(ianswett): Currently the RTO can fire while there are pending NACK
- // retransmissions for the same data, which is not ideal.
- if (ContainsKey(pending_retransmissions_, packet_number)) {
- return;
- }
+ 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 (ContainsKey(pending_retransmissions_, packet_number)) {
+ return;
+ }
- pending_retransmissions_[packet_number] = transmission_type;
+ pending_retransmissions_[packet_number] = transmission_type;
+ }
}
void QuicSentPacketManager::RecordOneSpuriousRetransmission(
@@ -406,31 +402,11 @@ void QuicSentPacketManager::RecordOneSpuriousRetransmission(
void QuicSentPacketManager::RecordSpuriousRetransmissions(
const TransmissionInfo& info,
QuicPacketNumber acked_packet_number) {
- if (unacked_packets_.track_single_retransmission()) {
- QuicPacketNumber retransmission = info.retransmission;
- while (retransmission != 0) {
- const TransmissionInfo& retransmit_info =
- unacked_packets_.GetTransmissionInfo(retransmission);
- retransmission = retransmit_info.retransmission;
- RecordOneSpuriousRetransmission(retransmit_info);
- }
- return;
- }
- const PacketNumberList* all_transmissions = info.all_transmissions;
- for (PacketNumberList::const_reverse_iterator it =
- all_transmissions->rbegin();
- it != all_transmissions->rend() && *it > acked_packet_number; ++it) {
- // ianswett: Prevents crash in b/20552846.
- if (*it < unacked_packets_.GetLeastUnacked() ||
- *it > unacked_packets_.largest_sent_packet()) {
- QUIC_BUG << "Retransmission out of range:" << *it
- << " least unacked:" << unacked_packets_.GetLeastUnacked()
- << " largest sent:" << unacked_packets_.largest_sent_packet();
- return;
- }
+ QuicPacketNumber retransmission = info.retransmission;
+ while (retransmission != 0) {
const TransmissionInfo& retransmit_info =
- unacked_packets_.GetTransmissionInfo(*it);
-
+ unacked_packets_.GetTransmissionInfo(retransmission);
+ retransmission = retransmit_info.retransmission;
RecordOneSpuriousRetransmission(retransmit_info);
}
}
@@ -439,9 +415,8 @@ bool QuicSentPacketManager::HasPendingRetransmissions() const {
return !pending_retransmissions_.empty();
}
-QuicSentPacketManager::PendingRetransmission
-QuicSentPacketManager::NextPendingRetransmission() {
- LOG_IF(DFATAL, pending_retransmissions_.empty())
+PendingRetransmission QuicSentPacketManager::NextPendingRetransmission() {
+ QUIC_BUG_IF(pending_retransmissions_.empty())
<< "Unexpected call to PendingRetransmissions() with empty pending "
<< "retransmission list. Corrupted memory usage imminent.";
QuicPacketNumber packet_number = pending_retransmissions_.begin()->first;
@@ -460,10 +435,12 @@ QuicSentPacketManager::NextPendingRetransmission() {
DCHECK(unacked_packets_.IsUnacked(packet_number)) << packet_number;
const TransmissionInfo& transmission_info =
unacked_packets_.GetTransmissionInfo(packet_number);
- DCHECK(transmission_info.retransmittable_frames);
+ DCHECK(!transmission_info.retransmittable_frames.empty());
return PendingRetransmission(path_id_, packet_number, transmission_type,
- *transmission_info.retransmittable_frames,
+ transmission_info.retransmittable_frames,
+ transmission_info.has_crypto_handshake,
+ transmission_info.needs_padding,
transmission_info.encryption_level,
transmission_info.packet_number_length);
}
@@ -471,24 +448,18 @@ QuicSentPacketManager::NextPendingRetransmission() {
QuicPacketNumber QuicSentPacketManager::GetNewestRetransmission(
QuicPacketNumber packet_number,
const TransmissionInfo& transmission_info) const {
- if (unacked_packets_.track_single_retransmission()) {
- QuicPacketNumber retransmission = transmission_info.retransmission;
- while (retransmission != 0) {
- packet_number = retransmission;
- retransmission =
- unacked_packets_.GetTransmissionInfo(retransmission).retransmission;
- }
- return packet_number;
- } else {
- return transmission_info.all_transmissions == nullptr
- ? packet_number
- : *transmission_info.all_transmissions->rbegin();
+ QuicPacketNumber retransmission = transmission_info.retransmission;
+ while (retransmission != 0) {
+ packet_number = retransmission;
+ retransmission =
+ unacked_packets_.GetTransmissionInfo(retransmission).retransmission;
}
+ return packet_number;
}
-void QuicSentPacketManager::MarkPacketRevived(
+void QuicSentPacketManager::MarkPacketNotRetransmittable(
QuicPacketNumber packet_number,
- QuicTime::Delta delta_largest_observed) {
+ QuicTime::Delta ack_delay_time) {
if (!unacked_packets_.IsUnacked(packet_number)) {
return;
}
@@ -497,35 +468,39 @@ void QuicSentPacketManager::MarkPacketRevived(
unacked_packets_.GetTransmissionInfo(packet_number);
QuicPacketNumber newest_transmission =
GetNewestRetransmission(packet_number, transmission_info);
- // This packet has been revived at the receiver. If we were going to
- // retransmit it, do not retransmit it anymore.
- pending_retransmissions_.erase(newest_transmission);
-
- // The AckListener needs to be notified for revived packets,
- // since it indicates the packet arrived from the appliction's perspective.
- unacked_packets_.NotifyAndClearListeners(newest_transmission,
- delta_largest_observed);
+ // 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,
- QuicTime::Delta delta_largest_observed) {
+void QuicSentPacketManager::MarkPacketHandled(QuicPacketNumber packet_number,
+ TransmissionInfo* info,
+ QuicTime::Delta ack_delay_time) {
QuicPacketNumber newest_transmission =
GetNewestRetransmission(packet_number, *info);
// Remove the most recent packet, if it is pending retransmission.
- pending_retransmissions_.erase(newest_transmission);
+ if (delegate_ != nullptr) {
+ delegate_->OnPacketMarkedHandled(path_id_, newest_transmission,
+ ack_delay_time);
+ } else {
+ 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.
if (newest_transmission == packet_number) {
unacked_packets_.NotifyAndClearListeners(&info->ack_listeners,
- delta_largest_observed);
+ ack_delay_time);
} else {
unacked_packets_.NotifyAndClearListeners(newest_transmission,
- delta_largest_observed);
+ ack_delay_time);
RecordSpuriousRetransmissions(*info, packet_number);
// Remove the most recent packet from flight if it's a crypto handshake
// packet, since they won't be acked now that one has been processed.
@@ -560,15 +535,15 @@ bool QuicSentPacketManager::OnPacketSent(
SerializedPacket* serialized_packet,
QuicPacketNumber original_packet_number,
QuicTime sent_time,
- QuicByteCount bytes,
TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data) {
QuicPacketNumber packet_number = serialized_packet->packet_number;
DCHECK_LT(0u, packet_number);
DCHECK(!unacked_packets_.IsUnacked(packet_number));
- LOG_IF(DFATAL, bytes == 0) << "Cannot send empty packets.";
+ QUIC_BUG_IF(serialized_packet->encrypted_length == 0)
+ << "Cannot send empty packets.";
- if (original_packet_number != 0) {
+ if (delegate_ == nullptr && original_packet_number != 0) {
if (!pending_retransmissions_.erase(original_packet_number)) {
QUIC_BUG << "Expected packet number to be in "
<< "pending_retransmissions_. packet_number: "
@@ -580,23 +555,13 @@ bool QuicSentPacketManager::OnPacketSent(
--pending_timer_transmission_count_;
}
- // Only track packets as in flight that the send algorithm wants us to track.
- // Since FEC packets should also be counted towards the congestion window,
- // consider them as retransmittable for the purposes of congestion control.
- HasRetransmittableData has_congestion_controlled_data =
- serialized_packet->is_fec_packet ? HAS_RETRANSMITTABLE_DATA
- : has_retransmittable_data;
// TODO(ianswett): Remove sent_time, because it's unused.
const bool in_flight = send_algorithm_->OnPacketSent(
- sent_time, unacked_packets_.bytes_in_flight(), packet_number, bytes,
- has_congestion_controlled_data);
+ sent_time, unacked_packets_.bytes_in_flight(), packet_number,
+ serialized_packet->encrypted_length, has_retransmittable_data);
unacked_packets_.AddSentPacket(serialized_packet, original_packet_number,
- transmission_type, sent_time, bytes,
- in_flight);
-
- // Take ownership of the retransmittable frames before exiting.
- serialized_packet->retransmittable_frames = nullptr;
+ transmission_type, sent_time, in_flight);
// Reset the retransmission timer anytime a pending packet is sent.
return in_flight;
}
@@ -633,6 +598,10 @@ void QuicSentPacketManager::OnRetransmissionTimeout() {
case RTO_MODE:
++stats_->rto_count;
RetransmitRtoPackets();
+ if (network_change_visitor_ != nullptr &&
+ consecutive_rto_count_ == kMinTimeoutsBeforePathDegrading) {
+ network_change_visitor_->OnPathDegrading();
+ }
return;
}
}
@@ -645,8 +614,8 @@ void QuicSentPacketManager::RetransmitCryptoPackets() {
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
// Only retransmit frames which are in flight, and therefore have been sent.
- if (!it->in_flight || it->retransmittable_frames == nullptr ||
- it->retransmittable_frames->HasCryptoHandshake() != IS_HANDSHAKE) {
+ if (!it->in_flight || it->retransmittable_frames.empty() ||
+ !it->has_crypto_handshake) {
continue;
}
packet_retransmitted = true;
@@ -664,11 +633,11 @@ bool QuicSentPacketManager::MaybeRetransmitTailLossProbe() {
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
// Only retransmit frames which are in flight, and therefore have been sent.
- if (!it->in_flight || it->retransmittable_frames == nullptr) {
+ if (!it->in_flight || it->retransmittable_frames.empty()) {
continue;
}
if (!handshake_confirmed_) {
- DCHECK_NE(IS_HANDSHAKE, it->retransmittable_frames->HasCryptoHandshake());
+ DCHECK(!it->has_crypto_handshake);
}
MarkForRetransmission(packet_number, TLP_RETRANSMISSION);
return true;
@@ -679,26 +648,30 @@ bool QuicSentPacketManager::MaybeRetransmitTailLossProbe() {
}
void QuicSentPacketManager::RetransmitRtoPackets() {
- LOG_IF(DFATAL, pending_timer_transmission_count_ > 0)
+ QUIC_BUG_IF(pending_timer_transmission_count_ > 0)
<< "Retransmissions already queued:" << pending_timer_transmission_count_;
// Mark two packets for retransmission.
QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked();
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
- if (it->retransmittable_frames != nullptr &&
+ if (!it->retransmittable_frames.empty() &&
pending_timer_transmission_count_ < kMaxRetransmissionsOnTimeout) {
MarkForRetransmission(packet_number, RTO_RETRANSMISSION);
++pending_timer_transmission_count_;
}
// Abandon non-retransmittable data that's in flight to ensure it doesn't
// fill up the congestion window.
- const bool has_retransmissions =
- unacked_packets_.track_single_retransmission()
- ? it->retransmission != 0
- : it->all_transmissions != nullptr;
- if (it->retransmittable_frames == nullptr && it->in_flight &&
+ const bool has_retransmissions = it->retransmission != 0;
+ if (it->retransmittable_frames.empty() && it->in_flight &&
!has_retransmissions) {
+ // Log only for non-retransmittable data.
+ // Retransmittable data is marked as lost during loss detection, and will
+ // be logged later.
unacked_packets_.RemoveFromInFlight(packet_number);
+ if (debug_delegate_ != nullptr) {
+ debug_delegate_->OnPacketLoss(packet_number, RTO_RETRANSMISSION,
+ clock_->Now());
+ }
}
}
if (pending_timer_transmission_count_ > 0) {
@@ -727,55 +700,30 @@ QuicSentPacketManager::GetRetransmissionMode() const {
}
void QuicSentPacketManager::InvokeLossDetection(QuicTime time) {
- if (use_general_loss_algorithm_) {
- loss_algorithm_->DetectLosses(unacked_packets_, time, rtt_stats_,
- &packets_lost_);
- for (const std::pair<QuicPacketNumber, QuicByteCount>& pair :
- packets_lost_) {
- ++stats_->packets_lost;
- // TODO(ianswett): This could be optimized.
- if (unacked_packets_.HasRetransmittableFrames(pair.first)) {
- MarkForRetransmission(pair.first, LOSS_RETRANSMISSION);
- } else {
- // Since we will not retransmit this, we need to remove it from
- // unacked_packets_. This is either the current transmission of
- // a packet whose previous transmission has been acked, a packet that
- // has been TLP retransmitted, or an FEC packet.
- unacked_packets_.RemoveFromInFlight(pair.first);
- }
- }
- return;
- }
- PacketNumberSet lost_packets = loss_algorithm_->DetectLostPackets(
- unacked_packets_, time, unacked_packets_.largest_observed(), rtt_stats_);
- for (PacketNumberSet::const_iterator it = lost_packets.begin();
- it != lost_packets.end(); ++it) {
- QuicPacketNumber packet_number = *it;
- const TransmissionInfo& transmission_info =
- unacked_packets_.GetTransmissionInfo(packet_number);
- // TODO(ianswett): If it's expected the FEC packet may repair the loss, it
- // should be recorded as a loss to the send algorithm, but not retransmitted
- // until it's known whether the FEC packet arrived.
+ loss_algorithm_->DetectLosses(unacked_packets_, time, rtt_stats_,
+ &packets_lost_);
+ for (const pair<QuicPacketNumber, QuicByteCount>& pair : packets_lost_) {
++stats_->packets_lost;
- packets_lost_.push_back(
- std::make_pair(packet_number, transmission_info.bytes_sent));
- DVLOG(1) << ENDPOINT << "Lost packet " << packet_number;
+ if (debug_delegate_ != nullptr) {
+ debug_delegate_->OnPacketLoss(pair.first, LOSS_RETRANSMISSION, time);
+ }
- if (transmission_info.retransmittable_frames != nullptr) {
- MarkForRetransmission(packet_number, LOSS_RETRANSMISSION);
+ // TODO(ianswett): This could be optimized.
+ if (unacked_packets_.HasRetransmittableFrames(pair.first)) {
+ MarkForRetransmission(pair.first, LOSS_RETRANSMISSION);
} else {
// Since we will not retransmit this, we need to remove it from
// unacked_packets_. This is either the current transmission of
- // a packet whose previous transmission has been acked, a packet that has
- // been TLP retransmitted, or an FEC packet.
- unacked_packets_.RemoveFromInFlight(packet_number);
+ // a packet whose previous transmission has been acked or a packet that
+ // has been TLP retransmitted.
+ unacked_packets_.RemoveFromInFlight(pair.first);
}
}
}
bool QuicSentPacketManager::MaybeUpdateRTT(const QuicAckFrame& ack_frame,
- const QuicTime& ack_receive_time) {
- // We rely on delta_time_largest_observed to compute an RTT estimate, so we
+ QuicTime ack_receive_time) {
+ // We rely on ack_delay_time to compute an RTT estimate, so we
// only update rtt when the largest observed gets acked.
// NOTE: If ack is a truncated ack, then the largest observed is in fact
// unacked, and may cause an RTT sample to be taken.
@@ -795,8 +743,7 @@ bool QuicSentPacketManager::MaybeUpdateRTT(const QuicAckFrame& ack_frame,
QuicTime::Delta send_delta =
ack_receive_time.Subtract(transmission_info.sent_time);
- rtt_stats_.UpdateRtt(send_delta, ack_frame.delta_time_largest_observed,
- ack_receive_time);
+ rtt_stats_.UpdateRtt(send_delta, ack_frame.ack_delay_time, ack_receive_time);
if (network_change_visitor_ != nullptr) {
network_change_visitor_->OnRttChange();
@@ -813,8 +760,8 @@ QuicTime::Delta QuicSentPacketManager::TimeUntilSend(
if (pending_timer_transmission_count_ > 0) {
return QuicTime::Delta::Zero();
}
- return send_algorithm_->TimeUntilSend(now, unacked_packets_.bytes_in_flight(),
- retransmittable);
+ return send_algorithm_->TimeUntilSend(now,
+ unacked_packets_.bytes_in_flight());
}
// Uses a 25ms delayed ack timer. Also helps with better signaling
@@ -962,6 +909,9 @@ QuicPacketCount QuicSentPacketManager::GetSlowStartThresholdInTcpMss() 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 (HasRetransmittableFrames(it->first)) {
@@ -988,18 +938,28 @@ void QuicSentPacketManager::EnablePacing() {
}
void QuicSentPacketManager::OnConnectionMigration(PeerAddressChangeType type) {
- if (type == UNKNOWN) {
- return;
- }
-
- if (type == NAT_PORT_REBINDING || type == IPV4_SUBNET_REBINDING) {
+ 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.
return;
}
-
+ consecutive_rto_count_ = 0;
+ consecutive_tlp_count_ = 0;
rtt_stats_.OnConnectionMigration();
send_algorithm_->OnConnectionMigration();
}
+bool QuicSentPacketManager::InSlowStart() const {
+ return send_algorithm_->InSlowStart();
+}
+
+TransmissionInfo* QuicSentPacketManager::GetMutableTransmissionInfo(
+ QuicPacketNumber packet_number) {
+ return unacked_packets_.GetMutableTransmissionInfo(packet_number);
+}
+
+void QuicSentPacketManager::RemoveObsoletePackets() {
+ unacked_packets_.RemoveObsoletePackets();
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_sent_packet_manager.h b/chromium/net/quic/quic_sent_packet_manager.h
index 87dedbcad14..6d4241e1e3d 100644
--- a/chromium/net/quic/quic_sent_packet_manager.h
+++ b/chromium/net/quic/quic_sent_packet_manager.h
@@ -12,7 +12,6 @@
#include <utility>
#include <vector>
-#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/linked_hash_map.h"
@@ -41,6 +40,31 @@ struct QuicConnectionStats;
// previous transmission is acked, the data will not be retransmitted.
class NET_EXPORT_PRIVATE QuicSentPacketManager {
public:
+ // A delegate interface which manages pending retransmissions.
+ class MultipathDelegateInterface {
+ 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;
+ };
+
// 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.
@@ -58,6 +82,10 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
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
@@ -73,29 +101,12 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
// Called when RTT may have changed, including when an RTT is read from
// the config.
virtual void OnRttChange() = 0;
- };
- // Struct to store the pending retransmission information.
- struct PendingRetransmission {
- PendingRetransmission(QuicPathId path_id,
- QuicPacketNumber packet_number,
- TransmissionType transmission_type,
- const RetransmittableFrames& retransmittable_frames,
- EncryptionLevel encryption_level,
- QuicPacketNumberLength packet_number_length)
- : path_id(path_id),
- packet_number(packet_number),
- transmission_type(transmission_type),
- retransmittable_frames(retransmittable_frames),
- encryption_level(encryption_level),
- packet_number_length(packet_number_length) {}
-
- QuicPathId path_id;
- QuicPacketNumber packet_number;
- TransmissionType transmission_type;
- const RetransmittableFrames& retransmittable_frames;
- EncryptionLevel encryption_level;
- QuicPacketNumberLength packet_number_length;
+ // 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;
};
QuicSentPacketManager(Perspective perspective,
@@ -103,7 +114,8 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
const QuicClock* clock,
QuicConnectionStats* stats,
CongestionControlType congestion_control_type,
- LossDetectionType loss_type);
+ LossDetectionType loss_type,
+ MultipathDelegateInterface* delegate);
virtual ~QuicSentPacketManager();
virtual void SetFromConfig(const QuicConfig& config);
@@ -120,7 +132,7 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
// Processes the incoming ack.
void OnIncomingAck(const QuicAckFrame& ack_frame, QuicTime ack_receive_time);
- // Returns true if the non-FEC packet |packet_number| is unacked.
+ // Returns true if packet |packet_number| is unacked.
bool IsUnacked(QuicPacketNumber packet_number) const;
// Requests retransmission of all unacked packets of |retransmission_type|.
@@ -166,7 +178,6 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
virtual bool OnPacketSent(SerializedPacket* serialized_packet,
QuicPacketNumber original_packet_number,
QuicTime sent_time,
- QuicByteCount bytes,
TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data);
@@ -249,6 +260,8 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
network_change_visitor_ = visitor;
}
+ bool InSlowStart() const;
+
// Used in Chromium, but not in the server.
size_t consecutive_rto_count() const { return consecutive_rto_count_; }
@@ -308,8 +321,7 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
// Update the RTT if the ack is for the largest acked packet number.
// Returns true if the rtt was updated.
- bool MaybeUpdateRTT(const QuicAckFrame& ack_frame,
- const QuicTime& ack_receive_time);
+ bool MaybeUpdateRTT(const QuicAckFrame& ack_frame, QuicTime ack_receive_time);
// Invokes the loss detection algorithm and loses and retransmits packets if
// necessary.
@@ -322,17 +334,22 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
void MaybeInvokeCongestionEvent(bool rtt_updated,
QuicByteCount bytes_in_flight);
- // Marks |packet_number| as having been revived by the peer, but not
- // received, so the packet remains pending if it is and the congestion control
- // does not consider the packet acked.
- void MarkPacketRevived(QuicPacketNumber packet_number,
- QuicTime::Delta delta_largest_observed);
+ // 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,
- QuicTime::Delta delta_largest_observed);
+ QuicTime::Delta ack_delay_time);
// Request that |packet_number| be retransmitted after the other pending
// retransmissions. Does not add it to the retransmissions if it's already
@@ -351,8 +368,16 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
void RecordSpuriousRetransmissions(const TransmissionInfo& info,
QuicPacketNumber acked_packet_number);
- // Newly serialized retransmittable and fec packets are added to this map,
- // which contains owning pointers to any contained frames. If a packet is
+ // 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();
+
+ // Newly serialized retransmittable packets are added to this map, which
+ // contains owning pointers to any contained frames. If a packet is
// retransmitted, this map will contain entries for both the old and the new
// packet. The old packet's retransmittable frames entry will be nullptr,
// while the new packet's entry will contain the frames to retransmit.
@@ -371,6 +396,10 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
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_;
@@ -415,9 +444,6 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
// retransmittable frames.
bool handshake_confirmed_;
- // Latched value of FLAGS_gfe2_reloadable_flag_quic_general_loss_algorithm.
- const bool use_general_loss_algorithm_;
-
// Records bandwidth from server to client in normal operation, over periods
// of time with no loss events.
QuicSustainedBandwidthRecorder sustained_bandwidth_recorder_;
diff --git a/chromium/net/quic/quic_sent_packet_manager_test.cc b/chromium/net/quic/quic_sent_packet_manager_test.cc
index 719137ce4ae..5098261e5c5 100644
--- a/chromium/net/quic/quic_sent_packet_manager_test.cc
+++ b/chromium/net/quic/quic_sent_packet_manager_test.cc
@@ -33,6 +33,9 @@ const uint32_t kDefaultLength = 1000;
// Stream ID for data sent in CreatePacket().
const QuicStreamId kStreamId = 7;
+// Minimum number of consecutive RTOs before path is considered to be degrading.
+const size_t kMinTimeoutsBeforePathDegrading = 2;
+
// Matcher to check the key of the key-value pair it receives as first argument
// equals its second argument.
MATCHER(KeyEq, "") {
@@ -44,6 +47,10 @@ class MockDebugDelegate : public QuicSentPacketManager::DebugDelegate {
MOCK_METHOD2(OnSpuriousPacketRetransmission,
void(TransmissionType transmission_type,
QuicByteCount byte_size));
+ MOCK_METHOD3(OnPacketLoss,
+ void(QuicPacketNumber lost_packet_number,
+ TransmissionType transmission_type,
+ QuicTime detection_time));
};
class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
@@ -54,7 +61,8 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
&clock_,
&stats_,
kCubic,
- kNack),
+ kNack,
+ /*delegate=*/nullptr),
send_algorithm_(new StrictMock<MockSendAlgorithm>),
network_change_visitor_(new StrictMock<MockNetworkChangeVisitor>) {
// These tests only work with pacing enabled.
@@ -166,7 +174,7 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
QuicSentPacketManagerPeer::MarkForRetransmission(
&manager_, old_packet_number, TLP_RETRANSMISSION);
EXPECT_TRUE(manager_.HasPendingRetransmissions());
- QuicSentPacketManager::PendingRetransmission next_retransmission =
+ PendingRetransmission next_retransmission =
manager_.NextPendingRetransmission();
EXPECT_EQ(old_packet_number, next_retransmission.packet_number);
EXPECT_EQ(TLP_RETRANSMISSION, next_retransmission.transmission_type);
@@ -177,8 +185,7 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
.WillOnce(Return(true));
SerializedPacket packet(CreatePacket(new_packet_number, false));
manager_.OnPacketSent(&packet, old_packet_number, clock_.Now(),
- kDefaultLength, TLP_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
+ TLP_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_,
new_packet_number));
}
@@ -189,25 +196,14 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
SerializedPacket CreatePacket(QuicPacketNumber packet_number,
bool retransmittable) {
- packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
- RetransmittableFrames* frames = nullptr;
+ SerializedPacket packet(kDefaultPathId, packet_number,
+ PACKET_6BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
+ 0u, false, false);
if (retransmittable) {
- frames = new RetransmittableFrames();
- frames->AddFrame(
+ packet.retransmittable_frames.push_back(
QuicFrame(new QuicStreamFrame(kStreamId, false, 0, StringPiece())));
}
- return SerializedPacket(kDefaultPathId, packet_number,
- PACKET_6BYTE_PACKET_NUMBER, packets_.back(), 0u,
- frames, false, false);
- }
-
- SerializedPacket CreateFecPacket(QuicPacketNumber packet_number) {
- packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
- SerializedPacket serialized(kDefaultPathId, packet_number,
- PACKET_6BYTE_PACKET_NUMBER, packets_.back(), 0u,
- nullptr, false, false);
- serialized.is_fec_packet = true;
- return serialized;
+ return packet;
}
void SendDataPacket(QuicPacketNumber packet_number) {
@@ -216,8 +212,8 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
.Times(1)
.WillOnce(Return(true));
SerializedPacket packet(CreateDataPacket(packet_number));
- manager_.OnPacketSent(&packet, 0, clock_.Now(), packet.packet->length(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
}
void SendCryptoPacket(QuicPacketNumber packet_number) {
@@ -227,21 +223,11 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
.Times(1)
.WillOnce(Return(true));
SerializedPacket packet(CreateDataPacket(packet_number));
- packet.retransmittable_frames->AddFrame(
+ packet.retransmittable_frames.push_back(
QuicFrame(new QuicStreamFrame(1, false, 0, StringPiece())));
- manager_.OnPacketSent(&packet, 0, clock_.Now(), packet.packet->length(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
- }
-
- void SendFecPacket(QuicPacketNumber packet_number) {
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, BytesInFlight(), packet_number, kDefaultLength,
- HAS_RETRANSMITTABLE_DATA))
- .Times(1)
- .WillOnce(Return(true));
- SerializedPacket packet(CreateFecPacket(packet_number));
- manager_.OnPacketSent(&packet, 0, clock_.Now(), packet.packet->length(),
- NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA);
+ packet.has_crypto_handshake = IS_HANDSHAKE;
+ manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
}
void SendAckPacket(QuicPacketNumber packet_number) {
@@ -251,8 +237,8 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
.Times(1)
.WillOnce(Return(false));
SerializedPacket packet(CreatePacket(packet_number, false));
- manager_.OnPacketSent(&packet, 0, clock_.Now(), packet.packet->length(),
- NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA);
}
// Based on QuicConnection's WritePendingRetransmissions.
@@ -263,12 +249,10 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
HAS_RETRANSMITTABLE_DATA))
.Times(1)
.WillOnce(Return(true));
- const QuicSentPacketManager::PendingRetransmission pending =
- manager_.NextPendingRetransmission();
+ const PendingRetransmission pending = manager_.NextPendingRetransmission();
SerializedPacket packet(CreatePacket(retransmission_packet_number, false));
manager_.OnPacketSent(&packet, pending.packet_number, clock_.Now(),
- kDefaultLength, pending.transmission_type,
- HAS_RETRANSMITTABLE_DATA);
+ pending.transmission_type, HAS_RETRANSMITTABLE_DATA);
}
QuicSentPacketManager manager_;
@@ -490,6 +474,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
SendDataPacket(5);
ack_frame.largest_observed = 5;
ExpectAckAndLoss(true, 5, 2);
+ EXPECT_CALL(debug_delegate, OnPacketLoss(2, LOSS_RETRANSMISSION, _));
manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
VerifyUnackedPackets(nullptr, 0);
@@ -497,70 +482,6 @@ TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
EXPECT_EQ(2u, stats_.packets_spuriously_retransmitted);
}
-TEST_F(QuicSentPacketManagerTest, LoseButDontRetransmitRevivedPacket) {
- SendDataPacket(1);
- SendDataPacket(2);
- SendFecPacket(3);
- SendDataPacket(4);
-
- // Ack 2 and 3, and mark 1 as revived.
- QuicAckFrame ack_frame;
- ack_frame.largest_observed = 3;
- ack_frame.missing_packets.Add(1);
- ack_frame.latest_revived_packet = 1;
- QuicPacketNumber acked[] = {2, 3};
- ExpectAcksAndLosses(true, acked, arraysize(acked), nullptr, 0);
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
-
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- QuicPacketNumber unacked[] = {1, 4};
- VerifyUnackedPackets(unacked, arraysize(unacked));
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
- QuicPacketNumber retransmittable[] = {4};
- VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
-
- // Ack the 4th packet and expect the 1st to be considered lost.
- ack_frame.largest_observed = 4;
- ExpectAckAndLoss(true, 4, 1);
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
-
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- VerifyRetransmittablePackets(nullptr, 0);
-}
-
-TEST_F(QuicSentPacketManagerTest, MarkLostThenReviveAndDontRetransmitPacket) {
- SendDataPacket(1);
- SendDataPacket(2);
- SendDataPacket(3);
- SendDataPacket(4);
- SendFecPacket(5);
-
- // Ack 2, 3, and 4, and expect the 1st to be considered lost.
- QuicAckFrame ack_frame;
- ack_frame.largest_observed = 4;
- ack_frame.missing_packets.Add(1);
- QuicPacketNumber acked[] = {2, 3, 4};
- QuicPacketNumber lost[] = {1};
- ExpectAcksAndLosses(true, acked, arraysize(acked), lost, arraysize(lost));
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
-
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- QuicPacketNumber unacked[] = {1, 5};
- VerifyUnackedPackets(unacked, arraysize(unacked));
- QuicPacketNumber retransmittable[] = {1};
- VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
-
- // Ack 5th packet (FEC) and revive 1st packet. 1st packet should now be
- // removed from pending retransmissions map.
- ack_frame.largest_observed = 5;
- ack_frame.latest_revived_packet = 1;
- ExpectAck(5);
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
-
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- VerifyRetransmittablePackets(nullptr, 0);
-}
-
TEST_F(QuicSentPacketManagerTest, AckPreviousTransmissionThenTruncatedAck) {
SendDataPacket(1);
RetransmitAndSendPacket(1, 2);
@@ -608,53 +529,6 @@ TEST_F(QuicSentPacketManagerTest, GetLeastUnackedUnacked) {
EXPECT_EQ(1u, manager_.GetLeastUnacked());
}
-TEST_F(QuicSentPacketManagerTest, GetLeastUnackedUnackedFec) {
- SendFecPacket(1);
- EXPECT_EQ(1u, manager_.GetLeastUnacked());
-}
-
-TEST_F(QuicSentPacketManagerTest, GetLeastUnackedAndDiscard) {
- VerifyUnackedPackets(nullptr, 0);
-
- SendFecPacket(1);
- EXPECT_EQ(1u, manager_.GetLeastUnacked());
-
- SendFecPacket(2);
- EXPECT_EQ(1u, manager_.GetLeastUnacked());
-
- SendFecPacket(3);
- EXPECT_EQ(1u, manager_.GetLeastUnacked());
-
- QuicPacketNumber unacked[] = {1, 2, 3};
- VerifyUnackedPackets(unacked, arraysize(unacked));
- VerifyRetransmittablePackets(nullptr, 0);
-
- // Ack 2, so there's an rtt update.
- ExpectAck(2);
- QuicAckFrame ack_frame;
- ack_frame.largest_observed = 2;
- ack_frame.missing_packets.Add(1);
- manager_.OnIncomingAck(ack_frame, clock_.Now());
-
- EXPECT_EQ(1u, manager_.GetLeastUnacked());
-}
-
-TEST_F(QuicSentPacketManagerTest, GetSentTime) {
- VerifyUnackedPackets(nullptr, 0);
-
- QuicTime sent_time = clock_.Now();
- SendFecPacket(1);
- QuicTime sent_time2 = clock_.Now();
- SendFecPacket(2);
- QuicPacketNumber unacked[] = {1, 2};
- VerifyUnackedPackets(unacked, arraysize(unacked));
- VerifyRetransmittablePackets(nullptr, 0);
-
- EXPECT_TRUE(manager_.HasUnackedPackets());
- EXPECT_EQ(sent_time, QuicSentPacketManagerPeer::GetSentTime(&manager_, 1));
- EXPECT_EQ(sent_time2, QuicSentPacketManagerPeer::GetSentTime(&manager_, 2));
-}
-
TEST_F(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
SendDataPacket(1);
SendAckPacket(2);
@@ -662,7 +536,7 @@ TEST_F(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
// Now ack the ack and expect an RTT update.
QuicAckFrame ack_frame;
ack_frame.largest_observed = 2;
- ack_frame.delta_time_largest_observed = QuicTime::Delta::FromMilliseconds(5);
+ ack_frame.ack_delay_time = QuicTime::Delta::FromMilliseconds(5);
ExpectAck(1);
manager_.OnIncomingAck(ack_frame, clock_.Now());
@@ -684,7 +558,7 @@ TEST_F(QuicSentPacketManagerTest, Rtt) {
ExpectAck(packet_number);
QuicAckFrame ack_frame;
ack_frame.largest_observed = packet_number;
- ack_frame.delta_time_largest_observed = QuicTime::Delta::FromMilliseconds(5);
+ ack_frame.ack_delay_time = QuicTime::Delta::FromMilliseconds(5);
manager_.OnIncomingAck(ack_frame, clock_.Now());
EXPECT_EQ(expected_rtt,
QuicSentPacketManagerPeer::GetRttStats(&manager_)->latest_rtt());
@@ -692,7 +566,7 @@ TEST_F(QuicSentPacketManagerTest, Rtt) {
TEST_F(QuicSentPacketManagerTest, RttWithInvalidDelta) {
// Expect that the RTT is equal to the local time elapsed, since the
- // delta_time_largest_observed is larger than the local time elapsed
+ // ack_delay_time is larger than the local time elapsed
// and is hence invalid.
QuicPacketNumber packet_number = 1;
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
@@ -702,7 +576,7 @@ TEST_F(QuicSentPacketManagerTest, RttWithInvalidDelta) {
ExpectAck(packet_number);
QuicAckFrame ack_frame;
ack_frame.largest_observed = packet_number;
- ack_frame.delta_time_largest_observed = QuicTime::Delta::FromMilliseconds(11);
+ ack_frame.ack_delay_time = QuicTime::Delta::FromMilliseconds(11);
manager_.OnIncomingAck(ack_frame, clock_.Now());
EXPECT_EQ(expected_rtt,
QuicSentPacketManagerPeer::GetRttStats(&manager_)->latest_rtt());
@@ -710,7 +584,7 @@ TEST_F(QuicSentPacketManagerTest, RttWithInvalidDelta) {
TEST_F(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
// Expect that the RTT is equal to the local time elapsed, since the
- // delta_time_largest_observed is infinite, and is hence invalid.
+ // ack_delay_time is infinite, and is hence invalid.
QuicPacketNumber packet_number = 1;
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
SendDataPacket(packet_number);
@@ -719,7 +593,7 @@ TEST_F(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
ExpectAck(packet_number);
QuicAckFrame ack_frame;
ack_frame.largest_observed = packet_number;
- ack_frame.delta_time_largest_observed = QuicTime::Delta::Infinite();
+ ack_frame.ack_delay_time = QuicTime::Delta::Infinite();
manager_.OnIncomingAck(ack_frame, clock_.Now());
EXPECT_EQ(expected_rtt,
QuicSentPacketManagerPeer::GetRttStats(&manager_)->latest_rtt());
@@ -727,7 +601,7 @@ TEST_F(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
TEST_F(QuicSentPacketManagerTest, RttZeroDelta) {
// Expect that the RTT is the time between send and receive since the
- // delta_time_largest_observed is zero.
+ // ack_delay_time is zero.
QuicPacketNumber packet_number = 1;
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
SendDataPacket(packet_number);
@@ -736,7 +610,7 @@ TEST_F(QuicSentPacketManagerTest, RttZeroDelta) {
ExpectAck(packet_number);
QuicAckFrame ack_frame;
ack_frame.largest_observed = packet_number;
- ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero();
+ ack_frame.ack_delay_time = QuicTime::Delta::Zero();
manager_.OnIncomingAck(ack_frame, clock_.Now());
EXPECT_EQ(expected_rtt,
QuicSentPacketManagerPeer::GetRttStats(&manager_)->latest_rtt());
@@ -767,7 +641,7 @@ TEST_F(QuicSentPacketManagerTest, TailLossProbeTimeout) {
manager_.MaybeRetransmitTailLossProbe();
EXPECT_TRUE(manager_.HasPendingRetransmissions());
RetransmitNextPacket(3);
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Infinite()));
EXPECT_EQ(QuicTime::Delta::Infinite(),
manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA));
@@ -814,7 +688,7 @@ TEST_F(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
manager_.MaybeRetransmitTailLossProbe();
EXPECT_TRUE(manager_.HasPendingRetransmissions());
RetransmitNextPacket(101);
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Infinite()));
EXPECT_EQ(QuicTime::Delta::Infinite(),
manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA));
@@ -829,7 +703,7 @@ TEST_F(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe());
EXPECT_TRUE(manager_.HasPendingRetransmissions());
RetransmitNextPacket(102);
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Infinite()));
EXPECT_EQ(QuicTime::Delta::Infinite(),
manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA));
@@ -947,10 +821,6 @@ TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
RetransmitNextPacket(12);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
- if (!FLAGS_quic_track_single_retransmission) {
- EXPECT_EQ(8u, manager_.GetLeastUnacked());
- return;
- }
EXPECT_EQ(1u, manager_.GetLeastUnacked());
// Least unacked isn't raised until an ack is received, so ack the
// crypto packets.
@@ -1037,14 +907,17 @@ TEST_F(QuicSentPacketManagerTest,
// Retransmit the crypto packet as 2.
manager_.OnRetransmissionTimeout();
RetransmitNextPacket(2);
+ EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
// Retransmit the crypto packet as 3.
manager_.OnRetransmissionTimeout();
RetransmitNextPacket(3);
+ EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
// Now neuter all unacked unencrypted packets, which occurs when the
// connection goes forward secure.
manager_.NeuterUnencryptedPackets();
+ EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
QuicPacketNumber unacked[] = {1, 2, 3};
VerifyUnackedPackets(unacked, arraysize(unacked));
VerifyRetransmittablePackets(nullptr, 0);
@@ -1063,6 +936,9 @@ TEST_F(QuicSentPacketManagerTest,
}
TEST_F(QuicSentPacketManagerTest, RetransmissionTimeout) {
+ StrictMock<MockDebugDelegate> debug_delegate;
+ manager_.set_debug_delegate(&debug_delegate);
+
// Send 100 packets.
const size_t kNumSentPackets = 100;
for (size_t i = 1; i <= kNumSentPackets; ++i) {
@@ -1080,7 +956,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmissionTimeout) {
// Ack a retransmission.
QuicAckFrame ack_frame;
- ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero();
+ ack_frame.ack_delay_time = QuicTime::Delta::Zero();
ack_frame.largest_observed = 102;
ack_frame.missing_packets.Add(0, 102);
// Ensure no packets are lost.
@@ -1090,6 +966,11 @@ TEST_F(QuicSentPacketManagerTest, RetransmissionTimeout) {
EXPECT_CALL(*network_change_visitor_, OnCongestionWindowChange());
EXPECT_CALL(*network_change_visitor_, OnRttChange());
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
+ // RTO's use loss detection instead of immediately declaring retransmitted
+ // packets lost.
+ for (int i = 1; i <= 99; ++i) {
+ EXPECT_CALL(debug_delegate, OnPacketLoss(i, LOSS_RETRANSMISSION, _));
+ }
manager_.OnIncomingAck(ack_frame, clock_.Now());
}
@@ -1126,7 +1007,7 @@ TEST_F(QuicSentPacketManagerTest, NewRetransmissionTimeout) {
// Ack a retransmission and expect no call to OnRetransmissionTimeout.
QuicAckFrame ack_frame;
- ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero();
+ ack_frame.ack_delay_time = QuicTime::Delta::Zero();
ack_frame.largest_observed = 102;
ack_frame.missing_packets.Add(0, 102);
// This will include packets in the lost packet map.
@@ -1150,6 +1031,7 @@ TEST_F(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
EXPECT_FALSE(manager_.HasPendingRetransmissions());
// Rto a second time.
+ EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
manager_.OnRetransmissionTimeout();
EXPECT_TRUE(manager_.HasPendingRetransmissions());
EXPECT_EQ(2 * kDefaultLength,
@@ -1160,7 +1042,7 @@ TEST_F(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
// Ack a retransmission and ensure OnRetransmissionTimeout is called.
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
QuicAckFrame ack_frame;
- ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero();
+ ack_frame.ack_delay_time = QuicTime::Delta::Zero();
ack_frame.largest_observed = 2;
ack_frame.missing_packets.Add(1);
ExpectAck(2);
@@ -1183,6 +1065,7 @@ TEST_F(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
EXPECT_FALSE(manager_.HasPendingRetransmissions());
// Rto a second time.
+ EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
manager_.OnRetransmissionTimeout();
EXPECT_TRUE(manager_.HasPendingRetransmissions());
EXPECT_EQ(2 * kDefaultLength,
@@ -1193,7 +1076,7 @@ TEST_F(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
// Ack a retransmission and ensure OnRetransmissionTimeout is called.
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
QuicAckFrame ack_frame;
- ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero();
+ ack_frame.ack_delay_time = QuicTime::Delta::Zero();
ack_frame.largest_observed = 3;
ack_frame.missing_packets.Add(1, 3);
ExpectAck(3);
@@ -1204,6 +1087,21 @@ TEST_F(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
}
+TEST_F(QuicSentPacketManagerTest, OnPathDegrading) {
+ SendDataPacket(1);
+ QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(500);
+ EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
+ .WillRepeatedly(Return(delay));
+ for (size_t i = 1; i < kMinTimeoutsBeforePathDegrading; ++i) {
+ manager_.OnRetransmissionTimeout();
+ RetransmitNextPacket(i + 2);
+ }
+ // Next RTO should cause network_change_visitor_'s OnPathDegrading method
+ // to be called.
+ EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
+ manager_.OnRetransmissionTimeout();
+}
+
TEST_F(QuicSentPacketManagerTest, GetTransmissionTime) {
EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
}
@@ -1263,7 +1161,7 @@ TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeTailLossProbe) {
EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe());
EXPECT_TRUE(manager_.HasPendingRetransmissions());
RetransmitNextPacket(3);
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Infinite()));
EXPECT_EQ(QuicTime::Delta::Infinite(),
manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA));
@@ -1337,6 +1235,7 @@ TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
// If the delay is smaller than the min, ensure it exponentially backs off
// from the min.
+ EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
for (int i = 0; i < 5; ++i) {
EXPECT_EQ(delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
@@ -1361,6 +1260,7 @@ TEST_F(QuicSentPacketManagerTest, GetTransmissionDelay) {
.WillRepeatedly(Return(delay));
// Delay should back off exponentially.
+ EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
for (int i = 0; i < 5; ++i) {
EXPECT_EQ(delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
@@ -1382,12 +1282,7 @@ TEST_F(QuicSentPacketManagerTest, GetLossDelay) {
// Handle an ack which causes the loss algorithm to be evaluated and
// set the loss timeout.
ExpectAck(2);
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _));
QuicAckFrame ack_frame;
ack_frame.largest_observed = 2;
ack_frame.missing_packets.Add(1);
@@ -1400,12 +1295,7 @@ TEST_F(QuicSentPacketManagerTest, GetLossDelay) {
// Fire the retransmission timeout and ensure the loss detection algorithm
// is invoked.
- if (FLAGS_quic_general_loss_algorithm) {
- EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _));
- } else {
- EXPECT_CALL(*loss_algorithm, DetectLostPackets(_, _, _, _))
- .WillOnce(Return(PacketNumberSet()));
- }
+ EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _));
manager_.OnRetransmissionTimeout();
}
@@ -1620,18 +1510,19 @@ TEST_F(QuicSentPacketManagerTest,
// Ensure the smaller send window only allows 16 packets to be sent.
for (QuicPacketNumber i = 1; i <= 16; ++i) {
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Zero()));
EXPECT_EQ(QuicTime::Delta::Zero(),
manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, BytesInFlight(), i, 1024,
- HAS_RETRANSMITTABLE_DATA))
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, BytesInFlight(), i, kDefaultLength,
+ HAS_RETRANSMITTABLE_DATA))
.WillOnce(Return(true));
SerializedPacket packet(CreatePacket(i, true));
- manager_.OnPacketSent(&packet, 0, clock_.Now(), 1024, NOT_RETRANSMISSION,
+ manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
}
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Infinite()));
EXPECT_EQ(QuicTime::Delta::Infinite(),
manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA));
@@ -1643,18 +1534,19 @@ TEST_F(QuicSentPacketManagerTest, ReceiveWindowLimited) {
// Ensure the smaller send window only allows 256 * 0.95 packets to be sent.
for (QuicPacketNumber i = 1; i <= 244; ++i) {
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Zero()));
EXPECT_EQ(QuicTime::Delta::Zero(),
manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, BytesInFlight(), i, 1024,
- HAS_RETRANSMITTABLE_DATA))
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, BytesInFlight(), i, kDefaultLength,
+ HAS_RETRANSMITTABLE_DATA))
.WillOnce(Return(true));
SerializedPacket packet(CreatePacket(i, true));
- manager_.OnPacketSent(&packet, 0, clock_.Now(), 1024, NOT_RETRANSMISSION,
+ manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
}
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Infinite()));
EXPECT_EQ(QuicTime::Delta::Infinite(),
manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA));
@@ -1689,6 +1581,61 @@ TEST_F(QuicSentPacketManagerTest, ResumeConnectionState) {
static_cast<uint64_t>(manager_.GetRttStats()->initial_rtt_us()));
}
+TEST_F(QuicSentPacketManagerTest, ConnectionMigrationUnspecifiedChange) {
+ RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(&manager_);
+ int64_t default_init_rtt = rtt_stats->initial_rtt_us();
+ rtt_stats->set_initial_rtt_us(default_init_rtt * 2);
+ EXPECT_EQ(2 * default_init_rtt, rtt_stats->initial_rtt_us());
+
+ QuicSentPacketManagerPeer::SetConsecutiveRtoCount(&manager_, 1);
+ EXPECT_EQ(1u, manager_.consecutive_rto_count());
+ QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, 2);
+ EXPECT_EQ(2u, manager_.consecutive_tlp_count());
+
+ EXPECT_CALL(*send_algorithm_, OnConnectionMigration());
+ manager_.OnConnectionMigration(UNSPECIFIED_CHANGE);
+
+ EXPECT_EQ(default_init_rtt, rtt_stats->initial_rtt_us());
+ EXPECT_EQ(0u, manager_.consecutive_rto_count());
+ EXPECT_EQ(0u, manager_.consecutive_tlp_count());
+}
+
+TEST_F(QuicSentPacketManagerTest, ConnectionMigrationIPSubnetChange) {
+ RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(&manager_);
+ int64_t default_init_rtt = rtt_stats->initial_rtt_us();
+ rtt_stats->set_initial_rtt_us(default_init_rtt * 2);
+ EXPECT_EQ(2 * default_init_rtt, rtt_stats->initial_rtt_us());
+
+ QuicSentPacketManagerPeer::SetConsecutiveRtoCount(&manager_, 1);
+ EXPECT_EQ(1u, manager_.consecutive_rto_count());
+ QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, 2);
+ EXPECT_EQ(2u, manager_.consecutive_tlp_count());
+
+ manager_.OnConnectionMigration(IPV4_SUBNET_CHANGE);
+
+ EXPECT_EQ(2 * default_init_rtt, rtt_stats->initial_rtt_us());
+ EXPECT_EQ(1u, manager_.consecutive_rto_count());
+ EXPECT_EQ(2u, manager_.consecutive_tlp_count());
+}
+
+TEST_F(QuicSentPacketManagerTest, ConnectionMigrationPortChange) {
+ RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(&manager_);
+ int64_t default_init_rtt = rtt_stats->initial_rtt_us();
+ rtt_stats->set_initial_rtt_us(default_init_rtt * 2);
+ EXPECT_EQ(2 * default_init_rtt, rtt_stats->initial_rtt_us());
+
+ QuicSentPacketManagerPeer::SetConsecutiveRtoCount(&manager_, 1);
+ EXPECT_EQ(1u, manager_.consecutive_rto_count());
+ QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, 2);
+ EXPECT_EQ(2u, manager_.consecutive_tlp_count());
+
+ manager_.OnConnectionMigration(PORT_CHANGE);
+
+ EXPECT_EQ(2 * default_init_rtt, rtt_stats->initial_rtt_us());
+ EXPECT_EQ(1u, manager_.consecutive_rto_count());
+ EXPECT_EQ(2u, manager_.consecutive_tlp_count());
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_session.cc b/chromium/net/quic/quic_session.cc
index 24a6e99d6c2..de558968e98 100644
--- a/chromium/net/quic/quic_session.cc
+++ b/chromium/net/quic/quic_session.cc
@@ -5,6 +5,7 @@
#include "net/quic/quic_session.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "net/quic/crypto/proof_verifier.h"
#include "net/quic/quic_bug_tracker.h"
@@ -13,9 +14,8 @@
#include "net/quic/quic_flow_controller.h"
#include "net/ssl/ssl_info.h"
+using base::IntToString;
using base::StringPiece;
-using base::hash_map;
-using base::hash_set;
using std::make_pair;
using std::map;
using std::max;
@@ -28,84 +28,11 @@ namespace net {
#define ENDPOINT \
(perspective() == Perspective::IS_SERVER ? "Server: " : " Client: ")
-// We want to make sure we delete any closed streams in a safe manner.
-// To avoid deleting a stream in mid-operation, we have a simple shim between
-// us and the stream, so we can delete any streams when we return from
-// processing.
-//
-// We could just override the base methods, but this makes it easier to make
-// sure we don't miss any.
-class VisitorShim : public QuicConnectionVisitorInterface {
- public:
- explicit VisitorShim(QuicSession* session) : session_(session) {}
-
- void OnStreamFrame(const QuicStreamFrame& frame) override {
- session_->OnStreamFrame(frame);
- session_->PostProcessAfterData();
- }
- void OnRstStream(const QuicRstStreamFrame& frame) override {
- session_->OnRstStream(frame);
- session_->PostProcessAfterData();
- }
-
- void OnGoAway(const QuicGoAwayFrame& frame) override {
- session_->OnGoAway(frame);
- session_->PostProcessAfterData();
- }
-
- void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override {
- session_->OnWindowUpdateFrame(frame);
- session_->PostProcessAfterData();
- }
-
- void OnBlockedFrame(const QuicBlockedFrame& frame) override {
- session_->OnBlockedFrame(frame);
- session_->PostProcessAfterData();
- }
-
- void OnCanWrite() override {
- session_->OnCanWrite();
- session_->PostProcessAfterData();
- }
-
- void OnCongestionWindowChange(QuicTime now) override {
- session_->OnCongestionWindowChange(now);
- }
-
- void OnSuccessfulVersionNegotiation(const QuicVersion& version) override {
- session_->OnSuccessfulVersionNegotiation(version);
- }
-
- void OnConnectionClosed(QuicErrorCode error, bool from_peer) override {
- session_->OnConnectionClosed(error, from_peer);
- // The session will go away, so don't bother with cleanup.
- }
-
- void OnWriteBlocked() override { session_->OnWriteBlocked(); }
-
- void OnConnectionMigration() override { session_->OnConnectionMigration(); }
-
- bool WillingAndAbleToWrite() const override {
- return session_->WillingAndAbleToWrite();
- }
-
- bool HasPendingHandshake() const override {
- return session_->HasPendingHandshake();
- }
-
- bool HasOpenDynamicStreams() const override {
- return session_->HasOpenDynamicStreams();
- }
-
- private:
- QuicSession* session_;
-};
-
QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config)
: connection_(connection),
- visitor_shim_(new VisitorShim(this)),
config_(config),
- max_open_streams_(config_.MaxStreamsPerConnection()),
+ max_open_outgoing_streams_(config_.MaxStreamsPerConnection()),
+ max_open_incoming_streams_(config_.MaxStreamsPerConnection()),
next_outgoing_stream_id_(perspective() == Perspective::IS_SERVER ? 2 : 3),
largest_peer_created_stream_id_(
perspective() == Perspective::IS_SERVER ? 1 : 0),
@@ -118,10 +45,11 @@ QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config)
perspective(),
kMinimumFlowControlSendWindow,
config_.GetInitialSessionFlowControlWindowToSend(),
- false) {}
+ false),
+ currently_writing_stream_id_(0) {}
void QuicSession::Initialize() {
- connection_->set_visitor(visitor_shim_.get());
+ connection_->set_visitor(this);
connection_->SetFromConfig(config_);
DCHECK_EQ(kCryptoStreamId, GetCryptoStream()->id());
@@ -133,12 +61,12 @@ QuicSession::~QuicSession() {
STLDeleteValues(&dynamic_stream_map_);
DLOG_IF(WARNING, num_locally_closed_incoming_streams_highest_offset() >
- max_open_streams_)
+ 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_streams_)
+ DLOG_IF(WARNING, GetNumLocallyClosedOutgoingStreamsHighestOffset() >
+ max_open_outgoing_streams_)
<< "Surprisingly high number of locally closed self initiated streams"
"still waiting for final byte offset: "
<< GetNumLocallyClosedOutgoingStreamsHighestOffset();
@@ -163,8 +91,9 @@ void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) {
void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
if (ContainsKey(static_stream_map_, frame.stream_id)) {
- connection()->SendConnectionCloseWithDetails(
- QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream");
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
@@ -181,7 +110,9 @@ void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) {
DCHECK(frame.last_good_stream_id < next_outgoing_stream_id_);
}
-void QuicSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) {
+void QuicSession::OnConnectionClosed(QuicErrorCode error,
+ const string& /*error_details*/,
+ ConnectionCloseSource source) {
DCHECK(!connection_->connected());
if (error_ == QUIC_NO_ERROR) {
error_ = error;
@@ -190,7 +121,7 @@ void QuicSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) {
while (!dynamic_stream_map_.empty()) {
StreamMap::iterator it = dynamic_stream_map_.begin();
QuicStreamId id = it->first;
- it->second->OnConnectionClosed(error, from_peer);
+ it->second->OnConnectionClosed(error, source);
// The stream should call CloseStream as part of OnConnectionClosed.
if (dynamic_stream_map_.find(id) != dynamic_stream_map_.end()) {
QUIC_BUG << ENDPOINT << "Stream failed to close under OnConnectionClosed";
@@ -202,6 +133,8 @@ void QuicSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) {
void QuicSession::OnSuccessfulVersionNegotiation(
const QuicVersion& /*version*/) {}
+void QuicSession::OnPathDegrading() {}
+
void QuicSession::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
// Stream may be closed by the time we receive a WINDOW_UPDATE, so we can't
// assume that it still exists.
@@ -251,26 +184,29 @@ void QuicSession::OnCanWrite() {
return;
}
- QuicConnection::ScopedPacketBundler ack_bundler(connection_.get(),
- QuicConnection::NO_ACK);
+ QuicConnection::ScopedPacketBundler ack_bundler(
+ connection_.get(), QuicConnection::SEND_ACK_IF_QUEUED);
for (size_t i = 0; i < num_writes; ++i) {
if (!(write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
write_blocked_streams_.HasWriteBlockedDataStreams())) {
// Writing one stream removed another!? Something's broken.
QUIC_BUG << "WriteBlockedStream is missing";
- connection_->CloseConnection(QUIC_INTERNAL_ERROR, false);
+ connection_->CloseConnection(QUIC_INTERNAL_ERROR,
+ "WriteBlockedStream is missing",
+ ConnectionCloseBehavior::SILENT_CLOSE);
return;
}
if (!connection_->CanWriteStreamData()) {
return;
}
- QuicStreamId stream_id = write_blocked_streams_.PopFront();
- ReliableQuicStream* stream = GetStream(stream_id);
+ currently_writing_stream_id_ = write_blocked_streams_.PopFront();
+ ReliableQuicStream* stream = GetStream(currently_writing_stream_id_);
if (stream != nullptr && !stream->flow_controller()->IsBlocked()) {
// If the stream can't write all bytes it'll re-add itself to the blocked
// list.
stream->OnCanWrite();
}
+ currently_writing_stream_id_ = 0;
}
}
@@ -293,21 +229,25 @@ bool QuicSession::HasOpenDynamicStreams() const {
locally_closed_streams_highest_offset_.size()) > 0;
}
+void QuicSession::ProcessUdpPacket(const IPEndPoint& self_address,
+ const IPEndPoint& peer_address,
+ const QuicReceivedPacket& packet) {
+ connection_->ProcessUdpPacket(self_address, peer_address, packet);
+}
+
QuicConsumedData QuicSession::WritevData(
QuicStreamId id,
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- FecProtection fec_protection,
QuicAckListenerInterface* ack_notifier_delegate) {
- if (FLAGS_quic_block_unencrypted_writes && !IsEncryptionEstablished() &&
- id != kCryptoStreamId) {
+ if (!IsEncryptionEstablished() && id != kCryptoStreamId) {
// Do not let streams write without encryption. The calling stream will end
// up write blocked until OnCanWrite is next called.
return QuicConsumedData(0, false);
}
- QuicConsumedData data = connection_->SendStreamData(
- id, iov, offset, fin, fec_protection, ack_notifier_delegate);
+ QuicConsumedData data =
+ connection_->SendStreamData(id, iov, offset, fin, ack_notifier_delegate);
write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed);
return data;
}
@@ -339,6 +279,15 @@ void QuicSession::CloseStream(QuicStreamId stream_id) {
CloseStreamInner(stream_id, false);
}
+void QuicSession::InsertLocallyClosedStreamsHighestOffset(
+ const QuicStreamId id,
+ QuicStreamOffset offset) {
+ locally_closed_streams_highest_offset_[id] = offset;
+ if (IsIncomingStream(id)) {
+ ++num_locally_closed_incoming_streams_highest_offset_;
+ }
+}
+
void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
@@ -363,11 +312,8 @@ void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
// of the how many bytes the stream's flow controller believes it has
// received, for accurate connection level flow control accounting.
if (!stream->HasFinalReceivedByteOffset()) {
- locally_closed_streams_highest_offset_[stream_id] =
- stream->flow_controller()->highest_received_byte_offset();
- if (IsIncomingStream(stream_id)) {
- ++num_locally_closed_incoming_streams_highest_offset_;
- }
+ InsertLocallyClosedStreamsHighestOffset(
+ stream_id, stream->flow_controller()->highest_received_byte_offset());
}
dynamic_stream_map_.erase(it);
@@ -402,9 +348,10 @@ void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset(
flow_controller_.highest_received_byte_offset() + offset_diff)) {
// If the final offset violates flow control, close the connection now.
if (flow_controller_.FlowControlViolation()) {
- connection_->SendConnectionCloseWithDetails(
+ connection_->CloseConnection(
QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
- "Connection level flow control violation");
+ "Connection level flow control violation",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
}
@@ -429,15 +376,6 @@ void QuicSession::OnConfigNegotiated() {
uint32_t max_streams = config_.MaxStreamsPerConnection();
if (perspective() == Perspective::IS_SERVER) {
- // A server should accept a small number of additional streams beyond the
- // limit sent to the client. This helps avoid early connection termination
- // when FIN/RSTs for old streams are lost or arrive out of order.
- // Use a minimum number of additional streams, or a percentage increase,
- // whichever is larger.
- max_streams =
- max(max_streams + kMaxStreamsMinimumIncrement,
- static_cast<uint32_t>(max_streams * kMaxStreamsMultiplier));
-
if (config_.HasReceivedConnectionOptions()) {
if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kAFCW)) {
// The following variations change the initial receive flow control
@@ -455,7 +393,18 @@ void QuicSession::OnConfigNegotiated() {
}
}
}
- set_max_open_streams(max_streams);
+
+ set_max_open_outgoing_streams(max_streams);
+
+ // A small number of additional incoming streams beyond the limit should be
+ // allowed. This helps avoid early connection termination when FIN/RSTs for
+ // old streams are lost or arrive out of order.
+ // 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));
+ set_max_open_incoming_streams(max_incoming_streams);
if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) {
// Streams which were created before the SHLO was received (0-RTT
@@ -513,8 +462,9 @@ void QuicSession::HandleFrameOnNonexistentOutgoingStream(
DCHECK(!IsClosedStream(stream_id));
// Received a frame for a locally-created stream that is not currently
// active. This is an error.
- CloseConnectionWithDetails(QUIC_INVALID_STREAM_ID,
- "Data for nonexistent stream");
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Data for nonexistent stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
void QuicSession::HandleRstOnValidNonexistentStream(
@@ -536,8 +486,9 @@ void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) {
<< new_window
<< ", below default: " << kMinimumFlowControlSendWindow;
if (connection_->connected()) {
- connection_->SendConnectionCloseWithDetails(
- QUIC_FLOW_CONTROL_INVALID_WINDOW, "New stream window too low");
+ connection_->CloseConnection(
+ QUIC_FLOW_CONTROL_INVALID_WINDOW, "New stream window too low",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
return;
}
@@ -557,8 +508,9 @@ void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) {
<< new_window
<< ", below default: " << kMinimumFlowControlSendWindow;
if (connection_->connected()) {
- connection_->SendConnectionCloseWithDetails(
- QUIC_FLOW_CONTROL_INVALID_WINDOW, "New connection window too low");
+ connection_->CloseConnection(
+ QUIC_FLOW_CONTROL_INVALID_WINDOW, "New connection window too low",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
return;
}
@@ -572,9 +524,7 @@ void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
// to QuicSession since it is the glue.
case ENCRYPTION_FIRST_ESTABLISHED:
// Given any streams blocked by encryption a chance to write.
- if (FLAGS_quic_block_unencrypted_writes) {
- OnCanWrite();
- }
+ OnCanWrite();
break;
case ENCRYPTION_REESTABLISHED:
@@ -582,13 +532,11 @@ void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
// decrypted by the peer.
connection_->RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION);
// Given any streams blocked by encryption a chance to write.
- if (FLAGS_quic_block_unencrypted_writes) {
- OnCanWrite();
- }
+ OnCanWrite();
break;
case HANDSHAKE_CONFIRMED:
- LOG_IF(DFATAL, !config_.negotiated())
+ QUIC_BUG_IF(!config_.negotiated())
<< ENDPOINT << "Handshake confirmed without parameter negotiation.";
// Discard originally encrypted packets, since they can't be decrypted by
// the peer.
@@ -647,11 +595,46 @@ void QuicSession::StreamDraining(QuicStreamId stream_id) {
}
}
-void QuicSession::CloseConnectionWithDetails(QuicErrorCode error,
- const char* details) {
- if (connection()->connected()) {
- connection()->SendConnectionCloseWithDetails(error, details);
+bool QuicSession::MaybeIncreaseLargestPeerStreamId(
+ const QuicStreamId stream_id) {
+ if (stream_id <= largest_peer_created_stream_id_) {
+ return true;
+ }
+
+ // Check if the new number of available streams would cause the number of
+ // available streams to exceed the limit. Note that the peer can create
+ // only alternately-numbered streams.
+ size_t additional_available_streams =
+ (stream_id - largest_peer_created_stream_id_) / 2 - 1;
+ size_t new_num_available_streams =
+ GetNumAvailableStreams() + additional_available_streams;
+ if (new_num_available_streams > MaxAvailableStreams()) {
+ DVLOG(1) << "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());
+ connection()->CloseConnection(
+ QUIC_TOO_MANY_AVAILABLE_STREAMS, details.c_str(),
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ for (QuicStreamId id = largest_peer_created_stream_id_ + 2; id < stream_id;
+ id += 2) {
+ available_streams_.insert(id);
}
+ largest_peer_created_stream_id_ = stream_id;
+
+ return true;
+}
+
+bool QuicSession::ShouldYield(QuicStreamId stream_id) {
+ if (stream_id == currently_writing_stream_id_) {
+ return false;
+ }
+ return write_blocked_streams()->ShouldYield(stream_id);
}
ReliableQuicStream* QuicSession::GetOrCreateDynamicStream(
@@ -678,65 +661,39 @@ ReliableQuicStream* QuicSession::GetOrCreateDynamicStream(
available_streams_.erase(stream_id);
- if (stream_id > largest_peer_created_stream_id_) {
- // Check if the new number of available streams would cause the number of
- // available streams to exceed the limit. Note that the peer can create
- // only alternately-numbered streams.
- size_t additional_available_streams =
- (stream_id - largest_peer_created_stream_id_) / 2 - 1;
- size_t new_num_available_streams =
- GetNumAvailableStreams() + additional_available_streams;
- if (new_num_available_streams > get_max_available_streams()) {
- DVLOG(1) << "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 "
- << get_max_available_streams() << ".";
- CloseConnectionWithDetails(
- QUIC_TOO_MANY_AVAILABLE_STREAMS,
- base::StringPrintf(
- "%lu above %lu",
- static_cast<unsigned long>(new_num_available_streams),
- static_cast<unsigned long>(get_max_available_streams()))
- .c_str());
- return nullptr;
- }
- for (QuicStreamId id = largest_peer_created_stream_id_ + 2; id < stream_id;
- id += 2) {
- available_streams_.insert(id);
- }
- largest_peer_created_stream_id_ = stream_id;
+ if (!MaybeIncreaseLargestPeerStreamId(stream_id)) {
+ return nullptr;
}
// Check if the new number of open streams would cause the number of
// open streams to exceed the limit.
- size_t num_current_open_streams =
- FLAGS_quic_distinguish_incoming_outgoing_streams
- ? GetNumOpenIncomingStreams()
- : dynamic_stream_map_.size() - draining_streams_.size() +
- locally_closed_streams_highest_offset_.size();
- if (num_current_open_streams >= get_max_open_streams()) {
+ if (GetNumOpenIncomingStreams() >= max_open_incoming_streams()) {
if (connection()->version() <= QUIC_VERSION_27) {
- CloseConnectionWithDetails(QUIC_TOO_MANY_OPEN_STREAMS,
- "Old style stream rejection");
+ connection()->CloseConnection(
+ QUIC_TOO_MANY_OPEN_STREAMS, "Old style stream rejection",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
} else {
// Refuse to open the stream.
SendRstStream(stream_id, QUIC_REFUSED_STREAM, 0);
}
return nullptr;
}
- ReliableQuicStream* stream = CreateIncomingDynamicStream(stream_id);
- if (stream == nullptr) {
- return nullptr;
- }
- ActivateStream(stream);
- return stream;
+
+ return CreateIncomingDynamicStream(stream_id);
}
-void QuicSession::set_max_open_streams(size_t max_open_streams) {
- DVLOG(1) << "Setting max_open_streams_ to " << max_open_streams;
- DVLOG(1) << "Setting get_max_available_streams() to "
- << get_max_available_streams();
- max_open_streams_ = max_open_streams;
+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;
+ max_open_incoming_streams_ = max_open_incoming_streams;
+ 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;
+ max_open_outgoing_streams_ = max_open_outgoing_streams;
}
bool QuicSession::goaway_sent() const {
@@ -749,8 +706,7 @@ bool QuicSession::goaway_received() const {
bool QuicSession::IsClosedStream(QuicStreamId id) {
DCHECK_NE(0u, id);
- if (ContainsKey(static_stream_map_, id) ||
- ContainsKey(dynamic_stream_map_, id)) {
+ if (IsOpenStream(id)) {
// Stream is active
return false;
}
@@ -764,6 +720,16 @@ bool QuicSession::IsClosedStream(QuicStreamId id) {
!ContainsKey(available_streams_, id);
}
+bool QuicSession::IsOpenStream(QuicStreamId id) {
+ DCHECK_NE(0u, id);
+ if (ContainsKey(static_stream_map_, id) ||
+ ContainsKey(dynamic_stream_map_, id)) {
+ // Stream is active
+ return true;
+ }
+ return false;
+}
+
size_t QuicSession::GetNumOpenIncomingStreams() const {
return num_dynamic_incoming_streams_ - num_draining_incoming_streams_ +
num_locally_closed_incoming_streams_highest_offset_;
@@ -782,21 +748,11 @@ size_t QuicSession::GetNumAvailableStreams() const {
return available_streams_.size();
}
-void QuicSession::MarkConnectionLevelWriteBlocked(QuicStreamId id,
- SpdyPriority priority) {
-#ifndef NDEBUG
- ReliableQuicStream* stream = GetStream(id);
- if (stream != nullptr) {
- LOG_IF(DFATAL, priority != stream->Priority())
- << ENDPOINT << "Stream " << id
- << "Priorities do not match. Got: " << static_cast<int>(priority)
- << " Expected: " << static_cast<int>(stream->Priority());
- } else {
- QUIC_BUG << "Marking unknown stream " << id << " blocked.";
- }
-#endif
+void QuicSession::MarkConnectionLevelWriteBlocked(QuicStreamId id) {
+ QUIC_BUG_IF(GetStream(id) == nullptr) << "Marking unknown stream " << id
+ << " blocked.";
- write_blocked_streams_.AddStream(id, priority);
+ write_blocked_streams_.AddStream(id);
}
bool QuicSession::HasDataToWrite() const {
@@ -841,6 +797,10 @@ bool QuicSession::IsStreamFlowControlBlocked() {
return false;
}
+size_t QuicSession::MaxAvailableStreams() const {
+ return max_open_incoming_streams_ * kMaxAvailableStreamsMultiplier;
+}
+
bool QuicSession::IsIncomingStream(QuicStreamId id) const {
return id % 2 != next_outgoing_stream_id_ % 2;
}
diff --git a/chromium/net/quic/quic_session.h b/chromium/net/quic/quic_session.h
index 87fa1083484..b072c9b0a0f 100644
--- a/chromium/net/quic/quic_session.h
+++ b/chromium/net/quic/quic_session.h
@@ -11,10 +11,11 @@
#include <map>
#include <string>
+#include <unordered_map>
+#include <unordered_set>
#include <vector>
#include "base/compiler_specific.h"
-#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
@@ -31,7 +32,6 @@ namespace net {
class QuicCryptoStream;
class QuicFlowController;
class ReliableQuicStream;
-class VisitorShim;
namespace test {
class QuicSessionPeer;
@@ -69,24 +69,32 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
void OnGoAway(const QuicGoAwayFrame& frame) override;
void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
void OnBlockedFrame(const QuicBlockedFrame& frame) override;
- void OnConnectionClosed(QuicErrorCode error, bool from_peer) override;
+ void OnConnectionClosed(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) override;
void OnWriteBlocked() override {}
void OnSuccessfulVersionNegotiation(const QuicVersion& version) override;
void OnCanWrite() override;
void OnCongestionWindowChange(QuicTime /*now*/) override {}
- void OnConnectionMigration() override {}
+ void OnConnectionMigration(PeerAddressChangeType type) override {}
+ // Deletes streams that are safe to be deleted now that it's safe to do so (no
+ // other operations are being done on the streams at this time).
+ void PostProcessAfterData() override;
bool WillingAndAbleToWrite() const override;
bool HasPendingHandshake() const override;
bool HasOpenDynamicStreams() const override;
+ void OnPathDegrading() override;
+
+ // Called on every incoming packet. Passes |packet| through to |connection_|.
+ virtual void ProcessUdpPacket(const IPEndPoint& self_address,
+ const IPEndPoint& peer_address,
+ const QuicReceivedPacket& packet);
// Called by streams when they want to write data to the peer.
// Returns a pair with the number of bytes consumed from data, and a boolean
// indicating if the fin bit was consumed. This does not indicate the data
// has been sent on the wire: it may have been turned into a packet and queued
- // if the socket was unexpectedly blocked. |fec_protection| indicates if
- // data is to be FEC protected. Note that data that is sent immediately
- // following MUST_FEC_PROTECT data may get protected by falling within the
- // same FEC group.
+ // if the socket was unexpectedly blocked.
// If provided, |ack_notifier_delegate| will be registered to be notified when
// we have seen ACKs for all packets resulting from this call.
virtual QuicConsumedData WritevData(
@@ -94,7 +102,6 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- FecProtection fec_protection,
QuicAckListenerInterface* ack_notifier_delegate);
// Called by streams when they want to close the stream in both directions.
@@ -174,7 +181,7 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// connection-level flow control but not by its own stream-level flow control.
// The stream will be given a chance to write when a connection-level
// WINDOW_UPDATE arrives.
- void MarkConnectionLevelWriteBlocked(QuicStreamId id, SpdyPriority priority);
+ void MarkConnectionLevelWriteBlocked(QuicStreamId id);
// Returns true if the session has data to be sent, either queued in the
// connection, or in a write-blocked stream.
@@ -196,30 +203,35 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// Returns true if any stream is flow controller blocked.
bool IsStreamFlowControlBlocked();
- size_t get_max_open_streams() const { return max_open_streams_; }
+ size_t max_open_incoming_streams() const {
+ return max_open_incoming_streams_;
+ }
- size_t get_max_available_streams() const {
- return max_open_streams_ * kMaxAvailableStreamsMultiplier;
+ size_t max_open_outgoing_streams() const {
+ return max_open_outgoing_streams_;
}
+ size_t MaxAvailableStreams() const;
+
ReliableQuicStream* GetStream(const QuicStreamId stream_id);
// Mark a stream as draining.
virtual void StreamDraining(QuicStreamId id);
- // Close the connection, if it is not already closed.
- void CloseConnectionWithDetails(QuicErrorCode error, const char* details);
+ // Returns true if this stream should yield writes to another blocked stream.
+ bool ShouldYield(QuicStreamId stream_id);
protected:
- typedef base::hash_map<QuicStreamId, ReliableQuicStream*> StreamMap;
+ typedef std::unordered_map<QuicStreamId, ReliableQuicStream*> StreamMap;
- // Creates a new stream, owned by the caller, to handle a peer-initiated
- // stream. Returns nullptr and does error handling if the stream can not be
- // created.
+ // Creates a new stream to handle a peer-initiated stream.
+ // Caller does not own the returned stream.
+ // Returns nullptr and does error handling if the stream can not be created.
virtual ReliableQuicStream* CreateIncomingDynamicStream(QuicStreamId id) = 0;
- // Create a new stream, owned by the caller, to handle a locally-initiated
- // stream. Returns nullptr if max streams have already been opened.
+ // Create a new stream to handle a locally-initiated stream.
+ // Caller does not own the returned stream.
+ // Returns nullptr if max streams have already been opened.
virtual ReliableQuicStream* CreateOutgoingDynamicStream(
SpdyPriority priority) = 0;
@@ -238,14 +250,9 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// and |stream_id| is a peer-created id, then a new stream is created and
// returned. However if |stream_id| is a locally-created id and no such stream
// exists, the connection is closed.
+ // Caller does not own the returned stream.
ReliableQuicStream* GetOrCreateDynamicStream(QuicStreamId stream_id);
- // This is called after every call other than OnConnectionClose from the
- // QuicConnectionVisitor to allow post-processing once the work has been done.
- // In this case, it deletes streams given that it's safe to do so (no other
- // operations are being done on the streams at this time)
- virtual void PostProcessAfterData();
-
// Performs the work required to close |stream_id|. If |locally_reset|
// then the stream has been reset by this endpoint, not by the peer.
virtual void CloseStreamInner(QuicStreamId stream_id, bool locally_reset);
@@ -271,7 +278,8 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
return &closed_streams_;
}
- void set_max_open_streams(size_t max_open_streams);
+ void set_max_open_incoming_streams(size_t max_open_incoming_streams);
+ void set_max_open_outgoing_streams(size_t max_open_outgoing_streams);
void set_largest_peer_created_stream_id(
QuicStreamId largest_peer_created_stream_id) {
@@ -292,6 +300,9 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
size_t GetNumLocallyClosedOutgoingStreamsHighestOffset() const;
+ // Returns true if the stream is still active.
+ bool IsOpenStream(QuicStreamId id);
+
QuicStreamId next_outgoing_stream_id() const {
return next_outgoing_stream_id_;
}
@@ -303,6 +314,10 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// stream to be promised before creating an active stream.
virtual void HandleFrameOnNonexistentOutgoingStream(QuicStreamId stream_id);
+ bool MaybeIncreaseLargestPeerStreamId(const QuicStreamId stream_id);
+
+ void InsertLocallyClosedStreamsHighestOffset(const QuicStreamId id,
+ QuicStreamOffset offset);
// If stream is a locally closed stream, this RST will update FIN offset.
// Otherwise stream is a preserved stream and the behavior of it depends on
// derived class's own implementation.
@@ -311,7 +326,6 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
private:
friend class test::QuicSessionPeer;
- friend class VisitorShim;
// Called in OnConfigNegotiated when we receive a new stream level flow
// control window in a negotiated config. Closes the connection if invalid.
@@ -336,16 +350,15 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
scoped_ptr<QuicConnection> connection_;
- // A shim to stand between the connection and the session, to handle stream
- // deletions.
- scoped_ptr<VisitorShim> visitor_shim_;
-
std::vector<ReliableQuicStream*> closed_streams_;
QuicConfig config_;
- // Returns the maximum number of streams this connection can open.
- size_t max_open_streams_;
+ // The maximum number of outgoing streams this connection can open.
+ size_t max_open_outgoing_streams_;
+
+ // The maximum number of incoming streams this connection will allow.
+ size_t max_open_incoming_streams_;
// Static streams, such as crypto and header streams. Owned by child classes
// that create these streams.
@@ -359,12 +372,12 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// Set of stream ids that are less than the largest stream id that has been
// received, but are nonetheless available to be created.
- base::hash_set<QuicStreamId> available_streams_;
+ std::unordered_set<QuicStreamId> available_streams_;
// Set of stream ids that are "draining" -- a FIN has been sent and received,
// but the stream object still exists because not all the received data has
// been consumed.
- base::hash_set<QuicStreamId> draining_streams_;
+ std::unordered_set<QuicStreamId> draining_streams_;
// A list of streams which need to write more data.
QuicWriteBlockedList write_blocked_streams_;
@@ -387,6 +400,10 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// Used for connection-level flow control.
QuicFlowController flow_controller_;
+ // The stream id which was last popped in OnCanWrite, or 0, if not under the
+ // call stack of OnCanWrite.
+ QuicStreamId currently_writing_stream_id_;
+
DISALLOW_COPY_AND_ASSIGN(QuicSession);
};
diff --git a/chromium/net/quic/quic_session_test.cc b/chromium/net/quic/quic_session_test.cc
index 6d71a77d939..2c180737aba 100644
--- a/chromium/net/quic/quic_session_test.cc
+++ b/chromium/net/quic/quic_session_test.cc
@@ -6,7 +6,6 @@
#include <set>
-#include "base/containers/hash_tables.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
@@ -31,7 +30,6 @@
#include "testing/gmock_mutant.h"
#include "testing/gtest/include/gtest/gtest.h"
-using base::hash_map;
using std::set;
using std::string;
using std::vector;
@@ -89,10 +87,6 @@ class TestStream : public QuicSpdyStream {
void OnDataAvailable() override {}
- void SendBody(const string& data, bool fin) {
- WriteOrBufferData(data, fin, nullptr);
- }
-
MOCK_METHOD0(OnCanWrite, void());
};
@@ -103,11 +97,7 @@ class StreamBlocker {
: session_(session), stream_id_(stream_id) {}
void MarkConnectionLevelWriteBlocked() {
- session_->MarkConnectionLevelWriteBlocked(stream_id_, kDefaultPriority);
- }
-
- void MarkHighPriorityWriteBlocked() {
- session_->MarkConnectionLevelWriteBlocked(stream_id_, kHighestPriority);
+ session_->MarkConnectionLevelWriteBlocked(stream_id_);
}
private:
@@ -135,15 +125,24 @@ class TestSession : public QuicSpdySession {
TestStream* CreateIncomingDynamicStream(QuicStreamId id) override {
// Enforce the limit on the number of open streams.
- if (GetNumOpenIncomingStreams() + 1 > get_max_open_streams()) {
- connection()->SendConnectionCloseWithDetails(QUIC_TOO_MANY_OPEN_STREAMS,
- "Too many streams!");
+ if (GetNumOpenIncomingStreams() + 1 > max_open_incoming_streams()) {
+ connection()->CloseConnection(
+ QUIC_TOO_MANY_OPEN_STREAMS, "Too many streams!",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return nullptr;
} else {
- return new TestStream(id, this);
+ TestStream* stream = new TestStream(id, this);
+ ActivateStream(stream);
+ return stream;
}
}
+ bool ShouldCreateIncomingDynamicStream(QuicStreamId /*id*/) override {
+ return true;
+ }
+
+ bool ShouldCreateOutgoingDynamicStream() override { return true; }
+
bool IsClosedStream(QuicStreamId id) {
return QuicSession::IsClosedStream(id);
}
@@ -157,15 +156,14 @@ class TestSession : public QuicSpdySession {
QuicIOVector data,
QuicStreamOffset offset,
bool fin,
- FecProtection fec_protection,
QuicAckListenerInterface* ack_notifier_delegate) override {
QuicConsumedData consumed(data.total_length, fin);
if (!writev_consumes_all_data_) {
- consumed = QuicSession::WritevData(id, data, offset, fin, fec_protection,
- ack_notifier_delegate);
+ consumed =
+ QuicSession::WritevData(id, data, offset, fin, ack_notifier_delegate);
}
- QuicSessionPeer::GetWriteBlockedStreams(this)
- ->UpdateBytesForStream(id, consumed.bytes_consumed);
+ QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
+ id, consumed.bytes_consumed);
return consumed;
}
@@ -175,8 +173,7 @@ class TestSession : public QuicSpdySession {
QuicConsumedData SendStreamData(QuicStreamId id) {
struct iovec iov;
- return WritevData(id, MakeIOVector("not empty", &iov), 0, true,
- MAY_FEC_PROTECT, nullptr);
+ return WritevData(id, MakeIOVector("not empty", &iov), 0, true, nullptr);
}
QuicConsumedData SendLargeFakeData(QuicStreamId id, int bytes) {
@@ -184,8 +181,7 @@ class TestSession : public QuicSpdySession {
struct iovec iov;
iov.iov_base = nullptr; // should not be read.
iov.iov_len = static_cast<size_t>(bytes);
- return WritevData(id, QuicIOVector(&iov, 1, bytes), 0, true,
- MAY_FEC_PROTECT, nullptr);
+ return WritevData(id, QuicIOVector(&iov, 1, bytes), 0, true, nullptr);
}
using QuicSession::PostProcessAfterData;
@@ -338,10 +334,10 @@ TEST_P(QuicSessionTestServer, IsClosedStreamPeerCreated) {
TEST_P(QuicSessionTestServer, MaximumAvailableOpenedStreams) {
QuicStreamId stream_id = kClientDataStreamId1;
session_.GetOrCreateDynamicStream(stream_id);
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0);
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
EXPECT_NE(nullptr,
session_.GetOrCreateDynamicStream(
- stream_id + 2 * (session_.get_max_open_streams() - 1)));
+ stream_id + 2 * (session_.max_open_incoming_streams() - 1)));
}
TEST_P(QuicSessionTestServer, TooManyAvailableStreams) {
@@ -349,20 +345,20 @@ TEST_P(QuicSessionTestServer, TooManyAvailableStreams) {
QuicStreamId stream_id2;
EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id1));
// A stream ID which is too large to create.
- stream_id2 = stream_id1 + 2 * session_.get_max_available_streams() + 4;
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_TOO_MANY_AVAILABLE_STREAMS, _));
+ stream_id2 = stream_id1 + 2 * session_.MaxAvailableStreams() + 4;
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id2));
}
TEST_P(QuicSessionTestServer, ManyAvailableStreams) {
// When max_open_streams_ is 200, should be able to create 200 streams
// out-of-order, that is, creating the one with the largest stream ID first.
- QuicSessionPeer::SetMaxOpenStreams(&session_, 200);
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
QuicStreamId stream_id = kClientDataStreamId1;
// Create one stream.
session_.GetOrCreateDynamicStream(stream_id);
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0);
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
// Create the largest stream ID of a threatened total of 200 streams.
session_.GetOrCreateDynamicStream(stream_id + 2 * (200 - 1));
}
@@ -373,20 +369,9 @@ TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
// Close the stream.
EXPECT_CALL(*connection_, SendRstStream(closed_stream_id, _, _));
stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
- EXPECT_DEBUG_DFATAL(session_.MarkConnectionLevelWriteBlocked(
- closed_stream_id, kDefaultPriority),
- "Marking unknown stream 2 blocked.");
-}
-
-TEST_P(QuicSessionTestServer,
- DebugDFatalIfMarkWriteBlockedCalledWithWrongPriority) {
- const SpdyPriority kDifferentPriority = 0;
-
- TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
- EXPECT_NE(kDifferentPriority, stream2->Priority());
- EXPECT_DEBUG_DFATAL(session_.MarkConnectionLevelWriteBlocked(
- stream2->id(), kDifferentPriority),
- "Priorities do not match. Got: 0 Expected: 3");
+ EXPECT_DEBUG_DFATAL(
+ session_.MarkConnectionLevelWriteBlocked(closed_stream_id),
+ "Marking unknown stream 2 blocked.");
}
TEST_P(QuicSessionTestServer, OnCanWrite) {
@@ -394,43 +379,33 @@ TEST_P(QuicSessionTestServer, OnCanWrite) {
TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream2->id(), kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream6->id(), kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream4->id(), kDefaultPriority);
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ session_.MarkConnectionLevelWriteBlocked(stream6->id());
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
InSequence s;
StreamBlocker stream2_blocker(&session_, stream2->id());
- if (FLAGS_quic_batch_writes) {
- // Reregister, to test the loop limit.
- EXPECT_CALL(*stream2, OnCanWrite())
- .WillOnce(Invoke(&stream2_blocker,
- &StreamBlocker::MarkConnectionLevelWriteBlocked));
- // 2 will get called a second time as it didn't finish its block
- EXPECT_CALL(*stream2, OnCanWrite());
- EXPECT_CALL(*stream6, OnCanWrite());
- // 4 will not get called, as we exceeded the loop limit.
- } else {
- // Reregister, to test the loop limit.
- EXPECT_CALL(*stream2, OnCanWrite())
- .WillOnce(Invoke(&stream2_blocker,
- &StreamBlocker::MarkConnectionLevelWriteBlocked));
- EXPECT_CALL(*stream6, OnCanWrite());
- EXPECT_CALL(*stream4, OnCanWrite());
- }
+ // Reregister, to test the loop limit.
+ EXPECT_CALL(*stream2, OnCanWrite())
+ .WillOnce(Invoke(&stream2_blocker,
+ &StreamBlocker::MarkConnectionLevelWriteBlocked));
+ // 2 will get called a second time as it didn't finish its block
+ EXPECT_CALL(*stream2, OnCanWrite());
+ EXPECT_CALL(*stream6, OnCanWrite());
+ // 4 will not get called, as we exceeded the loop limit.
session_.OnCanWrite();
EXPECT_TRUE(session_.WillingAndAbleToWrite());
}
TEST_P(QuicSessionTestServer, TestBatchedWrites) {
- ValueRestore<bool> old_flag(&FLAGS_quic_batch_writes, true);
TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
session_.set_writev_consumes_all_data(true);
- session_.MarkConnectionLevelWriteBlocked(stream2->id(), kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream4->id(), kDefaultPriority);
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
StreamBlocker stream2_blocker(&session_, stream2->id());
StreamBlocker stream4_blocker(&session_, stream4->id());
@@ -441,13 +416,15 @@ TEST_P(QuicSessionTestServer, TestBatchedWrites) {
InSequence s;
EXPECT_CALL(*stream2, OnCanWrite())
.WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
- &session_, &TestSession::SendLargeFakeData,
+ &TestSession::SendLargeFakeData,
+ base::Unretained(&session_),
stream2->id(), 6000))),
Invoke(&stream2_blocker,
&StreamBlocker::MarkConnectionLevelWriteBlocked)));
EXPECT_CALL(*stream2, OnCanWrite())
.WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
- &session_, &TestSession::SendLargeFakeData,
+ &TestSession::SendLargeFakeData,
+ base::Unretained(&session_),
stream2->id(), 6000))),
Invoke(&stream2_blocker,
&StreamBlocker::MarkConnectionLevelWriteBlocked)));
@@ -457,13 +434,15 @@ TEST_P(QuicSessionTestServer, TestBatchedWrites) {
// write quota and we move over to stream 4.
EXPECT_CALL(*stream2, OnCanWrite())
.WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
- &session_, &TestSession::SendLargeFakeData,
+ &TestSession::SendLargeFakeData,
+ base::Unretained(&session_),
stream2->id(), 6000))),
Invoke(&stream2_blocker,
&StreamBlocker::MarkConnectionLevelWriteBlocked)));
EXPECT_CALL(*stream4, OnCanWrite())
.WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
- &session_, &TestSession::SendLargeFakeData,
+ &TestSession::SendLargeFakeData,
+ base::Unretained(&session_),
stream4->id(), 6000))),
Invoke(&stream4_blocker,
&StreamBlocker::MarkConnectionLevelWriteBlocked)));
@@ -475,28 +454,31 @@ TEST_P(QuicSessionTestServer, TestBatchedWrites) {
stream6->SetPriority(kHighestPriority);
EXPECT_CALL(*stream4, OnCanWrite())
.WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
- &session_, &TestSession::SendLargeFakeData,
- stream4->id(), 6000))),
+ &TestSession::SendLargeFakeData,
+ base::Unretained(&session_), stream4->id(), 6000))),
Invoke(&stream4_blocker,
&StreamBlocker::MarkConnectionLevelWriteBlocked),
Invoke(&stream6_blocker,
- &StreamBlocker::MarkHighPriorityWriteBlocked)));
+ &StreamBlocker::MarkConnectionLevelWriteBlocked)));
EXPECT_CALL(*stream6, OnCanWrite())
.WillOnce(testing::IgnoreResult(Invoke(CreateFunctor(
- &session_, &TestSession::SendLargeFakeData, stream4->id(), 6000))));
+ &TestSession::SendLargeFakeData,
+ base::Unretained(&session_), stream4->id(), 6000))));
session_.OnCanWrite();
// Stream4 alread did 6k worth of writes, so after doing another 12k it should
// cede and 2 should resume.
EXPECT_CALL(*stream4, OnCanWrite())
.WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
- &session_, &TestSession::SendLargeFakeData,
+ &TestSession::SendLargeFakeData,
+ base::Unretained(&session_),
stream4->id(), 12000))),
Invoke(&stream4_blocker,
&StreamBlocker::MarkConnectionLevelWriteBlocked)));
EXPECT_CALL(*stream2, OnCanWrite())
.WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
- &session_, &TestSession::SendLargeFakeData,
+ &TestSession::SendLargeFakeData,
+ base::Unretained(&session_),
stream2->id(), 6000))),
Invoke(&stream2_blocker,
&StreamBlocker::MarkConnectionLevelWriteBlocked)));
@@ -516,29 +498,34 @@ TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) {
TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream2->id(), kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream6->id(), kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream4->id(), kDefaultPriority);
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ session_.MarkConnectionLevelWriteBlocked(stream6->id());
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
- EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
.WillRepeatedly(Return(QuicTime::Delta::Zero()));
EXPECT_CALL(*send_algorithm, GetCongestionWindow())
.WillRepeatedly(Return(kMaxPacketSize * 10));
EXPECT_CALL(*stream2, OnCanWrite())
.WillOnce(testing::IgnoreResult(Invoke(CreateFunctor(
- &session_, &TestSession::SendStreamData, stream2->id()))));
+ &TestSession::SendStreamData,
+ base::Unretained(&session_), stream2->id()))));
EXPECT_CALL(*stream4, OnCanWrite())
.WillOnce(testing::IgnoreResult(Invoke(CreateFunctor(
- &session_, &TestSession::SendStreamData, stream4->id()))));
+ &TestSession::SendStreamData,
+ base::Unretained(&session_),
+ stream4->id()))));
EXPECT_CALL(*stream6, OnCanWrite())
.WillOnce(testing::IgnoreResult(Invoke(CreateFunctor(
- &session_, &TestSession::SendStreamData, stream6->id()))));
+ &TestSession::SendStreamData,
+ base::Unretained(&session_),
+ stream6->id()))));
// 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(_, _, _, _))
+ EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _));
session_.OnCanWrite();
@@ -556,18 +543,18 @@ TEST_P(QuicSessionTestServer, OnCanWriteCongestionControlBlocks) {
TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream2->id(), kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream6->id(), kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream4->id(), kDefaultPriority);
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ session_.MarkConnectionLevelWriteBlocked(stream6->id());
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
StreamBlocker stream2_blocker(&session_, stream2->id());
- EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Zero()));
EXPECT_CALL(*stream2, OnCanWrite());
- EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Zero()));
EXPECT_CALL(*stream6, OnCanWrite());
- EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Infinite()));
// stream4->OnCanWrite is not called.
@@ -575,14 +562,14 @@ TEST_P(QuicSessionTestServer, OnCanWriteCongestionControlBlocks) {
EXPECT_TRUE(session_.WillingAndAbleToWrite());
// Still congestion-control blocked.
- EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Infinite()));
session_.OnCanWrite();
EXPECT_TRUE(session_.WillingAndAbleToWrite());
// stream4->OnCanWrite is called once the connection stops being
// congestion-control blocked.
- EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _))
+ EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
.WillOnce(Return(QuicTime::Delta::Zero()));
EXPECT_CALL(*stream4, OnCanWrite());
session_.OnCanWrite();
@@ -604,7 +591,7 @@ TEST_P(QuicSessionTestServer, BufferedHandshake) {
EXPECT_FALSE(session_.HasPendingHandshake());
// Blocking (due to buffering of) the Crypto stream is detected.
- session_.MarkConnectionLevelWriteBlocked(kCryptoStreamId, kHighestPriority);
+ session_.MarkConnectionLevelWriteBlocked(kCryptoStreamId);
EXPECT_TRUE(session_.HasPendingHandshake());
TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
@@ -638,9 +625,9 @@ TEST_P(QuicSessionTestServer, OnCanWriteWithClosedStream) {
TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream2->id(), kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream6->id(), kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream4->id(), kDefaultPriority);
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ session_.MarkConnectionLevelWriteBlocked(stream6->id());
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
CloseStream(stream6->id());
InSequence s;
@@ -659,13 +646,13 @@ TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
// Mark the crypto and headers streams as write blocked, we expect them to be
// allowed to write later.
- session_.MarkConnectionLevelWriteBlocked(kCryptoStreamId, kHighestPriority);
- session_.MarkConnectionLevelWriteBlocked(kHeadersStreamId, kHighestPriority);
+ session_.MarkConnectionLevelWriteBlocked(kCryptoStreamId);
+ session_.MarkConnectionLevelWriteBlocked(kHeadersStreamId);
// Create a data stream, and although it is write blocked we never expect it
// to be allowed to write as we are connection level flow control blocked.
TestStream* stream = session_.CreateOutgoingDynamicStream(kDefaultPriority);
- session_.MarkConnectionLevelWriteBlocked(stream->id(), kDefaultPriority);
+ session_.MarkConnectionLevelWriteBlocked(stream->id());
EXPECT_CALL(*stream, OnCanWrite()).Times(0);
// The crypto and headers streams should be called even though we are
@@ -683,7 +670,7 @@ TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
TEST_P(QuicSessionTestServer, SendGoAway) {
MockPacketWriter* writer = static_cast<MockPacketWriter*>(
QuicConnectionPeer::GetWriter(session_.connection()));
- EXPECT_CALL(*writer, WritePacket(_, _, _, _))
+ EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
EXPECT_CALL(*connection_, SendGoAway(_, _, _))
.WillOnce(Invoke(connection_, &MockConnection::ReallySendGoAway));
@@ -721,32 +708,6 @@ TEST_P(QuicSessionTestServer, RstStreamBeforeHeadersDecompressed) {
EXPECT_TRUE(connection_->connected());
}
-TEST_P(QuicSessionTestServer, MultipleRstStreamsCauseSingleConnectionClose) {
- // If multiple invalid reset stream frames arrive in a single packet, this
- // should trigger a connection close. However there is no need to send
- // multiple connection close frames.
-
- // Create valid stream.
- QuicStreamFrame data1(kClientDataStreamId1, false, 0, StringPiece("HT"));
- session_.OnStreamFrame(data1);
- EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
-
- // Process first invalid stream reset, resulting in the connection being
- // closed.
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_TOO_MANY_AVAILABLE_STREAMS, _));
-
- const QuicStreamId kLargeInvalidStreamId = 99999999;
- QuicRstStreamFrame rst1(kLargeInvalidStreamId, QUIC_STREAM_NO_ERROR, 0);
- session_.OnRstStream(rst1);
- QuicConnectionPeer::CloseConnection(connection_);
-
- // Processing of second invalid stream reset should not result in the
- // connection being closed for a second time.
- QuicRstStreamFrame rst2(kLargeInvalidStreamId, QUIC_STREAM_NO_ERROR, 0);
- session_.OnRstStream(rst2);
-}
-
TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
// Test that if a stream is flow control blocked, then on receipt of the SHLO
// containing a suitable send window offset, the stream becomes unblocked.
@@ -763,7 +724,7 @@ TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
EXPECT_CALL(*connection_, SendBlocked(stream2->id()));
EXPECT_CALL(*connection_, SendBlocked(0));
- stream2->SendBody(body, false);
+ stream2->WriteOrBufferBody(body, false, nullptr);
EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
@@ -1013,8 +974,8 @@ TEST_P(QuicSessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(),
kInvalidWindow);
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_FLOW_CONTROL_INVALID_WINDOW, _));
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
session_.OnConfigNegotiated();
}
@@ -1025,8 +986,8 @@ TEST_P(QuicSessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(),
kInvalidWindow);
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_FLOW_CONTROL_INVALID_WINDOW, _));
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
session_.OnConfigNegotiated();
}
@@ -1034,8 +995,8 @@ 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.
const uint64_t kLargeOffset = kInitialSessionFlowControlWindowForTest + 1;
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _))
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _))
.Times(2);
// Check that stream frame + FIN results in connection close.
@@ -1078,7 +1039,7 @@ TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
// with a FIN or RST then we send a connection close or an RST to
// refuse streams.
const QuicStreamId kMaxStreams = 5;
- QuicSessionPeer::SetMaxOpenStreams(&session_, kMaxStreams);
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
const QuicStreamId kFirstStreamId = kClientDataStreamId1;
const QuicStreamId kFinalStreamId = kClientDataStreamId1 + 2 * kMaxStreams;
@@ -1094,7 +1055,7 @@ TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
if (GetParam() <= QUIC_VERSION_27) {
EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(QUIC_TOO_MANY_OPEN_STREAMS, _));
+ CloseConnection(QUIC_TOO_MANY_OPEN_STREAMS, _, _));
EXPECT_CALL(*connection_, SendRstStream(kFinalStreamId, _, _)).Times(0);
} else {
EXPECT_CALL(*connection_,
@@ -1115,15 +1076,14 @@ TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
// it) does not count against the open quota (because it is closed from the
// protocol point of view).
if (GetParam() <= QUIC_VERSION_27) {
- EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(QUIC_TOO_MANY_OPEN_STREAMS, _))
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_TOO_MANY_OPEN_STREAMS, _, _))
.Times(0);
} else {
EXPECT_CALL(*connection_, SendRstStream(_, QUIC_REFUSED_STREAM, _))
.Times(0);
}
const QuicStreamId kMaxStreams = 5;
- QuicSessionPeer::SetMaxOpenStreams(&session_, kMaxStreams);
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
// Create kMaxStreams + 1 data streams, and mark them draining.
const QuicStreamId kFirstStreamId = kClientDataStreamId1;
@@ -1142,6 +1102,22 @@ TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
session_.PostProcessAfterData();
}
+TEST_P(QuicSessionTestServer, TestMaxIncomingAndOutgoingStreamsAllowed) {
+ // Tests that on server side, the value of max_open_incoming/outgoing streams
+ // are setup correctly during negotiation.
+ // The value for outgoing stream is limited to negotiated value and for
+ // incoming stream it is set to be larger than that.
+ session_.OnConfigNegotiated();
+ // The max number of open outgoing streams is less than that of incoming
+ // streams, and it should be same as negotiated value.
+ EXPECT_LT(session_.max_open_outgoing_streams(),
+ session_.max_open_incoming_streams());
+ EXPECT_EQ(session_.max_open_outgoing_streams(),
+ kDefaultMaxStreamsPerConnection);
+ EXPECT_GT(session_.max_open_incoming_streams(),
+ kDefaultMaxStreamsPerConnection);
+}
+
class QuicSessionTestClient : public QuicSessionTestBase {
protected:
QuicSessionTestClient() : QuicSessionTestBase(Perspective::IS_CLIENT) {}
@@ -1190,8 +1166,21 @@ TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) {
// The stream is not waiting for the arrival of the peer's final offset as it
// was received with the FIN earlier.
- EXPECT_EQ(0u, QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_)
- .size());
+ EXPECT_EQ(
+ 0u,
+ QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size());
+}
+
+TEST_P(QuicSessionTestClient, TestMaxIncomingAndOutgoingStreamsAllowed) {
+ // Tests that on client side, the value of max_open_incoming/outgoing streams
+ // are setup correctly during negotiation.
+ // When flag is true, the value for outgoing stream is limited to negotiated
+ // value and for incoming stream it is set to be larger than that.
+ session_.OnConfigNegotiated();
+ EXPECT_LT(session_.max_open_outgoing_streams(),
+ session_.max_open_incoming_streams());
+ EXPECT_EQ(session_.max_open_outgoing_streams(),
+ kDefaultMaxStreamsPerConnection);
}
} // namespace
diff --git a/chromium/net/quic/quic_simple_buffer_allocator.cc b/chromium/net/quic/quic_simple_buffer_allocator.cc
index 5dae280d7e3..efee2ccc98b 100644
--- a/chromium/net/quic/quic_simple_buffer_allocator.cc
+++ b/chromium/net/quic/quic_simple_buffer_allocator.cc
@@ -10,6 +10,10 @@ char* SimpleBufferAllocator::New(size_t size) {
return new char[size];
}
+char* SimpleBufferAllocator::New(size_t size, bool /* flag_enable */) {
+ return New(size);
+}
+
void SimpleBufferAllocator::Delete(char* buffer) {
delete[] buffer;
}
diff --git a/chromium/net/quic/quic_simple_buffer_allocator.h b/chromium/net/quic/quic_simple_buffer_allocator.h
index 171f6b0d099..dfb0fffa2e8 100644
--- a/chromium/net/quic/quic_simple_buffer_allocator.h
+++ b/chromium/net/quic/quic_simple_buffer_allocator.h
@@ -12,6 +12,7 @@ namespace net {
class NET_EXPORT_PRIVATE SimpleBufferAllocator : public QuicBufferAllocator {
public:
char* New(size_t size) override;
+ char* New(size_t size, bool flag_enable) override;
void Delete(char* buffer) override;
};
diff --git a/chromium/net/quic/quic_socket_address_coder.cc b/chromium/net/quic/quic_socket_address_coder.cc
index bd28353e864..c0f528d5a4e 100644
--- a/chromium/net/quic/quic_socket_address_coder.cc
+++ b/chromium/net/quic/quic_socket_address_coder.cc
@@ -4,6 +4,7 @@
#include "net/quic/quic_socket_address_coder.h"
+#include "net/base/ip_address.h"
#include "net/base/sys_addrinfo.h"
using std::string;
@@ -70,7 +71,7 @@ bool QuicSocketAddressCoder::Decode(const char* data, size_t length) {
if (length < ip_length) {
return false;
}
- IPAddressNumber ip(ip_length);
+ std::vector<uint8_t> ip(ip_length);
memcpy(&ip[0], data, ip_length);
data += ip_length;
length -= ip_length;
@@ -81,7 +82,7 @@ bool QuicSocketAddressCoder::Decode(const char* data, size_t length) {
}
memcpy(&port, data, length);
- address_ = IPEndPoint(ip, port);
+ address_ = IPEndPoint(IPAddress(ip), port);
return true;
}
diff --git a/chromium/net/quic/quic_socket_address_coder.h b/chromium/net/quic/quic_socket_address_coder.h
index 0b620ba9a0a..e6f8bf6a08b 100644
--- a/chromium/net/quic/quic_socket_address_coder.h
+++ b/chromium/net/quic/quic_socket_address_coder.h
@@ -16,6 +16,8 @@
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.
@@ -29,7 +31,7 @@ class NET_EXPORT_PRIVATE QuicSocketAddressCoder {
bool Decode(const char* data, size_t length);
- IPAddressNumber ip() const { return address_.address(); }
+ const IPAddress& ip() const { return address_.address(); }
uint16_t port() const { return address_.port(); }
diff --git a/chromium/net/quic/quic_socket_address_coder_test.cc b/chromium/net/quic/quic_socket_address_coder_test.cc
index 79624938df3..babc00090cf 100644
--- a/chromium/net/quic/quic_socket_address_coder_test.cc
+++ b/chromium/net/quic/quic_socket_address_coder_test.cc
@@ -13,8 +13,8 @@ namespace net {
namespace test {
TEST(QuicSocketAddressCoderTest, EncodeIPv4) {
- IPAddressNumber ip;
- ASSERT_TRUE(ParseIPLiteralToNumber("4.31.198.44", &ip));
+ IPAddress ip;
+ ASSERT_TRUE(ip.AssignFromIPLiteral("4.31.198.44"));
QuicSocketAddressCoder coder(IPEndPoint(ip, 0x1234));
string serialized = coder.Encode();
string expected("\x02\x00\x04\x1f\xc6\x2c\x34\x12", 8);
@@ -22,8 +22,8 @@ TEST(QuicSocketAddressCoderTest, EncodeIPv4) {
}
TEST(QuicSocketAddressCoderTest, EncodeIPv6) {
- IPAddressNumber ip;
- ASSERT_TRUE(ParseIPLiteralToNumber("2001:700:300:1800::f", &ip));
+ IPAddress ip;
+ ASSERT_TRUE(ip.AssignFromIPLiteral("2001:700:300:1800::f"));
QuicSocketAddressCoder coder(IPEndPoint(ip, 0x5678));
string serialized = coder.Encode();
string expected(
@@ -110,8 +110,8 @@ TEST(QuicSocketAddressCoderTest, EncodeAndDecode) {
};
for (size_t i = 0; i < arraysize(test_case); i++) {
- IPAddressNumber ip;
- ASSERT_TRUE(ParseIPLiteralToNumber(test_case[i].ip_literal, &ip));
+ IPAddress ip;
+ ASSERT_TRUE(ip.AssignFromIPLiteral(test_case[i].ip_literal));
QuicSocketAddressCoder encoder(IPEndPoint(ip, test_case[i].port));
string serialized = encoder.Encode();
diff --git a/chromium/net/quic/quic_spdy_session.cc b/chromium/net/quic/quic_spdy_session.cc
index fc420baf555..af923870049 100644
--- a/chromium/net/quic/quic_spdy_session.cc
+++ b/chromium/net/quic/quic_spdy_session.cc
@@ -7,6 +7,8 @@
#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_headers_stream.h"
+using std::string;
+
namespace net {
QuicSpdySession::QuicSpdySession(QuicConnection* connection,
@@ -96,15 +98,19 @@ QuicSpdyStream* QuicSpdySession::GetSpdyDataStream(
void QuicSpdySession::OnPromiseHeaders(QuicStreamId stream_id,
StringPiece headers_data) {
- QUIC_BUG << "OnPromiseHeaders should be overriden in client code.";
- connection()->CloseConnection(QUIC_INTERNAL_ERROR, false);
+ string error = "OnPromiseHeaders should be overriden in client code.";
+ QUIC_BUG << error;
+ connection()->CloseConnection(QUIC_INTERNAL_ERROR, error,
+ ConnectionCloseBehavior::SILENT_CLOSE);
}
void QuicSpdySession::OnPromiseHeadersComplete(QuicStreamId stream_id,
QuicStreamId promised_stream_id,
size_t frame_len) {
- QUIC_BUG << "OnPromiseHeadersComplete shoule be overriden in client code.";
- connection()->CloseConnection(QUIC_INTERNAL_ERROR, false);
+ string error = "OnPromiseHeadersComplete should be overriden in client code.";
+ QUIC_BUG << error;
+ connection()->CloseConnection(QUIC_INTERNAL_ERROR, error,
+ ConnectionCloseBehavior::SILENT_CLOSE);
}
} // namespace net
diff --git a/chromium/net/quic/quic_spdy_session.h b/chromium/net/quic/quic_spdy_session.h
index 246a6defb82..8db704918bf 100644
--- a/chromium/net/quic/quic_spdy_session.h
+++ b/chromium/net/quic/quic_spdy_session.h
@@ -89,6 +89,12 @@ class NET_EXPORT_PRIVATE QuicSpdySession : public QuicSession {
QuicSpdyStream* GetSpdyDataStream(const QuicStreamId stream_id);
+ // If an incoming stream can be created, return true.
+ virtual bool ShouldCreateIncomingDynamicStream(QuicStreamId id) = 0;
+
+ // If an outgoing stream can be created, return true.
+ virtual bool ShouldCreateOutgoingDynamicStream() = 0;
+
private:
friend class test::QuicSpdySessionPeer;
diff --git a/chromium/net/quic/quic_spdy_stream.cc b/chromium/net/quic/quic_spdy_stream.cc
index 394bea13f88..2e099ca5e76 100644
--- a/chromium/net/quic/quic_spdy_stream.cc
+++ b/chromium/net/quic/quic_spdy_stream.cc
@@ -6,13 +6,16 @@
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
+#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_spdy_session.h"
#include "net/quic/quic_utils.h"
#include "net/quic/quic_write_blocked_list.h"
+#include "net/quic/spdy_utils.h"
using base::StringPiece;
-using std::min;
using net::SpdyPriority;
+using std::min;
+using std::string;
namespace net {
@@ -75,14 +78,18 @@ size_t QuicSpdyStream::WriteHeaders(
return bytes_written;
}
+void QuicSpdyStream::WriteOrBufferBody(
+ const string& data,
+ bool fin,
+ QuicAckListenerInterface* ack_notifier_delegate) {
+ WriteOrBufferData(data, fin, ack_notifier_delegate);
+}
+
size_t QuicSpdyStream::WriteTrailers(
SpdyHeaderBlock trailer_block,
QuicAckListenerInterface* ack_notifier_delegate) {
- if (!FLAGS_quic_supports_trailers) {
- return 0;
- }
if (fin_sent()) {
- LOG(DFATAL) << "Trailers cannot be sent after a FIN.";
+ QUIC_BUG << "Trailers cannot be sent after a FIN.";
return 0;
}
@@ -133,8 +140,7 @@ bool QuicSpdyStream::IsDoneReading() const {
bool QuicSpdyStream::HasBytesToRead() const {
bool headers_to_read = !decompressed_headers_.empty();
bool body_to_read = sequencer()->HasBytesToRead();
- bool trailers_to_read =
- (FLAGS_quic_supports_trailers && !decompressed_trailers_.empty());
+ bool trailers_to_read = !decompressed_trailers_.empty();
return headers_to_read || body_to_read || trailers_to_read;
}
@@ -155,12 +161,8 @@ void QuicSpdyStream::SetPriority(SpdyPriority priority) {
priority_ = priority;
}
-SpdyPriority QuicSpdyStream::Priority() const {
- return priority();
-}
-
void QuicSpdyStream::OnStreamHeaders(StringPiece headers_data) {
- if (!FLAGS_quic_supports_trailers || !headers_decompressed_) {
+ if (!headers_decompressed_) {
headers_data.AppendToString(&decompressed_headers_);
} else {
DCHECK(!trailers_decompressed_);
@@ -174,7 +176,7 @@ void QuicSpdyStream::OnStreamHeadersPriority(SpdyPriority priority) {
}
void QuicSpdyStream::OnStreamHeadersComplete(bool fin, size_t frame_len) {
- if (!FLAGS_quic_supports_trailers || !headers_decompressed_) {
+ if (!headers_decompressed_) {
OnInitialHeadersComplete(fin, frame_len);
} else {
OnTrailingHeadersComplete(fin, frame_len);
@@ -200,8 +202,9 @@ void QuicSpdyStream::OnPromiseHeadersComplete(
size_t /* frame_len */) {
// To be overridden in QuicSpdyClientStream. Not supported on
// server side.
- session()->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
- "Promise headers received by server");
+ session()->connection()->CloseConnection(
+ QUIC_INVALID_HEADERS_STREAM_DATA, "Promise headers received by server",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
@@ -209,16 +212,36 @@ void QuicSpdyStream::OnTrailingHeadersComplete(bool fin, size_t /*frame_len*/) {
DCHECK(!trailers_decompressed_);
if (fin_received()) {
DLOG(ERROR) << "Received Trailers after FIN, on stream: " << id();
- session()->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
- "Trailers after fin");
+ 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();
- session()->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
- "Fin missing from trailers");
+ session()->connection()->CloseConnection(
+ QUIC_INVALID_HEADERS_STREAM_DATA, "Fin missing from trailers",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
+
+ size_t final_byte_offset = 0;
+ SpdyHeaderBlock trailers;
+ if (!SpdyUtils::ParseTrailers(decompressed_trailers().data(),
+ decompressed_trailers().length(),
+ &final_byte_offset, &received_trailers_)) {
+ DLOG(ERROR) << "Trailers are malformed: " << id();
+ session()->connection()->CloseConnection(
+ QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers are malformed",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
+
+ // The data on this stream ends at |final_byte_offset|.
+ DVLOG(1) << "Stream ends at byte offset: " << final_byte_offset
+ << " currently read: " << stream_bytes_read();
+
+ OnStreamFrame(QuicStreamFrame(id(), fin, final_byte_offset, StringPiece()));
trailers_decompressed_ = true;
}
@@ -251,14 +274,31 @@ bool QuicSpdyStream::FinishedReadingHeaders() const {
return headers_decompressed_ && decompressed_headers_.empty();
}
-bool QuicSpdyStream::FinishedReadingTrailers() const {
- if (!FLAGS_quic_supports_trailers) {
- return true;
+bool QuicSpdyStream::ParseHeaderStatusCode(SpdyHeaderBlock* header,
+ int* status_code) const {
+ StringPiece status = (*header)[":status"];
+ if (status.size() != 3) {
+ return false;
+ }
+ // First character must be an integer in range [1,5].
+ if (status[0] < '1' || status[0] > '5') {
+ return false;
}
+ // The remaining two characters must be integers.
+ if (!isdigit(status[1]) || !isdigit(status[2])) {
+ return false;
+ }
+ return StringToInt(status, status_code);
+}
+
+bool QuicSpdyStream::FinishedReadingTrailers() const {
// If no further trailing headers are expected, and the decompressed trailers
// (if any) have been consumed, then reading of trailers is finished.
bool no_more_trailers = fin_received() || trailers_decompressed_;
return no_more_trailers && decompressed_trailers_.empty();
}
+SpdyPriority QuicSpdyStream::priority() const {
+ return priority_;
+}
} // namespace net
diff --git a/chromium/net/quic/quic_spdy_stream.h b/chromium/net/quic/quic_spdy_stream.h
index d821f77c82e..2d864955f0f 100644
--- a/chromium/net/quic/quic_spdy_stream.h
+++ b/chromium/net/quic/quic_spdy_stream.h
@@ -69,10 +69,6 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public ReliableQuicStream {
// ReliableQuicStream implementation
void OnClose() override;
- // This is the same as priority() and is being deprecated
- // TODO(alyssar) remove after Priority refactor.
- SpdyPriority Priority() const override;
-
// Called by the session when decompressed headers data is received
// for this stream.
// May be called multiple times, with each call providing additional headers
@@ -109,10 +105,15 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public ReliableQuicStream {
bool fin,
QuicAckListenerInterface* ack_notifier_delegate);
+ // 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);
+
// 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);
+ size_t WriteTrailers(SpdyHeaderBlock trailer_block,
+ QuicAckListenerInterface* ack_notifier_delegate);
// Marks |bytes_consumed| of the headers data as consumed.
void MarkHeadersConsumed(size_t bytes_consumed);
@@ -127,6 +128,10 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public ReliableQuicStream {
virtual int GetReadableRegions(iovec* iov, size_t iov_len) const;
void MarkConsumed(size_t num_bytes);
+ // Returns true if header contains a valid 3-digit status and parse the status
+ // code to |status_code|.
+ bool ParseHeaderStatusCode(SpdyHeaderBlock* header, int* status_code) const;
+
// Returns true when all data has been read from the peer, including the fin.
bool IsDoneReading() const;
bool HasBytesToRead() const;
@@ -145,7 +150,12 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public ReliableQuicStream {
return decompressed_trailers_;
}
- SpdyPriority priority() const { return priority_; }
+ // Returns whatever trailers have been received for this stream.
+ const SpdyHeaderBlock& received_trailers() const {
+ return received_trailers_;
+ }
+
+ virtual SpdyPriority priority() const;
// Sets priority_ to priority. This should only be called before bytes are
// written to the server.
@@ -157,6 +167,7 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public ReliableQuicStream {
virtual void OnInitialHeadersComplete(bool fin, size_t frame_len);
virtual void OnTrailingHeadersComplete(bool fin, size_t frame_len);
QuicSpdySession* spdy_session() const { return spdy_session_; }
+ Visitor* visitor() { return visitor_; }
// Returns true if headers have been fully read and consumed.
bool FinishedReadingHeaders() const;
@@ -185,6 +196,8 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public ReliableQuicStream {
// Contains a copy of the decompressed trailers until they are consumed
// via ProcessData or Readv.
std::string decompressed_trailers_;
+ // The parsed trailers received from the peer.
+ SpdyHeaderBlock received_trailers_;
DISALLOW_COPY_AND_ASSIGN(QuicSpdyStream);
};
diff --git a/chromium/net/quic/quic_spdy_stream_test.cc b/chromium/net/quic/quic_spdy_stream_test.cc
index 95d31a8f4c4..a50c082470a 100644
--- a/chromium/net/quic/quic_spdy_stream_test.cc
+++ b/chromium/net/quic/quic_spdy_stream_test.cc
@@ -65,6 +65,7 @@ class TestStream : public QuicSpdyStream {
class QuicSpdyStreamTest : public ::testing::TestWithParam<QuicVersion> {
public:
QuicSpdyStreamTest() {
+ FLAGS_quic_always_log_bugs_for_tests = true;
headers_[":host"] = "www.google.com";
headers_[":path"] = "/index.hml";
headers_[":scheme"] = "https";
@@ -131,7 +132,7 @@ TEST_P(QuicSpdyStreamTest, ProcessHeaders) {
EXPECT_EQ("", stream_->data());
EXPECT_EQ(headers, stream_->decompressed_headers());
stream_->OnStreamHeadersComplete(false, headers.size());
- EXPECT_EQ(kV3HighestPriority, stream_->Priority());
+ EXPECT_EQ(kV3HighestPriority, stream_->priority());
EXPECT_EQ("", stream_->data());
EXPECT_EQ(headers, stream_->decompressed_headers());
EXPECT_FALSE(stream_->IsDoneReading());
@@ -146,13 +147,57 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersWithFin) {
EXPECT_EQ("", stream_->data());
EXPECT_EQ(headers, stream_->decompressed_headers());
stream_->OnStreamHeadersComplete(true, headers.size());
- EXPECT_EQ(kV3HighestPriority, stream_->Priority());
+ EXPECT_EQ(kV3HighestPriority, stream_->priority());
EXPECT_EQ("", stream_->data());
EXPECT_EQ(headers, stream_->decompressed_headers());
EXPECT_FALSE(stream_->IsDoneReading());
EXPECT_TRUE(stream_->HasFinalReceivedByteOffset());
}
+TEST_P(QuicSpdyStreamTest, ParseHeaderStatusCode) {
+ // A valid status code should be 3-digit integer. The first digit should be in
+ // the range of [1, 5]. All the others are invalid.
+ Initialize(kShouldProcessData);
+ int status_code = 0;
+
+ // Valid status code.
+ headers_.ReplaceOrAppendHeader(":status", "404");
+ EXPECT_TRUE(stream_->ParseHeaderStatusCode(&headers_, &status_code));
+ EXPECT_EQ(404, status_code);
+
+ // Invalid status codes.
+ headers_.ReplaceOrAppendHeader(":status", "010");
+ EXPECT_FALSE(stream_->ParseHeaderStatusCode(&headers_, &status_code));
+
+ headers_.ReplaceOrAppendHeader(":status", "600");
+ EXPECT_FALSE(stream_->ParseHeaderStatusCode(&headers_, &status_code));
+
+ headers_.ReplaceOrAppendHeader(":status", "200 ok");
+ EXPECT_FALSE(stream_->ParseHeaderStatusCode(&headers_, &status_code));
+
+ headers_.ReplaceOrAppendHeader(":status", "2000");
+ EXPECT_FALSE(stream_->ParseHeaderStatusCode(&headers_, &status_code));
+
+ headers_.ReplaceOrAppendHeader(":status", "+200");
+ EXPECT_FALSE(stream_->ParseHeaderStatusCode(&headers_, &status_code));
+
+ headers_.ReplaceOrAppendHeader(":status", "+20");
+ EXPECT_FALSE(stream_->ParseHeaderStatusCode(&headers_, &status_code));
+
+ // Leading or trailing spaces are also invalid.
+ headers_.ReplaceOrAppendHeader(":status", " 200");
+ EXPECT_FALSE(stream_->ParseHeaderStatusCode(&headers_, &status_code));
+
+ headers_.ReplaceOrAppendHeader(":status", "200 ");
+ EXPECT_FALSE(stream_->ParseHeaderStatusCode(&headers_, &status_code));
+
+ headers_.ReplaceOrAppendHeader(":status", " 200 ");
+ EXPECT_FALSE(stream_->ParseHeaderStatusCode(&headers_, &status_code));
+
+ headers_.ReplaceOrAppendHeader(":status", " ");
+ EXPECT_FALSE(stream_->ParseHeaderStatusCode(&headers_, &status_code));
+}
+
TEST_P(QuicSpdyStreamTest, MarkHeadersConsumed) {
Initialize(kShouldProcessData);
@@ -362,7 +407,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) {
GenerateBody(&body, kWindow + kOverflow);
EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1));
- EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _))
.WillOnce(Return(QuicConsumedData(kWindow, true)));
stream_->WriteOrBufferData(body, false, nullptr);
@@ -536,8 +581,8 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlViolation) {
string body;
GenerateBody(&body, kWindow + 1);
QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _));
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
stream_->OnStreamFrame(frame);
}
@@ -587,8 +632,8 @@ TEST_P(QuicSpdyStreamTest, ConnectionFlowControlViolation) {
EXPECT_LT(body.size(), kStreamWindow);
QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _));
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
stream_->OnStreamFrame(frame);
}
@@ -608,7 +653,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlFinNotBlocked) {
bool fin = true;
EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)).Times(0);
- EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _))
.WillOnce(Return(QuicConsumedData(0, fin)));
stream_->WriteOrBufferData(body, fin, nullptr);
@@ -617,7 +662,6 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlFinNotBlocked) {
TEST_P(QuicSpdyStreamTest, ReceivingTrailers) {
// Test that receiving trailing headers from the peer works, and can be read
// from the stream and consumed.
- ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true);
Initialize(kShouldProcessData);
// Receive initial headers.
@@ -631,6 +675,7 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailers) {
trailers_block["key1"] = "value1";
trailers_block["key2"] = "value2";
trailers_block["key3"] = "value3";
+ trailers_block[kFinalOffsetHeaderKey] = "0";
string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block);
stream_->OnStreamHeaders(trailers);
stream_->OnStreamHeadersComplete(/*fin=*/true, trailers.size());
@@ -645,9 +690,37 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailers) {
EXPECT_EQ("", stream_->decompressed_trailers());
}
+TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutOffset) {
+ // Test that receiving trailers without a final offset field is an error.
+ Initialize(kShouldProcessData);
+
+ // Receive initial headers.
+ string headers = SpdyUtils::SerializeUncompressedHeaders(headers_);
+ stream_->OnStreamHeaders(headers);
+ stream_->OnStreamHeadersComplete(false, headers.size());
+ stream_->MarkHeadersConsumed(stream_->decompressed_headers().size());
+
+ const string body = "this is the body";
+ // Receive trailing headers, without kFinalOffsetHeaderKey.
+ SpdyHeaderBlock trailers_block;
+ trailers_block["key1"] = "value1";
+ trailers_block["key2"] = "value2";
+ trailers_block["key3"] = "value3";
+ string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block);
+ stream_->OnStreamHeaders(trailers);
+
+ // Verify that the trailers block didn't contain a final offset.
+ EXPECT_EQ("", trailers_block[kFinalOffsetHeaderKey].as_string());
+
+ // Receipt of the malformed trailers will close the connection.
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
+ .Times(1);
+ stream_->OnStreamHeadersComplete(/*fin=*/true, trailers.size());
+}
+
TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutFin) {
// Test that received Trailers must always have the FIN set.
- ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true);
Initialize(kShouldProcessData);
// Receive initial headers.
@@ -660,15 +733,14 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutFin) {
string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block);
stream_->OnStreamHeaders(trailers);
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_INVALID_HEADERS_STREAM_DATA, _))
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
.Times(1);
stream_->OnStreamHeadersComplete(/*fin=*/false, trailers.size());
}
TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterFin) {
// If Trailers are sent, neither Headers nor Body should contain a FIN.
- ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true);
Initialize(kShouldProcessData);
// Receive initial headers with FIN set.
@@ -681,15 +753,14 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterFin) {
string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block);
stream_->OnStreamHeaders(trailers);
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_INVALID_HEADERS_STREAM_DATA, _))
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
.Times(1);
stream_->OnStreamHeadersComplete(/*fin=*/true, trailers.size());
}
TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterBodyWithFin) {
// If body data are received with a FIN, no trailers should then arrive.
- ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true);
Initialize(kShouldProcessData);
// Receive initial headers without FIN set.
@@ -706,16 +777,53 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterBodyWithFin) {
string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block);
stream_->OnStreamHeaders(trailers);
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_INVALID_HEADERS_STREAM_DATA, _))
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
.Times(1);
stream_->OnStreamHeadersComplete(/*fin=*/true, trailers.size());
}
+TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithOffset) {
+ // Test that when receiving trailing headers with an offset before response
+ // body, stream is closed at the right offset.
+ Initialize(kShouldProcessData);
+
+ // Receive initial headers.
+ string headers = SpdyUtils::SerializeUncompressedHeaders(headers_);
+ stream_->OnStreamHeaders(headers);
+ stream_->OnStreamHeadersComplete(false, headers.size());
+ stream_->MarkHeadersConsumed(stream_->decompressed_headers().size());
+
+ const string body = "this is the body";
+ // Receive trailing headers.
+ SpdyHeaderBlock trailers_block;
+ trailers_block["key1"] = "value1";
+ trailers_block["key2"] = "value2";
+ trailers_block["key3"] = "value3";
+ trailers_block[kFinalOffsetHeaderKey] = base::IntToString(body.size());
+ string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block);
+ stream_->OnStreamHeaders(trailers);
+ stream_->OnStreamHeadersComplete(/*fin=*/true, trailers.size());
+
+ // The trailers should be decompressed, and readable from the stream.
+ EXPECT_TRUE(stream_->trailers_decompressed());
+ const string decompressed_trailers = stream_->decompressed_trailers();
+ EXPECT_EQ(trailers, decompressed_trailers);
+ // Consuming the trailers erases them from the stream.
+ stream_->MarkTrailersConsumed(decompressed_trailers.size());
+ EXPECT_EQ("", stream_->decompressed_trailers());
+
+ EXPECT_FALSE(stream_->IsDoneReading());
+ // Receive and consume body.
+ QuicStreamFrame frame(kClientDataStreamId1, /*fin=*/false, 0, body);
+ stream_->OnStreamFrame(frame);
+ EXPECT_EQ(body, stream_->data());
+ EXPECT_TRUE(stream_->IsDoneReading());
+}
+
TEST_P(QuicSpdyStreamTest, ClosingStreamWithNoTrailers) {
// Verify that a stream receiving headers, body, and no trailers is correctly
// marked as done reading on consumption of headers and body.
- ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true);
Initialize(kShouldProcessData);
// Receive and consume initial headers with FIN not set.
@@ -735,9 +843,8 @@ TEST_P(QuicSpdyStreamTest, ClosingStreamWithNoTrailers) {
TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) {
// Test that writing trailers will send a FIN, as Trailers are the last thing
// to be sent on a stream.
- ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true);
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData));
@@ -757,9 +864,8 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) {
TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
// Test that when writing trailers, the trailers that are actually sent to the
// peer contain the final offset field indicating last byte of data.
- ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true);
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData));
@@ -785,9 +891,8 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) {
// Test that if trailers are written after all other data has been written
// (headers and body), that this closes the stream for writing.
- ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true);
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData));
@@ -811,9 +916,8 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) {
TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) {
// Test that the stream is not closed for writing when trailers are sent
// while there are still body bytes queued.
- ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true);
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData));
@@ -823,7 +927,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) {
// Write non-zero body data, but only consume partially, ensuring queueing.
const int kBodySize = 1 * 1024; // 1 MB
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillOnce(Return(QuicConsumedData(kBodySize - 1, false)));
stream_->WriteOrBufferData(string(kBodySize, 'x'), false, nullptr);
EXPECT_EQ(1u, stream_->queued_data_bytes());
@@ -839,9 +943,8 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) {
TEST_P(QuicSpdyStreamTest, WritingTrailersAfterFIN) {
// Test that it is not possible to write Trailers after a FIN has been sent.
- ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true);
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData));
diff --git a/chromium/net/quic/quic_stream_factory.cc b/chromium/net/quic/quic_stream_factory.cc
index 858f1cb93f0..65d7f276eec 100644
--- a/chromium/net/quic/quic_stream_factory.cc
+++ b/chromium/net/quic/quic_stream_factory.cc
@@ -19,7 +19,9 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/base/socket_performance_watcher.h"
#include "net/base/socket_performance_watcher_factory.h"
@@ -27,6 +29,8 @@
#include "net/cert/ct_verifier.h"
#include "net/dns/host_resolver.h"
#include "net/dns/single_request_host_resolver.h"
+#include "net/http/bidirectional_stream_impl.h"
+#include "net/quic/bidirectional_stream_quic_impl.h"
#include "net/quic/crypto/channel_id_chromium.h"
#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/quic/crypto/properties_based_quic_server_info.h"
@@ -35,16 +39,18 @@
#include "net/quic/port_suggester.h"
#include "net/quic/quic_chromium_client_session.h"
#include "net/quic/quic_chromium_connection_helper.h"
+#include "net/quic/quic_chromium_packet_reader.h"
+#include "net/quic/quic_chromium_packet_writer.h"
+#include "net/quic/quic_client_promised_info.h"
#include "net/quic/quic_clock.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_crypto_client_stream_factory.h"
-#include "net/quic/quic_default_packet_writer.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_http_stream.h"
-#include "net/quic/quic_packet_reader.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_server_id.h"
#include "net/socket/client_socket_factory.h"
+#include "net/ssl/token_binding.h"
#include "net/udp/udp_client_socket.h"
#if defined(OS_WIN)
@@ -59,6 +65,8 @@
#endif
using std::min;
+using std::vector;
+using NetworkHandle = net::NetworkChangeNotifier::NetworkHandle;
namespace net {
@@ -77,6 +85,8 @@ enum QuicConnectionMigrationStatus {
MIGRATION_STATUS_INTERNAL_ERROR,
MIGRATION_STATUS_TOO_MANY_CHANGES,
MIGRATION_STATUS_SUCCESS,
+ MIGRATION_STATUS_NON_MIGRATABLE_STREAM,
+ MIGRATION_STATUS_DISABLED,
MIGRATION_STATUS_MAX
};
@@ -125,10 +135,9 @@ class QuicStreamFactory::Job {
public:
Job(QuicStreamFactory* factory,
HostResolver* host_resolver,
- const HostPortPair& host_port_pair,
+ const QuicServerId& server_id,
bool server_and_origin_have_same_host,
bool was_alternative_service_recently_broken,
- PrivacyMode privacy_mode,
int cert_verify_flags,
bool is_post,
QuicServerInfo* server_info,
@@ -190,6 +199,7 @@ class QuicStreamFactory::Job {
scoped_ptr<QuicServerInfo> server_info_;
bool started_another_job_;
const BoundNetLog net_log_;
+ int num_sent_client_hellos_;
QuicChromiumClientSession* session_;
CompletionCallback callback_;
AddressList address_list_;
@@ -201,10 +211,9 @@ class QuicStreamFactory::Job {
QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
HostResolver* host_resolver,
- const HostPortPair& host_port_pair,
+ const QuicServerId& server_id,
bool server_and_origin_have_same_host,
bool was_alternative_service_recently_broken,
- PrivacyMode privacy_mode,
int cert_verify_flags,
bool is_post,
QuicServerInfo* server_info,
@@ -212,7 +221,7 @@ QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
: io_state_(STATE_RESOLVE_HOST),
factory_(factory),
host_resolver_(host_resolver),
- server_id_(host_port_pair, privacy_mode),
+ server_id_(server_id),
cert_verify_flags_(cert_verify_flags),
server_and_origin_have_same_host_(server_and_origin_have_same_host),
is_post_(is_post),
@@ -221,6 +230,7 @@ QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
server_info_(server_info),
started_another_job_(false),
net_log_(net_log),
+ num_sent_client_hellos_(0),
session_(nullptr),
weak_factory_(this) {}
@@ -238,6 +248,7 @@ QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
was_alternative_service_recently_broken_(false), // unused
started_another_job_(false), // unused
net_log_(session->net_log()), // unused
+ num_sent_client_hellos_(0),
session_(session),
weak_factory_(this) {}
@@ -256,6 +267,7 @@ int QuicStreamFactory::Job::Run(const CompletionCallback& callback) {
}
int QuicStreamFactory::Job::DoLoop(int rv) {
+ TRACE_EVENT0("net", "QuicStreamFactory::Job::DoLoop");
do {
IoState state = io_state_;
io_state_ = STATE_NONE;
@@ -310,8 +322,9 @@ void QuicStreamFactory::Job::RunAuxilaryJob() {
void QuicStreamFactory::Job::Cancel() {
callback_.Reset();
if (session_)
- session_->connection()->SendConnectionCloseWithDetails(
- QUIC_CONNECTION_CANCELLED, "New job canceled.");
+ session_->connection()->CloseConnection(
+ QUIC_CONNECTION_CANCELLED, "New job canceled.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
void QuicStreamFactory::Job::CancelWaitForDataReadyCallback() {
@@ -459,6 +472,17 @@ int QuicStreamFactory::Job::DoResumeConnect() {
}
int QuicStreamFactory::Job::DoConnectComplete(int rv) {
+ if (session_ && session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
+ num_sent_client_hellos_ += session_->GetNumSentClientHellos();
+ if (num_sent_client_hellos_ >= QuicCryptoClientStream::kMaxClientHellos) {
+ return ERR_QUIC_HANDSHAKE_FAILED;
+ }
+ // The handshake was rejected statelessly, so create another connection
+ // to resume the handshake.
+ io_state_ = STATE_CONNECT;
+ return OK;
+ }
+
if (rv != OK)
return rv;
@@ -467,9 +491,9 @@ int QuicStreamFactory::Job::DoConnectComplete(int rv) {
// existing session instead.
AddressList address(session_->connection()->peer_address());
if (factory_->OnResolution(server_id_, address)) {
- session_->connection()->SendConnectionCloseWithDetails(
- QUIC_CONNECTION_IP_POOLED,
- "An active session exists for the given IP.");
+ session_->connection()->CloseConnection(
+ QUIC_CONNECTION_IP_POOLED, "An active session exists for the given IP.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
session_ = nullptr;
return OK;
}
@@ -490,17 +514,17 @@ QuicStreamRequest::~QuicStreamRequest() {
int QuicStreamRequest::Request(const HostPortPair& host_port_pair,
PrivacyMode privacy_mode,
int cert_verify_flags,
- base::StringPiece origin_host,
+ const GURL& url,
base::StringPiece method,
const BoundNetLog& net_log,
const CompletionCallback& callback) {
- DCHECK(!stream_);
DCHECK(callback_.is_null());
DCHECK(factory_);
- origin_host_ = origin_host.as_string();
+ origin_host_ = url.host();
privacy_mode_ = privacy_mode;
+
int rv = factory_->Create(host_port_pair, privacy_mode, cert_verify_flags,
- origin_host, method, net_log, this);
+ url, method, net_log, this);
if (rv == ERR_IO_PENDING) {
host_port_pair_ = host_port_pair;
net_log_ = net_log;
@@ -509,13 +533,13 @@ int QuicStreamRequest::Request(const HostPortPair& host_port_pair,
factory_ = nullptr;
}
if (rv == OK)
- DCHECK(stream_);
+ DCHECK(session_);
return rv;
}
-void QuicStreamRequest::set_stream(scoped_ptr<QuicHttpStream> stream) {
- DCHECK(stream);
- stream_ = std::move(stream);
+void QuicStreamRequest::SetSession(QuicChromiumClientSession* session) {
+ DCHECK(session);
+ session_ = session->GetWeakPtr();
}
void QuicStreamRequest::OnRequestComplete(int rv) {
@@ -530,9 +554,17 @@ base::TimeDelta QuicStreamRequest::GetTimeDelayForWaitingJob() const {
QuicServerId(host_port_pair_, privacy_mode_));
}
-scoped_ptr<QuicHttpStream> QuicStreamRequest::ReleaseStream() {
- DCHECK(stream_);
- return std::move(stream_);
+scoped_ptr<QuicHttpStream> QuicStreamRequest::CreateStream() {
+ if (!session_)
+ return nullptr;
+ return make_scoped_ptr(new QuicHttpStream(session_));
+}
+
+scoped_ptr<BidirectionalStreamImpl>
+QuicStreamRequest::CreateBidirectionalStreamImpl() {
+ if (!session_)
+ return nullptr;
+ return make_scoped_ptr(new BidirectionalStreamQuicImpl(session_));
}
QuicStreamFactory::QuicStreamFactory(
@@ -568,9 +600,12 @@ QuicStreamFactory::QuicStreamFactory(
bool delay_tcp_race,
int max_server_configs_stored_in_properties,
bool close_sessions_on_ip_change,
+ bool disable_quic_on_timeout_with_open_streams,
int idle_connection_timeout_seconds,
bool migrate_sessions_on_network_change,
- const QuicTagVector& connection_options)
+ bool migrate_sessions_early,
+ const QuicTagVector& connection_options,
+ bool enable_token_binding)
: require_confirmation_(true),
host_resolver_(host_resolver),
client_socket_factory_(client_socket_factory),
@@ -619,11 +654,17 @@ QuicStreamFactory::QuicStreamFactory(
migrate_sessions_on_network_change_(
migrate_sessions_on_network_change &&
NetworkChangeNotifier::AreNetworkHandlesSupported()),
+ migrate_sessions_early_(migrate_sessions_early &&
+ migrate_sessions_on_network_change_),
port_seed_(random_generator_->RandUint64()),
check_persisted_supports_quic_(true),
has_initialized_data_(false),
+ num_push_streams_created_(0),
+ status_(OPEN),
task_runner_(nullptr),
weak_factory_(this) {
+ if (disable_quic_on_timeout_with_open_streams)
+ threshold_timeouts_with_open_streams_ = 1;
DCHECK(transport_security_state_);
DCHECK(http_server_properties_);
crypto_config_.set_user_agent_id(user_agent_id);
@@ -636,6 +677,8 @@ QuicStreamFactory::QuicStreamFactory(
crypto_config_.SetChannelIDSource(
new ChannelIDSourceChromium(channel_id_service));
}
+ if (enable_token_binding && channel_id_service && IsTokenBindingSupported())
+ crypto_config_.tb_key_params.push_back(kP256);
#if defined(USE_OPENSSL)
crypto::EnsureOpenSSLInit();
bool has_aes_hardware_support = !!EVP_has_aes_hardware();
@@ -657,8 +700,14 @@ QuicStreamFactory::QuicStreamFactory(
new PropertiesBasedQuicServerInfoFactory(http_server_properties_));
}
- DCHECK(
- !(close_sessions_on_ip_change_ && migrate_sessions_on_network_change_));
+ // migrate_sessions_early should only be set to true if
+ // migrate_sessions_on_network_change is set to true.
+ if (migrate_sessions_early)
+ DCHECK(migrate_sessions_on_network_change);
+ // close_sessions_on_ip_change and migrate_sessions_on_network_change should
+ // never be simultaneously set to true.
+ DCHECK(!(close_sessions_on_ip_change && migrate_sessions_on_network_change));
+
if (migrate_sessions_on_network_change_) {
NetworkChangeNotifier::AddNetworkObserver(this);
} else if (close_sessions_on_ip_change_) {
@@ -667,7 +716,7 @@ QuicStreamFactory::QuicStreamFactory(
}
QuicStreamFactory::~QuicStreamFactory() {
- CloseAllSessions(ERR_ABORTED, QUIC_INTERNAL_ERROR);
+ CloseAllSessions(ERR_ABORTED, QUIC_CONNECTION_CANCELLED);
while (!all_sessions_.empty()) {
delete all_sessions_.begin()->first;
all_sessions_.erase(all_sessions_.begin());
@@ -732,19 +781,37 @@ bool QuicStreamFactory::CanUseExistingSession(QuicServerId server_id,
int QuicStreamFactory::Create(const HostPortPair& host_port_pair,
PrivacyMode privacy_mode,
int cert_verify_flags,
- base::StringPiece origin_host,
+ const GURL& url,
base::StringPiece method,
const BoundNetLog& net_log,
QuicStreamRequest* request) {
+ // Enforce session affinity for promised streams.
+ QuicClientPromisedInfo* promised =
+ push_promise_index_.GetPromised(url.spec());
+ if (promised) {
+ QuicChromiumClientSession* session =
+ static_cast<QuicChromiumClientSession*>(promised->session());
+ DCHECK(session);
+ if (session->server_id().privacy_mode() == privacy_mode) {
+ request->SetSession(session);
+ ++num_push_streams_created_;
+ return OK;
+ }
+ // This should happen extremely rarely (if ever), but if somehow a
+ // request comes in with a mismatched privacy mode, consider the
+ // promise borked.
+ promised->Cancel();
+ }
+
QuicServerId server_id(host_port_pair, privacy_mode);
// TODO(rtenneti): crbug.com/498823 - delete active_sessions_.empty() checks.
if (!active_sessions_.empty()) {
SessionMap::iterator it = active_sessions_.find(server_id);
if (it != active_sessions_.end()) {
QuicChromiumClientSession* session = it->second;
- if (!session->CanPool(origin_host.as_string(), privacy_mode))
+ if (!session->CanPool(url.host(), privacy_mode))
return ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN;
- request->set_stream(CreateFromSession(session));
+ request->SetSession(session);
return OK;
}
}
@@ -764,8 +831,7 @@ int QuicStreamFactory::Create(const HostPortPair& host_port_pair,
if (quic_server_info_factory_.get()) {
bool load_from_disk_cache = !disable_disk_cache_;
MaybeInitialize();
- if (!ContainsKey(quic_supported_servers_at_startup_,
- server_id.host_port_pair())) {
+ if (!ContainsKey(quic_supported_servers_at_startup_, host_port_pair)) {
// If there is no entry for QUIC, consider that as a new server and
// don't wait for Cache thread to load the data for that server.
load_from_disk_cache = false;
@@ -775,11 +841,11 @@ int QuicStreamFactory::Create(const HostPortPair& host_port_pair,
}
}
- bool server_and_origin_have_same_host = host_port_pair.host() == origin_host;
- scoped_ptr<Job> job(new Job(
- this, host_resolver_, host_port_pair, server_and_origin_have_same_host,
- WasQuicRecentlyBroken(server_id), privacy_mode, cert_verify_flags,
- method == "POST" /* is_post */, quic_server_info, net_log));
+ bool server_and_origin_have_same_host = host_port_pair.host() == url.host();
+ scoped_ptr<Job> job(
+ new Job(this, host_resolver_, server_id, server_and_origin_have_same_host,
+ WasQuicRecentlyBroken(server_id), cert_verify_flags,
+ method == "POST" /* is_post */, quic_server_info, net_log));
int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
base::Unretained(this), job.get()));
if (rv == ERR_IO_PENDING) {
@@ -798,9 +864,9 @@ int QuicStreamFactory::Create(const HostPortPair& host_port_pair,
if (it == active_sessions_.end())
return ERR_QUIC_PROTOCOL_ERROR;
QuicChromiumClientSession* session = it->second;
- if (!session->CanPool(origin_host.as_string(), privacy_mode))
+ if (!session->CanPool(url.host(), privacy_mode))
return ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN;
- request->set_stream(CreateFromSession(session));
+ request->SetSession(session);
}
return rv;
}
@@ -810,10 +876,10 @@ void QuicStreamFactory::CreateAuxilaryJob(const QuicServerId server_id,
bool server_and_origin_have_same_host,
bool is_post,
const BoundNetLog& net_log) {
- Job* aux_job = new Job(
- this, host_resolver_, server_id.host_port_pair(),
- server_and_origin_have_same_host, WasQuicRecentlyBroken(server_id),
- server_id.privacy_mode(), cert_verify_flags, is_post, nullptr, net_log);
+ Job* aux_job =
+ new Job(this, host_resolver_, server_id, server_and_origin_have_same_host,
+ WasQuicRecentlyBroken(server_id), cert_verify_flags, is_post,
+ nullptr, net_log);
active_jobs_[server_id].insert(aux_job);
task_runner_->PostTask(FROM_HERE,
base::Bind(&QuicStreamFactory::Job::RunAuxilaryJob,
@@ -878,7 +944,7 @@ void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
request->OnRequestComplete(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN);
continue;
}
- request->set_stream(CreateFromSession(session));
+ request->SetSession(session);
++request_it;
}
}
@@ -946,9 +1012,8 @@ const char* QuicStreamFactory::QuicDisabledReasonString() const {
}
}
-bool QuicStreamFactory::IsQuicDisabled(uint16_t port) {
- return QuicDisabledReason(port) !=
- QuicChromiumClientSession::QUIC_DISABLED_NOT;
+bool QuicStreamFactory::IsQuicDisabled(uint16_t port) const {
+ return status_ != OPEN;
}
bool QuicStreamFactory::OnHandshakeConfirmed(QuicChromiumClientSession* session,
@@ -977,6 +1042,8 @@ bool QuicStreamFactory::OnHandshakeConfirmed(QuicChromiumClientSession* session,
max_number_of_lossy_connections_));
}
+ MaybeDisableQuic(port);
+
bool is_quic_disabled = IsQuicDisabled(port);
if (is_quic_disabled) {
// Close QUIC connection if Quic is disabled for this port.
@@ -990,6 +1057,22 @@ bool QuicStreamFactory::OnHandshakeConfirmed(QuicChromiumClientSession* session,
return is_quic_disabled;
}
+void QuicStreamFactory::OnTcpJobCompleted(bool succeeded) {
+ if (status_ != CLOSED)
+ return;
+
+ // If QUIC connections are failing while TCP connections are working,
+ // then stop using QUIC. On the other hand if both QUIC and TCP are
+ // failing, then attempt to use QUIC again.
+ if (succeeded) {
+ status_ = DISABLED;
+ return;
+ }
+
+ status_ = OPEN;
+ num_timeouts_with_open_streams_ = 0;
+}
+
void QuicStreamFactory::OnIdleSession(QuicChromiumClientSession* session) {}
void QuicStreamFactory::OnSessionGoingAway(QuicChromiumClientSession* session) {
@@ -1060,6 +1143,7 @@ void QuicStreamFactory::MaybeDisableQuic(QuicChromiumClientSession* session) {
num_public_resets_post_handshake_, 0, 20, 10);
}
+ MaybeDisableQuic(port);
if (IsQuicDisabled(port)) {
if (disabled_reason ==
QuicChromiumClientSession::QUIC_DISABLED_PUBLIC_RESET_POST_HANDSHAKE) {
@@ -1076,6 +1160,35 @@ void QuicStreamFactory::MaybeDisableQuic(QuicChromiumClientSession* session) {
}
}
+void QuicStreamFactory::MaybeDisableQuic(uint16_t port) {
+ if (status_ == DISABLED)
+ return;
+
+ QuicChromiumClientSession::QuicDisabledReason disabled_reason =
+ QuicDisabledReason(port);
+ if (disabled_reason == QuicChromiumClientSession::QUIC_DISABLED_NOT) {
+ DCHECK_EQ(OPEN, status_);
+ return;
+ }
+
+ if (disabled_reason ==
+ QuicChromiumClientSession::QUIC_DISABLED_TIMEOUT_WITH_OPEN_STREAMS) {
+ // When QUIC there are too many timeouts with open stream, the factory
+ // should be closed. When TCP jobs complete, they will move the factory
+ // to either fully disabled or back to open.
+ status_ = CLOSED;
+ DCHECK(IsQuicDisabled(port));
+ DCHECK_NE(QuicChromiumClientSession::QuicDisabledReason(port),
+ QuicChromiumClientSession::QUIC_DISABLED_NOT);
+ return;
+ }
+
+ status_ = DISABLED;
+ DCHECK(IsQuicDisabled(port));
+ DCHECK_NE(QuicChromiumClientSession::QuicDisabledReason(port),
+ QuicChromiumClientSession::QUIC_DISABLED_NOT);
+}
+
void QuicStreamFactory::OnSessionClosed(QuicChromiumClientSession* session) {
DCHECK_EQ(0u, session->GetNumActiveStreams());
MaybeDisableQuic(session);
@@ -1120,6 +1233,7 @@ void QuicStreamFactory::CancelRequest(QuicStreamRequest* request) {
}
void QuicStreamFactory::CloseAllSessions(int error, QuicErrorCode quic_error) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.CloseAllSessionsError", -error);
while (!active_sessions_.empty()) {
size_t initial_size = active_sessions_.size();
active_sessions_.begin()->second->CloseSessionOnError(error, quic_error);
@@ -1160,45 +1274,47 @@ void QuicStreamFactory::ClearCachedStatesInCryptoConfig() {
}
void QuicStreamFactory::OnIPAddressChanged() {
+ num_timeouts_with_open_streams_ = 0;
+ status_ = OPEN;
CloseAllSessions(ERR_NETWORK_CHANGED, QUIC_IP_ADDRESS_CHANGED);
set_require_confirmation(true);
}
-void QuicStreamFactory::OnNetworkConnected(
- NetworkChangeNotifier::NetworkHandle network) {}
+void QuicStreamFactory::OnNetworkConnected(NetworkHandle network) {
+ num_timeouts_with_open_streams_ = 0;
+ status_ = OPEN;
+}
-void QuicStreamFactory::OnNetworkMadeDefault(
- NetworkChangeNotifier::NetworkHandle network) {}
+void QuicStreamFactory::OnNetworkMadeDefault(NetworkHandle network) {}
-void QuicStreamFactory::OnNetworkDisconnected(
- NetworkChangeNotifier::NetworkHandle network) {
+void QuicStreamFactory::OnNetworkDisconnected(NetworkHandle network) {
MaybeMigrateOrCloseSessions(network, /*force_close=*/true);
set_require_confirmation(true);
}
// This method is expected to only be called when migrating from Cellular to
// WiFi on Android.
-void QuicStreamFactory::OnNetworkSoonToDisconnect(
- NetworkChangeNotifier::NetworkHandle network) {
+void QuicStreamFactory::OnNetworkSoonToDisconnect(NetworkHandle network) {
MaybeMigrateOrCloseSessions(network, /*force_close=*/false);
}
-void QuicStreamFactory::MaybeMigrateOrCloseSessions(
- NetworkChangeNotifier::NetworkHandle network,
- bool force_close) {
- DCHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, network);
-
- // Find a new network that sessions bound to |network| can be migrated to.
+NetworkHandle QuicStreamFactory::FindAlternateNetwork(
+ NetworkHandle old_network) {
+ // Find a new network that sessions bound to |old_network| can be migrated to.
NetworkChangeNotifier::NetworkList network_list;
NetworkChangeNotifier::GetConnectedNetworks(&network_list);
- NetworkChangeNotifier::NetworkHandle new_network =
- NetworkChangeNotifier::kInvalidNetworkHandle;
- for (NetworkChangeNotifier::NetworkHandle n : network_list) {
- if (n != network) {
- new_network = n;
- break;
+ for (NetworkHandle new_network : network_list) {
+ if (new_network != old_network) {
+ return new_network;
}
}
+ return NetworkChangeNotifier::kInvalidNetworkHandle;
+}
+
+void QuicStreamFactory::MaybeMigrateOrCloseSessions(NetworkHandle network,
+ bool force_close) {
+ DCHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, network);
+ NetworkHandle new_network = FindAlternateNetwork(network);
QuicStreamFactory::SessionIdMap::iterator it = all_sessions_.begin();
while (it != all_sessions_.end()) {
@@ -1220,6 +1336,7 @@ void QuicStreamFactory::MaybeMigrateOrCloseSessions(
}
// If session has active streams, mark it as going away.
OnSessionGoingAway(session);
+
if (new_network == NetworkChangeNotifier::kInvalidNetworkHandle) {
// No new network was found.
if (force_close) {
@@ -1228,46 +1345,88 @@ void QuicStreamFactory::MaybeMigrateOrCloseSessions(
}
continue;
}
-
- // Use OS-specified port for socket (DEFAULT_BIND) instead of
- // using the PortSuggester since the connection is being migrated
- // and not being newly created.
- scoped_ptr<DatagramClientSocket> socket(
- client_socket_factory_->CreateDatagramClientSocket(
- DatagramSocket::DEFAULT_BIND, RandIntCallback(),
- session->net_log().net_log(), session->net_log().source()));
-
- QuicConnection* connection = session->connection();
- if (ConfigureSocket(socket.get(), connection->peer_address(),
- new_network) != OK) {
- session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR);
- HistogramMigrationStatus(MIGRATION_STATUS_INTERNAL_ERROR);
+ if (session->config()->DisableConnectionMigration()) {
+ // Do not migrate sessions where connection migration is disabled by
+ // config.
+ if (force_close) {
+ // Close sessions where connection migration is disabled.
+ session->CloseSessionOnError(ERR_NETWORK_CHANGED,
+ QUIC_IP_ADDRESS_CHANGED);
+ HistogramMigrationStatus(MIGRATION_STATUS_DISABLED);
+ }
continue;
}
-
- scoped_ptr<QuicPacketReader> new_reader(new QuicPacketReader(
- socket.get(), clock_.get(), session, yield_after_packets_,
- yield_after_duration_, session->net_log()));
- scoped_ptr<QuicPacketWriter> new_writer(
- new QuicDefaultPacketWriter(socket.get()));
-
- if (!session->MigrateToSocket(std::move(socket), std::move(new_reader),
- std::move(new_writer))) {
- session->CloseSessionOnError(ERR_NETWORK_CHANGED,
- QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES);
- HistogramMigrationStatus(MIGRATION_STATUS_TOO_MANY_CHANGES);
- } else {
- HistogramMigrationStatus(MIGRATION_STATUS_SUCCESS);
+ if (session->HasNonMigratableStreams()) {
+ // Do not migrate sessions with non-migratable streams.
+ if (force_close) {
+ // Close sessions with non-migratable streams.
+ session->CloseSessionOnError(
+ ERR_NETWORK_CHANGED,
+ QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM);
+ HistogramMigrationStatus(MIGRATION_STATUS_NON_MIGRATABLE_STREAM);
+ }
+ continue;
}
+
+ MigrateSessionToNetwork(session, new_network);
}
}
+void QuicStreamFactory::MaybeMigrateSessionEarly(
+ QuicChromiumClientSession* session) {
+ if (!migrate_sessions_early_ || session->HasNonMigratableStreams() ||
+ session->config()->DisableConnectionMigration()) {
+ return;
+ }
+ NetworkHandle new_network =
+ FindAlternateNetwork(session->GetDefaultSocket()->GetBoundNetwork());
+ if (new_network == NetworkChangeNotifier::kInvalidNetworkHandle) {
+ // No alternate network found.
+ return;
+ }
+ OnSessionGoingAway(session);
+ MigrateSessionToNetwork(session, new_network);
+}
+
+void QuicStreamFactory::MigrateSessionToNetwork(
+ QuicChromiumClientSession* session,
+ NetworkHandle new_network) {
+ // Use OS-specified port for socket (DEFAULT_BIND) instead of
+ // using the PortSuggester since the connection is being migrated
+ // and not being newly created.
+ scoped_ptr<DatagramClientSocket> socket(
+ client_socket_factory_->CreateDatagramClientSocket(
+ DatagramSocket::DEFAULT_BIND, RandIntCallback(),
+ session->net_log().net_log(), session->net_log().source()));
+ QuicConnection* connection = session->connection();
+ if (ConfigureSocket(socket.get(), connection->peer_address(), new_network) !=
+ OK) {
+ session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR);
+ HistogramMigrationStatus(MIGRATION_STATUS_INTERNAL_ERROR);
+ return;
+ }
+ scoped_ptr<QuicChromiumPacketReader> new_reader(new QuicChromiumPacketReader(
+ socket.get(), clock_.get(), session, yield_after_packets_,
+ yield_after_duration_, session->net_log()));
+ scoped_ptr<QuicPacketWriter> new_writer(
+ new QuicChromiumPacketWriter(socket.get()));
+
+ if (!session->MigrateToSocket(std::move(socket), std::move(new_reader),
+ std::move(new_writer))) {
+ session->CloseSessionOnError(ERR_NETWORK_CHANGED,
+ QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES);
+ HistogramMigrationStatus(MIGRATION_STATUS_TOO_MANY_CHANGES);
+ return;
+ }
+ HistogramMigrationStatus(MIGRATION_STATUS_SUCCESS);
+}
+
void QuicStreamFactory::OnSSLConfigChanged() {
- CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_INTERNAL_ERROR);
+ CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED);
}
void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) {
- CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_INTERNAL_ERROR);
+ CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED);
}
void QuicStreamFactory::OnCACertChanged(const X509Certificate* cert) {
@@ -1280,7 +1439,7 @@ void QuicStreamFactory::OnCACertChanged(const X509Certificate* cert) {
// Since the OnCACertChanged method doesn't tell us what
// kind of change it is, we have to flush the socket
// pools to be safe.
- CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_INTERNAL_ERROR);
+ CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED);
}
bool QuicStreamFactory::HasActiveSession(const QuicServerId& server_id) const {
@@ -1294,10 +1453,9 @@ bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const {
return ContainsKey(active_jobs_, key);
}
-int QuicStreamFactory::ConfigureSocket(
- DatagramClientSocket* socket,
- IPEndPoint addr,
- NetworkChangeNotifier::NetworkHandle network) {
+int QuicStreamFactory::ConfigureSocket(DatagramClientSocket* socket,
+ IPEndPoint addr,
+ NetworkHandle network) {
if (enable_non_blocking_io_ &&
client_socket_factory_ == ClientSocketFactory::GetDefaultFactory()) {
#if defined(OS_WIN)
@@ -1305,19 +1463,17 @@ int QuicStreamFactory::ConfigureSocket(
#endif
}
- // If caller leaves network unspecified, use current default.
int rv;
if (migrate_sessions_on_network_change_) {
+ // If caller leaves network unspecified, use current default network.
if (network == NetworkChangeNotifier::kInvalidNetworkHandle) {
- rv = socket->BindToDefaultNetwork();
+ rv = socket->ConnectUsingDefaultNetwork(addr);
} else {
- rv = socket->BindToNetwork(network);
+ rv = socket->ConnectUsingNetwork(network, addr);
}
- if (rv != OK)
- return rv;
+ } else {
+ rv = socket->Connect(addr);
}
-
- rv = socket->Connect(addr);
if (rv != OK) {
HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET);
return rv;
@@ -1341,7 +1497,7 @@ int QuicStreamFactory::ConfigureSocket(
socket->GetLocalAddress(&local_address_);
if (check_persisted_supports_quic_) {
check_persisted_supports_quic_ = false;
- IPAddressNumber last_address;
+ IPAddress last_address;
if (http_server_properties_->GetSupportsQuic(&last_address) &&
last_address == local_address_.address()) {
require_confirmation_ = false;
@@ -1358,6 +1514,7 @@ int QuicStreamFactory::CreateSession(const QuicServerId& server_id,
base::TimeTicks dns_resolution_end_time,
const BoundNetLog& net_log,
QuicChromiumClientSession** session) {
+ TRACE_EVENT0("net", "QuicStreamFactory::CreateSession");
IPEndPoint addr = *address_list.begin();
bool enable_port_selection = enable_port_selection_;
if (enable_port_selection && ContainsKey(gone_away_aliases_, server_id)) {
@@ -1399,17 +1556,16 @@ int QuicStreamFactory::CreateSession(const QuicServerId& server_id,
base::ThreadTaskRunnerHandle::Get().get(), clock_.get(),
random_generator_));
}
-
- QuicDefaultPacketWriter* writer = new QuicDefaultPacketWriter(socket.get());
QuicConnectionId connection_id = random_generator_->RandUint64();
+ InitializeCachedStateInCryptoConfig(server_id, server_info, &connection_id);
+
+ QuicChromiumPacketWriter* writer = new QuicChromiumPacketWriter(socket.get());
QuicConnection* connection = new QuicConnection(
connection_id, addr, helper_.get(), writer, true /* owns_writer */,
Perspective::IS_CLIENT, supported_versions_);
writer->SetConnection(connection);
connection->SetMaxPacketLength(max_packet_length_);
- InitializeCachedStateInCryptoConfig(server_id, server_info);
-
QuicConfig config = config_;
config.SetSocketReceiveBufferToSend(socket_receive_buffer_size_);
config.set_max_undecryptable_packets(kMaxUndecryptablePackets);
@@ -1443,7 +1599,8 @@ int QuicStreamFactory::CreateSession(const QuicServerId& server_id,
clock_.get(), transport_security_state_, std::move(server_info),
server_id, yield_after_packets_, yield_after_duration_, cert_verify_flags,
config, &crypto_config_, network_connection_.GetDescription(),
- dns_resolution_end_time, base::ThreadTaskRunnerHandle::Get().get(),
+ dns_resolution_end_time, &push_promise_index_,
+ base::ThreadTaskRunnerHandle::Get().get(),
std::move(socket_performance_watcher), net_log.net_log());
all_sessions_[*session] = server_id; // owning pointer
@@ -1499,17 +1656,21 @@ bool QuicStreamFactory::CryptoConfigCacheIsEmpty(
void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
const QuicServerId& server_id,
- const scoped_ptr<QuicServerInfo>& server_info) {
- // |server_info| will be NULL, if a non-empty server config already exists in
- // the memory cache. This is a minor optimization to avoid LookupOrCreate.
- if (!server_info)
- return;
-
+ const scoped_ptr<QuicServerInfo>& server_info,
+ QuicConnectionId* connection_id) {
QuicCryptoClientConfig::CachedState* cached =
crypto_config_.LookupOrCreate(server_id);
+ if (cached->has_server_designated_connection_id())
+ *connection_id = cached->GetNextServerDesignatedConnectionId();
+
if (!cached->IsEmpty())
return;
+ // |server_info| will be NULL, if a non-empty server config already exists in
+ // the memory cache.
+ if (!server_info)
+ return;
+
// TODO(rtenneti): Delete the following histogram after collecting stats.
// If the AlternativeServiceMap contained an entry for this host, check if
// the disk cache contained an entry for it.
@@ -1521,7 +1682,8 @@ void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
cached->Initialize(server_info->state().server_config,
server_info->state().source_address_token,
- server_info->state().certs, "",
+ server_info->state().certs, server_info->state().cert_sct,
+ server_info->state().chlo_hash,
server_info->state().server_config_sig, clock_->WallNow());
}
@@ -1548,16 +1710,22 @@ void QuicStreamFactory::MaybeInitialize() {
if (http_server_properties_->max_server_configs_stored_in_properties() == 0)
return;
// Create a temporary QuicServerInfo object to deserialize and to populate the
- // in-memory crypto server config cache.
+ // in-memory crypto server config cache in the MRU order.
scoped_ptr<QuicServerInfo> server_info;
CompletionCallback callback;
- for (const auto& key_value :
- http_server_properties_->quic_server_info_map()) {
- const QuicServerId& server_id = key_value.first;
+ // Get the list of servers to be deserialized first because WaitForDataReady
+ // touches quic_server_info_map.
+ const QuicServerInfoMap& quic_server_info_map =
+ http_server_properties_->quic_server_info_map();
+ vector<QuicServerId> server_list(quic_server_info_map.size());
+ for (const auto& key_value : quic_server_info_map)
+ server_list.push_back(key_value.first);
+ for (auto it = server_list.rbegin(); it != server_list.rend(); ++it) {
+ const QuicServerId& server_id = *it;
server_info.reset(quic_server_info_factory_->GetForServer(server_id));
if (server_info->WaitForDataReady(callback) == OK) {
DVLOG(1) << "Initialized server config for: " << server_id.ToString();
- InitializeCachedStateInCryptoConfig(server_id, server_info);
+ InitializeCachedStateInCryptoConfig(server_id, server_info, nullptr);
}
}
}
diff --git a/chromium/net/quic/quic_stream_factory.h b/chromium/net/quic/quic_stream_factory.h
index 9a7cfe5e74e..c2dbfbcf89f 100644
--- a/chromium/net/quic/quic_stream_factory.h
+++ b/chromium/net/quic/quic_stream_factory.h
@@ -8,8 +8,10 @@
#include <stddef.h>
#include <stdint.h>
+#include <deque>
#include <list>
#include <map>
+#include <set>
#include <string>
#include <vector>
@@ -24,10 +26,12 @@
#include "net/base/network_change_notifier.h"
#include "net/cert/cert_database.h"
#include "net/http/http_server_properties.h"
+#include "net/http/http_stream_factory.h"
#include "net/log/net_log.h"
#include "net/proxy/proxy_server.h"
#include "net/quic/network_connection.h"
#include "net/quic/quic_chromium_client_session.h"
+#include "net/quic/quic_client_push_promise_index.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_crypto_stream.h"
#include "net/quic/quic_http_stream.h"
@@ -54,6 +58,7 @@ class QuicServerInfoFactory;
class QuicStreamFactory;
class SocketPerformanceWatcherFactory;
class TransportSecurityState;
+class BidirectionalStreamImpl;
namespace test {
class QuicStreamFactoryPeer;
@@ -75,7 +80,7 @@ class NET_EXPORT_PRIVATE QuicStreamRequest {
int Request(const HostPortPair& host_port_pair,
PrivacyMode privacy_mode,
int cert_verify_flags,
- base::StringPiece origin_host,
+ const GURL& url,
base::StringPiece method,
const BoundNetLog& net_log,
const CompletionCallback& callback);
@@ -86,9 +91,12 @@ class NET_EXPORT_PRIVATE QuicStreamRequest {
// returns the amount of time waiting job should be delayed.
base::TimeDelta GetTimeDelayForWaitingJob() const;
- scoped_ptr<QuicHttpStream> ReleaseStream();
+ scoped_ptr<QuicHttpStream> CreateStream();
- void set_stream(scoped_ptr<QuicHttpStream> stream);
+ scoped_ptr<BidirectionalStreamImpl> CreateBidirectionalStreamImpl();
+
+ // Sets |session_|.
+ void SetSession(QuicChromiumClientSession* session);
const std::string& origin_host() const { return origin_host_; }
@@ -100,10 +108,11 @@ class NET_EXPORT_PRIVATE QuicStreamRequest {
QuicStreamFactory* factory_;
HostPortPair host_port_pair_;
std::string origin_host_;
+ std::string url_;
PrivacyMode privacy_mode_;
BoundNetLog net_log_;
CompletionCallback callback_;
- scoped_ptr<QuicHttpStream> stream_;
+ base::WeakPtr<QuicChromiumClientSession> session_;
DISALLOW_COPY_AND_ASSIGN(QuicStreamRequest);
};
@@ -149,9 +158,12 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
bool delay_tcp_race,
int max_server_configs_stored_in_properties,
bool close_sessions_on_ip_change,
+ bool disable_quic_on_timeout_with_open_streams,
int idle_connection_timeout_seconds,
bool migrate_sessions_on_network_change,
- const QuicTagVector& connection_options);
+ bool migrate_sessions_early,
+ const QuicTagVector& connection_options,
+ bool enable_token_binding);
~QuicStreamFactory() override;
// Returns true if there is an existing session to |server_id| which can be
@@ -168,7 +180,7 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
int Create(const HostPortPair& host_port_pair,
PrivacyMode privacy_mode,
int cert_verify_flags,
- base::StringPiece origin_host,
+ const GURL& url,
base::StringPiece method,
const BoundNetLog& net_log,
QuicStreamRequest* request);
@@ -183,8 +195,12 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
bool OnHandshakeConfirmed(QuicChromiumClientSession* session,
float packet_loss_rate);
+ // Called when a TCP job completes for an origin that QUIC potentially
+ // could be used for.
+ void OnTcpJobCompleted(bool succeeded);
+
// Returns true if QUIC is disabled for this port.
- bool IsQuicDisabled(uint16_t port);
+ bool IsQuicDisabled(uint16_t port) const;
// Returns reason QUIC is disabled for this port, or QUIC_DISABLED_NOT if not.
QuicChromiumClientSession::QuicDisabledReason QuicDisabledReason(
@@ -226,7 +242,13 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
IPEndPoint addr,
NetworkChangeNotifier::NetworkHandle network);
- // Helper method that initiates migration of active sessions
+ // Finds an alternative to |old_network| from the platform's list of connected
+ // networks. Returns NetworkChangeNotifier::kInvalidNetworkHandle if no
+ // alternative is found.
+ NetworkChangeNotifier::NetworkHandle FindAlternateNetwork(
+ NetworkChangeNotifier::NetworkHandle old_network);
+
+ // Method that initiates migration of active sessions
// currently bound to |network| to an alternate network, if one
// exists. Idle sessions bound to |network| are closed. If there is
// no alternate network to migrate active sessions onto, active
@@ -235,6 +257,16 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
void MaybeMigrateOrCloseSessions(NetworkChangeNotifier::NetworkHandle network,
bool force_close);
+ // Method that initiates early migration of |session| if |session| is
+ // active and if there is an alternate network than the one to which
+ // |session| is currently bound.
+ void MaybeMigrateSessionEarly(QuicChromiumClientSession* session);
+
+ // Method that migrates |session| over to using |new_network|.
+ void MigrateSessionToNetwork(
+ QuicChromiumClientSession* session,
+ NetworkChangeNotifier::NetworkHandle new_network);
+
// NetworkChangeNotifier::IPAddressObserver methods:
// Until the servers support roaming, close all connections when the local
@@ -311,6 +343,12 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
typedef std::deque<enum QuicChromiumClientSession::QuicDisabledReason>
DisabledReasonsQueue;
+ enum FactoryStatus {
+ OPEN, // New streams may be created.
+ CLOSED, // No new streams may be created temporarily.
+ DISABLED // No more streams may be created until the network changes.
+ };
+
// Creates a job which doesn't wait for server config to be loaded from the
// disk cache. This job is started via a PostTask.
void CreateAuxilaryJob(const QuicServerId server_id,
@@ -350,10 +388,13 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
bool CryptoConfigCacheIsEmpty(const QuicServerId& server_id);
// Initializes the cached state associated with |server_id| in
- // |crypto_config_| with the information in |server_info|.
+ // |crypto_config_| with the information in |server_info|. Populates
+ // |connection_id| with the next server designated connection id,
+ // if any, and otherwise leaves it unchanged.
void InitializeCachedStateInCryptoConfig(
const QuicServerId& server_id,
- const scoped_ptr<QuicServerInfo>& server_info);
+ const scoped_ptr<QuicServerInfo>& server_info,
+ QuicConnectionId* connection_id);
// Initialize |quic_supported_servers_at_startup_| with the list of servers
// that supported QUIC at start up and also initialize in-memory cache of
@@ -367,6 +408,8 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
// Collect stats from recent connections, possibly disabling Quic.
void MaybeDisableQuic(QuicChromiumClientSession* session);
+ void MaybeDisableQuic(uint16_t port);
+
bool require_confirmation_;
HostResolver* host_resolver_;
ClientSocketFactory* client_socket_factory_;
@@ -474,7 +517,7 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
// If more than |yield_after_packets_| packets have been read or more than
// |yield_after_duration_| time has passed, then
- // QuicPacketReader::StartReading() yields by doing a PostTask().
+ // QuicChromiumPacketReader::StartReading() yields by doing a PostTask().
int yield_after_packets_;
QuicTime::Delta yield_after_duration_;
@@ -485,6 +528,10 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
// interface changes.
const bool migrate_sessions_on_network_change_;
+ // Set if early migration should be attempted when the connection
+ // experiences poor connectivity.
+ const bool migrate_sessions_early_;
+
// 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
@@ -501,6 +548,13 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
NetworkConnection network_connection_;
+ int num_push_streams_created_;
+
+ QuicClientPushPromiseIndex push_promise_index_;
+
+ // Current status of the factory's ability to create streams.
+ FactoryStatus status_;
+
base::TaskRunner* task_runner_;
base::WeakPtrFactory<QuicStreamFactory> weak_factory_;
diff --git a/chromium/net/quic/quic_stream_factory_test.cc b/chromium/net/quic/quic_stream_factory_test.cc
index 8754453ccab..e6fffabfbed 100644
--- a/chromium/net/quic/quic_stream_factory_test.cc
+++ b/chromium/net/quic/quic_stream_factory_test.cc
@@ -23,12 +23,14 @@
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/crypto/quic_server_info.h"
+#include "net/quic/quic_client_promised_info.h"
#include "net/quic/quic_http_stream.h"
#include "net/quic/quic_http_utils.h"
#include "net/quic/quic_server_id.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"
@@ -56,6 +58,10 @@ const char kServer2HostName[] = "mail.example.org";
const char kServer3HostName[] = "docs.example.org";
const char kServer4HostName[] = "images.example.org";
const int kDefaultServerPort = 443;
+const char kDefaultUrl[] = "https://www.example.org/";
+const char kServer2Url[] = "https://mail.example.org/";
+const char kServer3Url[] = "https://docs.example.org/";
+const char kServer4Url[] = "https://images.example.org/";
// Run all tests with all the combinations of versions and
// enable_connection_racing.
@@ -201,6 +207,10 @@ class QuicStreamFactoryTest : public ::testing::TestWithParam<TestParams> {
scoped_mock_network_change_notifier_(nullptr),
factory_(nullptr),
host_port_pair_(kDefaultServerHostName, kDefaultServerPort),
+ url_(kDefaultUrl),
+ url2_(kServer2Url),
+ url3_(kServer3Url),
+ url4_(kServer4Url),
privacy_mode_(PRIVACY_MODE_DISABLED),
enable_port_selection_(true),
always_require_handshake_confirmation_(false),
@@ -218,8 +228,10 @@ class QuicStreamFactoryTest : public ::testing::TestWithParam<TestParams> {
receive_buffer_size_(0),
delay_tcp_race_(false),
close_sessions_on_ip_change_(false),
+ disable_quic_on_timeout_with_open_streams_(false),
idle_connection_timeout_seconds_(kIdleConnectionTimeoutSeconds),
- migrate_sessions_on_network_change_(false) {
+ migrate_sessions_on_network_change_(false),
+ migrate_sessions_early_(false) {
clock_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
@@ -239,8 +251,11 @@ class QuicStreamFactoryTest : public ::testing::TestWithParam<TestParams> {
max_disabled_reasons_, threshold_timeouts_with_open_streams_,
threshold_public_resets_post_handshake_, receive_buffer_size_,
delay_tcp_race_, /*max_server_configs_stored_in_properties*/ 0,
- close_sessions_on_ip_change_, idle_connection_timeout_seconds_,
- migrate_sessions_on_network_change_, QuicTagVector()));
+ close_sessions_on_ip_change_,
+ disable_quic_on_timeout_with_open_streams_,
+ idle_connection_timeout_seconds_, migrate_sessions_on_network_change_,
+ migrate_sessions_early_, QuicTagVector(),
+ /*enable_token_binding*/ false));
factory_->set_require_confirmation(false);
EXPECT_FALSE(factory_->has_quic_server_info_factory());
factory_->set_quic_server_info_factory(new MockQuicServerInfoFactory());
@@ -256,6 +271,7 @@ class QuicStreamFactoryTest : public ::testing::TestWithParam<TestParams> {
mock_ncn->ForceNetworkHandlesSupported();
mock_ncn->SetConnectedNetworksList(connected_networks);
migrate_sessions_on_network_change_ = true;
+ migrate_sessions_early_ = true;
Initialize();
}
@@ -290,13 +306,14 @@ class QuicStreamFactoryTest : public ::testing::TestWithParam<TestParams> {
socket_factory_.AddSocketDataProvider(&socket_data);
QuicStreamRequest request(factory_.get());
+ GURL url("https://" + destination.host() + "/");
EXPECT_EQ(ERR_IO_PENDING,
request.Request(destination, privacy_mode_,
- /*cert_verify_flags=*/0, destination.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
stream.reset();
@@ -392,6 +409,11 @@ class QuicStreamFactoryTest : public ::testing::TestWithParam<TestParams> {
scoped_mock_network_change_notifier_;
scoped_ptr<QuicStreamFactory> factory_;
HostPortPair host_port_pair_;
+ GURL url_;
+ GURL url2_;
+ GURL url3_;
+ GURL url4_;
+
PrivacyMode privacy_mode_;
BoundNetLog net_log_;
TestCompletionCallback callback_;
@@ -413,8 +435,10 @@ class QuicStreamFactoryTest : public ::testing::TestWithParam<TestParams> {
int receive_buffer_size_;
bool delay_tcp_race_;
bool close_sessions_on_ip_change_;
+ bool disable_quic_on_timeout_with_open_streams_;
int idle_connection_timeout_seconds_;
bool migrate_sessions_on_network_change_;
+ bool migrate_sessions_early_;
};
INSTANTIATE_TEST_CASE_P(Version,
@@ -433,11 +457,11 @@ TEST_P(QuicStreamFactoryTest, Create) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
// Will reset stream 3.
@@ -447,11 +471,10 @@ TEST_P(QuicStreamFactoryTest, Create) {
// TODO(rtenneti): We should probably have a tests that HTTP and HTTPS result
// in streams on different sessions.
QuicStreamRequest request2(factory_.get());
- EXPECT_EQ(OK,
- request2.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
- stream = request2.ReleaseStream(); // Will reset stream 5.
+ EXPECT_EQ(OK, request2.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ stream = request2.CreateStream(); // Will reset stream 5.
stream.reset(); // Will reset stream 7.
EXPECT_TRUE(socket_data.AllReadDataConsumed());
@@ -475,10 +498,10 @@ TEST_P(QuicStreamFactoryTest, CreateZeroRtt) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -503,15 +526,15 @@ TEST_P(QuicStreamFactoryTest, CreateZeroRttPost) {
// Posts require handshake confirmation, so this will return asynchronously.
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "POST", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "POST", net_log_,
+ callback_.callback()));
// Confirm the handshake and verify that the stream is created.
crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent(
QuicSession::HANDSHAKE_CONFIRMED);
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -533,9 +556,9 @@ TEST_P(QuicStreamFactoryTest, NoZeroRttForDifferentHost) {
"192.168.0.1", "");
QuicStreamRequest request(factory_.get());
- int rv =
- request.Request(host_port_pair_, privacy_mode_, /*cert_verify_flags=*/0,
- kServer2HostName, "GET", net_log_, callback_.callback());
+ int rv = request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url2_, "GET", net_log_,
+ callback_.callback());
// If server and origin have different hostnames, then handshake confirmation
// should be required, so Request will return asynchronously.
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -544,7 +567,7 @@ TEST_P(QuicStreamFactoryTest, NoZeroRttForDifferentHost) {
QuicSession::HANDSHAKE_CONFIRMED);
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -562,11 +585,11 @@ TEST_P(QuicStreamFactoryTest, GoAway) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
QuicChromiumClientSession* session =
@@ -581,6 +604,46 @@ TEST_P(QuicStreamFactoryTest, GoAway) {
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
+TEST_P(QuicStreamFactoryTest, GoAwayForConnectionMigrationWithPortOnly) {
+ Initialize();
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ SequencedSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_TRUE(stream.get());
+
+ QuicChromiumClientSession* session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+
+ session->OnGoAway(
+ QuicGoAwayFrame(QUIC_ERROR_MIGRATING_PORT, 0,
+ "peer connection migration due to port change only"));
+ NetErrorDetails details;
+ EXPECT_FALSE(details.quic_port_migration_detected);
+ session->PopulateNetErrorDetails(&details);
+ EXPECT_TRUE(details.quic_port_migration_detected);
+ details.quic_port_migration_detected = false;
+ stream->PopulateNetErrorDetails(&details);
+ EXPECT_TRUE(details.quic_port_migration_detected);
+
+ EXPECT_FALSE(
+ QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
+
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
TEST_P(QuicStreamFactoryTest, Pooling) {
Initialize();
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -598,17 +661,17 @@ TEST_P(QuicStreamFactoryTest, Pooling) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
TestCompletionCallback callback;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback.callback()));
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
EXPECT_EQ(
@@ -640,17 +703,17 @@ TEST_P(QuicStreamFactoryTest, NoPoolingIfDisabled) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
TestCompletionCallback callback;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback.callback()));
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
EXPECT_NE(
@@ -683,17 +746,17 @@ TEST_P(QuicStreamFactoryTest, NoPoolingAfterGoAway) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
TestCompletionCallback callback;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback.callback()));
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
factory_->OnSessionGoingAway(
@@ -706,9 +769,9 @@ TEST_P(QuicStreamFactoryTest, NoPoolingAfterGoAway) {
TestCompletionCallback callback3;
QuicStreamRequest request3(factory_.get());
EXPECT_EQ(OK, request3.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback3.callback()));
- scoped_ptr<QuicHttpStream> stream3 = request3.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream3 = request3.CreateStream();
EXPECT_TRUE(stream3.get());
EXPECT_TRUE(QuicStreamFactoryPeer::HasActiveSession(factory_.get(), server2));
@@ -738,17 +801,17 @@ TEST_P(QuicStreamFactoryTest, HttpsPooling) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(server1, privacy_mode_,
- /*cert_verify_flags=*/0, server1.host(), "GET",
- net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
TestCompletionCallback callback;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
EXPECT_EQ(QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server1),
@@ -781,17 +844,17 @@ TEST_P(QuicStreamFactoryTest, NoHttpsPoolingIfDisabled) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(server1, privacy_mode_,
- /*cert_verify_flags=*/0, server1.host(), "GET",
- net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
TestCompletionCallback callback;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
EXPECT_NE(QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server1),
@@ -814,14 +877,14 @@ class QuicAlternativeServiceCertificateValidationPooling
HostPortPair server1(kDefaultServerHostName, 443);
HostPortPair server2(kServer2HostName, 443);
- std::string origin_host(valid ? kServer2HostName : "invalid.example.com");
+ GURL url(valid ? url2_ : GURL("http://invalid.example.com/"));
HostPortPair alternative(kDefaultServerHostName, 443);
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
bool common_name_fallback_used;
EXPECT_EQ(valid,
verify_details.cert_verify_result.verified_cert->VerifyNameMatch(
- origin_host, &common_name_fallback_used));
+ url.host(), &common_name_fallback_used));
EXPECT_TRUE(
verify_details.cert_verify_result.verified_cert->VerifyNameMatch(
alternative.host(), &common_name_fallback_used));
@@ -834,22 +897,22 @@ class QuicAlternativeServiceCertificateValidationPooling
// Open first stream to alternative.
QuicStreamRequest request1(factory_.get());
EXPECT_EQ(OK, request1.Request(alternative, privacy_mode_,
- /*cert_verify_flags=*/0, alternative.host(),
- "GET", net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream1 = request1.ReleaseStream();
+ /*cert_verify_flags=*/0, url_, "GET",
+ net_log_, callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream1 = request1.CreateStream();
EXPECT_TRUE(stream1.get());
QuicStreamRequest request2(factory_.get());
int rv = request2.Request(alternative, privacy_mode_,
- /*cert_verify_flags=*/0, origin_host, "GET",
- net_log_, callback_.callback());
+ /*cert_verify_flags=*/0, url, "GET", net_log_,
+ callback_.callback());
if (valid) {
// Alternative service of origin to |alternative| should pool to session
// of |stream1| even if origin is different. Since only one
// SocketDataProvider is set up, the second request succeeding means that
// it pooled to the session opened by the first one.
EXPECT_EQ(OK, rv);
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
} else {
EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv);
@@ -898,17 +961,17 @@ TEST_P(QuicStreamFactoryTest, HttpsPoolingWithMatchingPins) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(server1, privacy_mode_,
- /*cert_verify_flags=*/0, server1.host(), "GET",
- net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
TestCompletionCallback callback;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
EXPECT_EQ(QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server1),
@@ -947,17 +1010,17 @@ TEST_P(QuicStreamFactoryTest, NoHttpsPoolingWithMatchingPinsIfDisabled) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(server1, privacy_mode_,
- /*cert_verify_flags=*/0, server1.host(), "GET",
- net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
TestCompletionCallback callback;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
EXPECT_NE(QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server1),
@@ -1001,17 +1064,17 @@ TEST_P(QuicStreamFactoryTest, NoHttpsPoolingWithDifferentPins) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(server1, privacy_mode_,
- /*cert_verify_flags=*/0, server1.host(), "GET",
- net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
TestCompletionCallback callback;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback_.callback()));
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
EXPECT_NE(QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server1),
@@ -1038,11 +1101,11 @@ TEST_P(QuicStreamFactoryTest, Goaway) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
// Mark the session as going away. Ensure that while it is still alive
@@ -1061,10 +1124,10 @@ TEST_P(QuicStreamFactoryTest, Goaway) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
EXPECT_TRUE(
@@ -1110,15 +1173,15 @@ TEST_P(QuicStreamFactoryTest, MaxOpenStream) {
for (size_t i = 0; i < kDefaultMaxStreamsPerConnection / 2; i++) {
QuicStreamRequest request(factory_.get());
int rv = request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback());
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback());
if (i == 0) {
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback_.WaitForResult());
} else {
EXPECT_EQ(OK, rv);
}
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream);
EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
net_log_, CompletionCallback()));
@@ -1127,9 +1190,9 @@ TEST_P(QuicStreamFactoryTest, MaxOpenStream) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, CompletionCallback()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ CompletionCallback()));
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream);
EXPECT_EQ(ERR_IO_PENDING,
stream->InitializeStream(&request_info, DEFAULT_PRIORITY, net_log_,
@@ -1149,7 +1212,8 @@ TEST_P(QuicStreamFactoryTest, MaxOpenStream) {
// this test anyway.
QuicChromiumClientSession* session =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
- session->connection()->CloseConnection(QUIC_PUBLIC_RESET, true);
+ session->connection()->CloseConnection(QUIC_PUBLIC_RESET, "test",
+ ConnectionCloseBehavior::SILENT_CLOSE);
STLDeleteElements(&streams);
}
@@ -1164,8 +1228,8 @@ TEST_P(QuicStreamFactoryTest, ResolutionErrorInCreate) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(ERR_NAME_NOT_RESOLVED, callback_.WaitForResult());
@@ -1183,8 +1247,8 @@ TEST_P(QuicStreamFactoryTest, ConnectErrorInCreate) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(ERR_ADDRESS_IN_USE, callback_.WaitForResult());
@@ -1201,8 +1265,8 @@ TEST_P(QuicStreamFactoryTest, CancelCreate) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
}
base::RunLoop().RunUntilIdle();
@@ -1272,11 +1336,11 @@ TEST_P(QuicStreamFactoryTest, CloseAllSessions) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
HttpRequestInfo request_info;
EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
net_log_, CompletionCallback()));
@@ -1292,11 +1356,11 @@ TEST_P(QuicStreamFactoryTest, CloseAllSessions) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- stream = request2.ReleaseStream();
+ stream = request2.CreateStream();
stream.reset(); // Will reset stream 3.
EXPECT_TRUE(socket_data.AllReadDataConsumed());
@@ -1328,11 +1392,11 @@ TEST_P(QuicStreamFactoryTest, OnIPAddressChanged) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
HttpRequestInfo request_info;
EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
net_log_, CompletionCallback()));
@@ -1349,11 +1413,11 @@ TEST_P(QuicStreamFactoryTest, OnIPAddressChanged) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- stream = request2.ReleaseStream();
+ stream = request2.CreateStream();
stream.reset(); // Will reset stream 3.
EXPECT_TRUE(socket_data.AllReadDataConsumed());
@@ -1382,10 +1446,10 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeSoonToDisconnect) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
// Cause QUIC stream to be created.
@@ -1447,22 +1511,27 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeSoonToDisconnect) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
EXPECT_TRUE(
QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
- EXPECT_NE(session, QuicStreamFactoryPeer::GetActiveSession(factory_.get(),
- host_port_pair_));
+ QuicChromiumClientSession* new_session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+ EXPECT_NE(session, new_session);
- // On a DISCONNECTED notification, nothing happens to the migrated session.
+ // On a DISCONNECTED notification, nothing happens to the migrated
+ // session, but the new session is closed since it has no open
+ // streams.
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->NotifyNetworkDisconnected(kDefaultNetworkForTests);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_EQ(1u, session->GetNumActiveStreams());
+ EXPECT_FALSE(
+ QuicStreamFactoryPeer::IsLiveSession(factory_.get(), new_session));
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -1492,10 +1561,10 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeDisconnected) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
// Cause QUIC stream to be created.
@@ -1553,10 +1622,10 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeDisconnected) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
EXPECT_TRUE(
@@ -1594,10 +1663,10 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeSoonToDisconnectNoNetworks) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
// Cause QUIC stream to be created.
@@ -1648,10 +1717,10 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeDisconnectedNoNetworks) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
// Cause QUIC stream to be created.
@@ -1697,10 +1766,10 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeSoonToDisconnectNoNewNetwork) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
// Cause QUIC stream to be created.
@@ -1749,10 +1818,10 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeDisconnectedNoNewNetwork) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
// Cause QUIC stream to be created.
@@ -1779,6 +1848,223 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeDisconnectedNoNewNetwork) {
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
+TEST_P(QuicStreamFactoryTest,
+ OnNetworkChangeSoonToDisconnectNonMigratableStream) {
+ InitializeConnectionMigrationTest(
+ {kDefaultNetworkForTests, kNewNetworkForTests});
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ scoped_ptr<QuicEncryptedPacket> client_rst(maker_.MakeRstPacket(
+ 1, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
+ MockWrite writes[] = {
+ MockWrite(SYNCHRONOUS, client_rst->data(), client_rst->length(), 1),
+ };
+ SequencedSocketData socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ // Create request and QuicHttpStream.
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_TRUE(stream.get());
+
+ // Cause QUIC stream to be created, but marked as non-migratable.
+ HttpRequestInfo request_info;
+ request_info.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION;
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
+ net_log_, CompletionCallback()));
+
+ // Ensure that session is alive and active.
+ QuicChromiumClientSession* session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+
+ // Trigger connection migration. Since there is a non-migratable stream,
+ // this should cause session to continue but be marked as going away.
+ scoped_mock_network_change_notifier_->mock_network_change_notifier()
+ ->NotifyNetworkSoonToDisconnect(kDefaultNetworkForTests);
+
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_EQ(1u, session->GetNumActiveStreams());
+
+ stream.reset();
+
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
+TEST_P(QuicStreamFactoryTest,
+ OnNetworkChangeSoonToDisconnectConnectionMigrationDisabled) {
+ InitializeConnectionMigrationTest(
+ {kDefaultNetworkForTests, kNewNetworkForTests});
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ scoped_ptr<QuicEncryptedPacket> client_rst(maker_.MakeRstPacket(
+ 1, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
+ MockWrite writes[] = {
+ MockWrite(SYNCHRONOUS, client_rst->data(), client_rst->length(), 1),
+ };
+ SequencedSocketData socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ // Create request and QuicHttpStream.
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_TRUE(stream.get());
+
+ // Cause QUIC stream to be created.
+ HttpRequestInfo request_info;
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
+ net_log_, CompletionCallback()));
+
+ // Ensure that session is alive and active.
+ QuicChromiumClientSession* session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+
+ // Set session config to have connection migration disabled.
+ QuicConfigPeer::SetReceivedDisableConnectionMigration(session->config());
+ EXPECT_TRUE(session->config()->DisableConnectionMigration());
+
+ // Trigger connection migration. Since there is a non-migratable stream,
+ // this should cause session to continue but be marked as going away.
+ scoped_mock_network_change_notifier_->mock_network_change_notifier()
+ ->NotifyNetworkSoonToDisconnect(kDefaultNetworkForTests);
+
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_EQ(1u, session->GetNumActiveStreams());
+
+ stream.reset();
+
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
+TEST_P(QuicStreamFactoryTest, OnNetworkChangeDisconnectedNonMigratableStream) {
+ InitializeConnectionMigrationTest(
+ {kDefaultNetworkForTests, kNewNetworkForTests});
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ scoped_ptr<QuicEncryptedPacket> client_rst(maker_.MakeRstPacket(
+ 1, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
+ MockWrite writes[] = {
+ MockWrite(ASYNC, client_rst->data(), client_rst->length(), 1),
+ };
+ SequencedSocketData socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ // Create request and QuicHttpStream.
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_TRUE(stream.get());
+
+ // Cause QUIC stream to be created, but marked as non-migratable.
+ HttpRequestInfo request_info;
+ request_info.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION;
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
+ net_log_, CompletionCallback()));
+
+ // Ensure that session is alive and active.
+ QuicChromiumClientSession* session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+
+ // Trigger connection migration. Since there is a non-migratable stream,
+ // this should cause a RST_STREAM frame to be emitted with
+ // QUIC_RST_ACKNOWLEDGEMENT error code, and the session will be closed.
+ scoped_mock_network_change_notifier_->mock_network_change_notifier()
+ ->NotifyNetworkDisconnected(kDefaultNetworkForTests);
+
+ EXPECT_FALSE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_FALSE(HasActiveSession(host_port_pair_));
+
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
+TEST_P(QuicStreamFactoryTest,
+ OnNetworkChangeDisconnectedConnectionMigrationDisabled) {
+ InitializeConnectionMigrationTest(
+ {kDefaultNetworkForTests, kNewNetworkForTests});
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ scoped_ptr<QuicEncryptedPacket> client_rst(maker_.MakeRstPacket(
+ 1, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
+ MockWrite writes[] = {
+ MockWrite(ASYNC, client_rst->data(), client_rst->length(), 1),
+ };
+ SequencedSocketData socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ // Create request and QuicHttpStream.
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_TRUE(stream.get());
+
+ // Cause QUIC stream to be created.
+ HttpRequestInfo request_info;
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
+ net_log_, CompletionCallback()));
+
+ // Ensure that session is alive and active.
+ QuicChromiumClientSession* session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+
+ // Set session config to have connection migration disabled.
+ QuicConfigPeer::SetReceivedDisableConnectionMigration(session->config());
+ EXPECT_TRUE(session->config()->DisableConnectionMigration());
+
+ // Trigger connection migration. Since there is a non-migratable stream,
+ // this should cause a RST_STREAM frame to be emitted with
+ // QUIC_RST_ACKNOWLEDGEMENT error code, and the session will be closed.
+ scoped_mock_network_change_notifier_->mock_network_change_notifier()
+ ->NotifyNetworkDisconnected(kDefaultNetworkForTests);
+
+ EXPECT_FALSE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_FALSE(HasActiveSession(host_port_pair_));
+
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
TEST_P(QuicStreamFactoryTest, OnNetworkChangeSoonToDisconnectNoOpenStreams) {
InitializeConnectionMigrationTest(
{kDefaultNetworkForTests, kNewNetworkForTests});
@@ -1793,10 +2079,10 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeSoonToDisconnectNoOpenStreams) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
// Ensure that session is alive and active.
@@ -1831,10 +2117,10 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeDisconnectedNoOpenStreams) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
// Ensure that session is alive and active.
@@ -1855,6 +2141,300 @@ TEST_P(QuicStreamFactoryTest, OnNetworkChangeDisconnectedNoOpenStreams) {
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
+TEST_P(QuicStreamFactoryTest, MigrateSessionEarly) {
+ InitializeConnectionMigrationTest(
+ {kDefaultNetworkForTests, kNewNetworkForTests});
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ scoped_ptr<QuicEncryptedPacket> request_packet(
+ ConstructGetRequestPacket(1, kClientDataStreamId1, true, true));
+ MockWrite writes[] = {MockWrite(SYNCHRONOUS, request_packet->data(),
+ request_packet->length(), 1)};
+ SequencedSocketData socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ // Create request and QuicHttpStream.
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_TRUE(stream.get());
+
+ // Cause QUIC stream to be created.
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("https://www.example.org/");
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
+ net_log_, CompletionCallback()));
+
+ // Ensure that session is alive and active.
+ QuicChromiumClientSession* session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+
+ // Send GET request on stream.
+ HttpResponseInfo response;
+ HttpRequestHeaders request_headers;
+ EXPECT_EQ(OK, stream->SendRequest(request_headers, &response,
+ callback_.callback()));
+
+ // Set up second socket data provider that is used after migration.
+ // The response to the earlier request is read on this new socket.
+ scoped_ptr<QuicEncryptedPacket> ping(
+ maker_.MakePingPacket(2, /*include_version=*/true));
+ MockWrite writes1[] = {
+ MockWrite(SYNCHRONOUS, ping->data(), ping->length(), 0)};
+ scoped_ptr<QuicEncryptedPacket> response_headers_packet(
+ ConstructOkResponsePacket(1, kClientDataStreamId1, false, false));
+ MockRead reads1[] = {MockRead(ASYNC, response_headers_packet->data(),
+ response_headers_packet->length(), 1),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
+ SequencedSocketData socket_data1(reads1, arraysize(reads1), writes1,
+ arraysize(writes1));
+ socket_factory_.AddSocketDataProvider(&socket_data1);
+
+ // Trigger early connection migration. This should cause a PING frame
+ // to be emitted.
+ session->OnPathDegrading();
+
+ // Run the message loop so that data queued in the new socket is read by the
+ // packet reader.
+ base::RunLoop().RunUntilIdle();
+
+ // The session should now be marked as going away. Ensure that
+ // while it is still alive, it is no longer active.
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_EQ(1u, session->GetNumActiveStreams());
+
+ // Verify that response headers on the migrated socket were delivered to the
+ // stream.
+ EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback()));
+ EXPECT_EQ(200, response.headers->response_code());
+
+ // Create a new request for the same destination and verify that a
+ // new session is created.
+ MockRead reads2[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ SequencedSocketData socket_data2(reads2, arraysize(reads2), nullptr, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data2);
+
+ QuicStreamRequest request2(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request2.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
+ EXPECT_TRUE(stream2.get());
+
+ EXPECT_TRUE(
+ QuicStreamFactoryPeer::HasActiveSession(factory_.get(), host_port_pair_));
+ QuicChromiumClientSession* new_session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+ EXPECT_NE(session, new_session);
+
+ // On a SOON_TO_DISCONNECT notification, nothing happens to the
+ // migrated session, but the new session is closed since it has no
+ // open streams.
+ scoped_mock_network_change_notifier_->mock_network_change_notifier()
+ ->NotifyNetworkSoonToDisconnect(kDefaultNetworkForTests);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_EQ(1u, session->GetNumActiveStreams());
+ EXPECT_FALSE(
+ QuicStreamFactoryPeer::IsLiveSession(factory_.get(), new_session));
+
+ // On a DISCONNECTED notification, nothing happens to the migrated session.
+ scoped_mock_network_change_notifier_->mock_network_change_notifier()
+ ->NotifyNetworkDisconnected(kDefaultNetworkForTests);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_EQ(1u, session->GetNumActiveStreams());
+
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+ EXPECT_TRUE(socket_data1.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
+ EXPECT_TRUE(socket_data2.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
+}
+
+TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyNoNewNetwork) {
+ InitializeConnectionMigrationTest({kDefaultNetworkForTests});
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ scoped_ptr<QuicEncryptedPacket> client_rst(maker_.MakeRstPacket(
+ 1, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
+ MockWrite writes[] = {
+ MockWrite(SYNCHRONOUS, client_rst->data(), client_rst->length(), 1),
+ };
+ SequencedSocketData socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ // Create request and QuicHttpStream.
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_TRUE(stream.get());
+
+ // Cause QUIC stream to be created.
+ HttpRequestInfo request_info;
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
+ net_log_, CompletionCallback()));
+
+ // Ensure that session is alive and active.
+ QuicChromiumClientSession* session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+
+ // Trigger connection migration. Since there are no networks
+ // to migrate to, this should cause session to be continue but be marked as
+ // going away.
+ session->OnPathDegrading();
+
+ // Run the message loop so that data queued in the new socket is read by the
+ // packet reader.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_EQ(1u, session->GetNumActiveStreams());
+
+ stream.reset();
+
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
+TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyNonMigratableStream) {
+ InitializeConnectionMigrationTest(
+ {kDefaultNetworkForTests, kNewNetworkForTests});
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ scoped_ptr<QuicEncryptedPacket> client_rst(maker_.MakeRstPacket(
+ 1, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
+ MockWrite writes[] = {
+ MockWrite(SYNCHRONOUS, client_rst->data(), client_rst->length(), 1),
+ };
+ SequencedSocketData socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ // Create request and QuicHttpStream.
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_TRUE(stream.get());
+
+ // Cause QUIC stream to be created, but marked as non-migratable.
+ HttpRequestInfo request_info;
+ request_info.load_flags |= LOAD_DISABLE_CONNECTION_MIGRATION;
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
+ net_log_, CompletionCallback()));
+
+ // Ensure that session is alive and active.
+ QuicChromiumClientSession* session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+
+ // Trigger connection migration. Since there is a non-migratable stream,
+ // this should cause session to be continue without migrating.
+ session->OnPathDegrading();
+
+ // Run the message loop so that data queued in the new socket is read by the
+ // packet reader.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_EQ(1u, session->GetNumActiveStreams());
+
+ stream.reset();
+
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
+TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyConnectionMigrationDisabled) {
+ InitializeConnectionMigrationTest(
+ {kDefaultNetworkForTests, kNewNetworkForTests});
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ scoped_ptr<QuicEncryptedPacket> client_rst(maker_.MakeRstPacket(
+ 1, true, kClientDataStreamId1, QUIC_STREAM_CANCELLED));
+ MockWrite writes[] = {
+ MockWrite(SYNCHRONOUS, client_rst->data(), client_rst->length(), 1),
+ };
+ SequencedSocketData socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ // Create request and QuicHttpStream.
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_TRUE(stream.get());
+
+ // Cause QUIC stream to be created.
+ HttpRequestInfo request_info;
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
+ net_log_, CompletionCallback()));
+
+ // Ensure that session is alive and active.
+ QuicChromiumClientSession* session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+
+ // Set session config to have connection migration disabled.
+ QuicConfigPeer::SetReceivedDisableConnectionMigration(session->config());
+ EXPECT_TRUE(session->config()->DisableConnectionMigration());
+
+ // Trigger connection migration. Since there is a non-migratable stream,
+ // this should cause session to be continue without migrating.
+ session->OnPathDegrading();
+
+ // Run the message loop so that data queued in the new socket is read by the
+ // packet reader.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_EQ(1u, session->GetNumActiveStreams());
+
+ stream.reset();
+
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
TEST_P(QuicStreamFactoryTest, OnSSLConfigChanged) {
Initialize();
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -1877,11 +2457,11 @@ TEST_P(QuicStreamFactoryTest, OnSSLConfigChanged) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
HttpRequestInfo request_info;
EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
net_log_, CompletionCallback()));
@@ -1897,11 +2477,11 @@ TEST_P(QuicStreamFactoryTest, OnSSLConfigChanged) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- stream = request2.ReleaseStream();
+ stream = request2.CreateStream();
stream.reset(); // Will reset stream 3.
EXPECT_TRUE(socket_data.AllReadDataConsumed());
@@ -1932,11 +2512,11 @@ TEST_P(QuicStreamFactoryTest, OnCertAdded) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
HttpRequestInfo request_info;
EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
net_log_, CompletionCallback()));
@@ -1953,11 +2533,11 @@ TEST_P(QuicStreamFactoryTest, OnCertAdded) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- stream = request2.ReleaseStream();
+ stream = request2.CreateStream();
stream.reset(); // Will reset stream 3.
EXPECT_TRUE(socket_data.AllReadDataConsumed());
@@ -1988,11 +2568,11 @@ TEST_P(QuicStreamFactoryTest, OnCACertChanged) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
HttpRequestInfo request_info;
EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
net_log_, CompletionCallback()));
@@ -2009,11 +2589,11 @@ TEST_P(QuicStreamFactoryTest, OnCACertChanged) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
- stream = request2.ReleaseStream();
+ stream = request2.CreateStream();
stream.reset(); // Will reset stream 3.
EXPECT_TRUE(socket_data.AllReadDataConsumed());
@@ -2118,7 +2698,7 @@ TEST_P(QuicStreamFactoryTest, RacingConnections) {
AlternativeServiceInfoVector alternative_service_info_vector;
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, 1.0, expiration));
+ AlternativeServiceInfo(alternative_service1, expiration));
http_server_properties_.SetAlternativeServices(
host_port_pair_, alternative_service_info_vector);
@@ -2133,14 +2713,14 @@ TEST_P(QuicStreamFactoryTest, RacingConnections) {
QuicServerId server_id(host_port_pair_, privacy_mode_);
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
EXPECT_EQ(2u, QuicStreamFactoryPeer::GetNumberOfActiveJobs(factory_.get(),
server_id));
runner_->RunNextTask();
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -2168,14 +2748,14 @@ TEST_P(QuicStreamFactoryTest, EnableNotLoadFromDiskCache) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
// If we are waiting for disk cache, we would have posted a task. Verify that
// the CancelWaitForDataReady task hasn't been posted.
ASSERT_EQ(0u, runner_->GetPostedTasks().size());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -2226,8 +2806,8 @@ TEST_P(QuicStreamFactoryTest, BadPacketLoss) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
QuicChromiumClientSession* session =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
@@ -2264,8 +2844,8 @@ TEST_P(QuicStreamFactoryTest, BadPacketLoss) {
TestCompletionCallback callback2;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
- net_log_, callback2.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback2.callback()));
QuicChromiumClientSession* session2 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
@@ -2296,7 +2876,7 @@ TEST_P(QuicStreamFactoryTest, BadPacketLoss) {
TestCompletionCallback callback3;
QuicStreamRequest request3(factory_.get());
EXPECT_EQ(OK, request3.Request(server3, privacy_mode_,
- /*cert_verify_flags=*/0, server3.host(), "GET",
+ /*cert_verify_flags=*/0, url3_, "GET",
net_log_, callback3.callback()));
QuicChromiumClientSession* session3 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server3);
@@ -2305,7 +2885,7 @@ TEST_P(QuicStreamFactoryTest, BadPacketLoss) {
TestCompletionCallback callback4;
QuicStreamRequest request4(factory_.get());
EXPECT_EQ(OK, request4.Request(server4, privacy_mode_,
- /*cert_verify_flags=*/0, server4.host(), "GET",
+ /*cert_verify_flags=*/0, url4_, "GET",
net_log_, callback4.callback()));
QuicChromiumClientSession* session4 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server4);
@@ -2336,13 +2916,13 @@ TEST_P(QuicStreamFactoryTest, BadPacketLoss) {
QuicStreamFactoryPeer::HasActiveSession(factory_.get(), server4));
EXPECT_FALSE(HasActiveSession(server4));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
- scoped_ptr<QuicHttpStream> stream3 = request3.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream3 = request3.CreateStream();
EXPECT_TRUE(stream3.get());
- scoped_ptr<QuicHttpStream> stream4 = request4.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream4 = request4.CreateStream();
EXPECT_TRUE(stream4.get());
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -2386,14 +2966,15 @@ TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfTwo) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
QuicChromiumClientSession* session =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
DVLOG(1) << "Created 1st session. Now trigger public reset post handshake";
- session->connection()->CloseConnection(QUIC_PUBLIC_RESET, true);
+ session->connection()->CloseConnection(QUIC_PUBLIC_RESET, "test",
+ ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop;
@@ -2409,12 +2990,13 @@ TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfTwo) {
TestCompletionCallback callback2;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback2.callback()));
QuicChromiumClientSession* session2 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
- session2->connection()->CloseConnection(QUIC_PUBLIC_RESET, true);
+ session2->connection()->CloseConnection(
+ QUIC_PUBLIC_RESET, "test", ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop2;
@@ -2427,10 +3009,10 @@ TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfTwo) {
QuicChromiumClientSession::QUIC_DISABLED_PUBLIC_RESET_POST_HANDSHAKE,
factory_->QuicDisabledReason(host_port_pair_.port()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
- EXPECT_TRUE(stream.get());
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
- EXPECT_TRUE(stream2.get());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_FALSE(stream.get()); // Session is already closed.
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
+ EXPECT_FALSE(stream2.get()); // Session is already closed.
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
EXPECT_TRUE(socket_data2.AllReadDataConsumed());
@@ -2469,13 +3051,13 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfTwo) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
QuicChromiumClientSession* session =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
HttpRequestInfo request_info;
EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
@@ -2483,7 +3065,8 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfTwo) {
DVLOG(1)
<< "Created 1st session and initialized a stream. Now trigger timeout";
- session->connection()->CloseConnection(QUIC_CONNECTION_TIMED_OUT, false);
+ session->connection()->CloseConnection(QUIC_NETWORK_IDLE_TIMEOUT, "test",
+ ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop;
@@ -2499,17 +3082,18 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfTwo) {
TestCompletionCallback callback2;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback2.callback()));
QuicChromiumClientSession* session2 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
EXPECT_TRUE(stream2.get());
EXPECT_EQ(OK, stream2->InitializeStream(&request_info, DEFAULT_PRIORITY,
net_log_, CompletionCallback()));
- session2->connection()->CloseConnection(QUIC_CONNECTION_TIMED_OUT, false);
+ session2->connection()->CloseConnection(
+ QUIC_NETWORK_IDLE_TIMEOUT, "test", ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop2;
@@ -2521,6 +3105,13 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfTwo) {
EXPECT_EQ(QuicChromiumClientSession::QUIC_DISABLED_TIMEOUT_WITH_OPEN_STREAMS,
factory_->QuicDisabledReason(host_port_pair_.port()));
+ // Verify that QUIC is un-disabled after a TCP job fails.
+ factory_->OnTcpJobCompleted(/*succeeded=*/false);
+ EXPECT_EQ(
+ 0, QuicStreamFactoryPeer::GetNumTimeoutsWithOpenStreams(factory_.get()));
+ EXPECT_FALSE(QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(),
+ host_port_pair_.port()));
+
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
EXPECT_TRUE(socket_data2.AllReadDataConsumed());
@@ -2565,14 +3156,15 @@ TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfThree) {
// Test first and third out of three public reset post handshakes.
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
QuicChromiumClientSession* session =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
DVLOG(1) << "Created 1st session. Now trigger public reset post handshake";
- session->connection()->CloseConnection(QUIC_PUBLIC_RESET, true);
+ session->connection()->CloseConnection(QUIC_PUBLIC_RESET, "test",
+ ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop;
@@ -2587,12 +3179,13 @@ TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfThree) {
TestCompletionCallback callback2;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback2.callback()));
QuicChromiumClientSession* session2 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
- session2->connection()->CloseConnection(QUIC_NO_ERROR, false);
+ session2->connection()->CloseConnection(
+ QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop2;
@@ -2607,12 +3200,13 @@ TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfThree) {
TestCompletionCallback callback3;
QuicStreamRequest request3(factory_.get());
EXPECT_EQ(OK, request3.Request(server3, privacy_mode_,
- /*cert_verify_flags=*/0, server3.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback3.callback()));
QuicChromiumClientSession* session3 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server3);
- session3->connection()->CloseConnection(QUIC_PUBLIC_RESET, true);
+ session3->connection()->CloseConnection(
+ QUIC_PUBLIC_RESET, "test", ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop3;
@@ -2625,12 +3219,12 @@ TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfThree) {
QuicChromiumClientSession::QUIC_DISABLED_PUBLIC_RESET_POST_HANDSHAKE,
factory_->QuicDisabledReason(host_port_pair_.port()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
- EXPECT_TRUE(stream.get());
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
- EXPECT_TRUE(stream2.get());
- scoped_ptr<QuicHttpStream> stream3 = request3.ReleaseStream();
- EXPECT_TRUE(stream3.get());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_FALSE(stream.get()); // Session is already closed.
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
+ EXPECT_FALSE(stream2.get()); // Session is already closed.
+ scoped_ptr<QuicHttpStream> stream3 = request3.CreateStream();
+ EXPECT_FALSE(stream3.get()); // Session is already closed.
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -2680,13 +3274,13 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfThree) {
// Test first and third out of three timeouts with open streams.
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
QuicChromiumClientSession* session =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
HttpRequestInfo request_info;
EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
@@ -2694,7 +3288,8 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfThree) {
DVLOG(1)
<< "Created 1st session and initialized a stream. Now trigger timeout";
- session->connection()->CloseConnection(QUIC_CONNECTION_TIMED_OUT, false);
+ session->connection()->CloseConnection(QUIC_NETWORK_IDLE_TIMEOUT, "test",
+ ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop;
@@ -2710,12 +3305,13 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfThree) {
TestCompletionCallback callback2;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback2.callback()));
QuicChromiumClientSession* session2 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
- session2->connection()->CloseConnection(QUIC_NO_ERROR, true);
+ session2->connection()->CloseConnection(
+ QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop2;
@@ -2731,16 +3327,17 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfThree) {
TestCompletionCallback callback3;
QuicStreamRequest request3(factory_.get());
EXPECT_EQ(OK, request3.Request(server3, privacy_mode_,
- /*cert_verify_flags=*/0, server3.host(), "GET",
+ /*cert_verify_flags=*/0, url3_, "GET",
net_log_, callback3.callback()));
QuicChromiumClientSession* session3 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server3);
- scoped_ptr<QuicHttpStream> stream3 = request3.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream3 = request3.CreateStream();
EXPECT_TRUE(stream3.get());
EXPECT_EQ(OK, stream3->InitializeStream(&request_info, DEFAULT_PRIORITY,
net_log_, CompletionCallback()));
- session3->connection()->CloseConnection(QUIC_CONNECTION_TIMED_OUT, false);
+ session3->connection()->CloseConnection(
+ QUIC_NETWORK_IDLE_TIMEOUT, "test", ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop3;
@@ -2752,8 +3349,16 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfThree) {
EXPECT_EQ(QuicChromiumClientSession::QUIC_DISABLED_TIMEOUT_WITH_OPEN_STREAMS,
factory_->QuicDisabledReason(host_port_pair_.port()));
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
- EXPECT_TRUE(stream2.get());
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
+ EXPECT_FALSE(stream2.get()); // Session is already closed.
+
+ // Verify that QUIC is un-disabled after a network change.
+ factory_->OnIPAddressChanged();
+ EXPECT_FALSE(QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(),
+ host_port_pair_.port()));
+ EXPECT_EQ(
+ 0, QuicStreamFactoryPeer::GetNumTimeoutsWithOpenStreams(factory_.get()));
+
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
EXPECT_TRUE(socket_data2.AllReadDataConsumed());
@@ -2762,6 +3367,76 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfThree) {
EXPECT_TRUE(socket_data3.AllWriteDataConsumed());
}
+TEST_P(QuicStreamFactoryTest, DisableQuicWhenTimeoutsWithOpenStreams) {
+ disable_disk_cache_ = true;
+ disable_quic_on_timeout_with_open_streams_ = true;
+ Initialize();
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+ QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), runner_.get());
+
+ EXPECT_FALSE(QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(),
+ host_port_pair_.port()));
+ EXPECT_EQ(0, QuicStreamFactoryPeer::GetNumberOfLossyConnections(
+ factory_.get(), host_port_pair_.port()));
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ SequencedSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ crypto_client_stream_factory_.set_handshake_mode(
+ MockCryptoClientStream::CONFIRM_HANDSHAKE);
+ host_resolver_.set_synchronous_mode(true);
+ host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
+ "192.168.0.1", "");
+
+ // Test first timeouts with open streams will disable QUIC.
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+
+ QuicChromiumClientSession* session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_TRUE(stream.get());
+ HttpRequestInfo request_info;
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
+ net_log_, CompletionCallback()));
+
+ DVLOG(1)
+ << "Created 1st session and initialized a stream. Now trigger timeout."
+ << "Will disable QUIC.";
+ session->connection()->CloseConnection(QUIC_NETWORK_IDLE_TIMEOUT, "test",
+ ConnectionCloseBehavior::SILENT_CLOSE);
+ // Need to spin the loop now to ensure that
+ // QuicStreamFactory::OnSessionClosed() runs.
+ base::RunLoop run_loop;
+ run_loop.RunUntilIdle();
+
+ EXPECT_EQ(
+ 1, QuicStreamFactoryPeer::GetNumTimeoutsWithOpenStreams(factory_.get()));
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(),
+ host_port_pair_.port()));
+
+ EXPECT_EQ(QuicChromiumClientSession::QUIC_DISABLED_TIMEOUT_WITH_OPEN_STREAMS,
+ factory_->QuicDisabledReason(host_port_pair_.port()));
+
+ // Verify that QUIC is fully disabled after a TCP job succeeds.
+ factory_->OnTcpJobCompleted(/*succeeded=*/true);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(),
+ host_port_pair_.port()));
+
+ // Verify that QUIC stays disabled after a TCP job succeeds.
+ factory_->OnTcpJobCompleted(/*succeeded=*/false);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(),
+ host_port_pair_.port()));
+
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfFour) {
disable_disk_cache_ = true;
threshold_public_resets_post_handshake_ = 2;
@@ -2807,14 +3482,15 @@ TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfFour) {
// Test first and fourth out of four public reset post handshakes.
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
QuicChromiumClientSession* session =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
DVLOG(1) << "Created 1st session. Now trigger public reset post handshake";
- session->connection()->CloseConnection(QUIC_PUBLIC_RESET, true);
+ session->connection()->CloseConnection(QUIC_PUBLIC_RESET, "test",
+ ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop;
@@ -2829,12 +3505,13 @@ TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfFour) {
TestCompletionCallback callback2;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback2.callback()));
QuicChromiumClientSession* session2 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
- session2->connection()->CloseConnection(QUIC_NO_ERROR, false);
+ session2->connection()->CloseConnection(
+ QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop2;
@@ -2847,12 +3524,13 @@ TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfFour) {
TestCompletionCallback callback3;
QuicStreamRequest request3(factory_.get());
EXPECT_EQ(OK, request3.Request(server3, privacy_mode_,
- /*cert_verify_flags=*/0, server3.host(), "GET",
+ /*cert_verify_flags=*/0, url3_, "GET",
net_log_, callback3.callback()));
QuicChromiumClientSession* session3 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server3);
- session3->connection()->CloseConnection(QUIC_NO_ERROR, false);
+ session3->connection()->CloseConnection(
+ QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop3;
@@ -2867,12 +3545,13 @@ TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfFour) {
TestCompletionCallback callback4;
QuicStreamRequest request4(factory_.get());
EXPECT_EQ(OK, request4.Request(server4, privacy_mode_,
- /*cert_verify_flags=*/0, server4.host(), "GET",
+ /*cert_verify_flags=*/0, url4_, "GET",
net_log_, callback4.callback()));
QuicChromiumClientSession* session4 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server4);
- session4->connection()->CloseConnection(QUIC_PUBLIC_RESET, true);
+ session4->connection()->CloseConnection(
+ QUIC_PUBLIC_RESET, "test", ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop4;
@@ -2882,14 +3561,14 @@ TEST_P(QuicStreamFactoryTest, PublicResetPostHandshakeTwoOfFour) {
EXPECT_FALSE(QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(),
host_port_pair_.port()));
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
- EXPECT_TRUE(stream.get());
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
- EXPECT_TRUE(stream2.get());
- scoped_ptr<QuicHttpStream> stream3 = request3.ReleaseStream();
- EXPECT_TRUE(stream3.get());
- scoped_ptr<QuicHttpStream> stream4 = request4.ReleaseStream();
- EXPECT_TRUE(stream4.get());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_FALSE(stream.get()); // Session is already closed.
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
+ EXPECT_FALSE(stream2.get()); // Session is already closed.
+ scoped_ptr<QuicHttpStream> stream3 = request3.CreateStream();
+ EXPECT_FALSE(stream3.get()); // Session is already closed.
+ scoped_ptr<QuicHttpStream> stream4 = request4.CreateStream();
+ EXPECT_FALSE(stream4.get()); // Session is already closed.
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -2947,13 +3626,13 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfFour) {
// Test first and fourth out of three timeouts with open streams.
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
QuicChromiumClientSession* session =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
HttpRequestInfo request_info;
EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
@@ -2961,7 +3640,8 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfFour) {
DVLOG(1)
<< "Created 1st session and initialized a stream. Now trigger timeout";
- session->connection()->CloseConnection(QUIC_CONNECTION_TIMED_OUT, false);
+ session->connection()->CloseConnection(QUIC_NETWORK_IDLE_TIMEOUT, "test",
+ ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop;
@@ -2976,12 +3656,13 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfFour) {
TestCompletionCallback callback2;
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK, request2.Request(server2, privacy_mode_,
- /*cert_verify_flags=*/0, server2.host(), "GET",
+ /*cert_verify_flags=*/0, url2_, "GET",
net_log_, callback2.callback()));
QuicChromiumClientSession* session2 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server2);
- session2->connection()->CloseConnection(QUIC_NO_ERROR, true);
+ session2->connection()->CloseConnection(
+ QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop2;
@@ -2994,12 +3675,13 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfFour) {
TestCompletionCallback callback3;
QuicStreamRequest request3(factory_.get());
EXPECT_EQ(OK, request3.Request(server3, privacy_mode_,
- /*cert_verify_flags=*/0, server3.host(), "GET",
+ /*cert_verify_flags=*/0, url3_, "GET",
net_log_, callback3.callback()));
QuicChromiumClientSession* session3 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server3);
- session3->connection()->CloseConnection(QUIC_NO_ERROR, true);
+ session3->connection()->CloseConnection(
+ QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop3;
@@ -3015,16 +3697,17 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfFour) {
TestCompletionCallback callback4;
QuicStreamRequest request4(factory_.get());
EXPECT_EQ(OK, request4.Request(server4, privacy_mode_,
- /*cert_verify_flags=*/0, server4.host(), "GET",
+ /*cert_verify_flags=*/0, url4_, "GET",
net_log_, callback4.callback()));
QuicChromiumClientSession* session4 =
QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server4);
- scoped_ptr<QuicHttpStream> stream4 = request4.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream4 = request4.CreateStream();
EXPECT_TRUE(stream4.get());
EXPECT_EQ(OK, stream4->InitializeStream(&request_info, DEFAULT_PRIORITY,
net_log_, CompletionCallback()));
- session4->connection()->CloseConnection(QUIC_CONNECTION_TIMED_OUT, false);
+ session4->connection()->CloseConnection(
+ QUIC_NETWORK_IDLE_TIMEOUT, "test", ConnectionCloseBehavior::SILENT_CLOSE);
// Need to spin the loop now to ensure that
// QuicStreamFactory::OnSessionClosed() runs.
base::RunLoop run_loop4;
@@ -3034,10 +3717,11 @@ TEST_P(QuicStreamFactoryTest, TimeoutsWithOpenStreamsTwoOfFour) {
EXPECT_FALSE(QuicStreamFactoryPeer::IsQuicDisabled(factory_.get(),
host_port_pair_.port()));
- scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
- EXPECT_TRUE(stream2.get());
- scoped_ptr<QuicHttpStream> stream3 = request3.ReleaseStream();
- EXPECT_TRUE(stream3.get());
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
+ EXPECT_FALSE(stream2.get()); // Session is already closed.
+ scoped_ptr<QuicHttpStream> stream3 = request3.CreateStream();
+ EXPECT_FALSE(stream3.get()); // Session is already closed.
+
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
EXPECT_TRUE(socket_data2.AllReadDataConsumed());
@@ -3071,8 +3755,8 @@ TEST_P(QuicStreamFactoryTest, EnableDelayTcpRace) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "POST", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "POST", net_log_,
+ callback_.callback()));
// If we don't delay TCP connection, then time delay should be 0.
EXPECT_FALSE(factory_->delay_tcp_race());
@@ -3091,7 +3775,7 @@ TEST_P(QuicStreamFactoryTest, EnableDelayTcpRace) {
EXPECT_EQ(OK, callback_.WaitForResult());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -3113,10 +3797,20 @@ TEST_P(QuicStreamFactoryTest, MaybeInitialize) {
AlternativeServiceInfoVector alternative_service_info_vector;
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
- AlternativeServiceInfo(alternative_service1, 1.0, expiration));
+ AlternativeServiceInfo(alternative_service1, expiration));
http_server_properties_.SetAlternativeServices(
host_port_pair_, alternative_service_info_vector);
+
+ HostPortPair host_port_pair2(kServer2HostName, kDefaultServerPort);
+ const AlternativeService alternative_service2(QUIC, host_port_pair2.host(),
+ host_port_pair2.port());
+ AlternativeServiceInfoVector alternative_service_info_vector2;
+ alternative_service_info_vector2.push_back(
+ AlternativeServiceInfo(alternative_service2, expiration));
+ http_server_properties_.SetAlternativeServices(
+ host_port_pair2, alternative_service_info_vector2);
+
http_server_properties_.SetMaxServerConfigsStoredInProperties(
kMaxQuicServersToPersist);
@@ -3149,19 +3843,73 @@ TEST_P(QuicStreamFactoryTest, MaybeInitialize) {
// Create temporary strings becasue Persist() clears string data in |state|.
string server_config(reinterpret_cast<const char*>(&scfg), sizeof(scfg));
string source_address_token("test_source_address_token");
+ string cert_sct("test_cert_sct");
+ string chlo_hash("test_chlo_hash");
string signature("test_signature");
string test_cert("test_cert");
vector<string> certs;
certs.push_back(test_cert);
state->server_config = server_config;
state->source_address_token = source_address_token;
+ state->cert_sct = cert_sct;
+ state->chlo_hash = chlo_hash;
state->server_config_sig = signature;
state->certs = certs;
quic_server_info->Persist();
+ QuicServerId quic_server_id2(kServer2HostName, 80, PRIVACY_MODE_DISABLED);
+ scoped_ptr<QuicServerInfo> quic_server_info2(
+ quic_server_info_factory->GetForServer(quic_server_id2));
+
+ // Update quic_server_info2's server_config and persist it.
+ QuicServerInfo::State* state2 = quic_server_info2->mutable_state();
+
+ // Minimum SCFG that passes config validation checks.
+ const char scfg2[] = {// SCFG
+ 0x53, 0x43, 0x46, 0x47,
+ // num entries
+ 0x01, 0x00,
+ // padding
+ 0x00, 0x00,
+ // EXPY
+ 0x45, 0x58, 0x50, 0x59,
+ // EXPY end offset
+ 0x08, 0x00, 0x00, 0x00,
+ // Value
+ '8', '7', '3', '4', '5', '6', '2', '1'};
+
+ // Create temporary strings becasue Persist() clears string data in |state2|.
+ string server_config2(reinterpret_cast<const char*>(&scfg2), sizeof(scfg2));
+ string source_address_token2("test_source_address_token2");
+ string cert_sct2("test_cert_sct2");
+ string chlo_hash2("test_chlo_hash2");
+ string signature2("test_signature2");
+ string test_cert2("test_cert2");
+ vector<string> certs2;
+ certs2.push_back(test_cert2);
+ state2->server_config = server_config2;
+ state2->source_address_token = source_address_token2;
+ state2->cert_sct = cert_sct2;
+ state2->chlo_hash = chlo_hash2;
+ state2->server_config_sig = signature2;
+ state2->certs = certs2;
+
+ quic_server_info2->Persist();
+
QuicStreamFactoryPeer::MaybeInitialize(factory_.get());
EXPECT_TRUE(QuicStreamFactoryPeer::HasInitializedData(factory_.get()));
+
+ // Verify the MRU order is maintained.
+ const QuicServerInfoMap& quic_server_info_map =
+ http_server_properties_.quic_server_info_map();
+ EXPECT_EQ(2u, quic_server_info_map.size());
+ QuicServerInfoMap::const_iterator quic_server_info_map_it =
+ quic_server_info_map.begin();
+ EXPECT_EQ(quic_server_info_map_it->first, quic_server_id2);
+ ++quic_server_info_map_it;
+ EXPECT_EQ(quic_server_info_map_it->first, quic_server_id);
+
EXPECT_TRUE(QuicStreamFactoryPeer::SupportsQuicAtStartUp(factory_.get(),
host_port_pair_));
EXPECT_FALSE(QuicStreamFactoryPeer::CryptoConfigCacheIsEmpty(factory_.get(),
@@ -3174,9 +3922,27 @@ TEST_P(QuicStreamFactoryTest, MaybeInitialize) {
EXPECT_TRUE(cached->GetServerConfig());
EXPECT_EQ(server_config, cached->server_config());
EXPECT_EQ(source_address_token, cached->source_address_token());
+ EXPECT_EQ(cert_sct, cached->cert_sct());
+ EXPECT_EQ(chlo_hash, cached->chlo_hash());
EXPECT_EQ(signature, cached->signature());
ASSERT_EQ(1U, cached->certs().size());
EXPECT_EQ(test_cert, cached->certs()[0]);
+
+ EXPECT_TRUE(QuicStreamFactoryPeer::SupportsQuicAtStartUp(factory_.get(),
+ host_port_pair2));
+ EXPECT_FALSE(QuicStreamFactoryPeer::CryptoConfigCacheIsEmpty(
+ factory_.get(), quic_server_id2));
+ QuicCryptoClientConfig::CachedState* cached2 =
+ crypto_config->LookupOrCreate(quic_server_id2);
+ EXPECT_FALSE(cached2->server_config().empty());
+ EXPECT_TRUE(cached2->GetServerConfig());
+ EXPECT_EQ(server_config2, cached2->server_config());
+ EXPECT_EQ(source_address_token2, cached2->source_address_token());
+ EXPECT_EQ(cert_sct2, cached2->cert_sct());
+ EXPECT_EQ(chlo_hash2, cached2->chlo_hash());
+ EXPECT_EQ(signature2, cached2->signature());
+ ASSERT_EQ(1U, cached->certs().size());
+ EXPECT_EQ(test_cert2, cached2->certs()[0]);
}
TEST_P(QuicStreamFactoryTest, QuicDoingZeroRTT) {
@@ -3215,27 +3981,29 @@ TEST_P(QuicStreamFactoryTest, YieldAfterPackets) {
host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
"192.168.0.1", "");
- // Set up the TaskObserver to verify QuicPacketReader::StartReading posts a
- // task.
+ // Set up the TaskObserver to verify QuicChromiumPacketReader::StartReading
+ // posts a task.
// TODO(rtenneti): Change SpdySessionTestTaskObserver to NetTestTaskObserver??
- SpdySessionTestTaskObserver observer("quic_packet_reader.cc", "StartReading");
+ SpdySessionTestTaskObserver observer("quic_chromium_packet_reader.cc",
+ "StartReading");
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
- // Call run_loop so that QuicPacketReader::OnReadComplete() gets called.
+ // Call run_loop so that QuicChromiumPacketReader::OnReadComplete() gets
+ // called.
base::RunLoop run_loop;
run_loop.RunUntilIdle();
// Verify task that the observer's executed_count is 1, which indicates
- // QuicPacketReader::StartReading() has posted only one task and yielded the
- // read.
+ // QuicChromiumPacketReader::StartReading() has posted only one task and
+ // yielded the read.
EXPECT_EQ(1u, observer.executed_count());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
- EXPECT_TRUE(stream.get());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_FALSE(stream.get()); // Session is already closed.
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
@@ -3262,30 +4030,136 @@ TEST_P(QuicStreamFactoryTest, YieldAfterDuration) {
host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
"192.168.0.1", "");
- // Set up the TaskObserver to verify QuicPacketReader::StartReading posts a
- // task.
+ // Set up the TaskObserver to verify QuicChromiumPacketReader::StartReading
+ // posts a task.
// TODO(rtenneti): Change SpdySessionTestTaskObserver to NetTestTaskObserver??
- SpdySessionTestTaskObserver observer("quic_packet_reader.cc", "StartReading");
+ SpdySessionTestTaskObserver observer("quic_chromium_packet_reader.cc",
+ "StartReading");
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_,
- /*cert_verify_flags=*/0, host_port_pair_.host(),
- "GET", net_log_, callback_.callback()));
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
- // Call run_loop so that QuicPacketReader::OnReadComplete() gets called.
+ // Call run_loop so that QuicChromiumPacketReader::OnReadComplete() gets
+ // called.
base::RunLoop run_loop;
run_loop.RunUntilIdle();
// Verify task that the observer's executed_count is 1, which indicates
- // QuicPacketReader::StartReading() has posted only one task and yielded the
- // read.
+ // QuicChromiumPacketReader::StartReading() has posted only one task and
+ // yielded the read.
EXPECT_EQ(1u, observer.executed_count());
- scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
- EXPECT_TRUE(stream.get());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_FALSE(stream.get()); // Session is already closed.
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
+TEST_P(QuicStreamFactoryTest, ServerPushSessionAffinity) {
+ Initialize();
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ SequencedSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_TRUE(stream.get());
+
+ EXPECT_EQ(0, QuicStreamFactoryPeer::GetNumPushStreamsCreated(factory_.get()));
+
+ std::string url = "https://www.example.org/";
+
+ QuicChromiumClientSession* session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+
+ QuicClientPromisedInfo promised(session, kServerDataStreamId1, url);
+ (*QuicStreamFactoryPeer::GetPushPromiseIndex(factory_.get())
+ ->promised_by_url())[url] = &promised;
+
+ QuicStreamRequest request2(factory_.get());
+ EXPECT_EQ(OK, request2.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, GURL(url), "GET",
+ net_log_, callback_.callback()));
+
+ EXPECT_EQ(1, QuicStreamFactoryPeer::GetNumPushStreamsCreated(factory_.get()));
+}
+
+TEST_P(QuicStreamFactoryTest, ServerPushPrivacyModeMismatch) {
+ Initialize();
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+
+ scoped_ptr<QuicEncryptedPacket> client_rst(maker_.MakeRstPacket(
+ 1, true, kServerDataStreamId1, QUIC_STREAM_CANCELLED));
+ MockWrite writes[] = {
+ MockWrite(SYNCHRONOUS, client_rst->data(), client_rst->length(), 1),
+ };
+
+ SequencedSocketData socket_data1(reads, arraysize(reads), writes,
+ arraysize(writes));
+ SequencedSocketData socket_data2(reads, arraysize(reads), nullptr, 0);
+
+ socket_factory_.AddSocketDataProvider(&socket_data1);
+ socket_factory_.AddSocketDataProvider(&socket_data2);
+
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request.Request(host_port_pair_, privacy_mode_,
+ /*cert_verify_flags=*/0, url_, "GET", net_log_,
+ callback_.callback()));
+
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.CreateStream();
+ EXPECT_TRUE(stream.get());
+
+ EXPECT_EQ(0, QuicStreamFactoryPeer::GetNumPushStreamsCreated(factory_.get()));
+
+ std::string url = "https://www.example.org/";
+ QuicChromiumClientSession* session =
+ QuicStreamFactoryPeer::GetActiveSession(factory_.get(), host_port_pair_);
+
+ QuicClientPromisedInfo promised(session, kServerDataStreamId1, url);
+
+ QuicClientPushPromiseIndex* index =
+ QuicStreamFactoryPeer::GetPushPromiseIndex(factory_.get());
+
+ (*index->promised_by_url())[url] = &promised;
+ EXPECT_EQ(index->GetPromised(url), &promised);
+
+ // Doing the request should not use the push stream, but rather
+ // cancel it because the privacy modes do not match.
+ QuicStreamRequest request2(factory_.get());
+ EXPECT_EQ(ERR_IO_PENDING,
+ request2.Request(host_port_pair_, PRIVACY_MODE_ENABLED,
+ /*cert_verify_flags=*/0, GURL(url), "GET",
+ net_log_, callback_.callback()));
+
+ EXPECT_EQ(0, QuicStreamFactoryPeer::GetNumPushStreamsCreated(factory_.get()));
+ EXPECT_EQ(index->GetPromised(url), nullptr);
+
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream2 = request2.CreateStream();
+ EXPECT_TRUE(stream2.get());
+
+ EXPECT_TRUE(socket_data1.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
+ EXPECT_TRUE(socket_data2.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_stream_sequencer.cc b/chromium/net/quic/quic_stream_sequencer.cc
index 1c4f5806f7b..b63618d1ffa 100644
--- a/chromium/net/quic/quic_stream_sequencer.cc
+++ b/chromium/net/quic/quic_stream_sequencer.cc
@@ -6,16 +6,17 @@
#include <algorithm>
#include <limits>
+#include <string>
#include <utility>
#include "base/logging.h"
#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_clock.h"
#include "net/quic/quic_flags.h"
-#include "net/quic/quic_frame_list.h"
#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_stream_sequencer_buffer.h"
+#include "net/quic/quic_utils.h"
#include "net/quic/reliable_quic_stream.h"
-#include "net/quic/stream_sequencer_buffer.h"
using std::min;
using std::numeric_limits;
@@ -26,20 +27,14 @@ namespace net {
QuicStreamSequencer::QuicStreamSequencer(ReliableQuicStream* quic_stream,
const QuicClock* clock)
: stream_(quic_stream),
+ buffered_frames_(kStreamReceiveWindowLimit),
close_offset_(numeric_limits<QuicStreamOffset>::max()),
blocked_(false),
num_frames_received_(0),
num_duplicate_frames_received_(0),
num_early_frames_received_(0),
clock_(clock),
- ignore_read_data_(false) {
- if (FLAGS_quic_use_stream_sequencer_buffer) {
- buffered_frames_.reset(
- new StreamSequencerBuffer(kStreamReceiveWindowLimit));
- } else {
- buffered_frames_.reset(new QuicFrameList());
- }
-}
+ ignore_read_data_(false) {}
QuicStreamSequencer::~QuicStreamSequencer() {}
@@ -47,9 +42,12 @@ void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
++num_frames_received_;
const QuicStreamOffset byte_offset = frame.offset;
const size_t data_len = frame.frame_length;
- if (data_len == 0 && !frame.fin) {
+ bool consolidate_errors = FLAGS_quic_consolidate_onstreamframe_errors;
+ if (!consolidate_errors && data_len == 0 && !frame.fin) {
// Stream frames must have data or a fin flag.
- stream_->CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME,
+ LOG(WARNING) << "QUIC_INVALID_STREAM_FRAM: Empty stream frame "
+ "without FIN set.";
+ stream_->CloseConnectionWithDetails(QUIC_EMPTY_STREAM_FRAME_NO_FIN,
"Empty stream frame without FIN set.");
return;
}
@@ -61,22 +59,34 @@ void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
}
}
size_t bytes_written;
- QuicErrorCode result = buffered_frames_->OnStreamData(
+ string error_details;
+ QuicErrorCode result = buffered_frames_.OnStreamData(
byte_offset, StringPiece(frame.frame_buffer, frame.frame_length),
- clock_->ApproximateNow(), &bytes_written);
-
- if (result == QUIC_INVALID_STREAM_DATA) {
- stream_->CloseConnectionWithDetails(
- QUIC_INVALID_STREAM_FRAME, "Stream frame overlaps with buffered data.");
- return;
+ clock_->ApproximateNow(), &bytes_written, &error_details);
+ if (!consolidate_errors) {
+ if (result == QUIC_OVERLAPPING_STREAM_DATA) {
+ LOG(WARNING) << "QUIC_INVALID_STREAM_FRAME: Stream frame "
+ "overlaps with buffered data.";
+ stream_->CloseConnectionWithDetails(
+ QUIC_EMPTY_STREAM_FRAME_NO_FIN,
+ "Stream frame overlaps with buffered data.");
+ return;
+ }
+ } else {
+ if (result != QUIC_NO_ERROR) {
+ LOG(WARNING) << QuicUtils::ErrorToString(result) << ": " << error_details;
+ stream_->CloseConnectionWithDetails(result, error_details);
+ return;
+ }
}
- if (result == QUIC_NO_ERROR && bytes_written == 0) {
+
+ if ((consolidate_errors || result == QUIC_NO_ERROR) && bytes_written == 0) {
++num_duplicate_frames_received_;
// Silently ignore duplicates.
return;
}
- if (byte_offset > buffered_frames_->BytesConsumed()) {
+ if (byte_offset > buffered_frames_.BytesConsumed()) {
++num_early_frames_received_;
}
@@ -84,7 +94,7 @@ void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
return;
}
- if (byte_offset == buffered_frames_->BytesConsumed()) {
+ if (byte_offset == buffered_frames_.BytesConsumed()) {
if (ignore_read_data_) {
FlushBufferedFrames();
} else {
@@ -113,7 +123,7 @@ bool QuicStreamSequencer::MaybeCloseStream() {
}
DVLOG(1) << "Passing up termination, as we've processed "
- << buffered_frames_->BytesConsumed() << " of " << close_offset_
+ << 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
@@ -125,39 +135,39 @@ bool QuicStreamSequencer::MaybeCloseStream() {
} else {
stream_->OnDataAvailable();
}
- buffered_frames_->Clear();
+ buffered_frames_.Clear();
return true;
}
int QuicStreamSequencer::GetReadableRegions(iovec* iov, size_t iov_len) const {
DCHECK(!blocked_);
- return buffered_frames_->GetReadableRegions(iov, iov_len);
+ return buffered_frames_.GetReadableRegions(iov, iov_len);
}
bool QuicStreamSequencer::GetReadableRegion(iovec* iov,
QuicTime* timestamp) const {
DCHECK(!blocked_);
- return buffered_frames_->GetReadableRegion(iov, timestamp);
+ return buffered_frames_.GetReadableRegion(iov, timestamp);
}
int QuicStreamSequencer::Readv(const struct iovec* iov, size_t iov_len) {
DCHECK(!blocked_);
- size_t bytes_read = buffered_frames_->Readv(iov, iov_len);
+ size_t bytes_read = buffered_frames_.Readv(iov, iov_len);
stream_->AddBytesConsumed(bytes_read);
return static_cast<int>(bytes_read);
}
bool QuicStreamSequencer::HasBytesToRead() const {
- return buffered_frames_->HasBytesToRead();
+ return buffered_frames_.HasBytesToRead();
}
bool QuicStreamSequencer::IsClosed() const {
- return buffered_frames_->BytesConsumed() >= close_offset_;
+ return buffered_frames_.BytesConsumed() >= close_offset_;
}
void QuicStreamSequencer::MarkConsumed(size_t num_bytes_consumed) {
DCHECK(!blocked_);
- bool result = buffered_frames_->MarkConsumed(num_bytes_consumed);
+ bool result = buffered_frames_.MarkConsumed(num_bytes_consumed);
if (!result) {
QUIC_BUG << "Invalid argument to MarkConsumed."
<< " expect to consume: " << num_bytes_consumed
@@ -189,20 +199,20 @@ void QuicStreamSequencer::StopReading() {
void QuicStreamSequencer::FlushBufferedFrames() {
DCHECK(ignore_read_data_);
- size_t bytes_flushed = buffered_frames_->FlushBufferedFrames();
+ size_t bytes_flushed = buffered_frames_.FlushBufferedFrames();
DVLOG(1) << "Flushing buffered data at offset "
- << buffered_frames_->BytesConsumed() << " length " << bytes_flushed
+ << buffered_frames_.BytesConsumed() << " length " << bytes_flushed
<< " for stream " << stream_->id();
stream_->AddBytesConsumed(bytes_flushed);
MaybeCloseStream();
}
size_t QuicStreamSequencer::NumBytesBuffered() const {
- return buffered_frames_->BytesBuffered();
+ return buffered_frames_.BytesBuffered();
}
QuicStreamOffset QuicStreamSequencer::NumBytesConsumed() const {
- return buffered_frames_->BytesConsumed();
+ return buffered_frames_.BytesConsumed();
}
} // namespace net
diff --git a/chromium/net/quic/quic_stream_sequencer.h b/chromium/net/quic/quic_stream_sequencer.h
index 65d99baaf28..3f37a7ec35f 100644
--- a/chromium/net/quic/quic_stream_sequencer.h
+++ b/chromium/net/quic/quic_stream_sequencer.h
@@ -8,11 +8,10 @@
#include <stddef.h>
#include <map>
-#include <string>
#include "base/macros.h"
-#include "net/quic/quic_frame_list.h"
#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_stream_sequencer_buffer.h"
namespace net {
@@ -114,7 +113,7 @@ class NET_EXPORT_PRIVATE QuicStreamSequencer {
ReliableQuicStream* stream_;
// Stores received data in offset order.
- scoped_ptr<QuicStreamSequencerBufferInterface> buffered_frames_;
+ QuicStreamSequencerBuffer buffered_frames_;
// The offset, if any, we got a stream termination for. When this many bytes
// have been processed, the sequencer will be closed.
diff --git a/chromium/net/quic/stream_sequencer_buffer.cc b/chromium/net/quic/quic_stream_sequencer_buffer.cc
index 5b98452d03c..dabb2ce3709 100644
--- a/chromium/net/quic/stream_sequencer_buffer.cc
+++ b/chromium/net/quic/quic_stream_sequencer_buffer.cc
@@ -2,26 +2,38 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/stream_sequencer_buffer.h"
+#include "net/quic/quic_stream_sequencer_buffer.h"
#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
#include "net/quic/quic_bug_tracker.h"
using std::min;
+using std::string;
namespace net {
-StreamSequencerBuffer::Gap::Gap(QuicStreamOffset begin_offset,
- QuicStreamOffset end_offset)
+namespace {
+
+string RangeDebugString(QuicStreamOffset start, QuicStreamOffset end) {
+ return string("[") + base::IntToString(start) + ", " +
+ base::IntToString(end) + ") ";
+}
+
+} // namespace
+
+QuicStreamSequencerBuffer::Gap::Gap(QuicStreamOffset begin_offset,
+ QuicStreamOffset end_offset)
: begin_offset(begin_offset), end_offset(end_offset) {}
-StreamSequencerBuffer::FrameInfo::FrameInfo()
+QuicStreamSequencerBuffer::FrameInfo::FrameInfo()
: length(1), timestamp(QuicTime::Zero()) {}
-StreamSequencerBuffer::FrameInfo::FrameInfo(size_t length, QuicTime timestamp)
+QuicStreamSequencerBuffer::FrameInfo::FrameInfo(size_t length,
+ QuicTime timestamp)
: length(length), timestamp(timestamp) {}
-StreamSequencerBuffer::StreamSequencerBuffer(size_t max_capacity_bytes)
+QuicStreamSequencerBuffer::QuicStreamSequencerBuffer(size_t max_capacity_bytes)
: max_buffer_capacity_bytes_(max_capacity_bytes),
blocks_count_(
ceil(static_cast<double>(max_capacity_bytes) / kBlockSizeBytes)),
@@ -30,11 +42,11 @@ StreamSequencerBuffer::StreamSequencerBuffer(size_t max_capacity_bytes)
Clear();
}
-StreamSequencerBuffer::~StreamSequencerBuffer() {
+QuicStreamSequencerBuffer::~QuicStreamSequencerBuffer() {
Clear();
}
-void StreamSequencerBuffer::Clear() {
+void QuicStreamSequencerBuffer::Clear() {
for (size_t i = 0; i < blocks_count_; ++i) {
if (blocks_[i] != nullptr) {
RetireBlock(i);
@@ -49,24 +61,25 @@ void StreamSequencerBuffer::Clear() {
frame_arrival_time_map_.clear();
}
-void StreamSequencerBuffer::RetireBlock(size_t idx) {
+void QuicStreamSequencerBuffer::RetireBlock(size_t idx) {
DCHECK(blocks_[idx] != nullptr);
delete blocks_[idx];
blocks_[idx] = nullptr;
DVLOG(1) << "Retired block with index: " << idx;
}
-QuicErrorCode StreamSequencerBuffer::OnStreamData(
+QuicErrorCode QuicStreamSequencerBuffer::OnStreamData(
QuicStreamOffset starting_offset,
base::StringPiece data,
QuicTime timestamp,
- size_t* const bytes_buffered) {
+ size_t* const bytes_buffered,
+ std::string* error_details) {
*bytes_buffered = 0;
QuicStreamOffset offset = starting_offset;
size_t size = data.size();
if (size == 0) {
- QUIC_BUG << "Attempted to write 0 bytes of data.";
- return QUIC_INVALID_STREAM_FRAME;
+ *error_details = "Received empty stream frame without FIN.";
+ return QUIC_EMPTY_STREAM_FRAME_NO_FIN;
}
// Find the first gap not ending before |offset|. This gap maybe the gap to
@@ -90,15 +103,35 @@ QuicErrorCode StreamSequencerBuffer::OnStreamData(
if (offset < current_gap->begin_offset &&
offset + size > current_gap->begin_offset) {
// Beginning of new data overlaps data before current gap.
- return QUIC_INVALID_STREAM_DATA;
+ *error_details =
+ string("Beginning of received data overlaps with buffered data.\n") +
+ "New frame range " + RangeDebugString(offset, offset + size) +
+ "\n"
+ "Currently received frames: " +
+ ReceivedFramesDebugString() +
+ "\n"
+ "Current gaps: " +
+ GapsDebugString() + "\n";
+ return QUIC_OVERLAPPING_STREAM_DATA;
}
if (offset + size > current_gap->end_offset) {
// End of new data overlaps with data after current gap.
- return QUIC_INVALID_STREAM_DATA;
+ *error_details =
+ "End of received data overlaps with buffered data.\n"
+ "New frame range " +
+ RangeDebugString(offset, offset + size) +
+ "\n"
+ "Currently received frames: " +
+ ReceivedFramesDebugString() +
+ "\n"
+ "Current gaps: " +
+ GapsDebugString() + "\n";
+ return QUIC_OVERLAPPING_STREAM_DATA;
}
// Write beyond the current range this buffer is covering.
if (offset + size > total_bytes_read_ + max_buffer_capacity_bytes_) {
+ *error_details = "Received data beyond available range.";
return QUIC_INTERNAL_ERROR;
}
@@ -148,7 +181,7 @@ QuicErrorCode StreamSequencerBuffer::OnStreamData(
return QUIC_NO_ERROR;
}
-inline void StreamSequencerBuffer::UpdateGapList(
+inline void QuicStreamSequencerBuffer::UpdateGapList(
std::list<Gap>::iterator gap_with_new_data_written,
QuicStreamOffset start_offset,
size_t bytes_written) {
@@ -166,7 +199,7 @@ inline void StreamSequencerBuffer::UpdateGapList(
start_offset + bytes_written) {
// New data has been written into the middle of the buffer.
auto current = gap_with_new_data_written++;
- size_t current_end = current->end_offset;
+ QuicStreamOffset current_end = current->end_offset;
current->end_offset = start_offset;
gaps_.insert(gap_with_new_data_written,
Gap(start_offset + bytes_written, current_end));
@@ -178,7 +211,8 @@ inline void StreamSequencerBuffer::UpdateGapList(
}
}
-size_t StreamSequencerBuffer::Readv(const iovec* dest_iov, size_t dest_count) {
+size_t QuicStreamSequencerBuffer::Readv(const iovec* dest_iov,
+ size_t dest_count) {
size_t bytes_read = 0;
for (size_t i = 0; i < dest_count && ReadableBytes() > 0; ++i) {
char* dest = reinterpret_cast<char*>(dest_iov[i].iov_base);
@@ -215,8 +249,8 @@ size_t StreamSequencerBuffer::Readv(const iovec* dest_iov, size_t dest_count) {
return bytes_read;
}
-int StreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
- int iov_count) const {
+int QuicStreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
+ int iov_count) const {
DCHECK(iov != nullptr);
DCHECK_GT(iov_count, 0);
@@ -273,8 +307,8 @@ int StreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
return iov_used;
}
-bool StreamSequencerBuffer::GetReadableRegion(iovec* iov,
- QuicTime* timestamp) const {
+bool QuicStreamSequencerBuffer::GetReadableRegion(iovec* iov,
+ QuicTime* timestamp) const {
if (ReadableBytes() == 0) {
iov[0].iov_base = nullptr;
iov[0].iov_len = 0;
@@ -312,7 +346,7 @@ bool StreamSequencerBuffer::GetReadableRegion(iovec* iov,
return true;
}
-bool StreamSequencerBuffer::MarkConsumed(size_t bytes_used) {
+bool QuicStreamSequencerBuffer::MarkConsumed(size_t bytes_used) {
if (bytes_used > ReadableBytes()) {
return false;
}
@@ -338,46 +372,47 @@ bool StreamSequencerBuffer::MarkConsumed(size_t bytes_used) {
return true;
}
-size_t StreamSequencerBuffer::FlushBufferedFrames() {
+size_t QuicStreamSequencerBuffer::FlushBufferedFrames() {
size_t prev_total_bytes_read = total_bytes_read_;
total_bytes_read_ = gaps_.back().begin_offset;
Clear();
return total_bytes_read_ - prev_total_bytes_read;
}
-size_t StreamSequencerBuffer::ReadableBytes() const {
+size_t QuicStreamSequencerBuffer::ReadableBytes() const {
return gaps_.front().begin_offset - total_bytes_read_;
}
-bool StreamSequencerBuffer::HasBytesToRead() const {
+bool QuicStreamSequencerBuffer::HasBytesToRead() const {
return ReadableBytes() > 0;
}
-QuicStreamOffset StreamSequencerBuffer::BytesConsumed() const {
+QuicStreamOffset QuicStreamSequencerBuffer::BytesConsumed() const {
return total_bytes_read_;
}
-size_t StreamSequencerBuffer::BytesBuffered() const {
+size_t QuicStreamSequencerBuffer::BytesBuffered() const {
return num_bytes_buffered_;
}
-size_t StreamSequencerBuffer::GetBlockIndex(QuicStreamOffset offset) const {
+size_t QuicStreamSequencerBuffer::GetBlockIndex(QuicStreamOffset offset) const {
return (offset % max_buffer_capacity_bytes_) / kBlockSizeBytes;
}
-size_t StreamSequencerBuffer::GetInBlockOffset(QuicStreamOffset offset) const {
+size_t QuicStreamSequencerBuffer::GetInBlockOffset(
+ QuicStreamOffset offset) const {
return (offset % max_buffer_capacity_bytes_) % kBlockSizeBytes;
}
-size_t StreamSequencerBuffer::ReadOffset() const {
+size_t QuicStreamSequencerBuffer::ReadOffset() const {
return GetInBlockOffset(total_bytes_read_);
}
-size_t StreamSequencerBuffer::NextBlockToRead() const {
+size_t QuicStreamSequencerBuffer::NextBlockToRead() const {
return GetBlockIndex(total_bytes_read_);
}
-void StreamSequencerBuffer::RetireBlockIfEmpty(size_t block_index) {
+void QuicStreamSequencerBuffer::RetireBlockIfEmpty(size_t block_index) {
DCHECK(ReadableBytes() == 0 || GetInBlockOffset(total_bytes_read_) == 0)
<< "RetireBlockIfEmpty() should only be called when advancing to next "
"block"
@@ -411,11 +446,11 @@ void StreamSequencerBuffer::RetireBlockIfEmpty(size_t block_index) {
RetireBlock(block_index);
}
-bool StreamSequencerBuffer::Empty() const {
+bool QuicStreamSequencerBuffer::Empty() const {
return gaps_.size() == 1 && gaps_.front().begin_offset == total_bytes_read_;
}
-size_t StreamSequencerBuffer::GetBlockCapacity(size_t block_index) const {
+size_t QuicStreamSequencerBuffer::GetBlockCapacity(size_t block_index) const {
if ((block_index + 1) == blocks_count_) {
size_t result = max_buffer_capacity_bytes_ % kBlockSizeBytes;
if (result == 0) { // whole block
@@ -427,7 +462,7 @@ size_t StreamSequencerBuffer::GetBlockCapacity(size_t block_index) const {
}
}
-void StreamSequencerBuffer::UpdateFrameArrivalMap(QuicStreamOffset offset) {
+void QuicStreamSequencerBuffer::UpdateFrameArrivalMap(QuicStreamOffset offset) {
// Get the frame before which all frames should be removed.
auto next_frame = frame_arrival_time_map_.upper_bound(offset);
DCHECK(next_frame != frame_arrival_time_map_.begin());
@@ -450,4 +485,26 @@ void StreamSequencerBuffer::UpdateFrameArrivalMap(QuicStreamOffset offset) {
}
}
+string QuicStreamSequencerBuffer::GapsDebugString() {
+ string current_gaps_string;
+ 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);
+ }
+ return current_gaps_string;
+}
+
+string QuicStreamSequencerBuffer::ReceivedFramesDebugString() {
+ string current_frames_string;
+ for (auto it : frame_arrival_time_map_) {
+ QuicStreamOffset current_frame_begin_offset = it.first;
+ QuicStreamOffset current_frame_end_offset =
+ it.second.length + current_frame_begin_offset;
+ current_frames_string +=
+ RangeDebugString(current_frame_begin_offset, current_frame_end_offset);
+ }
+ return current_frames_string;
+}
+
} // namespace net
diff --git a/chromium/net/quic/stream_sequencer_buffer.h b/chromium/net/quic/quic_stream_sequencer_buffer.h
index 64a7959ccb8..7b854aeeb69 100644
--- a/chromium/net/quic/stream_sequencer_buffer.h
+++ b/chromium/net/quic/quic_stream_sequencer_buffer.h
@@ -2,10 +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_STREAM_SEQUENCER_BUFFER_H_
-#define NET_QUIC_STREAM_SEQUENCER_BUFFER_H_
+#ifndef NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_H_
+#define NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_H_
-// StreamSequencerBuffer implements QuicStreamSequencerBufferInterface.
+// QuicStreamSequencerBuffer implements QuicStreamSequencerBufferInterface.
// It is a circular stream buffer with random write and
// in-sequence read. It consists of a vector of pointers pointing
// to memory blocks created as needed and a list of Gaps to indicate
@@ -20,14 +20,14 @@
//
// This class is thread-unsafe.
//
-// StreamSequencerBuffer maintains a concept of the readable region, which
+// QuicStreamSequencerBuffer maintains a concept of the readable region, which
// contains all written data that has not been read.
// It promises stability of the underlying memory addresses in the readable
// region, so pointers into it can be maintained, and the offset of a pointer
// from the start of the read region can be calculated.
//
// Expected Use:
-// StreamSequencerBuffer buffer(2.5 * 8 * 1024);
+// QuicStreamSequencerBuffer buffer(2.5 * 8 * 1024);
// std::string source(1024, 'a');
// base::StringPiece std::string_piece(source.data(), source.size());
// size_t written = 0;
@@ -68,20 +68,20 @@
#include "base/macros.h"
#include "net/quic/quic_protocol.h"
-#include "net/quic/quic_stream_sequencer_buffer_interface.h"
+
+using base::StringPiece;
namespace net {
namespace test {
-class StreamSequencerBufferPeer;
+class QuicStreamSequencerBufferPeer;
} // namespace test
-class NET_EXPORT_PRIVATE StreamSequencerBuffer
- : public QuicStreamSequencerBufferInterface {
+class NET_EXPORT_PRIVATE QuicStreamSequencerBuffer {
public:
// A Gap indicates a missing chunk of bytes between
// [begin_offset, end_offset) in the stream
- struct Gap {
+ struct NET_EXPORT_PRIVATE Gap {
Gap(QuicStreamOffset begin_offset, QuicStreamOffset end_offset);
QuicStreamOffset begin_offset;
QuicStreamOffset end_offset;
@@ -106,28 +106,65 @@ class NET_EXPORT_PRIVATE StreamSequencerBuffer
char buffer[kBlockSizeBytes];
};
- explicit StreamSequencerBuffer(size_t max_capacity_bytes);
+ explicit QuicStreamSequencerBuffer(size_t max_capacity_bytes);
+ ~QuicStreamSequencerBuffer();
+
+ // Free the space used to buffer data.
+ void Clear();
- ~StreamSequencerBuffer() override;
+ // Returns true if there is nothing to read in this buffer.
+ bool Empty() const;
- // QuicStreamSequencerBufferInterface implementation.
- void Clear() override;
- bool Empty() const override;
+ // 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.
QuicErrorCode OnStreamData(QuicStreamOffset offset,
base::StringPiece data,
QuicTime timestamp,
- size_t* bytes_buffered) override;
- size_t Readv(const struct iovec* dest_iov, size_t dest_count) override;
- int GetReadableRegions(struct iovec* iov, int iov_len) const override;
- bool GetReadableRegion(iovec* iov, QuicTime* timestamp) const override;
- bool MarkConsumed(size_t bytes_buffered) override;
- size_t FlushBufferedFrames() override;
- bool HasBytesToRead() const override;
- QuicStreamOffset BytesConsumed() const override;
- size_t BytesBuffered() const override;
+ size_t* bytes_buffered,
+ std::string* error_details);
+
+ // Reads from this buffer into given iovec array, up to number of iov_len
+ // iovec objects and returns the number of bytes read.
+ size_t Readv(const struct iovec* dest_iov, size_t dest_count);
+
+ // 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.
+ int GetReadableRegions(struct iovec* iov, int iov_len) const;
+
+ // 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.
+ bool GetReadableRegion(iovec* iov, QuicTime* timestamp) const;
+
+ // Called after GetReadableRegions() to free up |bytes_used| space if these
+ // bytes are processed.
+ // Pre-requisite: bytes_used <= available bytes to read.
+ bool MarkConsumed(size_t bytes_buffered);
+
+ // Deletes and records as consumed any buffered data and clear the buffer.
+ // (To be called only after sequencer's StopReading has been called.)
+ size_t FlushBufferedFrames();
+
+ // Whether there are bytes can be read out.
+ bool HasBytesToRead() const;
+
+ // Count how many bytes have been consumed (read out of buffer).
+ QuicStreamOffset BytesConsumed() const;
+
+ // Count how many bytes are in buffer at this moment.
+ size_t BytesBuffered() const;
private:
- friend class test::StreamSequencerBufferPeer;
+ friend class test::QuicStreamSequencerBufferPeer;
// Dispose the given buffer block.
// After calling this method, blocks_[index] is set to nullptr
@@ -173,6 +210,14 @@ class NET_EXPORT_PRIVATE StreamSequencerBuffer
// should be removed from the map.
void UpdateFrameArrivalMap(QuicStreamOffset offset);
+ // Return |gaps_| as a std::string: [1024, 1500) [1800, 2048)... for
+ // debugging.
+ std::string GapsDebugString();
+
+ // Return all received frames as a std::string in same format as
+ // GapsDebugString();
+ std::string ReceivedFramesDebugString();
+
// The maximum total capacity of this buffer in byte, as constructed.
const size_t max_buffer_capacity_bytes_;
@@ -196,8 +241,8 @@ class NET_EXPORT_PRIVATE StreamSequencerBuffer
// Stores all the buffered frames' start offset, length and arrival time.
std::map<QuicStreamOffset, FrameInfo> frame_arrival_time_map_;
- DISALLOW_COPY_AND_ASSIGN(StreamSequencerBuffer);
+ DISALLOW_COPY_AND_ASSIGN(QuicStreamSequencerBuffer);
};
} // namespace net
-#endif // NET_QUIC_STREAM_SEQUENCER_BUFFER_H_
+#endif // NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_H_
diff --git a/chromium/net/quic/stream_sequencer_buffer_test.cc b/chromium/net/quic/quic_stream_sequencer_buffer_test.cc
index ccebb73539e..ce0cb72d31c 100644
--- a/chromium/net/quic/stream_sequencer_buffer_test.cc
+++ b/chromium/net/quic/quic_stream_sequencer_buffer_test.cc
@@ -1,8 +1,13 @@
// 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/quic_stream_sequencer_buffer.h"
-#include "net/quic/stream_sequencer_buffer.h"
+#include <algorithm>
+#include <limits>
+#include <map>
+#include <string>
+#include <utility>
#include "base/logging.h"
#include "base/macros.h"
@@ -15,6 +20,7 @@
#include "testing/gtest/include/gtest/gtest.h"
using std::min;
+using std::string;
namespace net {
@@ -41,14 +47,15 @@ char GetCharFromIOVecs(size_t offset, iovec iov[], size_t count) {
return '\0';
}
-static const size_t kBlockSizeBytes = StreamSequencerBuffer::kBlockSizeBytes;
-typedef StreamSequencerBuffer::BufferBlock BufferBlock;
-typedef StreamSequencerBuffer::Gap Gap;
-typedef StreamSequencerBuffer::FrameInfo FrameInfo;
+static const size_t kBlockSizeBytes =
+ QuicStreamSequencerBuffer::kBlockSizeBytes;
+typedef QuicStreamSequencerBuffer::BufferBlock BufferBlock;
+typedef QuicStreamSequencerBuffer::Gap Gap;
+typedef QuicStreamSequencerBuffer::FrameInfo FrameInfo;
-class StreamSequencerBufferPeer {
+class QuicStreamSequencerBufferPeer {
public:
- explicit StreamSequencerBufferPeer(StreamSequencerBuffer* buffer)
+ explicit QuicStreamSequencerBufferPeer(QuicStreamSequencerBuffer* buffer)
: buffer_(buffer) {}
// Read from this buffer_->into the given destination buffer_-> up to the
@@ -135,13 +142,19 @@ class StreamSequencerBufferPeer {
return &(buffer_->frame_arrival_time_map_);
}
+ void set_total_bytes_read(QuicStreamOffset total_bytes_read) {
+ buffer_->total_bytes_read_ = total_bytes_read;
+ }
+
+ void set_gaps(const std::list<Gap>& gaps) { buffer_->gaps_ = gaps; }
+
private:
- StreamSequencerBuffer* buffer_;
+ QuicStreamSequencerBuffer* buffer_;
};
namespace {
-class StreamSequencerBufferTest : public testing::Test {
+class QuicStreamSequencerBufferTest : public testing::Test {
public:
void SetUp() override { Initialize(); }
@@ -152,8 +165,8 @@ class StreamSequencerBufferTest : public testing::Test {
protected:
void Initialize() {
- buffer_.reset(new StreamSequencerBuffer(max_capacity_bytes_));
- helper_.reset(new StreamSequencerBufferPeer(buffer_.get()));
+ buffer_.reset(new QuicStreamSequencerBuffer(max_capacity_bytes_));
+ helper_.reset(new QuicStreamSequencerBufferPeer(buffer_.get()));
}
// Use 2.5 here to make sure the buffer has more than one block and its end
@@ -162,42 +175,43 @@ class StreamSequencerBufferTest : public testing::Test {
size_t max_capacity_bytes_ = 2.5 * kBlockSizeBytes;
MockClock clock_;
- std::unique_ptr<StreamSequencerBuffer> buffer_;
- std::unique_ptr<StreamSequencerBufferPeer> helper_;
+ std::unique_ptr<QuicStreamSequencerBuffer> buffer_;
+ std::unique_ptr<QuicStreamSequencerBufferPeer> helper_;
+ string error_details_;
};
-TEST_F(StreamSequencerBufferTest, InitializationWithDifferentSizes) {
- const size_t kCapacity = 2 * StreamSequencerBuffer::kBlockSizeBytes;
+TEST_F(QuicStreamSequencerBufferTest, InitializationWithDifferentSizes) {
+ const size_t kCapacity = 2 * QuicStreamSequencerBuffer::kBlockSizeBytes;
ResetMaxCapacityBytes(kCapacity);
EXPECT_EQ(max_capacity_bytes_, helper_->max_buffer_capacity());
EXPECT_TRUE(helper_->CheckInitialState());
- const size_t kCapacity1 = 8 * StreamSequencerBuffer::kBlockSizeBytes;
+ const size_t kCapacity1 = 8 * QuicStreamSequencerBuffer::kBlockSizeBytes;
ResetMaxCapacityBytes(kCapacity1);
EXPECT_EQ(kCapacity1, helper_->max_buffer_capacity());
EXPECT_TRUE(helper_->CheckInitialState());
}
-TEST_F(StreamSequencerBufferTest, ClearOnEmpty) {
+TEST_F(QuicStreamSequencerBufferTest, ClearOnEmpty) {
buffer_->Clear();
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamData0length) {
- std::string source;
+TEST_F(QuicStreamSequencerBufferTest, OnStreamData0length) {
size_t written;
- EXPECT_DFATAL(
- buffer_->OnStreamData(800, source, clock_.ApproximateNow(), &written),
- "Attempted to write 0 bytes of data.");
+ QuicErrorCode error = buffer_->OnStreamData(800, "", clock_.ApproximateNow(),
+ &written, &error_details_);
+ EXPECT_EQ(error, QUIC_EMPTY_STREAM_FRAME_NO_FIN);
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataWithinBlock) {
- std::string source(1024, 'a');
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) {
+ string source(1024, 'a');
size_t written;
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t = clock_.ApproximateNow();
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(800, source, t, &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(800, source, t, &written, &error_details_));
BufferBlock* block_ptr = helper_->GetBlock(0);
for (size_t i = 0; i < source.size(); ++i) {
ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]);
@@ -213,128 +227,172 @@ TEST_F(StreamSequencerBufferTest, OnStreamDataWithinBlock) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataWithOverlap) {
- std::string source(1024, 'a');
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithOverlap) {
+ string source(1024, 'a');
// Write something into [800, 1824)
size_t written;
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t1 = clock_.ApproximateNow();
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(800, source, t1, &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(800, source, t1, &written, &error_details_));
// Try to write to [0, 1024) and [1024, 2048).
// But no byte will be written since overlap.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t2 = clock_.ApproximateNow();
- EXPECT_EQ(QUIC_INVALID_STREAM_DATA,
- buffer_->OnStreamData(0, source, t2, &written));
- EXPECT_EQ(QUIC_INVALID_STREAM_DATA,
- buffer_->OnStreamData(1024, source, t2, &written));
+ EXPECT_EQ(QUIC_OVERLAPPING_STREAM_DATA,
+ buffer_->OnStreamData(0, source, t2, &written, &error_details_));
+ EXPECT_EQ(QUIC_OVERLAPPING_STREAM_DATA,
+ buffer_->OnStreamData(1024, source, t2, &written, &error_details_));
auto frame_map = helper_->frame_arrival_time_map();
EXPECT_EQ(1u, frame_map->size());
EXPECT_EQ(t1, (*frame_map)[800].timestamp);
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataOverlapAndDuplicateCornerCases) {
- std::string source(1024, 'a');
+TEST_F(QuicStreamSequencerBufferTest,
+ OnStreamDataOverlapAndDuplicateCornerCases) {
+ string source(1024, 'a');
// Write something into [800, 1824)
size_t written;
- buffer_->OnStreamData(800, source, clock_.ApproximateNow(), &written);
- source = std::string(800, 'b');
+ buffer_->OnStreamData(800, source, clock_.ApproximateNow(), &written,
+ &error_details_);
+ source = string(800, 'b');
// Try to write to [1, 801), but should fail due to overlapping
- EXPECT_EQ(
- QUIC_INVALID_STREAM_DATA,
- buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written));
+ EXPECT_EQ(QUIC_OVERLAPPING_STREAM_DATA,
+ buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written,
+ &error_details_));
// write to [0, 800)
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(
- 0, source, clock_.ApproximateNow(), &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_));
// Try to write one byte to [1823, 1824), but should count as duplicate
- std::string one_byte = "c";
- EXPECT_EQ(
- QUIC_NO_ERROR,
- buffer_->OnStreamData(1823, one_byte, clock_.ApproximateNow(), &written));
+ string one_byte = "c";
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(1823, one_byte, clock_.ApproximateNow(),
+ &written, &error_details_));
EXPECT_EQ(0u, written);
// write one byte to [1824, 1825)
- EXPECT_EQ(
- QUIC_NO_ERROR,
- buffer_->OnStreamData(1824, one_byte, clock_.ApproximateNow(), &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(1824, one_byte, clock_.ApproximateNow(),
+ &written, &error_details_));
auto frame_map = helper_->frame_arrival_time_map();
EXPECT_EQ(3u, frame_map->size());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataWithoutOverlap) {
- std::string source(1024, 'a');
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithoutOverlap) {
+ string source(1024, 'a');
// Write something into [800, 1824).
size_t written;
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(
- 800, source, clock_.ApproximateNow(), &written));
- source = std::string(100, 'b');
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(800, source, clock_.ApproximateNow(),
+ &written, &error_details_));
+ source = string(100, 'b');
// Write something into [kBlockSizeBytes * 2 - 20, kBlockSizeBytes * 2 + 80).
EXPECT_EQ(QUIC_NO_ERROR,
buffer_->OnStreamData(kBlockSizeBytes * 2 - 20, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_EQ(3, helper_->GapSize());
EXPECT_EQ(1024u + 100u, buffer_->BytesBuffered());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataTillEnd) {
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInLongStreamWithOverlap) {
+ // Assume a stream has already buffered almost 4GB.
+ uint64_t total_bytes_read = pow(2, 32) - 1;
+ helper_->set_total_bytes_read(total_bytes_read);
+ helper_->set_gaps(std::list<Gap>(
+ 1, Gap(total_bytes_read, std::numeric_limits<QuicStreamOffset>::max())));
+
+ // Three new out of order frames arrive.
+ const size_t kBytesToWrite = 100;
+ string source(kBytesToWrite, 'a');
+ size_t written;
+ // Frame [2^32 + 500, 2^32 + 600).
+ QuicStreamOffset offset = pow(2, 32) + 500;
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(offset, source, clock_.ApproximateNow(),
+ &written, &error_details_));
+ EXPECT_EQ(2, helper_->GapSize());
+
+ // Frame [2^32 + 700, 2^32 + 800).
+ offset = pow(2, 32) + 700;
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(offset, source, clock_.ApproximateNow(),
+ &written, &error_details_));
+ EXPECT_EQ(3, helper_->GapSize());
+
+ // Another frame [2^32 + 300, 2^32 + 400).
+ offset = pow(2, 32) + 300;
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(offset, source, clock_.ApproximateNow(),
+ &written, &error_details_));
+ EXPECT_EQ(4, helper_->GapSize());
+}
+
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataTillEnd) {
// Write 50 bytes to the end.
const size_t kBytesToWrite = 50;
- std::string source(kBytesToWrite, 'a');
+ string source(kBytesToWrite, 'a');
size_t written;
EXPECT_EQ(QUIC_NO_ERROR,
buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_EQ(50u, buffer_->BytesBuffered());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataTillEndCorner) {
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataTillEndCorner) {
// Write 1 byte to the end.
const size_t kBytesToWrite = 1;
- std::string source(kBytesToWrite, 'a');
+ string source(kBytesToWrite, 'a');
size_t written;
EXPECT_EQ(QUIC_NO_ERROR,
buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_EQ(1u, buffer_->BytesBuffered());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataBeyondCapacity) {
- std::string source(60, 'a');
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataBeyondCapacity) {
+ string source(60, 'a');
size_t written;
EXPECT_EQ(QUIC_INTERNAL_ERROR,
buffer_->OnStreamData(max_capacity_bytes_ - 50, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_TRUE(helper_->CheckBufferInvariants());
source = "b";
EXPECT_EQ(QUIC_INTERNAL_ERROR,
buffer_->OnStreamData(max_capacity_bytes_, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_TRUE(helper_->CheckBufferInvariants());
EXPECT_EQ(QUIC_INTERNAL_ERROR,
buffer_->OnStreamData(max_capacity_bytes_ * 1000, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_TRUE(helper_->CheckBufferInvariants());
EXPECT_EQ(0u, buffer_->BytesBuffered());
}
-TEST_F(StreamSequencerBufferTest, Readv100Bytes) {
- std::string source(1024, 'a');
+TEST_F(QuicStreamSequencerBufferTest, Readv100Bytes) {
+ string source(1024, 'a');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t1 = clock_.ApproximateNow();
// Write something into [kBlockSizeBytes, kBlockSizeBytes + 1024).
size_t written;
- buffer_->OnStreamData(kBlockSizeBytes, source, t1, &written);
+ buffer_->OnStreamData(kBlockSizeBytes, source, t1, &written, &error_details_);
EXPECT_FALSE(buffer_->HasBytesToRead());
- source = std::string(100, 'b');
+ source = string(100, 'b');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t2 = clock_.ApproximateNow();
// Write something into [0, 100).
- buffer_->OnStreamData(0, source, t2, &written);
+ buffer_->OnStreamData(0, source, t2, &written, &error_details_);
EXPECT_TRUE(buffer_->HasBytesToRead());
EXPECT_EQ(2u, helper_->frame_arrival_time_map()->size());
// Read into a iovec array with total capacity of 120 bytes.
@@ -343,16 +401,17 @@ TEST_F(StreamSequencerBufferTest, Readv100Bytes) {
size_t read = buffer_->Readv(iovecs, 3);
EXPECT_EQ(100u, read);
EXPECT_EQ(100u, buffer_->BytesConsumed());
- EXPECT_EQ(source, std::string(dest, read));
+ EXPECT_EQ(source, string(dest, read));
EXPECT_EQ(1u, helper_->frame_arrival_time_map()->size());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, ReadvAcrossBlocks) {
- std::string source(kBlockSizeBytes + 50, 'a');
+TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossBlocks) {
+ string source(kBlockSizeBytes + 50, 'a');
// Write 1st block to full and extand 50 bytes to next block.
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
EXPECT_EQ(source.size(), helper_->ReadableBytes());
// Iteratively read 512 bytes from buffer_-> Overwrite dest[] each time.
char dest[512];
@@ -362,18 +421,19 @@ TEST_F(StreamSequencerBufferTest, ReadvAcrossBlocks) {
buffer_->Readv(iovecs, 2);
}
// The last read only reads the rest 50 bytes in 2nd block.
- EXPECT_EQ(std::string(50, 'a'), std::string(dest, 50));
+ EXPECT_EQ(string(50, 'a'), string(dest, 50));
EXPECT_EQ(0, dest[50]) << "Dest[50] shouln't be filled.";
EXPECT_EQ(source.size(), buffer_->BytesConsumed());
EXPECT_TRUE(buffer_->Empty());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, ClearAfterRead) {
- std::string source(kBlockSizeBytes + 50, 'a');
+TEST_F(QuicStreamSequencerBufferTest, ClearAfterRead) {
+ string source(kBlockSizeBytes + 50, 'a');
// Write 1st block to full with 'a'.
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
// Read first 512 bytes from buffer to make space at the beginning.
char dest[512]{0};
const iovec iov{dest, 512};
@@ -384,11 +444,13 @@ TEST_F(StreamSequencerBufferTest, ClearAfterRead) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataAcrossLastBlockAndFillCapacity) {
- std::string source(kBlockSizeBytes + 50, 'a');
+TEST_F(QuicStreamSequencerBufferTest,
+ OnStreamDataAcrossLastBlockAndFillCapacity) {
+ string source(kBlockSizeBytes + 50, 'a');
// Write 1st block to full with 'a'.
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
// Read first 512 bytes from buffer to make space at the beginning.
char dest[512]{0};
const iovec iov{dest, 512};
@@ -397,20 +459,21 @@ TEST_F(StreamSequencerBufferTest, OnStreamDataAcrossLastBlockAndFillCapacity) {
// Write more than half block size of bytes in the last block with 'b', which
// will wrap to the beginning and reaches the full capacity.
- source = std::string(0.5 * kBlockSizeBytes + 512, 'b');
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(2 * kBlockSizeBytes, source,
- clock_.ApproximateNow(), &written));
+ source = string(0.5 * kBlockSizeBytes + 512, 'b');
+ EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(2 * kBlockSizeBytes, source,
+ clock_.ApproximateNow(),
+ &written, &error_details_));
EXPECT_EQ(source.size(), written);
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest,
+TEST_F(QuicStreamSequencerBufferTest,
OnStreamDataAcrossLastBlockAndExceedCapacity) {
- std::string source(kBlockSizeBytes + 50, 'a');
+ string source(kBlockSizeBytes + 50, 'a');
// Write 1st block to full.
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
// Read first 512 bytes from buffer to make space at the beginning.
char dest[512]{0};
const iovec iov{dest, 512};
@@ -418,33 +481,36 @@ TEST_F(StreamSequencerBufferTest,
// Try to write from [max_capacity_bytes_ - 0.5 * kBlockSizeBytes,
// max_capacity_bytes_ + 512 + 1). But last bytes exceeds current capacity.
- source = std::string(0.5 * kBlockSizeBytes + 512 + 1, 'b');
+ source = string(0.5 * kBlockSizeBytes + 512 + 1, 'b');
EXPECT_EQ(QUIC_INTERNAL_ERROR,
buffer_->OnStreamData(2 * kBlockSizeBytes, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, ReadvAcrossLastBlock) {
+TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossLastBlock) {
// Write to full capacity and read out 512 bytes at beginning and continue
// appending 256 bytes.
- std::string source(max_capacity_bytes_, 'a');
+ string source(max_capacity_bytes_, 'a');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t = clock_.ApproximateNow();
size_t written;
- buffer_->OnStreamData(0, source, t, &written);
+ buffer_->OnStreamData(0, source, t, &written, &error_details_);
char dest[512]{0};
const iovec iov{dest, 512};
buffer_->Readv(&iov, 1);
- source = std::string(256, 'b');
+ source = string(256, 'b');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t2 = clock_.ApproximateNow();
- buffer_->OnStreamData(max_capacity_bytes_, source, t2, &written);
+ buffer_->OnStreamData(max_capacity_bytes_, source, t2, &written,
+ &error_details_);
EXPECT_TRUE(helper_->CheckBufferInvariants());
EXPECT_EQ(2u, helper_->frame_arrival_time_map()->size());
// Read all data out.
- std::unique_ptr<char[]> dest1{new char[max_capacity_bytes_]{0}};
+ std::unique_ptr<char[]> dest1{new char[max_capacity_bytes_]};
+ dest1[0] = 0;
const iovec iov1{dest1.get(), max_capacity_bytes_};
EXPECT_EQ(max_capacity_bytes_ - 512 + 256, buffer_->Readv(&iov1, 1));
EXPECT_EQ(max_capacity_bytes_ + 256, buffer_->BytesConsumed());
@@ -453,7 +519,7 @@ TEST_F(StreamSequencerBufferTest, ReadvAcrossLastBlock) {
EXPECT_EQ(0u, helper_->frame_arrival_time_map()->size());
}
-TEST_F(StreamSequencerBufferTest, ReadvEmpty) {
+TEST_F(QuicStreamSequencerBufferTest, ReadvEmpty) {
char dest[512]{0};
iovec iov{dest, 512};
size_t read = buffer_->Readv(&iov, 1);
@@ -461,7 +527,7 @@ TEST_F(StreamSequencerBufferTest, ReadvEmpty) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionsEmpty) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsEmpty) {
iovec iovs[2];
int iov_count = buffer_->GetReadableRegions(iovs, 2);
EXPECT_EQ(0, iov_count);
@@ -469,55 +535,60 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionsEmpty) {
EXPECT_EQ(0u, iovs[iov_count].iov_len);
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionsBlockedByGap) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsBlockedByGap) {
// Write into [1, 1024).
- std::string source(1023, 'a');
+ string source(1023, 'a');
size_t written;
- buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written,
+ &error_details_);
// Try to get readable regions, but none is there.
iovec iovs[2];
int iov_count = buffer_->GetReadableRegions(iovs, 2);
EXPECT_EQ(0, iov_count);
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionsTillEndOfBlock) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsTillEndOfBlock) {
// Write first block to full with [0, 256) 'a' and the rest 'b' then read out
// [0, 256)
- std::string source(kBlockSizeBytes, 'a');
+ string source(kBlockSizeBytes, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[256];
helper_->Read(dest, 256);
// Get readable region from [256, 1024)
iovec iovs[2];
int iov_count = buffer_->GetReadableRegions(iovs, 2);
EXPECT_EQ(1, iov_count);
- EXPECT_EQ(std::string(kBlockSizeBytes - 256, 'a'),
- std::string(reinterpret_cast<const char*>(iovs[0].iov_base),
- iovs[0].iov_len));
+ EXPECT_EQ(
+ string(kBlockSizeBytes - 256, 'a'),
+ string(reinterpret_cast<const char*>(iovs[0].iov_base), iovs[0].iov_len));
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionsWithinOneBlock) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsWithinOneBlock) {
// Write into [0, 1024) and then read out [0, 256)
- std::string source(1024, 'a');
+ string source(1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[256];
helper_->Read(dest, 256);
// Get readable region from [256, 1024)
iovec iovs[2];
int iov_count = buffer_->GetReadableRegions(iovs, 2);
EXPECT_EQ(1, iov_count);
- EXPECT_EQ(std::string(1024 - 256, 'a'),
- std::string(reinterpret_cast<const char*>(iovs[0].iov_base),
- iovs[0].iov_len));
+ EXPECT_EQ(
+ string(1024 - 256, 'a'),
+ string(reinterpret_cast<const char*>(iovs[0].iov_base), iovs[0].iov_len));
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionsAcrossBlockWithLongIOV) {
+TEST_F(QuicStreamSequencerBufferTest,
+ GetReadableRegionsAcrossBlockWithLongIOV) {
// Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
- std::string source(2 * kBlockSizeBytes + 1024, 'a');
+ string source(2 * kBlockSizeBytes + 1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[1024];
helper_->Read(dest, 1024);
@@ -529,18 +600,20 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionsAcrossBlockWithLongIOV) {
EXPECT_EQ(1024u, iovs[2].iov_len);
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionsWithMultipleIOVsAcrossEnd) {
+TEST_F(QuicStreamSequencerBufferTest,
+ GetReadableRegionsWithMultipleIOVsAcrossEnd) {
// Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
// and then append 1024 + 512 bytes.
- std::string source(2.5 * kBlockSizeBytes - 1024, 'a');
+ string source(2.5 * kBlockSizeBytes - 1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[1024];
helper_->Read(dest, 1024);
// Write across the end.
- source = std::string(1024 + 512, 'b');
+ source = string(1024 + 512, 'b');
buffer_->OnStreamData(2.5 * kBlockSizeBytes - 1024, source,
- clock_.ApproximateNow(), &written);
+ clock_.ApproximateNow(), &written, &error_details_);
// Use short iovec's.
iovec iovs[2];
int iov_count = buffer_->GetReadableRegions(iovs, 2);
@@ -552,12 +625,12 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionsWithMultipleIOVsAcrossEnd) {
EXPECT_EQ(4, buffer_->GetReadableRegions(iovs1, 5));
EXPECT_EQ(0.5 * kBlockSizeBytes, iovs1[2].iov_len);
EXPECT_EQ(512u, iovs1[3].iov_len);
- EXPECT_EQ(std::string(512, 'b'),
- std::string(reinterpret_cast<const char*>(iovs1[3].iov_base),
- iovs1[3].iov_len));
+ EXPECT_EQ(string(512, 'b'),
+ string(reinterpret_cast<const char*>(iovs1[3].iov_base),
+ iovs1[3].iov_len));
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionEmpty) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionEmpty) {
iovec iov;
QuicTime t = QuicTime::Zero();
EXPECT_FALSE(buffer_->GetReadableRegion(&iov, &t));
@@ -565,11 +638,12 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionEmpty) {
EXPECT_EQ(0u, iov.iov_len);
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionBeforeGap) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionBeforeGap) {
// Write into [1, 1024).
- std::string source(1023, 'a');
+ string source(1023, 'a');
size_t written;
- buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written,
+ &error_details_);
// GetReadableRegion should return false because range [0,1) hasn't been
// filled yet.
iovec iov;
@@ -577,13 +651,13 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionBeforeGap) {
EXPECT_FALSE(buffer_->GetReadableRegion(&iov, &t));
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionTillEndOfBlock) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionTillEndOfBlock) {
// Write into [0, kBlockSizeBytes + 1) and then read out [0, 256)
- std::string source(kBlockSizeBytes + 1, 'a');
+ string source(kBlockSizeBytes + 1, 'a');
size_t written;
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t = clock_.ApproximateNow();
- buffer_->OnStreamData(0, source, t, &written);
+ buffer_->OnStreamData(0, source, t, &written, &error_details_);
char dest[256];
helper_->Read(dest, 256);
// Get readable region from [256, 1024)
@@ -591,18 +665,17 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionTillEndOfBlock) {
QuicTime t2 = QuicTime::Zero();
EXPECT_TRUE(buffer_->GetReadableRegion(&iov, &t2));
EXPECT_EQ(t, t2);
- EXPECT_EQ(
- std::string(kBlockSizeBytes - 256, 'a'),
- std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
+ EXPECT_EQ(string(kBlockSizeBytes - 256, 'a'),
+ string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionTillGap) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionTillGap) {
// Write into [0, kBlockSizeBytes - 1) and then read out [0, 256)
- std::string source(kBlockSizeBytes - 1, 'a');
+ string source(kBlockSizeBytes - 1, 'a');
size_t written;
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t = clock_.ApproximateNow();
- buffer_->OnStreamData(0, source, t, &written);
+ buffer_->OnStreamData(0, source, t, &written, &error_details_);
char dest[256];
helper_->Read(dest, 256);
// Get readable region from [256, 1023)
@@ -610,46 +683,47 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionTillGap) {
QuicTime t2 = QuicTime::Zero();
EXPECT_TRUE(buffer_->GetReadableRegion(&iov, &t2));
EXPECT_EQ(t, t2);
- EXPECT_EQ(
- std::string(kBlockSizeBytes - 1 - 256, 'a'),
- std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
+ EXPECT_EQ(string(kBlockSizeBytes - 1 - 256, 'a'),
+ string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionByArrivalTime) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionByArrivalTime) {
// Write into [0, kBlockSizeBytes - 100) and then read out [0, 256)
- std::string source(kBlockSizeBytes - 100, 'a');
+ string source(kBlockSizeBytes - 100, 'a');
size_t written;
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t = clock_.ApproximateNow();
- buffer_->OnStreamData(0, source, t, &written);
+ buffer_->OnStreamData(0, source, t, &written, &error_details_);
char dest[256];
helper_->Read(dest, 256);
// Write into [kBlockSizeBytes - 100, kBlockSizeBytes - 50)] in same time
- std::string source2(50, 'b');
+ string source2(50, 'b');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
- buffer_->OnStreamData(kBlockSizeBytes - 100, source2, t, &written);
+ buffer_->OnStreamData(kBlockSizeBytes - 100, source2, t, &written,
+ &error_details_);
// Write into [kBlockSizeBytes - 50, kBlockSizeBytes)] in another time
- std::string source3(50, 'c');
+ string source3(50, 'c');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t3 = clock_.ApproximateNow();
- buffer_->OnStreamData(kBlockSizeBytes - 50, source3, t3, &written);
+ buffer_->OnStreamData(kBlockSizeBytes - 50, source3, t3, &written,
+ &error_details_);
// Get readable region from [256, 1024 - 50)
iovec iov;
QuicTime t4 = QuicTime::Zero();
EXPECT_TRUE(buffer_->GetReadableRegion(&iov, &t4));
EXPECT_EQ(t, t4);
- EXPECT_EQ(
- std::string(kBlockSizeBytes - 100 - 256, 'a') + source2,
- std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
+ EXPECT_EQ(string(kBlockSizeBytes - 100 - 256, 'a') + source2,
+ string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
}
-TEST_F(StreamSequencerBufferTest, MarkConsumedInOneBlock) {
+TEST_F(QuicStreamSequencerBufferTest, MarkConsumedInOneBlock) {
// Write into [0, 1024) and then read out [0, 256)
- std::string source(1024, 'a');
+ string source(1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[256];
helper_->Read(dest, 256);
@@ -663,12 +737,12 @@ TEST_F(StreamSequencerBufferTest, MarkConsumedInOneBlock) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, MarkConsumedNotEnoughBytes) {
+TEST_F(QuicStreamSequencerBufferTest, MarkConsumedNotEnoughBytes) {
// Write into [0, 1024) and then read out [0, 256)
- std::string source(1024, 'a');
+ string source(1024, 'a');
size_t written;
QuicTime t = clock_.ApproximateNow();
- buffer_->OnStreamData(0, source, t, &written);
+ buffer_->OnStreamData(0, source, t, &written, &error_details_);
char dest[256];
helper_->Read(dest, 256);
@@ -686,11 +760,12 @@ TEST_F(StreamSequencerBufferTest, MarkConsumedNotEnoughBytes) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, MarkConsumedAcrossBlock) {
+TEST_F(QuicStreamSequencerBufferTest, MarkConsumedAcrossBlock) {
// Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
- std::string source(2 * kBlockSizeBytes + 1024, 'a');
+ string source(2 * kBlockSizeBytes + 1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[1024];
helper_->Read(dest, 1024);
@@ -700,17 +775,18 @@ TEST_F(StreamSequencerBufferTest, MarkConsumedAcrossBlock) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, MarkConsumedAcrossEnd) {
+TEST_F(QuicStreamSequencerBufferTest, MarkConsumedAcrossEnd) {
// Write into [0, 2.5 * kBlockSizeBytes - 1024) and then read out [0, 1024)
// and then append 1024 + 512 bytes.
- std::string source(2.5 * kBlockSizeBytes - 1024, 'a');
+ string source(2.5 * kBlockSizeBytes - 1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[1024];
helper_->Read(dest, 1024);
- source = std::string(1024 + 512, 'b');
+ source = string(1024 + 512, 'b');
buffer_->OnStreamData(2.5 * kBlockSizeBytes - 1024, source,
- clock_.ApproximateNow(), &written);
+ clock_.ApproximateNow(), &written, &error_details_);
EXPECT_EQ(1024u, buffer_->BytesConsumed());
// Consume to the end of 2nd block.
@@ -727,18 +803,19 @@ TEST_F(StreamSequencerBufferTest, MarkConsumedAcrossEnd) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, FlushBufferedFrames) {
+TEST_F(QuicStreamSequencerBufferTest, FlushBufferedFrames) {
// Write into [0, 2.5 * kBlockSizeBytes - 1024) and then read out [0, 1024).
- std::string source(max_capacity_bytes_ - 1024, 'a');
+ string source(max_capacity_bytes_ - 1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[1024];
helper_->Read(dest, 1024);
EXPECT_EQ(1024u, buffer_->BytesConsumed());
// Write [1024, 512) to the physical beginning.
- source = std::string(512, 'b');
+ source = string(512, 'b');
buffer_->OnStreamData(max_capacity_bytes_, source, clock_.ApproximateNow(),
- &written);
+ &written, &error_details_);
EXPECT_EQ(512u, written);
EXPECT_EQ(max_capacity_bytes_ - 1024 + 512, buffer_->FlushBufferedFrames());
EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed());
@@ -750,7 +827,8 @@ TEST_F(StreamSequencerBufferTest, FlushBufferedFrames) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-class StreamSequencerBufferRandomIOTest : public StreamSequencerBufferTest {
+class QuicStreamSequencerBufferRandomIOTest
+ : public QuicStreamSequencerBufferTest {
public:
typedef std::pair<QuicStreamOffset, size_t> OffsetSizePair;
@@ -803,7 +881,7 @@ class StreamSequencerBufferRandomIOTest : public StreamSequencerBufferTest {
}
// Write the currently first chunk of data in the out-of-order stream into
- // StreamSequencerBuffer. If current chuck cannot be written into buffer
+ // QuicStreamSequencerBuffer. If current chuck cannot be written into buffer
// because it goes beyond current capacity, move it to the end of
// shuffled_buf_ and write it later.
void WriteNextChunkToBuffer() {
@@ -816,8 +894,9 @@ class StreamSequencerBufferRandomIOTest : public StreamSequencerBufferTest {
}
base::StringPiece string_piece_w(write_buf.get(), num_to_write);
size_t written;
- auto result = buffer_->OnStreamData(offset, string_piece_w,
- clock_.ApproximateNow(), &written);
+ auto result =
+ buffer_->OnStreamData(offset, string_piece_w, clock_.ApproximateNow(),
+ &written, &error_details_);
if (result == QUIC_NO_ERROR) {
shuffled_buf_.pop_front();
total_bytes_written_ += num_to_write;
@@ -840,7 +919,7 @@ class StreamSequencerBufferRandomIOTest : public StreamSequencerBufferTest {
SimpleRandom rng_;
};
-TEST_F(StreamSequencerBufferRandomIOTest, RandomWriteAndReadv) {
+TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndReadv) {
// Set kMaxReadSize larger than kBlockSizeBytes to test both small and large
// read.
const size_t kMaxReadSize = kBlockSizeBytes * 2;
@@ -900,7 +979,7 @@ TEST_F(StreamSequencerBufferRandomIOTest, RandomWriteAndReadv) {
EXPECT_LE(bytes_to_buffer_, total_bytes_written_);
}
-TEST_F(StreamSequencerBufferRandomIOTest, RandomWriteAndConsumeInPlace) {
+TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndConsumeInPlace) {
// The value 4 is chosen such that the max write size is no larger than the
// maximum buffer capacity.
const size_t kMaxNumReads = 4;
diff --git a/chromium/net/quic/quic_stream_sequencer_test.cc b/chromium/net/quic/quic_stream_sequencer_test.cc
index 3fb6bdacc26..b66bf1d4a84 100644
--- a/chromium/net/quic/quic_stream_sequencer_test.cc
+++ b/chromium/net/quic/quic_stream_sequencer_test.cc
@@ -11,7 +11,6 @@
#include "base/rand_util.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/quic_flags.h"
-#include "net/quic/quic_frame_list.h"
#include "net/quic/quic_utils.h"
#include "net/quic/reliable_quic_stream.h"
#include "net/quic/test_tools/mock_clock.h"
@@ -49,7 +48,6 @@ class MockStream : public ReliableQuicStream {
void(QuicErrorCode error, const string& details));
MOCK_METHOD1(Reset, void(QuicRstStreamErrorCode error));
MOCK_METHOD0(OnCanWrite, void());
- SpdyPriority Priority() const override { return kV3HighestPriority; }
virtual bool IsFlowControlEnabled() const { return true; }
};
@@ -58,13 +56,8 @@ namespace {
static const char kPayload[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-class QuicStreamSequencerTest : public ::testing::TestWithParam<bool> {
+class QuicStreamSequencerTest : public ::testing::Test {
public:
- void SetUp() override {
- FLAGS_quic_use_stream_sequencer_buffer = GetParam();
- sequencer_.reset(new QuicStreamSequencer(&stream_, &clock_));
- }
-
void ConsumeData(size_t num_bytes) {
char buffer[1024];
ASSERT_GT(arraysize(buffer), num_bytes);
@@ -78,7 +71,8 @@ class QuicStreamSequencerTest : public ::testing::TestWithParam<bool> {
QuicStreamSequencerTest()
: connection_(new MockConnection(&helper_, Perspective::IS_CLIENT)),
session_(connection_),
- stream_(&session_, 1) {}
+ stream_(&session_, 1),
+ sequencer_(new QuicStreamSequencer(&stream_, &clock_)) {}
// Verify that the data in first region match with the expected[0].
bool VerifyReadableRegion(const vector<string>& expected) {
@@ -102,27 +96,13 @@ class QuicStreamSequencerTest : public ::testing::TestWithParam<bool> {
bool VerifyIovecs(iovec* iovecs,
size_t num_iovecs,
const vector<string>& expected) {
- if (!FLAGS_quic_use_stream_sequencer_buffer) {
- if (expected.size() != num_iovecs) {
- LOG(ERROR) << "Incorrect number of iovecs. Expected: "
- << expected.size() << " Actual: " << num_iovecs;
+ int start_position = 0;
+ for (size_t i = 0; i < num_iovecs; ++i) {
+ if (!VerifyIovec(iovecs[i],
+ expected[0].substr(start_position, iovecs[i].iov_len))) {
return false;
}
-
- for (size_t i = 0; i < num_iovecs; ++i) {
- if (!VerifyIovec(iovecs[i], expected[i])) {
- return false;
- }
- }
- } else {
- int start_position = 0;
- for (size_t i = 0; i < num_iovecs; ++i) {
- if (!VerifyIovec(iovecs[i], expected[0].substr(start_position,
- iovecs[i].iov_len))) {
- return false;
- }
- start_position += iovecs[i].iov_len;
- }
+ start_position += iovecs[i].iov_len;
}
return true;
}
@@ -173,16 +153,13 @@ class QuicStreamSequencerTest : public ::testing::TestWithParam<bool> {
scoped_ptr<QuicStreamSequencer> sequencer_;
};
-INSTANTIATE_TEST_CASE_P(QuicStreamSequencerTests,
- QuicStreamSequencerTest,
- ::testing::Values(false, true));
-
// TODO(rch): reorder these tests so they build on each other.
-TEST_P(QuicStreamSequencerTest, RejectOldFrame) {
+TEST_F(QuicStreamSequencerTest, RejectOldFrame) {
EXPECT_CALL(stream_, OnDataAvailable())
.WillOnce(testing::Invoke(
- CreateFunctor(this, &QuicStreamSequencerTest::ConsumeData, 3)));
+ CreateFunctor(&QuicStreamSequencerTest::ConsumeData,
+ base::Unretained(this), 3)));
OnFrame(0, "abc");
@@ -195,7 +172,7 @@ TEST_P(QuicStreamSequencerTest, RejectOldFrame) {
EXPECT_EQ(0u, NumBufferedBytes());
}
-TEST_P(QuicStreamSequencerTest, RejectBufferedFrame) {
+TEST_F(QuicStreamSequencerTest, RejectBufferedFrame) {
EXPECT_CALL(stream_, OnDataAvailable());
OnFrame(0, "abc");
@@ -208,17 +185,18 @@ TEST_P(QuicStreamSequencerTest, RejectBufferedFrame) {
EXPECT_EQ(3u, NumBufferedBytes());
}
-TEST_P(QuicStreamSequencerTest, FullFrameConsumed) {
+TEST_F(QuicStreamSequencerTest, FullFrameConsumed) {
EXPECT_CALL(stream_, OnDataAvailable())
.WillOnce(testing::Invoke(
- CreateFunctor(this, &QuicStreamSequencerTest::ConsumeData, 3)));
+ CreateFunctor(&QuicStreamSequencerTest::ConsumeData,
+ base::Unretained(this), 3)));
OnFrame(0, "abc");
EXPECT_EQ(0u, NumBufferedBytes());
EXPECT_EQ(3u, sequencer_->NumBytesConsumed());
}
-TEST_P(QuicStreamSequencerTest, BlockedThenFullFrameConsumed) {
+TEST_F(QuicStreamSequencerTest, BlockedThenFullFrameConsumed) {
sequencer_->SetBlockedUntilFlush();
OnFrame(0, "abc");
@@ -227,20 +205,22 @@ TEST_P(QuicStreamSequencerTest, BlockedThenFullFrameConsumed) {
EXPECT_CALL(stream_, OnDataAvailable())
.WillOnce(testing::Invoke(
- CreateFunctor(this, &QuicStreamSequencerTest::ConsumeData, 3)));
+ CreateFunctor(&QuicStreamSequencerTest::ConsumeData,
+ base::Unretained(this), 3)));
sequencer_->SetUnblocked();
EXPECT_EQ(0u, NumBufferedBytes());
EXPECT_EQ(3u, sequencer_->NumBytesConsumed());
EXPECT_CALL(stream_, OnDataAvailable())
.WillOnce(testing::Invoke(
- CreateFunctor(this, &QuicStreamSequencerTest::ConsumeData, 3)));
+ CreateFunctor(&QuicStreamSequencerTest::ConsumeData,
+ base::Unretained(this), 3)));
EXPECT_FALSE(sequencer_->IsClosed());
OnFinFrame(3, "def");
EXPECT_TRUE(sequencer_->IsClosed());
}
-TEST_P(QuicStreamSequencerTest, BlockedThenFullFrameAndFinConsumed) {
+TEST_F(QuicStreamSequencerTest, BlockedThenFullFrameAndFinConsumed) {
sequencer_->SetBlockedUntilFlush();
OnFinFrame(0, "abc");
@@ -249,7 +229,8 @@ TEST_P(QuicStreamSequencerTest, BlockedThenFullFrameAndFinConsumed) {
EXPECT_CALL(stream_, OnDataAvailable())
.WillOnce(testing::Invoke(
- CreateFunctor(this, &QuicStreamSequencerTest::ConsumeData, 3)));
+ CreateFunctor(&QuicStreamSequencerTest::ConsumeData,
+ base::Unretained(this), 3)));
EXPECT_FALSE(sequencer_->IsClosed());
sequencer_->SetUnblocked();
EXPECT_TRUE(sequencer_->IsClosed());
@@ -257,32 +238,33 @@ TEST_P(QuicStreamSequencerTest, BlockedThenFullFrameAndFinConsumed) {
EXPECT_EQ(3u, sequencer_->NumBytesConsumed());
}
-TEST_P(QuicStreamSequencerTest, EmptyFrame) {
+TEST_F(QuicStreamSequencerTest, EmptyFrame) {
EXPECT_CALL(stream_,
- CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME, _));
+ CloseConnectionWithDetails(QUIC_EMPTY_STREAM_FRAME_NO_FIN, _));
OnFrame(0, "");
EXPECT_EQ(0u, NumBufferedBytes());
EXPECT_EQ(0u, sequencer_->NumBytesConsumed());
}
-TEST_P(QuicStreamSequencerTest, EmptyFinFrame) {
+TEST_F(QuicStreamSequencerTest, EmptyFinFrame) {
EXPECT_CALL(stream_, OnDataAvailable());
OnFinFrame(0, "");
EXPECT_EQ(0u, NumBufferedBytes());
EXPECT_EQ(0u, sequencer_->NumBytesConsumed());
}
-TEST_P(QuicStreamSequencerTest, PartialFrameConsumed) {
+TEST_F(QuicStreamSequencerTest, PartialFrameConsumed) {
EXPECT_CALL(stream_, OnDataAvailable())
.WillOnce(testing::Invoke(
- CreateFunctor(this, &QuicStreamSequencerTest::ConsumeData, 2)));
+ CreateFunctor(&QuicStreamSequencerTest::ConsumeData,
+ base::Unretained(this), 2)));
OnFrame(0, "abc");
EXPECT_EQ(1u, NumBufferedBytes());
EXPECT_EQ(2u, sequencer_->NumBytesConsumed());
}
-TEST_P(QuicStreamSequencerTest, NextxFrameNotConsumed) {
+TEST_F(QuicStreamSequencerTest, NextxFrameNotConsumed) {
EXPECT_CALL(stream_, OnDataAvailable());
OnFrame(0, "abc");
@@ -291,14 +273,14 @@ TEST_P(QuicStreamSequencerTest, NextxFrameNotConsumed) {
EXPECT_EQ(0, sequencer_->num_early_frames_received());
}
-TEST_P(QuicStreamSequencerTest, FutureFrameNotProcessed) {
+TEST_F(QuicStreamSequencerTest, FutureFrameNotProcessed) {
OnFrame(3, "abc");
EXPECT_EQ(3u, NumBufferedBytes());
EXPECT_EQ(0u, sequencer_->NumBytesConsumed());
EXPECT_EQ(1, sequencer_->num_early_frames_received());
}
-TEST_P(QuicStreamSequencerTest, OutOfOrderFrameProcessed) {
+TEST_F(QuicStreamSequencerTest, OutOfOrderFrameProcessed) {
// Buffer the first
OnFrame(6, "ghi");
EXPECT_EQ(3u, NumBufferedBytes());
@@ -312,7 +294,8 @@ TEST_P(QuicStreamSequencerTest, OutOfOrderFrameProcessed) {
EXPECT_CALL(stream_, OnDataAvailable())
.WillOnce(testing::Invoke(
- CreateFunctor(this, &QuicStreamSequencerTest::ConsumeData, 9)));
+ CreateFunctor(&QuicStreamSequencerTest::ConsumeData,
+ base::Unretained(this), 9)));
// Now process all of them at once.
OnFrame(0, "abc");
@@ -322,43 +305,46 @@ TEST_P(QuicStreamSequencerTest, OutOfOrderFrameProcessed) {
EXPECT_EQ(0u, NumBufferedBytes());
}
-TEST_P(QuicStreamSequencerTest, BasicHalfCloseOrdered) {
+TEST_F(QuicStreamSequencerTest, BasicHalfCloseOrdered) {
InSequence s;
EXPECT_CALL(stream_, OnDataAvailable())
.WillOnce(testing::Invoke(
- CreateFunctor(this, &QuicStreamSequencerTest::ConsumeData, 3)));
+ CreateFunctor(&QuicStreamSequencerTest::ConsumeData,
+ base::Unretained(this), 3)));
OnFinFrame(0, "abc");
EXPECT_EQ(3u, QuicStreamSequencerPeer::GetCloseOffset(sequencer_.get()));
}
-TEST_P(QuicStreamSequencerTest, BasicHalfCloseUnorderedWithFlush) {
+TEST_F(QuicStreamSequencerTest, BasicHalfCloseUnorderedWithFlush) {
OnFinFrame(6, "");
EXPECT_EQ(6u, QuicStreamSequencerPeer::GetCloseOffset(sequencer_.get()));
OnFrame(3, "def");
EXPECT_CALL(stream_, OnDataAvailable())
.WillOnce(testing::Invoke(
- CreateFunctor(this, &QuicStreamSequencerTest::ConsumeData, 6)));
+ CreateFunctor(&QuicStreamSequencerTest::ConsumeData,
+ base::Unretained(this), 6)));
EXPECT_FALSE(sequencer_->IsClosed());
OnFrame(0, "abc");
EXPECT_TRUE(sequencer_->IsClosed());
}
-TEST_P(QuicStreamSequencerTest, BasicHalfUnordered) {
+TEST_F(QuicStreamSequencerTest, BasicHalfUnordered) {
OnFinFrame(3, "");
EXPECT_EQ(3u, QuicStreamSequencerPeer::GetCloseOffset(sequencer_.get()));
EXPECT_CALL(stream_, OnDataAvailable())
.WillOnce(testing::Invoke(
- CreateFunctor(this, &QuicStreamSequencerTest::ConsumeData, 3)));
+ CreateFunctor(&QuicStreamSequencerTest::ConsumeData,
+ base::Unretained(this), 3)));
EXPECT_FALSE(sequencer_->IsClosed());
OnFrame(0, "abc");
EXPECT_TRUE(sequencer_->IsClosed());
}
-TEST_P(QuicStreamSequencerTest, TerminateWithReadv) {
+TEST_F(QuicStreamSequencerTest, TerminateWithReadv) {
char buffer[3];
OnFinFrame(3, "");
@@ -375,7 +361,7 @@ TEST_P(QuicStreamSequencerTest, TerminateWithReadv) {
EXPECT_TRUE(sequencer_->IsClosed());
}
-TEST_P(QuicStreamSequencerTest, MutipleOffsets) {
+TEST_F(QuicStreamSequencerTest, MutipleOffsets) {
OnFinFrame(3, "");
EXPECT_EQ(3u, QuicStreamSequencerPeer::GetCloseOffset(sequencer_.get()));
@@ -430,7 +416,7 @@ class QuicSequencerRandomTest : public QuicStreamSequencerTest {
// All frames are processed as soon as we have sequential data.
// Infinite buffering, so all frames are acked right away.
-TEST_P(QuicSequencerRandomTest, RandomFramesNoDroppingNoBackup) {
+TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingNoBackup) {
InSequence s;
EXPECT_CALL(stream_, OnDataAvailable())
.Times(AnyNumber())
@@ -449,7 +435,7 @@ TEST_P(QuicSequencerRandomTest, RandomFramesNoDroppingNoBackup) {
EXPECT_EQ(kPayload, output_);
}
-TEST_P(QuicSequencerRandomTest, RandomFramesNoDroppingBackup) {
+TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingBackup) {
char buffer[10];
iovec iov[2];
iov[0].iov_base = &buffer[0];
@@ -495,7 +481,7 @@ TEST_P(QuicSequencerRandomTest, RandomFramesNoDroppingBackup) {
}
// Same as above, just using a different method for reading.
-TEST_P(QuicStreamSequencerTest, MarkConsumed) {
+TEST_F(QuicStreamSequencerTest, MarkConsumed) {
InSequence s;
EXPECT_CALL(stream_, OnDataAvailable());
@@ -507,24 +493,14 @@ TEST_P(QuicStreamSequencerTest, MarkConsumed) {
EXPECT_EQ(9u, sequencer_->NumBytesBuffered());
// Peek into the data.
- vector<string> expected;
- if (FLAGS_quic_use_stream_sequencer_buffer) {
- expected = vector<string>{"abcdefghi"};
- } else {
- expected = vector<string>{"abc", "def", "ghi"};
- }
+ vector<string> expected = {"abcdefghi"};
ASSERT_TRUE(VerifyReadableRegions(expected));
// Consume 1 byte.
sequencer_->MarkConsumed(1);
EXPECT_EQ(1u, stream_.flow_controller()->bytes_consumed());
// Verify data.
- vector<string> expected2;
- if (FLAGS_quic_use_stream_sequencer_buffer) {
- expected2 = vector<string>{"bcdefghi"};
- } else {
- expected2 = vector<string>{"bc", "def", "ghi"};
- }
+ vector<string> expected2 = {"bcdefghi"};
ASSERT_TRUE(VerifyReadableRegions(expected2));
EXPECT_EQ(8u, sequencer_->NumBytesBuffered());
@@ -532,12 +508,7 @@ TEST_P(QuicStreamSequencerTest, MarkConsumed) {
sequencer_->MarkConsumed(2);
EXPECT_EQ(3u, stream_.flow_controller()->bytes_consumed());
// Verify data.
- vector<string> expected3;
- if (FLAGS_quic_use_stream_sequencer_buffer) {
- expected3 = vector<string>{"defghi"};
- } else {
- expected3 = vector<string>{"def", "ghi"};
- }
+ vector<string> expected3 = {"defghi"};
ASSERT_TRUE(VerifyReadableRegions(expected3));
EXPECT_EQ(6u, sequencer_->NumBytesBuffered());
@@ -550,7 +521,7 @@ TEST_P(QuicStreamSequencerTest, MarkConsumed) {
EXPECT_EQ(1u, sequencer_->NumBytesBuffered());
}
-TEST_P(QuicStreamSequencerTest, MarkConsumedError) {
+TEST_F(QuicStreamSequencerTest, MarkConsumedError) {
EXPECT_CALL(stream_, OnDataAvailable());
OnFrame(0, "abc");
@@ -569,7 +540,7 @@ TEST_P(QuicStreamSequencerTest, MarkConsumedError) {
" expect to consume: 4, but not enough bytes available.");
}
-TEST_P(QuicStreamSequencerTest, MarkConsumedWithMissingPacket) {
+TEST_F(QuicStreamSequencerTest, MarkConsumedWithMissingPacket) {
InSequence s;
EXPECT_CALL(stream_, OnDataAvailable());
@@ -578,66 +549,13 @@ TEST_P(QuicStreamSequencerTest, MarkConsumedWithMissingPacket) {
// Missing packet: 6, ghi.
OnFrame(9, "jkl");
- vector<string> expected;
- if (FLAGS_quic_use_stream_sequencer_buffer) {
- expected = vector<string>{"abcdef"};
- } else {
- expected = vector<string>{"abc", "def"};
- }
+ vector<string> expected = {"abcdef"};
ASSERT_TRUE(VerifyReadableRegions(expected));
sequencer_->MarkConsumed(6);
}
-TEST(QuicFrameListTest, FrameOverlapsBufferedData) {
- QuicFrameList buffer;
-
- // Ensure that FrameOverlapsBufferedData returns appropriate responses when
- // there is existing data buffered.
- const int kBufferedOffset = 10;
- const int kBufferedDataLength = 3;
- const int kNewDataLength = 3;
- string data(kNewDataLength, '.');
-
- // No overlap if no buffered frames.
- EXPECT_EQ(0u, buffer.BytesBuffered());
- size_t bytes_written;
- // Add a buffered frame.
- buffer.OnStreamData(
- kBufferedOffset,
- StringPiece(string(kBufferedDataLength, '.').data(), kBufferedDataLength),
- QuicTime::Zero(), &bytes_written);
-
- // New byte range partially overlaps with buffered frame, start offset
- // preceding buffered frame.
- EXPECT_TRUE(QuicStreamSequencerPeer::FrameOverlapsBufferedData(
- &buffer, QuicStreamFrame(1, false, kBufferedOffset - 1, data)));
- EXPECT_TRUE(QuicStreamSequencerPeer::FrameOverlapsBufferedData(
- &buffer,
- QuicStreamFrame(1, false, kBufferedOffset - kNewDataLength + 1, data)));
-
- // New byte range partially overlaps with buffered frame, start offset inside
- // existing buffered frame.
- EXPECT_TRUE(QuicStreamSequencerPeer::FrameOverlapsBufferedData(
- &buffer, QuicStreamFrame(1, false, kBufferedOffset + 1, data)));
- EXPECT_TRUE(QuicStreamSequencerPeer::FrameOverlapsBufferedData(
- &buffer, QuicStreamFrame(
- 1, false, kBufferedOffset + kBufferedDataLength - 1, data)));
-
- // New byte range entirely outside of buffered frames, start offset
- // preceeding buffered frame.
- EXPECT_FALSE(QuicStreamSequencerPeer::FrameOverlapsBufferedData(
- &buffer,
- QuicStreamFrame(1, false, kBufferedOffset - kNewDataLength, data)));
-
- // New byte range entirely outside of buffered frames, start offset later than
- // buffered frame.
- EXPECT_FALSE(QuicStreamSequencerPeer::FrameOverlapsBufferedData(
- &buffer,
- QuicStreamFrame(1, false, kBufferedOffset + kBufferedDataLength, data)));
-}
-
-TEST_P(QuicStreamSequencerTest, DontAcceptOverlappingFrames) {
+TEST_F(QuicStreamSequencerTest, DontAcceptOverlappingFrames) {
// The peer should never send us non-identical stream frames which contain
// overlapping byte ranges - if they do, we close the connection.
@@ -645,12 +563,16 @@ TEST_P(QuicStreamSequencerTest, DontAcceptOverlappingFrames) {
sequencer_->OnStreamFrame(frame1);
QuicStreamFrame frame2(kClientDataStreamId1, false, 2, StringPiece("hello"));
- EXPECT_CALL(stream_, CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME, _))
+ EXPECT_CALL(stream_, CloseConnectionWithDetails(
+ FLAGS_quic_consolidate_onstreamframe_errors
+ ? QUIC_OVERLAPPING_STREAM_DATA
+ : QUIC_EMPTY_STREAM_FRAME_NO_FIN,
+ _))
.Times(1);
sequencer_->OnStreamFrame(frame2);
}
-TEST_P(QuicStreamSequencerTest, InOrderTimestamps) {
+TEST_F(QuicStreamSequencerTest, InOrderTimestamps) {
// This test verifies that timestamps returned by
// GetReadableRegion() are in the correct sequence when frames
// arrive at the sequencer in order.
@@ -691,7 +613,7 @@ TEST_P(QuicStreamSequencerTest, InOrderTimestamps) {
EXPECT_EQ(0u, sequencer_->NumBytesBuffered());
}
-TEST_P(QuicStreamSequencerTest, OutOfOrderTimestamps) {
+TEST_F(QuicStreamSequencerTest, OutOfOrderTimestamps) {
// This test verifies that timestamps returned by
// GetReadableRegion() are in the correct sequence when frames
// arrive at the sequencer out of order.
diff --git a/chromium/net/quic/quic_unacked_packet_map.cc b/chromium/net/quic/quic_unacked_packet_map.cc
index 6beb9bc667f..fc72388d0cc 100644
--- a/chromium/net/quic/quic_unacked_packet_map.cc
+++ b/chromium/net/quic/quic_unacked_packet_map.cc
@@ -5,9 +5,11 @@
#include "net/quic/quic_unacked_packet_map.h"
#include "base/logging.h"
+#include "base/stl_util.h"
#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_connection_stats.h"
#include "net/quic/quic_flags.h"
+#include "net/quic/quic_utils.h"
#include "net/quic/quic_utils_chromium.h"
using std::max;
@@ -19,19 +21,13 @@ QuicUnackedPacketMap::QuicUnackedPacketMap()
largest_observed_(0),
least_unacked_(1),
bytes_in_flight_(0),
- pending_crypto_packet_count_(0),
- track_single_retransmission_(FLAGS_quic_track_single_retransmission) {}
+ pending_crypto_packet_count_(0) {}
QuicUnackedPacketMap::~QuicUnackedPacketMap() {
QuicPacketNumber index = least_unacked_;
for (UnackedPacketMap::iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++index) {
- delete it->retransmittable_frames;
- // Only delete all_transmissions once, for the newest packet.
- if (it->all_transmissions != nullptr &&
- index == *it->all_transmissions->rbegin()) {
- delete it->all_transmissions;
- }
+ QuicUtils::DeleteFrames(&it->retransmittable_frames);
}
}
@@ -39,20 +35,21 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,
QuicPacketNumber old_packet_number,
TransmissionType transmission_type,
QuicTime sent_time,
- QuicByteCount bytes_sent,
bool set_in_flight) {
QuicPacketNumber packet_number = packet->packet_number;
- LOG_IF(DFATAL, largest_sent_packet_ >= packet_number) << packet_number;
+ QuicPacketLength bytes_sent = packet->encrypted_length;
+ 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_.back().is_unackable = true;
}
- TransmissionInfo info(packet->retransmittable_frames,
- packet->encryption_level, packet->packet_number_length,
+ 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,
- packet->is_fec_packet);
+ has_crypto_handshake, packet->needs_padding);
if (old_packet_number > 0) {
TransferRetransmissionInfo(old_packet_number, packet_number,
transmission_type, &info);
@@ -64,13 +61,15 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,
info.in_flight = true;
}
unacked_packets_.push_back(info);
- // Swap the ack listeners after to avoid an extra list allocation.
+ // Swap the ack listeners and retransmittable frames to avoid allocations.
// TODO(ianswett): Could use emplace_back when Chromium can.
if (old_packet_number == 0) {
- if (packet->retransmittable_frames != nullptr &&
- packet->retransmittable_frames->HasCryptoHandshake() == IS_HANDSHAKE) {
+ if (has_crypto_handshake) {
++pending_crypto_packet_count_;
}
+
+ packet->retransmittable_frames.swap(
+ unacked_packets_.back().retransmittable_frames);
unacked_packets_.back().ack_listeners.swap(packet->listeners);
}
}
@@ -103,56 +102,30 @@ void QuicUnackedPacketMap::TransferRetransmissionInfo(
TransmissionInfo* transmission_info =
&unacked_packets_.at(old_packet_number - least_unacked_);
- RetransmittableFrames* frames = transmission_info->retransmittable_frames;
- transmission_info->retransmittable_frames = nullptr;
+ QuicFrames* frames = &transmission_info->retransmittable_frames;
for (AckListenerWrapper& wrapper : transmission_info->ack_listeners) {
wrapper.ack_listener->OnPacketRetransmitted(wrapper.length);
}
+
+ // Swap the frames and preserve needs_padding and has_crypto_handshake.
+ frames->swap(info->retransmittable_frames);
+ info->has_crypto_handshake = transmission_info->has_crypto_handshake;
+ transmission_info->has_crypto_handshake = false;
+ info->needs_padding = transmission_info->needs_padding;
+
// Transfer the AckListeners if any are present.
info->ack_listeners.swap(transmission_info->ack_listeners);
- LOG_IF(DFATAL, frames == nullptr)
+ QUIC_BUG_IF(frames == nullptr)
<< "Attempt to retransmit packet with no "
<< "retransmittable frames: " << old_packet_number;
- // Only keep one transmission older than largest observed, because only the
- // most recent is expected to possibly be a spurious retransmission.
- if (!track_single_retransmission_) {
- while (transmission_info->all_transmissions != nullptr &&
- transmission_info->all_transmissions->size() > 1 &&
- *(++transmission_info->all_transmissions->begin()) <
- largest_observed_) {
- QuicPacketNumber old_transmission =
- *transmission_info->all_transmissions->begin();
- TransmissionInfo* old_info =
- &unacked_packets_[old_transmission - least_unacked_];
- // Don't remove old packets if they're still in flight.
- if (old_info->in_flight) {
- break;
- }
- old_info->all_transmissions->pop_front();
- // This will cause the packet be removed in RemoveObsoletePackets.
- old_info->all_transmissions = nullptr;
- }
- }
// Don't link old transmissions to new ones when version or
// encryption changes.
if (transmission_type == ALL_INITIAL_RETRANSMISSION ||
transmission_type == ALL_UNACKED_RETRANSMISSION) {
RemoveAckability(transmission_info);
} else {
- if (track_single_retransmission_) {
- transmission_info->retransmission = new_packet_number;
- } else {
- if (transmission_info->all_transmissions == nullptr) {
- transmission_info->all_transmissions = new PacketNumberList();
- transmission_info->all_transmissions->push_back(old_packet_number);
- }
- transmission_info->all_transmissions->push_back(new_packet_number);
- }
- }
- info->retransmittable_frames = frames;
- if (!track_single_retransmission_) {
- info->all_transmissions = transmission_info->all_transmissions;
+ transmission_info->retransmission = new_packet_number;
}
// Proactively remove obsolete packets so the least unacked can be raised.
RemoveObsoletePackets();
@@ -162,8 +135,8 @@ bool QuicUnackedPacketMap::HasRetransmittableFrames(
QuicPacketNumber packet_number) const {
DCHECK_GE(packet_number, least_unacked_);
DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
- return unacked_packets_[packet_number - least_unacked_]
- .retransmittable_frames != nullptr;
+ return !unacked_packets_[packet_number - least_unacked_]
+ .retransmittable_frames.empty();
}
void QuicUnackedPacketMap::NackPacket(QuicPacketNumber packet_number,
@@ -175,29 +148,12 @@ void QuicUnackedPacketMap::NackPacket(QuicPacketNumber packet_number,
}
void QuicUnackedPacketMap::RemoveRetransmittability(TransmissionInfo* info) {
- if (track_single_retransmission_) {
- while (info->retransmission != 0) {
- const QuicPacketNumber retransmission = info->retransmission;
- info->retransmission = 0;
- info = &unacked_packets_[retransmission - least_unacked_];
- }
- MaybeRemoveRetransmittableFrames(info);
- return;
- }
- PacketNumberList* all_transmissions = info->all_transmissions;
- if (all_transmissions == nullptr) {
- MaybeRemoveRetransmittableFrames(info);
- return;
- }
- // TODO(ianswett): Consider adding a check to ensure there are retransmittable
- // frames associated with this packet.
- for (QuicPacketNumber packet_number : *all_transmissions) {
- TransmissionInfo* transmission_info =
- &unacked_packets_[packet_number - least_unacked_];
- MaybeRemoveRetransmittableFrames(transmission_info);
- transmission_info->all_transmissions = nullptr;
+ while (info->retransmission != 0) {
+ const QuicPacketNumber retransmission = info->retransmission;
+ info->retransmission = 0;
+ info = &unacked_packets_[retransmission - least_unacked_];
}
- delete all_transmissions;
+ MaybeRemoveRetransmittableFrames(info);
}
void QuicUnackedPacketMap::RemoveRetransmittability(
@@ -209,36 +165,20 @@ void QuicUnackedPacketMap::RemoveRetransmittability(
}
void QuicUnackedPacketMap::RemoveAckability(TransmissionInfo* info) {
- DCHECK(info->retransmittable_frames == nullptr);
+ DCHECK(info->retransmittable_frames.empty());
+ DCHECK_EQ(0u, info->retransmission);
info->is_unackable = true;
- if (track_single_retransmission_) {
- DCHECK_EQ(0u, info->retransmission);
- return;
- }
- PacketNumberList* all_transmissions = info->all_transmissions;
- if (all_transmissions == nullptr) {
- return;
- }
- for (QuicPacketNumber packet_number : *all_transmissions) {
- TransmissionInfo* transmission_info =
- &unacked_packets_[packet_number - least_unacked_];
- transmission_info->all_transmissions = nullptr;
- transmission_info->is_unackable = true;
- }
- delete all_transmissions;
}
void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames(
TransmissionInfo* transmission_info) {
- if (transmission_info->retransmittable_frames == nullptr) {
- return;
- }
- if (transmission_info->retransmittable_frames->HasCryptoHandshake() ==
- IS_HANDSHAKE) {
+ 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;
}
- delete transmission_info->retransmittable_frames;
- transmission_info->retransmittable_frames = nullptr;
+ QuicUtils::DeleteFrames(&transmission_info->retransmittable_frames);
}
void QuicUnackedPacketMap::IncreaseLargestObserved(
@@ -265,8 +205,7 @@ bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData(
const TransmissionInfo& info) const {
// Packet may have retransmittable frames, or the data may have been
// retransmitted with a new packet number.
- return info.retransmittable_frames != nullptr ||
- info.all_transmissions != nullptr ||
+ return !info.retransmittable_frames.empty() ||
// Allow for an extra 1 RTT before stopping to track old packets.
info.retransmission > largest_observed_;
}
@@ -289,25 +228,25 @@ bool QuicUnackedPacketMap::IsUnacked(QuicPacketNumber packet_number) const {
void QuicUnackedPacketMap::NotifyAndClearListeners(
std::list<AckListenerWrapper>* ack_listeners,
- QuicTime::Delta delta_largest_observed) {
+ QuicTime::Delta ack_delay_time) {
for (const AckListenerWrapper& wrapper : *ack_listeners) {
- wrapper.ack_listener->OnPacketAcked(wrapper.length, delta_largest_observed);
+ wrapper.ack_listener->OnPacketAcked(wrapper.length, ack_delay_time);
}
ack_listeners->clear();
}
void QuicUnackedPacketMap::NotifyAndClearListeners(
QuicPacketNumber packet_number,
- QuicTime::Delta delta_largest_observed) {
+ 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_];
- NotifyAndClearListeners(&info->ack_listeners, delta_largest_observed);
+ NotifyAndClearListeners(&info->ack_listeners, ack_delay_time);
}
void QuicUnackedPacketMap::RemoveFromInFlight(TransmissionInfo* info) {
if (info->in_flight) {
- LOG_IF(DFATAL, bytes_in_flight_ < info->bytes_sent);
+ QUIC_BUG_IF(bytes_in_flight_ < info->bytes_sent);
bytes_in_flight_ -= info->bytes_sent;
info->in_flight = false;
}
@@ -323,14 +262,14 @@ void QuicUnackedPacketMap::RemoveFromInFlight(QuicPacketNumber packet_number) {
void QuicUnackedPacketMap::CancelRetransmissionsForStream(
QuicStreamId stream_id) {
QuicPacketNumber packet_number = least_unacked_;
- for (UnackedPacketMap::const_iterator it = unacked_packets_.begin();
+ for (UnackedPacketMap::iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
- RetransmittableFrames* retransmittable_frames = it->retransmittable_frames;
- if (retransmittable_frames == nullptr) {
+ QuicFrames* frames = &it->retransmittable_frames;
+ if (frames->empty()) {
continue;
}
- retransmittable_frames->RemoveFramesForStream(stream_id);
- if (retransmittable_frames->frames().empty()) {
+ QuicUtils::RemoveFramesForStream(frames, stream_id);
+ if (frames->empty()) {
RemoveRetransmittability(packet_number);
}
}
@@ -349,11 +288,16 @@ const TransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo(
return unacked_packets_[packet_number - least_unacked_];
}
+TransmissionInfo* QuicUnackedPacketMap::GetMutableTransmissionInfo(
+ QuicPacketNumber packet_number) {
+ return &unacked_packets_[packet_number - least_unacked_];
+}
+
QuicTime QuicUnackedPacketMap::GetLastPacketSentTime() const {
UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin();
while (it != unacked_packets_.rend()) {
if (it->in_flight) {
- LOG_IF(DFATAL, it->sent_time == QuicTime::Zero())
+ QUIC_BUG_IF(it->sent_time == QuicTime::Zero())
<< "Sent time can never be zero for a packet in flight.";
return it->sent_time;
}
@@ -399,7 +343,7 @@ bool QuicUnackedPacketMap::HasPendingCryptoPackets() const {
bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const {
for (UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin();
it != unacked_packets_.rend(); ++it) {
- if (it->in_flight && it->retransmittable_frames) {
+ if (it->in_flight && !it->retransmittable_frames.empty()) {
return true;
}
}
diff --git a/chromium/net/quic/quic_unacked_packet_map.h b/chromium/net/quic/quic_unacked_packet_map.h
index 51cd03e68e0..31fc7f43008 100644
--- a/chromium/net/quic/quic_unacked_packet_map.h
+++ b/chromium/net/quic/quic_unacked_packet_map.h
@@ -37,7 +37,6 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
QuicPacketNumber old_packet_number,
TransmissionType transmission_type,
QuicTime sent_time,
- QuicByteCount bytes_sent,
bool set_in_flight);
// Returns true if the packet |packet_number| is unacked.
@@ -85,10 +84,6 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
// Returns the largest packet number that has been acked.
QuicPacketNumber largest_observed() const { return largest_observed_; }
- bool track_single_retransmission() const {
- return track_single_retransmission_;
- }
-
// Returns the sum of bytes from all packets in flight.
QuicByteCount bytes_in_flight() const { return bytes_in_flight_; }
@@ -114,6 +109,10 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
const TransmissionInfo& GetTransmissionInfo(
QuicPacketNumber packet_number) const;
+ // Returns mutable TransmissionInfo associated with |packet_number|, which
+ // must be unacked.
+ TransmissionInfo* GetMutableTransmissionInfo(QuicPacketNumber packet_number);
+
// Returns the time that the last unacked packet was sent.
QuicTime GetLastPacketSentTime() const;
@@ -176,8 +175,8 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
QuicPacketNumber largest_sent_packet_;
QuicPacketNumber largest_observed_;
- // Newly serialized retransmittable and fec packets are added to this map,
- // which contains owning pointers to any contained frames. If a packet is
+ // Newly serialized retransmittable packets are added to this map, which
+ // contains owning pointers to any contained frames. If a packet is
// retransmitted, this map will contain entries for both the old and the new
// packet. The old packet's retransmittable frames entry will be nullptr,
// while the new packet's entry will contain the frames to retransmit.
@@ -192,9 +191,6 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap {
// Number of retransmittable crypto handshake packets.
size_t pending_crypto_packet_count_;
- // Latched copy of gfe2_reloadable_flag_quic_track_single_retransmission.
- const bool track_single_retransmission_;
-
DISALLOW_COPY_AND_ASSIGN(QuicUnackedPacketMap);
};
diff --git a/chromium/net/quic/quic_unacked_packet_map_test.cc b/chromium/net/quic/quic_unacked_packet_map_test.cc
index 1adc819e5f6..26a00435374 100644
--- a/chromium/net/quic/quic_unacked_packet_map_test.cc
+++ b/chromium/net/quic/quic_unacked_packet_map_test.cc
@@ -18,7 +18,6 @@ namespace test {
namespace {
// Default packet length.
-const uint32_t kDefaultAckLength = 50;
const uint32_t kDefaultLength = 1000;
class QuicUnackedPacketMapTest : public ::testing::Test {
@@ -37,22 +36,20 @@ class QuicUnackedPacketMapTest : public ::testing::Test {
SerializedPacket CreateRetransmittablePacketForStream(
QuicPacketNumber packet_number,
QuicStreamId stream_id) {
- packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
- RetransmittableFrames* frames = new RetransmittableFrames();
+ SerializedPacket packet(kDefaultPathId, packet_number,
+ PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
+ 0, false, false);
QuicStreamFrame* frame = new QuicStreamFrame();
frame->stream_id = stream_id;
- frames->AddFrame(QuicFrame(frame));
- return SerializedPacket(kDefaultPathId, packet_number,
- PACKET_1BYTE_PACKET_NUMBER, packets_.back(), 0,
- frames, false, false);
+ packet.retransmittable_frames.push_back(QuicFrame(frame));
+ return packet;
}
SerializedPacket CreateNonRetransmittablePacket(
QuicPacketNumber packet_number) {
- packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
return SerializedPacket(kDefaultPathId, packet_number,
- PACKET_1BYTE_PACKET_NUMBER, packets_.back(), 0,
- nullptr, false, false);
+ PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
+ 0, false, false);
}
void VerifyInFlightPackets(QuicPacketNumber* packets, size_t num_packets) {
@@ -102,7 +99,7 @@ class QuicUnackedPacketMapTest : public ::testing::Test {
size_t num_retransmittable_packets = 0;
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it) {
- if (it->retransmittable_frames != nullptr) {
+ if (!it->retransmittable_frames.empty()) {
++num_retransmittable_packets;
}
}
@@ -120,8 +117,7 @@ class QuicUnackedPacketMapTest : public ::testing::Test {
TEST_F(QuicUnackedPacketMapTest, RttOnly) {
// Acks are only tracked for RTT measurement purposes.
SerializedPacket packet(CreateNonRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_,
- kDefaultAckLength, false);
+ unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_, false);
QuicPacketNumber unacked[] = {1};
VerifyUnackedPackets(unacked, arraysize(unacked));
@@ -137,8 +133,7 @@ TEST_F(QuicUnackedPacketMapTest, RttOnly) {
TEST_F(QuicUnackedPacketMapTest, RetransmittableInflightAndRtt) {
// Simulate a retransmittable packet being sent and acked.
SerializedPacket packet(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_, true);
QuicPacketNumber unacked[] = {1};
VerifyUnackedPackets(unacked, arraysize(unacked));
@@ -164,8 +159,7 @@ TEST_F(QuicUnackedPacketMapTest, RetransmittableInflightAndRtt) {
TEST_F(QuicUnackedPacketMapTest, StopRetransmission) {
const QuicStreamId stream_id = 2;
SerializedPacket packet(CreateRetransmittablePacketForStream(1, stream_id));
- unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_, true);
QuicPacketNumber unacked[] = {1};
VerifyUnackedPackets(unacked, arraysize(unacked));
@@ -182,8 +176,7 @@ TEST_F(QuicUnackedPacketMapTest, StopRetransmission) {
TEST_F(QuicUnackedPacketMapTest, StopRetransmissionOnOtherStream) {
const QuicStreamId stream_id = 2;
SerializedPacket packet(CreateRetransmittablePacketForStream(1, stream_id));
- unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_, true);
QuicPacketNumber unacked[] = {1};
VerifyUnackedPackets(unacked, arraysize(unacked));
@@ -201,11 +194,9 @@ TEST_F(QuicUnackedPacketMapTest, StopRetransmissionOnOtherStream) {
TEST_F(QuicUnackedPacketMapTest, StopRetransmissionAfterRetransmission) {
const QuicStreamId stream_id = 2;
SerializedPacket packet1(CreateRetransmittablePacketForStream(1, stream_id));
- unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true);
SerializedPacket packet2(CreateNonRetransmittablePacket(2));
- unacked_packets_.AddSentPacket(&packet2, 1, LOSS_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet2, 1, LOSS_RETRANSMISSION, now_, true);
QuicPacketNumber unacked[] = {1, 2};
VerifyUnackedPackets(unacked, arraysize(unacked));
@@ -223,11 +214,9 @@ TEST_F(QuicUnackedPacketMapTest, RetransmittedPacket) {
// Simulate a retransmittable packet being sent, retransmitted, and the first
// transmission being acked.
SerializedPacket packet1(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true);
SerializedPacket packet2(CreateNonRetransmittablePacket(2));
- unacked_packets_.AddSentPacket(&packet2, 1, LOSS_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet2, 1, LOSS_RETRANSMISSION, now_, true);
QuicPacketNumber unacked[] = {1, 2};
VerifyUnackedPackets(unacked, arraysize(unacked));
@@ -260,11 +249,9 @@ TEST_F(QuicUnackedPacketMapTest, RetransmittedPacket) {
TEST_F(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
// Simulate a retransmittable packet being sent and retransmitted twice.
SerializedPacket packet1(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true);
SerializedPacket packet2(CreateRetransmittablePacket(2));
- unacked_packets_.AddSentPacket(&packet2, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet2, 0, NOT_RETRANSMISSION, now_, true);
QuicPacketNumber unacked[] = {1, 2};
VerifyUnackedPackets(unacked, arraysize(unacked));
@@ -278,11 +265,9 @@ TEST_F(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
unacked_packets_.RemoveRetransmittability(2);
unacked_packets_.RemoveFromInFlight(1);
SerializedPacket packet3(CreateNonRetransmittablePacket(3));
- unacked_packets_.AddSentPacket(&packet3, 1, LOSS_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet3, 1, LOSS_RETRANSMISSION, now_, true);
SerializedPacket packet4(CreateRetransmittablePacket(4));
- unacked_packets_.AddSentPacket(&packet4, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet4, 0, NOT_RETRANSMISSION, now_, true);
QuicPacketNumber unacked2[] = {1, 3, 4};
VerifyUnackedPackets(unacked2, arraysize(unacked2));
@@ -296,11 +281,9 @@ TEST_F(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
unacked_packets_.RemoveFromInFlight(4);
unacked_packets_.RemoveRetransmittability(4);
SerializedPacket packet5(CreateNonRetransmittablePacket(5));
- unacked_packets_.AddSentPacket(&packet5, 3, LOSS_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet5, 3, LOSS_RETRANSMISSION, now_, true);
SerializedPacket packet6(CreateRetransmittablePacket(6));
- unacked_packets_.AddSentPacket(&packet6, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet6, 0, NOT_RETRANSMISSION, now_, true);
QuicPacketNumber unacked3[] = {3, 5, 6};
VerifyUnackedPackets(unacked3, arraysize(unacked3));
@@ -314,8 +297,7 @@ TEST_F(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
unacked_packets_.RemoveFromInFlight(6);
unacked_packets_.RemoveRetransmittability(6);
SerializedPacket packet7(CreateNonRetransmittablePacket(7));
- unacked_packets_.AddSentPacket(&packet7, 5, LOSS_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet7, 5, LOSS_RETRANSMISSION, now_, true);
QuicPacketNumber unacked4[] = {3, 5, 7};
VerifyUnackedPackets(unacked4, arraysize(unacked4));
@@ -334,11 +316,9 @@ TEST_F(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
TEST_F(QuicUnackedPacketMapTest, RetransmitFourTimes) {
// Simulate a retransmittable packet being sent and retransmitted twice.
SerializedPacket packet1(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true);
SerializedPacket packet2(CreateRetransmittablePacket(2));
- unacked_packets_.AddSentPacket(&packet2, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet2, 0, NOT_RETRANSMISSION, now_, true);
QuicPacketNumber unacked[] = {1, 2};
VerifyUnackedPackets(unacked, arraysize(unacked));
@@ -352,8 +332,7 @@ TEST_F(QuicUnackedPacketMapTest, RetransmitFourTimes) {
unacked_packets_.RemoveRetransmittability(2);
unacked_packets_.RemoveFromInFlight(1);
SerializedPacket packet3(CreateNonRetransmittablePacket(3));
- unacked_packets_.AddSentPacket(&packet3, 1, LOSS_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet3, 1, LOSS_RETRANSMISSION, now_, true);
QuicPacketNumber unacked2[] = {1, 3};
VerifyUnackedPackets(unacked2, arraysize(unacked2));
@@ -364,11 +343,9 @@ TEST_F(QuicUnackedPacketMapTest, RetransmitFourTimes) {
// TLP 3 (formerly 1) as 4, and don't remove 1 from unacked.
SerializedPacket packet4(CreateNonRetransmittablePacket(4));
- unacked_packets_.AddSentPacket(&packet4, 3, TLP_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet4, 3, TLP_RETRANSMISSION, now_, true);
SerializedPacket packet5(CreateRetransmittablePacket(5));
- unacked_packets_.AddSentPacket(&packet5, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet5, 0, NOT_RETRANSMISSION, now_, true);
QuicPacketNumber unacked3[] = {1, 3, 4, 5};
VerifyUnackedPackets(unacked3, arraysize(unacked3));
@@ -384,8 +361,7 @@ TEST_F(QuicUnackedPacketMapTest, RetransmitFourTimes) {
unacked_packets_.RemoveFromInFlight(3);
unacked_packets_.RemoveFromInFlight(4);
SerializedPacket packet6(CreateNonRetransmittablePacket(6));
- unacked_packets_.AddSentPacket(&packet6, 4, LOSS_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet6, 4, LOSS_RETRANSMISSION, now_, true);
QuicPacketNumber unacked4[] = {4, 6};
VerifyUnackedPackets(unacked4, arraysize(unacked4));
@@ -399,14 +375,11 @@ TEST_F(QuicUnackedPacketMapTest, SendWithGap) {
// Simulate a retransmittable packet being sent, retransmitted, and the first
// transmission being acked.
SerializedPacket packet1(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true);
SerializedPacket packet3(CreateRetransmittablePacket(3));
- unacked_packets_.AddSentPacket(&packet3, 0, NOT_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet3, 0, NOT_RETRANSMISSION, now_, true);
SerializedPacket packet5(CreateNonRetransmittablePacket(5));
- unacked_packets_.AddSentPacket(&packet5, 3, LOSS_RETRANSMISSION, now_,
- kDefaultLength, true);
+ unacked_packets_.AddSentPacket(&packet5, 3, LOSS_RETRANSMISSION, now_, true);
EXPECT_EQ(1u, unacked_packets_.GetLeastUnacked());
EXPECT_TRUE(unacked_packets_.IsUnacked(1));
diff --git a/chromium/net/quic/quic_utils.cc b/chromium/net/quic/quic_utils.cc
index 8781afbdcf0..dffdc14ca69 100644
--- a/chromium/net/quic/quic_utils.cc
+++ b/chromium/net/quic/quic_utils.cc
@@ -15,6 +15,7 @@
#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/quic_flags.h"
#include "net/quic/quic_write_blocked_list.h"
@@ -55,6 +56,8 @@ uint128 IncrementalHashFast(uint128 uhash, const char* data, size_t len) {
}
#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) {
// kPrime = 309485009821345068724781371
static const uint128 kPrime(16777216, 315);
@@ -65,17 +68,21 @@ uint128 IncrementalHashSlow(uint128 hash, const char* data, size_t len) {
}
return hash;
}
+#endif
uint128 IncrementalHash(uint128 hash, const char* data, size_t len) {
#ifdef QUIC_UTIL_HAS_UINT128
- return FLAGS_quic_utils_use_fast_incremental_hash
- ? IncrementalHashFast(hash, data, len)
- : IncrementalHashSlow(hash, data, len);
+ return IncrementalHashFast(hash, data, len);
#else
return IncrementalHashSlow(hash, data, len);
#endif
}
+bool IsInitializedIPEndPoint(const IPEndPoint& address) {
+ return net::GetAddressFamily(address.address().bytes()) !=
+ net::ADDRESS_FAMILY_UNSPECIFIED;
+}
+
} // namespace
// static
@@ -191,6 +198,11 @@ const char* QuicUtils::StreamErrorToString(QuicRstStreamErrorCode error) {
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 a default value so that we return this when |error| doesn't match
// any of the QuicRstStreamErrorCodes. This can happen when the RstStream
@@ -209,6 +221,7 @@ const char* QuicUtils::ErrorToString(QuicErrorCode error) {
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);
@@ -216,6 +229,7 @@ const char* QuicUtils::ErrorToString(QuicErrorCode error) {
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);
@@ -246,12 +260,13 @@ const char* QuicUtils::ErrorToString(QuicErrorCode error) {
RETURN_STRING_LITERAL(QUIC_INVALID_HEADER_ID);
RETURN_STRING_LITERAL(QUIC_INVALID_NEGOTIATED_VALUE);
RETURN_STRING_LITERAL(QUIC_DECOMPRESSION_FAILURE);
- RETURN_STRING_LITERAL(QUIC_CONNECTION_TIMED_OUT);
- RETURN_STRING_LITERAL(QUIC_CONNECTION_OVERALL_TIMED_OUT);
+ 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_INVALID_STREAM_FRAME);
+ 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);
@@ -275,10 +290,14 @@ const char* QuicUtils::ErrorToString(QuicErrorCode error) {
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_LAST_ERROR);
// Intentionally have no default case, so we'll break the build
// if we add errors and don't put them here.
@@ -391,4 +410,125 @@ string QuicUtils::StringToHexASCIIDump(StringPiece in_buffer) {
return s;
}
+// 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
+ // specific sizes.
+ static_assert(sizeof(path_id) == 1, "Size of QuicPathId changed.");
+ static_assert(sizeof(packet_number) == 8,
+ "Size of QuicPacketNumber changed.");
+ // Use path_id and lower 7 bytes of packet_number as lower 8 bytes of nonce.
+ uint64_t path_id_packet_number =
+ (static_cast<uint64_t>(path_id) << 56) | packet_number;
+ DCHECK(path_id != kDefaultPathId || path_id_packet_number == packet_number);
+ return path_id_packet_number;
+}
+
+// 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) {
+ return NO_CHANGE;
+ }
+
+ if (old_address.address() == new_address.address()) {
+ return PORT_CHANGE;
+ }
+
+ bool old_ip_is_ipv4 = old_address.address().IsIPv4();
+ bool migrating_ip_is_ipv4 = new_address.address().IsIPv4();
+ if (old_ip_is_ipv4 && !migrating_ip_is_ipv4) {
+ return IPV4_TO_IPV6_CHANGE;
+ }
+
+ if (!old_ip_is_ipv4) {
+ return migrating_ip_is_ipv4 ? IPV6_TO_IPV4_CHANGE : IPV6_TO_IPV6_CHANGE;
+ }
+
+ if (IPAddressMatchesPrefix(old_address.address(), new_address.address(),
+ 24)) {
+ // Subnet part does not change (here, we use /24), which is considered to be
+ // caused by NATs.
+ return IPV4_SUBNET_CHANGE;
+ }
+
+ return UNSPECIFIED_CHANGE;
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_utils.h b/chromium/net/quic/quic_utils.h
index 35b675c63ec..5af98c40ee6 100644
--- a/chromium/net/quic/quic_utils.h
+++ b/chromium/net/quic/quic_utils.h
@@ -18,6 +18,16 @@
#include "net/base/net_export.h"
#include "net/quic/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
+
namespace net {
class NET_EXPORT_PRIVATE QuicUtils {
@@ -95,6 +105,31 @@ class NET_EXPORT_PRIVATE QuicUtils {
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);
+
private:
DISALLOW_COPY_AND_ASSIGN(QuicUtils);
};
diff --git a/chromium/net/quic/quic_utils_test.cc b/chromium/net/quic/quic_utils_test.cc
index 2c4aacb37d7..7412a24052d 100644
--- a/chromium/net/quic/quic_utils_test.cc
+++ b/chromium/net/quic/quic_utils_test.cc
@@ -100,6 +100,65 @@ TEST(QuicUtilsTest, ParseQuicConnectionOptions) {
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;
+
+ EXPECT_EQ(NO_CHANGE,
+ QuicUtils::DetermineAddressChangeType(old_address, new_address));
+ ASSERT_TRUE(address.AssignFromIPLiteral(kIPv4String1));
+ old_address = IPEndPoint(address, 1234);
+ EXPECT_EQ(NO_CHANGE,
+ QuicUtils::DetermineAddressChangeType(old_address, new_address));
+ new_address = IPEndPoint(address, 1234);
+ EXPECT_EQ(NO_CHANGE,
+ QuicUtils::DetermineAddressChangeType(old_address, new_address));
+
+ new_address = IPEndPoint(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);
+ 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);
+ 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);
+ EXPECT_EQ(IPV6_TO_IPV4_CHANGE,
+ QuicUtils::DetermineAddressChangeType(old_address, new_address));
+
+ ASSERT_TRUE(address.AssignFromIPLiteral(kIPv6String2));
+ new_address = IPEndPoint(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);
+ EXPECT_EQ(IPV4_SUBNET_CHANGE,
+ QuicUtils::DetermineAddressChangeType(old_address, new_address));
+ ASSERT_TRUE(address.AssignFromIPLiteral(kIPv4String3));
+ new_address = IPEndPoint(address, 1234);
+ EXPECT_EQ(UNSPECIFIED_CHANGE,
+ QuicUtils::DetermineAddressChangeType(old_address, new_address));
+}
+
uint128 IncrementalHashReference(const void* data, size_t len) {
// The two constants are defined as part of the hash algorithm.
// see http://www.isthe.com/chongo/tech/comp/fnv/
@@ -116,19 +175,7 @@ uint128 IncrementalHashReference(const void* data, size_t len) {
return hash;
}
-TEST(QuicUtilsHashTest, ReferenceTestSlow) {
- FLAGS_quic_utils_use_fast_incremental_hash = false;
- std::vector<uint8_t> data(32);
- for (size_t i = 0; i < data.size(); ++i) {
- data[i] = i % 255;
- }
- EXPECT_EQ(IncrementalHashReference(data.data(), data.size()),
- QuicUtils::FNV1a_128_Hash(
- reinterpret_cast<const char*>(data.data()), data.size()));
-}
-
-TEST(QuicUtilsHashTest, ReferenceTestFast) {
- FLAGS_quic_utils_use_fast_incremental_hash = true;
+TEST(QuicUtilsHashTest, ReferenceTest) {
std::vector<uint8_t> data(32);
for (size_t i = 0; i < data.size(); ++i) {
data[i] = i % 255;
diff --git a/chromium/net/quic/quic_write_blocked_list.h b/chromium/net/quic/quic_write_blocked_list.h
index ad511877a66..2988a9d1e67 100644
--- a/chromium/net/quic/quic_write_blocked_list.h
+++ b/chromium/net/quic/quic_write_blocked_list.h
@@ -15,7 +15,6 @@
#include "net/quic/quic_flags.h"
#include "net/quic/quic_protocol.h"
#include "net/spdy/priority_write_scheduler.h"
-#include "net/spdy/write_blocked_list.h"
namespace net {
@@ -24,7 +23,6 @@ namespace net {
// Crypto stream > Headers stream > Data streams by requested priority.
class NET_EXPORT_PRIVATE QuicWriteBlockedList {
private:
- typedef WriteBlockedList<QuicStreamId> QuicWriteBlockedListBase;
typedef PriorityWriteScheduler<QuicStreamId> QuicPriorityWriteScheduler;
public:
@@ -32,11 +30,7 @@ class NET_EXPORT_PRIVATE QuicWriteBlockedList {
~QuicWriteBlockedList();
bool HasWriteBlockedDataStreams() const {
- if (use_new_blocked_list_) {
- return priority_write_scheduler_.HasReadyStreams();
- } else {
- return base_write_blocked_list_.HasWriteBlockedStreams();
- }
+ return priority_write_scheduler_.HasReadyStreams();
}
bool HasWriteBlockedCryptoOrHeadersStream() const {
@@ -44,9 +38,7 @@ class NET_EXPORT_PRIVATE QuicWriteBlockedList {
}
size_t NumBlockedStreams() const {
- size_t num_blocked = use_new_blocked_list_
- ? priority_write_scheduler_.NumReadyStreams()
- : base_write_blocked_list_.NumBlockedStreams();
+ size_t num_blocked = priority_write_scheduler_.NumReadyStreams();
if (crypto_stream_blocked_) {
++num_blocked;
}
@@ -57,6 +49,23 @@ class NET_EXPORT_PRIVATE QuicWriteBlockedList {
return num_blocked;
}
+ bool ShouldYield(QuicStreamId id) const {
+ if (id == kCryptoStreamId) {
+ return false; // The crypto stream yields to none.
+ }
+ if (crypto_stream_blocked_) {
+ return true; // If the crypto stream is blocked, all other streams yield.
+ }
+ if (id == kHeadersStreamId) {
+ return false; // The crypto stream isn't blocked so headers won't yield.
+ }
+ if (headers_stream_blocked_) {
+ return true; // All data streams yield to the headers stream.
+ }
+
+ return priority_write_scheduler_.ShouldYield(id);
+ }
+
// Pops the highest priorty stream, special casing crypto and headers streams.
// Latches the most recently popped data stream for batch writing purposes.
QuicStreamId PopFront() {
@@ -70,23 +79,10 @@ class NET_EXPORT_PRIVATE QuicWriteBlockedList {
return kHeadersStreamId;
}
- SpdyPriority priority;
- QuicStreamId id;
-
- if (use_new_blocked_list_) {
- id = priority_write_scheduler_.PopNextReadyStream();
- priority = priority_write_scheduler_.GetStreamPriority(id);
- } else {
- priority = base_write_blocked_list_.GetHighestPriorityWriteBlockedList();
- id = base_write_blocked_list_.PopFront(priority);
- }
+ QuicStreamId id = priority_write_scheduler_.PopNextReadyStream();
+ SpdyPriority priority = priority_write_scheduler_.GetStreamPriority(id);
- size_t num_blocked_for_priority =
- use_new_blocked_list_
- ? priority_write_scheduler_.NumReadyStreams(priority)
- : base_write_blocked_list_.NumBlockedStreams(priority);
-
- if (num_blocked_for_priority == 0) {
+ if (!priority_write_scheduler_.HasReadyStreams()) {
// If no streams are blocked, don't bother latching. This stream will be
// the first popped for its priority anyway.
batch_write_stream_id_[priority] = 0;
@@ -102,21 +98,15 @@ class NET_EXPORT_PRIVATE QuicWriteBlockedList {
}
void RegisterStream(QuicStreamId stream_id, SpdyPriority priority) {
- if (use_new_blocked_list_) {
- priority_write_scheduler_.RegisterStream(stream_id, priority);
- }
+ priority_write_scheduler_.RegisterStream(stream_id, priority);
}
void UnregisterStream(QuicStreamId stream_id) {
- if (use_new_blocked_list_) {
- priority_write_scheduler_.UnregisterStream(stream_id);
- }
+ priority_write_scheduler_.UnregisterStream(stream_id);
}
void UpdateStreamPriority(QuicStreamId stream_id, SpdyPriority new_priority) {
- if (use_new_blocked_list_) {
- priority_write_scheduler_.UpdateStreamPriority(stream_id, new_priority);
- }
+ priority_write_scheduler_.UpdateStreamPriority(stream_id, new_priority);
}
void UpdateBytesForStream(QuicStreamId stream_id, size_t bytes) {
@@ -125,51 +115,30 @@ class NET_EXPORT_PRIVATE QuicWriteBlockedList {
// bytes remaining in its batch write.
bytes_left_for_batch_write_[last_priority_popped_] -=
static_cast<int32_t>(bytes);
- } else {
- // If a batch write stream was set, it should only be preempted by the
- // crypto or headers streams. Any higher priority data stream would
- // *become* the new batch write stream.
- if (FLAGS_quic_respect_send_alarm2 && FLAGS_quic_batch_writes) {
- DCHECK(stream_id == kCryptoStreamId || stream_id == kHeadersStreamId ||
- batch_write_stream_id_[last_priority_popped_] == 0 ||
- bytes == 0);
- }
}
}
- // Pushes a stream to the back of the list for this priority level
- // *unless* it is latched for doing batched writes in which case it goes to
- // the front of the list for this 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, SpdyPriority priority) {
+ void AddStream(QuicStreamId stream_id) {
if (stream_id == kCryptoStreamId) {
- DCHECK_EQ(kV3HighestPriority, priority);
// TODO(avd) Add DCHECK(!crypto_stream_blocked_)
crypto_stream_blocked_ = true;
return;
}
if (stream_id == kHeadersStreamId) {
- DCHECK_EQ(kV3HighestPriority, priority);
// TODO(avd) Add DCHECK(!headers_stream_blocked_);
headers_stream_blocked_ = true;
return;
}
- if (use_new_blocked_list_) {
- bool push_front =
- FLAGS_quic_batch_writes &&
- stream_id == batch_write_stream_id_[last_priority_popped_] &&
- bytes_left_for_batch_write_[last_priority_popped_] > 0;
- priority_write_scheduler_.MarkStreamReady(stream_id, push_front);
- } else if (FLAGS_quic_batch_writes &&
- stream_id == batch_write_stream_id_[last_priority_popped_] &&
- bytes_left_for_batch_write_[last_priority_popped_] > 0) {
- // If the batch write stream has more data to write, push it to the front
- // for its priority level.
- base_write_blocked_list_.PushFront(stream_id, priority);
- } else {
- base_write_blocked_list_.PushBack(stream_id, priority);
- }
+ bool push_front =
+ stream_id == batch_write_stream_id_[last_priority_popped_] &&
+ bytes_left_for_batch_write_[last_priority_popped_] > 0;
+ priority_write_scheduler_.MarkStreamReady(stream_id, push_front);
+
return;
}
@@ -177,9 +146,7 @@ class NET_EXPORT_PRIVATE QuicWriteBlockedList {
bool headers_stream_blocked() const { return headers_stream_blocked_; }
private:
- QuicWriteBlockedListBase base_write_blocked_list_;
QuicPriorityWriteScheduler priority_write_scheduler_;
- bool use_new_blocked_list_ = FLAGS_quic_new_blocked_list;
// If performing batch writes, this will be the stream ID of the stream doing
// batch writes for this priority level. We will allow this stream to write
diff --git a/chromium/net/quic/quic_write_blocked_list_test.cc b/chromium/net/quic/quic_write_blocked_list_test.cc
index bb5ff23b007..23009c06853 100644
--- a/chromium/net/quic/quic_write_blocked_list_test.cc
+++ b/chromium/net/quic/quic_write_blocked_list_test.cc
@@ -25,11 +25,11 @@ TEST(QuicWriteBlockedListTest, PriorityOrder) {
write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority);
write_blocked_list.RegisterStream(kCryptoStreamId, kV3HighestPriority);
- write_blocked_list.AddStream(40, kV3LowestPriority);
- write_blocked_list.AddStream(23, kV3HighestPriority);
- write_blocked_list.AddStream(17, kV3HighestPriority);
- write_blocked_list.AddStream(kHeadersStreamId, kV3HighestPriority);
- write_blocked_list.AddStream(kCryptoStreamId, kV3HighestPriority);
+ write_blocked_list.AddStream(40);
+ write_blocked_list.AddStream(23);
+ write_blocked_list.AddStream(17);
+ write_blocked_list.AddStream(kHeadersStreamId);
+ write_blocked_list.AddStream(kCryptoStreamId);
EXPECT_EQ(5u, write_blocked_list.NumBlockedStreams());
EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream());
@@ -52,7 +52,7 @@ TEST(QuicWriteBlockedListTest, PriorityOrder) {
TEST(QuicWriteBlockedListTest, CryptoStream) {
QuicWriteBlockedList write_blocked_list;
write_blocked_list.RegisterStream(kCryptoStreamId, kV3HighestPriority);
- write_blocked_list.AddStream(kCryptoStreamId, kV3HighestPriority);
+ write_blocked_list.AddStream(kCryptoStreamId);
EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams());
EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream());
@@ -64,7 +64,7 @@ TEST(QuicWriteBlockedListTest, CryptoStream) {
TEST(QuicWriteBlockedListTest, HeadersStream) {
QuicWriteBlockedList write_blocked_list;
write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority);
- write_blocked_list.AddStream(kHeadersStreamId, kV3HighestPriority);
+ write_blocked_list.AddStream(kHeadersStreamId);
EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams());
EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream());
@@ -77,8 +77,8 @@ TEST(QuicWriteBlockedListTest, VerifyHeadersStream) {
QuicWriteBlockedList write_blocked_list;
write_blocked_list.RegisterStream(5, kV3HighestPriority);
write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority);
- write_blocked_list.AddStream(5, kV3HighestPriority);
- write_blocked_list.AddStream(kHeadersStreamId, kV3HighestPriority);
+ write_blocked_list.AddStream(5);
+ write_blocked_list.AddStream(kHeadersStreamId);
EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream());
@@ -100,9 +100,9 @@ TEST(QuicWriteBlockedListTest, NoDuplicateEntries) {
// priority.
const QuicStreamId kBlockedId = kClientDataStreamId1;
write_blocked_list.RegisterStream(kBlockedId, kV3HighestPriority);
- write_blocked_list.AddStream(kBlockedId, kV3HighestPriority);
- write_blocked_list.AddStream(kBlockedId, kV3HighestPriority);
- write_blocked_list.AddStream(kBlockedId, kV3HighestPriority);
+ write_blocked_list.AddStream(kBlockedId);
+ write_blocked_list.AddStream(kBlockedId);
+ write_blocked_list.AddStream(kBlockedId);
// This should only result in one blocked stream being added.
EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams());
@@ -115,7 +115,6 @@ TEST(QuicWriteBlockedListTest, NoDuplicateEntries) {
}
TEST(QuicWriteBlockedListTest, BatchingWrites) {
- ValueRestore<bool> old_flag(&FLAGS_quic_batch_writes, true);
QuicWriteBlockedList write_blocked_list;
const QuicStreamId id1 = kClientDataStreamId1;
@@ -125,49 +124,96 @@ TEST(QuicWriteBlockedListTest, BatchingWrites) {
write_blocked_list.RegisterStream(id2, kV3LowestPriority);
write_blocked_list.RegisterStream(id3, kV3HighestPriority);
- write_blocked_list.AddStream(id1, kV3LowestPriority);
- write_blocked_list.AddStream(id2, kV3LowestPriority);
+ write_blocked_list.AddStream(id1);
+ write_blocked_list.AddStream(id2);
EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
// The first stream we push back should stay at the front until 16k is
// written.
EXPECT_EQ(id1, write_blocked_list.PopFront());
write_blocked_list.UpdateBytesForStream(id1, 15999);
- write_blocked_list.AddStream(id1, kV3LowestPriority);
+ write_blocked_list.AddStream(id1);
EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
EXPECT_EQ(id1, write_blocked_list.PopFront());
- // Once 16k is written the first stream will cede to the next.
+ // Once 16k is written the first stream will yield to the next.
write_blocked_list.UpdateBytesForStream(id1, 1);
- write_blocked_list.AddStream(id1, kV3LowestPriority);
+ write_blocked_list.AddStream(id1);
EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
EXPECT_EQ(id2, write_blocked_list.PopFront());
// Set the new stream to have written all but one byte.
write_blocked_list.UpdateBytesForStream(id2, 15999);
- write_blocked_list.AddStream(id2, kV3LowestPriority);
+ write_blocked_list.AddStream(id2);
EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
// Ensure higher priority streams are popped first.
- write_blocked_list.AddStream(id3, kV3HighestPriority);
+ write_blocked_list.AddStream(id3);
EXPECT_EQ(id3, write_blocked_list.PopFront());
// Higher priority streams will always be popped first, even if using their
// byte quota
write_blocked_list.UpdateBytesForStream(id3, 20000);
- write_blocked_list.AddStream(id3, kV3HighestPriority);
+ write_blocked_list.AddStream(id3);
EXPECT_EQ(id3, write_blocked_list.PopFront());
// Once the higher priority stream is out of the way, id2 will resume its 16k
// write, with only 1 byte remaining of its guaranteed write allocation.
EXPECT_EQ(id2, write_blocked_list.PopFront());
- write_blocked_list.AddStream(id2, net::kV3HighestPriority);
+ write_blocked_list.AddStream(id2);
write_blocked_list.UpdateBytesForStream(id2, 1);
- write_blocked_list.AddStream(id2, kV3LowestPriority);
+ write_blocked_list.AddStream(id2);
EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
EXPECT_EQ(id1, write_blocked_list.PopFront());
}
+TEST(QuicWriteBlockedListTest, Ceding) {
+ QuicWriteBlockedList write_blocked_list;
+
+ write_blocked_list.RegisterStream(15, kV3HighestPriority);
+ write_blocked_list.RegisterStream(16, kV3HighestPriority);
+ write_blocked_list.RegisterStream(5, 5);
+ write_blocked_list.RegisterStream(4, 5);
+ write_blocked_list.RegisterStream(7, 7);
+ write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority);
+ write_blocked_list.RegisterStream(kCryptoStreamId, kV3HighestPriority);
+
+ // When nothing is on the list, nothing yields.
+ EXPECT_FALSE(write_blocked_list.ShouldYield(5));
+
+ write_blocked_list.AddStream(5);
+ // 5 should not yield to itself.
+ EXPECT_FALSE(write_blocked_list.ShouldYield(5));
+ // 4 and 7 are equal or lower priority and should yield to 5.
+ EXPECT_TRUE(write_blocked_list.ShouldYield(4));
+ EXPECT_TRUE(write_blocked_list.ShouldYield(7));
+ // 15, headers and crypto should preempt 5.
+ EXPECT_FALSE(write_blocked_list.ShouldYield(15));
+ EXPECT_FALSE(write_blocked_list.ShouldYield(kHeadersStreamId));
+ EXPECT_FALSE(write_blocked_list.ShouldYield(kCryptoStreamId));
+
+ // Block a high priority stream.
+ write_blocked_list.AddStream(15);
+ // 16 should yield (same priority) but headers and crypto will still not.
+ EXPECT_TRUE(write_blocked_list.ShouldYield(16));
+ EXPECT_FALSE(write_blocked_list.ShouldYield(kHeadersStreamId));
+ EXPECT_FALSE(write_blocked_list.ShouldYield(kCryptoStreamId));
+
+ // Block the headers stream. All streams but crypto and headers should yield.
+ write_blocked_list.AddStream(kHeadersStreamId);
+ EXPECT_TRUE(write_blocked_list.ShouldYield(16));
+ EXPECT_TRUE(write_blocked_list.ShouldYield(15));
+ EXPECT_FALSE(write_blocked_list.ShouldYield(kHeadersStreamId));
+ EXPECT_FALSE(write_blocked_list.ShouldYield(kCryptoStreamId));
+
+ // Block the crypto stream. All streams but crypto should yield.
+ write_blocked_list.AddStream(kCryptoStreamId);
+ EXPECT_TRUE(write_blocked_list.ShouldYield(16));
+ EXPECT_TRUE(write_blocked_list.ShouldYield(15));
+ EXPECT_TRUE(write_blocked_list.ShouldYield(kHeadersStreamId));
+ EXPECT_FALSE(write_blocked_list.ShouldYield(kCryptoStreamId));
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/reliable_quic_stream.cc b/chromium/net/quic/reliable_quic_stream.cc
index f3ff54145f0..6df81ee0795 100644
--- a/chromium/net/quic/reliable_quic_stream.cc
+++ b/chromium/net/quic/reliable_quic_stream.cc
@@ -6,7 +6,6 @@
#include "base/logging.h"
#include "net/quic/iovector.h"
-#include "net/quic/quic_ack_listener_interface.h"
#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_flow_controller.h"
@@ -67,7 +66,6 @@ ReliableQuicStream::ReliableQuicStream(QuicStreamId id, QuicSession* session)
fin_received_(false),
rst_sent_(false),
rst_received_(false),
- fec_policy_(FEC_PROTECT_OPTIONAL),
perspective_(session_->perspective()),
flow_controller_(session_->connection(),
id_,
@@ -82,15 +80,13 @@ ReliableQuicStream::ReliableQuicStream(QuicStreamId id, QuicSession* session)
ReliableQuicStream::~ReliableQuicStream() {}
-void ReliableQuicStream::SetFromConfig() {
- if (session_->config()->HasClientSentConnectionOption(kFSTR, perspective_)) {
- fec_policy_ = FEC_PROTECT_ALWAYS;
- }
-}
+void ReliableQuicStream::SetFromConfig() {}
void ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
DCHECK_EQ(frame.stream_id, id_);
+ DCHECK(!(read_side_closed_ && write_side_closed_));
+
if (frame.fin) {
fin_received_ = true;
if (fin_sent_) {
@@ -114,7 +110,7 @@ void ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
// violation of flow control.
if (flow_controller_.FlowControlViolation() ||
connection_flow_controller_->FlowControlViolation()) {
- session_->connection()->SendConnectionCloseWithDetails(
+ CloseConnectionWithDetails(
QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
"Flow control violation after increasing offset");
return;
@@ -146,7 +142,7 @@ void ReliableQuicStream::OnStreamReset(const QuicRstStreamFrame& frame) {
}
void ReliableQuicStream::OnConnectionClosed(QuicErrorCode error,
- bool /*from_peer*/) {
+ ConnectionCloseSource /*source*/) {
if (read_side_closed_ && write_side_closed_) {
return;
}
@@ -179,7 +175,8 @@ void ReliableQuicStream::Reset(QuicRstStreamErrorCode error) {
void ReliableQuicStream::CloseConnectionWithDetails(QuicErrorCode error,
const string& details) {
- session()->connection()->SendConnectionCloseWithDetails(error, details);
+ session()->connection()->CloseConnection(
+ error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
void ReliableQuicStream::WriteOrBufferData(
@@ -214,7 +211,7 @@ void ReliableQuicStream::WriteOrBufferData(
(fin && !consumed_data.fin_consumed)) {
StringPiece remainder(data.substr(consumed_data.bytes_consumed));
queued_data_bytes_ += remainder.size();
- queued_data_.push_back(PendingData(remainder.as_string(), ack_listener));
+ queued_data_.emplace_back(remainder.as_string(), ack_listener);
}
}
@@ -264,7 +261,7 @@ void ReliableQuicStream::MaybeSendBlocked() {
// WINDOW_UPDATE arrives.
if (connection_flow_controller_->IsBlocked() &&
!flow_controller_.IsBlocked()) {
- session_->MarkConnectionLevelWriteBlocked(id(), Priority());
+ session_->MarkConnectionLevelWriteBlocked(id());
}
}
@@ -291,6 +288,11 @@ QuicConsumedData ReliableQuicStream::WritevData(
min(send_window, connection_flow_controller_->SendWindowSize());
}
+ if (FLAGS_quic_cede_correctly && session_->ShouldYield(id())) {
+ session_->MarkConnectionLevelWriteBlocked(id());
+ return QuicConsumedData(0, false);
+ }
+
if (send_window == 0 && !fin_with_zero_data) {
// Quick return if nothing can be sent.
MaybeSendBlocked();
@@ -305,9 +307,9 @@ QuicConsumedData ReliableQuicStream::WritevData(
write_length = static_cast<size_t>(send_window);
}
- QuicConsumedData consumed_data = session()->WritevData(
- id(), QuicIOVector(iov, iov_count, write_length), stream_bytes_written_,
- fin, GetFecProtection(), ack_listener);
+ QuicConsumedData consumed_data =
+ session()->WritevData(id(), QuicIOVector(iov, iov_count, write_length),
+ stream_bytes_written_, fin, ack_listener);
stream_bytes_written_ += consumed_data.bytes_consumed;
AddBytesSent(consumed_data.bytes_consumed);
@@ -329,18 +331,14 @@ QuicConsumedData ReliableQuicStream::WritevData(
}
CloseWriteSide();
} else if (fin && !consumed_data.fin_consumed) {
- session_->MarkConnectionLevelWriteBlocked(id(), Priority());
+ session_->MarkConnectionLevelWriteBlocked(id());
}
} else {
- session_->MarkConnectionLevelWriteBlocked(id(), Priority());
+ session_->MarkConnectionLevelWriteBlocked(id());
}
return consumed_data;
}
-FecProtection ReliableQuicStream::GetFecProtection() {
- return fec_policy_ == FEC_PROTECT_ALWAYS ? MUST_FEC_PROTECT : MAY_FEC_PROTECT;
-}
-
void ReliableQuicStream::CloseReadSide() {
if (read_side_closed_) {
return;
diff --git a/chromium/net/quic/reliable_quic_stream.h b/chromium/net/quic/reliable_quic_stream.h
index 22dce1050db..e0be70b0f1f 100644
--- a/chromium/net/quic/reliable_quic_stream.h
+++ b/chromium/net/quic/reliable_quic_stream.h
@@ -33,8 +33,6 @@
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_stream_sequencer.h"
#include "net/quic/quic_types.h"
-//#include "std::strings/std::stringpiece.h"
-//#include "util/refcount/reffed_ptr.h"
// TODO(alyssar) remove this after cleaning Priority logic from this class.
#include "net/quic/quic_write_blocked_list.h"
@@ -52,7 +50,7 @@ class NET_EXPORT_PRIVATE ReliableQuicStream {
virtual ~ReliableQuicStream();
- // Sets |fec_policy_| parameter from |session_|'s config.
+ // Not in use currently.
void SetFromConfig();
// Called by the session when a (potentially duplicate) stream frame has been
@@ -75,7 +73,8 @@ class NET_EXPORT_PRIVATE ReliableQuicStream {
// Called by the session when the endpoint receives or sends a connection
// close, and should immediately close the stream.
- virtual void OnConnectionClosed(QuicErrorCode error, bool from_peer);
+ virtual void OnConnectionClosed(QuicErrorCode error,
+ ConnectionCloseSource source);
// Called by the stream subclass after it has consumed the final incoming
// data.
@@ -95,9 +94,6 @@ class NET_EXPORT_PRIVATE ReliableQuicStream {
virtual void CloseConnectionWithDetails(QuicErrorCode error,
const std::string& details);
- // Returns the priority for the stream.
- virtual SpdyPriority Priority() const = 0;
-
QuicStreamId id() const { return id_; }
QuicRstStreamErrorCode stream_error() const { return stream_error_; }
@@ -122,9 +118,6 @@ class NET_EXPORT_PRIVATE ReliableQuicStream {
void set_fin_received(bool fin_received) { fin_received_ = fin_received; }
void set_rst_sent(bool rst_sent) { rst_sent_ = rst_sent; }
- void set_fec_policy(FecPolicy fec_policy) { fec_policy_ = fec_policy; }
- FecPolicy fec_policy() const { return fec_policy_; }
-
void set_rst_received(bool rst_received) { rst_received_ = rst_received; }
void set_stream_error(QuicRstStreamErrorCode error) { stream_error_ = error; }
@@ -202,9 +195,6 @@ class NET_EXPORT_PRIVATE ReliableQuicStream {
// Does not send a FIN. May cause the stream to be closed.
virtual void CloseWriteSide();
- // Helper method that returns FecProtection to use when writing.
- FecProtection GetFecProtection();
-
bool fin_buffered() const { return fin_buffered_; }
const QuicSession* session() const { return session_; }
@@ -291,9 +281,6 @@ class NET_EXPORT_PRIVATE ReliableQuicStream {
// True if this stream has received a RST_STREAM frame.
bool rst_received_;
- // FEC policy to be used for this stream.
- FecPolicy fec_policy_;
-
// Tracks if the session this stream is running under was created by a
// server or a client.
Perspective perspective_;
diff --git a/chromium/net/quic/reliable_quic_stream_test.cc b/chromium/net/quic/reliable_quic_stream_test.cc
index 10656c722f0..58a99d38d80 100644
--- a/chromium/net/quic/reliable_quic_stream_test.cc
+++ b/chromium/net/quic/reliable_quic_stream_test.cc
@@ -58,8 +58,6 @@ class TestStream : public ReliableQuicStream {
return should_process_data_ ? data_len : 0;
}
- SpdyPriority Priority() const override { return net::kV3HighestPriority; }
-
using ReliableQuicStream::WriteOrBufferData;
using ReliableQuicStream::CloseWriteSide;
using ReliableQuicStream::OnClose;
@@ -143,7 +141,6 @@ class ReliableQuicStreamTest : public ::testing::TestWithParam<bool> {
QuicIOVector /*iov*/,
QuicStreamOffset /*offset*/,
bool /*fin*/,
- FecProtection /*fec_protection*/,
QuicAckListenerInterface* /*ack_notifier_delegate*/) {
session_->CloseStream(id);
return QuicConsumedData(1, false);
@@ -167,10 +164,10 @@ TEST_F(ReliableQuicStreamTest, WriteAllData) {
size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead(
PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- PACKET_6BYTE_PACKET_NUMBER, 0u, NOT_IN_FEC_GROUP);
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, 0u);
connection_->SetMaxPacketLength(length);
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(Return(QuicConsumedData(kDataLen, true)));
stream_->WriteOrBufferData(kData1, false, nullptr);
EXPECT_FALSE(HasWriteBlockedStreams());
@@ -190,7 +187,7 @@ TEST_F(ReliableQuicStreamTest, BlockIfOnlySomeDataConsumed) {
// Write some data and no fin. If we consume some but not all of the data,
// we should be write blocked a not all the data was consumed.
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(Return(QuicConsumedData(1, false)));
stream_->WriteOrBufferData(StringPiece(kData1, 2), false, nullptr);
ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
@@ -204,7 +201,7 @@ TEST_F(ReliableQuicStreamTest, BlockIfFinNotConsumedWithData) {
// we should be write blocked because the fin was not consumed.
// (This should never actually happen as the fin should be sent out with the
// last data)
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(Return(QuicConsumedData(2, false)));
stream_->WriteOrBufferData(StringPiece(kData1, 2), true, nullptr);
ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
@@ -215,7 +212,7 @@ TEST_F(ReliableQuicStreamTest, BlockIfSoloFinNotConsumed) {
// Write no data and a fin. If we consume nothing we should be write blocked,
// as the fin was not consumed.
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(Return(QuicConsumedData(0, false)));
stream_->WriteOrBufferData(StringPiece(), true, nullptr);
ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
@@ -227,7 +224,7 @@ TEST_F(ReliableQuicStreamTest, CloseOnPartialWrite) {
// Write some data and no fin. However, while writing the data
// close the stream and verify that MarkConnectionLevelWriteBlocked does not
// crash with an unknown stream.
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(Invoke(this, &ReliableQuicStreamTest::CloseStreamOnWriteError));
stream_->WriteOrBufferData(StringPiece(kData1, 2), false, nullptr);
ASSERT_EQ(0u, write_blocked_list_->NumBlockedStreams());
@@ -239,10 +236,10 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferData) {
EXPECT_FALSE(HasWriteBlockedStreams());
size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead(
PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- PACKET_6BYTE_PACKET_NUMBER, 0u, NOT_IN_FEC_GROUP);
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, 0u);
connection_->SetMaxPacketLength(length);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillOnce(Return(QuicConsumedData(kDataLen - 1, false)));
stream_->WriteOrBufferData(kData1, false, nullptr);
EXPECT_TRUE(HasWriteBlockedStreams());
@@ -252,84 +249,14 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferData) {
// Make sure we get the tail of the first write followed by the bytes_consumed
InSequence s;
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillOnce(Return(QuicConsumedData(1, false)));
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillOnce(Return(QuicConsumedData(kDataLen - 2, false)));
stream_->OnCanWrite();
// And finally the end of the bytes_consumed.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
- .WillOnce(Return(QuicConsumedData(2, true)));
- stream_->OnCanWrite();
-}
-
-TEST_F(ReliableQuicStreamTest, WriteOrBufferDataWithFecProtectAlways) {
- Initialize(kShouldProcessData);
-
- // Set FEC policy on stream.
- ReliableQuicStreamPeer::SetFecPolicy(stream_, FEC_PROTECT_ALWAYS);
-
- EXPECT_FALSE(HasWriteBlockedStreams());
- size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead(
- PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- PACKET_6BYTE_PACKET_NUMBER, 0u, IN_FEC_GROUP);
- connection_->SetMaxPacketLength(length);
-
- // Write first data onto stream, which will cause one session write.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, MUST_FEC_PROTECT, _))
- .WillOnce(Return(QuicConsumedData(kDataLen - 1, false)));
- stream_->WriteOrBufferData(kData1, false, nullptr);
- EXPECT_TRUE(HasWriteBlockedStreams());
-
- // Queue a bytes_consumed write.
- stream_->WriteOrBufferData(kData2, false, nullptr);
-
- // Make sure we get the tail of the first write followed by the bytes_consumed
- InSequence s;
- EXPECT_CALL(*session_, WritevData(_, _, _, _, MUST_FEC_PROTECT, _))
- .WillOnce(Return(QuicConsumedData(1, false)));
- EXPECT_CALL(*session_, WritevData(_, _, _, _, MUST_FEC_PROTECT, _))
- .WillOnce(Return(QuicConsumedData(kDataLen - 2, false)));
- stream_->OnCanWrite();
-
- // And finally the end of the bytes_consumed.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, MUST_FEC_PROTECT, _))
- .WillOnce(Return(QuicConsumedData(2, true)));
- stream_->OnCanWrite();
-}
-
-TEST_F(ReliableQuicStreamTest, WriteOrBufferDataWithFecProtectOptional) {
- Initialize(kShouldProcessData);
-
- // Set FEC policy on stream.
- ReliableQuicStreamPeer::SetFecPolicy(stream_, FEC_PROTECT_OPTIONAL);
-
- EXPECT_FALSE(HasWriteBlockedStreams());
- size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead(
- PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- PACKET_6BYTE_PACKET_NUMBER, 0u, NOT_IN_FEC_GROUP);
- connection_->SetMaxPacketLength(length);
-
- // Write first data onto stream, which will cause one session write.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, MAY_FEC_PROTECT, _))
- .WillOnce(Return(QuicConsumedData(kDataLen - 1, false)));
- stream_->WriteOrBufferData(kData1, false, nullptr);
- EXPECT_TRUE(HasWriteBlockedStreams());
-
- // Queue a bytes_consumed write.
- stream_->WriteOrBufferData(kData2, false, nullptr);
-
- // Make sure we get the tail of the first write followed by the bytes_consumed
- InSequence s;
- EXPECT_CALL(*session_, WritevData(_, _, _, _, MAY_FEC_PROTECT, _))
- .WillOnce(Return(QuicConsumedData(1, false)));
- EXPECT_CALL(*session_, WritevData(_, _, _, _, MAY_FEC_PROTECT, _))
- .WillOnce(Return(QuicConsumedData(kDataLen - 2, false)));
- stream_->OnCanWrite();
-
- // And finally the end of the bytes_consumed.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, MAY_FEC_PROTECT, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillOnce(Return(QuicConsumedData(2, true)));
stream_->OnCanWrite();
}
@@ -341,7 +268,8 @@ TEST_F(ReliableQuicStreamTest, ConnectionCloseAfterStreamClose) {
stream_->CloseWriteSide();
EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error());
- stream_->OnConnectionClosed(QUIC_INTERNAL_ERROR, false);
+ stream_->OnConnectionClosed(QUIC_INTERNAL_ERROR,
+ ConnectionCloseSource::FROM_SELF);
EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error());
}
@@ -356,7 +284,7 @@ TEST_F(ReliableQuicStreamTest, RstAlwaysSentIfNoFinSent) {
EXPECT_FALSE(rst_sent());
// Write some data, with no FIN.
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(Return(QuicConsumedData(1, false)));
stream_->WriteOrBufferData(StringPiece(kData1, 1), false, nullptr);
EXPECT_FALSE(fin_sent());
@@ -379,7 +307,7 @@ TEST_F(ReliableQuicStreamTest, RstNotSentIfFinSent) {
EXPECT_FALSE(rst_sent());
// Write some data, with FIN.
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(Return(QuicConsumedData(1, true)));
stream_->WriteOrBufferData(StringPiece(kData1, 1), true, nullptr);
EXPECT_TRUE(fin_sent());
@@ -473,26 +401,23 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferDataWithQuicAckNotifier) {
scoped_refptr<QuicAckListenerInterface> ack_listener;
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &ack_listener))),
+ WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &ack_listener))),
Return(QuicConsumedData(kFirstWriteSize, false))));
stream_->WriteOrBufferData(kData, false, delegate.get());
EXPECT_TRUE(HasWriteBlockedStreams());
- EXPECT_CALL(*session_,
- WritevData(kTestStreamId, _, _, _, _, ack_listener.get()))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, ack_listener.get()))
.WillOnce(Return(QuicConsumedData(kSecondWriteSize, false)));
stream_->OnCanWrite();
// No ack expected for an empty write.
- EXPECT_CALL(*session_,
- WritevData(kTestStreamId, _, _, _, _, ack_listener.get()))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, ack_listener.get()))
.WillOnce(Return(QuicConsumedData(0, false)));
stream_->OnCanWrite();
- EXPECT_CALL(*session_,
- WritevData(kTestStreamId, _, _, _, _, ack_listener.get()))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, ack_listener.get()))
.WillOnce(Return(QuicConsumedData(kLastWriteSize, false)));
stream_->OnCanWrite();
}
@@ -515,16 +440,16 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferDataAckNotificationBeforeFlush) {
scoped_refptr<QuicAckListenerInterface> proxy_delegate;
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
+ WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
Return(QuicConsumedData(kInitialWriteSize, false))));
stream_->WriteOrBufferData(kData, false, ack_listener.get());
EXPECT_TRUE(HasWriteBlockedStreams());
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
+ WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
Return(QuicConsumedData(kDataSize - kInitialWriteSize, false))));
stream_->OnCanWrite();
}
@@ -537,9 +462,9 @@ TEST_F(ReliableQuicStreamTest, WriteAndBufferDataWithAckNotiferNoBuffer) {
scoped_refptr<QuicAckListenerInterface> proxy_delegate;
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
+ WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
Return(QuicConsumedData(kDataLen, true))));
stream_->WriteOrBufferData(kData1, true, delegate.get());
EXPECT_FALSE(HasWriteBlockedStreams());
@@ -553,14 +478,14 @@ TEST_F(ReliableQuicStreamTest, BufferOnWriteAndBufferDataWithAckNotifer) {
scoped_refptr<QuicAckListenerInterface> proxy_delegate;
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(Return(QuicConsumedData(0, false)));
stream_->WriteOrBufferData(kData1, true, delegate.get());
EXPECT_TRUE(HasWriteBlockedStreams());
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
+ WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
Return(QuicConsumedData(kDataLen, true))));
stream_->OnCanWrite();
}
@@ -574,16 +499,16 @@ TEST_F(ReliableQuicStreamTest, WriteAndBufferDataWithAckNotiferOnlyFinRemains) {
scoped_refptr<QuicAckListenerInterface> proxy_delegate;
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
+ WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
Return(QuicConsumedData(kDataLen, false))));
stream_->WriteOrBufferData(kData1, true, delegate.get());
EXPECT_TRUE(HasWriteBlockedStreams());
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(DoAll(
- WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
+ WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
Return(QuicConsumedData(0, true))));
stream_->OnCanWrite();
}
@@ -604,8 +529,8 @@ TEST_F(ReliableQuicStreamTest,
stream_->flow_controller()));
// Stream should not accept the frame, and the connection should be closed.
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _));
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
stream_->OnStreamFrame(frame);
}
@@ -617,8 +542,8 @@ TEST_F(ReliableQuicStreamTest, StopReadingSendsFlowControl) {
stream_->StopReading();
// Connection should not get terminated due to flow control errors.
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _))
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _))
.Times(0);
EXPECT_CALL(*connection_, SendWindowUpdate(_, _)).Times(AtLeast(1));
@@ -675,7 +600,7 @@ TEST_F(ReliableQuicStreamTest, SetDrainingIncomingOutgoing) {
EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
// Outgoing data with FIN.
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(Return(QuicConsumedData(2, true)));
stream_->WriteOrBufferData(StringPiece(kData1, 2), true, nullptr);
EXPECT_TRUE(stream_->write_side_closed());
@@ -690,7 +615,7 @@ TEST_F(ReliableQuicStreamTest, SetDrainingOutgoingIncoming) {
Initialize(kShouldNotProcessData);
// Outgoing data with FIN.
- EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
.WillOnce(Return(QuicConsumedData(2, true)));
stream_->WriteOrBufferData(StringPiece(kData1, 2), true, nullptr);
EXPECT_TRUE(stream_->write_side_closed());
@@ -711,26 +636,13 @@ TEST_F(ReliableQuicStreamTest, SetDrainingOutgoingIncoming) {
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
}
-TEST_F(ReliableQuicStreamTest, FecSendPolicyReceivedConnectionOption) {
- Initialize(kShouldProcessData);
-
- // Test ReceivedConnectionOptions.
- QuicConfig* config = session_->config();
- QuicTagVector copt;
- copt.push_back(kFSTR);
- QuicConfigPeer::SetReceivedConnectionOptions(config, copt);
- EXPECT_EQ(FEC_PROTECT_OPTIONAL, stream_->fec_policy());
- stream_->SetFromConfig();
- EXPECT_EQ(FEC_PROTECT_ALWAYS, stream_->fec_policy());
-}
-
TEST_F(ReliableQuicStreamTest, EarlyResponseFinHandling) {
// Verify that if the server completes the response before reading the end of
// the request, the received FIN is recorded.
Initialize(kShouldProcessData);
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData));
// Receive data for the request.
diff --git a/chromium/net/quic/spdy_utils.cc b/chromium/net/quic/spdy_utils.cc
index 6f2d29f423a..468c9823e1a 100644
--- a/chromium/net/quic/spdy_utils.cc
+++ b/chromium/net/quic/spdy_utils.cc
@@ -26,15 +26,16 @@ string SpdyUtils::SerializeUncompressedHeaders(const SpdyHeaderBlock& headers) {
size_t length = SpdyFramer::GetSerializedLength(spdy_version, &headers);
SpdyFrameBuilder builder(length, spdy_version);
- SpdyFramer::WriteHeaderBlock(&builder, spdy_version, &headers);
- scoped_ptr<SpdyFrame> block(builder.take());
- return string(block->data(), length);
+ SpdyFramer framer(spdy_version);
+ framer.SerializeHeaderBlockWithoutCompression(&builder, headers);
+ SpdySerializedFrame block(builder.take());
+ return string(block.data(), length);
}
// static
bool SpdyUtils::ParseHeaders(const char* data,
uint32_t data_len,
- int* content_length,
+ int64_t* content_length,
SpdyHeaderBlock* headers) {
SpdyFramer framer(HTTP2);
if (!framer.ParseHeaderBlockInBuffer(data, data_len, headers) ||
@@ -109,25 +110,33 @@ bool SpdyUtils::ParseTrailers(const char* data,
// static
string SpdyUtils::GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers) {
SpdyHeaderBlock::const_iterator it = headers.find(":scheme");
- if (it == headers.end())
+ if (it == headers.end()) {
return "";
+ }
std::string url = it->second.as_string();
url.append("://");
it = headers.find(":authority");
- if (it == headers.end())
+ if (it == headers.end()) {
return "";
+ }
url.append(it->second.as_string());
it = headers.find(":path");
- if (it == headers.end())
+ if (it == headers.end()) {
return "";
+ }
url.append(it->second.as_string());
return url;
}
// static
+string SpdyUtils::GetHostNameFromHeaderBlock(const SpdyHeaderBlock& headers) {
+ return GURL(GetUrlFromHeaderBlock(headers)).host();
+}
+
+// static
bool SpdyUtils::UrlIsValid(const SpdyHeaderBlock& headers) {
string url(GetUrlFromHeaderBlock(headers));
return url != "" && GURL(url).is_valid();
diff --git a/chromium/net/quic/spdy_utils.h b/chromium/net/quic/spdy_utils.h
index 2351e57506f..ba8fecb9a26 100644
--- a/chromium/net/quic/spdy_utils.h
+++ b/chromium/net/quic/spdy_utils.h
@@ -30,7 +30,7 @@ class NET_EXPORT_PRIVATE SpdyUtils {
// Returns true on success, false if parsing fails, or invalid keys are found.
static bool ParseHeaders(const char* data,
uint32_t data_len,
- int* content_length,
+ int64_t* content_length,
SpdyHeaderBlock* headers);
// Parses |data| as a std::string containing serialized HTTP/2 HEADERS frame,
@@ -47,6 +47,9 @@ class NET_EXPORT_PRIVATE SpdyUtils {
// values, or empty string if any of those fields are missing.
static std::string GetUrlFromHeaderBlock(const net::SpdyHeaderBlock& headers);
+ // Returns hostname, or empty std::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);
diff --git a/chromium/net/quic/spdy_utils_test.cc b/chromium/net/quic/spdy_utils_test.cc
index b727638caa2..c3ebf704b52 100644
--- a/chromium/net/quic/spdy_utils_test.cc
+++ b/chromium/net/quic/spdy_utils_test.cc
@@ -31,7 +31,7 @@ TEST(SpdyUtilsTest, SerializeAndParseHeaders) {
// Take the serialized header block, and parse back into SpdyHeaderBlock.
SpdyHeaderBlock output_headers;
- int content_length = -1;
+ int64_t content_length = -1;
ASSERT_TRUE(SpdyUtils::ParseHeaders(serialized_headers.data(),
serialized_headers.size(),
&content_length, &output_headers));
@@ -125,6 +125,26 @@ TEST(SpdyUtilsTest, GetUrlFromHeaderBlock) {
"https://www.google.com/index.html");
}
+TEST(SpdyUtilsTest, GetHostNameFromHeaderBlock) {
+ SpdyHeaderBlock headers;
+ EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "");
+ headers[":scheme"] = "https";
+ EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "");
+ headers[":authority"] = "www.google.com";
+ EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "");
+ headers[":path"] = "/index.html";
+ EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "www.google.com");
+ headers["key1"] = "value1";
+ headers["key2"] = "value2";
+ EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "www.google.com");
+ headers[":authority"] = "www.google.com:6666";
+ EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "www.google.com");
+ headers[":authority"] = "192.168.1.1";
+ EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "192.168.1.1");
+ headers[":authority"] = "192.168.1.1:6666";
+ EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "192.168.1.1");
+}
+
TEST(SpdyUtilsTest, UrlIsValid) {
SpdyHeaderBlock headers;
EXPECT_FALSE(SpdyUtils::UrlIsValid(headers));
@@ -137,4 +157,4 @@ TEST(SpdyUtilsTest, UrlIsValid) {
}
} // namespace test
-} // namespace net_quic
+} // namespace net
diff --git a/chromium/net/quic/test_tools/crypto_test_utils.cc b/chromium/net/quic/test_tools/crypto_test_utils.cc
index 8f46d92144f..29232949bc6 100644
--- a/chromium/net/quic/test_tools/crypto_test_utils.cc
+++ b/chromium/net/quic/test_tools/crypto_test_utils.cc
@@ -16,6 +16,7 @@
#include "net/quic/quic_crypto_server_stream.h"
#include "net/quic/quic_crypto_stream.h"
#include "net/quic/quic_server_id.h"
+#include "net/quic/quic_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"
@@ -136,11 +137,14 @@ int CryptoTestUtils::HandshakeWithFakeServer(
QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance(),
ProofSourceForTesting());
+ QuicCompressedCertsCache compressed_certs_cache(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
SetupCryptoServerConfigForTest(server_conn->clock(),
server_conn->random_generator(), &config,
&crypto_config, options);
- TestQuicSpdyServerSession server_session(server_conn, config, &crypto_config);
+ TestQuicSpdyServerSession server_session(server_conn, config, &crypto_config,
+ &compressed_certs_cache);
// The client's handshake must have been started already.
CHECK_NE(0u, client_conn->encrypted_packets_.size());
@@ -180,6 +184,8 @@ int CryptoTestUtils::HandshakeWithFakeClient(
TestQuicSpdyClientSession client_session(client_conn, DefaultQuicConfig(),
server_id, &crypto_config);
+ EXPECT_CALL(client_session, OnProofValid(testing::_))
+ .Times(testing::AnyNumber());
client_session.GetCryptoStream()->CryptoConnect();
CHECK_EQ(1u, client_conn->encrypted_packets_.size());
@@ -438,12 +444,16 @@ void CryptoTestUtils::CompareClientAndServerKeys(
const size_t kSampleOutputLength = 32;
string client_key_extraction;
string server_key_extraction;
+ string client_tb_ekm;
+ string server_tb_ekm;
EXPECT_TRUE(client->ExportKeyingMaterial(kSampleLabel, kSampleContext,
kSampleOutputLength,
&client_key_extraction));
EXPECT_TRUE(server->ExportKeyingMaterial(kSampleLabel, kSampleContext,
kSampleOutputLength,
&server_key_extraction));
+ EXPECT_TRUE(client->ExportTokenBindingKeyingMaterial(&client_tb_ekm));
+ EXPECT_TRUE(server->ExportTokenBindingKeyingMaterial(&server_tb_ekm));
CompareCharArraysWithHexError("client write key", client_encrypter_key.data(),
client_encrypter_key.length(),
@@ -489,6 +499,10 @@ void CryptoTestUtils::CompareClientAndServerKeys(
"sample key extraction", client_key_extraction.data(),
client_key_extraction.length(), server_key_extraction.data(),
server_key_extraction.length());
+
+ CompareCharArraysWithHexError("token binding key extraction",
+ client_tb_ekm.data(), client_tb_ekm.length(),
+ server_tb_ekm.data(), server_tb_ekm.length());
}
// static
diff --git a/chromium/net/quic/test_tools/crypto_test_utils_chromium.cc b/chromium/net/quic/test_tools/crypto_test_utils_chromium.cc
index babaceff3f5..3932f31c0fc 100644
--- a/chromium/net/quic/test_tools/crypto_test_utils_chromium.cc
+++ b/chromium/net/quic/test_tools/crypto_test_utils_chromium.cc
@@ -102,32 +102,36 @@ class FakeProofSource : public ProofSource {
return false;
}
+ vector<string> certs;
for (const scoped_refptr<X509Certificate>& cert : certs_in_file) {
std::string der_encoded_cert;
if (!X509Certificate::GetDEREncoded(cert->os_cert_handle(),
&der_encoded_cert)) {
return false;
}
- certificates_.push_back(der_encoded_cert);
+ certs.push_back(der_encoded_cert);
}
+ chain_ = new ProofSource::Chain(certs);
return true;
}
- bool GetProof(const IPAddressNumber& server_ip,
+ bool GetProof(const IPAddress& server_ip,
const std::string& hostname,
const std::string& server_config,
+ QuicVersion quic_version,
+ StringPiece chlo_hash,
bool ecdsa_ok,
- const std::vector<std::string>** out_certs,
+ scoped_refptr<ProofSource::Chain>* out_chain,
std::string* out_signature,
std::string* out_leaf_cert_sct) override {
out_signature->assign(kSignature);
- *out_certs = &certificates_;
+ *out_chain = chain_;
*out_leaf_cert_sct = kSCT;
return true;
}
private:
- std::vector<std::string> certificates_;
+ scoped_refptr<ProofSource::Chain> chain_;
DISALLOW_COPY_AND_ASSIGN(FakeProofSource);
};
@@ -146,7 +150,10 @@ class FakeProofVerifier : public TestProofVerifierChromium {
// ProofVerifier interface
QuicAsyncStatus VerifyProof(const std::string& hostname,
+ const uint16_t port,
const std::string& server_config,
+ QuicVersion quic_version,
+ StringPiece chlo_hash,
const std::vector<std::string>& certs,
const std::string& cert_sct,
const std::string& signature,
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 b0db4dd05d3..f3e4aa938df 100644
--- a/chromium/net/quic/test_tools/mock_crypto_client_stream.cc
+++ b/chromium/net/quic/test_tools/mock_crypto_client_stream.cc
@@ -20,9 +20,14 @@ MockCryptoClientStream::MockCryptoClientStream(
ProofVerifyContext* verify_context,
QuicCryptoClientConfig* crypto_config,
HandshakeMode handshake_mode,
- const ProofVerifyDetails* proof_verify_details)
- : QuicCryptoClientStream(server_id, session, verify_context, crypto_config),
+ const ProofVerifyDetailsChromium* proof_verify_details)
+ : QuicCryptoClientStream(server_id,
+ session,
+ verify_context,
+ crypto_config,
+ session),
handshake_mode_(handshake_mode),
+ server_id_(server_id),
proof_verify_details_(proof_verify_details) {}
MockCryptoClientStream::~MockCryptoClientStream() {}
@@ -34,6 +39,19 @@ void MockCryptoClientStream::OnHandshakeMessage(
}
void MockCryptoClientStream::CryptoConnect() {
+ if (proof_verify_details_) {
+ bool unused = false;
+ if (!proof_verify_details_->cert_verify_result.verified_cert
+ ->VerifyNameMatch(server_id_.host(), &unused)) {
+ handshake_confirmed_ = false;
+ encryption_established_ = false;
+ session()->connection()->CloseConnection(
+ QUIC_PROOF_INVALID, "proof invalid",
+ ConnectionCloseBehavior::SILENT_CLOSE);
+ return;
+ }
+ }
+
switch (handshake_mode_) {
case ZERO_RTT: {
encryption_established_ = true;
@@ -41,7 +59,8 @@ void MockCryptoClientStream::CryptoConnect() {
crypto_negotiated_params_.key_exchange = kC255;
crypto_negotiated_params_.aead = kAESG;
if (proof_verify_details_) {
- client_session()->OnProofVerifyDetailsAvailable(*proof_verify_details_);
+ reinterpret_cast<QuicClientSessionBase*>(session())
+ ->OnProofVerifyDetailsAvailable(*proof_verify_details_);
}
session()->connection()->SetDecrypter(ENCRYPTION_INITIAL,
QuicDecrypter::Create(kNULL));
@@ -59,7 +78,8 @@ void MockCryptoClientStream::CryptoConnect() {
crypto_negotiated_params_.key_exchange = kC255;
crypto_negotiated_params_.aead = kAESG;
if (proof_verify_details_) {
- client_session()->OnProofVerifyDetailsAvailable(*proof_verify_details_);
+ reinterpret_cast<QuicClientSessionBase*>(session())
+ ->OnProofVerifyDetailsAvailable(*proof_verify_details_);
}
SetConfigNegotiated();
session()->connection()->SetDecrypter(ENCRYPTION_FORWARD_SECURE,
@@ -116,8 +136,4 @@ void MockCryptoClientStream::SetConfigNegotiated() {
session()->OnConfigNegotiated();
}
-QuicClientSessionBase* MockCryptoClientStream::client_session() {
- return reinterpret_cast<QuicClientSessionBase*>(session());
-}
-
} // namespace net
diff --git a/chromium/net/quic/test_tools/mock_crypto_client_stream.h b/chromium/net/quic/test_tools/mock_crypto_client_stream.h
index e9281ab26e4..b9bb57ffb89 100644
--- a/chromium/net/quic/test_tools/mock_crypto_client_stream.h
+++ b/chromium/net/quic/test_tools/mock_crypto_client_stream.h
@@ -10,6 +10,8 @@
#include "base/macros.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/crypto/proof_verifier_chromium.h"
+#include "net/quic/quic_client_session_base.h"
#include "net/quic/quic_crypto_client_stream.h"
#include "net/quic/quic_session.h"
@@ -36,12 +38,13 @@ class MockCryptoClientStream : public QuicCryptoClientStream {
COLD_START,
};
- MockCryptoClientStream(const QuicServerId& server_id,
- QuicClientSessionBase* session,
- ProofVerifyContext* verify_context,
- QuicCryptoClientConfig* crypto_config,
- HandshakeMode handshake_mode,
- const ProofVerifyDetails* proof_verify_details_);
+ MockCryptoClientStream(
+ const QuicServerId& server_id,
+ QuicClientSessionBase* session,
+ ProofVerifyContext* verify_context,
+ QuicCryptoClientConfig* crypto_config,
+ HandshakeMode handshake_mode,
+ const ProofVerifyDetailsChromium* proof_verify_details_);
~MockCryptoClientStream() override;
// CryptoFramerVisitorInterface implementation.
@@ -58,9 +61,9 @@ class MockCryptoClientStream : public QuicCryptoClientStream {
private:
void SetConfigNegotiated();
- QuicClientSessionBase* client_session();
- const ProofVerifyDetails* proof_verify_details_;
+ const QuicServerId server_id_;
+ const ProofVerifyDetailsChromium* proof_verify_details_;
DISALLOW_COPY_AND_ASSIGN(MockCryptoClientStream);
};
diff --git a/chromium/net/quic/test_tools/mock_crypto_client_stream_factory.cc b/chromium/net/quic/test_tools/mock_crypto_client_stream_factory.cc
index 1773059e20e..52501788b4a 100644
--- a/chromium/net/quic/test_tools/mock_crypto_client_stream_factory.cc
+++ b/chromium/net/quic/test_tools/mock_crypto_client_stream_factory.cc
@@ -25,7 +25,7 @@ MockCryptoClientStreamFactory::CreateQuicCryptoClientStream(
QuicChromiumClientSession* session,
scoped_ptr<ProofVerifyContext> /*proof_verify_context*/,
QuicCryptoClientConfig* crypto_config) {
- const ProofVerifyDetails* proof_verify_details = nullptr;
+ const ProofVerifyDetailsChromium* proof_verify_details = nullptr;
if (!proof_verify_details_queue_.empty()) {
proof_verify_details = proof_verify_details_queue_.front();
proof_verify_details_queue_.pop();
diff --git a/chromium/net/quic/test_tools/mock_crypto_client_stream_factory.h b/chromium/net/quic/test_tools/mock_crypto_client_stream_factory.h
index 5ca04bfbaa1..1a12a39f78c 100644
--- a/chromium/net/quic/test_tools/mock_crypto_client_stream_factory.h
+++ b/chromium/net/quic/test_tools/mock_crypto_client_stream_factory.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/macros.h"
+#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/quic/quic_crypto_client_stream.h"
#include "net/quic/quic_crypto_client_stream_factory.h"
#include "net/quic/test_tools/mock_crypto_client_stream.h"
@@ -34,7 +35,8 @@ class MockCryptoClientStreamFactory : public QuicCryptoClientStreamFactory {
}
// The caller keeps ownership of |proof_verify_details|.
- void AddProofVerifyDetails(const ProofVerifyDetails* proof_verify_details) {
+ void AddProofVerifyDetails(
+ const ProofVerifyDetailsChromium* proof_verify_details) {
proof_verify_details_queue_.push(proof_verify_details);
}
@@ -43,7 +45,7 @@ class MockCryptoClientStreamFactory : public QuicCryptoClientStreamFactory {
private:
MockCryptoClientStream::HandshakeMode handshake_mode_;
MockCryptoClientStream* last_stream_;
- std::queue<const ProofVerifyDetails*> proof_verify_details_queue_;
+ std::queue<const ProofVerifyDetailsChromium*> proof_verify_details_queue_;
DISALLOW_COPY_AND_ASSIGN(MockCryptoClientStreamFactory);
};
diff --git a/chromium/net/quic/test_tools/mock_quic_client_promised_info.cc b/chromium/net/quic/test_tools/mock_quic_client_promised_info.cc
new file mode 100644
index 00000000000..793ed3fdf6a
--- /dev/null
+++ b/chromium/net/quic/test_tools/mock_quic_client_promised_info.cc
@@ -0,0 +1,21 @@
+// 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/mock_quic_client_promised_info.h"
+
+using std::string;
+
+namespace net {
+namespace test {
+
+MockQuicClientPromisedInfo::MockQuicClientPromisedInfo(
+ QuicClientSessionBase* session,
+ QuicStreamId id,
+ string url)
+ : QuicClientPromisedInfo(session, id, url) {}
+
+MockQuicClientPromisedInfo::~MockQuicClientPromisedInfo() {}
+
+} // namespace test
+} // namespace net
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
new file mode 100644
index 00000000000..40da296de8a
--- /dev/null
+++ b/chromium/net/quic/test_tools/mock_quic_client_promised_info.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_QUIC_TEST_TOOLS_MOCK_QUIC_CLIENT_PROMISED_INFO_H_
+#define NET_QUIC_TEST_TOOLS_MOCK_QUIC_CLIENT_PROMISED_INFO_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "net/quic/quic_client_promised_info.h"
+#include "net/quic/quic_protocol.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace net {
+namespace test {
+
+class MockQuicClientPromisedInfo : public QuicClientPromisedInfo {
+ public:
+ MockQuicClientPromisedInfo(QuicClientSessionBase* session,
+ QuicStreamId id,
+ std::string url);
+ ~MockQuicClientPromisedInfo() override;
+
+ MOCK_METHOD2(HandleClientRequest,
+ QuicAsyncStatus(const SpdyHeaderBlock& headers,
+ QuicClientPushPromiseIndex::Delegate* delegate));
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_QUIC_TEST_TOOLS_MOCK_QUIC_CLIENT_PROMISED_INFO_H_
diff --git a/chromium/net/quic/test_tools/mock_quic_dispatcher.cc b/chromium/net/quic/test_tools/mock_quic_dispatcher.cc
index 66b940b8e45..a31365198c8 100644
--- a/chromium/net/quic/test_tools/mock_quic_dispatcher.cc
+++ b/chromium/net/quic/test_tools/mock_quic_dispatcher.cc
@@ -13,10 +13,7 @@ MockQuicDispatcher::MockQuicDispatcher(
const QuicConfig& config,
const QuicCryptoServerConfig* crypto_config,
QuicConnectionHelperInterface* helper)
- : QuicDispatcher(config,
- crypto_config,
- QuicSupportedVersions(),
- helper) {}
+ : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), helper) {}
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 2ef15809703..05c9c9baa55 100644
--- a/chromium/net/quic/test_tools/mock_quic_dispatcher.h
+++ b/chromium/net/quic/test_tools/mock_quic_dispatcher.h
@@ -16,7 +16,7 @@
namespace net {
namespace test {
-class MockQuicDispatcher : public tools::QuicDispatcher {
+class MockQuicDispatcher : public QuicDispatcher {
public:
MockQuicDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig* crypto_config,
@@ -27,7 +27,7 @@ class MockQuicDispatcher : public tools::QuicDispatcher {
MOCK_METHOD3(ProcessPacket,
void(const IPEndPoint& server_address,
const IPEndPoint& client_address,
- const QuicEncryptedPacket& packet));
+ const QuicReceivedPacket& packet));
private:
DISALLOW_COPY_AND_ASSIGN(MockQuicDispatcher);
diff --git a/chromium/net/quic/test_tools/mock_quic_spdy_client_stream.cc b/chromium/net/quic/test_tools/mock_quic_spdy_client_stream.cc
new file mode 100644
index 00000000000..874f89f675d
--- /dev/null
+++ b/chromium/net/quic/test_tools/mock_quic_spdy_client_stream.cc
@@ -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.
+
+#include "net/quic/test_tools/mock_quic_spdy_client_stream.h"
+
+using net::QuicClientSession;
+
+namespace net {
+namespace test {
+
+MockQuicSpdyClientStream::MockQuicSpdyClientStream(QuicStreamId id,
+ QuicClientSession* session)
+ : QuicSpdyClientStream(id, session) {}
+
+MockQuicSpdyClientStream::~MockQuicSpdyClientStream() {}
+
+} // namespace test
+} // namespace net
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
new file mode 100644
index 00000000000..d5bd14f15b9
--- /dev/null
+++ b/chromium/net/quic/test_tools/mock_quic_spdy_client_stream.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_TEST_TOOLS_MOCK_QUIC_SPDY_CLIENT_STREAM_H_
+#define NET_QUIC_TEST_TOOLS_MOCK_QUIC_SPDY_CLIENT_STREAM_H_
+
+#include "base/macros.h"
+#include "net/quic/quic_protocol.h"
+#include "net/tools/quic/quic_spdy_client_stream.h"
+#include "testing/gmock/include/gmock/gmock.h"
+// #include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+class MockQuicSpdyClientStream : public net::QuicSpdyClientStream {
+ public:
+ MockQuicSpdyClientStream(QuicStreamId id, net::QuicClientSession* session);
+ ~MockQuicSpdyClientStream() override;
+
+ MOCK_METHOD1(OnStreamFrame, void(const QuicStreamFrame& frame));
+ MOCK_METHOD2(OnInitialHeadersComplete, void(bool fin, size_t frame_len));
+ MOCK_METHOD2(OnTrailingHeadersComplete, void(bool fin, size_t frame_len));
+ MOCK_METHOD1(OnPromiseHeaders, void(base::StringPiece headers_data));
+ MOCK_METHOD2(OnPromiseHeadersComplete,
+ void(QuicStreamId promised_stream_id, size_t frame_len));
+ MOCK_METHOD0(OnDataAvailable, void());
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_QUIC_TEST_TOOLS_MOCK_QUIC_SPDY_CLIENT_STREAM_H_
diff --git a/chromium/net/quic/test_tools/quic_config_peer.cc b/chromium/net/quic/test_tools/quic_config_peer.cc
index 84fa19007ce..6c0daa70eca 100644
--- a/chromium/net/quic/test_tools/quic_config_peer.cc
+++ b/chromium/net/quic/test_tools/quic_config_peer.cc
@@ -45,5 +45,10 @@ void QuicConfigPeer::SetReceivedBytesForConnectionId(QuicConfig* config,
config->bytes_for_connection_id_.SetReceivedValue(bytes);
}
+// static
+void QuicConfigPeer::SetReceivedDisableConnectionMigration(QuicConfig* config) {
+ config->connection_migration_disabled_.SetReceivedValue(1);
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/test_tools/quic_config_peer.h b/chromium/net/quic/test_tools/quic_config_peer.h
index c212270fafe..c74d330d3be 100644
--- a/chromium/net/quic/test_tools/quic_config_peer.h
+++ b/chromium/net/quic/test_tools/quic_config_peer.h
@@ -33,6 +33,7 @@ class QuicConfigPeer {
static void SetReceivedBytesForConnectionId(QuicConfig* config,
uint32_t bytes);
+ static void SetReceivedDisableConnectionMigration(QuicConfig* config);
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 f171bff8ca6..8b2407c34d5 100644
--- a/chromium/net/quic/test_tools/quic_connection_peer.cc
+++ b/chromium/net/quic/test_tools/quic_connection_peer.cc
@@ -6,7 +6,6 @@
#include "base/stl_util.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
-#include "net/quic/quic_connection.h"
#include "net/quic/quic_packet_writer.h"
#include "net/quic/quic_received_packet_manager.h"
#include "net/quic/test_tools/quic_framer_peer.h"
@@ -29,9 +28,9 @@ void QuicConnectionPeer::SetSendAlgorithm(
}
// static
-void QuicConnectionPeer::PopulateAckFrame(QuicConnection* connection,
- QuicAckFrame* ack) {
- connection->PopulateAckFrame(ack);
+const QuicFrame QuicConnectionPeer::GetUpdatedAckFrame(
+ QuicConnection* connection) {
+ return connection->GetUpdatedAckFrame();
}
// static
@@ -125,7 +124,8 @@ void QuicConnectionPeer::SetPeerAddress(QuicConnection* connection,
// static
bool QuicConnectionPeer::IsSilentCloseEnabled(QuicConnection* connection) {
- return connection->silent_close_enabled_;
+ return connection->idle_timeout_connection_close_behavior_ ==
+ ConnectionCloseBehavior::SILENT_CLOSE;
}
// static
@@ -151,13 +151,6 @@ QuicFramer* QuicConnectionPeer::GetFramer(QuicConnection* connection) {
}
// static
-QuicFecGroup* QuicConnectionPeer::GetFecGroup(QuicConnection* connection,
- int fec_group) {
- connection->last_header_.fec_group = fec_group;
- return connection->GetFecGroup();
-}
-
-// static
QuicAlarm* QuicConnectionPeer::GetAckAlarm(QuicConnection* connection) {
return connection->ack_alarm_.get();
}
@@ -168,11 +161,6 @@ QuicAlarm* QuicConnectionPeer::GetPingAlarm(QuicConnection* connection) {
}
// static
-QuicAlarm* QuicConnectionPeer::GetFecAlarm(QuicConnection* connection) {
- return connection->fec_alarm_.get();
-}
-
-// static
QuicAlarm* QuicConnectionPeer::GetResumeWritesAlarm(
QuicConnection* connection) {
return connection->resume_writes_alarm_.get();
@@ -217,7 +205,8 @@ void QuicConnectionPeer::SetWriter(QuicConnection* connection,
}
// static
-void QuicConnectionPeer::CloseConnection(QuicConnection* connection) {
+void QuicConnectionPeer::TearDownLocalConnectionState(
+ QuicConnection* connection) {
connection->connected_ = false;
}
@@ -268,8 +257,9 @@ void QuicConnectionPeer::SetNextMtuProbeAt(QuicConnection* connection,
}
// static
-void QuicConnectionPeer::EnableAckDecimation(QuicConnection* connection) {
- connection->ack_decimation_enabled_ = true;
+void QuicConnectionPeer::SetAckMode(QuicConnection* connection,
+ QuicConnection::AckMode ack_mode) {
+ connection->ack_mode_ = ack_mode;
}
} // 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 524eb159ffc..d6130e9f36a 100644
--- a/chromium/net/quic/test_tools/quic_connection_peer.h
+++ b/chromium/net/quic/test_tools/quic_connection_peer.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "net/base/ip_endpoint.h"
+#include "net/quic/quic_connection.h"
#include "net/quic/quic_connection_stats.h"
#include "net/quic/quic_protocol.h"
@@ -15,11 +16,9 @@ namespace net {
struct QuicAckFrame;
struct QuicPacketHeader;
class QuicAlarm;
-class QuicConnection;
class QuicConnectionHelperInterface;
class QuicConnectionVisitorInterface;
class QuicEncryptedPacket;
-class QuicFecGroup;
class QuicFramer;
class QuicPacketCreator;
class QuicPacketGenerator;
@@ -39,7 +38,7 @@ class QuicConnectionPeer {
static void SetSendAlgorithm(QuicConnection* connection,
SendAlgorithmInterface* send_algorithm);
- static void PopulateAckFrame(QuicConnection* connection, QuicAckFrame* ack);
+ static const QuicFrame GetUpdatedAckFrame(QuicConnection* connection);
static void PopulateStopWaitingFrame(QuicConnection* connection,
QuicStopWaitingFrame* stop_waiting);
@@ -88,12 +87,8 @@ class QuicConnectionPeer {
static QuicFramer* GetFramer(QuicConnection* connection);
- // Set last_header_->fec_group = fec_group and return connection->GetFecGroup
- static QuicFecGroup* GetFecGroup(QuicConnection* connection, int fec_group);
-
static QuicAlarm* GetAckAlarm(QuicConnection* connection);
static QuicAlarm* GetPingAlarm(QuicConnection* connection);
- static QuicAlarm* GetFecAlarm(QuicConnection* connection);
static QuicAlarm* GetResumeWritesAlarm(QuicConnection* connection);
static QuicAlarm* GetRetransmissionAlarm(QuicConnection* connection);
static QuicAlarm* GetSendAlarm(QuicConnection* connection);
@@ -105,7 +100,7 @@ class QuicConnectionPeer {
static void SetWriter(QuicConnection* connection,
QuicPacketWriter* writer,
bool owns_writer);
- static void CloseConnection(QuicConnection* connection);
+ static void TearDownLocalConnectionState(QuicConnection* connection);
static QuicEncryptedPacket* GetConnectionClosePacket(
QuicConnection* connection);
@@ -122,7 +117,8 @@ class QuicConnectionPeer {
QuicPacketCount packets);
static void SetNextMtuProbeAt(QuicConnection* connection,
QuicPacketNumber number);
- static void EnableAckDecimation(QuicConnection* connection);
+ static void SetAckMode(QuicConnection* connection,
+ QuicConnection::AckMode ack_mode);
private:
DISALLOW_COPY_AND_ASSIGN(QuicConnectionPeer);
diff --git a/chromium/net/quic/test_tools/quic_framer_peer.cc b/chromium/net/quic/test_tools/quic_framer_peer.cc
index dd997365b53..aadecb6b73d 100644
--- a/chromium/net/quic/test_tools/quic_framer_peer.cc
+++ b/chromium/net/quic/test_tools/quic_framer_peer.cc
@@ -4,6 +4,7 @@
#include "net/quic/test_tools/quic_framer_peer.h"
+#include "base/stl_util.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_protocol.h"
@@ -75,5 +76,10 @@ QuicPathId QuicFramerPeer::GetLastPathId(QuicFramer* framer) {
return framer->last_path_id_;
}
+// static
+bool QuicFramerPeer::IsPathClosed(QuicFramer* framer, QuicPathId path_id) {
+ return ContainsKey(framer->closed_paths_, path_id);
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/test_tools/quic_framer_peer.h b/chromium/net/quic/test_tools/quic_framer_peer.h
index a31ab265818..8d14c05a3ef 100644
--- a/chromium/net/quic/test_tools/quic_framer_peer.h
+++ b/chromium/net/quic/test_tools/quic_framer_peer.h
@@ -37,6 +37,8 @@ class QuicFramerPeer {
static QuicPathId GetLastPathId(QuicFramer* framer);
+ static bool IsPathClosed(QuicFramer* framer, QuicPathId path_id);
+
private:
DISALLOW_COPY_AND_ASSIGN(QuicFramerPeer);
};
diff --git a/chromium/net/quic/test_tools/quic_packet_creator_peer.cc b/chromium/net/quic/test_tools/quic_packet_creator_peer.cc
index 48ad5ca749b..83b783c4d38 100644
--- a/chromium/net/quic/test_tools/quic_packet_creator_peer.cc
+++ b/chromium/net/quic/test_tools/quic_packet_creator_peer.cc
@@ -15,6 +15,11 @@ bool QuicPacketCreatorPeer::SendVersionInPacket(QuicPacketCreator* creator) {
}
// static
+bool QuicPacketCreatorPeer::SendPathIdInPacket(QuicPacketCreator* creator) {
+ return creator->send_path_id_in_packet_;
+}
+
+// static
void QuicPacketCreatorPeer::SetSendVersionInPacket(
QuicPacketCreator* creator,
bool send_version_in_packet) {
@@ -22,10 +27,16 @@ void QuicPacketCreatorPeer::SetSendVersionInPacket(
}
// static
+void QuicPacketCreatorPeer::SetSendPathIdInPacket(QuicPacketCreator* creator,
+ bool send_path_id_in_packet) {
+ creator->send_path_id_in_packet_ = send_path_id_in_packet;
+}
+
+// static
void QuicPacketCreatorPeer::SetPacketNumberLength(
QuicPacketCreator* creator,
QuicPacketNumberLength packet_number_length) {
- creator->packet_number_length_ = packet_number_length;
+ creator->packet_.packet_number_length = packet_number_length;
}
// static
@@ -44,20 +55,18 @@ QuicPacketNumberLength QuicPacketCreatorPeer::NextPacketNumberLength(
// static
QuicPacketNumberLength QuicPacketCreatorPeer::GetPacketNumberLength(
QuicPacketCreator* creator) {
- return creator->packet_number_length_;
+ return creator->packet_.packet_number_length;
}
void QuicPacketCreatorPeer::SetPacketNumber(QuicPacketCreator* creator,
QuicPacketNumber s) {
- creator->packet_number_ = s;
+ creator->packet_.packet_number = s;
}
// static
void QuicPacketCreatorPeer::FillPacketHeader(QuicPacketCreator* creator,
- QuicFecGroupNumber fec_group,
- bool fec_flag,
QuicPacketHeader* header) {
- creator->FillPacketHeader(fec_group, fec_flag, header);
+ creator->FillPacketHeader(header);
}
// static
@@ -72,60 +81,34 @@ size_t QuicPacketCreatorPeer::CreateStreamFrame(QuicPacketCreator* creator,
}
// static
-bool QuicPacketCreatorPeer::IsFecProtected(QuicPacketCreator* creator) {
- return creator->fec_protect_;
-}
-
-// static
-bool QuicPacketCreatorPeer::IsFecEnabled(QuicPacketCreator* creator) {
- return creator->max_packets_per_fec_group_ > 0;
-}
-
-// static
-void QuicPacketCreatorPeer::StartFecProtectingPackets(
- QuicPacketCreator* creator) {
- creator->StartFecProtectingPackets();
-}
-
-// static
-void QuicPacketCreatorPeer::StopFecProtectingPackets(
- QuicPacketCreator* creator) {
- creator->StopFecProtectingPackets();
-}
-
-// static
-SerializedPacket QuicPacketCreatorPeer::SerializeFec(QuicPacketCreator* creator,
- char* buffer,
- size_t buffer_len) {
- return creator->SerializeFec(buffer, buffer_len);
-}
-
-// static
-void QuicPacketCreatorPeer::ResetFecGroup(QuicPacketCreator* creator) {
- creator->ResetFecGroup();
-}
-
-// static
-QuicTime::Delta QuicPacketCreatorPeer::GetFecTimeout(
- QuicPacketCreator* creator) {
- return creator->fec_timeout_;
-}
-
-// static
-float QuicPacketCreatorPeer::GetRttMultiplierForFecTimeout(
- QuicPacketCreator* creator) {
- return creator->rtt_multiplier_for_fec_timeout_;
+SerializedPacket QuicPacketCreatorPeer::SerializeAllFrames(
+ QuicPacketCreator* creator,
+ const QuicFrames& frames,
+ char* buffer,
+ size_t buffer_len) {
+ DCHECK(creator->queued_frames_.empty());
+ DCHECK(!frames.empty());
+ for (const QuicFrame& frame : frames) {
+ bool success = creator->AddFrame(frame, false);
+ DCHECK(success);
+ }
+ creator->SerializePacket(buffer, buffer_len);
+ SerializedPacket packet = creator->packet_;
+ // The caller takes ownership of the QuicEncryptedPacket.
+ creator->packet_.encrypted_buffer = nullptr;
+ DCHECK(packet.retransmittable_frames.empty());
+ return packet;
}
// static
EncryptionLevel QuicPacketCreatorPeer::GetEncryptionLevel(
QuicPacketCreator* creator) {
- return creator->encryption_level_;
+ return creator->packet_.encryption_level;
}
// static
QuicPathId QuicPacketCreatorPeer::GetCurrentPath(QuicPacketCreator* creator) {
- return creator->current_path_;
+ return creator->packet_.path_id;
}
} // namespace test
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 a5ac0eda086..6849c1f1bd1 100644
--- a/chromium/net/quic/test_tools/quic_packet_creator_peer.h
+++ b/chromium/net/quic/test_tools/quic_packet_creator_peer.h
@@ -18,9 +18,12 @@ namespace test {
class QuicPacketCreatorPeer {
public:
static bool SendVersionInPacket(QuicPacketCreator* creator);
+ static bool SendPathIdInPacket(QuicPacketCreator* creator);
static void SetSendVersionInPacket(QuicPacketCreator* creator,
bool send_version_in_packet);
+ static void SetSendPathIdInPacket(QuicPacketCreator* creator,
+ bool send_path_id_in_packet);
static void SetPacketNumberLength(
QuicPacketCreator* creator,
QuicPacketNumberLength packet_number_length);
@@ -33,8 +36,6 @@ class QuicPacketCreatorPeer {
QuicPacketCreator* creator);
static void SetPacketNumber(QuicPacketCreator* creator, QuicPacketNumber s);
static void FillPacketHeader(QuicPacketCreator* creator,
- QuicFecGroupNumber fec_group,
- bool fec_flag,
QuicPacketHeader* header);
static size_t CreateStreamFrame(QuicPacketCreator* creator,
QuicStreamId id,
@@ -43,17 +44,10 @@ class QuicPacketCreatorPeer {
QuicStreamOffset offset,
bool fin,
QuicFrame* frame);
- static bool IsFecProtected(QuicPacketCreator* creator);
- static bool IsFecEnabled(QuicPacketCreator* creator);
- static void StartFecProtectingPackets(QuicPacketCreator* creator);
- static void StopFecProtectingPackets(QuicPacketCreator* creator);
- static SerializedPacket SerializeFec(QuicPacketCreator* creator,
- char* buffer,
- size_t buffer_len);
- static void ResetFecGroup(QuicPacketCreator* creator);
- static QuicTime::Delta GetFecTimeout(QuicPacketCreator* creator);
- // TODO(rtenneti): Delete this code after the 0.25 RTT FEC experiment.
- static float GetRttMultiplierForFecTimeout(QuicPacketCreator* creator);
+ static SerializedPacket SerializeAllFrames(QuicPacketCreator* creator,
+ const QuicFrames& frames,
+ char* buffer,
+ size_t buffer_len);
static EncryptionLevel GetEncryptionLevel(QuicPacketCreator* creator);
static QuicPathId GetCurrentPath(QuicPacketCreator* creator);
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 a5f63fcbdd0..8e6ec36c9b9 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
@@ -53,7 +53,7 @@ void QuicSentPacketManagerPeer::SetPerspective(
}
// static
-const SendAlgorithmInterface* QuicSentPacketManagerPeer::GetSendAlgorithm(
+SendAlgorithmInterface* QuicSentPacketManagerPeer::GetSendAlgorithm(
const QuicSentPacketManager& sent_packet_manager) {
return sent_packet_manager.send_algorithm_.get();
}
@@ -106,21 +106,15 @@ bool QuicSentPacketManagerPeer::IsRetransmission(
QuicSentPacketManager* sent_packet_manager,
QuicPacketNumber packet_number) {
DCHECK(sent_packet_manager->HasRetransmittableFrames(packet_number));
- if (FLAGS_quic_track_single_retransmission) {
- if (!sent_packet_manager->HasRetransmittableFrames(packet_number)) {
- return false;
- }
- for (auto transmission_info : sent_packet_manager->unacked_packets_) {
- if (transmission_info.retransmission == packet_number) {
- return true;
- }
- }
+ if (!sent_packet_manager->HasRetransmittableFrames(packet_number)) {
return false;
}
- return sent_packet_manager->HasRetransmittableFrames(packet_number) &&
- sent_packet_manager->unacked_packets_.GetTransmissionInfo(
- packet_number)
- .all_transmissions != nullptr;
+ for (auto transmission_info : sent_packet_manager->unacked_packets_) {
+ if (transmission_info.retransmission == packet_number) {
+ return true;
+ }
+ }
+ return false;
}
// static
@@ -150,7 +144,7 @@ size_t QuicSentPacketManagerPeer::GetNumRetransmittablePackets(
for (QuicUnackedPacketMap::const_iterator it =
sent_packet_manager->unacked_packets_.begin();
it != sent_packet_manager->unacked_packets_.end(); ++it) {
- if (it->retransmittable_frames != nullptr) {
+ if (!it->retransmittable_frames.empty()) {
++num_unacked_packets;
}
}
@@ -171,6 +165,20 @@ QuicSentPacketManagerPeer::GetNetworkChangeVisitor(
}
// static
+void QuicSentPacketManagerPeer::SetConsecutiveRtoCount(
+ QuicSentPacketManager* sent_packet_manager,
+ size_t count) {
+ sent_packet_manager->consecutive_rto_count_ = count;
+}
+
+// static
+void QuicSentPacketManagerPeer::SetConsecutiveTlpCount(
+ QuicSentPacketManager* sent_packet_manager,
+ size_t count) {
+ sent_packet_manager->consecutive_tlp_count_ = count;
+}
+
+// static
QuicSustainedBandwidthRecorder& QuicSentPacketManagerPeer::GetBandwidthRecorder(
QuicSentPacketManager* sent_packet_manager) {
return sent_packet_manager->sustained_bandwidth_recorder_;
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 d7f28ebd846..9fbbd28e231 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
@@ -36,7 +36,7 @@ class QuicSentPacketManagerPeer {
static void SetPerspective(QuicSentPacketManager* sent_packet_manager,
Perspective perspective);
- static const SendAlgorithmInterface* GetSendAlgorithm(
+ static SendAlgorithmInterface* GetSendAlgorithm(
const QuicSentPacketManager& sent_packet_manager);
static void SetSendAlgorithm(QuicSentPacketManager* sent_packet_manager,
@@ -79,6 +79,12 @@ class QuicSentPacketManagerPeer {
static QuicSentPacketManager::NetworkChangeVisitor* GetNetworkChangeVisitor(
const QuicSentPacketManager* sent_packet_manager);
+ static void SetConsecutiveRtoCount(QuicSentPacketManager* sent_packet_manager,
+ size_t count);
+
+ static void SetConsecutiveTlpCount(QuicSentPacketManager* sent_packet_manager,
+ size_t count);
+
static QuicSustainedBandwidthRecorder& GetBandwidthRecorder(
QuicSentPacketManager* sent_packet_manager);
diff --git a/chromium/net/quic/test_tools/quic_session_peer.cc b/chromium/net/quic/test_tools/quic_session_peer.cc
index 64ca722d00a..04f59123d76 100644
--- a/chromium/net/quic/test_tools/quic_session_peer.cc
+++ b/chromium/net/quic/test_tools/quic_session_peer.cc
@@ -25,9 +25,15 @@ void QuicSessionPeer::SetNextOutgoingStreamId(QuicSession* session,
}
// static
-void QuicSessionPeer::SetMaxOpenStreams(QuicSession* session,
- uint32_t max_streams) {
- session->max_open_streams_ = max_streams;
+void QuicSessionPeer::SetMaxOpenIncomingStreams(QuicSession* session,
+ uint32_t max_streams) {
+ session->max_open_incoming_streams_ = max_streams;
+}
+
+// static
+void QuicSessionPeer::SetMaxOpenOutgoingStreams(QuicSession* session,
+ uint32_t max_streams) {
+ session->max_open_outgoing_streams_ = max_streams;
}
// static
@@ -65,7 +71,7 @@ QuicSession::StreamMap& QuicSessionPeer::dynamic_streams(QuicSession* session) {
}
// static
-base::hash_set<QuicStreamId>* QuicSessionPeer::GetDrainingStreams(
+std::unordered_set<QuicStreamId>* QuicSessionPeer::GetDrainingStreams(
QuicSession* session) {
return &session->draining_streams_;
}
diff --git a/chromium/net/quic/test_tools/quic_session_peer.h b/chromium/net/quic/test_tools/quic_session_peer.h
index bf9af6934f8..dcc60b990ae 100644
--- a/chromium/net/quic/test_tools/quic_session_peer.h
+++ b/chromium/net/quic/test_tools/quic_session_peer.h
@@ -9,7 +9,6 @@
#include <map>
-#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_session.h"
@@ -29,7 +28,10 @@ class QuicSessionPeer {
public:
static QuicStreamId GetNextOutgoingStreamId(QuicSession* session);
static void SetNextOutgoingStreamId(QuicSession* session, QuicStreamId id);
- static void SetMaxOpenStreams(QuicSession* session, uint32_t max_streams);
+ static void SetMaxOpenIncomingStreams(QuicSession* session,
+ uint32_t max_streams);
+ static void SetMaxOpenOutgoingStreams(QuicSession* session,
+ uint32_t max_streams);
static QuicCryptoStream* GetCryptoStream(QuicSession* session);
static QuicWriteBlockedList* GetWriteBlockedStreams(QuicSession* session);
static ReliableQuicStream* GetOrCreateDynamicStream(QuicSession* session,
@@ -38,7 +40,8 @@ class QuicSessionPeer {
GetLocallyClosedStreamsHighestOffset(QuicSession* session);
static QuicSession::StreamMap& static_streams(QuicSession* session);
static QuicSession::StreamMap& dynamic_streams(QuicSession* session);
- static base::hash_set<QuicStreamId>* GetDrainingStreams(QuicSession* session);
+ static std::unordered_set<QuicStreamId>* GetDrainingStreams(
+ QuicSession* session);
// Discern the state of a stream. Exactly one of these should be true at a
// time for any stream id > 0 (other than the special streams 1 and 3).
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 99c4ef3feba..bcb7ba7a364 100644
--- a/chromium/net/quic/test_tools/quic_stream_factory_peer.cc
+++ b/chromium/net/quic/test_tools/quic_stream_factory_peer.cc
@@ -157,8 +157,18 @@ void QuicStreamFactoryPeer::CacheDummyServerConfig(
QuicCryptoClientConfig::CachedState* cached =
crypto_config->LookupOrCreate(quic_server_id);
QuicClock clock;
- cached->Initialize(server_config, source_address_token, certs, "", signature,
- clock.WallNow());
+ cached->Initialize(server_config, source_address_token, certs, "", "",
+ signature, clock.WallNow());
+}
+
+QuicClientPushPromiseIndex* QuicStreamFactoryPeer::GetPushPromiseIndex(
+ QuicStreamFactory* factory) {
+ return &factory->push_promise_index_;
+}
+
+int QuicStreamFactoryPeer::GetNumPushStreamsCreated(
+ QuicStreamFactory* factory) {
+ return factory->num_push_streams_created_;
}
} // namespace test
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 2f731764f45..c2d299322ce 100644
--- a/chromium/net/quic/test_tools/quic_stream_factory_peer.h
+++ b/chromium/net/quic/test_tools/quic_stream_factory_peer.h
@@ -23,6 +23,7 @@ class QuicCryptoClientConfig;
class QuicHttpStream;
class QuicStreamFactory;
class QuicChromiumClientSession;
+class QuicClientPushPromiseIndex;
namespace test {
@@ -85,6 +86,11 @@ class QuicStreamFactoryPeer {
static void CacheDummyServerConfig(QuicStreamFactory* factory,
const QuicServerId& quic_server_id);
+ static QuicClientPushPromiseIndex* GetPushPromiseIndex(
+ QuicStreamFactory* factory);
+
+ static int GetNumPushStreamsCreated(QuicStreamFactory* factory);
+
private:
DISALLOW_COPY_AND_ASSIGN(QuicStreamFactoryPeer);
};
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 290e2eaa198..739db22b4f2 100644
--- a/chromium/net/quic/test_tools/quic_stream_sequencer_peer.cc
+++ b/chromium/net/quic/test_tools/quic_stream_sequencer_peer.cc
@@ -15,17 +15,7 @@ namespace test {
// static
size_t QuicStreamSequencerPeer::GetNumBufferedBytes(
QuicStreamSequencer* sequencer) {
- return sequencer->buffered_frames_->BytesBuffered();
-}
-
-// static
-bool QuicStreamSequencerPeer::FrameOverlapsBufferedData(
- QuicFrameList* buffer,
- const QuicStreamFrame& frame) {
- list<QuicFrameList::FrameData>::iterator it =
- buffer->FindInsertionPoint(frame.offset, frame.frame_length);
- return buffer->FrameOverlapsBufferedData(frame.offset, frame.frame_length,
- it);
+ return sequencer->buffered_frames_.BytesBuffered();
}
// static
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 f25c8984b69..f5307e1f53a 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,6 @@
#include <stddef.h>
#include "base/macros.h"
-#include "net/quic/quic_frame_list.h"
#include "net/quic/quic_protocol.h"
namespace net {
@@ -21,9 +20,6 @@ class QuicStreamSequencerPeer {
public:
static size_t GetNumBufferedBytes(QuicStreamSequencer* sequencer);
- static bool FrameOverlapsBufferedData(QuicFrameList* buffer,
- const QuicStreamFrame& frame);
-
static QuicStreamOffset GetCloseOffset(QuicStreamSequencer* sequencer);
private:
diff --git a/chromium/net/quic/test_tools/quic_test_packet_maker.cc b/chromium/net/quic/test_tools/quic_test_packet_maker.cc
index 25f0f4310f3..67e0ffa91fd 100644
--- a/chromium/net/quic/test_tools/quic_test_packet_maker.cc
+++ b/chromium/net/quic/test_tools/quic_test_packet_maker.cc
@@ -33,7 +33,7 @@ void QuicTestPacketMaker::set_hostname(const std::string& host) {
host_.assign(host);
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakePingPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakePingPacket(
QuicPacketNumber num,
bool include_version) {
QuicPacketHeader header;
@@ -47,14 +47,23 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakePingPacket(
header.fec_group = 0;
QuicPingFrame ping;
- return scoped_ptr<QuicEncryptedPacket>(MakePacket(header, QuicFrame(ping)));
+ return scoped_ptr<QuicReceivedPacket>(MakePacket(header, QuicFrame(ping)));
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRstPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeRstPacket(
QuicPacketNumber num,
bool include_version,
QuicStreamId stream_id,
QuicRstStreamErrorCode error_code) {
+ return MakeRstPacket(num, include_version, stream_id, error_code, 0);
+}
+
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeRstPacket(
+ QuicPacketNumber num,
+ bool include_version,
+ QuicStreamId stream_id,
+ QuicRstStreamErrorCode error_code,
+ size_t bytes_written) {
QuicPacketHeader header;
header.public_header.connection_id = connection_id_;
header.public_header.reset_flag = false;
@@ -65,17 +74,19 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRstPacket(
header.fec_flag = false;
header.fec_group = 0;
- QuicRstStreamFrame rst(stream_id, error_code, 0);
- return scoped_ptr<QuicEncryptedPacket>(MakePacket(header, QuicFrame(&rst)));
+ QuicRstStreamFrame rst(stream_id, error_code, bytes_written);
+ DVLOG(1) << "Adding frame: " << QuicFrame(&rst);
+ return scoped_ptr<QuicReceivedPacket>(MakePacket(header, QuicFrame(&rst)));
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckAndRstPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeAckAndRstPacket(
QuicPacketNumber num,
bool include_version,
QuicStreamId stream_id,
QuicRstStreamErrorCode error_code,
QuicPacketNumber largest_received,
- QuicPacketNumber least_unacked,
+ QuicPacketNumber ack_least_unacked,
+ QuicPacketNumber stop_least_unacked,
bool send_feedback) {
QuicPacketHeader header;
header.public_header.connection_id = connection_id_;
@@ -88,37 +99,41 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckAndRstPacket(
header.fec_group = 0;
QuicAckFrame ack(MakeAckFrame(largest_received));
- ack.delta_time_largest_observed = QuicTime::Delta::Zero();
- for (QuicPacketNumber i = least_unacked; i <= largest_received; ++i) {
+ 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()));
}
QuicFrames frames;
frames.push_back(QuicFrame(&ack));
+ DVLOG(1) << "Adding frame: " << frames[0];
QuicStopWaitingFrame stop_waiting;
- stop_waiting.least_unacked = least_unacked;
+ stop_waiting.least_unacked = stop_least_unacked;
frames.push_back(QuicFrame(&stop_waiting));
+ DVLOG(1) << "Adding frame: " << frames[1];
QuicRstStreamFrame rst(stream_id, error_code, 0);
frames.push_back(QuicFrame(&rst));
+ DVLOG(1) << "Adding frame: " << frames[2];
QuicFramer framer(SupportedVersions(version_), clock_->Now(),
Perspective::IS_CLIENT);
scoped_ptr<QuicPacket> packet(
BuildUnsizedDataPacket(&framer, header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_size = framer.EncryptPayload(
- ENCRYPTION_NONE, header.packet_number, *packet, buffer, kMaxPacketSize);
+ size_t encrypted_size = framer.EncryptPayload(ENCRYPTION_NONE, /*path_id=*/0u,
+ header.packet_number, *packet,
+ buffer, kMaxPacketSize);
EXPECT_NE(0u, encrypted_size);
- QuicEncryptedPacket encrypted(buffer, encrypted_size, false);
- return scoped_ptr<QuicEncryptedPacket>(encrypted.Clone());
+ QuicReceivedPacket encrypted(buffer, encrypted_size, QuicTime::Zero(), false);
+ return scoped_ptr<QuicReceivedPacket>(encrypted.Clone());
}
-scoped_ptr<QuicEncryptedPacket>
+scoped_ptr<QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndConnectionClosePacket(
QuicPacketNumber num,
bool include_version,
- QuicTime::Delta delta_time_largest_observed,
+ QuicTime::Delta ack_delay_time,
QuicPacketNumber largest_received,
QuicPacketNumber least_unacked,
QuicErrorCode quic_error,
@@ -134,7 +149,7 @@ QuicTestPacketMaker::MakeAckAndConnectionClosePacket(
header.fec_group = 0;
QuicAckFrame ack(MakeAckFrame(largest_received));
- ack.delta_time_largest_observed = delta_time_largest_observed;
+ 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()));
}
@@ -159,14 +174,15 @@ QuicTestPacketMaker::MakeAckAndConnectionClosePacket(
scoped_ptr<QuicPacket> packet(
BuildUnsizedDataPacket(&framer, header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_size = framer.EncryptPayload(
- ENCRYPTION_NONE, header.packet_number, *packet, buffer, kMaxPacketSize);
+ size_t encrypted_size = framer.EncryptPayload(ENCRYPTION_NONE, /*path_id=*/0u,
+ header.packet_number, *packet,
+ buffer, kMaxPacketSize);
EXPECT_NE(0u, encrypted_size);
- QuicEncryptedPacket encrypted(buffer, encrypted_size, false);
- return scoped_ptr<QuicEncryptedPacket>(encrypted.Clone());
+ QuicReceivedPacket encrypted(buffer, encrypted_size, clock_->Now(), false);
+ return scoped_ptr<QuicReceivedPacket>(encrypted.Clone());
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeConnectionClosePacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeConnectionClosePacket(
QuicPacketNumber num) {
QuicPacketHeader header;
header.public_header.connection_id = connection_id_;
@@ -181,12 +197,33 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeConnectionClosePacket(
QuicConnectionCloseFrame close;
close.error_code = QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
close.error_details = "Time to panic!";
- return scoped_ptr<QuicEncryptedPacket>(MakePacket(header, QuicFrame(&close)));
+ return scoped_ptr<QuicReceivedPacket>(MakePacket(header, QuicFrame(&close)));
+}
+
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeGoAwayPacket(
+ QuicPacketNumber num,
+ QuicErrorCode error_code,
+ std::string reason_phrase) {
+ QuicPacketHeader header;
+ header.public_header.connection_id = connection_id_;
+ header.public_header.reset_flag = false;
+ header.public_header.version_flag = false;
+ header.public_header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
+ header.packet_number = num;
+ header.entropy_flag = false;
+ header.fec_flag = false;
+ header.fec_group = 0;
+
+ QuicGoAwayFrame goaway;
+ goaway.error_code = error_code;
+ goaway.last_good_stream_id = 0;
+ goaway.reason_phrase = reason_phrase;
+ return scoped_ptr<QuicReceivedPacket>(MakePacket(header, QuicFrame(&goaway)));
}
// Sets both least_unacked fields in stop waiting frame and ack frame
// to be |least_unacked|.
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeAckPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber least_unacked,
@@ -195,7 +232,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckPacket(
least_unacked, send_feedback);
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeAckPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber ack_least_unacked,
@@ -212,7 +249,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckPacket(
header.fec_group = 0;
QuicAckFrame ack(MakeAckFrame(largest_received));
- ack.delta_time_largest_observed = QuicTime::Delta::Zero();
+ 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()));
}
@@ -229,15 +266,16 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckPacket(
scoped_ptr<QuicPacket> packet(
BuildUnsizedDataPacket(&framer, header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_size = framer.EncryptPayload(
- ENCRYPTION_NONE, header.packet_number, *packet, buffer, kMaxPacketSize);
+ size_t encrypted_size = framer.EncryptPayload(ENCRYPTION_NONE, /*path_id=*/0u,
+ header.packet_number, *packet,
+ buffer, kMaxPacketSize);
EXPECT_NE(0u, encrypted_size);
- QuicEncryptedPacket encrypted(buffer, encrypted_size, false);
- return scoped_ptr<QuicEncryptedPacket>(encrypted.Clone());
+ QuicReceivedPacket encrypted(buffer, encrypted_size, clock_->Now(), false);
+ return scoped_ptr<QuicReceivedPacket>(encrypted.Clone());
}
// Returns a newly created packet to send kData on stream 1.
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeDataPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeDataPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -249,7 +287,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeDataPacket(
return MakePacket(header_, QuicFrame(&frame));
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckAndDataPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeAckAndDataPacket(
QuicPacketNumber packet_number,
bool include_version,
QuicStreamId stream_id,
@@ -261,7 +299,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckAndDataPacket(
InitializeHeader(packet_number, include_version);
QuicAckFrame ack(MakeAckFrame(largest_received));
- ack.delta_time_largest_observed = QuicTime::Delta::Zero();
+ 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()));
}
@@ -278,7 +316,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckAndDataPacket(
return MakeMultipleFramesPacket(header_, frames);
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -293,7 +331,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
// If |offset| is provided, will use the value when creating the packet.
// Will also update the value after packet creation.
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -303,34 +341,34 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
size_t* spdy_headers_frame_length,
QuicStreamOffset* offset) {
InitializeHeader(packet_number, should_include_version);
- scoped_ptr<SpdySerializedFrame> spdy_frame;
+ SpdySerializedFrame spdy_frame;
if (spdy_request_framer_.protocol_version() == SPDY3) {
SpdySynStreamIR syn_stream(stream_id);
syn_stream.set_header_block(headers);
syn_stream.set_fin(fin);
syn_stream.set_priority(priority);
- spdy_frame.reset(spdy_request_framer_.SerializeSynStream(syn_stream));
+ spdy_frame = spdy_request_framer_.SerializeSynStream(syn_stream);
} else {
SpdyHeadersIR headers_frame(stream_id);
headers_frame.set_header_block(headers);
headers_frame.set_fin(fin);
headers_frame.set_priority(priority);
headers_frame.set_has_priority(true);
- spdy_frame.reset(spdy_request_framer_.SerializeFrame(headers_frame));
+ spdy_frame = spdy_request_framer_.SerializeFrame(headers_frame);
}
if (spdy_headers_frame_length) {
- *spdy_headers_frame_length = spdy_frame->size();
+ *spdy_headers_frame_length = spdy_frame.size();
}
if (offset != nullptr) {
QuicStreamFrame frame(
kHeadersStreamId, false, *offset,
- base::StringPiece(spdy_frame->data(), spdy_frame->size()));
- *offset += spdy_frame->size();
+ base::StringPiece(spdy_frame.data(), spdy_frame.size()));
+ *offset += spdy_frame.size();
return MakePacket(header_, QuicFrame(&frame));
} else {
QuicStreamFrame frame(
kHeadersStreamId, false, 0,
- base::StringPiece(spdy_frame->data(), spdy_frame->size()));
+ base::StringPiece(spdy_frame.data(), spdy_frame.size()));
return MakePacket(header_, QuicFrame(&frame));
}
@@ -338,7 +376,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
// Convenience method for calling MakeRequestHeadersPacket with nullptr for
// |spdy_headers_frame_length|.
-scoped_ptr<QuicEncryptedPacket>
+scoped_ptr<QuicReceivedPacket>
QuicTestPacketMaker::MakeRequestHeadersPacketWithOffsetTracking(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
@@ -354,7 +392,7 @@ QuicTestPacketMaker::MakeRequestHeadersPacketWithOffsetTracking(
// If |offset| is provided, will use the value when creating the packet.
// Will also update the value after packet creation.
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeResponseHeadersPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeResponseHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -363,36 +401,36 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeResponseHeadersPacket(
size_t* spdy_headers_frame_length,
QuicStreamOffset* offset) {
InitializeHeader(packet_number, should_include_version);
- scoped_ptr<SpdySerializedFrame> spdy_frame;
+ SpdySerializedFrame spdy_frame;
if (spdy_response_framer_.protocol_version() == SPDY3) {
SpdySynReplyIR syn_reply(stream_id);
syn_reply.set_header_block(headers);
syn_reply.set_fin(fin);
- spdy_frame.reset(spdy_response_framer_.SerializeSynReply(syn_reply));
+ spdy_frame = spdy_response_framer_.SerializeSynReply(syn_reply);
} else {
SpdyHeadersIR headers_frame(stream_id);
headers_frame.set_header_block(headers);
headers_frame.set_fin(fin);
- spdy_frame.reset(spdy_response_framer_.SerializeFrame(headers_frame));
+ spdy_frame = spdy_response_framer_.SerializeFrame(headers_frame);
}
if (spdy_headers_frame_length) {
- *spdy_headers_frame_length = spdy_frame->size();
+ *spdy_headers_frame_length = spdy_frame.size();
}
if (offset != nullptr) {
QuicStreamFrame frame(
kHeadersStreamId, false, *offset,
- base::StringPiece(spdy_frame->data(), spdy_frame->size()));
- *offset += spdy_frame->size();
+ base::StringPiece(spdy_frame.data(), spdy_frame.size()));
+ *offset += spdy_frame.size();
return MakePacket(header_, QuicFrame(&frame));
} else {
QuicStreamFrame frame(
kHeadersStreamId, false, 0,
- base::StringPiece(spdy_frame->data(), spdy_frame->size()));
+ base::StringPiece(spdy_frame.data(), spdy_frame.size()));
return MakePacket(header_, QuicFrame(&frame));
}
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeResponseHeadersPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeResponseHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -406,7 +444,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeResponseHeadersPacket(
// Convenience method for calling MakeResponseHeadersPacket with nullptr for
// |spdy_headers_frame_length|.
-scoped_ptr<QuicEncryptedPacket>
+scoped_ptr<QuicReceivedPacket>
QuicTestPacketMaker::MakeResponseHeadersPacketWithOffsetTracking(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
@@ -449,7 +487,7 @@ SpdyHeaderBlock QuicTestPacketMaker::GetResponseHeaders(
return headers;
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakePacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakePacket(
const QuicPacketHeader& header,
const QuicFrame& frame) {
QuicFrames frames;
@@ -457,19 +495,20 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakePacket(
return MakeMultipleFramesPacket(header, frames);
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeMultipleFramesPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeMultipleFramesPacket(
const QuicPacketHeader& header,
const QuicFrames& frames) {
- QuicFramer framer(SupportedVersions(version_), QuicTime::Zero(),
+ QuicFramer framer(SupportedVersions(version_), clock_->Now(),
Perspective::IS_CLIENT);
scoped_ptr<QuicPacket> packet(
BuildUnsizedDataPacket(&framer, header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_size = framer.EncryptPayload(
- ENCRYPTION_NONE, header.packet_number, *packet, buffer, kMaxPacketSize);
+ size_t encrypted_size = framer.EncryptPayload(ENCRYPTION_NONE, /*path_id=*/0u,
+ header.packet_number, *packet,
+ buffer, kMaxPacketSize);
EXPECT_NE(0u, encrypted_size);
- QuicEncryptedPacket encrypted(buffer, encrypted_size, false);
- return scoped_ptr<QuicEncryptedPacket>(encrypted.Clone());
+ QuicReceivedPacket encrypted(buffer, encrypted_size, clock_->Now(), false);
+ return scoped_ptr<QuicReceivedPacket>(encrypted.Clone());
}
void QuicTestPacketMaker::InitializeHeader(QuicPacketNumber packet_number,
diff --git a/chromium/net/quic/test_tools/quic_test_packet_maker.h b/chromium/net/quic/test_tools/quic_test_packet_maker.h
index cad8082bd57..3574ab7185c 100644
--- a/chromium/net/quic/test_tools/quic_test_packet_maker.h
+++ b/chromium/net/quic/test_tools/quic_test_packet_maker.h
@@ -30,22 +30,31 @@ class QuicTestPacketMaker {
~QuicTestPacketMaker();
void set_hostname(const std::string& host);
- scoped_ptr<QuicEncryptedPacket> MakePingPacket(QuicPacketNumber num,
- bool include_version);
- scoped_ptr<QuicEncryptedPacket> MakeRstPacket(
+ scoped_ptr<QuicReceivedPacket> MakePingPacket(QuicPacketNumber num,
+ bool include_version);
+ scoped_ptr<QuicReceivedPacket> MakeRstPacket(
QuicPacketNumber num,
bool include_version,
QuicStreamId stream_id,
QuicRstStreamErrorCode error_code);
- scoped_ptr<QuicEncryptedPacket> MakeAckAndRstPacket(
+
+ scoped_ptr<QuicReceivedPacket> MakeRstPacket(
+ QuicPacketNumber num,
+ bool include_version,
+ QuicStreamId stream_id,
+ QuicRstStreamErrorCode error_code,
+ size_t bytes_written);
+
+ scoped_ptr<QuicReceivedPacket> MakeAckAndRstPacket(
QuicPacketNumber num,
bool include_version,
QuicStreamId stream_id,
QuicRstStreamErrorCode error_code,
QuicPacketNumber largest_received,
- QuicPacketNumber least_unacked,
+ QuicPacketNumber ack_least_unacked,
+ QuicPacketNumber stop_least_unacked,
bool send_feedback);
- scoped_ptr<QuicEncryptedPacket> MakeAckAndConnectionClosePacket(
+ scoped_ptr<QuicReceivedPacket> MakeAckAndConnectionClosePacket(
QuicPacketNumber num,
bool include_version,
QuicTime::Delta delta_time_largest_observed,
@@ -53,26 +62,29 @@ class QuicTestPacketMaker {
QuicPacketNumber least_unacked,
QuicErrorCode quic_error,
std::string& quic_error_details);
- scoped_ptr<QuicEncryptedPacket> MakeConnectionClosePacket(
+ scoped_ptr<QuicReceivedPacket> MakeConnectionClosePacket(
QuicPacketNumber num);
- scoped_ptr<QuicEncryptedPacket> MakeAckPacket(
+ scoped_ptr<QuicReceivedPacket> MakeGoAwayPacket(QuicPacketNumber num,
+ QuicErrorCode error_code,
+ std::string reason_phrase);
+ scoped_ptr<QuicReceivedPacket> MakeAckPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber least_unacked,
bool send_feedback);
- scoped_ptr<QuicEncryptedPacket> MakeAckPacket(
+ scoped_ptr<QuicReceivedPacket> MakeAckPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber ack_least_unacked,
QuicPacketNumber stop_least_unacked,
bool send_feedback);
- scoped_ptr<QuicEncryptedPacket> MakeDataPacket(QuicPacketNumber packet_number,
- QuicStreamId stream_id,
- bool should_include_version,
- bool fin,
- QuicStreamOffset offset,
- base::StringPiece data);
- scoped_ptr<QuicEncryptedPacket> MakeAckAndDataPacket(
+ scoped_ptr<QuicReceivedPacket> MakeDataPacket(QuicPacketNumber packet_number,
+ QuicStreamId stream_id,
+ bool should_include_version,
+ bool fin,
+ QuicStreamOffset offset,
+ base::StringPiece data);
+ scoped_ptr<QuicReceivedPacket> MakeAckAndDataPacket(
QuicPacketNumber packet_number,
bool include_version,
QuicStreamId stream_id,
@@ -84,7 +96,7 @@ class QuicTestPacketMaker {
// If |spdy_headers_frame_length| is non-null, it will be set to the size of
// the SPDY headers frame created for this packet.
- scoped_ptr<QuicEncryptedPacket> MakeRequestHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> MakeRequestHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -93,7 +105,7 @@ class QuicTestPacketMaker {
const SpdyHeaderBlock& headers,
size_t* spdy_headers_frame_length);
- scoped_ptr<QuicEncryptedPacket> MakeRequestHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> MakeRequestHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -105,7 +117,7 @@ class QuicTestPacketMaker {
// Convenience method for calling MakeRequestHeadersPacket with nullptr for
// |spdy_headers_frame_length|.
- scoped_ptr<QuicEncryptedPacket> MakeRequestHeadersPacketWithOffsetTracking(
+ scoped_ptr<QuicReceivedPacket> MakeRequestHeadersPacketWithOffsetTracking(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -116,7 +128,7 @@ class QuicTestPacketMaker {
// If |spdy_headers_frame_length| is non-null, it will be set to the size of
// the SPDY headers frame created for this packet.
- scoped_ptr<QuicEncryptedPacket> MakeResponseHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> MakeResponseHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -125,7 +137,7 @@ class QuicTestPacketMaker {
size_t* spdy_headers_frame_length,
QuicStreamOffset* offset);
- scoped_ptr<QuicEncryptedPacket> MakeResponseHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> MakeResponseHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -135,7 +147,7 @@ class QuicTestPacketMaker {
// Convenience method for calling MakeResponseHeadersPacket with nullptr for
// |spdy_headers_frame_length|.
- scoped_ptr<QuicEncryptedPacket> MakeResponseHeadersPacketWithOffsetTracking(
+ scoped_ptr<QuicReceivedPacket> MakeResponseHeadersPacketWithOffsetTracking(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -152,9 +164,9 @@ class QuicTestPacketMaker {
const std::string& alt_svc);
private:
- scoped_ptr<QuicEncryptedPacket> MakePacket(const QuicPacketHeader& header,
- const QuicFrame& frame);
- scoped_ptr<QuicEncryptedPacket> MakeMultipleFramesPacket(
+ scoped_ptr<QuicReceivedPacket> MakePacket(const QuicPacketHeader& header,
+ const QuicFrame& frame);
+ scoped_ptr<QuicReceivedPacket> MakeMultipleFramesPacket(
const QuicPacketHeader& header,
const QuicFrames& frames);
diff --git a/chromium/net/quic/test_tools/quic_test_utils.cc b/chromium/net/quic/test_tools/quic_test_utils.cc
index a2ba09f9e04..3d9267a8f58 100644
--- a/chromium/net/quic/test_tools/quic_test_utils.cc
+++ b/chromium/net/quic/test_tools/quic_test_utils.cc
@@ -30,6 +30,7 @@ using testing::Invoke;
using testing::_;
namespace net {
+
namespace test {
QuicAckFrame MakeAckFrame(QuicPacketNumber largest_observed) {
@@ -60,7 +61,7 @@ QuicPacket* BuildUnsizedDataPacket(QuicFramer* framer,
bool last_frame = i == frames.size() - 1;
const size_t frame_size = framer->GetSerializedFrameLength(
frames[i], max_plaintext_size - packet_size, first_frame, last_frame,
- header.is_in_fec_group, header.public_header.packet_number_length);
+ header.public_header.packet_number_length);
DCHECK(frame_size);
packet_size += frame_size;
}
@@ -78,6 +79,7 @@ QuicPacket* BuildUnsizedDataPacket(QuicFramer* framer,
return new QuicPacket(buffer, length, /* owns_buffer */ true,
header.public_header.connection_id_length,
header.public_header.version_flag,
+ header.public_header.multipath_flag,
header.public_header.packet_number_length);
}
@@ -177,6 +179,10 @@ bool NoOpFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& frame) {
return true;
}
+bool NoOpFramerVisitor::OnPathCloseFrame(const QuicPathCloseFrame& frame) {
+ return true;
+}
+
MockConnectionVisitor::MockConnectionVisitor() {}
MockConnectionVisitor::~MockConnectionVisitor() {}
@@ -194,7 +200,19 @@ QuicRandom* MockConnectionHelper::GetRandomGenerator() {
}
QuicAlarm* MockConnectionHelper::CreateAlarm(QuicAlarm::Delegate* delegate) {
- return new MockConnectionHelper::TestAlarm(delegate);
+ return new MockConnectionHelper::TestAlarm(
+ QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate));
+}
+
+QuicArenaScopedPtr<QuicAlarm> MockConnectionHelper::CreateAlarm(
+ QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+ QuicConnectionArena* arena) {
+ if (arena != nullptr) {
+ return arena->New<MockConnectionHelper::TestAlarm>(std::move(delegate));
+ } else {
+ return QuicArenaScopedPtr<MockConnectionHelper::TestAlarm>(
+ new TestAlarm(std::move(delegate)));
+ }
}
QuicBufferAllocator* MockConnectionHelper::GetBufferAllocator() {
@@ -278,14 +296,11 @@ PacketSavingConnection::~PacketSavingConnection() {
}
void PacketSavingConnection::SendOrQueuePacket(SerializedPacket* packet) {
- if (!packet->packet->owns_buffer()) {
- scoped_ptr<QuicEncryptedPacket> encrypted_deleter(packet->packet);
- packet->packet = packet->packet->Clone();
- }
- encrypted_packets_.push_back(packet->packet);
+ encrypted_packets_.push_back(new QuicEncryptedPacket(
+ QuicUtils::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, 0, QuicTime::Zero(), 1000,
+ sent_packet_manager_.OnPacketSent(packet, 0, QuicTime::Zero(),
NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
}
@@ -294,7 +309,7 @@ MockQuicSpdySession::MockQuicSpdySession(QuicConnection* connection)
: QuicSpdySession(connection, DefaultQuicConfig()) {
crypto_stream_.reset(new QuicCryptoStream(this));
Initialize();
- ON_CALL(*this, WritevData(_, _, _, _, _, _))
+ ON_CALL(*this, WritevData(_, _, _, _, _))
.WillByDefault(testing::Return(QuicConsumedData(0, false)));
}
@@ -306,7 +321,6 @@ QuicConsumedData MockQuicSpdySession::ConsumeAllData(
const QuicIOVector& data,
QuicStreamOffset /*offset*/,
bool fin,
- FecProtection /*fec_protection*/,
QuicAckListenerInterface* /*ack_notifier_delegate*/) {
return QuicConsumedData(data.total_length, fin);
}
@@ -314,8 +328,13 @@ QuicConsumedData MockQuicSpdySession::ConsumeAllData(
TestQuicSpdyServerSession::TestQuicSpdyServerSession(
QuicConnection* connection,
const QuicConfig& config,
- const QuicCryptoServerConfig* crypto_config)
- : QuicServerSessionBase(config, connection, &visitor_, crypto_config) {
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache)
+ : QuicServerSessionBase(config,
+ connection,
+ &visitor_,
+ crypto_config,
+ compressed_certs_cache) {
Initialize();
}
@@ -323,8 +342,11 @@ TestQuicSpdyServerSession::~TestQuicSpdyServerSession() {}
QuicCryptoServerStreamBase*
TestQuicSpdyServerSession::CreateQuicCryptoServerStream(
- const QuicCryptoServerConfig* crypto_config) {
- return new QuicCryptoServerStream(crypto_config, this);
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache) {
+ return new QuicCryptoServerStream(crypto_config, compressed_certs_cache,
+ FLAGS_enable_quic_stateless_reject_support,
+ this);
}
QuicCryptoServerStream* TestQuicSpdyServerSession::GetCryptoStream() {
@@ -337,15 +359,19 @@ TestQuicSpdyClientSession::TestQuicSpdyClientSession(
const QuicConfig& config,
const QuicServerId& server_id,
QuicCryptoClientConfig* crypto_config)
- : QuicClientSessionBase(connection, config) {
+ : QuicClientSessionBase(connection, &push_promise_index_, config) {
crypto_stream_.reset(new QuicCryptoClientStream(
server_id, this, CryptoTestUtils::ProofVerifyContextForTesting(),
- crypto_config));
+ crypto_config, this));
Initialize();
}
TestQuicSpdyClientSession::~TestQuicSpdyClientSession() {}
+bool TestQuicSpdyClientSession::IsAuthorized(const string& authority) {
+ return true;
+}
+
QuicCryptoClientStream* TestQuicSpdyClientSession::GetCryptoStream() {
return crypto_stream_.get();
}
@@ -417,7 +443,7 @@ string HexDumpWithMarks(const char* data,
} // namespace
-IPAddressNumber TestPeerIPAddress() {
+IPAddress TestPeerIPAddress() {
return Loopback4();
}
@@ -429,22 +455,16 @@ QuicVersion QuicVersionMin() {
return QuicSupportedVersions().back();
}
-IPAddressNumber Loopback4() {
- IPAddressNumber addr;
- CHECK(ParseIPLiteralToNumber("127.0.0.1", &addr));
- return addr;
+IPAddress Loopback4() {
+ return IPAddress::IPv4Localhost();
}
-IPAddressNumber Loopback6() {
- IPAddressNumber addr;
- CHECK(ParseIPLiteralToNumber("::1", &addr));
- return addr;
+IPAddress Loopback6() {
+ return IPAddress::IPv6Localhost();
}
-IPAddressNumber Any4() {
- IPAddressNumber any4;
- CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
- return any4;
+IPAddress Any4() {
+ return IPAddress::IPv4AllZeros();
}
void GenerateBody(string* body, int length) {
@@ -457,31 +477,38 @@ void GenerateBody(string* body, int length) {
QuicEncryptedPacket* ConstructEncryptedPacket(QuicConnectionId connection_id,
bool version_flag,
+ bool multipath_flag,
bool reset_flag,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
const string& data) {
- return ConstructEncryptedPacket(
- connection_id, version_flag, reset_flag, packet_number, data,
- PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER);
+ return ConstructEncryptedPacket(connection_id, version_flag, multipath_flag,
+ reset_flag, path_id, packet_number, data,
+ PACKET_8BYTE_CONNECTION_ID,
+ PACKET_6BYTE_PACKET_NUMBER);
}
QuicEncryptedPacket* ConstructEncryptedPacket(
QuicConnectionId connection_id,
bool version_flag,
+ bool multipath_flag,
bool reset_flag,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
const string& data,
QuicConnectionIdLength connection_id_length,
QuicPacketNumberLength packet_number_length) {
- return ConstructEncryptedPacket(connection_id, version_flag, reset_flag,
- packet_number, data, connection_id_length,
- packet_number_length, nullptr);
+ return ConstructEncryptedPacket(
+ connection_id, version_flag, multipath_flag, reset_flag, path_id,
+ packet_number, data, connection_id_length, packet_number_length, nullptr);
}
QuicEncryptedPacket* ConstructEncryptedPacket(
QuicConnectionId connection_id,
bool version_flag,
+ bool multipath_flag,
bool reset_flag,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
const string& data,
QuicConnectionIdLength connection_id_length,
@@ -491,8 +518,10 @@ QuicEncryptedPacket* ConstructEncryptedPacket(
header.public_header.connection_id = connection_id;
header.public_header.connection_id_length = connection_id_length;
header.public_header.version_flag = version_flag;
+ header.public_header.multipath_flag = multipath_flag;
header.public_header.reset_flag = reset_flag;
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;
@@ -511,15 +540,26 @@ QuicEncryptedPacket* ConstructEncryptedPacket(
EXPECT_TRUE(packet != nullptr);
char* buffer = new char[kMaxPacketSize];
size_t encrypted_length = framer.EncryptPayload(
- ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize);
+ ENCRYPTION_NONE, path_id, packet_number, *packet, buffer, kMaxPacketSize);
EXPECT_NE(0u, encrypted_length);
return new QuicEncryptedPacket(buffer, encrypted_length, true);
}
+QuicReceivedPacket* ConstructReceivedPacket(
+ const QuicEncryptedPacket& encrypted_packet,
+ QuicTime receipt_time) {
+ char* buffer = new char[encrypted_packet.length()];
+ memcpy(buffer, encrypted_packet.data(), encrypted_packet.length());
+ return new QuicReceivedPacket(buffer, encrypted_packet.length(), receipt_time,
+ true);
+}
+
QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
QuicConnectionId connection_id,
bool version_flag,
+ bool multipath_flag,
bool reset_flag,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
const string& data,
QuicConnectionIdLength connection_id_length,
@@ -529,8 +569,10 @@ QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
header.public_header.connection_id = connection_id;
header.public_header.connection_id_length = connection_id_length;
header.public_header.version_flag = version_flag;
+ header.public_header.multipath_flag = multipath_flag;
header.public_header.reset_flag = reset_flag;
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;
@@ -551,11 +593,12 @@ QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
// Now set the packet's private flags byte to 0xFF, which is an invalid value.
reinterpret_cast<unsigned char*>(
packet->mutable_data())[GetStartOfEncryptedData(
- connection_id_length, version_flag, packet_number_length)] = 0xFF;
+ connection_id_length, version_flag, multipath_flag,
+ packet_number_length)] = 0xFF;
char* buffer = new char[kMaxPacketSize];
size_t encrypted_length = framer.EncryptPayload(
- ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize);
+ ENCRYPTION_NONE, path_id, packet_number, *packet, buffer, kMaxPacketSize);
EXPECT_NE(0u, encrypted_length);
return new QuicEncryptedPacket(buffer, encrypted_length, true);
}
@@ -583,7 +626,8 @@ void CompareCharArraysWithHexError(const string& description,
}
if (identical)
return;
- ADD_FAILURE() << "Description:\n" << description << "\n\nExpected:\n"
+ ADD_FAILURE() << "Description:\n"
+ << description << "\n\nExpected:\n"
<< HexDumpWithMarks(expected, expected_len, marks.get(),
max_len)
<< "\nActual:\n"
@@ -639,30 +683,29 @@ QuicPacket* ConstructHandshakePacket(QuicConnectionId connection_id,
size_t GetPacketLengthForOneStream(QuicVersion version,
bool include_version,
+ bool include_path_id,
QuicConnectionIdLength connection_id_length,
QuicPacketNumberLength packet_number_length,
- InFecGroup is_in_fec_group,
size_t* payload_length) {
*payload_length = 1;
const size_t stream_length =
NullEncrypter().GetCiphertextSize(*payload_length) +
QuicPacketCreator::StreamFramePacketOverhead(
- PACKET_8BYTE_CONNECTION_ID, include_version, packet_number_length, 0u,
- is_in_fec_group);
+ PACKET_8BYTE_CONNECTION_ID, include_version, include_path_id,
+ packet_number_length, 0u);
const size_t ack_length =
NullEncrypter().GetCiphertextSize(
QuicFramer::GetMinAckFrameSize(PACKET_1BYTE_PACKET_NUMBER)) +
GetPacketHeaderSize(connection_id_length, include_version,
- /*include_path_id=*/false, packet_number_length,
- is_in_fec_group);
+ include_path_id, packet_number_length);
if (stream_length < ack_length) {
*payload_length = 1 + ack_length - stream_length;
}
return NullEncrypter().GetCiphertextSize(*payload_length) +
QuicPacketCreator::StreamFramePacketOverhead(
- connection_id_length, include_version, packet_number_length, 0u,
- is_in_fec_group);
+ connection_id_length, include_version, include_path_id,
+ packet_number_length, 0u);
}
TestEntropyCalculator::TestEntropyCalculator() {}
@@ -735,13 +778,15 @@ void CreateClientSessionForTest(QuicServerId server_id,
(*client_connection)->AdvanceTime(connection_start_time);
}
-void CreateServerSessionForTest(QuicServerId server_id,
- QuicTime::Delta connection_start_time,
- QuicVersionVector supported_versions,
- MockConnectionHelper* helper,
- QuicCryptoServerConfig* server_crypto_config,
- PacketSavingConnection** server_connection,
- TestQuicSpdyServerSession** server_session) {
+void CreateServerSessionForTest(
+ QuicServerId server_id,
+ QuicTime::Delta connection_start_time,
+ QuicVersionVector supported_versions,
+ MockConnectionHelper* helper,
+ QuicCryptoServerConfig* server_crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ PacketSavingConnection** server_connection,
+ TestQuicSpdyServerSession** server_session) {
CHECK(server_crypto_config);
CHECK(server_connection);
CHECK(server_session);
@@ -752,7 +797,8 @@ void CreateServerSessionForTest(QuicServerId server_id,
*server_connection = new PacketSavingConnection(
helper, Perspective::IS_SERVER, supported_versions);
*server_session = new TestQuicSpdyServerSession(
- *server_connection, DefaultQuicConfig(), server_crypto_config);
+ *server_connection, DefaultQuicConfig(), server_crypto_config,
+ compressed_certs_cache);
// We advance the clock initially because the default time is zero and the
// strike register worries that we've just overflowed a uint32_t time.
diff --git a/chromium/net/quic/test_tools/quic_test_utils.h b/chromium/net/quic/test_tools/quic_test_utils.h
index 5293e5b1a11..87889f7ebce 100644
--- a/chromium/net/quic/test_tools/quic_test_utils.h
+++ b/chromium/net/quic/test_tools/quic_test_utils.h
@@ -15,9 +15,10 @@
#include "base/macros.h"
#include "base/strings/string_piece.h"
+#include "net/base/ip_address.h"
#include "net/quic/congestion_control/loss_detection_interface.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
-#include "net/quic/quic_client_session_base.h"
+#include "net/quic/quic_client_push_promise_index.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_protocol.h"
@@ -47,9 +48,10 @@ static const uint32_t kInitialSessionFlowControlWindowForTest =
static const QuicStreamId kClientDataStreamId1 = 5;
static const QuicStreamId kClientDataStreamId2 = 7;
static const QuicStreamId kClientDataStreamId3 = 9;
+static const QuicStreamId kServerDataStreamId1 = 4;
// Returns the test peer IP address.
-IPAddressNumber TestPeerIPAddress();
+IPAddress TestPeerIPAddress();
// Upper limit on versions we support.
QuicVersion QuicVersionMax();
@@ -58,13 +60,13 @@ QuicVersion QuicVersionMax();
QuicVersion QuicVersionMin();
// Returns an address for 127.0.0.1.
-IPAddressNumber Loopback4();
+IPAddress Loopback4();
// Returns an address for ::1.
-IPAddressNumber Loopback6();
+IPAddress Loopback6();
// Returns an address for 0.0.0.0.
-IPAddressNumber Any4();
+IPAddress Any4();
void GenerateBody(std::string* body, int length);
@@ -75,7 +77,9 @@ void GenerateBody(std::string* body, int length);
QuicEncryptedPacket* ConstructEncryptedPacket(
QuicConnectionId connection_id,
bool version_flag,
+ bool multipath_flag,
bool reset_flag,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
const std::string& data,
QuicConnectionIdLength connection_id_length,
@@ -86,7 +90,9 @@ QuicEncryptedPacket* ConstructEncryptedPacket(
QuicEncryptedPacket* ConstructEncryptedPacket(
QuicConnectionId connection_id,
bool version_flag,
+ bool multipath_flag,
bool reset_flag,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
const std::string& data,
QuicConnectionIdLength connection_id_length,
@@ -97,10 +103,18 @@ QuicEncryptedPacket* ConstructEncryptedPacket(
// |versions| == nullptr.
QuicEncryptedPacket* ConstructEncryptedPacket(QuicConnectionId connection_id,
bool version_flag,
+ bool multipath_flag,
bool reset_flag,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
const std::string& data);
+// Constructs a received packet for testing. The caller must take ownership of
+// the returned pointer.
+QuicReceivedPacket* ConstructReceivedPacket(
+ const QuicEncryptedPacket& encrypted_packet,
+ QuicTime receipt_time);
+
// Create an encrypted packet for testing whose data portion erroneous.
// The specific way the data portion is erroneous is not specified, but
// it is an error that QuicFramer detects.
@@ -109,7 +123,9 @@ QuicEncryptedPacket* ConstructEncryptedPacket(QuicConnectionId connection_id,
QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
QuicConnectionId connection_id,
bool version_flag,
+ bool multipath_flag,
bool reset_flag,
+ QuicPathId path_id,
QuicPacketNumber packet_number,
const std::string& data,
QuicConnectionIdLength connection_id_length,
@@ -129,9 +145,9 @@ bool DecodeHexString(const base::StringPiece& hex, std::string* bytes);
// of bytes of stream data that will fit in such a packet.
size_t GetPacketLengthForOneStream(QuicVersion version,
bool include_version,
+ bool include_path_id,
QuicConnectionIdLength connection_id_length,
QuicPacketNumberLength packet_number_length,
- InFecGroup is_in_fec_group,
size_t* payload_length);
// Returns QuicConfig set to default values.
@@ -210,7 +226,6 @@ class MockFramerVisitor : public QuicFramerVisitorInterface {
MOCK_METHOD1(OnPublicResetPacket, void(const QuicPublicResetPacket& header));
MOCK_METHOD1(OnVersionNegotiationPacket,
void(const QuicVersionNegotiationPacket& packet));
- MOCK_METHOD0(OnRevivedPacket, void());
// The constructor sets this up to return true by default.
MOCK_METHOD1(OnUnauthenticatedHeader, bool(const QuicPacketHeader& header));
// The constructor sets this up to return true by default.
@@ -218,18 +233,17 @@ class MockFramerVisitor : public QuicFramerVisitorInterface {
bool(const QuicPacketPublicHeader& header));
MOCK_METHOD1(OnDecryptedPacket, void(EncryptionLevel level));
MOCK_METHOD1(OnPacketHeader, bool(const QuicPacketHeader& header));
- MOCK_METHOD1(OnFecProtectedPayload, void(base::StringPiece payload));
MOCK_METHOD1(OnStreamFrame, bool(const QuicStreamFrame& frame));
MOCK_METHOD1(OnAckFrame, bool(const QuicAckFrame& frame));
MOCK_METHOD1(OnStopWaitingFrame, bool(const QuicStopWaitingFrame& frame));
MOCK_METHOD1(OnPingFrame, bool(const QuicPingFrame& frame));
- MOCK_METHOD1(OnFecData, void(StringPiece redundancy));
MOCK_METHOD1(OnRstStreamFrame, bool(const QuicRstStreamFrame& frame));
MOCK_METHOD1(OnConnectionCloseFrame,
bool(const QuicConnectionCloseFrame& frame));
MOCK_METHOD1(OnGoAwayFrame, bool(const QuicGoAwayFrame& frame));
MOCK_METHOD1(OnWindowUpdateFrame, bool(const QuicWindowUpdateFrame& frame));
MOCK_METHOD1(OnBlockedFrame, bool(const QuicBlockedFrame& frame));
+ MOCK_METHOD1(OnPathCloseFrame, bool(const QuicPathCloseFrame& frame));
MOCK_METHOD0(OnPacketComplete, void());
private:
@@ -245,24 +259,22 @@ class NoOpFramerVisitor : public QuicFramerVisitorInterface {
void OnPublicResetPacket(const QuicPublicResetPacket& packet) override {}
void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) override {}
- void OnRevivedPacket() override {}
bool OnProtocolVersionMismatch(QuicVersion version) override;
bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
bool OnUnauthenticatedPublicHeader(
const QuicPacketPublicHeader& header) override;
void OnDecryptedPacket(EncryptionLevel level) override {}
bool OnPacketHeader(const QuicPacketHeader& header) override;
- void OnFecProtectedPayload(base::StringPiece payload) override {}
bool OnStreamFrame(const QuicStreamFrame& frame) override;
bool OnAckFrame(const QuicAckFrame& frame) override;
bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override;
bool OnPingFrame(const QuicPingFrame& frame) override;
- void OnFecData(StringPiece redundancy) override {}
bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override;
bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override;
bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
+ bool OnPathCloseFrame(const QuicPathCloseFrame& frame) override;
void OnPacketComplete() override {}
private:
@@ -279,17 +291,22 @@ class MockConnectionVisitor : public QuicConnectionVisitorInterface {
MOCK_METHOD1(OnBlockedFrame, void(const QuicBlockedFrame& frame));
MOCK_METHOD1(OnRstStream, void(const QuicRstStreamFrame& frame));
MOCK_METHOD1(OnGoAway, void(const QuicGoAwayFrame& frame));
- MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer));
+ MOCK_METHOD3(OnConnectionClosed,
+ void(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source));
MOCK_METHOD0(OnWriteBlocked, void());
MOCK_METHOD0(OnCanWrite, void());
MOCK_METHOD1(OnCongestionWindowChange, void(QuicTime now));
- MOCK_METHOD0(OnConnectionMigration, void());
+ MOCK_METHOD1(OnConnectionMigration, void(PeerAddressChangeType type));
+ MOCK_METHOD0(OnPathDegrading, void());
MOCK_CONST_METHOD0(WillingAndAbleToWrite, bool());
MOCK_CONST_METHOD0(HasPendingHandshake, bool());
MOCK_CONST_METHOD0(HasOpenDynamicStreams, bool());
MOCK_METHOD1(OnSuccessfulVersionNegotiation,
void(const QuicVersion& version));
MOCK_METHOD0(OnConfigNegotiated, void());
+ MOCK_METHOD0(PostProcessAfterData, void());
private:
DISALLOW_COPY_AND_ASSIGN(MockConnectionVisitor);
@@ -302,13 +319,17 @@ class MockConnectionHelper : public QuicConnectionHelperInterface {
const QuicClock* GetClock() const override;
QuicRandom* GetRandomGenerator() override;
QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override;
+ QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
+ QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+ QuicConnectionArena* arena) override;
QuicBufferAllocator* GetBufferAllocator() override;
void AdvanceTime(QuicTime::Delta delta);
// No-op alarm implementation
class TestAlarm : public QuicAlarm {
public:
- explicit TestAlarm(QuicAlarm::Delegate* delegate) : QuicAlarm(delegate) {}
+ explicit TestAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate> delegate)
+ : QuicAlarm(std::move(delegate)) {}
void SetImpl() override {}
void CancelImpl() override {}
@@ -364,10 +385,12 @@ class MockConnection : public QuicConnection {
MOCK_METHOD3(ProcessUdpPacket,
void(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
- const QuicEncryptedPacket& packet));
+ const QuicReceivedPacket& packet));
MOCK_METHOD1(SendConnectionClose, void(QuicErrorCode error));
- MOCK_METHOD2(SendConnectionCloseWithDetails,
- void(QuicErrorCode error, const std::string& details));
+ MOCK_METHOD3(CloseConnection,
+ void(QuicErrorCode error,
+ const std::string& details,
+ ConnectionCloseBehavior connection_close_behavior));
MOCK_METHOD2(SendConnectionClosePacket,
void(QuicErrorCode error, const std::string& details));
MOCK_METHOD3(SendRstStream,
@@ -394,7 +417,7 @@ class MockConnection : public QuicConnection {
void ReallyProcessUdpPacket(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
- const QuicEncryptedPacket& packet) {
+ const QuicReceivedPacket& packet) {
QuicConnection::ProcessUdpPacket(self_address, peer_address, packet);
}
@@ -436,17 +459,22 @@ class MockQuicSpdySession : public QuicSpdySession {
QuicCryptoStream* GetCryptoStream() override { return crypto_stream_.get(); }
// From QuicSession.
- MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer));
+ MOCK_METHOD3(OnConnectionClosed,
+ void(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source));
MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id));
MOCK_METHOD1(CreateOutgoingDynamicStream,
QuicSpdyStream*(SpdyPriority priority));
- MOCK_METHOD6(WritevData,
+ MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id));
+ MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool());
+ MOCK_METHOD5(WritevData,
QuicConsumedData(QuicStreamId id,
QuicIOVector data,
QuicStreamOffset offset,
bool fin,
- FecProtection fec_protection,
QuicAckListenerInterface*));
+
MOCK_METHOD3(SendRstStream,
void(QuicStreamId stream_id,
QuicRstStreamErrorCode error,
@@ -482,7 +510,6 @@ class MockQuicSpdySession : public QuicSpdySession {
const QuicIOVector& data,
QuicStreamOffset offset,
bool fin,
- FecProtection fec_protection,
QuicAckListenerInterface* ack_notifier_delegate);
private:
@@ -491,23 +518,25 @@ class MockQuicSpdySession : public QuicSpdySession {
DISALLOW_COPY_AND_ASSIGN(MockQuicSpdySession);
};
-class TestQuicSpdyServerSession : public tools::QuicServerSessionBase {
+class TestQuicSpdyServerSession : public QuicServerSessionBase {
public:
TestQuicSpdyServerSession(QuicConnection* connection,
const QuicConfig& config,
- const QuicCryptoServerConfig* crypto_config);
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache);
~TestQuicSpdyServerSession() override;
MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id));
MOCK_METHOD1(CreateOutgoingDynamicStream,
QuicSpdyStream*(SpdyPriority priority));
QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
- const QuicCryptoServerConfig* crypto_config) override;
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache) override;
QuicCryptoServerStream* GetCryptoStream() override;
private:
- tools::test::MockQuicServerSessionVisitor visitor_;
+ MockQuicServerSessionVisitor visitor_;
DISALLOW_COPY_AND_ASSIGN(TestQuicSpdyServerSession);
};
@@ -520,6 +549,8 @@ class TestQuicSpdyClientSession : public QuicClientSessionBase {
QuicCryptoClientConfig* crypto_config);
~TestQuicSpdyClientSession() override;
+ bool IsAuthorized(const std::string& authority) override;
+
// QuicClientSessionBase
MOCK_METHOD1(OnProofValid,
void(const QuicCryptoClientConfig::CachedState& cached));
@@ -530,11 +561,14 @@ class TestQuicSpdyClientSession : public QuicClientSessionBase {
MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id));
MOCK_METHOD1(CreateOutgoingDynamicStream,
QuicSpdyStream*(SpdyPriority priority));
+ MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id));
+ MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool());
QuicCryptoClientStream* GetCryptoStream() override;
private:
scoped_ptr<QuicCryptoClientStream> crypto_stream_;
+ QuicClientPushPromiseIndex push_promise_index_;
DISALLOW_COPY_AND_ASSIGN(TestQuicSpdyClientSession);
};
@@ -544,11 +578,12 @@ class MockPacketWriter : public QuicPacketWriter {
MockPacketWriter();
~MockPacketWriter() override;
- MOCK_METHOD4(WritePacket,
+ MOCK_METHOD5(WritePacket,
WriteResult(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address));
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options));
MOCK_CONST_METHOD0(IsWriteBlockedDataBuffered, bool());
MOCK_CONST_METHOD0(IsWriteBlocked, bool());
MOCK_METHOD0(SetWritable, void());
@@ -583,10 +618,9 @@ class MockSendAlgorithm : public SendAlgorithmInterface {
MOCK_METHOD1(OnRetransmissionTimeout, void(bool));
MOCK_METHOD0(OnConnectionMigration, void());
MOCK_METHOD0(RevertRetransmissionTimeout, void());
- MOCK_CONST_METHOD3(TimeUntilSend,
+ MOCK_CONST_METHOD2(TimeUntilSend,
QuicTime::Delta(QuicTime now,
- QuicByteCount bytes_in_flight,
- HasRetransmittableData));
+ QuicByteCount bytes_in_flight));
MOCK_CONST_METHOD0(PacingRate, QuicBandwidth(void));
MOCK_CONST_METHOD0(BandwidthEstimate, QuicBandwidth(void));
MOCK_CONST_METHOD0(HasReliableBandwidthEstimate, bool());
@@ -610,14 +644,9 @@ class MockLossAlgorithm : public LossDetectionInterface {
~MockLossAlgorithm() override;
MOCK_CONST_METHOD0(GetLossDetectionType, LossDetectionType());
- MOCK_METHOD4(DetectLostPackets,
- PacketNumberSet(const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
- QuicPacketNumber largest_observed,
- const RttStats& rtt_stats));
MOCK_METHOD4(DetectLosses,
void(const QuicUnackedPacketMap& unacked_packets,
- const QuicTime& time,
+ QuicTime time,
const RttStats& rtt_stats,
SendAlgorithmInterface::CongestionVector* packets_lost));
MOCK_CONST_METHOD0(GetLossTimeout, QuicTime());
@@ -656,7 +685,7 @@ class MockAckListener : public QuicAckListenerInterface {
MockAckListener();
MOCK_METHOD2(OnPacketAcked,
- void(int acked_bytes, QuicTime::Delta delta_largest_observed));
+ void(int acked_bytes, QuicTime::Delta ack_delay_time));
MOCK_METHOD1(OnPacketRetransmitted, void(int retransmitted_bytes));
@@ -676,6 +705,7 @@ class MockNetworkChangeVisitor
MOCK_METHOD0(OnCongestionWindowChange, void());
MOCK_METHOD0(OnRttChange, void());
+ MOCK_METHOD0(OnPathDegrading, void());
private:
DISALLOW_COPY_AND_ASSIGN(MockNetworkChangeVisitor);
@@ -688,11 +718,10 @@ class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor {
MOCK_METHOD1(OnFrameAddedToPacket, void(const QuicFrame&));
- MOCK_METHOD5(OnPacketSent,
+ MOCK_METHOD4(OnPacketSent,
void(const SerializedPacket&,
QuicPacketNumber,
TransmissionType,
- size_t encrypted_length,
QuicTime));
MOCK_METHOD3(OnPacketReceived,
@@ -722,9 +751,6 @@ class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor {
MOCK_METHOD1(OnVersionNegotiationPacket,
void(const QuicVersionNegotiationPacket&));
-
- MOCK_METHOD2(OnRevivedPacket,
- void(const QuicPacketHeader&, StringPiece payload));
};
class MockReceivedPacketManager : public QuicReceivedPacketManager {
@@ -736,7 +762,6 @@ class MockReceivedPacketManager : public QuicReceivedPacketManager {
void(QuicByteCount bytes,
const QuicPacketHeader& header,
QuicTime receipt_time));
- MOCK_METHOD1(RecordPacketRevived, void(QuicPacketNumber packet_number));
MOCK_METHOD1(IsMissing, bool(QuicPacketNumber packet_number));
MOCK_METHOD1(IsAwaitingPacket, bool(QuicPacketNumber packet_number));
MOCK_METHOD1(UpdatePacketInformationSentByPeer,
@@ -785,13 +810,15 @@ void CreateClientSessionForTest(QuicServerId server_id,
// server_session.
// server_session: Pointer reference for the newly created server
// session. The new object will be owned by the caller.
-void CreateServerSessionForTest(QuicServerId server_id,
- QuicTime::Delta connection_start_time,
- QuicVersionVector supported_versions,
- MockConnectionHelper* helper,
- QuicCryptoServerConfig* crypto_server_config,
- PacketSavingConnection** server_connection,
- TestQuicSpdyServerSession** server_session);
+void CreateServerSessionForTest(
+ QuicServerId server_id,
+ QuicTime::Delta connection_start_time,
+ QuicVersionVector supported_versions,
+ MockConnectionHelper* helper,
+ QuicCryptoServerConfig* crypto_server_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ PacketSavingConnection** server_connection,
+ TestQuicSpdyServerSession** server_session);
// Helper to generate client side stream ids, generalizes
// kClientDataStreamId1 etc. above.
diff --git a/chromium/net/quic/test_tools/reliable_quic_stream_peer.cc b/chromium/net/quic/test_tools/reliable_quic_stream_peer.cc
index 97a7278c45c..2b419bfd93a 100644
--- a/chromium/net/quic/test_tools/reliable_quic_stream_peer.cc
+++ b/chromium/net/quic/test_tools/reliable_quic_stream_peer.cc
@@ -79,12 +79,6 @@ uint32_t ReliableQuicStreamPeer::SizeOfQueuedData(ReliableQuicStream* stream) {
}
// static
-void ReliableQuicStreamPeer::SetFecPolicy(ReliableQuicStream* stream,
- FecPolicy fec_policy) {
- stream->set_fec_policy(fec_policy);
-}
-
-// static
bool ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl(
ReliableQuicStream* stream) {
return stream->stream_contributes_to_connection_flow_control_;
diff --git a/chromium/net/quic/test_tools/reliable_quic_stream_peer.h b/chromium/net/quic/test_tools/reliable_quic_stream_peer.h
index db172da1061..04bbe7b4cce 100644
--- a/chromium/net/quic/test_tools/reliable_quic_stream_peer.h
+++ b/chromium/net/quic/test_tools/reliable_quic_stream_peer.h
@@ -35,8 +35,6 @@ class ReliableQuicStreamPeer {
static uint32_t SizeOfQueuedData(ReliableQuicStream* stream);
- static void SetFecPolicy(ReliableQuicStream* stream, FecPolicy fec_policy);
-
static bool StreamContributesToConnectionFlowControl(
ReliableQuicStream* stream);
diff --git a/chromium/net/quic/test_tools/simple_quic_framer.cc b/chromium/net/quic/test_tools/simple_quic_framer.cc
index 7b65ca7c41d..dd0e0cb6a74 100644
--- a/chromium/net/quic/test_tools/simple_quic_framer.cc
+++ b/chromium/net/quic/test_tools/simple_quic_framer.cc
@@ -37,7 +37,6 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
const QuicVersionNegotiationPacket& packet) override {
version_negotiation_packet_.reset(new QuicVersionNegotiationPacket(packet));
}
- void OnRevivedPacket() override {}
bool OnUnauthenticatedPublicHeader(
const QuicPacketPublicHeader& header) override {
@@ -53,8 +52,6 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
return true;
}
- void OnFecProtectedPayload(StringPiece payload) override {}
-
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();
@@ -82,10 +79,6 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
return true;
}
- void OnFecData(StringPiece redundancy) override {
- fec_redundancy_ = redundancy.as_string();
- }
-
bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override {
rst_stream_frames_.push_back(frame);
return true;
@@ -111,6 +104,11 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
return true;
}
+ bool OnPathCloseFrame(const QuicPathCloseFrame& frame) override {
+ path_close_frames_.push_back(frame);
+ return true;
+ }
+
void OnPacketComplete() override {}
const QuicPacketHeader& header() const { return header_; }
@@ -131,7 +129,6 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
return stop_waiting_frames_;
}
const vector<QuicPingFrame>& ping_frames() const { return ping_frames_; }
- StringPiece fec_data() const { return fec_redundancy_; }
const QuicVersionNegotiationPacket* version_negotiation_packet() const {
return version_negotiation_packet_.get();
}
@@ -142,7 +139,6 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
QuicPacketHeader header_;
scoped_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_;
scoped_ptr<QuicPublicResetPacket> public_reset_packet_;
- string fec_redundancy_;
vector<QuicAckFrame> ack_frames_;
vector<QuicStopWaitingFrame> stop_waiting_frames_;
vector<QuicPingFrame> ping_frames_;
@@ -152,6 +148,7 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
vector<QuicConnectionCloseFrame> connection_close_frames_;
vector<QuicWindowUpdateFrame> window_update_frames_;
vector<QuicBlockedFrame> blocked_frames_;
+ vector<QuicPathCloseFrame> path_close_frames_;
vector<string*> stream_data_;
DISALLOW_COPY_AND_ASSIGN(SimpleFramerVisitor);
@@ -181,10 +178,6 @@ const QuicPacketHeader& SimpleQuicFramer::header() const {
return visitor_->header();
}
-StringPiece SimpleQuicFramer::fec_data() const {
- return visitor_->fec_data();
-}
-
const QuicVersionNegotiationPacket*
SimpleQuicFramer::version_negotiation_packet() const {
return visitor_->version_negotiation_packet();
diff --git a/chromium/net/quic/test_tools/simple_quic_framer.h b/chromium/net/quic/test_tools/simple_quic_framer.h
index c476550be8b..f09db61e830 100644
--- a/chromium/net/quic/test_tools/simple_quic_framer.h
+++ b/chromium/net/quic/test_tools/simple_quic_framer.h
@@ -46,7 +46,6 @@ class SimpleQuicFramer {
const std::vector<QuicGoAwayFrame>& goaway_frames() const;
const std::vector<QuicRstStreamFrame>& rst_stream_frames() const;
const std::vector<QuicStreamFrame*>& stream_frames() const;
- base::StringPiece fec_data() const;
const QuicVersionNegotiationPacket* version_negotiation_packet() const;
QuicFramer* framer();
diff --git a/chromium/net/sdch/sdch_owner.cc b/chromium/net/sdch/sdch_owner.cc
index bfb2dd91b65..03e268e1343 100644
--- a/chromium/net/sdch/sdch_owner.cc
+++ b/chromium/net/sdch/sdch_owner.cc
@@ -11,8 +11,6 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
-#include "base/prefs/persistent_pref_store.h"
-#include "base/prefs/value_map_pref_store.h"
#include "base/strings/string_util.h"
#include "base/time/default_clock.h"
#include "base/values.h"
@@ -23,19 +21,6 @@ namespace net {
namespace {
-enum PersistenceFailureReason {
- // File didn't exist; is being created.
- PERSISTENCE_FAILURE_REASON_NO_FILE = 1,
-
- // Error reading in information, but should be able to write.
- PERSISTENCE_FAILURE_REASON_READ_FAILED = 2,
-
- // Error leading to abort on attempted persistence.
- PERSISTENCE_FAILURE_REASON_WRITE_FAILED = 3,
-
- PERSISTENCE_FAILURE_REASON_MAX = 4
-};
-
// Dictionaries that haven't been touched in 24 hours may be evicted
// to make room for new dictionaries.
const int kFreshnessLifetimeHours = 24;
@@ -43,9 +28,11 @@ const int kFreshnessLifetimeHours = 24;
// Dictionaries that have never been used only stay fresh for one hour.
const int kNeverUsedFreshnessLifetimeHours = 1;
-void RecordPersistenceFailure(PersistenceFailureReason failure_reason) {
- UMA_HISTOGRAM_ENUMERATION("Sdch3.PersistenceFailureReason", failure_reason,
- PERSISTENCE_FAILURE_REASON_MAX);
+void RecordPersistenceFailure(
+ SdchOwner::PrefStorage::ReadError failure_reason) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Sdch3.PersistenceFailureReason", failure_reason,
+ SdchOwner::PrefStorage::PERSISTENCE_FAILURE_REASON_MAX);
}
// Schema specifications and access routines.
@@ -54,7 +41,7 @@ void RecordPersistenceFailure(PersistenceFailureReason failure_reason) {
// stack systems that want to persist data over browser restarts, and so
// use of it must be namespace restricted.
// Schema:
-// pref_store_->GetValue(kPreferenceName) -> Dictionary {
+// pref_store_->GetValue() -> Dictionary {
// 'version' -> 2 [int]
// 'dictionaries' -> Dictionary {
// server_hash -> {
@@ -65,7 +52,6 @@ void RecordPersistenceFailure(PersistenceFailureReason failure_reason) {
// 'size' -> size [int]
// }
// }
-const char kPreferenceName[] = "SDCH";
const char kVersionKey[] = "version";
const char kDictionariesKey[] = "dictionaries";
const char kDictionaryUrlKey[] = "url";
@@ -76,19 +62,49 @@ const char kDictionarySizeKey[] = "size";
const int kVersion = 2;
+// A simple implementation of pref storage that just stores the value in
+// memory.
+class ValueMapPrefStorage : public SdchOwner::PrefStorage {
+ public:
+ ValueMapPrefStorage() {}
+ ~ValueMapPrefStorage() override {}
+
+ ReadError GetReadError() const override { return PERSISTENCE_FAILURE_NONE; }
+
+ bool GetValue(const base::DictionaryValue** result) const override {
+ *result = &storage_;
+ return true;
+ }
+ bool GetMutableValue(base::DictionaryValue** result) override {
+ *result = &storage_;
+ return true;
+ }
+ void SetValue(scoped_ptr<base::DictionaryValue> value) override {
+ storage_.Clear();
+ storage_.MergeDictionary(value.get());
+ }
+
+ void ReportValueChanged() override {}
+
+ // This storage class requires no special initialization.
+ bool IsInitializationComplete() override { return true; }
+ void StartObservingInit(SdchOwner* observer) override {}
+ void StopObservingInit() override {}
+
+ private:
+ base::DictionaryValue storage_;
+
+ DISALLOW_COPY_AND_ASSIGN(ValueMapPrefStorage);
+};
+
// This function returns store[kPreferenceName/kDictionariesKey]. The caller
// is responsible for making sure any needed calls to
// |store->ReportValueChanged()| occur.
base::DictionaryValue* GetPersistentStoreDictionaryMap(
- WriteablePrefStore* store) {
- base::Value* result = nullptr;
- bool success = store->GetMutableValue(kPreferenceName, &result);
- DCHECK(success);
-
+ SdchOwner::PrefStorage* store) {
base::DictionaryValue* preference_dictionary = nullptr;
- success = result->GetAsDictionary(&preference_dictionary);
+ bool success = store->GetMutableValue(&preference_dictionary);
DCHECK(success);
- DCHECK(preference_dictionary);
base::DictionaryValue* dictionary_list_dictionary = nullptr;
success = preference_dictionary->GetDictionary(kDictionariesKey,
@@ -102,13 +118,12 @@ base::DictionaryValue* GetPersistentStoreDictionaryMap(
// This function initializes a pref store with an empty version of the
// above schema, removing anything previously in the store under
// kPreferenceName.
-void InitializePrefStore(WriteablePrefStore* store) {
+void InitializePrefStore(SdchOwner::PrefStorage* store) {
scoped_ptr<base::DictionaryValue> empty_store(new base::DictionaryValue);
empty_store->SetInteger(kVersionKey, kVersion);
empty_store->Set(kDictionariesKey,
make_scoped_ptr(new base::DictionaryValue));
- store->SetValue(kPreferenceName, std::move(empty_store),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ store->SetValue(std::move(empty_store));
}
// A class to allow iteration over all dictionaries in the pref store, and
@@ -122,7 +137,7 @@ void InitializePrefStore(WriteablePrefStore* store) {
// pref store schema.
class DictionaryPreferenceIterator {
public:
- explicit DictionaryPreferenceIterator(WriteablePrefStore* pref_store);
+ explicit DictionaryPreferenceIterator(SdchOwner::PrefStorage* pref_store);
bool IsAtEnd() const;
void Advance();
@@ -152,7 +167,7 @@ class DictionaryPreferenceIterator {
};
DictionaryPreferenceIterator::DictionaryPreferenceIterator(
- WriteablePrefStore* pref_store)
+ SdchOwner::PrefStorage* pref_store)
: use_count_(0),
size_(0),
dictionary_iterator_(*GetPersistentStoreDictionaryMap(pref_store)) {
@@ -215,21 +230,19 @@ bool DictionaryPreferenceIterator::TryLoadDictionary() {
return true;
}
-// Triggers a ReportValueChanged() on the specified WriteablePrefStore
-// when the object goes out of scope.
+// Triggers a ReportValueChanged() when the object goes out of scope.
class ScopedPrefNotifier {
public:
// Caller must guarantee lifetime of |*pref_store| exceeds the
// lifetime of this object.
- ScopedPrefNotifier(WriteablePrefStore* pref_store)
- : pref_store_(pref_store) {}
- ~ScopedPrefNotifier() {
- pref_store_->ReportValueChanged(
- kPreferenceName, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ ScopedPrefNotifier(SdchOwner::PrefStorage* pref_store)
+ : pref_store_(pref_store) {
+ DCHECK(pref_store);
}
+ ~ScopedPrefNotifier() { pref_store_->ReportValueChanged(); }
private:
- WriteablePrefStore* pref_store_;
+ SdchOwner::PrefStorage* pref_store_;
DISALLOW_COPY_AND_ASSIGN(ScopedPrefNotifier);
};
@@ -245,6 +258,8 @@ const size_t SdchOwner::kMaxTotalDictionarySize = 2 * 500 * 1000;
const size_t SdchOwner::kMaxTotalDictionarySize = 20 * 1000 * 1000;
#endif
+SdchOwner::PrefStorage::~PrefStorage() {}
+
// Somewhat arbitrary, but we assume a dictionary smaller than
// 50K isn't going to do anyone any good. Note that this still doesn't
// prevent download and addition unless there is less than this
@@ -287,7 +302,7 @@ SdchOwner::SdchOwner(SdchManager* sdch_manager, URLRequestContext* context)
// SdchOwner, the SdchOwner object will be available
// for the lifetime of |memory_pressure_listener_|.
base::Unretained(this))),
- in_memory_pref_store_(new ValueMapPrefStore()),
+ in_memory_pref_store_(new ValueMapPrefStorage()),
external_pref_store_(nullptr),
pref_store_(in_memory_pref_store_.get()),
creation_time_(clock_->Now()) {
@@ -309,8 +324,8 @@ SdchOwner::~SdchOwner() {
// This object only observes the external store during loading,
// i.e. before it's made the default preferences store.
- if (external_pref_store_)
- external_pref_store_->RemoveObserver(this);
+ if (external_pref_store_ && pref_store_ != external_pref_store_.get())
+ external_pref_store_->StopObservingInit();
int64_t object_lifetime = (clock_->Now() - creation_time_).InMilliseconds();
for (const auto& val : consumed_byte_seconds_) {
@@ -321,16 +336,16 @@ SdchOwner::~SdchOwner() {
val / object_lifetime);
}
}
-
}
-void SdchOwner::EnablePersistentStorage(PersistentPrefStore* pref_store) {
+void SdchOwner::EnablePersistentStorage(scoped_ptr<PrefStorage> pref_store) {
DCHECK(!external_pref_store_);
- external_pref_store_ = pref_store;
- external_pref_store_->AddObserver(this);
+ DCHECK(pref_store);
+ external_pref_store_ = std::move(pref_store);
+ external_pref_store_->StartObservingInit(this);
if (external_pref_store_->IsInitializationComplete())
- OnInitializationCompleted(true);
+ OnPrefStorageInitializationComplete(true);
}
void SdchOwner::SetMaxTotalDictionarySize(size_t max_total_dictionary_size) {
@@ -581,12 +596,8 @@ void SdchOwner::OnClearDictionaries() {
InitializePrefStore(pref_store_);
}
-void SdchOwner::OnPrefValueChanged(const std::string& key) {
-}
-
-void SdchOwner::OnInitializationCompleted(bool succeeded) {
- PersistentPrefStore::PrefReadError error =
- external_pref_store_->GetReadError();
+void SdchOwner::OnPrefStorageInitializationComplete(bool succeeded) {
+ PrefStorage::ReadError error = external_pref_store_->GetReadError();
// Errors on load are self-correcting; if dictionaries were not
// persisted from the last instance of the browser, they will be
// faulted in by user action over time. However, if a load error
@@ -594,73 +605,38 @@ void SdchOwner::OnInitializationCompleted(bool succeeded) {
// the in memory pref store is left in place.
if (!succeeded) {
// Failure means a write failed, since read failures are recoverable.
- DCHECK_NE(
- error,
- PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE);
- DCHECK_NE(error,
- PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM);
-
- LOG(ERROR) << "Pref store write failed: " << error;
- external_pref_store_->RemoveObserver(this);
+ external_pref_store_->StopObservingInit();
external_pref_store_ = nullptr;
- RecordPersistenceFailure(PERSISTENCE_FAILURE_REASON_WRITE_FAILED);
+ RecordPersistenceFailure(
+ PrefStorage::PERSISTENCE_FAILURE_REASON_WRITE_FAILED);
return;
}
- switch (external_pref_store_->GetReadError()) {
- case PersistentPrefStore::PREF_READ_ERROR_NONE:
- break;
-
- case PersistentPrefStore::PREF_READ_ERROR_NO_FILE:
- // First time reading; the file will be created.
- RecordPersistenceFailure(PERSISTENCE_FAILURE_REASON_NO_FILE);
- break;
-
- case PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE:
- case PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE:
- case PersistentPrefStore::PREF_READ_ERROR_FILE_OTHER:
- case PersistentPrefStore::PREF_READ_ERROR_FILE_LOCKED:
- case PersistentPrefStore::PREF_READ_ERROR_JSON_REPEAT:
- RecordPersistenceFailure(PERSISTENCE_FAILURE_REASON_READ_FAILED);
- break;
-
- case PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED:
- case PersistentPrefStore::PREF_READ_ERROR_FILE_NOT_SPECIFIED:
- case PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE:
- case PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM:
- // Shouldn't ever happen. ACCESS_DENIED and FILE_NOT_SPECIFIED should
- // imply !succeeded, and TASK_INCOMPLETE should never be delivered.
- NOTREACHED();
- break;
- }
+ if (error != PrefStorage::PERSISTENCE_FAILURE_NONE)
+ RecordPersistenceFailure(error);
// Load in what was stored before chrome exited previously.
- const base::Value* sdch_persistence_value = nullptr;
const base::DictionaryValue* sdch_persistence_dictionary = nullptr;
// The GetPersistentStore() routine above assumes data formatted
// according to the schema described at the top of this file. Since
// this data comes from disk, to avoid disk corruption resulting in
// persistent chrome errors this code avoids those assupmtions.
- if (external_pref_store_->GetValue(kPreferenceName,
- &sdch_persistence_value) &&
- sdch_persistence_value->GetAsDictionary(&sdch_persistence_dictionary)) {
+ if (external_pref_store_->GetValue(&sdch_persistence_dictionary))
SchedulePersistedDictionaryLoads(*sdch_persistence_dictionary);
- }
// Reset the persistent store and update it with the accumulated
// information from the local store.
- InitializePrefStore(external_pref_store_);
+ InitializePrefStore(external_pref_store_.get());
- ScopedPrefNotifier scoped_pref_notifier(external_pref_store_);
- GetPersistentStoreDictionaryMap(external_pref_store_)
+ ScopedPrefNotifier scoped_pref_notifier(external_pref_store_.get());
+ GetPersistentStoreDictionaryMap(external_pref_store_.get())
->Swap(GetPersistentStoreDictionaryMap(in_memory_pref_store_.get()));
// This object can stop waiting on (i.e. observing) the external preference
// store and switch over to using it as the primary preference store.
- pref_store_ = external_pref_store_;
- external_pref_store_->RemoveObserver(this);
- external_pref_store_ = nullptr;
+ pref_store_ = external_pref_store_.get();
+ external_pref_store_->StopObservingInit();
in_memory_pref_store_ = nullptr;
}
diff --git a/chromium/net/sdch/sdch_owner.h b/chromium/net/sdch/sdch_owner.h
index 3c965d92a1e..6af0bf01f0b 100644
--- a/chromium/net/sdch/sdch_owner.h
+++ b/chromium/net/sdch/sdch_owner.h
@@ -14,14 +14,10 @@
#include "base/macros.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/ref_counted.h"
-#include "base/prefs/pref_store.h"
#include "net/base/sdch_observer.h"
#include "net/url_request/sdch_dictionary_fetcher.h"
class GURL;
-class PersistentPrefStore;
-class ValueMapPrefStore;
-class WriteablePrefStore;
namespace base {
class Clock;
@@ -35,8 +31,63 @@ class URLRequestContext;
// exposes interface for setting SDCH policy. It should be instantiated by
// the net/ embedder.
// TODO(rdsmith): Implement dictionary prioritization.
-class NET_EXPORT SdchOwner : public SdchObserver, public PrefStore::Observer {
+class NET_EXPORT SdchOwner : public SdchObserver {
public:
+ // Abstact storage interface for storing settings that allows the embedder
+ // to provide the appropriate storage backend.
+ class NET_EXPORT PrefStorage {
+ public:
+ // Possible values returned by GetReadError. This is a subset of the error
+ // values of Chromium's pref storage that we care about.
+ //
+ // DO NOT CHANGE VALUES. This is logged persistently in a histogram.
+ enum ReadError {
+ PERSISTENCE_FAILURE_NONE = 0,
+
+ // File didn't exist; is being created.
+ PERSISTENCE_FAILURE_REASON_NO_FILE = 1,
+
+ // Error reading in information, but should be able to write.
+ PERSISTENCE_FAILURE_REASON_READ_FAILED = 2,
+
+ // Error leading to abort on attempted persistence.
+ PERSISTENCE_FAILURE_REASON_WRITE_FAILED = 3,
+
+ // Anything else.
+ PERSISTENCE_FAILURE_REASON_OTHER = 4,
+
+ PERSISTENCE_FAILURE_REASON_MAX = 5
+ // See RecordPersistenceFailure for UMA logging of this value if
+ // adding a value here.
+ };
+
+ virtual ~PrefStorage();
+
+ // Returns the read error if any. Valid to be called after initialization
+ // is complete (see IsInitializationComplete).
+ virtual ReadError GetReadError() const = 0;
+
+ // Gets or sets the value in the preferences store.
+ virtual bool GetValue(const base::DictionaryValue** result) const = 0;
+ virtual bool GetMutableValue(base::DictionaryValue** result) = 0;
+ virtual void SetValue(scoped_ptr<base::DictionaryValue> value) = 0;
+
+ // Notifies the storage system that a value was changed via mutating the
+ // result of GetMutableValue().
+ virtual void ReportValueChanged() = 0;
+
+ // Returns true if the store's init is complete. See the Start/Stop
+ // functions below for observing changes to this value.
+ virtual bool IsInitializationComplete() = 0;
+
+ // Starts and stops observing preferences storage init. There will only
+ // be one observer active at a time. The store should call
+ // OnPrefStorageInitializationComplete() when it transitions to initialized
+ // and there is an observer active. See also IsInitializationComplete().
+ virtual void StartObservingInit(SdchOwner* observer) = 0;
+ virtual void StopObservingInit() = 0;
+ };
+
static const size_t kMaxTotalDictionarySize;
static const size_t kMinSpaceForDictionaryFetch;
@@ -45,12 +96,9 @@ class NET_EXPORT SdchOwner : public SdchObserver, public PrefStore::Observer {
SdchOwner(SdchManager* sdch_manager, URLRequestContext* context);
~SdchOwner() override;
- // Enables use of pref persistence. Note that |pref_store| is owned
- // by the caller, but must be guaranteed to outlive SdchOwner. The
- // actual mechanisms by which the PersistentPrefStore are persisted
- // are the responsibility of the caller. This routine may only be
- // called once per SdchOwner instance.
- void EnablePersistentStorage(PersistentPrefStore* pref_store);
+ // Enables use of pref persistence. Ownership of the storage will be passed.
+ // This routine may only be called once per SdchOwner instance.
+ void EnablePersistentStorage(scoped_ptr<PrefStorage> pref_store);
// Defaults to kMaxTotalDictionarySize.
void SetMaxTotalDictionarySize(size_t max_total_dictionary_size);
@@ -67,9 +115,9 @@ class NET_EXPORT SdchOwner : public SdchObserver, public PrefStore::Observer {
const GURL& dictionary_url) override;
void OnClearDictionaries() override;
- // PrefStore::Observer implementation.
- void OnPrefValueChanged(const std::string& key) override;
- void OnInitializationCompleted(bool succeeded) override;
+ // Called by the PrefStorage implementation when initialization is complete.
+ // See PrefStorage::StartObservingInit().
+ void OnPrefStorageInitializationComplete(bool succeeded);
// Implementation detail--this is the function callback by the callback passed
// to the fetcher through which the fetcher informs the SdchOwner that it's
@@ -179,21 +227,21 @@ class NET_EXPORT SdchOwner : public SdchObserver, public PrefStore::Observer {
base::MemoryPressureListener memory_pressure_listener_;
// Dictionary persistence machinery.
- // * |in_memory_pref_store_| is created on construction and used in
- // the absence of any call to EnablePersistentStorage().
- // * |external_pref_store_| holds the preference store specified
- // by EnablePersistentStorage() (if any), while it is being read in.
- // A non-null value here signals that the SdchOwner is observing
- // the pref store; when read-in completes and observation is no longer
- // needed, the pointer is set to null. This is to avoid lots of
- // extra irrelevant function calls; the only observer interface this
- // class is interested in is OnInitializationCompleted().
+ // * |in_memory_pref_store_| is created on construction and used in the
+ // absence of any call to EnablePersistentStorage().
+ // * |external_pref_store_| holds the preference store specified by
+ // EnablePersistentStorage() (if any).
+ // * The external pref store is initialized asynchronously. During this time,
+ // both pointers will be value, pref_store_ will point to the in-memory
+ // one, and this class will be observing the initialization of the external
+ // store.
+ // * When the external pref store is initialized, the in-memory version will
+ // be freed, and pref_store_ will point to the external one.
// * |pref_store_| holds an unowned pointer to the currently
// active pref store (one of the preceding two).
- scoped_refptr<ValueMapPrefStore> in_memory_pref_store_;
- PersistentPrefStore* external_pref_store_;
-
- WriteablePrefStore* pref_store_;
+ scoped_ptr<PrefStorage> in_memory_pref_store_;
+ scoped_ptr<PrefStorage> external_pref_store_;
+ PrefStorage* pref_store_;
// The use counts of dictionaries when they were loaded from the persistent
// store, keyed by server hash. These are stored to avoid generating
diff --git a/chromium/net/sdch/sdch_owner_unittest.cc b/chromium/net/sdch/sdch_owner_unittest.cc
index 9ce957928f2..91d1e6d51f3 100644
--- a/chromium/net/sdch/sdch_owner_unittest.cc
+++ b/chromium/net/sdch/sdch_owner_unittest.cc
@@ -9,7 +9,6 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/memory_pressure_listener.h"
-#include "base/prefs/testing_pref_store.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
@@ -27,17 +26,16 @@
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace net {
+
namespace {
-bool GetDictionaryForURL(TestingPrefStore* store,
+bool GetDictionaryForURL(SdchOwner::PrefStorage* store,
const GURL& url,
std::string* hash,
base::DictionaryValue** dict) {
- base::Value* sdch_val = nullptr;
base::DictionaryValue* sdch_dict = nullptr;
- if (!store->GetMutableValue("SDCH", &sdch_val))
- return false;
- if (!sdch_val->GetAsDictionary(&sdch_dict))
+ if (!store->GetMutableValue(&sdch_dict))
return false;
base::DictionaryValue* dicts_dict = nullptr;
@@ -63,9 +61,59 @@ bool GetDictionaryForURL(TestingPrefStore* store,
return false;
}
-} // namespace
+// This class supports copying so we can emulate persistent storage.
+class TestPrefStorage : public SdchOwner::PrefStorage {
+ public:
+ explicit TestPrefStorage(bool initialized)
+ : initialized_(initialized), initialization_observer_(nullptr) {}
+ explicit TestPrefStorage(const TestPrefStorage& other)
+ : initialized_(other.initialized_),
+ initialization_observer_(nullptr) { // Don't copy observer.
+ storage_.MergeDictionary(&other.storage_);
+ }
-namespace net {
+ ~TestPrefStorage() override {}
+
+ void SetInitialized() {
+ DCHECK(!initialized_);
+ initialized_ = true;
+ if (initialization_observer_)
+ initialization_observer_->OnPrefStorageInitializationComplete(true);
+ }
+
+ ReadError GetReadError() const override { return PERSISTENCE_FAILURE_NONE; }
+
+ bool GetValue(const base::DictionaryValue** result) const override {
+ *result = &storage_;
+ return true;
+ }
+ bool GetMutableValue(base::DictionaryValue** result) override {
+ *result = &storage_;
+ return true;
+ }
+ void SetValue(scoped_ptr<base::DictionaryValue> value) override {
+ storage_.Clear();
+ storage_.MergeDictionary(value.get());
+ }
+
+ void ReportValueChanged() override {}
+
+ // This storage class requires no special initialization.
+ bool IsInitializationComplete() override { return initialized_; }
+ void StartObservingInit(SdchOwner* observer) override {
+ DCHECK(!initialization_observer_);
+ initialization_observer_ = observer;
+ }
+ void StopObservingInit() override { initialization_observer_ = nullptr; }
+
+ private:
+ bool initialized_;
+ SdchOwner* initialization_observer_;
+
+ base::DictionaryValue storage_;
+};
+
+} // namespace
static const char generic_url[] = "http://www.example.com";
static const char generic_domain[] = "www.example.com";
@@ -263,7 +311,6 @@ class SdchOwnerTest : public testing::Test {
SdchOwnerTest()
: last_jobs_created_(error_jobs_created),
dictionary_creation_index_(0),
- pref_store_(new TestingPrefStore),
sdch_owner_(new SdchOwner(&sdch_manager_, &url_request_context_)) {
// Any jobs created on this context will immediately error,
// which leaves the test in control of signals to SdchOwner.
@@ -277,7 +324,6 @@ class SdchOwnerTest : public testing::Test {
SdchManager& sdch_manager() { return sdch_manager_; }
SdchOwner& sdch_owner() { return *(sdch_owner_.get()); }
BoundNetLog& bound_net_log() { return net_log_; }
- TestingPrefStore& pref_store() { return *(pref_store_.get()); }
int JobsRecentlyCreated() {
int result = error_jobs_created - last_jobs_created_;
@@ -359,7 +405,6 @@ class SdchOwnerTest : public testing::Test {
MockURLRequestJobFactory job_factory_;
URLRequestContext url_request_context_;
SdchManager sdch_manager_;
- scoped_refptr<TestingPrefStore> pref_store_;
scoped_ptr<SdchOwner> sdch_owner_;
DISALLOW_COPY_AND_ASSIGN(SdchOwnerTest);
@@ -686,8 +731,10 @@ TEST_F(SdchOwnerTest, MemoryPressureReturnsSpace) {
// Confirm that use of a pinned dictionary after its removal works properly.
TEST_F(SdchOwnerTest, PinRemoveUse) {
- pref_store().SetInitializationCompleted();
- sdch_owner().EnablePersistentStorage(&pref_store());
+ // Pass ownership of the storage to the SdchOwner, but keep a pointer.
+ TestPrefStorage* pref_store = new TestPrefStorage(true);
+ sdch_owner().EnablePersistentStorage(
+ scoped_ptr<SdchOwner::PrefStorage>(pref_store));
std::string server_hash_d1;
EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, base::Time::Now(),
@@ -701,15 +748,13 @@ TEST_F(SdchOwnerTest, PinRemoveUse) {
const base::Value* result = nullptr;
const base::DictionaryValue* dict_result = nullptr;
- ASSERT_TRUE(pref_store().GetValue("SDCH", &result));
- ASSERT_TRUE(result->GetAsDictionary(&dict_result));
+ ASSERT_TRUE(pref_store->GetValue(&dict_result));
EXPECT_TRUE(dict_result->Get("dictionaries", &result));
EXPECT_TRUE(dict_result->Get("dictionaries." + server_hash_d1, &result));
sdch_manager().ClearData();
- ASSERT_TRUE(pref_store().GetValue("SDCH", &result));
- ASSERT_TRUE(result->GetAsDictionary(&dict_result));
+ ASSERT_TRUE(pref_store->GetValue(&dict_result));
EXPECT_TRUE(dict_result->Get("dictionaries", &result));
EXPECT_FALSE(dict_result->Get("dictionaries." + server_hash_d1, &result));
@@ -720,8 +765,7 @@ TEST_F(SdchOwnerTest, PinRemoveUse) {
sdch_manager().OnDictionaryUsed(server_hash_d1);
- ASSERT_TRUE(pref_store().GetValue("SDCH", &result));
- ASSERT_TRUE(result->GetAsDictionary(&dict_result));
+ ASSERT_TRUE(pref_store->GetValue(&dict_result));
EXPECT_TRUE(dict_result->Get("dictionaries", &result));
EXPECT_FALSE(dict_result->Get("dictionaries." + server_hash_d1, &result));
}
@@ -749,16 +793,16 @@ TEST_F(SdchOwnerTest, UsageIntervalMetrics) {
class SdchOwnerPersistenceTest : public ::testing::Test {
public:
- SdchOwnerPersistenceTest() : pref_store_(new TestingPrefStore()) {
- pref_store_->SetInitializationCompleted();
- }
+ SdchOwnerPersistenceTest() {}
virtual ~SdchOwnerPersistenceTest() {}
void ClearOwner() {
owner_.reset(NULL);
}
- void ResetOwner(bool delay) {
+ // If the storage points is non-null it will be saved as the persistent
+ // storage for the SdchOwner.
+ void ResetOwner(scoped_ptr<SdchOwner::PrefStorage> storage) {
// This has to be done first, since SdchOwner may be observing SdchManager,
// and SdchManager can't be destroyed with a live observer.
owner_.reset(NULL);
@@ -770,8 +814,8 @@ class SdchOwnerPersistenceTest : public ::testing::Test {
owner_->SetMinSpaceForDictionaryFetch(
SdchOwnerTest::kMinFetchSpaceForTesting);
owner_->SetFetcherForTesting(make_scoped_ptr(fetcher_));
- if (!delay)
- owner_->EnablePersistentStorage(pref_store_.get());
+ if (storage)
+ owner_->EnablePersistentStorage(std::move(storage));
}
void InsertDictionaryForURL(const GURL& url, const std::string& nonce) {
@@ -798,7 +842,6 @@ class SdchOwnerPersistenceTest : public ::testing::Test {
protected:
BoundNetLog net_log_;
- scoped_refptr<TestingPrefStore> pref_store_;
scoped_ptr<SdchManager> manager_;
MockSdchDictionaryFetcher* fetcher_;
scoped_ptr<SdchOwner> owner_;
@@ -807,15 +850,7 @@ class SdchOwnerPersistenceTest : public ::testing::Test {
// Test an empty persistence store.
TEST_F(SdchOwnerPersistenceTest, Empty) {
- ResetOwner(false);
- EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
-}
-
-// Test a persistence store with an empty dictionary.
-TEST_F(SdchOwnerPersistenceTest, Persistent_EmptyDict) {
- pref_store_->SetValue("SDCH", make_scoped_ptr(new base::DictionaryValue()),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- ResetOwner(false);
+ ResetOwner(make_scoped_ptr(new TestPrefStorage(true)));
EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
}
@@ -823,10 +858,15 @@ TEST_F(SdchOwnerPersistenceTest, Persistent_EmptyDict) {
TEST_F(SdchOwnerPersistenceTest, Persistent_BadVersion) {
scoped_ptr<base::DictionaryValue> sdch_dict(new base::DictionaryValue());
sdch_dict->SetInteger("version", 2);
- pref_store_->SetValue("SDCH", std::move(sdch_dict),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- ResetOwner(false);
+ scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true));
+ storage->SetValue(std::move(sdch_dict));
+
+ TestPrefStorage* old_storage = storage.get(); // Save storage pointer.
+ ResetOwner(std::move(storage)); // Takes ownership of storage pointer.
+
+ storage.reset(new TestPrefStorage(*old_storage));
+ ResetOwner(std::move(storage));
EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
}
@@ -836,21 +876,25 @@ TEST_F(SdchOwnerPersistenceTest, Persistent_EmptyDictList) {
scoped_ptr<base::DictionaryValue> dicts(new base::DictionaryValue());
sdch_dict->SetInteger("version", 1);
sdch_dict->Set("dictionaries", std::move(dicts));
- pref_store_->SetValue("SDCH", std::move(sdch_dict),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- ResetOwner(false);
+ scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true));
+ storage->SetValue(std::move(sdch_dict));
+ ResetOwner(std::move(storage));
EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
}
TEST_F(SdchOwnerPersistenceTest, OneDict) {
const GURL url("http://www.example.com/dict");
- ResetOwner(false);
+
+ scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true));
+ TestPrefStorage* old_storage = storage.get(); // Save storage pointer.
+ ResetOwner(std::move(storage)); // Takes ownership of storage pointer.
EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
InsertDictionaryForURL(url, "0");
EXPECT_EQ(1, owner_->GetDictionaryCountForTesting());
- ResetOwner(false);
+ storage.reset(new TestPrefStorage(*old_storage));
+ ResetOwner(std::move(storage));
EXPECT_EQ(0, owner_->GetDictionaryCountForTesting());
EXPECT_TRUE(CompleteLoadFromURL(url, "0", true));
EXPECT_EQ(1, owner_->GetDictionaryCountForTesting());
@@ -859,11 +903,15 @@ TEST_F(SdchOwnerPersistenceTest, OneDict) {
TEST_F(SdchOwnerPersistenceTest, TwoDicts) {
const GURL url0("http://www.example.com/dict0");
const GURL url1("http://www.example.com/dict1");
- ResetOwner(false);
+
+ scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true));
+ TestPrefStorage* old_storage = storage.get(); // Save storage pointer.
+ ResetOwner(std::move(storage)); // Takes ownership of storage pointer.
InsertDictionaryForURL(url0, "0");
InsertDictionaryForURL(url1, "1");
- ResetOwner(false);
+ storage.reset(new TestPrefStorage(*old_storage));
+ ResetOwner(std::move(storage));
EXPECT_TRUE(CompleteLoadFromURL(url0, "0", true));
EXPECT_TRUE(CompleteLoadFromURL(url1, "1", true));
EXPECT_EQ(2, owner_->GetDictionaryCountForTesting());
@@ -874,19 +922,20 @@ TEST_F(SdchOwnerPersistenceTest, TwoDicts) {
TEST_F(SdchOwnerPersistenceTest, OneGoodDictOneBadDict) {
const GURL url0("http://www.example.com/dict0");
const GURL url1("http://www.example.com/dict1");
- ResetOwner(false);
+
+ scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true));
+ TestPrefStorage* old_storage = storage.get(); // Save storage pointer.
+ ResetOwner(std::move(storage)); // Takes ownership of storage.
InsertDictionaryForURL(url0, "0");
InsertDictionaryForURL(url1, "1");
- // Mutate the pref store a bit now. Clear the owner first, to ensure that the
- // SdchOwner doesn't observe these changes and object. The manual dictionary
- // manipulation is a bit icky.
- ClearOwner();
+ // Make a new storage based on the current contents of the old one.
+ storage.reset(new TestPrefStorage(*old_storage));
base::DictionaryValue* dict = nullptr;
- ASSERT_TRUE(GetDictionaryForURL(pref_store_.get(), url1, nullptr, &dict));
+ ASSERT_TRUE(GetDictionaryForURL(storage.get(), url1, nullptr, &dict));
dict->Remove("use_count", nullptr);
- ResetOwner(false);
+ ResetOwner(std::move(storage));
EXPECT_TRUE(CompleteLoadFromURL(url0, "0", true));
EXPECT_FALSE(CompleteLoadFromURL(url1, "1", true));
EXPECT_EQ(1, owner_->GetDictionaryCountForTesting());
@@ -896,27 +945,31 @@ TEST_F(SdchOwnerPersistenceTest, OneGoodDictOneBadDict) {
TEST_F(SdchOwnerPersistenceTest, UsingDictionaryUpdatesUseCount) {
const GURL url("http://www.example.com/dict");
- ResetOwner(false);
+
+ scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true));
+ TestPrefStorage* old_storage = storage.get(); // Save storage pointer.
+ ResetOwner(std::move(storage)); // Takes ownership of storage pointer.
InsertDictionaryForURL(url, "0");
std::string hash;
int old_count;
+ storage.reset(new TestPrefStorage(*old_storage));
{
ClearOwner();
base::DictionaryValue* dict = nullptr;
- ASSERT_TRUE(GetDictionaryForURL(pref_store_.get(), url, &hash, &dict));
+ ASSERT_TRUE(GetDictionaryForURL(storage.get(), url, &hash, &dict));
ASSERT_TRUE(dict->GetInteger("use_count", &old_count));
}
- ResetOwner(false);
+ old_storage = storage.get(); // Save storage pointer.
+ ResetOwner(std::move(storage)); // Takes ownership of storage pointer.
ASSERT_TRUE(CompleteLoadFromURL(url, "0", true));
owner_->OnDictionaryUsed(hash);
int new_count;
{
- ClearOwner();
base::DictionaryValue* dict = nullptr;
- ASSERT_TRUE(GetDictionaryForURL(pref_store_.get(), url, nullptr, &dict));
+ ASSERT_TRUE(GetDictionaryForURL(old_storage, url, nullptr, &dict));
ASSERT_TRUE(dict->GetInteger("use_count", &new_count));
}
@@ -927,13 +980,16 @@ TEST_F(SdchOwnerPersistenceTest, LoadingDictionaryMerges) {
const GURL url0("http://www.example.com/dict0");
const GURL url1("http://www.example.com/dict1");
- ResetOwner(false);
+ scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true));
+ TestPrefStorage* old_storage = storage.get(); // Save storage pointer.
+ ResetOwner(std::move(storage)); // Takes ownership of storage pointer.
InsertDictionaryForURL(url1, "1");
- ResetOwner(true);
+ storage.reset(new TestPrefStorage(*old_storage));
+ ResetOwner(scoped_ptr<SdchOwner::PrefStorage>());
InsertDictionaryForURL(url0, "0");
EXPECT_EQ(1, owner_->GetDictionaryCountForTesting());
- owner_->EnablePersistentStorage(pref_store_.get());
+ owner_->EnablePersistentStorage(std::move(storage));
ASSERT_TRUE(CompleteLoadFromURL(url1, "1", true));
EXPECT_EQ(2, owner_->GetDictionaryCountForTesting());
}
@@ -941,12 +997,16 @@ TEST_F(SdchOwnerPersistenceTest, LoadingDictionaryMerges) {
TEST_F(SdchOwnerPersistenceTest, PersistenceMetrics) {
const GURL url0("http://www.example.com/dict0");
const GURL url1("http://www.example.com/dict1");
- ResetOwner(false);
+
+ scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true));
+ TestPrefStorage* old_storage = storage.get(); // Save storage pointer.
+ ResetOwner(std::move(storage)); // Takes ownership of storage pointer.
InsertDictionaryForURL(url0, "0");
InsertDictionaryForURL(url1, "1");
- ResetOwner(false);
+ storage.reset(new TestPrefStorage(*old_storage));
+ ResetOwner(std::move(storage));
base::HistogramTester tester;
diff --git a/chromium/net/server/http_server_request_info.cc b/chromium/net/server/http_server_request_info.cc
index 07c15a54353..765ddc030d3 100644
--- a/chromium/net/server/http_server_request_info.cc
+++ b/chromium/net/server/http_server_request_info.cc
@@ -11,6 +11,9 @@ namespace net {
HttpServerRequestInfo::HttpServerRequestInfo() {}
+HttpServerRequestInfo::HttpServerRequestInfo(
+ const HttpServerRequestInfo& other) = default;
+
HttpServerRequestInfo::~HttpServerRequestInfo() {}
std::string HttpServerRequestInfo::GetHeaderValue(
diff --git a/chromium/net/server/http_server_request_info.h b/chromium/net/server/http_server_request_info.h
index 1b02655b742..014142cac74 100644
--- a/chromium/net/server/http_server_request_info.h
+++ b/chromium/net/server/http_server_request_info.h
@@ -19,6 +19,7 @@ namespace net {
class HttpServerRequestInfo {
public:
HttpServerRequestInfo();
+ HttpServerRequestInfo(const HttpServerRequestInfo& other);
~HttpServerRequestInfo();
// Returns header value for given header name. |header_name| should be
diff --git a/chromium/net/server/http_server_response_info.cc b/chromium/net/server/http_server_response_info.cc
index 2d0a32e6cce..7c195812e5e 100644
--- a/chromium/net/server/http_server_response_info.cc
+++ b/chromium/net/server/http_server_response_info.cc
@@ -15,6 +15,9 @@ HttpServerResponseInfo::HttpServerResponseInfo() : status_code_(HTTP_OK) {}
HttpServerResponseInfo::HttpServerResponseInfo(HttpStatusCode status_code)
: status_code_(status_code) {}
+HttpServerResponseInfo::HttpServerResponseInfo(
+ const HttpServerResponseInfo& other) = default;
+
HttpServerResponseInfo::~HttpServerResponseInfo() {}
// static
diff --git a/chromium/net/server/http_server_response_info.h b/chromium/net/server/http_server_response_info.h
index fd8dfbc30b7..c2451e8d91e 100644
--- a/chromium/net/server/http_server_response_info.h
+++ b/chromium/net/server/http_server_response_info.h
@@ -20,6 +20,7 @@ class HttpServerResponseInfo {
// Creates a 200 OK HttpServerResponseInfo.
HttpServerResponseInfo();
explicit HttpServerResponseInfo(HttpStatusCode status_code);
+ HttpServerResponseInfo(const HttpServerResponseInfo& other);
~HttpServerResponseInfo();
static HttpServerResponseInfo CreateFor404();
diff --git a/chromium/net/server/http_server_unittest.cc b/chromium/net/server/http_server_unittest.cc
index bda95d1180a..2c72323db98 100644
--- a/chromium/net/server/http_server_unittest.cc
+++ b/chromium/net/server/http_server_unittest.cc
@@ -30,7 +30,6 @@
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/test_completion_callback.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
@@ -498,7 +497,6 @@ class MockStreamSocket : public StreamSocket {
void SetSubresourceSpeculation() override {}
void SetOmniboxSpeculation() override {}
bool WasEverUsed() const override { return true; }
- bool UsingTCPFastOpen() const override { return false; }
bool WasNpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
diff --git a/chromium/net/server/web_socket_encoder.cc b/chromium/net/server/web_socket_encoder.cc
index 6d59713d9b3..d90a156aaae 100644
--- a/chromium/net/server/web_socket_encoder.cc
+++ b/chromium/net/server/web_socket_encoder.cc
@@ -4,6 +4,7 @@
#include "net/server/web_socket_encoder.h"
+#include <limits>
#include <utility>
#include <vector>
diff --git a/chromium/net/server/web_socket_encoder.h b/chromium/net/server/web_socket_encoder.h
index 1e9206fd3c5..caeec946599 100644
--- a/chromium/net/server/web_socket_encoder.h
+++ b/chromium/net/server/web_socket_encoder.h
@@ -42,7 +42,7 @@ class WebSocketEncoder final {
int masking_key,
std::string* output);
- bool deflate_enabled() const { return deflater_; }
+ bool deflate_enabled() const { return !!deflater_; }
private:
enum Type {
diff --git a/chromium/net/socket/client_socket_handle.cc b/chromium/net/socket/client_socket_handle.cc
index b177fb6f3b2..97b1b89d844 100644
--- a/chromium/net/socket/client_socket_handle.cc
+++ b/chromium/net/socket/client_socket_handle.cc
@@ -10,6 +10,7 @@
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
+#include "base/trace_event/trace_event.h"
#include "net/base/net_errors.h"
#include "net/socket/client_socket_pool.h"
@@ -140,6 +141,7 @@ void ClientSocketHandle::SetSocket(scoped_ptr<StreamSocket> s) {
}
void ClientSocketHandle::OnIOComplete(int result) {
+ TRACE_EVENT0("net", "ClientSocketHandle::OnIOComplete");
CompletionCallback callback = user_callback_;
user_callback_.Reset();
HandleInitCompletion(result);
diff --git a/chromium/net/socket/client_socket_handle.h b/chromium/net/socket/client_socket_handle.h
index c5b2720f7d3..a8af5c078be 100644
--- a/chromium/net/socket/client_socket_handle.h
+++ b/chromium/net/socket/client_socket_handle.h
@@ -50,6 +50,8 @@ class NET_EXPORT ClientSocketHandle {
// ClientSocketPool to obtain a connected socket, possibly reusing one. This
// method returns either OK or ERR_IO_PENDING. On ERR_IO_PENDING, |priority|
// is used to determine the placement in ClientSocketPool's wait list.
+ // If |respect_limits| is DISABLED, will bypass the wait list, but |priority|
+ // must also be HIGHEST, if set.
//
// If this method succeeds, then the socket member will be set to an existing
// connected socket if an existing connected socket was available to reuse,
@@ -78,6 +80,7 @@ class NET_EXPORT ClientSocketHandle {
int Init(const std::string& group_name,
const scoped_refptr<typename PoolType::SocketParams>& socket_params,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const CompletionCallback& callback,
PoolType* pool,
const BoundNetLog& net_log);
@@ -236,6 +239,7 @@ int ClientSocketHandle::Init(
const std::string& group_name,
const scoped_refptr<typename PoolType::SocketParams>& socket_params,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const CompletionCallback& callback,
PoolType* pool,
const BoundNetLog& net_log) {
@@ -247,8 +251,8 @@ int ClientSocketHandle::Init(
pool_ = pool;
group_name_ = group_name;
init_time_ = base::TimeTicks::Now();
- int rv = pool_->RequestSocket(
- group_name, &socket_params, priority, this, callback_, net_log);
+ int rv = pool_->RequestSocket(group_name, &socket_params, priority,
+ respect_limits, this, callback_, net_log);
if (rv == ERR_IO_PENDING) {
user_callback_ = callback;
} else {
diff --git a/chromium/net/socket/client_socket_pool.h b/chromium/net/socket/client_socket_pool.h
index e1785a3a7c7..73d90dd485c 100644
--- a/chromium/net/socket/client_socket_pool.h
+++ b/chromium/net/socket/client_socket_pool.h
@@ -11,7 +11,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/template_util.h"
#include "base/time/time.h"
#include "net/base/completion_callback.h"
#include "net/base/load_states.h"
@@ -61,11 +60,14 @@ class NET_EXPORT LowerLayeredPool {
// A ClientSocketPool is used to restrict the number of sockets open at a time.
// It also maintains a list of idle persistent sockets.
//
+// Subclasses must also have an inner class SocketParams which is
+// the type for the |params| argument in RequestSocket() and
+// RequestSockets() below.
class NET_EXPORT ClientSocketPool : public LowerLayeredPool {
public:
- // Subclasses must also have an inner class SocketParams which is
- // the type for the |params| argument in RequestSocket() and
- // RequestSockets() below.
+ // Indicates whether or not a request for a socket should respect the
+ // SocketPool's global and per-group socket limits.
+ enum class RespectLimits { DISABLED, ENABLED };
// Requests a connected socket for a group_name.
//
@@ -96,9 +98,12 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool {
// client of completion.
//
// Profiling information for the request is saved to |net_log| if non-NULL.
+ //
+ // If |respect_limits| is DISABLED, priority must be HIGHEST.
virtual int RequestSocket(const std::string& group_name,
const void* params,
RequestPriority priority,
+ RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) = 0;
diff --git a/chromium/net/socket/client_socket_pool_base.cc b/chromium/net/socket/client_socket_pool_base.cc
index 4a76913b7a4..b240e3db026 100644
--- a/chromium/net/socket/client_socket_pool_base.cc
+++ b/chromium/net/socket/client_socket_pool_base.cc
@@ -16,6 +16,7 @@
#include "base/strings/string_util.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/net_errors.h"
#include "net/log/net_log.h"
@@ -53,11 +54,13 @@ bool g_connect_backup_jobs_enabled = true;
ConnectJob::ConnectJob(const std::string& group_name,
base::TimeDelta timeout_duration,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
Delegate* delegate,
const BoundNetLog& net_log)
: group_name_(group_name),
timeout_duration_(timeout_duration),
priority_(priority),
+ respect_limits_(respect_limits),
delegate_(delegate),
net_log_(net_log),
idle_(true) {
@@ -102,6 +105,7 @@ void ConnectJob::SetSocket(scoped_ptr<StreamSocket> socket) {
}
void ConnectJob::NotifyDelegateOfCompletion(int rv) {
+ TRACE_EVENT0("net", "ConnectJob::NotifyDelegateOfCompletion");
// The delegate will own |this|.
Delegate* delegate = delegate_;
delegate_ = NULL;
@@ -141,16 +145,16 @@ ClientSocketPoolBaseHelper::Request::Request(
ClientSocketHandle* handle,
const CompletionCallback& callback,
RequestPriority priority,
- bool ignore_limits,
+ ClientSocketPool::RespectLimits respect_limits,
Flags flags,
const BoundNetLog& net_log)
: handle_(handle),
callback_(callback),
priority_(priority),
- ignore_limits_(ignore_limits),
+ respect_limits_(respect_limits),
flags_(flags),
net_log_(net_log) {
- if (ignore_limits_)
+ if (respect_limits_ == ClientSocketPool::RespectLimits::DISABLED)
DCHECK_EQ(priority_, MAXIMUM_PRIORITY);
}
@@ -218,6 +222,9 @@ ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair(
result(result_in) {
}
+ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair(
+ const CallbackResultPair& other) = default;
+
ClientSocketPoolBaseHelper::CallbackResultPair::~CallbackResultPair() {}
bool ClientSocketPoolBaseHelper::IsStalled() const {
@@ -378,7 +385,7 @@ int ClientSocketPoolBaseHelper::RequestSocketInternal(
// Can we make another active socket now?
if (!group->HasAvailableSocketSlot(max_sockets_per_group_) &&
- !request.ignore_limits()) {
+ request.respect_limits() == ClientSocketPool::RespectLimits::ENABLED) {
// TODO(willchan): Consider whether or not we need to close a socket in a
// higher layered group. I don't think this makes sense since we would just
// reuse that socket then if we needed one and wouldn't make it down to this
@@ -388,7 +395,8 @@ int ClientSocketPoolBaseHelper::RequestSocketInternal(
return ERR_IO_PENDING;
}
- if (ReachedMaxSocketsLimit() && !request.ignore_limits()) {
+ if (ReachedMaxSocketsLimit() &&
+ request.respect_limits() == ClientSocketPool::RespectLimits::ENABLED) {
// NOTE(mmenke): Wonder if we really need different code for each case
// here. Only reason for them now seems to be preconnects.
if (idle_socket_count() > 0) {
@@ -1302,8 +1310,8 @@ void ClientSocketPoolBaseHelper::Group::InsertPendingRequest(
scoped_ptr<const Request> request) {
// This value must be cached before we release |request|.
RequestPriority priority = request->priority();
- if (request->ignore_limits()) {
- // Put requests with ignore_limits == true (which should have
+ if (request->respect_limits() == ClientSocketPool::RespectLimits::DISABLED) {
+ // Put requests with RespectLimits::DISABLED (which should have
// priority == MAXIMUM_PRIORITY) ahead of other requests with
// MAXIMUM_PRIORITY.
DCHECK_EQ(priority, MAXIMUM_PRIORITY);
diff --git a/chromium/net/socket/client_socket_pool_base.h b/chromium/net/socket/client_socket_pool_base.h
index cd13ce0dbdd..1e57adb65b1 100644
--- a/chromium/net/socket/client_socket_pool_base.h
+++ b/chromium/net/socket/client_socket_pool_base.h
@@ -81,6 +81,7 @@ class NET_EXPORT_PRIVATE ConnectJob {
ConnectJob(const std::string& group_name,
base::TimeDelta timeout_duration,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
Delegate* delegate,
const BoundNetLog& net_log);
virtual ~ConnectJob();
@@ -117,6 +118,9 @@ class NET_EXPORT_PRIVATE ConnectJob {
protected:
RequestPriority priority() const { return priority_; }
+ ClientSocketPool::RespectLimits respect_limits() const {
+ return respect_limits_;
+ }
void SetSocket(scoped_ptr<StreamSocket> socket);
StreamSocket* socket() { return socket_.get(); }
void NotifyDelegateOfCompletion(int rv);
@@ -138,6 +142,7 @@ class NET_EXPORT_PRIVATE ConnectJob {
const base::TimeDelta timeout_duration_;
// TODO(akalin): Support reprioritization.
const RequestPriority priority_;
+ const ClientSocketPool::RespectLimits respect_limits_;
// Timer to abort jobs that take too long.
base::OneShotTimer timer_;
Delegate* delegate_;
@@ -173,7 +178,7 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
Request(ClientSocketHandle* handle,
const CompletionCallback& callback,
RequestPriority priority,
- bool ignore_limits,
+ ClientSocketPool::RespectLimits respect_limits,
Flags flags,
const BoundNetLog& net_log);
@@ -182,7 +187,9 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
ClientSocketHandle* handle() const { return handle_; }
const CompletionCallback& callback() const { return callback_; }
RequestPriority priority() const { return priority_; }
- bool ignore_limits() const { return ignore_limits_; }
+ ClientSocketPool::RespectLimits respect_limits() const {
+ return respect_limits_;
+ }
Flags flags() const { return flags_; }
const BoundNetLog& net_log() const { return net_log_; }
@@ -200,7 +207,7 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
const CompletionCallback callback_;
// TODO(akalin): Support reprioritization.
const RequestPriority priority_;
- const bool ignore_limits_;
+ const ClientSocketPool::RespectLimits respect_limits_;
const Flags flags_;
const BoundNetLog net_log_;
@@ -406,8 +413,8 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
// Returns the priority of the top of the pending request queue
// (which may be less than the maximum priority over the entire
- // queue, due to how we prioritize requests with |ignore_limits|
- // set over others).
+ // queue, due to how we prioritize requests with |respect_limits|
+ // DISABLED over others).
RequestPriority TopPendingPriority() const {
// NOTE: FirstMax().value()->priority() is not the same as
// FirstMax().priority()!
@@ -507,6 +514,7 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
struct CallbackResultPair {
CallbackResultPair();
CallbackResultPair(const CompletionCallback& callback_in, int result_in);
+ CallbackResultPair(const CallbackResultPair& other);
~CallbackResultPair();
CompletionCallback callback;
@@ -680,12 +688,16 @@ class ClientSocketPoolBase {
Request(ClientSocketHandle* handle,
const CompletionCallback& callback,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
internal::ClientSocketPoolBaseHelper::Flags flags,
- bool ignore_limits,
const scoped_refptr<SocketParams>& params,
const BoundNetLog& net_log)
- : internal::ClientSocketPoolBaseHelper::Request(
- handle, callback, priority, ignore_limits, flags, net_log),
+ : internal::ClientSocketPoolBaseHelper::Request(handle,
+ callback,
+ priority,
+ respect_limits,
+ flags,
+ net_log),
params_(params) {}
const scoped_refptr<SocketParams>& params() const { return params_; }
@@ -749,14 +761,13 @@ class ClientSocketPoolBase {
int RequestSocket(const std::string& group_name,
const scoped_refptr<SocketParams>& params,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) {
- scoped_ptr<const Request> request(
- new Request(handle, callback, priority,
- internal::ClientSocketPoolBaseHelper::NORMAL,
- params->ignore_limits(),
- params, net_log));
+ scoped_ptr<const Request> request(new Request(
+ handle, callback, priority, respect_limits,
+ internal::ClientSocketPoolBaseHelper::NORMAL, params, net_log));
return helper_.RequestSocket(group_name, std::move(request));
}
@@ -767,9 +778,10 @@ class ClientSocketPoolBase {
const scoped_refptr<SocketParams>& params,
int num_sockets,
const BoundNetLog& net_log) {
- const Request request(NULL /* no handle */, CompletionCallback(), IDLE,
+ const Request request(nullptr /* no handle */, CompletionCallback(), IDLE,
+ ClientSocketPool::RespectLimits::ENABLED,
internal::ClientSocketPoolBaseHelper::NO_IDLE_SOCKETS,
- params->ignore_limits(), params, net_log);
+ params, net_log);
helper_.RequestSockets(group_name, request, num_sockets);
}
diff --git a/chromium/net/socket/client_socket_pool_base_unittest.cc b/chromium/net/socket/client_socket_pool_base_unittest.cc
index a467f49e601..308d4af9248 100644
--- a/chromium/net/socket/client_socket_pool_base_unittest.cc
+++ b/chromium/net/socket/client_socket_pool_base_unittest.cc
@@ -107,16 +107,11 @@ void TestLoadTimingInfoNotConnected(const ClientSocketHandle& handle) {
class TestSocketParams : public base::RefCounted<TestSocketParams> {
public:
- explicit TestSocketParams(bool ignore_limits)
- : ignore_limits_(ignore_limits) {}
-
- bool ignore_limits() { return ignore_limits_; }
+ explicit TestSocketParams() {}
private:
friend class base::RefCounted<TestSocketParams>;
~TestSocketParams() {}
-
- const bool ignore_limits_;
};
typedef ClientSocketPoolBase<TestSocketParams> TestClientSocketPoolBase;
@@ -180,7 +175,6 @@ class MockClientSocket : public StreamSocket {
void SetSubresourceSpeculation() override {}
void SetOmniboxSpeculation() override {}
bool WasEverUsed() const override { return was_used_to_convey_data_; }
- bool UsingTCPFastOpen() const override { return false; }
bool WasNpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
@@ -278,14 +272,17 @@ class TestConnectJob : public ConnectJob {
ConnectJob::Delegate* delegate,
MockClientSocketFactory* client_socket_factory,
NetLog* net_log)
- : ConnectJob(group_name, timeout_duration, request.priority(), delegate,
+ : ConnectJob(group_name,
+ timeout_duration,
+ request.priority(),
+ request.respect_limits(),
+ delegate,
BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
job_type_(job_type),
client_socket_factory_(client_socket_factory),
load_state_(LOAD_STATE_IDLE),
store_additional_error_state_(false),
- weak_factory_(this) {
- }
+ weak_factory_(this) {}
void Signal() {
DoConnect(waiting_success_, true /* async */, false /* recoverable */);
@@ -505,13 +502,14 @@ class TestClientSocketPool : public ClientSocketPool {
int RequestSocket(const std::string& group_name,
const void* params,
RequestPriority priority,
+ RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) override {
const scoped_refptr<TestSocketParams>* casted_socket_params =
static_cast<const scoped_refptr<TestSocketParams>*>(params);
return base_.RequestSocket(group_name, *casted_socket_params, priority,
- handle, callback, net_log);
+ respect_limits, handle, callback, net_log);
}
void RequestSockets(const std::string& group_name,
@@ -663,8 +661,7 @@ class TestConnectJobDelegate : public ConnectJob::Delegate {
class ClientSocketPoolBaseTest : public testing::Test {
protected:
- ClientSocketPoolBaseTest()
- : params_(new TestSocketParams(false /* ignore_limits */)) {
+ ClientSocketPoolBaseTest() : params_(new TestSocketParams()) {
connect_backup_jobs_enabled_ =
internal::ClientSocketPoolBaseHelper::connect_backup_jobs_enabled();
internal::ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(true);
@@ -701,16 +698,17 @@ class ClientSocketPoolBaseTest : public testing::Test {
connect_job_factory_));
}
- int StartRequestWithParams(
+ int StartRequestWithIgnoreLimits(
const std::string& group_name,
RequestPriority priority,
- const scoped_refptr<TestSocketParams>& params) {
- return test_base_.StartRequestUsingPool(
- pool_.get(), group_name, priority, params);
+ ClientSocketPool::RespectLimits respect_limits) {
+ return test_base_.StartRequestUsingPool(pool_.get(), group_name, priority,
+ respect_limits, params_);
}
int StartRequest(const std::string& group_name, RequestPriority priority) {
- return StartRequestWithParams(group_name, priority, params_);
+ return StartRequestWithIgnoreLimits(
+ group_name, priority, ClientSocketPool::RespectLimits::ENABLED);
}
int GetOrderOfRequest(size_t index) const {
@@ -749,8 +747,8 @@ TEST_F(ClientSocketPoolBaseTest, ConnectJob_NoTimeoutOnSynchronousCompletion) {
ClientSocketHandle ignored;
TestClientSocketPoolBase::Request request(
&ignored, CompletionCallback(), DEFAULT_PRIORITY,
- internal::ClientSocketPoolBaseHelper::NORMAL,
- false, params_, BoundNetLog());
+ ClientSocketPool::RespectLimits::ENABLED,
+ internal::ClientSocketPoolBaseHelper::NORMAL, params_, BoundNetLog());
scoped_ptr<TestConnectJob> job(
new TestConnectJob(TestConnectJob::kMockJob,
"a",
@@ -769,8 +767,8 @@ TEST_F(ClientSocketPoolBaseTest, ConnectJob_TimedOut) {
TestClientSocketPoolBase::Request request(
&ignored, CompletionCallback(), DEFAULT_PRIORITY,
- internal::ClientSocketPoolBaseHelper::NORMAL,
- false, params_, BoundNetLog());
+ ClientSocketPool::RespectLimits::ENABLED,
+ internal::ClientSocketPoolBaseHelper::NORMAL, params_, BoundNetLog());
// Deleted by TestConnectJobDelegate.
TestConnectJob* job =
new TestConnectJob(TestConnectJob::kMockPendingJob,
@@ -812,13 +810,9 @@ TEST_F(ClientSocketPoolBaseTest, BasicSynchronous) {
BoundTestNetLog log;
TestLoadTimingInfoNotConnected(handle);
- EXPECT_EQ(OK,
- handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- log.bound()));
+ EXPECT_EQ(OK, handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), log.bound()));
EXPECT_TRUE(handle.is_initialized());
EXPECT_TRUE(handle.socket());
TestLoadTimingInfoConnectedNotReused(handle);
@@ -856,12 +850,9 @@ TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) {
info.headers = new HttpResponseHeaders(std::string());
handle.set_ssl_error_response_info(info);
EXPECT_EQ(ERR_CONNECTION_FAILED,
- handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- log.bound()));
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), log.bound()));
EXPECT_FALSE(handle.socket());
EXPECT_FALSE(handle.is_ssl_error());
EXPECT_TRUE(handle.ssl_error_response_info().headers.get() == NULL);
@@ -1096,23 +1087,17 @@ TEST_F(ClientSocketPoolBaseTest, StallAndThenCancelAndTriggerAvailableSocket) {
ClientSocketHandle handle;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
ClientSocketHandle handles[4];
for (size_t i = 0; i < arraysize(handles); ++i) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- handles[i].Init("b",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ handles[i].Init("b", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
}
// One will be stalled, cancel all the handles now.
@@ -1130,23 +1115,20 @@ TEST_F(ClientSocketPoolBaseTest, CancelStalledSocketAtSocketLimit) {
ClientSocketHandle handles[kDefaultMaxSockets];
TestCompletionCallback callbacks[kDefaultMaxSockets];
for (int i = 0; i < kDefaultMaxSockets; ++i) {
- EXPECT_EQ(OK, handles[i].Init(base::IntToString(i),
- params_,
- DEFAULT_PRIORITY,
- callbacks[i].callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(OK, handles[i].Init(
+ base::IntToString(i), params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callbacks[i].callback(), pool_.get(), BoundNetLog()));
}
// Force a stalled group.
ClientSocketHandle stalled_handle;
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(
+ ERR_IO_PENDING,
+ stalled_handle.Init("foo", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
// Cancel the stalled request.
stalled_handle.Reset();
@@ -1169,24 +1151,22 @@ TEST_F(ClientSocketPoolBaseTest, CancelPendingSocketAtSocketLimit) {
ClientSocketHandle handles[kDefaultMaxSockets];
for (int i = 0; i < kDefaultMaxSockets; ++i) {
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, handles[i].Init(base::IntToString(i),
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(
+ ERR_IO_PENDING,
+ handles[i].Init(base::IntToString(i), params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
}
// Force a stalled group.
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
ClientSocketHandle stalled_handle;
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(
+ ERR_IO_PENDING,
+ stalled_handle.Init("foo", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
// Since it is stalled, it should have no connect jobs.
EXPECT_EQ(0, pool_->NumConnectJobsInGroup("foo"));
@@ -1225,13 +1205,11 @@ TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) {
ClientSocketHandle handles[kDefaultMaxSockets];
for (int i = 0; i < kDefaultMaxSockets; ++i) {
TestCompletionCallback callback;
- EXPECT_EQ(OK, handles[i].Init(base::StringPrintf(
- "Take 2: %d", i),
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(
+ OK, handles[i].Init(base::StringPrintf("Take 2: %d", i), params_,
+ DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
}
EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
@@ -1239,12 +1217,11 @@ TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) {
EXPECT_FALSE(pool_->IsStalled());
// Now we will hit the socket limit.
- EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(
+ ERR_IO_PENDING,
+ stalled_handle.Init("foo", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_TRUE(pool_->IsStalled());
// Dropping out of scope will close all handles and return them to idle.
@@ -1267,12 +1244,9 @@ TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketAtSocketLimitDeleteGroup) {
for (int i = 0; i < kDefaultMaxSockets; ++i) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(OK, handle.Init(base::IntToString(i),
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(OK, handle.Init(base::IntToString(i), params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
}
// Flush all the DoReleaseSocket tasks.
@@ -1287,12 +1261,9 @@ TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketAtSocketLimitDeleteGroup) {
// "0" is special here, since it should be the first entry in the sorted map,
// which is the one which we would close an idle socket for. We shouldn't
// close an idle socket though, since we should reuse the idle socket.
- EXPECT_EQ(OK, handle.Init("0",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(OK, handle.Init("0", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
EXPECT_EQ(kDefaultMaxSockets - 1, pool_->IdleSocketCount());
@@ -1361,12 +1332,10 @@ TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) {
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
handle.Reset();
}
@@ -1377,23 +1346,18 @@ TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
handle.Reset();
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(OK, callback2.WaitForResult());
EXPECT_FALSE(callback.have_result());
@@ -1457,11 +1421,11 @@ void RequestSocketOnComplete(ClientSocketHandle* handle,
handle->socket()->Disconnect();
handle->Reset();
- scoped_refptr<TestSocketParams> params(
- new TestSocketParams(false /* ignore_limits */));
+ scoped_refptr<TestSocketParams> params(new TestSocketParams());
TestCompletionCallback callback;
- int rv =
- handle->Init("a", params, LOWEST, nested_callback, pool, BoundNetLog());
+ int rv = handle->Init("a", params, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ nested_callback, pool, BoundNetLog());
if (rv != ERR_IO_PENDING) {
DCHECK_EQ(TestConnectJob::kMockJob, next_job_type);
nested_callback.Run(rv);
@@ -1480,7 +1444,7 @@ TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) {
ClientSocketHandle handle;
TestCompletionCallback second_result_callback;
int rv = handle.Init(
- "a", params_, DEFAULT_PRIORITY,
+ "a", params_, DEFAULT_PRIORITY, ClientSocketPool::RespectLimits::ENABLED,
base::Bind(&RequestSocketOnComplete, &handle, pool_.get(),
connect_job_factory_, TestConnectJob::kMockPendingJob,
second_result_callback.callback()),
@@ -1500,7 +1464,7 @@ TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) {
ClientSocketHandle handle;
TestCompletionCallback second_result_callback;
int rv = handle.Init(
- "a", params_, DEFAULT_PRIORITY,
+ "a", params_, DEFAULT_PRIORITY, ClientSocketPool::RespectLimits::ENABLED,
base::Bind(&RequestSocketOnComplete, &handle, pool_.get(),
connect_job_factory_, TestConnectJob::kMockPendingJob,
second_result_callback.callback()),
@@ -1567,23 +1531,17 @@ TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestThenRequestSocket) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog());
+ int rv = handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Cancel the active request.
handle.Reset();
- rv = handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
@@ -1636,12 +1594,9 @@ TEST_F(ClientSocketPoolBaseTest, BasicAsynchronous) {
ClientSocketHandle handle;
TestCompletionCallback callback;
BoundTestNetLog log;
- int rv = handle.Init("a",
- params_,
- LOWEST,
- callback.callback(),
- pool_.get(),
- log.bound());
+ int rv = handle.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
TestLoadTimingInfoNotConnected(handle);
@@ -1683,12 +1638,10 @@ TEST_F(ClientSocketPoolBaseTest,
HttpResponseInfo info;
info.headers = new HttpResponseHeaders(std::string());
handle.set_ssl_error_response_info(info);
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- log.bound()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), log.bound()));
EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult());
EXPECT_FALSE(handle.is_ssl_error());
@@ -1735,20 +1688,14 @@ TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) {
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
BoundTestNetLog log2;
EXPECT_EQ(ERR_IO_PENDING,
- handle2.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog()));
handle.Reset();
@@ -1795,11 +1742,9 @@ TEST_F(ClientSocketPoolBaseTest, ReleaseSockets) {
std::vector<TestSocketRequest*> request_order;
size_t completion_count; // unused
TestSocketRequest req1(&request_order, &completion_count);
- int rv = req1.handle()->Init("a",
- params_,
- DEFAULT_PRIORITY,
- req1.callback(), pool_.get(),
- BoundNetLog());
+ int rv = req1.handle()->Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ req1.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, req1.WaitForResult());
@@ -1808,20 +1753,14 @@ TEST_F(ClientSocketPoolBaseTest, ReleaseSockets) {
connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
TestSocketRequest req2(&request_order, &completion_count);
- rv = req2.handle()->Init("a",
- params_,
- DEFAULT_PRIORITY,
- req2.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = req2.handle()->Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ req2.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
TestSocketRequest req3(&request_order, &completion_count);
- rv = req3.handle()->Init("a",
- params_,
- DEFAULT_PRIORITY,
- req3.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = req3.handle()->Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ req3.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Both Requests 2 and 3 are pending. We release socket 1 which should
@@ -1855,33 +1794,24 @@ TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) {
std::vector<TestSocketRequest*> request_order;
size_t completion_count; // unused
TestSocketRequest req1(&request_order, &completion_count);
- int rv = req1.handle()->Init("a",
- params_,
- DEFAULT_PRIORITY,
- req1.callback(),
- pool_.get(),
- BoundNetLog());
+ int rv = req1.handle()->Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ req1.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
TestSocketRequest req2(&request_order, &completion_count);
- rv = req2.handle()->Init("a",
- params_,
- DEFAULT_PRIORITY,
- req2.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = req2.handle()->Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ req2.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// The pending job is sync.
connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
TestSocketRequest req3(&request_order, &completion_count);
- rv = req3.handle()->Init("a",
- params_,
- DEFAULT_PRIORITY,
- req3.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = req3.handle()->Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ req3.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult());
@@ -1901,12 +1831,9 @@ TEST_F(ClientSocketPoolBaseTest, LoadStateOneRequest) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog());
+ int rv = handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState());
@@ -1925,15 +1852,17 @@ TEST_F(ClientSocketPoolBaseTest, LoadStateTwoRequests) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a", params_, DEFAULT_PRIORITY, callback.callback(),
- pool_.get(), BoundNetLog());
+ int rv = handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
client_socket_factory_.SetJobLoadState(0, LOAD_STATE_RESOLVING_HOST);
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- rv = handle2.Init("a", params_, DEFAULT_PRIORITY, callback2.callback(),
- pool_.get(), BoundNetLog());
+ rv = handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
client_socket_factory_.SetJobLoadState(1, LOAD_STATE_RESOLVING_HOST);
@@ -1956,14 +1885,16 @@ TEST_F(ClientSocketPoolBaseTest, LoadStateTwoRequestsChangeSecondRequestState) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a", params_, DEFAULT_PRIORITY, callback.callback(),
- pool_.get(), BoundNetLog());
+ int rv = handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- rv = handle2.Init("a", params_, DEFAULT_PRIORITY, callback2.callback(),
- pool_.get(), BoundNetLog());
+ rv = handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
client_socket_factory_.SetJobLoadState(1, LOAD_STATE_RESOLVING_HOST);
@@ -1984,12 +1915,9 @@ TEST_F(ClientSocketPoolBaseTest, LoadStateGroupLimit) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a",
- params_,
- MEDIUM,
- callback.callback(),
- pool_.get(),
- BoundNetLog());
+ int rv = handle.Init("a", params_, MEDIUM,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState());
@@ -1997,12 +1925,9 @@ TEST_F(ClientSocketPoolBaseTest, LoadStateGroupLimit) {
// The first request should now be stalled at the socket group limit.
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- rv = handle2.Init("a",
- params_,
- HIGHEST,
- callback2.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = handle2.Init("a", params_, HIGHEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET, handle.GetLoadState());
EXPECT_EQ(LOAD_STATE_CONNECTING, handle2.GetLoadState());
@@ -2032,35 +1957,26 @@ TEST_F(ClientSocketPoolBaseTest, LoadStatePoolLimit) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog());
+ int rv = handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Request for socket from another pool.
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- rv = handle2.Init("b",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = handle2.Init("b", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Request another socket from the first pool. Request should stall at the
// socket pool limit.
ClientSocketHandle handle3;
TestCompletionCallback callback3;
- rv = handle3.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = handle3.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// The third handle should remain stalled as the other sockets in its group
@@ -2091,8 +2007,9 @@ TEST_F(ClientSocketPoolBaseTest, Recoverable) {
ClientSocketHandle handle;
TestCompletionCallback callback;
EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED,
- handle.Init("a", params_, DEFAULT_PRIORITY, callback.callback(),
- pool_.get(), BoundNetLog()));
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_TRUE(handle.is_initialized());
EXPECT_TRUE(handle.socket());
}
@@ -2105,12 +2022,9 @@ TEST_F(ClientSocketPoolBaseTest, AsyncRecoverable) {
ClientSocketHandle handle;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, callback.WaitForResult());
EXPECT_TRUE(handle.is_initialized());
@@ -2125,12 +2039,9 @@ TEST_F(ClientSocketPoolBaseTest, AdditionalErrorStateSynchronous) {
ClientSocketHandle handle;
TestCompletionCallback callback;
EXPECT_EQ(ERR_CONNECTION_FAILED,
- handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
EXPECT_TRUE(handle.is_ssl_error());
@@ -2145,12 +2056,9 @@ TEST_F(ClientSocketPoolBaseTest, AdditionalErrorStateAsynchronous) {
ClientSocketHandle handle;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult());
EXPECT_FALSE(handle.is_initialized());
@@ -2173,12 +2081,9 @@ TEST_F(ClientSocketPoolBaseTest, DisableCleanupTimerReuse) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a",
- params_,
- LOWEST,
- callback.callback(),
- pool_.get(),
- BoundNetLog());
+ int rv = handle.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
ASSERT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
ASSERT_EQ(OK, callback.WaitForResult());
@@ -2194,12 +2099,9 @@ TEST_F(ClientSocketPoolBaseTest, DisableCleanupTimerReuse) {
// Request a new socket. This should reuse the old socket and complete
// synchronously.
BoundTestNetLog log;
- rv = handle.Init("a",
- params_,
- LOWEST,
- CompletionCallback(),
- pool_.get(),
- log.bound());
+ rv = handle.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ CompletionCallback(), pool_.get(), log.bound());
ASSERT_EQ(OK, rv);
EXPECT_TRUE(handle.is_reused());
TestLoadTimingInfoConnectedReused(handle);
@@ -2236,23 +2138,17 @@ TEST_F(ClientSocketPoolBaseTest, MAYBE_DisableCleanupTimerNoReuse) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a",
- params_,
- LOWEST,
- callback.callback(),
- pool_.get(),
- BoundNetLog());
+ int rv = handle.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
ASSERT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- rv = handle2.Init("a",
- params_,
- LOWEST,
- callback2.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = handle2.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog());
ASSERT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle2));
@@ -2281,12 +2177,9 @@ TEST_F(ClientSocketPoolBaseTest, MAYBE_DisableCleanupTimerNoReuse) {
// A new socket will be created rather than reusing the idle one.
BoundTestNetLog log;
TestCompletionCallback callback3;
- rv = handle.Init("a",
- params_,
- LOWEST,
- callback3.callback(),
- pool_.get(),
- log.bound());
+ rv = handle.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback3.callback(), pool_.get(), log.bound());
ASSERT_EQ(ERR_IO_PENDING, rv);
ASSERT_EQ(OK, callback3.WaitForResult());
EXPECT_FALSE(handle.is_reused());
@@ -2314,23 +2207,17 @@ TEST_F(ClientSocketPoolBaseTest, CleanupTimedOutIdleSockets) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a",
- params_,
- LOWEST,
- callback.callback(),
- pool_.get(),
- BoundNetLog());
+ int rv = handle.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- rv = handle2.Init("a",
- params_,
- LOWEST,
- callback2.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = handle2.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle2));
@@ -2359,12 +2246,9 @@ TEST_F(ClientSocketPoolBaseTest, CleanupTimedOutIdleSockets) {
pool_->CleanupTimedOutIdleSockets();
BoundTestNetLog log;
- rv = handle.Init("a",
- params_,
- LOWEST,
- callback.callback(),
- pool_.get(),
- log.bound());
+ rv = handle.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), log.bound());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(handle.is_reused());
@@ -2388,42 +2272,30 @@ TEST_F(ClientSocketPoolBaseTest, MultipleReleasingDisconnectedSockets) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init("a",
- params_,
- LOWEST,
- callback.callback(),
- pool_.get(),
- BoundNetLog());
+ int rv = handle.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(OK, rv);
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- rv = handle2.Init("a",
- params_,
- LOWEST,
- callback2.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = handle2.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(OK, rv);
ClientSocketHandle handle3;
TestCompletionCallback callback3;
- rv = handle3.Init("a",
- params_,
- LOWEST,
- callback3.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = handle3.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback3.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ClientSocketHandle handle4;
TestCompletionCallback callback4;
- rv = handle4.Init("a",
- params_,
- LOWEST,
- callback4.callback(),
- pool_.get(),
- BoundNetLog());
+ rv = handle4.Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback4.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Release two disconnected sockets.
@@ -2458,37 +2330,29 @@ TEST_F(ClientSocketPoolBaseTest, SocketLimitReleasingSockets) {
TestCompletionCallback callback_b[4];
for (int i = 0; i < 2; ++i) {
- EXPECT_EQ(OK, handle_a[i].Init("a",
- params_,
- LOWEST,
- callback_a[i].callback(),
- pool_.get(),
+ EXPECT_EQ(OK, handle_a[i].Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback_a[i].callback(), pool_.get(),
BoundNetLog()));
- EXPECT_EQ(OK, handle_b[i].Init("b",
- params_,
- LOWEST,
- callback_b[i].callback(),
- pool_.get(),
+ EXPECT_EQ(OK, handle_b[i].Init("b", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback_b[i].callback(), pool_.get(),
BoundNetLog()));
}
// Make 4 pending requests, 2 per group.
for (int i = 2; i < 4; ++i) {
- EXPECT_EQ(ERR_IO_PENDING,
- handle_a[i].Init("a",
- params_,
- LOWEST,
- callback_a[i].callback(),
- pool_.get(),
- BoundNetLog()));
- EXPECT_EQ(ERR_IO_PENDING,
- handle_b[i].Init("b",
- params_,
- LOWEST,
- callback_b[i].callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(
+ ERR_IO_PENDING,
+ handle_a[i].Init("a", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback_a[i].callback(), pool_.get(), BoundNetLog()));
+ EXPECT_EQ(
+ ERR_IO_PENDING,
+ handle_b[i].Init("b", params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback_b[i].callback(), pool_.get(), BoundNetLog()));
}
// Release b's socket first. The order is important, because in
@@ -2571,10 +2435,10 @@ class TestReleasingSocketRequest : public TestCompletionCallbackBase {
if (reset_releasing_handle_)
handle_.Reset();
- scoped_refptr<TestSocketParams> con_params(
- new TestSocketParams(false /* ignore_limits */));
+ scoped_refptr<TestSocketParams> con_params(new TestSocketParams());
EXPECT_EQ(expected_result_,
handle2_.Init("a", con_params, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
callback2_.callback(), pool_, BoundNetLog()));
}
@@ -2602,8 +2466,9 @@ TEST_F(ClientSocketPoolBaseTest, AdditionalErrorSocketsDontUseSlot) {
TestConnectJob::kMockPendingAdditionalErrorStateJob);
TestReleasingSocketRequest req(pool_.get(), OK, false);
EXPECT_EQ(ERR_IO_PENDING,
- req.handle()->Init("a", params_, DEFAULT_PRIORITY, req.callback(),
- pool_.get(), BoundNetLog()));
+ req.handle()->Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ req.callback(), pool_.get(), BoundNetLog()));
// The next job should complete synchronously
connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
@@ -2628,12 +2493,10 @@ TEST_F(ClientSocketPoolBaseTest, CallbackThatReleasesPool) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
pool_->FlushWithError(ERR_NETWORK_CHANGED);
@@ -2647,12 +2510,10 @@ TEST_F(ClientSocketPoolBaseTest, DoNotReuseSocketAfterFlush) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(OK, callback.WaitForResult());
EXPECT_EQ(ClientSocketHandle::UNUSED, handle.reuse_type());
@@ -2661,12 +2522,10 @@ TEST_F(ClientSocketPoolBaseTest, DoNotReuseSocketAfterFlush) {
handle.Reset();
base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(OK, callback.WaitForResult());
EXPECT_EQ(ClientSocketHandle::UNUSED, handle.reuse_type());
}
@@ -2696,12 +2555,9 @@ class ConnectWithinCallback : public TestCompletionCallbackBase {
void OnComplete(int result) {
SetResult(result);
EXPECT_EQ(ERR_IO_PENDING,
- handle_.Init(group_name_,
- params_,
- DEFAULT_PRIORITY,
- nested_callback_.callback(),
- pool_,
- BoundNetLog()));
+ handle_.Init(group_name_, params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ nested_callback_.callback(), pool_, BoundNetLog()));
}
const std::string group_name_;
@@ -2722,12 +2578,10 @@ TEST_F(ClientSocketPoolBaseTest, AbortAllRequestsOnFlush) {
ClientSocketHandle handle;
ConnectWithinCallback callback("a", params_, pool_.get());
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
// Second job will be started during the first callback, and will
// asynchronously complete with OK.
@@ -2749,24 +2603,20 @@ TEST_F(ClientSocketPoolBaseTest, BackupSocketCancelAtMaxSockets) {
connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("bar",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("bar", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
// Start (MaxSockets - 1) connected sockets to reach max sockets.
connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
ClientSocketHandle handles[kDefaultMaxSockets];
for (int i = 1; i < kDefaultMaxSockets; ++i) {
TestCompletionCallback callback;
- EXPECT_EQ(OK, handles[i].Init("bar",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(OK,
+ handles[i].Init("bar", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
}
base::MessageLoop::current()->RunUntilIdle();
@@ -2791,12 +2641,10 @@ TEST_F(ClientSocketPoolBaseTest, CancelBackupSocketAfterCancelingAllRequests) {
connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("bar",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("bar", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
ASSERT_TRUE(pool_->HasGroup("bar"));
EXPECT_EQ(1, pool_->NumConnectJobsInGroup("bar"));
EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("bar"));
@@ -2821,21 +2669,17 @@ TEST_F(ClientSocketPoolBaseTest, CancelBackupSocketAfterFinishingAllRequests) {
connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("bar",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("bar", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- EXPECT_EQ(ERR_IO_PENDING, handle2.Init("bar",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle2.Init("bar", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog()));
ASSERT_TRUE(pool_->HasGroup("bar"));
EXPECT_EQ(2, pool_->NumConnectJobsInGroup("bar"));
@@ -2860,12 +2704,9 @@ TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingWaitingForConnect) {
ClientSocketHandle handle1;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(OK, callback.WaitForResult());
// No idle sockets, no pending jobs.
@@ -2876,12 +2717,9 @@ TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingWaitingForConnect) {
connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
ClientSocketHandle handle2;
EXPECT_EQ(ERR_IO_PENDING,
- handle2.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
// No idle sockets, and one connecting job.
EXPECT_EQ(0, pool_->IdleSocketCount());
EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a"));
@@ -2918,12 +2756,9 @@ TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingAtGroupCapacity) {
ClientSocketHandle handle1;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(OK, callback.WaitForResult());
// No idle sockets, no pending jobs.
@@ -2934,12 +2769,9 @@ TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingAtGroupCapacity) {
connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
ClientSocketHandle handle2;
EXPECT_EQ(ERR_IO_PENDING,
- handle2.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
// No idle sockets, and one connecting job.
EXPECT_EQ(0, pool_->IdleSocketCount());
EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a"));
@@ -2978,12 +2810,9 @@ TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingAtStall) {
ClientSocketHandle handle1;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(OK, callback.WaitForResult());
// No idle sockets, no pending jobs.
@@ -2994,12 +2823,9 @@ TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingAtStall) {
connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
ClientSocketHandle handle2;
EXPECT_EQ(ERR_IO_PENDING,
- handle2.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
// No idle sockets, and one connecting job.
EXPECT_EQ(0, pool_->IdleSocketCount());
EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a"));
@@ -3041,12 +2867,9 @@ TEST_F(ClientSocketPoolBaseTest, SynchronouslyProcessOnePendingRequest) {
ClientSocketHandle handle1;
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING,
- handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a"));
// Make the second request synchronously fail. This should make the Group
@@ -3057,12 +2880,9 @@ TEST_F(ClientSocketPoolBaseTest, SynchronouslyProcessOnePendingRequest) {
// It'll be ERR_IO_PENDING now, but the TestConnectJob will synchronously fail
// when created.
EXPECT_EQ(ERR_IO_PENDING,
- handle2.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog()));
+ handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a"));
@@ -3078,29 +2898,23 @@ TEST_F(ClientSocketPoolBaseTest, PreferUsedSocketToUnusedSocket) {
ClientSocketHandle handle1;
TestCompletionCallback callback1;
- EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- EXPECT_EQ(ERR_IO_PENDING, handle2.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog()));
ClientSocketHandle handle3;
TestCompletionCallback callback3;
- EXPECT_EQ(ERR_IO_PENDING, handle3.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback3.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle3.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback3.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(OK, callback1.WaitForResult());
EXPECT_EQ(OK, callback2.WaitForResult());
@@ -3114,24 +2928,15 @@ TEST_F(ClientSocketPoolBaseTest, PreferUsedSocketToUnusedSocket) {
handle2.Reset();
handle3.Reset();
- EXPECT_EQ(OK, handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
- EXPECT_EQ(OK, handle2.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog()));
- EXPECT_EQ(OK, handle3.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback3.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(OK, handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
+ EXPECT_EQ(OK, handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog()));
+ EXPECT_EQ(OK, handle3.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback3.callback(), pool_.get(), BoundNetLog()));
EXPECT_TRUE(handle1.socket()->WasEverUsed());
EXPECT_TRUE(handle2.socket()->WasEverUsed());
@@ -3151,21 +2956,17 @@ TEST_F(ClientSocketPoolBaseTest, RequestSockets) {
ClientSocketHandle handle1;
TestCompletionCallback callback1;
- EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- EXPECT_EQ(ERR_IO_PENDING, handle2.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(2, pool_->NumConnectJobsInGroup("a"));
EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a"));
@@ -3187,12 +2988,10 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsWhenAlreadyHaveAConnectJob) {
ClientSocketHandle handle1;
TestCompletionCallback callback1;
- EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
ASSERT_TRUE(pool_->HasGroup("a"));
EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a"));
@@ -3207,12 +3006,10 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsWhenAlreadyHaveAConnectJob) {
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- EXPECT_EQ(ERR_IO_PENDING, handle2.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(2, pool_->NumConnectJobsInGroup("a"));
EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a"));
@@ -3235,30 +3032,24 @@ TEST_F(ClientSocketPoolBaseTest,
ClientSocketHandle handle1;
TestCompletionCallback callback1;
- EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- EXPECT_EQ(ERR_IO_PENDING, handle2.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog()));
ClientSocketHandle handle3;
TestCompletionCallback callback3;
- EXPECT_EQ(ERR_IO_PENDING, handle3.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback3.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle3.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback3.callback(), pool_.get(), BoundNetLog()));
ASSERT_TRUE(pool_->HasGroup("a"));
EXPECT_EQ(3, pool_->NumConnectJobsInGroup("a"));
@@ -3335,12 +3126,10 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountIdleSockets) {
ClientSocketHandle handle1;
TestCompletionCallback callback1;
- EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
ASSERT_EQ(OK, callback1.WaitForResult());
handle1.Reset();
@@ -3362,12 +3151,10 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountActiveSockets) {
ClientSocketHandle handle1;
TestCompletionCallback callback1;
- EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
ASSERT_EQ(OK, callback1.WaitForResult());
ASSERT_TRUE(pool_->HasGroup("a"));
@@ -3439,22 +3226,17 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsMultipleTimesDoesNothing) {
ClientSocketHandle handle1;
TestCompletionCallback callback1;
- EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
ASSERT_EQ(OK, callback1.WaitForResult());
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- int rv = handle2.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog());
+ int rv = handle2.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog());
if (rv != OK) {
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback2.WaitForResult());
@@ -3518,12 +3300,10 @@ TEST_F(ClientSocketPoolBaseTest, PreconnectJobsTakenByNormalRequests) {
ClientSocketHandle handle1;
TestCompletionCallback callback1;
- EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a"));
EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a"));
@@ -3553,12 +3333,9 @@ TEST_F(ClientSocketPoolBaseTest, ConnectedPreconnectJobsHaveNoConnectTimes) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(OK, handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(OK, handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
// Make sure the idle socket was used.
EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
@@ -3581,12 +3358,10 @@ TEST_F(ClientSocketPoolBaseTest, PreconnectClosesIdleSocketRemovesGroup) {
// Set up one idle socket in "a".
ClientSocketHandle handle1;
TestCompletionCallback callback1;
- EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle1.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
ASSERT_EQ(OK, callback1.WaitForResult());
handle1.Reset();
@@ -3595,18 +3370,14 @@ TEST_F(ClientSocketPoolBaseTest, PreconnectClosesIdleSocketRemovesGroup) {
// Set up two active sockets in "b".
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- EXPECT_EQ(ERR_IO_PENDING, handle1.Init("b",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
- EXPECT_EQ(ERR_IO_PENDING, handle2.Init("b",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle1.Init("b", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle2.Init("b", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog()));
ASSERT_EQ(OK, callback1.WaitForResult());
ASSERT_EQ(OK, callback2.WaitForResult());
@@ -3688,12 +3459,10 @@ TEST_F(ClientSocketPoolBaseTest, PreconnectWithBackupJob) {
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
// Timer has started, but the backup connect job shouldn't be created yet.
EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a"));
EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a"));
@@ -3727,12 +3496,9 @@ TEST_F(ClientSocketPoolBaseTest, PreconnectWithUnreadData) {
connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob);
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(OK, handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(OK, handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
ASSERT_TRUE(pool_->HasGroup("a"));
EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
@@ -3764,16 +3530,16 @@ class MockLayeredPool : public HigherLayeredPool {
}
int RequestSocket(TestClientSocketPool* pool) {
- scoped_refptr<TestSocketParams> params(
- new TestSocketParams(false /* ignore_limits */));
+ scoped_refptr<TestSocketParams> params(new TestSocketParams());
return handle_.Init(group_name_, params, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
callback_.callback(), pool, BoundNetLog());
}
int RequestSocketWithoutLimits(TestClientSocketPool* pool) {
- scoped_refptr<TestSocketParams> params(
- new TestSocketParams(true /* ignore_limits */));
+ scoped_refptr<TestSocketParams> params(new TestSocketParams());
return handle_.Init(group_name_, params, MAXIMUM_PRIORITY,
+ ClientSocketPool::RespectLimits::DISABLED,
callback_.callback(), pool, BoundNetLog());
}
@@ -3836,12 +3602,10 @@ TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketsHeldByLayeredPoolWhenNeeded) {
&MockLayeredPool::ReleaseOneConnection));
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(OK, callback.WaitForResult());
}
@@ -3859,12 +3623,9 @@ TEST_F(ClientSocketPoolBaseTest,
// has the maximum number of connections already, it's not stalled).
ClientSocketHandle handle1;
TestCompletionCallback callback1;
- EXPECT_EQ(OK, handle1.Init("group1",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(OK, handle1.Init("group1", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
MockLayeredPool mock_layered_pool(pool_.get(), "group2");
EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get()));
@@ -3873,12 +3634,10 @@ TEST_F(ClientSocketPoolBaseTest,
&MockLayeredPool::ReleaseOneConnection));
ClientSocketHandle handle;
TestCompletionCallback callback2;
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("group2",
- params_,
- DEFAULT_PRIORITY,
- callback2.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("group2", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(OK, callback2.WaitForResult());
}
@@ -3896,12 +3655,9 @@ TEST_F(ClientSocketPoolBaseTest,
ClientSocketHandle handle1;
TestCompletionCallback callback1;
- EXPECT_EQ(OK, handle1.Init("group1",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(OK, handle1.Init("group1", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
MockLayeredPool mock_layered_pool(pool_.get(), "group2");
EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get()));
@@ -3913,12 +3669,10 @@ TEST_F(ClientSocketPoolBaseTest,
// The third request is made when the socket pool is in a stalled state.
ClientSocketHandle handle3;
TestCompletionCallback callback3;
- EXPECT_EQ(ERR_IO_PENDING, handle3.Init("group3",
- params_,
- DEFAULT_PRIORITY,
- callback3.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle3.Init("group3", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback3.callback(), pool_.get(), BoundNetLog()));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(callback3.have_result());
@@ -3929,12 +3683,10 @@ TEST_F(ClientSocketPoolBaseTest,
mock_layered_pool.set_can_release_connection(true);
ClientSocketHandle handle4;
TestCompletionCallback callback4;
- EXPECT_EQ(ERR_IO_PENDING, handle4.Init("group3",
- params_,
- DEFAULT_PRIORITY,
- callback4.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle4.Init("group3", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback4.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(OK, callback3.WaitForResult());
EXPECT_FALSE(callback4.have_result());
@@ -3961,12 +3713,9 @@ TEST_F(ClientSocketPoolBaseTest,
ClientSocketHandle handle1;
TestCompletionCallback callback1;
- EXPECT_EQ(OK, handle1.Init("group1",
- params_,
- DEFAULT_PRIORITY,
- callback1.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(OK, handle1.Init("group1", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), pool_.get(), BoundNetLog()));
MockLayeredPool mock_layered_pool(pool_.get(), "group2");
EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get()));
@@ -3978,12 +3727,10 @@ TEST_F(ClientSocketPoolBaseTest,
// The third request is made when the socket pool is in a stalled state.
ClientSocketHandle handle3;
TestCompletionCallback callback3;
- EXPECT_EQ(ERR_IO_PENDING, handle3.Init("group3",
- params_,
- MEDIUM,
- callback3.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle3.Init("group3", params_, MEDIUM,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback3.callback(), pool_.get(), BoundNetLog()));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(callback3.have_result());
@@ -3993,12 +3740,10 @@ TEST_F(ClientSocketPoolBaseTest,
mock_layered_pool.set_can_release_connection(true);
ClientSocketHandle handle4;
TestCompletionCallback callback4;
- EXPECT_EQ(ERR_IO_PENDING, handle4.Init("group3",
- params_,
- HIGHEST,
- callback4.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle4.Init("group3", params_, HIGHEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback4.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(OK, callback4.WaitForResult());
EXPECT_FALSE(callback3.have_result());
@@ -4024,36 +3769,38 @@ TEST_F(ClientSocketPoolBaseTest,
&MockLayeredPool::ReleaseOneConnection));
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
- params_,
- DEFAULT_PRIORITY,
- callback.callback(),
- pool_.get(),
- BoundNetLog()));
+ EXPECT_EQ(ERR_IO_PENDING,
+ handle.Init("a", params_, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(OK, callback.WaitForResult());
}
// Test that when a socket pool and group are at their limits, a request
-// with |ignore_limits| triggers creation of a new socket, and gets the socket
-// instead of a request with the same priority that was issued earlier, but
-// that does not have |ignore_limits| set.
+// with RespectLimits::DISABLED triggers creation of a new socket, and gets the
+// socket instead of a request with the same priority that was issued earlier,
+// but has RespectLimits::ENABLED.
TEST_F(ClientSocketPoolBaseTest, IgnoreLimits) {
- scoped_refptr<TestSocketParams> params_ignore_limits(
- new TestSocketParams(true /* ignore_limits */));
CreatePool(1, 1);
// Issue a request to reach the socket pool limit.
- EXPECT_EQ(OK, StartRequestWithParams("a", MAXIMUM_PRIORITY, params_));
+ EXPECT_EQ(
+ OK, StartRequestWithIgnoreLimits(
+ "a", MAXIMUM_PRIORITY, ClientSocketPool::RespectLimits::ENABLED));
EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", MAXIMUM_PRIORITY,
- params_));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequestWithIgnoreLimits(
+ "a", MAXIMUM_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED));
EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", MAXIMUM_PRIORITY,
- params_ignore_limits));
+ // Issue a request that ignores the limits, so a new ConnectJob is
+ // created.
+ EXPECT_EQ(ERR_IO_PENDING, StartRequestWithIgnoreLimits(
+ "a", MAXIMUM_PRIORITY,
+ ClientSocketPool::RespectLimits::DISABLED));
ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a"));
EXPECT_EQ(OK, request(2)->WaitForResult());
@@ -4061,28 +3808,32 @@ TEST_F(ClientSocketPoolBaseTest, IgnoreLimits) {
}
// Test that when a socket pool and group are at their limits, a ConnectJob
-// issued for a request with |ignore_limits| set is not cancelled when a request
-// without |ignore_limits| issued to the same group is cancelled.
+// issued for a request with RespectLimits::DISABLED is not cancelled when a
+// request with RespectLimits::ENABLED issued to the same group is cancelled.
TEST_F(ClientSocketPoolBaseTest, IgnoreLimitsCancelOtherJob) {
- scoped_refptr<TestSocketParams> params_ignore_limits(
- new TestSocketParams(true /* ignore_limits */));
CreatePool(1, 1);
// Issue a request to reach the socket pool limit.
- EXPECT_EQ(OK, StartRequestWithParams("a", MAXIMUM_PRIORITY, params_));
+ EXPECT_EQ(
+ OK, StartRequestWithIgnoreLimits(
+ "a", MAXIMUM_PRIORITY, ClientSocketPool::RespectLimits::ENABLED));
EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", MAXIMUM_PRIORITY,
- params_));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequestWithIgnoreLimits(
+ "a", MAXIMUM_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED));
EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", MAXIMUM_PRIORITY,
- params_ignore_limits));
+ // Issue a request with RespectLimits::DISABLED, so a new ConnectJob is
+ // created.
+ EXPECT_EQ(ERR_IO_PENDING, StartRequestWithIgnoreLimits(
+ "a", MAXIMUM_PRIORITY,
+ ClientSocketPool::RespectLimits::DISABLED));
ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a"));
- // Cancel the pending request without ignore_limits set. The ConnectJob
+ // Cancel the pending request with RespectLimits::ENABLED. The ConnectJob
// should not be cancelled.
request(1)->handle()->Reset();
ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a"));
diff --git a/chromium/net/socket/client_socket_pool_manager.cc b/chromium/net/socket/client_socket_pool_manager.cc
index c053b1f4c04..dee8218294a 100644
--- a/chromium/net/socket/client_socket_pool_manager.cc
+++ b/chromium/net/socket/client_socket_pool_manager.cc
@@ -14,6 +14,7 @@
#include "net/http/http_stream_factory.h"
#include "net/proxy/proxy_info.h"
#include "net/socket/client_socket_handle.h"
+#include "net/socket/client_socket_pool.h"
#include "net/socket/socks_client_socket_pool.h"
#include "net/socket/ssl_client_socket_pool.h"
#include "net/socket/transport_client_socket_pool.h"
@@ -148,7 +149,10 @@ int InitSocketPoolHelper(ClientSocketPoolManager::SocketGroupType group_type,
connection_group = prefix + connection_group;
}
- bool ignore_limits = (request_load_flags & LOAD_IGNORE_LIMITS) != 0;
+ ClientSocketPool::RespectLimits respect_limits =
+ ClientSocketPool::RespectLimits::ENABLED;
+ if ((request_load_flags & LOAD_IGNORE_LIMITS) != 0)
+ respect_limits = ClientSocketPool::RespectLimits::DISABLED;
if (!proxy_info.is_direct()) {
ProxyServer proxy_server = proxy_info.proxy_server();
proxy_host_port.reset(new HostPortPair(proxy_server.host_port_pair()));
@@ -156,7 +160,6 @@ int InitSocketPoolHelper(ClientSocketPoolManager::SocketGroupType group_type,
new TransportSocketParams(
*proxy_host_port,
disable_resolver_cache,
- ignore_limits,
resolution_callback,
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
@@ -175,7 +178,6 @@ int InitSocketPoolHelper(ClientSocketPoolManager::SocketGroupType group_type,
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT;
proxy_tcp_params = new TransportSocketParams(*proxy_host_port,
disable_resolver_cache,
- ignore_limits,
resolution_callback,
combine_connect_and_write);
// Set ssl_params, and unset proxy_tcp_params
@@ -229,7 +231,6 @@ int InitSocketPoolHelper(ClientSocketPoolManager::SocketGroupType group_type,
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT;
ssl_tcp_params = new TransportSocketParams(origin_host_port,
disable_resolver_cache,
- ignore_limits,
resolution_callback,
combine_connect_and_write);
}
@@ -250,9 +251,8 @@ int InitSocketPoolHelper(ClientSocketPoolManager::SocketGroupType group_type,
return OK;
}
- return socket_handle->Init(connection_group, ssl_params,
- request_priority, callback, ssl_pool,
- net_log);
+ return socket_handle->Init(connection_group, ssl_params, request_priority,
+ respect_limits, callback, ssl_pool, net_log);
}
// Finally, get the connection started.
@@ -267,8 +267,8 @@ int InitSocketPoolHelper(ClientSocketPoolManager::SocketGroupType group_type,
}
return socket_handle->Init(connection_group, http_proxy_params,
- request_priority, callback,
- pool, net_log);
+ request_priority, respect_limits, callback, pool,
+ net_log);
}
if (proxy_info.is_socks()) {
@@ -280,9 +280,8 @@ int InitSocketPoolHelper(ClientSocketPoolManager::SocketGroupType group_type,
return OK;
}
- return socket_handle->Init(connection_group, socks_params,
- request_priority, callback, pool,
- net_log);
+ return socket_handle->Init(connection_group, socks_params, request_priority,
+ respect_limits, callback, pool, net_log);
}
DCHECK(proxy_info.is_direct());
@@ -290,7 +289,6 @@ int InitSocketPoolHelper(ClientSocketPoolManager::SocketGroupType group_type,
new TransportSocketParams(
origin_host_port,
disable_resolver_cache,
- ignore_limits,
resolution_callback,
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT);
TransportClientSocketPool* pool =
@@ -301,9 +299,8 @@ int InitSocketPoolHelper(ClientSocketPoolManager::SocketGroupType group_type,
return OK;
}
- return socket_handle->Init(connection_group, tcp_params,
- request_priority, callback,
- pool, net_log);
+ return socket_handle->Init(connection_group, tcp_params, request_priority,
+ respect_limits, callback, pool, net_log);
}
} // namespace
diff --git a/chromium/net/socket/client_socket_pool_manager_impl.h b/chromium/net/socket/client_socket_pool_manager_impl.h
index 538e507fe6e..e0662f19037 100644
--- a/chromium/net/socket/client_socket_pool_manager_impl.h
+++ b/chromium/net/socket/client_socket_pool_manager_impl.h
@@ -6,12 +6,13 @@
#define NET_SOCKET_CLIENT_SOCKET_POOL_MANAGER_IMPL_H_
#include <map>
+#include <type_traits>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
-#include "base/template_util.h"
#include "base/threading/non_thread_safe.h"
#include "net/cert/cert_database.h"
#include "net/http/http_network_session.h"
@@ -39,7 +40,7 @@ template <typename Key, typename Value>
class OwnedPoolMap : public std::map<Key, Value> {
public:
OwnedPoolMap() {
- static_assert(base::is_pointer<Value>::value, "value must be a pointer");
+ static_assert(std::is_pointer<Value>::value, "value must be a pointer");
}
~OwnedPoolMap() {
diff --git a/chromium/net/socket/next_proto.cc b/chromium/net/socket/next_proto.cc
index a22418c542e..a3e2e0bd767 100644
--- a/chromium/net/socket/next_proto.cc
+++ b/chromium/net/socket/next_proto.cc
@@ -6,35 +6,6 @@
namespace net {
-NextProtoVector NextProtosDefaults() {
- NextProtoVector next_protos;
- next_protos.push_back(kProtoHTTP2);
- next_protos.push_back(kProtoSPDY31);
- next_protos.push_back(kProtoHTTP11);
- return next_protos;
-}
-
-NextProtoVector NextProtosWithSpdyAndQuic(bool spdy_enabled,
- bool quic_enabled) {
- NextProtoVector next_protos;
- if (quic_enabled)
- next_protos.push_back(kProtoQUIC1SPDY3);
- if (spdy_enabled) {
- next_protos.push_back(kProtoHTTP2);
- next_protos.push_back(kProtoSPDY31);
- }
- next_protos.push_back(kProtoHTTP11);
- return next_protos;
-}
-
-NextProtoVector NextProtosSpdy31() {
- NextProtoVector next_protos;
- next_protos.push_back(kProtoQUIC1SPDY3);
- next_protos.push_back(kProtoSPDY31);
- next_protos.push_back(kProtoHTTP11);
- return next_protos;
-}
-
bool NextProtoIsSPDY(NextProto next_proto) {
return next_proto >= kProtoSPDYMinimumVersion &&
next_proto <= kProtoSPDYMaximumVersion;
diff --git a/chromium/net/socket/next_proto.h b/chromium/net/socket/next_proto.h
index 3938d4424ad..734e0dd85fc 100644
--- a/chromium/net/socket/next_proto.h
+++ b/chromium/net/socket/next_proto.h
@@ -43,16 +43,6 @@ typedef std::vector<NextProto> NextProtoVector;
// Convenience functions to create NextProtoVector.
-// Default values, which are subject to change over time.
-NET_EXPORT NextProtoVector NextProtosDefaults();
-
-// Enable SPDY/3.1 and QUIC, but not HTTP/2.
-NET_EXPORT NextProtoVector NextProtosSpdy31();
-
-// Control SPDY/3.1 and HTTP/2 separately.
-NET_EXPORT NextProtoVector NextProtosWithSpdyAndQuic(bool spdy_enabled,
- bool quic_enabled);
-
// Returns true if |next_proto| is a version of SPDY or HTTP/2.
bool NextProtoIsSPDY(NextProto next_proto);
diff --git a/chromium/net/socket/nss_ssl_util.cc b/chromium/net/socket/nss_ssl_util.cc
index ee587571639..6d0064d0b94 100644
--- a/chromium/net/socket/nss_ssl_util.cc
+++ b/chromium/net/socket/nss_ssl_util.cc
@@ -148,8 +148,9 @@ class NSSSSLInitSingleton {
// we prefer AES-GCM, otherwise ChaCha20. The remainder of the cipher suite
// preference is inheriented from NSS. */
static const uint16_t chacha_ciphers[] = {
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 0,
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0,
};
static const uint16_t aes_gcm_ciphers[] = {
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
diff --git a/chromium/net/socket/sequenced_socket_data_unittest.cc b/chromium/net/socket/sequenced_socket_data_unittest.cc
index e8df5546e74..c27fd615fd4 100644
--- a/chromium/net/socket/sequenced_socket_data_unittest.cc
+++ b/chromium/net/socket/sequenced_socket_data_unittest.cc
@@ -235,7 +235,6 @@ SequencedSocketDataTest::SequencedSocketDataTest()
tcp_params_(new TransportSocketParams(
endpoint_,
false,
- false,
OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)),
socket_pool_(10, 10, &socket_factory_),
@@ -262,7 +261,8 @@ void SequencedSocketDataTest::Initialize(MockRead* reads,
EXPECT_EQ(OK,
connection_.Init(
- endpoint_.ToString(), tcp_params_, LOWEST, CompletionCallback(),
+ endpoint_.ToString(), tcp_params_, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED, CompletionCallback(),
reinterpret_cast<TransportClientSocketPool*>(&socket_pool_),
BoundNetLog()));
sock_ = connection_.socket();
diff --git a/chromium/net/socket/server_socket.cc b/chromium/net/socket/server_socket.cc
index 50722a91f32..f2c2383ab58 100644
--- a/chromium/net/socket/server_socket.cc
+++ b/chromium/net/socket/server_socket.cc
@@ -4,9 +4,9 @@
#include "net/socket/server_socket.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
namespace net {
@@ -19,12 +19,12 @@ ServerSocket::~ServerSocket() {
int ServerSocket::ListenWithAddressAndPort(const std::string& address_string,
uint16_t port,
int backlog) {
- IPAddressNumber address_number;
- if (!ParseIPLiteralToNumber(address_string, &address_number)) {
+ IPAddress ip_address;
+ if (!ip_address.AssignFromIPLiteral(address_string)) {
return ERR_ADDRESS_INVALID;
}
- return Listen(IPEndPoint(address_number, port), backlog);
+ return Listen(IPEndPoint(ip_address, port), backlog);
}
} // namespace net
diff --git a/chromium/net/socket/server_socket.h b/chromium/net/socket/server_socket.h
index 41894338e8a..a0794f16dee 100644
--- a/chromium/net/socket/server_socket.h
+++ b/chromium/net/socket/server_socket.h
@@ -30,8 +30,6 @@ class NET_EXPORT ServerSocket {
// Binds the socket with address and port, and starts listening. It expects
// a valid IPv4 or IPv6 address. Otherwise, it returns ERR_ADDRESS_INVALID.
- // Subclasses may override this function if |address_string| is in a different
- // format, for example, unix domain socket path.
virtual int ListenWithAddressAndPort(const std::string& address_string,
uint16_t port,
int backlog);
diff --git a/chromium/net/socket/socket_net_log_params.cc b/chromium/net/socket/socket_net_log_params.cc
index 37be0a6a34b..347644ac06d 100644
--- a/chromium/net/socket/socket_net_log_params.cc
+++ b/chromium/net/socket/socket_net_log_params.cc
@@ -10,7 +10,6 @@
#include "base/values.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_endpoint.h"
-#include "net/base/net_util.h"
namespace net {
diff --git a/chromium/net/socket/socket_posix.cc b/chromium/net/socket/socket_posix.cc
index 96892891d09..ca8b04f09a4 100644
--- a/chromium/net/socket/socket_posix.cc
+++ b/chromium/net/socket/socket_posix.cc
@@ -13,6 +13,7 @@
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
+#include "base/trace_event/trace_event.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
@@ -348,6 +349,7 @@ void SocketPosix::DetachFromThread() {
}
void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
+ TRACE_EVENT0("net", "SocketPosix::OnFileCanReadWithoutBlocking");
DCHECK(!accept_callback_.is_null() || !read_callback_.is_null());
if (!accept_callback_.is_null()) {
AcceptCompleted();
diff --git a/chromium/net/socket/socket_test_util.cc b/chromium/net/socket/socket_test_util.cc
index 04f5151d4fe..f6b2e098feb 100644
--- a/chromium/net/socket/socket_test_util.cc
+++ b/chromium/net/socket/socket_test_util.cc
@@ -20,6 +20,7 @@
#include "net/base/address_family.h"
#include "net/base/address_list.h"
#include "net/base/auth.h"
+#include "net/base/ip_address.h"
#include "net/base/load_timing_info.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_headers.h"
@@ -123,15 +124,11 @@ void DumpMockReadWrite(const MockReadWrite<type>& r) {
} // namespace
MockConnect::MockConnect() : mode(ASYNC), result(OK) {
- IPAddressNumber ip;
- CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
- peer_addr = IPEndPoint(ip, 0);
+ peer_addr = IPEndPoint(IPAddress(192, 0, 2, 33), 0);
}
MockConnect::MockConnect(IoMode io_mode, int r) : mode(io_mode), result(r) {
- IPAddressNumber ip;
- CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
- peer_addr = IPEndPoint(ip, 0);
+ peer_addr = IPEndPoint(IPAddress(192, 0, 2, 33), 0);
}
MockConnect::MockConnect(IoMode io_mode, int r, IPEndPoint addr) :
@@ -142,6 +139,8 @@ MockConnect::MockConnect(IoMode io_mode, int r, IPEndPoint addr) :
MockConnect::~MockConnect() {}
+void SocketDataProvider::OnEnableTCPFastOpenIfSupported() {}
+
bool SocketDataProvider::IsIdle() const {
return true;
}
@@ -287,13 +286,17 @@ SSLSocketDataProvider::SSLSocketDataProvider(IoMode mode, int result)
client_cert_sent(false),
cert_request_info(NULL),
channel_id_sent(false),
- connection_status(0) {
+ connection_status(0),
+ token_binding_negotiated(false) {
SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2,
&connection_status);
// Set to TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
SSLConnectionStatusSetCipherSuite(0xcc14, &connection_status);
}
+SSLSocketDataProvider::SSLSocketDataProvider(
+ const SSLSocketDataProvider& other) = default;
+
SSLSocketDataProvider::~SSLSocketDataProvider() {
}
@@ -311,6 +314,7 @@ SequencedSocketData::SequencedSocketData(MockRead* reads,
read_state_(IDLE),
write_state_(IDLE),
busy_before_sync_reads_(false),
+ is_using_tcp_fast_open_(false),
weak_factory_(this) {
// Check that reads and writes have a contiguous set of sequence numbers
// starting from 0 and working their way up, with no repeats and skipping
@@ -489,6 +493,10 @@ bool SequencedSocketData::AllWriteDataConsumed() const {
return helper_.AllWriteDataConsumed();
}
+void SequencedSocketData::OnEnableTCPFastOpenIfSupported() {
+ is_using_tcp_fast_open_ = true;
+}
+
bool SequencedSocketData::IsIdle() const {
// If |busy_before_sync_reads_| is not set, always considered idle. If
// no reads left, or the next operation is a write, also consider it idle.
@@ -584,6 +592,10 @@ void SequencedSocketData::MaybePostReadCompleteTask() {
read_state_ = COMPLETING;
}
+bool SequencedSocketData::IsUsingTCPFastOpen() const {
+ return is_using_tcp_fast_open_;
+}
+
void SequencedSocketData::MaybePostWriteCompleteTask() {
NET_TRACE(1, " ****** ") << " current: " << sequence_number_;
// Only trigger the next write to complete if there is already a write pending
@@ -616,6 +628,7 @@ void SequencedSocketData::Reset() {
sequence_number_ = 0;
read_state_ = IDLE;
write_state_ = IDLE;
+ is_using_tcp_fast_open_ = false;
weak_factory_.InvalidateWeakPtrs();
}
@@ -744,15 +757,11 @@ scoped_ptr<SSLClientSocket> MockClientSocketFactory::CreateSSLClientSocket(
void MockClientSocketFactory::ClearSSLSessionCache() {
}
-const char MockClientSocket::kTlsUnique[] = "MOCK_TLSUNIQ";
-
MockClientSocket::MockClientSocket(const BoundNetLog& net_log)
: connected_(false),
net_log_(net_log),
weak_factory_(this) {
- IPAddressNumber ip;
- CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
- peer_addr_ = IPEndPoint(ip, 0);
+ peer_addr_ = IPEndPoint(IPAddress(192, 0, 2, 33), 0);
}
int MockClientSocket::SetReceiveBufferSize(int32_t size) {
@@ -783,10 +792,7 @@ int MockClientSocket::GetPeerAddress(IPEndPoint* address) const {
}
int MockClientSocket::GetLocalAddress(IPEndPoint* address) const {
- IPAddressNumber ip;
- bool rv = ParseIPLiteralToNumber("192.0.2.33", &ip);
- CHECK(rv);
- *address = IPEndPoint(ip, 123);
+ *address = IPEndPoint(IPAddress(192, 0, 2, 33), 123);
return OK;
}
@@ -816,12 +822,18 @@ int MockClientSocket::ExportKeyingMaterial(const base::StringPiece& label,
return OK;
}
-int MockClientSocket::GetTLSUniqueChannelBinding(std::string* out) {
- out->assign(MockClientSocket::kTlsUnique);
- return OK;
+ChannelIDService* MockClientSocket::GetChannelIDService() const {
+ NOTREACHED();
+ return NULL;
}
-ChannelIDService* MockClientSocket::GetChannelIDService() const {
+Error MockClientSocket::GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ NOTREACHED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
+crypto::ECPrivateKey* MockClientSocket::GetChannelIDKey() const {
NOTREACHED();
return NULL;
}
@@ -1013,8 +1025,10 @@ bool MockTCPClientSocket::WasEverUsed() const {
return was_used_to_convey_data_;
}
-bool MockTCPClientSocket::UsingTCPFastOpen() const {
- return false;
+void MockTCPClientSocket::EnableTCPFastOpenIfSupported() {
+ EXPECT_FALSE(IsConnected()) << "Can't enable fast open after connect.";
+
+ data_->OnEnableTCPFastOpenIfSupported();
}
bool MockTCPClientSocket::WasNpnNegotiated() const {
@@ -1185,10 +1199,6 @@ bool MockSSLClientSocket::WasEverUsed() const {
return transport_->socket()->WasEverUsed();
}
-bool MockSSLClientSocket::UsingTCPFastOpen() const {
- return transport_->socket()->UsingTCPFastOpen();
-}
-
int MockSSLClientSocket::GetPeerAddress(IPEndPoint* address) const {
return transport_->socket()->GetPeerAddress(address);
}
@@ -1199,6 +1209,8 @@ bool MockSSLClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->client_cert_sent = data_->client_cert_sent;
ssl_info->channel_id_sent = data_->channel_id_sent;
ssl_info->connection_status = data_->connection_status;
+ ssl_info->token_binding_negotiated = data_->token_binding_negotiated;
+ ssl_info->token_binding_key_param = data_->token_binding_key_param;
return true;
}
@@ -1224,6 +1236,13 @@ ChannelIDService* MockSSLClientSocket::GetChannelIDService() const {
return data_->channel_id_service;
}
+Error MockSSLClientSocket::GetSignedEKMForTokenBinding(
+ crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ out->push_back('A');
+ return OK;
+}
+
void MockSSLClientSocket::OnReadComplete(const MockRead& data) {
NOTIMPLEMENTED();
}
@@ -1330,10 +1349,7 @@ int MockUDPClientSocket::GetPeerAddress(IPEndPoint* address) const {
}
int MockUDPClientSocket::GetLocalAddress(IPEndPoint* address) const {
- IPAddressNumber ip;
- bool rv = ParseIPLiteralToNumber("192.0.2.33", &ip);
- CHECK(rv);
- *address = IPEndPoint(ip, source_port_);
+ *address = IPEndPoint(IPAddress(192, 0, 2, 33), source_port_);
return OK;
}
@@ -1341,30 +1357,41 @@ const BoundNetLog& MockUDPClientSocket::NetLog() const {
return net_log_;
}
-int MockUDPClientSocket::BindToNetwork(
- NetworkChangeNotifier::NetworkHandle network) {
- network_ = network;
- return OK;
-}
-
-int MockUDPClientSocket::BindToDefaultNetwork() {
- network_ = kDefaultNetworkForTests;
- return OK;
+int MockUDPClientSocket::Connect(const IPEndPoint& address) {
+ if (!data_)
+ return ERR_UNEXPECTED;
+ connected_ = true;
+ peer_addr_ = address;
+ return data_->connect_data().result;
}
-NetworkChangeNotifier::NetworkHandle MockUDPClientSocket::GetBoundNetwork()
- const {
- return network_;
+int MockUDPClientSocket::ConnectUsingNetwork(
+ NetworkChangeNotifier::NetworkHandle network,
+ const IPEndPoint& address) {
+ DCHECK(!connected_);
+ if (!data_)
+ return ERR_UNEXPECTED;
+ network_ = network;
+ connected_ = true;
+ peer_addr_ = address;
+ return data_->connect_data().result;
}
-int MockUDPClientSocket::Connect(const IPEndPoint& address) {
+int MockUDPClientSocket::ConnectUsingDefaultNetwork(const IPEndPoint& address) {
+ DCHECK(!connected_);
if (!data_)
return ERR_UNEXPECTED;
+ network_ = kDefaultNetworkForTests;
connected_ = true;
peer_addr_ = address;
return data_->connect_data().result;
}
+NetworkChangeNotifier::NetworkHandle MockUDPClientSocket::GetBoundNetwork()
+ const {
+ return network_;
+}
+
void MockUDPClientSocket::OnReadComplete(const MockRead& data) {
if (!data_)
return;
@@ -1595,9 +1622,13 @@ MockTransportClientSocketPool::MockTransportClientSocketPool(
MockTransportClientSocketPool::~MockTransportClientSocketPool() {}
int MockTransportClientSocketPool::RequestSocket(
- const std::string& group_name, const void* socket_params,
- RequestPriority priority, ClientSocketHandle* handle,
- const CompletionCallback& callback, const BoundNetLog& net_log) {
+ const std::string& group_name,
+ const void* socket_params,
+ RequestPriority priority,
+ RespectLimits respect_limits,
+ ClientSocketHandle* handle,
+ const CompletionCallback& callback,
+ const BoundNetLog& net_log) {
last_request_priority_ = priority;
scoped_ptr<StreamSocket> socket =
client_socket_factory_->CreateTransportClientSocket(
@@ -1640,12 +1671,16 @@ MockSOCKSClientSocketPool::MockSOCKSClientSocketPool(
MockSOCKSClientSocketPool::~MockSOCKSClientSocketPool() {}
-int MockSOCKSClientSocketPool::RequestSocket(
- const std::string& group_name, const void* socket_params,
- RequestPriority priority, ClientSocketHandle* handle,
- const CompletionCallback& callback, const BoundNetLog& net_log) {
- return transport_pool_->RequestSocket(
- group_name, socket_params, priority, handle, callback, net_log);
+int MockSOCKSClientSocketPool::RequestSocket(const std::string& group_name,
+ const void* socket_params,
+ RequestPriority priority,
+ RespectLimits respect_limits,
+ ClientSocketHandle* handle,
+ const CompletionCallback& callback,
+ const BoundNetLog& net_log) {
+ return transport_pool_->RequestSocket(group_name, socket_params, priority,
+ respect_limits, handle, callback,
+ net_log);
}
void MockSOCKSClientSocketPool::CancelRequest(
diff --git a/chromium/net/socket/socket_test_util.h b/chromium/net/socket/socket_test_util.h
index a3c6df42149..dada520bd0d 100644
--- a/chromium/net/socket/socket_test_util.h
+++ b/chromium/net/socket/socket_test_util.h
@@ -212,6 +212,8 @@ class SocketDataProvider {
virtual bool AllReadDataConsumed() const = 0;
virtual bool AllWriteDataConsumed() const = 0;
+ virtual void OnEnableTCPFastOpenIfSupported();
+
// Returns true if the request should be considered idle, for the purposes of
// IsConnectedAndIdle.
virtual bool IsIdle() const;
@@ -347,6 +349,7 @@ class StaticSocketDataProvider : public SocketDataProvider {
// to Connect().
struct SSLSocketDataProvider {
SSLSocketDataProvider(IoMode mode, int result);
+ SSLSocketDataProvider(const SSLSocketDataProvider& other);
~SSLSocketDataProvider();
void SetNextProto(NextProto proto);
@@ -361,6 +364,8 @@ struct SSLSocketDataProvider {
bool channel_id_sent;
ChannelIDService* channel_id_service;
int connection_status;
+ bool token_binding_negotiated;
+ TokenBindingParam token_binding_key_param;
};
// Uses the sequence_number field in the mock reads and writes to
@@ -390,6 +395,7 @@ class SequencedSocketData : public SocketDataProvider {
MockWriteResult OnWrite(const std::string& data) override;
bool AllReadDataConsumed() const override;
bool AllWriteDataConsumed() const override;
+ void OnEnableTCPFastOpenIfSupported() override;
bool IsIdle() const override;
// An ASYNC read event with a return value of ERR_IO_PENDING will cause the
@@ -407,6 +413,8 @@ class SequencedSocketData : public SocketDataProvider {
void Resume();
void RunUntilPaused();
+ bool IsUsingTCPFastOpen() const;
+
// When true, IsConnectedAndIdle() will return false if the next event in the
// sequence is a synchronous. Otherwise, the socket claims to be idle as
// long as it's connected. Defaults to false.
@@ -442,6 +450,7 @@ class SequencedSocketData : public SocketDataProvider {
IoState write_state_;
bool busy_before_sync_reads_;
+ bool is_using_tcp_fast_open_;
// Used by RunUntilPaused. NULL at all other times.
scoped_ptr<base::RunLoop> run_until_paused_run_loop_;
@@ -535,9 +544,6 @@ class MockClientSocketFactory : public ClientSocketFactory {
class MockClientSocket : public SSLClientSocket {
public:
- // Value returned by GetTLSUniqueChannelBinding().
- static const char kTlsUnique[];
-
// The BoundNetLog is needed to test LoadTimingInfo, which uses NetLog IDs as
// unique socket IDs.
explicit MockClientSocket(const BoundNetLog& net_log);
@@ -574,9 +580,11 @@ class MockClientSocket : public SSLClientSocket {
const base::StringPiece& context,
unsigned char* out,
unsigned int outlen) override;
- int GetTLSUniqueChannelBinding(std::string* out) override;
NextProtoStatus GetNextProto(std::string* proto) const override;
ChannelIDService* GetChannelIDService() const override;
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override;
+ crypto::ECPrivateKey* GetChannelIDKey() const override;
SSLFailureState GetSSLFailureState() const override;
protected:
@@ -622,7 +630,7 @@ class MockTCPClientSocket : public MockClientSocket, public AsyncSocket {
bool IsConnectedAndIdle() const override;
int GetPeerAddress(IPEndPoint* address) const override;
bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
+ void EnableTCPFastOpenIfSupported() override;
bool WasNpnNegotiated() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
@@ -685,12 +693,13 @@ class MockSSLClientSocket : public MockClientSocket, public AsyncSocket {
bool IsConnected() const override;
bool IsConnectedAndIdle() const override;
bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
int GetPeerAddress(IPEndPoint* address) const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
// SSLClientSocket implementation.
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override;
NextProtoStatus GetNextProto(std::string* proto) const override;
// This MockSocket does not implement the manual async IO feature.
@@ -737,10 +746,11 @@ class MockUDPClientSocket : public DatagramClientSocket, public AsyncSocket {
const BoundNetLog& NetLog() const override;
// DatagramClientSocket implementation.
- int BindToNetwork(NetworkChangeNotifier::NetworkHandle network) override;
- int BindToDefaultNetwork() override;
- NetworkChangeNotifier::NetworkHandle GetBoundNetwork() const override;
int Connect(const IPEndPoint& address) override;
+ int ConnectUsingNetwork(NetworkChangeNotifier::NetworkHandle network,
+ const IPEndPoint& address) override;
+ int ConnectUsingDefaultNetwork(const IPEndPoint& address) override;
+ NetworkChangeNotifier::NetworkHandle GetBoundNetwork() const override;
// AsyncSocket implementation.
void OnReadComplete(const MockRead& data) override;
@@ -824,17 +834,15 @@ class ClientSocketPoolTest {
PoolType* socket_pool,
const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const scoped_refptr<typename PoolType::SocketParams>& socket_params) {
DCHECK(socket_pool);
TestSocketRequest* request(
new TestSocketRequest(&request_order_, &completion_count_));
requests_.push_back(make_scoped_ptr(request));
- int rv = request->handle()->Init(group_name,
- socket_params,
- priority,
- request->callback(),
- socket_pool,
- BoundNetLog());
+ int rv = request->handle()->Init(group_name, socket_params, priority,
+ respect_limits, request->callback(),
+ socket_pool, BoundNetLog());
if (rv != ERR_IO_PENDING)
request_order_.push_back(request);
return rv;
@@ -918,6 +926,7 @@ class MockTransportClientSocketPool : public TransportClientSocketPool {
int RequestSocket(const std::string& group_name,
const void* socket_params,
RequestPriority priority,
+ RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) override;
@@ -950,6 +959,7 @@ class MockSOCKSClientSocketPool : public SOCKSClientSocketPool {
int RequestSocket(const std::string& group_name,
const void* socket_params,
RequestPriority priority,
+ RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) override;
diff --git a/chromium/net/socket/socks5_client_socket.cc b/chromium/net/socket/socks5_client_socket.cc
index 20baaf2cbe4..8c172b0b514 100644
--- a/chromium/net/socket/socks5_client_socket.cc
+++ b/chromium/net/socket/socks5_client_socket.cc
@@ -13,7 +13,6 @@
#include "base/sys_byteorder.h"
#include "base/trace_event/trace_event.h"
#include "net/base/io_buffer.h"
-#include "net/base/net_util.h"
#include "net/log/net_log.h"
#include "net/socket/client_socket_handle.h"
@@ -114,14 +113,6 @@ bool SOCKS5ClientSocket::WasEverUsed() const {
return was_ever_used_;
}
-bool SOCKS5ClientSocket::UsingTCPFastOpen() const {
- if (transport_.get() && transport_->socket()) {
- return transport_->socket()->UsingTCPFastOpen();
- }
- NOTREACHED();
- return false;
-}
-
bool SOCKS5ClientSocket::WasNpnNegotiated() const {
if (transport_.get() && transport_->socket()) {
return transport_->socket()->WasNpnNegotiated();
diff --git a/chromium/net/socket/socks5_client_socket.h b/chromium/net/socket/socks5_client_socket.h
index a5438b643ad..4d3d6dbcf1d 100644
--- a/chromium/net/socket/socks5_client_socket.h
+++ b/chromium/net/socket/socks5_client_socket.h
@@ -53,7 +53,6 @@ class NET_EXPORT_PRIVATE SOCKS5ClientSocket : public StreamSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
bool WasNpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
diff --git a/chromium/net/socket/socks_client_socket.cc b/chromium/net/socket/socks_client_socket.cc
index 69805bb6f3a..0f6e925596e 100644
--- a/chromium/net/socket/socks_client_socket.cc
+++ b/chromium/net/socket/socks_client_socket.cc
@@ -11,7 +11,6 @@
#include "base/compiler_specific.h"
#include "base/sys_byteorder.h"
#include "net/base/io_buffer.h"
-#include "net/base/net_util.h"
#include "net/log/net_log.h"
#include "net/socket/client_socket_handle.h"
@@ -143,14 +142,6 @@ bool SOCKSClientSocket::WasEverUsed() const {
return was_ever_used_;
}
-bool SOCKSClientSocket::UsingTCPFastOpen() const {
- if (transport_.get() && transport_->socket()) {
- return transport_->socket()->UsingTCPFastOpen();
- }
- NOTREACHED();
- return false;
-}
-
bool SOCKSClientSocket::WasNpnNegotiated() const {
if (transport_.get() && transport_->socket()) {
return transport_->socket()->WasNpnNegotiated();
@@ -335,7 +326,8 @@ const std::string SOCKSClientSocket::BuildHandshakeWriteBuffer() const {
// failing the connect attempt.
CHECK_EQ(ADDRESS_FAMILY_IPV4, endpoint.GetFamily());
CHECK_LE(endpoint.address().size(), sizeof(request.ip));
- memcpy(&request.ip, &endpoint.address()[0], endpoint.address().size());
+ memcpy(&request.ip, &endpoint.address().bytes()[0],
+ endpoint.address().size());
DVLOG(1) << "Resolved Host is : " << endpoint.ToStringWithoutPort();
diff --git a/chromium/net/socket/socks_client_socket.h b/chromium/net/socket/socks_client_socket.h
index 8d5accd4200..c01156050a4 100644
--- a/chromium/net/socket/socks_client_socket.h
+++ b/chromium/net/socket/socks_client_socket.h
@@ -51,7 +51,6 @@ class NET_EXPORT_PRIVATE SOCKSClientSocket : public StreamSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
bool WasNpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
diff --git a/chromium/net/socket/socks_client_socket_pool.cc b/chromium/net/socket/socks_client_socket_pool.cc
index 543c2c4ad72..d7f97f3ec8b 100644
--- a/chromium/net/socket/socks_client_socket_pool.cc
+++ b/chromium/net/socket/socks_client_socket_pool.cc
@@ -27,10 +27,6 @@ SOCKSSocketParams::SOCKSSocketParams(
: transport_params_(proxy_server),
destination_(host_port_pair),
socks_v5_(socks_v5) {
- if (transport_params_.get())
- ignore_limits_ = transport_params_->ignore_limits();
- else
- ignore_limits_ = false;
}
SOCKSSocketParams::~SOCKSSocketParams() {}
@@ -42,20 +38,24 @@ static const int kSOCKSConnectJobTimeoutInSeconds = 30;
SOCKSConnectJob::SOCKSConnectJob(
const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const scoped_refptr<SOCKSSocketParams>& socks_params,
const base::TimeDelta& timeout_duration,
TransportClientSocketPool* transport_pool,
HostResolver* host_resolver,
Delegate* delegate,
NetLog* net_log)
- : ConnectJob(group_name, timeout_duration, priority, delegate,
+ : ConnectJob(group_name,
+ timeout_duration,
+ priority,
+ respect_limits,
+ delegate,
BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
socks_params_(socks_params),
transport_pool_(transport_pool),
resolver_(host_resolver),
- callback_(base::Bind(&SOCKSConnectJob::OnIOComplete,
- base::Unretained(this))) {
-}
+ callback_(
+ base::Bind(&SOCKSConnectJob::OnIOComplete, base::Unretained(this))) {}
SOCKSConnectJob::~SOCKSConnectJob() {
// We don't worry about cancelling the tcp socket since the destructor in
@@ -118,12 +118,9 @@ int SOCKSConnectJob::DoLoop(int result) {
int SOCKSConnectJob::DoTransportConnect() {
next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
transport_socket_handle_.reset(new ClientSocketHandle());
- return transport_socket_handle_->Init(group_name(),
- socks_params_->transport_params(),
- priority(),
- callback_,
- transport_pool_,
- net_log());
+ return transport_socket_handle_->Init(
+ group_name(), socks_params_->transport_params(), priority(),
+ respect_limits(), callback_, transport_pool_, net_log());
}
int SOCKSConnectJob::DoTransportConnectComplete(int result) {
@@ -174,14 +171,10 @@ SOCKSClientSocketPool::SOCKSConnectJobFactory::NewConnectJob(
const std::string& group_name,
const PoolBase::Request& request,
ConnectJob::Delegate* delegate) const {
- return scoped_ptr<ConnectJob>(new SOCKSConnectJob(group_name,
- request.priority(),
- request.params(),
- ConnectionTimeout(),
- transport_pool_,
- host_resolver_,
- delegate,
- net_log_));
+ return scoped_ptr<ConnectJob>(new SOCKSConnectJob(
+ group_name, request.priority(), request.respect_limits(),
+ request.params(), ConnectionTimeout(), transport_pool_, host_resolver_,
+ delegate, net_log_));
}
base::TimeDelta
@@ -212,15 +205,18 @@ SOCKSClientSocketPool::SOCKSClientSocketPool(
SOCKSClientSocketPool::~SOCKSClientSocketPool() {
}
-int SOCKSClientSocketPool::RequestSocket(
- const std::string& group_name, const void* socket_params,
- RequestPriority priority, ClientSocketHandle* handle,
- const CompletionCallback& callback, const BoundNetLog& net_log) {
+int SOCKSClientSocketPool::RequestSocket(const std::string& group_name,
+ const void* socket_params,
+ RequestPriority priority,
+ RespectLimits respect_limits,
+ ClientSocketHandle* handle,
+ const CompletionCallback& callback,
+ const BoundNetLog& net_log) {
const scoped_refptr<SOCKSSocketParams>* casted_socket_params =
static_cast<const scoped_refptr<SOCKSSocketParams>*>(socket_params);
return base_.RequestSocket(group_name, *casted_socket_params, priority,
- handle, callback, net_log);
+ respect_limits, handle, callback, net_log);
}
void SOCKSClientSocketPool::RequestSockets(
diff --git a/chromium/net/socket/socks_client_socket_pool.h b/chromium/net/socket/socks_client_socket_pool.h
index 8aaf726c353..66d0e53794e 100644
--- a/chromium/net/socket/socks_client_socket_pool.h
+++ b/chromium/net/socket/socks_client_socket_pool.h
@@ -34,7 +34,6 @@ class NET_EXPORT_PRIVATE SOCKSSocketParams
}
const HostResolver::RequestInfo& destination() const { return destination_; }
bool is_socks_v5() const { return socks_v5_; }
- bool ignore_limits() const { return ignore_limits_; }
private:
friend class base::RefCounted<SOCKSSocketParams>;
@@ -45,7 +44,6 @@ class NET_EXPORT_PRIVATE SOCKSSocketParams
// This is the HTTP destination.
HostResolver::RequestInfo destination_;
const bool socks_v5_;
- bool ignore_limits_;
DISALLOW_COPY_AND_ASSIGN(SOCKSSocketParams);
};
@@ -56,6 +54,7 @@ class SOCKSConnectJob : public ConnectJob {
public:
SOCKSConnectJob(const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const scoped_refptr<SOCKSSocketParams>& params,
const base::TimeDelta& timeout_duration,
TransportClientSocketPool* transport_pool,
@@ -121,6 +120,7 @@ class NET_EXPORT_PRIVATE SOCKSClientSocketPool
int RequestSocket(const std::string& group_name,
const void* connect_params,
RequestPriority priority,
+ RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) override;
diff --git a/chromium/net/socket/socks_client_socket_pool_unittest.cc b/chromium/net/socket/socks_client_socket_pool_unittest.cc
index 587f1fa5fa5..5d16ce4cdb5 100644
--- a/chromium/net/socket/socks_client_socket_pool_unittest.cc
+++ b/chromium/net/socket/socks_client_socket_pool_unittest.cc
@@ -43,7 +43,7 @@ void TestLoadTimingInfo(const ClientSocketHandle& handle) {
scoped_refptr<TransportSocketParams> CreateProxyHostParams() {
return new TransportSocketParams(
- HostPortPair("proxy", 80), false, false, OnHostResolutionCallback(),
+ HostPortPair("proxy", 80), false, OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT);
}
@@ -102,7 +102,8 @@ class SOCKSClientSocketPoolTest : public testing::Test {
int StartRequestV5(const std::string& group_name, RequestPriority priority) {
return test_base_.StartRequestUsingPool(
- &pool_, group_name, priority, CreateSOCKSv5Params());
+ &pool_, group_name, priority, ClientSocketPool::RespectLimits::ENABLED,
+ CreateSOCKSv5Params());
}
int GetOrderOfRequest(size_t index) const {
@@ -127,8 +128,9 @@ TEST_F(SOCKSClientSocketPoolTest, Simple) {
transport_client_socket_factory_.AddSocketDataProvider(data.data_provider());
ClientSocketHandle handle;
- int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, CompletionCallback(),
- &pool_, BoundNetLog());
+ int rv = handle.Init("a", CreateSOCKSv5Params(), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
+ CompletionCallback(), &pool_, BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(handle.is_initialized());
EXPECT_TRUE(handle.socket());
@@ -146,9 +148,9 @@ TEST_F(SOCKSClientSocketPoolTest, SetSocketRequestPriorityOnInit) {
data.data_provider());
ClientSocketHandle handle;
- EXPECT_EQ(OK,
- handle.Init("a", CreateSOCKSv5Params(), priority,
- CompletionCallback(), &pool_, BoundNetLog()));
+ EXPECT_EQ(OK, handle.Init("a", CreateSOCKSv5Params(), priority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ CompletionCallback(), &pool_, BoundNetLog()));
EXPECT_EQ(priority, transport_socket_pool_.last_request_priority());
handle.socket()->Disconnect();
}
@@ -167,6 +169,7 @@ TEST_F(SOCKSClientSocketPoolTest, SetResolvePriorityOnInit) {
ClientSocketHandle handle;
EXPECT_EQ(ERR_IO_PENDING,
handle.Init("a", CreateSOCKSv4Params(), priority,
+ ClientSocketPool::RespectLimits::ENABLED,
CompletionCallback(), &pool_, BoundNetLog()));
EXPECT_EQ(priority, transport_socket_pool_.last_request_priority());
EXPECT_EQ(priority, host_resolver_.last_request_priority());
@@ -180,8 +183,9 @@ TEST_F(SOCKSClientSocketPoolTest, Async) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, callback.callback(),
- &pool_, BoundNetLog());
+ int rv = handle.Init("a", CreateSOCKSv5Params(), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -199,8 +203,9 @@ TEST_F(SOCKSClientSocketPoolTest, TransportConnectError) {
transport_client_socket_factory_.AddSocketDataProvider(&socket_data);
ClientSocketHandle handle;
- int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, CompletionCallback(),
- &pool_, BoundNetLog());
+ int rv = handle.Init("a", CreateSOCKSv5Params(), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
+ CompletionCallback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -213,8 +218,9 @@ TEST_F(SOCKSClientSocketPoolTest, AsyncTransportConnectError) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, callback.callback(),
- &pool_, BoundNetLog());
+ int rv = handle.Init("a", CreateSOCKSv5Params(), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -235,8 +241,9 @@ TEST_F(SOCKSClientSocketPoolTest, SOCKSConnectError) {
ClientSocketHandle handle;
EXPECT_EQ(0, transport_socket_pool_.release_count());
- int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, CompletionCallback(),
- &pool_, BoundNetLog());
+ int rv = handle.Init("a", CreateSOCKSv5Params(), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
+ CompletionCallback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_SOCKS_CONNECTION_FAILED, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -255,8 +262,9 @@ TEST_F(SOCKSClientSocketPoolTest, AsyncSOCKSConnectError) {
TestCompletionCallback callback;
ClientSocketHandle handle;
EXPECT_EQ(0, transport_socket_pool_.release_count());
- int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, callback.callback(),
- &pool_, BoundNetLog());
+ int rv = handle.Init("a", CreateSOCKSv5Params(), LOW,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
diff --git a/chromium/net/socket/ssl_client_socket.h b/chromium/net/socket/ssl_client_socket.h
index 3a6aa94258f..10affda136a 100644
--- a/chromium/net/socket/ssl_client_socket.h
+++ b/chromium/net/socket/ssl_client_socket.h
@@ -22,6 +22,10 @@ class FilePath;
class SequencedTaskRunner;
}
+namespace crypto {
+class ECPrivateKey;
+}
+
namespace net {
class CTPolicyEnforcer;
@@ -144,6 +148,16 @@ class NET_EXPORT SSLClientSocket : public SSLSocket {
// channel ids are not supported.
virtual ChannelIDService* GetChannelIDService() const = 0;
+ // Signs the EKM value for Token Binding with |*key| and puts it in |*out|.
+ // Returns a net error code.
+ virtual Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) = 0;
+
+ // This method is only for debugging crbug.com/548423 and will be removed when
+ // that bug is closed. This returns the channel ID key that was used when
+ // establishing the connection (or NULL if no channel ID was used).
+ virtual crypto::ECPrivateKey* GetChannelIDKey() const = 0;
+
// Returns the state of the handshake when it failed, or |SSL_FAILURE_NONE| if
// the handshake succeeded. This is used to classify causes of the TLS version
// fallback.
diff --git a/chromium/net/socket/ssl_client_socket_nss.cc b/chromium/net/socket/ssl_client_socket_nss.cc
index b15d76174aa..e3d0a36bde4 100644
--- a/chromium/net/socket/ssl_client_socket_nss.cc
+++ b/chromium/net/socket/ssl_client_socket_nss.cc
@@ -95,6 +95,7 @@
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_ev_whitelist.h"
#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verifier.h"
#include "net/cert/ct_verify_result.h"
#include "net/cert/scoped_nss_types.h"
@@ -520,6 +521,10 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
// verified, and may not be called within an NSS callback.
void CacheSessionIfNecessary();
+ crypto::ECPrivateKey* GetChannelIDKey() const {
+ return channel_id_key_.get();
+ }
+
private:
friend class base::RefCountedThreadSafe<Core>;
~Core();
@@ -964,9 +969,8 @@ int SSLClientSocketNSS::Core::Read(IOBuffer* buf, int buf_len,
nss_waiting_read_ = true;
bool posted = nss_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(IgnoreResult(&Core::Read), this, make_scoped_refptr(buf),
- buf_len, callback));
+ FROM_HERE, base::Bind(IgnoreResult(&Core::Read), this,
+ base::RetainedRef(buf), buf_len, callback));
if (!posted) {
nss_is_closed_ = true;
nss_waiting_read_ = false;
@@ -1021,9 +1025,8 @@ int SSLClientSocketNSS::Core::Write(IOBuffer* buf, int buf_len,
nss_waiting_write_ = true;
bool posted = nss_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(IgnoreResult(&Core::Write), this, make_scoped_refptr(buf),
- buf_len, callback));
+ FROM_HERE, base::Bind(IgnoreResult(&Core::Write), this,
+ base::RetainedRef(buf), buf_len, callback));
if (!posted) {
nss_is_closed_ = true;
nss_waiting_write_ = false;
@@ -1531,11 +1534,10 @@ int SSLClientSocketNSS::Core::DoPayloadRead() {
pending_read_nss_error_ = 0;
if (rv == 0) {
- PostOrRunCallback(
- FROM_HERE,
- base::Bind(&LogByteTransferEvent, weak_net_log_,
- NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
- scoped_refptr<IOBuffer>(user_read_buf_)));
+ PostOrRunCallback(FROM_HERE,
+ base::Bind(&LogByteTransferEvent, weak_net_log_,
+ NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
+ base::RetainedRef(user_read_buf_)));
} else {
PostOrRunCallback(
FROM_HERE,
@@ -1616,11 +1618,10 @@ int SSLClientSocketNSS::Core::DoPayloadRead() {
DCHECK_NE(ERR_IO_PENDING, pending_read_result_);
if (rv >= 0) {
- PostOrRunCallback(
- FROM_HERE,
- base::Bind(&LogByteTransferEvent, weak_net_log_,
- NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
- scoped_refptr<IOBuffer>(user_read_buf_)));
+ PostOrRunCallback(FROM_HERE,
+ base::Bind(&LogByteTransferEvent, weak_net_log_,
+ NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
+ base::RetainedRef(user_read_buf_)));
} else if (rv != ERR_IO_PENDING) {
PostOrRunCallback(
FROM_HERE,
@@ -1649,11 +1650,10 @@ int SSLClientSocketNSS::Core::DoPayloadWrite() {
base::Bind(&Core::OnNSSBufferUpdated, this, new_amount_in_read_buffer));
}
if (rv >= 0) {
- PostOrRunCallback(
- FROM_HERE,
- base::Bind(&LogByteTransferEvent, weak_net_log_,
- NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
- scoped_refptr<IOBuffer>(user_write_buf_)));
+ PostOrRunCallback(FROM_HERE,
+ base::Bind(&LogByteTransferEvent, weak_net_log_,
+ NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
+ base::RetainedRef(user_write_buf_)));
return rv;
}
PRErrorCode prerr = PR_GetError();
@@ -1720,9 +1720,8 @@ int SSLClientSocketNSS::Core::BufferRecv() {
rv = DoBufferRecv(read_buffer.get(), nb);
} else {
bool posted = network_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(IgnoreResult(&Core::DoBufferRecv), this, read_buffer,
- nb));
+ FROM_HERE, base::Bind(IgnoreResult(&Core::DoBufferRecv), this,
+ base::RetainedRef(read_buffer), nb));
rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
}
@@ -1770,9 +1769,8 @@ int SSLClientSocketNSS::Core::BufferSend() {
rv = DoBufferSend(send_buffer.get(), len);
} else {
bool posted = network_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(IgnoreResult(&Core::DoBufferSend), this, send_buffer,
- len));
+ FROM_HERE, base::Bind(IgnoreResult(&Core::DoBufferSend), this,
+ base::RetainedRef(send_buffer), len));
rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
}
@@ -1978,7 +1976,7 @@ void SSLClientSocketNSS::Core::UpdateServerCert() {
// own a reference to the certificate.
NetLog::ParametersCallback net_log_callback =
base::Bind(&NetLogX509CertificateCallback,
- nss_handshake_state_.server_cert);
+ base::RetainedRef(nss_handshake_state_.server_cert));
PostOrRunCallback(
FROM_HERE,
base::Bind(&AddLogEventWithCallback, weak_net_log_,
@@ -2159,12 +2157,12 @@ int SSLClientSocketNSS::Core::DoBufferRecv(IOBuffer* read_buffer, int len) {
int rv = transport_->socket()->Read(
read_buffer, len,
base::Bind(&Core::BufferRecvComplete, base::Unretained(this),
- scoped_refptr<IOBuffer>(read_buffer)));
+ base::RetainedRef(read_buffer)));
if (!OnNSSTaskRunner() && rv != ERR_IO_PENDING) {
- nss_task_runner_->PostTask(
- FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
- scoped_refptr<IOBuffer>(read_buffer), rv));
+ nss_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&Core::BufferRecvComplete, this,
+ base::RetainedRef(read_buffer), rv));
return rv;
}
@@ -2301,7 +2299,7 @@ void SSLClientSocketNSS::Core::BufferRecvComplete(
nss_task_runner_->PostTask(
FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
- scoped_refptr<IOBuffer>(read_buffer), result));
+ base::RetainedRef(read_buffer), result));
return;
}
@@ -2410,7 +2408,7 @@ bool SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->cert = server_cert_verify_result_.verified_cert;
ssl_info->unverified_cert = core_->state().server_cert;
- AddSCTInfoToSSLInfo(ssl_info);
+ AddCTInfoToSSLInfo(ssl_info);
ssl_info->connection_status =
core_->state().ssl_connection_status;
@@ -2480,22 +2478,6 @@ int SSLClientSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
return OK;
}
-int SSLClientSocketNSS::GetTLSUniqueChannelBinding(std::string* out) {
- if (!IsConnected())
- return ERR_SOCKET_NOT_CONNECTED;
- unsigned char buf[64];
- unsigned int len;
- SECStatus result = SSL_GetChannelBinding(nss_fd_,
- SSL_CHANNEL_BINDING_TLS_UNIQUE,
- buf, &len, arraysize(buf));
- if (result != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_GetChannelBinding", "");
- return MapNSSError(PORT_GetError());
- }
- out->assign(reinterpret_cast<char*>(buf), len);
- return OK;
-}
-
SSLClientSocket::NextProtoStatus SSLClientSocketNSS::GetNextProto(
std::string* proto) const {
*proto = core_->state().next_proto;
@@ -2631,14 +2613,6 @@ bool SSLClientSocketNSS::WasEverUsed() const {
return core_->WasEverUsed();
}
-bool SSLClientSocketNSS::UsingTCPFastOpen() const {
- if (transport_.get() && transport_->socket()) {
- return transport_->socket()->UsingTCPFastOpen();
- }
- NOTREACHED();
- return false;
-}
-
int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len,
const CompletionCallback& callback) {
DCHECK(core_.get());
@@ -2678,7 +2652,7 @@ int SSLClientSocketNSS::Init() {
EnsureNSSSSLInit();
if (!NSS_IsInitialized())
return ERR_UNEXPECTED;
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
if (ssl_config_.cert_io_enabled) {
// We must call EnsureNSSHttpIOInit() here, on the IO thread, to get the IO
// loop by MessageLoopForIO::current().
@@ -3126,22 +3100,38 @@ void SSLClientSocketNSS::VerifyCT() {
// TODO(ekasper): wipe stapled_ocsp_response and sct_list_from_tls_extension
// from the state after verification is complete, to conserve memory.
- if (policy_enforcer_ &&
- (server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV)) {
- scoped_refptr<ct::EVCertsWhitelist> ev_whitelist =
- SSLConfigService::GetEVCertsWhitelist();
- if (!policy_enforcer_->DoesConformToCTEVPolicy(
- server_cert_verify_result_.verified_cert.get(), ev_whitelist.get(),
- ct_verify_result_, net_log_)) {
- // TODO(eranm): Log via the BoundNetLog, see crbug.com/437766
- VLOG(1) << "EV certificate for "
- << server_cert_verify_result_.verified_cert->subject()
- .GetDisplayName()
- << " does not conform to CT policy, removing EV status.";
- server_cert_verify_result_.cert_status |=
- CERT_STATUS_CT_COMPLIANCE_FAILED;
- server_cert_verify_result_.cert_status &= ~CERT_STATUS_IS_EV;
+ ct_verify_result_.ct_policies_applied = (policy_enforcer_ != nullptr);
+ ct_verify_result_.ev_policy_compliance =
+ ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
+ if (policy_enforcer_) {
+ if ((server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV)) {
+ scoped_refptr<ct::EVCertsWhitelist> ev_whitelist =
+ SSLConfigService::GetEVCertsWhitelist();
+ ct::EVPolicyCompliance ev_policy_compliance =
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ server_cert_verify_result_.verified_cert.get(),
+ ev_whitelist.get(), ct_verify_result_.verified_scts, net_log_);
+ ct_verify_result_.ev_policy_compliance = ev_policy_compliance;
+ if (ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY &&
+ ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST &&
+ ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS) {
+ // TODO(eranm): Log via the BoundNetLog, see crbug.com/437766
+ VLOG(1) << "EV certificate for "
+ << server_cert_verify_result_.verified_cert->subject()
+ .GetDisplayName()
+ << " does not conform to CT policy, removing EV status.";
+ server_cert_verify_result_.cert_status |=
+ CERT_STATUS_CT_COMPLIANCE_FAILED;
+ server_cert_verify_result_.cert_status &= ~CERT_STATUS_IS_EV;
+ }
}
+ ct_verify_result_.cert_policy_compliance =
+ policy_enforcer_->DoesConformToCertPolicy(
+ server_cert_verify_result_.verified_cert.get(),
+ ct_verify_result_.verified_scts, net_log_);
}
}
@@ -3158,8 +3148,8 @@ bool SSLClientSocketNSS::CalledOnValidThread() const {
return valid_thread_id_ == base::PlatformThread::CurrentId();
}
-void SSLClientSocketNSS::AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const {
- ssl_info->UpdateSignedCertificateTimestamps(ct_verify_result_);
+void SSLClientSocketNSS::AddCTInfoToSSLInfo(SSLInfo* ssl_info) const {
+ ssl_info->UpdateCertificateTransparencyInfo(ct_verify_result_);
}
// static
@@ -3179,6 +3169,17 @@ ChannelIDService* SSLClientSocketNSS::GetChannelIDService() const {
return channel_id_service_;
}
+Error SSLClientSocketNSS::GetSignedEKMForTokenBinding(
+ crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ NOTREACHED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
+crypto::ECPrivateKey* SSLClientSocketNSS::GetChannelIDKey() const {
+ return core_->GetChannelIDKey();
+}
+
SSLFailureState SSLClientSocketNSS::GetSSLFailureState() const {
if (completed_handshake_)
return SSL_FAILURE_NONE;
diff --git a/chromium/net/socket/ssl_client_socket_nss.h b/chromium/net/socket/ssl_client_socket_nss.h
index 366df1c4ee7..7073290a791 100644
--- a/chromium/net/socket/ssl_client_socket_nss.h
+++ b/chromium/net/socket/ssl_client_socket_nss.h
@@ -67,7 +67,6 @@ class SSLClientSocketNSS : public SSLClientSocket {
const base::StringPiece& context,
unsigned char* out,
unsigned int outlen) override;
- int GetTLSUniqueChannelBinding(std::string* out) override;
// StreamSocket implementation.
int Connect(const CompletionCallback& callback) override;
@@ -80,7 +79,6 @@ class SSLClientSocketNSS : public SSLClientSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
void ClearConnectionAttempts() override {}
@@ -99,6 +97,9 @@ class SSLClientSocketNSS : public SSLClientSocket {
// SSLClientSocket implementation.
ChannelIDService* GetChannelIDService() const override;
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override;
+ crypto::ECPrivateKey* GetChannelIDKey() const override;
SSLFailureState GetSSLFailureState() const override;
private:
@@ -144,7 +145,7 @@ class SSLClientSocketNSS : public SSLClientSocket {
// vetor representing a particular verification state, this method associates
// each of the SCTs with the corresponding SCTVerifyStatus as it adds it to
// the |ssl_info|.signed_certificate_timestamps list.
- void AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const;
+ void AddCTInfoToSSLInfo(SSLInfo* ssl_info) const;
// Move last protocol to first place: SSLConfig::next_protos has protocols in
// decreasing order of preference with NPN fallback protocol at the end, but
diff --git a/chromium/net/socket/ssl_client_socket_openssl.cc b/chromium/net/socket/ssl_client_socket_openssl.cc
index 82ced7cbfea..cfad9deeba2 100644
--- a/chromium/net/socket/ssl_client_socket_openssl.cc
+++ b/chromium/net/socket/ssl_client_socket_openssl.cc
@@ -26,18 +26,22 @@
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/profiler/scoped_tracker.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_local.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
+#include "crypto/auto_cbb.h"
#include "crypto/ec_private_key.h"
#include "crypto/openssl_util.h"
#include "crypto/scoped_openssl_types.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_ev_whitelist.h"
#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_verifier.h"
#include "net/cert/x509_certificate_net_log_param.h"
#include "net/cert/x509_util_openssl.h"
@@ -49,16 +53,13 @@
#include "net/ssl/ssl_failure_state.h"
#include "net/ssl/ssl_info.h"
#include "net/ssl/ssl_private_key.h"
-
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
+#include "net/ssl/token_binding.h"
#if !defined(OS_NACL)
#include "net/ssl/ssl_key_logger.h"
#endif
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
#include "net/cert_net/nss_ocsp.h"
#endif
@@ -87,71 +88,13 @@ const char kDefaultSupportedNPNProtocol[] = "http/1.1";
const int KDefaultOpenSSLBufferSize = 17 * 1024;
// TLS extension number use for Token Binding.
-const unsigned int kTbExtNum = 30033;
+const unsigned int kTbExtNum = 24;
// Token Binding ProtocolVersions supported.
const uint8_t kTbProtocolVersionMajor = 0;
-const uint8_t kTbProtocolVersionMinor = 3;
+const uint8_t kTbProtocolVersionMinor = 5;
const uint8_t kTbMinProtocolVersionMajor = 0;
-const uint8_t kTbMinProtocolVersionMinor = 2;
-
-void FreeX509Stack(STACK_OF(X509)* ptr) {
- sk_X509_pop_free(ptr, X509_free);
-}
-
-using ScopedX509Stack = crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack>;
-
-// Used for encoding the |connection_status| field of an SSLInfo object.
-int EncodeSSLConnectionStatus(uint16_t cipher_suite,
- int compression,
- int version) {
- return cipher_suite |
- ((compression & SSL_CONNECTION_COMPRESSION_MASK) <<
- SSL_CONNECTION_COMPRESSION_SHIFT) |
- ((version & SSL_CONNECTION_VERSION_MASK) <<
- SSL_CONNECTION_VERSION_SHIFT);
-}
-
-// Returns the net SSL version number (see ssl_connection_status_flags.h) for
-// this SSL connection.
-int GetNetSSLVersion(SSL* ssl) {
- switch (SSL_version(ssl)) {
- case TLS1_VERSION:
- return SSL_CONNECTION_VERSION_TLS1;
- case TLS1_1_VERSION:
- return SSL_CONNECTION_VERSION_TLS1_1;
- case TLS1_2_VERSION:
- return SSL_CONNECTION_VERSION_TLS1_2;
- default:
- NOTREACHED();
- return SSL_CONNECTION_VERSION_UNKNOWN;
- }
-}
-
-ScopedX509 OSCertHandleToOpenSSL(
- X509Certificate::OSCertHandle os_handle) {
-#if defined(USE_OPENSSL_CERTS)
- return ScopedX509(X509Certificate::DupOSCertHandle(os_handle));
-#else // !defined(USE_OPENSSL_CERTS)
- std::string der_encoded;
- if (!X509Certificate::GetDEREncoded(os_handle, &der_encoded))
- return ScopedX509();
- const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_encoded.data());
- return ScopedX509(d2i_X509(NULL, &bytes, der_encoded.size()));
-#endif // defined(USE_OPENSSL_CERTS)
-}
-
-ScopedX509Stack OSCertHandlesToOpenSSL(
- const X509Certificate::OSCertHandles& os_handles) {
- ScopedX509Stack stack(sk_X509_new_null());
- for (size_t i = 0; i < os_handles.size(); i++) {
- ScopedX509 x509 = OSCertHandleToOpenSSL(os_handles[i]);
- if (!x509)
- return ScopedX509Stack();
- sk_X509_push(stack.get(), x509.release());
- }
- return stack;
-}
+const uint8_t kTbMinProtocolVersionMinor = 3;
bool EVP_MDToPrivateKeyHash(const EVP_MD* md, SSLPrivateKey::Hash* hash) {
switch (EVP_MD_type(md)) {
@@ -175,18 +118,6 @@ bool EVP_MDToPrivateKeyHash(const EVP_MD* md, SSLPrivateKey::Hash* hash) {
}
}
-class ScopedCBB {
- public:
- ScopedCBB() { CBB_zero(&cbb_); }
- ~ScopedCBB() { CBB_cleanup(&cbb_); }
-
- CBB* get() { return &cbb_; }
-
- private:
- CBB cbb_;
- DISALLOW_COPY_AND_ASSIGN(ScopedCBB);
-};
-
scoped_ptr<base::Value> NetLogPrivateKeyOperationCallback(
SSLPrivateKey::Type type,
SSLPrivateKey::Hash hash,
@@ -226,6 +157,35 @@ scoped_ptr<base::Value> NetLogPrivateKeyOperationCallback(
return std::move(value);
}
+scoped_ptr<base::Value> NetLogChannelIDLookupCallback(
+ ChannelIDService* channel_id_service,
+ NetLogCaptureMode capture_mode) {
+ ChannelIDStore* store = channel_id_service->GetChannelIDStore();
+ scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ dict->SetBoolean("ephemeral", store->IsEphemeral());
+ dict->SetString("service", base::HexEncode(&channel_id_service,
+ sizeof(channel_id_service)));
+ dict->SetString("store", base::HexEncode(&store, sizeof(store)));
+ return std::move(dict);
+}
+
+scoped_ptr<base::Value> NetLogChannelIDLookupCompleteCallback(
+ crypto::ECPrivateKey* key,
+ int result,
+ NetLogCaptureMode capture_mode) {
+ scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ 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());
+ }
+ dict->SetString("key", key_to_log);
+ }
+ return std::move(dict);
+}
+
} // namespace
class SSLClientSocketOpenSSL::SSLContext {
@@ -483,8 +443,8 @@ SSLClientSocketOpenSSL::PeerCertificateChain::AsOSChain() const {
intermediates.push_back(sk_X509_value(openssl_chain_.get(), i));
}
- return make_scoped_refptr(X509Certificate::CreateFromHandle(
- sk_X509_value(openssl_chain_.get(), 0), intermediates));
+ return X509Certificate::CreateFromHandle(
+ sk_X509_value(openssl_chain_.get(), 0), intermediates);
#else
// DER-encode the chain and convert to a platform certificate handle.
std::vector<base::StringPiece> der_chain;
@@ -496,7 +456,7 @@ SSLClientSocketOpenSSL::PeerCertificateChain::AsOSChain() const {
der_chain.push_back(der);
}
- return make_scoped_refptr(X509Certificate::CreateFromDERCertChain(der_chain));
+ return X509Certificate::CreateFromDERCertChain(der_chain);
#endif
}
@@ -526,6 +486,7 @@ SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
channel_id_service_(context.channel_id_service),
tb_was_negotiated_(false),
tb_negotiated_param_(TB_PARAM_ECDSAP256),
+ tb_signed_ekm_map_(10),
ssl_(NULL),
transport_bio_(NULL),
transport_(std::move(transport_socket)),
@@ -577,6 +538,43 @@ SSLClientSocketOpenSSL::GetChannelIDService() const {
return channel_id_service_;
}
+Error SSLClientSocketOpenSSL::GetSignedEKMForTokenBinding(
+ crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ // The same key will be used across multiple requests to sign the same value,
+ // so the signature is cached.
+ std::string raw_public_key;
+ if (!key->ExportRawPublicKey(&raw_public_key))
+ return ERR_FAILED;
+ SignedEkmMap::iterator it = tb_signed_ekm_map_.Get(raw_public_key);
+ if (it != tb_signed_ekm_map_.end()) {
+ *out = it->second;
+ return OK;
+ }
+
+ uint8_t tb_ekm_buf[32];
+ static const char kTokenBindingExporterLabel[] = "EXPORTER-Token-Binding";
+ if (!SSL_export_keying_material(ssl_, tb_ekm_buf, sizeof(tb_ekm_buf),
+ kTokenBindingExporterLabel,
+ strlen(kTokenBindingExporterLabel), nullptr,
+ 0, false /* no context */)) {
+ return ERR_FAILED;
+ }
+
+ if (!SignTokenBindingEkm(
+ base::StringPiece(reinterpret_cast<char*>(tb_ekm_buf),
+ sizeof(tb_ekm_buf)),
+ key, out))
+ return ERR_FAILED;
+
+ tb_signed_ekm_map_.Put(raw_public_key, *out);
+ return OK;
+}
+
+crypto::ECPrivateKey* SSLClientSocketOpenSSL::GetChannelIDKey() const {
+ return channel_id_key_.get();
+}
+
SSLFailureState SSLClientSocketOpenSSL::GetSSLFailureState() const {
return ssl_failure_state_;
}
@@ -605,11 +603,6 @@ int SSLClientSocketOpenSSL::ExportKeyingMaterial(
return OK;
}
-int SSLClientSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
- NOTIMPLEMENTED();
- return ERR_NOT_IMPLEMENTED;
-}
-
int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) {
// It is an error to create an SSLClientSocket whose context has no
// TransportSecurityState.
@@ -647,6 +640,8 @@ int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) {
}
void SSLClientSocketOpenSSL::Disconnect() {
+ crypto::OpenSSLErrStackTracer tracer(FROM_HERE);
+
if (ssl_) {
// Calling SSL_shutdown prevents the session from being marked as
// unresumable.
@@ -772,14 +767,6 @@ bool SSLClientSocketOpenSSL::WasEverUsed() const {
return was_ever_used_;
}
-bool SSLClientSocketOpenSSL::UsingTCPFastOpen() const {
- if (transport_.get() && transport_->socket())
- return transport_->socket()->UsingTCPFastOpen();
-
- NOTREACHED();
- return false;
-}
-
bool SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->Reset();
if (server_cert_chain_->empty())
@@ -799,7 +786,7 @@ bool SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->token_binding_key_param = tb_negotiated_param_;
ssl_info->pinning_failure_log = pinning_failure_log_;
- AddSCTInfoToSSLInfo(ssl_info);
+ AddCTInfoToSSLInfo(ssl_info);
const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
CHECK(cipher);
@@ -807,9 +794,11 @@ bool SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->key_exchange_info =
SSL_SESSION_get_key_exchange_info(SSL_get_session(ssl_));
- ssl_info->connection_status = EncodeSSLConnectionStatus(
- static_cast<uint16_t>(SSL_CIPHER_get_id(cipher)), 0 /* no compression */,
- GetNetSSLVersion(ssl_));
+ SSLConnectionStatusSetCipherSuite(
+ static_cast<uint16_t>(SSL_CIPHER_get_id(cipher)),
+ &ssl_info->connection_status);
+ SSLConnectionStatusSetVersion(GetNetSSLVersion(ssl_),
+ &ssl_info->connection_status);
if (!SSL_get_secure_renegotiation_support(ssl_))
ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
@@ -888,7 +877,7 @@ int SSLClientSocketOpenSSL::Init() {
DCHECK(!ssl_);
DCHECK(!transport_bio_);
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
if (ssl_config_.cert_io_enabled) {
// TODO(davidben): Move this out of SSLClientSocket. See
// https://crbug.com/539520.
@@ -908,8 +897,8 @@ int SSLClientSocketOpenSSL::Init() {
//
// TODO(rsleevi): Should this code allow hostnames that violate the LDH rule?
// See https://crbug.com/496472 and https://crbug.com/496468 for discussion.
- IPAddressNumber unused;
- if (!ParseIPLiteralToNumber(host_and_port_.host(), &unused) &&
+ IPAddress unused;
+ if (!unused.AssignFromIPLiteral(host_and_port_.host()) &&
!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) {
return ERR_UNEXPECTED;
}
@@ -972,11 +961,13 @@ int SSLClientSocketOpenSSL::Init() {
SSL_set_mode(ssl_, mode.set_mask);
SSL_clear_mode(ssl_, mode.clear_mask);
- // See SSLConfig::disabled_cipher_suites for description of the suites
- // disabled by default. Note that SHA256 and SHA384 only select HMAC-SHA256
- // and HMAC-SHA384 cipher suites, not GCM cipher suites with SHA256 or SHA384
- // as the handshake hash.
- std::string command("DEFAULT:!SHA256:-SHA384:!AESGCM+AES256:!aPSK");
+ // 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
+ // supported. As DHE is being deprecated, don't add a cipher only to remove it
+ // immediately.
+ std::string command(
+ "DEFAULT:!SHA256:!SHA384:!DHE-RSA-AES256-GCM-SHA384:!aPSK");
if (ssl_config_.require_ecdhe)
command.append(":!kRSA:!kDHE");
@@ -1000,14 +991,6 @@ int SSLClientSocketOpenSSL::Init() {
}
}
- // Disable ECDSA cipher suites on platforms that do not support ECDSA
- // signed certificates, as servers may use the presence of such
- // ciphersuites as a hint to send an ECDSA certificate.
-#if defined(OS_WIN)
- if (base::win::GetVersion() < base::win::VERSION_VISTA)
- command.append(":!ECDSA");
-#endif
-
int rv = SSL_set_cipher_list(ssl_, command.c_str());
// If this fails (rv = 0) it means there are no ciphers enabled on this SSL.
// This will almost certainly result in the socket failing to complete the
@@ -1244,7 +1227,9 @@ int SSLClientSocketOpenSSL::DoHandshakeComplete(int result) {
}
int SSLClientSocketOpenSSL::DoChannelIDLookup() {
- net_log_.AddEvent(NetLog::TYPE_SSL_CHANNEL_ID_REQUESTED);
+ NetLog::ParametersCallback callback = base::Bind(
+ &NetLogChannelIDLookupCallback, base::Unretained(channel_id_service_));
+ net_log_.BeginEvent(NetLog::TYPE_SSL_GET_CHANNEL_ID, callback);
GotoState(STATE_CHANNEL_ID_LOOKUP_COMPLETE);
return channel_id_service_->GetOrCreateChannelID(
host_and_port_.host(), &channel_id_key_,
@@ -1254,16 +1239,15 @@ int SSLClientSocketOpenSSL::DoChannelIDLookup() {
}
int SSLClientSocketOpenSSL::DoChannelIDLookupComplete(int result) {
+ net_log_.EndEvent(NetLog::TYPE_SSL_GET_CHANNEL_ID,
+ base::Bind(&NetLogChannelIDLookupCompleteCallback,
+ channel_id_key_.get(), result));
if (result < 0)
return result;
- if (!channel_id_key_) {
- LOG(ERROR) << "Failed to import Channel ID.";
- return ERR_CHANNEL_ID_IMPORT_FAILED;
- }
-
// Hand the key to OpenSSL. Check for error in case OpenSSL rejects the key
// type.
+ DCHECK(channel_id_key_);
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
int rv = SSL_set1_tls_channel_id(ssl_, channel_id_key_->key());
if (!rv) {
@@ -1274,7 +1258,6 @@ int SSLClientSocketOpenSSL::DoChannelIDLookupComplete(int result) {
// Return to the handshake.
channel_id_sent_ = true;
- net_log_.AddEvent(NetLog::TYPE_SSL_CHANNEL_ID_PROVIDED);
GotoState(STATE_HANDSHAKE);
return OK;
}
@@ -1419,22 +1402,38 @@ void SSLClientSocketOpenSSL::VerifyCT() {
server_cert_verify_result_.verified_cert.get(), ocsp_response, sct_list,
&ct_verify_result_, net_log_);
- if (policy_enforcer_ &&
- (server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV)) {
- scoped_refptr<ct::EVCertsWhitelist> ev_whitelist =
- SSLConfigService::GetEVCertsWhitelist();
- if (!policy_enforcer_->DoesConformToCTEVPolicy(
- server_cert_verify_result_.verified_cert.get(), ev_whitelist.get(),
- ct_verify_result_, net_log_)) {
- // TODO(eranm): Log via the BoundNetLog, see crbug.com/437766
- VLOG(1) << "EV certificate for "
- << server_cert_verify_result_.verified_cert->subject()
- .GetDisplayName()
- << " does not conform to CT policy, removing EV status.";
- server_cert_verify_result_.cert_status |=
- CERT_STATUS_CT_COMPLIANCE_FAILED;
- server_cert_verify_result_.cert_status &= ~CERT_STATUS_IS_EV;
+ ct_verify_result_.ct_policies_applied = (policy_enforcer_ != nullptr);
+ ct_verify_result_.ev_policy_compliance =
+ ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
+ if (policy_enforcer_) {
+ if ((server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV)) {
+ scoped_refptr<ct::EVCertsWhitelist> ev_whitelist =
+ SSLConfigService::GetEVCertsWhitelist();
+ ct::EVPolicyCompliance ev_policy_compliance =
+ policy_enforcer_->DoesConformToCTEVPolicy(
+ server_cert_verify_result_.verified_cert.get(),
+ ev_whitelist.get(), ct_verify_result_.verified_scts, net_log_);
+ ct_verify_result_.ev_policy_compliance = ev_policy_compliance;
+ if (ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY &&
+ ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST &&
+ ev_policy_compliance !=
+ ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS) {
+ // TODO(eranm): Log via the BoundNetLog, see crbug.com/437766
+ VLOG(1) << "EV certificate for "
+ << server_cert_verify_result_.verified_cert->subject()
+ .GetDisplayName()
+ << " does not conform to CT policy, removing EV status.";
+ server_cert_verify_result_.cert_status |=
+ CERT_STATUS_CT_COMPLIANCE_FAILED;
+ server_cert_verify_result_.cert_status &= ~CERT_STATUS_IS_EV;
+ }
}
+ ct_verify_result_.cert_policy_compliance =
+ policy_enforcer_->DoesConformToCertPolicy(
+ server_cert_verify_result_.verified_cert.get(),
+ ct_verify_result_.verified_scts, net_log_);
}
}
@@ -1459,6 +1458,7 @@ void SSLClientSocketOpenSSL::OnSendComplete(int result) {
}
void SSLClientSocketOpenSSL::OnRecvComplete(int result) {
+ TRACE_EVENT0("net", "SSLClientSocketOpenSSL::OnRecvComplete");
if (next_handshake_state_ == STATE_HANDSHAKE) {
// In handshake phase.
OnHandshakeIOComplete(result);
@@ -1476,6 +1476,7 @@ void SSLClientSocketOpenSSL::OnRecvComplete(int result) {
}
int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
+ TRACE_EVENT0("net", "SSLClientSocketOpenSSL::DoHandshakeLoop");
int rv = last_io_result;
do {
// Default to STATE_NONE for next state.
@@ -2087,8 +2088,8 @@ int SSLClientSocketOpenSSL::NewSessionCallback(SSL_SESSION* session) {
return 1;
}
-void SSLClientSocketOpenSSL::AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const {
- ssl_info->UpdateSignedCertificateTimestamps(ct_verify_result_);
+void SSLClientSocketOpenSSL::AddCTInfoToSSLInfo(SSLInfo* ssl_info) const {
+ ssl_info->UpdateCertificateTransparencyInfo(ct_verify_result_);
}
std::string SSLClientSocketOpenSSL::GetSessionCacheKey() const {
@@ -2237,7 +2238,7 @@ int SSLClientSocketOpenSSL::TokenBindingAdd(const uint8_t** out,
if (ssl_config_.token_binding_params.empty()) {
return 0;
}
- ScopedCBB output;
+ crypto::AutoCBB output;
CBB parameters_list;
if (!CBB_init(output.get(), 7) ||
!CBB_add_u8(output.get(), kTbProtocolVersionMajor) ||
diff --git a/chromium/net/socket/ssl_client_socket_openssl.h b/chromium/net/socket/ssl_client_socket_openssl.h
index 178daeb3273..628d4dbeedc 100644
--- a/chromium/net/socket/ssl_client_socket_openssl.h
+++ b/chromium/net/socket/ssl_client_socket_openssl.h
@@ -13,6 +13,8 @@
#include <string>
#include <vector>
+#include "base/compiler_specific.h"
+#include "base/containers/mru_cache.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
@@ -42,6 +44,8 @@ class CTVerifier;
class SSLCertRequestInfo;
class SSLInfo;
+using SignedEkmMap = base::MRUCache<std::string, std::vector<uint8_t>>;
+
// An SSL client socket implemented with OpenSSL.
class SSLClientSocketOpenSSL : public SSLClientSocket {
public:
@@ -72,6 +76,9 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
NextProtoStatus GetNextProto(std::string* proto) const override;
ChannelIDService* GetChannelIDService() const override;
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override;
+ crypto::ECPrivateKey* GetChannelIDKey() const override;
SSLFailureState GetSSLFailureState() const override;
// SSLSocket implementation.
@@ -80,7 +87,6 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
const base::StringPiece& context,
unsigned char* out,
unsigned int outlen) override;
- int GetTLSUniqueChannelBinding(std::string* out) override;
// StreamSocket implementation.
int Connect(const CompletionCallback& callback) override;
@@ -93,7 +99,6 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
void ClearConnectionAttempts() override {}
@@ -191,12 +196,13 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
// Called from the SSL layer whenever a new session is established.
int NewSessionCallback(SSL_SESSION* session);
- // Adds the SignedCertificateTimestamps from ct_verify_result_ to |ssl_info|.
+ // Adds the Certificate Transparency info from ct_verify_result_ to
+ // |ssl_info|.
// SCTs are held in three separate vectors in ct_verify_result, each
// vetor representing a particular verification state, this method associates
// each of the SCTs with the corresponding SCTVerifyStatus as it adds it to
// the |ssl_info|.signed_certificate_timestamps list.
- void AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const;
+ void AddCTInfoToSSLInfo(SSLInfo* ssl_info) const;
// Returns a unique key string for the SSL session cache for
// this socket.
@@ -301,6 +307,7 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
ChannelIDService* channel_id_service_;
bool tb_was_negotiated_;
TokenBindingParam tb_negotiated_param_;
+ SignedEkmMap tb_signed_ekm_map_;
// OpenSSL stuff
SSL* ssl_;
diff --git a/chromium/net/socket/ssl_client_socket_openssl_unittest.cc b/chromium/net/socket/ssl_client_socket_openssl_unittest.cc
deleted file mode 100644
index a1ab91a4754..00000000000
--- a/chromium/net/socket/ssl_client_socket_openssl_unittest.cc
+++ /dev/null
@@ -1,267 +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/socket/ssl_client_socket.h"
-
-#include <errno.h>
-#include <openssl/bio.h>
-#include <openssl/bn.h>
-#include <openssl/evp.h>
-#include <openssl/pem.h>
-#include <openssl/rsa.h>
-#include <string.h>
-#include <utility>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/values.h"
-#include "crypto/openssl_util.h"
-#include "crypto/scoped_openssl_types.h"
-#include "net/base/address_list.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
-#include "net/base/test_data_directory.h"
-#include "net/cert/mock_cert_verifier.h"
-#include "net/cert/test_root_certs.h"
-#include "net/dns/host_resolver.h"
-#include "net/http/transport_security_state.h"
-#include "net/log/net_log.h"
-#include "net/socket/client_socket_factory.h"
-#include "net/socket/client_socket_handle.h"
-#include "net/socket/socket_test_util.h"
-#include "net/socket/tcp_client_socket.h"
-#include "net/ssl/openssl_client_key_store.h"
-#include "net/ssl/ssl_cert_request_info.h"
-#include "net/ssl/ssl_config_service.h"
-#include "net/ssl/ssl_platform_key.h"
-#include "net/test/cert_test_util.h"
-#include "net/test/spawned_test_server/spawned_test_server.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace net {
-
-namespace {
-
-// These client auth tests are currently dependent on OpenSSL's struct X509.
-#if defined(USE_OPENSSL_CERTS)
-
-// Loads a PEM-encoded private key file into a scoped EVP_PKEY object.
-// |filepath| is the private key file path.
-// |*pkey| is reset to the new EVP_PKEY on success, untouched otherwise.
-// Returns true on success, false on failure.
-bool LoadPrivateKeyOpenSSL(
- const base::FilePath& filepath,
- crypto::ScopedEVP_PKEY* pkey) {
- std::string data;
- if (!base::ReadFileToString(filepath, &data)) {
- LOG(ERROR) << "Could not read private key file: "
- << filepath.value() << ": " << strerror(errno);
- return false;
- }
- crypto::ScopedBIO bio(BIO_new_mem_buf(
- const_cast<char*>(reinterpret_cast<const char*>(data.data())),
- static_cast<int>(data.size())));
- if (!bio.get()) {
- LOG(ERROR) << "Could not allocate BIO for buffer?";
- return false;
- }
- EVP_PKEY* result = PEM_read_bio_PrivateKey(bio.get(), NULL, NULL, NULL);
- if (result == NULL) {
- LOG(ERROR) << "Could not decode private key file: "
- << filepath.value();
- return false;
- }
- pkey->reset(result);
- return true;
-}
-
-class SSLClientSocketOpenSSLClientAuthTest : public PlatformTest {
- public:
- SSLClientSocketOpenSSLClientAuthTest()
- : socket_factory_(ClientSocketFactory::GetDefaultFactory()),
- cert_verifier_(new MockCertVerifier),
- transport_security_state_(new TransportSecurityState) {
- cert_verifier_->set_default_result(OK);
- context_.cert_verifier = cert_verifier_.get();
- context_.transport_security_state = transport_security_state_.get();
- key_store_ = OpenSSLClientKeyStore::GetInstance();
- }
-
- ~SSLClientSocketOpenSSLClientAuthTest() override { key_store_->Flush(); }
-
- protected:
- scoped_ptr<SSLClientSocket> CreateSSLClientSocket(
- scoped_ptr<StreamSocket> transport_socket,
- const HostPortPair& host_and_port,
- const SSLConfig& ssl_config) {
- scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
- connection->SetSocket(std::move(transport_socket));
- return socket_factory_->CreateSSLClientSocket(
- std::move(connection), host_and_port, ssl_config, context_);
- }
-
- // Connect to a HTTPS test server.
- bool ConnectToTestServer(SpawnedTestServer::SSLOptions& ssl_options) {
- test_server_.reset(new SpawnedTestServer(SpawnedTestServer::TYPE_HTTPS,
- ssl_options,
- base::FilePath()));
- if (!test_server_->Start()) {
- LOG(ERROR) << "Could not start SpawnedTestServer";
- return false;
- }
-
- if (!test_server_->GetAddressList(&addr_)) {
- LOG(ERROR) << "Could not get SpawnedTestServer address list";
- return false;
- }
-
- transport_.reset(new TCPClientSocket(
- addr_, &log_, NetLog::Source()));
- int rv = callback_.GetResult(
- transport_->Connect(callback_.callback()));
- if (rv != OK) {
- LOG(ERROR) << "Could not connect to SpawnedTestServer";
- return false;
- }
- return true;
- }
-
- // Record a certificate's private key to ensure it can be used
- // by the OpenSSL-based SSLClientSocket implementation.
- // |ssl_config| provides a client certificate.
- // |private_key| must be an EVP_PKEY for the corresponding private key.
- // Returns true on success, false on failure.
- bool RecordPrivateKey(SSLConfig& ssl_config,
- EVP_PKEY* private_key) {
- return key_store_->RecordClientCertPrivateKey(
- ssl_config.client_cert.get(), private_key);
- }
-
- // Create an SSLClientSocket object and use it to connect to a test
- // server, then wait for connection results. This must be called after
- // a succesful ConnectToTestServer() call.
- // |ssl_config| the SSL configuration to use.
- // |result| will retrieve the ::Connect() result value.
- // Returns true on succes, false otherwise. Success means that the socket
- // could be created and its Connect() was called, not that the connection
- // itself was a success.
- bool CreateAndConnectSSLClientSocket(const SSLConfig& ssl_config,
- int* result) {
- sock_ = CreateSSLClientSocket(std::move(transport_),
- test_server_->host_port_pair(), ssl_config);
-
- if (sock_->IsConnected()) {
- LOG(ERROR) << "SSL Socket prematurely connected";
- return false;
- }
-
- *result = callback_.GetResult(sock_->Connect(callback_.callback()));
- return true;
- }
-
-
- // Check that the client certificate was sent.
- // Returns true on success.
- bool CheckSSLClientSocketSentCert() {
- SSLInfo ssl_info;
- sock_->GetSSLInfo(&ssl_info);
- return ssl_info.client_cert_sent;
- }
-
- ClientSocketFactory* socket_factory_;
- scoped_ptr<MockCertVerifier> cert_verifier_;
- scoped_ptr<TransportSecurityState> transport_security_state_;
- SSLClientSocketContext context_;
- OpenSSLClientKeyStore* key_store_;
- scoped_ptr<SpawnedTestServer> test_server_;
- AddressList addr_;
- TestCompletionCallback callback_;
- NetLog log_;
- scoped_ptr<StreamSocket> transport_;
- scoped_ptr<SSLClientSocket> sock_;
-};
-
-// Connect to a server requesting client authentication, do not send
-// any client certificates. It should refuse the connection.
-TEST_F(SSLClientSocketOpenSSLClientAuthTest, NoCert) {
- SpawnedTestServer::SSLOptions ssl_options;
- ssl_options.request_client_certificate = true;
-
- ASSERT_TRUE(ConnectToTestServer(ssl_options));
-
- base::FilePath certs_dir = GetTestCertsDirectory();
-
- int rv;
- ASSERT_TRUE(CreateAndConnectSSLClientSocket(SSLConfig(), &rv));
-
- EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
- EXPECT_FALSE(sock_->IsConnected());
-}
-
-// Connect to a server requesting client authentication, and send it
-// an empty certificate. It should refuse the connection.
-TEST_F(SSLClientSocketOpenSSLClientAuthTest, SendEmptyCert) {
- SpawnedTestServer::SSLOptions ssl_options;
- ssl_options.request_client_certificate = true;
- ssl_options.client_authorities.push_back(
- GetTestClientCertsDirectory().AppendASCII("client_1_ca.pem"));
-
- ASSERT_TRUE(ConnectToTestServer(ssl_options));
-
- base::FilePath certs_dir = GetTestCertsDirectory();
- SSLConfig ssl_config;
- ssl_config.send_client_cert = true;
- ssl_config.client_cert = NULL;
- ssl_config.client_private_key = NULL;
-
- int rv;
- ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
-
- EXPECT_EQ(OK, rv);
- EXPECT_TRUE(sock_->IsConnected());
-}
-
-// Connect to a server requesting client authentication. Send it a
-// matching certificate. It should allow the connection.
-TEST_F(SSLClientSocketOpenSSLClientAuthTest, SendGoodCert) {
- SpawnedTestServer::SSLOptions ssl_options;
- ssl_options.request_client_certificate = true;
- ssl_options.client_authorities.push_back(
- GetTestClientCertsDirectory().AppendASCII("client_1_ca.pem"));
-
- ASSERT_TRUE(ConnectToTestServer(ssl_options));
-
- base::FilePath certs_dir = GetTestCertsDirectory();
- SSLConfig ssl_config;
- ssl_config.send_client_cert = true;
- ssl_config.client_cert = ImportCertFromFile(certs_dir, "client_1.pem");
-
- // This is required to ensure that signing works with the client
- // certificate's private key.
- crypto::ScopedEVP_PKEY client_private_key;
- ASSERT_TRUE(LoadPrivateKeyOpenSSL(certs_dir.AppendASCII("client_1.key"),
- &client_private_key));
- EXPECT_TRUE(RecordPrivateKey(ssl_config, client_private_key.get()));
-
- ssl_config.client_private_key =
- FetchClientCertPrivateKey(ssl_config.client_cert.get());
-
- int rv;
- ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
-
- EXPECT_EQ(OK, rv);
- EXPECT_TRUE(sock_->IsConnected());
-
- EXPECT_TRUE(CheckSSLClientSocketSentCert());
-
- sock_->Disconnect();
- EXPECT_FALSE(sock_->IsConnected());
-}
-#endif // defined(USE_OPENSSL_CERTS)
-
-} // namespace
-} // namespace net
diff --git a/chromium/net/socket/ssl_client_socket_pool.cc b/chromium/net/socket/ssl_client_socket_pool.cc
index f9a405854b3..2a2865c65f9 100644
--- a/chromium/net/socket/ssl_client_socket_pool.cc
+++ b/chromium/net/socket/ssl_client_socket_pool.cc
@@ -12,6 +12,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/profiler/scoped_tracker.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
@@ -45,19 +46,11 @@ SSLSocketParams::SSLSocketParams(
ssl_config_(ssl_config),
privacy_mode_(privacy_mode),
load_flags_(load_flags),
- expect_spdy_(expect_spdy),
- ignore_limits_(false) {
- if (direct_params_.get()) {
- DCHECK(!socks_proxy_params_.get());
- DCHECK(!http_proxy_params_.get());
- ignore_limits_ = direct_params_->ignore_limits();
- } else if (socks_proxy_params_.get()) {
- DCHECK(!http_proxy_params_.get());
- ignore_limits_ = socks_proxy_params_->ignore_limits();
- } else {
- DCHECK(http_proxy_params_.get());
- ignore_limits_ = http_proxy_params_->ignore_limits();
- }
+ expect_spdy_(expect_spdy) {
+ // Only one set of lower level pool params should be non-NULL.
+ DCHECK((direct_params_ && !socks_proxy_params_ && !http_proxy_params_) ||
+ (!direct_params_ && socks_proxy_params_ && !http_proxy_params_) ||
+ (!direct_params_ && !socks_proxy_params_ && http_proxy_params_));
}
SSLSocketParams::~SSLSocketParams() {}
@@ -101,6 +94,7 @@ static const int kSSLHandshakeTimeoutInSeconds = 30;
SSLConnectJob::SSLConnectJob(const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const scoped_refptr<SSLSocketParams>& params,
const base::TimeDelta& timeout_duration,
TransportClientSocketPool* transport_pool,
@@ -113,6 +107,7 @@ SSLConnectJob::SSLConnectJob(const std::string& group_name,
: ConnectJob(group_name,
timeout_duration,
priority,
+ respect_limits,
delegate,
BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
params_(params),
@@ -129,8 +124,7 @@ SSLConnectJob::SSLConnectJob(const std::string& group_name,
? "pm/" + context.ssl_session_cache_shard
: context.ssl_session_cache_shard)),
callback_(
- base::Bind(&SSLConnectJob::OnIOComplete, base::Unretained(this))) {
-}
+ base::Bind(&SSLConnectJob::OnIOComplete, base::Unretained(this))) {}
SSLConnectJob::~SSLConnectJob() {
}
@@ -179,6 +173,7 @@ void SSLConnectJob::OnIOComplete(int result) {
}
int SSLConnectJob::DoLoop(int result) {
+ TRACE_EVENT0("net", "SSLConnectJob::DoLoop");
DCHECK_NE(next_state_, STATE_NONE);
int rv = result;
@@ -232,7 +227,8 @@ int SSLConnectJob::DoTransportConnect() {
scoped_refptr<TransportSocketParams> direct_params =
params_->GetDirectConnectionParams();
return transport_socket_handle_->Init(group_name(), direct_params, priority(),
- callback_, transport_pool_, net_log());
+ respect_limits(), callback_,
+ transport_pool_, net_log());
}
int SSLConnectJob::DoTransportConnectComplete(int result) {
@@ -252,8 +248,8 @@ int SSLConnectJob::DoSOCKSConnect() {
scoped_refptr<SOCKSSocketParams> socks_proxy_params =
params_->GetSocksProxyConnectionParams();
return transport_socket_handle_->Init(group_name(), socks_proxy_params,
- priority(), callback_, socks_pool_,
- net_log());
+ priority(), respect_limits(), callback_,
+ socks_pool_, net_log());
}
int SSLConnectJob::DoSOCKSConnectComplete(int result) {
@@ -271,8 +267,8 @@ int SSLConnectJob::DoTunnelConnect() {
scoped_refptr<HttpProxySocketParams> http_proxy_params =
params_->GetHttpProxyConnectionParams();
return transport_socket_handle_->Init(group_name(), http_proxy_params,
- priority(), callback_, http_proxy_pool_,
- net_log());
+ priority(), respect_limits(), callback_,
+ http_proxy_pool_, net_log());
}
int SSLConnectJob::DoTunnelConnectComplete(int result) {
@@ -295,6 +291,7 @@ int SSLConnectJob::DoTunnelConnectComplete(int result) {
}
int SSLConnectJob::DoSSLConnect() {
+ TRACE_EVENT0("net", "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"));
@@ -558,17 +555,10 @@ scoped_ptr<ConnectJob> SSLClientSocketPool::SSLConnectJobFactory::NewConnectJob(
const std::string& group_name,
const PoolBase::Request& request,
ConnectJob::Delegate* delegate) const {
- return scoped_ptr<ConnectJob>(new SSLConnectJob(group_name,
- request.priority(),
- request.params(),
- ConnectionTimeout(),
- transport_pool_,
- socks_pool_,
- http_proxy_pool_,
- client_socket_factory_,
- context_,
- delegate,
- net_log_));
+ return scoped_ptr<ConnectJob>(new SSLConnectJob(
+ group_name, request.priority(), request.respect_limits(),
+ request.params(), ConnectionTimeout(), transport_pool_, socks_pool_,
+ http_proxy_pool_, client_socket_factory_, context_, delegate, net_log_));
}
base::TimeDelta SSLClientSocketPool::SSLConnectJobFactory::ConnectionTimeout()
@@ -579,6 +569,7 @@ base::TimeDelta SSLClientSocketPool::SSLConnectJobFactory::ConnectionTimeout()
int SSLClientSocketPool::RequestSocket(const std::string& group_name,
const void* socket_params,
RequestPriority priority,
+ RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) {
@@ -586,7 +577,7 @@ int SSLClientSocketPool::RequestSocket(const std::string& group_name,
static_cast<const scoped_refptr<SSLSocketParams>*>(socket_params);
return base_.RequestSocket(group_name, *casted_socket_params, priority,
- handle, callback, net_log);
+ respect_limits, handle, callback, net_log);
}
void SSLClientSocketPool::RequestSockets(
diff --git a/chromium/net/socket/ssl_client_socket_pool.h b/chromium/net/socket/ssl_client_socket_pool.h
index b015baeb797..d5f480799ef 100644
--- a/chromium/net/socket/ssl_client_socket_pool.h
+++ b/chromium/net/socket/ssl_client_socket_pool.h
@@ -72,7 +72,6 @@ class NET_EXPORT_PRIVATE SSLSocketParams
PrivacyMode privacy_mode() const { return privacy_mode_; }
int load_flags() const { return load_flags_; }
bool expect_spdy() const { return expect_spdy_; }
- bool ignore_limits() const { return ignore_limits_; }
private:
friend class base::RefCounted<SSLSocketParams>;
@@ -86,7 +85,6 @@ class NET_EXPORT_PRIVATE SSLSocketParams
const PrivacyMode privacy_mode_;
const int load_flags_;
const bool expect_spdy_;
- bool ignore_limits_;
DISALLOW_COPY_AND_ASSIGN(SSLSocketParams);
};
@@ -99,6 +97,7 @@ class SSLConnectJob : public ConnectJob {
// job.
SSLConnectJob(const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const scoped_refptr<SSLSocketParams>& params,
const base::TimeDelta& timeout_duration,
TransportClientSocketPool* transport_pool,
@@ -205,6 +204,7 @@ class NET_EXPORT_PRIVATE SSLClientSocketPool
int RequestSocket(const std::string& group_name,
const void* connect_params,
RequestPriority priority,
+ RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) override;
diff --git a/chromium/net/socket/ssl_client_socket_pool_unittest.cc b/chromium/net/socket/ssl_client_socket_pool_unittest.cc
index 2baae896fb0..f83ffd50d13 100644
--- a/chromium/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/chromium/net/socket/ssl_client_socket_pool_unittest.cc
@@ -87,7 +87,6 @@ class SSLClientSocketPoolTest
direct_transport_socket_params_(new TransportSocketParams(
HostPortPair("host", 443),
false,
- false,
OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)),
transport_socket_pool_(kMaxSockets,
@@ -96,7 +95,6 @@ class SSLClientSocketPoolTest
proxy_transport_socket_params_(new TransportSocketParams(
HostPortPair("proxy", 443),
false,
- false,
OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)),
socks_socket_params_(
@@ -170,7 +168,6 @@ class SSLClientSocketPoolTest
params.http_auth_handler_factory = http_auth_handler_factory_.get();
params.http_server_properties =
http_server_properties_.GetWeakPtr();
- params.enable_spdy_compression = false;
params.spdy_default_protocol = GetParam();
return new HttpNetworkSession(params);
}
@@ -217,8 +214,9 @@ TEST_P(SSLClientSocketPoolTest, TCPFail) {
false);
ClientSocketHandle handle;
- int rv = handle.Init("a", params, MEDIUM, CompletionCallback(), pool_.get(),
- BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ CompletionCallback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_CONNECTION_FAILED, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -238,8 +236,9 @@ TEST_P(SSLClientSocketPoolTest, TCPFailAsync) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -265,8 +264,9 @@ TEST_P(SSLClientSocketPoolTest, BasicDirect) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(handle.is_initialized());
EXPECT_TRUE(handle.socket());
@@ -291,8 +291,9 @@ TEST_P(SSLClientSocketPoolTest, SetSocketRequestPriorityOnInitDirect) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(OK, handle.Init("a", params, priority, callback.callback(),
- pool_.get(), BoundNetLog()));
+ EXPECT_EQ(OK, handle.Init("a", params, priority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(priority, transport_socket_pool_.last_request_priority());
handle.socket()->Disconnect();
}
@@ -310,8 +311,9 @@ TEST_P(SSLClientSocketPoolTest, BasicDirectAsync) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -334,8 +336,9 @@ TEST_P(SSLClientSocketPoolTest, DirectCertError) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -358,8 +361,9 @@ TEST_P(SSLClientSocketPoolTest, DirectSSLError) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -383,8 +387,9 @@ TEST_P(SSLClientSocketPoolTest, DirectWithNPN) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -410,8 +415,9 @@ TEST_P(SSLClientSocketPoolTest, DirectNoSPDY) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -435,8 +441,9 @@ TEST_P(SSLClientSocketPoolTest, DirectGotSPDY) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -466,8 +473,9 @@ TEST_P(SSLClientSocketPoolTest, DirectGotBonusSPDY) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -495,8 +503,9 @@ TEST_P(SSLClientSocketPoolTest, SOCKSFail) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_CONNECTION_FAILED, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -514,8 +523,9 @@ TEST_P(SSLClientSocketPoolTest, SOCKSFailAsync) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -539,8 +549,9 @@ TEST_P(SSLClientSocketPoolTest, SOCKSBasic) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(handle.is_initialized());
EXPECT_TRUE(handle.socket());
@@ -564,8 +575,9 @@ TEST_P(SSLClientSocketPoolTest, SetTransportPriorityOnInitSOCKS) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(OK, handle.Init("a", params, HIGHEST, callback.callback(),
- pool_.get(), BoundNetLog()));
+ EXPECT_EQ(OK, handle.Init("a", params, HIGHEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(HIGHEST, transport_socket_pool_.last_request_priority());
}
@@ -581,8 +593,9 @@ TEST_P(SSLClientSocketPoolTest, SOCKSBasicAsync) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -606,8 +619,9 @@ TEST_P(SSLClientSocketPoolTest, HttpProxyFail) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -625,8 +639,9 @@ TEST_P(SSLClientSocketPoolTest, HttpProxyFailAsync) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -662,8 +677,9 @@ TEST_P(SSLClientSocketPoolTest, HttpProxyBasic) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_TRUE(handle.is_initialized());
EXPECT_TRUE(handle.socket());
@@ -697,8 +713,9 @@ TEST_P(SSLClientSocketPoolTest, SetTransportPriorityOnInitHTTP) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(OK, handle.Init("a", params, HIGHEST, callback.callback(),
- pool_.get(), BoundNetLog()));
+ EXPECT_EQ(OK, handle.Init("a", params, HIGHEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog()));
EXPECT_EQ(HIGHEST, transport_socket_pool_.last_request_priority());
}
@@ -726,8 +743,9 @@ TEST_P(SSLClientSocketPoolTest, HttpProxyBasicAsync) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -763,8 +781,9 @@ TEST_P(SSLClientSocketPoolTest, NeedProxyAuth) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv = handle.Init(
- "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
+ int rv =
+ handle.Init("a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), pool_.get(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
diff --git a/chromium/net/socket/ssl_client_socket_unittest.cc b/chromium/net/socket/ssl_client_socket_unittest.cc
index 6a9d4654bdf..d5656567984 100644
--- a/chromium/net/socket/ssl_client_socket_unittest.cc
+++ b/chromium/net/socket/ssl_client_socket_unittest.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/callback_helpers.h"
+#include "base/files/file_util.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -21,6 +22,7 @@
#include "net/base/test_data_directory.h"
#include "net/cert/asn1_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/mock_cert_verifier.h"
#include "net/cert/test_root_certs.h"
@@ -49,6 +51,17 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
+#if defined(USE_OPENSSL)
+#include <errno.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <string.h>
+
+#include "crypto/scoped_openssl_types.h"
+#include "net/ssl/test_ssl_private_key.h"
+#endif
+
using testing::_;
using testing::Return;
using testing::Truly;
@@ -90,9 +103,6 @@ class WrappedStreamSocket : public StreamSocket {
}
void SetOmniboxSpeculation() override { transport_->SetOmniboxSpeculation(); }
bool WasEverUsed() const override { return transport_->WasEverUsed(); }
- bool UsingTCPFastOpen() const override {
- return transport_->UsingTCPFastOpen();
- }
bool WasNpnNegotiated() const override {
return transport_->WasNpnNegotiated();
}
@@ -643,6 +653,7 @@ class FailingChannelIDStore : public ChannelIDStore {
void GetAllChannelIDs(const GetChannelIDListCallback& callback) override {}
int GetChannelIDCount() override { return 0; }
void SetForceKeepSessionState() override {}
+ bool IsEphemeral() override { return true; }
};
// A ChannelIDStore that asynchronously returns an error when asked for a
@@ -667,6 +678,7 @@ class AsyncFailingChannelIDStore : public ChannelIDStore {
void GetAllChannelIDs(const GetChannelIDListCallback& callback) override {}
int GetChannelIDCount() override { return 0; }
void SetForceKeepSessionState() override {}
+ bool IsEphemeral() override { return true; }
};
// A mock CTVerifier that records every call to Verify but doesn't verify
@@ -684,11 +696,15 @@ class MockCTVerifier : public CTVerifier {
// A mock CTPolicyEnforcer that returns a custom verification result.
class MockCTPolicyEnforcer : public CTPolicyEnforcer {
public:
+ MOCK_METHOD3(DoesConformToCertPolicy,
+ ct::CertPolicyCompliance(X509Certificate* cert,
+ const ct::SCTList&,
+ const BoundNetLog&));
MOCK_METHOD4(DoesConformToCTEVPolicy,
- bool(X509Certificate* cert,
- const ct::EVCertsWhitelist*,
- const ct::CTVerifyResult&,
- const BoundNetLog&));
+ ct::EVPolicyCompliance(X509Certificate* cert,
+ const ct::EVCertsWhitelist*,
+ const ct::SCTList&,
+ const BoundNetLog&));
};
class SSLClientSocketTest : public PlatformTest {
@@ -2334,8 +2350,12 @@ TEST_F(SSLClientSocketTest, EVCertStatusMaintainedForCompliantCert) {
// Emulate compliance of the certificate to the policy.
MockCTPolicyEnforcer policy_enforcer;
SetCTPolicyEnforcer(&policy_enforcer);
+ EXPECT_CALL(policy_enforcer, DoesConformToCertPolicy(_, _, _))
+ .WillRepeatedly(
+ Return(ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS));
EXPECT_CALL(policy_enforcer, DoesConformToCTEVPolicy(_, _, _, _))
- .WillRepeatedly(Return(true));
+ .WillRepeatedly(
+ Return(ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS));
int rv;
ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
@@ -2366,8 +2386,12 @@ TEST_F(SSLClientSocketTest, EVCertStatusRemovedForNonCompliantCert) {
// Emulate non-compliance of the certificate to the policy.
MockCTPolicyEnforcer policy_enforcer;
SetCTPolicyEnforcer(&policy_enforcer);
+ EXPECT_CALL(policy_enforcer, DoesConformToCertPolicy(_, _, _))
+ .WillRepeatedly(
+ Return(ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS));
EXPECT_CALL(policy_enforcer, DoesConformToCTEVPolicy(_, _, _, _))
- .WillRepeatedly(Return(false));
+ .WillRepeatedly(
+ Return(ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS));
int rv;
ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
@@ -3240,4 +3264,111 @@ TEST_F(SSLClientSocketTest, NPNServerDisabled) {
sock_->GetNextProto(&proto));
}
+// Client auth is not supported in NSS ports.
+#if defined(USE_OPENSSL)
+
+namespace {
+
+// Loads a PEM-encoded private key file into a SSLPrivateKey object.
+// |filepath| is the private key file path.
+// Returns the new SSLPrivateKey.
+scoped_refptr<SSLPrivateKey> LoadPrivateKeyOpenSSL(
+ const base::FilePath& filepath) {
+ std::string data;
+ if (!base::ReadFileToString(filepath, &data)) {
+ LOG(ERROR) << "Could not read private key file: " << filepath.value();
+ return nullptr;
+ }
+ crypto::ScopedBIO bio(BIO_new_mem_buf(const_cast<char*>(data.data()),
+ static_cast<int>(data.size())));
+ if (!bio) {
+ LOG(ERROR) << "Could not allocate BIO for buffer?";
+ return nullptr;
+ }
+ crypto::ScopedEVP_PKEY result(
+ PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
+ if (!result) {
+ LOG(ERROR) << "Could not decode private key file: " << filepath.value();
+ return nullptr;
+ }
+ return WrapOpenSSLPrivateKey(std::move(result));
+}
+
+} // namespace
+
+// Connect to a server requesting client authentication, do not send
+// any client certificates. It should refuse the connection.
+TEST_F(SSLClientSocketTest, NoCert) {
+ SpawnedTestServer::SSLOptions ssl_options;
+ ssl_options.request_client_certificate = true;
+ ASSERT_TRUE(StartTestServer(ssl_options));
+
+ int rv;
+ ASSERT_TRUE(CreateAndConnectSSLClientSocket(SSLConfig(), &rv));
+
+ EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
+ EXPECT_FALSE(sock_->IsConnected());
+}
+
+// Connect to a server requesting client authentication, and send it
+// an empty certificate.
+TEST_F(SSLClientSocketTest, SendEmptyCert) {
+ SpawnedTestServer::SSLOptions ssl_options;
+ ssl_options.request_client_certificate = true;
+ ssl_options.client_authorities.push_back(
+ GetTestClientCertsDirectory().AppendASCII("client_1_ca.pem"));
+
+ ASSERT_TRUE(StartTestServer(ssl_options));
+
+ SSLConfig ssl_config;
+ ssl_config.send_client_cert = true;
+ ssl_config.client_cert = nullptr;
+ ssl_config.client_private_key = nullptr;
+
+ int rv;
+ ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
+
+ EXPECT_EQ(OK, rv);
+ EXPECT_TRUE(sock_->IsConnected());
+
+ SSLInfo ssl_info;
+ ASSERT_TRUE(sock_->GetSSLInfo(&ssl_info));
+ EXPECT_FALSE(ssl_info.client_cert_sent);
+}
+
+// Connect to a server requesting client authentication. Send it a
+// matching certificate. It should allow the connection.
+TEST_F(SSLClientSocketTest, SendGoodCert) {
+ SpawnedTestServer::SSLOptions ssl_options;
+ ssl_options.request_client_certificate = true;
+ ssl_options.client_authorities.push_back(
+ GetTestClientCertsDirectory().AppendASCII("client_1_ca.pem"));
+
+ ASSERT_TRUE(StartTestServer(ssl_options));
+
+ base::FilePath certs_dir = GetTestCertsDirectory();
+ SSLConfig ssl_config;
+ ssl_config.send_client_cert = true;
+ ssl_config.client_cert = ImportCertFromFile(certs_dir, "client_1.pem");
+
+ // This is required to ensure that signing works with the client
+ // certificate's private key.
+ ssl_config.client_private_key =
+ LoadPrivateKeyOpenSSL(certs_dir.AppendASCII("client_1.key"));
+
+ int rv;
+ ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
+
+ EXPECT_EQ(OK, rv);
+ EXPECT_TRUE(sock_->IsConnected());
+
+ SSLInfo ssl_info;
+ ASSERT_TRUE(sock_->GetSSLInfo(&ssl_info));
+ EXPECT_TRUE(ssl_info.client_cert_sent);
+
+ sock_->Disconnect();
+ EXPECT_FALSE(sock_->IsConnected());
+}
+#endif // defined(USE_OPENSSL)
+
} // namespace net
diff --git a/chromium/net/socket/ssl_server_socket.h b/chromium/net/socket/ssl_server_socket.h
index bfbe7de9110..479bbc7a4f9 100644
--- a/chromium/net/socket/ssl_server_socket.h
+++ b/chromium/net/socket/ssl_server_socket.h
@@ -31,6 +31,20 @@ class SSLServerSocket : public SSLSocket {
virtual int Handshake(const CompletionCallback& callback) = 0;
};
+class SSLServerContext {
+ public:
+ virtual ~SSLServerContext(){};
+
+ // Creates an SSL server socket over an already-connected transport socket.
+ // The caller must ensure the returned socket does not outlive the server
+ // context.
+ //
+ // The caller starts the SSL server handshake by calling Handshake on the
+ // returned socket.
+ virtual scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
+ scoped_ptr<StreamSocket> socket) = 0;
+};
+
// Configures the underlying SSL library for the use of SSL server sockets.
//
// Due to the requirements of the underlying libraries, this should be called
@@ -41,18 +55,14 @@ class SSLServerSocket : public SSLSocket {
// omitted.
NET_EXPORT void EnableSSLServerSockets();
-// Creates an SSL server socket over an already-connected transport socket.
-// The caller must provide the server certificate and private key to use.
+// Creates an SSL server socket context where all sockets spawned using this
+// context will share the same session cache.
//
-// The returned SSLServerSocket takes ownership of |socket|. Stubbed versions
-// of CreateSSLServerSocket will delete |socket| and return NULL.
+// The caller must provide the server certificate and private key to use.
// It takes a reference to |certificate|.
// The |key| and |ssl_config| parameters are copied.
//
-// The caller starts the SSL server handshake by calling Handshake on the
-// returned socket.
-NET_EXPORT scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
- scoped_ptr<StreamSocket> socket,
+NET_EXPORT scoped_ptr<SSLServerContext> CreateSSLServerContext(
X509Certificate* certificate,
const crypto::RSAPrivateKey& key,
const SSLServerConfig& ssl_config);
diff --git a/chromium/net/socket/ssl_server_socket_nss.cc b/chromium/net/socket/ssl_server_socket_nss.cc
index 80450fe65fa..8e02909cf54 100644
--- a/chromium/net/socket/ssl_server_socket_nss.cc
+++ b/chromium/net/socket/ssl_server_socket_nss.cc
@@ -75,29 +75,140 @@ class NSSSSLServerInitSingleton {
static base::LazyInstance<NSSSSLServerInitSingleton>::Leaky
g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER;
-} // namespace
-
-void EnableSSLServerSockets() {
- g_nss_ssl_server_init_singleton.Get();
-}
-
-scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
- scoped_ptr<StreamSocket> socket,
- X509Certificate* cert,
- const crypto::RSAPrivateKey& key,
- const SSLServerConfig& ssl_config) {
- DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been"
- << " called yet!";
-
- return scoped_ptr<SSLServerSocket>(
- new SSLServerSocketNSS(std::move(socket), cert, key, ssl_config));
-}
+class SSLServerSocketNSS : public SSLServerSocket {
+ public:
+ // See comments on CreateSSLServerSocket for details of how these
+ // parameters are used.
+ SSLServerSocketNSS(scoped_ptr<StreamSocket> socket,
+ X509Certificate* certificate,
+ const crypto::RSAPrivateKey& key,
+ const SSLServerConfig& ssl_server_config);
+ ~SSLServerSocketNSS() override;
+
+ // SSLServerSocket interface.
+ int Handshake(const CompletionCallback& callback) override;
+
+ // SSLSocket interface.
+ int ExportKeyingMaterial(const base::StringPiece& label,
+ bool has_context,
+ const base::StringPiece& context,
+ unsigned char* out,
+ unsigned int outlen) override;
+
+ // Socket interface (via StreamSocket).
+ int Read(IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) override;
+ int Write(IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) override;
+ int SetReceiveBufferSize(int32_t size) override;
+ int SetSendBufferSize(int32_t size) override;
+
+ // StreamSocket implementation.
+ int Connect(const CompletionCallback& callback) override;
+ void Disconnect() override;
+ bool IsConnected() const override;
+ bool IsConnectedAndIdle() const override;
+ int GetPeerAddress(IPEndPoint* address) const override;
+ int GetLocalAddress(IPEndPoint* address) const override;
+ const BoundNetLog& NetLog() const override;
+ void SetSubresourceSpeculation() override;
+ void SetOmniboxSpeculation() override;
+ bool WasEverUsed() const override;
+ bool WasNpnNegotiated() 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;
+
+ private:
+ enum State {
+ STATE_NONE,
+ STATE_HANDSHAKE,
+ };
+
+ int InitializeSSLOptions();
+
+ void OnSendComplete(int result);
+ void OnRecvComplete(int result);
+ void OnHandshakeIOComplete(int result);
+
+ int BufferSend();
+ void BufferSendComplete(int result);
+ int BufferRecv();
+ void BufferRecvComplete(int result);
+ bool DoTransportIO();
+ int DoPayloadRead();
+ int DoPayloadWrite();
+
+ int DoHandshakeLoop(int last_io_result);
+ int DoReadLoop(int result);
+ int DoWriteLoop(int result);
+ int DoHandshake();
+ void DoHandshakeCallback(int result);
+ void DoReadCallback(int result);
+ void DoWriteCallback(int result);
+
+ static SECStatus OwnAuthCertHandler(void* arg,
+ PRFileDesc* socket,
+ PRBool checksig,
+ PRBool is_server);
+ static void HandshakeCallback(PRFileDesc* socket, void* arg);
+
+ int Init();
+
+ // Members used to send and receive buffer.
+ bool transport_send_busy_;
+ bool transport_recv_busy_;
+
+ scoped_refptr<IOBuffer> recv_buffer_;
+
+ BoundNetLog net_log_;
+
+ CompletionCallback user_handshake_callback_;
+ CompletionCallback user_read_callback_;
+ CompletionCallback user_write_callback_;
+
+ // Used by Read function.
+ scoped_refptr<IOBuffer> user_read_buf_;
+ int user_read_buf_len_;
+
+ // Used by Write function.
+ scoped_refptr<IOBuffer> user_write_buf_;
+ int user_write_buf_len_;
+
+ // The NSS SSL state machine
+ PRFileDesc* nss_fd_;
+
+ // Buffers for the network end of the SSL state machine
+ memio_Private* nss_bufs_;
+
+ // StreamSocket for sending and receiving data.
+ scoped_ptr<StreamSocket> transport_socket_;
+
+ // Options for the SSL socket.
+ SSLServerConfig ssl_server_config_;
+
+ // Certificate for the server.
+ scoped_refptr<X509Certificate> cert_;
+
+ // Private key used by the server.
+ scoped_ptr<crypto::RSAPrivateKey> key_;
+
+ State next_handshake_state_;
+ bool completed_handshake_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLServerSocketNSS);
+};
SSLServerSocketNSS::SSLServerSocketNSS(
scoped_ptr<StreamSocket> transport_socket,
- scoped_refptr<X509Certificate> cert,
+ X509Certificate* cert,
const crypto::RSAPrivateKey& key,
- const SSLServerConfig& ssl_config)
+ const SSLServerConfig& ssl_server_config)
: transport_send_busy_(false),
transport_recv_busy_(false),
user_read_buf_len_(0),
@@ -105,7 +216,7 @@ SSLServerSocketNSS::SSLServerSocketNSS(
nss_fd_(NULL),
nss_bufs_(NULL),
transport_socket_(std::move(transport_socket)),
- ssl_config_(ssl_config),
+ ssl_server_config_(ssl_server_config),
cert_(cert),
key_(key.Copy()),
next_handshake_state_(STATE_NONE),
@@ -172,28 +283,13 @@ int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
return OK;
}
-int SSLServerSocketNSS::GetTLSUniqueChannelBinding(std::string* out) {
- if (!IsConnected())
- return ERR_SOCKET_NOT_CONNECTED;
- unsigned char buf[64];
- unsigned int len;
- SECStatus result = SSL_GetChannelBinding(nss_fd_,
- SSL_CHANNEL_BINDING_TLS_UNIQUE,
- buf, &len, arraysize(buf));
- if (result != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_GetChannelBinding", "");
- return MapNSSError(PORT_GetError());
- }
- out->assign(reinterpret_cast<char*>(buf), len);
- return OK;
-}
-
int SSLServerSocketNSS::Connect(const CompletionCallback& callback) {
NOTIMPLEMENTED();
return ERR_NOT_IMPLEMENTED;
}
-int SSLServerSocketNSS::Read(IOBuffer* buf, int buf_len,
+int SSLServerSocketNSS::Read(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) {
DCHECK(user_read_callback_.is_null());
DCHECK(user_handshake_callback_.is_null());
@@ -217,7 +313,8 @@ int SSLServerSocketNSS::Read(IOBuffer* buf, int buf_len,
return rv;
}
-int SSLServerSocketNSS::Write(IOBuffer* buf, int buf_len,
+int SSLServerSocketNSS::Write(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) {
DCHECK(user_write_callback_.is_null());
DCHECK(!user_write_buf_);
@@ -288,10 +385,6 @@ bool SSLServerSocketNSS::WasEverUsed() const {
return transport_socket_->WasEverUsed();
}
-bool SSLServerSocketNSS::UsingTCPFastOpen() const {
- return transport_socket_->UsingTCPFastOpen();
-}
-
bool SSLServerSocketNSS::WasNpnNegotiated() const {
NOTIMPLEMENTED();
return false;
@@ -337,7 +430,8 @@ int SSLServerSocketNSS::InitializeSSLOptions() {
int rv;
- if (ssl_config_.require_client_cert) {
+ if (ssl_server_config_.client_cert_type ==
+ SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT) {
rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE);
if (rv != SECSuccess) {
LogFailedNSSFunction(net_log_, "SSL_OptionSet",
@@ -359,15 +453,15 @@ int SSLServerSocketNSS::InitializeSSLOptions() {
}
SSLVersionRange version_range;
- version_range.min = ssl_config_.version_min;
- version_range.max = ssl_config_.version_max;
+ version_range.min = ssl_server_config_.version_min;
+ version_range.max = ssl_server_config_.version_max;
rv = SSL_VersionRangeSet(nss_fd_, &version_range);
if (rv != SECSuccess) {
LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
return ERR_NO_SSL_VERSIONS_ENABLED;
}
- if (ssl_config_.require_ecdhe) {
+ if (ssl_server_config_.require_ecdhe) {
const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
@@ -384,8 +478,8 @@ int SSLServerSocketNSS::InitializeSSLOptions() {
}
for (std::vector<uint16_t>::const_iterator it =
- ssl_config_.disabled_cipher_suites.begin();
- it != ssl_config_.disabled_cipher_suites.end(); ++it) {
+ ssl_server_config_.disabled_cipher_suites.begin();
+ it != ssl_server_config_.disabled_cipher_suites.end(); ++it) {
// This will fail if the specified cipher is not implemented by NSS, but
// the failure is harmless.
SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
@@ -581,8 +675,7 @@ int SSLServerSocketNSS::BufferSend(void) {
memcpy(send_buffer->data(), buf1, len1);
memcpy(send_buffer->data() + len1, buf2, len2);
rv = transport_socket_->Write(
- send_buffer.get(),
- len,
+ send_buffer.get(), len,
base::Bind(&SSLServerSocketNSS::BufferSendComplete,
base::Unretained(this)));
if (rv == ERR_IO_PENDING) {
@@ -613,8 +706,7 @@ int SSLServerSocketNSS::BufferRecv(void) {
} else {
recv_buffer_ = new IOBuffer(nb);
rv = transport_socket_->Read(
- recv_buffer_.get(),
- nb,
+ recv_buffer_.get(), nb,
base::Bind(&SSLServerSocketNSS::BufferRecvComplete,
base::Unretained(this)));
if (rv == ERR_IO_PENDING) {
@@ -798,7 +890,7 @@ int SSLServerSocketNSS::DoHandshake() {
void SSLServerSocketNSS::DoHandshakeCallback(int rv) {
DCHECK_NE(rv, ERR_IO_PENDING);
- ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
+ base::ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
}
void SSLServerSocketNSS::DoReadCallback(int rv) {
@@ -807,7 +899,7 @@ void SSLServerSocketNSS::DoReadCallback(int rv) {
user_read_buf_ = NULL;
user_read_buf_len_ = 0;
- ResetAndReturn(&user_read_callback_).Run(rv);
+ base::ResetAndReturn(&user_read_callback_).Run(rv);
}
void SSLServerSocketNSS::DoWriteCallback(int rv) {
@@ -816,7 +908,7 @@ void SSLServerSocketNSS::DoWriteCallback(int rv) {
user_write_buf_ = NULL;
user_write_buf_len_ = 0;
- ResetAndReturn(&user_write_callback_).Run(rv);
+ base::ResetAndReturn(&user_write_callback_).Run(rv);
}
// static
@@ -837,8 +929,7 @@ SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
// static
// NSS calls this when handshake is completed.
// After the SSL handshake is finished we need to verify the certificate.
-void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
- void* arg) {
+void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket, void* arg) {
// TODO(hclam): Implement.
}
@@ -853,4 +944,39 @@ int SSLServerSocketNSS::Init() {
return OK;
}
+} // namespace
+
+scoped_ptr<SSLServerContext> CreateSSLServerContext(
+ X509Certificate* certificate,
+ const crypto::RSAPrivateKey& key,
+ const SSLServerConfig& ssl_server_config) {
+ return scoped_ptr<SSLServerContext>(
+ new SSLServerContextNSS(certificate, key, ssl_server_config));
+}
+
+SSLServerContextNSS::SSLServerContextNSS(
+ X509Certificate* certificate,
+ const crypto::RSAPrivateKey& key,
+ const SSLServerConfig& ssl_server_config)
+ : ssl_server_config_(ssl_server_config),
+ cert_(certificate),
+ key_(key.Copy()) {
+ CHECK(key_);
+}
+
+SSLServerContextNSS::~SSLServerContextNSS() {}
+
+scoped_ptr<SSLServerSocket> SSLServerContextNSS::CreateSSLServerSocket(
+ scoped_ptr<StreamSocket> socket) {
+ DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been"
+ << " called yet!";
+
+ return scoped_ptr<SSLServerSocket>(new SSLServerSocketNSS(
+ std::move(socket), cert_.get(), *key_, ssl_server_config_));
+}
+
+void EnableSSLServerSockets() {
+ g_nss_ssl_server_init_singleton.Get();
+}
+
} // namespace net
diff --git a/chromium/net/socket/ssl_server_socket_nss.h b/chromium/net/socket/ssl_server_socket_nss.h
index 6bdcf112f76..497d461767a 100644
--- a/chromium/net/socket/ssl_server_socket_nss.h
+++ b/chromium/net/socket/ssl_server_socket_nss.h
@@ -22,135 +22,25 @@
namespace net {
-class SSLServerSocketNSS : public SSLServerSocket {
+class SSLServerContextNSS : public SSLServerContext {
public:
- // See comments on CreateSSLServerSocket for details of how these
- // parameters are used.
- SSLServerSocketNSS(scoped_ptr<StreamSocket> socket,
- scoped_refptr<X509Certificate> certificate,
- const crypto::RSAPrivateKey& key,
- const SSLServerConfig& ssl_config);
- ~SSLServerSocketNSS() override;
+ SSLServerContextNSS(X509Certificate* certificate,
+ const crypto::RSAPrivateKey& key,
+ const SSLServerConfig& ssl_server_config);
+ ~SSLServerContextNSS() override;
- // SSLServerSocket interface.
- int Handshake(const CompletionCallback& callback) override;
-
- // SSLSocket interface.
- int ExportKeyingMaterial(const base::StringPiece& label,
- bool has_context,
- const base::StringPiece& context,
- unsigned char* out,
- unsigned int outlen) override;
- int GetTLSUniqueChannelBinding(std::string* out) override;
-
- // Socket interface (via StreamSocket).
- int Read(IOBuffer* buf,
- int buf_len,
- const CompletionCallback& callback) override;
- int Write(IOBuffer* buf,
- int buf_len,
- const CompletionCallback& callback) override;
- int SetReceiveBufferSize(int32_t size) override;
- int SetSendBufferSize(int32_t size) override;
-
- // StreamSocket implementation.
- int Connect(const CompletionCallback& callback) override;
- void Disconnect() override;
- bool IsConnected() const override;
- bool IsConnectedAndIdle() const override;
- int GetPeerAddress(IPEndPoint* address) const override;
- int GetLocalAddress(IPEndPoint* address) const override;
- const BoundNetLog& NetLog() const override;
- void SetSubresourceSpeculation() override;
- void SetOmniboxSpeculation() override;
- bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
- bool WasNpnNegotiated() 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;
+ scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
+ scoped_ptr<StreamSocket> socket) override;
private:
- enum State {
- STATE_NONE,
- STATE_HANDSHAKE,
- };
-
- int InitializeSSLOptions();
-
- void OnSendComplete(int result);
- void OnRecvComplete(int result);
- void OnHandshakeIOComplete(int result);
-
- int BufferSend();
- void BufferSendComplete(int result);
- int BufferRecv();
- void BufferRecvComplete(int result);
- bool DoTransportIO();
- int DoPayloadRead();
- int DoPayloadWrite();
-
- int DoHandshakeLoop(int last_io_result);
- int DoReadLoop(int result);
- int DoWriteLoop(int result);
- int DoHandshake();
- void DoHandshakeCallback(int result);
- void DoReadCallback(int result);
- void DoWriteCallback(int result);
-
- static SECStatus OwnAuthCertHandler(void* arg,
- PRFileDesc* socket,
- PRBool checksig,
- PRBool is_server);
- static void HandshakeCallback(PRFileDesc* socket, void* arg);
-
- int Init();
-
- // Members used to send and receive buffer.
- bool transport_send_busy_;
- bool transport_recv_busy_;
-
- scoped_refptr<IOBuffer> recv_buffer_;
-
- BoundNetLog net_log_;
-
- CompletionCallback user_handshake_callback_;
- CompletionCallback user_read_callback_;
- CompletionCallback user_write_callback_;
-
- // Used by Read function.
- scoped_refptr<IOBuffer> user_read_buf_;
- int user_read_buf_len_;
-
- // Used by Write function.
- scoped_refptr<IOBuffer> user_write_buf_;
- int user_write_buf_len_;
-
- // The NSS SSL state machine
- PRFileDesc* nss_fd_;
-
- // Buffers for the network end of the SSL state machine
- memio_Private* nss_bufs_;
-
- // StreamSocket for sending and receiving data.
- scoped_ptr<StreamSocket> transport_socket_;
-
// Options for the SSL socket.
- SSLServerConfig ssl_config_;
+ SSLServerConfig ssl_server_config_;
// Certificate for the server.
scoped_refptr<X509Certificate> cert_;
// Private key used by the server.
scoped_ptr<crypto::RSAPrivateKey> key_;
-
- State next_handshake_state_;
- bool completed_handshake_;
-
- DISALLOW_COPY_AND_ASSIGN(SSLServerSocketNSS);
};
} // namespace net
diff --git a/chromium/net/socket/ssl_server_socket_openssl.cc b/chromium/net/socket/ssl_server_socket_openssl.cc
index c3869cd865d..74f223131d8 100644
--- a/chromium/net/socket/ssl_server_socket_openssl.cc
+++ b/chromium/net/socket/ssl_server_socket_openssl.cc
@@ -15,48 +15,176 @@
#include "crypto/rsa_private_key.h"
#include "crypto/scoped_openssl_types.h"
#include "net/base/net_errors.h"
+#include "net/cert/cert_verify_result.h"
+#include "net/cert/client_cert_verifier.h"
+#include "net/cert/x509_util_openssl.h"
#include "net/ssl/openssl_ssl_util.h"
-#include "net/ssl/scoped_openssl_types.h"
+#include "net/ssl/ssl_connection_status_flags.h"
+#include "net/ssl/ssl_info.h"
#define GotoState(s) next_handshake_state_ = s
namespace net {
-void EnableSSLServerSockets() {
- // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit().
-}
+namespace {
+
+// Creates an X509Certificate out of the concatenation of |cert|, if non-null,
+// with |chain|.
+scoped_refptr<X509Certificate> CreateX509Certificate(X509* cert,
+ STACK_OF(X509) * chain) {
+ std::vector<base::StringPiece> der_chain;
+ base::StringPiece der_cert;
+ scoped_refptr<X509Certificate> client_cert;
+ if (cert) {
+ if (!x509_util::GetDER(cert, &der_cert))
+ return nullptr;
+ der_chain.push_back(der_cert);
+ }
-scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
- scoped_ptr<StreamSocket> socket,
- X509Certificate* certificate,
- const crypto::RSAPrivateKey& key,
- const SSLServerConfig& ssl_config) {
- crypto::EnsureOpenSSLInit();
- return scoped_ptr<SSLServerSocket>(new SSLServerSocketOpenSSL(
- std::move(socket), certificate, key, ssl_config));
-}
+ for (size_t i = 0; i < sk_X509_num(chain); ++i) {
+ X509* x = sk_X509_value(chain, i);
+ if (!x509_util::GetDER(x, &der_cert))
+ return nullptr;
+ der_chain.push_back(der_cert);
+ }
+
+ return X509Certificate::CreateFromDERCertChain(der_chain);
+}
+
+class SSLServerSocketOpenSSL : public SSLServerSocket {
+ public:
+ // See comments on CreateSSLServerSocket for details of how these
+ // parameters are used.
+ SSLServerSocketOpenSSL(scoped_ptr<StreamSocket> socket, SSL* ssl);
+ ~SSLServerSocketOpenSSL() override;
+
+ // SSLServerSocket interface.
+ int Handshake(const CompletionCallback& callback) override;
+
+ // SSLSocket interface.
+ int ExportKeyingMaterial(const base::StringPiece& label,
+ bool has_context,
+ const base::StringPiece& context,
+ unsigned char* out,
+ unsigned int outlen) override;
+
+ // Socket interface (via StreamSocket).
+ int Read(IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) override;
+ int Write(IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) override;
+ int SetReceiveBufferSize(int32_t size) override;
+ int SetSendBufferSize(int32_t size) override;
+
+ // StreamSocket implementation.
+ int Connect(const CompletionCallback& callback) override;
+ void Disconnect() override;
+ bool IsConnected() const override;
+ bool IsConnectedAndIdle() const override;
+ int GetPeerAddress(IPEndPoint* address) const override;
+ int GetLocalAddress(IPEndPoint* address) const override;
+ const BoundNetLog& NetLog() const override;
+ void SetSubresourceSpeculation() override;
+ void SetOmniboxSpeculation() override;
+ bool WasEverUsed() const override;
+ bool WasNpnNegotiated() 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;
+ static int CertVerifyCallback(X509_STORE_CTX* store_ctx, void* arg);
+
+ private:
+ enum State {
+ STATE_NONE,
+ STATE_HANDSHAKE,
+ };
+
+ void OnSendComplete(int result);
+ void OnRecvComplete(int result);
+ void OnHandshakeIOComplete(int result);
+
+ int BufferSend();
+ void BufferSendComplete(int result);
+ void TransportWriteComplete(int result);
+ int BufferRecv();
+ void BufferRecvComplete(int result);
+ int TransportReadComplete(int result);
+ bool DoTransportIO();
+ int DoPayloadRead();
+ int DoPayloadWrite();
+
+ int DoHandshakeLoop(int last_io_result);
+ int DoReadLoop(int result);
+ int DoWriteLoop(int result);
+ int DoHandshake();
+ void DoHandshakeCallback(int result);
+ void DoReadCallback(int result);
+ void DoWriteCallback(int result);
+
+ int Init();
+ void ExtractClientCert();
+
+ // Members used to send and receive buffer.
+ bool transport_send_busy_;
+ bool transport_recv_busy_;
+ bool transport_recv_eof_;
+
+ scoped_refptr<DrainableIOBuffer> send_buffer_;
+ scoped_refptr<IOBuffer> recv_buffer_;
+
+ BoundNetLog net_log_;
+
+ CompletionCallback user_handshake_callback_;
+ CompletionCallback user_read_callback_;
+ CompletionCallback user_write_callback_;
+
+ // Used by Read function.
+ scoped_refptr<IOBuffer> user_read_buf_;
+ int user_read_buf_len_;
+
+ // Used by Write function.
+ scoped_refptr<IOBuffer> user_write_buf_;
+ int user_write_buf_len_;
+
+ // Used by TransportWriteComplete() and TransportReadComplete() to signify an
+ // error writing to the transport socket. A value of OK indicates no error.
+ int transport_write_error_;
+
+ // OpenSSL stuff
+ SSL* ssl_;
+ BIO* transport_bio_;
+
+ // StreamSocket for sending and receiving data.
+ scoped_ptr<StreamSocket> transport_socket_;
+
+ // Certificate for the client.
+ scoped_refptr<X509Certificate> client_cert_;
+
+ State next_handshake_state_;
+ bool completed_handshake_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLServerSocketOpenSSL);
+};
SSLServerSocketOpenSSL::SSLServerSocketOpenSSL(
scoped_ptr<StreamSocket> transport_socket,
- scoped_refptr<X509Certificate> certificate,
- const crypto::RSAPrivateKey& key,
- const SSLServerConfig& ssl_config)
+ SSL* ssl)
: transport_send_busy_(false),
transport_recv_busy_(false),
transport_recv_eof_(false),
user_read_buf_len_(0),
user_write_buf_len_(0),
transport_write_error_(OK),
- ssl_(NULL),
+ ssl_(ssl),
transport_bio_(NULL),
transport_socket_(std::move(transport_socket)),
- ssl_config_(ssl_config),
- cert_(certificate),
- key_(key.Copy()),
next_handshake_state_(STATE_NONE),
- completed_handshake_(false) {
- CHECK(key_);
-}
+ completed_handshake_(false) {}
SSLServerSocketOpenSSL::~SSLServerSocketOpenSSL() {
if (ssl_) {
@@ -123,12 +251,8 @@ int SSLServerSocketOpenSSL::ExportKeyingMaterial(
return OK;
}
-int SSLServerSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
- NOTIMPLEMENTED();
- return ERR_NOT_IMPLEMENTED;
-}
-
-int SSLServerSocketOpenSSL::Read(IOBuffer* buf, int buf_len,
+int SSLServerSocketOpenSSL::Read(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) {
DCHECK(user_read_callback_.is_null());
DCHECK(user_handshake_callback_.is_null());
@@ -152,7 +276,8 @@ int SSLServerSocketOpenSSL::Read(IOBuffer* buf, int buf_len,
return rv;
}
-int SSLServerSocketOpenSSL::Write(IOBuffer* buf, int buf_len,
+int SSLServerSocketOpenSSL::Write(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) {
DCHECK(user_write_callback_.is_null());
DCHECK(!user_write_buf_);
@@ -227,10 +352,6 @@ bool SSLServerSocketOpenSSL::WasEverUsed() const {
return transport_socket_->WasEverUsed();
}
-bool SSLServerSocketOpenSSL::UsingTCPFastOpen() const {
- return transport_socket_->UsingTCPFastOpen();
-}
-
bool SSLServerSocketOpenSSL::WasNpnNegotiated() const {
NOTIMPLEMENTED();
return false;
@@ -242,8 +363,30 @@ NextProto SSLServerSocketOpenSSL::GetNegotiatedProtocol() const {
}
bool SSLServerSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
- NOTIMPLEMENTED();
- return false;
+ ssl_info->Reset();
+ if (!completed_handshake_)
+ return false;
+
+ ssl_info->cert = client_cert_;
+
+ const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
+ CHECK(cipher);
+ ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL);
+
+ SSLConnectionStatusSetCipherSuite(
+ static_cast<uint16_t>(SSL_CIPHER_get_id(cipher)),
+ &ssl_info->connection_status);
+ SSLConnectionStatusSetVersion(GetNetSSLVersion(ssl_),
+ &ssl_info->connection_status);
+
+ if (!SSL_get_secure_renegotiation_support(ssl_))
+ ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
+
+ ssl_info->handshake_type = SSL_session_reused(ssl_)
+ ? SSLInfo::HANDSHAKE_RESUME
+ : SSLInfo::HANDSHAKE_FULL;
+
+ return true;
}
void SSLServerSocketOpenSSL::GetConnectionAttempts(
@@ -323,8 +466,7 @@ int SSLServerSocketOpenSSL::BufferSend() {
}
int rv = transport_socket_->Write(
- send_buffer_.get(),
- send_buffer_->BytesRemaining(),
+ send_buffer_.get(), send_buffer_->BytesRemaining(),
base::Bind(&SSLServerSocketOpenSSL::BufferSendComplete,
base::Unretained(this)));
if (rv == ERR_IO_PENDING) {
@@ -396,8 +538,7 @@ int SSLServerSocketOpenSSL::BufferRecv() {
recv_buffer_ = new IOBuffer(max_write);
int rv = transport_socket_->Read(
- recv_buffer_.get(),
- max_write,
+ recv_buffer_.get(), max_write,
base::Bind(&SSLServerSocketOpenSSL::BufferRecvComplete,
base::Unretained(this)));
if (rv == ERR_IO_PENDING) {
@@ -566,11 +707,28 @@ int SSLServerSocketOpenSSL::DoHandshake() {
if (rv == 1) {
completed_handshake_ = true;
+ // The results of SSL_get_peer_certificate() must be explicitly freed.
+ ScopedX509 cert(SSL_get_peer_certificate(ssl_));
+ if (cert) {
+ // The caller does not take ownership of SSL_get_peer_cert_chain's
+ // results.
+ STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_);
+ client_cert_ = CreateX509Certificate(cert.get(), chain);
+ if (!client_cert_.get())
+ return ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT;
+ }
} else {
int ssl_error = SSL_get_error(ssl_, rv);
OpenSSLErrorInfo error_info;
net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info);
+ // This hack is necessary because the mapping of SSL error codes to
+ // net_errors assumes (correctly for client sockets, but erroneously for
+ // server sockets) that peer cert verification failure can only occur if
+ // the cert changed during a renego. crbug.com/570351
+ if (net_error == ERR_SSL_SERVER_CERT_CHANGED)
+ net_error = ERR_BAD_SSL_CLIENT_AUTH_CERT;
+
// If not done, stay in this state
if (net_error == ERR_IO_PENDING) {
GotoState(STATE_HANDSHAKE);
@@ -588,7 +746,7 @@ int SSLServerSocketOpenSSL::DoHandshake() {
void SSLServerSocketOpenSSL::DoHandshakeCallback(int rv) {
DCHECK_NE(rv, ERR_IO_PENDING);
- ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
+ base::ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
}
void SSLServerSocketOpenSSL::DoReadCallback(int rv) {
@@ -597,7 +755,7 @@ void SSLServerSocketOpenSSL::DoReadCallback(int rv) {
user_read_buf_ = NULL;
user_read_buf_len_ = 0;
- ResetAndReturn(&user_read_callback_).Run(rv);
+ base::ResetAndReturn(&user_read_callback_).Run(rv);
}
void SSLServerSocketOpenSSL::DoWriteCallback(int rv) {
@@ -606,21 +764,14 @@ void SSLServerSocketOpenSSL::DoWriteCallback(int rv) {
user_write_buf_ = NULL;
user_write_buf_len_ = 0;
- ResetAndReturn(&user_write_callback_).Run(rv);
+ base::ResetAndReturn(&user_write_callback_).Run(rv);
}
int SSLServerSocketOpenSSL::Init() {
- DCHECK(!ssl_);
DCHECK(!transport_bio_);
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
- ScopedSSL_CTX ssl_ctx(SSL_CTX_new(SSLv23_server_method()));
-
- if (ssl_config_.require_client_cert)
- SSL_CTX_set_verify(ssl_ctx.get(), SSL_VERIFY_PEER, NULL);
-
- ssl_ = SSL_new(ssl_ctx.get());
if (!ssl_)
return ERR_UNEXPECTED;
@@ -633,59 +784,122 @@ int SSLServerSocketOpenSSL::Init() {
SSL_set_bio(ssl_, ssl_bio, ssl_bio);
+ return OK;
+}
+
+// static
+int SSLServerSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx,
+ void* arg) {
+ ClientCertVerifier* verifier = reinterpret_cast<ClientCertVerifier*>(arg);
+ // If a verifier was not supplied, all certificates are accepted.
+ if (!verifier)
+ return 1;
+ STACK_OF(X509)* chain = store_ctx->untrusted;
+ scoped_refptr<X509Certificate> client_cert(
+ CreateX509Certificate(nullptr, chain));
+ if (!client_cert.get()) {
+ X509_STORE_CTX_set_error(store_ctx, X509_V_ERR_CERT_REJECTED);
+ return 0;
+ }
+ // Asynchronous completion of Verify is currently not supported.
+ // http://crbug.com/347402
+ // The API for Verify supports the parts needed for async completion
+ // but is currently expected to complete synchronously.
+ scoped_ptr<ClientCertVerifier::Request> ignore_async;
+ int res =
+ verifier->Verify(client_cert.get(), CompletionCallback(), &ignore_async);
+ DCHECK_NE(res, ERR_IO_PENDING);
+
+ if (res != OK) {
+ X509_STORE_CTX_set_error(store_ctx, X509_V_ERR_CERT_REJECTED);
+ return 0;
+ }
+ return 1;
+}
+
+} // namespace
+
+scoped_ptr<SSLServerContext> CreateSSLServerContext(
+ X509Certificate* certificate,
+ const crypto::RSAPrivateKey& key,
+ const SSLServerConfig& ssl_server_config) {
+ return scoped_ptr<SSLServerContext>(
+ new SSLServerContextOpenSSL(certificate, key, ssl_server_config));
+}
+
+SSLServerContextOpenSSL::SSLServerContextOpenSSL(
+ X509Certificate* certificate,
+ const crypto::RSAPrivateKey& key,
+ const SSLServerConfig& ssl_server_config)
+ : ssl_server_config_(ssl_server_config),
+ cert_(certificate),
+ key_(key.Copy()) {
+ CHECK(key_);
+ crypto::EnsureOpenSSLInit();
+ ssl_ctx_.reset(SSL_CTX_new(TLS_method()));
+ SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_SERVER);
+ uint8_t session_ctx_id = 0;
+ SSL_CTX_set_session_id_context(ssl_ctx_.get(), &session_ctx_id,
+ sizeof(session_ctx_id));
+
+ int verify_mode = 0;
+ switch (ssl_server_config_.client_cert_type) {
+ case SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT:
+ verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+ // Fall-through
+ case SSLServerConfig::ClientCertType::OPTIONAL_CLIENT_CERT:
+ verify_mode |= SSL_VERIFY_PEER;
+ SSL_CTX_set_verify(ssl_ctx_.get(), verify_mode, nullptr);
+ SSL_CTX_set_cert_verify_callback(
+ ssl_ctx_.get(), SSLServerSocketOpenSSL::CertVerifyCallback,
+ ssl_server_config_.client_cert_verifier);
+ break;
+ case SSLServerConfig::ClientCertType::NO_CLIENT_CERT:
+ break;
+ }
+
// Set certificate and private key.
DCHECK(cert_->os_cert_handle());
#if defined(USE_OPENSSL_CERTS)
- if (SSL_use_certificate(ssl_, cert_->os_cert_handle()) != 1) {
- LOG(ERROR) << "Cannot set certificate.";
- return ERR_UNEXPECTED;
- }
+ CHECK(SSL_CTX_use_certificate(ssl_ctx_.get(), cert_->os_cert_handle()));
#else
// Convert OSCertHandle to X509 structure.
std::string der_string;
- if (!X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string))
- return ERR_UNEXPECTED;
+ CHECK(X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string));
const unsigned char* der_string_array =
reinterpret_cast<const unsigned char*>(der_string.data());
ScopedX509 x509(d2i_X509(NULL, &der_string_array, der_string.length()));
- if (!x509)
- return ERR_UNEXPECTED;
+ CHECK(x509);
- // On success, SSL_use_certificate acquires a reference to |x509|.
- if (SSL_use_certificate(ssl_, x509.get()) != 1) {
- LOG(ERROR) << "Cannot set certificate.";
- return ERR_UNEXPECTED;
- }
+ // On success, SSL_CTX_use_certificate acquires a reference to |x509|.
+ CHECK(SSL_CTX_use_certificate(ssl_ctx_.get(), x509.get()));
#endif // USE_OPENSSL_CERTS
DCHECK(key_->key());
- if (SSL_use_PrivateKey(ssl_, key_->key()) != 1) {
- LOG(ERROR) << "Cannot set private key.";
- return ERR_UNEXPECTED;
- }
+ CHECK(SSL_CTX_use_PrivateKey(ssl_ctx_.get(), key_->key()));
- DCHECK_LT(SSL3_VERSION, ssl_config_.version_min);
- DCHECK_LT(SSL3_VERSION, ssl_config_.version_max);
- SSL_set_min_version(ssl_, ssl_config_.version_min);
- SSL_set_max_version(ssl_, ssl_config_.version_max);
+ DCHECK_LT(SSL3_VERSION, ssl_server_config_.version_min);
+ DCHECK_LT(SSL3_VERSION, ssl_server_config_.version_max);
+ SSL_CTX_set_min_version(ssl_ctx_.get(), ssl_server_config_.version_min);
+ SSL_CTX_set_max_version(ssl_ctx_.get(), ssl_server_config_.version_max);
// OpenSSL defaults some options to on, others to off. To avoid ambiguity,
// set everything we care about to an absolute value.
SslSetClearMask options;
options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true);
- SSL_set_options(ssl_, options.set_mask);
- SSL_clear_options(ssl_, options.clear_mask);
+ SSL_CTX_set_options(ssl_ctx_.get(), options.set_mask);
+ SSL_CTX_clear_options(ssl_ctx_.get(), options.clear_mask);
// Same as above, this time for the SSL mode.
SslSetClearMask mode;
mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true);
- SSL_set_mode(ssl_, mode.set_mask);
- SSL_clear_mode(ssl_, mode.clear_mask);
+ SSL_CTX_set_mode(ssl_ctx_.get(), mode.set_mask);
+ SSL_CTX_clear_mode(ssl_ctx_.get(), mode.clear_mask);
// See SSLServerConfig::disabled_cipher_suites for description of the suites
// disabled by default. Note that !SHA256 and !SHA384 only remove HMAC-SHA256
@@ -693,11 +907,11 @@ int SSLServerSocketOpenSSL::Init() {
// as the handshake hash.
std::string command("DEFAULT:!SHA256:!SHA384:!AESGCM+AES256:!aPSK");
- if (ssl_config_.require_ecdhe)
+ if (ssl_server_config_.require_ecdhe)
command.append(":!kRSA:!kDHE");
// Remove any disabled ciphers.
- for (uint16_t id : ssl_config_.disabled_cipher_suites) {
+ for (uint16_t id : ssl_server_config_.disabled_cipher_suites) {
const SSL_CIPHER* cipher = SSL_get_cipher_by_value(id);
if (cipher) {
command.append(":!");
@@ -705,14 +919,39 @@ int SSLServerSocketOpenSSL::Init() {
}
}
- int rv = SSL_set_cipher_list(ssl_, command.c_str());
+ int rv = SSL_CTX_set_cipher_list(ssl_ctx_.get(), command.c_str());
// If this fails (rv = 0) it means there are no ciphers enabled on this SSL.
// This will almost certainly result in the socket failing to complete the
// handshake at which point the appropriate error is bubbled up to the client.
LOG_IF(WARNING, rv != 1) << "SSL_set_cipher_list('" << command
<< "') returned " << rv;
- return OK;
+ if (ssl_server_config_.client_cert_type !=
+ SSLServerConfig::ClientCertType::NO_CLIENT_CERT &&
+ !ssl_server_config_.cert_authorities_.empty()) {
+ ScopedX509NameStack stack(sk_X509_NAME_new_null());
+ for (const auto& authority : ssl_server_config_.cert_authorities_) {
+ const uint8_t* name = reinterpret_cast<const uint8_t*>(authority.c_str());
+ const uint8_t* name_start = name;
+ ScopedX509_NAME subj(d2i_X509_NAME(nullptr, &name, authority.length()));
+ CHECK(subj && name == name_start + authority.length());
+ sk_X509_NAME_push(stack.get(), subj.release());
+ }
+ SSL_CTX_set_client_CA_list(ssl_ctx_.get(), stack.release());
+ }
+}
+
+SSLServerContextOpenSSL::~SSLServerContextOpenSSL() {}
+
+scoped_ptr<SSLServerSocket> SSLServerContextOpenSSL::CreateSSLServerSocket(
+ scoped_ptr<StreamSocket> socket) {
+ SSL* ssl = SSL_new(ssl_ctx_.get());
+ return scoped_ptr<SSLServerSocket>(
+ new SSLServerSocketOpenSSL(std::move(socket), ssl));
+}
+
+void EnableSSLServerSockets() {
+ // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit().
}
} // namespace net
diff --git a/chromium/net/socket/ssl_server_socket_openssl.h b/chromium/net/socket/ssl_server_socket_openssl.h
index fd7824970fc..3a9d9c85fc1 100644
--- a/chromium/net/socket/ssl_server_socket_openssl.h
+++ b/chromium/net/socket/ssl_server_socket_openssl.h
@@ -13,6 +13,7 @@
#include "net/base/io_buffer.h"
#include "net/log/net_log.h"
#include "net/socket/ssl_server_socket.h"
+#include "net/ssl/scoped_openssl_types.h"
#include "net/ssl/ssl_server_config.h"
// Avoid including misc OpenSSL headers, i.e.:
@@ -20,138 +21,33 @@
typedef struct bio_st BIO;
// <openssl/ssl.h>
typedef struct ssl_st SSL;
+typedef struct x509_store_ctx_st X509_STORE_CTX;
namespace net {
class SSLInfo;
-class SSLServerSocketOpenSSL : public SSLServerSocket {
+class SSLServerContextOpenSSL : public SSLServerContext {
public:
- // See comments on CreateSSLServerSocket for details of how these
- // parameters are used.
- SSLServerSocketOpenSSL(scoped_ptr<StreamSocket> socket,
- scoped_refptr<X509Certificate> certificate,
- const crypto::RSAPrivateKey& key,
- const SSLServerConfig& ssl_config);
- ~SSLServerSocketOpenSSL() override;
+ SSLServerContextOpenSSL(X509Certificate* certificate,
+ const crypto::RSAPrivateKey& key,
+ const SSLServerConfig& ssl_server_config);
+ ~SSLServerContextOpenSSL() override;
- // SSLServerSocket interface.
- int Handshake(const CompletionCallback& callback) override;
-
- // SSLSocket interface.
- int ExportKeyingMaterial(const base::StringPiece& label,
- bool has_context,
- const base::StringPiece& context,
- unsigned char* out,
- unsigned int outlen) override;
- int GetTLSUniqueChannelBinding(std::string* out) override;
-
- // Socket interface (via StreamSocket).
- int Read(IOBuffer* buf,
- int buf_len,
- const CompletionCallback& callback) override;
- int Write(IOBuffer* buf,
- int buf_len,
- const CompletionCallback& callback) override;
- int SetReceiveBufferSize(int32_t size) override;
- int SetSendBufferSize(int32_t size) override;
-
- // StreamSocket implementation.
- int Connect(const CompletionCallback& callback) override;
- void Disconnect() override;
- bool IsConnected() const override;
- bool IsConnectedAndIdle() const override;
- int GetPeerAddress(IPEndPoint* address) const override;
- int GetLocalAddress(IPEndPoint* address) const override;
- const BoundNetLog& NetLog() const override;
- void SetSubresourceSpeculation() override;
- void SetOmniboxSpeculation() override;
- bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
- bool WasNpnNegotiated() 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;
+ scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
+ scoped_ptr<StreamSocket> socket) override;
private:
- enum State {
- STATE_NONE,
- STATE_HANDSHAKE,
- };
-
- void OnSendComplete(int result);
- void OnRecvComplete(int result);
- void OnHandshakeIOComplete(int result);
-
- int BufferSend();
- void BufferSendComplete(int result);
- void TransportWriteComplete(int result);
- int BufferRecv();
- void BufferRecvComplete(int result);
- int TransportReadComplete(int result);
- bool DoTransportIO();
- int DoPayloadRead();
- int DoPayloadWrite();
-
- int DoHandshakeLoop(int last_io_result);
- int DoReadLoop(int result);
- int DoWriteLoop(int result);
- int DoHandshake();
- void DoHandshakeCallback(int result);
- void DoReadCallback(int result);
- void DoWriteCallback(int result);
-
- int Init();
-
- // Members used to send and receive buffer.
- bool transport_send_busy_;
- bool transport_recv_busy_;
- bool transport_recv_eof_;
-
- scoped_refptr<DrainableIOBuffer> send_buffer_;
- scoped_refptr<IOBuffer> recv_buffer_;
-
- BoundNetLog net_log_;
-
- CompletionCallback user_handshake_callback_;
- CompletionCallback user_read_callback_;
- CompletionCallback user_write_callback_;
-
- // Used by Read function.
- scoped_refptr<IOBuffer> user_read_buf_;
- int user_read_buf_len_;
-
- // Used by Write function.
- scoped_refptr<IOBuffer> user_write_buf_;
- int user_write_buf_len_;
-
- // Used by TransportWriteComplete() and TransportReadComplete() to signify an
- // error writing to the transport socket. A value of OK indicates no error.
- int transport_write_error_;
-
- // OpenSSL stuff
- SSL* ssl_;
- BIO* transport_bio_;
-
- // StreamSocket for sending and receiving data.
- scoped_ptr<StreamSocket> transport_socket_;
+ ScopedSSL_CTX ssl_ctx_;
// Options for the SSL socket.
- SSLServerConfig ssl_config_;
+ SSLServerConfig ssl_server_config_;
// Certificate for the server.
scoped_refptr<X509Certificate> cert_;
// Private key used by the server.
scoped_ptr<crypto::RSAPrivateKey> key_;
-
- State next_handshake_state_;
- bool completed_handshake_;
-
- DISALLOW_COPY_AND_ASSIGN(SSLServerSocketOpenSSL);
};
} // namespace net
diff --git a/chromium/net/socket/ssl_server_socket_unittest.cc b/chromium/net/socket/ssl_server_socket_unittest.cc
index ac2d44ec413..7327586d37c 100644
--- a/chromium/net/socket/ssl_server_socket_unittest.cc
+++ b/chromium/net/socket/ssl_server_socket_unittest.cc
@@ -20,6 +20,7 @@
#include <queue>
#include <utility>
+#include "base/callback_helpers.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
@@ -29,17 +30,22 @@
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
+#include "build/build_config.h"
#include "crypto/nss_util.h"
#include "crypto/rsa_private_key.h"
+#include "crypto/scoped_openssl_types.h"
+#include "crypto/signature_creator.h"
#include "net/base/address_list.h"
#include "net/base/completion_callback.h"
#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/test_data_directory.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/mock_cert_verifier.h"
+#include "net/cert/mock_client_cert_verifier.h"
#include "net/cert/x509_certificate.h"
#include "net/http/transport_security_state.h"
#include "net/log/net_log.h"
@@ -47,18 +53,34 @@
#include "net/socket/socket_test_util.h"
#include "net/socket/ssl_client_socket.h"
#include "net/socket/stream_socket.h"
+#include "net/ssl/scoped_openssl_types.h"
+#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_cipher_suite_names.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_info.h"
+#include "net/ssl/ssl_private_key.h"
#include "net/ssl/ssl_server_config.h"
+#include "net/ssl/test_ssl_private_key.h"
#include "net/test/cert_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
+#if defined(USE_OPENSSL)
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+#endif
+
namespace net {
namespace {
+const char kClientCertFileName[] = "client_1.pem";
+const char kClientPrivateKeyFileName[] = "client_1.pk8";
+const char kWrongClientCertFileName[] = "client_2.pem";
+const char kWrongClientPrivateKeyFileName[] = "client_2.pk8";
+const char kClientCertCAFileName[] = "client_1_ca.pem";
+
class FakeDataChannel {
public:
FakeDataChannel()
@@ -110,11 +132,24 @@ class FakeDataChannel {
// asynchronously, which is necessary to reproduce bug 127822.
void Close() {
closed_ = true;
+ if (!read_callback_.is_null()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&FakeDataChannel::DoReadCallback,
+ weak_factory_.GetWeakPtr()));
+ }
}
private:
void DoReadCallback() {
- if (read_callback_.is_null() || data_.empty())
+ if (read_callback_.is_null())
+ return;
+
+ if (closed_) {
+ base::ResetAndReturn(&read_callback_).Run(ERR_CONNECTION_CLOSED);
+ return;
+ }
+
+ if (data_.empty())
return;
int copied = PropagateData(read_buf_, read_buf_len_);
@@ -170,9 +205,7 @@ class FakeSocket : public StreamSocket {
public:
FakeSocket(FakeDataChannel* incoming_channel,
FakeDataChannel* outgoing_channel)
- : incoming_(incoming_channel),
- outgoing_(outgoing_channel) {
- }
+ : incoming_(incoming_channel), outgoing_(outgoing_channel) {}
~FakeSocket() override {}
@@ -208,14 +241,12 @@ class FakeSocket : public StreamSocket {
bool IsConnectedAndIdle() const override { return true; }
int GetPeerAddress(IPEndPoint* address) const override {
- IPAddressNumber ip_address(kIPv4AddressSize);
- *address = IPEndPoint(ip_address, 0 /*port*/);
+ *address = IPEndPoint(IPAddress::IPv4AllZeros(), 0 /*port*/);
return OK;
}
int GetLocalAddress(IPEndPoint* address) const override {
- IPAddressNumber ip_address(4);
- *address = IPEndPoint(ip_address, 0);
+ *address = IPEndPoint(IPAddress::IPv4AllZeros(), 0 /*port*/);
return OK;
}
@@ -226,8 +257,6 @@ class FakeSocket : public StreamSocket {
bool WasEverUsed() const override { return true; }
- bool UsingTCPFastOpen() const override { return false; }
-
bool WasNpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
@@ -302,37 +331,20 @@ class SSLServerSocketTest : public PlatformTest {
SSLServerSocketTest()
: socket_factory_(ClientSocketFactory::GetDefaultFactory()),
cert_verifier_(new MockCertVerifier()),
- transport_security_state_(new TransportSecurityState) {
- cert_verifier_->set_default_result(CERT_STATUS_AUTHORITY_INVALID);
- }
+ client_cert_verifier_(new MockClientCertVerifier()),
+ transport_security_state_(new TransportSecurityState) {}
- protected:
- void Initialize() {
- scoped_ptr<ClientSocketHandle> client_connection(new ClientSocketHandle);
- client_connection->SetSocket(
- scoped_ptr<StreamSocket>(new FakeSocket(&channel_1_, &channel_2_)));
- scoped_ptr<StreamSocket> server_socket(
- new FakeSocket(&channel_2_, &channel_1_));
-
- base::FilePath certs_dir(GetTestCertsDirectory());
+ void SetUp() override {
+ PlatformTest::SetUp();
- base::FilePath cert_path = certs_dir.AppendASCII("unittest.selfsigned.der");
- std::string cert_der;
- ASSERT_TRUE(base::ReadFileToString(cert_path, &cert_der));
-
- scoped_refptr<X509Certificate> cert =
- X509Certificate::CreateFromBytes(cert_der.data(), cert_der.size());
-
- base::FilePath key_path = certs_dir.AppendASCII("unittest.key.bin");
- std::string key_string;
- ASSERT_TRUE(base::ReadFileToString(key_path, &key_string));
- std::vector<uint8_t> key_vector(
- reinterpret_cast<const uint8_t*>(key_string.data()),
- reinterpret_cast<const uint8_t*>(key_string.data() +
- key_string.length()));
+ cert_verifier_->set_default_result(ERR_CERT_AUTHORITY_INVALID);
+ client_cert_verifier_->set_default_result(ERR_CERT_AUTHORITY_INVALID);
- scoped_ptr<crypto::RSAPrivateKey> private_key(
- crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vector));
+ server_cert_ =
+ ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der");
+ ASSERT_TRUE(server_cert_);
+ server_private_key_ = ReadTestKey("unittest.key.bin");
+ ASSERT_TRUE(server_private_key_);
client_ssl_config_.false_start_enabled = false;
client_ssl_config_.channel_id_enabled = false;
@@ -340,59 +352,152 @@ class SSLServerSocketTest : public PlatformTest {
// Certificate provided by the host doesn't need authority.
SSLConfig::CertAndStatus cert_and_status;
cert_and_status.cert_status = CERT_STATUS_AUTHORITY_INVALID;
- cert_and_status.der_cert = cert_der;
+ std::string server_cert_der;
+ ASSERT_TRUE(X509Certificate::GetDEREncoded(server_cert_->os_cert_handle(),
+ &server_cert_der));
+ cert_and_status.der_cert = server_cert_der;
client_ssl_config_.allowed_bad_certs.push_back(cert_and_status);
+ }
+
+ protected:
+ void CreateContext() {
+ client_socket_.reset();
+ server_socket_.reset();
+ channel_1_.reset();
+ channel_2_.reset();
+ server_context_.reset();
+ server_context_ = CreateSSLServerContext(
+ server_cert_.get(), *server_private_key_, server_ssl_config_);
+ }
+
+ void CreateSockets() {
+ client_socket_.reset();
+ server_socket_.reset();
+ channel_1_.reset(new FakeDataChannel());
+ channel_2_.reset(new FakeDataChannel());
+ scoped_ptr<ClientSocketHandle> client_connection(new ClientSocketHandle);
+ client_connection->SetSocket(scoped_ptr<StreamSocket>(
+ new FakeSocket(channel_1_.get(), channel_2_.get())));
+ scoped_ptr<StreamSocket> server_socket(
+ new FakeSocket(channel_2_.get(), channel_1_.get()));
HostPortPair host_and_pair("unittest", 0);
SSLClientSocketContext context;
context.cert_verifier = cert_verifier_.get();
context.transport_security_state = transport_security_state_.get();
+
client_socket_ = socket_factory_->CreateSSLClientSocket(
std::move(client_connection), host_and_pair, client_ssl_config_,
context);
- server_socket_ = CreateSSLServerSocket(std::move(server_socket), cert.get(),
- *private_key, server_ssl_config_);
+ ASSERT_TRUE(client_socket_);
+
+ server_socket_ =
+ server_context_->CreateSSLServerSocket(std::move(server_socket));
+ ASSERT_TRUE(server_socket_);
}
- FakeDataChannel channel_1_;
- FakeDataChannel channel_2_;
+#if defined(USE_OPENSSL)
+ void ConfigureClientCertsForClient(const char* cert_file_name,
+ const char* private_key_file_name) {
+ client_ssl_config_.send_client_cert = true;
+ client_ssl_config_.client_cert =
+ ImportCertFromFile(GetTestCertsDirectory(), cert_file_name);
+ ASSERT_TRUE(client_ssl_config_.client_cert);
+
+ scoped_ptr<crypto::RSAPrivateKey> key = ReadTestKey(private_key_file_name);
+ ASSERT_TRUE(key);
+
+ client_ssl_config_.client_private_key = WrapOpenSSLPrivateKey(
+ crypto::ScopedEVP_PKEY(EVP_PKEY_up_ref(key->key())));
+ }
+
+ void ConfigureClientCertsForServer() {
+ server_ssl_config_.client_cert_type =
+ SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
+
+ ScopedX509NameStack cert_names(
+ SSL_load_client_CA_file(GetTestCertsDirectory()
+ .AppendASCII(kClientCertCAFileName)
+ .MaybeAsASCII()
+ .c_str()));
+ ASSERT_TRUE(cert_names);
+
+ for (size_t i = 0; i < sk_X509_NAME_num(cert_names.get()); ++i) {
+ uint8_t* str = nullptr;
+ int length = i2d_X509_NAME(sk_X509_NAME_value(cert_names.get(), i), &str);
+ ASSERT_LT(0, length);
+
+ server_ssl_config_.cert_authorities_.push_back(std::string(
+ reinterpret_cast<const char*>(str), static_cast<size_t>(length)));
+ OPENSSL_free(str);
+ }
+
+ scoped_refptr<X509Certificate> expected_client_cert(
+ ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName));
+ ASSERT_TRUE(expected_client_cert);
+
+ client_cert_verifier_->AddResultForCert(expected_client_cert.get(), OK);
+
+ server_ssl_config_.client_cert_verifier = client_cert_verifier_.get();
+ }
+
+ scoped_ptr<crypto::RSAPrivateKey> ReadTestKey(const base::StringPiece& name) {
+ base::FilePath certs_dir(GetTestCertsDirectory());
+ base::FilePath key_path = certs_dir.AppendASCII(name);
+ std::string key_string;
+ if (!base::ReadFileToString(key_path, &key_string))
+ return nullptr;
+ std::vector<uint8_t> key_vector(
+ reinterpret_cast<const uint8_t*>(key_string.data()),
+ reinterpret_cast<const uint8_t*>(key_string.data() +
+ key_string.length()));
+ scoped_ptr<crypto::RSAPrivateKey> key(
+ crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vector));
+ return key;
+ }
+#endif
+
+ scoped_ptr<FakeDataChannel> channel_1_;
+ scoped_ptr<FakeDataChannel> channel_2_;
SSLConfig client_ssl_config_;
SSLServerConfig server_ssl_config_;
scoped_ptr<SSLClientSocket> client_socket_;
scoped_ptr<SSLServerSocket> server_socket_;
ClientSocketFactory* socket_factory_;
scoped_ptr<MockCertVerifier> cert_verifier_;
+ scoped_ptr<MockClientCertVerifier> client_cert_verifier_;
scoped_ptr<TransportSecurityState> transport_security_state_;
+ scoped_ptr<SSLServerContext> server_context_;
+ scoped_ptr<crypto::RSAPrivateKey> server_private_key_;
+ scoped_refptr<X509Certificate> server_cert_;
};
// This test only executes creation of client and server sockets. This is to
// test that creation of sockets doesn't crash and have minimal code to run
// under valgrind in order to help debugging memory problems.
TEST_F(SSLServerSocketTest, Initialize) {
- Initialize();
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
}
// This test executes Connect() on SSLClientSocket and Handshake() on
// SSLServerSocket to make sure handshaking between the two sockets is
// completed successfully.
TEST_F(SSLServerSocketTest, Handshake) {
- Initialize();
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
- TestCompletionCallback connect_callback;
TestCompletionCallback handshake_callback;
-
int server_ret = server_socket_->Handshake(handshake_callback.callback());
- EXPECT_TRUE(server_ret == OK || server_ret == ERR_IO_PENDING);
+ TestCompletionCallback connect_callback;
int client_ret = client_socket_->Connect(connect_callback.callback());
- EXPECT_TRUE(client_ret == OK || client_ret == ERR_IO_PENDING);
- if (client_ret == ERR_IO_PENDING) {
- EXPECT_EQ(OK, connect_callback.WaitForResult());
- }
- if (server_ret == ERR_IO_PENDING) {
- EXPECT_EQ(OK, handshake_callback.WaitForResult());
- }
+ client_ret = connect_callback.GetResult(client_ret);
+ server_ret = handshake_callback.GetResult(server_ret);
+
+ ASSERT_EQ(OK, client_ret);
+ ASSERT_EQ(OK, server_ret);
// Make sure the cert status is expected.
SSLInfo ssl_info;
@@ -412,16 +517,363 @@ TEST_F(SSLServerSocketTest, Handshake) {
EXPECT_TRUE(is_aead);
}
-TEST_F(SSLServerSocketTest, DataTransfer) {
- Initialize();
+// NSS ports don't support client certificates and have a global session cache.
+#if defined(USE_OPENSSL)
+
+// This test makes sure the session cache is working.
+TEST_F(SSLServerSocketTest, HandshakeCached) {
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+
+ TestCompletionCallback handshake_callback;
+ int server_ret = server_socket_->Handshake(handshake_callback.callback());
TestCompletionCallback connect_callback;
+ int client_ret = client_socket_->Connect(connect_callback.callback());
+
+ client_ret = connect_callback.GetResult(client_ret);
+ server_ret = handshake_callback.GetResult(server_ret);
+
+ ASSERT_EQ(OK, client_ret);
+ ASSERT_EQ(OK, server_ret);
+
+ // Make sure the cert status is expected.
+ SSLInfo ssl_info;
+ ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info));
+ EXPECT_EQ(ssl_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
+ SSLInfo ssl_server_info;
+ ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info));
+ EXPECT_EQ(ssl_server_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
+
+ // Make sure the second connection is cached.
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+ TestCompletionCallback handshake_callback2;
+ int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());
+
+ TestCompletionCallback connect_callback2;
+ int client_ret2 = client_socket_->Connect(connect_callback2.callback());
+
+ client_ret2 = connect_callback2.GetResult(client_ret2);
+ server_ret2 = handshake_callback2.GetResult(server_ret2);
+
+ ASSERT_EQ(OK, client_ret2);
+ ASSERT_EQ(OK, server_ret2);
+
+ // Make sure the cert status is expected.
+ SSLInfo ssl_info2;
+ ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info2));
+ EXPECT_EQ(ssl_info2.handshake_type, SSLInfo::HANDSHAKE_RESUME);
+ SSLInfo ssl_server_info2;
+ ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info2));
+ EXPECT_EQ(ssl_server_info2.handshake_type, SSLInfo::HANDSHAKE_RESUME);
+}
+
+// This test makes sure the session cache separates out by server context.
+TEST_F(SSLServerSocketTest, HandshakeCachedContextSwitch) {
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+
TestCompletionCallback handshake_callback;
+ int server_ret = server_socket_->Handshake(handshake_callback.callback());
+
+ TestCompletionCallback connect_callback;
+ int client_ret = client_socket_->Connect(connect_callback.callback());
+
+ client_ret = connect_callback.GetResult(client_ret);
+ server_ret = handshake_callback.GetResult(server_ret);
+
+ ASSERT_EQ(OK, client_ret);
+ ASSERT_EQ(OK, server_ret);
+
+ // Make sure the cert status is expected.
+ SSLInfo ssl_info;
+ ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info));
+ EXPECT_EQ(ssl_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
+ SSLInfo ssl_server_info;
+ ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info));
+ EXPECT_EQ(ssl_server_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
+
+ // Make sure the second connection is NOT cached when using a new context.
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+
+ TestCompletionCallback handshake_callback2;
+ int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());
+
+ TestCompletionCallback connect_callback2;
+ int client_ret2 = client_socket_->Connect(connect_callback2.callback());
+
+ client_ret2 = connect_callback2.GetResult(client_ret2);
+ server_ret2 = handshake_callback2.GetResult(server_ret2);
+
+ ASSERT_EQ(OK, client_ret2);
+ ASSERT_EQ(OK, server_ret2);
+
+ // Make sure the cert status is expected.
+ SSLInfo ssl_info2;
+ ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info2));
+ EXPECT_EQ(ssl_info2.handshake_type, SSLInfo::HANDSHAKE_FULL);
+ SSLInfo ssl_server_info2;
+ ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info2));
+ EXPECT_EQ(ssl_server_info2.handshake_type, SSLInfo::HANDSHAKE_FULL);
+}
+
+// This test executes Connect() on SSLClientSocket and Handshake() on
+// SSLServerSocket to make sure handshaking between the two sockets is
+// completed successfully, using client certificate.
+TEST_F(SSLServerSocketTest, HandshakeWithClientCert) {
+ scoped_refptr<X509Certificate> client_cert =
+ ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
+ ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForClient(
+ kClientCertFileName, kClientPrivateKeyFileName));
+ ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+
+ TestCompletionCallback handshake_callback;
+ int server_ret = server_socket_->Handshake(handshake_callback.callback());
+
+ TestCompletionCallback connect_callback;
+ int client_ret = client_socket_->Connect(connect_callback.callback());
+
+ client_ret = connect_callback.GetResult(client_ret);
+ server_ret = handshake_callback.GetResult(server_ret);
+
+ ASSERT_EQ(OK, client_ret);
+ ASSERT_EQ(OK, server_ret);
+
+ // Make sure the cert status is expected.
+ SSLInfo ssl_info;
+ client_socket_->GetSSLInfo(&ssl_info);
+ EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, ssl_info.cert_status);
+ server_socket_->GetSSLInfo(&ssl_info);
+ ASSERT_TRUE(ssl_info.cert.get());
+ EXPECT_TRUE(client_cert->Equals(ssl_info.cert.get()));
+}
+
+// This test executes Connect() on SSLClientSocket and Handshake() twice on
+// SSLServerSocket to make sure handshaking between the two sockets is
+// completed successfully, using client certificate. The second connection is
+// expected to succeed through the session cache.
+TEST_F(SSLServerSocketTest, HandshakeWithClientCertCached) {
+ scoped_refptr<X509Certificate> client_cert =
+ ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
+ ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForClient(
+ kClientCertFileName, kClientPrivateKeyFileName));
+ ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+
+ TestCompletionCallback handshake_callback;
+ int server_ret = server_socket_->Handshake(handshake_callback.callback());
+
+ TestCompletionCallback connect_callback;
+ int client_ret = client_socket_->Connect(connect_callback.callback());
+
+ client_ret = connect_callback.GetResult(client_ret);
+ server_ret = handshake_callback.GetResult(server_ret);
+
+ ASSERT_EQ(OK, client_ret);
+ ASSERT_EQ(OK, server_ret);
+
+ // Make sure the cert status is expected.
+ SSLInfo ssl_info;
+ ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info));
+ EXPECT_EQ(ssl_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
+ SSLInfo ssl_server_info;
+ ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info));
+ ASSERT_TRUE(ssl_server_info.cert.get());
+ EXPECT_TRUE(client_cert->Equals(ssl_server_info.cert.get()));
+ EXPECT_EQ(ssl_server_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
+ server_socket_->Disconnect();
+ client_socket_->Disconnect();
+
+ // Create the connection again.
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+ TestCompletionCallback handshake_callback2;
+ int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());
+
+ TestCompletionCallback connect_callback2;
+ int client_ret2 = client_socket_->Connect(connect_callback2.callback());
+
+ client_ret2 = connect_callback2.GetResult(client_ret2);
+ server_ret2 = handshake_callback2.GetResult(server_ret2);
+
+ ASSERT_EQ(OK, client_ret2);
+ ASSERT_EQ(OK, server_ret2);
+
+ // Make sure the cert status is expected.
+ SSLInfo ssl_info2;
+ ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info2));
+ EXPECT_EQ(ssl_info2.handshake_type, SSLInfo::HANDSHAKE_RESUME);
+ SSLInfo ssl_server_info2;
+ ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info2));
+ ASSERT_TRUE(ssl_server_info2.cert.get());
+ EXPECT_TRUE(client_cert->Equals(ssl_server_info2.cert.get()));
+ EXPECT_EQ(ssl_server_info2.handshake_type, SSLInfo::HANDSHAKE_RESUME);
+}
+
+TEST_F(SSLServerSocketTest, HandshakeWithClientCertRequiredNotSupplied) {
+ ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+ // Use the default setting for the client socket, which is to not send
+ // a client certificate. This will cause the client to receive an
+ // ERR_SSL_CLIENT_AUTH_CERT_NEEDED error, and allow for inspecting the
+ // requested cert_authorities from the CertificateRequest sent by the
+ // server.
+
+ TestCompletionCallback handshake_callback;
+ int server_ret = server_socket_->Handshake(handshake_callback.callback());
+
+ TestCompletionCallback connect_callback;
+ EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
+ connect_callback.GetResult(
+ client_socket_->Connect(connect_callback.callback())));
+
+ scoped_refptr<SSLCertRequestInfo> request_info = new SSLCertRequestInfo();
+ client_socket_->GetSSLCertRequestInfo(request_info.get());
+
+ // Check that the authority name that arrived in the CertificateRequest
+ // handshake message is as expected.
+ scoped_refptr<X509Certificate> client_cert =
+ ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
+ ASSERT_TRUE(client_cert);
+ EXPECT_TRUE(client_cert->IsIssuedByEncoded(request_info->cert_authorities));
+
+ client_socket_->Disconnect();
+
+ EXPECT_EQ(ERR_FAILED, handshake_callback.GetResult(server_ret));
+}
+
+TEST_F(SSLServerSocketTest, HandshakeWithClientCertRequiredNotSuppliedCached) {
+ ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+ // Use the default setting for the client socket, which is to not send
+ // a client certificate. This will cause the client to receive an
+ // ERR_SSL_CLIENT_AUTH_CERT_NEEDED error, and allow for inspecting the
+ // requested cert_authorities from the CertificateRequest sent by the
+ // server.
+
+ TestCompletionCallback handshake_callback;
+ int server_ret = server_socket_->Handshake(handshake_callback.callback());
+
+ TestCompletionCallback connect_callback;
+ EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
+ connect_callback.GetResult(
+ client_socket_->Connect(connect_callback.callback())));
+
+ scoped_refptr<SSLCertRequestInfo> request_info = new SSLCertRequestInfo();
+ client_socket_->GetSSLCertRequestInfo(request_info.get());
+
+ // Check that the authority name that arrived in the CertificateRequest
+ // handshake message is as expected.
+ scoped_refptr<X509Certificate> client_cert =
+ ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
+ ASSERT_TRUE(client_cert);
+ EXPECT_TRUE(client_cert->IsIssuedByEncoded(request_info->cert_authorities));
+
+ client_socket_->Disconnect();
+
+ EXPECT_EQ(ERR_FAILED, handshake_callback.GetResult(server_ret));
+ server_socket_->Disconnect();
+
+ // Below, check that the cache didn't store the result of a failed handshake.
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+ TestCompletionCallback handshake_callback2;
+ int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());
+
+ TestCompletionCallback connect_callback2;
+ EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
+ connect_callback2.GetResult(
+ client_socket_->Connect(connect_callback2.callback())));
+
+ scoped_refptr<SSLCertRequestInfo> request_info2 = new SSLCertRequestInfo();
+ client_socket_->GetSSLCertRequestInfo(request_info2.get());
+
+ // Check that the authority name that arrived in the CertificateRequest
+ // handshake message is as expected.
+ EXPECT_TRUE(client_cert->IsIssuedByEncoded(request_info2->cert_authorities));
+
+ client_socket_->Disconnect();
+
+ EXPECT_EQ(ERR_FAILED, handshake_callback2.GetResult(server_ret2));
+}
+
+TEST_F(SSLServerSocketTest, HandshakeWithWrongClientCertSupplied) {
+ scoped_refptr<X509Certificate> client_cert =
+ ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
+ ASSERT_TRUE(client_cert);
+
+ ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForClient(
+ kWrongClientCertFileName, kWrongClientPrivateKeyFileName));
+ ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+
+ TestCompletionCallback handshake_callback;
+ int server_ret = server_socket_->Handshake(handshake_callback.callback());
+
+ TestCompletionCallback connect_callback;
+ int client_ret = client_socket_->Connect(connect_callback.callback());
+
+ EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
+ connect_callback.GetResult(client_ret));
+ EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
+ handshake_callback.GetResult(server_ret));
+}
+
+TEST_F(SSLServerSocketTest, HandshakeWithWrongClientCertSuppliedCached) {
+ scoped_refptr<X509Certificate> client_cert =
+ ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
+ ASSERT_TRUE(client_cert);
+
+ ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForClient(
+ kWrongClientCertFileName, kWrongClientPrivateKeyFileName));
+ ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+
+ TestCompletionCallback handshake_callback;
+ int server_ret = server_socket_->Handshake(handshake_callback.callback());
+
+ TestCompletionCallback connect_callback;
+ int client_ret = client_socket_->Connect(connect_callback.callback());
+
+ EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
+ connect_callback.GetResult(client_ret));
+ EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
+ handshake_callback.GetResult(server_ret));
+
+ client_socket_->Disconnect();
+ server_socket_->Disconnect();
+
+ // Below, check that the cache didn't store the result of a failed handshake.
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
+ TestCompletionCallback handshake_callback2;
+ int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());
+
+ TestCompletionCallback connect_callback2;
+ int client_ret2 = client_socket_->Connect(connect_callback2.callback());
+
+ EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
+ connect_callback2.GetResult(client_ret2));
+ EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
+ handshake_callback2.GetResult(server_ret2));
+}
+#endif // defined(USE_OPENSSL)
+
+TEST_F(SSLServerSocketTest, DataTransfer) {
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
// Establish connection.
+ TestCompletionCallback connect_callback;
int client_ret = client_socket_->Connect(connect_callback.callback());
ASSERT_TRUE(client_ret == OK || client_ret == ERR_IO_PENDING);
+ TestCompletionCallback handshake_callback;
int server_ret = server_socket_->Handshake(handshake_callback.callback());
ASSERT_TRUE(server_ret == OK || server_ret == ERR_IO_PENDING);
@@ -439,8 +891,8 @@ TEST_F(SSLServerSocketTest, DataTransfer) {
// Write then read.
TestCompletionCallback write_callback;
TestCompletionCallback read_callback;
- server_ret = server_socket_->Write(
- write_buf.get(), write_buf->size(), write_callback.callback());
+ server_ret = server_socket_->Write(write_buf.get(), write_buf->size(),
+ write_callback.callback());
EXPECT_TRUE(server_ret > 0 || server_ret == ERR_IO_PENDING);
client_ret = client_socket_->Read(
read_buf.get(), read_buf->BytesRemaining(), read_callback.callback());
@@ -469,8 +921,8 @@ TEST_F(SSLServerSocketTest, DataTransfer) {
server_ret = server_socket_->Read(
read_buf.get(), read_buf->BytesRemaining(), read_callback.callback());
EXPECT_TRUE(server_ret > 0 || server_ret == ERR_IO_PENDING);
- client_ret = client_socket_->Write(
- write_buf.get(), write_buf->size(), write_callback.callback());
+ client_ret = client_socket_->Write(write_buf.get(), write_buf->size(),
+ write_callback.callback());
EXPECT_TRUE(client_ret > 0 || client_ret == ERR_IO_PENDING);
server_ret = read_callback.GetResult(server_ret);
@@ -497,15 +949,15 @@ TEST_F(SSLServerSocketTest, DataTransfer) {
// the client's Write() call should not cause an infinite loop.
// NOTE: this is a test for SSLClientSocket rather than SSLServerSocket.
TEST_F(SSLServerSocketTest, ClientWriteAfterServerClose) {
- Initialize();
-
- TestCompletionCallback connect_callback;
- TestCompletionCallback handshake_callback;
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
// Establish connection.
+ TestCompletionCallback connect_callback;
int client_ret = client_socket_->Connect(connect_callback.callback());
ASSERT_TRUE(client_ret == OK || client_ret == ERR_IO_PENDING);
+ TestCompletionCallback handshake_callback;
int server_ret = server_socket_->Handshake(handshake_callback.callback());
ASSERT_TRUE(server_ret == OK || server_ret == ERR_IO_PENDING);
@@ -521,9 +973,8 @@ TEST_F(SSLServerSocketTest, ClientWriteAfterServerClose) {
// socket won't return ERR_IO_PENDING. This ensures that the client
// will call Read() on the transport socket again.
TestCompletionCallback write_callback;
-
- server_ret = server_socket_->Write(
- write_buf.get(), write_buf->size(), write_callback.callback());
+ server_ret = server_socket_->Write(write_buf.get(), write_buf->size(),
+ write_callback.callback());
EXPECT_TRUE(server_ret > 0 || server_ret == ERR_IO_PENDING);
server_ret = write_callback.GetResult(server_ret);
@@ -532,8 +983,8 @@ TEST_F(SSLServerSocketTest, ClientWriteAfterServerClose) {
server_socket_->Disconnect();
// The client writes some data. This should not cause an infinite loop.
- client_ret = client_socket_->Write(
- write_buf.get(), write_buf->size(), write_callback.callback());
+ client_ret = client_socket_->Write(write_buf.get(), write_buf->size(),
+ write_callback.callback());
EXPECT_TRUE(client_ret > 0 || client_ret == ERR_IO_PENDING);
client_ret = write_callback.GetResult(client_ret);
@@ -549,14 +1000,14 @@ TEST_F(SSLServerSocketTest, ClientWriteAfterServerClose) {
// after connecting them, and verifies that the results match.
// This test will fail if False Start is enabled (see crbug.com/90208).
TEST_F(SSLServerSocketTest, ExportKeyingMaterial) {
- Initialize();
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
TestCompletionCallback connect_callback;
- TestCompletionCallback handshake_callback;
-
int client_ret = client_socket_->Connect(connect_callback.callback());
ASSERT_TRUE(client_ret == OK || client_ret == ERR_IO_PENDING);
+ TestCompletionCallback handshake_callback;
int server_ret = server_socket_->Handshake(handshake_callback.callback());
ASSERT_TRUE(server_ret == OK || server_ret == ERR_IO_PENDING);
@@ -571,23 +1022,20 @@ TEST_F(SSLServerSocketTest, ExportKeyingMaterial) {
const char kKeyingLabel[] = "EXPERIMENTAL-server-socket-test";
const char kKeyingContext[] = "";
unsigned char server_out[kKeyingMaterialSize];
- int rv = server_socket_->ExportKeyingMaterial(kKeyingLabel,
- false, kKeyingContext,
- server_out, sizeof(server_out));
+ int rv = server_socket_->ExportKeyingMaterial(
+ kKeyingLabel, false, kKeyingContext, server_out, sizeof(server_out));
ASSERT_EQ(OK, rv);
unsigned char client_out[kKeyingMaterialSize];
- rv = client_socket_->ExportKeyingMaterial(kKeyingLabel,
- false, kKeyingContext,
+ rv = client_socket_->ExportKeyingMaterial(kKeyingLabel, false, kKeyingContext,
client_out, sizeof(client_out));
ASSERT_EQ(OK, rv);
EXPECT_EQ(0, memcmp(server_out, client_out, sizeof(server_out)));
const char kKeyingLabelBad[] = "EXPERIMENTAL-server-socket-test-bad";
unsigned char client_bad[kKeyingMaterialSize];
- rv = client_socket_->ExportKeyingMaterial(kKeyingLabelBad,
- false, kKeyingContext,
- client_bad, sizeof(client_bad));
+ rv = client_socket_->ExportKeyingMaterial(
+ kKeyingLabelBad, false, kKeyingContext, client_bad, sizeof(client_bad));
ASSERT_EQ(rv, OK);
EXPECT_NE(0, memcmp(server_out, client_bad, sizeof(server_out)));
}
@@ -613,12 +1061,13 @@ TEST_F(SSLServerSocketTest, RequireEcdheFlag) {
// Require ECDHE on the server.
server_ssl_config_.require_ecdhe = true;
- Initialize();
+ ASSERT_NO_FATAL_FAILURE(CreateContext());
+ ASSERT_NO_FATAL_FAILURE(CreateSockets());
TestCompletionCallback connect_callback;
- TestCompletionCallback handshake_callback;
-
int client_ret = client_socket_->Connect(connect_callback.callback());
+
+ TestCompletionCallback handshake_callback;
int server_ret = server_socket_->Handshake(handshake_callback.callback());
client_ret = connect_callback.GetResult(client_ret);
diff --git a/chromium/net/socket/ssl_socket.h b/chromium/net/socket/ssl_socket.h
index 5f60e800b5b..bd813c35fea 100644
--- a/chromium/net/socket/ssl_socket.h
+++ b/chromium/net/socket/ssl_socket.h
@@ -26,9 +26,6 @@ public:
const base::StringPiece& context,
unsigned char* out,
unsigned int outlen) = 0;
-
- // Stores the the tls-unique channel binding (see RFC 5929) in |*out|.
- virtual int GetTLSUniqueChannelBinding(std::string* out) = 0;
};
} // namespace net
diff --git a/chromium/net/socket/stream_socket.h b/chromium/net/socket/stream_socket.h
index e2f9d3cd790..98efcdafb9b 100644
--- a/chromium/net/socket/stream_socket.h
+++ b/chromium/net/socket/stream_socket.h
@@ -79,11 +79,6 @@ class NET_EXPORT_PRIVATE StreamSocket : public Socket {
// Write() methods had been called, not the underlying transport's.
virtual bool WasEverUsed() const = 0;
- // TODO(jri): Clean up -- remove this method.
- // Returns true if the underlying transport socket is using TCP FastOpen.
- // TCP FastOpen is an experiment with sending data in the TCP SYN packet.
- virtual bool UsingTCPFastOpen() const = 0;
-
// TODO(jri): Clean up -- rename to a more general EnableAutoConnectOnWrite.
// Enables use of TCP FastOpen for the underlying transport socket.
virtual void EnableTCPFastOpenIfSupported() {}
diff --git a/chromium/net/socket/tcp_client_socket.cc b/chromium/net/socket/tcp_client_socket.cc
index 700fa1c1655..56238ba0d12 100644
--- a/chromium/net/socket/tcp_client_socket.cc
+++ b/chromium/net/socket/tcp_client_socket.cc
@@ -14,7 +14,6 @@
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
namespace net {
@@ -240,10 +239,6 @@ bool TCPClientSocket::WasEverUsed() const {
return use_history_.was_used_to_convey_data();
}
-bool TCPClientSocket::UsingTCPFastOpen() const {
- return socket_->UsingTCPFastOpen();
-}
-
void TCPClientSocket::EnableTCPFastOpenIfSupported() {
socket_->EnableTCPFastOpenIfSupported();
}
diff --git a/chromium/net/socket/tcp_client_socket.h b/chromium/net/socket/tcp_client_socket.h
index 73ee62bfeb2..ae6083fed6c 100644
--- a/chromium/net/socket/tcp_client_socket.h
+++ b/chromium/net/socket/tcp_client_socket.h
@@ -51,7 +51,6 @@ class NET_EXPORT TCPClientSocket : public StreamSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
void EnableTCPFastOpenIfSupported() override;
bool WasNpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
diff --git a/chromium/net/socket/tcp_client_socket_unittest.cc b/chromium/net/socket/tcp_client_socket_unittest.cc
index ce0c53559f8..1c39719f59d 100644
--- a/chromium/net/socket/tcp_client_socket_unittest.cc
+++ b/chromium/net/socket/tcp_client_socket_unittest.cc
@@ -8,9 +8,9 @@
#include "net/socket/tcp_client_socket.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/test_completion_callback.h"
#include "net/socket/tcp_server_socket.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -22,8 +22,7 @@ namespace {
// Try binding a socket to loopback interface and verify that we can
// still connect to a server on the same interface.
TEST(TCPClientSocketTest, BindLoopbackToLoopback) {
- IPAddressNumber lo_address;
- ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &lo_address));
+ IPAddress lo_address = IPAddress::IPv4Localhost();
TCPServerSocket server(NULL, NetLog::Source());
ASSERT_EQ(OK, server.Listen(IPEndPoint(lo_address, 0), 1));
@@ -60,14 +59,11 @@ TEST(TCPClientSocketTest, BindLoopbackToLoopback) {
// Try to bind socket to the loopback interface and connect to an
// external address, verify that connection fails.
TEST(TCPClientSocketTest, BindLoopbackToExternal) {
- IPAddressNumber external_ip;
- ASSERT_TRUE(ParseIPLiteralToNumber("72.14.213.105", &external_ip));
+ IPAddress external_ip(72, 14, 213, 105);
TCPClientSocket socket(AddressList::CreateFromIPAddress(external_ip, 80),
NULL, NetLog::Source());
- IPAddressNumber lo_address;
- ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &lo_address));
- EXPECT_EQ(OK, socket.Bind(IPEndPoint(lo_address, 0)));
+ EXPECT_EQ(OK, socket.Bind(IPEndPoint(IPAddress::IPv4Localhost(), 0)));
TestCompletionCallback connect_callback;
int result = socket.Connect(connect_callback.callback());
@@ -82,10 +78,9 @@ TEST(TCPClientSocketTest, BindLoopbackToExternal) {
// Bind a socket to the IPv4 loopback interface and try to connect to
// the IPv6 loopback interface, verify that connection fails.
TEST(TCPClientSocketTest, BindLoopbackToIPv6) {
- IPAddressNumber ipv6_lo_ip;
- ASSERT_TRUE(ParseIPLiteralToNumber("::1", &ipv6_lo_ip));
TCPServerSocket server(NULL, NetLog::Source());
- int listen_result = server.Listen(IPEndPoint(ipv6_lo_ip, 0), 1);
+ int listen_result =
+ server.Listen(IPEndPoint(IPAddress::IPv6Localhost(), 0), 1);
if (listen_result != OK) {
LOG(ERROR) << "Failed to listen on ::1 - probably because IPv6 is disabled."
" Skipping the test";
@@ -96,9 +91,7 @@ TEST(TCPClientSocketTest, BindLoopbackToIPv6) {
ASSERT_EQ(OK, server.GetLocalAddress(&server_address));
TCPClientSocket socket(AddressList(server_address), NULL, NetLog::Source());
- IPAddressNumber ipv4_lo_ip;
- ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ipv4_lo_ip));
- EXPECT_EQ(OK, socket.Bind(IPEndPoint(ipv4_lo_ip, 0)));
+ EXPECT_EQ(OK, socket.Bind(IPEndPoint(IPAddress::IPv4Localhost(), 0)));
TestCompletionCallback connect_callback;
int result = socket.Connect(connect_callback.callback());
diff --git a/chromium/net/socket/tcp_server_socket.h b/chromium/net/socket/tcp_server_socket.h
index ea2021c921e..7611ff911b9 100644
--- a/chromium/net/socket/tcp_server_socket.h
+++ b/chromium/net/socket/tcp_server_socket.h
@@ -5,7 +5,6 @@
#ifndef NET_SOCKET_TCP_SERVER_SOCKET_H_
#define NET_SOCKET_TCP_SERVER_SOCKET_H_
-#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/ip_endpoint.h"
@@ -16,7 +15,7 @@
namespace net {
-class NET_EXPORT_PRIVATE TCPServerSocket : public ServerSocket {
+class NET_EXPORT TCPServerSocket : public ServerSocket {
public:
TCPServerSocket(NetLog* net_log, const NetLog::Source& source);
~TCPServerSocket() override;
diff --git a/chromium/net/socket/tcp_server_socket_unittest.cc b/chromium/net/socket/tcp_server_socket_unittest.cc
index 133c8073188..651cd6964ad 100644
--- a/chromium/net/socket/tcp_server_socket_unittest.cc
+++ b/chromium/net/socket/tcp_server_socket_unittest.cc
@@ -12,6 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
@@ -31,16 +32,14 @@ class TCPServerSocketTest : public PlatformTest {
}
void SetUpIPv4() {
- IPEndPoint address;
- ParseAddress("127.0.0.1", 0, &address);
+ IPEndPoint address(IPAddress::IPv4Localhost(), 0);
ASSERT_EQ(OK, socket_.Listen(address, kListenBacklog));
ASSERT_EQ(OK, socket_.GetLocalAddress(&local_address_));
}
void SetUpIPv6(bool* success) {
*success = false;
- IPEndPoint address;
- ParseAddress("::1", 0, &address);
+ IPEndPoint address(IPAddress::IPv6Localhost(), 0);
if (socket_.Listen(address, kListenBacklog) != 0) {
LOG(ERROR) << "Failed to listen on ::1 - probably because IPv6 is "
"disabled. Skipping the test";
@@ -50,16 +49,6 @@ class TCPServerSocketTest : public PlatformTest {
*success = true;
}
- void ParseAddress(const std::string& ip_str,
- uint16_t port,
- IPEndPoint* address) {
- IPAddressNumber ip_number;
- bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
- if (!rv)
- return;
- *address = IPEndPoint(ip_number, port);
- }
-
static IPEndPoint GetPeerAddress(StreamSocket* socket) {
IPEndPoint address;
EXPECT_EQ(OK, socket->GetPeerAddress(&address));
diff --git a/chromium/net/socket/tcp_socket.cc b/chromium/net/socket/tcp_socket.cc
new file mode 100644
index 00000000000..ad5250620d0
--- /dev/null
+++ b/chromium/net/socket/tcp_socket.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/socket/tcp_socket.h"
+
+#include "build/build_config.h"
+
+#if defined(OS_POSIX)
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#elif defined(OS_WIN)
+#include <winsock2.h>
+#endif
+
+namespace net {
+
+bool SetTCPNoDelay(SocketDescriptor socket, bool no_delay) {
+#if defined(OS_POSIX)
+ int on = no_delay ? 1 : 0;
+#elif defined(OS_WIN)
+ BOOL on = no_delay ? TRUE : FALSE;
+#endif
+ return setsockopt(socket, IPPROTO_TCP, TCP_NODELAY,
+ reinterpret_cast<const char*>(&on), sizeof(on)) == 0;
+}
+
+} // namespace net
diff --git a/chromium/net/socket/tcp_socket.h b/chromium/net/socket/tcp_socket.h
index 58797bb0851..319a6b261d0 100644
--- a/chromium/net/socket/tcp_socket.h
+++ b/chromium/net/socket/tcp_socket.h
@@ -7,6 +7,7 @@
#include "build/build_config.h"
#include "net/base/net_export.h"
+#include "net/socket/socket_descriptor.h"
#if defined(OS_WIN)
#include "net/socket/tcp_socket_win.h"
@@ -39,6 +40,39 @@ bool IsTCPFastOpenUserEnabled();
// Not thread safe. Must be called during initialization/startup only.
NET_EXPORT void CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled);
+// This function enables/disables buffering in the kernel. By default, on Linux,
+// TCP sockets will wait up to 200ms for more data to complete a packet before
+// transmitting. After calling this function, the kernel will not wait. See
+// TCP_NODELAY in `man 7 tcp`.
+//
+// For Windows:
+//
+// The Nagle implementation on Windows is governed by RFC 896. The idea
+// behind Nagle is to reduce small packets on the network. When Nagle is
+// enabled, if a partial packet has been sent, the TCP stack will disallow
+// further *partial* packets until an ACK has been received from the other
+// side. Good applications should always strive to send as much data as
+// possible and avoid partial-packet sends. However, in most real world
+// applications, there are edge cases where this does not happen, and two
+// partial packets may be sent back to back. For a browser, it is NEVER
+// a benefit to delay for an RTT before the second packet is sent.
+//
+// As a practical example in Chromium today, consider the case of a small
+// POST. I have verified this:
+// Client writes 649 bytes of header (partial packet #1)
+// Client writes 50 bytes of POST data (partial packet #2)
+// In the above example, with Nagle, a RTT delay is inserted between these
+// two sends due to nagle. RTTs can easily be 100ms or more. The best
+// fix is to make sure that for POSTing data, we write as much data as
+// possible and minimize partial packets. We will fix that. But disabling
+// Nagle also ensure we don't run into this delay in other edge cases.
+// See also:
+// http://technet.microsoft.com/en-us/library/bb726981.aspx
+//
+// This function returns true if it succeeds to set the TCP_NODELAY option,
+// otherwise returns false.
+NET_EXPORT_PRIVATE bool SetTCPNoDelay(SocketDescriptor socket, bool no_delay);
+
} // namespace net
#endif // NET_SOCKET_TCP_SOCKET_H_
diff --git a/chromium/net/socket/tcp_socket_posix.cc b/chromium/net/socket/tcp_socket_posix.cc
index 0546e6075a5..95fe6b5bd01 100644
--- a/chromium/net/socket/tcp_socket_posix.cc
+++ b/chromium/net/socket/tcp_socket_posix.cc
@@ -44,16 +44,6 @@ bool g_tcp_fastopen_user_enabled = false;
// True if TCP FastOpen connect-with-write has failed at least once.
bool g_tcp_fastopen_has_failed = false;
-// SetTCPNoDelay turns on/off buffering in the kernel. By default, TCP sockets
-// will wait up to 200ms for more data to complete a packet before transmitting.
-// After calling this function, the kernel will not wait. See TCP_NODELAY in
-// `man 7 tcp`.
-bool SetTCPNoDelay(int fd, bool no_delay) {
- int on = no_delay ? 1 : 0;
- int error = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
- return error == 0;
-}
-
// SetTCPKeepAlive sets SO_KEEPALIVE.
bool SetTCPKeepAlive(int fd, bool enable, int delay) {
// Enabling TCP keepalives is the same on all platforms.
@@ -443,10 +433,6 @@ void TCPSocketPosix::Close() {
tcp_fastopen_status_ = TCP_FASTOPEN_STATUS_UNKNOWN;
}
-bool TCPSocketPosix::UsingTCPFastOpen() const {
- return use_tcp_fastopen_;
-}
-
void TCPSocketPosix::EnableTCPFastOpenIfSupported() {
if (!IsTCPFastOpenSupported())
return;
@@ -455,7 +441,7 @@ void TCPSocketPosix::EnableTCPFastOpenIfSupported() {
// This check conservatively avoids middleboxes that may blackhole
// TCP FastOpen SYN+Data packets; on such a failure, subsequent sockets
// should not use TCP FastOpen.
- if(!g_tcp_fastopen_has_failed)
+ if (!g_tcp_fastopen_has_failed)
use_tcp_fastopen_ = true;
else
tcp_fastopen_status_ = TCP_FASTOPEN_PREVIOUSLY_FAILED;
diff --git a/chromium/net/socket/tcp_socket_posix.h b/chromium/net/socket/tcp_socket_posix.h
index 8d53caf567f..98849e45a19 100644
--- a/chromium/net/socket/tcp_socket_posix.h
+++ b/chromium/net/socket/tcp_socket_posix.h
@@ -73,8 +73,6 @@ class NET_EXPORT TCPSocketPosix {
void Close();
- // Setter/Getter methods for TCP FastOpen socket option.
- bool UsingTCPFastOpen() const;
void EnableTCPFastOpenIfSupported();
bool IsValid() const;
diff --git a/chromium/net/socket/tcp_socket_unittest.cc b/chromium/net/socket/tcp_socket_unittest.cc
index ade3ee7fd8d..15f93551673 100644
--- a/chromium/net/socket/tcp_socket_unittest.cc
+++ b/chromium/net/socket/tcp_socket_unittest.cc
@@ -14,6 +14,7 @@
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
+#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/sockaddr_storage.h"
#include "net/base/test_completion_callback.h"
@@ -32,22 +33,17 @@ class TCPSocketTest : public PlatformTest {
}
void SetUpListenIPv4() {
- IPEndPoint address;
- ParseAddress("127.0.0.1", 0, &address);
-
ASSERT_EQ(OK, socket_.Open(ADDRESS_FAMILY_IPV4));
- ASSERT_EQ(OK, socket_.Bind(address));
+ ASSERT_EQ(OK, socket_.Bind(IPEndPoint(IPAddress::IPv4Localhost(), 0)));
ASSERT_EQ(OK, socket_.Listen(kListenBacklog));
ASSERT_EQ(OK, socket_.GetLocalAddress(&local_address_));
}
void SetUpListenIPv6(bool* success) {
*success = false;
- IPEndPoint address;
- ParseAddress("::1", 0, &address);
if (socket_.Open(ADDRESS_FAMILY_IPV6) != OK ||
- socket_.Bind(address) != OK ||
+ socket_.Bind(IPEndPoint(IPAddress::IPv6Localhost(), 0)) != OK ||
socket_.Listen(kListenBacklog) != OK) {
LOG(ERROR) << "Failed to listen on ::1 - probably because IPv6 is "
"disabled. Skipping the test";
@@ -57,16 +53,6 @@ class TCPSocketTest : public PlatformTest {
*success = true;
}
- void ParseAddress(const std::string& ip_str,
- uint16_t port,
- IPEndPoint* address) {
- IPAddressNumber ip_number;
- bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
- if (!rv)
- return;
- *address = IPEndPoint(ip_number, port);
- }
-
void TestAcceptAsync() {
TestCompletionCallback accept_callback;
scoped_ptr<TCPSocket> accepted_socket;
@@ -138,8 +124,7 @@ TEST_F(TCPSocketTest, AcceptForAdoptedListenSocket) {
SOCKET existing_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ASSERT_EQ(OK, socket_.AdoptListenSocket(existing_socket));
- IPEndPoint address;
- ParseAddress("127.0.0.1", 0, &address);
+ IPEndPoint address(IPAddress::IPv4Localhost(), 0);
SockaddrStorage storage;
ASSERT_TRUE(address.ToSockAddr(storage.addr, &storage.addr_len));
ASSERT_EQ(0, bind(existing_socket, storage.addr, storage.addr_len));
diff --git a/chromium/net/socket/tcp_socket_win.cc b/chromium/net/socket/tcp_socket_win.cc
index a9998e2c0c6..0d11a0d7443 100644
--- a/chromium/net/socket/tcp_socket_win.cc
+++ b/chromium/net/socket/tcp_socket_win.cc
@@ -8,12 +8,13 @@
#include <errno.h>
#include <mstcpip.h>
+#include <utility>
+
#include "base/callback_helpers.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/profiler/scoped_tracker.h"
-#include "base/win/windows_version.h"
#include "net/base/address_list.h"
#include "net/base/connection_type_histograms.h"
#include "net/base/io_buffer.h"
@@ -50,36 +51,6 @@ int SetSocketSendBufferSize(SOCKET socket, int32_t size) {
}
// Disable Nagle.
-// The Nagle implementation on windows is governed by RFC 896. The idea
-// behind Nagle is to reduce small packets on the network. When Nagle is
-// enabled, if a partial packet has been sent, the TCP stack will disallow
-// further *partial* packets until an ACK has been received from the other
-// side. Good applications should always strive to send as much data as
-// possible and avoid partial-packet sends. However, in most real world
-// applications, there are edge cases where this does not happen, and two
-// partial packets may be sent back to back. For a browser, it is NEVER
-// a benefit to delay for an RTT before the second packet is sent.
-//
-// As a practical example in Chromium today, consider the case of a small
-// POST. I have verified this:
-// Client writes 649 bytes of header (partial packet #1)
-// Client writes 50 bytes of POST data (partial packet #2)
-// In the above example, with Nagle, a RTT delay is inserted between these
-// two sends due to nagle. RTTs can easily be 100ms or more. The best
-// fix is to make sure that for POSTing data, we write as much data as
-// possible and minimize partial packets. We will fix that. But disabling
-// Nagle also ensure we don't run into this delay in other edge cases.
-// See also:
-// http://technet.microsoft.com/en-us/library/bb726981.aspx
-bool DisableNagle(SOCKET socket, bool disable) {
- BOOL val = disable ? TRUE : FALSE;
- int rv = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY,
- reinterpret_cast<const char*>(&val),
- sizeof(val));
- DCHECK(!rv) << "Could not disable nagle";
- return rv == 0;
-}
-
// Enable TCP Keep-Alive to prevent NAT routers from timing out TCP
// connections. See http://crbug.com/27400 for details.
bool SetTCPKeepAlive(SOCKET socket, BOOL enable, int delay_secs) {
@@ -580,23 +551,7 @@ int TCPSocketWin::SetDefaultOptionsForServer() {
}
void TCPSocketWin::SetDefaultOptionsForClient() {
- // Increase the socket buffer sizes from the default sizes for WinXP. In
- // performance testing, there is substantial benefit by increasing from 8KB
- // to 64KB.
- // See also:
- // http://support.microsoft.com/kb/823764/EN-US
- // On Vista, if we manually set these sizes, Vista turns off its receive
- // window auto-tuning feature.
- // http://blogs.msdn.com/wndp/archive/2006/05/05/Winhec-blog-tcpip-2.aspx
- // Since Vista's auto-tune is better than any static value we can could set,
- // only change these on pre-vista machines.
- if (base::win::GetVersion() < base::win::VERSION_VISTA) {
- const int32_t kSocketBufferSize = 64 * 1024;
- SetSocketReceiveBufferSize(socket_, kSocketBufferSize);
- SetSocketSendBufferSize(socket_, kSocketBufferSize);
- }
-
- DisableNagle(socket_, true);
+ SetTCPNoDelay(socket_, /*no_delay=*/true);
SetTCPKeepAlive(socket_, true, kTCPKeepAliveSeconds);
}
@@ -641,7 +596,7 @@ bool TCPSocketWin::SetKeepAlive(bool enable, int delay) {
}
bool TCPSocketWin::SetNoDelay(bool no_delay) {
- return DisableNagle(socket_, no_delay);
+ return SetTCPNoDelay(socket_, no_delay);
}
void TCPSocketWin::Close() {
@@ -751,7 +706,7 @@ int TCPSocketWin::AcceptInternal(scoped_ptr<TCPSocketWin>* socket,
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result);
return adopt_result;
}
- *socket = tcp_socket.Pass();
+ *socket = std::move(tcp_socket);
*address = ip_end_point;
net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT,
CreateNetLogIPEndPointCallback(&ip_end_point));
diff --git a/chromium/net/socket/tcp_socket_win.h b/chromium/net/socket/tcp_socket_win.h
index f24ffb801b7..1786af11ada 100644
--- a/chromium/net/socket/tcp_socket_win.h
+++ b/chromium/net/socket/tcp_socket_win.h
@@ -81,9 +81,7 @@ class NET_EXPORT TCPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe),
void Close();
- // Setter/Getter methods for TCP FastOpen socket option.
- // NOOPs since TCP FastOpen is not implemented in Windows.
- bool UsingTCPFastOpen() const { return false; }
+ // NOOP since TCP FastOpen is not implemented in Windows.
void EnableTCPFastOpenIfSupported() {}
bool IsValid() const { return socket_ != INVALID_SOCKET; }
diff --git a/chromium/net/socket/transport_client_socket_pool.cc b/chromium/net/socket/transport_client_socket_pool.cc
index 0949193ff2e..dbc701a9386 100644
--- a/chromium/net/socket/transport_client_socket_pool.cc
+++ b/chromium/net/socket/transport_client_socket_pool.cc
@@ -16,6 +16,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 "base/values.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
@@ -61,11 +62,9 @@ static base::LazyInstance<base::TimeTicks>::Leaky
TransportSocketParams::TransportSocketParams(
const HostPortPair& host_port_pair,
bool disable_resolver_cache,
- bool ignore_limits,
const OnHostResolutionCallback& host_resolution_callback,
CombineConnectAndWritePolicy combine_connect_and_write_if_supported)
: destination_(host_port_pair),
- ignore_limits_(ignore_limits),
host_resolution_callback_(host_resolution_callback),
combine_connect_and_write_(combine_connect_and_write_if_supported) {
if (disable_resolver_cache)
@@ -117,6 +116,7 @@ int TransportConnectJobHelper::DoResolveHost(RequestPriority priority,
int TransportConnectJobHelper::DoResolveHostComplete(
int result,
const BoundNetLog& net_log) {
+ TRACE_EVENT0("net", "TransportConnectJobHelper::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.
@@ -196,6 +196,7 @@ base::TimeDelta TransportConnectJobHelper::HistogramDuration(
TransportConnectJob::TransportConnectJob(
const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const scoped_refptr<TransportSocketParams>& params,
base::TimeDelta timeout_duration,
ClientSocketFactory* client_socket_factory,
@@ -205,6 +206,7 @@ TransportConnectJob::TransportConnectJob(
: ConnectJob(group_name,
timeout_duration,
priority,
+ respect_limits,
delegate,
BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
helper_(params, client_socket_factory, host_resolver, &connect_timing_),
@@ -487,15 +489,10 @@ TransportClientSocketPool::TransportConnectJobFactory::NewConnectJob(
const std::string& group_name,
const PoolBase::Request& request,
ConnectJob::Delegate* delegate) const {
- return scoped_ptr<ConnectJob>(
- new TransportConnectJob(group_name,
- request.priority(),
- request.params(),
- ConnectionTimeout(),
- client_socket_factory_,
- host_resolver_,
- delegate,
- net_log_));
+ return scoped_ptr<ConnectJob>(new TransportConnectJob(
+ group_name, request.priority(), request.respect_limits(),
+ request.params(), ConnectionTimeout(), client_socket_factory_,
+ host_resolver_, delegate, net_log_));
}
base::TimeDelta
@@ -523,20 +520,20 @@ TransportClientSocketPool::TransportClientSocketPool(
TransportClientSocketPool::~TransportClientSocketPool() {}
-int TransportClientSocketPool::RequestSocket(
- const std::string& group_name,
- const void* params,
- RequestPriority priority,
- ClientSocketHandle* handle,
- const CompletionCallback& callback,
- const BoundNetLog& net_log) {
+int TransportClientSocketPool::RequestSocket(const std::string& group_name,
+ const void* params,
+ RequestPriority priority,
+ RespectLimits respect_limits,
+ ClientSocketHandle* handle,
+ const CompletionCallback& callback,
+ const BoundNetLog& net_log) {
const scoped_refptr<TransportSocketParams>* casted_params =
static_cast<const scoped_refptr<TransportSocketParams>*>(params);
NetLogTcpClientSocketPoolRequestedSocket(net_log, casted_params);
- return base_.RequestSocket(group_name, *casted_params, priority, handle,
- callback, net_log);
+ return base_.RequestSocket(group_name, *casted_params, priority,
+ respect_limits, handle, callback, net_log);
}
void TransportClientSocketPool::NetLogTcpClientSocketPoolRequestedSocket(
diff --git a/chromium/net/socket/transport_client_socket_pool.h b/chromium/net/socket/transport_client_socket_pool.h
index 07a67b515a5..085fbb91e86 100644
--- a/chromium/net/socket/transport_client_socket_pool.h
+++ b/chromium/net/socket/transport_client_socket_pool.h
@@ -50,12 +50,10 @@ class NET_EXPORT_PRIVATE TransportSocketParams
TransportSocketParams(
const HostPortPair& host_port_pair,
bool disable_resolver_cache,
- bool ignore_limits,
const OnHostResolutionCallback& host_resolution_callback,
CombineConnectAndWritePolicy combine_connect_and_write);
const HostResolver::RequestInfo& destination() const { return destination_; }
- bool ignore_limits() const { return ignore_limits_; }
const OnHostResolutionCallback& host_resolution_callback() const {
return host_resolution_callback_;
}
@@ -69,7 +67,6 @@ class NET_EXPORT_PRIVATE TransportSocketParams
~TransportSocketParams();
HostResolver::RequestInfo destination_;
- bool ignore_limits_;
const OnHostResolutionCallback host_resolution_callback_;
CombineConnectAndWritePolicy combine_connect_and_write_;
@@ -158,6 +155,7 @@ class NET_EXPORT_PRIVATE TransportConnectJob : public ConnectJob {
public:
TransportConnectJob(const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const scoped_refptr<TransportSocketParams>& params,
base::TimeDelta timeout_duration,
ClientSocketFactory* client_socket_factory,
@@ -241,6 +239,7 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool : public ClientSocketPool {
int RequestSocket(const std::string& group_name,
const void* resolve_info,
RequestPriority priority,
+ RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) override;
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 0140c255e18..190b1c57579 100644
--- a/chromium/net/socket/transport_client_socket_pool_test_util.cc
+++ b/chromium/net/socket/transport_client_socket_pool_test_util.cc
@@ -15,10 +15,10 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/load_timing_info.h"
#include "net/base/load_timing_info_test_util.h"
-#include "net/base/net_util.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/ssl_client_socket.h"
#include "net/udp/datagram_client_socket.h"
@@ -28,10 +28,10 @@ namespace net {
namespace {
-IPAddressNumber ParseIP(const std::string& ip) {
- IPAddressNumber number;
- CHECK(ParseIPLiteralToNumber(ip, &number));
- return number;
+IPAddress ParseIP(const std::string& ip) {
+ IPAddress address;
+ CHECK(address.AssignFromIPLiteral(ip));
+ return address;
}
// A StreamSocket which connects synchronously and successfully.
@@ -40,8 +40,7 @@ class MockConnectClientSocket : public StreamSocket {
MockConnectClientSocket(const AddressList& addrlist, net::NetLog* net_log)
: connected_(false),
addrlist_(addrlist),
- net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
- use_tcp_fastopen_(false) {}
+ net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {}
// StreamSocket implementation.
int Connect(const CompletionCallback& callback) override {
@@ -70,8 +69,7 @@ class MockConnectClientSocket : public StreamSocket {
void SetSubresourceSpeculation() override {}
void SetOmniboxSpeculation() override {}
bool WasEverUsed() const override { return false; }
- void EnableTCPFastOpenIfSupported() override { use_tcp_fastopen_ = true; }
- bool UsingTCPFastOpen() const override { return use_tcp_fastopen_; }
+ void EnableTCPFastOpenIfSupported() override {}
bool WasNpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
@@ -103,7 +101,6 @@ class MockConnectClientSocket : public StreamSocket {
bool connected_;
const AddressList addrlist_;
BoundNetLog net_log_;
- bool use_tcp_fastopen_;
DISALLOW_COPY_AND_ASSIGN(MockConnectClientSocket);
};
@@ -112,8 +109,7 @@ class MockFailingClientSocket : public StreamSocket {
public:
MockFailingClientSocket(const AddressList& addrlist, net::NetLog* net_log)
: addrlist_(addrlist),
- net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
- use_tcp_fastopen_(false) {}
+ net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {}
// StreamSocket implementation.
int Connect(const CompletionCallback& callback) override {
@@ -135,8 +131,7 @@ class MockFailingClientSocket : public StreamSocket {
void SetSubresourceSpeculation() override {}
void SetOmniboxSpeculation() override {}
bool WasEverUsed() const override { return false; }
- void EnableTCPFastOpenIfSupported() override { use_tcp_fastopen_ = true; }
- bool UsingTCPFastOpen() const override { return use_tcp_fastopen_; }
+ void EnableTCPFastOpenIfSupported() override {}
bool WasNpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
@@ -170,7 +165,6 @@ class MockFailingClientSocket : public StreamSocket {
private:
const AddressList addrlist_;
BoundNetLog net_log_;
- bool use_tcp_fastopen_;
DISALLOW_COPY_AND_ASSIGN(MockFailingClientSocket);
};
@@ -186,7 +180,6 @@ class MockTriggerableClientSocket : public StreamSocket {
is_connected_(false),
addrlist_(addrlist),
net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
- use_tcp_fastopen_(false),
weak_factory_(this) {}
// Call this method to get a closure which will trigger the connect callback
@@ -264,8 +257,7 @@ class MockTriggerableClientSocket : public StreamSocket {
void SetSubresourceSpeculation() override {}
void SetOmniboxSpeculation() override {}
bool WasEverUsed() const override { return false; }
- void EnableTCPFastOpenIfSupported() override { use_tcp_fastopen_ = true; }
- bool UsingTCPFastOpen() const override { return use_tcp_fastopen_; }
+ void EnableTCPFastOpenIfSupported() override {}
bool WasNpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
@@ -308,7 +300,6 @@ class MockTriggerableClientSocket : public StreamSocket {
const AddressList addrlist_;
BoundNetLog net_log_;
CompletionCallback callback_;
- bool use_tcp_fastopen_;
ConnectionAttempts connection_attempts_;
base::WeakPtrFactory<MockTriggerableClientSocket> weak_factory_;
diff --git a/chromium/net/socket/transport_client_socket_pool_unittest.cc b/chromium/net/socket/transport_client_socket_pool_unittest.cc
index dab0d076398..c8702f70fb2 100644
--- a/chromium/net/socket/transport_client_socket_pool_unittest.cc
+++ b/chromium/net/socket/transport_client_socket_pool_unittest.cc
@@ -10,11 +10,11 @@
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/platform_thread.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/load_timing_info.h"
#include "net/base/load_timing_info_test_util.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
#include "net/log/test_net_log.h"
@@ -43,7 +43,6 @@ class TransportClientSocketPoolTest : public testing::Test {
new TransportSocketParams(
HostPortPair("www.google.com", 80),
false,
- false,
OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)),
host_resolver_(new MockHostResolver),
@@ -61,18 +60,18 @@ class TransportClientSocketPoolTest : public testing::Test {
}
scoped_refptr<TransportSocketParams> CreateParamsForTCPFastOpen() {
- return new TransportSocketParams(HostPortPair("www.google.com", 80),
- false, false, OnHostResolutionCallback(),
- TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DESIRED);
+ return new TransportSocketParams(
+ HostPortPair("www.google.com", 80), false, OnHostResolutionCallback(),
+ TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DESIRED);
}
int StartRequest(const std::string& group_name, RequestPriority priority) {
scoped_refptr<TransportSocketParams> params(new TransportSocketParams(
- HostPortPair("www.google.com", 80), false, false,
- OnHostResolutionCallback(),
+ HostPortPair("www.google.com", 80), false, OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
return test_base_.StartRequestUsingPool(
- &pool_, group_name, priority, params);
+ &pool_, group_name, priority, ClientSocketPool::RespectLimits::ENABLED,
+ params);
}
int GetOrderOfRequest(size_t index) {
@@ -105,15 +104,13 @@ class TransportClientSocketPoolTest : public testing::Test {
};
TEST(TransportConnectJobTest, MakeAddrListStartWithIPv4) {
- IPAddressNumber ip_number;
- ASSERT_TRUE(ParseIPLiteralToNumber("192.168.1.1", &ip_number));
- IPEndPoint addrlist_v4_1(ip_number, 80);
- ASSERT_TRUE(ParseIPLiteralToNumber("192.168.1.2", &ip_number));
- IPEndPoint addrlist_v4_2(ip_number, 80);
- ASSERT_TRUE(ParseIPLiteralToNumber("2001:4860:b006::64", &ip_number));
- IPEndPoint addrlist_v6_1(ip_number, 80);
- ASSERT_TRUE(ParseIPLiteralToNumber("2001:4860:b006::66", &ip_number));
- IPEndPoint addrlist_v6_2(ip_number, 80);
+ IPEndPoint addrlist_v4_1(IPAddress(192, 168, 1, 1), 80);
+ IPEndPoint addrlist_v4_2(IPAddress(192, 168, 1, 2), 80);
+ IPAddress ip_address;
+ ASSERT_TRUE(ip_address.AssignFromIPLiteral("2001:4860:b006::64"));
+ IPEndPoint addrlist_v6_1(ip_address, 80);
+ ASSERT_TRUE(ip_address.AssignFromIPLiteral("2001:4860:b006::66"));
+ IPEndPoint addrlist_v6_2(ip_address, 80);
AddressList addrlist;
@@ -178,8 +175,9 @@ TEST(TransportConnectJobTest, MakeAddrListStartWithIPv4) {
TEST_F(TransportClientSocketPoolTest, Basic) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("a", params_, LOW, callback.callback(), &pool_,
- BoundNetLog());
+ int rv =
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -199,8 +197,9 @@ TEST_F(TransportClientSocketPoolTest, SetResolvePriorityOnInit) {
TestCompletionCallback callback;
ClientSocketHandle handle;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a", params_, priority, callback.callback(), &pool_,
- BoundNetLog()));
+ handle.Init("a", params_, priority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
EXPECT_EQ(priority, host_resolver_->last_request_priority());
}
}
@@ -211,11 +210,12 @@ TEST_F(TransportClientSocketPoolTest, InitHostResolutionFailure) {
ClientSocketHandle handle;
HostPortPair host_port_pair("unresolvable.host.name", 80);
scoped_refptr<TransportSocketParams> dest(new TransportSocketParams(
- host_port_pair, false, false, OnHostResolutionCallback(),
+ host_port_pair, false, OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a", dest, kDefaultPriority, callback.callback(),
- &pool_, BoundNetLog()));
+ handle.Init("a", dest, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
EXPECT_EQ(ERR_NAME_NOT_RESOLVED, callback.WaitForResult());
ASSERT_EQ(1u, handle.connection_attempts().size());
EXPECT_TRUE(handle.connection_attempts()[0].endpoint.address().empty());
@@ -228,8 +228,9 @@ TEST_F(TransportClientSocketPoolTest, InitConnectionFailure) {
TestCompletionCallback callback;
ClientSocketHandle handle;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a", params_, kDefaultPriority, callback.callback(),
- &pool_, BoundNetLog()));
+ handle.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult());
ASSERT_EQ(1u, handle.connection_attempts().size());
EXPECT_EQ("127.0.0.1:80",
@@ -239,8 +240,9 @@ TEST_F(TransportClientSocketPoolTest, InitConnectionFailure) {
// Make the host resolutions complete synchronously this time.
host_resolver_->set_synchronous_mode(true);
EXPECT_EQ(ERR_CONNECTION_FAILED,
- handle.Init("a", params_, kDefaultPriority, callback.callback(),
- &pool_, BoundNetLog()));
+ handle.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
ASSERT_EQ(1u, handle.connection_attempts().size());
EXPECT_EQ("127.0.0.1:80",
handle.connection_attempts()[0].endpoint.ToString());
@@ -350,8 +352,9 @@ TEST_F(TransportClientSocketPoolTest, CancelRequestClearGroup) {
TestCompletionCallback callback;
ClientSocketHandle handle;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a", params_, kDefaultPriority, callback.callback(),
- &pool_, BoundNetLog()));
+ handle.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
handle.Reset();
}
@@ -362,11 +365,13 @@ TEST_F(TransportClientSocketPoolTest, TwoRequestsCancelOne) {
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a", params_, kDefaultPriority, callback.callback(),
- &pool_, BoundNetLog()));
+ handle.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
EXPECT_EQ(ERR_IO_PENDING,
- handle2.Init("a", params_, kDefaultPriority, callback2.callback(),
- &pool_, BoundNetLog()));
+ handle2.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), &pool_, BoundNetLog()));
handle.Reset();
@@ -380,15 +385,17 @@ TEST_F(TransportClientSocketPoolTest, ConnectCancelConnect) {
ClientSocketHandle handle;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a", params_, kDefaultPriority, callback.callback(),
- &pool_, BoundNetLog()));
+ handle.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
handle.Reset();
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a", params_, kDefaultPriority, callback2.callback(),
- &pool_, BoundNetLog()));
+ handle.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), &pool_, BoundNetLog()));
host_resolver_->set_synchronous_mode(true);
// At this point, handle has two ConnectingSockets out for it. Due to the
@@ -497,11 +504,11 @@ class RequestSocketCallback : public TestCompletionCallbackBase {
}
within_callback_ = true;
scoped_refptr<TransportSocketParams> dest(new TransportSocketParams(
- HostPortPair("www.google.com", 80), false, false,
- OnHostResolutionCallback(),
+ HostPortPair("www.google.com", 80), false, OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
- int rv = handle_->Init("a", dest, LOWEST, callback(), pool_,
- BoundNetLog());
+ int rv = handle_->Init("a", dest, LOWEST,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback(), pool_, BoundNetLog());
EXPECT_EQ(OK, rv);
}
}
@@ -518,11 +525,11 @@ TEST_F(TransportClientSocketPoolTest, RequestTwice) {
ClientSocketHandle handle;
RequestSocketCallback callback(&handle, &pool_);
scoped_refptr<TransportSocketParams> dest(new TransportSocketParams(
- HostPortPair("www.google.com", 80), false, false,
- OnHostResolutionCallback(),
+ HostPortPair("www.google.com", 80), false, OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
- int rv = handle.Init("a", dest, LOWEST, callback.callback(), &pool_,
- BoundNetLog());
+ int rv =
+ handle.Init("a", dest, LOWEST, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
ASSERT_EQ(ERR_IO_PENDING, rv);
// The callback is going to request "www.google.com". We want it to complete
@@ -584,8 +591,9 @@ TEST_F(TransportClientSocketPoolTest, FailingActiveRequestWithPendingRequests) {
TEST_F(TransportClientSocketPoolTest, IdleSocketLoadTiming) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("a", params_, LOW, callback.callback(), &pool_,
- BoundNetLog());
+ int rv =
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -602,8 +610,8 @@ TEST_F(TransportClientSocketPoolTest, IdleSocketLoadTiming) {
// Now we should have 1 idle socket.
EXPECT_EQ(1, pool_.IdleSocketCount());
- rv = handle.Init("a", params_, LOW, callback.callback(), &pool_,
- BoundNetLog());
+ rv = handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(OK, rv);
EXPECT_EQ(0, pool_.IdleSocketCount());
TestLoadTimingInfoConnectedReused(handle);
@@ -612,8 +620,9 @@ TEST_F(TransportClientSocketPoolTest, IdleSocketLoadTiming) {
TEST_F(TransportClientSocketPoolTest, ResetIdleSocketsOnIPAddressChange) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("a", params_, LOW, callback.callback(), &pool_,
- BoundNetLog());
+ int rv =
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -668,8 +677,9 @@ TEST_F(TransportClientSocketPoolTest, BackupSocketConnect) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("b", params_, LOW, callback.callback(), &pool_,
- BoundNetLog());
+ int rv =
+ handle.Init("b", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -710,8 +720,9 @@ TEST_F(TransportClientSocketPoolTest, BackupSocketCancel) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("c", params_, LOW, callback.callback(), &pool_,
- BoundNetLog());
+ int rv =
+ handle.Init("c", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -756,8 +767,9 @@ TEST_F(TransportClientSocketPoolTest, BackupSocketFailAfterStall) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("b", params_, LOW, callback.callback(), &pool_,
- BoundNetLog());
+ int rv =
+ handle.Init("b", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -806,8 +818,9 @@ TEST_F(TransportClientSocketPoolTest, BackupSocketFailAfterDelay) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("b", params_, LOW, callback.callback(), &pool_,
- BoundNetLog());
+ int rv =
+ handle.Init("b", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -863,8 +876,9 @@ TEST_F(TransportClientSocketPoolTest, IPv6FallbackSocketIPv4FinishesFirst) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("a", params_, LOW, callback.callback(), &pool,
- BoundNetLog());
+ int rv =
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -915,8 +929,9 @@ TEST_F(TransportClientSocketPoolTest, IPv6FallbackSocketIPv6FinishesFirst) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("a", params_, LOW, callback.callback(), &pool,
- BoundNetLog());
+ int rv =
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -957,8 +972,9 @@ TEST_F(TransportClientSocketPoolTest, IPv6NoIPv4AddressesToFallbackTo) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("a", params_, LOW, callback.callback(), &pool,
- BoundNetLog());
+ int rv =
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -990,8 +1006,9 @@ TEST_F(TransportClientSocketPoolTest, IPv4HasNoFallback) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init("a", params_, LOW, callback.callback(), &pool,
- BoundNetLog());
+ int rv =
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -1009,15 +1026,16 @@ TEST_F(TransportClientSocketPoolTest, IPv4HasNoFallback) {
// Test that if TCP FastOpen is enabled, it is set on the socket
// when we have only an IPv4 address.
TEST_F(TransportClientSocketPoolTest, TCPFastOpenOnIPv4WithNoFallback) {
+ SequencedSocketData socket_data(nullptr, 0, nullptr, 0);
+ MockClientSocketFactory factory;
+ factory.AddSocketDataProvider(&socket_data);
// Create a pool without backup jobs.
ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false);
TransportClientSocketPool pool(kMaxSockets,
kMaxSocketsPerGroup,
host_resolver_.get(),
- &client_socket_factory_,
+ &factory,
NULL);
- client_socket_factory_.set_default_client_socket_type(
- MockTransportClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET);
// Resolve an AddressList with only IPv4 addresses.
host_resolver_->rules()->AddIPLiteralRule("*", "1.1.1.1", std::string());
@@ -1025,20 +1043,24 @@ TEST_F(TransportClientSocketPoolTest, TCPFastOpenOnIPv4WithNoFallback) {
ClientSocketHandle handle;
// Enable TCP FastOpen in TransportSocketParams.
scoped_refptr<TransportSocketParams> params = CreateParamsForTCPFastOpen();
- handle.Init("a", params, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(OK, callback.WaitForResult());
- EXPECT_TRUE(handle.socket()->UsingTCPFastOpen());
+ EXPECT_TRUE(socket_data.IsUsingTCPFastOpen());
}
// Test that if TCP FastOpen is enabled, it is set on the socket
// when we have only IPv6 addresses.
TEST_F(TransportClientSocketPoolTest, TCPFastOpenOnIPv6WithNoFallback) {
+ SequencedSocketData socket_data(nullptr, 0, nullptr, 0);
+ MockClientSocketFactory factory;
+ factory.AddSocketDataProvider(&socket_data);
// Create a pool without backup jobs.
ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false);
TransportClientSocketPool pool(kMaxSockets,
kMaxSocketsPerGroup,
host_resolver_.get(),
- &client_socket_factory_,
+ &factory,
NULL);
client_socket_factory_.set_default_client_socket_type(
MockTransportClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET);
@@ -1050,31 +1072,31 @@ TEST_F(TransportClientSocketPoolTest, TCPFastOpenOnIPv6WithNoFallback) {
ClientSocketHandle handle;
// Enable TCP FastOpen in TransportSocketParams.
scoped_refptr<TransportSocketParams> params = CreateParamsForTCPFastOpen();
- handle.Init("a", params, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(OK, callback.WaitForResult());
- EXPECT_TRUE(handle.socket()->UsingTCPFastOpen());
+ EXPECT_TRUE(socket_data.IsUsingTCPFastOpen());
}
// Test that if TCP FastOpen is enabled, it does not do anything when there
// is a IPv6 address with fallback to an IPv4 address. This test tests the case
// when the IPv6 connect fails and the IPv4 one succeeds.
TEST_F(TransportClientSocketPoolTest,
- NoTCPFastOpenOnIPv6FailureWithIPv4Fallback) {
+ NoTCPFastOpenOnIPv6FailureWithIPv4Fallback) {
+ SequencedSocketData socket_data_1(nullptr, 0, nullptr, 0);
+ socket_data_1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
+ SequencedSocketData socket_data_2(nullptr, 0, nullptr, 0);
+ MockClientSocketFactory factory;
+ factory.AddSocketDataProvider(&socket_data_1);
+ factory.AddSocketDataProvider(&socket_data_2);
// Create a pool without backup jobs.
ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false);
TransportClientSocketPool pool(kMaxSockets,
kMaxSocketsPerGroup,
host_resolver_.get(),
- &client_socket_factory_,
+ &factory,
NULL);
- MockTransportClientSocketFactory::ClientSocketType case_types[] = {
- // This is the IPv6 socket.
- MockTransportClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET,
- // This is the IPv4 socket.
- MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET
- };
- client_socket_factory_.set_client_socket_types(case_types, 2);
// Resolve an AddressList with a IPv6 address first and then a IPv4 address.
host_resolver_->rules()
->AddIPLiteralRule("*", "2:abcd::3:4:ff,2.2.2.2", std::string());
@@ -1083,37 +1105,33 @@ TEST_F(TransportClientSocketPoolTest,
ClientSocketHandle handle;
// Enable TCP FastOpen in TransportSocketParams.
scoped_refptr<TransportSocketParams> params = CreateParamsForTCPFastOpen();
- handle.Init("a", params, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(OK, callback.WaitForResult());
// Verify that the socket used is connected to the fallback IPv4 address.
IPEndPoint endpoint;
- handle.socket()->GetLocalAddress(&endpoint);
+ handle.socket()->GetPeerAddress(&endpoint);
EXPECT_EQ(kIPv4AddressSize, endpoint.address().size());
- EXPECT_EQ(2, client_socket_factory_.allocation_count());
// Verify that TCP FastOpen was not turned on for the socket.
- EXPECT_FALSE(handle.socket()->UsingTCPFastOpen());
+ EXPECT_FALSE(socket_data_1.IsUsingTCPFastOpen());
}
// Test that if TCP FastOpen is enabled, it does not do anything when there
// is a IPv6 address with fallback to an IPv4 address. This test tests the case
// when the IPv6 connect succeeds.
TEST_F(TransportClientSocketPoolTest,
- NoTCPFastOpenOnIPv6SuccessWithIPv4Fallback) {
+ NoTCPFastOpenOnIPv6SuccessWithIPv4Fallback) {
+ SequencedSocketData socket_data(nullptr, 0, nullptr, 0);
+ MockClientSocketFactory factory;
+ factory.AddSocketDataProvider(&socket_data);
// Create a pool without backup jobs.
ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false);
TransportClientSocketPool pool(kMaxSockets,
kMaxSocketsPerGroup,
host_resolver_.get(),
- &client_socket_factory_,
+ &factory,
NULL);
- MockTransportClientSocketFactory::ClientSocketType case_types[] = {
- // This is the IPv6 socket.
- MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET,
- // This is the IPv4 socket.
- MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET
- };
- client_socket_factory_.set_client_socket_types(case_types, 2);
// Resolve an AddressList with a IPv6 address first and then a IPv4 address.
host_resolver_->rules()
->AddIPLiteralRule("*", "2:abcd::3:4:ff,2.2.2.2", std::string());
@@ -1122,15 +1140,15 @@ TEST_F(TransportClientSocketPoolTest,
ClientSocketHandle handle;
// Enable TCP FastOpen in TransportSocketParams.
scoped_refptr<TransportSocketParams> params = CreateParamsForTCPFastOpen();
- handle.Init("a", params, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(OK, callback.WaitForResult());
- // Verify that the socket used is connected to the IPv6 address.
IPEndPoint endpoint;
- handle.socket()->GetLocalAddress(&endpoint);
+ handle.socket()->GetPeerAddress(&endpoint);
+ // Verify that the socket used is connected to the IPv6 address.
EXPECT_EQ(kIPv6AddressSize, endpoint.address().size());
- EXPECT_EQ(1, client_socket_factory_.allocation_count());
// Verify that TCP FastOpen was not turned on for the socket.
- EXPECT_FALSE(handle.socket()->UsingTCPFastOpen());
+ EXPECT_FALSE(socket_data.IsUsingTCPFastOpen());
}
} // namespace
diff --git a/chromium/net/socket/transport_client_socket_unittest.cc b/chromium/net/socket/transport_client_socket_unittest.cc
index ef5291d52d5..f9b095ca925 100644
--- a/chromium/net/socket/transport_client_socket_unittest.cc
+++ b/chromium/net/socket/transport_client_socket_unittest.cc
@@ -10,6 +10,7 @@
#include "base/run_loop.h"
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
@@ -97,9 +98,7 @@ void TransportClientSocketTest::SetUp() {
// Open a server socket on an ephemeral port.
listen_sock_.reset(new TCPServerSocket(NULL, NetLog::Source()));
- IPAddressNumber address;
- ParseIPLiteralToNumber("127.0.0.1", &address);
- IPEndPoint local_address(address, 0);
+ IPEndPoint local_address(IPAddress::IPv4Localhost(), 0);
ASSERT_EQ(OK, listen_sock_->Listen(local_address, 1));
// Get the server's address (including the actual port number).
ASSERT_EQ(OK, listen_sock_->GetLocalAddress(&local_address));
diff --git a/chromium/net/socket/unix_domain_client_socket_posix.cc b/chromium/net/socket/unix_domain_client_socket_posix.cc
index 564bef80d71..792cfac9bd2 100644
--- a/chromium/net/socket/unix_domain_client_socket_posix.cc
+++ b/chromium/net/socket/unix_domain_client_socket_posix.cc
@@ -9,8 +9,6 @@
#include <utility>
#include "base/logging.h"
-#include "base/posix/eintr_wrapper.h"
-#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/sockaddr_storage.h"
#include "net/socket/socket_posix.h"
@@ -34,8 +32,10 @@ UnixDomainClientSocket::~UnixDomainClientSocket() {
bool UnixDomainClientSocket::FillAddress(const std::string& socket_path,
bool use_abstract_namespace,
SockaddrStorage* address) {
- struct sockaddr_un* socket_addr =
- reinterpret_cast<struct sockaddr_un*>(address->addr);
+ // Caller should provide a non-empty path for the socket address.
+ if (socket_path.empty())
+ return false;
+
size_t path_max = address->addr_len - offsetof(struct sockaddr_un, sun_path);
// Non abstract namespace pathname should be null-terminated. Abstract
// namespace pathname must start with '\0'. So, the size is always greater
@@ -44,6 +44,8 @@ bool UnixDomainClientSocket::FillAddress(const std::string& socket_path,
if (path_size > path_max)
return false;
+ struct sockaddr_un* socket_addr =
+ reinterpret_cast<struct sockaddr_un*>(address->addr);
memset(socket_addr, 0, address->addr_len);
socket_addr->sun_family = AF_UNIX;
address->addr_len = path_size + offsetof(struct sockaddr_un, sun_path);
@@ -68,9 +70,6 @@ bool UnixDomainClientSocket::FillAddress(const std::string& socket_path,
int UnixDomainClientSocket::Connect(const CompletionCallback& callback) {
DCHECK(!socket_);
- if (socket_path_.empty())
- return ERR_ADDRESS_INVALID;
-
SockaddrStorage address;
if (!FillAddress(socket_path_, use_abstract_namespace_, &address))
return ERR_ADDRESS_INVALID;
@@ -132,10 +131,6 @@ bool UnixDomainClientSocket::WasEverUsed() const {
return true; // We don't care.
}
-bool UnixDomainClientSocket::UsingTCPFastOpen() const {
- return false;
-}
-
bool UnixDomainClientSocket::WasNpnNegotiated() 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 260b3b9be42..596aa096c53 100644
--- a/chromium/net/socket/unix_domain_client_socket_posix.h
+++ b/chromium/net/socket/unix_domain_client_socket_posix.h
@@ -52,7 +52,6 @@ class NET_EXPORT UnixDomainClientSocket : public StreamSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
bool WasNpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
diff --git a/chromium/net/socket/unix_domain_client_socket_posix_unittest.cc b/chromium/net/socket/unix_domain_client_socket_posix_unittest.cc
index 35830759630..b20678b420a 100644
--- a/chromium/net/socket/unix_domain_client_socket_posix_unittest.cc
+++ b/chromium/net/socket/unix_domain_client_socket_posix_unittest.cc
@@ -131,7 +131,7 @@ TEST_F(UnixDomainClientSocketTest, Connect) {
UnixDomainServerSocket server_socket(CreateAuthCallback(true),
kUseAbstractNamespace);
- EXPECT_EQ(OK, server_socket.ListenWithAddressAndPort(socket_path_, 0, 1));
+ EXPECT_EQ(OK, server_socket.BindAndListen(socket_path_, /*backlog=*/1));
scoped_ptr<StreamSocket> accepted_socket;
TestCompletionCallback accept_callback;
@@ -157,7 +157,7 @@ TEST_F(UnixDomainClientSocketTest, ConnectWithSocketDescriptor) {
UnixDomainServerSocket server_socket(CreateAuthCallback(true),
kUseAbstractNamespace);
- EXPECT_EQ(OK, server_socket.ListenWithAddressAndPort(socket_path_, 0, 1));
+ EXPECT_EQ(OK, server_socket.BindAndListen(socket_path_, /*backlog=*/1));
SocketDescriptor accepted_socket_fd = kInvalidSocket;
TestCompletionCallback accept_callback;
@@ -209,7 +209,7 @@ TEST_F(UnixDomainClientSocketTest, ConnectWithAbstractNamespace) {
#if defined(OS_ANDROID) || defined(OS_LINUX)
UnixDomainServerSocket server_socket(CreateAuthCallback(true),
kUseAbstractNamespace);
- EXPECT_EQ(OK, server_socket.ListenWithAddressAndPort(socket_path_, 0, 1));
+ EXPECT_EQ(OK, server_socket.BindAndListen(socket_path_, /*backlog=*/1));
scoped_ptr<StreamSocket> accepted_socket;
TestCompletionCallback accept_callback;
@@ -255,7 +255,7 @@ TEST_F(UnixDomainClientSocketTest,
TEST_F(UnixDomainClientSocketTest, DisconnectFromClient) {
UnixDomainServerSocket server_socket(CreateAuthCallback(true), false);
- EXPECT_EQ(OK, server_socket.ListenWithAddressAndPort(socket_path_, 0, 1));
+ EXPECT_EQ(OK, server_socket.BindAndListen(socket_path_, /*backlog=*/1));
scoped_ptr<StreamSocket> accepted_socket;
TestCompletionCallback accept_callback;
EXPECT_EQ(ERR_IO_PENDING,
@@ -288,7 +288,7 @@ TEST_F(UnixDomainClientSocketTest, DisconnectFromClient) {
TEST_F(UnixDomainClientSocketTest, DisconnectFromServer) {
UnixDomainServerSocket server_socket(CreateAuthCallback(true), false);
- EXPECT_EQ(OK, server_socket.ListenWithAddressAndPort(socket_path_, 0, 1));
+ EXPECT_EQ(OK, server_socket.BindAndListen(socket_path_, /*backlog=*/1));
scoped_ptr<StreamSocket> accepted_socket;
TestCompletionCallback accept_callback;
EXPECT_EQ(ERR_IO_PENDING,
@@ -321,7 +321,7 @@ TEST_F(UnixDomainClientSocketTest, DisconnectFromServer) {
TEST_F(UnixDomainClientSocketTest, ReadAfterWrite) {
UnixDomainServerSocket server_socket(CreateAuthCallback(true), false);
- EXPECT_EQ(OK, server_socket.ListenWithAddressAndPort(socket_path_, 0, 1));
+ EXPECT_EQ(OK, server_socket.BindAndListen(socket_path_, /*backlog=*/1));
scoped_ptr<StreamSocket> accepted_socket;
TestCompletionCallback accept_callback;
EXPECT_EQ(ERR_IO_PENDING,
@@ -390,7 +390,7 @@ TEST_F(UnixDomainClientSocketTest, ReadAfterWrite) {
TEST_F(UnixDomainClientSocketTest, ReadBeforeWrite) {
UnixDomainServerSocket server_socket(CreateAuthCallback(true), false);
- EXPECT_EQ(OK, server_socket.ListenWithAddressAndPort(socket_path_, 0, 1));
+ EXPECT_EQ(OK, server_socket.BindAndListen(socket_path_, /*backlog=*/1));
scoped_ptr<StreamSocket> accepted_socket;
TestCompletionCallback accept_callback;
EXPECT_EQ(ERR_IO_PENDING,
diff --git a/chromium/net/socket/unix_domain_server_socket_posix.cc b/chromium/net/socket/unix_domain_server_socket_posix.cc
index 161893a4324..b6ba35c6362 100644
--- a/chromium/net/socket/unix_domain_server_socket_posix.cc
+++ b/chromium/net/socket/unix_domain_server_socket_posix.cc
@@ -68,13 +68,19 @@ int UnixDomainServerSocket::Listen(const IPEndPoint& address, int backlog) {
}
int UnixDomainServerSocket::ListenWithAddressAndPort(
- const std::string& unix_domain_path,
- uint16_t port_unused,
+ const std::string& address_string,
+ uint16_t port,
int backlog) {
+ NOTIMPLEMENTED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
+int UnixDomainServerSocket::BindAndListen(const std::string& socket_path,
+ int backlog) {
DCHECK(!listen_socket_);
SockaddrStorage address;
- if (!UnixDomainClientSocket::FillAddress(unix_domain_path,
+ if (!UnixDomainClientSocket::FillAddress(socket_path,
use_abstract_namespace_,
&address)) {
return ERR_ADDRESS_INVALID;
@@ -90,7 +96,7 @@ int UnixDomainServerSocket::ListenWithAddressAndPort(
DCHECK_NE(ERR_IO_PENDING, rv);
if (rv != OK) {
PLOG(ERROR)
- << "Could not bind unix domain socket to " << unix_domain_path
+ << "Could not bind unix domain socket to " << socket_path
<< (use_abstract_namespace_ ? " (with abstract namespace)" : "");
return rv;
}
diff --git a/chromium/net/socket/unix_domain_server_socket_posix.h b/chromium/net/socket/unix_domain_server_socket_posix.h
index 55d2708b323..7395f058ce5 100644
--- a/chromium/net/socket/unix_domain_server_socket_posix.h
+++ b/chromium/net/socket/unix_domain_server_socket_posix.h
@@ -52,13 +52,17 @@ class NET_EXPORT UnixDomainServerSocket : public ServerSocket {
// ServerSocket implementation.
int Listen(const IPEndPoint& address, int backlog) override;
- int ListenWithAddressAndPort(const std::string& unix_domain_path,
- uint16_t port_unused,
+ int ListenWithAddressAndPort(const std::string& address_string,
+ uint16_t port,
int backlog) override;
int GetLocalAddress(IPEndPoint* address) const override;
int Accept(scoped_ptr<StreamSocket>* socket,
const CompletionCallback& callback) override;
+ // Creates a server socket, binds it to the specified |socket_path| and
+ // starts listening for incoming connections with the specified |backlog|.
+ int BindAndListen(const std::string& socket_path, int backlog);
+
// Accepts an incoming connection on |listen_socket_|, but passes back
// a raw SocketDescriptor instead of a StreamSocket.
int AcceptSocketDescriptor(SocketDescriptor* socket_descriptor,
@@ -88,4 +92,4 @@ class NET_EXPORT UnixDomainServerSocket : public ServerSocket {
} // namespace net
-#endif // NET_SOCKET_UNIX_DOMAIN_SOCKET_POSIX_H_
+#endif // NET_SOCKET_UNIX_DOMAIN_SERVER_SOCKET_POSIX_H_
diff --git a/chromium/net/socket/unix_domain_server_socket_posix_unittest.cc b/chromium/net/socket/unix_domain_server_socket_posix_unittest.cc
index bdf1efa29c4..be472c0775c 100644
--- a/chromium/net/socket/unix_domain_server_socket_posix_unittest.cc
+++ b/chromium/net/socket/unix_domain_server_socket_posix_unittest.cc
@@ -55,7 +55,7 @@ TEST_F(UnixDomainServerSocketTest, ListenWithInvalidPath) {
UnixDomainServerSocket server_socket(CreateAuthCallback(true),
kUseAbstractNamespace);
EXPECT_EQ(ERR_FILE_NOT_FOUND,
- server_socket.ListenWithAddressAndPort(kInvalidSocketPath, 0, 1));
+ server_socket.BindAndListen(kInvalidSocketPath, /*backlog=*/1));
}
TEST_F(UnixDomainServerSocketTest, ListenWithInvalidPathWithAbstractNamespace) {
@@ -63,11 +63,10 @@ TEST_F(UnixDomainServerSocketTest, ListenWithInvalidPathWithAbstractNamespace) {
UnixDomainServerSocket server_socket(CreateAuthCallback(true),
kUseAbstractNamespace);
#if defined(OS_ANDROID) || defined(OS_LINUX)
- EXPECT_EQ(OK,
- server_socket.ListenWithAddressAndPort(kInvalidSocketPath, 0, 1));
+ EXPECT_EQ(OK, server_socket.BindAndListen(kInvalidSocketPath, /*backlog=*/1));
#else
EXPECT_EQ(ERR_ADDRESS_INVALID,
- server_socket.ListenWithAddressAndPort(kInvalidSocketPath, 0, 1));
+ server_socket.BindAndListen(kInvalidSocketPath, /*backlog=*/1));
#endif
}
@@ -76,8 +75,8 @@ TEST_F(UnixDomainServerSocketTest, ListenAgainAfterFailureWithInvalidPath) {
UnixDomainServerSocket server_socket(CreateAuthCallback(true),
kUseAbstractNamespace);
EXPECT_EQ(ERR_FILE_NOT_FOUND,
- server_socket.ListenWithAddressAndPort(kInvalidSocketPath, 0, 1));
- EXPECT_EQ(OK, server_socket.ListenWithAddressAndPort(socket_path_, 0, 1));
+ server_socket.BindAndListen(kInvalidSocketPath, /*backlog=*/1));
+ EXPECT_EQ(OK, server_socket.BindAndListen(socket_path_, /*backlog=*/1));
}
TEST_F(UnixDomainServerSocketTest, AcceptWithForbiddenUser) {
@@ -85,7 +84,7 @@ TEST_F(UnixDomainServerSocketTest, AcceptWithForbiddenUser) {
UnixDomainServerSocket server_socket(CreateAuthCallback(false),
kUseAbstractNamespace);
- EXPECT_EQ(OK, server_socket.ListenWithAddressAndPort(socket_path_, 0, 1));
+ EXPECT_EQ(OK, server_socket.BindAndListen(socket_path_, /*backlog=*/1));
scoped_ptr<StreamSocket> accepted_socket;
TestCompletionCallback accept_callback;
@@ -119,6 +118,21 @@ TEST_F(UnixDomainServerSocketTest, AcceptWithForbiddenUser) {
EXPECT_FALSE(accepted_socket);
}
+TEST_F(UnixDomainServerSocketTest, UnimplementedMethodsFail) {
+ const bool kUseAbstractNamespace = false;
+ UnixDomainServerSocket server_socket(CreateAuthCallback(true),
+ kUseAbstractNamespace);
+
+ IPEndPoint ep;
+ EXPECT_EQ(ERR_NOT_IMPLEMENTED, server_socket.Listen(ep, 0));
+ EXPECT_EQ(ERR_NOT_IMPLEMENTED,
+ server_socket.ListenWithAddressAndPort(kInvalidSocketPath,
+ 0,
+ /*backlog=*/1));
+
+ EXPECT_EQ(ERR_ADDRESS_INVALID, server_socket.GetLocalAddress(&ep));
+}
+
// Normal cases including read/write are tested by UnixDomainClientSocketTest.
} // namespace
diff --git a/chromium/net/socket/websocket_endpoint_lock_manager_unittest.cc b/chromium/net/socket/websocket_endpoint_lock_manager_unittest.cc
index 6808d3733fc..640d8b3bd5d 100644
--- a/chromium/net/socket/websocket_endpoint_lock_manager_unittest.cc
+++ b/chromium/net/socket/websocket_endpoint_lock_manager_unittest.cc
@@ -9,6 +9,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/time/time.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/socket/next_proto.h"
#include "net/socket/socket_test_util.h"
@@ -48,8 +49,6 @@ class FakeStreamSocket : public StreamSocket {
bool WasEverUsed() const override { return false; }
- bool UsingTCPFastOpen() const override { return false; }
-
bool WasNpnNegotiated() const override { return false; }
NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
@@ -138,9 +137,7 @@ class WebSocketEndpointLockManagerTest : public ::testing::Test {
WebSocketEndpointLockManager* instance() const { return instance_; }
IPEndPoint DummyEndpoint() {
- IPAddressNumber ip_address_number;
- CHECK(ParseIPLiteralToNumber("127.0.0.1", &ip_address_number));
- return IPEndPoint(ip_address_number, 80);
+ return IPEndPoint(IPAddress::IPv4Localhost(), 80);
}
void UnlockDummyEndpoint(int times) {
diff --git a/chromium/net/socket/websocket_transport_client_socket_pool.cc b/chromium/net/socket/websocket_transport_client_socket_pool.cc
index 73d8599b0e9..e4f0883acce 100644
--- a/chromium/net/socket/websocket_transport_client_socket_pool.cc
+++ b/chromium/net/socket/websocket_transport_client_socket_pool.cc
@@ -39,6 +39,7 @@ const int kTransportConnectJobTimeoutInSeconds = 240; // 4 minutes.
WebSocketTransportConnectJob::WebSocketTransportConnectJob(
const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const scoped_refptr<TransportSocketParams>& params,
TimeDelta timeout_duration,
const CompletionCallback& callback,
@@ -51,6 +52,7 @@ WebSocketTransportConnectJob::WebSocketTransportConnectJob(
: ConnectJob(group_name,
timeout_duration,
priority,
+ respect_limits,
delegate,
BoundNetLog::Make(pool_net_log, NetLog::SOURCE_CONNECT_JOB)),
helper_(params, client_socket_factory, host_resolver, &connect_timing_),
@@ -272,6 +274,7 @@ int WebSocketTransportClientSocketPool::RequestSocket(
const std::string& group_name,
const void* params,
RequestPriority priority,
+ RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& request_net_log) {
@@ -286,7 +289,8 @@ int WebSocketTransportClientSocketPool::RequestSocket(
request_net_log.BeginEvent(NetLog::TYPE_SOCKET_POOL);
- if (ReachedMaxSocketsLimit() && !casted_params->ignore_limits()) {
+ if (ReachedMaxSocketsLimit() &&
+ respect_limits == ClientSocketPool::RespectLimits::ENABLED) {
request_net_log.AddEvent(NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS);
// TODO(ricea): Use emplace_back when C++11 becomes allowed.
StalledRequest request(
@@ -306,17 +310,10 @@ int WebSocketTransportClientSocketPool::RequestSocket(
}
scoped_ptr<WebSocketTransportConnectJob> connect_job(
- new WebSocketTransportConnectJob(group_name,
- priority,
- casted_params,
- ConnectionTimeout(),
- callback,
- client_socket_factory_,
- host_resolver_,
- handle,
- &connect_job_delegate_,
- pool_net_log_,
- request_net_log));
+ new WebSocketTransportConnectJob(
+ group_name, priority, respect_limits, casted_params,
+ ConnectionTimeout(), callback, client_socket_factory_, host_resolver_,
+ handle, &connect_job_delegate_, pool_net_log_, request_net_log));
int rv = connect_job->Connect();
// Regardless of the outcome of |connect_job|, it will always be bound to
@@ -589,12 +586,11 @@ void WebSocketTransportClientSocketPool::ActivateStalledRequest() {
StalledRequest request(stalled_request_queue_.front());
stalled_request_queue_.pop_front();
stalled_request_map_.erase(request.handle);
- int rv = RequestSocket("ignored",
- &request.params,
- request.priority,
- request.handle,
- request.callback,
- request.net_log);
+ int rv = RequestSocket("ignored", &request.params, request.priority,
+ // Stalled requests can't have |respect_limits|
+ // DISABLED.
+ RespectLimits::ENABLED, request.handle,
+ request.callback, request.net_log);
// ActivateStalledRequest() never returns synchronously, so it is never
// called re-entrantly.
if (rv != ERR_IO_PENDING)
@@ -638,6 +634,9 @@ WebSocketTransportClientSocketPool::StalledRequest::StalledRequest(
callback(callback),
net_log(net_log) {}
+WebSocketTransportClientSocketPool::StalledRequest::StalledRequest(
+ const StalledRequest& other) = default;
+
WebSocketTransportClientSocketPool::StalledRequest::~StalledRequest() {}
} // namespace net
diff --git a/chromium/net/socket/websocket_transport_client_socket_pool.h b/chromium/net/socket/websocket_transport_client_socket_pool.h
index c0f1351dfe8..23b777457fa 100644
--- a/chromium/net/socket/websocket_transport_client_socket_pool.h
+++ b/chromium/net/socket/websocket_transport_client_socket_pool.h
@@ -43,6 +43,7 @@ class NET_EXPORT_PRIVATE WebSocketTransportConnectJob : public ConnectJob {
WebSocketTransportConnectJob(
const std::string& group_name,
RequestPriority priority,
+ ClientSocketPool::RespectLimits respect_limits,
const scoped_refptr<TransportSocketParams>& params,
base::TimeDelta timeout_duration,
const CompletionCallback& callback,
@@ -134,6 +135,7 @@ class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool
int RequestSocket(const std::string& group_name,
const void* resolve_info,
RequestPriority priority,
+ RespectLimits respect_limits,
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log) override;
@@ -183,6 +185,7 @@ class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool
ClientSocketHandle* handle,
const CompletionCallback& callback,
const BoundNetLog& net_log);
+ StalledRequest(const StalledRequest& other);
~StalledRequest();
const scoped_refptr<TransportSocketParams> params;
const RequestPriority priority;
diff --git a/chromium/net/socket/websocket_transport_client_socket_pool_unittest.cc b/chromium/net/socket/websocket_transport_client_socket_pool_unittest.cc
index 96aa84a9921..bbc9de80018 100644
--- a/chromium/net/socket/websocket_transport_client_socket_pool_unittest.cc
+++ b/chromium/net/socket/websocket_transport_client_socket_pool_unittest.cc
@@ -21,7 +21,6 @@
#include "net/base/load_timing_info.h"
#include "net/base/load_timing_info_test_util.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
#include "net/log/test_net_log.h"
@@ -55,7 +54,6 @@ class WebSocketTransportClientSocketPoolTest : public ::testing::Test {
: params_(new TransportSocketParams(
HostPortPair("www.google.com", 80),
false,
- false,
OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)),
host_resolver_(new MockHostResolver),
@@ -81,11 +79,11 @@ class WebSocketTransportClientSocketPoolTest : public ::testing::Test {
new TransportSocketParams(
HostPortPair("www.google.com", 80),
false,
- false,
OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
return test_base_.StartRequestUsingPool(
- &pool_, group_name, priority, params);
+ &pool_, group_name, priority, ClientSocketPool::RespectLimits::ENABLED,
+ params);
}
int GetOrderOfRequest(size_t index) {
@@ -122,8 +120,9 @@ class WebSocketTransportClientSocketPoolTest : public ::testing::Test {
TEST_F(WebSocketTransportClientSocketPoolTest, Basic) {
TestCompletionCallback callback;
ClientSocketHandle handle;
- int rv = handle.Init(
- "a", params_, LOW, callback.callback(), &pool_, BoundNetLog());
+ int rv =
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -142,12 +141,9 @@ TEST_F(WebSocketTransportClientSocketPoolTest, SetResolvePriorityOnInit) {
TestCompletionCallback callback;
ClientSocketHandle handle;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a",
- params_,
- priority,
- callback.callback(),
- &pool_,
- BoundNetLog()));
+ handle.Init("a", params_, priority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
EXPECT_EQ(priority, host_resolver_->last_request_priority());
}
}
@@ -158,15 +154,12 @@ TEST_F(WebSocketTransportClientSocketPoolTest, InitHostResolutionFailure) {
ClientSocketHandle handle;
HostPortPair host_port_pair("unresolvable.host.name", 80);
scoped_refptr<TransportSocketParams> dest(new TransportSocketParams(
- host_port_pair, false, false, OnHostResolutionCallback(),
+ host_port_pair, false, OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a",
- dest,
- kDefaultPriority,
- callback.callback(),
- &pool_,
- BoundNetLog()));
+ handle.Init("a", dest, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
EXPECT_EQ(ERR_NAME_NOT_RESOLVED, callback.WaitForResult());
}
@@ -176,23 +169,17 @@ TEST_F(WebSocketTransportClientSocketPoolTest, InitConnectionFailure) {
TestCompletionCallback callback;
ClientSocketHandle handle;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a",
- params_,
- kDefaultPriority,
- callback.callback(),
- &pool_,
- BoundNetLog()));
+ handle.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult());
// Make the host resolutions complete synchronously this time.
host_resolver_->set_synchronous_mode(true);
EXPECT_EQ(ERR_CONNECTION_FAILED,
- handle.Init("a",
- params_,
- kDefaultPriority,
- callback.callback(),
- &pool_,
- BoundNetLog()));
+ handle.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
}
TEST_F(WebSocketTransportClientSocketPoolTest, PendingRequestsFinishFifo) {
@@ -267,12 +254,9 @@ TEST_F(WebSocketTransportClientSocketPoolTest, CancelRequestClearGroup) {
TestCompletionCallback callback;
ClientSocketHandle handle;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a",
- params_,
- kDefaultPriority,
- callback.callback(),
- &pool_,
- BoundNetLog()));
+ handle.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
handle.Reset();
}
@@ -283,19 +267,13 @@ TEST_F(WebSocketTransportClientSocketPoolTest, TwoRequestsCancelOne) {
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a",
- params_,
- kDefaultPriority,
- callback.callback(),
- &pool_,
- BoundNetLog()));
+ handle.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
EXPECT_EQ(ERR_IO_PENDING,
- handle2.Init("a",
- params_,
- kDefaultPriority,
- callback2.callback(),
- &pool_,
- BoundNetLog()));
+ handle2.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), &pool_, BoundNetLog()));
handle.Reset();
@@ -309,23 +287,17 @@ TEST_F(WebSocketTransportClientSocketPoolTest, ConnectCancelConnect) {
ClientSocketHandle handle;
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a",
- params_,
- kDefaultPriority,
- callback.callback(),
- &pool_,
- BoundNetLog()));
+ handle.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog()));
handle.Reset();
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a",
- params_,
- kDefaultPriority,
- callback2.callback(),
- &pool_,
- BoundNetLog()));
+ handle.Init("a", params_, kDefaultPriority,
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), &pool_, BoundNetLog()));
host_resolver_->set_synchronous_mode(true);
// At this point, handle has two ConnectingSockets out for it. Due to the
@@ -395,11 +367,11 @@ void RequestSocketOnComplete(ClientSocketHandle* handle,
handle->Reset();
scoped_refptr<TransportSocketParams> dest(new TransportSocketParams(
- HostPortPair("www.google.com", 80), false, false,
- OnHostResolutionCallback(),
+ HostPortPair("www.google.com", 80), false, OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
int rv =
- handle->Init("a", dest, LOWEST, nested_callback, pool, BoundNetLog());
+ handle->Init("a", dest, LOWEST, ClientSocketPool::RespectLimits::ENABLED,
+ nested_callback, pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
if (ERR_IO_PENDING != rv)
nested_callback.Run(rv);
@@ -414,14 +386,14 @@ TEST_F(WebSocketTransportClientSocketPoolTest, RequestTwice) {
new TransportSocketParams(
HostPortPair("www.google.com", 80),
false,
- false,
OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
TestCompletionCallback second_result_callback;
- int rv = handle.Init("a", dest, LOWEST,
- base::Bind(&RequestSocketOnComplete, &handle, &pool_,
- second_result_callback.callback()),
- &pool_, BoundNetLog());
+ int rv =
+ handle.Init("a", dest, LOWEST, ClientSocketPool::RespectLimits::ENABLED,
+ base::Bind(&RequestSocketOnComplete, &handle, &pool_,
+ second_result_callback.callback()),
+ &pool_, BoundNetLog());
ASSERT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, second_result_callback.WaitForResult());
@@ -492,8 +464,9 @@ TEST_F(WebSocketTransportClientSocketPoolTest, LockReleasedOnHandleReset) {
TEST_F(WebSocketTransportClientSocketPoolTest, LockReleasedOnHandleDelete) {
TestCompletionCallback callback;
scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle);
- int rv = handle->Init(
- "a", params_, LOW, callback.callback(), &pool_, BoundNetLog());
+ int rv =
+ handle->Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool_, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
@@ -560,7 +533,8 @@ TEST_F(WebSocketTransportClientSocketPoolTest,
TestCompletionCallback callback;
ClientSocketHandle handle;
int rv =
- handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -602,7 +576,8 @@ TEST_F(WebSocketTransportClientSocketPoolTest,
TestCompletionCallback callback;
ClientSocketHandle handle;
int rv =
- handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -634,7 +609,8 @@ TEST_F(WebSocketTransportClientSocketPoolTest,
TestCompletionCallback callback;
ClientSocketHandle handle;
int rv =
- handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -664,7 +640,8 @@ TEST_F(WebSocketTransportClientSocketPoolTest, IPv4HasNoFallback) {
TestCompletionCallback callback;
ClientSocketHandle handle;
int rv =
- handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -705,7 +682,8 @@ TEST_F(WebSocketTransportClientSocketPoolTest, IPv6InstantFail) {
TestCompletionCallback callback;
ClientSocketHandle handle;
int rv =
- handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(OK, rv);
ASSERT_TRUE(handle.socket());
@@ -741,7 +719,8 @@ TEST_F(WebSocketTransportClientSocketPoolTest, IPv6RapidFail) {
TestCompletionCallback callback;
ClientSocketHandle handle;
int rv =
- handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.socket());
@@ -777,7 +756,8 @@ TEST_F(WebSocketTransportClientSocketPoolTest, FirstSuccessWins) {
TestCompletionCallback callback;
ClientSocketHandle handle;
int rv =
- handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
ASSERT_FALSE(handle.socket());
@@ -829,7 +809,8 @@ TEST_F(WebSocketTransportClientSocketPoolTest, LastFailureWins) {
ClientSocketHandle handle;
base::TimeTicks start(base::TimeTicks::Now());
int rv =
- handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult());
@@ -866,7 +847,8 @@ TEST_F(WebSocketTransportClientSocketPoolTest, DISABLED_OverallTimeoutApplies) {
ClientSocketHandle handle;
int rv =
- handle.Init("a", params_, LOW, callback.callback(), &pool, BoundNetLog());
+ handle.Init("a", params_, LOW, ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), &pool, BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(ERR_TIMED_OUT, callback.WaitForResult());
diff --git a/chromium/net/spdy/bidirectional_stream_spdy_job.cc b/chromium/net/spdy/bidirectional_stream_spdy_impl.cc
index 553d191c63d..c7e023baeb4 100644
--- a/chromium/net/spdy/bidirectional_stream_spdy_job.cc
+++ b/chromium/net/spdy/bidirectional_stream_spdy_impl.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/spdy/bidirectional_stream_spdy_job.h"
+#include "net/spdy/bidirectional_stream_spdy_impl.h"
#include "base/bind.h"
#include "base/location.h"
@@ -26,7 +26,7 @@ const int kBufferTimeMs = 1;
} // namespace
-BidirectionalStreamSpdyJob::BidirectionalStreamSpdyJob(
+BidirectionalStreamSpdyImpl::BidirectionalStreamSpdyImpl(
const base::WeakPtr<SpdySession>& spdy_session)
: spdy_session_(spdy_session),
request_info_(nullptr),
@@ -40,17 +40,17 @@ BidirectionalStreamSpdyJob::BidirectionalStreamSpdyJob(
closed_stream_sent_bytes_(0),
weak_factory_(this) {}
-BidirectionalStreamSpdyJob::~BidirectionalStreamSpdyJob() {
+BidirectionalStreamSpdyImpl::~BidirectionalStreamSpdyImpl() {
if (stream_) {
stream_->DetachDelegate();
DCHECK(!stream_);
}
}
-void BidirectionalStreamSpdyJob::Start(
+void BidirectionalStreamSpdyImpl::Start(
const BidirectionalStreamRequestInfo* request_info,
const BoundNetLog& net_log,
- BidirectionalStreamJob::Delegate* delegate,
+ BidirectionalStreamImpl::Delegate* delegate,
scoped_ptr<base::Timer> timer) {
DCHECK(!stream_);
DCHECK(timer);
@@ -68,13 +68,13 @@ void BidirectionalStreamSpdyJob::Start(
int rv = stream_request_.StartRequest(
SPDY_BIDIRECTIONAL_STREAM, spdy_session_, request_info_->url,
request_info_->priority, net_log,
- base::Bind(&BidirectionalStreamSpdyJob::OnStreamInitialized,
+ base::Bind(&BidirectionalStreamSpdyImpl::OnStreamInitialized,
weak_factory_.GetWeakPtr()));
if (rv != ERR_IO_PENDING)
OnStreamInitialized(rv);
}
-int BidirectionalStreamSpdyJob::ReadData(IOBuffer* buf, int buf_len) {
+int BidirectionalStreamSpdyImpl::ReadData(IOBuffer* buf, int buf_len) {
if (stream_)
DCHECK(!stream_->IsIdle());
@@ -95,9 +95,9 @@ int BidirectionalStreamSpdyJob::ReadData(IOBuffer* buf, int buf_len) {
return ERR_IO_PENDING;
}
-void BidirectionalStreamSpdyJob::SendData(IOBuffer* data,
- int length,
- bool end_stream) {
+void BidirectionalStreamSpdyImpl::SendData(IOBuffer* data,
+ int length,
+ bool end_stream) {
DCHECK(!stream_closed_);
DCHECK(stream_);
@@ -105,7 +105,7 @@ void BidirectionalStreamSpdyJob::SendData(IOBuffer* data,
end_stream ? NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND);
}
-void BidirectionalStreamSpdyJob::Cancel() {
+void BidirectionalStreamSpdyImpl::Cancel() {
if (!stream_)
return;
// Cancels the stream and detaches the delegate so it doesn't get called back.
@@ -113,11 +113,11 @@ void BidirectionalStreamSpdyJob::Cancel() {
DCHECK(!stream_);
}
-NextProto BidirectionalStreamSpdyJob::GetProtocol() const {
+NextProto BidirectionalStreamSpdyImpl::GetProtocol() const {
return negotiated_protocol_;
}
-int64_t BidirectionalStreamSpdyJob::GetTotalReceivedBytes() const {
+int64_t BidirectionalStreamSpdyImpl::GetTotalReceivedBytes() const {
if (stream_closed_)
return closed_stream_received_bytes_;
@@ -127,7 +127,7 @@ int64_t BidirectionalStreamSpdyJob::GetTotalReceivedBytes() const {
return stream_->raw_received_bytes();
}
-int64_t BidirectionalStreamSpdyJob::GetTotalSentBytes() const {
+int64_t BidirectionalStreamSpdyImpl::GetTotalSentBytes() const {
if (stream_closed_)
return closed_stream_sent_bytes_;
@@ -137,14 +137,14 @@ int64_t BidirectionalStreamSpdyJob::GetTotalSentBytes() const {
return stream_->raw_sent_bytes();
}
-void BidirectionalStreamSpdyJob::OnRequestHeadersSent() {
+void BidirectionalStreamSpdyImpl::OnRequestHeadersSent() {
DCHECK(stream_);
negotiated_protocol_ = stream_->GetProtocol();
delegate_->OnHeadersSent();
}
-SpdyResponseHeadersStatus BidirectionalStreamSpdyJob::OnResponseHeadersUpdated(
+SpdyResponseHeadersStatus BidirectionalStreamSpdyImpl::OnResponseHeadersUpdated(
const SpdyHeaderBlock& response_headers) {
DCHECK(stream_);
@@ -152,12 +152,13 @@ SpdyResponseHeadersStatus BidirectionalStreamSpdyJob::OnResponseHeadersUpdated(
return RESPONSE_HEADERS_ARE_COMPLETE;
}
-void BidirectionalStreamSpdyJob::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) {
+void BidirectionalStreamSpdyImpl::OnDataReceived(
+ scoped_ptr<SpdyBuffer> buffer) {
DCHECK(stream_);
DCHECK(!stream_closed_);
- // If |buffer| is null, BidirectionalStreamSpdyJob::OnClose will be invoked by
- // SpdyStream to indicate the end of stream.
+ // If |buffer| is null, BidirectionalStreamSpdyImpl::OnClose will be invoked
+ // by SpdyStream to indicate the end of stream.
if (!buffer)
return;
@@ -171,21 +172,21 @@ void BidirectionalStreamSpdyJob::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) {
}
}
-void BidirectionalStreamSpdyJob::OnDataSent() {
+void BidirectionalStreamSpdyImpl::OnDataSent() {
DCHECK(stream_);
DCHECK(!stream_closed_);
delegate_->OnDataSent();
}
-void BidirectionalStreamSpdyJob::OnTrailers(const SpdyHeaderBlock& trailers) {
+void BidirectionalStreamSpdyImpl::OnTrailers(const SpdyHeaderBlock& trailers) {
DCHECK(stream_);
DCHECK(!stream_closed_);
delegate_->OnTrailersReceived(trailers);
}
-void BidirectionalStreamSpdyJob::OnClose(int status) {
+void BidirectionalStreamSpdyImpl::OnClose(int status) {
DCHECK(stream_);
stream_closed_ = true;
@@ -205,7 +206,7 @@ void BidirectionalStreamSpdyJob::OnClose(int status) {
DoBufferedRead();
}
-void BidirectionalStreamSpdyJob::SendRequestHeaders() {
+void BidirectionalStreamSpdyImpl::SendRequestHeaders() {
scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
HttpRequestInfo http_request_info;
http_request_info.url = request_info_->url;
@@ -221,7 +222,7 @@ void BidirectionalStreamSpdyJob::SendRequestHeaders() {
: MORE_DATA_TO_SEND);
}
-void BidirectionalStreamSpdyJob::OnStreamInitialized(int rv) {
+void BidirectionalStreamSpdyImpl::OnStreamInitialized(int rv) {
DCHECK_NE(ERR_IO_PENDING, rv);
if (rv == OK) {
stream_ = stream_request_.ReleaseStream();
@@ -232,7 +233,7 @@ void BidirectionalStreamSpdyJob::OnStreamInitialized(int rv) {
delegate_->OnFailed(rv);
}
-void BidirectionalStreamSpdyJob::ScheduleBufferedRead() {
+void BidirectionalStreamSpdyImpl::ScheduleBufferedRead() {
// If there is already a scheduled DoBufferedRead, don't issue
// another one. Mark that we have received more data and return.
if (timer_->IsRunning()) {
@@ -242,11 +243,11 @@ void BidirectionalStreamSpdyJob::ScheduleBufferedRead() {
more_read_data_pending_ = false;
timer_->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kBufferTimeMs),
- base::Bind(&BidirectionalStreamSpdyJob::DoBufferedRead,
+ base::Bind(&BidirectionalStreamSpdyImpl::DoBufferedRead,
weak_factory_.GetWeakPtr()));
}
-void BidirectionalStreamSpdyJob::DoBufferedRead() {
+void BidirectionalStreamSpdyImpl::DoBufferedRead() {
DCHECK(!timer_->IsRunning());
// Check to see that the stream has not errored out.
DCHECK(stream_ || stream_closed_);
@@ -269,7 +270,7 @@ void BidirectionalStreamSpdyJob::DoBufferedRead() {
}
}
-bool BidirectionalStreamSpdyJob::ShouldWaitForMoreBufferedData() const {
+bool BidirectionalStreamSpdyImpl::ShouldWaitForMoreBufferedData() const {
if (stream_closed_)
return false;
DCHECK_GT(read_buffer_len_, 0);
diff --git a/chromium/net/spdy/bidirectional_stream_spdy_job.h b/chromium/net/spdy/bidirectional_stream_spdy_impl.h
index 7dda52f4759..62e7bb66f00 100644
--- a/chromium/net/spdy/bidirectional_stream_spdy_job.h
+++ b/chromium/net/spdy/bidirectional_stream_spdy_impl.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_SPDY_BIDIRECTIONAL_STREAM_SPDY_JOB_H_
-#define NET_SPDY_BIDIRECTIONAL_STREAM_SPDY_JOB_H_
+#ifndef NET_SPDY_BIDIRECTIONAL_STREAM_SPDY_IMPL_H_
+#define NET_SPDY_BIDIRECTIONAL_STREAM_SPDY_IMPL_H_
#include <stdint.h>
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "net/http/bidirectional_stream_job.h"
+#include "net/http/bidirectional_stream_impl.h"
#include "net/http/bidirectional_stream_request_info.h"
#include "net/http/http_request_info.h"
#include "net/spdy/spdy_read_queue.h"
@@ -27,19 +27,19 @@ class BoundNetLog;
class IOBuffer;
class SpdyHeaderBlock;
-class NET_EXPORT_PRIVATE BidirectionalStreamSpdyJob
- : public BidirectionalStreamJob,
+class NET_EXPORT_PRIVATE BidirectionalStreamSpdyImpl
+ : public BidirectionalStreamImpl,
public SpdyStream::Delegate {
public:
- explicit BidirectionalStreamSpdyJob(
+ explicit BidirectionalStreamSpdyImpl(
const base::WeakPtr<SpdySession>& spdy_session);
- ~BidirectionalStreamSpdyJob() override;
+ ~BidirectionalStreamSpdyImpl() override;
- // BidirectionalStreamJob implementation:
+ // BidirectionalStreamImpl implementation:
void Start(const BidirectionalStreamRequestInfo* request_info,
const BoundNetLog& net_log,
- BidirectionalStreamJob::Delegate* delegate,
+ BidirectionalStreamImpl::Delegate* delegate,
scoped_ptr<base::Timer> timer) override;
int ReadData(IOBuffer* buf, int buf_len) override;
void SendData(IOBuffer* data, int length, bool end_stream) override;
@@ -66,7 +66,7 @@ class NET_EXPORT_PRIVATE BidirectionalStreamSpdyJob
const base::WeakPtr<SpdySession> spdy_session_;
const BidirectionalStreamRequestInfo* request_info_;
- BidirectionalStreamJob::Delegate* delegate_;
+ BidirectionalStreamImpl::Delegate* delegate_;
scoped_ptr<base::Timer> timer_;
SpdyStreamRequest stream_request_;
base::WeakPtr<SpdyStream> stream_;
@@ -92,11 +92,11 @@ class NET_EXPORT_PRIVATE BidirectionalStreamSpdyJob
// bytes sent over the network for |stream_| while it was open.
int64_t closed_stream_sent_bytes_;
- base::WeakPtrFactory<BidirectionalStreamSpdyJob> weak_factory_;
+ base::WeakPtrFactory<BidirectionalStreamSpdyImpl> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(BidirectionalStreamSpdyJob);
+ DISALLOW_COPY_AND_ASSIGN(BidirectionalStreamSpdyImpl);
};
} // namespace net
-#endif // NET_SPDY_BIDIRECTIONAL_STREAM_SPDY_JOB_H_
+#endif // NET_SPDY_BIDIRECTIONAL_STREAM_SPDY_IMPL_H_
diff --git a/chromium/net/spdy/buffered_spdy_framer.cc b/chromium/net/spdy/buffered_spdy_framer.cc
index d68dea78f01..ba0f4583fe3 100644
--- a/chromium/net/spdy/buffered_spdy_framer.cc
+++ b/chromium/net/spdy/buffered_spdy_framer.cc
@@ -34,15 +34,12 @@ SpdyMajorVersion NextProtoToSpdyMajorVersion(NextProto next_proto) {
return HTTP2;
}
-BufferedSpdyFramer::BufferedSpdyFramer(SpdyMajorVersion version,
- bool enable_compression)
+BufferedSpdyFramer::BufferedSpdyFramer(SpdyMajorVersion version)
: spdy_framer_(version),
visitor_(NULL),
header_buffer_valid_(false),
header_stream_id_(SpdyFramer::kInvalidStream),
- frames_received_(0) {
- spdy_framer_.set_enable_compression(enable_compression);
-}
+ frames_received_(0) {}
BufferedSpdyFramer::~BufferedSpdyFramer() {
}
@@ -204,6 +201,10 @@ void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id,
visitor_->OnStreamFrameData(stream_id, data, len, fin);
}
+void BufferedSpdyFramer::OnStreamEnd(SpdyStreamId stream_id) {
+ visitor_->OnStreamFrameData(stream_id, nullptr, 0, true);
+}
+
void BufferedSpdyFramer::OnStreamPadding(SpdyStreamId stream_id, size_t len) {
visitor_->OnStreamPadding(stream_id, len);
}
@@ -325,7 +326,7 @@ bool BufferedSpdyFramer::HasError() {
// TODO(jgraettinger): Eliminate uses of this method (prefer
// SpdySynStreamIR).
-SpdyFrame* BufferedSpdyFramer::CreateSynStream(
+SpdySerializedFrame* BufferedSpdyFramer::CreateSynStream(
SpdyStreamId stream_id,
SpdyStreamId associated_stream_id,
SpdyPriority priority,
@@ -338,12 +339,12 @@ SpdyFrame* BufferedSpdyFramer::CreateSynStream(
syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
// TODO(hkhalil): Avoid copy here.
syn_stream.set_header_block(*headers);
- return spdy_framer_.SerializeSynStream(syn_stream);
+ return new SpdySerializedFrame(spdy_framer_.SerializeSynStream(syn_stream));
}
// TODO(jgraettinger): Eliminate uses of this method (prefer
// SpdySynReplyIR).
-SpdyFrame* BufferedSpdyFramer::CreateSynReply(
+SpdySerializedFrame* BufferedSpdyFramer::CreateSynReply(
SpdyStreamId stream_id,
SpdyControlFlags flags,
const SpdyHeaderBlock* headers) {
@@ -351,21 +352,21 @@ SpdyFrame* BufferedSpdyFramer::CreateSynReply(
syn_reply.set_fin(flags & CONTROL_FLAG_FIN);
// TODO(hkhalil): Avoid copy here.
syn_reply.set_header_block(*headers);
- return spdy_framer_.SerializeSynReply(syn_reply);
+ return new SpdySerializedFrame(spdy_framer_.SerializeSynReply(syn_reply));
}
// TODO(jgraettinger): Eliminate uses of this method (prefer
// SpdyRstStreamIR).
-SpdyFrame* BufferedSpdyFramer::CreateRstStream(
+SpdySerializedFrame* BufferedSpdyFramer::CreateRstStream(
SpdyStreamId stream_id,
SpdyRstStreamStatus status) const {
SpdyRstStreamIR rst_ir(stream_id, status);
- return spdy_framer_.SerializeRstStream(rst_ir);
+ return new SpdySerializedFrame(spdy_framer_.SerializeRstStream(rst_ir));
}
// TODO(jgraettinger): Eliminate uses of this method (prefer
// SpdySettingsIR).
-SpdyFrame* BufferedSpdyFramer::CreateSettings(
+SpdySerializedFrame* BufferedSpdyFramer::CreateSettings(
const SettingsMap& values) const {
SpdySettingsIR settings_ir;
for (SettingsMap::const_iterator it = values.begin();
@@ -377,28 +378,28 @@ SpdyFrame* BufferedSpdyFramer::CreateSettings(
(it->second.first & SETTINGS_FLAG_PERSISTED) != 0,
it->second.second);
}
- return spdy_framer_.SerializeSettings(settings_ir);
+ return new SpdySerializedFrame(spdy_framer_.SerializeSettings(settings_ir));
}
// TODO(jgraettinger): Eliminate uses of this method (prefer SpdyPingIR).
-SpdyFrame* BufferedSpdyFramer::CreatePingFrame(SpdyPingId unique_id,
- bool is_ack) const {
+SpdySerializedFrame* BufferedSpdyFramer::CreatePingFrame(SpdyPingId unique_id,
+ bool is_ack) const {
SpdyPingIR ping_ir(unique_id);
ping_ir.set_is_ack(is_ack);
- return spdy_framer_.SerializePing(ping_ir);
+ return new SpdySerializedFrame(spdy_framer_.SerializePing(ping_ir));
}
// TODO(jgraettinger): Eliminate uses of this method (prefer SpdyGoAwayIR).
-SpdyFrame* BufferedSpdyFramer::CreateGoAway(
+SpdySerializedFrame* BufferedSpdyFramer::CreateGoAway(
SpdyStreamId last_accepted_stream_id,
SpdyGoAwayStatus status,
base::StringPiece debug_data) const {
SpdyGoAwayIR go_ir(last_accepted_stream_id, status, debug_data);
- return spdy_framer_.SerializeGoAway(go_ir);
+ return new SpdySerializedFrame(spdy_framer_.SerializeGoAway(go_ir));
}
// TODO(jgraettinger): Eliminate uses of this method (prefer SpdyHeadersIR).
-SpdyFrame* BufferedSpdyFramer::CreateHeaders(
+SpdySerializedFrame* BufferedSpdyFramer::CreateHeaders(
SpdyStreamId stream_id,
SpdyControlFlags flags,
SpdyPriority priority,
@@ -410,37 +411,38 @@ SpdyFrame* BufferedSpdyFramer::CreateHeaders(
headers_ir.set_priority(priority);
}
headers_ir.set_header_block(*headers);
- return spdy_framer_.SerializeHeaders(headers_ir);
+ return new SpdySerializedFrame(spdy_framer_.SerializeHeaders(headers_ir));
}
// TODO(jgraettinger): Eliminate uses of this method (prefer
// SpdyWindowUpdateIR).
-SpdyFrame* BufferedSpdyFramer::CreateWindowUpdate(
+SpdySerializedFrame* BufferedSpdyFramer::CreateWindowUpdate(
SpdyStreamId stream_id,
uint32_t delta_window_size) const {
SpdyWindowUpdateIR update_ir(stream_id, delta_window_size);
- return spdy_framer_.SerializeWindowUpdate(update_ir);
+ return new SpdySerializedFrame(spdy_framer_.SerializeWindowUpdate(update_ir));
}
// TODO(jgraettinger): Eliminate uses of this method (prefer SpdyDataIR).
-SpdyFrame* BufferedSpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
- const char* data,
- uint32_t len,
- SpdyDataFlags flags) {
+SpdySerializedFrame* BufferedSpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
+ const char* data,
+ uint32_t len,
+ SpdyDataFlags flags) {
SpdyDataIR data_ir(stream_id,
base::StringPiece(data, len));
data_ir.set_fin((flags & DATA_FLAG_FIN) != 0);
- return spdy_framer_.SerializeData(data_ir);
+ return new SpdySerializedFrame(spdy_framer_.SerializeData(data_ir));
}
// TODO(jgraettinger): Eliminate uses of this method (prefer SpdyPushPromiseIR).
-SpdyFrame* BufferedSpdyFramer::CreatePushPromise(
+SpdySerializedFrame* BufferedSpdyFramer::CreatePushPromise(
SpdyStreamId stream_id,
SpdyStreamId promised_stream_id,
const SpdyHeaderBlock* headers) {
SpdyPushPromiseIR push_promise_ir(stream_id, promised_stream_id);
push_promise_ir.set_header_block(*headers);
- return spdy_framer_.SerializePushPromise(push_promise_ir);
+ return new SpdySerializedFrame(
+ spdy_framer_.SerializePushPromise(push_promise_ir));
}
SpdyPriority BufferedSpdyFramer::GetHighestPriority() const {
diff --git a/chromium/net/spdy/buffered_spdy_framer.h b/chromium/net/spdy/buffered_spdy_framer.h
index 5f893ad44d8..8ad0defed0f 100644
--- a/chromium/net/spdy/buffered_spdy_framer.h
+++ b/chromium/net/spdy/buffered_spdy_framer.h
@@ -29,7 +29,7 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramerVisitorInterface {
public:
BufferedSpdyFramerVisitorInterface() {}
- // Called if an error is detected in the SpdyFrame protocol.
+ // 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.
@@ -145,8 +145,7 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramerVisitorInterface {
class NET_EXPORT_PRIVATE BufferedSpdyFramer
: public SpdyFramerVisitorInterface {
public:
- BufferedSpdyFramer(SpdyMajorVersion version,
- bool enable_compression);
+ explicit BufferedSpdyFramer(SpdyMajorVersion version);
~BufferedSpdyFramer() override;
// Sets callbacks to be called from the buffered spdy framer. A visitor must
@@ -182,6 +181,7 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramer
const char* data,
size_t len,
bool fin) override;
+ void OnStreamEnd(SpdyStreamId stream_id) override;
void OnStreamPadding(SpdyStreamId stream_id, size_t len) override;
SpdyHeadersHandlerInterface* OnHeaderFrameStart(
SpdyStreamId stream_id) override;
@@ -213,37 +213,37 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramer
SpdyFramer::SpdyState state() const;
bool MessageFullyRead();
bool HasError();
- SpdyFrame* CreateSynStream(SpdyStreamId stream_id,
- SpdyStreamId associated_stream_id,
- SpdyPriority priority,
- SpdyControlFlags flags,
- const SpdyHeaderBlock* headers);
- SpdyFrame* CreateSynReply(SpdyStreamId stream_id,
- SpdyControlFlags flags,
- const SpdyHeaderBlock* headers);
- SpdyFrame* CreateRstStream(SpdyStreamId stream_id,
- SpdyRstStreamStatus status) const;
- SpdyFrame* CreateSettings(const SettingsMap& values) const;
- SpdyFrame* CreatePingFrame(SpdyPingId unique_id, bool is_ack) const;
- SpdyFrame* CreateGoAway(SpdyStreamId last_accepted_stream_id,
- SpdyGoAwayStatus status,
- base::StringPiece debug_data) const;
- SpdyFrame* CreateHeaders(SpdyStreamId stream_id,
- SpdyControlFlags flags,
- SpdyPriority priority,
- const SpdyHeaderBlock* headers);
- SpdyFrame* CreateWindowUpdate(SpdyStreamId stream_id,
- uint32_t delta_window_size) const;
- SpdyFrame* CreateDataFrame(SpdyStreamId stream_id,
- const char* data,
- uint32_t len,
- SpdyDataFlags flags);
- SpdyFrame* CreatePushPromise(SpdyStreamId stream_id,
- SpdyStreamId promised_stream_id,
- const SpdyHeaderBlock* headers);
+ SpdySerializedFrame* CreateSynStream(SpdyStreamId stream_id,
+ SpdyStreamId associated_stream_id,
+ SpdyPriority priority,
+ SpdyControlFlags flags,
+ const SpdyHeaderBlock* headers);
+ SpdySerializedFrame* CreateSynReply(SpdyStreamId stream_id,
+ SpdyControlFlags flags,
+ const SpdyHeaderBlock* headers);
+ SpdySerializedFrame* CreateRstStream(SpdyStreamId stream_id,
+ SpdyRstStreamStatus status) const;
+ SpdySerializedFrame* CreateSettings(const SettingsMap& values) const;
+ SpdySerializedFrame* CreatePingFrame(SpdyPingId unique_id, bool is_ack) const;
+ SpdySerializedFrame* CreateGoAway(SpdyStreamId last_accepted_stream_id,
+ SpdyGoAwayStatus status,
+ base::StringPiece debug_data) const;
+ SpdySerializedFrame* CreateHeaders(SpdyStreamId stream_id,
+ SpdyControlFlags flags,
+ SpdyPriority priority,
+ const SpdyHeaderBlock* headers);
+ SpdySerializedFrame* CreateWindowUpdate(SpdyStreamId stream_id,
+ uint32_t delta_window_size) const;
+ SpdySerializedFrame* CreateDataFrame(SpdyStreamId stream_id,
+ const char* data,
+ uint32_t len,
+ SpdyDataFlags flags);
+ SpdySerializedFrame* CreatePushPromise(SpdyStreamId stream_id,
+ SpdyStreamId promised_stream_id,
+ const SpdyHeaderBlock* headers);
// Serialize a frame of unknown type.
- SpdySerializedFrame* SerializeFrame(const SpdyFrameIR& frame) {
+ SpdySerializedFrame SerializeFrame(const SpdyFrameIR& frame) {
return spdy_framer_.SerializeFrame(frame);
}
diff --git a/chromium/net/spdy/buffered_spdy_framer_unittest.cc b/chromium/net/spdy/buffered_spdy_framer_unittest.cc
index fd61298e7a0..be2d66e6036 100644
--- a/chromium/net/spdy/buffered_spdy_framer_unittest.cc
+++ b/chromium/net/spdy/buffered_spdy_framer_unittest.cc
@@ -14,7 +14,7 @@ namespace {
class TestBufferedSpdyVisitor : public BufferedSpdyFramerVisitorInterface {
public:
explicit TestBufferedSpdyVisitor(SpdyMajorVersion spdy_version)
- : buffered_spdy_framer_(spdy_version, true),
+ : buffered_spdy_framer_(spdy_version),
error_count_(0),
setting_count_(0),
syn_frame_count_(0),
@@ -118,13 +118,13 @@ class TestBufferedSpdyVisitor : public BufferedSpdyFramerVisitorInterface {
goaway_debug_data_.assign(debug_data.data(), debug_data.size());
}
- void OnDataFrameHeader(const SpdyFrame* frame) {
+ void OnDataFrameHeader(const SpdySerializedFrame* frame) {
LOG(FATAL) << "Unexpected OnDataFrameHeader call.";
}
- void OnRstStream(const SpdyFrame& frame) {}
- void OnGoAway(const SpdyFrame& frame) {}
- void OnPing(const SpdyFrame& frame) {}
+ void OnRstStream(const SpdySerializedFrame& frame) {}
+ void OnGoAway(const SpdySerializedFrame& frame) {}
+ void OnPing(const SpdySerializedFrame& frame) {}
void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {}
void OnPushPromise(SpdyStreamId stream_id,
@@ -208,12 +208,12 @@ TEST_P(BufferedSpdyFramerTest, OnSetting) {
SpdySettingsIR settings_ir;
settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, false, false, 2);
settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, false, false, 3);
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
+ SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
TestBufferedSpdyVisitor visitor(spdy_version());
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->size());
+ reinterpret_cast<unsigned char*>(control_frame.data()),
+ control_frame.size());
EXPECT_EQ(0, visitor.error_count_);
EXPECT_EQ(2, visitor.setting_count_);
}
@@ -226,13 +226,12 @@ TEST_P(BufferedSpdyFramerTest, ReadSynStreamHeaderBlock) {
SpdyHeaderBlock headers;
headers["aa"] = "vv";
headers["bb"] = "ww";
- BufferedSpdyFramer framer(spdy_version(), true);
- scoped_ptr<SpdyFrame> control_frame(
- framer.CreateSynStream(1, // stream_id
- 0, // associated_stream_id
- 1, // priority
- CONTROL_FLAG_NONE,
- &headers));
+ BufferedSpdyFramer framer(spdy_version());
+ scoped_ptr<SpdySerializedFrame> control_frame(
+ framer.CreateSynStream(1, // stream_id
+ 0, // associated_stream_id
+ 1, // priority
+ CONTROL_FLAG_NONE, &headers));
EXPECT_TRUE(control_frame.get() != NULL);
TestBufferedSpdyVisitor visitor(spdy_version());
@@ -255,11 +254,10 @@ TEST_P(BufferedSpdyFramerTest, ReadSynReplyHeaderBlock) {
SpdyHeaderBlock headers;
headers["alpha"] = "beta";
headers["gamma"] = "delta";
- BufferedSpdyFramer framer(spdy_version(), true);
- scoped_ptr<SpdyFrame> control_frame(
- framer.CreateSynReply(1, // stream_id
- CONTROL_FLAG_NONE,
- &headers));
+ BufferedSpdyFramer framer(spdy_version());
+ scoped_ptr<SpdySerializedFrame> control_frame(
+ framer.CreateSynReply(1, // stream_id
+ CONTROL_FLAG_NONE, &headers));
EXPECT_TRUE(control_frame.get() != NULL);
TestBufferedSpdyVisitor visitor(spdy_version());
@@ -283,11 +281,11 @@ TEST_P(BufferedSpdyFramerTest, ReadHeadersHeaderBlock) {
SpdyHeaderBlock headers;
headers["alpha"] = "beta";
headers["gamma"] = "delta";
- BufferedSpdyFramer framer(spdy_version(), true);
- scoped_ptr<SpdyFrame> control_frame(
- framer.CreateHeaders(1, // stream_id
+ BufferedSpdyFramer framer(spdy_version());
+ scoped_ptr<SpdySerializedFrame> control_frame(
+ framer.CreateHeaders(1, // stream_id
CONTROL_FLAG_NONE,
- 0, // priority
+ 0, // priority
&headers));
EXPECT_TRUE(control_frame.get() != NULL);
@@ -309,8 +307,8 @@ TEST_P(BufferedSpdyFramerTest, ReadPushPromiseHeaderBlock) {
SpdyHeaderBlock headers;
headers["alpha"] = "beta";
headers["gamma"] = "delta";
- BufferedSpdyFramer framer(spdy_version(), true);
- scoped_ptr<SpdyFrame> control_frame(
+ BufferedSpdyFramer framer(spdy_version());
+ scoped_ptr<SpdySerializedFrame> control_frame(
framer.CreatePushPromise(1, 2, &headers));
EXPECT_TRUE(control_frame.get() != NULL);
@@ -331,8 +329,8 @@ TEST_P(BufferedSpdyFramerTest, ReadPushPromiseHeaderBlock) {
TEST_P(BufferedSpdyFramerTest, GoAwayDebugData) {
if (spdy_version() < HTTP2)
return;
- BufferedSpdyFramer framer(spdy_version(), true);
- scoped_ptr<SpdyFrame> goaway_frame(
+ BufferedSpdyFramer framer(spdy_version());
+ scoped_ptr<SpdySerializedFrame> goaway_frame(
framer.CreateGoAway(2u, GOAWAY_FRAME_SIZE_ERROR, "foo"));
TestBufferedSpdyVisitor visitor(spdy_version());
diff --git a/chromium/net/spdy/hpack/hpack_decoder.cc b/chromium/net/spdy/hpack/hpack_decoder.cc
index 13654dd3f5c..6d4ab9896d7 100644
--- a/chromium/net/spdy/hpack/hpack_decoder.cc
+++ b/chromium/net/spdy/hpack/hpack_decoder.cc
@@ -24,6 +24,7 @@ const char kCookieKey[] = "cookie";
HpackDecoder::HpackDecoder()
: max_string_literal_size_(kDefaultMaxStringLiteralSize),
handler_(nullptr),
+ total_header_bytes_(0),
regular_header_seen_(false),
header_block_started_(false) {}
@@ -61,7 +62,7 @@ bool HpackDecoder::HandleControlFrameHeadersComplete(size_t* compressed_len) {
}
}
if (handler_ != nullptr) {
- handler_->OnHeaderBlockEnd(headers_block_buffer_.size());
+ handler_->OnHeaderBlockEnd(total_header_bytes_);
}
headers_block_buffer_.clear();
header_block_started_ = false;
@@ -71,6 +72,8 @@ bool HpackDecoder::HandleControlFrameHeadersComplete(size_t* compressed_len) {
bool HpackDecoder::HandleHeaderRepresentation(StringPiece name,
StringPiece value) {
+ total_header_bytes_ += name.size() + value.size();
+
// Fail if pseudo-header follows regular header.
if (name.size() > 0) {
if (name[0] == kPseudoHeaderPrefix) {
diff --git a/chromium/net/spdy/hpack/hpack_decoder.h b/chromium/net/spdy/hpack/hpack_decoder.h
index da6162d7f37..b430f7c56ba 100644
--- a/chromium/net/spdy/hpack/hpack_decoder.h
+++ b/chromium/net/spdy/hpack/hpack_decoder.h
@@ -45,6 +45,7 @@ class NET_EXPORT_PRIVATE HpackDecoder {
// headers to it rather than accumulating them in a SpdyHeaderBlock.
void HandleControlFrameHeadersStart(SpdyHeadersHandlerInterface* handler) {
handler_ = handler;
+ total_header_bytes_ = 0;
}
// Called as headers data arrives. Returns false if an error occurred.
@@ -103,6 +104,7 @@ class NET_EXPORT_PRIVATE HpackDecoder {
// If non-NULL, handles decoded headers.
SpdyHeadersHandlerInterface* handler_;
+ size_t total_header_bytes_;
// Flag to keep track of having seen a regular header field.
bool regular_header_seen_;
diff --git a/chromium/net/spdy/hpack/hpack_decoder_test.cc b/chromium/net/spdy/hpack/hpack_decoder_test.cc
index 7c3b7d6753a..e0c49caed8f 100644
--- a/chromium/net/spdy/hpack/hpack_decoder_test.cc
+++ b/chromium/net/spdy/hpack/hpack_decoder_test.cc
@@ -12,7 +12,6 @@
#include "net/spdy/hpack/hpack_encoder.h"
#include "net/spdy/hpack/hpack_input_stream.h"
#include "net/spdy/hpack/hpack_output_stream.h"
-#include "net/spdy/spdy_headers_handler_interface.h"
#include "net/spdy/spdy_protocol.h"
#include "net/spdy/spdy_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -24,37 +23,6 @@ namespace test {
using base::StringPiece;
using std::string;
-// A test implementation of SpdyHeadersHandlerInterface.
-class TestHeadersHandler : public SpdyHeadersHandlerInterface {
- public:
- TestHeadersHandler() : header_bytes_parsed_(0) {}
-
- void OnHeaderBlockStart() override { block_.clear(); }
-
- void OnHeader(StringPiece key, StringPiece value) override {
- auto it = block_.find(key);
- if (it == block_.end()) {
- block_[key] = value;
- } else {
- string new_value = it->second.as_string();
- new_value.append((key == "cookie") ? "; " : string(1, '\0'));
- value.AppendToString(&new_value);
- block_.ReplaceOrAppendHeader(key, new_value);
- }
- }
-
- void OnHeaderBlockEnd(size_t header_bytes_parsed) override {
- header_bytes_parsed_ = header_bytes_parsed;
- }
-
- const SpdyHeaderBlock& decoded_block() const { return block_; }
- size_t header_bytes_parsed() { return header_bytes_parsed_; }
-
- private:
- SpdyHeaderBlock block_;
- size_t header_bytes_parsed_;
-};
-
class HpackDecoderPeer {
public:
explicit HpackDecoderPeer(HpackDecoder* decoder) : decoder_(decoder) {}
diff --git a/chromium/net/spdy/hpack/hpack_header_table.cc b/chromium/net/spdy/hpack/hpack_header_table.cc
index bf5d312ea0b..01e96c09a0c 100644
--- a/chromium/net/spdy/hpack/hpack_header_table.cc
+++ b/chromium/net/spdy/hpack/hpack_header_table.cc
@@ -14,29 +14,27 @@ namespace net {
using base::StringPiece;
-bool HpackHeaderTable::EntryComparator::operator()(
- const HpackEntry* lhs,
- const HpackEntry* rhs) const {
- int result = lhs->name().compare(rhs->name());
- if (result != 0) {
- return result < 0;
- }
- result = lhs->value().compare(rhs->value());
- if (result != 0) {
- return result < 0;
- }
- const size_t lhs_index = lhs->IsLookup() ? 0 : 1 + lhs->InsertionIndex();
- const size_t rhs_index = rhs->IsLookup() ? 0 : 1 + rhs->InsertionIndex();
- DCHECK(lhs == rhs || lhs_index != rhs_index)
- << "lhs: (" << lhs->name() << ", " << rhs->value() << ") rhs: ("
- << rhs->name() << ", " << rhs->value() << ")"
- << " lhs index: " << lhs_index << " rhs index: " << rhs_index;
- return lhs_index < rhs_index;
+size_t HpackHeaderTable::EntryHasher::operator()(
+ const HpackEntry* entry) const {
+ return base::StringPieceHash()(entry->name()) ^
+ base::StringPieceHash()(entry->value());
+}
+
+bool HpackHeaderTable::EntriesEq::operator()(const HpackEntry* lhs,
+ const HpackEntry* rhs) const {
+ if (lhs == nullptr) {
+ return rhs == nullptr;
+ }
+ if (rhs == nullptr) {
+ return false;
+ }
+ return lhs->name() == rhs->name() && lhs->value() == rhs->value();
}
HpackHeaderTable::HpackHeaderTable()
: static_entries_(ObtainHpackStaticTable().GetStaticEntries()),
static_index_(ObtainHpackStaticTable().GetStaticIndex()),
+ static_name_index_(ObtainHpackStaticTable().GetStaticNameIndex()),
settings_size_bound_(kDefaultHeaderTableSizeSetting),
size_(0),
max_size_(kDefaultHeaderTableSizeSetting),
@@ -60,17 +58,16 @@ const HpackEntry* HpackHeaderTable::GetByIndex(size_t index) {
}
const HpackEntry* HpackHeaderTable::GetByName(StringPiece name) {
- HpackEntry query(name, "");
{
- OrderedEntrySet::const_iterator it = static_index_.lower_bound(&query);
- if (it != static_index_.end() && (*it)->name() == name) {
- return *it;
+ NameToEntryMap::const_iterator it = static_name_index_.find(name);
+ if (it != static_name_index_.end()) {
+ return it->second;
}
}
{
- OrderedEntrySet::const_iterator it = dynamic_index_.lower_bound(&query);
- if (it != dynamic_index_.end() && (*it)->name() == name) {
- return *it;
+ NameToEntryMap::const_iterator it = dynamic_name_index_.find(name);
+ if (it != dynamic_name_index_.end()) {
+ return it->second;
}
}
return NULL;
@@ -80,16 +77,14 @@ const HpackEntry* HpackHeaderTable::GetByNameAndValue(StringPiece name,
StringPiece value) {
HpackEntry query(name, value);
{
- OrderedEntrySet::const_iterator it = static_index_.lower_bound(&query);
- if (it != static_index_.end() && (*it)->name() == name &&
- (*it)->value() == value) {
+ UnorderedEntrySet::const_iterator it = static_index_.find(&query);
+ if (it != static_index_.end()) {
return *it;
}
}
{
- OrderedEntrySet::const_iterator it = dynamic_index_.lower_bound(&query);
- if (it != dynamic_index_.end() && (*it)->name() == name &&
- (*it)->value() == value) {
+ UnorderedEntrySet::const_iterator it = dynamic_index_.find(&query);
+ if (it != dynamic_index_.end()) {
return *it;
}
}
@@ -159,7 +154,22 @@ void HpackHeaderTable::Evict(size_t count) {
HpackEntry* entry = &dynamic_entries_.back();
size_ -= entry->Size();
- CHECK_EQ(1u, dynamic_index_.erase(entry));
+ UnorderedEntrySet::iterator it = dynamic_index_.find(entry);
+ DCHECK(it != dynamic_index_.end());
+ // Only remove an entry from the index if its insertion index matches;
+ // otherwise, the index refers to another entry with the same name and
+ // value.
+ if ((*it)->InsertionIndex() == entry->InsertionIndex()) {
+ dynamic_index_.erase(it);
+ }
+ NameToEntryMap::iterator name_it = dynamic_name_index_.find(entry->name());
+ DCHECK(name_it != dynamic_name_index_.end());
+ // Only remove an entry from the literal index if its insertion index
+ /// matches; otherwise, the index refers to another entry with the same
+ // name.
+ if (name_it->second->InsertionIndex() == entry->InsertionIndex()) {
+ dynamic_name_index_.erase(name_it);
+ }
dynamic_entries_.pop_back();
}
}
@@ -178,7 +188,35 @@ const HpackEntry* HpackHeaderTable::TryAddEntry(StringPiece name,
dynamic_entries_.push_front(HpackEntry(name, value,
false, // is_static
total_insertions_));
- CHECK(dynamic_index_.insert(&dynamic_entries_.front()).second);
+ HpackEntry* new_entry = &dynamic_entries_.front();
+ auto index_result = dynamic_index_.insert(new_entry);
+ if (!index_result.second) {
+ // An entry with the same name and value already exists in the dynamic
+ // index. We should replace it with the newly added entry.
+ DVLOG(1) << "Found existing entry: "
+ << (*index_result.first)->GetDebugString()
+ << " replacing with: " << new_entry->GetDebugString();
+ DCHECK_GT(new_entry->InsertionIndex(),
+ (*index_result.first)->InsertionIndex());
+ dynamic_index_.erase(index_result.first);
+ CHECK(dynamic_index_.insert(new_entry).second);
+ }
+
+ auto name_result =
+ dynamic_name_index_.insert(std::make_pair(new_entry->name(), new_entry));
+ if (!name_result.second) {
+ // An entry with the same name already exists in the dynamic index. We
+ // should replace it with the newly added entry.
+ DVLOG(1) << "Found existing entry: "
+ << name_result.first->second->GetDebugString()
+ << " replacing with: " << new_entry->GetDebugString();
+ DCHECK_GT(new_entry->InsertionIndex(),
+ name_result.first->second->InsertionIndex());
+ dynamic_name_index_.erase(name_result.first);
+ auto insert_result = dynamic_name_index_.insert(
+ std::make_pair(new_entry->name(), new_entry));
+ CHECK(insert_result.second);
+ }
size_ += entry_size;
++total_insertions_;
@@ -193,14 +231,20 @@ void HpackHeaderTable::DebugLogTableState() const {
DVLOG(2) << " " << it->GetDebugString();
}
DVLOG(2) << "Full Static Index:";
- for (OrderedEntrySet::const_iterator it = static_index_.begin();
- it != static_index_.end(); ++it) {
- DVLOG(2) << " " << (*it)->GetDebugString();
+ for (const auto entry : static_index_) {
+ DVLOG(2) << " " << entry->GetDebugString();
+ }
+ DVLOG(2) << "Full Static Name Index:";
+ for (const auto it : static_name_index_) {
+ DVLOG(2) << " " << it.first << ": " << it.second->GetDebugString();
}
DVLOG(2) << "Full Dynamic Index:";
- for (OrderedEntrySet::const_iterator it = dynamic_index_.begin();
- it != dynamic_index_.end(); ++it) {
- DVLOG(2) << " " << (*it)->GetDebugString();
+ for (const auto entry : dynamic_index_) {
+ DVLOG(2) << " " << entry->GetDebugString();
+ }
+ DVLOG(2) << "Full Dynamic Name Index:";
+ for (const auto it : dynamic_name_index_) {
+ DVLOG(2) << " " << it.first << ": " << it.second->GetDebugString();
}
}
diff --git a/chromium/net/spdy/hpack/hpack_header_table.h b/chromium/net/spdy/hpack/hpack_header_table.h
index be0ac0b7b6a..02b9e27d745 100644
--- a/chromium/net/spdy/hpack/hpack_header_table.h
+++ b/chromium/net/spdy/hpack/hpack_header_table.h
@@ -7,9 +7,11 @@
#include <cstddef>
#include <deque>
-#include <set>
+#include <unordered_map>
+#include <unordered_set>
#include "base/macros.h"
+#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
#include "net/spdy/hpack/hpack_entry.h"
@@ -33,15 +35,18 @@ class NET_EXPORT_PRIVATE HpackHeaderTable {
// extended to map to list iterators.
typedef std::deque<HpackEntry> EntryTable;
- // Implements a total ordering of HpackEntry on name(), value(), then index
- // ascending. Note that index may change over the lifetime of an HpackEntry,
- // but the relative index order of two entries will not. This comparator is
- // composed with the 'lookup' HpackEntry constructor to allow for efficient
- // lower-bounding of matching entries.
- struct NET_EXPORT_PRIVATE EntryComparator {
+ struct NET_EXPORT_PRIVATE EntryHasher {
+ size_t operator()(const HpackEntry* entry) const;
+ };
+ struct NET_EXPORT_PRIVATE EntriesEq {
bool operator()(const HpackEntry* lhs, const HpackEntry* rhs) const;
};
- typedef std::set<HpackEntry*, EntryComparator> OrderedEntrySet;
+
+ using UnorderedEntrySet =
+ std::unordered_set<HpackEntry*, EntryHasher, EntriesEq>;
+ using NameToEntryMap = std::unordered_map<base::StringPiece,
+ const HpackEntry*,
+ base::StringPieceHash>;
HpackHeaderTable();
@@ -109,8 +114,18 @@ class NET_EXPORT_PRIVATE HpackHeaderTable {
const EntryTable& static_entries_;
EntryTable dynamic_entries_;
- const OrderedEntrySet& static_index_;
- OrderedEntrySet dynamic_index_;
+ // Tracks the unique HpackEntry for a given header name and value.
+ const UnorderedEntrySet& static_index_;
+
+ // Tracks the first static entry for each name in the static table.
+ const NameToEntryMap& static_name_index_;
+
+ // Tracks the most recently inserted HpackEntry for a given header name and
+ // value.
+ UnorderedEntrySet dynamic_index_;
+
+ // Tracks the most recently inserted HpackEntry for a given header name.
+ NameToEntryMap dynamic_name_index_;
// Last acknowledged value for SETTINGS_HEADER_TABLE_SIZE.
size_t settings_size_bound_;
diff --git a/chromium/net/spdy/hpack/hpack_header_table_test.cc b/chromium/net/spdy/hpack/hpack_header_table_test.cc
index 1d9071d2ccf..b79b7a717f9 100644
--- a/chromium/net/spdy/hpack/hpack_header_table_test.cc
+++ b/chromium/net/spdy/hpack/hpack_header_table_test.cc
@@ -221,8 +221,8 @@ TEST_F(HpackHeaderTableTest, EntryIndexing) {
EXPECT_EQ(entry1, table_.GetByIndex(68));
EXPECT_EQ(first_static_entry, table_.GetByIndex(1));
- // Querying by name returns the lowest-value matching entry.
- EXPECT_EQ(entry3, table_.GetByName("key-1"));
+ // Querying by name returns the most recently added matching entry.
+ EXPECT_EQ(entry5, table_.GetByName("key-1"));
EXPECT_EQ(entry7, table_.GetByName("key-2"));
EXPECT_EQ(entry2->name(),
table_.GetByName(first_static_entry->name())->name());
@@ -232,7 +232,7 @@ TEST_F(HpackHeaderTableTest, EntryIndexing) {
// static entries, and the highest-index one among dynamic entries.
EXPECT_EQ(entry3, table_.GetByNameAndValue("key-1", "Value One"));
EXPECT_EQ(entry5, table_.GetByNameAndValue("key-1", "Value Two"));
- EXPECT_EQ(entry4, table_.GetByNameAndValue("key-2", "Value Three"));
+ EXPECT_EQ(entry6, table_.GetByNameAndValue("key-2", "Value Three"));
EXPECT_EQ(entry7, table_.GetByNameAndValue("key-2", "Value Four"));
EXPECT_EQ(first_static_entry,
table_.GetByNameAndValue(first_static_entry->name(),
@@ -401,41 +401,48 @@ TEST_F(HpackHeaderTableTest, TryAddTooLargeEntry) {
EXPECT_EQ(0u, peer_.dynamic_entries().size());
}
-TEST_F(HpackHeaderTableTest, ComparatorNameOrdering) {
+TEST_F(HpackHeaderTableTest, EntryNamesDiffer) {
HpackEntry entry1("header", "value");
HpackEntry entry2("HEADER", "value");
- HpackHeaderTable::EntryComparator comparator;
- EXPECT_FALSE(comparator(&entry1, &entry2));
- EXPECT_TRUE(comparator(&entry2, &entry1));
+ HpackHeaderTable::EntryHasher hasher;
+ EXPECT_NE(hasher(&entry1), hasher(&entry2));
+
+ HpackHeaderTable::EntriesEq eq;
+ EXPECT_FALSE(eq(&entry1, &entry2));
}
-TEST_F(HpackHeaderTableTest, ComparatorValueOrdering) {
+TEST_F(HpackHeaderTableTest, EntryValuesDiffer) {
HpackEntry entry1("header", "value");
HpackEntry entry2("header", "VALUE");
- HpackHeaderTable::EntryComparator comparator;
- EXPECT_FALSE(comparator(&entry1, &entry2));
- EXPECT_TRUE(comparator(&entry2, &entry1));
+ HpackHeaderTable::EntryHasher hasher;
+ EXPECT_NE(hasher(&entry1), hasher(&entry2));
+
+ HpackHeaderTable::EntriesEq eq;
+ EXPECT_FALSE(eq(&entry1, &entry2));
}
-TEST_F(HpackHeaderTableTest, ComparatorIndexOrdering) {
- HpackHeaderTable::EntryComparator comparator;
+TEST_F(HpackHeaderTableTest, EntriesEqual) {
HpackEntry entry1(DynamicEntry("name", "value"));
HpackEntry entry2(DynamicEntry("name", "value"));
- // |entry1| has lower insertion index than |entry2|.
- EXPECT_TRUE(comparator(&entry1, &entry2));
- EXPECT_FALSE(comparator(&entry2, &entry1));
+ HpackHeaderTable::EntryHasher hasher;
+ EXPECT_EQ(hasher(&entry1), hasher(&entry2));
+
+ HpackHeaderTable::EntriesEq eq;
+ EXPECT_TRUE(eq(&entry1, &entry2));
}
-TEST_F(HpackHeaderTableTest, ComparatorEqualityOrdering) {
+TEST_F(HpackHeaderTableTest, StaticAndDynamicEntriesEqual) {
HpackEntry entry1("name", "value");
HpackEntry entry2(DynamicEntry("name", "value"));
- HpackHeaderTable::EntryComparator comparator;
- EXPECT_FALSE(comparator(&entry1, &entry1));
- EXPECT_FALSE(comparator(&entry2, &entry2));
+ HpackHeaderTable::EntryHasher hasher;
+ EXPECT_EQ(hasher(&entry1), hasher(&entry2));
+
+ HpackHeaderTable::EntriesEq eq;
+ EXPECT_TRUE(eq(&entry1, &entry2));
}
} // namespace
diff --git a/chromium/net/spdy/hpack/hpack_static_table.cc b/chromium/net/spdy/hpack/hpack_static_table.cc
index b954c3482d7..5588ebe1838 100644
--- a/chromium/net/spdy/hpack/hpack_static_table.cc
+++ b/chromium/net/spdy/hpack/hpack_static_table.cc
@@ -26,7 +26,10 @@ void HpackStaticTable::Initialize(const HpackStaticEntry* static_entry_table,
base::StringPiece(it->value, it->value_len),
true, // is_static
total_insertions));
- CHECK(static_index_.insert(&static_entries_.back()).second);
+ HpackEntry* entry = &static_entries_.back();
+ CHECK(static_index_.insert(entry).second);
+ // Multiple static entries may have the same name, so inserts may fail.
+ static_name_index_.insert(make_pair(entry->name(), entry));
++total_insertions;
}
diff --git a/chromium/net/spdy/hpack/hpack_static_table.h b/chromium/net/spdy/hpack/hpack_static_table.h
index e7616b33843..42798bfc959 100644
--- a/chromium/net/spdy/hpack/hpack_static_table.h
+++ b/chromium/net/spdy/hpack/hpack_static_table.h
@@ -34,13 +34,17 @@ class NET_EXPORT_PRIVATE HpackStaticTable {
const HpackHeaderTable::EntryTable& GetStaticEntries() const {
return static_entries_;
}
- const HpackHeaderTable::OrderedEntrySet& GetStaticIndex() const {
+ const HpackHeaderTable::UnorderedEntrySet& GetStaticIndex() const {
return static_index_;
}
+ const HpackHeaderTable::NameToEntryMap& GetStaticNameIndex() const {
+ return static_name_index_;
+ }
private:
HpackHeaderTable::EntryTable static_entries_;
- HpackHeaderTable::OrderedEntrySet static_index_;
+ HpackHeaderTable::UnorderedEntrySet static_index_;
+ HpackHeaderTable::NameToEntryMap static_name_index_;
};
} // namespace net
diff --git a/chromium/net/spdy/hpack/hpack_static_table_test.cc b/chromium/net/spdy/hpack/hpack_static_table_test.cc
index 441668f4349..8728d82fac5 100644
--- a/chromium/net/spdy/hpack/hpack_static_table_test.cc
+++ b/chromium/net/spdy/hpack/hpack_static_table_test.cc
@@ -4,6 +4,7 @@
#include "net/spdy/hpack/hpack_static_table.h"
+#include <set>
#include <vector>
#include "net/base/net_export.h"
@@ -33,8 +34,16 @@ TEST_F(HpackStaticTableTest, Initialize) {
HpackHeaderTable::EntryTable static_entries = table_.GetStaticEntries();
EXPECT_EQ(static_table.size(), static_entries.size());
- HpackHeaderTable::OrderedEntrySet static_index = table_.GetStaticIndex();
+ HpackHeaderTable::UnorderedEntrySet static_index = table_.GetStaticIndex();
EXPECT_EQ(static_table.size(), static_index.size());
+
+ HpackHeaderTable::NameToEntryMap static_name_index =
+ table_.GetStaticNameIndex();
+ std::set<base::StringPiece> names;
+ for (auto entry : static_index) {
+ names.insert(entry->name());
+ }
+ EXPECT_EQ(names.size(), static_name_index.size());
}
// Test that ObtainHpackStaticTable returns the same instance every time.
diff --git a/chromium/net/spdy/http2_priority_dependencies.cc b/chromium/net/spdy/http2_priority_dependencies.cc
new file mode 100644
index 00000000000..a09ef1d08ae
--- /dev/null
+++ b/chromium/net/spdy/http2_priority_dependencies.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/http2_priority_dependencies.h"
+
+namespace net {
+
+Http2PriorityDependencies::Http2PriorityDependencies() {}
+
+Http2PriorityDependencies::~Http2PriorityDependencies() {}
+
+void Http2PriorityDependencies::OnStreamSynSent(
+ SpdyStreamId id,
+ SpdyPriority priority,
+ SpdyStreamId* dependent_stream_id,
+ bool* exclusive) {
+ DCHECK(entry_by_stream_id_.find(id) == entry_by_stream_id_.end());
+
+ *dependent_stream_id = 0ul;
+ *exclusive = true;
+
+ // Find the next highest entry in total order.
+ for (int i = priority; i >= kV3HighestPriority; --i) {
+ if (!id_priority_lists_[i].empty()) {
+ *dependent_stream_id = id_priority_lists_[i].back().first;
+ break;
+ }
+ }
+
+ 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;
+}
+
+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;
+
+ IdList::iterator it = emit->second;
+ id_priority_lists_[it->second].erase(it);
+ entry_by_stream_id_.erase(emit);
+}
+
+} // namespace net
diff --git a/chromium/net/spdy/http2_priority_dependencies.h b/chromium/net/spdy/http2_priority_dependencies.h
new file mode 100644
index 00000000000..8f4ced01167
--- /dev/null
+++ b/chromium/net/spdy/http2_priority_dependencies.h
@@ -0,0 +1,60 @@
+// 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_PRIORITY_DEPENDENCIES_H_
+#define NET_HTTP2_PRIORITY_DEPENDENCIES_H_
+
+#include <list>
+#include <map>
+
+#include "net/spdy/spdy_protocol.h"
+
+namespace net {
+
+// A helper class encapsulating the state and logic to set dependencies of
+// HTTP2 streams based on their SpdyPriority and the ordering
+// of creation and deletion of the streams.
+class NET_EXPORT_PRIVATE Http2PriorityDependencies {
+ public:
+ 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).
+ // 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 OnStreamDestruction(SpdyStreamId id);
+
+ private:
+ // The requirements for the internal data structure for this class are:
+ // a) Constant time insertion of entries at the end of the list,
+ // b) Fast removal of any entry based on its id.
+ // c) Constant time lookup of the entry at the end of the list.
+ // std::list would satisfy (a) & (c), but some form of map is
+ // needed for (b). The priority must be included in the map
+ // entries so that deletion can determine which list in id_priority_lists_
+ // to erase from.
+ using IdList = std::list<std::pair<SpdyStreamId, SpdyPriority>>;
+ using EntryMap = std::map<SpdyStreamId, IdList::iterator>;
+
+ IdList id_priority_lists_[kV3LowestPriority + 1];
+
+ // Tracks the location of an id anywhere in the above vector of lists.
+ // Iterators to list elements remain valid until those particular elements
+ // are erased.
+ EntryMap entry_by_stream_id_;
+};
+
+} // namespace net
+
+#endif // NET_HTTP2_PRIORITY_DEPENDENCIES_H_
diff --git a/chromium/net/spdy/http2_priority_dependencies_unittest.cc b/chromium/net/spdy/http2_priority_dependencies_unittest.cc
new file mode 100644
index 00000000000..05c482bbfc5
--- /dev/null
+++ b/chromium/net/spdy/http2_priority_dependencies_unittest.cc
@@ -0,0 +1,144 @@
+// 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_priority_dependencies.h"
+
+#include "testing/platform_test.h"
+
+namespace net {
+
+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 };
+
+ SpdyStreamId GetId() { return ++next_id_; }
+
+ void TestStreamCreation(SpdyStreamId new_id,
+ SpdyPriority priority,
+ 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);
+ }
+
+ void OnStreamDestruction(SpdyStreamId id) {
+ dependency_state.OnStreamDestruction(id);
+ }
+
+ private:
+ SpdyStreamId next_id_;
+ 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();
+
+ TestStreamCreation(first_id, MEDIUM, 0u);
+ TestStreamCreation(second_id, MEDIUM, first_id);
+ TestStreamCreation(third_id, MEDIUM, second_id);
+}
+
+// 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();
+
+ TestStreamCreation(first_id, LOWEST, 0u);
+ TestStreamCreation(second_id, MEDIUM, 0u);
+ TestStreamCreation(third_id, HIGHEST, 0u);
+}
+
+// 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();
+
+ TestStreamCreation(first_id, HIGHEST, 0u);
+ TestStreamCreation(second_id, MEDIUM, first_id);
+ TestStreamCreation(third_id, LOWEST, second_id);
+}
+
+// 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();
+
+ TestStreamCreation(first_id, HIGHEST, 0u);
+ OnStreamDestruction(first_id);
+ TestStreamCreation(second_id, MEDIUM, 0u);
+ OnStreamDestruction(second_id);
+ TestStreamCreation(third_id, LOWEST, 0u);
+}
+
+// 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();
+
+ TestStreamCreation(first_id, HIGHEST, 0u);
+ TestStreamCreation(second_id, MEDIUM, first_id);
+ OnStreamDestruction(second_id);
+ TestStreamCreation(third_id, LOWEST, first_id);
+}
+
+// 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();
+ const SpdyStreamId fourth_id = GetId();
+ const SpdyStreamId fifth_id = GetId();
+ const SpdyStreamId sixth_id = GetId();
+ const SpdyStreamId seventh_id = GetId();
+ const SpdyStreamId eighth_id = GetId();
+ const SpdyStreamId nineth_id = GetId();
+ const SpdyStreamId tenth_id = GetId();
+
+ TestStreamCreation(first_id, HIGHEST, 0u);
+ TestStreamCreation(second_id, MEDIUM, first_id);
+ TestStreamCreation(third_id, MEDIUM, second_id);
+ OnStreamDestruction(first_id);
+ TestStreamCreation(fourth_id, MEDIUM, third_id);
+ TestStreamCreation(fifth_id, LOWEST, fourth_id);
+ TestStreamCreation(sixth_id, MEDIUM, fourth_id);
+ OnStreamDestruction(third_id);
+ TestStreamCreation(seventh_id, MEDIUM, sixth_id);
+ TestStreamCreation(eighth_id, LOW, seventh_id);
+ OnStreamDestruction(second_id);
+ OnStreamDestruction(fourth_id);
+ OnStreamDestruction(fifth_id);
+ OnStreamDestruction(sixth_id);
+ OnStreamDestruction(seventh_id);
+ TestStreamCreation(nineth_id, MEDIUM, 0u);
+ TestStreamCreation(tenth_id, HIGHEST, 0u);
+}
+
+} // namespace net
diff --git a/chromium/net/spdy/http2_write_scheduler.h b/chromium/net/spdy/http2_write_scheduler.h
new file mode 100644
index 00000000000..2bf5aee0cf5
--- /dev/null
+++ b/chromium/net/spdy/http2_write_scheduler.h
@@ -0,0 +1,739 @@
+// Copyright 2014 The Chromium 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_WRITE_SCHEDULER_H_
+#define NET_SPDY_HTTP2_WRITE_SCHEDULER_H_
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <cmath>
+#include <deque>
+#include <map>
+#include <queue>
+#include <set>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "base/containers/hash_tables.h"
+#include "base/containers/linked_list.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
+
+namespace net {
+
+// This data structure implements the HTTP/2 stream priority tree defined in
+// section 5.3 of RFC 7540:
+// http://tools.ietf.org/html/rfc7540#section-5.3
+//
+// Streams can be added and removed, and dependencies between them defined.
+// Streams constitute a tree rooted at stream ID 0: each stream has a single
+// parent stream, and 0 or more child streams. Individual streams can be
+// marked as ready to read/write, and then the whole structure can be queried
+// to pick the next stream to read/write out of those that are ready.
+//
+// The StreamIdType type must be a POD that supports comparison (most
+// likely, it will be a number).
+
+namespace test {
+template <typename StreamIdType>
+class Http2PriorityWriteSchedulerPeer;
+}
+
+const unsigned int kHttp2RootStreamId = 0;
+const int kHttp2DefaultStreamWeight = 16;
+const int kHttp2MinStreamWeight = 1;
+const int kHttp2MaxStreamWeight = 256;
+
+template <typename StreamIdType>
+class Http2PriorityWriteScheduler {
+ public:
+ Http2PriorityWriteScheduler();
+
+ friend class test::Http2PriorityWriteSchedulerPeer<StreamIdType>;
+
+ // Return the number of streams currently in the tree.
+ int num_streams() const;
+
+ // Return true if the tree contains a stream with the given ID.
+ bool StreamRegistered(StreamIdType stream_id) const;
+
+ // Registers a new stream with the given weight and parent, adding it to the
+ // dependency tree. Non-exclusive streams simply get added below the parent
+ // stream. If exclusive = true, the stream becomes the parent's sole child
+ // and the parent's previous children become the children of the new
+ // stream. If the stream was already registered, logs DFATAL and does
+ // nothing. If the parent stream is not registered, logs DFATAL and uses the
+ // root stream as the parent.
+ void RegisterStream(StreamIdType stream_id,
+ StreamIdType parent_id,
+ int weight,
+ bool exclusive);
+
+ // Unregisters the given stream from the scheduler, removing it from the
+ // dependency tree. If the stream was not previously registered, logs DFATAL
+ // and does nothing.
+ void UnregisterStream(StreamIdType stream_id);
+
+ // Returns the weight value for the specified stream. If the stream is not
+ // registered, logs DFATAL and returns the lowest weight.
+ int GetStreamWeight(StreamIdType stream_id) const;
+
+ // Returns the stream ID for the parent of the given stream. If the stream
+ // isn't registered, logs DFATAL and returns the root stream ID (0).
+ StreamIdType GetStreamParent(StreamIdType stream_id) const;
+
+ // Returns stream IDs of the children of the given stream, if any. If the
+ // stream isn't registered, logs DFATAL and returns an empty vector.
+ std::vector<StreamIdType> GetStreamChildren(StreamIdType stream_id) const;
+
+ // Sets the weight of the given stream. If the stream isn't registered or is
+ // the root stream, logs DFATAL and does nothing.
+ void SetStreamWeight(StreamIdType stream_id, int weight);
+
+ // Sets the parent of the given stream. If the stream and/or parent aren't
+ // registered, logs DFATAL and does nothing. If the new parent is a
+ // descendant of the stream (i.e. this would have created a cycle) then the
+ // topology of the tree is rearranged as described in section 5.3.3 of RFC
+ // 7540: https://tools.ietf.org/html/rfc7540#section-5.3.3
+ void SetStreamParent(StreamIdType stream_id,
+ StreamIdType parent_id,
+ bool exclusive);
+
+ // Returns true if the stream parent_id has child_id in its children. If
+ // either parent or child stream aren't registered, logs DFATAL and returns
+ // false.
+ bool StreamHasChild(StreamIdType parent_id, StreamIdType child_id) const;
+
+ // Marks the stream as blocked or unblocked. If the stream is not registered,
+ // logs DFATAL and does nothing.
+ void MarkStreamBlocked(StreamIdType stream_id, bool blocked);
+
+ // Marks the stream as ready or not ready to write; i.e. whether there is
+ // buffered data for the associated stream. If the stream is not registered,
+ // logs DFATAL and does nothing.
+ void MarkStreamReady(StreamIdType stream_id, bool ready);
+
+ // Returns true iff the scheduler has one or more usable streams. A stream is
+ // usable if it has ready == true and blocked == false, and is not the direct
+ // or indirect child of another stream that itself has ready == true and
+ // blocked == false. (Note that the root stream always has ready == false.)
+ bool HasUsableStreams() const;
+
+ // If the scheduler has any usable streams, returns the ID of the next usable
+ // stream, in the process changing its ready state to false. If the scheduler
+ // does not have any usable streams, logs DFATAL and returns the root stream
+ // ID (0). If there are multiple usable streams, precedence is given to the
+ // one with the highest priority (thus preserving SPDY priority semantics),
+ // or, if there are multiple with the highest priority, the one with the
+ // lowest ordinal (ensuring round-robin ordering).
+ StreamIdType PopNextUsableStream();
+
+ private:
+ struct StreamInfo;
+ using StreamInfoVector = std::vector<StreamInfo*>;
+ using StreamInfoMap = std::unordered_map<StreamIdType, StreamInfo*>;
+
+ struct StreamInfo : public base::LinkNode<StreamInfo> {
+ // ID for this stream.
+ StreamIdType id;
+ // ID of parent stream.
+ StreamInfo* parent = nullptr;
+ // Weights can range between 1 and 256 (inclusive).
+ int weight = kHttp2DefaultStreamWeight;
+ // The total weight of this stream's direct descendants.
+ int total_child_weights = 0;
+ // Pointers to StreamInfos for children, if any.
+ StreamInfoVector children;
+ // Is the associated stream write-blocked?
+ bool blocked = false;
+ // Does the stream have data ready for writing?
+ bool ready = false;
+ // Whether the stream is currently present in scheduling_queue_.
+ bool scheduled = false;
+ // The scheduling priority of this stream. Streams with higher priority
+ // values are scheduled first.
+ float priority = 0;
+ // Ordinal value for this stream, used to ensure round-robin scheduling:
+ // among streams with the same scheduling priority, streams with lower
+ // ordinal are scheduled first. The ordinal is reset to a new, greater
+ // value when the stream is next inserted into scheduling_queue_.
+ int64_t ordinal = 0;
+
+ // Whether the stream ought to be in scheduling_queue_.
+ bool IsSchedulable() const { return ready && !blocked; }
+
+ // Whether this stream should be scheduled ahead of another stream.
+ bool SchedulesBefore(const StreamInfo& other) const {
+ return (priority != other.priority) ? priority > other.priority
+ : ordinal < other.ordinal;
+ }
+ };
+
+ static bool Remove(StreamInfoVector* stream_infos,
+ const StreamInfo* stream_info);
+
+ // Clamps weight to a value in [kHttp2MinStreamWeight,
+ // kHttp2MaxStreamWeight].
+ static int ClampWeight(int weight);
+
+ // Returns true iff any direct or transitive parent of the given stream is
+ // currently scheduled.
+ static bool HasScheduledAncestor(const StreamInfo& stream_info);
+
+ // Returns StreamInfo for the given stream, or nullptr if it isn't
+ // registered.
+ const StreamInfo* FindStream(StreamIdType stream_id) const;
+ StreamInfo* FindStream(StreamIdType stream_id);
+
+ // Update all priority values in the subtree rooted at the given stream, not
+ // including the stream itself. If this results in priority value changes for
+ // scheduled streams, those streams are rescheduled to ensure proper ordering
+ // of scheduling_queue_.
+ void UpdatePrioritiesUnder(StreamInfo* stream_info);
+
+ // Adds or removes stream from scheduling_queue_ according to whether it is
+ // schedulable. If stream is newly schedulable, assigns it the next
+ // (increasing) ordinal value.
+ void UpdateScheduling(StreamInfo* stream_info);
+
+ // Inserts stream into scheduling_queue_ at the appropriate location given
+ // its priority and ordinal. Time complexity is O(scheduling_queue.size()).
+ void Schedule(StreamInfo* stream_info);
+
+ // Removes stream from scheduling_queue_.
+ void Unschedule(StreamInfo* stream_info);
+
+ // Return true if all internal invariants hold (useful for unit tests).
+ // Unless there are bugs, this should always return true.
+ bool ValidateInvariantsForTests() const;
+
+ // Pointee owned by all_stream_infos_.
+ StreamInfo* root_stream_info_;
+ // Maps from stream IDs to StreamInfo objects.
+ StreamInfoMap all_stream_infos_;
+ STLValueDeleter<StreamInfoMap> all_stream_infos_deleter_;
+ // Queue containing all streams that are ready and unblocked, ordered with
+ // streams of higher priority before streams of lower priority, and, among
+ // streams of equal priority, streams with lower ordinal before those with
+ // higher ordinal. Note that not all streams in scheduling_queue_ are
+ // necessarily usable: some may have ancestor stream(s) that are ready and
+ // unblocked. In these situations the occluded child streams are left in the
+ // queue, to reduce churn.
+ base::LinkedList<StreamInfo> scheduling_queue_;
+ // Ordinal value to assign to next node inserted into
+ // scheduling_queue_. Incremented after each insertion.
+ int64_t next_ordinal_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(Http2PriorityWriteScheduler);
+};
+
+template <typename StreamIdType>
+Http2PriorityWriteScheduler<StreamIdType>::Http2PriorityWriteScheduler()
+ : all_stream_infos_deleter_(&all_stream_infos_) {
+ root_stream_info_ = new StreamInfo();
+ root_stream_info_->id = kHttp2RootStreamId;
+ root_stream_info_->weight = kHttp2DefaultStreamWeight;
+ root_stream_info_->parent = nullptr;
+ root_stream_info_->priority = 1.0;
+ root_stream_info_->ready = true;
+ all_stream_infos_[kHttp2RootStreamId] = root_stream_info_;
+}
+
+template <typename StreamIdType>
+int Http2PriorityWriteScheduler<StreamIdType>::num_streams() const {
+ return all_stream_infos_.size();
+}
+
+template <typename StreamIdType>
+bool Http2PriorityWriteScheduler<StreamIdType>::StreamRegistered(
+ StreamIdType stream_id) const {
+ return ContainsKey(all_stream_infos_, stream_id);
+}
+
+template <typename StreamIdType>
+void Http2PriorityWriteScheduler<StreamIdType>::RegisterStream(
+ StreamIdType stream_id,
+ StreamIdType parent_id,
+ int weight,
+ bool exclusive) {
+ if (StreamRegistered(stream_id)) {
+ LOG(DFATAL) << "Stream " << stream_id << " already registered";
+ return;
+ }
+ weight = ClampWeight(weight);
+
+ StreamInfo* parent = FindStream(parent_id);
+ if (parent == nullptr) {
+ LOG(DFATAL) << "Parent stream " << parent_id << " not registered";
+ parent = root_stream_info_;
+ }
+
+ StreamInfo* new_stream_info = new StreamInfo;
+ new_stream_info->id = stream_id;
+ new_stream_info->weight = weight;
+ new_stream_info->parent = parent;
+ all_stream_infos_[stream_id] = new_stream_info;
+ if (exclusive) {
+ // Move the parent's current children below the new stream.
+ using std::swap;
+ swap(new_stream_info->children, parent->children);
+ new_stream_info->total_child_weights = parent->total_child_weights;
+ // Update each child's parent.
+ for (StreamInfo* child : new_stream_info->children) {
+ child->parent = new_stream_info;
+ }
+ // Clear parent's old child data.
+ DCHECK(parent->children.empty());
+ parent->total_child_weights = 0;
+ }
+ // Add new stream to parent.
+ parent->children.push_back(new_stream_info);
+ parent->total_child_weights += weight;
+
+ // Update all priorities under parent, since addition of a stream affects
+ // sibling priorities as well.
+ UpdatePrioritiesUnder(parent);
+
+ // Stream starts with ready == false, so no need to schedule it yet.
+ DCHECK(!new_stream_info->IsSchedulable());
+}
+
+template <typename StreamIdType>
+void Http2PriorityWriteScheduler<StreamIdType>::UnregisterStream(
+ StreamIdType stream_id) {
+ if (stream_id == kHttp2RootStreamId) {
+ LOG(DFATAL) << "Cannot unregister root stream";
+ return;
+ }
+ // Remove the stream from table.
+ typename StreamInfoMap::iterator it = all_stream_infos_.find(stream_id);
+ if (it == all_stream_infos_.end()) {
+ LOG(DFATAL) << "Stream " << stream_id << " not registered";
+ return;
+ }
+ scoped_ptr<StreamInfo> stream_info(std::move(it->second));
+ all_stream_infos_.erase(it);
+ // If scheduled, unschedule.
+ if (stream_info->scheduled) {
+ Unschedule(stream_info.get());
+ }
+
+ StreamInfo* parent = stream_info->parent;
+ // Remove the stream from parent's child list.
+ Remove(&parent->children, stream_info.get());
+ parent->total_child_weights -= stream_info->weight;
+
+ // Move the stream's children to the parent's child list.
+ // Update each child's parent and weight.
+ for (StreamInfo* child : stream_info->children) {
+ child->parent = parent;
+ parent->children.push_back(child);
+ // Divide the removed stream's weight among its children, rounding to the
+ // nearest valid weight.
+ float float_weight = stream_info->weight *
+ static_cast<float>(child->weight) /
+ static_cast<float>(stream_info->total_child_weights);
+ int new_weight = floor(float_weight + 0.5);
+ if (new_weight == 0) {
+ new_weight = 1;
+ }
+ child->weight = new_weight;
+ parent->total_child_weights += child->weight;
+ }
+ UpdatePrioritiesUnder(parent);
+}
+
+template <typename StreamIdType>
+int Http2PriorityWriteScheduler<StreamIdType>::GetStreamWeight(
+ StreamIdType stream_id) const {
+ const StreamInfo* stream_info = FindStream(stream_id);
+ if (stream_info == nullptr) {
+ LOG(DFATAL) << "Stream " << stream_id << " not registered";
+ return kHttp2MinStreamWeight;
+ }
+ return stream_info->weight;
+}
+
+template <typename StreamIdType>
+StreamIdType Http2PriorityWriteScheduler<StreamIdType>::GetStreamParent(
+ StreamIdType stream_id) const {
+ const StreamInfo* stream_info = FindStream(stream_id);
+ if (stream_info == nullptr) {
+ LOG(DFATAL) << "Stream " << stream_id << " not registered";
+ return kHttp2RootStreamId;
+ }
+ if (stream_info->parent == nullptr) { // root stream
+ return kHttp2RootStreamId;
+ }
+ return stream_info->parent->id;
+}
+
+template <typename StreamIdType>
+std::vector<StreamIdType> Http2PriorityWriteScheduler<
+ StreamIdType>::GetStreamChildren(StreamIdType stream_id) const {
+ std::vector<StreamIdType> child_vec;
+ const StreamInfo* stream_info = FindStream(stream_id);
+ if (stream_info == nullptr) {
+ LOG(DFATAL) << "Stream " << stream_id << " not registered";
+ } else {
+ child_vec.reserve(stream_info->children.size());
+ for (StreamInfo* child : stream_info->children) {
+ child_vec.push_back(child->id);
+ }
+ }
+ return child_vec;
+}
+
+template <typename StreamIdType>
+void Http2PriorityWriteScheduler<StreamIdType>::SetStreamWeight(
+ StreamIdType stream_id,
+ int weight) {
+ if (stream_id == kHttp2RootStreamId) {
+ LOG(DFATAL) << "Cannot set weight of root stream";
+ return;
+ }
+ StreamInfo* stream_info = FindStream(stream_id);
+ if (stream_info == nullptr) {
+ LOG(DFATAL) << "Stream " << stream_id << " not registered";
+ return;
+ }
+ weight = ClampWeight(weight);
+ if (weight == stream_info->weight) {
+ return;
+ }
+ if (stream_info->parent != nullptr) {
+ stream_info->parent->total_child_weights += (weight - stream_info->weight);
+ }
+ stream_info->weight = weight;
+
+ // Change in weight also affects sibling priorities.
+ UpdatePrioritiesUnder(stream_info->parent);
+}
+
+template <typename StreamIdType>
+void Http2PriorityWriteScheduler<StreamIdType>::SetStreamParent(
+ StreamIdType stream_id,
+ StreamIdType parent_id,
+ bool exclusive) {
+ if (stream_id == kHttp2RootStreamId) {
+ LOG(DFATAL) << "Cannot set parent of root stream";
+ return;
+ }
+ if (stream_id == parent_id) {
+ LOG(DFATAL) << "Cannot set stream to be its own parent";
+ return;
+ }
+ StreamInfo* stream_info = FindStream(stream_id);
+ if (stream_info == nullptr) {
+ LOG(DFATAL) << "Stream " << stream_id << " not registered";
+ return;
+ }
+ StreamInfo* new_parent = FindStream(parent_id);
+ if (new_parent == nullptr) {
+ LOG(DFATAL) << "Parent stream " << parent_id << " not registered";
+ return;
+ }
+
+ // If the new parent is already the stream's parent, we're done.
+ if (stream_info->parent == new_parent) {
+ return;
+ }
+
+ // Next, check to see if the new parent is currently a descendant
+ // of the stream.
+ StreamInfo* last = new_parent->parent;
+ bool cycle_exists = false;
+ while (last != nullptr) {
+ if (last == stream_info) {
+ cycle_exists = true;
+ break;
+ }
+ last = last->parent;
+ }
+
+ if (cycle_exists) {
+ // The new parent moves to the level of the current stream.
+ SetStreamParent(parent_id, stream_info->parent->id, false);
+ }
+
+ // Remove stream from old parent's child list.
+ StreamInfo* old_parent = stream_info->parent;
+ Remove(&old_parent->children, stream_info);
+ old_parent->total_child_weights -= stream_info->weight;
+ UpdatePrioritiesUnder(old_parent);
+
+ if (exclusive) {
+ // Move the new parent's current children below the current stream.
+ for (StreamInfo* child : new_parent->children) {
+ child->parent = stream_info;
+ stream_info->children.push_back(child);
+ }
+ stream_info->total_child_weights += new_parent->total_child_weights;
+ // Clear new parent's old child data.
+ new_parent->children.clear();
+ new_parent->total_child_weights = 0;
+ }
+
+ // Make the change.
+ stream_info->parent = new_parent;
+ new_parent->children.push_back(stream_info);
+ new_parent->total_child_weights += stream_info->weight;
+ UpdatePrioritiesUnder(new_parent);
+}
+
+template <typename StreamIdType>
+void Http2PriorityWriteScheduler<StreamIdType>::MarkStreamBlocked(
+ StreamIdType stream_id,
+ bool blocked) {
+ if (stream_id == kHttp2RootStreamId) {
+ LOG(DFATAL) << "Cannot mark root stream blocked or unblocked";
+ return;
+ }
+ StreamInfo* stream_info = FindStream(stream_id);
+ if (stream_info == nullptr) {
+ LOG(DFATAL) << "Stream " << stream_id << " not registered";
+ return;
+ }
+ stream_info->blocked = blocked;
+ UpdateScheduling(stream_info);
+}
+
+template <typename StreamIdType>
+void Http2PriorityWriteScheduler<StreamIdType>::MarkStreamReady(
+ StreamIdType stream_id,
+ bool ready) {
+ if (stream_id == kHttp2RootStreamId) {
+ LOG(DFATAL) << "Cannot mark root stream ready or unready";
+ return;
+ }
+ StreamInfo* stream_info = FindStream(stream_id);
+ if (stream_info == nullptr) {
+ LOG(DFATAL) << "Stream " << stream_id << " not registered";
+ return;
+ }
+ stream_info->ready = ready;
+ UpdateScheduling(stream_info);
+}
+
+template <typename StreamIdType>
+bool Http2PriorityWriteScheduler<StreamIdType>::Remove(
+ StreamInfoVector* stream_infos,
+ const StreamInfo* stream_info) {
+ for (typename StreamInfoVector::iterator it = stream_infos->begin();
+ it != stream_infos->end(); ++it) {
+ if (*it == stream_info) {
+ stream_infos->erase(it);
+ return true;
+ }
+ }
+ return false;
+}
+
+template <typename StreamIdType>
+int Http2PriorityWriteScheduler<StreamIdType>::ClampWeight(int weight) {
+ if (weight < kHttp2MinStreamWeight) {
+ LOG(DFATAL) << "Invalid weight: " << weight;
+ return kHttp2MinStreamWeight;
+ }
+ if (weight > kHttp2MaxStreamWeight) {
+ LOG(DFATAL) << "Invalid weight: " << weight;
+ return kHttp2MaxStreamWeight;
+ }
+ return weight;
+}
+
+template <typename StreamIdType>
+bool Http2PriorityWriteScheduler<StreamIdType>::HasScheduledAncestor(
+ const StreamInfo& stream_info) {
+ for (const StreamInfo* parent = stream_info.parent; parent != nullptr;
+ parent = parent->parent) {
+ if (parent->scheduled) {
+ return true;
+ }
+ }
+ return false;
+}
+
+template <typename StreamIdType>
+const typename Http2PriorityWriteScheduler<StreamIdType>::StreamInfo*
+Http2PriorityWriteScheduler<StreamIdType>::FindStream(
+ StreamIdType stream_id) const {
+ typename StreamInfoMap::const_iterator it = all_stream_infos_.find(stream_id);
+ return it == all_stream_infos_.end() ? nullptr : it->second;
+}
+
+template <typename StreamIdType>
+typename Http2PriorityWriteScheduler<StreamIdType>::StreamInfo*
+Http2PriorityWriteScheduler<StreamIdType>::FindStream(StreamIdType stream_id) {
+ typename StreamInfoMap::iterator it = all_stream_infos_.find(stream_id);
+ return it == all_stream_infos_.end() ? nullptr : it->second;
+}
+
+template <typename StreamIdType>
+void Http2PriorityWriteScheduler<StreamIdType>::UpdatePrioritiesUnder(
+ StreamInfo* stream_info) {
+ for (StreamInfo* child : stream_info->children) {
+ child->priority = stream_info->priority *
+ (static_cast<float>(child->weight) /
+ static_cast<float>(stream_info->total_child_weights));
+ if (child->scheduled) {
+ // Reposition in scheduling_queue_. Use post-order for scheduling, to
+ // benefit from the fact that children have priority <= parent priority.
+ Unschedule(child);
+ UpdatePrioritiesUnder(child);
+ Schedule(child);
+ } else {
+ UpdatePrioritiesUnder(child);
+ }
+ }
+}
+
+template <typename StreamIdType>
+void Http2PriorityWriteScheduler<StreamIdType>::UpdateScheduling(
+ StreamInfo* stream_info) {
+ if (stream_info->IsSchedulable() != stream_info->scheduled) {
+ if (stream_info->scheduled) {
+ Unschedule(stream_info);
+ } else {
+ stream_info->ordinal = next_ordinal_++;
+ Schedule(stream_info);
+ }
+ }
+}
+
+template <typename StreamIdType>
+void Http2PriorityWriteScheduler<StreamIdType>::Schedule(
+ StreamInfo* stream_info) {
+ DCHECK(!stream_info->scheduled);
+ for (base::LinkNode<StreamInfo>* s = scheduling_queue_.head();
+ s != scheduling_queue_.end(); s = s->next()) {
+ if (stream_info->SchedulesBefore(*s->value())) {
+ stream_info->InsertBefore(s);
+ stream_info->scheduled = true;
+ break;
+ }
+ }
+ if (!stream_info->scheduled) {
+ stream_info->InsertAfter(scheduling_queue_.tail());
+ stream_info->scheduled = true;
+ }
+}
+
+template <typename StreamIdType>
+void Http2PriorityWriteScheduler<StreamIdType>::Unschedule(
+ StreamInfo* stream_info) {
+ DCHECK(stream_info->scheduled);
+ stream_info->RemoveFromList();
+ stream_info->scheduled = false;
+}
+
+template <typename StreamIdType>
+bool Http2PriorityWriteScheduler<StreamIdType>::StreamHasChild(
+ StreamIdType parent_id,
+ StreamIdType child_id) const {
+ const StreamInfo* parent = FindStream(parent_id);
+ if (parent == nullptr) {
+ LOG(DFATAL) << "Parent stream " << parent_id << " not registered";
+ return false;
+ }
+ if (!StreamRegistered(child_id)) {
+ LOG(DFATAL) << "Child stream " << child_id << " not registered";
+ return false;
+ }
+ auto found = std::find_if(parent->children.begin(), parent->children.end(),
+ [child_id](StreamInfo* stream_info) {
+ return stream_info->id == child_id;
+ });
+ return found != parent->children.end();
+}
+
+template <typename StreamIdType>
+bool Http2PriorityWriteScheduler<StreamIdType>::HasUsableStreams() const {
+ // Even though not every stream in scheduling queue is guaranteed to be
+ // usable (since children are occluded by parents), the presence of any
+ // streams guarantees at least one is usable.
+ return !scheduling_queue_.empty();
+}
+
+template <typename StreamIdType>
+StreamIdType Http2PriorityWriteScheduler<StreamIdType>::PopNextUsableStream() {
+ for (base::LinkNode<StreamInfo>* s = scheduling_queue_.head();
+ s != scheduling_queue_.end(); s = s->next()) {
+ StreamInfo* stream_info = s->value();
+ if (!HasScheduledAncestor(*stream_info)) {
+ stream_info->ready = false;
+ Unschedule(stream_info);
+ return stream_info->id;
+ }
+ }
+ LOG(DFATAL) << "No usable streams";
+ return kHttp2RootStreamId;
+}
+
+template <typename StreamIdType>
+bool Http2PriorityWriteScheduler<StreamIdType>::ValidateInvariantsForTests()
+ const {
+ int total_streams = 0;
+ int streams_visited = 0;
+ // Iterate through all streams in the map.
+ for (const auto& kv : all_stream_infos_) {
+ ++total_streams;
+ ++streams_visited;
+ const StreamInfo& stream_info = *kv.second;
+ // All streams except the root should have a parent, and should appear in
+ // the children of that parent.
+ if (stream_info.id != kHttp2RootStreamId &&
+ !StreamHasChild(stream_info.parent->id, stream_info.id)) {
+ DLOG(INFO) << "Parent stream " << stream_info.parent->id
+ << " is not registered, or does not list stream "
+ << stream_info.id << " as its child.";
+ return false;
+ }
+
+ if (!stream_info.children.empty()) {
+ int total_child_weights = 0;
+ // Iterate through the stream's children.
+ for (StreamInfo* child : stream_info.children) {
+ ++streams_visited;
+ // Each stream in the list should exist and should have this stream
+ // set as its parent.
+ if (!StreamRegistered(child->id) ||
+ stream_info.id != GetStreamParent(child->id)) {
+ DLOG(INFO) << "Child stream " << child->id << " is not registered, "
+ << "or does not list " << stream_info.id
+ << " as its parent.";
+ return false;
+ }
+ total_child_weights += child->weight;
+ }
+ // Verify that total_child_weights is correct.
+ if (total_child_weights != stream_info.total_child_weights) {
+ DLOG(INFO) << "Child weight totals do not agree. For stream "
+ << stream_info.id << " total_child_weights has value "
+ << stream_info.total_child_weights << ", expected "
+ << total_child_weights;
+ return false;
+ }
+ }
+ }
+
+ // Make sure num_streams reflects the total number of streams the map
+ // contains.
+ if (total_streams != num_streams()) {
+ DLOG(INFO) << "Map contains incorrect number of streams.";
+ return false;
+ }
+ // Validate the validation function; we should have visited each stream twice
+ // (except for the root)
+ DCHECK(streams_visited == 2 * num_streams() - 1);
+ return true;
+}
+
+} // namespace net
+
+#endif // NET_SPDY_HTTP2_WRITE_SCHEDULER_H_
diff --git a/chromium/net/spdy/http2_write_scheduler_test.cc b/chromium/net/spdy/http2_write_scheduler_test.cc
new file mode 100644
index 00000000000..f581d353263
--- /dev/null
+++ b/chromium/net/spdy/http2_write_scheduler_test.cc
@@ -0,0 +1,675 @@
+// Copyright 2014 The Chromium 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_write_scheduler.h"
+
+#include "net/test/gtest_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+using ::testing::UnorderedElementsAre;
+
+namespace test {
+
+template <typename StreamIdType>
+class Http2PriorityWriteSchedulerPeer {
+ public:
+ explicit Http2PriorityWriteSchedulerPeer(
+ Http2PriorityWriteScheduler<StreamIdType>* scheduler)
+ : scheduler_(scheduler) {}
+
+ int TotalChildWeights(StreamIdType stream_id) const {
+ return scheduler_->FindStream(stream_id)->total_child_weights;
+ }
+
+ bool ValidateInvariants() const {
+ return scheduler_->ValidateInvariantsForTests();
+ }
+
+ private:
+ Http2PriorityWriteScheduler<StreamIdType>* scheduler_;
+};
+
+class Http2PriorityWriteSchedulerTest : public ::testing::Test {
+ protected:
+ using SpdyStreamId = uint32_t;
+
+ Http2PriorityWriteSchedulerTest() : peer_(&scheduler_) {}
+
+ Http2PriorityWriteScheduler<SpdyStreamId> scheduler_;
+ Http2PriorityWriteSchedulerPeer<SpdyStreamId> peer_;
+};
+
+TEST_F(Http2PriorityWriteSchedulerTest, RegisterAndUnregisterStreams) {
+ EXPECT_EQ(1, scheduler_.num_streams());
+ EXPECT_TRUE(scheduler_.StreamRegistered(0));
+ EXPECT_FALSE(scheduler_.StreamRegistered(1));
+
+ scheduler_.RegisterStream(1, 0, 100, false);
+ EXPECT_EQ(2, scheduler_.num_streams());
+ ASSERT_TRUE(scheduler_.StreamRegistered(1));
+ EXPECT_EQ(100, scheduler_.GetStreamWeight(1));
+ EXPECT_FALSE(scheduler_.StreamRegistered(5));
+ EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(1));
+
+ scheduler_.RegisterStream(5, 0, 50, false);
+ // Should not be able to add a stream with an id that already exists.
+ EXPECT_DFATAL(scheduler_.RegisterStream(5, 1, 50, false),
+ "Stream 5 already registered");
+ EXPECT_EQ(3, scheduler_.num_streams());
+ EXPECT_TRUE(scheduler_.StreamRegistered(1));
+ ASSERT_TRUE(scheduler_.StreamRegistered(5));
+ EXPECT_EQ(50, scheduler_.GetStreamWeight(5));
+ EXPECT_FALSE(scheduler_.StreamRegistered(13));
+
+ scheduler_.RegisterStream(13, 5, 130, true);
+ EXPECT_EQ(4, scheduler_.num_streams());
+ EXPECT_TRUE(scheduler_.StreamRegistered(1));
+ EXPECT_TRUE(scheduler_.StreamRegistered(5));
+ ASSERT_TRUE(scheduler_.StreamRegistered(13));
+ EXPECT_EQ(130, scheduler_.GetStreamWeight(13));
+ EXPECT_EQ(5u, scheduler_.GetStreamParent(13));
+
+ scheduler_.UnregisterStream(5);
+ // Cannot remove a stream that has already been removed.
+ EXPECT_DFATAL(scheduler_.UnregisterStream(5), "Stream 5 not registered");
+ EXPECT_EQ(3, scheduler_.num_streams());
+ EXPECT_TRUE(scheduler_.StreamRegistered(1));
+ EXPECT_FALSE(scheduler_.StreamRegistered(5));
+ EXPECT_TRUE(scheduler_.StreamRegistered(13));
+ EXPECT_EQ(kHttp2RootStreamId, scheduler_.GetStreamParent(13));
+
+ // The parent stream 19 doesn't exist, so this should use 0 as parent stream:
+ EXPECT_DFATAL(scheduler_.RegisterStream(7, 19, 70, false),
+ "Parent stream 19 not registered");
+ EXPECT_TRUE(scheduler_.StreamRegistered(7));
+ EXPECT_EQ(0u, scheduler_.GetStreamParent(7));
+ // Now stream 7 already exists, so this should fail:
+ EXPECT_DFATAL(scheduler_.RegisterStream(7, 1, 70, false),
+ "Stream 7 already registered");
+ // Try adding a second child to stream 13:
+ scheduler_.RegisterStream(17, 13, 170, false);
+
+ // TODO(birenroy): Add a separate test that verifies weight invariants when
+ // SetStreamWeight is called.
+ scheduler_.SetStreamWeight(17, 150);
+ EXPECT_EQ(150, scheduler_.GetStreamWeight(17));
+
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, GetStreamWeight) {
+ EXPECT_DFATAL(EXPECT_EQ(kHttp2MinStreamWeight, scheduler_.GetStreamWeight(3)),
+ "Stream 3 not registered");
+ scheduler_.RegisterStream(3, 0, 130, true);
+ EXPECT_EQ(130, scheduler_.GetStreamWeight(3));
+ scheduler_.SetStreamWeight(3, 50);
+ EXPECT_EQ(50, scheduler_.GetStreamWeight(3));
+ scheduler_.UnregisterStream(3);
+ EXPECT_DFATAL(EXPECT_EQ(kHttp2MinStreamWeight, scheduler_.GetStreamWeight(3)),
+ "Stream 3 not registered");
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, GetStreamParent) {
+ EXPECT_DFATAL(EXPECT_EQ(kHttp2RootStreamId, scheduler_.GetStreamParent(3)),
+ "Stream 3 not registered");
+ scheduler_.RegisterStream(2, 0, 20, false);
+ scheduler_.RegisterStream(3, 2, 30, false);
+ EXPECT_EQ(2u, scheduler_.GetStreamParent(3));
+ scheduler_.UnregisterStream(3);
+ EXPECT_DFATAL(EXPECT_EQ(kHttp2RootStreamId, scheduler_.GetStreamParent(3)),
+ "Stream 3 not registered");
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, GetStreamChildren) {
+ EXPECT_DFATAL(EXPECT_THAT(scheduler_.GetStreamChildren(7), IsEmpty()),
+ "Stream 7 not registered");
+ scheduler_.RegisterStream(7, 0, 70, false);
+ EXPECT_THAT(scheduler_.GetStreamChildren(7), IsEmpty());
+ scheduler_.RegisterStream(9, 7, 90, false);
+ scheduler_.RegisterStream(15, 7, 150, false);
+ EXPECT_THAT(scheduler_.GetStreamChildren(7), UnorderedElementsAre(9, 15));
+ scheduler_.UnregisterStream(7);
+ EXPECT_DFATAL(EXPECT_THAT(scheduler_.GetStreamChildren(7), IsEmpty()),
+ "Stream 7 not registered");
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, SetStreamWeight) {
+ EXPECT_DFATAL(scheduler_.SetStreamWeight(0, 10),
+ "Cannot set weight of root stream");
+ EXPECT_DFATAL(scheduler_.SetStreamWeight(3, 10), "Stream 3 not registered");
+ scheduler_.RegisterStream(3, 0, 10, false);
+ scheduler_.SetStreamWeight(3, 20);
+ EXPECT_EQ(20, scheduler_.GetStreamWeight(3));
+ EXPECT_DFATAL(scheduler_.SetStreamWeight(3, 500), "Invalid weight: 500");
+ EXPECT_EQ(kHttp2MaxStreamWeight, scheduler_.GetStreamWeight(3));
+ EXPECT_DFATAL(scheduler_.SetStreamWeight(3, 0), "Invalid weight: 0");
+ EXPECT_EQ(kHttp2MinStreamWeight, scheduler_.GetStreamWeight(3));
+ scheduler_.UnregisterStream(3);
+ EXPECT_DFATAL(scheduler_.SetStreamWeight(3, 10), "Stream 3 not registered");
+}
+
+// Basic case of reparenting a subtree.
+TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentBasicNonExclusive) {
+ /* Tree:
+ 0
+ / \
+ 1 2
+ / \
+ 3 4
+ */
+ scheduler_.RegisterStream(1, 0, 100, false);
+ scheduler_.RegisterStream(2, 0, 100, false);
+ scheduler_.RegisterStream(3, 1, 100, false);
+ scheduler_.RegisterStream(4, 1, 100, false);
+ scheduler_.SetStreamParent(1, 2, false);
+ EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(2));
+ EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(3, 4));
+ EXPECT_THAT(scheduler_.GetStreamChildren(2), ElementsAre(1));
+ EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(4), IsEmpty());
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+// Basic case of reparenting a subtree. Result here is the same as the
+// non-exclusive case.
+TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentBasicExclusive) {
+ /* Tree:
+ 0
+ / \
+ 1 2
+ / \
+ 3 4
+ */
+ scheduler_.RegisterStream(1, 0, 100, false);
+ scheduler_.RegisterStream(2, 0, 100, false);
+ scheduler_.RegisterStream(3, 1, 100, false);
+ scheduler_.RegisterStream(4, 1, 100, false);
+ scheduler_.SetStreamParent(1, 2, true);
+ EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(2));
+ EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(3, 4));
+ EXPECT_THAT(scheduler_.GetStreamChildren(2), ElementsAre(1));
+ EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(4), IsEmpty());
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+// We can't set the parent of a nonexistent stream, or set the parent to a
+// nonexistent stream.
+TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentNonexistent) {
+ scheduler_.RegisterStream(1, 0, 100, false);
+ scheduler_.RegisterStream(2, 0, 100, false);
+ for (bool exclusive : {true, false}) {
+ EXPECT_DFATAL(scheduler_.SetStreamParent(1, 3, exclusive),
+ "Parent stream 3 not registered");
+ EXPECT_DFATAL(scheduler_.SetStreamParent(4, 2, exclusive),
+ "Stream 4 not registered");
+ EXPECT_DFATAL(scheduler_.SetStreamParent(3, 4, exclusive),
+ "Stream 3 not registered");
+ EXPECT_THAT(scheduler_.GetStreamChildren(0), UnorderedElementsAre(1, 2));
+ EXPECT_THAT(scheduler_.GetStreamChildren(1), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(2), IsEmpty());
+ }
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+// We should be able to add multiple children to streams.
+TEST_F(Http2PriorityWriteSchedulerTest,
+ SetStreamParentMultipleChildrenNonExclusive) {
+ /* Tree:
+ 0
+ / \
+ 1 2
+ / \ \
+ 3 4 5
+ */
+ scheduler_.RegisterStream(1, 0, 100, false);
+ scheduler_.RegisterStream(2, 0, 100, false);
+ scheduler_.RegisterStream(3, 1, 100, false);
+ scheduler_.RegisterStream(4, 1, 100, false);
+ scheduler_.RegisterStream(5, 2, 100, false);
+ scheduler_.SetStreamParent(2, 1, false);
+ EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(1));
+ EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(2, 3, 4));
+ EXPECT_THAT(scheduler_.GetStreamChildren(2), ElementsAre(5));
+ EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(4), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(5), IsEmpty());
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest,
+ SetStreamParentMultipleChildrenExclusive) {
+ /* Tree:
+ 0
+ / \
+ 1 2
+ / \ \
+ 3 4 5
+ */
+ scheduler_.RegisterStream(1, 0, 100, false);
+ scheduler_.RegisterStream(2, 0, 100, false);
+ scheduler_.RegisterStream(3, 1, 100, false);
+ scheduler_.RegisterStream(4, 1, 100, false);
+ scheduler_.RegisterStream(5, 2, 100, false);
+ scheduler_.SetStreamParent(2, 1, true);
+ EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(1));
+ EXPECT_THAT(scheduler_.GetStreamChildren(1), ElementsAre(2));
+ EXPECT_THAT(scheduler_.GetStreamChildren(2), UnorderedElementsAre(3, 4, 5));
+ EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(4), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(5), IsEmpty());
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentToChildNonExclusive) {
+ /* Tree:
+ 0
+ |
+ 1
+ / \
+ 2 3
+ |
+ 4
+ */
+ scheduler_.RegisterStream(1, 0, 100, false);
+ scheduler_.RegisterStream(2, 1, 100, false);
+ scheduler_.RegisterStream(3, 1, 100, false);
+ scheduler_.RegisterStream(4, 2, 100, false);
+ scheduler_.SetStreamParent(1, 2, false);
+ EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(2));
+ EXPECT_THAT(scheduler_.GetStreamChildren(1), ElementsAre(3));
+ EXPECT_THAT(scheduler_.GetStreamChildren(2), UnorderedElementsAre(1, 4));
+ EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(4), IsEmpty());
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentToChildExclusive) {
+ /* Tree:
+ 0
+ |
+ 1
+ / \
+ 2 3
+ |
+ 4
+ */
+ scheduler_.RegisterStream(1, 0, 100, false);
+ scheduler_.RegisterStream(2, 1, 100, false);
+ scheduler_.RegisterStream(3, 1, 100, false);
+ scheduler_.RegisterStream(4, 2, 100, false);
+ scheduler_.SetStreamParent(1, 2, true);
+ EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(2));
+ EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(3, 4));
+ EXPECT_THAT(scheduler_.GetStreamChildren(2), ElementsAre(1));
+ EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(4), IsEmpty());
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest,
+ SetStreamParentToGrandchildNonExclusive) {
+ /* Tree:
+ 0
+ |
+ 1
+ / \
+ 2 3
+ / \
+ 4 5
+ |
+ 6
+ */
+ scheduler_.RegisterStream(1, 0, 100, false);
+ scheduler_.RegisterStream(2, 1, 100, false);
+ scheduler_.RegisterStream(3, 1, 100, false);
+ scheduler_.RegisterStream(4, 2, 100, false);
+ scheduler_.RegisterStream(5, 2, 100, false);
+ scheduler_.RegisterStream(6, 4, 100, false);
+ scheduler_.SetStreamParent(1, 4, false);
+ EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(4));
+ EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(2, 3));
+ EXPECT_THAT(scheduler_.GetStreamChildren(2), ElementsAre(5));
+ EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(4), UnorderedElementsAre(1, 6));
+ EXPECT_THAT(scheduler_.GetStreamChildren(5), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(6), IsEmpty());
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentToGrandchildExclusive) {
+ /* Tree:
+ 0
+ |
+ 1
+ / \
+ 2 3
+ / \
+ 4 5
+ |
+ 6
+ */
+ scheduler_.RegisterStream(1, 0, 100, false);
+ scheduler_.RegisterStream(2, 1, 100, false);
+ scheduler_.RegisterStream(3, 1, 100, false);
+ scheduler_.RegisterStream(4, 2, 100, false);
+ scheduler_.RegisterStream(5, 2, 100, false);
+ scheduler_.RegisterStream(6, 4, 100, false);
+ scheduler_.SetStreamParent(1, 4, true);
+ EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(4));
+ EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(2, 3, 6));
+ EXPECT_THAT(scheduler_.GetStreamChildren(2), ElementsAre(5));
+ EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(4), ElementsAre(1));
+ EXPECT_THAT(scheduler_.GetStreamChildren(5), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(6), IsEmpty());
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentToParent) {
+ scheduler_.RegisterStream(1, 0, 100, false);
+ scheduler_.RegisterStream(2, 1, 100, false);
+ scheduler_.RegisterStream(3, 1, 100, false);
+ for (bool exclusive : {true, false}) {
+ scheduler_.SetStreamParent(2, 1, exclusive);
+ EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(1));
+ EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(2, 3));
+ EXPECT_THAT(scheduler_.GetStreamChildren(2), IsEmpty());
+ EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
+ }
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentToSelf) {
+ scheduler_.RegisterStream(1, 0, 100, false);
+ EXPECT_DFATAL(scheduler_.SetStreamParent(1, 1, false),
+ "Cannot set stream to be its own parent");
+ EXPECT_DFATAL(scheduler_.SetStreamParent(1, 1, true),
+ "Cannot set stream to be its own parent");
+ EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(1));
+ EXPECT_THAT(scheduler_.GetStreamChildren(1), IsEmpty());
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, StreamHasChild) {
+ scheduler_.RegisterStream(1, 0, 10, false);
+ scheduler_.RegisterStream(2, 1, 20, false);
+ scheduler_.RegisterStream(3, 1, 30, false);
+ EXPECT_DFATAL(EXPECT_FALSE(scheduler_.StreamHasChild(4, 1)),
+ "Parent stream 4 not registered");
+ EXPECT_DFATAL(EXPECT_FALSE(scheduler_.StreamHasChild(3, 7)),
+ "Child stream 7 not registered");
+ EXPECT_FALSE(scheduler_.StreamHasChild(3, 1));
+ EXPECT_TRUE(scheduler_.StreamHasChild(1, 3));
+ EXPECT_TRUE(scheduler_.StreamHasChild(1, 2));
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, BlockAndUnblock) {
+ /* Create the tree.
+
+ 0
+ / | \
+ / | \
+ 1 2 3
+ / \ \ \
+ 4 5 6 7
+ /| / \ | |\
+ 8 9 10 11 12 13 14
+ / \
+ 15 16
+
+ */
+ scheduler_.RegisterStream(1, 0, 100, false);
+ scheduler_.RegisterStream(2, 0, 100, false);
+ scheduler_.RegisterStream(3, 0, 100, false);
+ scheduler_.RegisterStream(4, 1, 100, false);
+ scheduler_.RegisterStream(5, 1, 100, false);
+ scheduler_.RegisterStream(8, 4, 100, false);
+ scheduler_.RegisterStream(9, 4, 100, false);
+ scheduler_.RegisterStream(10, 5, 100, false);
+ scheduler_.RegisterStream(11, 5, 100, false);
+ scheduler_.RegisterStream(15, 8, 100, false);
+ scheduler_.RegisterStream(16, 8, 100, false);
+ scheduler_.RegisterStream(12, 2, 100, false);
+ scheduler_.RegisterStream(6, 2, 100, true);
+ scheduler_.RegisterStream(7, 0, 100, false);
+ scheduler_.RegisterStream(13, 7, 100, true);
+ scheduler_.RegisterStream(14, 7, 100, false);
+ scheduler_.SetStreamParent(7, 3, false);
+ EXPECT_EQ(0u, scheduler_.GetStreamParent(1));
+ EXPECT_EQ(0u, scheduler_.GetStreamParent(2));
+ EXPECT_EQ(0u, scheduler_.GetStreamParent(3));
+ EXPECT_EQ(1u, scheduler_.GetStreamParent(4));
+ EXPECT_EQ(1u, scheduler_.GetStreamParent(5));
+ EXPECT_EQ(2u, scheduler_.GetStreamParent(6));
+ EXPECT_EQ(3u, scheduler_.GetStreamParent(7));
+ EXPECT_EQ(4u, scheduler_.GetStreamParent(8));
+ EXPECT_EQ(4u, scheduler_.GetStreamParent(9));
+ EXPECT_EQ(5u, scheduler_.GetStreamParent(10));
+ EXPECT_EQ(5u, scheduler_.GetStreamParent(11));
+ EXPECT_EQ(6u, scheduler_.GetStreamParent(12));
+ EXPECT_EQ(7u, scheduler_.GetStreamParent(13));
+ EXPECT_EQ(7u, scheduler_.GetStreamParent(14));
+ EXPECT_EQ(8u, scheduler_.GetStreamParent(15));
+ EXPECT_EQ(8u, scheduler_.GetStreamParent(16));
+ ASSERT_TRUE(peer_.ValidateInvariants());
+
+ EXPECT_EQ(peer_.TotalChildWeights(0), scheduler_.GetStreamWeight(1) +
+ scheduler_.GetStreamWeight(2) +
+ scheduler_.GetStreamWeight(3));
+ EXPECT_EQ(peer_.TotalChildWeights(3), scheduler_.GetStreamWeight(7));
+ EXPECT_EQ(peer_.TotalChildWeights(7),
+ scheduler_.GetStreamWeight(13) + scheduler_.GetStreamWeight(14));
+ EXPECT_EQ(peer_.TotalChildWeights(13), 0);
+ EXPECT_EQ(peer_.TotalChildWeights(14), 0);
+
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, HasUsableStreams) {
+ EXPECT_FALSE(scheduler_.HasUsableStreams());
+ scheduler_.RegisterStream(1, 0, 10, false);
+ EXPECT_FALSE(scheduler_.HasUsableStreams());
+ scheduler_.MarkStreamReady(1, true);
+ EXPECT_TRUE(scheduler_.HasUsableStreams());
+ scheduler_.MarkStreamBlocked(1, true);
+ EXPECT_FALSE(scheduler_.HasUsableStreams());
+ scheduler_.MarkStreamReady(1, false);
+ EXPECT_FALSE(scheduler_.HasUsableStreams());
+ scheduler_.MarkStreamBlocked(1, false);
+ EXPECT_FALSE(scheduler_.HasUsableStreams());
+ scheduler_.MarkStreamReady(1, true);
+ EXPECT_TRUE(scheduler_.HasUsableStreams());
+ scheduler_.UnregisterStream(1);
+ EXPECT_FALSE(scheduler_.HasUsableStreams());
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+TEST_F(Http2PriorityWriteSchedulerTest, CalculateRoundedWeights) {
+ /* Create the tree.
+
+ 0
+ / \
+ 1 2
+ /| |\ |\
+ 8 3 4 5 6 7
+ */
+ scheduler_.RegisterStream(3, 0, 100, false);
+ scheduler_.RegisterStream(4, 0, 100, false);
+ scheduler_.RegisterStream(5, 0, 100, false);
+ scheduler_.RegisterStream(1, 0, 10, true);
+ scheduler_.RegisterStream(2, 0, 5, false);
+ scheduler_.RegisterStream(6, 2, 1, false);
+ scheduler_.RegisterStream(7, 2, 1, false);
+ scheduler_.RegisterStream(8, 1, 1, false);
+
+ // Remove higher-level streams.
+ scheduler_.UnregisterStream(1);
+ scheduler_.UnregisterStream(2);
+
+ // 3.3 rounded down = 3.
+ EXPECT_EQ(3, scheduler_.GetStreamWeight(3));
+ EXPECT_EQ(3, scheduler_.GetStreamWeight(4));
+ EXPECT_EQ(3, scheduler_.GetStreamWeight(5));
+ // 2.5 rounded up = 3.
+ EXPECT_EQ(3, scheduler_.GetStreamWeight(6));
+ EXPECT_EQ(3, scheduler_.GetStreamWeight(7));
+ // 0 is not a valid weight, so round up to 1.
+ EXPECT_EQ(1, scheduler_.GetStreamWeight(8));
+ ASSERT_TRUE(peer_.ValidateInvariants());
+}
+
+class PopNextUsableStreamTest : public Http2PriorityWriteSchedulerTest {
+ protected:
+ void SetUp() override {
+ /* Create the tree.
+
+ 0
+ /|\
+ 1 2 3
+ /| |\
+ 4 5 6 7
+ /
+ 8
+
+ */
+ scheduler_.RegisterStream(1, 0, 100, false);
+ scheduler_.RegisterStream(2, 0, 100, false);
+ scheduler_.RegisterStream(3, 0, 100, false);
+ scheduler_.RegisterStream(4, 1, 100, false);
+ scheduler_.RegisterStream(5, 1, 100, false);
+ scheduler_.RegisterStream(6, 2, 100, false);
+ scheduler_.RegisterStream(7, 2, 100, false);
+ scheduler_.RegisterStream(8, 4, 100, false);
+
+ // Set all nodes ready to write.
+ for (SpdyStreamId id = 1; id <= 8; ++id) {
+ scheduler_.MarkStreamReady(id, true);
+ }
+ }
+
+ AssertionResult PopNextReturnsCycle(
+ std::initializer_list<SpdyStreamId> stream_ids) {
+ int count = 0;
+ const int kNumCyclesToCheck = 2;
+ for (int i = 0; i < kNumCyclesToCheck; i++) {
+ for (SpdyStreamId expected_id : stream_ids) {
+ SpdyStreamId next_id = scheduler_.PopNextUsableStream();
+ scheduler_.MarkStreamReady(next_id, true);
+ if (next_id != expected_id) {
+ return AssertionFailure() << "Pick " << count << ": expected stream "
+ << expected_id << " instead of " << next_id;
+ }
+ if (!peer_.ValidateInvariants()) {
+ return AssertionFailure() << "ValidateInvariants failed";
+ }
+ ++count;
+ }
+ }
+ return AssertionSuccess();
+ }
+};
+
+// When all streams are schedulable, only top-level streams should be returned.
+TEST_F(PopNextUsableStreamTest, NoneBlocked) {
+ EXPECT_TRUE(PopNextReturnsCycle({1, 2, 3}));
+}
+
+// When a parent stream is blocked, its children should be scheduled, if
+// priorities allow.
+TEST_F(PopNextUsableStreamTest, SingleStreamBlocked) {
+ scheduler_.MarkStreamReady(1, false);
+
+ // Round-robin only across 2 and 3, since children of 1 have lower priority.
+ EXPECT_TRUE(PopNextReturnsCycle({2, 3}));
+
+ // Make children of 1 have equal priority as 2 and 3, after which they should
+ // be returned as well.
+ scheduler_.SetStreamWeight(1, 200);
+ EXPECT_TRUE(PopNextReturnsCycle({4, 5, 2, 3}));
+}
+
+// Block multiple levels of streams.
+TEST_F(PopNextUsableStreamTest, MultiLevelBlocked) {
+ for (SpdyStreamId stream_id : {1, 4, 5}) {
+ scheduler_.MarkStreamReady(stream_id, false);
+ }
+ // Round-robin only across 2 and 3, since children of 1 have lower priority.
+ EXPECT_TRUE(PopNextReturnsCycle({2, 3}));
+
+ // Make 8 have equal priority as 2 and 3.
+ scheduler_.SetStreamWeight(1, 200);
+ EXPECT_TRUE(PopNextReturnsCycle({8, 2, 3}));
+}
+
+// A removed stream shouldn't be scheduled.
+TEST_F(PopNextUsableStreamTest, RemoveStream) {
+ scheduler_.UnregisterStream(1);
+
+ // Round-robin only across 2 and 3, since previous children of 1 have lower
+ // priority (the weight of 4 and 5 is scaled down when they are elevated to
+ // siblings of 2 and 3).
+ EXPECT_TRUE(PopNextReturnsCycle({2, 3}));
+
+ // Make previous children of 1 have equal priority as 2 and 3.
+ scheduler_.SetStreamWeight(4, 100);
+ scheduler_.SetStreamWeight(5, 100);
+ EXPECT_TRUE(PopNextReturnsCycle({4, 5, 2, 3}));
+}
+
+// Block an entire subtree.
+TEST_F(PopNextUsableStreamTest, SubtreeBlocked) {
+ for (SpdyStreamId stream_id : {1, 4, 5, 8}) {
+ scheduler_.MarkStreamReady(stream_id, false);
+ }
+ EXPECT_TRUE(PopNextReturnsCycle({2, 3}));
+}
+
+// If all parent streams are blocked, children should be returned.
+TEST_F(PopNextUsableStreamTest, ParentsBlocked) {
+ for (SpdyStreamId stream_id : {1, 2, 3}) {
+ scheduler_.MarkStreamReady(stream_id, false);
+ }
+ EXPECT_TRUE(PopNextReturnsCycle({4, 5, 6, 7}));
+}
+
+// Unblocking streams should make them schedulable.
+TEST_F(PopNextUsableStreamTest, BlockAndUnblock) {
+ EXPECT_TRUE(PopNextReturnsCycle({1, 2, 3}));
+ scheduler_.MarkStreamReady(2, false);
+ EXPECT_TRUE(PopNextReturnsCycle({1, 3}));
+ scheduler_.MarkStreamReady(2, true);
+ // Cycle order permuted since 2 effectively appended at tail.
+ EXPECT_TRUE(PopNextReturnsCycle({1, 3, 2}));
+}
+
+// Block nodes in multiple subtrees.
+TEST_F(PopNextUsableStreamTest, ScatteredBlocked) {
+ for (SpdyStreamId stream_id : {1, 2, 6, 7}) {
+ scheduler_.MarkStreamReady(stream_id, false);
+ }
+ // Only 3 returned, since of remaining streams it has highest priority.
+ EXPECT_TRUE(PopNextReturnsCycle({3}));
+
+ // Make children of 1 have priority equal to 3.
+ scheduler_.SetStreamWeight(1, 200);
+ EXPECT_TRUE(PopNextReturnsCycle({4, 5, 3}));
+
+ // When 4 is blocked, its child 8 should take its place, since it has same
+ // priority.
+ scheduler_.MarkStreamReady(4, false);
+ EXPECT_TRUE(PopNextReturnsCycle({8, 5, 3}));
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/spdy/mock_spdy_framer_visitor.h b/chromium/net/spdy/mock_spdy_framer_visitor.h
index 85bf5ba068c..d330c262b25 100644
--- a/chromium/net/spdy/mock_spdy_framer_visitor.h
+++ b/chromium/net/spdy/mock_spdy_framer_visitor.h
@@ -28,6 +28,7 @@ class MockSpdyFramerVisitor : public SpdyFramerVisitorInterface {
const char* data,
size_t len,
bool fin));
+ MOCK_METHOD1(OnStreamEnd, void(SpdyStreamId stream_id));
MOCK_METHOD2(OnStreamPadding, void(SpdyStreamId stream_id, size_t len));
MOCK_METHOD1(OnHeaderFrameStart,
SpdyHeadersHandlerInterface*(SpdyStreamId stream_id));
diff --git a/chromium/net/spdy/priority_write_scheduler.h b/chromium/net/spdy/priority_write_scheduler.h
index dd16b41cb8c..e1e144dd96c 100644
--- a/chromium/net/spdy/priority_write_scheduler.h
+++ b/chromium/net/spdy/priority_write_scheduler.h
@@ -130,16 +130,43 @@ class PriorityWriteScheduler {
return stream_id;
}
+ // Returns true if there's another stream of greater or equal priority ahead
+ // of |stream_id| in the queue. This function can be called to see if
+ // |stream_id| should yield work to another stream.
+ bool ShouldYield(StreamIdType stream_id) const {
+ // If there's a higher priority stream, this stream should yield.
+ if (HasHigherPriorityReadyStream(stream_id)) {
+ return true;
+ }
+
+ auto it = stream_infos_.find(stream_id);
+ if (it == stream_infos_.end()) {
+ LOG(DFATAL) << "Stream " << stream_id << " not registered";
+ return false;
+ }
+
+ // If this priority level is empty, or this stream is the next up, there's
+ // no need to yield.
+ auto ready_list = ready_lists_[it->second.priority];
+ if (ready_list.empty() || ready_list.front() == stream_id) {
+ return false;
+ }
+
+ // There are other streams in this priority level which take precedence.
+ // Yield.
+ return true;
+ }
+
// Returns true if the scheduler has any ready streams with a higher priority
// than that of the specified stream. If the stream is not registered, logs
// DFATAL and returns false.
- bool HasHigherPriorityReadyStream(StreamIdType stream_id) {
+ bool HasHigherPriorityReadyStream(StreamIdType stream_id) const {
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
LOG(DFATAL) << "Stream " << stream_id << " not registered";
return false;
}
- StreamInfo& stream_info = it->second;
+ const StreamInfo& stream_info = it->second;
for (SpdyPriority p = kV3HighestPriority; p < stream_info.priority; ++p) {
if (!ready_lists_[p].empty()) {
return true;
diff --git a/chromium/net/spdy/priority_write_scheduler_test.cc b/chromium/net/spdy/priority_write_scheduler_test.cc
index c503f5e243e..56f659d0d7d 100644
--- a/chromium/net/spdy/priority_write_scheduler_test.cc
+++ b/chromium/net/spdy/priority_write_scheduler_test.cc
@@ -257,6 +257,33 @@ TEST_F(PriorityWriteSchedulerTest, UnregisterRemovesStream) {
"No ready streams available");
}
+TEST_F(PriorityWriteSchedulerTest, ShouldYield) {
+ scheduler_.RegisterStream(1, 1);
+ scheduler_.RegisterStream(4, 4);
+ scheduler_.RegisterStream(5, 4);
+ scheduler_.RegisterStream(7, 7);
+
+ // Make sure we don't yield when the list is empty.
+ EXPECT_FALSE(scheduler_.ShouldYield(1));
+
+ // Add a low priority stream.
+ scheduler_.MarkStreamReady(4, false);
+ // 4 should not yield to itself.
+ EXPECT_FALSE(scheduler_.ShouldYield(4));
+ // 7 should yield as 4 is blocked and a higher priority.
+ EXPECT_TRUE(scheduler_.ShouldYield(7));
+ // 5 should yield to 4 as they are the same priority.
+ EXPECT_TRUE(scheduler_.ShouldYield(5));
+ // 1 should not yield as 1 is higher priority.
+ EXPECT_FALSE(scheduler_.ShouldYield(1));
+
+ // Add a second stream in that priority class.
+ scheduler_.MarkStreamReady(5, false);
+ // 4 and 5 are both blocked, but 4 is at the front so should not yield.
+ EXPECT_FALSE(scheduler_.ShouldYield(4));
+ EXPECT_TRUE(scheduler_.ShouldYield(5));
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/spdy/spdy_alt_svc_wire_format.cc b/chromium/net/spdy/spdy_alt_svc_wire_format.cc
index ba32160e6f9..2ec677754b7 100644
--- a/chromium/net/spdy/spdy_alt_svc_wire_format.cc
+++ b/chromium/net/spdy/spdy_alt_svc_wire_format.cc
@@ -4,6 +4,7 @@
#include "net/spdy/spdy_alt_svc_wire_format.h"
+#include <algorithm>
#include <limits>
#include <string>
@@ -54,6 +55,9 @@ SpdyAltSvcWireFormat::AlternativeService::AlternativeService(
SpdyAltSvcWireFormat::AlternativeService::~AlternativeService() {}
+SpdyAltSvcWireFormat::AlternativeService::AlternativeService(
+ const AlternativeService& other) = default;
+
// static
bool SpdyAltSvcWireFormat::ParseHeaderFieldValue(
StringPiece value,
diff --git a/chromium/net/spdy/spdy_alt_svc_wire_format.h b/chromium/net/spdy/spdy_alt_svc_wire_format.h
index 28b45723684..de4043527a9 100644
--- a/chromium/net/spdy/spdy_alt_svc_wire_format.h
+++ b/chromium/net/spdy/spdy_alt_svc_wire_format.h
@@ -47,6 +47,7 @@ class NET_EXPORT_PRIVATE SpdyAltSvcWireFormat {
uint32_t max_age,
double probability,
VersionVector version);
+ AlternativeService(const AlternativeService& other);
~AlternativeService();
bool operator==(const AlternativeService& other) const {
diff --git a/chromium/net/spdy/spdy_buffer.cc b/chromium/net/spdy/spdy_buffer.cc
index fad3305d894..be783fc6a1a 100644
--- a/chromium/net/spdy/spdy_buffer.cc
+++ b/chromium/net/spdy/spdy_buffer.cc
@@ -20,16 +20,17 @@ namespace {
// Bound on largest frame any SPDY version has allowed.
const size_t kMaxSpdyFrameSize = 0x00ffffff;
-// Makes a SpdyFrame with |size| bytes of data copied from
-// |data|. |data| must be non-NULL and |size| must be positive.
-scoped_ptr<SpdyFrame> MakeSpdyFrame(const char* data, size_t size) {
+// Makes a SpdySerializedFrame with |size| bytes of data copied from |data|.
+// |data| must be non-NULL and |size| must be positive.
+scoped_ptr<SpdySerializedFrame> MakeSpdySerializedFrame(const char* data,
+ size_t size) {
DCHECK(data);
CHECK_GT(size, 0u);
CHECK_LE(size, kMaxSpdyFrameSize);
scoped_ptr<char[]> frame_data(new char[size]);
std::memcpy(frame_data.get(), data, size);
- scoped_ptr<SpdyFrame> frame(
- new SpdyFrame(frame_data.release(), size, true /* owns_buffer */));
+ scoped_ptr<SpdySerializedFrame> frame(new SpdySerializedFrame(
+ frame_data.release(), size, true /* owns_buffer */));
return frame;
}
@@ -56,9 +57,8 @@ class SpdyBuffer::SharedFrameIOBuffer : public IOBuffer {
DISALLOW_COPY_AND_ASSIGN(SharedFrameIOBuffer);
};
-SpdyBuffer::SpdyBuffer(scoped_ptr<SpdyFrame> frame)
- : shared_frame_(new SharedFrame()),
- offset_(0) {
+SpdyBuffer::SpdyBuffer(scoped_ptr<SpdySerializedFrame> frame)
+ : shared_frame_(new SharedFrame()), offset_(0) {
shared_frame_->data = std::move(frame);
}
@@ -69,7 +69,7 @@ SpdyBuffer::SpdyBuffer(const char* data, size_t size) :
offset_(0) {
CHECK_GT(size, 0u);
CHECK_LE(size, kMaxSpdyFrameSize);
- shared_frame_->data = MakeSpdyFrame(data, size);
+ shared_frame_->data = MakeSpdySerializedFrame(data, size);
}
SpdyBuffer::~SpdyBuffer() {
diff --git a/chromium/net/spdy/spdy_buffer.h b/chromium/net/spdy/spdy_buffer.h
index 94ee97fe6d5..d12c89fcf83 100644
--- a/chromium/net/spdy/spdy_buffer.h
+++ b/chromium/net/spdy/spdy_buffer.h
@@ -17,7 +17,7 @@
namespace net {
class IOBuffer;
-class SpdyFrame;
+class SpdySerializedFrame;
// SpdyBuffer is a class to hold data read from or to be written to a
// SPDY connection. It is similar to a DrainableIOBuffer but is not
@@ -47,7 +47,7 @@ class NET_EXPORT_PRIVATE SpdyBuffer {
// Construct with the data in the given frame. Assumes that data is
// owned by |frame| or outlives it.
- explicit SpdyBuffer(scoped_ptr<SpdyFrame> frame);
+ explicit SpdyBuffer(scoped_ptr<SpdySerializedFrame> frame);
// Construct with a copy of the given raw data. |data| must be
// non-NULL and |size| must be non-zero.
@@ -86,9 +86,9 @@ class NET_EXPORT_PRIVATE SpdyBuffer {
private:
void ConsumeHelper(size_t consume_size, ConsumeSource consume_source);
- // Ref-count the passed-in SpdyFrame to support the semantics of
+ // Ref-count the passed-in SpdySerializedFrame to support the semantics of
// |GetIOBufferForRemainingData()|.
- typedef base::RefCountedData<scoped_ptr<SpdyFrame> > SharedFrame;
+ typedef base::RefCountedData<scoped_ptr<SpdySerializedFrame>> SharedFrame;
class SharedFrameIOBuffer;
diff --git a/chromium/net/spdy/spdy_buffer_unittest.cc b/chromium/net/spdy/spdy_buffer_unittest.cc
index 4200916c426..46a5c2b63fd 100644
--- a/chromium/net/spdy/spdy_buffer_unittest.cc
+++ b/chromium/net/spdy/spdy_buffer_unittest.cc
@@ -29,13 +29,11 @@ std::string BufferToString(const SpdyBuffer& buffer) {
return std::string(buffer.GetRemainingData(), buffer.GetRemainingSize());
}
-// Construct a SpdyBuffer from a SpdyFrame and make sure its data
+// Construct a SpdyBuffer from a SpdySerializedFrame and make sure its data
// points to the frame's underlying data.
TEST_F(SpdyBufferTest, FrameConstructor) {
- SpdyBuffer buffer(
- scoped_ptr<SpdyFrame>(
- new SpdyFrame(const_cast<char*>(kData), kDataSize,
- false /* owns_buffer */)));
+ SpdyBuffer buffer(scoped_ptr<SpdySerializedFrame>(new SpdySerializedFrame(
+ const_cast<char*>(kData), kDataSize, false /* owns_buffer */)));
EXPECT_EQ(kData, buffer.GetRemainingData());
EXPECT_EQ(kDataSize, buffer.GetRemainingSize());
diff --git a/chromium/net/spdy/spdy_frame_builder.cc b/chromium/net/spdy/spdy_frame_builder.cc
index fb8cdccb45b..7911b808ac7 100644
--- a/chromium/net/spdy/spdy_frame_builder.cc
+++ b/chromium/net/spdy/spdy_frame_builder.cc
@@ -62,14 +62,13 @@ bool SpdyFrameBuilder::Seek(size_t length) {
bool SpdyFrameBuilder::WriteControlFrameHeader(const SpdyFramer& framer,
SpdyFrameType type,
uint8_t flags) {
- DCHECK_GE(SPDY3, version_);
+ DCHECK_EQ(SPDY3, version_);
DCHECK(SpdyConstants::IsValidFrameType(
version_, SpdyConstants::SerializeFrameType(version_, type)));
bool success = true;
FlagsAndLength flags_length = CreateFlagsAndLength(
flags, capacity_ - framer.GetControlFrameHeaderSize());
- success &= WriteUInt16(kControlFlagMask |
- SpdyConstants::SerializeMajorVersion(version_));
+ success &= WriteUInt16(kControlFlagMask | kSpdy3Version);
success &= WriteUInt16(
SpdyConstants::SerializeFrameType(framer.protocol_version(), type));
success &= WriteBytes(&flags_length, sizeof(flags_length));
@@ -80,7 +79,7 @@ bool SpdyFrameBuilder::WriteControlFrameHeader(const SpdyFramer& framer,
bool SpdyFrameBuilder::WriteDataFrameHeader(const SpdyFramer& framer,
SpdyStreamId stream_id,
uint8_t flags) {
- if (version_ > SPDY3) {
+ if (version_ == HTTP2) {
return BeginNewFrame(framer, DATA, flags, stream_id);
}
DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
@@ -104,7 +103,7 @@ bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer,
DCHECK(SpdyConstants::IsValidFrameType(
version_, SpdyConstants::SerializeFrameType(version_, type)));
DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
- DCHECK_GT(framer.protocol_version(), SPDY3);
+ DCHECK_EQ(HTTP2, framer.protocol_version());
bool success = true;
if (length_ > 0) {
// Update length field for previous frame.
@@ -169,7 +168,7 @@ bool SpdyFrameBuilder::RewriteLength(const SpdyFramer& framer) {
bool SpdyFrameBuilder::OverwriteLength(const SpdyFramer& framer,
size_t length) {
- if (version_ < HTTP2) {
+ if (version_ == SPDY3) {
DCHECK_LE(length,
SpdyConstants::GetFrameMaximumSize(version_) -
framer.GetFrameMinimumSize());
@@ -179,7 +178,7 @@ bool SpdyFrameBuilder::OverwriteLength(const SpdyFramer& framer,
bool success = false;
const size_t old_length = length_;
- if (version_ < HTTP2) {
+ if (version_ == SPDY3) {
FlagsAndLength flags_length = CreateFlagsAndLength(
0, // We're not writing over the flags value anyway.
length);
@@ -198,7 +197,7 @@ bool SpdyFrameBuilder::OverwriteLength(const SpdyFramer& framer,
}
bool SpdyFrameBuilder::OverwriteFlags(const SpdyFramer& framer, uint8_t flags) {
- DCHECK_GT(framer.protocol_version(), SPDY3);
+ 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 8d75aef760f..d1f9535f2f6 100644
--- a/chromium/net/spdy/spdy_frame_builder.h
+++ b/chromium/net/spdy/spdy_frame_builder.h
@@ -74,13 +74,13 @@ class NET_EXPORT_PRIVATE SpdyFrameBuilder {
SpdyStreamId stream_id);
// Takes the buffer from the SpdyFrameBuilder.
- SpdyFrame* take() {
- if (version_ > SPDY3) {
+ SpdySerializedFrame take() {
+ if (version_ == HTTP2) {
DLOG_IF(DFATAL, SpdyConstants::GetFrameMaximumSize(version_) < length_)
<< "Frame length " << length_
<< " is longer than the maximum allowed length.";
}
- SpdyFrame* rv = new SpdyFrame(buffer_.release(), length(), true);
+ SpdySerializedFrame rv(buffer_.release(), length(), true);
capacity_ = 0;
length_ = 0;
offset_ = 0;
diff --git a/chromium/net/spdy/spdy_frame_builder_test.cc b/chromium/net/spdy/spdy_frame_builder_test.cc
index 70b9374d8b8..b27abf9e551 100644
--- a/chromium/net/spdy/spdy_frame_builder_test.cc
+++ b/chromium/net/spdy/spdy_frame_builder_test.cc
@@ -29,11 +29,11 @@ TEST_P(SpdyFrameBuilderTest, GetWritableBuffer) {
char* writable_buffer = builder.GetWritableBuffer(builder_size);
memset(writable_buffer, ~1, builder_size);
EXPECT_TRUE(builder.Seek(builder_size));
- scoped_ptr<SpdyFrame> frame(builder.take());
+ 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));
+ base::StringPiece(frame.data(), builder_size));
}
TEST_P(SpdyFrameBuilderTest, RewriteLength) {
@@ -42,9 +42,9 @@ TEST_P(SpdyFrameBuilderTest, RewriteLength) {
// then is corrected via RewriteLength().
SpdyFramer framer(spdy_version_);
SpdySettingsIR settings_ir;
- scoped_ptr<SpdyFrame> expected(framer.SerializeSettings(settings_ir));
- SpdyFrameBuilder builder(expected->size() + 1, spdy_version_);
- if (spdy_version_ <= SPDY3) {
+ 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 {
@@ -52,26 +52,26 @@ TEST_P(SpdyFrameBuilderTest, RewriteLength) {
}
EXPECT_TRUE(builder.GetWritableBuffer(1) != NULL);
builder.RewriteLength(framer);
- scoped_ptr<SpdyFrame> built(builder.take());
- EXPECT_EQ(base::StringPiece(expected->data(), expected->size()),
- base::StringPiece(built->data(), expected->size()));
+ SpdySerializedFrame built(builder.take());
+ EXPECT_EQ(base::StringPiece(expected.data(), expected.size()),
+ base::StringPiece(built.data(), expected.size()));
}
TEST_P(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) {
+ if (spdy_version_ == SPDY3) {
return;
}
SpdyHeadersIR headers_ir(1);
- scoped_ptr<SpdyFrame> expected(framer.SerializeHeaders(headers_ir));
- SpdyFrameBuilder builder(expected->size(), spdy_version_);
+ SpdySerializedFrame expected(framer.SerializeHeaders(headers_ir));
+ SpdyFrameBuilder builder(expected.size(), spdy_version_);
builder.BeginNewFrame(framer, HEADERS, 0, 1);
builder.OverwriteFlags(framer, HEADERS_FLAG_END_HEADERS);
- scoped_ptr<SpdyFrame> built(builder.take());
- EXPECT_EQ(base::StringPiece(expected->data(), expected->size()),
- base::StringPiece(built->data(), built->size()));
+ 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_framer.cc b/chromium/net/spdy/spdy_framer.cc
index 6568b281d2c..ab242b8e1c9 100644
--- a/chromium/net/spdy/spdy_framer.cc
+++ b/chromium/net/spdy/spdy_framer.cc
@@ -14,6 +14,7 @@
#include "base/lazy_instance.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram_macros.h"
+#include "net/quic/quic_flags.h"
#include "net/spdy/hpack/hpack_constants.h"
#include "net/spdy/spdy_frame_builder.h"
#include "net/spdy/spdy_frame_reader.h"
@@ -105,8 +106,10 @@ const size_t kPadLengthFieldSize = 1;
const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1);
const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
-// We fragment sent control frames at smaller payload boundaries.
-const size_t SpdyFramer::kMaxControlFrameSize = 1024;
+// Even though the length field is 24 bits, we keep this 16 kB
+// limit on control frame size for legacy reasons and to
+// mitigate DOS attacks.
+const size_t SpdyFramer::kMaxControlFrameSize = (1 << 14) - 1;
// 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.
@@ -169,9 +172,9 @@ SpdyFramer::SpdyFramer(SpdyMajorVersion version)
enable_compression_(true),
syn_frame_processed_(false),
probable_http_response_(false),
- end_stream_when_done_(false) {
- DCHECK_GE(protocol_version_, SPDY_MIN_VERSION);
- DCHECK_LE(protocol_version_, SPDY_MAX_VERSION);
+ end_stream_when_done_(false),
+ spdy_on_stream_end_(FLAGS_spdy_on_stream_end) {
+ DCHECK(protocol_version_ == SPDY3 || protocol_version_ == HTTP2);
DCHECK_LE(kMaxControlFrameSize,
SpdyConstants::GetFrameMaximumSize(protocol_version_) +
SpdyConstants::GetControlFrameHeaderSize(protocol_version_));
@@ -204,18 +207,18 @@ void SpdyFramer::Reset() {
}
size_t SpdyFramer::GetDataFrameMinimumSize() const {
- return SpdyConstants::GetDataFrameMinimumSize(protocol_version());
+ return SpdyConstants::GetDataFrameMinimumSize(protocol_version_);
}
// Size, in bytes, of the control frame header.
size_t SpdyFramer::GetControlFrameHeaderSize() const {
- return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
+ return SpdyConstants::GetControlFrameHeaderSize(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) {
+ if (protocol_version_ == SPDY3) {
// Calculated as:
// control frame header + 2 * 4 (stream IDs) + 1 (priority)
// + 1 (unused)
@@ -231,7 +234,7 @@ size_t SpdyFramer::GetSynReplyMinimumSize() const {
// Size, in bytes, of a SYN_REPLY frame not including the variable-length
// header block.
size_t size = GetControlFrameHeaderSize();
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
// Calculated as:
// control frame header + 4 (stream IDs)
size += 4;
@@ -242,7 +245,7 @@ size_t SpdyFramer::GetSynReplyMinimumSize() const {
size_t SpdyFramer::GetRstStreamMinimumSize() const {
// Size, in bytes, of a RST_STREAM frame.
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
// Calculated as:
// control frame header + 4 (stream id) + 4 (status code)
return GetControlFrameHeaderSize() + 8;
@@ -257,7 +260,7 @@ 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) {
+ if (protocol_version_ == SPDY3) {
return GetControlFrameHeaderSize() + 4;
} else {
return GetControlFrameHeaderSize();
@@ -266,7 +269,7 @@ size_t SpdyFramer::GetSettingsMinimumSize() const {
size_t SpdyFramer::GetPingSize() const {
// Size, in bytes, of this PING frame.
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
// Calculated as:
// control frame header + 4 (id)
return GetControlFrameHeaderSize() + 4;
@@ -279,23 +282,15 @@ size_t SpdyFramer::GetPingSize() const {
size_t SpdyFramer::GetGoAwayMinimumSize() const {
// Size, in bytes, of this GOAWAY frame. Calculated as:
- // 1. Control frame header size
- size_t size = GetControlFrameHeaderSize();
-
- // 2. Last good stream id (4 bytes)
- size += 4;
-
- // 3. GOAWAY frames also contain a status (4 bytes)
- size += 4;
-
- return size;
+ // Control frame header + last stream id (4 bytes) + error code (4 bytes).
+ return GetControlFrameHeaderSize() + 8;
}
size_t SpdyFramer::GetHeadersMinimumSize() const {
// Size, in bytes, of a HEADERS frame not including the variable-length
// header block.
size_t size = GetControlFrameHeaderSize();
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
// Calculated as:
// control frame header + 4 (stream IDs)
size += 4;
@@ -306,7 +301,7 @@ size_t SpdyFramer::GetHeadersMinimumSize() const {
size_t SpdyFramer::GetWindowUpdateSize() const {
// Size, in bytes, of a WINDOW_UPDATE frame.
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
// Calculated as:
// control frame header + 4 (stream id) + 4 (delta)
return GetControlFrameHeaderSize() + 8;
@@ -318,14 +313,14 @@ size_t SpdyFramer::GetWindowUpdateSize() const {
}
size_t SpdyFramer::GetBlockedSize() const {
- DCHECK_LT(SPDY3, protocol_version());
+ DCHECK_EQ(HTTP2, protocol_version_);
// Size, in bytes, of a BLOCKED frame.
// The BLOCKED frame has no payload beyond the control frame header.
return GetControlFrameHeaderSize();
}
size_t SpdyFramer::GetPushPromiseMinimumSize() const {
- DCHECK_LT(SPDY3, protocol_version());
+ 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 GetControlFrameHeaderSize() + 4;
@@ -358,7 +353,7 @@ size_t SpdyFramer::GetFrameMinimumSize() const {
}
size_t SpdyFramer::GetFrameMaximumSize() const {
- return SpdyConstants::GetFrameMaximumSize(protocol_version());
+ return SpdyConstants::GetFrameMaximumSize(protocol_version_);
}
size_t SpdyFramer::GetDataFrameMaximumPayload() const {
@@ -366,7 +361,7 @@ size_t SpdyFramer::GetDataFrameMaximumPayload() const {
}
size_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const {
- return SpdyConstants::GetPrefixLength(type, protocol_version());
+ return SpdyConstants::GetPrefixLength(type, protocol_version_);
}
const char* SpdyFramer::StateToString(int state) {
@@ -397,6 +392,8 @@ const char* SpdyFramer::StateToString(int state) {
return "SPDY_GOAWAY_FRAME_PAYLOAD";
case SPDY_RST_STREAM_FRAME_PAYLOAD:
return "SPDY_RST_STREAM_FRAME_PAYLOAD";
+ case SPDY_SETTINGS_FRAME_HEADER:
+ return "SPDY_SETTINGS_FRAME_HEADER";
case SPDY_SETTINGS_FRAME_PAYLOAD:
return "SPDY_SETTINGS_FRAME_PAYLOAD";
case SPDY_ALTSVC_FRAME_PAYLOAD:
@@ -426,6 +423,8 @@ const char* SpdyFramer::ErrorCodeToString(int error_code) {
return "INVALID_CONTROL_FRAME";
case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
return "CONTROL_PAYLOAD_TOO_LARGE";
+ case SPDY_INVALID_CONTROL_FRAME_SIZE:
+ return "INVALID_CONTROL_FRAME_SIZE";
case SPDY_ZLIB_INIT_FAILURE:
return "ZLIB_INIT_FAILURE";
case SPDY_UNSUPPORTED_VERSION:
@@ -550,23 +549,23 @@ 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)
- // take a different path through the state machine - they
+ // take a special path through the state machine - they
// will go:
// 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
// 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
- //
- // SETTINGS frames take a slightly modified route:
- // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
- // 2. SPDY_SETTINGS_FRAME_PAYLOAD
- //
- // All other control frames will use the alternate route directly to
- // SPDY_CONTROL_FRAME_PAYLOAD
int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
len -= bytes_read;
data += bytes_read;
break;
}
+ case SPDY_SETTINGS_FRAME_HEADER: {
+ int bytes_read = ProcessSettingsFrameHeader(data, len);
+ len -= bytes_read;
+ data += bytes_read;
+ break;
+ }
+
case SPDY_SETTINGS_FRAME_PAYLOAD: {
int bytes_read = ProcessSettingsFramePayload(data, len);
len -= bytes_read;
@@ -576,7 +575,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() > SPDY3);
+ data, len, protocol_version_ == HTTP2);
len -= bytes_read;
data += bytes_read;
break;
@@ -704,26 +703,21 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
bool is_control_frame = false;
int control_frame_type_field =
- SpdyConstants::DataFrameType(protocol_version());
+ SpdyConstants::DataFrameType(protocol_version_);
// 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) {
+ if (protocol_version_ == SPDY3) {
uint16_t version = 0;
bool successful_read = reader.ReadUInt16(&version);
DCHECK(successful_read);
is_control_frame = (version & kControlFlagMask) != 0;
- version &= ~kControlFlagMask; // Only valid for control frames.
if (is_control_frame) {
- // We check version before we check validity: version can never be
- // 'invalid', it can only be unsupported.
- if (version < SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION) ||
- version > SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION) ||
- SpdyConstants::ParseMajorVersion(version) != protocol_version()) {
+ version &= ~kControlFlagMask;
+ if (version != kSpdy3Version) {
// Version does not match the version the framer was initialized with.
- DVLOG(1) << "Unsupported SPDY version "
- << version
- << " (expected " << protocol_version() << ")";
+ DVLOG(1) << "Unsupported SPDY version " << version << " (expected "
+ << kSpdy3Version << ")";
set_error(SPDY_UNSUPPORTED_VERSION);
return 0;
}
@@ -757,8 +751,9 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
// 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);
+ is_control_frame =
+ control_frame_type_field !=
+ SpdyConstants::SerializeFrameType(protocol_version_, DATA);
if (is_control_frame) {
current_frame_length_ = length_field + GetControlFrameHeaderSize();
@@ -776,8 +771,9 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
// Before we accept a DATA frame, we need to make sure we're not in the
// middle of processing a header block.
- const bool is_continuation_frame = (control_frame_type_field ==
- SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION));
+ const bool is_continuation_frame =
+ (control_frame_type_field ==
+ SpdyConstants::SerializeFrameType(protocol_version_, CONTINUATION));
if ((expect_continuation_ != 0) != is_continuation_frame) {
if (expect_continuation_ != 0) {
DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
@@ -813,18 +809,18 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
// if we're here, then we have the common header all received.
if (!is_control_frame) {
- if (protocol_version() > SPDY3) {
+ if (protocol_version_ == HTTP2) {
// Catch bogus tests sending oversized DATA frames.
DCHECK_GE(GetFrameMaximumSize(), current_frame_length_)
<< "DATA frame too large for SPDY >= 4.";
}
uint8_t valid_data_flags = 0;
- if (protocol_version() > SPDY3) {
+ if (protocol_version_ == SPDY3) {
+ valid_data_flags = DATA_FLAG_FIN;
+ } else {
valid_data_flags =
DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | DATA_FLAG_PADDED;
- } else {
- valid_data_flags = DATA_FLAG_FIN;
}
if (current_frame_flags_ & ~valid_data_flags) {
@@ -838,8 +834,12 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
} else {
// Empty data frame.
if (current_frame_flags_ & DATA_FLAG_FIN) {
- visitor_->OnStreamFrameData(
- current_frame_stream_id_, NULL, 0, true);
+ if (spdy_on_stream_end_) {
+ visitor_->OnStreamEnd(current_frame_stream_id_);
+ } else {
+ visitor_->OnStreamFrameData(current_frame_stream_id_, nullptr, 0,
+ true);
+ }
}
CHANGE_STATE(SPDY_FRAME_COMPLETE);
}
@@ -855,11 +855,11 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
DCHECK_EQ(SPDY_NO_ERROR, error_code_);
DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_.len());
- if (!SpdyConstants::IsValidFrameType(protocol_version(),
+ if (!SpdyConstants::IsValidFrameType(protocol_version_,
control_frame_type_field)) {
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field
- << " (protocol version: " << protocol_version() << ")";
+ << " (protocol version: " << protocol_version_ << ")";
set_error(SPDY_INVALID_CONTROL_FRAME);
return;
} else {
@@ -884,7 +884,7 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
}
}
- current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(),
+ current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version_,
control_frame_type_field);
// Do some sanity checking on the control frame sizes and flags.
@@ -905,13 +905,11 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
}
break;
case RST_STREAM:
- // TODO(bnc): Enforce the length of the header, and change error to
- // FRAME_SIZE_ERROR.
if ((current_frame_length_ != GetRstStreamMinimumSize() &&
- protocol_version() <= SPDY3) ||
+ protocol_version_ == SPDY3) ||
(current_frame_length_ < GetRstStreamMinimumSize() &&
- protocol_version() > SPDY3)) {
- set_error(SPDY_INVALID_CONTROL_FRAME);
+ protocol_version_ == HTTP2)) {
+ set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
} else if (current_frame_flags_ != 0) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
}
@@ -920,47 +918,46 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
{
// 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_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());
+ size_t setting_size = SpdyConstants::GetSettingSize(protocol_version_);
if (current_frame_length_ < GetSettingsMinimumSize() ||
(current_frame_length_ - GetControlFrameHeaderSize())
% setting_size != values_prefix_size) {
DLOG(WARNING) << "Invalid length for SETTINGS frame: "
<< current_frame_length_;
- set_error(SPDY_INVALID_CONTROL_FRAME);
- } else if (protocol_version() <= SPDY3 &&
+ set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
+ } else if (protocol_version_ == SPDY3 &&
current_frame_flags_ &
- ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
+ ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
- } else if (protocol_version() > SPDY3 &&
+ } else if (protocol_version_ == HTTP2 &&
current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
- } else if (protocol_version() > SPDY3 &&
+ } else if (protocol_version_ == HTTP2 &&
current_frame_flags_ & SETTINGS_FLAG_ACK &&
current_frame_length_ > GetSettingsMinimumSize()) {
- set_error(SPDY_INVALID_CONTROL_FRAME);
+ set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
}
break;
}
case PING:
if (current_frame_length_ != GetPingSize()) {
- set_error(SPDY_INVALID_CONTROL_FRAME);
- } else if ((protocol_version() <= SPDY3 && current_frame_flags_ != 0) ||
+ set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
+ } else if ((protocol_version_ == SPDY3 && current_frame_flags_ != 0) ||
(current_frame_flags_ & ~PING_FLAG_ACK)) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
}
break;
case GOAWAY:
{
- // For SPDY version < 4, there are only mandatory fields and the header
- // has a fixed length. For SPDY version >= 4, optional opaque data may
- // be appended to the GOAWAY frame, thus there is only a minimal length
- // restriction.
- if ((current_frame_length_ != GetGoAwayMinimumSize() &&
- protocol_version() <= SPDY3) ||
- (current_frame_length_ < GetGoAwayMinimumSize() &&
- protocol_version() > SPDY3)) {
+ // 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);
} else if (current_frame_flags_ != 0) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
@@ -970,7 +967,7 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
case HEADERS:
{
size_t min_size = GetHeadersMinimumSize();
- if (protocol_version() > SPDY3 &&
+ if (protocol_version_ == HTTP2 &&
(current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
min_size += 4;
}
@@ -978,10 +975,10 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
// TODO(mlavan): check here for HEADERS with no payload?
// (not allowed in HTTP2)
set_error(SPDY_INVALID_CONTROL_FRAME);
- } else if (protocol_version() <= SPDY3 &&
+ } else if (protocol_version_ == SPDY3 &&
current_frame_flags_ & ~CONTROL_FLAG_FIN) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
- } else if (protocol_version() > SPDY3 &&
+ } else if (protocol_version_ == HTTP2 &&
current_frame_flags_ &
~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT |
@@ -992,14 +989,14 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
break;
case WINDOW_UPDATE:
if (current_frame_length_ != GetWindowUpdateSize()) {
- set_error(SPDY_INVALID_CONTROL_FRAME);
+ set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
} else if (current_frame_flags_ != 0) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
}
break;
case BLOCKED:
- if (current_frame_length_ != GetBlockedSize() ||
- protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3 ||
+ current_frame_length_ != GetBlockedSize()) {
set_error(SPDY_INVALID_CONTROL_FRAME);
} else if (current_frame_flags_ != 0) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
@@ -1008,9 +1005,9 @@ 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) {
+ } else if (protocol_version_ == SPDY3 && current_frame_flags_ != 0) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
- } else if (protocol_version() > SPDY3 &&
+ } else if (protocol_version_ == HTTP2 &&
current_frame_flags_ &
~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
HEADERS_FLAG_PADDED)) {
@@ -1018,8 +1015,8 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
}
break;
case CONTINUATION:
- if (current_frame_length_ < GetContinuationMinimumSize() ||
- protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3 ||
+ current_frame_length_ < GetContinuationMinimumSize()) {
set_error(SPDY_INVALID_CONTROL_FRAME);
} else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
@@ -1033,9 +1030,9 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
}
break;
case PRIORITY:
- if (current_frame_length_ != GetPrioritySize() ||
- protocol_version() <= SPDY3) {
- set_error(SPDY_INVALID_CONTROL_FRAME);
+ if (protocol_version_ == SPDY3 ||
+ current_frame_length_ != GetPrioritySize()) {
+ set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
} else if (current_frame_flags_ != 0) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
}
@@ -1058,8 +1055,8 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
}
if (current_frame_length_ >
- SpdyConstants::GetFrameMaximumSize(protocol_version()) +
- SpdyConstants::GetControlFrameHeaderSize(protocol_version())) {
+ SpdyConstants::GetFrameMaximumSize(protocol_version_) +
+ SpdyConstants::GetControlFrameHeaderSize(protocol_version_)) {
DLOG(WARNING) << "Received control frame of type " << current_frame_type_
<< " with way too big of a payload: "
<< current_frame_length_;
@@ -1097,7 +1094,7 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
break;
case HEADERS:
frame_size_without_variable_data = GetHeadersMinimumSize();
- if (protocol_version() > SPDY3) {
+ if (protocol_version_ == HTTP2) {
if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
frame_size_without_variable_data += kPadLengthFieldSize;
}
@@ -1110,7 +1107,7 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
break;
case PUSH_PROMISE:
frame_size_without_variable_data = GetPushPromiseMinimumSize();
- if (protocol_version() > SPDY3 &&
+ if (protocol_version_ == HTTP2 &&
current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
frame_size_without_variable_data += kPadLengthFieldSize;
}
@@ -1136,15 +1133,19 @@ void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
}
if (frame_size_without_variable_data > 0) {
- // We have a control frame with a header block. We need to parse the
- // remainder of the control frame's header before we can parse the header
- // block. The start of the header block varies with the control type.
+ // We have a control frame with variable-size data. We need to parse the
+ // remainder of the control frame's header before we can parse the payload.
+ // The start of the payload varies with the control frame type.
DCHECK_GE(frame_size_without_variable_data,
static_cast<int32_t>(current_frame_buffer_.len()));
remaining_control_header_ =
frame_size_without_variable_data - current_frame_buffer_.len();
- CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
+ if (current_frame_type_ == SETTINGS) {
+ CHANGE_STATE(SPDY_SETTINGS_FRAME_HEADER);
+ } else {
+ CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
+ }
return;
}
@@ -1179,17 +1180,6 @@ size_t SpdyFramer::GetSerializedLength(
return total_length;
}
-void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
- const SpdyMajorVersion spdy_version,
- const SpdyHeaderBlock* headers) {
- frame->WriteUInt32(headers->size());
- SpdyHeaderBlock::const_iterator it;
- for (it = headers->begin(); it != headers->end(); ++it) {
- frame->WriteStringPiece32(it->first);
- frame->WriteStringPiece32(it->second);
- }
-}
-
// TODO(phajdan.jr): Clean up after we no longer need
// to workaround http://crbug.com/139744.
#if !defined(USE_SYSTEM_ZLIB)
@@ -1381,13 +1371,13 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
switch (current_frame_type_) {
case SYN_STREAM:
{
- DCHECK_GE(SPDY3, protocol_version());
+ 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);
- break;
+ return original_len - len;
}
SpdyStreamId associated_to_stream_id = kInvalidStream;
@@ -1416,42 +1406,29 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
(current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
(current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
}
- CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
- break;
- case SETTINGS:
- if (protocol_version() > SPDY3 &&
- current_frame_flags_ & SETTINGS_FLAG_ACK) {
- visitor_->OnSettingsAck();
- CHANGE_STATE(SPDY_FRAME_COMPLETE);
- } else {
- visitor_->OnSettings(current_frame_flags_ &
- SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
- CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
- }
break;
case SYN_REPLY:
+ DCHECK_EQ(SPDY3, protocol_version_);
+ /* FALLTHROUGH */
case HEADERS:
// SYN_REPLY and HEADERS are the same, save for the visitor call.
{
- if (protocol_version() > SPDY3) {
- DCHECK_EQ(HEADERS, current_frame_type_);
- }
bool successful_read = true;
- if (protocol_version() <= SPDY3) {
+ 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);
- break;
+ return original_len - len;
}
- if (protocol_version() > SPDY3 &&
- !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
- current_frame_type_ == HEADERS) {
+ if (protocol_version_ == HTTP2 &&
+ !(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() > SPDY3 &&
+ if (protocol_version_ == HTTP2 &&
current_frame_flags_ & HEADERS_FLAG_PADDED) {
uint8_t pad_payload_len = 0;
DCHECK_EQ(remaining_padding_payload_length_, 0u);
@@ -1464,7 +1441,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
SpdyPriority priority = 0;
uint32_t parent_stream_id = 0;
bool exclusive = false;
- if (protocol_version() > SPDY3 && has_priority) {
+ if (protocol_version_ == HTTP2 && has_priority) {
uint32_t stream_dependency;
successful_read = reader.ReadUInt32(&stream_dependency);
DCHECK(successful_read);
@@ -1497,17 +1474,16 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
expect_continuation_ == 0);
}
}
- CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
break;
case PUSH_PROMISE:
{
- DCHECK_LT(SPDY3, protocol_version());
+ DCHECK_EQ(HTTP2, protocol_version_);
if (current_frame_stream_id_ == 0) {
set_error(SPDY_INVALID_CONTROL_FRAME);
- break;
+ return original_len - len;
}
bool successful_read = true;
- if (protocol_version() > SPDY3 &&
+ if (protocol_version_ == HTTP2 &&
current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
DCHECK_EQ(remaining_padding_payload_length_, 0u);
uint8_t pad_payload_len = 0;
@@ -1523,7 +1499,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
DCHECK(reader.IsDoneReading());
if (promised_stream_id == 0) {
set_error(SPDY_INVALID_CONTROL_FRAME);
- break;
+ return original_len - len;
}
if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) {
expect_continuation_ = current_frame_stream_id_;
@@ -1539,7 +1515,6 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
(current_frame_flags_ &
PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
}
- CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
break;
case CONTINUATION:
{
@@ -1550,7 +1525,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
// that current_frame_stream_id != 0.
if (current_frame_stream_id_ != expect_continuation_) {
set_error(SPDY_INVALID_CONTROL_FRAME);
- break;
+ return original_len - len;
}
if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) {
expect_continuation_ = 0;
@@ -1565,11 +1540,16 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
(current_frame_flags_ &
HEADERS_FLAG_END_HEADERS) != 0);
}
- CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
break;
default:
- DCHECK(false);
+#ifndef NDEBUG
+ LOG(FATAL) << "Invalid control frame type: " << current_frame_type_;
+#else
+ set_error(SPDY_INVALID_CONTROL_FRAME);
+ return original_len - len;
+#endif
}
+ CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
}
return original_len - len;
}
@@ -1601,7 +1581,7 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
processed_successfully = false;
}
} else if (process_bytes > 0) {
- if (enable_compression_ && protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3 && enable_compression_) {
processed_successfully = IncrementallyDecompressControlFrameHeaderData(
current_frame_stream_id_, data, process_bytes);
} else {
@@ -1648,6 +1628,31 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
return process_bytes;
}
+size_t SpdyFramer::ProcessSettingsFrameHeader(const char* data, size_t len) {
+ // TODO(birenroy): Remove this state when removing SPDY3. I think it only
+ // exists to read the number of settings in the frame for SPDY3. This value
+ // is never parsed or used.
+ size_t bytes_read = 0;
+ if (remaining_control_header_ > 0) {
+ bytes_read =
+ UpdateCurrentFrameBuffer(&data, &len, remaining_control_header_);
+ remaining_control_header_ -= bytes_read;
+ remaining_data_length_ -= bytes_read;
+ }
+ if (remaining_control_header_ == 0) {
+ if (protocol_version_ == HTTP2 &&
+ current_frame_flags_ & SETTINGS_FLAG_ACK) {
+ visitor_->OnSettingsAck();
+ CHANGE_STATE(SPDY_FRAME_COMPLETE);
+ } else {
+ visitor_->OnSettings(current_frame_flags_ &
+ SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
+ CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
+ }
+ }
+ return bytes_read;
+}
+
size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
size_t data_len) {
DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
@@ -1655,7 +1660,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 = SpdyConstants::GetSettingSize(protocol_version_);
// Loop over our incoming data.
while (unprocessed_bytes > 0) {
@@ -1701,7 +1706,7 @@ size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
}
void SpdyFramer::DeliverHpackBlockAsSpdy3Block(size_t compressed_len) {
- DCHECK_LT(SPDY3, protocol_version());
+ DCHECK_EQ(HTTP2, protocol_version_);
DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
const SpdyHeaderBlock& block = GetHpackDecoder()->decoded_block();
@@ -1710,17 +1715,17 @@ void SpdyFramer::DeliverHpackBlockAsSpdy3Block(size_t compressed_len) {
ProcessControlFrameHeaderBlock(NULL, 0, false);
return;
}
- size_t payload_len = GetSerializedLength(protocol_version(), &block);
+ size_t payload_len = GetSerializedLength(protocol_version_, &block);
SpdyFrameBuilder builder(payload_len, SPDY3);
SerializeHeaderBlockWithoutCompression(&builder, block);
- scoped_ptr<SpdyFrame> frame(builder.take());
+ SpdySerializedFrame frame = builder.take();
// Preserve padding length, and reset it after the re-entrant call.
size_t remaining_padding = remaining_padding_payload_length_;
remaining_padding_payload_length_ = 0;
- remaining_data_length_ = frame->size();
+ remaining_data_length_ = frame.size();
if (payload_len != 0) {
int compression_pct = 100 - (100 * compressed_len) / payload_len;
@@ -1729,7 +1734,7 @@ void SpdyFramer::DeliverHpackBlockAsSpdy3Block(size_t compressed_len) {
compression_pct);
}
- ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false);
+ ProcessControlFrameHeaderBlock(frame.data(), frame.size(), false);
remaining_padding_payload_length_ = remaining_padding;
remaining_data_length_ = remaining_padding;
@@ -1743,11 +1748,11 @@ bool SpdyFramer::ProcessSetting(const char* data) {
// Extract fields.
// Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
- if (protocol_version() <= SPDY3) {
+ 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);
+ 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)));
@@ -1757,18 +1762,18 @@ bool SpdyFramer::ProcessSetting(const char* data) {
}
// Validate id.
- if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) {
+ if (!SpdyConstants::IsValidSettingId(protocol_version_, id_field)) {
DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
return false;
} else {
// In HTTP2 we ignore unknown settings for extensibility.
return true;
}
}
- id = SpdyConstants::ParseSettingId(protocol_version(), id_field);
+ id = SpdyConstants::ParseSettingId(protocol_version_, id_field);
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
// Detect duplicates.
if (id <= settings_scratch_.last_setting_id) {
DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
@@ -1807,10 +1812,10 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
switch (current_frame_type_) {
case PING: {
SpdyPingId id = 0;
- bool is_ack = protocol_version() > SPDY3 &&
- (current_frame_flags_ & PING_FLAG_ACK);
+ bool is_ack = protocol_version_ == HTTP2 &&
+ (current_frame_flags_ & PING_FLAG_ACK);
bool successful_read = true;
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
uint32_t id32 = 0;
successful_read = reader.ReadUInt32(&id32);
id = id32;
@@ -1825,7 +1830,7 @@ 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) {
+ if (protocol_version_ == SPDY3) {
successful_read = reader.ReadUInt31(&current_frame_stream_id_);
DCHECK(successful_read);
}
@@ -1837,13 +1842,13 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
}
break;
case BLOCKED: {
- DCHECK_LT(SPDY3, protocol_version());
+ DCHECK_EQ(HTTP2, protocol_version_);
DCHECK(reader.IsDoneReading());
visitor_->OnBlocked(current_frame_stream_id_);
}
break;
case PRIORITY: {
- DCHECK_LT(SPDY3, protocol_version());
+ DCHECK_EQ(HTTP2, protocol_version_);
uint32_t stream_dependency;
uint32_t parent_stream_id;
bool exclusive;
@@ -1897,22 +1902,19 @@ size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
DCHECK(successful_read);
- // In SPDYv3 and up, frames also specify a status code - parse it out.
+ // Parse status code.
SpdyGoAwayStatus status = GOAWAY_OK;
- if (protocol_version() >= SPDY3) {
- uint32_t status_raw = GOAWAY_OK;
- successful_read = reader.ReadUInt32(&status_raw);
- DCHECK(successful_read);
- if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
- status_raw)) {
- status = SpdyConstants::ParseGoAwayStatus(protocol_version(),
- status_raw);
- } else {
- if (protocol_version() > SPDY3) {
- // Treat unrecognized status codes as INTERNAL_ERROR as
- // recommended by the HTTP/2 spec.
- status = GOAWAY_INTERNAL_ERROR;
- }
+ uint32_t status_raw = GOAWAY_OK;
+ successful_read = reader.ReadUInt32(&status_raw);
+ DCHECK(successful_read);
+ if (SpdyConstants::IsValidGoAwayStatus(protocol_version_, status_raw)) {
+ status =
+ SpdyConstants::ParseGoAwayStatus(protocol_version_, 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;
}
}
// Finished parsing the GOAWAY header, call frame handler.
@@ -1961,7 +1963,7 @@ size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
SpdyFrameReader reader(current_frame_buffer_.data(),
current_frame_buffer_.len());
reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
DCHECK(successful_read);
}
@@ -1970,12 +1972,12 @@ size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
uint32_t status_raw = status;
bool successful_read = reader.ReadUInt32(&status_raw);
DCHECK(successful_read);
- if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
+ if (SpdyConstants::IsValidRstStreamStatus(protocol_version_,
status_raw)) {
status =
- SpdyConstants::ParseRstStreamStatus(protocol_version(), status_raw);
+ SpdyConstants::ParseRstStreamStatus(protocol_version_, status_raw);
} else {
- if (protocol_version() > SPDY3) {
+ if (protocol_version_ == HTTP2) {
// Treat unrecognized status codes as INTERNAL_ERROR as
// recommended by the HTTP/2 spec.
status = RST_STREAM_INTERNAL_ERROR;
@@ -2087,7 +2089,7 @@ 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) {
- DCHECK_LE(HTTP2, protocol_version());
+ DCHECK_EQ(HTTP2, protocol_version_);
visitor_->OnStreamPadding(current_frame_stream_id_, amount_to_discard);
}
data += amount_to_discard;
@@ -2103,7 +2105,11 @@ size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 ||
end_stream_when_done_)) {
end_stream_when_done_ = false;
- visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
+ if (spdy_on_stream_end_) {
+ visitor_->OnStreamEnd(current_frame_stream_id_);
+ } else {
+ visitor_->OnStreamFrameData(current_frame_stream_id_, nullptr, 0, true);
+ }
}
CHANGE_STATE(SPDY_FRAME_COMPLETE);
}
@@ -2200,14 +2206,20 @@ bool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
return true;
}
-SpdySerializedFrame* SpdyFramer::SerializeData(
- const SpdyDataIR& data_ir) const {
+SpdySerializedFrame SpdyFramer::SerializeData(const SpdyDataIR& data_ir) const {
uint8_t flags = DATA_FLAG_NONE;
if (data_ir.fin()) {
flags = DATA_FLAG_FIN;
}
- if (protocol_version() > SPDY3) {
+ if (protocol_version_ == SPDY3) {
+ const size_t size = GetDataFrameMinimumSize() + data_ir.data().length();
+ SpdyFrameBuilder builder(size, protocol_version_);
+ builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
+ builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
+ DCHECK_EQ(size, builder.length());
+ return builder.take();
+ } else {
int num_padding_fields = 0;
if (data_ir.padded()) {
flags |= DATA_FLAG_PADDED;
@@ -2217,7 +2229,7 @@ SpdySerializedFrame* SpdyFramer::SerializeData(
const size_t size_with_padding = num_padding_fields +
data_ir.data().length() + data_ir.padding_payload_len() +
GetDataFrameMinimumSize();
- SpdyFrameBuilder builder(size_with_padding, protocol_version());
+ 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);
@@ -2229,17 +2241,10 @@ SpdySerializedFrame* SpdyFramer::SerializeData(
}
DCHECK_EQ(size_with_padding, builder.length());
return builder.take();
- } else {
- const size_t size = GetDataFrameMinimumSize() + data_ir.data().length();
- SpdyFrameBuilder builder(size, protocol_version());
- builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
- builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
- DCHECK_EQ(size, builder.length());
- return builder.take();
}
}
-SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
+SpdySerializedFrame SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
const SpdyDataIR& data_ir) const {
uint8_t flags = DATA_FLAG_NONE;
if (data_ir.fin()) {
@@ -2248,7 +2253,7 @@ SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
size_t frame_size = GetDataFrameMinimumSize();
size_t num_padding_fields = 0;
- if (protocol_version() > SPDY3) {
+ if (protocol_version_ == HTTP2) {
if (data_ir.padded()) {
flags |= DATA_FLAG_PADDED;
++num_padding_fields;
@@ -2256,9 +2261,9 @@ SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
frame_size += num_padding_fields;
}
- SpdyFrameBuilder builder(frame_size, protocol_version());
+ SpdyFrameBuilder builder(frame_size, protocol_version_);
builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
- if (protocol_version() > SPDY3) {
+ if (protocol_version_ == HTTP2) {
if (data_ir.padded()) {
builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
}
@@ -2271,15 +2276,14 @@ SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
return builder.take();
}
-SpdySerializedFrame* SpdyFramer::SerializeSynStream(
+SpdySerializedFrame SpdyFramer::SerializeSynStream(
const SpdySynStreamIR& syn_stream) {
- DCHECK_GE(SPDY3, protocol_version());
+ DCHECK_EQ(SPDY3, protocol_version_);
uint8_t flags = 0;
if (syn_stream.fin()) {
flags |= CONTROL_FLAG_FIN;
}
if (syn_stream.unidirectional()) {
- // TODO(hkhalil): invalid for HTTP2.
flags |= CONTROL_FLAG_UNIDIRECTIONAL;
}
@@ -2294,7 +2298,7 @@ SpdySerializedFrame* SpdyFramer::SerializeSynStream(
size_t size = GetSynStreamMinimumSize() +
GetSerializedLength(syn_stream.header_block());
- SpdyFrameBuilder builder(size, protocol_version());
+ 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());
@@ -2305,7 +2309,7 @@ SpdySerializedFrame* SpdyFramer::SerializeSynStream(
if (debug_visitor_) {
const size_t payload_len =
- GetSerializedLength(protocol_version(), &(syn_stream.header_block()));
+ GetSerializedLength(protocol_version_, &(syn_stream.header_block()));
debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
SYN_STREAM,
payload_len,
@@ -2315,9 +2319,9 @@ SpdySerializedFrame* SpdyFramer::SerializeSynStream(
return builder.take();
}
-SpdySerializedFrame* SpdyFramer::SerializeSynReply(
+SpdySerializedFrame SpdyFramer::SerializeSynReply(
const SpdySynReplyIR& syn_reply) {
- DCHECK_GE(SPDY3, protocol_version());
+ DCHECK_EQ(SPDY3, protocol_version_);
uint8_t flags = 0;
if (syn_reply.fin()) {
flags |= CONTROL_FLAG_FIN;
@@ -2327,22 +2331,15 @@ SpdySerializedFrame* SpdyFramer::SerializeSynReply(
const size_t size =
GetSynReplyMinimumSize() + GetSerializedLength(syn_reply.header_block());
- SpdyFrameBuilder builder(size, protocol_version());
- if (protocol_version() <= SPDY3) {
- builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
- builder.WriteUInt32(syn_reply.stream_id());
- } else {
- builder.BeginNewFrame(*this,
- HEADERS,
- flags,
- syn_reply.stream_id());
- }
+ 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()));
+ GetSerializedLength(protocol_version_, &(syn_reply.header_block()));
debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
SYN_REPLY,
payload_len,
@@ -2352,7 +2349,7 @@ SpdySerializedFrame* SpdyFramer::SerializeSynReply(
return builder.take();
}
-SpdySerializedFrame* SpdyFramer::SerializeRstStream(
+SpdySerializedFrame SpdyFramer::SerializeRstStream(
const SpdyRstStreamIR& rst_stream) const {
// TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
// payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
@@ -2360,10 +2357,10 @@ SpdySerializedFrame* SpdyFramer::SerializeRstStream(
// 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());
+ SpdyFrameBuilder builder(expected_length, protocol_version_);
// Serialize the RST_STREAM frame.
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
builder.WriteUInt32(rst_stream.stream_id());
} else {
@@ -2371,17 +2368,17 @@ SpdySerializedFrame* SpdyFramer::SerializeRstStream(
}
builder.WriteUInt32(SpdyConstants::SerializeRstStreamStatus(
- protocol_version(), rst_stream.status()));
+ protocol_version_, rst_stream.status()));
DCHECK_EQ(expected_length, builder.length());
return builder.take();
}
-SpdySerializedFrame* SpdyFramer::SerializeSettings(
+SpdySerializedFrame SpdyFramer::SerializeSettings(
const SpdySettingsIR& settings) const {
uint8_t flags = 0;
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
if (settings.clear_settings()) {
flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
}
@@ -2392,23 +2389,23 @@ SpdySerializedFrame* SpdyFramer::SerializeSettings(
}
const SpdySettingsIR::ValueMap* values = &(settings.values());
- size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
+ size_t setting_size = SpdyConstants::GetSettingSize(protocol_version_);
// 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) {
+ SpdyFrameBuilder builder(size, protocol_version_);
+ if (protocol_version_ == SPDY3) {
builder.WriteControlFrameHeader(*this, SETTINGS, flags);
} else {
builder.BeginNewFrame(*this, SETTINGS, flags, 0);
}
// If this is an ACK, payload should be empty.
- if (protocol_version() > SPDY3 && settings.is_ack()) {
+ if (protocol_version_ == HTTP2 && settings.is_ack()) {
return builder.take();
}
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
builder.WriteUInt32(values->size());
}
DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
@@ -2416,9 +2413,9 @@ SpdySerializedFrame* SpdyFramer::SerializeSettings(
it != values->end();
++it) {
int setting_id =
- SpdyConstants::SerializeSettingId(protocol_version(), it->first);
+ SpdyConstants::SerializeSettingId(protocol_version_, it->first);
DCHECK_GE(setting_id, 0);
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
uint8_t setting_flags = 0;
if (it->second.persist_value) {
setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
@@ -2428,7 +2425,7 @@ SpdySerializedFrame* SpdyFramer::SerializeSettings(
}
SettingsFlagsAndId flags_and_id(setting_flags, setting_id);
uint32_t id_and_flags_wire =
- flags_and_id.GetWireFormat(protocol_version());
+ flags_and_id.GetWireFormat(protocol_version_);
builder.WriteBytes(&id_and_flags_wire, 4);
} else {
builder.WriteUInt16(static_cast<uint16_t>(setting_id));
@@ -2439,9 +2436,9 @@ SpdySerializedFrame* SpdyFramer::SerializeSettings(
return builder.take();
}
-SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
- SpdyFrameBuilder builder(GetPingSize(), protocol_version());
- if (protocol_version() <= SPDY3) {
+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 {
@@ -2456,18 +2453,17 @@ SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
return builder.take();
}
-SpdySerializedFrame* SpdyFramer::SerializeGoAway(
+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() > SPDY3) {
+ if (protocol_version_ == HTTP2) {
expected_length += goaway.description().size();
}
- SpdyFrameBuilder builder(expected_length, protocol_version());
+ SpdyFrameBuilder builder(expected_length, protocol_version_);
// Serialize the GOAWAY frame.
- if (protocol_version() <= SPDY3) {
+ if (protocol_version_ == SPDY3) {
builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
} else {
builder.BeginNewFrame(*this, GOAWAY, 0, 0);
@@ -2477,14 +2473,11 @@ SpdySerializedFrame* SpdyFramer::SerializeGoAway(
builder.WriteUInt32(goaway.last_good_stream_id());
// GOAWAY frames also specify the error status code.
- if (protocol_version() >= SPDY3) {
- // TODO(jgraettinger): Merge back to server-side.
- builder.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
- goaway.status()));
- }
+ builder.WriteUInt32(
+ SpdyConstants::SerializeGoAwayStatus(protocol_version_, goaway.status()));
- // In HTTP2 and up, GOAWAY frames may also specify opaque data.
- if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) {
+ // In HTTP2, GOAWAY frames may also specify opaque data.
+ if ((protocol_version_ == HTTP2) && (goaway.description().size() > 0)) {
builder.WriteBytes(goaway.description().data(),
goaway.description().size());
}
@@ -2493,13 +2486,12 @@ SpdySerializedFrame* SpdyFramer::SerializeGoAway(
return builder.take();
}
-SpdySerializedFrame* SpdyFramer::SerializeHeaders(
- const SpdyHeadersIR& headers) {
+SpdySerializedFrame SpdyFramer::SerializeHeaders(const SpdyHeadersIR& headers) {
uint8_t flags = 0;
if (headers.fin()) {
flags |= CONTROL_FLAG_FIN;
}
- if (protocol_version() > SPDY3) {
+ if (protocol_version_ == HTTP2) {
// This will get overwritten if we overflow into a CONTINUATION frame.
flags |= HEADERS_FLAG_END_HEADERS;
if (headers.has_priority()) {
@@ -2514,7 +2506,7 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
// variable-length header block.
size_t size = GetHeadersMinimumSize();
- if (protocol_version() > SPDY3 && headers.padded()) {
+ if (protocol_version_ == HTTP2 && headers.padded()) {
size += kPadLengthFieldSize;
size += headers.padding_payload_len();
}
@@ -2529,7 +2521,9 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
}
string hpack_encoding;
- if (protocol_version() > SPDY3) {
+ if (protocol_version_ == SPDY3) {
+ size += GetSerializedLength(headers.header_block());
+ } else {
if (enable_compression_) {
GetHpackEncoder()->EncodeHeaderSet(headers.header_block(),
&hpack_encoding);
@@ -2543,12 +2537,10 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
GetContinuationMinimumSize();
flags &= ~HEADERS_FLAG_END_HEADERS;
}
- } else {
- size += GetSerializedLength(headers.header_block());
}
- SpdyFrameBuilder builder(size, protocol_version());
- if (protocol_version() <= SPDY3) {
+ SpdyFrameBuilder builder(size, protocol_version_);
+ if (protocol_version_ == SPDY3) {
builder.WriteControlFrameHeader(*this, HEADERS, flags);
builder.WriteUInt32(headers.stream_id());
} else {
@@ -2559,7 +2551,9 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
}
DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
- if (protocol_version() > SPDY3) {
+ if (protocol_version_ == SPDY3) {
+ SerializeHeaderBlock(&builder, headers);
+ } else {
int padding_payload_len = 0;
if (headers.padded()) {
builder.WriteUInt8(headers.padding_payload_len());
@@ -2575,8 +2569,6 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
headers.stream_id(),
HEADERS,
padding_payload_len);
- } else {
- SerializeHeaderBlock(&builder, headers);
}
if (debug_visitor_) {
@@ -2584,7 +2576,7 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
// 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()));
+ GetSerializedLength(protocol_version_, &(headers.header_block()));
debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
HEADERS,
payload_len,
@@ -2594,10 +2586,10 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
return builder.take();
}
-SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
+SpdySerializedFrame SpdyFramer::SerializeWindowUpdate(
const SpdyWindowUpdateIR& window_update) const {
- SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version());
- if (protocol_version() <= SPDY3) {
+ SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version_);
+ if (protocol_version_ == SPDY3) {
builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
builder.WriteUInt32(window_update.stream_id());
} else {
@@ -2611,16 +2603,17 @@ SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
return builder.take();
}
-SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
- DCHECK_LT(SPDY3, protocol_version());
- SpdyFrameBuilder builder(GetBlockedSize(), protocol_version());
+SpdySerializedFrame SpdyFramer::SerializeBlocked(
+ const SpdyBlockedIR& blocked) const {
+ DCHECK_EQ(HTTP2, protocol_version_);
+ SpdyFrameBuilder builder(GetBlockedSize(), protocol_version_);
builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id());
return builder.take();
}
-SpdyFrame* SpdyFramer::SerializePushPromise(
+SpdySerializedFrame SpdyFramer::SerializePushPromise(
const SpdyPushPromiseIR& push_promise) {
- DCHECK_LT(SPDY3, protocol_version());
+ 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;
@@ -2648,7 +2641,7 @@ SpdyFrame* SpdyFramer::SerializePushPromise(
flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
}
- SpdyFrameBuilder builder(size, protocol_version());
+ SpdyFrameBuilder builder(size, protocol_version_);
builder.BeginNewFrame(*this,
PUSH_PROMISE,
flags,
@@ -2677,7 +2670,7 @@ SpdyFrame* 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(protocol_version_, &(push_promise.header_block()));
debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
PUSH_PROMISE,
payload_len,
@@ -2690,9 +2683,9 @@ SpdyFrame* SpdyFramer::SerializePushPromise(
// TODO(jgraettinger): This implementation is incorrect. The continuation
// frame continues a previously-begun HPACK encoding; it doesn't begin a
// new one. Figure out whether it makes sense to keep SerializeContinuation().
-SpdyFrame* SpdyFramer::SerializeContinuation(
+SpdySerializedFrame SpdyFramer::SerializeContinuation(
const SpdyContinuationIR& continuation) {
- CHECK_LT(SPDY3, protocol_version());
+ CHECK_EQ(HTTP2, protocol_version_);
uint8_t flags = 0;
if (continuation.end_headers()) {
flags |= HEADERS_FLAG_END_HEADERS;
@@ -2710,7 +2703,7 @@ SpdyFrame* SpdyFramer::SerializeContinuation(
}
size += hpack_encoding.size();
- SpdyFrameBuilder builder(size, protocol_version());
+ SpdyFrameBuilder builder(size, protocol_version_);
builder.BeginNewFrame(*this, CONTINUATION, flags,
continuation.stream_id());
DCHECK_EQ(GetContinuationMinimumSize(), builder.length());
@@ -2719,8 +2712,8 @@ SpdyFrame* SpdyFramer::SerializeContinuation(
return builder.take();
}
-SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) {
- DCHECK_LT(SPDY3, protocol_version());
+SpdySerializedFrame SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) {
+ DCHECK_EQ(HTTP2, protocol_version_);
size_t size = GetAltSvcMinimumSize();
size += altsvc_ir.origin().length();
@@ -2728,7 +2721,7 @@ SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) {
altsvc_ir.altsvc_vector());
size += value.length();
- SpdyFrameBuilder builder(size, protocol_version());
+ SpdyFrameBuilder builder(size, protocol_version_);
builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc_ir.stream_id());
builder.WriteUInt16(altsvc_ir.origin().length());
@@ -2738,11 +2731,12 @@ SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) {
return builder.take();
}
-SpdyFrame* SpdyFramer::SerializePriority(const SpdyPriorityIR& priority) const {
- DCHECK_LT(SPDY3, protocol_version());
+SpdySerializedFrame SpdyFramer::SerializePriority(
+ const SpdyPriorityIR& priority) const {
+ DCHECK_EQ(HTTP2, protocol_version_);
size_t size = GetPrioritySize();
- SpdyFrameBuilder builder(size, protocol_version());
+ SpdyFrameBuilder builder(size, protocol_version_);
builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id());
builder.WriteUInt32(PackStreamDependencyValues(priority.exclusive(),
@@ -2756,71 +2750,71 @@ namespace {
class FrameSerializationVisitor : public SpdyFrameVisitor {
public:
- explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
+ explicit FrameSerializationVisitor(SpdyFramer* framer)
+ : framer_(framer), frame_() {}
~FrameSerializationVisitor() override {}
- SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
+ SpdySerializedFrame ReleaseSerializedFrame() { return std::move(frame_); }
void VisitData(const SpdyDataIR& data) override {
- frame_.reset(framer_->SerializeData(data));
+ frame_ = framer_->SerializeData(data);
}
void VisitSynStream(const SpdySynStreamIR& syn_stream) override {
- frame_.reset(framer_->SerializeSynStream(syn_stream));
+ frame_ = framer_->SerializeSynStream(syn_stream);
}
void VisitSynReply(const SpdySynReplyIR& syn_reply) override {
- frame_.reset(framer_->SerializeSynReply(syn_reply));
+ frame_ = framer_->SerializeSynReply(syn_reply);
}
void VisitRstStream(const SpdyRstStreamIR& rst_stream) override {
- frame_.reset(framer_->SerializeRstStream(rst_stream));
+ frame_ = framer_->SerializeRstStream(rst_stream);
}
void VisitSettings(const SpdySettingsIR& settings) override {
- frame_.reset(framer_->SerializeSettings(settings));
+ frame_ = framer_->SerializeSettings(settings);
}
void VisitPing(const SpdyPingIR& ping) override {
- frame_.reset(framer_->SerializePing(ping));
+ frame_ = framer_->SerializePing(ping);
}
void VisitGoAway(const SpdyGoAwayIR& goaway) override {
- frame_.reset(framer_->SerializeGoAway(goaway));
+ frame_ = framer_->SerializeGoAway(goaway);
}
void VisitHeaders(const SpdyHeadersIR& headers) override {
- frame_.reset(framer_->SerializeHeaders(headers));
+ frame_ = framer_->SerializeHeaders(headers);
}
void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) override {
- frame_.reset(framer_->SerializeWindowUpdate(window_update));
+ frame_ = framer_->SerializeWindowUpdate(window_update);
}
void VisitBlocked(const SpdyBlockedIR& blocked) override {
- frame_.reset(framer_->SerializeBlocked(blocked));
+ frame_ = framer_->SerializeBlocked(blocked);
}
void VisitPushPromise(const SpdyPushPromiseIR& push_promise) override {
- frame_.reset(framer_->SerializePushPromise(push_promise));
+ frame_ = framer_->SerializePushPromise(push_promise);
}
void VisitContinuation(const SpdyContinuationIR& continuation) override {
- frame_.reset(framer_->SerializeContinuation(continuation));
+ frame_ = framer_->SerializeContinuation(continuation);
}
void VisitAltSvc(const SpdyAltSvcIR& altsvc) override {
- frame_.reset(framer_->SerializeAltSvc(altsvc));
+ frame_ = framer_->SerializeAltSvc(altsvc);
}
void VisitPriority(const SpdyPriorityIR& priority) override {
- frame_.reset(framer_->SerializePriority(priority));
+ frame_ = framer_->SerializePriority(priority);
}
private:
SpdyFramer* framer_;
- scoped_ptr<SpdySerializedFrame> frame_;
+ SpdySerializedFrame frame_;
};
} // namespace
-SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
+SpdySerializedFrame SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
FrameSerializationVisitor visitor(this);
frame.Visit(&visitor);
return visitor.ReleaseSerializedFrame();
}
size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
- CHECK_GE(SPDY3, protocol_version());
const size_t uncompressed_length =
- GetSerializedLength(protocol_version(), &headers);
+ GetSerializedLength(protocol_version_, &headers);
if (!enable_compression_) {
return uncompressed_length;
}
@@ -2831,7 +2825,7 @@ size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
}
size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
- DCHECK_GT(protocol_version(), SPDY3);
+ DCHECK_EQ(HTTP2, protocol_version_);
DCHECK_GT(size, kMaxControlFrameSize);
size_t overflow = size - kMaxControlFrameSize;
size_t payload_size = kMaxControlFrameSize - GetContinuationMinimumSize();
@@ -2951,7 +2945,7 @@ z_stream* SpdyFramer::GetHeaderDecompressor() {
}
HpackEncoder* SpdyFramer::GetHpackEncoder() {
- DCHECK_LT(SPDY3, protocol_version());
+ DCHECK_EQ(HTTP2, protocol_version_);
if (hpack_encoder_.get() == nullptr) {
hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
}
@@ -2959,7 +2953,7 @@ HpackEncoder* SpdyFramer::GetHpackEncoder() {
}
HpackDecoder* SpdyFramer::GetHpackDecoder() {
- DCHECK_LT(SPDY3, protocol_version());
+ DCHECK_EQ(HTTP2, protocol_version_);
if (hpack_decoder_.get() == nullptr) {
hpack_decoder_.reset(new HpackDecoder());
}
@@ -3092,7 +3086,6 @@ void SpdyFramer::SerializeHeaderBlockWithoutCompression(
void SpdyFramer::SerializeHeaderBlock(SpdyFrameBuilder* builder,
const SpdyFrameWithHeaderBlockIR& frame) {
- CHECK_GE(SPDY3, protocol_version());
if (!enable_compression_) {
return SerializeHeaderBlockWithoutCompression(builder,
frame.header_block());
@@ -3100,11 +3093,11 @@ void SpdyFramer::SerializeHeaderBlock(SpdyFrameBuilder* builder,
// 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());
+ GetSerializedLength(protocol_version_, &(frame.header_block()));
+ SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version_);
SerializeHeaderBlockWithoutCompression(&uncompressed_builder,
frame.header_block());
- scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
+ SpdySerializedFrame uncompressed_payload(uncompressed_builder.take());
z_stream* compressor = GetHeaderCompressor();
if (!compressor) {
@@ -3123,7 +3116,7 @@ void SpdyFramer::SerializeHeaderBlock(SpdyFrameBuilder* builder,
// 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->next_in = reinterpret_cast<Bytef*>(uncompressed_payload.data());
compressor->avail_in = uncompressed_len;
#endif // defined(USE_SYSTEM_ZLIB)
compressor->next_out = reinterpret_cast<Bytef*>(
diff --git a/chromium/net/spdy/spdy_framer.h b/chromium/net/spdy/spdy_framer.h
index 5f3ff2a2cc3..7375333d6f5 100644
--- a/chromium/net/spdy/spdy_framer.h
+++ b/chromium/net/spdy/spdy_framer.h
@@ -98,7 +98,7 @@ class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface {
public:
virtual ~SpdyFramerVisitorInterface() {}
- // Called if an error is detected in the SpdyFrame protocol.
+ // Called if an error is detected in the SpdySerializedFrame protocol.
virtual void OnError(SpdyFramer* framer) = 0;
// Called when a data frame header is received. The frame's data
@@ -119,6 +119,10 @@ class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface {
size_t len,
bool fin) = 0;
+ // Called when the other side has finished sending data on this stream.
+ // |stream_id| The stream that was receivin data.
+ virtual void OnStreamEnd(SpdyStreamId stream_id) = 0;
+
// Called when padding is received (padding length field or padding octets).
// |stream_id| The stream receiving data.
// |len| The number of padding octets.
@@ -195,13 +199,13 @@ class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface {
// OnControlFrameHeaderData().
// |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.
- // |priority| If |has_priority| is true and protocol version > SPDY3,
- // priority value for the receiving stream, else 0.
+ // and, if protocol version == HTTP2, stream dependency info.
+ // |priority| If |has_priority| is true, then priority value 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.
+ // 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,
+ // version == HTTP2, 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,
@@ -317,6 +321,7 @@ class NET_EXPORT_PRIVATE SpdyFramer {
SPDY_CONTROL_FRAME_HEADER_BLOCK,
SPDY_GOAWAY_FRAME_PAYLOAD,
SPDY_RST_STREAM_FRAME_PAYLOAD,
+ SPDY_SETTINGS_FRAME_HEADER,
SPDY_SETTINGS_FRAME_PAYLOAD,
SPDY_ALTSVC_FRAME_PAYLOAD,
};
@@ -335,6 +340,7 @@ class NET_EXPORT_PRIVATE SpdyFramer {
SPDY_INVALID_DATA_FRAME_FLAGS, // Data frame has invalid flags.
SPDY_INVALID_CONTROL_FRAME_FLAGS, // Control frame has invalid flags.
SPDY_UNEXPECTED_FRAME, // Frame received out of order.
+ SPDY_INVALID_CONTROL_FRAME_SIZE, // Control frame not sized to spec
LAST_ERROR, // Must be the last entry in the enum.
};
@@ -347,10 +353,9 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// purposes.)
static const size_t kHeaderDataChunkMaxSize;
- // Serializes a SpdyHeaderBlock.
- static void WriteHeaderBlock(SpdyFrameBuilder* frame,
- const SpdyMajorVersion spdy_version,
- const SpdyHeaderBlock* headers);
+ void SerializeHeaderBlockWithoutCompression(
+ SpdyFrameBuilder* builder,
+ const SpdyHeaderBlock& header_block) const;
// Retrieve serialized length of SpdyHeaderBlock.
// TODO(hkhalil): Remove, or move to quic code.
@@ -409,55 +414,55 @@ class NET_EXPORT_PRIVATE SpdyFramer {
SpdyHeaderBlock* block) const;
// Serialize a data frame.
- SpdySerializedFrame* SerializeData(const SpdyDataIR& data) const;
+ SpdySerializedFrame SerializeData(const SpdyDataIR& data) const;
// Serializes the data frame header and optionally padding length fields,
// excluding actual data payload and padding.
- SpdySerializedFrame* SerializeDataFrameHeaderWithPaddingLengthField(
+ SpdySerializedFrame SerializeDataFrameHeaderWithPaddingLengthField(
const SpdyDataIR& data) const;
// Serializes a SYN_STREAM frame.
- SpdySerializedFrame* SerializeSynStream(const SpdySynStreamIR& syn_stream);
+ SpdySerializedFrame SerializeSynStream(const SpdySynStreamIR& syn_stream);
- // Serialize a SYN_REPLY SpdyFrame.
- SpdySerializedFrame* SerializeSynReply(const SpdySynReplyIR& syn_reply);
+ // Serialize a SYN_REPLY frame.
+ SpdySerializedFrame SerializeSynReply(const SpdySynReplyIR& syn_reply);
- SpdySerializedFrame* SerializeRstStream(
+ SpdySerializedFrame SerializeRstStream(
const SpdyRstStreamIR& rst_stream) const;
// Serializes a SETTINGS frame. The SETTINGS frame is
// used to communicate name/value pairs relevant to the communication channel.
- SpdySerializedFrame* SerializeSettings(const SpdySettingsIR& settings) const;
+ SpdySerializedFrame SerializeSettings(const SpdySettingsIR& settings) const;
// Serializes a PING frame. The unique_id is used to
// identify the ping request/response.
- SpdySerializedFrame* SerializePing(const SpdyPingIR& ping) const;
+ SpdySerializedFrame SerializePing(const SpdyPingIR& ping) const;
// Serializes a GOAWAY frame. The GOAWAY frame is used
// prior to the shutting down of the TCP connection, and includes the
// stream_id of the last stream the sender of the frame is willing to process
// to completion.
- SpdySerializedFrame* SerializeGoAway(const SpdyGoAwayIR& goaway) const;
+ 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.
- SpdySerializedFrame* SerializeHeaders(const SpdyHeadersIR& 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.
- SpdySerializedFrame* SerializeWindowUpdate(
+ SpdySerializedFrame SerializeWindowUpdate(
const SpdyWindowUpdateIR& window_update) const;
// Serializes a BLOCKED frame. 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.
- SpdySerializedFrame* SerializeBlocked(const SpdyBlockedIR& blocked) const;
+ SpdySerializedFrame SerializeBlocked(const SpdyBlockedIR& blocked) const;
// Serializes a PUSH_PROMISE frame. The PUSH_PROMISE frame is used
// to inform the client that it will be receiving an additional stream
// in response to the original request. The frame includes synthesized
// headers to explain the upcoming data.
- SpdySerializedFrame* SerializePushPromise(
+ SpdySerializedFrame SerializePushPromise(
const SpdyPushPromiseIR& push_promise);
// Serializes a CONTINUATION frame. The CONTINUATION frame is used
@@ -465,19 +470,19 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// TODO(jgraettinger): This implementation is incorrect. The continuation
// frame continues a previously-begun HPACK encoding; it doesn't begin a
// new one. Figure out whether it makes sense to keep SerializeContinuation().
- SpdySerializedFrame* SerializeContinuation(
+ SpdySerializedFrame SerializeContinuation(
const SpdyContinuationIR& continuation);
// Serializes an ALTSVC frame. The ALTSVC frame advertises the
// availability of an alternative service to the client.
- SpdySerializedFrame* SerializeAltSvc(const SpdyAltSvcIR& altsvc);
+ SpdySerializedFrame SerializeAltSvc(const SpdyAltSvcIR& altsvc);
// Serializes a PRIORITY frame. The PRIORITY frame advises a change in
// the relative priority of the given stream.
- SpdySerializedFrame* SerializePriority(const SpdyPriorityIR& priority) const;
+ SpdySerializedFrame SerializePriority(const SpdyPriorityIR& priority) const;
// Serialize a frame of unknown type.
- SpdySerializedFrame* SerializeFrame(const SpdyFrameIR& frame);
+ SpdySerializedFrame SerializeFrame(const SpdyFrameIR& frame);
// NOTES about frame compression.
// We want spdy to compress headers across the entire session. As long as
@@ -490,13 +495,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// not build its state in a serial (stream based) manner.... For now, we're
// using zlib anyway.
- // Compresses a SpdyFrame.
- // On success, returns a new SpdyFrame with the payload compressed.
- // Compression state is maintained as part of the SpdyFramer.
- // Returned frame must be freed with "delete".
- // On failure, returns NULL.
- SpdyFrame* CompressFrame(const SpdyFrame& frame);
-
// For ease of testing and experimentation we can tweak compression on/off.
void set_enable_compression(bool value) {
enable_compression_ = value;
@@ -629,6 +627,7 @@ class NET_EXPORT_PRIVATE SpdyFramer {
size_t ProcessDataFramePayload(const char* data, size_t len);
size_t ProcessGoAwayFramePayload(const char* data, size_t len);
size_t ProcessRstStreamFramePayload(const char* data, size_t len);
+ size_t ProcessSettingsFrameHeader(const char* data, size_t len);
size_t ProcessSettingsFramePayload(const char* data, size_t len);
size_t ProcessAltSvcFramePayload(const char* data, size_t len);
size_t ProcessIgnoredControlFramePayload(/*const char* data,*/ size_t len);
@@ -685,10 +684,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
void WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
z_stream* out) const;
- void SerializeHeaderBlockWithoutCompression(
- SpdyFrameBuilder* builder,
- const SpdyHeaderBlock& header_block) const;
-
// Compresses automatically according to enable_compression_.
void SerializeHeaderBlock(SpdyFrameBuilder* builder,
const SpdyFrameWithHeaderBlockIR& frame);
@@ -794,6 +789,11 @@ 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_spdy_on_stream_end.
+ // If true, OnStreamEnd will be called instead of the sentinel call of
+ // OnStreamFrameData(stream_id, nullptr, 0, true)
+ bool spdy_on_stream_end_;
};
} // namespace net
diff --git a/chromium/net/spdy/spdy_framer_test.cc b/chromium/net/spdy/spdy_framer_test.cc
index ac971373de9..3c4724eb77b 100644
--- a/chromium/net/spdy/spdy_framer_test.cc
+++ b/chromium/net/spdy/spdy_framer_test.cc
@@ -16,6 +16,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "net/quic/quic_flags.h"
#include "net/spdy/hpack/hpack_constants.h"
#include "net/spdy/mock_spdy_framer_visitor.h"
#include "net/spdy/spdy_frame_builder.h"
@@ -54,9 +55,10 @@ class SpdyFramerTestUtil {
// and will CHECK fail if the input is anything other than a single,
// well-formed compressed frame.
//
- // Returns a new decompressed SpdyFrame.
- template<class SpdyFrameType> static SpdyFrame* DecompressFrame(
- SpdyFramer* framer, const SpdyFrameType& frame) {
+ // Returns a new decompressed SpdySerializedFrame.
+ template <class SpdyFrameType>
+ static SpdySerializedFrame DecompressFrame(SpdyFramer* framer,
+ const SpdyFrameType& frame) {
DecompressionVisitor visitor(framer->protocol_version());
framer->set_visitor(&visitor);
CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
@@ -65,8 +67,8 @@ class SpdyFramerTestUtil {
char* buffer = visitor.ReleaseBuffer();
CHECK(buffer != NULL);
- SpdyFrame* decompressed_frame = new SpdyFrame(buffer, visitor.size(), true);
- SetFrameLength(decompressed_frame,
+ SpdySerializedFrame decompressed_frame(buffer, visitor.size(), true);
+ SetFrameLength(&decompressed_frame,
visitor.size() - framer->GetControlFrameHeaderSize(),
framer->protocol_version());
return decompressed_frame;
@@ -97,6 +99,8 @@ class SpdyFramerTestUtil {
LOG(FATAL);
}
+ void OnStreamEnd(SpdyStreamId stream_id) override { LOG(FATAL); }
+
void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
LOG(FATAL);
}
@@ -139,9 +143,9 @@ class SpdyFramerTestUtil {
syn_stream.set_priority(priority);
syn_stream.set_fin(fin);
syn_stream.set_unidirectional(unidirectional);
- scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
+ SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
ResetBuffer();
- memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
+ memcpy(buffer_.get(), frame.data(), framer.GetSynStreamMinimumSize());
size_ += framer.GetSynStreamMinimumSize();
}
@@ -150,9 +154,9 @@ class SpdyFramerTestUtil {
framer.set_enable_compression(false);
SpdyHeadersIR headers(stream_id);
headers.set_fin(fin);
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers));
ResetBuffer();
- memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
+ memcpy(buffer_.get(), frame.data(), framer.GetHeadersMinimumSize());
size_ += framer.GetSynStreamMinimumSize();
}
@@ -185,9 +189,9 @@ class SpdyFramerTestUtil {
headers.set_parent_stream_id(parent_stream_id);
headers.set_exclusive(exclusive);
headers.set_fin(fin);
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers));
ResetBuffer();
- memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
+ memcpy(buffer_.get(), frame.data(), framer.GetHeadersMinimumSize());
size_ += framer.GetHeadersMinimumSize();
}
@@ -202,9 +206,9 @@ class SpdyFramerTestUtil {
SpdyFramer framer(version_);
framer.set_enable_compression(false);
SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
- scoped_ptr<SpdyFrame> frame(framer.SerializePushPromise(push_promise));
+ SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
ResetBuffer();
- memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
+ memcpy(buffer_.get(), frame.data(), framer.GetPushPromiseMinimumSize());
size_ += framer.GetPushPromiseMinimumSize();
}
@@ -279,7 +283,7 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
fin_frame_count_(0),
fin_opaque_data_(),
fin_flag_count_(0),
- zero_length_data_frame_count_(0),
+ end_of_stream_count_(0),
control_frame_header_data_count_(0),
zero_length_control_frame_header_data_count_(0),
data_frame_count_(0),
@@ -310,8 +314,10 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
size_t len,
bool fin) override {
EXPECT_EQ(header_stream_id_, stream_id);
- if (len == 0) {
- ++zero_length_data_frame_count_;
+ if (!FLAGS_spdy_on_stream_end) {
+ if (len == 0) {
+ ++end_of_stream_count_;
+ }
}
data_bytes_ += len;
@@ -325,6 +331,12 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
LOG(INFO) << "\", " << len << ")\n";
}
+ void OnStreamEnd(SpdyStreamId stream_id) override {
+ LOG(INFO) << "OnStreamEnd(" << stream_id << ")";
+ EXPECT_EQ(header_stream_id_, stream_id);
+ ++end_of_stream_count_;
+ }
+
void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
EXPECT_EQ(header_stream_id_, stream_id);
data_bytes_ += len;
@@ -370,10 +382,10 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
bool fin,
bool unidirectional) override {
++syn_frame_count_;
- if (framer_.protocol_version() > SPDY3) {
- InitHeaderStreaming(HEADERS, stream_id);
- } else {
+ if (framer_.protocol_version() == SPDY3) {
InitHeaderStreaming(SYN_STREAM, stream_id);
+ } else {
+ InitHeaderStreaming(HEADERS, stream_id);
}
if (fin) {
++fin_flag_count_;
@@ -382,10 +394,10 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
void OnSynReply(SpdyStreamId stream_id, bool fin) override {
++syn_reply_frame_count_;
- if (framer_.protocol_version() > SPDY3) {
- InitHeaderStreaming(HEADERS, stream_id);
- } else {
+ if (framer_.protocol_version() == SPDY3) {
InitHeaderStreaming(SYN_REPLY, stream_id);
+ } else {
+ InitHeaderStreaming(HEADERS, stream_id);
}
if (fin) {
++fin_flag_count_;
@@ -409,13 +421,14 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
}
void OnSettingsAck() override {
- DCHECK_LT(SPDY3, framer_.protocol_version());
+ DCHECK_EQ(HTTP2, framer_.protocol_version());
++settings_ack_received_;
}
void OnSettingsEnd() override {
- if (framer_.protocol_version() <= SPDY3) { return; }
- ++settings_ack_sent_;
+ if (framer_.protocol_version() == HTTP2) {
+ ++settings_ack_sent_;
+ }
}
void OnPing(SpdyPingId unique_id, bool is_ack) override { DLOG(FATAL); }
@@ -580,7 +593,7 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
int fin_frame_count_; // The count of RST_STREAM type frames received.
string fin_opaque_data_;
int fin_flag_count_; // The count of frames with the FIN flag set.
- int zero_length_data_frame_count_; // The count of zero-length data frames.
+ int end_of_stream_count_; // The count of zero-length data frames.
int control_frame_header_data_count_; // The count of chunks received.
// The count of zero-length control frame header data chunks received.
int zero_length_control_frame_header_data_count_;
@@ -613,16 +626,22 @@ class SpdyFramerPeer {
};
// Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
-StringPiece GetSerializedHeaders(const SpdyFrame* frame,
+StringPiece GetSerializedHeaders(const SpdySerializedFrame& frame,
const SpdyFramer& framer) {
- SpdyFrameReader reader(frame->data(), frame->size());
- if (framer.protocol_version() > SPDY3) {
- reader.Seek(3); // Seek past the frame length.
- } else {
+ 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) {
+ 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(),
@@ -633,21 +652,14 @@ StringPiece GetSerializedHeaders(const SpdyFrame* frame,
if (flags & HEADERS_FLAG_PRIORITY) {
frame_type = SYN_STREAM;
}
- } else {
- 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;
}
if (frame_type == SYN_STREAM) {
- return StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
- frame->size() - framer.GetSynStreamMinimumSize());
+ return StringPiece(frame.data() + framer.GetSynStreamMinimumSize(),
+ frame.size() - framer.GetSynStreamMinimumSize());
} else {
- return StringPiece(frame->data() + framer.GetHeadersMinimumSize(),
- frame->size() - framer.GetHeadersMinimumSize());
+ return StringPiece(frame.data() + framer.GetHeadersMinimumSize(),
+ frame.size() - framer.GetHeadersMinimumSize());
}
}
@@ -655,12 +667,10 @@ class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
protected:
void SetUp() override {
spdy_version_ = GetParam();
- spdy_version_ch_ = static_cast<unsigned char>(
- SpdyConstants::SerializeMajorVersion(spdy_version_));
}
void CompareFrame(const string& description,
- const SpdyFrame& actual_frame,
+ const SpdySerializedFrame& actual_frame,
const unsigned char* expected,
const int expected_len) {
const unsigned char* actual =
@@ -670,8 +680,8 @@ class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
}
void CompareFrames(const string& description,
- const SpdyFrame& expected_frame,
- const SpdyFrame& actual_frame) {
+ const SpdySerializedFrame& expected_frame,
+ const SpdySerializedFrame& actual_frame) {
CompareCharArraysWithHexError(
description,
reinterpret_cast<const unsigned char*>(expected_frame.data()),
@@ -685,7 +695,6 @@ class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
// Version of SPDY protocol to be used.
SpdyMajorVersion spdy_version_;
- unsigned char spdy_version_ch_;
};
// All tests are run with SPDY/3 and HTTP/2.
@@ -695,7 +704,7 @@ INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
// Test that we ignore cookie where both name and value are empty.
TEST_P(SpdyFramerTest, HeaderBlockWithEmptyCookie) {
- if (spdy_version_ > SPDY3) {
+ if (!IsSpdy3()) {
// Not implemented for hpack.
return;
}
@@ -706,14 +715,12 @@ TEST_P(SpdyFramerTest, HeaderBlockWithEmptyCookie) {
headers.set_priority(1);
headers.SetHeader("cookie",
"=; key=value; ; = ; foo; bar=; ; = ; k2=v2 ; =");
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
- EXPECT_TRUE(frame.get() != NULL);
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers));
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = true;
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(frame->data()),
- frame->size());
+ visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
+ frame.size());
EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
EXPECT_NE(headers.header_block(), visitor.headers_);
@@ -732,14 +739,12 @@ TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
headers.SetHeader("alpha", "beta");
headers.SetHeader("gamma", "charlie");
headers.SetHeader("cookie", "key1=value1; key2=value2");
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
- EXPECT_TRUE(frame.get() != NULL);
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers));
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = false;
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(frame->data()),
- frame->size());
+ visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
+ frame.size());
EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
EXPECT_EQ(headers.header_block(), visitor.headers_);
@@ -755,14 +760,12 @@ TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
headers.set_priority(1);
headers.SetHeader("alpha", "beta");
headers.SetHeader("gamma", "charlie");
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
- EXPECT_TRUE(frame.get() != NULL);
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers));
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = false;
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(frame->data()),
- frame->size() - 2);
+ visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
+ frame.size() - 2);
EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
EXPECT_EQ(0u, visitor.headers_.size());
@@ -771,9 +774,10 @@ TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
// Test that we can encode and decode stream dependency values in a header
// frame.
TEST_P(SpdyFramerTest, HeaderStreamDependencyValues) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
+
SpdyFramer framer(spdy_version_);
framer.set_enable_compression(false);
@@ -785,13 +789,12 @@ TEST_P(SpdyFramerTest, HeaderStreamDependencyValues) {
headers.set_has_priority(true);
headers.set_parent_stream_id(parent_stream_id);
headers.set_exclusive(exclusive);
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
- EXPECT_TRUE(frame.get() != NULL);
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers));
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = false;
- visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame->data()),
- frame->size());
+ visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
+ frame.size());
EXPECT_TRUE(visitor.header_has_priority_);
EXPECT_EQ(parent_stream_id, visitor.header_parent_stream_id_);
@@ -803,21 +806,21 @@ TEST_P(SpdyFramerTest, HeaderStreamDependencyValues) {
// 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 (spdy_version_ > SPDY3) {
+ 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");
- scoped_ptr<SpdySerializedFrame> frame(framer.SerializeSynReply(syn_reply));
- ASSERT_TRUE(frame.get() != NULL);
+ 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_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());
@@ -832,12 +835,11 @@ TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
SpdyHeadersIR headers_ir(0);
headers_ir.SetHeader("alpha", "beta");
- scoped_ptr<SpdySerializedFrame> frame(framer.SerializeHeaders(headers_ir));
- ASSERT_TRUE(frame.get() != NULL);
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers_ir));
// 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_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());
@@ -846,7 +848,7 @@ TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
// Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
// error (but don't crash).
TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -856,13 +858,11 @@ TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
SpdyPushPromiseIR push_promise(0, 4);
push_promise.SetHeader("alpha", "beta");
- scoped_ptr<SpdySerializedFrame> frame(
- framer.SerializePushPromise(push_promise));
- ASSERT_TRUE(frame.get() != NULL);
+ 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()));
+ 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());
@@ -871,7 +871,7 @@ TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
// Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
// signal an error (but don't crash).
TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -881,20 +881,18 @@ TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
SpdyPushPromiseIR push_promise(3, 0);
push_promise.SetHeader("alpha", "beta");
- scoped_ptr<SpdySerializedFrame> frame(
- framer.SerializePushPromise(push_promise));
- ASSERT_TRUE(frame.get() != NULL);
+ 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()));
+ 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_P(SpdyFramerTest, DuplicateHeader) {
- if (spdy_version_ > SPDY3) {
+ 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.
@@ -923,9 +921,8 @@ TEST_P(SpdyFramerTest, DuplicateHeader) {
SpdyHeaderBlock new_headers;
framer.set_enable_compression(false);
- scoped_ptr<SpdyFrame> control_frame(frame.take());
- StringPiece serialized_headers =
- GetSerializedHeaders(control_frame.get(), framer);
+ SpdySerializedFrame control_frame(frame.take());
+ StringPiece serialized_headers = GetSerializedHeaders(control_frame, framer);
// This should fail because duplicate headers are verboten by the spec.
EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
serialized_headers.size(),
@@ -936,7 +933,7 @@ TEST_P(SpdyFramerTest, MultiValueHeader) {
SpdyFramer framer(spdy_version_);
// Frame builder with plentiful buffer size.
SpdyFrameBuilder frame(1024, spdy_version_);
- if (spdy_version_ <= SPDY3) {
+ if (IsSpdy3()) {
frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
frame.WriteUInt32(3); // stream_id
frame.WriteUInt32(0); // associated stream id
@@ -951,7 +948,11 @@ TEST_P(SpdyFramerTest, MultiValueHeader) {
}
string value("value1\0value2", 13);
- if (spdy_version_ > SPDY3) {
+ 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;
@@ -959,32 +960,29 @@ TEST_P(SpdyFramerTest, MultiValueHeader) {
HpackEncoder encoder(ObtainHpackHuffmanTable());
encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
frame.WriteBytes(&buffer[0], buffer.size());
- } else {
- frame.WriteUInt32(1); // Number of headers.
- frame.WriteStringPiece32("name");
- frame.WriteStringPiece32(value);
}
// write the length
frame.RewriteLength(framer);
framer.set_enable_compression(false);
- scoped_ptr<SpdyFrame> control_frame(frame.take());
+ SpdySerializedFrame control_frame(frame.take());
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = false;
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->size());
+ reinterpret_cast<unsigned char*>(control_frame.data()),
+ control_frame.size());
EXPECT_THAT(visitor.headers_,
testing::ElementsAre(testing::Pair("name", StringPiece(value))));
}
TEST_P(SpdyFramerTest, BasicCompression) {
- if (spdy_version_ > SPDY3) {
+ if (!IsSpdy3()) {
// Deflate compression doesn't apply to HPACK.
return;
}
+
scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
SpdyFramer framer(spdy_version_);
framer.set_debug_visitor(visitor.get());
@@ -996,7 +994,7 @@ TEST_P(SpdyFramerTest, BasicCompression) {
syn_stream.SetHeader("version", "HTTP/1.1");
syn_stream.SetHeader("content-type", "text/html");
syn_stream.SetHeader("content-length", "12");
- scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
+ SpdySerializedFrame frame1(framer.SerializeSynStream(syn_stream));
size_t uncompressed_size1 = visitor->last_payload_len_;
size_t compressed_size1 =
visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
@@ -1006,25 +1004,24 @@ TEST_P(SpdyFramerTest, BasicCompression) {
#else // !defined(USE_SYSTEM_ZLIB)
EXPECT_EQ(117u, compressed_size1);
#endif // !defined(USE_SYSTEM_ZLIB)
- scoped_ptr<SpdyFrame> frame2(framer.SerializeSynStream(syn_stream));
+ 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());
+ EXPECT_LE(frame2.size(), frame1.size());
// Decompress the first frame
- scoped_ptr<SpdyFrame> frame3(
- SpdyFramerTestUtil::DecompressFrame(&framer, *frame1));
+ SpdySerializedFrame frame3(
+ SpdyFramerTestUtil::DecompressFrame(&framer, frame1));
// Decompress the second frame
visitor.reset(new TestSpdyVisitor(spdy_version_));
framer.set_debug_visitor(visitor.get());
- scoped_ptr<SpdyFrame> frame4(
- SpdyFramerTestUtil::DecompressFrame(&framer, *frame2));
- size_t uncompressed_size4 =
- frame4->size() - framer.GetSynStreamMinimumSize();
+ 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);
@@ -1039,14 +1036,13 @@ TEST_P(SpdyFramerTest, BasicCompression) {
EXPECT_EQ(compressed_size2, compressed_size4);
// Expect frames 3 & 4 to be the same.
- CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
+ 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);
- scoped_ptr<SpdyFrame> uncompressed_frame(
- framer.SerializeSynStream(syn_stream));
- CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
+ SpdySerializedFrame uncompressed_frame(framer.SerializeSynStream(syn_stream));
+ CompareFrames("Uncompressed SYN_STREAM", frame3, uncompressed_frame);
}
TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
@@ -1062,12 +1058,12 @@ TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
SpdyFramer framer(spdy_version_);
framer.set_enable_compression(true);
- scoped_ptr<SpdyFrame> frame1(framer.SerializeHeaders(headers));
+ SpdySerializedFrame frame1(framer.SerializeHeaders(headers));
}
TEST_P(SpdyFramerTest, Basic) {
const unsigned char kV3Input[] = {
- 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
+ 0x80, 0x03, 0x00, 0x01, // SYN Stream #1
0x00, 0x00, 0x00, 0x1a,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
@@ -1077,7 +1073,7 @@ TEST_P(SpdyFramerTest, Basic) {
0x00, 0x00, 0x00, 0x02,
'v', 'v',
- 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
+ 0x80, 0x03, 0x00, 0x08, // HEADERS on Stream #1
0x00, 0x00, 0x00, 0x20,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x02,
@@ -1089,90 +1085,90 @@ TEST_P(SpdyFramerTest, Basic) {
0x00, 0x00, 0x00, 0x02,
'v', '3',
- 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
+ 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, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
+ 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, 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, 0x01, // DATA on Stream #1
0x00, 0x00, 0x00, 0x04,
0xde, 0xad, 0xbe, 0xef,
- 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
+ 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, 0x05, // RST_STREAM_CANCEL
- 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
+ 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
0x00, 0x00, 0x00, 0x00,
- 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
+ 0x80, 0x03, 0x00, 0x03, // RST_STREAM on Stream #3
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
+ 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
};
// SYN_STREAM doesn't exist in HTTP/2, so instead we send
// HEADERS frames with PRIORITY and END_HEADERS set.
const unsigned char kH2Input[] = {
- 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
+ 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
0x24, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
- 0x00, 0x82, // :method: GET
+ 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
+ 0x00, 0x82, // :method: GET
- 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
- 0x04, 0x00, 0x00, 0x00, // Stream 1
- 0x01, 0x8c, // :status: 200
+ 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
+ 0x04, 0x00, 0x00, 0x00, // Stream 1
+ 0x01, 0x8c, // :status: 200
- 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
+ 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
0x00, 0x00, 0x00, 0x00,
0x01, 0xde, 0xad, 0xbe,
0xef, 0xde, 0xad, 0xbe,
0xef, 0xde, 0xad, 0xbe,
0xef,
- 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
+ 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
0x24, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
- 0x00, 0x82, // :method: GET
+ 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
+ 0x00, 0x82, // :method: GET
- 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
+ 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
0x00, 0x00, 0x00, 0x00,
0x03, 0xde, 0xad, 0xbe,
0xef, 0xde, 0xad, 0xbe,
0xef,
- 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
+ 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
0x00, 0x00, 0x00, 0x00,
0x01, 0xde, 0xad, 0xbe,
0xef,
- 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
+ 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00,
- 0x08, // RST_STREAM_CANCEL
+ 0x08, // RST_STREAM_CANCEL
- 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
+ 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
0x00, 0x00, 0x00, 0x00,
0x03,
- 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
+ 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
0x00, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
- 0x08, 0x52, 0x45, 0x53, // opaque data
+ 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
+ 0x08, 0x52, 0x45, 0x53, // opaque data
0x45, 0x54, 0x53, 0x54,
0x52, 0x45, 0x41, 0x4d,
};
@@ -1189,19 +1185,19 @@ TEST_P(SpdyFramerTest, Basic) {
EXPECT_EQ(0, visitor.error_count_);
EXPECT_EQ(2, visitor.fin_frame_count_);
- if (IsHttp2()) {
+ 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_);
StringPiece reset_stream = "RESETSTREAM";
EXPECT_EQ(reset_stream, visitor.fin_opaque_data_);
- } else {
- EXPECT_EQ(1, visitor.headers_frame_count_);
- EXPECT_EQ(2, visitor.syn_frame_count_);
- EXPECT_TRUE(visitor.fin_opaque_data_.empty());
}
EXPECT_EQ(0, visitor.fin_flag_count_);
- EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
+ EXPECT_EQ(0, visitor.end_of_stream_count_);
EXPECT_EQ(4, visitor.data_frame_count_);
visitor.fin_opaque_data_.clear();
}
@@ -1209,7 +1205,7 @@ TEST_P(SpdyFramerTest, Basic) {
// Test that the FIN flag on a data frame signifies EOF.
TEST_P(SpdyFramerTest, FinOnDataFrame) {
const unsigned char kV3Input[] = {
- 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
+ 0x80, 0x03, 0x00, 0x01, // SYN Stream #1
0x00, 0x00, 0x00, 0x1a,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
@@ -1219,7 +1215,7 @@ TEST_P(SpdyFramerTest, FinOnDataFrame) {
0x00, 0x00, 0x00, 0x02,
'v', 'v',
- 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
+ 0x80, 0x03, 0x00, 0x02, // SYN REPLY Stream #1
0x00, 0x00, 0x00, 0x14,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01,
@@ -1227,13 +1223,13 @@ TEST_P(SpdyFramerTest, FinOnDataFrame) {
'a', 'a', 0x00, 0x00,
0x00, 0x02, 'b', 'b',
- 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
+ 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
+ 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
0x01, 0x00, 0x00, 0x04,
0xde, 0xad, 0xbe, 0xef,
};
@@ -1241,23 +1237,23 @@ TEST_P(SpdyFramerTest, FinOnDataFrame) {
// SYN_STREAM and SYN_REPLY don't exist in HTTP/2, so instead we send
// HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
const unsigned char kH2Input[] = {
- 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
- 0x24, 0x00, 0x00, 0x00, // Stream 1
- 0x01, 0x00, 0x00, 0x00, // Priority 0
- 0x00, 0x82, // :method: GET
+ 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
+ 0x24, 0x00, 0x00, 0x00, // Stream 1
+ 0x01, 0x00, 0x00, 0x00, // Priority 0
+ 0x00, 0x82, // :method: GET
- 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
- 0x04, 0x00, 0x00, 0x00, // Stream 1
- 0x01, 0x8c, // :status: 200
+ 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
+ 0x04, 0x00, 0x00, 0x00, // Stream 1
+ 0x01, 0x8c, // :status: 200
- 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
+ 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
0x00, 0x00, 0x00, 0x00,
0x01, 0xde, 0xad, 0xbe,
0xef, 0xde, 0xad, 0xbe,
0xef, 0xde, 0xad, 0xbe,
0xef,
- 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
+ 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
0x01, 0x00, 0x00, 0x00,
0x01, 0xde, 0xad, 0xbe,
0xef,
@@ -1271,26 +1267,26 @@ TEST_P(SpdyFramerTest, FinOnDataFrame) {
}
EXPECT_EQ(0, visitor.error_count_);
- if (IsHttp2()) {
- EXPECT_EQ(0, visitor.syn_frame_count_);
- EXPECT_EQ(0, visitor.syn_reply_frame_count_);
- EXPECT_EQ(2, visitor.headers_frame_count_);
- } else {
+ 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(16, visitor.data_bytes_);
EXPECT_EQ(0, visitor.fin_frame_count_);
EXPECT_EQ(0, visitor.fin_flag_count_);
- EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
+ EXPECT_EQ(1, visitor.end_of_stream_count_);
EXPECT_EQ(2, visitor.data_frame_count_);
}
// Test that the FIN flag on a SYN reply frame signifies EOF.
TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
const unsigned char kV3Input[] = {
- 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
+ 0x80, 0x03, 0x00, // SYN Stream #1
0x01, 0x00, 0x00, 0x00,
0x1a, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00,
@@ -1300,27 +1296,26 @@ TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
'h', 0x00, 0x00, 0x00,
0x02, 'v', 'v',
- 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
- 0x02, 0x01, 0x00, 0x00,
- 0x14, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00,
- 0x02, 'a', 'a', 0x00,
- 0x00, 0x00, 0x02, 'b',
- 'b',
+ 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',
};
// SYN_STREAM and SYN_REPLY don't exist in HTTP/2, so instead we send
// HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
const unsigned char kH2Input[] = {
- 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
+ 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
0x24, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
- 0x00, 0x82, // :method: GET
+ 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
+ 0x00, 0x82, // :method: GET
- 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
+ 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
0x05, 0x00, 0x00, 0x00,
- 0x01, 0x8c, // Stream 1, :status: 200
+ 0x01, 0x8c, // Stream 1, :status: 200
};
TestSpdyVisitor visitor(spdy_version_);
@@ -1331,27 +1326,28 @@ TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
}
EXPECT_EQ(0, visitor.error_count_);
- if (IsHttp2()) {
- EXPECT_EQ(0, visitor.syn_frame_count_);
- EXPECT_EQ(0, visitor.syn_reply_frame_count_);
- EXPECT_EQ(2, visitor.headers_frame_count_);
- } else {
+ 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(0, visitor.data_bytes_);
EXPECT_EQ(0, visitor.fin_frame_count_);
EXPECT_EQ(1, visitor.fin_flag_count_);
- EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
+ EXPECT_EQ(1, visitor.end_of_stream_count_);
EXPECT_EQ(0, visitor.data_frame_count_);
}
TEST_P(SpdyFramerTest, HeaderCompression) {
- if (spdy_version_ > SPDY3) {
+ if (!IsSpdy3()) {
// Deflate compression doesn't apply to HPACK.
return;
}
+
SpdyFramer send_framer(spdy_version_);
SpdyFramer recv_framer(spdy_version_);
@@ -1371,27 +1367,20 @@ TEST_P(SpdyFramerTest, HeaderCompression) {
block[kHeader2] = kValue2;
SpdySynStreamIR syn_ir_1(1);
syn_ir_1.set_header_block(block);
- scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
- EXPECT_TRUE(syn_frame_1.get() != NULL);
+ SpdySerializedFrame syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
// SYN_STREAM #2
block[kHeader3] = kValue3;
SpdySynStreamIR syn_stream(3);
syn_stream.set_header_block(block);
- scoped_ptr<SpdyFrame> syn_frame_2(send_framer.SerializeSynStream(syn_stream));
- EXPECT_TRUE(syn_frame_2.get() != NULL);
-
- // Now start decompressing
- scoped_ptr<SpdyFrame> decompressed;
- scoped_ptr<SpdyFrame> uncompressed;
- StringPiece serialized_headers;
- SpdyHeaderBlock decompressed_headers;
+ SpdySerializedFrame syn_frame_2(send_framer.SerializeSynStream(syn_stream));
// Decompress SYN_STREAM #1
- decompressed.reset(
- SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_1));
- EXPECT_TRUE(decompressed.get() != NULL);
- serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
+ 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));
@@ -1400,10 +1389,8 @@ TEST_P(SpdyFramerTest, HeaderCompression) {
EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
// Decompress SYN_STREAM #2
- decompressed.reset(
- SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_2));
- EXPECT_TRUE(decompressed.get() != NULL);
- serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
+ 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(),
@@ -1429,26 +1416,24 @@ TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
SpdyHeadersIR headers(1);
headers.SetHeader(kHeader1, kValue1);
headers.SetHeader(kHeader2, kValue2);
- scoped_ptr<SpdyFrame> headers_frame(send_framer.SerializeHeaders(headers));
- EXPECT_TRUE(headers_frame.get() != NULL);
+ SpdySerializedFrame headers_frame(send_framer.SerializeHeaders(headers));
const char bytes[] = "this is a test test test test test!";
SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes)));
data_ir.set_fin(true);
- scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
- EXPECT_TRUE(send_frame.get() != NULL);
+ SpdySerializedFrame send_frame(send_framer.SerializeData(data_ir));
// Run the inputs through the framer.
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = true;
const unsigned char* data;
- data = reinterpret_cast<const unsigned char*>(headers_frame->data());
- for (size_t idx = 0; idx < headers_frame->size(); ++idx) {
+ data = reinterpret_cast<const unsigned char*>(headers_frame.data());
+ for (size_t idx = 0; idx < headers_frame.size(); ++idx) {
visitor.SimulateInFramer(data + idx, 1);
ASSERT_EQ(0, visitor.error_count_);
}
- data = reinterpret_cast<const unsigned char*>(send_frame->data());
- for (size_t idx = 0; idx < send_frame->size(); ++idx) {
+ data = reinterpret_cast<const unsigned char*>(send_frame.data());
+ for (size_t idx = 0; idx < send_frame.size(); ++idx) {
visitor.SimulateInFramer(data + idx, 1);
ASSERT_EQ(0, visitor.error_count_);
}
@@ -1460,18 +1445,18 @@ TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
EXPECT_EQ(0, visitor.fin_frame_count_);
EXPECT_EQ(0, visitor.fin_flag_count_);
- EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
+ EXPECT_EQ(1, visitor.end_of_stream_count_);
EXPECT_EQ(1, visitor.data_frame_count_);
}
TEST_P(SpdyFramerTest, WindowUpdateFrame) {
SpdyFramer framer(spdy_version_);
- scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
- SpdyWindowUpdateIR(1, 0x12345678)));
+ SpdySerializedFrame frame(
+ framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 0x12345678)));
const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x09,
+ 0x80, 0x03, 0x00, 0x09,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x01,
0x12, 0x34, 0x56, 0x78
@@ -1483,10 +1468,10 @@ TEST_P(SpdyFramerTest, WindowUpdateFrame) {
0x78
};
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -1518,22 +1503,21 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
const char bytes[] = "hello";
SpdyDataIR data_ir(1, bytes);
- scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(framer.SerializeData(data_ir));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(
- kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
SpdyDataIR data_header_ir(1);
data_header_ir.SetDataShallow(bytes);
- frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(
- data_header_ir));
+ frame =
+ framer.SerializeDataFrameHeaderWithPaddingLengthField(data_header_ir);
CompareCharArraysWithHexError(
- kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
+ kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
framer.GetDataFrameMinimumSize(),
- IsHttp2() ? kH2FrameData : kV3FrameData,
+ IsSpdy3() ? kV3FrameData : kH2FrameData,
framer.GetDataFrameMinimumSize());
}
@@ -1547,10 +1531,10 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
};
const unsigned char kH2FrameData[] = {
- 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
+ 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
0x08, 0x00, 0x00, 0x00,
- 0x01, 0xf7, // Pad length field.
- 'h', 'e', 'l', 'l', // Data
+ 0x01, 0xf7, // Pad length field.
+ 'h', 'e', 'l', 'l', // Data
'o',
// Padding of 247 0x00(s).
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1581,19 +1565,18 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
// 247 zeros and the pad length field make the overall padding to be 248
// bytes.
data_ir.set_padding_len(248);
- scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(framer.SerializeData(data_ir));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(
- kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
- frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
+ frame = framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
CompareCharArraysWithHexError(
- kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
+ kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
framer.GetDataFrameMinimumSize(),
- IsHttp2() ? kH2FrameData : kV3FrameData,
+ IsSpdy3() ? kV3FrameData : kH2FrameData,
framer.GetDataFrameMinimumSize());
}
@@ -1607,9 +1590,9 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
};
const unsigned char kH2FrameData[] = {
- 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
+ 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
0x08, 0x00, 0x00, 0x00,
- 0x01, 0x07, // Pad length field.
+ 0x01, 0x07, // Pad length field.
'h', 'e', 'l', 'l', // Data
'o',
0x00, 0x00, 0x00, 0x00, // Padding
@@ -1620,12 +1603,11 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
SpdyDataIR data_ir(1, bytes);
// 7 zeros and the pad length field make the overall padding to be 8 bytes.
data_ir.set_padding_len(8);
- scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(framer.SerializeData(data_ir));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(
- kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -1640,9 +1622,9 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
};
const unsigned char kH2FrameData[] = {
- 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
+ 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
0x08, 0x00, 0x00, 0x00,
- 0x01, 0x00, // Pad length field.
+ 0x01, 0x00, // Pad length field.
'h', 'e', 'l', 'l', // Data
'o',
};
@@ -1652,19 +1634,18 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
// The pad length field itself is used for the 1-byte padding and no padding
// payload is needed.
data_ir.set_padding_len(1);
- scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(framer.SerializeData(data_ir));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(
- kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
- frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
+ frame = framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
CompareCharArraysWithHexError(
- kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
+ kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
framer.GetDataFrameMinimumSize(),
- IsHttp2() ? kH2FrameData : kV3FrameData,
+ IsSpdy3() ? kV3FrameData : kH2FrameData,
framer.GetDataFrameMinimumSize());
}
@@ -1678,12 +1659,11 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff};
SpdyDataIR data_ir(1, "\xff");
- scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(framer.SerializeData(data_ir));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(
- kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -1703,12 +1683,11 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
};
SpdyDataIR data_ir(1, "hello");
data_ir.set_fin(true);
- scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(framer.SerializeData(data_ir));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(
- kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -1723,19 +1702,18 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
0x01,
};
SpdyDataIR data_ir(1, "");
- scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(framer.SerializeData(data_ir));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(
- kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
- frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
+ frame = framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
CompareCharArraysWithHexError(
- kDescription, reinterpret_cast<const unsigned char*>(frame->data()),
+ kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
framer.GetDataFrameMinimumSize(),
- IsHttp2() ? kH2FrameData : kV3FrameData,
+ IsSpdy3() ? kV3FrameData : kH2FrameData,
framer.GetDataFrameMinimumSize());
}
@@ -1755,12 +1733,11 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
};
SpdyDataIR data_ir(0x7fffffff, "hello");
data_ir.set_fin(true);
- scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(framer.SerializeData(data_ir));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(
- kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -1783,16 +1760,16 @@ TEST_P(SpdyFramerTest, CreateDataFrame) {
SpdyDataIR data_ir(1, kData);
data_ir.set_fin(true);
- scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
- CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
+ SpdySerializedFrame frame(framer.SerializeData(data_ir));
+ CompareFrame(kDescription, frame, expected_frame_data.get(), kFrameSize);
}
}
TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
if (!IsSpdy3()) {
- // SYN_STREAM unsupported in SPDY>3
return;
}
+
SpdyFramer framer(spdy_version_);
framer.set_enable_compression(false);
@@ -1800,7 +1777,7 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x01,
+ 0x80, 0x03, 0x00, 0x01,
0x00, 0x00, 0x00, 0x2a,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
@@ -1818,9 +1795,9 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
syn_stream.set_priority(framer.GetLowestPriority());
syn_stream.SetHeader("bar", "foo");
syn_stream.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
+ SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
LOG(FATAL) << "Unsupported version in test.";
}
@@ -1832,7 +1809,7 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
"max stream ID";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x01,
+ 0x80, 0x03, 0x00, 0x01,
0x01, 0x00, 0x00, 0x27,
0x7f, 0xff, 0xff, 0xff,
0x7f, 0xff, 0xff, 0xff,
@@ -1851,9 +1828,9 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
syn_stream.set_fin(true);
syn_stream.SetHeader("", "foo");
syn_stream.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
+ SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
LOG(FATAL) << "Unsupported version in test.";
}
@@ -1865,7 +1842,7 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
"max stream ID";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x01,
+ 0x80, 0x03, 0x00, 0x01,
0x01, 0x00, 0x00, 0x27,
0x7f, 0xff, 0xff, 0xff,
0x7f, 0xff, 0xff, 0xff,
@@ -1884,9 +1861,9 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
syn_stream.set_fin(true);
syn_stream.SetHeader("bar", "foo");
syn_stream.SetHeader("foo", "");
- scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
+ SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
LOG(FATAL) << "Unsupported version in test.";
}
@@ -1898,9 +1875,9 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
#if !defined(USE_SYSTEM_ZLIB)
TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
if (!IsSpdy3()) {
- // SYN_STREAM not supported for SPDY>3
return;
}
+
SpdyFramer framer(spdy_version_);
framer.set_enable_compression(true);
@@ -1909,7 +1886,7 @@ TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
"SYN_STREAM frame, low pri, no FIN";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x01,
+ 0x80, 0x03, 0x00, 0x01,
0x00, 0x00, 0x00, 0x37,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
@@ -1927,7 +1904,7 @@ TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
0x00, 0xFF, 0xFF,
};
const unsigned char kV3SIMDFrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x01,
+ 0x80, 0x03, 0x00, 0x01,
0x00, 0x00, 0x00, 0x32,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
@@ -1948,18 +1925,14 @@ TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
syn_stream.set_priority(4);
syn_stream.SetHeader("bar", "foo");
syn_stream.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
+ SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
const unsigned char* frame_data =
- reinterpret_cast<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));
+ 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.";
@@ -1969,10 +1942,10 @@ TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
#endif // !defined(USE_SYSTEM_ZLIB)
TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
- if (spdy_version_ > SPDY3) {
- // SYN_REPLY unsupported in SPDY>3
+ if (!IsSpdy3()) {
return;
}
+
SpdyFramer framer(spdy_version_);
framer.set_enable_compression(false);
@@ -1980,7 +1953,7 @@ TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
const char kDescription[] = "SYN_REPLY frame, no FIN";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x02,
+ 0x80, 0x03, 0x00, 0x02,
0x00, 0x00, 0x00, 0x24,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x02,
@@ -1995,9 +1968,9 @@ TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
SpdySynReplyIR syn_reply(1);
syn_reply.SetHeader("bar", "foo");
syn_reply.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
+ SpdySerializedFrame frame(framer.SerializeSynReply(syn_reply));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
LOG(FATAL) << "Unsupported version in test.";
}
@@ -2008,7 +1981,7 @@ TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
"SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x02,
+ 0x80, 0x03, 0x00, 0x02,
0x01, 0x00, 0x00, 0x21,
0x7f, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x02,
@@ -2024,9 +1997,9 @@ TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
syn_reply.set_fin(true);
syn_reply.SetHeader("", "foo");
syn_reply.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
+ SpdySerializedFrame frame(framer.SerializeSynReply(syn_reply));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
LOG(FATAL) << "Unsupported version in test.";
}
@@ -2037,7 +2010,7 @@ TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
"SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x02,
+ 0x80, 0x03, 0x00, 0x02,
0x01, 0x00, 0x00, 0x21,
0x7f, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x02,
@@ -2053,9 +2026,9 @@ TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
syn_reply.set_fin(true);
syn_reply.SetHeader("bar", "foo");
syn_reply.SetHeader("foo", "");
- scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
+ SpdySerializedFrame frame(framer.SerializeSynReply(syn_reply));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
LOG(FATAL) << "Unsupported version in test.";
}
@@ -2066,10 +2039,10 @@ TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
// to workaround http://crbug.com/139744.
#if !defined(USE_SYSTEM_ZLIB)
TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
- if (spdy_version_ > SPDY3) {
- // SYN_REPLY unsupported in SPDY>3
+ if (!IsSpdy3()) {
return;
}
+
SpdyFramer framer(spdy_version_);
framer.set_enable_compression(true);
@@ -2077,7 +2050,7 @@ TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
const char kDescription[] = "SYN_REPLY frame, no FIN";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x02,
+ 0x80, 0x03, 0x00, 0x02,
0x00, 0x00, 0x00, 0x31,
0x00, 0x00, 0x00, 0x01,
0x38, 0xea, 0xe3, 0xc6,
@@ -2094,7 +2067,7 @@ TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
0xff,
};
const unsigned char kV3SIMDFrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x02,
+ 0x80, 0x03, 0x00, 0x02,
0x00, 0x00, 0x00, 0x2c,
0x00, 0x00, 0x00, 0x01,
0x38, 0xea, 0xe3, 0xc6,
@@ -2112,18 +2085,14 @@ TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
SpdySynReplyIR syn_reply(1);
syn_reply.SetHeader("bar", "foo");
syn_reply.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
+ SpdySerializedFrame frame(framer.SerializeSynReply(syn_reply));
const unsigned char* frame_data =
- reinterpret_cast<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));
+ 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.";
@@ -2138,7 +2107,7 @@ TEST_P(SpdyFramerTest, CreateRstStream) {
{
const char kDescription[] = "RST_STREAM frame";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x03,
+ 0x80, 0x03, 0x00, 0x03,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01,
@@ -2148,18 +2117,18 @@ TEST_P(SpdyFramerTest, CreateRstStream) {
0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
};
SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR);
- scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
{
const char kDescription[] = "RST_STREAM frame with max stream ID";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x03,
+ 0x80, 0x03, 0x00, 0x03,
0x00, 0x00, 0x00, 0x08,
0x7f, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x01,
@@ -2171,18 +2140,18 @@ TEST_P(SpdyFramerTest, CreateRstStream) {
0x01,
};
SpdyRstStreamIR rst_stream(0x7FFFFFFF, RST_STREAM_PROTOCOL_ERROR);
- scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
{
const char kDescription[] = "RST_STREAM frame with max status code";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x03,
+ 0x80, 0x03, 0x00, 0x03,
0x00, 0x00, 0x00, 0x08,
0x7f, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x06,
@@ -2194,11 +2163,11 @@ TEST_P(SpdyFramerTest, CreateRstStream) {
0x02,
};
SpdyRstStreamIR rst_stream(0x7FFFFFFF, RST_STREAM_INTERNAL_ERROR);
- scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
}
@@ -2210,7 +2179,7 @@ TEST_P(SpdyFramerTest, CreateSettings) {
const char kDescription[] = "Network byte order SETTINGS frame";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x04,
+ 0x80, 0x03, 0x00, 0x04,
0x00, 0x00, 0x00, 0x0c,
0x00, 0x00, 0x00, 0x01,
0x01, 0x00, 0x00, 0x07,
@@ -2233,11 +2202,11 @@ TEST_P(SpdyFramerTest, CreateSettings) {
kFlags & SETTINGS_FLAG_PERSISTED,
kValue);
- scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
+ SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -2245,7 +2214,7 @@ TEST_P(SpdyFramerTest, CreateSettings) {
const char kDescription[] = "Basic SETTINGS frame";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x04,
+ 0x80, 0x03, 0x00, 0x04,
0x00, 0x00, 0x00, 0x24,
0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x01, // 1st Setting
@@ -2290,12 +2259,12 @@ TEST_P(SpdyFramerTest, CreateSettings) {
false, // persist
false, // persisted
8);
- scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
+ SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -2303,7 +2272,7 @@ TEST_P(SpdyFramerTest, CreateSettings) {
const char kDescription[] = "Empty SETTINGS frame";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x04,
+ 0x80, 0x03, 0x00, 0x04,
0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00,
};
@@ -2313,11 +2282,11 @@ TEST_P(SpdyFramerTest, CreateSettings) {
0x00,
};
SpdySettingsIR settings_ir;
- scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
}
@@ -2328,7 +2297,7 @@ TEST_P(SpdyFramerTest, CreatePingFrame) {
{
const char kDescription[] = "PING frame";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x06,
+ 0x80, 0x03, 0x00, 0x06,
0x00, 0x00, 0x00, 0x04,
0x12, 0x34, 0x56, 0x78,
};
@@ -2346,24 +2315,23 @@ TEST_P(SpdyFramerTest, CreatePingFrame) {
0x78, 0x9a, 0xbc, 0xde,
0xff,
};
- scoped_ptr<SpdyFrame> frame;
- if (IsHttp2()) {
+ 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.reset(framer.SerializePing(ping_ir));
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ 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.reset(framer.SerializePing(ping_ir));
- CompareFrame(kDescription, *frame, kH2FrameDataWithAck,
+ frame = framer.SerializePing(ping_ir);
+ CompareFrame(kDescription, frame, kH2FrameDataWithAck,
arraysize(kH2FrameDataWithAck));
-
- } else {
- frame.reset(framer.SerializePing(SpdyPingIR(0x12345678ull)));
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
}
}
}
@@ -2374,7 +2342,7 @@ TEST_P(SpdyFramerTest, CreateGoAway) {
{
const char kDescription[] = "GOAWAY frame";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x07,
+ 0x80, 0x03, 0x00, 0x07,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x00, // Stream Id
0x00, 0x00, 0x00, 0x00, // Status
@@ -2387,18 +2355,18 @@ TEST_P(SpdyFramerTest, CreateGoAway) {
0x00, 0x47, 0x41, // Opaque Description
};
SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
- scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
+ SpdySerializedFrame frame(framer.SerializeGoAway(goaway_ir));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ 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";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x07,
+ 0x80, 0x03, 0x00, 0x07,
0x00, 0x00, 0x00, 0x08,
0x7f, 0xff, 0xff, 0xff, // Stream Id
0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
@@ -2411,11 +2379,11 @@ TEST_P(SpdyFramerTest, CreateGoAway) {
0x02, 0x47, 0x41, // Opaque Description
};
SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
- scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
+ SpdySerializedFrame frame(framer.SerializeGoAway(goaway_ir));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
}
@@ -2428,7 +2396,7 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
const char kDescription[] = "HEADERS frame, no FIN";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x08,
+ 0x80, 0x03, 0x00, 0x08,
0x00, 0x00, 0x00, 0x24,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x02,
@@ -2452,11 +2420,11 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
SpdyHeadersIR headers_ir(1);
headers_ir.SetHeader("bar", "foo");
headers_ir.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers_ir));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -2465,7 +2433,7 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
"HEADERS frame with a 0-length header name, FIN, max stream ID";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x08,
+ 0x80, 0x03, 0x00, 0x08,
0x01, 0x00, 0x00, 0x21,
0x7f, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x02,
@@ -2489,11 +2457,11 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers_ir.set_fin(true);
headers_ir.SetHeader("", "foo");
headers_ir.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers_ir));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -2502,7 +2470,7 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
"HEADERS frame with a 0-length header val, FIN, max stream ID";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x08,
+ 0x80, 0x03, 0x00, 0x08,
0x01, 0x00, 0x00, 0x21,
0x7f, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x02,
@@ -2526,11 +2494,11 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers_ir.set_fin(true);
headers_ir.SetHeader("bar", "foo");
headers_ir.SetHeader("foo", "");
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers_ir));
if (IsSpdy3()) {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -2554,11 +2522,11 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers_ir.set_has_priority(true);
headers_ir.SetHeader("bar", "foo");
headers_ir.SetHeader("foo", "");
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers_ir));
if (IsSpdy3()) {
// HEADERS with priority not supported.
} else {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -2585,11 +2553,11 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers_ir.set_parent_stream_id(0);
headers_ir.SetHeader("bar", "foo");
headers_ir.SetHeader("foo", "");
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers_ir));
if (IsSpdy3()) {
// HEADERS with priority not supported.
} else {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -2616,11 +2584,11 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers_ir.set_parent_stream_id(0x7fffffff);
headers_ir.SetHeader("bar", "foo");
headers_ir.SetHeader("foo", "");
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers_ir));
if (IsSpdy3()) {
// HEADERS with priority not supported.
} else {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
@@ -2645,11 +2613,11 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
headers_ir.SetHeader("", "foo");
headers_ir.SetHeader("foo", "bar");
headers_ir.set_padding_len(6);
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers_ir));
if (IsSpdy3()) {
// Padding is not supported.
} else {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
}
@@ -2665,7 +2633,7 @@ TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
const char kDescription[] = "HEADERS frame, no FIN";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x08,
+ 0x80, 0x03, 0x00, 0x08,
0x00, 0x00, 0x00, 0x31,
0x00, 0x00, 0x00, 0x01,
0x38, 0xea, 0xe3, 0xc6,
@@ -2682,7 +2650,7 @@ TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
0xff,
};
const unsigned char kV3SIMDFrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x08,
+ 0x80, 0x03, 0x00, 0x08,
0x00, 0x00, 0x00, 0x2c,
0x00, 0x00, 0x00, 0x01,
0x38, 0xea, 0xe3, 0xc6,
@@ -2700,18 +2668,14 @@ TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
SpdyHeadersIR headers_ir(1);
headers_ir.SetHeader("bar", "foo");
headers_ir.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
+ SpdySerializedFrame frame(framer.SerializeHeaders(headers_ir));
const unsigned char* frame_data =
- reinterpret_cast<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));
+ 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.
@@ -2726,7 +2690,7 @@ TEST_P(SpdyFramerTest, CreateWindowUpdate) {
{
const char kDescription[] = "WINDOW_UPDATE frame";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x09,
+ 0x80, 0x03, 0x00, 0x09,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01,
@@ -2737,19 +2701,19 @@ TEST_P(SpdyFramerTest, CreateWindowUpdate) {
0x01, 0x00, 0x00, 0x00,
0x01,
};
- scoped_ptr<SpdyFrame> frame(
+ SpdySerializedFrame frame(
framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
{
const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x09,
+ 0x80, 0x03, 0x00, 0x09,
0x00, 0x00, 0x00, 0x08,
0x7f, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x01,
@@ -2760,19 +2724,19 @@ TEST_P(SpdyFramerTest, CreateWindowUpdate) {
0xff, 0x00, 0x00, 0x00,
0x01,
};
- scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
- SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(
+ framer.SerializeWindowUpdate(SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
{
const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x09,
+ 0x80, 0x03, 0x00, 0x09,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x01,
0x7f, 0xff, 0xff, 0xff,
@@ -2783,18 +2747,18 @@ TEST_P(SpdyFramerTest, CreateWindowUpdate) {
0x01, 0x7f, 0xff, 0xff,
0xff,
};
- scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
- SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
- if (IsHttp2()) {
- CompareFrame(kDescription, *frame, kH2FrameData, arraysize(kH2FrameData));
+ SpdySerializedFrame frame(
+ framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
+ if (IsSpdy3()) {
+ CompareFrame(kDescription, frame, kV3FrameData, arraysize(kV3FrameData));
} else {
- CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
}
}
}
TEST_P(SpdyFramerTest, SerializeBlocked) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -2808,12 +2772,12 @@ TEST_P(SpdyFramerTest, SerializeBlocked) {
0x00, 0x00, 0x00, 0x00,
};
SpdyBlockedIR blocked_ir(0);
- scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
+ SpdySerializedFrame frame(framer.SerializeFrame(blocked_ir));
+ CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
}
TEST_P(SpdyFramerTest, CreateBlocked) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -2822,17 +2786,16 @@ TEST_P(SpdyFramerTest, CreateBlocked) {
const char kDescription[] = "BLOCKED frame";
const SpdyStreamId kStreamId = 3;
- scoped_ptr<SpdySerializedFrame> frame_serialized(
+ SpdySerializedFrame frame_serialized(
framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
SpdyBlockedIR blocked_ir(kStreamId);
- scoped_ptr<SpdySerializedFrame> frame_created(
- framer.SerializeFrame(blocked_ir));
+ SpdySerializedFrame frame_created(framer.SerializeFrame(blocked_ir));
- CompareFrames(kDescription, *frame_serialized, *frame_created);
+ CompareFrames(kDescription, frame_serialized, frame_created);
}
TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -2856,9 +2819,8 @@ TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
SpdyPushPromiseIR push_promise(42, 57);
push_promise.SetHeader("bar", "foo");
push_promise.SetHeader("foo", "bar");
- scoped_ptr<SpdySerializedFrame> frame(
- framer.SerializePushPromise(push_promise));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
+ SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
+ CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
}
{
@@ -2882,9 +2844,8 @@ TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
push_promise.set_padding_len(1);
push_promise.SetHeader("bar", "foo");
push_promise.SetHeader("foo", "bar");
- scoped_ptr<SpdySerializedFrame> frame(
- framer.SerializePushPromise(push_promise));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
+ SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
+ CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
}
{
@@ -2924,27 +2885,30 @@ TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
push_promise.set_padding_len(177);
push_promise.SetHeader("bar", "foo");
push_promise.SetHeader("foo", "bar");
- scoped_ptr<SpdySerializedFrame> frame(
- framer.SerializePushPromise(push_promise));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
+ SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
+ CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
}
}
+// Regression test for https://crbug.com/464748.
TEST_P(SpdyFramerTest, GetNumberRequiredContinuationFrames) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
SpdyFramer framer(spdy_version_);
- // Test case from https://crbug.com/464748.
- EXPECT_EQ(1u,
- SpdyFramerPeer::GetNumberRequiredContinuationFrames(&framer, 2039));
- EXPECT_EQ(2u,
- SpdyFramerPeer::GetNumberRequiredContinuationFrames(&framer, 2040));
+ EXPECT_EQ(1u, SpdyFramerPeer::GetNumberRequiredContinuationFrames(
+ &framer, 16383 + 16374));
+ EXPECT_EQ(2u, SpdyFramerPeer::GetNumberRequiredContinuationFrames(
+ &framer, 16383 + 16374 + 1));
+ EXPECT_EQ(2u, SpdyFramerPeer::GetNumberRequiredContinuationFrames(
+ &framer, 16383 + 2 * 16374));
+ EXPECT_EQ(3u, SpdyFramerPeer::GetNumberRequiredContinuationFrames(
+ &framer, 16383 + 2 * 16374 + 1));
}
TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -2966,13 +2930,12 @@ TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
continuation.SetHeader("bar", "foo");
continuation.SetHeader("foo", "bar");
continuation.set_end_headers(true);
- scoped_ptr<SpdySerializedFrame> frame(
- framer.SerializeContinuation(continuation));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
+ SpdySerializedFrame frame(framer.SerializeContinuation(continuation));
+ CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
}
TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -2986,12 +2949,12 @@ TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
"PUSH_PROMISE and CONTINUATION frames with one byte of padding";
const unsigned char kPartialPushPromiseFrameData[] = {
- 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
+ 0x00, 0x3f, 0xf6, 0x05, // PUSH_PROMISE
0x08, 0x00, 0x00, 0x00, // PADDED
0x2a, 0x00, 0x00, 0x00, // Stream 42
0x00, 0x39, 0x00, 0x03, // Promised stream 57
0x78, 0x78, 0x78, 0x7f, // xxx.
- 0x81, 0x07, 0x78, 0x78, // ..xx
+ 0x80, 0x7f, 0x78, 0x78, // ..xx
0x78, 0x78, 0x78, 0x78, // xxxx
0x78, 0x78, 0x78, 0x78, // xxxx
0x78, 0x78, 0x78, 0x78, // xxxx
@@ -3030,8 +2993,7 @@ TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
push_promise.set_padding_len(1);
string big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
push_promise.SetHeader("xxx", big_value);
- scoped_ptr<SpdySerializedFrame> frame(
- framer.SerializePushPromise(push_promise));
+ SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
// The entire frame should look like below:
// Name Length in Byte
@@ -3052,11 +3014,11 @@ TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
int len_non_data_payload = 31;
EXPECT_EQ(
TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload,
- frame->size());
+ frame.size());
// Partially compare the PUSH_PROMISE frame against the template.
const unsigned char* frame_data =
- reinterpret_cast<const unsigned char*>(frame->data());
+ reinterpret_cast<const unsigned char*>(frame.data());
CompareCharArraysWithHexError(kDescription,
frame_data,
arraysize(kPartialPushPromiseFrameData),
@@ -3074,7 +3036,7 @@ TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
}
TEST_P(SpdyFramerTest, CreateAltSvc) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -3099,12 +3061,12 @@ TEST_P(SpdyFramerTest, CreateAltSvc) {
altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
"p\"=i:d", "h_\\o\"st", 123, 42, 0.2,
SpdyAltSvcWireFormat::VersionVector{24}));
- scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
+ SpdySerializedFrame frame(framer.SerializeFrame(altsvc_ir));
+ CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
}
TEST_P(SpdyFramerTest, CreatePriority) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -3116,65 +3078,59 @@ TEST_P(SpdyFramerTest, CreatePriority) {
const unsigned char kFrameData[] = {
0x00, 0x00, 0x05, kType, 0x00,
0x00, 0x00, 0x00, 0x02, // Stream ID = 2
- 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
- 0x10, // Weight = 16
+ 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
+ 0x10, // Weight = 16
};
SpdyPriorityIR priority_ir(2, 1, 16, true);
- scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(priority_ir));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
+ SpdySerializedFrame frame(framer.SerializeFrame(priority_ir));
+ CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
SpdyPriorityIR priority2(2);
priority2.set_parent_stream_id(1);
priority2.set_weight(16);
priority2.set_exclusive(true);
- frame.reset(framer.SerializeFrame(priority2));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
+ frame = framer.SerializeFrame(priority2);
+ CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
}
TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
- if (spdy_version_ > SPDY3) {
- // SYN_STREAM not supported in SPDY>3
+ 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");
SpdyHeaderBlock headers = syn_stream.header_block();
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
- EXPECT_TRUE(control_frame.get() != NULL);
+ 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());
+ reinterpret_cast<unsigned char*>(control_frame.data()),
+ control_frame.size());
EXPECT_EQ(1, visitor.syn_frame_count_);
EXPECT_EQ(headers, visitor.headers_);
}
TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
- if (spdy_version_ > SPDY3) {
+ if (!IsSpdy3()) {
return;
}
+
SpdyFramer framer(spdy_version_);
SpdySynReplyIR syn_reply(1);
syn_reply.SetHeader("alpha", "beta");
syn_reply.SetHeader("gamma", "delta");
SpdyHeaderBlock headers = syn_reply.header_block();
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
- EXPECT_TRUE(control_frame.get() != NULL);
+ 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());
- if (IsHttp2()) {
- EXPECT_EQ(0, visitor.syn_reply_frame_count_);
- EXPECT_EQ(1, visitor.headers_frame_count_);
- } else {
- EXPECT_EQ(1, visitor.syn_reply_frame_count_);
- EXPECT_EQ(0, visitor.headers_frame_count_);
- }
+ 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(headers, visitor.headers_);
}
@@ -3184,13 +3140,12 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
headers_ir.SetHeader("alpha", "beta");
headers_ir.SetHeader("gamma", "delta");
SpdyHeaderBlock headers = headers_ir.header_block();
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
- EXPECT_TRUE(control_frame.get() != NULL);
+ SpdySerializedFrame control_frame(framer.SerializeHeaders(headers_ir));
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = true;
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->size());
+ reinterpret_cast<unsigned char*>(control_frame.data()),
+ control_frame.size());
EXPECT_EQ(1, visitor.headers_frame_count_);
// control_frame_header_data_count_ depends on the random sequence
// produced by rand(), so adding, removing or running single tests
@@ -3198,7 +3153,7 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
// at least twice.
EXPECT_LE(2, visitor.control_frame_header_data_count_);
EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
- EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
+ EXPECT_EQ(0, visitor.end_of_stream_count_);
EXPECT_EQ(headers, visitor.headers_);
}
@@ -3209,13 +3164,12 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
headers_ir.SetHeader("alpha", "beta");
headers_ir.SetHeader("gamma", "delta");
SpdyHeaderBlock headers = headers_ir.header_block();
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
- EXPECT_TRUE(control_frame.get() != NULL);
+ SpdySerializedFrame control_frame(framer.SerializeHeaders(headers_ir));
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = true;
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->size());
+ reinterpret_cast<unsigned char*>(control_frame.data()),
+ control_frame.size());
EXPECT_EQ(1, visitor.headers_frame_count_);
// control_frame_header_data_count_ depends on the random sequence
// produced by rand(), so adding, removing or running single tests
@@ -3223,15 +3177,16 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
// at least twice.
EXPECT_LE(2, visitor.control_frame_header_data_count_);
EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
- EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
+ EXPECT_EQ(1, visitor.end_of_stream_count_);
EXPECT_EQ(headers, visitor.headers_);
}
TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
- if (spdy_version_ > SPDY3) {
+ 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_);
@@ -3239,40 +3194,35 @@ TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
SpdySynStreamIR syn_stream(1);
syn_stream.set_priority(1);
syn_stream.SetHeader("aa", "");
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
+ SpdySerializedFrame control_frame(framer.SerializeSynStream(syn_stream));
const size_t kBigValueSize =
- TestSpdyVisitor::sent_control_frame_max_size() - control_frame->size();
+ 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.reset(framer.SerializeSynStream(syn_stream));
- EXPECT_TRUE(control_frame.get() != NULL);
+ control_frame = framer.SerializeSynStream(syn_stream);
EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
- control_frame->size());
+ control_frame.size());
TestSpdyVisitor visitor(spdy_version_);
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->size());
+ 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(1, visitor.zero_length_control_frame_header_data_count_);
- EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
+ EXPECT_EQ(0, visitor.end_of_stream_count_);
EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
}
TEST_P(SpdyFramerTest, ControlFrameMaximumSize) {
- if (spdy_version_ > SPDY3) {
+ if (!IsSpdy3()) {
// TODO(jgraettinger): This test setup doesn't work with HPACK.
return;
}
- if (spdy_version_ < SPDY3) {
- // Since SPDY/2 uses 16 bit header field lengths, one cannot easily create a
- // header frame of maximum size.
- return;
- }
+
// First find the size of the header value in order to just reach the control
// frame max size.
SpdyFramer framer(spdy_version_);
@@ -3280,9 +3230,9 @@ TEST_P(SpdyFramerTest, ControlFrameMaximumSize) {
SpdySynStreamIR syn_stream(1);
syn_stream.SetHeader("aa", "");
syn_stream.set_priority(1);
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
+ SpdySerializedFrame control_frame(framer.SerializeSynStream(syn_stream));
const size_t kBigValueSize =
- SpdyConstants::GetFrameMaximumSize(spdy_version_) - control_frame->size();
+ SpdyConstants::GetFrameMaximumSize(spdy_version_) - control_frame.size();
// Create a frame at exatly that size.
string big_value(kBigValueSize, 'x');
@@ -3290,25 +3240,25 @@ TEST_P(SpdyFramerTest, ControlFrameMaximumSize) {
// Upstream branches here and wraps HTTP/2 with EXPECT_DEBUG_DFATAL. We
// neither support that in Chromium, nor do we use the same DFATAL (see
// SpdyFrameBuilder::WriteFramePrefix()).
- control_frame.reset(framer.SerializeSynStream(syn_stream));
+ control_frame = framer.SerializeSynStream(syn_stream);
- EXPECT_TRUE(control_frame.get() != NULL);
EXPECT_EQ(SpdyConstants::GetFrameMaximumSize(spdy_version_),
- control_frame->size());
+ control_frame.size());
TestSpdyVisitor visitor(spdy_version_);
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->size());
+ 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_);
}
TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
+
SpdyFramer framer(spdy_version_);
framer.set_enable_compression(false);
SpdyHeadersIR headers(1);
@@ -3316,29 +3266,29 @@ TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
// Exact payload length will change with HPACK, but this should be long
// enough to cause an overflow.
- const size_t kBigValueSize = kControlFrameSizeLimit;
+ const size_t kBigValueSize = TestSpdyVisitor::sent_control_frame_max_size();
string big_value(kBigValueSize, 'x');
headers.SetHeader("aa", big_value);
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
- EXPECT_TRUE(control_frame.get() != NULL);
- EXPECT_GT(control_frame->size(),
+ SpdySerializedFrame control_frame(framer.SerializeHeaders(headers));
+ EXPECT_GT(control_frame.size(),
TestSpdyVisitor::sent_control_frame_max_size());
TestSpdyVisitor visitor(spdy_version_);
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->size());
+ 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.headers_frame_count_);
- EXPECT_EQ(16, visitor.continuation_count_);
+ EXPECT_EQ(1, visitor.continuation_count_);
EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
}
TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
+
SpdyFramer framer(spdy_version_);
framer.set_enable_compression(false);
SpdyPushPromiseIR push_promise(1, 2);
@@ -3346,23 +3296,21 @@ TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
// Exact payload length will change with HPACK, but this should be long
// enough to cause an overflow.
- const size_t kBigValueSize = kControlFrameSizeLimit;
+ const size_t kBigValueSize = TestSpdyVisitor::sent_control_frame_max_size();
string big_value(kBigValueSize, 'x');
push_promise.SetHeader("aa", big_value);
- scoped_ptr<SpdyFrame> control_frame(
- framer.SerializePushPromise(push_promise));
- EXPECT_TRUE(control_frame.get() != NULL);
- EXPECT_GT(control_frame->size(),
+ SpdySerializedFrame control_frame(framer.SerializePushPromise(push_promise));
+ EXPECT_GT(control_frame.size(),
TestSpdyVisitor::sent_control_frame_max_size());
TestSpdyVisitor visitor(spdy_version_);
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->size());
+ 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.push_promise_frame_count_);
- EXPECT_EQ(16, visitor.continuation_count_);
+ EXPECT_EQ(1, visitor.continuation_count_);
EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
}
@@ -3380,14 +3328,13 @@ TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
headers.set_priority(1);
headers.set_fin(true);
headers.SetHeader("aa", big_value);
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
- EXPECT_TRUE(control_frame.get() != NULL);
+ SpdySerializedFrame control_frame(framer.SerializeHeaders(headers));
TestSpdyVisitor visitor(spdy_version_);
visitor.set_header_buffer_size(kHeaderBufferSize);
visitor.use_compression_ = true;
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->size());
+ 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,
@@ -3406,14 +3353,15 @@ TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
// The framer should not have sent half-close to the visitor.
- EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
+ EXPECT_EQ(0, visitor.end_of_stream_count_);
}
TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
- if (spdy_version_ > SPDY3) {
+ 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,
@@ -3422,12 +3370,12 @@ TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
SpdySynStreamIR syn_stream(1);
syn_stream.set_priority(1);
syn_stream.SetHeader("aa", "alpha beta gamma delta");
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
+ 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());
+ 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(framer.error_code());
@@ -3441,14 +3389,14 @@ TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
ASSERT_LE(SpdyFramerPeer::ControlFrameBufferSize(), 250u);
const size_t length = SpdyFramerPeer::ControlFrameBufferSize() + 1;
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x07,
+ 0x80, 0x03, 0x00, 0x07,
0x00, 0x00, 0x00, static_cast<unsigned char>(length),
0x00, 0x00, 0x00, 0x00, // Stream ID
0x00, 0x00, 0x00, 0x00, // Status
};
- // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
- // since it may carry opaque data. Verify that minimal length is tested.
+ // 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.GetControlFrameHeaderSize());
const size_t less_than_min_length =
framer.GetGoAwayMinimumSize() - framer.GetControlFrameHeaderSize() - 1;
@@ -3462,14 +3410,14 @@ TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
};
const size_t pad_length =
length + framer.GetControlFrameHeaderSize() -
- (IsHttp2() ? sizeof(kH2FrameData) : sizeof(kV3FrameData));
+ (IsSpdy3() ? sizeof(kV3FrameData) : sizeof(kH2FrameData));
string pad(pad_length, 'A');
TestSpdyVisitor visitor(spdy_version_);
- if (IsHttp2()) {
- visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
- } else {
+ if (IsSpdy3()) {
visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
+ } else {
+ visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
}
visitor.SimulateInFramer(
reinterpret_cast<const unsigned char*>(pad.c_str()),
@@ -3485,14 +3433,14 @@ TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
SpdyFramer framer(spdy_version_);
SpdySettingsIR settings_ir;
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
- SetFrameLength(control_frame.get(), 0, spdy_version_);
+ SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
+ SetFrameLength(&control_frame, 0, spdy_version_);
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = false;
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
+ reinterpret_cast<unsigned char*>(control_frame.data()),
framer.GetControlFrameHeaderSize());
- if (spdy_version_ <= SPDY3) {
+ if (IsSpdy3()) {
// Should generate an error, since zero-len settings frames are unsupported.
EXPECT_EQ(1, visitor.error_count_);
} else {
@@ -3512,17 +3460,20 @@ TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
false,
false,
0x00000002);
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
+ SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
const size_t kNewLength = 14;
- SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
+ SetFrameLength(&control_frame, kNewLength, spdy_version_);
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = false;
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
+ reinterpret_cast<unsigned char*>(control_frame.data()),
framer.GetControlFrameHeaderSize() + kNewLength);
// Should generate an error, since its not possible to have a
// settings frame of length kNewLength.
EXPECT_EQ(1, visitor.error_count_);
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
+ visitor.framer_.error_code())
+ << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
}
// Tests handling of SETTINGS frames larger than the frame buffer size.
@@ -3542,36 +3493,36 @@ TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
false, // persisted
7);
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
- EXPECT_LT(SpdyFramerPeer::ControlFrameBufferSize(), control_frame->size());
+ SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
+ EXPECT_LT(SpdyFramerPeer::ControlFrameBufferSize(), control_frame.size());
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = false;
// Read all at once.
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->size());
+ reinterpret_cast<unsigned char*>(control_frame.data()),
+ control_frame.size());
EXPECT_EQ(0, visitor.error_count_);
EXPECT_EQ(3, visitor.setting_count_);
- if (spdy_version_ > SPDY3) {
+ if (IsHttp2()) {
EXPECT_EQ(1, visitor.settings_ack_sent_);
}
// Read data in small chunks.
size_t framed_data = 0;
- size_t unframed_data = control_frame->size();
+ size_t unframed_data = control_frame.size();
size_t kReadChunkSize = 5; // Read five bytes at a time.
while (unframed_data > 0) {
size_t to_read = std::min(kReadChunkSize, unframed_data);
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
+ reinterpret_cast<unsigned char*>(control_frame.data() + framed_data),
to_read);
unframed_data -= to_read;
framed_data += to_read;
}
EXPECT_EQ(0, visitor.error_count_);
EXPECT_EQ(3 * 2, visitor.setting_count_);
- if (spdy_version_ > SPDY3) {
+ if (IsHttp2()) {
EXPECT_EQ(2, visitor.settings_ack_sent_);
}
}
@@ -3581,7 +3532,7 @@ TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
SpdyFramer framer(spdy_version_);
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x04,
+ 0x80, 0x03, 0x00, 0x04,
0x00, 0x00, 0x00, 0x1C,
0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x01, // 1st Setting
@@ -3610,7 +3561,7 @@ TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
}
- if (!IsHttp2()) {
+ if (IsSpdy3()) {
EXPECT_EQ(1, visitor.setting_count_);
EXPECT_EQ(1, visitor.error_count_);
} else {
@@ -3627,7 +3578,7 @@ TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
SpdyFramer framer(spdy_version_);
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x04,
+ 0x80, 0x03, 0x00, 0x04,
0x00, 0x00, 0x00, 0x1C,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x10, // 1st Setting
@@ -3648,7 +3599,7 @@ TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
}
- if (!IsHttp2()) {
+ if (IsSpdy3()) {
EXPECT_EQ(0, visitor.setting_count_);
EXPECT_EQ(1, visitor.error_count_);
} else {
@@ -3663,7 +3614,7 @@ TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
SpdyFramer framer(spdy_version_);
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x04,
+ 0x80, 0x03, 0x00, 0x04,
0x00, 0x00, 0x00, 0x1C,
0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x02, // 1st Setting
@@ -3692,7 +3643,7 @@ TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
}
- if (!IsHttp2()) {
+ if (IsSpdy3()) {
EXPECT_EQ(1, visitor.setting_count_);
EXPECT_EQ(1, visitor.error_count_);
} else {
@@ -3703,9 +3654,10 @@ TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
}
TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
+
SpdyFramer framer(spdy_version_);
const unsigned char kFrameData[] = {
@@ -3723,7 +3675,7 @@ TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
}
TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -3736,8 +3688,7 @@ TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
SpdyDataIR data_ir(1, data_payload);
data_ir.set_padding_len(kPaddingLen);
- scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
- ASSERT_TRUE(frame.get() != NULL);
+ SpdySerializedFrame frame(framer.SerializeData(data_ir));
int bytes_consumed = 0;
@@ -3746,61 +3697,60 @@ TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
kPaddingLen + strlen(data_payload),
false));
CHECK_EQ(framer.GetDataFrameMinimumSize(),
- framer.ProcessInput(frame->data(),
- framer.GetDataFrameMinimumSize()));
+ framer.ProcessInput(frame.data(), framer.GetDataFrameMinimumSize()));
CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
bytes_consumed += framer.GetDataFrameMinimumSize();
// Send the padding length field.
EXPECT_CALL(visitor, OnStreamPadding(1, 1));
- CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
+ CHECK_EQ(1u, framer.ProcessInput(frame.data() + bytes_consumed, 1));
CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
bytes_consumed += 1;
// Send the first two bytes of the data payload, i.e., "he".
EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false));
- CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2));
+ CHECK_EQ(2u, framer.ProcessInput(frame.data() + bytes_consumed, 2));
CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
bytes_consumed += 2;
// Send the rest three bytes of the data payload, i.e., "llo".
EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false));
- CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3));
+ CHECK_EQ(3u, framer.ProcessInput(frame.data() + bytes_consumed, 3));
CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
bytes_consumed += 3;
// Send the first 100 bytes of the padding payload.
EXPECT_CALL(visitor, OnStreamPadding(1, 100));
- CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100));
+ CHECK_EQ(100u, framer.ProcessInput(frame.data() + bytes_consumed, 100));
CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
bytes_consumed += 100;
// Send rest of the padding payload.
EXPECT_CALL(visitor, OnStreamPadding(1, 18));
- CHECK_EQ(18u, framer.ProcessInput(frame->data() + bytes_consumed, 18));
+ CHECK_EQ(18u, framer.ProcessInput(frame.data() + bytes_consumed, 18));
CHECK_EQ(framer.state(), SpdyFramer::SPDY_READY_FOR_FRAME);
CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
}
TEST_P(SpdyFramerTest, ReadWindowUpdate) {
SpdyFramer framer(spdy_version_);
- scoped_ptr<SpdyFrame> control_frame(
+ SpdySerializedFrame control_frame(
framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
TestSpdyVisitor visitor(spdy_version_);
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->size());
+ reinterpret_cast<unsigned char*>(control_frame.data()),
+ control_frame.size());
EXPECT_EQ(1u, visitor.last_window_update_stream_);
EXPECT_EQ(2, visitor.last_window_update_delta_);
}
TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -3809,68 +3759,18 @@ TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
push_promise.SetHeader("foo", "bar");
push_promise.SetHeader("bar", "foofoo");
SpdyHeaderBlock headers = push_promise.header_block();
- scoped_ptr<SpdySerializedFrame> frame(
- framer.SerializePushPromise(push_promise));
- EXPECT_TRUE(frame.get() != NULL);
+ SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = true;
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(frame->data()),
- frame->size());
+ visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
+ frame.size());
EXPECT_EQ(42u, visitor.last_push_promise_stream_);
EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
EXPECT_EQ(headers, visitor.headers_);
}
TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
- if (spdy_version_ <= SPDY3) {
- return;
- }
-
- const unsigned char kInput[] = {
- 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
- 0x00, 0x00, 0x00, 0x01, // Stream 1
- 0x03, // Padding of 3.
- 0x00, 0x06, 'c', 'o',
- 'o', 'k', 'i', 'e',
- 0x07, 'f', 'o', 'o',
- '=', 'b', 'a', 'r',
- 0x00, 0x00, 0x00,
-
- 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
- 0x00, 0x00, 0x00, 0x01, // Stream 1
- 0x00, 0x06, 'c', 'o',
- 'o', 'k', 'i', 'e',
- 0x08, 'b', 'a', 'z',
- '=', 'b', 'i', 'n',
- 'g', 0x00, 0x06, 'c',
-
- 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
- 0x00, 0x00, 0x00, 0x01, // Stream 1
- 'o', 'o', 'k', 'i',
- 'e', 0x00, 0x00, 0x04,
- 'n', 'a', 'm', 'e',
- 0x05, 'v', 'a', 'l',
- 'u', 'e',
- };
-
- TestSpdyVisitor visitor(spdy_version_);
- visitor.SimulateInFramer(kInput, sizeof(kInput));
-
- EXPECT_EQ(0, visitor.error_count_);
- EXPECT_EQ(1, visitor.headers_frame_count_);
- EXPECT_EQ(2, visitor.continuation_count_);
- EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
- EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
-
- EXPECT_THAT(visitor.headers_,
- testing::ElementsAre(
- testing::Pair("cookie", "foo=bar; baz=bing; "),
- testing::Pair("name", "value")));
-}
-
-TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -3908,7 +3808,7 @@ TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
EXPECT_EQ(2, visitor.continuation_count_);
EXPECT_EQ(1, visitor.fin_flag_count_);
EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
- EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
+ EXPECT_EQ(1, visitor.end_of_stream_count_);
EXPECT_THAT(visitor.headers_,
testing::ElementsAre(
@@ -3917,7 +3817,7 @@ TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
}
TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -3958,7 +3858,7 @@ TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
EXPECT_EQ(2, visitor.continuation_count_);
EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
- EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
+ EXPECT_EQ(0, visitor.end_of_stream_count_);
EXPECT_THAT(visitor.headers_,
testing::ElementsAre(
@@ -3967,7 +3867,7 @@ TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
}
TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -4003,7 +3903,7 @@ TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
}
TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -4030,7 +3930,7 @@ TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
}
TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -4063,7 +3963,7 @@ TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
}
TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -4100,9 +4000,10 @@ TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
}
TEST_P(SpdyFramerTest, EndSegmentOnDataFrame) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
+
const unsigned char kInput[] = {
0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
0x00, 0x00, 0x00, 0x01, // Stream 1
@@ -4122,9 +4023,10 @@ TEST_P(SpdyFramerTest, EndSegmentOnDataFrame) {
}
TEST_P(SpdyFramerTest, EndSegmentOnHeadersFrame) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
+
const unsigned char kInput[] = {
0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
0x00, 0x00, 0x00, 0x01, // Stream 1
@@ -4157,9 +4059,10 @@ TEST_P(SpdyFramerTest, ReadGarbage) {
}
TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
+
SpdyFramer framer(spdy_version_);
// The unrecognized frame type should still have a valid length.
@@ -4184,10 +4087,10 @@ TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
false, // persist
false, // persisted
10);
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
+ SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->size());
+ reinterpret_cast<unsigned char*>(control_frame.data()),
+ control_frame.size());
EXPECT_EQ(0, visitor.error_count_);
EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
@@ -4197,6 +4100,7 @@ TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
if (!IsHttp2()) {
return;
}
+
SpdyFramer framer(spdy_version_);
const unsigned char kFrameData[] = {
0x00, 0x00, 0x08, 0xff, 0xff,
@@ -4211,13 +4115,13 @@ TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
}
TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
- if (IsHttp2()) {
- // Not valid for HTTP/2 since there is no version field.
+ if (!IsSpdy3()) {
return;
}
+
SpdyFramer framer(spdy_version_);
const unsigned char kFrameData[] = {
- 0x80, spdy_version_ch_, 0xff, 0xff,
+ 0x80, 0x03, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
};
TestSpdyVisitor visitor(spdy_version_);
@@ -4227,9 +4131,10 @@ TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
}
TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
+
const unsigned char kInput[] = {
0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
0x00, 0x00, 0x00, 0x01, // Stream 1
@@ -4247,7 +4152,21 @@ TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
TEST_P(SpdyFramerTest, SizesTest) {
SpdyFramer framer(spdy_version_);
- if (IsHttp2()) {
+ if (IsSpdy3()) {
+ EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
+ EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
+ 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.GetControlFrameHeaderSize());
EXPECT_EQ(14u, framer.GetSynStreamMinimumSize());
@@ -4264,20 +4183,6 @@ TEST_P(SpdyFramerTest, SizesTest) {
EXPECT_EQ(9u, framer.GetFrameMinimumSize());
EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
- } else {
- EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
- EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
- 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());
}
}
@@ -4326,6 +4231,9 @@ TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
SpdyFramer::ErrorCodeToString(
SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
+ EXPECT_STREQ("INVALID_CONTROL_FRAME_SIZE",
+ SpdyFramer::ErrorCodeToString(
+ SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE));
EXPECT_STREQ("ZLIB_INIT_FAILURE",
SpdyFramer::ErrorCodeToString(
SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
@@ -4395,10 +4303,11 @@ TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
}
TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
- if (IsHttp2()) {
+ if (!IsSpdy3()) {
// TODO(hkhalil): catch probable HTTP response in HTTP/2?
return;
}
+
{
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
SpdyFramer framer(spdy_version_);
@@ -4426,7 +4335,9 @@ TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
}
TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
- if (spdy_version_ > SPDY3) {
+ FLAGS_spdy_on_stream_end = true;
+
+ if (!IsSpdy3()) {
return;
}
@@ -4439,8 +4350,50 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
framer.set_visitor(&visitor);
SpdyDataIR data_ir(1, "hello");
- scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
- SetFrameFlags(frame.get(), flags, spdy_version_);
+ 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, false));
+ 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, DataFrameFlagsV2V3disabled) {
+ FLAGS_spdy_on_stream_end = false;
+
+ if (!IsSpdy3()) {
+ return;
+ }
+
+ uint8_t flags = 0;
+ do {
+ SCOPED_TRACE(testing::Message() << "Flags " << 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(_));
@@ -4452,7 +4405,7 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
}
}
- framer.ProcessInput(frame->data(), frame->size());
+ 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,
@@ -4467,7 +4420,61 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
}
TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
- if (spdy_version_ <= SPDY3) {
+ FLAGS_spdy_on_stream_end = true;
+
+ if (!IsHttp2()) {
+ return;
+ }
+
+ uint8_t valid_data_flags =
+ DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | DATA_FLAG_PADDED;
+
+ uint8_t flags = 0;
+ do {
+ SCOPED_TRACE(testing::Message() << "Flags " << 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 & ~valid_data_flags) {
+ EXPECT_CALL(visitor, OnError(_));
+ } else {
+ EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
+ if (flags & DATA_FLAG_PADDED) {
+ // The first byte of payload is parsed as padding length.
+ EXPECT_CALL(visitor, OnStreamPadding(_, 1));
+ // Expect Error since the frame ends prematurely.
+ EXPECT_CALL(visitor, OnError(_));
+ } else {
+ EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
+ if (flags & DATA_FLAG_FIN) {
+ EXPECT_CALL(visitor, OnStreamEnd(_));
+ }
+ }
+ }
+
+ framer.ProcessInput(frame.data(), frame.size());
+ if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) {
+ 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, DataFrameFlagsV4disabled) {
+ FLAGS_spdy_on_stream_end = false;
+
+ if (!IsHttp2()) {
return;
}
@@ -4483,8 +4490,8 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
framer.set_visitor(&visitor);
SpdyDataIR data_ir(1, "hello");
- scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
- SetFrameFlags(frame.get(), flags, spdy_version_);
+ SpdySerializedFrame frame(framer.SerializeData(data_ir));
+ SetFrameFlags(&frame, flags, spdy_version_);
if (flags & ~valid_data_flags) {
EXPECT_CALL(visitor, OnError(_));
@@ -4503,7 +4510,7 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
}
}
- framer.ProcessInput(frame->data(), frame->size());
+ framer.ProcessInput(frame.data(), frame.size());
if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) {
EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
@@ -4517,10 +4524,68 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
}
TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
+ FLAGS_spdy_on_stream_end = true;
+
+ if (!IsSpdy3()) {
+ return;
+ }
+
+ uint8_t flags = 0;
+ do {
+ SCOPED_TRACE(testing::Message() << "Flags " << 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, OnControlFrameHeaderData(8, _, _))
+ .WillRepeatedly(testing::Return(true));
+ 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, SynStreamFrameFlagsDisabled) {
+ FLAGS_spdy_on_stream_end = false;
+
if (!IsSpdy3()) {
- // SYN_STREAM not supported in SPDY>3
return;
}
+
uint8_t flags = 0;
do {
SCOPED_TRACE(testing::Message() << "Flags " << flags);
@@ -4537,8 +4602,8 @@ TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
syn_stream.set_associated_to_stream_id(3);
syn_stream.set_priority(1);
syn_stream.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
- SetFrameFlags(frame.get(), flags, spdy_version_);
+ SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
+ SetFrameFlags(&frame, flags, spdy_version_);
if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
EXPECT_CALL(visitor, OnError(_));
@@ -4556,7 +4621,7 @@ TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
}
}
- framer.ProcessInput(frame->data(), frame->size());
+ 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,
@@ -4571,10 +4636,57 @@ TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
}
TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
+ FLAGS_spdy_on_stream_end = true;
+
+ if (!IsSpdy3()) {
+ return;
+ }
+
+ uint8_t flags = 0;
+ do {
+ SCOPED_TRACE(testing::Message() << "Flags " << 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, OnControlFrameHeaderData(37, _, _))
+ .WillRepeatedly(testing::Return(true));
+ 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, SynReplyFrameFlagsDisabled) {
+ FLAGS_spdy_on_stream_end = false;
+
if (!IsSpdy3()) {
- // SYN_REPLY not supported in SPDY>3
return;
}
+
uint8_t flags = 0;
do {
SCOPED_TRACE(testing::Message() << "Flags " << flags);
@@ -4585,8 +4697,8 @@ TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
SpdySynReplyIR syn_reply(37);
syn_reply.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
- SetFrameFlags(frame.get(), flags, spdy_version_);
+ SpdySerializedFrame frame(framer.SerializeSynReply(syn_reply));
+ SetFrameFlags(&frame, flags, spdy_version_);
if (flags & ~CONTROL_FLAG_FIN) {
EXPECT_CALL(visitor, OnError(_));
@@ -4599,7 +4711,7 @@ TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
}
}
- framer.ProcessInput(frame->data(), frame->size());
+ 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,
@@ -4623,8 +4735,8 @@ TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
framer.set_visitor(&visitor);
SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL);
- scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
- SetFrameFlags(frame.get(), flags, spdy_version_);
+ SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
+ SetFrameFlags(&frame, flags, spdy_version_);
if (flags != 0) {
EXPECT_CALL(visitor, OnError(_));
@@ -4632,7 +4744,7 @@ TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
}
- framer.ProcessInput(frame->data(), frame->size());
+ framer.ProcessInput(frame.data(), frame.size());
if (flags != 0) {
EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
@@ -4647,7 +4759,10 @@ TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
}
TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
- if (spdy_version_ > SPDY3) { return; }
+ if (!IsSpdy3()) {
+ return;
+ }
+
uint8_t flags = 0;
do {
SCOPED_TRACE(testing::Message() << "Flags " << flags);
@@ -4661,8 +4776,8 @@ TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
false,
false,
54321);
- scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
- SetFrameFlags(frame.get(), flags, spdy_version_);
+ SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
+ SetFrameFlags(&frame, flags, spdy_version_);
if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
EXPECT_CALL(visitor, OnError(_));
@@ -4674,7 +4789,7 @@ TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
EXPECT_CALL(visitor, OnSettingsEnd());
}
- framer.ProcessInput(frame->data(), frame->size());
+ 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,
@@ -4689,7 +4804,10 @@ TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
}
TEST_P(SpdyFramerTest, SettingsFrameFlags) {
- if (spdy_version_ <= SPDY3) { return; }
+ if (!IsHttp2()) {
+ return;
+ }
+
uint8_t flags = 0;
do {
SCOPED_TRACE(testing::Message() << "Flags " << flags);
@@ -4700,8 +4818,8 @@ TEST_P(SpdyFramerTest, SettingsFrameFlags) {
SpdySettingsIR settings_ir;
settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
- scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
- SetFrameFlags(frame.get(), flags, spdy_version_);
+ SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
+ SetFrameFlags(&frame, flags, spdy_version_);
if (flags != 0) {
EXPECT_CALL(visitor, OnError(_));
@@ -4711,7 +4829,7 @@ TEST_P(SpdyFramerTest, SettingsFrameFlags) {
EXPECT_CALL(visitor, OnSettingsEnd());
}
- framer.ProcessInput(frame->data(), frame->size());
+ framer.ProcessInput(frame.data(), frame.size());
if (flags & ~SETTINGS_FLAG_ACK) {
EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
@@ -4720,7 +4838,7 @@ TEST_P(SpdyFramerTest, SettingsFrameFlags) {
} else if (flags & SETTINGS_FLAG_ACK) {
// The frame is invalid because ACK frames should have no payload.
EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
- EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
framer.error_code())
<< SpdyFramer::ErrorCodeToString(framer.error_code());
} else {
@@ -4741,8 +4859,8 @@ TEST_P(SpdyFramerTest, GoawayFrameFlags) {
framer.set_visitor(&visitor);
SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
- scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
- SetFrameFlags(frame.get(), flags, spdy_version_);
+ SpdySerializedFrame frame(framer.SerializeGoAway(goaway_ir));
+ SetFrameFlags(&frame, flags, spdy_version_);
if (flags != 0) {
EXPECT_CALL(visitor, OnError(_));
@@ -4750,7 +4868,7 @@ TEST_P(SpdyFramerTest, GoawayFrameFlags) {
EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
}
- framer.ProcessInput(frame->data(), frame->size());
+ framer.ProcessInput(frame.data(), frame.size());
if (flags != 0) {
EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
@@ -4765,6 +4883,8 @@ TEST_P(SpdyFramerTest, GoawayFrameFlags) {
}
TEST_P(SpdyFramerTest, HeadersFrameFlags) {
+ FLAGS_spdy_on_stream_end = true;
+
uint8_t flags = 0;
do {
SCOPED_TRACE(testing::Message() << "Flags " << flags);
@@ -4781,22 +4901,113 @@ TEST_P(SpdyFramerTest, HeadersFrameFlags) {
headers_ir.set_exclusive(true);
}
headers_ir.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
+ SpdySerializedFrame frame(framer.SerializeHeaders(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.get(), set_flags, spdy_version_);
+ SetFrameFlags(&frame, set_flags, spdy_version_);
if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) {
EXPECT_CALL(visitor, OnError(_));
- } else if (IsHttp2() && flags & ~(CONTROL_FLAG_FIN |
- HEADERS_FLAG_END_HEADERS |
- HEADERS_FLAG_END_SEGMENT |
- HEADERS_FLAG_PADDED |
- HEADERS_FLAG_PRIORITY)) {
+ } else if (IsHttp2() &&
+ flags &
+ ~(CONTROL_FLAG_FIN | HEADERS_FLAG_END_HEADERS |
+ HEADERS_FLAG_END_SEGMENT | HEADERS_FLAG_PADDED |
+ HEADERS_FLAG_PRIORITY)) {
+ EXPECT_CALL(visitor, OnError(_));
+ } else {
+ // Expected callback values
+ SpdyStreamId stream_id = 57;
+ bool has_priority = false;
+ SpdyPriority priority = 0;
+ 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) {
+ has_priority = true;
+ priority = 3;
+ parent_stream_id = 5;
+ exclusive = true;
+ }
+ EXPECT_CALL(visitor, OnHeaders(stream_id, has_priority, priority,
+ parent_stream_id, exclusive, fin, end));
+ EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
+ .WillRepeatedly(testing::Return(true));
+ if (flags & DATA_FLAG_FIN &&
+ (IsSpdy3() || flags & HEADERS_FLAG_END_HEADERS)) {
+ 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 (IsSpdy3() && 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 if (IsHttp2() &&
+ flags &
+ ~(CONTROL_FLAG_FIN | HEADERS_FLAG_END_HEADERS |
+ HEADERS_FLAG_END_SEGMENT | HEADERS_FLAG_PADDED |
+ HEADERS_FLAG_PRIORITY)) {
+ EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
+ framer.error_code())
+ << SpdyFramer::ErrorCodeToString(framer.error_code());
+ } else if (IsHttp2() && ~(flags & HEADERS_FLAG_END_HEADERS)) {
+ EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
+ EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, 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, HeadersFrameFlagsDisabled) {
+ FLAGS_spdy_on_stream_end = false;
+
+ uint8_t flags = 0;
+ do {
+ SCOPED_TRACE(testing::Message() << "Flags " << flags);
+
+ testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
+ SpdyFramer framer(spdy_version_);
+ framer.set_visitor(&visitor);
+
+ SpdyHeadersIR headers_ir(57);
+ if (IsHttp2() && (flags & HEADERS_FLAG_PRIORITY)) {
+ headers_ir.set_priority(3);
+ headers_ir.set_has_priority(true);
+ headers_ir.set_parent_stream_id(5);
+ headers_ir.set_exclusive(true);
+ }
+ headers_ir.SetHeader("foo", "bar");
+ SpdySerializedFrame frame(framer.SerializeHeaders(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_);
+
+ if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) {
+ EXPECT_CALL(visitor, OnError(_));
+ } else if (IsHttp2() &&
+ flags &
+ ~(CONTROL_FLAG_FIN | HEADERS_FLAG_END_HEADERS |
+ HEADERS_FLAG_END_SEGMENT | HEADERS_FLAG_PADDED |
+ HEADERS_FLAG_PRIORITY)) {
EXPECT_CALL(visitor, OnError(_));
} else {
// Expected callback values
@@ -4806,8 +5017,8 @@ TEST_P(SpdyFramerTest, HeadersFrameFlags) {
SpdyStreamId parent_stream_id = 0;
bool exclusive = false;
bool fin = flags & CONTROL_FLAG_FIN;
- bool end = !IsHttp2() || (flags & HEADERS_FLAG_END_HEADERS);
- if (spdy_version_ > SPDY3 && flags & HEADERS_FLAG_PRIORITY) {
+ bool end = IsSpdy3() || (flags & HEADERS_FLAG_END_HEADERS);
+ if (IsHttp2() && flags & HEADERS_FLAG_PRIORITY) {
has_priority = true;
priority = 3;
parent_stream_id = 5;
@@ -4818,7 +5029,7 @@ TEST_P(SpdyFramerTest, HeadersFrameFlags) {
EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
.WillRepeatedly(testing::Return(true));
if (flags & DATA_FLAG_FIN &&
- (!IsHttp2() || flags & HEADERS_FLAG_END_HEADERS)) {
+ (IsSpdy3() || flags & HEADERS_FLAG_END_HEADERS)) {
EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
} else {
// Do not close the stream if we are expecting a CONTINUATION frame.
@@ -4826,8 +5037,8 @@ TEST_P(SpdyFramerTest, HeadersFrameFlags) {
}
}
- framer.ProcessInput(frame->data(), frame->size());
- if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) {
+ framer.ProcessInput(frame.data(), frame.size());
+ if (IsSpdy3() && flags & ~CONTROL_FLAG_FIN) {
EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
framer.error_code())
@@ -4862,11 +5073,10 @@ TEST_P(SpdyFramerTest, PingFrameFlags) {
SpdyFramer framer(spdy_version_);
framer.set_visitor(&visitor);
- scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
- SetFrameFlags(frame.get(), flags, spdy_version_);
+ SpdySerializedFrame frame(framer.SerializePing(SpdyPingIR(42)));
+ SetFrameFlags(&frame, flags, spdy_version_);
- if (spdy_version_ > SPDY3 &&
- flags == PING_FLAG_ACK) {
+ if (IsHttp2() && flags == PING_FLAG_ACK) {
EXPECT_CALL(visitor, OnPing(42, true));
} else if (flags == 0) {
EXPECT_CALL(visitor, OnPing(42, false));
@@ -4874,9 +5084,8 @@ TEST_P(SpdyFramerTest, PingFrameFlags) {
EXPECT_CALL(visitor, OnError(_));
}
- framer.ProcessInput(frame->data(), frame->size());
- if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) ||
- flags == 0) {
+ framer.ProcessInput(frame.data(), frame.size());
+ if ((IsHttp2() && flags == PING_FLAG_ACK) || flags == 0) {
EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
<< SpdyFramer::ErrorCodeToString(framer.error_code());
@@ -4898,9 +5107,9 @@ TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
SpdyFramer framer(spdy_version_);
framer.set_visitor(&visitor);
- scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
- SpdyWindowUpdateIR(4, 1024)));
- SetFrameFlags(frame.get(), flags, spdy_version_);
+ SpdySerializedFrame frame(
+ framer.SerializeWindowUpdate(SpdyWindowUpdateIR(4, 1024)));
+ SetFrameFlags(&frame, flags, spdy_version_);
if (flags != 0) {
EXPECT_CALL(visitor, OnError(_));
@@ -4908,7 +5117,7 @@ TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
}
- framer.ProcessInput(frame->data(), frame->size());
+ framer.ProcessInput(frame.data(), frame.size());
if (flags != 0) {
EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
@@ -4923,7 +5132,7 @@ TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
}
TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -4941,11 +5150,10 @@ TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
SpdyPushPromiseIR push_promise(42, 57);
push_promise.SetHeader("foo", "bar");
- scoped_ptr<SpdySerializedFrame> frame(
- framer.SerializePushPromise(push_promise));
+ SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
// TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
// and implement framing.
- SetFrameFlags(frame.get(), flags & ~HEADERS_FLAG_PADDED, spdy_version_);
+ SetFrameFlags(&frame, flags & ~HEADERS_FLAG_PADDED, spdy_version_);
if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
EXPECT_CALL(visitor, OnError(_));
@@ -4957,7 +5165,7 @@ TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
.WillRepeatedly(testing::Return(true));
}
- framer.ProcessInput(frame->data(), frame->size());
+ framer.ProcessInput(frame.data(), frame.size());
if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
@@ -4972,7 +5180,7 @@ TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
}
TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -4994,14 +5202,13 @@ TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
SpdyHeadersIR headers_ir(42);
headers_ir.SetHeader("foo", "bar");
- scoped_ptr<SpdyFrame> frame0(framer.SerializeHeaders(headers_ir));
- SetFrameFlags(frame0.get(), 0, spdy_version_);
+ SpdySerializedFrame frame0(framer.SerializeHeaders(headers_ir));
+ SetFrameFlags(&frame0, 0, spdy_version_);
SpdyContinuationIR continuation(42);
continuation.SetHeader("foo", "bar");
- scoped_ptr<SpdySerializedFrame> frame(
- framer.SerializeContinuation(continuation));
- SetFrameFlags(frame.get(), flags, spdy_version_);
+ SpdySerializedFrame frame(framer.SerializeContinuation(continuation));
+ SetFrameFlags(&frame, flags, spdy_version_);
if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
EXPECT_CALL(visitor, OnError(_));
@@ -5013,8 +5220,8 @@ TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
.WillRepeatedly(testing::Return(true));
}
- framer.ProcessInput(frame0->data(), frame0->size());
- framer.ProcessInput(frame->data(), frame->size());
+ framer.ProcessInput(frame0.data(), frame0.size());
+ framer.ProcessInput(frame.data(), frame.size());
if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
@@ -5034,9 +5241,9 @@ TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
TEST_P(SpdyFramerTest, EmptySynStream) {
if (!IsSpdy3()) {
- // SYN_STREAM not supported in SPDY>3.
return;
}
+
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
testing::StrictMock<test::MockDebugVisitor> debug_visitor;
SpdyFramer framer(spdy_version_);
@@ -5047,18 +5254,17 @@ TEST_P(SpdyFramerTest, EmptySynStream) {
SpdySynStreamIR syn_stream(1);
syn_stream.set_priority(1);
- scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
+ SpdySerializedFrame frame(framer.SerializeSynStream(syn_stream));
// Adjust size to remove the header block.
- SetFrameLength(
- frame.get(),
- framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
- spdy_version_);
+ SetFrameLength(&frame, framer.GetSynStreamMinimumSize() -
+ framer.GetControlFrameHeaderSize(),
+ spdy_version_);
EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
- framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
+ 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());
@@ -5081,7 +5287,7 @@ TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
const unsigned char kRstStreamStatusTooLow = 0x00;
const unsigned char kRstStreamStatusTooHigh = 0xff;
const unsigned char kV3RstStreamInvalid[] = {
- 0x80, spdy_version_ch_, 0x00, 0x03,
+ 0x80, 0x03, 0x00, 0x03,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, kRstStreamStatusTooLow
@@ -5094,7 +5300,7 @@ TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
};
const unsigned char kV3RstStreamNumStatusCodes[] = {
- 0x80, spdy_version_ch_, 0x00, 0x03,
+ 0x80, 0x03, 0x00, 0x03,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, kRstStreamStatusTooHigh
@@ -5110,14 +5316,14 @@ TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
SpdyFramer framer(spdy_version_);
framer.set_visitor(&visitor);
- if (IsHttp2()) {
- EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
- framer.ProcessInput(reinterpret_cast<const char*>(kH2RstStreamInvalid),
- arraysize(kH2RstStreamInvalid));
- } else {
+ if (IsSpdy3()) {
EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
arraysize(kV3RstStreamInvalid));
+ } else {
+ EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_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())
@@ -5126,16 +5332,16 @@ TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
framer.Reset();
- if (IsHttp2()) {
- EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
- framer.ProcessInput(
- reinterpret_cast<const char*>(kH2RstStreamNumStatusCodes),
- arraysize(kH2RstStreamNumStatusCodes));
- } else {
+ if (IsSpdy3()) {
EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
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_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
@@ -5147,7 +5353,7 @@ TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
SpdyFramer framer(spdy_version_);
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x07,
+ 0x80, 0x03, 0x00, 0x07,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x01, // Stream Id
0xff, 0xff, 0xff, 0xff, // Status
@@ -5179,7 +5385,7 @@ TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
// Tests handling of a GOAWAY frame with out-of-bounds stream ID.
TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
const unsigned char kV3FrameData[] = {
- 0x80, spdy_version_ch_, 0x00, 0x07,
+ 0x80, 0x03, 0x00, 0x07,
0x00, 0x00, 0x00, 0x08,
0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00,
@@ -5210,7 +5416,7 @@ TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
}
TEST_P(SpdyFramerTest, OnBlocked) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -5223,8 +5429,8 @@ TEST_P(SpdyFramerTest, OnBlocked) {
EXPECT_CALL(visitor, OnBlocked(kStreamId));
SpdyBlockedIR blocked_ir(0);
- scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
- framer.ProcessInput(frame->data(), framer.GetBlockedSize());
+ SpdySerializedFrame frame(framer.SerializeFrame(blocked_ir));
+ framer.ProcessInput(frame.data(), framer.GetBlockedSize());
EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
@@ -5232,7 +5438,7 @@ TEST_P(SpdyFramerTest, OnBlocked) {
}
TEST_P(SpdyFramerTest, OnAltSvc) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -5257,8 +5463,8 @@ TEST_P(SpdyFramerTest, OnAltSvc) {
altsvc_ir.set_origin("o_r|g!n");
altsvc_ir.add_altsvc(altsvc1);
altsvc_ir.add_altsvc(altsvc2);
- scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
- framer.ProcessInput(frame->data(), frame->size());
+ 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())
@@ -5266,7 +5472,7 @@ TEST_P(SpdyFramerTest, OnAltSvc) {
}
TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -5289,8 +5495,8 @@ TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
SpdyAltSvcIR altsvc_ir(1);
altsvc_ir.add_altsvc(altsvc1);
altsvc_ir.add_altsvc(altsvc2);
- scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
- framer.ProcessInput(frame->data(), frame->size());
+ 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())
@@ -5298,7 +5504,7 @@ TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
}
TEST_P(SpdyFramerTest, OnAltSvcEmptyProtocolId) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -5314,8 +5520,8 @@ TEST_P(SpdyFramerTest, OnAltSvcEmptyProtocolId) {
"pid1", "host", 443, 5, 1.0, SpdyAltSvcWireFormat::VersionVector()));
altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
"", "h1", 443, 10, 1.0, SpdyAltSvcWireFormat::VersionVector()));
- scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
- framer.ProcessInput(frame->data(), frame->size());
+ SpdySerializedFrame frame(framer.SerializeFrame(altsvc_ir));
+ framer.ProcessInput(frame.data(), frame.size());
EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
@@ -5323,7 +5529,7 @@ TEST_P(SpdyFramerTest, OnAltSvcEmptyProtocolId) {
}
TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -5342,8 +5548,8 @@ TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
SpdyAltSvcIR altsvc_ir(1);
altsvc_ir.set_origin("o1");
altsvc_ir.add_altsvc(altsvc);
- scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
- framer.ProcessInput(frame->data(), frame->size());
+ 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())
@@ -5352,7 +5558,7 @@ TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
// Tests handling of ALTSVC frames delivered in small chunks.
TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -5366,18 +5572,18 @@ TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
altsvc_ir.add_altsvc(altsvc1);
altsvc_ir.add_altsvc(altsvc2);
- scoped_ptr<SpdyFrame> control_frame(framer.SerializeAltSvc(altsvc_ir));
+ SpdySerializedFrame control_frame(framer.SerializeAltSvc(altsvc_ir));
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = false;
// Read data in small chunks.
size_t framed_data = 0;
- size_t unframed_data = control_frame->size();
+ size_t unframed_data = control_frame.size();
size_t kReadChunkSize = 5; // Read five bytes at a time.
while (unframed_data > 0) {
size_t to_read = std::min(kReadChunkSize, unframed_data);
visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
+ reinterpret_cast<unsigned char*>(control_frame.data() + framed_data),
to_read);
unframed_data -= to_read;
framed_data += to_read;
@@ -5391,16 +5597,17 @@ TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
// Tests handling of PRIORITY frames.
TEST_P(SpdyFramerTest, ReadPriority) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
+
SpdyFramer framer(spdy_version_);
SpdyPriorityIR priority(3, 1, 255, false);
- scoped_ptr<SpdySerializedFrame> frame(framer.SerializePriority(priority));
+ SpdySerializedFrame frame(framer.SerializePriority(priority));
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
framer.set_visitor(&visitor);
EXPECT_CALL(visitor, OnPriority(3, 1, 255, false));
- framer.ProcessInput(frame->data(), frame->size());
+ framer.ProcessInput(frame.data(), frame.size());
EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
@@ -5410,9 +5617,10 @@ TEST_P(SpdyFramerTest, ReadPriority) {
}
TEST_P(SpdyFramerTest, PriorityWeightMapping) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
+
SpdyFramer framer(spdy_version_);
EXPECT_EQ(255u, framer.MapPriorityToWeight(0));
@@ -5443,7 +5651,7 @@ TEST_P(SpdyFramerTest, PriorityWeightMapping) {
// Tests handling of PRIORITY frame with incorrect size.
TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
- if (spdy_version_ <= SPDY3) {
+ if (!IsHttp2()) {
return;
}
@@ -5458,7 +5666,68 @@ TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
- EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
+ visitor.framer_.error_code())
+ << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
+}
+
+// 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, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x01,
+ };
+
+ TestSpdyVisitor visitor(spdy_version_);
+ visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
+
+ EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
+ visitor.framer_.error_code())
+ << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
+}
+
+// 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, 0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01,
+ };
+
+ TestSpdyVisitor visitor(spdy_version_);
+ visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
+
+ EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
+ visitor.framer_.error_code())
+ << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
+}
+
+// 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, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01,
+ };
+
+ TestSpdyVisitor visitor(spdy_version_);
+ visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
+
+ EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
+ EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
visitor.framer_.error_code())
<< SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
}
@@ -5476,26 +5745,26 @@ TEST_P(SpdyFramerTest, ProcessAllInput) {
headers.SetHeader("alpha", "beta");
headers.SetHeader("gamma", "charlie");
headers.SetHeader("cookie", "key1=value1; key2=value2");
- scoped_ptr<SpdyFrame> headers_frame(framer.SerializeHeaders(headers));
+ SpdySerializedFrame headers_frame(framer.SerializeHeaders(headers));
const char four_score[] = "Four score and seven years ago";
SpdyDataIR four_score_ir(1, four_score);
- scoped_ptr<SpdyFrame> four_score_frame(framer.SerializeData(four_score_ir));
+ SpdySerializedFrame four_score_frame(framer.SerializeData(four_score_ir));
// Put them in a single buffer (new variables here to make it easy to
// change the order and type of frames).
- SpdyFrame* frame1 = headers_frame.get();
- SpdyFrame* frame2 = four_score_frame.get();
+ SpdySerializedFrame frame1 = std::move(headers_frame);
+ SpdySerializedFrame frame2 = std::move(four_score_frame);
- const size_t frame1_size = frame1->size();
- const size_t frame2_size = frame2->size();
+ const size_t frame1_size = frame1.size();
+ const size_t frame2_size = frame2.size();
LOG(INFO) << "frame1_size = " << frame1_size;
LOG(INFO) << "frame2_size = " << frame2_size;
string input_buffer;
- input_buffer.append(frame1->data(), frame1_size);
- input_buffer.append(frame2->data(), frame2_size);
+ input_buffer.append(frame1.data(), frame1_size);
+ input_buffer.append(frame2.data(), frame2_size);
const char* buf = input_buffer.data();
const size_t buf_size = input_buffer.size();
@@ -5522,28 +5791,28 @@ TEST_P(SpdyFramerTest, ProcessAtMostOneFrame) {
// Create two input frames.
const char four_score[] = "Four score and ...";
SpdyDataIR four_score_ir(1, four_score);
- scoped_ptr<SpdyFrame> four_score_frame(framer.SerializeData(four_score_ir));
+ SpdySerializedFrame four_score_frame(framer.SerializeData(four_score_ir));
SpdyHeadersIR headers(2);
headers.SetHeader("alpha", "beta");
headers.SetHeader("gamma", "charlie");
headers.SetHeader("cookie", "key1=value1; key2=value2");
- scoped_ptr<SpdyFrame> headers_frame(framer.SerializeHeaders(headers));
+ SpdySerializedFrame headers_frame(framer.SerializeHeaders(headers));
// Put them in a single buffer (new variables here to make it easy to
// change the order and type of frames).
- SpdyFrame* frame1 = four_score_frame.get();
- SpdyFrame* frame2 = headers_frame.get();
+ SpdySerializedFrame frame1 = std::move(four_score_frame);
+ SpdySerializedFrame frame2 = std::move(headers_frame);
- const size_t frame1_size = frame1->size();
- const size_t frame2_size = frame2->size();
+ const size_t frame1_size = frame1.size();
+ const size_t frame2_size = frame2.size();
LOG(INFO) << "frame1_size = " << frame1_size;
LOG(INFO) << "frame2_size = " << frame2_size;
string input_buffer;
- input_buffer.append(frame1->data(), frame1_size);
- input_buffer.append(frame2->data(), frame2_size);
+ input_buffer.append(frame1.data(), frame1_size);
+ input_buffer.append(frame2.data(), frame2_size);
const char* buf = input_buffer.data();
const size_t buf_size = input_buffer.size();
diff --git a/chromium/net/spdy/spdy_header_block.cc b/chromium/net/spdy/spdy_header_block.cc
index 49243a7a341..b24085fea02 100644
--- a/chromium/net/spdy/spdy_header_block.cc
+++ b/chromium/net/spdy/spdy_header_block.cc
@@ -114,6 +114,9 @@ SpdyHeaderBlock::StringPieceProxy::StringPieceProxy(
lookup_result_(lookup_result),
key_(key) {}
+SpdyHeaderBlock::StringPieceProxy::StringPieceProxy(
+ const StringPieceProxy& other) = default;
+
SpdyHeaderBlock::StringPieceProxy::~StringPieceProxy() {}
SpdyHeaderBlock::StringPieceProxy& SpdyHeaderBlock::StringPieceProxy::operator=(
diff --git a/chromium/net/spdy/spdy_header_block.h b/chromium/net/spdy/spdy_header_block.h
index 2c57d413fd4..58d6cf4cdd8 100644
--- a/chromium/net/spdy/spdy_header_block.h
+++ b/chromium/net/spdy/spdy_header_block.h
@@ -35,7 +35,9 @@ using ::operator<<;
// 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>;
+ using MapType = linked_hash_map<base::StringPiece,
+ base::StringPiece,
+ base::StringPieceHash>;
class Storage;
public:
@@ -87,6 +89,7 @@ class NET_EXPORT SpdyHeaderBlock {
class NET_EXPORT StringPieceProxy {
public:
~StringPieceProxy();
+ StringPieceProxy(const StringPieceProxy& other);
// Assignment modifies the underlying SpdyHeaderBlock.
StringPieceProxy& operator=(const base::StringPiece other);
diff --git a/chromium/net/spdy/spdy_headers_handler_interface.h b/chromium/net/spdy/spdy_headers_handler_interface.h
index 5543194752e..a6861afa217 100644
--- a/chromium/net/spdy/spdy_headers_handler_interface.h
+++ b/chromium/net/spdy/spdy_headers_handler_interface.h
@@ -18,7 +18,8 @@ class SpdyHeadersHandlerInterface {
virtual ~SpdyHeadersHandlerInterface() {}
// A callback method which notifies when the parser starts handling a new
- // header block fragment.
+ // header block. Will only be called once per block, even if it extends into
+ // CONTINUATION frames.
virtual void OnHeaderBlockStart() = 0;
// A callback method which notifies on a header key value pair. Multiple
@@ -26,9 +27,9 @@ class SpdyHeadersHandlerInterface {
virtual void OnHeader(base::StringPiece key, base::StringPiece value) = 0;
// A callback method which notifies when the parser finishes handling a
- // header block fragment. Also indicates the total number of bytes in this
- // block.
- virtual void OnHeaderBlockEnd(size_t header_bytes_parsed) = 0;
+ // header block (i.e. the containing frame has the END_STREAM flag set).
+ // Also indicates the total number of bytes in this block.
+ virtual void OnHeaderBlockEnd(size_t uncompressed_header_bytes) = 0;
};
} // namespace net
diff --git a/chromium/net/spdy/spdy_http_stream.cc b/chromium/net/spdy/spdy_http_stream.cc
index 16e19b209ab..4fdbc0e918e 100644
--- a/chromium/net/spdy/spdy_http_stream.cc
+++ b/chromium/net/spdy/spdy_http_stream.cc
@@ -17,7 +17,6 @@
#include "base/thread_task_runner_handle.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
-#include "net/base/net_util.h"
#include "net/base/upload_data_stream.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_request_info.h"
@@ -537,7 +536,7 @@ void SpdyHttpStream::DoRequestCallback(int rv) {
// Since Run may result in being called back, reset request_callback_ in
// advance.
- ResetAndReturn(&request_callback_).Run(rv);
+ base::ResetAndReturn(&request_callback_).Run(rv);
}
void SpdyHttpStream::DoResponseCallback(int rv) {
@@ -546,7 +545,7 @@ void SpdyHttpStream::DoResponseCallback(int rv) {
// Since Run may result in being called back, reset response_callback_ in
// advance.
- ResetAndReturn(&response_callback_).Run(rv);
+ base::ResetAndReturn(&response_callback_).Run(rv);
}
void SpdyHttpStream::GetSSLInfo(SSLInfo* ssl_info) {
@@ -570,13 +569,19 @@ bool SpdyHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
return spdy_session_->GetPeerAddress(endpoint) == OK;
}
+Error SpdyHttpStream::GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ return spdy_session_->GetSignedEKMForTokenBinding(key, out);
+}
+
void SpdyHttpStream::Drain(HttpNetworkSession* session) {
NOTREACHED();
Close(false);
delete this;
}
-void SpdyHttpStream::PopulateNetErrorDetails(NetErrorDetails* /*details*/) {
+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 a79569a33f0..76130d8c641 100644
--- a/chromium/net/spdy/spdy_http_stream.h
+++ b/chromium/net/spdy/spdy_http_stream.h
@@ -79,6 +79,8 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
void GetSSLInfo(SSLInfo* ssl_info) override;
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override;
void Drain(HttpNetworkSession* session) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
void SetPriority(RequestPriority priority) override;
diff --git a/chromium/net/spdy/spdy_http_stream_unittest.cc b/chromium/net/spdy/spdy_http_stream_unittest.cc
index 9aff81b57b5..9ef70cede19 100644
--- a/chromium/net/spdy/spdy_http_stream_unittest.cc
+++ b/chromium/net/spdy/spdy_http_stream_unittest.cc
@@ -82,14 +82,11 @@ class SpdyHttpStreamTest : public testing::Test,
SpdyHttpStreamTest()
: spdy_util_(GetProtocol(), GetDependenciesFromPriority()),
session_deps_(GetProtocol()) {
- SpdySession::SetPriorityDependencyDefaultForTesting(
- GetDependenciesFromPriority());
+ session_deps_.enable_priority_dependencies = GetDependenciesFromPriority();
session_deps_.net_log = &net_log_;
}
- ~SpdyHttpStreamTest() {
- SpdySession::SetPriorityDependencyDefaultForTesting(false);
- }
+ ~SpdyHttpStreamTest() {}
protected:
NextProto GetProtocol() const {
@@ -165,12 +162,13 @@ TEST_P(SpdyHttpStreamTest, GetUploadProgressBeforeInitialization) {
}
TEST_P(SpdyHttpStreamTest, SendRequest) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req.get(), 0),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead reads[] = {
CreateMockRead(*resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
};
@@ -225,21 +223,21 @@ TEST_P(SpdyHttpStreamTest, SendRequest) {
}
TEST_P(SpdyHttpStreamTest, LoadTimingTwoRequests) {
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
CreateMockWrite(*req2, 1),
};
- scoped_ptr<SpdyFrame> resp1(
+ scoped_ptr<SpdySerializedFrame> resp1(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body1(
+ scoped_ptr<SpdySerializedFrame> body1(
spdy_util_.ConstructSpdyBodyFrame(1, "", 0, true));
- scoped_ptr<SpdyFrame> resp2(
+ scoped_ptr<SpdySerializedFrame> resp2(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body2(
+ scoped_ptr<SpdySerializedFrame> body2(
spdy_util_.ConstructSpdyBodyFrame(3, "", 0, true));
MockRead reads[] = {
CreateMockRead(*resp1, 2),
@@ -325,18 +323,19 @@ TEST_P(SpdyHttpStreamTest, LoadTimingTwoRequests) {
}
TEST_P(SpdyHttpStreamTest, SendChunkedPost) {
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req(
+ scoped_ptr<SpdySerializedFrame> req(
spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
- scoped_ptr<SpdyFrame> body(
+ scoped_ptr<SpdySerializedFrame> body(
framer.CreateDataFrame(1, kUploadData, kUploadDataSize, DATA_FLAG_FIN));
MockWrite writes[] = {
CreateMockWrite(*req, 0), // request
CreateMockWrite(*body, 1) // POST upload frame
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
CreateMockRead(*resp, 2),
CreateMockRead(*body, 3),
@@ -389,17 +388,19 @@ TEST_P(SpdyHttpStreamTest, SendChunkedPost) {
}
TEST_P(SpdyHttpStreamTest, ConnectionClosedDuringChunkedPost) {
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
- scoped_ptr<SpdyFrame> body(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> body(
framer.CreateDataFrame(1, kUploadData, kUploadDataSize, DATA_FLAG_NONE));
MockWrite writes[] = {
CreateMockWrite(*req, 0), // Request
CreateMockWrite(*body, 1) // First POST upload frame
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
MockRead(ASYNC, ERR_CONNECTION_CLOSED, 2) // Server hangs up early.
};
@@ -460,19 +461,22 @@ TEST_P(SpdyHttpStreamTest, ConnectionClosedDuringChunkedPost) {
TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPost) {
const char kUploadData1[] = "12345678";
const int kUploadData1Size = arraysize(kUploadData1)-1;
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
- scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> chunk2(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, kUploadData1, kUploadData1Size, false));
- scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> chunk1(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(
+ 1, kUploadData1, kUploadData1Size, false));
+ scoped_ptr<SpdySerializedFrame> chunk3(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(*req.get(), 0),
CreateMockWrite(*chunk1, 1), // POST upload frames
CreateMockWrite(*chunk2, 2),
CreateMockWrite(*chunk3, 3),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
CreateMockRead(*resp, 4),
CreateMockRead(*chunk1, 5),
@@ -560,16 +564,19 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPost) {
// Test that the SpdyStream state machine can handle sending a final empty data
// frame when uploading a chunked data stream.
TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithEmptyFinalDataFrame) {
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
- scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> chunk2(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> chunk1(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> chunk2(
spdy_util_.ConstructSpdyBodyFrame(1, "", 0, true));
MockWrite writes[] = {
CreateMockWrite(*req.get(), 0),
CreateMockWrite(*chunk1, 1), // POST upload frames
CreateMockWrite(*chunk2, 2),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
CreateMockRead(*resp, 3),
CreateMockRead(*chunk1, 4),
@@ -649,14 +656,16 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithEmptyFinalDataFrame) {
// Test that the SpdyStream state machine handles a chunked upload with no
// payload. Unclear if this is a case worth supporting.
TEST_P(SpdyHttpStreamTest, ChunkedPostWithEmptyPayload) {
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
- scoped_ptr<SpdyFrame> chunk(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> chunk(
spdy_util_.ConstructSpdyBodyFrame(1, "", 0, true));
MockWrite writes[] = {
CreateMockWrite(*req.get(), 0),
CreateMockWrite(*chunk, 1),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
CreateMockRead(*resp, 2),
CreateMockRead(*chunk, 3),
@@ -719,12 +728,13 @@ TEST_P(SpdyHttpStreamTest, ChunkedPostWithEmptyPayload) {
TEST_P(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";
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(base_url, false, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(base_url, 1, LOWEST));
MockWrite writes[] = {
CreateMockWrite(*req.get(), 0),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead reads[] = {
CreateMockRead(*resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
};
@@ -766,14 +776,17 @@ TEST_P(SpdyHttpStreamTest, SpdyURLTest) {
// Test the receipt of a WINDOW_UPDATE frame while waiting for a chunk to be
// made available is handled correctly.
TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) {
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
- scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> chunk1(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(*req.get(), 0),
CreateMockWrite(*chunk1, 1),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
- scoped_ptr<SpdyFrame> window_update(
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
MockRead reads[] = {
CreateMockRead(*window_update, 2),
diff --git a/chromium/net/spdy/spdy_http_utils.cc b/chromium/net/spdy/spdy_http_utils.cc
index 8692305bf56..573bce18b8f 100644
--- a/chromium/net/spdy/spdy_http_utils.cc
+++ b/chromium/net/spdy/spdy_http_utils.cc
@@ -7,11 +7,12 @@
#include <string>
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_headers.h"
@@ -164,7 +165,7 @@ void CreateSpdyHeadersFromHttpResponse(
std::find(after_version + 1, status_line.end(), ' ');
(*headers)[status_key] = std::string(after_version + 1, after_status);
- void* iter = NULL;
+ size_t iter = 0;
std::string raw_name, value;
while (response_headers.EnumerateHeaderLines(&iter, &raw_name, &value)) {
std::string name = base::ToLowerASCII(raw_name);
@@ -192,10 +193,24 @@ NET_EXPORT_PRIVATE RequestPriority ConvertSpdyPriorityToRequestPriority(
IDLE : static_cast<RequestPriority>(4 - priority);
}
+NET_EXPORT_PRIVATE void ConvertHeaderBlockToHttpRequestHeaders(
+ const SpdyHeaderBlock& spdy_headers,
+ HttpRequestHeaders* http_headers) {
+ for (const auto& it : spdy_headers) {
+ base::StringPiece key = it.first;
+ if (key[0] == ':') {
+ key.remove_prefix(1);
+ }
+ std::vector<base::StringPiece> values = base::SplitStringPiece(
+ it.second, "\0", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ for (const auto& value : values) {
+ http_headers->SetHeader(key, value);
+ }
+ }
+}
+
GURL GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers,
- SpdyMajorVersion protocol_version,
- bool pushed) {
- DCHECK_LE(SPDY3, protocol_version);
+ SpdyMajorVersion protocol_version) {
SpdyHeaderBlock::const_iterator it = headers.find(":scheme");
if (it == headers.end())
return GURL();
diff --git a/chromium/net/spdy/spdy_http_utils.h b/chromium/net/spdy/spdy_http_utils.h
index a0db4752f63..b33a91a2215 100644
--- a/chromium/net/spdy/spdy_http_utils.h
+++ b/chromium/net/spdy/spdy_http_utils.h
@@ -43,11 +43,15 @@ NET_EXPORT void CreateSpdyHeadersFromHttpResponse(
SpdyMajorVersion protocol_version,
SpdyHeaderBlock* headers);
+// Create HttpRequestHeaders from SpdyHeaderBlock.
+NET_EXPORT void ConvertHeaderBlockToHttpRequestHeaders(
+ const SpdyHeaderBlock& spdy_headers,
+ HttpRequestHeaders* http_headers);
+
// Returns the URL associated with the |headers| by assembling the
// scheme, host and path from the protocol specific keys.
NET_EXPORT GURL GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers,
- SpdyMajorVersion protocol_version,
- bool pushed);
+ SpdyMajorVersion protocol_version);
NET_EXPORT SpdyPriority ConvertRequestPriorityToSpdyPriority(
RequestPriority priority,
diff --git a/chromium/net/spdy/spdy_network_transaction_unittest.cc b/chromium/net/spdy/spdy_network_transaction_unittest.cc
index 59951ae8f7b..900f1038a45 100644
--- a/chromium/net/spdy/spdy_network_transaction_unittest.cc
+++ b/chromium/net/spdy/spdy_network_transaction_unittest.cc
@@ -18,8 +18,10 @@
#include "net/base/auth.h"
#include "net/base/chunked_upload_data_stream.h"
#include "net/base/elements_upload_data_stream.h"
+#include "net/base/proxy_delegate.h"
#include "net/base/request_priority.h"
#include "net/base/test_data_directory.h"
+#include "net/base/test_proxy_delegate.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_file_element_reader.h"
#include "net/http/http_auth_scheme.h"
@@ -30,6 +32,7 @@
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_entry.h"
#include "net/log/test_net_log_util.h"
+#include "net/proxy/proxy_server.h"
#include "net/socket/client_socket_pool_base.h"
#include "net/socket/next_proto.h"
#include "net/spdy/buffered_spdy_framer.h"
@@ -101,16 +104,18 @@ struct SpdyNetworkTransactionTestParams {
void UpdateSpdySessionDependencies(SpdyNetworkTransactionTestParams test_params,
SpdySessionDependencies* session_deps) {
- session_deps->use_alternative_services = true;
- session_deps->next_protos = SpdyNextProtos();
+ session_deps->parse_alternative_services = true;
+ session_deps->enable_alternative_service_with_different_host = true;
if (test_params.ssl_type == HTTP_SPDY_VIA_ALT_SVC) {
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
session_deps->http_server_properties.SetAlternativeService(
HostPortPair("www.example.org", 80),
AlternativeService(AlternateProtocolFromNextProto(test_params.protocol),
"www.example.org", 443),
- 1.0, expiration);
+ expiration);
}
+ session_deps->enable_priority_dependencies =
+ test_params.priority_to_dependency;
}
scoped_ptr<SpdySessionDependencies> CreateSpdySessionDependencies(
@@ -137,8 +142,6 @@ class SpdyNetworkTransactionTest
protected:
SpdyNetworkTransactionTest()
: spdy_util_(GetParam().protocol, GetParam().priority_to_dependency) {
- SpdySession::SetPriorityDependencyDefaultForTesting(
- GetParam().priority_to_dependency);
spdy_util_.set_default_url(GURL(GetDefaultUrl()));
}
@@ -147,7 +150,6 @@ class SpdyNetworkTransactionTest
// destruction.
upload_data_stream_.reset();
base::RunLoop().RunUntilIdle();
- SpdySession::SetPriorityDependencyDefaultForTesting(false);
}
void SetUp() override {
@@ -556,7 +558,7 @@ class SpdyNetworkTransactionTest
BoundNetLog log;
HttpNetworkSession* session = helper.session();
base::WeakPtr<SpdySession> spdy_session =
- session->spdy_session_pool()->FindAvailableSession(key, log);
+ session->spdy_session_pool()->FindAvailableSession(key, url, log);
ASSERT_TRUE(spdy_session != NULL);
EXPECT_EQ(0u, spdy_session->num_active_streams());
EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
@@ -710,12 +712,14 @@ TEST_P(SpdyNetworkTransactionTest, Constructor) {
TEST_P(SpdyNetworkTransactionTest, Get) {
// Construct the request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -735,14 +739,18 @@ TEST_P(SpdyNetworkTransactionTest, Get) {
TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
p = RequestPriority(p + 1)) {
+ SpdyTestUtil spdy_test_util(GetParam().protocol,
+ GetParam().priority_to_dependency);
+ spdy_test_util.set_default_url(GURL(GetDefaultUrl()));
+
// Construct the request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
- spdy_util_.UpdateWithStreamDestruction(1);
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, p, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
SpdyPriority spdy_prio = 0;
- EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
+ EXPECT_TRUE(
+ GetSpdyPriority(spdy_test_util.spdy_version(), *req, &spdy_prio));
// this repeats the RequestPriority-->SpdyPriority mapping from
// SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
// sure it's being done right.
@@ -766,8 +774,10 @@ TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
FAIL();
}
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_test_util.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_test_util.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -799,23 +809,32 @@ TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
// can allow multiple streams in flight.
TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
-
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
- scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
-
- scoped_ptr<SpdyFrame> req3(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
- scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
- scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
- scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> fbody(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(3, false));
+ scoped_ptr<SpdySerializedFrame> fbody2(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
+
+ scoped_ptr<SpdySerializedFrame> req3(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp3(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
+ scoped_ptr<SpdySerializedFrame> body3(
+ spdy_util_.ConstructSpdyBodyFrame(5, false));
+ scoped_ptr<SpdySerializedFrame> fbody3(
+ spdy_util_.ConstructSpdyBodyFrame(5, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
@@ -896,17 +915,23 @@ TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
}
TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
-
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
- scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> fbody(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(3, false));
+ scoped_ptr<SpdySerializedFrame> fbody2(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*req2, 3),
@@ -981,17 +1006,23 @@ TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
}
TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
-
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
- scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> fbody(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(3, false));
+ scoped_ptr<SpdySerializedFrame> fbody2(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*req2, 3),
@@ -1086,33 +1117,43 @@ TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
// Construct the request.
// Each request fully completes before the next starts.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> fbody(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
spdy_util_.UpdateWithStreamDestruction(1);
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
- scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(3, false));
+ scoped_ptr<SpdySerializedFrame> fbody2(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
spdy_util_.UpdateWithStreamDestruction(3);
- scoped_ptr<SpdyFrame> req3(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
- scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
- scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
- scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
+ scoped_ptr<SpdySerializedFrame> req3(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp3(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
+ scoped_ptr<SpdySerializedFrame> body3(
+ spdy_util_.ConstructSpdyBodyFrame(5, false));
+ scoped_ptr<SpdySerializedFrame> fbody3(
+ spdy_util_.ConstructSpdyBodyFrame(5, true));
SettingsMap settings;
const uint32_t max_concurrent_streams = 1;
settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
- scoped_ptr<SpdyFrame> settings_frame(
+ scoped_ptr<SpdySerializedFrame> settings_frame(
spdy_util_.ConstructSpdySettings(settings));
- scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
+ scoped_ptr<SpdySerializedFrame> settings_ack(
+ spdy_util_.ConstructSpdySettingsAck());
MockWrite writes[] = {
CreateMockWrite(*req, 0),
@@ -1216,39 +1257,51 @@ TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
// the response from the server.
TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
// Construct the request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> fbody(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
spdy_util_.UpdateWithStreamDestruction(1);
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
- scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(3, false));
+ scoped_ptr<SpdySerializedFrame> fbody2(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
spdy_util_.UpdateWithStreamDestruction(3);
- scoped_ptr<SpdyFrame> req4(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
- scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
- scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
+ scoped_ptr<SpdySerializedFrame> req4(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 5, HIGHEST, true));
+ scoped_ptr<SpdySerializedFrame> resp4(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
+ scoped_ptr<SpdySerializedFrame> fbody4(
+ spdy_util_.ConstructSpdyBodyFrame(5, true));
spdy_util_.UpdateWithStreamDestruction(5);
- scoped_ptr<SpdyFrame> req3(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
- scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
- scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
- scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
+ scoped_ptr<SpdySerializedFrame> req3(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 7, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp3(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
+ scoped_ptr<SpdySerializedFrame> body3(
+ spdy_util_.ConstructSpdyBodyFrame(7, false));
+ scoped_ptr<SpdySerializedFrame> fbody3(
+ spdy_util_.ConstructSpdyBodyFrame(7, true));
SettingsMap settings;
const uint32_t max_concurrent_streams = 1;
settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
- scoped_ptr<SpdyFrame> settings_frame(
+ scoped_ptr<SpdySerializedFrame> settings_frame(
spdy_util_.ConstructSpdySettings(settings));
- scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
+ scoped_ptr<SpdySerializedFrame> settings_ack(
+ spdy_util_.ConstructSpdySettingsAck());
MockWrite writes[] = {
CreateMockWrite(*req, 0),
CreateMockWrite(*settings_ack, 5),
@@ -1368,26 +1421,33 @@ TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
// the spdy_session
TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
// Construct the request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> fbody(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
spdy_util_.UpdateWithStreamDestruction(1);
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
- scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(3, false));
+ scoped_ptr<SpdySerializedFrame> fbody2(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
SettingsMap settings;
const uint32_t max_concurrent_streams = 1;
settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
- scoped_ptr<SpdyFrame> settings_frame(
+ scoped_ptr<SpdySerializedFrame> settings_frame(
spdy_util_.ConstructSpdySettings(settings));
- scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
+ scoped_ptr<SpdySerializedFrame> settings_ack(
+ spdy_util_.ConstructSpdySettingsAck());
MockWrite writes[] = {
CreateMockWrite(*req, 0),
@@ -1500,24 +1560,29 @@ class KillerCallback : public TestCompletionCallbackBase {
// a pending stream creation. http://crbug.com/52901
TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
// Construct the request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> fin_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
spdy_util_.UpdateWithStreamDestruction(1);
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
SettingsMap settings;
const uint32_t max_concurrent_streams = 1;
settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
- scoped_ptr<SpdyFrame> settings_frame(
+ scoped_ptr<SpdySerializedFrame> settings_frame(
spdy_util_.ConstructSpdySettings(settings));
- scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
+ scoped_ptr<SpdySerializedFrame> settings_ack(
+ spdy_util_.ConstructSpdySettingsAck());
MockWrite writes[] = {
CreateMockWrite(*req, 0),
@@ -1600,14 +1665,16 @@ TEST_P(SpdyNetworkTransactionTest, Put) {
scoped_ptr<SpdyHeaderBlock> put_headers(
spdy_util_.ConstructPutHeaderBlock(GetDefaultUrl(), 0));
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, false, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -1633,14 +1700,16 @@ TEST_P(SpdyNetworkTransactionTest, Head) {
scoped_ptr<SpdyHeaderBlock> head_headers(
spdy_util_.ConstructHeadHeaderBlock(GetDefaultUrl(), 0));
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, false, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -1659,14 +1728,16 @@ TEST_P(SpdyNetworkTransactionTest, Head) {
// Test that a simple POST works.
TEST_P(SpdyNetworkTransactionTest, Post) {
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
CreateMockRead(*resp, 2),
CreateMockRead(*body, 3),
@@ -1685,14 +1756,16 @@ TEST_P(SpdyNetworkTransactionTest, Post) {
// Test that a POST with a file works.
TEST_P(SpdyNetworkTransactionTest, FilePost) {
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
CreateMockRead(*resp, 2),
CreateMockRead(*body, 3),
@@ -1733,14 +1806,16 @@ TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
// Test that a complex POST works.
TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
CreateMockRead(*resp, 2),
CreateMockRead(*body, 3),
@@ -1760,13 +1835,16 @@ TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
// Test that a chunked POST works.
TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*body, 1),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
CreateMockRead(*resp, 2),
CreateMockRead(*body, 3),
@@ -1793,10 +1871,14 @@ TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
// Test that a chunked POST works with chunks appended after transaction starts.
TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
- scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> chunk1(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> chunk2(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> chunk3(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
CreateMockWrite(*chunk1, 1),
@@ -1804,7 +1886,8 @@ TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
CreateMockWrite(*chunk3, 3),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
CreateMockRead(*resp, 4),
CreateMockRead(*chunk1, 5),
@@ -1845,7 +1928,7 @@ TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
// Test that a POST without any post data works.
TEST_P(SpdyNetworkTransactionTest, NullPost) {
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
// Setup the request
HttpRequestInfo request;
request.method = "POST";
@@ -1857,15 +1940,17 @@ TEST_P(SpdyNetworkTransactionTest, NullPost) {
// expected to be 0.
scoped_ptr<SpdyHeaderBlock> req_block(
spdy_util_.ConstructPostHeaderBlock(GetDefaultUrl(), 0));
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -1885,7 +1970,7 @@ TEST_P(SpdyNetworkTransactionTest, NullPost) {
// Test that a simple POST works.
TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
// Create an empty UploadDataStream.
std::vector<scoped_ptr<UploadElementReader>> element_readers;
ElementsUploadDataStream stream(std::move(element_readers), 0);
@@ -1900,15 +1985,17 @@ TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
scoped_ptr<SpdyHeaderBlock> req_block(
spdy_util_.ConstructPostHeaderBlock(GetDefaultUrl(), kContentLength));
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -1928,13 +2015,16 @@ TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
// While we're doing a post, the server sends the reply before upload completes.
TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
CreateMockWrite(*body, 3),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -1973,9 +2063,9 @@ TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
// socket causes the TCP write to return zero. This test checks that the client
// tries to queue up the RST_STREAM frame again.
TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
@@ -1983,7 +2073,8 @@ TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead reads[] = {
CreateMockRead(*resp.get(), 1, ASYNC),
MockRead(ASYNC, 0, 0, 4) // EOF
@@ -2009,14 +2100,15 @@ TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
// Test that the transaction doesn't crash when we don't have a reply.
TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*body, 1), MockRead(ASYNC, 0, 3) // EOF
};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
@@ -2032,21 +2124,23 @@ TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
// Test that the transaction doesn't crash when we get two replies on the same
// stream ID. See http://crbug.com/45639.
TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp0(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp1(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
- CreateMockRead(*resp, 1),
- CreateMockRead(*resp, 2),
- CreateMockRead(*body, 3),
- MockRead(ASYNC, 0, 5) // EOF
+ CreateMockRead(*resp0, 1), CreateMockRead(*resp1, 2),
+ CreateMockRead(*body, 3), MockRead(ASYNC, 0, 5) // EOF
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -2077,9 +2171,9 @@ TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
// Construct the request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
@@ -2088,9 +2182,9 @@ TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
const char* const headers[] = {
"transfer-encoding", "chunked"
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
- scoped_ptr<SpdyFrame> body(
+ scoped_ptr<SpdySerializedFrame> body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
@@ -2111,22 +2205,24 @@ TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
// Construct the request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
const char* const headers[] = {
"transfer-encoding", "chunked"
};
- scoped_ptr<SpdyFrame> push(
+ scoped_ptr<SpdySerializedFrame> push(
spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2, 2, 1,
GetDefaultUrlWithPath("/1").c_str()));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*push, 2),
@@ -2149,13 +2245,14 @@ TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
// Construct the request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead reads[] = {
CreateMockRead(*resp),
// This following read isn't used by the test, except during the
@@ -2188,16 +2285,17 @@ TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
// Verify that the client sends a Rst Frame upon cancelling the stream.
TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*req, 0, SYNCHRONOUS),
CreateMockWrite(*rst, 2, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC),
MockRead(ASYNC, 0, 0, 3) // EOF
@@ -2228,8 +2326,8 @@ TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
// to start another transaction on a session that is closing down. See
// http://crbug.com/47455
TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req)};
MockWrite writes2[] = {CreateMockWrite(*req, 0)};
@@ -2241,7 +2339,8 @@ TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
0x07, 'h', 'e', 'l', 'l', 'o', '!',
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead reads[] = {
CreateMockRead(*resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
@@ -2292,12 +2391,14 @@ TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
// transaction. Failures will usually be valgrind errors. See
// http://crbug.com/46925
TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp.get(), 1),
MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
@@ -2348,11 +2449,12 @@ TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectGetRequest) {
(*headers2)["accept-encoding"] = "gzip, deflate";
// Setup writes/reads to www.example.org
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
MockWrite writes[] = {
CreateMockWrite(*req, 1),
};
@@ -2362,8 +2464,10 @@ TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectGetRequest) {
};
// Setup writes/reads to www.foo.com
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes2[] = {
CreateMockWrite(*req2, 1),
};
@@ -2416,14 +2520,16 @@ TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
(*headers)["accept-encoding"] = "gzip, deflate";
// Setup writes/reads to www.example.org
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> rep(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> rep(spdy_util_.ConstructSpdyPush(
NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str(),
"301 Moved Permanently", "http://www.foo.com/index.php"));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*req, 1),
@@ -2442,10 +2548,12 @@ TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
(*headers2)["user-agent"] = "";
(*headers2)["accept-encoding"] = "gzip, deflate";
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes2[] = {
CreateMockWrite(*req2, 1),
};
@@ -2500,22 +2608,22 @@ TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
}
TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
const char kPushedData[] = "pushed";
- scoped_ptr<SpdyFrame> stream2_body(
- spdy_util_.ConstructSpdyBodyFrame(
- 2, kPushedData, strlen(kPushedData), true));
+ scoped_ptr<SpdySerializedFrame> stream2_body(
+ spdy_util_.ConstructSpdyBodyFrame(2, kPushedData, strlen(kPushedData),
+ true));
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1),
CreateMockRead(*stream2_syn, 2),
@@ -2539,26 +2647,26 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
// Verify the pushed stream.
EXPECT_TRUE(response2.headers.get() != NULL);
- EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
+ EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
}
TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
- spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
- NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
const char kPushedData[] = "pushed";
- scoped_ptr<SpdyFrame> stream2_body(
- spdy_util_.ConstructSpdyBodyFrame(
- 2, kPushedData, strlen(kPushedData), true));
+ scoped_ptr<SpdySerializedFrame> stream2_body(
+ spdy_util_.ConstructSpdyBodyFrame(2, kPushedData, strlen(kPushedData),
+ true));
MockRead reads[] = {
CreateMockRead(*stream2_syn, 1),
CreateMockRead(*stream1_reply, 2),
@@ -2582,26 +2690,26 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
// Verify the pushed stream.
EXPECT_TRUE(response2.headers.get() != NULL);
- EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
+ EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
}
TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
const char kPushedData[] = "pushed";
- scoped_ptr<SpdyFrame> stream2_body(
- spdy_util_.ConstructSpdyBodyFrame(
- 2, kPushedData, strlen(kPushedData), true));
- scoped_ptr<SpdyFrame>
- stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> stream2_body(
+ spdy_util_.ConstructSpdyBodyFrame(2, kPushedData, strlen(kPushedData),
+ true));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1),
CreateMockRead(*stream2_syn, 2),
@@ -2625,23 +2733,23 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
// Verify the pushed stream.
EXPECT_TRUE(response2.headers.get() != NULL);
- EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
+ EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
}
TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
- scoped_ptr<SpdyFrame> stream2_rst(
+ scoped_ptr<SpdySerializedFrame> stream2_rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1),
@@ -2681,25 +2789,25 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
// Verify that we don't leak streams and that we properly send a reset
// if the server pushes the same stream twice.
TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> stream3_rst(
+ scoped_ptr<SpdySerializedFrame> stream3_rst(
spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream3_rst, 4),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
const char kPushedData[] = "pushed";
- scoped_ptr<SpdyFrame> stream2_body(
- spdy_util_.ConstructSpdyBodyFrame(
- 2, kPushedData, strlen(kPushedData), true));
- scoped_ptr<SpdyFrame> stream3_syn(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> stream2_body(
+ spdy_util_.ConstructSpdyBodyFrame(2, kPushedData, strlen(kPushedData),
+ true));
+ scoped_ptr<SpdySerializedFrame> stream3_syn(spdy_util_.ConstructSpdyPush(
NULL, 0, 4, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1),
@@ -2725,37 +2833,36 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
// Verify the pushed stream.
EXPECT_TRUE(response2.headers.get() != NULL);
- EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
+ EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
}
TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
static const char kPushedData[] = "pushed my darling hello my baby";
- scoped_ptr<SpdyFrame> stream2_body_base(
- spdy_util_.ConstructSpdyBodyFrame(
- 2, kPushedData, strlen(kPushedData), true));
+ scoped_ptr<SpdySerializedFrame> stream2_body_base(
+ spdy_util_.ConstructSpdyBodyFrame(2, kPushedData, strlen(kPushedData),
+ true));
const size_t kChunkSize = strlen(kPushedData) / 4;
- scoped_ptr<SpdyFrame> stream2_body1(
- new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
- scoped_ptr<SpdyFrame> stream2_body2(
- new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
- scoped_ptr<SpdyFrame> stream2_body3(
- new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
- kChunkSize, false));
- scoped_ptr<SpdyFrame> stream2_body4(
- new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
- stream2_body_base->size() - 3 * kChunkSize, false));
+ scoped_ptr<SpdySerializedFrame> stream2_body1(
+ new SpdySerializedFrame(stream2_body_base->data(), kChunkSize, false));
+ scoped_ptr<SpdySerializedFrame> stream2_body2(new SpdySerializedFrame(
+ stream2_body_base->data() + kChunkSize, kChunkSize, false));
+ scoped_ptr<SpdySerializedFrame> stream2_body3(new SpdySerializedFrame(
+ stream2_body_base->data() + 2 * kChunkSize, kChunkSize, false));
+ scoped_ptr<SpdySerializedFrame> stream2_body4(new SpdySerializedFrame(
+ stream2_body_base->data() + 3 * kChunkSize,
+ stream2_body_base->size() - 3 * kChunkSize, false));
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1),
CreateMockRead(*stream2_syn, 2),
@@ -2779,37 +2886,36 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
// Verify the pushed stream.
EXPECT_TRUE(response2.headers.get() != NULL);
- EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
+ EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
}
TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
static const char kPushedData[] = "pushed my darling hello my baby";
- scoped_ptr<SpdyFrame> stream2_body_base(
- spdy_util_.ConstructSpdyBodyFrame(
- 2, kPushedData, strlen(kPushedData), true));
+ scoped_ptr<SpdySerializedFrame> stream2_body_base(
+ spdy_util_.ConstructSpdyBodyFrame(2, kPushedData, strlen(kPushedData),
+ true));
const size_t kChunkSize = strlen(kPushedData) / 4;
- scoped_ptr<SpdyFrame> stream2_body1(
- new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
- scoped_ptr<SpdyFrame> stream2_body2(
- new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
- scoped_ptr<SpdyFrame> stream2_body3(
- new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
- kChunkSize, false));
- scoped_ptr<SpdyFrame> stream2_body4(
- new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
- stream2_body_base->size() - 3 * kChunkSize, false));
+ scoped_ptr<SpdySerializedFrame> stream2_body1(
+ new SpdySerializedFrame(stream2_body_base->data(), kChunkSize, false));
+ scoped_ptr<SpdySerializedFrame> stream2_body2(new SpdySerializedFrame(
+ stream2_body_base->data() + kChunkSize, kChunkSize, false));
+ scoped_ptr<SpdySerializedFrame> stream2_body3(new SpdySerializedFrame(
+ stream2_body_base->data() + 2 * kChunkSize, kChunkSize, false));
+ scoped_ptr<SpdySerializedFrame> stream2_body4(new SpdySerializedFrame(
+ stream2_body_base->data() + 3 * kChunkSize,
+ stream2_body_base->size() - 3 * kChunkSize, false));
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1),
CreateMockRead(*stream2_syn, 2),
@@ -2832,35 +2938,31 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
// Verify the pushed stream.
EXPECT_TRUE(response2.headers.get() != NULL);
- EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
+ EXPECT_EQ("HTTP/1.1 200", response2.headers->GetStatusLine());
}
TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
- if (spdy_util_.spdy_version() == HTTP2) {
- // PUSH_PROMISE with stream id 0 is connection-level error.
- // TODO(baranovich): Test session going away.
- return;
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> goaway;
+ if (spdy_util_.spdy_version() == SPDY3) {
+ goaway.reset(spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR,
+ "Push on even stream id."));
+ } else {
+ goaway.reset(spdy_util_.ConstructSpdyGoAway(
+ 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
}
-
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
- spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> stream2_rst(
- spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
MockWrite writes[] = {
- CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
+ CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*goaway, 3),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
NULL, 0, 2, 0, GetDefaultUrlWithPath("/foo.dat").c_str()));
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1),
CreateMockRead(*stream2_syn, 2),
- CreateMockRead(*stream1_body, 4),
- MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -2891,19 +2993,19 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
}
TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> stream2_rst(
+ scoped_ptr<SpdySerializedFrame> stream2_rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
NULL, 0, 2, 9, GetDefaultUrlWithPath("/foo.dat").c_str()));
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1),
@@ -2940,24 +3042,25 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
}
TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> stream2_rst(
+ scoped_ptr<SpdySerializedFrame> stream2_rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
(*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
(*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
(*incomplete_headers)["hello"] = "bye";
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
- std::move(incomplete_headers), 2, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(
+ spdy_util_.ConstructInitialSpdyPushFrame(std::move(incomplete_headers), 2,
+ 1));
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1),
CreateMockRead(*stream2_syn, 2),
@@ -2992,6 +3095,143 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
}
+// PUSH_PROMISE on a server-initiated stream should trigger GOAWAY.
+TEST_P(SpdyNetworkTransactionTest, ServerPushOnPushedStream) {
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(
+ 2, GOAWAY_PROTOCOL_ERROR, "Push on even stream id."));
+ MockWrite writes[] = {
+ CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*goaway, 4),
+ };
+
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ scoped_ptr<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),
+ };
+
+ SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
+ NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
+ BoundNetLog(), GetParam(), nullptr);
+ helper.RunToCompletion(&data);
+}
+
+// PUSH_PROMISE on a closed client-initiated stream should trigger RST_STREAM.
+TEST_P(SpdyNetworkTransactionTest, ServerPushOnClosedStream) {
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
+ spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
+ MockWrite writes[] = {
+ CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*rst, 5),
+ };
+
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ MockRead reads[] = {
+ CreateMockRead(*stream1_reply, 1), CreateMockRead(*stream1_body, 2),
+ CreateMockRead(*stream2_syn, 3), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
+ };
+
+ SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
+ NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
+ BoundNetLog(), GetParam(), nullptr);
+ helper.RunPreTestSetup();
+ helper.AddData(&data);
+
+ HttpNetworkTransaction* trans = helper.trans();
+
+ TestCompletionCallback callback;
+ int rv =
+ trans->Start(&CreateGetRequest(), callback.callback(), BoundNetLog());
+ rv = callback.GetResult(rv);
+ EXPECT_EQ(OK, rv);
+ HttpResponseInfo response = *trans->GetResponseInfo();
+ EXPECT_TRUE(response.headers.get());
+ EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
+
+ EXPECT_TRUE(data.AllReadDataConsumed());
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ VerifyStreamsClosed(helper);
+}
+
+// PUSH_PROMISE on a server-initiated stream should trigger GOAWAY even if
+// stream is closed.
+TEST_P(SpdyNetworkTransactionTest, ServerPushOnClosedPushedStream) {
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(
+ 2, GOAWAY_PROTOCOL_ERROR, "Push on even stream id."));
+ MockWrite writes[] = {
+ CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*goaway, 7),
+ };
+
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
+ nullptr, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+ const char kPushedData[] = "pushed";
+ scoped_ptr<SpdySerializedFrame> stream2_body(
+ spdy_util_.ConstructSpdyBodyFrame(2, kPushedData, strlen(kPushedData),
+ true));
+ scoped_ptr<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(*stream1_body, 3), CreateMockRead(*stream2_body, 4),
+ MockRead(ASYNC, ERR_IO_PENDING, 5), CreateMockRead(*stream3_syn, 6),
+ };
+
+ SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
+ NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
+ BoundNetLog(), GetParam(), nullptr);
+ helper.RunPreTestSetup();
+ helper.AddData(&data);
+
+ HttpNetworkTransaction* trans1 = helper.trans();
+ TestCompletionCallback callback1;
+ int rv =
+ trans1->Start(&CreateGetRequest(), callback1.callback(), BoundNetLog());
+ rv = callback1.GetResult(rv);
+ EXPECT_EQ(OK, rv);
+ HttpResponseInfo response = *trans1->GetResponseInfo();
+ EXPECT_TRUE(response.headers.get());
+ EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
+
+ scoped_ptr<HttpNetworkTransaction> trans2(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
+ TestCompletionCallback callback2;
+ rv = trans2->Start(&CreateGetPushRequest(), callback2.callback(),
+ BoundNetLog());
+ rv = callback2.GetResult(rv);
+ EXPECT_EQ(OK, rv);
+ response = *trans2->GetResponseInfo();
+ EXPECT_TRUE(response.headers.get());
+ EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
+ std::string result;
+ ReadResult(trans2.get(), &result);
+ EXPECT_EQ(kPushedData, result);
+
+ data.Resume();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(data.AllReadDataConsumed());
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+}
+
// Verify that various SynReply headers parse correctly through the
// HTTP layer.
TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
@@ -3024,7 +3264,7 @@ TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
test_cases[2].expected_headers["status"] = "200";
// HTTP/2 eliminates use of the :version header.
- if (spdy_util_.spdy_version() < HTTP2) {
+ if (GetParam().protocol == kProtoSPDY31) {
test_cases[0].expected_headers["version"] = "HTTP/1.1";
test_cases[1].expected_headers["version"] = "HTTP/1.1";
test_cases[2].expected_headers["version"] = "HTTP/1.1";
@@ -3038,16 +3278,18 @@ TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
test_cases[2].expected_headers["cookie"] = "val1,val2";
for (size_t i = 0; i < arraysize(test_cases); ++i) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ SpdyTestUtil spdy_test_util(GetParam().protocol,
+ GetParam().priority_to_dependency);
+ spdy_test_util.set_default_url(GURL(GetDefaultUrl()));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> resp(
- spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
- test_cases[i].num_headers,
- 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
- spdy_util_.UpdateWithStreamDestruction(1);
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_test_util.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
+ test_cases[i].num_headers, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_test_util.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -3067,7 +3309,7 @@ TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
EXPECT_TRUE(headers.get() != NULL);
- void* iter = NULL;
+ size_t iter = 0;
std::string name, value;
SpdyHeaderBlock header_block;
while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
@@ -3126,11 +3368,14 @@ TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
"friend,enemy", NULL}}}};
for (size_t i = 0; i < arraysize(test_cases); ++i) {
+ SpdyTestUtil spdy_test_util(GetParam().protocol,
+ GetParam().priority_to_dependency);
+ spdy_test_util.set_default_url(GURL(GetDefaultUrl()));
+
// Construct the request.
- scoped_ptr<SpdyFrame> frame_req(
- spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
- test_cases[i].num_headers[0],
- false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> frame_req(spdy_test_util.ConstructSpdyGet(
+ test_cases[i].extra_headers[0], test_cases[i].num_headers[0], 1, LOWEST,
+ true));
MockWrite writes[] = {
CreateMockWrite(*frame_req, 0),
@@ -3141,11 +3386,11 @@ TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
AppendToHeaderBlock(test_cases[i].extra_headers[1],
test_cases[i].num_headers[1],
&reply_headers);
- scoped_ptr<SpdyFrame> frame_reply(
- spdy_util_.ConstructSpdyReply(1, reply_headers));
+ scoped_ptr<SpdySerializedFrame> frame_reply(
+ spdy_test_util.ConstructSpdyReply(1, reply_headers));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
- spdy_util_.UpdateWithStreamDestruction(1);
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_test_util.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*frame_reply, 1),
CreateMockRead(*body, 2),
@@ -3180,7 +3425,7 @@ TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
// Check the headers.
scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
ASSERT_TRUE(headers.get() != NULL) << i;
- void* iter = NULL;
+ size_t iter = 0;
std::string name, value, lines;
while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
lines.append(name);
@@ -3191,7 +3436,7 @@ TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
// Construct the expected header reply string.
std::string expected_reply =
- spdy_util_.ConstructSpdyReplyString(reply_headers);
+ spdy_test_util.ConstructSpdyReplyString(reply_headers);
EXPECT_EQ(expected_reply, lines) << i;
}
}
@@ -3219,11 +3464,14 @@ TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
};
for (size_t i = 0; i < arraysize(test_cases); ++i) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
- spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
- spdy_util_.UpdateWithStreamDestruction(1);
+ SpdyTestUtil spdy_test_util(GetParam().protocol,
+ GetParam().priority_to_dependency);
+ spdy_test_util.set_default_url(GURL(GetDefaultUrl()));
+
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
+ spdy_test_util.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
};
@@ -3232,7 +3480,8 @@ TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
SpdyHeaderBlock reply_headers;
AppendToHeaderBlock(
test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, reply_headers));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_test_util.ConstructSpdyReply(1, reply_headers));
MockRead reads[] = {
CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 3) // EOF
};
@@ -3247,81 +3496,67 @@ TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
}
}
-// Verify that we don't crash on some corrupt frames.
-// TODO(jgraettinger): HTTP/2 treats a header decompression failure as a
-// connection error. I'd like to backport this behavior to SPDY3 as well.
TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
- if (spdy_util_.spdy_version() >= HTTP2) {
+ if (spdy_util_.spdy_version() != SPDY3) {
return;
}
+
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(
+ 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
+ MockWrite writes[] = {
+ CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
+ };
+
// This is the length field that's too short.
- scoped_ptr<SpdyFrame> syn_reply_wrong_length(
- spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ scoped_ptr<SpdySerializedFrame> syn_reply_wrong_length(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
size_t right_size =
- (spdy_util_.spdy_version() < HTTP2)
- ? syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize()
- : syn_reply_wrong_length->size();
+ syn_reply_wrong_length->size() -
+ SpdyConstants::GetControlFrameHeaderSize(spdy_util_.spdy_version());
size_t wrong_size = right_size - 4;
test::SetFrameLength(syn_reply_wrong_length.get(),
wrong_size,
spdy_util_.spdy_version());
-
- struct SynReplyTests {
- const SpdyFrame* syn_reply;
- } test_cases[] = {
- { syn_reply_wrong_length.get(), },
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+ MockRead reads[] = {
+ MockRead(ASYNC, syn_reply_wrong_length->data(),
+ syn_reply_wrong_length->size(), 1),
+ CreateMockRead(*body, 2),
};
- for (size_t i = 0; i < arraysize(test_cases); ++i) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
- spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
- MockWrite writes[] = {
- CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
- };
-
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
- MockRead reads[] = {
- MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size, 1),
- CreateMockRead(*body, 2),
- MockRead(ASYNC, 0, 4) // EOF
- };
-
- SequencedSocketData data(reads, arraysize(reads), writes,
- arraysize(writes));
- NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- BoundNetLog(), GetParam(), NULL);
- helper.RunToCompletion(&data);
- TransactionHelperResult out = helper.output();
- EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
- }
+ SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
+ NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
+ BoundNetLog(), GetParam(), nullptr);
+ helper.RunToCompletion(&data);
+ TransactionHelperResult out = helper.output();
+ EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
}
-// HTTP/2 treats a header decompression failure as a connection-level error.
TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
- if (spdy_util_.spdy_version() < HTTP2) {
+ if (spdy_util_.spdy_version() != HTTP2) {
return;
}
+
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(
+ 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
+ MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
+
// This is the length field that's too short.
- scoped_ptr<SpdyFrame> syn_reply_wrong_length(
- spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ scoped_ptr<SpdySerializedFrame> syn_reply_wrong_length(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
size_t right_size =
- syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize();
+ syn_reply_wrong_length->size() -
+ SpdyConstants::GetControlFrameHeaderSize(spdy_util_.spdy_version());
size_t wrong_size = right_size - 4;
test::SetFrameLength(syn_reply_wrong_length.get(),
wrong_size,
spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
- 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
- MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
-
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
MockRead(ASYNC, syn_reply_wrong_length->data(),
syn_reply_wrong_length->size() - 4, 1),
@@ -3337,18 +3572,19 @@ TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
if (GetParam().protocol < kProtoHTTP2) {
- // Decompression failures are a stream error in SPDY3 and above.
+ // Decompression failures are a stream error in SPDY3.
return;
}
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(
0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
// Read HEADERS with corrupted payload.
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- memset(resp->data() + 12, 0xff, resp->size() - 12);
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ memset(resp->data() + 12, 0xcf, resp->size() - 12);
MockRead reads[] = {CreateMockRead(*resp, 1)};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -3360,16 +3596,15 @@ TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
}
TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
- 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(
+ 0, GOAWAY_FRAME_SIZE_ERROR,
+ "Framer error: 12 (INVALID_CONTROL_FRAME_SIZE)."));
MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
// Read WINDOW_UPDATE with incorrectly-sized payload.
- // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
- // which is mapped to a protocol error, and not a frame size error.
- scoped_ptr<SpdyFrame> bad_window_update(
+ scoped_ptr<SpdySerializedFrame> bad_window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, 1));
test::SetFrameLength(bad_window_update.get(),
bad_window_update->size() - 1,
@@ -3381,13 +3616,13 @@ TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
helper.RunToCompletion(&data);
TransactionHelperResult out = helper.output();
- EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
+ EXPECT_EQ(ERR_SPDY_FRAME_SIZE_ERROR, out.rv);
}
// Test that we shutdown correctly on write errors.
TEST_P(SpdyNetworkTransactionTest, WriteError) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
// We'll write 10 bytes successfully
MockWrite(ASYNC, req->data(), 10, 1),
@@ -3416,16 +3651,18 @@ TEST_P(SpdyNetworkTransactionTest, WriteError) {
// Test that partial writes work.
TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
// Chop the SYN_STREAM frame into 5 chunks.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
const int kChunks = 5;
scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
for (int i = 0; i < kChunks; ++i) {
writes[i].sequence_number = i;
}
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, kChunks),
CreateMockRead(*body, kChunks + 1),
@@ -3442,49 +3679,19 @@ TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
EXPECT_EQ("hello!", out.response_data);
}
-// In this test, we enable compression, but get a uncompressed SynReply from
-// the server. Verify that teardown is all clean.
-TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
- if (spdy_util_.spdy_version() >= HTTP2) {
- // HPACK doesn't use deflate compression.
- return;
- }
- scoped_ptr<SpdyFrame> compressed(
- spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
- 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
- MockWrite writes[] = {CreateMockWrite(*compressed, 0),
- CreateMockWrite(*goaway, 2)};
-
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
- MockRead reads[] = {
- CreateMockRead(*resp, 1),
- };
-
- SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
- scoped_ptr<SpdySessionDependencies> session_deps =
- CreateSpdySessionDependencies(GetParam());
- session_deps->enable_compression = true;
- NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
- BoundNetLog(), GetParam(),
- std::move(session_deps));
- helper.RunToCompletion(&data);
- TransactionHelperResult out = helper.output();
- EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
-}
-
// Test that the NetLog contains good data for a simple GET request.
TEST_P(SpdyNetworkTransactionTest, NetLog) {
static const char* const kExtraHeaders[] = {
"user-agent", "Chrome",
};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -3568,29 +3775,29 @@ TEST_P(SpdyNetworkTransactionTest, NetLog) {
// on the network, but issued a Read for only 5 of those bytes) that the data
// flow still works correctly.
TEST_P(SpdyNetworkTransactionTest, BufferFull) {
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
// 2 data frames in a single read.
- scoped_ptr<SpdyFrame> data_frame_1(
+ scoped_ptr<SpdySerializedFrame> data_frame_1(
framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> data_frame_2(
+ scoped_ptr<SpdySerializedFrame> data_frame_2(
framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
- const SpdyFrame* data_frames[2] = {
- data_frame_1.get(),
- data_frame_2.get(),
+ const SpdySerializedFrame* data_frames[2] = {
+ data_frame_1.get(), data_frame_2.get(),
};
char combined_data_frames[100];
int combined_data_frames_len =
CombineFrames(data_frames, arraysize(data_frames),
combined_data_frames, arraysize(combined_data_frames));
- scoped_ptr<SpdyFrame> last_frame(
+ scoped_ptr<SpdySerializedFrame> last_frame(
framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead reads[] = {
CreateMockRead(*resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
@@ -3661,29 +3868,27 @@ TEST_P(SpdyNetworkTransactionTest, BufferFull) {
// at the same time, ensure that we don't notify a read completion for
// each data frame individually.
TEST_P(SpdyNetworkTransactionTest, Buffering) {
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
// 4 data frames in a single read.
- scoped_ptr<SpdyFrame> data_frame(
+ scoped_ptr<SpdySerializedFrame> data_frame(
framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> data_frame_fin(
+ scoped_ptr<SpdySerializedFrame> data_frame_fin(
framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
- const SpdyFrame* data_frames[4] = {
- data_frame.get(),
- data_frame.get(),
- data_frame.get(),
- data_frame_fin.get()
- };
+ const SpdySerializedFrame* data_frames[4] = {
+ data_frame.get(), data_frame.get(), data_frame.get(),
+ data_frame_fin.get()};
char combined_data_frames[100];
int combined_data_frames_len =
CombineFrames(data_frames, arraysize(data_frames),
combined_data_frames, arraysize(combined_data_frames));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead reads[] = {
CreateMockRead(*resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause
@@ -3755,20 +3960,22 @@ TEST_P(SpdyNetworkTransactionTest, Buffering) {
// Verify the case where we buffer data but read it after it has been buffered.
TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
// 5 data frames in a single read.
- scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> data_frame(
+ scoped_ptr<SpdySerializedFrame> reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> data_frame(
framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> data_frame_fin(
+ scoped_ptr<SpdySerializedFrame> data_frame_fin(
framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
- const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
- data_frame.get(), data_frame_fin.get()};
+ const SpdySerializedFrame* frames[5] = {reply.get(), data_frame.get(),
+ data_frame.get(), data_frame.get(),
+ data_frame_fin.get()};
char combined_frames[200];
int combined_frames_len =
CombineFrames(frames, arraysize(frames),
@@ -3839,27 +4046,24 @@ TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
// Verify the case where we buffer data and close the connection.
TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
// All data frames in a single read.
// NOTE: We don't FIN the stream.
- scoped_ptr<SpdyFrame> data_frame(
+ scoped_ptr<SpdySerializedFrame> data_frame(
framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
- const SpdyFrame* data_frames[4] = {
- data_frame.get(),
- data_frame.get(),
- data_frame.get(),
- data_frame.get()
- };
+ const SpdySerializedFrame* data_frames[4] = {
+ data_frame.get(), data_frame.get(), data_frame.get(), data_frame.get()};
char combined_data_frames[100];
int combined_data_frames_len =
CombineFrames(data_frames, arraysize(data_frames),
combined_data_frames, arraysize(combined_data_frames));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead reads[] = {
CreateMockRead(*resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
@@ -3929,19 +4133,20 @@ TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
// Verify the case where we buffer data and cancel the transaction.
TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4)};
// NOTE: We don't FIN the stream.
- scoped_ptr<SpdyFrame> data_frame(
+ scoped_ptr<SpdySerializedFrame> data_frame(
framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead reads[] = {
CreateMockRead(*resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait
@@ -4009,7 +4214,6 @@ TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
ConvertRequestPriorityToSpdyPriority(
LOWEST, spdy_util_.spdy_version()),
CONTROL_FLAG_NONE, // Control Flags
- false, // Compressed
RST_STREAM_INVALID, // Status
NULL, // Data
0, // Data Length
@@ -4028,15 +4232,15 @@ TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
host_port_pair).empty());
// Construct the request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
// Construct the reply.
scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
(*reply_headers)[spdy_util_.GetStatusKey()] = "200";
(*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
- scoped_ptr<SpdyFrame> reply(
+ scoped_ptr<SpdySerializedFrame> reply(
spdy_util_.ConstructSpdyFrame(kSynReplyInfo, std::move(reply_headers)));
const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
@@ -4045,7 +4249,7 @@ TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
unsigned int kSampleValue2 = 0x0b0b0b0b;
const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
unsigned int kSampleValue3 = 0x0c0c0c0c;
- scoped_ptr<SpdyFrame> settings_frame;
+ scoped_ptr<SpdySerializedFrame> settings_frame;
{
// Construct the SETTINGS frame.
SettingsMap settings;
@@ -4061,7 +4265,8 @@ TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
}
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*reply, 1),
CreateMockRead(*body, 2),
@@ -4115,7 +4320,6 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
ConvertRequestPriorityToSpdyPriority(
LOWEST, spdy_util_.spdy_version()),
CONTROL_FLAG_NONE, // Control Flags
- false, // Compressed
RST_STREAM_INVALID, // Status
NULL, // Data
0, // Data Length
@@ -4163,19 +4367,19 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
SettingsMap initial_settings;
initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
- scoped_ptr<SpdyFrame> initial_settings_frame(
+ scoped_ptr<SpdySerializedFrame> initial_settings_frame(
spdy_util_.ConstructSpdySettings(initial_settings));
// Construct the persisted SETTINGS frame.
const SettingsMap& settings =
spdy_session_pool->http_server_properties()->GetSpdySettings(
host_port_pair);
- scoped_ptr<SpdyFrame> settings_frame(
+ scoped_ptr<SpdySerializedFrame> settings_frame(
spdy_util_.ConstructSpdySettings(settings));
// Construct the request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*initial_settings_frame, 0),
@@ -4187,10 +4391,11 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
(*reply_headers)[spdy_util_.GetStatusKey()] = "200";
(*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
- scoped_ptr<SpdyFrame> reply(
+ scoped_ptr<SpdySerializedFrame> reply(
spdy_util_.ConstructSpdyFrame(kSynReplyInfo, std::move(reply_headers)));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*reply, 3),
CreateMockRead(*body, 4),
@@ -4230,11 +4435,11 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
}
TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
+ scoped_ptr<SpdySerializedFrame> go_away(spdy_util_.ConstructSpdyGoAway());
MockRead reads[] = {
CreateMockRead(*go_away, 1),
};
@@ -4249,11 +4454,12 @@ TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
}
TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
MockRead reads[] = {
CreateMockRead(*resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
};
@@ -4293,7 +4499,7 @@ TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredError) {
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
BoundNetLog(), GetParam(), nullptr);
- scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
+ scoped_ptr<SpdySerializedFrame> go_away(spdy_util_.ConstructSpdyGoAway(
0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
MockRead reads[] = {
CreateMockRead(*go_away, 0),
@@ -4323,17 +4529,16 @@ TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
scoped_ptr<SpdySessionDependencies> session_deps(
CreateSpdySessionDependencies(GetParam()));
// Do not force SPDY so that second socket can negotiate HTTP/1.1.
- session_deps->next_protos = SpdyNextProtos();
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
GetParam(), std::move(session_deps));
// First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
const char* url = request.url.spec().c_str();
scoped_ptr<SpdyHeaderBlock> headers(spdy_util_.ConstructGetHeaderBlock(url));
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, true));
MockWrite writes0[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
+ scoped_ptr<SpdySerializedFrame> go_away(spdy_util_.ConstructSpdyGoAway(
0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
MockRead reads0[] = {CreateMockRead(*go_away, 1)};
SequencedSocketData data0(reads0, arraysize(reads0), writes0,
@@ -4342,9 +4547,9 @@ TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
scoped_ptr<SSLSocketDataProvider> ssl_provider0(
new SSLSocketDataProvider(ASYNC, OK));
// Expect HTTP/2 protocols too in SSLConfig.
- ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
- ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP2);
+ ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
+ ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
// Force SPDY.
ssl_provider0->SetNextProto(GetParam().protocol);
helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
@@ -4415,15 +4620,14 @@ TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
GetParam(),
ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")));
// Do not force SPDY so that second socket can negotiate HTTP/1.1.
- session_deps->next_protos = SpdyNextProtos();
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
GetParam(), std::move(session_deps));
// First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyConnect(
nullptr, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
MockWrite writes0[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
+ scoped_ptr<SpdySerializedFrame> go_away(spdy_util_.ConstructSpdyGoAway(
0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
MockRead reads0[] = {CreateMockRead(*go_away, 1)};
SequencedSocketData data0(reads0, arraysize(reads0), writes0,
@@ -4432,9 +4636,9 @@ TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
scoped_ptr<SSLSocketDataProvider> ssl_provider0(
new SSLSocketDataProvider(ASYNC, OK));
// Expect HTTP/2 protocols too in SSLConfig.
- ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
- ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP2);
+ ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
+ ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
// Force SPDY.
ssl_provider0->SetNextProto(GetParam().protocol);
helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
@@ -4517,10 +4721,12 @@ TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
"Host: www.example.org:443\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"};
const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
@@ -4579,14 +4785,16 @@ TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
helper.RunPreTestSetup();
// Construct and send a simple GET request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -4636,10 +4844,12 @@ TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
"Host: www.example.org:443\r\n"
"Proxy-Connection: keep-alive\r\n\r\n"};
const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
- scoped_ptr<SpdyFrame> req2(spdy_util_2.ConstructSpdyGet(
- GetDefaultUrlWithPath("/foo.dat").c_str(), false, 1, LOWEST));
- scoped_ptr<SpdyFrame> resp2(spdy_util_2.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body2(spdy_util_2.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> req2(spdy_util_2.ConstructSpdyGet(
+ GetDefaultUrlWithPath("/foo.dat").c_str(), 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_2.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_2.ConstructSpdyBodyFrame(1, true));
MockWrite writes2[] = {
MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
@@ -4700,8 +4910,10 @@ TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
// This can happen when a server reboots without saying goodbye, or when
// we're behind a NAT that masked the RST.
TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -4715,13 +4927,13 @@ TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
MockRead(ASYNC, 0, 3) // EOF
};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
// In all cases the connection will be reset before req3 can be
// dispatched, destroying both streams.
spdy_util_.UpdateWithStreamDestruction(1);
- scoped_ptr<SpdyFrame> req3(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req3(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
MockWrite writes1[] = {CreateMockWrite(*req, 0), CreateMockWrite(*req3, 5)};
MockWrite writes2[] = {CreateMockWrite(*req, 0)};
@@ -4790,12 +5002,14 @@ TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
// Test that turning SPDY on and off works properly.
TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
HttpStreamFactory::set_spdy_enabled(true);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -4845,17 +5059,17 @@ TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
// The first request will be a bare GET, the second request will be a
// GET with an Authorization header.
- scoped_ptr<SpdyFrame> req_get(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req_get(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
// Will be refused for lack of auth.
spdy_util_.UpdateWithStreamDestruction(1);
const char* const kExtraAuthorizationHeaders[] = {
"authorization", "Basic Zm9vOmJhcg=="
};
- scoped_ptr<SpdyFrame> req_get_authorization(
+ scoped_ptr<SpdySerializedFrame> req_get_authorization(
spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
- arraysize(kExtraAuthorizationHeaders) / 2,
- false, 3, LOWEST, true));
+ arraysize(kExtraAuthorizationHeaders) / 2, 3,
+ LOWEST, true));
MockWrite spdy_writes[] = {
CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
};
@@ -4867,17 +5081,16 @@ TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
"www-authenticate",
"Basic realm=\"MyRealm\""
};
- scoped_ptr<SpdyFrame> resp_authentication(
+ scoped_ptr<SpdySerializedFrame> resp_authentication(
spdy_util_.ConstructSpdySynReplyError(
- "401 Authentication Required",
- kExtraAuthenticationHeaders,
- arraysize(kExtraAuthenticationHeaders) / 2,
- 1));
- scoped_ptr<SpdyFrame> body_authentication(
+ "401 Authentication Required", kExtraAuthenticationHeaders,
+ arraysize(kExtraAuthenticationHeaders) / 2, 1));
+ scoped_ptr<SpdySerializedFrame> body_authentication(
spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> resp_data(
+ scoped_ptr<SpdySerializedFrame> resp_data(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
+ scoped_ptr<SpdySerializedFrame> body_data(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead spdy_reads[] = {
CreateMockRead(*resp_authentication, 1),
CreateMockRead(*body_authentication, 2),
@@ -4933,34 +5146,37 @@ TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
}
TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
- spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0),
};
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+
scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
initial_headers.get());
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
- std::move(initial_headers), 2, 1));
-
- scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
- (*late_headers)[spdy_util_.GetStatusKey()] = "200";
- (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
- (*late_headers)["hello"] = "bye";
- scoped_ptr<SpdyFrame> stream2_headers(spdy_util_.ConstructSpdyControlFrame(
- std::move(late_headers), false, 2, LOWEST, HEADERS, CONTROL_FLAG_NONE,
- 0));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(
+ spdy_util_.ConstructInitialSpdyPushFrame(std::move(initial_headers), 2,
+ 1));
+
+ SpdyHeaderBlock late_headers;
+ late_headers[spdy_util_.GetStatusKey()] = "200";
+ late_headers[spdy_util_.GetVersionKey()] = "HTTP/1.1";
+ late_headers["hello"] = "bye";
+ scoped_ptr<SpdySerializedFrame> stream2_headers(
+ spdy_util_.ConstructSpdyResponseHeaders(2, late_headers, false));
+
+ scoped_ptr<SpdySerializedFrame> stream1_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
const char kPushedData[] = "pushed";
- scoped_ptr<SpdyFrame> stream2_body(
- spdy_util_.ConstructSpdyBodyFrame(
- 2, kPushedData, strlen(kPushedData), true));
+ scoped_ptr<SpdySerializedFrame> stream2_body(
+ spdy_util_.ConstructSpdyBodyFrame(2, kPushedData, strlen(kPushedData),
+ true));
+
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1),
CreateMockRead(*stream2_syn, 2),
@@ -4990,34 +5206,32 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
// We push a stream and attempt to claim it before the headers come down.
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
- spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
};
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
initial_headers.get());
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
- std::move(initial_headers), 2, 1));
-
- scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
- (*late_headers)[spdy_util_.GetStatusKey()] = "200";
- (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
- (*late_headers)["hello"] = "bye";
- scoped_ptr<SpdyFrame> stream2_headers(spdy_util_.ConstructSpdyControlFrame(
- std::move(late_headers), false, 2, LOWEST, HEADERS, CONTROL_FLAG_NONE,
- 0));
-
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(
+ spdy_util_.ConstructInitialSpdyPushFrame(std::move(initial_headers), 2,
+ 1));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+ SpdyHeaderBlock late_headers;
+ late_headers[spdy_util_.GetStatusKey()] = "200";
+ late_headers[spdy_util_.GetVersionKey()] = "HTTP/1.1";
+ late_headers["hello"] = "bye";
+ scoped_ptr<SpdySerializedFrame> stream2_headers(
+ spdy_util_.ConstructSpdyResponseHeaders(2, late_headers, false));
const char kPushedData[] = "pushed";
- scoped_ptr<SpdyFrame> stream2_body(
- spdy_util_.ConstructSpdyBodyFrame(
- 2, kPushedData, strlen(kPushedData), true));
+ scoped_ptr<SpdySerializedFrame> stream2_body(
+ spdy_util_.ConstructSpdyBodyFrame(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),
@@ -5100,14 +5314,15 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
// TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
// We push a stream and attempt to claim it before the headers come down.
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
- spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
};
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+
scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
if (spdy_util_.spdy_version() < HTTP2) {
// In HTTP/2 PUSH_PROMISE headers won't show up in the response headers.
@@ -5115,31 +5330,32 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
}
spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
initial_headers.get());
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
- std::move(initial_headers), 2, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(
+ spdy_util_.ConstructInitialSpdyPushFrame(std::move(initial_headers), 2,
+ 1));
- scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
- (*middle_headers)["hello"] = "bye";
- scoped_ptr<SpdyFrame> stream2_headers1(spdy_util_.ConstructSpdyControlFrame(
- std::move(middle_headers), false, 2, LOWEST, HEADERS, CONTROL_FLAG_NONE,
- 0));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+
+ SpdyHeaderBlock middle_headers;
+ middle_headers["hello"] = "bye";
+ scoped_ptr<SpdySerializedFrame> stream2_headers1(
+ spdy_util_.ConstructSpdyResponseHeaders(2, middle_headers, false));
- scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
- (*late_headers)[spdy_util_.GetStatusKey()] = "200";
+ SpdyHeaderBlock late_headers;
+ late_headers[spdy_util_.GetStatusKey()] = "200";
if (spdy_util_.spdy_version() < HTTP2) {
// HTTP/2 eliminates use of the :version header.
- (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
+ late_headers[spdy_util_.GetVersionKey()] = "HTTP/1.1";
}
- scoped_ptr<SpdyFrame> stream2_headers2(spdy_util_.ConstructSpdyControlFrame(
- std::move(late_headers), false, 2, LOWEST, HEADERS, CONTROL_FLAG_NONE,
- 0));
+ scoped_ptr<SpdySerializedFrame> stream2_headers2(
+ spdy_util_.ConstructSpdyResponseHeaders(2, late_headers, false));
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
const char kPushedData[] = "pushed";
- scoped_ptr<SpdyFrame> stream2_body(
- spdy_util_.ConstructSpdyBodyFrame(
- 2, kPushedData, strlen(kPushedData), true));
+ scoped_ptr<SpdySerializedFrame> stream2_body(
+ spdy_util_.ConstructSpdyBodyFrame(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),
@@ -5230,32 +5446,35 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
// We push a stream and attempt to claim it before the headers come down.
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> stream1_body(
- spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
};
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+
scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
initial_headers.get());
- scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
- std::move(initial_headers), 2, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(
+ spdy_util_.ConstructInitialSpdyPushFrame(std::move(initial_headers), 2,
+ 1));
- scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
- (*middle_headers)["hello"] = "bye";
- scoped_ptr<SpdyFrame> stream2_headers1(spdy_util_.ConstructSpdyControlFrame(
- std::move(middle_headers), false, 2, LOWEST, HEADERS, CONTROL_FLAG_NONE,
- 0));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+
+ SpdyHeaderBlock middle_headers;
+ middle_headers["hello"] = "bye";
+ scoped_ptr<SpdySerializedFrame> stream2_headers1(
+ spdy_util_.ConstructSpdyResponseHeaders(2, middle_headers, false));
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
const char kPushedData[] = "pushed";
- scoped_ptr<SpdyFrame> stream2_body(
- spdy_util_.ConstructSpdyBodyFrame(
- 2, kPushedData, strlen(kPushedData), true));
+ scoped_ptr<SpdySerializedFrame> stream2_body(
+ spdy_util_.ConstructSpdyBodyFrame(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),
@@ -5325,23 +5544,22 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
}
TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
};
- scoped_ptr<SpdyFrame> stream1_reply(
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
- (*late_headers)["hello"] = "bye";
- scoped_ptr<SpdyFrame> stream1_headers(spdy_util_.ConstructSpdyControlFrame(
- std::move(late_headers), false, 1, LOWEST, HEADERS, CONTROL_FLAG_NONE,
- 0));
- scoped_ptr<SpdyFrame> stream1_body(
+ SpdyHeaderBlock late_headers;
+ late_headers["hello"] = "bye";
+ scoped_ptr<SpdySerializedFrame> stream1_headers(
+ spdy_util_.ConstructSpdyResponseHeaders(1, late_headers, false));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1),
@@ -5362,25 +5580,24 @@ TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
// trigger a ERR_SPDY_PROTOCOL_ERROR because trailing HEADERS must not be
// followed by any DATA frames.
TEST_P(SpdyNetworkTransactionTest, SyncReplyDataAfterTrailers) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
};
- scoped_ptr<SpdyFrame> stream1_reply(
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
-
- scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
- (*late_headers)["hello"] = "bye";
- scoped_ptr<SpdyFrame> stream1_headers(spdy_util_.ConstructSpdyControlFrame(
- std::move(late_headers), false, 1, LOWEST, HEADERS, CONTROL_FLAG_NONE,
- 0));
- scoped_ptr<SpdyFrame> stream1_body(
+ scoped_ptr<SpdySerializedFrame> stream1_body(
spdy_util_.ConstructSpdyBodyFrame(1, false));
- scoped_ptr<SpdyFrame> stream1_body2(
+
+ SpdyHeaderBlock late_headers;
+ late_headers["hello"] = "bye";
+ scoped_ptr<SpdySerializedFrame> stream1_headers(
+ spdy_util_.ConstructSpdyResponseHeaders(1, late_headers, false));
+ scoped_ptr<SpdySerializedFrame> stream1_body2(
spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1), CreateMockRead(*stream1_body, 2),
@@ -5410,9 +5627,6 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
// A list of the URL to fetch, followed by the URL being pushed.
static const char* const kTestCases[] = {
"https://www.example.org/foo.html",
- "https://www.example.org:81/foo.js", // Bad port
-
- "https://www.example.org/foo.html",
"http://www.example.org/foo.js", // Bad protocol
"https://www.example.org/foo.html",
@@ -5429,31 +5643,28 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
const char* url_to_fetch = kTestCases[index];
const char* url_to_push = kTestCases[index + 1];
- scoped_ptr<SpdyFrame> stream1_syn(
- spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
- scoped_ptr<SpdyFrame> stream1_body(
- spdy_util_.ConstructSpdyBodyFrame(1, true));
- spdy_util_.UpdateWithStreamDestruction(1);
- scoped_ptr<SpdyFrame> push_rst(
- spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
+ SpdyTestUtil spdy_test_util(GetParam().protocol,
+ GetParam().priority_to_dependency);
+ scoped_ptr<SpdySerializedFrame> stream1_syn(
+ spdy_test_util.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> stream1_body(
+ spdy_test_util.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> push_rst(
+ spdy_test_util.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
MockWrite writes[] = {
CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*push_rst, 3),
};
- scoped_ptr<SpdyFrame>
- stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame>
- stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
- 0,
- 2,
- 1,
- url_to_push));
+ scoped_ptr<SpdySerializedFrame> stream1_reply(
+ spdy_test_util.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> stream2_syn(
+ spdy_test_util.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
const char kPushedData[] = "pushed";
- scoped_ptr<SpdyFrame> stream2_body(
- spdy_util_.ConstructSpdyBodyFrame(
- 2, kPushedData, strlen(kPushedData), true));
- scoped_ptr<SpdyFrame> rst(
- spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
+ scoped_ptr<SpdySerializedFrame> stream2_body(
+ spdy_test_util.ConstructSpdyBodyFrame(2, kPushedData,
+ strlen(kPushedData), true));
+ scoped_ptr<SpdySerializedFrame> rst(
+ spdy_test_util.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
MockRead reads[] = {
CreateMockRead(*stream1_reply, 1),
@@ -5476,7 +5687,10 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
// not actually enable cross-origin SPDY push.
scoped_ptr<SpdySessionDependencies> session_deps(
CreateSpdySessionDependencies(GetParam()));
- session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
+ scoped_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());
NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
GetParam(), std::move(session_deps));
helper.RunPreTestSetup();
@@ -5511,22 +5725,345 @@ TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
}
}
+// Verify that push works cross origin as long as the certificate is valid for
+// the pushed authority.
+TEST_P(SpdyNetworkTransactionTest, ServerPushValidCrossOrigin) {
+ // "spdy_pooling.pem" is valid for both www.example.org and mail.example.org.
+ const char* url_to_fetch = "https://www.example.org";
+ const char* url_to_push = "https://mail.example.org";
+
+ scoped_ptr<SpdySerializedFrame> headers(
+ spdy_util_.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
+ MockWrite writes[] = {
+ CreateMockWrite(*headers, 0),
+ };
+
+ scoped_ptr<SpdySerializedFrame> reply(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> push(
+ spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+ const char kPushedData[] = "pushed";
+ scoped_ptr<SpdySerializedFrame> pushed_body(spdy_util_.ConstructSpdyBodyFrame(
+ 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),
+ };
+
+ SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL(url_to_fetch);
+ request.load_flags = 0;
+
+ BoundNetLog log;
+ NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, log, GetParam(),
+ nullptr);
+ helper.RunPreTestSetup();
+ helper.AddData(&data);
+
+ HttpNetworkTransaction* trans0 = helper.trans();
+ TestCompletionCallback callback0;
+ int rv = trans0->Start(&request, callback0.callback(), log);
+ rv = callback0.GetResult(rv);
+ EXPECT_EQ(OK, rv);
+
+ SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
+ HostPortPair host_port_pair("www.example.org", 443);
+ SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
+ PRIVACY_MODE_DISABLED);
+ base::WeakPtr<SpdySession> spdy_session =
+ spdy_session_pool->FindAvailableSession(key, GURL(), log);
+
+ EXPECT_FALSE(spdy_session->unclaimed_pushed_streams_.empty());
+ EXPECT_EQ(1u, spdy_session->unclaimed_pushed_streams_.size());
+ EXPECT_EQ(1u,
+ spdy_session->unclaimed_pushed_streams_.count(GURL(url_to_push)));
+
+ scoped_ptr<HttpNetworkTransaction> trans1(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
+ HttpRequestInfo push_request;
+ push_request.method = "GET";
+ push_request.url = GURL(url_to_push);
+ push_request.load_flags = 0;
+ TestCompletionCallback callback1;
+ rv = trans1->Start(&push_request, callback1.callback(), log);
+ rv = callback1.GetResult(rv);
+ EXPECT_EQ(OK, rv);
+
+ 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.get() != nullptr);
+ EXPECT_EQ("HTTP/1.1 200", response.headers->GetStatusLine());
+
+ std::string result0;
+ ReadResult(trans0, &result0);
+ EXPECT_EQ("hello!", result0);
+
+ HttpResponseInfo push_response = *trans1->GetResponseInfo();
+ EXPECT_TRUE(push_response.headers.get() != nullptr);
+ EXPECT_EQ("HTTP/1.1 200", push_response.headers->GetStatusLine());
+
+ std::string result1;
+ ReadResult(trans1.get(), &result1);
+ EXPECT_EQ(kPushedData, result1);
+}
+
+// Verify that push works cross origin, even if there is already a connection
+// open to origin of pushed resource.
+TEST_P(SpdyNetworkTransactionTest, ServerPushValidCrossOriginWithOpenSession) {
+ // Running this test via Alt-Svc is too complicated to be worthwhile.
+ if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
+ return;
+
+ const char* url_to_fetch0 = "https://mail.example.org/foo";
+ const char* url_to_fetch1 = "https://docs.example.org";
+ const char* url_to_push = "https://mail.example.org/bar";
+
+ SpdyTestUtil spdy_util_0(GetParam().protocol,
+ GetParam().priority_to_dependency);
+
+ scoped_ptr<SpdySerializedFrame> headers0(
+ spdy_util_0.ConstructSpdyGet(url_to_fetch0, 1, LOWEST));
+ MockWrite writes0[] = {
+ CreateMockWrite(*headers0, 0),
+ };
+
+ scoped_ptr<SpdySerializedFrame> reply0(
+ spdy_util_0.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ const char kData0[] = "first";
+ scoped_ptr<SpdySerializedFrame> body0(
+ spdy_util_0.ConstructSpdyBodyFrame(1, kData0, strlen(kData0), true));
+ MockRead reads0[] = {
+ CreateMockRead(*reply0, 1),
+ CreateMockRead(*body0, 2),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)
+ };
+
+ SequencedSocketData data0(reads0, arraysize(reads0), writes0,
+ arraysize(writes0));
+
+ SpdyTestUtil spdy_util_1(GetParam().protocol,
+ GetParam().priority_to_dependency);
+
+ scoped_ptr<SpdySerializedFrame> headers1(
+ spdy_util_1.ConstructSpdyGet(url_to_fetch1, 1, LOWEST));
+ MockWrite writes1[] = {
+ CreateMockWrite(*headers1, 0),
+ };
+
+ scoped_ptr<SpdySerializedFrame> reply1(
+ spdy_util_1.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> push(
+ spdy_util_1.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
+ const char kData1[] = "second";
+ scoped_ptr<SpdySerializedFrame> body1(
+ spdy_util_1.ConstructSpdyBodyFrame(1, kData1, strlen(kData1), true));
+ const char kPushedData[] = "pushed";
+ scoped_ptr<SpdySerializedFrame> pushed_body(
+ spdy_util_1.ConstructSpdyBodyFrame(2, kPushedData, strlen(kPushedData),
+ true));
+
+ MockRead reads1[] = {
+ CreateMockRead(*reply1, 1),
+ CreateMockRead(*push, 2),
+ CreateMockRead(*body1, 3),
+ CreateMockRead(*pushed_body, 4),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
+ };
+
+ SequencedSocketData data1(reads1, arraysize(reads1), writes1,
+ arraysize(writes1));
+
+ // Request |url_to_fetch0| to open connection to mail.example.org.
+ HttpRequestInfo request0;
+ request0.method = "GET";
+ request0.url = GURL(url_to_fetch0);
+ request0.load_flags = 0;
+
+ BoundNetLog log;
+ NormalSpdyTransactionHelper helper(request0, DEFAULT_PRIORITY, log,
+ GetParam(), nullptr);
+ helper.RunPreTestSetup();
+
+ // "spdy_pooling.pem" is valid for www.example.org, but not for
+ // docs.example.org.
+ scoped_ptr<SSLSocketDataProvider> ssl_provider0(
+ new SSLSocketDataProvider(ASYNC, OK));
+ ssl_provider0->cert =
+ ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
+ helper.AddDataWithSSLSocketDataProvider(&data0, std::move(ssl_provider0));
+
+ // "wildcard.pem" is valid for both www.example.org and docs.example.org.
+ scoped_ptr<SSLSocketDataProvider> ssl_provider1(
+ new SSLSocketDataProvider(ASYNC, OK));
+ ssl_provider1->cert =
+ ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
+ helper.AddDataWithSSLSocketDataProvider(&data1, std::move(ssl_provider1));
+
+ HttpNetworkTransaction* trans0 = helper.trans();
+ TestCompletionCallback callback0;
+ int rv = trans0->Start(&request0, callback0.callback(), log);
+ rv = callback0.GetResult(rv);
+ EXPECT_EQ(OK, rv);
+
+ // Request |url_to_fetch1|, during which docs.example.org pushes
+ // |url_to_push|, which happens to be for www.example.org, to which there is
+ // already an open connection.
+ scoped_ptr<HttpNetworkTransaction> trans1(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
+ HttpRequestInfo request1;
+ request1.method = "GET";
+ request1.url = GURL(url_to_fetch1);
+ request1.load_flags = 0;
+ TestCompletionCallback callback1;
+ rv = trans1->Start(&request1, callback1.callback(), log);
+ rv = callback1.GetResult(rv);
+ EXPECT_EQ(OK, rv);
+
+ SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
+ HostPortPair host_port_pair0("mail.example.org", 443);
+ SpdySessionKey key0(host_port_pair0, ProxyServer::Direct(),
+ PRIVACY_MODE_DISABLED);
+ base::WeakPtr<SpdySession> spdy_session0 =
+ spdy_session_pool->FindAvailableSession(key0, GURL(), log);
+
+ EXPECT_TRUE(spdy_session0->unclaimed_pushed_streams_.empty());
+ EXPECT_EQ(0u, spdy_session0->unclaimed_pushed_streams_.size());
+
+ HostPortPair host_port_pair1("docs.example.org", 443);
+ SpdySessionKey key1(host_port_pair1, ProxyServer::Direct(),
+ PRIVACY_MODE_DISABLED);
+ base::WeakPtr<SpdySession> spdy_session1 =
+ spdy_session_pool->FindAvailableSession(key1, GURL(), log);
+
+ EXPECT_FALSE(spdy_session1->unclaimed_pushed_streams_.empty());
+ EXPECT_EQ(1u, spdy_session1->unclaimed_pushed_streams_.size());
+ EXPECT_EQ(1u,
+ spdy_session1->unclaimed_pushed_streams_.count(GURL(url_to_push)));
+
+ // Request |url_to_push|, which should be served from the pushed resource.
+ scoped_ptr<HttpNetworkTransaction> trans2(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session()));
+ HttpRequestInfo push_request;
+ push_request.method = "GET";
+ push_request.url = GURL(url_to_push);
+ push_request.load_flags = 0;
+ TestCompletionCallback callback2;
+ rv = trans2->Start(&push_request, callback2.callback(), log);
+ rv = callback2.GetResult(rv);
+ EXPECT_EQ(OK, rv);
+
+ EXPECT_TRUE(spdy_session0->unclaimed_pushed_streams_.empty());
+ EXPECT_EQ(0u, spdy_session0->unclaimed_pushed_streams_.size());
+
+ 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.get() != nullptr);
+ EXPECT_EQ("HTTP/1.1 200", response0.headers->GetStatusLine());
+
+ std::string result0;
+ ReadResult(trans0, &result0);
+ EXPECT_EQ(kData0, result0);
+
+ HttpResponseInfo response1 = *trans1->GetResponseInfo();
+ EXPECT_TRUE(response1.headers.get() != nullptr);
+ EXPECT_EQ("HTTP/1.1 200", response1.headers->GetStatusLine());
+
+ std::string result1;
+ ReadResult(trans1.get(), &result1);
+ EXPECT_EQ(kData1, result1);
+
+ HttpResponseInfo push_response = *trans2->GetResponseInfo();
+ EXPECT_TRUE(push_response.headers.get() != nullptr);
+ EXPECT_EQ("HTTP/1.1 200", push_response.headers->GetStatusLine());
+
+ std::string result2;
+ ReadResult(trans2.get(), &result2);
+ EXPECT_EQ(kPushedData, result2);
+}
+
+TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidCrossOrigin) {
+ // "spdy_pooling.pem" is valid for www.example.org,
+ // but not for invalid.example.org.
+ const char* url_to_fetch = "https://www.example.org";
+ const char* url_to_push = "https://invalid.example.org";
+
+ scoped_ptr<SpdySerializedFrame> headers(
+ spdy_util_.ConstructSpdyGet(url_to_fetch, 1, LOWEST));
+ scoped_ptr<SpdySerializedFrame> rst(
+ spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
+ MockWrite writes[] = {
+ CreateMockWrite(*headers, 0),
+ CreateMockWrite(*rst, 3),
+ };
+
+ scoped_ptr<SpdySerializedFrame> reply(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ scoped_ptr<SpdySerializedFrame> push(
+ spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, url_to_push));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+ const char kPushedData[] = "pushed";
+ scoped_ptr<SpdySerializedFrame> pushed_body(spdy_util_.ConstructSpdyBodyFrame(
+ 2, kPushedData, strlen(kPushedData), true));
+ MockRead reads[] = {
+ CreateMockRead(*reply, 1),
+ CreateMockRead(*push, 2),
+ CreateMockRead(*body, 4),
+ CreateMockRead(*pushed_body, 5),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
+ };
+
+ SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL(url_to_fetch);
+ request.load_flags = 0;
+
+ NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
+ GetParam(), nullptr);
+ helper.RunToCompletion(&data);
+ TransactionHelperResult out = helper.output();
+ EXPECT_EQ("HTTP/1.1 200", out.status_line);
+ EXPECT_EQ("hello!", out.response_data);
+}
+
TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
// Construct the request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
// Will be destroyed by the RST before stream 3 starts.
spdy_util_.UpdateWithStreamDestruction(1);
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*req2, 2),
};
- scoped_ptr<SpdyFrame> refused(
+ scoped_ptr<SpdySerializedFrame> refused(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead reads[] = {
CreateMockRead(*refused, 1),
CreateMockRead(*resp, 3),
@@ -5578,24 +6115,30 @@ TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
// req1 is alive when req2 is attempted (during but not after the
// |data.RunFor(2);| statement below) but not when req3 is attempted.
// The call to spdy_util_.UpdateWithStreamDestruction() reflects this.
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, HIGHEST, true));
spdy_util_.UpdateWithStreamDestruction(1);
- scoped_ptr<SpdyFrame> req3(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req3(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 5, MEDIUM, true));
MockWrite writes[] = {
MockWrite(ASYNC, ERR_IO_PENDING, 0), CreateMockWrite(*req1, 1),
CreateMockWrite(*req2, 5), CreateMockWrite(*req3, 6),
};
- scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
- scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
- scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
+ scoped_ptr<SpdySerializedFrame> resp1(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body1(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp2(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
+ scoped_ptr<SpdySerializedFrame> resp3(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
+ scoped_ptr<SpdySerializedFrame> body3(
+ spdy_util_.ConstructSpdyBodyFrame(5, true));
MockRead reads[] = {
CreateMockRead(*resp1, 2), MockRead(ASYNC, ERR_IO_PENDING, 3),
CreateMockRead(*body1, 4), CreateMockRead(*resp2, 7),
@@ -5681,15 +6224,13 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
static int kFrameCount = 2;
scoped_ptr<std::string> content(
new std::string(kMaxSpdyFrameChunkSize, 'a'));
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
GetDefaultUrl(), 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL,
0));
- scoped_ptr<SpdyFrame> body(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, content->c_str(), content->size(), false));
- scoped_ptr<SpdyFrame> body_end(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, content->c_str(), content->size(), true));
+ scoped_ptr<SpdySerializedFrame> body(spdy_util_.ConstructSpdyBodyFrame(
+ 1, content->c_str(), content->size(), false));
+ scoped_ptr<SpdySerializedFrame> body_end(spdy_util_.ConstructSpdyBodyFrame(
+ 1, content->c_str(), content->size(), true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
@@ -5699,11 +6240,12 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
static const int32_t kDeltaWindowSize = 0xff;
static const int kDeltaCount = 4;
- scoped_ptr<SpdyFrame> window_update(
+ scoped_ptr<SpdySerializedFrame> window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
- scoped_ptr<SpdyFrame> window_update_dummy(
+ scoped_ptr<SpdySerializedFrame> window_update_dummy(
spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
CreateMockRead(*window_update_dummy, 3),
CreateMockRead(*window_update_dummy, 4),
@@ -5801,17 +6343,17 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
initial_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, stream_max_recv_window_size);
- scoped_ptr<SpdyFrame> initial_settings_frame(
+ scoped_ptr<SpdySerializedFrame> initial_settings_frame(
spdy_util_.ConstructSpdySettings(initial_settings));
- scoped_ptr<SpdyFrame> initial_window_update(
+ scoped_ptr<SpdySerializedFrame> initial_window_update(
spdy_util_.ConstructSpdyWindowUpdate(
kSessionFlowControlStreamId,
session_max_recv_window_size - default_initial_window_size));
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> session_window_update(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> session_window_update(
spdy_util_.ConstructSpdyWindowUpdate(0, session_window_update_delta));
- scoped_ptr<SpdyFrame> stream_window_update(
+ scoped_ptr<SpdySerializedFrame> stream_window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, stream_window_update_delta));
std::vector<MockWrite> writes;
@@ -5824,11 +6366,11 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
writes.push_back(CreateMockWrite(*req, writes.size()));
std::vector<MockRead> reads;
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
reads.push_back(CreateMockRead(*resp, writes.size() + reads.size()));
- std::vector<scoped_ptr<SpdyFrame>> body_frames;
+ std::vector<scoped_ptr<SpdySerializedFrame>> body_frames;
const std::string body_data(kChunkSize, 'x');
for (size_t remaining = kTargetSize; remaining != 0;) {
size_t frame_size = std::min(remaining, body_data.size());
@@ -5906,13 +6448,12 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
scoped_ptr<std::string> content(
new std::string(kMaxSpdyFrameChunkSize, 'a'));
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
GetDefaultUrl(), 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL,
0));
- scoped_ptr<SpdyFrame> body(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, content->c_str(), content->size(), false));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> body(spdy_util_.ConstructSpdyBodyFrame(
+ 1, content->c_str(), content->size(), false));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
// We're not going to write a data frame with FIN, we'll receive a bad
@@ -5924,7 +6465,7 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
};
static const int32_t kDeltaWindowSize = 0x7fffffff; // cause an overflow
- scoped_ptr<SpdyFrame> window_update(
+ scoped_ptr<SpdySerializedFrame> window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
MockRead reads[] = {
CreateMockRead(*window_update, 1),
@@ -5992,22 +6533,21 @@ TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
// Construct content for a data frame of maximum size.
std::string content(kMaxSpdyFrameChunkSize, 'a');
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
0));
// Full frames.
- scoped_ptr<SpdyFrame> body1(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, content.c_str(), content.size(), false));
+ scoped_ptr<SpdySerializedFrame> body1(spdy_util_.ConstructSpdyBodyFrame(
+ 1, content.c_str(), content.size(), false));
// Last frame to zero out the window size.
- scoped_ptr<SpdyFrame> body2(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, content.c_str(), last_frame_size, false));
+ scoped_ptr<SpdySerializedFrame> body2(spdy_util_.ConstructSpdyBodyFrame(
+ 1, content.c_str(), last_frame_size, false));
// Data frame to be sent once WINDOW_UPDATE frame is received.
- scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body3(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
// Fill in mock writes.
scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
@@ -6022,11 +6562,12 @@ TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
// Construct read frame, give enough space to upload the rest of the
// data.
- scoped_ptr<SpdyFrame> session_window_update(
+ scoped_ptr<SpdySerializedFrame> session_window_update(
spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
- scoped_ptr<SpdyFrame> window_update(
+ scoped_ptr<SpdySerializedFrame> window_update(
spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
- scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> reply(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, i + 1), // Force a pause
CreateMockRead(*session_window_update, i + 2),
@@ -6098,22 +6639,21 @@ TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
// Construct content for a data frame of maximum size.
std::string content(kMaxSpdyFrameChunkSize, 'a');
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
0));
// Full frames.
- scoped_ptr<SpdyFrame> body1(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, content.c_str(), content.size(), false));
+ scoped_ptr<SpdySerializedFrame> body1(spdy_util_.ConstructSpdyBodyFrame(
+ 1, content.c_str(), content.size(), false));
// Last frame to zero out the window size.
- scoped_ptr<SpdyFrame> body2(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, content.c_str(), last_frame_size, false));
+ scoped_ptr<SpdySerializedFrame> body2(spdy_util_.ConstructSpdyBodyFrame(
+ 1, content.c_str(), last_frame_size, false));
// Data frame to be sent once SETTINGS frame is received.
- scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body3(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
// Fill in mock reads/writes.
std::vector<MockRead> reads;
@@ -6131,21 +6671,23 @@ TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
SettingsMap settings;
settings[SETTINGS_INITIAL_WINDOW_SIZE] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size * 2);
- scoped_ptr<SpdyFrame> settings_frame_large(
+ scoped_ptr<SpdySerializedFrame> settings_frame_large(
spdy_util_.ConstructSpdySettings(settings));
reads.push_back(CreateMockRead(*settings_frame_large, i++));
- scoped_ptr<SpdyFrame> session_window_update(
+ scoped_ptr<SpdySerializedFrame> session_window_update(
spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
reads.push_back(CreateMockRead(*session_window_update, i++));
- scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
+ scoped_ptr<SpdySerializedFrame> settings_ack(
+ spdy_util_.ConstructSpdySettingsAck());
writes.push_back(CreateMockWrite(*settings_ack, i++));
writes.push_back(CreateMockWrite(*body3, i++));
- scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> reply(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
reads.push_back(CreateMockRead(*reply, i++));
reads.push_back(CreateMockRead(*body2, i++));
reads.push_back(CreateMockRead(*body3, i++));
@@ -6220,22 +6762,21 @@ TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
// Construct content for a data frame of maximum size.
std::string content(kMaxSpdyFrameChunkSize, 'a');
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
0));
// Full frames.
- scoped_ptr<SpdyFrame> body1(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, content.c_str(), content.size(), false));
+ scoped_ptr<SpdySerializedFrame> body1(spdy_util_.ConstructSpdyBodyFrame(
+ 1, content.c_str(), content.size(), false));
// Last frame to zero out the window size.
- scoped_ptr<SpdyFrame> body2(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, content.c_str(), last_frame_size, false));
+ scoped_ptr<SpdySerializedFrame> body2(spdy_util_.ConstructSpdyBodyFrame(
+ 1, content.c_str(), last_frame_size, false));
// Data frame to be sent once SETTINGS frame is received.
- scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body3(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
// Fill in mock reads/writes.
std::vector<MockRead> reads;
@@ -6253,25 +6794,27 @@ TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
SettingsMap new_settings;
new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size / 2);
- scoped_ptr<SpdyFrame> settings_frame_small(
+ scoped_ptr<SpdySerializedFrame> settings_frame_small(
spdy_util_.ConstructSpdySettings(new_settings));
// Construct read frames for WINDOW_UPDATE that makes the send_window_size
// positive.
- scoped_ptr<SpdyFrame> session_window_update_init_size(
+ scoped_ptr<SpdySerializedFrame> session_window_update_init_size(
spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
- scoped_ptr<SpdyFrame> window_update_init_size(
+ scoped_ptr<SpdySerializedFrame> window_update_init_size(
spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
reads.push_back(CreateMockRead(*settings_frame_small, i++));
reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
reads.push_back(CreateMockRead(*window_update_init_size, i++));
- scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
+ scoped_ptr<SpdySerializedFrame> settings_ack(
+ spdy_util_.ConstructSpdySettingsAck());
writes.push_back(CreateMockWrite(*settings_ack, i++));
writes.push_back(CreateMockWrite(*body3, i++));
- scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> reply(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
reads.push_back(CreateMockRead(*reply, i++));
reads.push_back(CreateMockRead(*body2, i++));
reads.push_back(CreateMockRead(*body3, i++));
@@ -6331,13 +6874,13 @@ TEST_P(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
spdy_util_.AddUrlToHeaderBlock("http://www.example.org/a.dat",
push_headers.get());
- scoped_ptr<SpdyFrame> push(
+ scoped_ptr<SpdySerializedFrame> push(
spdy_util_.ConstructInitialSpdyPushFrame(std::move(push_headers), 3, 1));
MockRead reads[] = {CreateMockRead(*push, 1)};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(
0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2),
@@ -6353,22 +6896,22 @@ TEST_P(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
TEST_P(SpdyNetworkTransactionTest,
GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
- scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> push_a(spdy_util_.ConstructSpdyPush(
NULL, 0, 4, 1, GetDefaultUrlWithPath("/a.dat").c_str()));
scoped_ptr<SpdyHeaderBlock> push_b_headers(new SpdyHeaderBlock);
spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/b.dat"),
push_b_headers.get());
- scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructInitialSpdyPushFrame(
- std::move(push_b_headers), 2, 1));
+ scoped_ptr<SpdySerializedFrame> push_b(
+ spdy_util_.ConstructInitialSpdyPushFrame(std::move(push_b_headers), 2,
+ 1));
MockRead reads[] = {
CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
- 4,
- GOAWAY_PROTOCOL_ERROR,
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<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),
@@ -6396,15 +6939,16 @@ TEST_P(SpdyNetworkTransactionTest, LargeRequest) {
scoped_ptr<SpdyHeaderBlock> headers(
spdy_util_.ConstructGetHeaderBlock(GetDefaultUrl()));
(*headers)[kKey] = kValue;
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -6426,8 +6970,8 @@ TEST_P(SpdyNetworkTransactionTest, LargeRequest) {
TEST_P(SpdyNetworkTransactionTest, LargeResponseHeader) {
scoped_ptr<SpdyHeaderBlock> headers(
spdy_util_.ConstructGetHeaderBlock(GetDefaultUrl()));
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
};
@@ -6439,9 +6983,10 @@ TEST_P(SpdyNetworkTransactionTest, LargeResponseHeader) {
const std::string kValue(16 * 1024, 'b');
response_headers[1] = kValue.data();
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(response_headers, 1, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
MockRead(ASYNC, 0, 3) // EOF
@@ -6468,12 +7013,14 @@ class SpdyNetworkTransactionNoTLSUsageCheckTest
protected:
void RunNoTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
// Construct the request.
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {CreateMockWrite(*req, 0)};
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*body, 2),
@@ -6530,7 +7077,7 @@ class SpdyNetworkTransactionTLSUsageCheckTest
: public SpdyNetworkTransactionTest {
protected:
void RunTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
- scoped_ptr<SpdyFrame> goaway(
+ scoped_ptr<SpdySerializedFrame> goaway(
spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
MockWrite writes[] = {CreateMockWrite(*goaway)};
diff --git a/chromium/net/spdy/spdy_priority_tree.h b/chromium/net/spdy/spdy_priority_tree.h
deleted file mode 100644
index ea09c2a592b..00000000000
--- a/chromium/net/spdy/spdy_priority_tree.h
+++ /dev/null
@@ -1,563 +0,0 @@
-// Copyright 2014 The Chromium 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_SPDY_PRIORITY_TREE_H_
-#define NET_SPDY_SPDY_PRIORITY_TREE_H_
-
-#include <cmath>
-#include <deque>
-#include <map>
-#include <queue>
-#include <set>
-#include <utility>
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/stl_util.h"
-
-namespace net {
-
-// This data structure implements the HTTP/2 stream priority tree defined in
-// section 5.3 of RFC 7540:
-// http://tools.ietf.org/html/rfc7540#section-5.3
-//
-// Nodes can be added and removed, and dependencies between them defined.
-// Nodes constitute a tree rooted at node ID 0: each node has a single parent
-// node, and 0 or more child nodes. Individual nodes can be marked as ready to
-// read/write, and then the whole structure can be queried to pick the next
-// node to read/write out of those that are ready.
-//
-// The NodeId type must be a POD that supports comparison (most
-// likely, it will be a number).
-
-namespace test {
-template <typename NodeId>
-class SpdyPriorityTreePeer;
-}
-
-const int kRootNodeId = 0;
-const int kDefaultWeight = 16;
-const int kMinWeight = 1;
-const int kMaxWeight = 256;
-
-template <typename NodeId>
-class SpdyPriorityTree {
- public:
- typedef std::pair<NodeId, float> PriorityNode;
- typedef std::vector<PriorityNode> PriorityList;
-
- SpdyPriorityTree();
-
- // Orders in descending order of priority.
- struct NodePriorityComparator {
- bool operator ()(const std::pair<NodeId, float>& lhs,
- const std::pair<NodeId, float>& rhs);
- };
-
- friend class test::SpdyPriorityTreePeer<NodeId>;
-
- // Return the number of nodes currently in the tree.
- int num_nodes() const;
-
- // Return true if the tree contains a node with the given ID.
- bool NodeExists(NodeId node_id) const;
-
- // Add a new node with the given weight and parent. Non-exclusive nodes
- // simply get added below the parent node. If exclusive = true, the node
- // becomes the parent's sole child and the parent's previous children
- // become the children of the new node.
- // Returns true on success. Returns false if the node already exists
- // in the tree, or if the parent node does not exist.
- bool AddNode(NodeId node_id, NodeId parent_id, int weight, bool exclusive);
-
- // Remove an existing node from the tree. Returns true on success, or
- // false if the node doesn't exist.
- bool RemoveNode(NodeId node_id);
-
- // Get the weight of the given node.
- int GetWeight(NodeId node_id) const;
-
- // Get the parent of the given node. If the node doesn't exist, or is a root
- // node (and thus has no parent), returns NodeId().
- NodeId GetParent(NodeId node_id) const;
-
- // Get the children of the given node. If the node doesn't exist, or has no
- // child, returns empty vector.
- std::vector<NodeId> GetChildren(NodeId node_id) const;
-
- // Set the priority of the given node.
- bool SetWeight(NodeId node_id, int weight);
-
- // Set the parent of the given node. Returns true on success.
- // Returns false and has no effect if the node and/or the parent doesn't
- // exist. If the new parent is a descendant of the node (i.e. this would have
- // created a cycle) then we rearrange the topology of the tree as described
- // in section 5.3.3 of RFC 7540:
- // https://tools.ietf.org/html/rfc7540#section-5.3.3
- bool SetParent(NodeId node_id, NodeId parent_id, bool exclusive);
-
- // Returns true if the node parent_id has child_id in its children.
- bool HasChild(NodeId parent_id, NodeId child_id) const;
-
- // Mark a node as blocked or unblocked. Return true on success, or false
- // if unable to mark the specified node.
- bool SetBlocked(NodeId node_id, bool blocked);
-
- // Mark whether or not a node is ready to write; i.e. whether there is
- // buffered data for the associated stream. Return true on success, or false
- // if unable to mark the specified node.
- bool SetReady(NodeId node_id, bool ready);
-
- // Returns an ordered list of writeable nodes and their priorities.
- // Priority is calculated as:
- // parent's priority * (node's weight / sum of sibling weights)
- PriorityList GetPriorityList();
-
- private:
- struct Node;
- typedef std::vector<Node*> NodeVector;
- typedef std::map<NodeId, Node*> NodeMap;
-
- struct Node {
- // ID for this node.
- NodeId id;
- // ID of parent node.
- Node* parent = nullptr;
- // Weights can range between 1 and 256 (inclusive).
- int weight = kDefaultWeight;
- // The total weight of this node's direct descendants.
- int total_child_weights = 0;
- // The total weight of direct descendants that are writeable
- // (ready to write and not blocked). This value does not necessarily
- // reflect the current state of the tree; instead, we lazily update it
- // on calls to PropagateNodeState().
- int total_writeable_child_weights = 0;
- // Pointers to nodes for children, if any.
- NodeVector children;
- // Is the associated stream write-blocked?
- bool blocked = false;
- // Does the stream have data ready for writing?
- bool ready = false;
- // The fraction of resources to dedicate to this node.
- float priority = 0;
- };
-
- static bool Remove(NodeVector* nodes, const Node* node);
-
- // Update the value of total_writeable_child_weights for the given node
- // to reflect the current state of the tree.
- void PropagateNodeState(Node* node);
-
- // Get the given node, or return nullptr if it doesn't exist.
- const Node* FindNode(NodeId node_id) const;
- Node* FindNode(NodeId node_id);
-
- // Return true if all internal invariants hold (useful for unit tests).
- // Unless there are bugs, this should always return true.
- bool ValidateInvariantsForTests() const;
-
- Node* root_node_; // pointee owned by all_nodes_
- NodeMap all_nodes_; // maps from node IDs to Node objects
- STLValueDeleter<NodeMap> all_nodes_deleter_;
-
- DISALLOW_COPY_AND_ASSIGN(SpdyPriorityTree);
-};
-
-template <typename NodeId>
-SpdyPriorityTree<NodeId>::SpdyPriorityTree()
- : all_nodes_deleter_(&all_nodes_) {
- root_node_ = new Node();
- root_node_->id = kRootNodeId;
- root_node_->weight = kDefaultWeight;
- root_node_->parent = nullptr;
- root_node_->priority = 1.0;
- root_node_->ready = true;
- all_nodes_[kRootNodeId] = root_node_;
-}
-
-template <typename NodeId>
-bool SpdyPriorityTree<NodeId>::NodePriorityComparator::operator()(
- const std::pair<NodeId, float>& lhs,
- const std::pair<NodeId, float>& rhs) {
- return lhs.second > rhs.second;
-}
-
-template <typename NodeId>
-int SpdyPriorityTree<NodeId>::num_nodes() const {
- return all_nodes_.size();
-}
-
-template <typename NodeId>
-bool SpdyPriorityTree<NodeId>::NodeExists(NodeId node_id) const {
- return ContainsKey(all_nodes_, node_id);
-}
-
-template <typename NodeId>
-bool SpdyPriorityTree<NodeId>::AddNode(NodeId node_id,
- NodeId parent_id,
- int weight,
- bool exclusive) {
- if (NodeExists(node_id) || weight < kMinWeight || weight > kMaxWeight) {
- return false;
- }
- Node* parent = FindNode(parent_id);
- if (parent == nullptr) {
- return false;
- }
- Node* new_node = new Node;
- new_node->id = node_id;
- new_node->weight = weight;
- new_node->parent = parent;
- all_nodes_[node_id] = new_node;
- if (exclusive) {
- // Move the parent's current children below the new node.
- using std::swap;
- swap(new_node->children, parent->children);
- new_node->total_child_weights = parent->total_child_weights;
- // Update each child's parent.
- for (Node* child : new_node->children) {
- child->parent = new_node;
- }
- // Clear parent's old child data.
- DCHECK(parent->children.empty());
- parent->total_child_weights = 0;
- }
- // Add new node to parent.
- parent->children.push_back(new_node);
- parent->total_child_weights += weight;
- return true;
-}
-
-template <typename NodeId>
-bool SpdyPriorityTree<NodeId>::RemoveNode(NodeId node_id) {
- if (node_id == kRootNodeId) {
- return false;
- }
- // Remove the node from table.
- typename NodeMap::iterator it = all_nodes_.find(node_id);
- if (it == all_nodes_.end()) {
- return false;
- }
- scoped_ptr<Node> node(it->second);
- all_nodes_.erase(it);
-
- Node* parent = node->parent;
- // Remove the node from parent's child list.
- Remove(&parent->children, node.get());
- parent->total_child_weights -= node->weight;
-
- // Move the node's children to the parent's child list.
- // Update each child's parent and weight.
- for (Node* child : node->children) {
- child->parent = parent;
- parent->children.push_back(child);
- // Divide the removed node's weight among its children, rounding to the
- // nearest valid weight.
- float float_weight = node->weight * static_cast<float>(child->weight) /
- static_cast<float>(node->total_child_weights);
- int new_weight = floor(float_weight + 0.5);
- if (new_weight == 0) {
- new_weight = 1;
- }
- child->weight = new_weight;
- parent->total_child_weights += child->weight;
- }
-
- return true;
-}
-
-template <typename NodeId>
-int SpdyPriorityTree<NodeId>::GetWeight(NodeId node_id) const {
- const Node* node = FindNode(node_id);
- return (node == nullptr) ? 0 : node->weight;
-}
-
-template <typename NodeId>
-NodeId SpdyPriorityTree<NodeId>::GetParent(NodeId node_id) const {
- const Node* node = FindNode(node_id);
- // Root node has null parent.
- return (node == nullptr || node->parent == nullptr) ? kRootNodeId
- : node->parent->id;
-}
-
-template <typename NodeId>
-std::vector<NodeId> SpdyPriorityTree<NodeId>::GetChildren(
- NodeId node_id) const {
- std::vector<NodeId> child_vec;
- const Node* node = FindNode(node_id);
- if (node != nullptr) {
- child_vec.reserve(node->children.size());
- for (Node* child : node->children) {
- child_vec.push_back(child->id);
- }
- }
- return child_vec;
-}
-
-template <typename NodeId>
-bool SpdyPriorityTree<NodeId>::SetWeight(
- NodeId node_id, int weight) {
- if (!NodeExists(node_id)) {
- return false;
- }
- if (weight < kMinWeight || weight > kMaxWeight) {
- return false;
- }
-
- Node* node = all_nodes_[node_id];
- if (node->parent != nullptr) {
- node->parent->total_child_weights += (weight - node->weight);
- }
- node->weight = weight;
-
- return true;
-}
-
-
-template <typename NodeId>
-bool SpdyPriorityTree<NodeId>::SetParent(
- NodeId node_id, NodeId parent_id, bool exclusive) {
- if (node_id == kRootNodeId || node_id == parent_id) {
- return false;
- }
- Node* node = FindNode(node_id);
- Node* new_parent = FindNode(parent_id);
- if (node == nullptr || new_parent == nullptr) {
- return false;
- }
-
- // If the new parent is already the node's parent, we're done.
- if (node->parent == new_parent) {
- return true;
- }
-
- // Next, check to see if the new parent is currently a descendant
- // of the node.
- Node* last = new_parent->parent;
- bool cycle_exists = false;
- while (last != nullptr) {
- if (last == node) {
- cycle_exists = true;
- break;
- }
- last = last->parent;
- }
-
- if (cycle_exists) {
- // The new parent moves to the level of the current node.
- SetParent(parent_id, node->parent->id, false);
- }
-
- // Remove node from old parent's child list.
- Node* old_parent = node->parent;
- Remove(&old_parent->children, node);
- old_parent->total_child_weights -= node->weight;
-
- if (exclusive) {
- // Move the new parent's current children below the current node.
- for (Node* child : new_parent->children) {
- child->parent = node;
- node->children.push_back(child);
- }
- node->total_child_weights += new_parent->total_child_weights;
- // Clear new parent's old child data.
- new_parent->children.clear();
- new_parent->total_child_weights = 0;
- }
-
- // Make the change.
- node->parent = new_parent;
- new_parent->children.push_back(node);
- new_parent->total_child_weights += node->weight;
- return true;
-}
-
-template <typename NodeId>
-bool SpdyPriorityTree<NodeId>::SetBlocked(NodeId node_id, bool blocked) {
- if (!NodeExists(node_id)) {
- return false;
- }
-
- Node* node = all_nodes_[node_id];
- node->blocked = blocked;
- return true;
-}
-
-template <typename NodeId>
-bool SpdyPriorityTree<NodeId>::SetReady(NodeId node_id, bool ready) {
- if (!NodeExists(node_id)) {
- return false;
- }
- Node* node = all_nodes_[node_id];
- node->ready = ready;
- return true;
-}
-
-template <typename NodeId>
-bool SpdyPriorityTree<NodeId>::Remove(NodeVector* nodes, const Node* node) {
- for (typename NodeVector::iterator it = nodes->begin(); it != nodes->end();
- ++it) {
- if (*it == node) {
- nodes->erase(it);
- return true;
- }
- }
- return false;
-}
-
-template <typename NodeId>
-void SpdyPriorityTree<NodeId>::PropagateNodeState(Node* node) {
- // Reset total_writeable_child_weights to its maximum value.
- node->total_writeable_child_weights = node->total_child_weights;
- for (Node* child : node->children) {
- PropagateNodeState(child);
- }
- if (node->total_writeable_child_weights == 0 &&
- (node->blocked || !node->ready)) {
- // Tell the parent that this entire subtree is unwriteable.
- node->parent->total_writeable_child_weights -= node->weight;
- }
-}
-
-template <typename NodeId>
-const typename SpdyPriorityTree<NodeId>::Node*
-SpdyPriorityTree<NodeId>::FindNode(NodeId node_id) const {
- typename NodeMap::const_iterator it = all_nodes_.find(node_id);
- return (it == all_nodes_.end() ? nullptr : it->second);
-}
-
-template <typename NodeId>
-typename SpdyPriorityTree<NodeId>::Node* SpdyPriorityTree<NodeId>::FindNode(
- NodeId node_id) {
- typename NodeMap::const_iterator it = all_nodes_.find(node_id);
- return (it == all_nodes_.end() ? nullptr : it->second);
-}
-
-template <typename NodeId>
-bool SpdyPriorityTree<NodeId>::HasChild(NodeId parent_id,
- NodeId child_id) const {
- const Node* parent = FindNode(parent_id);
- if (parent == nullptr) {
- return false;
- }
- auto found =
- std::find_if(parent->children.begin(), parent->children.end(),
- [child_id](Node* node) { return node->id == child_id; });
- return found != parent->children.end();
-}
-
-template <typename NodeId>
-std::vector<std::pair<NodeId, float> >
-SpdyPriorityTree<NodeId>::GetPriorityList() {
- PriorityList priority_list;
-
- // Update total_writeable_child_weights to reflect the current
- // state of the tree.
- PropagateNodeState(root_node_);
-
- std::deque<Node*> queue;
- DCHECK(root_node_->priority == 1.0);
- // Start by examining our top-level nodes.
- for (Node* child : root_node_->children) {
- queue.push_back(child);
- }
- while (!queue.empty()) {
- Node* current_node = queue.front();
- const Node* parent_node = current_node->parent;
- if (current_node->blocked || !current_node->ready) {
- if (current_node->total_writeable_child_weights > 0) {
- // This node isn't writeable, but it has writeable children.
- // Calculate the total fraction of resources we can allot
- // to this subtree.
- current_node->priority = parent_node->priority *
- (static_cast<float>(current_node->weight) /
- static_cast<float>(parent_node->total_writeable_child_weights));
- // Examine the children.
- for (Node* child : current_node->children) {
- queue.push_back(child);
- }
- } else {
- // There's nothing to see in this subtree.
- current_node->priority = 0;
- }
- } else {
- // This node is writeable; calculate its priority.
- current_node->priority = parent_node->priority *
- (static_cast<float>(current_node->weight) /
- static_cast<float>(parent_node->total_writeable_child_weights));
- // Add this node to the priority list.
- priority_list.push_back(
- PriorityNode(current_node->id, current_node->priority));
- }
- // Remove this node from the queue.
- queue.pop_front();
- }
-
- // Sort the nodes in descending order of priority.
- std::sort(priority_list.begin(), priority_list.end(),
- NodePriorityComparator());
-
- return priority_list;
-}
-
-template <typename NodeId>
-bool SpdyPriorityTree<NodeId>::ValidateInvariantsForTests() const {
- int total_nodes = 0;
- int nodes_visited = 0;
- // Iterate through all nodes in the map.
- for (const auto& kv : all_nodes_) {
- ++total_nodes;
- ++nodes_visited;
- const Node& node = *kv.second;
- // All nodes except the root should have a parent, and should appear in
- // the children of that parent.
- if (node.id != kRootNodeId && !HasChild(node.parent->id, node.id)) {
- DLOG(INFO) << "Parent node " << node.parent->id
- << " does not exist, or does not list node " << node.id
- << " as its child.";
- return false;
- }
-
- if (!node.children.empty()) {
- int total_child_weights = 0;
- // Iterate through the node's children.
- for (Node* child : node.children) {
- ++nodes_visited;
- // Each node in the list should exist and should have this node
- // set as its parent.
- if (!NodeExists(child->id) || node.id != GetParent(child->id)) {
- DLOG(INFO) << "Child node " << child->id << " does not exist, "
- << "or does not list " << node.id << " as its parent.";
- return false;
- }
- total_child_weights += child->weight;
- }
- // Verify that total_child_weights is correct.
- if (total_child_weights != node.total_child_weights) {
- DLOG(INFO) << "Child weight totals do not agree. For node " << node.id
- << " total_child_weights has value "
- << node.total_child_weights
- << ", expected " << total_child_weights;
- return false;
- }
- }
- }
-
- // Make sure num_nodes reflects the total number of nodes the map contains.
- if (total_nodes != num_nodes()) {
- DLOG(INFO) << "Map contains incorrect number of nodes.";
- return false;
- }
- // Validate the validation function; we should have visited each node twice
- // (except for the root)
- DCHECK(nodes_visited == 2*num_nodes() - 1);
- return true;
-}
-
-} // namespace net
-
-#endif // NET_SPDY_SPDY_PRIORITY_TREE_H_
diff --git a/chromium/net/spdy/spdy_priority_tree_test.cc b/chromium/net/spdy/spdy_priority_tree_test.cc
deleted file mode 100644
index b953c01c696..00000000000
--- a/chromium/net/spdy/spdy_priority_tree_test.cc
+++ /dev/null
@@ -1,607 +0,0 @@
-// Copyright 2014 The Chromium 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/spdy_priority_tree.h"
-
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-
-using ::testing::ElementsAre;
-using ::testing::IsEmpty;
-using ::testing::UnorderedElementsAre;
-
-namespace test {
-
-template <typename NodeId>
-class SpdyPriorityTreePeer {
- public:
- explicit SpdyPriorityTreePeer(SpdyPriorityTree<NodeId>* tree) : tree_(tree) {}
-
- void PropagateNodeState(NodeId node_id) {
- auto node = tree_->FindNode(node_id);
- tree_->PropagateNodeState(node);
- }
-
- int TotalChildWeights(NodeId node_id) const {
- return tree_->FindNode(node_id)->total_child_weights;
- }
-
- int TotalWriteableChildWeights(NodeId node_id) const {
- return tree_->FindNode(node_id)->total_writeable_child_weights;
- }
-
- bool ValidateInvariants() const {
- return tree_->ValidateInvariantsForTests();
- }
-
- private:
- SpdyPriorityTree<NodeId>* tree_;
-};
-
-class SpdyPriorityTreeTest : public ::testing::Test {
- protected:
- typedef uint32_t SpdyStreamId;
- typedef std::pair<SpdyStreamId, float> PriorityNode;
- typedef std::vector<PriorityNode> PriorityList;
-
- SpdyPriorityTreeTest() : peer(&tree) {}
-
- SpdyPriorityTree<SpdyStreamId> tree;
- SpdyPriorityTreePeer<SpdyStreamId> peer;
-};
-
-TEST_F(SpdyPriorityTreeTest, AddAndRemoveNodes) {
- EXPECT_EQ(1, tree.num_nodes());
- EXPECT_TRUE(tree.NodeExists(0));
- EXPECT_FALSE(tree.NodeExists(1));
-
- EXPECT_TRUE(tree.AddNode(1, 0, 100, false));
- EXPECT_EQ(2, tree.num_nodes());
- ASSERT_TRUE(tree.NodeExists(1));
- EXPECT_EQ(100, tree.GetWeight(1));
- EXPECT_FALSE(tree.NodeExists(5));
- EXPECT_THAT(tree.GetChildren(0), ElementsAre(1));
-
- EXPECT_TRUE(tree.AddNode(5, 0, 50, false));
- // Should not be able to add a node with an id that already exists.
- EXPECT_FALSE(tree.AddNode(5, 1, 50, false));
- EXPECT_EQ(3, tree.num_nodes());
- EXPECT_TRUE(tree.NodeExists(1));
- ASSERT_TRUE(tree.NodeExists(5));
- EXPECT_EQ(50, tree.GetWeight(5));
- EXPECT_FALSE(tree.NodeExists(13));
-
- EXPECT_TRUE(tree.AddNode(13, 5, 130, true));
- EXPECT_EQ(4, tree.num_nodes());
- EXPECT_TRUE(tree.NodeExists(1));
- EXPECT_TRUE(tree.NodeExists(5));
- ASSERT_TRUE(tree.NodeExists(13));
- EXPECT_EQ(130, tree.GetWeight(13));
- EXPECT_EQ(5u, tree.GetParent(13));
-
- EXPECT_TRUE(tree.RemoveNode(5));
- // Cannot remove a node that has already been removed.
- EXPECT_FALSE(tree.RemoveNode(5));
- EXPECT_EQ(3, tree.num_nodes());
- EXPECT_TRUE(tree.NodeExists(1));
- EXPECT_FALSE(tree.NodeExists(5));
- EXPECT_TRUE(tree.NodeExists(13));
- EXPECT_EQ(0u, tree.GetParent(13));
-
- // The parent node 19 doesn't exist, so this should fail:
- EXPECT_FALSE(tree.AddNode(7, 19, 70, false));
- // This should succeed, creating node 7:
- EXPECT_TRUE(tree.AddNode(7, 13, 70, false));
- // Now node 7 already exists, so this should fail:
- EXPECT_FALSE(tree.AddNode(7, 1, 70, false));
- // Try adding a second child to node 13:
- EXPECT_TRUE(tree.AddNode(17, 13, 170, false));
-
- // TODO(birenroy): Add a separate test that verifies weight invariants when
- // SetWeight is called.
- EXPECT_TRUE(tree.SetWeight(17, 150));
- EXPECT_EQ(150, tree.GetWeight(17));
-
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-// Basic case of reparenting a subtree.
-TEST_F(SpdyPriorityTreeTest, SetParentBasicNonExclusive) {
- /* Tree:
- 0
- / \
- 1 2
- / \
- 3 4
- */
- tree.AddNode(1, 0, 100, false);
- tree.AddNode(2, 0, 100, false);
- tree.AddNode(3, 1, 100, false);
- tree.AddNode(4, 1, 100, false);
- EXPECT_TRUE(tree.SetParent(1, 2, false));
- EXPECT_THAT(tree.GetChildren(0), ElementsAre(2));
- EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(3, 4));
- EXPECT_THAT(tree.GetChildren(2), ElementsAre(1));
- EXPECT_THAT(tree.GetChildren(3), IsEmpty());
- EXPECT_THAT(tree.GetChildren(4), IsEmpty());
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-// Basic case of reparenting a subtree. Result here is the same as the
-// non-exclusive case.
-TEST_F(SpdyPriorityTreeTest, SetParentBasicExclusive) {
- /* Tree:
- 0
- / \
- 1 2
- / \
- 3 4
- */
- tree.AddNode(1, 0, 100, false);
- tree.AddNode(2, 0, 100, false);
- tree.AddNode(3, 1, 100, false);
- tree.AddNode(4, 1, 100, false);
- EXPECT_TRUE(tree.SetParent(1, 2, true));
- EXPECT_THAT(tree.GetChildren(0), ElementsAre(2));
- EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(3, 4));
- EXPECT_THAT(tree.GetChildren(2), ElementsAre(1));
- EXPECT_THAT(tree.GetChildren(3), IsEmpty());
- EXPECT_THAT(tree.GetChildren(4), IsEmpty());
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-// We can't set the parent of a nonexistent node, or set the parent to a
-// nonexistent node.
-TEST_F(SpdyPriorityTreeTest, SetParentNonexistent) {
- tree.AddNode(1, 0, 100, false);
- tree.AddNode(2, 0, 100, false);
- bool test_bool_values[] = {true, false};
- for (bool exclusive : test_bool_values) {
- EXPECT_FALSE(tree.SetParent(1, 3, exclusive));
- EXPECT_FALSE(tree.SetParent(4, 2, exclusive));
- EXPECT_FALSE(tree.SetParent(3, 4, exclusive));
- EXPECT_THAT(tree.GetChildren(0), UnorderedElementsAre(1, 2));
- EXPECT_THAT(tree.GetChildren(1), IsEmpty());
- EXPECT_THAT(tree.GetChildren(2), IsEmpty());
- }
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-// We should be able to add multiple children to nodes.
-TEST_F(SpdyPriorityTreeTest, SetParentMultipleChildrenNonExclusive) {
- /* Tree:
- 0
- / \
- 1 2
- / \ \
- 3 4 5
- */
- tree.AddNode(1, 0, 100, false);
- tree.AddNode(2, 0, 100, false);
- tree.AddNode(3, 1, 100, false);
- tree.AddNode(4, 1, 100, false);
- tree.AddNode(5, 2, 100, false);
- EXPECT_TRUE(tree.SetParent(2, 1, false));
- EXPECT_THAT(tree.GetChildren(0), ElementsAre(1));
- EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(2, 3, 4));
- EXPECT_THAT(tree.GetChildren(2), ElementsAre(5));
- EXPECT_THAT(tree.GetChildren(3), IsEmpty());
- EXPECT_THAT(tree.GetChildren(4), IsEmpty());
- EXPECT_THAT(tree.GetChildren(5), IsEmpty());
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-TEST_F(SpdyPriorityTreeTest, SetParentMultipleChildrenExclusive) {
- /* Tree:
- 0
- / \
- 1 2
- / \ \
- 3 4 5
- */
- tree.AddNode(1, 0, 100, false);
- tree.AddNode(2, 0, 100, false);
- tree.AddNode(3, 1, 100, false);
- tree.AddNode(4, 1, 100, false);
- tree.AddNode(5, 2, 100, false);
- EXPECT_TRUE(tree.SetParent(2, 1, true));
- EXPECT_THAT(tree.GetChildren(0), ElementsAre(1));
- EXPECT_THAT(tree.GetChildren(1), ElementsAre(2));
- EXPECT_THAT(tree.GetChildren(2), UnorderedElementsAre(3, 4, 5));
- EXPECT_THAT(tree.GetChildren(3), IsEmpty());
- EXPECT_THAT(tree.GetChildren(4), IsEmpty());
- EXPECT_THAT(tree.GetChildren(5), IsEmpty());
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-TEST_F(SpdyPriorityTreeTest, SetParentToChildNonExclusive) {
- /* Tree:
- 0
- |
- 1
- / \
- 2 3
- |
- 4
- */
- tree.AddNode(1, 0, 100, false);
- tree.AddNode(2, 1, 100, false);
- tree.AddNode(3, 1, 100, false);
- tree.AddNode(4, 2, 100, false);
- EXPECT_TRUE(tree.SetParent(1, 2, false));
- EXPECT_THAT(tree.GetChildren(0), ElementsAre(2));
- EXPECT_THAT(tree.GetChildren(1), ElementsAre(3));
- EXPECT_THAT(tree.GetChildren(2), UnorderedElementsAre(1, 4));
- EXPECT_THAT(tree.GetChildren(3), IsEmpty());
- EXPECT_THAT(tree.GetChildren(4), IsEmpty());
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-TEST_F(SpdyPriorityTreeTest, SetParentToChildExclusive) {
- /* Tree:
- 0
- |
- 1
- / \
- 2 3
- |
- 4
- */
- tree.AddNode(1, 0, 100, false);
- tree.AddNode(2, 1, 100, false);
- tree.AddNode(3, 1, 100, false);
- tree.AddNode(4, 2, 100, false);
- EXPECT_TRUE(tree.SetParent(1, 2, true));
- EXPECT_THAT(tree.GetChildren(0), ElementsAre(2));
- EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(3, 4));
- EXPECT_THAT(tree.GetChildren(2), ElementsAre(1));
- EXPECT_THAT(tree.GetChildren(3), IsEmpty());
- EXPECT_THAT(tree.GetChildren(4), IsEmpty());
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-TEST_F(SpdyPriorityTreeTest, SetParentToGrandchildNonExclusive) {
- /* Tree:
- 0
- |
- 1
- / \
- 2 3
- / \
- 4 5
- |
- 6
- */
- tree.AddNode(1, 0, 100, false);
- tree.AddNode(2, 1, 100, false);
- tree.AddNode(3, 1, 100, false);
- tree.AddNode(4, 2, 100, false);
- tree.AddNode(5, 2, 100, false);
- tree.AddNode(6, 4, 100, false);
- EXPECT_TRUE(tree.SetParent(1, 4, false));
- EXPECT_THAT(tree.GetChildren(0), ElementsAre(4));
- EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(2, 3));
- EXPECT_THAT(tree.GetChildren(2), ElementsAre(5));
- EXPECT_THAT(tree.GetChildren(3), IsEmpty());
- EXPECT_THAT(tree.GetChildren(4), UnorderedElementsAre(1, 6));
- EXPECT_THAT(tree.GetChildren(5), IsEmpty());
- EXPECT_THAT(tree.GetChildren(6), IsEmpty());
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-TEST_F(SpdyPriorityTreeTest, SetParentToGrandchildExclusive) {
- /* Tree:
- 0
- |
- 1
- / \
- 2 3
- / \
- 4 5
- |
- 6
- */
- tree.AddNode(1, 0, 100, false);
- tree.AddNode(2, 1, 100, false);
- tree.AddNode(3, 1, 100, false);
- tree.AddNode(4, 2, 100, false);
- tree.AddNode(5, 2, 100, false);
- tree.AddNode(6, 4, 100, false);
- EXPECT_TRUE(tree.SetParent(1, 4, true));
- EXPECT_THAT(tree.GetChildren(0), ElementsAre(4));
- EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(2, 3, 6));
- EXPECT_THAT(tree.GetChildren(2), ElementsAre(5));
- EXPECT_THAT(tree.GetChildren(3), IsEmpty());
- EXPECT_THAT(tree.GetChildren(4), ElementsAre(1));
- EXPECT_THAT(tree.GetChildren(5), IsEmpty());
- EXPECT_THAT(tree.GetChildren(6), IsEmpty());
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-TEST_F(SpdyPriorityTreeTest, SetParentToParent) {
- tree.AddNode(1, 0, 100, false);
- tree.AddNode(2, 1, 100, false);
- tree.AddNode(3, 1, 100, false);
- bool test_bool_values[] = {true, false};
- for (bool exclusive : test_bool_values) {
- EXPECT_TRUE(tree.SetParent(2, 1, exclusive));
- EXPECT_THAT(tree.GetChildren(0), ElementsAre(1));
- EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(2, 3));
- EXPECT_THAT(tree.GetChildren(2), IsEmpty());
- EXPECT_THAT(tree.GetChildren(3), IsEmpty());
- }
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-TEST_F(SpdyPriorityTreeTest, SetParentToSelf) {
- tree.AddNode(1, 0, 100, false);
- EXPECT_FALSE(tree.SetParent(1, 1, false));
- EXPECT_FALSE(tree.SetParent(1, 1, true));
- EXPECT_THAT(tree.GetChildren(0), ElementsAre(1));
- EXPECT_THAT(tree.GetChildren(1), IsEmpty());
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-TEST_F(SpdyPriorityTreeTest, BlockAndUnblock) {
- /* Create the tree.
-
- 0
- / | \
- / | \
- 1 2 3
- / \ \ \
- 4 5 6 7
- /| / \ | |\
- 8 9 10 11 12 13 14
- / \
- 15 16
-
- */
- tree.AddNode(1, 0, 100, false);
- tree.AddNode(2, 0, 100, false);
- tree.AddNode(3, 0, 100, false);
- tree.AddNode(4, 1, 100, false);
- tree.AddNode(5, 1, 100, false);
- tree.AddNode(8, 4, 100, false);
- tree.AddNode(9, 4, 100, false);
- tree.AddNode(10, 5, 100, false);
- tree.AddNode(11, 5, 100, false);
- tree.AddNode(15, 8, 100, false);
- tree.AddNode(16, 8, 100, false);
- tree.AddNode(12, 2, 100, false);
- tree.AddNode(6, 2, 100, true);
- tree.AddNode(7, 0, 100, false);
- tree.AddNode(13, 7, 100, true);
- tree.AddNode(14, 7, 100, false);
- tree.SetParent(7, 3, false);
- EXPECT_EQ(0u, tree.GetParent(1));
- EXPECT_EQ(0u, tree.GetParent(2));
- EXPECT_EQ(0u, tree.GetParent(3));
- EXPECT_EQ(1u, tree.GetParent(4));
- EXPECT_EQ(1u, tree.GetParent(5));
- EXPECT_EQ(2u, tree.GetParent(6));
- EXPECT_EQ(3u, tree.GetParent(7));
- EXPECT_EQ(4u, tree.GetParent(8));
- EXPECT_EQ(4u, tree.GetParent(9));
- EXPECT_EQ(5u, tree.GetParent(10));
- EXPECT_EQ(5u, tree.GetParent(11));
- EXPECT_EQ(6u, tree.GetParent(12));
- EXPECT_EQ(7u, tree.GetParent(13));
- EXPECT_EQ(7u, tree.GetParent(14));
- EXPECT_EQ(8u, tree.GetParent(15));
- EXPECT_EQ(8u, tree.GetParent(16));
- ASSERT_TRUE(peer.ValidateInvariants());
-
- EXPECT_EQ(peer.TotalChildWeights(0),
- tree.GetWeight(1) + tree.GetWeight(2) + tree.GetWeight(3));
- EXPECT_EQ(peer.TotalChildWeights(3), tree.GetWeight(7));
- EXPECT_EQ(peer.TotalChildWeights(7), tree.GetWeight(13) + tree.GetWeight(14));
- EXPECT_EQ(peer.TotalChildWeights(13), 0);
- EXPECT_EQ(peer.TotalChildWeights(14), 0);
-
- // Set all nodes ready to write.
- EXPECT_TRUE(tree.SetReady(1, true));
- EXPECT_TRUE(tree.SetReady(2, true));
- EXPECT_TRUE(tree.SetReady(3, true));
- EXPECT_TRUE(tree.SetReady(4, true));
- EXPECT_TRUE(tree.SetReady(5, true));
- EXPECT_TRUE(tree.SetReady(6, true));
- EXPECT_TRUE(tree.SetReady(7, true));
- EXPECT_TRUE(tree.SetReady(8, true));
- EXPECT_TRUE(tree.SetReady(9, true));
- EXPECT_TRUE(tree.SetReady(10, true));
- EXPECT_TRUE(tree.SetReady(11, true));
- EXPECT_TRUE(tree.SetReady(12, true));
- EXPECT_TRUE(tree.SetReady(13, true));
- EXPECT_TRUE(tree.SetReady(14, true));
- EXPECT_TRUE(tree.SetReady(15, true));
- EXPECT_TRUE(tree.SetReady(16, true));
-
- // Number of readable child weights should not change because
- // 7 has unblocked children.
- tree.SetBlocked(7, true);
- peer.PropagateNodeState(kRootNodeId);
- EXPECT_EQ(peer.TotalChildWeights(3), peer.TotalWriteableChildWeights(3));
-
- // Readable children for 7 should decrement.
- // Number of readable child weights for 3 still should not change.
- tree.SetBlocked(13, true);
- peer.PropagateNodeState(kRootNodeId);
- EXPECT_EQ(peer.TotalChildWeights(3), peer.TotalWriteableChildWeights(3));
- EXPECT_EQ(tree.GetWeight(14), peer.TotalWriteableChildWeights(7));
-
- // Once 14 becomes blocked, readable children for 7 and 3 should both be
- // decremented. Total readable weights at the root should still be the same
- // because 3 is still writeable.
- tree.SetBlocked(14, true);
- peer.PropagateNodeState(kRootNodeId);
- EXPECT_EQ(0, peer.TotalWriteableChildWeights(3));
- EXPECT_EQ(0, peer.TotalWriteableChildWeights(7));
- EXPECT_EQ(peer.TotalChildWeights(0),
- tree.GetWeight(1) + tree.GetWeight(2) + tree.GetWeight(3));
-
- // And now the root should be decremented as well.
- tree.SetBlocked(3, true);
- peer.PropagateNodeState(kRootNodeId);
- EXPECT_EQ(tree.GetWeight(1) + tree.GetWeight(2),
- peer.TotalWriteableChildWeights(0));
-
- // Unblocking 7 should propagate all the way up to the root.
- tree.SetBlocked(7, false);
- peer.PropagateNodeState(kRootNodeId);
- EXPECT_EQ(peer.TotalWriteableChildWeights(0),
- tree.GetWeight(1) + tree.GetWeight(2) + tree.GetWeight(3));
- EXPECT_EQ(peer.TotalWriteableChildWeights(3), tree.GetWeight(7));
- EXPECT_EQ(0, peer.TotalWriteableChildWeights(7));
-
- // Ditto for reblocking 7.
- tree.SetBlocked(7, true);
- peer.PropagateNodeState(kRootNodeId);
- EXPECT_EQ(peer.TotalWriteableChildWeights(0),
- tree.GetWeight(1) + tree.GetWeight(2));
- EXPECT_EQ(0, peer.TotalWriteableChildWeights(3));
- EXPECT_EQ(0, peer.TotalWriteableChildWeights(7));
- ASSERT_TRUE(peer.ValidateInvariants());
-}
-
-TEST_F(SpdyPriorityTreeTest, GetPriorityList) {
- PriorityList expected_list;
- PriorityList priority_list;
-
- /* Create the tree.
-
- 0
- /|\
- 1 2 3
- /| |\
- 4 5 6 7
- /
- 8
-
- */
- tree.AddNode(1, 0, 10, false);
- tree.AddNode(2, 0, 20, false);
- tree.AddNode(3, 0, 30, false);
- tree.AddNode(4, 1, 10, false);
- tree.AddNode(5, 1, 90, false);
- tree.AddNode(6, 2, 10, false);
- tree.AddNode(7, 2, 10, false);
- tree.AddNode(8, 4, 256, false);
-
- // Set all nodes ready to write.
- EXPECT_TRUE(tree.SetReady(1, true));
- EXPECT_TRUE(tree.SetReady(2, true));
- EXPECT_TRUE(tree.SetReady(3, true));
- EXPECT_TRUE(tree.SetReady(4, true));
- EXPECT_TRUE(tree.SetReady(5, true));
- EXPECT_TRUE(tree.SetReady(6, true));
- EXPECT_TRUE(tree.SetReady(7, true));
- EXPECT_TRUE(tree.SetReady(8, true));
-
- expected_list.push_back(PriorityNode(3, 1.0/2.0));
- expected_list.push_back(PriorityNode(2, 1.0/3.0));
- expected_list.push_back(PriorityNode(1, 1.0/6.0));
- priority_list = tree.GetPriorityList();
- EXPECT_EQ(expected_list, priority_list);
-
- // Check that the list updates as expected when a node gets blocked.
- EXPECT_TRUE(tree.SetReady(1, false));
- expected_list.clear();
- expected_list.push_back(PriorityNode(3, 1.0/2.0));
- expected_list.push_back(PriorityNode(2, 1.0/3.0));
- expected_list.push_back(PriorityNode(5, 0.9*1.0/6.0));
- expected_list.push_back(PriorityNode(4, 0.1*1.0/6.0));
- priority_list = tree.GetPriorityList();
- EXPECT_EQ(expected_list, priority_list);
-
- // Block multiple levels of nodes.
- EXPECT_TRUE(tree.SetReady(4, false));
- EXPECT_TRUE(tree.SetReady(5, false));
- expected_list.clear();
- expected_list.push_back(PriorityNode(3, 1.0/2.0));
- expected_list.push_back(PriorityNode(2, 1.0/3.0));
- expected_list.push_back(PriorityNode(8, 1.0/6.0));
- priority_list = tree.GetPriorityList();
- EXPECT_EQ(expected_list, priority_list);
-
- // Remove a node from the tree to make sure priorities
- // get redistributed accordingly.
- EXPECT_TRUE(tree.RemoveNode(1));
- expected_list.clear();
- expected_list.push_back(PriorityNode(3, 30.0/51.0));
- expected_list.push_back(PriorityNode(2, 20.0/51.0));
- expected_list.push_back(PriorityNode(8, 1.0/51.0));
- priority_list = tree.GetPriorityList();
- EXPECT_EQ(expected_list, priority_list);
-
- // Block an entire subtree.
- EXPECT_TRUE(tree.SetReady(8, false));
- expected_list.clear();
- expected_list.push_back(PriorityNode(3, 0.6));
- expected_list.push_back(PriorityNode(2, 0.4));
- priority_list = tree.GetPriorityList();
- EXPECT_EQ(expected_list, priority_list);
-
- // Unblock previously blocked nodes.
- EXPECT_TRUE(tree.SetReady(4, true));
- EXPECT_TRUE(tree.SetReady(5, true));
- expected_list.clear();
- expected_list.push_back(PriorityNode(3, 1.0/2.0));
- expected_list.push_back(PriorityNode(2, 1.0/3.0));
- expected_list.push_back(PriorityNode(5, 9.0/60.0));
- expected_list.push_back(PriorityNode(4, 1.0/60.0));
- priority_list = tree.GetPriorityList();
- EXPECT_EQ(expected_list, priority_list);
-
- // Blocked nodes in multiple subtrees.
- EXPECT_TRUE(tree.SetReady(2, false));
- EXPECT_TRUE(tree.SetReady(6, false));
- EXPECT_TRUE(tree.SetReady(7, false));
- expected_list.clear();
- expected_list.push_back(PriorityNode(3, 3.0/4.0));
- expected_list.push_back(PriorityNode(5, 9.0/40.0));
- expected_list.push_back(PriorityNode(4, 1.0/40.0));
- priority_list = tree.GetPriorityList();
- EXPECT_EQ(expected_list, priority_list);
-}
-
-TEST_F(SpdyPriorityTreeTest, CalculateRoundedWeights) {
- PriorityList expected_list;
- PriorityList priority_list;
-
- /* Create the tree.
-
- 0
- / \
- 1 2
- /| |\ |\
- 8 3 4 5 6 7
- */
- tree.AddNode(3, 0, 100, false);
- tree.AddNode(4, 0, 100, false);
- tree.AddNode(5, 0, 100, false);
- tree.AddNode(1, 0, 10, true);
- tree.AddNode(2, 0, 5, false);
- tree.AddNode(6, 2, 1, false);
- tree.AddNode(7, 2, 1, false);
- tree.AddNode(8, 1, 1, false);
-
- // Remove higher-level nodes.
- tree.RemoveNode(1);
- tree.RemoveNode(2);
-
- // 3.3 rounded down = 3.
- EXPECT_EQ(3, tree.GetWeight(3));
- EXPECT_EQ(3, tree.GetWeight(4));
- EXPECT_EQ(3, tree.GetWeight(5));
- // 2.5 rounded up = 3.
- EXPECT_EQ(3, tree.GetWeight(6));
- EXPECT_EQ(3, tree.GetWeight(7));
- // 0 is not a valid weight, so round up to 1.
- EXPECT_EQ(1, tree.GetWeight(8));
-}
-} // namespace test
-} // namespace gfe_spdy
diff --git a/chromium/net/spdy/spdy_protocol.cc b/chromium/net/spdy/spdy_protocol.cc
index ca48c5470ae..f69e02c10be 100644
--- a/chromium/net/spdy/spdy_protocol.cc
+++ b/chromium/net/spdy/spdy_protocol.cc
@@ -657,9 +657,9 @@ size_t SpdyConstants::GetPrefixLength(SpdyFrameType type,
}
size_t SpdyConstants::GetFrameMaximumSize(SpdyMajorVersion version) {
- if (version < HTTP2) {
+ if (version == SPDY3) {
// 24-bit length field plus eight-byte frame header.
- return ((1<<24) - 1) + 8;
+ return ((1 << 24) - 1) + 8;
} else {
// Max payload of 2^14 plus nine-byte frame header.
// TODO(mlavan): In HTTP/2 this is actually not a constant;
@@ -674,39 +674,15 @@ size_t SpdyConstants::GetSizeOfSizeField() {
}
size_t SpdyConstants::GetSettingSize(SpdyMajorVersion version) {
- return version <= SPDY3 ? 8 : 6;
+ return version == SPDY3 ? 8 : 6;
}
int32_t SpdyConstants::GetInitialStreamWindowSize(SpdyMajorVersion version) {
- return (version <= SPDY3) ? (64 * 1024) : (64 * 1024 - 1);
+ return (version == SPDY3) ? (64 * 1024) : (64 * 1024 - 1);
}
int32_t SpdyConstants::GetInitialSessionWindowSize(SpdyMajorVersion version) {
- return (version <= SPDY3) ? (64 * 1024) : (64 * 1024 - 1);
-}
-
-SpdyMajorVersion SpdyConstants::ParseMajorVersion(int version_number) {
- switch (version_number) {
- case 3:
- return SPDY3;
- case 4:
- return HTTP2;
- default:
- LOG(DFATAL) << "Unsupported SPDY version number: " << version_number;
- return SPDY3;
- }
-}
-
-int SpdyConstants::SerializeMajorVersion(SpdyMajorVersion version) {
- switch (version) {
- case SPDY3:
- return 3;
- case HTTP2:
- return 4;
- default:
- LOG(DFATAL) << "Unsupported SPDY major version: " << version;
- return -1;
- }
+ return (version == SPDY3) ? (64 * 1024) : (64 * 1024 - 1);
}
std::string SpdyConstants::GetVersionString(SpdyMajorVersion version) {
diff --git a/chromium/net/spdy/spdy_protocol.h b/chromium/net/spdy/spdy_protocol.h
index 86eb9b1a400..e22f89c0260 100644
--- a/chromium/net/spdy/spdy_protocol.h
+++ b/chromium/net/spdy/spdy_protocol.h
@@ -35,11 +35,12 @@ namespace net {
// that the enum value SPDYn maps to the integer n.
enum SpdyMajorVersion {
SPDY3 = 1,
- SPDY_MIN_VERSION = SPDY3,
HTTP2,
- SPDY_MAX_VERSION = HTTP2
};
+// 15 bit version field for SPDY/3 frames.
+const uint16_t kSpdy3Version = 3;
+
// A SPDY stream id is a 31 bit entity.
typedef uint32_t SpdyStreamId;
@@ -518,21 +519,12 @@ class NET_EXPORT_PRIVATE SpdyConstants {
// Initial window size for a session in bytes.
static int32_t GetInitialSessionWindowSize(SpdyMajorVersion version);
- static SpdyMajorVersion ParseMajorVersion(int version_number);
-
- static int SerializeMajorVersion(SpdyMajorVersion version);
-
static std::string GetVersionString(SpdyMajorVersion version);
};
-class SpdyFrame;
-typedef SpdyFrame SpdySerializedFrame;
-
class SpdyFrameVisitor;
// Intermediate representation for SPDY frames.
-// TODO(hkhalil): Rename this class to SpdyFrame when the existing SpdyFrame is
-// gone.
class NET_EXPORT_PRIVATE SpdyFrameIR {
public:
virtual ~SpdyFrameIR() {}
@@ -990,35 +982,50 @@ class NET_EXPORT_PRIVATE SpdyPriorityIR : public SpdyFrameWithStreamIdIR {
DISALLOW_COPY_AND_ASSIGN(SpdyPriorityIR);
};
-// -------------------------------------------------------------------------
-// Wrapper classes for various SPDY frames.
-
-// All Spdy Frame types derive from this SpdyFrame class.
-class SpdyFrame {
+class SpdySerializedFrame {
public:
- // Create a SpdyFrame using a pre-created buffer.
- // If |owns_buffer| is true, this class takes ownership of the buffer
- // and will delete it on cleanup. The buffer must have been created using
- // new char[].
+ SpdySerializedFrame()
+ : frame_(const_cast<char*>("")), size_(0), owns_buffer_(false) {}
+
+ // Create a valid SpdySerializedFrame using a pre-created buffer.
+ // If |owns_buffer| is true, this class takes ownership of the buffer and will
+ // delete it on cleanup. The buffer must have been created using new char[].
// If |owns_buffer| is false, the caller retains ownership of the buffer and
// is responsible for making sure the buffer outlives this frame. In other
// words, this class does NOT create a copy of the buffer.
- SpdyFrame(char* data, size_t size, bool owns_buffer)
- : frame_(data),
- size_(size),
- owns_buffer_(owns_buffer) {
- DCHECK(frame_);
+ SpdySerializedFrame(char* data, size_t size, bool owns_buffer)
+ : frame_(data), size_(size), owns_buffer_(owns_buffer) {}
+
+ SpdySerializedFrame(SpdySerializedFrame&& other)
+ : frame_(other.frame_),
+ size_(other.size_),
+ owns_buffer_(other.owns_buffer_) {
+ // |other| is no longer responsible for the buffer.
+ other.owns_buffer_ = false;
+ }
+
+ SpdySerializedFrame& operator=(SpdySerializedFrame&& other) {
+ // Free buffer if necessary.
+ if (owns_buffer_) {
+ delete[] frame_;
+ }
+ // Take over |other|.
+ frame_ = other.frame_;
+ size_ = other.size_;
+ owns_buffer_ = other.owns_buffer_;
+ // |other| is no longer responsible for the buffer.
+ other.owns_buffer_ = false;
+ return *this;
}
- ~SpdyFrame() {
+ ~SpdySerializedFrame() {
if (owns_buffer_) {
- delete [] frame_;
+ delete[] frame_;
}
- frame_ = NULL;
}
- // Provides access to the frame bytes, which is a buffer containing
- // the frame packed as expected for sending over the wire.
+ // Provides access to the frame bytes, which is a buffer containing the frame
+ // packed as expected for sending over the wire.
char* data() const { return frame_; }
// Returns the actual size of the underlying buffer.
@@ -1030,7 +1037,7 @@ class SpdyFrame {
private:
size_t size_;
bool owns_buffer_;
- DISALLOW_COPY_AND_ASSIGN(SpdyFrame);
+ DISALLOW_COPY_AND_ASSIGN(SpdySerializedFrame);
};
// This interface is for classes that want to process SpdyFrameIRs without
diff --git a/chromium/net/spdy/spdy_proxy_client_socket.cc b/chromium/net/spdy/spdy_proxy_client_socket.cc
index df2530b19dc..2d75c4cdc56 100644
--- a/chromium/net/spdy/spdy_proxy_client_socket.cc
+++ b/chromium/net/spdy/spdy_proxy_client_socket.cc
@@ -18,7 +18,6 @@
#include "base/values.h"
#include "net/base/auth.h"
#include "net/base/io_buffer.h"
-#include "net/base/net_util.h"
#include "net/http/http_auth_cache.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_request_info.h"
@@ -171,10 +170,6 @@ bool SpdyProxyClientSocket::WasEverUsed() const {
return was_ever_used_ || (spdy_stream_.get() && spdy_stream_->WasEverUsed());
}
-bool SpdyProxyClientSocket::UsingTCPFastOpen() const {
- return false;
-}
-
bool SpdyProxyClientSocket::WasNpnNegotiated() const {
return false;
}
@@ -496,7 +491,7 @@ void SpdyProxyClientSocket::OnDataSent() {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&SpdyProxyClientSocket::RunCallback,
write_callback_weak_factory_.GetWeakPtr(),
- ResetAndReturn(&write_callback_), rv));
+ base::ResetAndReturn(&write_callback_), rv));
}
void SpdyProxyClientSocket::OnTrailers(const SpdyHeaderBlock& trailers) {
diff --git a/chromium/net/spdy/spdy_proxy_client_socket.h b/chromium/net/spdy/spdy_proxy_client_socket.h
index 9dc9cff15be..f773666ed22 100644
--- a/chromium/net/spdy/spdy_proxy_client_socket.h
+++ b/chromium/net/spdy/spdy_proxy_client_socket.h
@@ -70,7 +70,6 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket,
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
bool WasNpnNegotiated() const override;
NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(SSLInfo* ssl_info) override;
diff --git a/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc b/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
index 2fcf3f431f8..6e83c3989a3 100644
--- a/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
+++ b/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -92,13 +92,13 @@ class SpdyProxyClientSocketTest : public PlatformTest,
size_t writes_count);
void PopulateConnectRequestIR(SpdyHeaderBlock* syn_ir);
void PopulateConnectReplyIR(SpdyHeaderBlock* block, const char* status);
- SpdyFrame* ConstructConnectRequestFrame();
- SpdyFrame* ConstructConnectAuthRequestFrame();
- SpdyFrame* ConstructConnectReplyFrame();
- SpdyFrame* ConstructConnectAuthReplyFrame();
- SpdyFrame* ConstructConnectRedirectReplyFrame();
- SpdyFrame* ConstructConnectErrorReplyFrame();
- SpdyFrame* ConstructBodyFrame(const char* data, int length);
+ SpdySerializedFrame* ConstructConnectRequestFrame();
+ SpdySerializedFrame* ConstructConnectAuthRequestFrame();
+ SpdySerializedFrame* ConstructConnectReplyFrame();
+ SpdySerializedFrame* ConstructConnectAuthReplyFrame();
+ SpdySerializedFrame* ConstructConnectRedirectReplyFrame();
+ SpdySerializedFrame* ConstructConnectErrorReplyFrame();
+ SpdySerializedFrame* ConstructBodyFrame(const char* data, int length);
scoped_refptr<IOBufferWithSize> CreateBuffer(const char* data, int size);
void AssertConnectSucceeds();
void AssertConnectFails(int result);
@@ -169,7 +169,7 @@ SpdyProxyClientSocketTest::SpdyProxyClientSocketTest()
read_buf_(NULL),
session_deps_(GetProtocol()),
connect_data_(SYNCHRONOUS, OK),
- framer_(spdy_util_.spdy_version(), false),
+ framer_(spdy_util_.spdy_version()),
user_agent_(kUserAgent),
url_(kRequestUrl),
proxy_host_port_(kProxyHost, kProxyPort),
@@ -179,14 +179,12 @@ SpdyProxyClientSocketTest::SpdyProxyClientSocketTest()
proxy_,
PRIVACY_MODE_DISABLED) {
session_deps_.net_log = net_log_.bound().net_log();
- SpdySession::SetPriorityDependencyDefaultForTesting(
- GetDependenciesFromPriority());
+ session_deps_.enable_priority_dependencies = GetDependenciesFromPriority();
}
SpdyProxyClientSocketTest::~SpdyProxyClientSocketTest() {
EXPECT_TRUE(data_->AllWriteDataConsumed());
EXPECT_TRUE(data_->AllReadDataConsumed());
- SpdySession::SetPriorityDependencyDefaultForTesting(false);
}
void SpdyProxyClientSocketTest::TearDown() {
@@ -337,24 +335,24 @@ void SpdyProxyClientSocketTest::PopulateConnectReplyIR(SpdyHeaderBlock* block,
}
// Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
-SpdyFrame*
-SpdyProxyClientSocketTest::ConstructConnectRequestFrame() {
+SpdySerializedFrame* SpdyProxyClientSocketTest::ConstructConnectRequestFrame() {
SpdyHeaderBlock block;
PopulateConnectRequestIR(&block);
- return spdy_util_.ConstructSpdySyn(kStreamId, block, LOWEST, false, false);
+ return spdy_util_.ConstructSpdySyn(kStreamId, block, LOWEST, false);
}
// Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes
// Proxy-Authorization headers.
-SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() {
+SpdySerializedFrame*
+SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() {
SpdyHeaderBlock block;
PopulateConnectRequestIR(&block);
block["proxy-authorization"] = "Basic Zm9vOmJhcg==";
- return spdy_util_.ConstructSpdySyn(kStreamId, block, LOWEST, false, false);
+ return spdy_util_.ConstructSpdySyn(kStreamId, block, LOWEST, false);
}
// Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT.
-SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() {
+SpdySerializedFrame* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() {
SpdyHeaderBlock block;
PopulateConnectReplyIR(&block, "200");
SpdySynReplyIR reply_ir(kStreamId);
@@ -363,7 +361,8 @@ SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() {
// Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT,
// including Proxy-Authenticate headers.
-SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() {
+SpdySerializedFrame*
+SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() {
SpdyHeaderBlock block;
PopulateConnectReplyIR(&block, "407");
block["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
@@ -371,7 +370,8 @@ SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() {
}
// Constructs a SPDY SYN_REPLY frame with an HTTP 302 redirect.
-SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectRedirectReplyFrame() {
+SpdySerializedFrame*
+SpdyProxyClientSocketTest::ConstructConnectRedirectReplyFrame() {
SpdyHeaderBlock block;
PopulateConnectReplyIR(&block, "302");
block["location"] = kRedirectUrl;
@@ -380,13 +380,14 @@ SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectRedirectReplyFrame() {
}
// Constructs a SPDY SYN_REPLY frame with an HTTP 500 error.
-SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() {
+SpdySerializedFrame*
+SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() {
SpdyHeaderBlock block;
PopulateConnectReplyIR(&block, "500");
return spdy_util_.ConstructSpdyReply(kStreamId, block);
}
-SpdyFrame* SpdyProxyClientSocketTest::ConstructBodyFrame(
+SpdySerializedFrame* SpdyProxyClientSocketTest::ConstructBodyFrame(
const char* data,
int length) {
return framer_.CreateDataFrame(kStreamId, data, length, DATA_FLAG_NONE);
@@ -395,12 +396,12 @@ SpdyFrame* SpdyProxyClientSocketTest::ConstructBodyFrame(
// ----------- Connect
TEST_P(SpdyProxyClientSocketTest, ConnectSendsCorrectRequest) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
};
@@ -415,12 +416,12 @@ TEST_P(SpdyProxyClientSocketTest, ConnectSendsCorrectRequest) {
}
TEST_P(SpdyProxyClientSocketTest, ConnectWithAuthRequested) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectAuthReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectAuthReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
};
@@ -435,12 +436,12 @@ TEST_P(SpdyProxyClientSocketTest, ConnectWithAuthRequested) {
}
TEST_P(SpdyProxyClientSocketTest, ConnectWithAuthCredentials) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectAuthRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectAuthRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
};
@@ -454,14 +455,14 @@ TEST_P(SpdyProxyClientSocketTest, ConnectWithAuthCredentials) {
}
TEST_P(SpdyProxyClientSocketTest, ConnectRedirects) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 3),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectRedirectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectRedirectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
};
@@ -487,12 +488,12 @@ TEST_P(SpdyProxyClientSocketTest, ConnectRedirects) {
}
TEST_P(SpdyProxyClientSocketTest, ConnectFails) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
MockRead(ASYNC, 0, 1), // EOF
};
@@ -509,14 +510,14 @@ TEST_P(SpdyProxyClientSocketTest, ConnectFails) {
// ----------- WasEverUsed
TEST_P(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 3),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
};
@@ -536,12 +537,12 @@ TEST_P(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) {
// ----------- GetPeerAddress
TEST_P(SpdyProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
MockRead(ASYNC, 0, 3), // EOF
@@ -569,16 +570,16 @@ TEST_P(SpdyProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) {
// ----------- Write
TEST_P(SpdyProxyClientSocketTest, WriteSendsDataInDataFrame) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
- scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
CreateMockWrite(*msg1, 3, SYNCHRONOUS),
CreateMockWrite(*msg2, 4, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
};
@@ -593,15 +594,15 @@ TEST_P(SpdyProxyClientSocketTest, WriteSendsDataInDataFrame) {
TEST_P(SpdyProxyClientSocketTest, WriteSplitsLargeDataIntoMultipleFrames) {
std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
- scoped_ptr<SpdyFrame> chunk(ConstructBodyFrame(chunk_data.data(),
- chunk_data.length()));
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> chunk(
+ ConstructBodyFrame(chunk_data.data(), chunk_data.length()));
MockWrite writes[] = {CreateMockWrite(*conn, 0, SYNCHRONOUS),
CreateMockWrite(*chunk, 3, SYNCHRONOUS),
CreateMockWrite(*chunk, 4, SYNCHRONOUS),
CreateMockWrite(*chunk, 5, SYNCHRONOUS)};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
};
@@ -622,13 +623,13 @@ TEST_P(SpdyProxyClientSocketTest, WriteSplitsLargeDataIntoMultipleFrames) {
// ----------- Read
TEST_P(SpdyProxyClientSocketTest, ReadReadsDataInDataFrame) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
CreateMockRead(*msg1, 3, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
@@ -644,14 +645,14 @@ TEST_P(SpdyProxyClientSocketTest, ReadReadsDataInDataFrame) {
}
TEST_P(SpdyProxyClientSocketTest, ReadDataFromBufferedFrames) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
- scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
CreateMockRead(*msg1, 3, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 4),
@@ -671,14 +672,14 @@ TEST_P(SpdyProxyClientSocketTest, ReadDataFromBufferedFrames) {
}
TEST_P(SpdyProxyClientSocketTest, ReadDataMultipleBufferedFrames) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
- scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC),
MockRead(ASYNC, ERR_IO_PENDING, 2),
@@ -700,14 +701,14 @@ TEST_P(SpdyProxyClientSocketTest, ReadDataMultipleBufferedFrames) {
TEST_P(SpdyProxyClientSocketTest,
LargeReadWillMergeDataFromDifferentFrames) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
- scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC),
MockRead(ASYNC, ERR_IO_PENDING, 2),
@@ -729,15 +730,15 @@ TEST_P(SpdyProxyClientSocketTest,
}
TEST_P(SpdyProxyClientSocketTest, MultipleShortReadsThenMoreRead) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
- scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
- scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
+ scoped_ptr<SpdySerializedFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC),
MockRead(ASYNC, ERR_IO_PENDING, 2),
@@ -763,15 +764,15 @@ TEST_P(SpdyProxyClientSocketTest, MultipleShortReadsThenMoreRead) {
}
TEST_P(SpdyProxyClientSocketTest, ReadWillSplitDataFromLargeFrame) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
- scoped_ptr<SpdyFrame> msg33(ConstructBodyFrame(kMsg33, kLen33));
- scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> msg33(ConstructBodyFrame(kMsg33, kLen33));
+ scoped_ptr<SpdySerializedFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC),
MockRead(ASYNC, ERR_IO_PENDING, 2),
@@ -795,13 +796,13 @@ TEST_P(SpdyProxyClientSocketTest, ReadWillSplitDataFromLargeFrame) {
}
TEST_P(SpdyProxyClientSocketTest, MultipleReadsFromSameLargeFrame) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg333(ConstructBodyFrame(kMsg333, kLen333));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg333(ConstructBodyFrame(kMsg333, kLen333));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
CreateMockRead(*msg333, 3, ASYNC),
@@ -826,14 +827,14 @@ TEST_P(SpdyProxyClientSocketTest, MultipleReadsFromSameLargeFrame) {
}
TEST_P(SpdyProxyClientSocketTest, ReadAuthResponseBody) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectAuthReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
- scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectAuthReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC),
MockRead(ASYNC, ERR_IO_PENDING, 2),
@@ -854,14 +855,14 @@ TEST_P(SpdyProxyClientSocketTest, ReadAuthResponseBody) {
}
TEST_P(SpdyProxyClientSocketTest, ReadErrorResponseBody) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectErrorReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
- scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectErrorReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC),
CreateMockRead(*msg1, 2, ASYNC),
@@ -877,16 +878,16 @@ TEST_P(SpdyProxyClientSocketTest, ReadErrorResponseBody) {
// ----------- Reads and Writes
TEST_P(SpdyProxyClientSocketTest, AsyncReadAroundWrite) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
- scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
CreateMockWrite(*msg2, 4, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
- scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC),
MockRead(ASYNC, ERR_IO_PENDING, 2),
@@ -915,16 +916,16 @@ TEST_P(SpdyProxyClientSocketTest, AsyncReadAroundWrite) {
}
TEST_P(SpdyProxyClientSocketTest, AsyncWriteAroundReads) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
- scoped_ptr<SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
MockWrite(ASYNC, ERR_IO_PENDING, 7), CreateMockWrite(*msg2, 8, ASYNC),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
- scoped_ptr<SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
CreateMockRead(*msg1, 3, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 4),
@@ -953,12 +954,12 @@ TEST_P(SpdyProxyClientSocketTest, AsyncWriteAroundReads) {
// Reading from an already closed socket should return 0
TEST_P(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsZero) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
MockRead(ASYNC, 0, 3), // EOF
@@ -979,12 +980,12 @@ TEST_P(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsZero) {
// Read pending when socket is closed should return 0
TEST_P(SpdyProxyClientSocketTest, PendingReadOnCloseReturnsZero) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
MockRead(ASYNC, 0, 3), // EOF
@@ -1004,14 +1005,14 @@ TEST_P(SpdyProxyClientSocketTest, PendingReadOnCloseReturnsZero) {
// Reading from a disconnected socket is an error
TEST_P(SpdyProxyClientSocketTest,
ReadOnDisconnectSocketReturnsNotConnected) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 3),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
};
@@ -1032,13 +1033,13 @@ TEST_P(SpdyProxyClientSocketTest,
// Reading buffered data from an already closed socket should return
// buffered data, then 0.
TEST_P(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsBufferedData) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
CreateMockRead(*msg1, 3, ASYNC), MockRead(ASYNC, 0, 4), // EOF
@@ -1064,13 +1065,13 @@ TEST_P(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsBufferedData) {
// Calling Write() on a closed socket is an error
TEST_P(SpdyProxyClientSocketTest, WriteOnClosedStream) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
MockRead(ASYNC, 0, 3), // EOF
@@ -1089,15 +1090,15 @@ TEST_P(SpdyProxyClientSocketTest, WriteOnClosedStream) {
// Calling Write() on a disconnected socket is an error.
TEST_P(SpdyProxyClientSocketTest, WriteOnDisconnectedSocket) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 3),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
};
@@ -1119,13 +1120,13 @@ TEST_P(SpdyProxyClientSocketTest, WriteOnDisconnectedSocket) {
// If the socket is closed with a pending Write(), the callback
// should be called with ERR_CONNECTION_CLOSED.
TEST_P(SpdyProxyClientSocketTest, WritePendingOnClose) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 3),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
};
@@ -1150,14 +1151,14 @@ TEST_P(SpdyProxyClientSocketTest, WritePendingOnClose) {
// If the socket is Disconnected with a pending Write(), the callback
// should not be called.
TEST_P(SpdyProxyClientSocketTest, DisconnectWithWritePending) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 3),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
};
@@ -1184,14 +1185,14 @@ TEST_P(SpdyProxyClientSocketTest, DisconnectWithWritePending) {
// If the socket is Disconnected with a pending Read(), the callback
// should not be called.
TEST_P(SpdyProxyClientSocketTest, DisconnectWithReadPending) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 3),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2),
};
@@ -1218,13 +1219,13 @@ TEST_P(SpdyProxyClientSocketTest, DisconnectWithReadPending) {
// If the socket is Reset when both a read and write are pending,
// both should be called back.
TEST_P(SpdyProxyClientSocketTest, RstWithReadAndWritePending) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
@@ -1260,15 +1261,15 @@ TEST_P(SpdyProxyClientSocketTest, RstWithReadAndWritePending) {
// Makes sure the proxy client socket's source gets the expected NetLog events
// and only the expected NetLog events (No SpdySession events).
TEST_P(SpdyProxyClientSocketTest, NetLog) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS), CreateMockWrite(*rst, 5),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
CreateMockRead(*msg1, 3, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
@@ -1346,13 +1347,13 @@ class DeleteSockCallback : public TestCompletionCallbackBase {
// read callback causes the socket to be deleted, the write callback should
// not be called.
TEST_P(SpdyProxyClientSocketTest, RstWithReadAndWritePendingDelete) {
- scoped_ptr<SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<SpdySerializedFrame> conn(ConstructConnectRequestFrame());
MockWrite writes[] = {
CreateMockWrite(*conn, 0, SYNCHRONOUS),
};
- scoped_ptr<SpdyFrame> resp(ConstructConnectReplyFrame());
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockRead reads[] = {
CreateMockRead(*resp, 1, ASYNC), MockRead(ASYNC, ERR_IO_PENDING, 2),
diff --git a/chromium/net/spdy/spdy_session.cc b/chromium/net/spdy/spdy_session.cc
index 0e4a3e8c3a0..d4c6f06c08b 100644
--- a/chromium/net/spdy/spdy_session.cc
+++ b/chromium/net/spdy/spdy_session.cc
@@ -13,7 +13,6 @@
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/profiler/scoped_tracker.h"
@@ -25,11 +24,12 @@
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "crypto/ec_private_key.h"
#include "crypto/ec_signature_creator.h"
#include "net/base/connection_type_histograms.h"
-#include "net/base/net_util.h"
+#include "net/base/proxy_delegate.h"
#include "net/cert/asn1_util.h"
#include "net/cert/cert_verify_result.h"
#include "net/http/http_log_util.h"
@@ -38,6 +38,7 @@
#include "net/http/http_util.h"
#include "net/http/transport_security_state.h"
#include "net/log/net_log.h"
+#include "net/proxy/proxy_server.h"
#include "net/socket/ssl_client_socket.h"
#include "net/spdy/spdy_buffer_producer.h"
#include "net/spdy/spdy_frame_builder.h"
@@ -60,14 +61,6 @@ const int kHungIntervalSeconds = 10;
// Minimum seconds that unclaimed pushed streams will be kept in memory.
const int kMinPushedStreamLifetimeSeconds = 300;
-// Field trial constants
-const char kSpdyDependenciesFieldTrial[] = "SpdyEnableDependencies";
-const char kSpdyDepencenciesFieldTrialEnable[] = "Enable";
-
-// Whether the creation of SPDY dependencies based on priority is
-// enabled by default.
-static bool priority_dependency_enabled_default = false;
-
scoped_ptr<base::ListValue> SpdyHeaderBlockToListValue(
const SpdyHeaderBlock& headers,
NetLogCaptureMode capture_mode) {
@@ -98,6 +91,28 @@ scoped_ptr<base::Value> NetLogSpdySynStreamSentCallback(
return std::move(dict);
}
+scoped_ptr<base::Value> NetLogSpdyHeadersSentCallback(
+ const SpdyHeaderBlock* headers,
+ bool fin,
+ SpdyStreamId stream_id,
+ bool has_priority,
+ uint32_t priority,
+ SpdyStreamId parent_stream_id,
+ bool exclusive,
+ NetLogCaptureMode capture_mode) {
+ scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ dict->Set("headers", SpdyHeaderBlockToListValue(*headers, capture_mode));
+ dict->SetBoolean("fin", fin);
+ dict->SetInteger("stream_id", stream_id);
+ dict->SetBoolean("has_priority", has_priority);
+ if (has_priority) {
+ dict->SetInteger("parent_stream_id", parent_stream_id);
+ dict->SetInteger("priority", static_cast<int>(priority));
+ dict->SetBoolean("exclusive", exclusive);
+ }
+ return std::move(dict);
+}
+
scoped_ptr<base::Value> NetLogSpdySynStreamReceivedCallback(
const SpdyHeaderBlock* headers,
bool fin,
@@ -315,7 +330,7 @@ template <typename T, size_t N> size_t GetTotalSize(const T (&arr)[N]) {
// SpdyStreamRequest weak pointers.
class RequestEquals {
public:
- RequestEquals(const base::WeakPtr<SpdyStreamRequest>& request)
+ explicit RequestEquals(const base::WeakPtr<SpdyStreamRequest>& request)
: request_(request) {}
bool operator()(const base::WeakPtr<SpdyStreamRequest>& request) const {
@@ -334,7 +349,7 @@ const size_t kMaxConcurrentStreamLimit = 256;
SpdyProtocolErrorDetails MapFramerErrorToProtocolError(
SpdyFramer::SpdyError err) {
- switch(err) {
+ switch (err) {
case SpdyFramer::SPDY_NO_ERROR:
return SPDY_ERROR_NO_ERROR;
case SpdyFramer::SPDY_INVALID_CONTROL_FRAME:
@@ -359,6 +374,8 @@ SpdyProtocolErrorDetails MapFramerErrorToProtocolError(
return SPDY_ERROR_INVALID_CONTROL_FRAME_FLAGS;
case SpdyFramer::SPDY_UNEXPECTED_FRAME:
return SPDY_ERROR_UNEXPECTED_FRAME;
+ case SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE:
+ return SPDY_ERROR_INVALID_CONTROL_FRAME_SIZE;
default:
NOTREACHED();
return static_cast<SpdyProtocolErrorDetails>(-1);
@@ -391,6 +408,8 @@ Error MapFramerErrorToNetError(SpdyFramer::SpdyError err) {
return ERR_SPDY_PROTOCOL_ERROR;
case SpdyFramer::SPDY_UNEXPECTED_FRAME:
return ERR_SPDY_PROTOCOL_ERROR;
+ case SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE:
+ return ERR_SPDY_FRAME_SIZE_ERROR;
default:
NOTREACHED();
return ERR_SPDY_PROTOCOL_ERROR;
@@ -399,7 +418,7 @@ Error MapFramerErrorToNetError(SpdyFramer::SpdyError err) {
SpdyProtocolErrorDetails MapRstStreamStatusToProtocolError(
SpdyRstStreamStatus status) {
- switch(status) {
+ switch (status) {
case RST_STREAM_PROTOCOL_ERROR:
return STATUS_CODE_PROTOCOL_ERROR;
case RST_STREAM_INVALID_STREAM:
@@ -570,15 +589,51 @@ SpdySession::ActiveStreamInfo::ActiveStreamInfo(SpdyStream* stream)
SpdySession::ActiveStreamInfo::~ActiveStreamInfo() {}
-SpdySession::PushedStreamInfo::PushedStreamInfo() : stream_id(0) {}
+SpdySession::UnclaimedPushedStreamContainer::UnclaimedPushedStreamContainer(
+ SpdySession* spdy_session)
+ : spdy_session_(spdy_session) {}
+SpdySession::UnclaimedPushedStreamContainer::~UnclaimedPushedStreamContainer() {
+}
-SpdySession::PushedStreamInfo::PushedStreamInfo(
- SpdyStreamId stream_id,
- base::TimeTicks creation_time)
- : stream_id(stream_id),
- creation_time(creation_time) {}
+size_t SpdySession::UnclaimedPushedStreamContainer::erase(const GURL& url) {
+ const_iterator it = find(url);
+ if (it != end()) {
+ streams_.erase(it);
+ return 1;
+ }
+ return 0;
+}
-SpdySession::PushedStreamInfo::~PushedStreamInfo() {}
+SpdySession::UnclaimedPushedStreamContainer::iterator
+SpdySession::UnclaimedPushedStreamContainer::erase(const_iterator it) {
+ DCHECK(spdy_session_->pool_);
+ DCHECK(it != end());
+ // Only allow cross-origin push for secure resources.
+ if (it->first.SchemeIsCryptographic()) {
+ spdy_session_->pool_->UnregisterUnclaimedPushedStream(it->first,
+ spdy_session_);
+ }
+ return streams_.erase(it);
+}
+
+SpdySession::UnclaimedPushedStreamContainer::iterator
+SpdySession::UnclaimedPushedStreamContainer::insert(
+ const_iterator position,
+ const GURL& url,
+ SpdyStreamId stream_id,
+ const base::TimeTicks& creation_time) {
+ DCHECK(spdy_session_->pool_);
+ // Only allow cross-origin push for https resources.
+ if (url.SchemeIsCryptographic()) {
+ spdy_session_->pool_->RegisterUnclaimedPushedStream(
+ url, spdy_session_->GetWeakPtr());
+ }
+ return streams_.insert(
+ position,
+ std::make_pair(
+ url, SpdySession::UnclaimedPushedStreamContainer::PushedStreamInfo(
+ stream_id, creation_time)));
+}
// static
bool SpdySession::CanPool(TransportSecurityState* transport_security_state,
@@ -607,11 +662,7 @@ bool SpdySession::CanPool(TransportSecurityState* transport_security_state,
std::string pinning_failure_log;
// DISABLE_PIN_REPORTS is set here because this check can fail in
// normal operation without being indicative of a misconfiguration or
- // attack.
- //
- // TODO(estark): replace 0 below with the port of the connection
- // (though it won't actually be used since reports aren't getting
- // sent).
+ // attack. Port is left at 0 as it is never used.
if (!transport_security_state->CheckPublicKeyPins(
HostPortPair(new_hostname, 0), ssl_info.is_issued_by_known_root,
ssl_info.public_key_hashes, ssl_info.unverified_cert.get(),
@@ -629,14 +680,13 @@ SpdySession::SpdySession(
TransportSecurityState* transport_security_state,
bool verify_domain_authentication,
bool enable_sending_initial_data,
- bool enable_compression,
bool enable_ping_based_connection_checking,
+ bool enable_priority_dependencies,
NextProto default_protocol,
size_t session_max_recv_window_size,
size_t stream_max_recv_window_size,
- size_t initial_max_concurrent_streams,
TimeFunc time_func,
- const HostPortPair& trusted_spdy_proxy,
+ ProxyDelegate* proxy_delegate,
NetLog* net_log)
: in_io_loop_(false),
spdy_session_key_(spdy_session_key),
@@ -646,6 +696,7 @@ SpdySession::SpdySession(
read_buffer_(new IOBuffer(kReadBufferSize)),
stream_hi_water_mark_(kFirstStreamId),
last_accepted_push_stream_id_(0),
+ unclaimed_pushed_streams_(this),
num_pushed_streams_(0u),
num_active_pushed_streams_(0u),
in_flight_write_frame_type_(DATA),
@@ -656,9 +707,7 @@ SpdySession::SpdySession(
read_state_(READ_STATE_DO_READ),
write_state_(WRITE_STATE_IDLE),
error_on_close_(OK),
- max_concurrent_streams_(initial_max_concurrent_streams == 0
- ? kInitialMaxConcurrentStreams
- : initial_max_concurrent_streams),
+ max_concurrent_streams_(kInitialMaxConcurrentStreams),
max_concurrent_pushed_streams_(kMaxConcurrentPushedStreams),
streams_initiated_count_(0),
streams_pushed_count_(0),
@@ -684,16 +733,15 @@ SpdySession::SpdySession(
net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_HTTP2_SESSION)),
verify_domain_authentication_(verify_domain_authentication),
enable_sending_initial_data_(enable_sending_initial_data),
- enable_compression_(enable_compression),
enable_ping_based_connection_checking_(
enable_ping_based_connection_checking),
protocol_(default_protocol),
connection_at_risk_of_loss_time_(
base::TimeDelta::FromSeconds(kDefaultConnectionAtRiskOfLossSeconds)),
hung_interval_(base::TimeDelta::FromSeconds(kHungIntervalSeconds)),
- trusted_spdy_proxy_(trusted_spdy_proxy),
+ proxy_delegate_(proxy_delegate),
time_func_(time_func),
- send_priority_dependency_(priority_dependency_enabled_default),
+ priority_dependencies_enabled_(enable_priority_dependencies),
weak_factory_(this) {
DCHECK_GE(protocol_, kProtoSPDYMinimumVersion);
DCHECK_LE(protocol_, kProtoSPDYMaximumVersion);
@@ -703,10 +751,6 @@ SpdySession::SpdySession(
base::Bind(&NetLogSpdySessionCallback, &host_port_proxy_pair()));
next_unclaimed_push_stream_sweep_time_ = time_func_() +
base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds);
- if (base::FieldTrialList::FindFullName(kSpdyDependenciesFieldTrial) ==
- kSpdyDepencenciesFieldTrialEnable) {
- send_priority_dependency_ = true;
- }
// TODO(mbelshe): consider randomization of the stream_hi_water_mark.
}
@@ -762,14 +806,12 @@ void SpdySession::InitializeWithSocket(
session_recv_window_size_ = GetDefaultInitialWindowSize(protocol_);
buffered_spdy_framer_.reset(
- new BufferedSpdyFramer(NextProtoToSpdyMajorVersion(protocol_),
- enable_compression_));
+ new BufferedSpdyFramer(NextProtoToSpdyMajorVersion(protocol_)));
buffered_spdy_framer_->set_visitor(this);
buffered_spdy_framer_->set_debug_visitor(this);
UMA_HISTOGRAM_ENUMERATION(
- "Net.SpdyVersion2",
- protocol_ - kProtoSPDYHistogramOffset,
- kProtoSPDYMaximumVersion - kProtoSPDYMinimumVersion + 1);
+ "Net.SpdyVersion3", protocol_ - kProtoSPDYHistogramOffset,
+ kProtoSPDYMaximumVersion - kProtoSPDYHistogramOffset + 1);
net_log_.AddEvent(
NetLog::TYPE_HTTP2_SESSION_INITIALIZED,
@@ -862,8 +904,7 @@ int SpdySession::TryCreateStream(
if (err != OK)
return err;
- if (!max_concurrent_streams_ ||
- (active_streams_.size() + created_streams_.size() - num_pushed_streams_ <
+ if ((active_streams_.size() + created_streams_.size() - num_pushed_streams_ <
max_concurrent_streams_)) {
return CreateStream(*request, stream);
}
@@ -970,16 +1011,10 @@ base::WeakPtr<SpdyStreamRequest> SpdySession::GetNextPendingStreamRequest() {
}
void SpdySession::ProcessPendingStreamRequests() {
- // Like |max_concurrent_streams_|, 0 means infinite for
- // |max_requests_to_process|.
- size_t max_requests_to_process = 0;
- if (max_concurrent_streams_ != 0) {
- max_requests_to_process =
- max_concurrent_streams_ -
- (active_streams_.size() + created_streams_.size());
- }
- for (size_t i = 0;
- max_requests_to_process == 0 || i < max_requests_to_process; ++i) {
+ size_t max_requests_to_process =
+ max_concurrent_streams_ -
+ (active_streams_.size() + created_streams_.size());
+ for (size_t i = 0; i < max_requests_to_process; ++i) {
base::WeakPtr<SpdyStreamRequest> pending_request =
GetNextPendingStreamRequest();
if (!pending_request)
@@ -1045,11 +1080,6 @@ bool SpdySession::CloseOneIdleConnection() {
return false;
}
-// static
-void SpdySession::SetPriorityDependencyDefaultForTesting(bool enable) {
- priority_dependency_enabled_default = enable;
-}
-
void SpdySession::EnqueueStreamWrite(
const base::WeakPtr<SpdyStream>& stream,
SpdyFrameType frame_type,
@@ -1060,7 +1090,7 @@ void SpdySession::EnqueueStreamWrite(
EnqueueWrite(stream->priority(), frame_type, std::move(producer), stream);
}
-scoped_ptr<SpdyFrame> SpdySession::CreateSynStream(
+scoped_ptr<SpdySerializedFrame> SpdySession::CreateSynStream(
SpdyStreamId stream_id,
RequestPriority priority,
SpdyControlFlags flags,
@@ -1075,7 +1105,7 @@ scoped_ptr<SpdyFrame> SpdySession::CreateSynStream(
SpdyPriority spdy_priority =
ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion());
- scoped_ptr<SpdyFrame> syn_frame;
+ scoped_ptr<SpdySerializedFrame> syn_frame;
// TODO(hkhalil): Avoid copy of |block|.
if (GetProtocolVersion() <= SPDY3) {
SpdySynStreamIR syn_stream(stream_id);
@@ -1084,65 +1114,47 @@ scoped_ptr<SpdyFrame> SpdySession::CreateSynStream(
syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0);
syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
syn_stream.set_header_block(block);
- syn_frame.reset(buffered_spdy_framer_->SerializeFrame(syn_stream));
+ syn_frame.reset(new SpdySerializedFrame(
+ buffered_spdy_framer_->SerializeFrame(syn_stream)));
+
+ if (net_log().IsCapturing()) {
+ net_log().AddEvent(NetLog::TYPE_HTTP2_SESSION_SYN_STREAM,
+ base::Bind(&NetLogSpdySynStreamSentCallback, &block,
+ (flags & CONTROL_FLAG_FIN) != 0,
+ (flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0,
+ spdy_priority, stream_id));
+ }
} else {
SpdyHeadersIR headers(stream_id);
headers.set_priority(spdy_priority);
headers.set_has_priority(true);
- if (send_priority_dependency_) {
- // Set dependencies to reflect request priority. A newly created
- // stream should be dependent on the most recent previously created
- // stream of the same priority level. The newly created stream
- // should also have all streams of a lower priority level dependent
- // on it, which is guaranteed by setting the exclusive bit.
- //
- // Note that this depends on stream ids being allocated in a monotonically
- // increasing fashion, and on all streams in
- // active_streams_{,by_priority_} having stream ids set.
- for (int i = priority; i >= IDLE; --i) {
- if (active_streams_by_priority_[i].empty())
- continue;
-
- auto candidate_it = active_streams_by_priority_[i].rbegin();
-
- // |active_streams_by_priority_| is updated before the
- // SYN stream frame is created, so the current streams
- // id is already on the list. Skip over it, skipping this
- // priority level if it's singular.
- if (candidate_it->second->stream_id() == stream_id)
- ++candidate_it;
- if (candidate_it == active_streams_by_priority_[i].rend())
- continue;
-
- headers.set_parent_stream_id(candidate_it->second->stream_id());
- break;
- }
-
- // If there are no streams of priority <= the current stream, the
- // current stream will default to a child of the idle node (0).
- headers.set_exclusive(true);
+ if (priority_dependencies_enabled_) {
+ SpdyStreamId dependent_stream_id = 0;
+ bool exclusive = false;
+ priority_dependency_state_.OnStreamSynSent(
+ stream_id, spdy_priority, &dependent_stream_id, &exclusive);
+ headers.set_parent_stream_id(dependent_stream_id);
+ headers.set_exclusive(exclusive);
}
headers.set_fin((flags & CONTROL_FLAG_FIN) != 0);
headers.set_header_block(block);
- syn_frame.reset(buffered_spdy_framer_->SerializeFrame(headers));
+ syn_frame.reset(new SpdySerializedFrame(
+ buffered_spdy_framer_->SerializeFrame(headers)));
+
+ if (net_log().IsCapturing()) {
+ net_log().AddEvent(
+ NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS,
+ base::Bind(&NetLogSpdyHeadersSentCallback, &block,
+ (flags & CONTROL_FLAG_FIN) != 0, stream_id,
+ headers.has_priority(), headers.priority(),
+ headers.parent_stream_id(), headers.exclusive()));
+ }
}
streams_initiated_count_++;
- if (net_log().IsCapturing()) {
- const NetLog::EventType type =
- (GetProtocolVersion() <= SPDY3)
- ? NetLog::TYPE_HTTP2_SESSION_SYN_STREAM
- : NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS;
- net_log().AddEvent(type,
- base::Bind(&NetLogSpdySynStreamSentCallback, &block,
- (flags & CONTROL_FLAG_FIN) != 0,
- (flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0,
- spdy_priority, stream_id));
- }
-
return syn_frame;
}
@@ -1237,7 +1249,7 @@ scoped_ptr<SpdyBuffer> SpdySession::CreateDataBuffer(SpdyStreamId stream_id,
// TODO(mbelshe): reduce memory copies here.
DCHECK(buffered_spdy_framer_.get());
- scoped_ptr<SpdyFrame> frame(buffered_spdy_framer_->CreateDataFrame(
+ scoped_ptr<SpdySerializedFrame> frame(buffered_spdy_framer_->CreateDataFrame(
stream_id, data->data(), static_cast<uint32_t>(effective_len), flags));
scoped_ptr<SpdyBuffer> data_buffer(new SpdyBuffer(std::move(frame)));
@@ -1311,8 +1323,8 @@ void SpdySession::CloseActiveStreamIterator(ActiveStreamMap::iterator it,
scoped_ptr<SpdyStream> owned_stream(it->second.stream);
active_streams_.erase(it);
- active_streams_by_priority_[owned_stream->priority()].erase(
- owned_stream->stream_id());
+ if (priority_dependencies_enabled_)
+ priority_dependency_state_.OnStreamDestruction(owned_stream->stream_id());
// TODO(akalin): When SpdyStream was ref-counted (and
// |unclaimed_pushed_streams_| held scoped_refptr<SpdyStream>), this
@@ -1370,7 +1382,7 @@ void SpdySession::EnqueueResetStreamFrame(SpdyStreamId stream_id,
base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description));
DCHECK(buffered_spdy_framer_.get());
- scoped_ptr<SpdyFrame> rst_frame(
+ scoped_ptr<SpdySerializedFrame> rst_frame(
buffered_spdy_framer_->CreateRstStream(stream_id, status));
EnqueueSessionWrite(priority, RST_STREAM, std::move(rst_frame));
@@ -1378,6 +1390,7 @@ void SpdySession::EnqueueResetStreamFrame(SpdyStreamId stream_id,
}
void SpdySession::PumpReadLoop(ReadState expected_read_state, int result) {
+ TRACE_EVENT0("net", "SpdySession::PumpReadLoop");
// TODO(bnc): Remove ScopedTracker below once crbug.com/462774 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION("462774 SpdySession::PumpReadLoop"));
@@ -1471,7 +1484,9 @@ int SpdySession::DoReadComplete(int result) {
}
if (result < 0) {
- DoDrainSession(static_cast<Error>(result), "result is < 0.");
+ DoDrainSession(
+ static_cast<Error>(result),
+ base::StringPrintf("Error %d reading from socket.", -result));
return result;
}
CHECK_LE(result, kReadBufferSize);
@@ -1766,10 +1781,9 @@ void SpdySession::DoDrainSession(Error err, const std::string& description) {
SpdyGoAwayIR goaway_ir(last_accepted_push_stream_id_,
MapNetErrorToGoAwayStatus(err),
description);
- EnqueueSessionWrite(HIGHEST,
- GOAWAY,
- scoped_ptr<SpdyFrame>(
- buffered_spdy_framer_->SerializeFrame(goaway_ir)));
+ EnqueueSessionWrite(HIGHEST, GOAWAY,
+ scoped_ptr<SpdySerializedFrame>(new SpdySerializedFrame(
+ buffered_spdy_framer_->SerializeFrame(goaway_ir))));
}
availability_state_ = STATE_DRAINING;
@@ -1812,7 +1826,7 @@ void SpdySession::LogAbandonedActiveStream(ActiveStreamMap::const_iterator it,
++streams_abandoned_count_;
if (it->second.stream->type() == SPDY_PUSH_STREAM &&
unclaimed_pushed_streams_.find(it->second.stream->url()) !=
- unclaimed_pushed_streams_.end()) {
+ unclaimed_pushed_streams_.end()) {
}
}
@@ -1894,6 +1908,15 @@ bool SpdySession::GetLoadTimingInfo(SpdyStreamId stream_id,
load_timing_info);
}
+size_t SpdySession::num_unclaimed_pushed_streams() const {
+ return unclaimed_pushed_streams_.size();
+}
+
+size_t SpdySession::count_unclaimed_pushed_streams_for_url(
+ const GURL& url) const {
+ return unclaimed_pushed_streams_.count(url);
+}
+
int SpdySession::GetPeerAddress(IPEndPoint* address) const {
int rv = ERR_SOCKET_NOT_CONNECTED;
if (connection_->socket()) {
@@ -1920,7 +1943,7 @@ int SpdySession::GetLocalAddress(IPEndPoint* address) const {
void SpdySession::EnqueueSessionWrite(RequestPriority priority,
SpdyFrameType frame_type,
- scoped_ptr<SpdyFrame> frame) {
+ scoped_ptr<SpdySerializedFrame> frame) {
DCHECK(frame_type == RST_STREAM || frame_type == SETTINGS ||
frame_type == WINDOW_UPDATE || frame_type == PING ||
frame_type == GOAWAY);
@@ -1973,8 +1996,6 @@ void SpdySession::InsertActivatedStream(scoped_ptr<SpdyStream> stream) {
std::pair<ActiveStreamMap::iterator, bool> result =
active_streams_.insert(
std::make_pair(stream_id, ActiveStreamInfo(stream.get())));
- active_streams_by_priority_[stream->priority()].insert(
- std::make_pair(stream_id, stream.get()));
CHECK(result.second);
ignore_result(stream.release());
}
@@ -1997,7 +2018,8 @@ void SpdySession::DeleteStream(scoped_ptr<SpdyStream> stream, int status) {
}
base::WeakPtr<SpdyStream> SpdySession::GetActivePushStream(const GURL& url) {
- PushedStreamMap::iterator unclaimed_it = unclaimed_pushed_streams_.find(url);
+ UnclaimedPushedStreamContainer::const_iterator unclaimed_it =
+ unclaimed_pushed_streams_.find(url);
if (unclaimed_it == unclaimed_pushed_streams_.end())
return base::WeakPtr<SpdyStream>();
@@ -2024,6 +2046,17 @@ bool SpdySession::GetSSLInfo(SSLInfo* ssl_info,
return connection_->socket()->GetSSLInfo(ssl_info);
}
+Error SpdySession::GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ if (!is_secure_) {
+ NOTREACHED();
+ return ERR_FAILED;
+ }
+ SSLClientSocket* ssl_socket =
+ static_cast<SSLClientSocket*>(connection_->socket());
+ return ssl_socket->GetSignedEKMForTokenBinding(key, out);
+}
+
void SpdySession::OnError(SpdyFramer::SpdyError error_code) {
CHECK(in_io_loop_);
@@ -2164,10 +2197,9 @@ void SpdySession::OnSettings(bool clear_persisted) {
SpdySettingsIR settings_ir;
settings_ir.set_is_ack(true);
EnqueueSessionWrite(
- HIGHEST,
- SETTINGS,
- scoped_ptr<SpdyFrame>(
- buffered_spdy_framer_->SerializeFrame(settings_ir)));
+ HIGHEST, SETTINGS,
+ scoped_ptr<SpdySerializedFrame>(new SpdySerializedFrame(
+ buffered_spdy_framer_->SerializeFrame(settings_ir))));
}
}
@@ -2304,7 +2336,8 @@ void SpdySession::DeleteExpiredPushedStreams() {
base::TimeTicks minimum_freshness = time_func_() -
base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds);
std::vector<SpdyStreamId> streams_to_close;
- for (PushedStreamMap::iterator it = unclaimed_pushed_streams_.begin();
+ for (UnclaimedPushedStreamContainer::const_iterator it =
+ unclaimed_pushed_streams_.begin();
it != unclaimed_pushed_streams_.end(); ++it) {
if (minimum_freshness > it->second.creation_time)
streams_to_close.push_back(it->second.stream_id);
@@ -2595,6 +2628,13 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
return false;
}
+ // Server-initiated streams must be associated with client-initiated streams.
+ if ((associated_stream_id & 0x1) != 1) {
+ LOG(WARNING) << "Received invalid associated stream id " << stream_id;
+ CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Push on even stream id.");
+ return false;
+ }
+
if (stream_id <= last_accepted_push_stream_id_) {
LOG(WARNING) << "Received push stream id lesser or equal to the last "
<< "accepted before " << stream_id;
@@ -2645,7 +2685,7 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
// TODO(mbelshe): DCHECK that this is a GET method?
// Verify that the response had a URL for us.
- GURL gurl = GetUrlFromHeaderBlock(headers, GetProtocolVersion(), true);
+ GURL gurl = GetUrlFromHeaderBlock(headers, GetProtocolVersion());
if (!gurl.is_valid()) {
EnqueueResetStreamFrame(stream_id,
request_priority,
@@ -2667,35 +2707,55 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
return false;
}
+ DCHECK(gurl.is_valid());
+
// Check that the pushed stream advertises the same origin as its associated
// stream. Bypass this check if and only if this session is with a SPDY proxy
- // that is trusted explicitly via the --trusted-spdy-proxy switch.
- if (trusted_spdy_proxy_.Equals(host_port_pair())) {
- // Disallow pushing of HTTPS content.
- if (gurl.SchemeIs("https")) {
- EnqueueResetStreamFrame(
- stream_id,
- request_priority,
- RST_STREAM_REFUSED_STREAM,
- base::StringPrintf("Rejected push of Cross Origin HTTPS content %d",
- associated_stream_id));
- return false;
- }
- } else {
- GURL associated_url(associated_it->second.stream->GetUrlFromHeaders());
- if (associated_url.GetOrigin() != gurl.GetOrigin()) {
- EnqueueResetStreamFrame(
- stream_id,
- request_priority,
- RST_STREAM_REFUSED_STREAM,
- base::StringPrintf("Rejected Cross Origin Push Stream %d",
- associated_stream_id));
- return false;
+ // that is trusted explicitly as determined by the |proxy_delegate_| or if the
+ // proxy is pushing same-origin resources.
+ if (!HostPortPair::FromURL(gurl).Equals(host_port_pair())) {
+ if (proxy_delegate_ &&
+ proxy_delegate_->IsTrustedSpdyProxy(
+ ProxyServer(ProxyServer::SCHEME_HTTPS, host_port_pair()))) {
+ // Disallow pushing of HTTPS content.
+ if (gurl.SchemeIs("https")) {
+ EnqueueResetStreamFrame(
+ stream_id, request_priority, RST_STREAM_REFUSED_STREAM,
+ base::StringPrintf("Rejected push of cross origin HTTPS content %d "
+ "from trusted proxy",
+ associated_stream_id));
+ return false;
+ }
+ } else {
+ GURL associated_url(associated_it->second.stream->GetUrlFromHeaders());
+ if (associated_url.SchemeIs("https")) {
+ SSLInfo ssl_info;
+ CHECK(connection_->socket()->GetSSLInfo(&ssl_info));
+ if (!gurl.SchemeIs("https") ||
+ !CanPool(transport_security_state_, ssl_info, associated_url.host(),
+ gurl.host())) {
+ EnqueueResetStreamFrame(
+ stream_id, request_priority, RST_STREAM_REFUSED_STREAM,
+ base::StringPrintf("Rejected push stream %d on secure connection",
+ associated_stream_id));
+ return false;
+ }
+ } else {
+ // TODO(bnc): Change SpdyNetworkTransactionTests to use secure sockets.
+ if (associated_url.GetOrigin() != gurl.GetOrigin()) {
+ EnqueueResetStreamFrame(
+ stream_id, request_priority, RST_STREAM_REFUSED_STREAM,
+ base::StringPrintf(
+ "Rejected cross origin push stream %d on insecure connection",
+ associated_stream_id));
+ return false;
+ }
+ }
}
}
// There should not be an existing pushed stream with the same path.
- PushedStreamMap::iterator pushed_it =
+ UnclaimedPushedStreamContainer::const_iterator pushed_it =
unclaimed_pushed_streams_.lower_bound(gurl);
if (pushed_it != unclaimed_pushed_streams_.end() &&
pushed_it->first == gurl) {
@@ -2723,10 +2783,9 @@ bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id,
last_compressed_frame_len_ = 0;
- PushedStreamMap::iterator inserted_pushed_it =
- unclaimed_pushed_streams_.insert(
- pushed_it,
- std::make_pair(gurl, PushedStreamInfo(stream_id, time_func_())));
+ UnclaimedPushedStreamContainer::const_iterator inserted_pushed_it =
+ unclaimed_pushed_streams_.insert(pushed_it, gurl, stream_id,
+ time_func_());
DCHECK(inserted_pushed_it != pushed_it);
DeleteExpiredPushedStreams();
@@ -2775,10 +2834,10 @@ void SpdySession::SendInitialData() {
if (send_connection_header_prefix_) {
DCHECK_EQ(protocol_, kProtoHTTP2);
- scoped_ptr<SpdyFrame> connection_header_prefix_frame(
- new SpdyFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix),
- kHttp2ConnectionHeaderPrefixSize,
- false /* take_ownership */));
+ scoped_ptr<SpdySerializedFrame> connection_header_prefix_frame(
+ new SpdySerializedFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix),
+ kHttp2ConnectionHeaderPrefixSize,
+ false /* take_ownership */));
// Count the prefix as part of the subsequent SETTINGS frame.
EnqueueSessionWrite(HIGHEST, SETTINGS,
std::move(connection_header_prefix_frame));
@@ -2843,7 +2902,7 @@ void SpdySession::SendSettings(const SettingsMap& settings) {
base::Bind(&NetLogSpdySendSettingsCallback, &settings, protocol_version));
// Create the SETTINGS frame and send it.
DCHECK(buffered_spdy_framer_.get());
- scoped_ptr<SpdyFrame> settings_frame(
+ scoped_ptr<SpdySerializedFrame> settings_frame(
buffered_spdy_framer_->CreateSettings(settings));
sent_settings_ = true;
EnqueueSessionWrite(HIGHEST, SETTINGS, std::move(settings_frame));
@@ -2918,14 +2977,14 @@ void SpdySession::SendWindowUpdateFrame(SpdyStreamId stream_id,
delta_window_size));
DCHECK(buffered_spdy_framer_.get());
- scoped_ptr<SpdyFrame> window_update_frame(
+ scoped_ptr<SpdySerializedFrame> window_update_frame(
buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size));
EnqueueSessionWrite(priority, WINDOW_UPDATE, std::move(window_update_frame));
}
void SpdySession::WritePingFrame(SpdyPingId unique_id, bool is_ack) {
DCHECK(buffered_spdy_framer_.get());
- scoped_ptr<SpdyFrame> ping_frame(
+ scoped_ptr<SpdySerializedFrame> ping_frame(
buffered_spdy_framer_->CreatePingFrame(unique_id, is_ack));
EnqueueSessionWrite(HIGHEST, PING, std::move(ping_frame));
diff --git a/chromium/net/spdy/spdy_session.h b/chromium/net/spdy/spdy_session.h
index 5d72161b592..d99ae0b0f21 100644
--- a/chromium/net/spdy/spdy_session.h
+++ b/chromium/net/spdy/spdy_session.h
@@ -12,6 +12,7 @@
#include <map>
#include <set>
#include <string>
+#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -19,6 +20,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
+#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
#include "net/base/load_states.h"
#include "net/base/net_errors.h"
@@ -30,6 +32,7 @@
#include "net/socket/ssl_client_socket.h"
#include "net/socket/stream_socket.h"
#include "net/spdy/buffered_spdy_framer.h"
+#include "net/spdy/http2_priority_dependencies.h"
#include "net/spdy/spdy_buffer.h"
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_header_block.h"
@@ -73,6 +76,7 @@ const SpdyStreamId kLastStreamId = 0x7fffffff;
class BoundNetLog;
struct LoadTimingInfo;
+class ProxyDelegate;
class SpdyStream;
class SSLInfo;
class TransportSecurityState;
@@ -93,6 +97,7 @@ enum SpdyProtocolErrorDetails {
SPDY_ERROR_INVALID_DATA_FRAME_FLAGS = 8,
SPDY_ERROR_INVALID_CONTROL_FRAME_FLAGS = 9,
SPDY_ERROR_UNEXPECTED_FRAME = 31,
+ SPDY_ERROR_INVALID_CONTROL_FRAME_SIZE = 37,
// SpdyRstStreamStatus mappings.
// RST_STREAM_INVALID not mapped.
STATUS_CODE_PROTOCOL_ERROR = 11,
@@ -121,7 +126,7 @@ enum SpdyProtocolErrorDetails {
PROTOCOL_ERROR_RECEIVE_WINDOW_VIOLATION = 28,
// Next free value.
- NUM_SPDY_PROTOCOL_ERROR_DETAILS = 37,
+ NUM_SPDY_PROTOCOL_ERROR_DETAILS = 38,
};
SpdyProtocolErrorDetails NET_EXPORT_PRIVATE
MapFramerErrorToProtocolError(SpdyFramer::SpdyError error);
@@ -132,7 +137,7 @@ SpdyGoAwayStatus NET_EXPORT_PRIVATE MapNetErrorToGoAwayStatus(Error err);
// If these compile asserts fail then SpdyProtocolErrorDetails needs
// to be updated with new values, as do the mapping functions above.
-static_assert(12 == SpdyFramer::LAST_ERROR,
+static_assert(13 == SpdyFramer::LAST_ERROR,
"SpdyProtocolErrorDetails / Spdy Errors mismatch");
static_assert(17 == RST_STREAM_NUM_STATUS_CODES,
"SpdyProtocolErrorDetails / RstStreamStatus mismatch");
@@ -221,8 +226,56 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// TODO(akalin): Use base::TickClock when it becomes available.
typedef base::TimeTicks (*TimeFunc)(void);
- // Returns true if |hostname| can be pooled into an existing connection
- // associated with |ssl_info|.
+ // Container class for unclaimed pushed streams on a SpdySession. Guarantees
+ // that |spdy_session_.pool_| gets notified every time a stream is pushed or
+ // an unclaimed pushed stream is claimed.
+ class UnclaimedPushedStreamContainer {
+ public:
+ struct PushedStreamInfo {
+ PushedStreamInfo() : stream_id(0) {}
+ PushedStreamInfo(SpdyStreamId stream_id, base::TimeTicks creation_time)
+ : stream_id(stream_id), creation_time(creation_time) {}
+ ~PushedStreamInfo() {}
+
+ SpdyStreamId stream_id;
+ base::TimeTicks creation_time;
+ };
+ using PushedStreamMap = std::map<GURL, PushedStreamInfo>;
+ using iterator = PushedStreamMap::iterator;
+ using const_iterator = PushedStreamMap::const_iterator;
+
+ UnclaimedPushedStreamContainer() = delete;
+ explicit UnclaimedPushedStreamContainer(SpdySession* spdy_session);
+ ~UnclaimedPushedStreamContainer();
+
+ bool empty() const { return streams_.empty(); }
+ size_t size() const { return streams_.size(); }
+ const_iterator begin() const { return streams_.begin(); }
+ const_iterator end() const { return streams_.end(); }
+ const_iterator find(const GURL& url) const { return streams_.find(url); }
+ size_t count(const GURL& url) const { return streams_.count(url); }
+ const_iterator lower_bound(const GURL& url) const {
+ return streams_.lower_bound(url);
+ }
+
+ size_t erase(const GURL& url);
+ iterator erase(const_iterator it);
+ iterator insert(const_iterator position,
+ const GURL& url,
+ SpdyStreamId stream_id,
+ const base::TimeTicks& creation_time);
+
+ private:
+ SpdySession* spdy_session_;
+
+ // (Bijective) map from the URL to the ID of the streams that have
+ // already started to be pushed by the server, but do not have
+ // consumers yet. Contains a subset of |active_streams_|.
+ PushedStreamMap streams_;
+ };
+
+ // Returns true if |new_hostname| can be pooled into an existing connection to
+ // |old_hostname| associated with |ssl_info|.
static bool CanPool(TransportSecurityState* transport_security_state,
const SSLInfo& ssl_info,
const std::string& old_hostname,
@@ -238,14 +291,13 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
TransportSecurityState* transport_security_state,
bool verify_domain_authentication,
bool enable_sending_initial_data,
- bool enable_compression,
bool enable_ping_based_connection_checking,
+ bool enable_priority_dependencies,
NextProto default_protocol,
size_t session_max_recv_window_size,
size_t stream_max_recv_window_size,
- size_t initial_max_concurrent_streams,
TimeFunc time_func,
- const HostPortPair& trusted_spdy_proxy,
+ ProxyDelegate* proxy_delegate,
NetLog* net_log);
~SpdySession() override;
@@ -315,7 +367,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
scoped_ptr<SpdyBufferProducer> producer);
// Creates and returns a SYN frame for |stream_id|.
- scoped_ptr<SpdyFrame> CreateSynStream(
+ scoped_ptr<SpdySerializedFrame> CreateSynStream(
SpdyStreamId stream_id,
RequestPriority priority,
SpdyControlFlags flags,
@@ -357,6 +409,11 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
bool* was_npn_negotiated,
NextProto* protocol_negotiated);
+ // Signs the EKM value for Token Binding from the TLS layer using |*key| and
+ // puts the result in |*out|. Returns OK or ERR_FAILED.
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ 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,
@@ -429,10 +486,9 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// Access to the number of active and pending streams. These are primarily
// available for testing and diagnostics.
size_t num_active_streams() const { return active_streams_.size(); }
- size_t num_unclaimed_pushed_streams() const {
- return unclaimed_pushed_streams_.size();
- }
+ size_t num_unclaimed_pushed_streams() const;
size_t num_created_streams() const { return created_streams_.size(); }
+ size_t count_unclaimed_pushed_streams_for_url(const GURL& url) const;
size_t num_pushed_streams() const { return num_pushed_streams_; }
size_t num_active_pushed_streams() const {
@@ -535,6 +591,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlNoSendLeaks);
FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlEndToEnd);
FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, StreamIdSpaceExhausted);
+ FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, MaxConcurrentStreamsZero);
FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, UnstallRacesWithStreamCreation);
FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, GoAwayOnSessionFlowControlError);
FRIEND_TEST_ALL_PREFIXES(SpdySessionTest,
@@ -544,6 +601,10 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
CancelReservedStreamOnHeadersReceived);
FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, RejectInvalidUnknownFrames);
FRIEND_TEST_ALL_PREFIXES(SpdySessionPoolTest, IPAddressChanged);
+ FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest,
+ ServerPushValidCrossOrigin);
+ FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest,
+ ServerPushValidCrossOriginWithOpenSession);
typedef std::deque<base::WeakPtr<SpdyStreamRequest> >
PendingStreamRequestQueue;
@@ -558,16 +619,6 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
};
typedef std::map<SpdyStreamId, ActiveStreamInfo> ActiveStreamMap;
- struct PushedStreamInfo {
- PushedStreamInfo();
- PushedStreamInfo(SpdyStreamId stream_id, base::TimeTicks creation_time);
- ~PushedStreamInfo();
-
- SpdyStreamId stream_id;
- base::TimeTicks creation_time;
- };
- typedef std::map<GURL, PushedStreamInfo> PushedStreamMap;
-
typedef std::set<SpdyStream*> CreatedStreamSet;
enum AvailabilityState {
@@ -739,7 +790,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// queue for the session.
void EnqueueSessionWrite(RequestPriority priority,
SpdyFrameType frame_type,
- scoped_ptr<SpdyFrame> frame);
+ scoped_ptr<SpdySerializedFrame> frame);
// Puts |producer| associated with |stream| onto the write queue
// with the given priority.
@@ -953,12 +1004,6 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
bool check_ping_status_pending() const { return check_ping_status_pending_; }
- size_t max_concurrent_streams() const { return max_concurrent_streams_; }
-
- // Set whether priority->dependency conversion is enabled
- // by default for all future SpdySessions.
- static void SetPriorityDependencyDefaultForTesting(bool enable);
-
// Whether Do{Read,Write}Loop() is in the call stack. Useful for
// making sure we don't destroy ourselves prematurely in that case.
bool in_io_loop_;
@@ -970,8 +1015,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// requests.
std::set<SpdySessionKey> pooled_aliases_;
- // |pool_| owns us, therefore its lifetime must exceed ours. We set
- // this to NULL after we are removed from the pool.
+ // |pool_| owns us, therefore its lifetime must exceed ours.
SpdySessionPool* pool_;
const base::WeakPtr<HttpServerProperties> http_server_properties_;
@@ -1005,18 +1049,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// them?
ActiveStreamMap active_streams_;
- // Per-priority map from stream id to all active streams. This map will
- // contain the same set of streams as |active_streams_|. It is used for
- // setting dependencies to match incoming requests RequestPriority.
- //
- // |active_streams_by_priority_| does *not* own its SpdyStream objects.
- std::map<SpdyStreamId, SpdyStream*>
- active_streams_by_priority_[NUM_PRIORITIES];
-
- // (Bijective) map from the URL to the ID of the streams that have
- // already started to be pushed by the server, but do not have
- // consumers yet. Contains a subset of |active_streams_|.
- PushedStreamMap unclaimed_pushed_streams_;
+ UnclaimedPushedStreamContainer unclaimed_pushed_streams_;
// Set of all created streams but that have not yet sent any frames.
//
@@ -1069,7 +1102,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
Error error_on_close_;
// Limits
- size_t max_concurrent_streams_; // 0 if no limit
+ size_t max_concurrent_streams_;
size_t max_concurrent_pushed_streams_;
// Some statistics counters for the session.
@@ -1153,7 +1186,6 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// Outside of tests, these should always be true.
bool verify_domain_authentication_;
bool enable_sending_initial_data_;
- bool enable_compression_;
bool enable_ping_based_connection_checking_;
// The SPDY protocol used. Always between kProtoSPDYMinimumVersion and
@@ -1182,15 +1214,15 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// get a PING response (http://crbug.com/127812).
base::TimeDelta hung_interval_;
- // This SPDY proxy is allowed to push resources from origins that are
- // different from those of their associated streams.
- HostPortPair trusted_spdy_proxy_;
+ // The |proxy_delegate_| verifies that a given proxy is a trusted SPDY proxy,
+ // which is allowed to push resources from origins that are different from
+ // those of their associated streams. May be nullptr.
+ ProxyDelegate* proxy_delegate_;
TimeFunc time_func_;
- // Should priority-based dependency information be sent in stream header
- // frames.
- bool send_priority_dependency_;
+ const bool priority_dependencies_enabled_;
+ Http2PriorityDependencies priority_dependency_state_;
// Used for posting asynchronous IO tasks. We use this even though
// SpdySession is refcounted because we don't need to keep the SpdySession
diff --git a/chromium/net/spdy/spdy_session_key.cc b/chromium/net/spdy/spdy_session_key.cc
index 59f36df7703..8b2fcbcc81f 100644
--- a/chromium/net/spdy/spdy_session_key.cc
+++ b/chromium/net/spdy/spdy_session_key.cc
@@ -32,6 +32,8 @@ SpdySessionKey::SpdySessionKey(const HostPortProxyPair& host_port_proxy_pair,
<< ", privacy=" << privacy_mode;
}
+SpdySessionKey::SpdySessionKey(const SpdySessionKey& other) = default;
+
SpdySessionKey::~SpdySessionKey() {}
bool SpdySessionKey::operator<(const SpdySessionKey& other) const {
diff --git a/chromium/net/spdy/spdy_session_key.h b/chromium/net/spdy/spdy_session_key.h
index 59c832bb52b..a393ce00a15 100644
--- a/chromium/net/spdy/spdy_session_key.h
+++ b/chromium/net/spdy/spdy_session_key.h
@@ -22,6 +22,8 @@ class NET_EXPORT_PRIVATE SpdySessionKey {
SpdySessionKey(const HostPortProxyPair& host_port_proxy_pair,
PrivacyMode privacy_mode);
+ SpdySessionKey(const SpdySessionKey& other);
+
~SpdySessionKey();
// Comparator function so this can be placed in a std::map.
diff --git a/chromium/net/spdy/spdy_session_pool.cc b/chromium/net/spdy/spdy_session_pool.cc
index 120887859ea..1875224e73b 100644
--- a/chromium/net/spdy/spdy_session_pool.cc
+++ b/chromium/net/spdy/spdy_session_pool.cc
@@ -9,6 +9,8 @@
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/profiler/scoped_tracker.h"
+#include "base/stl_util.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/address_list.h"
#include "net/http/http_network_session.h"
@@ -34,32 +36,30 @@ SpdySessionPool::SpdySessionPool(
SSLConfigService* ssl_config_service,
const base::WeakPtr<HttpServerProperties>& http_server_properties,
TransportSecurityState* transport_security_state,
- bool enable_compression,
bool enable_ping_based_connection_checking,
+ bool enable_priority_dependencies,
NextProto default_protocol,
size_t session_max_recv_window_size,
size_t stream_max_recv_window_size,
- size_t initial_max_concurrent_streams,
SpdySessionPool::TimeFunc time_func,
- const std::string& trusted_spdy_proxy)
+ ProxyDelegate* proxy_delegate)
: http_server_properties_(http_server_properties),
transport_security_state_(transport_security_state),
ssl_config_service_(ssl_config_service),
resolver_(resolver),
verify_domain_authentication_(true),
enable_sending_initial_data_(true),
- enable_compression_(enable_compression),
enable_ping_based_connection_checking_(
enable_ping_based_connection_checking),
+ enable_priority_dependencies_(enable_priority_dependencies),
// TODO(akalin): Force callers to have a valid value of
// |default_protocol_|.
default_protocol_((default_protocol == kProtoUnknown) ? kProtoSPDY31
: default_protocol),
session_max_recv_window_size_(session_max_recv_window_size),
stream_max_recv_window_size_(stream_max_recv_window_size),
- initial_max_concurrent_streams_(initial_max_concurrent_streams),
time_func_(time_func),
- trusted_spdy_proxy_(HostPortPair::FromString(trusted_spdy_proxy)) {
+ proxy_delegate_(proxy_delegate) {
DCHECK(default_protocol_ >= kProtoSPDYMinimumVersion &&
default_protocol_ <= kProtoSPDYMaximumVersion);
NetworkChangeNotifier::AddIPAddressObserver(this);
@@ -89,6 +89,7 @@ base::WeakPtr<SpdySession> SpdySessionPool::CreateAvailableSessionFromSocket(
const BoundNetLog& net_log,
int certificate_error_code,
bool is_secure) {
+ TRACE_EVENT0("net", "SpdySessionPool::CreateAvailableSessionFromSocket");
DCHECK_GE(default_protocol_, kProtoSPDYMinimumVersion);
DCHECK_LE(default_protocol_, kProtoSPDYMaximumVersion);
@@ -98,10 +99,10 @@ base::WeakPtr<SpdySession> SpdySessionPool::CreateAvailableSessionFromSocket(
scoped_ptr<SpdySession> new_session(new SpdySession(
key, http_server_properties_, transport_security_state_,
verify_domain_authentication_, enable_sending_initial_data_,
- enable_compression_, enable_ping_based_connection_checking_,
+ enable_ping_based_connection_checking_, enable_priority_dependencies_,
default_protocol_, session_max_recv_window_size_,
- stream_max_recv_window_size_, initial_max_concurrent_streams_, time_func_,
- trusted_spdy_proxy_, net_log.net_log()));
+ stream_max_recv_window_size_, time_func_, proxy_delegate_,
+ net_log.net_log()));
new_session->InitializeWithSocket(std::move(connection), this, is_secure,
certificate_error_code);
@@ -130,7 +131,37 @@ base::WeakPtr<SpdySession> SpdySessionPool::CreateAvailableSessionFromSocket(
base::WeakPtr<SpdySession> SpdySessionPool::FindAvailableSession(
const SpdySessionKey& key,
+ const GURL& url,
const BoundNetLog& net_log) {
+ UnclaimedPushedStreamMap::iterator url_it =
+ unclaimed_pushed_streams_.find(url);
+ if (!url.is_empty() && url_it != unclaimed_pushed_streams_.end()) {
+ DCHECK(url.SchemeIsCryptographic());
+ for (WeakSessionList::iterator it = url_it->second.begin();
+ it != url_it->second.end();) {
+ base::WeakPtr<SpdySession> spdy_session = *it;
+ // Lazy deletion of destroyed SpdySessions.
+ if (!spdy_session) {
+ it = url_it->second.erase(it);
+ continue;
+ }
+ ++it;
+ const SpdySessionKey& spdy_session_key = spdy_session->spdy_session_key();
+ if (!(spdy_session_key.proxy_server() == key.proxy_server()) ||
+ !(spdy_session_key.privacy_mode() == key.privacy_mode())) {
+ continue;
+ }
+ if (!spdy_session->VerifyDomainAuthentication(
+ key.host_port_pair().host())) {
+ continue;
+ }
+ return spdy_session;
+ }
+ if (url_it->second.empty()) {
+ unclaimed_pushed_streams_.erase(url_it);
+ }
+ }
+
AvailableSessionMap::iterator it = LookupAvailableSessionByKey(key);
if (it != available_sessions_.end()) {
UMA_HISTOGRAM_ENUMERATION(
@@ -249,6 +280,52 @@ void SpdySessionPool::CloseAllSessions() {
}
}
+void SpdySessionPool::RegisterUnclaimedPushedStream(
+ GURL url,
+ base::WeakPtr<SpdySession> spdy_session) {
+ DCHECK(!url.is_empty());
+ // This SpdySessionPool must own |spdy_session|.
+ DCHECK(ContainsKey(sessions_, spdy_session.get()));
+ UnclaimedPushedStreamMap::iterator url_it =
+ unclaimed_pushed_streams_.lower_bound(url);
+ if (url_it == unclaimed_pushed_streams_.end() || url_it->first != url) {
+ WeakSessionList list;
+ list.push_back(std::move(spdy_session));
+ UnclaimedPushedStreamMap::value_type value(std::move(url), std::move(list));
+ unclaimed_pushed_streams_.insert(url_it, std::move(value));
+ return;
+ }
+ url_it->second.push_back(spdy_session);
+}
+
+void SpdySessionPool::UnregisterUnclaimedPushedStream(
+ const GURL& url,
+ SpdySession* spdy_session) {
+ DCHECK(!url.is_empty());
+ UnclaimedPushedStreamMap::iterator url_it =
+ unclaimed_pushed_streams_.find(url);
+ DCHECK(url_it != unclaimed_pushed_streams_.end());
+ size_t removed = 0;
+ for (WeakSessionList::iterator it = url_it->second.begin();
+ it != url_it->second.end();) {
+ // Lazy deletion of destroyed SpdySessions.
+ if (!*it) {
+ it = url_it->second.erase(it);
+ continue;
+ }
+ if (it->get() == spdy_session) {
+ it = url_it->second.erase(it);
+ ++removed;
+ break;
+ }
+ ++it;
+ }
+ if (url_it->second.empty()) {
+ unclaimed_pushed_streams_.erase(url_it);
+ }
+ DCHECK_EQ(1u, removed);
+}
+
scoped_ptr<base::Value> SpdySessionPool::SpdySessionPoolInfoToValue() const {
scoped_ptr<base::ListValue> list(new base::ListValue());
diff --git a/chromium/net/spdy/spdy_session_pool.h b/chromium/net/spdy/spdy_session_pool.h
index 0b0f97edb81..eeae3148f54 100644
--- a/chromium/net/spdy/spdy_session_pool.h
+++ b/chromium/net/spdy/spdy_session_pool.h
@@ -34,6 +34,7 @@ class BoundNetLog;
class ClientSocketHandle;
class HostResolver;
class HttpServerProperties;
+class ProxyDelegate;
class SpdySession;
class TransportSecurityState;
@@ -53,14 +54,13 @@ class NET_EXPORT SpdySessionPool
SSLConfigService* ssl_config_service,
const base::WeakPtr<HttpServerProperties>& http_server_properties,
TransportSecurityState* transport_security_state,
- bool enable_compression,
bool enable_ping_based_connection_checking,
+ bool enable_priority_dependencies,
NextProto default_protocol,
size_t session_max_recv_window_size,
size_t stream_max_recv_window_size,
- size_t initial_max_concurrent_streams,
SpdySessionPool::TimeFunc time_func,
- const std::string& trusted_spdy_proxy);
+ ProxyDelegate* proxy_delegate);
~SpdySessionPool() override;
// In the functions below, a session is "available" if this pool has
@@ -91,8 +91,11 @@ class NET_EXPORT SpdySessionPool
int certificate_error_code,
bool is_secure);
- // Find an available session for the given key, or NULL if there isn't one.
+ // Return an available session for |key| that has an unclaimed push stream for
+ // |url| if such exists and |url| is not empty, or else an available session
+ // for |key| if such exists, or else nullptr.
base::WeakPtr<SpdySession> FindAvailableSession(const SpdySessionKey& key,
+ const GURL& url,
const BoundNetLog& net_log);
// Remove all mappings and aliases for the given session, which must
@@ -120,6 +123,13 @@ class NET_EXPORT SpdySessionPool
// closing the current ones.
void CloseAllSessions();
+ // (Un)register a SpdySession with an unclaimed pushed stream for |url|, so
+ // that the right SpdySession can be served by FindAvailableSession.
+ void RegisterUnclaimedPushedStream(GURL url,
+ base::WeakPtr<SpdySession> spdy_session);
+ void UnregisterUnclaimedPushedStream(const GURL& url,
+ SpdySession* spdy_session);
+
// Creates a Value summary of the state of the spdy session pool.
scoped_ptr<base::Value> SpdySessionPoolInfoToValue() const;
@@ -154,6 +164,7 @@ class NET_EXPORT SpdySessionPool
typedef std::map<SpdySessionKey, base::WeakPtr<SpdySession> >
AvailableSessionMap;
typedef std::map<IPEndPoint, SpdySessionKey> AliasMap;
+ typedef std::map<GURL, WeakSessionList> UnclaimedPushedStreamMap;
// Returns true iff |session| is in |available_sessions_|.
bool IsSessionAvailable(const base::WeakPtr<SpdySession>& session) const;
@@ -203,23 +214,30 @@ class NET_EXPORT SpdySessionPool
// A map of IPEndPoint aliases for sessions.
AliasMap aliases_;
+ // A map of all SpdySessions owned by |this| that have an unclaimed pushed
+ // streams for a GURL. Might contain invalid WeakPtr's.
+ // A single SpdySession can only have at most one pushed stream for each GURL,
+ // but it is possible that multiple SpdySessions have pushed streams for the
+ // same GURL.
+ UnclaimedPushedStreamMap unclaimed_pushed_streams_;
+
const scoped_refptr<SSLConfigService> ssl_config_service_;
HostResolver* const resolver_;
// Defaults to true. May be controlled via SpdySessionPoolPeer for tests.
bool verify_domain_authentication_;
bool enable_sending_initial_data_;
- bool enable_compression_;
bool enable_ping_based_connection_checking_;
+ const bool enable_priority_dependencies_;
const NextProto default_protocol_;
size_t session_max_recv_window_size_;
size_t stream_max_recv_window_size_;
- size_t initial_max_concurrent_streams_;
TimeFunc time_func_;
- // This SPDY proxy is allowed to push resources from origins that are
- // different from those of their associated streams.
- HostPortPair trusted_spdy_proxy_;
+ // 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
+ // streams. May be nullptr.
+ ProxyDelegate* proxy_delegate_;
DISALLOW_COPY_AND_ASSIGN(SpdySessionPool);
};
diff --git a/chromium/net/spdy/spdy_session_pool_unittest.cc b/chromium/net/spdy/spdy_session_pool_unittest.cc
index 3791c7f88ae..4d34869fcf5 100644
--- a/chromium/net/spdy/spdy_session_pool_unittest.cc
+++ b/chromium/net/spdy/spdy_session_pool_unittest.cc
@@ -415,7 +415,7 @@ void SpdySessionPoolTest::RunIPPoolingTest(
// we got with host 0, and that is a different from host 2's session.
base::WeakPtr<SpdySession> session1 =
spdy_session_pool_->FindAvailableSession(
- test_hosts[1].key, BoundNetLog());
+ test_hosts[1].key, GURL(test_hosts[1].url), BoundNetLog());
EXPECT_EQ(session.get(), session1.get());
EXPECT_NE(session2.get(), session1.get());
@@ -520,14 +520,14 @@ TEST_P(SpdySessionPoolTest, IPAddressChanged) {
// can ignore issues of how dependencies are set. We default to
// setting them (when doing the appropriate protocol) since that's
// where we're eventually headed for all HTTP/2 connections.
- SpdyTestUtil spdy_util(GetParam(), true);
- SpdySession::SetPriorityDependencyDefaultForTesting(true);
+ session_deps_.enable_priority_dependencies = true;
+ SpdyTestUtil spdy_util(GetParam(), /*enable_priority_dependencies*/ true);
MockRead reads[] = {
MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
};
- scoped_ptr<SpdyFrame> req(
- spdy_util.ConstructSpdyGet("http://www.a.com", false, 1, MEDIUM));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util.ConstructSpdyGet("http://www.a.com", 1, MEDIUM));
MockWrite writes[] = {CreateMockWrite(*req, 1)};
StaticSocketDataProvider dataA(reads, arraysize(reads), writes,
@@ -630,7 +630,43 @@ TEST_P(SpdySessionPoolTest, IPAddressChanged) {
EXPECT_TRUE(delegateB.StreamIsClosed());
EXPECT_EQ(ERR_NETWORK_CHANGED, delegateB.WaitForClose());
#endif // defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
- SpdySession::SetPriorityDependencyDefaultForTesting(false);
+}
+
+TEST_P(SpdySessionPoolTest, FindAvailableSession) {
+ 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 =
+ CreateInsecureSpdySession(http_session_.get(), key, BoundNetLog());
+
+ // Flush the SpdySession::OnReadComplete() task.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key));
+
+ // FindAvailableSession should return |session| if called with empty |url|.
+ base::WeakPtr<SpdySession> session1 =
+ spdy_session_pool_->FindAvailableSession(key, GURL(), BoundNetLog());
+ EXPECT_EQ(session.get(), session1.get());
+
+ // FindAvailableSession should return |session| if called with |url| for which
+ // there is no pushed stream on any sessions owned by |spdy_session_pool_|.
+ base::WeakPtr<SpdySession> session2 =
+ spdy_session_pool_->FindAvailableSession(
+ key, GURL("http://news.example.org/foo.html"), BoundNetLog());
+ EXPECT_EQ(session.get(), session2.get());
+
+ 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 ee19f03ac0d..0cd890f6672 100644
--- a/chromium/net/spdy/spdy_session_unittest.cc
+++ b/chromium/net/spdy/spdy_session_unittest.cc
@@ -12,14 +12,18 @@
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/test/histogram_tester.h"
+#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
+#include "net/base/proxy_delegate.h"
#include "net/base/request_priority.h"
#include "net/base/test_data_directory.h"
#include "net/base/test_data_stream.h"
+#include "net/base/test_proxy_delegate.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_entry.h"
#include "net/log/test_net_log_util.h"
+#include "net/proxy/proxy_server.h"
#include "net/socket/client_socket_pool_manager.h"
#include "net/socket/next_proto.h"
#include "net/socket/socket_test_util.h"
@@ -135,8 +139,7 @@ class SpdySessionTest : public PlatformTest,
key_(test_host_port_pair_,
ProxyServer::Direct(),
PRIVACY_MODE_DISABLED) {
- SpdySession::SetPriorityDependencyDefaultForTesting(
- GetDependenciesFromPriority());
+ session_deps_.enable_priority_dependencies = GetDependenciesFromPriority();
}
virtual ~SpdySessionTest() {
@@ -146,7 +149,6 @@ class SpdySessionTest : public PlatformTest,
HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
ClientSocketPoolManager::set_max_sockets_per_group(
HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
- SpdySession::SetPriorityDependencyDefaultForTesting(false);
}
void SetUp() override {
@@ -310,7 +312,7 @@ TEST_P(SpdySessionTest, PendingStreamCancellingAnother) {
TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
MockRead reads[] = {
CreateMockRead(*goaway, 0),
};
@@ -335,7 +337,7 @@ TEST_P(SpdySessionTest, GoAwayWithNoActiveStreams) {
TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
MockRead reads[] = {
CreateMockRead(*goaway, 0, SYNCHRONOUS), MockRead(ASYNC, 0, 1) // EOF
};
@@ -358,17 +360,17 @@ TEST_P(SpdySessionTest, GoAwayImmediatelyWithNoActiveStreams) {
TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 2),
CreateMockRead(*goaway, 3),
MockRead(ASYNC, ERR_IO_PENDING, 4),
MockRead(ASYNC, 0, 5) // EOF
};
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
CreateMockWrite(*req2, 1),
@@ -433,14 +435,14 @@ TEST_P(SpdySessionTest, GoAwayWithActiveStreams) {
TEST_P(SpdySessionTest, GoAwayWithActiveAndCreatedStream) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(0));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(0));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(*goaway, 2),
};
// No |req2|, because the second stream will never get activated.
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
};
@@ -491,8 +493,8 @@ TEST_P(SpdySessionTest, GoAwayWithActiveAndCreatedStream) {
TEST_P(SpdySessionTest, GoAwayTwice) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
- scoped_ptr<SpdyFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
+ scoped_ptr<SpdySerializedFrame> goaway1(spdy_util_.ConstructSpdyGoAway(1));
+ scoped_ptr<SpdySerializedFrame> goaway2(spdy_util_.ConstructSpdyGoAway(0));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 2),
CreateMockRead(*goaway1, 3),
@@ -501,10 +503,10 @@ TEST_P(SpdySessionTest, GoAwayTwice) {
MockRead(ASYNC, ERR_IO_PENDING, 6),
MockRead(ASYNC, 0, 7) // EOF
};
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
CreateMockWrite(*req2, 1),
@@ -567,17 +569,17 @@ TEST_P(SpdySessionTest, GoAwayTwice) {
TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 2),
CreateMockRead(*goaway, 3),
MockRead(ASYNC, ERR_IO_PENDING, 4),
MockRead(ASYNC, 0, 5) // EOF
};
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
CreateMockWrite(*req2, 1),
@@ -641,16 +643,17 @@ TEST_P(SpdySessionTest, GoAwayWithActiveStreamsThenClose) {
TEST_P(SpdySessionTest, GoAwayWhileDraining) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
size_t joint_size = goaway->size() * 2 + body->size();
// Compose interleaved |goaway| and |body| frames into a single read.
@@ -665,7 +668,7 @@ TEST_P(SpdySessionTest, GoAwayWhileDraining) {
out += goaway->size();
ASSERT_EQ(out, joint_size);
}
- SpdyFrame joint_frames(buffer.get(), joint_size, false);
+ SpdySerializedFrame joint_frames(buffer.get(), joint_size, false);
MockRead reads[] = {
CreateMockRead(*resp, 1), CreateMockRead(joint_frames, 2),
@@ -702,15 +705,15 @@ TEST_P(SpdySessionTest, GoAwayWhileDraining) {
TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1),
CreateMockRead(*goaway, 2),
MockRead(ASYNC, ERR_IO_PENDING, 3),
MockRead(ASYNC, 0, 4) // EOF
};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
};
@@ -762,8 +765,8 @@ TEST_P(SpdySessionTest, CreateStreamAfterGoAway) {
TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
- scoped_ptr<SpdyFrame> push(
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(1));
+ scoped_ptr<SpdySerializedFrame> push(
spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kDefaultURL));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1),
@@ -772,9 +775,9 @@ TEST_P(SpdySessionTest, SynStreamAfterGoAway) {
CreateMockRead(*push, 4),
MockRead(ASYNC, 0, 6) // EOF
};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5)};
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
@@ -823,8 +826,8 @@ TEST_P(SpdySessionTest, NetworkChangeWithActiveStreams) {
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
};
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
};
@@ -882,13 +885,15 @@ TEST_P(SpdySessionTest, ClientPing) {
session_deps_.enable_ping = true;
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(1, true));
+ scoped_ptr<SpdySerializedFrame> read_ping(
+ spdy_util_.ConstructSpdyPing(1, true));
MockRead reads[] = {
CreateMockRead(*read_ping, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2),
MockRead(ASYNC, 0, 3) // EOF
};
- scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
+ scoped_ptr<SpdySerializedFrame> write_ping(
+ spdy_util_.ConstructSpdyPing(1, false));
MockWrite writes[] = {
CreateMockWrite(*write_ping, 0),
};
@@ -933,12 +938,14 @@ TEST_P(SpdySessionTest, ClientPing) {
TEST_P(SpdySessionTest, ServerPing) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> read_ping(spdy_util_.ConstructSpdyPing(2, false));
+ scoped_ptr<SpdySerializedFrame> read_ping(
+ spdy_util_.ConstructSpdyPing(2, false));
MockRead reads[] = {
CreateMockRead(*read_ping),
MockRead(SYNCHRONOUS, 0, 0) // EOF
};
- scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(2, true));
+ scoped_ptr<SpdySerializedFrame> write_ping(
+ spdy_util_.ConstructSpdyPing(2, true));
MockWrite writes[] = {
CreateMockWrite(*write_ping),
};
@@ -972,9 +979,10 @@ TEST_P(SpdySessionTest, PingAndWriteLoop) {
session_deps_.enable_ping = true;
session_deps_.time_func = TheNearFuture;
- scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> write_ping(
+ spdy_util_.ConstructSpdyPing(1, false));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
CreateMockWrite(*write_ping, 1),
@@ -1023,23 +1031,23 @@ TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
// stalled streams are aborted. Also verify the activated streams complete,
// at which point the session closes.
- scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyGet(
- nullptr, 0, false, kLastStreamId - 2, MEDIUM, true));
- scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
- nullptr, 0, false, kLastStreamId, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, kLastStreamId - 2, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, kLastStreamId, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1),
};
- scoped_ptr<SpdyFrame> resp1(
+ scoped_ptr<SpdySerializedFrame> resp1(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId - 2));
- scoped_ptr<SpdyFrame> resp2(
+ scoped_ptr<SpdySerializedFrame> resp2(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, kLastStreamId));
- scoped_ptr<SpdyFrame> body1(
+ scoped_ptr<SpdySerializedFrame> body1(
spdy_util_.ConstructSpdyBodyFrame(kLastStreamId - 2, true));
- scoped_ptr<SpdyFrame> body2(
+ scoped_ptr<SpdySerializedFrame> body2(
spdy_util_.ConstructSpdyBodyFrame(kLastStreamId, true));
MockRead reads[] = {
@@ -1132,6 +1140,113 @@ TEST_P(SpdySessionTest, StreamIdSpaceExhausted) {
EXPECT_FALSE(session_);
}
+// Regression test for https://crbug.com/481009.
+TEST_P(SpdySessionTest, MaxConcurrentStreamsZero) {
+ session_deps_.host_resolver->set_synchronous_mode(true);
+
+ int seq = 0;
+ std::vector<MockRead> reads;
+
+ // Receive SETTINGS frame that sets max_concurrent_streams to zero.
+ SettingsMap settings_zero;
+ settings_zero[SETTINGS_MAX_CONCURRENT_STREAMS] =
+ SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 0);
+ scoped_ptr<SpdySerializedFrame> settings_frame_zero(
+ spdy_util_.ConstructSpdySettings(settings_zero));
+ reads.push_back(CreateMockRead(*settings_frame_zero, seq++));
+
+ // Acknowledge it.
+ std::vector<MockWrite> writes;
+ scoped_ptr<SpdySerializedFrame> settings_ack0;
+ if (GetProtocol() == kProtoHTTP2) {
+ settings_ack0.reset(spdy_util_.ConstructSpdySettingsAck());
+ writes.push_back(CreateMockWrite(*settings_ack0, seq++));
+ }
+
+ // Pause.
+ reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, seq++));
+
+ // Receive SETTINGS frame that sets max_concurrent_streams to one.
+ SettingsMap settings_one;
+ settings_one[SETTINGS_MAX_CONCURRENT_STREAMS] =
+ SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 1);
+ scoped_ptr<SpdySerializedFrame> settings_frame_one(
+ spdy_util_.ConstructSpdySettings(settings_one));
+ reads.push_back(CreateMockRead(*settings_frame_one, seq++));
+
+ // Acknowledge it.
+ scoped_ptr<SpdySerializedFrame> settings_ack1;
+ if (GetProtocol() == kProtoHTTP2) {
+ settings_ack1.reset(spdy_util_.ConstructSpdySettingsAck());
+ writes.push_back(CreateMockWrite(*settings_ack1, seq++));
+ }
+
+ // Request and response.
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
+ writes.push_back(CreateMockWrite(*req, seq++));
+
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
+ reads.push_back(CreateMockRead(*resp, seq++));
+
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+ reads.push_back(CreateMockRead(*body, seq++));
+
+ reads.push_back(MockRead(ASYNC, 0, seq++));
+
+ SequencedSocketData data(reads.data(), reads.size(), writes.data(),
+ writes.size());
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ // Create session.
+ CreateNetworkSession();
+ CreateInsecureSpdySession();
+
+ // Receive SETTINGS frame that sets max_concurrent_streams to zero.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0u, session_->max_concurrent_streams_);
+
+ // Start request.
+ SpdyStreamRequest request;
+ TestCompletionCallback callback;
+ int rv =
+ request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_,
+ MEDIUM, BoundNetLog(), callback.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Stream is stalled.
+ EXPECT_EQ(1u, session_->pending_create_stream_queue_size(MEDIUM));
+ EXPECT_EQ(0u, session_->num_created_streams());
+
+ // Receive SETTINGS frame that sets max_concurrent_streams to one.
+ data.Resume();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1u, session_->max_concurrent_streams_);
+
+ // Stream is created.
+ EXPECT_EQ(0u, session_->pending_create_stream_queue_size(MEDIUM));
+ EXPECT_EQ(1u, session_->num_created_streams());
+
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ // Send request.
+ base::WeakPtr<SpdyStream> stream = request.ReleaseStream();
+ test::StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
+ scoped_ptr<SpdyHeaderBlock> headers(
+ spdy_util_.ConstructGetHeaderBlock(kDefaultURL));
+ stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
+ EXPECT_TRUE(stream->HasUrlFromHeaders());
+
+ EXPECT_EQ(OK, delegate.WaitForClose());
+ EXPECT_EQ("hello!", delegate.TakeReceivedData());
+
+ // Session is destroyed.
+ EXPECT_FALSE(session_);
+}
+
// Verifies that an unstalled pending stream creation racing with a new stream
// creation doesn't violate the maximum stream concurrency. Regression test for
// crbug.com/373858.
@@ -1198,19 +1313,19 @@ TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
session_deps_.host_resolver->set_synchronous_mode(true);
session_deps_.time_func = TheNearFuture;
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5)};
- scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> push_a(spdy_util_.ConstructSpdyPush(
nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
- scoped_ptr<SpdyFrame> push_a_body(
+ scoped_ptr<SpdySerializedFrame> push_a_body(
spdy_util_.ConstructSpdyBodyFrame(2, false));
// In ascii "0" < "a". We use it to verify that we properly handle std::map
// iterators inside. See http://crbug.com/443490
- scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> push_b(spdy_util_.ConstructSpdyPush(
nullptr, 0, 4, 1, "http://www.example.org/0.dat"));
MockRead reads[] = {
CreateMockRead(*push_a, 1),
@@ -1241,10 +1356,8 @@ TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
// Verify that there is one unclaimed push stream.
EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
- SpdySession::PushedStreamMap::iterator iter =
- session_->unclaimed_pushed_streams_.find(
- GURL("http://www.example.org/a.dat"));
- EXPECT_TRUE(session_->unclaimed_pushed_streams_.end() != iter);
+ EXPECT_EQ(1u, session_->count_unclaimed_pushed_streams_for_url(
+ GURL("http://www.example.org/a.dat")));
// Unclaimed push body consumed bytes from the session window.
EXPECT_EQ(
@@ -1260,9 +1373,8 @@ TEST_P(SpdySessionTest, DeleteExpiredPushStreams) {
// Verify that the second pushed stream evicted the first pushed stream.
EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
- iter = session_->unclaimed_pushed_streams_.find(
- GURL("http://www.example.org/0.dat"));
- EXPECT_TRUE(session_->unclaimed_pushed_streams_.end() != iter);
+ EXPECT_EQ(1u, session_->count_unclaimed_pushed_streams_for_url(
+ GURL("http://www.example.org/0.dat")));
// Verify that the session window reclaimed the evicted stream body.
EXPECT_EQ(SpdySession::GetDefaultInitialWindowSize(GetProtocol()),
@@ -1282,8 +1394,9 @@ TEST_P(SpdySessionTest, FailedPing) {
MockRead reads[] = {
MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
};
- scoped_ptr<SpdyFrame> write_ping(spdy_util_.ConstructSpdyPing(1, false));
- scoped_ptr<SpdyFrame> goaway(
+ scoped_ptr<SpdySerializedFrame> write_ping(
+ spdy_util_.ConstructSpdyPing(1, false));
+ scoped_ptr<SpdySerializedFrame> goaway(
spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Failed ping."));
MockWrite writes[] = {CreateMockWrite(*write_ping), CreateMockWrite(*goaway)};
@@ -1339,7 +1452,8 @@ TEST_P(SpdySessionTest, OnSettings) {
int seq = 0;
std::vector<MockWrite> writes;
- scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
+ scoped_ptr<SpdySerializedFrame> settings_ack(
+ spdy_util_.ConstructSpdySettingsAck());
if (GetProtocol() == kProtoHTTP2) {
writes.push_back(CreateMockWrite(*settings_ack, ++seq));
}
@@ -1348,7 +1462,7 @@ TEST_P(SpdySessionTest, OnSettings) {
const uint32_t max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
new_settings[kSpdySettingsIds] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
- scoped_ptr<SpdyFrame> settings_frame(
+ scoped_ptr<SpdySerializedFrame> settings_frame(
spdy_util_.ConstructSpdySettings(new_settings));
MockRead reads[] = {
CreateMockRead(*settings_frame, 0),
@@ -1405,7 +1519,7 @@ TEST_P(SpdySessionTest, ClearSettings) {
const uint32_t max_concurrent_streams = kInitialMaxConcurrentStreams + 1;
new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
- scoped_ptr<SpdyFrame> settings_frame(
+ scoped_ptr<SpdySerializedFrame> settings_frame(
spdy_util_.ConstructSpdySettings(new_settings));
uint8_t flags = SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
test::SetFrameFlags(settings_frame.get(), flags, spdy_util_.spdy_version());
@@ -1459,7 +1573,7 @@ TEST_P(SpdySessionTest, ClearSettings) {
// Make sure session's max_concurrent_streams is correct.
EXPECT_EQ(kInitialMaxConcurrentStreams + 1,
- session_->max_concurrent_streams());
+ session_->max_concurrent_streams_);
data.Resume();
base::RunLoop().RunUntilIdle();
@@ -1534,7 +1648,7 @@ TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
SettingsMap settings;
settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
- scoped_ptr<SpdyFrame> settings_frame(
+ scoped_ptr<SpdySerializedFrame> settings_frame(
spdy_util_.ConstructSpdySettings(settings));
std::vector<MockWrite> writes;
if (GetProtocol() == kProtoHTTP2) {
@@ -1550,7 +1664,7 @@ TEST_P(SpdySessionTest, SendInitialDataOnNewSession) {
server_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED,
initial_max_concurrent_streams);
- scoped_ptr<SpdyFrame> server_settings_frame(
+ scoped_ptr<SpdySerializedFrame> server_settings_frame(
spdy_util_.ConstructSpdySettings(server_settings));
if (GetProtocol() == kProtoSPDY31) {
writes.push_back(CreateMockWrite(*server_settings_frame));
@@ -1632,7 +1746,7 @@ TEST_P(SpdySessionTest, Initialize) {
TEST_P(SpdySessionTest, NetLogOnSessionGoaway) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> goaway(
+ scoped_ptr<SpdySerializedFrame> goaway(
spdy_util_.ConstructSpdyGoAway(42, GOAWAY_ENHANCE_YOUR_CALM, "foo"));
MockRead reads[] = {
CreateMockRead(*goaway),
@@ -1728,10 +1842,8 @@ TEST_P(SpdySessionTest, NetLogOnSessionEOF) {
}
TEST_P(SpdySessionTest, SynCompressionHistograms) {
- session_deps_.enable_compression = true;
-
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, true, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
};
@@ -1784,22 +1896,22 @@ TEST_P(SpdySessionTest, SynCompressionHistograms) {
// first.
TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
// Construct the request.
- scoped_ptr<SpdyFrame> req_highest(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, HIGHEST, true));
- scoped_ptr<SpdyFrame> req_lowest(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req_highest(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST, true));
+ scoped_ptr<SpdySerializedFrame> req_lowest(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req_highest, 0),
CreateMockWrite(*req_lowest, 1),
};
- scoped_ptr<SpdyFrame> resp_highest(
+ scoped_ptr<SpdySerializedFrame> resp_highest(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> body_highest(
+ scoped_ptr<SpdySerializedFrame> body_highest(
spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> resp_lowest(
+ scoped_ptr<SpdySerializedFrame> resp_lowest(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
- scoped_ptr<SpdyFrame> body_lowest(
+ scoped_ptr<SpdySerializedFrame> body_lowest(
spdy_util_.ConstructSpdyBodyFrame(3, true));
MockRead reads[] = {
CreateMockRead(*resp_highest, 2),
@@ -1857,15 +1969,16 @@ TEST_P(SpdySessionTest, OutOfOrderSynStreams) {
TEST_P(SpdySessionTest, CancelStream) {
// Request 1, at HIGHEST priority, will be cancelled before it writes data.
// Request 2, at LOWEST priority, will be a full request and will be id 1.
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*req2, 0),
};
- scoped_ptr<SpdyFrame> resp2(
+ scoped_ptr<SpdySerializedFrame> resp2(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
CreateMockRead(*resp2, 1),
MockRead(ASYNC, ERR_IO_PENDING, 2),
@@ -2047,10 +2160,10 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) {
TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
CreateMockWrite(*req2, 1),
@@ -2121,10 +2234,10 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) {
TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
CreateMockWrite(*req2, 1),
@@ -2215,11 +2328,11 @@ class SessionClosingDelegate : public test::StreamDelegateDoNothing {
TEST_P(SpdySessionTest, CloseActivatedStreamThatClosesSession) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
- scoped_ptr<SpdyFrame> goaway(
+ scoped_ptr<SpdySerializedFrame> goaway(
spdy_util_.ConstructSpdyGoAway(0, GOAWAY_PROTOCOL_ERROR, "Error"));
// The GOAWAY has higher-priority than the RST_STREAM, and is written first
// despite being queued second.
@@ -2338,15 +2451,16 @@ TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
new_settings[kSpdySettingsIds1] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
- scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> settings_ack(
+ spdy_util_.ConstructSpdySettingsAck());
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
spdy_util_.UpdateWithStreamDestruction(1);
- scoped_ptr<SpdyFrame> req2(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 3, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req2(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
spdy_util_.UpdateWithStreamDestruction(3);
- scoped_ptr<SpdyFrame> req3(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 5, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> req3(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*settings_ack, 1),
CreateMockWrite(*req1, 2),
@@ -2356,20 +2470,23 @@ TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) {
// Set up the socket so we read a SETTINGS frame that sets max concurrent
// streams to 1.
- scoped_ptr<SpdyFrame> settings_frame(
+ scoped_ptr<SpdySerializedFrame> settings_frame(
spdy_util_.ConstructSpdySettings(new_settings));
- scoped_ptr<SpdyFrame> resp1(
+ scoped_ptr<SpdySerializedFrame> resp1(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body1(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> resp2(
+ scoped_ptr<SpdySerializedFrame> resp2(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
- scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
+ scoped_ptr<SpdySerializedFrame> body2(
+ spdy_util_.ConstructSpdyBodyFrame(3, true));
- scoped_ptr<SpdyFrame> resp3(
+ scoped_ptr<SpdySerializedFrame> resp3(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 5));
- scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
+ scoped_ptr<SpdySerializedFrame> body3(
+ spdy_util_.ConstructSpdyBodyFrame(5, true));
MockRead reads[] = {
CreateMockRead(*settings_frame, 0),
@@ -2564,10 +2681,10 @@ TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
session_deps_.host_resolver->set_synchronous_mode(true);
session_deps_.time_func = InstantaneousReads;
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
};
@@ -2582,12 +2699,12 @@ TEST_P(SpdySessionTest, ReadDataWithoutYielding) {
char* payload_data = payload->data();
test_stream.GetBytes(payload_data, kPayloadSize);
- scoped_ptr<SpdyFrame> partial_data_frame(
+ scoped_ptr<SpdySerializedFrame> partial_data_frame(
framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> finish_data_frame(
+ scoped_ptr<SpdySerializedFrame> finish_data_frame(
framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
- scoped_ptr<SpdyFrame> resp1(
+ scoped_ptr<SpdySerializedFrame> resp1(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
// Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
@@ -2651,15 +2768,15 @@ TEST_P(SpdySessionTest, TestYieldingSlowReads) {
session_deps_.host_resolver->set_synchronous_mode(true);
session_deps_.time_func = SlowReads;
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
};
- scoped_ptr<SpdyFrame> resp1(
+ scoped_ptr<SpdySerializedFrame> resp1(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
MockRead reads[] = {
@@ -2712,20 +2829,20 @@ TEST_P(SpdySessionTest, TestYieldingSlowSynchronousReads) {
session_deps_.host_resolver->set_synchronous_mode(true);
session_deps_.time_func = SlowReads;
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
};
- scoped_ptr<SpdyFrame> partial_data_frame(
+ scoped_ptr<SpdySerializedFrame> partial_data_frame(
framer.CreateDataFrame(1, "foo ", 4, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> finish_data_frame(
+ scoped_ptr<SpdySerializedFrame> finish_data_frame(
framer.CreateDataFrame(1, "bar", 3, DATA_FLAG_FIN));
- scoped_ptr<SpdyFrame> resp1(
+ scoped_ptr<SpdySerializedFrame> resp1(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
MockRead reads[] = {
@@ -2780,10 +2897,10 @@ TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
session_deps_.host_resolver->set_synchronous_mode(true);
session_deps_.time_func = InstantaneousReads;
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
};
@@ -2798,12 +2915,12 @@ TEST_P(SpdySessionTest, TestYieldingDuringReadData) {
char* payload_data = payload->data();
test_stream.GetBytes(payload_data, kPayloadSize);
- scoped_ptr<SpdyFrame> partial_data_frame(
+ scoped_ptr<SpdySerializedFrame> partial_data_frame(
framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> finish_data_frame(
+ scoped_ptr<SpdySerializedFrame> finish_data_frame(
framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
- scoped_ptr<SpdyFrame> resp1(
+ scoped_ptr<SpdySerializedFrame> resp1(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
// Write 1 byte more than kMaxReadBytes to check that DoRead yields.
@@ -2874,10 +2991,10 @@ TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
session_deps_.host_resolver->set_synchronous_mode(true);
session_deps_.time_func = InstantaneousReads;
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
};
@@ -2899,14 +3016,14 @@ TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
char* twok_payload_data = twok_payload->data();
test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
- scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
+ scoped_ptr<SpdySerializedFrame> eightk_data_frame(framer.CreateDataFrame(
1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
+ scoped_ptr<SpdySerializedFrame> twok_data_frame(framer.CreateDataFrame(
1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
- scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
- 1, "h", 1, DATA_FLAG_FIN));
+ scoped_ptr<SpdySerializedFrame> finish_data_frame(
+ framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
- scoped_ptr<SpdyFrame> resp1(
+ scoped_ptr<SpdySerializedFrame> resp1(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
MockRead reads[] = {
@@ -2973,18 +3090,19 @@ TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) {
TEST_P(SpdySessionTest, GoAwayWhileInDoReadLoop) {
session_deps_.host_resolver->set_synchronous_mode(true);
- BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
+ BufferedSpdyFramer framer(spdy_util_.spdy_version());
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
};
- scoped_ptr<SpdyFrame> resp1(
+ scoped_ptr<SpdySerializedFrame> resp1(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway());
+ scoped_ptr<SpdySerializedFrame> body1(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway());
MockRead reads[] = {
CreateMockRead(*resp1, 1),
@@ -3080,13 +3198,13 @@ TEST_P(SpdySessionTest, CloseOneIdleConnection) {
// post a task asynchronously to try and close the session.
TestCompletionCallback callback2;
HostPortPair host_port2("2.com", 80);
- scoped_refptr<TransportSocketParams> params2(
- new TransportSocketParams(
- host_port2, false, false, OnHostResolutionCallback(),
- TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
+ scoped_refptr<TransportSocketParams> params2(new TransportSocketParams(
+ host_port2, false, OnHostResolutionCallback(),
+ TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
EXPECT_EQ(ERR_IO_PENDING,
connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
callback2.callback(), pool, BoundNetLog()));
EXPECT_TRUE(pool->IsStalled());
@@ -3147,7 +3265,7 @@ TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
BoundNetLog());
// Get a session for |key2|, which should return the session created earlier.
base::WeakPtr<SpdySession> session2 =
- spdy_session_pool_->FindAvailableSession(key2, BoundNetLog());
+ spdy_session_pool_->FindAvailableSession(key2, GURL(), BoundNetLog());
ASSERT_EQ(session1.get(), session2.get());
EXPECT_FALSE(pool->IsStalled());
@@ -3155,13 +3273,13 @@ TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
// post a task asynchronously to try and close the session.
TestCompletionCallback callback3;
HostPortPair host_port3("3.com", 80);
- scoped_refptr<TransportSocketParams> params3(
- new TransportSocketParams(
- host_port3, false, false, OnHostResolutionCallback(),
- TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
+ scoped_refptr<TransportSocketParams> params3(new TransportSocketParams(
+ host_port3, false, OnHostResolutionCallback(),
+ TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle);
EXPECT_EQ(ERR_IO_PENDING,
connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
callback3.callback(), pool, BoundNetLog()));
EXPECT_TRUE(pool->IsStalled());
@@ -3184,9 +3302,9 @@ TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
MockRead reads[] = {
MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
};
- scoped_ptr<SpdyFrame> req1(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> cancel1(
+ scoped_ptr<SpdySerializedFrame> req1(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> cancel1(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*req1, 1),
@@ -3236,13 +3354,13 @@ TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
// post a task asynchronously to try and close the session.
TestCompletionCallback callback2;
HostPortPair host_port2("2.com", 80);
- scoped_refptr<TransportSocketParams> params2(
- new TransportSocketParams(
- host_port2, false, false, OnHostResolutionCallback(),
- TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
+ scoped_refptr<TransportSocketParams> params2(new TransportSocketParams(
+ host_port2, false, OnHostResolutionCallback(),
+ TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle);
EXPECT_EQ(ERR_IO_PENDING,
connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY,
+ ClientSocketPool::RespectLimits::ENABLED,
callback2.callback(), pool, BoundNetLog()));
EXPECT_TRUE(pool->IsStalled());
@@ -3326,13 +3444,13 @@ class StreamCreatingDelegate : public test::StreamDelegateDoNothing {
TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true));
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
};
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1),
@@ -3390,7 +3508,7 @@ TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
// Set up the socket so we read a SETTINGS frame that sets
// INITIAL_WINDOW_SIZE.
- scoped_ptr<SpdyFrame> settings_frame(
+ scoped_ptr<SpdySerializedFrame> settings_frame(
spdy_util_.ConstructSpdySettings(new_settings));
MockRead reads[] = {
CreateMockRead(*settings_frame, 0),
@@ -3398,7 +3516,8 @@ TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
MockRead(ASYNC, 0, 2) // EOF
};
- scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
+ scoped_ptr<SpdySerializedFrame> settings_ack(
+ spdy_util_.ConstructSpdySettingsAck());
MockWrite writes[] = {
CreateMockWrite(*settings_ack, 3),
};
@@ -3452,8 +3571,10 @@ TEST_P(SpdySessionTest, AdjustRecvWindowSize) {
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF
};
- scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId, initial_window_size + delta_window_size));
+ scoped_ptr<SpdySerializedFrame> window_update(
+ spdy_util_.ConstructSpdyWindowUpdate(
+ kSessionFlowControlStreamId,
+ initial_window_size + delta_window_size));
MockWrite writes[] = {
CreateMockWrite(*window_update, 0),
};
@@ -3528,7 +3649,8 @@ TEST_P(SpdySessionTest, AdjustSendWindowSize) {
TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyBodyFrame(1, false));
MockRead reads[] = {
CreateMockRead(*resp, 0),
MockRead(ASYNC, ERR_IO_PENDING, 1),
@@ -3566,7 +3688,7 @@ TEST_P(SpdySessionTest, SessionFlowControlPadding) {
session_deps_.host_resolver->set_synchronous_mode(true);
const int padding_length = 42;
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyBodyFrame(
+ scoped_ptr<SpdySerializedFrame> resp(spdy_util_.ConstructSpdyBodyFrame(
1, kUploadData, kUploadDataSize, false, padding_length));
MockRead reads[] = {
CreateMockRead(*resp, 0),
@@ -3600,18 +3722,18 @@ TEST_P(SpdySessionTest, StreamFlowControlTooMuchData) {
const int32_t stream_max_recv_window_size = 1024;
const int32_t data_frame_size = 2 * stream_max_recv_window_size;
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
const std::string payload(data_frame_size, 'a');
- scoped_ptr<SpdyFrame> data_frame(spdy_util_.ConstructSpdyBodyFrame(
+ scoped_ptr<SpdySerializedFrame> data_frame(spdy_util_.ConstructSpdyBodyFrame(
1, payload.data(), data_frame_size, false));
MockRead reads[] = {
CreateMockRead(*resp, 1),
@@ -3675,7 +3797,7 @@ TEST_P(SpdySessionTest, SessionFlowControlTooMuchDataTwoDataFrames) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(
0, GOAWAY_FLOW_CONTROL_ERROR,
"delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
"than the receive window size of 500"));
@@ -3684,10 +3806,10 @@ TEST_P(SpdySessionTest, SessionFlowControlTooMuchDataTwoDataFrames) {
};
const std::string first_data_frame(first_data_frame_size, 'a');
- scoped_ptr<SpdyFrame> first(spdy_util_.ConstructSpdyBodyFrame(
+ scoped_ptr<SpdySerializedFrame> first(spdy_util_.ConstructSpdyBodyFrame(
1, first_data_frame.data(), first_data_frame_size, false));
const std::string second_data_frame(second_data_frame_size, 'b');
- scoped_ptr<SpdyFrame> second(spdy_util_.ConstructSpdyBodyFrame(
+ scoped_ptr<SpdySerializedFrame> second(spdy_util_.ConstructSpdyBodyFrame(
1, second_data_frame.data(), second_data_frame_size, false));
MockRead reads[] = {
CreateMockRead(*first, 0),
@@ -3734,21 +3856,21 @@ TEST_P(SpdySessionTest, StreamFlowControlTooMuchDataTwoDataFrames) {
ASSERT_LT(stream_max_recv_window_size,
first_data_frame_size + second_data_frame_size);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 6),
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
const std::string first_data_frame(first_data_frame_size, 'a');
- scoped_ptr<SpdyFrame> first(spdy_util_.ConstructSpdyBodyFrame(
+ scoped_ptr<SpdySerializedFrame> first(spdy_util_.ConstructSpdyBodyFrame(
1, first_data_frame.data(), first_data_frame_size, false));
const std::string second_data_frame(second_data_frame_size, 'b');
- scoped_ptr<SpdyFrame> second(spdy_util_.ConstructSpdyBodyFrame(
+ scoped_ptr<SpdySerializedFrame> second(spdy_util_.ConstructSpdyBodyFrame(
1, second_data_frame.data(), second_data_frame_size, false));
MockRead reads[] = {
CreateMockRead(*resp, 1),
@@ -3828,21 +3950,22 @@ TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) {
const int32_t kMsgDataSize = 100;
const std::string msg_data(kMsgDataSize, 'a');
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
kDefaultURL, 1, kMsgDataSize, MEDIUM, nullptr, 0));
- scoped_ptr<SpdyFrame> msg(spdy_util_.ConstructSpdyBodyFrame(
+ scoped_ptr<SpdySerializedFrame> msg(spdy_util_.ConstructSpdyBodyFrame(
1, msg_data.data(), kMsgDataSize, false));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
CreateMockWrite(*msg, 2),
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> echo(spdy_util_.ConstructSpdyBodyFrame(
+ scoped_ptr<SpdySerializedFrame> echo(spdy_util_.ConstructSpdyBodyFrame(
1, msg_data.data(), kMsgDataSize, false));
- scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId, kMsgDataSize));
+ scoped_ptr<SpdySerializedFrame> window_update(
+ spdy_util_.ConstructSpdyWindowUpdate(kSessionFlowControlStreamId,
+ kMsgDataSize));
MockRead reads[] = {
CreateMockRead(*resp, 1),
CreateMockRead(*echo, 3),
@@ -3902,13 +4025,13 @@ TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) {
const int32_t kMsgDataSize = 100;
const std::string msg_data(kMsgDataSize, 'a');
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
kDefaultURL, 1, kMsgDataSize, MEDIUM, nullptr, 0));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1),
@@ -3975,21 +4098,22 @@ TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) {
const int32_t kMsgDataSize = 100;
const std::string msg_data(kMsgDataSize, 'a');
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
kDefaultURL, 1, kMsgDataSize, MEDIUM, nullptr, 0));
- scoped_ptr<SpdyFrame> msg(spdy_util_.ConstructSpdyBodyFrame(
+ scoped_ptr<SpdySerializedFrame> msg(spdy_util_.ConstructSpdyBodyFrame(
1, msg_data.data(), kMsgDataSize, false));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
CreateMockWrite(*msg, 2),
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> echo(spdy_util_.ConstructSpdyBodyFrame(
+ scoped_ptr<SpdySerializedFrame> echo(spdy_util_.ConstructSpdyBodyFrame(
1, msg_data.data(), kMsgDataSize, false));
- scoped_ptr<SpdyFrame> window_update(spdy_util_.ConstructSpdyWindowUpdate(
- kSessionFlowControlStreamId, kMsgDataSize));
+ scoped_ptr<SpdySerializedFrame> window_update(
+ spdy_util_.ConstructSpdyWindowUpdate(kSessionFlowControlStreamId,
+ kMsgDataSize));
MockRead reads[] = {
CreateMockRead(*resp, 1),
MockRead(ASYNC, ERR_IO_PENDING, 3),
@@ -4084,18 +4208,18 @@ void SpdySessionTest::RunResumeAfterUnstallTest(
const base::Callback<void(SpdyStream*, int32_t)>& unstall_function) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
kDefaultURL, 1, kBodyDataSize, LOWEST, nullptr, 0));
- scoped_ptr<SpdyFrame> body(
+ scoped_ptr<SpdySerializedFrame> body(
spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
MockWrite writes[] = {
CreateMockWrite(*req, 0),
CreateMockWrite(*body, 1),
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> echo(
+ scoped_ptr<SpdySerializedFrame> echo(
spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
MockRead reads[] = {
CreateMockRead(*resp, 2), MockRead(ASYNC, 0, 3) // EOF
@@ -4202,13 +4326,13 @@ TEST_P(SpdySessionTest, StallSessionStreamResumeAfterUnstallStreamSession) {
TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req1(spdy_util_.ConstructSpdyPost(
kDefaultURL, 1, kBodyDataSize, LOWEST, nullptr, 0));
- scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req2(spdy_util_.ConstructSpdyPost(
kDefaultURL, 3, kBodyDataSize, MEDIUM, nullptr, 0));
- scoped_ptr<SpdyFrame> body1(
+ scoped_ptr<SpdySerializedFrame> body1(
spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, true));
- scoped_ptr<SpdyFrame> body2(
+ scoped_ptr<SpdySerializedFrame> body2(
spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
@@ -4217,9 +4341,9 @@ TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) {
CreateMockWrite(*body1, 3),
};
- scoped_ptr<SpdyFrame> resp1(
+ scoped_ptr<SpdySerializedFrame> resp1(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> resp2(
+ scoped_ptr<SpdySerializedFrame> resp2(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
MockRead reads[] = {
CreateMockRead(*resp1, 4),
@@ -4343,13 +4467,13 @@ class StreamClosingDelegate : public test::StreamDelegateWithBody {
TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req1(spdy_util_.ConstructSpdyPost(
kDefaultURL, 1, kBodyDataSize, LOWEST, nullptr, 0));
- scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req2(spdy_util_.ConstructSpdyPost(
kDefaultURL, 3, kBodyDataSize, LOWEST, nullptr, 0));
- scoped_ptr<SpdyFrame> req3(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req3(spdy_util_.ConstructSpdyPost(
kDefaultURL, 5, kBodyDataSize, LOWEST, nullptr, 0));
- scoped_ptr<SpdyFrame> body2(
+ scoped_ptr<SpdySerializedFrame> body2(
spdy_util_.ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, true));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
@@ -4358,7 +4482,7 @@ TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
CreateMockWrite(*body2, 3),
};
- scoped_ptr<SpdyFrame> resp2(
+ scoped_ptr<SpdySerializedFrame> resp2(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 3));
MockRead reads[] = {
CreateMockRead(*resp2, 4),
@@ -4490,11 +4614,11 @@ TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) {
TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
session_deps_.host_resolver->set_synchronous_mode(true);
- scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req1(spdy_util_.ConstructSpdyPost(
kDefaultURL, 1, kBodyDataSize, LOWEST, nullptr, 0));
- scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req2(spdy_util_.ConstructSpdyPost(
kDefaultURL, 3, kBodyDataSize, LOWEST, nullptr, 0));
- scoped_ptr<SpdyFrame> body1(
+ scoped_ptr<SpdySerializedFrame> body1(
spdy_util_.ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false));
MockWrite writes[] = {
CreateMockWrite(*req1, 0),
@@ -4583,9 +4707,9 @@ TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) {
}
TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> goaway(spdy_util_.ConstructSpdyGoAway(
0, GOAWAY_FLOW_CONTROL_ERROR,
"delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than "
"the receive window size of 1"));
@@ -4593,9 +4717,10 @@ TEST_P(SpdySessionTest, GoAwayOnSessionFlowControlError) {
CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 4),
};
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
- scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
+ scoped_ptr<SpdySerializedFrame> body(
+ spdy_util_.ConstructSpdyBodyFrame(1, true));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1),
CreateMockRead(*resp, 2),
@@ -4651,7 +4776,7 @@ TEST_P(SpdySessionTest, SplitHeaders) {
EXPECT_EQ("beta", alpha_val);
GURL request_url =
- GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version(), true);
+ GetUrlFromHeaderBlock(request_headers, spdy_util_.spdy_version());
EXPECT_EQ(kStreamUrl, request_url);
}
@@ -4661,9 +4786,9 @@ TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
SettingsMap new_settings;
new_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2);
- scoped_ptr<SpdyFrame> settings_frame(
+ scoped_ptr<SpdySerializedFrame> settings_frame(
spdy_util_.ConstructSpdySettings(new_settings));
- scoped_ptr<SpdyFrame> pushed(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> pushed(spdy_util_.ConstructSpdyPush(
nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
MockRead reads[] = {
CreateMockRead(*settings_frame, 0),
@@ -4673,9 +4798,10 @@ TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
MockRead(ASYNC, 0, 6),
};
- scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> settings_ack(
+ spdy_util_.ConstructSpdySettingsAck());
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
MockWrite writes[] = {
CreateMockWrite(*settings_ack, 1), CreateMockWrite(*req, 2),
};
@@ -4741,9 +4867,9 @@ TEST_P(SpdySessionTest, PushedStreamShouldNotCountToClientConcurrencyLimit) {
}
TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
- scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> push_a(spdy_util_.ConstructSpdyPush(
nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
- scoped_ptr<SpdyFrame> push_b(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> push_b(spdy_util_.ConstructSpdyPush(
nullptr, 0, 4, 1, "http://www.example.org/b.dat"));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1),
@@ -4754,9 +4880,9 @@ TEST_P(SpdySessionTest, RejectPushedStreamExceedingConcurrencyLimit) {
MockRead(ASYNC, 0, 7),
};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
@@ -4827,11 +4953,13 @@ TEST_P(SpdySessionTest, TrustedSpdyProxy) {
// cross_origin_push contains HTTP resource for an origin different from the
// origin of kDefaultURL, and should be accepted.
- scoped_ptr<SpdyFrame> cross_origin_push(spdy_util_.ConstructSpdyPush(
- nullptr, 0, 2, 1, kHttpURLFromAnotherOrigin));
+ scoped_ptr<SpdySerializedFrame> cross_origin_push(
+ spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1,
+ kHttpURLFromAnotherOrigin));
// cross_origin_https_push contains HTTPS resource, and should be refused.
- scoped_ptr<SpdyFrame> cross_origin_https_push(spdy_util_.ConstructSpdyPush(
- nullptr, 0, 4, 1, kHttpsURLFromAnotherOrigin));
+ scoped_ptr<SpdySerializedFrame> cross_origin_https_push(
+ spdy_util_.ConstructSpdyPush(nullptr, 0, 4, 1,
+ kHttpsURLFromAnotherOrigin));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1),
CreateMockRead(*cross_origin_push, 2),
@@ -4841,9 +4969,9 @@ TEST_P(SpdySessionTest, TrustedSpdyProxy) {
MockRead(ASYNC, 0, 7),
};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
@@ -4851,8 +4979,12 @@ TEST_P(SpdySessionTest, TrustedSpdyProxy) {
SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
session_deps_.socket_factory->AddSocketDataProvider(&data);
- session_deps_.trusted_spdy_proxy =
- HostPortPair::FromURL(GURL(kDefaultURL)).ToString();
+
+ scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
+ proxy_delegate->set_trusted_spdy_proxy(
+ net::ProxyServer(net::ProxyServer::SCHEME_HTTPS,
+ HostPortPair(GURL(kDefaultURL).host(), 80)));
+ session_deps_.proxy_delegate.reset(proxy_delegate.release());
CreateNetworkSession();
CreateInsecureSpdySession();
@@ -4914,16 +5046,17 @@ TEST_P(SpdySessionTest, TrustedSpdyProxyNotSet) {
// cross_origin_push contains resource for an origin different from the
// origin of kDefaultURL, and should be refused.
- scoped_ptr<SpdyFrame> cross_origin_push(spdy_util_.ConstructSpdyPush(
- nullptr, 0, 2, 1, kHttpURLFromAnotherOrigin));
+ scoped_ptr<SpdySerializedFrame> cross_origin_push(
+ spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1,
+ kHttpURLFromAnotherOrigin));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(*cross_origin_push, 2),
MockRead(ASYNC, 0, 4),
};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
@@ -4972,14 +5105,14 @@ TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
if (spdy_util_.spdy_version() < HTTP2)
return;
- scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
+ scoped_ptr<SpdySerializedFrame> push_a(spdy_util_.ConstructSpdyPush(
nullptr, 0, 2, 1, "http://www.example.org/a.dat"));
scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
spdy_util_.AddUrlToHeaderBlock("http://www.example.org/b.dat",
push_headers.get());
- scoped_ptr<SpdyFrame> push_b(
+ scoped_ptr<SpdySerializedFrame> push_b(
spdy_util_.ConstructInitialSpdyPushFrame(std::move(push_headers), 4, 1));
- scoped_ptr<SpdyFrame> headers_b(
+ scoped_ptr<SpdySerializedFrame> headers_b(
spdy_util_.ConstructSpdyPushHeaders(4, nullptr, 0));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1),
@@ -4992,9 +5125,9 @@ TEST_P(SpdySessionTest, IgnoreReservedRemoteStreamsCount) {
MockRead(ASYNC, 0, 9),
};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_REFUSED_STREAM));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 7),
@@ -5072,9 +5205,9 @@ TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
const char kPushedUrl[] = "http://www.example.org/a.dat";
scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
spdy_util_.AddUrlToHeaderBlock(kPushedUrl, push_headers.get());
- scoped_ptr<SpdyFrame> push_promise(
+ scoped_ptr<SpdySerializedFrame> push_promise(
spdy_util_.ConstructInitialSpdyPushFrame(std::move(push_headers), 2, 1));
- scoped_ptr<SpdyFrame> headers_frame(
+ scoped_ptr<SpdySerializedFrame> headers_frame(
spdy_util_.ConstructSpdyPushHeaders(2, nullptr, 0));
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 1),
@@ -5085,9 +5218,9 @@ TEST_P(SpdySessionTest, CancelReservedStreamOnHeadersReceived) {
MockRead(ASYNC, 0, 7),
};
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
MockWrite writes[] = {
CreateMockWrite(*req, 0), CreateMockWrite(*rst, 5),
diff --git a/chromium/net/spdy/spdy_stream.cc b/chromium/net/spdy/spdy_stream.cc
index 4fedae416cb..9a7ddef8162 100644
--- a/chromium/net/spdy/spdy_stream.cc
+++ b/chromium/net/spdy/spdy_stream.cc
@@ -203,7 +203,7 @@ void SpdyStream::PushedStreamReplay() {
}
}
-scoped_ptr<SpdyFrame> SpdyStream::ProduceSynStreamFrame() {
+scoped_ptr<SpdySerializedFrame> SpdyStream::ProduceSynStreamFrame() {
CHECK_EQ(io_state_, STATE_IDLE);
CHECK(request_headers_);
CHECK_GT(stream_id_, 0u);
@@ -211,7 +211,7 @@ scoped_ptr<SpdyFrame> SpdyStream::ProduceSynStreamFrame() {
SpdyControlFlags flags =
(pending_send_status_ == NO_MORE_DATA_TO_SEND) ?
CONTROL_FLAG_FIN : CONTROL_FLAG_NONE;
- scoped_ptr<SpdyFrame> frame(session_->CreateSynStream(
+ scoped_ptr<SpdySerializedFrame> frame(session_->CreateSynStream(
stream_id_, priority_, flags, *request_headers_));
send_time_ = base::TimeTicks::Now();
return frame;
@@ -782,8 +782,7 @@ GURL SpdyStream::GetUrlFromHeaders() const {
if (!request_headers_)
return GURL();
- return GetUrlFromHeaderBlock(
- *request_headers_, GetProtocolVersion(), type_ == SPDY_PUSH_STREAM);
+ return GetUrlFromHeaderBlock(*request_headers_, GetProtocolVersion());
}
bool SpdyStream::HasUrlFromHeaders() const {
diff --git a/chromium/net/spdy/spdy_stream.h b/chromium/net/spdy/spdy_stream.h
index 43629957cb0..742f24867c9 100644
--- a/chromium/net/spdy/spdy_stream.h
+++ b/chromium/net/spdy/spdy_stream.h
@@ -481,11 +481,11 @@ class NET_EXPORT_PRIVATE SpdyStream {
// Produces the SYN_STREAM frame for the stream. The stream must
// already be activated.
- scoped_ptr<SpdyFrame> ProduceSynStreamFrame();
+ scoped_ptr<SpdySerializedFrame> ProduceSynStreamFrame();
// Produce the initial HEADER frame for the stream with the given
// block. The stream must already be activated.
- scoped_ptr<SpdyFrame> ProduceHeaderFrame(
+ scoped_ptr<SpdySerializedFrame> ProduceHeaderFrame(
scoped_ptr<SpdyHeaderBlock> header_block);
// Queues the send for next frame of the remaining data in
diff --git a/chromium/net/spdy/spdy_stream_unittest.cc b/chromium/net/spdy/spdy_stream_unittest.cc
index 7177651411e..e9867dc1ecd 100644
--- a/chromium/net/spdy/spdy_stream_unittest.cc
+++ b/chromium/net/spdy/spdy_stream_unittest.cc
@@ -69,14 +69,12 @@ class SpdyStreamTest : public ::testing::Test,
SpdyStreamTest()
: spdy_util_(GetProtocol(), GetDependenciesFromPriority()),
session_deps_(GetProtocol()),
- session_(SpdySessionDependencies::SpdyCreateSession(&session_deps_)),
offset_(0) {
- SpdySession::SetPriorityDependencyDefaultForTesting(
- GetDependenciesFromPriority());
+ session_deps_.enable_priority_dependencies = GetDependenciesFromPriority();
+ session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
}
~SpdyStreamTest() {
- SpdySession::SetPriorityDependencyDefaultForTesting(false);
}
base::WeakPtr<SpdySession> CreateDefaultSpdySession() {
@@ -104,11 +102,11 @@ class SpdyStreamTest : public ::testing::Test,
// Add{Read,Write}() populates lists that are eventually passed to a
// SocketData class. |frame| must live for the whole test.
- void AddRead(const SpdyFrame& frame) {
+ void AddRead(const SpdySerializedFrame& frame) {
reads_.push_back(CreateMockRead(frame, offset_++));
}
- void AddWrite(const SpdyFrame& frame) {
+ void AddWrite(const SpdySerializedFrame& frame) {
writes_.push_back(CreateMockWrite(frame, offset_++));
}
@@ -156,20 +154,19 @@ INSTANTIATE_TEST_CASE_P(ProtoPlusDepend,
TEST_P(SpdyStreamTest, SendDataAfterOpen) {
GURL url(kStreamUrl);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
+ kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
AddWrite(*req);
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
AddRead(*resp);
- scoped_ptr<SpdyFrame> msg(
+ scoped_ptr<SpdySerializedFrame> msg(
spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
AddWrite(*msg);
- scoped_ptr<SpdyFrame> echo(
+ scoped_ptr<SpdySerializedFrame> echo(
spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
AddRead(*echo);
@@ -233,24 +230,26 @@ class StreamDelegateWithTrailers : public test::StreamDelegateWithBody {
TEST_P(SpdyStreamTest, Trailers) {
GURL url(kStreamUrl);
- scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
AddWrite(*req);
- scoped_ptr<SpdyFrame> msg(
+ scoped_ptr<SpdySerializedFrame> msg(
spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, true));
AddWrite(*msg);
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
AddRead(*resp);
- scoped_ptr<SpdyFrame> echo(
+ scoped_ptr<SpdySerializedFrame> echo(
spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
AddRead(*echo);
- const char* const kExtraHeaders[] = {"foo", "bar"};
- scoped_ptr<SpdyFrame> trailers(
- spdy_util_.ConstructSpdyHeaderFrame(1, kExtraHeaders, 1));
+ SpdyHeaderBlock late_headers;
+ late_headers["foo"] = "bar";
+ scoped_ptr<SpdySerializedFrame> trailers(
+ spdy_util_.ConstructSpdyResponseHeaders(1, late_headers, false));
AddRead(*trailers);
AddReadEOF();
@@ -347,20 +346,19 @@ TEST_P(SpdyStreamTest, PushedStream) {
TEST_P(SpdyStreamTest, StreamError) {
GURL url(kStreamUrl);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
+ kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
AddWrite(*req);
- scoped_ptr<SpdyFrame> resp(
+ scoped_ptr<SpdySerializedFrame> resp(
spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
AddRead(*resp);
- scoped_ptr<SpdyFrame> msg(
+ scoped_ptr<SpdySerializedFrame> msg(
spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
AddWrite(*msg);
- scoped_ptr<SpdyFrame> echo(
+ scoped_ptr<SpdySerializedFrame> echo(
spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
AddRead(*echo);
@@ -424,24 +422,22 @@ TEST_P(SpdyStreamTest, StreamError) {
TEST_P(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
GURL url(kStreamUrl);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
+ kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
AddWrite(*req);
std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
- scoped_ptr<SpdyFrame> chunk(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, chunk_data.data(), chunk_data.length(), false));
+ scoped_ptr<SpdySerializedFrame> chunk(spdy_util_.ConstructSpdyBodyFrame(
+ 1, chunk_data.data(), chunk_data.length(), false));
AddWrite(*chunk);
AddWrite(*chunk);
- scoped_ptr<SpdyFrame> last_chunk(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, chunk_data.data(), chunk_data.length(), true));
+ scoped_ptr<SpdySerializedFrame> last_chunk(spdy_util_.ConstructSpdyBodyFrame(
+ 1, chunk_data.data(), chunk_data.length(), true));
AddWrite(*last_chunk);
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
AddRead(*resp);
AddReadEOF();
@@ -487,18 +483,17 @@ TEST_P(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
TEST_P(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
GURL url(kStreamUrl);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
+ kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
AddWrite(*req);
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
AddRead(*resp);
std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
- scoped_ptr<SpdyFrame> chunk(
- spdy_util_.ConstructSpdyBodyFrame(
- 1, chunk_data.data(), chunk_data.length(), false));
+ scoped_ptr<SpdySerializedFrame> chunk(spdy_util_.ConstructSpdyBodyFrame(
+ 1, chunk_data.data(), chunk_data.length(), false));
AddWrite(*chunk);
AddWrite(*chunk);
AddWrite(*chunk);
@@ -545,16 +540,16 @@ TEST_P(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
TEST_P(SpdyStreamTest, UpperCaseHeaders) {
GURL url(kStreamUrl);
- scoped_ptr<SpdyFrame> syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
AddWrite(*syn);
const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
- scoped_ptr<SpdyFrame>
- reply(spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
+ scoped_ptr<SpdySerializedFrame> reply(
+ spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
AddRead(*reply);
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
AddWrite(*rst);
@@ -594,20 +589,20 @@ TEST_P(SpdyStreamTest, UpperCaseHeaders) {
TEST_P(SpdyStreamTest, UpperCaseHeadersOnPush) {
GURL url(kStreamUrl);
- scoped_ptr<SpdyFrame> syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
AddWrite(*syn);
- scoped_ptr<SpdyFrame>
- reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
AddRead(*reply);
const char* const extra_headers[] = {"X-UpperCase", "yes"};
- scoped_ptr<SpdyFrame>
- push(spdy_util_.ConstructSpdyPush(extra_headers, 1, 2, 1, kStreamUrl));
+ scoped_ptr<SpdySerializedFrame> push(
+ spdy_util_.ConstructSpdyPush(extra_headers, 1, 2, 1, kStreamUrl));
AddRead(*push);
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
AddWrite(*rst);
@@ -657,30 +652,29 @@ TEST_P(SpdyStreamTest, UpperCaseHeadersOnPush) {
TEST_P(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
GURL url(kStreamUrl);
- scoped_ptr<SpdyFrame> syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
AddWrite(*syn);
- scoped_ptr<SpdyFrame>
- reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
AddRead(*reply);
- scoped_ptr<SpdyFrame>
- push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
+ scoped_ptr<SpdySerializedFrame> push(
+ spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
AddRead(*push);
AddReadPause();
- scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
- (*late_headers)["X-UpperCase"] = "yes";
- scoped_ptr<SpdyFrame> headers_frame(spdy_util_.ConstructSpdyControlFrame(
- std::move(late_headers), false, 2, LOWEST, HEADERS, CONTROL_FLAG_NONE,
- 0));
+ SpdyHeaderBlock late_headers;
+ late_headers["X-UpperCase"] = "yes";
+ scoped_ptr<SpdySerializedFrame> headers_frame(
+ spdy_util_.ConstructSpdyReply(2, late_headers));
AddRead(*headers_frame);
AddWritePause();
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
AddWrite(*rst);
@@ -734,30 +728,29 @@ TEST_P(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
TEST_P(SpdyStreamTest, DuplicateHeaders) {
GURL url(kStreamUrl);
- scoped_ptr<SpdyFrame> syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
AddWrite(*syn);
- scoped_ptr<SpdyFrame>
- reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
AddRead(*reply);
- scoped_ptr<SpdyFrame>
- push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
+ scoped_ptr<SpdySerializedFrame> push(
+ spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
AddRead(*push);
AddReadPause();
- scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
- (*late_headers)[spdy_util_.GetStatusKey()] = "500 Server Error";
- scoped_ptr<SpdyFrame> headers_frame(spdy_util_.ConstructSpdyControlFrame(
- std::move(late_headers), false, 2, LOWEST, HEADERS, CONTROL_FLAG_NONE,
- 0));
+ SpdyHeaderBlock late_headers;
+ late_headers[spdy_util_.GetStatusKey()] = "500 Server Error";
+ scoped_ptr<SpdySerializedFrame> headers_frame(
+ spdy_util_.ConstructSpdyReply(2, late_headers));
AddRead(*headers_frame);
AddReadPause();
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
AddWrite(*rst);
@@ -810,16 +803,15 @@ TEST_P(SpdyStreamTest, DuplicateHeaders) {
// to overflow an int32_t. The SpdyStream should handle that case
// gracefully.
TEST_P(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
+ kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
AddWrite(*req);
AddReadPause();
// Triggered by the overflowing call to IncreaseSendWindowSize
// below.
- scoped_ptr<SpdyFrame> rst(
+ scoped_ptr<SpdySerializedFrame> rst(
spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
AddWrite(*rst);
@@ -903,16 +895,16 @@ void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest(
const UnstallFunction& unstall_function) {
GURL url(kStreamUrl);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
+ kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
AddWrite(*req);
- scoped_ptr<SpdyFrame> body(
+ scoped_ptr<SpdySerializedFrame> body(
spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, true));
AddWrite(*body);
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
AddRead(*resp);
AddReadEOF();
@@ -979,21 +971,21 @@ void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest(
const UnstallFunction& unstall_function) {
GURL url(kStreamUrl);
- scoped_ptr<SpdyFrame> req(
- spdy_util_.ConstructSpdyPost(
- kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
+ scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
+ kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
AddWrite(*req);
AddReadPause();
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
AddRead(*resp);
- scoped_ptr<SpdyFrame> msg(
+ scoped_ptr<SpdySerializedFrame> msg(
spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
AddWrite(*msg);
- scoped_ptr<SpdyFrame> echo(
+ scoped_ptr<SpdySerializedFrame> echo(
spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
AddRead(*echo);
@@ -1063,19 +1055,19 @@ TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
TEST_P(SpdyStreamTest, ReceivedBytes) {
GURL url(kStreamUrl);
- scoped_ptr<SpdyFrame> syn(
- spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ scoped_ptr<SpdySerializedFrame> syn(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
AddWrite(*syn);
AddReadPause();
- scoped_ptr<SpdyFrame>
- reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<SpdySerializedFrame> reply(
+ spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
AddRead(*reply);
AddReadPause();
- scoped_ptr<SpdyFrame> msg(
+ scoped_ptr<SpdySerializedFrame> msg(
spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
AddRead(*msg);
@@ -1110,8 +1102,8 @@ TEST_P(SpdyStreamTest, ReceivedBytes) {
EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
int64_t reply_frame_len = reply->size();
- int64_t data_header_len =
- spdy_util_.CreateFramer(false)->GetDataFrameMinimumSize();
+ int64_t data_header_len = SpdyConstants::GetDataFrameMinimumSize(
+ NextProtoToSpdyMajorVersion(GetProtocol()));
int64_t data_frame_len = data_header_len + kPostBodyLength;
int64_t response_len = reply_frame_len + data_frame_len;
diff --git a/chromium/net/spdy/spdy_test_util_common.cc b/chromium/net/spdy/spdy_test_util_common.cc
index 6a287948021..53e73345364 100644
--- a/chromium/net/spdy/spdy_test_util_common.cc
+++ b/chromium/net/spdy/spdy_test_util_common.cc
@@ -13,6 +13,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
+#include "net/base/host_port_pair.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_session.h"
@@ -54,19 +55,10 @@ void ParseUrl(base::StringPiece url, std::string* scheme, std::string* host,
} // namespace
-NextProtoVector SpdyNextProtos() {
- NextProtoVector next_protos;
- next_protos.push_back(kProtoHTTP11);
- next_protos.push_back(kProtoSPDY31);
- next_protos.push_back(kProtoHTTP2);
- next_protos.push_back(kProtoQUIC1SPDY3);
- return next_protos;
-}
-
// Chop a frame into an array of MockWrites.
// |frame| is the frame to chop.
// |num_chunks| is the number of chunks to create.
-MockWrite* ChopWriteFrame(const SpdyFrame& frame, int num_chunks) {
+MockWrite* ChopWriteFrame(const SpdySerializedFrame& frame, int num_chunks) {
MockWrite* chunks = new MockWrite[num_chunks];
int chunk_size = frame.size() / num_chunks;
for (int index = 0; index < num_chunks; index++) {
@@ -126,39 +118,41 @@ void AppendToHeaderBlock(const char* const extra_headers[],
}
}
-// Create a MockWrite from the given SpdyFrame.
-MockWrite CreateMockWrite(const SpdyFrame& req) {
+// Create a MockWrite from the given SpdySerializedFrame.
+MockWrite CreateMockWrite(const SpdySerializedFrame& req) {
return MockWrite(ASYNC, req.data(), req.size());
}
-// Create a MockWrite from the given SpdyFrame and sequence number.
-MockWrite CreateMockWrite(const SpdyFrame& req, int seq) {
+// Create a MockWrite from the given SpdySerializedFrame and sequence number.
+MockWrite CreateMockWrite(const SpdySerializedFrame& req, int seq) {
return CreateMockWrite(req, seq, ASYNC);
}
-// Create a MockWrite from the given SpdyFrame and sequence number.
-MockWrite CreateMockWrite(const SpdyFrame& req, int seq, IoMode mode) {
+// Create a MockWrite from the given SpdySerializedFrame and sequence number.
+MockWrite CreateMockWrite(const SpdySerializedFrame& req,
+ int seq,
+ IoMode mode) {
return MockWrite(mode, req.data(), req.size(), seq);
}
-// Create a MockRead from the given SpdyFrame.
-MockRead CreateMockRead(const SpdyFrame& resp) {
+// Create a MockRead from the given SpdySerializedFrame.
+MockRead CreateMockRead(const SpdySerializedFrame& resp) {
return MockRead(ASYNC, resp.data(), resp.size());
}
-// Create a MockRead from the given SpdyFrame and sequence number.
-MockRead CreateMockRead(const SpdyFrame& resp, int seq) {
+// Create a MockRead from the given SpdySerializedFrame and sequence number.
+MockRead CreateMockRead(const SpdySerializedFrame& resp, int seq) {
return CreateMockRead(resp, seq, ASYNC);
}
-// Create a MockRead from the given SpdyFrame and sequence number.
-MockRead CreateMockRead(const SpdyFrame& resp, int seq, IoMode mode) {
+// Create a MockRead from the given SpdySerializedFrame and sequence number.
+MockRead CreateMockRead(const SpdySerializedFrame& resp, int seq, IoMode mode) {
return MockRead(mode, resp.data(), resp.size(), seq);
}
// Combines the given SpdyFrames into the given char array and returns
// the total length.
-int CombineFrames(const SpdyFrame** frames,
+int CombineFrames(const SpdySerializedFrame** frames,
int num_frames,
char* buf,
int buf_len) {
@@ -248,9 +242,9 @@ class PriorityGetter : public BufferedSpdyFramerVisitorInterface {
} // namespace
bool GetSpdyPriority(SpdyMajorVersion version,
- const SpdyFrame& frame,
+ const SpdySerializedFrame& frame,
SpdyPriority* priority) {
- BufferedSpdyFramer framer(version, false);
+ BufferedSpdyFramer framer(version);
PriorityGetter priority_getter;
framer.set_visitor(&priority_getter);
size_t frame_size = frame.size();
@@ -300,7 +294,8 @@ bool MockECSignatureCreator::Sign(const uint8_t* data,
int data_len,
std::vector<uint8_t>* signature) {
std::vector<uint8_t> private_key_value;
- key_->ExportValue(&private_key_value);
+ if (!key_->ExportValueForTesting(&private_key_value))
+ return false;
std::string head = "fakesignature";
std::string tail = "/fakesignature";
@@ -337,6 +332,7 @@ crypto::ECSignatureCreator* MockECSignatureCreatorFactory::Create(
SpdySessionDependencies::SpdySessionDependencies(NextProto protocol)
: host_resolver(new MockCachingHostResolver),
cert_verifier(new MockCertVerifier),
+ channel_id_service(nullptr),
transport_security_state(new TransportSecurityState),
proxy_service(ProxyService::CreateDirect()),
ssl_config_service(new SSLConfigServiceDefaults),
@@ -344,17 +340,20 @@ SpdySessionDependencies::SpdySessionDependencies(NextProto protocol)
http_auth_handler_factory(
HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
enable_ip_pooling(true),
- enable_compression(false),
enable_ping(false),
enable_user_alternate_protocol_ports(false),
- enable_npn(true),
+ enable_npn(false),
+ enable_priority_dependencies(true),
+ enable_spdy31(true),
+ enable_quic(false),
protocol(protocol),
session_max_recv_window_size(
SpdySession::GetDefaultInitialWindowSize(protocol)),
stream_max_recv_window_size(
SpdySession::GetDefaultInitialWindowSize(protocol)),
time_func(&base::TimeTicks::Now),
- use_alternative_services(false),
+ parse_alternative_services(false),
+ enable_alternative_service_with_different_host(false),
net_log(NULL) {
DCHECK(next_proto_is_spdy(protocol)) << "Invalid protocol: " << protocol;
@@ -372,6 +371,7 @@ SpdySessionDependencies::SpdySessionDependencies(
scoped_ptr<ProxyService> proxy_service)
: host_resolver(new MockHostResolver),
cert_verifier(new MockCertVerifier),
+ channel_id_service(nullptr),
transport_security_state(new TransportSecurityState),
proxy_service(std::move(proxy_service)),
ssl_config_service(new SSLConfigServiceDefaults),
@@ -379,17 +379,20 @@ SpdySessionDependencies::SpdySessionDependencies(
http_auth_handler_factory(
HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
enable_ip_pooling(true),
- enable_compression(false),
enable_ping(false),
enable_user_alternate_protocol_ports(false),
- enable_npn(true),
+ enable_npn(false),
+ enable_priority_dependencies(true),
+ enable_spdy31(true),
+ enable_quic(false),
protocol(protocol),
session_max_recv_window_size(
SpdySession::GetDefaultInitialWindowSize(protocol)),
stream_max_recv_window_size(
SpdySession::GetDefaultInitialWindowSize(protocol)),
time_func(&base::TimeTicks::Now),
- use_alternative_services(true),
+ parse_alternative_services(false),
+ enable_alternative_service_with_different_host(false),
net_log(NULL) {
DCHECK(next_proto_is_spdy(protocol)) << "Invalid protocol: " << protocol;
}
@@ -416,6 +419,7 @@ HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams(
HttpNetworkSession::Params params;
params.host_resolver = session_deps->host_resolver.get();
params.cert_verifier = session_deps->cert_verifier.get();
+ params.channel_id_service = session_deps->channel_id_service.get();
params.transport_security_state =
session_deps->transport_security_state.get();
params.proxy_service = session_deps->proxy_service.get();
@@ -424,20 +428,24 @@ HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams(
session_deps->http_auth_handler_factory.get();
params.http_server_properties =
session_deps->http_server_properties.GetWeakPtr();
- params.enable_spdy_compression = session_deps->enable_compression;
params.enable_spdy_ping_based_connection_checking = session_deps->enable_ping;
params.enable_user_alternate_protocol_ports =
session_deps->enable_user_alternate_protocol_ports;
params.enable_npn = session_deps->enable_npn;
+ params.enable_priority_dependencies =
+ session_deps->enable_priority_dependencies;
+ params.enable_spdy31 = session_deps->enable_spdy31;
+ params.enable_quic = session_deps->enable_quic;
params.spdy_default_protocol = session_deps->protocol;
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.time_func = session_deps->time_func;
- params.next_protos = session_deps->next_protos;
- params.trusted_spdy_proxy = session_deps->trusted_spdy_proxy;
- params.use_alternative_services = session_deps->use_alternative_services;
+ params.proxy_delegate = session_deps->proxy_delegate.get();
+ params.parse_alternative_services = session_deps->parse_alternative_services;
+ params.enable_alternative_service_with_different_host =
+ session_deps->enable_alternative_service_with_different_host;
params.net_log = session_deps->net_log;
return params;
}
@@ -465,8 +473,6 @@ SpdyURLRequestContext::SpdyURLRequestContext(NextProto protocol)
params.proxy_service = proxy_service();
params.ssl_config_service = ssl_config_service();
params.http_auth_handler_factory = http_auth_handler_factory();
- params.network_delegate = network_delegate();
- params.enable_spdy_compression = false;
params.enable_spdy_ping_based_connection_checking = false;
params.spdy_default_protocol = protocol;
params.http_server_properties = http_server_properties();
@@ -485,7 +491,7 @@ SpdyURLRequestContext::~SpdyURLRequestContext() {
}
bool HasSpdySession(SpdySessionPool* pool, const SpdySessionKey& key) {
- return pool->FindAvailableSession(key, BoundNetLog()) != NULL;
+ return pool->FindAvailableSession(key, GURL(), BoundNetLog()) != NULL;
}
namespace {
@@ -500,7 +506,7 @@ base::WeakPtr<SpdySession> CreateSpdySessionHelper(
scoped_refptr<TransportSocketParams> transport_params(
new TransportSocketParams(
- key.host_port_pair(), false, false, OnHostResolutionCallback(),
+ key.host_port_pair(), false, OnHostResolutionCallback(),
TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT));
scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
@@ -518,17 +524,14 @@ base::WeakPtr<SpdySession> CreateSpdySessionHelper(
key.privacy_mode(),
0,
false));
- rv = connection->Init(key.host_port_pair().ToString(),
- ssl_params,
- MEDIUM,
- callback.callback(),
- http_session->GetSSLSocketPool(
- HttpNetworkSession::NORMAL_SOCKET_POOL),
- net_log);
+ rv = connection->Init(
+ key.host_port_pair().ToString(), ssl_params, MEDIUM,
+ ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+ http_session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL),
+ net_log);
} else {
- rv = connection->Init(key.host_port_pair().ToString(),
- transport_params,
- MEDIUM,
+ rv = connection->Init(key.host_port_pair().ToString(), transport_params,
+ MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
callback.callback(),
http_session->GetTransportSocketPool(
HttpNetworkSession::NORMAL_SOCKET_POOL),
@@ -614,11 +617,6 @@ class FakeSpdySessionClientSocket : public MockClientSocket {
return false;
}
- bool UsingTCPFastOpen() const override {
- ADD_FAILURE();
- return false;
- }
-
bool WasNpnNegotiated() const override {
ADD_FAILURE();
return false;
@@ -697,6 +695,9 @@ void SpdySessionPoolPeer::SetStreamInitialRecvWindowSize(size_t window) {
SpdyTestUtil::SpdyTestUtil(NextProto protocol, bool dependency_priorities)
: protocol_(protocol),
spdy_version_(NextProtoToSpdyMajorVersion(protocol)),
+ headerless_spdy_framer_(spdy_version_),
+ request_spdy_framer_(spdy_version_),
+ response_spdy_framer_(spdy_version_),
default_url_(GURL(kDefaultURL)),
dependency_priorities_(dependency_priorities) {
DCHECK(next_proto_is_spdy(protocol)) << "Invalid protocol: " << protocol;
@@ -742,11 +743,11 @@ scoped_ptr<SpdyHeaderBlock> SpdyTestUtil::ConstructPutHeaderBlock(
return ConstructHeaderBlock("PUT", url, &content_length);
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyFrame(
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyFrame(
const SpdyHeaderInfo& header_info,
scoped_ptr<SpdyHeaderBlock> headers) const {
- BufferedSpdyFramer framer(spdy_version_, header_info.compressed);
- SpdyFrame* frame = NULL;
+ BufferedSpdyFramer framer(spdy_version_);
+ SpdySerializedFrame* frame = NULL;
switch (header_info.kind) {
case DATA:
frame = framer.CreateDataFrame(header_info.id, header_info.data,
@@ -780,11 +781,12 @@ SpdyFrame* SpdyTestUtil::ConstructSpdyFrame(
return frame;
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyFrame(const SpdyHeaderInfo& header_info,
- const char* const extra_headers[],
- int extra_header_count,
- const char* const tail_headers[],
- int tail_header_count) const {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyFrame(
+ const SpdyHeaderInfo& header_info,
+ const char* const extra_headers[],
+ int extra_header_count,
+ const char* const tail_headers[],
+ int tail_header_count) const {
scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock());
AppendToHeaderBlock(extra_headers, extra_header_count, headers.get());
if (tail_headers && tail_header_count)
@@ -792,51 +794,6 @@ SpdyFrame* SpdyTestUtil::ConstructSpdyFrame(const SpdyHeaderInfo& header_info,
return ConstructSpdyFrame(header_info, std::move(headers));
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyControlFrame(
- scoped_ptr<SpdyHeaderBlock> headers,
- bool compressed,
- SpdyStreamId stream_id,
- RequestPriority request_priority,
- SpdyFrameType type,
- SpdyControlFlags flags,
- SpdyStreamId associated_stream_id) const {
- EXPECT_GE(type, DATA);
- EXPECT_LE(type, PRIORITY);
- const SpdyHeaderInfo header_info = {
- type,
- stream_id,
- associated_stream_id,
- ConvertRequestPriorityToSpdyPriority(request_priority, spdy_version_),
- flags,
- compressed,
- RST_STREAM_INVALID, // status
- NULL, // data
- 0, // length
- DATA_FLAG_NONE
- };
- return ConstructSpdyFrame(header_info, std::move(headers));
-}
-
-SpdyFrame* SpdyTestUtil::ConstructSpdyControlFrame(
- const char* const extra_headers[],
- int extra_header_count,
- bool compressed,
- SpdyStreamId stream_id,
- RequestPriority request_priority,
- SpdyFrameType type,
- SpdyControlFlags flags,
- const char* const* tail_headers,
- int tail_header_size,
- SpdyStreamId associated_stream_id) const {
- scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock());
- AppendToHeaderBlock(extra_headers, extra_header_count, headers.get());
- if (tail_headers && tail_header_size)
- AppendToHeaderBlock(tail_headers, tail_header_size / 2, headers.get());
- return ConstructSpdyControlFrame(std::move(headers), compressed, stream_id,
- request_priority, type, flags,
- associated_stream_id);
-}
-
std::string SpdyTestUtil::ConstructSpdyReplyString(
const SpdyHeaderBlock& headers) const {
std::string reply_string;
@@ -858,8 +815,8 @@ std::string SpdyTestUtil::ConstructSpdyReplyString(
// TODO(jgraettinger): Eliminate uses of this method in tests (prefer
// SpdySettingsIR).
-SpdyFrame* SpdyTestUtil::ConstructSpdySettings(
- const SettingsMap& settings) const {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdySettings(
+ const SettingsMap& settings) {
SpdySettingsIR settings_ir;
for (SettingsMap::const_iterator it = settings.begin();
it != settings.end();
@@ -870,85 +827,90 @@ SpdyFrame* SpdyTestUtil::ConstructSpdySettings(
(it->second.first & SETTINGS_FLAG_PERSISTED) != 0,
it->second.second);
}
- return CreateFramer(false)->SerializeFrame(settings_ir);
+ return new SpdySerializedFrame(
+ headerless_spdy_framer_.SerializeFrame(settings_ir));
}
-SpdyFrame* SpdyTestUtil::ConstructSpdySettingsAck() const {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdySettingsAck() {
char kEmptyWrite[] = "";
if (spdy_version() > SPDY3) {
SpdySettingsIR settings_ir;
settings_ir.set_is_ack(true);
- return CreateFramer(false)->SerializeFrame(settings_ir);
+ return new SpdySerializedFrame(
+ headerless_spdy_framer_.SerializeFrame(settings_ir));
}
// No settings ACK write occurs. Create an empty placeholder write.
- return new SpdyFrame(kEmptyWrite, 0, false);
+ return new SpdySerializedFrame(kEmptyWrite, 0, false);
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyPing(uint32_t ping_id,
- bool is_ack) const {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyPing(uint32_t ping_id,
+ bool is_ack) {
SpdyPingIR ping_ir(ping_id);
ping_ir.set_is_ack(is_ack);
- return CreateFramer(false)->SerializeFrame(ping_ir);
+ return new SpdySerializedFrame(
+ headerless_spdy_framer_.SerializeFrame(ping_ir));
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyGoAway() const {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyGoAway() {
return ConstructSpdyGoAway(0);
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyGoAway(
- SpdyStreamId last_good_stream_id) const {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyGoAway(
+ SpdyStreamId last_good_stream_id) {
SpdyGoAwayIR go_ir(last_good_stream_id, GOAWAY_OK, "go away");
- return CreateFramer(false)->SerializeFrame(go_ir);
+ return new SpdySerializedFrame(headerless_spdy_framer_.SerializeFrame(go_ir));
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyGoAway(SpdyStreamId last_good_stream_id,
- SpdyGoAwayStatus status,
- const std::string& desc) const {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyGoAway(
+ SpdyStreamId last_good_stream_id,
+ SpdyGoAwayStatus status,
+ const std::string& desc) {
SpdyGoAwayIR go_ir(last_good_stream_id, status, desc);
- return CreateFramer(false)->SerializeFrame(go_ir);
+ return new SpdySerializedFrame(headerless_spdy_framer_.SerializeFrame(go_ir));
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyWindowUpdate(
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyWindowUpdate(
const SpdyStreamId stream_id,
- uint32_t delta_window_size) const {
+ uint32_t delta_window_size) {
SpdyWindowUpdateIR update_ir(stream_id, delta_window_size);
- return CreateFramer(false)->SerializeFrame(update_ir);
+ return new SpdySerializedFrame(
+ headerless_spdy_framer_.SerializeFrame(update_ir));
}
// TODO(jgraettinger): Eliminate uses of this method in tests (prefer
// SpdyRstStreamIR).
-SpdyFrame* SpdyTestUtil::ConstructSpdyRstStream(
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyRstStream(
SpdyStreamId stream_id,
- SpdyRstStreamStatus status) const {
+ SpdyRstStreamStatus status) {
SpdyRstStreamIR rst_ir(stream_id, status);
- return CreateFramer(false)->SerializeRstStream(rst_ir);
+ return new SpdySerializedFrame(
+ headerless_spdy_framer_.SerializeRstStream(rst_ir));
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyGet(const char* const url,
- bool compressed,
- SpdyStreamId stream_id,
- RequestPriority request_priority) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyGet(
+ const char* const url,
+ SpdyStreamId stream_id,
+ RequestPriority request_priority) {
scoped_ptr<SpdyHeaderBlock> block(ConstructGetHeaderBlock(url));
- return ConstructSpdySyn(
- stream_id, *block, request_priority, compressed, true);
+ return ConstructSpdySyn(stream_id, *block, request_priority, true);
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyGet(const char* const extra_headers[],
- int extra_header_count,
- bool compressed,
- int stream_id,
- RequestPriority request_priority,
- bool direct) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyGet(
+ const char* const extra_headers[],
+ int extra_header_count,
+ int stream_id,
+ RequestPriority request_priority,
+ bool direct) {
SpdyHeaderBlock block;
MaybeAddVersionHeader(&block);
block[GetMethodKey()] = "GET";
AddUrlToHeaderBlock(default_url_.spec(), &block);
AppendToHeaderBlock(extra_headers, extra_header_count, &block);
- return ConstructSpdySyn(stream_id, block, request_priority, compressed, true);
+ return ConstructSpdySyn(stream_id, block, request_priority, true);
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyConnect(
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyConnect(
const char* const extra_headers[],
int extra_header_count,
int stream_id,
@@ -966,57 +928,60 @@ SpdyFrame* SpdyTestUtil::ConstructSpdyConnect(
block[GetHostKey()] = host_port_pair.ToString();
}
AppendToHeaderBlock(extra_headers, extra_header_count, &block);
- return ConstructSpdySyn(stream_id, block, priority, false, false);
+ return ConstructSpdySyn(stream_id, block, priority, false);
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyPush(const char* const extra_headers[],
- int extra_header_count,
- int stream_id,
- int associated_stream_id,
- const char* url) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyPush(
+ const char* const extra_headers[],
+ int extra_header_count,
+ int stream_id,
+ int associated_stream_id,
+ const char* url) {
if (spdy_version() < HTTP2) {
SpdySynStreamIR syn_stream(stream_id);
syn_stream.set_associated_to_stream_id(associated_stream_id);
syn_stream.SetHeader("hello", "bye");
- syn_stream.SetHeader(GetStatusKey(), "200 OK");
+ syn_stream.SetHeader(GetStatusKey(), "200");
syn_stream.SetHeader(GetVersionKey(), "HTTP/1.1");
AddUrlToHeaderBlock(url, syn_stream.mutable_header_block());
AppendToHeaderBlock(extra_headers, extra_header_count,
syn_stream.mutable_header_block());
- return CreateFramer(false)->SerializeFrame(syn_stream);
+ return new SpdySerializedFrame(
+ response_spdy_framer_.SerializeFrame(syn_stream));
} else {
SpdyPushPromiseIR push_promise(associated_stream_id, stream_id);
AddUrlToHeaderBlock(url, push_promise.mutable_header_block());
- scoped_ptr<SpdyFrame> push_promise_frame(
- CreateFramer(false)->SerializeFrame(push_promise));
+ SpdySerializedFrame push_promise_frame(
+ response_spdy_framer_.SerializeFrame(push_promise));
SpdyHeadersIR headers(stream_id);
- headers.SetHeader(GetStatusKey(), "200 OK");
+ headers.SetHeader(GetStatusKey(), "200");
headers.SetHeader("hello", "bye");
AppendToHeaderBlock(extra_headers, extra_header_count,
headers.mutable_header_block());
- scoped_ptr<SpdyFrame> headers_frame(
- CreateFramer(false)->SerializeFrame(headers));
+ SpdySerializedFrame headers_frame(
+ response_spdy_framer_.SerializeFrame(headers));
- int joint_data_size = push_promise_frame->size() + headers_frame->size();
+ int joint_data_size = push_promise_frame.size() + headers_frame.size();
scoped_ptr<char[]> data(new char[joint_data_size]);
- const SpdyFrame* frames[2] = {
- push_promise_frame.get(), headers_frame.get(),
+ const SpdySerializedFrame* frames[2] = {
+ &push_promise_frame, &headers_frame,
};
int combined_size =
CombineFrames(frames, arraysize(frames), data.get(), joint_data_size);
DCHECK_EQ(combined_size, joint_data_size);
- return new SpdyFrame(data.release(), joint_data_size, true);
+ return new SpdySerializedFrame(data.release(), joint_data_size, true);
}
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyPush(const char* const extra_headers[],
- int extra_header_count,
- int stream_id,
- int associated_stream_id,
- const char* url,
- const char* status,
- const char* location) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyPush(
+ const char* const extra_headers[],
+ int extra_header_count,
+ int stream_id,
+ int associated_stream_id,
+ const char* url,
+ const char* status,
+ const char* location) {
if (spdy_version() < HTTP2) {
SpdySynStreamIR syn_stream(stream_id);
syn_stream.set_associated_to_stream_id(associated_stream_id);
@@ -1027,12 +992,13 @@ SpdyFrame* SpdyTestUtil::ConstructSpdyPush(const char* const extra_headers[],
AddUrlToHeaderBlock(url, syn_stream.mutable_header_block());
AppendToHeaderBlock(extra_headers, extra_header_count,
syn_stream.mutable_header_block());
- return CreateFramer(false)->SerializeFrame(syn_stream);
+ return new SpdySerializedFrame(
+ response_spdy_framer_.SerializeFrame(syn_stream));
} else {
SpdyPushPromiseIR push_promise(associated_stream_id, stream_id);
AddUrlToHeaderBlock(url, push_promise.mutable_header_block());
- scoped_ptr<SpdyFrame> push_promise_frame(
- CreateFramer(false)->SerializeFrame(push_promise));
+ SpdySerializedFrame push_promise_frame(
+ response_spdy_framer_.SerializeFrame(push_promise));
SpdyHeadersIR headers(stream_id);
headers.SetHeader("hello", "bye");
@@ -1040,22 +1006,22 @@ SpdyFrame* SpdyTestUtil::ConstructSpdyPush(const char* const extra_headers[],
headers.SetHeader("location", location);
AppendToHeaderBlock(extra_headers, extra_header_count,
headers.mutable_header_block());
- scoped_ptr<SpdyFrame> headers_frame(
- CreateFramer(false)->SerializeFrame(headers));
+ SpdySerializedFrame headers_frame(
+ response_spdy_framer_.SerializeFrame(headers));
- int joint_data_size = push_promise_frame->size() + headers_frame->size();
+ int joint_data_size = push_promise_frame.size() + headers_frame.size();
scoped_ptr<char[]> data(new char[joint_data_size]);
- const SpdyFrame* frames[2] = {
- push_promise_frame.get(), headers_frame.get(),
+ const SpdySerializedFrame* frames[2] = {
+ &push_promise_frame, &headers_frame,
};
int combined_size =
CombineFrames(frames, arraysize(frames), data.get(), joint_data_size);
DCHECK_EQ(combined_size, joint_data_size);
- return new SpdyFrame(data.release(), joint_data_size, true);
+ return new SpdySerializedFrame(data.release(), joint_data_size, true);
}
}
-SpdyFrame* SpdyTestUtil::ConstructInitialSpdyPushFrame(
+SpdySerializedFrame* SpdyTestUtil::ConstructInitialSpdyPushFrame(
scoped_ptr<SpdyHeaderBlock> headers,
int stream_id,
int associated_stream_id) {
@@ -1064,53 +1030,54 @@ SpdyFrame* SpdyTestUtil::ConstructInitialSpdyPushFrame(
syn_stream.set_associated_to_stream_id(associated_stream_id);
SetPriority(LOWEST, &syn_stream);
syn_stream.set_header_block(*headers);
- return CreateFramer(false)->SerializeFrame(syn_stream);
+ return new SpdySerializedFrame(
+ response_spdy_framer_.SerializeFrame(syn_stream));
} else {
SpdyPushPromiseIR push_promise(associated_stream_id, stream_id);
push_promise.set_header_block(*headers);
- return CreateFramer(false)->SerializeFrame(push_promise);
+ return new SpdySerializedFrame(
+ response_spdy_framer_.SerializeFrame(push_promise));
}
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyPushHeaders(
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyPushHeaders(
int stream_id,
const char* const extra_headers[],
int extra_header_count) {
SpdyHeadersIR headers(stream_id);
- headers.SetHeader(GetStatusKey(), "200 OK");
+ headers.SetHeader(GetStatusKey(), "200");
MaybeAddVersionHeader(&headers);
AppendToHeaderBlock(extra_headers, extra_header_count,
headers.mutable_header_block());
- return CreateFramer(false)->SerializeFrame(headers);
+ return new SpdySerializedFrame(response_spdy_framer_.SerializeFrame(headers));
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyHeaderFrame(int stream_id,
- const char* const headers[],
- int header_count) {
- return ConstructSpdyHeaderFrame(stream_id, headers, header_count, false);
-}
-
-SpdyFrame* SpdyTestUtil::ConstructSpdyHeaderFrame(int stream_id,
- const char* const headers[],
- int header_count,
- bool fin) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyResponseHeaders(
+ int stream_id,
+ const SpdyHeaderBlock& headers,
+ bool fin) {
SpdyHeadersIR spdy_headers(stream_id);
+ spdy_headers.set_header_block(headers);
spdy_headers.set_fin(fin);
- AppendToHeaderBlock(headers, header_count,
- spdy_headers.mutable_header_block());
- return CreateFramer(false)->SerializeFrame(spdy_headers);
+ return new SpdySerializedFrame(
+ response_spdy_framer_.SerializeFrame(spdy_headers));
}
-SpdyFrame* SpdyTestUtil::ConstructSpdySyn(int stream_id,
- const SpdyHeaderBlock& block,
- RequestPriority priority,
- bool compressed,
- bool fin) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdySyn(
+ int stream_id,
+ const SpdyHeaderBlock& block,
+ RequestPriority priority,
+ bool fin) {
// Get the stream id of the next highest priority request
// (most recent request of the same priority, or last request of
// an earlier priority).
+ // Note that this is a duplicate of the logic in Http2PriorityDependencies
+ // (slightly transformed as this is based on RequestPriority and that logic
+ // on SpdyPriority, but only slightly transformed) and hence tests using
+ // this function do not effectively test that logic.
+ // That logic is tested by the Http2PriorityDependencies unit tests.
int parent_stream_id = 0;
- for (int q = priority; q >= IDLE; --q) {
+ for (int q = priority; q <= HIGHEST; ++q) {
if (!priority_to_stream_id_list_[q].empty()) {
parent_stream_id = priority_to_stream_id_list_[q].back();
break;
@@ -1125,7 +1092,8 @@ SpdyFrame* SpdyTestUtil::ConstructSpdySyn(int stream_id,
syn_stream.set_priority(
ConvertRequestPriorityToSpdyPriority(priority, spdy_version()));
syn_stream.set_fin(fin);
- return CreateFramer(compressed)->SerializeFrame(syn_stream);
+ return new SpdySerializedFrame(
+ request_spdy_framer_.SerializeFrame(syn_stream));
} else {
SpdyHeadersIR headers(stream_id);
headers.set_header_block(block);
@@ -1137,24 +1105,27 @@ SpdyFrame* SpdyTestUtil::ConstructSpdySyn(int stream_id,
headers.set_exclusive(true);
}
headers.set_fin(fin);
- return CreateFramer(compressed)->SerializeFrame(headers);
+ return new SpdySerializedFrame(
+ request_spdy_framer_.SerializeFrame(headers));
}
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyReply(int stream_id,
- const SpdyHeaderBlock& headers) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyReply(
+ int stream_id,
+ const SpdyHeaderBlock& headers) {
if (protocol_ < kProtoHTTP2) {
SpdySynReplyIR syn_reply(stream_id);
syn_reply.set_header_block(headers);
- return CreateFramer(false)->SerializeFrame(syn_reply);
+ return new SpdySerializedFrame(
+ response_spdy_framer_.SerializeFrame(syn_reply));
} else {
SpdyHeadersIR reply(stream_id);
reply.set_header_block(headers);
- return CreateFramer(false)->SerializeFrame(reply);
+ return new SpdySerializedFrame(response_spdy_framer_.SerializeFrame(reply));
}
}
-SpdyFrame* SpdyTestUtil::ConstructSpdySynReplyError(
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdySynReplyError(
const char* const status,
const char* const* const extra_headers,
int extra_header_count,
@@ -1168,7 +1139,8 @@ SpdyFrame* SpdyTestUtil::ConstructSpdySynReplyError(
return ConstructSpdyReply(stream_id, block);
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyGetSynReplyRedirect(int stream_id) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyGetSynReplyRedirect(
+ int stream_id) {
static const char* const kExtraHeaders[] = {
"location", "http://www.foo.com/index.php",
};
@@ -1176,11 +1148,11 @@ SpdyFrame* SpdyTestUtil::ConstructSpdyGetSynReplyRedirect(int stream_id) {
arraysize(kExtraHeaders)/2, stream_id);
}
-SpdyFrame* SpdyTestUtil::ConstructSpdySynReplyError(int stream_id) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdySynReplyError(int stream_id) {
return ConstructSpdySynReplyError("500 Internal Server Error", NULL, 0, 1);
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyGetSynReply(
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyGetSynReply(
const char* const extra_headers[],
int extra_header_count,
int stream_id) {
@@ -1193,19 +1165,20 @@ SpdyFrame* SpdyTestUtil::ConstructSpdyGetSynReply(
return ConstructSpdyReply(stream_id, block);
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyPost(const char* url,
- SpdyStreamId stream_id,
- int64_t content_length,
- RequestPriority priority,
- const char* const extra_headers[],
- int extra_header_count) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyPost(
+ const char* url,
+ SpdyStreamId stream_id,
+ int64_t content_length,
+ RequestPriority priority,
+ const char* const extra_headers[],
+ int extra_header_count) {
scoped_ptr<SpdyHeaderBlock> block(
ConstructPostHeaderBlock(url, content_length));
AppendToHeaderBlock(extra_headers, extra_header_count, block.get());
- return ConstructSpdySyn(stream_id, *block, priority, false, false);
+ return ConstructSpdySyn(stream_id, *block, priority, false);
}
-SpdyFrame* SpdyTestUtil::ConstructChunkedSpdyPost(
+SpdySerializedFrame* SpdyTestUtil::ConstructChunkedSpdyPost(
const char* const extra_headers[],
int extra_header_count) {
SpdyHeaderBlock block;
@@ -1213,48 +1186,49 @@ SpdyFrame* SpdyTestUtil::ConstructChunkedSpdyPost(
block[GetMethodKey()] = "POST";
AddUrlToHeaderBlock(default_url_.spec(), &block);
AppendToHeaderBlock(extra_headers, extra_header_count, &block);
- return ConstructSpdySyn(1, block, LOWEST, false, false);
+ return ConstructSpdySyn(1, block, LOWEST, false);
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyPostSynReply(
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyPostSynReply(
const char* const extra_headers[],
int extra_header_count) {
// TODO(jgraettinger): Remove this method.
return ConstructSpdyGetSynReply(extra_headers, extra_header_count, 1);
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyBodyFrame(int stream_id, bool fin) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyBodyFrame(int stream_id,
+ bool fin) {
SpdyFramer framer(spdy_version_);
SpdyDataIR data_ir(stream_id,
base::StringPiece(kUploadData, kUploadDataSize));
data_ir.set_fin(fin);
- return framer.SerializeData(data_ir);
+ return new SpdySerializedFrame(framer.SerializeData(data_ir));
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyBodyFrame(int stream_id,
- const char* data,
- uint32_t len,
- bool fin) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyBodyFrame(int stream_id,
+ const char* data,
+ uint32_t len,
+ bool fin) {
SpdyFramer framer(spdy_version_);
SpdyDataIR data_ir(stream_id, base::StringPiece(data, len));
data_ir.set_fin(fin);
- return framer.SerializeData(data_ir);
+ return new SpdySerializedFrame(framer.SerializeData(data_ir));
}
-SpdyFrame* SpdyTestUtil::ConstructSpdyBodyFrame(int stream_id,
- const char* data,
- uint32_t len,
- bool fin,
- int padding_length) {
+SpdySerializedFrame* SpdyTestUtil::ConstructSpdyBodyFrame(int stream_id,
+ const char* data,
+ uint32_t len,
+ bool fin,
+ int padding_length) {
SpdyFramer framer(spdy_version_);
SpdyDataIR data_ir(stream_id, base::StringPiece(data, len));
data_ir.set_fin(fin);
data_ir.set_padding_len(padding_length);
- return framer.SerializeData(data_ir);
+ return new SpdySerializedFrame(framer.SerializeData(data_ir));
}
-SpdyFrame* SpdyTestUtil::ConstructWrappedSpdyFrame(
- const scoped_ptr<SpdyFrame>& frame,
+SpdySerializedFrame* SpdyTestUtil::ConstructWrappedSpdyFrame(
+ const scoped_ptr<SpdySerializedFrame>& frame,
int stream_id) {
return ConstructSpdyBodyFrame(stream_id, frame->data(),
frame->size(), false);
@@ -1274,12 +1248,6 @@ void SpdyTestUtil::UpdateWithStreamDestruction(int stream_id) {
NOTREACHED();
}
-scoped_ptr<SpdyFramer> SpdyTestUtil::CreateFramer(bool compressed) const {
- scoped_ptr<SpdyFramer> framer(new SpdyFramer(spdy_version_));
- framer->set_enable_compression(compressed);
- return framer;
-}
-
const char* SpdyTestUtil::GetMethodKey() const {
return ":method";
}
diff --git a/chromium/net/spdy/spdy_test_util_common.h b/chromium/net/spdy/spdy_test_util_common.h
index 9ef8df53876..c25fa968878 100644
--- a/chromium/net/spdy/spdy_test_util_common.h
+++ b/chromium/net/spdy/spdy_test_util_common.h
@@ -17,6 +17,7 @@
#include "crypto/ec_private_key.h"
#include "crypto/ec_signature_creator.h"
#include "net/base/completion_callback.h"
+#include "net/base/proxy_delegate.h"
#include "net/base/request_priority.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/cert_verifier.h"
@@ -26,6 +27,7 @@
#include "net/http/http_response_info.h"
#include "net/http/http_server_properties_impl.h"
#include "net/http/transport_security_state.h"
+#include "net/proxy/proxy_server.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/next_proto.h"
#include "net/socket/socket_test_util.h"
@@ -40,6 +42,7 @@ class GURL;
namespace net {
class BoundNetLog;
+class HostPortPair;
class SpdySession;
class SpdySessionKey;
class SpdySessionPool;
@@ -52,14 +55,10 @@ const char kDefaultURL[] = "http://www.example.org/";
const char kUploadData[] = "hello!";
const int kUploadDataSize = arraysize(kUploadData)-1;
-// SpdyNextProtos returns a vector of next protocols for negotiating
-// SPDY.
-NextProtoVector SpdyNextProtos();
-
-// Chop a SpdyFrame into an array of MockWrites.
+// Chop a SpdySerializedFrame into an array of MockWrites.
// |frame| is the frame to chop.
// |num_chunks| is the number of chunks to create.
-MockWrite* ChopWriteFrame(const SpdyFrame& frame, int num_chunks);
+MockWrite* ChopWriteFrame(const SpdySerializedFrame& frame, int num_chunks);
// Adds headers and values to a map.
// |extra_headers| is an array of { name, value } pairs, arranged as strings
@@ -70,25 +69,26 @@ void AppendToHeaderBlock(const char* const extra_headers[],
int extra_header_count,
SpdyHeaderBlock* headers);
-// Create an async MockWrite from the given SpdyFrame.
-MockWrite CreateMockWrite(const SpdyFrame& req);
+// Create an async MockWrite from the given SpdySerializedFrame.
+MockWrite CreateMockWrite(const SpdySerializedFrame& req);
-// Create an async MockWrite from the given SpdyFrame and sequence number.
-MockWrite CreateMockWrite(const SpdyFrame& req, int seq);
+// Create an async MockWrite from the given SpdySerializedFrame and sequence
+// number.
+MockWrite CreateMockWrite(const SpdySerializedFrame& req, int seq);
-MockWrite CreateMockWrite(const SpdyFrame& req, int seq, IoMode mode);
+MockWrite CreateMockWrite(const SpdySerializedFrame& req, int seq, IoMode mode);
-// Create a MockRead from the given SpdyFrame.
-MockRead CreateMockRead(const SpdyFrame& resp);
+// Create a MockRead from the given SpdySerializedFrame.
+MockRead CreateMockRead(const SpdySerializedFrame& resp);
-// Create a MockRead from the given SpdyFrame and sequence number.
-MockRead CreateMockRead(const SpdyFrame& resp, int seq);
+// Create a MockRead from the given SpdySerializedFrame and sequence number.
+MockRead CreateMockRead(const SpdySerializedFrame& resp, int seq);
-MockRead CreateMockRead(const SpdyFrame& resp, int seq, IoMode mode);
+MockRead CreateMockRead(const SpdySerializedFrame& resp, int seq, IoMode mode);
-// Combines the given SpdyFrames into the given char array and returns
+// Combines the given SpdySerializedFrame into the given char array and returns
// the total length.
-int CombineFrames(const SpdyFrame** frames,
+int CombineFrames(const SpdySerializedFrame** frames,
int num_frames,
char* buf,
int buf_len);
@@ -96,7 +96,7 @@ int CombineFrames(const SpdyFrame** frames,
// Returns the SpdyPriority embedded in the given frame. Returns true
// and fills in |priority| on success.
bool GetSpdyPriority(SpdyMajorVersion version,
- const SpdyFrame& frame,
+ const SpdySerializedFrame& frame,
SpdyPriority* priority);
// Tries to create a stream in |session| synchronously. Returns NULL
@@ -130,7 +130,6 @@ struct SpdyHeaderInfo {
SpdyStreamId assoc_id;
SpdyPriority priority;
SpdyControlFlags control_flags;
- bool compressed;
SpdyRstStreamStatus status;
const char* data;
uint32_t data_length;
@@ -188,6 +187,7 @@ struct SpdySessionDependencies {
// NOTE: host_resolver must be ordered before http_auth_handler_factory.
scoped_ptr<MockHostResolverBase> host_resolver;
scoped_ptr<CertVerifier> cert_verifier;
+ scoped_ptr<ChannelIDService> channel_id_service;
scoped_ptr<TransportSecurityState> transport_security_state;
scoped_ptr<ProxyService> proxy_service;
scoped_refptr<SSLConfigService> ssl_config_service;
@@ -195,17 +195,19 @@ struct SpdySessionDependencies {
scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
HttpServerPropertiesImpl http_server_properties;
bool enable_ip_pooling;
- bool enable_compression;
bool enable_ping;
bool enable_user_alternate_protocol_ports;
bool enable_npn;
+ bool enable_priority_dependencies;
+ bool enable_spdy31;
+ bool enable_quic;
NextProto protocol;
size_t session_max_recv_window_size;
size_t stream_max_recv_window_size;
SpdySession::TimeFunc time_func;
- NextProtoVector next_protos;
- std::string trusted_spdy_proxy;
- bool use_alternative_services;
+ scoped_ptr<ProxyDelegate> proxy_delegate;
+ bool parse_alternative_services;
+ bool enable_alternative_service_with_different_host;
NetLog* net_log;
};
@@ -306,7 +308,7 @@ class SpdyTestUtil {
// Construct a SPDY frame. If it is a SYN_STREAM or SYN_REPLY frame (as
// specified in header_info.kind), the provided headers are included in the
// frame.
- SpdyFrame* ConstructSpdyFrame(
+ SpdySerializedFrame* ConstructSpdyFrame(
const SpdyHeaderInfo& header_info,
scoped_ptr<SpdyHeaderBlock> headers) const;
@@ -314,39 +316,11 @@ class SpdyTestUtil {
// specified in header_info.kind), the headers provided in extra_headers and
// (if non-NULL) tail_headers are concatenated and included in the frame.
// (extra_headers must always be non-NULL.)
- SpdyFrame* ConstructSpdyFrame(const SpdyHeaderInfo& header_info,
- const char* const extra_headers[],
- int extra_header_count,
- const char* const tail_headers[],
- int tail_header_count) const;
-
- // Construct a generic SpdyControlFrame.
- SpdyFrame* ConstructSpdyControlFrame(
- scoped_ptr<SpdyHeaderBlock> headers,
- bool compressed,
- SpdyStreamId stream_id,
- RequestPriority request_priority,
- SpdyFrameType type,
- SpdyControlFlags flags,
- SpdyStreamId associated_stream_id) const;
-
- // Construct a generic SpdyControlFrame.
- //
- // Warning: extra_header_count is the number of header-value pairs in
- // extra_headers (so half the number of elements), but tail_headers_size is
- // the actual number of elements (both keys and values) in tail_headers.
- // TODO(ttuttle): Fix this inconsistency.
- SpdyFrame* ConstructSpdyControlFrame(
- const char* const extra_headers[],
- int extra_header_count,
- bool compressed,
- SpdyStreamId stream_id,
- RequestPriority request_priority,
- SpdyFrameType type,
- SpdyControlFlags flags,
- const char* const* tail_headers,
- int tail_headers_size,
- SpdyStreamId associated_stream_id) const;
+ SpdySerializedFrame* ConstructSpdyFrame(const SpdyHeaderInfo& header_info,
+ const char* const extra_headers[],
+ int extra_header_count,
+ const char* const tail_headers[],
+ int tail_header_count) const;
// Construct an expected SPDY reply string from the given headers.
std::string ConstructSpdyReplyString(const SpdyHeaderBlock& headers) const;
@@ -354,190 +328,189 @@ class SpdyTestUtil {
// Construct an expected SPDY SETTINGS frame.
// |settings| are the settings to set.
// Returns the constructed frame. The caller takes ownership of the frame.
- SpdyFrame* ConstructSpdySettings(const SettingsMap& settings) const;
+ SpdySerializedFrame* ConstructSpdySettings(const SettingsMap& settings);
// Constructs an expected SPDY SETTINGS acknowledgement frame, if the protocol
// version is SPDY4 or higher, or an empty placeholder frame otherwise.
- SpdyFrame* ConstructSpdySettingsAck() const;
+ SpdySerializedFrame* ConstructSpdySettingsAck();
// Construct a SPDY PING frame.
// Returns the constructed frame. The caller takes ownership of the frame.
- SpdyFrame* ConstructSpdyPing(uint32_t ping_id, bool is_ack) const;
+ SpdySerializedFrame* ConstructSpdyPing(uint32_t ping_id, bool is_ack);
// Construct a SPDY GOAWAY frame with last_good_stream_id = 0.
// Returns the constructed frame. The caller takes ownership of the frame.
- SpdyFrame* ConstructSpdyGoAway() const;
+ SpdySerializedFrame* ConstructSpdyGoAway();
// Construct a SPDY GOAWAY frame with the specified last_good_stream_id.
// Returns the constructed frame. The caller takes ownership of the frame.
- SpdyFrame* ConstructSpdyGoAway(SpdyStreamId last_good_stream_id) const;
+ SpdySerializedFrame* ConstructSpdyGoAway(SpdyStreamId last_good_stream_id);
// Construct a SPDY GOAWAY frame with the specified last_good_stream_id,
// status, and description. Returns the constructed frame. The caller takes
// ownership of the frame.
- SpdyFrame* ConstructSpdyGoAway(SpdyStreamId last_good_stream_id,
- SpdyGoAwayStatus status,
- const std::string& desc) const;
+ SpdySerializedFrame* ConstructSpdyGoAway(SpdyStreamId last_good_stream_id,
+ SpdyGoAwayStatus status,
+ const std::string& desc);
// Construct a SPDY WINDOW_UPDATE frame.
// Returns the constructed frame. The caller takes ownership of the frame.
- SpdyFrame* ConstructSpdyWindowUpdate(SpdyStreamId stream_id,
- uint32_t delta_window_size) const;
+ SpdySerializedFrame* ConstructSpdyWindowUpdate(SpdyStreamId stream_id,
+ uint32_t delta_window_size);
// Construct a SPDY RST_STREAM frame.
// Returns the constructed frame. The caller takes ownership of the frame.
- SpdyFrame* ConstructSpdyRstStream(SpdyStreamId stream_id,
- SpdyRstStreamStatus status) const;
+ SpdySerializedFrame* ConstructSpdyRstStream(SpdyStreamId stream_id,
+ SpdyRstStreamStatus status);
- // Constructs a standard SPDY GET SYN frame, optionally compressed
- // for |url|.
+ // Constructs a standard SPDY GET SYN frame for |url| with header compression.
// |extra_headers| are the extra header-value pairs, which typically
// will vary the most between calls.
- // Returns a SpdyFrame.
- SpdyFrame* ConstructSpdyGet(const char* const url,
- bool compressed,
- SpdyStreamId stream_id,
- RequestPriority request_priority);
+ // Returns a SpdySerializedFrame.
+ SpdySerializedFrame* ConstructSpdyGet(const char* const url,
+ SpdyStreamId stream_id,
+ RequestPriority request_priority);
- // Constructs a standard SPDY GET SYN frame, optionally compressed.
+ // Constructs a standard SPDY GET SYN frame with header compression.
// |extra_headers| are the extra header-value pairs, which typically
// will vary the most between calls. If |direct| is false, the
// the full url will be used instead of simply the path.
- // Returns a SpdyFrame.
- SpdyFrame* ConstructSpdyGet(const char* const extra_headers[],
- int extra_header_count,
- bool compressed,
- int stream_id,
- RequestPriority request_priority,
- bool direct);
+ // Returns a SpdySerializedFrame.
+ SpdySerializedFrame* ConstructSpdyGet(const char* const extra_headers[],
+ int extra_header_count,
+ int stream_id,
+ RequestPriority request_priority,
+ bool direct);
// Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
- SpdyFrame* ConstructSpdyConnect(const char* const extra_headers[],
- int extra_header_count,
- int stream_id,
- RequestPriority priority,
- const HostPortPair& host_port_pair);
+ SpdySerializedFrame* ConstructSpdyConnect(const char* const extra_headers[],
+ int extra_header_count,
+ int stream_id,
+ RequestPriority priority,
+ const HostPortPair& host_port_pair);
// Constructs a standard SPDY push SYN frame.
// |extra_headers| are the extra header-value pairs, which typically
// will vary the most between calls.
- // Returns a SpdyFrame.
- SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
- int extra_header_count,
- int stream_id,
- int associated_stream_id,
- const char* url);
- SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
- int extra_header_count,
- int stream_id,
- int associated_stream_id,
- const char* url,
- const char* status,
- const char* location);
-
- SpdyFrame* ConstructInitialSpdyPushFrame(scoped_ptr<SpdyHeaderBlock> headers,
- int stream_id,
- int associated_stream_id);
-
- SpdyFrame* ConstructSpdyPushHeaders(int stream_id,
- const char* const extra_headers[],
- int extra_header_count);
-
- SpdyFrame* ConstructSpdyHeaderFrame(int stream_id,
- const char* const headers[],
- int header_count);
-
- // Constructs a SPDY header frame with END_STREAM flag set to |fin|.
- SpdyFrame* ConstructSpdyHeaderFrame(int stream_id,
- const char* const headers[],
- int header_count,
- bool fin);
+ // Returns a SpdySerializedFrame.
+ SpdySerializedFrame* ConstructSpdyPush(const char* const extra_headers[],
+ int extra_header_count,
+ int stream_id,
+ int associated_stream_id,
+ const char* url);
+ SpdySerializedFrame* ConstructSpdyPush(const char* const extra_headers[],
+ int extra_header_count,
+ int stream_id,
+ int associated_stream_id,
+ const char* url,
+ const char* status,
+ const char* location);
+
+ SpdySerializedFrame* ConstructInitialSpdyPushFrame(
+ scoped_ptr<SpdyHeaderBlock> headers,
+ int stream_id,
+ int associated_stream_id);
+
+ SpdySerializedFrame* ConstructSpdyPushHeaders(
+ int stream_id,
+ const char* const extra_headers[],
+ int extra_header_count);
+
+ // Constructs a SPDY header frame with the request header compression context
+ // with END_STREAM flag set to |fin|.
+ SpdySerializedFrame* ConstructSpdyResponseHeaders(
+ int stream_id,
+ const SpdyHeaderBlock& headers,
+ bool fin);
// Construct a SPDY syn (HEADERS or SYN_STREAM, depending on protocol
// version) carrying exactly the given headers and priority.
- SpdyFrame* ConstructSpdySyn(int stream_id,
- const SpdyHeaderBlock& headers,
- RequestPriority priority,
- bool compressed,
- bool fin);
+ SpdySerializedFrame* ConstructSpdySyn(int stream_id,
+ const SpdyHeaderBlock& headers,
+ RequestPriority priority,
+ bool fin);
// Construct a SPDY reply (HEADERS or SYN_REPLY, depending on protocol
// version) carrying exactly the given headers, and the default priority
- // (or no priority, depending on protocl version).
- // The |headers| parameter variant is preferred.
- SpdyFrame* ConstructSpdyReply(int stream_id, const SpdyHeaderBlock& headers);
+ // (or no priority, depending on protocol version).
+ SpdySerializedFrame* ConstructSpdyReply(int stream_id,
+ const SpdyHeaderBlock& headers);
// Constructs a standard SPDY SYN_REPLY frame to match the SPDY GET.
// |extra_headers| are the extra header-value pairs, which typically
// will vary the most between calls.
- // Returns a SpdyFrame.
- SpdyFrame* ConstructSpdyGetSynReply(const char* const extra_headers[],
- int extra_header_count,
- int stream_id);
+ // Returns a SpdySerializedFrame.
+ SpdySerializedFrame* ConstructSpdyGetSynReply(
+ const char* const extra_headers[],
+ int extra_header_count,
+ int stream_id);
// Constructs a standard SPDY SYN_REPLY frame to match the SPDY GET.
// |extra_headers| are the extra header-value pairs, which typically
// will vary the most between calls.
- // Returns a SpdyFrame.
- SpdyFrame* ConstructSpdyGetSynReplyRedirect(int stream_id);
+ // Returns a SpdySerializedFrame.
+ SpdySerializedFrame* ConstructSpdyGetSynReplyRedirect(int stream_id);
// Constructs a standard SPDY SYN_REPLY frame with an Internal Server
// Error status code.
- // Returns a SpdyFrame.
- SpdyFrame* ConstructSpdySynReplyError(int stream_id);
+ // Returns a SpdySerializedFrame.
+ SpdySerializedFrame* ConstructSpdySynReplyError(int stream_id);
// Constructs a standard SPDY SYN_REPLY frame with the specified status code.
- // Returns a SpdyFrame.
- SpdyFrame* ConstructSpdySynReplyError(const char* const status,
- const char* const* const extra_headers,
- int extra_header_count,
- int stream_id);
+ // Returns a SpdySerializedFrame.
+ SpdySerializedFrame* ConstructSpdySynReplyError(
+ const char* const status,
+ const char* const* const extra_headers,
+ int extra_header_count,
+ int stream_id);
// Constructs a standard SPDY POST SYN frame.
// |extra_headers| are the extra header-value pairs, which typically
// will vary the most between calls.
- // Returns a SpdyFrame.
- SpdyFrame* ConstructSpdyPost(const char* url,
- SpdyStreamId stream_id,
- int64_t content_length,
- RequestPriority priority,
- const char* const extra_headers[],
- int extra_header_count);
+ // Returns a SpdySerializedFrame.
+ SpdySerializedFrame* ConstructSpdyPost(const char* url,
+ SpdyStreamId stream_id,
+ int64_t content_length,
+ RequestPriority priority,
+ const char* const extra_headers[],
+ int extra_header_count);
// Constructs a chunked transfer SPDY POST SYN frame.
// |extra_headers| are the extra header-value pairs, which typically
// will vary the most between calls.
- // Returns a SpdyFrame.
- SpdyFrame* ConstructChunkedSpdyPost(const char* const extra_headers[],
- int extra_header_count);
+ // Returns a SpdySerializedFrame.
+ SpdySerializedFrame* ConstructChunkedSpdyPost(
+ const char* const extra_headers[],
+ int extra_header_count);
// Constructs a standard SPDY SYN_REPLY frame to match the SPDY POST.
// |extra_headers| are the extra header-value pairs, which typically
// will vary the most between calls.
- // Returns a SpdyFrame.
- SpdyFrame* ConstructSpdyPostSynReply(const char* const extra_headers[],
- int extra_header_count);
+ // Returns a SpdySerializedFrame.
+ SpdySerializedFrame* ConstructSpdyPostSynReply(
+ const char* const extra_headers[],
+ int extra_header_count);
// Constructs a single SPDY data frame with the contents "hello!"
- SpdyFrame* ConstructSpdyBodyFrame(int stream_id,
- bool fin);
+ SpdySerializedFrame* ConstructSpdyBodyFrame(int stream_id, bool fin);
// Constructs a single SPDY data frame with the given content.
- SpdyFrame* ConstructSpdyBodyFrame(int stream_id,
- const char* data,
- uint32_t len,
- bool fin);
+ SpdySerializedFrame* ConstructSpdyBodyFrame(int stream_id,
+ const char* data,
+ uint32_t len,
+ bool fin);
// Constructs a single SPDY data frame with the given content and padding.
- SpdyFrame* ConstructSpdyBodyFrame(int stream_id,
- const char* data,
- uint32_t len,
- bool fin,
- int padding_length);
+ SpdySerializedFrame* ConstructSpdyBodyFrame(int stream_id,
+ const char* data,
+ uint32_t len,
+ bool fin,
+ int padding_length);
// Wraps |frame| in the payload of a data frame in stream |stream_id|.
- SpdyFrame* ConstructWrappedSpdyFrame(const scoped_ptr<SpdyFrame>& frame,
- int stream_id);
+ SpdySerializedFrame* ConstructWrappedSpdyFrame(
+ const scoped_ptr<SpdySerializedFrame>& frame,
+ int stream_id);
// Called when necessary (when it will affect stream dependency specification
// when setting dependencies based on priorioties) to notify the utility
@@ -554,7 +527,6 @@ class SpdyTestUtil {
NextProto protocol() const { return protocol_; }
SpdyMajorVersion spdy_version() const { return spdy_version_; }
bool include_version_header() const { return protocol_ < kProtoHTTP2; }
- scoped_ptr<SpdyFramer> CreateFramer(bool compressed) const;
const GURL& default_url() const { return default_url_; }
void set_default_url(const GURL& url) { default_url_ = url; }
@@ -576,6 +548,16 @@ class SpdyTestUtil {
const NextProto protocol_;
const SpdyMajorVersion spdy_version_;
+
+ // Multiple SpdyFramers are required to keep track of header compression
+ // state.
+ // Use to serialize frames (request or response) without headers.
+ SpdyFramer headerless_spdy_framer_;
+ // Use to serialize request frames with headers.
+ SpdyFramer request_spdy_framer_;
+ // Use to serialize response frames with headers.
+ SpdyFramer response_spdy_framer_;
+
GURL default_url_;
bool dependency_priorities_;
diff --git a/chromium/net/spdy/spdy_test_utils.cc b/chromium/net/spdy/spdy_test_utils.cc
index 668a9028f87..acc61c17914 100644
--- a/chromium/net/spdy/spdy_test_utils.cc
+++ b/chromium/net/spdy/spdy_test_utils.cc
@@ -19,8 +19,12 @@
namespace net {
namespace test {
-std::string HexDumpWithMarks(const unsigned char* data, int length,
- const bool* marks, int mark_length) {
+using std::string;
+
+string HexDumpWithMarks(const unsigned char* data,
+ int length,
+ const bool* marks,
+ int mark_length) {
static const char kHexChars[] = "0123456789abcdef";
static const int kColumns = 4;
@@ -31,7 +35,7 @@ std::string HexDumpWithMarks(const unsigned char* data, int length,
mark_length = std::min(mark_length, kSizeLimit);
}
- std::string hex;
+ string hex;
for (const unsigned char* row = data; length > 0;
row += kColumns, length -= kColumns) {
for (const unsigned char *p = row; p < row + 4; ++p) {
@@ -57,12 +61,11 @@ std::string HexDumpWithMarks(const unsigned char* data, int length,
return hex;
}
-void CompareCharArraysWithHexError(
- const std::string& description,
- const unsigned char* actual,
- const int actual_len,
- const unsigned char* expected,
- const int expected_len) {
+void CompareCharArraysWithHexError(const string& description,
+ const unsigned char* actual,
+ const int actual_len,
+ const unsigned char* expected,
+ const int expected_len) {
const int min_len = std::min(actual_len, expected_len);
const int max_len = std::max(actual_len, expected_len);
scoped_ptr<bool[]> marks(new bool[max_len]);
@@ -88,7 +91,7 @@ void CompareCharArraysWithHexError(
<< HexDumpWithMarks(actual, actual_len, marks.get(), max_len);
}
-void SetFrameFlags(SpdyFrame* frame,
+void SetFrameFlags(SpdySerializedFrame* frame,
uint8_t flags,
SpdyMajorVersion spdy_version) {
switch (spdy_version) {
@@ -101,7 +104,7 @@ void SetFrameFlags(SpdyFrame* frame,
}
}
-void SetFrameLength(SpdyFrame* frame,
+void SetFrameLength(SpdySerializedFrame* frame,
size_t length,
SpdyMajorVersion spdy_version) {
switch (spdy_version) {
@@ -128,9 +131,9 @@ void SetFrameLength(SpdyFrame* frame,
}
}
-std::string a2b_hex(const char* hex_data) {
+string a2b_hex(const char* hex_data) {
std::vector<uint8_t> output;
- std::string result;
+ string result;
if (base::HexStringToBytes(hex_data, &output))
result.assign(reinterpret_cast<const char*>(&output[0]), output.size());
return result;
@@ -142,22 +145,22 @@ HashValue GetTestHashValue(uint8_t label) {
return hash_value;
}
-std::string GetTestPin(uint8_t label) {
+string GetTestPin(uint8_t label) {
HashValue hash_value = GetTestHashValue(label);
- std::string base64;
+ string base64;
base::Base64Encode(base::StringPiece(
reinterpret_cast<char*>(hash_value.data()), hash_value.size()), &base64);
- return std::string("pin-sha256=\"") + base64 + "\"";
+ return string("pin-sha256=\"") + base64 + "\"";
}
void AddPin(TransportSecurityState* state,
- const std::string& host,
+ const string& host,
uint8_t primary_label,
uint8_t backup_label) {
- std::string primary_pin = GetTestPin(primary_label);
- std::string backup_pin = GetTestPin(backup_label);
- std::string header = "max-age = 10000; " + primary_pin + "; " + backup_pin;
+ string primary_pin = GetTestPin(primary_label);
+ string backup_pin = GetTestPin(backup_label);
+ string header = "max-age = 10000; " + primary_pin + "; " + backup_pin;
// Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
SSLInfo ssl_info;
@@ -166,5 +169,26 @@ void AddPin(TransportSecurityState* state,
EXPECT_TRUE(state->AddHPKPHeader(host, header, ssl_info));
}
+void TestHeadersHandler::OnHeaderBlockStart() {
+ block_.clear();
+}
+
+void TestHeadersHandler::OnHeader(base::StringPiece name,
+ base::StringPiece value) {
+ auto it = block_.find(name);
+ if (it == block_.end()) {
+ block_[name] = value;
+ } else {
+ string new_value = it->second.as_string();
+ new_value.append((name == "cookie") ? "; " : string(1, '\0'));
+ value.AppendToString(&new_value);
+ block_.ReplaceOrAppendHeader(name, new_value);
+ }
+}
+
+void TestHeadersHandler::OnHeaderBlockEnd(size_t header_bytes_parsed) {
+ header_bytes_parsed_ = header_bytes_parsed;
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/spdy/spdy_test_utils.h b/chromium/net/spdy/spdy_test_utils.h
index de4212f6b09..388cb2baee4 100644
--- a/chromium/net/spdy/spdy_test_utils.h
+++ b/chromium/net/spdy/spdy_test_utils.h
@@ -10,7 +10,9 @@
#include <string>
+#include "base/strings/string_piece.h"
#include "net/spdy/spdy_header_block.h"
+#include "net/spdy/spdy_headers_handler_interface.h"
#include "net/spdy/spdy_protocol.h"
namespace net {
@@ -35,11 +37,11 @@ void CompareCharArraysWithHexError(
const unsigned char* expected,
const int expected_len);
-void SetFrameFlags(SpdyFrame* frame,
+void SetFrameFlags(SpdySerializedFrame* frame,
uint8_t flags,
SpdyMajorVersion spdy_version);
-void SetFrameLength(SpdyFrame* frame,
+void SetFrameLength(SpdySerializedFrame* frame,
size_t length,
SpdyMajorVersion spdy_version);
@@ -58,6 +60,28 @@ void AddPin(TransportSecurityState* state,
uint8_t primary_label,
uint8_t backup_label);
+// A test implementation of SpdyHeadersHandlerInterface that correctly
+// reconstructs multiple header values for the same name.
+class TestHeadersHandler : public SpdyHeadersHandlerInterface {
+ public:
+ TestHeadersHandler() : header_bytes_parsed_(0) {}
+
+ void OnHeaderBlockStart() override;
+
+ void OnHeader(base::StringPiece name, base::StringPiece value) override;
+
+ void OnHeaderBlockEnd(size_t header_bytes_parsed) override;
+
+ const SpdyHeaderBlock& decoded_block() const { return block_; }
+ size_t header_bytes_parsed() { return header_bytes_parsed_; }
+
+ private:
+ SpdyHeaderBlock block_;
+ size_t header_bytes_parsed_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestHeadersHandler);
+};
+
} // namespace test
} // namespace net
diff --git a/chromium/net/spdy/spdy_write_queue.cc b/chromium/net/spdy/spdy_write_queue.cc
index ab25eaef8fb..a8e6553283a 100644
--- a/chromium/net/spdy/spdy_write_queue.cc
+++ b/chromium/net/spdy/spdy_write_queue.cc
@@ -26,6 +26,8 @@ SpdyWriteQueue::PendingWrite::PendingWrite(
stream(stream),
has_stream(stream.get() != NULL) {}
+SpdyWriteQueue::PendingWrite::PendingWrite(const PendingWrite& other) = default;
+
SpdyWriteQueue::PendingWrite::~PendingWrite() {}
SpdyWriteQueue::SpdyWriteQueue() : removing_writes_(false) {}
diff --git a/chromium/net/spdy/spdy_write_queue.h b/chromium/net/spdy/spdy_write_queue.h
index c19b3f206c6..8383e7a3cea 100644
--- a/chromium/net/spdy/spdy_write_queue.h
+++ b/chromium/net/spdy/spdy_write_queue.h
@@ -75,6 +75,7 @@ class NET_EXPORT_PRIVATE SpdyWriteQueue {
PendingWrite(SpdyFrameType frame_type,
SpdyBufferProducer* frame_producer,
const base::WeakPtr<SpdyStream>& stream);
+ PendingWrite(const PendingWrite& other);
~PendingWrite();
};
diff --git a/chromium/net/spdy/spdy_write_queue_unittest.cc b/chromium/net/spdy/spdy_write_queue_unittest.cc
index 1c7bc0a8805..da9d98778f7 100644
--- a/chromium/net/spdy/spdy_write_queue_unittest.cc
+++ b/chromium/net/spdy/spdy_write_queue_unittest.cc
@@ -35,12 +35,9 @@ class SpdyWriteQueueTest : public ::testing::Test {};
scoped_ptr<SpdyBufferProducer> StringToProducer(const std::string& s) {
scoped_ptr<char[]> data(new char[s.size()]);
std::memcpy(data.get(), s.data(), s.size());
- return scoped_ptr<SpdyBufferProducer>(
- new SimpleBufferProducer(
- scoped_ptr<SpdyBuffer>(
- new SpdyBuffer(
- scoped_ptr<SpdyFrame>(
- new SpdyFrame(data.release(), s.size(), true))))));
+ return scoped_ptr<SpdyBufferProducer>(new SimpleBufferProducer(
+ scoped_ptr<SpdyBuffer>(new SpdyBuffer(scoped_ptr<SpdySerializedFrame>(
+ new SpdySerializedFrame(data.release(), s.size(), true))))));
}
// Makes a SpdyBufferProducer producing a frame with the data in the
diff --git a/chromium/net/ssl/channel_id_service.cc b/chromium/net/ssl/channel_id_service.cc
index e17b813cd73..7cae014a2f0 100644
--- a/chromium/net/ssl/channel_id_service.cc
+++ b/chromium/net/ssl/channel_id_service.cc
@@ -8,6 +8,7 @@
#include <limits>
#include <utility>
+#include "base/atomic_sequence_num.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
@@ -38,6 +39,8 @@ namespace net {
namespace {
+base::StaticAtomicSequenceNumber g_next_id;
+
// Used by the GetDomainBoundCertResult histogram to record the final
// outcome of each GetChannelID or GetOrCreateChannelID call.
// Do not re-use values.
@@ -288,12 +291,12 @@ ChannelIDService::ChannelIDService(
const scoped_refptr<base::TaskRunner>& task_runner)
: channel_id_store_(channel_id_store),
task_runner_(task_runner),
+ id_(g_next_id.GetNext()),
requests_(0),
key_store_hits_(0),
inflight_joins_(0),
workers_created_(0),
- weak_ptr_factory_(this) {
-}
+ weak_ptr_factory_(this) {}
ChannelIDService::~ChannelIDService() {
STLDeleteValues(&inflight_);
diff --git a/chromium/net/ssl/channel_id_service.h b/chromium/net/ssl/channel_id_service.h
index eb4a92ae6f5..ef577974ccb 100644
--- a/chromium/net/ssl/channel_id_service.h
+++ b/chromium/net/ssl/channel_id_service.h
@@ -129,6 +129,10 @@ class NET_EXPORT ChannelIDService
// Returns the backing ChannelIDStore.
ChannelIDStore* GetChannelIDStore();
+ // Returns an ID that is unique across all instances of ChannelIDService in
+ // this process. TODO(nharper): remove this once crbug.com/548423 is resolved.
+ int GetUniqueID() const { return id_; }
+
// Public only for unit testing.
int channel_id_count();
uint64_t requests() const { return requests_; }
@@ -171,6 +175,7 @@ class NET_EXPORT ChannelIDService
scoped_ptr<ChannelIDStore> channel_id_store_;
scoped_refptr<base::TaskRunner> task_runner_;
+ const int id_;
// inflight_ maps from a server to an active generation which is taking
// place.
diff --git a/chromium/net/ssl/channel_id_store.h b/chromium/net/ssl/channel_id_store.h
index efdf7e5e4c4..3eb9d67a31f 100644
--- a/chromium/net/ssl/channel_id_store.h
+++ b/chromium/net/ssl/channel_id_store.h
@@ -104,6 +104,10 @@ class NET_EXPORT ChannelIDStore
// When invoked, instructs the store to keep session related data on
// destruction.
virtual void SetForceKeepSessionState() = 0;
+
+ // Returns true if this ChannelIDStore is ephemeral, and false if it is
+ // persistent.
+ virtual bool IsEphemeral() = 0;
};
} // namespace net
diff --git a/chromium/net/ssl/client_cert_store_mac.cc b/chromium/net/ssl/client_cert_store_mac.cc
index 06d7d0613c8..ec662b57bb8 100644
--- a/chromium/net/ssl/client_cert_store_mac.cc
+++ b/chromium/net/ssl/client_cert_store_mac.cc
@@ -28,6 +28,11 @@ using base::ScopedCFTypeRef;
namespace net {
+// 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"
+
namespace {
// Gets the issuer for a given cert, starting with the cert itself and
@@ -274,4 +279,6 @@ bool ClientCertStoreMac::SelectClientCertsGivenPreferredForTesting(
return true;
}
+#pragma clang diagnostic pop // "-Wdeprecated-declarations"
+
} // namespace net
diff --git a/chromium/net/ssl/client_cert_store_nss.cc b/chromium/net/ssl/client_cert_store_nss.cc
index 8a6c329b58f..073745ef3ad 100644
--- a/chromium/net/ssl/client_cert_store_nss.cc
+++ b/chromium/net/ssl/client_cert_store_nss.cc
@@ -6,6 +6,8 @@
#include <nss.h>
#include <ssl.h>
+
+#include <algorithm>
#include <utility>
#include "base/bind.h"
@@ -55,7 +57,6 @@ void ClientCertStoreNSS::GetClientCerts(const SSLCertRequestInfo& request,
void ClientCertStoreNSS::FilterCertsOnWorkerThread(
const CertificateList& certs,
const SSLCertRequestInfo& request,
- bool query_nssdb,
CertificateList* filtered_certs) {
DCHECK(filtered_certs);
@@ -95,16 +96,15 @@ void ClientCertStoreNSS::FilterCertsOnWorkerThread(
}
// Check if the certificate issuer is allowed by the server.
- if (request.cert_authorities.empty() ||
- (!query_nssdb && cert->IsIssuedByEncoded(request.cert_authorities)) ||
- (query_nssdb &&
- NSS_CmpCertChainWCANames(handle, &ca_names) == SECSuccess)) {
- DVLOG(2) << "matched cert: " << base::StringPiece(handle->nickname);
- filtered_certs->push_back(cert);
- } else {
+ if (!request.cert_authorities.empty() &&
+ NSS_CmpCertChainWCANames(handle, &ca_names) != SECSuccess) {
DVLOG(2) << "skipped non-matching cert: "
<< base::StringPiece(handle->nickname);
+ continue;
}
+
+ DVLOG(2) << "matched cert: " << base::StringPiece(handle->nickname);
+ filtered_certs->push_back(cert);
}
DVLOG(2) << "num_raw:" << num_raw
<< " num_filtered:" << filtered_certs->size();
@@ -119,7 +119,7 @@ void ClientCertStoreNSS::GetAndFilterCertsOnWorkerThread(
CertificateList* selected_certs) {
CertificateList platform_certs;
GetPlatformCertsOnWorkerThread(std::move(password_delegate), &platform_certs);
- FilterCertsOnWorkerThread(platform_certs, *request, true, selected_certs);
+ FilterCertsOnWorkerThread(platform_certs, *request, selected_certs);
}
// static
diff --git a/chromium/net/ssl/client_cert_store_nss.h b/chromium/net/ssl/client_cert_store_nss.h
index cb560f1ca18..5583661a917 100644
--- a/chromium/net/ssl/client_cert_store_nss.h
+++ b/chromium/net/ssl/client_cert_store_nss.h
@@ -39,12 +39,9 @@ class NET_EXPORT ClientCertStoreNSS : public ClientCertStore {
// the client certificate request in |request|, storing the matching
// certificates in |filtered_certs|. Any previous content of |filtered_certs|
// will be removed.
- // If |query_nssdb| is true, NSS will be queried to construct full certificate
- // chains. If it is false, only the certificate will be considered.
// Must be called from a worker thread.
static void FilterCertsOnWorkerThread(const CertificateList& certs,
const SSLCertRequestInfo& request,
- bool query_nssdb,
CertificateList* filtered_certs);
// Retrieves all client certificates that are stored by NSS and adds them to
diff --git a/chromium/net/ssl/client_cert_store_nss_unittest.cc b/chromium/net/ssl/client_cert_store_nss_unittest.cc
index 00d3a9c655d..dbf06660bb0 100644
--- a/chromium/net/ssl/client_cert_store_nss_unittest.cc
+++ b/chromium/net/ssl/client_cert_store_nss_unittest.cc
@@ -18,7 +18,7 @@ class ClientCertStoreNSSTestDelegate {
// Filters |input_certs| using the logic being used to filter the system
// store when GetClientCerts() is called.
ClientCertStoreNSS::FilterCertsOnWorkerThread(
- input_certs, cert_request_info, false, selected_certs);
+ input_certs, cert_request_info, selected_certs);
return true;
}
};
diff --git a/chromium/net/ssl/default_channel_id_store.cc b/chromium/net/ssl/default_channel_id_store.cc
index 8fff6f04132..184fccd3055 100644
--- a/chromium/net/ssl/default_channel_id_store.cc
+++ b/chromium/net/ssl/default_channel_id_store.cc
@@ -425,6 +425,10 @@ void DefaultChannelIDStore::InternalInsertChannelID(
channel_ids_[server_identifier] = channel_id.release();
}
+bool DefaultChannelIDStore::IsEphemeral() {
+ return store_.get() == nullptr;
+}
+
DefaultChannelIDStore::PersistentStore::PersistentStore() {}
DefaultChannelIDStore::PersistentStore::~PersistentStore() {}
diff --git a/chromium/net/ssl/default_channel_id_store.h b/chromium/net/ssl/default_channel_id_store.h
index 52eb1d01947..fed03193796 100644
--- a/chromium/net/ssl/default_channel_id_store.h
+++ b/chromium/net/ssl/default_channel_id_store.h
@@ -61,6 +61,7 @@ class NET_EXPORT DefaultChannelIDStore : public ChannelIDStore {
void GetAllChannelIDs(const GetChannelIDListCallback& callback) override;
int GetChannelIDCount() override;
void SetForceKeepSessionState() override;
+ bool IsEphemeral() override;
private:
class Task;
diff --git a/chromium/net/ssl/openssl_ssl_util.cc b/chromium/net/ssl/openssl_ssl_util.cc
index b91acdd97a2..ae3834a71d4 100644
--- a/chromium/net/ssl/openssl_ssl_util.cc
+++ b/chromium/net/ssl/openssl_ssl_util.cc
@@ -16,6 +16,7 @@
#include "base/values.h"
#include "crypto/openssl_util.h"
#include "net/base/net_errors.h"
+#include "net/ssl/ssl_connection_status_flags.h"
namespace net {
@@ -205,4 +206,42 @@ NetLog::ParametersCallback CreateNetLogOpenSSLErrorCallback(
net_error, ssl_error, error_info);
}
+int GetNetSSLVersion(SSL* ssl) {
+ switch (SSL_version(ssl)) {
+ case TLS1_VERSION:
+ return SSL_CONNECTION_VERSION_TLS1;
+ case TLS1_1_VERSION:
+ return SSL_CONNECTION_VERSION_TLS1_1;
+ case TLS1_2_VERSION:
+ return SSL_CONNECTION_VERSION_TLS1_2;
+ default:
+ NOTREACHED();
+ return SSL_CONNECTION_VERSION_UNKNOWN;
+ }
+}
+
+ScopedX509 OSCertHandleToOpenSSL(X509Certificate::OSCertHandle os_handle) {
+#if defined(USE_OPENSSL_CERTS)
+ return ScopedX509(X509Certificate::DupOSCertHandle(os_handle));
+#else // !defined(USE_OPENSSL_CERTS)
+ std::string der_encoded;
+ if (!X509Certificate::GetDEREncoded(os_handle, &der_encoded))
+ return ScopedX509();
+ const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_encoded.data());
+ return ScopedX509(d2i_X509(NULL, &bytes, der_encoded.size()));
+#endif // defined(USE_OPENSSL_CERTS)
+}
+
+ScopedX509Stack OSCertHandlesToOpenSSL(
+ const X509Certificate::OSCertHandles& os_handles) {
+ ScopedX509Stack stack(sk_X509_new_null());
+ for (size_t i = 0; i < os_handles.size(); i++) {
+ ScopedX509 x509 = OSCertHandleToOpenSSL(os_handles[i]);
+ if (!x509)
+ return nullptr;
+ sk_X509_push(stack.get(), x509.release());
+ }
+ return stack;
+}
+
} // namespace net
diff --git a/chromium/net/ssl/openssl_ssl_util.h b/chromium/net/ssl/openssl_ssl_util.h
index af8b9abb15b..545c95810e9 100644
--- a/chromium/net/ssl/openssl_ssl_util.h
+++ b/chromium/net/ssl/openssl_ssl_util.h
@@ -7,7 +7,11 @@
#include <stdint.h>
+#include <openssl/ssl.h>
+
+#include "net/cert/x509_certificate.h"
#include "net/log/net_log.h"
+#include "net/ssl/scoped_openssl_types.h"
namespace crypto {
class OpenSSLErrStackTracer;
@@ -69,6 +73,15 @@ NetLog::ParametersCallback CreateNetLogOpenSSLErrorCallback(
int ssl_error,
const OpenSSLErrorInfo& error_info);
+// Returns the net SSL version number (see ssl_connection_status_flags.h) for
+// this SSL connection.
+int GetNetSSLVersion(SSL* ssl);
+
+ScopedX509 OSCertHandleToOpenSSL(X509Certificate::OSCertHandle os_handle);
+
+ScopedX509Stack OSCertHandlesToOpenSSL(
+ const X509Certificate::OSCertHandles& os_handles);
+
} // namespace net
#endif // NET_SSL_OPENSSL_SSL_UTIL_H_
diff --git a/chromium/net/ssl/scoped_openssl_types.h b/chromium/net/ssl/scoped_openssl_types.h
index a8c3c345975..8bee4981b24 100644
--- a/chromium/net/ssl/scoped_openssl_types.h
+++ b/chromium/net/ssl/scoped_openssl_types.h
@@ -6,18 +6,29 @@
#define NET_SSL_SCOPED_OPENSSL_TYPES_H_
#include <openssl/ssl.h>
+#include <openssl/stack.h>
#include <openssl/x509.h>
#include "crypto/scoped_openssl_types.h"
namespace net {
-using ScopedPKCS8_PRIV_KEY_INFO =
- crypto::ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>;
+inline void FreeX509Stack(STACK_OF(X509)* ptr) {
+ sk_X509_pop_free(ptr, X509_free);
+}
+
+inline void FreeX509NameStack(STACK_OF(X509_NAME)* ptr) {
+ sk_X509_NAME_pop_free(ptr, X509_NAME_free);
+}
+
using ScopedSSL = crypto::ScopedOpenSSL<SSL, SSL_free>;
using ScopedSSL_CTX = crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free>;
using ScopedSSL_SESSION = crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free>;
using ScopedX509 = crypto::ScopedOpenSSL<X509, X509_free>;
+using ScopedX509_NAME = crypto::ScopedOpenSSL<X509_NAME, X509_NAME_free>;
+using ScopedX509Stack = crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack>;
+using ScopedX509NameStack =
+ crypto::ScopedOpenSSL<STACK_OF(X509_NAME), FreeX509NameStack>;
} // namespace net
diff --git a/chromium/net/ssl/signed_certificate_timestamp_and_status.cc b/chromium/net/ssl/signed_certificate_timestamp_and_status.cc
index 245fcf2ac2e..55deaa38a10 100644
--- a/chromium/net/ssl/signed_certificate_timestamp_and_status.cc
+++ b/chromium/net/ssl/signed_certificate_timestamp_and_status.cc
@@ -13,6 +13,9 @@ SignedCertificateTimestampAndStatus::SignedCertificateTimestampAndStatus(
const ct::SCTVerifyStatus status)
: sct(sct), status(status) {}
+SignedCertificateTimestampAndStatus::SignedCertificateTimestampAndStatus(
+ const SignedCertificateTimestampAndStatus& other) = default;
+
SignedCertificateTimestampAndStatus::~SignedCertificateTimestampAndStatus() {}
} // namespace net
diff --git a/chromium/net/ssl/signed_certificate_timestamp_and_status.h b/chromium/net/ssl/signed_certificate_timestamp_and_status.h
index c23753ea4d7..650e5b1a715 100644
--- a/chromium/net/ssl/signed_certificate_timestamp_and_status.h
+++ b/chromium/net/ssl/signed_certificate_timestamp_and_status.h
@@ -19,6 +19,9 @@ struct NET_EXPORT SignedCertificateTimestampAndStatus {
const scoped_refptr<ct::SignedCertificateTimestamp>& sct,
ct::SCTVerifyStatus status);
+ SignedCertificateTimestampAndStatus(
+ const SignedCertificateTimestampAndStatus& other);
+
~SignedCertificateTimestampAndStatus();
scoped_refptr<ct::SignedCertificateTimestamp> sct;
diff --git a/chromium/net/ssl/ssl_cert_request_info.h b/chromium/net/ssl/ssl_cert_request_info.h
index 13f91d6913b..8b9e542221d 100644
--- a/chromium/net/ssl/ssl_cert_request_info.h
+++ b/chromium/net/ssl/ssl_cert_request_info.h
@@ -32,7 +32,7 @@ class X509Certificate;
//
// struct {
// ClientCertificateType certificate_types<1..2^8-1>;
-// DistinguishedName certificate_authorities<3..2^16-1>;
+// DistinguishedName certificate_authorities<0..2^16-1>;
// } CertificateRequest;
class NET_EXPORT SSLCertRequestInfo
: public base::RefCountedThreadSafe<SSLCertRequestInfo> {
diff --git a/chromium/net/ssl/ssl_client_session_cache_openssl.cc b/chromium/net/ssl/ssl_client_session_cache_openssl.cc
index 6246bd54365..a413eeeafe0 100644
--- a/chromium/net/ssl/ssl_client_session_cache_openssl.cc
+++ b/chromium/net/ssl/ssl_client_session_cache_openssl.cc
@@ -40,7 +40,7 @@ ScopedSSL_SESSION SSLClientSessionCacheOpenSSL::Lookup(
CacheEntryMap::iterator iter = cache_.Get(cache_key);
if (iter == cache_.end())
return nullptr;
- if (IsExpired(iter->second, clock_->Now())) {
+ if (IsExpired(iter->second.get(), clock_->Now())) {
cache_.Erase(iter);
return nullptr;
}
@@ -52,12 +52,12 @@ void SSLClientSessionCacheOpenSSL::Insert(const std::string& cache_key,
base::AutoLock lock(lock_);
// Make a new entry.
- CacheEntry* entry = new CacheEntry;
+ scoped_ptr<CacheEntry> entry(new CacheEntry);
entry->session.reset(SSL_SESSION_up_ref(session));
entry->creation_time = clock_->Now();
// Takes ownership.
- cache_.Put(cache_key, entry);
+ cache_.Put(cache_key, std::move(entry));
}
void SSLClientSessionCacheOpenSSL::Flush() {
@@ -88,7 +88,7 @@ void SSLClientSessionCacheOpenSSL::FlushExpiredSessions() {
base::Time now = clock_->Now();
CacheEntryMap::iterator iter = cache_.begin();
while (iter != cache_.end()) {
- if (IsExpired(iter->second, now)) {
+ if (IsExpired(iter->second.get(), now)) {
iter = cache_.Erase(iter);
} else {
++iter;
diff --git a/chromium/net/ssl/ssl_client_session_cache_openssl.h b/chromium/net/ssl/ssl_client_session_cache_openssl.h
index b74042ed4ff..a432b5958fc 100644
--- a/chromium/net/ssl/ssl_client_session_cache_openssl.h
+++ b/chromium/net/ssl/ssl_client_session_cache_openssl.h
@@ -66,10 +66,7 @@ class NET_EXPORT SSLClientSessionCacheOpenSSL {
};
using CacheEntryMap =
- base::MRUCacheBase<std::string,
- CacheEntry*,
- base::MRUCachePointerDeletor<CacheEntry*>,
- base::MRUCacheHashMap>;
+ base::HashingMRUCache<std::string, scoped_ptr<CacheEntry>>;
// Returns true if |entry| is expired as of |now|.
bool IsExpired(CacheEntry* entry, const base::Time& now);
diff --git a/chromium/net/ssl/ssl_config.cc b/chromium/net/ssl/ssl_config.cc
index e3ced671925..4a71b5948cb 100644
--- a/chromium/net/ssl/ssl_config.cc
+++ b/chromium/net/ssl/ssl_config.cc
@@ -12,7 +12,7 @@ const uint16_t kDefaultSSLVersionMin = SSL_PROTOCOL_VERSION_TLS1;
const uint16_t kDefaultSSLVersionMax = SSL_PROTOCOL_VERSION_TLS1_2;
-const uint16_t kDefaultSSLVersionFallbackMin = SSL_PROTOCOL_VERSION_TLS1_1;
+const uint16_t kDefaultSSLVersionFallbackMin = SSL_PROTOCOL_VERSION_TLS1_2;
SSLConfig::CertAndStatus::CertAndStatus() : cert_status(0) {}
@@ -36,6 +36,8 @@ SSLConfig::SSLConfig()
cert_io_enabled(true),
renego_allowed_default(false) {}
+SSLConfig::SSLConfig(const SSLConfig& other) = default;
+
SSLConfig::~SSLConfig() {}
bool SSLConfig::IsAllowedBadCert(X509Certificate* cert,
diff --git a/chromium/net/ssl/ssl_config.h b/chromium/net/ssl/ssl_config.h
index 5460f6640ef..21f4cccbdf8 100644
--- a/chromium/net/ssl/ssl_config.h
+++ b/chromium/net/ssl/ssl_config.h
@@ -47,6 +47,7 @@ NET_EXPORT extern const uint16_t kDefaultSSLVersionFallbackMin;
struct NET_EXPORT SSLConfig {
// Default to revocation checking.
SSLConfig();
+ SSLConfig(const SSLConfig& other);
~SSLConfig();
// Returns true if |cert| is one of the certs in |allowed_bad_certs|.
@@ -96,19 +97,6 @@ struct NET_EXPORT SSLConfig {
// Presorted list of cipher suites which should be explicitly prevented from
// being used in addition to those disabled by the net built-in policy.
//
- // By default, all cipher suites supported by the underlying SSL
- // implementation will be enabled except for:
- // - Null encryption cipher suites.
- // - Weak cipher suites: < 80 bits of security strength.
- // - FORTEZZA cipher suites (obsolete).
- // - IDEA cipher suites (RFC 5469 explains why).
- // - Anonymous cipher suites.
- // - ECDSA cipher suites on platforms that do not support ECDSA signed
- // certificates, as servers may use the presence of such ciphersuites as a
- // hint to send an ECDSA certificate.
- // The ciphers listed in |disabled_cipher_suites| will be removed in addition
- // to the above list.
- //
// Though cipher suites are sent in TLS as "uint8_t CipherSuite[2]", in
// big-endian form, they should be declared in host byte order, with the
// first uint8_t occupying the most significant byte.
diff --git a/chromium/net/ssl/ssl_info.cc b/chromium/net/ssl/ssl_info.cc
index 545bf7ec6df..c6bc04137fd 100644
--- a/chromium/net/ssl/ssl_info.cc
+++ b/chromium/net/ssl/ssl_info.cc
@@ -6,6 +6,7 @@
#include "base/pickle.h"
#include "net/cert/cert_status_flags.h"
+#include "net/cert/ct_policy_status.h"
#include "net/cert/signed_certificate_timestamp.h"
#include "net/cert/x509_certificate.h"
@@ -36,8 +37,11 @@ SSLInfo& SSLInfo::operator=(const SSLInfo& info) {
token_binding_key_param = info.token_binding_key_param;
handshake_type = info.handshake_type;
public_key_hashes = info.public_key_hashes;
- signed_certificate_timestamps = info.signed_certificate_timestamps;
pinning_failure_log = info.pinning_failure_log;
+ signed_certificate_timestamps = info.signed_certificate_timestamps;
+ ct_compliance_details_available = info.ct_compliance_details_available;
+ ct_ev_policy_compliance = info.ct_ev_policy_compliance;
+ ct_cert_policy_compliance = info.ct_cert_policy_compliance;
return *this;
}
@@ -56,15 +60,19 @@ void SSLInfo::Reset() {
token_binding_key_param = TB_PARAM_ECDSAP256;
handshake_type = HANDSHAKE_UNKNOWN;
public_key_hashes.clear();
- signed_certificate_timestamps.clear();
pinning_failure_log.clear();
+ signed_certificate_timestamps.clear();
+ ct_compliance_details_available = false;
+ ct_ev_policy_compliance = ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
+ ct_cert_policy_compliance =
+ ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS;
}
void SSLInfo::SetCertError(int error) {
cert_status |= MapNetErrorToCertStatus(error);
}
-void SSLInfo::UpdateSignedCertificateTimestamps(
+void SSLInfo::UpdateCertificateTransparencyInfo(
const ct::CTVerifyResult& ct_verify_result) {
for (const auto& sct : ct_verify_result.verified_scts) {
signed_certificate_timestamps.push_back(
@@ -78,6 +86,10 @@ void SSLInfo::UpdateSignedCertificateTimestamps(
signed_certificate_timestamps.push_back(
SignedCertificateTimestampAndStatus(sct, ct::SCT_STATUS_LOG_UNKNOWN));
}
+
+ ct_compliance_details_available = ct_verify_result.ct_policies_applied;
+ ct_cert_policy_compliance = ct_verify_result.cert_policy_compliance;
+ ct_ev_policy_compliance = ct_verify_result.ev_policy_compliance;
}
} // namespace net
diff --git a/chromium/net/ssl/ssl_info.h b/chromium/net/ssl/ssl_info.h
index 40dec286572..6bb21875e0a 100644
--- a/chromium/net/ssl/ssl_info.h
+++ b/chromium/net/ssl/ssl_info.h
@@ -18,6 +18,13 @@
namespace net {
+namespace ct {
+
+enum class CertPolicyCompliance;
+enum class EVPolicyCompliance;
+
+} // namespace ct
+
class X509Certificate;
// SSL connection info.
@@ -44,12 +51,14 @@ class NET_EXPORT SSLInfo {
// Adds the specified |error| to the cert status.
void SetCertError(int error);
- // Adds the SignedCertificateTimestamps from ct_verify_result to
- // |signed_certificate_timestamps|. SCTs are held in three separate vectors
- // in ct_verify_result, each vetor representing a particular verification
- // state, this method associates each of the SCTs with the corresponding
- // SCTVerifyStatus as it adds it to the |signed_certificate_timestamps| list.
- void UpdateSignedCertificateTimestamps(
+ // Adds the SignedCertificateTimestamps and policy compliance details
+ // from ct_verify_result to |signed_certificate_timestamps| and
+ // |ct_policy_compliance_details|. SCTs are held in three separate
+ // vectors in ct_verify_result, each vetor representing a particular
+ // verification state, this method associates each of the SCTs with
+ // the corresponding SCTVerifyStatus as it adds it to the
+ // |signed_certificate_timestamps| list.
+ void UpdateCertificateTransparencyInfo(
const ct::CTVerifyResult& ct_verify_result);
// The SSL certificate.
@@ -115,6 +124,23 @@ class NET_EXPORT SSLInfo {
// List of SignedCertificateTimestamps and their corresponding validation
// status.
SignedCertificateTimestampAndStatusList signed_certificate_timestamps;
+
+ // True if Certificate Transparency policies were applied on this
+ // connection and results are available. If true, the field below
+ // (|ev_policy_compliance|) will contain information about whether
+ // the connection complied with the policy and why the connection
+ // was considered non-compliant, if applicable.
+ bool ct_compliance_details_available;
+
+ // Whether the connection complied with the CT EV policy, and if not,
+ // why not. Only meaningful if |ct_compliance_details_available| is
+ // true.
+ ct::EVPolicyCompliance ct_ev_policy_compliance;
+
+ // Whether the connection complied with the CT cert policy, and if
+ // not, why not. Only meaningful it |ct_compliance_details_available|
+ // is true.
+ ct::CertPolicyCompliance ct_cert_policy_compliance;
};
} // namespace net
diff --git a/chromium/net/ssl/ssl_platform_key_chromecast.cc b/chromium/net/ssl/ssl_platform_key_chromecast.cc
new file mode 100644
index 00000000000..ef1fef56e60
--- /dev/null
+++ b/chromium/net/ssl/ssl_platform_key_chromecast.cc
@@ -0,0 +1,136 @@
+// 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 <prerror.h>
+
+#include <openssl/rsa.h>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/sequenced_task_runner.h"
+#include "crypto/scoped_nss_types.h"
+#include "crypto/scoped_openssl_types.h"
+#include "net/cert/x509_certificate.h"
+#include "net/ssl/client_key_store.h"
+#include "net/ssl/ssl_platform_key_task_runner.h"
+#include "net/ssl/ssl_private_key.h"
+#include "net/ssl/threaded_ssl_private_key.h"
+
+namespace net {
+
+namespace {
+
+void LogPRError() {
+ PRErrorCode err = PR_GetError();
+ const char* err_name = PR_ErrorToName(err);
+ if (err_name == nullptr)
+ err_name = "";
+ LOG(ERROR) << "Could not sign digest: " << err << " (" << err_name << ")";
+}
+
+class SSLPlatformKeyChromecast : public ThreadedSSLPrivateKey::Delegate {
+ public:
+ SSLPlatformKeyChromecast(crypto::ScopedSECKEYPrivateKey key)
+ : key_(std::move(key)) {}
+ ~SSLPlatformKeyChromecast() override {}
+
+ 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));
+ }
+
+ size_t GetMaxSignatureLengthInBytes() override {
+ int len = PK11_SignatureLen(key_.get());
+ if (len <= 0)
+ return 0;
+ return static_cast<size_t>(len);
+ }
+
+ Error SignDigest(SSLPrivateKey::Hash hash,
+ const base::StringPiece& input,
+ std::vector<uint8_t>* signature) override {
+ SECItem digest_item;
+ digest_item.data =
+ const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(input.data()));
+ digest_item.len = input.size();
+
+ crypto::ScopedOpenSSLBytes free_digest_info;
+ // PK11_Sign expects the caller to prepend the DigestInfo.
+ int hash_nid = NID_undef;
+ switch (hash) {
+ case SSLPrivateKey::Hash::MD5_SHA1:
+ hash_nid = NID_md5_sha1;
+ break;
+ case SSLPrivateKey::Hash::SHA1:
+ hash_nid = NID_sha1;
+ break;
+ case SSLPrivateKey::Hash::SHA256:
+ hash_nid = NID_sha256;
+ break;
+ default:
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+ DCHECK_NE(NID_undef, hash_nid);
+ int is_alloced;
+ size_t prefix_len;
+ if (!RSA_add_pkcs1_prefix(&digest_item.data, &prefix_len, &is_alloced,
+ hash_nid, digest_item.data, digest_item.len)) {
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+ digest_item.len = prefix_len;
+ if (is_alloced)
+ free_digest_info.reset(digest_item.data);
+
+ int len = PK11_SignatureLen(key_.get());
+ if (len <= 0) {
+ LogPRError();
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+ signature->resize(len);
+ SECItem signature_item;
+ signature_item.data = signature->data();
+ signature_item.len = signature->size();
+
+ SECStatus rv = PK11_Sign(key_.get(), &signature_item, &digest_item);
+ if (rv != SECSuccess) {
+ LogPRError();
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+ signature->resize(signature_item.len);
+
+ return OK;
+ }
+
+ private:
+ crypto::ScopedSECKEYPrivateKey key_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyChromecast);
+};
+
+} // namespace
+
+scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
+ X509Certificate* certificate) {
+ crypto::ScopedSECKEYPrivateKey key(
+ PK11_FindKeyByAnyCert(certificate->os_cert_handle(), nullptr));
+ if (!key) {
+ return ClientKeyStore::GetInstance()->FetchClientCertPrivateKey(
+ *certificate);
+ }
+
+ return make_scoped_refptr(new ThreadedSSLPrivateKey(
+ make_scoped_ptr(new SSLPlatformKeyChromecast(std::move(key))),
+ GetSSLPlatformKeyTaskRunner()));
+}
+
+} // namespace net
diff --git a/chromium/net/ssl/ssl_platform_key_mac.cc b/chromium/net/ssl/ssl_platform_key_mac.cc
index ec7cb42f0db..050189b7af4 100644
--- a/chromium/net/ssl/ssl_platform_key_mac.cc
+++ b/chromium/net/ssl/ssl_platform_key_mac.cc
@@ -34,6 +34,11 @@
namespace net {
+// 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"
+
namespace {
class ScopedCSSM_CC_HANDLE {
@@ -241,4 +246,6 @@ scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
GetSSLPlatformKeyTaskRunner()));
}
+#pragma clang diagnostic pop // "-Wdeprecated-declarations"
+
} // namespace net
diff --git a/chromium/net/ssl/ssl_platform_key_win.cc b/chromium/net/ssl/ssl_platform_key_win.cc
index 2f3e7c6764c..49fc31a6725 100644
--- a/chromium/net/ssl/ssl_platform_key_win.cc
+++ b/chromium/net/ssl/ssl_platform_key_win.cc
@@ -9,6 +9,7 @@
#include <algorithm>
#include <string>
+#include <utility>
#include <vector>
#include <openssl/bn.h>
@@ -358,7 +359,7 @@ scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
delegate.reset(new SSLPlatformKeyCAPI(prov_or_key, key_spec, max_length));
}
return make_scoped_refptr(new ThreadedSSLPrivateKey(
- delegate.Pass(), GetSSLPlatformKeyTaskRunner()));
+ std::move(delegate), GetSSLPlatformKeyTaskRunner()));
}
} // namespace net
diff --git a/chromium/net/ssl/ssl_server_config.cc b/chromium/net/ssl/ssl_server_config.cc
index 8b3e67f7f21..f5041b672b1 100644
--- a/chromium/net/ssl/ssl_server_config.cc
+++ b/chromium/net/ssl/ssl_server_config.cc
@@ -13,7 +13,10 @@ SSLServerConfig::SSLServerConfig()
: version_min(kDefaultSSLVersionMin),
version_max(SSL_PROTOCOL_VERSION_TLS1_2),
require_ecdhe(false),
- require_client_cert(false) {}
+ client_cert_type(NO_CLIENT_CERT),
+ client_cert_verifier(nullptr) {}
+
+SSLServerConfig::SSLServerConfig(const SSLServerConfig& other) = default;
SSLServerConfig::~SSLServerConfig() {}
diff --git a/chromium/net/ssl/ssl_server_config.h b/chromium/net/ssl/ssl_server_config.h
index 36d1286b225..21ec1285c87 100644
--- a/chromium/net/ssl/ssl_server_config.h
+++ b/chromium/net/ssl/ssl_server_config.h
@@ -14,10 +14,19 @@
namespace net {
+class ClientCertVerifier;
+
// A collection of server-side SSL-related configuration settings.
struct NET_EXPORT SSLServerConfig {
+ enum ClientCertType {
+ NO_CLIENT_CERT,
+ OPTIONAL_CLIENT_CERT,
+ REQUIRE_CLIENT_CERT,
+ };
+
// Defaults
SSLServerConfig();
+ SSLServerConfig(const SSLServerConfig& other);
~SSLServerConfig();
// The minimum and maximum protocol versions that are enabled.
@@ -53,9 +62,21 @@ struct NET_EXPORT SSLServerConfig {
// If true, causes only ECDHE cipher suites to be enabled.
bool require_ecdhe;
- // Requires a client certificate for client authentication from the client.
- // This doesn't currently enforce certificate validity.
- bool require_client_cert;
+ // Sets the requirement for client certificates during handshake.
+ ClientCertType client_cert_type;
+
+ // List of DER-encoded X.509 DistinguishedName of certificate authorities
+ // to be included in the CertificateRequest handshake message,
+ // if client certificates are required.
+ std::vector<std::string> cert_authorities_;
+
+ // Provides the ClientCertVerifier that is to be used to verify
+ // client certificates during the handshake.
+ // The |client_cert_verifier| continues to be owned by the caller,
+ // and must outlive any sockets spawned from this SSLServerContext.
+ // This field is meaningful only if client certificates are requested.
+ // If a verifier is not provided then all certificates are accepted.
+ ClientCertVerifier* client_cert_verifier;
};
} // namespace net
diff --git a/chromium/net/ssl/test_ssl_private_key.cc b/chromium/net/ssl/test_ssl_private_key.cc
new file mode 100644
index 00000000000..99ed33b15cd
--- /dev/null
+++ b/chromium/net/ssl/test_ssl_private_key.cc
@@ -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.
+
+#include "net/ssl/test_ssl_private_key.h"
+
+#include <openssl/digest.h>
+#include <openssl/evp.h>
+#include <utility>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "crypto/scoped_openssl_types.h"
+#include "net/base/net_errors.h"
+#include "net/ssl/ssl_platform_key_task_runner.h"
+#include "net/ssl/ssl_private_key.h"
+#include "net/ssl/threaded_ssl_private_key.h"
+
+namespace net {
+
+namespace {
+
+class TestSSLPlatformKey : public ThreadedSSLPrivateKey::Delegate {
+ public:
+ TestSSLPlatformKey(crypto::ScopedEVP_PKEY key, SSLPrivateKey::Type type)
+ : key_(std::move(key)), type_(type) {}
+
+ ~TestSSLPlatformKey() override {}
+
+ SSLPrivateKey::Type GetType() override { return type_; }
+
+ std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override {
+ static const SSLPrivateKey::Hash kHashes[] = {
+ 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 EVP_PKEY_size(key_.get());
+ }
+
+ Error SignDigest(SSLPrivateKey::Hash hash,
+ const base::StringPiece& input,
+ std::vector<uint8_t>* signature) override {
+ crypto::ScopedEVP_PKEY_CTX ctx =
+ crypto::ScopedEVP_PKEY_CTX(EVP_PKEY_CTX_new(key_.get(), NULL));
+ if (!ctx)
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ if (!EVP_PKEY_sign_init(ctx.get()))
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+
+ if (type_ == SSLPrivateKey::Type::RSA) {
+ const EVP_MD* digest = nullptr;
+ switch (hash) {
+ case SSLPrivateKey::Hash::MD5_SHA1:
+ digest = EVP_md5_sha1();
+ break;
+ case SSLPrivateKey::Hash::SHA1:
+ digest = EVP_sha1();
+ break;
+ case SSLPrivateKey::Hash::SHA256:
+ digest = EVP_sha256();
+ break;
+ case SSLPrivateKey::Hash::SHA384:
+ digest = EVP_sha384();
+ break;
+ case SSLPrivateKey::Hash::SHA512:
+ digest = EVP_sha512();
+ break;
+ default:
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+ DCHECK(digest);
+ if (!EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING))
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), digest))
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+
+ const uint8_t* input_ptr = reinterpret_cast<const uint8_t*>(input.data());
+ size_t input_len = input.size();
+ size_t sig_len = 0;
+ if (!EVP_PKEY_sign(ctx.get(), NULL, &sig_len, input_ptr, input_len))
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ signature->resize(sig_len);
+ if (!EVP_PKEY_sign(ctx.get(), signature->data(), &sig_len, input_ptr,
+ input_len)) {
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+
+ signature->resize(sig_len);
+
+ return OK;
+ }
+
+ private:
+ crypto::ScopedEVP_PKEY key_;
+ SSLPrivateKey::Type type_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSSLPlatformKey);
+};
+
+} // namespace
+
+scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(crypto::ScopedEVP_PKEY key) {
+ if (!key)
+ return nullptr;
+
+ SSLPrivateKey::Type type;
+ switch (EVP_PKEY_id(key.get())) {
+ case EVP_PKEY_RSA:
+ type = SSLPrivateKey::Type::RSA;
+ break;
+ case EVP_PKEY_EC:
+ type = SSLPrivateKey::Type::ECDSA;
+ break;
+ default:
+ LOG(ERROR) << "Unknown key type: " << EVP_PKEY_id(key.get());
+ return nullptr;
+ }
+ return make_scoped_refptr(new ThreadedSSLPrivateKey(
+ make_scoped_ptr(new TestSSLPlatformKey(std::move(key), type)),
+ GetSSLPlatformKeyTaskRunner()));
+}
+
+} // namespace net
diff --git a/chromium/net/ssl/test_ssl_private_key.h b/chromium/net/ssl/test_ssl_private_key.h
new file mode 100644
index 00000000000..f9ae906d30a
--- /dev/null
+++ b/chromium/net/ssl/test_ssl_private_key.h
@@ -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.
+
+#ifndef NET_SSL_TEST_SSL_PLATFORM_KEY_H_
+#define NET_SSL_TEST_SSL_PLATFORM_KEY_H_
+
+#include <openssl/evp.h>
+
+#include "base/memory/ref_counted.h"
+#include "crypto/scoped_openssl_types.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+class SSLPrivateKey;
+
+// Returns a new SSLPrivateKey which uses |key| for signing operations or
+// nullptr on error.
+NET_EXPORT scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(
+ crypto::ScopedEVP_PKEY key);
+
+} // namespace net
+
+#endif // NET_SSL_TEST_SSL_PLATFORM_KEY_H_
diff --git a/chromium/net/ssl/threaded_ssl_private_key.h b/chromium/net/ssl/threaded_ssl_private_key.h
index 629ce3b9160..23aed37cba3 100644
--- a/chromium/net/ssl/threaded_ssl_private_key.h
+++ b/chromium/net/ssl/threaded_ssl_private_key.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "net/ssl/ssl_private_key.h"
diff --git a/chromium/net/ssl/token_binding.h b/chromium/net/ssl/token_binding.h
new file mode 100644
index 00000000000..64104aa5c86
--- /dev/null
+++ b/chromium/net/ssl/token_binding.h
@@ -0,0 +1,117 @@
+// 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_SSL_TOKEN_BINDING_H_
+#define NET_SSL_TOKEN_BINDING_H_
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string_piece.h"
+#include "crypto/ec_private_key.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+enum class TokenBindingType {
+ PROVIDED = 0,
+ REFERRED = 1,
+};
+
+// Returns whether Token Binding is supported on this platform. If this function
+// returns false, Token Binding must not be negotiated.
+bool IsTokenBindingSupported();
+
+// Takes an exported keying material value |ekm| from the TLS layer and a token
+// binding key |key| and signs the EKM, putting the signature in |*out|. Returns
+// true on success or false if there's an error in the signing operations.
+bool SignTokenBindingEkm(base::StringPiece ekm,
+ crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out);
+
+// Given a vector of serialized TokenBinding structs (as defined in
+// draft-ietf-tokbind-protocol-04), this function combines them to form the
+// serialized TokenBindingMessage struct in |*out|. This function returns a net
+// error.
+//
+// struct {
+// TokenBinding tokenbindings<0..2^16-1>;
+// } TokenBindingMessage;
+Error BuildTokenBindingMessageFromTokenBindings(
+ const std::vector<base::StringPiece>& token_bindings,
+ std::string* out);
+
+// Builds a TokenBinding struct of type |type| with a TokenBindingID created
+// from |*key| and a signature of |ekm| using |*key| to sign.
+//
+// enum {
+// rsa2048_pkcs1.5(0), rsa2048_pss(1), ecdsap256(2), (255)
+// } TokenBindingKeyParameters;
+//
+// struct {
+// opaque modulus<1..2^16-1>;
+// opaque publicexponent<1..2^8-1>;
+// } RSAPublicKey;
+//
+// struct {
+// opaque point <1..2^8-1>;
+// } ECPoint;
+//
+// enum {
+// provided_token_binding(0), referred_token_binding(1), (255)
+// } TokenBindingType;
+//
+// struct {
+// TokenBindingType tokenbinding_type;
+// TokenBindingKeyParameters key_parameters;
+// select (key_parameters) {
+// case rsa2048_pkcs1.5:
+// case rsa2048_pss:
+// RSAPublicKey rsapubkey;
+// case ecdsap256:
+// ECPoint point;
+// }
+// } TokenBindingID;
+//
+// struct {
+// TokenBindingID tokenbindingid;
+// opaque signature<0..2^16-1>;// Signature over the exported keying
+// // material value
+// Extension extensions<0..2^16-1>;
+// } TokenBinding;
+Error BuildTokenBinding(TokenBindingType type,
+ crypto::ECPrivateKey* key,
+ const std::vector<uint8_t>& ekm,
+ std::string* out);
+
+// Represents a parsed TokenBinding from a TokenBindingMessage.
+struct TokenBinding {
+ TokenBinding();
+
+ TokenBindingType type;
+ std::string ec_point;
+ std::string signature;
+};
+
+// Given a TokenBindingMessage, parses the TokenBinding structs from it, putting
+// them into |*token_bindings|. If there is an error parsing the
+// TokenBindingMessage or the key parameter for any TokenBinding in the
+// TokenBindingMessage is not ecdsap256, then this function returns false.
+NET_EXPORT_PRIVATE bool ParseTokenBindingMessage(
+ base::StringPiece token_binding_message,
+ std::vector<TokenBinding>* token_bindings);
+
+// Takes an ECPoint |ec_point| from a TokenBindingID and |signature| from a
+// TokenBinding and verifies that |signature| is the signature of |ekm| using
+// |ec_point| as the public key. Returns true if the signature verifies and
+// false if it doesn't or some other error occurs in verification. This function
+// is only provided for testing.
+NET_EXPORT_PRIVATE bool VerifyEKMSignature(base::StringPiece ec_point,
+ base::StringPiece signature,
+ base::StringPiece ekm);
+
+} // namespace net
+
+#endif // NET_SSL_TOKEN_BINDING_H_
diff --git a/chromium/net/ssl/token_binding_nss.cc b/chromium/net/ssl/token_binding_nss.cc
new file mode 100644
index 00000000000..aa2dd09439a
--- /dev/null
+++ b/chromium/net/ssl/token_binding_nss.cc
@@ -0,0 +1,51 @@
+// 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 "token_binding.h"
+
+#include "net/base/net_errors.h"
+
+namespace net {
+
+bool IsTokenBindingSupported() {
+ return false;
+}
+
+bool SignTokenBindingEkm(base::StringPiece ekm,
+ crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ return false;
+}
+
+Error BuildTokenBindingMessageFromTokenBindings(
+ const std::vector<base::StringPiece>& token_bindings,
+ std::string* out) {
+ NOTREACHED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
+Error BuildTokenBinding(TokenBindingType type,
+ crypto::ECPrivateKey* key,
+ const std::vector<uint8_t>& ekm,
+ std::string* out) {
+ NOTREACHED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
+TokenBinding::TokenBinding() {}
+
+bool ParseTokenBindingMessage(base::StringPiece token_binding_message,
+ std::vector<TokenBinding>* token_bindings) {
+ NOTREACHED();
+ return false;
+}
+
+bool VerifyEKMSignature(base::StringPiece ec_point,
+ base::StringPiece signature,
+ base::StringPiece ekm) {
+ NOTREACHED();
+ return false;
+}
+
+} // namespace net
diff --git a/chromium/net/ssl/token_binding_openssl.cc b/chromium/net/ssl/token_binding_openssl.cc
new file mode 100644
index 00000000000..f2a48ed113d
--- /dev/null
+++ b/chromium/net/ssl/token_binding_openssl.cc
@@ -0,0 +1,166 @@
+// 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/ssl/token_binding.h"
+
+#include <openssl/bytestring.h>
+#include <openssl/ec.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+
+#include "base/stl_util.h"
+#include "crypto/scoped_openssl_types.h"
+#include "net/base/net_errors.h"
+#include "net/ssl/ssl_config.h"
+
+namespace net {
+
+namespace {
+
+bool BuildTokenBindingID(crypto::ECPrivateKey* key, CBB* out) {
+ EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key->key());
+ DCHECK(ec_key);
+
+ CBB ec_point;
+ return CBB_add_u8(out, TB_PARAM_ECDSAP256) &&
+ CBB_add_u8_length_prefixed(out, &ec_point) &&
+ EC_POINT_point2cbb(&ec_point, EC_KEY_get0_group(ec_key),
+ EC_KEY_get0_public_key(ec_key),
+ POINT_CONVERSION_UNCOMPRESSED, nullptr) &&
+ CBB_flush(out);
+}
+
+} // namespace
+
+bool IsTokenBindingSupported() {
+ return true;
+}
+
+bool SignTokenBindingEkm(base::StringPiece ekm,
+ crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ size_t sig_len;
+ const uint8_t* ekm_data = reinterpret_cast<const uint8_t*>(ekm.data());
+ crypto::ScopedEVP_PKEY_CTX pctx(EVP_PKEY_CTX_new(key->key(), nullptr));
+ if (!EVP_PKEY_sign_init(pctx.get()) ||
+ !EVP_PKEY_sign(pctx.get(), nullptr, &sig_len, ekm_data, ekm.size())) {
+ return false;
+ }
+ out->resize(sig_len);
+ if (!EVP_PKEY_sign(pctx.get(), out->data(), &sig_len, ekm_data, ekm.size()))
+ return false;
+ out->resize(sig_len);
+ return true;
+}
+
+Error BuildTokenBindingMessageFromTokenBindings(
+ const std::vector<base::StringPiece>& token_bindings,
+ std::string* out) {
+ CBB tb_message, child;
+ if (!CBB_init(&tb_message, 0) ||
+ !CBB_add_u16_length_prefixed(&tb_message, &child)) {
+ CBB_cleanup(&tb_message);
+ return ERR_FAILED;
+ }
+ for (const base::StringPiece& token_binding : token_bindings) {
+ if (!CBB_add_bytes(&child,
+ reinterpret_cast<const uint8_t*>(token_binding.data()),
+ token_binding.size())) {
+ CBB_cleanup(&tb_message);
+ return ERR_FAILED;
+ }
+ }
+
+ uint8_t* out_data;
+ size_t out_len;
+ if (!CBB_finish(&tb_message, &out_data, &out_len)) {
+ CBB_cleanup(&tb_message);
+ return ERR_FAILED;
+ }
+ out->assign(reinterpret_cast<char*>(out_data), out_len);
+ OPENSSL_free(out_data);
+ return OK;
+}
+
+Error BuildTokenBinding(TokenBindingType type,
+ crypto::ECPrivateKey* key,
+ const std::vector<uint8_t>& signed_ekm,
+ std::string* out) {
+ uint8_t* out_data;
+ size_t out_len;
+ CBB token_binding;
+ if (!CBB_init(&token_binding, 0) ||
+ !CBB_add_u8(&token_binding, static_cast<uint8_t>(type)) ||
+ !BuildTokenBindingID(key, &token_binding) ||
+ !CBB_add_u16(&token_binding, signed_ekm.size()) ||
+ !CBB_add_bytes(&token_binding, signed_ekm.data(), signed_ekm.size()) ||
+ // 0-length extensions
+ !CBB_add_u16(&token_binding, 0) ||
+ !CBB_finish(&token_binding, &out_data, &out_len)) {
+ CBB_cleanup(&token_binding);
+ return ERR_FAILED;
+ }
+ out->assign(reinterpret_cast<char*>(out_data), out_len);
+ OPENSSL_free(out_data);
+ return OK;
+}
+
+TokenBinding::TokenBinding() {}
+
+bool ParseTokenBindingMessage(base::StringPiece token_binding_message,
+ std::vector<TokenBinding>* token_bindings) {
+ CBS tb_message, tb, ec_point, signature, extensions;
+ uint8_t tb_type, tb_param;
+ CBS_init(&tb_message,
+ reinterpret_cast<const uint8_t*>(token_binding_message.data()),
+ token_binding_message.size());
+ if (!CBS_get_u16_length_prefixed(&tb_message, &tb))
+ return false;
+ while (CBS_len(&tb)) {
+ if (!CBS_get_u8(&tb, &tb_type) || !CBS_get_u8(&tb, &tb_param) ||
+ !CBS_get_u8_length_prefixed(&tb, &ec_point) ||
+ !CBS_get_u16_length_prefixed(&tb, &signature) ||
+ !CBS_get_u16_length_prefixed(&tb, &extensions) ||
+ tb_param != TB_PARAM_ECDSAP256 ||
+ (TokenBindingType(tb_type) != TokenBindingType::PROVIDED &&
+ TokenBindingType(tb_type) != TokenBindingType::REFERRED)) {
+ return false;
+ }
+
+ TokenBinding token_binding;
+ token_binding.type = TokenBindingType(tb_type);
+ token_binding.ec_point = std::string(
+ reinterpret_cast<const char*>(CBS_data(&ec_point)), CBS_len(&ec_point));
+ token_binding.signature =
+ std::string(reinterpret_cast<const char*>(CBS_data(&signature)),
+ CBS_len(&signature));
+ token_bindings->push_back(token_binding);
+ }
+ return true;
+}
+
+bool VerifyEKMSignature(base::StringPiece ec_point,
+ base::StringPiece signature,
+ base::StringPiece ekm) {
+ crypto::ScopedEC_Key key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+ EC_KEY* keyp = key.get();
+ const uint8_t* ec_point_data =
+ reinterpret_cast<const uint8_t*>(ec_point.data());
+ if (o2i_ECPublicKey(&keyp, &ec_point_data, ec_point.size()) != key.get())
+ return false;
+ crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
+ if (!EVP_PKEY_assign_EC_KEY(pkey.get(), key.release()))
+ return false;
+ crypto::ScopedEVP_PKEY_CTX pctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
+ if (!EVP_PKEY_verify_init(pctx.get()) ||
+ !EVP_PKEY_verify(
+ pctx.get(), reinterpret_cast<const uint8_t*>(signature.data()),
+ signature.size(), reinterpret_cast<const uint8_t*>(ekm.data()),
+ ekm.size())) {
+ return false;
+ }
+ return true;
+}
+
+} // namespace net
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/IEmbeddedTestServerImpl.aidl b/chromium/net/test/android/javatests/src/org/chromium/net/test/IEmbeddedTestServerImpl.aidl
index 898b7f582e1..366210a1c78 100644
--- a/chromium/net/test/android/javatests/src/org/chromium/net/test/IEmbeddedTestServerImpl.aidl
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/IEmbeddedTestServerImpl.aidl
@@ -15,6 +15,14 @@ interface IEmbeddedTestServerImpl {
*/
boolean start();
+ /** Add the default handlers and serve files from the provided directory relative to the
+ * external storage directory.
+ *
+ * @param directoryPath The path of the directory from which files should be served, relative
+ * to the external storage directory.
+ */
+ void addDefaultHandlers(String directoryPath);
+
/** Serve files from the provided directory.
*
* @param directoryPath The path of the directory from which files should be served.
diff --git a/chromium/net/test/cert_test_util_nss.cc b/chromium/net/test/cert_test_util_nss.cc
index 4cd435bc3ac..b171fe9e841 100644
--- a/chromium/net/test/cert_test_util_nss.cc
+++ b/chromium/net/test/cert_test_util_nss.cc
@@ -37,7 +37,7 @@ bool ImportSensitiveKeyFromFile(const base::FilePath& dir,
true /* permanent */));
LOG_IF(ERROR, !private_key) << "Could not create key from file "
<< key_path.value();
- return private_key;
+ return !!private_key;
}
bool ImportClientCertToSlot(const scoped_refptr<X509Certificate>& cert,
diff --git a/chromium/net/test/ct_test_util.cc b/chromium/net/test/ct_test_util.cc
index b36c13ded8a..9bc6f958da7 100644
--- a/chromium/net/test/ct_test_util.cc
+++ b/chromium/net/test/ct_test_util.cc
@@ -14,7 +14,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/cert/ct_serialization.h"
-#include "net/cert/signed_certificate_timestamp.h"
+#include "net/cert/ct_verify_result.h"
#include "net/cert/signed_tree_head.h"
#include "net/cert/x509_certificate.h"
@@ -360,6 +360,38 @@ std::string CreateConsistencyProofJsonString(
return consistency_proof_json;
}
+std::string GetSCTListForTesting() {
+ const std::string sct = ct::GetTestSignedCertificateTimestamp();
+ std::string sct_list;
+ ct::EncodeSCTListForTesting(sct, &sct_list);
+ return sct_list;
+}
+
+std::string GetSCTListWithInvalidSCT() {
+ std::string sct(ct::GetTestSignedCertificateTimestamp());
+
+ // Change a byte inside the Log ID part of the SCT so it does not match the
+ // log used in the tests.
+ sct[15] = 't';
+
+ std::string sct_list;
+ ct::EncodeSCTListForTesting(sct, &sct_list);
+ return sct_list;
+}
+
+bool CheckForSingleVerifiedSCTInResult(const ct::CTVerifyResult& result,
+ const std::string& log_description) {
+ return (result.verified_scts.size() == 1U) && result.invalid_scts.empty() &&
+ result.unknown_logs_scts.empty() &&
+ result.verified_scts[0]->log_description == log_description;
+}
+
+bool CheckForSCTOrigin(const ct::CTVerifyResult& result,
+ ct::SignedCertificateTimestamp::Origin origin) {
+ return (result.verified_scts.size() > 0) &&
+ (result.verified_scts[0]->origin == origin);
+}
+
} // namespace ct
} // namespace net
diff --git a/chromium/net/test/ct_test_util.h b/chromium/net/test/ct_test_util.h
index e1d6cff6f09..d3df6e62d9b 100644
--- a/chromium/net/test/ct_test_util.h
+++ b/chromium/net/test/ct_test_util.h
@@ -12,14 +12,15 @@
#include <vector>
#include "base/memory/ref_counted.h"
+#include "net/cert/signed_certificate_timestamp.h"
namespace net {
namespace ct {
+struct CTVerifyResult;
struct DigitallySigned;
struct LogEntry;
-struct SignedCertificateTimestamp;
struct SignedTreeHead;
// Note: unless specified otherwise, all test data is taken from Certificate
@@ -102,6 +103,23 @@ std::string CreateSignedTreeHeadJsonString(size_t tree_size,
// the provided raw nodes (i.e. the raw nodes will be base64-encoded).
std::string CreateConsistencyProofJsonString(
const std::vector<std::string>& raw_nodes);
+
+// Returns SCTList for testing.
+std::string GetSCTListForTesting();
+
+// Returns a corrupted SCTList. This is done by changing a byte inside the
+// Log ID part of the SCT so it does not match the log used in the tests.
+std::string GetSCTListWithInvalidSCT();
+
+// Returns true if |log_description| is in the |result|'s |verified_scts| and
+// number of |verified_scts| in |result| is equal to 1.
+bool CheckForSingleVerifiedSCTInResult(const CTVerifyResult& result,
+ const std::string& log_description);
+
+// Returns true if |origin| is in the |result|'s |verified_scts|.
+bool CheckForSCTOrigin(const CTVerifyResult& result,
+ SignedCertificateTimestamp::Origin origin);
+
} // namespace ct
} // namespace net
diff --git a/chromium/net/test/embedded_test_server/android/embedded_test_server_android.cc b/chromium/net/test/embedded_test_server/android/embedded_test_server_android.cc
index 0f53545b5bf..f3f301241e4 100644
--- a/chromium/net/test/embedded_test_server/android/embedded_test_server_android.cc
+++ b/chromium/net/test/embedded_test_server/android/embedded_test_server_android.cc
@@ -46,6 +46,15 @@ base::android::ScopedJavaLocalRef<jstring> EmbeddedTestServerAndroid::GetURL(
return base::android::ConvertUTF8ToJavaString(env, gurl.spec());
}
+void EmbeddedTestServerAndroid::AddDefaultHandlers(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& jobj,
+ const JavaParamRef<jstring>& jdirectory_path) {
+ const base::FilePath directory(
+ base::android::ConvertJavaStringToUTF8(env, jdirectory_path));
+ test_server_.AddDefaultHandlers(directory);
+}
+
void EmbeddedTestServerAndroid::ServeFilesFromDirectory(
JNIEnv* env,
const JavaParamRef<jobject>& jobj,
diff --git a/chromium/net/test/embedded_test_server/android/embedded_test_server_android.h b/chromium/net/test/embedded_test_server/android/embedded_test_server_android.h
index a3876f71836..c0d1cec6008 100644
--- a/chromium/net/test/embedded_test_server/android/embedded_test_server_android.h
+++ b/chromium/net/test/embedded_test_server/android/embedded_test_server_android.h
@@ -36,6 +36,11 @@ class EmbeddedTestServerAndroid {
const base::android::JavaParamRef<jobject>& jobj,
const base::android::JavaParamRef<jstring>& jrelative_url) const;
+ void AddDefaultHandlers(
+ JNIEnv* jenv,
+ const base::android::JavaParamRef<jobject>& jobj,
+ const base::android::JavaParamRef<jstring>& jdirectory_path);
+
void ServeFilesFromDirectory(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jobj,
diff --git a/chromium/net/test/embedded_test_server/default_handlers.cc b/chromium/net/test/embedded_test_server/default_handlers.cc
index 039ac3c8665..74967217f5f 100644
--- a/chromium/net/test/embedded_test_server/default_handlers.cc
+++ b/chromium/net/test/embedded_test_server/default_handlers.cc
@@ -34,7 +34,8 @@ namespace test_server {
namespace {
const UnescapeRule::Type kUnescapeAll =
- UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS |
+ UnescapeRule::SPACES | UnescapeRule::PATH_SEPARATORS |
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS |
UnescapeRule::SPOOFING_AND_CONTROL_CHARS |
UnescapeRule::REPLACE_PLUS_WITH_SPACE;
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 8f10e1ca301..eb09b967867 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server.cc
+++ b/chromium/net/test/embedded_test_server/embedded_test_server.cc
@@ -111,9 +111,32 @@ bool EmbeddedTestServer::InitializeAndListen() {
port_ = local_endpoint_.port();
listen_socket_->DetachFromThread();
+
+ if (is_using_ssl_)
+ InitializeSSLServerContext();
return true;
}
+void EmbeddedTestServer::InitializeSSLServerContext() {
+ base::FilePath certs_dir(GetTestCertsDirectory());
+ std::string cert_name = GetCertificateName();
+
+ base::FilePath key_path = certs_dir.AppendASCII(cert_name);
+ std::string key_string;
+ CHECK(base::ReadFileToString(key_path, &key_string));
+ std::vector<std::string> headers;
+ headers.push_back("PRIVATE KEY");
+ PEMTokenizer pem_tokenizer(key_string, headers);
+ pem_tokenizer.GetNext();
+ std::vector<uint8_t> key_vector;
+ key_vector.assign(pem_tokenizer.data().begin(), pem_tokenizer.data().end());
+
+ scoped_ptr<crypto::RSAPrivateKey> server_key(
+ crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vector));
+ context_ =
+ CreateSSLServerContext(GetCertificate().get(), *server_key, ssl_config_);
+}
+
void EmbeddedTestServer::StartAcceptingConnections() {
DCHECK(!io_thread_.get());
base::Thread::Options thread_options;
@@ -276,24 +299,7 @@ scoped_ptr<StreamSocket> EmbeddedTestServer::DoSSLUpgrade(
scoped_ptr<StreamSocket> connection) {
DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
- base::FilePath certs_dir(GetTestCertsDirectory());
- std::string cert_name = GetCertificateName();
-
- base::FilePath key_path = certs_dir.AppendASCII(cert_name);
- std::string key_string;
- CHECK(base::ReadFileToString(key_path, &key_string));
- std::vector<std::string> headers;
- headers.push_back("PRIVATE KEY");
- PEMTokenizer pem_tokenizer(key_string, headers);
- pem_tokenizer.GetNext();
- std::vector<uint8_t> key_vector;
- key_vector.assign(pem_tokenizer.data().begin(), pem_tokenizer.data().end());
-
- scoped_ptr<crypto::RSAPrivateKey> server_key(
- crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vector));
-
- return CreateSSLServerSocket(std::move(connection), GetCertificate().get(),
- *server_key, ssl_config_);
+ return context_->CreateSSLServerSocket(std::move(connection));
}
void EmbeddedTestServer::DoAcceptLoop() {
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 ad69a141843..00952f9905d 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server.h
+++ b/chromium/net/test/embedded_test_server/embedded_test_server.h
@@ -25,6 +25,7 @@
#include "net/base/host_port_pair.h"
#include "net/base/ip_endpoint.h"
#include "net/cert/x509_certificate.h"
+#include "net/socket/ssl_server_socket.h"
#include "net/socket/stream_socket.h"
#include "net/socket/tcp_server_socket.h"
#include "net/ssl/ssl_server_config.h"
@@ -65,7 +66,7 @@ struct HttpRequest;
// http_response->set_code(test_server::SUCCESS);
// http_response->set_content("hello");
// http_response->set_content_type("text/plain");
-// return http_response.Pass();
+// return http_response;
// }
//
// For a test that spawns another process such as browser_tests, it is
@@ -243,6 +244,10 @@ class EmbeddedTestServer {
void HandleRequest(HttpConnection* connection,
scoped_ptr<HttpRequest> request);
+ // Initializes the SSLServerContext so that SSLServerSocket connections may
+ // share the same cache
+ void InitializeSSLServerContext();
+
HttpConnection* FindConnection(StreamSocket* socket);
// Posts a task to the |io_thread_| and waits for a reply.
@@ -272,6 +277,7 @@ class EmbeddedTestServer {
net::SSLServerConfig ssl_config_;
ServerCertificate cert_;
+ scoped_ptr<SSLServerContext> context_;
base::WeakPtrFactory<EmbeddedTestServer> weak_factory_;
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 a08d3b7e254..bdd4a826d04 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
@@ -30,7 +30,7 @@
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
#include "net/cert_net/nss_ocsp.h"
#endif
@@ -122,7 +122,7 @@ class EmbeddedTestServerTest
}
void SetUp() override {
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
// This is needed so NSS's HTTP client functions are initialized on the
// right thread. These tests create SSLClientSockets on a different thread.
// TODO(davidben): Initialization can't be deferred to SSLClientSocket. See
@@ -145,7 +145,7 @@ class EmbeddedTestServerTest
void TearDown() override {
if (server_->Started())
ASSERT_TRUE(server_->ShutdownAndWaitUntilComplete());
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
ShutdownNSSHttpIO();
#endif
}
@@ -496,7 +496,7 @@ typedef std::tr1::tuple<bool, bool, EmbeddedTestServer::Type>
class EmbeddedTestServerThreadingTest
: public testing::TestWithParam<ThreadingTestParams> {
void SetUp() override {
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
// This is needed so NSS's HTTP client functions are initialized on the
// right thread. These tests create SSLClientSockets on a different thread.
// TODO(davidben): Initialization can't be deferred to SSLClientSocket. See
@@ -507,7 +507,7 @@ class EmbeddedTestServerThreadingTest
}
void TearDown() override {
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
ShutdownNSSHttpIO();
#endif
}
diff --git a/chromium/net/test/embedded_test_server/http_request.cc b/chromium/net/test/embedded_test_server/http_request.cc
index b5b2e4f372d..a1332bee3b4 100644
--- a/chromium/net/test/embedded_test_server/http_request.cc
+++ b/chromium/net/test/embedded_test_server/http_request.cc
@@ -34,6 +34,8 @@ HttpRequest::HttpRequest() : method(METHOD_UNKNOWN),
has_content(false) {
}
+HttpRequest::HttpRequest(const HttpRequest& other) = default;
+
HttpRequest::~HttpRequest() {
}
@@ -244,6 +246,8 @@ HttpMethod HttpRequestParser::GetMethodType(const std::string& token) const {
return METHOD_PATCH;
} else if (token == "connect") {
return METHOD_CONNECT;
+ } else if (token == "options") {
+ return METHOD_OPTIONS;
}
LOG(WARNING) << "Method not implemented: " << token;
return METHOD_GET;
diff --git a/chromium/net/test/embedded_test_server/http_request.h b/chromium/net/test/embedded_test_server/http_request.h
index d99c0500267..d9e54b8151b 100644
--- a/chromium/net/test/embedded_test_server/http_request.h
+++ b/chromium/net/test/embedded_test_server/http_request.h
@@ -32,6 +32,7 @@ enum HttpMethod {
METHOD_DELETE,
METHOD_PATCH,
METHOD_CONNECT,
+ METHOD_OPTIONS,
};
// Represents a HTTP request. Since it can be big, use scoped_ptr to pass it
@@ -48,6 +49,7 @@ struct HttpRequest {
std::map<std::string, std::string, CaseInsensitiveStringComparator>;
HttpRequest();
+ HttpRequest(const HttpRequest& other);
~HttpRequest();
// Returns a GURL as a convenience to extract the path and query strings.
diff --git a/chromium/net/test/embedded_test_server/request_handler_util.cc b/chromium/net/test/embedded_test_server/request_handler_util.cc
index ab3e975e2e4..db3f3a6fa0f 100644
--- a/chromium/net/test/embedded_test_server/request_handler_util.cc
+++ b/chromium/net/test/embedded_test_server/request_handler_util.cc
@@ -27,7 +27,8 @@ namespace test_server {
namespace {
const UnescapeRule::Type kUnescapeAll =
- UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS |
+ UnescapeRule::SPACES | UnescapeRule::PATH_SEPARATORS |
+ UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS |
UnescapeRule::SPOOFING_AND_CONTROL_CHARS |
UnescapeRule::REPLACE_PLUS_WITH_SPACE;
@@ -38,6 +39,10 @@ std::string GetContentType(const base::FilePath& path) {
return "application/octet-stream";
if (path.MatchesExtension(FILE_PATH_LITERAL(".gif")))
return "image/gif";
+ if (path.MatchesExtension(FILE_PATH_LITERAL(".gzip")) ||
+ path.MatchesExtension(FILE_PATH_LITERAL(".gz"))) {
+ return "application/x-gzip";
+ }
if (path.MatchesExtension(FILE_PATH_LITERAL(".jpeg")) ||
path.MatchesExtension(FILE_PATH_LITERAL(".jpg"))) {
return "image/jpeg";
diff --git a/chromium/net/test/net_test_suite.cc b/chromium/net/test/net_test_suite.cc
index a657d26df6b..561f149488e 100644
--- a/chromium/net/test/net_test_suite.cc
+++ b/chromium/net/test/net_test_suite.cc
@@ -10,7 +10,7 @@
#include "net/spdy/spdy_session.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
#include "net/cert_net/nss_ocsp.h"
#endif
@@ -33,7 +33,7 @@ void NetTestSuite::Initialize() {
}
void NetTestSuite::Shutdown() {
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
net::ShutdownNSSHttpIO();
#endif
diff --git a/chromium/net/test/run_all_unittests.cc b/chromium/net/test/run_all_unittests.cc
index 87f757ac402..e5ea90043b7 100644
--- a/chromium/net/test/run_all_unittests.cc
+++ b/chromium/net/test/run_all_unittests.cc
@@ -21,11 +21,11 @@
#endif
#if defined(USE_ICU_ALTERNATIVES_ON_ANDROID)
-#include "url/android/url_jni_registrar.h"
+#include "url/android/url_jni_registrar.h" // nogncheck
#endif
#if !defined(OS_ANDROID) && !defined(OS_IOS)
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/embedder.h" // nogncheck
#endif
using net::internal::ClientSocketPoolBaseHelper;
@@ -68,7 +68,7 @@ int main(int argc, char** argv) {
net::EnableSSLServerSockets();
#if !defined(OS_ANDROID) && !defined(OS_IOS)
- mojo::embedder::Init();
+ mojo::edk::Init();
#endif
return base::LaunchUnitTests(
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 e69233e5a61..ecf5af5d636 100644
--- a/chromium/net/test/spawned_test_server/base_test_server.cc
+++ b/chromium/net/test/spawned_test_server/base_test_server.cc
@@ -159,6 +159,8 @@ BaseTestServer::SSLOptions::SSLOptions(
disable_channel_id(false),
disable_extended_master_secret(false) {}
+BaseTestServer::SSLOptions::SSLOptions(const SSLOptions& other) = default;
+
BaseTestServer::SSLOptions::~SSLOptions() {}
base::FilePath BaseTestServer::SSLOptions::GetCertificateFile() const {
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 7df24163713..60d37e1206f 100644
--- a/chromium/net/test/spawned_test_server/base_test_server.h
+++ b/chromium/net/test/spawned_test_server/base_test_server.h
@@ -140,6 +140,7 @@ class BaseTestServer {
// Initialize a new SSLOptions that will use the specified certificate.
explicit SSLOptions(ServerCertificate cert);
+ SSLOptions(const SSLOptions& other);
~SSLOptions();
// Returns the relative filename of the file that contains the
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 d7c479b14f7..890a0614261 100644
--- a/chromium/net/test/url_request/url_request_failed_job.cc
+++ b/chromium/net/test/url_request/url_request_failed_job.cc
@@ -181,7 +181,6 @@ void URLRequestFailedJob::StartAsync() {
NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, net_error_));
return;
}
- SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
return;
}
response_info_.headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK");
diff --git a/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp b/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp
index f239cc14c3d..51d15bd0426 100644
--- a/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp
+++ b/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp
@@ -215,9 +215,9 @@ std::string GenKeyAndSignChallenge(int key_size_in_bits,
}
// Convert the signed public key and challenge into base64/ascii.
- base::Base64Encode(
- std::string(reinterpret_cast<char*>(signedItem.data), signedItem.len),
- &result_blob);
+ base::Base64Encode(base::StringPiece(reinterpret_cast<char*>(signedItem.data),
+ signedItem.len),
+ &result_blob);
failure:
if (!isSuccess) {
diff --git a/chromium/net/third_party/nist-pkits/BUILD.gn b/chromium/net/third_party/nist-pkits/BUILD.gn
new file mode 100644
index 00000000000..a1d8b3f6c95
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/BUILD.gn
@@ -0,0 +1,12 @@
+# 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.
+
+# Depend on this to get the data deps necessary to run the PKITS tests in the
+# test environment.
+group("nist-pkits") {
+ data = [
+ "certs/",
+ "crls/",
+ ]
+}
diff --git a/chromium/net/third_party/nist-pkits/README.chromium b/chromium/net/third_party/nist-pkits/README.chromium
new file mode 100644
index 00000000000..b017b54365c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/README.chromium
@@ -0,0 +1,19 @@
+Name: NIST Public Key Interoperability Test Suite
+Short Name: NIST PKITS
+URL: http://csrc.nist.gov/groups/ST/crypto_apps_infra/pki/pkitesting.html
+Version: 1.0.1
+Date: April 14, 2011
+License: Public Domain: United States Government Work under 17 U.S.C. 105
+License File: NOT_SHIPPED
+
+Description:
+The Public Key Interoperability Test Suite (PKITS) is a comprehensive X.509
+path validation test suite that was developed by NIST in conjunction with BAE
+Systems and NSA. The PKITS path validation test suite is designed to cover
+most of the features specified in X.509 and RFC 3280.
+
+Local Modifications:
+Only the certs/ and crls/ directories were extracted from PKITS_data.zip.
+
+pkits_testcases-inl.h is generated from the test descriptions in PKITS.pdf
+using generate_tests.py.
diff --git a/chromium/net/third_party/nist-pkits/certs/AllCertificatesNoPoliciesTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/AllCertificatesNoPoliciesTest2EE.crt
new file mode 100644
index 00000000000..ae6be6c4c8f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/AllCertificatesNoPoliciesTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/AllCertificatesSamePoliciesTest10EE.crt b/chromium/net/third_party/nist-pkits/certs/AllCertificatesSamePoliciesTest10EE.crt
new file mode 100644
index 00000000000..e36fdb8fc37
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/AllCertificatesSamePoliciesTest10EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/AllCertificatesSamePoliciesTest13EE.crt b/chromium/net/third_party/nist-pkits/certs/AllCertificatesSamePoliciesTest13EE.crt
new file mode 100644
index 00000000000..c296e5a4308
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/AllCertificatesSamePoliciesTest13EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/AllCertificatesanyPolicyTest11EE.crt b/chromium/net/third_party/nist-pkits/certs/AllCertificatesanyPolicyTest11EE.crt
new file mode 100644
index 00000000000..7439f85152a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/AllCertificatesanyPolicyTest11EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/AnyPolicyTest14EE.crt b/chromium/net/third_party/nist-pkits/certs/AnyPolicyTest14EE.crt
new file mode 100644
index 00000000000..a6cf3528fa3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/AnyPolicyTest14EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/BadCRLIssuerNameCACert.crt b/chromium/net/third_party/nist-pkits/certs/BadCRLIssuerNameCACert.crt
new file mode 100644
index 00000000000..05e4b3ddbe8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/BadCRLIssuerNameCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/BadCRLSignatureCACert.crt b/chromium/net/third_party/nist-pkits/certs/BadCRLSignatureCACert.crt
new file mode 100644
index 00000000000..6dfa00d6b8e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/BadCRLSignatureCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/BadSignedCACert.crt b/chromium/net/third_party/nist-pkits/certs/BadSignedCACert.crt
new file mode 100644
index 00000000000..0a598fcb8eb
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/BadSignedCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/BadnotAfterDateCACert.crt b/chromium/net/third_party/nist-pkits/certs/BadnotAfterDateCACert.crt
new file mode 100644
index 00000000000..7a7dcec6651
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/BadnotAfterDateCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/BadnotBeforeDateCACert.crt b/chromium/net/third_party/nist-pkits/certs/BadnotBeforeDateCACert.crt
new file mode 100644
index 00000000000..33cfbd7ce8c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/BadnotBeforeDateCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCACert.crt b/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCACert.crt
new file mode 100644
index 00000000000..4e1245299d4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt b/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt
new file mode 100644
index 00000000000..7f86064c26b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedNewKeyCACert.crt b/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedNewKeyCACert.crt
new file mode 100644
index 00000000000..1f83cb863f1
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedNewKeyCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt b/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt
new file mode 100644
index 00000000000..8773e48464c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedOldKeyCACert.crt b/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedOldKeyCACert.crt
new file mode 100644
index 00000000000..b00748cc262
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedOldKeyCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt b/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt
new file mode 100644
index 00000000000..963f57a485d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/CPSPointerQualifierTest20EE.crt b/chromium/net/third_party/nist-pkits/certs/CPSPointerQualifierTest20EE.crt
new file mode 100644
index 00000000000..706d98d63b8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/CPSPointerQualifierTest20EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/DSACACert.crt b/chromium/net/third_party/nist-pkits/certs/DSACACert.crt
new file mode 100644
index 00000000000..14787b05801
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/DSACACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/DSAParametersInheritedCACert.crt b/chromium/net/third_party/nist-pkits/certs/DSAParametersInheritedCACert.crt
new file mode 100644
index 00000000000..5e2fa5bc921
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/DSAParametersInheritedCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest12EE.crt b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest12EE.crt
new file mode 100644
index 00000000000..7873bd8d367
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest12EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest3EE.crt
new file mode 100644
index 00000000000..57f1df4334e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest4EE.crt
new file mode 100644
index 00000000000..4967f41d302
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest5EE.crt
new file mode 100644
index 00000000000..b6d31236e2c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest7EE.crt
new file mode 100644
index 00000000000..4c9c82bbcda
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest8EE.crt
new file mode 100644
index 00000000000..6c01f377f46
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest9EE.crt b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest9EE.crt
new file mode 100644
index 00000000000..b2e30bd6921
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/DifferentPoliciesTest9EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/GeneralizedTimeCRLnextUpdateCACert.crt b/chromium/net/third_party/nist-pkits/certs/GeneralizedTimeCRLnextUpdateCACert.crt
new file mode 100644
index 00000000000..f4acda66ec5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/GeneralizedTimeCRLnextUpdateCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/GoodCACert.crt b/chromium/net/third_party/nist-pkits/certs/GoodCACert.crt
new file mode 100644
index 00000000000..edbfa648f24
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/GoodCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/GoodsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/GoodsubCACert.crt
new file mode 100644
index 00000000000..7a770c31ae7
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/GoodsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt b/chromium/net/third_party/nist-pkits/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt
new file mode 100644
index 00000000000..9f4d95f3953
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidBadCRLIssuerNameTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidBadCRLIssuerNameTest5EE.crt
new file mode 100644
index 00000000000..e24d88d444d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidBadCRLIssuerNameTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidBadCRLSignatureTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidBadCRLSignatureTest4EE.crt
new file mode 100644
index 00000000000..4b35bd248ed
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidBadCRLSignatureTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt
new file mode 100644
index 00000000000..348df8fe0db
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt
new file mode 100644
index 00000000000..3ca79954600
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt
new file mode 100644
index 00000000000..6cc192b8ba2
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt
new file mode 100644
index 00000000000..18033bc34b0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidCASignatureTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidCASignatureTest2EE.crt
new file mode 100644
index 00000000000..1f4ad3e1a15
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidCASignatureTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidCAnotAfterDateTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidCAnotAfterDateTest5EE.crt
new file mode 100644
index 00000000000..a9938aa80e9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidCAnotAfterDateTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidCAnotBeforeDateTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidCAnotBeforeDateTest1EE.crt
new file mode 100644
index 00000000000..f15d6a9ed22
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidCAnotBeforeDateTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNSnameConstraintsTest31EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNSnameConstraintsTest31EE.crt
new file mode 100644
index 00000000000..5f7ad1535aa
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNSnameConstraintsTest31EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNSnameConstraintsTest33EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNSnameConstraintsTest33EE.crt
new file mode 100644
index 00000000000..fa59d6fbd0d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNSnameConstraintsTest33EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNSnameConstraintsTest38EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNSnameConstraintsTest38EE.crt
new file mode 100644
index 00000000000..334fed1f111
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNSnameConstraintsTest38EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt
new file mode 100644
index 00000000000..f724473de87
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt
new file mode 100644
index 00000000000..468cb7bede2
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest10EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest10EE.crt
new file mode 100644
index 00000000000..806ebf3ce7f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest10EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest12EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest12EE.crt
new file mode 100644
index 00000000000..5f3a49f93e4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest12EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest13EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest13EE.crt
new file mode 100644
index 00000000000..d64ddf53c7a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest13EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest15EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest15EE.crt
new file mode 100644
index 00000000000..fd864ced34c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest15EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest16EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest16EE.crt
new file mode 100644
index 00000000000..455658dbc97
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest16EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest17EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest17EE.crt
new file mode 100644
index 00000000000..63f262b99fb
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest17EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest20EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest20EE.crt
new file mode 100644
index 00000000000..a7ef3220436
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest20EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest2EE.crt
new file mode 100644
index 00000000000..3fd895c9242
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest3EE.crt
new file mode 100644
index 00000000000..decbf34aace
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest7EE.crt
new file mode 100644
index 00000000000..6ac76654e5e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest8EE.crt
new file mode 100644
index 00000000000..48adc0a6d55
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest9EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest9EE.crt
new file mode 100644
index 00000000000..ed753d42e66
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDNnameConstraintsTest9EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidDSASignatureTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidDSASignatureTest6EE.crt
new file mode 100644
index 00000000000..a1725b19dac
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidDSASignatureTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidEESignatureTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidEESignatureTest3EE.crt
new file mode 100644
index 00000000000..9238109b646
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidEESignatureTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidEEnotAfterDateTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidEEnotAfterDateTest6EE.crt
new file mode 100644
index 00000000000..af6fdf8c5a9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidEEnotAfterDateTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidEEnotBeforeDateTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidEEnotBeforeDateTest2EE.crt
new file mode 100644
index 00000000000..3ddef09cabf
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidEEnotBeforeDateTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidIDPwithindirectCRLTest23EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidIDPwithindirectCRLTest23EE.crt
new file mode 100644
index 00000000000..5cf92f7ce45
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidIDPwithindirectCRLTest23EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidIDPwithindirectCRLTest26EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidIDPwithindirectCRLTest26EE.crt
new file mode 100644
index 00000000000..c4b45f87831
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidIDPwithindirectCRLTest26EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidLongSerialNumberTest18EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidLongSerialNumberTest18EE.crt
new file mode 100644
index 00000000000..56b1ab45831
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidLongSerialNumberTest18EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidMappingFromanyPolicyTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidMappingFromanyPolicyTest7EE.crt
new file mode 100644
index 00000000000..eec4c3c3a6d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidMappingFromanyPolicyTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidMappingToanyPolicyTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidMappingToanyPolicyTest8EE.crt
new file mode 100644
index 00000000000..ee6914c15ab
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidMappingToanyPolicyTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidMissingCRLTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidMissingCRLTest1EE.crt
new file mode 100644
index 00000000000..30b02759033
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidMissingCRLTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidMissingbasicConstraintsTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidMissingbasicConstraintsTest1EE.crt
new file mode 100644
index 00000000000..80ba7a03dd1
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidMissingbasicConstraintsTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidNameChainingOrderTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidNameChainingOrderTest2EE.crt
new file mode 100644
index 00000000000..6b7d7de29c6
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidNameChainingOrderTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidNameChainingTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidNameChainingTest1EE.crt
new file mode 100644
index 00000000000..ee18fa08fbb
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidNameChainingTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidNegativeSerialNumberTest15EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidNegativeSerialNumberTest15EE.crt
new file mode 100644
index 00000000000..2c479ca231f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidNegativeSerialNumberTest15EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidOldCRLnextUpdateTest11EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidOldCRLnextUpdateTest11EE.crt
new file mode 100644
index 00000000000..1ec410d7554
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidOldCRLnextUpdateTest11EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidPolicyMappingTest10EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidPolicyMappingTest10EE.crt
new file mode 100644
index 00000000000..053a608d7e6
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidPolicyMappingTest10EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidPolicyMappingTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidPolicyMappingTest2EE.crt
new file mode 100644
index 00000000000..1ed661582c4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidPolicyMappingTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidPolicyMappingTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidPolicyMappingTest4EE.crt
new file mode 100644
index 00000000000..a194a040a70
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidPolicyMappingTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidRFC822nameConstraintsTest22EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidRFC822nameConstraintsTest22EE.crt
new file mode 100644
index 00000000000..c9ad311ac0a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidRFC822nameConstraintsTest22EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidRFC822nameConstraintsTest24EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidRFC822nameConstraintsTest24EE.crt
new file mode 100644
index 00000000000..28ef8f7491e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidRFC822nameConstraintsTest24EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidRFC822nameConstraintsTest26EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidRFC822nameConstraintsTest26EE.crt
new file mode 100644
index 00000000000..0e7f71937a5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidRFC822nameConstraintsTest26EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidRevokedCATest2EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidRevokedCATest2EE.crt
new file mode 100644
index 00000000000..80545971141
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidRevokedCATest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidRevokedEETest3EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidRevokedEETest3EE.crt
new file mode 100644
index 00000000000..455cb0240c4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidRevokedEETest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt
new file mode 100644
index 00000000000..2e85ce5c21c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt
new file mode 100644
index 00000000000..ee48b7fc85e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt
new file mode 100644
index 00000000000..e729fe77cda
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt
new file mode 100644
index 00000000000..103e0940fe5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt
new file mode 100644
index 00000000000..3eaa74deb81
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt
new file mode 100644
index 00000000000..1a1da9fe7a0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt
new file mode 100644
index 00000000000..2ff84b8b7d3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt
new file mode 100644
index 00000000000..d4050e6f4f0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt
new file mode 100644
index 00000000000..77b6a3c1472
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt
new file mode 100644
index 00000000000..2cbab480b15
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt
new file mode 100644
index 00000000000..e703d679051
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidURInameConstraintsTest35EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidURInameConstraintsTest35EE.crt
new file mode 100644
index 00000000000..65096685fe2
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidURInameConstraintsTest35EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidURInameConstraintsTest37EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidURInameConstraintsTest37EE.crt
new file mode 100644
index 00000000000..e64db473af5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidURInameConstraintsTest37EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt
new file mode 100644
index 00000000000..8630e99cb24
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidUnknownCRLExtensionTest10EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidUnknownCRLExtensionTest10EE.crt
new file mode 100644
index 00000000000..42fda8fc122
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidUnknownCRLExtensionTest10EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidUnknownCRLExtensionTest9EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidUnknownCRLExtensionTest9EE.crt
new file mode 100644
index 00000000000..c3f93b5bd7c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidUnknownCRLExtensionTest9EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt
new file mode 100644
index 00000000000..9200cccb39a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidWrongCRLTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidWrongCRLTest6EE.crt
new file mode 100644
index 00000000000..148f9fb23ab
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidWrongCRLTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidcAFalseTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidcAFalseTest2EE.crt
new file mode 100644
index 00000000000..3d5b82946bc
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidcAFalseTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidcAFalseTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidcAFalseTest3EE.crt
new file mode 100644
index 00000000000..f791140ceda
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidcAFalseTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest27EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest27EE.crt
new file mode 100644
index 00000000000..2433e3b95e1
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest27EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest31EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest31EE.crt
new file mode 100644
index 00000000000..210bb41fef9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest31EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest32EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest32EE.crt
new file mode 100644
index 00000000000..5509dda847d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest32EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest34EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest34EE.crt
new file mode 100644
index 00000000000..8b9041f5ba4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest34EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest35EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest35EE.crt
new file mode 100644
index 00000000000..32e72a225ec
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidcRLIssuerTest35EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt
new file mode 100644
index 00000000000..10da3212470
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest10EE.crt b/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest10EE.crt
new file mode 100644
index 00000000000..d60812c6a41
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest10EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest3EE.crt
new file mode 100644
index 00000000000..6b3c374331d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest4EE.crt
new file mode 100644
index 00000000000..b9594149344
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest6EE.crt
new file mode 100644
index 00000000000..ea141b173af
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest9EE.crt b/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest9EE.crt
new file mode 100644
index 00000000000..de4da9d69b0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvaliddeltaCRLTest9EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest2EE.crt
new file mode 100644
index 00000000000..a60b030e9e0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest3EE.crt
new file mode 100644
index 00000000000..bbb8271d6bb
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest6EE.crt
new file mode 100644
index 00000000000..a47f7b20856
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest8EE.crt
new file mode 100644
index 00000000000..af3a366dd74
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest9EE.crt b/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest9EE.crt
new file mode 100644
index 00000000000..3456831e0b9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvaliddistributionPointTest9EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest1EE.crt
new file mode 100644
index 00000000000..828203b11c7
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest4EE.crt
new file mode 100644
index 00000000000..2ffd9dd8ce5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest5EE.crt
new file mode 100644
index 00000000000..2fc212d33ed
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest6EE.crt
new file mode 100644
index 00000000000..9aafebfc25f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitAnyPolicyTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest1EE.crt
new file mode 100644
index 00000000000..65ca6340ea6
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest3EE.crt
new file mode 100644
index 00000000000..c8b06f07e40
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest5EE.crt
new file mode 100644
index 00000000000..f3526efb69f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest6EE.crt
new file mode 100644
index 00000000000..733c152685d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidinhibitPolicyMappingTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt
new file mode 100644
index 00000000000..cfddd3a4359
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt
new file mode 100644
index 00000000000..16c103f7446
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt
new file mode 100644
index 00000000000..5583f19690c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt
new file mode 100644
index 00000000000..f3062e9e480
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidonlyContainsAttributeCertsTest14EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidonlyContainsAttributeCertsTest14EE.crt
new file mode 100644
index 00000000000..279306ed188
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidonlyContainsAttributeCertsTest14EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidonlyContainsCACertsTest12EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidonlyContainsCACertsTest12EE.crt
new file mode 100644
index 00000000000..f206348963c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidonlyContainsCACertsTest12EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidonlyContainsUserCertsTest11EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidonlyContainsUserCertsTest11EE.crt
new file mode 100644
index 00000000000..ecf51285fa4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidonlyContainsUserCertsTest11EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest15EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest15EE.crt
new file mode 100644
index 00000000000..f536fc6d2bd
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest15EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest16EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest16EE.crt
new file mode 100644
index 00000000000..af5aa4b0d41
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest16EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest17EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest17EE.crt
new file mode 100644
index 00000000000..59722f96227
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest17EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest20EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest20EE.crt
new file mode 100644
index 00000000000..4a0f1916509
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest20EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest21EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest21EE.crt
new file mode 100644
index 00000000000..59a02de9d78
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidonlySomeReasonsTest21EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest10EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest10EE.crt
new file mode 100644
index 00000000000..447115e6368
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest10EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest11EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest11EE.crt
new file mode 100644
index 00000000000..c28c455abbe
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest11EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest12EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest12EE.crt
new file mode 100644
index 00000000000..dc6d0dda96a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest12EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest5EE.crt
new file mode 100644
index 00000000000..b8830a24055
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest6EE.crt
new file mode 100644
index 00000000000..b96d3c626fd
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest9EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest9EE.crt
new file mode 100644
index 00000000000..c339f6fae75
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidpathLenConstraintTest9EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/Invalidpre2000CRLnextUpdateTest12EE.crt b/chromium/net/third_party/nist-pkits/certs/Invalidpre2000CRLnextUpdateTest12EE.crt
new file mode 100644
index 00000000000..3e1ba073e13
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/Invalidpre2000CRLnextUpdateTest12EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt
new file mode 100644
index 00000000000..4a7e31caf02
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidrequireExplicitPolicyTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidrequireExplicitPolicyTest3EE.crt
new file mode 100644
index 00000000000..e9b7cf2510f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidrequireExplicitPolicyTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/InvalidrequireExplicitPolicyTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/InvalidrequireExplicitPolicyTest5EE.crt
new file mode 100644
index 00000000000..971d0a5de61
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/InvalidrequireExplicitPolicyTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/LongSerialNumberCACert.crt b/chromium/net/third_party/nist-pkits/certs/LongSerialNumberCACert.crt
new file mode 100644
index 00000000000..12830d90697
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/LongSerialNumberCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/Mapping1to2CACert.crt b/chromium/net/third_party/nist-pkits/certs/Mapping1to2CACert.crt
new file mode 100644
index 00000000000..4b70c9a4fc0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/Mapping1to2CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/MappingFromanyPolicyCACert.crt b/chromium/net/third_party/nist-pkits/certs/MappingFromanyPolicyCACert.crt
new file mode 100644
index 00000000000..0a8f1e98114
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/MappingFromanyPolicyCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/MappingToanyPolicyCACert.crt b/chromium/net/third_party/nist-pkits/certs/MappingToanyPolicyCACert.crt
new file mode 100644
index 00000000000..d93d8c79c98
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/MappingToanyPolicyCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/MissingbasicConstraintsCACert.crt b/chromium/net/third_party/nist-pkits/certs/MissingbasicConstraintsCACert.crt
new file mode 100644
index 00000000000..e6f41a446b3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/MissingbasicConstraintsCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/NameOrderingCACert.crt b/chromium/net/third_party/nist-pkits/certs/NameOrderingCACert.crt
new file mode 100644
index 00000000000..f1c4a55fbf5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/NameOrderingCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/NegativeSerialNumberCACert.crt b/chromium/net/third_party/nist-pkits/certs/NegativeSerialNumberCACert.crt
new file mode 100644
index 00000000000..1a4d9ba374c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/NegativeSerialNumberCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/NoCRLCACert.crt b/chromium/net/third_party/nist-pkits/certs/NoCRLCACert.crt
new file mode 100644
index 00000000000..71c607dac44
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/NoCRLCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/NoPoliciesCACert.crt b/chromium/net/third_party/nist-pkits/certs/NoPoliciesCACert.crt
new file mode 100644
index 00000000000..3a94cb157d2
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/NoPoliciesCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/NoissuingDistributionPointCACert.crt b/chromium/net/third_party/nist-pkits/certs/NoissuingDistributionPointCACert.crt
new file mode 100644
index 00000000000..c4f182ad7f9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/NoissuingDistributionPointCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/OldCRLnextUpdateCACert.crt b/chromium/net/third_party/nist-pkits/certs/OldCRLnextUpdateCACert.crt
new file mode 100644
index 00000000000..2666670afb5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/OldCRLnextUpdateCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/OverlappingPoliciesTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/OverlappingPoliciesTest6EE.crt
new file mode 100644
index 00000000000..82b5b5e0ee1
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/OverlappingPoliciesTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/P12Mapping1to3CACert.crt b/chromium/net/third_party/nist-pkits/certs/P12Mapping1to3CACert.crt
new file mode 100644
index 00000000000..9139bd730d3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/P12Mapping1to3CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/P12Mapping1to3subCACert.crt b/chromium/net/third_party/nist-pkits/certs/P12Mapping1to3subCACert.crt
new file mode 100644
index 00000000000..3b9c2a751c4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/P12Mapping1to3subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/P12Mapping1to3subsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/P12Mapping1to3subsubCACert.crt
new file mode 100644
index 00000000000..91fc36a7273
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/P12Mapping1to3subsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/P1Mapping1to234CACert.crt b/chromium/net/third_party/nist-pkits/certs/P1Mapping1to234CACert.crt
new file mode 100644
index 00000000000..3500737ab8e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/P1Mapping1to234CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/P1Mapping1to234subCACert.crt b/chromium/net/third_party/nist-pkits/certs/P1Mapping1to234subCACert.crt
new file mode 100644
index 00000000000..eb900ebc1cb
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/P1Mapping1to234subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/P1anyPolicyMapping1to2CACert.crt b/chromium/net/third_party/nist-pkits/certs/P1anyPolicyMapping1to2CACert.crt
new file mode 100644
index 00000000000..3818b6a7f51
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/P1anyPolicyMapping1to2CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PanyPolicyMapping1to2CACert.crt b/chromium/net/third_party/nist-pkits/certs/PanyPolicyMapping1to2CACert.crt
new file mode 100644
index 00000000000..db220487cc0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PanyPolicyMapping1to2CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP1234CACert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP1234CACert.crt
new file mode 100644
index 00000000000..36cf4ce24ea
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP1234CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP1234subCAP123Cert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP1234subCAP123Cert.crt
new file mode 100644
index 00000000000..1ab7ab104f6
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP1234subCAP123Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP1234subsubCAP123P12Cert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP1234subsubCAP123P12Cert.crt
new file mode 100644
index 00000000000..df834464bba
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP1234subsubCAP123P12Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP123CACert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP123CACert.crt
new file mode 100644
index 00000000000..26262a3d72f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP123CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP123subCAP12Cert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP123subCAP12Cert.crt
new file mode 100644
index 00000000000..cef6abeb29c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP123subCAP12Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP123subsubCAP12P1Cert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP123subsubCAP12P1Cert.crt
new file mode 100644
index 00000000000..49e66b5be01
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP123subsubCAP12P1Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP123subsubCAP12P2Cert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP123subsubCAP12P2Cert.crt
new file mode 100644
index 00000000000..d7b5a42353b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP123subsubCAP12P2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt
new file mode 100644
index 00000000000..3a79422477f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP12CACert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP12CACert.crt
new file mode 100644
index 00000000000..dc1b60de0e8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP12CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP12subCAP1Cert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP12subCAP1Cert.crt
new file mode 100644
index 00000000000..081f951b80d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP12subCAP1Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP12subsubCAP1P2Cert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP12subsubCAP1P2Cert.crt
new file mode 100644
index 00000000000..e8d0bb8ba8d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP12subsubCAP1P2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP2subCA2Cert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP2subCA2Cert.crt
new file mode 100644
index 00000000000..c734009d050
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP2subCA2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP2subCACert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP2subCACert.crt
new file mode 100644
index 00000000000..0f3fbbb01a1
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP2subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/PoliciesP3CACert.crt b/chromium/net/third_party/nist-pkits/certs/PoliciesP3CACert.crt
new file mode 100644
index 00000000000..9740b309d40
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/PoliciesP3CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/RFC3280MandatoryAttributeTypesCACert.crt b/chromium/net/third_party/nist-pkits/certs/RFC3280MandatoryAttributeTypesCACert.crt
new file mode 100644
index 00000000000..9c648a30be0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/RFC3280MandatoryAttributeTypesCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/RFC3280OptionalAttributeTypesCACert.crt b/chromium/net/third_party/nist-pkits/certs/RFC3280OptionalAttributeTypesCACert.crt
new file mode 100644
index 00000000000..306303a8465
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/RFC3280OptionalAttributeTypesCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/RevokedsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/RevokedsubCACert.crt
new file mode 100644
index 00000000000..25705b2f670
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/RevokedsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt b/chromium/net/third_party/nist-pkits/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt
new file mode 100644
index 00000000000..32ddfe3e315
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt b/chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt
new file mode 100644
index 00000000000..17b3cbba30f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt b/chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt
new file mode 100644
index 00000000000..d747ea1fe51
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt b/chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt
new file mode 100644
index 00000000000..3c1730f41ab
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt b/chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt
new file mode 100644
index 00000000000..e75eb4cd707
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/TrustAnchorRootCertificate.crt b/chromium/net/third_party/nist-pkits/certs/TrustAnchorRootCertificate.crt
new file mode 100644
index 00000000000..04efaa0659b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/TrustAnchorRootCertificate.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/TwoCRLsCACert.crt b/chromium/net/third_party/nist-pkits/certs/TwoCRLsCACert.crt
new file mode 100644
index 00000000000..28eb60a0713
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/TwoCRLsCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/UIDCACert.crt b/chromium/net/third_party/nist-pkits/certs/UIDCACert.crt
new file mode 100644
index 00000000000..ec04d744557
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/UIDCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/UTF8StringCaseInsensitiveMatchCACert.crt b/chromium/net/third_party/nist-pkits/certs/UTF8StringCaseInsensitiveMatchCACert.crt
new file mode 100644
index 00000000000..2d653ef65b1
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/UTF8StringCaseInsensitiveMatchCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/UTF8StringEncodedNamesCACert.crt b/chromium/net/third_party/nist-pkits/certs/UTF8StringEncodedNamesCACert.crt
new file mode 100644
index 00000000000..ae2ce8a7b49
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/UTF8StringEncodedNamesCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/UnknownCRLEntryExtensionCACert.crt b/chromium/net/third_party/nist-pkits/certs/UnknownCRLEntryExtensionCACert.crt
new file mode 100644
index 00000000000..69128811ba3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/UnknownCRLEntryExtensionCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/UnknownCRLExtensionCACert.crt b/chromium/net/third_party/nist-pkits/certs/UnknownCRLExtensionCACert.crt
new file mode 100644
index 00000000000..2e2c3ef3d69
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/UnknownCRLExtensionCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest15EE.crt b/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest15EE.crt
new file mode 100644
index 00000000000..afb3455e36b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest15EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest16EE.crt b/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest16EE.crt
new file mode 100644
index 00000000000..7d3bcc5d0bc
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest16EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest17EE.crt b/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest17EE.crt
new file mode 100644
index 00000000000..5fefe199444
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest17EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest18EE.crt b/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest18EE.crt
new file mode 100644
index 00000000000..1168b580e8c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest18EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest19EE.crt b/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest19EE.crt
new file mode 100644
index 00000000000..3cb86cd1ce6
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/UserNoticeQualifierTest19EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt
new file mode 100644
index 00000000000..c91b9f3665c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt
new file mode 100644
index 00000000000..34197f03601
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt
new file mode 100644
index 00000000000..9a7919b00ac
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt
new file mode 100644
index 00000000000..038e4d7a80a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidCertificatePathTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidCertificatePathTest1EE.crt
new file mode 100644
index 00000000000..69ba3019d4b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidCertificatePathTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDNSnameConstraintsTest30EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDNSnameConstraintsTest30EE.crt
new file mode 100644
index 00000000000..e5235c7ff25
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDNSnameConstraintsTest30EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDNSnameConstraintsTest32EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDNSnameConstraintsTest32EE.crt
new file mode 100644
index 00000000000..8bc3e87b9fc
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDNSnameConstraintsTest32EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDNandRFC822nameConstraintsTest27EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDNandRFC822nameConstraintsTest27EE.crt
new file mode 100644
index 00000000000..2332d4c189a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDNandRFC822nameConstraintsTest27EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest11EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest11EE.crt
new file mode 100644
index 00000000000..f8fe1223249
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest11EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest14EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest14EE.crt
new file mode 100644
index 00000000000..4364e1bcbf5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest14EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest18EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest18EE.crt
new file mode 100644
index 00000000000..3b5ac8be530
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest18EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest19EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest19EE.crt
new file mode 100644
index 00000000000..20fa140e19d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest19EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest1EE.crt
new file mode 100644
index 00000000000..c59e921bac7
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest4EE.crt
new file mode 100644
index 00000000000..c6cfcbb7786
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest5EE.crt
new file mode 100644
index 00000000000..f2c4dfc553f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest6EE.crt
new file mode 100644
index 00000000000..675711970ce
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDNnameConstraintsTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDSAParameterInheritanceTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDSAParameterInheritanceTest5EE.crt
new file mode 100644
index 00000000000..d8b6ce36d0d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDSAParameterInheritanceTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidDSASignaturesTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidDSASignaturesTest4EE.crt
new file mode 100644
index 00000000000..2fc40a6c2f3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidDSASignaturesTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt
new file mode 100644
index 00000000000..7f77ee81965
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt
new file mode 100644
index 00000000000..f97ed0a3e95
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt
new file mode 100644
index 00000000000..2ef73e1f697
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidIDPwithindirectCRLTest22EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidIDPwithindirectCRLTest22EE.crt
new file mode 100644
index 00000000000..66296ac7e75
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidIDPwithindirectCRLTest22EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidIDPwithindirectCRLTest24EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidIDPwithindirectCRLTest24EE.crt
new file mode 100644
index 00000000000..0a1b85dc680
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidIDPwithindirectCRLTest24EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidIDPwithindirectCRLTest25EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidIDPwithindirectCRLTest25EE.crt
new file mode 100644
index 00000000000..6f69c0c8bca
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidIDPwithindirectCRLTest25EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidLongSerialNumberTest16EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidLongSerialNumberTest16EE.crt
new file mode 100644
index 00000000000..44e890546d5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidLongSerialNumberTest16EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidLongSerialNumberTest17EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidLongSerialNumberTest17EE.crt
new file mode 100644
index 00000000000..96186587225
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidLongSerialNumberTest17EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidNameChainingCapitalizationTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidNameChainingCapitalizationTest5EE.crt
new file mode 100644
index 00000000000..c0a6b3d03ec
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidNameChainingCapitalizationTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidNameChainingWhitespaceTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidNameChainingWhitespaceTest3EE.crt
new file mode 100644
index 00000000000..fc0f65d0796
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidNameChainingWhitespaceTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidNameChainingWhitespaceTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidNameChainingWhitespaceTest4EE.crt
new file mode 100644
index 00000000000..a8ffc872cae
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidNameChainingWhitespaceTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidNameUIDsTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidNameUIDsTest6EE.crt
new file mode 100644
index 00000000000..7d0b7061137
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidNameUIDsTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidNegativeSerialNumberTest14EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidNegativeSerialNumberTest14EE.crt
new file mode 100644
index 00000000000..ab39228409f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidNegativeSerialNumberTest14EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidNoissuingDistributionPointTest10EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidNoissuingDistributionPointTest10EE.crt
new file mode 100644
index 00000000000..89eac753f30
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidNoissuingDistributionPointTest10EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest11EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest11EE.crt
new file mode 100644
index 00000000000..865c97542ee
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest11EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest12EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest12EE.crt
new file mode 100644
index 00000000000..eb4306ab5a6
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest12EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest13EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest13EE.crt
new file mode 100644
index 00000000000..2d1b18c33f4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest13EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest14EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest14EE.crt
new file mode 100644
index 00000000000..2487d626f7f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest14EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest1EE.crt
new file mode 100644
index 00000000000..f2bd7d381de
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest3EE.crt
new file mode 100644
index 00000000000..e941bbbad00
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest5EE.crt
new file mode 100644
index 00000000000..d084fc72158
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest6EE.crt
new file mode 100644
index 00000000000..97dd2e72c11
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest9EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest9EE.crt
new file mode 100644
index 00000000000..ef1ac897e08
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidPolicyMappingTest9EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt
new file mode 100644
index 00000000000..15825d7eb3b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt
new file mode 100644
index 00000000000..60a20316813
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidRFC822nameConstraintsTest21EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidRFC822nameConstraintsTest21EE.crt
new file mode 100644
index 00000000000..576a1b81716
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidRFC822nameConstraintsTest21EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidRFC822nameConstraintsTest23EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidRFC822nameConstraintsTest23EE.crt
new file mode 100644
index 00000000000..c0ff7596a09
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidRFC822nameConstraintsTest23EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidRFC822nameConstraintsTest25EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidRFC822nameConstraintsTest25EE.crt
new file mode 100644
index 00000000000..75f67b73c86
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidRFC822nameConstraintsTest25EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt
new file mode 100644
index 00000000000..0a4e150700f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt
new file mode 100644
index 00000000000..16968ab59b1
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt
new file mode 100644
index 00000000000..1516f1ee703
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt
new file mode 100644
index 00000000000..a4385c1d959
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt
new file mode 100644
index 00000000000..1cb0924ec36
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt
new file mode 100644
index 00000000000..ed346760878
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt
new file mode 100644
index 00000000000..44e5c1e2532
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt
new file mode 100644
index 00000000000..08260919768
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidTwoCRLsTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidTwoCRLsTest7EE.crt
new file mode 100644
index 00000000000..c42779d70ce
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidTwoCRLsTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidURInameConstraintsTest34EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidURInameConstraintsTest34EE.crt
new file mode 100644
index 00000000000..be8ef42f19a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidURInameConstraintsTest34EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidURInameConstraintsTest36EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidURInameConstraintsTest36EE.crt
new file mode 100644
index 00000000000..6a24838f5dc
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidURInameConstraintsTest36EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt
new file mode 100644
index 00000000000..d1f80a74a4b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidUTF8StringEncodedNamesTest9EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidUTF8StringEncodedNamesTest9EE.crt
new file mode 100644
index 00000000000..b14d789b5dc
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidUTF8StringEncodedNamesTest9EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt
new file mode 100644
index 00000000000..d55dcb1a6f4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidbasicConstraintsNotCriticalTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidbasicConstraintsNotCriticalTest4EE.crt
new file mode 100644
index 00000000000..4059c017a74
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidbasicConstraintsNotCriticalTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest28EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest28EE.crt
new file mode 100644
index 00000000000..9145515308c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest28EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest29EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest29EE.crt
new file mode 100644
index 00000000000..b10632b2093
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest29EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest30EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest30EE.crt
new file mode 100644
index 00000000000..593ef98e350
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest30EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest33EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest33EE.crt
new file mode 100644
index 00000000000..2ae810abf9d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidcRLIssuerTest33EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest2EE.crt
new file mode 100644
index 00000000000..a2eb9a7dc42
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest5EE.crt
new file mode 100644
index 00000000000..1a3f7f51427
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest7EE.crt
new file mode 100644
index 00000000000..43b44bc5d89
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest8EE.crt
new file mode 100644
index 00000000000..8be24581eb9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValiddeltaCRLTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest1EE.crt
new file mode 100644
index 00000000000..b2c832fa41d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest4EE.crt
new file mode 100644
index 00000000000..47feb00fd03
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest5EE.crt b/chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest5EE.crt
new file mode 100644
index 00000000000..a93d6663841
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest5EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest7EE.crt
new file mode 100644
index 00000000000..107f102c98d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValiddistributionPointTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidinhibitAnyPolicyTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidinhibitAnyPolicyTest2EE.crt
new file mode 100644
index 00000000000..df4ba444504
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidinhibitAnyPolicyTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidinhibitPolicyMappingTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidinhibitPolicyMappingTest2EE.crt
new file mode 100644
index 00000000000..f13524a0dce
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidinhibitPolicyMappingTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidinhibitPolicyMappingTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidinhibitPolicyMappingTest4EE.crt
new file mode 100644
index 00000000000..75daa870284
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidinhibitPolicyMappingTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidkeyUsageNotCriticalTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidkeyUsageNotCriticalTest3EE.crt
new file mode 100644
index 00000000000..6da79065ea1
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidkeyUsageNotCriticalTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidonlyContainsCACertsTest13EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidonlyContainsCACertsTest13EE.crt
new file mode 100644
index 00000000000..3eec5cc6fe8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidonlyContainsCACertsTest13EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidonlySomeReasonsTest18EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidonlySomeReasonsTest18EE.crt
new file mode 100644
index 00000000000..f255d3ad711
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidonlySomeReasonsTest18EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidonlySomeReasonsTest19EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidonlySomeReasonsTest19EE.crt
new file mode 100644
index 00000000000..912968e9502
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidonlySomeReasonsTest19EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest13EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest13EE.crt
new file mode 100644
index 00000000000..1ad52efdb6c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest13EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest14EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest14EE.crt
new file mode 100644
index 00000000000..76800f5159c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest14EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest7EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest7EE.crt
new file mode 100644
index 00000000000..f3368edd5d1
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest7EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest8EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest8EE.crt
new file mode 100644
index 00000000000..8ff0a131e7c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidpathLenConstraintTest8EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/Validpre2000UTCnotBeforeDateTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/Validpre2000UTCnotBeforeDateTest3EE.crt
new file mode 100644
index 00000000000..15b2928401a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/Validpre2000UTCnotBeforeDateTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidrequireExplicitPolicyTest1EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidrequireExplicitPolicyTest1EE.crt
new file mode 100644
index 00000000000..7cf888e16ad
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidrequireExplicitPolicyTest1EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidrequireExplicitPolicyTest2EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidrequireExplicitPolicyTest2EE.crt
new file mode 100644
index 00000000000..23889360cc2
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidrequireExplicitPolicyTest2EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/ValidrequireExplicitPolicyTest4EE.crt b/chromium/net/third_party/nist-pkits/certs/ValidrequireExplicitPolicyTest4EE.crt
new file mode 100644
index 00000000000..e93a0e1fe91
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/ValidrequireExplicitPolicyTest4EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/WrongCRLCACert.crt b/chromium/net/third_party/nist-pkits/certs/WrongCRLCACert.crt
new file mode 100644
index 00000000000..3a96d87cfc5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/WrongCRLCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/anyPolicyCACert.crt b/chromium/net/third_party/nist-pkits/certs/anyPolicyCACert.crt
new file mode 100644
index 00000000000..df54668adbd
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/anyPolicyCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/basicConstraintsCriticalcAFalseCACert.crt b/chromium/net/third_party/nist-pkits/certs/basicConstraintsCriticalcAFalseCACert.crt
new file mode 100644
index 00000000000..4b678fee0c5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/basicConstraintsCriticalcAFalseCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/basicConstraintsNotCriticalCACert.crt b/chromium/net/third_party/nist-pkits/certs/basicConstraintsNotCriticalCACert.crt
new file mode 100644
index 00000000000..d6c7fb805fa
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/basicConstraintsNotCriticalCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/basicConstraintsNotCriticalcAFalseCACert.crt b/chromium/net/third_party/nist-pkits/certs/basicConstraintsNotCriticalcAFalseCACert.crt
new file mode 100644
index 00000000000..27e670ec162
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/basicConstraintsNotCriticalcAFalseCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/deltaCRLCA1Cert.crt b/chromium/net/third_party/nist-pkits/certs/deltaCRLCA1Cert.crt
new file mode 100644
index 00000000000..6815e4f888f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/deltaCRLCA1Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/deltaCRLCA2Cert.crt b/chromium/net/third_party/nist-pkits/certs/deltaCRLCA2Cert.crt
new file mode 100644
index 00000000000..2f64a74e135
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/deltaCRLCA2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/deltaCRLCA3Cert.crt b/chromium/net/third_party/nist-pkits/certs/deltaCRLCA3Cert.crt
new file mode 100644
index 00000000000..31e6b33a463
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/deltaCRLCA3Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/deltaCRLIndicatorNoBaseCACert.crt b/chromium/net/third_party/nist-pkits/certs/deltaCRLIndicatorNoBaseCACert.crt
new file mode 100644
index 00000000000..7cd82a4363c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/deltaCRLIndicatorNoBaseCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/distributionPoint1CACert.crt b/chromium/net/third_party/nist-pkits/certs/distributionPoint1CACert.crt
new file mode 100644
index 00000000000..23250812d93
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/distributionPoint1CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/distributionPoint2CACert.crt b/chromium/net/third_party/nist-pkits/certs/distributionPoint2CACert.crt
new file mode 100644
index 00000000000..205b62ad165
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/distributionPoint2CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/indirectCRLCA1Cert.crt b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA1Cert.crt
new file mode 100644
index 00000000000..046deefaec8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA1Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/indirectCRLCA2Cert.crt b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA2Cert.crt
new file mode 100644
index 00000000000..de9a0be510e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/indirectCRLCA3Cert.crt b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA3Cert.crt
new file mode 100644
index 00000000000..03bb3eb2da9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA3Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/indirectCRLCA3cRLIssuerCert.crt b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA3cRLIssuerCert.crt
new file mode 100644
index 00000000000..20e8267eeef
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA3cRLIssuerCert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/indirectCRLCA4Cert.crt b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA4Cert.crt
new file mode 100644
index 00000000000..f1cb26b375b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA4Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/indirectCRLCA4cRLIssuerCert.crt b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA4cRLIssuerCert.crt
new file mode 100644
index 00000000000..ff1203df3ad
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA4cRLIssuerCert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/indirectCRLCA5Cert.crt b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA5Cert.crt
new file mode 100644
index 00000000000..c4f9f178746
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA5Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/indirectCRLCA6Cert.crt b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA6Cert.crt
new file mode 100644
index 00000000000..46443aab941
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/indirectCRLCA6Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy0CACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy0CACert.crt
new file mode 100644
index 00000000000..cf3611025ed
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy0CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1CACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1CACert.crt
new file mode 100644
index 00000000000..0494c8fe5bb
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedCACert.crt
new file mode 100644
index 00000000000..6512e9d2e9c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt
new file mode 100644
index 00000000000..42e00344afc
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subCA1Cert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subCA1Cert.crt
new file mode 100644
index 00000000000..633536c33ae
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subCA1Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subCA2Cert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subCA2Cert.crt
new file mode 100644
index 00000000000..319e8098786
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subCA2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subCAIAP5Cert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subCAIAP5Cert.crt
new file mode 100644
index 00000000000..a3c4f2134e9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subCAIAP5Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subsubCA2Cert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subsubCA2Cert.crt
new file mode 100644
index 00000000000..3c4512ac28a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy1subsubCA2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy5CACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy5CACert.crt
new file mode 100644
index 00000000000..fc9b4232992
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy5CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy5subCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy5subCACert.crt
new file mode 100644
index 00000000000..11ceeb78cc9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy5subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy5subsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy5subsubCACert.crt
new file mode 100644
index 00000000000..32bbffeb446
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicy5subsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicyTest3EE.crt b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicyTest3EE.crt
new file mode 100644
index 00000000000..2c8fd4f6d12
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitAnyPolicyTest3EE.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping0CACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping0CACert.crt
new file mode 100644
index 00000000000..16808f7c50a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping0CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping0subCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping0subCACert.crt
new file mode 100644
index 00000000000..846abc924da
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping0subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12CACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12CACert.crt
new file mode 100644
index 00000000000..5baaf35e0f1
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subCACert.crt
new file mode 100644
index 00000000000..b2f0979ccee
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt
new file mode 100644
index 00000000000..4ad9f1e174d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subsubCACert.crt
new file mode 100644
index 00000000000..f514e5d88b7
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt
new file mode 100644
index 00000000000..b1e9ff8d068
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1CACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1CACert.crt
new file mode 100644
index 00000000000..ec47ee63731
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt
new file mode 100644
index 00000000000..65155c7b5a0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt
new file mode 100644
index 00000000000..ae1891624b9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1subCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1subCACert.crt
new file mode 100644
index 00000000000..80135df8695
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1subsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1subsubCACert.crt
new file mode 100644
index 00000000000..3a72ec12fb8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping1P1subsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5CACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5CACert.crt
new file mode 100644
index 00000000000..fd092230fbd
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5subCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5subCACert.crt
new file mode 100644
index 00000000000..93857ab6565
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5subsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5subsubCACert.crt
new file mode 100644
index 00000000000..134b7f8cb18
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5subsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5subsubsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5subsubsubCACert.crt
new file mode 100644
index 00000000000..dfb268d1d33
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/inhibitPolicyMapping5subsubsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/keyUsageCriticalcRLSignFalseCACert.crt b/chromium/net/third_party/nist-pkits/certs/keyUsageCriticalcRLSignFalseCACert.crt
new file mode 100644
index 00000000000..2467c945add
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/keyUsageCriticalcRLSignFalseCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/keyUsageCriticalkeyCertSignFalseCACert.crt b/chromium/net/third_party/nist-pkits/certs/keyUsageCriticalkeyCertSignFalseCACert.crt
new file mode 100644
index 00000000000..aa19cec73d2
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/keyUsageCriticalkeyCertSignFalseCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/keyUsageNotCriticalCACert.crt b/chromium/net/third_party/nist-pkits/certs/keyUsageNotCriticalCACert.crt
new file mode 100644
index 00000000000..bab8307e330
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/keyUsageNotCriticalCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/keyUsageNotCriticalcRLSignFalseCACert.crt b/chromium/net/third_party/nist-pkits/certs/keyUsageNotCriticalcRLSignFalseCACert.crt
new file mode 100644
index 00000000000..a6d878c8dff
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/keyUsageNotCriticalcRLSignFalseCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt b/chromium/net/third_party/nist-pkits/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt
new file mode 100644
index 00000000000..ef1056f1c39
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1CACert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1CACert.crt
new file mode 100644
index 00000000000..206359f9131
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1SelfIssuedCACert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1SelfIssuedCACert.crt
new file mode 100644
index 00000000000..452ea547524
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1SelfIssuedCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1subCA1Cert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1subCA1Cert.crt
new file mode 100644
index 00000000000..645f0ae7c4b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1subCA1Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1subCA2Cert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1subCA2Cert.crt
new file mode 100644
index 00000000000..6cfc5926a50
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1subCA2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1subCA3Cert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1subCA3Cert.crt
new file mode 100644
index 00000000000..840d073f6b5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN1subCA3Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN2CACert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN2CACert.crt
new file mode 100644
index 00000000000..c68d496e652
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN2CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN3CACert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN3CACert.crt
new file mode 100644
index 00000000000..87ba14d13a6
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN3CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN3subCA1Cert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN3subCA1Cert.crt
new file mode 100644
index 00000000000..7eed575fb48
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN3subCA1Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN3subCA2Cert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN3subCA2Cert.crt
new file mode 100644
index 00000000000..08f2245ef6c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN3subCA2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN4CACert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN4CACert.crt
new file mode 100644
index 00000000000..3b114631869
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN4CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN5CACert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN5CACert.crt
new file mode 100644
index 00000000000..c190f7a7f24
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDN5CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDNS1CACert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDNS1CACert.crt
new file mode 100644
index 00000000000..a7ec3bd1ebb
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDNS1CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsDNS2CACert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDNS2CACert.crt
new file mode 100644
index 00000000000..c70846206c5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsDNS2CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsRFC822CA1Cert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsRFC822CA1Cert.crt
new file mode 100644
index 00000000000..1be8e993355
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsRFC822CA1Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsRFC822CA2Cert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsRFC822CA2Cert.crt
new file mode 100644
index 00000000000..58308f8939d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsRFC822CA2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsRFC822CA3Cert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsRFC822CA3Cert.crt
new file mode 100644
index 00000000000..ff6ba166ba4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsRFC822CA3Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsURI1CACert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsURI1CACert.crt
new file mode 100644
index 00000000000..5f638c093c0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsURI1CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/nameConstraintsURI2CACert.crt b/chromium/net/third_party/nist-pkits/certs/nameConstraintsURI2CACert.crt
new file mode 100644
index 00000000000..e06b6377a9b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/nameConstraintsURI2CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/onlyContainsAttributeCertsCACert.crt b/chromium/net/third_party/nist-pkits/certs/onlyContainsAttributeCertsCACert.crt
new file mode 100644
index 00000000000..e8d2b7224a8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/onlyContainsAttributeCertsCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/onlyContainsCACertsCACert.crt b/chromium/net/third_party/nist-pkits/certs/onlyContainsCACertsCACert.crt
new file mode 100644
index 00000000000..d75988ad008
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/onlyContainsCACertsCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/onlyContainsUserCertsCACert.crt b/chromium/net/third_party/nist-pkits/certs/onlyContainsUserCertsCACert.crt
new file mode 100644
index 00000000000..0d0b95030b1
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/onlyContainsUserCertsCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA1Cert.crt b/chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA1Cert.crt
new file mode 100644
index 00000000000..ca247b06b40
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA1Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA2Cert.crt b/chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA2Cert.crt
new file mode 100644
index 00000000000..c1cce6e0cec
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA3Cert.crt b/chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA3Cert.crt
new file mode 100644
index 00000000000..cd65a820e42
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA3Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA4Cert.crt b/chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA4Cert.crt
new file mode 100644
index 00000000000..f205db0a3be
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/onlySomeReasonsCA4Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint0CACert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint0CACert.crt
new file mode 100644
index 00000000000..ce9b90d2844
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint0CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint0SelfIssuedCACert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint0SelfIssuedCACert.crt
new file mode 100644
index 00000000000..6e8f97c2035
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint0SelfIssuedCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint0subCA2Cert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint0subCA2Cert.crt
new file mode 100644
index 00000000000..2fc8fb590f8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint0subCA2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint0subCACert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint0subCACert.crt
new file mode 100644
index 00000000000..b156179e3a7
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint0subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint1CACert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint1CACert.crt
new file mode 100644
index 00000000000..a4242616728
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint1CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint1SelfIssuedCACert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint1SelfIssuedCACert.crt
new file mode 100644
index 00000000000..87590c3d262
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint1SelfIssuedCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint1SelfIssuedsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint1SelfIssuedsubCACert.crt
new file mode 100644
index 00000000000..f2c43ea8936
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint1SelfIssuedsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint1subCACert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint1subCACert.crt
new file mode 100644
index 00000000000..05a2bac1da8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint1subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6CACert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6CACert.crt
new file mode 100644
index 00000000000..c254a2376d3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subCA0Cert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subCA0Cert.crt
new file mode 100644
index 00000000000..0a8c99dd3e4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subCA0Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subCA1Cert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subCA1Cert.crt
new file mode 100644
index 00000000000..bd686290efe
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subCA1Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subCA4Cert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subCA4Cert.crt
new file mode 100644
index 00000000000..822a383d053
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subCA4Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubCA00Cert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubCA00Cert.crt
new file mode 100644
index 00000000000..e2fd7ae3cd6
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubCA00Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubCA11Cert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubCA11Cert.crt
new file mode 100644
index 00000000000..44c0162e945
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubCA11Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubCA41Cert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubCA41Cert.crt
new file mode 100644
index 00000000000..284f4a9e483
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubCA41Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubsubCA11XCert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubsubCA11XCert.crt
new file mode 100644
index 00000000000..9766cf01596
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubsubCA11XCert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubsubCA41XCert.crt b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubsubCA41XCert.crt
new file mode 100644
index 00000000000..e14753174b4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pathLenConstraint6subsubsubCA41XCert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/pre2000CRLnextUpdateCACert.crt b/chromium/net/third_party/nist-pkits/certs/pre2000CRLnextUpdateCACert.crt
new file mode 100644
index 00000000000..30aff16129d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/pre2000CRLnextUpdateCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0CACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0CACert.crt
new file mode 100644
index 00000000000..16594b9e970
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0subCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0subCACert.crt
new file mode 100644
index 00000000000..b7a1518eb86
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0subsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0subsubCACert.crt
new file mode 100644
index 00000000000..db57e9b337f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0subsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0subsubsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0subsubsubCACert.crt
new file mode 100644
index 00000000000..4952094eef3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy0subsubsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10CACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10CACert.crt
new file mode 100644
index 00000000000..3a54e7f2b82
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10subCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10subCACert.crt
new file mode 100644
index 00000000000..650a53f4c2e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10subsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10subsubCACert.crt
new file mode 100644
index 00000000000..139be532a59
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10subsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10subsubsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10subsubsubCACert.crt
new file mode 100644
index 00000000000..a7c216c1640
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy10subsubsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2CACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2CACert.crt
new file mode 100644
index 00000000000..f7ca7ae7e2a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2SelfIssuedCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2SelfIssuedCACert.crt
new file mode 100644
index 00000000000..9d162690905
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2SelfIssuedCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt
new file mode 100644
index 00000000000..b53bec1560d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2subCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2subCACert.crt
new file mode 100644
index 00000000000..36fc0d8df48
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy2subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4CACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4CACert.crt
new file mode 100644
index 00000000000..723ae42a47c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4subCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4subCACert.crt
new file mode 100644
index 00000000000..1bd237f766c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4subsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4subsubCACert.crt
new file mode 100644
index 00000000000..1a37158581b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4subsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4subsubsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4subsubsubCACert.crt
new file mode 100644
index 00000000000..3047d74341e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy4subsubsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5CACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5CACert.crt
new file mode 100644
index 00000000000..c6b69ad95d5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5subCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5subCACert.crt
new file mode 100644
index 00000000000..16958532f00
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5subCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5subsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5subsubCACert.crt
new file mode 100644
index 00000000000..093963aeca5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5subsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5subsubsubCACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5subsubsubCACert.crt
new file mode 100644
index 00000000000..58da176c465
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy5subsubsubCACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7CACert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7CACert.crt
new file mode 100644
index 00000000000..aba4a7fde45
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7CACert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7subCARE2Cert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7subCARE2Cert.crt
new file mode 100644
index 00000000000..c57e9e4a5bd
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7subCARE2Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt
new file mode 100644
index 00000000000..343efa5ec2d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt
new file mode 100644
index 00000000000..9a8e72a1ce3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/BadCRLIssuerNameCACRL.crl b/chromium/net/third_party/nist-pkits/crls/BadCRLIssuerNameCACRL.crl
new file mode 100644
index 00000000000..eb091dc2aef
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/BadCRLIssuerNameCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/BadCRLSignatureCACRL.crl b/chromium/net/third_party/nist-pkits/crls/BadCRLSignatureCACRL.crl
new file mode 100644
index 00000000000..7b801c20c3d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/BadCRLSignatureCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/BadSignedCACRL.crl b/chromium/net/third_party/nist-pkits/crls/BadSignedCACRL.crl
new file mode 100644
index 00000000000..f7d0c8030a7
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/BadSignedCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/BadnotAfterDateCACRL.crl b/chromium/net/third_party/nist-pkits/crls/BadnotAfterDateCACRL.crl
new file mode 100644
index 00000000000..21f7c815e5f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/BadnotAfterDateCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/BadnotBeforeDateCACRL.crl b/chromium/net/third_party/nist-pkits/crls/BadnotBeforeDateCACRL.crl
new file mode 100644
index 00000000000..24f368640e3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/BadnotBeforeDateCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl b/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl
new file mode 100644
index 00000000000..4adc345354c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl b/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl
new file mode 100644
index 00000000000..f687137caf9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedNewKeyCACRL.crl b/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedNewKeyCACRL.crl
new file mode 100644
index 00000000000..5a098acdf4d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedNewKeyCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedOldKeyCACRL.crl b/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedOldKeyCACRL.crl
new file mode 100644
index 00000000000..f5783829b67
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedOldKeyCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl b/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl
new file mode 100644
index 00000000000..f29c23f0471
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/DSACACRL.crl b/chromium/net/third_party/nist-pkits/crls/DSACACRL.crl
new file mode 100644
index 00000000000..369b5976278
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/DSACACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/DSAParametersInheritedCACRL.crl b/chromium/net/third_party/nist-pkits/crls/DSAParametersInheritedCACRL.crl
new file mode 100644
index 00000000000..9b5c377a317
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/DSAParametersInheritedCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.crl b/chromium/net/third_party/nist-pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.crl
new file mode 100644
index 00000000000..31360af09e8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/GoodCACRL.crl b/chromium/net/third_party/nist-pkits/crls/GoodCACRL.crl
new file mode 100644
index 00000000000..d46110c5cf0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/GoodCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/GoodsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/GoodsubCACRL.crl
new file mode 100644
index 00000000000..199966e4f61
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/GoodsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl b/chromium/net/third_party/nist-pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl
new file mode 100644
index 00000000000..7364f4da3ba
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/LongSerialNumberCACRL.crl b/chromium/net/third_party/nist-pkits/crls/LongSerialNumberCACRL.crl
new file mode 100644
index 00000000000..9998cc47300
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/LongSerialNumberCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/Mapping1to2CACRL.crl b/chromium/net/third_party/nist-pkits/crls/Mapping1to2CACRL.crl
new file mode 100644
index 00000000000..50834db1c1a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/Mapping1to2CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/MappingFromanyPolicyCACRL.crl b/chromium/net/third_party/nist-pkits/crls/MappingFromanyPolicyCACRL.crl
new file mode 100644
index 00000000000..19251462802
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/MappingFromanyPolicyCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/MappingToanyPolicyCACRL.crl b/chromium/net/third_party/nist-pkits/crls/MappingToanyPolicyCACRL.crl
new file mode 100644
index 00000000000..97f10205e58
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/MappingToanyPolicyCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/MissingbasicConstraintsCACRL.crl b/chromium/net/third_party/nist-pkits/crls/MissingbasicConstraintsCACRL.crl
new file mode 100644
index 00000000000..c33ff4dfe78
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/MissingbasicConstraintsCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/NameOrderCACRL.crl b/chromium/net/third_party/nist-pkits/crls/NameOrderCACRL.crl
new file mode 100644
index 00000000000..592460fdd7d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/NameOrderCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/NegativeSerialNumberCACRL.crl b/chromium/net/third_party/nist-pkits/crls/NegativeSerialNumberCACRL.crl
new file mode 100644
index 00000000000..d438c2f9d50
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/NegativeSerialNumberCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/NoPoliciesCACRL.crl b/chromium/net/third_party/nist-pkits/crls/NoPoliciesCACRL.crl
new file mode 100644
index 00000000000..376e255f29d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/NoPoliciesCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/NoissuingDistributionPointCACRL.crl b/chromium/net/third_party/nist-pkits/crls/NoissuingDistributionPointCACRL.crl
new file mode 100644
index 00000000000..c9d965a23c7
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/NoissuingDistributionPointCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/OldCRLnextUpdateCACRL.crl b/chromium/net/third_party/nist-pkits/crls/OldCRLnextUpdateCACRL.crl
new file mode 100644
index 00000000000..552b999a56d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/OldCRLnextUpdateCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/P12Mapping1to3CACRL.crl b/chromium/net/third_party/nist-pkits/crls/P12Mapping1to3CACRL.crl
new file mode 100644
index 00000000000..3ab53b31d5e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/P12Mapping1to3CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/P12Mapping1to3subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/P12Mapping1to3subCACRL.crl
new file mode 100644
index 00000000000..50aa43deccc
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/P12Mapping1to3subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/P12Mapping1to3subsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/P12Mapping1to3subsubCACRL.crl
new file mode 100644
index 00000000000..e154010a0b4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/P12Mapping1to3subsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/P1Mapping1to234CACRL.crl b/chromium/net/third_party/nist-pkits/crls/P1Mapping1to234CACRL.crl
new file mode 100644
index 00000000000..823347c2c00
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/P1Mapping1to234CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/P1Mapping1to234subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/P1Mapping1to234subCACRL.crl
new file mode 100644
index 00000000000..62829b6a172
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/P1Mapping1to234subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/P1anyPolicyMapping1to2CACRL.crl b/chromium/net/third_party/nist-pkits/crls/P1anyPolicyMapping1to2CACRL.crl
new file mode 100644
index 00000000000..5391d2d9e83
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/P1anyPolicyMapping1to2CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PanyPolicyMapping1to2CACRL.crl b/chromium/net/third_party/nist-pkits/crls/PanyPolicyMapping1to2CACRL.crl
new file mode 100644
index 00000000000..73a8a501711
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PanyPolicyMapping1to2CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP1234CACRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP1234CACRL.crl
new file mode 100644
index 00000000000..7cee15b532b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP1234CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP1234subCAP123CRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP1234subCAP123CRL.crl
new file mode 100644
index 00000000000..a0fd524128c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP1234subCAP123CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP1234subsubCAP123P12CRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP1234subsubCAP123P12CRL.crl
new file mode 100644
index 00000000000..3759346c7c8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP1234subsubCAP123P12CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP123CACRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP123CACRL.crl
new file mode 100644
index 00000000000..24b15c090c3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP123CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP123subCAP12CRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP123subCAP12CRL.crl
new file mode 100644
index 00000000000..4a26b90f0a0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP123subCAP12CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP123subsubCAP12P1CRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP123subsubCAP12P1CRL.crl
new file mode 100644
index 00000000000..2529aeccb1c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP123subsubCAP12P1CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP123subsubCAP2P2CRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP123subsubCAP2P2CRL.crl
new file mode 100644
index 00000000000..f49e81b193f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP123subsubCAP2P2CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl
new file mode 100644
index 00000000000..a354659c086
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP12CACRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP12CACRL.crl
new file mode 100644
index 00000000000..1838a183a7a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP12CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP12subCAP1CRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP12subCAP1CRL.crl
new file mode 100644
index 00000000000..0c0a57ffcde
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP12subCAP1CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP12subsubCAP1P2CRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP12subsubCAP1P2CRL.crl
new file mode 100644
index 00000000000..6c48e2745a2
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP12subsubCAP1P2CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP2subCA2CRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP2subCA2CRL.crl
new file mode 100644
index 00000000000..821ceda6d20
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP2subCA2CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP2subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP2subCACRL.crl
new file mode 100644
index 00000000000..8017295e1ba
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP2subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/PoliciesP3CACRL.crl b/chromium/net/third_party/nist-pkits/crls/PoliciesP3CACRL.crl
new file mode 100644
index 00000000000..8585ce40c73
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/PoliciesP3CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/RFC3280MandatoryAttributeTypesCACRL.crl b/chromium/net/third_party/nist-pkits/crls/RFC3280MandatoryAttributeTypesCACRL.crl
new file mode 100644
index 00000000000..f68a34557c4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/RFC3280MandatoryAttributeTypesCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/RFC3280OptionalAttributeTypesCACRL.crl b/chromium/net/third_party/nist-pkits/crls/RFC3280OptionalAttributeTypesCACRL.crl
new file mode 100644
index 00000000000..102aad68b77
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/RFC3280OptionalAttributeTypesCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/RevokedsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/RevokedsubCACRL.crl
new file mode 100644
index 00000000000..d5346166d8a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/RevokedsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl b/chromium/net/third_party/nist-pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl
new file mode 100644
index 00000000000..17a3f741240
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/SeparateCertificateandCRLKeysCA2CRL.crl b/chromium/net/third_party/nist-pkits/crls/SeparateCertificateandCRLKeysCA2CRL.crl
new file mode 100644
index 00000000000..90ec891f9d7
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/SeparateCertificateandCRLKeysCA2CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/SeparateCertificateandCRLKeysCRL.crl b/chromium/net/third_party/nist-pkits/crls/SeparateCertificateandCRLKeysCRL.crl
new file mode 100644
index 00000000000..2dffb144a59
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/SeparateCertificateandCRLKeysCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/TrustAnchorRootCRL.crl b/chromium/net/third_party/nist-pkits/crls/TrustAnchorRootCRL.crl
new file mode 100644
index 00000000000..f6245e4a62d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/TrustAnchorRootCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/TwoCRLsCABadCRL.crl b/chromium/net/third_party/nist-pkits/crls/TwoCRLsCABadCRL.crl
new file mode 100644
index 00000000000..daaaeef5324
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/TwoCRLsCABadCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/TwoCRLsCAGoodCRL.crl b/chromium/net/third_party/nist-pkits/crls/TwoCRLsCAGoodCRL.crl
new file mode 100644
index 00000000000..074e99bc5ce
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/TwoCRLsCAGoodCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/UIDCACRL.crl b/chromium/net/third_party/nist-pkits/crls/UIDCACRL.crl
new file mode 100644
index 00000000000..76fca88ed9f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/UIDCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.crl b/chromium/net/third_party/nist-pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.crl
new file mode 100644
index 00000000000..4b18abe0f5a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/UTF8StringEncodedNamesCACRL.crl b/chromium/net/third_party/nist-pkits/crls/UTF8StringEncodedNamesCACRL.crl
new file mode 100644
index 00000000000..4411276786e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/UTF8StringEncodedNamesCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/UnknownCRLEntryExtensionCACRL.crl b/chromium/net/third_party/nist-pkits/crls/UnknownCRLEntryExtensionCACRL.crl
new file mode 100644
index 00000000000..53f90a87261
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/UnknownCRLEntryExtensionCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/UnknownCRLExtensionCACRL.crl b/chromium/net/third_party/nist-pkits/crls/UnknownCRLExtensionCACRL.crl
new file mode 100644
index 00000000000..15df8d6c03b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/UnknownCRLExtensionCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/WrongCRLCACRL.crl b/chromium/net/third_party/nist-pkits/crls/WrongCRLCACRL.crl
new file mode 100644
index 00000000000..f6245e4a62d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/WrongCRLCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/anyPolicyCACRL.crl b/chromium/net/third_party/nist-pkits/crls/anyPolicyCACRL.crl
new file mode 100644
index 00000000000..cd2add46a6a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/anyPolicyCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/basicConstraintsCriticalcAFalseCACRL.crl b/chromium/net/third_party/nist-pkits/crls/basicConstraintsCriticalcAFalseCACRL.crl
new file mode 100644
index 00000000000..3dee2bcb21f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/basicConstraintsCriticalcAFalseCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/basicConstraintsNotCriticalCACRL.crl b/chromium/net/third_party/nist-pkits/crls/basicConstraintsNotCriticalCACRL.crl
new file mode 100644
index 00000000000..b4ee320e65b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/basicConstraintsNotCriticalCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.crl b/chromium/net/third_party/nist-pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.crl
new file mode 100644
index 00000000000..08f4df8c2f8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/deltaCRLCA1CRL.crl b/chromium/net/third_party/nist-pkits/crls/deltaCRLCA1CRL.crl
new file mode 100644
index 00000000000..550bff39cdb
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/deltaCRLCA1CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/deltaCRLCA1deltaCRL.crl b/chromium/net/third_party/nist-pkits/crls/deltaCRLCA1deltaCRL.crl
new file mode 100644
index 00000000000..74f746a42fb
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/deltaCRLCA1deltaCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/deltaCRLCA2CRL.crl b/chromium/net/third_party/nist-pkits/crls/deltaCRLCA2CRL.crl
new file mode 100644
index 00000000000..8e13c071e0b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/deltaCRLCA2CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/deltaCRLCA2deltaCRL.crl b/chromium/net/third_party/nist-pkits/crls/deltaCRLCA2deltaCRL.crl
new file mode 100644
index 00000000000..c692f3a7a66
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/deltaCRLCA2deltaCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/deltaCRLCA3CRL.crl b/chromium/net/third_party/nist-pkits/crls/deltaCRLCA3CRL.crl
new file mode 100644
index 00000000000..8aaebce2ae6
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/deltaCRLCA3CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/deltaCRLCA3deltaCRL.crl b/chromium/net/third_party/nist-pkits/crls/deltaCRLCA3deltaCRL.crl
new file mode 100644
index 00000000000..fff39a5c1bf
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/deltaCRLCA3deltaCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/deltaCRLIndicatorNoBaseCACRL.crl b/chromium/net/third_party/nist-pkits/crls/deltaCRLIndicatorNoBaseCACRL.crl
new file mode 100644
index 00000000000..7620c94b383
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/deltaCRLIndicatorNoBaseCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/distributionPoint1CACRL.crl b/chromium/net/third_party/nist-pkits/crls/distributionPoint1CACRL.crl
new file mode 100644
index 00000000000..aa785bc6ef0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/distributionPoint1CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/distributionPoint2CACRL.crl b/chromium/net/third_party/nist-pkits/crls/distributionPoint2CACRL.crl
new file mode 100644
index 00000000000..0875c0b9e71
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/distributionPoint2CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/indirectCRLCA1CRL.crl b/chromium/net/third_party/nist-pkits/crls/indirectCRLCA1CRL.crl
new file mode 100644
index 00000000000..e8edba2102b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/indirectCRLCA1CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/indirectCRLCA3CRL.crl b/chromium/net/third_party/nist-pkits/crls/indirectCRLCA3CRL.crl
new file mode 100644
index 00000000000..cd2639c848b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/indirectCRLCA3CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/indirectCRLCA3cRLIssuerCRL.crl b/chromium/net/third_party/nist-pkits/crls/indirectCRLCA3cRLIssuerCRL.crl
new file mode 100644
index 00000000000..9289a281144
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/indirectCRLCA3cRLIssuerCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/indirectCRLCA4cRLIssuerCRL.crl b/chromium/net/third_party/nist-pkits/crls/indirectCRLCA4cRLIssuerCRL.crl
new file mode 100644
index 00000000000..2f73d9cd4a9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/indirectCRLCA4cRLIssuerCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/indirectCRLCA5CRL.crl b/chromium/net/third_party/nist-pkits/crls/indirectCRLCA5CRL.crl
new file mode 100644
index 00000000000..d6b3943996f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/indirectCRLCA5CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy0CACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy0CACRL.crl
new file mode 100644
index 00000000000..1f14141335f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy0CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1CACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1CACRL.crl
new file mode 100644
index 00000000000..8538d385887
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subCA1CRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subCA1CRL.crl
new file mode 100644
index 00000000000..bfa4095b2b4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subCA1CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subCA2CRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subCA2CRL.crl
new file mode 100644
index 00000000000..54d54c1228e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subCA2CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.crl
new file mode 100644
index 00000000000..a2856f6c2f5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subsubCA2CRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subsubCA2CRL.crl
new file mode 100644
index 00000000000..4e07e80da57
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy1subsubCA2CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy5CACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy5CACRL.crl
new file mode 100644
index 00000000000..227d712f153
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy5CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy5subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy5subCACRL.crl
new file mode 100644
index 00000000000..5b6b1e7c9d3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy5subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy5subsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy5subsubCACRL.crl
new file mode 100644
index 00000000000..78628f83f0d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitAnyPolicy5subsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping0CACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping0CACRL.crl
new file mode 100644
index 00000000000..69c39da01c7
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping0CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping0subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping0subCACRL.crl
new file mode 100644
index 00000000000..b96ccff8424
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping0subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12CACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12CACRL.crl
new file mode 100644
index 00000000000..00074f5b050
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subCACRL.crl
new file mode 100644
index 00000000000..9b90c9925ac
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl
new file mode 100644
index 00000000000..ab2b70a8a4f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subsubCACRL.crl
new file mode 100644
index 00000000000..7e96d093397
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl
new file mode 100644
index 00000000000..b5c88aa6410
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P1CACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P1CACRL.crl
new file mode 100644
index 00000000000..134a2039243
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P1CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P1subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P1subCACRL.crl
new file mode 100644
index 00000000000..42a66d51883
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P1subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P1subsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P1subsubCACRL.crl
new file mode 100644
index 00000000000..bf0a11951d7
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping1P1subsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5CACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5CACRL.crl
new file mode 100644
index 00000000000..a605a5d12ff
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5subCACRL.crl
new file mode 100644
index 00000000000..10b9eb22bfc
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5subsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5subsubCACRL.crl
new file mode 100644
index 00000000000..660555a90c3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5subsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5subsubsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5subsubsubCACRL.crl
new file mode 100644
index 00000000000..9400ea8c239
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/inhibitPolicyMapping5subsubsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/keyUsageCriticalcRLSignFalseCACRL.crl b/chromium/net/third_party/nist-pkits/crls/keyUsageCriticalcRLSignFalseCACRL.crl
new file mode 100644
index 00000000000..89dd9a8351c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/keyUsageCriticalcRLSignFalseCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl b/chromium/net/third_party/nist-pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl
new file mode 100644
index 00000000000..6266447c354
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/keyUsageNotCriticalCACRL.crl b/chromium/net/third_party/nist-pkits/crls/keyUsageNotCriticalCACRL.crl
new file mode 100644
index 00000000000..bd099eb98ca
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/keyUsageNotCriticalCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl b/chromium/net/third_party/nist-pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl
new file mode 100644
index 00000000000..ae04987076e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl b/chromium/net/third_party/nist-pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl
new file mode 100644
index 00000000000..4e91c590d0e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1CACRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1CACRL.crl
new file mode 100644
index 00000000000..d03eab299b8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1subCA1CRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1subCA1CRL.crl
new file mode 100644
index 00000000000..441164e02cc
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1subCA1CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1subCA2CRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1subCA2CRL.crl
new file mode 100644
index 00000000000..024ce6fe61a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1subCA2CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1subCA3CRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1subCA3CRL.crl
new file mode 100644
index 00000000000..230bff5d6f7
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN1subCA3CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN2CACRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN2CACRL.crl
new file mode 100644
index 00000000000..8d7a0cef94c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN2CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN3CACRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN3CACRL.crl
new file mode 100644
index 00000000000..19907d79024
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN3CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN3subCA1CRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN3subCA1CRL.crl
new file mode 100644
index 00000000000..784ceaa3378
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN3subCA1CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN3subCA2CRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN3subCA2CRL.crl
new file mode 100644
index 00000000000..b3ebd2e0286
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN3subCA2CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN4CACRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN4CACRL.crl
new file mode 100644
index 00000000000..7e096a143cf
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN4CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN5CACRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN5CACRL.crl
new file mode 100644
index 00000000000..f734c51e322
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDN5CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsDNS1CACRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDNS1CACRL.crl
new file mode 100644
index 00000000000..7608ab1f5f5
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDNS1CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsDNS2CACRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDNS2CACRL.crl
new file mode 100644
index 00000000000..9349f5003f3
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsDNS2CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsRFC822CA1CRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsRFC822CA1CRL.crl
new file mode 100644
index 00000000000..af2d043280c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsRFC822CA1CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsRFC822CA2CRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsRFC822CA2CRL.crl
new file mode 100644
index 00000000000..ed1b062d61a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsRFC822CA2CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsRFC822CA3CRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsRFC822CA3CRL.crl
new file mode 100644
index 00000000000..c9cca94a9d6
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsRFC822CA3CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsURI1CACRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsURI1CACRL.crl
new file mode 100644
index 00000000000..2ee9a8f5993
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsURI1CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/nameConstraintsURI2CACRL.crl b/chromium/net/third_party/nist-pkits/crls/nameConstraintsURI2CACRL.crl
new file mode 100644
index 00000000000..192b5d85e66
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/nameConstraintsURI2CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/onlyContainsAttributeCertsCACRL.crl b/chromium/net/third_party/nist-pkits/crls/onlyContainsAttributeCertsCACRL.crl
new file mode 100644
index 00000000000..676823e13c8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/onlyContainsAttributeCertsCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/onlyContainsCACertsCACRL.crl b/chromium/net/third_party/nist-pkits/crls/onlyContainsCACertsCACRL.crl
new file mode 100644
index 00000000000..715f3aa375c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/onlyContainsCACertsCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/onlyContainsUserCertsCACRL.crl b/chromium/net/third_party/nist-pkits/crls/onlyContainsUserCertsCACRL.crl
new file mode 100644
index 00000000000..3e8c024c085
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/onlyContainsUserCertsCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA1compromiseCRL.crl b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA1compromiseCRL.crl
new file mode 100644
index 00000000000..f78c17c43e8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA1compromiseCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA1otherreasonsCRL.crl b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA1otherreasonsCRL.crl
new file mode 100644
index 00000000000..8167a3a0aaf
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA1otherreasonsCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA2CRL1.crl b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA2CRL1.crl
new file mode 100644
index 00000000000..c2e7a0170d7
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA2CRL1.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA2CRL2.crl b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA2CRL2.crl
new file mode 100644
index 00000000000..7d1f1a6ab15
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA2CRL2.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA3compromiseCRL.crl b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA3compromiseCRL.crl
new file mode 100644
index 00000000000..09176f9bacb
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA3compromiseCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA3otherreasonsCRL.crl b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA3otherreasonsCRL.crl
new file mode 100644
index 00000000000..efe111731da
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA3otherreasonsCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA4compromiseCRL.crl b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA4compromiseCRL.crl
new file mode 100644
index 00000000000..0f742ced57e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA4compromiseCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA4otherreasonsCRL.crl b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA4otherreasonsCRL.crl
new file mode 100644
index 00000000000..4201d626faa
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/onlySomeReasonsCA4otherreasonsCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint0CACRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint0CACRL.crl
new file mode 100644
index 00000000000..d1a0ef8235a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint0CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint0subCA2CRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint0subCA2CRL.crl
new file mode 100644
index 00000000000..b90fa087072
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint0subCA2CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint0subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint0subCACRL.crl
new file mode 100644
index 00000000000..8d2c43633bf
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint0subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint1CACRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint1CACRL.crl
new file mode 100644
index 00000000000..dcffee381f8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint1CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint1subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint1subCACRL.crl
new file mode 100644
index 00000000000..f7ddec3508c
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint1subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6CACRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6CACRL.crl
new file mode 100644
index 00000000000..a2119730794
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subCA0CRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subCA0CRL.crl
new file mode 100644
index 00000000000..71f4e104c2b
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subCA0CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subCA1CRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subCA1CRL.crl
new file mode 100644
index 00000000000..ab792d4da06
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subCA1CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subCA4CRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subCA4CRL.crl
new file mode 100644
index 00000000000..27865650bad
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subCA4CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubCA00CRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubCA00CRL.crl
new file mode 100644
index 00000000000..64d154cd2f0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubCA00CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubCA11CRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubCA11CRL.crl
new file mode 100644
index 00000000000..54db33e52a9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubCA11CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubCA41CRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubCA41CRL.crl
new file mode 100644
index 00000000000..9fe269d34f2
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubCA41CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubsubCA11XCRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubsubCA11XCRL.crl
new file mode 100644
index 00000000000..c10a7ad3463
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubsubCA11XCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubsubCA41XCRL.crl b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubsubCA41XCRL.crl
new file mode 100644
index 00000000000..23a21b42edc
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pathLenConstraint6subsubsubCA41XCRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/pre2000CRLnextUpdateCACRL.crl b/chromium/net/third_party/nist-pkits/crls/pre2000CRLnextUpdateCACRL.crl
new file mode 100644
index 00000000000..436ffad9fbf
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/pre2000CRLnextUpdateCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0CACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0CACRL.crl
new file mode 100644
index 00000000000..3c73231310f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0subCACRL.crl
new file mode 100644
index 00000000000..9186affded4
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0subsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0subsubCACRL.crl
new file mode 100644
index 00000000000..671e072afb2
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0subsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0subsubsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0subsubsubCACRL.crl
new file mode 100644
index 00000000000..1bddb2a0bed
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy0subsubsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10CACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10CACRL.crl
new file mode 100644
index 00000000000..751e35c5292
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10subCACRL.crl
new file mode 100644
index 00000000000..78a021691b6
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10subsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10subsubCACRL.crl
new file mode 100644
index 00000000000..9731f01ecc8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10subsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10subsubsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10subsubsubCACRL.crl
new file mode 100644
index 00000000000..cfc28d0948a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy10subsubsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy2CACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy2CACRL.crl
new file mode 100644
index 00000000000..69c8132fb8a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy2CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy2subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy2subCACRL.crl
new file mode 100644
index 00000000000..6c62766150d
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy2subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4CACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4CACRL.crl
new file mode 100644
index 00000000000..1cd554bd7e9
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4subCACRL.crl
new file mode 100644
index 00000000000..004faafa66a
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4subsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4subsubCACRL.crl
new file mode 100644
index 00000000000..fb3a9e7ec22
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4subsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4subsubsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4subsubsubCACRL.crl
new file mode 100644
index 00000000000..94e259b854f
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy4subsubsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5CACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5CACRL.crl
new file mode 100644
index 00000000000..786949ba0c0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5subCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5subCACRL.crl
new file mode 100644
index 00000000000..0a9b3475abc
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5subCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5subsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5subsubCACRL.crl
new file mode 100644
index 00000000000..ed1fcabb4f8
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5subsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5subsubsubCACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5subsubsubCACRL.crl
new file mode 100644
index 00000000000..b80e6695704
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy5subsubsubCACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7CACRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7CACRL.crl
new file mode 100644
index 00000000000..71b1511ecc0
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7CACRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7subCARE2CRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7subCARE2CRL.crl
new file mode 100644
index 00000000000..0f3d5f6b372
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7subCARE2CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl
new file mode 100644
index 00000000000..b700ba5156e
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl
new file mode 100644
index 00000000000..0d42a673591
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl
Binary files differ
diff --git a/chromium/net/third_party/nist-pkits/generate_tests.py b/chromium/net/third_party/nist-pkits/generate_tests.py
new file mode 100644
index 00000000000..fe9f9b76af6
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/generate_tests.py
@@ -0,0 +1,196 @@
+# 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.
+
+'''Generates a test suite from NIST PKITS test descriptions.
+
+The output is a set of Type Parameterized Tests which are included by
+pkits_unittest.h. See pkits_unittest.h for information on using the tests.
+GoogleTest has a limit of 50 tests per type parameterized testcase, so the tests
+are split up by section number (this also makes it possible to easily skip
+sections that pertain to non-implemented features).
+
+Usage:
+ generate_tests.py <PKITS.pdf> <output.h>
+'''
+
+import os
+import re
+import subprocess
+import sys
+import tempfile
+
+
+def sanitize_name(s):
+ return s.translate(None, ' -')
+
+
+def finalize_test_case(test_case_name, sanitized_test_names, output):
+ output.write('\nWRAPPED_REGISTER_TYPED_TEST_CASE_P(%s' % test_case_name)
+ for name in sanitized_test_names:
+ output.write(',\n %s' % name)
+ output.write(');\n')
+
+
+def generate_test(test_case_name, test_number, raw_test_name, certs, crls, should_validate,
+ output):
+ sanitized_test_name = 'Section%s%s' % (test_number.split('.')[1],
+ sanitize_name(raw_test_name))
+ certs_formatted = ', '.join('"%s"' % n for n in certs)
+ crls_formatted = ', '.join('"%s"' % n for n in crls)
+ assert_function = 'ASSERT_TRUE' if should_validate else 'ASSERT_FALSE'
+ output.write('''
+// %(test_number)s %(raw_test_name)s
+WRAPPED_TYPED_TEST_P(%(test_case_name)s, %(sanitized_test_name)s) {
+ const char* const certs[] = {
+ %(certs_formatted)s
+ };
+ const char* const crls[] = {
+ %(crls_formatted)s
+ };
+ %(assert_function)s(this->Verify(certs, crls));
+}
+''' % vars())
+
+ return sanitized_test_name
+
+
+# Matches a section header, ex: "4.1 Signature Verification"
+SECTION_MATCHER = re.compile('^\s*(\d+\.\d+)\s+(.+)\s*$')
+# Matches a test header, ex: "4.1.1 Valid Signatures Test1"
+TEST_MATCHER = re.compile('^\s*(\d+\.\d+.\d+)\s+(.+)\s*$')
+# Match an expected test result. Note that some results in the PDF have a typo
+# "path not should validate" instead of "path should not validate".
+TEST_RESULT_MATCHER = re.compile(
+ '^\s*Expected Result:.*path (should validate|'
+ 'should not validate|not should validate)')
+PATH_HEADER_MATCHER = re.compile('^\s*Certification Path:')
+# Matches a line in the certification path, ex: "\u2022 Good CA Cert, Good CA CRL"
+PATH_MATCHER = re.compile('^\s*\xe2\x80\xa2\s*(.+)\s*$')
+# Matches a page number. These may appear in the middle of multi-line fields and
+# thus need to be ignored.
+PAGE_NUMBER_MATCHER = re.compile('^\s*\d+\s*$')
+# Matches if an entry in a certification path refers to a CRL, ex:
+# "onlySomeReasons CA2 CRL1".
+CRL_MATCHER = re.compile('^.*CRL\d*$')
+def parse_test(lines, i, test_case_name, test_number, test_name, output):
+ expected_result = None
+ certs = []
+ crls = []
+
+ while i < len(lines):
+ result_match = TEST_RESULT_MATCHER.match(lines[i])
+ i += 1
+ if result_match:
+ expected_result = result_match.group(1) == 'should validate'
+ break
+
+ while i < len(lines):
+ path_match = PATH_HEADER_MATCHER.match(lines[i])
+ i += 1
+ if path_match:
+ break
+
+ path_lines = []
+ while i < len(lines):
+ line = lines[i].strip()
+ if TEST_MATCHER.match(line) or SECTION_MATCHER.match(line):
+ break
+ i += 1
+ if not line or PAGE_NUMBER_MATCHER.match(line):
+ continue
+ path_match = PATH_MATCHER.match(line)
+ if path_match:
+ path_lines.append(path_match.group(1))
+ continue
+ # Continuation of previous path line.
+ path_lines[-1] += ' ' + line
+
+ for path_line in path_lines:
+ for path in path_line.split(','):
+ path = sanitize_name(path.strip())
+ if CRL_MATCHER.match(path):
+ crls.append(path)
+ else:
+ certs.append(path)
+
+ assert certs
+ assert crls
+ assert expected_result is not None
+ sanitized_test_name = generate_test(test_case_name, test_number, test_name,
+ certs, crls, expected_result, output)
+
+ return i, sanitized_test_name
+
+
+def main():
+ pkits_pdf_path, output_path = sys.argv[1:]
+
+ pkits_txt_file = tempfile.NamedTemporaryFile()
+
+ subprocess.check_call(['pdftotext', '-layout', '-nopgbrk', '-eol', 'unix',
+ pkits_pdf_path, pkits_txt_file.name])
+
+ test_descriptions = pkits_txt_file.read()
+
+ # Extract section 4 of the text, which is the part that contains the tests.
+ test_descriptions = test_descriptions.split(
+ '4 Certification Path Validation Tests')[-1]
+ test_descriptions = test_descriptions.split(
+ '5 Relationship to Previous Test Suite', 1)[0]
+
+ output = open(output_path, 'w')
+ output.write('// Autogenerated by %s, do not edit\n\n' % sys.argv[0])
+ output.write('// Hack to allow disabling type parameterized test cases.\n'
+ '// See https://github.com/google/googletest/issues/389\n')
+ output.write('#define WRAPPED_TYPED_TEST_P(CaseName, TestName) '
+ 'TYPED_TEST_P(CaseName, TestName)\n')
+ output.write('#define WRAPPED_REGISTER_TYPED_TEST_CASE_P(CaseName, ...) '
+ 'REGISTER_TYPED_TEST_CASE_P(CaseName, __VA_ARGS__)\n\n')
+
+ test_case_name = None
+ sanitized_test_names = []
+
+ lines = test_descriptions.splitlines()
+
+ i = 0
+ while i < len(lines):
+ section_match = SECTION_MATCHER.match(lines[i])
+ match = TEST_MATCHER.match(lines[i])
+ i += 1
+
+ if section_match:
+ if test_case_name:
+ finalize_test_case(test_case_name, sanitized_test_names, output)
+ sanitized_test_names = []
+
+ # TODO(mattm): Handle certificate policies tests.
+ if section_match.group(1) in ('4.8', '4.9', '4.10', '4.11', '4.12'):
+ test_case_name = None
+ output.write('\n// Skipping section %s\n' % section_match.group(1))
+ continue
+
+ test_case_name = 'PkitsTest%02d%s' % (
+ int(section_match.group(1).split('.')[-1]),
+ sanitize_name(section_match.group(2)))
+ output.write('\ntemplate <typename PkitsTestDelegate>\n')
+ output.write('class %s : public PkitsTest<PkitsTestDelegate> {};\n' % test_case_name)
+ output.write('TYPED_TEST_CASE_P(%s);\n' % test_case_name)
+
+ if match:
+ test_number = match.group(1)
+ test_name = match.group(2)
+ if not test_case_name:
+ output.write('// Skipped %s %s\n' % (test_number, test_name))
+ continue
+ i, sanitized_test_name = parse_test(lines, i, test_case_name, test_number,
+ test_name, output)
+ if sanitized_test_name:
+ sanitized_test_names.append(sanitized_test_name)
+
+ if test_case_name:
+ finalize_test_case(test_case_name, sanitized_test_names, output)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/net/third_party/nist-pkits/pkits_testcases-inl.h b/chromium/net/third_party/nist-pkits/pkits_testcases-inl.h
new file mode 100644
index 00000000000..22f3c47d551
--- /dev/null
+++ b/chromium/net/third_party/nist-pkits/pkits_testcases-inl.h
@@ -0,0 +1,2035 @@
+// Autogenerated by generate_tests.py, do not edit
+
+// Hack to allow disabling type parameterized test cases.
+// See https://github.com/google/googletest/issues/389
+#define WRAPPED_TYPED_TEST_P(CaseName, TestName) \
+ TYPED_TEST_P(CaseName, TestName)
+#define WRAPPED_REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
+ REGISTER_TYPED_TEST_CASE_P(CaseName, __VA_ARGS__)
+
+template <typename PkitsTestDelegate>
+class PkitsTest01SignatureVerification : public PkitsTest<PkitsTestDelegate> {};
+TYPED_TEST_CASE_P(PkitsTest01SignatureVerification);
+
+// 4.1.1 Valid Signatures Test1
+WRAPPED_TYPED_TEST_P(PkitsTest01SignatureVerification,
+ Section1ValidSignaturesTest1) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "ValidCertificatePathTest1EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.1.2 Invalid CA Signature Test2
+WRAPPED_TYPED_TEST_P(PkitsTest01SignatureVerification,
+ Section1InvalidCASignatureTest2) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "BadSignedCACert",
+ "InvalidCASignatureTest2EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "BadSignedCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.1.3 Invalid EE Signature Test3
+WRAPPED_TYPED_TEST_P(PkitsTest01SignatureVerification,
+ Section1InvalidEESignatureTest3) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "InvalidEESignatureTest3EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.1.4 Valid DSA Signatures Test4
+WRAPPED_TYPED_TEST_P(PkitsTest01SignatureVerification,
+ Section1ValidDSASignaturesTest4) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "DSACACert",
+ "ValidDSASignaturesTest4EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "DSACACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.1.5 Valid DSA Parameter Inheritance Test5
+WRAPPED_TYPED_TEST_P(PkitsTest01SignatureVerification,
+ Section1ValidDSAParameterInheritanceTest5) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "DSACACert",
+ "DSAParametersInheritedCACert",
+ "ValidDSAParameterInheritanceTest5EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "DSACACRL",
+ "DSAParametersInheritedCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.1.6 Invalid DSA Signature Test6
+WRAPPED_TYPED_TEST_P(PkitsTest01SignatureVerification,
+ Section1InvalidDSASignatureTest6) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "DSACACert",
+ "InvalidDSASignatureTest6EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "DSACACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+WRAPPED_REGISTER_TYPED_TEST_CASE_P(PkitsTest01SignatureVerification,
+ Section1ValidSignaturesTest1,
+ Section1InvalidCASignatureTest2,
+ Section1InvalidEESignatureTest3,
+ Section1ValidDSASignaturesTest4,
+ Section1ValidDSAParameterInheritanceTest5,
+ Section1InvalidDSASignatureTest6);
+
+template <typename PkitsTestDelegate>
+class PkitsTest02ValidityPeriods : public PkitsTest<PkitsTestDelegate> {};
+TYPED_TEST_CASE_P(PkitsTest02ValidityPeriods);
+
+// 4.2.1 Invalid CA notBefore Date Test1
+WRAPPED_TYPED_TEST_P(PkitsTest02ValidityPeriods,
+ Section2InvalidCAnotBeforeDateTest1) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "BadnotBeforeDateCACert",
+ "InvalidCAnotBeforeDateTest1EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "BadnotBeforeDateCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.2.2 Invalid EE notBefore Date Test2
+WRAPPED_TYPED_TEST_P(PkitsTest02ValidityPeriods,
+ Section2InvalidEEnotBeforeDateTest2) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "InvalidEEnotBeforeDateTest2EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.2.3 Valid pre2000 UTC notBefore Date Test3
+WRAPPED_TYPED_TEST_P(PkitsTest02ValidityPeriods,
+ Section2Validpre2000UTCnotBeforeDateTest3) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "Validpre2000UTCnotBeforeDateTest3EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.2.4 Valid GeneralizedTime notBefore Date Test4
+WRAPPED_TYPED_TEST_P(PkitsTest02ValidityPeriods,
+ Section2ValidGeneralizedTimenotBeforeDateTest4) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "ValidGeneralizedTimenotBeforeDateTest4EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.2.5 Invalid CA notAfter Date Test5
+WRAPPED_TYPED_TEST_P(PkitsTest02ValidityPeriods,
+ Section2InvalidCAnotAfterDateTest5) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "BadnotAfterDateCACert",
+ "InvalidCAnotAfterDateTest5EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "BadnotAfterDateCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.2.6 Invalid EE notAfter Date Test6
+WRAPPED_TYPED_TEST_P(PkitsTest02ValidityPeriods,
+ Section2InvalidEEnotAfterDateTest6) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "InvalidEEnotAfterDateTest6EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.2.7 Invalid pre2000 UTC EE notAfter Date Test7
+WRAPPED_TYPED_TEST_P(PkitsTest02ValidityPeriods,
+ Section2Invalidpre2000UTCEEnotAfterDateTest7) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "Invalidpre2000UTCEEnotAfterDateTest7EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.2.8 Valid GeneralizedTime notAfter Date Test8
+WRAPPED_TYPED_TEST_P(PkitsTest02ValidityPeriods,
+ Section2ValidGeneralizedTimenotAfterDateTest8) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "ValidGeneralizedTimenotAfterDateTest8EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+WRAPPED_REGISTER_TYPED_TEST_CASE_P(
+ PkitsTest02ValidityPeriods,
+ Section2InvalidCAnotBeforeDateTest1,
+ Section2InvalidEEnotBeforeDateTest2,
+ Section2Validpre2000UTCnotBeforeDateTest3,
+ Section2ValidGeneralizedTimenotBeforeDateTest4,
+ Section2InvalidCAnotAfterDateTest5,
+ Section2InvalidEEnotAfterDateTest6,
+ Section2Invalidpre2000UTCEEnotAfterDateTest7,
+ Section2ValidGeneralizedTimenotAfterDateTest8);
+
+template <typename PkitsTestDelegate>
+class PkitsTest03VerifyingNameChaining : public PkitsTest<PkitsTestDelegate> {};
+TYPED_TEST_CASE_P(PkitsTest03VerifyingNameChaining);
+
+// 4.3.1 Invalid Name Chaining EE Test1
+WRAPPED_TYPED_TEST_P(PkitsTest03VerifyingNameChaining,
+ Section3InvalidNameChainingEETest1) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "InvalidNameChainingTest1EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.3.2 Invalid Name Chaining Order Test2
+WRAPPED_TYPED_TEST_P(PkitsTest03VerifyingNameChaining,
+ Section3InvalidNameChainingOrderTest2) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "NameOrderingCACert",
+ "InvalidNameChainingOrderTest2EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "NameOrderCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.3.3 Valid Name Chaining Whitespace Test3
+WRAPPED_TYPED_TEST_P(PkitsTest03VerifyingNameChaining,
+ Section3ValidNameChainingWhitespaceTest3) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "ValidNameChainingWhitespaceTest3EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.3.4 Valid Name Chaining Whitespace Test4
+WRAPPED_TYPED_TEST_P(PkitsTest03VerifyingNameChaining,
+ Section3ValidNameChainingWhitespaceTest4) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "ValidNameChainingWhitespaceTest4EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.3.5 Valid Name Chaining Capitalization Test5
+WRAPPED_TYPED_TEST_P(PkitsTest03VerifyingNameChaining,
+ Section3ValidNameChainingCapitalizationTest5) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "ValidNameChainingCapitalizationTest5EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.3.6 Valid Name Chaining UIDs Test6
+WRAPPED_TYPED_TEST_P(PkitsTest03VerifyingNameChaining,
+ Section3ValidNameChainingUIDsTest6) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "UIDCACert",
+ "ValidNameUIDsTest6EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "UIDCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.3.7 Valid RFC3280 Mandatory Attribute Types Test7
+WRAPPED_TYPED_TEST_P(PkitsTest03VerifyingNameChaining,
+ Section3ValidRFC3280MandatoryAttributeTypesTest7) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "RFC3280MandatoryAttributeTypesCACert",
+ "ValidRFC3280MandatoryAttributeTypesTest7EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "RFC3280MandatoryAttributeTypesCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.3.8 Valid RFC3280 Optional Attribute Types Test8
+WRAPPED_TYPED_TEST_P(PkitsTest03VerifyingNameChaining,
+ Section3ValidRFC3280OptionalAttributeTypesTest8) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "RFC3280OptionalAttributeTypesCACert",
+ "ValidRFC3280OptionalAttributeTypesTest8EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "RFC3280OptionalAttributeTypesCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.3.9 Valid UTF8String Encoded Names Test9
+WRAPPED_TYPED_TEST_P(PkitsTest03VerifyingNameChaining,
+ Section3ValidUTF8StringEncodedNamesTest9) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "UTF8StringEncodedNamesCACert",
+ "ValidUTF8StringEncodedNamesTest9EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "UTF8StringEncodedNamesCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.3.10 Valid Rollover from PrintableString to UTF8String Test10
+WRAPPED_TYPED_TEST_P(
+ PkitsTest03VerifyingNameChaining,
+ Section3ValidRolloverfromPrintableStringtoUTF8StringTest10) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate",
+ "RolloverfromPrintableStringtoUTF8StringCACert",
+ "ValidRolloverfromPrintableStringtoUTF8StringTest10EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "RolloverfromPrintableStringtoUTF8StringCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.3.11 Valid UTF8String Case Insensitive Match Test11
+WRAPPED_TYPED_TEST_P(PkitsTest03VerifyingNameChaining,
+ Section3ValidUTF8StringCaseInsensitiveMatchTest11) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "UTF8StringCaseInsensitiveMatchCACert",
+ "ValidUTF8StringCaseInsensitiveMatchTest11EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "UTF8StringCaseInsensitiveMatchCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+WRAPPED_REGISTER_TYPED_TEST_CASE_P(
+ PkitsTest03VerifyingNameChaining,
+ Section3InvalidNameChainingEETest1,
+ Section3InvalidNameChainingOrderTest2,
+ Section3ValidNameChainingWhitespaceTest3,
+ Section3ValidNameChainingWhitespaceTest4,
+ Section3ValidNameChainingCapitalizationTest5,
+ Section3ValidNameChainingUIDsTest6,
+ Section3ValidRFC3280MandatoryAttributeTypesTest7,
+ Section3ValidRFC3280OptionalAttributeTypesTest8,
+ Section3ValidUTF8StringEncodedNamesTest9,
+ Section3ValidRolloverfromPrintableStringtoUTF8StringTest10,
+ Section3ValidUTF8StringCaseInsensitiveMatchTest11);
+
+template <typename PkitsTestDelegate>
+class PkitsTest04BasicCertificateRevocationTests
+ : public PkitsTest<PkitsTestDelegate> {};
+TYPED_TEST_CASE_P(PkitsTest04BasicCertificateRevocationTests);
+
+// 4.4.1 Missing CRL Test1
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4MissingCRLTest1) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "NoCRLCACert",
+ "InvalidMissingCRLTest1EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.2 Invalid Revoked CA Test2
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidRevokedCATest2) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "RevokedsubCACert", "InvalidRevokedCATest2EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL",
+ "RevokedsubCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.3 Invalid Revoked EE Test3
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidRevokedEETest3) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "GoodCACert",
+ "InvalidRevokedEETest3EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.4 Invalid Bad CRL Signature Test4
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidBadCRLSignatureTest4) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "BadCRLSignatureCACert",
+ "InvalidBadCRLSignatureTest4EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "BadCRLSignatureCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.5 Invalid Bad CRL Issuer Name Test5
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidBadCRLIssuerNameTest5) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "BadCRLIssuerNameCACert",
+ "InvalidBadCRLIssuerNameTest5EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "BadCRLIssuerNameCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.6 Invalid Wrong CRL Test6
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidWrongCRLTest6) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "WrongCRLCACert",
+ "InvalidWrongCRLTest6EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "WrongCRLCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.7 Valid Two CRLs Test7
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4ValidTwoCRLsTest7) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "TwoCRLsCACert",
+ "ValidTwoCRLsTest7EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "TwoCRLsCAGoodCRL",
+ "TwoCRLsCABadCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.4.8 Invalid Unknown CRL Entry Extension Test8
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidUnknownCRLEntryExtensionTest8) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "UnknownCRLEntryExtensionCACert",
+ "InvalidUnknownCRLEntryExtensionTest8EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "UnknownCRLEntryExtensionCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.9 Invalid Unknown CRL Extension Test9
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidUnknownCRLExtensionTest9) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "UnknownCRLExtensionCACert",
+ "InvalidUnknownCRLExtensionTest9EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "UnknownCRLExtensionCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.10 Invalid Unknown CRL Extension Test10
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidUnknownCRLExtensionTest10) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "UnknownCRLExtensionCACert",
+ "InvalidUnknownCRLExtensionTest10EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "UnknownCRLExtensionCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.11 Invalid Old CRL nextUpdate Test11
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidOldCRLnextUpdateTest11) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "OldCRLnextUpdateCACert",
+ "InvalidOldCRLnextUpdateTest11EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "OldCRLnextUpdateCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.12 Invalid pre2000 CRL nextUpdate Test12
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4Invalidpre2000CRLnextUpdateTest12) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "pre2000CRLnextUpdateCACert",
+ "Invalidpre2000CRLnextUpdateTest12EESeetheintrod"
+ "uctiontoSection4.4formoreinformation."};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "pre2000CRLnextUpdateCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.13 Valid GeneralizedTime CRL nextUpdate Test13
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4ValidGeneralizedTimeCRLnextUpdateTest13) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "GeneralizedTimeCRLnextUpdateCACert",
+ "ValidGeneralizedTimeCRLnextUpdateTest13EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "GeneralizedTimeCRLnextUpdateCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.4.14 Valid Negative Serial Number Test14
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4ValidNegativeSerialNumberTest14) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "NegativeSerialNumberCACert",
+ "ValidNegativeSerialNumberTest14EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "NegativeSerialNumberCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.4.15 Invalid Negative Serial Number Test15
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidNegativeSerialNumberTest15) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "NegativeSerialNumberCACert",
+ "InvalidNegativeSerialNumberTest15EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "NegativeSerialNumberCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.16 Valid Long Serial Number Test16
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4ValidLongSerialNumberTest16) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "LongSerialNumberCACert",
+ "ValidLongSerialNumberTest16EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "LongSerialNumberCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.4.17 Valid Long Serial Number Test17
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4ValidLongSerialNumberTest17) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "LongSerialNumberCACert",
+ "ValidLongSerialNumberTest17EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "LongSerialNumberCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.4.18 Invalid Long Serial Number Test18
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidLongSerialNumberTest18) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "LongSerialNumberCACert",
+ "InvalidLongSerialNumberTest18EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "LongSerialNumberCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.19 Valid Separate Certificate and CRL Keys Test19
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4ValidSeparateCertificateandCRLKeysTest19) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate",
+ "SeparateCertificateandCRLKeysCertificateSigningCACert",
+ "SeparateCertificateandCRLKeysCRLSigningCert",
+ "ValidSeparateCertificateandCRLKeysTest19EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "SeparateCertificateandCRLKeysCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.4.20 Invalid Separate Certificate and CRL Keys Test20
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidSeparateCertificateandCRLKeysTest20) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate",
+ "SeparateCertificateandCRLKeysCertificateSigningCACert",
+ "SeparateCertificateandCRLKeysCRLSigningCert",
+ "InvalidSeparateCertificateandCRLKeysTest20EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "SeparateCertificateandCRLKeysCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.4.21 Invalid Separate Certificate and CRL Keys Test21
+WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
+ Section4InvalidSeparateCertificateandCRLKeysTest21) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate",
+ "SeparateCertificateandCRLKeysCA2CertificateSigningCACert",
+ "SeparateCertificateandCRLKeysCA2CRLSigningCert",
+ "InvalidSeparateCertificateandCRLKeysTest21EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "SeparateCertificateandCRLKeysCA2CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+WRAPPED_REGISTER_TYPED_TEST_CASE_P(
+ PkitsTest04BasicCertificateRevocationTests,
+ Section4MissingCRLTest1,
+ Section4InvalidRevokedCATest2,
+ Section4InvalidRevokedEETest3,
+ Section4InvalidBadCRLSignatureTest4,
+ Section4InvalidBadCRLIssuerNameTest5,
+ Section4InvalidWrongCRLTest6,
+ Section4ValidTwoCRLsTest7,
+ Section4InvalidUnknownCRLEntryExtensionTest8,
+ Section4InvalidUnknownCRLExtensionTest9,
+ Section4InvalidUnknownCRLExtensionTest10,
+ Section4InvalidOldCRLnextUpdateTest11,
+ Section4Invalidpre2000CRLnextUpdateTest12,
+ Section4ValidGeneralizedTimeCRLnextUpdateTest13,
+ Section4ValidNegativeSerialNumberTest14,
+ Section4InvalidNegativeSerialNumberTest15,
+ Section4ValidLongSerialNumberTest16,
+ Section4ValidLongSerialNumberTest17,
+ Section4InvalidLongSerialNumberTest18,
+ Section4ValidSeparateCertificateandCRLKeysTest19,
+ Section4InvalidSeparateCertificateandCRLKeysTest20,
+ Section4InvalidSeparateCertificateandCRLKeysTest21);
+
+template <typename PkitsTestDelegate>
+class PkitsTest05VerifyingPathswithSelfIssuedCertificates
+ : public PkitsTest<PkitsTestDelegate> {};
+TYPED_TEST_CASE_P(PkitsTest05VerifyingPathswithSelfIssuedCertificates);
+
+// 4.5.1 Valid Basic Self-Issued Old With New Test1
+WRAPPED_TYPED_TEST_P(PkitsTest05VerifyingPathswithSelfIssuedCertificates,
+ Section5ValidBasicSelfIssuedOldWithNewTest1) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "BasicSelfIssuedNewKeyCACert",
+ "BasicSelfIssuedNewKeyOldWithNewCACert",
+ "ValidBasicSelfIssuedOldWithNewTest1EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "BasicSelfIssuedNewKeyCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.5.2 Invalid Basic Self-Issued Old With New Test2
+WRAPPED_TYPED_TEST_P(PkitsTest05VerifyingPathswithSelfIssuedCertificates,
+ Section5InvalidBasicSelfIssuedOldWithNewTest2) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "BasicSelfIssuedNewKeyCACert",
+ "BasicSelfIssuedNewKeyOldWithNewCACert",
+ "InvalidBasicSelfIssuedOldWithNewTest2EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "BasicSelfIssuedNewKeyCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.5.3 Valid Basic Self-Issued New With Old Test3
+WRAPPED_TYPED_TEST_P(PkitsTest05VerifyingPathswithSelfIssuedCertificates,
+ Section5ValidBasicSelfIssuedNewWithOldTest3) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "BasicSelfIssuedOldKeyCACert",
+ "BasicSelfIssuedOldKeyNewWithOldCACert",
+ "ValidBasicSelfIssuedNewWithOldTest3EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "BasicSelfIssuedOldKeySelfIssuedCertCRL",
+ "BasicSelfIssuedOldKeyCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.5.4 Valid Basic Self-Issued New With Old Test4
+WRAPPED_TYPED_TEST_P(PkitsTest05VerifyingPathswithSelfIssuedCertificates,
+ Section5ValidBasicSelfIssuedNewWithOldTest4) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "BasicSelfIssuedOldKeyCACert",
+ "BasicSelfIssuedOldKeyNewWithOldCACert",
+ "ValidBasicSelfIssuedNewWithOldTest4EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "BasicSelfIssuedOldKeySelfIssuedCertCRL",
+ "BasicSelfIssuedOldKeyCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.5.5 Invalid Basic Self-Issued New With Old Test5
+WRAPPED_TYPED_TEST_P(PkitsTest05VerifyingPathswithSelfIssuedCertificates,
+ Section5InvalidBasicSelfIssuedNewWithOldTest5) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "BasicSelfIssuedOldKeyCACert",
+ "BasicSelfIssuedOldKeyNewWithOldCACert",
+ "InvalidBasicSelfIssuedNewWithOldTest5EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "BasicSelfIssuedOldKeySelfIssuedCertCRL",
+ "BasicSelfIssuedOldKeyCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.5.6 Valid Basic Self-Issued CRL Signing Key Test6
+WRAPPED_TYPED_TEST_P(PkitsTest05VerifyingPathswithSelfIssuedCertificates,
+ Section5ValidBasicSelfIssuedCRLSigningKeyTest6) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "BasicSelfIssuedCRLSigningKeyCACert",
+ "BasicSelfIssuedCRLSigningKeyCRLCert",
+ "ValidBasicSelfIssuedCRLSigningKeyTest6EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "BasicSelfIssuedCRLSigningKeyCRLCertCRL",
+ "BasicSelfIssuedCRLSigningKeyCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.5.7 Invalid Basic Self-Issued CRL Signing Key Test7
+WRAPPED_TYPED_TEST_P(PkitsTest05VerifyingPathswithSelfIssuedCertificates,
+ Section5InvalidBasicSelfIssuedCRLSigningKeyTest7) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "BasicSelfIssuedCRLSigningKeyCACert",
+ "BasicSelfIssuedCRLSigningKeyCRLCert",
+ "InvalidBasicSelfIssuedCRLSigningKeyTest7EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "BasicSelfIssuedCRLSigningKeyCRLCertCRL",
+ "BasicSelfIssuedCRLSigningKeyCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.5.8 Invalid Basic Self-Issued CRL Signing Key Test8
+WRAPPED_TYPED_TEST_P(PkitsTest05VerifyingPathswithSelfIssuedCertificates,
+ Section5InvalidBasicSelfIssuedCRLSigningKeyTest8) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "BasicSelfIssuedCRLSigningKeyCACert",
+ "BasicSelfIssuedCRLSigningKeyCRLCert",
+ "InvalidBasicSelfIssuedCRLSigningKeyTest8EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "BasicSelfIssuedCRLSigningKeyCRLCertCRL",
+ "BasicSelfIssuedCRLSigningKeyCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+WRAPPED_REGISTER_TYPED_TEST_CASE_P(
+ PkitsTest05VerifyingPathswithSelfIssuedCertificates,
+ Section5ValidBasicSelfIssuedOldWithNewTest1,
+ Section5InvalidBasicSelfIssuedOldWithNewTest2,
+ Section5ValidBasicSelfIssuedNewWithOldTest3,
+ Section5ValidBasicSelfIssuedNewWithOldTest4,
+ Section5InvalidBasicSelfIssuedNewWithOldTest5,
+ Section5ValidBasicSelfIssuedCRLSigningKeyTest6,
+ Section5InvalidBasicSelfIssuedCRLSigningKeyTest7,
+ Section5InvalidBasicSelfIssuedCRLSigningKeyTest8);
+
+template <typename PkitsTestDelegate>
+class PkitsTest06VerifyingBasicConstraints
+ : public PkitsTest<PkitsTestDelegate> {};
+TYPED_TEST_CASE_P(PkitsTest06VerifyingBasicConstraints);
+
+// 4.6.1 Invalid Missing basicConstraints Test1
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6InvalidMissingbasicConstraintsTest1) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "MissingbasicConstraintsCACert",
+ "InvalidMissingbasicConstraintsTest1EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "MissingbasicConstraintsCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.6.2 Invalid cA False Test2
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6InvalidcAFalseTest2) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "basicConstraintsCriticalcAFalseCACert",
+ "InvalidcAFalseTest2EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "basicConstraintsCriticalcAFalseCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.6.3 Invalid cA False Test3
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6InvalidcAFalseTest3) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "basicConstraintsNotCriticalcAFalseCACert",
+ "InvalidcAFalseTest3EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "basicConstraintsNotCriticalcAFalseCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.6.4 Valid basicConstraints Not Critical Test4
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6ValidbasicConstraintsNotCriticalTest4) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "basicConstraintsNotCriticalCACert",
+ "ValidbasicConstraintsNotCriticalTest4EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "basicConstraintsNotCriticalCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.6.5 Invalid pathLenConstraint Test5
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6InvalidpathLenConstraintTest5) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "pathLenConstraint0CACert",
+ "pathLenConstraint0subCACert", "InvalidpathLenConstraintTest5EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint0CACRL",
+ "pathLenConstraint0subCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.6.6 Invalid pathLenConstraint Test6
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6InvalidpathLenConstraintTest6) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "pathLenConstraint0CACert",
+ "pathLenConstraint0subCACert", "InvalidpathLenConstraintTest6EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint0CACRL",
+ "pathLenConstraint0subCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.6.7 Valid pathLenConstraint Test7
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6ValidpathLenConstraintTest7) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "pathLenConstraint0CACert",
+ "ValidpathLenConstraintTest7EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint0CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.6.8 Valid pathLenConstraint Test8
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6ValidpathLenConstraintTest8) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "pathLenConstraint0CACert",
+ "ValidpathLenConstraintTest8EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint0CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.6.9 Invalid pathLenConstraint Test9
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6InvalidpathLenConstraintTest9) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "pathLenConstraint6CACert",
+ "pathLenConstraint6subCA0Cert", "pathLenConstraint6subsubCA00Cert",
+ "InvalidpathLenConstraintTest9EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint6CACRL",
+ "pathLenConstraint6subCA0CRL",
+ "pathLenConstraint6subsubCA00CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.6.10 Invalid pathLenConstraint Test10
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6InvalidpathLenConstraintTest10) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "pathLenConstraint6CACert",
+ "pathLenConstraint6subCA0Cert", "pathLenConstraint6subsubCA00Cert",
+ "InvalidpathLenConstraintTest10EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint6CACRL",
+ "pathLenConstraint6subCA0CRL",
+ "pathLenConstraint6subsubCA00CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.6.11 Invalid pathLenConstraint Test11
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6InvalidpathLenConstraintTest11) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "pathLenConstraint6CACert",
+ "pathLenConstraint6subCA1Cert",
+ "pathLenConstraint6subsubCA11Cert",
+ "pathLenConstraint6subsubsubCA11XCert",
+ "InvalidpathLenConstraintTest11EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint6CACRL",
+ "pathLenConstraint6subCA1CRL",
+ "pathLenConstraint6subsubCA11CRL",
+ "pathLenConstraint6subsubsubCA11XCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.6.12 Invalid pathLenConstraint Test12
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6InvalidpathLenConstraintTest12) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "pathLenConstraint6CACert",
+ "pathLenConstraint6subCA1Cert",
+ "pathLenConstraint6subsubCA11Cert",
+ "pathLenConstraint6subsubsubCA11XCert",
+ "InvalidpathLenConstraintTest12EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint6CACRL",
+ "pathLenConstraint6subCA1CRL",
+ "pathLenConstraint6subsubCA11CRL",
+ "pathLenConstraint6subsubsubCA11XCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.6.13 Valid pathLenConstraint Test13
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6ValidpathLenConstraintTest13) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "pathLenConstraint6CACert",
+ "pathLenConstraint6subCA4Cert",
+ "pathLenConstraint6subsubCA41Cert",
+ "pathLenConstraint6subsubsubCA41XCert",
+ "ValidpathLenConstraintTest13EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint6CACRL",
+ "pathLenConstraint6subCA4CRL",
+ "pathLenConstraint6subsubCA41CRL",
+ "pathLenConstraint6subsubsubCA41XCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.6.14 Valid pathLenConstraint Test14
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6ValidpathLenConstraintTest14) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "pathLenConstraint6CACert",
+ "pathLenConstraint6subCA4Cert",
+ "pathLenConstraint6subsubCA41Cert",
+ "pathLenConstraint6subsubsubCA41XCert",
+ "ValidpathLenConstraintTest14EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint6CACRL",
+ "pathLenConstraint6subCA4CRL",
+ "pathLenConstraint6subsubCA41CRL",
+ "pathLenConstraint6subsubsubCA41XCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.6.15 Valid Self-Issued pathLenConstraint Test15
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6ValidSelfIssuedpathLenConstraintTest15) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "pathLenConstraint0CACert",
+ "pathLenConstraint0SelfIssuedCACert",
+ "ValidSelfIssuedpathLenConstraintTest15EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint0CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.6.16 Invalid Self-Issued pathLenConstraint Test16
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6InvalidSelfIssuedpathLenConstraintTest16) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "pathLenConstraint0CACert",
+ "pathLenConstraint0SelfIssuedCACert", "pathLenConstraint0subCA2Cert",
+ "InvalidSelfIssuedpathLenConstraintTest16EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint0CACRL",
+ "pathLenConstraint0subCA2CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.6.17 Valid Self-Issued pathLenConstraint Test17
+WRAPPED_TYPED_TEST_P(PkitsTest06VerifyingBasicConstraints,
+ Section6ValidSelfIssuedpathLenConstraintTest17) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "pathLenConstraint1CACert",
+ "pathLenConstraint1SelfIssuedCACert",
+ "pathLenConstraint1subCACert",
+ "pathLenConstraint1SelfIssuedsubCACert",
+ "ValidSelfIssuedpathLenConstraintTest17EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "pathLenConstraint1CACRL",
+ "pathLenConstraint1subCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+WRAPPED_REGISTER_TYPED_TEST_CASE_P(
+ PkitsTest06VerifyingBasicConstraints,
+ Section6InvalidMissingbasicConstraintsTest1,
+ Section6InvalidcAFalseTest2,
+ Section6InvalidcAFalseTest3,
+ Section6ValidbasicConstraintsNotCriticalTest4,
+ Section6InvalidpathLenConstraintTest5,
+ Section6InvalidpathLenConstraintTest6,
+ Section6ValidpathLenConstraintTest7,
+ Section6ValidpathLenConstraintTest8,
+ Section6InvalidpathLenConstraintTest9,
+ Section6InvalidpathLenConstraintTest10,
+ Section6InvalidpathLenConstraintTest11,
+ Section6InvalidpathLenConstraintTest12,
+ Section6ValidpathLenConstraintTest13,
+ Section6ValidpathLenConstraintTest14,
+ Section6ValidSelfIssuedpathLenConstraintTest15,
+ Section6InvalidSelfIssuedpathLenConstraintTest16,
+ Section6ValidSelfIssuedpathLenConstraintTest17);
+
+template <typename PkitsTestDelegate>
+class PkitsTest07KeyUsage : public PkitsTest<PkitsTestDelegate> {};
+TYPED_TEST_CASE_P(PkitsTest07KeyUsage);
+
+// 4.7.1 Invalid keyUsage Critical keyCertSign False Test1
+WRAPPED_TYPED_TEST_P(PkitsTest07KeyUsage,
+ Section7InvalidkeyUsageCriticalkeyCertSignFalseTest1) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "keyUsageCriticalkeyCertSignFalseCACert",
+ "InvalidkeyUsageCriticalkeyCertSignFalseTest1EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "keyUsageCriticalkeyCertSignFalseCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.7.2 Invalid keyUsage Not Critical keyCertSign False Test2
+WRAPPED_TYPED_TEST_P(PkitsTest07KeyUsage,
+ Section7InvalidkeyUsageNotCriticalkeyCertSignFalseTest2) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "keyUsageNotCriticalkeyCertSignFalseCACert",
+ "InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "keyUsageNotCriticalkeyCertSignFalseCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.7.3 Valid keyUsage Not Critical Test3
+WRAPPED_TYPED_TEST_P(PkitsTest07KeyUsage,
+ Section7ValidkeyUsageNotCriticalTest3) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "keyUsageNotCriticalCACert",
+ "ValidkeyUsageNotCriticalTest3EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "keyUsageNotCriticalCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.7.4 Invalid keyUsage Critical cRLSign False Test4
+WRAPPED_TYPED_TEST_P(PkitsTest07KeyUsage,
+ Section7InvalidkeyUsageCriticalcRLSignFalseTest4) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "keyUsageCriticalcRLSignFalseCACert",
+ "InvalidkeyUsageCriticalcRLSignFalseTest4EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "keyUsageCriticalcRLSignFalseCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.7.5 Invalid keyUsage Not Critical cRLSign False Test5
+WRAPPED_TYPED_TEST_P(PkitsTest07KeyUsage,
+ Section7InvalidkeyUsageNotCriticalcRLSignFalseTest5) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "keyUsageNotCriticalcRLSignFalseCACert",
+ "InvalidkeyUsageNotCriticalcRLSignFalseTest5EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "keyUsageNotCriticalcRLSignFalseCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+WRAPPED_REGISTER_TYPED_TEST_CASE_P(
+ PkitsTest07KeyUsage,
+ Section7InvalidkeyUsageCriticalkeyCertSignFalseTest1,
+ Section7InvalidkeyUsageNotCriticalkeyCertSignFalseTest2,
+ Section7ValidkeyUsageNotCriticalTest3,
+ Section7InvalidkeyUsageCriticalcRLSignFalseTest4,
+ Section7InvalidkeyUsageNotCriticalcRLSignFalseTest5);
+
+// Skipping section 4.8
+// Skipped 4.8.1 All Certificates Same Policy Test1
+// Skipped 4.8.2 All Certificates No Policies Test2
+// Skipped 4.8.3 Different Policies Test3
+// Skipped 4.8.4 Different Policies Test4
+// Skipped 4.8.5 Different Policies Test5
+// Skipped 4.8.6 Overlapping Policies Test6
+// Skipped 4.8.7 Different Policies Test7
+// Skipped 4.8.8 Different Policies Test8
+// Skipped 4.8.9 Different Policies Test9
+// Skipped 4.8.10 All Certificates Same Policies Test10
+// Skipped 4.8.11 All Certificates AnyPolicy Test11
+// Skipped 4.8.12 Different Policies Test12
+// Skipped 4.8.13 All Certificates Same Policies Test13
+// Skipped 4.8.14 AnyPolicy Test14
+// Skipped 4.8.15 User Notice Qualifier Test15
+// Skipped 4.8.16 User Notice Qualifier Test16
+// Skipped 4.8.17 User Notice Qualifier Test17
+// Skipped 4.8.18 User Notice Qualifier Test18
+// Skipped 4.8.19 User Notice Qualifier Test19
+// Skipped 4.8.20 CPS Pointer Qualifier Test20
+
+// Skipping section 4.9
+// Skipped 4.9.1 Valid RequireExplicitPolicy Test1
+// Skipped 4.9.2 Valid RequireExplicitPolicy Test2
+// Skipped 4.9.3 Invalid RequireExplicitPolicy Test3
+// Skipped 4.9.4 Valid RequireExplicitPolicy Test4
+// Skipped 4.9.5 Invalid RequireExplicitPolicy Test5
+// Skipped 4.9.6 Valid Self-Issued requireExplicitPolicy Test6
+// Skipped 4.9.7 Invalid Self-Issued requireExplicitPolicy Test7
+// Skipped 4.9.8 Invalid Self-Issued requireExplicitPolicy Test8
+
+// Skipping section 4.10
+// Skipped 4.10.1 Valid Policy Mapping Test1
+// Skipped 4.10.2 Invalid Policy Mapping Test2
+// Skipped 4.10.3 Valid Policy Mapping Test3
+// Skipped 4.10.4 Invalid Policy Mapping Test4
+// Skipped 4.10.5 Valid Policy Mapping Test5
+// Skipped 4.10.6 Valid Policy Mapping Test6
+// Skipped 4.10.7 Invalid Mapping From anyPolicy Test7
+// Skipped 4.10.8 Invalid Mapping To anyPolicy Test8
+// Skipped 4.10.9 Valid Policy Mapping Test9
+// Skipped 4.10.10 Invalid Policy Mapping Test10
+// Skipped 4.10.11 Valid Policy Mapping Test11
+// Skipped 4.10.12 Valid Policy Mapping Test12
+// Skipped 4.10.13 Valid Policy Mapping Test13
+// Skipped 4.10.14 Valid Policy Mapping Test14
+
+// Skipping section 4.11
+// Skipped 4.11.1 Invalid inhibitPolicyMapping Test1
+// Skipped 4.11.2 Valid inhibitPolicyMapping Test2
+// Skipped 4.11.3 Invalid inhibitPolicyMapping Test3
+// Skipped 4.11.4 Valid inhibitPolicyMapping Test4
+// Skipped 4.11.5 Invalid inhibitPolicyMapping Test5
+// Skipped 4.11.6 Invalid inhibitPolicyMapping Test6
+// Skipped 4.11.7 Valid Self-Issued inhibitPolicyMapping Test7
+// Skipped 4.11.8 Invalid Self-Issued inhibitPolicyMapping Test8
+// Skipped 4.11.9 Invalid Self-Issued inhibitPolicyMapping Test9
+// Skipped 4.11.10 Invalid Self-Issued inhibitPolicyMapping Test10
+// Skipped 4.11.11 Invalid Self-Issued inhibitPolicyMapping Test11
+
+// Skipping section 4.12
+// Skipped 4.12.1 Invalid inhibitAnyPolicy Test1
+// Skipped 4.12.2 Valid inhibitAnyPolicy Test2
+// Skipped 4.12.3 inhibitAnyPolicy Test3
+// Skipped 4.12.4 Invalid inhibitAnyPolicy Test4
+// Skipped 4.12.5 Invalid inhibitAnyPolicy Test5
+// Skipped 4.12.6 Invalid inhibitAnyPolicy Test6
+// Skipped 4.12.7 Valid Self-Issued inhibitAnyPolicy Test7
+// Skipped 4.12.8 Invalid Self-Issued inhibitAnyPolicy Test8
+// Skipped 4.12.9 Valid Self-Issued inhibitAnyPolicy Test9
+// Skipped 4.12.10 Invalid Self-Issued inhibitAnyPolicy Test10
+
+template <typename PkitsTestDelegate>
+class PkitsTest13NameConstraints : public PkitsTest<PkitsTestDelegate> {};
+TYPED_TEST_CASE_P(PkitsTest13NameConstraints);
+
+// 4.13.1 Valid DN nameConstraints Test1
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidDNnameConstraintsTest1) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN1CACert",
+ "ValidDNnameConstraintsTest1EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.2 Invalid DN nameConstraints Test2
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNnameConstraintsTest2) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN1CACert",
+ "InvalidDNnameConstraintsTest2EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.3 Invalid DN nameConstraints Test3
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNnameConstraintsTest3) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN1CACert",
+ "InvalidDNnameConstraintsTest3EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.4 Valid DN nameConstraints Test4
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidDNnameConstraintsTest4) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN1CACert",
+ "ValidDNnameConstraintsTest4EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.5 Valid DN nameConstraints Test5
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidDNnameConstraintsTest5) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN2CACert",
+ "ValidDNnameConstraintsTest5EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN2CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.6 Valid DN nameConstraints Test6
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidDNnameConstraintsTest6) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN3CACert",
+ "ValidDNnameConstraintsTest6EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN3CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.7 Invalid DN nameConstraints Test7
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNnameConstraintsTest7) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN3CACert",
+ "InvalidDNnameConstraintsTest7EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN3CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.8 Invalid DN nameConstraints Test8
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNnameConstraintsTest8) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN4CACert",
+ "InvalidDNnameConstraintsTest8EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN4CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.9 Invalid DN nameConstraints Test9
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNnameConstraintsTest9) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN4CACert",
+ "InvalidDNnameConstraintsTest9EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN4CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.10 Invalid DN nameConstraints Test10
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNnameConstraintsTest10) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN5CACert",
+ "InvalidDNnameConstraintsTest10EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN5CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.11 Valid DN nameConstraints Test11
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidDNnameConstraintsTest11) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN5CACert",
+ "ValidDNnameConstraintsTest11EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN5CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.12 Invalid DN nameConstraints Test12
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNnameConstraintsTest12) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "nameConstraintsDN1CACert",
+ "nameConstraintsDN1subCA1Cert", "InvalidDNnameConstraintsTest12EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL",
+ "nameConstraintsDN1subCA1CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.13 Invalid DN nameConstraints Test13
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNnameConstraintsTest13) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "nameConstraintsDN1CACert",
+ "nameConstraintsDN1subCA2Cert", "InvalidDNnameConstraintsTest13EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL",
+ "nameConstraintsDN1subCA2CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.14 Valid DN nameConstraints Test14
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidDNnameConstraintsTest14) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "nameConstraintsDN1CACert",
+ "nameConstraintsDN1subCA2Cert", "ValidDNnameConstraintsTest14EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL",
+ "nameConstraintsDN1subCA2CRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.15 Invalid DN nameConstraints Test15
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNnameConstraintsTest15) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "nameConstraintsDN3CACert",
+ "nameConstraintsDN3subCA1Cert", "InvalidDNnameConstraintsTest15EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN3CACRL",
+ "nameConstraintsDN3subCA1CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.16 Invalid DN nameConstraints Test16
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNnameConstraintsTest16) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "nameConstraintsDN3CACert",
+ "nameConstraintsDN3subCA1Cert", "InvalidDNnameConstraintsTest16EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN3CACRL",
+ "nameConstraintsDN3subCA1CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.17 Invalid DN nameConstraints Test17
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNnameConstraintsTest17) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "nameConstraintsDN3CACert",
+ "nameConstraintsDN3subCA2Cert", "InvalidDNnameConstraintsTest17EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN3CACRL",
+ "nameConstraintsDN3subCA2CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.18 Valid DN nameConstraints Test18
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidDNnameConstraintsTest18) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "nameConstraintsDN3CACert",
+ "nameConstraintsDN3subCA2Cert", "ValidDNnameConstraintsTest18EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN3CACRL",
+ "nameConstraintsDN3subCA2CRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.19 Valid Self-Issued DN nameConstraints Test19
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidSelfIssuedDNnameConstraintsTest19) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "nameConstraintsDN1CACert",
+ "nameConstraintsDN1SelfIssuedCACert", "ValidDNnameConstraintsTest19EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.20 Invalid Self-Issued DN nameConstraints Test20
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidSelfIssuedDNnameConstraintsTest20) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN1CACert",
+ "InvalidDNnameConstraintsTest20EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.21 Valid RFC822 nameConstraints Test21
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidRFC822nameConstraintsTest21) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsRFC822CA1Cert",
+ "ValidRFC822nameConstraintsTest21EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "nameConstraintsRFC822CA1CRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.22 Invalid RFC822 nameConstraints Test22
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidRFC822nameConstraintsTest22) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsRFC822CA1Cert",
+ "InvalidRFC822nameConstraintsTest22EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "nameConstraintsRFC822CA1CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.23 Valid RFC822 nameConstraints Test23
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidRFC822nameConstraintsTest23) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsRFC822CA2Cert",
+ "ValidRFC822nameConstraintsTest23EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "nameConstraintsRFC822CA2CRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.24 Invalid RFC822 nameConstraints Test24
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidRFC822nameConstraintsTest24) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsRFC822CA2Cert",
+ "InvalidRFC822nameConstraintsTest24EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "nameConstraintsRFC822CA2CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.25 Valid RFC822 nameConstraints Test25
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidRFC822nameConstraintsTest25) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsRFC822CA3Cert",
+ "ValidRFC822nameConstraintsTest25EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "nameConstraintsRFC822CA3CRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.26 Invalid RFC822 nameConstraints Test26
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidRFC822nameConstraintsTest26) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsRFC822CA3Cert",
+ "InvalidRFC822nameConstraintsTest26EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "nameConstraintsRFC822CA3CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.27 Valid DN and RFC822 nameConstraints Test27
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidDNandRFC822nameConstraintsTest27) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN1CACert",
+ "nameConstraintsDN1subCA3Cert",
+ "ValidDNandRFC822nameConstraintsTest27EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL",
+ "nameConstraintsDN1subCA3CRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.28 Invalid DN and RFC822 nameConstraints Test28
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNandRFC822nameConstraintsTest28) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN1CACert",
+ "nameConstraintsDN1subCA3Cert",
+ "InvalidDNandRFC822nameConstraintsTest28EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL",
+ "nameConstraintsDN1subCA3CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.29 Invalid DN and RFC822 nameConstraints Test29
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNandRFC822nameConstraintsTest29) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDN1CACert",
+ "nameConstraintsDN1subCA3Cert",
+ "InvalidDNandRFC822nameConstraintsTest29EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL",
+ "nameConstraintsDN1subCA3CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.30 Valid DNS nameConstraints Test30
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidDNSnameConstraintsTest30) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDNS1CACert",
+ "ValidDNSnameConstraintsTest30EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDNS1CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.31 Invalid DNS nameConstraints Test31
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNSnameConstraintsTest31) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDNS1CACert",
+ "InvalidDNSnameConstraintsTest31EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDNS1CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.32 Valid DNS nameConstraints Test32
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidDNSnameConstraintsTest32) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDNS2CACert",
+ "ValidDNSnameConstraintsTest32EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDNS2CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.33 Invalid DNS nameConstraints Test33
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNSnameConstraintsTest33) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDNS2CACert",
+ "InvalidDNSnameConstraintsTest33EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDNS2CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.34 Valid URI nameConstraints Test34
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidURInameConstraintsTest34) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsURI1CACert",
+ "ValidURInameConstraintsTest34EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsURI1CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.35 Invalid URI nameConstraints Test35
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidURInameConstraintsTest35) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsURI1CACert",
+ "InvalidURInameConstraintsTest35EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsURI1CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.36 Valid URI nameConstraints Test36
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13ValidURInameConstraintsTest36) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsURI2CACert",
+ "ValidURInameConstraintsTest36EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsURI2CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.13.37 Invalid URI nameConstraints Test37
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidURInameConstraintsTest37) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsURI2CACert",
+ "InvalidURInameConstraintsTest37EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsURI2CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.13.38 Invalid DNS nameConstraints Test38
+WRAPPED_TYPED_TEST_P(PkitsTest13NameConstraints,
+ Section13InvalidDNSnameConstraintsTest38) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "nameConstraintsDNS1CACert",
+ "InvalidDNSnameConstraintsTest38EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDNS1CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+WRAPPED_REGISTER_TYPED_TEST_CASE_P(
+ PkitsTest13NameConstraints,
+ Section13ValidDNnameConstraintsTest1,
+ Section13InvalidDNnameConstraintsTest2,
+ Section13InvalidDNnameConstraintsTest3,
+ Section13ValidDNnameConstraintsTest4,
+ Section13ValidDNnameConstraintsTest5,
+ Section13ValidDNnameConstraintsTest6,
+ Section13InvalidDNnameConstraintsTest7,
+ Section13InvalidDNnameConstraintsTest8,
+ Section13InvalidDNnameConstraintsTest9,
+ Section13InvalidDNnameConstraintsTest10,
+ Section13ValidDNnameConstraintsTest11,
+ Section13InvalidDNnameConstraintsTest12,
+ Section13InvalidDNnameConstraintsTest13,
+ Section13ValidDNnameConstraintsTest14,
+ Section13InvalidDNnameConstraintsTest15,
+ Section13InvalidDNnameConstraintsTest16,
+ Section13InvalidDNnameConstraintsTest17,
+ Section13ValidDNnameConstraintsTest18,
+ Section13ValidSelfIssuedDNnameConstraintsTest19,
+ Section13InvalidSelfIssuedDNnameConstraintsTest20,
+ Section13ValidRFC822nameConstraintsTest21,
+ Section13InvalidRFC822nameConstraintsTest22,
+ Section13ValidRFC822nameConstraintsTest23,
+ Section13InvalidRFC822nameConstraintsTest24,
+ Section13ValidRFC822nameConstraintsTest25,
+ Section13InvalidRFC822nameConstraintsTest26,
+ Section13ValidDNandRFC822nameConstraintsTest27,
+ Section13InvalidDNandRFC822nameConstraintsTest28,
+ Section13InvalidDNandRFC822nameConstraintsTest29,
+ Section13ValidDNSnameConstraintsTest30,
+ Section13InvalidDNSnameConstraintsTest31,
+ Section13ValidDNSnameConstraintsTest32,
+ Section13InvalidDNSnameConstraintsTest33,
+ Section13ValidURInameConstraintsTest34,
+ Section13InvalidURInameConstraintsTest35,
+ Section13ValidURInameConstraintsTest36,
+ Section13InvalidURInameConstraintsTest37,
+ Section13InvalidDNSnameConstraintsTest38);
+
+template <typename PkitsTestDelegate>
+class PkitsTest14DistributionPoints : public PkitsTest<PkitsTestDelegate> {};
+TYPED_TEST_CASE_P(PkitsTest14DistributionPoints);
+
+// 4.14.1 Valid distributionPoint Test1
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValiddistributionPointTest1) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "distributionPoint1CACert",
+ "ValiddistributionPointTest1EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "distributionPoint1CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.2 Invalid distributionPoint Test2
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvaliddistributionPointTest2) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "distributionPoint1CACert",
+ "InvaliddistributionPointTest2EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "distributionPoint1CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.3 Invalid distributionPoint Test3
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvaliddistributionPointTest3) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "distributionPoint1CACert",
+ "InvaliddistributionPointTest3EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "distributionPoint1CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.4 Valid distributionPoint Test4
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValiddistributionPointTest4) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "distributionPoint1CACert",
+ "ValiddistributionPointTest4EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "distributionPoint1CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.5 Valid distributionPoint Test5
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValiddistributionPointTest5) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "distributionPoint2CACert",
+ "ValiddistributionPointTest5EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "distributionPoint2CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.6 Invalid distributionPoint Test6
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvaliddistributionPointTest6) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "distributionPoint2CACert",
+ "InvaliddistributionPointTest6EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "distributionPoint2CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.7 Valid distributionPoint Test7
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValiddistributionPointTest7) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "distributionPoint2CACert",
+ "ValiddistributionPointTest7EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "distributionPoint2CACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.8 Invalid distributionPoint Test8
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvaliddistributionPointTest8) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "distributionPoint2CACert",
+ "InvaliddistributionPointTest8EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "distributionPoint2CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.9 Invalid distributionPoint Test9
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvaliddistributionPointTest9) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "distributionPoint2CACert",
+ "InvaliddistributionPointTest9EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "distributionPoint2CACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.10 Valid No issuingDistributionPoint Test10
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValidNoissuingDistributionPointTest10) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "NoissuingDistributionPointCACert",
+ "ValidNoissuingDistributionPointTest10EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "NoissuingDistributionPointCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.11 Invalid onlyContainsUserCerts CRL Test11
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidonlyContainsUserCertsCRLTest11) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "onlyContainsUserCertsCACert",
+ "InvalidonlyContainsUserCertsTest11EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "onlyContainsUserCertsCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.12 Invalid onlyContainsCACerts CRL Test12
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidonlyContainsCACertsCRLTest12) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "onlyContainsCACertsCACert",
+ "InvalidonlyContainsCACertsTest12EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "onlyContainsCACertsCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.13 Valid onlyContainsCACerts CRL Test13
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValidonlyContainsCACertsCRLTest13) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "onlyContainsCACertsCACert",
+ "ValidonlyContainsCACertsTest13EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "onlyContainsCACertsCACRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.14 Invalid onlyContainsAttributeCerts Test14
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidonlyContainsAttributeCertsTest14) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "onlyContainsAttributeCertsCACert",
+ "InvalidonlyContainsAttributeCertsTest14EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "onlyContainsAttributeCertsCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.15 Invalid onlySomeReasons Test15
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidonlySomeReasonsTest15) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "onlySomeReasonsCA1Cert",
+ "InvalidonlySomeReasonsTest15EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "onlySomeReasonsCA1compromiseCRL",
+ "onlySomeReasonsCA1otherreasonsCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.16 Invalid onlySomeReasons Test16
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidonlySomeReasonsTest16) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "onlySomeReasonsCA1Cert",
+ "InvalidonlySomeReasonsTest16EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "onlySomeReasonsCA1compromiseCRL",
+ "onlySomeReasonsCA1otherreasonsCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.17 Invalid onlySomeReasons Test17
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidonlySomeReasonsTest17) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "onlySomeReasonsCA2Cert",
+ "InvalidonlySomeReasonsTest17EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "onlySomeReasonsCA2CRL1",
+ "onlySomeReasonsCA2CRL2"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.18 Valid onlySomeReasons Test18
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValidonlySomeReasonsTest18) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "onlySomeReasonsCA3Cert",
+ "ValidonlySomeReasonsTest18EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "onlySomeReasonsCA3compromiseCRL",
+ "onlySomeReasonsCA3otherreasonsCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.19 Valid onlySomeReasons Test19
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValidonlySomeReasonsTest19) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "onlySomeReasonsCA4Cert",
+ "ValidonlySomeReasonsTest19EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "onlySomeReasonsCA4compromiseCRL",
+ "onlySomeReasonsCA4otherreasonsCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.20 Invalid onlySomeReasons Test20
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidonlySomeReasonsTest20) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "onlySomeReasonsCA4Cert",
+ "InvalidonlySomeReasonsTest20EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "onlySomeReasonsCA4compromiseCRL",
+ "onlySomeReasonsCA4otherreasonsCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.21 Invalid onlySomeReasons Test21
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidonlySomeReasonsTest21) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "onlySomeReasonsCA4Cert",
+ "InvalidonlySomeReasonsTest21EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "onlySomeReasonsCA4compromiseCRL",
+ "onlySomeReasonsCA4otherreasonsCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.22 Valid IDP with indirectCRL Test22
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValidIDPwithindirectCRLTest22) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "indirectCRLCA1Cert",
+ "ValidIDPwithindirectCRLTest22EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "indirectCRLCA1CRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.23 Invalid IDP with indirectCRL Test23
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidIDPwithindirectCRLTest23) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "indirectCRLCA1Cert",
+ "InvalidIDPwithindirectCRLTest23EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "indirectCRLCA1CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.24 Valid IDP with indirectCRL Test24
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValidIDPwithindirectCRLTest24) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "indirectCRLCA2Cert", "indirectCRLCA1Cert",
+ "ValidIDPwithindirectCRLTest24EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "indirectCRLCA1CRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.25 Valid IDP with indirectCRL Test25
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValidIDPwithindirectCRLTest25) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "indirectCRLCA2Cert", "indirectCRLCA1Cert",
+ "ValidIDPwithindirectCRLTest25EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "indirectCRLCA1CRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.26 Invalid IDP with indirectCRL Test26
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidIDPwithindirectCRLTest26) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "indirectCRLCA2Cert", "indirectCRLCA1Cert",
+ "InvalidIDPwithindirectCRLTest26EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "indirectCRLCA1CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.27 Invalid cRLIssuer Test27
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidcRLIssuerTest27) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "indirectCRLCA2Cert", "GoodCACert",
+ "InvalidcRLIssuerTest27EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "GoodCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.28 Valid cRLIssuer Test28
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValidcRLIssuerTest28) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "indirectCRLCA3Cert",
+ "indirectCRLCA3cRLIssuerCert", "ValidcRLIssuerTest28EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "indirectCRLCA3CRL",
+ "indirectCRLCA3cRLIssuerCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.29 Valid cRLIssuer Test29
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValidcRLIssuerTest29) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "indirectCRLCA3Cert",
+ "indirectCRLCA3cRLIssuerCert", "ValidcRLIssuerTest29EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "indirectCRLCA3CRL",
+ "indirectCRLCA3cRLIssuerCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.30 Valid cRLIssuer Test30
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValidcRLIssuerTest30) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate", "indirectCRLCA4Cert",
+ "indirectCRLCA4cRLIssuerCert", "ValidcRLIssuerTest30EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "indirectCRLCA4cRLIssuerCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.31 Invalid cRLIssuer Test31
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidcRLIssuerTest31) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "indirectCRLCA5Cert", "indirectCRLCA6Cert",
+ "InvalidcRLIssuerTest31EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "indirectCRLCA5CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.32 Invalid cRLIssuer Test32
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidcRLIssuerTest32) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "indirectCRLCA5Cert", "indirectCRLCA6Cert",
+ "InvalidcRLIssuerTest32EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "indirectCRLCA5CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.33 Valid cRLIssuer Test33
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14ValidcRLIssuerTest33) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "indirectCRLCA5Cert", "indirectCRLCA6Cert",
+ "ValidcRLIssuerTest33EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "indirectCRLCA5CRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.14.34 Invalid cRLIssuer Test34
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidcRLIssuerTest34) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "indirectCRLCA5Cert",
+ "InvalidcRLIssuerTest34EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "indirectCRLCA5CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.14.35 Invalid cRLIssuer Test35
+WRAPPED_TYPED_TEST_P(PkitsTest14DistributionPoints,
+ Section14InvalidcRLIssuerTest35) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "indirectCRLCA5Cert",
+ "InvalidcRLIssuerTest35EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "indirectCRLCA5CRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+WRAPPED_REGISTER_TYPED_TEST_CASE_P(
+ PkitsTest14DistributionPoints,
+ Section14ValiddistributionPointTest1,
+ Section14InvaliddistributionPointTest2,
+ Section14InvaliddistributionPointTest3,
+ Section14ValiddistributionPointTest4,
+ Section14ValiddistributionPointTest5,
+ Section14InvaliddistributionPointTest6,
+ Section14ValiddistributionPointTest7,
+ Section14InvaliddistributionPointTest8,
+ Section14InvaliddistributionPointTest9,
+ Section14ValidNoissuingDistributionPointTest10,
+ Section14InvalidonlyContainsUserCertsCRLTest11,
+ Section14InvalidonlyContainsCACertsCRLTest12,
+ Section14ValidonlyContainsCACertsCRLTest13,
+ Section14InvalidonlyContainsAttributeCertsTest14,
+ Section14InvalidonlySomeReasonsTest15,
+ Section14InvalidonlySomeReasonsTest16,
+ Section14InvalidonlySomeReasonsTest17,
+ Section14ValidonlySomeReasonsTest18,
+ Section14ValidonlySomeReasonsTest19,
+ Section14InvalidonlySomeReasonsTest20,
+ Section14InvalidonlySomeReasonsTest21,
+ Section14ValidIDPwithindirectCRLTest22,
+ Section14InvalidIDPwithindirectCRLTest23,
+ Section14ValidIDPwithindirectCRLTest24,
+ Section14ValidIDPwithindirectCRLTest25,
+ Section14InvalidIDPwithindirectCRLTest26,
+ Section14InvalidcRLIssuerTest27,
+ Section14ValidcRLIssuerTest28,
+ Section14ValidcRLIssuerTest29,
+ Section14ValidcRLIssuerTest30,
+ Section14InvalidcRLIssuerTest31,
+ Section14InvalidcRLIssuerTest32,
+ Section14ValidcRLIssuerTest33,
+ Section14InvalidcRLIssuerTest34,
+ Section14InvalidcRLIssuerTest35);
+
+template <typename PkitsTestDelegate>
+class PkitsTest15DeltaCRLs : public PkitsTest<PkitsTestDelegate> {};
+TYPED_TEST_CASE_P(PkitsTest15DeltaCRLs);
+
+// 4.15.1 Invalid deltaCRLIndicator No Base Test1
+WRAPPED_TYPED_TEST_P(PkitsTest15DeltaCRLs,
+ Section15InvaliddeltaCRLIndicatorNoBaseTest1) {
+ const char* const certs[] = {"TrustAnchorRootCertificate",
+ "deltaCRLIndicatorNoBaseCACert",
+ "InvaliddeltaCRLIndicatorNoBaseTest1EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL",
+ "deltaCRLIndicatorNoBaseCACRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.15.2 Valid delta-CRL Test2
+WRAPPED_TYPED_TEST_P(PkitsTest15DeltaCRLs, Section15ValiddeltaCRLTest2) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "deltaCRLCA1Cert",
+ "ValiddeltaCRLTest2EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "deltaCRLCA1CRL",
+ "deltaCRLCA1deltaCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.15.3 Invalid delta-CRL Test3
+WRAPPED_TYPED_TEST_P(PkitsTest15DeltaCRLs, Section15InvaliddeltaCRLTest3) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "deltaCRLCA1Cert",
+ "InvaliddeltaCRLTest3EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "deltaCRLCA1CRL",
+ "deltaCRLCA1deltaCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.15.4 Invalid delta-CRL Test4
+WRAPPED_TYPED_TEST_P(PkitsTest15DeltaCRLs, Section15InvaliddeltaCRLTest4) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "deltaCRLCA1Cert",
+ "InvaliddeltaCRLTest4EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "deltaCRLCA1CRL",
+ "deltaCRLCA1deltaCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.15.5 Valid delta-CRL Test5
+WRAPPED_TYPED_TEST_P(PkitsTest15DeltaCRLs, Section15ValiddeltaCRLTest5) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "deltaCRLCA1Cert",
+ "ValiddeltaCRLTest5EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "deltaCRLCA1CRL",
+ "deltaCRLCA1deltaCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.15.6 Invalid delta-CRL Test6
+WRAPPED_TYPED_TEST_P(PkitsTest15DeltaCRLs, Section15InvaliddeltaCRLTest6) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "deltaCRLCA1Cert",
+ "InvaliddeltaCRLTest6EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "deltaCRLCA1CRL",
+ "deltaCRLCA1deltaCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.15.7 Valid delta-CRL Test7
+WRAPPED_TYPED_TEST_P(PkitsTest15DeltaCRLs, Section15ValiddeltaCRLTest7) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "deltaCRLCA1Cert",
+ "ValiddeltaCRLTest7EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "deltaCRLCA1CRL",
+ "deltaCRLCA1deltaCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.15.8 Valid delta-CRL Test8
+WRAPPED_TYPED_TEST_P(PkitsTest15DeltaCRLs, Section15ValiddeltaCRLTest8) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "deltaCRLCA2Cert",
+ "ValiddeltaCRLTest8EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "deltaCRLCA2CRL",
+ "deltaCRLCA2deltaCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.15.9 Invalid delta-CRL Test9
+WRAPPED_TYPED_TEST_P(PkitsTest15DeltaCRLs, Section15InvaliddeltaCRLTest9) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "deltaCRLCA2Cert",
+ "InvaliddeltaCRLTest9EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "deltaCRLCA2CRL",
+ "deltaCRLCA2deltaCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+// 4.15.10 Invalid delta-CRL Test10
+WRAPPED_TYPED_TEST_P(PkitsTest15DeltaCRLs, Section15InvaliddeltaCRLTest10) {
+ const char* const certs[] = {"TrustAnchorRootCertificate", "deltaCRLCA3Cert",
+ "InvaliddeltaCRLTest10EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL", "deltaCRLCA3CRL",
+ "deltaCRLCA3deltaCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+WRAPPED_REGISTER_TYPED_TEST_CASE_P(PkitsTest15DeltaCRLs,
+ Section15InvaliddeltaCRLIndicatorNoBaseTest1,
+ Section15ValiddeltaCRLTest2,
+ Section15InvaliddeltaCRLTest3,
+ Section15InvaliddeltaCRLTest4,
+ Section15ValiddeltaCRLTest5,
+ Section15InvaliddeltaCRLTest6,
+ Section15ValiddeltaCRLTest7,
+ Section15ValiddeltaCRLTest8,
+ Section15InvaliddeltaCRLTest9,
+ Section15InvaliddeltaCRLTest10);
+
+template <typename PkitsTestDelegate>
+class PkitsTest16PrivateCertificateExtensions
+ : public PkitsTest<PkitsTestDelegate> {};
+TYPED_TEST_CASE_P(PkitsTest16PrivateCertificateExtensions);
+
+// 4.16.1 Valid Unknown Not Critical Certificate Extension Test1
+WRAPPED_TYPED_TEST_P(
+ PkitsTest16PrivateCertificateExtensions,
+ Section16ValidUnknownNotCriticalCertificateExtensionTest1) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate",
+ "ValidUnknownNotCriticalCertificateExtensionTest1EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL"};
+ ASSERT_TRUE(this->Verify(certs, crls));
+}
+
+// 4.16.2 Invalid Unknown Critical Certificate Extension Test2
+WRAPPED_TYPED_TEST_P(PkitsTest16PrivateCertificateExtensions,
+ Section16InvalidUnknownCriticalCertificateExtensionTest2) {
+ const char* const certs[] = {
+ "TrustAnchorRootCertificate",
+ "InvalidUnknownCriticalCertificateExtensionTest2EE"};
+ const char* const crls[] = {"TrustAnchorRootCRL"};
+ ASSERT_FALSE(this->Verify(certs, crls));
+}
+
+WRAPPED_REGISTER_TYPED_TEST_CASE_P(
+ PkitsTest16PrivateCertificateExtensions,
+ Section16ValidUnknownNotCriticalCertificateExtensionTest1,
+ Section16InvalidUnknownCriticalCertificateExtensionTest2);
diff --git a/chromium/net/third_party/nss/README.chromium b/chromium/net/third_party/nss/README.chromium
index 02700b86409..10ed53389a2 100644
--- a/chromium/net/third_party/nss/README.chromium
+++ b/chromium/net/third_party/nss/README.chromium
@@ -1,6 +1,6 @@
Name: Network Security Services (NSS)
URL: http://www.mozilla.org/projects/security/pki/nss/
-Version: 3.21 RTM
+Version: 3.23 RTM
Security Critical: Yes
License: MPL 2
License File: NOT_SHIPPED
@@ -11,7 +11,7 @@ This directory includes a copy of NSS's libssl from the hg repo at:
The same module appears in crypto/third_party/nss (and third_party/nss on some
platforms), so we don't repeat the license file here.
-The snapshot was updated to the hg tag: NSS_3_21_RTM
+The snapshot was updated to the hg tag: NSS_3_23_RTM
Patches:
@@ -20,10 +20,6 @@ Patches:
patches/cachecerts.patch
https://bugzilla.mozilla.org/show_bug.cgi?id=731478
- * Add support for client auth with native crypto APIs on Mac and Windows.
- patches/clientauth.patch
- ssl/sslplatf.c
-
* Add a function to export whether the last handshake on a socket resumed a
previous session.
patches/didhandshakeresume.patch
@@ -47,39 +43,10 @@ Patches:
This change was made in https://chromiumcodereview.appspot.com/10454066.
patches/secretexporterlocks.patch
- * Change ssl3_SuiteBOnly to always return PR_TRUE. The softoken in NSS
- versions older than 3.15 report an EC key size range of 112 bits to 571
- bits, even when it is compiled to support only the NIST P-256, P-384, and
- P-521 curves. Remove this patch when all system NSS softoken packages are
- NSS 3.15 or later.
- patches/suitebonly.patch
-
- * Define the SECItemArray type and declare the SECItemArray handling
- functions, which were added in NSS 3.15. Remove this patch when all system
- NSS packages are NSS 3.15 or later.
- patches/secitemarray.patch
-
- * Update Chromium-specific code for TLS 1.2.
- patches/tls12chromium.patch
-
- * Add Chromium-specific code to detect AES GCM support in the system NSS
- libraries at run time. Remove this patch when all system NSS packages are
- NSS 3.15 or later.
- patches/aesgcmchromium.patch
-
- * Support ChaCha20+Poly1305 ciphersuites
- http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-01
- patches/chacha20poly1305.patch
-
* Fix session cache lock creation race.
patches/cachelocks.patch
https://bugzilla.mozilla.org/show_bug.cgi?id=764646
- * Support the Certificate Transparency (RFC 6962) TLS extension
- signed_certificate_timestamp (client only).
- patches/signedcertificatetimestamps.patch
- https://bugzilla.mozilla.org/show_bug.cgi?id=944175
-
* Add a function to allow the cipher suites preference order to be set.
patches/cipherorder.patch
@@ -88,11 +55,6 @@ Patches:
asynchronous certificate verification.
patches/sessioncache.patch
- * Use NSSRWLock instead of PRRWLock in sslSessionID. This avoids the bugs
- in the lock rank checking code in PRRWLock.
- patches/nssrwlock.patch
- https://bugzilla.mozilla.org/show_bug.cgi?id=957812
-
* Add a comment explaining why signature_algorithms extension should be at
the end of the extension list. This works around a bug in WebSphere
Application Server 7.0, which is intolerant to the final extension having
@@ -100,8 +62,9 @@ Patches:
length.
patches/reorderextensions.patch
+ * Fix an unused method when disabling PKCS#11 bypass mode
+ patches/nobypass.patch
+
Apply the patches to NSS by running the patches/applypatches.sh script. Read
the comments at the top of patches/applypatches.sh for instructions.
-The ssl/bodge directory contains files taken from the NSS repo that we required
-for building libssl outside of its usual build environment.
diff --git a/chromium/net/third_party/nss/patches/aesgcmchromium.patch b/chromium/net/third_party/nss/patches/aesgcmchromium.patch
deleted file mode 100644
index b144e9494fa..00000000000
--- a/chromium/net/third_party/nss/patches/aesgcmchromium.patch
+++ /dev/null
@@ -1,121 +0,0 @@
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index c5cb1eb..299e414 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -8,6 +8,7 @@
-
- /* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */
-
-+#define _GNU_SOURCE 1
- #include "cert.h"
- #include "ssl.h"
- #include "cryptohi.h" /* for DSAU_ stuff */
-@@ -46,6 +47,9 @@
- #ifdef NSS_ENABLE_ZLIB
- #include "zlib.h"
- #endif
-+#ifdef LINUX
-+#include <dlfcn.h>
-+#endif
-
- #ifndef PK11_SETATTRS
- #define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
-@@ -1897,6 +1901,63 @@ ssl3_BuildRecordPseudoHeader(unsigned char *out,
- return 13;
- }
-
-+typedef SECStatus (*PK11CryptFcn)(
-+ PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism, SECItem *param,
-+ unsigned char *out, unsigned int *outLen, unsigned int maxLen,
-+ const unsigned char *in, unsigned int inLen);
-+
-+static PK11CryptFcn pk11_encrypt = NULL;
-+static PK11CryptFcn pk11_decrypt = NULL;
-+
-+static PRCallOnceType resolvePK11CryptOnce;
-+
-+static PRStatus
-+ssl3_ResolvePK11CryptFunctions(void)
-+{
-+#ifdef LINUX
-+ /* On Linux we use the system NSS libraries. Look up the PK11_Encrypt and
-+ * PK11_Decrypt functions at run time. */
-+ pk11_encrypt = (PK11CryptFcn)dlsym(RTLD_DEFAULT, "PK11_Encrypt");
-+ pk11_decrypt = (PK11CryptFcn)dlsym(RTLD_DEFAULT, "PK11_Decrypt");
-+ return PR_SUCCESS;
-+#else
-+ /* On other platforms we use our own copy of NSS. PK11_Encrypt and
-+ * PK11_Decrypt are known to be available. */
-+ pk11_encrypt = PK11_Encrypt;
-+ pk11_decrypt = PK11_Decrypt;
-+ return PR_SUCCESS;
-+#endif
-+}
-+
-+/*
-+ * In NSS 3.15, PK11_Encrypt and PK11_Decrypt were added to provide access
-+ * to the AES GCM implementation in the NSS softoken. So the presence of
-+ * these two functions implies the NSS version supports AES GCM.
-+ */
-+static PRBool
-+ssl3_HasGCMSupport(void)
-+{
-+ (void)PR_CallOnce(&resolvePK11CryptOnce, ssl3_ResolvePK11CryptFunctions);
-+ return pk11_encrypt != NULL;
-+}
-+
-+/* On this socket, disable the GCM cipher suites */
-+SECStatus
-+ssl3_DisableGCMSuites(sslSocket * ss)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < PR_ARRAY_SIZE(cipher_suite_defs); i++) {
-+ const ssl3CipherSuiteDef *cipher_def = &cipher_suite_defs[i];
-+ if (cipher_def->bulk_cipher_alg == cipher_aes_128_gcm) {
-+ SECStatus rv = ssl3_CipherPrefSet(ss, cipher_def->cipher_suite,
-+ PR_FALSE);
-+ PORT_Assert(rv == SECSuccess); /* else is coding error */
-+ }
-+ }
-+ return SECSuccess;
-+}
-+
- static SECStatus
- ssl3_AESGCM(ssl3KeyMaterial *keys,
- PRBool doDecrypt,
-@@ -1948,10 +2009,10 @@ ssl3_AESGCM(ssl3KeyMaterial *keys,
- gcmParams.ulTagBits = tagSize * 8;
-
- if (doDecrypt) {
-- rv = PK11_Decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
-+ rv = pk11_decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
- maxout, in, inlen);
- } else {
-- rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
-+ rv = pk11_encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
- maxout, in, inlen);
- }
- *outlen += (int) uOutLen;
-@@ -5337,6 +5398,10 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- ssl3_DisableNonDTLSSuites(ss);
- }
-
-+ if (!ssl3_HasGCMSupport()) {
-+ ssl3_DisableGCMSuites(ss);
-+ }
-+
- /* how many suites are permitted by policy and user preference? */
- num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE);
- if (!num_suites) {
-@@ -8400,6 +8465,10 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
- ssl3_DisableNonDTLSSuites(ss);
- }
-
-+ if (!ssl3_HasGCMSupport()) {
-+ ssl3_DisableGCMSuites(ss);
-+ }
-+
- #ifdef PARANOID
- /* Look for a matching cipher suite. */
- j = ssl3_config_match_init(ss);
diff --git a/chromium/net/third_party/nss/patches/applypatches.sh b/chromium/net/third_party/nss/patches/applypatches.sh
index faf850a444d..47242330839 100755
--- a/chromium/net/third_party/nss/patches/applypatches.sh
+++ b/chromium/net/third_party/nss/patches/applypatches.sh
@@ -11,8 +11,6 @@ patches_dir=/Users/sleevi/development/chromium/src/net/third_party/nss/patches
patch -p2 < $patches_dir/cachecerts.patch
-patch -p2 < $patches_dir/clientauth.patch
-
patch -p2 < $patches_dir/didhandshakeresume.patch
patch -p2 < $patches_dir/getrequestedclientcerttypes.patch
@@ -25,24 +23,12 @@ patch -p2 < $patches_dir/tlsunique.patch
patch -p2 < $patches_dir/secretexporterlocks.patch
-patch -p2 < $patches_dir/suitebonly.patch
-
-patch -p2 < $patches_dir/secitemarray.patch
-
-patch -p2 < $patches_dir/tls12chromium.patch
-
-patch -p2 < $patches_dir/aesgcmchromium.patch
-
-patch -p2 < $patches_dir/chacha20poly1305.patch
-
patch -p2 < $patches_dir/cachelocks.patch
-patch -p2 < $patches_dir/signedcertificatetimestamps.patch
-
patch -p2 < $patches_dir/cipherorder.patch
patch -p2 < $patches_dir/sessioncache.patch
-patch -p2 < $patches_dir/nssrwlock.patch
-
patch -p2 < $patches_dir/reorderextensions.patch
+
+patch -p2 < $patches_dir/nobypass.patch
diff --git a/chromium/net/third_party/nss/patches/cachecerts.patch b/chromium/net/third_party/nss/patches/cachecerts.patch
index 1e0e3135c8c..196bb278194 100644
--- a/chromium/net/third_party/nss/patches/cachecerts.patch
+++ b/chromium/net/third_party/nss/patches/cachecerts.patch
@@ -1,33 +1,25 @@
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 8f1c547..9aaf601 100644
+index c3698f3..b8d4784 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
-@@ -45,6 +45,7 @@
+@@ -47,6 +47,7 @@
static SECStatus ssl3_AuthCertificate(sslSocket *ss);
- static void ssl3_CleanupPeerCerts(sslSocket *ss);
-+static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid);
+ static void ssl3_CleanupPeerCerts(sslSocket *ss);
++static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid);
static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
- PK11SlotInfo * serverKeySlot);
+ PK11SlotInfo *serverKeySlot);
static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms);
-@@ -6751,6 +6752,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
- /* copy the peer cert from the SID */
- if (sid->peerCert != NULL) {
- ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
-+ ssl3_CopyPeerCertsFromSID(ss, sid);
- }
+@@ -7102,6 +7103,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+ /* copy the peer cert from the SID */
+ if (sid->peerCert != NULL) {
+ ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
++ ssl3_CopyPeerCertsFromSID(ss, sid);
+ }
- /* NULL value for PMS because we are reusing the old MS */
-@@ -8405,6 +8407,7 @@ compression_found:
- ss->sec.ci.sid = sid;
- if (sid->peerCert != NULL) {
- ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
-+ ssl3_CopyPeerCertsFromSID(ss, sid);
- }
-
- /*
-@@ -10389,6 +10392,44 @@ ssl3_CleanupPeerCerts(sslSocket *ss)
- ss->ssl3.peerCertChain = NULL;
+ /* NULL value for PMS because we are reusing the old MS */
+@@ -8266,6 +8268,44 @@ ssl3_KEAAllowsSessionTicket(SSL3KeyExchangeAlgorithm kea)
+ };
}
+static void
@@ -39,20 +31,20 @@ index 8f1c547..9aaf601 100644
+ int i;
+
+ if (!sid->peerCertChain[0])
-+ return;
++ return;
+ PORT_Assert(!ss->ssl3.peerCertArena);
+ PORT_Assert(!ss->ssl3.peerCertChain);
+ ss->ssl3.peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
-+ ssl3CertNode *c = PORT_ArenaNew(arena, ssl3CertNode);
-+ c->cert = CERT_DupCertificate(sid->peerCertChain[i]);
-+ c->next = NULL;
-+ if (lastCert) {
-+ lastCert->next = c;
-+ } else {
-+ certs = c;
-+ }
-+ lastCert = c;
++ ssl3CertNode *c = PORT_ArenaNew(arena, ssl3CertNode);
++ c->cert = CERT_DupCertificate(sid->peerCertChain[i]);
++ c->next = NULL;
++ if (lastCert) {
++ lastCert->next = c;
++ } else {
++ certs = c;
++ }
++ lastCert = c;
+ }
+ ss->ssl3.peerCertChain = certs;
+}
@@ -63,15 +55,23 @@ index 8f1c547..9aaf601 100644
+ int i = 0;
+ ssl3CertNode *c = certs;
+ for (; i < MAX_PEER_CERT_CHAIN_SIZE && c; i++, c = c->next) {
-+ PORT_Assert(!sid->peerCertChain[i]);
-+ sid->peerCertChain[i] = CERT_DupCertificate(c->cert);
++ PORT_Assert(!sid->peerCertChain[i]);
++ sid->peerCertChain[i] = CERT_DupCertificate(c->cert);
+ }
+}
+
/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
- * ssl3 CertificateStatus message.
+ * ssl3 Client Hello message.
* Caller must hold Handshake and RecvBuf locks.
-@@ -10669,6 +10710,7 @@ ssl3_AuthCertificate(sslSocket *ss)
+@@ -8886,6 +8926,7 @@ compression_found:
+ ss->sec.ci.sid = sid;
+ if (sid->peerCert != NULL) {
+ ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
++ ssl3_CopyPeerCertsFromSID(ss, sid);
+ }
+
+ /*
+@@ -11240,6 +11281,7 @@ ssl3_AuthCertificate(sslSocket *ss)
}
ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
@@ -80,11 +80,11 @@ index 8f1c547..9aaf601 100644
if (!ss->sec.isServer) {
CERTCertificate *cert = ss->sec.peerCert;
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index ad31aae..9dcc29e 100644
+index bce9437..10361a0 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
-@@ -608,6 +608,8 @@ typedef enum { never_cached,
- invalid_cache /* no longer in any cache. */
+@@ -614,6 +614,8 @@ typedef enum { never_cached,
+ invalid_cache /* no longer in any cache. */
} Cached;
+#define MAX_PEER_CERT_CHAIN_SIZE 8
@@ -92,19 +92,19 @@ index ad31aae..9dcc29e 100644
struct sslSessionIDStr {
/* The global cache lock must be held when accessing these members when the
* sid is in any cache.
-@@ -622,6 +624,7 @@ struct sslSessionIDStr {
+@@ -628,6 +630,7 @@ struct sslSessionIDStr {
*/
- CERTCertificate * peerCert;
-+ CERTCertificate * peerCertChain[MAX_PEER_CERT_CHAIN_SIZE];
- SECItemArray peerCertStatus; /* client only */
- const char * peerID; /* client only */
- const char * urlSvrName; /* client only */
+ CERTCertificate *peerCert;
++ CERTCertificate *peerCertChain[MAX_PEER_CERT_CHAIN_SIZE];
+ SECItemArray peerCertStatus; /* client only */
+ const char *peerID; /* client only */
+ const char *urlSvrName; /* client only */
diff --git a/lib/ssl/sslnonce.c b/lib/ssl/sslnonce.c
-index 2e861f1..be11008 100644
+index 85031c4..3216892 100644
--- a/lib/ssl/sslnonce.c
+++ b/lib/ssl/sslnonce.c
-@@ -164,6 +164,7 @@ lock_cache(void)
+@@ -167,6 +167,7 @@ lock_cache(void)
static void
ssl_DestroySID(sslSessionID *sid)
{
@@ -112,9 +112,9 @@ index 2e861f1..be11008 100644
SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached));
PORT_Assert(sid->references == 0);
PORT_Assert(sid->cached != in_client_cache);
-@@ -194,6 +195,9 @@ ssl_DestroySID(sslSessionID *sid)
- if ( sid->peerCert ) {
- CERT_DestroyCertificate(sid->peerCert);
+@@ -200,6 +201,9 @@ ssl_DestroySID(sslSessionID *sid)
+ if (sid->peerCert) {
+ CERT_DestroyCertificate(sid->peerCert);
}
+ for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
+ CERT_DestroyCertificate(sid->peerCertChain[i]);
diff --git a/chromium/net/third_party/nss/patches/cachelocks.patch b/chromium/net/third_party/nss/patches/cachelocks.patch
index d2bde5f8093..9ba646b8a69 100644
--- a/chromium/net/third_party/nss/patches/cachelocks.patch
+++ b/chromium/net/third_party/nss/patches/cachelocks.patch
@@ -1,8 +1,8 @@
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 2533679..ba3d012 100644
+index 1394542..d7d186a 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
-@@ -5921,7 +5921,6 @@ SSL3_ShutdownServerCache(void)
+@@ -6049,7 +6049,6 @@ SSL3_ShutdownServerCache(void)
}
PZ_Unlock(symWrapKeysLock);
@@ -10,7 +10,7 @@ index 2533679..ba3d012 100644
return SECSuccess;
}
-@@ -5973,7 +5972,7 @@ getWrappingKey( sslSocket * ss,
+@@ -6102,7 +6101,7 @@ getWrappingKey(sslSocket *ss,
pSymWrapKey = &symWrapKeys[symWrapMechIndex].symWrapKey[exchKeyType];
@@ -20,10 +20,10 @@ index 2533679..ba3d012 100644
PZ_Lock(symWrapKeysLock);
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index d5f326f..d53c446 100644
+index d47eb28..c0e3a0b 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
-@@ -1957,9 +1957,7 @@ extern SECStatus ssl_InitSymWrapKeysLock(void);
+@@ -2029,9 +2029,7 @@ extern SECStatus ssl_InitSymWrapKeysLock(void);
extern SECStatus ssl_FreeSymWrapKeysLock(void);
@@ -32,15 +32,15 @@ index d5f326f..d53c446 100644
-extern SECStatus ssl_FreeSessionCacheLocks(void);
+extern SECStatus ssl_InitSessionCacheLocks(void);
- /***************** platform client auth ****************/
-
+ /**************** DTLS-specific functions **************/
+ extern void dtls_FreeQueuedMessage(DTLSQueuedMessage *msg);
diff --git a/lib/ssl/sslnonce.c b/lib/ssl/sslnonce.c
-index 1326a8b..c45849d 100644
+index 4804cb8..99591cc 100644
--- a/lib/ssl/sslnonce.c
+++ b/lib/ssl/sslnonce.c
-@@ -35,91 +35,55 @@ static PZLock * cacheLock = NULL;
- #define LOCK_CACHE lock_cache()
- #define UNLOCK_CACHE PZ_Unlock(cacheLock)
+@@ -35,93 +35,55 @@ static PZLock *cacheLock = NULL;
+ #define LOCK_CACHE lock_cache()
+ #define UNLOCK_CACHE PZ_Unlock(cacheLock)
-static SECStatus
-ssl_InitClientSessionCacheLock(void)
@@ -69,12 +69,12 @@ index 1326a8b..c45849d 100644
+ * state. */
static SECStatus
-FreeSessionCacheLocks()
-+FreeSessionCacheLocks(void* appData, void* nssData)
++FreeSessionCacheLocks(void *appData, void *nssData)
{
- SECStatus rv1, rv2;
- rv1 = ssl_FreeSymWrapKeysLock();
- rv2 = ssl_FreeClientSessionCacheLock();
-- if ( (SECSuccess == rv1) && (SECSuccess == rv2) ) {
+- if ((SECSuccess == rv1) && (SECSuccess == rv2)) {
- return SECSuccess;
- }
- return SECFailure;
@@ -89,7 +89,7 @@ index 1326a8b..c45849d 100644
- PRErrorCode rc;
- rv1 = ssl_InitSymWrapKeysLock();
- rv2 = ssl_InitClientSessionCacheLock();
-- if ( (SECSuccess == rv1) && (SECSuccess == rv2) ) {
+- if ((SECSuccess == rv1) && (SECSuccess == rv2)) {
- return SECSuccess;
- }
- rc = PORT_GetError();
@@ -118,7 +118,8 @@ index 1326a8b..c45849d 100644
+ cacheLock = NULL;
-/* free the session cache locks if they were initialized lazily */
--static SECStatus ssl_ShutdownLocks(void* appData, void* nssData)
+-static SECStatus
+-ssl_ShutdownLocks(void *appData, void *nssData)
-{
- PORT_Assert(PR_FALSE == LocksInitializedEarly);
- if (LocksInitializedEarly) {
@@ -135,10 +136,10 @@ index 1326a8b..c45849d 100644
return SECSuccess;
}
--static PRStatus initSessionCacheLocksLazily(void)
+/* InitSessionCacheLocks is called, protected by lockOnce, to create the
+ * session cache locks. */
-+static PRStatus
+ static PRStatus
+-initSessionCacheLocksLazily(void)
+InitSessionCacheLocks(void)
{
- SECStatus rv = InitSessionCacheLocks();
@@ -163,7 +164,7 @@ index 1326a8b..c45849d 100644
PORT_Assert(SECSuccess == rv);
if (SECSuccess != rv) {
return PR_FAILURE;
-@@ -127,34 +91,18 @@ static PRStatus initSessionCacheLocksLazily(void)
+@@ -129,35 +91,19 @@ initSessionCacheLocksLazily(void)
return PR_SUCCESS;
}
@@ -172,7 +173,7 @@ index 1326a8b..c45849d 100644
- */
SECStatus
-ssl_InitSessionCacheLocks(PRBool lazyInit)
-+ssl_InitSessionCacheLocks(void)
++ssl_InitSessionCacheLocks()
{
- if (LocksInitializedEarly) {
- return SECSuccess;
@@ -180,10 +181,11 @@ index 1326a8b..c45849d 100644
-
- if (lazyInit) {
- return (PR_SUCCESS ==
-- PR_CallOnce(&lockOnce, initSessionCacheLocksLazily)) ?
-- SECSuccess : SECFailure;
+- PR_CallOnce(&lockOnce, initSessionCacheLocksLazily))
+- ? SECSuccess
+- : SECFailure;
- }
--
+-
- if (SECSuccess == InitSessionCacheLocks()) {
- LocksInitializedEarly = PR_TRUE;
- return SECSuccess;
@@ -191,12 +193,12 @@ index 1326a8b..c45849d 100644
-
- return SECFailure;
+ return (PR_SUCCESS ==
-+ PR_CallOnce(&lockOnce, InitSessionCacheLocks)) ?
-+ SECSuccess : SECFailure;
++ PR_CallOnce(&lockOnce, InitSessionCacheLocks))
++ ? SECSuccess
++ : SECFailure;
}
--static void
-+static void
+ static void
lock_cache(void)
{
- ssl_InitSessionCacheLocks(PR_TRUE);
@@ -205,33 +207,33 @@ index 1326a8b..c45849d 100644
}
diff --git a/lib/ssl/sslsnce.c b/lib/ssl/sslsnce.c
-index f31b2e9..3856c13 100644
+index da1f93f..e3f749e 100644
--- a/lib/ssl/sslsnce.c
+++ b/lib/ssl/sslsnce.c
-@@ -1363,7 +1363,7 @@ SSL_ConfigServerSessionIDCache( int maxCacheEntries,
- PRUint32 ssl3_timeout,
- const char * directory)
+@@ -1344,7 +1344,7 @@ SSL_ConfigServerSessionIDCache(int maxCacheEntries,
+ PRUint32 ssl3_timeout,
+ const char *directory)
{
- ssl_InitSessionCacheLocks(PR_FALSE);
+ ssl_InitSessionCacheLocks();
- return SSL_ConfigServerSessionIDCacheInstance(&globalCache,
- maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE);
+ return SSL_ConfigServerSessionIDCacheInstance(&globalCache,
+ maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE);
}
-@@ -1477,7 +1477,7 @@ SSL_ConfigServerSessionIDCacheWithOpt(
- PRBool enableMPCache)
+@@ -1458,7 +1458,7 @@ SSL_ConfigServerSessionIDCacheWithOpt(
+ PRBool enableMPCache)
{
if (!enableMPCache) {
- ssl_InitSessionCacheLocks(PR_FALSE);
+ ssl_InitSessionCacheLocks();
- return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache,
- ssl2_timeout, ssl3_timeout, directory, PR_FALSE,
- maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries);
-@@ -1521,7 +1521,7 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
- return SECSuccess; /* already done. */
+ return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache,
+ ssl2_timeout, ssl3_timeout, directory, PR_FALSE,
+ maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries);
+@@ -1502,7 +1502,7 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char *envString)
+ return SECSuccess; /* already done. */
}
- ssl_InitSessionCacheLocks(PR_FALSE);
+ ssl_InitSessionCacheLocks();
- ssl_sid_lookup = ServerSessionIDLookup;
- ssl_sid_cache = ServerSessionIDCache;
+ ssl_sid_lookup = ServerSessionIDLookup;
+ ssl_sid_cache = ServerSessionIDCache;
diff --git a/chromium/net/third_party/nss/patches/chacha20poly1305.patch b/chromium/net/third_party/nss/patches/chacha20poly1305.patch
deleted file mode 100644
index e4c78017d9a..00000000000
--- a/chromium/net/third_party/nss/patches/chacha20poly1305.patch
+++ /dev/null
@@ -1,285 +0,0 @@
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 299e414..2533679 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -43,6 +43,21 @@
- #define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24)
- #endif
-
-+/* This is a bodge to allow this code to be compiled against older NSS
-+ * headers. */
-+#ifndef CKM_NSS_CHACHA20_POLY1305
-+#define CKM_NSS_CHACHA20_POLY1305 (CKM_NSS + 26)
-+
-+typedef struct CK_NSS_AEAD_PARAMS {
-+ CK_BYTE_PTR pIv; /* This is the nonce. */
-+ CK_ULONG ulIvLen;
-+ CK_BYTE_PTR pAAD;
-+ CK_ULONG ulAADLen;
-+ CK_ULONG ulTagLen;
-+} CK_NSS_AEAD_PARAMS;
-+
-+#endif
-+
- #include <stdio.h>
- #ifdef NSS_ENABLE_ZLIB
- #include "zlib.h"
-@@ -110,6 +125,8 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
- /* cipher_suite policy enabled isPresent */
-
- #ifndef NSS_DISABLE_ECC
-+ { TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, SSL_ALLOWED, PR_FALSE, PR_FALSE},
-+ { TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
- /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA is out of order to work around
-@@ -307,6 +324,7 @@ static const ssl3BulkCipherDef bulk_cipher_defs[] = {
- {cipher_camellia_256, calg_camellia, 32,32, type_block, 16,16, 0, 0},
- {cipher_seed, calg_seed, 16,16, type_block, 16,16, 0, 0},
- {cipher_aes_128_gcm, calg_aes_gcm, 16,16, type_aead, 4, 0,16, 8},
-+ {cipher_chacha20, calg_chacha20, 32,32, type_aead, 0, 0,16, 0},
- {cipher_missing, calg_null, 0, 0, type_stream, 0, 0, 0, 0},
- };
-
-@@ -433,6 +451,8 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] =
- {TLS_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_rsa},
- {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_rsa},
- {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_ecdsa},
-+ {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, cipher_chacha20, mac_aead, kea_ecdhe_rsa},
-+ {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, cipher_chacha20, mac_aead, kea_ecdhe_ecdsa},
-
- {TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_dhe_dss},
- {TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_dhe_dss},
-@@ -502,6 +522,7 @@ static const SSLCipher2Mech alg2Mech[] = {
- { calg_camellia , CKM_CAMELLIA_CBC },
- { calg_seed , CKM_SEED_CBC },
- { calg_aes_gcm , CKM_AES_GCM },
-+ { calg_chacha20 , CKM_NSS_CHACHA20_POLY1305 },
- /* { calg_init , (CK_MECHANISM_TYPE)0x7fffffffL } */
- };
-
-@@ -679,6 +700,8 @@ ssl3_CipherSuiteAllowedForVersionRange(
- case TLS_RSA_WITH_NULL_SHA256:
- return vrange->max == SSL_LIBRARY_VERSION_TLS_1_2;
-
-+ case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305:
-+ case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305:
- case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-@@ -2093,6 +2116,46 @@ ssl3_AESGCMBypass(ssl3KeyMaterial *keys,
- }
- #endif
-
-+static SECStatus
-+ssl3_ChaCha20Poly1305(
-+ ssl3KeyMaterial *keys,
-+ PRBool doDecrypt,
-+ unsigned char *out,
-+ int *outlen,
-+ int maxout,
-+ const unsigned char *in,
-+ int inlen,
-+ const unsigned char *additionalData,
-+ int additionalDataLen)
-+{
-+ SECItem param;
-+ SECStatus rv = SECFailure;
-+ unsigned int uOutLen;
-+ CK_NSS_AEAD_PARAMS aeadParams;
-+ static const int tagSize = 16;
-+
-+ param.type = siBuffer;
-+ param.len = sizeof(aeadParams);
-+ param.data = (unsigned char *) &aeadParams;
-+ memset(&aeadParams, 0, sizeof(aeadParams));
-+ aeadParams.pIv = (unsigned char *) additionalData;
-+ aeadParams.ulIvLen = 8;
-+ aeadParams.pAAD = (unsigned char *) additionalData;
-+ aeadParams.ulAADLen = additionalDataLen;
-+ aeadParams.ulTagLen = tagSize;
-+
-+ if (doDecrypt) {
-+ rv = pk11_decrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, &param,
-+ out, &uOutLen, maxout, in, inlen);
-+ } else {
-+ rv = pk11_encrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, &param,
-+ out, &uOutLen, maxout, in, inlen);
-+ }
-+ *outlen = (int) uOutLen;
-+
-+ return rv;
-+}
-+
- /* Initialize encryption and MAC contexts for pending spec.
- * Master Secret already is derived.
- * Caller holds Spec write lock.
-@@ -2126,13 +2189,17 @@ ssl3_InitPendingContextsPKCS11(sslSocket *ss)
- pwSpec->client.write_mac_context = NULL;
- pwSpec->server.write_mac_context = NULL;
-
-- if (calg == calg_aes_gcm) {
-+ if (calg == calg_aes_gcm || calg == calg_chacha20) {
- pwSpec->encode = NULL;
- pwSpec->decode = NULL;
- pwSpec->destroy = NULL;
- pwSpec->encodeContext = NULL;
- pwSpec->decodeContext = NULL;
-- pwSpec->aead = ssl3_AESGCM;
-+ if (calg == calg_aes_gcm) {
-+ pwSpec->aead = ssl3_AESGCM;
-+ } else {
-+ pwSpec->aead = ssl3_ChaCha20Poly1305;
-+ }
- return SECSuccess;
- }
-
-diff --git a/lib/ssl/ssl3ecc.c b/lib/ssl/ssl3ecc.c
-index cf8e741..ab5ab14 100644
---- a/lib/ssl/ssl3ecc.c
-+++ b/lib/ssl/ssl3ecc.c
-@@ -926,6 +926,7 @@ static const ssl3CipherSuite ecdhe_ecdsa_suites[] = {
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
-+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
- TLS_ECDHE_ECDSA_WITH_NULL_SHA,
- TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
- 0 /* end of list marker */
-@@ -937,6 +938,7 @@ static const ssl3CipherSuite ecdhe_rsa_suites[] = {
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
- TLS_ECDHE_RSA_WITH_NULL_SHA,
- TLS_ECDHE_RSA_WITH_RC4_128_SHA,
- 0 /* end of list marker */
-@@ -949,6 +951,7 @@ static const ssl3CipherSuite ecSuites[] = {
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
-+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
- TLS_ECDHE_ECDSA_WITH_NULL_SHA,
- TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
-@@ -956,6 +959,7 @@ static const ssl3CipherSuite ecSuites[] = {
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
- TLS_ECDHE_RSA_WITH_NULL_SHA,
- TLS_ECDHE_RSA_WITH_RC4_128_SHA,
- TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
-diff --git a/lib/ssl/sslenum.c b/lib/ssl/sslenum.c
-index f69aed2..b4a8844 100644
---- a/lib/ssl/sslenum.c
-+++ b/lib/ssl/sslenum.c
-@@ -37,17 +37,21 @@
- *
- * Exception: Because some servers ignore the high-order byte of the cipher
- * suite ID, we must be careful about adding cipher suites with IDs larger
-- * than 0x00ff; see bug 946147. For these broken servers, the first four cipher
-+ * than 0x00ff; see bug 946147. For these broken servers, the first six cipher
- * suites, with the MSB zeroed, look like:
-+ * TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA { 0x00,0x14 }
-+ * TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA { 0x00,0x13 }
- * TLS_KRB5_EXPORT_WITH_RC4_40_MD5 { 0x00,0x2B }
- * TLS_RSA_WITH_AES_128_CBC_SHA { 0x00,0x2F }
- * TLS_RSA_WITH_3DES_EDE_CBC_SHA { 0x00,0x0A }
- * TLS_RSA_WITH_DES_CBC_SHA { 0x00,0x09 }
-- * The broken server only supports the third and fourth ones and will select
-- * the third one.
-+ * The broken server only supports the fifth and sixth ones and will select
-+ * the fifth one.
- */
- const PRUint16 SSL_ImplementedCiphers[] = {
- #ifndef NSS_DISABLE_ECC
-+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
-+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA must appear before
-diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index 60dd243..d5f326f 100644
---- a/lib/ssl/sslimpl.h
-+++ b/lib/ssl/sslimpl.h
-@@ -66,6 +66,7 @@ typedef SSLSignType SSL3SignType;
- #define calg_camellia ssl_calg_camellia
- #define calg_seed ssl_calg_seed
- #define calg_aes_gcm ssl_calg_aes_gcm
-+#define calg_chacha20 ssl_calg_chacha20
-
- #define mac_null ssl_mac_null
- #define mac_md5 ssl_mac_md5
-@@ -301,7 +302,7 @@ typedef struct {
- } ssl3CipherSuiteCfg;
-
- #ifndef NSS_DISABLE_ECC
--#define ssl_V3_SUITES_IMPLEMENTED 64
-+#define ssl_V3_SUITES_IMPLEMENTED 66
- #else
- #define ssl_V3_SUITES_IMPLEMENTED 40
- #endif /* NSS_DISABLE_ECC */
-@@ -495,6 +496,7 @@ typedef enum {
- cipher_camellia_256,
- cipher_seed,
- cipher_aes_128_gcm,
-+ cipher_chacha20,
- cipher_missing /* reserved for no such supported cipher */
- /* This enum must match ssl3_cipherName[] in ssl3con.c. */
- } SSL3BulkCipher;
-diff --git a/lib/ssl/sslinfo.c b/lib/ssl/sslinfo.c
-index 7048eb8..bef3190 100644
---- a/lib/ssl/sslinfo.c
-+++ b/lib/ssl/sslinfo.c
-@@ -148,6 +148,7 @@ SSL_GetPreliminaryChannelInfo(PRFileDesc *fd,
- #define C_NULL "NULL", calg_null
- #define C_SJ "SKIPJACK", calg_sj
- #define C_AESGCM "AES-GCM", calg_aes_gcm
-+#define C_CHACHA20 "CHACHA20POLY1305", calg_chacha20
-
- #define B_256 256, 256, 256
- #define B_128 128, 128, 128
-@@ -229,12 +230,14 @@ static const SSLCipherSuiteInfo suiteInfo[] = {
- {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0, },
- {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0, },
- {0,CS(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0, },
-+{0,CS(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305),S_ECDSA,K_ECDHE,C_CHACHA20,B_256,M_AEAD_128,0, 0, 0, },
-
- {0,CS(TLS_ECDH_RSA_WITH_NULL_SHA), S_RSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, },
- {0,CS(TLS_ECDH_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0, },
- {0,CS(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0, },
- {0,CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0, },
- {0,CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0, },
-+{0,CS(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305), S_RSA,K_ECDHE,C_CHACHA20,B_256,M_AEAD_128, 0, 0, 0, },
-
- {0,CS(TLS_ECDHE_RSA_WITH_NULL_SHA), S_RSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0, },
- {0,CS(TLS_ECDHE_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0, },
-diff --git a/lib/ssl/sslproto.h b/lib/ssl/sslproto.h
-index 2db47a5..36ae6c9 100644
---- a/lib/ssl/sslproto.h
-+++ b/lib/ssl/sslproto.h
-@@ -260,6 +260,9 @@
- #define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F
- #define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031
-
-+#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 0xCC13
-+#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 0xCC14
-+
- /* Netscape "experimental" cipher suites. */
- #define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA 0xffe0
- #define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA 0xffe1
-diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h
-index 5593579..a2eff62 100644
---- a/lib/ssl/sslt.h
-+++ b/lib/ssl/sslt.h
-@@ -117,7 +117,8 @@ typedef enum {
- ssl_calg_aes = 7,
- ssl_calg_camellia = 8,
- ssl_calg_seed = 9,
-- ssl_calg_aes_gcm = 10
-+ ssl_calg_aes_gcm = 10,
-+ ssl_calg_chacha20 = 11
- } SSLCipherAlgorithm;
-
- typedef enum {
diff --git a/chromium/net/third_party/nss/patches/channelid.patch b/chromium/net/third_party/nss/patches/channelid.patch
index 58b0ae7d1ae..674d4eeebad 100644
--- a/chromium/net/third_party/nss/patches/channelid.patch
+++ b/chromium/net/third_party/nss/patches/channelid.patch
@@ -1,25 +1,25 @@
diff --git a/lib/ssl/SSLerrs.h b/lib/ssl/SSLerrs.h
-index 6028396..3d21ab8 100644
+index 15bf0b4..555e629 100644
--- a/lib/ssl/SSLerrs.h
+++ b/lib/ssl/SSLerrs.h
-@@ -440,3 +440,12 @@ ER3(SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET, (SSL_ERROR_BASE + 136),
+@@ -465,3 +465,12 @@ ER3(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, (SSL_ERROR_BASE + 145),
- ER3(SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET, (SSL_ERROR_BASE + 137),
- "The peer tried to resume with an unexpected extended_master_secret extension")
+ ER3(SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS, (SSL_ERROR_BASE + 146),
+ "SSL received a malformed Encrypted Extensions handshake message.")
+
-+ER3(SSL_ERROR_BAD_CHANNEL_ID_DATA, (SSL_ERROR_BASE + 138),
-+"SSL received a malformed TLS Channel ID extension.")
++ER3(SSL_ERROR_BAD_CHANNEL_ID_DATA, (SSL_ERROR_BASE + 147),
++ "SSL received a malformed TLS Channel ID extension.")
+
-+ER3(SSL_ERROR_INVALID_CHANNEL_ID_KEY, (SSL_ERROR_BASE + 139),
-+"The application provided an invalid TLS Channel ID key.")
++ER3(SSL_ERROR_INVALID_CHANNEL_ID_KEY, (SSL_ERROR_BASE + 148),
++ "The application provided an invalid TLS Channel ID key.")
+
-+ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 140),
-+"The application could not get a TLS Channel ID.")
++ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 149),
++ "The application could not get a TLS Channel ID.")
diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index 85ced8a..120c257 100644
+index aa4a3e5..870a8cc 100644
--- a/lib/ssl/ssl.h
+++ b/lib/ssl/ssl.h
-@@ -1135,6 +1135,34 @@ SSL_IMPORT SECStatus SSL_HandshakeNegotiatedExtension(PRFileDesc * socket,
+@@ -1142,6 +1142,34 @@ SSL_IMPORT SECStatus SSL_HandshakeNegotiatedExtension(PRFileDesc *socket,
SSL_IMPORT SECStatus SSL_HandshakeResumedSession(PRFileDesc *fd,
PRBool *last_handshake_resumed);
@@ -27,7 +27,7 @@ index 85ced8a..120c257 100644
+ * SECWouldBlock then SSL_RestartHandshakeAfterChannelIDReq should be called in
+ * the future to restart the handshake. On SECSuccess, the callback must have
+ * written a P-256, EC key pair to |*out_public_key| and |*out_private_key|. */
-+typedef SECStatus (PR_CALLBACK *SSLClientChannelIDCallback)(
++typedef SECStatus(PR_CALLBACK *SSLClientChannelIDCallback)(
+ void *arg,
+ PRFileDesc *fd,
+ SECKEYPublicKey **out_public_key,
@@ -55,43 +55,43 @@ index 85ced8a..120c257 100644
** How long should we wait before retransmitting the next flight of
** the DTLS handshake? Returns SECFailure if not DTLS or not in a
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 304e03b..2ae8ce9 100644
+index 2a2e644..a2beec2 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
-@@ -57,6 +57,7 @@ static SECStatus ssl3_SendCertificateStatus( sslSocket *ss);
- static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss);
+@@ -57,6 +57,7 @@ static SECStatus ssl3_InitState(sslSocket *ss);
+
static SECStatus ssl3_SendCertificateRequest(sslSocket *ss);
- static SECStatus ssl3_SendNextProto( sslSocket *ss);
-+static SECStatus ssl3_SendEncryptedExtensions(sslSocket *ss);
- static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags);
- static SECStatus ssl3_SendServerHello( sslSocket *ss);
- static SECStatus ssl3_SendServerHelloDone( sslSocket *ss);
-@@ -6470,6 +6471,15 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+ static SECStatus ssl3_SendNextProto(sslSocket *ss);
++static SECStatus ssl3_SendChannelIDEncryptedExtensions(sslSocket *ss);
+ static SECStatus ssl3_SendFinished(sslSocket *ss, PRInt32 flags);
+ static SECStatus ssl3_SendServerHelloDone(sslSocket *ss);
+ static SECStatus ssl3_SendServerKeyExchange(sslSocket *ss);
+@@ -6762,6 +6763,15 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+ ss->ssl3.clientPrivateKey = NULL;
}
- #endif /* NSS_PLATFORM_CLIENT_AUTH */
+ if (ss->ssl3.channelID != NULL) {
-+ SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
-+ ss->ssl3.channelID = NULL;
++ SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
++ ss->ssl3.channelID = NULL;
+ }
+ if (ss->ssl3.channelIDPub != NULL) {
-+ SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
-+ ss->ssl3.channelIDPub = NULL;
++ SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
++ ss->ssl3.channelIDPub = NULL;
+ }
+
temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
if (temp < 0) {
- goto loser; /* alert has been sent */
-@@ -6780,7 +6790,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
- if (rv != SECSuccess) {
- goto alert_loser; /* err code was set */
- }
-- return SECSuccess;
-+ goto winner;
- } while (0);
+ goto loser; /* alert has been sent */
+@@ -7111,7 +7121,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+ if (rv != SECSuccess) {
+ goto alert_loser; /* err code was set */
+ }
+- return SECSuccess;
++ goto winner;
+ } while (0);
if (sid_match)
-@@ -6819,6 +6829,27 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+@@ -7166,6 +7176,27 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
PORT_Assert(ss->ssl3.hs.kea_def->ephemeral);
ss->ssl3.hs.ws = wait_server_key;
}
@@ -101,42 +101,42 @@ index 304e03b..2ae8ce9 100644
+ * allows the handshake to be restarted cleanly if the callback returns
+ * SECWouldBlock. */
+ if (ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
-+ rv = ss->getChannelID(ss->getChannelIDArg, ss->fd,
-+ &ss->ssl3.channelIDPub, &ss->ssl3.channelID);
-+ if (rv == SECWouldBlock) {
-+ ssl3_SetAlwaysBlock(ss);
-+ return rv;
-+ }
-+ if (rv != SECSuccess ||
-+ ss->ssl3.channelIDPub == NULL ||
-+ ss->ssl3.channelID == NULL) {
-+ PORT_SetError(SSL_ERROR_GET_CHANNEL_ID_FAILED);
-+ desc = internal_error;
-+ goto alert_loser;
-+ }
++ rv = ss->getChannelID(ss->getChannelIDArg, ss->fd,
++ &ss->ssl3.channelIDPub, &ss->ssl3.channelID);
++ if (rv == SECWouldBlock) {
++ ssl3_SetAlwaysBlock(ss);
++ return rv;
++ }
++ if (rv != SECSuccess ||
++ ss->ssl3.channelIDPub == NULL ||
++ ss->ssl3.channelID == NULL) {
++ PORT_SetError(SSL_ERROR_GET_CHANNEL_ID_FAILED);
++ desc = internal_error;
++ goto alert_loser;
++ }
+ }
+
return SECSuccess;
alert_loser:
-@@ -7774,7 +7805,14 @@ ssl3_SendClientSecondRound(sslSocket *ss)
- if (rv != SECSuccess) {
- goto loser; /* err code was set. */
- }
+@@ -8096,7 +8127,14 @@ ssl3_SendClientSecondRound(sslSocket *ss)
+ if (rv != SECSuccess) {
+ goto loser; /* err code was set. */
+ }
+ }
-+
-+ rv = ssl3_SendEncryptedExtensions(ss);
+
++ rv = ssl3_SendChannelIDEncryptedExtensions(ss);
+ if (rv != SECSuccess) {
-+ goto loser; /* err code was set. */
++ goto loser; /* err code was set. */
+ }
-
++
+ if (!ss->firstHsDone) {
- if (ss->opt.enableFalseStart) {
- if (!ss->ssl3.hs.authCertificatePending) {
- /* When we fix bug 589047, we will need to know whether we are
-@@ -7811,6 +7849,33 @@ ssl3_SendClientSecondRound(sslSocket *ss)
+ if (ss->opt.enableFalseStart) {
+ if (!ss->ssl3.hs.authCertificatePending) {
+ /* When we fix bug 589047, we will need to know whether we are
+@@ -8133,6 +8171,33 @@ ssl3_SendClientSecondRound(sslSocket *ss)
- ssl_ReleaseXmitBufLock(ss); /*******************************/
+ ssl_ReleaseXmitBufLock(ss); /*******************************/
+ if (!ss->ssl3.hs.isResuming &&
+ ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
@@ -166,16 +166,16 @@ index 304e03b..2ae8ce9 100644
+ }
+
if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
- ss->ssl3.hs.ws = wait_new_session_ticket;
+ ss->ssl3.hs.ws = wait_new_session_ticket;
else
-@@ -11264,6 +11329,184 @@ ssl3_RecordKeyLog(sslSocket *ss)
+@@ -11763,6 +11828,184 @@ ssl3_RecordKeyLog(sslSocket *ss)
}
/* called from ssl3_SendClientSecondRound
+ * ssl3_HandleFinished
+ */
+static SECStatus
-+ssl3_SendEncryptedExtensions(sslSocket *ss)
++ssl3_SendChannelIDEncryptedExtensions(sslSocket *ss)
+{
+ static const char CHANNEL_ID_MAGIC[] = "TLS Channel ID signature";
+ static const char CHANNEL_ID_RESUMPTION_MAGIC[] = "Resumption";
@@ -190,10 +190,10 @@ index 304e03b..2ae8ce9 100644
+ * public key. Following that are the two field elements as 32-byte,
+ * big-endian numbers, as required by the Channel ID. */
+ static const unsigned char P256_SPKI_PREFIX[] = {
-+ 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
-+ 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
-+ 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
-+ 0x42, 0x00, 0x04
++ 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
++ 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
++ 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
++ 0x42, 0x00, 0x04
+ };
+ /* ChannelIDs are always 128 bytes long: 64 bytes of P-256 public key and 64
+ * bytes of ECDSA signature. */
@@ -206,7 +206,7 @@ index 304e03b..2ae8ce9 100644
+ const unsigned char *pub_bytes;
+ unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) +
+ sizeof(CHANNEL_ID_RESUMPTION_MAGIC) +
-+ sizeof(SSL3Hashes)*2];
++ sizeof(SSL3Hashes) * 2];
+ size_t signed_data_len;
+ unsigned char digest[SHA256_LENGTH];
+ SECItem digest_item;
@@ -217,15 +217,15 @@ index 304e03b..2ae8ce9 100644
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ if (ss->ssl3.channelID == NULL)
-+ return SECSuccess;
++ return SECSuccess;
+
+ PORT_Assert(ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn));
+
+ if (SECKEY_GetPrivateKeyType(ss->ssl3.channelID) != ecKey ||
-+ PK11_SignatureLen(ss->ssl3.channelID) != sizeof(signature)) {
-+ PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
-+ rv = SECFailure;
-+ goto loser;
++ PK11_SignatureLen(ss->ssl3.channelID) != sizeof(signature)) {
++ PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
++ rv = SECFailure;
++ goto loser;
+ }
+
+ ssl_GetSpecReadLock(ss);
@@ -233,26 +233,26 @@ index 304e03b..2ae8ce9 100644
+ ssl_ReleaseSpecReadLock(ss);
+
+ if (rv != SECSuccess)
-+ goto loser;
++ goto loser;
+
-+ rv = ssl3_AppendHandshakeHeader(ss, encrypted_extensions,
-+ 2 + 2 + CHANNEL_ID_LENGTH);
++ rv = ssl3_AppendHandshakeHeader(ss, channelid_encrypted_extensions,
++ 2 + 2 + CHANNEL_ID_LENGTH);
+ if (rv != SECSuccess)
-+ goto loser; /* error code set by AppendHandshakeHeader */
++ goto loser; /* error code set by AppendHandshakeHeader */
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
+ if (rv != SECSuccess)
-+ goto loser; /* error code set by AppendHandshake */
++ goto loser; /* error code set by AppendHandshake */
+ rv = ssl3_AppendHandshakeNumber(ss, CHANNEL_ID_LENGTH, 2);
+ if (rv != SECSuccess)
-+ goto loser; /* error code set by AppendHandshake */
++ goto loser; /* error code set by AppendHandshake */
+
+ spki = SECKEY_EncodeDERSubjectPublicKeyInfo(ss->ssl3.channelIDPub);
+
+ if (spki->len != sizeof(P256_SPKI_PREFIX) + CHANNEL_ID_PUBLIC_KEY_LENGTH ||
-+ memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX)) != 0) {
-+ PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
-+ rv = SECFailure;
-+ goto loser;
++ memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX)) != 0) {
++ PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
++ rv = SECFailure;
++ goto loser;
+ }
+
+ pub_bytes = spki->data + sizeof(P256_SPKI_PREFIX);
@@ -278,7 +278,7 @@ index 304e03b..2ae8ce9 100644
+
+ rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, signed_data_len);
+ if (rv != SECSuccess)
-+ goto loser;
++ goto loser;
+
+ digest_item.data = digest;
+ digest_item.len = sizeof(digest);
@@ -288,23 +288,23 @@ index 304e03b..2ae8ce9 100644
+
+ rv = PK11_Sign(ss->ssl3.channelID, &signature_item, &digest_item);
+ if (rv != SECSuccess)
-+ goto loser;
++ goto loser;
+
+ rv = ssl3_AppendHandshake(ss, pub_bytes, CHANNEL_ID_PUBLIC_KEY_LENGTH);
+ if (rv != SECSuccess)
-+ goto loser;
++ goto loser;
+ rv = ssl3_AppendHandshake(ss, signature, sizeof(signature));
+
+loser:
+ if (spki)
-+ SECITEM_FreeItem(spki, PR_TRUE);
++ SECITEM_FreeItem(spki, PR_TRUE);
+ if (ss->ssl3.channelID) {
-+ SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
-+ ss->ssl3.channelID = NULL;
++ SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
++ ss->ssl3.channelID = NULL;
+ }
+ if (ss->ssl3.channelIDPub) {
-+ SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
-+ ss->ssl3.channelIDPub = NULL;
++ SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
++ ss->ssl3.channelIDPub = NULL;
+ }
+
+ return rv;
@@ -317,30 +317,30 @@ index 304e03b..2ae8ce9 100644
+ * waiting in the buffer or we'll get network I/O. */
+SECStatus
+ssl3_RestartHandshakeAfterChannelIDReq(sslSocket *ss,
-+ SECKEYPublicKey *channelIDPub,
-+ SECKEYPrivateKey *channelID)
++ SECKEYPublicKey *channelIDPub,
++ SECKEYPrivateKey *channelID)
+{
+ if (ss->handshake == 0) {
-+ SECKEY_DestroyPublicKey(channelIDPub);
-+ SECKEY_DestroyPrivateKey(channelID);
-+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-+ return SECFailure;
++ SECKEY_DestroyPublicKey(channelIDPub);
++ SECKEY_DestroyPrivateKey(channelID);
++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++ return SECFailure;
+ }
+
+ if (channelIDPub == NULL ||
-+ channelID == NULL) {
-+ if (channelIDPub)
-+ SECKEY_DestroyPublicKey(channelIDPub);
-+ if (channelID)
-+ SECKEY_DestroyPrivateKey(channelID);
-+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-+ return SECFailure;
++ channelID == NULL) {
++ if (channelIDPub)
++ SECKEY_DestroyPublicKey(channelIDPub);
++ if (channelID)
++ SECKEY_DestroyPrivateKey(channelID);
++ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
++ return SECFailure;
+ }
+
+ if (ss->ssl3.channelID)
-+ SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
++ SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
+ if (ss->ssl3.channelIDPub)
-+ SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
++ SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
+
+ ss->handshake = ssl_GatherRecord1stHandshake;
+ ss->ssl3.channelID = channelID;
@@ -353,99 +353,99 @@ index 304e03b..2ae8ce9 100644
* ssl3_HandleClientHello
* ssl3_HandleFinished
*/
-@@ -11531,11 +11774,16 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
- flags = ssl_SEND_FLAG_FORCE_INTO_BUFFER;
- }
+@@ -12030,11 +12273,16 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
+ flags = ssl_SEND_FLAG_FORCE_INTO_BUFFER;
+ }
-- if (!isServer && !ss->firstHsDone) {
-- rv = ssl3_SendNextProto(ss);
-- if (rv != SECSuccess) {
-- goto xmit_loser; /* err code was set. */
-+ if (!isServer) {
-+ if (!ss->firstHsDone) {
-+ rv = ssl3_SendNextProto(ss);
-+ if (rv != SECSuccess) {
-+ goto xmit_loser; /* err code was set. */
-+ }
- }
-+ rv = ssl3_SendEncryptedExtensions(ss);
-+ if (rv != SECSuccess)
-+ goto xmit_loser; /* err code was set. */
- }
+- if (!isServer && !ss->firstHsDone) {
+- rv = ssl3_SendNextProto(ss);
+- if (rv != SECSuccess) {
+- goto xmit_loser; /* err code was set. */
++ if (!isServer) {
++ if (!ss->firstHsDone) {
++ rv = ssl3_SendNextProto(ss);
++ if (rv != SECSuccess) {
++ goto xmit_loser; /* err code was set. */
++ }
+ }
++ rv = ssl3_SendChannelIDEncryptedExtensions(ss);
++ if (rv != SECSuccess)
++ goto xmit_loser; /* err code was set. */
+ }
- if (IS_DTLS(ss)) {
-@@ -13095,6 +13343,11 @@ ssl3_DestroySSL3Info(sslSocket *ss)
- ssl_FreePlatformKey(ss->ssl3.platformClientKey);
- #endif /* NSS_PLATFORM_CLIENT_AUTH */
+ if (IS_DTLS(ss)) {
+@@ -13658,6 +13906,11 @@ ssl3_DestroySSL3Info(sslSocket *ss)
+ if (ss->ssl3.clientPrivateKey != NULL)
+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
+ if (ss->ssl3.channelID)
-+ SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
++ SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
+ if (ss->ssl3.channelIDPub)
-+ SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
++ SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
+
if (ss->ssl3.peerCertArena != NULL)
- ssl3_CleanupPeerCerts(ss);
+ ssl3_CleanupPeerCerts(ss);
diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c
-index 5661a5c..78825cb 100644
+index 2e99a40..2ffe77b 100644
--- a/lib/ssl/ssl3ext.c
+++ b/lib/ssl/ssl3ext.c
-@@ -73,6 +73,10 @@ static SECStatus ssl3_ClientHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type,
+@@ -73,6 +73,10 @@ static SECStatus ssl3_ClientHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data);
- static SECStatus ssl3_ServerHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type,
+ static SECStatus ssl3_ServerHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data);
+static SECStatus ssl3_ClientHandleChannelIDXtn(sslSocket *ss,
-+ PRUint16 ex_type, SECItem *data);
++ PRUint16 ex_type, SECItem *data);
+static PRInt32 ssl3_ClientSendChannelIDXtn(sslSocket *ss, PRBool append,
-+ PRUint32 maxBytes);
- static PRInt32 ssl3_ServerSendStatusRequestXtn(sslSocket * ss,
- PRBool append, PRUint32 maxBytes);
++ PRUint32 maxBytes);
+ static PRInt32 ssl3_ServerSendStatusRequestXtn(sslSocket *ss,
+ PRBool append, PRUint32 maxBytes);
static SECStatus ssl3_ServerHandleStatusRequestXtn(sslSocket *ss,
-@@ -276,6 +280,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
- { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
+@@ -298,6 +302,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
+ { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
{ ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn },
- { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn },
-+ { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
- { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
+ { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn },
++ { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
{ ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
- { -1, NULL }
-@@ -304,6 +309,7 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
- { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn },
- { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn },
- { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn },
-+ { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
- { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
- { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
- { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
-@@ -945,6 +951,61 @@ ssl3_ServerSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
+ { ssl_signed_cert_timestamp_xtn, &ssl3_ClientHandleSignedCertTimestampXtn },
+@@ -329,6 +334,7 @@ static const ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS]
+ { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn },
+ { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn },
+ { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn },
++ { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
+ { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
+ { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
+@@ -981,6 +987,61 @@ ssl3_ServerSendAppProtoXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
}
static SECStatus
+ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type,
-+ SECItem *data)
++ SECItem *data)
+{
+ PORT_Assert(ss->getChannelID != NULL);
+
+ if (data->len) {
-+ PORT_SetError(SSL_ERROR_BAD_CHANNEL_ID_DATA);
-+ return SECFailure;
++ PORT_SetError(SSL_ERROR_BAD_CHANNEL_ID_DATA);
++ return SECFailure;
+ }
+ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
+ return SECSuccess;
+}
+
+static PRInt32
-+ssl3_ClientSendChannelIDXtn(sslSocket * ss, PRBool append,
-+ PRUint32 maxBytes)
++ssl3_ClientSendChannelIDXtn(sslSocket *ss, PRBool append,
++ PRUint32 maxBytes)
+{
+ PRInt32 extension_length = 4;
+
+ if (!ss->getChannelID)
-+ return 0;
++ return 0;
+
+ if (maxBytes < extension_length) {
-+ PORT_Assert(0);
-+ return 0;
++ PORT_Assert(0);
++ return 0;
+ }
+
+ if (ss->sec.ci.sid->cached != never_cached &&
@@ -454,19 +454,19 @@ index 5661a5c..78825cb 100644
+ * do ChannelID on the original connection: without ChannelID on the
+ * original connection we didn't record the handshake hashes needed for
+ * the signature. */
-+ return 0;
++ return 0;
+ }
+
+ if (append) {
-+ SECStatus rv;
-+ rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
-+ if (rv != SECSuccess)
-+ goto loser;
-+ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-+ if (rv != SECSuccess)
-+ goto loser;
-+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-+ ssl_channel_id_xtn;
++ SECStatus rv;
++ rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
++ if (rv != SECSuccess)
++ goto loser;
++ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
++ if (rv != SECSuccess)
++ goto loser;
++ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
++ ssl_channel_id_xtn;
+ }
+
+ return extension_length;
@@ -477,40 +477,41 @@ index 5661a5c..78825cb 100644
+
+static SECStatus
ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type,
- SECItem *data)
+ SECItem *data)
{
diff --git a/lib/ssl/ssl3prot.h b/lib/ssl/ssl3prot.h
-index a93bef1..848bdee 100644
+index e637d11..928d059 100644
--- a/lib/ssl/ssl3prot.h
+++ b/lib/ssl/ssl3prot.h
-@@ -136,7 +136,8 @@ typedef enum {
+@@ -140,7 +140,8 @@ typedef enum {
client_key_exchange = 16,
- finished = 20,
- certificate_status = 22,
-- next_proto = 67
-+ next_proto = 67,
-+ encrypted_extensions = 203,
+ finished = 20,
+ certificate_status = 22,
+- next_proto = 67
++ next_proto = 67,
++ channelid_encrypted_extensions = 203
} SSL3HandshakeType;
typedef struct {
diff --git a/lib/ssl/sslauth.c b/lib/ssl/sslauth.c
-index e6981f0..03b23b4 100644
+index 7fb4dc5..e78a513 100644
--- a/lib/ssl/sslauth.c
+++ b/lib/ssl/sslauth.c
-@@ -216,6 +216,24 @@ SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
+@@ -221,6 +221,25 @@ SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
return SECSuccess;
}
+SECStatus
+SSL_SetClientChannelIDCallback(PRFileDesc *fd,
-+ SSLClientChannelIDCallback callback,
-+ void *arg) {
++ SSLClientChannelIDCallback callback,
++ void *arg)
++{
+ sslSocket *ss = ssl_FindSocket(fd);
+
+ if (!ss) {
-+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetClientChannelIDCallback",
-+ SSL_GETPID(), fd));
-+ return SECFailure;
++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetClientChannelIDCallback",
++ SSL_GETPID(), fd));
++ return SECFailure;
+ }
+
+ ss->getChannelID = callback;
@@ -519,31 +520,32 @@ index e6981f0..03b23b4 100644
+ return SECSuccess;
+}
+
- #ifdef NSS_PLATFORM_CLIENT_AUTH
/* NEED LOCKS IN HERE. */
- SECStatus
+ SECStatus
+ SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
diff --git a/lib/ssl/sslerr.h b/lib/ssl/sslerr.h
-index 192a107..835b812 100644
+index f806359..299951c 100644
--- a/lib/ssl/sslerr.h
+++ b/lib/ssl/sslerr.h
-@@ -208,6 +208,10 @@ SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 135),
- SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET = (SSL_ERROR_BASE + 136),
- SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET = (SSL_ERROR_BASE + 137),
-
-+SSL_ERROR_BAD_CHANNEL_ID_DATA = (SSL_ERROR_BASE + 138),
-+SSL_ERROR_INVALID_CHANNEL_ID_KEY = (SSL_ERROR_BASE + 139),
-+SSL_ERROR_GET_CHANNEL_ID_FAILED = (SSL_ERROR_BASE + 140),
+@@ -220,6 +220,11 @@ typedef enum {
+ SSL_ERROR_KEY_EXCHANGE_FAILURE = (SSL_ERROR_BASE + 144),
+ SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION = (SSL_ERROR_BASE + 145),
+ SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS = (SSL_ERROR_BASE + 146),
++
++ SSL_ERROR_BAD_CHANNEL_ID_DATA = (SSL_ERROR_BASE + 147),
++ SSL_ERROR_INVALID_CHANNEL_ID_KEY = (SSL_ERROR_BASE + 148),
++ SSL_ERROR_GET_CHANNEL_ID_FAILED = (SSL_ERROR_BASE + 149),
+
- SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
+ SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
} SSLErrorCodes;
#endif /* NO_SECURITY_ERROR_ENUM */
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index c089889..c286518 100644
+index dad75b2..4607655 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
-@@ -722,6 +722,14 @@ struct sslSessionIDStr {
+@@ -710,6 +710,14 @@ struct sslSessionIDStr {
- SECItem srvName;
+ SECItem srvName;
+ /* originalHandshakeHash contains the hash of the original, full
+ * handshake prior to the server's final flow. This is either a
@@ -551,34 +553,36 @@ index c089889..c286518 100644
+ * TLS 1.2). This is recorded and used only when ChannelID is
+ * negotiated as it's used to bind the ChannelID signature on the
+ * resumption handshake to the original handshake. */
-+ SECItem originalHandshakeHash;
-+
- /* This lock is lazily initialized by CacheSID when a sid is first
- * cached. Before then, there is no need to lock anything because
- * the sid isn't being shared by anything.
-@@ -999,6 +1007,9 @@ struct ssl3StateStr {
- CERTCertificateList *clientCertChain; /* used by client */
- PRBool sendEmptyCert; /* used by client */
-
-+ SECKEYPrivateKey *channelID; /* used by client */
-+ SECKEYPublicKey *channelIDPub; /* used by client */
-+
- int policy;
- /* This says what cipher suites we can do, and should
- * be either SSL_ALLOWED or SSL_RESTRICTED
-@@ -1294,6 +1305,8 @@ const unsigned char * preferredCipher;
- void *pkcs11PinArg;
- SSLNextProtoCallback nextProtoCallback;
- void *nextProtoArg;
-+ SSLClientChannelIDCallback getChannelID;
-+ void *getChannelIDArg;
++ SECItem originalHandshakeHash;
++
+ /* Signed certificate timestamps received in a TLS extension.
+ ** (used only in client).
+ */
+@@ -1025,6 +1033,9 @@ struct ssl3StateStr {
+ CERTCertificateList *clientCertChain; /* used by client */
+ PRBool sendEmptyCert; /* used by client */
- PRIntervalTime rTimeout; /* timeout for NSPR I/O */
- PRIntervalTime wTimeout; /* timeout for NSPR I/O */
-@@ -1640,6 +1653,11 @@ extern SECStatus ssl3_RestartHandshakeAfterCertReq(sslSocket * ss,
- SECKEYPrivateKey * key,
- CERTCertificateList *certChain);
++ SECKEYPrivateKey *channelID; /* used by client */
++ SECKEYPublicKey *channelIDPub; /* used by client */
++
+ int policy;
+ /* This says what cipher suites we can do, and should
+ * be either SSL_ALLOWED or SSL_RESTRICTED
+@@ -1322,6 +1333,9 @@ struct sslSocketStr {
+ SSLNextProtoCallback nextProtoCallback;
+ void *nextProtoArg;
++ SSLClientChannelIDCallback getChannelID;
++ void *getChannelIDArg;
++
+ PRIntervalTime rTimeout; /* timeout for NSPR I/O */
+ PRIntervalTime wTimeout; /* timeout for NSPR I/O */
+ PRIntervalTime cTimeout; /* timeout for NSPR I/O */
+@@ -1712,6 +1726,12 @@ extern SECStatus ssl3_RestartHandshakeAfterCertReq(struct sslSocketStr *ss,
+ CERTCertificate *cert,
+ SECKEYPrivateKey *key,
+ CERTCertificateList *certChain);
++
+extern SECStatus ssl3_RestartHandshakeAfterChannelIDReq(
+ sslSocket *ss,
+ SECKEYPublicKey *channelIDPub,
@@ -588,12 +592,12 @@ index c089889..c286518 100644
/*
diff --git a/lib/ssl/sslnonce.c b/lib/ssl/sslnonce.c
-index be11008..1326a8b 100644
+index 3216892..4804cb8 100644
--- a/lib/ssl/sslnonce.c
+++ b/lib/ssl/sslnonce.c
-@@ -180,6 +180,9 @@ ssl_DestroySID(sslSessionID *sid)
- if (sid->u.ssl3.srvName.data) {
- SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE);
+@@ -186,6 +186,9 @@ ssl_DestroySID(sslSessionID *sid)
+ if (sid->u.ssl3.signedCertTimestamps.data) {
+ SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE);
}
+ if (sid->u.ssl3.originalHandshakeHash.data) {
+ SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE);
@@ -602,39 +606,38 @@ index be11008..1326a8b 100644
if (sid->u.ssl3.lock) {
PR_DestroyRWLock(sid->u.ssl3.lock);
diff --git a/lib/ssl/sslsecur.c b/lib/ssl/sslsecur.c
-index f77d6fa..cca55bb 100644
+index a087ffc..7ff0a2c 100644
--- a/lib/ssl/sslsecur.c
+++ b/lib/ssl/sslsecur.c
-@@ -1598,6 +1598,42 @@ SSL_RestartHandshakeAfterCertReq(PRFileDesc * fd,
+@@ -1601,6 +1601,41 @@ SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd,
return ret;
}
+SECStatus
-+SSL_RestartHandshakeAfterChannelIDReq(PRFileDesc * fd,
-+ SECKEYPublicKey * channelIDPub,
-+ SECKEYPrivateKey *channelID)
++SSL_RestartHandshakeAfterChannelIDReq(PRFileDesc *fd,
++ SECKEYPublicKey *channelIDPub,
++ SECKEYPrivateKey *channelID)
+{
-+ sslSocket * ss = ssl_FindSocket(fd);
-+ SECStatus ret;
++ sslSocket *ss = ssl_FindSocket(fd);
++ SECStatus ret;
+
+ if (!ss) {
-+ SSL_DBG(("%d: SSL[%d]: bad socket in"
-+ " SSL_RestartHandshakeAfterChannelIDReq",
-+ SSL_GETPID(), fd));
-+ goto loser;
++ SSL_DBG(("%d: SSL[%d]: bad socket in"
++ " SSL_RestartHandshakeAfterChannelIDReq",
++ SSL_GETPID(), fd));
++ goto loser;
+ }
+
-+
+ ssl_Get1stHandshakeLock(ss);
+
+ if (ss->version < SSL_LIBRARY_VERSION_3_0) {
-+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-+ ssl_Release1stHandshakeLock(ss);
-+ goto loser;
++ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
++ ssl_Release1stHandshakeLock(ss);
++ goto loser;
+ }
+
+ ret = ssl3_RestartHandshakeAfterChannelIDReq(ss, channelIDPub,
-+ channelID);
++ channelID);
+ ssl_Release1stHandshakeLock(ss);
+
+ return ret;
@@ -649,53 +652,53 @@ index f77d6fa..cca55bb 100644
* this implementation exists to maintain link-time compatibility.
*/
diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index 11e66f2..efba686 100644
+index 7f97b14..84c78b3 100644
--- a/lib/ssl/sslsock.c
+++ b/lib/ssl/sslsock.c
-@@ -313,6 +313,8 @@ ssl_DupSocket(sslSocket *os)
+@@ -315,6 +315,8 @@ ssl_DupSocket(sslSocket *os)
ss->canFalseStartCallback = os->canFalseStartCallback;
ss->canFalseStartCallbackData = os->canFalseStartCallbackData;
- ss->pkcs11PinArg = os->pkcs11PinArg;
-+ ss->getChannelID = os->getChannelID;
-+ ss->getChannelIDArg = os->getChannelIDArg;
+ ss->pkcs11PinArg = os->pkcs11PinArg;
++ ss->getChannelID = os->getChannelID;
++ ss->getChannelIDArg = os->getChannelIDArg;
/* Create security data */
rv = ssl_CopySecurityInfo(ss, os);
-@@ -1987,6 +1989,10 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
+@@ -2155,6 +2157,10 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
ss->handshakeCallbackData = sm->handshakeCallbackData;
if (sm->pkcs11PinArg)
- ss->pkcs11PinArg = sm->pkcs11PinArg;
+ ss->pkcs11PinArg = sm->pkcs11PinArg;
+ if (sm->getChannelID)
-+ ss->getChannelID = sm->getChannelID;
++ ss->getChannelID = sm->getChannelID;
+ if (sm->getChannelIDArg)
-+ ss->getChannelIDArg = sm->getChannelIDArg;
++ ss->getChannelIDArg = sm->getChannelIDArg;
return fd;
loser:
return NULL;
-@@ -3279,6 +3285,8 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
- ss->badCertArg = NULL;
- ss->pkcs11PinArg = NULL;
+@@ -3643,6 +3649,8 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
+ ss->badCertArg = NULL;
+ ss->pkcs11PinArg = NULL;
ss->ephemeralECDHKeyPair = NULL;
-+ ss->getChannelID = NULL;
-+ ss->getChannelIDArg = NULL;
++ ss->getChannelID = NULL;
++ ss->getChannelIDArg = NULL;
ssl_ChooseOps(ss);
ssl2_InitSocketPolicy(ss);
diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h
-index cd742bb..b6616e2 100644
+index bf722b5..6f26e5f 100644
--- a/lib/ssl/sslt.h
+++ b/lib/ssl/sslt.h
-@@ -238,11 +238,12 @@ typedef enum {
- ssl_extended_master_secret_xtn = 23,
- ssl_session_ticket_xtn = 35,
- ssl_next_proto_nego_xtn = 13172,
-+ ssl_channel_id_xtn = 30032,
- ssl_renegotiation_info_xtn = 0xff01,
- ssl_tls13_draft_version_xtn = 0xff02 /* experimental number */
+@@ -249,11 +249,12 @@ typedef enum {
+ ssl_session_ticket_xtn = 35,
+ ssl_tls13_key_share_xtn = 40, /* unofficial TODO(ekr) */
+ ssl_next_proto_nego_xtn = 13172,
++ ssl_channel_id_xtn = 30032,
+ ssl_renegotiation_info_xtn = 0xff01,
+ ssl_tls13_draft_version_xtn = 0xff02 /* experimental number */
} SSLExtensionType;
--#define SSL_MAX_EXTENSIONS 12 /* doesn't include ssl_padding_xtn. */
-+#define SSL_MAX_EXTENSIONS 13 /* doesn't include ssl_padding_xtn. */
+-#define SSL_MAX_EXTENSIONS 14 /* doesn't include ssl_padding_xtn. */
++#define SSL_MAX_EXTENSIONS 15 /* doesn't include ssl_padding_xtn. */
typedef enum {
ssl_dhe_group_none = 0,
diff --git a/chromium/net/third_party/nss/patches/cipherorder.patch b/chromium/net/third_party/nss/patches/cipherorder.patch
index eb15be7b735..26e83261f7f 100644
--- a/chromium/net/third_party/nss/patches/cipherorder.patch
+++ b/chromium/net/third_party/nss/patches/cipherorder.patch
@@ -1,5 +1,5 @@
diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index db09425..437a822 100644
+index 3550580..70665a1 100644
--- a/lib/ssl/ssl.h
+++ b/lib/ssl/ssl.h
@@ -387,6 +387,13 @@ SSL_IMPORT SECStatus SSL_DHEGroupPrefSet(PRFileDesc *fd,
@@ -17,10 +17,10 @@ index db09425..437a822 100644
* values. See RFC 5929. */
typedef enum SSLChannelBindingType {
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 5c09f25..572bba9 100644
+index d7d186a..b100b9b 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
-@@ -13390,6 +13390,46 @@ SSL_SignatureMaxCount() {
+@@ -13797,6 +13797,46 @@ SSL_SignatureMaxCount()
return MAX_SIGNATURE_ALGORITHMS;
}
@@ -32,33 +32,33 @@ index 5c09f25..572bba9 100644
+ unsigned int i, done;
+
+ for (i = done = 0; i < len; i++) {
-+ PRUint16 id = ciphers[i];
-+ unsigned int existingIndex, j;
-+ PRBool found = PR_FALSE;
++ PRUint16 id = ciphers[i];
++ unsigned int existingIndex, j;
++ PRBool found = PR_FALSE;
+
-+ for (j = done; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
-+ if (ss->cipherSuites[j].cipher_suite == id) {
-+ existingIndex = j;
-+ found = PR_TRUE;
-+ break;
-+ }
-+ }
++ for (j = done; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
++ if (ss->cipherSuites[j].cipher_suite == id) {
++ existingIndex = j;
++ found = PR_TRUE;
++ break;
++ }
++ }
+
-+ if (!found) {
-+ continue;
-+ }
++ if (!found) {
++ continue;
++ }
+
-+ if (existingIndex != done) {
-+ const ssl3CipherSuiteCfg temp = ss->cipherSuites[done];
-+ ss->cipherSuites[done] = ss->cipherSuites[existingIndex];
-+ ss->cipherSuites[existingIndex] = temp;
-+ }
-+ done++;
++ if (existingIndex != done) {
++ const ssl3CipherSuiteCfg temp = ss->cipherSuites[done];
++ ss->cipherSuites[done] = ss->cipherSuites[existingIndex];
++ ss->cipherSuites[existingIndex] = temp;
++ }
++ done++;
+ }
+
+ /* Disable all cipher suites that weren't included. */
+ for (; done < ssl_V3_SUITES_IMPLEMENTED; done++) {
-+ ss->cipherSuites[done].enabled = 0;
++ ss->cipherSuites[done].enabled = 0;
+ }
+
+ return SECSuccess;
@@ -68,23 +68,23 @@ index 5c09f25..572bba9 100644
void
ssl3_InitSocketPolicy(sslSocket *ss)
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index 080debe..3403091 100644
+index c0e3a0b..f56ab53 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
-@@ -1786,6 +1786,8 @@ extern SECStatus ssl3_CipherPrefSet(sslSocket *ss, ssl3CipherSuite which, PRBool
+@@ -1835,6 +1835,8 @@ extern SECStatus ssl3_CipherPrefSet(sslSocket *ss, ssl3CipherSuite which, PRBool
extern SECStatus ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *on);
extern SECStatus ssl2_CipherPrefSet(sslSocket *ss, PRInt32 which, PRBool enabled);
extern SECStatus ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled);
+extern SECStatus ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *cipher,
-+ unsigned int len);
++ unsigned int len);
extern SECStatus ssl3_SetPolicy(ssl3CipherSuite which, PRInt32 policy);
extern SECStatus ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *policy);
diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index 28e3543..8ad1517 100644
+index e312d82..e82c916 100644
--- a/lib/ssl/sslsock.c
+++ b/lib/ssl/sslsock.c
-@@ -1369,6 +1369,19 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled)
+@@ -1500,6 +1500,19 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled)
}
SECStatus
@@ -93,9 +93,9 @@ index 28e3543..8ad1517 100644
+ sslSocket *ss = ssl_FindSocket(fd);
+
+ if (!ss) {
-+ SSL_DBG(("%d: SSL[%d]: bad socket in CipherOrderSet", SSL_GETPID(),
-+ fd));
-+ return SECFailure;
++ SSL_DBG(("%d: SSL[%d]: bad socket in CipherOrderSet", SSL_GETPID(),
++ fd));
++ return SECFailure;
+ }
+ return ssl3_CipherOrderSet(ss, ciphers, len);
+}
@@ -103,4 +103,4 @@ index 28e3543..8ad1517 100644
+SECStatus
SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled)
{
- SECStatus rv;
+ SECStatus rv;
diff --git a/chromium/net/third_party/nss/patches/clientauth.patch b/chromium/net/third_party/nss/patches/clientauth.patch
deleted file mode 100644
index 17539d16322..00000000000
--- a/chromium/net/third_party/nss/patches/clientauth.patch
+++ /dev/null
@@ -1,457 +0,0 @@
-diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index 2a52769..48fa018 100644
---- a/lib/ssl/ssl.h
-+++ b/lib/ssl/ssl.h
-@@ -636,6 +636,48 @@ typedef SECStatus (PR_CALLBACK *SSLGetClientAuthData)(void *arg,
- SSL_IMPORT SECStatus SSL_GetClientAuthDataHook(PRFileDesc *fd,
- SSLGetClientAuthData f, void *a);
-
-+/*
-+ * Prototype for SSL callback to get client auth data from the application,
-+ * optionally using the underlying platform's cryptographic primitives.
-+ * To use the platform cryptographic primitives, caNames and pRetCerts
-+ * should be set. To use NSS, pRetNSSCert and pRetNSSKey should be set.
-+ * Returning SECFailure will cause the socket to send no client certificate.
-+ * arg - application passed argument
-+ * caNames - pointer to distinguished names of CAs that the server likes
-+ * pRetCerts - pointer to pointer to list of certs, with the first being
-+ * the client cert, and any following being used for chain
-+ * building
-+ * pRetKey - pointer to native key pointer, for return of key
-+ * - Windows: A pointer to a PCERT_KEY_CONTEXT that was allocated
-+ * via PORT_Alloc(). Ownership of the PCERT_KEY_CONTEXT
-+ * is transferred to NSS, which will free via
-+ * PORT_Free().
-+ * - Mac OS X: A pointer to a SecKeyRef. Ownership is
-+ * transferred to NSS, which will free via CFRelease().
-+ * pRetNSSCert - pointer to pointer to NSS cert, for return of cert.
-+ * pRetNSSKey - pointer to NSS key pointer, for return of key.
-+ */
-+typedef SECStatus (PR_CALLBACK *SSLGetPlatformClientAuthData)(void *arg,
-+ PRFileDesc *fd,
-+ CERTDistNames *caNames,
-+ CERTCertList **pRetCerts,/*return */
-+ void **pRetKey,/* return */
-+ CERTCertificate **pRetNSSCert,/*return */
-+ SECKEYPrivateKey **pRetNSSKey);/* return */
-+
-+/*
-+ * Set the client side callback for SSL to retrieve user's private key
-+ * and certificate.
-+ * Note: If a platform client auth callback is set, the callback configured by
-+ * SSL_GetClientAuthDataHook, if any, will not be called.
-+ *
-+ * fd - the file descriptor for the connection in question
-+ * f - the application's callback that delivers the key and cert
-+ * a - application specific data
-+ */
-+SSL_IMPORT SECStatus
-+SSL_GetPlatformClientAuthDataHook(PRFileDesc *fd,
-+ SSLGetPlatformClientAuthData f, void *a);
-
- /*
- ** SNI extension processing callback function.
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 9aaf601..cc193cd 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -2530,6 +2530,9 @@ ssl3_ClientAuthTokenPresent(sslSessionID *sid) {
- PRBool isPresent = PR_TRUE;
-
- /* we only care if we are doing client auth */
-+ /* If NSS_PLATFORM_CLIENT_AUTH is defined and a platformClientKey is being
-+ * used, u.ssl3.clAuthValid will be false and this function will always
-+ * return PR_TRUE. */
- if (!sid || !sid->u.ssl3.clAuthValid) {
- return PR_TRUE;
- }
-@@ -6352,25 +6355,36 @@ ssl3_SendCertificateVerify(sslSocket *ss)
-
- isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
- isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-- keyType = ss->ssl3.clientPrivateKey->keyType;
-- rv = ssl3_SignHashes(&hashes, ss->ssl3.clientPrivateKey, &buf, isTLS);
-- if (rv == SECSuccess) {
-- PK11SlotInfo * slot;
-- sslSessionID * sid = ss->sec.ci.sid;
-+ if (ss->ssl3.platformClientKey) {
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+ keyType = CERT_GetCertKeyType(
-+ &ss->ssl3.clientCertificate->subjectPublicKeyInfo);
-+ rv = ssl3_PlatformSignHashes(
-+ &hashes, ss->ssl3.platformClientKey, &buf, isTLS, keyType);
-+ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
-+ ss->ssl3.platformClientKey = (PlatformKey)NULL;
-+#endif /* NSS_PLATFORM_CLIENT_AUTH */
-+ } else {
-+ keyType = ss->ssl3.clientPrivateKey->keyType;
-+ rv = ssl3_SignHashes(&hashes, ss->ssl3.clientPrivateKey, &buf, isTLS);
-+ if (rv == SECSuccess) {
-+ PK11SlotInfo * slot;
-+ sslSessionID * sid = ss->sec.ci.sid;
-
-- /* Remember the info about the slot that did the signing.
-- ** Later, when doing an SSL restart handshake, verify this.
-- ** These calls are mere accessors, and can't fail.
-- */
-- slot = PK11_GetSlotFromPrivateKey(ss->ssl3.clientPrivateKey);
-- sid->u.ssl3.clAuthSeries = PK11_GetSlotSeries(slot);
-- sid->u.ssl3.clAuthSlotID = PK11_GetSlotID(slot);
-- sid->u.ssl3.clAuthModuleID = PK11_GetModuleID(slot);
-- sid->u.ssl3.clAuthValid = PR_TRUE;
-- PK11_FreeSlot(slot);
-+ /* Remember the info about the slot that did the signing.
-+ ** Later, when doing an SSL restart handshake, verify this.
-+ ** These calls are mere accessors, and can't fail.
-+ */
-+ slot = PK11_GetSlotFromPrivateKey(ss->ssl3.clientPrivateKey);
-+ sid->u.ssl3.clAuthSeries = PK11_GetSlotSeries(slot);
-+ sid->u.ssl3.clAuthSlotID = PK11_GetSlotID(slot);
-+ sid->u.ssl3.clAuthModuleID = PK11_GetModuleID(slot);
-+ sid->u.ssl3.clAuthValid = PR_TRUE;
-+ PK11_FreeSlot(slot);
-+ }
-+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-+ ss->ssl3.clientPrivateKey = NULL;
- }
-- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-- ss->ssl3.clientPrivateKey = NULL;
- if (rv != SECSuccess) {
- goto done; /* err code was set by ssl3_SignHashes */
- }
-@@ -6449,6 +6463,12 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
- ss->ssl3.clientPrivateKey = NULL;
- }
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+ if (ss->ssl3.platformClientKey) {
-+ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
-+ ss->ssl3.platformClientKey = (PlatformKey)NULL;
-+ }
-+#endif /* NSS_PLATFORM_CLIENT_AUTH */
-
- temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
- if (temp < 0) {
-@@ -7109,6 +7129,18 @@ ssl3_ExtractClientKeyInfo(sslSocket *ss,
- goto done;
- }
-
-+#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(_WIN32)
-+ /* If the key is in CAPI, assume conservatively that the CAPI service
-+ * provider may be unable to sign SHA-256 hashes.
-+ */
-+ if (ss->ssl3.platformClientKey->dwKeySpec != CERT_NCRYPT_KEY_SPEC) {
-+ /* CAPI only supports RSA and DSA signatures, so we don't need to
-+ * check the key type. */
-+ *preferSha1 = PR_TRUE;
-+ goto done;
-+ }
-+#endif /* NSS_PLATFORM_CLIENT_AUTH && _WIN32 */
-+
- /* If the key is a 1024-bit RSA or DSA key, assume conservatively that
- * it may be unable to sign SHA-256 hashes. This is the case for older
- * Estonian ID cards that have 1024-bit RSA keys. In FIPS 186-2 and
-@@ -7207,6 +7239,10 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
- SECItem cert_types = {siBuffer, NULL, 0};
- SECItem algorithms = {siBuffer, NULL, 0};
- CERTDistNames ca_list;
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+ CERTCertList * platform_cert_list = NULL;
-+ CERTCertListNode * certNode = NULL;
-+#endif /* NSS_PLATFORM_CLIENT_AUTH */
-
- SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake",
- SSL_GETPID(), ss->fd));
-@@ -7222,6 +7258,7 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
- PORT_Assert(ss->ssl3.clientCertChain == NULL);
- PORT_Assert(ss->ssl3.clientCertificate == NULL);
- PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
-+ PORT_Assert(ss->ssl3.platformClientKey == (PlatformKey)NULL);
-
- isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
- isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
-@@ -7301,6 +7338,18 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
- desc = no_certificate;
- ss->ssl3.hs.ws = wait_hello_done;
-
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+ if (ss->getPlatformClientAuthData != NULL) {
-+ /* XXX Should pass cert_types and algorithms in this call!! */
-+ rv = (SECStatus)(*ss->getPlatformClientAuthData)(
-+ ss->getPlatformClientAuthDataArg,
-+ ss->fd, &ca_list,
-+ &platform_cert_list,
-+ (void**)&ss->ssl3.platformClientKey,
-+ &ss->ssl3.clientCertificate,
-+ &ss->ssl3.clientPrivateKey);
-+ } else
-+#endif
- if (ss->getClientAuthData != NULL) {
- PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
- ssl_preinfo_all);
-@@ -7312,12 +7361,55 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
- } else {
- rv = SECFailure; /* force it to send a no_certificate alert */
- }
-+
- switch (rv) {
- case SECWouldBlock: /* getClientAuthData has put up a dialog box. */
- ssl3_SetAlwaysBlock(ss);
- break; /* not an error */
-
- case SECSuccess:
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+ if (!platform_cert_list || CERT_LIST_EMPTY(platform_cert_list) ||
-+ !ss->ssl3.platformClientKey) {
-+ if (platform_cert_list) {
-+ CERT_DestroyCertList(platform_cert_list);
-+ platform_cert_list = NULL;
-+ }
-+ if (ss->ssl3.platformClientKey) {
-+ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
-+ ss->ssl3.platformClientKey = (PlatformKey)NULL;
-+ }
-+ /* Fall through to NSS client auth check */
-+ } else {
-+ certNode = CERT_LIST_HEAD(platform_cert_list);
-+ ss->ssl3.clientCertificate = CERT_DupCertificate(certNode->cert);
-+
-+ /* Setting ssl3.clientCertChain non-NULL will cause
-+ * ssl3_HandleServerHelloDone to call SendCertificate.
-+ * Note: clientCertChain should include the EE cert as
-+ * clientCertificate is ignored during the actual sending
-+ */
-+ ss->ssl3.clientCertChain =
-+ hack_NewCertificateListFromCertList(platform_cert_list);
-+ CERT_DestroyCertList(platform_cert_list);
-+ platform_cert_list = NULL;
-+ if (ss->ssl3.clientCertChain == NULL) {
-+ if (ss->ssl3.clientCertificate != NULL) {
-+ CERT_DestroyCertificate(ss->ssl3.clientCertificate);
-+ ss->ssl3.clientCertificate = NULL;
-+ }
-+ if (ss->ssl3.platformClientKey) {
-+ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
-+ ss->ssl3.platformClientKey = (PlatformKey)NULL;
-+ }
-+ goto send_no_certificate;
-+ }
-+ if (ss->ssl3.hs.hashType == handshake_hash_single) {
-+ ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, &algorithms);
-+ }
-+ break; /* not an error */
-+ }
-+#endif /* NSS_PLATFORM_CLIENT_AUTH */
- /* check what the callback function returned */
- if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) {
- /* we are missing either the key or cert */
-@@ -7379,6 +7471,10 @@ loser:
- done:
- if (arena != NULL)
- PORT_FreeArena(arena, PR_FALSE);
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+ if (platform_cert_list)
-+ CERT_DestroyCertList(platform_cert_list);
-+#endif
- return rv;
- }
-
-@@ -7497,7 +7593,8 @@ ssl3_SendClientSecondRound(sslSocket *ss)
-
- sendClientCert = !ss->ssl3.sendEmptyCert &&
- ss->ssl3.clientCertChain != NULL &&
-- ss->ssl3.clientPrivateKey != NULL;
-+ (ss->ssl3.platformClientKey ||
-+ ss->ssl3.clientPrivateKey != NULL);
-
- if (!sendClientCert &&
- ss->ssl3.hs.hashType == handshake_hash_single &&
-@@ -12910,6 +13007,10 @@ ssl3_DestroySSL3Info(sslSocket *ss)
-
- if (ss->ssl3.clientPrivateKey != NULL)
- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+ if (ss->ssl3.platformClientKey)
-+ ssl_FreePlatformKey(ss->ssl3.platformClientKey);
-+#endif /* NSS_PLATFORM_CLIENT_AUTH */
-
- if (ss->ssl3.peerCertArena != NULL)
- ssl3_CleanupPeerCerts(ss);
-diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c
-index cf04aba..5661a5c 100644
---- a/lib/ssl/ssl3ext.c
-+++ b/lib/ssl/ssl3ext.c
-@@ -11,8 +11,8 @@
- #include "nssrenam.h"
- #include "nss.h"
- #include "ssl.h"
--#include "sslproto.h"
- #include "sslimpl.h"
-+#include "sslproto.h"
- #include "pk11pub.h"
- #ifdef NO_PKCS11_BYPASS
- #include "blapit.h"
-diff --git a/lib/ssl/sslauth.c b/lib/ssl/sslauth.c
-index b144336..e6981f0 100644
---- a/lib/ssl/sslauth.c
-+++ b/lib/ssl/sslauth.c
-@@ -216,6 +216,28 @@ SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
- return SECSuccess;
- }
-
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+/* NEED LOCKS IN HERE. */
-+SECStatus
-+SSL_GetPlatformClientAuthDataHook(PRFileDesc *s,
-+ SSLGetPlatformClientAuthData func,
-+ void *arg)
-+{
-+ sslSocket *ss;
-+
-+ ss = ssl_FindSocket(s);
-+ if (!ss) {
-+ SSL_DBG(("%d: SSL[%d]: bad socket in GetPlatformClientAuthDataHook",
-+ SSL_GETPID(), s));
-+ return SECFailure;
-+ }
-+
-+ ss->getPlatformClientAuthData = func;
-+ ss->getPlatformClientAuthDataArg = arg;
-+ return SECSuccess;
-+}
-+#endif /* NSS_PLATFORM_CLIENT_AUTH */
-+
- /* NEED LOCKS IN HERE. */
- SECStatus
- SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
-diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index 9dcc29e..94bb9f4 100644
---- a/lib/ssl/sslimpl.h
-+++ b/lib/ssl/sslimpl.h
-@@ -21,6 +21,7 @@
- #include "sslerr.h"
- #include "ssl3prot.h"
- #include "hasht.h"
-+#include "keythi.h"
- #include "nssilock.h"
- #include "pkcs11t.h"
- #if defined(XP_UNIX) || defined(XP_BEOS)
-@@ -32,6 +33,15 @@
-
- #include "sslt.h" /* for some formerly private types, now public */
-
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+#if defined(XP_WIN32)
-+#include <windows.h>
-+#include <wincrypt.h>
-+#elif defined(XP_MACOSX)
-+#include <Security/Security.h>
-+#endif
-+#endif
-+
- /* to make some of these old enums public without namespace pollution,
- ** it was necessary to prepend ssl_ to the names.
- ** These #defines preserve compatibility with the old code here in libssl.
-@@ -453,6 +463,14 @@ struct sslGatherStr {
- #define GS_DATA 3
- #define GS_PAD 4
-
-+#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_WIN32)
-+typedef PCERT_KEY_CONTEXT PlatformKey;
-+#elif defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_MACOSX)
-+typedef SecKeyRef PlatformKey;
-+#else
-+typedef void *PlatformKey;
-+#endif
-+
-
-
- /*
-@@ -974,6 +992,10 @@ struct ssl3StateStr {
-
- CERTCertificate * clientCertificate; /* used by client */
- SECKEYPrivateKey * clientPrivateKey; /* used by client */
-+ /* platformClientKey is present even when NSS_PLATFORM_CLIENT_AUTH is not
-+ * defined in order to allow cleaner conditional code.
-+ * At most one of clientPrivateKey and platformClientKey may be set. */
-+ PlatformKey platformClientKey; /* used by client */
- CERTCertificateList *clientCertChain; /* used by client */
- PRBool sendEmptyCert; /* used by client */
-
-@@ -1253,6 +1275,10 @@ const unsigned char * preferredCipher;
- void *authCertificateArg;
- SSLGetClientAuthData getClientAuthData;
- void *getClientAuthDataArg;
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+ SSLGetPlatformClientAuthData getPlatformClientAuthData;
-+ void *getPlatformClientAuthDataArg;
-+#endif /* NSS_PLATFORM_CLIENT_AUTH */
- SSLSNISocketConfig sniSocketConfig;
- void *sniSocketConfigArg;
- SSLBadCertHandler handleBadCert;
-@@ -1896,6 +1922,26 @@ extern SECStatus ssl_InitSessionCacheLocks(PRBool lazyInit);
-
- extern SECStatus ssl_FreeSessionCacheLocks(void);
-
-+/***************** platform client auth ****************/
-+
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+// Releases the platform key.
-+extern void ssl_FreePlatformKey(PlatformKey key);
-+
-+// Implement the client CertificateVerify message for SSL3/TLS1.0
-+extern SECStatus ssl3_PlatformSignHashes(SSL3Hashes *hash,
-+ PlatformKey key, SECItem *buf,
-+ PRBool isTLS, KeyType keyType);
-+
-+// Converts a CERTCertList* (A collection of CERTCertificates) into a
-+// CERTCertificateList* (A collection of SECItems), or returns NULL if
-+// it cannot be converted.
-+// This is to allow the platform-supplied chain to be created with purely
-+// public API functions, using the preferred CERTCertList mutators, rather
-+// pushing this hack to clients.
-+extern CERTCertificateList* hack_NewCertificateListFromCertList(
-+ CERTCertList* list);
-+#endif /* NSS_PLATFORM_CLIENT_AUTH */
-
- /**************** DTLS-specific functions **************/
- extern void dtls_FreeQueuedMessage(DTLSQueuedMessage *msg);
-diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index f735009..21754d6 100644
---- a/lib/ssl/sslsock.c
-+++ b/lib/ssl/sslsock.c
-@@ -300,6 +300,10 @@ ssl_DupSocket(sslSocket *os)
- ss->authCertificateArg = os->authCertificateArg;
- ss->getClientAuthData = os->getClientAuthData;
- ss->getClientAuthDataArg = os->getClientAuthDataArg;
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+ ss->getPlatformClientAuthData = os->getPlatformClientAuthData;
-+ ss->getPlatformClientAuthDataArg = os->getPlatformClientAuthDataArg;
-+#endif
- ss->sniSocketConfig = os->sniSocketConfig;
- ss->sniSocketConfigArg = os->sniSocketConfigArg;
- ss->handleBadCert = os->handleBadCert;
-@@ -1963,6 +1967,12 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
- ss->getClientAuthData = sm->getClientAuthData;
- if (sm->getClientAuthDataArg)
- ss->getClientAuthDataArg = sm->getClientAuthDataArg;
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+ if (sm->getPlatformClientAuthData)
-+ ss->getPlatformClientAuthData = sm->getPlatformClientAuthData;
-+ if (sm->getPlatformClientAuthDataArg)
-+ ss->getPlatformClientAuthDataArg = sm->getPlatformClientAuthDataArg;
-+#endif
- if (sm->sniSocketConfig)
- ss->sniSocketConfig = sm->sniSocketConfig;
- if (sm->sniSocketConfigArg)
-@@ -3232,6 +3242,10 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
- ss->sniSocketConfig = NULL;
- ss->sniSocketConfigArg = NULL;
- ss->getClientAuthData = NULL;
-+#ifdef NSS_PLATFORM_CLIENT_AUTH
-+ ss->getPlatformClientAuthData = NULL;
-+ ss->getPlatformClientAuthDataArg = NULL;
-+#endif /* NSS_PLATFORM_CLIENT_AUTH */
- ss->handleBadCert = NULL;
- ss->badCertArg = NULL;
- ss->pkcs11PinArg = NULL;
diff --git a/chromium/net/third_party/nss/patches/didhandshakeresume.patch b/chromium/net/third_party/nss/patches/didhandshakeresume.patch
index bceeae1d8e6..8acb6e718ad 100644
--- a/chromium/net/third_party/nss/patches/didhandshakeresume.patch
+++ b/chromium/net/third_party/nss/patches/didhandshakeresume.patch
@@ -1,8 +1,8 @@
diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index 48fa018..0983b5f 100644
+index 3974ee8..e905aab 100644
--- a/lib/ssl/ssl.h
+++ b/lib/ssl/ssl.h
-@@ -1117,6 +1117,9 @@ SSL_IMPORT SECStatus SSL_HandshakeNegotiatedExtension(PRFileDesc * socket,
+@@ -1123,6 +1123,9 @@ SSL_IMPORT SECStatus SSL_HandshakeNegotiatedExtension(PRFileDesc *socket,
SSLExtensionType extId,
PRBool *yes);
@@ -13,21 +13,22 @@ index 48fa018..0983b5f 100644
** How long should we wait before retransmitting the next flight of
** the DTLS handshake? Returns SECFailure if not DTLS or not in a
diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index 21754d6..b73f8f6 100644
+index cc15406..601df2a 100644
--- a/lib/ssl/sslsock.c
+++ b/lib/ssl/sslsock.c
-@@ -2151,6 +2151,20 @@ SSL_PeerStapledOCSPResponses(PRFileDesc *fd)
+@@ -2481,6 +2481,21 @@ SSL_PeerStapledOCSPResponses(PRFileDesc *fd)
return &ss->sec.ci.sid->peerCertStatus;
}
+SECStatus
-+SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed) {
++SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed)
++{
+ sslSocket *ss = ssl_FindSocket(fd);
+
+ if (!ss) {
-+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_HandshakeResumedSession",
-+ SSL_GETPID(), fd));
-+ return SECFailure;
++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_HandshakeResumedSession",
++ SSL_GETPID(), fd));
++ return SECFailure;
+ }
+
+ *handshake_resumed = ss->ssl3.hs.isResuming;
diff --git a/chromium/net/third_party/nss/patches/getrequestedclientcerttypes.patch b/chromium/net/third_party/nss/patches/getrequestedclientcerttypes.patch
index e58cb58a612..d19c2280bf5 100644
--- a/chromium/net/third_party/nss/patches/getrequestedclientcerttypes.patch
+++ b/chromium/net/third_party/nss/patches/getrequestedclientcerttypes.patch
@@ -1,8 +1,8 @@
diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index 0983b5f..cf9f6db 100644
+index e905aab..9e57220 100644
--- a/lib/ssl/ssl.h
+++ b/lib/ssl/ssl.h
-@@ -896,6 +896,16 @@ SSL_IMPORT SECStatus SSL_ReHandshakeWithTimeout(PRFileDesc *fd,
+@@ -896,6 +896,17 @@ SSL_IMPORT SECStatus SSL_ReHandshakeWithTimeout(PRFileDesc *fd,
PRBool flushCache,
PRIntervalTime timeout);
@@ -16,76 +16,78 @@ index 0983b5f..cf9f6db 100644
+*/
+SSL_IMPORT const SECItem *
+SSL_GetRequestedClientCertificateTypes(PRFileDesc *fd);
-
- #ifdef SSL_DEPRECATED_FUNCTION
++
+ #ifdef SSL_DEPRECATED_FUNCTION
/* deprecated!
+ ** For the server, request a new handshake. For the client, begin a new
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index cc193cd..27038f3 100644
+index b8d4784..784f59b 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
-@@ -7266,6 +7266,9 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+@@ -7674,6 +7674,9 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
if (rv != SECSuccess)
- goto loser; /* malformed, alert has been sent */
+ goto loser; /* malformed, alert has been sent */
+ PORT_Assert(!ss->requestedCertTypes);
+ ss->requestedCertTypes = &cert_types;
+
if (isTLS12) {
- rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &b, &length);
- if (rv != SECSuccess)
-@@ -7469,6 +7472,7 @@ loser:
+ rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &b, &length);
+ if (rv != SECSuccess)
+@@ -7723,6 +7726,7 @@ loser:
PORT_SetError(errCode);
rv = SECFailure;
done:
+ ss->requestedCertTypes = NULL;
if (arena != NULL)
- PORT_FreeArena(arena, PR_FALSE);
- #ifdef NSS_PLATFORM_CLIENT_AUTH
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index 94bb9f4..c7231a7 100644
+index 10361a0..5f0e6c9 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
-@@ -1265,6 +1265,10 @@ struct sslSocketStr {
- unsigned int sizeCipherSpecs;
- const unsigned char * preferredCipher;
+@@ -1296,6 +1296,10 @@ struct sslSocketStr {
+ unsigned int sizeCipherSpecs;
+ const unsigned char *preferredCipher;
+ /* TLS ClientCertificateTypes requested during HandleCertificateRequest. */
+ /* Will be NULL at all other times. */
-+ const SECItem *requestedCertTypes;
++ const SECItem *requestedCertTypes;
+
- ssl3KeyPair * stepDownKeyPair; /* RSA step down keys */
+ ssl3KeyPair *stepDownKeyPair; /* RSA step down keys */
- const ssl3DHParams *dheParams; /* DHE param */
+ const ssl3DHParams *dheParams; /* DHE param */
diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index b73f8f6..11e66f2 100644
+index 601df2a..7f97b14 100644
--- a/lib/ssl/sslsock.c
+++ b/lib/ssl/sslsock.c
-@@ -2165,6 +2165,20 @@ SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed) {
+@@ -2496,6 +2496,21 @@ SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed)
return SECSuccess;
}
+const SECItem *
+SSL_GetRequestedClientCertificateTypes(PRFileDesc *fd)
+{
-+ sslSocket *ss = ssl_FindSocket(fd);
++ sslSocket *ss = ssl_FindSocket(fd);
+
-+ if (!ss) {
-+ SSL_DBG(("%d: SSL[%d]: bad socket in "
-+ "SSL_GetRequestedClientCertificateTypes", SSL_GETPID(), fd));
-+ return NULL;
-+ }
++ if (!ss) {
++ SSL_DBG(("%d: SSL[%d]: bad socket in "
++ "SSL_GetRequestedClientCertificateTypes",
++ SSL_GETPID(), fd));
++ return NULL;
++ }
+
-+ return ss->requestedCertTypes;
++ return ss->requestedCertTypes;
+}
+
/************************************************************************/
/* The following functions are the TOP LEVEL SSL functions.
** They all get called through the NSPRIOMethods table below.
-@@ -3243,6 +3257,7 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
- sc->serverKeyBits = 0;
+@@ -3610,6 +3625,7 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
+ sc->serverKeyBits = 0;
ss->certStatusArray[i] = NULL;
}
+ ss->requestedCertTypes = NULL;
- ss->stepDownKeyPair = NULL;
+ ss->stepDownKeyPair = NULL;
ss->dheParams = NULL;
diff --git a/chromium/net/third_party/nss/patches/nobypass.patch b/chromium/net/third_party/nss/patches/nobypass.patch
new file mode 100644
index 00000000000..8896d36e159
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/nobypass.patch
@@ -0,0 +1,20 @@
+diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
+index 7649abe..b6f4987 100644
+--- a/lib/ssl/ssl3con.c
++++ b/lib/ssl/ssl3con.c
+@@ -2297,6 +2297,7 @@ fail:
+ return SECFailure;
+ }
+
++#ifndef NO_PKCS11_BYPASS
+ /* Returns whether we can bypass PKCS#11 for a given cipher algorithm.
+ *
+ * We do not support PKCS#11 bypass for ChaCha20/Poly1305.
+@@ -2311,6 +2312,7 @@ ssl3_CanBypassCipher(SSLCipherAlgorithm calg)
+ return PR_TRUE;
+ }
+ }
++#endif
+
+ /* Complete the initialization of all keys, ciphers, MACs and their contexts
+ * for the pending Cipher Spec.
diff --git a/chromium/net/third_party/nss/patches/nssrwlock.patch b/chromium/net/third_party/nss/patches/nssrwlock.patch
deleted file mode 100644
index ed0e9109ef4..00000000000
--- a/chromium/net/third_party/nss/patches/nssrwlock.patch
+++ /dev/null
@@ -1,238 +0,0 @@
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index afab931..e5e620f 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -5436,7 +5436,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- * the lock across the calls to ssl3_CallHelloExtensionSenders.
- */
- if (sid->u.ssl3.lock) {
-- PR_RWLock_Rlock(sid->u.ssl3.lock);
-+ NSSRWLock_LockRead(sid->u.ssl3.lock);
- }
-
- if (isTLS || (ss->firstHsDone && ss->peerRequestedProtection)) {
-@@ -5445,7 +5445,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
-
- extLen = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, maxBytes, NULL);
- if (extLen < 0) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return SECFailure;
- }
- total_exten_len += extLen;
-@@ -5472,7 +5472,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- /* how many suites are permitted by policy and user preference? */
- num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE);
- if (!num_suites) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return SECFailure; /* count_cipher_suites has set error code. */
- }
-
-@@ -5517,7 +5517,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
-
- rv = ssl3_AppendHandshakeHeader(ss, client_hello, length);
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
-
-@@ -5536,21 +5536,21 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- rv = ssl3_AppendHandshakeNumber(ss, ss->clientHelloVersion, 2);
- }
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
-
- if (!resending) { /* Don't re-generate if we are in DTLS re-sending mode */
- rv = ssl3_GetNewRandom(&ss->ssl3.hs.client_random);
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by GetNewRandom. */
- }
- }
- rv = ssl3_AppendHandshake(ss, &ss->ssl3.hs.client_random,
- SSL3_RANDOM_LENGTH);
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
-
-@@ -5560,7 +5560,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- else
- rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
-
-@@ -5568,14 +5568,14 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- rv = ssl3_AppendHandshakeVariable(
- ss, ss->ssl3.hs.cookie, ss->ssl3.hs.cookieLen, 1);
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
- }
-
- rv = ssl3_AppendHandshakeNumber(ss, num_suites*sizeof(ssl3CipherSuite), 2);
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
-
-@@ -5584,7 +5584,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- rv = ssl3_AppendHandshakeNumber(ss, TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
- sizeof(ssl3CipherSuite));
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
- actual_count++;
-@@ -5593,7 +5593,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV,
- sizeof(ssl3CipherSuite));
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
- actual_count++;
-@@ -5603,7 +5603,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- if (config_match(suite, ss->ssl3.policy, PR_TRUE, &ss->vrange, ss)) {
- actual_count++;
- if (actual_count > num_suites) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- /* set error card removal/insertion error */
- PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
- return SECFailure;
-@@ -5611,7 +5611,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- rv = ssl3_AppendHandshakeNumber(ss, suite->cipher_suite,
- sizeof(ssl3CipherSuite));
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
- }
-@@ -5622,14 +5622,14 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- * the server.. */
- if (actual_count != num_suites) {
- /* Card removal/insertion error */
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
- return SECFailure;
- }
-
- rv = ssl3_AppendHandshakeNumber(ss, numCompressionMethods, 1);
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
- for (i = 0; i < compressionMethodsCount; i++) {
-@@ -5637,7 +5637,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- continue;
- rv = ssl3_AppendHandshakeNumber(ss, compressions[i], 1);
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
- }
-@@ -5648,20 +5648,20 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
-
- rv = ssl3_AppendHandshakeNumber(ss, maxBytes, 2);
- if (rv != SECSuccess) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by AppendHandshake. */
- }
-
- extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, maxBytes, NULL);
- if (extLen < 0) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return SECFailure;
- }
- maxBytes -= extLen;
-
- extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
- if (extLen < 0) {
-- if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
-+ if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return SECFailure;
- }
- maxBytes -= extLen;
-@@ -5670,7 +5670,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
- }
-
- if (sid->u.ssl3.lock) {
-- PR_RWLock_Unlock(sid->u.ssl3.lock);
-+ NSSRWLock_UnlockRead(sid->u.ssl3.lock);
- }
-
- if (ss->xtnData.sentSessionTicketInClientHello) {
-diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index 3403091..874e59c 100644
---- a/lib/ssl/sslimpl.h
-+++ b/lib/ssl/sslimpl.h
-@@ -742,7 +742,7 @@ struct sslSessionIDStr {
- * cached. Before then, there is no need to lock anything because
- * the sid isn't being shared by anything.
- */
-- PRRWLock *lock;
-+ NSSRWLock *lock;
-
- /* The lock must be held while reading or writing these members
- * because they change while the sid is cached.
-diff --git a/lib/ssl/sslnonce.c b/lib/ssl/sslnonce.c
-index cefdda6..28ad364 100644
---- a/lib/ssl/sslnonce.c
-+++ b/lib/ssl/sslnonce.c
-@@ -136,7 +136,7 @@ ssl_DestroySID(sslSessionID *sid)
- }
-
- if (sid->u.ssl3.lock) {
-- PR_DestroyRWLock(sid->u.ssl3.lock);
-+ NSSRWLock_Destroy(sid->u.ssl3.lock);
- }
- }
-
-@@ -308,7 +308,7 @@ CacheSID(sslSessionID *sid)
- PRINT_BUF(8, (0, "sessionID:",
- sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength));
-
-- sid->u.ssl3.lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, NULL);
-+ sid->u.ssl3.lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL);
- if (!sid->u.ssl3.lock) {
- return;
- }
-@@ -450,7 +450,7 @@ ssl3_SetSIDSessionTicket(sslSessionID *sid,
- * yet, so no locking is needed.
- */
- if (sid->u.ssl3.lock) {
-- PR_RWLock_Wlock(sid->u.ssl3.lock);
-+ NSSRWLock_LockWrite(sid->u.ssl3.lock);
- if (sid->u.ssl3.locked.sessionTicket.ticket.data) {
- SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket,
- PR_FALSE);
-@@ -465,6 +465,6 @@ ssl3_SetSIDSessionTicket(sslSessionID *sid,
- newSessionTicket->ticket.len = 0;
-
- if (sid->u.ssl3.lock) {
-- PR_RWLock_Unlock(sid->u.ssl3.lock);
-+ NSSRWLock_UnlockWrite(sid->u.ssl3.lock);
- }
- }
diff --git a/chromium/net/third_party/nss/patches/reorderextensions.patch b/chromium/net/third_party/nss/patches/reorderextensions.patch
index c522822506e..0779e6971ac 100644
--- a/chromium/net/third_party/nss/patches/reorderextensions.patch
+++ b/chromium/net/third_party/nss/patches/reorderextensions.patch
@@ -1,19 +1,24 @@
diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c
-index 9cfd541..eb3fb70 100644
+index 2ffe77b..3b48c9e 100644
--- a/lib/ssl/ssl3ext.c
+++ b/lib/ssl/ssl3ext.c
-@@ -321,6 +321,10 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
- { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
- { ssl_signed_certificate_timestamp_xtn,
- &ssl3_ClientSendSignedCertTimestampXtn },
-+ /* WebSphere Application Server 7.0 is intolerant to the last extension
-+ * being zero-length. It is not intolerant of TLS 1.2, so ensure that
-+ * signature_algorithms is at the end to guarantee a non-empty
-+ * extension. */
- { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
- { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
- { ssl_extended_master_secret_xtn, &ssl3_SendExtendedMasterSecretXtn},
-@@ -2546,9 +2550,11 @@ ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength)
+@@ -336,10 +336,14 @@ static const ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS]
+ { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn },
+ { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
+- { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
+ { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
+ { ssl_signed_cert_timestamp_xtn, &ssl3_ClientSendSignedCertTimestampXtn },
+ { ssl_tls13_key_share_xtn, &tls13_ClientSendKeyShareXtn },
++ /* Some servers (e.g. WebSphere Application Server 7.0 and Tomcat) will
++ * time out or terminate the connection if the last extension in the
++ * client hello is empty. They are not intolerant of TLS 1.2, so list
++ * signature_algorithms at the end. See bug 1243641. */
++ { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
+ /* any extra entries will appear as { 0, NULL } */
+ };
+
+@@ -2690,9 +2694,11 @@ ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength)
}
extensionLength = 512 - recordLength;
diff --git a/chromium/net/third_party/nss/patches/restartclientauth.patch b/chromium/net/third_party/nss/patches/restartclientauth.patch
index 6e3a0b9ed9b..811e98c8049 100644
--- a/chromium/net/third_party/nss/patches/restartclientauth.patch
+++ b/chromium/net/third_party/nss/patches/restartclientauth.patch
@@ -1,24 +1,24 @@
diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index cf9f6db..85ced8a 100644
+index 9e57220..aa4a3e5 100644
--- a/lib/ssl/ssl.h
+++ b/lib/ssl/ssl.h
-@@ -502,6 +502,11 @@ SSL_IMPORT SECStatus SSL_ForceHandshake(PRFileDesc *fd);
+@@ -516,6 +516,11 @@ SSL_IMPORT SECStatus SSL_ForceHandshake(PRFileDesc *fd);
SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd,
PRIntervalTime timeout);
+SSL_IMPORT SECStatus SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd,
-+ CERTCertificate *cert,
-+ SECKEYPrivateKey *key,
-+ CERTCertificateList *certChain);
++ CERTCertificate *cert,
++ SECKEYPrivateKey *key,
++ CERTCertificateList *certChain);
+
/*
** Query security status of socket. *on is set to one if security is
** enabled. *keySize will contain the stream key size used. *issuer will
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 27038f3..304e03b 100644
+index 784f59b..2a2e644 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
-@@ -7482,6 +7482,85 @@ done:
+@@ -7803,6 +7803,85 @@ ssl3_CompleteHandleCertificateRequest(sslSocket *ss, SECItem *algorithms,
return rv;
}
@@ -50,21 +50,21 @@ index 27038f3..304e03b 100644
+ * Caller holds 1stHandshakeLock.
+ */
+SECStatus
-+ssl3_RestartHandshakeAfterCertReq(sslSocket * ss,
-+ CERTCertificate * cert,
-+ SECKEYPrivateKey * key,
-+ CERTCertificateList *certChain)
++ssl3_RestartHandshakeAfterCertReq(sslSocket *ss,
++ CERTCertificate *cert,
++ SECKEYPrivateKey *key,
++ CERTCertificateList *certChain)
+{
-+ SECStatus rv = SECSuccess;
++ SECStatus rv = SECSuccess;
+
+ /* XXX This code only works on the initial handshake on a connection,
+ ** XXX It does not work on a subsequent handshake (redo).
+ */
+ if (ss->handshake != 0) {
-+ ss->handshake = ssl_GatherRecord1stHandshake;
-+ ss->ssl3.clientCertificate = cert;
-+ ss->ssl3.clientPrivateKey = key;
-+ ss->ssl3.clientCertChain = certChain;
++ ss->handshake = ssl_GatherRecord1stHandshake;
++ ss->ssl3.clientCertificate = cert;
++ ss->ssl3.clientPrivateKey = key;
++ ss->ssl3.clientCertChain = certChain;
+ if (!cert || !key || !certChain) {
+ /* we are missing the key, cert, or cert chain */
+ if (ss->ssl3.clientCertificate) {
@@ -84,19 +84,19 @@ index 27038f3..304e03b 100644
+ } else {
+ (void)SSL3_SendAlert(ss, alert_warning, no_certificate);
+ }
-+ }
++ }
+ } else {
-+ if (cert) {
-+ CERT_DestroyCertificate(cert);
-+ }
-+ if (key) {
-+ SECKEY_DestroyPrivateKey(key);
-+ }
-+ if (certChain) {
-+ CERT_DestroyCertificateList(certChain);
-+ }
-+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-+ rv = SECFailure;
++ if (cert) {
++ CERT_DestroyCertificate(cert);
++ }
++ if (key) {
++ SECKEY_DestroyPrivateKey(key);
++ }
++ if (certChain) {
++ CERT_DestroyCertificateList(certChain);
++ }
++ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++ rv = SECFailure;
+ }
+ return rv;
+}
@@ -105,41 +105,43 @@ index 27038f3..304e03b 100644
ssl3_CheckFalseStart(sslSocket *ss)
{
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index c7231a7..c089889 100644
+index 5f0e6c9..dad75b2 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
-@@ -1629,16 +1629,17 @@ extern SECStatus ssl3_MasterSecretDeriveBypass( ssl3CipherSpec * pwSpec,
+@@ -1702,16 +1702,16 @@ extern SECStatus ssl3_MasterSecretDeriveBypass(ssl3CipherSpec *pwSpec,
/* These functions are called from secnav, even though they're "private". */
extern int ssl2_SendErrorMessage(struct sslSocketStr *ss, int error);
-extern int SSL_RestartHandshakeAfterCertReq(struct sslSocketStr *ss,
-- CERTCertificate *cert,
-- SECKEYPrivateKey *key,
-- CERTCertificateList *certChain);
+- CERTCertificate *cert,
+- SECKEYPrivateKey *key,
+- CERTCertificateList *certChain);
extern sslSocket *ssl_FindSocket(PRFileDesc *fd);
extern void ssl_FreeSocket(struct sslSocketStr *ssl);
extern SECStatus SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level,
- SSL3AlertDescription desc);
+ SSL3AlertDescription desc);
extern SECStatus ssl3_DecodeError(sslSocket *ss);
-+extern SECStatus ssl3_RestartHandshakeAfterCertReq(sslSocket * ss,
-+ CERTCertificate * cert,
-+ SECKEYPrivateKey * key,
-+ CERTCertificateList *certChain);
-+
++extern SECStatus ssl3_RestartHandshakeAfterCertReq(struct sslSocketStr *ss,
++ CERTCertificate *cert,
++ SECKEYPrivateKey *key,
++ CERTCertificateList *certChain);
extern SECStatus ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error);
/*
diff --git a/lib/ssl/sslsecur.c b/lib/ssl/sslsecur.c
-index 53b4885..f77d6fa 100644
+index 5773748..a087ffc 100644
--- a/lib/ssl/sslsecur.c
+++ b/lib/ssl/sslsecur.c
-@@ -1532,17 +1532,70 @@ SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle)
+@@ -1535,17 +1535,70 @@ SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle)
return SECSuccess;
}
-/* DO NOT USE. This function was exported in ssl.def with the wrong signature;
- * this implementation exists to maintain link-time compatibility.
+- */
+-int
+-SSL_RestartHandshakeAfterCertReq(sslSocket *ss,
+/*
+ * attempt to restart the handshake after asynchronously handling
+ * a request for the client's certificate.
@@ -165,48 +167,46 @@ index 53b4885..f77d6fa 100644
+ *
+ * XXX This code only works on the initial handshake on a connection, XXX
+ * It does not work on a subsequent handshake (redo).
- */
--int
--SSL_RestartHandshakeAfterCertReq(sslSocket * ss,
++ */
+SECStatus
-+SSL_RestartHandshakeAfterCertReq(PRFileDesc * fd,
- CERTCertificate * cert,
- SECKEYPrivateKey * key,
- CERTCertificateList *certChain)
++SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd,
+ CERTCertificate *cert,
+ SECKEYPrivateKey *key,
+ CERTCertificateList *certChain)
{
- PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
- return -1;
-+ sslSocket * ss = ssl_FindSocket(fd);
-+ SECStatus ret;
++ sslSocket *ss = ssl_FindSocket(fd);
++ SECStatus ret;
+
+ if (!ss) {
-+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RestartHandshakeAfterCertReq",
-+ SSL_GETPID(), fd));
-+ if (cert) {
-+ CERT_DestroyCertificate(cert);
-+ }
-+ if (key) {
-+ SECKEY_DestroyPrivateKey(key);
-+ }
-+ if (certChain) {
-+ CERT_DestroyCertificateList(certChain);
-+ }
-+ return SECFailure;
++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RestartHandshakeAfterCertReq",
++ SSL_GETPID(), fd));
++ if (cert) {
++ CERT_DestroyCertificate(cert);
++ }
++ if (key) {
++ SECKEY_DestroyPrivateKey(key);
++ }
++ if (certChain) {
++ CERT_DestroyCertificateList(certChain);
++ }
++ return SECFailure;
+ }
+
-+ ssl_Get1stHandshakeLock(ss); /************************************/
++ ssl_Get1stHandshakeLock(ss); /************************************/
+
+ if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
-+ ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain);
++ ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain);
+ } else {
-+ if (certChain != NULL) {
-+ CERT_DestroyCertificateList(certChain);
-+ }
-+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-+ ret = SECFailure;
++ if (certChain != NULL) {
++ CERT_DestroyCertificateList(certChain);
++ }
++ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
++ ret = SECFailure;
+ }
+
-+ ssl_Release1stHandshakeLock(ss); /************************************/
++ ssl_Release1stHandshakeLock(ss); /************************************/
+ return ret;
}
diff --git a/chromium/net/third_party/nss/patches/secitemarray.patch b/chromium/net/third_party/nss/patches/secitemarray.patch
deleted file mode 100644
index d40e7ca3407..00000000000
--- a/chromium/net/third_party/nss/patches/secitemarray.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index 976330e..60dd243 100644
---- a/lib/ssl/sslimpl.h
-+++ b/lib/ssl/sslimpl.h
-@@ -1403,6 +1403,15 @@ extern sslSessionIDUncacheFunc ssl_sid_uncache;
-
- SEC_BEGIN_PROTOS
-
-+/* Functions for handling SECItemArrays, added in NSS 3.15 */
-+extern SECItemArray *SECITEM_AllocArray(PLArenaPool *arena,
-+ SECItemArray *array,
-+ unsigned int len);
-+extern SECItemArray *SECITEM_DupArray(PLArenaPool *arena,
-+ const SECItemArray *from);
-+extern void SECITEM_FreeArray(SECItemArray *array, PRBool freeit);
-+extern void SECITEM_ZfreeArray(SECItemArray *array, PRBool freeit);
-+
- /* Internal initialization and installation of the SSL error tables */
- extern SECStatus ssl_Init(void);
- extern SECStatus ssl_InitializePRErrorTable(void);
-diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h
-index b6616e2..5593579 100644
---- a/lib/ssl/sslt.h
-+++ b/lib/ssl/sslt.h
-@@ -11,6 +11,19 @@
-
- #include "prtypes.h"
-
-+/* SECItemArray is added in NSS 3.15. Define the type if compiling
-+** against an older version of NSS.
-+*/
-+#include "nssutil.h"
-+#if NSSUTIL_VMAJOR == 3 && NSSUTIL_VMINOR < 15
-+typedef struct SECItemArrayStr SECItemArray;
-+
-+struct SECItemArrayStr {
-+ SECItem *items;
-+ unsigned int len;
-+};
-+#endif /* NSSUTIL_VMAJOR == 3 && NSSUTIL_VMINOR < 15 */
-+
- typedef struct SSL3StatisticsStr {
- /* statistics from ssl3_SendClientHello (sch) */
- long sch_sid_cache_hits;
diff --git a/chromium/net/third_party/nss/patches/secretexporterlocks.patch b/chromium/net/third_party/nss/patches/secretexporterlocks.patch
index 232b93237fb..a95ef278d0e 100644
--- a/chromium/net/third_party/nss/patches/secretexporterlocks.patch
+++ b/chromium/net/third_party/nss/patches/secretexporterlocks.patch
@@ -1,41 +1,32 @@
diff --git a/lib/ssl/sslinfo.c b/lib/ssl/sslinfo.c
-index 216ab0f..7048eb8 100644
+index 527b1a4..c59879c 100644
--- a/lib/ssl/sslinfo.c
+++ b/lib/ssl/sslinfo.c
-@@ -387,8 +387,13 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd,
- return SECFailure;
+@@ -406,8 +406,13 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd,
+ return SECFailure;
}
+ ssl_GetRecvBufLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+
if (ss->version < SSL_LIBRARY_VERSION_3_1_TLS) {
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION);
-+ ssl_ReleaseSSL3HandshakeLock(ss);
-+ ssl_ReleaseRecvBufLock(ss);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION);
++ ssl_ReleaseSSL3HandshakeLock(ss);
++ ssl_ReleaseRecvBufLock(ss);
+ return SECFailure;
}
-@@ -399,13 +404,17 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd,
+@@ -418,6 +423,8 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd,
}
val = PORT_Alloc(valLen);
if (!val) {
-+ ssl_ReleaseSSL3HandshakeLock(ss);
-+ ssl_ReleaseRecvBufLock(ss);
- return SECFailure;
++ ssl_ReleaseSSL3HandshakeLock(ss);
++ ssl_ReleaseRecvBufLock(ss);
+ return SECFailure;
}
i = 0;
-+
- PORT_Memcpy(val + i, &ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
- i += SSL3_RANDOM_LENGTH;
- PORT_Memcpy(val + i, &ss->ssl3.hs.server_random.rand, SSL3_RANDOM_LENGTH);
- i += SSL3_RANDOM_LENGTH;
-+
- if (hasContext) {
- val[i++] = contextLen >> 8;
- val[i++] = contextLen;
-@@ -426,6 +435,8 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd,
- valLen, out, outLen);
+@@ -445,6 +452,8 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd,
+ valLen, out, outLen);
}
ssl_ReleaseSpecReadLock(ss);
+ ssl_ReleaseSSL3HandshakeLock(ss);
diff --git a/chromium/net/third_party/nss/patches/sessioncache.patch b/chromium/net/third_party/nss/patches/sessioncache.patch
index 07e762fc02a..6e100c6f956 100644
--- a/chromium/net/third_party/nss/patches/sessioncache.patch
+++ b/chromium/net/third_party/nss/patches/sessioncache.patch
@@ -1,8 +1,8 @@
diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index 437a822..bc417a5 100644
+index 70665a1..de5078b 100644
--- a/lib/ssl/ssl.h
+++ b/lib/ssl/ssl.h
-@@ -992,6 +992,18 @@ SSL_IMPORT int SSL_DataPending(PRFileDesc *fd);
+@@ -973,6 +973,18 @@ SSL_IMPORT int SSL_DataPending(PRFileDesc *fd);
SSL_IMPORT SECStatus SSL_InvalidateSession(PRFileDesc *fd);
/*
@@ -22,23 +22,23 @@ index 437a822..bc417a5 100644
*/
SSL_IMPORT SECItem *SSL_GetSessionID(PRFileDesc *fd);
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 572bba9..afab931 100644
+index b100b9b..7649abe 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
-@@ -12058,7 +12058,7 @@ ssl3_FinishHandshake(sslSocket * ss)
+@@ -12397,7 +12397,7 @@ ssl3_FinishHandshake(sslSocket *ss)
ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
}
- if (ss->ssl3.hs.cacheSID) {
+ if (ss->ssl3.hs.cacheSID && ss->sec.isServer) {
- PORT_Assert(ss->sec.ci.sid->cached == never_cached);
- (*ss->sec.cache)(ss->sec.ci.sid);
- ss->ssl3.hs.cacheSID = PR_FALSE;
+ PORT_Assert(ss->sec.ci.sid->cached == never_cached);
+ (*ss->sec.cache)(ss->sec.ci.sid);
+ ss->ssl3.hs.cacheSID = PR_FALSE;
diff --git a/lib/ssl/sslsecur.c b/lib/ssl/sslsecur.c
-index cca55bb..b4b8e95 100644
+index 7ff0a2c..129f1f3 100644
--- a/lib/ssl/sslsecur.c
+++ b/lib/ssl/sslsecur.c
-@@ -1483,6 +1483,49 @@ SSL_InvalidateSession(PRFileDesc *fd)
+@@ -1486,6 +1486,49 @@ SSL_InvalidateSession(PRFileDesc *fd)
return rv;
}
@@ -48,26 +48,26 @@ index cca55bb..b4b8e95 100644
+ PORT_Assert(!ss->sec.isServer);
+
+ if (ss->ssl3.hs.cacheSID) {
-+ ss->sec.cache(ss->sec.ci.sid);
-+ ss->ssl3.hs.cacheSID = PR_FALSE;
++ ss->sec.cache(ss->sec.ci.sid);
++ ss->ssl3.hs.cacheSID = PR_FALSE;
+ }
+}
+
+SECStatus
+SSL_CacheSession(PRFileDesc *fd)
+{
-+ sslSocket * ss = ssl_FindSocket(fd);
-+ SECStatus rv = SECFailure;
++ sslSocket *ss = ssl_FindSocket(fd);
++ SECStatus rv = SECFailure;
+
+ if (ss) {
-+ ssl_Get1stHandshakeLock(ss);
-+ ssl_GetSSL3HandshakeLock(ss);
++ ssl_Get1stHandshakeLock(ss);
++ ssl_GetSSL3HandshakeLock(ss);
+
-+ ssl3_CacheSessionUnlocked(ss);
-+ rv = SECSuccess;
++ ssl3_CacheSessionUnlocked(ss);
++ rv = SECSuccess;
+
-+ ssl_ReleaseSSL3HandshakeLock(ss);
-+ ssl_Release1stHandshakeLock(ss);
++ ssl_ReleaseSSL3HandshakeLock(ss);
++ ssl_Release1stHandshakeLock(ss);
+ }
+ return rv;
+}
@@ -75,12 +75,12 @@ index cca55bb..b4b8e95 100644
+SECStatus
+SSL_CacheSessionUnlocked(PRFileDesc *fd)
+{
-+ sslSocket * ss = ssl_FindSocket(fd);
-+ SECStatus rv = SECFailure;
++ sslSocket *ss = ssl_FindSocket(fd);
++ SECStatus rv = SECFailure;
+
+ if (ss) {
-+ ssl3_CacheSessionUnlocked(ss);
-+ rv = SECSuccess;
++ ssl3_CacheSessionUnlocked(ss);
++ rv = SECSuccess;
+ }
+ return rv;
+}
diff --git a/chromium/net/third_party/nss/patches/signedcertificatetimestamps.patch b/chromium/net/third_party/nss/patches/signedcertificatetimestamps.patch
deleted file mode 100644
index e6af84fcb10..00000000000
--- a/chromium/net/third_party/nss/patches/signedcertificatetimestamps.patch
+++ /dev/null
@@ -1,355 +0,0 @@
-diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index eb7f7ec..db09425 100644
---- a/lib/ssl/ssl.h
-+++ b/lib/ssl/ssl.h
-@@ -203,6 +203,8 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
- */
- #define SSL_ENABLE_EXTENDED_MASTER_SECRET 30
-
-+/* Request Signed Certificate Timestamps via TLS extension (client) */
-+#define SSL_ENABLE_SIGNED_CERT_TIMESTAMPS 31
-
- #ifdef SSL_DEPRECATED_FUNCTION
- /* Old deprecated function names */
-@@ -586,6 +588,23 @@ SSL_IMPORT CERTCertList *SSL_PeerCertificateChain(PRFileDesc *fd);
- */
- SSL_IMPORT const SECItemArray * SSL_PeerStapledOCSPResponses(PRFileDesc *fd);
-
-+/* SSL_PeerSignedCertTimestamps returns the signed_certificate_timestamp
-+ * extension data provided by the TLS server. The return value is a pointer
-+ * to an internal SECItem that contains the returned response (as a serialized
-+ * SignedCertificateTimestampList, see RFC 6962). The returned pointer is only
-+ * valid until the callback function that calls SSL_PeerSignedCertTimestamps
-+ * (e.g. the authenticate certificate hook, or the handshake callback) returns.
-+ *
-+ * If no Signed Certificate Timestamps were given by the server then the result
-+ * will be empty. If there was an error, then the result will be NULL.
-+ *
-+ * You must set the SSL_ENABLE_SIGNED_CERT_TIMESTAMPS option to indicate support
-+ * for Signed Certificate Timestamps to a server.
-+ *
-+ * libssl does not do any parsing or validation of the response itself.
-+ */
-+SSL_IMPORT const SECItem * SSL_PeerSignedCertTimestamps(PRFileDesc *fd);
-+
- /* SSL_SetStapledOCSPResponses stores an array of one or multiple OCSP responses
- * in the fd's data, which may be sent as part of a server side cert_status
- * handshake message. Parameter |responses| is for the server certificate of
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index ba3d012..5c09f25 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -6957,6 +6957,14 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
- sid->u.ssl3.keys.extendedMasterSecretUsed =
- ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn);
-
-+ /* Copy Signed Certificate Timestamps, if any. */
-+ if (ss->xtnData.signedCertTimestamps.data) {
-+ rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.signedCertTimestamps,
-+ &ss->xtnData.signedCertTimestamps);
-+ if (rv != SECSuccess)
-+ goto loser;
-+ }
-+
- ss->ssl3.hs.isResuming = PR_FALSE;
- if (ss->ssl3.hs.kea_def->signKeyType != sign_null) {
- /* All current cipher suites other than those with sign_null (i.e.,
-@@ -6971,6 +6979,10 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
- }
-
- winner:
-+ /* Clean up the temporary pointer to the handshake buffer. */
-+ ss->xtnData.signedCertTimestamps.data = NULL;
-+ ss->xtnData.signedCertTimestamps.len = 0;
-+
- /* If we will need a ChannelID key then we make the callback now. This
- * allows the handshake to be restarted cleanly if the callback returns
- * SECWouldBlock. */
-@@ -6996,6 +7008,9 @@ alert_loser:
- (void)SSL3_SendAlert(ss, alert_fatal, desc);
-
- loser:
-+ /* Clean up the temporary pointer to the handshake buffer. */
-+ ss->xtnData.signedCertTimestamps.data = NULL;
-+ ss->xtnData.signedCertTimestamps.len = 0;
- errCode = ssl_MapLowLevelError(errCode);
- return SECFailure;
- }
-diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c
-index 78825cb..9cfd541 100644
---- a/lib/ssl/ssl3ext.c
-+++ b/lib/ssl/ssl3ext.c
-@@ -90,6 +90,12 @@ static PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append,
- PRUint32 maxBytes);
- static SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
- SECItem *data);
-+static PRInt32 ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss,
-+ PRBool append,
-+ PRUint32 maxBytes);
-+static SECStatus ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss,
-+ PRUint16 ex_type,
-+ SECItem *data);
-
- static PRInt32 ssl3_ClientSendDraftVersionXtn(sslSocket *ss, PRBool append,
- PRUint32 maxBytes);
-@@ -283,6 +289,8 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
- { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
- { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
- { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
-+ { ssl_signed_certificate_timestamp_xtn,
-+ &ssl3_ClientHandleSignedCertTimestampXtn },
- { -1, NULL }
- };
-
-@@ -311,6 +319,8 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
- { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn },
- { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
- { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
-+ { ssl_signed_certificate_timestamp_xtn,
-+ &ssl3_ClientSendSignedCertTimestampXtn },
- { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
- { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
- { ssl_extended_master_secret_xtn, &ssl3_SendExtendedMasterSecretXtn},
-@@ -2698,11 +2708,48 @@ ssl3_SendExtendedMasterSecretXtn(sslSocket * ss, PRBool append,
- }
-
- return extension_length;
--
- loser:
- return -1;
- }
-
-+/* ssl3_ClientSendSignedCertTimestampXtn sends the signed_certificate_timestamp
-+ * extension for TLS ClientHellos. */
-+static PRInt32
-+ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, PRBool append,
-+ PRUint32 maxBytes)
-+{
-+ PRInt32 extension_length = 2 /* extension_type */ +
-+ 2 /* length(extension_data) */;
-+
-+ /* Only send the extension if processing is enabled. */
-+ if (!ss->opt.enableSignedCertTimestamps)
-+ return 0;
-+
-+ if (maxBytes < extension_length) {
-+ PORT_Assert(0);
-+ return 0;
-+ }
-+
-+ if (append) {
-+ SECStatus rv;
-+ /* extension_type */
-+ rv = ssl3_AppendHandshakeNumber(ss,
-+ ssl_signed_certificate_timestamp_xtn,
-+ 2);
-+ if (rv != SECSuccess)
-+ goto loser;
-+ /* zero length */
-+ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-+ if (rv != SECSuccess)
-+ goto loser;
-+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
-+ ssl_signed_certificate_timestamp_xtn;
-+ }
-+
-+ return extension_length;
-+loser:
-+ return -1;
-+}
-
- static SECStatus
- ssl3_HandleExtendedMasterSecretXtn(sslSocket * ss, PRUint16 ex_type,
-@@ -2743,3 +2790,28 @@ ssl3_HandleExtendedMasterSecretXtn(sslSocket * ss, PRUint16 ex_type,
- }
- return SECSuccess;
- }
-+
-+static SECStatus
-+ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type,
-+ SECItem *data)
-+{
-+ /* We do not yet know whether we'll be resuming a session or creating
-+ * a new one, so we keep a pointer to the data in the TLSExtensionData
-+ * structure. This pointer is only valid in the scope of
-+ * ssl3_HandleServerHello, and, if not resuming a session, the data is
-+ * copied once a new session structure has been set up.
-+ * All parsing is currently left to the application and we accept
-+ * everything, including empty data.
-+ */
-+ SECItem *scts = &ss->xtnData.signedCertTimestamps;
-+ PORT_Assert(!scts->data && !scts->len);
-+
-+ if (!data->len) {
-+ /* Empty extension data: RFC 6962 mandates non-empty contents. */
-+ return SECFailure;
-+ }
-+ *scts = *data;
-+ /* Keep track of negotiated extensions. */
-+ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-+ return SECSuccess;
-+}
-diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index d53c446..080debe 100644
---- a/lib/ssl/sslimpl.h
-+++ b/lib/ssl/sslimpl.h
-@@ -349,6 +349,7 @@ typedef struct sslOptionsStr {
- unsigned int enableFallbackSCSV : 1; /* 29 */
- unsigned int enableServerDhe : 1; /* 30 */
- unsigned int enableExtendedMS : 1; /* 31 */
-+ unsigned int enableSignedCertTimestamps : 1; /* 32 */
- } sslOptions;
-
- typedef enum { sslHandshakingUndetermined = 0,
-@@ -732,6 +733,11 @@ struct sslSessionIDStr {
- * resumption handshake to the original handshake. */
- SECItem originalHandshakeHash;
-
-+ /* Signed certificate timestamps received in a TLS extension.
-+ ** (used only in client).
-+ */
-+ SECItem signedCertTimestamps;
-+
- /* This lock is lazily initialized by CacheSID when a sid is first
- * cached. Before then, there is no need to lock anything because
- * the sid isn't being shared by anything.
-@@ -846,6 +852,18 @@ struct TLSExtensionDataStr {
- * is beyond ssl3_HandleClientHello function. */
- SECItem *sniNameArr;
- PRUint32 sniNameArrSize;
-+
-+ /* Signed Certificate Timestamps extracted from the TLS extension.
-+ * (client only).
-+ * This container holds a temporary pointer to the extension data,
-+ * until a session structure (the sec.ci.sid of an sslSocket) is setup
-+ * that can hold a permanent copy of the data
-+ * (in sec.ci.sid.u.ssl3.signedCertTimestamps).
-+ * The data pointed to by this structure is neither explicitly allocated
-+ * nor copied: the pointer points to the handshake message buffer and is
-+ * only valid in the scope of ssl3_HandleServerHello.
-+ */
-+ SECItem signedCertTimestamps;
- };
-
- typedef SECStatus (*sslRestartTarget)(sslSocket *);
-diff --git a/lib/ssl/sslnonce.c b/lib/ssl/sslnonce.c
-index c45849d..cefdda6 100644
---- a/lib/ssl/sslnonce.c
-+++ b/lib/ssl/sslnonce.c
-@@ -131,6 +131,9 @@ ssl_DestroySID(sslSessionID *sid)
- if (sid->u.ssl3.originalHandshakeHash.data) {
- SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE);
- }
-+ if (sid->u.ssl3.signedCertTimestamps.data) {
-+ SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE);
-+ }
-
- if (sid->u.ssl3.lock) {
- PR_DestroyRWLock(sid->u.ssl3.lock);
-diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index 6d700a7..28e3543 100644
---- a/lib/ssl/sslsock.c
-+++ b/lib/ssl/sslsock.c
-@@ -92,7 +92,8 @@ static sslOptions ssl_defaults = {
- PR_TRUE, /* reuseServerECDHEKey */
- PR_FALSE, /* enableFallbackSCSV */
- PR_TRUE, /* enableServerDhe */
-- PR_FALSE /* enableExtendedMS */
-+ PR_FALSE, /* enableExtendedMS */
-+ PR_FALSE, /* enableSignedCertTimestamps */
- };
-
- /*
-@@ -843,6 +844,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
- ss->opt.enableExtendedMS = on;
- break;
-
-+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
-+ ss->opt.enableSignedCertTimestamps = on;
-+ break;
-+
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure;
-@@ -921,6 +926,9 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
- case SSL_ENABLE_SERVER_DHE: on = ss->opt.enableServerDhe; break;
- case SSL_ENABLE_EXTENDED_MASTER_SECRET:
- on = ss->opt.enableExtendedMS; break;
-+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
-+ on = ss->opt.enableSignedCertTimestamps;
-+ break;
-
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
-@@ -996,6 +1004,9 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
- case SSL_ENABLE_EXTENDED_MASTER_SECRET:
- on = ssl_defaults.enableExtendedMS;
- break;
-+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
-+ on = ssl_defaults.enableSignedCertTimestamps;
-+ break;
-
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
-@@ -1187,6 +1198,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
- ssl_defaults.enableExtendedMS = on;
- break;
-
-+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
-+ ssl_defaults.enableSignedCertTimestamps = on;
-+ break;
-+
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
-@@ -2218,6 +2233,29 @@ SSL_PeerStapledOCSPResponses(PRFileDesc *fd)
- return &ss->sec.ci.sid->peerCertStatus;
- }
-
-+const SECItem *
-+SSL_PeerSignedCertTimestamps(PRFileDesc *fd)
-+{
-+ sslSocket *ss = ssl_FindSocket(fd);
-+
-+ if (!ss) {
-+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerSignedCertTimestamps",
-+ SSL_GETPID(), fd));
-+ return NULL;
-+ }
-+
-+ if (!ss->sec.ci.sid) {
-+ PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
-+ return NULL;
-+ }
-+
-+ if (ss->sec.ci.sid->version < SSL_LIBRARY_VERSION_3_0) {
-+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
-+ return NULL;
-+ }
-+ return &ss->sec.ci.sid->u.ssl3.signedCertTimestamps;
-+}
-+
- SECStatus
- SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed) {
- sslSocket *ss = ssl_FindSocket(fd);
-diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h
-index a2eff62..36e34df 100644
---- a/lib/ssl/sslt.h
-+++ b/lib/ssl/sslt.h
-@@ -248,6 +248,7 @@ typedef enum {
- ssl_signature_algorithms_xtn = 13,
- ssl_use_srtp_xtn = 14,
- ssl_app_layer_protocol_xtn = 16,
-+ ssl_signed_certificate_timestamp_xtn = 18, /* RFC 6962 */
- ssl_padding_xtn = 21,
- ssl_extended_master_secret_xtn = 23,
- ssl_session_ticket_xtn = 35,
-@@ -257,7 +258,7 @@ typedef enum {
- ssl_tls13_draft_version_xtn = 0xff02 /* experimental number */
- } SSLExtensionType;
-
--#define SSL_MAX_EXTENSIONS 13 /* doesn't include ssl_padding_xtn. */
-+#define SSL_MAX_EXTENSIONS 14 /* doesn't include ssl_padding_xtn. */
-
- typedef enum {
- ssl_dhe_group_none = 0,
diff --git a/chromium/net/third_party/nss/patches/suitebonly.patch b/chromium/net/third_party/nss/patches/suitebonly.patch
deleted file mode 100644
index 32f0f7e25e2..00000000000
--- a/chromium/net/third_party/nss/patches/suitebonly.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/lib/ssl/ssl3ecc.c b/lib/ssl/ssl3ecc.c
-index 94008a0..6d89bbe 100644
---- a/lib/ssl/ssl3ecc.c
-+++ b/lib/ssl/ssl3ecc.c
-@@ -1093,6 +1093,7 @@ static const PRUint8 ecPtFmt[6] = {
- static PRBool
- ssl3_SuiteBOnly(sslSocket *ss)
- {
-+#if 0
- /* See if we can support small curves (like 163). If not, assume we can
- * only support Suite-B curves (P-256, P-384, P-521). */
- PK11SlotInfo *slot =
-@@ -1106,6 +1107,9 @@ ssl3_SuiteBOnly(sslSocket *ss)
- /* we can, presume we can do all curves */
- PK11_FreeSlot(slot);
- return PR_FALSE;
-+#else
-+ return PR_TRUE;
-+#endif
- }
-
- /* Send our "canned" (precompiled) Supported Elliptic Curves extension,
diff --git a/chromium/net/third_party/nss/patches/tls12chromium.patch b/chromium/net/third_party/nss/patches/tls12chromium.patch
deleted file mode 100644
index b6e168b53cc..00000000000
--- a/chromium/net/third_party/nss/patches/tls12chromium.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index ce92cf1..c5cb1eb 100644
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -33,6 +33,15 @@
- #include "blapi.h"
- #endif
-
-+/* This is a bodge to allow this code to be compiled against older NSS headers
-+ * that don't contain the TLS 1.2 changes. */
-+#ifndef CKM_NSS_TLS_PRF_GENERAL_SHA256
-+#define CKM_NSS_TLS_PRF_GENERAL_SHA256 (CKM_NSS + 21)
-+#define CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256 (CKM_NSS + 22)
-+#define CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256 (CKM_NSS + 23)
-+#define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24)
-+#endif
-+
- #include <stdio.h>
- #ifdef NSS_ENABLE_ZLIB
- #include "zlib.h"
-diff --git a/lib/ssl/ssl3ecc.c b/lib/ssl/ssl3ecc.c
-index 6d89bbe..cf8e741 100644
---- a/lib/ssl/ssl3ecc.c
-+++ b/lib/ssl/ssl3ecc.c
-@@ -31,6 +31,12 @@
-
- #include <stdio.h>
-
-+/* This is a bodge to allow this code to be compiled against older NSS headers
-+ * that don't contain the TLS 1.2 changes. */
-+#ifndef CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256
-+#define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24)
-+#endif
-+
- #ifndef NSS_DISABLE_ECC
-
- #ifndef PK11_SETATTRS
-diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index c9a4493..6d700a7 100644
---- a/lib/ssl/sslsock.c
-+++ b/lib/ssl/sslsock.c
-@@ -17,9 +17,16 @@
- #ifndef NO_PKCS11_BYPASS
- #include "blapi.h"
- #endif
-+#include "pk11pub.h"
- #include "nss.h"
- #include "pk11pqg.h"
-
-+/* This is a bodge to allow this code to be compiled against older NSS headers
-+ * that don't contain the TLS 1.2 changes. */
-+#ifndef CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256
-+#define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24)
-+#endif
-+
- #define SET_ERROR_CODE /* reminder */
-
- static const sslSocketOps ssl_default_ops = { /* No SSL. */
-@@ -2133,6 +2140,24 @@ SSL_VersionRangeGet(PRFileDesc *fd, SSLVersionRange *vrange)
- return SECSuccess;
- }
-
-+static PRCallOnceType checkTLS12TokenOnce;
-+static PRBool tls12TokenExists;
-+
-+static PRStatus
-+ssl_CheckTLS12Token(void)
-+{
-+ tls12TokenExists =
-+ PK11_TokenExists(CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256);
-+ return PR_SUCCESS;
-+}
-+
-+static PRBool
-+ssl_TLS12TokenExists(void)
-+{
-+ (void) PR_CallOnce(&checkTLS12TokenOnce, ssl_CheckTLS12Token);
-+ return tls12TokenExists;
-+}
-+
- SECStatus
- SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange)
- {
-@@ -2153,6 +2178,20 @@ SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange)
- ssl_GetSSL3HandshakeLock(ss);
-
- ss->vrange = *vrange;
-+ /* If we don't have a sufficiently up-to-date softoken then we cannot do
-+ * TLS 1.2. */
-+ if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_2 &&
-+ !ssl_TLS12TokenExists()) {
-+ /* If the user requested a minimum version of 1.2, then we don't
-+ * silently downgrade. */
-+ if (ss->vrange.min >= SSL_LIBRARY_VERSION_TLS_1_2) {
-+ ssl_ReleaseSSL3HandshakeLock(ss);
-+ ssl_Release1stHandshakeLock(ss);
-+ PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE);
-+ return SECFailure;
-+ }
-+ ss->vrange.max = SSL_LIBRARY_VERSION_TLS_1_1;
-+ }
-
- ssl_ReleaseSSL3HandshakeLock(ss);
- ssl_Release1stHandshakeLock(ss);
diff --git a/chromium/net/third_party/nss/patches/tlsunique.patch b/chromium/net/third_party/nss/patches/tlsunique.patch
index a31049aec75..d004ca73542 100644
--- a/chromium/net/third_party/nss/patches/tlsunique.patch
+++ b/chromium/net/third_party/nss/patches/tlsunique.patch
@@ -1,8 +1,8 @@
diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
-index 120c257..eb7f7ec 100644
+index 870a8cc..3550580 100644
--- a/lib/ssl/ssl.h
+++ b/lib/ssl/ssl.h
-@@ -385,6 +385,27 @@ SSL_IMPORT SECStatus SSL_DHEGroupPrefSet(PRFileDesc *fd,
+@@ -387,6 +387,27 @@ SSL_IMPORT SECStatus SSL_DHEGroupPrefSet(PRFileDesc *fd,
*/
SSL_IMPORT SECStatus SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled);
@@ -22,31 +22,32 @@ index 120c257..eb7f7ec 100644
+ *
+ * This call will fail if made during a renegotiation. */
+SSL_IMPORT SECStatus SSL_GetChannelBinding(PRFileDesc *fd,
-+ SSLChannelBindingType binding_type,
-+ unsigned char *out,
-+ unsigned int *outLen,
-+ unsigned int outLenMax);
++ SSLChannelBindingType binding_type,
++ unsigned char *out,
++ unsigned int *outLen,
++ unsigned int outLenMax);
+
/* SSL Version Range API
**
** This API should be used to control SSL 3.0 & TLS support instead of the
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
-index 2ae8ce9..ce92cf1 100644
+index a2beec2..1394542 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
-@@ -13241,6 +13241,68 @@ ssl3_InitSocketPolicy(sslSocket *ss)
+@@ -13808,6 +13808,69 @@ ssl3_InitSocketPolicy(sslSocket *ss)
ss->ssl3.signatureAlgorithmCount = PR_ARRAY_SIZE(defaultSignatureAlgorithms);
}
+SECStatus
+ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
-+ unsigned char *out,
-+ unsigned int *outLen,
-+ unsigned int outLenMax) {
-+ PRBool isTLS;
-+ int index = 0;
++ unsigned char *out,
++ unsigned int *outLen,
++ unsigned int outLenMax)
++{
++ PRBool isTLS;
++ int index = 0;
+ unsigned int len;
-+ SECStatus rv = SECFailure;
++ SECStatus rv = SECFailure;
+
+ *outLen = 0;
+
@@ -64,33 +65,33 @@ index 2ae8ce9..ce92cf1 100644
+ /* Sending or receiving a Finished message will set finishedBytes to a
+ * non-zero value. */
+ if (len == 0) {
-+ PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
-+ goto loser;
++ PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
++ goto loser;
+ }
+
+ /* If we are in the middle of a renegotiation then the channel binding
+ * value is poorly defined and depends on the direction that it will be
+ * used on. Therefore we simply return an error in this case. */
+ if (ss->firstHsDone && ss->ssl3.hs.ws != idle_handshake) {
-+ PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
-+ goto loser;
++ PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
++ goto loser;
+ }
+
+ /* If resuming, then we want the second Finished value in the array, which
+ * is the server's */
+ if (ss->ssl3.hs.isResuming)
-+ index = 1;
++ index = 1;
+
+ *outLen = len;
+ if (outLenMax < len) {
-+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
-+ goto loser;
++ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
++ goto loser;
+ }
+
+ if (isTLS) {
-+ memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len);
++ memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len);
+ } else {
-+ memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len);
++ memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len);
+ }
+
+ rv = SECSuccess;
@@ -104,46 +105,47 @@ index 2ae8ce9..ce92cf1 100644
* the caller of this function.
*/
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
-index c286518..976330e 100644
+index 4607655..d47eb28 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
-@@ -1897,6 +1897,11 @@ extern PRBool ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey,
- extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data,
- unsigned int length);
+@@ -1981,6 +1981,11 @@ extern PRBool ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey,
+ extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char *data,
+ unsigned int length);
+extern SECStatus ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
-+ unsigned char *out,
-+ unsigned int *outLen,
-+ unsigned int outLenMax);
++ unsigned char *out,
++ unsigned int *outLen,
++ unsigned int outLenMax);
+
/* Construct a new NSPR socket for the app to use */
extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd);
extern void ssl_FreePRSocket(PRFileDesc *fd);
diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
-index efba686..c9a4493 100644
+index 84c78b3..e312d82 100644
--- a/lib/ssl/sslsock.c
+++ b/lib/ssl/sslsock.c
-@@ -1540,6 +1540,28 @@ SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled)
+@@ -1700,6 +1700,29 @@ SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled)
return SECSuccess;
}
+SECStatus
+SSL_GetChannelBinding(PRFileDesc *fd,
-+ SSLChannelBindingType binding_type,
-+ unsigned char *out,
-+ unsigned int *outLen,
-+ unsigned int outLenMax) {
++ SSLChannelBindingType binding_type,
++ unsigned char *out,
++ unsigned int *outLen,
++ unsigned int outLenMax)
++{
+ sslSocket *ss = ssl_FindSocket(fd);
+
+ if (!ss) {
-+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding",
-+ SSL_GETPID(), fd));
-+ return SECFailure;
++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding",
++ SSL_GETPID(), fd));
++ return SECFailure;
+ }
+
+ if (binding_type != SSL_CHANNEL_BINDING_TLS_UNIQUE) {
-+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
-+ return SECFailure;
++ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
++ return SECFailure;
+ }
+
+ return ssl3_GetTLSUniqueChannelBinding(ss, out, outLen, outLenMax);
diff --git a/chromium/net/third_party/nss/ssl.gyp b/chromium/net/third_party/nss/ssl.gyp
index 89319ae59c7..4abf713603a 100644
--- a/chromium/net/third_party/nss/ssl.gyp
+++ b/chromium/net/third_party/nss/ssl.gyp
@@ -11,12 +11,9 @@
'sources': [
'ssl/SSLerrs.h',
'ssl/authcert.c',
- 'ssl/bodge/secitem_array.c',
'ssl/cmpcert.c',
'ssl/derive.c',
'ssl/dtlscon.c',
- 'ssl/os2_err.c',
- 'ssl/os2_err.h',
'ssl/preenc.h',
'ssl/prelib.c',
'ssl/ssl.h',
@@ -39,7 +36,6 @@
'ssl/sslmutex.c',
'ssl/sslmutex.h',
'ssl/sslnonce.c',
- 'ssl/sslplatf.c',
'ssl/sslproto.h',
'ssl/sslreveal.c',
'ssl/sslsecur.c',
@@ -48,21 +44,18 @@
'ssl/sslt.h',
'ssl/ssltrace.c',
'ssl/sslver.c',
+ 'ssl/tls13con.c',
+ 'ssl/tls13con.h',
+ 'ssl/tls13hkdf.c',
+ 'ssl/tls13hkdf.h',
'ssl/unix_err.c',
'ssl/unix_err.h',
- 'ssl/win32err.c',
- 'ssl/win32err.h',
- ],
- 'sources!': [
- 'ssl/os2_err.c',
- 'ssl/os2_err.h',
],
'defines': [
'NO_PKCS11_BYPASS',
'NSS_ENABLE_ECC',
'USE_UTIL_DIRECTLY',
],
- 'msvs_disabled_warnings': [4244, 4267],
'variables': {
'clang_warning_flags_unset': [
# ssl uses PR_ASSERT(!"foo") instead of PR_ASSERT(false && "foo")
@@ -72,19 +65,11 @@
'conditions': [
['component == "shared_library"', {
'conditions': [
- ['OS == "mac" or OS == "ios"', {
+ ['OS == "ios"', {
'xcode_settings': {
'GCC_SYMBOLS_PRIVATE_EXTERN': 'NO',
},
}],
- ['OS == "win"', {
- 'sources': [
- 'ssl/exports_win.def',
- ],
- }],
- ['os_posix == 1 and OS != "mac" and OS != "ios"', {
- 'cflags!': ['-fvisibility=hidden'],
- }],
],
}],
[ 'clang == 1', {
@@ -94,70 +79,14 @@
'-Wno-header-guard',
],
}],
- [ 'OS == "linux"', {
- 'link_settings': {
- 'libraries': [
- '-ldl',
- ],
- },
- }],
- [ 'OS == "mac" or OS == "ios"', {
+ [ 'OS == "ios"', {
'defines': [
'XP_UNIX',
'DARWIN',
'XP_MACOSX',
],
}],
- [ 'OS == "mac"', {
- 'link_settings': {
- 'libraries': [
- '$(SDKROOT)/System/Library/Frameworks/Security.framework',
- ],
- },
- }],
- [ 'OS == "win"', {
- 'sources!': [
- 'ssl/unix_err.c',
- 'ssl/unix_err.h',
- ],
- },
- { # else: OS != "win"
- 'sources!': [
- 'ssl/win32err.c',
- 'ssl/win32err.h',
- ],
- },
- ],
- [ 'os_posix == 1 and OS != "mac" and OS != "ios"', {
- 'include_dirs': [
- 'ssl/bodge',
- ],
- 'cflags': [
- '<!@(<(pkg-config) --cflags nss)',
- ],
- 'ldflags': [
- '<!@(<(pkg-config) --libs-only-L --libs-only-other nss)',
- ],
- 'libraries': [
- '<!@(<(pkg-config) --libs-only-l nss | sed -e "s/-lssl3//")',
- ],
- }],
- [ 'OS == "mac" or OS == "ios" or OS == "win"', {
- 'sources/': [
- ['exclude', 'ssl/bodge/'],
- ],
- 'conditions': [
- ['OS != "ios"', {
- 'defines': [
- 'NSS_PLATFORM_CLIENT_AUTH',
- ],
- 'direct_dependent_settings': {
- 'defines': [
- 'NSS_PLATFORM_CLIENT_AUTH',
- ],
- },
- }],
- ],
+ [ 'OS == "ios"', {
'dependencies': [
'../../../third_party/nss/nss.gyp:nspr',
'../../../third_party/nss/nss.gyp:nss',
diff --git a/chromium/net/third_party/nss/ssl/BUILD.gn b/chromium/net/third_party/nss/ssl/BUILD.gn
index 1e43806bd06..06a113d277b 100644
--- a/chromium/net/third_party/nss/ssl/BUILD.gn
+++ b/chromium/net/third_party/nss/ssl/BUILD.gn
@@ -16,7 +16,6 @@ component("libssl") {
sources = [
"SSLerrs.h",
"authcert.c",
- "bodge/secitem_array.c",
"cmpcert.c",
"derive.c",
"dtlscon.c",
@@ -42,7 +41,6 @@ component("libssl") {
"sslmutex.c",
"sslmutex.h",
"sslnonce.c",
- "sslplatf.c",
"sslproto.h",
"sslreveal.c",
"sslsecur.c",
@@ -51,10 +49,12 @@ component("libssl") {
"sslt.h",
"ssltrace.c",
"sslver.c",
+ "tls13con.c",
+ "tls13con.h",
+ "tls13hkdf.c",
+ "tls13hkdf.h",
"unix_err.c",
"unix_err.h",
- "win32err.c",
- "win32err.h",
]
public_configs = [ ":ssl_config" ]
@@ -69,30 +69,6 @@ component("libssl") {
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
- if (is_win) {
- sources -= [
- "unix_err.c",
- "unix_err.h",
- ]
- if (is_component_build) {
- ldflags = [ "/DEF:" + rebase_path("exports_win.def", root_build_dir) ]
- }
- } else if (is_linux) {
- if (is_component_build) {
- configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
- }
-
- libs = [ "dl" ]
-
- include_dirs = [ "bodge" ]
-
- # Must be after ssl_config since we want our SSL headers to take
- # precedence.
- public_configs += [ "//third_party/nss:system_nss_no_ssl_config" ]
- } else if (is_mac) {
- libs = [ "Security.framework" ]
- }
-
if (is_clang) {
# SSL triggers some of these Clang warnings.
configs -= [ "//build/config/clang:extra_warnings" ]
@@ -108,14 +84,7 @@ component("libssl") {
}
}
- if (is_posix) {
- sources -= [
- "win32err.c",
- "win32err.h",
- ]
- }
-
- if (is_mac || is_ios) {
+ if (is_ios) {
defines += [
"XP_UNIX",
"DARWIN",
@@ -123,8 +92,7 @@ component("libssl") {
]
}
- if (is_mac || is_ios || is_win) {
- sources -= [ "bodge/secitem_array.c" ]
+ if (is_ios) {
public_deps = [
"//third_party/nss:nspr",
"//third_party/nss:nss",
diff --git a/chromium/net/third_party/nss/ssl/SSLerrs.h b/chromium/net/third_party/nss/ssl/SSLerrs.h
index 3d21ab805d5..555e6296733 100644
--- a/chromium/net/third_party/nss/ssl/SSLerrs.h
+++ b/chromium/net/third_party/nss/ssl/SSLerrs.h
@@ -5,447 +5,472 @@
/* SSL-specific security error codes */
/* caller must include "sslerr.h" */
-ER3(SSL_ERROR_EXPORT_ONLY_SERVER, SSL_ERROR_BASE + 0,
-"Unable to communicate securely. Peer does not support high-grade encryption.")
+ER3(SSL_ERROR_EXPORT_ONLY_SERVER, SSL_ERROR_BASE + 0,
+ "Unable to communicate securely. Peer does not support high-grade encryption.")
-ER3(SSL_ERROR_US_ONLY_SERVER, SSL_ERROR_BASE + 1,
-"Unable to communicate securely. Peer requires high-grade encryption which is not supported.")
+ER3(SSL_ERROR_US_ONLY_SERVER, SSL_ERROR_BASE + 1,
+ "Unable to communicate securely. Peer requires high-grade encryption which is not supported.")
-ER3(SSL_ERROR_NO_CYPHER_OVERLAP, SSL_ERROR_BASE + 2,
-"Cannot communicate securely with peer: no common encryption algorithm(s).")
+ER3(SSL_ERROR_NO_CYPHER_OVERLAP, SSL_ERROR_BASE + 2,
+ "Cannot communicate securely with peer: no common encryption algorithm(s).")
-ER3(SSL_ERROR_NO_CERTIFICATE, SSL_ERROR_BASE + 3,
-"Unable to find the certificate or key necessary for authentication.")
+ER3(SSL_ERROR_NO_CERTIFICATE, SSL_ERROR_BASE + 3,
+ "Unable to find the certificate or key necessary for authentication.")
-ER3(SSL_ERROR_BAD_CERTIFICATE, SSL_ERROR_BASE + 4,
-"Unable to communicate securely with peer: peers's certificate was rejected.")
+ER3(SSL_ERROR_BAD_CERTIFICATE, SSL_ERROR_BASE + 4,
+ "Unable to communicate securely with peer: peers's certificate was rejected.")
-ER3(SSL_ERROR_UNUSED_5, SSL_ERROR_BASE + 5,
-"Unrecognized SSL error code.")
+ER3(SSL_ERROR_UNUSED_5, SSL_ERROR_BASE + 5,
+ "Unrecognized SSL error code.")
-ER3(SSL_ERROR_BAD_CLIENT, SSL_ERROR_BASE + 6,
-"The server has encountered bad data from the client.")
+ER3(SSL_ERROR_BAD_CLIENT, SSL_ERROR_BASE + 6,
+ "The server has encountered bad data from the client.")
-ER3(SSL_ERROR_BAD_SERVER, SSL_ERROR_BASE + 7,
-"The client has encountered bad data from the server.")
+ER3(SSL_ERROR_BAD_SERVER, SSL_ERROR_BASE + 7,
+ "The client has encountered bad data from the server.")
-ER3(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE, SSL_ERROR_BASE + 8,
-"Unsupported certificate type.")
+ER3(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE, SSL_ERROR_BASE + 8,
+ "Unsupported certificate type.")
-ER3(SSL_ERROR_UNSUPPORTED_VERSION, SSL_ERROR_BASE + 9,
-"Peer using unsupported version of security protocol.")
+ER3(SSL_ERROR_UNSUPPORTED_VERSION, SSL_ERROR_BASE + 9,
+ "Peer using unsupported version of security protocol.")
-ER3(SSL_ERROR_UNUSED_10, SSL_ERROR_BASE + 10,
-"Unrecognized SSL error code.")
+ER3(SSL_ERROR_UNUSED_10, SSL_ERROR_BASE + 10,
+ "Unrecognized SSL error code.")
-ER3(SSL_ERROR_WRONG_CERTIFICATE, SSL_ERROR_BASE + 11,
-"Client authentication failed: private key in key database does not match public key in certificate database.")
+ER3(SSL_ERROR_WRONG_CERTIFICATE, SSL_ERROR_BASE + 11,
+ "Client authentication failed: private key in key database does not match public key in certificate database.")
-ER3(SSL_ERROR_BAD_CERT_DOMAIN, SSL_ERROR_BASE + 12,
-"Unable to communicate securely with peer: requested domain name does not match the server's certificate.")
+ER3(SSL_ERROR_BAD_CERT_DOMAIN, SSL_ERROR_BASE + 12,
+ "Unable to communicate securely with peer: requested domain name does not match the server's certificate.")
-ER3(SSL_ERROR_POST_WARNING, SSL_ERROR_BASE + 13,
-"Unrecognized SSL error code.")
+ER3(SSL_ERROR_POST_WARNING, SSL_ERROR_BASE + 13,
+ "Unrecognized SSL error code.")
-ER3(SSL_ERROR_SSL2_DISABLED, (SSL_ERROR_BASE + 14),
-"Peer only supports SSL version 2, which is locally disabled.")
+ER3(SSL_ERROR_SSL2_DISABLED, (SSL_ERROR_BASE + 14),
+ "Peer only supports SSL version 2, which is locally disabled.")
+ER3(SSL_ERROR_BAD_MAC_READ, (SSL_ERROR_BASE + 15),
+ "SSL received a record with an incorrect Message Authentication Code.")
-ER3(SSL_ERROR_BAD_MAC_READ, (SSL_ERROR_BASE + 15),
-"SSL received a record with an incorrect Message Authentication Code.")
+ER3(SSL_ERROR_BAD_MAC_ALERT, (SSL_ERROR_BASE + 16),
+ "SSL peer reports incorrect Message Authentication Code.")
-ER3(SSL_ERROR_BAD_MAC_ALERT, (SSL_ERROR_BASE + 16),
-"SSL peer reports incorrect Message Authentication Code.")
+ER3(SSL_ERROR_BAD_CERT_ALERT, (SSL_ERROR_BASE + 17),
+ "SSL peer cannot verify your certificate.")
-ER3(SSL_ERROR_BAD_CERT_ALERT, (SSL_ERROR_BASE + 17),
-"SSL peer cannot verify your certificate.")
+ER3(SSL_ERROR_REVOKED_CERT_ALERT, (SSL_ERROR_BASE + 18),
+ "SSL peer rejected your certificate as revoked.")
-ER3(SSL_ERROR_REVOKED_CERT_ALERT, (SSL_ERROR_BASE + 18),
-"SSL peer rejected your certificate as revoked.")
+ER3(SSL_ERROR_EXPIRED_CERT_ALERT, (SSL_ERROR_BASE + 19),
+ "SSL peer rejected your certificate as expired.")
-ER3(SSL_ERROR_EXPIRED_CERT_ALERT, (SSL_ERROR_BASE + 19),
-"SSL peer rejected your certificate as expired.")
+ER3(SSL_ERROR_SSL_DISABLED, (SSL_ERROR_BASE + 20),
+ "Cannot connect: SSL is disabled.")
-ER3(SSL_ERROR_SSL_DISABLED, (SSL_ERROR_BASE + 20),
-"Cannot connect: SSL is disabled.")
+ER3(SSL_ERROR_FORTEZZA_PQG, (SSL_ERROR_BASE + 21),
+ "Cannot connect: SSL peer is in another FORTEZZA domain.")
-ER3(SSL_ERROR_FORTEZZA_PQG, (SSL_ERROR_BASE + 21),
-"Cannot connect: SSL peer is in another FORTEZZA domain.")
+ER3(SSL_ERROR_UNKNOWN_CIPHER_SUITE, (SSL_ERROR_BASE + 22),
+ "An unknown SSL cipher suite has been requested.")
-ER3(SSL_ERROR_UNKNOWN_CIPHER_SUITE , (SSL_ERROR_BASE + 22),
-"An unknown SSL cipher suite has been requested.")
+ER3(SSL_ERROR_NO_CIPHERS_SUPPORTED, (SSL_ERROR_BASE + 23),
+ "No cipher suites are present and enabled in this program.")
-ER3(SSL_ERROR_NO_CIPHERS_SUPPORTED , (SSL_ERROR_BASE + 23),
-"No cipher suites are present and enabled in this program.")
+ER3(SSL_ERROR_BAD_BLOCK_PADDING, (SSL_ERROR_BASE + 24),
+ "SSL received a record with bad block padding.")
-ER3(SSL_ERROR_BAD_BLOCK_PADDING , (SSL_ERROR_BASE + 24),
-"SSL received a record with bad block padding.")
+ER3(SSL_ERROR_RX_RECORD_TOO_LONG, (SSL_ERROR_BASE + 25),
+ "SSL received a record that exceeded the maximum permissible length.")
-ER3(SSL_ERROR_RX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 25),
-"SSL received a record that exceeded the maximum permissible length.")
-
-ER3(SSL_ERROR_TX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 26),
-"SSL attempted to send a record that exceeded the maximum permissible length.")
+ER3(SSL_ERROR_TX_RECORD_TOO_LONG, (SSL_ERROR_BASE + 26),
+ "SSL attempted to send a record that exceeded the maximum permissible length.")
/*
* Received a malformed (too long or short or invalid content) SSL handshake.
*/
-ER3(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST , (SSL_ERROR_BASE + 27),
-"SSL received a malformed Hello Request handshake message.")
+ER3(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST, (SSL_ERROR_BASE + 27),
+ "SSL received a malformed Hello Request handshake message.")
-ER3(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO , (SSL_ERROR_BASE + 28),
-"SSL received a malformed Client Hello handshake message.")
+ER3(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, (SSL_ERROR_BASE + 28),
+ "SSL received a malformed Client Hello handshake message.")
-ER3(SSL_ERROR_RX_MALFORMED_SERVER_HELLO , (SSL_ERROR_BASE + 29),
-"SSL received a malformed Server Hello handshake message.")
+ER3(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, (SSL_ERROR_BASE + 29),
+ "SSL received a malformed Server Hello handshake message.")
-ER3(SSL_ERROR_RX_MALFORMED_CERTIFICATE , (SSL_ERROR_BASE + 30),
-"SSL received a malformed Certificate handshake message.")
+ER3(SSL_ERROR_RX_MALFORMED_CERTIFICATE, (SSL_ERROR_BASE + 30),
+ "SSL received a malformed Certificate handshake message.")
-ER3(SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 31),
-"SSL received a malformed Server Key Exchange handshake message.")
+ER3(SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH, (SSL_ERROR_BASE + 31),
+ "SSL received a malformed Server Key Exchange handshake message.")
-ER3(SSL_ERROR_RX_MALFORMED_CERT_REQUEST , (SSL_ERROR_BASE + 32),
-"SSL received a malformed Certificate Request handshake message.")
+ER3(SSL_ERROR_RX_MALFORMED_CERT_REQUEST, (SSL_ERROR_BASE + 32),
+ "SSL received a malformed Certificate Request handshake message.")
-ER3(SSL_ERROR_RX_MALFORMED_HELLO_DONE , (SSL_ERROR_BASE + 33),
-"SSL received a malformed Server Hello Done handshake message.")
+ER3(SSL_ERROR_RX_MALFORMED_HELLO_DONE, (SSL_ERROR_BASE + 33),
+ "SSL received a malformed Server Hello Done handshake message.")
-ER3(SSL_ERROR_RX_MALFORMED_CERT_VERIFY , (SSL_ERROR_BASE + 34),
-"SSL received a malformed Certificate Verify handshake message.")
+ER3(SSL_ERROR_RX_MALFORMED_CERT_VERIFY, (SSL_ERROR_BASE + 34),
+ "SSL received a malformed Certificate Verify handshake message.")
-ER3(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 35),
-"SSL received a malformed Client Key Exchange handshake message.")
+ER3(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH, (SSL_ERROR_BASE + 35),
+ "SSL received a malformed Client Key Exchange handshake message.")
-ER3(SSL_ERROR_RX_MALFORMED_FINISHED , (SSL_ERROR_BASE + 36),
-"SSL received a malformed Finished handshake message.")
+ER3(SSL_ERROR_RX_MALFORMED_FINISHED, (SSL_ERROR_BASE + 36),
+ "SSL received a malformed Finished handshake message.")
/*
* Received a malformed (too long or short) SSL record.
*/
-ER3(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER , (SSL_ERROR_BASE + 37),
-"SSL received a malformed Change Cipher Spec record.")
+ER3(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER, (SSL_ERROR_BASE + 37),
+ "SSL received a malformed Change Cipher Spec record.")
-ER3(SSL_ERROR_RX_MALFORMED_ALERT , (SSL_ERROR_BASE + 38),
-"SSL received a malformed Alert record.")
+ER3(SSL_ERROR_RX_MALFORMED_ALERT, (SSL_ERROR_BASE + 38),
+ "SSL received a malformed Alert record.")
-ER3(SSL_ERROR_RX_MALFORMED_HANDSHAKE , (SSL_ERROR_BASE + 39),
-"SSL received a malformed Handshake record.")
+ER3(SSL_ERROR_RX_MALFORMED_HANDSHAKE, (SSL_ERROR_BASE + 39),
+ "SSL received a malformed Handshake record.")
-ER3(SSL_ERROR_RX_MALFORMED_APPLICATION_DATA , (SSL_ERROR_BASE + 40),
-"SSL received a malformed Application Data record.")
+ER3(SSL_ERROR_RX_MALFORMED_APPLICATION_DATA, (SSL_ERROR_BASE + 40),
+ "SSL received a malformed Application Data record.")
/*
* Received an SSL handshake that was inappropriate for the state we're in.
* E.g. Server received message from server, or wrong state in state machine.
*/
-ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST , (SSL_ERROR_BASE + 41),
-"SSL received an unexpected Hello Request handshake message.")
+ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST, (SSL_ERROR_BASE + 41),
+ "SSL received an unexpected Hello Request handshake message.")
-ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO , (SSL_ERROR_BASE + 42),
-"SSL received an unexpected Client Hello handshake message.")
+ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO, (SSL_ERROR_BASE + 42),
+ "SSL received an unexpected Client Hello handshake message.")
-ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO , (SSL_ERROR_BASE + 43),
-"SSL received an unexpected Server Hello handshake message.")
+ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO, (SSL_ERROR_BASE + 43),
+ "SSL received an unexpected Server Hello handshake message.")
-ER3(SSL_ERROR_RX_UNEXPECTED_CERTIFICATE , (SSL_ERROR_BASE + 44),
-"SSL received an unexpected Certificate handshake message.")
+ER3(SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, (SSL_ERROR_BASE + 44),
+ "SSL received an unexpected Certificate handshake message.")
-ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 45),
-"SSL received an unexpected Server Key Exchange handshake message.")
+ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH, (SSL_ERROR_BASE + 45),
+ "SSL received an unexpected Server Key Exchange handshake message.")
-ER3(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST , (SSL_ERROR_BASE + 46),
-"SSL received an unexpected Certificate Request handshake message.")
+ER3(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, (SSL_ERROR_BASE + 46),
+ "SSL received an unexpected Certificate Request handshake message.")
-ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE , (SSL_ERROR_BASE + 47),
-"SSL received an unexpected Server Hello Done handshake message.")
+ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE, (SSL_ERROR_BASE + 47),
+ "SSL received an unexpected Server Hello Done handshake message.")
-ER3(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY , (SSL_ERROR_BASE + 48),
-"SSL received an unexpected Certificate Verify handshake message.")
+ER3(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY, (SSL_ERROR_BASE + 48),
+ "SSL received an unexpected Certificate Verify handshake message.")
-ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 49),
-"SSL received an unexpected Client Key Exchange handshake message.")
+ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH, (SSL_ERROR_BASE + 49),
+ "SSL received an unexpected Client Key Exchange handshake message.")
-ER3(SSL_ERROR_RX_UNEXPECTED_FINISHED , (SSL_ERROR_BASE + 50),
-"SSL received an unexpected Finished handshake message.")
+ER3(SSL_ERROR_RX_UNEXPECTED_FINISHED, (SSL_ERROR_BASE + 50),
+ "SSL received an unexpected Finished handshake message.")
/*
* Received an SSL record that was inappropriate for the state we're in.
*/
-ER3(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER , (SSL_ERROR_BASE + 51),
-"SSL received an unexpected Change Cipher Spec record.")
+ER3(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER, (SSL_ERROR_BASE + 51),
+ "SSL received an unexpected Change Cipher Spec record.")
-ER3(SSL_ERROR_RX_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 52),
-"SSL received an unexpected Alert record.")
+ER3(SSL_ERROR_RX_UNEXPECTED_ALERT, (SSL_ERROR_BASE + 52),
+ "SSL received an unexpected Alert record.")
-ER3(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE , (SSL_ERROR_BASE + 53),
-"SSL received an unexpected Handshake record.")
+ER3(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE, (SSL_ERROR_BASE + 53),
+ "SSL received an unexpected Handshake record.")
ER3(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA, (SSL_ERROR_BASE + 54),
-"SSL received an unexpected Application Data record.")
+ "SSL received an unexpected Application Data record.")
/*
* Received record/message with unknown discriminant.
*/
-ER3(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE , (SSL_ERROR_BASE + 55),
-"SSL received a record with an unknown content type.")
+ER3(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE, (SSL_ERROR_BASE + 55),
+ "SSL received a record with an unknown content type.")
-ER3(SSL_ERROR_RX_UNKNOWN_HANDSHAKE , (SSL_ERROR_BASE + 56),
-"SSL received a handshake message with an unknown message type.")
+ER3(SSL_ERROR_RX_UNKNOWN_HANDSHAKE, (SSL_ERROR_BASE + 56),
+ "SSL received a handshake message with an unknown message type.")
-ER3(SSL_ERROR_RX_UNKNOWN_ALERT , (SSL_ERROR_BASE + 57),
-"SSL received an alert record with an unknown alert description.")
+ER3(SSL_ERROR_RX_UNKNOWN_ALERT, (SSL_ERROR_BASE + 57),
+ "SSL received an alert record with an unknown alert description.")
/*
* Received an alert reporting what we did wrong. (more alerts above)
*/
-ER3(SSL_ERROR_CLOSE_NOTIFY_ALERT , (SSL_ERROR_BASE + 58),
-"SSL peer has closed this connection.")
-
-ER3(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 59),
-"SSL peer was not expecting a handshake message it received.")
+ER3(SSL_ERROR_CLOSE_NOTIFY_ALERT, (SSL_ERROR_BASE + 58),
+ "SSL peer has closed this connection.")
-ER3(SSL_ERROR_DECOMPRESSION_FAILURE_ALERT , (SSL_ERROR_BASE + 60),
-"SSL peer was unable to successfully decompress an SSL record it received.")
+ER3(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT, (SSL_ERROR_BASE + 59),
+ "SSL peer was not expecting a handshake message it received.")
-ER3(SSL_ERROR_HANDSHAKE_FAILURE_ALERT , (SSL_ERROR_BASE + 61),
-"SSL peer was unable to negotiate an acceptable set of security parameters.")
+ER3(SSL_ERROR_DECOMPRESSION_FAILURE_ALERT, (SSL_ERROR_BASE + 60),
+ "SSL peer was unable to successfully decompress an SSL record it received.")
-ER3(SSL_ERROR_ILLEGAL_PARAMETER_ALERT , (SSL_ERROR_BASE + 62),
-"SSL peer rejected a handshake message for unacceptable content.")
+ER3(SSL_ERROR_HANDSHAKE_FAILURE_ALERT, (SSL_ERROR_BASE + 61),
+ "SSL peer was unable to negotiate an acceptable set of security parameters.")
-ER3(SSL_ERROR_UNSUPPORTED_CERT_ALERT , (SSL_ERROR_BASE + 63),
-"SSL peer does not support certificates of the type it received.")
+ER3(SSL_ERROR_ILLEGAL_PARAMETER_ALERT, (SSL_ERROR_BASE + 62),
+ "SSL peer rejected a handshake message for unacceptable content.")
-ER3(SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT , (SSL_ERROR_BASE + 64),
-"SSL peer had some unspecified issue with the certificate it received.")
+ER3(SSL_ERROR_UNSUPPORTED_CERT_ALERT, (SSL_ERROR_BASE + 63),
+ "SSL peer does not support certificates of the type it received.")
+ER3(SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT, (SSL_ERROR_BASE + 64),
+ "SSL peer had some unspecified issue with the certificate it received.")
-ER3(SSL_ERROR_GENERATE_RANDOM_FAILURE , (SSL_ERROR_BASE + 65),
-"SSL experienced a failure of its random number generator.")
+ER3(SSL_ERROR_GENERATE_RANDOM_FAILURE, (SSL_ERROR_BASE + 65),
+ "SSL experienced a failure of its random number generator.")
-ER3(SSL_ERROR_SIGN_HASHES_FAILURE , (SSL_ERROR_BASE + 66),
-"Unable to digitally sign data required to verify your certificate.")
+ER3(SSL_ERROR_SIGN_HASHES_FAILURE, (SSL_ERROR_BASE + 66),
+ "Unable to digitally sign data required to verify your certificate.")
-ER3(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE , (SSL_ERROR_BASE + 67),
-"SSL was unable to extract the public key from the peer's certificate.")
+ER3(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE, (SSL_ERROR_BASE + 67),
+ "SSL was unable to extract the public key from the peer's certificate.")
-ER3(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 68),
-"Unspecified failure while processing SSL Server Key Exchange handshake.")
+ER3(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE, (SSL_ERROR_BASE + 68),
+ "Unspecified failure while processing SSL Server Key Exchange handshake.")
-ER3(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 69),
-"Unspecified failure while processing SSL Client Key Exchange handshake.")
+ER3(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE, (SSL_ERROR_BASE + 69),
+ "Unspecified failure while processing SSL Client Key Exchange handshake.")
-ER3(SSL_ERROR_ENCRYPTION_FAILURE , (SSL_ERROR_BASE + 70),
-"Bulk data encryption algorithm failed in selected cipher suite.")
+ER3(SSL_ERROR_ENCRYPTION_FAILURE, (SSL_ERROR_BASE + 70),
+ "Bulk data encryption algorithm failed in selected cipher suite.")
-ER3(SSL_ERROR_DECRYPTION_FAILURE , (SSL_ERROR_BASE + 71),
-"Bulk data decryption algorithm failed in selected cipher suite.")
+ER3(SSL_ERROR_DECRYPTION_FAILURE, (SSL_ERROR_BASE + 71),
+ "Bulk data decryption algorithm failed in selected cipher suite.")
-ER3(SSL_ERROR_SOCKET_WRITE_FAILURE , (SSL_ERROR_BASE + 72),
-"Attempt to write encrypted data to underlying socket failed.")
+ER3(SSL_ERROR_SOCKET_WRITE_FAILURE, (SSL_ERROR_BASE + 72),
+ "Attempt to write encrypted data to underlying socket failed.")
-ER3(SSL_ERROR_MD5_DIGEST_FAILURE , (SSL_ERROR_BASE + 73),
-"MD5 digest function failed.")
+ER3(SSL_ERROR_MD5_DIGEST_FAILURE, (SSL_ERROR_BASE + 73),
+ "MD5 digest function failed.")
-ER3(SSL_ERROR_SHA_DIGEST_FAILURE , (SSL_ERROR_BASE + 74),
-"SHA-1 digest function failed.")
+ER3(SSL_ERROR_SHA_DIGEST_FAILURE, (SSL_ERROR_BASE + 74),
+ "SHA-1 digest function failed.")
-ER3(SSL_ERROR_MAC_COMPUTATION_FAILURE , (SSL_ERROR_BASE + 75),
-"MAC computation failed.")
+ER3(SSL_ERROR_MAC_COMPUTATION_FAILURE, (SSL_ERROR_BASE + 75),
+ "MAC computation failed.")
-ER3(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE , (SSL_ERROR_BASE + 76),
-"Failure to create Symmetric Key context.")
+ER3(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE, (SSL_ERROR_BASE + 76),
+ "Failure to create Symmetric Key context.")
-ER3(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE , (SSL_ERROR_BASE + 77),
-"Failure to unwrap the Symmetric key in Client Key Exchange message.")
+ER3(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE, (SSL_ERROR_BASE + 77),
+ "Failure to unwrap the Symmetric key in Client Key Exchange message.")
-ER3(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED , (SSL_ERROR_BASE + 78),
-"SSL Server attempted to use domestic-grade public key with export cipher suite.")
+ER3(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED, (SSL_ERROR_BASE + 78),
+ "SSL Server attempted to use domestic-grade public key with export cipher suite.")
-ER3(SSL_ERROR_IV_PARAM_FAILURE , (SSL_ERROR_BASE + 79),
-"PKCS11 code failed to translate an IV into a param.")
+ER3(SSL_ERROR_IV_PARAM_FAILURE, (SSL_ERROR_BASE + 79),
+ "PKCS11 code failed to translate an IV into a param.")
-ER3(SSL_ERROR_INIT_CIPHER_SUITE_FAILURE , (SSL_ERROR_BASE + 80),
-"Failed to initialize the selected cipher suite.")
+ER3(SSL_ERROR_INIT_CIPHER_SUITE_FAILURE, (SSL_ERROR_BASE + 80),
+ "Failed to initialize the selected cipher suite.")
-ER3(SSL_ERROR_SESSION_KEY_GEN_FAILURE , (SSL_ERROR_BASE + 81),
-"Client failed to generate session keys for SSL session.")
+ER3(SSL_ERROR_SESSION_KEY_GEN_FAILURE, (SSL_ERROR_BASE + 81),
+ "Client failed to generate session keys for SSL session.")
-ER3(SSL_ERROR_NO_SERVER_KEY_FOR_ALG , (SSL_ERROR_BASE + 82),
-"Server has no key for the attempted key exchange algorithm.")
+ER3(SSL_ERROR_NO_SERVER_KEY_FOR_ALG, (SSL_ERROR_BASE + 82),
+ "Server has no key for the attempted key exchange algorithm.")
-ER3(SSL_ERROR_TOKEN_INSERTION_REMOVAL , (SSL_ERROR_BASE + 83),
-"PKCS#11 token was inserted or removed while operation was in progress.")
+ER3(SSL_ERROR_TOKEN_INSERTION_REMOVAL, (SSL_ERROR_BASE + 83),
+ "PKCS#11 token was inserted or removed while operation was in progress.")
-ER3(SSL_ERROR_TOKEN_SLOT_NOT_FOUND , (SSL_ERROR_BASE + 84),
-"No PKCS#11 token could be found to do a required operation.")
+ER3(SSL_ERROR_TOKEN_SLOT_NOT_FOUND, (SSL_ERROR_BASE + 84),
+ "No PKCS#11 token could be found to do a required operation.")
-ER3(SSL_ERROR_NO_COMPRESSION_OVERLAP , (SSL_ERROR_BASE + 85),
-"Cannot communicate securely with peer: no common compression algorithm(s).")
+ER3(SSL_ERROR_NO_COMPRESSION_OVERLAP, (SSL_ERROR_BASE + 85),
+ "Cannot communicate securely with peer: no common compression algorithm(s).")
-ER3(SSL_ERROR_HANDSHAKE_NOT_COMPLETED , (SSL_ERROR_BASE + 86),
-"Cannot perform the operation until the handshake is complete.")
+ER3(SSL_ERROR_HANDSHAKE_NOT_COMPLETED, (SSL_ERROR_BASE + 86),
+ "Cannot perform the operation until the handshake is complete.")
-ER3(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE , (SSL_ERROR_BASE + 87),
-"Received incorrect handshakes hash values from peer.")
+ER3(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE, (SSL_ERROR_BASE + 87),
+ "Received incorrect handshakes hash values from peer.")
-ER3(SSL_ERROR_CERT_KEA_MISMATCH , (SSL_ERROR_BASE + 88),
-"The certificate provided cannot be used with the selected key exchange algorithm.")
+ER3(SSL_ERROR_CERT_KEA_MISMATCH, (SSL_ERROR_BASE + 88),
+ "The certificate provided cannot be used with the selected key exchange algorithm.")
-ER3(SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA , (SSL_ERROR_BASE + 89),
-"No certificate authority is trusted for SSL client authentication.")
+ER3(SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA, (SSL_ERROR_BASE + 89),
+ "No certificate authority is trusted for SSL client authentication.")
-ER3(SSL_ERROR_SESSION_NOT_FOUND , (SSL_ERROR_BASE + 90),
-"Client's SSL session ID not found in server's session cache.")
+ER3(SSL_ERROR_SESSION_NOT_FOUND, (SSL_ERROR_BASE + 90),
+ "Client's SSL session ID not found in server's session cache.")
-ER3(SSL_ERROR_DECRYPTION_FAILED_ALERT , (SSL_ERROR_BASE + 91),
-"Peer was unable to decrypt an SSL record it received.")
+ER3(SSL_ERROR_DECRYPTION_FAILED_ALERT, (SSL_ERROR_BASE + 91),
+ "Peer was unable to decrypt an SSL record it received.")
-ER3(SSL_ERROR_RECORD_OVERFLOW_ALERT , (SSL_ERROR_BASE + 92),
-"Peer received an SSL record that was longer than is permitted.")
+ER3(SSL_ERROR_RECORD_OVERFLOW_ALERT, (SSL_ERROR_BASE + 92),
+ "Peer received an SSL record that was longer than is permitted.")
-ER3(SSL_ERROR_UNKNOWN_CA_ALERT , (SSL_ERROR_BASE + 93),
-"Peer does not recognize and trust the CA that issued your certificate.")
+ER3(SSL_ERROR_UNKNOWN_CA_ALERT, (SSL_ERROR_BASE + 93),
+ "Peer does not recognize and trust the CA that issued your certificate.")
-ER3(SSL_ERROR_ACCESS_DENIED_ALERT , (SSL_ERROR_BASE + 94),
-"Peer received a valid certificate, but access was denied.")
+ER3(SSL_ERROR_ACCESS_DENIED_ALERT, (SSL_ERROR_BASE + 94),
+ "Peer received a valid certificate, but access was denied.")
-ER3(SSL_ERROR_DECODE_ERROR_ALERT , (SSL_ERROR_BASE + 95),
-"Peer could not decode an SSL handshake message.")
+ER3(SSL_ERROR_DECODE_ERROR_ALERT, (SSL_ERROR_BASE + 95),
+ "Peer could not decode an SSL handshake message.")
-ER3(SSL_ERROR_DECRYPT_ERROR_ALERT , (SSL_ERROR_BASE + 96),
-"Peer reports failure of signature verification or key exchange.")
+ER3(SSL_ERROR_DECRYPT_ERROR_ALERT, (SSL_ERROR_BASE + 96),
+ "Peer reports failure of signature verification or key exchange.")
-ER3(SSL_ERROR_EXPORT_RESTRICTION_ALERT , (SSL_ERROR_BASE + 97),
-"Peer reports negotiation not in compliance with export regulations.")
+ER3(SSL_ERROR_EXPORT_RESTRICTION_ALERT, (SSL_ERROR_BASE + 97),
+ "Peer reports negotiation not in compliance with export regulations.")
-ER3(SSL_ERROR_PROTOCOL_VERSION_ALERT , (SSL_ERROR_BASE + 98),
-"Peer reports incompatible or unsupported protocol version.")
+ER3(SSL_ERROR_PROTOCOL_VERSION_ALERT, (SSL_ERROR_BASE + 98),
+ "Peer reports incompatible or unsupported protocol version.")
-ER3(SSL_ERROR_INSUFFICIENT_SECURITY_ALERT , (SSL_ERROR_BASE + 99),
-"Server requires ciphers more secure than those supported by client.")
+ER3(SSL_ERROR_INSUFFICIENT_SECURITY_ALERT, (SSL_ERROR_BASE + 99),
+ "Server requires ciphers more secure than those supported by client.")
-ER3(SSL_ERROR_INTERNAL_ERROR_ALERT , (SSL_ERROR_BASE + 100),
-"Peer reports it experienced an internal error.")
+ER3(SSL_ERROR_INTERNAL_ERROR_ALERT, (SSL_ERROR_BASE + 100),
+ "Peer reports it experienced an internal error.")
-ER3(SSL_ERROR_USER_CANCELED_ALERT , (SSL_ERROR_BASE + 101),
-"Peer user canceled handshake.")
+ER3(SSL_ERROR_USER_CANCELED_ALERT, (SSL_ERROR_BASE + 101),
+ "Peer user canceled handshake.")
-ER3(SSL_ERROR_NO_RENEGOTIATION_ALERT , (SSL_ERROR_BASE + 102),
-"Peer does not permit renegotiation of SSL security parameters.")
+ER3(SSL_ERROR_NO_RENEGOTIATION_ALERT, (SSL_ERROR_BASE + 102),
+ "Peer does not permit renegotiation of SSL security parameters.")
-ER3(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED , (SSL_ERROR_BASE + 103),
-"SSL server cache not configured and not disabled for this socket.")
+ER3(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED, (SSL_ERROR_BASE + 103),
+ "SSL server cache not configured and not disabled for this socket.")
-ER3(SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT , (SSL_ERROR_BASE + 104),
-"SSL peer does not support requested TLS hello extension.")
+ER3(SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT, (SSL_ERROR_BASE + 104),
+ "SSL peer does not support requested TLS hello extension.")
-ER3(SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT , (SSL_ERROR_BASE + 105),
-"SSL peer could not obtain your certificate from the supplied URL.")
+ER3(SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT, (SSL_ERROR_BASE + 105),
+ "SSL peer could not obtain your certificate from the supplied URL.")
-ER3(SSL_ERROR_UNRECOGNIZED_NAME_ALERT , (SSL_ERROR_BASE + 106),
-"SSL peer has no certificate for the requested DNS name.")
+ER3(SSL_ERROR_UNRECOGNIZED_NAME_ALERT, (SSL_ERROR_BASE + 106),
+ "SSL peer has no certificate for the requested DNS name.")
-ER3(SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT , (SSL_ERROR_BASE + 107),
-"SSL peer was unable to get an OCSP response for its certificate.")
+ER3(SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT, (SSL_ERROR_BASE + 107),
+ "SSL peer was unable to get an OCSP response for its certificate.")
-ER3(SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT , (SSL_ERROR_BASE + 108),
-"SSL peer reported bad certificate hash value.")
+ER3(SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT, (SSL_ERROR_BASE + 108),
+ "SSL peer reported bad certificate hash value.")
ER3(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET, (SSL_ERROR_BASE + 109),
-"SSL received an unexpected New Session Ticket handshake message.")
+ "SSL received an unexpected New Session Ticket handshake message.")
ER3(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET, (SSL_ERROR_BASE + 110),
-"SSL received a malformed New Session Ticket handshake message.")
+ "SSL received a malformed New Session Ticket handshake message.")
-ER3(SSL_ERROR_DECOMPRESSION_FAILURE, (SSL_ERROR_BASE + 111),
-"SSL received a compressed record that could not be decompressed.")
+ER3(SSL_ERROR_DECOMPRESSION_FAILURE, (SSL_ERROR_BASE + 111),
+ "SSL received a compressed record that could not be decompressed.")
-ER3(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED, (SSL_ERROR_BASE + 112),
-"Renegotiation is not allowed on this SSL socket.")
+ER3(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED, (SSL_ERROR_BASE + 112),
+ "Renegotiation is not allowed on this SSL socket.")
-ER3(SSL_ERROR_UNSAFE_NEGOTIATION, (SSL_ERROR_BASE + 113),
-"Peer attempted old style (potentially vulnerable) handshake.")
+ER3(SSL_ERROR_UNSAFE_NEGOTIATION, (SSL_ERROR_BASE + 113),
+ "Peer attempted old style (potentially vulnerable) handshake.")
ER3(SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD, (SSL_ERROR_BASE + 114),
-"SSL received an unexpected uncompressed record.")
+ "SSL received an unexpected uncompressed record.")
-ER3(SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY, (SSL_ERROR_BASE + 115),
-"SSL received a weak ephemeral Diffie-Hellman key in Server Key Exchange handshake message.")
+ER3(SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY, (SSL_ERROR_BASE + 115),
+ "SSL received a weak ephemeral Diffie-Hellman key in Server Key Exchange handshake message.")
-ER3(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID, (SSL_ERROR_BASE + 116),
-"SSL received invalid NPN extension data.")
+ER3(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID, (SSL_ERROR_BASE + 116),
+ "SSL received invalid NPN extension data.")
-ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2, (SSL_ERROR_BASE + 117),
-"SSL feature not supported for SSL 2.0 connections.")
+ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2, (SSL_ERROR_BASE + 117),
+ "SSL feature not supported for SSL 2.0 connections.")
ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS, (SSL_ERROR_BASE + 118),
-"SSL feature not supported for servers.")
+ "SSL feature not supported for servers.")
ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_CLIENTS, (SSL_ERROR_BASE + 119),
-"SSL feature not supported for clients.")
+ "SSL feature not supported for clients.")
-ER3(SSL_ERROR_INVALID_VERSION_RANGE, (SSL_ERROR_BASE + 120),
-"SSL version range is not valid.")
+ER3(SSL_ERROR_INVALID_VERSION_RANGE, (SSL_ERROR_BASE + 120),
+ "SSL version range is not valid.")
-ER3(SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION, (SSL_ERROR_BASE + 121),
-"SSL peer selected a cipher suite disallowed for the selected protocol version.")
+ER3(SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION, (SSL_ERROR_BASE + 121),
+ "SSL peer selected a cipher suite disallowed for the selected protocol version.")
ER3(SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST, (SSL_ERROR_BASE + 122),
-"SSL received a malformed Hello Verify Request handshake message.")
+ "SSL received a malformed Hello Verify Request handshake message.")
ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST, (SSL_ERROR_BASE + 123),
-"SSL received an unexpected Hello Verify Request handshake message.")
+ "SSL received an unexpected Hello Verify Request handshake message.")
ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION, (SSL_ERROR_BASE + 124),
-"SSL feature not supported for the protocol version.")
+ "SSL feature not supported for the protocol version.")
-ER3(SSL_ERROR_RX_UNEXPECTED_CERT_STATUS, (SSL_ERROR_BASE + 125),
-"SSL received an unexpected Certificate Status handshake message.")
+ER3(SSL_ERROR_RX_UNEXPECTED_CERT_STATUS, (SSL_ERROR_BASE + 125),
+ "SSL received an unexpected Certificate Status handshake message.")
ER3(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM, (SSL_ERROR_BASE + 126),
-"Unsupported hash algorithm used by TLS peer.")
+ "Unsupported hash algorithm used by TLS peer.")
ER3(SSL_ERROR_DIGEST_FAILURE, (SSL_ERROR_BASE + 127),
-"Digest function failed.")
+ "Digest function failed.")
ER3(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 128),
-"Incorrect signature algorithm specified in a digitally-signed element.")
+ "Incorrect signature algorithm specified in a digitally-signed element.")
ER3(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK, (SSL_ERROR_BASE + 129),
-"The next protocol negotiation extension was enabled, but the callback was cleared prior to being needed.")
+ "The next protocol negotiation extension was enabled, but the callback was cleared prior to being needed.")
ER3(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL, (SSL_ERROR_BASE + 130),
-"The server supports no protocols that the client advertises in the ALPN extension.")
+ "The server supports no protocols that the client advertises in the ALPN extension.")
ER3(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT, (SSL_ERROR_BASE + 131),
-"The server rejected the handshake because the client downgraded to a lower "
-"TLS version than the server supports.")
+ "The server rejected the handshake because the client downgraded to a lower "
+ "TLS version than the server supports.")
ER3(SSL_ERROR_WEAK_SERVER_CERT_KEY, (SSL_ERROR_BASE + 132),
-"The server certificate included a public key that was too weak.")
+ "The server certificate included a public key that was too weak.")
ER3(SSL_ERROR_RX_SHORT_DTLS_READ, (SSL_ERROR_BASE + 133),
-"Not enough room in buffer for DTLS record.")
+ "Not enough room in buffer for DTLS record.")
ER3(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 134),
-"No supported TLS signature algorithm was configured.")
+ "No supported TLS signature algorithm was configured.")
ER3(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 135),
-"The peer used an unsupported combination of signature and hash algorithm.")
+ "The peer used an unsupported combination of signature and hash algorithm.")
ER3(SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET, (SSL_ERROR_BASE + 136),
-"The peer tried to resume without a correct extended_master_secret extension")
+ "The peer tried to resume without a correct extended_master_secret extension")
ER3(SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET, (SSL_ERROR_BASE + 137),
-"The peer tried to resume with an unexpected extended_master_secret extension")
+ "The peer tried to resume with an unexpected extended_master_secret extension")
+
+ER3(SSL_ERROR_RX_MALFORMED_KEY_SHARE, (SSL_ERROR_BASE + 138),
+ "SSL received a malformed Key Share extension.")
+
+ER3(SSL_ERROR_MISSING_KEY_SHARE, (SSL_ERROR_BASE + 139),
+ "SSL expected a Key Share extension.")
+
+ER3(SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE, (SSL_ERROR_BASE + 140),
+ "SSL received a malformed ECDHE key share handshake extension.")
+
+ER3(SSL_ERROR_RX_MALFORMED_DHE_KEY_SHARE, (SSL_ERROR_BASE + 141),
+ "SSL received a malformed DHE key share handshake extension.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_ENCRYPTED_EXTENSIONS, (SSL_ERROR_BASE + 142),
+ "SSL received an unexpected Encrypted Extensions handshake message.")
+
+ER3(SSL_ERROR_MISSING_EXTENSION_ALERT, (SSL_ERROR_BASE + 143),
+ "SSL received a missing_extenson alert.")
+
+ER3(SSL_ERROR_KEY_EXCHANGE_FAILURE, (SSL_ERROR_BASE + 144),
+ "SSL had an error performing key exchange.")
+
+ER3(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, (SSL_ERROR_BASE + 145),
+ "SSL received an extension that is not permitted for this version.")
+
+ER3(SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS, (SSL_ERROR_BASE + 146),
+ "SSL received a malformed Encrypted Extensions handshake message.")
-ER3(SSL_ERROR_BAD_CHANNEL_ID_DATA, (SSL_ERROR_BASE + 138),
-"SSL received a malformed TLS Channel ID extension.")
+ER3(SSL_ERROR_BAD_CHANNEL_ID_DATA, (SSL_ERROR_BASE + 147),
+ "SSL received a malformed TLS Channel ID extension.")
-ER3(SSL_ERROR_INVALID_CHANNEL_ID_KEY, (SSL_ERROR_BASE + 139),
-"The application provided an invalid TLS Channel ID key.")
+ER3(SSL_ERROR_INVALID_CHANNEL_ID_KEY, (SSL_ERROR_BASE + 148),
+ "The application provided an invalid TLS Channel ID key.")
-ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 140),
-"The application could not get a TLS Channel ID.")
+ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 149),
+ "The application could not get a TLS Channel ID.")
diff --git a/chromium/net/third_party/nss/ssl/authcert.c b/chromium/net/third_party/nss/ssl/authcert.c
index bd0f6ed49a2..88c7c084ae4 100644
--- a/chromium/net/third_party/nss/ssl/authcert.c
+++ b/chromium/net/third_party/nss/ssl/authcert.c
@@ -16,74 +16,74 @@
#include "key.h"
#include "nss.h"
#include "ssl.h"
-#include "pk11func.h" /* for PK11_ function calls */
+#include "pk11func.h" /* for PK11_ function calls */
/*
* This callback used by SSL to pull client sertificate upon
* server request
*/
-SECStatus
-NSS_GetClientAuthData(void * arg,
- PRFileDesc * socket,
- struct CERTDistNamesStr * caNames,
- struct CERTCertificateStr ** pRetCert,
- struct SECKEYPrivateKeyStr **pRetKey)
+SECStatus
+NSS_GetClientAuthData(void *arg,
+ PRFileDesc *socket,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
{
- CERTCertificate * cert = NULL;
- SECKEYPrivateKey * privkey = NULL;
- char * chosenNickName = (char *)arg; /* CONST */
- void * proto_win = NULL;
- SECStatus rv = SECFailure;
-
- proto_win = SSL_RevealPinArg(socket);
-
- if (chosenNickName) {
- cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
- chosenNickName, certUsageSSLClient,
- PR_FALSE, proto_win);
- if ( cert ) {
- privkey = PK11_FindKeyByAnyCert(cert, proto_win);
- if ( privkey ) {
- rv = SECSuccess;
- } else {
- CERT_DestroyCertificate(cert);
- }
+ CERTCertificate *cert = NULL;
+ SECKEYPrivateKey *privkey = NULL;
+ char *chosenNickName = (char *)arg; /* CONST */
+ void *proto_win = NULL;
+ SECStatus rv = SECFailure;
+
+ proto_win = SSL_RevealPinArg(socket);
+
+ if (chosenNickName) {
+ cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
+ chosenNickName, certUsageSSLClient,
+ PR_FALSE, proto_win);
+ if (cert) {
+ privkey = PK11_FindKeyByAnyCert(cert, proto_win);
+ if (privkey) {
+ rv = SECSuccess;
+ } else {
+ CERT_DestroyCertificate(cert);
+ }
+ }
+ } else { /* no name given, automatically find the right cert. */
+ CERTCertNicknames *names;
+ int i;
+
+ names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
+ SEC_CERT_NICKNAMES_USER, proto_win);
+ if (names != NULL) {
+ for (i = 0; i < names->numnicknames; i++) {
+ cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
+ names->nicknames[i], certUsageSSLClient,
+ PR_FALSE, proto_win);
+ if (!cert)
+ continue;
+ /* Only check unexpired certs */
+ if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) !=
+ secCertTimeValid) {
+ CERT_DestroyCertificate(cert);
+ continue;
+ }
+ rv = NSS_CmpCertChainWCANames(cert, caNames);
+ if (rv == SECSuccess) {
+ privkey =
+ PK11_FindKeyByAnyCert(cert, proto_win);
+ if (privkey)
+ break;
+ }
+ rv = SECFailure;
+ CERT_DestroyCertificate(cert);
+ }
+ CERT_FreeNicknames(names);
+ }
}
- } else { /* no name given, automatically find the right cert. */
- CERTCertNicknames * names;
- int i;
-
- names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
- SEC_CERT_NICKNAMES_USER, proto_win);
- if (names != NULL) {
- for (i = 0; i < names->numnicknames; i++) {
- cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
- names->nicknames[i], certUsageSSLClient,
- PR_FALSE, proto_win);
- if ( !cert )
- continue;
- /* Only check unexpired certs */
- if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) !=
- secCertTimeValid ) {
- CERT_DestroyCertificate(cert);
- continue;
- }
- rv = NSS_CmpCertChainWCANames(cert, caNames);
- if ( rv == SECSuccess ) {
- privkey = PK11_FindKeyByAnyCert(cert, proto_win);
- if ( privkey )
- break;
- }
- rv = SECFailure;
- CERT_DestroyCertificate(cert);
- }
- CERT_FreeNicknames(names);
+ if (rv == SECSuccess) {
+ *pRetCert = cert;
+ *pRetKey = privkey;
}
- }
- if (rv == SECSuccess) {
- *pRetCert = cert;
- *pRetKey = privkey;
- }
- return rv;
+ return rv;
}
-
diff --git a/chromium/net/third_party/nss/ssl/bodge/nssrenam.h b/chromium/net/third_party/nss/ssl/bodge/nssrenam.h
deleted file mode 100644
index 156646cdd2d..00000000000
--- a/chromium/net/third_party/nss/ssl/bodge/nssrenam.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* ***** 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 the Netscape security libraries.
- *
- * 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):
- *
- * 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 __nssrenam_h_
-#define __nssrenam_h_
-
-#define CERT_AddTempCertToPerm __CERT_AddTempCertToPerm
-#define PK11_CreateContextByRawKey __PK11_CreateContextByRawKey
-#define CERT_ClosePermCertDB __CERT_ClosePermCertDB
-#define CERT_DecodeDERCertificate __CERT_DecodeDERCertificate
-#define CERT_TraversePermCertsForNickname __CERT_TraversePermCertsForNickname
-#define CERT_TraversePermCertsForSubject __CERT_TraversePermCertsForSubject
-
-#endif /* __nssrenam_h_ */
diff --git a/chromium/net/third_party/nss/ssl/bodge/secitem_array.c b/chromium/net/third_party/nss/ssl/bodge/secitem_array.c
deleted file mode 100644
index 2acd5f8e24a..00000000000
--- a/chromium/net/third_party/nss/ssl/bodge/secitem_array.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- * Support routines for SECItemArray data structure.
- */
-
-#include "nssutil.h"
-#include "seccomon.h"
-#include "secitem.h"
-#include "secerr.h"
-#include "secport.h"
-
-#define NSSUTIL_VERSION_NUM \
- (NSSUTIL_VMAJOR * 10000 + NSSUTIL_VMINOR * 100 + NSSUTIL_VPATCH)
-#if NSSUTIL_VERSION_NUM < 31500
-// Added in NSS 3.15.
-typedef struct SECItemArrayStr SECItemArray;
-
-struct SECItemArrayStr {
- SECItem *items;
- unsigned int len;
-};
-#endif
-
-SECItemArray *
-SECITEM_AllocArray(PLArenaPool *arena, SECItemArray *array, unsigned int len)
-{
- SECItemArray *result = NULL;
- void *mark = NULL;
-
- if (arena != NULL) {
- mark = PORT_ArenaMark(arena);
- }
-
- if (array == NULL) {
- if (arena != NULL) {
- result = PORT_ArenaZAlloc(arena, sizeof(SECItemArray));
- } else {
- result = PORT_ZAlloc(sizeof(SECItemArray));
- }
- if (result == NULL) {
- goto loser;
- }
- } else {
- PORT_Assert(array->items == NULL);
- result = array;
- }
-
- result->len = len;
- if (len) {
- if (arena != NULL) {
- result->items = PORT_ArenaZNewArray(arena, SECItem, len);
- } else {
- result->items = PORT_ZNewArray(SECItem, len);
- }
- if (result->items == NULL) {
- goto loser;
- }
- } else {
- result->items = NULL;
- }
-
- if (mark) {
- PORT_ArenaUnmark(arena, mark);
- }
- return(result);
-
-loser:
- if ( arena != NULL ) {
- if (mark) {
- PORT_ArenaRelease(arena, mark);
- }
- if (array != NULL) {
- array->items = NULL;
- array->len = 0;
- }
- } else {
- if (result != NULL && array == NULL) {
- PORT_Free(result);
- }
- /*
- * If array is not NULL, the above has set array->data and
- * array->len to 0.
- */
- }
- return(NULL);
-}
-
-static void
-secitem_FreeArray(SECItemArray *array, PRBool zero_items, PRBool freeit)
-{
- unsigned int i;
-
- if (!array || !array->len || !array->items)
- return;
-
- for (i=0; i<array->len; ++i) {
- SECItem *item = &array->items[i];
-
- if (item->data) {
- if (zero_items) {
- SECITEM_ZfreeItem(item, PR_FALSE);
- } else {
- SECITEM_FreeItem(item, PR_FALSE);
- }
- }
- }
- PORT_Free(array->items);
- array->items = NULL;
- array->len = 0;
-
- if (freeit)
- PORT_Free(array);
-}
-
-void SECITEM_FreeArray(SECItemArray *array, PRBool freeit)
-{
- secitem_FreeArray(array, PR_FALSE, freeit);
-}
-
-void SECITEM_ZfreeArray(SECItemArray *array, PRBool freeit)
-{
- secitem_FreeArray(array, PR_TRUE, freeit);
-}
-
-SECItemArray *
-SECITEM_DupArray(PLArenaPool *arena, const SECItemArray *from)
-{
- SECItemArray *result;
- unsigned int i;
-
- if (!from || !from->items || !from->len)
- return NULL;
-
- result = SECITEM_AllocArray(arena, NULL, from->len);
- if (!result)
- return NULL;
-
- for (i=0; i<from->len; ++i) {
- SECStatus rv = SECITEM_CopyItem(arena,
- &result->items[i], &from->items[i]);
- if (rv != SECSuccess) {
- SECITEM_ZfreeArray(result, PR_TRUE);
- return NULL;
- }
- }
-
- return result;
-}
diff --git a/chromium/net/third_party/nss/ssl/cmpcert.c b/chromium/net/third_party/nss/ssl/cmpcert.c
index 6d8423822d5..e6edbee83e1 100644
--- a/chromium/net/third_party/nss/ssl/cmpcert.c
+++ b/chromium/net/third_party/nss/ssl/cmpcert.c
@@ -18,73 +18,72 @@
/*
* Look to see if any of the signers in the cert chain for "cert" are found
- * in the list of caNames.
+ * in the list of caNames.
* Returns SECSuccess if so, SECFailure if not.
*/
SECStatus
NSS_CmpCertChainWCANames(CERTCertificate *cert, CERTDistNames *caNames)
{
- SECItem * caname;
- CERTCertificate * curcert;
- CERTCertificate * oldcert;
- PRInt32 contentlen;
- int j;
- int headerlen;
- int depth;
- SECStatus rv;
- SECItem issuerName;
- SECItem compatIssuerName;
+ SECItem *caname;
+ CERTCertificate *curcert;
+ CERTCertificate *oldcert;
+ PRInt32 contentlen;
+ int j;
+ int headerlen;
+ int depth;
+ SECStatus rv;
+ SECItem issuerName;
+ SECItem compatIssuerName;
- if (!cert || !caNames || !caNames->nnames || !caNames->names ||
- !caNames->names->data)
- return SECFailure;
- depth=0;
- curcert = CERT_DupCertificate(cert);
-
- while( curcert ) {
- issuerName = curcert->derIssuer;
-
- /* compute an alternate issuer name for compatibility with 2.0
- * enterprise server, which send the CA names without
- * the outer layer of DER header
- */
- rv = DER_Lengths(&issuerName, &headerlen, (PRUint32 *)&contentlen);
- if ( rv == SECSuccess ) {
- compatIssuerName.data = &issuerName.data[headerlen];
- compatIssuerName.len = issuerName.len - headerlen;
- } else {
- compatIssuerName.data = NULL;
- compatIssuerName.len = 0;
- }
-
- for (j = 0; j < caNames->nnames; j++) {
- caname = &caNames->names[j];
- if (SECITEM_CompareItem(&issuerName, caname) == SECEqual) {
- rv = SECSuccess;
- CERT_DestroyCertificate(curcert);
- goto done;
- } else if (SECITEM_CompareItem(&compatIssuerName, caname) == SECEqual) {
- rv = SECSuccess;
- CERT_DestroyCertificate(curcert);
- goto done;
- }
- }
- if ( ( depth <= 20 ) &&
- ( SECITEM_CompareItem(&curcert->derIssuer, &curcert->derSubject)
- != SECEqual ) ) {
- oldcert = curcert;
- curcert = CERT_FindCertByName(curcert->dbhandle,
- &curcert->derIssuer);
- CERT_DestroyCertificate(oldcert);
- depth++;
- } else {
- CERT_DestroyCertificate(curcert);
- curcert = NULL;
+ if (!cert || !caNames || !caNames->nnames || !caNames->names ||
+ !caNames->names->data)
+ return SECFailure;
+ depth = 0;
+ curcert = CERT_DupCertificate(cert);
+
+ while (curcert) {
+ issuerName = curcert->derIssuer;
+
+ /* compute an alternate issuer name for compatibility with 2.0
+ * enterprise server, which send the CA names without
+ * the outer layer of DER header
+ */
+ rv = DER_Lengths(&issuerName, &headerlen, (PRUint32 *)&contentlen);
+ if (rv == SECSuccess) {
+ compatIssuerName.data = &issuerName.data[headerlen];
+ compatIssuerName.len = issuerName.len - headerlen;
+ } else {
+ compatIssuerName.data = NULL;
+ compatIssuerName.len = 0;
+ }
+
+ for (j = 0; j < caNames->nnames; j++) {
+ caname = &caNames->names[j];
+ if (SECITEM_CompareItem(&issuerName, caname) == SECEqual) {
+ rv = SECSuccess;
+ CERT_DestroyCertificate(curcert);
+ goto done;
+ } else if (SECITEM_CompareItem(&compatIssuerName, caname) == SECEqual) {
+ rv = SECSuccess;
+ CERT_DestroyCertificate(curcert);
+ goto done;
+ }
+ }
+ if ((depth <= 20) &&
+ (SECITEM_CompareItem(&curcert->derIssuer, &curcert->derSubject) !=
+ SECEqual)) {
+ oldcert = curcert;
+ curcert = CERT_FindCertByName(curcert->dbhandle,
+ &curcert->derIssuer);
+ CERT_DestroyCertificate(oldcert);
+ depth++;
+ } else {
+ CERT_DestroyCertificate(curcert);
+ curcert = NULL;
+ }
}
- }
- rv = SECFailure;
-
+ rv = SECFailure;
+
done:
- return rv;
+ return rv;
}
-
diff --git a/chromium/net/third_party/nss/ssl/derive.c b/chromium/net/third_party/nss/ssl/derive.c
index 8b58b800d71..026dbd2e029 100644
--- a/chromium/net/third_party/nss/ssl/derive.c
+++ b/chromium/net/third_party/nss/ssl/derive.c
@@ -5,9 +5,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "ssl.h" /* prereq to sslimpl.h */
-#include "certt.h" /* prereq to sslimpl.h */
-#include "keythi.h" /* prereq to sslimpl.h */
+#include "ssl.h" /* prereq to sslimpl.h */
+#include "certt.h" /* prereq to sslimpl.h */
+#include "keythi.h" /* prereq to sslimpl.h */
#include "sslimpl.h"
#ifndef NO_PKCS11_BYPASS
#include "blapi.h"
@@ -26,22 +26,22 @@
/* make this a macro! */
#ifdef NOT_A_MACRO
static void
-buildSSLKey(unsigned char * keyBlock, unsigned int keyLen, SECItem * result,
- const char * label)
+buildSSLKey(unsigned char *keyBlock, unsigned int keyLen, SECItem *result,
+ const char *label)
{
result->type = siBuffer;
result->data = keyBlock;
- result->len = keyLen;
+ result->len = keyLen;
PRINT_BUF(100, (NULL, label, keyBlock, keyLen));
}
#else
-#define buildSSLKey(keyBlock, keyLen, result, label) \
-{ \
- (result)->type = siBuffer; \
- (result)->data = keyBlock; \
- (result)->len = keyLen; \
- PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); \
-}
+#define buildSSLKey(keyBlock, keyLen, result, label) \
+ { \
+ (result)->type = siBuffer; \
+ (result)->data = keyBlock; \
+ (result)->len = keyLen; \
+ PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); \
+ }
#endif
/*
@@ -50,100 +50,99 @@ buildSSLKey(unsigned char * keyBlock, unsigned int keyLen, SECItem * result,
#ifndef NUM_MIXERS
#define NUM_MIXERS 9
#endif
-static const char * const mixers[NUM_MIXERS] = {
- "A",
- "BB",
- "CCC",
- "DDDD",
- "EEEEE",
- "FFFFFF",
+static const char *const mixers[NUM_MIXERS] = {
+ "A",
+ "BB",
+ "CCC",
+ "DDDD",
+ "EEEEE",
+ "FFFFFF",
"GGGGGGG",
"HHHHHHHH",
- "IIIIIIIII"
+ "IIIIIIIII"
};
-
SECStatus
ssl3_KeyAndMacDeriveBypass(
- ssl3CipherSpec * pwSpec,
- const unsigned char * cr,
- const unsigned char * sr,
- PRBool isTLS,
- PRBool isExport)
+ ssl3CipherSpec *pwSpec,
+ const unsigned char *cr,
+ const unsigned char *sr,
+ PRBool isTLS,
+ PRBool isExport)
{
const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;
- unsigned char * key_block = pwSpec->key_block;
- unsigned char * key_block2 = NULL;
- unsigned int block_bytes = 0;
- unsigned int block_needed = 0;
- unsigned int i;
- unsigned int keySize; /* actual size of cipher keys */
- unsigned int effKeySize; /* effective size of cipher keys */
- unsigned int macSize; /* size of MAC secret */
- unsigned int IVSize; /* size of IV */
- PRBool explicitIV = PR_FALSE;
- SECStatus rv = SECFailure;
- SECStatus status = SECSuccess;
- PRBool isFIPS = PR_FALSE;
- PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2;
-
- SECItem srcr;
- SECItem crsr;
-
- unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
- unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
- PRUint64 md5buf[22];
- PRUint64 shabuf[40];
+ unsigned char *key_block = pwSpec->key_block;
+ unsigned char *key_block2 = NULL;
+ unsigned int block_bytes = 0;
+ unsigned int block_needed = 0;
+ unsigned int i;
+ unsigned int keySize; /* actual size of cipher keys */
+ unsigned int effKeySize; /* effective size of cipher keys */
+ unsigned int macSize; /* size of MAC secret */
+ unsigned int IVSize; /* size of IV */
+ PRBool explicitIV = PR_FALSE;
+ SECStatus rv = SECFailure;
+ SECStatus status = SECSuccess;
+ PRBool isFIPS = PR_FALSE;
+ PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2;
+
+ SECItem srcr;
+ SECItem crsr;
+
+ unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
+ unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
+ PRUint64 md5buf[22];
+ PRUint64 shabuf[40];
#define md5Ctx ((MD5Context *)md5buf)
#define shaCtx ((SHA1Context *)shabuf)
- static const SECItem zed = { siBuffer, NULL, 0 };
+ static const SECItem zed = { siBuffer, NULL, 0 };
if (pwSpec->msItem.data == NULL ||
- pwSpec->msItem.len != SSL3_MASTER_SECRET_LENGTH) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return rv;
+ pwSpec->msItem.len != SSL3_MASTER_SECRET_LENGTH) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return rv;
}
- PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data,
- pwSpec->msItem.len));
+ PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data,
+ pwSpec->msItem.len));
/* figure out how much is needed */
- macSize = pwSpec->mac_size;
- keySize = cipher_def->key_size;
+ macSize = pwSpec->mac_size;
+ keySize = cipher_def->key_size;
effKeySize = cipher_def->secret_key_size;
- IVSize = cipher_def->iv_size;
+ IVSize = cipher_def->iv_size;
if (keySize == 0) {
- effKeySize = IVSize = 0; /* only MACing */
+ effKeySize = IVSize = 0; /* only MACing */
}
if (cipher_def->type == type_block &&
- pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
- /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */
- explicitIV = PR_TRUE;
+ pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
+ /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */
+ explicitIV = PR_TRUE;
}
block_needed =
- 2 * (macSize + effKeySize + ((!isExport && !explicitIV) * IVSize));
+ 2 * (macSize + effKeySize + ((!isExport && !explicitIV) * IVSize));
/*
* clear out our returned keys so we can recover on failure
*/
- pwSpec->client.write_key_item = zed;
+ pwSpec->client.write_key_item = zed;
pwSpec->client.write_mac_key_item = zed;
- pwSpec->server.write_key_item = zed;
+ pwSpec->server.write_key_item = zed;
pwSpec->server.write_mac_key_item = zed;
/* initialize the server random, client random block */
- srcr.type = siBuffer;
- srcr.data = srcrdata;
- srcr.len = sizeof srcrdata;
+ srcr.type = siBuffer;
+ srcr.data = srcrdata;
+ srcr.len = sizeof srcrdata;
PORT_Memcpy(srcrdata, sr, SSL3_RANDOM_LENGTH);
PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, cr, SSL3_RANDOM_LENGTH);
/* initialize the client random, server random block */
- crsr.type = siBuffer;
- crsr.data = crsrdata;
- crsr.len = sizeof crsrdata;
+ crsr.type = siBuffer;
+ crsr.data = crsrdata;
+ crsr.len = sizeof crsrdata;
PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH);
PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH);
PRINT_BUF(100, (NULL, "Key & MAC CRSR", crsr.data, crsr.len));
@@ -152,53 +151,53 @@ ssl3_KeyAndMacDeriveBypass(
* generate the key material:
*/
if (isTLS) {
- SECItem keyblk;
-
- keyblk.type = siBuffer;
- keyblk.data = key_block;
- keyblk.len = block_needed;
-
- if (isTLS12) {
- status = TLS_P_hash(HASH_AlgSHA256, &pwSpec->msItem,
- "key expansion", &srcr, &keyblk, isFIPS);
- } else {
- status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk,
- isFIPS);
- }
- if (status != SECSuccess) {
- goto key_and_mac_derive_fail;
- }
- block_bytes = keyblk.len;
+ SECItem keyblk;
+
+ keyblk.type = siBuffer;
+ keyblk.data = key_block;
+ keyblk.len = block_needed;
+
+ if (isTLS12) {
+ status = TLS_P_hash(HASH_AlgSHA256, &pwSpec->msItem,
+ "key expansion", &srcr, &keyblk, isFIPS);
+ } else {
+ status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk,
+ isFIPS);
+ }
+ if (status != SECSuccess) {
+ goto key_and_mac_derive_fail;
+ }
+ block_bytes = keyblk.len;
} else {
- /* key_block =
- * MD5(master_secret + SHA('A' + master_secret +
- * ServerHello.random + ClientHello.random)) +
- * MD5(master_secret + SHA('BB' + master_secret +
- * ServerHello.random + ClientHello.random)) +
- * MD5(master_secret + SHA('CCC' + master_secret +
- * ServerHello.random + ClientHello.random)) +
- * [...];
- */
- unsigned int made = 0;
- for (i = 0; made < block_needed && i < NUM_MIXERS; ++i) {
- unsigned int outLen;
- unsigned char sha_out[SHA1_LENGTH];
-
- SHA1_Begin(shaCtx);
- SHA1_Update(shaCtx, (unsigned char*)(mixers[i]), i+1);
- SHA1_Update(shaCtx, pwSpec->msItem.data, pwSpec->msItem.len);
- SHA1_Update(shaCtx, srcr.data, srcr.len);
- SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH);
- PORT_Assert(outLen == SHA1_LENGTH);
-
- MD5_Begin(md5Ctx);
- MD5_Update(md5Ctx, pwSpec->msItem.data, pwSpec->msItem.len);
- MD5_Update(md5Ctx, sha_out, outLen);
- MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH);
- PORT_Assert(outLen == MD5_LENGTH);
- made += MD5_LENGTH;
- }
- block_bytes = made;
+ /* key_block =
+ * MD5(master_secret + SHA('A' + master_secret +
+ * ServerHello.random + ClientHello.random)) +
+ * MD5(master_secret + SHA('BB' + master_secret +
+ * ServerHello.random + ClientHello.random)) +
+ * MD5(master_secret + SHA('CCC' + master_secret +
+ * ServerHello.random + ClientHello.random)) +
+ * [...];
+ */
+ unsigned int made = 0;
+ for (i = 0; made < block_needed && i < NUM_MIXERS; ++i) {
+ unsigned int outLen;
+ unsigned char sha_out[SHA1_LENGTH];
+
+ SHA1_Begin(shaCtx);
+ SHA1_Update(shaCtx, (unsigned char *)(mixers[i]), i + 1);
+ SHA1_Update(shaCtx, pwSpec->msItem.data, pwSpec->msItem.len);
+ SHA1_Update(shaCtx, srcr.data, srcr.len);
+ SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH);
+ PORT_Assert(outLen == SHA1_LENGTH);
+
+ MD5_Begin(md5Ctx);
+ MD5_Update(md5Ctx, pwSpec->msItem.data, pwSpec->msItem.len);
+ MD5_Update(md5Ctx, sha_out, outLen);
+ MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH);
+ PORT_Assert(outLen == MD5_LENGTH);
+ made += MD5_LENGTH;
+ }
+ block_bytes = made;
}
PORT_Assert(block_bytes >= block_needed);
PORT_Assert(block_bytes <= sizeof pwSpec->key_block);
@@ -208,208 +207,208 @@ ssl3_KeyAndMacDeriveBypass(
* Put the key material where it goes.
*/
key_block2 = key_block + block_bytes;
- i = 0; /* now shows how much consumed */
+ i = 0; /* now shows how much consumed */
- /*
+ /*
* The key_block is partitioned as follows:
* client_write_MAC_secret[CipherSpec.hash_size]
*/
- buildSSLKey(&key_block[i],macSize, &pwSpec->client.write_mac_key_item, \
+ buildSSLKey(&key_block[i], macSize, &pwSpec->client.write_mac_key_item,
"Client Write MAC Secret");
i += macSize;
- /*
+ /*
* server_write_MAC_secret[CipherSpec.hash_size]
*/
- buildSSLKey(&key_block[i],macSize, &pwSpec->server.write_mac_key_item, \
+ buildSSLKey(&key_block[i], macSize, &pwSpec->server.write_mac_key_item,
"Server Write MAC Secret");
i += macSize;
if (!keySize) {
- /* only MACing */
- buildSSLKey(NULL, 0, &pwSpec->client.write_key_item, \
- "Client Write Key (MAC only)");
- buildSSLKey(NULL, 0, &pwSpec->server.write_key_item, \
- "Server Write Key (MAC only)");
- buildSSLKey(NULL, 0, &pwSpec->client.write_iv_item, \
- "Client Write IV (MAC only)");
- buildSSLKey(NULL, 0, &pwSpec->server.write_iv_item, \
- "Server Write IV (MAC only)");
+ /* only MACing */
+ buildSSLKey(NULL, 0, &pwSpec->client.write_key_item,
+ "Client Write Key (MAC only)");
+ buildSSLKey(NULL, 0, &pwSpec->server.write_key_item,
+ "Server Write Key (MAC only)");
+ buildSSLKey(NULL, 0, &pwSpec->client.write_iv_item,
+ "Client Write IV (MAC only)");
+ buildSSLKey(NULL, 0, &pwSpec->server.write_iv_item,
+ "Server Write IV (MAC only)");
} else if (!isExport) {
- /*
- ** Generate Domestic write keys and IVs.
- ** client_write_key[CipherSpec.key_material]
- */
- buildSSLKey(&key_block[i], keySize, &pwSpec->client.write_key_item, \
- "Domestic Client Write Key");
- i += keySize;
-
- /*
- ** server_write_key[CipherSpec.key_material]
- */
- buildSSLKey(&key_block[i], keySize, &pwSpec->server.write_key_item, \
- "Domestic Server Write Key");
- i += keySize;
-
- if (IVSize > 0) {
- if (explicitIV) {
- static unsigned char zero_block[32];
- PORT_Assert(IVSize <= sizeof zero_block);
- buildSSLKey(&zero_block[0], IVSize, \
- &pwSpec->client.write_iv_item, \
- "Domestic Client Write IV");
- buildSSLKey(&zero_block[0], IVSize, \
- &pwSpec->server.write_iv_item, \
- "Domestic Server Write IV");
- } else {
- /*
- ** client_write_IV[CipherSpec.IV_size]
- */
- buildSSLKey(&key_block[i], IVSize, \
- &pwSpec->client.write_iv_item, \
- "Domestic Client Write IV");
- i += IVSize;
-
- /*
- ** server_write_IV[CipherSpec.IV_size]
- */
- buildSSLKey(&key_block[i], IVSize, \
- &pwSpec->server.write_iv_item, \
- "Domestic Server Write IV");
- i += IVSize;
- }
- }
- PORT_Assert(i <= block_bytes);
- } else if (!isTLS) {
- /*
- ** Generate SSL3 Export write keys and IVs.
- */
- unsigned int outLen;
-
- /*
- ** client_write_key[CipherSpec.key_material]
- ** final_client_write_key = MD5(client_write_key +
- ** ClientHello.random + ServerHello.random);
- */
- MD5_Begin(md5Ctx);
- MD5_Update(md5Ctx, &key_block[i], effKeySize);
- MD5_Update(md5Ctx, crsr.data, crsr.len);
- MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
- i += effKeySize;
- buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item, \
- "SSL3 Export Client Write Key");
- key_block2 += keySize;
-
- /*
- ** server_write_key[CipherSpec.key_material]
- ** final_server_write_key = MD5(server_write_key +
- ** ServerHello.random + ClientHello.random);
- */
- MD5_Begin(md5Ctx);
- MD5_Update(md5Ctx, &key_block[i], effKeySize);
- MD5_Update(md5Ctx, srcr.data, srcr.len);
- MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
- i += effKeySize;
- buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item, \
- "SSL3 Export Server Write Key");
- key_block2 += keySize;
- PORT_Assert(i <= block_bytes);
-
- if (IVSize) {
- /*
- ** client_write_IV =
- ** MD5(ClientHello.random + ServerHello.random);
- */
- MD5_Begin(md5Ctx);
- MD5_Update(md5Ctx, crsr.data, crsr.len);
- MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
- buildSSLKey(key_block2, IVSize, &pwSpec->client.write_iv_item, \
- "SSL3 Export Client Write IV");
- key_block2 += IVSize;
-
- /*
- ** server_write_IV =
- ** MD5(ServerHello.random + ClientHello.random);
- */
- MD5_Begin(md5Ctx);
- MD5_Update(md5Ctx, srcr.data, srcr.len);
- MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
- buildSSLKey(key_block2, IVSize, &pwSpec->server.write_iv_item, \
- "SSL3 Export Server Write IV");
- key_block2 += IVSize;
- }
-
- PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block);
+ /*
+ ** Generate Domestic write keys and IVs.
+ ** client_write_key[CipherSpec.key_material]
+ */
+ buildSSLKey(&key_block[i], keySize, &pwSpec->client.write_key_item,
+ "Domestic Client Write Key");
+ i += keySize;
+
+ /*
+ ** server_write_key[CipherSpec.key_material]
+ */
+ buildSSLKey(&key_block[i], keySize, &pwSpec->server.write_key_item,
+ "Domestic Server Write Key");
+ i += keySize;
+
+ if (IVSize > 0) {
+ if (explicitIV) {
+ static unsigned char zero_block[32];
+ PORT_Assert(IVSize <= sizeof zero_block);
+ buildSSLKey(&zero_block[0], IVSize,
+ &pwSpec->client.write_iv_item,
+ "Domestic Client Write IV");
+ buildSSLKey(&zero_block[0], IVSize,
+ &pwSpec->server.write_iv_item,
+ "Domestic Server Write IV");
+ } else {
+ /*
+ ** client_write_IV[CipherSpec.IV_size]
+ */
+ buildSSLKey(&key_block[i], IVSize,
+ &pwSpec->client.write_iv_item,
+ "Domestic Client Write IV");
+ i += IVSize;
+
+ /*
+ ** server_write_IV[CipherSpec.IV_size]
+ */
+ buildSSLKey(&key_block[i], IVSize,
+ &pwSpec->server.write_iv_item,
+ "Domestic Server Write IV");
+ i += IVSize;
+ }
+ }
+ PORT_Assert(i <= block_bytes);
+ } else if (!isTLS) {
+ /*
+ ** Generate SSL3 Export write keys and IVs.
+ */
+ unsigned int outLen;
+
+ /*
+ ** client_write_key[CipherSpec.key_material]
+ ** final_client_write_key = MD5(client_write_key +
+ ** ClientHello.random + ServerHello.random);
+ */
+ MD5_Begin(md5Ctx);
+ MD5_Update(md5Ctx, &key_block[i], effKeySize);
+ MD5_Update(md5Ctx, crsr.data, crsr.len);
+ MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
+ i += effKeySize;
+ buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item,
+ "SSL3 Export Client Write Key");
+ key_block2 += keySize;
+
+ /*
+ ** server_write_key[CipherSpec.key_material]
+ ** final_server_write_key = MD5(server_write_key +
+ ** ServerHello.random + ClientHello.random);
+ */
+ MD5_Begin(md5Ctx);
+ MD5_Update(md5Ctx, &key_block[i], effKeySize);
+ MD5_Update(md5Ctx, srcr.data, srcr.len);
+ MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
+ i += effKeySize;
+ buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item,
+ "SSL3 Export Server Write Key");
+ key_block2 += keySize;
+ PORT_Assert(i <= block_bytes);
+
+ if (IVSize) {
+ /*
+ ** client_write_IV =
+ ** MD5(ClientHello.random + ServerHello.random);
+ */
+ MD5_Begin(md5Ctx);
+ MD5_Update(md5Ctx, crsr.data, crsr.len);
+ MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
+ buildSSLKey(key_block2, IVSize, &pwSpec->client.write_iv_item,
+ "SSL3 Export Client Write IV");
+ key_block2 += IVSize;
+
+ /*
+ ** server_write_IV =
+ ** MD5(ServerHello.random + ClientHello.random);
+ */
+ MD5_Begin(md5Ctx);
+ MD5_Update(md5Ctx, srcr.data, srcr.len);
+ MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
+ buildSSLKey(key_block2, IVSize, &pwSpec->server.write_iv_item,
+ "SSL3 Export Server Write IV");
+ key_block2 += IVSize;
+ }
+
+ PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block);
} else {
- /*
- ** Generate TLS Export write keys and IVs.
- */
- SECItem secret ;
- SECItem keyblk ;
-
- secret.type = siBuffer;
- keyblk.type = siBuffer;
- /*
- ** client_write_key[CipherSpec.key_material]
- ** final_client_write_key = PRF(client_write_key,
- ** "client write key",
- ** client_random + server_random);
- */
- secret.data = &key_block[i];
- secret.len = effKeySize;
- i += effKeySize;
- keyblk.data = key_block2;
- keyblk.len = keySize;
- status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, isFIPS);
- if (status != SECSuccess) {
- goto key_and_mac_derive_fail;
- }
- buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item, \
- "TLS Export Client Write Key");
- key_block2 += keySize;
-
- /*
- ** server_write_key[CipherSpec.key_material]
- ** final_server_write_key = PRF(server_write_key,
- ** "server write key",
- ** client_random + server_random);
- */
- secret.data = &key_block[i];
- secret.len = effKeySize;
- i += effKeySize;
- keyblk.data = key_block2;
- keyblk.len = keySize;
- status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, isFIPS);
- if (status != SECSuccess) {
- goto key_and_mac_derive_fail;
- }
- buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item, \
- "TLS Export Server Write Key");
- key_block2 += keySize;
-
- /*
- ** iv_block = PRF("", "IV block", client_random + server_random);
- ** client_write_IV[SecurityParameters.IV_size]
- ** server_write_IV[SecurityParameters.IV_size]
- */
- if (IVSize) {
- secret.data = NULL;
- secret.len = 0;
- keyblk.data = key_block2;
- keyblk.len = 2 * IVSize;
- status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, isFIPS);
- if (status != SECSuccess) {
- goto key_and_mac_derive_fail;
- }
- buildSSLKey(key_block2, IVSize, \
- &pwSpec->client.write_iv_item, \
- "TLS Export Client Write IV");
- buildSSLKey(key_block2 + IVSize, IVSize, \
- &pwSpec->server.write_iv_item, \
- "TLS Export Server Write IV");
- key_block2 += 2 * IVSize;
- }
- PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block);
+ /*
+ ** Generate TLS Export write keys and IVs.
+ */
+ SECItem secret;
+ SECItem keyblk;
+
+ secret.type = siBuffer;
+ keyblk.type = siBuffer;
+ /*
+ ** client_write_key[CipherSpec.key_material]
+ ** final_client_write_key = PRF(client_write_key,
+ ** "client write key",
+ ** client_random + server_random);
+ */
+ secret.data = &key_block[i];
+ secret.len = effKeySize;
+ i += effKeySize;
+ keyblk.data = key_block2;
+ keyblk.len = keySize;
+ status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, isFIPS);
+ if (status != SECSuccess) {
+ goto key_and_mac_derive_fail;
+ }
+ buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item,
+ "TLS Export Client Write Key");
+ key_block2 += keySize;
+
+ /*
+ ** server_write_key[CipherSpec.key_material]
+ ** final_server_write_key = PRF(server_write_key,
+ ** "server write key",
+ ** client_random + server_random);
+ */
+ secret.data = &key_block[i];
+ secret.len = effKeySize;
+ i += effKeySize;
+ keyblk.data = key_block2;
+ keyblk.len = keySize;
+ status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, isFIPS);
+ if (status != SECSuccess) {
+ goto key_and_mac_derive_fail;
+ }
+ buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item,
+ "TLS Export Server Write Key");
+ key_block2 += keySize;
+
+ /*
+ ** iv_block = PRF("", "IV block", client_random + server_random);
+ ** client_write_IV[SecurityParameters.IV_size]
+ ** server_write_IV[SecurityParameters.IV_size]
+ */
+ if (IVSize) {
+ secret.data = NULL;
+ secret.len = 0;
+ keyblk.data = key_block2;
+ keyblk.len = 2 * IVSize;
+ status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, isFIPS);
+ if (status != SECSuccess) {
+ goto key_and_mac_derive_fail;
+ }
+ buildSSLKey(key_block2, IVSize,
+ &pwSpec->client.write_iv_item,
+ "TLS Export Client Write IV");
+ buildSSLKey(key_block2 + IVSize, IVSize,
+ &pwSpec->server.write_iv_item,
+ "TLS Export Server Write IV");
+ key_block2 += 2 * IVSize;
+ }
+ PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block);
}
rv = SECSuccess;
@@ -419,177 +418,180 @@ key_and_mac_derive_fail:
SHA1_DestroyContext(shaCtx, PR_FALSE);
if (rv != SECSuccess) {
- PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
+ PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
}
return rv;
}
-
/* derive the Master Secret from the PMS */
/* Presently, this is only done wtih RSA PMS, and only on the server side,
- * so isRSA is always true.
+ * so isRSA is always true.
*/
SECStatus
-ssl3_MasterSecretDeriveBypass(
- ssl3CipherSpec * pwSpec,
- const unsigned char * cr,
- const unsigned char * sr,
- const SECItem * pms,
- PRBool isTLS,
- PRBool isRSA)
+ssl3_MasterSecretDeriveBypass(
+ ssl3CipherSpec *pwSpec,
+ const unsigned char *cr,
+ const unsigned char *sr,
+ const SECItem *pms,
+ PRBool isTLS,
+ PRBool isRSA)
{
- unsigned char * key_block = pwSpec->key_block;
- SECStatus rv = SECSuccess;
- PRBool isFIPS = PR_FALSE;
- PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2;
+ unsigned char *key_block = pwSpec->key_block;
+ SECStatus rv = SECSuccess;
+ PRBool isFIPS = PR_FALSE;
+ PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2;
- SECItem crsr;
+ SECItem crsr;
- unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
- PRUint64 md5buf[22];
- PRUint64 shabuf[40];
+ unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
+ PRUint64 md5buf[22];
+ PRUint64 shabuf[40];
#define md5Ctx ((MD5Context *)md5buf)
#define shaCtx ((SHA1Context *)shabuf)
/* first do the consistancy checks */
- if (isRSA) {
- PORT_Assert(pms->len == SSL3_RSA_PMS_LENGTH);
- if (pms->len != SSL3_RSA_PMS_LENGTH) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
- /* caller must test PMS version for rollback */
+ if (isRSA) {
+ PORT_Assert(pms->len == SSL3_RSA_PMS_LENGTH);
+ if (pms->len != SSL3_RSA_PMS_LENGTH) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ /* caller must test PMS version for rollback */
}
/* initialize the client random, server random block */
- crsr.type = siBuffer;
- crsr.data = crsrdata;
- crsr.len = sizeof crsrdata;
+ crsr.type = siBuffer;
+ crsr.data = crsrdata;
+ crsr.len = sizeof crsrdata;
PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH);
PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH);
PRINT_BUF(100, (NULL, "Master Secret CRSR", crsr.data, crsr.len));
/* finally do the key gen */
if (isTLS) {
- SECItem master = { siBuffer, NULL, 0 };
-
- master.data = key_block;
- master.len = SSL3_MASTER_SECRET_LENGTH;
-
- if (isTLS12) {
- rv = TLS_P_hash(HASH_AlgSHA256, pms, "master secret", &crsr,
- &master, isFIPS);
- } else {
- rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS);
- }
- if (rv != SECSuccess) {
- PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
- }
+ SECItem master = { siBuffer, NULL, 0 };
+
+ master.data = key_block;
+ master.len = SSL3_MASTER_SECRET_LENGTH;
+
+ if (isTLS12) {
+ rv = TLS_P_hash(HASH_AlgSHA256, pms, "master secret", &crsr,
+ &master, isFIPS);
+ } else {
+ rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS);
+ }
+ if (rv != SECSuccess) {
+ PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
+ }
} else {
- int i;
- unsigned int made = 0;
- for (i = 0; i < 3; i++) {
- unsigned int outLen;
- unsigned char sha_out[SHA1_LENGTH];
-
- SHA1_Begin(shaCtx);
- SHA1_Update(shaCtx, (unsigned char*) mixers[i], i+1);
- SHA1_Update(shaCtx, pms->data, pms->len);
- SHA1_Update(shaCtx, crsr.data, crsr.len);
- SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH);
- PORT_Assert(outLen == SHA1_LENGTH);
-
- MD5_Begin(md5Ctx);
- MD5_Update(md5Ctx, pms->data, pms->len);
- MD5_Update(md5Ctx, sha_out, outLen);
- MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH);
- PORT_Assert(outLen == MD5_LENGTH);
- made += outLen;
- }
+ int i;
+ unsigned int made = 0;
+ for (i = 0; i < 3; i++) {
+ unsigned int outLen;
+ unsigned char sha_out[SHA1_LENGTH];
+
+ SHA1_Begin(shaCtx);
+ SHA1_Update(shaCtx, (unsigned char *)mixers[i], i + 1);
+ SHA1_Update(shaCtx, pms->data, pms->len);
+ SHA1_Update(shaCtx, crsr.data, crsr.len);
+ SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH);
+ PORT_Assert(outLen == SHA1_LENGTH);
+
+ MD5_Begin(md5Ctx);
+ MD5_Update(md5Ctx, pms->data, pms->len);
+ MD5_Update(md5Ctx, sha_out, outLen);
+ MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH);
+ PORT_Assert(outLen == MD5_LENGTH);
+ made += outLen;
+ }
}
/* store the results */
- PORT_Memcpy(pwSpec->raw_master_secret, key_block,
- SSL3_MASTER_SECRET_LENGTH);
+ PORT_Memcpy(pwSpec->raw_master_secret, key_block,
+ SSL3_MASTER_SECRET_LENGTH);
pwSpec->msItem.data = pwSpec->raw_master_secret;
- pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH;
- PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data,
- pwSpec->msItem.len));
+ pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH;
+ PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data,
+ pwSpec->msItem.len));
return rv;
}
static SECStatus
ssl_canExtractMS(PK11SymKey *pms, PRBool isTLS, PRBool isDH, PRBool *pcbp)
-{ SECStatus rv;
- PK11SymKey * ms = NULL;
- SECItem params = {siBuffer, NULL, 0};
+{
+ SECStatus rv;
+ PK11SymKey *ms = NULL;
+ SECItem params = { siBuffer, NULL, 0 };
CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params;
- unsigned char rand[SSL3_RANDOM_LENGTH];
- CK_VERSION pms_version;
+ unsigned char rand[SSL3_RANDOM_LENGTH];
+ CK_VERSION pms_version;
CK_MECHANISM_TYPE master_derive;
CK_MECHANISM_TYPE key_derive;
- CK_FLAGS keyFlags;
-
+ CK_FLAGS keyFlags;
+
if (pms == NULL)
- return(SECFailure);
+ return (SECFailure);
PORT_Memset(rand, 0, SSL3_RANDOM_LENGTH);
if (isTLS) {
- if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH;
- else master_derive = CKM_TLS_MASTER_KEY_DERIVE;
- key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
- keyFlags = CKF_SIGN | CKF_VERIFY;
+ if (isDH)
+ master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH;
+ else
+ master_derive = CKM_TLS_MASTER_KEY_DERIVE;
+ key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
+ keyFlags = CKF_SIGN | CKF_VERIFY;
} else {
- if (isDH) master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH;
- else master_derive = CKM_SSL3_MASTER_KEY_DERIVE;
- key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
- keyFlags = 0;
+ if (isDH)
+ master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH;
+ else
+ master_derive = CKM_SSL3_MASTER_KEY_DERIVE;
+ key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
+ keyFlags = 0;
}
- master_params.pVersion = &pms_version;
- master_params.RandomInfo.pClientRandom = rand;
+ master_params.pVersion = &pms_version;
+ master_params.RandomInfo.pClientRandom = rand;
master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
- master_params.RandomInfo.pServerRandom = rand;
+ master_params.RandomInfo.pServerRandom = rand;
master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
- params.data = (unsigned char *) &master_params;
- params.len = sizeof master_params;
+ params.data = (unsigned char *)&master_params;
+ params.len = sizeof master_params;
ms = PK11_DeriveWithFlags(pms, master_derive, &params, key_derive,
- CKA_DERIVE, 0, keyFlags);
+ CKA_DERIVE, 0, keyFlags);
if (ms == NULL)
- return(SECFailure);
+ return (SECFailure);
rv = PK11_ExtractKeyValue(ms);
*pcbp = (rv == SECSuccess);
PK11_FreeSymKey(ms);
-
- return(rv);
+ return (rv);
}
-#endif /* !NO_PKCS11_BYPASS */
+#endif /* !NO_PKCS11_BYPASS */
/* Check the key exchange algorithm for each cipher in the list to see if
- * a master secret key can be extracted. If the KEA will use keys from the
+ * a master secret key can be extracted. If the KEA will use keys from the
* specified cert make sure the extract operation is attempted from the slot
* where the private key resides.
* If MS can be extracted for all ciphers, (*pcanbypass) is set to TRUE and
* SECSuccess is returned. In all other cases but one (*pcanbypass) is
* set to FALSE and SECFailure is returned.
- * In that last case Derive() has been called successfully but the MS is null,
+ * In that last case Derive() has been called successfully but the MS is null,
* CanBypass sets (*pcanbypass) to FALSE and returns SECSuccess indicating the
* arguments were all valid but the slot cannot be bypassed.
*/
/* XXX Add SSL_CBP_TLS1_1 and test it in protocolmask when setting isTLS. */
-SECStatus
+SECStatus
SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey,
- PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites,
+ PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites,
PRBool *pcanbypass, void *pwArg)
{
#ifdef NO_PKCS11_BYPASS
@@ -600,282 +602,282 @@ SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey,
*pcanbypass = PR_FALSE;
return SECSuccess;
#else
- SECStatus rv;
- int i;
- PRUint16 suite;
- PK11SymKey * pms = NULL;
- SECKEYPublicKey * srvPubkey = NULL;
- KeyType privKeytype;
- PK11SlotInfo * slot = NULL;
- SECItem param;
- CK_VERSION version;
+ SECStatus rv;
+ int i;
+ PRUint16 suite;
+ PK11SymKey *pms = NULL;
+ SECKEYPublicKey *srvPubkey = NULL;
+ KeyType privKeytype;
+ PK11SlotInfo *slot = NULL;
+ SECItem param;
+ CK_VERSION version;
CK_MECHANISM_TYPE mechanism_array[2];
- SECItem enc_pms = {siBuffer, NULL, 0};
- PRBool isTLS = PR_FALSE;
+ SECItem enc_pms = { siBuffer, NULL, 0 };
+ PRBool isTLS = PR_FALSE;
SSLCipherSuiteInfo csdef;
- PRBool testrsa = PR_FALSE;
- PRBool testrsa_export = PR_FALSE;
- PRBool testecdh = PR_FALSE;
- PRBool testecdhe = PR_FALSE;
+ PRBool testrsa = PR_FALSE;
+ PRBool testrsa_export = PR_FALSE;
+ PRBool testecdh = PR_FALSE;
+ PRBool testecdhe = PR_FALSE;
#ifndef NSS_DISABLE_ECC
SECKEYECParams ecParams = { siBuffer, NULL, 0 };
#endif
if (!cert || !srvPrivkey || !ciphersuites || !pcanbypass) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
-
+
srvPubkey = CERT_ExtractPublicKey(cert);
if (!srvPubkey)
return SECFailure;
-
+
*pcanbypass = PR_TRUE;
rv = SECFailure;
-
+
/* determine which KEAs to test */
/* 0 (TLS_NULL_WITH_NULL_NULL) is used as a list terminator because
* SSL3 and TLS specs forbid negotiating that cipher suite number.
*/
- for (i=0; i < nsuites && (suite = *ciphersuites++) != 0; i++) {
- /* skip SSL2 cipher suites and ones NSS doesn't support */
- if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess
- || SSL_IS_SSL2_CIPHER(suite) )
- continue;
- switch (csdef.keaType) {
- case ssl_kea_rsa:
- switch (csdef.cipherSuite) {
- case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA:
- case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA:
- case TLS_RSA_EXPORT_WITH_RC4_40_MD5:
- case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
- testrsa_export = PR_TRUE;
- }
- if (!testrsa_export)
- testrsa = PR_TRUE;
- break;
- case ssl_kea_ecdh:
- if (strcmp(csdef.keaTypeName, "ECDHE") == 0) /* ephemeral? */
- testecdhe = PR_TRUE;
- else
- testecdh = PR_TRUE;
- break;
- case ssl_kea_dh:
- /* this is actually DHE */
- default:
- continue;
- }
+ for (i = 0; i < nsuites && (suite = *ciphersuites++) != 0; i++) {
+ /* skip SSL2 cipher suites and ones NSS doesn't support */
+ if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess ||
+ SSL_IS_SSL2_CIPHER(suite))
+ continue;
+ switch (csdef.keaType) {
+ case ssl_kea_rsa:
+ switch (csdef.cipherSuite) {
+ case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA:
+ case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA:
+ case TLS_RSA_EXPORT_WITH_RC4_40_MD5:
+ case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
+ testrsa_export = PR_TRUE;
+ }
+ if (!testrsa_export)
+ testrsa = PR_TRUE;
+ break;
+ case ssl_kea_ecdh:
+ if (strcmp(csdef.keaTypeName, "ECDHE") == 0) /* ephemeral? */
+ testecdhe = PR_TRUE;
+ else
+ testecdh = PR_TRUE;
+ break;
+ case ssl_kea_dh:
+ /* this is actually DHE */
+ default:
+ continue;
+ }
}
-
+
/* For each protocol try to derive and extract an MS.
* Failure of function any function except MS extract means
* continue with the next cipher test. Stop testing when the list is
* exhausted or when the first MS extract--not derive--fails.
*/
privKeytype = SECKEY_GetPrivateKeyType(srvPrivkey);
- protocolmask &= SSL_CBP_SSL3|SSL_CBP_TLS1_0;
+ protocolmask &= SSL_CBP_SSL3 | SSL_CBP_TLS1_0;
while (protocolmask) {
- if (protocolmask & SSL_CBP_SSL3) {
- isTLS = PR_FALSE;
- protocolmask ^= SSL_CBP_SSL3;
- } else {
- isTLS = PR_TRUE;
- protocolmask ^= SSL_CBP_TLS1_0;
- }
-
- if (privKeytype == rsaKey && testrsa_export) {
- if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) {
- *pcanbypass = PR_FALSE;
- rv = SECSuccess;
- break;
- } else
- testrsa = PR_TRUE;
- }
- for (; privKeytype == rsaKey && testrsa; ) {
- /* TLS_RSA */
- unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
- unsigned int outLen = 0;
- CK_MECHANISM_TYPE target;
- SECStatus irv;
-
- mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN;
- mechanism_array[1] = CKM_RSA_PKCS;
-
- slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg);
- if (slot == NULL) {
- PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND);
- break;
- }
-
- /* Generate the pre-master secret ... (client side) */
- version.major = 3 /*MSB(clientHelloVersion)*/;
- version.minor = 0 /*LSB(clientHelloVersion)*/;
- param.data = (unsigned char *)&version;
- param.len = sizeof version;
- pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, &param, 0, pwArg);
- PK11_FreeSlot(slot);
- if (!pms)
- break;
- /* now wrap it */
- enc_pms.len = SECKEY_PublicKeyStrength(srvPubkey);
- enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len);
- if (enc_pms.data == NULL) {
- PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
- break;
- }
- irv = PK11_PubWrapSymKey(CKM_RSA_PKCS, srvPubkey, pms, &enc_pms);
- if (irv != SECSuccess)
- break;
- PK11_FreeSymKey(pms);
- pms = NULL;
- /* now do the server side--check the triple bypass first */
- rv = PK11_PrivDecryptPKCS1(srvPrivkey, rsaPmsBuf, &outLen,
- sizeof rsaPmsBuf,
- (unsigned char *)enc_pms.data,
- enc_pms.len);
- /* if decrypt worked we're done with the RSA test */
- if (rv == SECSuccess) {
- *pcanbypass = PR_TRUE;
- break;
- }
- /* check for fallback to double bypass */
- target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE
- : CKM_SSL3_MASTER_KEY_DERIVE;
- pms = PK11_PubUnwrapSymKey(srvPrivkey, &enc_pms,
- target, CKA_DERIVE, 0);
- rv = ssl_canExtractMS(pms, isTLS, PR_FALSE, pcanbypass);
- if (rv == SECSuccess && *pcanbypass == PR_FALSE)
- goto done;
- break;
- }
-
- /* Check for NULL to avoid double free.
- * SECItem_FreeItem sets data NULL in secitem.c#265
- */
- if (enc_pms.data != NULL) {
- SECITEM_FreeItem(&enc_pms, PR_FALSE);
+ if (protocolmask & SSL_CBP_SSL3) {
+ isTLS = PR_FALSE;
+ protocolmask ^= SSL_CBP_SSL3;
+ } else {
+ isTLS = PR_TRUE;
+ protocolmask ^= SSL_CBP_TLS1_0;
+ }
+
+ if (privKeytype == rsaKey && testrsa_export) {
+ if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) {
+ *pcanbypass = PR_FALSE;
+ rv = SECSuccess;
+ break;
+ } else
+ testrsa = PR_TRUE;
+ }
+ for (; privKeytype == rsaKey && testrsa;) {
+ /* TLS_RSA */
+ unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
+ unsigned int outLen = 0;
+ CK_MECHANISM_TYPE target;
+ SECStatus irv;
+
+ mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN;
+ mechanism_array[1] = CKM_RSA_PKCS;
+
+ slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg);
+ if (slot == NULL) {
+ PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND);
+ break;
+ }
+
+ /* Generate the pre-master secret ... (client side) */
+ version.major = 3 /*MSB(clientHelloVersion)*/;
+ version.minor = 0 /*LSB(clientHelloVersion)*/;
+ param.data = (unsigned char *)&version;
+ param.len = sizeof version;
+ pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, &param, 0, pwArg);
+ PK11_FreeSlot(slot);
+ if (!pms)
+ break;
+ /* now wrap it */
+ enc_pms.len = SECKEY_PublicKeyStrength(srvPubkey);
+ enc_pms.data = (unsigned char *)PORT_Alloc(enc_pms.len);
+ if (enc_pms.data == NULL) {
+ PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
+ break;
+ }
+ irv = PK11_PubWrapSymKey(CKM_RSA_PKCS, srvPubkey, pms, &enc_pms);
+ if (irv != SECSuccess)
+ break;
+ PK11_FreeSymKey(pms);
+ pms = NULL;
+ /* now do the server side--check the triple bypass first */
+ rv = PK11_PrivDecryptPKCS1(srvPrivkey, rsaPmsBuf, &outLen,
+ sizeof rsaPmsBuf,
+ (unsigned char *)enc_pms.data,
+ enc_pms.len);
+ /* if decrypt worked we're done with the RSA test */
+ if (rv == SECSuccess) {
+ *pcanbypass = PR_TRUE;
+ break;
+ }
+ /* check for fallback to double bypass */
+ target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE
+ : CKM_SSL3_MASTER_KEY_DERIVE;
+ pms = PK11_PubUnwrapSymKey(srvPrivkey, &enc_pms,
+ target, CKA_DERIVE, 0);
+ rv = ssl_canExtractMS(pms, isTLS, PR_FALSE, pcanbypass);
+ if (rv == SECSuccess && *pcanbypass == PR_FALSE)
+ goto done;
+ break;
+ }
+
+ /* Check for NULL to avoid double free.
+ * SECItem_FreeItem sets data NULL in secitem.c#265
+ */
+ if (enc_pms.data != NULL) {
+ SECITEM_FreeItem(&enc_pms, PR_FALSE);
}
#ifndef NSS_DISABLE_ECC
- for (; (privKeytype == ecKey && ( testecdh || testecdhe)) ||
- (privKeytype == rsaKey && testecdhe); ) {
- CK_MECHANISM_TYPE target;
- SECKEYPublicKey *keapub = NULL;
- SECKEYPrivateKey *keapriv;
- SECKEYPublicKey *cpub = NULL; /* client's ephemeral ECDH keys */
- SECKEYPrivateKey *cpriv = NULL;
- SECKEYECParams *pecParams = NULL;
-
- if (privKeytype == ecKey && testecdhe) {
- /* TLS_ECDHE_ECDSA */
- pecParams = &srvPubkey->u.ec.DEREncodedParams;
- } else if (privKeytype == rsaKey && testecdhe) {
- /* TLS_ECDHE_RSA */
- ECName ec_curve;
- int serverKeyStrengthInBits;
- int signatureKeyStrength;
- int requiredECCbits;
-
- /* find a curve of equivalent strength to the RSA key's */
- requiredECCbits = PK11_GetPrivateModulusLen(srvPrivkey);
- if (requiredECCbits < 0)
- break;
- requiredECCbits *= BPB;
- serverKeyStrengthInBits = srvPubkey->u.rsa.modulus.len;
- if (srvPubkey->u.rsa.modulus.data[0] == 0) {
- serverKeyStrengthInBits--;
- }
- /* convert to strength in bits */
- serverKeyStrengthInBits *= BPB;
-
- signatureKeyStrength =
- SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
-
- if ( requiredECCbits > signatureKeyStrength )
- requiredECCbits = signatureKeyStrength;
-
- ec_curve =
- ssl3_GetCurveWithECKeyStrength(
- ssl3_GetSupportedECCurveMask(NULL),
- requiredECCbits);
- rv = ssl3_ECName2Params(NULL, ec_curve, &ecParams);
- if (rv == SECFailure) {
- break;
- }
- pecParams = &ecParams;
- }
-
- if (testecdhe) {
- /* generate server's ephemeral keys */
- keapriv = SECKEY_CreateECPrivateKey(pecParams, &keapub, NULL);
- if (!keapriv || !keapub) {
- if (keapriv)
- SECKEY_DestroyPrivateKey(keapriv);
- if (keapub)
- SECKEY_DestroyPublicKey(keapub);
- PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
- rv = SECFailure;
- break;
- }
- } else {
- /* TLS_ECDH_ECDSA */
- keapub = srvPubkey;
- keapriv = srvPrivkey;
- pecParams = &srvPubkey->u.ec.DEREncodedParams;
- }
-
- /* perform client side ops */
- /* generate a pair of ephemeral keys using server's parms */
- cpriv = SECKEY_CreateECPrivateKey(pecParams, &cpub, NULL);
- if (!cpriv || !cpub) {
- if (testecdhe) {
- SECKEY_DestroyPrivateKey(keapriv);
- SECKEY_DestroyPublicKey(keapub);
- }
- PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
- rv = SECFailure;
- break;
- }
- /* now do the server side */
- /* determine the PMS using client's public value */
- target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE_DH
- : CKM_SSL3_MASTER_KEY_DERIVE_DH;
- pms = PK11_PubDeriveWithKDF(keapriv, cpub, PR_FALSE, NULL, NULL,
- CKM_ECDH1_DERIVE,
- target,
- CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
- rv = ssl_canExtractMS(pms, isTLS, PR_TRUE, pcanbypass);
- SECKEY_DestroyPrivateKey(cpriv);
- SECKEY_DestroyPublicKey(cpub);
- if (testecdhe) {
- SECKEY_DestroyPrivateKey(keapriv);
- SECKEY_DestroyPublicKey(keapub);
- }
- if (rv == SECSuccess && *pcanbypass == PR_FALSE)
- goto done;
- break;
- }
- /* Check for NULL to avoid double free. */
- if (ecParams.data != NULL) {
- PORT_Free(ecParams.data);
- ecParams.data = NULL;
- }
+ for (; (privKeytype == ecKey && (testecdh || testecdhe)) ||
+ (privKeytype == rsaKey && testecdhe);) {
+ CK_MECHANISM_TYPE target;
+ SECKEYPublicKey *keapub = NULL;
+ SECKEYPrivateKey *keapriv;
+ SECKEYPublicKey *cpub = NULL; /* client's ephemeral ECDH keys */
+ SECKEYPrivateKey *cpriv = NULL;
+ SECKEYECParams *pecParams = NULL;
+
+ if (privKeytype == ecKey && testecdhe) {
+ /* TLS_ECDHE_ECDSA */
+ pecParams = &srvPubkey->u.ec.DEREncodedParams;
+ } else if (privKeytype == rsaKey && testecdhe) {
+ /* TLS_ECDHE_RSA */
+ ECName ec_curve;
+ int serverKeyStrengthInBits;
+ int signatureKeyStrength;
+ int requiredECCbits;
+
+ /* find a curve of equivalent strength to the RSA key's */
+ requiredECCbits = PK11_GetPrivateModulusLen(srvPrivkey);
+ if (requiredECCbits < 0)
+ break;
+ requiredECCbits *= BPB;
+ serverKeyStrengthInBits = srvPubkey->u.rsa.modulus.len;
+ if (srvPubkey->u.rsa.modulus.data[0] == 0) {
+ serverKeyStrengthInBits--;
+ }
+ /* convert to strength in bits */
+ serverKeyStrengthInBits *= BPB;
+
+ signatureKeyStrength =
+ SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
+
+ if (requiredECCbits > signatureKeyStrength)
+ requiredECCbits = signatureKeyStrength;
+
+ ec_curve =
+ ssl3_GetCurveWithECKeyStrength(
+ ssl3_GetSupportedECCurveMask(NULL),
+ requiredECCbits);
+ rv = ssl3_ECName2Params(NULL, ec_curve, &ecParams);
+ if (rv == SECFailure) {
+ break;
+ }
+ pecParams = &ecParams;
+ }
+
+ if (testecdhe) {
+ /* generate server's ephemeral keys */
+ keapriv = SECKEY_CreateECPrivateKey(pecParams, &keapub, NULL);
+ if (!keapriv || !keapub) {
+ if (keapriv)
+ SECKEY_DestroyPrivateKey(keapriv);
+ if (keapub)
+ SECKEY_DestroyPublicKey(keapub);
+ PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
+ rv = SECFailure;
+ break;
+ }
+ } else {
+ /* TLS_ECDH_ECDSA */
+ keapub = srvPubkey;
+ keapriv = srvPrivkey;
+ pecParams = &srvPubkey->u.ec.DEREncodedParams;
+ }
+
+ /* perform client side ops */
+ /* generate a pair of ephemeral keys using server's parms */
+ cpriv = SECKEY_CreateECPrivateKey(pecParams, &cpub, NULL);
+ if (!cpriv || !cpub) {
+ if (testecdhe) {
+ SECKEY_DestroyPrivateKey(keapriv);
+ SECKEY_DestroyPublicKey(keapub);
+ }
+ PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
+ rv = SECFailure;
+ break;
+ }
+ /* now do the server side */
+ /* determine the PMS using client's public value */
+ target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE_DH
+ : CKM_SSL3_MASTER_KEY_DERIVE_DH;
+ pms = PK11_PubDeriveWithKDF(keapriv, cpub, PR_FALSE, NULL, NULL,
+ CKM_ECDH1_DERIVE,
+ target,
+ CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
+ rv = ssl_canExtractMS(pms, isTLS, PR_TRUE, pcanbypass);
+ SECKEY_DestroyPrivateKey(cpriv);
+ SECKEY_DestroyPublicKey(cpub);
+ if (testecdhe) {
+ SECKEY_DestroyPrivateKey(keapriv);
+ SECKEY_DestroyPublicKey(keapub);
+ }
+ if (rv == SECSuccess && *pcanbypass == PR_FALSE)
+ goto done;
+ break;
+ }
+ /* Check for NULL to avoid double free. */
+ if (ecParams.data != NULL) {
+ PORT_Free(ecParams.data);
+ ecParams.data = NULL;
+ }
#endif /* NSS_DISABLE_ECC */
- if (pms)
- PK11_FreeSymKey(pms);
+ if (pms)
+ PK11_FreeSymKey(pms);
}
/* *pcanbypass has been set */
rv = SECSuccess;
-
- done:
+
+done:
if (pms)
- PK11_FreeSymKey(pms);
+ PK11_FreeSymKey(pms);
- /* Check for NULL to avoid double free.
- * SECItem_FreeItem sets data NULL in secitem.c#265
+ /* Check for NULL to avoid double free.
+ * SECItem_FreeItem sets data NULL in secitem.c#265
*/
if (enc_pms.data != NULL) {
- SECITEM_FreeItem(&enc_pms, PR_FALSE);
+ SECITEM_FreeItem(&enc_pms, PR_FALSE);
}
#ifndef NSS_DISABLE_ECC
if (ecParams.data != NULL) {
@@ -885,12 +887,10 @@ SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey,
#endif /* NSS_DISABLE_ECC */
if (srvPubkey) {
- SECKEY_DestroyPublicKey(srvPubkey);
- srvPubkey = NULL;
+ SECKEY_DestroyPublicKey(srvPubkey);
+ srvPubkey = NULL;
}
-
return rv;
#endif /* NO_PKCS11_BYPASS */
}
-
diff --git a/chromium/net/third_party/nss/ssl/dtlscon.c b/chromium/net/third_party/nss/ssl/dtlscon.c
index 1b21107094e..35d995e9175 100644
--- a/chromium/net/third_party/nss/ssl/dtlscon.c
+++ b/chromium/net/third_party/nss/ssl/dtlscon.c
@@ -11,7 +11,7 @@
#include "sslproto.h"
#ifndef PR_ARRAY_SIZE
-#define PR_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+#define PR_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#endif
static SECStatus dtls_TransmitMessageFlight(sslSocket *ss);
@@ -20,10 +20,10 @@ static SECStatus dtls_SendSavedWriteData(sslSocket *ss);
/* -28 adjusts for the IP/UDP header */
static const PRUint16 COMMON_MTU_VALUES[] = {
- 1500 - 28, /* Ethernet MTU */
- 1280 - 28, /* IPv6 minimum MTU */
- 576 - 28, /* Common assumption */
- 256 - 28 /* We're in serious trouble now */
+ 1500 - 28, /* Ethernet MTU */
+ 1280 - 28, /* IPv6 minimum MTU */
+ 576 - 28, /* Common assumption */
+ 256 - 28 /* We're in serious trouble now */
};
#define DTLS_COOKIE_BYTES 32
@@ -86,6 +86,11 @@ dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv)
if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) {
return SSL_LIBRARY_VERSION_TLS_1_1;
}
+ /* Handle the skipped version of DTLS 1.1 by returning
+ * an error. */
+ if (dtlsv == ((~0x0101) & 0xffff)) {
+ return 0;
+ }
if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_2_WIRE) {
return SSL_LIBRARY_VERSION_TLS_1_2;
}
@@ -94,14 +99,14 @@ dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv)
}
/* Return a fictional higher version than we know of */
- return SSL_LIBRARY_VERSION_TLS_1_2 + 1;
+ return SSL_LIBRARY_VERSION_MAX_SUPPORTED + 1;
}
/* On this socket, Disable non-DTLS cipher suites in the argument's list */
SECStatus
-ssl3_DisableNonDTLSSuites(sslSocket * ss)
+ssl3_DisableNonDTLSSuites(sslSocket *ss)
{
- const ssl3CipherSuite * suite;
+ const ssl3CipherSuite *suite;
for (suite = nonDTLSSuites; *suite; ++suite) {
PORT_CheckSuccess(ssl3_CipherPrefSet(ss, *suite, PR_FALSE));
@@ -185,8 +190,8 @@ dtls_FreeHandshakeMessages(PRCList *list)
* the state of reassembly (i.e., whether one is in progress). That
* is carried in recvdHighWater and recvdFragments.
*/
-#define OFFSET_BYTE(o) (o/8)
-#define OFFSET_MASK(o) (1 << (o%8))
+#define OFFSET_BYTE(o) (o / 8)
+#define OFFSET_MASK(o) (1 << (o % 8))
SECStatus
dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
@@ -224,7 +229,7 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
fragment_offset = (buf.buf[6] << 16) | (buf.buf[7] << 8) | buf.buf[8];
fragment_length = (buf.buf[9] << 16) | (buf.buf[10] << 8) | buf.buf[11];
-#define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */
+#define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */
if (message_length > MAX_HANDSHAKE_MSG_LEN) {
(void)ssl3_DecodeError(ss);
PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
@@ -258,9 +263,9 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
* If it's the complete next message we accept it right away.
* This is the common case for short messages
*/
- if ((message_seq == ss->ssl3.hs.recvMessageSeq)
- && (fragment_offset == 0)
- && (fragment_length == message_length)) {
+ if ((message_seq == ss->ssl3.hs.recvMessageSeq) &&
+ (fragment_offset == 0) &&
+ (fragment_length == message_length)) {
/* Complete next message. Process immediately */
ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
ss->ssl3.hs.msg_len = message_length;
@@ -289,7 +294,7 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
if (ss->ssl3.hs.rtTimerCb == NULL) {
/* Ignore */
} else if (ss->ssl3.hs.rtTimerCb ==
- dtls_RetransmitTimerExpiredCb) {
+ dtls_RetransmitTimerExpiredCb) {
SSL_TRC(30, ("%d: SSL3[%d]: Retransmit detected",
SSL_GETPID(), ss->fd));
/* Check to see if we retransmitted recently. If so,
@@ -299,23 +304,23 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
*/
if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
(ss->ssl3.hs.rtTimeoutMs / 4)) {
- SSL_TRC(30,
- ("%d: SSL3[%d]: Shortcutting retransmit timer",
- SSL_GETPID(), ss->fd));
-
- /* Cancel the timer and call the CB,
- * which re-arms the timer */
- dtls_CancelTimer(ss);
- dtls_RetransmitTimerExpiredCb(ss);
- rv = SECSuccess;
- break;
- } else {
- SSL_TRC(30,
- ("%d: SSL3[%d]: We just retransmitted. Ignoring.",
- SSL_GETPID(), ss->fd));
- rv = SECSuccess;
- break;
- }
+ SSL_TRC(30,
+ ("%d: SSL3[%d]: Shortcutting retransmit timer",
+ SSL_GETPID(), ss->fd));
+
+ /* Cancel the timer and call the CB,
+ * which re-arms the timer */
+ dtls_CancelTimer(ss);
+ dtls_RetransmitTimerExpiredCb(ss);
+ rv = SECSuccess;
+ break;
+ } else {
+ SSL_TRC(30,
+ ("%d: SSL3[%d]: We just retransmitted. Ignoring.",
+ SSL_GETPID(), ss->fd));
+ rv = SECSuccess;
+ break;
+ }
} else if (ss->ssl3.hs.rtTimerCb == dtls_FinishedTimerCb) {
/* Retransmit the messages and re-arm the timer
* Note that we are not backing off the timer here.
@@ -450,7 +455,7 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
buf.len -= fragment_length;
}
- origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
+ origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
/* XXX OK for now. In future handle rv == SECWouldBlock safely in order
* to deal with asynchronous certificate verification */
@@ -463,8 +468,9 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
* dtls_StageHandshakeMessage()
* ssl3_SendChangeCipherSpecs()
*/
-SECStatus dtls_QueueMessage(sslSocket *ss, SSL3ContentType type,
- const SSL3Opaque *pIn, PRInt32 nIn)
+SECStatus
+dtls_QueueMessage(sslSocket *ss, SSL3ContentType type,
+ const SSL3Opaque *pIn, PRInt32 nIn)
{
SECStatus rv = SECSuccess;
DTLSQueuedMessage *msg = NULL;
@@ -634,7 +640,7 @@ dtls_TransmitMessageFlight(sslSocket *ss)
sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
msg->data, msg->len,
ssl_SEND_FLAG_FORCE_INTO_BUFFER |
- ssl_SEND_FLAG_USE_EPOCH);
+ ssl_SEND_FLAG_USE_EPOCH);
if (sent != msg->len) {
rv = SECFailure;
if (sent != -1) {
@@ -694,12 +700,12 @@ dtls_TransmitMessageFlight(sslSocket *ss)
/* Offset */
fragment[6] = (fragment_offset >> 16) & 0xff;
fragment[7] = (fragment_offset >> 8) & 0xff;
- fragment[8] = (fragment_offset) & 0xff;
+ fragment[8] = (fragment_offset)&0xff;
/* Fragment length */
fragment[9] = (fragment_len >> 16) & 0xff;
fragment[10] = (fragment_len >> 8) & 0xff;
- fragment[11] = (fragment_len) & 0xff;
+ fragment[11] = (fragment_len)&0xff;
PORT_Memcpy(fragment + 12, content + fragment_offset,
fragment_len);
@@ -711,7 +717,7 @@ dtls_TransmitMessageFlight(sslSocket *ss)
sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
fragment, fragment_len + 12,
ssl_SEND_FLAG_FORCE_INTO_BUFFER |
- ssl_SEND_FLAG_USE_EPOCH);
+ ssl_SEND_FLAG_USE_EPOCH);
if (sent != (fragment_len + 12)) {
rv = SECFailure;
if (sent != -1) {
@@ -747,8 +753,8 @@ dtls_TransmitMessageFlight(sslSocket *ss)
*
* Called from dtls_TransmitMessageFlight()
*/
-static
-SECStatus dtls_SendSavedWriteData(sslSocket *ss)
+static SECStatus
+dtls_SendSavedWriteData(sslSocket *ss)
{
PRInt32 sent;
@@ -779,18 +785,18 @@ SECStatus dtls_SendSavedWriteData(sslSocket *ss)
* Called from ssl3_SendRecord()
*/
SECStatus
-dtls_CompressMACEncryptRecord(sslSocket * ss,
- DTLSEpoch epoch,
- PRBool use_epoch,
- SSL3ContentType type,
- const SSL3Opaque * pIn,
- PRUint32 contentLen,
- sslBuffer * wrBuf)
+dtls_CompressMACEncryptRecord(sslSocket *ss,
+ DTLSEpoch epoch,
+ PRBool use_epoch,
+ SSL3ContentType type,
+ const SSL3Opaque *pIn,
+ PRUint32 contentLen,
+ sslBuffer *wrBuf)
{
SECStatus rv = SECFailure;
- ssl3CipherSpec * cwSpec;
+ ssl3CipherSpec *cwSpec;
- ssl_GetSpecReadLock(ss); /********************************/
+ ssl_GetSpecReadLock(ss); /********************************/
/* The reason for this switch-hitting code is that we might have
* a flight of records spanning an epoch boundary, e.g.,
@@ -814,9 +820,13 @@ dtls_CompressMACEncryptRecord(sslSocket * ss,
}
if (cwSpec) {
- rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE,
- PR_FALSE, type, pIn, contentLen,
- wrBuf);
+ if (ss->ssl3.cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE,
+ PR_FALSE, type, pIn, contentLen,
+ wrBuf);
+ } else {
+ rv = tls13_ProtectRecord(ss, type, pIn, contentLen, wrBuf);
+ }
} else {
PR_NOT_REACHED("Couldn't find a cipher spec matching epoch");
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
@@ -956,7 +966,7 @@ dtls_SetMTU(sslSocket *ss, PRUint16 advertised)
}
/* Fallback */
- ss->ssl3.mtu = COMMON_MTU_VALUES[PR_ARRAY_SIZE(COMMON_MTU_VALUES)-1];
+ ss->ssl3.mtu = COMMON_MTU_VALUES[PR_ARRAY_SIZE(COMMON_MTU_VALUES) - 1];
SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
}
@@ -967,27 +977,27 @@ dtls_SetMTU(sslSocket *ss, PRUint16 advertised)
SECStatus
dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
- int errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
- SECStatus rv;
- PRInt32 temp;
- SECItem cookie = {siBuffer, NULL, 0};
- SSL3AlertDescription desc = illegal_parameter;
+ int errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
+ SECStatus rv;
+ PRInt32 temp;
+ SECItem cookie = { siBuffer, NULL, 0 };
+ SSL3AlertDescription desc = illegal_parameter;
SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ss->ssl3.hs.ws != wait_server_hello) {
errCode = SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST;
- desc = unexpected_message;
+ desc = unexpected_message;
goto alert_loser;
}
/* The version */
temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
if (temp < 0) {
- goto loser; /* alert has been sent */
+ goto loser; /* alert has been sent */
}
if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE &&
@@ -998,23 +1008,22 @@ dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
/* The cookie */
rv = ssl3_ConsumeHandshakeVariable(ss, &cookie, 1, &b, &length);
if (rv != SECSuccess) {
- goto loser; /* alert has been sent */
+ goto loser; /* alert has been sent */
}
if (cookie.len > DTLS_COOKIE_BYTES) {
desc = decode_error;
- goto alert_loser; /* malformed. */
+ goto alert_loser; /* malformed. */
}
PORT_Memcpy(ss->ssl3.hs.cookie, cookie.data, cookie.len);
ss->ssl3.hs.cookieLen = cookie.len;
-
- ssl_GetXmitBufLock(ss); /*******************************/
+ ssl_GetXmitBufLock(ss); /*******************************/
/* Now re-send the client hello */
rv = ssl3_SendClientHello(ss, PR_TRUE);
- ssl_ReleaseXmitBufLock(ss); /*******************************/
+ ssl_ReleaseXmitBufLock(ss); /*******************************/
if (rv == SECSuccess)
return rv;
@@ -1023,7 +1032,7 @@ alert_loser:
(void)SSL3_SendAlert(ss, alert_fatal, desc);
loser:
- errCode = ssl_MapLowLevelError(errCode);
+ ssl_MapLowLevelError(errCode);
return SECFailure;
}
@@ -1047,10 +1056,10 @@ dtls_InitRecvdRecords(DTLSRecvdRecords *records)
* 0 -- not received yet
* 1 -- replay
*
- * Called from: dtls_HandleRecord()
+ * Called from: ssl3_HandleRecord()
*/
int
-dtls_RecordGetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
+dtls_RecordGetRecvd(const DTLSRecvdRecords *records, PRUint64 seq)
{
PRUint64 offset;
@@ -1118,7 +1127,7 @@ dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
SECStatus
DTLS_GetHandshakeTimeout(PRFileDesc *socket, PRIntervalTime *timeout)
{
- sslSocket * ss = NULL;
+ sslSocket *ss = NULL;
PRIntervalTime elapsed;
PRIntervalTime desired;
@@ -1144,3 +1153,43 @@ DTLS_GetHandshakeTimeout(PRFileDesc *socket, PRIntervalTime *timeout)
return SECSuccess;
}
+
+/*
+ * DTLS relevance checks:
+ * Note that this code currently ignores all out-of-epoch packets,
+ * which means we lose some in the case of rehandshake +
+ * loss/reordering. Since DTLS is explicitly unreliable, this
+ * seems like a good tradeoff for implementation effort and is
+ * consistent with the guidance of RFC 6347 Sections 4.1 and 4.2.4.1.
+ *
+ * If the packet is not relevant, this function returns PR_FALSE.
+ * If the packet is relevant, this function returns PR_TRUE
+ * and sets |*seqNum| to the packet sequence number.
+ */
+PRBool
+dtls_IsRelevant(sslSocket *ss, const ssl3CipherSpec *crSpec,
+ const SSL3Ciphertext *cText, PRUint64 *seqNum)
+{
+ DTLSEpoch epoch = cText->seq_num.high >> 16;
+ PRUint64 dtls_seq_num;
+
+ if (crSpec->epoch != epoch) {
+ SSL_DBG(("%d: SSL3[%d]: dtls_IsRelevant, received packet "
+ "from irrelevant epoch %d",
+ SSL_GETPID(), ss->fd, epoch));
+ return PR_FALSE;
+ }
+
+ dtls_seq_num = (((PRUint64)(cText->seq_num.high & 0xffff)) << 32) |
+ ((PRUint64)cText->seq_num.low);
+
+ if (dtls_RecordGetRecvd(&crSpec->recvdRecords, dtls_seq_num) != 0) {
+ SSL_DBG(("%d: SSL3[%d]: dtls_IsRelevant, rejecting "
+ "potentially replayed packet",
+ SSL_GETPID(), ss->fd));
+ return PR_FALSE;
+ }
+
+ *seqNum = dtls_seq_num;
+ return PR_TRUE;
+}
diff --git a/chromium/net/third_party/nss/ssl/exports_win.def b/chromium/net/third_party/nss/ssl/exports_win.def
deleted file mode 100644
index a1045bb9212..00000000000
--- a/chromium/net/third_party/nss/ssl/exports_win.def
+++ /dev/null
@@ -1,66 +0,0 @@
-; 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.
-
-LIBRARY CRSSL
-EXPORTS
-
-NSS_CmpCertChainWCANames
-NSS_FindCertKEAType
-NSS_GetClientAuthData
-NSS_SetDomesticPolicy
-SSL_AuthCertificate
-SSL_AuthCertificateHook
-SSL_CipherPolicyGet
-SSL_CipherPolicySet
-SSL_CipherPrefGet
-SSL_CipherPrefGetDefault
-SSL_CipherPrefSet
-SSL_CipherPrefSetDefault
-SSL_ClearSessionCache
-SSL_ConfigSecureServer
-SSL_ConfigServerSessionIDCache
-SSL_ForceHandshake
-SSL_GetClientAuthDataHook
-SSL_GetSessionID
-SSL_HandshakeCallback
-SSL_ImportFD
-SSL_InvalidateSession
-SSL_OptionGet
-SSL_OptionGetDefault
-SSL_OptionSet
-SSL_OptionSetDefault
-SSL_PeerCertificate
-SSL_PeerStapledOCSPResponses
-SSL_ResetHandshake
-SSL_SetSockPeerID
-SSL_SetURL
-SSL_GetChannelInfo
-SSL_GetCipherSuiteInfo
-SSL_ShutdownServerSessionIDCache
-SSL_GetImplementedCiphers
-SSL_GetNumImplementedCiphers
-SSL_HandshakeNegotiatedExtension
-SSL_SetNextProtoCallback
-SSL_SetNextProtoNego
-SSL_GetNextProto
-DTLS_GetHandshakeTimeout
-DTLS_ImportFD
-SSL_ExportKeyingMaterial
-SSL_VersionRangeSet
-SSL_GetSRTPCipher
-SSL_SetSRTPCiphers
-SSL_RecommendedCanFalseStart
-SSL_SetCanFalseStartCallback
-
-; Chromium patches
-SSL_PeerCertificateChain
-SSL_SetClientChannelIDCallback
-SSL_GetPlatformClientAuthDataHook
-SSL_HandshakeResumedSession
-SSL_RestartHandshakeAfterChannelIDReq
-SSL_GetChannelBinding
-SSL_PeerSignedCertTimestamps
-SSL_CipherOrderSet
-SSL_CacheSession
-SSL_CacheSessionUnlocked
diff --git a/chromium/net/third_party/nss/ssl/manifest.mn b/chromium/net/third_party/nss/ssl/manifest.mn
index 4d46d46b86b..1366d15e558 100644
--- a/chromium/net/third_party/nss/ssl/manifest.mn
+++ b/chromium/net/third_party/nss/ssl/manifest.mn
@@ -44,6 +44,8 @@ CSRCS = \
cmpcert.c \
sslinfo.c \
ssl3ecc.c \
+ tls13con.c \
+ tls13hkdf.c \
$(NULL)
LIBRARY_NAME = ssl
diff --git a/chromium/net/third_party/nss/ssl/notes.txt b/chromium/net/third_party/nss/ssl/notes.txt
index a71c08ef2a5..cf514ad20f2 100644
--- a/chromium/net/third_party/nss/ssl/notes.txt
+++ b/chromium/net/third_party/nss/ssl/notes.txt
@@ -10,49 +10,49 @@ incoming:
gs = ss->gather
hs = ss->ssl3->hs
-gs->inbuf SSL3 only: incoming (encrypted) ssl records are placed here,
- and then decrypted (or copied) to gs->buf.
+gs->inbuf SSL3 only: incoming (encrypted) ssl records are placed here,
+ and then decrypted (or copied) to gs->buf.
-gs->buf SSL2: incoming SSL records are put here, and then decrypted
- in place.
- SSL3: ssl3_HandleHandshake puts decrypted ssl records here.
+gs->buf SSL2: incoming SSL records are put here, and then decrypted
+ in place.
+ SSL3: ssl3_HandleHandshake puts decrypted ssl records here.
-hs.msg_body (SSL3 only) When an incoming handshake message spans more
- than one ssl record, the first part(s) of it are accumulated
- here until it all arrives.
+hs.msg_body (SSL3 only) When an incoming handshake message spans more
+ than one ssl record, the first part(s) of it are accumulated
+ here until it all arrives.
-hs.msgState (SSL3 only) an alternative set of pointers/lengths for gs->buf.
- Used only when a handleHandshake function returns SECWouldBlock.
- ssl3_HandleHandshake remembers how far it previously got by
- using these pointers instead of gs->buf when it is called
- after a previous SECWouldBlock return.
+hs.msgState (SSL3 only) an alternative set of pointers/lengths for gs->buf.
+ Used only when a handleHandshake function returns SECWouldBlock.
+ ssl3_HandleHandshake remembers how far it previously got by
+ using these pointers instead of gs->buf when it is called
+ after a previous SECWouldBlock return.
---------------------------------------------------------------------------
outgoing:
sec = ss->sec
-ci = ss->sec->ci /* connect info */
+ci = ss->sec->ci /* connect info */
-ci->sendBuf Outgoing handshake messages are appended to this buffer.
- This buffer will then be sent as a single SSL record.
+ci->sendBuf Outgoing handshake messages are appended to this buffer.
+ This buffer will then be sent as a single SSL record.
-sec->writeBuf outgoing ssl records are constructed here and encrypted in
- place before being written or copied to pendingBuf.
+sec->writeBuf outgoing ssl records are constructed here and encrypted in
+ place before being written or copied to pendingBuf.
-ss->pendingBuf contains outgoing ciphertext that was saved after a write
- attempt to the socket failed, e.g. EWouldBlock.
- Generally empty with blocking sockets (should be no incomplete
- writes).
+ss->pendingBuf contains outgoing ciphertext that was saved after a write
+ attempt to the socket failed, e.g. EWouldBlock.
+ Generally empty with blocking sockets (should be no incomplete
+ writes).
-ss->saveBuf Used only by socks code. Intended to be used to buffer
- outgoing data until a socks handshake completes. However,
- this buffer is always empty. There is no code to put
- anything into it.
+ss->saveBuf Used only by socks code. Intended to be used to buffer
+ outgoing data until a socks handshake completes. However,
+ this buffer is always empty. There is no code to put
+ anything into it.
---------------------------------------------------------------------------
-SECWouldBlock means that the function cannot make progress because it is
-waiting for some event OTHER THAN socket I/O completion (e.g. waiting for
+SECWouldBlock means that the function cannot make progress because it is
+waiting for some event OTHER THAN socket I/O completion (e.g. waiting for
user dialog to finish). It is not the same as EWOULDBLOCK.
---------------------------------------------------------------------------
@@ -65,51 +65,51 @@ sendLock ->/
crypto and hash Data that must be protected while turning plaintext into
ciphertext:
-SSL2: (in ssl2_Send*)
- sec->hash*
- sec->hashcx (ptr and data)
- sec->enc
- sec->writecx* (ptr and content)
- sec->sendSecret*(ptr and content)
- sec->sendSequence locked by xmitBufLock
- sec->blockSize
- sec->writeBuf* (ptr & content) locked by xmitBufLock
- "in" locked by xmitBufLock
-
-SSl3: (in ssl3_SendPlainText)
- ss->ssl3 (the pointer)
- ss->ssl3->current_write* (the pointer and the data in the spec
- and any data referenced by the spec.
-
- ss->sec->isServer
- ss->sec->writebuf* (ptr & content) locked by xmitBufLock
- "buf" locked by xmitBufLock
-
-crypto and hash data that must be protected while turning ciphertext into
+SSL2: (in ssl2_Send*)
+ sec->hash*
+ sec->hashcx (ptr and data)
+ sec->enc
+ sec->writecx* (ptr and content)
+ sec->sendSecret*(ptr and content)
+ sec->sendSequence locked by xmitBufLock
+ sec->blockSize
+ sec->writeBuf* (ptr & content) locked by xmitBufLock
+ "in" locked by xmitBufLock
+
+SSl3: (in ssl3_SendPlainText)
+ ss->ssl3 (the pointer)
+ ss->ssl3->current_write* (the pointer and the data in the spec
+ and any data referenced by the spec.
+
+ ss->sec->isServer
+ ss->sec->writebuf* (ptr & content) locked by xmitBufLock
+ "buf" locked by xmitBufLock
+
+crypto and hash data that must be protected while turning ciphertext into
plaintext:
-SSL2: (in ssl2_GatherData)
- gs->* (locked by recvBufLock )
- sec->dec
- sec->readcx
- sec->hash* (ptr and data)
- sec->hashcx (ptr and data)
+SSL2: (in ssl2_GatherData)
+ gs->* (locked by recvBufLock )
+ sec->dec
+ sec->readcx
+ sec->hash* (ptr and data)
+ sec->hashcx (ptr and data)
-SSL3: (in ssl3_HandleRecord )
- ssl3->current_read* (the pointer and all data refernced)
- ss->sec->isServer
+SSL3: (in ssl3_HandleRecord )
+ ssl3->current_read* (the pointer and all data refernced)
+ ss->sec->isServer
Data that must be protected while being used by a "writer":
ss->pendingBuf.*
-ss->saveBuf.* (which is dead)
+ss->saveBuf.* (which is dead)
in ssl3_sendPlainText
ss->ssl3->current_write-> (spec)
ss->sec->writeBuf.*
-ss->sec->isServer
+ss->sec->isServer
in SendBlock
@@ -118,17 +118,17 @@ ss->sec->blockSize
ss->sec->writeBuf.*
ss->sec->sendSecret
ss->sec->sendSequence
-ss->sec->writecx *
+ss->sec->writecx *
ss->pendingBuf
--------------------------------------------------------------------------
-Data variables (not const) protected by the "sslGlobalDataLock".
+Data variables (not const) protected by the "sslGlobalDataLock".
Note, this really should be a reader/writer lock.
-allowedByPolicy sslcon.c
-maybeAllowedByPolicy sslcon.c
-chosenPreference sslcon.c
-policyWasSet sslcon.c
+allowedByPolicy sslcon.c
+maybeAllowedByPolicy sslcon.c
+chosenPreference sslcon.c
+policyWasSet sslcon.c
-cipherSuites[] ssl3con.c
+cipherSuites[] ssl3con.c
diff --git a/chromium/net/third_party/nss/ssl/os2_err.c b/chromium/net/third_party/nss/ssl/os2_err.c
index a69ca91d9ce..6e3d423f49a 100644
--- a/chromium/net/third_party/nss/ssl/os2_err.c
+++ b/chromium/net/third_party/nss/ssl/os2_err.c
@@ -1,12 +1,12 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* This file essentially replicates NSPR's source for the functions that
- * map system-specific error codes to NSPR error codes. We would use
+ * map system-specific error codes to NSPR error codes. We would use
* NSPR's functions, instead of duplicating them, but they're private.
* As long as SSL's server session cache code must do platform native I/O
* to accomplish its job, and NSPR's error mapping functions remain private,
* this code will continue to need to be replicated.
- *
+ *
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@@ -15,7 +15,6 @@
#include "prlog.h"
#include <errno.h>
-
/*
* Based on win32err.c
* OS2TODO Stub everything for now to build. HCT
@@ -24,79 +23,94 @@
/* forward declaration. */
void nss_MD_os2_map_default_error(PRInt32 err);
-void nss_MD_os2_map_opendir_error(PRInt32 err)
+void
+nss_MD_os2_map_opendir_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_closedir_error(PRInt32 err)
+void
+nss_MD_os2_map_closedir_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_readdir_error(PRInt32 err)
+void
+nss_MD_os2_map_readdir_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_delete_error(PRInt32 err)
+void
+nss_MD_os2_map_delete_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
/* The error code for stat() is in errno. */
-void nss_MD_os2_map_stat_error(PRInt32 err)
+void
+nss_MD_os2_map_stat_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_fstat_error(PRInt32 err)
+void
+nss_MD_os2_map_fstat_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_rename_error(PRInt32 err)
+void
+nss_MD_os2_map_rename_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
/* The error code for access() is in errno. */
-void nss_MD_os2_map_access_error(PRInt32 err)
+void
+nss_MD_os2_map_access_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_mkdir_error(PRInt32 err)
+void
+nss_MD_os2_map_mkdir_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_rmdir_error(PRInt32 err)
+void
+nss_MD_os2_map_rmdir_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_read_error(PRInt32 err)
+void
+nss_MD_os2_map_read_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_transmitfile_error(PRInt32 err)
+void
+nss_MD_os2_map_transmitfile_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_write_error(PRInt32 err)
+void
+nss_MD_os2_map_write_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_lseek_error(PRInt32 err)
+void
+nss_MD_os2_map_lseek_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_fsync_error(PRInt32 err)
+void
+nss_MD_os2_map_fsync_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
@@ -104,177 +118,213 @@ void nss_MD_os2_map_fsync_error(PRInt32 err)
/*
* For both CloseHandle() and closesocket().
*/
-void nss_MD_os2_map_close_error(PRInt32 err)
+void
+nss_MD_os2_map_close_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_socket_error(PRInt32 err)
+void
+nss_MD_os2_map_socket_error(PRInt32 err)
{
-// PR_ASSERT(err != WSANOTINITIALISED);
+ // PR_ASSERT(err != WSANOTINITIALISED);
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_recv_error(PRInt32 err)
+void
+nss_MD_os2_map_recv_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_recvfrom_error(PRInt32 err)
+void
+nss_MD_os2_map_recvfrom_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_send_error(PRInt32 err)
+void
+nss_MD_os2_map_send_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
-// case WSAEMSGSIZE: prError = PR_INVALID_ARGUMENT_ERROR; break;
- default: nss_MD_os2_map_default_error(err); return;
+ // case WSAEMSGSIZE: prError = PR_INVALID_ARGUMENT_ERROR; break;
+ default:
+ nss_MD_os2_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_os2_map_sendto_error(PRInt32 err)
+void
+nss_MD_os2_map_sendto_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
-// case WSAEMSGSIZE: prError = PR_INVALID_ARGUMENT_ERROR; break;
- default: nss_MD_os2_map_default_error(err); return;
+ // case WSAEMSGSIZE: prError = PR_INVALID_ARGUMENT_ERROR; break;
+ default:
+ nss_MD_os2_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_os2_map_accept_error(PRInt32 err)
+void
+nss_MD_os2_map_accept_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
-// case WSAEOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break;
-// case WSAEINVAL: prError = PR_INVALID_STATE_ERROR; break;
- default: nss_MD_os2_map_default_error(err); return;
+ // case WSAEOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break;
+ // case WSAEINVAL: prError = PR_INVALID_STATE_ERROR; break;
+ default:
+ nss_MD_os2_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_os2_map_acceptex_error(PRInt32 err)
+void
+nss_MD_os2_map_acceptex_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_connect_error(PRInt32 err)
+void
+nss_MD_os2_map_connect_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
-// case WSAEWOULDBLOCK: prError = PR_IN_PROGRESS_ERROR; break;
-// case WSAEINVAL: prError = PR_ALREADY_INITIATED_ERROR; break;
-// case WSAETIMEDOUT: prError = PR_IO_TIMEOUT_ERROR; break;
- default: nss_MD_os2_map_default_error(err); return;
+ // case WSAEWOULDBLOCK: prError = PR_IN_PROGRESS_ERROR; break;
+ // case WSAEINVAL: prError = PR_ALREADY_INITIATED_ERROR; break;
+ // case WSAETIMEDOUT: prError = PR_IO_TIMEOUT_ERROR; break;
+ default:
+ nss_MD_os2_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_os2_map_bind_error(PRInt32 err)
+void
+nss_MD_os2_map_bind_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
-// case WSAEINVAL: prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR; break;
- default: nss_MD_os2_map_default_error(err); return;
+ // case WSAEINVAL: prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR; break;
+ default:
+ nss_MD_os2_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_os2_map_listen_error(PRInt32 err)
+void
+nss_MD_os2_map_listen_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
-// case WSAEOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break;
-// case WSAEINVAL: prError = PR_INVALID_STATE_ERROR; break;
- default: nss_MD_os2_map_default_error(err); return;
+ // case WSAEOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break;
+ // case WSAEINVAL: prError = PR_INVALID_STATE_ERROR; break;
+ default:
+ nss_MD_os2_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_os2_map_shutdown_error(PRInt32 err)
+void
+nss_MD_os2_map_shutdown_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_getsockname_error(PRInt32 err)
+void
+nss_MD_os2_map_getsockname_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
-// case WSAEINVAL: prError = PR_INVALID_STATE_ERROR; break;
- default: nss_MD_os2_map_default_error(err); return;
+ // case WSAEINVAL: prError = PR_INVALID_STATE_ERROR; break;
+ default:
+ nss_MD_os2_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_os2_map_getpeername_error(PRInt32 err)
+void
+nss_MD_os2_map_getpeername_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_getsockopt_error(PRInt32 err)
+void
+nss_MD_os2_map_getsockopt_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_setsockopt_error(PRInt32 err)
+void
+nss_MD_os2_map_setsockopt_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_open_error(PRInt32 err)
+void
+nss_MD_os2_map_open_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-void nss_MD_os2_map_gethostname_error(PRInt32 err)
+void
+nss_MD_os2_map_gethostname_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
/* Win32 select() only works on sockets. So in this
-** context, WSAENOTSOCK is equivalent to EBADF on Unix.
+** context, WSAENOTSOCK is equivalent to EBADF on Unix.
*/
-void nss_MD_os2_map_select_error(PRInt32 err)
+void
+nss_MD_os2_map_select_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
-// case WSAENOTSOCK: prError = PR_BAD_DESCRIPTOR_ERROR; break;
- default: nss_MD_os2_map_default_error(err); return;
+ // case WSAENOTSOCK: prError = PR_BAD_DESCRIPTOR_ERROR; break;
+ default:
+ nss_MD_os2_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_os2_map_lockf_error(PRInt32 err)
+void
+nss_MD_os2_map_lockf_error(PRInt32 err)
{
nss_MD_os2_map_default_error(err);
}
-
-
-void nss_MD_os2_map_default_error(PRInt32 err)
+void
+nss_MD_os2_map_default_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
-// case ENOENT: prError = PR_FILE_NOT_FOUND_ERROR; break;
-// case ERROR_ACCESS_DENIED: prError = PR_NO_ACCESS_RIGHTS_ERROR; break;
-// case ERROR_ALREADY_EXISTS: prError = PR_FILE_EXISTS_ERROR; break;
-// case ERROR_DISK_CORRUPT: prError = PR_IO_ERROR; break;
-// case ERROR_DISK_FULL: prError = PR_NO_DEVICE_SPACE_ERROR; break;
+// case ENOENT: prError = PR_FILE_NOT_FOUND_ERROR; break;
+// case ERROR_ACCESS_DENIED: prError = PR_NO_ACCESS_RIGHTS_ERROR; break;
+// case ERROR_ALREADY_EXISTS: prError = PR_FILE_EXISTS_ERROR; break;
+// case ERROR_DISK_CORRUPT: prError = PR_IO_ERROR; break;
+// case ERROR_DISK_FULL: prError = PR_NO_DEVICE_SPACE_ERROR; break;
// case ERROR_DISK_OPERATION_FAILED: prError = PR_IO_ERROR; break;
-// case ERROR_DRIVE_LOCKED: prError = PR_FILE_IS_LOCKED_ERROR; break;
+// case ERROR_DRIVE_LOCKED: prError = PR_FILE_IS_LOCKED_ERROR; break;
// case ERROR_FILENAME_EXCED_RANGE: prError = PR_NAME_TOO_LONG_ERROR; break;
-// case ERROR_FILE_CORRUPT: prError = PR_IO_ERROR; break;
-// case ERROR_FILE_EXISTS: prError = PR_FILE_EXISTS_ERROR; break;
-// case ERROR_FILE_INVALID: prError = PR_BAD_DESCRIPTOR_ERROR; break;
+// case ERROR_FILE_CORRUPT: prError = PR_IO_ERROR; break;
+// case ERROR_FILE_EXISTS: prError = PR_FILE_EXISTS_ERROR; break;
+// case ERROR_FILE_INVALID: prError = PR_BAD_DESCRIPTOR_ERROR; break;
#if ERROR_FILE_NOT_FOUND != ENOENT
-// case ERROR_FILE_NOT_FOUND: prError = PR_FILE_NOT_FOUND_ERROR; break;
+// case ERROR_FILE_NOT_FOUND: prError = PR_FILE_NOT_FOUND_ERROR; break;
#endif
- default: prError = PR_UNKNOWN_ERROR; break;
+ default:
+ prError = PR_UNKNOWN_ERROR;
+ break;
}
PR_SetError(prError, err);
}
-
diff --git a/chromium/net/third_party/nss/ssl/os2_err.h b/chromium/net/third_party/nss/ssl/os2_err.h
index 3052d54a7af..15e47411a13 100644
--- a/chromium/net/third_party/nss/ssl/os2_err.h
+++ b/chromium/net/third_party/nss/ssl/os2_err.h
@@ -1,11 +1,11 @@
/*
* This file essentially replicates NSPR's source for the functions that
- * map system-specific error codes to NSPR error codes. We would use
+ * map system-specific error codes to NSPR error codes. We would use
* NSPR's functions, instead of duplicating them, but they're private.
* As long as SSL's server session cache code must do platform native I/O
* to accomplish its job, and NSPR's error mapping functions remain private,
* This code will continue to need to be replicated.
- *
+ *
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
diff --git a/chromium/net/third_party/nss/ssl/preenc.h b/chromium/net/third_party/nss/ssl/preenc.h
index af2475ddd2b..bebff89e22c 100644
--- a/chromium/net/third_party/nss/ssl/preenc.h
+++ b/chromium/net/third_party/nss/ssl/preenc.h
@@ -25,89 +25,89 @@ typedef struct PEFixedKeyHeaderStr PEFixedKeyHeader;
typedef struct PERSAKeyHeaderStr PERSAKeyHeader;
struct PEFortezzaHeaderStr {
- unsigned char key[12];
- unsigned char iv[24];
- unsigned char hash[20];
- unsigned char serial[8];
+ unsigned char key[12];
+ unsigned char iv[24];
+ unsigned char hash[20];
+ unsigned char serial[8];
};
struct PEFortezzaGeneratedHeaderStr {
- unsigned char key[12];
- unsigned char iv[24];
- unsigned char hash[20];
- unsigned char Ra[128];
- unsigned char Y[128];
+ unsigned char key[12];
+ unsigned char iv[24];
+ unsigned char hash[20];
+ unsigned char Ra[128];
+ unsigned char Y[128];
};
struct PEFixedKeyHeaderStr {
- unsigned char pkcs11Mech[4];
- unsigned char labelLen[2];
- unsigned char keyIDLen[2];
- unsigned char ivLen[2];
- unsigned char keyLen[2];
- unsigned char data[1];
+ unsigned char pkcs11Mech[4];
+ unsigned char labelLen[2];
+ unsigned char keyIDLen[2];
+ unsigned char ivLen[2];
+ unsigned char keyLen[2];
+ unsigned char data[1];
};
struct PERSAKeyHeaderStr {
- unsigned char pkcs11Mech[4];
- unsigned char issuerLen[2];
- unsigned char serialLen[2];
- unsigned char ivLen[2];
- unsigned char keyLen[2];
- unsigned char data[1];
+ unsigned char pkcs11Mech[4];
+ unsigned char issuerLen[2];
+ unsigned char serialLen[2];
+ unsigned char ivLen[2];
+ unsigned char keyLen[2];
+ unsigned char data[1];
};
#define PEFIXED_Label(header) (header->data)
#define PEFIXED_KeyID(header) (&header->data[GetInt2(header->labelLen)])
-#define PEFIXED_IV(header) (&header->data[GetInt2(header->labelLen)\
- +GetInt2(header->keyIDLen)])
-#define PEFIXED_Key(header) (&header->data[GetInt2(header->labelLen)\
- +GetInt2(header->keyIDLen)+GetInt2(header->keyLen)])
+#define PEFIXED_IV(header) (&header->data[GetInt2(header->labelLen) + \
+ GetInt2(header->keyIDLen)])
+#define PEFIXED_Key(header) (&header->data[GetInt2(header->labelLen) + \
+ GetInt2(header->keyIDLen) + \
+ GetInt2(header->keyLen)])
#define PERSA_Issuer(header) (header->data)
#define PERSA_Serial(header) (&header->data[GetInt2(header->issuerLen)])
-#define PERSA_IV(header) (&header->data[GetInt2(header->issuerLen)\
- +GetInt2(header->serialLen)])
-#define PERSA_Key(header) (&header->data[GetInt2(header->issuerLen)\
- +GetInt2(header->serialLen)+GetInt2(header->keyLen)])
+#define PERSA_IV(header) (&header->data[GetInt2(header->issuerLen) + \
+ GetInt2(header->serialLen)])
+#define PERSA_Key(header) (&header->data[GetInt2(header->issuerLen) + \
+ GetInt2(header->serialLen) + \
+ GetInt2(header->keyLen)])
struct PEHeaderStr {
- unsigned char magic [2];
- unsigned char len [2];
- unsigned char type [2];
- unsigned char version[2];
+ unsigned char magic[2];
+ unsigned char len[2];
+ unsigned char type[2];
+ unsigned char version[2];
union {
- PEFortezzaHeader fortezza;
+ PEFortezzaHeader fortezza;
PEFortezzaGeneratedHeader g_fortezza;
- PEFixedKeyHeader fixed;
- PERSAKeyHeader rsa;
+ PEFixedKeyHeader fixed;
+ PERSAKeyHeader rsa;
} u;
};
#define PE_CRYPT_INTRO_LEN 8
#define PE_INTRO_LEN 4
-#define PE_BASE_HEADER_LEN 8
-
-#define PRE_BLOCK_SIZE 8
+#define PE_BASE_HEADER_LEN 8
+#define PRE_BLOCK_SIZE 8
#define GetInt2(c) ((c[0] << 8) | c[1])
-#define GetInt4(c) (((unsigned long)c[0] << 24)|((unsigned long)c[1] << 16)\
- |((unsigned long)c[2] << 8)| ((unsigned long)c[3]))
-#define PutInt2(c,i) ((c[1] = (i) & 0xff), (c[0] = ((i) >> 8) & 0xff))
-#define PutInt4(c,i) ((c[0]=((i) >> 24) & 0xff),(c[1]=((i) >> 16) & 0xff),\
- (c[2] = ((i) >> 8) & 0xff), (c[3] = (i) & 0xff))
-
-#define PRE_MAGIC 0xc0de
-#define PRE_VERSION 0x1010
-#define PRE_FORTEZZA_FILE 0x00ff
-#define PRE_FORTEZZA_STREAM 0x00f5
-#define PRE_FORTEZZA_GEN_STREAM 0x00f6
-#define PRE_FIXED_FILE 0x000f
-#define PRE_RSA_FILE 0x001f
-#define PRE_FIXED_STREAM 0x0005
+#define GetInt4(c) (((unsigned long)c[0] << 24) | ((unsigned long)c[1] << 16) | \
+ ((unsigned long)c[2] << 8) | ((unsigned long)c[3]))
+#define PutInt2(c, i) ((c[1] = (i)&0xff), (c[0] = ((i) >> 8) & 0xff))
+#define PutInt4(c, i) ((c[0] = ((i) >> 24) & 0xff), (c[1] = ((i) >> 16) & 0xff), \
+ (c[2] = ((i) >> 8) & 0xff), (c[3] = (i)&0xff))
+
+#define PRE_MAGIC 0xc0de
+#define PRE_VERSION 0x1010
+#define PRE_FORTEZZA_FILE 0x00ff
+#define PRE_FORTEZZA_STREAM 0x00f5
+#define PRE_FORTEZZA_GEN_STREAM 0x00f6
+#define PRE_FIXED_FILE 0x000f
+#define PRE_RSA_FILE 0x001f
+#define PRE_FIXED_STREAM 0x0005
PEHeader *SSL_PreencryptedStreamToFile(PRFileDesc *fd, PEHeader *,
- int *headerSize);
+ int *headerSize);
PEHeader *SSL_PreencryptedFileToStream(PRFileDesc *fd, PEHeader *,
- int *headerSize);
-
+ int *headerSize);
diff --git a/chromium/net/third_party/nss/ssl/prelib.c b/chromium/net/third_party/nss/ssl/prelib.c
index a15174a31b1..4db9ffe699d 100644
--- a/chromium/net/third_party/nss/ssl/prelib.c
+++ b/chromium/net/third_party/nss/ssl/prelib.c
@@ -17,18 +17,18 @@
#include "preenc.h"
#include "pk11func.h"
-PEHeader *SSL_PreencryptedStreamToFile(PRFileDesc *fd, PEHeader *inHeader,
- int *headerSize)
+PEHeader *
+SSL_PreencryptedStreamToFile(PRFileDesc *fd, PEHeader *inHeader,
+ int *headerSize)
{
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
return NULL;
}
-PEHeader *SSL_PreencryptedFileToStream(PRFileDesc *fd, PEHeader *header,
- int *headerSize)
+PEHeader *
+SSL_PreencryptedFileToStream(PRFileDesc *fd, PEHeader *header,
+ int *headerSize)
{
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
return NULL;
}
-
-
diff --git a/chromium/net/third_party/nss/ssl/ssl.h b/chromium/net/third_party/nss/ssl/ssl.h
index bc417a5e4be..de5078b6783 100644
--- a/chromium/net/third_party/nss/ssl/ssl.h
+++ b/chromium/net/third_party/nss/ssl/ssl.h
@@ -15,7 +15,7 @@
#include "cert.h"
#include "keyt.h"
-#include "sslt.h" /* public ssl data types */
+#include "sslt.h" /* public ssl data types */
#if defined(_WIN32) && !defined(IN_LIBSSL) && !defined(NSS_USE_STATIC_LIBS)
#define SSL_IMPORT extern __declspec(dllimport)
@@ -38,7 +38,7 @@ SSL_IMPORT const PRUint16 SSL_NumImplementedCiphers;
SSL_IMPORT PRUint16 SSL_GetNumImplementedCiphers(void);
/* Macro to tell which ciphers in table are SSL2 vs SSL3/TLS. */
-#define SSL_IS_SSL2_CIPHER(which) (((which) & 0xfff0) == 0xff00)
+#define SSL_IS_SSL2_CIPHER(which) (((which)&0xfff0) == 0xff00)
/*
** Imports fd into SSL, returning a new socket. Copies SSL configuration
@@ -55,72 +55,72 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
/*
** Enable/disable an ssl mode
**
-** SSL_SECURITY:
-** enable/disable use of SSL security protocol before connect
+** SSL_SECURITY:
+** enable/disable use of SSL security protocol before connect
**
-** SSL_SOCKS:
-** enable/disable use of socks before connect
-** (No longer supported).
+** SSL_SOCKS:
+** enable/disable use of socks before connect
+** (No longer supported).
**
-** SSL_REQUEST_CERTIFICATE:
-** require a certificate during secure connect
+** SSL_REQUEST_CERTIFICATE:
+** require a certificate during secure connect
*/
/* options */
-#define SSL_SECURITY 1 /* (on by default) */
-#define SSL_SOCKS 2 /* (off by default) */
-#define SSL_REQUEST_CERTIFICATE 3 /* (off by default) */
-#define SSL_HANDSHAKE_AS_CLIENT 5 /* force accept to hs as client */
- /* (off by default) */
-#define SSL_HANDSHAKE_AS_SERVER 6 /* force connect to hs as server */
- /* (off by default) */
+#define SSL_SECURITY 1 /* (on by default) */
+#define SSL_SOCKS 2 /* (off by default) */
+#define SSL_REQUEST_CERTIFICATE 3 /* (off by default) */
+#define SSL_HANDSHAKE_AS_CLIENT 5 /* force accept to hs as client */
+ /* (off by default) */
+#define SSL_HANDSHAKE_AS_SERVER 6 /* force connect to hs as server */
+ /* (off by default) */
/* OBSOLETE: SSL v2 is obsolete and may be removed soon. */
-#define SSL_ENABLE_SSL2 7 /* enable ssl v2 (off by default) */
+#define SSL_ENABLE_SSL2 7 /* enable ssl v2 (off by default) */
/* OBSOLETE: See "SSL Version Range API" below for the replacement and a
** description of the non-obvious semantics of using SSL_ENABLE_SSL3.
*/
-#define SSL_ENABLE_SSL3 8 /* enable ssl v3 (on by default) */
+#define SSL_ENABLE_SSL3 8 /* enable ssl v3 (on by default) */
-#define SSL_NO_CACHE 9 /* don't use the session cache */
- /* (off by default) */
-#define SSL_REQUIRE_CERTIFICATE 10 /* (SSL_REQUIRE_FIRST_HANDSHAKE */
- /* by default) */
-#define SSL_ENABLE_FDX 11 /* permit simultaneous read/write */
- /* (off by default) */
+#define SSL_NO_CACHE 9 /* don't use the session cache */
+ /* (off by default) */
+#define SSL_REQUIRE_CERTIFICATE 10 /* (SSL_REQUIRE_FIRST_HANDSHAKE */
+ /* by default) */
+#define SSL_ENABLE_FDX 11 /* permit simultaneous read/write */
+ /* (off by default) */
/* OBSOLETE: SSL v2 compatible hellos are not accepted by some TLS servers
** and cannot negotiate extensions. SSL v2 is obsolete. This option may be
** removed soon.
*/
-#define SSL_V2_COMPATIBLE_HELLO 12 /* send v3 client hello in v2 fmt */
- /* (off by default) */
+#define SSL_V2_COMPATIBLE_HELLO 12 /* send v3 client hello in v2 fmt */
+ /* (off by default) */
/* OBSOLETE: See "SSL Version Range API" below for the replacement and a
** description of the non-obvious semantics of using SSL_ENABLE_TLS.
*/
-#define SSL_ENABLE_TLS 13 /* enable TLS (on by default) */
-
-#define SSL_ROLLBACK_DETECTION 14 /* for compatibility, default: on */
-#define SSL_NO_STEP_DOWN 15 /* Disable export cipher suites */
- /* if step-down keys are needed. */
- /* default: off, generate */
- /* step-down keys if needed. */
-#define SSL_BYPASS_PKCS11 16 /* use PKCS#11 for pub key only */
-#define SSL_NO_LOCKS 17 /* Don't use locks for protection */
-#define SSL_ENABLE_SESSION_TICKETS 18 /* Enable TLS SessionTicket */
- /* extension (off by default) */
-#define SSL_ENABLE_DEFLATE 19 /* Enable TLS compression with */
- /* DEFLATE (off by default) */
-#define SSL_ENABLE_RENEGOTIATION 20 /* Values below (default: never) */
-#define SSL_REQUIRE_SAFE_NEGOTIATION 21 /* Peer must send Signaling */
- /* Cipher Suite Value (SCSV) or */
- /* Renegotiation Info (RI) */
- /* extension in ALL handshakes. */
- /* default: off */
-#define SSL_ENABLE_FALSE_START 22 /* Enable SSL false start (off by */
- /* default, applies only to */
- /* clients). False start is a */
+#define SSL_ENABLE_TLS 13 /* enable TLS (on by default) */
+
+#define SSL_ROLLBACK_DETECTION 14 /* for compatibility, default: on */
+#define SSL_NO_STEP_DOWN 15 /* Disable export cipher suites */
+ /* if step-down keys are needed. */
+ /* default: off, generate */
+ /* step-down keys if needed. */
+#define SSL_BYPASS_PKCS11 16 /* use PKCS#11 for pub key only */
+#define SSL_NO_LOCKS 17 /* Don't use locks for protection */
+#define SSL_ENABLE_SESSION_TICKETS 18 /* Enable TLS SessionTicket */
+ /* extension (off by default) */
+#define SSL_ENABLE_DEFLATE 19 /* Enable TLS compression with */
+ /* DEFLATE (off by default) */
+#define SSL_ENABLE_RENEGOTIATION 20 /* Values below (default: never) */
+#define SSL_REQUIRE_SAFE_NEGOTIATION 21 /* Peer must send Signaling */
+ /* Cipher Suite Value (SCSV) or */
+ /* Renegotiation Info (RI) */
+ /* extension in ALL handshakes. */
+ /* default: off */
+#define SSL_ENABLE_FALSE_START 22 /* Enable SSL false start (off by */
+ /* default, applies only to */
+ /* clients). False start is a */
/* mode where an SSL client will start sending application data before
* verifying the server's Finished message. This means that we could end up
* sending data to an imposter. However, the data will be encrypted and
@@ -160,7 +160,7 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
* accept fragmented alerts).
*/
#define SSL_CBC_RANDOM_IV 23
-#define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */
+#define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */
/* SSL_ENABLE_NPN controls whether the NPN extension is enabled for the initial
* handshake when application layer protocol negotiation is used.
@@ -189,8 +189,8 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
*/
#define SSL_REUSE_SERVER_ECDHE_KEY 27
-#define SSL_ENABLE_FALLBACK_SCSV 28 /* Send fallback SCSV in
- * handshakes. */
+#define SSL_ENABLE_FALLBACK_SCSV 28 /* Send fallback SCSV in \
+ * handshakes. */
/* SSL_ENABLE_SERVER_DHE controls whether DHE is enabled for the server socket.
*/
@@ -206,7 +206,7 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
/* Request Signed Certificate Timestamps via TLS extension (client) */
#define SSL_ENABLE_SIGNED_CERT_TIMESTAMPS 31
-#ifdef SSL_DEPRECATED_FUNCTION
+#ifdef SSL_DEPRECATED_FUNCTION
/* Old deprecated function names */
SSL_IMPORT SECStatus SSL_Enable(PRFileDesc *fd, int option, PRBool on);
SSL_IMPORT SECStatus SSL_EnableDefault(int option, PRBool on);
@@ -229,13 +229,13 @@ SSL_IMPORT SECStatus SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHan
*
* The callback must return SECFailure or SECSuccess (not SECWouldBlock).
*/
-typedef SECStatus (PR_CALLBACK *SSLNextProtoCallback)(
+typedef SECStatus(PR_CALLBACK *SSLNextProtoCallback)(
void *arg,
PRFileDesc *fd,
- const unsigned char* protos,
+ const unsigned char *protos,
unsigned int protosLen,
- unsigned char* protoOut,
- unsigned int* protoOutLen,
+ unsigned char *protoOut,
+ unsigned int *protoOutLen,
unsigned int protoMaxOut);
/* SSL_SetNextProtoCallback sets a callback function to handle Next Protocol
@@ -263,14 +263,14 @@ SSL_IMPORT SECStatus SSL_SetNextProtoCallback(PRFileDesc *fd,
* The supported protocols are specified in |data| in wire-format (8-bit
* length-prefixed). For example: "\010http/1.1\006spdy/2". */
SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd,
- const unsigned char *data,
- unsigned int length);
-
-typedef enum SSLNextProtoState {
- SSL_NEXT_PROTO_NO_SUPPORT = 0, /* No peer support */
- SSL_NEXT_PROTO_NEGOTIATED = 1, /* Mutual agreement */
- SSL_NEXT_PROTO_NO_OVERLAP = 2, /* No protocol overlap found */
- SSL_NEXT_PROTO_SELECTED = 3 /* Server selected proto (ALPN) */
+ const unsigned char *data,
+ unsigned int length);
+
+typedef enum SSLNextProtoState {
+ SSL_NEXT_PROTO_NO_SUPPORT = 0, /* No peer support */
+ SSL_NEXT_PROTO_NEGOTIATED = 1, /* Mutual agreement */
+ SSL_NEXT_PROTO_NO_OVERLAP = 2, /* No protocol overlap found */
+ SSL_NEXT_PROTO_SELECTED = 3 /* Server selected proto (ALPN) */
} SSLNextProtoState;
/* SSL_GetNextProto can be used in the HandshakeCallback or any time after
@@ -281,19 +281,19 @@ typedef enum SSLNextProtoState {
* returned. Otherwise, the negotiated protocol, if any, is written into buf,
* and SECSuccess is returned. */
SSL_IMPORT SECStatus SSL_GetNextProto(PRFileDesc *fd,
- SSLNextProtoState *state,
- unsigned char *buf,
- unsigned int *bufLen,
- unsigned int bufLenMax);
+ SSLNextProtoState *state,
+ unsigned char *buf,
+ unsigned int *bufLen,
+ unsigned int bufLenMax);
/*
** Control ciphers that SSL uses. If on is non-zero then the named cipher
-** is enabled, otherwise it is disabled.
+** is enabled, otherwise it is disabled.
** The "cipher" values are defined in sslproto.h (the SSL_EN_* values).
** EnableCipher records user preferences.
** SetPolicy sets the policy according to the policy module.
*/
-#ifdef SSL_DEPRECATED_FUNCTION
+#ifdef SSL_DEPRECATED_FUNCTION
/* Old deprecated function names */
SSL_IMPORT SECStatus SSL_EnableCipher(long which, PRBool enabled);
SSL_IMPORT SECStatus SSL_SetPolicy(long which, int policy);
@@ -410,10 +410,10 @@ typedef enum SSLChannelBindingType {
*
* This call will fail if made during a renegotiation. */
SSL_IMPORT SECStatus SSL_GetChannelBinding(PRFileDesc *fd,
- SSLChannelBindingType binding_type,
- unsigned char *out,
- unsigned int *outLen,
- unsigned int outLenMax);
+ SSLChannelBindingType binding_type,
+ unsigned char *out,
+ unsigned int *outLen,
+ unsigned int outLenMax);
/* SSL Version Range API
**
@@ -479,34 +479,46 @@ SSL_IMPORT SECStatus SSL_VersionRangeSetDefault(
/* Returns, in |*vrange|, the range of enabled SSL3/TLS versions for |fd|. */
SSL_IMPORT SECStatus SSL_VersionRangeGet(PRFileDesc *fd,
- SSLVersionRange *vrange);
+ SSLVersionRange *vrange);
/* Sets the range of enabled SSL3/TLS versions for |fd| to |*vrange|. */
SSL_IMPORT SECStatus SSL_VersionRangeSet(PRFileDesc *fd,
- const SSLVersionRange *vrange);
-
+ const SSLVersionRange *vrange);
+
+/* Sets the version to check the server random against for the
+ * fallback check defined in [draft-ietf-tls-tls13-11 Section 6.3.1.1].
+ * This function is provided to allow for detection of forced downgrade
+ * attacks against client-side reconnect-and-fallback outside of TLS
+ * by setting |version| to be that of the original connection, rather
+ * than that of the new connection.
+ *
+ * The default, which can also be enabled by setting |version| to
+ * zero, is just to check against the max version in the
+ * version range (see SSL_VersionRangeSet). */
+SSL_IMPORT SECStatus SSL_SetDowngradeCheckVersion(PRFileDesc *fd,
+ PRUint16 version);
/* Values for "policy" argument to SSL_CipherPolicySet */
/* Values returned by SSL_CipherPolicyGet. */
-#define SSL_NOT_ALLOWED 0 /* or invalid or unimplemented */
-#define SSL_ALLOWED 1
-#define SSL_RESTRICTED 2 /* only with "Step-Up" certs. */
+#define SSL_NOT_ALLOWED 0 /* or invalid or unimplemented */
+#define SSL_ALLOWED 1
+#define SSL_RESTRICTED 2 /* only with "Step-Up" certs. */
/* Values for "on" with SSL_REQUIRE_CERTIFICATE. */
-#define SSL_REQUIRE_NEVER ((PRBool)0)
-#define SSL_REQUIRE_ALWAYS ((PRBool)1)
+#define SSL_REQUIRE_NEVER ((PRBool)0)
+#define SSL_REQUIRE_ALWAYS ((PRBool)1)
#define SSL_REQUIRE_FIRST_HANDSHAKE ((PRBool)2)
-#define SSL_REQUIRE_NO_ERROR ((PRBool)3)
+#define SSL_REQUIRE_NO_ERROR ((PRBool)3)
/* Values for "on" with SSL_ENABLE_RENEGOTIATION */
/* Never renegotiate at all. */
-#define SSL_RENEGOTIATE_NEVER ((PRBool)0)
+#define SSL_RENEGOTIATE_NEVER ((PRBool)0)
/* Renegotiate without restriction, whether or not the peer's client hello */
/* bears the renegotiation info extension. Vulnerable, as in the past. */
#define SSL_RENEGOTIATE_UNRESTRICTED ((PRBool)1)
/* Only renegotiate if the peer's hello bears the TLS renegotiation_info */
/* extension. This is safe renegotiation. */
-#define SSL_RENEGOTIATE_REQUIRES_XTN ((PRBool)2)
+#define SSL_RENEGOTIATE_REQUIRES_XTN ((PRBool)2)
/* Disallow unsafe renegotiation in server sockets only, but allow clients */
/* to continue to renegotiate with vulnerable servers. */
/* This value should only be used during the transition period when few */
@@ -533,9 +545,9 @@ SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd,
PRIntervalTime timeout);
SSL_IMPORT SECStatus SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd,
- CERTCertificate *cert,
- SECKEYPrivateKey *key,
- CERTCertificateList *certChain);
+ CERTCertificate *cert,
+ SECKEYPrivateKey *key,
+ CERTCertificateList *certChain);
/*
** Query security status of socket. *on is set to one if security is
@@ -549,22 +561,22 @@ SSL_IMPORT SECStatus SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd,
** by the caller, and need to be freed with PORT_Free.
*/
SSL_IMPORT SECStatus SSL_SecurityStatus(PRFileDesc *fd, int *on, char **cipher,
- int *keySize, int *secretKeySize,
- char **issuer, char **subject);
+ int *keySize, int *secretKeySize,
+ char **issuer, char **subject);
/* Values for "on" */
-#define SSL_SECURITY_STATUS_NOOPT -1
-#define SSL_SECURITY_STATUS_OFF 0
-#define SSL_SECURITY_STATUS_ON_HIGH 1
-#define SSL_SECURITY_STATUS_ON_LOW 2
-#define SSL_SECURITY_STATUS_FORTEZZA 3 /* NO LONGER SUPPORTED */
+#define SSL_SECURITY_STATUS_NOOPT -1
+#define SSL_SECURITY_STATUS_OFF 0
+#define SSL_SECURITY_STATUS_ON_HIGH 1
+#define SSL_SECURITY_STATUS_ON_LOW 2
+#define SSL_SECURITY_STATUS_FORTEZZA 3 /* NO LONGER SUPPORTED */
/*
** Return the certificate for our SSL peer. If the client calls this
** it will always return the server's certificate. If the server calls
** this, it may return NULL if client authentication is not enabled or
** if the client had no certificate when asked.
-** "fd" the socket "file" descriptor
+** "fd" the socket "file" descriptor
*/
SSL_IMPORT CERTCertificate *SSL_PeerCertificate(PRFileDesc *fd);
@@ -573,7 +585,7 @@ SSL_IMPORT CERTCertificate *SSL_PeerCertificate(PRFileDesc *fd);
** did not present certificates, return NULL with the
** SSL_ERROR_NO_CERTIFICATE error. On failure, return NULL with an error
** code other than SSL_ERROR_NO_CERTIFICATE.
-** "fd" the socket "file" descriptor
+** "fd" the socket "file" descriptor
*/
SSL_IMPORT CERTCertList *SSL_PeerCertificateChain(PRFileDesc *fd);
@@ -593,7 +605,7 @@ SSL_IMPORT CERTCertList *SSL_PeerCertificateChain(PRFileDesc *fd);
* authenticate certificate hook, SSL_AuthCertificate, does not implement
* any OCSP stapling funtionality, but this may change in future versions.
*/
-SSL_IMPORT const SECItemArray * SSL_PeerStapledOCSPResponses(PRFileDesc *fd);
+SSL_IMPORT const SECItemArray *SSL_PeerStapledOCSPResponses(PRFileDesc *fd);
/* SSL_PeerSignedCertTimestamps returns the signed_certificate_timestamp
* extension data provided by the TLS server. The return value is a pointer
@@ -610,7 +622,7 @@ SSL_IMPORT const SECItemArray * SSL_PeerStapledOCSPResponses(PRFileDesc *fd);
*
* libssl does not do any parsing or validation of the response itself.
*/
-SSL_IMPORT const SECItem * SSL_PeerSignedCertTimestamps(PRFileDesc *fd);
+SSL_IMPORT const SECItem *SSL_PeerSignedCertTimestamps(PRFileDesc *fd);
/* SSL_SetStapledOCSPResponses stores an array of one or multiple OCSP responses
* in the fd's data, which may be sent as part of a server side cert_status
@@ -620,7 +632,19 @@ SSL_IMPORT const SECItem * SSL_PeerSignedCertTimestamps(PRFileDesc *fd);
*/
SSL_IMPORT SECStatus
SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses,
- SSLKEAType kea);
+ SSLKEAType kea);
+
+/*
+ * SSL_SetSignedCertTimestamps stores serialized signed_certificate_timestamp
+ * extension data in the fd. The signed_certificate_timestamp data is sent
+ * during the handshake (if requested by the client). Parameter |scts|
+ * is for the server certificate of the key exchange type |kea|.
+ * The function will duplicate the provided data item. To clear previously
+ * set data for a given key exchange type |kea|, pass NULL to |scts|.
+ */
+SSL_IMPORT SECStatus
+SSL_SetSignedCertTimestamps(PRFileDesc *fd, const SECItem *scts,
+ SSLKEAType kea);
/*
** Authenticate certificate hook. Called when a certificate comes in
@@ -653,83 +677,40 @@ SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses,
** Consequently, the current version of libssl does not ever send the
** bad_certificate_status_response alert. This may change in future releases.
*/
-typedef SECStatus (PR_CALLBACK *SSLAuthCertificate)(void *arg, PRFileDesc *fd,
- PRBool checkSig,
- PRBool isServer);
+typedef SECStatus(PR_CALLBACK *SSLAuthCertificate)(void *arg, PRFileDesc *fd,
+ PRBool checkSig,
+ PRBool isServer);
-SSL_IMPORT SECStatus SSL_AuthCertificateHook(PRFileDesc *fd,
- SSLAuthCertificate f,
- void *arg);
+SSL_IMPORT SECStatus SSL_AuthCertificateHook(PRFileDesc *fd,
+ SSLAuthCertificate f,
+ void *arg);
/* An implementation of the certificate authentication hook */
-SSL_IMPORT SECStatus SSL_AuthCertificate(void *arg, PRFileDesc *fd,
- PRBool checkSig, PRBool isServer);
+SSL_IMPORT SECStatus SSL_AuthCertificate(void *arg, PRFileDesc *fd,
+ PRBool checkSig, PRBool isServer);
/*
* Prototype for SSL callback to get client auth data from the application.
- * arg - application passed argument
- * caNames - pointer to distinguished names of CAs that the server likes
- * pRetCert - pointer to pointer to cert, for return of cert
- * pRetKey - pointer to key pointer, for return of key
+ * arg - application passed argument
+ * caNames - pointer to distinguished names of CAs that the server likes
+ * pRetCert - pointer to pointer to cert, for return of cert
+ * pRetKey - pointer to key pointer, for return of key
*/
-typedef SECStatus (PR_CALLBACK *SSLGetClientAuthData)(void *arg,
- PRFileDesc *fd,
- CERTDistNames *caNames,
- CERTCertificate **pRetCert,/*return */
- SECKEYPrivateKey **pRetKey);/* return */
+typedef SECStatus(PR_CALLBACK *SSLGetClientAuthData)(void *arg,
+ PRFileDesc *fd,
+ CERTDistNames *caNames,
+ CERTCertificate **pRetCert, /*return */
+ SECKEYPrivateKey **pRetKey); /* return */
/*
* Set the client side callback for SSL to retrieve user's private key
* and certificate.
- * fd - the file descriptor for the connection in question
- * f - the application's callback that delivers the key and cert
- * a - application specific data
+ * fd - the file descriptor for the connection in question
+ * f - the application's callback that delivers the key and cert
+ * a - application specific data
*/
-SSL_IMPORT SECStatus SSL_GetClientAuthDataHook(PRFileDesc *fd,
- SSLGetClientAuthData f, void *a);
-
-/*
- * Prototype for SSL callback to get client auth data from the application,
- * optionally using the underlying platform's cryptographic primitives.
- * To use the platform cryptographic primitives, caNames and pRetCerts
- * should be set. To use NSS, pRetNSSCert and pRetNSSKey should be set.
- * Returning SECFailure will cause the socket to send no client certificate.
- * arg - application passed argument
- * caNames - pointer to distinguished names of CAs that the server likes
- * pRetCerts - pointer to pointer to list of certs, with the first being
- * the client cert, and any following being used for chain
- * building
- * pRetKey - pointer to native key pointer, for return of key
- * - Windows: A pointer to a PCERT_KEY_CONTEXT that was allocated
- * via PORT_Alloc(). Ownership of the PCERT_KEY_CONTEXT
- * is transferred to NSS, which will free via
- * PORT_Free().
- * - Mac OS X: A pointer to a SecKeyRef. Ownership is
- * transferred to NSS, which will free via CFRelease().
- * pRetNSSCert - pointer to pointer to NSS cert, for return of cert.
- * pRetNSSKey - pointer to NSS key pointer, for return of key.
- */
-typedef SECStatus (PR_CALLBACK *SSLGetPlatformClientAuthData)(void *arg,
- PRFileDesc *fd,
- CERTDistNames *caNames,
- CERTCertList **pRetCerts,/*return */
- void **pRetKey,/* return */
- CERTCertificate **pRetNSSCert,/*return */
- SECKEYPrivateKey **pRetNSSKey);/* return */
-
-/*
- * Set the client side callback for SSL to retrieve user's private key
- * and certificate.
- * Note: If a platform client auth callback is set, the callback configured by
- * SSL_GetClientAuthDataHook, if any, will not be called.
- *
- * fd - the file descriptor for the connection in question
- * f - the application's callback that delivers the key and cert
- * a - application specific data
- */
-SSL_IMPORT SECStatus
-SSL_GetPlatformClientAuthDataHook(PRFileDesc *fd,
- SSLGetPlatformClientAuthData f, void *a);
+SSL_IMPORT SECStatus SSL_GetClientAuthDataHook(PRFileDesc *fd,
+ SSLGetClientAuthData f, void *a);
/*
** SNI extension processing callback function.
@@ -757,10 +738,10 @@ SSL_GetPlatformClientAuthDataHook(PRFileDesc *fd,
** send an "unrecognized_name" alert if SNI extension name list contains more
** then one name of a type.
*/
-typedef PRInt32 (PR_CALLBACK *SSLSNISocketConfig)(PRFileDesc *fd,
- const SECItem *srvNameArr,
- PRUint32 srvNameArrSize,
- void *arg);
+typedef PRInt32(PR_CALLBACK *SSLSNISocketConfig)(PRFileDesc *fd,
+ const SECItem *srvNameArr,
+ PRUint32 srvNameArrSize,
+ void *arg);
/*
** SSLSNISocketConfig should return an index within 0 and srvNameArrSize-1
@@ -769,13 +750,13 @@ typedef PRInt32 (PR_CALLBACK *SSLSNISocketConfig)(PRFileDesc *fd,
** tells libSSL to use the default cert and key. The other tells libSSL
** to send the "unrecognized_name" alert. These values are:
**/
-#define SSL_SNI_CURRENT_CONFIG_IS_USED -1
-#define SSL_SNI_SEND_ALERT -2
+#define SSL_SNI_CURRENT_CONFIG_IS_USED -1
+#define SSL_SNI_SEND_ALERT -2
/*
** Set application implemented SNISocketConfig callback.
*/
-SSL_IMPORT SECStatus SSL_SNISocketConfigHook(PRFileDesc *fd,
+SSL_IMPORT SECStatus SSL_SNISocketConfigHook(PRFileDesc *fd,
SSLSNISocketConfig f,
void *arg);
@@ -788,8 +769,8 @@ SSL_IMPORT PRFileDesc *SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd);
/*
* Set the client side argument for SSL to retrieve PKCS #11 pin.
- * fd - the file descriptor for the connection in question
- * a - pkcs11 application specific data
+ * fd - the file descriptor for the connection in question
+ * a - pkcs11 application specific data
*/
SSL_IMPORT SECStatus SSL_SetPKCS11PinArg(PRFileDesc *fd, void *a);
@@ -808,9 +789,9 @@ SSL_IMPORT SECStatus SSL_SetPKCS11PinArg(PRFileDesc *fd, void *a);
** about the asynchronous behavior that occurs when the bad cert hook returns
** SECWouldBlock.
*/
-typedef SECStatus (PR_CALLBACK *SSLBadCertHandler)(void *arg, PRFileDesc *fd);
-SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f,
- void *arg);
+typedef SECStatus(PR_CALLBACK *SSLBadCertHandler)(void *arg, PRFileDesc *fd);
+SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f,
+ void *arg);
/*
** Configure SSL socket for running a secure server. Needs the
@@ -818,8 +799,8 @@ SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f,
** are copied.
*/
SSL_IMPORT SECStatus SSL_ConfigSecureServer(
- PRFileDesc *fd, CERTCertificate *cert,
- SECKEYPrivateKey *key, SSLKEAType kea);
+ PRFileDesc *fd, CERTCertificate *cert,
+ SECKEYPrivateKey *key, SSLKEAType kea);
/*
** Allows SSL socket configuration with caller-supplied certificate chain.
@@ -833,63 +814,63 @@ SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert,
/*
** Configure a secure server's session-id cache. Define the maximum number
** of entries in the cache, the longevity of the entires, and the directory
-** where the cache files will be placed. These values can be zero, and
+** where the cache files will be placed. These values can be zero, and
** if so, the implementation will choose defaults.
-** This version of the function is for use in applications that have only one
+** This version of the function is for use in applications that have only one
** process that uses the cache (even if that process has multiple threads).
*/
-SSL_IMPORT SECStatus SSL_ConfigServerSessionIDCache(int maxCacheEntries,
- PRUint32 timeout,
- PRUint32 ssl3_timeout,
- const char * directory);
+SSL_IMPORT SECStatus SSL_ConfigServerSessionIDCache(int maxCacheEntries,
+ PRUint32 timeout,
+ PRUint32 ssl3_timeout,
+ const char *directory);
/* Configure a secure server's session-id cache. Depends on value of
* enableMPCache, configures malti-proc or single proc cache. */
SSL_IMPORT SECStatus SSL_ConfigServerSessionIDCacheWithOpt(
- PRUint32 timeout,
- PRUint32 ssl3_timeout,
- const char * directory,
- int maxCacheEntries,
- int maxCertCacheEntries,
- int maxSrvNameCacheEntries,
- PRBool enableMPCache);
+ PRUint32 timeout,
+ PRUint32 ssl3_timeout,
+ const char *directory,
+ int maxCacheEntries,
+ int maxCertCacheEntries,
+ int maxSrvNameCacheEntries,
+ PRBool enableMPCache);
/*
** Like SSL_ConfigServerSessionIDCache, with one important difference.
-** If the application will run multiple processes (as opposed to, or in
+** If the application will run multiple processes (as opposed to, or in
** addition to multiple threads), then it must call this function, instead
** of calling SSL_ConfigServerSessionIDCache().
** This has nothing to do with the number of processORs, only processEs.
** This function sets up a Server Session ID (SID) cache that is safe for
** access by multiple processes on the same system.
*/
-SSL_IMPORT SECStatus SSL_ConfigMPServerSIDCache(int maxCacheEntries,
- PRUint32 timeout,
- PRUint32 ssl3_timeout,
- const char * directory);
-
-/* Get and set the configured maximum number of mutexes used for the
-** server's store of SSL sessions. This value is used by the server
-** session ID cache initialization functions shown above. Note that on
-** some platforms, these mutexes are actually implemented with POSIX
+SSL_IMPORT SECStatus SSL_ConfigMPServerSIDCache(int maxCacheEntries,
+ PRUint32 timeout,
+ PRUint32 ssl3_timeout,
+ const char *directory);
+
+/* Get and set the configured maximum number of mutexes used for the
+** server's store of SSL sessions. This value is used by the server
+** session ID cache initialization functions shown above. Note that on
+** some platforms, these mutexes are actually implemented with POSIX
** semaphores, or with unnamed pipes. The default value varies by platform.
-** An attempt to set a too-low maximum will return an error and the
+** An attempt to set a too-low maximum will return an error and the
** configured value will not be changed.
*/
-SSL_IMPORT PRUint32 SSL_GetMaxServerCacheLocks(void);
+SSL_IMPORT PRUint32 SSL_GetMaxServerCacheLocks(void);
SSL_IMPORT SECStatus SSL_SetMaxServerCacheLocks(PRUint32 maxLocks);
/* environment variable set by SSL_ConfigMPServerSIDCache, and queried by
* SSL_InheritMPServerSIDCache when envString is NULL.
*/
-#define SSL_ENV_VAR_NAME "SSL_INHERITANCE"
+#define SSL_ENV_VAR_NAME "SSL_INHERITANCE"
-/* called in child to inherit SID Cache variables.
+/* called in child to inherit SID Cache variables.
* If envString is NULL, this function will use the value of the environment
- * variable "SSL_INHERITANCE", otherwise the string value passed in will be
+ * variable "SSL_INHERITANCE", otherwise the string value passed in will be
* used.
*/
-SSL_IMPORT SECStatus SSL_InheritMPServerSIDCache(const char * envString);
+SSL_IMPORT SECStatus SSL_InheritMPServerSIDCache(const char *envString);
/*
** Set the callback that gets called when a TLS handshake is complete. The
@@ -901,10 +882,10 @@ SSL_IMPORT SECStatus SSL_InheritMPServerSIDCache(const char * envString);
** before the handshake callback is called. If we did not false start then the
** callback will get called before any application data is sent.
*/
-typedef void (PR_CALLBACK *SSLHandshakeCallback)(PRFileDesc *fd,
- void *client_data);
-SSL_IMPORT SECStatus SSL_HandshakeCallback(PRFileDesc *fd,
- SSLHandshakeCallback cb, void *client_data);
+typedef void(PR_CALLBACK *SSLHandshakeCallback)(PRFileDesc *fd,
+ void *client_data);
+SSL_IMPORT SECStatus SSL_HandshakeCallback(PRFileDesc *fd,
+ SSLHandshakeCallback cb, void *client_data);
/* Applications that wish to enable TLS false start must set this callback
** function. NSS will invoke the functon to determine if a particular
@@ -917,7 +898,7 @@ SSL_IMPORT SECStatus SSL_HandshakeCallback(PRFileDesc *fd,
** If no false start callback is registered then false start will never be
** done, even if the SSL_ENABLE_FALSE_START option is enabled.
**/
-typedef SECStatus (PR_CALLBACK *SSLCanFalseStartCallback)(
+typedef SECStatus(PR_CALLBACK *SSLCanFalseStartCallback)(
PRFileDesc *fd, void *arg, PRBool *canFalseStart);
SSL_IMPORT SECStatus SSL_SetCanFalseStartCallback(
@@ -933,10 +914,10 @@ SSL_IMPORT SECStatus SSL_RecommendedCanFalseStart(PRFileDesc *fd,
/*
** For the server, request a new handshake. For the client, begin a new
-** handshake. If flushCache is non-zero, the SSL3 cache entry will be
+** handshake. If flushCache is non-zero, the SSL3 cache entry will be
** flushed first, ensuring that a full SSL handshake will be done.
-** If flushCache is zero, and an SSL connection is established, it will
-** do the much faster session restart handshake. This will change the
+** If flushCache is zero, and an SSL connection is established, it will
+** do the much faster session restart handshake. This will change the
** session keys without doing another private key operation.
*/
SSL_IMPORT SECStatus SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache);
@@ -959,11 +940,11 @@ SSL_IMPORT SECStatus SSL_ReHandshakeWithTimeout(PRFileDesc *fd,
SSL_IMPORT const SECItem *
SSL_GetRequestedClientCertificateTypes(PRFileDesc *fd);
-#ifdef SSL_DEPRECATED_FUNCTION
+#ifdef SSL_DEPRECATED_FUNCTION
/* deprecated!
** For the server, request a new handshake. For the client, begin a new
-** handshake. Flushes SSL3 session cache entry first, ensuring that a
-** full handshake will be done.
+** handshake. Flushes SSL3 session cache entry first, ensuring that a
+** full handshake will be done.
** This call is equivalent to SSL_ReHandshake(fd, PR_TRUE)
*/
SSL_IMPORT SECStatus SSL_RedoHandshake(PRFileDesc *fd);
@@ -1025,11 +1006,11 @@ SSL_IMPORT SECStatus SSL_ShutdownServerSessionIDCache(void);
SSL_IMPORT SECStatus SSL_SetSockPeerID(PRFileDesc *fd, const char *peerID);
/*
-** Reveal the security information for the peer.
+** Reveal the security information for the peer.
*/
-SSL_IMPORT CERTCertificate * SSL_RevealCert(PRFileDesc * socket);
-SSL_IMPORT void * SSL_RevealPinArg(PRFileDesc * socket);
-SSL_IMPORT char * SSL_RevealURL(PRFileDesc * socket);
+SSL_IMPORT CERTCertificate *SSL_RevealCert(PRFileDesc *socket);
+SSL_IMPORT void *SSL_RevealPinArg(PRFileDesc *socket);
+SSL_IMPORT char *SSL_RevealURL(PRFileDesc *socket);
/* This callback may be passed to the SSL library via a call to
* SSL_GetClientAuthDataHook() for each SSL client socket.
@@ -1037,14 +1018,14 @@ SSL_IMPORT char * SSL_RevealURL(PRFileDesc * socket);
* (if any) to use to respond to a request for client authentication.
* If arg is non-NULL, it is a pointer to a NULL-terminated string containing
* the nickname of the cert/key pair to use.
- * If arg is NULL, this function will search the cert and key databases for
+ * If arg is NULL, this function will search the cert and key databases for
* a suitable match and send it if one is found.
*/
SSL_IMPORT SECStatus
-NSS_GetClientAuthData(void * arg,
- PRFileDesc * socket,
- struct CERTDistNamesStr * caNames,
- struct CERTCertificateStr ** pRetCert,
+NSS_GetClientAuthData(void *arg,
+ PRFileDesc *socket,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
struct SECKEYPrivateKeyStr **pRetKey);
/*
@@ -1058,8 +1039,8 @@ NSS_GetClientAuthData(void * arg,
** Otherwise returns SECFailure.
*/
SSL_IMPORT SECStatus SSL_SetSRTPCiphers(PRFileDesc *fd,
- const PRUint16 *ciphers,
- unsigned int numCiphers);
+ const PRUint16 *ciphers,
+ unsigned int numCiphers);
/*
** Get the selected DTLS-SRTP cipher suite (if any).
@@ -1067,21 +1048,21 @@ SSL_IMPORT SECStatus SSL_SetSRTPCiphers(PRFileDesc *fd,
** Returns SECFailure if not negotiated.
*/
SSL_IMPORT SECStatus SSL_GetSRTPCipher(PRFileDesc *fd,
- PRUint16 *cipher);
+ PRUint16 *cipher);
/*
* Look to see if any of the signers in the cert chain for "cert" are found
- * in the list of caNames.
+ * in the list of caNames.
* Returns SECSuccess if so, SECFailure if not.
* Used by NSS_GetClientAuthData. May be used by other callback functions.
*/
-SSL_IMPORT SECStatus NSS_CmpCertChainWCANames(CERTCertificate *cert,
- CERTDistNames *caNames);
+SSL_IMPORT SECStatus NSS_CmpCertChainWCANames(CERTCertificate *cert,
+ CERTDistNames *caNames);
-/*
+/*
* Returns key exchange type of the keys in an SSL server certificate.
*/
-SSL_IMPORT SSLKEAType NSS_FindCertKEAType(CERTCertificate * cert);
+SSL_IMPORT SSLKEAType NSS_FindCertKEAType(CERTCertificate *cert);
/* Set cipher policies to a predefined Domestic (U.S.A.) policy.
* This essentially allows all supported ciphers.
@@ -1095,16 +1076,18 @@ SSL_IMPORT SECStatus NSS_SetDomesticPolicy(void);
SSL_IMPORT SECStatus NSS_SetExportPolicy(void);
/* Set cipher policies to a predefined Policy that is exportable from the USA
- * according to present U.S. policies as we understand them, and that the
+ * according to present U.S. policies as we understand them, and that the
* nation of France will permit to be imported into their country.
* It is the same as NSS_SetDomesticPolicy now.
*/
SSL_IMPORT SECStatus NSS_SetFrancePolicy(void);
-SSL_IMPORT SSL3Statistics * SSL_GetStatistics(void);
+SSL_IMPORT SSL3Statistics *SSL_GetStatistics(void);
/* Report more information than SSL_SecurityStatus.
- * Caller supplies the info struct. This function fills it in.
+ * Caller supplies the info struct. This function fills it in. Caller should
+ * pass sizeof(SSLChannelInfo) as the |len| argument.
+ *
* The information here will be zeroed prior to details being confirmed. The
* details are confirmed either when a Finished message is received, or - for a
* client - when the second flight of messages have been sent. This function
@@ -1114,8 +1097,9 @@ SSL_IMPORT SSL3Statistics * SSL_GetStatistics(void);
SSL_IMPORT SECStatus SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info,
PRUintn len);
/* Get preliminary information about a channel.
- * This function can be called prior to handshake details being confirmed (see
- * SSL_GetChannelInfo above for what that means). Thus, information provided by
+ * Caller supplies the info struct. This function fills it in. Caller should
+ * pass sizeof(SSLPreliminaryChannelInfo) as the |len| argument.
+ *
* this function is available to SSLAuthCertificate, SSLGetClientAuthData,
* SSLSNISocketConfig, and other callbacks that might be called during the
* processing of the first flight of client of server handshake messages.
@@ -1125,8 +1109,12 @@ SSL_IMPORT SECStatus
SSL_GetPreliminaryChannelInfo(PRFileDesc *fd,
SSLPreliminaryChannelInfo *info,
PRUintn len);
-SSL_IMPORT SECStatus SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
- SSLCipherSuiteInfo *info, PRUintn len);
+/* Get information about cipher suite with id of |cipherSuite|.
+ * Caller supplies the info struct. This function fills it in. Caller should
+ * pass sizeof(SSLCipherSuiteInfo) as the |len| argument.
+ */
+SSL_IMPORT SECStatus SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
+ SSLCipherSuiteInfo *info, PRUintn len);
/* Returnes negotiated through SNI host info. */
SSL_IMPORT SECItem *SSL_GetNegotiatedHostInfo(PRFileDesc *fd);
@@ -1150,7 +1138,7 @@ SSL_IMPORT SECStatus SSL_ExportKeyingMaterial(PRFileDesc *fd,
** Return a new reference to the certificate that was most recently sent
** to the peer on this SSL/TLS connection, or NULL if none has been sent.
*/
-SSL_IMPORT CERTCertificate * SSL_LocalCertificate(PRFileDesc *fd);
+SSL_IMPORT CERTCertificate *SSL_LocalCertificate(PRFileDesc *fd);
/* Test an SSL configuration to see if SSL_BYPASS_PKCS11 can be turned on.
** Check the key exchange algorithm for each cipher in the list to see if
@@ -1174,20 +1162,20 @@ SSL_IMPORT CERTCertificate * SSL_LocalCertificate(PRFileDesc *fd);
**/
/* protocol mask bits */
-#define SSL_CBP_SSL3 0x0001 /* test SSL v3 mechanisms */
-#define SSL_CBP_TLS1_0 0x0002 /* test TLS v1.0 mechanisms */
+#define SSL_CBP_SSL3 0x0001 /* test SSL v3 mechanisms */
+#define SSL_CBP_TLS1_0 0x0002 /* test TLS v1.0 mechanisms */
SSL_IMPORT SECStatus SSL_CanBypass(CERTCertificate *cert,
SECKEYPrivateKey *privKey,
- PRUint32 protocolmask,
- PRUint16 *ciphers, int nciphers,
+ PRUint32 protocolmask,
+ PRUint16 *ciphers, int nciphers,
PRBool *pcanbypass, void *pwArg);
/*
** Did the handshake with the peer negotiate the given extension?
** Output parameter valid only if function returns SECSuccess
*/
-SSL_IMPORT SECStatus SSL_HandshakeNegotiatedExtension(PRFileDesc * socket,
+SSL_IMPORT SECStatus SSL_HandshakeNegotiatedExtension(PRFileDesc *socket,
SSLExtensionType extId,
PRBool *yes);
@@ -1198,7 +1186,7 @@ SSL_IMPORT SECStatus SSL_HandshakeResumedSession(PRFileDesc *fd,
* SECWouldBlock then SSL_RestartHandshakeAfterChannelIDReq should be called in
* the future to restart the handshake. On SECSuccess, the callback must have
* written a P-256, EC key pair to |*out_public_key| and |*out_private_key|. */
-typedef SECStatus (PR_CALLBACK *SSLClientChannelIDCallback)(
+typedef SECStatus(PR_CALLBACK *SSLClientChannelIDCallback)(
void *arg,
PRFileDesc *fd,
SECKEYPublicKey **out_public_key,
@@ -1308,7 +1296,7 @@ extern const char *NSSSSL_GetVersion(void);
* connection.
*/
SSL_IMPORT SECStatus SSL_AuthCertificateComplete(PRFileDesc *fd,
- PRErrorCode error);
+ PRErrorCode error);
SEC_END_PROTOS
#endif /* __ssl_h_ */
diff --git a/chromium/net/third_party/nss/ssl/ssl3con.c b/chromium/net/third_party/nss/ssl/ssl3con.c
index e5e620fd34c..b6f4987b6c7 100644
--- a/chromium/net/third_party/nss/ssl/ssl3con.c
+++ b/chromium/net/third_party/nss/ssl/ssl3con.c
@@ -8,10 +8,9 @@
/* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */
-#define _GNU_SOURCE 1
#include "cert.h"
#include "ssl.h"
-#include "cryptohi.h" /* for DSAU_ stuff */
+#include "cryptohi.h" /* for DSAU_ stuff */
#include "keyhi.h"
#include "secder.h"
#include "secitem.h"
@@ -34,84 +33,56 @@
#include "blapi.h"
#endif
-/* This is a bodge to allow this code to be compiled against older NSS headers
- * that don't contain the TLS 1.2 changes. */
-#ifndef CKM_NSS_TLS_PRF_GENERAL_SHA256
-#define CKM_NSS_TLS_PRF_GENERAL_SHA256 (CKM_NSS + 21)
-#define CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256 (CKM_NSS + 22)
-#define CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256 (CKM_NSS + 23)
-#define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24)
-#endif
-
-/* This is a bodge to allow this code to be compiled against older NSS
- * headers. */
-#ifndef CKM_NSS_CHACHA20_POLY1305
-#define CKM_NSS_CHACHA20_POLY1305 (CKM_NSS + 26)
-
-typedef struct CK_NSS_AEAD_PARAMS {
- CK_BYTE_PTR pIv; /* This is the nonce. */
- CK_ULONG ulIvLen;
- CK_BYTE_PTR pAAD;
- CK_ULONG ulAADLen;
- CK_ULONG ulTagLen;
-} CK_NSS_AEAD_PARAMS;
-
-#endif
-
#include <stdio.h>
-#ifdef NSS_ENABLE_ZLIB
+#ifdef NSS_SSL_ENABLE_ZLIB
#include "zlib.h"
#endif
-#ifdef LINUX
-#include <dlfcn.h>
-#endif
#ifndef PK11_SETATTRS
-#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
- (x)->pValue=(v); (x)->ulValueLen = (l);
+#define PK11_SETATTRS(x, id, v, l) \
+ (x)->type = (id); \
+ (x)->pValue = (v); \
+ (x)->ulValueLen = (l);
#endif
static SECStatus ssl3_AuthCertificate(sslSocket *ss);
-static void ssl3_CleanupPeerCerts(sslSocket *ss);
-static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid);
+static void ssl3_CleanupPeerCerts(sslSocket *ss);
+static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid);
static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
- PK11SlotInfo * serverKeySlot);
+ PK11SlotInfo *serverKeySlot);
static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms);
static SECStatus ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss);
-static SECStatus ssl3_HandshakeFailure( sslSocket *ss);
-static SECStatus ssl3_InitState( sslSocket *ss);
-static SECStatus ssl3_SendCertificate( sslSocket *ss);
-static SECStatus ssl3_SendCertificateStatus( sslSocket *ss);
-static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss);
+static SECStatus ssl3_HandshakeFailure(sslSocket *ss);
+static SECStatus ssl3_InitState(sslSocket *ss);
+
static SECStatus ssl3_SendCertificateRequest(sslSocket *ss);
-static SECStatus ssl3_SendNextProto( sslSocket *ss);
-static SECStatus ssl3_SendEncryptedExtensions(sslSocket *ss);
-static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags);
-static SECStatus ssl3_SendServerHello( sslSocket *ss);
-static SECStatus ssl3_SendServerHelloDone( sslSocket *ss);
-static SECStatus ssl3_SendServerKeyExchange( sslSocket *ss);
-static SECStatus ssl3_UpdateHandshakeHashes( sslSocket *ss,
- const unsigned char *b,
- unsigned int l);
-static SECStatus ssl3_ComputeHandshakeHashes(sslSocket *ss,
- ssl3CipherSpec *spec,
- SSL3Hashes *hashes,
- PRUint32 sender);
+static SECStatus ssl3_SendNextProto(sslSocket *ss);
+static SECStatus ssl3_SendChannelIDEncryptedExtensions(sslSocket *ss);
+static SECStatus ssl3_SendFinished(sslSocket *ss, PRInt32 flags);
+static SECStatus ssl3_SendServerHelloDone(sslSocket *ss);
+static SECStatus ssl3_SendServerKeyExchange(sslSocket *ss);
+static SECStatus ssl3_UpdateHandshakeHashes(sslSocket *ss,
+ const unsigned char *b,
+ unsigned int l);
+static SECStatus ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss,
+ SSL3Opaque *b,
+ PRUint32 length,
+ SSL3Hashes *hashesPtr);
static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags);
static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen,
- int maxOutputLen, const unsigned char *input,
- int inputLen);
+ int maxOutputLen, const unsigned char *input,
+ int inputLen);
#ifndef NO_PKCS11_BYPASS
static SECStatus ssl3_AESGCMBypass(ssl3KeyMaterial *keys, PRBool doDecrypt,
- unsigned char *out, int *outlen, int maxout,
- const unsigned char *in, int inlen,
- const unsigned char *additionalData,
- int additionalDataLen);
+ unsigned char *out, int *outlen, int maxout,
+ const unsigned char *in, int inlen,
+ const unsigned char *additionalData,
+ int additionalDataLen);
#endif
#define MAX_SEND_BUF_LENGTH 32000 /* watch for 16-bit integer overflow */
-#define MIN_SEND_BUF_LENGTH 4000
+#define MIN_SEND_BUF_LENGTH 4000
/* This list of SSL3 cipher suites is sorted in descending order of
* precedence (desirability). It only includes cipher suites we implement.
@@ -121,14 +92,15 @@ static SECStatus ssl3_AESGCMBypass(ssl3KeyMaterial *keys, PRBool doDecrypt,
* Important: See bug 946147 before enabling, reordering, or adding any cipher
* suites to this list.
*/
+/* clang-format off */
static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
/* cipher_suite policy enabled isPresent */
#ifndef NSS_DISABLE_ECC
- { TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
/* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA is out of order to work around
* bug 946147.
*/
@@ -145,6 +117,7 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
#endif /* NSS_DISABLE_ECC */
{ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,SSL_ALLOWED,PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
@@ -212,20 +185,21 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
{ TLS_RSA_WITH_NULL_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_RSA_WITH_NULL_MD5, SSL_ALLOWED, PR_FALSE, PR_FALSE},
};
+/* clang-format on */
static const SSLSignatureAndHashAlg defaultSignatureAlgorithms[] = {
- {ssl_hash_sha256, ssl_sign_rsa},
- {ssl_hash_sha384, ssl_sign_rsa},
- {ssl_hash_sha512, ssl_sign_rsa},
- {ssl_hash_sha1, ssl_sign_rsa},
+ { ssl_hash_sha256, ssl_sign_rsa },
+ { ssl_hash_sha384, ssl_sign_rsa },
+ { ssl_hash_sha512, ssl_sign_rsa },
+ { ssl_hash_sha1, ssl_sign_rsa },
#ifndef NSS_DISABLE_ECC
- {ssl_hash_sha256, ssl_sign_ecdsa},
- {ssl_hash_sha384, ssl_sign_ecdsa},
- {ssl_hash_sha512, ssl_sign_ecdsa},
- {ssl_hash_sha1, ssl_sign_ecdsa},
+ { ssl_hash_sha256, ssl_sign_ecdsa },
+ { ssl_hash_sha384, ssl_sign_ecdsa },
+ { ssl_hash_sha512, ssl_sign_ecdsa },
+ { ssl_hash_sha1, ssl_sign_ecdsa },
#endif
- {ssl_hash_sha256, ssl_sign_dsa},
- {ssl_hash_sha1, ssl_sign_dsa}
+ { ssl_hash_sha256, ssl_sign_dsa },
+ { ssl_hash_sha1, ssl_sign_dsa }
};
PR_STATIC_ASSERT(PR_ARRAY_SIZE(defaultSignatureAlgorithms) <=
MAX_SIGNATURE_ALGORITHMS);
@@ -233,7 +207,8 @@ PR_STATIC_ASSERT(PR_ARRAY_SIZE(defaultSignatureAlgorithms) <=
/* Verify that SSL_ImplementedCiphers and cipherSuites are in consistent order.
*/
#ifdef DEBUG
-void ssl3_CheckCipherSuiteOrderConsistency()
+void
+ssl3_CheckCipherSuiteOrderConsistency()
{
unsigned int i;
@@ -252,8 +227,8 @@ void ssl3_CheckCipherSuiteOrderConsistency()
* precedence (desirability). It only includes compression methods we
* implement.
*/
-static const /*SSLCompressionMethod*/ PRUint8 compressions [] = {
-#ifdef NSS_ENABLE_ZLIB
+static const /*SSLCompressionMethod*/ PRUint8 compressions[] = {
+#ifdef NSS_SSL_ENABLE_ZLIB
ssl_compression_deflate,
#endif
ssl_compression_null
@@ -268,21 +243,21 @@ static PRBool
compressionEnabled(sslSocket *ss, SSLCompressionMethod compression)
{
switch (compression) {
- case ssl_compression_null:
- return PR_TRUE; /* Always enabled */
-#ifdef NSS_ENABLE_ZLIB
- case ssl_compression_deflate:
- if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
- return ss->opt.enableDeflate;
- }
- return PR_FALSE;
+ case ssl_compression_null:
+ return PR_TRUE; /* Always enabled */
+#ifdef NSS_SSL_ENABLE_ZLIB
+ case ssl_compression_deflate:
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ return ss->opt.enableDeflate;
+ }
+ return PR_FALSE;
#endif
- default:
- return PR_FALSE;
+ default:
+ return PR_FALSE;
}
}
-static const /*SSL3ClientCertificateType */ PRUint8 certificate_types [] = {
+static const /*SSL3ClientCertificateType */ PRUint8 certificate_types[] = {
ct_RSA_sign,
#ifndef NSS_DISABLE_ECC
ct_ECDSA_sign,
@@ -290,8 +265,7 @@ static const /*SSL3ClientCertificateType */ PRUint8 certificate_types [] = {
ct_DSS_sign,
};
-#define EXPORT_RSA_KEY_LENGTH 64 /* bytes */
-
+#define EXPORT_RSA_KEY_LENGTH 64 /* bytes */
/* This global item is used only in servers. It is is initialized by
** SSL_ConfigSecureServer(), and is used in ssl3_SendCertificateRequest().
@@ -300,63 +274,64 @@ CERTDistNames *ssl3_server_ca_list = NULL;
static SSL3Statistics ssl3stats;
/* indexed by SSL3BulkCipher */
+/* clang-format off */
static const ssl3BulkCipherDef bulk_cipher_defs[] = {
/* |--------- Lengths --------| */
- /* cipher calg k s type i b t n */
- /* e e v l a o */
- /* y c | o g n */
- /* | r | c | c */
- /* | e | k | e */
- /* | t | | | | */
- {cipher_null, calg_null, 0, 0, type_stream, 0, 0, 0, 0},
- {cipher_rc4, calg_rc4, 16,16, type_stream, 0, 0, 0, 0},
- {cipher_rc4_40, calg_rc4, 16, 5, type_stream, 0, 0, 0, 0},
- {cipher_rc4_56, calg_rc4, 16, 7, type_stream, 0, 0, 0, 0},
- {cipher_rc2, calg_rc2, 16,16, type_block, 8, 8, 0, 0},
- {cipher_rc2_40, calg_rc2, 16, 5, type_block, 8, 8, 0, 0},
- {cipher_des, calg_des, 8, 8, type_block, 8, 8, 0, 0},
- {cipher_3des, calg_3des, 24,24, type_block, 8, 8, 0, 0},
- {cipher_des40, calg_des, 8, 5, type_block, 8, 8, 0, 0},
- {cipher_idea, calg_idea, 16,16, type_block, 8, 8, 0, 0},
- {cipher_aes_128, calg_aes, 16,16, type_block, 16,16, 0, 0},
- {cipher_aes_256, calg_aes, 32,32, type_block, 16,16, 0, 0},
- {cipher_camellia_128, calg_camellia, 16,16, type_block, 16,16, 0, 0},
- {cipher_camellia_256, calg_camellia, 32,32, type_block, 16,16, 0, 0},
- {cipher_seed, calg_seed, 16,16, type_block, 16,16, 0, 0},
- {cipher_aes_128_gcm, calg_aes_gcm, 16,16, type_aead, 4, 0,16, 8},
- {cipher_chacha20, calg_chacha20, 32,32, type_aead, 0, 0,16, 0},
- {cipher_missing, calg_null, 0, 0, type_stream, 0, 0, 0, 0},
+ /* cipher calg k s type i b t n o */
+ /* e e v l a o i */
+ /* y c | o g n d */
+ /* | r | c | c | */
+ /* | e | k | e | */
+ /* | t | | | | | */
+ {cipher_null, calg_null, 0, 0, type_stream, 0, 0, 0, 0, SEC_OID_NULL_CIPHER},
+ {cipher_rc4, calg_rc4, 16,16, type_stream, 0, 0, 0, 0, SEC_OID_RC4},
+ {cipher_rc4_40, calg_rc4, 16, 5, type_stream, 0, 0, 0, 0, SEC_OID_RC4_40},
+ {cipher_rc4_56, calg_rc4, 16, 7, type_stream, 0, 0, 0, 0, SEC_OID_RC4_56},
+ {cipher_rc2, calg_rc2, 16,16, type_block, 8, 8, 0, 0, SEC_OID_RC2_CBC},
+ {cipher_rc2_40, calg_rc2, 16, 5, type_block, 8, 8, 0, 0, SEC_OID_RC2_40_CBC},
+ {cipher_des, calg_des, 8, 8, type_block, 8, 8, 0, 0, SEC_OID_DES_CBC},
+ {cipher_3des, calg_3des, 24,24, type_block, 8, 8, 0, 0, SEC_OID_DES_EDE3_CBC},
+ {cipher_des40, calg_des, 8, 5, type_block, 8, 8, 0, 0, SEC_OID_DES_40_CBC},
+ {cipher_idea, calg_idea, 16,16, type_block, 8, 8, 0, 0, SEC_OID_IDEA_CBC},
+ {cipher_aes_128, calg_aes, 16,16, type_block, 16,16, 0, 0, SEC_OID_AES_128_CBC},
+ {cipher_aes_256, calg_aes, 32,32, type_block, 16,16, 0, 0, SEC_OID_AES_256_CBC},
+ {cipher_camellia_128, calg_camellia, 16,16, type_block, 16,16, 0, 0, SEC_OID_CAMELLIA_128_CBC},
+ {cipher_camellia_256, calg_camellia, 32,32, type_block, 16,16, 0, 0, SEC_OID_CAMELLIA_256_CBC},
+ {cipher_seed, calg_seed, 16,16, type_block, 16,16, 0, 0, SEC_OID_SEED_CBC},
+ {cipher_aes_128_gcm, calg_aes_gcm, 16,16, type_aead, 4, 0,16, 8, SEC_OID_AES_128_GCM},
+ {cipher_chacha20, calg_chacha20, 32,32, type_aead, 12, 0,16, 0, SEC_OID_CHACHA20_POLY1305},
+ {cipher_missing, calg_null, 0, 0, type_stream, 0, 0, 0, 0, 0},
};
static const ssl3KEADef kea_defs[] =
{ /* indexed by SSL3KeyExchangeAlgorithm */
- /* kea exchKeyType signKeyType is_limited limit tls_keygen ephemeral */
- {kea_null, kt_null, sign_null, PR_FALSE, 0, PR_FALSE, PR_FALSE},
- {kea_rsa, kt_rsa, sign_rsa, PR_FALSE, 0, PR_FALSE, PR_FALSE},
- {kea_rsa_export, kt_rsa, sign_rsa, PR_TRUE, 512, PR_FALSE, PR_FALSE},
- {kea_rsa_export_1024,kt_rsa, sign_rsa, PR_TRUE, 1024, PR_FALSE, PR_FALSE},
- {kea_dh_dss, kt_dh, sign_dsa, PR_FALSE, 0, PR_FALSE, PR_FALSE},
- {kea_dh_dss_export, kt_dh, sign_dsa, PR_TRUE, 512, PR_FALSE, PR_FALSE},
- {kea_dh_rsa, kt_dh, sign_rsa, PR_FALSE, 0, PR_FALSE, PR_FALSE},
- {kea_dh_rsa_export, kt_dh, sign_rsa, PR_TRUE, 512, PR_FALSE, PR_FALSE},
- {kea_dhe_dss, kt_dh, sign_dsa, PR_FALSE, 0, PR_FALSE, PR_TRUE},
- {kea_dhe_dss_export, kt_dh, sign_dsa, PR_TRUE, 512, PR_FALSE, PR_TRUE},
- {kea_dhe_rsa, kt_dh, sign_rsa, PR_FALSE, 0, PR_FALSE, PR_TRUE},
- {kea_dhe_rsa_export, kt_dh, sign_rsa, PR_TRUE, 512, PR_FALSE, PR_TRUE},
- {kea_dh_anon, kt_dh, sign_null, PR_FALSE, 0, PR_FALSE, PR_TRUE},
- {kea_dh_anon_export, kt_dh, sign_null, PR_TRUE, 512, PR_FALSE, PR_TRUE},
- {kea_rsa_fips, kt_rsa, sign_rsa, PR_FALSE, 0, PR_TRUE, PR_FALSE},
+ /* kea exchKeyType signKeyType is_limited limit tls_keygen ephemeral oid */
+ {kea_null, kt_null, ssl_sign_null, PR_FALSE, 0, PR_FALSE, PR_FALSE, 0},
+ {kea_rsa, kt_rsa, ssl_sign_rsa, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA},
+ {kea_rsa_export, kt_rsa, ssl_sign_rsa, PR_TRUE, 512, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA_EXPORT},
+ {kea_rsa_export_1024,kt_rsa, ssl_sign_rsa, PR_TRUE, 1024, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA_EXPORT},
+ {kea_dh_dss, kt_dh, ssl_sign_dsa, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_DSS},
+ {kea_dh_dss_export, kt_dh, ssl_sign_dsa, PR_TRUE, 512, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_DSS_EXPORT},
+ {kea_dh_rsa, kt_dh, ssl_sign_rsa, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_RSA},
+ {kea_dh_rsa_export, kt_dh, ssl_sign_rsa, PR_TRUE, 512, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_RSA_EXPORT},
+ {kea_dhe_dss, kt_dh, ssl_sign_dsa, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_DSS},
+ {kea_dhe_dss_export, kt_dh, ssl_sign_dsa, PR_TRUE, 512, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_DSS_EXPORT},
+ {kea_dhe_rsa, kt_dh, ssl_sign_rsa, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_RSA},
+ {kea_dhe_rsa_export, kt_dh, ssl_sign_rsa, PR_TRUE, 512, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_RSA_EXPORT},
+ {kea_dh_anon, kt_dh, ssl_sign_null, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_DH_ANON},
+ {kea_dh_anon_export, kt_dh, ssl_sign_null, PR_TRUE, 512, PR_FALSE, PR_TRUE, SEC_OID_TLS_DH_ANON_EXPORT},
+ {kea_rsa_fips, kt_rsa, ssl_sign_rsa, PR_FALSE, 0, PR_TRUE, PR_FALSE, SEC_OID_TLS_RSA},
#ifndef NSS_DISABLE_ECC
- {kea_ecdh_ecdsa, kt_ecdh, sign_ecdsa, PR_FALSE, 0, PR_FALSE, PR_FALSE},
- {kea_ecdhe_ecdsa, kt_ecdh, sign_ecdsa, PR_FALSE, 0, PR_FALSE, PR_TRUE},
- {kea_ecdh_rsa, kt_ecdh, sign_rsa, PR_FALSE, 0, PR_FALSE, PR_FALSE},
- {kea_ecdhe_rsa, kt_ecdh, sign_rsa, PR_FALSE, 0, PR_FALSE, PR_TRUE},
- {kea_ecdh_anon, kt_ecdh, sign_null, PR_FALSE, 0, PR_FALSE, PR_TRUE},
+ {kea_ecdh_ecdsa, kt_ecdh, ssl_sign_ecdsa, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_ECDH_ECDSA},
+ {kea_ecdhe_ecdsa, kt_ecdh, ssl_sign_ecdsa, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_ECDHE_ECDSA},
+ {kea_ecdh_rsa, kt_ecdh, ssl_sign_rsa, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_ECDH_RSA},
+ {kea_ecdhe_rsa, kt_ecdh, ssl_sign_rsa, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_ECDHE_RSA},
+ {kea_ecdh_anon, kt_ecdh, ssl_sign_null, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_ECDH_ANON},
#endif /* NSS_DISABLE_ECC */
};
/* must use ssl_LookupCipherSuiteDef to access */
-static const ssl3CipherSuiteDef cipher_suite_defs[] =
+static const ssl3CipherSuiteDef cipher_suite_defs[] =
{
/* cipher_suite bulk_cipher_alg mac_alg key_exchange_alg */
@@ -407,33 +382,33 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] =
/* New TLS cipher suites */
- {TLS_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_rsa},
- {TLS_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_rsa},
- {TLS_DHE_DSS_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dhe_dss},
- {TLS_DHE_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dhe_rsa},
+ {TLS_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_rsa},
+ {TLS_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_rsa},
+ {TLS_DHE_DSS_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dhe_dss},
+ {TLS_DHE_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dhe_rsa},
{TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_dhe_rsa},
- {TLS_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_rsa},
- {TLS_RSA_WITH_AES_256_CBC_SHA256, cipher_aes_256, hmac_sha256, kea_rsa},
- {TLS_DHE_DSS_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dhe_dss},
- {TLS_DHE_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dhe_rsa},
+ {TLS_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_rsa},
+ {TLS_RSA_WITH_AES_256_CBC_SHA256, cipher_aes_256, hmac_sha256, kea_rsa},
+ {TLS_DHE_DSS_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dhe_dss},
+ {TLS_DHE_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dhe_rsa},
{TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, cipher_aes_256, hmac_sha256, kea_dhe_rsa},
#if 0
- {TLS_DH_DSS_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dh_dss},
- {TLS_DH_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dh_rsa},
- {TLS_DH_anon_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dh_anon},
- {TLS_DH_DSS_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dh_dss},
- {TLS_DH_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dh_rsa},
- {TLS_DH_anon_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dh_anon},
+ {TLS_DH_DSS_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dh_dss},
+ {TLS_DH_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dh_rsa},
+ {TLS_DH_anon_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dh_anon},
+ {TLS_DH_DSS_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dh_dss},
+ {TLS_DH_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dh_rsa},
+ {TLS_DH_anon_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dh_anon},
#endif
- {TLS_RSA_WITH_SEED_CBC_SHA, cipher_seed, mac_sha, kea_rsa},
+ {TLS_RSA_WITH_SEED_CBC_SHA, cipher_seed, mac_sha, kea_rsa},
{TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, cipher_camellia_128, mac_sha, kea_rsa},
{TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
cipher_camellia_128, mac_sha, kea_dhe_dss},
{TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
cipher_camellia_128, mac_sha, kea_dhe_rsa},
- {TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, cipher_camellia_256, mac_sha, kea_rsa},
+ {TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, cipher_camellia_256, mac_sha, kea_rsa},
{TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
cipher_camellia_256, mac_sha, kea_dhe_dss},
{TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
@@ -451,13 +426,15 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] =
{TLS_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_rsa},
{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_rsa},
{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_ecdsa},
- {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, cipher_chacha20, mac_aead, kea_ecdhe_rsa},
- {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, cipher_chacha20, mac_aead, kea_ecdhe_ecdsa},
{TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_dhe_dss},
{TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_dhe_dss},
{TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, cipher_aes_256, hmac_sha256, kea_dhe_dss},
+ {TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, cipher_chacha20, mac_aead, kea_dhe_rsa},
+ {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, cipher_chacha20, mac_aead, kea_ecdhe_rsa},
+ {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, cipher_chacha20, mac_aead, kea_ecdhe_ecdsa},
+
#ifndef NSS_DISABLE_ECC
{TLS_ECDH_ECDSA_WITH_NULL_SHA, cipher_null, mac_sha, kea_ecdh_ecdsa},
{TLS_ECDH_ECDSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_ecdh_ecdsa},
@@ -494,6 +471,7 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] =
#endif
#endif /* NSS_DISABLE_ECC */
};
+/* clang-format on */
static const CK_MECHANISM_TYPE kea_alg_defs[] = {
0x80000000L,
@@ -504,49 +482,51 @@ static const CK_MECHANISM_TYPE kea_alg_defs[] = {
};
typedef struct SSLCipher2MechStr {
- SSLCipherAlgorithm calg;
- CK_MECHANISM_TYPE cmech;
+ SSLCipherAlgorithm calg;
+ CK_MECHANISM_TYPE cmech;
} SSLCipher2Mech;
/* indexed by type SSLCipherAlgorithm */
static const SSLCipher2Mech alg2Mech[] = {
/* calg, cmech */
- { calg_null , (CK_MECHANISM_TYPE)0x80000000L },
- { calg_rc4 , CKM_RC4 },
- { calg_rc2 , CKM_RC2_CBC },
- { calg_des , CKM_DES_CBC },
- { calg_3des , CKM_DES3_CBC },
- { calg_idea , CKM_IDEA_CBC },
- { calg_fortezza , CKM_SKIPJACK_CBC64 },
- { calg_aes , CKM_AES_CBC },
- { calg_camellia , CKM_CAMELLIA_CBC },
- { calg_seed , CKM_SEED_CBC },
- { calg_aes_gcm , CKM_AES_GCM },
- { calg_chacha20 , CKM_NSS_CHACHA20_POLY1305 },
-/* { calg_init , (CK_MECHANISM_TYPE)0x7fffffffL } */
+ { calg_null, (CK_MECHANISM_TYPE)0x80000000L },
+ { calg_rc4, CKM_RC4 },
+ { calg_rc2, CKM_RC2_CBC },
+ { calg_des, CKM_DES_CBC },
+ { calg_3des, CKM_DES3_CBC },
+ { calg_idea, CKM_IDEA_CBC },
+ { calg_fortezza, CKM_SKIPJACK_CBC64 },
+ { calg_aes, CKM_AES_CBC },
+ { calg_camellia, CKM_CAMELLIA_CBC },
+ { calg_seed, CKM_SEED_CBC },
+ { calg_aes_gcm, CKM_AES_GCM },
+ { calg_chacha20, CKM_NSS_CHACHA20_POLY1305 },
+ /* { calg_init , (CK_MECHANISM_TYPE)0x7fffffffL } */
};
-#define mmech_invalid (CK_MECHANISM_TYPE)0x80000000L
-#define mmech_md5 CKM_SSL3_MD5_MAC
-#define mmech_sha CKM_SSL3_SHA1_MAC
+#define mmech_invalid (CK_MECHANISM_TYPE)0x80000000L
+#define mmech_md5 CKM_SSL3_MD5_MAC
+#define mmech_sha CKM_SSL3_SHA1_MAC
#define mmech_md5_hmac CKM_MD5_HMAC
#define mmech_sha_hmac CKM_SHA_1_HMAC
#define mmech_sha256_hmac CKM_SHA256_HMAC
+/* clang-format off */
static const ssl3MACDef mac_defs[] = { /* indexed by SSL3MACAlgorithm */
/* pad_size is only used for SSL 3.0 MAC. See RFC 6101 Sec. 5.2.3.1. */
/* mac mmech pad_size mac_size */
- { mac_null, mmech_invalid, 0, 0 },
- { mac_md5, mmech_md5, 48, MD5_LENGTH },
- { mac_sha, mmech_sha, 40, SHA1_LENGTH},
- {hmac_md5, mmech_md5_hmac, 0, MD5_LENGTH },
- {hmac_sha, mmech_sha_hmac, 0, SHA1_LENGTH},
- {hmac_sha256, mmech_sha256_hmac, 0, SHA256_LENGTH},
- { mac_aead, mmech_invalid, 0, 0 },
+ { mac_null, mmech_invalid, 0, 0 , 0},
+ { mac_md5, mmech_md5, 48, MD5_LENGTH, SEC_OID_HMAC_MD5 },
+ { mac_sha, mmech_sha, 40, SHA1_LENGTH, SEC_OID_HMAC_SHA1},
+ {hmac_md5, mmech_md5_hmac, 0, MD5_LENGTH, SEC_OID_HMAC_MD5},
+ {hmac_sha, mmech_sha_hmac, 0, SHA1_LENGTH, SEC_OID_HMAC_SHA1},
+ {hmac_sha256, mmech_sha256_hmac, 0, SHA256_LENGTH, SEC_OID_HMAC_SHA256},
+ { mac_aead, mmech_invalid, 0, 0, 0 },
};
+/* clang-format on */
/* indexed by SSL3BulkCipher */
-const char * const ssl3_cipherName[] = {
+const char *const ssl3_cipherName[] = {
"NULL",
"RC4",
"RC4-40",
@@ -566,53 +546,90 @@ const char * const ssl3_cipherName[] = {
"missing"
};
+const PRUint8 tls13_downgrade_random[] = { 0x44, 0x4F, 0x57, 0x4E,
+ 0x47, 0x52, 0x44, 0x01 };
+const PRUint8 tls12_downgrade_random[] = { 0x44, 0x4F, 0x57, 0x4E,
+ 0x47, 0x52, 0x44, 0x00 };
+
#ifndef NSS_DISABLE_ECC
-/* The ECCWrappedKeyInfo structure defines how various pieces of
- * information are laid out within wrappedSymmetricWrappingkey
- * for ECDH key exchange. Since wrappedSymmetricWrappingkey is
- * a 512-byte buffer (see sslimpl.h), the variable length field
+/* The ECCWrappedKeyInfo structure defines how various pieces of
+ * information are laid out within wrappedSymmetricWrappingkey
+ * for ECDH key exchange. Since wrappedSymmetricWrappingkey is
+ * a 512-byte buffer (see sslimpl.h), the variable length field
* in ECCWrappedKeyInfo can be at most (512 - 8) = 504 bytes.
*
- * XXX For now, NSS only supports named elliptic curves of size 571 bits
+ * XXX For now, NSS only supports named elliptic curves of size 571 bits
* or smaller. The public value will fit within 145 bytes and EC params
* will fit within 12 bytes. We'll need to revisit this when NSS
* supports arbitrary curves.
*/
-#define MAX_EC_WRAPPED_KEY_BUFLEN 504
+#define MAX_EC_WRAPPED_KEY_BUFLEN 504
typedef struct ECCWrappedKeyInfoStr {
- PRUint16 size; /* EC public key size in bits */
- PRUint16 encodedParamLen; /* length (in bytes) of DER encoded EC params */
- PRUint16 pubValueLen; /* length (in bytes) of EC public value */
- PRUint16 wrappedKeyLen; /* length (in bytes) of the wrapped key */
+ PRUint16 size; /* EC public key size in bits */
+ PRUint16 encodedParamLen; /* length (in bytes) of DER encoded EC params */
+ PRUint16 pubValueLen; /* length (in bytes) of EC public value */
+ PRUint16 wrappedKeyLen; /* length (in bytes) of the wrapped key */
PRUint8 var[MAX_EC_WRAPPED_KEY_BUFLEN]; /* this buffer contains the */
/* EC public-key params, the EC public value and the wrapped key */
} ECCWrappedKeyInfo;
#endif /* NSS_DISABLE_ECC */
+CK_MECHANISM_TYPE
+ssl3_Alg2Mech(SSLCipherAlgorithm calg)
+{
+ PORT_Assert(alg2Mech[calg].calg == calg);
+ return alg2Mech[calg].cmech;
+}
+
#if defined(TRACE)
static char *
ssl3_DecodeHandshakeType(int msgType)
{
- char * rv;
+ char *rv;
static char line[40];
- switch(msgType) {
- case hello_request: rv = "hello_request (0)"; break;
- case client_hello: rv = "client_hello (1)"; break;
- case server_hello: rv = "server_hello (2)"; break;
- case hello_verify_request: rv = "hello_verify_request (3)"; break;
- case certificate: rv = "certificate (11)"; break;
- case server_key_exchange: rv = "server_key_exchange (12)"; break;
- case certificate_request: rv = "certificate_request (13)"; break;
- case server_hello_done: rv = "server_hello_done (14)"; break;
- case certificate_verify: rv = "certificate_verify (15)"; break;
- case client_key_exchange: rv = "client_key_exchange (16)"; break;
- case finished: rv = "finished (20)"; break;
- default:
- sprintf(line, "*UNKNOWN* handshake type! (%d)", msgType);
- rv = line;
+ switch (msgType) {
+ case hello_request:
+ rv = "hello_request (0)";
+ break;
+ case client_hello:
+ rv = "client_hello (1)";
+ break;
+ case server_hello:
+ rv = "server_hello (2)";
+ break;
+ case hello_verify_request:
+ rv = "hello_verify_request (3)";
+ break;
+ case encrypted_extensions:
+ rv = "encrypted_extensions (8)";
+ break;
+ case certificate:
+ rv = "certificate (11)";
+ break;
+ case server_key_exchange:
+ rv = "server_key_exchange (12)";
+ break;
+ case certificate_request:
+ rv = "certificate_request (13)";
+ break;
+ case server_hello_done:
+ rv = "server_hello_done (14)";
+ break;
+ case certificate_verify:
+ rv = "certificate_verify (15)";
+ break;
+ case client_key_exchange:
+ rv = "client_key_exchange (16)";
+ break;
+ case finished:
+ rv = "finished (20)";
+ break;
+ default:
+ sprintf(line, "*UNKNOWN* handshake type! (%d)", msgType);
+ rv = line;
}
return rv;
}
@@ -620,26 +637,32 @@ ssl3_DecodeHandshakeType(int msgType)
static char *
ssl3_DecodeContentType(int msgType)
{
- char * rv;
+ char *rv;
static char line[40];
- switch(msgType) {
- case content_change_cipher_spec:
- rv = "change_cipher_spec (20)"; break;
- case content_alert: rv = "alert (21)"; break;
- case content_handshake: rv = "handshake (22)"; break;
- case content_application_data:
- rv = "application_data (23)"; break;
- default:
- sprintf(line, "*UNKNOWN* record type! (%d)", msgType);
- rv = line;
+ switch (msgType) {
+ case content_change_cipher_spec:
+ rv = "change_cipher_spec (20)";
+ break;
+ case content_alert:
+ rv = "alert (21)";
+ break;
+ case content_handshake:
+ rv = "handshake (22)";
+ break;
+ case content_application_data:
+ rv = "application_data (23)";
+ break;
+ default:
+ sprintf(line, "*UNKNOWN* record type! (%d)", msgType);
+ rv = line;
}
return rv;
}
#endif
-SSL3Statistics *
+SSL3Statistics *
SSL_GetStatistics(void)
{
return &ssl3stats;
@@ -655,14 +678,15 @@ typedef struct tooLongStr {
#endif
} tooLong;
-void SSL_AtomicIncrementLong(long * x)
+void
+SSL_AtomicIncrementLong(long *x)
{
if ((sizeof *x) == sizeof(PRInt32)) {
PR_ATOMIC_INCREMENT((PRInt32 *)x);
} else {
- tooLong * tl = (tooLong *)x;
- if (PR_ATOMIC_INCREMENT(&tl->low) == 0)
- PR_ATOMIC_INCREMENT(&tl->high);
+ tooLong *tl = (tooLong *)x;
+ if (PR_ATOMIC_INCREMENT(&tl->low) == 0)
+ PR_ATOMIC_INCREMENT(&tl->high);
}
}
@@ -672,69 +696,67 @@ ssl3_CipherSuiteAllowedForVersionRange(
const SSLVersionRange *vrange)
{
switch (cipherSuite) {
- /* See RFC 4346 A.5. Export cipher suites must not be used in TLS 1.1 or
- * later. This set of cipher suites is similar to, but different from, the
- * set of cipher suites considered exportable by SSL_IsExportCipherSuite.
- */
- case TLS_RSA_EXPORT_WITH_RC4_40_MD5:
- case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
- /* TLS_RSA_EXPORT_WITH_DES40_CBC_SHA: never implemented
- * TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: never implemented
- * TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: never implemented
- * TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: never implemented
- * TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: never implemented
- * TLS_DH_anon_EXPORT_WITH_RC4_40_MD5: never implemented
- * TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA: never implemented
- */
- return vrange->min <= SSL_LIBRARY_VERSION_TLS_1_0;
-
- case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
- case TLS_RSA_WITH_AES_256_CBC_SHA256:
- case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
- case TLS_RSA_WITH_AES_128_CBC_SHA256:
- case TLS_RSA_WITH_AES_128_GCM_SHA256:
- case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
- case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
- case TLS_RSA_WITH_NULL_SHA256:
- return vrange->max == SSL_LIBRARY_VERSION_TLS_1_2;
-
- case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305:
- case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305:
- case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
- case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
- return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_2;
-
- /* RFC 4492: ECC cipher suites need TLS extensions to negotiate curves and
- * point formats.*/
- case TLS_ECDH_ECDSA_WITH_NULL_SHA:
- case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
- case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
- case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
- case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
- case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
- case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
- case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
- case TLS_ECDH_RSA_WITH_NULL_SHA:
- case TLS_ECDH_RSA_WITH_RC4_128_SHA:
- case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
- case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
- case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
- case TLS_ECDHE_RSA_WITH_NULL_SHA:
- case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
- case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
- return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_0 &&
- vrange->min < SSL_LIBRARY_VERSION_TLS_1_3;
-
- default:
- return vrange->min < SSL_LIBRARY_VERSION_TLS_1_3;
+ /* See RFC 4346 A.5. Export cipher suites must not be used in TLS 1.1 or
+ * later. This set of cipher suites is similar to, but different from, the
+ * set of cipher suites considered exportable by SSL_IsExportCipherSuite.
+ */
+ case TLS_RSA_EXPORT_WITH_RC4_40_MD5:
+ case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
+ /* TLS_RSA_EXPORT_WITH_DES40_CBC_SHA: never implemented
+ * TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: never implemented
+ * TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: never implemented
+ * TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: never implemented
+ * TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: never implemented
+ * TLS_DH_anon_EXPORT_WITH_RC4_40_MD5: never implemented
+ * TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA: never implemented
+ */
+ return vrange->min <= SSL_LIBRARY_VERSION_TLS_1_0;
+
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+ case TLS_RSA_WITH_AES_256_CBC_SHA256:
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+ case TLS_RSA_WITH_AES_128_CBC_SHA256:
+ case TLS_RSA_WITH_AES_128_GCM_SHA256:
+ case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+ case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+ case TLS_RSA_WITH_NULL_SHA256:
+ case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+ return vrange->max == SSL_LIBRARY_VERSION_TLS_1_2;
+
+ case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+ return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_2;
+
+ /* RFC 4492: ECC cipher suites need TLS extensions to negotiate curves and
+ * point formats.*/
+ case TLS_ECDH_ECDSA_WITH_NULL_SHA:
+ case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+ case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+ case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+ case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+ case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+ case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+ case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+ case TLS_ECDH_RSA_WITH_NULL_SHA:
+ case TLS_ECDH_RSA_WITH_RC4_128_SHA:
+ case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+ case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+ case TLS_ECDHE_RSA_WITH_NULL_SHA:
+ case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+ case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+ return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_0 &&
+ vrange->min < SSL_LIBRARY_VERSION_TLS_1_3;
+
+ default:
+ return vrange->min < SSL_LIBRARY_VERSION_TLS_1_3;
}
}
@@ -744,14 +766,14 @@ static const ssl3CipherSuiteDef *
ssl_LookupCipherSuiteDef(ssl3CipherSuite suite)
{
int cipher_suite_def_len =
- sizeof(cipher_suite_defs) / sizeof(cipher_suite_defs[0]);
+ sizeof(cipher_suite_defs) / sizeof(cipher_suite_defs[0]);
int i;
for (i = 0; i < cipher_suite_def_len; i++) {
- if (cipher_suite_defs[i].cipher_suite == suite)
- return &cipher_suite_defs[i];
+ if (cipher_suite_defs[i].cipher_suite == suite)
+ return &cipher_suite_defs[i];
}
- PORT_Assert(PR_FALSE); /* We should never get here. */
+ PORT_Assert(PR_FALSE); /* We should never get here. */
PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
return NULL;
}
@@ -764,15 +786,14 @@ ssl_LookupCipherSuiteCfg(ssl3CipherSuite suite, ssl3CipherSuiteCfg *suites)
int i;
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
- if (suites[i].cipher_suite == suite)
- return &suites[i];
+ if (suites[i].cipher_suite == suite)
+ return &suites[i];
}
/* return NULL and let the caller handle it. */
PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
return NULL;
}
-
/* Initialize the suite->isPresent value for config_match
* Returns count of enabled ciphers supported by extant tokens,
* regardless of policy or user preference.
@@ -781,97 +802,94 @@ ssl_LookupCipherSuiteCfg(ssl3CipherSuite suite, ssl3CipherSuiteCfg *suites)
int
ssl3_config_match_init(sslSocket *ss)
{
- ssl3CipherSuiteCfg * suite;
+ ssl3CipherSuiteCfg *suite;
const ssl3CipherSuiteDef *cipher_def;
- SSLCipherAlgorithm cipher_alg;
- CK_MECHANISM_TYPE cipher_mech;
- SSL3KEAType exchKeyType;
- int i;
- int numPresent = 0;
- int numEnabled = 0;
- PRBool isServer;
- sslServerCerts *svrAuth;
+ SSLCipherAlgorithm cipher_alg;
+ CK_MECHANISM_TYPE cipher_mech;
+ SSL3KEAType exchKeyType;
+ int i;
+ int numPresent = 0;
+ int numEnabled = 0;
+ PRBool isServer;
+ sslServerCerts *svrAuth;
PORT_Assert(ss);
if (!ss) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return 0;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return 0;
}
if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
- return 0;
+ return 0;
}
isServer = (PRBool)(ss->sec.isServer != 0);
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
- suite = &ss->cipherSuites[i];
- if (suite->enabled) {
- ++numEnabled;
- /* We need the cipher defs to see if we have a token that can handle
- * this cipher. It isn't part of the static definition.
- */
- cipher_def = ssl_LookupCipherSuiteDef(suite->cipher_suite);
- if (!cipher_def) {
- suite->isPresent = PR_FALSE;
- continue;
- }
- cipher_alg = bulk_cipher_defs[cipher_def->bulk_cipher_alg].calg;
- PORT_Assert( alg2Mech[cipher_alg].calg == cipher_alg);
- cipher_mech = alg2Mech[cipher_alg].cmech;
- exchKeyType =
- kea_defs[cipher_def->key_exchange_alg].exchKeyType;
+ suite = &ss->cipherSuites[i];
+ if (suite->enabled) {
+ ++numEnabled;
+ /* We need the cipher defs to see if we have a token that can handle
+ * this cipher. It isn't part of the static definition.
+ */
+ cipher_def = ssl_LookupCipherSuiteDef(suite->cipher_suite);
+ if (!cipher_def) {
+ suite->isPresent = PR_FALSE;
+ continue;
+ }
+ cipher_alg = bulk_cipher_defs[cipher_def->bulk_cipher_alg].calg;
+ cipher_mech = ssl3_Alg2Mech(cipher_alg);
+ exchKeyType =
+ kea_defs[cipher_def->key_exchange_alg].exchKeyType;
#ifdef NSS_DISABLE_ECC
- svrAuth = ss->serverCerts + exchKeyType;
+ svrAuth = ss->serverCerts + exchKeyType;
#else
- /* XXX SSLKEAType isn't really a good choice for
- * indexing certificates. It doesn't work for
- * (EC)DHE-* ciphers. Here we use a hack to ensure
- * that the server uses an RSA cert for (EC)DHE-RSA.
- */
- switch (cipher_def->key_exchange_alg) {
- case kea_dhe_dss:
- svrAuth = ss->serverCerts + ssl_kea_dh;
- break;
- case kea_ecdhe_rsa:
- case kea_dhe_rsa:
- svrAuth = ss->serverCerts + kt_rsa;
- break;
- case kea_ecdh_ecdsa:
- case kea_ecdh_rsa:
- /*
- * XXX We ought to have different indices for
- * ECDSA- and RSA-signed EC certificates so
- * we could support both key exchange mechanisms
- * simultaneously. For now, both of them use
- * whatever is in the certificate slot for kt_ecdh
- */
- case kea_dhe_dss_export:
- case kea_dhe_rsa_export:
- default:
- svrAuth = ss->serverCerts + exchKeyType;
- break;
- }
+ /* XXX SSLKEAType isn't really a good choice for
+ * indexing certificates. It doesn't work for
+ * (EC)DHE-* ciphers. Here we use a hack to ensure
+ * that the server uses an RSA cert for (EC)DHE-RSA.
+ */
+ switch (cipher_def->key_exchange_alg) {
+ case kea_dhe_dss:
+ svrAuth = ss->serverCerts + ssl_kea_dh;
+ break;
+ case kea_ecdhe_rsa:
+ case kea_dhe_rsa:
+ svrAuth = ss->serverCerts + kt_rsa;
+ break;
+ case kea_ecdh_ecdsa:
+ case kea_ecdh_rsa:
+ /*
+ * XXX We ought to have different indices for
+ * ECDSA- and RSA-signed EC certificates so
+ * we could support both key exchange mechanisms
+ * simultaneously. For now, both of them use
+ * whatever is in the certificate slot for kt_ecdh
+ */
+ case kea_dhe_dss_export:
+ case kea_dhe_rsa_export:
+ default:
+ svrAuth = ss->serverCerts + exchKeyType;
+ break;
+ }
#endif /* NSS_DISABLE_ECC */
- /* Mark the suites that are backed by real tokens, certs and keys */
- suite->isPresent = (PRBool)
- (((exchKeyType == kt_null) ||
- ((!isServer || (svrAuth->serverKeyPair &&
- svrAuth->SERVERKEY &&
- svrAuth->serverCertChain)) &&
- PK11_TokenExists(kea_alg_defs[exchKeyType]))) &&
- ((cipher_alg == calg_null) || PK11_TokenExists(cipher_mech)));
- if (suite->isPresent)
- ++numPresent;
- }
+ /* Mark the suites that are backed by real tokens, certs and keys */
+ suite->isPresent = (PRBool)(((exchKeyType == kt_null) ||
+ ((!isServer ||
+ (svrAuth->serverKeyPair && svrAuth->SERVERKEY &&
+ svrAuth->serverCertChain)) &&
+ PK11_TokenExists(kea_alg_defs[exchKeyType]))) &&
+ ((cipher_alg == calg_null) || PK11_TokenExists(cipher_mech)));
+ if (suite->isPresent)
+ ++numPresent;
+ }
}
PORT_Assert(numPresent > 0 || numEnabled == 0);
if (numPresent <= 0) {
- PORT_SetError(SSL_ERROR_NO_CIPHERS_SUPPORTED);
+ PORT_SetError(SSL_ERROR_NO_CIPHERS_SUPPORTED);
}
return numPresent;
}
-
/* return PR_TRUE if suite matches policy, enabled state and is applicable to
* the given version range. */
/* It would be a REALLY BAD THING (tm) if we ever permitted the use
@@ -882,13 +900,13 @@ ssl3_config_match_init(sslSocket *ss)
* cipher suite. */
static PRBool
config_match(ssl3CipherSuiteCfg *suite, int policy, PRBool enabled,
- const SSLVersionRange *vrange, const sslSocket *ss)
+ const SSLVersionRange *vrange, const sslSocket *ss)
{
const ssl3CipherSuiteDef *cipher_def;
PORT_Assert(policy != SSL_NOT_ALLOWED && enabled != PR_FALSE);
if (policy == SSL_NOT_ALLOWED || !enabled)
- return PR_FALSE;
+ return PR_FALSE;
cipher_def = ssl_LookupCipherSuiteDef(suite->cipher_suite);
PORT_Assert(cipher_def != NULL);
@@ -896,13 +914,13 @@ config_match(ssl3CipherSuiteCfg *suite, int policy, PRBool enabled,
PORT_Assert(ss != NULL);
if (ss->sec.isServer && !ss->opt.enableServerDhe &&
kea_defs[cipher_def->key_exchange_alg].exchKeyType == ssl_kea_dh)
- return PR_FALSE;
+ return PR_FALSE;
return (PRBool)(suite->enabled &&
suite->isPresent &&
- suite->policy != SSL_NOT_ALLOWED &&
- suite->policy <= policy &&
- ssl3_CipherSuiteAllowedForVersionRange(
+ suite->policy != SSL_NOT_ALLOWED &&
+ suite->policy <= policy &&
+ ssl3_CipherSuiteAllowedForVersionRange(
suite->cipher_suite, vrange));
}
@@ -915,14 +933,14 @@ count_cipher_suites(sslSocket *ss, int policy, PRBool enabled)
int i, count = 0;
if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
- return 0;
+ return 0;
}
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
- if (config_match(&ss->cipherSuites[i], policy, enabled, &ss->vrange, ss))
- count++;
+ if (config_match(&ss->cipherSuites[i], policy, enabled, &ss->vrange, ss))
+ count++;
}
if (count <= 0) {
- PORT_SetError(SSL_ERROR_SSL_DISABLED);
+ PORT_SetError(SSL_ERROR_SSL_DISABLED);
}
return count;
}
@@ -933,16 +951,16 @@ count_cipher_suites(sslSocket *ss, int policy, PRBool enabled)
static SECStatus
Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen,
- const unsigned char *input, int inputLen)
+ const unsigned char *input, int inputLen)
{
if (inputLen > maxOutputLen) {
- *outputLen = 0; /* Match PK11_CipherOp in setting outputLen */
+ *outputLen = 0; /* Match PK11_CipherOp in setting outputLen */
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
*outputLen = inputLen;
if (input != output)
- PORT_Memcpy(output, input, inputLen);
+ PORT_Memcpy(output, input, inputLen);
return SECSuccess;
}
@@ -959,17 +977,17 @@ Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen,
*/
SECStatus
ssl3_NegotiateVersion(sslSocket *ss, SSL3ProtocolVersion peerVersion,
- PRBool allowLargerPeerVersion)
+ PRBool allowLargerPeerVersion)
{
if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
- PORT_SetError(SSL_ERROR_SSL_DISABLED);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_SSL_DISABLED);
+ return SECFailure;
}
if (peerVersion < ss->vrange.min ||
- (peerVersion > ss->vrange.max && !allowLargerPeerVersion)) {
- PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
- return SECFailure;
+ (peerVersion > ss->vrange.max && !allowLargerPeerVersion)) {
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
+ return SECFailure;
}
ss->version = PR_MIN(peerVersion, ss->vrange.max);
@@ -983,206 +1001,203 @@ ssl3_GetNewRandom(SSL3Random *random)
{
SECStatus rv;
- /* first 4 bytes are reserverd for time */
rv = PK11_GenerateRandom(random->rand, SSL3_RANDOM_LENGTH);
if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
+ ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
}
return rv;
}
/* Called by ssl3_SendServerKeyExchange and ssl3_SendCertificateVerify */
SECStatus
-ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf,
+ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf,
PRBool isTLS)
{
- SECStatus rv = SECFailure;
- PRBool doDerEncode = PR_FALSE;
- int signatureLen;
- SECItem hashItem;
+ SECStatus rv = SECFailure;
+ PRBool doDerEncode = PR_FALSE;
+ int signatureLen;
+ SECItem hashItem;
- buf->data = NULL;
+ buf->data = NULL;
switch (key->keyType) {
- case rsaKey:
- hashItem.data = hash->u.raw;
- hashItem.len = hash->len;
- break;
- case dsaKey:
- doDerEncode = isTLS;
- /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
- * In that case, we use just the SHA1 part. */
- if (hash->hashAlg == ssl_hash_none) {
- hashItem.data = hash->u.s.sha;
- hashItem.len = sizeof(hash->u.s.sha);
- } else {
- hashItem.data = hash->u.raw;
- hashItem.len = hash->len;
- }
- break;
+ case rsaKey:
+ hashItem.data = hash->u.raw;
+ hashItem.len = hash->len;
+ break;
+ case dsaKey:
+ doDerEncode = isTLS;
+ /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
+ * In that case, we use just the SHA1 part. */
+ if (hash->hashAlg == ssl_hash_none) {
+ hashItem.data = hash->u.s.sha;
+ hashItem.len = sizeof(hash->u.s.sha);
+ } else {
+ hashItem.data = hash->u.raw;
+ hashItem.len = hash->len;
+ }
+ break;
#ifndef NSS_DISABLE_ECC
- case ecKey:
- doDerEncode = PR_TRUE;
- /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
- * In that case, we use just the SHA1 part. */
- if (hash->hashAlg == ssl_hash_none) {
- hashItem.data = hash->u.s.sha;
- hashItem.len = sizeof(hash->u.s.sha);
- } else {
- hashItem.data = hash->u.raw;
- hashItem.len = hash->len;
- }
- break;
+ case ecKey:
+ doDerEncode = PR_TRUE;
+ /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
+ * In that case, we use just the SHA1 part. */
+ if (hash->hashAlg == ssl_hash_none) {
+ hashItem.data = hash->u.s.sha;
+ hashItem.len = sizeof(hash->u.s.sha);
+ } else {
+ hashItem.data = hash->u.raw;
+ hashItem.len = hash->len;
+ }
+ break;
#endif /* NSS_DISABLE_ECC */
- default:
- PORT_SetError(SEC_ERROR_INVALID_KEY);
- goto done;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ goto done;
}
PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len));
if (hash->hashAlg == ssl_hash_none) {
- signatureLen = PK11_SignatureLen(key);
- if (signatureLen <= 0) {
- PORT_SetError(SEC_ERROR_INVALID_KEY);
- goto done;
- }
-
- buf->len = (unsigned)signatureLen;
- buf->data = (unsigned char *)PORT_Alloc(signatureLen);
- if (!buf->data)
- goto done; /* error code was set. */
-
- rv = PK11_Sign(key, buf, &hashItem);
+ signatureLen = PK11_SignatureLen(key);
+ if (signatureLen <= 0) {
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ goto done;
+ }
+
+ buf->len = (unsigned)signatureLen;
+ buf->data = (unsigned char *)PORT_Alloc(signatureLen);
+ if (!buf->data)
+ goto done; /* error code was set. */
+
+ rv = PK11_Sign(key, buf, &hashItem);
} else {
SECOidTag hashOID = ssl3_TLSHashAlgorithmToOID(hash->hashAlg);
rv = SGN_Digest(key, hashOID, buf, &hashItem);
}
if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
+ ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
} else if (doDerEncode) {
- SECItem derSig = {siBuffer, NULL, 0};
+ SECItem derSig = { siBuffer, NULL, 0 };
- /* This also works for an ECDSA signature */
- rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len);
- if (rv == SECSuccess) {
- PORT_Free(buf->data); /* discard unencoded signature. */
- *buf = derSig; /* give caller encoded signature. */
- } else if (derSig.data) {
- PORT_Free(derSig.data);
- }
+ /* This also works for an ECDSA signature */
+ rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len);
+ if (rv == SECSuccess) {
+ PORT_Free(buf->data); /* discard unencoded signature. */
+ *buf = derSig; /* give caller encoded signature. */
+ } else if (derSig.data) {
+ PORT_Free(derSig.data);
+ }
}
- PRINT_BUF(60, (NULL, "signed hashes", (unsigned char*)buf->data, buf->len));
+ PRINT_BUF(60, (NULL, "signed hashes", (unsigned char *)buf->data, buf->len));
done:
if (rv != SECSuccess && buf->data) {
- PORT_Free(buf->data);
- buf->data = NULL;
+ PORT_Free(buf->data);
+ buf->data = NULL;
}
return rv;
}
/* Called from ssl3_HandleServerKeyExchange, ssl3_HandleCertificateVerify */
SECStatus
-ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
+ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
SECItem *buf, PRBool isTLS, void *pwArg)
{
- SECKEYPublicKey * key;
- SECItem * signature = NULL;
- SECStatus rv;
- SECItem hashItem;
- SECOidTag encAlg;
- SECOidTag hashAlg;
-
+ SECKEYPublicKey *key;
+ SECItem *signature = NULL;
+ SECStatus rv;
+ SECItem hashItem;
+ SECOidTag encAlg;
+ SECOidTag hashAlg;
PRINT_BUF(60, (NULL, "check signed hashes",
- buf->data, buf->len));
+ buf->data, buf->len));
key = CERT_ExtractPublicKey(cert);
if (key == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
- return SECFailure;
+ ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
+ return SECFailure;
}
hashAlg = ssl3_TLSHashAlgorithmToOID(hash->hashAlg);
switch (key->keyType) {
- case rsaKey:
- encAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
- hashItem.data = hash->u.raw;
- hashItem.len = hash->len;
- break;
- case dsaKey:
- encAlg = SEC_OID_ANSIX9_DSA_SIGNATURE;
- /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
- * In that case, we use just the SHA1 part. */
- if (hash->hashAlg == ssl_hash_none) {
- hashItem.data = hash->u.s.sha;
- hashItem.len = sizeof(hash->u.s.sha);
- } else {
- hashItem.data = hash->u.raw;
- hashItem.len = hash->len;
- }
- /* Allow DER encoded DSA signatures in SSL 3.0 */
- if (isTLS || buf->len != SECKEY_SignatureLen(key)) {
- signature = DSAU_DecodeDerSigToLen(buf, SECKEY_SignatureLen(key));
- if (!signature) {
- PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
- return SECFailure;
- }
- buf = signature;
- }
- break;
+ case rsaKey:
+ encAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
+ hashItem.data = hash->u.raw;
+ hashItem.len = hash->len;
+ break;
+ case dsaKey:
+ encAlg = SEC_OID_ANSIX9_DSA_SIGNATURE;
+ /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
+ * In that case, we use just the SHA1 part. */
+ if (hash->hashAlg == ssl_hash_none) {
+ hashItem.data = hash->u.s.sha;
+ hashItem.len = sizeof(hash->u.s.sha);
+ } else {
+ hashItem.data = hash->u.raw;
+ hashItem.len = hash->len;
+ }
+ /* Allow DER encoded DSA signatures in SSL 3.0 */
+ if (isTLS || buf->len != SECKEY_SignatureLen(key)) {
+ signature = DSAU_DecodeDerSigToLen(buf, SECKEY_SignatureLen(key));
+ if (!signature) {
+ PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
+ return SECFailure;
+ }
+ buf = signature;
+ }
+ break;
#ifndef NSS_DISABLE_ECC
- case ecKey:
- encAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
- /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
- * In that case, we use just the SHA1 part.
- * ECDSA signatures always encode the integers r and s using ASN.1
- * (unlike DSA where ASN.1 encoding is used with TLS but not with
- * SSL3). So we can use VFY_VerifyDigestDirect for ECDSA.
- */
- if (hash->hashAlg == ssl_hash_none) {
- hashAlg = SEC_OID_SHA1;
- hashItem.data = hash->u.s.sha;
- hashItem.len = sizeof(hash->u.s.sha);
- } else {
- hashItem.data = hash->u.raw;
- hashItem.len = hash->len;
- }
- break;
+ case ecKey:
+ encAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
+ /* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
+ * In that case, we use just the SHA1 part.
+ * ECDSA signatures always encode the integers r and s using ASN.1
+ * (unlike DSA where ASN.1 encoding is used with TLS but not with
+ * SSL3). So we can use VFY_VerifyDigestDirect for ECDSA.
+ */
+ if (hash->hashAlg == ssl_hash_none) {
+ hashAlg = SEC_OID_SHA1;
+ hashItem.data = hash->u.s.sha;
+ hashItem.len = sizeof(hash->u.s.sha);
+ } else {
+ hashItem.data = hash->u.raw;
+ hashItem.len = hash->len;
+ }
+ break;
#endif /* NSS_DISABLE_ECC */
- default:
- SECKEY_DestroyPublicKey(key);
- PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
- return SECFailure;
+ default:
+ SECKEY_DestroyPublicKey(key);
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
+ return SECFailure;
}
PRINT_BUF(60, (NULL, "hash(es) to be verified",
- hashItem.data, hashItem.len));
+ hashItem.data, hashItem.len));
if (hashAlg == SEC_OID_UNKNOWN || key->keyType == dsaKey) {
- /* VFY_VerifyDigestDirect requires DSA signatures to be DER-encoded.
- * DSA signatures are DER-encoded in TLS but not in SSL3 and the code
- * above always removes the DER encoding of DSA signatures when
- * present. Thus DSA signatures are always verified with PK11_Verify.
- */
- rv = PK11_Verify(key, buf, &hashItem, pwArg);
+ /* VFY_VerifyDigestDirect requires DSA signatures to be DER-encoded.
+ * DSA signatures are DER-encoded in TLS but not in SSL3 and the code
+ * above always removes the DER encoding of DSA signatures when
+ * present. Thus DSA signatures are always verified with PK11_Verify.
+ */
+ rv = PK11_Verify(key, buf, &hashItem, pwArg);
} else {
rv = VFY_VerifyDigestDirect(&hashItem, key, buf, encAlg, hashAlg,
pwArg);
}
SECKEY_DestroyPublicKey(key);
if (signature) {
- SECITEM_FreeItem(signature, PR_TRUE);
+ SECITEM_FreeItem(signature, PR_TRUE);
}
if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
+ ssl_MapLowLevelError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
}
return rv;
}
-
/* Caller must set hiLevel error code. */
/* Called from ssl3_ComputeExportRSAKeyHash
* ssl3_ComputeDHKeyHash
@@ -1192,7 +1207,7 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
*/
SECStatus
ssl3_ComputeCommonKeyHash(SSLHashType hashAlg,
- PRUint8 * hashBuf, unsigned int bufLen,
+ PRUint8 *hashBuf, unsigned int bufLen,
SSL3Hashes *hashes, PRBool bypassPKCS11)
{
SECStatus rv;
@@ -1201,7 +1216,7 @@ ssl3_ComputeCommonKeyHash(SSLHashType hashAlg,
#ifndef NO_PKCS11_BYPASS
if (bypassPKCS11) {
if (hashAlg == ssl_hash_none) {
- MD5_HashBuf (hashes->u.s.md5, hashBuf, bufLen);
+ MD5_HashBuf(hashes->u.s.md5, hashBuf, bufLen);
SHA1_HashBuf(hashes->u.s.sha, hashBuf, bufLen);
hashes->len = MD5_LENGTH + SHA1_LENGTH;
} else if (hashAlg == ssl_hash_sha1) {
@@ -1253,8 +1268,8 @@ ssl3_ComputeCommonKeyHash(SSLHashType hashAlg,
return SECSuccess;
}
-/* Caller must set hiLevel error code.
-** Called from ssl3_SendServerKeyExchange and
+/* Caller must set hiLevel error code.
+** Called from ssl3_SendServerKeyExchange and
** ssl3_HandleServerKeyExchange.
*/
static SECStatus
@@ -1263,54 +1278,54 @@ ssl3_ComputeExportRSAKeyHash(SSLHashType hashAlg,
SSL3Random *client_rand, SSL3Random *server_rand,
SSL3Hashes *hashes, PRBool bypassPKCS11)
{
- PRUint8 * hashBuf;
- PRUint8 * pBuf;
- SECStatus rv = SECSuccess;
- unsigned int bufLen;
- PRUint8 buf[2*SSL3_RANDOM_LENGTH + 2 + 4096/8 + 2 + 4096/8];
+ PRUint8 *hashBuf;
+ PRUint8 *pBuf;
+ SECStatus rv = SECSuccess;
+ unsigned int bufLen;
+ PRUint8 buf[2 * SSL3_RANDOM_LENGTH + 2 + 4096 / 8 + 2 + 4096 / 8];
- bufLen = 2*SSL3_RANDOM_LENGTH + 2 + modulus.len + 2 + publicExponent.len;
+ bufLen = 2 * SSL3_RANDOM_LENGTH + 2 + modulus.len + 2 + publicExponent.len;
if (bufLen <= sizeof buf) {
- hashBuf = buf;
+ hashBuf = buf;
} else {
- hashBuf = PORT_Alloc(bufLen);
- if (!hashBuf) {
- return SECFailure;
- }
+ hashBuf = PORT_Alloc(bufLen);
+ if (!hashBuf) {
+ return SECFailure;
+ }
}
- memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
- pBuf = hashBuf + SSL3_RANDOM_LENGTH;
+ memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
+ pBuf = hashBuf + SSL3_RANDOM_LENGTH;
memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
- pBuf += SSL3_RANDOM_LENGTH;
- pBuf[0] = (PRUint8)(modulus.len >> 8);
- pBuf[1] = (PRUint8)(modulus.len);
- pBuf += 2;
+ pBuf += SSL3_RANDOM_LENGTH;
+ pBuf[0] = (PRUint8)(modulus.len >> 8);
+ pBuf[1] = (PRUint8)(modulus.len);
+ pBuf += 2;
memcpy(pBuf, modulus.data, modulus.len);
- pBuf += modulus.len;
+ pBuf += modulus.len;
pBuf[0] = (PRUint8)(publicExponent.len >> 8);
pBuf[1] = (PRUint8)(publicExponent.len);
- pBuf += 2;
+ pBuf += 2;
memcpy(pBuf, publicExponent.data, publicExponent.len);
- pBuf += publicExponent.len;
+ pBuf += publicExponent.len;
PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes,
- bypassPKCS11);
+ bypassPKCS11);
PRINT_BUF(95, (NULL, "RSAkey hash: ", hashBuf, bufLen));
if (hashAlg == ssl_hash_none) {
- PRINT_BUF(95, (NULL, "RSAkey hash: MD5 result",
- hashes->u.s.md5, MD5_LENGTH));
- PRINT_BUF(95, (NULL, "RSAkey hash: SHA1 result",
- hashes->u.s.sha, SHA1_LENGTH));
+ PRINT_BUF(95, (NULL, "RSAkey hash: MD5 result",
+ hashes->u.s.md5, MD5_LENGTH));
+ PRINT_BUF(95, (NULL, "RSAkey hash: SHA1 result",
+ hashes->u.s.sha, SHA1_LENGTH));
} else {
- PRINT_BUF(95, (NULL, "RSAkey hash: result",
- hashes->u.raw, hashes->len));
+ PRINT_BUF(95, (NULL, "RSAkey hash: result",
+ hashes->u.raw, hashes->len));
}
if (hashBuf != buf && hashBuf != NULL)
- PORT_Free(hashBuf);
+ PORT_Free(hashBuf);
return rv;
}
@@ -1322,68 +1337,68 @@ ssl3_ComputeDHKeyHash(SSLHashType hashAlg,
SSL3Random *client_rand, SSL3Random *server_rand,
SSL3Hashes *hashes, PRBool bypassPKCS11)
{
- PRUint8 * hashBuf;
- PRUint8 * pBuf;
- SECStatus rv = SECSuccess;
- unsigned int bufLen;
- PRUint8 buf[2*SSL3_RANDOM_LENGTH + 2 + 4096/8 + 2 + 4096/8];
+ PRUint8 *hashBuf;
+ PRUint8 *pBuf;
+ SECStatus rv = SECSuccess;
+ unsigned int bufLen;
+ PRUint8 buf[2 * SSL3_RANDOM_LENGTH + 2 + 4096 / 8 + 2 + 4096 / 8];
- bufLen = 2*SSL3_RANDOM_LENGTH + 2 + dh_p.len + 2 + dh_g.len + 2 + dh_Ys.len;
+ bufLen = 2 * SSL3_RANDOM_LENGTH + 2 + dh_p.len + 2 + dh_g.len + 2 + dh_Ys.len;
if (bufLen <= sizeof buf) {
- hashBuf = buf;
+ hashBuf = buf;
} else {
- hashBuf = PORT_Alloc(bufLen);
- if (!hashBuf) {
- return SECFailure;
- }
+ hashBuf = PORT_Alloc(bufLen);
+ if (!hashBuf) {
+ return SECFailure;
+ }
}
- memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
- pBuf = hashBuf + SSL3_RANDOM_LENGTH;
+ memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
+ pBuf = hashBuf + SSL3_RANDOM_LENGTH;
memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
- pBuf += SSL3_RANDOM_LENGTH;
- pBuf[0] = (PRUint8)(dh_p.len >> 8);
- pBuf[1] = (PRUint8)(dh_p.len);
- pBuf += 2;
+ pBuf += SSL3_RANDOM_LENGTH;
+ pBuf[0] = (PRUint8)(dh_p.len >> 8);
+ pBuf[1] = (PRUint8)(dh_p.len);
+ pBuf += 2;
memcpy(pBuf, dh_p.data, dh_p.len);
- pBuf += dh_p.len;
+ pBuf += dh_p.len;
pBuf[0] = (PRUint8)(dh_g.len >> 8);
pBuf[1] = (PRUint8)(dh_g.len);
- pBuf += 2;
+ pBuf += 2;
memcpy(pBuf, dh_g.data, dh_g.len);
- pBuf += dh_g.len;
+ pBuf += dh_g.len;
pBuf[0] = (PRUint8)(dh_Ys.len >> 8);
pBuf[1] = (PRUint8)(dh_Ys.len);
- pBuf += 2;
+ pBuf += 2;
memcpy(pBuf, dh_Ys.data, dh_Ys.len);
- pBuf += dh_Ys.len;
+ pBuf += dh_Ys.len;
PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes,
- bypassPKCS11);
+ bypassPKCS11);
PRINT_BUF(95, (NULL, "DHkey hash: ", hashBuf, bufLen));
if (hashAlg == ssl_hash_none) {
- PRINT_BUF(95, (NULL, "DHkey hash: MD5 result",
- hashes->u.s.md5, MD5_LENGTH));
- PRINT_BUF(95, (NULL, "DHkey hash: SHA1 result",
- hashes->u.s.sha, SHA1_LENGTH));
+ PRINT_BUF(95, (NULL, "DHkey hash: MD5 result",
+ hashes->u.s.md5, MD5_LENGTH));
+ PRINT_BUF(95, (NULL, "DHkey hash: SHA1 result",
+ hashes->u.s.sha, SHA1_LENGTH));
} else {
- PRINT_BUF(95, (NULL, "DHkey hash: result",
- hashes->u.raw, hashes->len));
+ PRINT_BUF(95, (NULL, "DHkey hash: result",
+ hashes->u.raw, hashes->len));
}
if (hashBuf != buf && hashBuf != NULL)
- PORT_Free(hashBuf);
+ PORT_Free(hashBuf);
return rv;
}
-static void
+void
ssl3_BumpSequenceNumber(SSL3SequenceNumber *num)
{
num->low++;
if (num->low == 0)
- num->high++;
+ num->high++;
}
/* Called twice, only from ssl3_DestroyCipherSpec (immediately below). */
@@ -1391,21 +1406,21 @@ static void
ssl3_CleanupKeyMaterial(ssl3KeyMaterial *mat)
{
if (mat->write_key != NULL) {
- PK11_FreeSymKey(mat->write_key);
- mat->write_key = NULL;
+ PK11_FreeSymKey(mat->write_key);
+ mat->write_key = NULL;
}
if (mat->write_mac_key != NULL) {
- PK11_FreeSymKey(mat->write_mac_key);
- mat->write_mac_key = NULL;
+ PK11_FreeSymKey(mat->write_mac_key);
+ mat->write_mac_key = NULL;
}
if (mat->write_mac_context != NULL) {
- PK11_DestroyContext(mat->write_mac_context, PR_TRUE);
- mat->write_mac_context = NULL;
+ PK11_DestroyContext(mat->write_mac_context, PR_TRUE);
+ mat->write_mac_context = NULL;
}
}
-/* Called from ssl3_SendChangeCipherSpecs() and
-** ssl3_HandleChangeCipherSpecs()
+/* Called from ssl3_SendChangeCipherSpecs() and
+** ssl3_HandleChangeCipherSpecs()
** ssl3_DestroySSL3Info
** Caller must hold SpecWriteLock.
*/
@@ -1413,34 +1428,34 @@ void
ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName)
{
PRBool freeit = (PRBool)(!spec->bypassCiphers);
-/* PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); Don't have ss! */
+ /* PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); Don't have ss! */
if (spec->destroy) {
- spec->destroy(spec->encodeContext, freeit);
- spec->destroy(spec->decodeContext, freeit);
- spec->encodeContext = NULL; /* paranoia */
- spec->decodeContext = NULL;
+ spec->destroy(spec->encodeContext, freeit);
+ spec->destroy(spec->decodeContext, freeit);
+ spec->encodeContext = NULL; /* paranoia */
+ spec->decodeContext = NULL;
}
if (spec->destroyCompressContext && spec->compressContext) {
- spec->destroyCompressContext(spec->compressContext, 1);
- spec->compressContext = NULL;
+ spec->destroyCompressContext(spec->compressContext, 1);
+ spec->compressContext = NULL;
}
if (spec->destroyDecompressContext && spec->decompressContext) {
- spec->destroyDecompressContext(spec->decompressContext, 1);
- spec->decompressContext = NULL;
+ spec->destroyDecompressContext(spec->decompressContext, 1);
+ spec->decompressContext = NULL;
}
if (freeSrvName && spec->srvVirtName.data) {
SECITEM_FreeItem(&spec->srvVirtName, PR_FALSE);
}
if (spec->master_secret != NULL) {
- PK11_FreeSymKey(spec->master_secret);
- spec->master_secret = NULL;
+ PK11_FreeSymKey(spec->master_secret);
+ spec->master_secret = NULL;
}
spec->msItem.data = NULL;
- spec->msItem.len = 0;
+ spec->msItem.len = 0;
ssl3_CleanupKeyMaterial(&spec->client);
ssl3_CleanupKeyMaterial(&spec->server);
spec->bypassCiphers = PR_FALSE;
- spec->destroy=NULL;
+ spec->destroy = NULL;
spec->destroyCompressContext = NULL;
spec->destroyDecompressContext = NULL;
}
@@ -1451,21 +1466,21 @@ ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName)
** Caller must hold the ssl3 handshake lock.
** Acquires & releases SpecWriteLock.
*/
-static SECStatus
+SECStatus
ssl3_SetupPendingCipherSpec(sslSocket *ss)
{
- ssl3CipherSpec * pwSpec;
- ssl3CipherSpec * cwSpec;
- ssl3CipherSuite suite = ss->ssl3.hs.cipher_suite;
- SSL3MACAlgorithm mac;
- SSL3BulkCipher cipher;
- SSL3KeyExchangeAlgorithm kea;
+ ssl3CipherSpec *pwSpec;
+ ssl3CipherSpec *cwSpec;
+ ssl3CipherSuite suite = ss->ssl3.hs.cipher_suite;
+ SSL3MACAlgorithm mac;
+ SSL3BulkCipher cipher;
+ SSL3KeyExchangeAlgorithm kea;
const ssl3CipherSuiteDef *suite_def;
- PRBool isTLS;
+ PRBool isTLS;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
- ssl_GetSpecWriteLock(ss); /*******************************/
+ ssl_GetSpecWriteLock(ss); /*******************************/
pwSpec = ss->ssl3.pwSpec;
PORT_Assert(pwSpec == ss->ssl3.prSpec);
@@ -1473,48 +1488,48 @@ ssl3_SetupPendingCipherSpec(sslSocket *ss)
/* This hack provides maximal interoperability with SSL 3 servers. */
cwSpec = ss->ssl3.cwSpec;
if (cwSpec->mac_def->mac == mac_null) {
- /* SSL records are not being MACed. */
- cwSpec->version = ss->version;
+ /* SSL records are not being MACed. */
+ cwSpec->version = ss->version;
}
- pwSpec->version = ss->version;
- isTLS = (PRBool)(pwSpec->version > SSL_LIBRARY_VERSION_3_0);
+ pwSpec->version = ss->version;
+ isTLS = (PRBool)(pwSpec->version > SSL_LIBRARY_VERSION_3_0);
SSL_TRC(3, ("%d: SSL3[%d]: Set XXX Pending Cipher Suite to 0x%04x",
- SSL_GETPID(), ss->fd, suite));
+ SSL_GETPID(), ss->fd, suite));
suite_def = ssl_LookupCipherSuiteDef(suite);
if (suite_def == NULL) {
- ssl_ReleaseSpecWriteLock(ss);
- return SECFailure; /* error code set by ssl_LookupCipherSuiteDef */
+ ssl_ReleaseSpecWriteLock(ss);
+ return SECFailure; /* error code set by ssl_LookupCipherSuiteDef */
}
if (IS_DTLS(ss)) {
- /* Double-check that we did not pick an RC4 suite */
- PORT_Assert((suite_def->bulk_cipher_alg != cipher_rc4) &&
- (suite_def->bulk_cipher_alg != cipher_rc4_40) &&
- (suite_def->bulk_cipher_alg != cipher_rc4_56));
+ /* Double-check that we did not pick an RC4 suite */
+ PORT_Assert((suite_def->bulk_cipher_alg != cipher_rc4) &&
+ (suite_def->bulk_cipher_alg != cipher_rc4_40) &&
+ (suite_def->bulk_cipher_alg != cipher_rc4_56));
}
cipher = suite_def->bulk_cipher_alg;
- kea = suite_def->key_exchange_alg;
- mac = suite_def->mac_alg;
+ kea = suite_def->key_exchange_alg;
+ mac = suite_def->mac_alg;
if (mac <= ssl_mac_sha && mac != ssl_mac_null && isTLS)
- mac += 2;
+ mac += 2;
ss->ssl3.hs.suite_def = suite_def;
- ss->ssl3.hs.kea_def = &kea_defs[kea];
+ ss->ssl3.hs.kea_def = &kea_defs[kea];
PORT_Assert(ss->ssl3.hs.kea_def->kea == kea);
- pwSpec->cipher_def = &bulk_cipher_defs[cipher];
+ pwSpec->cipher_def = &bulk_cipher_defs[cipher];
PORT_Assert(pwSpec->cipher_def->cipher == cipher);
pwSpec->mac_def = &mac_defs[mac];
PORT_Assert(pwSpec->mac_def->mac == mac);
- ss->sec.keyBits = pwSpec->cipher_def->key_size * BPB;
+ ss->sec.keyBits = pwSpec->cipher_def->key_size * BPB;
ss->sec.secretKeyBits = pwSpec->cipher_def->secret_key_size * BPB;
- ss->sec.cipherType = cipher;
+ ss->sec.cipherType = cipher;
pwSpec->encodeContext = NULL;
pwSpec->decodeContext = NULL;
@@ -1525,21 +1540,25 @@ ssl3_SetupPendingCipherSpec(sslSocket *ss)
pwSpec->compressContext = NULL;
pwSpec->decompressContext = NULL;
- ssl_ReleaseSpecWriteLock(ss); /*******************************/
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ PORT_Assert(ss->ssl3.hs.kea_def->ephemeral);
+ PORT_Assert(pwSpec->cipher_def->type == type_aead);
+ }
+ ssl_ReleaseSpecWriteLock(ss); /*******************************/
return SECSuccess;
}
-#ifdef NSS_ENABLE_ZLIB
+#ifdef NSS_SSL_ENABLE_ZLIB
#define SSL3_DEFLATE_CONTEXT_SIZE sizeof(z_stream)
static SECStatus
ssl3_MapZlibError(int zlib_error)
{
switch (zlib_error) {
- case Z_OK:
- return SECSuccess;
- default:
- return SECFailure;
+ case Z_OK:
+ return SECSuccess;
+ default:
+ return SECFailure;
}
}
@@ -1578,7 +1597,7 @@ ssl3_DeflateCompress(void *void_context, unsigned char *out, int *out_len,
return SECSuccess;
}
- context->next_in = (unsigned char*) in;
+ context->next_in = (unsigned char *)in;
context->avail_in = inlen;
context->next_out = out;
context->avail_out = maxout;
@@ -1607,7 +1626,7 @@ ssl3_DeflateDecompress(void *void_context, unsigned char *out, int *out_len,
return SECSuccess;
}
- context->next_in = (unsigned char*) in;
+ context->next_in = (unsigned char *)in;
context->avail_in = inlen;
context->next_out = out;
context->avail_out = maxout;
@@ -1636,7 +1655,7 @@ ssl3_DestroyDecompressContext(void *void_context, PRBool unused)
return SECSuccess;
}
-#endif /* NSS_ENABLE_ZLIB */
+#endif /* NSS_SSL_ENABLE_ZLIB */
/* Initialize the compression functions and contexts for the given
* CipherSpec. */
@@ -1645,30 +1664,30 @@ ssl3_InitCompressionContext(ssl3CipherSpec *pwSpec)
{
/* Setup the compression functions */
switch (pwSpec->compression_method) {
- case ssl_compression_null:
- pwSpec->compressor = NULL;
- pwSpec->decompressor = NULL;
- pwSpec->compressContext = NULL;
- pwSpec->decompressContext = NULL;
- pwSpec->destroyCompressContext = NULL;
- pwSpec->destroyDecompressContext = NULL;
- break;
-#ifdef NSS_ENABLE_ZLIB
- case ssl_compression_deflate:
- pwSpec->compressor = ssl3_DeflateCompress;
- pwSpec->decompressor = ssl3_DeflateDecompress;
- pwSpec->compressContext = PORT_Alloc(SSL3_DEFLATE_CONTEXT_SIZE);
- pwSpec->decompressContext = PORT_Alloc(SSL3_DEFLATE_CONTEXT_SIZE);
- pwSpec->destroyCompressContext = ssl3_DestroyCompressContext;
- pwSpec->destroyDecompressContext = ssl3_DestroyDecompressContext;
- ssl3_DeflateInit(pwSpec->compressContext);
- ssl3_InflateInit(pwSpec->decompressContext);
- break;
-#endif /* NSS_ENABLE_ZLIB */
- default:
- PORT_Assert(0);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
+ case ssl_compression_null:
+ pwSpec->compressor = NULL;
+ pwSpec->decompressor = NULL;
+ pwSpec->compressContext = NULL;
+ pwSpec->decompressContext = NULL;
+ pwSpec->destroyCompressContext = NULL;
+ pwSpec->destroyDecompressContext = NULL;
+ break;
+#ifdef NSS_SSL_ENABLE_ZLIB
+ case ssl_compression_deflate:
+ pwSpec->compressor = ssl3_DeflateCompress;
+ pwSpec->decompressor = ssl3_DeflateDecompress;
+ pwSpec->compressContext = PORT_Alloc(SSL3_DEFLATE_CONTEXT_SIZE);
+ pwSpec->decompressContext = PORT_Alloc(SSL3_DEFLATE_CONTEXT_SIZE);
+ pwSpec->destroyCompressContext = ssl3_DestroyCompressContext;
+ pwSpec->destroyDecompressContext = ssl3_DestroyDecompressContext;
+ ssl3_DeflateInit(pwSpec->compressContext);
+ ssl3_InflateInit(pwSpec->decompressContext);
+ break;
+#endif /* NSS_SSL_ENABLE_ZLIB */
+ default:
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
}
return SECSuccess;
@@ -1683,156 +1702,157 @@ ssl3_InitCompressionContext(ssl3CipherSpec *pwSpec)
static SECStatus
ssl3_InitPendingContextsBypass(sslSocket *ss)
{
- ssl3CipherSpec * pwSpec;
- const ssl3BulkCipherDef *cipher_def;
- void * serverContext = NULL;
- void * clientContext = NULL;
- BLapiInitContextFunc initFn = (BLapiInitContextFunc)NULL;
- int mode = 0;
- unsigned int optArg1 = 0;
- unsigned int optArg2 = 0;
- PRBool server_encrypts = ss->sec.isServer;
- SSLCipherAlgorithm calg;
- SECStatus rv;
+ ssl3CipherSpec *pwSpec;
+ const ssl3BulkCipherDef *cipher_def;
+ void *serverContext = NULL;
+ void *clientContext = NULL;
+ BLapiInitContextFunc initFn = (BLapiInitContextFunc)NULL;
+ int mode = 0;
+ unsigned int optArg1 = 0;
+ unsigned int optArg2 = 0;
+ PRBool server_encrypts = ss->sec.isServer;
+ SSLCipherAlgorithm calg;
+ SECStatus rv;
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
- pwSpec = ss->ssl3.pwSpec;
- cipher_def = pwSpec->cipher_def;
+ pwSpec = ss->ssl3.pwSpec;
+ cipher_def = pwSpec->cipher_def;
calg = cipher_def->calg;
if (calg == ssl_calg_aes_gcm) {
- pwSpec->encode = NULL;
- pwSpec->decode = NULL;
- pwSpec->destroy = NULL;
- pwSpec->encodeContext = NULL;
- pwSpec->decodeContext = NULL;
- pwSpec->aead = ssl3_AESGCMBypass;
- ssl3_InitCompressionContext(pwSpec);
- return SECSuccess;
+ pwSpec->encode = NULL;
+ pwSpec->decode = NULL;
+ pwSpec->destroy = NULL;
+ pwSpec->encodeContext = NULL;
+ pwSpec->decodeContext = NULL;
+ pwSpec->aead = ssl3_AESGCMBypass;
+ ssl3_InitCompressionContext(pwSpec);
+ return SECSuccess;
}
serverContext = pwSpec->server.cipher_context;
clientContext = pwSpec->client.cipher_context;
switch (calg) {
- case ssl_calg_null:
- pwSpec->encode = Null_Cipher;
- pwSpec->decode = Null_Cipher;
- pwSpec->destroy = NULL;
- goto success;
-
- case ssl_calg_rc4:
- initFn = (BLapiInitContextFunc)RC4_InitContext;
- pwSpec->encode = (SSLCipher) RC4_Encrypt;
- pwSpec->decode = (SSLCipher) RC4_Decrypt;
- pwSpec->destroy = (SSLDestroy) RC4_DestroyContext;
- break;
- case ssl_calg_rc2:
- initFn = (BLapiInitContextFunc)RC2_InitContext;
- mode = NSS_RC2_CBC;
- optArg1 = cipher_def->key_size;
- pwSpec->encode = (SSLCipher) RC2_Encrypt;
- pwSpec->decode = (SSLCipher) RC2_Decrypt;
- pwSpec->destroy = (SSLDestroy) RC2_DestroyContext;
- break;
- case ssl_calg_des:
- initFn = (BLapiInitContextFunc)DES_InitContext;
- mode = NSS_DES_CBC;
- optArg1 = server_encrypts;
- pwSpec->encode = (SSLCipher) DES_Encrypt;
- pwSpec->decode = (SSLCipher) DES_Decrypt;
- pwSpec->destroy = (SSLDestroy) DES_DestroyContext;
- break;
- case ssl_calg_3des:
- initFn = (BLapiInitContextFunc)DES_InitContext;
- mode = NSS_DES_EDE3_CBC;
- optArg1 = server_encrypts;
- pwSpec->encode = (SSLCipher) DES_Encrypt;
- pwSpec->decode = (SSLCipher) DES_Decrypt;
- pwSpec->destroy = (SSLDestroy) DES_DestroyContext;
- break;
- case ssl_calg_aes:
- initFn = (BLapiInitContextFunc)AES_InitContext;
- mode = NSS_AES_CBC;
- optArg1 = server_encrypts;
- optArg2 = AES_BLOCK_SIZE;
- pwSpec->encode = (SSLCipher) AES_Encrypt;
- pwSpec->decode = (SSLCipher) AES_Decrypt;
- pwSpec->destroy = (SSLDestroy) AES_DestroyContext;
- break;
-
- case ssl_calg_camellia:
- initFn = (BLapiInitContextFunc)Camellia_InitContext;
- mode = NSS_CAMELLIA_CBC;
- optArg1 = server_encrypts;
- optArg2 = CAMELLIA_BLOCK_SIZE;
- pwSpec->encode = (SSLCipher) Camellia_Encrypt;
- pwSpec->decode = (SSLCipher) Camellia_Decrypt;
- pwSpec->destroy = (SSLDestroy) Camellia_DestroyContext;
- break;
-
- case ssl_calg_seed:
- initFn = (BLapiInitContextFunc)SEED_InitContext;
- mode = NSS_SEED_CBC;
- optArg1 = server_encrypts;
- optArg2 = SEED_BLOCK_SIZE;
- pwSpec->encode = (SSLCipher) SEED_Encrypt;
- pwSpec->decode = (SSLCipher) SEED_Decrypt;
- pwSpec->destroy = (SSLDestroy) SEED_DestroyContext;
- break;
-
- case ssl_calg_idea:
- case ssl_calg_fortezza :
- default:
- PORT_Assert(0);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- goto bail_out;
+ case ssl_calg_null:
+ pwSpec->encode = Null_Cipher;
+ pwSpec->decode = Null_Cipher;
+ pwSpec->destroy = NULL;
+ goto success;
+
+ case ssl_calg_rc4:
+ initFn = (BLapiInitContextFunc)RC4_InitContext;
+ pwSpec->encode = (SSLCipher)RC4_Encrypt;
+ pwSpec->decode = (SSLCipher)RC4_Decrypt;
+ pwSpec->destroy = (SSLDestroy)RC4_DestroyContext;
+ break;
+ case ssl_calg_rc2:
+ initFn = (BLapiInitContextFunc)RC2_InitContext;
+ mode = NSS_RC2_CBC;
+ optArg1 = cipher_def->key_size;
+ pwSpec->encode = (SSLCipher)RC2_Encrypt;
+ pwSpec->decode = (SSLCipher)RC2_Decrypt;
+ pwSpec->destroy = (SSLDestroy)RC2_DestroyContext;
+ break;
+ case ssl_calg_des:
+ initFn = (BLapiInitContextFunc)DES_InitContext;
+ mode = NSS_DES_CBC;
+ optArg1 = server_encrypts;
+ pwSpec->encode = (SSLCipher)DES_Encrypt;
+ pwSpec->decode = (SSLCipher)DES_Decrypt;
+ pwSpec->destroy = (SSLDestroy)DES_DestroyContext;
+ break;
+ case ssl_calg_3des:
+ initFn = (BLapiInitContextFunc)DES_InitContext;
+ mode = NSS_DES_EDE3_CBC;
+ optArg1 = server_encrypts;
+ pwSpec->encode = (SSLCipher)DES_Encrypt;
+ pwSpec->decode = (SSLCipher)DES_Decrypt;
+ pwSpec->destroy = (SSLDestroy)DES_DestroyContext;
+ break;
+ case ssl_calg_aes:
+ initFn = (BLapiInitContextFunc)AES_InitContext;
+ mode = NSS_AES_CBC;
+ optArg1 = server_encrypts;
+ optArg2 = AES_BLOCK_SIZE;
+ pwSpec->encode = (SSLCipher)AES_Encrypt;
+ pwSpec->decode = (SSLCipher)AES_Decrypt;
+ pwSpec->destroy = (SSLDestroy)AES_DestroyContext;
+ break;
+
+ case ssl_calg_camellia:
+ initFn = (BLapiInitContextFunc)Camellia_InitContext;
+ mode = NSS_CAMELLIA_CBC;
+ optArg1 = server_encrypts;
+ optArg2 = CAMELLIA_BLOCK_SIZE;
+ pwSpec->encode = (SSLCipher)Camellia_Encrypt;
+ pwSpec->decode = (SSLCipher)Camellia_Decrypt;
+ pwSpec->destroy = (SSLDestroy)Camellia_DestroyContext;
+ break;
+
+ case ssl_calg_seed:
+ initFn = (BLapiInitContextFunc)SEED_InitContext;
+ mode = NSS_SEED_CBC;
+ optArg1 = server_encrypts;
+ optArg2 = SEED_BLOCK_SIZE;
+ pwSpec->encode = (SSLCipher)SEED_Encrypt;
+ pwSpec->decode = (SSLCipher)SEED_Decrypt;
+ pwSpec->destroy = (SSLDestroy)SEED_DestroyContext;
+ break;
+
+ case ssl_calg_idea:
+ case ssl_calg_fortezza:
+ default:
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ goto bail_out;
}
rv = (*initFn)(serverContext,
- pwSpec->server.write_key_item.data,
- pwSpec->server.write_key_item.len,
- pwSpec->server.write_iv_item.data,
- mode, optArg1, optArg2);
+ pwSpec->server.write_key_item.data,
+ pwSpec->server.write_key_item.len,
+ pwSpec->server.write_iv_item.data,
+ mode, optArg1, optArg2);
if (rv != SECSuccess) {
- PORT_Assert(0);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- goto bail_out;
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ goto bail_out;
}
switch (calg) {
- case ssl_calg_des:
- case ssl_calg_3des:
- case ssl_calg_aes:
- case ssl_calg_camellia:
- case ssl_calg_seed:
- /* For block ciphers, if the server is encrypting, then the client
- * is decrypting, and vice versa.
- */
- optArg1 = !optArg1;
- break;
- /* kill warnings. */
- case ssl_calg_null:
- case ssl_calg_rc4:
- case ssl_calg_rc2:
- case ssl_calg_idea:
- case ssl_calg_fortezza:
- case ssl_calg_aes_gcm:
- break;
+ case ssl_calg_des:
+ case ssl_calg_3des:
+ case ssl_calg_aes:
+ case ssl_calg_camellia:
+ case ssl_calg_seed:
+ /* For block ciphers, if the server is encrypting, then the client
+ * is decrypting, and vice versa.
+ */
+ optArg1 = !optArg1;
+ break;
+ /* kill warnings. */
+ case ssl_calg_null:
+ case ssl_calg_rc4:
+ case ssl_calg_rc2:
+ case ssl_calg_idea:
+ case ssl_calg_fortezza:
+ case ssl_calg_aes_gcm:
+ case ssl_calg_chacha20:
+ break;
}
rv = (*initFn)(clientContext,
- pwSpec->client.write_key_item.data,
- pwSpec->client.write_key_item.len,
- pwSpec->client.write_iv_item.data,
- mode, optArg1, optArg2);
+ pwSpec->client.write_key_item.data,
+ pwSpec->client.write_key_item.len,
+ pwSpec->client.write_iv_item.data,
+ mode, optArg1, optArg2);
if (rv != SECSuccess) {
- PORT_Assert(0);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- goto bail_out;
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ goto bail_out;
}
pwSpec->encodeContext = (ss->sec.isServer) ? serverContext : clientContext;
@@ -1848,24 +1868,25 @@ bail_out:
}
#endif
-/* This function should probably be moved to pk11wrap and be named
+/* This function should probably be moved to pk11wrap and be named
* PK11_ParamFromIVAndEffectiveKeyBits
*/
static SECItem *
ssl3_ParamFromIV(CK_MECHANISM_TYPE mtype, SECItem *iv, CK_ULONG ulEffectiveBits)
{
- SECItem * param = PK11_ParamFromIV(mtype, iv);
- if (param && param->data && param->len >= sizeof(CK_RC2_PARAMS)) {
- switch (mtype) {
- case CKM_RC2_KEY_GEN:
- case CKM_RC2_ECB:
- case CKM_RC2_CBC:
- case CKM_RC2_MAC:
- case CKM_RC2_MAC_GENERAL:
- case CKM_RC2_CBC_PAD:
- *(CK_RC2_PARAMS *)param->data = ulEffectiveBits;
- default: break;
- }
+ SECItem *param = PK11_ParamFromIV(mtype, iv);
+ if (param && param->data && param->len >= sizeof(CK_RC2_PARAMS)) {
+ switch (mtype) {
+ case CKM_RC2_KEY_GEN:
+ case CKM_RC2_ECB:
+ case CKM_RC2_CBC:
+ case CKM_RC2_MAC:
+ case CKM_RC2_MAC_GENERAL:
+ case CKM_RC2_CBC_PAD:
+ *(CK_RC2_PARAMS *)param->data = ulEffectiveBits;
+ default:
+ break;
+ }
}
return param;
}
@@ -1884,161 +1905,105 @@ ssl3_ParamFromIV(CK_MECHANISM_TYPE mtype, SECItem *iv, CK_ULONG ulEffectiveBits)
*/
static unsigned int
ssl3_BuildRecordPseudoHeader(unsigned char *out,
- SSL3SequenceNumber seq_num,
- SSL3ContentType type,
- PRBool includesVersion,
- SSL3ProtocolVersion version,
- PRBool isDTLS,
- int length)
+ SSL3SequenceNumber seq_num,
+ SSL3ContentType type,
+ PRBool includesVersion,
+ SSL3ProtocolVersion version,
+ PRBool isDTLS,
+ int length)
{
out[0] = (unsigned char)(seq_num.high >> 24);
out[1] = (unsigned char)(seq_num.high >> 16);
- out[2] = (unsigned char)(seq_num.high >> 8);
- out[3] = (unsigned char)(seq_num.high >> 0);
- out[4] = (unsigned char)(seq_num.low >> 24);
- out[5] = (unsigned char)(seq_num.low >> 16);
- out[6] = (unsigned char)(seq_num.low >> 8);
- out[7] = (unsigned char)(seq_num.low >> 0);
+ out[2] = (unsigned char)(seq_num.high >> 8);
+ out[3] = (unsigned char)(seq_num.high >> 0);
+ out[4] = (unsigned char)(seq_num.low >> 24);
+ out[5] = (unsigned char)(seq_num.low >> 16);
+ out[6] = (unsigned char)(seq_num.low >> 8);
+ out[7] = (unsigned char)(seq_num.low >> 0);
out[8] = type;
/* SSL3 MAC doesn't include the record's version field. */
if (!includesVersion) {
- out[9] = MSB(length);
- out[10] = LSB(length);
- return 11;
+ out[9] = MSB(length);
+ out[10] = LSB(length);
+ return 11;
}
/* TLS MAC and AEAD additional data include version. */
if (isDTLS) {
- SSL3ProtocolVersion dtls_version;
+ SSL3ProtocolVersion dtls_version;
- dtls_version = dtls_TLSVersionToDTLSVersion(version);
- out[9] = MSB(dtls_version);
- out[10] = LSB(dtls_version);
+ dtls_version = dtls_TLSVersionToDTLSVersion(version);
+ out[9] = MSB(dtls_version);
+ out[10] = LSB(dtls_version);
} else {
- out[9] = MSB(version);
- out[10] = LSB(version);
+ out[9] = MSB(version);
+ out[10] = LSB(version);
}
out[11] = MSB(length);
out[12] = LSB(length);
return 13;
}
-typedef SECStatus (*PK11CryptFcn)(
- PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism, SECItem *param,
- unsigned char *out, unsigned int *outLen, unsigned int maxLen,
- const unsigned char *in, unsigned int inLen);
-
-static PK11CryptFcn pk11_encrypt = NULL;
-static PK11CryptFcn pk11_decrypt = NULL;
-
-static PRCallOnceType resolvePK11CryptOnce;
-
-static PRStatus
-ssl3_ResolvePK11CryptFunctions(void)
-{
-#ifdef LINUX
- /* On Linux we use the system NSS libraries. Look up the PK11_Encrypt and
- * PK11_Decrypt functions at run time. */
- pk11_encrypt = (PK11CryptFcn)dlsym(RTLD_DEFAULT, "PK11_Encrypt");
- pk11_decrypt = (PK11CryptFcn)dlsym(RTLD_DEFAULT, "PK11_Decrypt");
- return PR_SUCCESS;
-#else
- /* On other platforms we use our own copy of NSS. PK11_Encrypt and
- * PK11_Decrypt are known to be available. */
- pk11_encrypt = PK11_Encrypt;
- pk11_decrypt = PK11_Decrypt;
- return PR_SUCCESS;
-#endif
-}
-
-/*
- * In NSS 3.15, PK11_Encrypt and PK11_Decrypt were added to provide access
- * to the AES GCM implementation in the NSS softoken. So the presence of
- * these two functions implies the NSS version supports AES GCM.
- */
-static PRBool
-ssl3_HasGCMSupport(void)
-{
- (void)PR_CallOnce(&resolvePK11CryptOnce, ssl3_ResolvePK11CryptFunctions);
- return pk11_encrypt != NULL;
-}
-
-/* On this socket, disable the GCM cipher suites */
-SECStatus
-ssl3_DisableGCMSuites(sslSocket * ss)
-{
- unsigned int i;
-
- for (i = 0; i < PR_ARRAY_SIZE(cipher_suite_defs); i++) {
- const ssl3CipherSuiteDef *cipher_def = &cipher_suite_defs[i];
- if (cipher_def->bulk_cipher_alg == cipher_aes_128_gcm) {
- SECStatus rv = ssl3_CipherPrefSet(ss, cipher_def->cipher_suite,
- PR_FALSE);
- PORT_Assert(rv == SECSuccess); /* else is coding error */
- }
- }
- return SECSuccess;
-}
-
static SECStatus
ssl3_AESGCM(ssl3KeyMaterial *keys,
- PRBool doDecrypt,
- unsigned char *out,
- int *outlen,
- int maxout,
- const unsigned char *in,
- int inlen,
- const unsigned char *additionalData,
- int additionalDataLen)
-{
- SECItem param;
- SECStatus rv = SECFailure;
- unsigned char nonce[12];
- unsigned int uOutLen;
- CK_GCM_PARAMS gcmParams;
-
- static const int tagSize = 16;
- static const int explicitNonceLen = 8;
+ PRBool doDecrypt,
+ unsigned char *out,
+ int *outlen,
+ int maxout,
+ const unsigned char *in,
+ int inlen,
+ const unsigned char *additionalData,
+ int additionalDataLen)
+{
+ SECItem param;
+ SECStatus rv = SECFailure;
+ unsigned char nonce[12];
+ unsigned int uOutLen;
+ CK_GCM_PARAMS gcmParams;
+
+ const int tagSize = bulk_cipher_defs[cipher_aes_128_gcm].tag_size;
+ const int explicitNonceLen =
+ bulk_cipher_defs[cipher_aes_128_gcm].explicit_nonce_size;
/* See https://tools.ietf.org/html/rfc5288#section-3 for details of how the
* nonce is formed. */
memcpy(nonce, keys->write_iv, 4);
if (doDecrypt) {
- memcpy(nonce + 4, in, explicitNonceLen);
- in += explicitNonceLen;
- inlen -= explicitNonceLen;
- *outlen = 0;
+ memcpy(nonce + 4, in, explicitNonceLen);
+ in += explicitNonceLen;
+ inlen -= explicitNonceLen;
+ *outlen = 0;
} else {
- if (maxout < explicitNonceLen) {
- PORT_SetError(SEC_ERROR_INPUT_LEN);
- return SECFailure;
+ if (maxout < explicitNonceLen) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ return SECFailure;
}
- /* Use the 64-bit sequence number as the explicit nonce. */
- memcpy(nonce + 4, additionalData, explicitNonceLen);
- memcpy(out, additionalData, explicitNonceLen);
- out += explicitNonceLen;
- maxout -= explicitNonceLen;
- *outlen = explicitNonceLen;
+ /* Use the 64-bit sequence number as the explicit nonce. */
+ memcpy(nonce + 4, additionalData, explicitNonceLen);
+ memcpy(out, additionalData, explicitNonceLen);
+ out += explicitNonceLen;
+ maxout -= explicitNonceLen;
+ *outlen = explicitNonceLen;
}
param.type = siBuffer;
- param.data = (unsigned char *) &gcmParams;
+ param.data = (unsigned char *)&gcmParams;
param.len = sizeof(gcmParams);
gcmParams.pIv = nonce;
gcmParams.ulIvLen = sizeof(nonce);
- gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */
+ gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */
gcmParams.ulAADLen = additionalDataLen;
gcmParams.ulTagBits = tagSize * 8;
if (doDecrypt) {
- rv = pk11_decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
- maxout, in, inlen);
+ rv = PK11_Decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
+ maxout, in, inlen);
} else {
- rv = pk11_encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
- maxout, in, inlen);
+ rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
+ maxout, in, inlen);
}
- *outlen += (int) uOutLen;
+ *outlen += (int)uOutLen;
return rv;
}
@@ -2046,112 +2011,122 @@ ssl3_AESGCM(ssl3KeyMaterial *keys,
#ifndef NO_PKCS11_BYPASS
static SECStatus
ssl3_AESGCMBypass(ssl3KeyMaterial *keys,
- PRBool doDecrypt,
- unsigned char *out,
- int *outlen,
- int maxout,
- const unsigned char *in,
- int inlen,
- const unsigned char *additionalData,
- int additionalDataLen)
-{
- SECStatus rv = SECFailure;
- unsigned char nonce[12];
- unsigned int uOutLen;
- AESContext *cx;
- CK_GCM_PARAMS gcmParams;
-
- static const int tagSize = 16;
- static const int explicitNonceLen = 8;
+ PRBool doDecrypt,
+ unsigned char *out,
+ int *outlen,
+ int maxout,
+ const unsigned char *in,
+ int inlen,
+ const unsigned char *additionalData,
+ int additionalDataLen)
+{
+ SECStatus rv = SECFailure;
+ unsigned char nonce[12];
+ unsigned int uOutLen;
+ AESContext *cx;
+ CK_GCM_PARAMS gcmParams;
+
+ const int tagSize = bulk_cipher_defs[cipher_aes_128_gcm].tag_size;
+ const int explicitNonceLen =
+ bulk_cipher_defs[cipher_aes_128_gcm].explicit_nonce_size;
/* See https://tools.ietf.org/html/rfc5288#section-3 for details of how the
* nonce is formed. */
PORT_Assert(keys->write_iv_item.len == 4);
if (keys->write_iv_item.len != 4) {
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
}
memcpy(nonce, keys->write_iv_item.data, 4);
if (doDecrypt) {
- memcpy(nonce + 4, in, explicitNonceLen);
- in += explicitNonceLen;
- inlen -= explicitNonceLen;
- *outlen = 0;
+ memcpy(nonce + 4, in, explicitNonceLen);
+ in += explicitNonceLen;
+ inlen -= explicitNonceLen;
+ *outlen = 0;
} else {
- if (maxout < explicitNonceLen) {
- PORT_SetError(SEC_ERROR_INPUT_LEN);
- return SECFailure;
+ if (maxout < explicitNonceLen) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ return SECFailure;
}
- /* Use the 64-bit sequence number as the explicit nonce. */
- memcpy(nonce + 4, additionalData, explicitNonceLen);
- memcpy(out, additionalData, explicitNonceLen);
- out += explicitNonceLen;
- maxout -= explicitNonceLen;
- *outlen = explicitNonceLen;
+ /* Use the 64-bit sequence number as the explicit nonce. */
+ memcpy(nonce + 4, additionalData, explicitNonceLen);
+ memcpy(out, additionalData, explicitNonceLen);
+ out += explicitNonceLen;
+ maxout -= explicitNonceLen;
+ *outlen = explicitNonceLen;
}
gcmParams.pIv = nonce;
gcmParams.ulIvLen = sizeof(nonce);
- gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */
+ gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */
gcmParams.ulAADLen = additionalDataLen;
gcmParams.ulTagBits = tagSize * 8;
cx = (AESContext *)keys->cipher_context;
rv = AES_InitContext(cx, keys->write_key_item.data,
- keys->write_key_item.len,
- (unsigned char *)&gcmParams, NSS_AES_GCM, !doDecrypt,
- AES_BLOCK_SIZE);
+ keys->write_key_item.len,
+ (unsigned char *)&gcmParams, NSS_AES_GCM, !doDecrypt,
+ AES_BLOCK_SIZE);
if (rv != SECSuccess) {
- return rv;
+ return rv;
}
if (doDecrypt) {
- rv = AES_Decrypt(cx, out, &uOutLen, maxout, in, inlen);
+ rv = AES_Decrypt(cx, out, &uOutLen, maxout, in, inlen);
} else {
- rv = AES_Encrypt(cx, out, &uOutLen, maxout, in, inlen);
+ rv = AES_Encrypt(cx, out, &uOutLen, maxout, in, inlen);
}
AES_DestroyContext(cx, PR_FALSE);
- *outlen += (int) uOutLen;
+ *outlen += (int)uOutLen;
return rv;
}
#endif
static SECStatus
-ssl3_ChaCha20Poly1305(
- ssl3KeyMaterial *keys,
- PRBool doDecrypt,
- unsigned char *out,
- int *outlen,
- int maxout,
- const unsigned char *in,
- int inlen,
- const unsigned char *additionalData,
- int additionalDataLen)
-{
- SECItem param;
- SECStatus rv = SECFailure;
- unsigned int uOutLen;
+ssl3_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt,
+ unsigned char *out, int *outlen, int maxout,
+ const unsigned char *in, int inlen,
+ const unsigned char *additionalData,
+ int additionalDataLen)
+{
+ size_t i;
+ SECItem param;
+ SECStatus rv = SECFailure;
+ unsigned int uOutLen;
+ unsigned char nonce[12];
CK_NSS_AEAD_PARAMS aeadParams;
- static const int tagSize = 16;
+
+ const int tagSize = bulk_cipher_defs[cipher_chacha20].tag_size;
+
+ /* See
+ * https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-04#section-2
+ * for details of how the nonce is formed. */
+ PORT_Memcpy(nonce, keys->write_iv, 12);
+
+ /* XOR the last 8 bytes of the IV with the sequence number. */
+ PORT_Assert(additionalDataLen >= 8);
+ for (i = 0; i < 8; ++i) {
+ nonce[4 + i] ^= additionalData[i];
+ }
param.type = siBuffer;
param.len = sizeof(aeadParams);
- param.data = (unsigned char *) &aeadParams;
+ param.data = (unsigned char *)&aeadParams;
memset(&aeadParams, 0, sizeof(aeadParams));
- aeadParams.pIv = (unsigned char *) additionalData;
- aeadParams.ulIvLen = 8;
- aeadParams.pAAD = (unsigned char *) additionalData;
+ aeadParams.pNonce = nonce;
+ aeadParams.ulNonceLen = sizeof(nonce);
+ aeadParams.pAAD = (unsigned char *)additionalData;
aeadParams.ulAADLen = additionalDataLen;
aeadParams.ulTagLen = tagSize;
if (doDecrypt) {
- rv = pk11_decrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, &param,
- out, &uOutLen, maxout, in, inlen);
+ rv = PK11_Decrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, &param,
+ out, &uOutLen, maxout, in, inlen);
} else {
- rv = pk11_encrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, &param,
- out, &uOutLen, maxout, in, inlen);
+ rv = PK11_Encrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, &param,
+ out, &uOutLen, maxout, in, inlen);
}
- *outlen = (int) uOutLen;
+ *outlen = (int)uOutLen;
return rv;
}
@@ -2163,129 +2138,137 @@ ssl3_ChaCha20Poly1305(
static SECStatus
ssl3_InitPendingContextsPKCS11(sslSocket *ss)
{
- ssl3CipherSpec * pwSpec;
- const ssl3BulkCipherDef *cipher_def;
- PK11Context * serverContext = NULL;
- PK11Context * clientContext = NULL;
- SECItem * param;
- CK_MECHANISM_TYPE mechanism;
- CK_MECHANISM_TYPE mac_mech;
- CK_ULONG macLength;
- CK_ULONG effKeyBits;
- SECItem iv;
- SECItem mac_param;
- SSLCipherAlgorithm calg;
-
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
+ ssl3CipherSpec *pwSpec;
+ const ssl3BulkCipherDef *cipher_def;
+ PK11Context *serverContext = NULL;
+ PK11Context *clientContext = NULL;
+ SECItem *param;
+ CK_MECHANISM_TYPE mechanism;
+ CK_MECHANISM_TYPE mac_mech;
+ CK_ULONG macLength;
+ CK_ULONG effKeyBits;
+ SECItem iv;
+ SECItem mac_param;
+ SSLCipherAlgorithm calg;
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
- pwSpec = ss->ssl3.pwSpec;
- cipher_def = pwSpec->cipher_def;
- macLength = pwSpec->mac_size;
- calg = cipher_def->calg;
+ pwSpec = ss->ssl3.pwSpec;
+ cipher_def = pwSpec->cipher_def;
+ macLength = pwSpec->mac_size;
+ calg = cipher_def->calg;
PORT_Assert(alg2Mech[calg].calg == calg);
pwSpec->client.write_mac_context = NULL;
pwSpec->server.write_mac_context = NULL;
- if (calg == calg_aes_gcm || calg == calg_chacha20) {
- pwSpec->encode = NULL;
- pwSpec->decode = NULL;
- pwSpec->destroy = NULL;
- pwSpec->encodeContext = NULL;
- pwSpec->decodeContext = NULL;
- if (calg == calg_aes_gcm) {
- pwSpec->aead = ssl3_AESGCM;
- } else {
- pwSpec->aead = ssl3_ChaCha20Poly1305;
- }
- return SECSuccess;
- }
-
- /*
- ** Now setup the MAC contexts,
+ if (cipher_def->type == type_aead) {
+ pwSpec->encode = NULL;
+ pwSpec->decode = NULL;
+ pwSpec->destroy = NULL;
+ pwSpec->encodeContext = NULL;
+ pwSpec->decodeContext = NULL;
+ switch (calg) {
+ case calg_aes_gcm:
+ pwSpec->aead = ssl3_AESGCM;
+ break;
+ case calg_chacha20:
+ pwSpec->aead = ssl3_ChaCha20Poly1305;
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ return SECSuccess;
+ }
+
+ /*
+ ** Now setup the MAC contexts,
** crypto contexts are setup below.
*/
- mac_mech = pwSpec->mac_def->mmech;
+ mac_mech = pwSpec->mac_def->mmech;
mac_param.data = (unsigned char *)&macLength;
- mac_param.len = sizeof(macLength);
+ mac_param.len = sizeof(macLength);
mac_param.type = 0;
pwSpec->client.write_mac_context = PK11_CreateContextBySymKey(
- mac_mech, CKA_SIGN, pwSpec->client.write_mac_key, &mac_param);
- if (pwSpec->client.write_mac_context == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
- goto fail;
+ mac_mech, CKA_SIGN, pwSpec->client.write_mac_key, &mac_param);
+ if (pwSpec->client.write_mac_context == NULL) {
+ ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
+ goto fail;
}
pwSpec->server.write_mac_context = PK11_CreateContextBySymKey(
- mac_mech, CKA_SIGN, pwSpec->server.write_mac_key, &mac_param);
+ mac_mech, CKA_SIGN, pwSpec->server.write_mac_key, &mac_param);
if (pwSpec->server.write_mac_context == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
- goto fail;
+ ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
+ goto fail;
}
- /*
+ /*
** Now setup the crypto contexts.
*/
if (calg == calg_null) {
- pwSpec->encode = Null_Cipher;
- pwSpec->decode = Null_Cipher;
- pwSpec->destroy = NULL;
- return SECSuccess;
+ pwSpec->encode = Null_Cipher;
+ pwSpec->decode = Null_Cipher;
+ pwSpec->destroy = NULL;
+ return SECSuccess;
}
- mechanism = alg2Mech[calg].cmech;
+ mechanism = ssl3_Alg2Mech(calg);
effKeyBits = cipher_def->key_size * BPB;
/*
* build the server context
*/
iv.data = pwSpec->server.write_iv;
- iv.len = cipher_def->iv_size;
+ iv.len = cipher_def->iv_size;
param = ssl3_ParamFromIV(mechanism, &iv, effKeyBits);
if (param == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE);
- goto fail;
+ ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE);
+ goto fail;
}
serverContext = PK11_CreateContextBySymKey(mechanism,
- (ss->sec.isServer ? CKA_ENCRYPT : CKA_DECRYPT),
- pwSpec->server.write_key, param);
+ (ss->sec.isServer ? CKA_ENCRYPT
+ : CKA_DECRYPT),
+ pwSpec->server.write_key, param);
iv.data = PK11_IVFromParam(mechanism, param, (int *)&iv.len);
if (iv.data)
- PORT_Memcpy(pwSpec->server.write_iv, iv.data, iv.len);
+ PORT_Memcpy(pwSpec->server.write_iv, iv.data, iv.len);
SECITEM_FreeItem(param, PR_TRUE);
if (serverContext == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
- goto fail;
+ ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
+ goto fail;
}
/*
* build the client context
*/
iv.data = pwSpec->client.write_iv;
- iv.len = cipher_def->iv_size;
+ iv.len = cipher_def->iv_size;
param = ssl3_ParamFromIV(mechanism, &iv, effKeyBits);
if (param == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE);
- goto fail;
+ ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE);
+ goto fail;
}
clientContext = PK11_CreateContextBySymKey(mechanism,
- (ss->sec.isServer ? CKA_DECRYPT : CKA_ENCRYPT),
- pwSpec->client.write_key, param);
+ (ss->sec.isServer ? CKA_DECRYPT
+ : CKA_ENCRYPT),
+ pwSpec->client.write_key, param);
iv.data = PK11_IVFromParam(mechanism, param, (int *)&iv.len);
if (iv.data)
- PORT_Memcpy(pwSpec->client.write_iv, iv.data, iv.len);
- SECITEM_FreeItem(param,PR_TRUE);
+ PORT_Memcpy(pwSpec->client.write_iv, iv.data, iv.len);
+ SECITEM_FreeItem(param, PR_TRUE);
if (clientContext == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
- goto fail;
+ ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
+ goto fail;
}
- pwSpec->encode = (SSLCipher) PK11_CipherOp;
- pwSpec->decode = (SSLCipher) PK11_CipherOp;
- pwSpec->destroy = (SSLDestroy) PK11_DestroyContext;
+ pwSpec->encode = (SSLCipher)PK11_CipherOp;
+ pwSpec->decode = (SSLCipher)PK11_CipherOp;
+ pwSpec->destroy = (SSLDestroy)PK11_DestroyContext;
pwSpec->encodeContext = (ss->sec.isServer) ? serverContext : clientContext;
pwSpec->decodeContext = (ss->sec.isServer) ? clientContext : serverContext;
@@ -2298,26 +2281,45 @@ ssl3_InitPendingContextsPKCS11(sslSocket *ss)
return SECSuccess;
fail:
- if (serverContext != NULL) PK11_DestroyContext(serverContext, PR_TRUE);
- if (clientContext != NULL) PK11_DestroyContext(clientContext, PR_TRUE);
+ if (serverContext != NULL)
+ PK11_DestroyContext(serverContext, PR_TRUE);
+ if (clientContext != NULL)
+ PK11_DestroyContext(clientContext, PR_TRUE);
if (pwSpec->client.write_mac_context != NULL) {
- PK11_DestroyContext(pwSpec->client.write_mac_context,PR_TRUE);
- pwSpec->client.write_mac_context = NULL;
+ PK11_DestroyContext(pwSpec->client.write_mac_context, PR_TRUE);
+ pwSpec->client.write_mac_context = NULL;
}
if (pwSpec->server.write_mac_context != NULL) {
- PK11_DestroyContext(pwSpec->server.write_mac_context,PR_TRUE);
- pwSpec->server.write_mac_context = NULL;
+ PK11_DestroyContext(pwSpec->server.write_mac_context, PR_TRUE);
+ pwSpec->server.write_mac_context = NULL;
}
return SECFailure;
}
+#ifndef NO_PKCS11_BYPASS
+/* Returns whether we can bypass PKCS#11 for a given cipher algorithm.
+ *
+ * We do not support PKCS#11 bypass for ChaCha20/Poly1305.
+ */
+static PRBool
+ssl3_CanBypassCipher(SSLCipherAlgorithm calg)
+{
+ switch (calg) {
+ case calg_chacha20:
+ return PR_FALSE;
+ default:
+ return PR_TRUE;
+ }
+}
+#endif
+
/* Complete the initialization of all keys, ciphers, MACs and their contexts
* for the pending Cipher Spec.
- * Called from: ssl3_SendClientKeyExchange (for Full handshake)
- * ssl3_HandleRSAClientKeyExchange (for Full handshake)
- * ssl3_HandleServerHello (for session restart)
- * ssl3_HandleClientHello (for session restart)
+ * Called from: ssl3_SendClientKeyExchange (for Full handshake)
+ * ssl3_HandleRSAClientKeyExchange (for Full handshake)
+ * ssl3_HandleServerHello (for session restart)
+ * ssl3_HandleClientHello (for session restart)
* Sets error code, but caller probably should override to disambiguate.
* NULL pms means re-use old master_secret.
*
@@ -2331,89 +2333,90 @@ fail:
SECStatus
ssl3_InitPendingCipherSpec(sslSocket *ss, PK11SymKey *pms)
{
- ssl3CipherSpec * pwSpec;
- ssl3CipherSpec * cwSpec;
- SECStatus rv;
+ ssl3CipherSpec *pwSpec;
+ ssl3CipherSpec *cwSpec;
+ SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
- ssl_GetSpecWriteLock(ss); /**************************************/
+ ssl_GetSpecWriteLock(ss); /**************************************/
PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
- pwSpec = ss->ssl3.pwSpec;
- cwSpec = ss->ssl3.cwSpec;
+ pwSpec = ss->ssl3.pwSpec;
+ cwSpec = ss->ssl3.cwSpec;
if (pms || (!pwSpec->msItem.len && !pwSpec->master_secret)) {
- rv = ssl3_DeriveMasterSecret(ss, pms);
- if (rv != SECSuccess) {
- goto done; /* err code set by ssl3_DeriveMasterSecret */
- }
+ rv = ssl3_DeriveMasterSecret(ss, pms);
+ if (rv != SECSuccess) {
+ goto done; /* err code set by ssl3_DeriveMasterSecret */
+ }
}
#ifndef NO_PKCS11_BYPASS
- if (ss->opt.bypassPKCS11 && pwSpec->msItem.len && pwSpec->msItem.data) {
- /* Double Bypass succeeded in extracting the master_secret */
- const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def;
- PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
+ if (ss->opt.bypassPKCS11 && pwSpec->msItem.len && pwSpec->msItem.data &&
+ ssl3_CanBypassCipher(ss->ssl3.pwSpec->cipher_def->calg)) {
+ /* Double Bypass succeeded in extracting the master_secret */
+ const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
+ PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
(pwSpec->version > SSL_LIBRARY_VERSION_3_0));
- pwSpec->bypassCiphers = PR_TRUE;
- rv = ssl3_KeyAndMacDeriveBypass( pwSpec,
- (const unsigned char *)&ss->ssl3.hs.client_random,
- (const unsigned char *)&ss->ssl3.hs.server_random,
- isTLS,
- (PRBool)(kea_def->is_limited));
- if (rv == SECSuccess) {
- rv = ssl3_InitPendingContextsBypass(ss);
- }
+ pwSpec->bypassCiphers = PR_TRUE;
+ rv = ssl3_KeyAndMacDeriveBypass(pwSpec,
+ (const unsigned char *)&ss->ssl3.hs.client_random,
+ (const unsigned char *)&ss->ssl3.hs.server_random,
+ isTLS,
+ (PRBool)(kea_def->is_limited));
+ if (rv == SECSuccess) {
+ rv = ssl3_InitPendingContextsBypass(ss);
+ }
} else
#endif
- if (pwSpec->master_secret) {
- rv = ssl3_DeriveConnectionKeysPKCS11(ss);
- if (rv == SECSuccess) {
- rv = ssl3_InitPendingContextsPKCS11(ss);
- }
+ if (pwSpec->master_secret) {
+ rv = ssl3_DeriveConnectionKeysPKCS11(ss);
+ if (rv == SECSuccess) {
+ rv = ssl3_InitPendingContextsPKCS11(ss);
+ }
} else {
- PORT_Assert(pwSpec->master_secret);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- rv = SECFailure;
+ PORT_Assert(pwSpec->master_secret);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ rv = SECFailure;
}
if (rv != SECSuccess) {
- goto done;
+ goto done;
}
/* Generic behaviors -- common to all crypto methods */
if (!IS_DTLS(ss)) {
- pwSpec->read_seq_num.high = pwSpec->write_seq_num.high = 0;
+ pwSpec->read_seq_num.high = pwSpec->write_seq_num.high = 0;
} else {
- if (cwSpec->epoch == PR_UINT16_MAX) {
- /* The problem here is that we have rehandshaked too many
- * times (you are not allowed to wrap the epoch). The
- * spec says you should be discarding the connection
- * and start over, so not much we can do here. */
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- rv = SECFailure;
- goto done;
- }
- /* The sequence number has the high 16 bits as the epoch. */
- pwSpec->epoch = cwSpec->epoch + 1;
- pwSpec->read_seq_num.high = pwSpec->write_seq_num.high =
- pwSpec->epoch << 16;
-
- dtls_InitRecvdRecords(&pwSpec->recvdRecords);
+ if (cwSpec->epoch == PR_UINT16_MAX) {
+ /* The problem here is that we have rehandshaked too many
+ * times (you are not allowed to wrap the epoch). The
+ * spec says you should be discarding the connection
+ * and start over, so not much we can do here. */
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ rv = SECFailure;
+ goto done;
+ }
+ /* The sequence number has the high 16 bits as the epoch. */
+ pwSpec->epoch = cwSpec->epoch + 1;
+ pwSpec->read_seq_num.high = pwSpec->write_seq_num.high =
+ pwSpec->epoch << 16;
+
+ dtls_InitRecvdRecords(&pwSpec->recvdRecords);
}
pwSpec->read_seq_num.low = pwSpec->write_seq_num.low = 0;
done:
- ssl_ReleaseSpecWriteLock(ss); /******************************/
+ ssl_ReleaseSpecWriteLock(ss); /******************************/
if (rv != SECSuccess)
- ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
+ ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
return rv;
}
/*
* 60 bytes is 3 times the maximum length MAC size that is supported.
*/
-static const unsigned char mac_pad_1 [60] = {
+static const unsigned char mac_pad_1[60] = {
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
@@ -2423,7 +2426,7 @@ static const unsigned char mac_pad_1 [60] = {
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36
};
-static const unsigned char mac_pad_2 [60] = {
+static const unsigned char mac_pad_2[60] = {
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
@@ -2439,126 +2442,126 @@ static const unsigned char mac_pad_2 [60] = {
*/
static SECStatus
ssl3_ComputeRecordMAC(
- ssl3CipherSpec * spec,
- PRBool useServerMacKey,
+ ssl3CipherSpec *spec,
+ PRBool useServerMacKey,
const unsigned char *header,
- unsigned int headerLen,
- const SSL3Opaque * input,
- int inputLength,
- unsigned char * outbuf,
- unsigned int * outLength)
+ unsigned int headerLen,
+ const SSL3Opaque *input,
+ int inputLength,
+ unsigned char *outbuf,
+ unsigned int *outLength)
{
- const ssl3MACDef * mac_def;
- SECStatus rv;
+ const ssl3MACDef *mac_def;
+ SECStatus rv;
PRINT_BUF(95, (NULL, "frag hash1: header", header, headerLen));
PRINT_BUF(95, (NULL, "frag hash1: input", input, inputLength));
mac_def = spec->mac_def;
if (mac_def->mac == mac_null) {
- *outLength = 0;
- return SECSuccess;
+ *outLength = 0;
+ return SECSuccess;
}
#ifndef NO_PKCS11_BYPASS
if (spec->bypassCiphers) {
- /* bypass version */
- const SECHashObject *hashObj = NULL;
- unsigned int pad_bytes = 0;
- PRUint64 write_mac_context[MAX_MAC_CONTEXT_LLONGS];
-
- switch (mac_def->mac) {
- case ssl_mac_null:
- *outLength = 0;
- return SECSuccess;
- case ssl_mac_md5:
- pad_bytes = 48;
- hashObj = HASH_GetRawHashObject(HASH_AlgMD5);
- break;
- case ssl_mac_sha:
- pad_bytes = 40;
- hashObj = HASH_GetRawHashObject(HASH_AlgSHA1);
- break;
- case ssl_hmac_md5: /* used with TLS */
- hashObj = HASH_GetRawHashObject(HASH_AlgMD5);
- break;
- case ssl_hmac_sha: /* used with TLS */
- hashObj = HASH_GetRawHashObject(HASH_AlgSHA1);
- break;
- case ssl_hmac_sha256: /* used with TLS */
- hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
- break;
- default:
- break;
- }
- if (!hashObj) {
- PORT_Assert(0);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
- }
-
- if (spec->version <= SSL_LIBRARY_VERSION_3_0) {
- unsigned int tempLen;
- unsigned char temp[MAX_MAC_LENGTH];
-
- /* compute "inner" part of SSL3 MAC */
- hashObj->begin(write_mac_context);
- if (useServerMacKey)
- hashObj->update(write_mac_context,
- spec->server.write_mac_key_item.data,
- spec->server.write_mac_key_item.len);
- else
- hashObj->update(write_mac_context,
- spec->client.write_mac_key_item.data,
- spec->client.write_mac_key_item.len);
- hashObj->update(write_mac_context, mac_pad_1, pad_bytes);
- hashObj->update(write_mac_context, header, headerLen);
- hashObj->update(write_mac_context, input, inputLength);
- hashObj->end(write_mac_context, temp, &tempLen, sizeof temp);
-
- /* compute "outer" part of SSL3 MAC */
- hashObj->begin(write_mac_context);
- if (useServerMacKey)
- hashObj->update(write_mac_context,
- spec->server.write_mac_key_item.data,
- spec->server.write_mac_key_item.len);
- else
- hashObj->update(write_mac_context,
- spec->client.write_mac_key_item.data,
- spec->client.write_mac_key_item.len);
- hashObj->update(write_mac_context, mac_pad_2, pad_bytes);
- hashObj->update(write_mac_context, temp, tempLen);
- hashObj->end(write_mac_context, outbuf, outLength, spec->mac_size);
- rv = SECSuccess;
- } else { /* is TLS */
+ /* bypass version */
+ const SECHashObject *hashObj = NULL;
+ unsigned int pad_bytes = 0;
+ PRUint64 write_mac_context[MAX_MAC_CONTEXT_LLONGS];
+
+ switch (mac_def->mac) {
+ case ssl_mac_null:
+ *outLength = 0;
+ return SECSuccess;
+ case ssl_mac_md5:
+ pad_bytes = 48;
+ hashObj = HASH_GetRawHashObject(HASH_AlgMD5);
+ break;
+ case ssl_mac_sha:
+ pad_bytes = 40;
+ hashObj = HASH_GetRawHashObject(HASH_AlgSHA1);
+ break;
+ case ssl_hmac_md5: /* used with TLS */
+ hashObj = HASH_GetRawHashObject(HASH_AlgMD5);
+ break;
+ case ssl_hmac_sha: /* used with TLS */
+ hashObj = HASH_GetRawHashObject(HASH_AlgSHA1);
+ break;
+ case ssl_hmac_sha256: /* used with TLS */
+ hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
+ break;
+ default:
+ break;
+ }
+ if (!hashObj) {
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
+ if (spec->version <= SSL_LIBRARY_VERSION_3_0) {
+ unsigned int tempLen;
+ unsigned char temp[MAX_MAC_LENGTH];
+
+ /* compute "inner" part of SSL3 MAC */
+ hashObj->begin(write_mac_context);
+ if (useServerMacKey)
+ hashObj->update(write_mac_context,
+ spec->server.write_mac_key_item.data,
+ spec->server.write_mac_key_item.len);
+ else
+ hashObj->update(write_mac_context,
+ spec->client.write_mac_key_item.data,
+ spec->client.write_mac_key_item.len);
+ hashObj->update(write_mac_context, mac_pad_1, pad_bytes);
+ hashObj->update(write_mac_context, header, headerLen);
+ hashObj->update(write_mac_context, input, inputLength);
+ hashObj->end(write_mac_context, temp, &tempLen, sizeof temp);
+
+ /* compute "outer" part of SSL3 MAC */
+ hashObj->begin(write_mac_context);
+ if (useServerMacKey)
+ hashObj->update(write_mac_context,
+ spec->server.write_mac_key_item.data,
+ spec->server.write_mac_key_item.len);
+ else
+ hashObj->update(write_mac_context,
+ spec->client.write_mac_key_item.data,
+ spec->client.write_mac_key_item.len);
+ hashObj->update(write_mac_context, mac_pad_2, pad_bytes);
+ hashObj->update(write_mac_context, temp, tempLen);
+ hashObj->end(write_mac_context, outbuf, outLength, spec->mac_size);
+ rv = SECSuccess;
+ } else { /* is TLS */
#define cx ((HMACContext *)write_mac_context)
- if (useServerMacKey) {
- rv = HMAC_Init(cx, hashObj,
- spec->server.write_mac_key_item.data,
- spec->server.write_mac_key_item.len, PR_FALSE);
- } else {
- rv = HMAC_Init(cx, hashObj,
- spec->client.write_mac_key_item.data,
- spec->client.write_mac_key_item.len, PR_FALSE);
- }
- if (rv == SECSuccess) {
- HMAC_Begin(cx);
- HMAC_Update(cx, header, headerLen);
- HMAC_Update(cx, input, inputLength);
- rv = HMAC_Finish(cx, outbuf, outLength, spec->mac_size);
- HMAC_Destroy(cx, PR_FALSE);
- }
+ if (useServerMacKey) {
+ rv = HMAC_Init(cx, hashObj,
+ spec->server.write_mac_key_item.data,
+ spec->server.write_mac_key_item.len, PR_FALSE);
+ } else {
+ rv = HMAC_Init(cx, hashObj,
+ spec->client.write_mac_key_item.data,
+ spec->client.write_mac_key_item.len, PR_FALSE);
+ }
+ if (rv == SECSuccess) {
+ HMAC_Begin(cx);
+ HMAC_Update(cx, header, headerLen);
+ HMAC_Update(cx, input, inputLength);
+ rv = HMAC_Finish(cx, outbuf, outLength, spec->mac_size);
+ HMAC_Destroy(cx, PR_FALSE);
+ }
#undef cx
- }
+ }
} else
#endif
{
- PK11Context *mac_context =
- (useServerMacKey ? spec->server.write_mac_context
- : spec->client.write_mac_context);
- rv = PK11_DigestBegin(mac_context);
- rv |= PK11_DigestOp(mac_context, header, headerLen);
- rv |= PK11_DigestOp(mac_context, input, inputLength);
- rv |= PK11_DigestFinal(mac_context, outbuf, outLength, spec->mac_size);
+ PK11Context *mac_context =
+ (useServerMacKey ? spec->server.write_mac_context
+ : spec->client.write_mac_context);
+ rv = PK11_DigestBegin(mac_context);
+ rv |= PK11_DigestOp(mac_context, header, headerLen);
+ rv |= PK11_DigestOp(mac_context, input, inputLength);
+ rv |= PK11_DigestFinal(mac_context, outbuf, outLength, spec->mac_size);
}
PORT_Assert(rv != SECSuccess || *outLength == (unsigned)spec->mac_size);
@@ -2566,8 +2569,8 @@ ssl3_ComputeRecordMAC(
PRINT_BUF(95, (NULL, "frag hash2: result", outbuf, *outLength));
if (rv != SECSuccess) {
- rv = SECFailure;
- ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
+ rv = SECFailure;
+ ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
}
return rv;
}
@@ -2580,51 +2583,51 @@ ssl3_ComputeRecordMAC(
*/
static SECStatus
ssl3_ComputeRecordMACConstantTime(
- ssl3CipherSpec * spec,
- PRBool useServerMacKey,
+ ssl3CipherSpec *spec,
+ PRBool useServerMacKey,
const unsigned char *header,
- unsigned int headerLen,
- const SSL3Opaque * input,
- int inputLen,
- int originalLen,
- unsigned char * outbuf,
- unsigned int * outLen)
-{
- CK_MECHANISM_TYPE macType;
+ unsigned int headerLen,
+ const SSL3Opaque *input,
+ int inputLen,
+ int originalLen,
+ unsigned char *outbuf,
+ unsigned int *outLen)
+{
+ CK_MECHANISM_TYPE macType;
CK_NSS_MAC_CONSTANT_TIME_PARAMS params;
- SECItem param, inputItem, outputItem;
- SECStatus rv;
- PK11SymKey * key;
+ SECItem param, inputItem, outputItem;
+ SECStatus rv;
+ PK11SymKey *key;
PORT_Assert(inputLen >= spec->mac_size);
PORT_Assert(originalLen >= inputLen);
if (spec->bypassCiphers) {
- /* This function doesn't support PKCS#11 bypass. We fallback on the
- * non-constant time version. */
- goto fallback;
+ /* This function doesn't support PKCS#11 bypass. We fallback on the
+ * non-constant time version. */
+ goto fallback;
}
if (spec->mac_def->mac == mac_null) {
- *outLen = 0;
- return SECSuccess;
+ *outLen = 0;
+ return SECSuccess;
}
macType = CKM_NSS_HMAC_CONSTANT_TIME;
if (spec->version <= SSL_LIBRARY_VERSION_3_0) {
- macType = CKM_NSS_SSL3_MAC_CONSTANT_TIME;
+ macType = CKM_NSS_SSL3_MAC_CONSTANT_TIME;
}
params.macAlg = spec->mac_def->mmech;
params.ulBodyTotalLen = originalLen;
- params.pHeader = (unsigned char *) header; /* const cast */
+ params.pHeader = (unsigned char *)header; /* const cast */
params.ulHeaderLen = headerLen;
- param.data = (unsigned char*) &params;
+ param.data = (unsigned char *)&params;
param.len = sizeof(params);
param.type = 0;
- inputItem.data = (unsigned char *) input;
+ inputItem.data = (unsigned char *)input;
inputItem.len = inputLen;
inputItem.type = 0;
@@ -2634,19 +2637,19 @@ ssl3_ComputeRecordMACConstantTime(
key = spec->server.write_mac_key;
if (!useServerMacKey) {
- key = spec->client.write_mac_key;
+ key = spec->client.write_mac_key;
}
rv = PK11_SignWithSymKey(key, macType, &param, &outputItem, &inputItem);
if (rv != SECSuccess) {
- if (PORT_GetError() == SEC_ERROR_INVALID_ALGORITHM) {
- goto fallback;
- }
+ if (PORT_GetError() == SEC_ERROR_INVALID_ALGORITHM) {
+ goto fallback;
+ }
- *outLen = 0;
- rv = SECFailure;
- ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
- return rv;
+ *outLen = 0;
+ rv = SECFailure;
+ ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
+ return rv;
}
PORT_Assert(outputItem.len == (unsigned)spec->mac_size);
@@ -2659,246 +2662,246 @@ fallback:
* length already. */
inputLen -= spec->mac_size;
return ssl3_ComputeRecordMAC(spec, useServerMacKey, header, headerLen,
- input, inputLen, outbuf, outLen);
+ input, inputLen, outbuf, outLen);
}
static PRBool
-ssl3_ClientAuthTokenPresent(sslSessionID *sid) {
+ssl3_ClientAuthTokenPresent(sslSessionID *sid)
+{
PK11SlotInfo *slot = NULL;
PRBool isPresent = PR_TRUE;
/* we only care if we are doing client auth */
- /* If NSS_PLATFORM_CLIENT_AUTH is defined and a platformClientKey is being
- * used, u.ssl3.clAuthValid will be false and this function will always
- * return PR_TRUE. */
if (!sid || !sid->u.ssl3.clAuthValid) {
- return PR_TRUE;
+ return PR_TRUE;
}
/* get the slot */
slot = SECMOD_LookupSlot(sid->u.ssl3.clAuthModuleID,
- sid->u.ssl3.clAuthSlotID);
+ sid->u.ssl3.clAuthSlotID);
if (slot == NULL ||
- !PK11_IsPresent(slot) ||
- sid->u.ssl3.clAuthSeries != PK11_GetSlotSeries(slot) ||
- sid->u.ssl3.clAuthSlotID != PK11_GetSlotID(slot) ||
- sid->u.ssl3.clAuthModuleID != PK11_GetModuleID(slot) ||
- (PK11_NeedLogin(slot) && !PK11_IsLoggedIn(slot, NULL))) {
- isPresent = PR_FALSE;
- }
+ !PK11_IsPresent(slot) ||
+ sid->u.ssl3.clAuthSeries != PK11_GetSlotSeries(slot) ||
+ sid->u.ssl3.clAuthSlotID != PK11_GetSlotID(slot) ||
+ sid->u.ssl3.clAuthModuleID != PK11_GetModuleID(slot) ||
+ (PK11_NeedLogin(slot) && !PK11_IsLoggedIn(slot, NULL))) {
+ isPresent = PR_FALSE;
+ }
if (slot) {
- PK11_FreeSlot(slot);
+ PK11_FreeSlot(slot);
}
return isPresent;
}
/* Caller must hold the spec read lock. */
SECStatus
-ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
- PRBool isServer,
- PRBool isDTLS,
- PRBool capRecordVersion,
- SSL3ContentType type,
- const SSL3Opaque * pIn,
- PRUint32 contentLen,
- sslBuffer * wrBuf)
-{
- const ssl3BulkCipherDef * cipher_def;
- SECStatus rv;
- PRUint32 macLen = 0;
- PRUint32 fragLen;
- PRUint32 p1Len, p2Len, oddLen = 0;
- PRUint16 headerLen;
+ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec,
+ PRBool isServer,
+ PRBool isDTLS,
+ PRBool capRecordVersion,
+ SSL3ContentType type,
+ const SSL3Opaque *pIn,
+ PRUint32 contentLen,
+ sslBuffer *wrBuf)
+{
+ const ssl3BulkCipherDef *cipher_def;
+ SECStatus rv;
+ PRUint32 macLen = 0;
+ PRUint32 fragLen;
+ PRUint32 p1Len, p2Len, oddLen = 0;
+ PRUint16 headerLen;
unsigned int ivLen = 0;
- int cipherBytes = 0;
- unsigned char pseudoHeader[13];
- unsigned int pseudoHeaderLen;
+ int cipherBytes = 0;
+ unsigned char pseudoHeader[13];
+ unsigned int pseudoHeaderLen;
cipher_def = cwSpec->cipher_def;
headerLen = isDTLS ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH;
if (cipher_def->type == type_block &&
- cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
- /* Prepend the per-record explicit IV using technique 2b from
- * RFC 4346 section 6.2.3.2: The IV is a cryptographically
- * strong random number XORed with the CBC residue from the previous
- * record.
- */
- ivLen = cipher_def->iv_size;
- if (ivLen > wrBuf->space - headerLen) {
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
- }
- rv = PK11_GenerateRandom(wrBuf->buf + headerLen, ivLen);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
- return rv;
- }
- rv = cwSpec->encode( cwSpec->encodeContext,
- wrBuf->buf + headerLen,
- &cipherBytes, /* output and actual outLen */
- ivLen, /* max outlen */
- wrBuf->buf + headerLen,
- ivLen); /* input and inputLen*/
- if (rv != SECSuccess || cipherBytes != ivLen) {
- PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
- return SECFailure;
- }
+ cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
+ /* Prepend the per-record explicit IV using technique 2b from
+ * RFC 4346 section 6.2.3.2: The IV is a cryptographically
+ * strong random number XORed with the CBC residue from the previous
+ * record.
+ */
+ ivLen = cipher_def->iv_size;
+ if (ivLen > wrBuf->space - headerLen) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ rv = PK11_GenerateRandom(wrBuf->buf + headerLen, ivLen);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
+ return rv;
+ }
+ rv = cwSpec->encode(cwSpec->encodeContext,
+ wrBuf->buf + headerLen,
+ &cipherBytes, /* output and actual outLen */
+ ivLen, /* max outlen */
+ wrBuf->buf + headerLen,
+ ivLen); /* input and inputLen*/
+ if (rv != SECSuccess || cipherBytes != ivLen) {
+ PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
+ return SECFailure;
+ }
}
if (cwSpec->compressor) {
- int outlen;
- rv = cwSpec->compressor(
- cwSpec->compressContext,
- wrBuf->buf + headerLen + ivLen, &outlen,
- wrBuf->space - headerLen - ivLen, pIn, contentLen);
- if (rv != SECSuccess)
- return rv;
- pIn = wrBuf->buf + headerLen + ivLen;
- contentLen = outlen;
+ int outlen;
+ rv = cwSpec->compressor(
+ cwSpec->compressContext,
+ wrBuf->buf + headerLen + ivLen, &outlen,
+ wrBuf->space - headerLen - ivLen, pIn, contentLen);
+ if (rv != SECSuccess)
+ return rv;
+ pIn = wrBuf->buf + headerLen + ivLen;
+ contentLen = outlen;
}
pseudoHeaderLen = ssl3_BuildRecordPseudoHeader(
- pseudoHeader, cwSpec->write_seq_num, type,
- cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->version,
- isDTLS, contentLen);
+ pseudoHeader, cwSpec->write_seq_num, type,
+ cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->version,
+ isDTLS, contentLen);
PORT_Assert(pseudoHeaderLen <= sizeof(pseudoHeader));
if (cipher_def->type == type_aead) {
- const int nonceLen = cipher_def->explicit_nonce_size;
- const int tagLen = cipher_def->tag_size;
-
- if (headerLen + nonceLen + contentLen + tagLen > wrBuf->space) {
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
- }
-
- cipherBytes = contentLen;
- rv = cwSpec->aead(
- isServer ? &cwSpec->server : &cwSpec->client,
- PR_FALSE, /* do encrypt */
- wrBuf->buf + headerLen, /* output */
- &cipherBytes, /* out len */
- wrBuf->space - headerLen, /* max out */
- pIn, contentLen, /* input */
- pseudoHeader, pseudoHeaderLen);
- if (rv != SECSuccess) {
- PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
- return SECFailure;
- }
+ const int nonceLen = cipher_def->explicit_nonce_size;
+ const int tagLen = cipher_def->tag_size;
+
+ if (headerLen + nonceLen + contentLen + tagLen > wrBuf->space) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
+ cipherBytes = contentLen;
+ rv = cwSpec->aead(
+ isServer ? &cwSpec->server : &cwSpec->client,
+ PR_FALSE, /* do encrypt */
+ wrBuf->buf + headerLen, /* output */
+ &cipherBytes, /* out len */
+ wrBuf->space - headerLen, /* max out */
+ pIn, contentLen, /* input */
+ pseudoHeader, pseudoHeaderLen);
+ if (rv != SECSuccess) {
+ PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
+ return SECFailure;
+ }
} else {
- /*
- * Add the MAC
- */
- rv = ssl3_ComputeRecordMAC(cwSpec, isServer,
- pseudoHeader, pseudoHeaderLen, pIn, contentLen,
- wrBuf->buf + headerLen + ivLen + contentLen, &macLen);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
- return SECFailure;
- }
- p1Len = contentLen;
- p2Len = macLen;
- fragLen = contentLen + macLen; /* needs to be encrypted */
- PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024);
-
- /*
- * Pad the text (if we're doing a block cipher)
- * then Encrypt it
- */
- if (cipher_def->type == type_block) {
- unsigned char * pBuf;
- int padding_length;
- int i;
-
- oddLen = contentLen % cipher_def->block_size;
- /* Assume blockSize is a power of two */
- padding_length = cipher_def->block_size - 1 -
- ((fragLen) & (cipher_def->block_size - 1));
- fragLen += padding_length + 1;
- PORT_Assert((fragLen % cipher_def->block_size) == 0);
-
- /* Pad according to TLS rules (also acceptable to SSL3). */
- pBuf = &wrBuf->buf[headerLen + ivLen + fragLen - 1];
- for (i = padding_length + 1; i > 0; --i) {
- *pBuf-- = padding_length;
- }
- /* now, if contentLen is not a multiple of block size, fix it */
- p2Len = fragLen - p1Len;
- }
- if (p1Len < 256) {
- oddLen = p1Len;
- p1Len = 0;
- } else {
- p1Len -= oddLen;
- }
- if (oddLen) {
- p2Len += oddLen;
- PORT_Assert( (cipher_def->block_size < 2) || \
- (p2Len % cipher_def->block_size) == 0);
- memmove(wrBuf->buf + headerLen + ivLen + p1Len, pIn + p1Len,
- oddLen);
- }
- if (p1Len > 0) {
- int cipherBytesPart1 = -1;
- rv = cwSpec->encode( cwSpec->encodeContext,
- wrBuf->buf + headerLen + ivLen, /* output */
- &cipherBytesPart1, /* actual outlen */
- p1Len, /* max outlen */
- pIn, p1Len); /* input, and inputlen */
- PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int) p1Len);
- if (rv != SECSuccess || cipherBytesPart1 != (int) p1Len) {
- PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
- return SECFailure;
- }
- cipherBytes += cipherBytesPart1;
- }
- if (p2Len > 0) {
- int cipherBytesPart2 = -1;
- rv = cwSpec->encode( cwSpec->encodeContext,
- wrBuf->buf + headerLen + ivLen + p1Len,
- &cipherBytesPart2, /* output and actual outLen */
- p2Len, /* max outlen */
- wrBuf->buf + headerLen + ivLen + p1Len,
- p2Len); /* input and inputLen*/
- PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int) p2Len);
- if (rv != SECSuccess || cipherBytesPart2 != (int) p2Len) {
- PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
- return SECFailure;
- }
- cipherBytes += cipherBytesPart2;
- }
+ /*
+ * Add the MAC
+ */
+ rv = ssl3_ComputeRecordMAC(cwSpec, isServer,
+ pseudoHeader, pseudoHeaderLen, pIn, contentLen,
+ wrBuf->buf + headerLen + ivLen + contentLen,
+ &macLen);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
+ return SECFailure;
+ }
+ p1Len = contentLen;
+ p2Len = macLen;
+ fragLen = contentLen + macLen; /* needs to be encrypted */
+ PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024);
+
+ /*
+ * Pad the text (if we're doing a block cipher)
+ * then Encrypt it
+ */
+ if (cipher_def->type == type_block) {
+ unsigned char *pBuf;
+ int padding_length;
+ int i;
+
+ oddLen = contentLen % cipher_def->block_size;
+ /* Assume blockSize is a power of two */
+ padding_length = cipher_def->block_size - 1 - ((fragLen) & (cipher_def->block_size - 1));
+ fragLen += padding_length + 1;
+ PORT_Assert((fragLen % cipher_def->block_size) == 0);
+
+ /* Pad according to TLS rules (also acceptable to SSL3). */
+ pBuf = &wrBuf->buf[headerLen + ivLen + fragLen - 1];
+ for (i = padding_length + 1; i > 0; --i) {
+ *pBuf-- = padding_length;
+ }
+ /* now, if contentLen is not a multiple of block size, fix it */
+ p2Len = fragLen - p1Len;
+ }
+ if (p1Len < 256) {
+ oddLen = p1Len;
+ p1Len = 0;
+ } else {
+ p1Len -= oddLen;
+ }
+ if (oddLen) {
+ p2Len += oddLen;
+ PORT_Assert((cipher_def->block_size < 2) ||
+ (p2Len % cipher_def->block_size) == 0);
+ memmove(wrBuf->buf + headerLen + ivLen + p1Len, pIn + p1Len,
+ oddLen);
+ }
+ if (p1Len > 0) {
+ int cipherBytesPart1 = -1;
+ rv = cwSpec->encode(cwSpec->encodeContext,
+ wrBuf->buf + headerLen + ivLen, /* output */
+ &cipherBytesPart1, /* actual outlen */
+ p1Len, /* max outlen */
+ pIn,
+ p1Len); /* input, and inputlen */
+ PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int)p1Len);
+ if (rv != SECSuccess || cipherBytesPart1 != (int)p1Len) {
+ PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
+ return SECFailure;
+ }
+ cipherBytes += cipherBytesPart1;
+ }
+ if (p2Len > 0) {
+ int cipherBytesPart2 = -1;
+ rv = cwSpec->encode(cwSpec->encodeContext,
+ wrBuf->buf + headerLen + ivLen + p1Len,
+ &cipherBytesPart2, /* output and actual outLen */
+ p2Len, /* max outlen */
+ wrBuf->buf + headerLen + ivLen + p1Len,
+ p2Len); /* input and inputLen*/
+ PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int)p2Len);
+ if (rv != SECSuccess || cipherBytesPart2 != (int)p2Len) {
+ PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
+ return SECFailure;
+ }
+ cipherBytes += cipherBytesPart2;
+ }
}
PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024);
- wrBuf->len = cipherBytes + headerLen;
+ wrBuf->len = cipherBytes + headerLen;
wrBuf->buf[0] = type;
if (isDTLS) {
- SSL3ProtocolVersion version;
-
- version = dtls_TLSVersionToDTLSVersion(cwSpec->version);
- wrBuf->buf[1] = MSB(version);
- wrBuf->buf[2] = LSB(version);
- wrBuf->buf[3] = (unsigned char)(cwSpec->write_seq_num.high >> 24);
- wrBuf->buf[4] = (unsigned char)(cwSpec->write_seq_num.high >> 16);
- wrBuf->buf[5] = (unsigned char)(cwSpec->write_seq_num.high >> 8);
- wrBuf->buf[6] = (unsigned char)(cwSpec->write_seq_num.high >> 0);
- wrBuf->buf[7] = (unsigned char)(cwSpec->write_seq_num.low >> 24);
- wrBuf->buf[8] = (unsigned char)(cwSpec->write_seq_num.low >> 16);
- wrBuf->buf[9] = (unsigned char)(cwSpec->write_seq_num.low >> 8);
- wrBuf->buf[10] = (unsigned char)(cwSpec->write_seq_num.low >> 0);
- wrBuf->buf[11] = MSB(cipherBytes);
- wrBuf->buf[12] = LSB(cipherBytes);
+ SSL3ProtocolVersion version;
+
+ version = dtls_TLSVersionToDTLSVersion(cwSpec->version);
+ wrBuf->buf[1] = MSB(version);
+ wrBuf->buf[2] = LSB(version);
+ wrBuf->buf[3] = (unsigned char)(cwSpec->write_seq_num.high >> 24);
+ wrBuf->buf[4] = (unsigned char)(cwSpec->write_seq_num.high >> 16);
+ wrBuf->buf[5] = (unsigned char)(cwSpec->write_seq_num.high >> 8);
+ wrBuf->buf[6] = (unsigned char)(cwSpec->write_seq_num.high >> 0);
+ wrBuf->buf[7] = (unsigned char)(cwSpec->write_seq_num.low >> 24);
+ wrBuf->buf[8] = (unsigned char)(cwSpec->write_seq_num.low >> 16);
+ wrBuf->buf[9] = (unsigned char)(cwSpec->write_seq_num.low >> 8);
+ wrBuf->buf[10] = (unsigned char)(cwSpec->write_seq_num.low >> 0);
+ wrBuf->buf[11] = MSB(cipherBytes);
+ wrBuf->buf[12] = LSB(cipherBytes);
} else {
- SSL3ProtocolVersion version = cwSpec->version;
+ SSL3ProtocolVersion version = cwSpec->version;
+
+ if (capRecordVersion || version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version);
+ }
- if (capRecordVersion) {
- version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version);
- }
- wrBuf->buf[1] = MSB(version);
- wrBuf->buf[2] = LSB(version);
- wrBuf->buf[3] = MSB(cipherBytes);
- wrBuf->buf[4] = LSB(cipherBytes);
+ wrBuf->buf[1] = MSB(version);
+ wrBuf->buf[2] = LSB(version);
+ wrBuf->buf[3] = MSB(cipherBytes);
+ wrBuf->buf[4] = LSB(cipherBytes);
}
ssl3_BumpSequenceNumber(&cwSpec->write_seq_num);
@@ -2908,8 +2911,8 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
/* Process the plain text before sending it.
* Returns the number of bytes of plaintext that were successfully sent
- * plus the number of bytes of plaintext that were copied into the
- * output (write) buffer.
+ * plus the number of bytes of plaintext that were copied into the
+ * output (write) buffer.
* Returns SECFailure on a hard IO error, memory error, or crypto error.
* Does NOT return SECWouldBlock.
*
@@ -2938,24 +2941,24 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
* flag to work around such servers.
*/
PRInt32
-ssl3_SendRecord( sslSocket * ss,
- DTLSEpoch epoch, /* DTLS only */
- SSL3ContentType type,
- const SSL3Opaque * pIn, /* input buffer */
- PRInt32 nIn, /* bytes of input */
- PRInt32 flags)
-{
- sslBuffer * wrBuf = &ss->sec.writeBuf;
- SECStatus rv;
- PRInt32 totalSent = 0;
- PRBool capRecordVersion;
+ssl3_SendRecord(sslSocket *ss,
+ DTLSEpoch epoch, /* DTLS only */
+ SSL3ContentType type,
+ const SSL3Opaque *pIn, /* input buffer */
+ PRInt32 nIn, /* bytes of input */
+ PRInt32 flags)
+{
+ sslBuffer *wrBuf = &ss->sec.writeBuf;
+ SECStatus rv;
+ PRInt32 totalSent = 0;
+ PRBool capRecordVersion;
SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d",
- SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),
- nIn));
+ SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),
+ nIn));
PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn));
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
if (ss->ssl3.fatalAlertSent) {
SSL_TRC(3, ("%d: SSL3[%d] Suppress write, fatal alert already sent",
@@ -2966,180 +2969,187 @@ ssl3_SendRecord( sslSocket * ss,
capRecordVersion = ((flags & ssl_SEND_FLAG_CAP_RECORD_VERSION) != 0);
if (capRecordVersion) {
- /* ssl_SEND_FLAG_CAP_RECORD_VERSION can only be used with the
- * TLS initial ClientHello. */
- PORT_Assert(!IS_DTLS(ss));
- PORT_Assert(!ss->firstHsDone);
- PORT_Assert(type == content_handshake);
- PORT_Assert(ss->ssl3.hs.ws == wait_server_hello);
+ /* ssl_SEND_FLAG_CAP_RECORD_VERSION can only be used with the
+ * TLS initial ClientHello. */
+ PORT_Assert(!IS_DTLS(ss));
+ PORT_Assert(!ss->firstHsDone);
+ PORT_Assert(type == content_handshake);
+ PORT_Assert(ss->ssl3.hs.ws == wait_server_hello);
}
if (ss->ssl3.initialized == PR_FALSE) {
- /* This can happen on a server if the very first incoming record
- ** looks like a defective ssl3 record (e.g. too long), and we're
- ** trying to send an alert.
- */
- PR_ASSERT(type == content_alert);
- rv = ssl3_InitState(ss);
- if (rv != SECSuccess) {
- return SECFailure; /* ssl3_InitState has set the error code. */
- }
+ /* This can happen on a server if the very first incoming record
+ ** looks like a defective ssl3 record (e.g. too long), and we're
+ ** trying to send an alert.
+ */
+ PR_ASSERT(type == content_alert);
+ rv = ssl3_InitState(ss);
+ if (rv != SECSuccess) {
+ return SECFailure; /* ssl3_InitState has set the error code. */
+ }
}
/* check for Token Presence */
if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) {
- PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
+ return SECFailure;
}
while (nIn > 0) {
- PRUint32 contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH);
- unsigned int spaceNeeded;
- unsigned int numRecords;
-
- ssl_GetSpecReadLock(ss); /********************************/
-
- if (nIn > 1 && ss->opt.cbcRandomIV &&
- ss->ssl3.cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_1 &&
- type == content_application_data &&
- ss->ssl3.cwSpec->cipher_def->type == type_block /* CBC mode */) {
- /* We will split the first byte of the record into its own record,
- * as explained in the documentation for SSL_CBC_RANDOM_IV in ssl.h
- */
- numRecords = 2;
- } else {
- numRecords = 1;
- }
-
- spaceNeeded = contentLen + (numRecords * SSL3_BUFFER_FUDGE);
- if (ss->ssl3.cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1 &&
- ss->ssl3.cwSpec->cipher_def->type == type_block) {
- spaceNeeded += ss->ssl3.cwSpec->cipher_def->iv_size;
- }
- if (spaceNeeded > wrBuf->space) {
- rv = sslBuffer_Grow(wrBuf, spaceNeeded);
- if (rv != SECSuccess) {
- SSL_DBG(("%d: SSL3[%d]: SendRecord, tried to get %d bytes",
- SSL_GETPID(), ss->fd, spaceNeeded));
- goto spec_locked_loser; /* sslBuffer_Grow set error code. */
- }
- }
-
- if (numRecords == 2) {
- sslBuffer secondRecord;
-
- rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
- ss->sec.isServer, IS_DTLS(ss),
- capRecordVersion, type, pIn,
- 1, wrBuf);
- if (rv != SECSuccess)
- goto spec_locked_loser;
-
- PRINT_BUF(50, (ss, "send (encrypted) record data [1/2]:",
- wrBuf->buf, wrBuf->len));
-
- secondRecord.buf = wrBuf->buf + wrBuf->len;
- secondRecord.len = 0;
- secondRecord.space = wrBuf->space - wrBuf->len;
-
- rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
- ss->sec.isServer, IS_DTLS(ss),
- capRecordVersion, type,
- pIn + 1, contentLen - 1,
- &secondRecord);
- if (rv == SECSuccess) {
- PRINT_BUF(50, (ss, "send (encrypted) record data [2/2]:",
- secondRecord.buf, secondRecord.len));
- wrBuf->len += secondRecord.len;
- }
- } else {
- if (!IS_DTLS(ss)) {
- rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
- ss->sec.isServer,
- IS_DTLS(ss),
- capRecordVersion,
- type, pIn,
- contentLen, wrBuf);
- } else {
- rv = dtls_CompressMACEncryptRecord(ss, epoch,
- !!(flags & ssl_SEND_FLAG_USE_EPOCH),
- type, pIn,
- contentLen, wrBuf);
- }
-
- if (rv == SECSuccess) {
- PRINT_BUF(50, (ss, "send (encrypted) record data:",
- wrBuf->buf, wrBuf->len));
- }
- }
-
-spec_locked_loser:
- ssl_ReleaseSpecReadLock(ss); /************************************/
-
- if (rv != SECSuccess)
- return SECFailure;
-
- pIn += contentLen;
- nIn -= contentLen;
- PORT_Assert( nIn >= 0 );
-
- /* If there's still some previously saved ciphertext,
- * or the caller doesn't want us to send the data yet,
- * then add all our new ciphertext to the amount previously saved.
- */
- if ((ss->pendingBuf.len > 0) ||
- (flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
-
- rv = ssl_SaveWriteData(ss, wrBuf->buf, wrBuf->len);
- if (rv != SECSuccess) {
- /* presumably a memory error, SEC_ERROR_NO_MEMORY */
- return SECFailure;
- }
- wrBuf->len = 0; /* All cipher text is saved away. */
-
- if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
- PRInt32 sent;
- ss->handshakeBegun = 1;
- sent = ssl_SendSavedWriteData(ss);
- if (sent < 0 && PR_GetError() != PR_WOULD_BLOCK_ERROR) {
- ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
- return SECFailure;
- }
- if (ss->pendingBuf.len) {
- flags |= ssl_SEND_FLAG_FORCE_INTO_BUFFER;
- }
- }
- } else if (wrBuf->len > 0) {
- PRInt32 sent;
- ss->handshakeBegun = 1;
- sent = ssl_DefSend(ss, wrBuf->buf, wrBuf->len,
- flags & ~ssl_SEND_FLAG_MASK);
- if (sent < 0) {
- if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
- ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
- return SECFailure;
- }
- /* we got PR_WOULD_BLOCK_ERROR, which means none was sent. */
- sent = 0;
- }
- wrBuf->len -= sent;
- if (wrBuf->len) {
- if (IS_DTLS(ss)) {
- /* DTLS just says no in this case. No buffering */
- PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
- return SECFailure;
- }
- /* now take all the remaining unsent new ciphertext and
- * append it to the buffer of previously unsent ciphertext.
- */
- rv = ssl_SaveWriteData(ss, wrBuf->buf + sent, wrBuf->len);
- if (rv != SECSuccess) {
- /* presumably a memory error, SEC_ERROR_NO_MEMORY */
- return SECFailure;
- }
- }
- }
- totalSent += contentLen;
+ PRUint32 contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH);
+ unsigned int spaceNeeded;
+ unsigned int numRecords;
+
+ ssl_GetSpecReadLock(ss); /********************************/
+
+ if (nIn > 1 && ss->opt.cbcRandomIV &&
+ ss->ssl3.cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_1 &&
+ type == content_application_data &&
+ ss->ssl3.cwSpec->cipher_def->type == type_block /* CBC mode */) {
+ /* We will split the first byte of the record into its own record,
+ * as explained in the documentation for SSL_CBC_RANDOM_IV in ssl.h
+ */
+ numRecords = 2;
+ } else {
+ numRecords = 1;
+ }
+
+ spaceNeeded = contentLen + (numRecords * SSL3_BUFFER_FUDGE);
+ if (ss->ssl3.cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1 &&
+ ss->ssl3.cwSpec->cipher_def->type == type_block) {
+ spaceNeeded += ss->ssl3.cwSpec->cipher_def->iv_size;
+ }
+ if (spaceNeeded > wrBuf->space) {
+ rv = sslBuffer_Grow(wrBuf, spaceNeeded);
+ if (rv != SECSuccess) {
+ SSL_DBG(("%d: SSL3[%d]: SendRecord, tried to get %d bytes",
+ SSL_GETPID(), ss->fd, spaceNeeded));
+ goto spec_locked_loser; /* sslBuffer_Grow set error code. */
+ }
+ }
+
+ if (numRecords == 2) {
+ sslBuffer secondRecord;
+ rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
+ ss->sec.isServer, IS_DTLS(ss),
+ capRecordVersion, type, pIn,
+ 1, wrBuf);
+ if (rv != SECSuccess)
+ goto spec_locked_loser;
+
+ PRINT_BUF(50, (ss, "send (encrypted) record data [1/2]:",
+ wrBuf->buf, wrBuf->len));
+
+ secondRecord.buf = wrBuf->buf + wrBuf->len;
+ secondRecord.len = 0;
+ secondRecord.space = wrBuf->space - wrBuf->len;
+
+ rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
+ ss->sec.isServer, IS_DTLS(ss),
+ capRecordVersion, type,
+ pIn + 1,
+ contentLen - 1,
+ &secondRecord);
+ if (rv == SECSuccess) {
+ PRINT_BUF(50, (ss, "send (encrypted) record data [2/2]:",
+ secondRecord.buf, secondRecord.len));
+ wrBuf->len += secondRecord.len;
+ }
+ } else {
+ if (!IS_DTLS(ss)) {
+ if (ss->ssl3.cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
+ ss->sec.isServer,
+ PR_FALSE,
+ capRecordVersion,
+ type, pIn,
+ contentLen, wrBuf);
+ } else {
+ rv = tls13_ProtectRecord(ss, type, pIn,
+ contentLen, wrBuf);
+ }
+ } else {
+ /* TLS <= 1.2 and TLS 1.3 cases are both handled in
+ * dtls_CompressMACEncryptRecord. */
+ rv = dtls_CompressMACEncryptRecord(ss, epoch,
+ !!(flags & ssl_SEND_FLAG_USE_EPOCH),
+ type, pIn,
+ contentLen, wrBuf);
+ }
+
+ if (rv == SECSuccess) {
+ PRINT_BUF(50, (ss, "send (encrypted) record data:",
+ wrBuf->buf, wrBuf->len));
+ }
+ }
+
+ spec_locked_loser:
+ ssl_ReleaseSpecReadLock(ss); /************************************/
+
+ if (rv != SECSuccess)
+ return SECFailure;
+
+ pIn += contentLen;
+ nIn -= contentLen;
+ PORT_Assert(nIn >= 0);
+
+ /* If there's still some previously saved ciphertext,
+ * or the caller doesn't want us to send the data yet,
+ * then add all our new ciphertext to the amount previously saved.
+ */
+ if ((ss->pendingBuf.len > 0) ||
+ (flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
+
+ rv = ssl_SaveWriteData(ss, wrBuf->buf, wrBuf->len);
+ if (rv != SECSuccess) {
+ /* presumably a memory error, SEC_ERROR_NO_MEMORY */
+ return SECFailure;
+ }
+ wrBuf->len = 0; /* All cipher text is saved away. */
+
+ if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
+ PRInt32 sent;
+ ss->handshakeBegun = 1;
+ sent = ssl_SendSavedWriteData(ss);
+ if (sent < 0 && PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
+ return SECFailure;
+ }
+ if (ss->pendingBuf.len) {
+ flags |= ssl_SEND_FLAG_FORCE_INTO_BUFFER;
+ }
+ }
+ } else if (wrBuf->len > 0) {
+ PRInt32 sent;
+ ss->handshakeBegun = 1;
+ sent = ssl_DefSend(ss, wrBuf->buf, wrBuf->len,
+ flags & ~ssl_SEND_FLAG_MASK);
+ if (sent < 0) {
+ if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
+ return SECFailure;
+ }
+ /* we got PR_WOULD_BLOCK_ERROR, which means none was sent. */
+ sent = 0;
+ }
+ wrBuf->len -= sent;
+ if (wrBuf->len) {
+ if (IS_DTLS(ss)) {
+ /* DTLS just says no in this case. No buffering */
+ PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
+ return SECFailure;
+ }
+ /* now take all the remaining unsent new ciphertext and
+ * append it to the buffer of previously unsent ciphertext.
+ */
+ rv = ssl_SaveWriteData(ss, wrBuf->buf + sent, wrBuf->len);
+ if (rv != SECSuccess) {
+ /* presumably a memory error, SEC_ERROR_NO_MEMORY */
+ return SECFailure;
+ }
+ }
+ }
+ totalSent += contentLen;
}
return totalSent;
}
@@ -3151,87 +3161,87 @@ spec_locked_loser:
*/
int
ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in,
- PRInt32 len, PRInt32 flags)
+ PRInt32 len, PRInt32 flags)
{
- PRInt32 totalSent = 0;
- PRInt32 discarded = 0;
+ PRInt32 totalSent = 0;
+ PRInt32 discarded = 0;
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
/* These flags for internal use only */
PORT_Assert(!(flags & (ssl_SEND_FLAG_USE_EPOCH |
- ssl_SEND_FLAG_NO_RETRANSMIT)));
+ ssl_SEND_FLAG_NO_RETRANSMIT)));
if (len < 0 || !in) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return SECFailure;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return SECFailure;
}
if (ss->pendingBuf.len > SSL3_PENDING_HIGH_WATER &&
!ssl_SocketIsBlocking(ss)) {
- PORT_Assert(!ssl_SocketIsBlocking(ss));
- PORT_SetError(PR_WOULD_BLOCK_ERROR);
- return SECFailure;
+ PORT_Assert(!ssl_SocketIsBlocking(ss));
+ PORT_SetError(PR_WOULD_BLOCK_ERROR);
+ return SECFailure;
}
if (ss->appDataBuffered && len) {
- PORT_Assert (in[0] == (unsigned char)(ss->appDataBuffered));
- if (in[0] != (unsigned char)(ss->appDataBuffered)) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return SECFailure;
- }
- in++;
- len--;
- discarded = 1;
+ PORT_Assert(in[0] == (unsigned char)(ss->appDataBuffered));
+ if (in[0] != (unsigned char)(ss->appDataBuffered)) {
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return SECFailure;
+ }
+ in++;
+ len--;
+ discarded = 1;
}
while (len > totalSent) {
- PRInt32 sent, toSend;
-
- if (totalSent > 0) {
- /*
- * The thread yield is intended to give the reader thread a
- * chance to get some cycles while the writer thread is in
- * the middle of a large application data write. (See
- * Bugzilla bug 127740, comment #1.)
- */
- ssl_ReleaseXmitBufLock(ss);
- PR_Sleep(PR_INTERVAL_NO_WAIT); /* PR_Yield(); */
- ssl_GetXmitBufLock(ss);
- }
- toSend = PR_MIN(len - totalSent, MAX_FRAGMENT_LENGTH);
- /*
- * Note that the 0 epoch is OK because flags will never require
- * its use, as guaranteed by the PORT_Assert above.
- */
- sent = ssl3_SendRecord(ss, 0, content_application_data,
- in + totalSent, toSend, flags);
- if (sent < 0) {
- if (totalSent > 0 && PR_GetError() == PR_WOULD_BLOCK_ERROR) {
- PORT_Assert(ss->lastWriteBlocked);
- break;
- }
- return SECFailure; /* error code set by ssl3_SendRecord */
- }
- totalSent += sent;
- if (ss->pendingBuf.len) {
- /* must be a non-blocking socket */
- PORT_Assert(!ssl_SocketIsBlocking(ss));
- PORT_Assert(ss->lastWriteBlocked);
- break;
- }
+ PRInt32 sent, toSend;
+
+ if (totalSent > 0) {
+ /*
+ * The thread yield is intended to give the reader thread a
+ * chance to get some cycles while the writer thread is in
+ * the middle of a large application data write. (See
+ * Bugzilla bug 127740, comment #1.)
+ */
+ ssl_ReleaseXmitBufLock(ss);
+ PR_Sleep(PR_INTERVAL_NO_WAIT); /* PR_Yield(); */
+ ssl_GetXmitBufLock(ss);
+ }
+ toSend = PR_MIN(len - totalSent, MAX_FRAGMENT_LENGTH);
+ /*
+ * Note that the 0 epoch is OK because flags will never require
+ * its use, as guaranteed by the PORT_Assert above.
+ */
+ sent = ssl3_SendRecord(ss, 0, content_application_data,
+ in + totalSent, toSend, flags);
+ if (sent < 0) {
+ if (totalSent > 0 && PR_GetError() == PR_WOULD_BLOCK_ERROR) {
+ PORT_Assert(ss->lastWriteBlocked);
+ break;
+ }
+ return SECFailure; /* error code set by ssl3_SendRecord */
+ }
+ totalSent += sent;
+ if (ss->pendingBuf.len) {
+ /* must be a non-blocking socket */
+ PORT_Assert(!ssl_SocketIsBlocking(ss));
+ PORT_Assert(ss->lastWriteBlocked);
+ break;
+ }
}
if (ss->pendingBuf.len) {
- /* Must be non-blocking. */
- PORT_Assert(!ssl_SocketIsBlocking(ss));
- if (totalSent > 0) {
- ss->appDataBuffered = 0x100 | in[totalSent - 1];
- }
-
- totalSent = totalSent + discarded - 1;
- if (totalSent <= 0) {
- PORT_SetError(PR_WOULD_BLOCK_ERROR);
- totalSent = SECFailure;
- }
- return totalSent;
- }
+ /* Must be non-blocking. */
+ PORT_Assert(!ssl_SocketIsBlocking(ss));
+ if (totalSent > 0) {
+ ss->appDataBuffered = 0x100 | in[totalSent - 1];
+ }
+
+ totalSent = totalSent + discarded - 1;
+ if (totalSent <= 0) {
+ PORT_SetError(PR_WOULD_BLOCK_ERROR);
+ totalSent = SECFailure;
+ }
+ return totalSent;
+ }
ss->appDataBuffered = 0;
return totalSent + discarded;
}
@@ -3250,7 +3260,7 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in,
* ssl3_SendHelloRequest(), ssl3_SendServerHelloDone(),
* ssl3_SendFinished(),
*/
-static SECStatus
+SECStatus
ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags)
{
if (IS_DTLS(ss)) {
@@ -3274,35 +3284,35 @@ ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
PRInt32 count = -1;
SECStatus rv = SECSuccess;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
- return rv;
+ return rv;
/* only these flags are allowed */
PORT_Assert(!(flags & ~allowedFlags));
if ((flags & ~allowedFlags) != 0) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
} else {
- count = ssl3_SendRecord(ss, 0, content_handshake, ss->sec.ci.sendBuf.buf,
- ss->sec.ci.sendBuf.len, flags);
+ count = ssl3_SendRecord(ss, 0, content_handshake, ss->sec.ci.sendBuf.buf,
+ ss->sec.ci.sendBuf.len, flags);
}
if (count < 0) {
- int err = PORT_GetError();
- PORT_Assert(err != PR_WOULD_BLOCK_ERROR);
- if (err == PR_WOULD_BLOCK_ERROR) {
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- }
+ int err = PORT_GetError();
+ PORT_Assert(err != PR_WOULD_BLOCK_ERROR);
+ if (err == PR_WOULD_BLOCK_ERROR) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ }
rv = SECFailure;
} else if ((unsigned int)count < ss->sec.ci.sendBuf.len) {
- /* short write should never happen */
- PORT_Assert((unsigned int)count >= ss->sec.ci.sendBuf.len);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- rv = SECFailure;
+ /* short write should never happen */
+ PORT_Assert((unsigned int)count >= ss->sec.ci.sendBuf.len);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ rv = SECFailure;
} else {
- rv = SECSuccess;
+ rv = SECSuccess;
}
/* Whether we succeeded or failed, toss the old handshake data. */
@@ -3320,12 +3330,12 @@ static SECStatus
ssl3_HandleNoCertificate(sslSocket *ss)
{
if (ss->sec.peerCert != NULL) {
- if (ss->sec.peerKey != NULL) {
- SECKEY_DestroyPublicKey(ss->sec.peerKey);
- ss->sec.peerKey = NULL;
- }
- CERT_DestroyCertificate(ss->sec.peerCert);
- ss->sec.peerCert = NULL;
+ if (ss->sec.peerKey != NULL) {
+ SECKEY_DestroyPublicKey(ss->sec.peerKey);
+ ss->sec.peerKey = NULL;
+ }
+ CERT_DestroyCertificate(ss->sec.peerCert);
+ ss->sec.peerCert = NULL;
}
ssl3_CleanupPeerCerts(ss);
@@ -3333,26 +3343,26 @@ ssl3_HandleNoCertificate(sslSocket *ss)
* actually look at the certificate it won't know that no
* certificate was presented so we shutdown the socket to ensure
* an error. We only do this if we haven't already completed the
- * first handshake because if we're redoing the handshake we
+ * first handshake because if we're redoing the handshake we
* know the server is paying attention to the certificate.
*/
if ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) ||
- (!ss->firstHsDone &&
- (ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE))) {
- PRFileDesc * lower;
+ (!ss->firstHsDone &&
+ (ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE))) {
+ PRFileDesc *lower;
- if (ss->sec.uncache)
+ if (ss->sec.uncache)
ss->sec.uncache(ss->sec.ci.sid);
- SSL3_SendAlert(ss, alert_fatal, bad_certificate);
+ SSL3_SendAlert(ss, alert_fatal, bad_certificate);
- lower = ss->fd->lower;
+ lower = ss->fd->lower;
#ifdef _WIN32
- lower->methods->shutdown(lower, PR_SHUTDOWN_SEND);
+ lower->methods->shutdown(lower, PR_SHUTDOWN_SEND);
#else
- lower->methods->shutdown(lower, PR_SHUTDOWN_BOTH);
+ lower->methods->shutdown(lower, PR_SHUTDOWN_BOTH);
#endif
- PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
+ return SECFailure;
}
return SECSuccess;
}
@@ -3363,59 +3373,59 @@ ssl3_HandleNoCertificate(sslSocket *ss)
/*
** Acquires both handshake and XmitBuf locks.
-** Called from: ssl3_IllegalParameter <-
-** ssl3_HandshakeFailure <-
-** ssl3_HandleAlert <- ssl3_HandleRecord.
+** Called from: ssl3_IllegalParameter <-
+** ssl3_HandshakeFailure <-
+** ssl3_HandleAlert <- ssl3_HandleRecord.
** ssl3_HandleChangeCipherSpecs <- ssl3_HandleRecord
** ssl3_ConsumeHandshakeVariable <-
-** ssl3_HandleHelloRequest <-
-** ssl3_HandleServerHello <-
+** ssl3_HandleHelloRequest <-
+** ssl3_HandleServerHello <-
** ssl3_HandleServerKeyExchange <-
** ssl3_HandleCertificateRequest <-
** ssl3_HandleServerHelloDone <-
-** ssl3_HandleClientHello <-
+** ssl3_HandleClientHello <-
** ssl3_HandleV2ClientHello <-
** ssl3_HandleCertificateVerify <-
** ssl3_HandleClientKeyExchange <-
-** ssl3_HandleCertificate <-
-** ssl3_HandleFinished <-
+** ssl3_HandleCertificate <-
+** ssl3_HandleFinished <-
** ssl3_HandleHandshakeMessage <-
-** ssl3_HandleRecord <-
+** ssl3_HandlePostHelloHandshakeMessage <-
+** ssl3_HandleRecord <-
**
*/
SECStatus
SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc)
{
- PRUint8 bytes[2];
- SECStatus rv;
+ PRUint8 bytes[2];
+ SECStatus rv;
SSL_TRC(3, ("%d: SSL3[%d]: send alert record, level=%d desc=%d",
- SSL_GETPID(), ss->fd, level, desc));
+ SSL_GETPID(), ss->fd, level, desc));
bytes[0] = level;
bytes[1] = desc;
ssl_GetSSL3HandshakeLock(ss);
if (level == alert_fatal) {
- if (!ss->opt.noCache && ss->sec.ci.sid && ss->sec.uncache) {
- ss->sec.uncache(ss->sec.ci.sid);
- }
+ if (!ss->opt.noCache && ss->sec.ci.sid && ss->sec.uncache) {
+ ss->sec.uncache(ss->sec.ci.sid);
+ }
}
ssl_GetXmitBufLock(ss);
rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
if (rv == SECSuccess) {
- PRInt32 sent;
- sent = ssl3_SendRecord(ss, 0, content_alert, bytes, 2,
- desc == no_certificate
- ? ssl_SEND_FLAG_FORCE_INTO_BUFFER : 0);
- rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
+ PRInt32 sent;
+ sent = ssl3_SendRecord(ss, 0, content_alert, bytes, 2,
+ desc == no_certificate ? ssl_SEND_FLAG_FORCE_INTO_BUFFER : 0);
+ rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
}
if (level == alert_fatal) {
ss->ssl3.fatalAlertSent = PR_TRUE;
}
ssl_ReleaseXmitBufLock(ss);
ssl_ReleaseSSL3HandshakeLock(ss);
- return rv; /* error set by ssl3_FlushHandshake or ssl3_SendRecord */
+ return rv; /* error set by ssl3_FlushHandshake or ssl3_SendRecord */
}
/*
@@ -3426,7 +3436,7 @@ ssl3_IllegalParameter(sslSocket *ss)
{
(void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
- : SSL_ERROR_BAD_SERVER );
+ : SSL_ERROR_BAD_SERVER);
return SECFailure;
}
@@ -3437,56 +3447,67 @@ static SECStatus
ssl3_HandshakeFailure(sslSocket *ss)
{
(void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
- PORT_SetError( ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
- : SSL_ERROR_BAD_SERVER );
+ PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
+ : SSL_ERROR_BAD_SERVER);
return SECFailure;
}
static void
-ssl3_SendAlertForCertError(sslSocket * ss, PRErrorCode errCode)
+ssl3_SendAlertForCertError(sslSocket *ss, PRErrorCode errCode)
{
- SSL3AlertDescription desc = bad_certificate;
+ SSL3AlertDescription desc = bad_certificate;
PRBool isTLS = ss->version >= SSL_LIBRARY_VERSION_3_1_TLS;
switch (errCode) {
- case SEC_ERROR_LIBRARY_FAILURE: desc = unsupported_certificate; break;
- case SEC_ERROR_EXPIRED_CERTIFICATE: desc = certificate_expired; break;
- case SEC_ERROR_REVOKED_CERTIFICATE: desc = certificate_revoked; break;
- case SEC_ERROR_INADEQUATE_KEY_USAGE:
- case SEC_ERROR_INADEQUATE_CERT_TYPE:
- desc = certificate_unknown; break;
- case SEC_ERROR_UNTRUSTED_CERT:
- desc = isTLS ? access_denied : certificate_unknown; break;
- case SEC_ERROR_UNKNOWN_ISSUER:
- case SEC_ERROR_UNTRUSTED_ISSUER:
- desc = isTLS ? unknown_ca : certificate_unknown; break;
- case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
- desc = isTLS ? unknown_ca : certificate_expired; break;
-
- case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
- case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID:
- case SEC_ERROR_CA_CERT_INVALID:
- case SEC_ERROR_BAD_SIGNATURE:
- default: desc = bad_certificate; break;
+ case SEC_ERROR_LIBRARY_FAILURE:
+ desc = unsupported_certificate;
+ break;
+ case SEC_ERROR_EXPIRED_CERTIFICATE:
+ desc = certificate_expired;
+ break;
+ case SEC_ERROR_REVOKED_CERTIFICATE:
+ desc = certificate_revoked;
+ break;
+ case SEC_ERROR_INADEQUATE_KEY_USAGE:
+ case SEC_ERROR_INADEQUATE_CERT_TYPE:
+ desc = certificate_unknown;
+ break;
+ case SEC_ERROR_UNTRUSTED_CERT:
+ desc = isTLS ? access_denied : certificate_unknown;
+ break;
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ case SEC_ERROR_UNTRUSTED_ISSUER:
+ desc = isTLS ? unknown_ca : certificate_unknown;
+ break;
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ desc = isTLS ? unknown_ca : certificate_expired;
+ break;
+
+ case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
+ case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID:
+ case SEC_ERROR_CA_CERT_INVALID:
+ case SEC_ERROR_BAD_SIGNATURE:
+ default:
+ desc = bad_certificate;
+ break;
}
SSL_DBG(("%d: SSL3[%d]: peer certificate is no good: error=%d",
- SSL_GETPID(), ss->fd, errCode));
+ SSL_GETPID(), ss->fd, errCode));
- (void) SSL3_SendAlert(ss, alert_fatal, desc);
+ (void)SSL3_SendAlert(ss, alert_fatal, desc);
}
-
/*
* Send decode_error alert. Set generic error number.
*/
SECStatus
ssl3_DecodeError(sslSocket *ss)
{
- (void)SSL3_SendAlert(ss, alert_fatal,
- ss->version > SSL_LIBRARY_VERSION_3_0 ? decode_error
- : illegal_parameter);
- PORT_SetError( ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
- : SSL_ERROR_BAD_SERVER );
+ (void)SSL3_SendAlert(ss, alert_fatal,
+ ss->version > SSL_LIBRARY_VERSION_3_0 ? decode_error
+ : illegal_parameter);
+ PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
+ : SSL_ERROR_BAD_SERVER);
return SECFailure;
}
@@ -3496,102 +3517,152 @@ ssl3_DecodeError(sslSocket *ss)
static SECStatus
ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf)
{
- SSL3AlertLevel level;
+ SSL3AlertLevel level;
SSL3AlertDescription desc;
- int error;
+ int error;
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
SSL_TRC(3, ("%d: SSL3[%d]: handle alert record", SSL_GETPID(), ss->fd));
if (buf->len != 2) {
- (void)ssl3_DecodeError(ss);
- PORT_SetError(SSL_ERROR_RX_MALFORMED_ALERT);
- return SECFailure;
+ (void)ssl3_DecodeError(ss);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_ALERT);
+ return SECFailure;
}
level = (SSL3AlertLevel)buf->buf[0];
- desc = (SSL3AlertDescription)buf->buf[1];
+ desc = (SSL3AlertDescription)buf->buf[1];
buf->len = 0;
SSL_TRC(5, ("%d: SSL3[%d] received alert, level = %d, description = %d",
- SSL_GETPID(), ss->fd, level, desc));
+ SSL_GETPID(), ss->fd, level, desc));
switch (desc) {
- case close_notify: ss->recvdCloseNotify = 1;
- error = SSL_ERROR_CLOSE_NOTIFY_ALERT; break;
- case unexpected_message: error = SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT;
- break;
- case bad_record_mac: error = SSL_ERROR_BAD_MAC_ALERT; break;
- case decryption_failed_RESERVED:
- error = SSL_ERROR_DECRYPTION_FAILED_ALERT;
- break;
- case record_overflow: error = SSL_ERROR_RECORD_OVERFLOW_ALERT; break;
- case decompression_failure: error = SSL_ERROR_DECOMPRESSION_FAILURE_ALERT;
- break;
- case handshake_failure: error = SSL_ERROR_HANDSHAKE_FAILURE_ALERT;
- break;
- case no_certificate: error = SSL_ERROR_NO_CERTIFICATE; break;
- case bad_certificate: error = SSL_ERROR_BAD_CERT_ALERT; break;
- case unsupported_certificate:error = SSL_ERROR_UNSUPPORTED_CERT_ALERT;break;
- case certificate_revoked: error = SSL_ERROR_REVOKED_CERT_ALERT; break;
- case certificate_expired: error = SSL_ERROR_EXPIRED_CERT_ALERT; break;
- case certificate_unknown: error = SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT;
- break;
- case illegal_parameter: error = SSL_ERROR_ILLEGAL_PARAMETER_ALERT;break;
- case inappropriate_fallback:
- error = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT;
- break;
-
- /* All alerts below are TLS only. */
- case unknown_ca: error = SSL_ERROR_UNKNOWN_CA_ALERT; break;
- case access_denied: error = SSL_ERROR_ACCESS_DENIED_ALERT; break;
- case decode_error: error = SSL_ERROR_DECODE_ERROR_ALERT; break;
- case decrypt_error: error = SSL_ERROR_DECRYPT_ERROR_ALERT; break;
- case export_restriction: error = SSL_ERROR_EXPORT_RESTRICTION_ALERT;
- break;
- case protocol_version: error = SSL_ERROR_PROTOCOL_VERSION_ALERT; break;
- case insufficient_security: error = SSL_ERROR_INSUFFICIENT_SECURITY_ALERT;
- break;
- case internal_error: error = SSL_ERROR_INTERNAL_ERROR_ALERT; break;
- case user_canceled: error = SSL_ERROR_USER_CANCELED_ALERT; break;
- case no_renegotiation: error = SSL_ERROR_NO_RENEGOTIATION_ALERT; break;
-
- /* Alerts for TLS client hello extensions */
- case unsupported_extension:
- error = SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT; break;
- case certificate_unobtainable:
- error = SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT; break;
- case unrecognized_name:
- error = SSL_ERROR_UNRECOGNIZED_NAME_ALERT; break;
- case bad_certificate_status_response:
- error = SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT; break;
- case bad_certificate_hash_value:
- error = SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT; break;
- default: error = SSL_ERROR_RX_UNKNOWN_ALERT; break;
+ case close_notify:
+ ss->recvdCloseNotify = 1;
+ error = SSL_ERROR_CLOSE_NOTIFY_ALERT;
+ break;
+ case unexpected_message:
+ error = SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT;
+ break;
+ case bad_record_mac:
+ error = SSL_ERROR_BAD_MAC_ALERT;
+ break;
+ case decryption_failed_RESERVED:
+ error = SSL_ERROR_DECRYPTION_FAILED_ALERT;
+ break;
+ case record_overflow:
+ error = SSL_ERROR_RECORD_OVERFLOW_ALERT;
+ break;
+ case decompression_failure:
+ error = SSL_ERROR_DECOMPRESSION_FAILURE_ALERT;
+ break;
+ case handshake_failure:
+ error = SSL_ERROR_HANDSHAKE_FAILURE_ALERT;
+ break;
+ case no_certificate:
+ error = SSL_ERROR_NO_CERTIFICATE;
+ break;
+ case bad_certificate:
+ error = SSL_ERROR_BAD_CERT_ALERT;
+ break;
+ case unsupported_certificate:
+ error = SSL_ERROR_UNSUPPORTED_CERT_ALERT;
+ break;
+ case certificate_revoked:
+ error = SSL_ERROR_REVOKED_CERT_ALERT;
+ break;
+ case certificate_expired:
+ error = SSL_ERROR_EXPIRED_CERT_ALERT;
+ break;
+ case certificate_unknown:
+ error = SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT;
+ break;
+ case illegal_parameter:
+ error = SSL_ERROR_ILLEGAL_PARAMETER_ALERT;
+ break;
+ case inappropriate_fallback:
+ error = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT;
+ break;
+
+ /* All alerts below are TLS only. */
+ case unknown_ca:
+ error = SSL_ERROR_UNKNOWN_CA_ALERT;
+ break;
+ case access_denied:
+ error = SSL_ERROR_ACCESS_DENIED_ALERT;
+ break;
+ case decode_error:
+ error = SSL_ERROR_DECODE_ERROR_ALERT;
+ break;
+ case decrypt_error:
+ error = SSL_ERROR_DECRYPT_ERROR_ALERT;
+ break;
+ case export_restriction:
+ error = SSL_ERROR_EXPORT_RESTRICTION_ALERT;
+ break;
+ case protocol_version:
+ error = SSL_ERROR_PROTOCOL_VERSION_ALERT;
+ break;
+ case insufficient_security:
+ error = SSL_ERROR_INSUFFICIENT_SECURITY_ALERT;
+ break;
+ case internal_error:
+ error = SSL_ERROR_INTERNAL_ERROR_ALERT;
+ break;
+ case user_canceled:
+ error = SSL_ERROR_USER_CANCELED_ALERT;
+ break;
+ case no_renegotiation:
+ error = SSL_ERROR_NO_RENEGOTIATION_ALERT;
+ break;
+
+ /* Alerts for TLS client hello extensions */
+ case missing_extension:
+ error = SSL_ERROR_MISSING_EXTENSION_ALERT;
+ break;
+ case unsupported_extension:
+ error = SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT;
+ break;
+ case certificate_unobtainable:
+ error = SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT;
+ break;
+ case unrecognized_name:
+ error = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
+ break;
+ case bad_certificate_status_response:
+ error = SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT;
+ break;
+ case bad_certificate_hash_value:
+ error = SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT;
+ break;
+ default:
+ error = SSL_ERROR_RX_UNKNOWN_ALERT;
+ break;
}
if (level == alert_fatal) {
- if (!ss->opt.noCache) {
- if (ss->sec.uncache)
+ if (!ss->opt.noCache) {
+ if (ss->sec.uncache)
ss->sec.uncache(ss->sec.ci.sid);
- }
- if ((ss->ssl3.hs.ws == wait_server_hello) &&
- (desc == handshake_failure)) {
- /* XXX This is a hack. We're assuming that any handshake failure
- * XXX on the client hello is a failure to match ciphers.
- */
- error = SSL_ERROR_NO_CYPHER_OVERLAP;
- }
- PORT_SetError(error);
- return SECFailure;
+ }
+ if ((ss->ssl3.hs.ws == wait_server_hello) &&
+ (desc == handshake_failure)) {
+ /* XXX This is a hack. We're assuming that any handshake failure
+ * XXX on the client hello is a failure to match ciphers.
+ */
+ error = SSL_ERROR_NO_CYPHER_OVERLAP;
+ }
+ PORT_SetError(error);
+ return SECFailure;
}
if ((desc == no_certificate) && (ss->ssl3.hs.ws == wait_client_cert)) {
- /* I'm a server. I've requested a client cert. He hasn't got one. */
- SECStatus rv;
+ /* I'm a server. I've requested a client cert. He hasn't got one. */
+ SECStatus rv;
- PORT_Assert(ss->sec.isServer);
- ss->ssl3.hs.ws = wait_client_key;
- rv = ssl3_HandleNoCertificate(ss);
- return rv;
+ PORT_Assert(ss->sec.isServer);
+ ss->ssl3.hs.ws = wait_client_key;
+ rv = ssl3_HandleNoCertificate(ss);
+ return rv;
}
return SECSuccess;
}
@@ -3609,57 +3680,57 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf)
static SECStatus
ssl3_SendChangeCipherSpecs(sslSocket *ss)
{
- PRUint8 change = change_cipher_spec_choice;
- ssl3CipherSpec * pwSpec;
- SECStatus rv;
- PRInt32 sent;
+ PRUint8 change = change_cipher_spec_choice;
+ ssl3CipherSpec *pwSpec;
+ SECStatus rv;
+ PRInt32 sent;
SSL_TRC(3, ("%d: SSL3[%d]: send change_cipher_spec record",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
if (rv != SECSuccess) {
- return rv; /* error code set by ssl3_FlushHandshake */
+ return rv; /* error code set by ssl3_FlushHandshake */
}
if (!IS_DTLS(ss)) {
- sent = ssl3_SendRecord(ss, 0, content_change_cipher_spec, &change, 1,
- ssl_SEND_FLAG_FORCE_INTO_BUFFER);
- if (sent < 0) {
- return (SECStatus)sent; /* error code set by ssl3_SendRecord */
- }
+ sent = ssl3_SendRecord(ss, 0, content_change_cipher_spec, &change, 1,
+ ssl_SEND_FLAG_FORCE_INTO_BUFFER);
+ if (sent < 0) {
+ return (SECStatus)sent; /* error code set by ssl3_SendRecord */
+ }
} else {
- rv = dtls_QueueMessage(ss, content_change_cipher_spec, &change, 1);
- if (rv != SECSuccess) {
- return rv;
- }
+ rv = dtls_QueueMessage(ss, content_change_cipher_spec, &change, 1);
+ if (rv != SECSuccess) {
+ return rv;
+ }
}
/* swap the pending and current write specs. */
- ssl_GetSpecWriteLock(ss); /**************************************/
- pwSpec = ss->ssl3.pwSpec;
+ ssl_GetSpecWriteLock(ss); /**************************************/
+ pwSpec = ss->ssl3.pwSpec;
ss->ssl3.pwSpec = ss->ssl3.cwSpec;
ss->ssl3.cwSpec = pwSpec;
SSL_TRC(3, ("%d: SSL3[%d] Set Current Write Cipher Suite to Pending",
- SSL_GETPID(), ss->fd ));
+ SSL_GETPID(), ss->fd));
/* We need to free up the contexts, keys and certs ! */
/* If we are really through with the old cipher spec
* (Both the read and write sides have changed) destroy it.
*/
if (ss->ssl3.prSpec == ss->ssl3.pwSpec) {
- if (!IS_DTLS(ss)) {
- ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE/*freeSrvName*/);
- } else {
- /* With DTLS, we need to set a holddown timer in case the final
- * message got lost */
- ss->ssl3.hs.rtTimeoutMs = DTLS_FINISHED_TIMER_MS;
- dtls_StartTimer(ss, dtls_FinishedTimerCb);
- }
+ if (!IS_DTLS(ss)) {
+ ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE /*freeSrvName*/);
+ } else {
+ /* With DTLS, we need to set a holddown timer in case the final
+ * message got lost */
+ ss->ssl3.hs.rtTimeoutMs = DTLS_FINISHED_TIMER_MS;
+ dtls_StartTimer(ss, dtls_FinishedTimerCb);
+ }
}
ssl_ReleaseSpecWriteLock(ss); /**************************************/
@@ -3675,62 +3746,62 @@ ssl3_SendChangeCipherSpecs(sslSocket *ss)
static SECStatus
ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf)
{
- ssl3CipherSpec * prSpec;
- SSL3WaitState ws = ss->ssl3.hs.ws;
+ ssl3CipherSpec *prSpec;
+ SSL3WaitState ws = ss->ssl3.hs.ws;
SSL3ChangeCipherSpecChoice change;
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
SSL_TRC(3, ("%d: SSL3[%d]: handle change_cipher_spec record",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
if (ws != wait_change_cipher) {
- if (IS_DTLS(ss)) {
- /* Ignore this because it's out of order. */
- SSL_TRC(3, ("%d: SSL3[%d]: discard out of order "
- "DTLS change_cipher_spec",
- SSL_GETPID(), ss->fd));
- buf->len = 0;
- return SECSuccess;
- }
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER);
- return SECFailure;
- }
-
- if(buf->len != 1) {
- (void)ssl3_DecodeError(ss);
- PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
- return SECFailure;
+ if (IS_DTLS(ss)) {
+ /* Ignore this because it's out of order. */
+ SSL_TRC(3, ("%d: SSL3[%d]: discard out of order "
+ "DTLS change_cipher_spec",
+ SSL_GETPID(), ss->fd));
+ buf->len = 0;
+ return SECSuccess;
+ }
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER);
+ return SECFailure;
+ }
+
+ if (buf->len != 1) {
+ (void)ssl3_DecodeError(ss);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
+ return SECFailure;
}
change = (SSL3ChangeCipherSpecChoice)buf->buf[0];
if (change != change_cipher_spec_choice) {
- /* illegal_parameter is correct here for both SSL3 and TLS. */
- (void)ssl3_IllegalParameter(ss);
- PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
- return SECFailure;
+ /* illegal_parameter is correct here for both SSL3 and TLS. */
+ (void)ssl3_IllegalParameter(ss);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
+ return SECFailure;
}
buf->len = 0;
/* Swap the pending and current read specs. */
- ssl_GetSpecWriteLock(ss); /*************************************/
- prSpec = ss->ssl3.prSpec;
+ ssl_GetSpecWriteLock(ss); /*************************************/
+ prSpec = ss->ssl3.prSpec;
- ss->ssl3.prSpec = ss->ssl3.crSpec;
- ss->ssl3.crSpec = prSpec;
- ss->ssl3.hs.ws = wait_finished;
+ ss->ssl3.prSpec = ss->ssl3.crSpec;
+ ss->ssl3.crSpec = prSpec;
+ ss->ssl3.hs.ws = wait_finished;
SSL_TRC(3, ("%d: SSL3[%d] Set Current Read Cipher Suite to Pending",
- SSL_GETPID(), ss->fd ));
+ SSL_GETPID(), ss->fd));
/* If we are really through with the old cipher prSpec
* (Both the read and write sides have changed) destroy it.
*/
if (ss->ssl3.prSpec == ss->ssl3.pwSpec) {
- ssl3_DestroyCipherSpec(ss->ssl3.prSpec, PR_FALSE/*freeSrvName*/);
+ ssl3_DestroyCipherSpec(ss->ssl3.prSpec, PR_FALSE /*freeSrvName*/);
}
- ssl_ReleaseSpecWriteLock(ss); /*************************************/
+ ssl_ReleaseSpecWriteLock(ss); /*************************************/
return SECSuccess;
}
@@ -3799,56 +3870,62 @@ static SECStatus
ssl3_ComputeMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
PK11SymKey **msp)
{
- ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec;
- const ssl3KEADef *kea_def= ss->ssl3.hs.kea_def;
- unsigned char * cr = (unsigned char *)&ss->ssl3.hs.client_random;
- unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random;
- PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
- (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
- PRBool isTLS12=
- (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
+ ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
+ const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
+ unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random;
+ unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random;
+ PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
+ (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
+ PRBool isTLS12 =
+ (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
/*
* Whenever isDH is true, we need to use CKM_TLS_MASTER_KEY_DERIVE_DH
* which, unlike CKM_TLS_MASTER_KEY_DERIVE, converts arbitrary size
* data into a 48-byte value, and does not expect to return the version.
*/
- PRBool isDH = (PRBool) ((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) ||
- (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh));
+ PRBool isDH = (PRBool)((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) ||
+ (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh));
CK_MECHANISM_TYPE master_derive;
CK_MECHANISM_TYPE key_derive;
- SECItem params;
- CK_FLAGS keyFlags;
- CK_VERSION pms_version;
- CK_VERSION *pms_version_ptr = NULL;
+ SECItem params;
+ CK_FLAGS keyFlags;
+ CK_VERSION pms_version;
+ CK_VERSION *pms_version_ptr = NULL;
/* master_params may be used as a CK_SSL3_MASTER_KEY_DERIVE_PARAMS */
CK_TLS12_MASTER_KEY_DERIVE_PARAMS master_params;
- unsigned int master_params_len;
+ unsigned int master_params_len;
if (isTLS12) {
- if(isDH) master_derive = CKM_TLS12_MASTER_KEY_DERIVE_DH;
- else master_derive = CKM_TLS12_MASTER_KEY_DERIVE;
- key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
- keyFlags = CKF_SIGN | CKF_VERIFY;
+ if (isDH)
+ master_derive = CKM_TLS12_MASTER_KEY_DERIVE_DH;
+ else
+ master_derive = CKM_TLS12_MASTER_KEY_DERIVE;
+ key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
+ keyFlags = CKF_SIGN | CKF_VERIFY;
} else if (isTLS) {
- if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH;
- else master_derive = CKM_TLS_MASTER_KEY_DERIVE;
- key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
- keyFlags = CKF_SIGN | CKF_VERIFY;
+ if (isDH)
+ master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH;
+ else
+ master_derive = CKM_TLS_MASTER_KEY_DERIVE;
+ key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
+ keyFlags = CKF_SIGN | CKF_VERIFY;
} else {
- if (isDH) master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH;
- else master_derive = CKM_SSL3_MASTER_KEY_DERIVE;
- key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
- keyFlags = 0;
+ if (isDH)
+ master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH;
+ else
+ master_derive = CKM_SSL3_MASTER_KEY_DERIVE;
+ key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
+ keyFlags = 0;
}
if (!isDH) {
pms_version_ptr = &pms_version;
}
- master_params.pVersion = pms_version_ptr;
- master_params.RandomInfo.pClientRandom = cr;
+ master_params.pVersion = pms_version_ptr;
+ master_params.RandomInfo.pClientRandom = cr;
master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
- master_params.RandomInfo.pServerRandom = sr;
+ master_params.RandomInfo.pServerRandom = sr;
master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
if (isTLS12) {
master_params.prfHashMechanism = CKM_SHA256;
@@ -3858,8 +3935,8 @@ ssl3_ComputeMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
master_params_len = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
}
- params.data = (unsigned char *) &master_params;
- params.len = master_params_len;
+ params.data = (unsigned char *)&master_params;
+ params.len = master_params_len;
return ssl3_ComputeMasterSecretFinish(ss, master_derive, key_derive,
pms_version_ptr, &params,
@@ -3883,9 +3960,9 @@ tls_ComputeExtendedMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
*/
/*
* TODO(ekr@rtfm.com): Verify that the slot can handle this key expansion
- * mode. Bug 1198298 */
- PRBool isDH = (PRBool) ((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) ||
- (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh));
+ * mode. Bug 1198298 */
+ PRBool isDH = (PRBool)((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) ||
+ (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh));
CK_MECHANISM_TYPE master_derive;
CK_MECHANISM_TYPE key_derive;
SECItem params;
@@ -3896,7 +3973,7 @@ tls_ComputeExtendedMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
rv = ssl3_ComputeHandshakeHashes(ss, pwSpec, &hashes, 0);
if (rv != SECSuccess) {
- PORT_Assert(0); /* Should never fail */
+ PORT_Assert(0); /* Should never fail */
ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
return SECFailure;
}
@@ -3915,14 +3992,14 @@ tls_ComputeExtendedMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
} else {
/* TLS < 1.2 */
extended_master_params.prfHashMechanism = CKM_TLS_PRF;
- key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
+ key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
}
extended_master_params.pVersion = pms_version_ptr;
extended_master_params.pSessionHash = hashes.u.raw;
extended_master_params.ulSessionHashLen = hashes.len;
- params.data = (unsigned char *) &extended_master_params;
+ params.data = (unsigned char *)&extended_master_params;
params.len = sizeof extended_master_params;
return ssl3_ComputeMasterSecretFinish(ss, master_derive, key_derive,
@@ -3930,7 +4007,6 @@ tls_ComputeExtendedMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
keyFlags, pms, msp);
}
-
/* Wrapper method to compute the master secret and return it in |*msp|.
**
** Called from ssl3_ComputeMasterSecret
@@ -3963,11 +4039,11 @@ static SECStatus
ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms)
{
SECStatus rv;
- PK11SymKey* ms = NULL;
+ PK11SymKey *ms = NULL;
ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
if (pms) {
@@ -3979,34 +4055,34 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms)
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11) {
- SECItem * keydata;
- /* In hope of doing a "double bypass",
- * need to extract the master secret's value from the key object
- * and store it raw in the sslSocket struct.
- */
- rv = PK11_ExtractKeyValue(pwSpec->master_secret);
- if (rv != SECSuccess) {
- return rv;
- }
- /* This returns the address of the secItem inside the key struct,
- * not a copy or a reference. So, there's no need to free it.
- */
- keydata = PK11_GetKeyData(pwSpec->master_secret);
- if (keydata && keydata->len <= sizeof pwSpec->raw_master_secret) {
- memcpy(pwSpec->raw_master_secret, keydata->data, keydata->len);
- pwSpec->msItem.data = pwSpec->raw_master_secret;
- pwSpec->msItem.len = keydata->len;
- } else {
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
- }
+ SECItem *keydata;
+ /* In hope of doing a "double bypass",
+ * need to extract the master secret's value from the key object
+ * and store it raw in the sslSocket struct.
+ */
+ rv = PK11_ExtractKeyValue(pwSpec->master_secret);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ /* This returns the address of the secItem inside the key struct,
+ * not a copy or a reference. So, there's no need to free it.
+ */
+ keydata = PK11_GetKeyData(pwSpec->master_secret);
+ if (keydata && keydata->len <= sizeof pwSpec->raw_master_secret) {
+ memcpy(pwSpec->raw_master_secret, keydata->data, keydata->len);
+ pwSpec->msItem.data = pwSpec->raw_master_secret;
+ pwSpec->msItem.len = keydata->len;
+ } else {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
}
#endif
return SECSuccess;
}
-/*
+/*
* Derive encryption and MAC Keys (and IVs) from master secret
* Sets a useful error code when returning SECFailure.
*
@@ -4024,138 +4100,137 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms)
static SECStatus
ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss)
{
- ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec;
- const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def;
- unsigned char * cr = (unsigned char *)&ss->ssl3.hs.client_random;
- unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random;
- PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
- (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
- PRBool isTLS12=
- (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
+ ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
+ const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
+ unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random;
+ unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random;
+ PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
+ (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
+ PRBool isTLS12 =
+ (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
/* following variables used in PKCS11 path */
const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;
- PK11SlotInfo * slot = NULL;
- PK11SymKey * symKey = NULL;
- void * pwArg = ss->pkcs11PinArg;
- int keySize;
+ PK11SlotInfo *slot = NULL;
+ PK11SymKey *symKey = NULL;
+ void *pwArg = ss->pkcs11PinArg;
+ int keySize;
CK_TLS12_KEY_MAT_PARAMS key_material_params; /* may be used as a
- * CK_SSL3_KEY_MAT_PARAMS */
- unsigned int key_material_params_len;
- CK_SSL3_KEY_MAT_OUT returnedKeys;
- CK_MECHANISM_TYPE key_derive;
- CK_MECHANISM_TYPE bulk_mechanism;
- SSLCipherAlgorithm calg;
- SECItem params;
- PRBool skipKeysAndIVs = (PRBool)(cipher_def->calg == calg_null);
-
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
+ * CK_SSL3_KEY_MAT_PARAMS */
+ unsigned int key_material_params_len;
+ CK_SSL3_KEY_MAT_OUT returnedKeys;
+ CK_MECHANISM_TYPE key_derive;
+ CK_MECHANISM_TYPE bulk_mechanism;
+ SSLCipherAlgorithm calg;
+ SECItem params;
+ PRBool skipKeysAndIVs = (PRBool)(cipher_def->calg == calg_null);
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
if (!pwSpec->master_secret) {
- PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
+ return SECFailure;
}
/*
* generate the key material
*/
- key_material_params.ulMacSizeInBits = pwSpec->mac_size * BPB;
- key_material_params.ulKeySizeInBits = cipher_def->secret_key_size* BPB;
- key_material_params.ulIVSizeInBits = cipher_def->iv_size * BPB;
+ key_material_params.ulMacSizeInBits = pwSpec->mac_size * BPB;
+ key_material_params.ulKeySizeInBits = cipher_def->secret_key_size * BPB;
+ key_material_params.ulIVSizeInBits = cipher_def->iv_size * BPB;
if (cipher_def->type == type_block &&
- pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
- /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */
- key_material_params.ulIVSizeInBits = 0;
- memset(pwSpec->client.write_iv, 0, cipher_def->iv_size);
- memset(pwSpec->server.write_iv, 0, cipher_def->iv_size);
+ pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
+ /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */
+ key_material_params.ulIVSizeInBits = 0;
+ memset(pwSpec->client.write_iv, 0, cipher_def->iv_size);
+ memset(pwSpec->server.write_iv, 0, cipher_def->iv_size);
}
key_material_params.bIsExport = (CK_BBOOL)(kea_def->is_limited);
- key_material_params.RandomInfo.pClientRandom = cr;
+ key_material_params.RandomInfo.pClientRandom = cr;
key_material_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
- key_material_params.RandomInfo.pServerRandom = sr;
+ key_material_params.RandomInfo.pServerRandom = sr;
key_material_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
- key_material_params.pReturnedKeyMaterial = &returnedKeys;
+ key_material_params.pReturnedKeyMaterial = &returnedKeys;
returnedKeys.pIVClient = pwSpec->client.write_iv;
returnedKeys.pIVServer = pwSpec->server.write_iv;
- keySize = cipher_def->key_size;
+ keySize = cipher_def->key_size;
if (skipKeysAndIVs) {
- keySize = 0;
+ keySize = 0;
key_material_params.ulKeySizeInBits = 0;
- key_material_params.ulIVSizeInBits = 0;
- returnedKeys.pIVClient = NULL;
- returnedKeys.pIVServer = NULL;
+ key_material_params.ulIVSizeInBits = 0;
+ returnedKeys.pIVClient = NULL;
+ returnedKeys.pIVServer = NULL;
}
calg = cipher_def->calg;
- PORT_Assert( alg2Mech[calg].calg == calg);
- bulk_mechanism = alg2Mech[calg].cmech;
+ bulk_mechanism = ssl3_Alg2Mech(calg);
if (isTLS12) {
- key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
- key_material_params.prfHashMechanism = CKM_SHA256;
- key_material_params_len = sizeof(CK_TLS12_KEY_MAT_PARAMS);
+ key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
+ key_material_params.prfHashMechanism = CKM_SHA256;
+ key_material_params_len = sizeof(CK_TLS12_KEY_MAT_PARAMS);
} else if (isTLS) {
- key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
- key_material_params_len = sizeof(CK_SSL3_KEY_MAT_PARAMS);
+ key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
+ key_material_params_len = sizeof(CK_SSL3_KEY_MAT_PARAMS);
} else {
- key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
- key_material_params_len = sizeof(CK_SSL3_KEY_MAT_PARAMS);
+ key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
+ key_material_params_len = sizeof(CK_SSL3_KEY_MAT_PARAMS);
}
params.data = (unsigned char *)&key_material_params;
- params.len = key_material_params_len;
+ params.len = key_material_params_len;
/* CKM_SSL3_KEY_AND_MAC_DERIVE is defined to set ENCRYPT, DECRYPT, and
* DERIVE by DEFAULT */
symKey = PK11_Derive(pwSpec->master_secret, key_derive, &params,
bulk_mechanism, CKA_ENCRYPT, keySize);
if (!symKey) {
- ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
- return SECFailure;
+ ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
+ return SECFailure;
}
/* we really should use the actual mac'ing mechanism here, but we
* don't because these types are used to map keytype anyway and both
* mac's map to the same keytype.
*/
- slot = PK11_GetSlotFromKey(symKey);
+ slot = PK11_GetSlotFromKey(symKey);
PK11_FreeSlot(slot); /* slot is held until the key is freed */
pwSpec->client.write_mac_key =
- PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
- CKM_SSL3_SHA1_MAC, returnedKeys.hClientMacSecret, PR_TRUE, pwArg);
- if (pwSpec->client.write_mac_key == NULL ) {
- goto loser; /* loser sets err */
+ PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
+ CKM_SSL3_SHA1_MAC, returnedKeys.hClientMacSecret, PR_TRUE, pwArg);
+ if (pwSpec->client.write_mac_key == NULL) {
+ goto loser; /* loser sets err */
}
pwSpec->server.write_mac_key =
- PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
- CKM_SSL3_SHA1_MAC, returnedKeys.hServerMacSecret, PR_TRUE, pwArg);
- if (pwSpec->server.write_mac_key == NULL ) {
- goto loser; /* loser sets err */
+ PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
+ CKM_SSL3_SHA1_MAC, returnedKeys.hServerMacSecret, PR_TRUE, pwArg);
+ if (pwSpec->server.write_mac_key == NULL) {
+ goto loser; /* loser sets err */
}
if (!skipKeysAndIVs) {
- pwSpec->client.write_key =
- PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
- bulk_mechanism, returnedKeys.hClientKey, PR_TRUE, pwArg);
- if (pwSpec->client.write_key == NULL ) {
- goto loser; /* loser sets err */
- }
- pwSpec->server.write_key =
- PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
- bulk_mechanism, returnedKeys.hServerKey, PR_TRUE, pwArg);
- if (pwSpec->server.write_key == NULL ) {
- goto loser; /* loser sets err */
- }
+ pwSpec->client.write_key =
+ PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
+ bulk_mechanism, returnedKeys.hClientKey, PR_TRUE, pwArg);
+ if (pwSpec->client.write_key == NULL) {
+ goto loser; /* loser sets err */
+ }
+ pwSpec->server.write_key =
+ PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,
+ bulk_mechanism, returnedKeys.hServerKey, PR_TRUE, pwArg);
+ if (pwSpec->server.write_key == NULL) {
+ goto loser; /* loser sets err */
+ }
}
PK11_FreeSymKey(symKey);
return SECSuccess;
-
loser:
- if (symKey) PK11_FreeSymKey(symKey);
+ if (symKey)
+ PK11_FreeSymKey(symKey);
ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
return SECFailure;
}
@@ -4165,123 +4240,123 @@ loser:
static SECStatus
ssl3_InitHandshakeHashes(sslSocket *ss)
{
- SSL_TRC(30,("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd));
+ SSL_TRC(30, ("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd));
PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_unknown);
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11) {
- PORT_Assert(!ss->ssl3.hs.sha_obj && !ss->ssl3.hs.sha_clone);
- if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
- /* If we ever support ciphersuites where the PRF hash isn't SHA-256
- * then this will need to be updated. */
- ss->ssl3.hs.sha_obj = HASH_GetRawHashObject(HASH_AlgSHA256);
- if (!ss->ssl3.hs.sha_obj) {
- ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
- return SECFailure;
- }
- ss->ssl3.hs.sha_clone = (void (*)(void *, void *))SHA256_Clone;
- ss->ssl3.hs.hashType = handshake_hash_single;
- ss->ssl3.hs.sha_obj->begin(ss->ssl3.hs.sha_cx);
- } else {
- ss->ssl3.hs.hashType = handshake_hash_combo;
- MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx);
- SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx);
- }
+ PORT_Assert(!ss->ssl3.hs.sha_obj && !ss->ssl3.hs.sha_clone);
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+ /* If we ever support ciphersuites where the PRF hash isn't SHA-256
+ * then this will need to be updated. */
+ ss->ssl3.hs.sha_obj = HASH_GetRawHashObject(HASH_AlgSHA256);
+ if (!ss->ssl3.hs.sha_obj) {
+ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
+ return SECFailure;
+ }
+ ss->ssl3.hs.sha_clone = (void (*)(void *, void *))SHA256_Clone;
+ ss->ssl3.hs.hashType = handshake_hash_single;
+ ss->ssl3.hs.sha_obj->begin(ss->ssl3.hs.sha_cx);
+ } else {
+ ss->ssl3.hs.hashType = handshake_hash_combo;
+ MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx);
+ SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx);
+ }
} else
#endif
{
- PORT_Assert(!ss->ssl3.hs.md5 && !ss->ssl3.hs.sha);
- /*
- * note: We should probably lookup an SSL3 slot for these
- * handshake hashes in hopes that we wind up with the same slots
- * that the master secret will wind up in ...
- */
- if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
- /* If we ever support ciphersuites where the PRF hash isn't SHA-256
- * then this will need to be updated. */
- ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA256);
- if (ss->ssl3.hs.sha == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- return SECFailure;
- }
- ss->ssl3.hs.hashType = handshake_hash_single;
-
- if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
- return SECFailure;
- }
-
- /* Create a backup SHA-1 hash for a potential client auth
- * signature.
- *
- * In TLS 1.2, ssl3_ComputeHandshakeHashes always uses the
- * handshake hash function (SHA-256). If the server or the client
- * does not support SHA-256 as a signature hash, we can either
- * maintain a backup SHA-1 handshake hash or buffer all handshake
- * messages.
- */
- if (!ss->sec.isServer) {
- ss->ssl3.hs.backupHash = PK11_CreateDigestContext(SEC_OID_SHA1);
- if (ss->ssl3.hs.backupHash == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- return SECFailure;
- }
-
- if (PK11_DigestBegin(ss->ssl3.hs.backupHash) != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- return SECFailure;
- }
- }
- } else {
- /* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or
- * created successfully. */
- ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_MD5);
- if (ss->ssl3.hs.md5 == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
- return SECFailure;
- }
- ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA1);
- if (ss->ssl3.hs.sha == NULL) {
- PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
- ss->ssl3.hs.md5 = NULL;
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- return SECFailure;
- }
- ss->ssl3.hs.hashType = handshake_hash_combo;
-
- if (PK11_DigestBegin(ss->ssl3.hs.md5) != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
- return SECFailure;
- }
- if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- return SECFailure;
- }
- }
+ PORT_Assert(!ss->ssl3.hs.md5 && !ss->ssl3.hs.sha);
+ /*
+ * note: We should probably lookup an SSL3 slot for these
+ * handshake hashes in hopes that we wind up with the same slots
+ * that the master secret will wind up in ...
+ */
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+ /* If we ever support ciphersuites where the PRF hash isn't SHA-256
+ * then this will need to be updated. */
+ ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA256);
+ if (ss->ssl3.hs.sha == NULL) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ return SECFailure;
+ }
+ ss->ssl3.hs.hashType = handshake_hash_single;
+
+ if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
+ return SECFailure;
+ }
+
+ /* Create a backup SHA-1 hash for a potential client auth
+ * signature.
+ *
+ * In TLS 1.2, ssl3_ComputeHandshakeHashes always uses the
+ * handshake hash function (SHA-256). If the server or the client
+ * does not support SHA-256 as a signature hash, we can either
+ * maintain a backup SHA-1 handshake hash or buffer all handshake
+ * messages.
+ */
+ if (!ss->sec.isServer) {
+ ss->ssl3.hs.backupHash = PK11_CreateDigestContext(SEC_OID_SHA1);
+ if (ss->ssl3.hs.backupHash == NULL) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ return SECFailure;
+ }
+
+ if (PK11_DigestBegin(ss->ssl3.hs.backupHash) != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ return SECFailure;
+ }
+ }
+ } else {
+ /* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or
+ * created successfully. */
+ ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_MD5);
+ if (ss->ssl3.hs.md5 == NULL) {
+ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
+ return SECFailure;
+ }
+ ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA1);
+ if (ss->ssl3.hs.sha == NULL) {
+ PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
+ ss->ssl3.hs.md5 = NULL;
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ return SECFailure;
+ }
+ ss->ssl3.hs.hashType = handshake_hash_combo;
+
+ if (PK11_DigestBegin(ss->ssl3.hs.md5) != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
+ return SECFailure;
+ }
+ if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ return SECFailure;
+ }
+ }
}
if (ss->ssl3.hs.messages.len > 0) {
- if (ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.messages.buf,
- ss->ssl3.hs.messages.len) !=
- SECSuccess) {
- return SECFailure;
- }
- PORT_Free(ss->ssl3.hs.messages.buf);
- ss->ssl3.hs.messages.buf = NULL;
- ss->ssl3.hs.messages.len = 0;
- ss->ssl3.hs.messages.space = 0;
+ if (ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.messages.buf,
+ ss->ssl3.hs.messages.len) !=
+ SECSuccess) {
+ return SECFailure;
+ }
+ PORT_Free(ss->ssl3.hs.messages.buf);
+ ss->ssl3.hs.messages.buf = NULL;
+ ss->ssl3.hs.messages.len = 0;
+ ss->ssl3.hs.messages.space = 0;
}
return SECSuccess;
}
-static SECStatus
+static SECStatus
ssl3_RestartHandshakeHashes(sslSocket *ss)
{
SECStatus rv = SECSuccess;
- SSL_TRC(30,("%d: SSL3[%d]: reset handshake hashes",
- SSL_GETPID(), ss->fd ));
+ SSL_TRC(30, ("%d: SSL3[%d]: reset handshake hashes",
+ SSL_GETPID(), ss->fd));
ss->ssl3.hs.hashType = handshake_hash_unknown;
ss->ssl3.hs.messages.len = 0;
#ifndef NO_PKCS11_BYPASS
@@ -4289,12 +4364,12 @@ ssl3_RestartHandshakeHashes(sslSocket *ss)
ss->ssl3.hs.sha_clone = NULL;
#endif
if (ss->ssl3.hs.md5) {
- PK11_DestroyContext(ss->ssl3.hs.md5,PR_TRUE);
- ss->ssl3.hs.md5 = NULL;
+ PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
+ ss->ssl3.hs.md5 = NULL;
}
if (ss->ssl3.hs.sha) {
- PK11_DestroyContext(ss->ssl3.hs.sha,PR_TRUE);
- ss->ssl3.hs.sha = NULL;
+ PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE);
+ ss->ssl3.hs.sha = NULL;
}
return rv;
}
@@ -4302,64 +4377,64 @@ ssl3_RestartHandshakeHashes(sslSocket *ss)
/*
* Handshake messages
*/
-/* Called from ssl3_InitHandshakeHashes()
-** ssl3_AppendHandshake()
-** ssl3_StartHandshakeHash()
-** ssl3_HandleV2ClientHello()
-** ssl3_HandleHandshakeMessage()
+/* Called from ssl3_InitHandshakeHashes()
+** ssl3_AppendHandshake()
+** ssl3_StartHandshakeHash()
+** ssl3_HandleV2ClientHello()
+** ssl3_HandleHandshakeMessage()
** Caller must hold the ssl3Handshake lock.
*/
static SECStatus
ssl3_UpdateHandshakeHashes(sslSocket *ss, const unsigned char *b,
- unsigned int l)
+ unsigned int l)
{
- SECStatus rv = SECSuccess;
+ SECStatus rv = SECSuccess;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
/* We need to buffer the handshake messages until we have established
* which handshake hash function to use. */
if (ss->ssl3.hs.hashType == handshake_hash_unknown) {
- return sslBuffer_Append(&ss->ssl3.hs.messages, b, l);
+ return sslBuffer_Append(&ss->ssl3.hs.messages, b, l);
}
PRINT_BUF(90, (NULL, "handshake hash input:", b, l));
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11) {
- if (ss->ssl3.hs.hashType == handshake_hash_single) {
- ss->ssl3.hs.sha_obj->update(ss->ssl3.hs.sha_cx, b, l);
- } else {
- MD5_Update((MD5Context *)ss->ssl3.hs.md5_cx, b, l);
- SHA1_Update((SHA1Context *)ss->ssl3.hs.sha_cx, b, l);
- }
- return rv;
+ if (ss->ssl3.hs.hashType == handshake_hash_single) {
+ ss->ssl3.hs.sha_obj->update(ss->ssl3.hs.sha_cx, b, l);
+ } else {
+ MD5_Update((MD5Context *)ss->ssl3.hs.md5_cx, b, l);
+ SHA1_Update((SHA1Context *)ss->ssl3.hs.sha_cx, b, l);
+ }
+ return rv;
}
#endif
if (ss->ssl3.hs.hashType == handshake_hash_single) {
- rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
- return rv;
- }
- if (ss->ssl3.hs.backupHash) {
- rv = PK11_DigestOp(ss->ssl3.hs.backupHash, b, l);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- return rv;
- }
- }
+ rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
+ return rv;
+ }
+ if (ss->ssl3.hs.backupHash) {
+ rv = PK11_DigestOp(ss->ssl3.hs.backupHash, b, l);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ return rv;
+ }
+ }
} else {
- rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
- return rv;
- }
- rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- return rv;
- }
+ rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
+ return rv;
+ }
+ rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ return rv;
+ }
}
return rv;
}
@@ -4372,40 +4447,40 @@ ssl3_UpdateHandshakeHashes(sslSocket *ss, const unsigned char *b,
SECStatus
ssl3_AppendHandshake(sslSocket *ss, const void *void_src, PRInt32 bytes)
{
- unsigned char * src = (unsigned char *)void_src;
- int room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len;
- SECStatus rv;
+ unsigned char *src = (unsigned char *)void_src;
+ int room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len;
+ SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); /* protects sendBuf. */
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); /* protects sendBuf. */
if (!bytes)
- return SECSuccess;
+ return SECSuccess;
if (ss->sec.ci.sendBuf.space < MAX_SEND_BUF_LENGTH && room < bytes) {
- rv = sslBuffer_Grow(&ss->sec.ci.sendBuf, PR_MAX(MIN_SEND_BUF_LENGTH,
- PR_MIN(MAX_SEND_BUF_LENGTH, ss->sec.ci.sendBuf.len + bytes)));
- if (rv != SECSuccess)
- return rv; /* sslBuffer_Grow has set a memory error code. */
- room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len;
+ rv = sslBuffer_Grow(&ss->sec.ci.sendBuf, PR_MAX(MIN_SEND_BUF_LENGTH,
+ PR_MIN(MAX_SEND_BUF_LENGTH, ss->sec.ci.sendBuf.len + bytes)));
+ if (rv != SECSuccess)
+ return rv; /* sslBuffer_Grow has set a memory error code. */
+ room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len;
}
- PRINT_BUF(60, (ss, "Append to Handshake", (unsigned char*)void_src, bytes));
+ PRINT_BUF(60, (ss, "Append to Handshake", (unsigned char *)void_src, bytes));
rv = ssl3_UpdateHandshakeHashes(ss, src, bytes);
if (rv != SECSuccess)
- return rv; /* error code set by ssl3_UpdateHandshakeHashes */
+ return rv; /* error code set by ssl3_UpdateHandshakeHashes */
while (bytes > room) {
- if (room > 0)
- PORT_Memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, src,
- room);
- ss->sec.ci.sendBuf.len += room;
- rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
- if (rv != SECSuccess) {
- return rv; /* error code set by ssl3_FlushHandshake */
- }
- bytes -= room;
- src += room;
- room = ss->sec.ci.sendBuf.space;
- PORT_Assert(ss->sec.ci.sendBuf.len == 0);
+ if (room > 0)
+ PORT_Memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, src,
+ room);
+ ss->sec.ci.sendBuf.len += room;
+ rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
+ if (rv != SECSuccess) {
+ return rv; /* error code set by ssl3_FlushHandshake */
+ }
+ bytes -= room;
+ src += room;
+ room = ss->sec.ci.sendBuf.space;
+ PORT_Assert(ss->sec.ci.sendBuf.len == 0);
}
PORT_Memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, src, bytes);
ss->sec.ci.sendBuf.len += bytes;
@@ -4416,8 +4491,8 @@ SECStatus
ssl3_AppendHandshakeNumber(sslSocket *ss, PRInt32 num, PRInt32 lenSize)
{
SECStatus rv;
- PRUint8 b[4];
- PRUint8 * p = b;
+ PRUint8 b[4];
+ PRUint8 *p = b;
PORT_Assert(lenSize <= 4 && lenSize > 0);
if (lenSize < 4 && num >= (1L << (lenSize * 8))) {
@@ -4426,18 +4501,18 @@ ssl3_AppendHandshakeNumber(sslSocket *ss, PRInt32 num, PRInt32 lenSize)
}
switch (lenSize) {
- case 4:
- *p++ = (num >> 24) & 0xff;
- case 3:
- *p++ = (num >> 16) & 0xff;
- case 2:
- *p++ = (num >> 8) & 0xff;
- case 1:
- *p = num & 0xff;
+ case 4:
+ *p++ = (num >> 24) & 0xff;
+ case 3:
+ *p++ = (num >> 16) & 0xff;
+ case 2:
+ *p++ = (num >> 8) & 0xff;
+ case 1:
+ *p = num & 0xff;
}
SSL_TRC(60, ("%d: number:", SSL_GETPID()));
rv = ssl3_AppendHandshake(ss, &b[0], lenSize);
- return rv; /* error code set by AppendHandshake, if applicable. */
+ return rv; /* error code set by AppendHandshake, if applicable. */
}
SECStatus
@@ -4446,18 +4521,18 @@ ssl3_AppendHandshakeVariable(
{
SECStatus rv;
- PORT_Assert((bytes < (1<<8) && lenSize == 1) ||
- (bytes < (1L<<16) && lenSize == 2) ||
- (bytes < (1L<<24) && lenSize == 3));
+ PORT_Assert((bytes < (1 << 8) && lenSize == 1) ||
+ (bytes < (1L << 16) && lenSize == 2) ||
+ (bytes < (1L << 24) && lenSize == 3));
- SSL_TRC(60,("%d: append variable:", SSL_GETPID()));
+ SSL_TRC(60, ("%d: append variable:", SSL_GETPID()));
rv = ssl3_AppendHandshakeNumber(ss, bytes, lenSize);
if (rv != SECSuccess) {
- return rv; /* error code set by AppendHandshake, if applicable. */
+ return rv; /* error code set by AppendHandshake, if applicable. */
}
SSL_TRC(60, ("data:"));
rv = ssl3_AppendHandshake(ss, src, bytes);
- return rv; /* error code set by AppendHandshake, if applicable. */
+ return rv; /* error code set by AppendHandshake, if applicable. */
}
SECStatus
@@ -4470,54 +4545,54 @@ ssl3_AppendHandshakeHeader(sslSocket *ss, SSL3HandshakeType t, PRUint32 length)
* dtls_StageHandshakeMessage to mark the message boundary.
*/
if (IS_DTLS(ss)) {
- rv = dtls_StageHandshakeMessage(ss);
- if (rv != SECSuccess) {
- return rv;
- }
+ rv = dtls_StageHandshakeMessage(ss);
+ if (rv != SECSuccess) {
+ return rv;
+ }
}
- SSL_TRC(30,("%d: SSL3[%d]: append handshake header: type %s",
- SSL_GETPID(), ss->fd, ssl3_DecodeHandshakeType(t)));
+ SSL_TRC(30, ("%d: SSL3[%d]: append handshake header: type %s",
+ SSL_GETPID(), ss->fd, ssl3_DecodeHandshakeType(t)));
rv = ssl3_AppendHandshakeNumber(ss, t, 1);
if (rv != SECSuccess) {
- return rv; /* error code set by AppendHandshake, if applicable. */
+ return rv; /* error code set by AppendHandshake, if applicable. */
}
rv = ssl3_AppendHandshakeNumber(ss, length, 3);
if (rv != SECSuccess) {
- return rv; /* error code set by AppendHandshake, if applicable. */
+ return rv; /* error code set by AppendHandshake, if applicable. */
}
if (IS_DTLS(ss)) {
- /* Note that we make an unfragmented message here. We fragment in the
- * transmission code, if necessary */
- rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.sendMessageSeq, 2);
- if (rv != SECSuccess) {
- return rv; /* error code set by AppendHandshake, if applicable. */
- }
- ss->ssl3.hs.sendMessageSeq++;
+ /* Note that we make an unfragmented message here. We fragment in the
+ * transmission code, if necessary */
+ rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.sendMessageSeq, 2);
+ if (rv != SECSuccess) {
+ return rv; /* error code set by AppendHandshake, if applicable. */
+ }
+ ss->ssl3.hs.sendMessageSeq++;
- /* 0 is the fragment offset, because it's not fragmented yet */
- rv = ssl3_AppendHandshakeNumber(ss, 0, 3);
- if (rv != SECSuccess) {
- return rv; /* error code set by AppendHandshake, if applicable. */
- }
+ /* 0 is the fragment offset, because it's not fragmented yet */
+ rv = ssl3_AppendHandshakeNumber(ss, 0, 3);
+ if (rv != SECSuccess) {
+ return rv; /* error code set by AppendHandshake, if applicable. */
+ }
- /* Fragment length -- set to the packet length because not fragmented */
- rv = ssl3_AppendHandshakeNumber(ss, length, 3);
- if (rv != SECSuccess) {
- return rv; /* error code set by AppendHandshake, if applicable. */
- }
+ /* Fragment length -- set to the packet length because not fragmented */
+ rv = ssl3_AppendHandshakeNumber(ss, length, 3);
+ if (rv != SECSuccess) {
+ return rv; /* error code set by AppendHandshake, if applicable. */
+ }
}
- return rv; /* error code set by AppendHandshake, if applicable. */
+ return rv; /* error code set by AppendHandshake, if applicable. */
}
/* ssl3_AppendSignatureAndHashAlgorithm appends the serialisation of
* |sigAndHash| to the current handshake message. */
SECStatus
ssl3_AppendSignatureAndHashAlgorithm(
- sslSocket *ss, const SSLSignatureAndHashAlg* sigAndHash)
+ sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash)
{
PRUint8 serialized[2];
@@ -4544,17 +4619,17 @@ ssl3_AppendSignatureAndHashAlgorithm(
*/
SECStatus
ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes, SSL3Opaque **b,
- PRUint32 *length)
+ PRUint32 *length)
{
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if ((PRUint32)bytes > *length) {
- return ssl3_DecodeError(ss);
+ return ssl3_DecodeError(ss);
}
PORT_Memcpy(v, *b, bytes);
PRINT_BUF(60, (ss, "consume bytes:", *b, bytes));
- *b += bytes;
+ *b += bytes;
*length -= bytes;
return SECSuccess;
}
@@ -4572,24 +4647,24 @@ ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes, SSL3Opaque **b,
*/
PRInt32
ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRInt32 bytes, SSL3Opaque **b,
- PRUint32 *length)
+ PRUint32 *length)
{
- PRUint8 *buf = *b;
- int i;
- PRInt32 num = 0;
+ PRUint8 *buf = *b;
+ int i;
+ PRInt32 num = 0;
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( bytes <= sizeof num);
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(bytes <= sizeof num);
if ((PRUint32)bytes > *length) {
- return ssl3_DecodeError(ss);
+ return ssl3_DecodeError(ss);
}
PRINT_BUF(60, (ss, "consume bytes:", *b, bytes));
for (i = 0; i < bytes; i++)
- num = (num << 8) + buf[i];
- *b += bytes;
+ num = (num << 8) + buf[i];
+ *b += bytes;
*length -= bytes;
return num;
}
@@ -4603,33 +4678,33 @@ ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRInt32 bytes, SSL3Opaque **b,
* Returns SECFailure (-1) on failure.
* On error, an alert has been sent, and a generic error code has been set.
*
- * RADICAL CHANGE for NSS 3.11. All callers of this function make copies
+ * RADICAL CHANGE for NSS 3.11. All callers of this function make copies
* of the data returned in the SECItem *i, so making a copy of it here
- * is simply wasteful. So, This function now just sets SECItem *i to
+ * is simply wasteful. So, This function now just sets SECItem *i to
* point to the values in the buffer **b.
*/
SECStatus
ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRInt32 bytes,
- SSL3Opaque **b, PRUint32 *length)
+ SSL3Opaque **b, PRUint32 *length)
{
- PRInt32 count;
+ PRInt32 count;
PORT_Assert(bytes <= 3);
- i->len = 0;
+ i->len = 0;
i->data = NULL;
i->type = siBuffer;
count = ssl3_ConsumeHandshakeNumber(ss, bytes, b, length);
- if (count < 0) { /* Can't test for SECSuccess here. */
- return SECFailure;
+ if (count < 0) { /* Can't test for SECSuccess here. */
+ return SECFailure;
}
if (count > 0) {
- if ((PRUint32)count > *length) {
- return ssl3_DecodeError(ss);
- }
- i->data = *b;
- i->len = count;
- *b += count;
- *length -= count;
+ if ((PRUint32)count > *length) {
+ return ssl3_DecodeError(ss);
+ }
+ i->data = *b;
+ i->len = count;
+ *b += count;
+ *length -= count;
}
return SECSuccess;
}
@@ -4656,9 +4731,9 @@ ssl3_TLSHashAlgorithmToOID(SSLHashType hashFunc)
unsigned int i;
for (i = 0; i < PR_ARRAY_SIZE(tlsHashOIDMap); i++) {
- if (hashFunc == tlsHashOIDMap[i].tlsHash) {
- return tlsHashOIDMap[i].oid;
- }
+ if (hashFunc == tlsHashOIDMap[i].tlsHash) {
+ return tlsHashOIDMap[i].oid;
+ }
}
return SEC_OID_UNKNOWN;
}
@@ -4669,18 +4744,18 @@ static SECStatus
ssl3_TLSSignatureAlgorithmForKeyType(KeyType keyType, SSLSignType *out)
{
switch (keyType) {
- case rsaKey:
- *out = ssl_sign_rsa;
- return SECSuccess;
- case dsaKey:
- *out = ssl_sign_dsa;
- return SECSuccess;
- case ecKey:
- *out = ssl_sign_ecdsa;
- return SECSuccess;
- default:
- PORT_SetError(SEC_ERROR_INVALID_KEY);
- return SECFailure;
+ case rsaKey:
+ *out = ssl_sign_rsa;
+ return SECSuccess;
+ case dsaKey:
+ *out = ssl_sign_dsa;
+ return SECSuccess;
+ case ecKey:
+ *out = ssl_sign_ecdsa;
+ return SECSuccess;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ return SECFailure;
}
}
@@ -4712,12 +4787,22 @@ ssl3_TLSSignatureAlgorithmForCertificate(CERTCertificate *cert,
SECStatus
ssl3_CheckSignatureAndHashAlgorithmConsistency(
sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash,
- CERTCertificate* cert)
+ CERTCertificate *cert)
{
SECStatus rv;
SSLSignType sigAlg;
unsigned int i;
+ /* If we're a client, check that the signature algorithm matches the signing
+ * key type of the cipher suite. */
+ if (!ss->sec.isServer &&
+ ss->ssl3.hs.kea_def->signKeyType != sigAndHash->sigAlg) {
+ PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
+ return SECFailure;
+ }
+
+ /* Verify that the signature algorithm used for the
+ * signature matches the signing key. */
rv = ssl3_TLSSignatureAlgorithmForCertificate(cert, &sigAlg);
if (rv != SECSuccess) {
return rv;
@@ -4816,21 +4901,21 @@ ssl3_ConsumeSignatureAndHashAlgorithm(sslSocket *ss,
*
* Caller must hold the SSL3HandshakeLock.
* Caller must hold a read or write lock on the Spec R/W lock.
- * (There is presently no way to assert on a Read lock.)
+ * (There is presently no way to assert on a Read lock.)
*/
-static SECStatus
-ssl3_ComputeHandshakeHashes(sslSocket * ss,
- ssl3CipherSpec *spec, /* uses ->master_secret */
- SSL3Hashes * hashes, /* output goes here. */
- PRUint32 sender)
-{
- SECStatus rv = SECSuccess;
- PRBool isTLS = (PRBool)(spec->version > SSL_LIBRARY_VERSION_3_0);
- unsigned int outLength;
- SSL3Opaque md5_inner[MAX_MAC_LENGTH];
- SSL3Opaque sha_inner[MAX_MAC_LENGTH];
-
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+SECStatus
+ssl3_ComputeHandshakeHashes(sslSocket *ss,
+ ssl3CipherSpec *spec, /* uses ->master_secret */
+ SSL3Hashes *hashes, /* output goes here. */
+ PRUint32 sender)
+{
+ SECStatus rv = SECSuccess;
+ PRBool isTLS = (PRBool)(spec->version > SSL_LIBRARY_VERSION_3_0);
+ unsigned int outLength;
+ SSL3Opaque md5_inner[MAX_MAC_LENGTH];
+ SSL3Opaque sha_inner[MAX_MAC_LENGTH];
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ss->ssl3.hs.hashType == handshake_hash_unknown) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
@@ -4840,306 +4925,305 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss,
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11 &&
- ss->ssl3.hs.hashType == handshake_hash_single) {
- /* compute them without PKCS11 */
- PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS];
+ ss->ssl3.hs.hashType == handshake_hash_single) {
+ /* compute them without PKCS11 */
+ PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS];
- ss->ssl3.hs.sha_clone(sha_cx, ss->ssl3.hs.sha_cx);
- ss->ssl3.hs.sha_obj->end(sha_cx, hashes->u.raw, &hashes->len,
- sizeof(hashes->u.raw));
+ ss->ssl3.hs.sha_clone(sha_cx, ss->ssl3.hs.sha_cx);
+ ss->ssl3.hs.sha_obj->end(sha_cx, hashes->u.raw, &hashes->len,
+ sizeof(hashes->u.raw));
- PRINT_BUF(60, (NULL, "SHA-256: result", hashes->u.raw, hashes->len));
+ PRINT_BUF(60, (NULL, "SHA-256: result", hashes->u.raw, hashes->len));
- /* If we ever support ciphersuites where the PRF hash isn't SHA-256
- * then this will need to be updated. */
- hashes->hashAlg = ssl_hash_sha256;
- rv = SECSuccess;
+ /* If we ever support ciphersuites where the PRF hash isn't SHA-256
+ * then this will need to be updated. */
+ hashes->hashAlg = ssl_hash_sha256;
+ rv = SECSuccess;
} else if (ss->opt.bypassPKCS11) {
- /* compute them without PKCS11 */
- PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS];
- PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS];
+ /* compute them without PKCS11 */
+ PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS];
+ PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS];
#define md5cx ((MD5Context *)md5_cx)
#define shacx ((SHA1Context *)sha_cx)
- MD5_Clone (md5cx, (MD5Context *)ss->ssl3.hs.md5_cx);
- SHA1_Clone(shacx, (SHA1Context *)ss->ssl3.hs.sha_cx);
+ MD5_Clone(md5cx, (MD5Context *)ss->ssl3.hs.md5_cx);
+ SHA1_Clone(shacx, (SHA1Context *)ss->ssl3.hs.sha_cx);
- if (!isTLS) {
- /* compute hashes for SSL3. */
- unsigned char s[4];
+ if (!isTLS) {
+ /* compute hashes for SSL3. */
+ unsigned char s[4];
if (!spec->msItem.data) {
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
return SECFailure;
}
- s[0] = (unsigned char)(sender >> 24);
- s[1] = (unsigned char)(sender >> 16);
- s[2] = (unsigned char)(sender >> 8);
- s[3] = (unsigned char)sender;
+ s[0] = (unsigned char)(sender >> 24);
+ s[1] = (unsigned char)(sender >> 16);
+ s[2] = (unsigned char)(sender >> 8);
+ s[3] = (unsigned char)sender;
- if (sender != 0) {
- MD5_Update(md5cx, s, 4);
- PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4));
- }
+ if (sender != 0) {
+ MD5_Update(md5cx, s, 4);
+ PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4));
+ }
- PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1,
- mac_defs[mac_md5].pad_size));
+ PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1,
+ mac_defs[mac_md5].pad_size));
- MD5_Update(md5cx, spec->msItem.data, spec->msItem.len);
- MD5_Update(md5cx, mac_pad_1, mac_defs[mac_md5].pad_size);
- MD5_End(md5cx, md5_inner, &outLength, MD5_LENGTH);
+ MD5_Update(md5cx, spec->msItem.data, spec->msItem.len);
+ MD5_Update(md5cx, mac_pad_1, mac_defs[mac_md5].pad_size);
+ MD5_End(md5cx, md5_inner, &outLength, MD5_LENGTH);
- PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength));
+ PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength));
- if (sender != 0) {
- SHA1_Update(shacx, s, 4);
- PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4));
- }
+ if (sender != 0) {
+ SHA1_Update(shacx, s, 4);
+ PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4));
+ }
- PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1,
- mac_defs[mac_sha].pad_size));
+ PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1,
+ mac_defs[mac_sha].pad_size));
- SHA1_Update(shacx, spec->msItem.data, spec->msItem.len);
- SHA1_Update(shacx, mac_pad_1, mac_defs[mac_sha].pad_size);
- SHA1_End(shacx, sha_inner, &outLength, SHA1_LENGTH);
+ SHA1_Update(shacx, spec->msItem.data, spec->msItem.len);
+ SHA1_Update(shacx, mac_pad_1, mac_defs[mac_sha].pad_size);
+ SHA1_End(shacx, sha_inner, &outLength, SHA1_LENGTH);
- PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength));
- PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2,
- mac_defs[mac_md5].pad_size));
- PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH));
+ PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength));
+ PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2,
+ mac_defs[mac_md5].pad_size));
+ PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH));
- MD5_Begin(md5cx);
- MD5_Update(md5cx, spec->msItem.data, spec->msItem.len);
- MD5_Update(md5cx, mac_pad_2, mac_defs[mac_md5].pad_size);
- MD5_Update(md5cx, md5_inner, MD5_LENGTH);
- }
- MD5_End(md5cx, hashes->u.s.md5, &outLength, MD5_LENGTH);
+ MD5_Begin(md5cx);
+ MD5_Update(md5cx, spec->msItem.data, spec->msItem.len);
+ MD5_Update(md5cx, mac_pad_2, mac_defs[mac_md5].pad_size);
+ MD5_Update(md5cx, md5_inner, MD5_LENGTH);
+ }
+ MD5_End(md5cx, hashes->u.s.md5, &outLength, MD5_LENGTH);
- PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->u.s.md5, MD5_LENGTH));
+ PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->u.s.md5, MD5_LENGTH));
- if (!isTLS) {
- PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2,
- mac_defs[mac_sha].pad_size));
- PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH));
+ if (!isTLS) {
+ PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2,
+ mac_defs[mac_sha].pad_size));
+ PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH));
- SHA1_Begin(shacx);
- SHA1_Update(shacx, spec->msItem.data, spec->msItem.len);
- SHA1_Update(shacx, mac_pad_2, mac_defs[mac_sha].pad_size);
- SHA1_Update(shacx, sha_inner, SHA1_LENGTH);
- }
- SHA1_End(shacx, hashes->u.s.sha, &outLength, SHA1_LENGTH);
+ SHA1_Begin(shacx);
+ SHA1_Update(shacx, spec->msItem.data, spec->msItem.len);
+ SHA1_Update(shacx, mac_pad_2, mac_defs[mac_sha].pad_size);
+ SHA1_Update(shacx, sha_inner, SHA1_LENGTH);
+ }
+ SHA1_End(shacx, hashes->u.s.sha, &outLength, SHA1_LENGTH);
- PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH));
+ PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH));
- hashes->len = MD5_LENGTH + SHA1_LENGTH;
- rv = SECSuccess;
+ hashes->len = MD5_LENGTH + SHA1_LENGTH;
+ rv = SECSuccess;
#undef md5cx
#undef shacx
- } else
+ } else
#endif
- if (ss->ssl3.hs.hashType == handshake_hash_single) {
- /* compute hashes with PKCS11 */
- PK11Context *h;
- unsigned int stateLen;
- unsigned char stackBuf[1024];
- unsigned char *stateBuf = NULL;
-
- h = ss->ssl3.hs.sha;
- stateBuf = PK11_SaveContextAlloc(h, stackBuf,
- sizeof(stackBuf), &stateLen);
- if (stateBuf == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
- goto tls12_loser;
- }
- rv |= PK11_DigestFinal(h, hashes->u.raw, &hashes->len,
- sizeof(hashes->u.raw));
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
- rv = SECFailure;
- goto tls12_loser;
- }
- /* If we ever support ciphersuites where the PRF hash isn't SHA-256
- * then this will need to be updated. */
- hashes->hashAlg = ssl_hash_sha256;
- rv = SECSuccess;
-
-tls12_loser:
- if (stateBuf) {
- if (PK11_RestoreContext(h, stateBuf, stateLen) != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
- rv = SECFailure;
- }
- if (stateBuf != stackBuf) {
- PORT_ZFree(stateBuf, stateLen);
- }
- }
+ if (ss->ssl3.hs.hashType == handshake_hash_single) {
+ /* compute hashes with PKCS11 */
+ PK11Context *h;
+ unsigned int stateLen;
+ unsigned char stackBuf[1024];
+ unsigned char *stateBuf = NULL;
+
+ h = ss->ssl3.hs.sha;
+ stateBuf = PK11_SaveContextAlloc(h, stackBuf,
+ sizeof(stackBuf), &stateLen);
+ if (stateBuf == NULL) {
+ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
+ goto tls12_loser;
+ }
+ rv |= PK11_DigestFinal(h, hashes->u.raw, &hashes->len,
+ sizeof(hashes->u.raw));
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
+ rv = SECFailure;
+ goto tls12_loser;
+ }
+ /* If we ever support ciphersuites where the PRF hash isn't SHA-256
+ * then this will need to be updated. */
+ hashes->hashAlg = ssl_hash_sha256;
+ rv = SECSuccess;
+
+ tls12_loser:
+ if (stateBuf) {
+ if (PK11_RestoreContext(h, stateBuf, stateLen) != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
+ rv = SECFailure;
+ }
+ if (stateBuf != stackBuf) {
+ PORT_ZFree(stateBuf, stateLen);
+ }
+ }
} else {
- /* compute hashes with PKCS11 */
- PK11Context * md5;
- PK11Context * sha = NULL;
- unsigned char *md5StateBuf = NULL;
- unsigned char *shaStateBuf = NULL;
- unsigned int md5StateLen, shaStateLen;
- unsigned char md5StackBuf[256];
- unsigned char shaStackBuf[512];
-
- md5StateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.md5, md5StackBuf,
- sizeof md5StackBuf, &md5StateLen);
- if (md5StateBuf == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
- goto loser;
- }
- md5 = ss->ssl3.hs.md5;
-
- shaStateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.sha, shaStackBuf,
- sizeof shaStackBuf, &shaStateLen);
- if (shaStateBuf == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- goto loser;
- }
- sha = ss->ssl3.hs.sha;
-
- if (!isTLS) {
- /* compute hashes for SSL3. */
- unsigned char s[4];
+ /* compute hashes with PKCS11 */
+ PK11Context *md5;
+ PK11Context *sha = NULL;
+ unsigned char *md5StateBuf = NULL;
+ unsigned char *shaStateBuf = NULL;
+ unsigned int md5StateLen, shaStateLen;
+ unsigned char md5StackBuf[256];
+ unsigned char shaStackBuf[512];
+
+ md5StateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.md5, md5StackBuf,
+ sizeof md5StackBuf, &md5StateLen);
+ if (md5StateBuf == NULL) {
+ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
+ goto loser;
+ }
+ md5 = ss->ssl3.hs.md5;
+
+ shaStateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.sha, shaStackBuf,
+ sizeof shaStackBuf, &shaStateLen);
+ if (shaStateBuf == NULL) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ goto loser;
+ }
+ sha = ss->ssl3.hs.sha;
+
+ if (!isTLS) {
+ /* compute hashes for SSL3. */
+ unsigned char s[4];
if (!spec->master_secret) {
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
- return SECFailure;
+ rv = SECFailure;
+ goto loser;
+ }
+
+ s[0] = (unsigned char)(sender >> 24);
+ s[1] = (unsigned char)(sender >> 16);
+ s[2] = (unsigned char)(sender >> 8);
+ s[3] = (unsigned char)sender;
+
+ if (sender != 0) {
+ rv |= PK11_DigestOp(md5, s, 4);
+ PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4));
+ }
+
+ PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1,
+ mac_defs[mac_md5].pad_size));
+
+ rv |= PK11_DigestKey(md5, spec->master_secret);
+ rv |= PK11_DigestOp(md5, mac_pad_1, mac_defs[mac_md5].pad_size);
+ rv |= PK11_DigestFinal(md5, md5_inner, &outLength, MD5_LENGTH);
+ PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
+ rv = SECFailure;
+ goto loser;
}
- s[0] = (unsigned char)(sender >> 24);
- s[1] = (unsigned char)(sender >> 16);
- s[2] = (unsigned char)(sender >> 8);
- s[3] = (unsigned char)sender;
-
- if (sender != 0) {
- rv |= PK11_DigestOp(md5, s, 4);
- PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4));
- }
-
- PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1,
- mac_defs[mac_md5].pad_size));
-
- rv |= PK11_DigestKey(md5,spec->master_secret);
- rv |= PK11_DigestOp(md5, mac_pad_1, mac_defs[mac_md5].pad_size);
- rv |= PK11_DigestFinal(md5, md5_inner, &outLength, MD5_LENGTH);
- PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
- rv = SECFailure;
- goto loser;
- }
-
- PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength));
-
- if (sender != 0) {
- rv |= PK11_DigestOp(sha, s, 4);
- PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4));
- }
-
- PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1,
- mac_defs[mac_sha].pad_size));
-
- rv |= PK11_DigestKey(sha, spec->master_secret);
- rv |= PK11_DigestOp(sha, mac_pad_1, mac_defs[mac_sha].pad_size);
- rv |= PK11_DigestFinal(sha, sha_inner, &outLength, SHA1_LENGTH);
- PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- rv = SECFailure;
- goto loser;
- }
-
- PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength));
-
- PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2,
- mac_defs[mac_md5].pad_size));
- PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH));
-
- rv |= PK11_DigestBegin(md5);
- rv |= PK11_DigestKey(md5, spec->master_secret);
- rv |= PK11_DigestOp(md5, mac_pad_2, mac_defs[mac_md5].pad_size);
- rv |= PK11_DigestOp(md5, md5_inner, MD5_LENGTH);
- }
- rv |= PK11_DigestFinal(md5, hashes->u.s.md5, &outLength, MD5_LENGTH);
- PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
- rv = SECFailure;
- goto loser;
- }
-
- PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->u.s.md5, MD5_LENGTH));
-
- if (!isTLS) {
- PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2,
- mac_defs[mac_sha].pad_size));
- PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH));
-
- rv |= PK11_DigestBegin(sha);
- rv |= PK11_DigestKey(sha,spec->master_secret);
- rv |= PK11_DigestOp(sha, mac_pad_2, mac_defs[mac_sha].pad_size);
- rv |= PK11_DigestOp(sha, sha_inner, SHA1_LENGTH);
- }
- rv |= PK11_DigestFinal(sha, hashes->u.s.sha, &outLength, SHA1_LENGTH);
- PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- rv = SECFailure;
- goto loser;
- }
-
- PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH));
-
- hashes->len = MD5_LENGTH + SHA1_LENGTH;
- rv = SECSuccess;
+ PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength));
+
+ if (sender != 0) {
+ rv |= PK11_DigestOp(sha, s, 4);
+ PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4));
+ }
+
+ PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1,
+ mac_defs[mac_sha].pad_size));
+
+ rv |= PK11_DigestKey(sha, spec->master_secret);
+ rv |= PK11_DigestOp(sha, mac_pad_1, mac_defs[mac_sha].pad_size);
+ rv |= PK11_DigestFinal(sha, sha_inner, &outLength, SHA1_LENGTH);
+ PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ rv = SECFailure;
+ goto loser;
+ }
+
+ PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength));
+
+ PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2,
+ mac_defs[mac_md5].pad_size));
+ PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH));
+
+ rv |= PK11_DigestBegin(md5);
+ rv |= PK11_DigestKey(md5, spec->master_secret);
+ rv |= PK11_DigestOp(md5, mac_pad_2, mac_defs[mac_md5].pad_size);
+ rv |= PK11_DigestOp(md5, md5_inner, MD5_LENGTH);
+ }
+ rv |= PK11_DigestFinal(md5, hashes->u.s.md5, &outLength, MD5_LENGTH);
+ PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
+ rv = SECFailure;
+ goto loser;
+ }
+
+ PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->u.s.md5, MD5_LENGTH));
+
+ if (!isTLS) {
+ PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2,
+ mac_defs[mac_sha].pad_size));
+ PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH));
+
+ rv |= PK11_DigestBegin(sha);
+ rv |= PK11_DigestKey(sha, spec->master_secret);
+ rv |= PK11_DigestOp(sha, mac_pad_2, mac_defs[mac_sha].pad_size);
+ rv |= PK11_DigestOp(sha, sha_inner, SHA1_LENGTH);
+ }
+ rv |= PK11_DigestFinal(sha, hashes->u.s.sha, &outLength, SHA1_LENGTH);
+ PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ rv = SECFailure;
+ goto loser;
+ }
+
+ PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH));
+
+ hashes->len = MD5_LENGTH + SHA1_LENGTH;
+ rv = SECSuccess;
loser:
- if (md5StateBuf) {
- if (PK11_RestoreContext(ss->ssl3.hs.md5, md5StateBuf, md5StateLen)
- != SECSuccess)
- {
- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
- rv = SECFailure;
- }
- if (md5StateBuf != md5StackBuf) {
- PORT_ZFree(md5StateBuf, md5StateLen);
- }
- }
- if (shaStateBuf) {
- if (PK11_RestoreContext(ss->ssl3.hs.sha, shaStateBuf, shaStateLen)
- != SECSuccess)
- {
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- rv = SECFailure;
- }
- if (shaStateBuf != shaStackBuf) {
- PORT_ZFree(shaStateBuf, shaStateLen);
- }
- }
+ if (md5StateBuf) {
+ if (PK11_RestoreContext(ss->ssl3.hs.md5, md5StateBuf, md5StateLen) !=
+ SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
+ rv = SECFailure;
+ }
+ if (md5StateBuf != md5StackBuf) {
+ PORT_ZFree(md5StateBuf, md5StateLen);
+ }
+ }
+ if (shaStateBuf) {
+ if (PK11_RestoreContext(ss->ssl3.hs.sha, shaStateBuf, shaStateLen) !=
+ SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ rv = SECFailure;
+ }
+ if (shaStateBuf != shaStackBuf) {
+ PORT_ZFree(shaStateBuf, shaStateLen);
+ }
+ }
}
return rv;
}
static SECStatus
-ssl3_ComputeBackupHandshakeHashes(sslSocket * ss,
- SSL3Hashes * hashes) /* output goes here. */
+ssl3_ComputeBackupHandshakeHashes(sslSocket *ss,
+ SSL3Hashes *hashes) /* output goes here. */
{
SECStatus rv = SECSuccess;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( !ss->sec.isServer );
- PORT_Assert( ss->ssl3.hs.hashType == handshake_hash_single );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(!ss->sec.isServer);
+ PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_single);
rv = PK11_DigestFinal(ss->ssl3.hs.backupHash, hashes->u.raw, &hashes->len,
- sizeof(hashes->u.raw));
+ sizeof(hashes->u.raw));
if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
- rv = SECFailure;
- goto loser;
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ rv = SECFailure;
+ goto loser;
}
hashes->hashAlg = ssl_hash_sha1;
@@ -5156,32 +5240,32 @@ loser:
* Called from ssl2_BeginClientHandshake() in sslcon.c
*/
SECStatus
-ssl3_StartHandshakeHash(sslSocket *ss, unsigned char * buf, int length)
+ssl3_StartHandshakeHash(sslSocket *ss, unsigned char *buf, int length)
{
SECStatus rv;
- ssl_GetSSL3HandshakeLock(ss); /**************************************/
+ ssl_GetSSL3HandshakeLock(ss); /**************************************/
rv = ssl3_InitState(ss);
if (rv != SECSuccess) {
- goto done; /* ssl3_InitState has set the error code. */
+ goto done; /* ssl3_InitState has set the error code. */
}
rv = ssl3_RestartHandshakeHashes(ss);
if (rv != SECSuccess) {
- goto done;
+ goto done;
}
PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH);
PORT_Memcpy(
- &ss->ssl3.hs.client_random.rand[SSL3_RANDOM_LENGTH - SSL_CHALLENGE_BYTES],
- &ss->sec.ci.clientChallenge,
- SSL_CHALLENGE_BYTES);
+ &ss->ssl3.hs.client_random.rand[SSL3_RANDOM_LENGTH - SSL_CHALLENGE_BYTES],
+ &ss->sec.ci.clientChallenge,
+ SSL_CHALLENGE_BYTES);
rv = ssl3_UpdateHandshakeHashes(ss, buf, length);
/* if it failed, ssl3_UpdateHandshakeHashes has set the error code. */
done:
- ssl_ReleaseSSL3HandshakeLock(ss); /**************************************/
+ ssl_ReleaseSSL3HandshakeLock(ss); /**************************************/
return rv;
}
@@ -5198,29 +5282,29 @@ done:
SECStatus
ssl3_SendClientHello(sslSocket *ss, PRBool resending)
{
- sslSessionID * sid;
- ssl3CipherSpec * cwSpec;
- SECStatus rv;
- int i;
- int length;
- int num_suites;
- int actual_count = 0;
- PRBool isTLS = PR_FALSE;
- PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE;
- PRInt32 total_exten_len = 0;
- unsigned paddingExtensionLen;
- unsigned numCompressionMethods;
- PRInt32 flags;
+ sslSessionID *sid;
+ ssl3CipherSpec *cwSpec;
+ SECStatus rv;
+ int i;
+ int length;
+ int num_suites;
+ int actual_count = 0;
+ PRBool isTLS = PR_FALSE;
+ PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE;
+ PRInt32 total_exten_len = 0;
+ unsigned paddingExtensionLen;
+ unsigned numCompressionMethods;
+ PRInt32 flags;
SSL_TRC(3, ("%d: SSL3[%d]: send client_hello handshake", SSL_GETPID(),
- ss->fd));
+ ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
rv = ssl3_InitState(ss);
if (rv != SECSuccess) {
- return rv; /* ssl3_InitState has set the error code. */
+ return rv; /* ssl3_InitState has set the error code. */
}
/* These must be reset every handshake. */
ss->ssl3.hs.sendingSCSV = PR_FALSE;
@@ -5237,7 +5321,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
rv = ssl3_RestartHandshakeHashes(ss);
if (rv != SECSuccess) {
- return rv;
+ return rv;
}
/*
@@ -5245,16 +5329,16 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
* work around a Windows SChannel bug. Ensure that it is still enabled.
*/
if (ss->firstHsDone) {
- if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
- PORT_SetError(SSL_ERROR_SSL_DISABLED);
- return SECFailure;
- }
+ if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
+ PORT_SetError(SSL_ERROR_SSL_DISABLED);
+ return SECFailure;
+ }
- if (ss->clientHelloVersion < ss->vrange.min ||
- ss->clientHelloVersion > ss->vrange.max) {
- PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
- return SECFailure;
- }
+ if (ss->clientHelloVersion < ss->vrange.min ||
+ ss->clientHelloVersion > ss->vrange.max) {
+ PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
+ return SECFailure;
+ }
}
/* We ignore ss->sec.ci.sid here, and use ssl_Lookup because Lookup
@@ -5263,7 +5347,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
* this lookup is duplicative and wasteful.
*/
sid = (ss->opt.noCache) ? NULL
- : ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID, ss->url);
+ : ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID, ss->url);
/* We can't resume based on a different token. If the sid exists,
* make sure the token that holds the master secret still exists ...
@@ -5271,122 +5355,133 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
* the private key still exists, is logged in, hasn't been removed, etc.
*/
if (sid) {
- PRBool sidOK = PR_TRUE;
- if (sid->u.ssl3.keys.msIsWrapped) {
- /* Session key was wrapped, which means it was using PKCS11, */
- PK11SlotInfo *slot = NULL;
- if (sid->u.ssl3.masterValid && !ss->opt.bypassPKCS11) {
- slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,
- sid->u.ssl3.masterSlotID);
- }
- if (slot == NULL) {
- sidOK = PR_FALSE;
- } else {
- PK11SymKey *wrapKey = NULL;
- if (!PK11_IsPresent(slot) ||
- ((wrapKey = PK11_GetWrapKey(slot,
- sid->u.ssl3.masterWrapIndex,
- sid->u.ssl3.masterWrapMech,
- sid->u.ssl3.masterWrapSeries,
- ss->pkcs11PinArg)) == NULL) ) {
- sidOK = PR_FALSE;
- }
- if (wrapKey) PK11_FreeSymKey(wrapKey);
- PK11_FreeSlot(slot);
- slot = NULL;
- }
- }
- /* If we previously did client-auth, make sure that the token that
- ** holds the private key still exists, is logged in, hasn't been
- ** removed, etc.
- */
- if (sidOK && !ssl3_ClientAuthTokenPresent(sid)) {
- sidOK = PR_FALSE;
- }
-
- if (sidOK) {
+ PRBool sidOK = PR_TRUE;
+ if (sid->u.ssl3.keys.msIsWrapped) {
+ /* Session key was wrapped, which means it was using PKCS11, */
+ PK11SlotInfo *slot = NULL;
+ if (sid->u.ssl3.masterValid && !ss->opt.bypassPKCS11) {
+ slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,
+ sid->u.ssl3.masterSlotID);
+ }
+ if (slot == NULL) {
+ sidOK = PR_FALSE;
+ } else {
+ PK11SymKey *wrapKey = NULL;
+ if (!PK11_IsPresent(slot) ||
+ ((wrapKey = PK11_GetWrapKey(slot,
+ sid->u.ssl3.masterWrapIndex,
+ sid->u.ssl3.masterWrapMech,
+ sid->u.ssl3.masterWrapSeries,
+ ss->pkcs11PinArg)) == NULL)) {
+ sidOK = PR_FALSE;
+ }
+ if (wrapKey)
+ PK11_FreeSymKey(wrapKey);
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ }
+ }
+ /* If we previously did client-auth, make sure that the token that
+ ** holds the private key still exists, is logged in, hasn't been
+ ** removed, etc.
+ */
+ if (sidOK && !ssl3_ClientAuthTokenPresent(sid)) {
+ sidOK = PR_FALSE;
+ }
+
+ if (sidOK) {
/* Set ss->version based on the session cache */
- if (ss->firstHsDone) {
- /*
- * Windows SChannel compares the client_version inside the RSA
- * EncryptedPreMasterSecret of a renegotiation with the
- * client_version of the initial ClientHello rather than the
- * ClientHello in the renegotiation. To work around this bug, we
- * continue to use the client_version used in the initial
- * ClientHello when renegotiating.
- *
- * The client_version of the initial ClientHello is still
- * available in ss->clientHelloVersion. Ensure that
- * sid->version is bounded within
- * [ss->vrange.min, ss->clientHelloVersion], otherwise we
- * can't use sid.
- */
- if (sid->version >= ss->vrange.min &&
- sid->version <= ss->clientHelloVersion) {
- ss->version = ss->clientHelloVersion;
- } else {
- sidOK = PR_FALSE;
- }
- } else {
+ if (ss->firstHsDone) {
+ /*
+ * Windows SChannel compares the client_version inside the RSA
+ * EncryptedPreMasterSecret of a renegotiation with the
+ * client_version of the initial ClientHello rather than the
+ * ClientHello in the renegotiation. To work around this bug, we
+ * continue to use the client_version used in the initial
+ * ClientHello when renegotiating.
+ *
+ * The client_version of the initial ClientHello is still
+ * available in ss->clientHelloVersion. Ensure that
+ * sid->version is bounded within
+ * [ss->vrange.min, ss->clientHelloVersion], otherwise we
+ * can't use sid.
+ */
+ if (sid->version >= ss->vrange.min &&
+ sid->version <= ss->clientHelloVersion) {
+ ss->version = ss->clientHelloVersion;
+ } else {
+ sidOK = PR_FALSE;
+ }
+ } else {
/*
* Check sid->version is OK first.
* Previously, we would cap the version based on sid->version,
* but that prevents negotiation of a higher version if the
* previous session was reduced (e.g., with version fallback)
*/
- if (sid->version < ss->vrange.min ||
+ if (sid->version < ss->vrange.min ||
sid->version > ss->vrange.max) {
- sidOK = PR_FALSE;
- } else {
- rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED,
+ sidOK = PR_FALSE;
+ } else {
+ rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED,
PR_TRUE);
- if (rv != SECSuccess) {
- return rv; /* error code was set */
+ if (rv != SECSuccess) {
+ return rv; /* error code was set */
}
- }
- }
- }
+ }
+ }
+ }
- if (!sidOK) {
- SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_not_ok );
- if (ss->sec.uncache)
+ if (!sidOK) {
+ SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_not_ok);
+ if (ss->sec.uncache)
(*ss->sec.uncache)(sid);
- ssl_FreeSID(sid);
- sid = NULL;
- }
+ ssl_FreeSID(sid);
+ sid = NULL;
+ }
}
if (sid) {
- requestingResume = PR_TRUE;
- SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_hits );
+ requestingResume = PR_TRUE;
+ SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_hits);
- PRINT_BUF(4, (ss, "client, found session-id:", sid->u.ssl3.sessionID,
- sid->u.ssl3.sessionIDLength));
+ PRINT_BUF(4, (ss, "client, found session-id:", sid->u.ssl3.sessionID,
+ sid->u.ssl3.sessionIDLength));
- ss->ssl3.policy = sid->u.ssl3.policy;
+ ss->ssl3.policy = sid->u.ssl3.policy;
} else {
- SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_misses );
-
- /*
- * Windows SChannel compares the client_version inside the RSA
- * EncryptedPreMasterSecret of a renegotiation with the
- * client_version of the initial ClientHello rather than the
- * ClientHello in the renegotiation. To work around this bug, we
- * continue to use the client_version used in the initial
- * ClientHello when renegotiating.
- */
- if (ss->firstHsDone) {
- ss->version = ss->clientHelloVersion;
- } else {
- rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED,
- PR_TRUE);
- if (rv != SECSuccess)
- return rv; /* error code was set */
- }
-
- sid = ssl3_NewSessionID(ss, PR_FALSE);
- if (!sid) {
- return SECFailure; /* memory error is set */
+ SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_misses);
+
+ /*
+ * Windows SChannel compares the client_version inside the RSA
+ * EncryptedPreMasterSecret of a renegotiation with the
+ * client_version of the initial ClientHello rather than the
+ * ClientHello in the renegotiation. To work around this bug, we
+ * continue to use the client_version used in the initial
+ * ClientHello when renegotiating.
+ */
+ if (ss->firstHsDone) {
+ ss->version = ss->clientHelloVersion;
+ } else {
+ rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED,
+ PR_TRUE);
+ if (rv != SECSuccess)
+ return rv; /* error code was set */
+ }
+
+ sid = ssl3_NewSessionID(ss, PR_FALSE);
+ if (!sid) {
+ return SECFailure; /* memory error is set */
+ }
+ }
+
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ rv = tls13_SetupClientHello(ss);
+ if (rv != SECSuccess) {
+ if (sid) {
+ ssl_FreeSID(sid);
+ }
+ return rv;
}
}
@@ -5394,13 +5489,13 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
ssl_GetSpecWriteLock(ss);
cwSpec = ss->ssl3.cwSpec;
if (cwSpec->mac_def->mac == mac_null) {
- /* SSL records are not being MACed. */
- cwSpec->version = ss->version;
+ /* SSL records are not being MACed. */
+ cwSpec->version = ss->version;
}
ssl_ReleaseSpecWriteLock(ss);
if (ss->sec.ci.sid != NULL) {
- ssl_FreeSID(ss->sec.ci.sid); /* decrement ref count, free if zero */
+ ssl_FreeSID(ss->sec.ci.sid); /* decrement ref count, free if zero */
}
ss->sec.ci.sid = sid;
@@ -5408,24 +5503,24 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
/* shouldn't get here if SSL3 is disabled, but ... */
if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
- PR_NOT_REACHED("No versions of SSL 3.0 or later are enabled");
- PORT_SetError(SSL_ERROR_SSL_DISABLED);
- return SECFailure;
+ PR_NOT_REACHED("No versions of SSL 3.0 or later are enabled");
+ PORT_SetError(SSL_ERROR_SSL_DISABLED);
+ return SECFailure;
}
/* how many suites does our PKCS11 support (regardless of policy)? */
num_suites = ssl3_config_match_init(ss);
if (!num_suites)
- return SECFailure; /* ssl3_config_match_init has set error code. */
+ return SECFailure; /* ssl3_config_match_init has set error code. */
/* HACK for SCSV in SSL 3.0. On initial handshake, prepend SCSV,
* only if TLS is disabled.
*/
if (!ss->firstHsDone && !isTLS) {
- /* Must set this before calling Hello Extension Senders,
- * to suppress sending of empty RI extension.
- */
- ss->ssl3.hs.sendingSCSV = PR_TRUE;
+ /* Must set this before calling Hello Extension Senders,
+ * to suppress sending of empty RI extension.
+ */
+ ss->ssl3.hs.sendingSCSV = PR_TRUE;
}
/* When we attempt session resumption (only), we must lock the sid to
@@ -5436,69 +5531,69 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
* the lock across the calls to ssl3_CallHelloExtensionSenders.
*/
if (sid->u.ssl3.lock) {
- NSSRWLock_LockRead(sid->u.ssl3.lock);
+ PR_RWLock_Rlock(sid->u.ssl3.lock);
}
if (isTLS || (ss->firstHsDone && ss->peerRequestedProtection)) {
- PRUint32 maxBytes = 65535; /* 2^16 - 1 */
- PRInt32 extLen;
+ PRUint32 maxBytes = 65535; /* 2^16 - 1 */
+ PRInt32 extLen;
- extLen = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, maxBytes, NULL);
- if (extLen < 0) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return SECFailure;
- }
- total_exten_len += extLen;
+ extLen = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, maxBytes, NULL);
+ if (extLen < 0) {
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return SECFailure;
+ }
+ total_exten_len += extLen;
- if (total_exten_len > 0)
- total_exten_len += 2;
+ if (total_exten_len > 0)
+ total_exten_len += 2;
}
#ifndef NSS_DISABLE_ECC
if (!total_exten_len || !isTLS) {
- /* not sending the elliptic_curves and ec_point_formats extensions */
- ssl3_DisableECCSuites(ss, NULL); /* disable all ECC suites */
+ /* not sending the elliptic_curves and ec_point_formats extensions */
+ ssl3_DisableECCSuites(ss, NULL); /* disable all ECC suites */
}
#endif /* NSS_DISABLE_ECC */
if (IS_DTLS(ss)) {
- ssl3_DisableNonDTLSSuites(ss);
- }
-
- if (!ssl3_HasGCMSupport()) {
- ssl3_DisableGCMSuites(ss);
+ ssl3_DisableNonDTLSSuites(ss);
}
/* how many suites are permitted by policy and user preference? */
num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE);
if (!num_suites) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return SECFailure; /* count_cipher_suites has set error code. */
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return SECFailure; /* count_cipher_suites has set error code. */
}
fallbackSCSV = ss->opt.enableFallbackSCSV && (!requestingResume ||
- ss->version < sid->version);
+ ss->version < sid->version);
/* make room for SCSV */
if (ss->ssl3.hs.sendingSCSV) {
- ++num_suites;
+ ++num_suites;
}
if (fallbackSCSV) {
- ++num_suites;
+ ++num_suites;
}
/* count compression methods */
numCompressionMethods = 0;
for (i = 0; i < compressionMethodsCount; i++) {
- if (compressionEnabled(ss, compressions[i]))
- numCompressionMethods++;
+ if (compressionEnabled(ss, compressions[i]))
+ numCompressionMethods++;
}
length = sizeof(SSL3ProtocolVersion) + SSL3_RANDOM_LENGTH +
- 1 + ((sid == NULL) ? 0 : sid->u.ssl3.sessionIDLength) +
- 2 + num_suites*sizeof(ssl3CipherSuite) +
- 1 + numCompressionMethods + total_exten_len;
+ 1 + ((sid == NULL) ? 0 : sid->u.ssl3.sessionIDLength) +
+ 2 + num_suites * sizeof(ssl3CipherSuite) +
+ 1 + numCompressionMethods + total_exten_len;
if (IS_DTLS(ss)) {
- length += 1 + ss->ssl3.hs.cookieLen;
+ length += 1 + ss->ssl3.hs.cookieLen;
}
/* A padding extension may be included to ensure that the record containing
@@ -5517,160 +5612,194 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
rv = ssl3_AppendHandshakeHeader(ss, client_hello, length);
if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by ssl3_AppendHandshake* */
}
if (ss->firstHsDone) {
- /* The client hello version must stay unchanged to work around
- * the Windows SChannel bug described above. */
- PORT_Assert(ss->version == ss->clientHelloVersion);
+ /* The client hello version must stay unchanged to work around
+ * the Windows SChannel bug described above. */
+ PORT_Assert(ss->version == ss->clientHelloVersion);
}
ss->clientHelloVersion = ss->version;
if (IS_DTLS(ss)) {
- PRUint16 version;
+ PRUint16 version;
- version = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion);
- rv = ssl3_AppendHandshakeNumber(ss, version, 2);
+ version = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion);
+ rv = ssl3_AppendHandshakeNumber(ss, version, 2);
} else {
- rv = ssl3_AppendHandshakeNumber(ss, ss->clientHelloVersion, 2);
+ rv = ssl3_AppendHandshakeNumber(ss, ss->clientHelloVersion, 2);
}
if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by ssl3_AppendHandshake* */
}
if (!resending) { /* Don't re-generate if we are in DTLS re-sending mode */
- rv = ssl3_GetNewRandom(&ss->ssl3.hs.client_random);
- if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by GetNewRandom. */
- }
+ rv = ssl3_GetNewRandom(&ss->ssl3.hs.client_random);
+ if (rv != SECSuccess) {
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by GetNewRandom. */
+ }
}
rv = ssl3_AppendHandshake(ss, &ss->ssl3.hs.client_random,
SSL3_RANDOM_LENGTH);
if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by ssl3_AppendHandshake* */
}
if (sid)
- rv = ssl3_AppendHandshakeVariable(
- ss, sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength, 1);
+ rv = ssl3_AppendHandshakeVariable(
+ ss, sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength, 1);
else
- rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
+ rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by ssl3_AppendHandshake* */
}
if (IS_DTLS(ss)) {
- rv = ssl3_AppendHandshakeVariable(
- ss, ss->ssl3.hs.cookie, ss->ssl3.hs.cookieLen, 1);
- if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
+ rv = ssl3_AppendHandshakeVariable(
+ ss, ss->ssl3.hs.cookie, ss->ssl3.hs.cookieLen, 1);
+ if (rv != SECSuccess) {
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by ssl3_AppendHandshake* */
+ }
}
- rv = ssl3_AppendHandshakeNumber(ss, num_suites*sizeof(ssl3CipherSuite), 2);
+ rv = ssl3_AppendHandshakeNumber(ss, num_suites * sizeof(ssl3CipherSuite), 2);
if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by ssl3_AppendHandshake* */
}
if (ss->ssl3.hs.sendingSCSV) {
- /* Add the actual SCSV */
- rv = ssl3_AppendHandshakeNumber(ss, TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
- sizeof(ssl3CipherSuite));
- if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
- actual_count++;
+ /* Add the actual SCSV */
+ rv = ssl3_AppendHandshakeNumber(ss, TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
+ sizeof(ssl3CipherSuite));
+ if (rv != SECSuccess) {
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by ssl3_AppendHandshake* */
+ }
+ actual_count++;
}
if (fallbackSCSV) {
- rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV,
- sizeof(ssl3CipherSuite));
- if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
- actual_count++;
+ rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV,
+ sizeof(ssl3CipherSuite));
+ if (rv != SECSuccess) {
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by ssl3_AppendHandshake* */
+ }
+ actual_count++;
}
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
- ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
- if (config_match(suite, ss->ssl3.policy, PR_TRUE, &ss->vrange, ss)) {
- actual_count++;
- if (actual_count > num_suites) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- /* set error card removal/insertion error */
- PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
- return SECFailure;
- }
- rv = ssl3_AppendHandshakeNumber(ss, suite->cipher_suite,
- sizeof(ssl3CipherSuite));
- if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
- }
+ ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
+ if (config_match(suite, ss->ssl3.policy, PR_TRUE, &ss->vrange, ss)) {
+ actual_count++;
+ if (actual_count > num_suites) {
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ /* set error card removal/insertion error */
+ PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
+ return SECFailure;
+ }
+ rv = ssl3_AppendHandshakeNumber(ss, suite->cipher_suite,
+ sizeof(ssl3CipherSuite));
+ if (rv != SECSuccess) {
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by ssl3_AppendHandshake* */
+ }
+ }
}
/* if cards were removed or inserted between count_cipher_suites and
* generating our list, detect the error here rather than send it off to
* the server.. */
if (actual_count != num_suites) {
- /* Card removal/insertion error */
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
- return SECFailure;
+ /* Card removal/insertion error */
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
+ return SECFailure;
}
rv = ssl3_AppendHandshakeNumber(ss, numCompressionMethods, 1);
if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by ssl3_AppendHandshake* */
}
for (i = 0; i < compressionMethodsCount; i++) {
- if (!compressionEnabled(ss, compressions[i]))
- continue;
- rv = ssl3_AppendHandshakeNumber(ss, compressions[i], 1);
- if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by ssl3_AppendHandshake* */
- }
+ if (!compressionEnabled(ss, compressions[i]))
+ continue;
+ rv = ssl3_AppendHandshakeNumber(ss, compressions[i], 1);
+ if (rv != SECSuccess) {
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by ssl3_AppendHandshake* */
+ }
}
if (total_exten_len) {
- PRUint32 maxBytes = total_exten_len - 2;
- PRInt32 extLen;
-
- rv = ssl3_AppendHandshakeNumber(ss, maxBytes, 2);
- if (rv != SECSuccess) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return rv; /* err set by AppendHandshake. */
- }
-
- extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, maxBytes, NULL);
- if (extLen < 0) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return SECFailure;
- }
- maxBytes -= extLen;
-
- extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
- if (extLen < 0) {
- if (sid->u.ssl3.lock) { NSSRWLock_UnlockRead(sid->u.ssl3.lock); }
- return SECFailure;
- }
- maxBytes -= extLen;
-
- PORT_Assert(!maxBytes);
- }
+ PRUint32 maxBytes = total_exten_len - 2;
+ PRInt32 extLen;
+
+ rv = ssl3_AppendHandshakeNumber(ss, maxBytes, 2);
+ if (rv != SECSuccess) {
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return rv; /* err set by AppendHandshake. */
+ }
+
+ extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, maxBytes, NULL);
+ if (extLen < 0) {
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return SECFailure;
+ }
+ maxBytes -= extLen;
+
+ extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
+ if (extLen < 0) {
+ if (sid->u.ssl3.lock) {
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
+ }
+ return SECFailure;
+ }
+ maxBytes -= extLen;
+
+ PORT_Assert(!maxBytes);
+ }
if (sid->u.ssl3.lock) {
- NSSRWLock_UnlockRead(sid->u.ssl3.lock);
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
}
if (ss->xtnData.sentSessionTicketInClientHello) {
@@ -5678,64 +5807,64 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
}
if (ss->ssl3.hs.sendingSCSV) {
- /* Since we sent the SCSV, pretend we sent empty RI extension. */
- TLSExtensionData *xtnData = &ss->xtnData;
- xtnData->advertised[xtnData->numAdvertised++] =
- ssl_renegotiation_info_xtn;
+ /* Since we sent the SCSV, pretend we sent empty RI extension. */
+ TLSExtensionData *xtnData = &ss->xtnData;
+ xtnData->advertised[xtnData->numAdvertised++] =
+ ssl_renegotiation_info_xtn;
}
flags = 0;
if (!ss->firstHsDone && !IS_DTLS(ss)) {
- flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION;
+ flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION;
}
rv = ssl3_FlushHandshake(ss, flags);
if (rv != SECSuccess) {
- return rv; /* error code set by ssl3_FlushHandshake */
+ return rv; /* error code set by ssl3_FlushHandshake */
}
ss->ssl3.hs.ws = wait_server_hello;
return rv;
}
-
-/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
- * ssl3 Hello Request.
+/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered a
+ * complete ssl3 Hello Request.
* Caller must hold Handshake and RecvBuf locks.
*/
static SECStatus
ssl3_HandleHelloRequest(sslSocket *ss)
{
sslSessionID *sid = ss->sec.ci.sid;
- SECStatus rv;
+ SECStatus rv;
SSL_TRC(3, ("%d: SSL3[%d]: handle hello_request handshake",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3);
if (ss->ssl3.hs.ws == wait_server_hello)
- return SECSuccess;
+ return SECSuccess;
if (ss->ssl3.hs.ws != idle_handshake || ss->sec.isServer) {
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST);
- return SECFailure;
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST);
+ return SECFailure;
}
if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
- (void)SSL3_SendAlert(ss, alert_warning, no_renegotiation);
- PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
- return SECFailure;
+ (void)SSL3_SendAlert(ss, alert_warning, no_renegotiation);
+ PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
+ return SECFailure;
}
if (sid) {
- if (ss->sec.uncache)
+ if (ss->sec.uncache)
ss->sec.uncache(sid);
- ssl_FreeSID(sid);
- ss->sec.ci.sid = NULL;
+ ssl_FreeSID(sid);
+ ss->sec.ci.sid = NULL;
}
if (IS_DTLS(ss)) {
- dtls_RehandshakeCleanup(ss);
+ dtls_RehandshakeCleanup(ss);
}
ssl_GetXmitBufLock(ss);
@@ -5772,7 +5901,7 @@ ssl_FindIndexByWrapMechanism(CK_MECHANISM_TYPE mech)
const CK_MECHANISM_TYPE *pMech = wrapMechanismList;
while (mech != *pMech && *pMech != UNKNOWN_WRAP_MECHANISM) {
- ++pMech;
+ ++pMech;
}
return (*pMech == UNKNOWN_WRAP_MECHANISM) ? -1
: (pMech - wrapMechanismList);
@@ -5780,97 +5909,97 @@ ssl_FindIndexByWrapMechanism(CK_MECHANISM_TYPE mech)
static PK11SymKey *
ssl_UnwrapSymWrappingKey(
- SSLWrappedSymWrappingKey *pWswk,
- SECKEYPrivateKey * svrPrivKey,
- SSL3KEAType exchKeyType,
- CK_MECHANISM_TYPE masterWrapMech,
- void * pwArg)
-{
- PK11SymKey * unwrappedWrappingKey = NULL;
- SECItem wrappedKey;
+ SSLWrappedSymWrappingKey *pWswk,
+ SECKEYPrivateKey *svrPrivKey,
+ SSL3KEAType exchKeyType,
+ CK_MECHANISM_TYPE masterWrapMech,
+ void *pwArg)
+{
+ PK11SymKey *unwrappedWrappingKey = NULL;
+ SECItem wrappedKey;
#ifndef NSS_DISABLE_ECC
- PK11SymKey * Ks;
- SECKEYPublicKey pubWrapKey;
- ECCWrappedKeyInfo *ecWrapped;
+ PK11SymKey *Ks;
+ SECKEYPublicKey pubWrapKey;
+ ECCWrappedKeyInfo *ecWrapped;
#endif /* NSS_DISABLE_ECC */
/* found the wrapping key on disk. */
PORT_Assert(pWswk->symWrapMechanism == masterWrapMech);
- PORT_Assert(pWswk->exchKeyType == exchKeyType);
+ PORT_Assert(pWswk->exchKeyType == exchKeyType);
if (pWswk->symWrapMechanism != masterWrapMech ||
- pWswk->exchKeyType != exchKeyType) {
- goto loser;
+ pWswk->exchKeyType != exchKeyType) {
+ goto loser;
}
wrappedKey.type = siBuffer;
wrappedKey.data = pWswk->wrappedSymmetricWrappingkey;
- wrappedKey.len = pWswk->wrappedSymKeyLen;
+ wrappedKey.len = pWswk->wrappedSymKeyLen;
PORT_Assert(wrappedKey.len <= sizeof pWswk->wrappedSymmetricWrappingkey);
switch (exchKeyType) {
- case kt_rsa:
- unwrappedWrappingKey =
- PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
- masterWrapMech, CKA_UNWRAP, 0);
- break;
+ case kt_rsa:
+ unwrappedWrappingKey =
+ PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
+ masterWrapMech, CKA_UNWRAP, 0);
+ break;
#ifndef NSS_DISABLE_ECC
- case kt_ecdh:
- /*
- * For kt_ecdh, we first create an EC public key based on
- * data stored with the wrappedSymmetricWrappingkey. Next,
- * we do an ECDH computation involving this public key and
- * the SSL server's (long-term) EC private key. The resulting
- * shared secret is treated the same way as Fortezza's Ks, i.e.,
- * it is used to recover the symmetric wrapping key.
- *
- * The data in wrappedSymmetricWrappingkey is laid out as defined
- * in the ECCWrappedKeyInfo structure.
- */
- ecWrapped = (ECCWrappedKeyInfo *) pWswk->wrappedSymmetricWrappingkey;
-
- PORT_Assert(ecWrapped->encodedParamLen + ecWrapped->pubValueLen +
- ecWrapped->wrappedKeyLen <= MAX_EC_WRAPPED_KEY_BUFLEN);
+ case kt_ecdh:
+ /*
+ * For kt_ecdh, we first create an EC public key based on
+ * data stored with the wrappedSymmetricWrappingkey. Next,
+ * we do an ECDH computation involving this public key and
+ * the SSL server's (long-term) EC private key. The resulting
+ * shared secret is treated the same way as Fortezza's Ks, i.e.,
+ * it is used to recover the symmetric wrapping key.
+ *
+ * The data in wrappedSymmetricWrappingkey is laid out as defined
+ * in the ECCWrappedKeyInfo structure.
+ */
+ ecWrapped = (ECCWrappedKeyInfo *)pWswk->wrappedSymmetricWrappingkey;
+
+ PORT_Assert(ecWrapped->encodedParamLen + ecWrapped->pubValueLen +
+ ecWrapped->wrappedKeyLen <= MAX_EC_WRAPPED_KEY_BUFLEN);
+
+ if (ecWrapped->encodedParamLen + ecWrapped->pubValueLen +
+ ecWrapped->wrappedKeyLen > MAX_EC_WRAPPED_KEY_BUFLEN) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ goto loser;
+ }
- if (ecWrapped->encodedParamLen + ecWrapped->pubValueLen +
- ecWrapped->wrappedKeyLen > MAX_EC_WRAPPED_KEY_BUFLEN) {
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- goto loser;
- }
+ pubWrapKey.keyType = ecKey;
+ pubWrapKey.u.ec.size = ecWrapped->size;
+ pubWrapKey.u.ec.DEREncodedParams.len = ecWrapped->encodedParamLen;
+ pubWrapKey.u.ec.DEREncodedParams.data = ecWrapped->var;
+ pubWrapKey.u.ec.publicValue.len = ecWrapped->pubValueLen;
+ pubWrapKey.u.ec.publicValue.data = ecWrapped->var +
+ ecWrapped->encodedParamLen;
+
+ wrappedKey.len = ecWrapped->wrappedKeyLen;
+ wrappedKey.data = ecWrapped->var + ecWrapped->encodedParamLen +
+ ecWrapped->pubValueLen;
+
+ /* Derive Ks using ECDH */
+ Ks = PK11_PubDeriveWithKDF(svrPrivKey, &pubWrapKey, PR_FALSE, NULL,
+ NULL, CKM_ECDH1_DERIVE, masterWrapMech,
+ CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
+ if (Ks == NULL) {
+ goto loser;
+ }
- pubWrapKey.keyType = ecKey;
- pubWrapKey.u.ec.size = ecWrapped->size;
- pubWrapKey.u.ec.DEREncodedParams.len = ecWrapped->encodedParamLen;
- pubWrapKey.u.ec.DEREncodedParams.data = ecWrapped->var;
- pubWrapKey.u.ec.publicValue.len = ecWrapped->pubValueLen;
- pubWrapKey.u.ec.publicValue.data = ecWrapped->var +
- ecWrapped->encodedParamLen;
-
- wrappedKey.len = ecWrapped->wrappedKeyLen;
- wrappedKey.data = ecWrapped->var + ecWrapped->encodedParamLen +
- ecWrapped->pubValueLen;
-
- /* Derive Ks using ECDH */
- Ks = PK11_PubDeriveWithKDF(svrPrivKey, &pubWrapKey, PR_FALSE, NULL,
- NULL, CKM_ECDH1_DERIVE, masterWrapMech,
- CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
- if (Ks == NULL) {
- goto loser;
- }
+ /* Use Ks to unwrap the wrapping key */
+ unwrappedWrappingKey = PK11_UnwrapSymKey(Ks, masterWrapMech, NULL,
+ &wrappedKey, masterWrapMech,
+ CKA_UNWRAP, 0);
+ PK11_FreeSymKey(Ks);
- /* Use Ks to unwrap the wrapping key */
- unwrappedWrappingKey = PK11_UnwrapSymKey(Ks, masterWrapMech, NULL,
- &wrappedKey, masterWrapMech,
- CKA_UNWRAP, 0);
- PK11_FreeSymKey(Ks);
-
- break;
+ break;
#endif
- default:
- /* Assert? */
- SET_ERROR_CODE
- goto loser;
+ default:
+ /* Assert? */
+ SET_ERROR_CODE
+ goto loser;
}
loser:
return unwrappedWrappingKey;
@@ -5883,13 +6012,14 @@ loser:
*/
typedef struct {
- PK11SymKey * symWrapKey[kt_kea_size];
+ PK11SymKey *symWrapKey[kt_kea_size];
} ssl3SymWrapKey;
-static PZLock * symWrapKeysLock = NULL;
-static ssl3SymWrapKey symWrapKeys[SSL_NUM_WRAP_MECHS];
+static PZLock *symWrapKeysLock = NULL;
+static ssl3SymWrapKey symWrapKeys[SSL_NUM_WRAP_MECHS];
-SECStatus ssl_FreeSymWrapKeysLock(void)
+SECStatus
+ssl_FreeSymWrapKeysLock(void)
{
if (symWrapKeysLock) {
PZ_DestroyLock(symWrapKeysLock);
@@ -5903,28 +6033,29 @@ SECStatus ssl_FreeSymWrapKeysLock(void)
SECStatus
SSL3_ShutdownServerCache(void)
{
- int i, j;
+ int i, j;
if (!symWrapKeysLock)
- return SECSuccess; /* lock was never initialized */
+ return SECSuccess; /* lock was never initialized */
PZ_Lock(symWrapKeysLock);
/* get rid of all symWrapKeys */
for (i = 0; i < SSL_NUM_WRAP_MECHS; ++i) {
- for (j = 0; j < kt_kea_size; ++j) {
- PK11SymKey ** pSymWrapKey;
- pSymWrapKey = &symWrapKeys[i].symWrapKey[j];
- if (*pSymWrapKey) {
- PK11_FreeSymKey(*pSymWrapKey);
- *pSymWrapKey = NULL;
- }
- }
+ for (j = 0; j < kt_kea_size; ++j) {
+ PK11SymKey **pSymWrapKey;
+ pSymWrapKey = &symWrapKeys[i].symWrapKey[j];
+ if (*pSymWrapKey) {
+ PK11_FreeSymKey(*pSymWrapKey);
+ *pSymWrapKey = NULL;
+ }
+ }
}
PZ_Unlock(symWrapKeysLock);
return SECSuccess;
}
-SECStatus ssl_InitSymWrapKeysLock(void)
+SECStatus
+ssl_InitSymWrapKeysLock(void)
{
symWrapKeysLock = PZ_NewLock(nssILockOther);
return symWrapKeysLock ? SECSuccess : SECFailure;
@@ -5936,39 +6067,39 @@ SECStatus ssl_InitSymWrapKeysLock(void)
* Put the new key in the in-memory array.
*/
static PK11SymKey *
-getWrappingKey( sslSocket * ss,
- PK11SlotInfo * masterSecretSlot,
- SSL3KEAType exchKeyType,
- CK_MECHANISM_TYPE masterWrapMech,
- void * pwArg)
-{
- SECKEYPrivateKey * svrPrivKey;
- SECKEYPublicKey * svrPubKey = NULL;
- PK11SymKey * unwrappedWrappingKey = NULL;
- PK11SymKey ** pSymWrapKey;
- CK_MECHANISM_TYPE asymWrapMechanism = CKM_INVALID_MECHANISM;
- int length;
- int symWrapMechIndex;
- SECStatus rv;
- SECItem wrappedKey;
+getWrappingKey(sslSocket *ss,
+ PK11SlotInfo *masterSecretSlot,
+ SSL3KEAType exchKeyType,
+ CK_MECHANISM_TYPE masterWrapMech,
+ void *pwArg)
+{
+ SECKEYPrivateKey *svrPrivKey;
+ SECKEYPublicKey *svrPubKey = NULL;
+ PK11SymKey *unwrappedWrappingKey = NULL;
+ PK11SymKey **pSymWrapKey;
+ CK_MECHANISM_TYPE asymWrapMechanism = CKM_INVALID_MECHANISM;
+ int length;
+ int symWrapMechIndex;
+ SECStatus rv;
+ SECItem wrappedKey;
SSLWrappedSymWrappingKey wswk;
#ifndef NSS_DISABLE_ECC
- PK11SymKey * Ks = NULL;
- SECKEYPublicKey *pubWrapKey = NULL;
- SECKEYPrivateKey *privWrapKey = NULL;
+ PK11SymKey *Ks = NULL;
+ SECKEYPublicKey *pubWrapKey = NULL;
+ SECKEYPrivateKey *privWrapKey = NULL;
ECCWrappedKeyInfo *ecWrapped;
#endif /* NSS_DISABLE_ECC */
- svrPrivKey = ss->serverCerts[exchKeyType].SERVERKEY;
+ svrPrivKey = ss->serverCerts[exchKeyType].SERVERKEY;
PORT_Assert(svrPrivKey != NULL);
if (!svrPrivKey) {
- return NULL; /* why are we here?!? */
+ return NULL; /* why are we here?!? */
}
symWrapMechIndex = ssl_FindIndexByWrapMechanism(masterWrapMech);
PORT_Assert(symWrapMechIndex >= 0);
if (symWrapMechIndex < 0)
- return NULL; /* invalid masterWrapMech. */
+ return NULL; /* invalid masterWrapMech. */
pSymWrapKey = &symWrapKeys[symWrapMechIndex].symWrapKey[exchKeyType];
@@ -5978,29 +6109,29 @@ getWrappingKey( sslSocket * ss,
unwrappedWrappingKey = *pSymWrapKey;
if (unwrappedWrappingKey != NULL) {
- if (PK11_VerifyKeyOK(unwrappedWrappingKey)) {
- unwrappedWrappingKey = PK11_ReferenceSymKey(unwrappedWrappingKey);
- goto done;
- }
- /* slot series has changed, so this key is no good any more. */
- PK11_FreeSymKey(unwrappedWrappingKey);
- *pSymWrapKey = unwrappedWrappingKey = NULL;
+ if (PK11_VerifyKeyOK(unwrappedWrappingKey)) {
+ unwrappedWrappingKey = PK11_ReferenceSymKey(unwrappedWrappingKey);
+ goto done;
+ }
+ /* slot series has changed, so this key is no good any more. */
+ PK11_FreeSymKey(unwrappedWrappingKey);
+ *pSymWrapKey = unwrappedWrappingKey = NULL;
}
/* Try to get wrapped SymWrapping key out of the (disk) cache. */
/* Following call fills in wswk on success. */
if (ssl_GetWrappingKey(symWrapMechIndex, exchKeyType, &wswk)) {
- /* found the wrapped sym wrapping key on disk. */
- unwrappedWrappingKey =
- ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, exchKeyType,
+ /* found the wrapped sym wrapping key on disk. */
+ unwrappedWrappingKey =
+ ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, exchKeyType,
masterWrapMech, pwArg);
- if (unwrappedWrappingKey) {
- goto install;
- }
+ if (unwrappedWrappingKey) {
+ goto install;
+ }
}
- if (!masterSecretSlot) /* caller doesn't want to create a new one. */
- goto loser;
+ if (!masterSecretSlot) /* caller doesn't want to create a new one. */
+ goto loser;
length = PK11_GetBestKeyLength(masterSecretSlot, masterWrapMech);
/* Zero length means fixed key length algorithm, or error.
@@ -6009,163 +6140,166 @@ getWrappingKey( sslSocket * ss,
unwrappedWrappingKey = PK11_KeyGen(masterSecretSlot, masterWrapMech, NULL,
length, pwArg);
if (!unwrappedWrappingKey) {
- goto loser;
+ goto loser;
}
/* Prepare the buffer to receive the wrappedWrappingKey,
* the symmetric wrapping key wrapped using the server's pub key.
*/
- PORT_Memset(&wswk, 0, sizeof wswk); /* eliminate UMRs. */
+ PORT_Memset(&wswk, 0, sizeof wswk); /* eliminate UMRs. */
if (ss->serverCerts[exchKeyType].serverKeyPair) {
- svrPubKey = ss->serverCerts[exchKeyType].serverKeyPair->pubKey;
+ svrPubKey = ss->serverCerts[exchKeyType].serverKeyPair->pubKey;
}
if (svrPubKey == NULL) {
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- goto loser;
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ goto loser;
}
wrappedKey.type = siBuffer;
- wrappedKey.len = SECKEY_PublicKeyStrength(svrPubKey);
+ wrappedKey.len = SECKEY_PublicKeyStrength(svrPubKey);
wrappedKey.data = wswk.wrappedSymmetricWrappingkey;
PORT_Assert(wrappedKey.len <= sizeof wswk.wrappedSymmetricWrappingkey);
if (wrappedKey.len > sizeof wswk.wrappedSymmetricWrappingkey)
- goto loser;
+ goto loser;
/* wrap symmetric wrapping key in server's public key. */
switch (exchKeyType) {
- case kt_rsa:
- asymWrapMechanism = CKM_RSA_PKCS;
- rv = PK11_PubWrapSymKey(asymWrapMechanism, svrPubKey,
- unwrappedWrappingKey, &wrappedKey);
- break;
+ case kt_rsa:
+ asymWrapMechanism = CKM_RSA_PKCS;
+ rv = PK11_PubWrapSymKey(asymWrapMechanism, svrPubKey,
+ unwrappedWrappingKey, &wrappedKey);
+ break;
#ifndef NSS_DISABLE_ECC
- case kt_ecdh:
- /*
- * We generate an ephemeral EC key pair. Perform an ECDH
- * computation involving this ephemeral EC public key and
- * the SSL server's (long-term) EC private key. The resulting
- * shared secret is treated in the same way as Fortezza's Ks,
- * i.e., it is used to wrap the wrapping key. To facilitate
- * unwrapping in ssl_UnwrapWrappingKey, we also store all
- * relevant info about the ephemeral EC public key in
- * wswk.wrappedSymmetricWrappingkey and lay it out as
- * described in the ECCWrappedKeyInfo structure.
- */
- PORT_Assert(svrPubKey->keyType == ecKey);
- if (svrPubKey->keyType != ecKey) {
- /* something is wrong in sslsecur.c if this isn't an ecKey */
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- rv = SECFailure;
- goto ec_cleanup;
- }
-
- privWrapKey = SECKEY_CreateECPrivateKey(
- &svrPubKey->u.ec.DEREncodedParams, &pubWrapKey, NULL);
- if ((privWrapKey == NULL) || (pubWrapKey == NULL)) {
- rv = SECFailure;
- goto ec_cleanup;
- }
-
- /* Set the key size in bits */
- if (pubWrapKey->u.ec.size == 0) {
- pubWrapKey->u.ec.size = SECKEY_PublicKeyStrengthInBits(svrPubKey);
- }
-
- PORT_Assert(pubWrapKey->u.ec.DEREncodedParams.len +
- pubWrapKey->u.ec.publicValue.len < MAX_EC_WRAPPED_KEY_BUFLEN);
- if (pubWrapKey->u.ec.DEREncodedParams.len +
- pubWrapKey->u.ec.publicValue.len >= MAX_EC_WRAPPED_KEY_BUFLEN) {
- PORT_SetError(SEC_ERROR_INVALID_KEY);
- rv = SECFailure;
- goto ec_cleanup;
- }
-
- /* Derive Ks using ECDH */
- Ks = PK11_PubDeriveWithKDF(svrPrivKey, pubWrapKey, PR_FALSE, NULL,
- NULL, CKM_ECDH1_DERIVE, masterWrapMech,
- CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
- if (Ks == NULL) {
- rv = SECFailure;
- goto ec_cleanup;
- }
-
- ecWrapped = (ECCWrappedKeyInfo *) (wswk.wrappedSymmetricWrappingkey);
- ecWrapped->size = pubWrapKey->u.ec.size;
- ecWrapped->encodedParamLen = pubWrapKey->u.ec.DEREncodedParams.len;
- PORT_Memcpy(ecWrapped->var, pubWrapKey->u.ec.DEREncodedParams.data,
- pubWrapKey->u.ec.DEREncodedParams.len);
-
- ecWrapped->pubValueLen = pubWrapKey->u.ec.publicValue.len;
- PORT_Memcpy(ecWrapped->var + ecWrapped->encodedParamLen,
- pubWrapKey->u.ec.publicValue.data,
- pubWrapKey->u.ec.publicValue.len);
-
- wrappedKey.len = MAX_EC_WRAPPED_KEY_BUFLEN -
- (ecWrapped->encodedParamLen + ecWrapped->pubValueLen);
- wrappedKey.data = ecWrapped->var + ecWrapped->encodedParamLen +
- ecWrapped->pubValueLen;
-
- /* wrap symmetricWrapping key with the local Ks */
- rv = PK11_WrapSymKey(masterWrapMech, NULL, Ks,
- unwrappedWrappingKey, &wrappedKey);
-
- if (rv != SECSuccess) {
- goto ec_cleanup;
- }
-
- /* Write down the length of wrapped key in the buffer
- * wswk.wrappedSymmetricWrappingkey at the appropriate offset
- */
- ecWrapped->wrappedKeyLen = wrappedKey.len;
-
-ec_cleanup:
- if (privWrapKey) SECKEY_DestroyPrivateKey(privWrapKey);
- if (pubWrapKey) SECKEY_DestroyPublicKey(pubWrapKey);
- if (Ks) PK11_FreeSymKey(Ks);
- asymWrapMechanism = masterWrapMech;
- break;
+ case kt_ecdh:
+ /*
+ * We generate an ephemeral EC key pair. Perform an ECDH
+ * computation involving this ephemeral EC public key and
+ * the SSL server's (long-term) EC private key. The resulting
+ * shared secret is treated in the same way as Fortezza's Ks,
+ * i.e., it is used to wrap the wrapping key. To facilitate
+ * unwrapping in ssl_UnwrapWrappingKey, we also store all
+ * relevant info about the ephemeral EC public key in
+ * wswk.wrappedSymmetricWrappingkey and lay it out as
+ * described in the ECCWrappedKeyInfo structure.
+ */
+ PORT_Assert(svrPubKey->keyType == ecKey);
+ if (svrPubKey->keyType != ecKey) {
+ /* something is wrong in sslsecur.c if this isn't an ecKey */
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ rv = SECFailure;
+ goto ec_cleanup;
+ }
+
+ privWrapKey = SECKEY_CreateECPrivateKey(
+ &svrPubKey->u.ec.DEREncodedParams, &pubWrapKey, NULL);
+ if ((privWrapKey == NULL) || (pubWrapKey == NULL)) {
+ rv = SECFailure;
+ goto ec_cleanup;
+ }
+
+ /* Set the key size in bits */
+ if (pubWrapKey->u.ec.size == 0) {
+ pubWrapKey->u.ec.size = SECKEY_PublicKeyStrengthInBits(svrPubKey);
+ }
+
+ PORT_Assert(pubWrapKey->u.ec.DEREncodedParams.len +
+ pubWrapKey->u.ec.publicValue.len < MAX_EC_WRAPPED_KEY_BUFLEN);
+ if (pubWrapKey->u.ec.DEREncodedParams.len +
+ pubWrapKey->u.ec.publicValue.len >= MAX_EC_WRAPPED_KEY_BUFLEN) {
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ rv = SECFailure;
+ goto ec_cleanup;
+ }
+
+ /* Derive Ks using ECDH */
+ Ks = PK11_PubDeriveWithKDF(svrPrivKey, pubWrapKey, PR_FALSE, NULL,
+ NULL, CKM_ECDH1_DERIVE, masterWrapMech,
+ CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
+ if (Ks == NULL) {
+ rv = SECFailure;
+ goto ec_cleanup;
+ }
+
+ ecWrapped = (ECCWrappedKeyInfo *)(wswk.wrappedSymmetricWrappingkey);
+ ecWrapped->size = pubWrapKey->u.ec.size;
+ ecWrapped->encodedParamLen = pubWrapKey->u.ec.DEREncodedParams.len;
+ PORT_Memcpy(ecWrapped->var, pubWrapKey->u.ec.DEREncodedParams.data,
+ pubWrapKey->u.ec.DEREncodedParams.len);
+
+ ecWrapped->pubValueLen = pubWrapKey->u.ec.publicValue.len;
+ PORT_Memcpy(ecWrapped->var + ecWrapped->encodedParamLen,
+ pubWrapKey->u.ec.publicValue.data,
+ pubWrapKey->u.ec.publicValue.len);
+
+ wrappedKey.len = MAX_EC_WRAPPED_KEY_BUFLEN -
+ (ecWrapped->encodedParamLen + ecWrapped->pubValueLen);
+ wrappedKey.data = ecWrapped->var + ecWrapped->encodedParamLen +
+ ecWrapped->pubValueLen;
+
+ /* wrap symmetricWrapping key with the local Ks */
+ rv = PK11_WrapSymKey(masterWrapMech, NULL, Ks,
+ unwrappedWrappingKey, &wrappedKey);
+
+ if (rv != SECSuccess) {
+ goto ec_cleanup;
+ }
+
+ /* Write down the length of wrapped key in the buffer
+ * wswk.wrappedSymmetricWrappingkey at the appropriate offset
+ */
+ ecWrapped->wrappedKeyLen = wrappedKey.len;
+
+ ec_cleanup:
+ if (privWrapKey)
+ SECKEY_DestroyPrivateKey(privWrapKey);
+ if (pubWrapKey)
+ SECKEY_DestroyPublicKey(pubWrapKey);
+ if (Ks)
+ PK11_FreeSymKey(Ks);
+ asymWrapMechanism = masterWrapMech;
+ break;
#endif /* NSS_DISABLE_ECC */
- default:
- rv = SECFailure;
- break;
+ default:
+ rv = SECFailure;
+ break;
}
if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
- goto loser;
+ ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ goto loser;
}
PORT_Assert(asymWrapMechanism != CKM_INVALID_MECHANISM);
- wswk.symWrapMechanism = masterWrapMech;
- wswk.symWrapMechIndex = symWrapMechIndex;
+ wswk.symWrapMechanism = masterWrapMech;
+ wswk.symWrapMechIndex = symWrapMechIndex;
wswk.asymWrapMechanism = asymWrapMechanism;
- wswk.exchKeyType = exchKeyType;
- wswk.wrappedSymKeyLen = wrappedKey.len;
+ wswk.exchKeyType = exchKeyType;
+ wswk.wrappedSymKeyLen = wrappedKey.len;
/* put it on disk. */
- /* If the wrapping key for this KEA type has already been set,
- * then abandon the value we just computed and
+ /* If the wrapping key for this KEA type has already been set,
+ * then abandon the value we just computed and
* use the one we got from the disk.
*/
if (ssl_SetWrappingKey(&wswk)) {
- /* somebody beat us to it. The original contents of our wswk
- * has been replaced with the content on disk. Now, discard
- * the key we just created and unwrap this new one.
- */
- PK11_FreeSymKey(unwrappedWrappingKey);
-
- unwrappedWrappingKey =
- ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, exchKeyType,
+ /* somebody beat us to it. The original contents of our wswk
+ * has been replaced with the content on disk. Now, discard
+ * the key we just created and unwrap this new one.
+ */
+ PK11_FreeSymKey(unwrappedWrappingKey);
+
+ unwrappedWrappingKey =
+ ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, exchKeyType,
masterWrapMech, pwArg);
}
install:
if (unwrappedWrappingKey) {
- *pSymWrapKey = PK11_ReferenceSymKey(unwrappedWrappingKey);
+ *pSymWrapKey = PK11_ReferenceSymKey(unwrappedWrappingKey);
}
loser:
@@ -6183,23 +6317,23 @@ hexEncode(char *out, const unsigned char *in, unsigned int length)
unsigned int i;
for (i = 0; i < length; i++) {
- *(out++) = hextable[in[i] >> 4];
- *(out++) = hextable[in[i] & 15];
+ *(out++) = hextable[in[i] >> 4];
+ *(out++) = hextable[in[i] & 15];
}
}
/* Called from ssl3_SendClientKeyExchange(). */
/* Presently, this always uses PKCS11. There is no bypass for this. */
static SECStatus
-sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
+sendRSAClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey)
{
- PK11SymKey * pms = NULL;
- SECStatus rv = SECFailure;
- SECItem enc_pms = {siBuffer, NULL, 0};
- PRBool isTLS;
+ PK11SymKey *pms = NULL;
+ SECStatus rv = SECFailure;
+ SECItem enc_pms = { siBuffer, NULL, 0 };
+ PRBool isTLS;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
/* Generate the pre-master secret ... */
ssl_GetSpecWriteLock(ss);
@@ -6208,68 +6342,69 @@ sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
pms = ssl3_GenerateRSAPMS(ss, ss->ssl3.pwSpec, NULL);
ssl_ReleaseSpecWriteLock(ss);
if (pms == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
- goto loser;
+ ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ goto loser;
}
/* Get the wrapped (encrypted) pre-master secret, enc_pms */
- enc_pms.len = SECKEY_PublicKeyStrength(svrPubKey);
- enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len);
+ enc_pms.len = SECKEY_PublicKeyStrength(svrPubKey);
+ enc_pms.data = (unsigned char *)PORT_Alloc(enc_pms.len);
if (enc_pms.data == NULL) {
- goto loser; /* err set by PORT_Alloc */
+ goto loser; /* err set by PORT_Alloc */
}
/* wrap pre-master secret in server's public key. */
rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, pms, &enc_pms);
if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
- goto loser;
+ ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ goto loser;
}
if (ssl_keylog_iob) {
- SECStatus extractRV = PK11_ExtractKeyValue(pms);
- if (extractRV == SECSuccess) {
- SECItem * keyData = PK11_GetKeyData(pms);
- if (keyData && keyData->data && keyData->len) {
+ SECStatus extractRV = PK11_ExtractKeyValue(pms);
+ if (extractRV == SECSuccess) {
+ SECItem *keyData = PK11_GetKeyData(pms);
+ if (keyData && keyData->data && keyData->len) {
#ifdef TRACE
- if (ssl_trace >= 100) {
- ssl_PrintBuf(ss, "Pre-Master Secret",
- keyData->data, keyData->len);
- }
+ if (ssl_trace >= 100) {
+ ssl_PrintBuf(ss, "Pre-Master Secret",
+ keyData->data, keyData->len);
+ }
#endif
- if (ssl_keylog_iob && enc_pms.len >= 8 && keyData->len == 48) {
- /* https://developer.mozilla.org/en/NSS_Key_Log_Format */
-
- /* There could be multiple, concurrent writers to the
- * keylog, so we have to do everything in a single call to
- * fwrite. */
- char buf[4 + 8*2 + 1 + 48*2 + 1];
-
- strcpy(buf, "RSA ");
- hexEncode(buf + 4, enc_pms.data, 8);
- buf[20] = ' ';
- hexEncode(buf + 21, keyData->data, 48);
- buf[sizeof(buf) - 1] = '\n';
-
- fwrite(buf, sizeof(buf), 1, ssl_keylog_iob);
- fflush(ssl_keylog_iob);
- }
- }
- }
+ if (ssl_keylog_iob && enc_pms.len >= 8 && keyData->len == 48) {
+ /* https://developer.mozilla.org/en/NSS_Key_Log_Format */
+
+ /* There could be multiple, concurrent writers to the
+ * keylog, so we have to do everything in a single call to
+ * fwrite. */
+ char buf[4 + 8 * 2 + 1 + 48 * 2 + 1];
+
+ strcpy(buf, "RSA ");
+ hexEncode(buf + 4, enc_pms.data, 8);
+ buf[20] = ' ';
+ hexEncode(buf + 21, keyData->data, 48);
+ buf[sizeof(buf) - 1] = '\n';
+
+ fwrite(buf, sizeof(buf), 1, ssl_keylog_iob);
+ fflush(ssl_keylog_iob);
+ }
+ }
+ }
}
- rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
- isTLS ? enc_pms.len + 2 : enc_pms.len);
+ rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
+ isTLS ? enc_pms.len + 2
+ : enc_pms.len);
if (rv != SECSuccess) {
- goto loser; /* err set by ssl3_AppendHandshake* */
+ goto loser; /* err set by ssl3_AppendHandshake* */
}
if (isTLS) {
- rv = ssl3_AppendHandshakeVariable(ss, enc_pms.data, enc_pms.len, 2);
+ rv = ssl3_AppendHandshakeVariable(ss, enc_pms.data, enc_pms.len, 2);
} else {
- rv = ssl3_AppendHandshake(ss, enc_pms.data, enc_pms.len);
+ rv = ssl3_AppendHandshake(ss, enc_pms.data, enc_pms.len);
}
if (rv != SECSuccess) {
- goto loser; /* err set by ssl3_AppendHandshake* */
+ goto loser; /* err set by ssl3_AppendHandshake* */
}
rv = ssl3_InitPendingCipherSpec(ss, pms);
@@ -6277,18 +6412,18 @@ sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
pms = NULL;
if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
- goto loser;
+ ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ goto loser;
}
rv = SECSuccess;
loser:
if (enc_pms.data != NULL) {
- PORT_Free(enc_pms.data);
+ PORT_Free(enc_pms.data);
}
if (pms != NULL) {
- PK11_FreeSymKey(pms);
+ PK11_FreeSymKey(pms);
}
return rv;
}
@@ -6296,27 +6431,27 @@ loser:
/* Called from ssl3_SendClientKeyExchange(). */
/* Presently, this always uses PKCS11. There is no bypass for this. */
static SECStatus
-sendDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
+sendDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey)
{
- PK11SymKey * pms = NULL;
- SECStatus rv = SECFailure;
- PRBool isTLS;
- CK_MECHANISM_TYPE target;
+ PK11SymKey *pms = NULL;
+ SECStatus rv = SECFailure;
+ PRBool isTLS;
+ CK_MECHANISM_TYPE target;
- SECKEYDHParams dhParam; /* DH parameters */
- SECKEYPublicKey *pubKey = NULL; /* Ephemeral DH key */
- SECKEYPrivateKey *privKey = NULL; /* Ephemeral DH key */
+ SECKEYDHParams dhParam; /* DH parameters */
+ SECKEYPublicKey *pubKey = NULL; /* Ephemeral DH key */
+ SECKEYPrivateKey *privKey = NULL; /* Ephemeral DH key */
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
/* Copy DH parameters from server key */
if (svrPubKey->keyType != dhKey) {
- PORT_SetError(SEC_ERROR_BAD_KEY);
- goto loser;
+ PORT_SetError(SEC_ERROR_BAD_KEY);
+ goto loser;
}
dhParam.prime.data = svrPubKey->u.dh.prime.data;
dhParam.prime.len = svrPubKey->u.dh.prime.len;
@@ -6326,43 +6461,45 @@ sendDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
/* Generate ephemeral DH keypair */
privKey = SECKEY_CreateDHPrivateKey(&dhParam, &pubKey, NULL);
if (!privKey || !pubKey) {
- ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
- rv = SECFailure;
- goto loser;
+ ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
+ rv = SECFailure;
+ goto loser;
}
PRINT_BUF(50, (ss, "DH public value:",
- pubKey->u.dh.publicValue.data,
- pubKey->u.dh.publicValue.len));
+ pubKey->u.dh.publicValue.data,
+ pubKey->u.dh.publicValue.len));
- if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
- else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
+ if (isTLS)
+ target = CKM_TLS_MASTER_KEY_DERIVE_DH;
+ else
+ target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
/* Determine the PMS */
pms = PK11_PubDerive(privKey, svrPubKey, PR_FALSE, NULL, NULL,
- CKM_DH_PKCS_DERIVE, target, CKA_DERIVE, 0, NULL);
+ CKM_DH_PKCS_DERIVE, target, CKA_DERIVE, 0, NULL);
if (pms == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
- goto loser;
+ ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ goto loser;
}
SECKEY_DestroyPrivateKey(privKey);
privKey = NULL;
- rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
- pubKey->u.dh.publicValue.len + 2);
+ rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
+ pubKey->u.dh.publicValue.len + 2);
if (rv != SECSuccess) {
- goto loser; /* err set by ssl3_AppendHandshake* */
+ goto loser; /* err set by ssl3_AppendHandshake* */
}
- rv = ssl3_AppendHandshakeVariable(ss,
- pubKey->u.dh.publicValue.data,
- pubKey->u.dh.publicValue.len, 2);
+ rv = ssl3_AppendHandshakeVariable(ss,
+ pubKey->u.dh.publicValue.data,
+ pubKey->u.dh.publicValue.len, 2);
SECKEY_DestroyPublicKey(pubKey);
pubKey = NULL;
if (rv != SECSuccess) {
- goto loser; /* err set by ssl3_AppendHandshake* */
+ goto loser; /* err set by ssl3_AppendHandshake* */
}
rv = ssl3_InitPendingCipherSpec(ss, pms);
@@ -6370,47 +6507,46 @@ sendDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
pms = NULL;
if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
- goto loser;
+ ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ goto loser;
}
rv = SECSuccess;
loser:
- if(pms) PK11_FreeSymKey(pms);
- if(privKey) SECKEY_DestroyPrivateKey(privKey);
- if(pubKey) SECKEY_DestroyPublicKey(pubKey);
+ if (pms)
+ PK11_FreeSymKey(pms);
+ if (privKey)
+ SECKEY_DestroyPrivateKey(privKey);
+ if (pubKey)
+ SECKEY_DestroyPublicKey(pubKey);
return rv;
}
-
-
-
-
/* Called from ssl3_HandleServerHelloDone(). */
static SECStatus
ssl3_SendClientKeyExchange(sslSocket *ss)
{
- SECKEYPublicKey * serverKey = NULL;
- SECStatus rv = SECFailure;
- PRBool isTLS;
+ SECKEYPublicKey *serverKey = NULL;
+ SECStatus rv = SECFailure;
+ PRBool isTLS;
SSL_TRC(3, ("%d: SSL3[%d]: send client_key_exchange handshake",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ss->sec.peerKey == NULL) {
- serverKey = CERT_ExtractPublicKey(ss->sec.peerCert);
- if (serverKey == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
- return SECFailure;
- }
+ serverKey = CERT_ExtractPublicKey(ss->sec.peerCert);
+ if (serverKey == NULL) {
+ ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
+ return SECFailure;
+ }
} else {
- serverKey = ss->sec.peerKey;
- ss->sec.peerKey = NULL; /* we're done with it now */
+ serverKey = ss->sec.peerKey;
+ ss->sec.peerKey = NULL; /* we're done with it now */
}
isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
@@ -6419,144 +6555,166 @@ ssl3_SendClientKeyExchange(sslSocket *ss)
unsigned int keyLen = SECKEY_PublicKeyStrengthInBits(serverKey);
if (keyLen > ss->ssl3.hs.kea_def->key_size_limit) {
- if (isTLS)
- (void)SSL3_SendAlert(ss, alert_fatal, export_restriction);
- else
- (void)ssl3_HandshakeFailure(ss);
- PORT_SetError(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED);
- goto loser;
- }
+ if (isTLS)
+ (void)SSL3_SendAlert(ss, alert_fatal, export_restriction);
+ else
+ (void)ssl3_HandshakeFailure(ss);
+ PORT_SetError(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED);
+ goto loser;
+ }
}
- ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
+ ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(serverKey);
switch (ss->ssl3.hs.kea_def->exchKeyType) {
- case kt_rsa:
- rv = sendRSAClientKeyExchange(ss, serverKey);
- break;
+ case kt_rsa:
+ rv = sendRSAClientKeyExchange(ss, serverKey);
+ break;
- case kt_dh:
- rv = sendDHClientKeyExchange(ss, serverKey);
- break;
+ case kt_dh:
+ rv = sendDHClientKeyExchange(ss, serverKey);
+ break;
#ifndef NSS_DISABLE_ECC
- case kt_ecdh:
- rv = ssl3_SendECDHClientKeyExchange(ss, serverKey);
- break;
+ case kt_ecdh:
+ rv = ssl3_SendECDHClientKeyExchange(ss, serverKey);
+ break;
#endif /* NSS_DISABLE_ECC */
- default:
- /* got an unknown or unsupported Key Exchange Algorithm. */
- SEND_ALERT
- PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
- break;
+ default:
+ /* got an unknown or unsupported Key Exchange Algorithm. */
+ SEND_ALERT
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
+ break;
}
SSL_TRC(3, ("%d: SSL3[%d]: DONE sending client_key_exchange",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
loser:
- if (serverKey)
- SECKEY_DestroyPublicKey(serverKey);
- return rv; /* err code already set. */
+ if (serverKey)
+ SECKEY_DestroyPublicKey(serverKey);
+ return rv; /* err code already set. */
}
/* Called from ssl3_HandleServerHelloDone(). */
-static SECStatus
-ssl3_SendCertificateVerify(sslSocket *ss)
-{
- SECStatus rv = SECFailure;
- PRBool isTLS;
- PRBool isTLS12;
- SECItem buf = {siBuffer, NULL, 0};
- SSL3Hashes hashes;
- KeyType keyType;
- unsigned int len;
+SECStatus
+ssl3_SendCertificateVerify(sslSocket *ss, SECKEYPrivateKey *privKey)
+{
+ SECStatus rv = SECFailure;
+ PRBool isTLS;
+ PRBool isTLS12;
+ PRBool isTLS13;
+ SECItem buf = { siBuffer, NULL, 0 };
+ SSL3Hashes hashes;
+ KeyType keyType;
+ unsigned int len;
SSLSignatureAndHashAlg sigAndHash;
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
SSL_TRC(3, ("%d: SSL3[%d]: send certificate_verify handshake",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
+ isTLS13 = (PRBool)(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
ssl_GetSpecReadLock(ss);
if (ss->ssl3.hs.hashType == handshake_hash_single &&
- ss->ssl3.hs.backupHash) {
- rv = ssl3_ComputeBackupHandshakeHashes(ss, &hashes);
- PORT_Assert(!ss->ssl3.hs.backupHash);
+ ss->ssl3.hs.backupHash) {
+ PORT_Assert(!ss->ssl3.hs.backupHash);
+ PORT_Assert(!isTLS13);
+ /* TODO(ekr@rtfm.com): The backup hash here contains a SHA-1 hash
+ * but in TLS 1.3, we always sign H(Context, Hash(handshake))
+ * where:
+ *
+ * H is the negotiated signature hash and
+ * Hash is the cipher-suite specific handshake hash
+ * Generally this means that Hash is SHA-256.
+ *
+ * We need code to negotiate H but the current code is a mess.
+ */
+ if (isTLS13) {
+ /* rv is already set to SECFailure */
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ } else {
+ rv = ssl3_ComputeBackupHandshakeHashes(ss, &hashes);
+ }
} else {
- rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0);
+ ssl3CipherSpec *spec;
+
+ if (isTLS13) {
+ /* In TLS 1.3, we are already encrypted. */
+ spec = ss->ssl3.cwSpec;
+ } else {
+ spec = ss->ssl3.pwSpec;
+ }
+
+ rv = ssl3_ComputeHandshakeHashes(ss, spec, &hashes, 0);
}
ssl_ReleaseSpecReadLock(ss);
if (rv != SECSuccess) {
- goto done; /* err code was set by ssl3_ComputeHandshakeHashes */
+ goto done; /* err code was set by ssl3_ComputeHandshakeHashes */
+ }
+
+ if (isTLS13) {
+ rv = tls13_AddContextToHashes(ss, &hashes, tls13_GetHash(ss), PR_TRUE);
+ if (rv != SECSuccess) {
+ goto done; /* err code was set by tls13_AddContextToHashes */
+ }
}
isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
- if (ss->ssl3.platformClientKey) {
-#ifdef NSS_PLATFORM_CLIENT_AUTH
- keyType = CERT_GetCertKeyType(
- &ss->ssl3.clientCertificate->subjectPublicKeyInfo);
- rv = ssl3_PlatformSignHashes(
- &hashes, ss->ssl3.platformClientKey, &buf, isTLS, keyType);
- ssl_FreePlatformKey(ss->ssl3.platformClientKey);
- ss->ssl3.platformClientKey = (PlatformKey)NULL;
-#endif /* NSS_PLATFORM_CLIENT_AUTH */
- } else {
- keyType = ss->ssl3.clientPrivateKey->keyType;
- rv = ssl3_SignHashes(&hashes, ss->ssl3.clientPrivateKey, &buf, isTLS);
- if (rv == SECSuccess) {
- PK11SlotInfo * slot;
- sslSessionID * sid = ss->sec.ci.sid;
-
- /* Remember the info about the slot that did the signing.
- ** Later, when doing an SSL restart handshake, verify this.
- ** These calls are mere accessors, and can't fail.
- */
- slot = PK11_GetSlotFromPrivateKey(ss->ssl3.clientPrivateKey);
- sid->u.ssl3.clAuthSeries = PK11_GetSlotSeries(slot);
- sid->u.ssl3.clAuthSlotID = PK11_GetSlotID(slot);
- sid->u.ssl3.clAuthModuleID = PK11_GetModuleID(slot);
- sid->u.ssl3.clAuthValid = PR_TRUE;
- PK11_FreeSlot(slot);
- }
- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
- ss->ssl3.clientPrivateKey = NULL;
+
+ keyType = privKey->keyType;
+ rv = ssl3_SignHashes(&hashes, privKey, &buf, isTLS);
+ if (rv == SECSuccess && !ss->sec.isServer) {
+ /* Remember the info about the slot that did the signing.
+ ** Later, when doing an SSL restart handshake, verify this.
+ ** These calls are mere accessors, and can't fail.
+ */
+ PK11SlotInfo *slot;
+ sslSessionID *sid = ss->sec.ci.sid;
+
+ slot = PK11_GetSlotFromPrivateKey(privKey);
+ sid->u.ssl3.clAuthSeries = PK11_GetSlotSeries(slot);
+ sid->u.ssl3.clAuthSlotID = PK11_GetSlotID(slot);
+ sid->u.ssl3.clAuthModuleID = PK11_GetModuleID(slot);
+ sid->u.ssl3.clAuthValid = PR_TRUE;
+ PK11_FreeSlot(slot);
}
if (rv != SECSuccess) {
- goto done; /* err code was set by ssl3_SignHashes */
+ goto done; /* err code was set by ssl3_SignHashes */
}
len = buf.len + 2 + (isTLS12 ? 2 : 0);
rv = ssl3_AppendHandshakeHeader(ss, certificate_verify, len);
if (rv != SECSuccess) {
- goto done; /* error code set by AppendHandshake */
+ goto done; /* error code set by AppendHandshake */
}
if (isTLS12) {
- rv = ssl3_TLSSignatureAlgorithmForKeyType(keyType,
+ rv = ssl3_TLSSignatureAlgorithmForKeyType(keyType,
&sigAndHash.sigAlg);
- if (rv != SECSuccess) {
- goto done;
- }
+ if (rv != SECSuccess) {
+ goto done;
+ }
sigAndHash.hashAlg = hashes.hashAlg;
- rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
- if (rv != SECSuccess) {
- goto done; /* err set by AppendHandshake. */
- }
+ rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
+ if (rv != SECSuccess) {
+ goto done; /* err set by AppendHandshake. */
+ }
}
rv = ssl3_AppendHandshakeVariable(ss, buf.data, buf.len, 2);
if (rv != SECSuccess) {
- goto done; /* error code set by AppendHandshake */
+ goto done; /* error code set by AppendHandshake */
}
done:
if (buf.data)
- PORT_Free(buf.data);
+ PORT_Free(buf.data);
return rv;
}
@@ -6567,177 +6725,207 @@ done:
static SECStatus
ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
- sslSessionID *sid = ss->sec.ci.sid;
- PRInt32 temp; /* allow for consume number failure */
- PRBool suite_found = PR_FALSE;
- int i;
- int errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
- SECStatus rv;
- SECItem sidBytes = {siBuffer, NULL, 0};
- PRBool sid_match;
- PRBool isTLS = PR_FALSE;
- SSL3AlertDescription desc = illegal_parameter;
+ sslSessionID *sid = ss->sec.ci.sid;
+ PRInt32 temp; /* allow for consume number failure */
+ PRBool suite_found = PR_FALSE;
+ int i;
+ int errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
+ SECStatus rv;
+ SECItem sidBytes = { siBuffer, NULL, 0 };
+ PRBool sid_match;
+ PRBool isTLS = PR_FALSE;
+ SSL3AlertDescription desc = illegal_parameter;
SSL3ProtocolVersion version;
+ SSL3ProtocolVersion downgradeCheckVersion;
SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello handshake",
- SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( ss->ssl3.initialized );
+ SSL_GETPID(), ss->fd));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->ssl3.initialized);
if (ss->ssl3.hs.ws != wait_server_hello) {
errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO;
- desc = unexpected_message;
- goto alert_loser;
+ desc = unexpected_message;
+ goto alert_loser;
}
/* clean up anything left from previous handshake. */
if (ss->ssl3.clientCertChain != NULL) {
- CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
- ss->ssl3.clientCertChain = NULL;
+ CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
+ ss->ssl3.clientCertChain = NULL;
}
if (ss->ssl3.clientCertificate != NULL) {
- CERT_DestroyCertificate(ss->ssl3.clientCertificate);
- ss->ssl3.clientCertificate = NULL;
+ CERT_DestroyCertificate(ss->ssl3.clientCertificate);
+ ss->ssl3.clientCertificate = NULL;
}
if (ss->ssl3.clientPrivateKey != NULL) {
- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
- ss->ssl3.clientPrivateKey = NULL;
- }
-#ifdef NSS_PLATFORM_CLIENT_AUTH
- if (ss->ssl3.platformClientKey) {
- ssl_FreePlatformKey(ss->ssl3.platformClientKey);
- ss->ssl3.platformClientKey = (PlatformKey)NULL;
+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
+ ss->ssl3.clientPrivateKey = NULL;
}
-#endif /* NSS_PLATFORM_CLIENT_AUTH */
if (ss->ssl3.channelID != NULL) {
- SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
- ss->ssl3.channelID = NULL;
+ SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
+ ss->ssl3.channelID = NULL;
}
if (ss->ssl3.channelIDPub != NULL) {
- SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
- ss->ssl3.channelIDPub = NULL;
+ SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
+ ss->ssl3.channelIDPub = NULL;
}
temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
if (temp < 0) {
- goto loser; /* alert has been sent */
+ goto loser; /* alert has been sent */
}
version = (SSL3ProtocolVersion)temp;
if (IS_DTLS(ss)) {
- /* RFC 4347 required that you verify that the server versions
- * match (Section 4.2.1) in the HelloVerifyRequest and the
- * ServerHello.
- *
- * RFC 6347 suggests (SHOULD) that servers always use 1.0
- * in HelloVerifyRequest and allows the versions not to match,
- * especially when 1.2 is being negotiated.
- *
- * Therefore we do not check for matching here.
- */
- version = dtls_DTLSVersionToTLSVersion(version);
- if (version == 0) { /* Insane version number */
+ /* RFC 4347 required that you verify that the server versions
+ * match (Section 4.2.1) in the HelloVerifyRequest and the
+ * ServerHello.
+ *
+ * RFC 6347 suggests (SHOULD) that servers always use 1.0
+ * in HelloVerifyRequest and allows the versions not to match,
+ * especially when 1.2 is being negotiated.
+ *
+ * Therefore we do not check for matching here.
+ */
+ version = dtls_DTLSVersionToTLSVersion(version);
+ if (version == 0) { /* Insane version number */
goto alert_loser;
- }
+ }
}
rv = ssl3_NegotiateVersion(ss, version, PR_FALSE);
if (rv != SECSuccess) {
- desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
- : handshake_failure;
- errCode = SSL_ERROR_UNSUPPORTED_VERSION;
- goto alert_loser;
+ desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
+ : handshake_failure;
+ errCode = SSL_ERROR_UNSUPPORTED_VERSION;
+ goto alert_loser;
}
ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0);
rv = ssl3_InitHandshakeHashes(ss);
if (rv != SECSuccess) {
- desc = internal_error;
- errCode = PORT_GetError();
- goto alert_loser;
+ desc = internal_error;
+ errCode = PORT_GetError();
+ goto alert_loser;
}
rv = ssl3_ConsumeHandshake(
- ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH, &b, &length);
+ ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH, &b, &length);
if (rv != SECSuccess) {
- goto loser; /* alert has been sent */
+ goto loser; /* alert has been sent */
}
- rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length);
- if (rv != SECSuccess) {
- goto loser; /* alert has been sent */
+ /* Check the ServerHello.random per
+ * [draft-ietf-tls-tls13-11 Section 6.3.1.1].
+ *
+ * TLS 1.3 clients receiving a TLS 1.2 or below ServerHello MUST check
+ * that the top eight octets are not equal to either of these values.
+ * TLS 1.2 clients SHOULD also perform this check if the ServerHello
+ * indicates TLS 1.1 or below. If a match is found the client MUST
+ * abort the handshake with a fatal "illegal_parameter" alert.
+ */
+ downgradeCheckVersion = ss->ssl3.downgradeCheckVersion ? ss->ssl3.downgradeCheckVersion
+ : ss->vrange.max;
+
+ if (downgradeCheckVersion >= SSL_LIBRARY_VERSION_TLS_1_2 &&
+ downgradeCheckVersion > ss->version) {
+ if (!PORT_Memcmp(ss->ssl3.hs.server_random.rand,
+ tls13_downgrade_random,
+ sizeof(tls13_downgrade_random)) ||
+ !PORT_Memcmp(ss->ssl3.hs.server_random.rand,
+ tls12_downgrade_random,
+ sizeof(tls12_downgrade_random))) {
+ desc = illegal_parameter;
+ errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
+ goto alert_loser;
+ }
}
- if (sidBytes.len > SSL3_SESSIONID_BYTES) {
- if (isTLS)
- desc = decode_error;
- goto alert_loser; /* malformed. */
+
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length);
+ if (rv != SECSuccess) {
+ goto loser; /* alert has been sent */
+ }
+ if (sidBytes.len > SSL3_SESSIONID_BYTES) {
+ if (isTLS)
+ desc = decode_error;
+ goto alert_loser; /* malformed. */
+ }
}
/* find selected cipher suite in our list. */
temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
if (temp < 0) {
- goto loser; /* alert has been sent */
+ goto loser; /* alert has been sent */
}
ssl3_config_match_init(ss);
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
- ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
- if (temp == suite->cipher_suite) {
- SSLVersionRange vrange = {ss->version, ss->version};
- if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss)) {
- /* config_match already checks whether the cipher suite is
- * acceptable for the version, but the check is repeated here
- * in order to give a more precise error code. */
- if (!ssl3_CipherSuiteAllowedForVersionRange(temp, &vrange)) {
- desc = handshake_failure;
- errCode = SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION;
- goto alert_loser;
- }
-
- break; /* failure */
- }
-
- suite_found = PR_TRUE;
- break; /* success */
- }
+ ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
+ if (temp == suite->cipher_suite) {
+ SSLVersionRange vrange = { ss->version, ss->version };
+ if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss)) {
+ /* config_match already checks whether the cipher suite is
+ * acceptable for the version, but the check is repeated here
+ * in order to give a more precise error code. */
+ if (!ssl3_CipherSuiteAllowedForVersionRange(temp, &vrange)) {
+ desc = handshake_failure;
+ errCode = SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION;
+ goto alert_loser;
+ }
+
+ break; /* failure */
+ }
+
+ suite_found = PR_TRUE;
+ break; /* success */
+ }
}
if (!suite_found) {
- desc = handshake_failure;
- errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
- goto alert_loser;
+ desc = handshake_failure;
+ errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
+ goto alert_loser;
}
ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)temp;
- ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef((ssl3CipherSuite)temp);
+ ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef((ssl3CipherSuite)temp);
ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
PORT_Assert(ss->ssl3.hs.suite_def);
if (!ss->ssl3.hs.suite_def) {
- PORT_SetError(errCode = SEC_ERROR_LIBRARY_FAILURE);
- goto loser; /* we don't send alerts for our screw-ups. */
+ errCode = SEC_ERROR_LIBRARY_FAILURE;
+ PORT_SetError(errCode);
+ goto loser; /* we don't send alerts for our screw-ups. */
}
- /* find selected compression method in our list. */
- temp = ssl3_ConsumeHandshakeNumber(ss, 1, &b, &length);
- if (temp < 0) {
- goto loser; /* alert has been sent */
- }
- suite_found = PR_FALSE;
- for (i = 0; i < compressionMethodsCount; i++) {
- if (temp == compressions[i]) {
- if (!compressionEnabled(ss, compressions[i])) {
- break; /* failure */
- }
- suite_found = PR_TRUE;
- break; /* success */
- }
- }
- if (!suite_found) {
- desc = handshake_failure;
- errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP;
- goto alert_loser;
+ ss->ssl3.hs.kea_def = &kea_defs[ss->ssl3.hs.suite_def->key_exchange_alg];
+
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ /* find selected compression method in our list. */
+ temp = ssl3_ConsumeHandshakeNumber(ss, 1, &b, &length);
+ if (temp < 0) {
+ goto loser; /* alert has been sent */
+ }
+ suite_found = PR_FALSE;
+ for (i = 0; i < compressionMethodsCount; i++) {
+ if (temp == compressions[i]) {
+ if (!compressionEnabled(ss, compressions[i])) {
+ break; /* failure */
+ }
+ suite_found = PR_TRUE;
+ break; /* success */
+ }
+ }
+ if (!suite_found) {
+ desc = handshake_failure;
+ errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP;
+ goto alert_loser;
+ }
+ ss->ssl3.hs.compression = (SSLCompressionMethod)temp;
+ } else {
+ ss->ssl3.hs.compression = ssl_compression_null;
}
- ss->ssl3.hs.compression = (SSLCompressionMethod)temp;
/* Note that if !isTLS and the extra stuff is not extensions, we
* do NOT goto alert_loser.
@@ -6749,36 +6937,37 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
* extension in SSL 3.0.
*/
if (length != 0) {
- SECItem extensions;
- rv = ssl3_ConsumeHandshakeVariable(ss, &extensions, 2, &b, &length);
- if (rv != SECSuccess || length != 0) {
- if (isTLS)
- goto alert_loser;
- } else {
- rv = ssl3_HandleHelloExtensions(ss, &extensions.data,
- &extensions.len);
- if (rv != SECSuccess)
- goto alert_loser;
- }
- }
- if ((ss->opt.requireSafeNegotiation ||
+ SECItem extensions;
+ rv = ssl3_ConsumeHandshakeVariable(ss, &extensions, 2, &b, &length);
+ if (rv != SECSuccess || length != 0) {
+ if (isTLS)
+ goto alert_loser;
+ } else {
+ rv = ssl3_HandleHelloExtensions(ss, &extensions.data,
+ &extensions.len, server_hello);
+ if (rv != SECSuccess)
+ goto alert_loser;
+ }
+ }
+ if ((ss->opt.requireSafeNegotiation ||
(ss->firstHsDone && (ss->peerRequestedProtection ||
- ss->opt.enableRenegotiation == SSL_RENEGOTIATE_REQUIRES_XTN))) &&
- !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
- desc = handshake_failure;
- errCode = ss->firstHsDone ? SSL_ERROR_RENEGOTIATION_NOT_ALLOWED
- : SSL_ERROR_UNSAFE_NEGOTIATION;
- goto alert_loser;
+ ss->opt.enableRenegotiation ==
+ SSL_RENEGOTIATE_REQUIRES_XTN))) &&
+ !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
+ desc = handshake_failure;
+ errCode = ss->firstHsDone ? SSL_ERROR_RENEGOTIATION_NOT_ALLOWED
+ : SSL_ERROR_UNSAFE_NEGOTIATION;
+ goto alert_loser;
}
/* Any errors after this point are not "malformed" errors. */
- desc = handshake_failure;
+ desc = handshake_failure;
/* we need to call ssl3_SetupPendingCipherSpec here so we can check the
* key exchange algorithm. */
rv = ssl3_SetupPendingCipherSpec(ss);
if (rv != SECSuccess) {
- goto alert_loser; /* error code is set. */
+ goto alert_loser; /* error code is set. */
}
/* We may or may not have sent a session id, we may get one back or
@@ -6787,156 +6976,159 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
* Don't consider failure to find a matching SID an error.
*/
sid_match = (PRBool)(sidBytes.len > 0 &&
- sidBytes.len == sid->u.ssl3.sessionIDLength &&
- !PORT_Memcmp(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len));
+ sidBytes.len ==
+ sid->u.ssl3.sessionIDLength &&
+ !PORT_Memcmp(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len));
if (sid_match &&
- sid->version == ss->version &&
- sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite) do {
- ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
-
- SECItem wrappedMS; /* wrapped master secret. */
-
- /* [draft-ietf-tls-session-hash-06; Section 5.3]
- *
- * o If the original session did not use the "extended_master_secret"
- * extension but the new ServerHello contains the extension, the
- * client MUST abort the handshake.
- */
- if (!sid->u.ssl3.keys.extendedMasterSecretUsed &&
- ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
- errCode = SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET;
- goto alert_loser;
- }
-
- /*
- * o If the original session used an extended master secret but the new
- * ServerHello does not contain the "extended_master_secret"
- * extension, the client SHOULD abort the handshake.
- *
- * TODO(ekr@rtfm.com): Add option to refuse to resume when EMS is not
- * used at all (bug 1176526).
- */
- if (sid->u.ssl3.keys.extendedMasterSecretUsed &&
- !ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
- errCode = SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET;
- goto alert_loser;
- }
+ sid->version == ss->version &&
+ sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite)
+ do {
+ ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
+
+ SECItem wrappedMS; /* wrapped master secret. */
+
+ /* [draft-ietf-tls-session-hash-06; Section 5.3]
+ *
+ * o If the original session did not use the "extended_master_secret"
+ * extension but the new ServerHello contains the extension, the
+ * client MUST abort the handshake.
+ */
+ if (!sid->u.ssl3.keys.extendedMasterSecretUsed &&
+ ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
+ errCode = SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET;
+ goto alert_loser;
+ }
- ss->sec.authAlgorithm = sid->authAlgorithm;
- ss->sec.authKeyBits = sid->authKeyBits;
- ss->sec.keaType = sid->keaType;
- ss->sec.keaKeyBits = sid->keaKeyBits;
+ /*
+ * o If the original session used an extended master secret but the new
+ * ServerHello does not contain the "extended_master_secret"
+ * extension, the client SHOULD abort the handshake.
+ *
+ * TODO(ekr@rtfm.com): Add option to refuse to resume when EMS is not
+ * used at all (bug 1176526).
+ */
+ if (sid->u.ssl3.keys.extendedMasterSecretUsed &&
+ !ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
+ errCode = SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET;
+ goto alert_loser;
+ }
- /* 3 cases here:
- * a) key is wrapped (implies using PKCS11)
- * b) key is unwrapped, but we're still using PKCS11
- * c) key is unwrapped, and we're bypassing PKCS11.
- */
- if (sid->u.ssl3.keys.msIsWrapped) {
- PK11SlotInfo *slot;
- PK11SymKey * wrapKey; /* wrapping key */
- CK_FLAGS keyFlags = 0;
+ ss->sec.authAlgorithm = sid->authAlgorithm;
+ ss->sec.authKeyBits = sid->authKeyBits;
+ ss->sec.keaType = sid->keaType;
+ ss->sec.keaKeyBits = sid->keaKeyBits;
+
+ /* 3 cases here:
+ * a) key is wrapped (implies using PKCS11)
+ * b) key is unwrapped, but we're still using PKCS11
+ * c) key is unwrapped, and we're bypassing PKCS11.
+ */
+ if (sid->u.ssl3.keys.msIsWrapped) {
+ PK11SlotInfo *slot;
+ PK11SymKey *wrapKey; /* wrapping key */
+ CK_FLAGS keyFlags = 0;
#ifndef NO_PKCS11_BYPASS
- if (ss->opt.bypassPKCS11) {
- /* we cannot restart a non-bypass session in a
- ** bypass socket.
- */
- break;
- }
+ if (ss->opt.bypassPKCS11) {
+ /* we cannot restart a non-bypass session in a
+ ** bypass socket.
+ */
+ break;
+ }
#endif
- /* unwrap master secret with PKCS11 */
- slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,
- sid->u.ssl3.masterSlotID);
- if (slot == NULL) {
- break; /* not considered an error. */
- }
- if (!PK11_IsPresent(slot)) {
- PK11_FreeSlot(slot);
- break; /* not considered an error. */
- }
- wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex,
- sid->u.ssl3.masterWrapMech,
- sid->u.ssl3.masterWrapSeries,
- ss->pkcs11PinArg);
- PK11_FreeSlot(slot);
- if (wrapKey == NULL) {
- break; /* not considered an error. */
- }
-
- if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
- keyFlags = CKF_SIGN | CKF_VERIFY;
- }
-
- wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
- wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
- pwSpec->master_secret =
- PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech,
- NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
- CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags);
- errCode = PORT_GetError();
- PK11_FreeSymKey(wrapKey);
- if (pwSpec->master_secret == NULL) {
- break; /* errorCode set just after call to UnwrapSymKey. */
- }
+ /* unwrap master secret with PKCS11 */
+ slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,
+ sid->u.ssl3.masterSlotID);
+ if (slot == NULL) {
+ break; /* not considered an error. */
+ }
+ if (!PK11_IsPresent(slot)) {
+ PK11_FreeSlot(slot);
+ break; /* not considered an error. */
+ }
+ wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex,
+ sid->u.ssl3.masterWrapMech,
+ sid->u.ssl3.masterWrapSeries,
+ ss->pkcs11PinArg);
+ PK11_FreeSlot(slot);
+ if (wrapKey == NULL) {
+ break; /* not considered an error. */
+ }
+
+ if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
+ keyFlags =
+ CKF_SIGN | CKF_VERIFY;
+ }
+
+ wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
+ wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
+ pwSpec->master_secret =
+ PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech,
+ NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
+ CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags);
+ errCode = PORT_GetError();
+ PK11_FreeSymKey(wrapKey);
+ if (pwSpec->master_secret == NULL) {
+ break; /* errorCode set just after call to UnwrapSymKey. */
+ }
#ifndef NO_PKCS11_BYPASS
- } else if (ss->opt.bypassPKCS11) {
- /* MS is not wrapped */
- wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
- wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
- memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len);
- pwSpec->msItem.data = pwSpec->raw_master_secret;
- pwSpec->msItem.len = wrappedMS.len;
+ } else if (ss->opt.bypassPKCS11) {
+ /* MS is not wrapped */
+ wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
+ wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
+ memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len);
+ pwSpec->msItem.data = pwSpec->raw_master_secret;
+ pwSpec->msItem.len = wrappedMS.len;
#endif
- } else {
- /* We CAN restart a bypass session in a non-bypass socket. */
- /* need to import the raw master secret to session object */
- PK11SlotInfo *slot = PK11_GetInternalSlot();
- wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
- wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
- pwSpec->master_secret =
- PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE,
- PK11_OriginUnwrap, CKA_ENCRYPT,
- &wrappedMS, NULL);
- PK11_FreeSlot(slot);
- if (pwSpec->master_secret == NULL) {
- break;
- }
- }
-
- /* Got a Match */
- SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_hits );
-
- /* If we sent a session ticket, then this is a stateless resume. */
- if (ss->xtnData.sentSessionTicketInClientHello)
- SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_stateless_resumes );
-
- if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
- ss->ssl3.hs.ws = wait_new_session_ticket;
- else
- ss->ssl3.hs.ws = wait_change_cipher;
-
- ss->ssl3.hs.isResuming = PR_TRUE;
-
- /* copy the peer cert from the SID */
- if (sid->peerCert != NULL) {
- ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
- ssl3_CopyPeerCertsFromSID(ss, sid);
- }
-
- /* NULL value for PMS because we are reusing the old MS */
- rv = ssl3_InitPendingCipherSpec(ss, NULL);
- if (rv != SECSuccess) {
- goto alert_loser; /* err code was set */
- }
- goto winner;
- } while (0);
+ } else {
+ /* We CAN restart a bypass session in a non-bypass socket. */
+ /* need to import the raw master secret to session object */
+ PK11SlotInfo *slot = PK11_GetInternalSlot();
+ wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
+ wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
+ pwSpec->master_secret =
+ PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE,
+ PK11_OriginUnwrap, CKA_ENCRYPT,
+ &wrappedMS, NULL);
+ PK11_FreeSlot(slot);
+ if (pwSpec->master_secret == NULL) {
+ break;
+ }
+ }
+
+ /* Got a Match */
+ SSL_AtomicIncrementLong(&ssl3stats.hsh_sid_cache_hits);
+
+ /* If we sent a session ticket, then this is a stateless resume. */
+ if (ss->xtnData.sentSessionTicketInClientHello)
+ SSL_AtomicIncrementLong(&ssl3stats.hsh_sid_stateless_resumes);
+
+ if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
+ ss->ssl3.hs.ws = wait_new_session_ticket;
+ else
+ ss->ssl3.hs.ws = wait_change_cipher;
+
+ ss->ssl3.hs.isResuming = PR_TRUE;
+
+ /* copy the peer cert from the SID */
+ if (sid->peerCert != NULL) {
+ ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
+ ssl3_CopyPeerCertsFromSID(ss, sid);
+ }
+
+ /* NULL value for PMS because we are reusing the old MS */
+ rv = ssl3_InitPendingCipherSpec(ss, NULL);
+ if (rv != SECSuccess) {
+ goto alert_loser; /* err code was set */
+ }
+ goto winner;
+ } while (0);
if (sid_match)
- SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_not_ok );
+ SSL_AtomicIncrementLong(&ssl3stats.hsh_sid_cache_not_ok);
else
- SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_misses );
+ SSL_AtomicIncrementLong(&ssl3stats.hsh_sid_cache_misses);
/* throw the old one away */
sid->u.ssl3.keys.resumable = PR_FALSE;
@@ -6947,7 +7139,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
/* get a new sid */
ss->sec.ci.sid = sid = ssl3_NewSessionID(ss, PR_FALSE);
if (sid == NULL) {
- goto alert_loser; /* memory error is set. */
+ goto alert_loser; /* memory error is set. */
}
sid->version = ss->version;
@@ -6955,19 +7147,27 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len);
sid->u.ssl3.keys.extendedMasterSecretUsed =
- ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn);
+ ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn);
/* Copy Signed Certificate Timestamps, if any. */
if (ss->xtnData.signedCertTimestamps.data) {
- rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.signedCertTimestamps,
- &ss->xtnData.signedCertTimestamps);
- if (rv != SECSuccess)
- goto loser;
+ rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.signedCertTimestamps,
+ &ss->xtnData.signedCertTimestamps);
+ if (rv != SECSuccess)
+ goto loser;
+ /* Clean up the temporary pointer to the handshake buffer. */
+ ss->xtnData.signedCertTimestamps.data = NULL;
+ ss->xtnData.signedCertTimestamps.len = 0;
}
ss->ssl3.hs.isResuming = PR_FALSE;
- if (ss->ssl3.hs.kea_def->signKeyType != sign_null) {
- /* All current cipher suites other than those with sign_null (i.e.,
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ rv = tls13_HandleServerKeyShare(ss);
+ if (rv != SECSuccess)
+ goto alert_loser;
+ TLS13_SET_HS_STATE(ss, wait_encrypted_extensions);
+ } else if (ss->ssl3.hs.kea_def->signKeyType != ssl_sign_null) {
+ /* All current cipher suites other than those with ssl_sign_null (i.e.,
* (EC)DH_anon_* suites) require a certificate, so use that signal. */
ss->ssl3.hs.ws = wait_server_cert;
} else {
@@ -6979,27 +7179,23 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
}
winner:
- /* Clean up the temporary pointer to the handshake buffer. */
- ss->xtnData.signedCertTimestamps.data = NULL;
- ss->xtnData.signedCertTimestamps.len = 0;
-
/* If we will need a ChannelID key then we make the callback now. This
* allows the handshake to be restarted cleanly if the callback returns
* SECWouldBlock. */
if (ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
- rv = ss->getChannelID(ss->getChannelIDArg, ss->fd,
- &ss->ssl3.channelIDPub, &ss->ssl3.channelID);
- if (rv == SECWouldBlock) {
- ssl3_SetAlwaysBlock(ss);
- return rv;
- }
- if (rv != SECSuccess ||
- ss->ssl3.channelIDPub == NULL ||
- ss->ssl3.channelID == NULL) {
- PORT_SetError(SSL_ERROR_GET_CHANNEL_ID_FAILED);
- desc = internal_error;
- goto alert_loser;
- }
+ rv = ss->getChannelID(ss->getChannelIDArg, ss->fd,
+ &ss->ssl3.channelIDPub, &ss->ssl3.channelID);
+ if (rv == SECWouldBlock) {
+ ssl3_SetAlwaysBlock(ss);
+ return rv;
+ }
+ if (rv != SECSuccess ||
+ ss->ssl3.channelIDPub == NULL ||
+ ss->ssl3.channelID == NULL) {
+ PORT_SetError(SSL_ERROR_GET_CHANNEL_ID_FAILED);
+ desc = internal_error;
+ goto alert_loser;
+ }
}
return SECSuccess;
@@ -7011,34 +7207,33 @@ loser:
/* Clean up the temporary pointer to the handshake buffer. */
ss->xtnData.signedCertTimestamps.data = NULL;
ss->xtnData.signedCertTimestamps.len = 0;
- errCode = ssl_MapLowLevelError(errCode);
+ ssl_MapLowLevelError(errCode);
return SECFailure;
}
-
-/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
- * ssl3 ServerKeyExchange message.
+/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered a
+ * complete ssl3 ServerKeyExchange message.
* Caller must hold Handshake and RecvBuf locks.
*/
static SECStatus
ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
- PLArenaPool * arena = NULL;
- SECKEYPublicKey *peerKey = NULL;
- PRBool isTLS, isTLS12;
- SECStatus rv;
- int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
- SSL3AlertDescription desc = illegal_parameter;
- SSL3Hashes hashes;
- SECItem signature = {siBuffer, NULL, 0};
+ PLArenaPool *arena = NULL;
+ SECKEYPublicKey *peerKey = NULL;
+ PRBool isTLS, isTLS12;
+ SECStatus rv;
+ int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
+ SSL3AlertDescription desc = illegal_parameter;
+ SSL3Hashes hashes;
+ SECItem signature = { siBuffer, NULL, 0 };
SSLSignatureAndHashAlg sigAndHash;
sigAndHash.hashAlg = ssl_hash_none;
SSL_TRC(3, ("%d: SSL3[%d]: handle server_key_exchange handshake",
- SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ SSL_GETPID(), ss->fd));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ss->ssl3.hs.ws != wait_server_key) {
errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH;
@@ -7051,228 +7246,228 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
switch (ss->ssl3.hs.kea_def->exchKeyType) {
- case kt_rsa: {
- SECItem modulus = {siBuffer, NULL, 0};
- SECItem exponent = {siBuffer, NULL, 0};
-
- rv = ssl3_ConsumeHandshakeVariable(ss, &modulus, 2, &b, &length);
- if (rv != SECSuccess) {
- goto loser; /* malformed. */
- }
- /* This exchange method is only used by export cipher suites.
- * Those are broken and so this code will eventually be removed. */
- if (SECKEY_BigIntegerBitLength(&modulus) < 512) {
- desc = isTLS ? insufficient_security : illegal_parameter;
- goto alert_loser;
+ case kt_rsa: {
+ SECItem modulus = { siBuffer, NULL, 0 };
+ SECItem exponent = { siBuffer, NULL, 0 };
+
+ rv = ssl3_ConsumeHandshakeVariable(ss, &modulus, 2, &b, &length);
+ if (rv != SECSuccess) {
+ goto loser; /* malformed. */
+ }
+ /* This exchange method is only used by export cipher suites.
+ * Those are broken and so this code will eventually be removed. */
+ if (SECKEY_BigIntegerBitLength(&modulus) < 512) {
+ desc = isTLS ? insufficient_security : illegal_parameter;
+ goto alert_loser;
+ }
+ rv = ssl3_ConsumeHandshakeVariable(ss, &exponent, 2, &b, &length);
+ if (rv != SECSuccess) {
+ goto loser; /* malformed. */
+ }
+ if (isTLS12) {
+ rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
+ &sigAndHash);
+ if (rv != SECSuccess) {
+ goto loser; /* malformed or unsupported. */
+ }
+ rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(ss,
+ &sigAndHash, ss->sec.peerCert);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+ rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
+ if (rv != SECSuccess) {
+ goto loser; /* malformed. */
+ }
+ if (length != 0) {
+ if (isTLS)
+ desc =
+ decode_error;
+ goto alert_loser; /* malformed. */
+ }
+
+ /* failures after this point are not malformed handshakes. */
+ /* TLS: send decrypt_error if signature failed. */
+ desc = isTLS ? decrypt_error : handshake_failure;
+
+ /*
+ * check to make sure the hash is signed by right guy
+ */
+ rv = ssl3_ComputeExportRSAKeyHash(sigAndHash.hashAlg, modulus, exponent,
+ &ss->ssl3.hs.client_random,
+ &ss->ssl3.hs.server_random,
+ &hashes, ss->opt.bypassPKCS11);
+ if (rv != SECSuccess) {
+ errCode =
+ ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
+ goto alert_loser;
+ }
+ rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
+ isTLS, ss->pkcs11PinArg);
+ if (rv != SECSuccess) {
+ errCode =
+ ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
+ goto alert_loser;
+ }
+
+ /*
+ * we really need to build a new key here because we can no longer
+ * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate
+ * pkcs11 slots and ID's.
+ */
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ goto no_memory;
+ }
+
+ peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
+ if (peerKey == NULL) {
+ goto no_memory;
+ }
+
+ peerKey->arena = arena;
+ peerKey->keyType = rsaKey;
+ peerKey->pkcs11Slot = NULL;
+ peerKey->pkcs11ID = CK_INVALID_HANDLE;
+ if (SECITEM_CopyItem(arena, &peerKey->u.rsa.modulus, &modulus) ||
+ SECITEM_CopyItem(arena, &peerKey->u.rsa.publicExponent, &exponent)) {
+ goto no_memory;
+ }
+ ss->sec.peerKey = peerKey;
+ ss->ssl3.hs.ws = wait_cert_request;
+ return SECSuccess;
+ }
+
+ case kt_dh: {
+ SECItem dh_p = { siBuffer, NULL, 0 };
+ SECItem dh_g = { siBuffer, NULL, 0 };
+ SECItem dh_Ys = { siBuffer, NULL, 0 };
+ unsigned dh_p_bits;
+ unsigned dh_g_bits;
+ unsigned dh_Ys_bits;
+ PRInt32 minDH;
+
+ rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length);
+ if (rv != SECSuccess) {
+ goto loser; /* malformed. */
+ }
+
+ rv = NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minDH);
+ if (rv != SECSuccess) {
+ minDH = SSL_DH_MIN_P_BITS;
+ }
+ dh_p_bits = SECKEY_BigIntegerBitLength(&dh_p);
+ if (dh_p_bits < minDH) {
+ errCode = SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY;
+ goto alert_loser;
+ }
+ rv = ssl3_ConsumeHandshakeVariable(ss, &dh_g, 2, &b, &length);
+ if (rv != SECSuccess) {
+ goto loser; /* malformed. */
+ }
+ /* Abort if dh_g is 0, 1, or obviously too big. */
+ dh_g_bits = SECKEY_BigIntegerBitLength(&dh_g);
+ if (dh_g_bits > dh_p_bits || dh_g_bits <= 1)
+ goto alert_loser;
+ rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length);
+ if (rv != SECSuccess) {
+ goto loser; /* malformed. */
+ }
+ dh_Ys_bits = SECKEY_BigIntegerBitLength(&dh_Ys);
+ if (dh_Ys_bits > dh_p_bits || dh_Ys_bits <= 1)
+ goto alert_loser;
+ if (isTLS12) {
+ rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
+ &sigAndHash);
+ if (rv != SECSuccess) {
+ goto loser; /* malformed or unsupported. */
+ }
+ rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(ss,
+ &sigAndHash, ss->sec.peerCert);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+ rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
+ if (rv != SECSuccess) {
+ goto loser; /* malformed. */
+ }
+ if (length != 0) {
+ if (isTLS)
+ desc =
+ decode_error;
+ goto alert_loser; /* malformed. */
+ }
+
+ PRINT_BUF(60, (NULL, "Server DH p", dh_p.data, dh_p.len));
+ PRINT_BUF(60, (NULL, "Server DH g", dh_g.data, dh_g.len));
+ PRINT_BUF(60, (NULL, "Server DH Ys", dh_Ys.data, dh_Ys.len));
+
+ /* failures after this point are not malformed handshakes. */
+ /* TLS: send decrypt_error if signature failed. */
+ desc = isTLS ? decrypt_error : handshake_failure;
+
+ /*
+ * check to make sure the hash is signed by right guy
+ */
+ rv = ssl3_ComputeDHKeyHash(sigAndHash.hashAlg, dh_p, dh_g, dh_Ys,
+ &ss->ssl3.hs.client_random,
+ &ss->ssl3.hs.server_random,
+ &hashes, ss->opt.bypassPKCS11);
+ if (rv != SECSuccess) {
+ errCode =
+ ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
+ goto alert_loser;
+ }
+ rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
+ isTLS, ss->pkcs11PinArg);
+ if (rv != SECSuccess) {
+ errCode =
+ ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
+ goto alert_loser;
+ }
+
+ /*
+ * we really need to build a new key here because we can no longer
+ * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate
+ * pkcs11 slots and ID's.
+ */
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ goto no_memory;
+ }
+
+ peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
+ if (peerKey == NULL) {
+ goto no_memory;
+ }
+
+ peerKey->arena = arena;
+ peerKey->keyType = dhKey;
+ peerKey->pkcs11Slot = NULL;
+ peerKey->pkcs11ID = CK_INVALID_HANDLE;
+
+ if (SECITEM_CopyItem(arena, &peerKey->u.dh.prime, &dh_p) ||
+ SECITEM_CopyItem(arena, &peerKey->u.dh.base, &dh_g) ||
+ SECITEM_CopyItem(arena, &peerKey->u.dh.publicValue, &dh_Ys)) {
+ goto no_memory;
+ }
+ ss->sec.peerKey = peerKey;
+ ss->ssl3.hs.ws = wait_cert_request;
+ return SECSuccess;
}
- rv = ssl3_ConsumeHandshakeVariable(ss, &exponent, 2, &b, &length);
- if (rv != SECSuccess) {
- goto loser; /* malformed. */
- }
- if (isTLS12) {
- rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
- &sigAndHash);
- if (rv != SECSuccess) {
- goto loser; /* malformed or unsupported. */
- }
- rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(ss,
- &sigAndHash, ss->sec.peerCert);
- if (rv != SECSuccess) {
- goto loser;
- }
- }
- rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
- if (rv != SECSuccess) {
- goto loser; /* malformed. */
- }
- if (length != 0) {
- if (isTLS)
- desc = decode_error;
- goto alert_loser; /* malformed. */
- }
-
- /* failures after this point are not malformed handshakes. */
- /* TLS: send decrypt_error if signature failed. */
- desc = isTLS ? decrypt_error : handshake_failure;
-
- /*
- * check to make sure the hash is signed by right guy
- */
- rv = ssl3_ComputeExportRSAKeyHash(sigAndHash.hashAlg, modulus, exponent,
- &ss->ssl3.hs.client_random,
- &ss->ssl3.hs.server_random,
- &hashes, ss->opt.bypassPKCS11);
- if (rv != SECSuccess) {
- errCode =
- ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
- goto alert_loser;
- }
- rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
- isTLS, ss->pkcs11PinArg);
- if (rv != SECSuccess) {
- errCode =
- ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
- goto alert_loser;
- }
-
- /*
- * we really need to build a new key here because we can no longer
- * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate
- * pkcs11 slots and ID's.
- */
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL) {
- goto no_memory;
- }
-
- peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
- if (peerKey == NULL) {
- goto no_memory;
- }
-
- peerKey->arena = arena;
- peerKey->keyType = rsaKey;
- peerKey->pkcs11Slot = NULL;
- peerKey->pkcs11ID = CK_INVALID_HANDLE;
- if (SECITEM_CopyItem(arena, &peerKey->u.rsa.modulus, &modulus) ||
- SECITEM_CopyItem(arena, &peerKey->u.rsa.publicExponent, &exponent))
- {
- goto no_memory;
- }
- ss->sec.peerKey = peerKey;
- ss->ssl3.hs.ws = wait_cert_request;
- return SECSuccess;
- }
-
- case kt_dh: {
- SECItem dh_p = {siBuffer, NULL, 0};
- SECItem dh_g = {siBuffer, NULL, 0};
- SECItem dh_Ys = {siBuffer, NULL, 0};
- unsigned dh_p_bits;
- unsigned dh_g_bits;
- unsigned dh_Ys_bits;
- PRInt32 minDH;
-
- rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length);
- if (rv != SECSuccess) {
- goto loser; /* malformed. */
- }
-
- rv = NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minDH);
- if (rv != SECSuccess) {
- minDH = SSL_DH_MIN_P_BITS;
- }
- dh_p_bits = SECKEY_BigIntegerBitLength(&dh_p);
- if (dh_p_bits < minDH) {
- errCode = SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY;
- goto alert_loser;
- }
- rv = ssl3_ConsumeHandshakeVariable(ss, &dh_g, 2, &b, &length);
- if (rv != SECSuccess) {
- goto loser; /* malformed. */
- }
- /* Abort if dh_g is 0, 1, or obviously too big. */
- dh_g_bits = SECKEY_BigIntegerBitLength(&dh_g);
- if (dh_g_bits > dh_p_bits || dh_g_bits <= 1)
- goto alert_loser;
- rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length);
- if (rv != SECSuccess) {
- goto loser; /* malformed. */
- }
- dh_Ys_bits = SECKEY_BigIntegerBitLength(&dh_Ys);
- if (dh_Ys_bits > dh_p_bits || dh_Ys_bits <= 1)
- goto alert_loser;
- if (isTLS12) {
- rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
- &sigAndHash);
- if (rv != SECSuccess) {
- goto loser; /* malformed or unsupported. */
- }
- rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(ss,
- &sigAndHash, ss->sec.peerCert);
- if (rv != SECSuccess) {
- goto loser;
- }
- }
- rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
- if (rv != SECSuccess) {
- goto loser; /* malformed. */
- }
- if (length != 0) {
- if (isTLS)
- desc = decode_error;
- goto alert_loser; /* malformed. */
- }
-
- PRINT_BUF(60, (NULL, "Server DH p", dh_p.data, dh_p.len));
- PRINT_BUF(60, (NULL, "Server DH g", dh_g.data, dh_g.len));
- PRINT_BUF(60, (NULL, "Server DH Ys", dh_Ys.data, dh_Ys.len));
-
- /* failures after this point are not malformed handshakes. */
- /* TLS: send decrypt_error if signature failed. */
- desc = isTLS ? decrypt_error : handshake_failure;
-
- /*
- * check to make sure the hash is signed by right guy
- */
- rv = ssl3_ComputeDHKeyHash(sigAndHash.hashAlg, dh_p, dh_g, dh_Ys,
- &ss->ssl3.hs.client_random,
- &ss->ssl3.hs.server_random,
- &hashes, ss->opt.bypassPKCS11);
- if (rv != SECSuccess) {
- errCode =
- ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
- goto alert_loser;
- }
- rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
- isTLS, ss->pkcs11PinArg);
- if (rv != SECSuccess) {
- errCode =
- ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
- goto alert_loser;
- }
-
- /*
- * we really need to build a new key here because we can no longer
- * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate
- * pkcs11 slots and ID's.
- */
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL) {
- goto no_memory;
- }
-
- peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
- if (peerKey == NULL) {
- goto no_memory;
- }
-
- peerKey->arena = arena;
- peerKey->keyType = dhKey;
- peerKey->pkcs11Slot = NULL;
- peerKey->pkcs11ID = CK_INVALID_HANDLE;
-
- if (SECITEM_CopyItem(arena, &peerKey->u.dh.prime, &dh_p) ||
- SECITEM_CopyItem(arena, &peerKey->u.dh.base, &dh_g) ||
- SECITEM_CopyItem(arena, &peerKey->u.dh.publicValue, &dh_Ys))
- {
- goto no_memory;
- }
- ss->sec.peerKey = peerKey;
- ss->ssl3.hs.ws = wait_cert_request;
- return SECSuccess;
- }
#ifndef NSS_DISABLE_ECC
- case kt_ecdh:
- rv = ssl3_HandleECDHServerKeyExchange(ss, b, length);
- return rv;
+ case kt_ecdh:
+ rv = ssl3_HandleECDHServerKeyExchange(ss, b, length);
+ return rv;
#endif /* NSS_DISABLE_ECC */
- default:
- desc = handshake_failure;
- errCode = SEC_ERROR_UNSUPPORTED_KEYALG;
- break; /* goto alert_loser; */
+ default:
+ desc = handshake_failure;
+ errCode = SEC_ERROR_UNSUPPORTED_KEYALG;
+ break; /* goto alert_loser; */
}
alert_loser:
@@ -7281,10 +7476,10 @@ loser:
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
}
- PORT_SetError( errCode );
+ PORT_SetError(errCode);
return SECFailure;
-no_memory: /* no-memory error has already been set. */
+no_memory: /* no-memory error has already been set. */
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
}
@@ -7298,35 +7493,23 @@ no_memory: /* no-memory error has already been set. */
*/
static SECStatus
ssl3_ExtractClientKeyInfo(sslSocket *ss,
- SSLSignType *sigAlg,
- PRBool *preferSha1)
+ SSLSignType *sigAlg,
+ PRBool *preferSha1)
{
SECStatus rv = SECSuccess;
SECKEYPublicKey *pubk;
pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
if (pubk == NULL) {
- rv = SECFailure;
- goto done;
+ rv = SECFailure;
+ goto done;
}
rv = ssl3_TLSSignatureAlgorithmForKeyType(pubk->keyType, sigAlg);
if (rv != SECSuccess) {
- goto done;
+ goto done;
}
-#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(_WIN32)
- /* If the key is in CAPI, assume conservatively that the CAPI service
- * provider may be unable to sign SHA-256 hashes.
- */
- if (ss->ssl3.platformClientKey->dwKeySpec != CERT_NCRYPT_KEY_SPEC) {
- /* CAPI only supports RSA and DSA signatures, so we don't need to
- * check the key type. */
- *preferSha1 = PR_TRUE;
- goto done;
- }
-#endif /* NSS_PLATFORM_CLIENT_AUTH && _WIN32 */
-
/* If the key is a 1024-bit RSA or DSA key, assume conservatively that
* it may be unable to sign SHA-256 hashes. This is the case for older
* Estonian ID cards that have 1024-bit RSA keys. In FIPS 186-2 and
@@ -7334,14 +7517,14 @@ ssl3_ExtractClientKeyInfo(sslSocket *ss,
* be SHA-1.
*/
if (pubk->keyType == rsaKey || pubk->keyType == dsaKey) {
- *preferSha1 = SECKEY_PublicKeyStrength(pubk) <= 128;
+ *preferSha1 = SECKEY_PublicKeyStrength(pubk) <= 128;
} else {
- *preferSha1 = PR_FALSE;
+ *preferSha1 = PR_FALSE;
}
done:
if (pubk)
- SECKEY_DestroyPublicKey(pubk);
+ SECKEY_DestroyPublicKey(pubk);
return rv;
}
@@ -7351,11 +7534,11 @@ done:
* to determine whether to use SHA-1 or SHA-256. */
static void
ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
- const SECItem *algorithms)
+ const SECItem *algorithms)
{
SECStatus rv;
SSLSignType sigAlg;
- PRBool preferSha1;
+ PRBool preferSha1 = PR_FALSE;
PRBool supportsSha1 = PR_FALSE;
PRBool supportsSha256 = PR_FALSE;
PRBool needBackupHash = PR_FALSE;
@@ -7364,8 +7547,8 @@ ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
#ifndef NO_PKCS11_BYPASS
/* Backup handshake hash is not supported in PKCS #11 bypass mode. */
if (ss->opt.bypassPKCS11) {
- PORT_Assert(!ss->ssl3.hs.backupHash);
- return;
+ PORT_Assert(!ss->ssl3.hs.backupHash);
+ return;
}
#endif
PORT_Assert(ss->ssl3.hs.backupHash);
@@ -7373,67 +7556,139 @@ ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
/* Determine the key's signature algorithm and whether it prefers SHA-1. */
rv = ssl3_ExtractClientKeyInfo(ss, &sigAlg, &preferSha1);
if (rv != SECSuccess) {
- goto done;
+ goto done;
}
/* Determine the server's hash support for that signature algorithm. */
for (i = 0; i < algorithms->len; i += 2) {
- if (algorithms->data[i+1] == sigAlg) {
- if (algorithms->data[i] == ssl_hash_sha1) {
- supportsSha1 = PR_TRUE;
- } else if (algorithms->data[i] == ssl_hash_sha256) {
- supportsSha256 = PR_TRUE;
- }
- }
+ if (algorithms->data[i + 1] == sigAlg) {
+ if (algorithms->data[i] == ssl_hash_sha1) {
+ supportsSha1 = PR_TRUE;
+ } else if (algorithms->data[i] == ssl_hash_sha256) {
+ supportsSha256 = PR_TRUE;
+ }
+ }
}
/* If either the server does not support SHA-256 or the client key prefers
* SHA-1, leave the backup hash. */
if (supportsSha1 && (preferSha1 || !supportsSha256)) {
- needBackupHash = PR_TRUE;
+ needBackupHash = PR_TRUE;
}
done:
if (!needBackupHash) {
- PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE);
- ss->ssl3.hs.backupHash = NULL;
+ PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE);
+ ss->ssl3.hs.backupHash = NULL;
}
}
typedef struct dnameNode {
struct dnameNode *next;
- SECItem name;
+ SECItem name;
} dnameNode;
-/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
- * ssl3 Certificate Request message.
+/*
+ * Parse the ca_list structure in a CertificateRequest.
+ *
+ * Called from:
+ * ssl3_HandleCertificateRequest
+ * tls13_HandleCertificateRequest
+ */
+SECStatus
+ssl3_ParseCertificateRequestCAs(sslSocket *ss, SSL3Opaque **b, PRUint32 *length,
+ PLArenaPool *arena, CERTDistNames *ca_list)
+{
+ PRInt32 remaining;
+ int nnames = 0;
+ dnameNode *node;
+ int i;
+
+ remaining = ssl3_ConsumeHandshakeNumber(ss, 2, b, length);
+ if (remaining < 0)
+ return SECFailure; /* malformed, alert has been sent */
+
+ if ((PRUint32)remaining > *length)
+ goto alert_loser;
+
+ ca_list->head = node = PORT_ArenaZNew(arena, dnameNode);
+ if (node == NULL)
+ goto no_mem;
+
+ while (remaining > 0) {
+ PRInt32 len;
+
+ if (remaining < 2)
+ goto alert_loser; /* malformed */
+
+ node->name.len = len = ssl3_ConsumeHandshakeNumber(ss, 2, b, length);
+ if (len <= 0)
+ return SECFailure; /* malformed, alert has been sent */
+
+ remaining -= 2;
+ if (remaining < len)
+ goto alert_loser; /* malformed */
+
+ node->name.data = *b;
+ *b += len;
+ *length -= len;
+ remaining -= len;
+ nnames++;
+ if (remaining <= 0)
+ break; /* success */
+
+ node->next = PORT_ArenaZNew(arena, dnameNode);
+ node = node->next;
+ if (node == NULL)
+ goto no_mem;
+ }
+
+ ca_list->nnames = nnames;
+ ca_list->names = PORT_ArenaNewArray(arena, SECItem, nnames);
+ if (nnames > 0 && ca_list->names == NULL)
+ goto no_mem;
+
+ for (i = 0, node = (dnameNode *)ca_list->head;
+ i < nnames;
+ i++, node = node->next) {
+ ca_list->names[i] = node->name;
+ }
+
+ return SECSuccess;
+
+no_mem:
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return SECFailure;
+
+alert_loser:
+ (void)SSL3_SendAlert(ss, alert_fatal,
+ ss->version < SSL_LIBRARY_VERSION_TLS_1_0 ? illegal_parameter
+ : decode_error);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_REQUEST);
+ return SECFailure;
+}
+
+/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
+ * a complete ssl3 Certificate Request message.
* Caller must hold Handshake and RecvBuf locks.
*/
static SECStatus
ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
- PLArenaPool * arena = NULL;
- dnameNode * node;
- PRInt32 remaining;
- PRBool isTLS = PR_FALSE;
- PRBool isTLS12 = PR_FALSE;
- int i;
- int errCode = SSL_ERROR_RX_MALFORMED_CERT_REQUEST;
- int nnames = 0;
- SECStatus rv;
- SSL3AlertDescription desc = illegal_parameter;
- SECItem cert_types = {siBuffer, NULL, 0};
- SECItem algorithms = {siBuffer, NULL, 0};
- CERTDistNames ca_list;
-#ifdef NSS_PLATFORM_CLIENT_AUTH
- CERTCertList * platform_cert_list = NULL;
- CERTCertListNode * certNode = NULL;
-#endif /* NSS_PLATFORM_CLIENT_AUTH */
+ PLArenaPool *arena = NULL;
+ PRBool isTLS = PR_FALSE;
+ PRBool isTLS12 = PR_FALSE;
+ int errCode = SSL_ERROR_RX_MALFORMED_CERT_REQUEST;
+ SECStatus rv;
+ SSL3AlertDescription desc = illegal_parameter;
+ SECItem cert_types = { siBuffer, NULL, 0 };
+ SECItem algorithms = { siBuffer, NULL, 0 };
+ CERTDistNames ca_list;
SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake",
- SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ SSL_GETPID(), ss->fd));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ss->ssl3.hs.ws != wait_cert_request) {
desc = unexpected_message;
@@ -7444,204 +7699,49 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
PORT_Assert(ss->ssl3.clientCertChain == NULL);
PORT_Assert(ss->ssl3.clientCertificate == NULL);
PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
- PORT_Assert(ss->ssl3.platformClientKey == (PlatformKey)NULL);
isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
rv = ssl3_ConsumeHandshakeVariable(ss, &cert_types, 1, &b, &length);
if (rv != SECSuccess)
- goto loser; /* malformed, alert has been sent */
+ goto loser; /* malformed, alert has been sent */
PORT_Assert(!ss->requestedCertTypes);
ss->requestedCertTypes = &cert_types;
if (isTLS12) {
- rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &b, &length);
- if (rv != SECSuccess)
- goto loser; /* malformed, alert has been sent */
- /* An empty or odd-length value is invalid.
- * SignatureAndHashAlgorithm
- * supported_signature_algorithms<2..2^16-2>;
- */
- if (algorithms.len == 0 || (algorithms.len & 1) != 0)
- goto alert_loser;
+ rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &b, &length);
+ if (rv != SECSuccess)
+ goto loser; /* malformed, alert has been sent */
+ /* An empty or odd-length value is invalid.
+ * SignatureAndHashAlgorithm
+ * supported_signature_algorithms<2..2^16-2>;
+ */
+ if (algorithms.len == 0 || (algorithms.len & 1) != 0)
+ goto alert_loser;
}
arena = ca_list.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL)
- goto no_mem;
-
- remaining = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
- if (remaining < 0)
- goto loser; /* malformed, alert has been sent */
-
- if ((PRUint32)remaining > length)
- goto alert_loser;
-
- ca_list.head = node = PORT_ArenaZNew(arena, dnameNode);
- if (node == NULL)
- goto no_mem;
-
- while (remaining > 0) {
- PRInt32 len;
-
- if (remaining < 2)
- goto alert_loser; /* malformed */
-
- node->name.len = len = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
- if (len <= 0)
- goto loser; /* malformed, alert has been sent */
-
- remaining -= 2;
- if (remaining < len)
- goto alert_loser; /* malformed */
-
- node->name.data = b;
- b += len;
- length -= len;
- remaining -= len;
- nnames++;
- if (remaining <= 0)
- break; /* success */
-
- node->next = PORT_ArenaZNew(arena, dnameNode);
- node = node->next;
- if (node == NULL)
- goto no_mem;
- }
-
- ca_list.nnames = nnames;
- ca_list.names = PORT_ArenaNewArray(arena, SECItem, nnames);
- if (nnames > 0 && ca_list.names == NULL)
goto no_mem;
- for(i = 0, node = (dnameNode*)ca_list.head;
- i < nnames;
- i++, node = node->next) {
- ca_list.names[i] = node->name;
- }
+ rv = ssl3_ParseCertificateRequestCAs(ss, &b, &length, arena, &ca_list);
+ if (rv != SECSuccess)
+ goto done; /* alert sent in ssl3_ParseCertificateRequestCAs */
if (length != 0)
- goto alert_loser; /* malformed */
+ goto alert_loser; /* malformed */
desc = no_certificate;
- ss->ssl3.hs.ws = wait_hello_done;
-#ifdef NSS_PLATFORM_CLIENT_AUTH
- if (ss->getPlatformClientAuthData != NULL) {
- /* XXX Should pass cert_types and algorithms in this call!! */
- rv = (SECStatus)(*ss->getPlatformClientAuthData)(
- ss->getPlatformClientAuthDataArg,
- ss->fd, &ca_list,
- &platform_cert_list,
- (void**)&ss->ssl3.platformClientKey,
- &ss->ssl3.clientCertificate,
- &ss->ssl3.clientPrivateKey);
- } else
-#endif
- if (ss->getClientAuthData != NULL) {
- PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
- ssl_preinfo_all);
- /* XXX Should pass cert_types and algorithms in this call!! */
- rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg,
- ss->fd, &ca_list,
- &ss->ssl3.clientCertificate,
- &ss->ssl3.clientPrivateKey);
- } else {
- rv = SECFailure; /* force it to send a no_certificate alert */
- }
+ ss->ssl3.hs.ws = wait_hello_done;
- switch (rv) {
- case SECWouldBlock: /* getClientAuthData has put up a dialog box. */
- ssl3_SetAlwaysBlock(ss);
- break; /* not an error */
-
- case SECSuccess:
-#ifdef NSS_PLATFORM_CLIENT_AUTH
- if (!platform_cert_list || CERT_LIST_EMPTY(platform_cert_list) ||
- !ss->ssl3.platformClientKey) {
- if (platform_cert_list) {
- CERT_DestroyCertList(platform_cert_list);
- platform_cert_list = NULL;
- }
- if (ss->ssl3.platformClientKey) {
- ssl_FreePlatformKey(ss->ssl3.platformClientKey);
- ss->ssl3.platformClientKey = (PlatformKey)NULL;
- }
- /* Fall through to NSS client auth check */
- } else {
- certNode = CERT_LIST_HEAD(platform_cert_list);
- ss->ssl3.clientCertificate = CERT_DupCertificate(certNode->cert);
-
- /* Setting ssl3.clientCertChain non-NULL will cause
- * ssl3_HandleServerHelloDone to call SendCertificate.
- * Note: clientCertChain should include the EE cert as
- * clientCertificate is ignored during the actual sending
- */
- ss->ssl3.clientCertChain =
- hack_NewCertificateListFromCertList(platform_cert_list);
- CERT_DestroyCertList(platform_cert_list);
- platform_cert_list = NULL;
- if (ss->ssl3.clientCertChain == NULL) {
- if (ss->ssl3.clientCertificate != NULL) {
- CERT_DestroyCertificate(ss->ssl3.clientCertificate);
- ss->ssl3.clientCertificate = NULL;
- }
- if (ss->ssl3.platformClientKey) {
- ssl_FreePlatformKey(ss->ssl3.platformClientKey);
- ss->ssl3.platformClientKey = (PlatformKey)NULL;
- }
- goto send_no_certificate;
- }
- if (ss->ssl3.hs.hashType == handshake_hash_single) {
- ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, &algorithms);
- }
- break; /* not an error */
- }
-#endif /* NSS_PLATFORM_CLIENT_AUTH */
- /* check what the callback function returned */
- if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) {
- /* we are missing either the key or cert */
- if (ss->ssl3.clientCertificate) {
- /* got a cert, but no key - free it */
- CERT_DestroyCertificate(ss->ssl3.clientCertificate);
- ss->ssl3.clientCertificate = NULL;
- }
- if (ss->ssl3.clientPrivateKey) {
- /* got a key, but no cert - free it */
- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
- ss->ssl3.clientPrivateKey = NULL;
- }
- goto send_no_certificate;
- }
- /* Setting ssl3.clientCertChain non-NULL will cause
- * ssl3_HandleServerHelloDone to call SendCertificate.
- */
- ss->ssl3.clientCertChain = CERT_CertChainFromCert(
- ss->ssl3.clientCertificate,
- certUsageSSLClient, PR_FALSE);
- if (ss->ssl3.clientCertChain == NULL) {
- CERT_DestroyCertificate(ss->ssl3.clientCertificate);
- ss->ssl3.clientCertificate = NULL;
- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
- ss->ssl3.clientPrivateKey = NULL;
- goto send_no_certificate;
- }
- if (ss->ssl3.hs.hashType == handshake_hash_single) {
- ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, &algorithms);
- }
- break; /* not an error */
-
- case SECFailure:
- default:
-send_no_certificate:
- if (isTLS) {
- ss->ssl3.sendEmptyCert = PR_TRUE;
- } else {
- (void)SSL3_SendAlert(ss, alert_warning, no_certificate);
- }
- rv = SECSuccess;
- break;
+ rv = ssl3_CompleteHandleCertificateRequest(ss, &algorithms, &ca_list);
+ if (rv == SECFailure) {
+ PORT_Assert(0);
+ errCode = SEC_ERROR_LIBRARY_FAILURE;
+ desc = internal_error;
+ goto alert_loser;
}
goto done;
@@ -7652,7 +7752,7 @@ no_mem:
alert_loser:
if (isTLS && desc == illegal_parameter)
- desc = decode_error;
+ desc = decode_error;
(void)SSL3_SendAlert(ss, alert_fatal, desc);
loser:
PORT_SetError(errCode);
@@ -7660,11 +7760,78 @@ loser:
done:
ss->requestedCertTypes = NULL;
if (arena != NULL)
- PORT_FreeArena(arena, PR_FALSE);
-#ifdef NSS_PLATFORM_CLIENT_AUTH
- if (platform_cert_list)
- CERT_DestroyCertList(platform_cert_list);
-#endif
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+SECStatus
+ssl3_CompleteHandleCertificateRequest(sslSocket *ss, SECItem *algorithms,
+ CERTDistNames *ca_list)
+{
+ SECStatus rv;
+
+ if (ss->getClientAuthData != NULL) {
+ PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
+ ssl_preinfo_all);
+ /* XXX Should pass cert_types and algorithms in this call!! */
+ rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg,
+ ss->fd, ca_list,
+ &ss->ssl3.clientCertificate,
+ &ss->ssl3.clientPrivateKey);
+ } else {
+ rv = SECFailure; /* force it to send a no_certificate alert */
+ }
+ switch (rv) {
+ case SECWouldBlock: /* getClientAuthData has put up a dialog box. */
+ ssl3_SetAlwaysBlock(ss);
+ break; /* not an error */
+
+ case SECSuccess:
+ /* check what the callback function returned */
+ if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) {
+ /* we are missing either the key or cert */
+ if (ss->ssl3.clientCertificate) {
+ /* got a cert, but no key - free it */
+ CERT_DestroyCertificate(ss->ssl3.clientCertificate);
+ ss->ssl3.clientCertificate = NULL;
+ }
+ if (ss->ssl3.clientPrivateKey) {
+ /* got a key, but no cert - free it */
+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
+ ss->ssl3.clientPrivateKey = NULL;
+ }
+ goto send_no_certificate;
+ }
+ /* Setting ssl3.clientCertChain non-NULL will cause
+ * ssl3_HandleServerHelloDone to call SendCertificate.
+ */
+ ss->ssl3.clientCertChain = CERT_CertChainFromCert(
+ ss->ssl3.clientCertificate,
+ certUsageSSLClient, PR_FALSE);
+ if (ss->ssl3.clientCertChain == NULL) {
+ CERT_DestroyCertificate(ss->ssl3.clientCertificate);
+ ss->ssl3.clientCertificate = NULL;
+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
+ ss->ssl3.clientPrivateKey = NULL;
+ goto send_no_certificate;
+ }
+ if (ss->ssl3.hs.hashType == handshake_hash_single) {
+ ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, algorithms);
+ }
+ break; /* not an error */
+
+ case SECFailure:
+ default:
+ send_no_certificate:
+ if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) {
+ ss->ssl3.sendEmptyCert = PR_TRUE;
+ } else {
+ (void)SSL3_SendAlert(ss, alert_warning, no_certificate);
+ }
+ rv = SECSuccess;
+ break;
+ }
+
return rv;
}
@@ -7696,21 +7863,21 @@ done:
* Caller holds 1stHandshakeLock.
*/
SECStatus
-ssl3_RestartHandshakeAfterCertReq(sslSocket * ss,
- CERTCertificate * cert,
- SECKEYPrivateKey * key,
- CERTCertificateList *certChain)
+ssl3_RestartHandshakeAfterCertReq(sslSocket *ss,
+ CERTCertificate *cert,
+ SECKEYPrivateKey *key,
+ CERTCertificateList *certChain)
{
- SECStatus rv = SECSuccess;
+ SECStatus rv = SECSuccess;
/* XXX This code only works on the initial handshake on a connection,
** XXX It does not work on a subsequent handshake (redo).
*/
if (ss->handshake != 0) {
- ss->handshake = ssl_GatherRecord1stHandshake;
- ss->ssl3.clientCertificate = cert;
- ss->ssl3.clientPrivateKey = key;
- ss->ssl3.clientCertChain = certChain;
+ ss->handshake = ssl_GatherRecord1stHandshake;
+ ss->ssl3.clientCertificate = cert;
+ ss->ssl3.clientPrivateKey = key;
+ ss->ssl3.clientCertChain = certChain;
if (!cert || !key || !certChain) {
/* we are missing the key, cert, or cert chain */
if (ss->ssl3.clientCertificate) {
@@ -7730,19 +7897,19 @@ ssl3_RestartHandshakeAfterCertReq(sslSocket * ss,
} else {
(void)SSL3_SendAlert(ss, alert_warning, no_certificate);
}
- }
+ }
} else {
- if (cert) {
- CERT_DestroyCertificate(cert);
- }
- if (key) {
- SECKEY_DestroyPrivateKey(key);
- }
- if (certChain) {
- CERT_DestroyCertificateList(certChain);
- }
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- rv = SECFailure;
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+ if (key) {
+ SECKEY_DestroyPrivateKey(key);
+ }
+ if (certChain) {
+ CERT_DestroyCertificateList(certChain);
+ }
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ rv = SECFailure;
}
return rv;
}
@@ -7750,45 +7917,46 @@ ssl3_RestartHandshakeAfterCertReq(sslSocket * ss,
static SECStatus
ssl3_CheckFalseStart(sslSocket *ss)
{
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( !ss->ssl3.hs.authCertificatePending );
- PORT_Assert( !ss->ssl3.hs.canFalseStart );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(!ss->ssl3.hs.authCertificatePending);
+ PORT_Assert(!ss->ssl3.hs.canFalseStart);
if (!ss->canFalseStartCallback) {
- SSL_TRC(3, ("%d: SSL[%d]: no false start callback so no false start",
- SSL_GETPID(), ss->fd));
+ SSL_TRC(3, ("%d: SSL[%d]: no false start callback so no false start",
+ SSL_GETPID(), ss->fd));
} else {
- PRBool maybeFalseStart;
- SECStatus rv;
+ PRBool maybeFalseStart;
+ SECStatus rv;
- /* An attacker can control the selected ciphersuite so we only wish to
- * do False Start in the case that the selected ciphersuite is
- * sufficiently strong that the attack can gain no advantage.
- * Therefore we always require an 80-bit cipher. */
+ /* An attacker can control the selected ciphersuite so we only wish to
+ * do False Start in the case that the selected ciphersuite is
+ * sufficiently strong that the attack can gain no advantage.
+ * Therefore we always require an 80-bit cipher. */
ssl_GetSpecReadLock(ss);
maybeFalseStart = ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10;
ssl_ReleaseSpecReadLock(ss);
- if (!maybeFalseStart) {
- SSL_TRC(3, ("%d: SSL[%d]: no false start due to weak cipher",
- SSL_GETPID(), ss->fd));
- } else {
+ if (!maybeFalseStart) {
+ SSL_TRC(3, ("%d: SSL[%d]: no false start due to weak cipher",
+ SSL_GETPID(), ss->fd));
+ } else {
PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
ssl_preinfo_all);
- rv = (ss->canFalseStartCallback)(ss->fd,
- ss->canFalseStartCallbackData,
- &ss->ssl3.hs.canFalseStart);
- if (rv == SECSuccess) {
- SSL_TRC(3, ("%d: SSL[%d]: false start callback returned %s",
- SSL_GETPID(), ss->fd,
- ss->ssl3.hs.canFalseStart ? "TRUE" : "FALSE"));
- } else {
- SSL_TRC(3, ("%d: SSL[%d]: false start callback failed (%s)",
- SSL_GETPID(), ss->fd,
- PR_ErrorToName(PR_GetError())));
- }
- return rv;
- }
+ rv = (ss->canFalseStartCallback)(ss->fd,
+ ss->canFalseStartCallbackData,
+ &ss->ssl3.hs.canFalseStart);
+ if (rv == SECSuccess) {
+ SSL_TRC(3, ("%d: SSL[%d]: false start callback returned %s",
+ SSL_GETPID(), ss->fd,
+ ss->ssl3.hs.canFalseStart ? "TRUE"
+ : "FALSE"));
+ } else {
+ SSL_TRC(3, ("%d: SSL[%d]: false start callback failed (%s)",
+ SSL_GETPID(), ss->fd,
+ PR_ErrorToName(PR_GetError())));
+ }
+ return rv;
+ }
}
ss->ssl3.hs.canFalseStart = PR_FALSE;
@@ -7796,22 +7964,21 @@ ssl3_CheckFalseStart(sslSocket *ss)
}
PRBool
-ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss)
+ssl3_WaitingForServerSecondRound(sslSocket *ss)
{
PRBool result;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
switch (ss->ssl3.hs.ws) {
- case wait_new_session_ticket:
- result = PR_TRUE;
- break;
- case wait_change_cipher:
- result = !ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn);
- break;
- default:
- result = PR_FALSE;
- break;
+ case wait_new_session_ticket:
+ case wait_change_cipher:
+ case wait_finished:
+ result = PR_TRUE;
+ break;
+ default:
+ result = PR_FALSE;
+ break;
}
return result;
@@ -7819,27 +7986,27 @@ ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss)
static SECStatus ssl3_SendClientSecondRound(sslSocket *ss);
-/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
- * ssl3 Server Hello Done message.
+/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
+ * a complete ssl3 Server Hello Done message.
* Caller must hold Handshake and RecvBuf locks.
*/
static SECStatus
ssl3_HandleServerHelloDone(sslSocket *ss)
{
- SECStatus rv;
- SSL3WaitState ws = ss->ssl3.hs.ws;
+ SECStatus rv;
+ SSL3WaitState ws = ss->ssl3.hs.ws;
SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello_done handshake",
- SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ SSL_GETPID(), ss->fd));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
/* Skipping CertificateRequest is always permitted. */
- if (ws != wait_hello_done &&
- ws != wait_cert_request) {
- SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
- return SECFailure;
+ if (ws != wait_hello_done &&
+ ws != wait_cert_request) {
+ SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
+ return SECFailure;
}
rv = ssl3_SendClientSecondRound(ss);
@@ -7857,20 +8024,19 @@ ssl3_SendClientSecondRound(sslSocket *ss)
SECStatus rv;
PRBool sendClientCert;
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
sendClientCert = !ss->ssl3.sendEmptyCert &&
- ss->ssl3.clientCertChain != NULL &&
- (ss->ssl3.platformClientKey ||
- ss->ssl3.clientPrivateKey != NULL);
+ ss->ssl3.clientCertChain != NULL &&
+ ss->ssl3.clientPrivateKey != NULL;
if (!sendClientCert &&
- ss->ssl3.hs.hashType == handshake_hash_single &&
- ss->ssl3.hs.backupHash) {
- /* Don't need the backup handshake hash. */
- PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE);
- ss->ssl3.hs.backupHash = NULL;
+ ss->ssl3.hs.hashType == handshake_hash_single &&
+ ss->ssl3.hs.backupHash) {
+ /* Don't need the backup handshake hash. */
+ PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE);
+ ss->ssl3.hs.backupHash = NULL;
}
/* We must wait for the server's certificate to be authenticated before
@@ -7898,50 +8064,52 @@ ssl3_SendClientSecondRound(sslSocket *ss)
* application data.
*/
if (ss->ssl3.hs.restartTarget) {
- PR_NOT_REACHED("unexpected ss->ssl3.hs.restartTarget");
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
+ PR_NOT_REACHED("unexpected ss->ssl3.hs.restartTarget");
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
}
if (ss->ssl3.hs.authCertificatePending &&
- (sendClientCert || ss->ssl3.sendEmptyCert || ss->firstHsDone)) {
- SSL_TRC(3, ("%d: SSL3[%p]: deferring ssl3_SendClientSecondRound because"
- " certificate authentication is still pending.",
- SSL_GETPID(), ss->fd));
- ss->ssl3.hs.restartTarget = ssl3_SendClientSecondRound;
- return SECWouldBlock;
+ (sendClientCert || ss->ssl3.sendEmptyCert || ss->firstHsDone)) {
+ SSL_TRC(3, ("%d: SSL3[%p]: deferring ssl3_SendClientSecondRound because"
+ " certificate authentication is still pending.",
+ SSL_GETPID(), ss->fd));
+ ss->ssl3.hs.restartTarget = ssl3_SendClientSecondRound;
+ return SECWouldBlock;
}
- ssl_GetXmitBufLock(ss); /*******************************/
+ ssl_GetXmitBufLock(ss); /*******************************/
if (ss->ssl3.sendEmptyCert) {
- ss->ssl3.sendEmptyCert = PR_FALSE;
- rv = ssl3_SendEmptyCertificate(ss);
- /* Don't send verify */
- if (rv != SECSuccess) {
- goto loser; /* error code is set. */
- }
+ ss->ssl3.sendEmptyCert = PR_FALSE;
+ rv = ssl3_SendEmptyCertificate(ss);
+ /* Don't send verify */
+ if (rv != SECSuccess) {
+ goto loser; /* error code is set. */
+ }
} else if (sendClientCert) {
- rv = ssl3_SendCertificate(ss);
- if (rv != SECSuccess) {
- goto loser; /* error code is set. */
- }
+ rv = ssl3_SendCertificate(ss);
+ if (rv != SECSuccess) {
+ goto loser; /* error code is set. */
+ }
}
rv = ssl3_SendClientKeyExchange(ss);
if (rv != SECSuccess) {
- goto loser; /* err is set. */
+ goto loser; /* err is set. */
}
if (sendClientCert) {
- rv = ssl3_SendCertificateVerify(ss);
- if (rv != SECSuccess) {
- goto loser; /* err is set. */
+ rv = ssl3_SendCertificateVerify(ss, ss->ssl3.clientPrivateKey);
+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
+ ss->ssl3.clientPrivateKey = NULL;
+ if (rv != SECSuccess) {
+ goto loser; /* err is set. */
}
}
rv = ssl3_SendChangeCipherSpecs(ss);
if (rv != SECSuccess) {
- goto loser; /* err code was set. */
+ goto loser; /* err code was set. */
}
/* This must be done after we've set ss->ssl3.cwSpec in
@@ -7953,56 +8121,56 @@ ssl3_SendClientSecondRound(sslSocket *ss)
ss->enoughFirstHsDone = PR_TRUE;
if (!ss->firstHsDone) {
- /* XXX: If the server's certificate hasn't been authenticated by this
- * point, then we may be leaking this NPN message to an attacker.
- */
- rv = ssl3_SendNextProto(ss);
- if (rv != SECSuccess) {
- goto loser; /* err code was set. */
- }
+ /* XXX: If the server's certificate hasn't been authenticated by this
+ * point, then we may be leaking this NPN message to an attacker.
+ */
+ rv = ssl3_SendNextProto(ss);
+ if (rv != SECSuccess) {
+ goto loser; /* err code was set. */
+ }
}
- rv = ssl3_SendEncryptedExtensions(ss);
+ rv = ssl3_SendChannelIDEncryptedExtensions(ss);
if (rv != SECSuccess) {
- goto loser; /* err code was set. */
+ goto loser; /* err code was set. */
}
if (!ss->firstHsDone) {
- if (ss->opt.enableFalseStart) {
- if (!ss->ssl3.hs.authCertificatePending) {
- /* When we fix bug 589047, we will need to know whether we are
- * false starting before we try to flush the client second
- * round to the network. With that in mind, we purposefully
- * call ssl3_CheckFalseStart before calling ssl3_SendFinished,
- * which includes a call to ssl3_FlushHandshake, so that
- * no application develops a reliance on such flushing being
- * done before its false start callback is called.
- */
- ssl_ReleaseXmitBufLock(ss);
- rv = ssl3_CheckFalseStart(ss);
- ssl_GetXmitBufLock(ss);
- if (rv != SECSuccess) {
- goto loser;
- }
- } else {
- /* The certificate authentication and the server's Finished
- * message are racing each other. If the certificate
- * authentication wins, then we will try to false start in
- * ssl3_AuthCertificateComplete.
- */
- SSL_TRC(3, ("%d: SSL3[%p]: deferring false start check because"
- " certificate authentication is still pending.",
- SSL_GETPID(), ss->fd));
- }
- }
+ if (ss->opt.enableFalseStart) {
+ if (!ss->ssl3.hs.authCertificatePending) {
+ /* When we fix bug 589047, we will need to know whether we are
+ * false starting before we try to flush the client second
+ * round to the network. With that in mind, we purposefully
+ * call ssl3_CheckFalseStart before calling ssl3_SendFinished,
+ * which includes a call to ssl3_FlushHandshake, so that
+ * no application develops a reliance on such flushing being
+ * done before its false start callback is called.
+ */
+ ssl_ReleaseXmitBufLock(ss);
+ rv = ssl3_CheckFalseStart(ss);
+ ssl_GetXmitBufLock(ss);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ } else {
+ /* The certificate authentication and the server's Finished
+ * message are racing each other. If the certificate
+ * authentication wins, then we will try to false start in
+ * ssl3_AuthCertificateComplete.
+ */
+ SSL_TRC(3, ("%d: SSL3[%p]: deferring false start check because"
+ " certificate authentication is still pending.",
+ SSL_GETPID(), ss->fd));
+ }
+ }
}
rv = ssl3_SendFinished(ss, 0);
if (rv != SECSuccess) {
- goto loser; /* err code was set. */
+ goto loser; /* err code was set. */
}
- ssl_ReleaseXmitBufLock(ss); /*******************************/
+ ssl_ReleaseXmitBufLock(ss); /*******************************/
if (!ss->ssl3.hs.isResuming &&
ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
@@ -8032,11 +8200,11 @@ ssl3_SendClientSecondRound(sslSocket *ss)
}
if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
- ss->ssl3.hs.ws = wait_new_session_ticket;
+ ss->ssl3.hs.ws = wait_new_session_ticket;
else
- ss->ssl3.hs.ws = wait_change_cipher;
+ ss->ssl3.hs.ws = wait_change_cipher;
- PORT_Assert(ssl3_WaitingForStartOfServerSecondRound(ss));
+ PORT_Assert(ssl3_WaitingForServerSecondRound(ss));
return SECSuccess;
@@ -8054,18 +8222,18 @@ ssl3_SendHelloRequest(sslSocket *ss)
SECStatus rv;
SSL_TRC(3, ("%d: SSL3[%d]: send hello_request handshake", SSL_GETPID(),
- ss->fd));
+ ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
rv = ssl3_AppendHandshakeHeader(ss, hello_request, 0);
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake */
+ return rv; /* err set by AppendHandshake */
}
rv = ssl3_FlushHandshake(ss, 0);
if (rv != SECSuccess) {
- return rv; /* error code set by ssl3_FlushHandshake */
+ return rv; /* error code set by ssl3_FlushHandshake */
}
ss->ssl3.hs.ws = wait_client_hello;
return SECSuccess;
@@ -8073,7 +8241,7 @@ ssl3_SendHelloRequest(sslSocket *ss)
/*
* Called from:
- * ssl3_HandleClientHello()
+ * ssl3_HandleClientHello()
*/
static SECComparison
ssl3_ServerNameCompare(const SECItem *name1, const SECItem *name2)
@@ -8092,10 +8260,10 @@ ssl3_ServerNameCompare(const SECItem *name1, const SECItem *name2)
/* Sets memory error when returning NULL.
* Called from:
- * ssl3_SendClientHello()
- * ssl3_HandleServerHello()
- * ssl3_HandleClientHello()
- * ssl3_HandleV2ClientHello()
+ * ssl3_SendClientHello()
+ * ssl3_HandleServerHello()
+ * ssl3_HandleClientHello()
+ * ssl3_HandleV2ClientHello()
*/
sslSessionID *
ssl3_NewSessionID(sslSocket *ss, PRBool is_server)
@@ -8104,13 +8272,13 @@ ssl3_NewSessionID(sslSocket *ss, PRBool is_server)
sid = PORT_ZNew(sslSessionID);
if (sid == NULL)
- return sid;
+ return sid;
if (is_server) {
- const SECItem * srvName;
- SECStatus rv = SECSuccess;
+ const SECItem *srvName;
+ SECStatus rv = SECSuccess;
- ssl_GetSpecReadLock(ss); /********************************/
+ ssl_GetSpecReadLock(ss); /********************************/
srvName = &ss->ssl3.prSpec->srvVirtName;
if (srvName->len && srvName->data) {
rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.srvName, srvName);
@@ -8121,34 +8289,34 @@ ssl3_NewSessionID(sslSocket *ss, PRBool is_server)
return NULL;
}
}
- sid->peerID = (ss->peerID == NULL) ? NULL : PORT_Strdup(ss->peerID);
- sid->urlSvrName = (ss->url == NULL) ? NULL : PORT_Strdup(ss->url);
- sid->addr = ss->sec.ci.peer;
- sid->port = ss->sec.ci.port;
- sid->references = 1;
- sid->cached = never_cached;
- sid->version = ss->version;
+ sid->peerID = (ss->peerID == NULL) ? NULL : PORT_Strdup(ss->peerID);
+ sid->urlSvrName = (ss->url == NULL) ? NULL : PORT_Strdup(ss->url);
+ sid->addr = ss->sec.ci.peer;
+ sid->port = ss->sec.ci.port;
+ sid->references = 1;
+ sid->cached = never_cached;
+ sid->version = ss->version;
sid->u.ssl3.keys.resumable = PR_TRUE;
- sid->u.ssl3.policy = SSL_ALLOWED;
+ sid->u.ssl3.policy = SSL_ALLOWED;
sid->u.ssl3.clientWriteKey = NULL;
sid->u.ssl3.serverWriteKey = NULL;
sid->u.ssl3.keys.extendedMasterSecretUsed = PR_FALSE;
if (is_server) {
- SECStatus rv;
- int pid = SSL_GETPID();
-
- sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES;
- sid->u.ssl3.sessionID[0] = (pid >> 8) & 0xff;
- sid->u.ssl3.sessionID[1] = pid & 0xff;
- rv = PK11_GenerateRandom(sid->u.ssl3.sessionID + 2,
- SSL3_SESSIONID_BYTES -2);
- if (rv != SECSuccess) {
- ssl_FreeSID(sid);
- ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
- return NULL;
- }
+ SECStatus rv;
+ int pid = SSL_GETPID();
+
+ sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES;
+ sid->u.ssl3.sessionID[0] = (pid >> 8) & 0xff;
+ sid->u.ssl3.sessionID[1] = pid & 0xff;
+ rv = PK11_GenerateRandom(sid->u.ssl3.sessionID + 2,
+ SSL3_SESSIONID_BYTES - 2);
+ if (rv != SECSuccess) {
+ ssl_FreeSID(sid);
+ ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
+ return NULL;
+ }
}
return sid;
}
@@ -8158,25 +8326,25 @@ static SECStatus
ssl3_SendServerHelloSequence(sslSocket *ss)
{
const ssl3KEADef *kea_def;
- SECStatus rv;
+ SECStatus rv;
SSL_TRC(3, ("%d: SSL3[%d]: begin send server_hello sequence",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
rv = ssl3_SendServerHello(ss);
if (rv != SECSuccess) {
- return rv; /* err code is set. */
+ return rv; /* err code is set. */
}
rv = ssl3_SendCertificate(ss);
if (rv != SECSuccess) {
- return rv; /* error code is set. */
+ return rv; /* error code is set. */
}
rv = ssl3_SendCertificateStatus(ss);
if (rv != SECSuccess) {
- return rv; /* error code is set. */
+ return rv; /* error code is set. */
}
/* We have to do this after the call to ssl3_SendServerHello,
* because kea_def is set up by ssl3_SendServerHello().
@@ -8185,70 +8353,108 @@ ssl3_SendServerHelloSequence(sslSocket *ss)
ss->ssl3.hs.usedStepDownKey = PR_FALSE;
if (kea_def->is_limited && kea_def->exchKeyType == kt_rsa) {
- /* see if we can legally use the key in the cert. */
- unsigned int keyLen; /* bytes */
-
- keyLen = PK11_GetPrivateModulusLen(
- ss->serverCerts[kea_def->exchKeyType].SERVERKEY);
-
- if (keyLen > 0 &&
- keyLen * BPB <= kea_def->key_size_limit ) {
- /* XXX AND cert is not signing only!! */
- /* just fall through and use it. */
- } else if (ss->stepDownKeyPair != NULL) {
- ss->ssl3.hs.usedStepDownKey = PR_TRUE;
- rv = ssl3_SendServerKeyExchange(ss);
- if (rv != SECSuccess) {
- return rv; /* err code was set. */
- }
- } else {
+ /* see if we can legally use the key in the cert. */
+ unsigned int keyLen; /* bytes */
+
+ keyLen = PK11_GetPrivateModulusLen(
+ ss->serverCerts[kea_def->exchKeyType].SERVERKEY);
+
+ if (keyLen > 0 &&
+ keyLen * BPB <= kea_def->key_size_limit) {
+ /* XXX AND cert is not signing only!! */
+ /* just fall through and use it. */
+ } else if (ss->stepDownKeyPair != NULL) {
+ ss->ssl3.hs.usedStepDownKey = PR_TRUE;
+ rv = ssl3_SendServerKeyExchange(ss);
+ if (rv != SECSuccess) {
+ return rv; /* err code was set. */
+ }
+ } else {
#ifndef HACKED_EXPORT_SERVER
- PORT_SetError(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED);
- return rv;
+ PORT_SetError(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED);
+ return rv;
#endif
- }
+ }
} else if (kea_def->ephemeral) {
rv = ssl3_SendServerKeyExchange(ss);
if (rv != SECSuccess) {
- return rv; /* err code was set. */
+ return rv; /* err code was set. */
}
}
if (ss->opt.requestCertificate) {
- rv = ssl3_SendCertificateRequest(ss);
- if (rv != SECSuccess) {
- return rv; /* err code is set. */
- }
+ rv = ssl3_SendCertificateRequest(ss);
+ if (rv != SECSuccess) {
+ return rv; /* err code is set. */
+ }
}
rv = ssl3_SendServerHelloDone(ss);
if (rv != SECSuccess) {
- return rv; /* err code is set. */
+ return rv; /* err code is set. */
}
ss->ssl3.hs.ws = (ss->opt.requestCertificate) ? wait_client_cert
- : wait_client_key;
+ : wait_client_key;
return SECSuccess;
}
/* An empty TLS Renegotiation Info (RI) extension */
-static const PRUint8 emptyRIext[5] = {0xff, 0x01, 0x00, 0x01, 0x00};
+static const PRUint8 emptyRIext[5] = { 0xff, 0x01, 0x00, 0x01, 0x00 };
static PRBool
ssl3_KEAAllowsSessionTicket(SSL3KeyExchangeAlgorithm kea)
{
switch (kea) {
- case kea_dhe_dss:
- case kea_dhe_dss_export:
- case kea_dh_dss_export:
- case kea_dh_dss:
- /* TODO: Fix session tickets for DSS. The server code rejects the
- * session ticket received from the client. Bug 1174677 */
- return PR_FALSE;
- default:
- return PR_TRUE;
+ case kea_dhe_dss:
+ case kea_dhe_dss_export:
+ case kea_dh_dss_export:
+ case kea_dh_dss:
+ /* TODO: Fix session tickets for DSS. The server code rejects the
+ * session ticket received from the client. Bug 1174677 */
+ return PR_FALSE;
+ default:
+ return PR_TRUE;
};
}
+static void
+ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid)
+{
+ PLArenaPool *arena;
+ ssl3CertNode *lastCert = NULL;
+ ssl3CertNode *certs = NULL;
+ int i;
+
+ if (!sid->peerCertChain[0])
+ return;
+ PORT_Assert(!ss->ssl3.peerCertArena);
+ PORT_Assert(!ss->ssl3.peerCertChain);
+ ss->ssl3.peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
+ ssl3CertNode *c = PORT_ArenaNew(arena, ssl3CertNode);
+ c->cert = CERT_DupCertificate(sid->peerCertChain[i]);
+ c->next = NULL;
+ if (lastCert) {
+ lastCert->next = c;
+ } else {
+ certs = c;
+ }
+ lastCert = c;
+ }
+ ss->ssl3.peerCertChain = certs;
+}
+
+static void
+ssl3_CopyPeerCertsToSID(ssl3CertNode *certs, sslSessionID *sid)
+{
+ int i = 0;
+ ssl3CertNode *c = certs;
+ for (; i < MAX_PEER_CERT_CHAIN_SIZE && c; i++, c = c->next) {
+ PORT_Assert(!sid->peerCertChain[i]);
+ sid->peerCertChain[i] = CERT_DupCertificate(c->cert);
+ }
+}
+
/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
* ssl3 Client Hello message.
* Caller must hold Handshake and RecvBuf locks.
@@ -8256,29 +8462,30 @@ ssl3_KEAAllowsSessionTicket(SSL3KeyExchangeAlgorithm kea)
static SECStatus
ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
- sslSessionID * sid = NULL;
- PRInt32 tmp;
- unsigned int i;
- int j;
- SECStatus rv;
- int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
- SSL3AlertDescription desc = illegal_parameter;
- SSL3AlertLevel level = alert_fatal;
+ sslSessionID *sid = NULL;
+ PRInt32 tmp;
+ unsigned int i;
+ int j;
+ SECStatus rv;
+ int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
+ SSL3AlertDescription desc = illegal_parameter;
+ SSL3AlertLevel level = alert_fatal;
SSL3ProtocolVersion version;
- SECItem sidBytes = {siBuffer, NULL, 0};
- SECItem cookieBytes = {siBuffer, NULL, 0};
- SECItem suites = {siBuffer, NULL, 0};
- SECItem comps = {siBuffer, NULL, 0};
- PRBool haveSpecWriteLock = PR_FALSE;
- PRBool haveXmitBufLock = PR_FALSE;
- PRBool canOfferSessionTicket = PR_FALSE;
+ SECItem sidBytes = { siBuffer, NULL, 0 };
+ SECItem cookieBytes = { siBuffer, NULL, 0 };
+ SECItem suites = { siBuffer, NULL, 0 };
+ SECItem comps = { siBuffer, NULL, 0 };
+ PRBool haveSpecWriteLock = PR_FALSE;
+ PRBool haveXmitBufLock = PR_FALSE;
+ PRBool canOfferSessionTicket = PR_FALSE;
+ PRBool isTLS13 = PR_FALSE;
SSL_TRC(3, ("%d: SSL3[%d]: handle client_hello handshake",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
- PORT_Assert( ss->ssl3.initialized );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->ssl3.initialized);
ss->ssl3.hs.preliminaryInfo = 0;
if (!ss->sec.isServer ||
@@ -8288,18 +8495,24 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO;
goto alert_loser;
}
- if (ss->ssl3.hs.ws == idle_handshake &&
- ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
- desc = no_renegotiation;
- level = alert_warning;
- errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
- goto alert_loser;
+ if (ss->ssl3.hs.ws == idle_handshake) {
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ desc = unexpected_message;
+ errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
+ goto alert_loser;
+ }
+ if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
+ desc = no_renegotiation;
+ level = alert_warning;
+ errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
+ goto alert_loser;
+ }
}
/* Get peer name of client */
rv = ssl_GetPeerInfo(ss);
if (rv != SECSuccess) {
- return rv; /* error code is set. */
+ return rv; /* error code is set. */
}
/* Clearing the handshake pointers so that ssl_Do1stHandshake won't
@@ -8312,8 +8525,8 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
* and need to reset these values here.
*/
if (IS_DTLS(ss)) {
- ss->nextHandshake = 0;
- ss->securityHandshake = 0;
+ ss->nextHandshake = 0;
+ ss->securityHandshake = 0;
}
/* We might be starting session renegotiation in which case we should
@@ -8323,85 +8536,130 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ss->statelessResume = PR_FALSE;
if (IS_DTLS(ss)) {
- dtls_RehandshakeCleanup(ss);
+ dtls_RehandshakeCleanup(ss);
}
tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
if (tmp < 0)
- goto loser; /* malformed, alert already sent */
+ goto loser; /* malformed, alert already sent */
/* Translate the version */
if (IS_DTLS(ss)) {
- ss->clientHelloVersion = version =
- dtls_DTLSVersionToTLSVersion((SSL3ProtocolVersion)tmp);
+ ss->clientHelloVersion = version =
+ dtls_DTLSVersionToTLSVersion((SSL3ProtocolVersion)tmp);
} else {
- ss->clientHelloVersion = version = (SSL3ProtocolVersion)tmp;
+ ss->clientHelloVersion = version = (SSL3ProtocolVersion)tmp;
}
rv = ssl3_NegotiateVersion(ss, version, PR_TRUE);
if (rv != SECSuccess) {
- desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
- : handshake_failure;
- errCode = SSL_ERROR_UNSUPPORTED_VERSION;
- goto alert_loser;
+ desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
+ : handshake_failure;
+ errCode = SSL_ERROR_UNSUPPORTED_VERSION;
+ goto alert_loser;
}
+ isTLS13 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
rv = ssl3_InitHandshakeHashes(ss);
if (rv != SECSuccess) {
- desc = internal_error;
- errCode = PORT_GetError();
- goto alert_loser;
+ desc = internal_error;
+ errCode = PORT_GetError();
+ goto alert_loser;
+ }
+
+ /* Generate the Server Random now so it is available
+ * when we process the ClientKeyShare in TLS 1.3 */
+ rv = ssl3_GetNewRandom(&ss->ssl3.hs.server_random);
+ if (rv != SECSuccess) {
+ errCode = SSL_ERROR_GENERATE_RANDOM_FAILURE;
+ goto loser;
+ }
+
+ /*
+ * [draft-ietf-tls-tls13-11 Section 6.3.1.1].
+ * TLS 1.3 server implementations which respond to a ClientHello with a
+ * client_version indicating TLS 1.2 or below MUST set the first eight
+ * bytes of their Random value to the bytes:
+ *
+ * 44 4F 57 4E 47 52 44 01
+ *
+ * TLS 1.2 server implementations which respond to a ClientHello with a
+ * client_version indicating TLS 1.1 or below SHOULD set the first eight
+ * bytes of their Random value to the bytes:
+ *
+ * 44 4F 57 4E 47 52 44 00
+ *
+ * TODO(ekr@rtfm.com): Note this change was not added in the SSLv2
+ * compat processing code since that will most likely be removed before
+ * we ship the final version of TLS 1.3.
+ */
+ if (ss->vrange.max > ss->version) {
+ switch (ss->vrange.max) {
+ case SSL_LIBRARY_VERSION_TLS_1_3:
+ PORT_Memcpy(ss->ssl3.hs.server_random.rand,
+ tls13_downgrade_random,
+ sizeof(tls13_downgrade_random));
+ break;
+ case SSL_LIBRARY_VERSION_TLS_1_2:
+ PORT_Memcpy(ss->ssl3.hs.server_random.rand,
+ tls12_downgrade_random,
+ sizeof(tls12_downgrade_random));
+ break;
+ default:
+ /* Do not change random. */
+ break;
+ }
}
/* grab the client random data. */
rv = ssl3_ConsumeHandshake(
- ss, &ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH, &b, &length);
+ ss, &ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH, &b, &length);
if (rv != SECSuccess) {
- goto loser; /* malformed */
+ goto loser; /* malformed */
}
/* grab the client's SID, if present. */
rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length);
if (rv != SECSuccess) {
- goto loser; /* malformed */
+ goto loser; /* malformed */
}
/* grab the client's cookie, if present. */
if (IS_DTLS(ss)) {
- rv = ssl3_ConsumeHandshakeVariable(ss, &cookieBytes, 1, &b, &length);
- if (rv != SECSuccess) {
- goto loser; /* malformed */
- }
+ rv = ssl3_ConsumeHandshakeVariable(ss, &cookieBytes, 1, &b, &length);
+ if (rv != SECSuccess) {
+ goto loser; /* malformed */
+ }
}
/* grab the list of cipher suites. */
rv = ssl3_ConsumeHandshakeVariable(ss, &suites, 2, &b, &length);
if (rv != SECSuccess) {
- goto loser; /* malformed */
+ goto loser; /* malformed */
}
/* If the ClientHello version is less than our maximum version, check for a
* TLS_FALLBACK_SCSV and reject the connection if found. */
if (ss->vrange.max > ss->clientHelloVersion) {
- for (i = 0; i + 1 < suites.len; i += 2) {
- PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
- if (suite_i != TLS_FALLBACK_SCSV)
- continue;
- desc = inappropriate_fallback;
- errCode = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT;
- goto alert_loser;
- }
+ for (i = 0; i + 1 < suites.len; i += 2) {
+ PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
+ if (suite_i != TLS_FALLBACK_SCSV)
+ continue;
+ desc = inappropriate_fallback;
+ errCode = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT;
+ goto alert_loser;
+ }
}
/* grab the list of compression methods. */
rv = ssl3_ConsumeHandshakeVariable(ss, &comps, 1, &b, &length);
if (rv != SECSuccess) {
- goto loser; /* malformed */
+ goto loser; /* malformed */
}
/* TLS 1.3 requires that compression be empty */
- if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ if (isTLS13) {
if (comps.len != 1 || comps.data[0] != ssl_compression_null) {
goto loser;
}
@@ -8416,51 +8674,51 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
*/
if (length) {
- /* Get length of hello extensions */
- PRInt32 extension_length;
- extension_length = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
- if (extension_length < 0) {
- goto loser; /* alert already sent */
- }
- if (extension_length != length) {
- ssl3_DecodeError(ss); /* send alert */
- goto loser;
- }
- rv = ssl3_HandleHelloExtensions(ss, &b, &length);
- if (rv != SECSuccess) {
- goto loser; /* malformed */
- }
+ /* Get length of hello extensions */
+ PRInt32 extension_length;
+ extension_length = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
+ if (extension_length < 0) {
+ goto loser; /* alert already sent */
+ }
+ if (extension_length != length) {
+ ssl3_DecodeError(ss); /* send alert */
+ goto loser;
+ }
+ rv = ssl3_HandleHelloExtensions(ss, &b, &length, client_hello);
+ if (rv != SECSuccess) {
+ goto loser; /* malformed */
+ }
}
if (!ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
- /* If we didn't receive an RI extension, look for the SCSV,
- * and if found, treat it just like an empty RI extension
- * by processing a local copy of an empty RI extension.
- */
- for (i = 0; i + 1 < suites.len; i += 2) {
- PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
- if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) {
- SSL3Opaque * b2 = (SSL3Opaque *)emptyRIext;
- PRUint32 L2 = sizeof emptyRIext;
- (void)ssl3_HandleHelloExtensions(ss, &b2, &L2);
- break;
- }
- }
+ /* If we didn't receive an RI extension, look for the SCSV,
+ * and if found, treat it just like an empty RI extension
+ * by processing a local copy of an empty RI extension.
+ */
+ for (i = 0; i + 1 < suites.len; i += 2) {
+ PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
+ if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) {
+ SSL3Opaque *b2 = (SSL3Opaque *)emptyRIext;
+ PRUint32 L2 = sizeof emptyRIext;
+ (void)ssl3_HandleHelloExtensions(ss, &b2, &L2, client_hello);
+ break;
+ }
+ }
}
if (ss->firstHsDone &&
(ss->opt.enableRenegotiation == SSL_RENEGOTIATE_REQUIRES_XTN ||
- ss->opt.enableRenegotiation == SSL_RENEGOTIATE_TRANSITIONAL) &&
- !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
- desc = no_renegotiation;
- level = alert_warning;
- errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
- goto alert_loser;
- }
- if ((ss->opt.requireSafeNegotiation ||
+ ss->opt.enableRenegotiation == SSL_RENEGOTIATE_TRANSITIONAL) &&
+ !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
+ desc = no_renegotiation;
+ level = alert_warning;
+ errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
+ goto alert_loser;
+ }
+ if ((ss->opt.requireSafeNegotiation ||
(ss->firstHsDone && ss->peerRequestedProtection)) &&
- !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
- desc = handshake_failure;
- errCode = SSL_ERROR_UNSAFE_NEGOTIATION;
- goto alert_loser;
+ !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
+ desc = handshake_failure;
+ errCode = SSL_ERROR_UNSAFE_NEGOTIATION;
+ goto alert_loser;
}
/* We do stateful resumes only if either of the following
@@ -8469,37 +8727,37 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
* ticket extension, but sent an empty ticket.
*/
if (!ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) ||
- ss->xtnData.emptySessionTicket) {
- if (sidBytes.len > 0 && !ss->opt.noCache) {
- SSL_TRC(7, ("%d: SSL3[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x",
- SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0],
- ss->sec.ci.peer.pr_s6_addr32[1],
- ss->sec.ci.peer.pr_s6_addr32[2],
- ss->sec.ci.peer.pr_s6_addr32[3]));
- if (ssl_sid_lookup) {
- sid = (*ssl_sid_lookup)(&ss->sec.ci.peer, sidBytes.data,
- sidBytes.len, ss->dbHandle);
- } else {
- errCode = SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED;
- goto loser;
- }
- }
+ ss->xtnData.emptySessionTicket) {
+ if (sidBytes.len > 0 && !ss->opt.noCache) {
+ SSL_TRC(7, ("%d: SSL3[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x",
+ SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0],
+ ss->sec.ci.peer.pr_s6_addr32[1],
+ ss->sec.ci.peer.pr_s6_addr32[2],
+ ss->sec.ci.peer.pr_s6_addr32[3]));
+ if (ssl_sid_lookup) {
+ sid = (*ssl_sid_lookup)(&ss->sec.ci.peer, sidBytes.data,
+ sidBytes.len, ss->dbHandle);
+ } else {
+ errCode = SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED;
+ goto loser;
+ }
+ }
} else if (ss->statelessResume) {
- /* Fill in the client's session ID if doing a stateless resume.
- * (When doing stateless resumes, server echos client's SessionID.)
- */
- sid = ss->sec.ci.sid;
- PORT_Assert(sid != NULL); /* Should have already been filled in.*/
-
- if (sidBytes.len > 0 && sidBytes.len <= SSL3_SESSIONID_BYTES) {
- sid->u.ssl3.sessionIDLength = sidBytes.len;
- PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data,
- sidBytes.len);
- sid->u.ssl3.sessionIDLength = sidBytes.len;
- } else {
- sid->u.ssl3.sessionIDLength = 0;
- }
- ss->sec.ci.sid = NULL;
+ /* Fill in the client's session ID if doing a stateless resume.
+ * (When doing stateless resumes, server echos client's SessionID.)
+ */
+ sid = ss->sec.ci.sid;
+ PORT_Assert(sid != NULL); /* Should have already been filled in.*/
+
+ if (sidBytes.len > 0 && sidBytes.len <= SSL3_SESSIONID_BYTES) {
+ sid->u.ssl3.sessionIDLength = sidBytes.len;
+ PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data,
+ sidBytes.len);
+ sid->u.ssl3.sessionIDLength = sidBytes.len;
+ } else {
+ sid->u.ssl3.sessionIDLength = 0;
+ }
+ ss->sec.ci.sid = NULL;
}
/* We only send a session ticket extension if the client supports
@@ -8513,28 +8771,28 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
* resuming.)
*/
if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) && sid == NULL) {
- canOfferSessionTicket = PR_TRUE;
+ canOfferSessionTicket = PR_TRUE;
}
if (sid != NULL) {
- /* We've found a session cache entry for this client.
- * Now, if we're going to require a client-auth cert,
- * and we don't already have this client's cert in the session cache,
- * and this is the first handshake on this connection (not a redo),
- * then drop this old cache entry and start a new session.
- */
- if ((sid->peerCert == NULL) && ss->opt.requestCertificate &&
- ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) ||
- (ss->opt.requireCertificate == SSL_REQUIRE_NO_ERROR) ||
- ((ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE)
- && !ss->firstHsDone))) {
-
- SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_not_ok );
- if (ss->sec.uncache)
+ /* We've found a session cache entry for this client.
+ * Now, if we're going to require a client-auth cert,
+ * and we don't already have this client's cert in the session cache,
+ * and this is the first handshake on this connection (not a redo),
+ * then drop this old cache entry and start a new session.
+ */
+ if ((sid->peerCert == NULL) && ss->opt.requestCertificate &&
+ ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) ||
+ (ss->opt.requireCertificate == SSL_REQUIRE_NO_ERROR) ||
+ ((ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE) &&
+ !ss->firstHsDone))) {
+
+ SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_not_ok);
+ if (ss->sec.uncache)
ss->sec.uncache(sid);
- ssl_FreeSID(sid);
- sid = NULL;
- }
+ ssl_FreeSID(sid);
+ sid = NULL;
+ }
}
#ifndef NSS_DISABLE_ECC
@@ -8543,19 +8801,15 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
#endif
if (IS_DTLS(ss)) {
- ssl3_DisableNonDTLSSuites(ss);
- }
-
- if (!ssl3_HasGCMSupport()) {
- ssl3_DisableGCMSuites(ss);
+ ssl3_DisableNonDTLSSuites(ss);
}
#ifdef PARANOID
/* Look for a matching cipher suite. */
j = ssl3_config_match_init(ss);
- if (j <= 0) { /* no ciphers are working/supported by PK11 */
- errCode = PORT_GetError(); /* error code is already set. */
- goto alert_loser;
+ if (j <= 0) { /* no ciphers are working/supported by PK11 */
+ errCode = PORT_GetError(); /* error code is already set. */
+ goto alert_loser;
}
#endif
@@ -8563,69 +8817,74 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
** same cipher suite and compression method we picked before.
** This is not a loop, despite appearances.
*/
- if (sid) do {
- ssl3CipherSuiteCfg *suite;
+ if (sid)
+ do {
+ ssl3CipherSuiteCfg *suite;
#ifdef PARANOID
- SSLVersionRange vrange = {ss->version, ss->version};
+ SSLVersionRange vrange = { ss->version, ss->version };
#endif
- /* Check that the cached compression method is still enabled. */
- if (!compressionEnabled(ss, sid->u.ssl3.compression))
- break;
-
- /* Check that the cached compression method is in the client's list */
- for (i = 0; i < comps.len; i++) {
- if (comps.data[i] == sid->u.ssl3.compression)
- break;
- }
- if (i == comps.len)
- break;
-
- suite = ss->cipherSuites;
- /* Find the entry for the cipher suite used in the cached session. */
- for (j = ssl_V3_SUITES_IMPLEMENTED; j > 0; --j, ++suite) {
- if (suite->cipher_suite == sid->u.ssl3.cipherSuite)
- break;
- }
- PORT_Assert(j > 0);
- if (j <= 0)
- break;
+ /* Check that the cached compression method is still enabled. */
+ if (!compressionEnabled(ss, sid->u.ssl3.compression))
+ break;
+
+ /* Check that the cached compression method is in the client's list */
+ for (i = 0; i < comps.len; i++) {
+ if (comps.data[i] == sid->u.ssl3.compression)
+ break;
+ }
+ if (i == comps.len)
+ break;
+
+ suite = ss->cipherSuites;
+ /* Find the entry for the cipher suite used in the cached session. */
+ for (j = ssl_V3_SUITES_IMPLEMENTED; j > 0; --j, ++suite) {
+ if (suite->cipher_suite == sid->u.ssl3.cipherSuite)
+ break;
+ }
+ PORT_Assert(j > 0);
+ if (j <= 0)
+ break;
#ifdef PARANOID
- /* Double check that the cached cipher suite is still enabled,
- * implemented, and allowed by policy. Might have been disabled.
- * The product policy won't change during the process lifetime.
- * Implemented ("isPresent") shouldn't change for servers.
- */
- if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss))
- break;
+ /* Double check that the cached cipher suite is still enabled,
+ * implemented, and allowed by policy. Might have been disabled.
+ * The product policy won't change during the process lifetime.
+ * Implemented ("isPresent") shouldn't change for servers.
+ */
+ if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss))
+ break;
#else
- if (!suite->enabled)
- break;
+ if (!suite->enabled)
+ break;
#endif
- /* Double check that the cached cipher suite is in the client's list */
- for (i = 0; i + 1 < suites.len; i += 2) {
- PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
- if (suite_i == suite->cipher_suite) {
- ss->ssl3.hs.cipher_suite = suite->cipher_suite;
- ss->ssl3.hs.suite_def =
- ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
- ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
-
- /* Use the cached compression method. */
- ss->ssl3.hs.compression = sid->u.ssl3.compression;
- goto compression_found;
- }
- }
- } while (0);
+ /* Double check that the cached cipher suite is in the client's list */
+ for (i = 0; i + 1 < suites.len; i += 2) {
+ PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
+ if (suite_i == suite->cipher_suite) {
+ ss->ssl3.hs.cipher_suite =
+ suite->cipher_suite;
+ ss->ssl3.hs.suite_def =
+ ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
+ ss->ssl3.hs.kea_def =
+ &kea_defs[ss->ssl3.hs.suite_def->key_exchange_alg];
+ ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
+
+ /* Use the cached compression method. */
+ ss->ssl3.hs.compression =
+ sid->u.ssl3.compression;
+ goto compression_found;
+ }
+ }
+ } while (0);
- /* START A NEW SESSION */
+/* START A NEW SESSION */
#ifndef PARANOID
/* Look for a matching cipher suite. */
j = ssl3_config_match_init(ss);
- if (j <= 0) { /* no ciphers are working/supported by PK11 */
- errCode = PORT_GetError(); /* error code is already set. */
- goto alert_loser;
+ if (j <= 0) { /* no ciphers are working/supported by PK11 */
+ errCode = PORT_GetError(); /* error code is already set. */
+ goto alert_loser;
}
#endif
@@ -8644,49 +8903,51 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
** (the server) have TLS 1.1 support enabled.
*/
for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
- ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
- SSLVersionRange vrange = {ss->version, ss->version};
- if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss)) {
- continue;
- }
- for (i = 0; i + 1 < suites.len; i += 2) {
- PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
- if (suite_i == suite->cipher_suite) {
- ss->ssl3.hs.cipher_suite = suite->cipher_suite;
- ss->ssl3.hs.suite_def =
- ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
+ ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
+ SSLVersionRange vrange = { ss->version, ss->version };
+ if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss)) {
+ continue;
+ }
+ for (i = 0; i + 1 < suites.len; i += 2) {
+ PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
+ if (suite_i == suite->cipher_suite) {
+ ss->ssl3.hs.cipher_suite = suite->cipher_suite;
+ ss->ssl3.hs.suite_def =
+ ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
+ ss->ssl3.hs.kea_def =
+ &kea_defs[ss->ssl3.hs.suite_def->key_exchange_alg];
ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
- goto suite_found;
- }
- }
+ goto suite_found;
+ }
+ }
}
errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
goto alert_loser;
suite_found:
if (canOfferSessionTicket)
- canOfferSessionTicket = ssl3_KEAAllowsSessionTicket(
- ss->ssl3.hs.suite_def->key_exchange_alg);
+ canOfferSessionTicket = ssl3_KEAAllowsSessionTicket(
+ ss->ssl3.hs.suite_def->key_exchange_alg);
if (canOfferSessionTicket) {
- ssl3_RegisterServerHelloExtensionSender(ss,
- ssl_session_ticket_xtn, ssl3_SendSessionTicketXtn);
+ ssl3_RegisterServerHelloExtensionSender(ss,
+ ssl_session_ticket_xtn, ssl3_SendSessionTicketXtn);
}
/* Select a compression algorithm. */
for (i = 0; i < comps.len; i++) {
- if (!compressionEnabled(ss, comps.data[i]))
- continue;
- for (j = 0; j < compressionMethodsCount; j++) {
- if (comps.data[i] == compressions[j]) {
- ss->ssl3.hs.compression =
- (SSLCompressionMethod)compressions[j];
- goto compression_found;
- }
- }
+ if (!compressionEnabled(ss, comps.data[i]))
+ continue;
+ for (j = 0; j < compressionMethodsCount; j++) {
+ if (comps.data[i] == compressions[j]) {
+ ss->ssl3.hs.compression =
+ (SSLCompressionMethod)compressions[j];
+ goto compression_found;
+ }
+ }
}
errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP;
- /* null compression must be supported */
+ /* null compression must be supported */
goto alert_loser;
compression_found:
@@ -8701,333 +8962,338 @@ compression_found:
* The exception here is attempts to resume extended_master_secret
* sessions without the extension, which causes an alert.
*/
- if (sid != NULL) do {
- ssl3CipherSpec *pwSpec;
- SECItem wrappedMS; /* wrapped key */
-
- if (sid->version != ss->version ||
- sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite ||
- sid->u.ssl3.compression != ss->ssl3.hs.compression) {
- break; /* not an error */
- }
-
- /* [draft-ietf-tls-session-hash-06; Section 5.3]
- * o If the original session did not use the "extended_master_secret"
- * extension but the new ClientHello contains the extension, then the
- * server MUST NOT perform the abbreviated handshake. Instead, it
- * SHOULD continue with a full handshake (as described in
- * Section 5.2) to negotiate a new session.
- *
- * o If the original session used the "extended_master_secret"
- * extension but the new ClientHello does not contain the extension,
- * the server MUST abort the abbreviated handshake.
- */
- if (ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
- if (!sid->u.ssl3.keys.extendedMasterSecretUsed) {
- break; /* not an error */
+ if (sid != NULL)
+ do {
+ ssl3CipherSpec *pwSpec;
+ SECItem wrappedMS; /* wrapped key */
+
+ if (sid->version != ss->version ||
+ sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite ||
+ sid->u.ssl3.compression != ss->ssl3.hs.compression) {
+ break; /* not an error */
}
- } else {
- if (sid->u.ssl3.keys.extendedMasterSecretUsed) {
- /* Note: we do not destroy the session */
- desc = handshake_failure;
- errCode = SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET;
- goto alert_loser;
+
+ /* [draft-ietf-tls-session-hash-06; Section 5.3]
+ * o If the original session did not use the "extended_master_secret"
+ * extension but the new ClientHello contains the extension, then the
+ * server MUST NOT perform the abbreviated handshake. Instead, it
+ * SHOULD continue with a full handshake (as described in
+ * Section 5.2) to negotiate a new session.
+ *
+ * o If the original session used the "extended_master_secret"
+ * extension but the new ClientHello does not contain the extension,
+ * the server MUST abort the abbreviated handshake.
+ */
+ if (ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
+ if (!sid->u.ssl3.keys.extendedMasterSecretUsed) {
+ break; /* not an error */
+ }
+ } else {
+ if (sid->u.ssl3.keys.extendedMasterSecretUsed) {
+ /* Note: we do not destroy the session */
+ desc = handshake_failure;
+ errCode = SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET;
+ goto alert_loser;
+ }
}
- }
- if (ss->sec.ci.sid) {
- if (ss->sec.uncache)
- ss->sec.uncache(ss->sec.ci.sid);
- PORT_Assert(ss->sec.ci.sid != sid); /* should be impossible, but ... */
- if (ss->sec.ci.sid != sid) {
- ssl_FreeSID(ss->sec.ci.sid);
- }
- ss->sec.ci.sid = NULL;
- }
- /* we need to resurrect the master secret.... */
-
- ssl_GetSpecWriteLock(ss); haveSpecWriteLock = PR_TRUE;
- pwSpec = ss->ssl3.pwSpec;
- if (sid->u.ssl3.keys.msIsWrapped) {
- PK11SymKey * wrapKey; /* wrapping key */
- CK_FLAGS keyFlags = 0;
+ if (ss->sec.ci.sid) {
+ if (ss->sec.uncache)
+ ss->sec.uncache(ss->sec.ci.sid);
+ PORT_Assert(ss->sec.ci.sid != sid); /* should be impossible, but ... */
+ if (ss->sec.ci.sid != sid) {
+ ssl_FreeSID(ss->sec.ci.sid);
+ }
+ ss->sec.ci.sid = NULL;
+ }
+ /* we need to resurrect the master secret.... */
+
+ ssl_GetSpecWriteLock(ss);
+ haveSpecWriteLock = PR_TRUE;
+ pwSpec = ss->ssl3.pwSpec;
+ if (sid->u.ssl3.keys.msIsWrapped) {
+ PK11SymKey *wrapKey; /* wrapping key */
+ CK_FLAGS keyFlags = 0;
#ifndef NO_PKCS11_BYPASS
- if (ss->opt.bypassPKCS11) {
- /* we cannot restart a non-bypass session in a
- ** bypass socket.
- */
- break;
- }
+ if (ss->opt.bypassPKCS11) {
+ /* we cannot restart a non-bypass session in a
+ ** bypass socket.
+ */
+ break;
+ }
#endif
- wrapKey = getWrappingKey(ss, NULL, sid->u.ssl3.exchKeyType,
- sid->u.ssl3.masterWrapMech,
- ss->pkcs11PinArg);
- if (!wrapKey) {
- /* we have a SID cache entry, but no wrapping key for it??? */
- break;
- }
-
- if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
- keyFlags = CKF_SIGN | CKF_VERIFY;
- }
-
- wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
- wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
-
- /* unwrap the master secret. */
- pwSpec->master_secret =
- PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech,
- NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
- CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags);
- PK11_FreeSymKey(wrapKey);
- if (pwSpec->master_secret == NULL) {
- break; /* not an error */
- }
+ wrapKey = getWrappingKey(ss, NULL, sid->u.ssl3.exchKeyType,
+ sid->u.ssl3.masterWrapMech,
+ ss->pkcs11PinArg);
+ if (!wrapKey) {
+ /* we have a SID cache entry, but no wrapping key for it??? */
+ break;
+ }
+
+ if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
+ keyFlags =
+ CKF_SIGN | CKF_VERIFY;
+ }
+
+ wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
+ wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
+
+ /* unwrap the master secret. */
+ pwSpec->master_secret =
+ PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech,
+ NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
+ CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags);
+ PK11_FreeSymKey(wrapKey);
+ if (pwSpec->master_secret == NULL) {
+ break; /* not an error */
+ }
#ifndef NO_PKCS11_BYPASS
- } else if (ss->opt.bypassPKCS11) {
- wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
- wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
- memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len);
- pwSpec->msItem.data = pwSpec->raw_master_secret;
- pwSpec->msItem.len = wrappedMS.len;
+ } else if (ss->opt.bypassPKCS11) {
+ wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
+ wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
+ memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len);
+ pwSpec->msItem.data = pwSpec->raw_master_secret;
+ pwSpec->msItem.len = wrappedMS.len;
#endif
- } else {
- /* We CAN restart a bypass session in a non-bypass socket. */
- /* need to import the raw master secret to session object */
- PK11SlotInfo * slot;
- wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
- wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
- slot = PK11_GetInternalSlot();
- pwSpec->master_secret =
- PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE,
- PK11_OriginUnwrap, CKA_ENCRYPT, &wrappedMS,
- NULL);
- PK11_FreeSlot(slot);
- if (pwSpec->master_secret == NULL) {
- break; /* not an error */
- }
- }
- ss->sec.ci.sid = sid;
- if (sid->peerCert != NULL) {
- ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
- ssl3_CopyPeerCertsFromSID(ss, sid);
- }
-
- /*
- * Old SID passed all tests, so resume this old session.
- *
- * XXX make sure compression still matches
- */
- SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_hits );
- if (ss->statelessResume)
- SSL_AtomicIncrementLong(& ssl3stats.hch_sid_stateless_resumes );
- ss->ssl3.hs.isResuming = PR_TRUE;
-
- ss->sec.authAlgorithm = sid->authAlgorithm;
- ss->sec.authKeyBits = sid->authKeyBits;
- ss->sec.keaType = sid->keaType;
- ss->sec.keaKeyBits = sid->keaKeyBits;
-
- /* server sids don't remember the server cert we previously sent,
- ** but they do remember the kea type we originally used, so we
- ** can locate it again, provided that the current ssl socket
- ** has had its server certs configured the same as the previous one.
- */
- ss->sec.localCert =
- CERT_DupCertificate(ss->serverCerts[sid->keaType].serverCert);
-
- /* Copy cached name in to pending spec */
- if (sid != NULL &&
- sid->version > SSL_LIBRARY_VERSION_3_0 &&
- sid->u.ssl3.srvName.len && sid->u.ssl3.srvName.data) {
- /* Set server name from sid */
- SECItem *sidName = &sid->u.ssl3.srvName;
- SECItem *pwsName = &ss->ssl3.pwSpec->srvVirtName;
- if (pwsName->data) {
- SECITEM_FreeItem(pwsName, PR_FALSE);
- }
- rv = SECITEM_CopyItem(NULL, pwsName, sidName);
+ } else {
+ /* We CAN restart a bypass session in a non-bypass socket. */
+ /* need to import the raw master secret to session object */
+ PK11SlotInfo *slot;
+ wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
+ wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
+ slot = PK11_GetInternalSlot();
+ pwSpec->master_secret =
+ PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE,
+ PK11_OriginUnwrap, CKA_ENCRYPT, &wrappedMS,
+ NULL);
+ PK11_FreeSlot(slot);
+ if (pwSpec->master_secret == NULL) {
+ break; /* not an error */
+ }
+ }
+ ss->sec.ci.sid = sid;
+ if (sid->peerCert != NULL) {
+ ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
+ ssl3_CopyPeerCertsFromSID(ss, sid);
+ }
+
+ /*
+ * Old SID passed all tests, so resume this old session.
+ *
+ * XXX make sure compression still matches
+ */
+ SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_hits);
+ if (ss->statelessResume)
+ SSL_AtomicIncrementLong(&ssl3stats.hch_sid_stateless_resumes);
+ ss->ssl3.hs.isResuming = PR_TRUE;
+
+ ss->sec.authAlgorithm = sid->authAlgorithm;
+ ss->sec.authKeyBits = sid->authKeyBits;
+ ss->sec.keaType = sid->keaType;
+ ss->sec.keaKeyBits = sid->keaKeyBits;
+
+ /* server sids don't remember the server cert we previously sent,
+ ** but they do remember the kea type we originally used, so we
+ ** can locate it again, provided that the current ssl socket
+ ** has had its server certs configured the same as the previous one.
+ */
+ ss->sec.localCert =
+ CERT_DupCertificate(ss->serverCerts[sid->keaType].serverCert);
+
+ /* Copy cached name in to pending spec */
+ if (sid != NULL &&
+ sid->version > SSL_LIBRARY_VERSION_3_0 &&
+ sid->u.ssl3.srvName.len && sid->u.ssl3.srvName.data) {
+ /* Set server name from sid */
+ SECItem *sidName = &sid->u.ssl3.srvName;
+ SECItem *pwsName = &ss->ssl3.pwSpec->srvVirtName;
+ if (pwsName->data) {
+ SECITEM_FreeItem(pwsName, PR_FALSE);
+ }
+ rv = SECITEM_CopyItem(NULL, pwsName, sidName);
+ if (rv != SECSuccess) {
+ errCode = PORT_GetError();
+ desc = internal_error;
+ goto alert_loser;
+ }
+ }
+
+ /* Clean up sni name array */
+ if (ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn) &&
+ ss->xtnData.sniNameArr) {
+ PORT_Free(ss->xtnData.sniNameArr);
+ ss->xtnData.sniNameArr = NULL;
+ ss->xtnData.sniNameArrSize = 0;
+ }
+
+ ssl_GetXmitBufLock(ss);
+ haveXmitBufLock = PR_TRUE;
+
+ rv = ssl3_SendServerHello(ss);
if (rv != SECSuccess) {
errCode = PORT_GetError();
- desc = internal_error;
- goto alert_loser;
+ goto loser;
}
- }
- /* Clean up sni name array */
- if (ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn) &&
- ss->xtnData.sniNameArr) {
- PORT_Free(ss->xtnData.sniNameArr);
- ss->xtnData.sniNameArr = NULL;
- ss->xtnData.sniNameArrSize = 0;
- }
+ if (haveSpecWriteLock) {
+ ssl_ReleaseSpecWriteLock(ss);
+ haveSpecWriteLock = PR_FALSE;
+ }
- ssl_GetXmitBufLock(ss); haveXmitBufLock = PR_TRUE;
-
- rv = ssl3_SendServerHello(ss);
- if (rv != SECSuccess) {
- errCode = PORT_GetError();
- goto loser;
- }
-
- if (haveSpecWriteLock) {
- ssl_ReleaseSpecWriteLock(ss);
- haveSpecWriteLock = PR_FALSE;
- }
-
- /* NULL value for PMS because we are re-using the old MS */
- rv = ssl3_InitPendingCipherSpec(ss, NULL);
- if (rv != SECSuccess) {
- errCode = PORT_GetError();
- goto loser;
- }
-
- rv = ssl3_SendChangeCipherSpecs(ss);
- if (rv != SECSuccess) {
- errCode = PORT_GetError();
- goto loser;
- }
- rv = ssl3_SendFinished(ss, 0);
- ss->ssl3.hs.ws = wait_change_cipher;
- if (rv != SECSuccess) {
- errCode = PORT_GetError();
- goto loser;
- }
-
- if (haveXmitBufLock) {
- ssl_ReleaseXmitBufLock(ss);
- haveXmitBufLock = PR_FALSE;
- }
+ /* NULL value for PMS because we are re-using the old MS */
+ rv = ssl3_InitPendingCipherSpec(ss, NULL);
+ if (rv != SECSuccess) {
+ errCode = PORT_GetError();
+ goto loser;
+ }
- return SECSuccess;
- } while (0);
+ rv = ssl3_SendChangeCipherSpecs(ss);
+ if (rv != SECSuccess) {
+ errCode = PORT_GetError();
+ goto loser;
+ }
+ rv = ssl3_SendFinished(ss, 0);
+ ss->ssl3.hs.ws = wait_change_cipher;
+ if (rv != SECSuccess) {
+ errCode = PORT_GetError();
+ goto loser;
+ }
+
+ if (haveXmitBufLock) {
+ ssl_ReleaseXmitBufLock(ss);
+ haveXmitBufLock = PR_FALSE;
+ }
+
+ return SECSuccess;
+ } while (0);
if (haveSpecWriteLock) {
- ssl_ReleaseSpecWriteLock(ss);
- haveSpecWriteLock = PR_FALSE;
+ ssl_ReleaseSpecWriteLock(ss);
+ haveSpecWriteLock = PR_FALSE;
}
- if (sid) { /* we had a sid, but it's no longer valid, free it */
- SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_not_ok );
- if (ss->sec.uncache)
+ if (sid) { /* we had a sid, but it's no longer valid, free it */
+ SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_not_ok);
+ if (ss->sec.uncache)
ss->sec.uncache(sid);
- ssl_FreeSID(sid);
- sid = NULL;
+ ssl_FreeSID(sid);
+ sid = NULL;
}
- SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_misses );
+ SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_misses);
if (ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn)) {
int ret = 0;
- if (ss->sniSocketConfig) do { /* not a loop */
- PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
- ssl_preinfo_all);
+ if (ss->sniSocketConfig)
+ do { /* not a loop */
+ PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
+ ssl_preinfo_all);
- ret = SSL_SNI_SEND_ALERT;
- /* If extension is negotiated, the len of names should > 0. */
- if (ss->xtnData.sniNameArrSize) {
- /* Calling client callback to reconfigure the socket. */
- ret = (SECStatus)(*ss->sniSocketConfig)(ss->fd,
- ss->xtnData.sniNameArr,
- ss->xtnData.sniNameArrSize,
- ss->sniSocketConfigArg);
- }
- if (ret <= SSL_SNI_SEND_ALERT) {
- /* Application does not know the name or was not able to
- * properly reconfigure the socket. */
- errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
- desc = unrecognized_name;
- break;
- } else if (ret == SSL_SNI_CURRENT_CONFIG_IS_USED) {
- SECStatus rv = SECSuccess;
- SECItem * cwsName, *pwsName;
+ ret = SSL_SNI_SEND_ALERT;
+ /* If extension is negotiated, the len of names should > 0. */
+ if (ss->xtnData.sniNameArrSize) {
+ /* Calling client callback to reconfigure the socket. */
+ ret = (SECStatus)(*ss->sniSocketConfig)(ss->fd,
+ ss->xtnData.sniNameArr,
+ ss->xtnData.sniNameArrSize,
+ ss->sniSocketConfigArg);
+ }
+ if (ret <= SSL_SNI_SEND_ALERT) {
+ /* Application does not know the name or was not able to
+ * properly reconfigure the socket. */
+ errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
+ desc = unrecognized_name;
+ break;
+ } else if (ret == SSL_SNI_CURRENT_CONFIG_IS_USED) {
+ SECStatus rv = SECSuccess;
+ SECItem *cwsName, *pwsName;
- ssl_GetSpecWriteLock(ss); /*******************************/
- pwsName = &ss->ssl3.pwSpec->srvVirtName;
- cwsName = &ss->ssl3.cwSpec->srvVirtName;
+ ssl_GetSpecWriteLock(ss); /*******************************/
+ pwsName = &ss->ssl3.pwSpec->srvVirtName;
+ cwsName = &ss->ssl3.cwSpec->srvVirtName;
#ifndef SSL_SNI_ALLOW_NAME_CHANGE_2HS
- /* not allow name change on the 2d HS */
- if (ss->firstHsDone) {
- if (ssl3_ServerNameCompare(pwsName, cwsName)) {
- ssl_ReleaseSpecWriteLock(ss); /******************/
- errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
- desc = handshake_failure;
+ /* not allow name change on the 2d HS */
+ if (ss->firstHsDone) {
+ if (ssl3_ServerNameCompare(pwsName, cwsName)) {
+ ssl_ReleaseSpecWriteLock(ss); /******************/
+ errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
+ desc = handshake_failure;
+ ret = SSL_SNI_SEND_ALERT;
+ break;
+ }
+ }
+#endif
+ if (pwsName->data) {
+ SECITEM_FreeItem(pwsName, PR_FALSE);
+ }
+ if (cwsName->data) {
+ rv = SECITEM_CopyItem(NULL, pwsName, cwsName);
+ }
+ ssl_ReleaseSpecWriteLock(ss); /**************************/
+ if (rv != SECSuccess) {
+ errCode = SSL_ERROR_INTERNAL_ERROR_ALERT;
+ desc = internal_error;
ret = SSL_SNI_SEND_ALERT;
break;
}
- }
-#endif
- if (pwsName->data) {
- SECITEM_FreeItem(pwsName, PR_FALSE);
- }
- if (cwsName->data) {
- rv = SECITEM_CopyItem(NULL, pwsName, cwsName);
- }
- ssl_ReleaseSpecWriteLock(ss); /**************************/
- if (rv != SECSuccess) {
- errCode = SSL_ERROR_INTERNAL_ERROR_ALERT;
- desc = internal_error;
- ret = SSL_SNI_SEND_ALERT;
- break;
- }
- } else if ((unsigned int)ret < ss->xtnData.sniNameArrSize) {
- /* Application has configured new socket info. Lets check it
- * and save the name. */
- SECStatus rv;
- SECItem * name = &ss->xtnData.sniNameArr[ret];
- int configedCiphers;
- SECItem * pwsName;
-
- /* get rid of the old name and save the newly picked. */
- /* This code is protected by ssl3HandshakeLock. */
- ssl_GetSpecWriteLock(ss); /*******************************/
+ } else if ((unsigned int)ret < ss->xtnData.sniNameArrSize) {
+ /* Application has configured new socket info. Lets check it
+ * and save the name. */
+ SECStatus rv;
+ SECItem *name = &ss->xtnData.sniNameArr[ret];
+ int configedCiphers;
+ SECItem *pwsName;
+
+ /* get rid of the old name and save the newly picked. */
+ /* This code is protected by ssl3HandshakeLock. */
+ ssl_GetSpecWriteLock(ss); /*******************************/
#ifndef SSL_SNI_ALLOW_NAME_CHANGE_2HS
- /* not allow name change on the 2d HS */
- if (ss->firstHsDone) {
- SECItem *cwsName = &ss->ssl3.cwSpec->srvVirtName;
- if (ssl3_ServerNameCompare(name, cwsName)) {
- ssl_ReleaseSpecWriteLock(ss); /******************/
- errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
+ /* not allow name change on the 2d HS */
+ if (ss->firstHsDone) {
+ SECItem *cwsName = &ss->ssl3.cwSpec->srvVirtName;
+ if (ssl3_ServerNameCompare(name, cwsName)) {
+ ssl_ReleaseSpecWriteLock(ss); /******************/
+ errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
+ desc = handshake_failure;
+ ret = SSL_SNI_SEND_ALERT;
+ break;
+ }
+ }
+#endif
+ pwsName = &ss->ssl3.pwSpec->srvVirtName;
+ if (pwsName->data) {
+ SECITEM_FreeItem(pwsName, PR_FALSE);
+ }
+ rv = SECITEM_CopyItem(NULL, pwsName, name);
+ ssl_ReleaseSpecWriteLock(ss); /***************************/
+ if (rv != SECSuccess) {
+ errCode = SSL_ERROR_INTERNAL_ERROR_ALERT;
+ desc = internal_error;
+ ret = SSL_SNI_SEND_ALERT;
+ break;
+ }
+ configedCiphers = ssl3_config_match_init(ss);
+ if (configedCiphers <= 0) {
+ /* no ciphers are working/supported */
+ errCode = PORT_GetError();
desc = handshake_failure;
ret = SSL_SNI_SEND_ALERT;
break;
}
- }
-#endif
- pwsName = &ss->ssl3.pwSpec->srvVirtName;
- if (pwsName->data) {
- SECITEM_FreeItem(pwsName, PR_FALSE);
- }
- rv = SECITEM_CopyItem(NULL, pwsName, name);
- ssl_ReleaseSpecWriteLock(ss); /***************************/
- if (rv != SECSuccess) {
+ /* Need to tell the client that application has picked
+ * the name from the offered list and reconfigured the socket.
+ */
+ ssl3_RegisterServerHelloExtensionSender(ss, ssl_server_name_xtn,
+ ssl3_SendServerNameXtn);
+ } else {
+ /* Callback returned index outside of the boundary. */
+ PORT_Assert((unsigned int)ret < ss->xtnData.sniNameArrSize);
errCode = SSL_ERROR_INTERNAL_ERROR_ALERT;
desc = internal_error;
ret = SSL_SNI_SEND_ALERT;
break;
}
- configedCiphers = ssl3_config_match_init(ss);
- if (configedCiphers <= 0) {
- /* no ciphers are working/supported */
- errCode = PORT_GetError();
- desc = handshake_failure;
- ret = SSL_SNI_SEND_ALERT;
- break;
- }
- /* Need to tell the client that application has picked
- * the name from the offered list and reconfigured the socket.
- */
- ssl3_RegisterServerHelloExtensionSender(ss, ssl_server_name_xtn,
- ssl3_SendServerNameXtn);
- } else {
- /* Callback returned index outside of the boundary. */
- PORT_Assert((unsigned int)ret < ss->xtnData.sniNameArrSize);
- errCode = SSL_ERROR_INTERNAL_ERROR_ALERT;
- desc = internal_error;
- ret = SSL_SNI_SEND_ALERT;
- break;
- }
- } while (0);
+ } while (0);
/* Free sniNameArr. The data that each SECItem in the array
* points into is the data from the input buffer "b". It will
* not be available outside the scope of this or it's child
@@ -9047,11 +9313,11 @@ compression_found:
/* Check that we don't have the name is current spec
* if this extension was not negotiated on the 2d hs. */
PRBool passed = PR_TRUE;
- ssl_GetSpecReadLock(ss); /*******************************/
+ ssl_GetSpecReadLock(ss); /*******************************/
if (ss->ssl3.cwSpec->srvVirtName.data) {
passed = PR_FALSE;
}
- ssl_ReleaseSpecReadLock(ss); /***************************/
+ ssl_ReleaseSpecReadLock(ss); /***************************/
if (!passed) {
errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
desc = handshake_failure;
@@ -9060,18 +9326,34 @@ compression_found:
}
#endif
+ /* If this is TLS 1.3 we are expecting a ClientKeyShare
+ * extension. Missing/absent extension cause failure
+ * below. */
+ if (isTLS13) {
+ rv = tls13_HandleClientKeyShare(ss);
+ if (rv != SECSuccess) {
+ errCode = PORT_GetError();
+ goto alert_loser;
+ }
+ }
+
sid = ssl3_NewSessionID(ss, PR_TRUE);
if (sid == NULL) {
- errCode = PORT_GetError();
- goto loser; /* memory error is set. */
+ errCode = PORT_GetError();
+ goto loser; /* memory error is set. */
}
ss->sec.ci.sid = sid;
sid->u.ssl3.keys.extendedMasterSecretUsed =
- ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn);
+ ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn);
ss->ssl3.hs.isResuming = PR_FALSE;
+
ssl_GetXmitBufLock(ss);
- rv = ssl3_SendServerHelloSequence(ss);
+ if (isTLS13) {
+ rv = tls13_SendServerHelloSequence(ss);
+ } else {
+ rv = ssl3_SendServerHelloSequence(ss);
+ }
ssl_ReleaseXmitBufLock(ss);
if (rv != SECSuccess) {
errCode = PORT_GetError();
@@ -9080,28 +9362,28 @@ compression_found:
}
if (haveXmitBufLock) {
- ssl_ReleaseXmitBufLock(ss);
- haveXmitBufLock = PR_FALSE;
+ ssl_ReleaseXmitBufLock(ss);
+ haveXmitBufLock = PR_FALSE;
}
return SECSuccess;
alert_loser:
if (haveSpecWriteLock) {
- ssl_ReleaseSpecWriteLock(ss);
- haveSpecWriteLock = PR_FALSE;
+ ssl_ReleaseSpecWriteLock(ss);
+ haveSpecWriteLock = PR_FALSE;
}
(void)SSL3_SendAlert(ss, level, desc);
- /* FALLTHRU */
+/* FALLTHRU */
loser:
if (haveSpecWriteLock) {
- ssl_ReleaseSpecWriteLock(ss);
- haveSpecWriteLock = PR_FALSE;
+ ssl_ReleaseSpecWriteLock(ss);
+ haveSpecWriteLock = PR_FALSE;
}
if (haveXmitBufLock) {
- ssl_ReleaseXmitBufLock(ss);
- haveXmitBufLock = PR_FALSE;
+ ssl_ReleaseXmitBufLock(ss);
+ haveXmitBufLock = PR_FALSE;
}
PORT_SetError(errCode);
@@ -9116,22 +9398,22 @@ loser:
SECStatus
ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length)
{
- sslSessionID * sid = NULL;
- unsigned char * suites;
- unsigned char * random;
+ sslSessionID *sid = NULL;
+ unsigned char *suites;
+ unsigned char *random;
SSL3ProtocolVersion version;
- SECStatus rv;
- int i;
- int j;
- int sid_length;
- int suite_length;
- int rand_length;
- int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
- SSL3AlertDescription desc = handshake_failure;
+ SECStatus rv;
+ int i;
+ int j;
+ int sid_length;
+ int suite_length;
+ int rand_length;
+ int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
+ SSL3AlertDescription desc = handshake_failure;
SSL_TRC(3, ("%d: SSL3[%d]: handle v2 client_hello", SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
ssl_GetSSL3HandshakeLock(ss);
@@ -9139,79 +9421,87 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length)
rv = ssl3_InitState(ss);
if (rv != SECSuccess) {
- ssl_ReleaseSSL3HandshakeLock(ss);
- return rv; /* ssl3_InitState has set the error code. */
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ return rv; /* ssl3_InitState has set the error code. */
}
rv = ssl3_RestartHandshakeHashes(ss);
if (rv != SECSuccess) {
- ssl_ReleaseSSL3HandshakeLock(ss);
- return rv;
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ return rv;
}
if (ss->ssl3.hs.ws != wait_client_hello) {
- desc = unexpected_message;
- errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO;
- goto loser; /* alert_loser */
+ desc = unexpected_message;
+ errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO;
+ goto loser; /* alert_loser */
}
- version = (buffer[1] << 8) | buffer[2];
+ version = (buffer[1] << 8) | buffer[2];
suite_length = (buffer[3] << 8) | buffer[4];
- sid_length = (buffer[5] << 8) | buffer[6];
- rand_length = (buffer[7] << 8) | buffer[8];
+ sid_length = (buffer[5] << 8) | buffer[6];
+ rand_length = (buffer[7] << 8) | buffer[8];
ss->clientHelloVersion = version;
+ if (version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ /* [draft-ietf-tls-tls-11; C.3] forbids sending a TLS 1.3
+ * ClientHello using the backwards-compatible format. */
+ desc = illegal_parameter;
+ errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
+ goto loser;
+ }
+
rv = ssl3_NegotiateVersion(ss, version, PR_TRUE);
if (rv != SECSuccess) {
- /* send back which ever alert client will understand. */
- desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
- : handshake_failure;
- errCode = SSL_ERROR_UNSUPPORTED_VERSION;
- goto alert_loser;
+ /* send back which ever alert client will understand. */
+ desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
+ : handshake_failure;
+ errCode = SSL_ERROR_UNSUPPORTED_VERSION;
+ goto alert_loser;
}
ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
rv = ssl3_InitHandshakeHashes(ss);
if (rv != SECSuccess) {
- desc = internal_error;
- errCode = PORT_GetError();
- goto alert_loser;
+ desc = internal_error;
+ errCode = PORT_GetError();
+ goto alert_loser;
}
/* if we get a non-zero SID, just ignore it. */
if (length !=
SSL_HL_CLIENT_HELLO_HBYTES + suite_length + sid_length + rand_length) {
- SSL_DBG(("%d: SSL3[%d]: bad v2 client hello message, len=%d should=%d",
- SSL_GETPID(), ss->fd, length,
- SSL_HL_CLIENT_HELLO_HBYTES + suite_length + sid_length +
- rand_length));
- goto loser; /* malformed */ /* alert_loser */
+ SSL_DBG(("%d: SSL3[%d]: bad v2 client hello message, len=%d should=%d",
+ SSL_GETPID(), ss->fd, length,
+ SSL_HL_CLIENT_HELLO_HBYTES + suite_length + sid_length +
+ rand_length));
+ goto loser; /* malformed */ /* alert_loser */
}
suites = buffer + SSL_HL_CLIENT_HELLO_HBYTES;
random = suites + suite_length + sid_length;
if (rand_length < SSL_MIN_CHALLENGE_BYTES ||
- rand_length > SSL_MAX_CHALLENGE_BYTES) {
- goto loser; /* malformed */ /* alert_loser */
+ rand_length > SSL_MAX_CHALLENGE_BYTES) {
+ goto loser; /* malformed */ /* alert_loser */
}
PORT_Assert(SSL_MAX_CHALLENGE_BYTES == SSL3_RANDOM_LENGTH);
PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH);
PORT_Memcpy(
- &ss->ssl3.hs.client_random.rand[SSL3_RANDOM_LENGTH - rand_length],
- random, rand_length);
+ &ss->ssl3.hs.client_random.rand[SSL3_RANDOM_LENGTH - rand_length],
+ random, rand_length);
PRINT_BUF(60, (ss, "client random:", &ss->ssl3.hs.client_random.rand[0],
- SSL3_RANDOM_LENGTH));
+ SSL3_RANDOM_LENGTH));
#ifndef NSS_DISABLE_ECC
/* Disable any ECC cipher suites for which we have no cert. */
ssl3_FilterECCipherSuitesByServerCerts(ss);
#endif
i = ssl3_config_match_init(ss);
if (i <= 0) {
- errCode = PORT_GetError(); /* error code is already set. */
- goto alert_loser;
+ errCode = PORT_GetError(); /* error code is already set. */
+ goto alert_loser;
}
/* Select a cipher suite.
@@ -9222,56 +9512,58 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length)
** See the comments about export cipher suites in ssl3_HandleClientHello().
*/
for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
- ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
- SSLVersionRange vrange = {ss->version, ss->version};
- if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss)) {
- continue;
- }
- for (i = 0; i+2 < suite_length; i += 3) {
- PRUint32 suite_i = (suites[i] << 16)|(suites[i+1] << 8)|suites[i+2];
- if (suite_i == suite->cipher_suite) {
- ss->ssl3.hs.cipher_suite = suite->cipher_suite;
- ss->ssl3.hs.suite_def =
- ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
+ ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
+ SSLVersionRange vrange = { ss->version, ss->version };
+ if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange, ss)) {
+ continue;
+ }
+ for (i = 0; i + 2 < suite_length; i += 3) {
+ PRUint32 suite_i = (suites[i] << 16) | (suites[i + 1] << 8) | suites[i + 2];
+ if (suite_i == suite->cipher_suite) {
+ ss->ssl3.hs.cipher_suite = suite->cipher_suite;
+ ss->ssl3.hs.suite_def =
+ ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
+ ss->ssl3.hs.kea_def =
+ &kea_defs[ss->ssl3.hs.suite_def->key_exchange_alg];
ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
- goto suite_found;
- }
- }
+ goto suite_found;
+ }
+ }
}
errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
goto alert_loser;
suite_found:
- /* Look for the SCSV, and if found, treat it just like an empty RI
+ /* Look for the SCSV, and if found, treat it just like an empty RI
* extension by processing a local copy of an empty RI extension.
*/
- for (i = 0; i+2 < suite_length; i += 3) {
- PRUint32 suite_i = (suites[i] << 16) | (suites[i+1] << 8) | suites[i+2];
- if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) {
- SSL3Opaque * b2 = (SSL3Opaque *)emptyRIext;
- PRUint32 L2 = sizeof emptyRIext;
- (void)ssl3_HandleHelloExtensions(ss, &b2, &L2);
- break;
- }
+ for (i = 0; i + 2 < suite_length; i += 3) {
+ PRUint32 suite_i = (suites[i] << 16) | (suites[i + 1] << 8) | suites[i + 2];
+ if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) {
+ SSL3Opaque *b2 = (SSL3Opaque *)emptyRIext;
+ PRUint32 L2 = sizeof emptyRIext;
+ (void)ssl3_HandleHelloExtensions(ss, &b2, &L2, client_hello);
+ break;
+ }
}
if (ss->opt.requireSafeNegotiation &&
- !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
- desc = handshake_failure;
- errCode = SSL_ERROR_UNSAFE_NEGOTIATION;
- goto alert_loser;
+ !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
+ desc = handshake_failure;
+ errCode = SSL_ERROR_UNSAFE_NEGOTIATION;
+ goto alert_loser;
}
ss->ssl3.hs.compression = ssl_compression_null;
- ss->sec.send = ssl3_SendApplicationData;
+ ss->sec.send = ssl3_SendApplicationData;
/* we don't even search for a cache hit here. It's just a miss. */
- SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_misses );
+ SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_misses);
sid = ssl3_NewSessionID(ss, PR_TRUE);
if (sid == NULL) {
- errCode = PORT_GetError();
- goto loser; /* memory error is set. */
+ errCode = PORT_GetError();
+ goto loser; /* memory error is set. */
}
ss->sec.ci.sid = sid;
/* do not worry about memory leak of sid since it now belongs to ci */
@@ -9279,23 +9571,23 @@ suite_found:
/* We have to update the handshake hashes before we can send stuff */
rv = ssl3_UpdateHandshakeHashes(ss, buffer, length);
if (rv != SECSuccess) {
- errCode = PORT_GetError();
- goto loser;
+ errCode = PORT_GetError();
+ goto loser;
}
ssl_GetXmitBufLock(ss);
rv = ssl3_SendServerHelloSequence(ss);
ssl_ReleaseXmitBufLock(ss);
if (rv != SECSuccess) {
- errCode = PORT_GetError();
- goto loser;
+ errCode = PORT_GetError();
+ goto loser;
}
- /* XXX_1 The call stack to here is:
+ /* XXX_1 The call stack to here is:
* ssl_Do1stHandshake -> ssl2_HandleClientHelloMessage -> here.
* ssl2_HandleClientHelloMessage returns whatever we return here.
* ssl_Do1stHandshake will continue looping if it gets back either
- * SECSuccess or SECWouldBlock.
+ * SECSuccess or SECWouldBlock.
* SECSuccess is preferable here. See XXX_1 in sslgathr.c.
*/
ssl_ReleaseSSL3HandshakeLock(ss);
@@ -9312,113 +9604,123 @@ loser:
/* The negotiated version number has been already placed in ss->version.
**
** Called from: ssl3_HandleClientHello (resuming session),
-** ssl3_SendServerHelloSequence <- ssl3_HandleClientHello (new session),
-** ssl3_SendServerHelloSequence <- ssl3_HandleV2ClientHello (new session)
+** ssl3_SendServerHelloSequence <- ssl3_HandleClientHello (new session),
+** ssl3_SendServerHelloSequence <- ssl3_HandleV2ClientHello (new session)
*/
-static SECStatus
+SECStatus
ssl3_SendServerHello(sslSocket *ss)
{
sslSessionID *sid;
- SECStatus rv;
- PRUint32 maxBytes = 65535;
- PRUint32 length;
- PRInt32 extensions_len = 0;
+ SECStatus rv;
+ PRUint32 maxBytes = 65535;
+ PRUint32 length;
+ PRInt32 extensions_len = 0;
SSL3ProtocolVersion version;
SSL_TRC(3, ("%d: SSL3[%d]: send server_hello handshake", SSL_GETPID(),
- ss->fd));
+ ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (!IS_DTLS(ss)) {
- PORT_Assert(MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_3_0));
+ PORT_Assert(MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_3_0));
- if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_3_0)) {
- PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
- return SECFailure;
- }
+ if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_3_0)) {
+ PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
+ return SECFailure;
+ }
} else {
- PORT_Assert(MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_DTLS_1_0));
+ PORT_Assert(MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_DTLS_1_0));
- if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_DTLS_1_0)) {
- PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
- return SECFailure;
- }
+ if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_DTLS_1_0)) {
+ PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
+ return SECFailure;
+ }
}
sid = ss->sec.ci.sid;
- extensions_len = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, maxBytes,
- &ss->xtnData.serverSenders[0]);
+ extensions_len = ssl3_CallHelloExtensionSenders(
+ ss, PR_FALSE, maxBytes, &ss->xtnData.serverHelloSenders[0]);
if (extensions_len > 0)
- extensions_len += 2; /* Add sizeof total extension length */
+ extensions_len += 2; /* Add sizeof total extension length */
+
+ /* TLS 1.3 doesn't use the session_id or compression_method
+ * fields in the ServerHello. */
+ length = sizeof(SSL3ProtocolVersion) + SSL3_RANDOM_LENGTH;
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ length += 1 + ((sid == NULL) ? 0 : sid->u.ssl3.sessionIDLength);
+ }
+ length += sizeof(ssl3CipherSuite);
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ length += 1; /* Compression */
+ }
+ length += extensions_len;
- length = sizeof(SSL3ProtocolVersion) + SSL3_RANDOM_LENGTH + 1 +
- ((sid == NULL) ? 0: sid->u.ssl3.sessionIDLength) +
- sizeof(ssl3CipherSuite) + 1 + extensions_len;
rv = ssl3_AppendHandshakeHeader(ss, server_hello, length);
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
}
if (IS_DTLS(ss)) {
- version = dtls_TLSVersionToDTLSVersion(ss->version);
+ version = dtls_TLSVersionToDTLSVersion(ss->version);
} else {
- version = ss->version;
+ version = ss->version;
}
rv = ssl3_AppendHandshakeNumber(ss, version, 2);
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
- }
- rv = ssl3_GetNewRandom(&ss->ssl3.hs.server_random);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
- return rv;
+ return rv; /* err set by AppendHandshake. */
}
+ /* Random already generated in ssl3_HandleClientHello */
rv = ssl3_AppendHandshake(
- ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH);
+ ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH);
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
}
- if (sid)
- rv = ssl3_AppendHandshakeVariable(
- ss, sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength, 1);
- else
- rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
- if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ if (sid) {
+ rv = ssl3_AppendHandshakeVariable(
+ ss, sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength, 1);
+ } else {
+ rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
+ }
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
}
rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.cipher_suite, 2);
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
}
- rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.compression, 1);
- if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.compression, 1);
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
}
if (extensions_len) {
- PRInt32 sent_len;
-
- extensions_len -= 2;
- rv = ssl3_AppendHandshakeNumber(ss, extensions_len, 2);
- if (rv != SECSuccess)
- return rv; /* err set by ssl3_SetupPendingCipherSpec */
- sent_len = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, extensions_len,
- &ss->xtnData.serverSenders[0]);
+ PRInt32 sent_len;
+
+ extensions_len -= 2;
+ rv = ssl3_AppendHandshakeNumber(ss, extensions_len, 2);
+ if (rv != SECSuccess)
+ return rv; /* err set by ssl3_AppendHandshakeNumber */
+ sent_len = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, extensions_len,
+ &ss->xtnData.serverHelloSenders[0]);
PORT_Assert(sent_len == extensions_len);
- if (sent_len != extensions_len) {
- if (sent_len >= 0)
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
- }
+ if (sent_len != extensions_len) {
+ if (sent_len >= 0)
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
}
rv = ssl3_SetupPendingCipherSpec(ss);
if (rv != SECSuccess) {
- return rv; /* err set by ssl3_SetupPendingCipherSpec */
+ return rv; /* err set by ssl3_SetupPendingCipherSpec */
}
return SECSuccess;
@@ -9426,30 +9728,30 @@ ssl3_SendServerHello(sslSocket *ss)
static SECStatus
ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
- SSLSignatureAndHashAlg* out);
+ SSLSignatureAndHashAlg *out);
static SECStatus
ssl3_SendDHServerKeyExchange(sslSocket *ss)
{
- const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def;
- SECStatus rv = SECFailure;
- int length;
- PRBool isTLS;
- SECItem signed_hash = {siBuffer, NULL, 0};
- SSL3Hashes hashes;
+ const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
+ SECStatus rv = SECFailure;
+ int length;
+ PRBool isTLS;
+ SECItem signed_hash = { siBuffer, NULL, 0 };
+ SSL3Hashes hashes;
SSLSignatureAndHashAlg sigAndHash;
SECKEYDHParams dhParam;
ssl3KeyPair *keyPair = NULL;
- SECKEYPublicKey *pubKey = NULL; /* Ephemeral DH key */
+ SECKEYPublicKey *pubKey = NULL; /* Ephemeral DH key */
SECKEYPrivateKey *privKey = NULL; /* Ephemeral DH key */
int certIndex = -1;
if (kea_def->kea != kea_dhe_dss && kea_def->kea != kea_dhe_rsa) {
- /* TODO: Support DH_anon. It might be sufficient to drop the signature.
- See bug 1170510. */
- PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
- return SECFailure;
+ /* TODO: Support DH_anon. It might be sufficient to drop the signature.
+ See bug 1170510. */
+ PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
+ return SECFailure;
}
dhParam.prime.data = ss->dheParams->prime.data;
@@ -9508,55 +9810,55 @@ ssl3_SendDHServerKeyExchange(sslSocket *ss)
rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY,
&signed_hash, isTLS);
if (rv != SECSuccess) {
- goto loser; /* ssl3_SignHashes has set err. */
+ goto loser; /* ssl3_SignHashes has set err. */
}
if (signed_hash.data == NULL) {
PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
goto loser;
}
length = 2 + pubKey->u.dh.prime.len +
- 2 + pubKey->u.dh.base.len +
- 2 + pubKey->u.dh.publicValue.len +
- 2 + signed_hash.len;
+ 2 + pubKey->u.dh.base.len +
+ 2 + pubKey->u.dh.publicValue.len +
+ 2 + signed_hash.len;
if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
- length += 2;
+ length += 2;
}
rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
+ goto loser; /* err set by AppendHandshake. */
}
rv = ssl3_AppendHandshakeVariable(ss, pubKey->u.dh.prime.data,
pubKey->u.dh.prime.len, 2);
if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
+ goto loser; /* err set by AppendHandshake. */
}
rv = ssl3_AppendHandshakeVariable(ss, pubKey->u.dh.base.data,
pubKey->u.dh.base.len, 2);
if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
+ goto loser; /* err set by AppendHandshake. */
}
rv = ssl3_AppendHandshakeVariable(ss, pubKey->u.dh.publicValue.data,
pubKey->u.dh.publicValue.len, 2);
if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
+ goto loser; /* err set by AppendHandshake. */
}
if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
- rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
- if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
- }
+ rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by AppendHandshake. */
+ }
}
rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
signed_hash.len, 2);
if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
+ goto loser; /* err set by AppendHandshake. */
}
PORT_Free(signed_hash.data);
ss->dheKeyPair = keyPair;
@@ -9579,40 +9881,12 @@ loser:
* hash combinations. */
static SECStatus
ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
- SSLSignatureAndHashAlg* out)
+ SSLSignatureAndHashAlg *out)
{
- SSLSignType sigAlg;
PRUint32 policy;
unsigned int i, j;
- switch (ss->ssl3.hs.kea_def->kea) {
- case kea_rsa:
- case kea_rsa_export:
- case kea_rsa_export_1024:
- case kea_dh_rsa:
- case kea_dh_rsa_export:
- case kea_dhe_rsa:
- case kea_dhe_rsa_export:
- case kea_rsa_fips:
- case kea_ecdh_rsa:
- case kea_ecdhe_rsa:
- sigAlg = ssl_sign_rsa;
- break;
- case kea_dh_dss:
- case kea_dh_dss_export:
- case kea_dhe_dss:
- case kea_dhe_dss_export:
- sigAlg = ssl_sign_dsa;
- break;
- case kea_ecdh_ecdsa:
- case kea_ecdhe_ecdsa:
- sigAlg = ssl_sign_ecdsa;
- break;
- default:
- PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
- return SECFailure;
- }
- out->sigAlg = sigAlg;
+ out->sigAlg = ss->ssl3.hs.kea_def->signKeyType;
if (ss->version <= SSL_LIBRARY_VERSION_TLS_1_1) {
/* SEC_OID_UNKNOWN means the MD5/SHA1 combo hash used in TLS 1.1 and
@@ -9633,22 +9907,22 @@ ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
* indicated support for in their signature_algorithms extension. */
for (i = 0; i < ss->ssl3.signatureAlgorithmCount; ++i) {
const SSLSignatureAndHashAlg *serverPref =
- &ss->ssl3.signatureAlgorithms[i];
- SECOidTag hashOID;
- if (serverPref->sigAlg != sigAlg) {
+ &ss->ssl3.signatureAlgorithms[i];
+ SECOidTag hashOID;
+ if (serverPref->sigAlg != out->sigAlg) {
continue;
}
hashOID = ssl3_TLSHashAlgorithmToOID(serverPref->hashAlg);
- if ((NSS_GetAlgorithmPolicy(hashOID, &policy) != SECSuccess)
- || !(policy & NSS_USE_ALG_IN_SSL_KX)) {
- /* we ignore hashes we don't support */
- continue;
- }
+ if ((NSS_GetAlgorithmPolicy(hashOID, &policy) == SECSuccess) &&
+ !(policy & NSS_USE_ALG_IN_SSL_KX)) {
+ /* we ignore hashes we don't support */
+ continue;
+ }
for (j = 0; j < ss->ssl3.hs.numClientSigAndHash; j++) {
const SSLSignatureAndHashAlg *clientPref =
&ss->ssl3.hs.clientSigAndHash[j];
if (clientPref->hashAlg == serverPref->hashAlg &&
- clientPref->sigAlg == sigAlg) {
+ clientPref->sigAlg == out->sigAlg) {
out->hashAlg = serverPref->hashAlg;
return SECSuccess;
}
@@ -9659,125 +9933,124 @@ ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
return SECFailure;
}
-
static SECStatus
ssl3_SendServerKeyExchange(sslSocket *ss)
{
- const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def;
- SECStatus rv = SECFailure;
- int length;
- PRBool isTLS;
- SECItem signed_hash = {siBuffer, NULL, 0};
- SSL3Hashes hashes;
- SECKEYPublicKey * sdPub; /* public key for step-down */
+ const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
+ SECStatus rv = SECFailure;
+ int length;
+ PRBool isTLS;
+ SECItem signed_hash = { siBuffer, NULL, 0 };
+ SSL3Hashes hashes;
+ SECKEYPublicKey *sdPub; /* public key for step-down */
SSLSignatureAndHashAlg sigAndHash;
SSL_TRC(3, ("%d: SSL3[%d]: send server_key_exchange handshake",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ssl3_PickSignatureHashAlgorithm(ss, &sigAndHash) != SECSuccess) {
- return SECFailure;
+ return SECFailure;
}
switch (kea_def->exchKeyType) {
- case kt_rsa:
- /* Perform SSL Step-Down here. */
- sdPub = ss->stepDownKeyPair->pubKey;
- PORT_Assert(sdPub != NULL);
- if (!sdPub) {
- PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
- return SECFailure;
- }
- rv = ssl3_ComputeExportRSAKeyHash(sigAndHash.hashAlg,
- sdPub->u.rsa.modulus,
- sdPub->u.rsa.publicExponent,
- &ss->ssl3.hs.client_random,
- &ss->ssl3.hs.server_random,
- &hashes, ss->opt.bypassPKCS11);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
- return rv;
- }
+ case kt_rsa:
+ /* Perform SSL Step-Down here. */
+ sdPub = ss->stepDownKeyPair->pubKey;
+ PORT_Assert(sdPub != NULL);
+ if (!sdPub) {
+ PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
+ return SECFailure;
+ }
+ rv = ssl3_ComputeExportRSAKeyHash(sigAndHash.hashAlg,
+ sdPub->u.rsa.modulus,
+ sdPub->u.rsa.publicExponent,
+ &ss->ssl3.hs.client_random,
+ &ss->ssl3.hs.server_random,
+ &hashes, ss->opt.bypassPKCS11);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
+ return rv;
+ }
- isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
- rv = ssl3_SignHashes(&hashes, ss->serverCerts[kt_rsa].SERVERKEY,
- &signed_hash, isTLS);
- if (rv != SECSuccess) {
- goto loser; /* ssl3_SignHashes has set err. */
- }
- if (signed_hash.data == NULL) {
- /* how can this happen and rv == SECSuccess ?? */
- PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
- goto loser;
- }
- length = 2 + sdPub->u.rsa.modulus.len +
- 2 + sdPub->u.rsa.publicExponent.len +
- 2 + signed_hash.len;
-
- if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
- length += 2;
- }
-
- rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
- if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
- }
-
- rv = ssl3_AppendHandshakeVariable(ss, sdPub->u.rsa.modulus.data,
- sdPub->u.rsa.modulus.len, 2);
- if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
- }
-
- rv = ssl3_AppendHandshakeVariable(
- ss, sdPub->u.rsa.publicExponent.data,
- sdPub->u.rsa.publicExponent.len, 2);
- if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
- }
-
- if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
- rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
- if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
- }
- }
-
- rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
- signed_hash.len, 2);
- if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
- }
- PORT_Free(signed_hash.data);
- return SECSuccess;
-
- case ssl_kea_dh: {
- rv = ssl3_SendDHServerKeyExchange(ss);
- return rv;
- }
+ isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
+ rv = ssl3_SignHashes(&hashes, ss->serverCerts[kt_rsa].SERVERKEY,
+ &signed_hash, isTLS);
+ if (rv != SECSuccess) {
+ goto loser; /* ssl3_SignHashes has set err. */
+ }
+ if (signed_hash.data == NULL) {
+ /* how can this happen and rv == SECSuccess ?? */
+ PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
+ goto loser;
+ }
+ length = 2 + sdPub->u.rsa.modulus.len +
+ 2 + sdPub->u.rsa.publicExponent.len +
+ 2 + signed_hash.len;
+
+ if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+ length += 2;
+ }
+
+ rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by AppendHandshake. */
+ }
+
+ rv = ssl3_AppendHandshakeVariable(ss, sdPub->u.rsa.modulus.data,
+ sdPub->u.rsa.modulus.len, 2);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by AppendHandshake. */
+ }
+
+ rv = ssl3_AppendHandshakeVariable(
+ ss, sdPub->u.rsa.publicExponent.data,
+ sdPub->u.rsa.publicExponent.len, 2);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by AppendHandshake. */
+ }
+
+ if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+ rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by AppendHandshake. */
+ }
+ }
+
+ rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
+ signed_hash.len, 2);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by AppendHandshake. */
+ }
+ PORT_Free(signed_hash.data);
+ return SECSuccess;
+
+ case ssl_kea_dh: {
+ rv = ssl3_SendDHServerKeyExchange(ss);
+ return rv;
+ }
#ifndef NSS_DISABLE_ECC
- case kt_ecdh: {
- rv = ssl3_SendECDHServerKeyExchange(ss, &sigAndHash);
- return rv;
- }
+ case kt_ecdh: {
+ rv = ssl3_SendECDHServerKeyExchange(ss, &sigAndHash);
+ return rv;
+ }
#endif /* NSS_DISABLE_ECC */
- case kt_null:
- default:
- PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
- break;
+ case kt_null:
+ default:
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
+ break;
}
loser:
- if (signed_hash.data != NULL)
- PORT_Free(signed_hash.data);
+ if (signed_hash.data != NULL)
+ PORT_Free(signed_hash.data);
return SECFailure;
}
-static SECStatus
+SECStatus
ssl3_EncodeCertificateRequestSigAlgs(sslSocket *ss, PRUint8 *buf,
unsigned maxLen, PRUint32 *len)
{
@@ -9808,47 +10081,60 @@ ssl3_EncodeCertificateRequestSigAlgs(sslSocket *ss, PRUint8 *buf,
return SECSuccess;
}
-static SECStatus
-ssl3_SendCertificateRequest(sslSocket *ss)
+void
+ssl3_GetCertificateRequestCAs(sslSocket *ss, int *calen, SECItem **names,
+ int *nnames)
{
- PRBool isTLS12;
- SECItem * name;
+ SECItem *name;
CERTDistNames *ca_list;
- const PRUint8 *certTypes;
- SECItem * names = NULL;
- SECStatus rv;
- int length;
- int i;
- int calen = 0;
- int nnames = 0;
- int certTypesLength;
- PRUint8 sigAlgs[MAX_SIGNATURE_ALGORITHMS * 2];
- unsigned int sigAlgsLength = 0;
-
- SSL_TRC(3, ("%d: SSL3[%d]: send certificate_request handshake",
- SSL_GETPID(), ss->fd));
-
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ int i;
- isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
+ *calen = 0;
+ *names = NULL;
+ *nnames = 0;
/* ssl3.ca_list is initialized to NULL, and never changed. */
ca_list = ss->ssl3.ca_list;
if (!ca_list) {
- ca_list = ssl3_server_ca_list;
+ ca_list = ssl3_server_ca_list;
}
if (ca_list != NULL) {
- names = ca_list->names;
- nnames = ca_list->nnames;
+ *names = ca_list->names;
+ *nnames = ca_list->nnames;
}
- for (i = 0, name = names; i < nnames; i++, name++) {
- calen += 2 + name->len;
+ for (i = 0, name = *names; i < *nnames; i++, name++) {
+ *calen += 2 + name->len;
}
+}
+
+static SECStatus
+ssl3_SendCertificateRequest(sslSocket *ss)
+{
+ PRBool isTLS12;
+ const PRUint8 *certTypes;
+ SECStatus rv;
+ int length;
+ SECItem *names;
+ int calen;
+ int nnames;
+ SECItem *name;
+ int i;
+ int certTypesLength;
+ PRUint8 sigAlgs[MAX_SIGNATURE_ALGORITHMS * 2];
+ unsigned int sigAlgsLength = 0;
+
+ SSL_TRC(3, ("%d: SSL3[%d]: send certificate_request handshake",
+ SSL_GETPID(), ss->fd));
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
- certTypes = certificate_types;
+ ssl3_GetCertificateRequestCAs(ss, &calen, &names, &nnames);
+ certTypes = certificate_types;
certTypesLength = sizeof certificate_types;
length = 1 + certTypesLength + 2 + calen;
@@ -9863,27 +10149,27 @@ ssl3_SendCertificateRequest(sslSocket *ss)
rv = ssl3_AppendHandshakeHeader(ss, certificate_request, length);
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
}
rv = ssl3_AppendHandshakeVariable(ss, certTypes, certTypesLength, 1);
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
}
if (isTLS12) {
- rv = ssl3_AppendHandshakeVariable(ss, sigAlgs, sigAlgsLength, 2);
- if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
- }
+ rv = ssl3_AppendHandshakeVariable(ss, sigAlgs, sigAlgsLength, 2);
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
}
rv = ssl3_AppendHandshakeNumber(ss, calen, 2);
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
}
for (i = 0, name = names; i < nnames; i++, name++) {
- rv = ssl3_AppendHandshakeVariable(ss, name->data, name->len, 2);
- if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
- }
+ rv = ssl3_AppendHandshakeVariable(ss, name->data, name->len, 2);
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
}
return SECSuccess;
@@ -9895,100 +10181,100 @@ ssl3_SendServerHelloDone(sslSocket *ss)
SECStatus rv;
SSL_TRC(3, ("%d: SSL3[%d]: send server_hello_done handshake",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
rv = ssl3_AppendHandshakeHeader(ss, server_hello_done, 0);
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
}
rv = ssl3_FlushHandshake(ss, 0);
if (rv != SECSuccess) {
- return rv; /* error code set by ssl3_FlushHandshake */
+ return rv; /* error code set by ssl3_FlushHandshake */
}
return SECSuccess;
}
-/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
- * ssl3 Certificate Verify message
+/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
+ * a complete ssl3 Certificate Verify message
* Caller must hold Handshake and RecvBuf locks.
*/
static SECStatus
ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
- SSL3Hashes *hashes)
+ SSL3Hashes *hashes)
{
- SECItem signed_hash = {siBuffer, NULL, 0};
- SECStatus rv;
- int errCode = SSL_ERROR_RX_MALFORMED_CERT_VERIFY;
- SSL3AlertDescription desc = handshake_failure;
- PRBool isTLS, isTLS12;
+ SECItem signed_hash = { siBuffer, NULL, 0 };
+ SECStatus rv;
+ int errCode = SSL_ERROR_RX_MALFORMED_CERT_VERIFY;
+ SSL3AlertDescription desc = handshake_failure;
+ PRBool isTLS, isTLS12;
SSLSignatureAndHashAlg sigAndHash;
SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_verify handshake",
- SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ SSL_GETPID(), ss->fd));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
if (ss->ssl3.hs.ws != wait_cert_verify) {
- desc = unexpected_message;
- errCode = SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY;
- goto alert_loser;
+ desc = unexpected_message;
+ errCode = SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY;
+ goto alert_loser;
}
if (!hashes) {
PORT_Assert(0);
- desc = internal_error;
- errCode = SEC_ERROR_LIBRARY_FAILURE;
- goto alert_loser;
+ desc = internal_error;
+ errCode = SEC_ERROR_LIBRARY_FAILURE;
+ goto alert_loser;
}
if (isTLS12) {
- rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
- &sigAndHash);
- if (rv != SECSuccess) {
- goto loser; /* malformed or unsupported. */
- }
- rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
+ rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
+ &sigAndHash);
+ if (rv != SECSuccess) {
+ goto loser; /* malformed or unsupported. */
+ }
+ rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
ss, &sigAndHash, ss->sec.peerCert);
- if (rv != SECSuccess) {
- errCode = PORT_GetError();
- desc = decrypt_error;
- goto alert_loser;
- }
-
- /* We only support CertificateVerify messages that use the handshake
- * hash. */
+ if (rv != SECSuccess) {
+ errCode = PORT_GetError();
+ desc = decrypt_error;
+ goto alert_loser;
+ }
+
+ /* We only support CertificateVerify messages that use the handshake
+ * hash. */
if (sigAndHash.hashAlg != hashes->hashAlg) {
- errCode = SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM;
- desc = decrypt_error;
- goto alert_loser;
- }
+ errCode = SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM;
+ desc = decrypt_error;
+ goto alert_loser;
+ }
}
rv = ssl3_ConsumeHandshakeVariable(ss, &signed_hash, 2, &b, &length);
if (rv != SECSuccess) {
- goto loser; /* malformed. */
+ goto loser; /* malformed. */
}
/* XXX verify that the key & kea match */
rv = ssl3_VerifySignedHashes(hashes, ss->sec.peerCert, &signed_hash,
- isTLS, ss->pkcs11PinArg);
+ isTLS, ss->pkcs11PinArg);
if (rv != SECSuccess) {
- errCode = PORT_GetError();
- desc = isTLS ? decrypt_error : handshake_failure;
- goto alert_loser;
+ errCode = PORT_GetError();
+ desc = isTLS ? decrypt_error : handshake_failure;
+ goto alert_loser;
}
signed_hash.data = NULL;
if (length != 0) {
- desc = isTLS ? decode_error : illegal_parameter;
- goto alert_loser; /* malformed */
+ desc = isTLS ? decode_error : illegal_parameter;
+ goto alert_loser; /* malformed */
}
ss->ssl3.hs.ws = wait_change_cipher;
return SECSuccess;
@@ -10000,78 +10286,76 @@ loser:
return SECFailure;
}
-
/* find a slot that is able to generate a PMS and wrap it with RSA.
* Then generate and return the PMS.
* If the serverKeySlot parameter is non-null, this function will use
* that slot to do the job, otherwise it will find a slot.
*
* Called from ssl3_DeriveConnectionKeysPKCS11() (above)
- * sendRSAClientKeyExchange() (above)
- * ssl3_HandleRSAClientKeyExchange() (below)
+ * sendRSAClientKeyExchange() (above)
+ * ssl3_HandleRSAClientKeyExchange() (below)
* Caller must hold the SpecWriteLock, the SSL3HandshakeLock
*/
static PK11SymKey *
ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
- PK11SlotInfo * serverKeySlot)
+ PK11SlotInfo *serverKeySlot)
{
- PK11SymKey * pms = NULL;
- PK11SlotInfo * slot = serverKeySlot;
- void * pwArg = ss->pkcs11PinArg;
- SECItem param;
- CK_VERSION version;
+ PK11SymKey *pms = NULL;
+ PK11SlotInfo *slot = serverKeySlot;
+ void *pwArg = ss->pkcs11PinArg;
+ SECItem param;
+ CK_VERSION version;
CK_MECHANISM_TYPE mechanism_array[3];
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (slot == NULL) {
- SSLCipherAlgorithm calg;
- /* The specReadLock would suffice here, but we cannot assert on
- ** read locks. Also, all the callers who call with a non-null
- ** slot already hold the SpecWriteLock.
- */
- PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
- PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
+ SSLCipherAlgorithm calg;
+ /* The specReadLock would suffice here, but we cannot assert on
+ ** read locks. Also, all the callers who call with a non-null
+ ** slot already hold the SpecWriteLock.
+ */
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
+ PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
calg = spec->cipher_def->calg;
- PORT_Assert(alg2Mech[calg].calg == calg);
-
- /* First get an appropriate slot. */
- mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN;
- mechanism_array[1] = CKM_RSA_PKCS;
- mechanism_array[2] = alg2Mech[calg].cmech;
- slot = PK11_GetBestSlotMultiple(mechanism_array, 3, pwArg);
- if (slot == NULL) {
- /* can't find a slot with all three, find a slot with the minimum */
- slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg);
- if (slot == NULL) {
- PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND);
- return pms; /* which is NULL */
- }
- }
+ /* First get an appropriate slot. */
+ mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN;
+ mechanism_array[1] = CKM_RSA_PKCS;
+ mechanism_array[2] = ssl3_Alg2Mech(calg);
+
+ slot = PK11_GetBestSlotMultiple(mechanism_array, 3, pwArg);
+ if (slot == NULL) {
+ /* can't find a slot with all three, find a slot with the minimum */
+ slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg);
+ if (slot == NULL) {
+ PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND);
+ return pms; /* which is NULL */
+ }
+ }
}
/* Generate the pre-master secret ... */
if (IS_DTLS(ss)) {
- SSL3ProtocolVersion temp;
+ SSL3ProtocolVersion temp;
- temp = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion);
- version.major = MSB(temp);
- version.minor = LSB(temp);
+ temp = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion);
+ version.major = MSB(temp);
+ version.minor = LSB(temp);
} else {
- version.major = MSB(ss->clientHelloVersion);
- version.minor = LSB(ss->clientHelloVersion);
+ version.major = MSB(ss->clientHelloVersion);
+ version.minor = LSB(ss->clientHelloVersion);
}
param.data = (unsigned char *)&version;
- param.len = sizeof version;
+ param.len = sizeof version;
pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, &param, 0, pwArg);
if (!serverKeySlot)
- PK11_FreeSlot(slot);
+ PK11_FreeSlot(slot);
if (pms == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
}
return pms;
}
@@ -10091,48 +10375,48 @@ ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
static SECStatus
ssl3_HandleRSAClientKeyExchange(sslSocket *ss,
SSL3Opaque *b,
- PRUint32 length,
- SECKEYPrivateKey *serverKey)
+ PRUint32 length,
+ SECKEYPrivateKey *serverKey)
{
#ifndef NO_PKCS11_BYPASS
- unsigned char * cr = (unsigned char *)&ss->ssl3.hs.client_random;
- unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random;
- ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec;
- unsigned int outLen = 0;
- PRBool isTLS = PR_FALSE;
- SECItem pmsItem = {siBuffer, NULL, 0};
- unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
+ unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random;
+ unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random;
+ ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
+ unsigned int outLen = 0;
+ PRBool isTLS = PR_FALSE;
+ SECItem pmsItem = { siBuffer, NULL, 0 };
+ unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
#endif
- SECStatus rv;
- SECItem enc_pms;
+ SECStatus rv;
+ SECItem enc_pms;
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( ss->ssl3.prSpec == ss->ssl3.pwSpec );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
enc_pms.data = b;
- enc_pms.len = length;
+ enc_pms.len = length;
#ifndef NO_PKCS11_BYPASS
pmsItem.data = rsaPmsBuf;
- pmsItem.len = sizeof rsaPmsBuf;
+ pmsItem.len = sizeof rsaPmsBuf;
#endif
if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
- PRInt32 kLen;
- kLen = ssl3_ConsumeHandshakeNumber(ss, 2, &enc_pms.data, &enc_pms.len);
- if (kLen < 0) {
- PORT_SetError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
- return SECFailure;
- }
- if ((unsigned)kLen < enc_pms.len) {
- enc_pms.len = kLen;
- }
+ PRInt32 kLen;
+ kLen = ssl3_ConsumeHandshakeNumber(ss, 2, &enc_pms.data, &enc_pms.len);
+ if (kLen < 0) {
+ PORT_SetError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ return SECFailure;
+ }
+ if ((unsigned)kLen < enc_pms.len) {
+ enc_pms.len = kLen;
+ }
#ifndef NO_PKCS11_BYPASS
- isTLS = PR_TRUE;
+ isTLS = PR_TRUE;
#endif
} else {
#ifndef NO_PKCS11_BYPASS
- isTLS = (PRBool)(ss->ssl3.hs.kea_def->tls_keygen != 0);
+ isTLS = (PRBool)(ss->ssl3.hs.kea_def->tls_keygen != 0);
#endif
}
@@ -10145,54 +10429,54 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss,
PORT_Assert(
!ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn));
- /* TRIPLE BYPASS, get PMS directly from RSA decryption.
- * Use PK11_PrivDecryptPKCS1 to decrypt the PMS to a buffer,
- * then, check for version rollback attack, then
- * do the equivalent of ssl3_DeriveMasterSecret, placing the MS in
- * pwSpec->msItem. Finally call ssl3_InitPendingCipherSpec with
- * ss and NULL, so that it will use the MS we've already derived here.
- */
-
- rv = PK11_PrivDecryptPKCS1(serverKey, rsaPmsBuf, &outLen,
- sizeof rsaPmsBuf, enc_pms.data, enc_pms.len);
- if (rv != SECSuccess) {
- /* triple bypass failed. Let's try for a double bypass. */
- goto double_bypass;
- } else if (ss->opt.detectRollBack) {
- SSL3ProtocolVersion client_version =
- (rsaPmsBuf[0] << 8) | rsaPmsBuf[1];
-
- if (IS_DTLS(ss)) {
- client_version = dtls_DTLSVersionToTLSVersion(client_version);
- }
-
- if (client_version != ss->clientHelloVersion) {
- /* Version roll-back detected. ensure failure. */
- rv = PK11_GenerateRandom(rsaPmsBuf, sizeof rsaPmsBuf);
- }
- }
- /* have PMS, build MS without PKCS11 */
- rv = ssl3_MasterSecretDeriveBypass(pwSpec, cr, sr, &pmsItem, isTLS,
+ /* TRIPLE BYPASS, get PMS directly from RSA decryption.
+ * Use PK11_PrivDecryptPKCS1 to decrypt the PMS to a buffer,
+ * then, check for version rollback attack, then
+ * do the equivalent of ssl3_DeriveMasterSecret, placing the MS in
+ * pwSpec->msItem. Finally call ssl3_InitPendingCipherSpec with
+ * ss and NULL, so that it will use the MS we've already derived here.
+ */
+
+ rv = PK11_PrivDecryptPKCS1(serverKey, rsaPmsBuf, &outLen,
+ sizeof rsaPmsBuf, enc_pms.data, enc_pms.len);
+ if (rv != SECSuccess) {
+ /* triple bypass failed. Let's try for a double bypass. */
+ goto double_bypass;
+ } else if (ss->opt.detectRollBack) {
+ SSL3ProtocolVersion client_version =
+ (rsaPmsBuf[0] << 8) | rsaPmsBuf[1];
+
+ if (IS_DTLS(ss)) {
+ client_version = dtls_DTLSVersionToTLSVersion(client_version);
+ }
+
+ if (client_version != ss->clientHelloVersion) {
+ /* Version roll-back detected. ensure failure. */
+ rv = PK11_GenerateRandom(rsaPmsBuf, sizeof rsaPmsBuf);
+ }
+ }
+ /* have PMS, build MS without PKCS11 */
+ rv = ssl3_MasterSecretDeriveBypass(pwSpec, cr, sr, &pmsItem, isTLS,
PR_TRUE);
- if (rv != SECSuccess) {
- pwSpec->msItem.data = pwSpec->raw_master_secret;
- pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH;
- PK11_GenerateRandom(pwSpec->msItem.data, pwSpec->msItem.len);
- }
- rv = ssl3_InitPendingCipherSpec(ss, NULL);
- } else
+ if (rv != SECSuccess) {
+ pwSpec->msItem.data = pwSpec->raw_master_secret;
+ pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH;
+ PK11_GenerateRandom(pwSpec->msItem.data, pwSpec->msItem.len);
+ }
+ rv = ssl3_InitPendingCipherSpec(ss, NULL);
+ } else
#endif
{
- PK11SymKey *tmpPms[2] = {NULL, NULL};
+ PK11SymKey *tmpPms[2] = { NULL, NULL };
PK11SlotInfo *slot;
int useFauxPms = 0;
#define currentPms tmpPms[!useFauxPms]
-#define unusedPms tmpPms[useFauxPms]
-#define realPms tmpPms[1]
-#define fauxPms tmpPms[0]
+#define unusedPms tmpPms[useFauxPms]
+#define realPms tmpPms[1]
+#define fauxPms tmpPms[0]
#ifndef NO_PKCS11_BYPASS
-double_bypass:
+ double_bypass:
#endif
/*
@@ -10239,18 +10523,18 @@ double_bypass:
PK11_FreeSlot(slot);
if (fauxPms == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
- return SECFailure;
- }
-
- /*
- * unwrap pms out of the incoming buffer
- * Note: CKM_SSL3_MASTER_KEY_DERIVE is NOT the mechanism used to do
- * the unwrap. Rather, it is the mechanism with which the
- * unwrapped pms will be used.
- */
- realPms = PK11_PubUnwrapSymKey(serverKey, &enc_pms,
- CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0);
+ ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ return SECFailure;
+ }
+
+ /*
+ * unwrap pms out of the incoming buffer
+ * Note: CKM_SSL3_MASTER_KEY_DERIVE is NOT the mechanism used to do
+ * the unwrap. Rather, it is the mechanism with which the
+ * unwrapped pms will be used.
+ */
+ realPms = PK11_PubUnwrapSymKey(serverKey, &enc_pms,
+ CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0);
/* Temporarily use the PMS if unwrapping the real PMS fails. */
useFauxPms |= (realPms == NULL);
@@ -10269,14 +10553,14 @@ double_bypass:
PK11_FreeSymKey(unusedPms);
}
- /* This step will derive the MS from the PMS, among other things. */
+ /* This step will derive the MS from the PMS, among other things. */
rv = ssl3_InitPendingCipherSpec(ss, currentPms);
PK11_FreeSymKey(currentPms);
}
if (rv != SECSuccess) {
- SEND_ALERT
- return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
+ SEND_ALERT
+ return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
}
#undef currentPms
@@ -10294,15 +10578,15 @@ ssl3_HandleDHClientKeyExchange(sslSocket *ss,
SECKEYPublicKey *srvrPubKey,
SECKEYPrivateKey *serverKey)
{
- PK11SymKey *pms;
- SECStatus rv;
- SECKEYPublicKey clntPubKey;
- CK_MECHANISM_TYPE target;
- PRBool isTLS;
+ PK11SymKey *pms;
+ SECStatus rv;
+ SECKEYPublicKey clntPubKey;
+ CK_MECHANISM_TYPE target;
+ PRBool isTLS;
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( srvrPubKey );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(srvrPubKey);
clntPubKey.keyType = dhKey;
clntPubKey.u.dh.prime.len = srvrPubKey->u.dh.prime.len;
@@ -10311,26 +10595,29 @@ ssl3_HandleDHClientKeyExchange(sslSocket *ss,
clntPubKey.u.dh.base.data = srvrPubKey->u.dh.base.data;
rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.dh.publicValue,
- 2, &b, &length);
+ 2, &b, &length);
if (rv != SECSuccess) {
- goto loser;
+ goto loser;
}
isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
- if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
- else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
+ if (isTLS)
+ target = CKM_TLS_MASTER_KEY_DERIVE_DH;
+ else
+ target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
/* Determine the PMS */
pms = PK11_PubDerive(serverKey, &clntPubKey, PR_FALSE, NULL, NULL,
CKM_DH_PKCS_DERIVE, target, CKA_DERIVE, 0, NULL);
if (pms == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
- goto loser;
+ ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+ goto loser;
}
- rv = ssl3_InitPendingCipherSpec(ss, pms);
- PK11_FreeSymKey(pms); pms = NULL;
+ rv = ssl3_InitPendingCipherSpec(ss, pms);
+ PK11_FreeSymKey(pms);
+ pms = NULL;
loser:
if (ss->dheKeyPair) {
@@ -10340,48 +10627,48 @@ loser:
return rv;
}
-
-/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
- * ssl3 ClientKeyExchange message from the remote client
+/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
+ * a complete ssl3 ClientKeyExchange message from the remote client
* Caller must hold Handshake and RecvBuf locks.
*/
static SECStatus
ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
- SECKEYPrivateKey *serverKey = NULL;
- SECStatus rv;
+ SECKEYPrivateKey *serverKey = NULL;
+ SECStatus rv;
const ssl3KEADef *kea_def;
- ssl3KeyPair *serverKeyPair = NULL;
- SECKEYPublicKey *serverPubKey = NULL;
+ ssl3KeyPair *serverKeyPair = NULL;
+ SECKEYPublicKey *serverPubKey = NULL;
SSL_TRC(3, ("%d: SSL3[%d]: handle client_key_exchange handshake",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ss->ssl3.hs.ws != wait_client_key) {
- SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH);
- return SECFailure;
+ SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH);
+ return SECFailure;
}
- kea_def = ss->ssl3.hs.kea_def;
+ kea_def = ss->ssl3.hs.kea_def;
if (ss->ssl3.hs.usedStepDownKey) {
- PORT_Assert(kea_def->is_limited /* XXX OR cert is signing only */
- && kea_def->exchKeyType == kt_rsa
- && ss->stepDownKeyPair != NULL);
- if (!kea_def->is_limited ||
- kea_def->exchKeyType != kt_rsa ||
- ss->stepDownKeyPair == NULL) {
- /* shouldn't happen, don't use step down if it does */
- goto skip;
- }
- serverKeyPair = ss->stepDownKeyPair;
- ss->sec.keaKeyBits = EXPORT_RSA_KEY_LENGTH * BPB;
- } else
-skip:
+ PORT_Assert(kea_def->is_limited /* XXX OR cert is signing only */
+ &&
+ kea_def->exchKeyType == kt_rsa &&
+ ss->stepDownKeyPair != NULL);
+ if (!kea_def->is_limited ||
+ kea_def->exchKeyType != kt_rsa ||
+ ss->stepDownKeyPair == NULL) {
+ /* shouldn't happen, don't use step down if it does */
+ goto skip;
+ }
+ serverKeyPair = ss->stepDownKeyPair;
+ ss->sec.keaKeyBits = EXPORT_RSA_KEY_LENGTH * BPB;
+ } else
+ skip:
if (kea_def->kea == kea_dhe_dss ||
kea_def->kea == kea_dhe_rsa) {
if (ss->dheKeyPair) {
@@ -10393,115 +10680,130 @@ skip:
}
} else
#ifndef NSS_DISABLE_ECC
- /* XXX Using SSLKEAType to index server certifiates
- * does not work for (EC)DHE ciphers. Until we have
- * an indexing mechanism general enough for all key
- * exchange algorithms, we'll need to deal with each
- * one seprately.
- */
- if ((kea_def->kea == kea_ecdhe_rsa) ||
- (kea_def->kea == kea_ecdhe_ecdsa)) {
- if (ss->ephemeralECDHKeyPair != NULL) {
- serverKeyPair = ss->ephemeralECDHKeyPair;
- if (serverKeyPair->pubKey) {
- ss->sec.keaKeyBits =
- SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey);
- }
- }
- } else
+ /* XXX Using SSLKEAType to index server certifiates
+ * does not work for (EC)DHE ciphers. Until we have
+ * an indexing mechanism general enough for all key
+ * exchange algorithms, we'll need to deal with each
+ * one seprately.
+ */
+ if ((kea_def->kea == kea_ecdhe_rsa) ||
+ (kea_def->kea == kea_ecdhe_ecdsa)) {
+ if (ss->ephemeralECDHKeyPair != NULL) {
+ serverKeyPair = ss->ephemeralECDHKeyPair;
+ if (serverKeyPair->pubKey) {
+ ss->sec.keaKeyBits =
+ SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey);
+ }
+ }
+ } else
#endif
{
- sslServerCerts * sc = ss->serverCerts + kea_def->exchKeyType;
- serverKeyPair = sc->serverKeyPair;
- ss->sec.keaKeyBits = sc->serverKeyBits;
+ sslServerCerts *sc = ss->serverCerts + kea_def->exchKeyType;
+ serverKeyPair = sc->serverKeyPair;
+ ss->sec.keaKeyBits = sc->serverKeyBits;
}
if (serverKeyPair) {
- serverKey = serverKeyPair->privKey;
+ serverKey = serverKeyPair->privKey;
}
if (serverKey == NULL) {
- SEND_ALERT
- PORT_SetError(SSL_ERROR_NO_SERVER_KEY_FOR_ALG);
- return SECFailure;
+ SEND_ALERT
+ PORT_SetError(SSL_ERROR_NO_SERVER_KEY_FOR_ALG);
+ return SECFailure;
}
- ss->sec.keaType = kea_def->exchKeyType;
+ ss->sec.keaType = kea_def->exchKeyType;
switch (kea_def->exchKeyType) {
- case kt_rsa:
- rv = ssl3_HandleRSAClientKeyExchange(ss, b, length, serverKey);
- if (rv != SECSuccess) {
- SEND_ALERT
- return SECFailure; /* error code set */
- }
- break;
-
- case ssl_kea_dh:
- if (ss->dheKeyPair && ss->dheKeyPair->pubKey) {
- serverPubKey = ss->dheKeyPair->pubKey;
- }
- if (!serverPubKey) {
- PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
- return SECFailure;
- }
- rv = ssl3_HandleDHClientKeyExchange(ss, b, length,
- serverPubKey, serverKey);
- if (rv != SECSuccess) {
- SSL3_SendAlert(ss, alert_fatal, handshake_failure);
- return SECFailure; /* error code set */
- }
- break;
+ case kt_rsa:
+ rv = ssl3_HandleRSAClientKeyExchange(ss, b, length, serverKey);
+ if (rv != SECSuccess) {
+ SEND_ALERT
+ return SECFailure; /* error code set */
+ }
+ break;
+
+ case ssl_kea_dh:
+ if (ss->dheKeyPair && ss->dheKeyPair->pubKey) {
+ serverPubKey = ss->dheKeyPair->pubKey;
+ }
+ if (!serverPubKey) {
+ PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
+ return SECFailure;
+ }
+ rv = ssl3_HandleDHClientKeyExchange(ss, b, length,
+ serverPubKey, serverKey);
+ if (rv != SECSuccess) {
+ SSL3_SendAlert(ss, alert_fatal, handshake_failure);
+ return SECFailure; /* error code set */
+ }
+ break;
#ifndef NSS_DISABLE_ECC
- case kt_ecdh:
- /* XXX We really ought to be able to store multiple
- * EC certs (a requirement if we wish to support both
- * ECDH-RSA and ECDH-ECDSA key exchanges concurrently).
- * When we make that change, we'll need an index other
- * than kt_ecdh to pick the right EC certificate.
- */
- if (serverKeyPair) {
- serverPubKey = serverKeyPair->pubKey;
- }
- if (serverPubKey == NULL) {
- /* XXX Is this the right error code? */
- PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
- return SECFailure;
- }
- rv = ssl3_HandleECDHClientKeyExchange(ss, b, length,
- serverPubKey, serverKey);
- if (ss->ephemeralECDHKeyPair) {
- ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair);
- ss->ephemeralECDHKeyPair = NULL;
- }
- if (rv != SECSuccess) {
- return SECFailure; /* error code set */
- }
- break;
+ case kt_ecdh:
+ /* XXX We really ought to be able to store multiple
+ * EC certs (a requirement if we wish to support both
+ * ECDH-RSA and ECDH-ECDSA key exchanges concurrently).
+ * When we make that change, we'll need an index other
+ * than kt_ecdh to pick the right EC certificate.
+ */
+ if (serverKeyPair) {
+ serverPubKey = serverKeyPair->pubKey;
+ }
+ if (serverPubKey == NULL) {
+ /* XXX Is this the right error code? */
+ PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
+ return SECFailure;
+ }
+ rv = ssl3_HandleECDHClientKeyExchange(ss, b, length,
+ serverPubKey, serverKey);
+ if (ss->ephemeralECDHKeyPair) {
+ ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair);
+ ss->ephemeralECDHKeyPair = NULL;
+ }
+ if (rv != SECSuccess) {
+ return SECFailure; /* error code set */
+ }
+ break;
#endif /* NSS_DISABLE_ECC */
- default:
- (void) ssl3_HandshakeFailure(ss);
- PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
- return SECFailure;
+ default:
+ (void)ssl3_HandshakeFailure(ss);
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
+ return SECFailure;
}
ss->ssl3.hs.ws = ss->sec.peerCert ? wait_cert_verify : wait_change_cipher;
return SECSuccess;
-
}
/* This is TLS's equivalent of sending a no_certificate alert. */
-static SECStatus
+SECStatus
ssl3_SendEmptyCertificate(sslSocket *ss)
{
- SECStatus rv;
+ SECStatus rv;
+ unsigned int len = 0;
+ PRBool isTLS13 = PR_FALSE;
- rv = ssl3_AppendHandshakeHeader(ss, certificate, 3);
- if (rv == SECSuccess) {
- rv = ssl3_AppendHandshakeNumber(ss, 0, 3);
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ len = ss->ssl3.hs.certReqContextLen + 1;
+ isTLS13 = PR_TRUE;
+ }
+
+ rv = ssl3_AppendHandshakeHeader(ss, certificate, len + 3);
+ if (rv != SECSuccess) {
+ return rv;
}
- return rv; /* error, if any, set by functions called above. */
+
+ if (isTLS13) {
+ rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.hs.certReqContext,
+ ss->ssl3.hs.certReqContextLen, 1);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ }
+
+ return ssl3_AppendHandshakeNumber(ss, 0, 3);
}
SECStatus
@@ -10511,18 +10813,18 @@ ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SECItem ticketData;
SSL_TRC(3, ("%d: SSL3[%d]: handle session_ticket handshake",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(!ss->ssl3.hs.newSessionTicket.ticket.data);
PORT_Assert(!ss->ssl3.hs.receivedNewSessionTicket);
if (ss->ssl3.hs.ws != wait_new_session_ticket) {
- SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET);
- return SECFailure;
+ SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET);
+ return SECFailure;
}
/* RFC5077 Section 3.3: "The client MUST NOT treat the ticket as valid
@@ -10531,28 +10833,28 @@ ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
*/
ss->ssl3.hs.newSessionTicket.received_timestamp = ssl_Time();
if (length < 4) {
- (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
- PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET);
- return SECFailure;
+ (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET);
+ return SECFailure;
}
ss->ssl3.hs.newSessionTicket.ticket_lifetime_hint =
- (PRUint32)ssl3_ConsumeHandshakeNumber(ss, 4, &b, &length);
+ (PRUint32)ssl3_ConsumeHandshakeNumber(ss, 4, &b, &length);
rv = ssl3_ConsumeHandshakeVariable(ss, &ticketData, 2, &b, &length);
if (rv != SECSuccess || length != 0) {
- (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
- PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET);
- return SECFailure; /* malformed */
+ (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET);
+ return SECFailure; /* malformed */
}
/* If the server sent a zero-length ticket, ignore it and keep the
* existing ticket. */
if (ticketData.len != 0) {
- rv = SECITEM_CopyItem(NULL, &ss->ssl3.hs.newSessionTicket.ticket,
- &ticketData);
- if (rv != SECSuccess) {
- return rv;
- }
- ss->ssl3.hs.receivedNewSessionTicket = PR_TRUE;
+ rv = SECITEM_CopyItem(NULL, &ss->ssl3.hs.newSessionTicket.ticket,
+ &ticketData);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ ss->ssl3.hs.receivedNewSessionTicket = PR_TRUE;
}
ss->ssl3.hs.ws = wait_change_cipher;
@@ -10562,54 +10864,54 @@ ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
#ifdef NISCC_TEST
static PRInt32 connNum = 0;
-static SECStatus
+static SECStatus
get_fake_cert(SECItem *pCertItem, int *pIndex)
{
PRFileDesc *cf;
- char * testdir;
- char * startat;
- char * stopat;
+ char *testdir;
+ char *startat;
+ char *stopat;
const char *extension;
- int fileNum;
- PRInt32 numBytes = 0;
- PRStatus prStatus;
- PRFileInfo info;
- char cfn[100];
+ int fileNum;
+ PRInt32 numBytes = 0;
+ PRStatus prStatus;
+ PRFileInfo info;
+ char cfn[100];
pCertItem->data = 0;
- if ((testdir = PR_GetEnv("NISCC_TEST")) == NULL) {
- return SECSuccess;
+ if ((testdir = PR_GetEnvSecure("NISCC_TEST")) == NULL) {
+ return SECSuccess;
}
- *pIndex = (NULL != strstr(testdir, "root"));
+ *pIndex = (NULL != strstr(testdir, "root"));
extension = (strstr(testdir, "simple") ? "" : ".der");
- fileNum = PR_ATOMIC_INCREMENT(&connNum) - 1;
- if ((startat = PR_GetEnv("START_AT")) != NULL) {
- fileNum += atoi(startat);
+ fileNum = PR_ATOMIC_INCREMENT(&connNum) - 1;
+ if ((startat = PR_GetEnvSecure("START_AT")) != NULL) {
+ fileNum += atoi(startat);
}
- if ((stopat = PR_GetEnv("STOP_AT")) != NULL &&
- fileNum >= atoi(stopat)) {
- *pIndex = -1;
- return SECSuccess;
+ if ((stopat = PR_GetEnvSecure("STOP_AT")) != NULL &&
+ fileNum >= atoi(stopat)) {
+ *pIndex = -1;
+ return SECSuccess;
}
sprintf(cfn, "%s/%08d%s", testdir, fileNum, extension);
cf = PR_Open(cfn, PR_RDONLY, 0);
if (!cf) {
- goto loser;
+ goto loser;
}
prStatus = PR_GetOpenFileInfo(cf, &info);
if (prStatus != PR_SUCCESS) {
- PR_Close(cf);
- goto loser;
+ PR_Close(cf);
+ goto loser;
}
pCertItem = SECITEM_AllocItem(NULL, pCertItem, info.size);
if (pCertItem) {
- numBytes = PR_Read(cf, pCertItem->data, info.size);
+ numBytes = PR_Read(cf, pCertItem->data, info.size);
}
PR_Close(cf);
if (numBytes != info.size) {
- SECITEM_FreeItem(pCertItem, PR_FALSE);
- PORT_SetError(SEC_ERROR_IO);
- goto loser;
+ SECITEM_FreeItem(pCertItem, PR_FALSE);
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
}
fprintf(stderr, "using %s\n", cfn);
return SECSuccess;
@@ -10625,79 +10927,102 @@ loser:
* Used by both client and server.
* Called from HandleServerHelloDone and from SendServerHelloSequence.
*/
-static SECStatus
+SECStatus
ssl3_SendCertificate(sslSocket *ss)
{
- SECStatus rv;
+ SECStatus rv;
CERTCertificateList *certChain;
- int len = 0;
- int i;
- SSL3KEAType certIndex;
+ int certChainLen = 0;
+ int i;
+ SSL3KEAType certIndex;
#ifdef NISCC_TEST
- SECItem fakeCert;
- int ndex = -1;
+ SECItem fakeCert;
+ int ndex = -1;
#endif
+ PRBool isTLS13 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
+ unsigned int contextLen = 0;
SSL_TRC(3, ("%d: SSL3[%d]: send certificate handshake",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ss->sec.localCert)
- CERT_DestroyCertificate(ss->sec.localCert);
+ CERT_DestroyCertificate(ss->sec.localCert);
if (ss->sec.isServer) {
- sslServerCerts * sc = NULL;
-
- /* XXX SSLKEAType isn't really a good choice for
- * indexing certificates (it breaks when we deal
- * with (EC)DHE-* cipher suites. This hack ensures
- * the RSA cert is picked for (EC)DHE-RSA.
- * Revisit this when we add server side support
- * for ECDHE-ECDSA or client-side authentication
- * using EC certificates.
- */
- if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) ||
- (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) {
- certIndex = kt_rsa;
- } else {
- certIndex = ss->ssl3.hs.kea_def->exchKeyType;
- }
- sc = ss->serverCerts + certIndex;
- certChain = sc->serverCertChain;
- ss->sec.authKeyBits = sc->serverKeyBits;
- ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType;
- ss->sec.localCert = CERT_DupCertificate(sc->serverCert);
+ sslServerCerts *sc = NULL;
+
+ /* XXX SSLKEAType isn't really a good choice for
+ * indexing certificates (it breaks when we deal
+ * with (EC)DHE-* cipher suites. This hack ensures
+ * the RSA cert is picked for (EC)DHE-RSA.
+ * Revisit this when we add server side support
+ * for ECDHE-ECDSA or client-side authentication
+ * using EC certificates.
+ */
+ if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) ||
+ (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) {
+ certIndex = kt_rsa;
+ } else {
+ certIndex = ss->ssl3.hs.kea_def->exchKeyType;
+ }
+ sc = ss->serverCerts + certIndex;
+ certChain = sc->serverCertChain;
+ ss->sec.authKeyBits = sc->serverKeyBits;
+ ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType;
+ ss->sec.localCert = CERT_DupCertificate(sc->serverCert);
} else {
- certChain = ss->ssl3.clientCertChain;
- ss->sec.localCert = CERT_DupCertificate(ss->ssl3.clientCertificate);
+ certChain = ss->ssl3.clientCertChain;
+ ss->sec.localCert = CERT_DupCertificate(ss->ssl3.clientCertificate);
}
#ifdef NISCC_TEST
rv = get_fake_cert(&fakeCert, &ndex);
#endif
+ if (isTLS13) {
+ contextLen = 1; /* Length of the context */
+ if (!ss->sec.isServer) {
+ contextLen += ss->ssl3.hs.certReqContextLen;
+ }
+ }
if (certChain) {
- for (i = 0; i < certChain->len; i++) {
+ for (i = 0; i < certChain->len; i++) {
#ifdef NISCC_TEST
- if (fakeCert.len > 0 && i == ndex) {
- len += fakeCert.len + 3;
- } else {
- len += certChain->certs[i].len + 3;
- }
+ if (fakeCert.len > 0 && i == ndex) {
+ certChainLen += fakeCert.len + 3;
+ } else {
+ certChainLen += certChain->certs[i].len + 3;
+ }
#else
- len += certChain->certs[i].len + 3;
+ certChainLen += certChain->certs[i].len + 3;
#endif
- }
+ }
}
- rv = ssl3_AppendHandshakeHeader(ss, certificate, len + 3);
+ rv = ssl3_AppendHandshakeHeader(ss, certificate,
+ contextLen + certChainLen + 3);
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
+ }
+
+ if (isTLS13) {
+ if (ss->sec.isServer) {
+ rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
+ } else {
+ rv = ssl3_AppendHandshakeVariable(ss,
+ ss->ssl3.hs.certReqContext,
+ ss->ssl3.hs.certReqContextLen, 1);
+ }
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
}
- rv = ssl3_AppendHandshakeNumber(ss, len, 3);
+
+ rv = ssl3_AppendHandshakeNumber(ss, certChainLen, 3);
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
}
if (certChain) {
for (i = 0; i < certChain->len; i++) {
@@ -10715,7 +11040,7 @@ ssl3_SendCertificate(sslSocket *ss)
certChain->certs[i].len, 3);
#endif
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
}
}
}
@@ -10727,7 +11052,7 @@ ssl3_SendCertificate(sslSocket *ss)
* Used by server only.
* single-stapling, send only a single cert status
*/
-static SECStatus
+SECStatus
ssl3_SendCertificateStatus(sslSocket *ss)
{
SECStatus rv;
@@ -10736,45 +11061,45 @@ ssl3_SendCertificateStatus(sslSocket *ss)
SSL3KEAType certIndex;
SSL_TRC(3, ("%d: SSL3[%d]: send certificate status handshake",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
- PORT_Assert( ss->sec.isServer);
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->sec.isServer);
if (!ssl3_ExtensionNegotiated(ss, ssl_cert_status_xtn))
- return SECSuccess;
+ return SECSuccess;
/* Use certStatus based on the cert being used. */
if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) ||
- (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) {
- certIndex = kt_rsa;
+ (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) {
+ certIndex = kt_rsa;
} else {
- certIndex = ss->ssl3.hs.kea_def->exchKeyType;
+ certIndex = ss->ssl3.hs.kea_def->exchKeyType;
}
if (ss->certStatusArray[certIndex] && ss->certStatusArray[certIndex]->len) {
- statusToSend = ss->certStatusArray[certIndex];
+ statusToSend = ss->certStatusArray[certIndex];
}
if (!statusToSend)
- return SECSuccess;
+ return SECSuccess;
/* Use the array's first item only (single stapling) */
len = 1 + statusToSend->items[0].len + 3;
rv = ssl3_AppendHandshakeHeader(ss, certificate_status, len);
if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
}
rv = ssl3_AppendHandshakeNumber(ss, 1 /*ocsp*/, 1);
if (rv != SECSuccess)
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
rv = ssl3_AppendHandshakeVariable(ss,
- statusToSend->items[0].data,
- statusToSend->items[0].len,
- 3);
+ statusToSend->items[0].data,
+ statusToSend->items[0].len,
+ 3);
if (rv != SECSuccess)
- return rv; /* err set by AppendHandshake. */
+ return rv; /* err set by AppendHandshake. */
return SECSuccess;
}
@@ -10785,94 +11110,66 @@ ssl3_SendCertificateStatus(sslSocket *ss)
static void
ssl3_CleanupPeerCerts(sslSocket *ss)
{
- PLArenaPool * arena = ss->ssl3.peerCertArena;
+ PLArenaPool *arena = ss->ssl3.peerCertArena;
ssl3CertNode *certs = (ssl3CertNode *)ss->ssl3.peerCertChain;
for (; certs; certs = certs->next) {
- CERT_DestroyCertificate(certs->cert);
+ CERT_DestroyCertificate(certs->cert);
}
- if (arena) PORT_FreeArena(arena, PR_FALSE);
+ if (arena)
+ PORT_FreeArena(arena, PR_FALSE);
ss->ssl3.peerCertArena = NULL;
ss->ssl3.peerCertChain = NULL;
}
-static void
-ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid)
-{
- PLArenaPool *arena;
- ssl3CertNode *lastCert = NULL;
- ssl3CertNode *certs = NULL;
- int i;
-
- if (!sid->peerCertChain[0])
- return;
- PORT_Assert(!ss->ssl3.peerCertArena);
- PORT_Assert(!ss->ssl3.peerCertChain);
- ss->ssl3.peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
- ssl3CertNode *c = PORT_ArenaNew(arena, ssl3CertNode);
- c->cert = CERT_DupCertificate(sid->peerCertChain[i]);
- c->next = NULL;
- if (lastCert) {
- lastCert->next = c;
- } else {
- certs = c;
- }
- lastCert = c;
- }
- ss->ssl3.peerCertChain = certs;
-}
-
-static void
-ssl3_CopyPeerCertsToSID(ssl3CertNode *certs, sslSessionID *sid)
-{
- int i = 0;
- ssl3CertNode *c = certs;
- for (; i < MAX_PEER_CERT_CHAIN_SIZE && c; i++, c = c->next) {
- PORT_Assert(!sid->peerCertChain[i]);
- sid->peerCertChain[i] = CERT_DupCertificate(c->cert);
- }
-}
-
-/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
- * ssl3 CertificateStatus message.
+/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
+ * a complete ssl3 CertificateStatus message.
* Caller must hold Handshake and RecvBuf locks.
- * This is always called before ssl3_HandleCertificate, even if the Certificate
- * message is sent first.
*/
static SECStatus
ssl3_HandleCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
- PRInt32 status, len;
-
if (ss->ssl3.hs.ws != wait_certificate_status) {
(void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_STATUS);
return SECFailure;
}
+ return ssl3_CompleteHandleCertificateStatus(ss, b, length);
+}
+
+/* Called from:
+ * ssl3_HandleCertificateStatus
+ * tls13_HandleCertificateStatus
+ */
+SECStatus
+ssl3_CompleteHandleCertificateStatus(sslSocket *ss, SSL3Opaque *b,
+ PRUint32 length)
+{
+ PRInt32 status, len;
+
PORT_Assert(!ss->sec.isServer);
/* Consume the CertificateStatusType enum */
status = ssl3_ConsumeHandshakeNumber(ss, 1, &b, &length);
if (status != 1 /* ocsp */) {
- goto format_loser;
+ goto format_loser;
}
len = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
if (len != length) {
- goto format_loser;
+ goto format_loser;
}
-#define MAX_CERTSTATUS_LEN 0x1ffff /* 128k - 1 */
+#define MAX_CERTSTATUS_LEN 0x1ffff /* 128k - 1 */
if (length > MAX_CERTSTATUS_LEN)
- goto format_loser;
+ goto format_loser;
#undef MAX_CERTSTATUS_LEN
/* Array size 1, because we currently implement single-stapling only */
SECITEM_AllocArray(NULL, &ss->sec.ci.sid->peerCertStatus, 1);
if (!ss->sec.ci.sid->peerCertStatus.items)
- return SECFailure;
+ return SECFailure;
ss->sec.ci.sid->peerCertStatus.items[0].data = PORT_Alloc(length);
@@ -10891,43 +11188,51 @@ format_loser:
return ssl3_DecodeError(ss);
}
-/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
- * ssl3 Certificate message.
+/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
+ * a complete ssl3 Certificate message.
* Caller must hold Handshake and RecvBuf locks.
*/
static SECStatus
ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
- ssl3CertNode * c;
- ssl3CertNode * lastCert = NULL;
- PRInt32 remaining = 0;
- PRInt32 size;
- SECStatus rv;
- PRBool isServer = (PRBool)(!!ss->sec.isServer);
- PRBool isTLS;
- SSL3AlertDescription desc;
- int errCode = SSL_ERROR_RX_MALFORMED_CERTIFICATE;
- SECItem certItem;
-
SSL_TRC(3, ("%d: SSL3[%d]: handle certificate handshake",
- SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ SSL_GETPID(), ss->fd));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
- if ((isServer && ss->ssl3.hs.ws != wait_client_cert) ||
- (!isServer && ss->ssl3.hs.ws != wait_server_cert)) {
- desc = unexpected_message;
- errCode = SSL_ERROR_RX_UNEXPECTED_CERTIFICATE;
- goto alert_loser;
+ if ((ss->sec.isServer && ss->ssl3.hs.ws != wait_client_cert) ||
+ (!ss->sec.isServer && ss->ssl3.hs.ws != wait_server_cert)) {
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERTIFICATE);
+ return SECFailure;
}
+ return ssl3_CompleteHandleCertificate(ss, b, length);
+}
+
+/* Called from ssl3_HandleCertificate
+ */
+SECStatus
+ssl3_CompleteHandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+{
+ ssl3CertNode *c;
+ ssl3CertNode *lastCert = NULL;
+ PRInt32 remaining = 0;
+ PRInt32 size;
+ SECStatus rv;
+ PRBool isServer = (PRBool)(!!ss->sec.isServer);
+ PRBool isTLS;
+ SSL3AlertDescription desc;
+ int errCode = SSL_ERROR_RX_MALFORMED_CERTIFICATE;
+ SECItem certItem;
+
if (ss->sec.peerCert != NULL) {
- if (ss->sec.peerKey) {
- SECKEY_DestroyPublicKey(ss->sec.peerKey);
- ss->sec.peerKey = NULL;
- }
- CERT_DestroyCertificate(ss->sec.peerCert);
- ss->sec.peerCert = NULL;
+ if (ss->sec.peerKey) {
+ SECKEY_DestroyPublicKey(ss->sec.peerKey);
+ ss->sec.peerKey = NULL;
+ }
+ CERT_DestroyCertificate(ss->sec.peerCert);
+ ss->sec.peerCert = NULL;
}
ssl3_CleanupPeerCerts(ss);
@@ -10938,98 +11243,103 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
** normal no_certificates message to maximize interoperability.
*/
if (length) {
- remaining = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
- if (remaining < 0)
- goto loser; /* fatal alert already sent by ConsumeHandshake. */
- if ((PRUint32)remaining > length)
- goto decode_loser;
+ remaining = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
+ if (remaining < 0)
+ goto loser; /* fatal alert already sent by ConsumeHandshake. */
+ if ((PRUint32)remaining > length)
+ goto decode_loser;
}
if (!remaining) {
- if (!(isTLS && isServer)) {
- desc = bad_certificate;
- goto alert_loser;
- }
- /* This is TLS's version of a no_certificate alert. */
- /* I'm a server. I've requested a client cert. He hasn't got one. */
- rv = ssl3_HandleNoCertificate(ss);
- if (rv != SECSuccess) {
- errCode = PORT_GetError();
- goto loser;
- }
- ss->ssl3.hs.ws = wait_client_key;
- return SECSuccess;
+ if (!(isTLS && isServer)) {
+ desc = bad_certificate;
+ goto alert_loser;
+ }
+ /* This is TLS's version of a no_certificate alert. */
+ /* I'm a server. I've requested a client cert. He hasn't got one. */
+ rv = ssl3_HandleNoCertificate(ss);
+ if (rv != SECSuccess) {
+ errCode = PORT_GetError();
+ goto loser;
+ }
+
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ ss->ssl3.hs.ws = wait_client_key;
+ } else {
+ TLS13_SET_HS_STATE(ss, wait_finished);
+ }
+ return SECSuccess;
}
ss->ssl3.peerCertArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (ss->ssl3.peerCertArena == NULL) {
- goto loser; /* don't send alerts on memory errors */
+ goto loser; /* don't send alerts on memory errors */
}
/* First get the peer cert. */
remaining -= 3;
if (remaining < 0)
- goto decode_loser;
+ goto decode_loser;
size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
if (size <= 0)
- goto loser; /* fatal alert already sent by ConsumeHandshake. */
+ goto loser; /* fatal alert already sent by ConsumeHandshake. */
if (remaining < size)
- goto decode_loser;
+ goto decode_loser;
certItem.data = b;
certItem.len = size;
- b += size;
+ b += size;
length -= size;
remaining -= size;
ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL,
- PR_FALSE, PR_TRUE);
+ PR_FALSE, PR_TRUE);
if (ss->sec.peerCert == NULL) {
- /* We should report an alert if the cert was bad, but not if the
- * problem was just some local problem, like memory error.
- */
- goto ambiguous_err;
+ /* We should report an alert if the cert was bad, but not if the
+ * problem was just some local problem, like memory error.
+ */
+ goto ambiguous_err;
}
/* Now get all of the CA certs. */
while (remaining > 0) {
- remaining -= 3;
- if (remaining < 0)
- goto decode_loser;
-
- size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
- if (size <= 0)
- goto loser; /* fatal alert already sent by ConsumeHandshake. */
-
- if (remaining < size)
- goto decode_loser;
-
- certItem.data = b;
- certItem.len = size;
- b += size;
- length -= size;
- remaining -= size;
-
- c = PORT_ArenaNew(ss->ssl3.peerCertArena, ssl3CertNode);
- if (c == NULL) {
- goto loser; /* don't send alerts on memory errors */
- }
-
- c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL,
- PR_FALSE, PR_TRUE);
- if (c->cert == NULL) {
- goto ambiguous_err;
- }
-
- c->next = NULL;
- if (lastCert) {
- lastCert->next = c;
- } else {
- ss->ssl3.peerCertChain = c;
- }
- lastCert = c;
+ remaining -= 3;
+ if (remaining < 0)
+ goto decode_loser;
+
+ size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length);
+ if (size <= 0)
+ goto loser; /* fatal alert already sent by ConsumeHandshake. */
+
+ if (remaining < size)
+ goto decode_loser;
+
+ certItem.data = b;
+ certItem.len = size;
+ b += size;
+ length -= size;
+ remaining -= size;
+
+ c = PORT_ArenaNew(ss->ssl3.peerCertArena, ssl3CertNode);
+ if (c == NULL) {
+ goto loser; /* don't send alerts on memory errors */
+ }
+
+ c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL,
+ PR_FALSE, PR_TRUE);
+ if (c->cert == NULL) {
+ goto ambiguous_err;
+ }
+
+ c->next = NULL;
+ if (lastCert) {
+ lastCert->next = c;
+ } else {
+ ss->ssl3.peerCertChain = c;
+ }
+ lastCert = c;
}
if (remaining != 0)
@@ -11038,10 +11348,10 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SECKEY_UpdateCertPQG(ss->sec.peerCert);
if (!isServer && ssl3_ExtensionNegotiated(ss, ssl_cert_status_xtn)) {
- ss->ssl3.hs.ws = wait_certificate_status;
- rv = SECSuccess;
+ ss->ssl3.hs.ws = wait_certificate_status;
+ rv = SECSuccess;
} else {
- rv = ssl3_AuthCertificate(ss); /* sets ss->ssl3.hs.ws */
+ rv = ssl3_AuthCertificate(ss); /* sets ss->ssl3.hs.ws */
}
return rv;
@@ -11049,14 +11359,14 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ambiguous_err:
errCode = PORT_GetError();
switch (errCode) {
- case PR_OUT_OF_MEMORY_ERROR:
- case SEC_ERROR_BAD_DATABASE:
- case SEC_ERROR_NO_MEMORY:
- if (isTLS) {
- desc = internal_error;
- goto alert_loser;
- }
- goto loser;
+ case PR_OUT_OF_MEMORY_ERROR:
+ case SEC_ERROR_BAD_DATABASE:
+ case SEC_ERROR_NO_MEMORY:
+ if (isTLS) {
+ desc = internal_error;
+ goto alert_loser;
+ }
+ goto loser;
}
ssl3_SendAlertForCertError(ss, errCode);
goto loser;
@@ -11075,9 +11385,9 @@ loser:
static SECStatus
ssl3_AuthCertificate(sslSocket *ss)
{
- SECStatus rv;
- PRBool isServer = (PRBool)(!!ss->sec.isServer);
- int errCode;
+ SECStatus rv;
+ PRBool isServer = (PRBool)(!!ss->sec.isServer);
+ int errCode;
ss->ssl3.hs.authCertificatePending = PR_FALSE;
@@ -11087,30 +11397,36 @@ ssl3_AuthCertificate(sslSocket *ss)
* Ask caller-supplied callback function to validate cert chain.
*/
rv = (SECStatus)(*ss->authCertificate)(ss->authCertificateArg, ss->fd,
- PR_TRUE, isServer);
- if (rv) {
- errCode = PORT_GetError();
- if (rv != SECWouldBlock) {
- if (ss->handleBadCert) {
- rv = (*ss->handleBadCert)(ss->badCertArg, ss->fd);
- }
- }
-
- if (rv == SECWouldBlock) {
- if (ss->sec.isServer) {
- errCode = SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS;
- rv = SECFailure;
- goto loser;
- }
-
- ss->ssl3.hs.authCertificatePending = PR_TRUE;
- rv = SECSuccess;
- }
-
- if (rv != SECSuccess) {
- ssl3_SendAlertForCertError(ss, errCode);
- goto loser;
- }
+ PR_TRUE, isServer);
+ if (rv != SECSuccess) {
+ errCode = PORT_GetError();
+ if (rv != SECWouldBlock) {
+ if (ss->handleBadCert) {
+ rv = (*ss->handleBadCert)(ss->badCertArg, ss->fd);
+ }
+ }
+
+ if (rv == SECWouldBlock) {
+ if (ss->sec.isServer) {
+ errCode = SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS;
+ rv = SECFailure;
+ goto loser;
+ }
+ /* TODO(ekr@rtfm.com): Reenable for TLS 1.3 */
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ errCode = SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION;
+ rv = SECFailure;
+ goto loser;
+ }
+
+ ss->ssl3.hs.authCertificatePending = PR_TRUE;
+ rv = SECSuccess;
+ }
+
+ if (rv != SECSuccess) {
+ ssl3_SendAlertForCertError(ss, errCode);
+ goto loser;
+ }
}
ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
@@ -11119,81 +11435,103 @@ ssl3_AuthCertificate(sslSocket *ss)
if (!ss->sec.isServer) {
CERTCertificate *cert = ss->sec.peerCert;
- /* set the server authentication and key exchange types and sizes
- ** from the value in the cert. If the key exchange key is different,
- ** it will get fixed when we handle the server key exchange message.
- */
- SECKEYPublicKey * pubKey = CERT_ExtractPublicKey(cert);
- ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType;
- ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
- if (pubKey) {
- KeyType pubKeyType;
- PRInt32 minKey;
- ss->sec.keaKeyBits = ss->sec.authKeyBits =
- SECKEY_PublicKeyStrengthInBits(pubKey);
+ /* set the server authentication type and size from the value
+ ** in the cert. */
+ SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(cert);
+ ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType;
+ ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
+ if (pubKey) {
+ KeyType pubKeyType;
+ PRInt32 minKey;
+ /* This partly fixes Bug 124230 and may cause problems for
+ * callers which depend on the old (wrong) behavior. */
+ ss->sec.authKeyBits = SECKEY_PublicKeyStrengthInBits(pubKey);
pubKeyType = SECKEY_GetPublicKeyType(pubKey);
- minKey = ss->sec.authKeyBits;
- switch (pubKeyType) {
- case rsaKey:
- case rsaPssKey:
- case rsaOaepKey:
- rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minKey);
- if (rv != SECSuccess) {
- minKey = SSL_RSA_MIN_MODULUS_BITS;
- }
- break;
- case dsaKey:
- rv = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minKey);
- if (rv != SECSuccess) {
- minKey = SSL_DSA_MIN_P_BITS;
- }
- break;
- case dhKey:
- rv = NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minKey);
- if (rv != SECSuccess) {
- minKey = SSL_DH_MIN_P_BITS;
- }
- break;
- default:
- break;
- }
+ minKey = ss->sec.authKeyBits;
+ switch (pubKeyType) {
+ case rsaKey:
+ case rsaPssKey:
+ case rsaOaepKey:
+ rv =
+ NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minKey);
+ if (rv !=
+ SECSuccess) {
+ minKey =
+ SSL_RSA_MIN_MODULUS_BITS;
+ }
+ break;
+ case dsaKey:
+ rv =
+ NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minKey);
+ if (rv !=
+ SECSuccess) {
+ minKey =
+ SSL_DSA_MIN_P_BITS;
+ }
+ break;
+ case dhKey:
+ rv =
+ NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minKey);
+ if (rv !=
+ SECSuccess) {
+ minKey =
+ SSL_DH_MIN_P_BITS;
+ }
+ break;
+ default:
+ break;
+ }
/* Too small: not good enough. Send a fatal alert. */
/* We aren't checking EC here on the understanding that we only
* support curves we like, a decision that might need revisiting. */
- if ( ss->sec.authKeyBits < minKey) {
+ if (ss->sec.authKeyBits < minKey) {
PORT_SetError(SSL_ERROR_WEAK_SERVER_CERT_KEY);
(void)SSL3_SendAlert(ss, alert_fatal,
ss->version >= SSL_LIBRARY_VERSION_TLS_1_0
- ? insufficient_security
- : illegal_parameter);
+ ? insufficient_security
+ : illegal_parameter);
SECKEY_DestroyPublicKey(pubKey);
return SECFailure;
}
- SECKEY_DestroyPublicKey(pubKey);
- pubKey = NULL;
- }
-
- /* Ephemeral suites require ServerKeyExchange. Export cipher suites
- * with RSA key exchange also require ServerKeyExchange if the
- * authentication key exceeds the key size limit. */
- if (ss->ssl3.hs.kea_def->ephemeral ||
- (ss->ssl3.hs.kea_def->is_limited &&
- ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_rsa &&
- ss->sec.authKeyBits > ss->ssl3.hs.kea_def->key_size_limit)) {
- ss->ssl3.hs.ws = wait_server_key; /* require server_key_exchange */
+ SECKEY_DestroyPublicKey(pubKey);
+ pubKey = NULL;
+ }
+
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ TLS13_SET_HS_STATE(ss, wait_cert_verify);
} else {
- ss->ssl3.hs.ws = wait_cert_request; /* disallow server_key_exchange */
+ /* Ephemeral suites require ServerKeyExchange. Export cipher suites
+ * with RSA key exchange also require ServerKeyExchange if the
+ * authentication key exceeds the key size limit. */
+ if (ss->ssl3.hs.kea_def->ephemeral ||
+ (ss->ssl3.hs.kea_def->is_limited &&
+ ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_rsa &&
+ ss->sec.authKeyBits > ss->ssl3.hs.kea_def->key_size_limit)) {
+ /* require server_key_exchange */
+ ss->ssl3.hs.ws = wait_server_key;
+ } else {
+ /* disallow server_key_exchange */
+ ss->ssl3.hs.ws = wait_cert_request;
+ /* This is static RSA key exchange so set the key bits to
+ * auth bits. */
+ ss->sec.keaKeyBits = ss->sec.authKeyBits;
+ }
}
} else {
- ss->ssl3.hs.ws = wait_client_key;
+ /* Server */
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ ss->ssl3.hs.ws = wait_client_key;
+ } else {
+ TLS13_SET_HS_STATE(ss, wait_cert_verify);
+ }
}
PORT_Assert(rv == SECSuccess);
if (rv != SECSuccess) {
- errCode = SEC_ERROR_LIBRARY_FAILURE;
- rv = SECFailure;
- goto loser;
+ errCode = SEC_ERROR_LIBRARY_FAILURE;
+ rv = SECFailure;
+ goto loser;
}
return rv;
@@ -11206,7 +11544,7 @@ loser:
static SECStatus ssl3_FinishHandshake(sslSocket *ss);
static SECStatus
-ssl3_AlwaysFail(sslSocket * ss)
+ssl3_AlwaysFail(sslSocket *ss)
{
PORT_SetError(PR_INVALID_STATE_ERROR);
return SECFailure;
@@ -11222,61 +11560,63 @@ ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error)
PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
if (ss->sec.isServer) {
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS);
+ return SECFailure;
}
ssl_GetRecvBufLock(ss);
ssl_GetSSL3HandshakeLock(ss);
if (!ss->ssl3.hs.authCertificatePending) {
- PORT_SetError(PR_INVALID_STATE_ERROR);
- rv = SECFailure;
- goto done;
+ PORT_SetError(PR_INVALID_STATE_ERROR);
+ rv = SECFailure;
+ goto done;
}
ss->ssl3.hs.authCertificatePending = PR_FALSE;
if (error != 0) {
- ss->ssl3.hs.restartTarget = ssl3_AlwaysFail;
- ssl3_SendAlertForCertError(ss, error);
- rv = SECSuccess;
+ ss->ssl3.hs.restartTarget = ssl3_AlwaysFail;
+ ssl3_SendAlertForCertError(ss, error);
+ rv = SECSuccess;
} else if (ss->ssl3.hs.restartTarget != NULL) {
- sslRestartTarget target = ss->ssl3.hs.restartTarget;
- ss->ssl3.hs.restartTarget = NULL;
-
- if (target == ssl3_FinishHandshake) {
- SSL_TRC(3,("%d: SSL3[%p]: certificate authentication lost the race"
- " with peer's finished message", SSL_GETPID(), ss->fd));
- }
-
- rv = target(ss);
- /* Even if we blocked here, we have accomplished enough to claim
- * success. Any remaining work will be taken care of by subsequent
- * calls to SSL_ForceHandshake/PR_Send/PR_Read/etc.
- */
- if (rv == SECWouldBlock) {
- rv = SECSuccess;
- }
+ sslRestartTarget target = ss->ssl3.hs.restartTarget;
+ ss->ssl3.hs.restartTarget = NULL;
+
+ if (target == ssl3_FinishHandshake) {
+ SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication lost the race"
+ " with peer's finished message",
+ SSL_GETPID(), ss->fd));
+ }
+
+ rv = target(ss);
+ /* Even if we blocked here, we have accomplished enough to claim
+ * success. Any remaining work will be taken care of by subsequent
+ * calls to SSL_ForceHandshake/PR_Send/PR_Read/etc.
+ */
+ if (rv == SECWouldBlock) {
+ rv = SECSuccess;
+ }
} else {
- SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race with"
- " peer's finished message", SSL_GETPID(), ss->fd));
-
- PORT_Assert(!ss->ssl3.hs.isResuming);
- PORT_Assert(ss->ssl3.hs.ws != idle_handshake);
-
- if (ss->opt.enableFalseStart &&
- !ss->firstHsDone &&
- !ss->ssl3.hs.isResuming &&
- ssl3_WaitingForStartOfServerSecondRound(ss)) {
- /* ssl3_SendClientSecondRound deferred the false start check because
- * certificate authentication was pending, so we do it now if we still
- * haven't received any of the server's second round yet.
- */
- rv = ssl3_CheckFalseStart(ss);
- } else {
- rv = SECSuccess;
- }
+ SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race with"
+ " peer's finished message",
+ SSL_GETPID(), ss->fd));
+
+ PORT_Assert(!ss->ssl3.hs.isResuming);
+ PORT_Assert(ss->ssl3.hs.ws != idle_handshake);
+
+ if (ss->opt.enableFalseStart &&
+ !ss->firstHsDone &&
+ !ss->ssl3.hs.isResuming &&
+ ssl3_WaitingForServerSecondRound(ss)) {
+ /* ssl3_SendClientSecondRound deferred the false start check because
+ * certificate authentication was pending, so we do it now if we still
+ * haven't received all of the server's second round yet.
+ */
+ rv = ssl3_CheckFalseStart(ss);
+ } else {
+ rv = SECSuccess;
+ }
}
done:
@@ -11288,43 +11628,43 @@ done:
static SECStatus
ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
- PRBool isServer,
- const SSL3Hashes * hashes,
- TLSFinished * tlsFinished)
+ PRBool isServer,
+ const SSL3Hashes *hashes,
+ TLSFinished *tlsFinished)
{
SECStatus rv;
CK_TLS_MAC_PARAMS tls_mac_params;
- SECItem param = {siBuffer, NULL, 0};
+ SECItem param = { siBuffer, NULL, 0 };
PK11Context *prf_context;
unsigned int retLen;
if (!spec->master_secret || spec->bypassCiphers) {
- const char *label = isServer ? "server finished" : "client finished";
- unsigned int len = 15;
+ const char *label = isServer ? "server finished" : "client finished";
+ unsigned int len = 15;
- return ssl3_TLSPRFWithMasterSecret(spec, label, len, hashes->u.raw,
- hashes->len, tlsFinished->verify_data,
- sizeof tlsFinished->verify_data);
+ return ssl3_TLSPRFWithMasterSecret(spec, label, len, hashes->u.raw,
+ hashes->len, tlsFinished->verify_data,
+ sizeof tlsFinished->verify_data);
}
if (spec->version < SSL_LIBRARY_VERSION_TLS_1_2) {
- tls_mac_params.prfMechanism = CKM_TLS_PRF;
+ tls_mac_params.prfMechanism = CKM_TLS_PRF;
} else {
- tls_mac_params.prfMechanism = CKM_SHA256;
+ tls_mac_params.prfMechanism = CKM_SHA256;
}
tls_mac_params.ulMacLength = 12;
tls_mac_params.ulServerOrClient = isServer ? 1 : 2;
param.data = (unsigned char *)&tls_mac_params;
param.len = sizeof(tls_mac_params);
prf_context = PK11_CreateContextBySymKey(CKM_TLS_MAC, CKA_SIGN,
- spec->master_secret, &param);
+ spec->master_secret, &param);
if (!prf_context)
- return SECFailure;
+ return SECFailure;
- rv = PK11_DigestBegin(prf_context);
+ rv = PK11_DigestBegin(prf_context);
rv |= PK11_DigestOp(prf_context, hashes->u.raw, hashes->len);
rv |= PK11_DigestFinal(prf_context, tlsFinished->verify_data, &retLen,
- sizeof tlsFinished->verify_data);
+ sizeof tlsFinished->verify_data);
PORT_Assert(rv != SECSuccess || retLen == sizeof tlsFinished->verify_data);
PK11_DestroyContext(prf_context, PR_TRUE);
@@ -11338,54 +11678,54 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
*/
SECStatus
ssl3_TLSPRFWithMasterSecret(ssl3CipherSpec *spec, const char *label,
- unsigned int labelLen, const unsigned char *val, unsigned int valLen,
- unsigned char *out, unsigned int outLen)
+ unsigned int labelLen, const unsigned char *val, unsigned int valLen,
+ unsigned char *out, unsigned int outLen)
{
SECStatus rv = SECSuccess;
if (spec->master_secret && !spec->bypassCiphers) {
- SECItem param = {siBuffer, NULL, 0};
- CK_MECHANISM_TYPE mech = CKM_TLS_PRF_GENERAL;
- PK11Context *prf_context;
- unsigned int retLen;
-
- if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
- mech = CKM_NSS_TLS_PRF_GENERAL_SHA256;
- }
- prf_context = PK11_CreateContextBySymKey(mech, CKA_SIGN,
- spec->master_secret, &param);
- if (!prf_context)
- return SECFailure;
-
- rv = PK11_DigestBegin(prf_context);
- rv |= PK11_DigestOp(prf_context, (unsigned char *) label, labelLen);
- rv |= PK11_DigestOp(prf_context, val, valLen);
- rv |= PK11_DigestFinal(prf_context, out, &retLen, outLen);
- PORT_Assert(rv != SECSuccess || retLen == outLen);
-
- PK11_DestroyContext(prf_context, PR_TRUE);
+ SECItem param = { siBuffer, NULL, 0 };
+ CK_MECHANISM_TYPE mech = CKM_TLS_PRF_GENERAL;
+ PK11Context *prf_context;
+ unsigned int retLen;
+
+ if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+ mech = CKM_NSS_TLS_PRF_GENERAL_SHA256;
+ }
+ prf_context = PK11_CreateContextBySymKey(mech, CKA_SIGN,
+ spec->master_secret, &param);
+ if (!prf_context)
+ return SECFailure;
+
+ rv = PK11_DigestBegin(prf_context);
+ rv |= PK11_DigestOp(prf_context, (unsigned char *)label, labelLen);
+ rv |= PK11_DigestOp(prf_context, val, valLen);
+ rv |= PK11_DigestFinal(prf_context, out, &retLen, outLen);
+ PORT_Assert(rv != SECSuccess || retLen == outLen);
+
+ PK11_DestroyContext(prf_context, PR_TRUE);
} else {
- /* bypass PKCS11 */
+/* bypass PKCS11 */
#ifdef NO_PKCS11_BYPASS
- PORT_Assert(spec->master_secret);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- rv = SECFailure;
+ PORT_Assert(spec->master_secret);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ rv = SECFailure;
#else
- SECItem inData = { siBuffer, };
- SECItem outData = { siBuffer, };
- PRBool isFIPS = PR_FALSE;
-
- inData.data = (unsigned char *) val;
- inData.len = valLen;
- outData.data = out;
- outData.len = outLen;
- if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
- rv = TLS_P_hash(HASH_AlgSHA256, &spec->msItem, label, &inData,
- &outData, isFIPS);
- } else {
- rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS);
- }
- PORT_Assert(rv != SECSuccess || outData.len == outLen);
+ SECItem inData = { siBuffer };
+ SECItem outData = { siBuffer };
+ PRBool isFIPS = PR_FALSE;
+
+ inData.data = (unsigned char *)val;
+ inData.len = valLen;
+ outData.data = out;
+ outData.len = outLen;
+ if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+ rv = TLS_P_hash(HASH_AlgSHA256, &spec->msItem, label, &inData,
+ &outData, isFIPS);
+ } else {
+ rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS);
+ }
+ PORT_Assert(rv != SECSuccess || outData.len == outLen);
#endif
}
return rv;
@@ -11399,31 +11739,32 @@ ssl3_SendNextProto(sslSocket *ss)
{
SECStatus rv;
int padding_len;
- static const unsigned char padding[32] = {0};
+ static const unsigned char padding[32] = { 0 };
if (ss->ssl3.nextProto.len == 0 ||
- ss->ssl3.nextProtoState == SSL_NEXT_PROTO_SELECTED) {
- return SECSuccess;
+ ss->ssl3.nextProtoState == SSL_NEXT_PROTO_SELECTED) {
+ return SECSuccess;
}
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
padding_len = 32 - ((ss->ssl3.nextProto.len + 2) % 32);
rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->ssl3.nextProto.len +
- 2 + padding_len);
+ 2 +
+ padding_len);
if (rv != SECSuccess) {
- return rv; /* error code set by AppendHandshakeHeader */
+ return rv; /* error code set by AppendHandshakeHeader */
}
rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.nextProto.data,
- ss->ssl3.nextProto.len, 1);
+ ss->ssl3.nextProto.len, 1);
if (rv != SECSuccess) {
- return rv; /* error code set by AppendHandshake */
+ return rv; /* error code set by AppendHandshake */
}
rv = ssl3_AppendHandshakeVariable(ss, padding, padding_len, 1);
if (rv != SECSuccess) {
- return rv; /* error code set by AppendHandshake */
+ return rv; /* error code set by AppendHandshake */
}
return rv;
}
@@ -11438,28 +11779,28 @@ ssl3_RecordKeyLog(sslSocket *ss)
SECStatus rv;
SECItem *keyData;
char buf[14 /* "CLIENT_RANDOM " */ +
- SSL3_RANDOM_LENGTH*2 /* client_random */ +
- 1 /* " " */ +
- 48*2 /* master secret */ +
+ SSL3_RANDOM_LENGTH * 2 /* client_random */ +
+ 1 /* " " */ +
+ 48 * 2 /* master secret */ +
1 /* new line */];
unsigned int j;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (!ssl_keylog_iob)
- return;
+ return;
rv = PK11_ExtractKeyValue(ss->ssl3.cwSpec->master_secret);
if (rv != SECSuccess)
- return;
+ return;
ssl_GetSpecReadLock(ss);
/* keyData does not need to be freed. */
keyData = PK11_GetKeyData(ss->ssl3.cwSpec->master_secret);
if (!keyData || !keyData->data || keyData->len != 48) {
- ssl_ReleaseSpecReadLock(ss);
- return;
+ ssl_ReleaseSpecReadLock(ss);
+ return;
}
/* https://developer.mozilla.org/en/NSS_Key_Log_Format */
@@ -11471,10 +11812,10 @@ ssl3_RecordKeyLog(sslSocket *ss)
memcpy(buf, "CLIENT_RANDOM ", 14);
j = 14;
hexEncode(buf + j, ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
- j += SSL3_RANDOM_LENGTH*2;
+ j += SSL3_RANDOM_LENGTH * 2;
buf[j++] = ' ';
hexEncode(buf + j, keyData->data, 48);
- j += 48*2;
+ j += 48 * 2;
buf[j++] = '\n';
PORT_Assert(j == sizeof(buf));
@@ -11491,7 +11832,7 @@ ssl3_RecordKeyLog(sslSocket *ss)
* ssl3_HandleFinished
*/
static SECStatus
-ssl3_SendEncryptedExtensions(sslSocket *ss)
+ssl3_SendChannelIDEncryptedExtensions(sslSocket *ss)
{
static const char CHANNEL_ID_MAGIC[] = "TLS Channel ID signature";
static const char CHANNEL_ID_RESUMPTION_MAGIC[] = "Resumption";
@@ -11506,10 +11847,10 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
* public key. Following that are the two field elements as 32-byte,
* big-endian numbers, as required by the Channel ID. */
static const unsigned char P256_SPKI_PREFIX[] = {
- 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
- 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
- 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
- 0x42, 0x00, 0x04
+ 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+ 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
+ 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
+ 0x42, 0x00, 0x04
};
/* ChannelIDs are always 128 bytes long: 64 bytes of P-256 public key and 64
* bytes of ECDSA signature. */
@@ -11522,7 +11863,7 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
const unsigned char *pub_bytes;
unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) +
sizeof(CHANNEL_ID_RESUMPTION_MAGIC) +
- sizeof(SSL3Hashes)*2];
+ sizeof(SSL3Hashes) * 2];
size_t signed_data_len;
unsigned char digest[SHA256_LENGTH];
SECItem digest_item;
@@ -11533,15 +11874,15 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ss->ssl3.channelID == NULL)
- return SECSuccess;
+ return SECSuccess;
PORT_Assert(ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn));
if (SECKEY_GetPrivateKeyType(ss->ssl3.channelID) != ecKey ||
- PK11_SignatureLen(ss->ssl3.channelID) != sizeof(signature)) {
- PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
- rv = SECFailure;
- goto loser;
+ PK11_SignatureLen(ss->ssl3.channelID) != sizeof(signature)) {
+ PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
+ rv = SECFailure;
+ goto loser;
}
ssl_GetSpecReadLock(ss);
@@ -11549,26 +11890,26 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
ssl_ReleaseSpecReadLock(ss);
if (rv != SECSuccess)
- goto loser;
+ goto loser;
- rv = ssl3_AppendHandshakeHeader(ss, encrypted_extensions,
- 2 + 2 + CHANNEL_ID_LENGTH);
+ rv = ssl3_AppendHandshakeHeader(ss, channelid_encrypted_extensions,
+ 2 + 2 + CHANNEL_ID_LENGTH);
if (rv != SECSuccess)
- goto loser; /* error code set by AppendHandshakeHeader */
+ goto loser; /* error code set by AppendHandshakeHeader */
rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
if (rv != SECSuccess)
- goto loser; /* error code set by AppendHandshake */
+ goto loser; /* error code set by AppendHandshake */
rv = ssl3_AppendHandshakeNumber(ss, CHANNEL_ID_LENGTH, 2);
if (rv != SECSuccess)
- goto loser; /* error code set by AppendHandshake */
+ goto loser; /* error code set by AppendHandshake */
spki = SECKEY_EncodeDERSubjectPublicKeyInfo(ss->ssl3.channelIDPub);
if (spki->len != sizeof(P256_SPKI_PREFIX) + CHANNEL_ID_PUBLIC_KEY_LENGTH ||
- memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX)) != 0) {
- PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
- rv = SECFailure;
- goto loser;
+ memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX)) != 0) {
+ PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
+ rv = SECFailure;
+ goto loser;
}
pub_bytes = spki->data + sizeof(P256_SPKI_PREFIX);
@@ -11594,7 +11935,7 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, signed_data_len);
if (rv != SECSuccess)
- goto loser;
+ goto loser;
digest_item.data = digest;
digest_item.len = sizeof(digest);
@@ -11604,23 +11945,23 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
rv = PK11_Sign(ss->ssl3.channelID, &signature_item, &digest_item);
if (rv != SECSuccess)
- goto loser;
+ goto loser;
rv = ssl3_AppendHandshake(ss, pub_bytes, CHANNEL_ID_PUBLIC_KEY_LENGTH);
if (rv != SECSuccess)
- goto loser;
+ goto loser;
rv = ssl3_AppendHandshake(ss, signature, sizeof(signature));
loser:
if (spki)
- SECITEM_FreeItem(spki, PR_TRUE);
+ SECITEM_FreeItem(spki, PR_TRUE);
if (ss->ssl3.channelID) {
- SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
- ss->ssl3.channelID = NULL;
+ SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
+ ss->ssl3.channelID = NULL;
}
if (ss->ssl3.channelIDPub) {
- SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
- ss->ssl3.channelIDPub = NULL;
+ SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
+ ss->ssl3.channelIDPub = NULL;
}
return rv;
@@ -11633,30 +11974,30 @@ loser:
* waiting in the buffer or we'll get network I/O. */
SECStatus
ssl3_RestartHandshakeAfterChannelIDReq(sslSocket *ss,
- SECKEYPublicKey *channelIDPub,
- SECKEYPrivateKey *channelID)
+ SECKEYPublicKey *channelIDPub,
+ SECKEYPrivateKey *channelID)
{
if (ss->handshake == 0) {
- SECKEY_DestroyPublicKey(channelIDPub);
- SECKEY_DestroyPrivateKey(channelID);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
+ SECKEY_DestroyPublicKey(channelIDPub);
+ SECKEY_DestroyPrivateKey(channelID);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
}
if (channelIDPub == NULL ||
- channelID == NULL) {
- if (channelIDPub)
- SECKEY_DestroyPublicKey(channelIDPub);
- if (channelID)
- SECKEY_DestroyPrivateKey(channelID);
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return SECFailure;
+ channelID == NULL) {
+ if (channelIDPub)
+ SECKEY_DestroyPublicKey(channelIDPub);
+ if (channelID)
+ SECKEY_DestroyPrivateKey(channelID);
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return SECFailure;
}
if (ss->ssl3.channelID)
- SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
+ SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
if (ss->ssl3.channelIDPub)
- SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
+ SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
ss->handshake = ssl_GatherRecord1stHandshake;
ss->ssl3.channelID = channelID;
@@ -11673,59 +12014,59 @@ static SECStatus
ssl3_SendFinished(sslSocket *ss, PRInt32 flags)
{
ssl3CipherSpec *cwSpec;
- PRBool isTLS;
- PRBool isServer = ss->sec.isServer;
- SECStatus rv;
- SSL3Sender sender = isServer ? sender_server : sender_client;
- SSL3Hashes hashes;
- TLSFinished tlsFinished;
+ PRBool isTLS;
+ PRBool isServer = ss->sec.isServer;
+ SECStatus rv;
+ SSL3Sender sender = isServer ? sender_server : sender_client;
+ SSL3Hashes hashes;
+ TLSFinished tlsFinished;
SSL_TRC(3, ("%d: SSL3[%d]: send finished handshake", SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
ssl_GetSpecReadLock(ss);
cwSpec = ss->ssl3.cwSpec;
isTLS = (PRBool)(cwSpec->version > SSL_LIBRARY_VERSION_3_0);
rv = ssl3_ComputeHandshakeHashes(ss, cwSpec, &hashes, sender);
if (isTLS && rv == SECSuccess) {
- rv = ssl3_ComputeTLSFinished(cwSpec, isServer, &hashes, &tlsFinished);
+ rv = ssl3_ComputeTLSFinished(cwSpec, isServer, &hashes, &tlsFinished);
}
ssl_ReleaseSpecReadLock(ss);
if (rv != SECSuccess) {
- goto fail; /* err code was set by ssl3_ComputeHandshakeHashes */
+ goto fail; /* err code was set by ssl3_ComputeHandshakeHashes */
}
if (isTLS) {
- if (isServer)
- ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished;
- else
- ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished;
- ss->ssl3.hs.finishedBytes = sizeof tlsFinished;
- rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof tlsFinished);
- if (rv != SECSuccess)
- goto fail; /* err set by AppendHandshake. */
- rv = ssl3_AppendHandshake(ss, &tlsFinished, sizeof tlsFinished);
- if (rv != SECSuccess)
- goto fail; /* err set by AppendHandshake. */
+ if (isServer)
+ ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished;
+ else
+ ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished;
+ ss->ssl3.hs.finishedBytes = sizeof tlsFinished;
+ rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof tlsFinished);
+ if (rv != SECSuccess)
+ goto fail; /* err set by AppendHandshake. */
+ rv = ssl3_AppendHandshake(ss, &tlsFinished, sizeof tlsFinished);
+ if (rv != SECSuccess)
+ goto fail; /* err set by AppendHandshake. */
} else {
- if (isServer)
- ss->ssl3.hs.finishedMsgs.sFinished[1] = hashes.u.s;
- else
- ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes.u.s;
- PORT_Assert(hashes.len == sizeof hashes.u.s);
- ss->ssl3.hs.finishedBytes = sizeof hashes.u.s;
- rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof hashes.u.s);
- if (rv != SECSuccess)
- goto fail; /* err set by AppendHandshake. */
- rv = ssl3_AppendHandshake(ss, &hashes.u.s, sizeof hashes.u.s);
- if (rv != SECSuccess)
- goto fail; /* err set by AppendHandshake. */
+ if (isServer)
+ ss->ssl3.hs.finishedMsgs.sFinished[1] = hashes.u.s;
+ else
+ ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes.u.s;
+ PORT_Assert(hashes.len == sizeof hashes.u.s);
+ ss->ssl3.hs.finishedBytes = sizeof hashes.u.s;
+ rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof hashes.u.s);
+ if (rv != SECSuccess)
+ goto fail; /* err set by AppendHandshake. */
+ rv = ssl3_AppendHandshake(ss, &hashes.u.s, sizeof hashes.u.s);
+ if (rv != SECSuccess)
+ goto fail; /* err set by AppendHandshake. */
}
rv = ssl3_FlushHandshake(ss, flags);
if (rv != SECSuccess) {
- goto fail; /* error code set by ssl3_FlushHandshake */
+ goto fail; /* error code set by ssl3_FlushHandshake */
}
ssl3_RecordKeyLog(ss);
@@ -11741,285 +12082,285 @@ fail:
*/
SECStatus
ssl3_CacheWrappedMasterSecret(sslSocket *ss, sslSessionID *sid,
- ssl3CipherSpec *spec, SSL3KEAType effectiveExchKeyType)
-{
- PK11SymKey * wrappingKey = NULL;
- PK11SlotInfo * symKeySlot;
- void * pwArg = ss->pkcs11PinArg;
- SECStatus rv = SECFailure;
- PRBool isServer = ss->sec.isServer;
- CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
+ ssl3CipherSpec *spec, SSL3KEAType effectiveExchKeyType)
+{
+ PK11SymKey *wrappingKey = NULL;
+ PK11SlotInfo *symKeySlot;
+ void *pwArg = ss->pkcs11PinArg;
+ SECStatus rv = SECFailure;
+ PRBool isServer = ss->sec.isServer;
+ CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
symKeySlot = PK11_GetSlotFromKey(spec->master_secret);
if (!isServer) {
- int wrapKeyIndex;
- int incarnation;
-
- /* these next few functions are mere accessors and don't fail. */
- sid->u.ssl3.masterWrapIndex = wrapKeyIndex =
- PK11_GetCurrentWrapIndex(symKeySlot);
- PORT_Assert(wrapKeyIndex == 0); /* array has only one entry! */
-
- sid->u.ssl3.masterWrapSeries = incarnation =
- PK11_GetSlotSeries(symKeySlot);
- sid->u.ssl3.masterSlotID = PK11_GetSlotID(symKeySlot);
- sid->u.ssl3.masterModuleID = PK11_GetModuleID(symKeySlot);
- sid->u.ssl3.masterValid = PR_TRUE;
- /* Get the default wrapping key, for wrapping the master secret before
- * placing it in the SID cache entry. */
- wrappingKey = PK11_GetWrapKey(symKeySlot, wrapKeyIndex,
- CKM_INVALID_MECHANISM, incarnation,
- pwArg);
- if (wrappingKey) {
- mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */
- } else {
- int keyLength;
- /* if the wrappingKey doesn't exist, attempt to create it.
- * Note: we intentionally ignore errors here. If we cannot
- * generate a wrapping key, it is not fatal to this SSL connection,
- * but we will not be able to restart this session.
- */
- mechanism = PK11_GetBestWrapMechanism(symKeySlot);
- keyLength = PK11_GetBestKeyLength(symKeySlot, mechanism);
- /* Zero length means fixed key length algorithm, or error.
- * It's ambiguous.
- */
- wrappingKey = PK11_KeyGen(symKeySlot, mechanism, NULL,
- keyLength, pwArg);
- if (wrappingKey) {
- PK11_SetWrapKey(symKeySlot, wrapKeyIndex, wrappingKey);
- }
- }
+ int wrapKeyIndex;
+ int incarnation;
+
+ /* these next few functions are mere accessors and don't fail. */
+ sid->u.ssl3.masterWrapIndex = wrapKeyIndex =
+ PK11_GetCurrentWrapIndex(symKeySlot);
+ PORT_Assert(wrapKeyIndex == 0); /* array has only one entry! */
+
+ sid->u.ssl3.masterWrapSeries = incarnation =
+ PK11_GetSlotSeries(symKeySlot);
+ sid->u.ssl3.masterSlotID = PK11_GetSlotID(symKeySlot);
+ sid->u.ssl3.masterModuleID = PK11_GetModuleID(symKeySlot);
+ sid->u.ssl3.masterValid = PR_TRUE;
+ /* Get the default wrapping key, for wrapping the master secret before
+ * placing it in the SID cache entry. */
+ wrappingKey = PK11_GetWrapKey(symKeySlot, wrapKeyIndex,
+ CKM_INVALID_MECHANISM, incarnation,
+ pwArg);
+ if (wrappingKey) {
+ mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */
+ } else {
+ int keyLength;
+ /* if the wrappingKey doesn't exist, attempt to create it.
+ * Note: we intentionally ignore errors here. If we cannot
+ * generate a wrapping key, it is not fatal to this SSL connection,
+ * but we will not be able to restart this session.
+ */
+ mechanism = PK11_GetBestWrapMechanism(symKeySlot);
+ keyLength = PK11_GetBestKeyLength(symKeySlot, mechanism);
+ /* Zero length means fixed key length algorithm, or error.
+ * It's ambiguous.
+ */
+ wrappingKey = PK11_KeyGen(symKeySlot, mechanism, NULL,
+ keyLength, pwArg);
+ if (wrappingKey) {
+ PK11_SetWrapKey(symKeySlot, wrapKeyIndex, wrappingKey);
+ }
+ }
} else {
- /* server socket using session cache. */
- mechanism = PK11_GetBestWrapMechanism(symKeySlot);
- if (mechanism != CKM_INVALID_MECHANISM) {
- wrappingKey =
- getWrappingKey(ss, symKeySlot, effectiveExchKeyType,
- mechanism, pwArg);
- if (wrappingKey) {
- mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */
- }
- }
+ /* server socket using session cache. */
+ mechanism = PK11_GetBestWrapMechanism(symKeySlot);
+ if (mechanism != CKM_INVALID_MECHANISM) {
+ wrappingKey =
+ getWrappingKey(ss, symKeySlot, effectiveExchKeyType,
+ mechanism, pwArg);
+ if (wrappingKey) {
+ mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */
+ }
+ }
}
sid->u.ssl3.masterWrapMech = mechanism;
PK11_FreeSlot(symKeySlot);
if (wrappingKey) {
- SECItem wmsItem;
+ SECItem wmsItem;
- wmsItem.data = sid->u.ssl3.keys.wrapped_master_secret;
- wmsItem.len = sizeof sid->u.ssl3.keys.wrapped_master_secret;
- rv = PK11_WrapSymKey(mechanism, NULL, wrappingKey,
- spec->master_secret, &wmsItem);
- /* rv is examined below. */
- sid->u.ssl3.keys.wrapped_master_secret_len = wmsItem.len;
- PK11_FreeSymKey(wrappingKey);
+ wmsItem.data = sid->u.ssl3.keys.wrapped_master_secret;
+ wmsItem.len = sizeof sid->u.ssl3.keys.wrapped_master_secret;
+ rv = PK11_WrapSymKey(mechanism, NULL, wrappingKey,
+ spec->master_secret, &wmsItem);
+ /* rv is examined below. */
+ sid->u.ssl3.keys.wrapped_master_secret_len = wmsItem.len;
+ PK11_FreeSymKey(wrappingKey);
}
return rv;
}
-/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
- * ssl3 Finished message from the peer.
+/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
+ * a complete ssl3 Finished message from the peer.
* Caller must hold Handshake and RecvBuf locks.
*/
static SECStatus
ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
- const SSL3Hashes *hashes)
+ const SSL3Hashes *hashes)
{
- sslSessionID * sid = ss->sec.ci.sid;
- SECStatus rv = SECSuccess;
- PRBool isServer = ss->sec.isServer;
- PRBool isTLS;
- SSL3KEAType effectiveExchKeyType;
+ sslSessionID *sid = ss->sec.ci.sid;
+ SECStatus rv = SECSuccess;
+ PRBool isServer = ss->sec.isServer;
+ PRBool isTLS;
+ SSL3KEAType effectiveExchKeyType;
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
SSL_TRC(3, ("%d: SSL3[%d]: handle finished handshake",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
if (ss->ssl3.hs.ws != wait_finished) {
- SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_FINISHED);
- return SECFailure;
+ SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_FINISHED);
+ return SECFailure;
}
if (!hashes) {
PORT_Assert(0);
- SSL3_SendAlert(ss, alert_fatal, internal_error);
+ SSL3_SendAlert(ss, alert_fatal, internal_error);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
isTLS = (PRBool)(ss->ssl3.crSpec->version > SSL_LIBRARY_VERSION_3_0);
if (isTLS) {
- TLSFinished tlsFinished;
-
- if (length != sizeof tlsFinished) {
- (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
- PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED);
- return SECFailure;
- }
- rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer,
- hashes, &tlsFinished);
- if (!isServer)
- ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished;
- else
- ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished;
- ss->ssl3.hs.finishedBytes = sizeof tlsFinished;
- if (rv != SECSuccess ||
- 0 != NSS_SecureMemcmp(&tlsFinished, b, length)) {
- (void)SSL3_SendAlert(ss, alert_fatal, decrypt_error);
- PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
- return SECFailure;
- }
+ TLSFinished tlsFinished;
+
+ if (length != sizeof tlsFinished) {
+ (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED);
+ return SECFailure;
+ }
+ rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer,
+ hashes, &tlsFinished);
+ if (!isServer)
+ ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished;
+ else
+ ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished;
+ ss->ssl3.hs.finishedBytes = sizeof tlsFinished;
+ if (rv != SECSuccess ||
+ 0 != NSS_SecureMemcmp(&tlsFinished, b, length)) {
+ (void)SSL3_SendAlert(ss, alert_fatal, decrypt_error);
+ PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
+ return SECFailure;
+ }
} else {
- if (length != sizeof(SSL3Finished)) {
- (void)ssl3_IllegalParameter(ss);
- PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED);
- return SECFailure;
- }
-
- if (!isServer)
- ss->ssl3.hs.finishedMsgs.sFinished[1] = hashes->u.s;
- else
- ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes->u.s;
- PORT_Assert(hashes->len == sizeof hashes->u.s);
- ss->ssl3.hs.finishedBytes = sizeof hashes->u.s;
- if (0 != NSS_SecureMemcmp(&hashes->u.s, b, length)) {
- (void)ssl3_HandshakeFailure(ss);
- PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
- return SECFailure;
- }
- }
-
- ssl_GetXmitBufLock(ss); /*************************************/
+ if (length != sizeof(SSL3Finished)) {
+ (void)ssl3_IllegalParameter(ss);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED);
+ return SECFailure;
+ }
+
+ if (!isServer)
+ ss->ssl3.hs.finishedMsgs.sFinished[1] = hashes->u.s;
+ else
+ ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes->u.s;
+ PORT_Assert(hashes->len == sizeof hashes->u.s);
+ ss->ssl3.hs.finishedBytes = sizeof hashes->u.s;
+ if (0 != NSS_SecureMemcmp(&hashes->u.s, b, length)) {
+ (void)ssl3_HandshakeFailure(ss);
+ PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
+ return SECFailure;
+ }
+ }
+
+ ssl_GetXmitBufLock(ss); /*************************************/
if ((isServer && !ss->ssl3.hs.isResuming) ||
- (!isServer && ss->ssl3.hs.isResuming)) {
- PRInt32 flags = 0;
-
- /* Send a NewSessionTicket message if the client sent us
- * either an empty session ticket, or one that did not verify.
- * (Note that if either of these conditions was met, then the
- * server has sent a SessionTicket extension in the
- * ServerHello message.)
- */
- if (isServer && !ss->ssl3.hs.isResuming &&
- ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) &&
- ssl3_KEAAllowsSessionTicket(ss->ssl3.hs.suite_def->key_exchange_alg)) {
- /* RFC 5077 Section 3.3: "In the case of a full handshake, the
- * server MUST verify the client's Finished message before sending
- * the ticket." Presumably, this also means that the client's
- * certificate, if any, must be verified beforehand too.
- */
- rv = ssl3_SendNewSessionTicket(ss);
- if (rv != SECSuccess) {
- goto xmit_loser;
- }
- }
-
- rv = ssl3_SendChangeCipherSpecs(ss);
- if (rv != SECSuccess) {
- goto xmit_loser; /* err is set. */
- }
- /* If this thread is in SSL_SecureSend (trying to write some data)
- ** then set the ssl_SEND_FLAG_FORCE_INTO_BUFFER flag, so that the
- ** last two handshake messages (change cipher spec and finished)
- ** will be sent in the same send/write call as the application data.
- */
- if (ss->writerThread == PR_GetCurrentThread()) {
- flags = ssl_SEND_FLAG_FORCE_INTO_BUFFER;
- }
-
- if (!isServer) {
- if (!ss->firstHsDone) {
- rv = ssl3_SendNextProto(ss);
- if (rv != SECSuccess) {
- goto xmit_loser; /* err code was set. */
- }
- }
- rv = ssl3_SendEncryptedExtensions(ss);
- if (rv != SECSuccess)
- goto xmit_loser; /* err code was set. */
- }
-
- if (IS_DTLS(ss)) {
- flags |= ssl_SEND_FLAG_NO_RETRANSMIT;
- }
-
- rv = ssl3_SendFinished(ss, flags);
- if (rv != SECSuccess) {
- goto xmit_loser; /* err is set. */
- }
+ (!isServer && ss->ssl3.hs.isResuming)) {
+ PRInt32 flags = 0;
+
+ /* Send a NewSessionTicket message if the client sent us
+ * either an empty session ticket, or one that did not verify.
+ * (Note that if either of these conditions was met, then the
+ * server has sent a SessionTicket extension in the
+ * ServerHello message.)
+ */
+ if (isServer && !ss->ssl3.hs.isResuming &&
+ ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) &&
+ ssl3_KEAAllowsSessionTicket(ss->ssl3.hs.suite_def->key_exchange_alg)) {
+ /* RFC 5077 Section 3.3: "In the case of a full handshake, the
+ * server MUST verify the client's Finished message before sending
+ * the ticket." Presumably, this also means that the client's
+ * certificate, if any, must be verified beforehand too.
+ */
+ rv = ssl3_SendNewSessionTicket(ss);
+ if (rv != SECSuccess) {
+ goto xmit_loser;
+ }
+ }
+
+ rv = ssl3_SendChangeCipherSpecs(ss);
+ if (rv != SECSuccess) {
+ goto xmit_loser; /* err is set. */
+ }
+ /* If this thread is in SSL_SecureSend (trying to write some data)
+ ** then set the ssl_SEND_FLAG_FORCE_INTO_BUFFER flag, so that the
+ ** last two handshake messages (change cipher spec and finished)
+ ** will be sent in the same send/write call as the application data.
+ */
+ if (ss->writerThread == PR_GetCurrentThread()) {
+ flags = ssl_SEND_FLAG_FORCE_INTO_BUFFER;
+ }
+
+ if (!isServer) {
+ if (!ss->firstHsDone) {
+ rv = ssl3_SendNextProto(ss);
+ if (rv != SECSuccess) {
+ goto xmit_loser; /* err code was set. */
+ }
+ }
+ rv = ssl3_SendChannelIDEncryptedExtensions(ss);
+ if (rv != SECSuccess)
+ goto xmit_loser; /* err code was set. */
+ }
+
+ if (IS_DTLS(ss)) {
+ flags |= ssl_SEND_FLAG_NO_RETRANSMIT;
+ }
+
+ rv = ssl3_SendFinished(ss, flags);
+ if (rv != SECSuccess) {
+ goto xmit_loser; /* err is set. */
+ }
}
xmit_loser:
- ssl_ReleaseXmitBufLock(ss); /*************************************/
+ ssl_ReleaseXmitBufLock(ss); /*************************************/
if (rv != SECSuccess) {
return rv;
}
if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) {
- effectiveExchKeyType = kt_rsa;
+ effectiveExchKeyType = kt_rsa;
} else {
- effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
+ effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
}
if (sid->cached == never_cached && !ss->opt.noCache && ss->sec.cache) {
- /* fill in the sid */
- sid->u.ssl3.cipherSuite = ss->ssl3.hs.cipher_suite;
- sid->u.ssl3.compression = ss->ssl3.hs.compression;
- sid->u.ssl3.policy = ss->ssl3.policy;
+ /* fill in the sid */
+ sid->u.ssl3.cipherSuite = ss->ssl3.hs.cipher_suite;
+ sid->u.ssl3.compression = ss->ssl3.hs.compression;
+ sid->u.ssl3.policy = ss->ssl3.policy;
#ifndef NSS_DISABLE_ECC
- sid->u.ssl3.negotiatedECCurves = ss->ssl3.hs.negotiatedECCurves;
+ sid->u.ssl3.negotiatedECCurves = ss->ssl3.hs.negotiatedECCurves;
#endif
- sid->u.ssl3.exchKeyType = effectiveExchKeyType;
- sid->version = ss->version;
- sid->authAlgorithm = ss->sec.authAlgorithm;
- sid->authKeyBits = ss->sec.authKeyBits;
- sid->keaType = ss->sec.keaType;
- sid->keaKeyBits = ss->sec.keaKeyBits;
- sid->lastAccessTime = sid->creationTime = ssl_Time();
- sid->expirationTime = sid->creationTime + ssl3_sid_timeout;
- sid->localCert = CERT_DupCertificate(ss->sec.localCert);
-
- ssl_GetSpecReadLock(ss); /*************************************/
-
- /* Copy the master secret (wrapped or unwrapped) into the sid */
- if (ss->ssl3.crSpec->msItem.len && ss->ssl3.crSpec->msItem.data) {
- sid->u.ssl3.keys.wrapped_master_secret_len =
- ss->ssl3.crSpec->msItem.len;
- memcpy(sid->u.ssl3.keys.wrapped_master_secret,
- ss->ssl3.crSpec->msItem.data, ss->ssl3.crSpec->msItem.len);
- sid->u.ssl3.masterValid = PR_TRUE;
- sid->u.ssl3.keys.msIsWrapped = PR_FALSE;
- rv = SECSuccess;
- } else {
- rv = ssl3_CacheWrappedMasterSecret(ss, ss->sec.ci.sid,
- ss->ssl3.crSpec,
- effectiveExchKeyType);
- sid->u.ssl3.keys.msIsWrapped = PR_TRUE;
- }
- ssl_ReleaseSpecReadLock(ss); /*************************************/
-
- /* If the wrap failed, we don't cache the sid.
- * The connection continues normally however.
- */
- ss->ssl3.hs.cacheSID = rv == SECSuccess;
+ sid->u.ssl3.exchKeyType = effectiveExchKeyType;
+ sid->version = ss->version;
+ sid->authAlgorithm = ss->sec.authAlgorithm;
+ sid->authKeyBits = ss->sec.authKeyBits;
+ sid->keaType = ss->sec.keaType;
+ sid->keaKeyBits = ss->sec.keaKeyBits;
+ sid->lastAccessTime = sid->creationTime = ssl_Time();
+ sid->expirationTime = sid->creationTime + ssl3_sid_timeout;
+ sid->localCert = CERT_DupCertificate(ss->sec.localCert);
+
+ ssl_GetSpecReadLock(ss); /*************************************/
+
+ /* Copy the master secret (wrapped or unwrapped) into the sid */
+ if (ss->ssl3.crSpec->msItem.len && ss->ssl3.crSpec->msItem.data) {
+ sid->u.ssl3.keys.wrapped_master_secret_len =
+ ss->ssl3.crSpec->msItem.len;
+ memcpy(sid->u.ssl3.keys.wrapped_master_secret,
+ ss->ssl3.crSpec->msItem.data, ss->ssl3.crSpec->msItem.len);
+ sid->u.ssl3.masterValid = PR_TRUE;
+ sid->u.ssl3.keys.msIsWrapped = PR_FALSE;
+ rv = SECSuccess;
+ } else {
+ rv = ssl3_CacheWrappedMasterSecret(ss, ss->sec.ci.sid,
+ ss->ssl3.crSpec,
+ effectiveExchKeyType);
+ sid->u.ssl3.keys.msIsWrapped = PR_TRUE;
+ }
+ ssl_ReleaseSpecReadLock(ss); /*************************************/
+
+ /* If the wrap failed, we don't cache the sid.
+ * The connection continues normally however.
+ */
+ ss->ssl3.hs.cacheSID = rv == SECSuccess;
}
if (ss->ssl3.hs.authCertificatePending) {
- if (ss->ssl3.hs.restartTarget) {
- PR_NOT_REACHED("ssl3_HandleFinished: unexpected restartTarget");
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
- }
+ if (ss->ssl3.hs.restartTarget) {
+ PR_NOT_REACHED("ssl3_HandleFinished: unexpected restartTarget");
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
- ss->ssl3.hs.restartTarget = ssl3_FinishHandshake;
- return SECWouldBlock;
+ ss->ssl3.hs.restartTarget = ssl3_FinishHandshake;
+ return SECWouldBlock;
}
rv = ssl3_FinishHandshake(ss);
@@ -12030,14 +12371,14 @@ xmit_loser:
* to have type sslRestartTarget.
*/
SECStatus
-ssl3_FinishHandshake(sslSocket * ss)
+ssl3_FinishHandshake(sslSocket *ss)
{
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( ss->ssl3.hs.restartTarget == NULL );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->ssl3.hs.restartTarget == NULL);
/* The first handshake is now completed. */
- ss->handshake = NULL;
+ ss->handshake = NULL;
/* RFC 5077 Section 3.3: "The client MUST NOT treat the ticket as valid
* until it has verified the server's Finished message." When the server
@@ -12051,17 +12392,17 @@ ssl3_FinishHandshake(sslSocket * ss)
* ssl3_SetSIDSessionTicket.
*/
if (ss->ssl3.hs.receivedNewSessionTicket) {
- PORT_Assert(!ss->sec.isServer);
- ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &ss->ssl3.hs.newSessionTicket);
- /* The sid took over the ticket data */
- PORT_Assert(!ss->ssl3.hs.newSessionTicket.ticket.data);
+ PORT_Assert(!ss->sec.isServer);
+ ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &ss->ssl3.hs.newSessionTicket);
+ /* The sid took over the ticket data */
+ PORT_Assert(!ss->ssl3.hs.newSessionTicket.ticket.data);
ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
}
if (ss->ssl3.hs.cacheSID && ss->sec.isServer) {
- PORT_Assert(ss->sec.ci.sid->cached == never_cached);
- (*ss->sec.cache)(ss->sec.ci.sid);
- ss->ssl3.hs.cacheSID = PR_FALSE;
+ PORT_Assert(ss->sec.ci.sid->cached == never_cached);
+ (*ss->sec.cache)(ss->sec.ci.sid);
+ ss->ssl3.hs.cacheSID = PR_FALSE;
}
ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */
@@ -12079,87 +12420,107 @@ ssl3_FinishHandshake(sslSocket * ss)
SECStatus
ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
- SECStatus rv = SECSuccess;
- SSL3HandshakeType type = ss->ssl3.hs.msg_type;
- SSL3Hashes hashes; /* computed hashes are put here. */
- SSL3Hashes *hashesPtr = NULL; /* Set when hashes are computed */
- PRUint8 hdr[4];
- PRUint8 dtlsData[8];
-
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ SECStatus rv = SECSuccess;
+ SSL3HandshakeType type = ss->ssl3.hs.msg_type;
+ SSL3Hashes hashes; /* computed hashes are put here. */
+ SSL3Hashes *hashesPtr = NULL; /* Set when hashes are computed */
+ PRUint8 hdr[4];
+ PRUint8 dtlsData[8];
+ PRBool computeHashes = PR_FALSE;
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
/*
* We have to compute the hashes before we update them with the
* current message.
*/
- ssl_GetSpecReadLock(ss); /************************************/
- if(((type == finished) && (ss->ssl3.hs.ws == wait_finished)) ||
- ((type == certificate_verify) && (ss->ssl3.hs.ws == wait_cert_verify))) {
- SSL3Sender sender = (SSL3Sender)0;
- ssl3CipherSpec *rSpec = ss->ssl3.prSpec;
-
- if (type == finished) {
- sender = ss->sec.isServer ? sender_client : sender_server;
- rSpec = ss->ssl3.crSpec;
- }
- rv = ssl3_ComputeHandshakeHashes(ss, rSpec, &hashes, sender);
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ if (((type == finished) && (ss->ssl3.hs.ws == wait_finished)) ||
+ ((type == certificate_verify) &&
+ (ss->ssl3.hs.ws == wait_cert_verify))) {
+ computeHashes = PR_TRUE;
+ }
+ } else {
+ if (type == certificate_verify) {
+ computeHashes =
+ TLS13_IN_HS_STATE(ss, wait_cert_verify);
+ } else if (type == finished) {
+ computeHashes =
+ TLS13_IN_HS_STATE(ss, wait_cert_request, wait_finished);
+ }
+ }
+
+ ssl_GetSpecReadLock(ss); /************************************/
+ if (computeHashes) {
+ SSL3Sender sender = (SSL3Sender)0;
+ ssl3CipherSpec *rSpec = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 ? ss->ssl3.crSpec
+ : ss->ssl3.prSpec;
+
+ if (type == finished) {
+ sender = ss->sec.isServer ? sender_client : sender_server;
+ rSpec = ss->ssl3.crSpec;
+ }
+ rv = ssl3_ComputeHandshakeHashes(ss, rSpec, &hashes, sender);
if (rv == SECSuccess) {
hashesPtr = &hashes;
}
}
ssl_ReleaseSpecReadLock(ss); /************************************/
if (rv != SECSuccess) {
- return rv; /* error code was set by ssl3_ComputeHandshakeHashes*/
+ return rv; /* error code was set by ssl3_ComputeHandshakeHashes*/
}
- SSL_TRC(30,("%d: SSL3[%d]: handle handshake message: %s", SSL_GETPID(),
- ss->fd, ssl3_DecodeHandshakeType(ss->ssl3.hs.msg_type)));
+ SSL_TRC(30, ("%d: SSL3[%d]: handle handshake message: %s", SSL_GETPID(),
+ ss->fd, ssl3_DecodeHandshakeType(ss->ssl3.hs.msg_type)));
hdr[0] = (PRUint8)ss->ssl3.hs.msg_type;
hdr[1] = (PRUint8)(length >> 16);
- hdr[2] = (PRUint8)(length >> 8);
- hdr[3] = (PRUint8)(length );
+ hdr[2] = (PRUint8)(length >> 8);
+ hdr[3] = (PRUint8)(length);
/* Start new handshake hashes when we start a new handshake */
if (ss->ssl3.hs.msg_type == client_hello) {
- rv = ssl3_RestartHandshakeHashes(ss);
- if (rv != SECSuccess) {
- return rv;
- }
+ rv = ssl3_RestartHandshakeHashes(ss);
+ if (rv != SECSuccess) {
+ return rv;
+ }
}
/* We should not include hello_request and hello_verify_request messages
* in the handshake hashes */
if ((ss->ssl3.hs.msg_type != hello_request) &&
- (ss->ssl3.hs.msg_type != hello_verify_request)) {
- rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char*) hdr, 4);
- if (rv != SECSuccess) return rv; /* err code already set. */
-
- /* Extra data to simulate a complete DTLS handshake fragment */
- if (IS_DTLS(ss)) {
- /* Sequence number */
- dtlsData[0] = MSB(ss->ssl3.hs.recvMessageSeq);
- dtlsData[1] = LSB(ss->ssl3.hs.recvMessageSeq);
-
- /* Fragment offset */
- dtlsData[2] = 0;
- dtlsData[3] = 0;
- dtlsData[4] = 0;
-
- /* Fragment length */
- dtlsData[5] = (PRUint8)(length >> 16);
- dtlsData[6] = (PRUint8)(length >> 8);
- dtlsData[7] = (PRUint8)(length );
+ (ss->ssl3.hs.msg_type != hello_verify_request)) {
+ rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *)hdr, 4);
+ if (rv != SECSuccess)
+ return rv; /* err code already set. */
- rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char*) dtlsData,
- sizeof(dtlsData));
- if (rv != SECSuccess) return rv; /* err code already set. */
- }
+ /* Extra data to simulate a complete DTLS handshake fragment */
+ if (IS_DTLS(ss)) {
+ /* Sequence number */
+ dtlsData[0] = MSB(ss->ssl3.hs.recvMessageSeq);
+ dtlsData[1] = LSB(ss->ssl3.hs.recvMessageSeq);
+
+ /* Fragment offset */
+ dtlsData[2] = 0;
+ dtlsData[3] = 0;
+ dtlsData[4] = 0;
+
+ /* Fragment length */
+ dtlsData[5] = (PRUint8)(length >> 16);
+ dtlsData[6] = (PRUint8)(length >> 8);
+ dtlsData[7] = (PRUint8)(length);
+
+ rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *)dtlsData,
+ sizeof(dtlsData));
+ if (rv != SECSuccess)
+ return rv; /* err code already set. */
+ }
- /* The message body */
- rv = ssl3_UpdateHandshakeHashes(ss, b, length);
- if (rv != SECSuccess) return rv; /* err code already set. */
+ /* The message body */
+ rv = ssl3_UpdateHandshakeHashes(ss, b, length);
+ if (rv != SECSuccess)
+ return rv; /* err code already set. */
}
- PORT_SetError(0); /* each message starts with no error. */
+ PORT_SetError(0); /* each message starts with no error. */
if (ss->ssl3.hs.ws == wait_certificate_status &&
ss->ssl3.hs.msg_type != certificate_status) {
@@ -12178,114 +12539,134 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
}
switch (ss->ssl3.hs.msg_type) {
- case hello_request:
- if (length != 0) {
- (void)ssl3_DecodeError(ss);
- PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST);
- return SECFailure;
- }
- if (ss->sec.isServer) {
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST);
- return SECFailure;
- }
- rv = ssl3_HandleHelloRequest(ss);
- break;
- case client_hello:
- if (!ss->sec.isServer) {
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO);
- return SECFailure;
- }
- rv = ssl3_HandleClientHello(ss, b, length);
- break;
- case server_hello:
- if (ss->sec.isServer) {
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO);
- return SECFailure;
- }
- rv = ssl3_HandleServerHello(ss, b, length);
- break;
- case hello_verify_request:
- if (!IS_DTLS(ss) || ss->sec.isServer) {
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST);
- return SECFailure;
- }
- rv = dtls_HandleHelloVerifyRequest(ss, b, length);
- break;
- case certificate:
- rv = ssl3_HandleCertificate(ss, b, length);
- break;
- case certificate_status:
- rv = ssl3_HandleCertificateStatus(ss, b, length);
- break;
- case server_key_exchange:
- if (ss->sec.isServer) {
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH);
- return SECFailure;
- }
- rv = ssl3_HandleServerKeyExchange(ss, b, length);
- break;
- case certificate_request:
- if (ss->sec.isServer) {
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST);
- return SECFailure;
- }
- rv = ssl3_HandleCertificateRequest(ss, b, length);
- break;
- case server_hello_done:
- if (length != 0) {
- (void)ssl3_DecodeError(ss);
- PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_DONE);
- return SECFailure;
- }
- if (ss->sec.isServer) {
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
- return SECFailure;
- }
- rv = ssl3_HandleServerHelloDone(ss);
- break;
- case certificate_verify:
- if (!ss->sec.isServer) {
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY);
- return SECFailure;
- }
- rv = ssl3_HandleCertificateVerify(ss, b, length, hashesPtr);
- break;
- case client_key_exchange:
- if (!ss->sec.isServer) {
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH);
- return SECFailure;
- }
- rv = ssl3_HandleClientKeyExchange(ss, b, length);
- break;
- case new_session_ticket:
- if (ss->sec.isServer) {
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET);
- return SECFailure;
- }
- rv = ssl3_HandleNewSessionTicket(ss, b, length);
- break;
- case finished:
- rv = ssl3_HandleFinished(ss, b, length, hashesPtr);
- break;
- default:
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNKNOWN_HANDSHAKE);
- rv = SECFailure;
+ case client_hello:
+ if (!ss->sec.isServer) {
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO);
+ return SECFailure;
+ }
+ rv = ssl3_HandleClientHello(ss, b, length);
+ break;
+ case server_hello:
+ if (ss->sec.isServer) {
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO);
+ return SECFailure;
+ }
+ rv = ssl3_HandleServerHello(ss, b, length);
+ break;
+ default:
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ rv = ssl3_HandlePostHelloHandshakeMessage(ss, b, length, hashesPtr);
+ } else {
+ rv = tls13_HandlePostHelloHandshakeMessage(ss, b, length,
+ hashesPtr);
+ }
+ break;
}
if (IS_DTLS(ss) && (rv != SECFailure)) {
- /* Increment the expected sequence number */
- ss->ssl3.hs.recvMessageSeq++;
+ /* Increment the expected sequence number */
+ ss->ssl3.hs.recvMessageSeq++;
+ }
+ return rv;
+}
+
+static SECStatus
+ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
+ PRUint32 length, SSL3Hashes *hashesPtr)
+{
+ SECStatus rv;
+ PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3);
+
+ switch (ss->ssl3.hs.msg_type) {
+ case hello_request:
+ if (length != 0) {
+ (void)ssl3_DecodeError(ss);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST);
+ return SECFailure;
+ }
+ if (ss->sec.isServer) {
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST);
+ return SECFailure;
+ }
+ rv = ssl3_HandleHelloRequest(ss);
+ break;
+ case hello_verify_request:
+ if (!IS_DTLS(ss) || ss->sec.isServer) {
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST);
+ return SECFailure;
+ }
+ rv = dtls_HandleHelloVerifyRequest(ss, b, length);
+ break;
+ case certificate:
+ rv = ssl3_HandleCertificate(ss, b, length);
+ break;
+ case certificate_status:
+ rv = ssl3_HandleCertificateStatus(ss, b, length);
+ break;
+ case server_key_exchange:
+ if (ss->sec.isServer) {
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH);
+ return SECFailure;
+ }
+ rv = ssl3_HandleServerKeyExchange(ss, b, length);
+ break;
+ case certificate_request:
+ if (ss->sec.isServer) {
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST);
+ return SECFailure;
+ }
+ rv = ssl3_HandleCertificateRequest(ss, b, length);
+ break;
+ case server_hello_done:
+ if (length != 0) {
+ (void)ssl3_DecodeError(ss);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_DONE);
+ return SECFailure;
+ }
+ if (ss->sec.isServer) {
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
+ return SECFailure;
+ }
+ rv = ssl3_HandleServerHelloDone(ss);
+ break;
+ case certificate_verify:
+ if (!ss->sec.isServer) {
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY);
+ return SECFailure;
+ }
+ rv = ssl3_HandleCertificateVerify(ss, b, length, hashesPtr);
+ break;
+ case client_key_exchange:
+ if (!ss->sec.isServer) {
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH);
+ return SECFailure;
+ }
+ rv = ssl3_HandleClientKeyExchange(ss, b, length);
+ break;
+ case new_session_ticket:
+ if (ss->sec.isServer) {
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET);
+ return SECFailure;
+ }
+ rv = ssl3_HandleNewSessionTicket(ss, b, length);
+ break;
+ case finished:
+ rv = ssl3_HandleFinished(ss, b, length, hashesPtr);
+ break;
+ default:
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNKNOWN_HANDSHAKE);
+ rv = SECFailure;
}
return rv;
@@ -12309,109 +12690,109 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
sslBuffer *buf = &ss->ssl3.hs.msgState; /* do not lose the original buffer pointer */
SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (buf->buf == NULL) {
- *buf = *origBuf;
+ *buf = *origBuf;
}
while (buf->len > 0) {
- if (ss->ssl3.hs.header_bytes < 4) {
- PRUint8 t;
- t = *(buf->buf++);
- buf->len--;
- if (ss->ssl3.hs.header_bytes++ == 0)
- ss->ssl3.hs.msg_type = (SSL3HandshakeType)t;
- else
- ss->ssl3.hs.msg_len = (ss->ssl3.hs.msg_len << 8) + t;
- if (ss->ssl3.hs.header_bytes < 4)
- continue;
-
-#define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */
- if (ss->ssl3.hs.msg_len > MAX_HANDSHAKE_MSG_LEN) {
- (void)ssl3_DecodeError(ss);
- PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
- return SECFailure;
- }
+ if (ss->ssl3.hs.header_bytes < 4) {
+ PRUint8 t;
+ t = *(buf->buf++);
+ buf->len--;
+ if (ss->ssl3.hs.header_bytes++ == 0)
+ ss->ssl3.hs.msg_type = (SSL3HandshakeType)t;
+ else
+ ss->ssl3.hs.msg_len = (ss->ssl3.hs.msg_len << 8) + t;
+ if (ss->ssl3.hs.header_bytes < 4)
+ continue;
+
+#define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */
+ if (ss->ssl3.hs.msg_len > MAX_HANDSHAKE_MSG_LEN) {
+ (void)ssl3_DecodeError(ss);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
+ return SECFailure;
+ }
#undef MAX_HANDSHAKE_MSG_LEN
- /* If msg_len is zero, be sure we fall through,
- ** even if buf->len is zero.
- */
- if (ss->ssl3.hs.msg_len > 0)
- continue;
- }
-
- /*
- * Header has been gathered and there is at least one byte of new
- * data available for this message. If it can be done right out
- * of the original buffer, then use it from there.
- */
- if (ss->ssl3.hs.msg_body.len == 0 && buf->len >= ss->ssl3.hs.msg_len) {
- /* handle it from input buffer */
- rv = ssl3_HandleHandshakeMessage(ss, buf->buf, ss->ssl3.hs.msg_len);
- if (rv == SECFailure) {
- /* This test wants to fall through on either
- * SECSuccess or SECWouldBlock.
- * ssl3_HandleHandshakeMessage MUST set the error code.
- */
- return rv;
- }
- buf->buf += ss->ssl3.hs.msg_len;
- buf->len -= ss->ssl3.hs.msg_len;
- ss->ssl3.hs.msg_len = 0;
- ss->ssl3.hs.header_bytes = 0;
- if (rv != SECSuccess) { /* return if SECWouldBlock. */
- return rv;
- }
- } else {
- /* must be copied to msg_body and dealt with from there */
- unsigned int bytes;
-
- PORT_Assert(ss->ssl3.hs.msg_body.len < ss->ssl3.hs.msg_len);
- bytes = PR_MIN(buf->len, ss->ssl3.hs.msg_len - ss->ssl3.hs.msg_body.len);
-
- /* Grow the buffer if needed */
- rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, ss->ssl3.hs.msg_len);
- if (rv != SECSuccess) {
- /* sslBuffer_Grow has set a memory error code. */
- return SECFailure;
- }
-
- PORT_Memcpy(ss->ssl3.hs.msg_body.buf + ss->ssl3.hs.msg_body.len,
- buf->buf, bytes);
- ss->ssl3.hs.msg_body.len += bytes;
- buf->buf += bytes;
- buf->len -= bytes;
-
- PORT_Assert(ss->ssl3.hs.msg_body.len <= ss->ssl3.hs.msg_len);
-
- /* if we have a whole message, do it */
- if (ss->ssl3.hs.msg_body.len == ss->ssl3.hs.msg_len) {
- rv = ssl3_HandleHandshakeMessage(
- ss, ss->ssl3.hs.msg_body.buf, ss->ssl3.hs.msg_len);
- if (rv == SECFailure) {
- /* This test wants to fall through on either
- * SECSuccess or SECWouldBlock.
- * ssl3_HandleHandshakeMessage MUST set error code.
- */
- return rv;
- }
- ss->ssl3.hs.msg_body.len = 0;
- ss->ssl3.hs.msg_len = 0;
- ss->ssl3.hs.header_bytes = 0;
- if (rv != SECSuccess) { /* return if SECWouldBlock. */
- return rv;
- }
- } else {
- PORT_Assert(buf->len == 0);
- break;
- }
- }
- } /* end loop */
-
- origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
- buf->buf = NULL; /* not a leak. */
+ /* If msg_len is zero, be sure we fall through,
+ ** even if buf->len is zero.
+ */
+ if (ss->ssl3.hs.msg_len > 0)
+ continue;
+ }
+
+ /*
+ * Header has been gathered and there is at least one byte of new
+ * data available for this message. If it can be done right out
+ * of the original buffer, then use it from there.
+ */
+ if (ss->ssl3.hs.msg_body.len == 0 && buf->len >= ss->ssl3.hs.msg_len) {
+ /* handle it from input buffer */
+ rv = ssl3_HandleHandshakeMessage(ss, buf->buf, ss->ssl3.hs.msg_len);
+ if (rv == SECFailure) {
+ /* This test wants to fall through on either
+ * SECSuccess or SECWouldBlock.
+ * ssl3_HandleHandshakeMessage MUST set the error code.
+ */
+ return rv;
+ }
+ buf->buf += ss->ssl3.hs.msg_len;
+ buf->len -= ss->ssl3.hs.msg_len;
+ ss->ssl3.hs.msg_len = 0;
+ ss->ssl3.hs.header_bytes = 0;
+ if (rv != SECSuccess) { /* return if SECWouldBlock. */
+ return rv;
+ }
+ } else {
+ /* must be copied to msg_body and dealt with from there */
+ unsigned int bytes;
+
+ PORT_Assert(ss->ssl3.hs.msg_body.len < ss->ssl3.hs.msg_len);
+ bytes = PR_MIN(buf->len, ss->ssl3.hs.msg_len - ss->ssl3.hs.msg_body.len);
+
+ /* Grow the buffer if needed */
+ rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, ss->ssl3.hs.msg_len);
+ if (rv != SECSuccess) {
+ /* sslBuffer_Grow has set a memory error code. */
+ return SECFailure;
+ }
+
+ PORT_Memcpy(ss->ssl3.hs.msg_body.buf + ss->ssl3.hs.msg_body.len,
+ buf->buf, bytes);
+ ss->ssl3.hs.msg_body.len += bytes;
+ buf->buf += bytes;
+ buf->len -= bytes;
+
+ PORT_Assert(ss->ssl3.hs.msg_body.len <= ss->ssl3.hs.msg_len);
+
+ /* if we have a whole message, do it */
+ if (ss->ssl3.hs.msg_body.len == ss->ssl3.hs.msg_len) {
+ rv = ssl3_HandleHandshakeMessage(
+ ss, ss->ssl3.hs.msg_body.buf, ss->ssl3.hs.msg_len);
+ if (rv == SECFailure) {
+ /* This test wants to fall through on either
+ * SECSuccess or SECWouldBlock.
+ * ssl3_HandleHandshakeMessage MUST set error code.
+ */
+ return rv;
+ }
+ ss->ssl3.hs.msg_body.len = 0;
+ ss->ssl3.hs.msg_len = 0;
+ ss->ssl3.hs.header_bytes = 0;
+ if (rv != SECSuccess) { /* return if SECWouldBlock. */
+ return rv;
+ }
+ } else {
+ PORT_Assert(buf->len == 0);
+ break;
+ }
+ }
+ } /* end loop */
+
+ origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
+ buf->buf = NULL; /* not a leak. */
return SECSuccess;
}
@@ -12419,7 +12800,7 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
* bits. They use the fact that arithmetic shift shifts-in the sign bit.
* However, this is not ensured by the C standard so you may need to replace
* them with something else for odd compilers. */
-#define DUPLICATE_MSB_TO_ALL(x) ( (unsigned)( (int)(x) >> (sizeof(int)*8-1) ) )
+#define DUPLICATE_MSB_TO_ALL(x) ((unsigned)((int)(x) >> (sizeof(int) * 8 - 1)))
#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x)))
/* SECStatusToMask returns, in constant time, a mask value of all ones if
@@ -12454,8 +12835,8 @@ ssl_ConstantTimeEQ8(unsigned char a, unsigned char b)
static SECStatus
ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext,
- unsigned int blockSize,
- unsigned int macSize)
+ unsigned int blockSize,
+ unsigned int macSize)
{
unsigned int paddingLength, good, t;
const unsigned int overhead = 1 /* padding length byte */ + macSize;
@@ -12463,19 +12844,19 @@ ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext,
/* These lengths are all public so we can test them in non-constant
* time. */
if (overhead > plaintext->len) {
- return SECFailure;
+ return SECFailure;
}
- paddingLength = plaintext->buf[plaintext->len-1];
+ paddingLength = plaintext->buf[plaintext->len - 1];
/* SSLv3 padding bytes are random and cannot be checked. */
t = plaintext->len;
- t -= paddingLength+overhead;
+ t -= paddingLength + overhead;
/* If len >= paddingLength+overhead then the MSB of t is zero. */
good = DUPLICATE_MSB_TO_ALL(~t);
/* SSLv3 requires that the padding is minimal. */
- t = blockSize - (paddingLength+1);
+ t = blockSize - (paddingLength + 1);
good &= DUPLICATE_MSB_TO_ALL(~t);
- plaintext->len -= good & (paddingLength+1);
+ plaintext->len -= good & (paddingLength + 1);
return (good & SECSuccess) | (~good & SECFailure);
}
@@ -12488,12 +12869,12 @@ ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize)
/* These lengths are all public so we can test them in non-constant
* time. */
if (overhead > plaintext->len) {
- return SECFailure;
+ return SECFailure;
}
- paddingLength = plaintext->buf[plaintext->len-1];
+ paddingLength = plaintext->buf[plaintext->len - 1];
t = plaintext->len;
- t -= paddingLength+overhead;
+ t -= paddingLength + overhead;
/* If len >= paddingLength+overhead then the MSB of t is zero. */
good = DUPLICATE_MSB_TO_ALL(~t);
@@ -12507,19 +12888,19 @@ ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize)
* amount of padding possible. (Again, the length of the record is
* public information so we can use it.) */
toCheck = 255; /* maximum amount of padding. */
- if (toCheck > plaintext->len-1) {
- toCheck = plaintext->len-1;
+ if (toCheck > plaintext->len - 1) {
+ toCheck = plaintext->len - 1;
}
for (i = 0; i < toCheck; i++) {
- unsigned int t = paddingLength - i;
- /* If i <= paddingLength then the MSB of t is zero and mask is
- * 0xff. Otherwise, mask is 0. */
- unsigned char mask = DUPLICATE_MSB_TO_ALL(~t);
- unsigned char b = plaintext->buf[plaintext->len-1-i];
- /* The final |paddingLength+1| bytes should all have the value
- * |paddingLength|. Therefore the XOR should be zero. */
- good &= ~(mask&(paddingLength ^ b));
+ unsigned int t = paddingLength - i;
+ /* If i <= paddingLength then the MSB of t is zero and mask is
+ * 0xff. Otherwise, mask is 0. */
+ unsigned char mask = DUPLICATE_MSB_TO_ALL(~t);
+ unsigned char b = plaintext->buf[plaintext->len - 1 - i];
+ /* The final |paddingLength+1| bytes should all have the value
+ * |paddingLength|. Therefore the XOR should be zero. */
+ good &= ~(mask & (paddingLength ^ b));
}
/* If any of the final |paddingLength+1| bytes had the wrong value,
@@ -12529,10 +12910,10 @@ ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize)
good &= good >> 4;
good &= good >> 2;
good &= good >> 1;
- good <<= sizeof(good)*8-1;
+ good <<= sizeof(good) * 8 - 1;
good = DUPLICATE_MSB_TO_ALL(good);
- plaintext->len -= good & (paddingLength+1);
+ plaintext->len -= good & (paddingLength + 1);
return (good & SECSuccess) | (~good & SECFailure);
}
@@ -12543,9 +12924,9 @@ ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize)
*/
static void
ssl_CBCExtractMAC(sslBuffer *plaintext,
- unsigned int originalLength,
- SSL3Opaque* out,
- unsigned int macSize)
+ unsigned int originalLength,
+ SSL3Opaque *out,
+ unsigned int macSize)
{
unsigned char rotatedMac[MAX_MAC_LENGTH];
/* macEnd is the index of |plaintext->buf| just after the end of the
@@ -12559,7 +12940,7 @@ ssl_CBCExtractMAC(sslBuffer *plaintext,
unsigned char rotateOffset;
if (originalLength > macSize + 255 + 1)
- scanStart = originalLength - (macSize + 255 + 1);
+ scanStart = originalLength - (macSize + 255 + 1);
/* divSpoiler contains a multiple of macSize that is used to cause the
* modulo operation to be constant time. Without this, the time varies
@@ -12569,30 +12950,230 @@ ssl_CBCExtractMAC(sslBuffer *plaintext,
* figure out that it can remove divSpoiler as that would require it
* to prove that macSize is always even, which I hope is beyond it. */
divSpoiler = macSize >> 1;
- divSpoiler <<= (sizeof(divSpoiler)-1)*8;
+ divSpoiler <<= (sizeof(divSpoiler) - 1) * 8;
rotateOffset = (divSpoiler + macStart - scanStart) % macSize;
memset(rotatedMac, 0, macSize);
for (i = scanStart; i < originalLength;) {
- for (j = 0; j < macSize && i < originalLength; i++, j++) {
- unsigned char macStarted = ssl_ConstantTimeGE(i, macStart);
- unsigned char macEnded = ssl_ConstantTimeGE(i, macEnd);
- unsigned char b = 0;
- b = plaintext->buf[i];
- rotatedMac[j] |= b & macStarted & ~macEnded;
- }
+ for (j = 0; j < macSize && i < originalLength; i++, j++) {
+ unsigned char macStarted = ssl_ConstantTimeGE(i, macStart);
+ unsigned char macEnded = ssl_ConstantTimeGE(i, macEnd);
+ unsigned char b = 0;
+ b = plaintext->buf[i];
+ rotatedMac[j] |= b & macStarted & ~macEnded;
+ }
}
/* Now rotate the MAC. If we knew that the MAC fit into a CPU cache line
* we could line-align |rotatedMac| and rotate in place. */
memset(out, 0, macSize);
for (i = 0; i < macSize; i++) {
- unsigned char offset =
- (divSpoiler + macSize - rotateOffset + i) % macSize;
- for (j = 0; j < macSize; j++) {
- out[j] |= rotatedMac[i] & ssl_ConstantTimeEQ8(j, offset);
- }
+ unsigned char offset =
+ (divSpoiler + macSize - rotateOffset + i) % macSize;
+ for (j = 0; j < macSize; j++) {
+ out[j] |= rotatedMac[i] & ssl_ConstantTimeEQ8(j, offset);
+ }
+ }
+}
+
+/* Unprotect an SSL3 record and leave the result in plaintext.
+ *
+ * If SECFailure is returned, we:
+ * 1. Set |*alert| to the alert to be sent.
+ * 2. Call PORT_SetError() with an appropriate code.
+ *
+ * Called by ssl3_HandleRecord. Caller must hold the spec read lock.
+ * Therefore, we MUST not call SSL3_SendAlert().
+ *
+ */
+static SECStatus
+ssl3_UnprotectRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *plaintext,
+ SSL3AlertDescription *alert)
+{
+ ssl3CipherSpec *crSpec = ss->ssl3.crSpec;
+ const ssl3BulkCipherDef *cipher_def = crSpec->cipher_def;
+ PRBool isTLS;
+ unsigned int good;
+ unsigned int ivLen = 0;
+ SSL3ContentType rType;
+ unsigned int minLength;
+ unsigned int originalLen = 0;
+ unsigned char header[13];
+ unsigned int headerLen;
+ SSL3Opaque hash[MAX_MAC_LENGTH];
+ SSL3Opaque givenHashBuf[MAX_MAC_LENGTH];
+ SSL3Opaque *givenHash;
+ unsigned int hashBytes = MAX_MAC_LENGTH + 1;
+ SECStatus rv;
+
+ good = ~0U;
+ minLength = crSpec->mac_size;
+ if (cipher_def->type == type_block) {
+ /* CBC records have a padding length byte at the end. */
+ minLength++;
+ if (crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
+ /* With >= TLS 1.1, CBC records have an explicit IV. */
+ minLength += cipher_def->iv_size;
+ }
+ } else if (cipher_def->type == type_aead) {
+ minLength = cipher_def->explicit_nonce_size + cipher_def->tag_size;
+ }
+
+ /* We can perform this test in variable time because the record's total
+ * length and the ciphersuite are both public knowledge. */
+ if (cText->buf->len < minLength) {
+ goto decrypt_loser;
+ }
+
+ if (cipher_def->type == type_block &&
+ crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
+ /* Consume the per-record explicit IV. RFC 4346 Section 6.2.3.2 states
+ * "The receiver decrypts the entire GenericBlockCipher structure and
+ * then discards the first cipher block corresponding to the IV
+ * component." Instead, we decrypt the first cipher block and then
+ * discard it before decrypting the rest.
+ */
+ SSL3Opaque iv[MAX_IV_LENGTH];
+ int decoded;
+
+ ivLen = cipher_def->iv_size;
+ if (ivLen < 8 || ivLen > sizeof(iv)) {
+ *alert = internal_error;
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
+ PRINT_BUF(80, (ss, "IV (ciphertext):", cText->buf->buf, ivLen));
+
+ /* The decryption result is garbage, but since we just throw away
+ * the block it doesn't matter. The decryption of the next block
+ * depends only on the ciphertext of the IV block.
+ */
+ rv = crSpec->decode(crSpec->decodeContext, iv, &decoded,
+ sizeof(iv), cText->buf->buf, ivLen);
+
+ good &= SECStatusToMask(rv);
+ }
+
+ PRINT_BUF(80, (ss, "ciphertext:", cText->buf->buf + ivLen,
+ cText->buf->len - ivLen));
+
+ isTLS = (PRBool)(crSpec->version > SSL_LIBRARY_VERSION_3_0);
+
+ if (isTLS && cText->buf->len - ivLen > (MAX_FRAGMENT_LENGTH + 2048)) {
+ *alert = record_overflow;
+ PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
+ return SECFailure;
+ }
+
+ rType = cText->type;
+ if (cipher_def->type == type_aead) {
+ /* XXX For many AEAD ciphers, the plaintext is shorter than the
+ * ciphertext by a fixed byte count, but it is not true in general.
+ * Each AEAD cipher should provide a function that returns the
+ * plaintext length for a given ciphertext. */
+ unsigned int decryptedLen =
+ cText->buf->len - cipher_def->explicit_nonce_size -
+ cipher_def->tag_size;
+ headerLen = ssl3_BuildRecordPseudoHeader(
+ header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
+ rType, isTLS, cText->version, IS_DTLS(ss), decryptedLen);
+ PORT_Assert(headerLen <= sizeof(header));
+ rv = crSpec->aead(
+ ss->sec.isServer ? &crSpec->client : &crSpec->server,
+ PR_TRUE, /* do decrypt */
+ plaintext->buf, /* out */
+ (int *)&plaintext->len, /* outlen */
+ plaintext->space, /* maxout */
+ cText->buf->buf, /* in */
+ cText->buf->len, /* inlen */
+ header, headerLen);
+ if (rv != SECSuccess) {
+ good = 0;
+ }
+ } else {
+ if (cipher_def->type == type_block &&
+ ((cText->buf->len - ivLen) % cipher_def->block_size) != 0) {
+ goto decrypt_loser;
+ }
+
+ /* decrypt from cText buf to plaintext. */
+ rv = crSpec->decode(
+ crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len,
+ plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen);
+ if (rv != SECSuccess) {
+ goto decrypt_loser;
+ }
+
+ PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len));
+
+ originalLen = plaintext->len;
+
+ /* If it's a block cipher, check and strip the padding. */
+ if (cipher_def->type == type_block) {
+ const unsigned int blockSize = cipher_def->block_size;
+ const unsigned int macSize = crSpec->mac_size;
+
+ if (!isTLS) {
+ good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding(
+ plaintext, blockSize, macSize));
+ } else {
+ good &= SECStatusToMask(ssl_RemoveTLSCBCPadding(
+ plaintext, macSize));
+ }
+ }
+
+ /* compute the MAC */
+ headerLen = ssl3_BuildRecordPseudoHeader(
+ header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
+ rType, isTLS, cText->version, IS_DTLS(ss),
+ plaintext->len - crSpec->mac_size);
+ PORT_Assert(headerLen <= sizeof(header));
+ if (cipher_def->type == type_block) {
+ rv = ssl3_ComputeRecordMACConstantTime(
+ crSpec, (PRBool)(!ss->sec.isServer), header, headerLen,
+ plaintext->buf, plaintext->len, originalLen,
+ hash, &hashBytes);
+
+ ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf,
+ crSpec->mac_size);
+ givenHash = givenHashBuf;
+
+ /* plaintext->len will always have enough space to remove the MAC
+ * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust
+ * plaintext->len if the result has enough space for the MAC and we
+ * tested the unadjusted size against minLength, above. */
+ plaintext->len -= crSpec->mac_size;
+ } else {
+ /* This is safe because we checked the minLength above. */
+ plaintext->len -= crSpec->mac_size;
+
+ rv = ssl3_ComputeRecordMAC(
+ crSpec, (PRBool)(!ss->sec.isServer), header, headerLen,
+ plaintext->buf, plaintext->len, hash, &hashBytes);
+
+ /* We can read the MAC directly from the record because its location
+ * is public when a stream cipher is used. */
+ givenHash = plaintext->buf + plaintext->len;
+ }
+
+ good &= SECStatusToMask(rv);
+
+ if (hashBytes != (unsigned)crSpec->mac_size ||
+ NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) {
+ /* We're allowed to leak whether or not the MAC check was correct */
+ good = 0;
+ }
}
+
+ if (good == 0) {
+ decrypt_loser:
+ /* always log mac error, in case attacker can read server logs. */
+ PORT_SetError(SSL_ERROR_BAD_MAC_READ);
+ *alert = bad_record_mac;
+ return SECFailure;
+ }
+ return SECSuccess;
}
/* if cText is non-null, then decipher, check MAC, and decompress the
@@ -12620,40 +13201,29 @@ ssl_CBCExtractMAC(sslBuffer *plaintext,
SECStatus
ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
{
- const ssl3BulkCipherDef *cipher_def;
- ssl3CipherSpec * crSpec;
- SECStatus rv;
- unsigned int hashBytes = MAX_MAC_LENGTH + 1;
- PRBool isTLS;
- SSL3ContentType rType;
- SSL3Opaque hash[MAX_MAC_LENGTH];
- SSL3Opaque givenHashBuf[MAX_MAC_LENGTH];
- SSL3Opaque *givenHash;
- sslBuffer *plaintext;
- sslBuffer temp_buf;
- PRUint64 dtls_seq_num = 0;
- unsigned int ivLen = 0;
- unsigned int originalLen = 0;
- unsigned int good;
- unsigned int minLength;
- unsigned char header[13];
- unsigned int headerLen;
-
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ SECStatus rv;
+ PRBool isTLS;
+ PRUint64 dtls_seq_num = 0;
+ ssl3CipherSpec *crSpec;
+ SSL3ContentType rType;
+ sslBuffer *plaintext;
+ sslBuffer temp_buf;
+ SSL3AlertDescription alert;
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
if (!ss->ssl3.initialized) {
- ssl_GetSSL3HandshakeLock(ss);
- rv = ssl3_InitState(ss);
- ssl_ReleaseSSL3HandshakeLock(ss);
- if (rv != SECSuccess) {
- return rv; /* ssl3_InitState has set the error code. */
- }
+ ssl_GetSSL3HandshakeLock(ss);
+ rv = ssl3_InitState(ss);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ if (rv != SECSuccess) {
+ return rv; /* ssl3_InitState has set the error code. */
+ }
}
/* check for Token Presence */
if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) {
- PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
+ return SECFailure;
}
/* cText is NULL when we're called from ssl3_RestartHandshakeAfterXXX().
@@ -12661,257 +13231,83 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
* message.
*/
if (cText == NULL) {
- SSL_DBG(("%d: SSL3[%d]: HandleRecord, resuming handshake",
- SSL_GETPID(), ss->fd));
- rType = content_handshake;
- goto process_it;
+ SSL_DBG(("%d: SSL3[%d]: HandleRecord, resuming handshake",
+ SSL_GETPID(), ss->fd));
+ rType = content_handshake;
+ goto process_it;
}
ssl_GetSpecReadLock(ss); /******************************************/
-
crSpec = ss->ssl3.crSpec;
- cipher_def = crSpec->cipher_def;
-
- /*
- * DTLS relevance checks:
- * Note that this code currently ignores all out-of-epoch packets,
- * which means we lose some in the case of rehandshake +
- * loss/reordering. Since DTLS is explicitly unreliable, this
- * seems like a good tradeoff for implementation effort and is
- * consistent with the guidance of RFC 6347 Sections 4.1 and 4.2.4.1
- */
- if (IS_DTLS(ss)) {
- DTLSEpoch epoch = (cText->seq_num.high >> 16) & 0xffff;
-
- if (crSpec->epoch != epoch) {
- ssl_ReleaseSpecReadLock(ss);
- SSL_DBG(("%d: SSL3[%d]: HandleRecord, received packet "
- "from irrelevant epoch %d", SSL_GETPID(), ss->fd, epoch));
- /* Silently drop the packet */
- databuf->len = 0; /* Needed to ensure data not left around */
- return SECSuccess;
- }
-
- dtls_seq_num = (((PRUint64)(cText->seq_num.high & 0xffff)) << 32) |
- ((PRUint64)cText->seq_num.low);
+ isTLS = (PRBool)(crSpec->version > SSL_LIBRARY_VERSION_3_0);
- if (dtls_RecordGetRecvd(&crSpec->recvdRecords, dtls_seq_num) != 0) {
- ssl_ReleaseSpecReadLock(ss);
- SSL_DBG(("%d: SSL3[%d]: HandleRecord, rejecting "
- "potentially replayed packet", SSL_GETPID(), ss->fd));
- /* Silently drop the packet */
+ if (IS_DTLS(ss)) {
+ if (!dtls_IsRelevant(ss, crSpec, cText, &dtls_seq_num)) {
+ ssl_ReleaseSpecReadLock(ss);
+ /* Silently drop the packet */
databuf->len = 0; /* Needed to ensure data not left around */
- return SECSuccess;
- }
- }
-
- good = ~0U;
- minLength = crSpec->mac_size;
- if (cipher_def->type == type_block) {
- /* CBC records have a padding length byte at the end. */
- minLength++;
- if (crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
- /* With >= TLS 1.1, CBC records have an explicit IV. */
- minLength += cipher_def->iv_size;
- }
- } else if (cipher_def->type == type_aead) {
- minLength = cipher_def->explicit_nonce_size + cipher_def->tag_size;
- }
-
- /* We can perform this test in variable time because the record's total
- * length and the ciphersuite are both public knowledge. */
- if (cText->buf->len < minLength) {
- goto decrypt_loser;
- }
-
- if (cipher_def->type == type_block &&
- crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
- /* Consume the per-record explicit IV. RFC 4346 Section 6.2.3.2 states
- * "The receiver decrypts the entire GenericBlockCipher structure and
- * then discards the first cipher block corresponding to the IV
- * component." Instead, we decrypt the first cipher block and then
- * discard it before decrypting the rest.
- */
- SSL3Opaque iv[MAX_IV_LENGTH];
- int decoded;
-
- ivLen = cipher_def->iv_size;
- if (ivLen < 8 || ivLen > sizeof(iv)) {
- ssl_ReleaseSpecReadLock(ss);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
- }
-
- PRINT_BUF(80, (ss, "IV (ciphertext):", cText->buf->buf, ivLen));
-
- /* The decryption result is garbage, but since we just throw away
- * the block it doesn't matter. The decryption of the next block
- * depends only on the ciphertext of the IV block.
- */
- rv = crSpec->decode(crSpec->decodeContext, iv, &decoded,
- sizeof(iv), cText->buf->buf, ivLen);
-
- good &= SECStatusToMask(rv);
+ return SECSuccess;
+ }
}
/* If we will be decompressing the buffer we need to decrypt somewhere
* other than into databuf */
if (crSpec->decompressor) {
- temp_buf.buf = NULL;
- temp_buf.space = 0;
- plaintext = &temp_buf;
+ temp_buf.buf = NULL;
+ temp_buf.space = 0;
+ plaintext = &temp_buf;
} else {
- plaintext = databuf;
+ plaintext = databuf;
}
- plaintext->len = 0; /* filled in by decode call below. */
+ plaintext->len = 0; /* filled in by Unprotect call below. */
if (plaintext->space < MAX_FRAGMENT_LENGTH) {
- rv = sslBuffer_Grow(plaintext, MAX_FRAGMENT_LENGTH + 2048);
- if (rv != SECSuccess) {
- ssl_ReleaseSpecReadLock(ss);
- SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes",
- SSL_GETPID(), ss->fd, MAX_FRAGMENT_LENGTH + 2048));
- /* sslBuffer_Grow has set a memory error code. */
- /* Perhaps we should send an alert. (but we have no memory!) */
- return SECFailure;
- }
- }
-
- PRINT_BUF(80, (ss, "ciphertext:", cText->buf->buf + ivLen,
- cText->buf->len - ivLen));
-
- isTLS = (PRBool)(crSpec->version > SSL_LIBRARY_VERSION_3_0);
-
- if (isTLS && cText->buf->len - ivLen > (MAX_FRAGMENT_LENGTH + 2048)) {
- ssl_ReleaseSpecReadLock(ss);
- SSL3_SendAlert(ss, alert_fatal, record_overflow);
- PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
- return SECFailure;
+ rv = sslBuffer_Grow(plaintext, MAX_FRAGMENT_LENGTH + 2048);
+ if (rv != SECSuccess) {
+ ssl_ReleaseSpecReadLock(ss);
+ SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes",
+ SSL_GETPID(), ss->fd, MAX_FRAGMENT_LENGTH + 2048));
+ /* sslBuffer_Grow has set a memory error code. */
+ /* Perhaps we should send an alert. (but we have no memory!) */
+ return SECFailure;
+ }
}
- rType = cText->type;
- if (cipher_def->type == type_aead) {
- /* XXX For many AEAD ciphers, the plaintext is shorter than the
- * ciphertext by a fixed byte count, but it is not true in general.
- * Each AEAD cipher should provide a function that returns the
- * plaintext length for a given ciphertext. */
- unsigned int decryptedLen =
- cText->buf->len - cipher_def->explicit_nonce_size -
- cipher_def->tag_size;
- headerLen = ssl3_BuildRecordPseudoHeader(
- header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
- rType, isTLS, cText->version, IS_DTLS(ss), decryptedLen);
- PORT_Assert(headerLen <= sizeof(header));
- rv = crSpec->aead(
- ss->sec.isServer ? &crSpec->client : &crSpec->server,
- PR_TRUE, /* do decrypt */
- plaintext->buf, /* out */
- (int*) &plaintext->len, /* outlen */
- plaintext->space, /* maxout */
- cText->buf->buf, /* in */
- cText->buf->len, /* inlen */
- header, headerLen);
- if (rv != SECSuccess) {
- good = 0;
- }
+ /* IMPORTANT: Unprotect functions MUST NOT send alerts
+ * because we still hold the spec read lock. Instead, if they
+ * return SECFailure, they set *alert to the alert to be sent. */
+ if (crSpec->version < SSL_LIBRARY_VERSION_TLS_1_3 ||
+ crSpec->cipher_def->calg == ssl_calg_null) {
+ /* Unencrypted TLS 1.3 records use the pre-TLS 1.3 format. */
+ rv = ssl3_UnprotectRecord(ss, cText, plaintext, &alert);
} else {
- if (cipher_def->type == type_block &&
- ((cText->buf->len - ivLen) % cipher_def->block_size) != 0) {
- goto decrypt_loser;
- }
-
- /* decrypt from cText buf to plaintext. */
- rv = crSpec->decode(
- crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len,
- plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen);
- if (rv != SECSuccess) {
- goto decrypt_loser;
- }
-
- PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len));
-
- originalLen = plaintext->len;
-
- /* If it's a block cipher, check and strip the padding. */
- if (cipher_def->type == type_block) {
- const unsigned int blockSize = cipher_def->block_size;
- const unsigned int macSize = crSpec->mac_size;
-
- if (!isTLS) {
- good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding(
- plaintext, blockSize, macSize));
- } else {
- good &= SECStatusToMask(ssl_RemoveTLSCBCPadding(
- plaintext, macSize));
- }
- }
-
- /* compute the MAC */
- headerLen = ssl3_BuildRecordPseudoHeader(
- header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
- rType, isTLS, cText->version, IS_DTLS(ss),
- plaintext->len - crSpec->mac_size);
- PORT_Assert(headerLen <= sizeof(header));
- if (cipher_def->type == type_block) {
- rv = ssl3_ComputeRecordMACConstantTime(
- crSpec, (PRBool)(!ss->sec.isServer), header, headerLen,
- plaintext->buf, plaintext->len, originalLen,
- hash, &hashBytes);
-
- ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf,
- crSpec->mac_size);
- givenHash = givenHashBuf;
-
- /* plaintext->len will always have enough space to remove the MAC
- * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust
- * plaintext->len if the result has enough space for the MAC and we
- * tested the unadjusted size against minLength, above. */
- plaintext->len -= crSpec->mac_size;
- } else {
- /* This is safe because we checked the minLength above. */
- plaintext->len -= crSpec->mac_size;
-
- rv = ssl3_ComputeRecordMAC(
- crSpec, (PRBool)(!ss->sec.isServer), header, headerLen,
- plaintext->buf, plaintext->len, hash, &hashBytes);
-
- /* We can read the MAC directly from the record because its location
- * is public when a stream cipher is used. */
- givenHash = plaintext->buf + plaintext->len;
- }
-
- good &= SECStatusToMask(rv);
-
- if (hashBytes != (unsigned)crSpec->mac_size ||
- NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) {
- /* We're allowed to leak whether or not the MAC check was correct */
- good = 0;
- }
+ rv = tls13_UnprotectRecord(ss, cText, plaintext, &alert);
}
- if (good == 0) {
-decrypt_loser:
- /* must not hold spec lock when calling SSL3_SendAlert. */
- ssl_ReleaseSpecReadLock(ss);
-
- SSL_DBG(("%d: SSL3[%d]: decryption failed", SSL_GETPID(), ss->fd));
-
- if (!IS_DTLS(ss)) {
- SSL3_SendAlert(ss, alert_fatal, bad_record_mac);
- /* always log mac error, in case attacker can read server logs. */
- PORT_SetError(SSL_ERROR_BAD_MAC_READ);
- return SECFailure;
- } else {
- /* Silently drop the packet */
+ if (rv != SECSuccess) {
+ ssl_ReleaseSpecReadLock(ss);
+
+ SSL_DBG(("%d: SSL3[%d]: decryption failed", SSL_GETPID(), ss->fd));
+
+ if (!IS_DTLS(ss)) {
+ int errCode = PORT_GetError();
+ SSL3_SendAlert(ss, alert_fatal, alert);
+ /* Reset the error code in case SSL3_SendAlert called
+ * PORT_SetError(). */
+ PORT_SetError(errCode);
+ return SECFailure;
+ } else {
+ /* Silently drop the packet */
databuf->len = 0; /* Needed to ensure data not left around */
- return SECSuccess;
- }
+ return SECSuccess;
+ }
}
+ /* SECSuccess */
if (!IS_DTLS(ss)) {
- ssl3_BumpSequenceNumber(&crSpec->read_seq_num);
+ ssl3_BumpSequenceNumber(&crSpec->read_seq_num);
} else {
- dtls_RecordSetRecvd(&crSpec->recvdRecords, dtls_seq_num);
+ dtls_RecordSetRecvd(&crSpec->recvdRecords, dtls_seq_num);
}
ssl_ReleaseSpecReadLock(ss); /*****************************************/
@@ -12919,83 +13315,87 @@ decrypt_loser:
/*
* The decrypted data is now in plaintext.
*/
+ rType = cText->type; /* This must go after decryption because TLS 1.3
+ * has encrypted content types. */
/* possibly decompress the record. If we aren't using compression then
* plaintext == databuf and so the uncompressed data is already in
* databuf. */
if (crSpec->decompressor) {
- if (databuf->space < plaintext->len + SSL3_COMPRESSION_MAX_EXPANSION) {
- rv = sslBuffer_Grow(
- databuf, plaintext->len + SSL3_COMPRESSION_MAX_EXPANSION);
- if (rv != SECSuccess) {
- SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes",
- SSL_GETPID(), ss->fd,
- plaintext->len + SSL3_COMPRESSION_MAX_EXPANSION));
- /* sslBuffer_Grow has set a memory error code. */
- /* Perhaps we should send an alert. (but we have no memory!) */
- PORT_Free(plaintext->buf);
- return SECFailure;
- }
- }
-
- rv = crSpec->decompressor(crSpec->decompressContext,
- databuf->buf,
- (int*) &databuf->len,
- databuf->space,
- plaintext->buf,
- plaintext->len);
-
- if (rv != SECSuccess) {
- int err = ssl_MapLowLevelError(SSL_ERROR_DECOMPRESSION_FAILURE);
- SSL3_SendAlert(ss, alert_fatal,
- isTLS ? decompression_failure : bad_record_mac);
-
- /* There appears to be a bug with (at least) Apache + OpenSSL where
- * resumed SSLv3 connections don't actually use compression. See
- * comments 93-95 of
- * https://bugzilla.mozilla.org/show_bug.cgi?id=275744
- *
- * So, if we get a decompression error, and the record appears to
- * be already uncompressed, then we return a more specific error
- * code to hopefully save somebody some debugging time in the
- * future.
- */
- if (plaintext->len >= 4) {
- unsigned int len = ((unsigned int) plaintext->buf[1] << 16) |
- ((unsigned int) plaintext->buf[2] << 8) |
- (unsigned int) plaintext->buf[3];
- if (len == plaintext->len - 4) {
- /* This appears to be uncompressed already */
- err = SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD;
- }
- }
-
- PORT_Free(plaintext->buf);
- PORT_SetError(err);
- return SECFailure;
- }
-
- PORT_Free(plaintext->buf);
+ if (databuf->space < plaintext->len + SSL3_COMPRESSION_MAX_EXPANSION) {
+ rv = sslBuffer_Grow(
+ databuf, plaintext->len + SSL3_COMPRESSION_MAX_EXPANSION);
+ if (rv != SECSuccess) {
+ SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes",
+ SSL_GETPID(), ss->fd,
+ plaintext->len +
+ SSL3_COMPRESSION_MAX_EXPANSION));
+ /* sslBuffer_Grow has set a memory error code. */
+ /* Perhaps we should send an alert. (but we have no memory!) */
+ PORT_Free(plaintext->buf);
+ return SECFailure;
+ }
+ }
+
+ rv = crSpec->decompressor(crSpec->decompressContext,
+ databuf->buf,
+ (int *)&databuf->len,
+ databuf->space,
+ plaintext->buf,
+ plaintext->len);
+
+ if (rv != SECSuccess) {
+ int err = ssl_MapLowLevelError(SSL_ERROR_DECOMPRESSION_FAILURE);
+ SSL3_SendAlert(ss, alert_fatal,
+ isTLS ? decompression_failure
+ : bad_record_mac);
+
+ /* There appears to be a bug with (at least) Apache + OpenSSL where
+ * resumed SSLv3 connections don't actually use compression. See
+ * comments 93-95 of
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=275744
+ *
+ * So, if we get a decompression error, and the record appears to
+ * be already uncompressed, then we return a more specific error
+ * code to hopefully save somebody some debugging time in the
+ * future.
+ */
+ if (plaintext->len >= 4) {
+ unsigned int len = ((unsigned int)plaintext->buf[1] << 16) |
+ ((unsigned int)plaintext->buf[2] << 8) |
+ (unsigned int)plaintext->buf[3];
+ if (len == plaintext->len - 4) {
+ /* This appears to be uncompressed already */
+ err = SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD;
+ }
+ }
+
+ PORT_Free(plaintext->buf);
+ PORT_SetError(err);
+ return SECFailure;
+ }
+
+ PORT_Free(plaintext->buf);
}
/*
- ** Having completed the decompression, check the length again.
+ ** Having completed the decompression, check the length again.
*/
if (isTLS && databuf->len > (MAX_FRAGMENT_LENGTH + 1024)) {
- SSL3_SendAlert(ss, alert_fatal, record_overflow);
- PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
- return SECFailure;
+ SSL3_SendAlert(ss, alert_fatal, record_overflow);
+ PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
+ return SECFailure;
}
/* Application data records are processed by the caller of this
** function, not by this function.
*/
if (rType == content_application_data) {
- if (ss->firstHsDone)
- return SECSuccess;
- (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- PORT_SetError(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA);
- return SECFailure;
+ if (ss->firstHsDone)
+ return SECSuccess;
+ (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA);
+ return SECFailure;
}
/* It's a record that must be handled by ssl itself, not the application.
@@ -13010,29 +13410,29 @@ process_it:
** they return SECFailure or SECWouldBlock.
*/
switch (rType) {
- case content_change_cipher_spec:
- rv = ssl3_HandleChangeCipherSpecs(ss, databuf);
- break;
- case content_alert:
- rv = ssl3_HandleAlert(ss, databuf);
- break;
- case content_handshake:
- if (!IS_DTLS(ss)) {
- rv = ssl3_HandleHandshake(ss, databuf);
- } else {
- rv = dtls_HandleHandshake(ss, databuf);
- }
- break;
- /*
- case content_application_data is handled before this switch
- */
- default:
- SSL_DBG(("%d: SSL3[%d]: bogus content type=%d",
- SSL_GETPID(), ss->fd, cText->type));
- /* XXX Send an alert ??? */
- PORT_SetError(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE);
- rv = SECFailure;
- break;
+ case content_change_cipher_spec:
+ rv = ssl3_HandleChangeCipherSpecs(ss, databuf);
+ break;
+ case content_alert:
+ rv = ssl3_HandleAlert(ss, databuf);
+ break;
+ case content_handshake:
+ if (!IS_DTLS(ss)) {
+ rv = ssl3_HandleHandshake(ss, databuf);
+ } else {
+ rv = dtls_HandleHandshake(ss, databuf);
+ }
+ break;
+ /*
+ case content_application_data is handled before this switch
+ */
+ default:
+ SSL_DBG(("%d: SSL3[%d]: bogus content type=%d",
+ SSL_GETPID(), ss->fd, cText->type));
+ /* XXX Send an alert ??? */
+ PORT_SetError(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE);
+ rv = SECFailure;
+ break;
}
ssl_ReleaseSSL3HandshakeLock(ss);
@@ -13048,49 +13448,49 @@ process_it:
static void
ssl3_InitCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
{
- spec->cipher_def = &bulk_cipher_defs[cipher_null];
+ spec->cipher_def = &bulk_cipher_defs[cipher_null];
PORT_Assert(spec->cipher_def->cipher == cipher_null);
- spec->mac_def = &mac_defs[mac_null];
+ spec->mac_def = &mac_defs[mac_null];
PORT_Assert(spec->mac_def->mac == mac_null);
- spec->encode = Null_Cipher;
- spec->decode = Null_Cipher;
- spec->destroy = NULL;
- spec->compressor = NULL;
- spec->decompressor = NULL;
- spec->destroyCompressContext = NULL;
+ spec->encode = Null_Cipher;
+ spec->decode = Null_Cipher;
+ spec->destroy = NULL;
+ spec->compressor = NULL;
+ spec->decompressor = NULL;
+ spec->destroyCompressContext = NULL;
spec->destroyDecompressContext = NULL;
- spec->mac_size = 0;
- spec->master_secret = NULL;
- spec->bypassCiphers = PR_FALSE;
+ spec->mac_size = 0;
+ spec->master_secret = NULL;
+ spec->bypassCiphers = PR_FALSE;
- spec->msItem.data = NULL;
- spec->msItem.len = 0;
+ spec->msItem.data = NULL;
+ spec->msItem.len = 0;
- spec->client.write_key = NULL;
- spec->client.write_mac_key = NULL;
+ spec->client.write_key = NULL;
+ spec->client.write_mac_key = NULL;
spec->client.write_mac_context = NULL;
- spec->server.write_key = NULL;
- spec->server.write_mac_key = NULL;
+ spec->server.write_key = NULL;
+ spec->server.write_mac_key = NULL;
spec->server.write_mac_context = NULL;
- spec->write_seq_num.high = 0;
- spec->write_seq_num.low = 0;
+ spec->write_seq_num.high = 0;
+ spec->write_seq_num.low = 0;
- spec->read_seq_num.high = 0;
- spec->read_seq_num.low = 0;
+ spec->read_seq_num.high = 0;
+ spec->read_seq_num.low = 0;
- spec->epoch = 0;
+ spec->epoch = 0;
dtls_InitRecvdRecords(&spec->recvdRecords);
- spec->version = ss->vrange.max;
+ spec->version = ss->vrange.max;
}
-/* Called from: ssl3_SendRecord
-** ssl3_StartHandshakeHash() <- ssl2_BeginClientHandshake()
-** ssl3_SendClientHello()
-** ssl3_HandleV2ClientHello()
-** ssl3_HandleRecord()
+/* Called from: ssl3_SendRecord
+** ssl3_StartHandshakeHash() <- ssl2_BeginClientHandshake()
+** ssl3_SendClientHello()
+** ssl3_HandleV2ClientHello()
+** ssl3_HandleRecord()
**
** This function should perhaps acquire and release the SpecWriteLock.
**
@@ -13099,10 +13499,10 @@ ssl3_InitCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
static SECStatus
ssl3_InitState(sslSocket *ss)
{
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ss->ssl3.initialized)
- return SECSuccess; /* Function should be idempotent */
+ return SECSuccess; /* Function should be idempotent */
ss->ssl3.policy = SSL_ALLOWED;
@@ -13123,14 +13523,22 @@ ssl3_InitState(sslSocket *ss)
PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData));
if (IS_DTLS(ss)) {
- ss->ssl3.hs.sendMessageSeq = 0;
- ss->ssl3.hs.recvMessageSeq = 0;
- ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
- ss->ssl3.hs.rtRetries = 0;
- ss->ssl3.hs.recvdHighWater = -1;
- PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight);
- dtls_SetMTU(ss, 0); /* Set the MTU to the highest plateau */
- }
+ ss->ssl3.hs.sendMessageSeq = 0;
+ ss->ssl3.hs.recvMessageSeq = 0;
+ ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
+ ss->ssl3.hs.rtRetries = 0;
+ ss->ssl3.hs.recvdHighWater = -1;
+ PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight);
+ dtls_SetMTU(ss, 0); /* Set the MTU to the highest plateau */
+ }
+
+ PR_INIT_CLIST(&ss->ssl3.hs.remoteKeyShares);
+ ss->ssl3.hs.xSS = NULL;
+ ss->ssl3.hs.xES = NULL;
+ ss->ssl3.hs.trafficSecret = NULL;
+ ss->ssl3.hs.clientFinishedSecret = NULL;
+ ss->ssl3.hs.serverFinishedSecret = NULL;
+ ss->ssl3.hs.certReqContextLen = 0;
PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space);
ss->ssl3.hs.messages.buf = NULL;
@@ -13138,7 +13546,7 @@ ssl3_InitState(sslSocket *ss)
ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
PORT_Memset(&ss->ssl3.hs.newSessionTicket, 0,
- sizeof(ss->ssl3.hs.newSessionTicket));
+ sizeof(ss->ssl3.hs.newSessionTicket));
ss->ssl3.initialized = PR_TRUE;
return SECSuccess;
@@ -13149,40 +13557,40 @@ ssl3_InitState(sslSocket *ss)
* Uses the keys in the pair as input.
*/
ssl3KeyPair *
-ssl3_NewKeyPair( SECKEYPrivateKey * privKey, SECKEYPublicKey * pubKey)
+ssl3_NewKeyPair(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey)
{
- ssl3KeyPair * pair;
+ ssl3KeyPair *pair;
if (!privKey || !pubKey) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return NULL;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return NULL;
}
pair = PORT_ZNew(ssl3KeyPair);
if (!pair)
- return NULL; /* error code is set. */
+ return NULL; /* error code is set. */
pair->refCount = 1;
- pair->privKey = privKey;
- pair->pubKey = pubKey;
- return pair; /* success */
+ pair->privKey = privKey;
+ pair->pubKey = pubKey;
+ return pair; /* success */
}
ssl3KeyPair *
-ssl3_GetKeyPairRef(ssl3KeyPair * keyPair)
+ssl3_GetKeyPairRef(ssl3KeyPair *keyPair)
{
PR_ATOMIC_INCREMENT(&keyPair->refCount);
return keyPair;
}
void
-ssl3_FreeKeyPair(ssl3KeyPair * keyPair)
+ssl3_FreeKeyPair(ssl3KeyPair *keyPair)
{
- PRInt32 newCount = PR_ATOMIC_DECREMENT(&keyPair->refCount);
+ PRInt32 newCount = PR_ATOMIC_DECREMENT(&keyPair->refCount);
if (!newCount) {
- if (keyPair->privKey)
- SECKEY_DestroyPrivateKey(keyPair->privKey);
- if (keyPair->pubKey)
- SECKEY_DestroyPublicKey( keyPair->pubKey);
- PORT_Free(keyPair);
+ if (keyPair->privKey)
+ SECKEY_DestroyPrivateKey(keyPair->privKey);
+ if (keyPair->pubKey)
+ SECKEY_DestroyPublicKey(keyPair->pubKey);
+ PORT_Free(keyPair);
}
}
@@ -13193,25 +13601,25 @@ ssl3_FreeKeyPair(ssl3KeyPair * keyPair)
SECStatus
ssl3_CreateRSAStepDownKeys(sslSocket *ss)
{
- SECStatus rv = SECSuccess;
- SECKEYPrivateKey * privKey; /* RSA step down key */
- SECKEYPublicKey * pubKey; /* RSA step down key */
+ SECStatus rv = SECSuccess;
+ SECKEYPrivateKey *privKey; /* RSA step down key */
+ SECKEYPublicKey *pubKey; /* RSA step down key */
if (ss->stepDownKeyPair)
- ssl3_FreeKeyPair(ss->stepDownKeyPair);
+ ssl3_FreeKeyPair(ss->stepDownKeyPair);
ss->stepDownKeyPair = NULL;
#ifndef HACKED_EXPORT_SERVER
/* Sigh, should have a get key strength call for private keys */
if (PK11_GetPrivateModulusLen(ss->serverCerts[kt_rsa].SERVERKEY) >
- EXPORT_RSA_KEY_LENGTH) {
- /* need to ask for the key size in bits */
- privKey = SECKEY_CreateRSAPrivateKey(EXPORT_RSA_KEY_LENGTH * BPB,
- &pubKey, NULL);
- if (!privKey || !pubKey ||
- !(ss->stepDownKeyPair = ssl3_NewKeyPair(privKey, pubKey))) {
- ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
- rv = SECFailure;
- }
+ EXPORT_RSA_KEY_LENGTH) {
+ /* need to ask for the key size in bits */
+ privKey = SECKEY_CreateRSAPrivateKey(EXPORT_RSA_KEY_LENGTH * BPB,
+ &pubKey, NULL);
+ if (!privKey || !pubKey ||
+ !(ss->stepDownKeyPair = ssl3_NewKeyPair(privKey, pubKey))) {
+ ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
+ rv = SECFailure;
+ }
}
#endif
return rv;
@@ -13225,7 +13633,7 @@ ssl3_SetPolicy(ssl3CipherSuite which, int policy)
suite = ssl_LookupCipherSuiteCfg(which, cipherSuites);
if (suite == NULL) {
- return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */
+ return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */
}
suite->policy = policy;
@@ -13236,16 +13644,16 @@ SECStatus
ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *oPolicy)
{
ssl3CipherSuiteCfg *suite;
- PRInt32 policy;
- SECStatus rv;
+ PRInt32 policy;
+ SECStatus rv;
suite = ssl_LookupCipherSuiteCfg(which, cipherSuites);
if (suite) {
- policy = suite->policy;
- rv = SECSuccess;
+ policy = suite->policy;
+ rv = SECSuccess;
} else {
- policy = SSL_NOT_ALLOWED;
- rv = SECFailure; /* err code was set by Lookup. */
+ policy = SSL_NOT_ALLOWED;
+ rv = SECFailure; /* err code was set by Lookup. */
}
*oPolicy = policy;
return rv;
@@ -13259,7 +13667,7 @@ ssl3_CipherPrefSetDefault(ssl3CipherSuite which, PRBool enabled)
suite = ssl_LookupCipherSuiteCfg(which, cipherSuites);
if (suite == NULL) {
- return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */
+ return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */
}
suite->enabled = enabled;
return SECSuccess;
@@ -13270,16 +13678,16 @@ SECStatus
ssl3_CipherPrefGetDefault(ssl3CipherSuite which, PRBool *enabled)
{
ssl3CipherSuiteCfg *suite;
- PRBool pref;
- SECStatus rv;
+ PRBool pref;
+ SECStatus rv;
suite = ssl_LookupCipherSuiteCfg(which, cipherSuites);
if (suite) {
- pref = suite->enabled;
- rv = SECSuccess;
+ pref = suite->enabled;
+ rv = SECSuccess;
} else {
- pref = SSL_NOT_ALLOWED;
- rv = SECFailure; /* err code was set by Lookup. */
+ pref = SSL_NOT_ALLOWED;
+ rv = SECFailure; /* err code was set by Lookup. */
}
*enabled = pref;
return rv;
@@ -13292,7 +13700,7 @@ ssl3_CipherPrefSet(sslSocket *ss, ssl3CipherSuite which, PRBool enabled)
suite = ssl_LookupCipherSuiteCfg(which, ss->cipherSuites);
if (suite == NULL) {
- return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */
+ return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */
}
suite->enabled = enabled;
return SECSuccess;
@@ -13302,16 +13710,16 @@ SECStatus
ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *enabled)
{
ssl3CipherSuiteCfg *suite;
- PRBool pref;
- SECStatus rv;
+ PRBool pref;
+ SECStatus rv;
suite = ssl_LookupCipherSuiteCfg(which, ss->cipherSuites);
if (suite) {
- pref = suite->enabled;
- rv = SECSuccess;
+ pref = suite->enabled;
+ rv = SECSuccess;
} else {
- pref = SSL_NOT_ALLOWED;
- rv = SECFailure; /* err code was set by Lookup. */
+ pref = SSL_NOT_ALLOWED;
+ rv = SECFailure; /* err code was set by Lookup. */
}
*enabled = pref;
return rv;
@@ -13347,7 +13755,7 @@ SSL_SignaturePrefSet(PRFileDesc *fd, const SSLSignatureAndHashAlg *algorithms,
}
ss->ssl3.signatureAlgorithms[ss->ssl3.signatureAlgorithmCount++] =
- algorithms[i];
+ algorithms[i];
}
if (ss->ssl3.signatureAlgorithmCount == 0) {
@@ -13379,14 +13787,15 @@ SSL_SignaturePrefGet(PRFileDesc *fd, SSLSignatureAndHashAlg *algorithms,
}
requiredSpace =
- ss->ssl3.signatureAlgorithmCount * sizeof(SSLSignatureAndHashAlg);
+ ss->ssl3.signatureAlgorithmCount * sizeof(SSLSignatureAndHashAlg);
PORT_Memcpy(algorithms, ss->ssl3.signatureAlgorithms, requiredSpace);
*count = ss->ssl3.signatureAlgorithmCount;
return SECSuccess;
}
unsigned int
-SSL_SignatureMaxCount() {
+SSL_SignatureMaxCount()
+{
return MAX_SIGNATURE_ALGORITHMS;
}
@@ -13398,33 +13807,33 @@ ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *ciphers, unsigned int
unsigned int i, done;
for (i = done = 0; i < len; i++) {
- PRUint16 id = ciphers[i];
- unsigned int existingIndex, j;
- PRBool found = PR_FALSE;
-
- for (j = done; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
- if (ss->cipherSuites[j].cipher_suite == id) {
- existingIndex = j;
- found = PR_TRUE;
- break;
- }
- }
-
- if (!found) {
- continue;
- }
-
- if (existingIndex != done) {
- const ssl3CipherSuiteCfg temp = ss->cipherSuites[done];
- ss->cipherSuites[done] = ss->cipherSuites[existingIndex];
- ss->cipherSuites[existingIndex] = temp;
- }
- done++;
+ PRUint16 id = ciphers[i];
+ unsigned int existingIndex, j;
+ PRBool found = PR_FALSE;
+
+ for (j = done; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
+ if (ss->cipherSuites[j].cipher_suite == id) {
+ existingIndex = j;
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ continue;
+ }
+
+ if (existingIndex != done) {
+ const ssl3CipherSuiteCfg temp = ss->cipherSuites[done];
+ ss->cipherSuites[done] = ss->cipherSuites[existingIndex];
+ ss->cipherSuites[existingIndex] = temp;
+ }
+ done++;
}
/* Disable all cipher suites that weren't included. */
for (; done < ssl_V3_SUITES_IMPLEMENTED; done++) {
- ss->cipherSuites[done].enabled = 0;
+ ss->cipherSuites[done].enabled = 0;
}
return SECSuccess;
@@ -13442,13 +13851,14 @@ ssl3_InitSocketPolicy(sslSocket *ss)
SECStatus
ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
- unsigned char *out,
- unsigned int *outLen,
- unsigned int outLenMax) {
- PRBool isTLS;
- int index = 0;
+ unsigned char *out,
+ unsigned int *outLen,
+ unsigned int outLenMax)
+{
+ PRBool isTLS;
+ int index = 0;
unsigned int len;
- SECStatus rv = SECFailure;
+ SECStatus rv = SECFailure;
*outLen = 0;
@@ -13466,33 +13876,33 @@ ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
/* Sending or receiving a Finished message will set finishedBytes to a
* non-zero value. */
if (len == 0) {
- PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
- goto loser;
+ PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
+ goto loser;
}
/* If we are in the middle of a renegotiation then the channel binding
* value is poorly defined and depends on the direction that it will be
* used on. Therefore we simply return an error in this case. */
if (ss->firstHsDone && ss->ssl3.hs.ws != idle_handshake) {
- PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
- goto loser;
+ PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
+ goto loser;
}
/* If resuming, then we want the second Finished value in the array, which
* is the server's */
if (ss->ssl3.hs.isResuming)
- index = 1;
+ index = 1;
*outLen = len;
if (outLenMax < len) {
- PORT_SetError(SEC_ERROR_OUTPUT_LEN);
- goto loser;
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ goto loser;
}
if (isTLS) {
- memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len);
+ memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len);
} else {
- memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len);
+ memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len);
}
rv = SECSuccess;
@@ -13512,36 +13922,36 @@ ssl3_ConstructV2CipherSpecsHack(sslSocket *ss, unsigned char *cs, int *size)
PORT_Assert(ss != 0);
if (!ss) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return SECFailure;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return SECFailure;
}
if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
- *size = 0;
- return SECSuccess;
+ *size = 0;
+ return SECSuccess;
}
if (cs == NULL) {
- *size = count_cipher_suites(ss, SSL_ALLOWED, PR_TRUE);
- return SECSuccess;
+ *size = count_cipher_suites(ss, SSL_ALLOWED, PR_TRUE);
+ return SECSuccess;
}
/* ssl3_config_match_init was called by the caller of this function. */
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
- ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
- if (config_match(suite, SSL_ALLOWED, PR_TRUE, &ss->vrange, ss)) {
- if (cs != NULL) {
- *cs++ = 0x00;
- *cs++ = (suite->cipher_suite >> 8) & 0xFF;
- *cs++ = suite->cipher_suite & 0xFF;
- }
- count++;
- }
+ ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
+ if (config_match(suite, SSL_ALLOWED, PR_TRUE, &ss->vrange, ss)) {
+ if (cs != NULL) {
+ *cs++ = 0x00;
+ *cs++ = (suite->cipher_suite >> 8) & 0xFF;
+ *cs++ = suite->cipher_suite & 0xFF;
+ }
+ count++;
+ }
}
*size = count;
return SECSuccess;
}
/*
-** If ssl3 socket has completed the first handshake, and is in idle state,
+** If ssl3 socket has completed the first handshake, and is in idle state,
** then start a new handshake.
** If flushCache is true, the SID cache will be flushed first, forcing a
** "Full" handshake (not a session restart handshake), to be done.
@@ -13551,41 +13961,41 @@ ssl3_ConstructV2CipherSpecsHack(sslSocket *ss, unsigned char *cs, int *size)
SECStatus
ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache)
{
- sslSessionID * sid = ss->sec.ci.sid;
- SECStatus rv;
+ sslSessionID *sid = ss->sec.ci.sid;
+ SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (!ss->firstHsDone ||
((ss->version >= SSL_LIBRARY_VERSION_3_0) &&
- ss->ssl3.initialized &&
- (ss->ssl3.hs.ws != idle_handshake))) {
- PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
- return SECFailure;
+ ss->ssl3.initialized &&
+ (ss->ssl3.hs.ws != idle_handshake))) {
+ PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
+ return SECFailure;
}
if (IS_DTLS(ss)) {
- dtls_RehandshakeCleanup(ss);
+ dtls_RehandshakeCleanup(ss);
}
if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
- PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
+ return SECFailure;
}
if (sid && flushCache) {
if (ss->sec.uncache)
ss->sec.uncache(sid); /* remove it from whichever cache it's in. */
- ssl_FreeSID(sid); /* dec ref count and free if zero. */
- ss->sec.ci.sid = NULL;
+ ssl_FreeSID(sid); /* dec ref count and free if zero. */
+ ss->sec.ci.sid = NULL;
}
- ssl_GetXmitBufLock(ss); /**************************************/
+ ssl_GetXmitBufLock(ss); /**************************************/
/* start off a new handshake. */
rv = (ss->sec.isServer) ? ssl3_SendHelloRequest(ss)
: ssl3_SendClientHello(ss, PR_FALSE);
- ssl_ReleaseXmitBufLock(ss); /**************************************/
+ ssl_ReleaseXmitBufLock(ss); /**************************************/
return rv;
}
@@ -13595,53 +14005,49 @@ ssl3_DestroySSL3Info(sslSocket *ss)
{
if (ss->ssl3.clientCertificate != NULL)
- CERT_DestroyCertificate(ss->ssl3.clientCertificate);
+ CERT_DestroyCertificate(ss->ssl3.clientCertificate);
if (ss->ssl3.clientPrivateKey != NULL)
- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
-#ifdef NSS_PLATFORM_CLIENT_AUTH
- if (ss->ssl3.platformClientKey)
- ssl_FreePlatformKey(ss->ssl3.platformClientKey);
-#endif /* NSS_PLATFORM_CLIENT_AUTH */
+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
if (ss->ssl3.channelID)
- SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
+ SECKEY_DestroyPrivateKey(ss->ssl3.channelID);
if (ss->ssl3.channelIDPub)
- SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
+ SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub);
if (ss->ssl3.peerCertArena != NULL)
- ssl3_CleanupPeerCerts(ss);
+ ssl3_CleanupPeerCerts(ss);
if (ss->ssl3.clientCertChain != NULL) {
- CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
- ss->ssl3.clientCertChain = NULL;
+ CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
+ ss->ssl3.clientCertChain = NULL;
}
- /* clean up handshake */
+/* clean up handshake */
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11) {
- if (ss->ssl3.hs.hashType == handshake_hash_combo) {
- SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE);
- MD5_DestroyContext((MD5Context *)ss->ssl3.hs.md5_cx, PR_FALSE);
- } else if (ss->ssl3.hs.hashType == handshake_hash_single) {
- ss->ssl3.hs.sha_obj->destroy(ss->ssl3.hs.sha_cx, PR_FALSE);
- }
- }
+ if (ss->ssl3.hs.hashType == handshake_hash_combo) {
+ SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE);
+ MD5_DestroyContext((MD5Context *)ss->ssl3.hs.md5_cx, PR_FALSE);
+ } else if (ss->ssl3.hs.hashType == handshake_hash_single) {
+ ss->ssl3.hs.sha_obj->destroy(ss->ssl3.hs.sha_cx, PR_FALSE);
+ }
+ }
#endif
if (ss->ssl3.hs.md5) {
- PK11_DestroyContext(ss->ssl3.hs.md5,PR_TRUE);
+ PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
}
if (ss->ssl3.hs.sha) {
- PK11_DestroyContext(ss->ssl3.hs.sha,PR_TRUE);
+ PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE);
}
if (ss->ssl3.hs.clientSigAndHash) {
- PORT_Free(ss->ssl3.hs.clientSigAndHash);
+ PORT_Free(ss->ssl3.hs.clientSigAndHash);
}
if (ss->ssl3.hs.messages.buf) {
- PORT_Free(ss->ssl3.hs.messages.buf);
- ss->ssl3.hs.messages.buf = NULL;
- ss->ssl3.hs.messages.len = 0;
- ss->ssl3.hs.messages.space = 0;
+ PORT_Free(ss->ssl3.hs.messages.buf);
+ ss->ssl3.hs.messages.buf = NULL;
+ ss->ssl3.hs.messages.len = 0;
+ ss->ssl3.hs.messages.space = 0;
}
/* free the SSL3Buffer (msg_body) */
@@ -13650,19 +14056,34 @@ ssl3_DestroySSL3Info(sslSocket *ss)
SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE);
/* free up the CipherSpecs */
- ssl3_DestroyCipherSpec(&ss->ssl3.specs[0], PR_TRUE/*freeSrvName*/);
- ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE/*freeSrvName*/);
+ ssl3_DestroyCipherSpec(&ss->ssl3.specs[0], PR_TRUE /*freeSrvName*/);
+ ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE /*freeSrvName*/);
/* Destroy the DTLS data */
if (IS_DTLS(ss)) {
- dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
- if (ss->ssl3.hs.recvdFragments.buf) {
- PORT_Free(ss->ssl3.hs.recvdFragments.buf);
- }
+ dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
+ if (ss->ssl3.hs.recvdFragments.buf) {
+ PORT_Free(ss->ssl3.hs.recvdFragments.buf);
+ }
}
+ /* Destroy TLS 1.3 handshake shares */
+ tls13_DestroyKeyShares(&ss->ssl3.hs.remoteKeyShares);
+
+ /* Destroy TLS 1.3 keys */
+ if (ss->ssl3.hs.xSS)
+ PK11_FreeSymKey(ss->ssl3.hs.xSS);
+ if (ss->ssl3.hs.xES)
+ PK11_FreeSymKey(ss->ssl3.hs.xES);
+ if (ss->ssl3.hs.trafficSecret)
+ PK11_FreeSymKey(ss->ssl3.hs.trafficSecret);
+ if (ss->ssl3.hs.clientFinishedSecret)
+ PK11_FreeSymKey(ss->ssl3.hs.clientFinishedSecret);
+ if (ss->ssl3.hs.serverFinishedSecret)
+ PK11_FreeSymKey(ss->ssl3.hs.serverFinishedSecret);
+
if (ss->ssl3.dheGroups) {
- PORT_Free(ss->ssl3.dheGroups);
+ PORT_Free(ss->ssl3.dheGroups);
}
ss->ssl3.initialized = PR_FALSE;
@@ -13670,4 +14091,56 @@ ssl3_DestroySSL3Info(sslSocket *ss)
SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
}
+#define MAP_NULL(x) (((x) != 0) ? (x) : SEC_OID_NULL_CIPHER)
+
+SECStatus
+ssl3_ApplyNSSPolicy(void)
+{
+ unsigned i;
+ SECStatus rv;
+ PRUint32 policy = 0;
+
+ rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, &policy);
+ if (rv != SECSuccess || !(policy & NSS_USE_POLICY_IN_SSL)) {
+ return SECSuccess; /* do nothing */
+ }
+
+ /* disable every ciphersuite */
+ for (i = 1; i < PR_ARRAY_SIZE(cipher_suite_defs); ++i) {
+ const ssl3CipherSuiteDef *suite = &cipher_suite_defs[i];
+ SECOidTag policyOid;
+
+ policyOid = MAP_NULL(kea_defs[suite->key_exchange_alg].oid);
+ rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
+ if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL_KX)) {
+ ssl_CipherPrefSetDefault(suite->cipher_suite, PR_FALSE);
+ ssl_CipherPolicySet(suite->cipher_suite, SSL_NOT_ALLOWED);
+ continue;
+ }
+
+ policyOid = MAP_NULL(bulk_cipher_defs[suite->bulk_cipher_alg].oid);
+ rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
+ if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL)) {
+ ssl_CipherPrefSetDefault(suite->cipher_suite, PR_FALSE);
+ ssl_CipherPolicySet(suite->cipher_suite, SSL_NOT_ALLOWED);
+ continue;
+ }
+
+ if (bulk_cipher_defs[suite->bulk_cipher_alg].type != type_aead) {
+ policyOid = MAP_NULL(mac_defs[suite->mac_alg].oid);
+ rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
+ if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL)) {
+ ssl_CipherPrefSetDefault(suite->cipher_suite, PR_FALSE);
+ ssl_CipherPolicySet(suite->cipher_suite,
+ SSL_NOT_ALLOWED);
+ continue;
+ }
+ }
+ }
+
+ rv = ssl3_ConstrainRangeByPolicy();
+
+ return rv;
+}
+
/* End of ssl3con.c */
diff --git a/chromium/net/third_party/nss/ssl/ssl3ecc.c b/chromium/net/third_party/nss/ssl/ssl3ecc.c
index ab5ab14d41d..c8e9d06b587 100644
--- a/chromium/net/third_party/nss/ssl/ssl3ecc.c
+++ b/chromium/net/third_party/nss/ssl/ssl3ecc.c
@@ -11,7 +11,7 @@
#include "nss.h"
#include "cert.h"
#include "ssl.h"
-#include "cryptohi.h" /* for DSAU_ stuff */
+#include "cryptohi.h" /* for DSAU_ stuff */
#include "keyhi.h"
#include "secder.h"
#include "secitem.h"
@@ -31,30 +31,24 @@
#include <stdio.h>
-/* This is a bodge to allow this code to be compiled against older NSS headers
- * that don't contain the TLS 1.2 changes. */
-#ifndef CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256
-#define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24)
-#endif
-
#ifndef NSS_DISABLE_ECC
#ifndef PK11_SETATTRS
-#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
- (x)->pValue=(v); (x)->ulValueLen = (l);
+#define PK11_SETATTRS(x, id, v, l) \
+ (x)->type = (id); \
+ (x)->pValue = (v); \
+ (x)->ulValueLen = (l);
#endif
-#define SSL_GET_SERVER_PUBLIC_KEY(sock, type) \
- (ss->serverCerts[type].serverKeyPair ? \
- ss->serverCerts[type].serverKeyPair->pubKey : NULL)
+#define SSL_GET_SERVER_PUBLIC_KEY(sock, type) \
+ (ss->serverCerts[type].serverKeyPair ? ss->serverCerts[type].serverKeyPair->pubKey \
+ : NULL)
#define SSL_IS_CURVE_NEGOTIATED(curvemsk, curveName) \
- ((curveName > ec_noName) && \
- (curveName < ec_pastLastName) && \
+ ((curveName > ec_noName) && \
+ (curveName < ec_pastLastName) && \
((1UL << curveName) & curvemsk) != 0)
-
-
static SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve);
#define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName))
@@ -63,101 +57,101 @@ static SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve);
* ECC-TLS IETF draft.
*/
static const SECOidTag ecName2OIDTag[] = {
- 0,
- SEC_OID_SECG_EC_SECT163K1, /* 1 */
- SEC_OID_SECG_EC_SECT163R1, /* 2 */
- SEC_OID_SECG_EC_SECT163R2, /* 3 */
- SEC_OID_SECG_EC_SECT193R1, /* 4 */
- SEC_OID_SECG_EC_SECT193R2, /* 5 */
- SEC_OID_SECG_EC_SECT233K1, /* 6 */
- SEC_OID_SECG_EC_SECT233R1, /* 7 */
- SEC_OID_SECG_EC_SECT239K1, /* 8 */
- SEC_OID_SECG_EC_SECT283K1, /* 9 */
- SEC_OID_SECG_EC_SECT283R1, /* 10 */
- SEC_OID_SECG_EC_SECT409K1, /* 11 */
- SEC_OID_SECG_EC_SECT409R1, /* 12 */
- SEC_OID_SECG_EC_SECT571K1, /* 13 */
- SEC_OID_SECG_EC_SECT571R1, /* 14 */
- SEC_OID_SECG_EC_SECP160K1, /* 15 */
- SEC_OID_SECG_EC_SECP160R1, /* 16 */
- SEC_OID_SECG_EC_SECP160R2, /* 17 */
- SEC_OID_SECG_EC_SECP192K1, /* 18 */
- SEC_OID_SECG_EC_SECP192R1, /* 19 */
- SEC_OID_SECG_EC_SECP224K1, /* 20 */
- SEC_OID_SECG_EC_SECP224R1, /* 21 */
- SEC_OID_SECG_EC_SECP256K1, /* 22 */
- SEC_OID_SECG_EC_SECP256R1, /* 23 */
- SEC_OID_SECG_EC_SECP384R1, /* 24 */
- SEC_OID_SECG_EC_SECP521R1, /* 25 */
+ 0,
+ SEC_OID_SECG_EC_SECT163K1, /* 1 */
+ SEC_OID_SECG_EC_SECT163R1, /* 2 */
+ SEC_OID_SECG_EC_SECT163R2, /* 3 */
+ SEC_OID_SECG_EC_SECT193R1, /* 4 */
+ SEC_OID_SECG_EC_SECT193R2, /* 5 */
+ SEC_OID_SECG_EC_SECT233K1, /* 6 */
+ SEC_OID_SECG_EC_SECT233R1, /* 7 */
+ SEC_OID_SECG_EC_SECT239K1, /* 8 */
+ SEC_OID_SECG_EC_SECT283K1, /* 9 */
+ SEC_OID_SECG_EC_SECT283R1, /* 10 */
+ SEC_OID_SECG_EC_SECT409K1, /* 11 */
+ SEC_OID_SECG_EC_SECT409R1, /* 12 */
+ SEC_OID_SECG_EC_SECT571K1, /* 13 */
+ SEC_OID_SECG_EC_SECT571R1, /* 14 */
+ SEC_OID_SECG_EC_SECP160K1, /* 15 */
+ SEC_OID_SECG_EC_SECP160R1, /* 16 */
+ SEC_OID_SECG_EC_SECP160R2, /* 17 */
+ SEC_OID_SECG_EC_SECP192K1, /* 18 */
+ SEC_OID_SECG_EC_SECP192R1, /* 19 */
+ SEC_OID_SECG_EC_SECP224K1, /* 20 */
+ SEC_OID_SECG_EC_SECP224R1, /* 21 */
+ SEC_OID_SECG_EC_SECP256K1, /* 22 */
+ SEC_OID_SECG_EC_SECP256R1, /* 23 */
+ SEC_OID_SECG_EC_SECP384R1, /* 24 */
+ SEC_OID_SECG_EC_SECP521R1, /* 25 */
};
static const PRUint16 curve2bits[] = {
- 0, /* ec_noName = 0, */
- 163, /* ec_sect163k1 = 1, */
- 163, /* ec_sect163r1 = 2, */
- 163, /* ec_sect163r2 = 3, */
- 193, /* ec_sect193r1 = 4, */
- 193, /* ec_sect193r2 = 5, */
- 233, /* ec_sect233k1 = 6, */
- 233, /* ec_sect233r1 = 7, */
- 239, /* ec_sect239k1 = 8, */
- 283, /* ec_sect283k1 = 9, */
- 283, /* ec_sect283r1 = 10, */
- 409, /* ec_sect409k1 = 11, */
- 409, /* ec_sect409r1 = 12, */
- 571, /* ec_sect571k1 = 13, */
- 571, /* ec_sect571r1 = 14, */
- 160, /* ec_secp160k1 = 15, */
- 160, /* ec_secp160r1 = 16, */
- 160, /* ec_secp160r2 = 17, */
- 192, /* ec_secp192k1 = 18, */
- 192, /* ec_secp192r1 = 19, */
- 224, /* ec_secp224k1 = 20, */
- 224, /* ec_secp224r1 = 21, */
- 256, /* ec_secp256k1 = 22, */
- 256, /* ec_secp256r1 = 23, */
- 384, /* ec_secp384r1 = 24, */
- 521, /* ec_secp521r1 = 25, */
- 65535 /* ec_pastLastName */
+ 0, /* ec_noName = 0, */
+ 163, /* ec_sect163k1 = 1, */
+ 163, /* ec_sect163r1 = 2, */
+ 163, /* ec_sect163r2 = 3, */
+ 193, /* ec_sect193r1 = 4, */
+ 193, /* ec_sect193r2 = 5, */
+ 233, /* ec_sect233k1 = 6, */
+ 233, /* ec_sect233r1 = 7, */
+ 239, /* ec_sect239k1 = 8, */
+ 283, /* ec_sect283k1 = 9, */
+ 283, /* ec_sect283r1 = 10, */
+ 409, /* ec_sect409k1 = 11, */
+ 409, /* ec_sect409r1 = 12, */
+ 571, /* ec_sect571k1 = 13, */
+ 571, /* ec_sect571r1 = 14, */
+ 160, /* ec_secp160k1 = 15, */
+ 160, /* ec_secp160r1 = 16, */
+ 160, /* ec_secp160r2 = 17, */
+ 192, /* ec_secp192k1 = 18, */
+ 192, /* ec_secp192r1 = 19, */
+ 224, /* ec_secp224k1 = 20, */
+ 224, /* ec_secp224r1 = 21, */
+ 256, /* ec_secp256k1 = 22, */
+ 256, /* ec_secp256r1 = 23, */
+ 384, /* ec_secp384r1 = 24, */
+ 521, /* ec_secp521r1 = 25, */
+ 65535 /* ec_pastLastName */
};
typedef struct Bits2CurveStr {
- PRUint16 bits;
- ECName curve;
+ PRUint16 bits;
+ ECName curve;
} Bits2Curve;
-static const Bits2Curve bits2curve [] = {
- { 192, ec_secp192r1 /* = 19, fast */ },
- { 160, ec_secp160r2 /* = 17, fast */ },
- { 160, ec_secp160k1 /* = 15, */ },
- { 160, ec_secp160r1 /* = 16, */ },
- { 163, ec_sect163k1 /* = 1, */ },
- { 163, ec_sect163r1 /* = 2, */ },
- { 163, ec_sect163r2 /* = 3, */ },
- { 192, ec_secp192k1 /* = 18, */ },
- { 193, ec_sect193r1 /* = 4, */ },
- { 193, ec_sect193r2 /* = 5, */ },
- { 224, ec_secp224r1 /* = 21, fast */ },
- { 224, ec_secp224k1 /* = 20, */ },
- { 233, ec_sect233k1 /* = 6, */ },
- { 233, ec_sect233r1 /* = 7, */ },
- { 239, ec_sect239k1 /* = 8, */ },
- { 256, ec_secp256r1 /* = 23, fast */ },
- { 256, ec_secp256k1 /* = 22, */ },
- { 283, ec_sect283k1 /* = 9, */ },
- { 283, ec_sect283r1 /* = 10, */ },
- { 384, ec_secp384r1 /* = 24, fast */ },
- { 409, ec_sect409k1 /* = 11, */ },
- { 409, ec_sect409r1 /* = 12, */ },
- { 521, ec_secp521r1 /* = 25, fast */ },
- { 571, ec_sect571k1 /* = 13, */ },
- { 571, ec_sect571r1 /* = 14, */ },
- { 65535, ec_noName }
+static const Bits2Curve bits2curve[] = {
+ { 192, ec_secp192r1 /* = 19, fast */ },
+ { 160, ec_secp160r2 /* = 17, fast */ },
+ { 160, ec_secp160k1 /* = 15, */ },
+ { 160, ec_secp160r1 /* = 16, */ },
+ { 163, ec_sect163k1 /* = 1, */ },
+ { 163, ec_sect163r1 /* = 2, */ },
+ { 163, ec_sect163r2 /* = 3, */ },
+ { 192, ec_secp192k1 /* = 18, */ },
+ { 193, ec_sect193r1 /* = 4, */ },
+ { 193, ec_sect193r2 /* = 5, */ },
+ { 224, ec_secp224r1 /* = 21, fast */ },
+ { 224, ec_secp224k1 /* = 20, */ },
+ { 233, ec_sect233k1 /* = 6, */ },
+ { 233, ec_sect233r1 /* = 7, */ },
+ { 239, ec_sect239k1 /* = 8, */ },
+ { 256, ec_secp256r1 /* = 23, fast */ },
+ { 256, ec_secp256k1 /* = 22, */ },
+ { 283, ec_sect283k1 /* = 9, */ },
+ { 283, ec_sect283r1 /* = 10, */ },
+ { 384, ec_secp384r1 /* = 24, fast */ },
+ { 409, ec_sect409k1 /* = 11, */ },
+ { 409, ec_sect409r1 /* = 12, */ },
+ { 521, ec_secp521r1 /* = 25, fast */ },
+ { 571, ec_sect571k1 /* = 13, */ },
+ { 571, ec_sect571r1 /* = 14, */ },
+ { 65535, ec_noName }
};
typedef struct ECDHEKeyPairStr {
- ssl3KeyPair * pair;
- int error; /* error code of the call-once function */
+ ssl3KeyPair *pair;
+ int error; /* error code of the call-once function */
PRCallOnceType once;
} ECDHEKeyPair;
@@ -165,9 +159,10 @@ typedef struct ECDHEKeyPairStr {
static ECDHEKeyPair gECDHEKeyPairs[ec_pastLastName];
SECStatus
-ssl3_ECName2Params(PLArenaPool * arena, ECName curve, SECKEYECParams * params)
+ssl3_ECName2Params(PLArenaPool *arena, ECName curve, SECKEYECParams *params)
{
SECOidData *oidData = NULL;
+ PRUint32 policyFlags = 0;
if ((curve <= ec_noName) || (curve >= ec_pastLastName) ||
((oidData = SECOID_FindOIDByTag(ecName2OIDTag[curve])) == NULL)) {
@@ -175,6 +170,13 @@ ssl3_ECName2Params(PLArenaPool * arena, ECName curve, SECKEYECParams * params)
return SECFailure;
}
+ if ((NSS_GetAlgorithmPolicy(ecName2OIDTag[curve], &policyFlags) ==
+ SECSuccess) &&
+ !(policyFlags & NSS_USE_ALG_IN_SSL_KX)) {
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+ return SECFailure;
+ }
+
SECITEM_AllocItem(arena, params, (2 + oidData->oid.len));
/*
* params->data needs to contain the ASN encoding of an object ID (OID)
@@ -188,22 +190,38 @@ ssl3_ECName2Params(PLArenaPool * arena, ECName curve, SECKEYECParams * params)
return SECSuccess;
}
-static ECName
-params2ecName(SECKEYECParams * params)
+ECName
+ssl3_PubKey2ECName(SECKEYPublicKey *pubKey)
{
- SECItem oid = { siBuffer, NULL, 0};
+ SECItem oid = { siBuffer, NULL, 0 };
SECOidData *oidData = NULL;
+ PRUint32 policyFlags = 0;
ECName i;
+ SECKEYECParams *params;
+
+ if (pubKey->keyType != ecKey) {
+ PORT_Assert(0);
+ return ec_noName;
+ }
+
+ params = &pubKey->u.ec.DEREncodedParams;
/*
* params->data needs to contain the ASN encoding of an object ID (OID)
* representing a named curve. Here, we strip away everything
* before the actual OID and use the OID to look up a named curve.
*/
- if (params->data[0] != SEC_ASN1_OBJECT_ID) return ec_noName;
+ if (params->data[0] != SEC_ASN1_OBJECT_ID)
+ return ec_noName;
oid.len = params->len - 2;
oid.data = params->data + 2;
- if ((oidData = SECOID_FindOID(&oid)) == NULL) return ec_noName;
+ if ((oidData = SECOID_FindOID(&oid)) == NULL)
+ return ec_noName;
+ if ((NSS_GetAlgorithmPolicy(oidData->offset, &policyFlags) ==
+ SECSuccess) &&
+ !(policyFlags & NSS_USE_ALG_IN_SSL_KX)) {
+ return ec_noName;
+ }
for (i = ec_noName + 1; i < ec_pastLastName; i++) {
if (ecName2OIDTag[i] == oidData->offset)
return i;
@@ -219,19 +237,19 @@ ssl3_ComputeECDHKeyHash(SSLHashType hashAlg,
SSL3Random *client_rand, SSL3Random *server_rand,
SSL3Hashes *hashes, PRBool bypassPKCS11)
{
- PRUint8 * hashBuf;
- PRUint8 * pBuf;
- SECStatus rv = SECSuccess;
- unsigned int bufLen;
+ PRUint8 *hashBuf;
+ PRUint8 *pBuf;
+ SECStatus rv = SECSuccess;
+ unsigned int bufLen;
/*
* XXX For now, we only support named curves (the appropriate
* checks are made before this method is called) so ec_params
* takes up only two bytes. ECPoint needs to fit in 256 bytes
* (because the spec says the length must fit in one byte)
*/
- PRUint8 buf[2*SSL3_RANDOM_LENGTH + 2 + 1 + 256];
+ PRUint8 buf[2 * SSL3_RANDOM_LENGTH + 2 + 1 + 256];
- bufLen = 2*SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len;
+ bufLen = 2 * SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len;
if (bufLen <= sizeof buf) {
hashBuf = buf;
} else {
@@ -242,15 +260,15 @@ ssl3_ComputeECDHKeyHash(SSLHashType hashAlg,
}
memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
- pBuf = hashBuf + SSL3_RANDOM_LENGTH;
+ pBuf = hashBuf + SSL3_RANDOM_LENGTH;
memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
- pBuf += SSL3_RANDOM_LENGTH;
+ pBuf += SSL3_RANDOM_LENGTH;
memcpy(pBuf, ec_params.data, ec_params.len);
- pBuf += ec_params.len;
+ pBuf += ec_params.len;
pBuf[0] = (PRUint8)(server_ecpoint.len);
pBuf += 1;
memcpy(pBuf, server_ecpoint.data, server_ecpoint.len);
- pBuf += server_ecpoint.len;
+ pBuf += server_ecpoint.len;
PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes,
@@ -258,29 +276,28 @@ ssl3_ComputeECDHKeyHash(SSLHashType hashAlg,
PRINT_BUF(95, (NULL, "ECDHkey hash: ", hashBuf, bufLen));
PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result",
- hashes->u.s.md5, MD5_LENGTH));
+ hashes->u.s.md5, MD5_LENGTH));
PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result",
- hashes->u.s.sha, SHA1_LENGTH));
+ hashes->u.s.sha, SHA1_LENGTH));
if (hashBuf != buf)
PORT_Free(hashBuf);
return rv;
}
-
/* Called from ssl3_SendClientKeyExchange(). */
SECStatus
-ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
+ssl3_SendECDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey)
{
- PK11SymKey * pms = NULL;
- SECStatus rv = SECFailure;
- PRBool isTLS, isTLS12;
- CK_MECHANISM_TYPE target;
- SECKEYPublicKey *pubKey = NULL; /* Ephemeral ECDH key */
- SECKEYPrivateKey *privKey = NULL; /* Ephemeral ECDH key */
+ PK11SymKey *pms = NULL;
+ SECStatus rv = SECFailure;
+ PRBool isTLS, isTLS12;
+ CK_MECHANISM_TYPE target;
+ SECKEYPublicKey *pubKey = NULL; /* Ephemeral ECDH key */
+ SECKEYPrivateKey *privKey = NULL; /* Ephemeral ECDH key */
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
@@ -294,13 +311,13 @@ ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams,
&pubKey, ss->pkcs11PinArg);
if (!privKey || !pubKey) {
- ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
- rv = SECFailure;
- goto loser;
+ ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
+ rv = SECFailure;
+ goto loser;
}
PRINT_BUF(50, (ss, "ECDH public value:",
- pubKey->u.ec.publicValue.data,
- pubKey->u.ec.publicValue.len));
+ pubKey->u.ec.publicValue.data,
+ pubKey->u.ec.publicValue.len));
if (isTLS12) {
target = CKM_TLS12_MASTER_KEY_DERIVE_DH;
@@ -312,11 +329,11 @@ ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
/* Determine the PMS */
pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL,
- CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
- CKD_NULL, NULL, NULL);
+ CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
+ CKD_NULL, NULL, NULL);
if (pms == NULL) {
- SSL3AlertDescription desc = illegal_parameter;
+ SSL3AlertDescription desc = illegal_parameter;
(void)SSL3_SendAlert(ss, alert_fatal, desc);
ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
goto loser;
@@ -326,23 +343,24 @@ ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
privKey = NULL;
rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
- pubKey->u.ec.publicValue.len + 1);
+ pubKey->u.ec.publicValue.len + 1);
if (rv != SECSuccess) {
- goto loser; /* err set by ssl3_AppendHandshake* */
+ goto loser; /* err set by ssl3_AppendHandshake* */
}
rv = ssl3_AppendHandshakeVariable(ss,
- pubKey->u.ec.publicValue.data,
- pubKey->u.ec.publicValue.len, 1);
+ pubKey->u.ec.publicValue.data,
+ pubKey->u.ec.publicValue.len, 1);
SECKEY_DestroyPublicKey(pubKey);
pubKey = NULL;
if (rv != SECSuccess) {
- goto loser; /* err set by ssl3_AppendHandshake* */
+ goto loser; /* err set by ssl3_AppendHandshake* */
}
- rv = ssl3_InitPendingCipherSpec(ss, pms);
- PK11_FreeSymKey(pms); pms = NULL;
+ rv = ssl3_InitPendingCipherSpec(ss, pms);
+ PK11_FreeSymKey(pms);
+ pms = NULL;
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
@@ -352,30 +370,63 @@ ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
rv = SECSuccess;
loser:
- if(pms) PK11_FreeSymKey(pms);
- if(privKey) SECKEY_DestroyPrivateKey(privKey);
- if(pubKey) SECKEY_DestroyPublicKey(pubKey);
+ if (pms)
+ PK11_FreeSymKey(pms);
+ if (privKey)
+ SECKEY_DestroyPrivateKey(privKey);
+ if (pubKey)
+ SECKEY_DestroyPublicKey(pubKey);
return rv;
}
+ECName
+tls13_GroupForECDHEKeyShare(ssl3KeyPair *pair)
+{
+ return ssl3_PubKey2ECName(pair->pubKey);
+}
+
+/* This function returns the size of the key_exchange field in
+ * the KeyShareEntry structure. */
+unsigned int
+tls13_SizeOfECDHEKeyShareKEX(ssl3KeyPair *pair)
+{
+ return 1 + /* Length */
+ pair->pubKey->u.ec.publicValue.len;
+}
+
+/* This function encodes the key_exchange field in
+ * the KeyShareEntry structure. */
+SECStatus
+tls13_EncodeECDHEKeyShareKEX(sslSocket *ss, ssl3KeyPair *pair)
+{
+ const SECItem *publicValue;
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+
+ publicValue = &pair->pubKey->u.ec.publicValue;
+
+ return ssl3_AppendHandshakeVariable(ss, publicValue->data,
+ publicValue->len, 1);
+}
/*
** Called from ssl3_HandleClientKeyExchange()
*/
SECStatus
ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
- PRUint32 length,
- SECKEYPublicKey *srvrPubKey,
- SECKEYPrivateKey *srvrPrivKey)
+ PRUint32 length,
+ SECKEYPublicKey *srvrPubKey,
+ SECKEYPrivateKey *srvrPrivKey)
{
- PK11SymKey * pms;
- SECStatus rv;
- SECKEYPublicKey clntPubKey;
- CK_MECHANISM_TYPE target;
+ PK11SymKey *pms;
+ SECStatus rv;
+ SECKEYPublicKey clntPubKey;
+ CK_MECHANISM_TYPE target;
PRBool isTLS, isTLS12;
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
clntPubKey.keyType = ecKey;
clntPubKey.u.ec.DEREncodedParams.len =
@@ -387,7 +438,7 @@ ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
1, &b, &length);
if (rv != SECSuccess) {
SEND_ALERT
- return SECFailure; /* XXX Who sets the error code?? */
+ return SECFailure; /* XXX Who sets the error code?? */
}
isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
@@ -403,8 +454,8 @@ ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
/* Determine the PMS */
pms = PK11_PubDeriveWithKDF(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL,
- CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
- CKD_NULL, NULL, NULL);
+ CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
+ CKD_NULL, NULL, NULL);
if (pms == NULL) {
/* last gasp. */
@@ -412,7 +463,7 @@ ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
return SECFailure;
}
- rv = ssl3_InitPendingCipherSpec(ss, pms);
+ rv = ssl3_InitPendingCipherSpec(ss, pms);
PK11_FreeSymKey(pms);
if (rv != SECSuccess) {
SEND_ALERT
@@ -421,12 +472,102 @@ ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
return SECSuccess;
}
+/*
+** Take an encoded key share and make a public key out of it.
+** returns NULL on error.
+*/
+SECKEYPublicKey *
+tls13_ImportECDHKeyShare(sslSocket *ss, SSL3Opaque *b,
+ PRUint32 length, ECName curve)
+{
+ PLArenaPool *arena = NULL;
+ SECKEYPublicKey *peerKey = NULL;
+ SECStatus rv;
+ SECItem ecPoint = { siBuffer, NULL, 0 };
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ rv = ssl3_ConsumeHandshakeVariable(ss, &ecPoint, 1, &b, &length);
+ if (rv != SECSuccess) {
+ tls13_FatalError(ss, SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE,
+ illegal_parameter);
+ return NULL;
+ }
+ if (length || !ecPoint.len) {
+ tls13_FatalError(ss, SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE,
+ illegal_parameter);
+ return NULL;
+ }
+
+ /* Fail if the ec point uses compressed representation */
+ if (ecPoint.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
+ tls13_FatalError(ss, SEC_ERROR_UNSUPPORTED_EC_POINT_FORM,
+ illegal_parameter);
+ return NULL;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ goto no_memory;
+ }
+
+ peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
+ if (peerKey == NULL) {
+ goto no_memory;
+ }
+
+ peerKey->arena = arena;
+ peerKey->keyType = ecKey;
+ /* Set up the encoded params */
+ rv = ssl3_ECName2Params(arena, curve, &peerKey->u.ec.DEREncodedParams);
+ if (rv != SECSuccess) {
+ goto no_memory;
+ }
+
+ /* copy publicValue in peerKey */
+ if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ecPoint) !=
+ SECSuccess) {
+ goto no_memory;
+ }
+ peerKey->pkcs11Slot = NULL;
+ peerKey->pkcs11ID = CK_INVALID_HANDLE;
+
+ return peerKey;
+
+no_memory: /* no-memory error has already been set. */
+ PORT_FreeArena(arena, PR_FALSE);
+ ssl_MapLowLevelError(SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE);
+ return NULL;
+}
+
+PK11SymKey *
+tls13_ComputeECDHSharedKey(sslSocket *ss,
+ SECKEYPrivateKey *myPrivKey,
+ SECKEYPublicKey *peerKey)
+{
+ PK11SymKey *shared;
+
+ /* Determine the PMS */
+ shared = PK11_PubDeriveWithKDF(myPrivKey, peerKey, PR_FALSE, NULL, NULL,
+ CKM_ECDH1_DERIVE,
+ tls13_GetHkdfMechanism(ss), CKA_DERIVE, 0,
+ CKD_NULL, NULL, NULL);
+
+ if (!shared) {
+ ssl_MapLowLevelError(SSL_ERROR_KEY_EXCHANGE_FAILURE);
+ return NULL;
+ }
+
+ return shared;
+}
+
ECName
ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits)
{
- int i;
+ int i;
- for ( i = 0; bits2curve[i].curve != ec_noName; i++) {
+ for (i = 0; bits2curve[i].curve != ec_noName; i++) {
if (bits2curve[i].bits < requiredECCbits)
continue;
if (SSL_IS_CURVE_NEGOTIATED(curvemsk, bits2curve[i].curve)) {
@@ -443,20 +584,20 @@ ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits)
ECName
ssl3_GetCurveNameForServerSocket(sslSocket *ss)
{
- SECKEYPublicKey * svrPublicKey = NULL;
+ SECKEYPublicKey *svrPublicKey = NULL;
ECName ec_curve = ec_noName;
- int signatureKeyStrength = 521;
- int requiredECCbits = ss->sec.secretKeyBits * 2;
+ int signatureKeyStrength = 521;
+ int requiredECCbits = ss->sec.secretKeyBits * 2;
if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa) {
svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_ecdh);
if (svrPublicKey)
- ec_curve = params2ecName(&svrPublicKey->u.ec.DEREncodedParams);
+ ec_curve = ssl3_PubKey2ECName(svrPublicKey);
if (!SSL_IS_CURVE_NEGOTIATED(ss->ssl3.hs.negotiatedECCurves, ec_curve)) {
PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
return ec_noName;
}
- signatureKeyStrength = curve2bits[ ec_curve ];
+ signatureKeyStrength = curve2bits[ec_curve];
} else {
/* RSA is our signing cert */
int serverKeyStrengthInBits;
@@ -478,8 +619,8 @@ ssl3_GetCurveNameForServerSocket(sslSocket *ss)
signatureKeyStrength =
SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
}
- if ( requiredECCbits > signatureKeyStrength )
- requiredECCbits = signatureKeyStrength;
+ if (requiredECCbits > signatureKeyStrength)
+ requiredECCbits = signatureKeyStrength;
return ssl3_GetCurveWithECKeyStrength(ss->ssl3.hs.negotiatedECCurves,
requiredECCbits);
@@ -492,7 +633,7 @@ ssl3_ShutdownECDHECurves(void *appData, void *nssData)
int i;
ECDHEKeyPair *keyPair = &gECDHEKeyPairs[0];
- for (i=0; i < ec_pastLastName; i++, keyPair++) {
+ for (i = 0; i < ec_pastLastName; i++, keyPair++) {
if (keyPair->pair) {
ssl3_FreeKeyPair(keyPair->pair);
}
@@ -513,12 +654,12 @@ ssl3_ECRegister(void)
}
/* Create an ECDHE key pair for a given curve */
-static SECStatus
-ssl3_CreateECDHEphemeralKeyPair(ECName ec_curve, ssl3KeyPair** keyPair)
+SECStatus
+ssl3_CreateECDHEphemeralKeyPair(ECName ec_curve, ssl3KeyPair **keyPair)
{
- SECKEYPrivateKey * privKey = NULL;
- SECKEYPublicKey * pubKey = NULL;
- SECKEYECParams ecParams = { siBuffer, NULL, 0 };
+ SECKEYPrivateKey *privKey = NULL;
+ SECKEYPublicKey *pubKey = NULL;
+ SECKEYECParams ecParams = { siBuffer, NULL, 0 };
if (ssl3_ECName2Params(NULL, ec_curve, &ecParams) != SECSuccess) {
return SECFailure;
@@ -542,10 +683,10 @@ ssl3_CreateECDHEphemeralKeyPair(ECName ec_curve, ssl3KeyPair** keyPair)
/* CallOnce function, called once for each named curve. */
static PRStatus
-ssl3_CreateECDHEphemeralKeyPairOnce(void * arg)
+ssl3_CreateECDHEphemeralKeyPairOnce(void *arg)
{
- ECName ec_curve = (ECName)arg;
- ssl3KeyPair * keyPair = NULL;
+ ECName ec_curve = (ECName)arg;
+ ssl3KeyPair *keyPair = NULL;
PORT_Assert(gECDHEKeyPairs[ec_curve].pair == NULL);
@@ -571,7 +712,7 @@ ssl3_CreateECDHEphemeralKeyPairOnce(void * arg)
static SECStatus
ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve)
{
- ssl3KeyPair * keyPair = NULL;
+ ssl3KeyPair *keyPair = NULL;
/* if there's no global key for this curve, make one. */
if (gECDHEKeyPairs[ec_curve].pair == NULL) {
@@ -603,18 +744,18 @@ ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve)
SECStatus
ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
- PLArenaPool * arena = NULL;
- SECKEYPublicKey *peerKey = NULL;
- PRBool isTLS, isTLS12;
- SECStatus rv;
- int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
- SSL3AlertDescription desc = illegal_parameter;
- SSL3Hashes hashes;
- SECItem signature = {siBuffer, NULL, 0};
-
- SECItem ec_params = {siBuffer, NULL, 0};
- SECItem ec_point = {siBuffer, NULL, 0};
- unsigned char paramBuf[3]; /* only for curve_type == named_curve */
+ PLArenaPool *arena = NULL;
+ SECKEYPublicKey *peerKey = NULL;
+ PRBool isTLS, isTLS12;
+ SECStatus rv;
+ int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
+ SSL3AlertDescription desc = illegal_parameter;
+ SSL3Hashes hashes;
+ SECItem signature = { siBuffer, NULL, 0 };
+
+ SECItem ec_params = { siBuffer, NULL, 0 };
+ SECItem ec_point = { siBuffer, NULL, 0 };
+ unsigned char paramBuf[3]; /* only for curve_type == named_curve */
SSLSignatureAndHashAlg sigAndHash;
sigAndHash.hashAlg = ssl_hash_none;
@@ -625,38 +766,38 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
/* XXX This works only for named curves, revisit this when
* we support generic curves.
*/
- ec_params.len = sizeof paramBuf;
+ ec_params.len = sizeof paramBuf;
ec_params.data = paramBuf;
rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length);
if (rv != SECSuccess) {
- goto loser; /* malformed. */
+ goto loser; /* malformed. */
}
/* Fail if the curve is not a named curve */
if ((ec_params.data[0] != ec_type_named) ||
(ec_params.data[1] != 0) ||
!supportedCurve(ec_params.data[2])) {
- errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
- desc = handshake_failure;
- goto alert_loser;
+ errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
+ desc = handshake_failure;
+ goto alert_loser;
}
rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length);
if (rv != SECSuccess) {
- goto loser; /* malformed. */
+ goto loser; /* malformed. */
}
/* Fail if the ec point uses compressed representation */
if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
- errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM;
- desc = handshake_failure;
- goto alert_loser;
+ errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM;
+ desc = handshake_failure;
+ goto alert_loser;
}
if (isTLS12) {
rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
&sigAndHash);
if (rv != SECSuccess) {
- goto loser; /* malformed or unsupported. */
+ goto loser; /* malformed or unsupported. */
}
rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
ss, &sigAndHash, ss->sec.peerCert);
@@ -667,17 +808,17 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
if (rv != SECSuccess) {
- goto loser; /* malformed. */
+ goto loser; /* malformed. */
}
if (length != 0) {
if (isTLS)
desc = decode_error;
- goto alert_loser; /* malformed. */
+ goto alert_loser; /* malformed. */
}
PRINT_BUF(60, (NULL, "Server EC params", ec_params.data,
- ec_params.len));
+ ec_params.len));
PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len));
/* failures after this point are not malformed handshakes. */
@@ -698,8 +839,8 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
goto alert_loser;
}
rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
- isTLS, ss->pkcs11PinArg);
- if (rv != SECSuccess) {
+ isTLS, ss->pkcs11PinArg);
+ if (rv != SECSuccess) {
errCode =
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
goto alert_loser;
@@ -715,12 +856,13 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
goto no_memory;
}
- peerKey->arena = arena;
- peerKey->keyType = ecKey;
+ peerKey->arena = arena;
+ peerKey->keyType = ecKey;
/* set up EC parameters in peerKey */
if (ssl3_ECName2Params(arena, ec_params.data[2],
- &peerKey->u.ec.DEREncodedParams) != SECSuccess) {
+ &peerKey->u.ec.DEREncodedParams) !=
+ SECSuccess) {
/* we should never get here since we already
* checked that we are dealing with a supported curve
*/
@@ -729,12 +871,11 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
}
/* copy publicValue in peerKey */
- if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ec_point))
- {
+ if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ec_point)) {
goto no_memory;
}
- peerKey->pkcs11Slot = NULL;
- peerKey->pkcs11ID = CK_INVALID_HANDLE;
+ peerKey->pkcs11Slot = NULL;
+ peerKey->pkcs11ID = CK_INVALID_HANDLE;
ss->sec.peerKey = peerKey;
ss->ssl3.hs.ws = wait_cert_request;
@@ -747,10 +888,10 @@ loser:
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
}
- PORT_SetError( errCode );
+ PORT_SetError(errCode);
return SECFailure;
-no_memory: /* no-memory error has already been set. */
+no_memory: /* no-memory error has already been set. */
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
}
@@ -763,18 +904,18 @@ ssl3_SendECDHServerKeyExchange(
sslSocket *ss,
const SSLSignatureAndHashAlg *sigAndHash)
{
- const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def;
- SECStatus rv = SECFailure;
- int length;
- PRBool isTLS, isTLS12;
- SECItem signed_hash = {siBuffer, NULL, 0};
- SSL3Hashes hashes;
-
- SECKEYPublicKey * ecdhePub;
- SECItem ec_params = {siBuffer, NULL, 0};
- unsigned char paramBuf[3];
- ECName curve;
- SSL3KEAType certIndex;
+ const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
+ SECStatus rv = SECFailure;
+ int length;
+ PRBool isTLS, isTLS12;
+ SECItem signed_hash = { siBuffer, NULL, 0 };
+ SSL3Hashes hashes;
+
+ SECKEYPublicKey *ecdhePub;
+ SECItem ec_params = { siBuffer, NULL, 0 };
+ unsigned char paramBuf[3];
+ ECName curve;
+ SSL3KEAType certIndex;
/* Generate ephemeral ECDH key pair and send the public key */
curve = ssl3_GetCurveNameForServerSocket(ss);
@@ -798,9 +939,9 @@ ssl3_SendECDHServerKeyExchange(
return SECFailure;
}
- ec_params.len = sizeof paramBuf;
+ ec_params.len = sizeof paramBuf;
ec_params.data = paramBuf;
- curve = params2ecName(&ecdhePub->u.ec.DEREncodedParams);
+ curve = ssl3_PubKey2ECName(ecdhePub);
if (curve != ec_noName) {
ec_params.data[0] = ec_type_named;
ec_params.data[1] = 0x00;
@@ -836,7 +977,7 @@ ssl3_SendECDHServerKeyExchange(
rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY,
&signed_hash, isTLS);
if (rv != SECSuccess) {
- goto loser; /* ssl3_SignHashes has set err. */
+ goto loser; /* ssl3_SignHashes has set err. */
}
if (signed_hash.data == NULL) {
/* how can this happen and rv == SECSuccess ?? */
@@ -850,31 +991,31 @@ ssl3_SendECDHServerKeyExchange(
rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
+ goto loser; /* err set by AppendHandshake. */
}
rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len);
if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
+ goto loser; /* err set by AppendHandshake. */
}
rv = ssl3_AppendHandshakeVariable(ss, ecdhePub->u.ec.publicValue.data,
ecdhePub->u.ec.publicValue.len, 1);
if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
+ goto loser; /* err set by AppendHandshake. */
}
if (isTLS12) {
rv = ssl3_AppendSignatureAndHashAlgorithm(ss, sigAndHash);
if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
+ goto loser; /* err set by AppendHandshake. */
}
}
rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
signed_hash.len, 2);
if (rv != SECSuccess) {
- goto loser; /* err set by AppendHandshake. */
+ goto loser; /* err set by AppendHandshake. */
}
PORT_Free(signed_hash.data);
@@ -926,7 +1067,7 @@ static const ssl3CipherSuite ecdhe_ecdsa_suites[] = {
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
TLS_ECDHE_ECDSA_WITH_NULL_SHA,
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
0 /* end of list marker */
@@ -938,7 +1079,7 @@ static const ssl3CipherSuite ecdhe_rsa_suites[] = {
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
TLS_ECDHE_RSA_WITH_NULL_SHA,
TLS_ECDHE_RSA_WITH_RC4_128_SHA,
0 /* end of list marker */
@@ -951,7 +1092,7 @@ static const ssl3CipherSuite ecSuites[] = {
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
TLS_ECDHE_ECDSA_WITH_NULL_SHA,
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
@@ -959,7 +1100,7 @@ static const ssl3CipherSuite ecSuites[] = {
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
TLS_ECDHE_RSA_WITH_NULL_SHA,
TLS_ECDHE_RSA_WITH_RC4_128_SHA,
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
@@ -977,7 +1118,7 @@ static const ssl3CipherSuite ecSuites[] = {
/* On this socket, Disable the ECC cipher suites in the argument's list */
SECStatus
-ssl3_DisableECCSuites(sslSocket * ss, const ssl3CipherSuite * suite)
+ssl3_DisableECCSuites(sslSocket *ss, const ssl3CipherSuite *suite)
{
if (!suite)
suite = ecSuites;
@@ -991,9 +1132,9 @@ ssl3_DisableECCSuites(sslSocket * ss, const ssl3CipherSuite * suite)
* ECC cipher suites that are not supported by those certs.
*/
void
-ssl3_FilterECCipherSuitesByServerCerts(sslSocket * ss)
+ssl3_FilterECCipherSuitesByServerCerts(sslSocket *ss)
{
- CERTCertificate * svrCert;
+ CERTCertificate *svrCert;
svrCert = ss->serverCerts[kt_rsa].serverCert;
if (!svrCert) {
@@ -1008,29 +1149,29 @@ ssl3_FilterECCipherSuitesByServerCerts(sslSocket * ss)
SECOidTag sigTag = SECOID_GetAlgorithmTag(&svrCert->signature);
switch (sigTag) {
- case SEC_OID_PKCS1_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
- ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
- break;
- case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
- case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
- case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
- case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
- case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
- case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
- case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
- ssl3_DisableECCSuites(ss, ecdh_rsa_suites);
- break;
- default:
- ssl3_DisableECCSuites(ss, ecdh_suites);
- break;
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
+ ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
+ break;
+ case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
+ case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
+ case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
+ case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
+ case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
+ case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
+ case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
+ ssl3_DisableECCSuites(ss, ecdh_rsa_suites);
+ break;
+ default:
+ ssl3_DisableECCSuites(ss, ecdh_suites);
+ break;
}
}
}
@@ -1038,13 +1179,13 @@ ssl3_FilterECCipherSuitesByServerCerts(sslSocket * ss)
/* Ask: is ANY ECC cipher suite enabled on this socket? */
/* Order(N^2). Yuk. Also, this ignores export policy. */
PRBool
-ssl3_IsECCEnabled(sslSocket * ss)
+ssl3_IsECCEnabled(sslSocket *ss)
{
- const ssl3CipherSuite * suite;
+ const ssl3CipherSuite *suite;
PK11SlotInfo *slot;
/* make sure we can do ECC */
- slot = PK11_GetBestSlot(CKM_ECDH1_DERIVE, ss->pkcs11PinArg);
+ slot = PK11_GetBestSlot(CKM_ECDH1_DERIVE, ss->pkcs11PinArg);
if (!slot) {
return PR_FALSE;
}
@@ -1052,8 +1193,8 @@ ssl3_IsECCEnabled(sslSocket * ss)
/* make sure an ECC cipher is enabled */
for (suite = ecSuites; *suite; ++suite) {
- PRBool enabled = PR_FALSE;
- SECStatus rv = ssl3_CipherPrefGet(ss, *suite, &enabled);
+ PRBool enabled = PR_FALSE;
+ SECStatus rv = ssl3_CipherPrefGet(ss, *suite, &enabled);
PORT_Assert(rv == SECSuccess); /* else is coding error */
if (rv == SECSuccess && enabled)
@@ -1067,31 +1208,27 @@ ssl3_IsECCEnabled(sslSocket * ss)
/* Prefabricated TLS client hello extension, Elliptic Curves List,
* offers only 3 curves, the Suite B curves, 23-25
*/
-static const PRUint8 suiteBECList[12] = {
- BE(10), /* Extension type */
- BE( 8), /* octets that follow ( 3 pairs + 1 length pair) */
- BE( 6), /* octets that follow ( 3 pairs) */
- BE(23), BE(24), BE(25)
+static const PRUint8 suiteBECList[] = {
+ 23, 24, 25
};
/* Prefabricated TLS client hello extension, Elliptic Curves List,
* offers curves 1-25.
*/
-static const PRUint8 tlsECList[56] = {
- BE(10), /* Extension type */
- BE(52), /* octets that follow (25 pairs + 1 length pair) */
- BE(50), /* octets that follow (25 pairs) */
- BE( 1), BE( 2), BE( 3), BE( 4), BE( 5), BE( 6), BE( 7),
- BE( 8), BE( 9), BE(10), BE(11), BE(12), BE(13), BE(14), BE(15),
- BE(16), BE(17), BE(18), BE(19), BE(20), BE(21), BE(22), BE(23),
- BE(24), BE(25)
+/* clang-format off */
+static const PRUint8 tlsECList[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25
};
+/* clang-format on */
static const PRUint8 ecPtFmt[6] = {
- BE(11), /* Extension type */
- BE( 2), /* octets that follow */
- 1, /* octets that follow */
- 0 /* uncompressed type only */
+ BE(11), /* Extension type */
+ BE(2), /* octets that follow */
+ 1, /* octets that follow */
+ 0 /* uncompressed type only */
};
/* This function already presumes we can do ECC, ssl3_IsECCEnabled must be
@@ -1103,7 +1240,6 @@ static const PRUint8 ecPtFmt[6] = {
static PRBool
ssl3_SuiteBOnly(sslSocket *ss)
{
-#if 0
/* See if we can support small curves (like 163). If not, assume we can
* only support Suite-B curves (P-256, P-384, P-521). */
PK11SlotInfo *slot =
@@ -1117,39 +1253,66 @@ ssl3_SuiteBOnly(sslSocket *ss)
/* we can, presume we can do all curves */
PK11_FreeSlot(slot);
return PR_FALSE;
-#else
- return PR_TRUE;
-#endif
}
+#define APPEND_CURVE(CURVE_ID) \
+ if ((NSS_GetAlgorithmPolicy(ecName2OIDTag[CURVE_ID], &policy) == \
+ SECFailure) || \
+ (policy & NSS_USE_ALG_IN_SSL_KX)) { \
+ enabledCurves[pos++] = 0; \
+ enabledCurves[pos++] = CURVE_ID; \
+ }
+
/* Send our "canned" (precompiled) Supported Elliptic Curves extension,
* which says that we support all TLS-defined named curves.
*/
PRInt32
ssl3_SendSupportedCurvesXtn(
- sslSocket * ss,
- PRBool append,
- PRUint32 maxBytes)
+ sslSocket *ss,
+ PRBool append,
+ PRUint32 maxBytes)
{
+ unsigned char enabledCurves[64];
+ PRUint32 policy;
+ PRInt32 extension_length;
PRInt32 ecListSize = 0;
- const PRUint8 *ecList = NULL;
+ unsigned int pos = 0;
+ unsigned int i;
if (!ss || !ssl3_IsECCEnabled(ss))
return 0;
+ PORT_Assert(sizeof(enabledCurves) > sizeof(tlsECList) * 2);
if (ssl3_SuiteBOnly(ss)) {
- ecListSize = sizeof suiteBECList;
- ecList = suiteBECList;
+ for (i = 0; i < sizeof(suiteBECList); i++) {
+ APPEND_CURVE(suiteBECList[i]);
+ }
+ ecListSize = pos;
} else {
- ecListSize = sizeof tlsECList;
- ecList = tlsECList;
+ for (i = 0; i < sizeof(tlsECList); i++) {
+ APPEND_CURVE(tlsECList[i]);
+ }
+ ecListSize = pos;
}
+ extension_length =
+ 2 /* extension type */ +
+ 2 /* extension length */ +
+ 2 /* elliptic curves length */ +
+ ecListSize;
- if (maxBytes < (PRUint32)ecListSize) {
+ if (maxBytes < (PRUint32)extension_length) {
return 0;
}
+
if (append) {
- SECStatus rv = ssl3_AppendHandshake(ss, ecList, ecListSize);
+ SECStatus rv;
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_elliptic_curves_xtn, 2);
+ if (rv != SECSuccess)
+ return -1;
+ rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
+ if (rv != SECSuccess)
+ return -1;
+ rv = ssl3_AppendHandshakeVariable(ss, enabledCurves, ecListSize, 2);
if (rv != SECSuccess)
return -1;
if (!ss->sec.isServer) {
@@ -1158,16 +1321,34 @@ ssl3_SendSupportedCurvesXtn(
ssl_elliptic_curves_xtn;
}
}
- return ecListSize;
+ return extension_length;
}
PRUint32
ssl3_GetSupportedECCurveMask(sslSocket *ss)
{
+ int i;
+ PRUint32 curves = 0;
+ PRUint32 policyFlags = 0;
+
+ PORT_Assert(ec_pastLastName < sizeof(PRUint32) * 8);
+
if (ssl3_SuiteBOnly(ss)) {
- return SSL3_SUITE_B_SUPPORTED_CURVES_MASK;
+ curves = SSL3_SUITE_B_SUPPORTED_CURVES_MASK;
+ } else {
+ curves = SSL3_ALL_SUPPORTED_CURVES_MASK;
}
- return SSL3_ALL_SUPPORTED_CURVES_MASK;
+
+ for (i = ec_noName + 1; i < ec_pastLastName; i++) {
+ PRUint32 curve_bit = (1U << i);
+ if ((curves & curve_bit) &&
+ (NSS_GetAlgorithmPolicy(ecName2OIDTag[i], &policyFlags) ==
+ SECSuccess) &&
+ !(policyFlags & NSS_USE_ALG_IN_SSL_KX)) {
+ curves &= ~curve_bit;
+ }
+ }
+ return curves;
}
/* Send our "canned" (precompiled) Supported Point Formats extension,
@@ -1175,9 +1356,9 @@ ssl3_GetSupportedECCurveMask(sslSocket *ss)
*/
PRInt32
ssl3_SendSupportedPointFormatsXtn(
- sslSocket * ss,
- PRBool append,
- PRUint32 maxBytes)
+ sslSocket *ss,
+ PRBool append,
+ PRUint32 maxBytes)
{
if (!ss || !ssl3_IsECCEnabled(ss))
return 0;
@@ -1207,12 +1388,12 @@ ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss, PRUint16 ex_type,
data->len != (unsigned int)data->data[0] + 1) {
return ssl3_DecodeError(ss);
}
- for (i = data->len; --i > 0; ) {
+ for (i = data->len; --i > 0;) {
if (data->data[i] == 0) {
/* indicate that we should send a reply */
SECStatus rv;
rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
- &ssl3_SendSupportedPointFormatsXtn);
+ &ssl3_SendSupportedPointFormatsXtn);
return rv;
}
}
@@ -1222,20 +1403,20 @@ ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss, PRUint16 ex_type,
return SECSuccess;
}
-
-#define SSL3_GET_SERVER_PUBLICKEY(sock, type) \
- (ss->serverCerts[type].serverKeyPair ? \
- ss->serverCerts[type].serverKeyPair->pubKey : NULL)
+#define SSL3_GET_SERVER_PUBLICKEY(sock, type) \
+ (ss->serverCerts[type].serverKeyPair ? ss->serverCerts[type].serverKeyPair->pubKey \
+ : NULL)
/* Extract the TLS curve name for the public key in our EC server cert. */
-ECName ssl3_GetSvrCertCurveName(sslSocket *ss)
+ECName
+ssl3_GetSvrCertCurveName(sslSocket *ss)
{
- SECKEYPublicKey *srvPublicKey;
- ECName ec_curve = ec_noName;
+ SECKEYPublicKey *srvPublicKey;
+ ECName ec_curve = ec_noName;
srvPublicKey = SSL3_GET_SERVER_PUBLICKEY(ss, kt_ecdh);
if (srvPublicKey) {
- ec_curve = params2ecName(&srvPublicKey->u.ec.DEREncodedParams);
+ ec_curve = ssl3_PubKey2ECName(srvPublicKey);
}
return ec_curve;
}
@@ -1246,8 +1427,8 @@ ECName ssl3_GetSvrCertCurveName(sslSocket *ss)
SECStatus
ssl3_HandleSupportedCurvesXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
{
- PRInt32 list_len;
- PRUint32 peerCurves = 0;
+ PRInt32 list_len;
+ PRUint32 peerCurves = 0;
PRUint32 mutualCurves = 0;
PRUint16 svrCertCurveName;
@@ -1265,7 +1446,7 @@ ssl3_HandleSupportedCurvesXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
/* build bit vector of peer's supported curve names */
while (data->len) {
PRInt32 curve_name =
- ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
+ ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
if (curve_name < 0) {
return SECFailure; /* fatal alert already sent */
}
diff --git a/chromium/net/third_party/nss/ssl/ssl3ext.c b/chromium/net/third_party/nss/ssl/ssl3ext.c
index eb3fb70f280..3b48c9e0aad 100644
--- a/chromium/net/third_party/nss/ssl/ssl3ext.c
+++ b/chromium/net/third_party/nss/ssl/ssl3ext.c
@@ -11,8 +11,8 @@
#include "nssrenam.h"
#include "nss.h"
#include "ssl.h"
-#include "sslimpl.h"
#include "sslproto.h"
+#include "sslimpl.h"
#include "pk11pub.h"
#ifdef NO_PKCS11_BYPASS
#include "blapit.h"
@@ -21,42 +21,42 @@
#endif
#include "prinit.h"
-static unsigned char key_name[SESS_TICKET_KEY_NAME_LEN];
-static PK11SymKey *session_ticket_enc_key_pkcs11 = NULL;
-static PK11SymKey *session_ticket_mac_key_pkcs11 = NULL;
+static unsigned char key_name[SESS_TICKET_KEY_NAME_LEN];
+static PK11SymKey *session_ticket_enc_key_pkcs11 = NULL;
+static PK11SymKey *session_ticket_mac_key_pkcs11 = NULL;
#ifndef NO_PKCS11_BYPASS
-static unsigned char session_ticket_enc_key[AES_256_KEY_LENGTH];
-static unsigned char session_ticket_mac_key[SHA256_LENGTH];
+static unsigned char session_ticket_enc_key[AES_256_KEY_LENGTH];
+static unsigned char session_ticket_mac_key[SHA256_LENGTH];
-static PRBool session_ticket_keys_initialized = PR_FALSE;
+static PRBool session_ticket_keys_initialized = PR_FALSE;
#endif
static PRCallOnceType generate_session_keys_once;
/* forward static function declarations */
static SECStatus ssl3_ParseEncryptedSessionTicket(sslSocket *ss,
- SECItem *data, EncryptedSessionTicket *enc_session_ticket);
+ SECItem *data, EncryptedSessionTicket *enc_session_ticket);
static SECStatus ssl3_AppendToItem(SECItem *item, const unsigned char *buf,
- PRUint32 bytes);
+ PRUint32 bytes);
static SECStatus ssl3_AppendNumberToItem(SECItem *item, PRUint32 num,
- PRInt32 lenSize);
+ PRInt32 lenSize);
static SECStatus ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss,
- PK11SymKey **aes_key, PK11SymKey **mac_key);
+ PK11SymKey **aes_key, PK11SymKey **mac_key);
#ifndef NO_PKCS11_BYPASS
static SECStatus ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
- PRUint32 *aes_key_length, const unsigned char **mac_key,
- PRUint32 *mac_key_length);
+ PRUint32 *aes_key_length, const unsigned char **mac_key,
+ PRUint32 *mac_key_length);
#endif
-static PRInt32 ssl3_SendRenegotiationInfoXtn(sslSocket * ss,
- PRBool append, PRUint32 maxBytes);
+static PRInt32 ssl3_SendRenegotiationInfoXtn(sslSocket *ss,
+ PRBool append, PRUint32 maxBytes);
static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss,
- PRUint16 ex_type, SECItem *data);
+ PRUint16 ex_type, SECItem *data);
static SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss,
- PRUint16 ex_type, SECItem *data);
+ PRUint16 ex_type, SECItem *data);
static SECStatus ssl3_ClientHandleAppProtoXtn(sslSocket *ss,
- PRUint16 ex_type, SECItem *data);
+ PRUint16 ex_type, SECItem *data);
static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss,
- PRUint16 ex_type, SECItem *data);
+ PRUint16 ex_type, SECItem *data);
static SECStatus ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data);
static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
@@ -69,34 +69,40 @@ static PRInt32 ssl3_ClientSendUseSRTPXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
static PRInt32 ssl3_ServerSendUseSRTPXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
-static SECStatus ssl3_ClientHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type,
+static SECStatus ssl3_ClientHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data);
-static SECStatus ssl3_ServerHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type,
+static SECStatus ssl3_ServerHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data);
static SECStatus ssl3_ClientHandleChannelIDXtn(sslSocket *ss,
- PRUint16 ex_type, SECItem *data);
+ PRUint16 ex_type, SECItem *data);
static PRInt32 ssl3_ClientSendChannelIDXtn(sslSocket *ss, PRBool append,
- PRUint32 maxBytes);
-static PRInt32 ssl3_ServerSendStatusRequestXtn(sslSocket * ss,
- PRBool append, PRUint32 maxBytes);
+ PRUint32 maxBytes);
+static PRInt32 ssl3_ServerSendStatusRequestXtn(sslSocket *ss,
+ PRBool append, PRUint32 maxBytes);
static SECStatus ssl3_ServerHandleStatusRequestXtn(sslSocket *ss,
- PRUint16 ex_type, SECItem *data);
+ PRUint16 ex_type, SECItem *data);
static SECStatus ssl3_ClientHandleStatusRequestXtn(sslSocket *ss,
PRUint16 ex_type,
SECItem *data);
-static PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append,
+static PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
static PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
static SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data);
+
static PRInt32 ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss,
PRBool append,
PRUint32 maxBytes);
static SECStatus ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss,
PRUint16 ex_type,
SECItem *data);
-
+static PRInt32 ssl3_ServerSendSignedCertTimestampXtn(sslSocket *ss,
+ PRBool append,
+ PRUint32 maxBytes);
+static SECStatus ssl3_ServerHandleSignedCertTimestampXtn(sslSocket *ss,
+ PRUint16 ex_type,
+ SECItem *data);
static PRInt32 ssl3_ClientSendDraftVersionXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
static SECStatus ssl3_ServerHandleDraftVersionXtn(sslSocket *ss, PRUint16 ex_type,
@@ -106,7 +112,14 @@ static PRInt32 ssl3_SendExtendedMasterSecretXtn(sslSocket *ss, PRBool append,
static SECStatus ssl3_HandleExtendedMasterSecretXtn(sslSocket *ss,
PRUint16 ex_type,
SECItem *data);
-
+static PRInt32 tls13_ClientSendKeyShareXtn(sslSocket *ss, PRBool append,
+ PRUint32 maxBytes);
+static SECStatus tls13_ClientHandleKeyShareXtn(sslSocket *ss,
+ PRUint16 ex_type,
+ SECItem *data);
+static SECStatus tls13_ServerHandleKeyShareXtn(sslSocket *ss,
+ PRUint16 ex_type,
+ SECItem *data);
/*
* Write bytes. Using this function means the SECItem structure
@@ -134,24 +147,25 @@ static SECStatus
ssl3_AppendNumberToItem(SECItem *item, PRUint32 num, PRInt32 lenSize)
{
SECStatus rv;
- PRUint8 b[4];
- PRUint8 * p = b;
+ PRUint8 b[4];
+ PRUint8 *p = b;
switch (lenSize) {
- case 4:
- *p++ = (PRUint8) (num >> 24);
- case 3:
- *p++ = (PRUint8) (num >> 16);
- case 2:
- *p++ = (PRUint8) (num >> 8);
- case 1:
- *p = (PRUint8) num;
+ case 4:
+ *p++ = (PRUint8)(num >> 24);
+ case 3:
+ *p++ = (PRUint8)(num >> 16);
+ case 2:
+ *p++ = (PRUint8)(num >> 8);
+ case 1:
+ *p = (PRUint8)num;
}
rv = ssl3_AppendToItem(item, &b[0], lenSize);
return rv;
}
-static SECStatus ssl3_SessionTicketShutdown(void* appData, void* nssData)
+static SECStatus
+ssl3_SessionTicketShutdown(void *appData, void *nssData)
{
if (session_ticket_enc_key_pkcs11) {
PK11_FreeSymKey(session_ticket_enc_key_pkcs11);
@@ -162,11 +176,10 @@ static SECStatus ssl3_SessionTicketShutdown(void* appData, void* nssData)
session_ticket_mac_key_pkcs11 = NULL;
}
PORT_Memset(&generate_session_keys_once, 0,
- sizeof(generate_session_keys_once));
+ sizeof(generate_session_keys_once));
return SECSuccess;
}
-
static PRStatus
ssl3_GenerateSessionTicketKeysPKCS11(void *data)
{
@@ -177,16 +190,16 @@ ssl3_GenerateSessionTicketKeysPKCS11(void *data)
if (svrPrivKey == NULL || svrPubKey == NULL) {
SSL_DBG(("%d: SSL[%d]: Pub or priv key(s) is NULL.",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
goto loser;
}
/* Get a copy of the session keys from shared memory. */
PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX,
- sizeof(SESS_TICKET_KEY_NAME_PREFIX));
+ sizeof(SESS_TICKET_KEY_NAME_PREFIX));
if (!ssl_GetSessionTicketKeysPKCS11(svrPrivKey, svrPubKey,
- ss->pkcs11PinArg, &key_name[SESS_TICKET_KEY_NAME_PREFIX_LEN],
- &session_ticket_enc_key_pkcs11, &session_ticket_mac_key_pkcs11))
+ ss->pkcs11PinArg, &key_name[SESS_TICKET_KEY_NAME_PREFIX_LEN],
+ &session_ticket_enc_key_pkcs11, &session_ticket_mac_key_pkcs11))
return PR_FAILURE;
rv = NSS_RegisterShutdown(ssl3_SessionTicketShutdown, NULL);
@@ -205,7 +218,8 @@ ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss, PK11SymKey **aes_key,
PK11SymKey **mac_key)
{
if (PR_CallOnceWithArg(&generate_session_keys_once,
- ssl3_GenerateSessionTicketKeysPKCS11, ss) != PR_SUCCESS)
+ ssl3_GenerateSessionTicketKeysPKCS11, ss) !=
+ PR_SUCCESS)
return SECFailure;
if (session_ticket_enc_key_pkcs11 == NULL ||
@@ -222,10 +236,10 @@ static PRStatus
ssl3_GenerateSessionTicketKeys(void)
{
PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX,
- sizeof(SESS_TICKET_KEY_NAME_PREFIX));
+ sizeof(SESS_TICKET_KEY_NAME_PREFIX));
if (!ssl_GetSessionTicketKeys(&key_name[SESS_TICKET_KEY_NAME_PREFIX_LEN],
- session_ticket_enc_key, session_ticket_mac_key))
+ session_ticket_enc_key, session_ticket_mac_key))
return PR_FAILURE;
session_ticket_keys_initialized = PR_TRUE;
@@ -234,11 +248,11 @@ ssl3_GenerateSessionTicketKeys(void)
static SECStatus
ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
- PRUint32 *aes_key_length, const unsigned char **mac_key,
- PRUint32 *mac_key_length)
+ PRUint32 *aes_key_length, const unsigned char **mac_key,
+ PRUint32 *mac_key_length)
{
if (PR_CallOnce(&generate_session_keys_once,
- ssl3_GenerateSessionTicketKeys) != PR_SUCCESS)
+ ssl3_GenerateSessionTicketKeys) != PR_SUCCESS)
return SECFailure;
if (!session_ticket_keys_initialized)
@@ -259,38 +273,40 @@ ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
*/
/* This table is used by the server, to handle client hello extensions. */
static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
- { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
+ { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
#ifndef NSS_DISABLE_ECC
- { ssl_elliptic_curves_xtn, &ssl3_HandleSupportedCurvesXtn },
- { ssl_ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn },
+ { ssl_elliptic_curves_xtn, &ssl3_HandleSupportedCurvesXtn },
+ { ssl_ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn },
#endif
- { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
+ { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
{ ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
- { ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
+ { ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
{ ssl_app_layer_protocol_xtn, &ssl3_ServerHandleAppProtoXtn },
- { ssl_use_srtp_xtn, &ssl3_ServerHandleUseSRTPXtn },
- { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn },
+ { ssl_use_srtp_xtn, &ssl3_ServerHandleUseSRTPXtn },
+ { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn },
{ ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn },
{ ssl_tls13_draft_version_xtn, &ssl3_ServerHandleDraftVersionXtn },
{ ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
+ { ssl_signed_cert_timestamp_xtn, &ssl3_ServerHandleSignedCertTimestampXtn },
+ { ssl_tls13_key_share_xtn, &tls13_ServerHandleKeyShareXtn },
{ -1, NULL }
};
/* These two tables are used by the client, to handle server hello
* extensions. */
static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
- { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
+ { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
/* TODO: add a handler for ssl_ec_point_formats_xtn */
- { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
+ { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
{ ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
- { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
+ { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
{ ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn },
- { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn },
- { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
- { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
+ { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn },
+ { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
{ ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
- { ssl_signed_certificate_timestamp_xtn,
- &ssl3_ClientHandleSignedCertTimestampXtn },
+ { ssl_signed_cert_timestamp_xtn, &ssl3_ClientHandleSignedCertTimestampXtn },
+ { ssl_tls13_key_share_xtn, &tls13_ClientHandleKeyShareXtn },
{ -1, NULL }
};
@@ -305,37 +321,37 @@ static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
* The server's table of hello senders is dynamic, in the socket struct,
* and sender functions are registered there.
*/
-static const
-ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
- { ssl_server_name_xtn, &ssl3_SendServerNameXtn },
- { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn },
+static const ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] =
+ {
+ { ssl_server_name_xtn, &ssl3_SendServerNameXtn },
+ { ssl_extended_master_secret_xtn, &ssl3_SendExtendedMasterSecretXtn },
+ { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn },
#ifndef NSS_DISABLE_ECC
- { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn },
- { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
+ { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn },
+ { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
#endif
- { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
- { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn },
- { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn },
- { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn },
- { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
- { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
- { ssl_signed_certificate_timestamp_xtn,
- &ssl3_ClientSendSignedCertTimestampXtn },
- /* WebSphere Application Server 7.0 is intolerant to the last extension
- * being zero-length. It is not intolerant of TLS 1.2, so ensure that
- * signature_algorithms is at the end to guarantee a non-empty
- * extension. */
- { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
- { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
- { ssl_extended_master_secret_xtn, &ssl3_SendExtendedMasterSecretXtn},
- /* any extra entries will appear as { 0, NULL } */
-};
-
-static const
-ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] = {
- { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }
- /* any extra entries will appear as { 0, NULL } */
-};
+ { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
+ { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn },
+ { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn },
+ { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn },
+ { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
+ { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
+ { ssl_signed_cert_timestamp_xtn, &ssl3_ClientSendSignedCertTimestampXtn },
+ { ssl_tls13_key_share_xtn, &tls13_ClientSendKeyShareXtn },
+ /* Some servers (e.g. WebSphere Application Server 7.0 and Tomcat) will
+ * time out or terminate the connection if the last extension in the
+ * client hello is empty. They are not intolerant of TLS 1.2, so list
+ * signature_algorithms at the end. See bug 1243641. */
+ { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
+ /* any extra entries will appear as { 0, NULL } */
+ };
+
+static const ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] =
+ {
+ { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }
+ /* any extra entries will appear as { 0, NULL } */
+ };
static PRBool
arrayContainsExtension(const PRUint16 *array, PRUint32 len, PRUint16 ex_type)
@@ -349,14 +365,16 @@ arrayContainsExtension(const PRUint16 *array, PRUint32 len, PRUint16 ex_type)
}
PRBool
-ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type) {
+ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type)
+{
TLSExtensionData *xtnData = &ss->xtnData;
return arrayContainsExtension(xtnData->negotiated,
xtnData->numNegotiated, ex_type);
}
static PRBool
-ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type) {
+ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type)
+{
TLSExtensionData *xtnData = &ss->xtnData;
return arrayContainsExtension(xtnData->advertised,
xtnData->numAdvertised, ex_type);
@@ -367,7 +385,7 @@ ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type) {
* Used by client and server.
*/
PRInt32
-ssl3_SendServerNameXtn(sslSocket * ss, PRBool append,
+ssl3_SendServerNameXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes)
{
SECStatus rv;
@@ -385,23 +403,28 @@ ssl3_SendServerNameXtn(sslSocket * ss, PRBool append,
/* is an IP address (v4 or v6) */
return 0;
}
- len = PORT_Strlen(ss->url);
+ len = PORT_Strlen(ss->url);
if (append && maxBytes >= len + 9) {
/* extension_type */
rv = ssl3_AppendHandshakeNumber(ss, ssl_server_name_xtn, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* length of extension_data */
rv = ssl3_AppendHandshakeNumber(ss, len + 5, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* length of server_name_list */
rv = ssl3_AppendHandshakeNumber(ss, len + 3, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* Name Type (sni_host_name) */
- rv = ssl3_AppendHandshake(ss, "\0", 1);
- if (rv != SECSuccess) return -1;
+ rv = ssl3_AppendHandshake(ss, "\0", 1);
+ if (rv != SECSuccess)
+ return -1;
/* HostName (length and value) */
rv = ssl3_AppendHandshakeVariable(ss, (PRUint8 *)ss->url, len, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
if (!ss->sec.isServer) {
TLSExtensionData *xtnData = &ss->xtnData;
xtnData->advertised[xtnData->numAdvertised++] =
@@ -413,23 +436,25 @@ ssl3_SendServerNameXtn(sslSocket * ss, PRBool append,
/* Server side */
if (append && maxBytes >= 4) {
rv = ssl3_AppendHandshakeNumber(ss, ssl_server_name_xtn, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* length of extension_data */
rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
}
return 4;
}
/* handle an incoming SNI extension, by ignoring it. */
SECStatus
-ssl3_HandleServerNameXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
+ssl3_HandleServerNameXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
{
SECItem *names = NULL;
PRUint32 listCount = 0, namesPos = 0, i;
TLSExtensionData *xtnData = &ss->xtnData;
- SECItem ldata;
- PRInt32 listLenBytes = 0;
+ SECItem ldata;
+ PRInt32 listLenBytes = 0;
if (!ss->sec.isServer) {
return SECSuccess; /* ignore extension */
@@ -476,15 +501,15 @@ ssl3_HandleServerNameXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
if (!names) {
return SECFailure;
}
- for (i = 0;i < listCount;i++) {
+ for (i = 0; i < listCount; i++) {
unsigned int j;
- PRInt32 type;
+ PRInt32 type;
SECStatus rv;
PRBool nametypePresent = PR_FALSE;
/* Name Type (sni_host_name) */
type = ssl3_ConsumeHandshakeNumber(ss, 1, &data->data, &data->len);
/* Check if we have such type in the list */
- for (j = 0;j < listCount && names[j].data;j++) {
+ for (j = 0; j < listCount && names[j].data; j++) {
/* TODO bug 998524: .type is not assigned a value */
if (names[j].type == type) {
nametypePresent = PR_TRUE;
@@ -521,9 +546,9 @@ ssl3_HandleServerNameXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
*/
PRInt32
ssl3_SendSessionTicketXtn(
- sslSocket * ss,
- PRBool append,
- PRUint32 maxBytes)
+ sslSocket *ss,
+ PRBool append,
+ PRUint32 maxBytes)
{
PRInt32 extension_length;
NewSessionTicket *session_ticket = NULL;
@@ -556,9 +581,10 @@ ssl3_SendSessionTicketXtn(
if (ss->xtnData.ticketTimestampVerified) {
extension_length += session_ticket->ticket.len;
} else if (!append &&
- (session_ticket->ticket_lifetime_hint == 0 ||
- (session_ticket->ticket_lifetime_hint +
- session_ticket->received_timestamp > ssl_Time()))) {
+ (session_ticket->ticket_lifetime_hint == 0 ||
+ (session_ticket->ticket_lifetime_hint +
+ session_ticket->received_timestamp >
+ ssl_Time()))) {
extension_length += session_ticket->ticket.len;
ss->xtnData.ticketTimestampVerified = PR_TRUE;
}
@@ -578,7 +604,7 @@ ssl3_SendSessionTicketXtn(
if (session_ticket && session_ticket->ticket.data &&
ss->xtnData.ticketTimestampVerified) {
rv = ssl3_AppendHandshakeVariable(ss, session_ticket->ticket.data,
- session_ticket->ticket.len, 2);
+ session_ticket->ticket.len, 2);
ss->xtnData.ticketTimestampVerified = PR_FALSE;
ss->xtnData.sentSessionTicketInClientHello = PR_TRUE;
} else {
@@ -595,14 +621,14 @@ ssl3_SendSessionTicketXtn(
}
return extension_length;
- loser:
+loser:
ss->xtnData.ticketTimestampVerified = PR_FALSE;
return -1;
}
/* handle an incoming Next Protocol Negotiation extension. */
static SECStatus
-ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type,
+ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data)
{
if (ss->firstHsDone || data->len != 0) {
@@ -624,12 +650,12 @@ ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type,
* of the lengths may be 0 and the sum of the lengths must equal the length of
* the block. */
SECStatus
-ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned int length)
+ssl3_ValidateNextProtoNego(const unsigned char *data, unsigned int length)
{
unsigned int offset = 0;
while (offset < length) {
- unsigned int newOffset = offset + 1 + (unsigned int) data[offset];
+ unsigned int newOffset = offset + 1 + (unsigned int)data[offset];
/* Reject embedded nulls to protect against buggy applications that
* store protocol identifiers in null-terminated strings.
*/
@@ -725,7 +751,7 @@ ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
rv = ssl3_SelectAppProtocol(ss, ex_type, data);
if (rv != SECSuccess) {
- return rv;
+ return rv;
}
/* prepare to send back a response, if we negotiated */
@@ -819,7 +845,7 @@ ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
}
static PRInt32
-ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append,
+ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes)
{
PRInt32 extension_length;
@@ -843,7 +869,7 @@ ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append,
if (rv != SECSuccess)
goto loser;
ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
- ssl_next_proto_nego_xtn;
+ ssl_next_proto_nego_xtn;
}
return extension_length;
@@ -853,7 +879,7 @@ loser:
}
static PRInt32
-ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
+ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
{
PRInt32 extension_length;
unsigned char *alpn_protos = NULL;
@@ -909,7 +935,7 @@ ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
goto loser;
}
ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
- ssl_app_layer_protocol_xtn;
+ ssl_app_layer_protocol_xtn;
}
return extension_length;
@@ -922,7 +948,7 @@ loser:
}
static PRInt32
-ssl3_ServerSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
+ssl3_ServerSendAppProtoXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
{
PRInt32 extension_length;
@@ -966,30 +992,30 @@ ssl3_ServerSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
static SECStatus
ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type,
- SECItem *data)
+ SECItem *data)
{
PORT_Assert(ss->getChannelID != NULL);
if (data->len) {
- PORT_SetError(SSL_ERROR_BAD_CHANNEL_ID_DATA);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_BAD_CHANNEL_ID_DATA);
+ return SECFailure;
}
ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
return SECSuccess;
}
static PRInt32
-ssl3_ClientSendChannelIDXtn(sslSocket * ss, PRBool append,
- PRUint32 maxBytes)
+ssl3_ClientSendChannelIDXtn(sslSocket *ss, PRBool append,
+ PRUint32 maxBytes)
{
PRInt32 extension_length = 4;
if (!ss->getChannelID)
- return 0;
+ return 0;
if (maxBytes < extension_length) {
- PORT_Assert(0);
- return 0;
+ PORT_Assert(0);
+ return 0;
}
if (ss->sec.ci.sid->cached != never_cached &&
@@ -998,19 +1024,19 @@ ssl3_ClientSendChannelIDXtn(sslSocket * ss, PRBool append,
* do ChannelID on the original connection: without ChannelID on the
* original connection we didn't record the handshake hashes needed for
* the signature. */
- return 0;
+ return 0;
}
if (append) {
- SECStatus rv;
- rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
- if (rv != SECSuccess)
- goto loser;
- rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
- if (rv != SECSuccess)
- goto loser;
- ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
- ssl_channel_id_xtn;
+ SECStatus rv;
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
+ ssl_channel_id_xtn;
}
return extension_length;
@@ -1021,11 +1047,11 @@ loser:
static SECStatus
ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type,
- SECItem *data)
+ SECItem *data)
{
/* The echoed extension must be empty. */
if (data->len != 0) {
- return SECSuccess; /* Ignore the extension. */
+ return SECSuccess; /* Ignore the extension. */
}
/* Keep track of negotiated extensions. */
@@ -1036,28 +1062,29 @@ ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type,
static PRInt32
ssl3_ServerSendStatusRequestXtn(
- sslSocket * ss,
- PRBool append,
- PRUint32 maxBytes)
+ sslSocket *ss,
+ PRBool append,
+ PRUint32 maxBytes)
{
PRInt32 extension_length;
+ SSLKEAType effectiveExchKeyType;
SECStatus rv;
- int i;
- PRBool haveStatus = PR_FALSE;
- for (i = kt_null; i < kt_kea_size; i++) {
- /* TODO: This is a temporary workaround.
- * The correct code needs to see if we have an OCSP response for
- * the server certificate being used, rather than if we have any
- * OCSP response. See also ssl3_SendCertificateStatus.
- */
- if (ss->certStatusArray[i] && ss->certStatusArray[i]->len) {
- haveStatus = PR_TRUE;
- break;
- }
+ /* ssl3_SendCertificateStatus (which sents the certificate status data)
+ * uses the exact same logic to select the server certificate
+ * and determine if we have the status for that certificate. */
+
+ if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
+ ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) {
+ effectiveExchKeyType = ssl_kea_rsa;
+ } else {
+ effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
}
- if (!haveStatus)
+
+ if (!ss->certStatusArray[effectiveExchKeyType] ||
+ !ss->certStatusArray[effectiveExchKeyType]->len) {
return 0;
+ }
extension_length = 2 + 2;
if (maxBytes < (PRUint32)extension_length) {
@@ -1072,6 +1099,7 @@ ssl3_ServerSendStatusRequestXtn(
rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
if (rv != SECSuccess)
return -1;
+ /* The certificate status data is sent in ssl3_SendCertificateStatus. */
}
return extension_length;
@@ -1080,13 +1108,13 @@ ssl3_ServerSendStatusRequestXtn(
/* ssl3_ClientSendStatusRequestXtn builds the status_request extension on the
* client side. See RFC 4366 section 3.6. */
static PRInt32
-ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append,
- PRUint32 maxBytes)
+ssl3_ClientSendStatusRequestXtn(sslSocket *ss, PRBool append,
+ PRUint32 maxBytes)
{
PRInt32 extension_length;
if (!ss->opt.enableOCSPStapling)
- return 0;
+ return 0;
/* extension_type (2-bytes) +
* length(extension_data) (2-bytes) +
@@ -1097,37 +1125,37 @@ ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append,
extension_length = 9;
if (maxBytes < (PRUint32)extension_length) {
- PORT_Assert(0);
- return 0;
+ PORT_Assert(0);
+ return 0;
}
if (append) {
- SECStatus rv;
- TLSExtensionData *xtnData;
-
- /* extension_type */
- rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2);
- if (rv != SECSuccess)
- return -1;
- rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
- if (rv != SECSuccess)
- return -1;
- rv = ssl3_AppendHandshakeNumber(ss, 1 /* status_type ocsp */, 1);
- if (rv != SECSuccess)
- return -1;
- /* A zero length responder_id_list means that the responders are
- * implicitly known to the server. */
- rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
- if (rv != SECSuccess)
- return -1;
- /* A zero length request_extensions means that there are no extensions.
- * Specifically, we don't set the id-pkix-ocsp-nonce extension. This
- * means that the server can replay a cached OCSP response to us. */
- rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
- if (rv != SECSuccess)
- return -1;
-
- xtnData = &ss->xtnData;
- xtnData->advertised[xtnData->numAdvertised++] = ssl_cert_status_xtn;
+ SECStatus rv;
+ TLSExtensionData *xtnData;
+
+ /* extension_type */
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2);
+ if (rv != SECSuccess)
+ return -1;
+ rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
+ if (rv != SECSuccess)
+ return -1;
+ rv = ssl3_AppendHandshakeNumber(ss, 1 /* status_type ocsp */, 1);
+ if (rv != SECSuccess)
+ return -1;
+ /* A zero length responder_id_list means that the responders are
+ * implicitly known to the server. */
+ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
+ if (rv != SECSuccess)
+ return -1;
+ /* A zero length request_extensions means that there are no extensions.
+ * Specifically, we don't set the id-pkix-ocsp-nonce extension. This
+ * means that the server can replay a cached OCSP response to us. */
+ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
+ if (rv != SECSuccess)
+ return -1;
+
+ xtnData = &ss->xtnData;
+ xtnData->advertised[xtnData->numAdvertised++] = ssl_cert_status_xtn;
}
return extension_length;
}
@@ -1140,74 +1168,77 @@ SECStatus
ssl3_SendNewSessionTicket(sslSocket *ss)
{
PRUint32 i;
- SECStatus rv;
- NewSessionTicket ticket;
- SECItem plaintext;
- SECItem plaintext_item = {0, NULL, 0};
- SECItem ciphertext = {0, NULL, 0};
- PRUint32 ciphertext_length;
- PRBool ms_is_wrapped;
- unsigned char wrapped_ms[SSL3_MASTER_SECRET_LENGTH];
- SECItem ms_item = {0, NULL, 0};
- SSL3KEAType effectiveExchKeyType = ssl_kea_null;
- PRUint32 padding_length;
- PRUint32 message_length;
- PRUint32 cert_length;
- PRUint8 length_buf[4];
- PRUint32 now;
- PK11SymKey *aes_key_pkcs11;
- PK11SymKey *mac_key_pkcs11;
+ SECStatus rv;
+ NewSessionTicket ticket;
+ SECItem plaintext;
+ SECItem plaintext_item = { 0, NULL, 0 };
+ SECItem ciphertext = { 0, NULL, 0 };
+ PRUint32 ciphertext_length;
+ PRBool ms_is_wrapped;
+ unsigned char wrapped_ms[SSL3_MASTER_SECRET_LENGTH];
+ SECItem ms_item = { 0, NULL, 0 };
+ SSL3KEAType effectiveExchKeyType = ssl_kea_null;
+ PRUint32 padding_length;
+ PRUint32 message_length;
+ PRUint32 cert_length = 0;
+ PRUint8 length_buf[4];
+ PRUint32 now;
+ PK11SymKey *aes_key_pkcs11;
+ PK11SymKey *mac_key_pkcs11;
#ifndef NO_PKCS11_BYPASS
const unsigned char *aes_key;
const unsigned char *mac_key;
- PRUint32 aes_key_length;
- PRUint32 mac_key_length;
- PRUint64 aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS];
- AESContext *aes_ctx;
+ PRUint32 aes_key_length;
+ PRUint32 mac_key_length;
+ PRUint64 aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS];
+ AESContext *aes_ctx;
const SECHashObject *hashObj = NULL;
- PRUint64 hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS];
- HMACContext *hmac_ctx;
+ PRUint64 hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS];
+ HMACContext *hmac_ctx;
#endif
- CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC;
- PK11Context *aes_ctx_pkcs11;
- CK_MECHANISM_TYPE macMech = CKM_SHA256_HMAC;
- PK11Context *hmac_ctx_pkcs11 = NULL;
- unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
- unsigned int computed_mac_length;
- unsigned char iv[AES_BLOCK_SIZE];
- SECItem ivItem;
- SECItem *srvName = NULL;
- PRUint32 srvNameLen = 0;
- CK_MECHANISM_TYPE msWrapMech = 0; /* dummy default value,
+ CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC;
+ PK11Context *aes_ctx_pkcs11;
+ CK_MECHANISM_TYPE macMech = CKM_SHA256_HMAC;
+ PK11Context *hmac_ctx_pkcs11 = NULL;
+ unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
+ unsigned int computed_mac_length;
+ unsigned char iv[AES_BLOCK_SIZE];
+ SECItem ivItem;
+ SECItem *srvName = NULL;
+ PRUint32 srvNameLen = 0;
+ CK_MECHANISM_TYPE msWrapMech = 0; /* dummy default value,
* must be >= 0 */
SSL_TRC(3, ("%d: SSL3[%d]: send session_ticket handshake",
SSL_GETPID(), ss->fd));
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
ticket.ticket_lifetime_hint = TLS_EX_SESS_TICKET_LIFETIME_HINT;
- cert_length = (ss->opt.requestCertificate && ss->sec.ci.sid->peerCert) ?
- 3 + ss->sec.ci.sid->peerCert->derCert.len : 0;
+ if (ss->opt.requestCertificate && ss->sec.ci.sid->peerCert) {
+ cert_length = 3 + ss->sec.ci.sid->peerCert->derCert.len;
+ }
/* Get IV and encryption keys */
ivItem.data = iv;
ivItem.len = sizeof(iv);
rv = PK11_GenerateRandom(iv, sizeof(iv));
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11) {
rv = ssl3_GetSessionTicketKeys(&aes_key, &aes_key_length,
- &mac_key, &mac_key_length);
+ &mac_key, &mac_key_length);
} else
#endif
{
rv = ssl3_GetSessionTicketKeysPKCS11(ss, &aes_key_pkcs11,
- &mac_key_pkcs11);
+ &mac_key_pkcs11);
}
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
if (ss->ssl3.pwSpec->msItem.len && ss->ssl3.pwSpec->msItem.data) {
/* The master secret is available unwrapped. */
@@ -1227,12 +1258,12 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
}
rv = ssl3_CacheWrappedMasterSecret(ss, &sid, ss->ssl3.pwSpec,
- effectiveExchKeyType);
+ effectiveExchKeyType);
if (rv == SECSuccess) {
if (sid.u.ssl3.keys.wrapped_master_secret_len > sizeof(wrapped_ms))
goto loser;
memcpy(wrapped_ms, sid.u.ssl3.keys.wrapped_master_secret,
- sid.u.ssl3.keys.wrapped_master_secret_len);
+ sid.u.ssl3.keys.wrapped_master_secret_len);
ms_item.data = wrapped_ms;
ms_item.len = sid.u.ssl3.keys.wrapped_master_secret_len;
msWrapMech = sid.u.ssl3.masterWrapMech;
@@ -1249,34 +1280,35 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
}
ciphertext_length =
- sizeof(PRUint16) /* ticket_version */
- + sizeof(SSL3ProtocolVersion) /* ssl_version */
- + sizeof(ssl3CipherSuite) /* ciphersuite */
- + 1 /* compression */
- + 10 /* cipher spec parameters */
- + 1 /* SessionTicket.ms_is_wrapped */
- + 1 /* effectiveExchKeyType */
- + 4 /* msWrapMech */
- + 2 /* master_secret.length */
- + ms_item.len /* master_secret */
- + 1 /* client_auth_type */
- + cert_length /* cert */
- + 1 /* server name type */
- + srvNameLen /* name len + length field */
- + 1 /* extendedMasterSecretUsed */
+ sizeof(PRUint16) /* ticket_version */
+ + sizeof(SSL3ProtocolVersion) /* ssl_version */
+ + sizeof(ssl3CipherSuite) /* ciphersuite */
+ + 1 /* compression */
+ + 10 /* cipher spec parameters */
+ + 1 /* SessionTicket.ms_is_wrapped */
+ + 1 /* effectiveExchKeyType */
+ + 4 /* msWrapMech */
+ + 2 /* master_secret.length */
+ + ms_item.len /* master_secret */
+ + 1 /* client_auth_type */
+ + cert_length /* cert */
+ + 1 /* server name type */
+ + srvNameLen /* name len + length field */
+ + 1 /* extendedMasterSecretUsed */
+ sizeof(ticket.ticket_lifetime_hint);
- padding_length = AES_BLOCK_SIZE -
- (ciphertext_length % AES_BLOCK_SIZE);
+ padding_length = AES_BLOCK_SIZE -
+ (ciphertext_length %
+ AES_BLOCK_SIZE);
ciphertext_length += padding_length;
message_length =
- sizeof(ticket.ticket_lifetime_hint) /* ticket_lifetime_hint */
- + 2 /* length field for NewSessionTicket.ticket */
- + SESS_TICKET_KEY_NAME_LEN /* key_name */
- + AES_BLOCK_SIZE /* iv */
- + 2 /* length field for NewSessionTicket.ticket.encrypted_state */
- + ciphertext_length /* encrypted_state */
- + TLS_EX_SESS_TICKET_MAC_LENGTH; /* mac */
+ sizeof(ticket.ticket_lifetime_hint) /* ticket_lifetime_hint */
+ + 2 /* length field for NewSessionTicket.ticket */
+ + SESS_TICKET_KEY_NAME_LEN /* key_name */
+ + AES_BLOCK_SIZE /* iv */
+ + 2 /* length field for NewSessionTicket.ticket.encrypted_state */
+ + ciphertext_length /* encrypted_state */
+ + TLS_EX_SESS_TICKET_MAC_LENGTH; /* mac */
if (SECITEM_AllocItem(NULL, &plaintext_item, ciphertext_length) == NULL)
goto loser;
@@ -1285,87 +1317,109 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
/* ticket_version */
rv = ssl3_AppendNumberToItem(&plaintext, TLS_EX_SESS_TICKET_VERSION,
- sizeof(PRUint16));
- if (rv != SECSuccess) goto loser;
+ sizeof(PRUint16));
+ if (rv != SECSuccess)
+ goto loser;
/* ssl_version */
rv = ssl3_AppendNumberToItem(&plaintext, ss->version,
- sizeof(SSL3ProtocolVersion));
- if (rv != SECSuccess) goto loser;
+ sizeof(SSL3ProtocolVersion));
+ if (rv != SECSuccess)
+ goto loser;
/* ciphersuite */
rv = ssl3_AppendNumberToItem(&plaintext, ss->ssl3.hs.cipher_suite,
- sizeof(ssl3CipherSuite));
- if (rv != SECSuccess) goto loser;
+ sizeof(ssl3CipherSuite));
+ if (rv != SECSuccess)
+ goto loser;
/* compression */
rv = ssl3_AppendNumberToItem(&plaintext, ss->ssl3.hs.compression, 1);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
/* cipher spec parameters */
rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authAlgorithm, 1);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authKeyBits, 4);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaType, 1);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaKeyBits, 4);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
/* master_secret */
rv = ssl3_AppendNumberToItem(&plaintext, ms_is_wrapped, 1);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendNumberToItem(&plaintext, effectiveExchKeyType, 1);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendNumberToItem(&plaintext, msWrapMech, 4);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendNumberToItem(&plaintext, ms_item.len, 2);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendToItem(&plaintext, ms_item.data, ms_item.len);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
/* client_identity */
if (ss->opt.requestCertificate && ss->sec.ci.sid->peerCert) {
rv = ssl3_AppendNumberToItem(&plaintext, CLIENT_AUTH_CERTIFICATE, 1);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendNumberToItem(&plaintext,
- ss->sec.ci.sid->peerCert->derCert.len, 3);
- if (rv != SECSuccess) goto loser;
+ ss->sec.ci.sid->peerCert->derCert.len, 3);
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendToItem(&plaintext,
- ss->sec.ci.sid->peerCert->derCert.data,
- ss->sec.ci.sid->peerCert->derCert.len);
- if (rv != SECSuccess) goto loser;
+ ss->sec.ci.sid->peerCert->derCert.data,
+ ss->sec.ci.sid->peerCert->derCert.len);
+ if (rv != SECSuccess)
+ goto loser;
} else {
rv = ssl3_AppendNumberToItem(&plaintext, 0, 1);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
}
/* timestamp */
now = ssl_Time();
rv = ssl3_AppendNumberToItem(&plaintext, now,
- sizeof(ticket.ticket_lifetime_hint));
- if (rv != SECSuccess) goto loser;
+ sizeof(ticket.ticket_lifetime_hint));
+ if (rv != SECSuccess)
+ goto loser;
if (srvNameLen) {
/* Name Type (sni_host_name) */
rv = ssl3_AppendNumberToItem(&plaintext, srvName->type, 1);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
/* HostName (length and value) */
rv = ssl3_AppendNumberToItem(&plaintext, srvName->len, 2);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendToItem(&plaintext, srvName->data, srvName->len);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
} else {
/* No Name */
- rv = ssl3_AppendNumberToItem(&plaintext, (char)TLS_STE_NO_SERVER_NAME,
- 1);
- if (rv != SECSuccess) goto loser;
+ rv = ssl3_AppendNumberToItem(&plaintext, (char)TLS_STE_NO_SERVER_NAME, 1);
+ if (rv != SECSuccess)
+ goto loser;
}
/* extendedMasterSecretUsed */
rv = ssl3_AppendNumberToItem(
&plaintext, ss->sec.ci.sid->u.ssl3.keys.extendedMasterSecretUsed, 1);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
PORT_Assert(plaintext.len == padding_length);
for (i = 0; i < padding_length; i++)
@@ -1376,45 +1430,48 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
goto loser;
}
- /* Generate encrypted portion of ticket. */
+/* Generate encrypted portion of ticket. */
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11) {
aes_ctx = (AESContext *)aes_ctx_buf;
rv = AES_InitContext(aes_ctx, aes_key, aes_key_length, iv,
- NSS_AES_CBC, 1, AES_BLOCK_SIZE);
- if (rv != SECSuccess) goto loser;
+ NSS_AES_CBC, 1, AES_BLOCK_SIZE);
+ if (rv != SECSuccess)
+ goto loser;
rv = AES_Encrypt(aes_ctx, ciphertext.data, &ciphertext.len,
- ciphertext.len, plaintext_item.data,
- plaintext_item.len);
- if (rv != SECSuccess) goto loser;
+ ciphertext.len, plaintext_item.data,
+ plaintext_item.len);
+ if (rv != SECSuccess)
+ goto loser;
} else
#endif
{
aes_ctx_pkcs11 = PK11_CreateContextBySymKey(cipherMech,
- CKA_ENCRYPT, aes_key_pkcs11, &ivItem);
+ CKA_ENCRYPT, aes_key_pkcs11, &ivItem);
if (!aes_ctx_pkcs11)
goto loser;
rv = PK11_CipherOp(aes_ctx_pkcs11, ciphertext.data,
- (int *)&ciphertext.len, ciphertext.len,
- plaintext_item.data, plaintext_item.len);
+ (int *)&ciphertext.len, ciphertext.len,
+ plaintext_item.data, plaintext_item.len);
PK11_Finalize(aes_ctx_pkcs11);
PK11_DestroyContext(aes_ctx_pkcs11, PR_TRUE);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
}
/* Convert ciphertext length to network order. */
length_buf[0] = (ciphertext.len >> 8) & 0xff;
- length_buf[1] = (ciphertext.len ) & 0xff;
+ length_buf[1] = (ciphertext.len) & 0xff;
- /* Compute MAC. */
+/* Compute MAC. */
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11) {
hmac_ctx = (HMACContext *)hmac_ctx_buf;
hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
if (HMAC_Init(hmac_ctx, hashObj, mac_key,
- mac_key_length, PR_FALSE) != SECSuccess)
+ mac_key_length, PR_FALSE) != SECSuccess)
goto loser;
HMAC_Begin(hmac_ctx);
@@ -1423,7 +1480,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
HMAC_Update(hmac_ctx, (unsigned char *)length_buf, 2);
HMAC_Update(hmac_ctx, ciphertext.data, ciphertext.len);
HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length,
- sizeof(computed_mac));
+ sizeof(computed_mac));
} else
#endif
{
@@ -1431,49 +1488,63 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
macParam.data = NULL;
macParam.len = 0;
hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech,
- CKA_SIGN, mac_key_pkcs11, &macParam);
+ CKA_SIGN, mac_key_pkcs11, &macParam);
if (!hmac_ctx_pkcs11)
goto loser;
rv = PK11_DigestBegin(hmac_ctx_pkcs11);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = PK11_DigestOp(hmac_ctx_pkcs11, key_name,
- SESS_TICKET_KEY_NAME_LEN);
- if (rv != SECSuccess) goto loser;
+ SESS_TICKET_KEY_NAME_LEN);
+ if (rv != SECSuccess)
+ goto loser;
rv = PK11_DigestOp(hmac_ctx_pkcs11, iv, sizeof(iv));
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = PK11_DigestOp(hmac_ctx_pkcs11, (unsigned char *)length_buf, 2);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = PK11_DigestOp(hmac_ctx_pkcs11, ciphertext.data, ciphertext.len);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = PK11_DigestFinal(hmac_ctx_pkcs11, computed_mac,
- &computed_mac_length, sizeof(computed_mac));
- if (rv != SECSuccess) goto loser;
+ &computed_mac_length, sizeof(computed_mac));
+ if (rv != SECSuccess)
+ goto loser;
}
/* Serialize the handshake message. */
rv = ssl3_AppendHandshakeHeader(ss, new_session_ticket, message_length);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendHandshakeNumber(ss, ticket.ticket_lifetime_hint,
- sizeof(ticket.ticket_lifetime_hint));
- if (rv != SECSuccess) goto loser;
+ sizeof(ticket.ticket_lifetime_hint));
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendHandshakeNumber(ss,
- message_length - sizeof(ticket.ticket_lifetime_hint) - 2, 2);
- if (rv != SECSuccess) goto loser;
+ message_length - sizeof(ticket.ticket_lifetime_hint) - 2,
+ 2);
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendHandshake(ss, key_name, SESS_TICKET_KEY_NAME_LEN);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendHandshake(ss, iv, sizeof(iv));
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendHandshakeVariable(ss, ciphertext.data, ciphertext.len, 2);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl3_AppendHandshake(ss, computed_mac, computed_mac_length);
- if (rv != SECSuccess) goto loser;
+ if (rv != SECSuccess)
+ goto loser;
loser:
if (hmac_ctx_pkcs11)
@@ -1494,7 +1565,7 @@ ssl3_ClientHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data)
{
if (data->len != 0) {
- return SECSuccess; /* Ignore the extension. */
+ return SECSuccess; /* Ignore the extension. */
}
/* Keep track of negotiated extensions. */
@@ -1528,34 +1599,34 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
ss->xtnData.emptySessionTicket = PR_TRUE;
} else {
PRUint32 i;
- SECItem extension_data;
+ SECItem extension_data;
EncryptedSessionTicket enc_session_ticket;
- unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
- unsigned int computed_mac_length;
+ unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
+ unsigned int computed_mac_length;
#ifndef NO_PKCS11_BYPASS
- const SECHashObject *hashObj;
- const unsigned char *aes_key;
- const unsigned char *mac_key;
- PRUint32 aes_key_length;
- PRUint32 mac_key_length;
- PRUint64 hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS];
- HMACContext *hmac_ctx;
- PRUint64 aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS];
- AESContext *aes_ctx;
+ const SECHashObject *hashObj;
+ const unsigned char *aes_key;
+ const unsigned char *mac_key;
+ PRUint32 aes_key_length;
+ PRUint32 mac_key_length;
+ PRUint64 hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS];
+ HMACContext *hmac_ctx;
+ PRUint64 aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS];
+ AESContext *aes_ctx;
#endif
- PK11SymKey *aes_key_pkcs11;
- PK11SymKey *mac_key_pkcs11;
- PK11Context *hmac_ctx_pkcs11;
- CK_MECHANISM_TYPE macMech = CKM_SHA256_HMAC;
- PK11Context *aes_ctx_pkcs11;
- CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC;
- unsigned char * padding;
- PRUint32 padding_length;
- unsigned char *buffer;
- unsigned int buffer_len;
- PRInt32 temp;
- SECItem cert_item;
- PRInt8 nameType = TLS_STE_NO_SERVER_NAME;
+ PK11SymKey *aes_key_pkcs11;
+ PK11SymKey *mac_key_pkcs11;
+ PK11Context *hmac_ctx_pkcs11;
+ CK_MECHANISM_TYPE macMech = CKM_SHA256_HMAC;
+ PK11Context *aes_ctx_pkcs11;
+ CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC;
+ unsigned char *padding;
+ PRUint32 padding_length;
+ unsigned char *buffer;
+ unsigned int buffer_len;
+ PRInt32 temp;
+ SECItem cert_item;
+ PRInt8 nameType = TLS_STE_NO_SERVER_NAME;
/* Turn off stateless session resumption if the client sends a
* SessionTicket extension, even if the extension turns out to be
@@ -1572,25 +1643,25 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
extension_data.data = data->data; /* Keep a copy for future use. */
extension_data.len = data->len;
- if (ssl3_ParseEncryptedSessionTicket(ss, data, &enc_session_ticket)
- != SECSuccess) {
+ if (ssl3_ParseEncryptedSessionTicket(ss, data, &enc_session_ticket) !=
+ SECSuccess) {
return SECSuccess; /* Pretend it isn't there */
}
- /* Get session ticket keys. */
+/* Get session ticket keys. */
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11) {
rv = ssl3_GetSessionTicketKeys(&aes_key, &aes_key_length,
- &mac_key, &mac_key_length);
+ &mac_key, &mac_key_length);
} else
#endif
{
rv = ssl3_GetSessionTicketKeysPKCS11(ss, &aes_key_pkcs11,
- &mac_key_pkcs11);
+ &mac_key_pkcs11);
}
if (rv != SECSuccess) {
SSL_DBG(("%d: SSL[%d]: Unable to get/generate session ticket keys.",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
goto loser;
}
@@ -1598,9 +1669,9 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
* from the one we have, bypass ticket processing.
*/
if (PORT_Memcmp(enc_session_ticket.key_name, key_name,
- SESS_TICKET_KEY_NAME_LEN) != 0) {
+ SESS_TICKET_KEY_NAME_LEN) != 0) {
SSL_DBG(("%d: SSL[%d]: Session ticket key_name sent mismatch.",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
goto no_ticket;
}
@@ -1612,13 +1683,13 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
hmac_ctx = (HMACContext *)hmac_ctx_buf;
hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
if (HMAC_Init(hmac_ctx, hashObj, mac_key,
- sizeof(session_ticket_mac_key), PR_FALSE) != SECSuccess)
+ sizeof(session_ticket_mac_key), PR_FALSE) != SECSuccess)
goto no_ticket;
HMAC_Begin(hmac_ctx);
HMAC_Update(hmac_ctx, extension_data.data,
- extension_data.len - TLS_EX_SESS_TICKET_MAC_LENGTH);
+ extension_data.len - TLS_EX_SESS_TICKET_MAC_LENGTH);
if (HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length,
- sizeof(computed_mac)) != SECSuccess)
+ sizeof(computed_mac)) != SECSuccess)
goto no_ticket;
} else
#endif
@@ -1627,32 +1698,34 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
macParam.data = NULL;
macParam.len = 0;
hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech,
- CKA_SIGN, mac_key_pkcs11, &macParam);
+ CKA_SIGN, mac_key_pkcs11, &macParam);
if (!hmac_ctx_pkcs11) {
SSL_DBG(("%d: SSL[%d]: Unable to create HMAC context: %d.",
- SSL_GETPID(), ss->fd, PORT_GetError()));
+ SSL_GETPID(), ss->fd, PORT_GetError()));
goto no_ticket;
} else {
SSL_DBG(("%d: SSL[%d]: Successfully created HMAC context.",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
}
rv = PK11_DigestBegin(hmac_ctx_pkcs11);
rv = PK11_DigestOp(hmac_ctx_pkcs11, extension_data.data,
- extension_data.len - TLS_EX_SESS_TICKET_MAC_LENGTH);
+ extension_data.len -
+ TLS_EX_SESS_TICKET_MAC_LENGTH);
if (rv != SECSuccess) {
PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
goto no_ticket;
}
rv = PK11_DigestFinal(hmac_ctx_pkcs11, computed_mac,
- &computed_mac_length, sizeof(computed_mac));
+ &computed_mac_length, sizeof(computed_mac));
PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
if (rv != SECSuccess)
goto no_ticket;
}
if (NSS_SecureMemcmp(computed_mac, enc_session_ticket.mac,
- computed_mac_length) != 0) {
+ computed_mac_length) !=
+ 0) {
SSL_DBG(("%d: SSL[%d]: Session ticket MAC mismatch.",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
goto no_ticket;
}
@@ -1664,24 +1737,24 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
/* Plaintext is shorter than the ciphertext due to padding. */
decrypted_state = SECITEM_AllocItem(NULL, NULL,
- enc_session_ticket.encrypted_state.len);
+ enc_session_ticket.encrypted_state.len);
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11) {
aes_ctx = (AESContext *)aes_ctx_buf;
rv = AES_InitContext(aes_ctx, aes_key,
- sizeof(session_ticket_enc_key), enc_session_ticket.iv,
- NSS_AES_CBC, 0,AES_BLOCK_SIZE);
+ sizeof(session_ticket_enc_key), enc_session_ticket.iv,
+ NSS_AES_CBC, 0, AES_BLOCK_SIZE);
if (rv != SECSuccess) {
SSL_DBG(("%d: SSL[%d]: Unable to create AES context.",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
goto no_ticket;
}
rv = AES_Decrypt(aes_ctx, decrypted_state->data,
- &decrypted_state->len, decrypted_state->len,
- enc_session_ticket.encrypted_state.data,
- enc_session_ticket.encrypted_state.len);
+ &decrypted_state->len, decrypted_state->len,
+ enc_session_ticket.encrypted_state.data,
+ enc_session_ticket.encrypted_state.len);
if (rv != SECSuccess)
goto no_ticket;
} else
@@ -1691,17 +1764,17 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
ivItem.data = enc_session_ticket.iv;
ivItem.len = AES_BLOCK_SIZE;
aes_ctx_pkcs11 = PK11_CreateContextBySymKey(cipherMech,
- CKA_DECRYPT, aes_key_pkcs11, &ivItem);
+ CKA_DECRYPT, aes_key_pkcs11, &ivItem);
if (!aes_ctx_pkcs11) {
SSL_DBG(("%d: SSL[%d]: Unable to create AES context.",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
goto no_ticket;
}
rv = PK11_CipherOp(aes_ctx_pkcs11, decrypted_state->data,
- (int *)&decrypted_state->len, decrypted_state->len,
- enc_session_ticket.encrypted_state.data,
- enc_session_ticket.encrypted_state.len);
+ (int *)&decrypted_state->len, decrypted_state->len,
+ enc_session_ticket.encrypted_state.data,
+ enc_session_ticket.encrypted_state.len);
PK11_Finalize(aes_ctx_pkcs11);
PK11_DestroyContext(aes_ctx_pkcs11, PR_TRUE);
if (rv != SECSuccess)
@@ -1732,65 +1805,77 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
/* Read ticket_version and reject if the version is wrong */
temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
- if (temp != TLS_EX_SESS_TICKET_VERSION) goto no_ticket;
+ if (temp != TLS_EX_SESS_TICKET_VERSION)
+ goto no_ticket;
parsed_session_ticket->ticket_version = (SSL3ProtocolVersion)temp;
/* Read SSLVersion. */
temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
- if (temp < 0) goto no_ticket;
+ if (temp < 0)
+ goto no_ticket;
parsed_session_ticket->ssl_version = (SSL3ProtocolVersion)temp;
/* Read cipher_suite. */
- temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
- if (temp < 0) goto no_ticket;
+ temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
+ if (temp < 0)
+ goto no_ticket;
parsed_session_ticket->cipher_suite = (ssl3CipherSuite)temp;
/* Read compression_method. */
temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
- if (temp < 0) goto no_ticket;
+ if (temp < 0)
+ goto no_ticket;
parsed_session_ticket->compression_method = (SSLCompressionMethod)temp;
/* Read cipher spec parameters. */
temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
- if (temp < 0) goto no_ticket;
+ if (temp < 0)
+ goto no_ticket;
parsed_session_ticket->authAlgorithm = (SSLSignType)temp;
temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
- if (temp < 0) goto no_ticket;
+ if (temp < 0)
+ goto no_ticket;
parsed_session_ticket->authKeyBits = (PRUint32)temp;
temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
- if (temp < 0) goto no_ticket;
+ if (temp < 0)
+ goto no_ticket;
parsed_session_ticket->keaType = (SSLKEAType)temp;
temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
- if (temp < 0) goto no_ticket;
+ if (temp < 0)
+ goto no_ticket;
parsed_session_ticket->keaKeyBits = (PRUint32)temp;
/* Read wrapped master_secret. */
temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
- if (temp < 0) goto no_ticket;
+ if (temp < 0)
+ goto no_ticket;
parsed_session_ticket->ms_is_wrapped = (PRBool)temp;
temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
- if (temp < 0) goto no_ticket;
+ if (temp < 0)
+ goto no_ticket;
parsed_session_ticket->exchKeyType = (SSL3KEAType)temp;
temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
- if (temp < 0) goto no_ticket;
+ if (temp < 0)
+ goto no_ticket;
parsed_session_ticket->msWrapMech = (CK_MECHANISM_TYPE)temp;
temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
- if (temp < 0) goto no_ticket;
+ if (temp < 0)
+ goto no_ticket;
parsed_session_ticket->ms_length = (PRUint16)temp;
- if (parsed_session_ticket->ms_length == 0 || /* sanity check MS. */
+ if (parsed_session_ticket->ms_length == 0 || /* sanity check MS. */
parsed_session_ticket->ms_length >
- sizeof(parsed_session_ticket->master_secret))
+ sizeof(parsed_session_ticket->master_secret))
goto no_ticket;
/* Allow for the wrapped master secret to be longer. */
if (buffer_len < parsed_session_ticket->ms_length)
goto no_ticket;
PORT_Memcpy(parsed_session_ticket->master_secret, buffer,
- parsed_session_ticket->ms_length);
+ parsed_session_ticket->ms_length);
buffer += parsed_session_ticket->ms_length;
buffer_len -= parsed_session_ticket->ms_length;
@@ -1800,16 +1885,18 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
goto no_ticket;
parsed_session_ticket->client_identity.client_auth_type =
(ClientAuthenticationType)temp;
- switch(parsed_session_ticket->client_identity.client_auth_type) {
+ switch (parsed_session_ticket->client_identity.client_auth_type) {
case CLIENT_AUTH_ANONYMOUS:
break;
case CLIENT_AUTH_CERTIFICATE:
rv = ssl3_ConsumeHandshakeVariable(ss, &cert_item, 3,
- &buffer, &buffer_len);
- if (rv != SECSuccess) goto no_ticket;
+ &buffer, &buffer_len);
+ if (rv != SECSuccess)
+ goto no_ticket;
rv = SECITEM_CopyItem(NULL, &parsed_session_ticket->peer_cert,
- &cert_item);
- if (rv != SECSuccess) goto no_ticket;
+ &cert_item);
+ if (rv != SECSuccess)
+ goto no_ticket;
break;
default:
goto no_ticket;
@@ -1822,15 +1909,17 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
/* Read server name */
nameType =
- ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
+ ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
if (nameType != TLS_STE_NO_SERVER_NAME) {
SECItem name_item;
rv = ssl3_ConsumeHandshakeVariable(ss, &name_item, 2, &buffer,
&buffer_len);
- if (rv != SECSuccess) goto no_ticket;
+ if (rv != SECSuccess)
+ goto no_ticket;
rv = SECITEM_CopyItem(NULL, &parsed_session_ticket->srvName,
&name_item);
- if (rv != SECSuccess) goto no_ticket;
+ if (rv != SECSuccess)
+ goto no_ticket;
parsed_session_ticket->srvName.type = nameType;
}
@@ -1850,7 +1939,8 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
*/
if (parsed_session_ticket->timestamp != 0 &&
parsed_session_ticket->timestamp +
- TLS_EX_SESS_TICKET_LIFETIME_HINT > ssl_Time()) {
+ TLS_EX_SESS_TICKET_LIFETIME_HINT >
+ ssl_Time()) {
sid = ssl3_NewSessionID(ss, PR_TRUE);
if (sid == NULL) {
@@ -1867,35 +1957,34 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
sid->keaType = parsed_session_ticket->keaType;
sid->keaKeyBits = parsed_session_ticket->keaKeyBits;
- /* Copy master secret. */
+/* Copy master secret. */
#ifndef NO_PKCS11_BYPASS
if (ss->opt.bypassPKCS11 &&
- parsed_session_ticket->ms_is_wrapped)
+ parsed_session_ticket->ms_is_wrapped)
goto no_ticket;
#endif
if (parsed_session_ticket->ms_length >
- sizeof(sid->u.ssl3.keys.wrapped_master_secret))
+ sizeof(sid->u.ssl3.keys.wrapped_master_secret))
goto no_ticket;
PORT_Memcpy(sid->u.ssl3.keys.wrapped_master_secret,
- parsed_session_ticket->master_secret,
- parsed_session_ticket->ms_length);
+ parsed_session_ticket->master_secret,
+ parsed_session_ticket->ms_length);
sid->u.ssl3.keys.wrapped_master_secret_len =
parsed_session_ticket->ms_length;
sid->u.ssl3.exchKeyType = parsed_session_ticket->exchKeyType;
sid->u.ssl3.masterWrapMech = parsed_session_ticket->msWrapMech;
sid->u.ssl3.keys.msIsWrapped =
parsed_session_ticket->ms_is_wrapped;
- sid->u.ssl3.masterValid = PR_TRUE;
+ sid->u.ssl3.masterValid = PR_TRUE;
sid->u.ssl3.keys.resumable = PR_TRUE;
- sid->u.ssl3.keys.extendedMasterSecretUsed = parsed_session_ticket->
- extendedMasterSecretUsed;
+ sid->u.ssl3.keys.extendedMasterSecretUsed = parsed_session_ticket->extendedMasterSecretUsed;
/* Copy over client cert from session ticket if there is one. */
if (parsed_session_ticket->peer_cert.data != NULL) {
if (sid->peerCert != NULL)
CERT_DestroyCertificate(sid->peerCert);
sid->peerCert = CERT_NewTempCertificate(ss->dbHandle,
- &parsed_session_ticket->peer_cert, NULL, PR_FALSE, PR_TRUE);
+ &parsed_session_ticket->peer_cert, NULL, PR_FALSE, PR_TRUE);
if (sid->peerCert == NULL) {
rv = SECFailure;
goto loser;
@@ -1910,22 +1999,22 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
}
if (0) {
-no_ticket:
+ no_ticket:
SSL_DBG(("%d: SSL[%d]: Session ticket parsing failed.",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
ssl3stats = SSL_GetStatistics();
- SSL_AtomicIncrementLong(& ssl3stats->hch_sid_ticket_parse_failures );
+ SSL_AtomicIncrementLong(&ssl3stats->hch_sid_ticket_parse_failures);
}
rv = SECSuccess;
loser:
- /* ss->sec.ci.sid == sid if it did NOT come here via goto statement
- * in that case do not free sid
- */
- if (sid && (ss->sec.ci.sid != sid)) {
- ssl_FreeSID(sid);
- sid = NULL;
- }
+ /* ss->sec.ci.sid == sid if it did NOT come here via goto statement
+ * in that case do not free sid
+ */
+ if (sid && (ss->sec.ci.sid != sid)) {
+ ssl_FreeSID(sid);
+ sid = NULL;
+ }
if (decrypted_state != NULL) {
SECITEM_FreeItem(decrypted_state, PR_TRUE);
decrypted_state = NULL;
@@ -1963,18 +2052,22 @@ ssl3_ParseEncryptedSessionTicket(sslSocket *ss, SECItem *data,
EncryptedSessionTicket *enc_session_ticket)
{
if (ssl3_ConsumeFromItem(data, &enc_session_ticket->key_name,
- SESS_TICKET_KEY_NAME_LEN) != SECSuccess)
+ SESS_TICKET_KEY_NAME_LEN) !=
+ SECSuccess)
return SECFailure;
if (ssl3_ConsumeFromItem(data, &enc_session_ticket->iv,
- AES_BLOCK_SIZE) != SECSuccess)
+ AES_BLOCK_SIZE) !=
+ SECSuccess)
return SECFailure;
if (ssl3_ConsumeHandshakeVariable(ss, &enc_session_ticket->encrypted_state,
- 2, &data->data, &data->len) != SECSuccess)
+ 2, &data->data, &data->len) !=
+ SECSuccess)
return SECFailure;
if (ssl3_ConsumeFromItem(data, &enc_session_ticket->mac,
- TLS_EX_SESS_TICKET_MAC_LENGTH) != SECSuccess)
+ TLS_EX_SESS_TICKET_MAC_LENGTH) !=
+ SECSuccess)
return SECFailure;
- if (data->len != 0) /* Make sure that we have consumed all bytes. */
+ if (data->len != 0) /* Make sure that we have consumed all bytes. */
return SECFailure;
return SECSuccess;
@@ -1985,30 +2078,46 @@ ssl3_ParseEncryptedSessionTicket(sslSocket *ss, SECItem *data,
* if present, invoke that handler.
* Servers ignore any extensions with unknown extension types.
* Clients reject any extensions with unadvertised extension types.
+ * In TLS >= 1.3, the client checks that extensions appear in the
+ * right phase.
*/
SECStatus
-ssl3_HandleHelloExtensions(sslSocket *ss, SSL3Opaque **b, PRUint32 *length)
+ssl3_HandleHelloExtensions(sslSocket *ss, SSL3Opaque **b, PRUint32 *length,
+ SSL3HandshakeType handshakeMessage)
{
- const ssl3HelloExtensionHandler * handlers;
+ const ssl3HelloExtensionHandler *handlers;
+ PRBool isTLS13 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
- if (ss->sec.isServer) {
- handlers = clientHelloHandlers;
- } else if (ss->version > SSL_LIBRARY_VERSION_3_0) {
- handlers = serverHelloHandlersTLS;
- } else {
- handlers = serverHelloHandlersSSL3;
+ switch (handshakeMessage) {
+ case client_hello:
+ handlers = clientHelloHandlers;
+ break;
+ case encrypted_extensions:
+ PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
+ /* fall through */
+ case server_hello:
+ if (ss->version > SSL_LIBRARY_VERSION_3_0) {
+ handlers = serverHelloHandlersTLS;
+ } else {
+ handlers = serverHelloHandlersSSL3;
+ }
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ PORT_Assert(0);
+ return SECFailure;
}
while (*length) {
- const ssl3HelloExtensionHandler * handler;
+ const ssl3HelloExtensionHandler *handler;
SECStatus rv;
- PRInt32 extension_type;
- SECItem extension_data;
+ PRInt32 extension_type;
+ SECItem extension_data;
/* Get the extension's type field */
extension_type = ssl3_ConsumeHandshakeNumber(ss, 2, b, length);
- if (extension_type < 0) /* failure to decode extension_type */
- return SECFailure; /* alert already sent */
+ if (extension_type < 0) /* failure to decode extension_type */
+ return SECFailure; /* alert already sent */
/* get the data for this extension, so we can pass it or skip it. */
rv = ssl3_ConsumeHandshakeVariable(ss, &extension_data, 2, b, length);
@@ -2016,8 +2125,7 @@ ssl3_HandleHelloExtensions(sslSocket *ss, SSL3Opaque **b, PRUint32 *length)
return rv; /* alert already sent */
/* Check whether the server sent an extension which was not advertised
- * in the ClientHello.
- */
+ * in the ClientHello */
if (!ss->sec.isServer &&
!ssl3_ClientExtensionAdvertised(ss, extension_type)) {
(void)SSL3_SendAlert(ss, alert_fatal, unsupported_extension);
@@ -2030,12 +2138,23 @@ ssl3_HandleHelloExtensions(sslSocket *ss, SSL3Opaque **b, PRUint32 *length)
return SECFailure;
}
+ /* Check that this is a legal extension in TLS 1.3 */
+ if (isTLS13 && !tls13_ExtensionAllowed(extension_type, handshakeMessage)) {
+ if (handshakeMessage == client_hello) {
+ /* Skip extensions not used in TLS 1.3 */
+ continue;
+ }
+ tls13_FatalError(ss, SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION,
+ unsupported_extension);
+ return SECFailure;
+ }
+
/* find extension_type in table of Hello Extension Handlers */
for (handler = handlers; handler->ex_type >= 0; handler++) {
/* if found, call this handler */
if (handler->ex_type == extension_type) {
rv = (*handler->ex_handler)(ss, (PRUint16)extension_type,
- &extension_data);
+ &extension_data);
if (rv != SECSuccess) {
if (!ss->ssl3.fatalAlertSent) {
/* send a generic alert if the handler didn't already */
@@ -2056,11 +2175,22 @@ ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type,
ssl3HelloExtensionSenderFunc cb)
{
int i;
- ssl3HelloExtensionSender *sender = &ss->xtnData.serverSenders[0];
+ ssl3HelloExtensionSender *sender;
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ sender = &ss->xtnData.serverHelloSenders[0];
+ } else {
+ if (tls13_ExtensionAllowed(ex_type, server_hello)) {
+ PORT_Assert(!tls13_ExtensionAllowed(ex_type, encrypted_extensions));
+ sender = &ss->xtnData.serverHelloSenders[0];
+ } else {
+ PORT_Assert(tls13_ExtensionAllowed(ex_type, encrypted_extensions));
+ sender = &ss->xtnData.encryptedExtensionsSenders[0];
+ }
+ }
for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) {
if (!sender->ex_sender) {
- sender->ex_type = ex_type;
+ sender->ex_type = ex_type;
sender->ex_sender = cb;
return SECSuccess;
}
@@ -2085,8 +2215,11 @@ ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
int i;
if (!sender) {
- sender = ss->version > SSL_LIBRARY_VERSION_3_0 ?
- &clientHelloSendersTLS[0] : &clientHelloSendersSSL3[0];
+ if (ss->version > SSL_LIBRARY_VERSION_3_0) {
+ sender = &clientHelloSendersTLS[0];
+ } else {
+ sender = &clientHelloSendersSSL3[0];
+ }
}
for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) {
@@ -2094,14 +2227,13 @@ ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
PRInt32 extLen = (*sender->ex_sender)(ss, append, maxBytes);
if (extLen < 0)
return -1;
- maxBytes -= extLen;
+ maxBytes -= extLen;
total_exten_len += extLen;
}
}
return total_exten_len;
}
-
/* Extension format:
* Extension number: 2 bytes
* Extension length: 2 bytes
@@ -2111,11 +2243,12 @@ ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
*/
static PRInt32
ssl3_SendRenegotiationInfoXtn(
- sslSocket * ss,
- PRBool append,
- PRUint32 maxBytes)
+ sslSocket *ss,
+ PRBool append,
+ PRUint32 maxBytes)
{
- PRInt32 len, needed;
+ PRInt32 len = 0;
+ PRInt32 needed;
/* In draft-ietf-tls-renegotiation-03, it is NOT RECOMMENDED to send
* both the SCSV and the empty RI, so when we send SCSV in
@@ -2123,9 +2256,10 @@ ssl3_SendRenegotiationInfoXtn(
*/
if (!ss || ss->ssl3.hs.sendingSCSV)
return 0;
- len = !ss->firstHsDone ? 0 :
- (ss->sec.isServer ? ss->ssl3.hs.finishedBytes * 2
- : ss->ssl3.hs.finishedBytes);
+ if (ss->firstHsDone) {
+ len = ss->sec.isServer ? ss->ssl3.hs.finishedBytes * 2
+ : ss->ssl3.hs.finishedBytes;
+ }
needed = 5 + len;
if (maxBytes < (PRUint32)needed) {
return 0;
@@ -2134,18 +2268,21 @@ ssl3_SendRenegotiationInfoXtn(
SECStatus rv;
/* extension_type */
rv = ssl3_AppendHandshakeNumber(ss, ssl_renegotiation_info_xtn, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* length of extension_data */
rv = ssl3_AppendHandshakeNumber(ss, len + 1, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* verify_Data from previous Finished message(s) */
rv = ssl3_AppendHandshakeVariable(ss,
- ss->ssl3.hs.finishedMsgs.data, len, 1);
- if (rv != SECSuccess) return -1;
+ ss->ssl3.hs.finishedMsgs.data, len, 1);
+ if (rv != SECSuccess)
+ return -1;
if (!ss->sec.isServer) {
TLSExtensionData *xtnData = &ss->xtnData;
xtnData->advertised[xtnData->numAdvertised++] =
- ssl_renegotiation_info_xtn;
+ ssl_renegotiation_info_xtn;
}
}
return needed;
@@ -2162,7 +2299,7 @@ ssl3_ServerHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type,
PORT_Assert(ss->sec.isServer);
/* prepare to send back the appropriate response */
rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
- ssl3_ServerSendStatusRequestXtn);
+ ssl3_ServerSendStatusRequestXtn);
return rv;
}
@@ -2177,7 +2314,7 @@ ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
len = ss->sec.isServer ? ss->ssl3.hs.finishedBytes
: ss->ssl3.hs.finishedBytes * 2;
}
- if (data->len != 1 + len || data->data[0] != len ) {
+ if (data->len != 1 + len || data->data[0] != len) {
(void)ssl3_DecodeError(ss);
return SECFailure;
}
@@ -2209,22 +2346,25 @@ ssl3_ClientSendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
return 0;
if (!IS_DTLS(ss) || !ss->ssl3.dtlsSRTPCipherCount)
- return 0; /* Not relevant */
+ return 0; /* Not relevant */
ext_data_len = 2 + 2 * ss->ssl3.dtlsSRTPCipherCount + 1;
if (append && maxBytes >= 4 + ext_data_len) {
/* Extension type */
rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* Length of extension data */
rv = ssl3_AppendHandshakeNumber(ss, ext_data_len, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* Length of the SRTP cipher list */
rv = ssl3_AppendHandshakeNumber(ss,
2 * ss->ssl3.dtlsSRTPCipherCount,
2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* The SRTP ciphers */
for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) {
rv = ssl3_AppendHandshakeNumber(ss,
@@ -2235,7 +2375,7 @@ ssl3_ClientSendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
ssl3_AppendHandshakeVariable(ss, NULL, 0, 1);
ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
- ssl_use_srtp_xtn;
+ ssl_use_srtp_xtn;
}
return 4 + ext_data_len;
@@ -2253,16 +2393,20 @@ ssl3_ServerSendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
/* Extension type */
rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* Length of extension data */
rv = ssl3_AppendHandshakeNumber(ss, 5, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* Length of the SRTP cipher list */
rv = ssl3_AppendHandshakeNumber(ss, 2, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* The selected cipher */
rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.dtlsSRTPCipherSuite, 2);
- if (rv != SECSuccess) return -1;
+ if (rv != SECSuccess)
+ return -1;
/* Empty MKI value */
ssl3_AppendHandshakeVariable(ss, NULL, 0, 1);
@@ -2270,10 +2414,10 @@ ssl3_ServerSendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
}
static SECStatus
-ssl3_ClientHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
+ssl3_ClientHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
{
SECStatus rv;
- SECItem ciphers = {siBuffer, NULL, 0};
+ SECItem ciphers = { siBuffer, NULL, 0 };
PRUint16 i;
PRUint16 cipher = 0;
PRBool found = PR_FALSE;
@@ -2288,7 +2432,7 @@ ssl3_ClientHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
rv = ssl3_ConsumeHandshakeVariable(ss, &ciphers, 2,
&data->data, &data->len);
if (rv != SECSuccess) {
- return SECFailure; /* fatal alert already sent */
+ return SECFailure; /* fatal alert already sent */
}
/* Now check that the server has picked just 1 (i.e., len = 2) */
if (ciphers.len != 2) {
@@ -2340,10 +2484,10 @@ ssl3_ClientHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
}
static SECStatus
-ssl3_ServerHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
+ssl3_ServerHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
{
SECStatus rv;
- SECItem ciphers = {siBuffer, NULL, 0};
+ SECItem ciphers = { siBuffer, NULL, 0 };
PRUint16 i;
unsigned int j;
PRUint16 cipher = 0;
@@ -2414,7 +2558,7 @@ ssl3_ServerHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
* from a client.
* See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
static SECStatus
-ssl3_ServerHandleSigAlgsXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
+ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
{
SECStatus rv;
SECItem algorithms;
@@ -2438,7 +2582,7 @@ ssl3_ServerHandleSigAlgsXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
return SECFailure;
}
- numAlgorithms = algorithms.len/2;
+ numAlgorithms = algorithms.len / 2;
/* We don't care to process excessive numbers of algorithms. */
if (numAlgorithms > 512) {
@@ -2446,7 +2590,7 @@ ssl3_ServerHandleSigAlgsXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
}
ss->ssl3.hs.clientSigAndHash =
- PORT_NewArray(SSLSignatureAndHashAlg, numAlgorithms);
+ PORT_NewArray(SSLSignatureAndHashAlg, numAlgorithms);
if (!ss->ssl3.hs.clientSigAndHash) {
(void)SSL3_SendAlert(ss, alert_fatal, internal_error);
PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
@@ -2459,8 +2603,8 @@ ssl3_ServerHandleSigAlgsXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
for (i = 0; i < numAlgorithms; i++) {
SSLSignatureAndHashAlg *sigAndHash =
&ss->ssl3.hs.clientSigAndHash[ss->ssl3.hs.numClientSigAndHash];
- sigAndHash->hashAlg = (SSLHashType)*(b++);
- sigAndHash->sigAlg = (SSLSignType)*(b++);
+ sigAndHash->hashAlg = (SSLHashType) * (b++);
+ sigAndHash->sigAlg = (SSLSignType) * (b++);
if (ssl3_IsSupportedSignatureAlgorithm(sigAndHash)) {
++ss->ssl3.hs.numClientSigAndHash;
}
@@ -2485,7 +2629,7 @@ ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
{
PRInt32 extension_length;
unsigned int i;
- PRInt32 pos=0;
+ PRInt32 pos = 0;
PRUint32 policy;
PRUint8 buf[MAX_SIGNATURE_ALGORITHMS * 2];
@@ -2493,14 +2637,14 @@ ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
return 0;
}
- for (i=0; i < ss->ssl3.signatureAlgorithmCount; i++) {
- SECOidTag hashOID = ssl3_TLSHashAlgorithmToOID(
- ss->ssl3.signatureAlgorithms[i].hashAlg);
- if ((NSS_GetAlgorithmPolicy(hashOID, & policy) != SECSuccess) ||
- (policy & NSS_USE_ALG_IN_SSL_KX)) {
- buf[pos++] = ss->ssl3.signatureAlgorithms[i].hashAlg;
- buf[pos++] = ss->ssl3.signatureAlgorithms[i].sigAlg;
- }
+ for (i = 0; i < ss->ssl3.signatureAlgorithmCount; i++) {
+ SECOidTag hashOID = ssl3_TLSHashAlgorithmToOID(
+ ss->ssl3.signatureAlgorithms[i].hashAlg);
+ if ((NSS_GetAlgorithmPolicy(hashOID, &policy) != SECSuccess) ||
+ (policy & NSS_USE_ALG_IN_SSL_KX)) {
+ buf[pos++] = ss->ssl3.signatureAlgorithms[i].hashAlg;
+ buf[pos++] = ss->ssl3.signatureAlgorithms[i].sigAlg;
+ }
}
extension_length =
@@ -2531,7 +2675,7 @@ ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
}
ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
- ssl_signature_algorithms_xtn;
+ ssl_signature_algorithms_xtn;
}
return extension_length;
@@ -2595,7 +2739,7 @@ ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
* version extension.
* TODO(ekr@rtfm.com): Remove when TLS 1.3 is published. */
static PRInt32
-ssl3_ClientSendDraftVersionXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
+ssl3_ClientSendDraftVersionXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
{
PRInt32 extension_length;
@@ -2603,7 +2747,7 @@ ssl3_ClientSendDraftVersionXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
return 0;
}
- extension_length = 6; /* Type + length + number */
+ extension_length = 6; /* Type + length + number */
if (maxBytes < (PRUint32)extension_length) {
PORT_Assert(0);
return 0;
@@ -2620,7 +2764,7 @@ ssl3_ClientSendDraftVersionXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
if (rv != SECSuccess)
goto loser;
ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
- ssl_tls13_draft_version_xtn;
+ ssl_tls13_draft_version_xtn;
}
return extension_length;
@@ -2633,7 +2777,7 @@ loser:
* version extension.
* TODO(ekr@rtfm.com): Remove when TLS 1.3 is published. */
static SECStatus
-ssl3_ServerHandleDraftVersionXtn(sslSocket * ss, PRUint16 ex_type,
+ssl3_ServerHandleDraftVersionXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data)
{
PRInt32 draft_version;
@@ -2674,7 +2818,7 @@ ssl3_ServerHandleDraftVersionXtn(sslSocket * ss, PRUint16 ex_type,
}
static PRInt32
-ssl3_SendExtendedMasterSecretXtn(sslSocket * ss, PRBool append,
+ssl3_SendExtendedMasterSecretXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes)
{
PRInt32 extension_length;
@@ -2695,7 +2839,7 @@ ssl3_SendExtendedMasterSecretXtn(sslSocket * ss, PRBool append,
/* Always send the extension in this function, since the
* client always sends it and this function is only called on
* the server if we negotiated the extension. */
- extension_length = 4; /* Type + length (0) */
+ extension_length = 4; /* Type + length (0) */
if (maxBytes < extension_length) {
PORT_Assert(0);
return 0;
@@ -2710,55 +2854,17 @@ ssl3_SendExtendedMasterSecretXtn(sslSocket * ss, PRBool append,
if (rv != SECSuccess)
goto loser;
ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
- ssl_extended_master_secret_xtn;
+ ssl_extended_master_secret_xtn;
}
return extension_length;
-loser:
- return -1;
-}
-
-/* ssl3_ClientSendSignedCertTimestampXtn sends the signed_certificate_timestamp
- * extension for TLS ClientHellos. */
-static PRInt32
-ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, PRBool append,
- PRUint32 maxBytes)
-{
- PRInt32 extension_length = 2 /* extension_type */ +
- 2 /* length(extension_data) */;
-
- /* Only send the extension if processing is enabled. */
- if (!ss->opt.enableSignedCertTimestamps)
- return 0;
- if (maxBytes < extension_length) {
- PORT_Assert(0);
- return 0;
- }
-
- if (append) {
- SECStatus rv;
- /* extension_type */
- rv = ssl3_AppendHandshakeNumber(ss,
- ssl_signed_certificate_timestamp_xtn,
- 2);
- if (rv != SECSuccess)
- goto loser;
- /* zero length */
- rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
- if (rv != SECSuccess)
- goto loser;
- ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
- ssl_signed_certificate_timestamp_xtn;
- }
-
- return extension_length;
loser:
return -1;
}
static SECStatus
-ssl3_HandleExtendedMasterSecretXtn(sslSocket * ss, PRUint16 ex_type,
+ssl3_HandleExtendedMasterSecretXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data)
{
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_0) {
@@ -2797,6 +2903,43 @@ ssl3_HandleExtendedMasterSecretXtn(sslSocket * ss, PRUint16 ex_type,
return SECSuccess;
}
+/* ssl3_ClientSendSignedCertTimestampXtn sends the signed_certificate_timestamp
+ * extension for TLS ClientHellos. */
+static PRInt32
+ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, PRBool append,
+ PRUint32 maxBytes)
+{
+ PRInt32 extension_length = 2 /* extension_type */ +
+ 2 /* length(extension_data) */;
+
+ /* Only send the extension if processing is enabled. */
+ if (!ss->opt.enableSignedCertTimestamps)
+ return 0;
+
+ if (append && maxBytes >= extension_length) {
+ SECStatus rv;
+ /* extension_type */
+ rv = ssl3_AppendHandshakeNumber(ss,
+ ssl_signed_cert_timestamp_xtn,
+ 2);
+ if (rv != SECSuccess)
+ goto loser;
+ /* zero length */
+ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
+ ssl_signed_cert_timestamp_xtn;
+ } else if (maxBytes < extension_length) {
+ PORT_Assert(0);
+ return 0;
+ }
+
+ return extension_length;
+loser:
+ return -1;
+}
+
static SECStatus
ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data)
@@ -2821,3 +2964,327 @@ ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type,
ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
return SECSuccess;
}
+
+static PRInt32
+ssl3_ServerSendSignedCertTimestampXtn(sslSocket *ss,
+ PRBool append,
+ PRUint32 maxBytes)
+{
+ PRInt32 extension_length;
+ SSLKEAType effectiveExchKeyType;
+ const SECItem *scts;
+
+ if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
+ ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) {
+ effectiveExchKeyType = ssl_kea_rsa;
+ } else {
+ effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
+ }
+
+ scts = &ss->signedCertTimestamps[effectiveExchKeyType];
+
+ if (!scts->len) {
+ /* No timestamps to send */
+ return 0;
+ }
+
+ extension_length = 2 /* extension_type */ +
+ 2 /* length(extension_data) */ +
+ scts->len;
+
+ if (maxBytes < extension_length) {
+ PORT_Assert(0);
+ return 0;
+ }
+ if (append) {
+ SECStatus rv;
+ /* extension_type */
+ rv = ssl3_AppendHandshakeNumber(ss,
+ ssl_signed_cert_timestamp_xtn,
+ 2);
+ if (rv != SECSuccess)
+ goto loser;
+ /* extension_data */
+ rv = ssl3_AppendHandshakeVariable(ss, scts->data, scts->len, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ }
+
+ return extension_length;
+
+loser:
+ return -1;
+}
+
+static SECStatus
+ssl3_ServerHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type,
+ SECItem *data)
+{
+ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
+ PORT_Assert(ss->sec.isServer);
+ return ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
+ ssl3_ServerSendSignedCertTimestampXtn);
+}
+
+/*
+ * [draft-ietf-tls-tls13-11] Section 6.3.2.3.
+ *
+ * struct {
+ * NamedGroup group;
+ * opaque key_exchange<1..2^16-1>;
+ * } KeyShareEntry;
+ *
+ * struct {
+ * select (role) {
+ * case client:
+ * KeyShareEntry client_shares<4..2^16-1>;
+ *
+ * case server:
+ * KeyShareEntry server_share;
+ * }
+ * } KeyShare;
+ */
+static SECStatus
+tls13_SizeOfKeyShareEntry(ssl3KeyPair *pair)
+{
+ return 2 + 2 + tls13_SizeOfECDHEKeyShareKEX(pair);
+}
+
+static SECStatus
+tls13_EncodeKeyShareEntry(sslSocket *ss, ssl3KeyPair *pair)
+{
+ SECStatus rv;
+
+ /* This currently only works for ECC keys */
+ PORT_Assert(pair->pubKey->keyType == ecKey);
+ if (pair->pubKey->keyType != ecKey) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
+ rv = ssl3_AppendHandshakeNumber(ss, tls13_GroupForECDHEKeyShare(pair), 2);
+ if (rv != SECSuccess)
+ return rv;
+
+ rv = ssl3_AppendHandshakeNumber(ss, tls13_SizeOfECDHEKeyShareKEX(pair), 2);
+ if (rv != SECSuccess)
+ return rv;
+
+ rv = tls13_EncodeECDHEKeyShareKEX(ss, pair);
+ if (rv != SECSuccess)
+ return rv;
+
+ return SECSuccess;
+}
+
+static PRInt32
+tls13_ClientSendKeyShareXtn(sslSocket *ss, PRBool append,
+ PRUint32 maxBytes)
+{
+ SECStatus rv;
+ PRUint32 entry_length;
+ PRUint32 extension_length;
+
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ return 0;
+ }
+
+ /* Optimistically try to send an ECDHE key using the
+ * preexisting key (in future will be keys) */
+ SSL_TRC(3, ("%d: TLS13[%d]: send client key share xtn",
+ SSL_GETPID(), ss->fd));
+
+ entry_length = tls13_SizeOfKeyShareEntry(ss->ephemeralECDHKeyPair);
+ /* Type + length + vector_length + entry */
+ extension_length = 2 + 2 + 2 + entry_length;
+
+ if (maxBytes < extension_length) {
+ PORT_Assert(0);
+ return 0;
+ }
+
+ if (append) {
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ rv = ssl3_AppendHandshakeNumber(ss, entry_length + 2, 2); /* Extension length */
+ if (rv != SECSuccess)
+ goto loser;
+ rv = ssl3_AppendHandshakeNumber(ss, entry_length, 2); /* Vector length */
+ if (rv != SECSuccess)
+ goto loser;
+ rv = tls13_EncodeKeyShareEntry(ss, ss->ephemeralECDHKeyPair);
+ if (rv != SECSuccess)
+ goto loser;
+
+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
+ ssl_tls13_key_share_xtn;
+ }
+
+ return extension_length;
+
+loser:
+ return -1;
+}
+
+static SECStatus
+tls13_HandleKeyShareEntry(sslSocket *ss, SECItem *data)
+{
+ SECStatus rv;
+ PRInt32 group;
+ TLS13KeyShareEntry *ks = NULL;
+ SECItem share = { siBuffer, NULL, 0 };
+
+ group = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
+ if (group < 0) {
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE);
+ goto loser;
+ }
+
+ rv = ssl3_ConsumeHandshakeVariable(ss, &share, 2, &data->data,
+ &data->len);
+ if (rv != SECSuccess)
+ goto loser;
+
+ ks = PORT_ZNew(TLS13KeyShareEntry);
+ if (!ks)
+ goto loser;
+ ks->group = group;
+
+ rv = SECITEM_CopyItem(NULL, &ks->key_exchange, &share);
+ if (rv != SECSuccess)
+ goto loser;
+
+ PR_APPEND_LINK(&ks->link, &ss->ssl3.hs.remoteKeyShares);
+ return SECSuccess;
+
+loser:
+ if (ks)
+ tls13_DestroyKeyShareEntry(ks);
+ return SECFailure;
+}
+
+/* Handle an incoming KeyShare extension at the client and copy to
+ * |ss->ssl3.hs.remoteKeyShares| for future use. The key
+ * share is processed in tls13_HandleServerKeyShare(). */
+static SECStatus
+tls13_ClientHandleKeyShareXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
+{
+ SECStatus rv;
+
+ PORT_Assert(!ss->sec.isServer);
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ /* This can't happen because the extension processing
+ * code filters out TLS 1.3 extensions when not in
+ * TLS 1.3 mode. */
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
+ SSL_TRC(3, ("%d: SSL3[%d]: handle key_share extension",
+ SSL_GETPID(), ss->fd));
+
+ rv = tls13_HandleKeyShareEntry(ss, data);
+ if (rv != SECSuccess) {
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE);
+ return SECFailure;
+ }
+
+ if (data->len) {
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE);
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+/* Handle an incoming KeyShare extension at the server and copy to
+ * |ss->ssl3.hs.remoteKeyShares| for future use. The key
+ * share is processed in tls13_HandleClientKeyShare(). */
+static SECStatus
+tls13_ServerHandleKeyShareXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
+{
+ SECStatus rv;
+ PRInt32 length;
+
+ PORT_Assert(ss->sec.isServer);
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ return SECSuccess;
+ }
+
+ SSL_TRC(3, ("%d: SSL3[%d]: handle key_share extension",
+ SSL_GETPID(), ss->fd));
+
+ /* Redundant length because of TLS encoding (this vector consumes
+ * the entire extension.) */
+ length = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data,
+ &data->len);
+ if (length < 0)
+ goto loser;
+ if (length != data->len) {
+ /* Check for consistency */
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE);
+ goto loser;
+ }
+
+ while (data->len) {
+ rv = tls13_HandleKeyShareEntry(ss, data);
+ if (rv != SECSuccess)
+ goto loser;
+ }
+ return SECSuccess;
+
+loser:
+ tls13_DestroyKeyShares(&ss->ssl3.hs.remoteKeyShares);
+ return SECFailure;
+}
+
+PRInt32
+tls13_ServerSendKeyShareXtn(sslSocket *ss, PRBool append,
+ PRUint32 maxBytes)
+{
+ PRUint32 extension_length;
+ PRUint32 entry_length;
+ SECStatus rv;
+
+ switch (ss->ssl3.hs.kea_def->exchKeyType) {
+#ifndef NSS_DISABLE_ECC
+ case ssl_kea_ecdh:
+ PORT_Assert(ss->ephemeralECDHKeyPair);
+ break;
+#endif
+ default:
+ /* got an unknown or unsupported Key Exchange Algorithm.
+ * Can't happen because tls13_HandleClientKeyShare
+ * enforces that we are ssl_kea_ecdh. */
+ PORT_Assert(0);
+ tls13_FatalError(ss, SEC_ERROR_UNSUPPORTED_KEYALG, internal_error);
+ return SECFailure;
+ }
+
+ entry_length = tls13_SizeOfKeyShareEntry(ss->ephemeralECDHKeyPair);
+ extension_length = 2 + 2 + entry_length; /* Type + length + entry_length */
+ if (maxBytes < extension_length) {
+ PORT_Assert(0);
+ return 0;
+ }
+
+ if (append) {
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2);
+ if (rv != SECSuccess)
+ goto loser;
+
+ rv = ssl3_AppendHandshakeNumber(ss, entry_length, 2);
+ if (rv != SECSuccess)
+ goto loser;
+
+ rv = tls13_EncodeKeyShareEntry(ss, ss->ephemeralECDHKeyPair);
+ if (rv != SECSuccess)
+ goto loser;
+ }
+
+ return extension_length;
+
+loser:
+ return -1;
+}
diff --git a/chromium/net/third_party/nss/ssl/ssl3gthr.c b/chromium/net/third_party/nss/ssl/ssl3gthr.c
index 23b9755b600..ea277135d4a 100644
--- a/chromium/net/third_party/nss/ssl/ssl3gthr.c
+++ b/chromium/net/third_party/nss/ssl/ssl3gthr.c
@@ -1,5 +1,5 @@
/*
- * Gather (Read) entire SSL3 records from socket into buffer.
+ * Gather (Read) entire SSL3 records from socket into buffer.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -10,15 +10,15 @@
#include "sslimpl.h"
#include "ssl3prot.h"
-/*
+/*
* Attempt to read in an entire SSL3 record.
- * Blocks here for blocking sockets, otherwise returns -1 with
- * PR_WOULD_BLOCK_ERROR when socket would block.
+ * Blocks here for blocking sockets, otherwise returns -1 with
+ * PR_WOULD_BLOCK_ERROR when socket would block.
*
* returns 1 if received a complete SSL3 record.
* returns 0 if recv returns EOF
- * returns -1 if recv returns < 0
- * (The error value may have already been set to PR_WOULD_BLOCK_ERROR)
+ * returns -1 if recv returns < 0
+ * (The error value may have already been set to PR_WOULD_BLOCK_ERROR)
*
* Caller must hold the recv buf lock.
*
@@ -28,108 +28,107 @@
*
* This loop returns when either
* (a) an error or EOF occurs,
- * (b) PR_WOULD_BLOCK_ERROR,
- * (c) data (entire SSL3 record) has been received.
+ * (b) PR_WOULD_BLOCK_ERROR,
+ * (c) data (entire SSL3 record) has been received.
*/
static int
ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags)
{
unsigned char *bp;
unsigned char *lbp;
- int nb;
- int err;
- int rv = 1;
+ int nb;
+ int err;
+ int rv = 1;
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
if (gs->state == GS_INIT) {
- gs->state = GS_HEADER;
- gs->remainder = 5;
- gs->offset = 0;
- gs->writeOffset = 0;
- gs->readOffset = 0;
- gs->inbuf.len = 0;
+ gs->state = GS_HEADER;
+ gs->remainder = 5;
+ gs->offset = 0;
+ gs->writeOffset = 0;
+ gs->readOffset = 0;
+ gs->inbuf.len = 0;
}
-
+
lbp = gs->inbuf.buf;
- for(;;) {
- SSL_TRC(30, ("%d: SSL3[%d]: gather state %d (need %d more)",
- SSL_GETPID(), ss->fd, gs->state, gs->remainder));
- bp = ((gs->state != GS_HEADER) ? lbp : gs->hdr) + gs->offset;
- nb = ssl_DefRecv(ss, bp, gs->remainder, flags);
-
- if (nb > 0) {
- PRINT_BUF(60, (ss, "raw gather data:", bp, nb));
- } else if (nb == 0) {
- /* EOF */
- SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
- rv = 0;
- break;
- } else /* if (nb < 0) */ {
- SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
- PR_GetError()));
- rv = SECFailure;
- break;
- }
-
- PORT_Assert( (unsigned int)nb <= gs->remainder );
- if ((unsigned int)nb > gs->remainder) {
- /* ssl_DefRecv is misbehaving! this error is fatal to SSL. */
- gs->state = GS_INIT; /* so we don't crash next time */
- rv = SECFailure;
- break;
- }
-
- gs->offset += nb;
- gs->remainder -= nb;
- if (gs->state == GS_DATA)
- gs->inbuf.len += nb;
-
- /* if there's more to go, read some more. */
- if (gs->remainder > 0) {
- continue;
- }
-
- /* have received entire record header, or entire record. */
- switch (gs->state) {
- case GS_HEADER:
- /*
- ** Have received SSL3 record header in gs->hdr.
- ** Now extract the length of the following encrypted data,
- ** and then read in the rest of the SSL3 record into gs->inbuf.
- */
- gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4];
-
- /* This is the max fragment length for an encrypted fragment
- ** plus the size of the record header.
- */
- if(gs->remainder > (MAX_FRAGMENT_LENGTH + 2048 + 5)) {
- SSL3_SendAlert(ss, alert_fatal, unexpected_message);
- gs->state = GS_INIT;
- PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
- return SECFailure;
- }
-
- gs->state = GS_DATA;
- gs->offset = 0;
- gs->inbuf.len = 0;
-
- if (gs->remainder > gs->inbuf.space) {
- err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
- if (err) { /* realloc has set error code to no mem. */
- return err;
- }
- lbp = gs->inbuf.buf;
- }
- break; /* End this case. Continue around the loop. */
-
-
- case GS_DATA:
- /*
- ** SSL3 record has been completely received.
- */
- gs->state = GS_INIT;
- return 1;
- }
+ for (;;) {
+ SSL_TRC(30, ("%d: SSL3[%d]: gather state %d (need %d more)",
+ SSL_GETPID(), ss->fd, gs->state, gs->remainder));
+ bp = ((gs->state != GS_HEADER) ? lbp : gs->hdr) + gs->offset;
+ nb = ssl_DefRecv(ss, bp, gs->remainder, flags);
+
+ if (nb > 0) {
+ PRINT_BUF(60, (ss, "raw gather data:", bp, nb));
+ } else if (nb == 0) {
+ /* EOF */
+ SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
+ rv = 0;
+ break;
+ } else /* if (nb < 0) */ {
+ SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
+ PR_GetError()));
+ rv = SECFailure;
+ break;
+ }
+
+ PORT_Assert((unsigned int)nb <= gs->remainder);
+ if ((unsigned int)nb > gs->remainder) {
+ /* ssl_DefRecv is misbehaving! this error is fatal to SSL. */
+ gs->state = GS_INIT; /* so we don't crash next time */
+ rv = SECFailure;
+ break;
+ }
+
+ gs->offset += nb;
+ gs->remainder -= nb;
+ if (gs->state == GS_DATA)
+ gs->inbuf.len += nb;
+
+ /* if there's more to go, read some more. */
+ if (gs->remainder > 0) {
+ continue;
+ }
+
+ /* have received entire record header, or entire record. */
+ switch (gs->state) {
+ case GS_HEADER:
+ /*
+ ** Have received SSL3 record header in gs->hdr.
+ ** Now extract the length of the following encrypted data,
+ ** and then read in the rest of the SSL3 record into gs->inbuf.
+ */
+ gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4];
+
+ /* This is the max fragment length for an encrypted fragment
+ ** plus the size of the record header.
+ */
+ if (gs->remainder > (MAX_FRAGMENT_LENGTH + 2048 + 5)) {
+ SSL3_SendAlert(ss, alert_fatal, unexpected_message);
+ gs->state = GS_INIT;
+ PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
+ return SECFailure;
+ }
+
+ gs->state = GS_DATA;
+ gs->offset = 0;
+ gs->inbuf.len = 0;
+
+ if (gs->remainder > gs->inbuf.space) {
+ err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
+ if (err) { /* realloc has set error code to no mem. */
+ return err;
+ }
+ lbp = gs->inbuf.buf;
+ }
+ break; /* End this case. Continue around the loop. */
+
+ case GS_DATA:
+ /*
+ ** SSL3 record has been completely received.
+ */
+ gs->state = GS_INIT;
+ return 1;
+ }
}
return rv;
@@ -139,7 +138,7 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags)
* Read in an entire DTLS record.
*
* Blocks here for blocking sockets, otherwise returns -1 with
- * PR_WOULD_BLOCK_ERROR when socket would block.
+ * PR_WOULD_BLOCK_ERROR when socket would block.
*
* This is simpler than SSL because we are reading on a datagram socket
* and datagrams must contain >=1 complete records.
@@ -147,43 +146,43 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags)
* returns 1 if received a complete DTLS record.
* returns 0 if recv returns EOF
* returns -1 if recv returns < 0
- * (The error value may have already been set to PR_WOULD_BLOCK_ERROR)
+ * (The error value may have already been set to PR_WOULD_BLOCK_ERROR)
*
* Caller must hold the recv buf lock.
*
* This loop returns when either
* (a) an error or EOF occurs,
- * (b) PR_WOULD_BLOCK_ERROR,
- * (c) data (entire DTLS record) has been received.
+ * (b) PR_WOULD_BLOCK_ERROR,
+ * (c) data (entire DTLS record) has been received.
*/
static int
dtls_GatherData(sslSocket *ss, sslGather *gs, int flags)
{
- int nb;
- int err;
- int rv = 1;
+ int nb;
+ int err;
+ int rv = 1;
SSL_TRC(30, ("dtls_GatherData"));
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
gs->state = GS_HEADER;
gs->offset = 0;
- if (gs->dtlsPacketOffset == gs->dtlsPacket.len) { /* No data left */
+ if (gs->dtlsPacketOffset == gs->dtlsPacket.len) { /* No data left */
gs->dtlsPacketOffset = 0;
gs->dtlsPacket.len = 0;
/* Resize to the maximum possible size so we can fit a full datagram */
- /* This is the max fragment length for an encrypted fragment
- ** plus the size of the record header.
- ** This magic constant is copied from ssl3_GatherData, with 5 changed
- ** to 13 (the size of the record header).
- */
+ /* This is the max fragment length for an encrypted fragment
+ ** plus the size of the record header.
+ ** This magic constant is copied from ssl3_GatherData, with 5 changed
+ ** to 13 (the size of the record header).
+ */
if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) {
err = sslBuffer_Grow(&gs->dtlsPacket,
- MAX_FRAGMENT_LENGTH + 2048 + 13);
- if (err) { /* realloc has set error code to no mem. */
+ MAX_FRAGMENT_LENGTH + 2048 + 13);
+ if (err) { /* realloc has set error code to no mem. */
return err;
}
}
@@ -213,7 +212,8 @@ dtls_GatherData(sslSocket *ss, sslGather *gs, int flags)
*/
if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) {
SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet "
- "too short to contain header", SSL_GETPID(), ss->fd));
+ "too short to contain header",
+ SSL_GETPID(), ss->fd));
PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
gs->dtlsPacketOffset = 0;
gs->dtlsPacket.len = 0;
@@ -228,7 +228,8 @@ dtls_GatherData(sslSocket *ss, sslGather *gs, int flags)
if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) {
SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short "
- "to contain rest of body", SSL_GETPID(), ss->fd));
+ "to contain rest of body",
+ SSL_GETPID(), ss->fd));
PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
gs->dtlsPacketOffset = 0;
gs->dtlsPacket.len = 0;
@@ -238,14 +239,14 @@ dtls_GatherData(sslSocket *ss, sslGather *gs, int flags)
/* OK, we have at least one complete packet, copy into inbuf */
if (gs->remainder > gs->inbuf.space) {
- err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
- if (err) { /* realloc has set error code to no mem. */
- return err;
- }
+ err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
+ if (err) { /* realloc has set error code to no mem. */
+ return err;
+ }
}
memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset,
- gs->remainder);
+ gs->remainder);
gs->inbuf.len = gs->remainder;
gs->offset = gs->remainder;
gs->dtlsPacketOffset += gs->remainder;
@@ -255,16 +256,16 @@ dtls_GatherData(sslSocket *ss, sslGather *gs, int flags)
}
/* Gather in a record and when complete, Handle that record.
- * Repeat this until the handshake is complete,
+ * Repeat this until the handshake is complete,
* or until application data is available.
*
- * Returns 1 when the handshake is completed without error, or
+ * Returns 1 when the handshake is completed without error, or
* application data is available.
* Returns 0 if ssl3_GatherData hits EOF.
* Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
* Returns -2 on SECWouldBlock return from ssl3_HandleRecord.
*
- * Called from ssl_GatherRecord1stHandshake in sslcon.c,
+ * Called from ssl_GatherRecord1stHandshake in sslcon.c,
* and from SSL_ForceHandshake in sslsecur.c
* and from ssl3_GatherAppDataRecord below (<- DoRecv in sslsecur.c).
*
@@ -274,8 +275,8 @@ int
ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
{
SSL3Ciphertext cText;
- int rv;
- PRBool keepGoing = PR_TRUE;
+ int rv;
+ PRBool keepGoing = PR_TRUE;
SSL_TRC(30, ("ssl3_GatherCompleteHandshake"));
@@ -283,143 +284,145 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
* which requires the 1stHandshakeLock, which must be acquired before the
* RecvBufLock.
*/
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
do {
- PRBool handleRecordNow = PR_FALSE;
-
- ssl_GetSSL3HandshakeLock(ss);
-
- /* Without this, we may end up wrongly reporting
- * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the
- * peer while we are waiting to be restarted.
- */
- if (ss->ssl3.hs.restartTarget) {
- ssl_ReleaseSSL3HandshakeLock(ss);
- PORT_SetError(PR_WOULD_BLOCK_ERROR);
- return (int) SECFailure;
- }
-
- /* Treat an empty msgState like a NULL msgState. (Most of the time
- * when ssl3_HandleHandshake returns SECWouldBlock, it leaves
- * behind a non-NULL but zero-length msgState).
- * Test: async_cert_restart_server_sends_hello_request_first_in_separate_record
- */
- if (ss->ssl3.hs.msgState.buf) {
- if (ss->ssl3.hs.msgState.len == 0) {
- ss->ssl3.hs.msgState.buf = NULL;
- } else {
- handleRecordNow = PR_TRUE;
- }
- }
-
- ssl_ReleaseSSL3HandshakeLock(ss);
-
- if (handleRecordNow) {
- /* ssl3_HandleHandshake previously returned SECWouldBlock and the
- * as-yet-unprocessed plaintext of that previous handshake record.
- * We need to process it now before we overwrite it with the next
- * handshake record.
- */
- rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf);
- } else {
- /* bring in the next sslv3 record. */
- if (ss->recvdCloseNotify) {
- /* RFC 5246 Section 7.2.1:
- * Any data received after a closure alert is ignored.
- */
- return 0;
- }
- if (!IS_DTLS(ss)) {
- rv = ssl3_GatherData(ss, &ss->gs, flags);
- } else {
- rv = dtls_GatherData(ss, &ss->gs, flags);
-
- /* If we got a would block error, that means that no data was
- * available, so we check the timer to see if it's time to
- * retransmit */
- if (rv == SECFailure &&
- (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) {
- ssl_GetSSL3HandshakeLock(ss);
- dtls_CheckTimer(ss);
- ssl_ReleaseSSL3HandshakeLock(ss);
- /* Restore the error in case something succeeded */
- PORT_SetError(PR_WOULD_BLOCK_ERROR);
- }
- }
-
- if (rv <= 0) {
- return rv;
- }
-
- /* decipher it, and handle it if it's a handshake.
- * If it's application data, ss->gs.buf will not be empty upon return.
- * If it's a change cipher spec, alert, or handshake message,
- * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess.
- */
- cText.type = (SSL3ContentType)ss->gs.hdr[0];
- cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
-
- if (IS_DTLS(ss)) {
- int i;
-
- cText.version = dtls_DTLSVersionToTLSVersion(cText.version);
- /* DTLS sequence number */
- cText.seq_num.high = 0; cText.seq_num.low = 0;
- for (i = 0; i < 4; i++) {
- cText.seq_num.high <<= 8; cText.seq_num.low <<= 8;
- cText.seq_num.high |= ss->gs.hdr[3 + i];
- cText.seq_num.low |= ss->gs.hdr[7 + i];
- }
- }
-
- cText.buf = &ss->gs.inbuf;
- rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
- }
- if (rv < 0) {
- return ss->recvdCloseNotify ? 0 : rv;
- }
- if (ss->gs.buf.len > 0) {
- /* We have application data to return to the application. This
- * prioritizes returning application data to the application over
- * completing any renegotiation handshake we may be doing.
- */
- PORT_Assert(ss->firstHsDone);
- PORT_Assert(cText.type == content_application_data);
- break;
- }
-
- PORT_Assert(keepGoing);
- ssl_GetSSL3HandshakeLock(ss);
- if (ss->ssl3.hs.ws == idle_handshake) {
- /* We are done with the current handshake so stop trying to
- * handshake. Note that it would be safe to test ss->firstHsDone
- * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead,
- * we prioritize completing a renegotiation handshake over sending
- * application data.
- */
- PORT_Assert(ss->firstHsDone);
- PORT_Assert(!ss->ssl3.hs.canFalseStart);
- keepGoing = PR_FALSE;
- } else if (ss->ssl3.hs.canFalseStart) {
- /* Prioritize sending application data over trying to complete
- * the handshake if we're false starting.
- *
- * If we were to do this check at the beginning of the loop instead
- * of here, then this function would become be a no-op after
- * receiving the ServerHelloDone in the false start case, and we
- * would never complete the handshake.
- */
- PORT_Assert(!ss->firstHsDone);
-
- if (ssl3_WaitingForStartOfServerSecondRound(ss)) {
- keepGoing = PR_FALSE;
- } else {
- ss->ssl3.hs.canFalseStart = PR_FALSE;
- }
- }
- ssl_ReleaseSSL3HandshakeLock(ss);
+ PRBool handleRecordNow = PR_FALSE;
+
+ ssl_GetSSL3HandshakeLock(ss);
+
+ /* Without this, we may end up wrongly reporting
+ * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the
+ * peer while we are waiting to be restarted.
+ */
+ if (ss->ssl3.hs.restartTarget) {
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ PORT_SetError(PR_WOULD_BLOCK_ERROR);
+ return (int)SECFailure;
+ }
+
+ /* Treat an empty msgState like a NULL msgState. (Most of the time
+ * when ssl3_HandleHandshake returns SECWouldBlock, it leaves
+ * behind a non-NULL but zero-length msgState).
+ * Test: async_cert_restart_server_sends_hello_request_first_in_separate_record
+ */
+ if (ss->ssl3.hs.msgState.buf) {
+ if (ss->ssl3.hs.msgState.len == 0) {
+ ss->ssl3.hs.msgState.buf = NULL;
+ } else {
+ handleRecordNow = PR_TRUE;
+ }
+ }
+
+ ssl_ReleaseSSL3HandshakeLock(ss);
+
+ if (handleRecordNow) {
+ /* ssl3_HandleHandshake previously returned SECWouldBlock and the
+ * as-yet-unprocessed plaintext of that previous handshake record.
+ * We need to process it now before we overwrite it with the next
+ * handshake record.
+ */
+ rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf);
+ } else {
+ /* bring in the next sslv3 record. */
+ if (ss->recvdCloseNotify) {
+ /* RFC 5246 Section 7.2.1:
+ * Any data received after a closure alert is ignored.
+ */
+ return 0;
+ }
+ if (!IS_DTLS(ss)) {
+ rv = ssl3_GatherData(ss, &ss->gs, flags);
+ } else {
+ rv = dtls_GatherData(ss, &ss->gs, flags);
+
+ /* If we got a would block error, that means that no data was
+ * available, so we check the timer to see if it's time to
+ * retransmit */
+ if (rv == SECFailure &&
+ (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) {
+ ssl_GetSSL3HandshakeLock(ss);
+ dtls_CheckTimer(ss);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ /* Restore the error in case something succeeded */
+ PORT_SetError(PR_WOULD_BLOCK_ERROR);
+ }
+ }
+
+ if (rv <= 0) {
+ return rv;
+ }
+
+ /* decipher it, and handle it if it's a handshake.
+ * If it's application data, ss->gs.buf will not be empty upon return.
+ * If it's a change cipher spec, alert, or handshake message,
+ * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess.
+ */
+ cText.type = (SSL3ContentType)ss->gs.hdr[0];
+ cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
+
+ if (IS_DTLS(ss)) {
+ int i;
+
+ cText.version = dtls_DTLSVersionToTLSVersion(cText.version);
+ /* DTLS sequence number */
+ cText.seq_num.high = 0;
+ cText.seq_num.low = 0;
+ for (i = 0; i < 4; i++) {
+ cText.seq_num.high <<= 8;
+ cText.seq_num.low <<= 8;
+ cText.seq_num.high |= ss->gs.hdr[3 + i];
+ cText.seq_num.low |= ss->gs.hdr[7 + i];
+ }
+ }
+
+ cText.buf = &ss->gs.inbuf;
+ rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
+ }
+ if (rv < 0) {
+ return ss->recvdCloseNotify ? 0 : rv;
+ }
+ if (ss->gs.buf.len > 0) {
+ /* We have application data to return to the application. This
+ * prioritizes returning application data to the application over
+ * completing any renegotiation handshake we may be doing.
+ */
+ PORT_Assert(ss->firstHsDone);
+ PORT_Assert(cText.type == content_application_data);
+ break;
+ }
+
+ PORT_Assert(keepGoing);
+ ssl_GetSSL3HandshakeLock(ss);
+ if (ss->ssl3.hs.ws == idle_handshake) {
+ /* We are done with the current handshake so stop trying to
+ * handshake. Note that it would be safe to test ss->firstHsDone
+ * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead,
+ * we prioritize completing a renegotiation handshake over sending
+ * application data.
+ */
+ PORT_Assert(ss->firstHsDone);
+ PORT_Assert(!ss->ssl3.hs.canFalseStart);
+ keepGoing = PR_FALSE;
+ } else if (ss->ssl3.hs.canFalseStart) {
+ /* Prioritize sending application data over trying to complete
+ * the handshake if we're false starting.
+ *
+ * If we were to do this check at the beginning of the loop instead
+ * of here, then this function would become be a no-op after
+ * receiving the ServerHelloDone in the false start case, and we
+ * would never complete the handshake.
+ */
+ PORT_Assert(!ss->firstHsDone);
+
+ if (ssl3_WaitingForServerSecondRound(ss)) {
+ keepGoing = PR_FALSE;
+ } else {
+ ss->ssl3.hs.canFalseStart = PR_FALSE;
+ }
+ }
+ ssl_ReleaseSSL3HandshakeLock(ss);
} while (keepGoing);
ss->gs.readOffset = 0;
@@ -441,14 +444,14 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
int
ssl3_GatherAppDataRecord(sslSocket *ss, int flags)
{
- int rv;
+ int rv;
/* ssl3_GatherCompleteHandshake requires both of these locks. */
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
do {
- rv = ssl3_GatherCompleteHandshake(ss, flags);
+ rv = ssl3_GatherCompleteHandshake(ss, flags);
} while (rv > 0 && ss->gs.buf.len == 0);
return rv;
diff --git a/chromium/net/third_party/nss/ssl/ssl3prot.h b/chromium/net/third_party/nss/ssl/ssl3prot.h
index 848bdee7a20..928d059651e 100644
--- a/chromium/net/third_party/nss/ssl/ssl3prot.h
+++ b/chromium/net/third_party/nss/ssl/ssl3prot.h
@@ -17,57 +17,57 @@ typedef PRUint16 SSL3ProtocolVersion;
/* The TLS 1.3 draft version. Used to avoid negotiating
* between incompatible pre-standard TLS 1.3 drafts.
* TODO(ekr@rtfm.com): Remove when TLS 1.3 is published. */
-#define TLS_1_3_DRAFT_VERSION 3
+#define TLS_1_3_DRAFT_VERSION 11
typedef PRUint16 ssl3CipherSuite;
/* The cipher suites are defined in sslproto.h */
-#define MAX_CERT_TYPES 10
-#define MAX_COMPRESSION_METHODS 10
-#define MAX_MAC_LENGTH 64
-#define MAX_PADDING_LENGTH 64
-#define MAX_KEY_LENGTH 64
-#define EXPORT_KEY_LENGTH 5
-#define SSL3_RANDOM_LENGTH 32
+#define MAX_CERT_TYPES 10
+#define MAX_COMPRESSION_METHODS 10
+#define MAX_MAC_LENGTH 64
+#define MAX_PADDING_LENGTH 64
+#define MAX_KEY_LENGTH 64
+#define EXPORT_KEY_LENGTH 5
+#define SSL3_RANDOM_LENGTH 32
-#define SSL3_RECORD_HEADER_LENGTH 5
+#define SSL3_RECORD_HEADER_LENGTH 5
/* SSL3_RECORD_HEADER_LENGTH + epoch/sequence_number */
-#define DTLS_RECORD_HEADER_LENGTH 13
+#define DTLS_RECORD_HEADER_LENGTH 13
-#define MAX_FRAGMENT_LENGTH 16384
+#define MAX_FRAGMENT_LENGTH 16384
typedef enum {
content_change_cipher_spec = 20,
- content_alert = 21,
- content_handshake = 22,
- content_application_data = 23
+ content_alert = 21,
+ content_handshake = 22,
+ content_application_data = 23
} SSL3ContentType;
typedef struct {
- SSL3ContentType type;
+ SSL3ContentType type;
SSL3ProtocolVersion version;
- PRUint16 length;
- SECItem fragment;
+ PRUint16 length;
+ SECItem fragment;
} SSL3Plaintext;
typedef struct {
- SSL3ContentType type;
+ SSL3ContentType type;
SSL3ProtocolVersion version;
- PRUint16 length;
- SECItem fragment;
+ PRUint16 length;
+ SECItem fragment;
} SSL3Compressed;
typedef struct {
- SECItem content;
+ SECItem content;
SSL3Opaque MAC[MAX_MAC_LENGTH];
} SSL3GenericStreamCipher;
typedef struct {
- SECItem content;
+ SECItem content;
SSL3Opaque MAC[MAX_MAC_LENGTH];
- PRUint8 padding[MAX_PADDING_LENGTH];
- PRUint8 padding_length;
+ PRUint8 padding[MAX_PADDING_LENGTH];
+ PRUint8 padding_length;
} SSL3GenericBlockCipher;
typedef enum { change_cipher_spec_choice = 1 } SSL3ChangeCipherSpecChoice;
@@ -76,68 +76,72 @@ typedef struct {
SSL3ChangeCipherSpecChoice choice;
} SSL3ChangeCipherSpec;
-typedef enum { alert_warning = 1, alert_fatal = 2 } SSL3AlertLevel;
+typedef enum { alert_warning = 1,
+ alert_fatal = 2 } SSL3AlertLevel;
typedef enum {
- close_notify = 0,
- unexpected_message = 10,
- bad_record_mac = 20,
- decryption_failed_RESERVED = 21, /* do not send; see RFC 5246 */
- record_overflow = 22, /* TLS only */
- decompression_failure = 30,
- handshake_failure = 40,
- no_certificate = 41, /* SSL3 only, NOT TLS */
- bad_certificate = 42,
+ close_notify = 0,
+ unexpected_message = 10,
+ bad_record_mac = 20,
+ decryption_failed_RESERVED = 21, /* do not send; see RFC 5246 */
+ record_overflow = 22, /* TLS only */
+ decompression_failure = 30,
+ handshake_failure = 40,
+ no_certificate = 41, /* SSL3 only, NOT TLS */
+ bad_certificate = 42,
unsupported_certificate = 43,
- certificate_revoked = 44,
- certificate_expired = 45,
- certificate_unknown = 46,
- illegal_parameter = 47,
-
-/* All alerts below are TLS only. */
- unknown_ca = 48,
- access_denied = 49,
- decode_error = 50,
- decrypt_error = 51,
- export_restriction = 60,
- protocol_version = 70,
- insufficient_security = 71,
- internal_error = 80,
- inappropriate_fallback = 86, /* could also be sent for SSLv3 */
- user_canceled = 90,
- no_renegotiation = 100,
-
-/* Alerts for client hello extensions */
- unsupported_extension = 110,
- certificate_unobtainable = 111,
- unrecognized_name = 112,
+ certificate_revoked = 44,
+ certificate_expired = 45,
+ certificate_unknown = 46,
+ illegal_parameter = 47,
+
+ /* All alerts below are TLS only. */
+ unknown_ca = 48,
+ access_denied = 49,
+ decode_error = 50,
+ decrypt_error = 51,
+ export_restriction = 60,
+ protocol_version = 70,
+ insufficient_security = 71,
+ internal_error = 80,
+ inappropriate_fallback = 86, /* could also be sent for SSLv3 */
+ user_canceled = 90,
+ no_renegotiation = 100,
+
+ /* Alerts for client hello extensions */
+ missing_extension = 109,
+ unsupported_extension = 110,
+ certificate_unobtainable = 111,
+ unrecognized_name = 112,
bad_certificate_status_response = 113,
- bad_certificate_hash_value = 114,
- no_application_protocol = 120
+ bad_certificate_hash_value = 114,
+ no_application_protocol = 120
} SSL3AlertDescription;
typedef struct {
- SSL3AlertLevel level;
+ SSL3AlertLevel level;
SSL3AlertDescription description;
} SSL3Alert;
typedef enum {
- hello_request = 0,
- client_hello = 1,
- server_hello = 2,
+ hello_request = 0,
+ client_hello = 1,
+ server_hello = 2,
hello_verify_request = 3,
- new_session_ticket = 4,
- certificate = 11,
+ new_session_ticket = 4,
+ hello_retry_request = 6,
+ encrypted_extensions = 8,
+ certificate = 11,
server_key_exchange = 12,
certificate_request = 13,
- server_hello_done = 14,
- certificate_verify = 15,
+ server_hello_done = 14,
+ certificate_verify = 15,
client_key_exchange = 16,
- finished = 20,
- certificate_status = 22,
- next_proto = 67,
- encrypted_extensions = 203,
+ finished = 20,
+ certificate_status = 22,
+ next_proto = 67,
+ channelid_encrypted_extensions = 203
} SSL3HandshakeType;
typedef struct {
@@ -154,20 +158,20 @@ typedef struct {
} SSL3SessionID;
typedef struct {
- SSL3ProtocolVersion client_version;
- SSL3Random random;
- SSL3SessionID session_id;
- SECItem cipher_suites;
- PRUint8 cm_count;
- SSLCompressionMethod compression_methods[MAX_COMPRESSION_METHODS];
+ SSL3ProtocolVersion client_version;
+ SSL3Random random;
+ SSL3SessionID session_id;
+ SECItem cipher_suites;
+ PRUint8 cm_count;
+ SSLCompressionMethod compression_methods[MAX_COMPRESSION_METHODS];
} SSL3ClientHello;
-typedef struct {
- SSL3ProtocolVersion server_version;
- SSL3Random random;
- SSL3SessionID session_id;
- ssl3CipherSuite cipher_suite;
- SSLCompressionMethod compression_method;
+typedef struct {
+ SSL3ProtocolVersion server_version;
+ SSL3Random random;
+ SSL3SessionID session_id;
+ ssl3CipherSuite cipher_suite;
+ SSLCompressionMethod compression_method;
} SSL3ServerHello;
typedef struct {
@@ -245,50 +249,25 @@ typedef struct {
} SSL3ServerKeyExchange;
typedef enum {
- ct_RSA_sign = 1,
- ct_DSS_sign = 2,
- ct_RSA_fixed_DH = 3,
- ct_DSS_fixed_DH = 4,
- ct_RSA_ephemeral_DH = 5,
- ct_DSS_ephemeral_DH = 6,
- ct_ECDSA_sign = 64,
- ct_RSA_fixed_ECDH = 65,
- ct_ECDSA_fixed_ECDH = 66
+ ct_RSA_sign = 1,
+ ct_DSS_sign = 2,
+ ct_RSA_fixed_DH = 3,
+ ct_DSS_fixed_DH = 4,
+ ct_RSA_ephemeral_DH = 5,
+ ct_DSS_ephemeral_DH = 6,
+ ct_ECDSA_sign = 64,
+ ct_RSA_fixed_ECDH = 65,
+ ct_ECDSA_fixed_ECDH = 66
} SSL3ClientCertificateType;
-typedef SECItem *SSL3DistinquishedName;
-
typedef struct {
SSL3Opaque client_version[2];
SSL3Opaque random[46];
} SSL3RSAPreMasterSecret;
-typedef SECItem SSL3EncryptedPreMasterSecret;
-
-
typedef SSL3Opaque SSL3MasterSecret[48];
-typedef enum { implicit, explicit } SSL3PublicValueEncoding;
-
-typedef struct {
- union {
- SSL3Opaque implicit;
- SECItem explicit;
- } dh_public;
-} SSL3ClientDiffieHellmanPublic;
-
-typedef struct {
- union {
- SSL3EncryptedPreMasterSecret rsa;
- SSL3ClientDiffieHellmanPublic diffie_helman;
- } exchange_keys;
-} SSL3ClientKeyExchange;
-
-typedef SSL3Hashes SSL3PreSignedCertificateVerify;
-
-typedef SECItem SSL3CertificateVerify;
-
typedef enum {
sender_client = 0x434c4e54,
sender_server = 0x53525652
@@ -310,11 +289,11 @@ typedef struct {
typedef struct {
PRUint32 received_timestamp;
PRUint32 ticket_lifetime_hint;
- SECItem ticket;
+ SECItem ticket;
} NewSessionTicket;
typedef enum {
- CLIENT_AUTH_ANONYMOUS = 0,
+ CLIENT_AUTH_ANONYMOUS = 0,
CLIENT_AUTH_CERTIFICATE = 1
} ClientAuthenticationType;
@@ -325,10 +304,10 @@ typedef struct {
} identity;
} ClientIdentity;
-#define SESS_TICKET_KEY_NAME_LEN 16
-#define SESS_TICKET_KEY_NAME_PREFIX "NSS!"
+#define SESS_TICKET_KEY_NAME_LEN 16
+#define SESS_TICKET_KEY_NAME_PREFIX "NSS!"
#define SESS_TICKET_KEY_NAME_PREFIX_LEN 4
-#define SESS_TICKET_KEY_VAR_NAME_LEN 12
+#define SESS_TICKET_KEY_VAR_NAME_LEN 12
typedef struct {
unsigned char *key_name;
@@ -339,6 +318,6 @@ typedef struct {
#define TLS_EX_SESS_TICKET_MAC_LENGTH 32
-#define TLS_STE_NO_SERVER_NAME -1
+#define TLS_STE_NO_SERVER_NAME -1
#endif /* __ssl3proto_h_ */
diff --git a/chromium/net/third_party/nss/ssl/sslauth.c b/chromium/net/third_party/nss/ssl/sslauth.c
index 03b23b48d12..e78a513a6ea 100644
--- a/chromium/net/third_party/nss/ssl/sslauth.c
+++ b/chromium/net/third_party/nss/ssl/sslauth.c
@@ -17,12 +17,12 @@ SSL_PeerCertificate(PRFileDesc *fd)
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
- SSL_GETPID(), fd));
- return 0;
+ SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
+ SSL_GETPID(), fd));
+ return 0;
}
if (ss->opt.useSecurity && ss->sec.peerCert) {
- return CERT_DupCertificate(ss->sec.peerCert);
+ return CERT_DupCertificate(ss->sec.peerCert);
}
return 0;
}
@@ -38,27 +38,27 @@ SSL_PeerCertificateChain(PRFileDesc *fd)
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificateChain",
- SSL_GETPID(), fd));
- return NULL;
+ SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificateChain",
+ SSL_GETPID(), fd));
+ return NULL;
}
if (!ss->opt.useSecurity || !ss->sec.peerCert) {
- PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
- return NULL;
+ PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
+ return NULL;
}
chain = CERT_NewCertList();
if (!chain) {
- return NULL;
+ return NULL;
}
cert = CERT_DupCertificate(ss->sec.peerCert);
if (CERT_AddCertToListTail(chain, cert) != SECSuccess) {
- goto loser;
+ goto loser;
}
for (cur = ss->ssl3.peerCertChain; cur; cur = cur->next) {
- cert = CERT_DupCertificate(cur->cert);
- if (CERT_AddCertToListTail(chain, cert) != SECSuccess) {
- goto loser;
- }
+ cert = CERT_DupCertificate(cur->cert);
+ if (CERT_AddCertToListTail(chain, cert) != SECSuccess) {
+ goto loser;
+ }
}
return chain;
@@ -75,27 +75,25 @@ SSL_LocalCertificate(PRFileDesc *fd)
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
- SSL_GETPID(), fd));
- return NULL;
+ SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
+ SSL_GETPID(), fd));
+ return NULL;
}
if (ss->opt.useSecurity) {
- if (ss->sec.localCert) {
- return CERT_DupCertificate(ss->sec.localCert);
- }
- if (ss->sec.ci.sid && ss->sec.ci.sid->localCert) {
- return CERT_DupCertificate(ss->sec.ci.sid->localCert);
- }
+ if (ss->sec.localCert) {
+ return CERT_DupCertificate(ss->sec.localCert);
+ }
+ if (ss->sec.ci.sid && ss->sec.ci.sid->localCert) {
+ return CERT_DupCertificate(ss->sec.ci.sid->localCert);
+ }
}
return NULL;
}
-
-
/* NEED LOCKS IN HERE. */
SECStatus
SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
- char **ip, char **sp)
+ char **ip, char **sp)
{
sslSocket *ss;
const char *cipherName;
@@ -103,74 +101,81 @@ SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SecurityStatus",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SecurityStatus",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
- if (cp) *cp = 0;
- if (kp0) *kp0 = 0;
- if (kp1) *kp1 = 0;
- if (ip) *ip = 0;
- if (sp) *sp = 0;
+ if (cp)
+ *cp = 0;
+ if (kp0)
+ *kp0 = 0;
+ if (kp1)
+ *kp1 = 0;
+ if (ip)
+ *ip = 0;
+ if (sp)
+ *sp = 0;
if (op) {
- *op = SSL_SECURITY_STATUS_OFF;
+ *op = SSL_SECURITY_STATUS_OFF;
}
if (ss->opt.useSecurity && ss->enoughFirstHsDone) {
- if (ss->version < SSL_LIBRARY_VERSION_3_0) {
- cipherName = ssl_cipherName[ss->sec.cipherType];
- } else {
- cipherName = ssl3_cipherName[ss->sec.cipherType];
- }
- PORT_Assert(cipherName);
- if (cipherName) {
- if (PORT_Strstr(cipherName, "DES")) isDes = PR_TRUE;
+ if (ss->version < SSL_LIBRARY_VERSION_3_0) {
+ cipherName = ssl_cipherName[ss->sec.cipherType];
+ } else {
+ cipherName = ssl3_cipherName[ss->sec.cipherType];
+ }
+ PORT_Assert(cipherName);
+ if (cipherName) {
+ if (PORT_Strstr(cipherName, "DES"))
+ isDes = PR_TRUE;
if (cp) {
*cp = PORT_Strdup(cipherName);
}
}
- if (kp0) {
- *kp0 = ss->sec.keyBits;
- if (isDes) *kp0 = (*kp0 * 7) / 8;
- }
- if (kp1) {
- *kp1 = ss->sec.secretKeyBits;
- if (isDes) *kp1 = (*kp1 * 7) / 8;
- }
- if (op) {
- if (ss->sec.keyBits == 0) {
- *op = SSL_SECURITY_STATUS_OFF;
- } else if (ss->sec.secretKeyBits < 90) {
- *op = SSL_SECURITY_STATUS_ON_LOW;
-
- } else {
- *op = SSL_SECURITY_STATUS_ON_HIGH;
- }
- }
-
- if (ip || sp) {
- CERTCertificate *cert;
-
- cert = ss->sec.peerCert;
- if (cert) {
- if (ip) {
- *ip = CERT_NameToAscii(&cert->issuer);
- }
- if (sp) {
- *sp = CERT_NameToAscii(&cert->subject);
- }
- } else {
- if (ip) {
- *ip = PORT_Strdup("no certificate");
- }
- if (sp) {
- *sp = PORT_Strdup("no certificate");
- }
- }
- }
+ if (kp0) {
+ *kp0 = ss->sec.keyBits;
+ if (isDes)
+ *kp0 = (*kp0 * 7) / 8;
+ }
+ if (kp1) {
+ *kp1 = ss->sec.secretKeyBits;
+ if (isDes)
+ *kp1 = (*kp1 * 7) / 8;
+ }
+ if (op) {
+ if (ss->sec.keyBits == 0) {
+ *op = SSL_SECURITY_STATUS_OFF;
+ } else if (ss->sec.secretKeyBits < 90) {
+ *op = SSL_SECURITY_STATUS_ON_LOW;
+ } else {
+ *op = SSL_SECURITY_STATUS_ON_HIGH;
+ }
+ }
+
+ if (ip || sp) {
+ CERTCertificate *cert;
+
+ cert = ss->sec.peerCert;
+ if (cert) {
+ if (ip) {
+ *ip = CERT_NameToAscii(&cert->issuer);
+ }
+ if (sp) {
+ *sp = CERT_NameToAscii(&cert->subject);
+ }
+ } else {
+ if (ip) {
+ *ip = PORT_Strdup("no certificate");
+ }
+ if (sp) {
+ *sp = PORT_Strdup("no certificate");
+ }
+ }
+ }
}
return SECSuccess;
@@ -186,9 +191,9 @@ SSL_AuthCertificateHook(PRFileDesc *s, SSLAuthCertificate func, void *arg)
ss = ssl_FindSocket(s);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in AuthCertificateHook",
- SSL_GETPID(), s));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in AuthCertificateHook",
+ SSL_GETPID(), s));
+ return SECFailure;
}
ss->authCertificate = func;
@@ -198,17 +203,17 @@ SSL_AuthCertificateHook(PRFileDesc *s, SSLAuthCertificate func, void *arg)
}
/* NEED LOCKS IN HERE. */
-SECStatus
+SECStatus
SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
- void *arg)
+ void *arg)
{
sslSocket *ss;
ss = ssl_FindSocket(s);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
- SSL_GETPID(), s));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
+ SSL_GETPID(), s));
+ return SECFailure;
}
ss->getClientAuthData = func;
@@ -218,14 +223,15 @@ SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
SECStatus
SSL_SetClientChannelIDCallback(PRFileDesc *fd,
- SSLClientChannelIDCallback callback,
- void *arg) {
+ SSLClientChannelIDCallback callback,
+ void *arg)
+{
sslSocket *ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetClientChannelIDCallback",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetClientChannelIDCallback",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
ss->getChannelID = callback;
@@ -234,100 +240,77 @@ SSL_SetClientChannelIDCallback(PRFileDesc *fd,
return SECSuccess;
}
-#ifdef NSS_PLATFORM_CLIENT_AUTH
-/* NEED LOCKS IN HERE. */
-SECStatus
-SSL_GetPlatformClientAuthDataHook(PRFileDesc *s,
- SSLGetPlatformClientAuthData func,
- void *arg)
-{
- sslSocket *ss;
-
- ss = ssl_FindSocket(s);
- if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in GetPlatformClientAuthDataHook",
- SSL_GETPID(), s));
- return SECFailure;
- }
-
- ss->getPlatformClientAuthData = func;
- ss->getPlatformClientAuthDataArg = arg;
- return SECSuccess;
-}
-#endif /* NSS_PLATFORM_CLIENT_AUTH */
-
/* NEED LOCKS IN HERE. */
-SECStatus
+SECStatus
SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
{
sslSocket *ss;
ss = ssl_FindSocket(s);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
- SSL_GETPID(), s));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
+ SSL_GETPID(), s));
+ return SECFailure;
}
ss->pkcs11PinArg = arg;
return SECSuccess;
}
-
-/* This is the "default" authCert callback function. It is called when a
+/* This is the "default" authCert callback function. It is called when a
* certificate message is received from the peer and the local application
* has not registered an authCert callback function.
*/
SECStatus
SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
{
- SECStatus rv;
- CERTCertDBHandle * handle;
- sslSocket * ss;
- SECCertUsage certUsage;
- const char * hostname = NULL;
- PRTime now = PR_Now();
- SECItemArray * certStatusArray;
-
+ SECStatus rv;
+ CERTCertDBHandle *handle;
+ sslSocket *ss;
+ SECCertUsage certUsage;
+ const char *hostname = NULL;
+ PRTime now = PR_Now();
+ SECItemArray *certStatusArray;
+
ss = ssl_FindSocket(fd);
PORT_Assert(ss != NULL);
if (!ss) {
- return SECFailure;
+ return SECFailure;
}
handle = (CERTCertDBHandle *)arg;
certStatusArray = &ss->sec.ci.sid->peerCertStatus;
if (certStatusArray->len) {
- PORT_SetError(0);
- if (CERT_CacheOCSPResponseFromSideChannel(handle, ss->sec.peerCert, now,
- &certStatusArray->items[0],
- ss->pkcs11PinArg)
- != SECSuccess) {
- PORT_Assert(PR_GetError() != 0);
- }
+ PORT_SetError(0);
+ if (CERT_CacheOCSPResponseFromSideChannel(handle, ss->sec.peerCert, now,
+ &certStatusArray->items[0],
+ ss->pkcs11PinArg) !=
+ SECSuccess) {
+ PORT_Assert(PR_GetError() != 0);
+ }
}
/* this may seem backwards, but isn't. */
certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
rv = CERT_VerifyCert(handle, ss->sec.peerCert, checkSig, certUsage,
- now, ss->pkcs11PinArg, NULL);
+ now, ss->pkcs11PinArg, NULL);
+
+ if (rv != SECSuccess || isServer)
+ return rv;
- if ( rv != SECSuccess || isServer )
- return rv;
-
/* cert is OK. This is the client side of an SSL connection.
* Now check the name field in the cert against the desired hostname.
* NB: This is our only defense against Man-In-The-Middle (MITM) attacks!
*/
hostname = ss->url;
if (hostname && hostname[0])
- rv = CERT_VerifyCertName(ss->sec.peerCert, hostname);
- else
- rv = SECFailure;
+ rv = CERT_VerifyCertName(ss->sec.peerCert, hostname);
+ else
+ rv = SECFailure;
if (rv != SECSuccess)
- PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
+ PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
return rv;
}
diff --git a/chromium/net/third_party/nss/ssl/sslcon.c b/chromium/net/third_party/nss/ssl/sslcon.c
index ccd00260ec2..95d27275f44 100644
--- a/chromium/net/third_party/nss/ssl/sslcon.c
+++ b/chromium/net/third_party/nss/ssl/sslcon.c
@@ -1,4 +1,4 @@
-/*
+/*
* SSL v2 handshake functions, and functions common to SSL2 and SSL3.
*
* This Source Code Form is subject to the terms of the Mozilla Public
@@ -9,8 +9,8 @@
#include "cert.h"
#include "secitem.h"
#include "sechash.h"
-#include "cryptohi.h" /* for SGN_ funcs */
-#include "keyhi.h" /* for SECKEY_ high level functions. */
+#include "cryptohi.h" /* for SGN_ funcs */
+#include "keyhi.h" /* for SECKEY_ high level functions. */
#include "ssl.h"
#include "sslimpl.h"
#include "sslproto.h"
@@ -18,75 +18,78 @@
#include "sslerr.h"
#include "pk11func.h"
#include "prinit.h"
-#include "prtime.h" /* for PR_Now() */
+#include "prtime.h" /* for PR_Now() */
static PRBool policyWasSet;
#define ssl2_NUM_SUITES_IMPLEMENTED 6
-/* This list is sent back to the client when the client-hello message
+/* This list is sent back to the client when the client-hello message
* contains no overlapping ciphers, so the client can report what ciphers
* are supported by the server. Unlike allCipherSuites (above), this list
- * is sorted by descending preference, not by cipherSuite number.
+ * is sorted by descending preference, not by cipherSuite number.
*/
+/* clang-format off */
static const PRUint8 implementedCipherSuites[ssl2_NUM_SUITES_IMPLEMENTED * 3] = {
- SSL_CK_RC4_128_WITH_MD5, 0x00, 0x80,
- SSL_CK_RC2_128_CBC_WITH_MD5, 0x00, 0x80,
- SSL_CK_DES_192_EDE3_CBC_WITH_MD5, 0x00, 0xC0,
- SSL_CK_DES_64_CBC_WITH_MD5, 0x00, 0x40,
- SSL_CK_RC4_128_EXPORT40_WITH_MD5, 0x00, 0x80,
- SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, 0x00, 0x80
+ SSL_CK_RC4_128_WITH_MD5, 0x00, 0x80,
+ SSL_CK_RC2_128_CBC_WITH_MD5, 0x00, 0x80,
+ SSL_CK_DES_192_EDE3_CBC_WITH_MD5, 0x00, 0xC0,
+ SSL_CK_DES_64_CBC_WITH_MD5, 0x00, 0x40,
+ SSL_CK_RC4_128_EXPORT40_WITH_MD5, 0x00, 0x80,
+ SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, 0x00, 0x80
};
+
typedef struct ssl2SpecsStr {
- PRUint8 nkm; /* do this many hashes to generate key material. */
- PRUint8 nkd; /* size of readKey and writeKey in bytes. */
- PRUint8 blockSize;
- PRUint8 blockShift;
+ PRUint8 nkm; /* do this many hashes to generate key material. */
+ PRUint8 nkd; /* size of readKey and writeKey in bytes. */
+ PRUint8 blockSize;
+ PRUint8 blockShift;
CK_MECHANISM_TYPE mechanism;
- PRUint8 keyLen; /* cipher symkey size in bytes. */
- PRUint8 pubLen; /* publicly reveal this many bytes of key. */
- PRUint8 ivLen; /* length of IV data at *ca. */
+ PRUint8 keyLen; /* cipher symkey size in bytes. */
+ PRUint8 pubLen; /* publicly reveal this many bytes of key. */
+ PRUint8 ivLen; /* length of IV data at *ca. */
} ssl2Specs;
static const ssl2Specs ssl_Specs[] = {
-/* NONE */
- { 0, 0, 0, 0, },
-/* SSL_CK_RC4_128_WITH_MD5 */
- { 2, 16, 1, 0, CKM_RC4, 16, 0, 0, },
-/* SSL_CK_RC4_128_EXPORT40_WITH_MD5 */
- { 2, 16, 1, 0, CKM_RC4, 16, 11, 0, },
-/* SSL_CK_RC2_128_CBC_WITH_MD5 */
- { 2, 16, 8, 3, CKM_RC2_CBC, 16, 0, 8, },
-/* SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5 */
- { 2, 16, 8, 3, CKM_RC2_CBC, 16, 11, 8, },
-/* SSL_CK_IDEA_128_CBC_WITH_MD5 */
- { 0, 0, 0, 0, },
-/* SSL_CK_DES_64_CBC_WITH_MD5 */
- { 1, 8, 8, 3, CKM_DES_CBC, 8, 0, 8, },
-/* SSL_CK_DES_192_EDE3_CBC_WITH_MD5 */
- { 3, 24, 8, 3, CKM_DES3_CBC, 24, 0, 8, },
+ /* NONE */
+ { 0, 0, 0, 0 },
+ /* SSL_CK_RC4_128_WITH_MD5 */
+ { 2, 16, 1, 0, CKM_RC4, 16, 0, 0 },
+ /* SSL_CK_RC4_128_EXPORT40_WITH_MD5 */
+ { 2, 16, 1, 0, CKM_RC4, 16, 11, 0 },
+ /* SSL_CK_RC2_128_CBC_WITH_MD5 */
+ { 2, 16, 8, 3, CKM_RC2_CBC, 16, 0, 8 },
+ /* SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5 */
+ { 2, 16, 8, 3, CKM_RC2_CBC, 16, 11, 8 },
+ /* SSL_CK_IDEA_128_CBC_WITH_MD5 */
+ { 0, 0, 0, 0 },
+ /* SSL_CK_DES_64_CBC_WITH_MD5 */
+ { 1, 8, 8, 3, CKM_DES_CBC, 8, 0, 8 },
+ /* SSL_CK_DES_192_EDE3_CBC_WITH_MD5 */
+ { 3, 24, 8, 3, CKM_DES3_CBC, 24, 0, 8 },
};
+/* clang-format on */
-#define SET_ERROR_CODE /* reminder */
-#define TEST_FOR_FAILURE /* reminder */
+#define SET_ERROR_CODE /* reminder */
+#define TEST_FOR_FAILURE /* reminder */
/*
** Put a string tag in the library so that we can examine an executable
** and see what kind of security it supports.
*/
const char *ssl_version = "SECURITY_VERSION:"
- " +us"
- " +export"
+ " +us"
+ " +export"
#ifdef TRACE
- " +trace"
+ " +trace"
#endif
#ifdef DEBUG
- " +debug"
+ " +debug"
#endif
- ;
+ ;
-const char * const ssl_cipherName[] = {
+const char *const ssl_cipherName[] = {
"unknown",
"RC4",
"RC4-Export",
@@ -99,100 +102,98 @@ const char * const ssl_cipherName[] = {
"unknown", /* was fortezza, NO LONGER USED */
};
-
/* bit-masks, showing which SSLv2 suites are allowed.
* lsb corresponds to first cipher suite in allCipherSuites[].
*/
-static PRUint16 allowedByPolicy; /* all off by default */
-static PRUint16 maybeAllowedByPolicy; /* all off by default */
-static PRUint16 chosenPreference = 0xff; /* all on by default */
+static PRUint16 allowedByPolicy; /* all off by default */
+static PRUint16 maybeAllowedByPolicy; /* all off by default */
+static PRUint16 chosenPreference = 0xff; /* all on by default */
/* bit values for the above two bit masks */
-#define SSL_CB_RC4_128_WITH_MD5 (1 << SSL_CK_RC4_128_WITH_MD5)
-#define SSL_CB_RC4_128_EXPORT40_WITH_MD5 (1 << SSL_CK_RC4_128_EXPORT40_WITH_MD5)
-#define SSL_CB_RC2_128_CBC_WITH_MD5 (1 << SSL_CK_RC2_128_CBC_WITH_MD5)
+#define SSL_CB_RC4_128_WITH_MD5 (1 << SSL_CK_RC4_128_WITH_MD5)
+#define SSL_CB_RC4_128_EXPORT40_WITH_MD5 (1 << SSL_CK_RC4_128_EXPORT40_WITH_MD5)
+#define SSL_CB_RC2_128_CBC_WITH_MD5 (1 << SSL_CK_RC2_128_CBC_WITH_MD5)
#define SSL_CB_RC2_128_CBC_EXPORT40_WITH_MD5 (1 << SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5)
-#define SSL_CB_IDEA_128_CBC_WITH_MD5 (1 << SSL_CK_IDEA_128_CBC_WITH_MD5)
-#define SSL_CB_DES_64_CBC_WITH_MD5 (1 << SSL_CK_DES_64_CBC_WITH_MD5)
-#define SSL_CB_DES_192_EDE3_CBC_WITH_MD5 (1 << SSL_CK_DES_192_EDE3_CBC_WITH_MD5)
-#define SSL_CB_IMPLEMENTED \
- (SSL_CB_RC4_128_WITH_MD5 | \
- SSL_CB_RC4_128_EXPORT40_WITH_MD5 | \
- SSL_CB_RC2_128_CBC_WITH_MD5 | \
- SSL_CB_RC2_128_CBC_EXPORT40_WITH_MD5 | \
- SSL_CB_DES_64_CBC_WITH_MD5 | \
- SSL_CB_DES_192_EDE3_CBC_WITH_MD5)
-
+#define SSL_CB_IDEA_128_CBC_WITH_MD5 (1 << SSL_CK_IDEA_128_CBC_WITH_MD5)
+#define SSL_CB_DES_64_CBC_WITH_MD5 (1 << SSL_CK_DES_64_CBC_WITH_MD5)
+#define SSL_CB_DES_192_EDE3_CBC_WITH_MD5 (1 << SSL_CK_DES_192_EDE3_CBC_WITH_MD5)
+#define SSL_CB_IMPLEMENTED \
+ (SSL_CB_RC4_128_WITH_MD5 | \
+ SSL_CB_RC4_128_EXPORT40_WITH_MD5 | \
+ SSL_CB_RC2_128_CBC_WITH_MD5 | \
+ SSL_CB_RC2_128_CBC_EXPORT40_WITH_MD5 | \
+ SSL_CB_DES_64_CBC_WITH_MD5 | \
+ SSL_CB_DES_192_EDE3_CBC_WITH_MD5)
/* Construct a socket's list of cipher specs from the global default values.
*/
static SECStatus
-ssl2_ConstructCipherSpecs(sslSocket *ss)
+ssl2_ConstructCipherSpecs(sslSocket *ss)
{
- PRUint8 * cs = NULL;
- unsigned int allowed;
- unsigned int count;
- int ssl3_count = 0;
- int final_count;
- int i;
- SECStatus rv;
+ PRUint8 *cs = NULL;
+ unsigned int allowed;
+ unsigned int count;
+ int ssl3_count = 0;
+ int final_count;
+ int i;
+ SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
count = 0;
PORT_Assert(ss != 0);
- allowed = !ss->opt.enableSSL2 ? 0 :
- (ss->allowedByPolicy & ss->chosenPreference & SSL_CB_IMPLEMENTED);
+ allowed = !ss->opt.enableSSL2 ? 0 : (ss->allowedByPolicy &
+ ss->chosenPreference & SSL_CB_IMPLEMENTED);
while (allowed) {
- if (allowed & 1)
- ++count;
- allowed >>= 1;
+ if (allowed & 1)
+ ++count;
+ allowed >>= 1;
}
- /* Call ssl3_config_match_init() once here,
+ /* Call ssl3_config_match_init() once here,
* instead of inside ssl3_ConstructV2CipherSpecsHack(),
- * because the latter gets called twice below,
+ * because the latter gets called twice below,
* and then again in ssl2_BeginClientHandshake().
*/
ssl3_config_match_init(ss);
/* ask SSL3 how many cipher suites it has. */
rv = ssl3_ConstructV2CipherSpecsHack(ss, NULL, &ssl3_count);
- if (rv < 0)
- return rv;
+ if (rv < 0)
+ return rv;
count += ssl3_count;
/* Allocate memory to hold cipher specs */
if (count > 0)
- cs = (PRUint8*) PORT_Alloc(count * 3);
+ cs = (PRUint8 *)PORT_Alloc(count * 3);
else
- PORT_SetError(SSL_ERROR_SSL_DISABLED);
+ PORT_SetError(SSL_ERROR_SSL_DISABLED);
if (cs == NULL)
- return SECFailure;
+ return SECFailure;
if (ss->cipherSpecs != NULL) {
- PORT_Free(ss->cipherSpecs);
+ PORT_Free(ss->cipherSpecs);
}
- ss->cipherSpecs = cs;
+ ss->cipherSpecs = cs;
ss->sizeCipherSpecs = count * 3;
/* fill in cipher specs for SSL2 cipher suites */
- allowed = !ss->opt.enableSSL2 ? 0 :
- (ss->allowedByPolicy & ss->chosenPreference & SSL_CB_IMPLEMENTED);
+ allowed = !ss->opt.enableSSL2 ? 0 : (ss->allowedByPolicy &
+ ss->chosenPreference & SSL_CB_IMPLEMENTED);
for (i = 0; i < ssl2_NUM_SUITES_IMPLEMENTED * 3; i += 3) {
- const PRUint8 * hs = implementedCipherSuites + i;
- int ok = allowed & (1U << hs[0]);
- if (ok) {
- cs[0] = hs[0];
- cs[1] = hs[1];
- cs[2] = hs[2];
- cs += 3;
- }
+ const PRUint8 *hs = implementedCipherSuites + i;
+ int ok = allowed & (1U << hs[0]);
+ if (ok) {
+ cs[0] = hs[0];
+ cs[1] = hs[1];
+ cs[2] = hs[2];
+ cs += 3;
+ }
}
/* now have SSL3 add its suites onto the end */
rv = ssl3_ConstructV2CipherSpecsHack(ss, cs, &final_count);
-
+
/* adjust for any difference between first pass and second pass */
ss->sizeCipherSpecs -= (ssl3_count - final_count) * 3;
@@ -202,7 +203,7 @@ ssl2_ConstructCipherSpecs(sslSocket *ss)
/* This function is called immediately after ssl2_ConstructCipherSpecs()
** at the beginning of a handshake. It detects cases where a protocol
** (e.g. SSL2 or SSL3) is logically enabled, but all its cipher suites
-** for that protocol have been disabled. If such cases, it clears the
+** for that protocol have been disabled. If such cases, it clears the
** enable bit for the protocol. If no protocols remain enabled, or
** if no cipher suites are found, it sets the error code and returns
** SECFailure, otherwise it returns SECSuccess.
@@ -210,69 +211,69 @@ ssl2_ConstructCipherSpecs(sslSocket *ss)
static SECStatus
ssl2_CheckConfigSanity(sslSocket *ss)
{
- unsigned int allowed;
- int ssl3CipherCount = 0;
- SECStatus rv;
+ unsigned int allowed;
+ int ssl3CipherCount = 0;
+ SECStatus rv;
/* count the SSL2 and SSL3 enabled ciphers.
* if either is zero, clear the socket's enable for that protocol.
*/
if (!ss->cipherSpecs)
- goto disabled;
+ goto disabled;
allowed = ss->allowedByPolicy & ss->chosenPreference;
- if (! allowed)
- ss->opt.enableSSL2 = PR_FALSE; /* not really enabled if no ciphers */
+ if (!allowed)
+ ss->opt.enableSSL2 = PR_FALSE; /* not really enabled if no ciphers */
/* ssl3_config_match_init was called in ssl2_ConstructCipherSpecs(). */
/* Ask how many ssl3 CipherSuites were enabled. */
rv = ssl3_ConstructV2CipherSpecsHack(ss, NULL, &ssl3CipherCount);
if (rv != SECSuccess || ssl3CipherCount <= 0) {
- /* SSL3/TLS not really enabled if no ciphers */
- ss->vrange.min = SSL_LIBRARY_VERSION_NONE;
- ss->vrange.max = SSL_LIBRARY_VERSION_NONE;
+ /* SSL3/TLS not really enabled if no ciphers */
+ ss->vrange.min = SSL_LIBRARY_VERSION_NONE;
+ ss->vrange.max = SSL_LIBRARY_VERSION_NONE;
}
if (!ss->opt.enableSSL2 && SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
- SSL_DBG(("%d: SSL[%d]: Can't handshake! all versions disabled.",
- SSL_GETPID(), ss->fd));
-disabled:
- PORT_SetError(SSL_ERROR_SSL_DISABLED);
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: Can't handshake! all versions disabled.",
+ SSL_GETPID(), ss->fd));
+ disabled:
+ PORT_SetError(SSL_ERROR_SSL_DISABLED);
+ return SECFailure;
}
return SECSuccess;
}
-/*
+/*
* Since this is a global (not per-socket) setting, we cannot use the
* HandshakeLock to protect this. Probably want a global lock.
*/
SECStatus
ssl2_SetPolicy(PRInt32 which, PRInt32 policy)
{
- PRUint32 bitMask;
- SECStatus rv = SECSuccess;
+ PRUint32 bitMask;
+ SECStatus rv = SECSuccess;
which &= 0x000f;
bitMask = 1 << which;
if (!(bitMask & SSL_CB_IMPLEMENTED)) {
- PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
+ return SECFailure;
}
if (policy == SSL_ALLOWED) {
- allowedByPolicy |= bitMask;
- maybeAllowedByPolicy |= bitMask;
+ allowedByPolicy |= bitMask;
+ maybeAllowedByPolicy |= bitMask;
} else if (policy == SSL_RESTRICTED) {
- allowedByPolicy &= ~bitMask;
- maybeAllowedByPolicy |= bitMask;
+ allowedByPolicy &= ~bitMask;
+ maybeAllowedByPolicy |= bitMask;
} else {
- allowedByPolicy &= ~bitMask;
- maybeAllowedByPolicy &= ~bitMask;
+ allowedByPolicy &= ~bitMask;
+ maybeAllowedByPolicy &= ~bitMask;
}
- allowedByPolicy &= SSL_CB_IMPLEMENTED;
- maybeAllowedByPolicy &= SSL_CB_IMPLEMENTED;
+ allowedByPolicy &= SSL_CB_IMPLEMENTED;
+ maybeAllowedByPolicy &= SSL_CB_IMPLEMENTED;
policyWasSet = PR_TRUE;
return rv;
@@ -281,70 +282,70 @@ ssl2_SetPolicy(PRInt32 which, PRInt32 policy)
SECStatus
ssl2_GetPolicy(PRInt32 which, PRInt32 *oPolicy)
{
- PRUint32 bitMask;
- PRInt32 policy;
+ PRUint32 bitMask;
+ PRInt32 policy;
which &= 0x000f;
bitMask = 1 << which;
/* Caller assures oPolicy is not null. */
if (!(bitMask & SSL_CB_IMPLEMENTED)) {
- PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
- *oPolicy = SSL_NOT_ALLOWED;
- return SECFailure;
+ PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
+ *oPolicy = SSL_NOT_ALLOWED;
+ return SECFailure;
}
if (maybeAllowedByPolicy & bitMask) {
- policy = (allowedByPolicy & bitMask) ? SSL_ALLOWED : SSL_RESTRICTED;
+ policy = (allowedByPolicy & bitMask) ? SSL_ALLOWED : SSL_RESTRICTED;
} else {
- policy = SSL_NOT_ALLOWED;
+ policy = SSL_NOT_ALLOWED;
}
*oPolicy = policy;
return SECSuccess;
}
-/*
+/*
* Since this is a global (not per-socket) setting, we cannot use the
* HandshakeLock to protect this. Probably want a global lock.
* Called from SSL_CipherPrefSetDefault in sslsock.c
- * These changes have no effect on any sslSockets already created.
+ * These changes have no effect on any sslSockets already created.
*/
SECStatus
ssl2_CipherPrefSetDefault(PRInt32 which, PRBool enabled)
{
- PRUint32 bitMask;
-
+ PRUint32 bitMask;
+
which &= 0x000f;
bitMask = 1 << which;
if (!(bitMask & SSL_CB_IMPLEMENTED)) {
- PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
+ return SECFailure;
}
if (enabled)
- chosenPreference |= bitMask;
+ chosenPreference |= bitMask;
else
- chosenPreference &= ~bitMask;
+ chosenPreference &= ~bitMask;
chosenPreference &= SSL_CB_IMPLEMENTED;
return SECSuccess;
}
-SECStatus
+SECStatus
ssl2_CipherPrefGetDefault(PRInt32 which, PRBool *enabled)
{
- PRBool rv = PR_FALSE;
- PRUint32 bitMask;
+ PRBool rv = PR_FALSE;
+ PRUint32 bitMask;
which &= 0x000f;
bitMask = 1 << which;
if (!(bitMask & SSL_CB_IMPLEMENTED)) {
- PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
- *enabled = PR_FALSE;
- return SECFailure;
+ PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
+ *enabled = PR_FALSE;
+ return SECFailure;
}
rv = (PRBool)((chosenPreference & bitMask) != 0);
@@ -352,41 +353,41 @@ ssl2_CipherPrefGetDefault(PRInt32 which, PRBool *enabled)
return SECSuccess;
}
-SECStatus
+SECStatus
ssl2_CipherPrefSet(sslSocket *ss, PRInt32 which, PRBool enabled)
{
- PRUint32 bitMask;
-
+ PRUint32 bitMask;
+
which &= 0x000f;
bitMask = 1 << which;
if (!(bitMask & SSL_CB_IMPLEMENTED)) {
- PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
+ return SECFailure;
}
if (enabled)
- ss->chosenPreference |= bitMask;
+ ss->chosenPreference |= bitMask;
else
- ss->chosenPreference &= ~bitMask;
+ ss->chosenPreference &= ~bitMask;
ss->chosenPreference &= SSL_CB_IMPLEMENTED;
return SECSuccess;
}
-SECStatus
+SECStatus
ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled)
{
- PRBool rv = PR_FALSE;
- PRUint32 bitMask;
+ PRBool rv = PR_FALSE;
+ PRUint32 bitMask;
which &= 0x000f;
bitMask = 1 << which;
if (!(bitMask & SSL_CB_IMPLEMENTED)) {
- PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
- *enabled = PR_FALSE;
- return SECFailure;
+ PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
+ *enabled = PR_FALSE;
+ return SECFailure;
}
rv = (PRBool)((ss->chosenPreference & bitMask) != 0);
@@ -394,51 +395,49 @@ ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled)
return SECSuccess;
}
-
/* copy global default policy into socket. */
-void
+void
ssl2_InitSocketPolicy(sslSocket *ss)
{
- ss->allowedByPolicy = allowedByPolicy;
- ss->maybeAllowedByPolicy = maybeAllowedByPolicy;
- ss->chosenPreference = chosenPreference;
+ ss->allowedByPolicy = allowedByPolicy;
+ ss->maybeAllowedByPolicy = maybeAllowedByPolicy;
+ ss->chosenPreference = chosenPreference;
}
-
/************************************************************************/
/* Called from ssl2_CreateSessionCypher(), which already holds handshake lock.
*/
static SECStatus
-ssl2_CreateMAC(sslSecurityInfo *sec, SECItem *readKey, SECItem *writeKey,
- int cipherChoice)
+ssl2_CreateMAC(sslSecurityInfo *sec, SECItem *readKey, SECItem *writeKey,
+ int cipherChoice)
{
switch (cipherChoice) {
- case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
- case SSL_CK_RC2_128_CBC_WITH_MD5:
- case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
- case SSL_CK_RC4_128_WITH_MD5:
- case SSL_CK_DES_64_CBC_WITH_MD5:
- case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:
- sec->hash = HASH_GetHashObject(HASH_AlgMD5);
- if (SECITEM_CopyItem(0, &sec->sendSecret, writeKey) ||
- SECITEM_CopyItem(0, &sec->rcvSecret, readKey)) {
- return SECFailure;
- }
- break;
-
- default:
- PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
- return SECFailure;
+ case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
+ case SSL_CK_RC2_128_CBC_WITH_MD5:
+ case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
+ case SSL_CK_RC4_128_WITH_MD5:
+ case SSL_CK_DES_64_CBC_WITH_MD5:
+ case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:
+ sec->hash = HASH_GetHashObject(HASH_AlgMD5);
+ if (SECITEM_CopyItem(0, &sec->sendSecret, writeKey) ||
+ SECITEM_CopyItem(0, &sec->rcvSecret, readKey)) {
+ return SECFailure;
+ }
+ break;
+
+ default:
+ PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
+ return SECFailure;
}
sec->hashcx = (*sec->hash->create)();
if (sec->hashcx == NULL)
- return SECFailure;
+ return SECFailure;
return SECSuccess;
}
/************************************************************************
- * All the Send functions below must acquire and release the socket's
+ * All the Send functions below must acquire and release the socket's
* xmitBufLock.
*/
@@ -451,115 +450,115 @@ ssl2_GetSendBuffer(sslSocket *ss, unsigned int len)
PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
if (len < 128) {
- len = 128;
+ len = 128;
}
if (len > ss->sec.ci.sendBuf.space) {
- rv = sslBuffer_Grow(&ss->sec.ci.sendBuf, len);
- if (rv != SECSuccess) {
- SSL_DBG(("%d: SSL[%d]: ssl2_GetSendBuffer failed, tried to get %d bytes",
- SSL_GETPID(), ss->fd, len));
- rv = SECFailure;
- }
+ rv = sslBuffer_Grow(&ss->sec.ci.sendBuf, len);
+ if (rv != SECSuccess) {
+ SSL_DBG(("%d: SSL[%d]: ssl2_GetSendBuffer failed, tried to get %d bytes",
+ SSL_GETPID(), ss->fd, len));
+ rv = SECFailure;
+ }
}
return rv;
}
/* Called from:
- * ssl2_ClientSetupSessionCypher() <- ssl2_HandleServerHelloMessage()
- * ssl2_HandleRequestCertificate() <- ssl2_HandleMessage() <-
- ssl_Do1stHandshake()
- * ssl2_HandleMessage() <- ssl_Do1stHandshake()
- * ssl2_HandleServerHelloMessage() <- ssl_Do1stHandshake()
- after ssl2_BeginClientHandshake()
- * ssl2_HandleClientHelloMessage() <- ssl_Do1stHandshake()
- after ssl2_BeginServerHandshake()
- *
+ * ssl2_ClientSetupSessionCypher() <- ssl2_HandleServerHelloMessage()
+ * ssl2_HandleRequestCertificate() <- ssl2_HandleMessage()
+ <- ssl_Do1stHandshake()
+ * ssl2_HandleMessage() <- ssl_Do1stHandshake()
+ * ssl2_HandleServerHelloMessage() <- ssl_Do1stHandshake()
+ after ssl2_BeginClientHandshake()
+ * ssl2_HandleClientHelloMessage() <- ssl_Do1stHandshake()
+ after ssl2_BeginServerHandshake()
+ *
* Acquires and releases the socket's xmitBufLock.
- */
+ */
int
ssl2_SendErrorMessage(sslSocket *ss, int error)
{
int rv;
PRUint8 msg[SSL_HL_ERROR_HBYTES];
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
msg[0] = SSL_MT_ERROR;
msg[1] = MSB(error);
msg[2] = LSB(error);
- ssl_GetXmitBufLock(ss); /***************************************/
+ ssl_GetXmitBufLock(ss); /***************************************/
SSL_TRC(3, ("%d: SSL[%d]: sending error %d", SSL_GETPID(), ss->fd, error));
ss->handshakeBegun = 1;
rv = (*ss->sec.send)(ss, msg, sizeof(msg), 0);
if (rv >= 0) {
- rv = SECSuccess;
+ rv = SECSuccess;
}
- ssl_ReleaseXmitBufLock(ss); /***************************************/
+ ssl_ReleaseXmitBufLock(ss); /***************************************/
return rv;
}
-/* Called from ssl2_TryToFinish().
+/* Called from ssl2_TryToFinish().
* Acquires and releases the socket's xmitBufLock.
*/
static SECStatus
ssl2_SendClientFinishedMessage(sslSocket *ss)
{
- SECStatus rv = SECSuccess;
- int sent;
- PRUint8 msg[1 + SSL_CONNECTIONID_BYTES];
+ SECStatus rv = SECSuccess;
+ int sent;
+ PRUint8 msg[1 + SSL_CONNECTIONID_BYTES];
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
- ssl_GetXmitBufLock(ss); /***************************************/
+ ssl_GetXmitBufLock(ss); /***************************************/
if (ss->sec.ci.sentFinished == 0) {
- ss->sec.ci.sentFinished = 1;
+ ss->sec.ci.sentFinished = 1;
- SSL_TRC(3, ("%d: SSL[%d]: sending client-finished",
- SSL_GETPID(), ss->fd));
+ SSL_TRC(3, ("%d: SSL[%d]: sending client-finished",
+ SSL_GETPID(), ss->fd));
- msg[0] = SSL_MT_CLIENT_FINISHED;
- PORT_Memcpy(msg+1, ss->sec.ci.connectionID,
- sizeof(ss->sec.ci.connectionID));
+ msg[0] = SSL_MT_CLIENT_FINISHED;
+ PORT_Memcpy(msg + 1, ss->sec.ci.connectionID,
+ sizeof(ss->sec.ci.connectionID));
- DUMP_MSG(29, (ss, msg, 1 + sizeof(ss->sec.ci.connectionID)));
- sent = (*ss->sec.send)(ss, msg, 1 + sizeof(ss->sec.ci.connectionID), 0);
- rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
+ DUMP_MSG(29, (ss, msg, 1 + sizeof(ss->sec.ci.connectionID)));
+ sent = (*ss->sec.send)(ss, msg, 1 + sizeof(ss->sec.ci.connectionID), 0);
+ rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
}
- ssl_ReleaseXmitBufLock(ss); /***************************************/
+ ssl_ReleaseXmitBufLock(ss); /***************************************/
return rv;
}
-/* Called from
+/* Called from
* ssl2_HandleClientSessionKeyMessage() <- ssl2_HandleClientHelloMessage()
- * ssl2_HandleClientHelloMessage() <- ssl_Do1stHandshake()
- after ssl2_BeginServerHandshake()
+ * ssl2_HandleClientHelloMessage() <- ssl_Do1stHandshake()
+ after ssl2_BeginServerHandshake()
* Acquires and releases the socket's xmitBufLock.
*/
static SECStatus
ssl2_SendServerVerifyMessage(sslSocket *ss)
{
- PRUint8 * msg;
- int sendLen;
- int sent;
- SECStatus rv;
+ PRUint8 *msg;
+ int sendLen;
+ int sent;
+ SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
- ssl_GetXmitBufLock(ss); /***************************************/
+ ssl_GetXmitBufLock(ss); /***************************************/
sendLen = 1 + SSL_CHALLENGE_BYTES;
rv = ssl2_GetSendBuffer(ss, sendLen);
if (rv != SECSuccess) {
- goto done;
+ goto done;
}
msg = ss->sec.ci.sendBuf.buf;
msg[0] = SSL_MT_SERVER_VERIFY;
- PORT_Memcpy(msg+1, ss->sec.ci.clientChallenge, SSL_CHALLENGE_BYTES);
+ PORT_Memcpy(msg + 1, ss->sec.ci.clientChallenge, SSL_CHALLENGE_BYTES);
DUMP_MSG(29, (ss, msg, sendLen));
sent = (*ss->sec.send)(ss, msg, sendLen, 0);
@@ -567,93 +566,92 @@ ssl2_SendServerVerifyMessage(sslSocket *ss)
rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
done:
- ssl_ReleaseXmitBufLock(ss); /***************************************/
+ ssl_ReleaseXmitBufLock(ss); /***************************************/
return rv;
}
-/* Called from ssl2_TryToFinish().
+/* Called from ssl2_TryToFinish().
* Acquires and releases the socket's xmitBufLock.
*/
static SECStatus
ssl2_SendServerFinishedMessage(sslSocket *ss)
{
- sslSessionID * sid;
- PRUint8 * msg;
- int sendLen, sent;
- SECStatus rv = SECSuccess;
+ sslSessionID *sid;
+ PRUint8 *msg;
+ int sendLen, sent;
+ SECStatus rv = SECSuccess;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
- ssl_GetXmitBufLock(ss); /***************************************/
+ ssl_GetXmitBufLock(ss); /***************************************/
if (ss->sec.ci.sentFinished == 0) {
- ss->sec.ci.sentFinished = 1;
- PORT_Assert(ss->sec.ci.sid != 0);
- sid = ss->sec.ci.sid;
-
- SSL_TRC(3, ("%d: SSL[%d]: sending server-finished",
- SSL_GETPID(), ss->fd));
-
- sendLen = 1 + sizeof(sid->u.ssl2.sessionID);
- rv = ssl2_GetSendBuffer(ss, sendLen);
- if (rv != SECSuccess) {
- goto done;
- }
-
- msg = ss->sec.ci.sendBuf.buf;
- msg[0] = SSL_MT_SERVER_FINISHED;
- PORT_Memcpy(msg+1, sid->u.ssl2.sessionID,
- sizeof(sid->u.ssl2.sessionID));
-
- DUMP_MSG(29, (ss, msg, sendLen));
- sent = (*ss->sec.send)(ss, msg, sendLen, 0);
-
- if (sent < 0) {
- /* If send failed, it is now a bogus session-id */
- if (ss->sec.uncache)
- (*ss->sec.uncache)(sid);
- rv = (SECStatus)sent;
- } else if (!ss->opt.noCache) {
- if (sid->cached == never_cached) {
- (*ss->sec.cache)(sid);
- }
- rv = SECSuccess;
- }
- ssl_FreeSID(sid);
- ss->sec.ci.sid = 0;
+ ss->sec.ci.sentFinished = 1;
+ PORT_Assert(ss->sec.ci.sid != 0);
+ sid = ss->sec.ci.sid;
+
+ SSL_TRC(3, ("%d: SSL[%d]: sending server-finished",
+ SSL_GETPID(), ss->fd));
+
+ sendLen = 1 + sizeof(sid->u.ssl2.sessionID);
+ rv = ssl2_GetSendBuffer(ss, sendLen);
+ if (rv != SECSuccess) {
+ goto done;
+ }
+
+ msg = ss->sec.ci.sendBuf.buf;
+ msg[0] = SSL_MT_SERVER_FINISHED;
+ PORT_Memcpy(msg + 1, sid->u.ssl2.sessionID,
+ sizeof(sid->u.ssl2.sessionID));
+
+ DUMP_MSG(29, (ss, msg, sendLen));
+ sent = (*ss->sec.send)(ss, msg, sendLen, 0);
+
+ if (sent < 0) {
+ /* If send failed, it is now a bogus session-id */
+ if (ss->sec.uncache)
+ (*ss->sec.uncache)(sid);
+ rv = (SECStatus)sent;
+ } else if (!ss->opt.noCache) {
+ if (sid->cached == never_cached) {
+ (*ss->sec.cache)(sid);
+ }
+ rv = SECSuccess;
+ }
+ ssl_FreeSID(sid);
+ ss->sec.ci.sid = 0;
}
done:
- ssl_ReleaseXmitBufLock(ss); /***************************************/
+ ssl_ReleaseXmitBufLock(ss); /***************************************/
return rv;
}
-/* Called from ssl2_ClientSetupSessionCypher() <-
- * ssl2_HandleServerHelloMessage()
- * after ssl2_BeginClientHandshake()
+/* Called from ssl2_ClientSetupSessionCypher() <- ssl2_HandleServerHelloMessage()
+ * after ssl2_BeginClientHandshake()
* Acquires and releases the socket's xmitBufLock.
*/
static SECStatus
ssl2_SendSessionKeyMessage(sslSocket *ss, int cipher, int keySize,
- PRUint8 *ca, int caLen,
- PRUint8 *ck, int ckLen,
- PRUint8 *ek, int ekLen)
+ PRUint8 *ca, int caLen,
+ PRUint8 *ck, int ckLen,
+ PRUint8 *ek, int ekLen)
{
- PRUint8 * msg;
- int sendLen;
- int sent;
- SECStatus rv;
+ PRUint8 *msg;
+ int sendLen;
+ int sent;
+ SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
- ssl_GetXmitBufLock(ss); /***************************************/
+ ssl_GetXmitBufLock(ss); /***************************************/
sendLen = SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen + caLen;
rv = ssl2_GetSendBuffer(ss, sendLen);
- if (rv != SECSuccess)
- goto done;
+ if (rv != SECSuccess)
+ goto done;
SSL_TRC(3, ("%d: SSL[%d]: sending client-session-key",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
msg = ss->sec.ci.sendBuf.buf;
msg[0] = SSL_MT_CLIENT_MASTER_KEY;
@@ -666,40 +664,40 @@ ssl2_SendSessionKeyMessage(sslSocket *ss, int cipher, int keySize,
msg[7] = LSB(ekLen);
msg[8] = MSB(caLen);
msg[9] = LSB(caLen);
- PORT_Memcpy(msg+SSL_HL_CLIENT_MASTER_KEY_HBYTES, ck, ckLen);
- PORT_Memcpy(msg+SSL_HL_CLIENT_MASTER_KEY_HBYTES+ckLen, ek, ekLen);
- PORT_Memcpy(msg+SSL_HL_CLIENT_MASTER_KEY_HBYTES+ckLen+ekLen, ca, caLen);
+ PORT_Memcpy(msg + SSL_HL_CLIENT_MASTER_KEY_HBYTES, ck, ckLen);
+ PORT_Memcpy(msg + SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen, ek, ekLen);
+ PORT_Memcpy(msg + SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen, ca, caLen);
DUMP_MSG(29, (ss, msg, sendLen));
sent = (*ss->sec.send)(ss, msg, sendLen, 0);
rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
done:
- ssl_ReleaseXmitBufLock(ss); /***************************************/
+ ssl_ReleaseXmitBufLock(ss); /***************************************/
return rv;
}
-/* Called from ssl2_TriggerNextMessage() <- ssl2_HandleMessage()
+/* Called from ssl2_TriggerNextMessage() <- ssl2_HandleMessage()
* Acquires and releases the socket's xmitBufLock.
*/
static SECStatus
ssl2_SendCertificateRequestMessage(sslSocket *ss)
{
- PRUint8 * msg;
- int sent;
- int sendLen;
- SECStatus rv;
+ PRUint8 *msg;
+ int sent;
+ int sendLen;
+ SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
- ssl_GetXmitBufLock(ss); /***************************************/
+ ssl_GetXmitBufLock(ss); /***************************************/
sendLen = SSL_HL_REQUEST_CERTIFICATE_HBYTES + SSL_CHALLENGE_BYTES;
rv = ssl2_GetSendBuffer(ss, sendLen);
- if (rv != SECSuccess)
- goto done;
+ if (rv != SECSuccess)
+ goto done;
SSL_TRC(3, ("%d: SSL[%d]: sending certificate request",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
/* Generate random challenge for client to encrypt */
PK11_GenerateRandom(ss->sec.ci.serverChallenge, SSL_CHALLENGE_BYTES);
@@ -707,14 +705,14 @@ ssl2_SendCertificateRequestMessage(sslSocket *ss)
msg = ss->sec.ci.sendBuf.buf;
msg[0] = SSL_MT_REQUEST_CERTIFICATE;
msg[1] = SSL_AT_MD5_WITH_RSA_ENCRYPTION;
- PORT_Memcpy(msg + SSL_HL_REQUEST_CERTIFICATE_HBYTES,
+ PORT_Memcpy(msg + SSL_HL_REQUEST_CERTIFICATE_HBYTES,
ss->sec.ci.serverChallenge, SSL_CHALLENGE_BYTES);
DUMP_MSG(29, (ss, msg, sendLen));
sent = (*ss->sec.send)(ss, msg, sendLen, 0);
rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
done:
- ssl_ReleaseXmitBufLock(ss); /***************************************/
+ ssl_ReleaseXmitBufLock(ss); /***************************************/
return rv;
}
@@ -722,23 +720,23 @@ done:
* Acquires and releases the socket's xmitBufLock.
*/
static int
-ssl2_SendCertificateResponseMessage(sslSocket *ss, SECItem *cert,
+ssl2_SendCertificateResponseMessage(sslSocket *ss, SECItem *cert,
SECItem *encCode)
{
PRUint8 *msg;
int rv, sendLen;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
- ssl_GetXmitBufLock(ss); /***************************************/
+ ssl_GetXmitBufLock(ss); /***************************************/
sendLen = SSL_HL_CLIENT_CERTIFICATE_HBYTES + encCode->len + cert->len;
rv = ssl2_GetSendBuffer(ss, sendLen);
- if (rv)
- goto done;
+ if (rv)
+ goto done;
SSL_TRC(3, ("%d: SSL[%d]: sending certificate response",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
msg = ss->sec.ci.sendBuf.buf;
msg[0] = SSL_MT_CLIENT_CERTIFICATE;
@@ -749,46 +747,46 @@ ssl2_SendCertificateResponseMessage(sslSocket *ss, SECItem *cert,
msg[5] = LSB(encCode->len);
PORT_Memcpy(msg + SSL_HL_CLIENT_CERTIFICATE_HBYTES, cert->data, cert->len);
PORT_Memcpy(msg + SSL_HL_CLIENT_CERTIFICATE_HBYTES + cert->len,
- encCode->data, encCode->len);
+ encCode->data, encCode->len);
DUMP_MSG(29, (ss, msg, sendLen));
rv = (*ss->sec.send)(ss, msg, sendLen, 0);
if (rv >= 0) {
- rv = SECSuccess;
+ rv = SECSuccess;
}
done:
- ssl_ReleaseXmitBufLock(ss); /***************************************/
+ ssl_ReleaseXmitBufLock(ss); /***************************************/
return rv;
}
/********************************************************************
-** Send functions above this line must aquire & release the socket's
-** xmitBufLock.
+** Send functions above this line must aquire & release the socket's
+** xmitBufLock.
** All the ssl2_Send functions below this line are called vis ss->sec.send
-** and require that the caller hold the xmitBufLock.
+** and require that the caller hold the xmitBufLock.
*/
/*
** Called from ssl2_SendStream, ssl2_SendBlock, but not from ssl2_SendClear.
*/
static SECStatus
-ssl2_CalcMAC(PRUint8 * result,
- sslSecurityInfo * sec,
- const PRUint8 * data,
- unsigned int dataLen,
- unsigned int paddingLen)
+ssl2_CalcMAC(PRUint8 *result,
+ sslSecurityInfo *sec,
+ const PRUint8 *data,
+ unsigned int dataLen,
+ unsigned int paddingLen)
{
- const PRUint8 * secret = sec->sendSecret.data;
- unsigned int secretLen = sec->sendSecret.len;
- unsigned long sequenceNumber = sec->sendSequence;
- unsigned int nout;
- PRUint8 seq[4];
- PRUint8 padding[32];/* XXX max blocksize? */
+ const PRUint8 *secret = sec->sendSecret.data;
+ unsigned int secretLen = sec->sendSecret.len;
+ unsigned long sequenceNumber = sec->sendSequence;
+ unsigned int nout;
+ PRUint8 seq[4];
+ PRUint8 padding[32]; /* XXX max blocksize? */
if (!sec->hash || !sec->hash->length)
- return SECSuccess;
+ return SECSuccess;
if (!sec->hashcx)
- return SECFailure;
+ return SECFailure;
/* Reset hash function */
(*sec->hash->begin)(sec->hashcx);
@@ -799,10 +797,10 @@ ssl2_CalcMAC(PRUint8 * result,
PORT_Memset(padding, paddingLen, paddingLen);
(*sec->hash->update)(sec->hashcx, padding, paddingLen);
- seq[0] = (PRUint8) (sequenceNumber >> 24);
- seq[1] = (PRUint8) (sequenceNumber >> 16);
- seq[2] = (PRUint8) (sequenceNumber >> 8);
- seq[3] = (PRUint8) (sequenceNumber);
+ seq[0] = (PRUint8)(sequenceNumber >> 24);
+ seq[1] = (PRUint8)(sequenceNumber >> 16);
+ seq[2] = (PRUint8)(sequenceNumber >> 8);
+ seq[3] = (PRUint8)(sequenceNumber);
PRINT_BUF(60, (0, "calc-mac secret:", secret, secretLen));
PRINT_BUF(60, (0, "calc-mac data:", data, dataLen));
@@ -823,76 +821,76 @@ ssl2_CalcMAC(PRUint8 * result,
** assuming the MAC is 16 bytes long and the padding is a max of 7 bytes
** long. This gives an additional 9 bytes of slop to work within.
*/
-#define MAX_STREAM_CYPHER_LEN 0x7fe0
-#define MAX_BLOCK_CYPHER_LEN 0x3fe0
+#define MAX_STREAM_CYPHER_LEN 0x7fe0
+#define MAX_BLOCK_CYPHER_LEN 0x3fe0
/*
-** Send some data in the clear.
+** Send some data in the clear.
** Package up data with the length header and send it.
**
** Return count of bytes successfully written, or negative number (failure).
*/
-static PRInt32
+static PRInt32
ssl2_SendClear(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags)
{
- PRUint8 * out;
- int rv;
+ PRUint8 *out;
+ int rv;
unsigned int amount;
- int count = 0;
+ int count = 0;
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes in the clear",
- SSL_GETPID(), ss->fd, len));
- PRINT_BUF(50, (ss, "clear data:", (PRUint8*) in, len));
+ SSL_GETPID(), ss->fd, len));
+ PRINT_BUF(50, (ss, "clear data:", (PRUint8 *)in, len));
while (len) {
- amount = PR_MIN( len, MAX_STREAM_CYPHER_LEN );
- if (amount + 2 > ss->sec.writeBuf.space) {
- rv = sslBuffer_Grow(&ss->sec.writeBuf, amount + 2);
- if (rv != SECSuccess) {
- count = rv;
- break;
- }
- }
- out = ss->sec.writeBuf.buf;
-
- /*
- ** Construct message.
- */
- out[0] = 0x80 | MSB(amount);
- out[1] = LSB(amount);
- PORT_Memcpy(&out[2], in, amount);
-
- /* Now send the data */
- rv = ssl_DefSend(ss, out, amount + 2, flags & ~ssl_SEND_FLAG_MASK);
- if (rv < 0) {
- if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {
- rv = 0;
- } else {
- /* Return short write if some data already went out... */
- if (count == 0)
- count = rv;
- break;
- }
- }
-
- if ((unsigned)rv < (amount + 2)) {
- /* Short write. Save the data and return. */
- if (ssl_SaveWriteData(ss, out + rv, amount + 2 - rv)
- == SECFailure) {
- count = SECFailure;
- } else {
- count += amount;
- ss->sec.sendSequence++;
- }
- break;
- }
-
- ss->sec.sendSequence++;
- in += amount;
- count += amount;
- len -= amount;
+ amount = PR_MIN(len, MAX_STREAM_CYPHER_LEN);
+ if (amount + 2 > ss->sec.writeBuf.space) {
+ rv = sslBuffer_Grow(&ss->sec.writeBuf, amount + 2);
+ if (rv != SECSuccess) {
+ count = rv;
+ break;
+ }
+ }
+ out = ss->sec.writeBuf.buf;
+
+ /*
+ ** Construct message.
+ */
+ out[0] = 0x80 | MSB(amount);
+ out[1] = LSB(amount);
+ PORT_Memcpy(&out[2], in, amount);
+
+ /* Now send the data */
+ rv = ssl_DefSend(ss, out, amount + 2, flags & ~ssl_SEND_FLAG_MASK);
+ if (rv < 0) {
+ if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {
+ rv = 0;
+ } else {
+ /* Return short write if some data already went out... */
+ if (count == 0)
+ count = rv;
+ break;
+ }
+ }
+
+ if ((unsigned)rv < (amount + 2)) {
+ /* Short write. Save the data and return. */
+ if (ssl_SaveWriteData(ss, out + rv, amount + 2 - rv) ==
+ SECFailure) {
+ count = SECFailure;
+ } else {
+ count += amount;
+ ss->sec.sendSequence++;
+ }
+ break;
+ }
+
+ ss->sec.sendSequence++;
+ in += amount;
+ count += amount;
+ len -= amount;
}
return count;
@@ -903,92 +901,95 @@ ssl2_SendClear(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags)
** block size of 1. Package up the data with the length header
** and send it.
*/
-static PRInt32
+static PRInt32
ssl2_SendStream(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags)
{
- PRUint8 * out;
- int rv;
- int count = 0;
+ PRUint8 *out;
+ int rv;
+ int count = 0;
- int amount;
- PRUint8 macLen;
- int nout;
+ int amount;
+ PRUint8 macLen;
+ int nout;
unsigned int buflen;
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes using stream cipher",
- SSL_GETPID(), ss->fd, len));
- PRINT_BUF(50, (ss, "clear data:", (PRUint8*) in, len));
+ SSL_GETPID(), ss->fd, len));
+ PRINT_BUF(50, (ss, "clear data:", (PRUint8 *)in, len));
while (len) {
- ssl_GetSpecReadLock(ss); /*************************************/
-
- macLen = ss->sec.hash->length;
- amount = PR_MIN( len, MAX_STREAM_CYPHER_LEN );
- buflen = amount + 2 + macLen;
- if (buflen > ss->sec.writeBuf.space) {
- rv = sslBuffer_Grow(&ss->sec.writeBuf, buflen);
- if (rv != SECSuccess) {
- goto loser;
- }
- }
- out = ss->sec.writeBuf.buf;
- nout = amount + macLen;
- out[0] = 0x80 | MSB(nout);
- out[1] = LSB(nout);
-
- /* Calculate MAC */
- rv = ssl2_CalcMAC(out+2, /* put MAC here */
- &ss->sec,
- in, amount, /* input addr & length */
- 0); /* no padding */
- if (rv != SECSuccess)
- goto loser;
-
- /* Encrypt MAC */
- rv = (*ss->sec.enc)(ss->sec.writecx, out+2, &nout, macLen, out+2, macLen);
- if (rv) goto loser;
-
- /* Encrypt data from caller */
- rv = (*ss->sec.enc)(ss->sec.writecx, out+2+macLen, &nout, amount, in, amount);
- if (rv) goto loser;
-
- ssl_ReleaseSpecReadLock(ss); /*************************************/
-
- PRINT_BUF(50, (ss, "encrypted data:", out, buflen));
-
- rv = ssl_DefSend(ss, out, buflen, flags & ~ssl_SEND_FLAG_MASK);
- if (rv < 0) {
- if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {
- SSL_TRC(50, ("%d: SSL[%d]: send stream would block, "
- "saving data", SSL_GETPID(), ss->fd));
- rv = 0;
- } else {
- SSL_TRC(10, ("%d: SSL[%d]: send stream error %d",
- SSL_GETPID(), ss->fd, PORT_GetError()));
- /* Return short write if some data already went out... */
- if (count == 0)
- count = rv;
- goto done;
- }
- }
-
- if ((unsigned)rv < buflen) {
- /* Short write. Save the data and return. */
- if (ssl_SaveWriteData(ss, out + rv, buflen - rv) == SECFailure) {
- count = SECFailure;
- } else {
- count += amount;
- ss->sec.sendSequence++;
- }
- goto done;
- }
-
- ss->sec.sendSequence++;
- in += amount;
- count += amount;
- len -= amount;
+ ssl_GetSpecReadLock(ss); /*************************************/
+
+ macLen = ss->sec.hash->length;
+ amount = PR_MIN(len, MAX_STREAM_CYPHER_LEN);
+ buflen = amount + 2 + macLen;
+ if (buflen > ss->sec.writeBuf.space) {
+ rv = sslBuffer_Grow(&ss->sec.writeBuf, buflen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+ out = ss->sec.writeBuf.buf;
+ nout = amount + macLen;
+ out[0] = 0x80 | MSB(nout);
+ out[1] = LSB(nout);
+
+ /* Calculate MAC */
+ rv = ssl2_CalcMAC(out + 2, /* put MAC here */
+ &ss->sec,
+ in, amount, /* input addr & length */
+ 0); /* no padding */
+ if (rv != SECSuccess)
+ goto loser;
+
+ /* Encrypt MAC */
+ rv = (*ss->sec.enc)(ss->sec.writecx, out + 2, &nout, macLen, out + 2, macLen);
+ if (rv)
+ goto loser;
+
+ /* Encrypt data from caller */
+ rv = (*ss->sec.enc)(ss->sec.writecx, out + 2 + macLen, &nout, amount, in, amount);
+ if (rv)
+ goto loser;
+
+ ssl_ReleaseSpecReadLock(ss); /*************************************/
+
+ PRINT_BUF(50, (ss, "encrypted data:", out, buflen));
+
+ rv = ssl_DefSend(ss, out, buflen, flags & ~ssl_SEND_FLAG_MASK);
+ if (rv < 0) {
+ if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {
+ SSL_TRC(50, ("%d: SSL[%d]: send stream would block, "
+ "saving data",
+ SSL_GETPID(), ss->fd));
+ rv = 0;
+ } else {
+ SSL_TRC(10, ("%d: SSL[%d]: send stream error %d",
+ SSL_GETPID(), ss->fd, PORT_GetError()));
+ /* Return short write if some data already went out... */
+ if (count == 0)
+ count = rv;
+ goto done;
+ }
+ }
+
+ if ((unsigned)rv < buflen) {
+ /* Short write. Save the data and return. */
+ if (ssl_SaveWriteData(ss, out + rv, buflen - rv) == SECFailure) {
+ count = SECFailure;
+ } else {
+ count += amount;
+ ss->sec.sendSequence++;
+ }
+ goto done;
+ }
+
+ ss->sec.sendSequence++;
+ in += amount;
+ count += amount;
+ len -= amount;
}
done:
@@ -1007,116 +1008,116 @@ loser:
static PRInt32
ssl2_SendBlock(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags)
{
- PRUint8 * out; /* begining of output buffer. */
- PRUint8 * op; /* next output byte goes here. */
- int rv; /* value from funcs we called. */
- int count = 0; /* this function's return value. */
-
- unsigned int hlen; /* output record hdr len, 2 or 3 */
- unsigned int macLen; /* MAC is this many bytes long. */
- int amount; /* of plaintext to go in record. */
- unsigned int padding; /* add this many padding byte. */
- int nout; /* ciphertext size after header. */
- unsigned int buflen; /* size of generated record. */
+ PRUint8 *out; /* begining of output buffer. */
+ PRUint8 *op; /* next output byte goes here. */
+ int rv; /* value from funcs we called. */
+ int count = 0; /* this function's return value. */
+
+ unsigned int hlen; /* output record hdr len, 2 or 3 */
+ unsigned int macLen; /* MAC is this many bytes long. */
+ int amount; /* of plaintext to go in record. */
+ unsigned int padding; /* add this many padding byte. */
+ int nout; /* ciphertext size after header. */
+ unsigned int buflen; /* size of generated record. */
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes using block cipher",
- SSL_GETPID(), ss->fd, len));
+ SSL_GETPID(), ss->fd, len));
PRINT_BUF(50, (ss, "clear data:", in, len));
while (len) {
- ssl_GetSpecReadLock(ss); /*************************************/
-
- macLen = ss->sec.hash->length;
- /* Figure out how much to send, including mac and padding */
- amount = PR_MIN( len, MAX_BLOCK_CYPHER_LEN );
- nout = amount + macLen;
- padding = nout & (ss->sec.blockSize - 1);
- if (padding) {
- hlen = 3;
- padding = ss->sec.blockSize - padding;
- nout += padding;
- } else {
- hlen = 2;
- }
- buflen = hlen + nout;
- if (buflen > ss->sec.writeBuf.space) {
- rv = sslBuffer_Grow(&ss->sec.writeBuf, buflen);
- if (rv != SECSuccess) {
- goto loser;
- }
- }
- out = ss->sec.writeBuf.buf;
-
- /* Construct header */
- op = out;
- if (padding) {
- *op++ = MSB(nout);
- *op++ = LSB(nout);
- *op++ = padding;
- } else {
- *op++ = 0x80 | MSB(nout);
- *op++ = LSB(nout);
- }
-
- /* Calculate MAC */
- rv = ssl2_CalcMAC(op, /* MAC goes here. */
- &ss->sec,
- in, amount, /* intput addr, len */
- padding);
- if (rv != SECSuccess)
- goto loser;
- op += macLen;
-
- /* Copy in the input data */
- /* XXX could eliminate the copy by folding it into the encryption */
- PORT_Memcpy(op, in, amount);
- op += amount;
- if (padding) {
- PORT_Memset(op, padding, padding);
- op += padding;
- }
-
- /* Encrypt result */
- rv = (*ss->sec.enc)(ss->sec.writecx, out+hlen, &nout, buflen-hlen,
- out+hlen, op - (out + hlen));
- if (rv)
- goto loser;
-
- ssl_ReleaseSpecReadLock(ss); /*************************************/
-
- PRINT_BUF(50, (ss, "final xmit data:", out, op - out));
-
- rv = ssl_DefSend(ss, out, op - out, flags & ~ssl_SEND_FLAG_MASK);
- if (rv < 0) {
- if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {
- rv = 0;
- } else {
- SSL_TRC(10, ("%d: SSL[%d]: send block error %d",
- SSL_GETPID(), ss->fd, PORT_GetError()));
- /* Return short write if some data already went out... */
- if (count == 0)
- count = rv;
- goto done;
- }
- }
-
- if (rv < (op - out)) {
- /* Short write. Save the data and return. */
- if (ssl_SaveWriteData(ss, out + rv, op - out - rv) == SECFailure) {
- count = SECFailure;
- } else {
- count += amount;
- ss->sec.sendSequence++;
- }
- goto done;
- }
-
- ss->sec.sendSequence++;
- in += amount;
- count += amount;
- len -= amount;
+ ssl_GetSpecReadLock(ss); /*************************************/
+
+ macLen = ss->sec.hash->length;
+ /* Figure out how much to send, including mac and padding */
+ amount = PR_MIN(len, MAX_BLOCK_CYPHER_LEN);
+ nout = amount + macLen;
+ padding = nout & (ss->sec.blockSize - 1);
+ if (padding) {
+ hlen = 3;
+ padding = ss->sec.blockSize - padding;
+ nout += padding;
+ } else {
+ hlen = 2;
+ }
+ buflen = hlen + nout;
+ if (buflen > ss->sec.writeBuf.space) {
+ rv = sslBuffer_Grow(&ss->sec.writeBuf, buflen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+ out = ss->sec.writeBuf.buf;
+
+ /* Construct header */
+ op = out;
+ if (padding) {
+ *op++ = MSB(nout);
+ *op++ = LSB(nout);
+ *op++ = padding;
+ } else {
+ *op++ = 0x80 | MSB(nout);
+ *op++ = LSB(nout);
+ }
+
+ /* Calculate MAC */
+ rv = ssl2_CalcMAC(op, /* MAC goes here. */
+ &ss->sec,
+ in, amount, /* intput addr, len */
+ padding);
+ if (rv != SECSuccess)
+ goto loser;
+ op += macLen;
+
+ /* Copy in the input data */
+ /* XXX could eliminate the copy by folding it into the encryption */
+ PORT_Memcpy(op, in, amount);
+ op += amount;
+ if (padding) {
+ PORT_Memset(op, padding, padding);
+ op += padding;
+ }
+
+ /* Encrypt result */
+ rv = (*ss->sec.enc)(ss->sec.writecx, out + hlen, &nout, buflen - hlen,
+ out + hlen, op - (out + hlen));
+ if (rv)
+ goto loser;
+
+ ssl_ReleaseSpecReadLock(ss); /*************************************/
+
+ PRINT_BUF(50, (ss, "final xmit data:", out, op - out));
+
+ rv = ssl_DefSend(ss, out, op - out, flags & ~ssl_SEND_FLAG_MASK);
+ if (rv < 0) {
+ if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) {
+ rv = 0;
+ } else {
+ SSL_TRC(10, ("%d: SSL[%d]: send block error %d",
+ SSL_GETPID(), ss->fd, PORT_GetError()));
+ /* Return short write if some data already went out... */
+ if (count == 0)
+ count = rv;
+ goto done;
+ }
+ }
+
+ if (rv < (op - out)) {
+ /* Short write. Save the data and return. */
+ if (ssl_SaveWriteData(ss, out + rv, op - out - rv) == SECFailure) {
+ count = SECFailure;
+ } else {
+ count += amount;
+ ss->sec.sendSequence++;
+ }
+ goto done;
+ }
+
+ ss->sec.sendSequence++;
+ in += amount;
+ count += amount;
+ len -= amount;
}
done:
@@ -1131,7 +1132,7 @@ loser:
** Called from: ssl2_HandleServerHelloMessage,
** ssl2_HandleClientSessionKeyMessage,
** ssl2_HandleClientHelloMessage,
-**
+**
*/
static void
ssl2_UseEncryptedSendFunc(sslSocket *ss)
@@ -1154,12 +1155,12 @@ ssl2_UseClearSendFunc(sslSocket *ss)
}
/************************************************************************
-** END of Send functions. *
+** END of Send functions. *
*************************************************************************/
/***********************************************************************
- * For SSL3, this gathers in and handles records/messages until either
- * the handshake is complete or application data is available.
+ * For SSL3, this gathers in and handles records/messages until either
+ * the handshake is complete or application data is available.
*
* For SSL2, this gathers in only the next SSLV2 record.
*
@@ -1169,37 +1170,37 @@ ssl2_UseClearSendFunc(sslSocket *ss)
*
* returns SECSuccess for success.
* returns SECWouldBlock when that value is returned by ssl2_GatherRecord() or
- * ssl3_GatherCompleteHandshake().
+ * ssl3_GatherCompleteHandshake().
* returns SECFailure on all other errors.
*
- * The gather functions called by ssl_GatherRecord1stHandshake are expected
- * to return values interpreted as follows:
+ * The gather functions called by ssl_GatherRecord1stHandshake are expected
+ * to return values interpreted as follows:
* 1 : the function completed without error.
* 0 : the function read EOF.
* -1 : read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
- * -2 : the function wants ssl_GatherRecord1stHandshake to be called again
- * immediately, by ssl_Do1stHandshake.
+ * -2 : the function wants ssl_GatherRecord1stHandshake to be called again
+ * immediately, by ssl_Do1stHandshake.
*
* This code is similar to, and easily confused with, DoRecv() in sslsecur.c
*
- * This function is called from ssl_Do1stHandshake().
+ * This function is called from ssl_Do1stHandshake().
* The following functions put ssl_GatherRecord1stHandshake into ss->handshake:
- * ssl2_HandleMessage
- * ssl2_HandleVerifyMessage
- * ssl2_HandleServerHelloMessage
- * ssl2_BeginClientHandshake
- * ssl2_HandleClientSessionKeyMessage
- * ssl3_RestartHandshakeAfterCertReq
- * ssl3_RestartHandshakeAfterServerCert
- * ssl2_HandleClientHelloMessage
- * ssl2_BeginServerHandshake
+ * ssl2_HandleMessage
+ * ssl2_HandleVerifyMessage
+ * ssl2_HandleServerHelloMessage
+ * ssl2_BeginClientHandshake
+ * ssl2_HandleClientSessionKeyMessage
+ * ssl3_RestartHandshakeAfterCertReq
+ * ssl3_RestartHandshakeAfterServerCert
+ * ssl2_HandleClientHelloMessage
+ * ssl2_BeginServerHandshake
*/
SECStatus
ssl_GatherRecord1stHandshake(sslSocket *ss)
{
int rv;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
ssl_GetRecvBufLock(ss);
@@ -1209,35 +1210,35 @@ ssl_GatherRecord1stHandshake(sslSocket *ss)
* SSL3 version.
*/
if ((ss->version >= SSL_LIBRARY_VERSION_3_0) || IS_DTLS(ss)) {
- /* Wait for handshake to complete, or application data to arrive. */
- rv = ssl3_GatherCompleteHandshake(ss, 0);
+ /* Wait for handshake to complete, or application data to arrive. */
+ rv = ssl3_GatherCompleteHandshake(ss, 0);
} else {
- /* See if we have a complete record */
- rv = ssl2_GatherRecord(ss, 0);
+ /* See if we have a complete record */
+ rv = ssl2_GatherRecord(ss, 0);
}
SSL_TRC(10, ("%d: SSL[%d]: handshake gathering, rv=%d",
- SSL_GETPID(), ss->fd, rv));
+ SSL_GETPID(), ss->fd, rv));
ssl_ReleaseRecvBufLock(ss);
if (rv <= 0) {
- if (rv == SECWouldBlock) {
- /* Progress is blocked waiting for callback completion. */
- SSL_TRC(10, ("%d: SSL[%d]: handshake blocked (need %d)",
- SSL_GETPID(), ss->fd, ss->gs.remainder));
- return SECWouldBlock;
- }
- if (rv == 0) {
- /* EOF. Loser */
- PORT_SetError(PR_END_OF_FILE_ERROR);
- }
- return SECFailure; /* rv is < 0 here. */
+ if (rv == SECWouldBlock) {
+ /* Progress is blocked waiting for callback completion. */
+ SSL_TRC(10, ("%d: SSL[%d]: handshake blocked (need %d)",
+ SSL_GETPID(), ss->fd, ss->gs.remainder));
+ return SECWouldBlock;
+ }
+ if (rv == 0) {
+ /* EOF. Loser */
+ PORT_SetError(PR_END_OF_FILE_ERROR);
+ }
+ return SECFailure; /* rv is < 0 here. */
}
SSL_TRC(10, ("%d: SSL[%d]: got handshake record of %d bytes",
- SSL_GETPID(), ss->fd, ss->gs.recordLen));
+ SSL_GETPID(), ss->fd, ss->gs.recordLen));
- ss->handshake = 0; /* makes ssl_Do1stHandshake call ss->nextHandshake.*/
+ ss->handshake = 0; /* makes ssl_Do1stHandshake call ss->nextHandshake.*/
return SECSuccess;
}
@@ -1247,18 +1248,18 @@ ssl_GatherRecord1stHandshake(sslSocket *ss)
* ssl2_ClientSetupSessionCypher()
*/
static SECStatus
-ssl2_FillInSID(sslSessionID * sid,
- int cipher,
- PRUint8 *keyData,
- int keyLen,
- PRUint8 *ca,
- int caLen,
- int keyBits,
- int secretKeyBits,
- SSLSignType authAlgorithm,
- PRUint32 authKeyBits,
- SSLKEAType keaType,
- PRUint32 keaKeyBits)
+ssl2_FillInSID(sslSessionID *sid,
+ int cipher,
+ PRUint8 *keyData,
+ int keyLen,
+ PRUint8 *ca,
+ int caLen,
+ int keyBits,
+ int secretKeyBits,
+ SSLSignType authAlgorithm,
+ PRUint32 authKeyBits,
+ SSLKEAType keaType,
+ PRUint32 keaKeyBits)
{
PORT_Assert(sid->references == 1);
PORT_Assert(sid->cached == never_cached);
@@ -1268,28 +1269,28 @@ ssl2_FillInSID(sslSessionID * sid,
sid->version = SSL_LIBRARY_VERSION_2;
sid->u.ssl2.cipherType = cipher;
- sid->u.ssl2.masterKey.data = (PRUint8*) PORT_Alloc(keyLen);
+ sid->u.ssl2.masterKey.data = (PRUint8 *)PORT_Alloc(keyLen);
if (!sid->u.ssl2.masterKey.data) {
- return SECFailure;
+ return SECFailure;
}
PORT_Memcpy(sid->u.ssl2.masterKey.data, keyData, keyLen);
sid->u.ssl2.masterKey.len = keyLen;
- sid->u.ssl2.keyBits = keyBits;
+ sid->u.ssl2.keyBits = keyBits;
sid->u.ssl2.secretKeyBits = secretKeyBits;
- sid->authAlgorithm = authAlgorithm;
- sid->authKeyBits = authKeyBits;
- sid->keaType = keaType;
- sid->keaKeyBits = keaKeyBits;
+ sid->authAlgorithm = authAlgorithm;
+ sid->authKeyBits = authKeyBits;
+ sid->keaType = keaType;
+ sid->keaKeyBits = keaKeyBits;
sid->lastAccessTime = sid->creationTime = ssl_Time();
sid->expirationTime = sid->creationTime + ssl_sid_timeout;
if (caLen) {
- sid->u.ssl2.cipherArg.data = (PRUint8*) PORT_Alloc(caLen);
- if (!sid->u.ssl2.cipherArg.data) {
- return SECFailure;
- }
- sid->u.ssl2.cipherArg.len = caLen;
- PORT_Memcpy(sid->u.ssl2.cipherArg.data, ca, caLen);
+ sid->u.ssl2.cipherArg.data = (PRUint8 *)PORT_Alloc(caLen);
+ if (!sid->u.ssl2.cipherArg.data) {
+ return SECFailure;
+ }
+ sid->u.ssl2.cipherArg.len = caLen;
+ PORT_Memcpy(sid->u.ssl2.cipherArg.data, ca, caLen);
}
return SECSuccess;
}
@@ -1301,68 +1302,68 @@ ssl2_FillInSID(sslSessionID * sid,
** Called from ssl2_CreateSessionCypher() <-
*/
static SECStatus
-ssl2_ProduceKeys(sslSocket * ss,
- SECItem * readKey,
- SECItem * writeKey,
- SECItem * masterKey,
- PRUint8 * challenge,
- PRUint8 * nonce,
- int cipherType)
+ssl2_ProduceKeys(sslSocket *ss,
+ SECItem *readKey,
+ SECItem *writeKey,
+ SECItem *masterKey,
+ PRUint8 *challenge,
+ PRUint8 *nonce,
+ int cipherType)
{
- PK11Context * cx = 0;
- unsigned nkm = 0; /* number of hashes to generate key mat. */
- unsigned nkd = 0; /* size of readKey and writeKey. */
- unsigned part;
- unsigned i;
- unsigned off;
- SECStatus rv;
- PRUint8 countChar;
- PRUint8 km[3*16]; /* buffer for key material. */
+ PK11Context *cx = 0;
+ unsigned nkm = 0; /* number of hashes to generate key mat. */
+ unsigned nkd = 0; /* size of readKey and writeKey. */
+ unsigned part;
+ unsigned i;
+ unsigned off;
+ SECStatus rv;
+ PRUint8 countChar;
+ PRUint8 km[3 * 16]; /* buffer for key material. */
readKey->data = 0;
writeKey->data = 0;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
rv = SECSuccess;
cx = PK11_CreateDigestContext(SEC_OID_MD5);
if (cx == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
- return SECFailure;
+ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
+ return SECFailure;
}
nkm = ssl_Specs[cipherType].nkm;
nkd = ssl_Specs[cipherType].nkd;
- readKey->data = (PRUint8*) PORT_Alloc(nkd);
- if (!readKey->data)
- goto loser;
+ readKey->data = (PRUint8 *)PORT_Alloc(nkd);
+ if (!readKey->data)
+ goto loser;
readKey->len = nkd;
- writeKey->data = (PRUint8*) PORT_Alloc(nkd);
- if (!writeKey->data)
- goto loser;
+ writeKey->data = (PRUint8 *)PORT_Alloc(nkd);
+ if (!writeKey->data)
+ goto loser;
writeKey->len = nkd;
/* Produce key material */
countChar = '0';
for (i = 0, off = 0; i < nkm; i++, off += 16) {
- rv = PK11_DigestBegin(cx);
- rv |= PK11_DigestOp(cx, masterKey->data, masterKey->len);
- rv |= PK11_DigestOp(cx, &countChar, 1);
- rv |= PK11_DigestOp(cx, challenge, SSL_CHALLENGE_BYTES);
- rv |= PK11_DigestOp(cx, nonce, SSL_CONNECTIONID_BYTES);
- rv |= PK11_DigestFinal(cx, km+off, &part, MD5_LENGTH);
- if (rv != SECSuccess) {
- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
- rv = SECFailure;
- goto loser;
- }
- countChar++;
+ rv = PK11_DigestBegin(cx);
+ rv |= PK11_DigestOp(cx, masterKey->data, masterKey->len);
+ rv |= PK11_DigestOp(cx, &countChar, 1);
+ rv |= PK11_DigestOp(cx, challenge, SSL_CHALLENGE_BYTES);
+ rv |= PK11_DigestOp(cx, nonce, SSL_CONNECTIONID_BYTES);
+ rv |= PK11_DigestFinal(cx, km + off, &part, MD5_LENGTH);
+ if (rv != SECSuccess) {
+ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
+ rv = SECFailure;
+ goto loser;
+ }
+ countChar++;
}
/* Produce keys */
- PORT_Memcpy(readKey->data, km, nkd);
+ PORT_Memcpy(readKey->data, km, nkd);
PORT_Memcpy(writeKey->data, km + nkd, nkd);
loser:
@@ -1370,62 +1371,62 @@ loser:
return rv;
}
-/* Called from ssl2_ServerSetupSessionCypher()
+/* Called from ssl2_ServerSetupSessionCypher()
** <- ssl2_HandleClientSessionKeyMessage()
** <- ssl2_HandleClientHelloMessage()
-** and from ssl2_ClientSetupSessionCypher()
+** and from ssl2_ClientSetupSessionCypher()
** <- ssl2_HandleServerHelloMessage()
*/
static SECStatus
ssl2_CreateSessionCypher(sslSocket *ss, sslSessionID *sid, PRBool isClient)
{
- SECItem * rk = NULL;
- SECItem * wk = NULL;
- SECItem * param;
- SECStatus rv;
- int cipherType = sid->u.ssl2.cipherType;
- PK11SlotInfo * slot = NULL;
+ SECItem *rk = NULL;
+ SECItem *wk = NULL;
+ SECItem *param;
+ SECStatus rv;
+ int cipherType = sid->u.ssl2.cipherType;
+ PK11SlotInfo *slot = NULL;
CK_MECHANISM_TYPE mechanism;
- SECItem readKey;
- SECItem writeKey;
+ SECItem readKey;
+ SECItem writeKey;
void *readcx = 0;
void *writecx = 0;
readKey.data = 0;
writeKey.data = 0;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
if (ss->sec.ci.sid == 0)
- goto sec_loser; /* don't crash if asserts are off */
+ goto sec_loser; /* don't crash if asserts are off */
/* Trying to cut down on all these switch statements that should be tables.
- * So, test cipherType once, here, and then use tables below.
+ * So, test cipherType once, here, and then use tables below.
*/
switch (cipherType) {
- case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
- case SSL_CK_RC4_128_WITH_MD5:
- case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
- case SSL_CK_RC2_128_CBC_WITH_MD5:
- case SSL_CK_DES_64_CBC_WITH_MD5:
- case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:
- break;
-
- default:
- SSL_DBG(("%d: SSL[%d]: ssl2_CreateSessionCypher: unknown cipher=%d",
- SSL_GETPID(), ss->fd, cipherType));
- PORT_SetError(isClient ? SSL_ERROR_BAD_SERVER : SSL_ERROR_BAD_CLIENT);
- goto sec_loser;
- }
-
- rk = isClient ? &readKey : &writeKey;
+ case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
+ case SSL_CK_RC4_128_WITH_MD5:
+ case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
+ case SSL_CK_RC2_128_CBC_WITH_MD5:
+ case SSL_CK_DES_64_CBC_WITH_MD5:
+ case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:
+ break;
+
+ default:
+ SSL_DBG(("%d: SSL[%d]: ssl2_CreateSessionCypher: unknown cipher=%d",
+ SSL_GETPID(), ss->fd, cipherType));
+ PORT_SetError(isClient ? SSL_ERROR_BAD_SERVER : SSL_ERROR_BAD_CLIENT);
+ goto sec_loser;
+ }
+
+ rk = isClient ? &readKey : &writeKey;
wk = isClient ? &writeKey : &readKey;
/* Produce the keys for this session */
rv = ssl2_ProduceKeys(ss, &readKey, &writeKey, &sid->u.ssl2.masterKey,
- ss->sec.ci.clientChallenge, ss->sec.ci.connectionID,
- cipherType);
- if (rv != SECSuccess)
- goto loser;
+ ss->sec.ci.clientChallenge, ss->sec.ci.connectionID,
+ cipherType);
+ if (rv != SECSuccess)
+ goto loser;
PRINT_BUF(7, (ss, "Session read-key: ", rk->data, rk->len));
PRINT_BUF(7, (ss, "Session write-key: ", wk->data, wk->len));
@@ -1435,73 +1436,75 @@ ssl2_CreateSessionCypher(sslSocket *ss, sslSessionID *sid, PRBool isClient)
/* Setup the MAC */
rv = ssl2_CreateMAC(&ss->sec, rk, wk, cipherType);
- if (rv != SECSuccess)
- goto loser;
+ if (rv != SECSuccess)
+ goto loser;
/* First create the session key object */
SSL_TRC(3, ("%d: SSL[%d]: using %s", SSL_GETPID(), ss->fd,
- ssl_cipherName[cipherType]));
-
+ ssl_cipherName[cipherType]));
- mechanism = ssl_Specs[cipherType].mechanism;
+ mechanism = ssl_Specs[cipherType].mechanism;
/* set destructer before we call loser... */
- ss->sec.destroy = (void (*)(void*, PRBool)) PK11_DestroyContext;
+ ss->sec.destroy = (void (*)(void *, PRBool))PK11_DestroyContext;
slot = PK11_GetBestSlot(mechanism, ss->pkcs11PinArg);
if (slot == NULL)
- goto loser;
+ goto loser;
param = PK11_ParamFromIV(mechanism, &sid->u.ssl2.cipherArg);
if (param == NULL)
- goto loser;
+ goto loser;
readcx = PK11_CreateContextByRawKey(slot, mechanism, PK11_OriginUnwrap,
- CKA_DECRYPT, rk, param,
- ss->pkcs11PinArg);
+ CKA_DECRYPT, rk, param,
+ ss->pkcs11PinArg);
SECITEM_FreeItem(param, PR_TRUE);
if (readcx == NULL)
- goto loser;
+ goto loser;
/* build the client context */
param = PK11_ParamFromIV(mechanism, &sid->u.ssl2.cipherArg);
if (param == NULL)
- goto loser;
+ goto loser;
writecx = PK11_CreateContextByRawKey(slot, mechanism, PK11_OriginUnwrap,
- CKA_ENCRYPT, wk, param,
- ss->pkcs11PinArg);
- SECITEM_FreeItem(param,PR_TRUE);
+ CKA_ENCRYPT, wk, param,
+ ss->pkcs11PinArg);
+ SECITEM_FreeItem(param, PR_TRUE);
if (writecx == NULL)
- goto loser;
+ goto loser;
PK11_FreeSlot(slot);
rv = SECSuccess;
- ss->sec.enc = (SSLCipher) PK11_CipherOp;
- ss->sec.dec = (SSLCipher) PK11_CipherOp;
- ss->sec.readcx = (void *) readcx;
- ss->sec.writecx = (void *) writecx;
- ss->sec.blockSize = ssl_Specs[cipherType].blockSize;
- ss->sec.blockShift = ssl_Specs[cipherType].blockShift;
- ss->sec.cipherType = sid->u.ssl2.cipherType;
- ss->sec.keyBits = sid->u.ssl2.keyBits;
+ ss->sec.enc = (SSLCipher)PK11_CipherOp;
+ ss->sec.dec = (SSLCipher)PK11_CipherOp;
+ ss->sec.readcx = (void *)readcx;
+ ss->sec.writecx = (void *)writecx;
+ ss->sec.blockSize = ssl_Specs[cipherType].blockSize;
+ ss->sec.blockShift = ssl_Specs[cipherType].blockShift;
+ ss->sec.cipherType = sid->u.ssl2.cipherType;
+ ss->sec.keyBits = sid->u.ssl2.keyBits;
ss->sec.secretKeyBits = sid->u.ssl2.secretKeyBits;
goto done;
- loser:
+loser:
if (ss->sec.destroy) {
- if (readcx) (*ss->sec.destroy)(readcx, PR_TRUE);
- if (writecx) (*ss->sec.destroy)(writecx, PR_TRUE);
+ if (readcx)
+ (*ss->sec.destroy)(readcx, PR_TRUE);
+ if (writecx)
+ (*ss->sec.destroy)(writecx, PR_TRUE);
}
ss->sec.destroy = NULL;
- if (slot) PK11_FreeSlot(slot);
+ if (slot)
+ PK11_FreeSlot(slot);
- sec_loser:
+sec_loser:
rv = SECFailure;
- done:
+done:
if (rk) {
- SECITEM_ZfreeItem(rk, PR_FALSE);
+ SECITEM_ZfreeItem(rk, PR_FALSE);
}
if (wk) {
- SECITEM_ZfreeItem(wk, PR_FALSE);
+ SECITEM_ZfreeItem(wk, PR_FALSE);
}
return rv;
}
@@ -1509,15 +1512,15 @@ ssl2_CreateSessionCypher(sslSocket *ss, sslSessionID *sid, PRBool isClient)
/*
** Setup the server ciphers given information from a CLIENT-MASTER-KEY
** message.
-** "ss" pointer to the ssl-socket object
-** "cipher" the cipher type to use
-** "keyBits" the size of the final cipher key
-** "ck" the clear-key data
-** "ckLen" the number of bytes of clear-key data
-** "ek" the encrypted-key data
-** "ekLen" the number of bytes of encrypted-key data
-** "ca" the cipher-arg data
-** "caLen" the number of bytes of cipher-arg data
+** "ss" pointer to the ssl-socket object
+** "cipher" the cipher type to use
+** "keyBits" the size of the final cipher key
+** "ck" the clear-key data
+** "ckLen" the number of bytes of clear-key data
+** "ek" the encrypted-key data
+** "ekLen" the number of bytes of encrypted-key data
+** "ca" the cipher-arg data
+** "caLen" the number of bytes of cipher-arg data
**
** The MASTER-KEY is constructed by first decrypting the encrypted-key
** data. This produces the SECRET-KEY-DATA. The MASTER-KEY is composed by
@@ -1530,171 +1533,171 @@ ssl2_CreateSessionCypher(sslSocket *ss, sslSessionID *sid, PRBool isClient)
*/
static SECStatus
ssl2_ServerSetupSessionCypher(sslSocket *ss, int cipher, unsigned int keyBits,
- PRUint8 *ck, unsigned int ckLen,
- PRUint8 *ek, unsigned int ekLen,
- PRUint8 *ca, unsigned int caLen)
+ PRUint8 *ck, unsigned int ckLen,
+ PRUint8 *ek, unsigned int ekLen,
+ PRUint8 *ca, unsigned int caLen)
{
- PRUint8 * dk = NULL; /* decrypted master key */
- sslSessionID * sid;
- sslServerCerts * sc = ss->serverCerts + kt_rsa;
- PRUint8 * kbuf = 0; /* buffer for RSA decrypted data. */
- unsigned int ddLen; /* length of RSA decrypted data in kbuf */
- unsigned int keySize;
- unsigned int dkLen; /* decrypted key length in bytes */
+ PRUint8 *dk = NULL; /* decrypted master key */
+ sslSessionID *sid;
+ sslServerCerts *sc = ss->serverCerts + kt_rsa;
+ PRUint8 *kbuf = 0; /* buffer for RSA decrypted data. */
+ unsigned int ddLen; /* length of RSA decrypted data in kbuf */
+ unsigned int keySize;
+ unsigned int dkLen; /* decrypted key length in bytes */
int modulusLen;
- SECStatus rv;
- PRUint16 allowed; /* cipher kinds enabled and allowed by policy */
- PRUint8 mkbuf[SSL_MAX_MASTER_KEY_BYTES];
+ SECStatus rv;
+ PRUint16 allowed; /* cipher kinds enabled and allowed by policy */
+ PRUint8 mkbuf[SSL_MAX_MASTER_KEY_BYTES];
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
PORT_Assert((sc->SERVERKEY != 0));
PORT_Assert((ss->sec.ci.sid != 0));
sid = ss->sec.ci.sid;
/* Trying to cut down on all these switch statements that should be tables.
- * So, test cipherType once, here, and then use tables below.
+ * So, test cipherType once, here, and then use tables below.
*/
switch (cipher) {
- case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
- case SSL_CK_RC4_128_WITH_MD5:
- case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
- case SSL_CK_RC2_128_CBC_WITH_MD5:
- case SSL_CK_DES_64_CBC_WITH_MD5:
- case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:
- break;
+ case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
+ case SSL_CK_RC4_128_WITH_MD5:
+ case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
+ case SSL_CK_RC2_128_CBC_WITH_MD5:
+ case SSL_CK_DES_64_CBC_WITH_MD5:
+ case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:
+ break;
- default:
- SSL_DBG(("%d: SSL[%d]: ssl2_ServerSetupSessionCypher: unknown cipher=%d",
- SSL_GETPID(), ss->fd, cipher));
- PORT_SetError(SSL_ERROR_BAD_CLIENT);
- goto loser;
+ default:
+ SSL_DBG(("%d: SSL[%d]: ssl2_ServerSetupSessionCypher: unknown cipher=%d",
+ SSL_GETPID(), ss->fd, cipher));
+ PORT_SetError(SSL_ERROR_BAD_CLIENT);
+ goto loser;
}
allowed = ss->allowedByPolicy & ss->chosenPreference & SSL_CB_IMPLEMENTED;
if (!(allowed & (1 << cipher))) {
- /* client chose a kind we don't allow! */
- SSL_DBG(("%d: SSL[%d]: disallowed cipher=%d",
- SSL_GETPID(), ss->fd, cipher));
- PORT_SetError(SSL_ERROR_BAD_CLIENT);
- goto loser;
+ /* client chose a kind we don't allow! */
+ SSL_DBG(("%d: SSL[%d]: disallowed cipher=%d",
+ SSL_GETPID(), ss->fd, cipher));
+ PORT_SetError(SSL_ERROR_BAD_CLIENT);
+ goto loser;
}
keySize = ssl_Specs[cipher].keyLen;
if (keyBits != keySize * BPB) {
- SSL_DBG(("%d: SSL[%d]: invalid master secret key length=%d (bits)!",
- SSL_GETPID(), ss->fd, keyBits));
- PORT_SetError(SSL_ERROR_BAD_CLIENT);
- goto loser;
+ SSL_DBG(("%d: SSL[%d]: invalid master secret key length=%d (bits)!",
+ SSL_GETPID(), ss->fd, keyBits));
+ PORT_SetError(SSL_ERROR_BAD_CLIENT);
+ goto loser;
}
if (ckLen != ssl_Specs[cipher].pubLen) {
- SSL_DBG(("%d: SSL[%d]: invalid clear key length, ckLen=%d (bytes)!",
- SSL_GETPID(), ss->fd, ckLen));
- PORT_SetError(SSL_ERROR_BAD_CLIENT);
- goto loser;
+ SSL_DBG(("%d: SSL[%d]: invalid clear key length, ckLen=%d (bytes)!",
+ SSL_GETPID(), ss->fd, ckLen));
+ PORT_SetError(SSL_ERROR_BAD_CLIENT);
+ goto loser;
}
if (caLen != ssl_Specs[cipher].ivLen) {
- SSL_DBG(("%d: SSL[%d]: invalid key args length, caLen=%d (bytes)!",
- SSL_GETPID(), ss->fd, caLen));
- PORT_SetError(SSL_ERROR_BAD_CLIENT);
- goto loser;
+ SSL_DBG(("%d: SSL[%d]: invalid key args length, caLen=%d (bytes)!",
+ SSL_GETPID(), ss->fd, caLen));
+ PORT_SetError(SSL_ERROR_BAD_CLIENT);
+ goto loser;
}
modulusLen = PK11_GetPrivateModulusLen(sc->SERVERKEY);
if (modulusLen < 0) {
- /* XXX If the key is bad, then PK11_PubDecryptRaw will fail below. */
- modulusLen = ekLen;
+ /* XXX If the key is bad, then PK11_PubDecryptRaw will fail below. */
+ modulusLen = ekLen;
}
if (ekLen > (unsigned int)modulusLen || ekLen + ckLen < keySize) {
- SSL_DBG(("%d: SSL[%d]: invalid encrypted key length, ekLen=%d (bytes)!",
- SSL_GETPID(), ss->fd, ekLen));
- PORT_SetError(SSL_ERROR_BAD_CLIENT);
- goto loser;
+ SSL_DBG(("%d: SSL[%d]: invalid encrypted key length, ekLen=%d (bytes)!",
+ SSL_GETPID(), ss->fd, ekLen));
+ PORT_SetError(SSL_ERROR_BAD_CLIENT);
+ goto loser;
}
/* allocate the buffer to hold the decrypted portion of the key. */
- kbuf = (PRUint8*)PORT_Alloc(modulusLen);
+ kbuf = (PRUint8 *)PORT_Alloc(modulusLen);
if (!kbuf) {
- goto loser;
+ goto loser;
}
dkLen = keySize - ckLen;
- dk = kbuf + modulusLen - dkLen;
+ dk = kbuf + modulusLen - dkLen;
- /* Decrypt encrypted half of the key.
+ /* Decrypt encrypted half of the key.
** NOTE: PK11_PubDecryptRaw will barf on a non-RSA key. This is
** desired behavior here.
*/
rv = PK11_PubDecryptRaw(sc->SERVERKEY, kbuf, &ddLen, modulusLen, ek, ekLen);
- if (rv != SECSuccess)
- goto hide_loser;
+ if (rv != SECSuccess)
+ goto hide_loser;
/* Is the length of the decrypted data (ddLen) the expected value? */
- if (modulusLen != ddLen)
- goto hide_loser;
+ if (modulusLen != ddLen)
+ goto hide_loser;
/* Cheaply verify that PKCS#1 was used to format the encryption block */
if ((kbuf[0] != 0x00) || (kbuf[1] != 0x02) || (dk[-1] != 0x00)) {
- SSL_DBG(("%d: SSL[%d]: strange encryption block",
- SSL_GETPID(), ss->fd));
- PORT_SetError(SSL_ERROR_BAD_CLIENT);
- goto hide_loser;
+ SSL_DBG(("%d: SSL[%d]: strange encryption block",
+ SSL_GETPID(), ss->fd));
+ PORT_SetError(SSL_ERROR_BAD_CLIENT);
+ goto hide_loser;
}
/* Make sure we're not subject to a version rollback attack. */
if (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
- static const PRUint8 threes[8] = { 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x03 };
-
- if (PORT_Memcmp(dk - 8 - 1, threes, 8) == 0) {
- PORT_SetError(SSL_ERROR_BAD_CLIENT);
- goto hide_loser;
- }
+ static const PRUint8 threes[8] = { 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x03, 0x03 };
+
+ if (PORT_Memcmp(dk - 8 - 1, threes, 8) == 0) {
+ PORT_SetError(SSL_ERROR_BAD_CLIENT);
+ goto hide_loser;
+ }
}
if (0) {
-hide_loser:
- /* Defense against the Bleichenbacher attack.
- * Provide the client with NO CLUES that the decrypted master key
- * was erroneous. Don't send any error messages.
- * Instead, Generate a completely bogus master key .
- */
- PK11_GenerateRandom(dk, dkLen);
+ hide_loser:
+ /* Defense against the Bleichenbacher attack.
+ * Provide the client with NO CLUES that the decrypted master key
+ * was erroneous. Don't send any error messages.
+ * Instead, Generate a completely bogus master key .
+ */
+ PK11_GenerateRandom(dk, dkLen);
}
/*
** Construct master key out of the pieces.
*/
if (ckLen) {
- PORT_Memcpy(mkbuf, ck, ckLen);
+ PORT_Memcpy(mkbuf, ck, ckLen);
}
PORT_Memcpy(mkbuf + ckLen, dk, dkLen);
/* Fill in session-id */
rv = ssl2_FillInSID(sid, cipher, mkbuf, keySize, ca, caLen,
- keyBits, keyBits - (ckLen<<3),
- ss->sec.authAlgorithm, ss->sec.authKeyBits,
- ss->sec.keaType, ss->sec.keaKeyBits);
+ keyBits, keyBits - (ckLen << 3),
+ ss->sec.authAlgorithm, ss->sec.authKeyBits,
+ ss->sec.keaType, ss->sec.keaKeyBits);
if (rv != SECSuccess) {
- goto loser;
+ goto loser;
}
/* Create session ciphers */
rv = ssl2_CreateSessionCypher(ss, sid, PR_FALSE);
if (rv != SECSuccess) {
- goto loser;
+ goto loser;
}
SSL_TRC(1, ("%d: SSL[%d]: server, using %s cipher, clear=%d total=%d",
- SSL_GETPID(), ss->fd, ssl_cipherName[cipher],
- ckLen<<3, keySize<<3));
+ SSL_GETPID(), ss->fd, ssl_cipherName[cipher],
+ ckLen << 3, keySize << 3));
rv = SECSuccess;
goto done;
- loser:
+loser:
rv = SECFailure;
- done:
+done:
PORT_Free(kbuf);
return rv;
}
@@ -1705,54 +1708,54 @@ hide_loser:
** Rewrite the incoming cipher specs, comparing to list of specs we support,
** (ss->cipherSpecs) and eliminating anything we don't support
**
-* Note: Our list may contain SSL v3 ciphers.
-* We MUST NOT match on any of those.
+* Note: Our list may contain SSL v3 ciphers.
+* We MUST NOT match on any of those.
* Fortunately, this is easy to detect because SSLv3 ciphers have zero
* in the first byte, and none of the SSLv2 ciphers do.
*
* Called from ssl2_HandleClientHelloMessage().
-* Returns the number of bytes of "qualified cipher specs",
+* Returns the number of bytes of "qualified cipher specs",
* which is typically a multiple of 3, but will be zero if there are none.
*/
static int
-ssl2_QualifyCypherSpecs(sslSocket *ss,
- PRUint8 * cs, /* cipher specs in client hello msg. */
- int csLen)
+ssl2_QualifyCypherSpecs(sslSocket *ss,
+ PRUint8 *cs, /* cipher specs in client hello msg. */
+ int csLen)
{
- PRUint8 * ms;
- PRUint8 * hs;
- PRUint8 * qs;
- int mc;
- int hc;
- PRUint8 qualifiedSpecs[ssl2_NUM_SUITES_IMPLEMENTED * 3];
+ PRUint8 *ms;
+ PRUint8 *hs;
+ PRUint8 *qs;
+ int mc;
+ int hc;
+ PRUint8 qualifiedSpecs[ssl2_NUM_SUITES_IMPLEMENTED * 3];
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
if (!ss->cipherSpecs) {
- SECStatus rv = ssl2_ConstructCipherSpecs(ss);
- if (rv != SECSuccess || !ss->cipherSpecs)
- return 0;
+ SECStatus rv = ssl2_ConstructCipherSpecs(ss);
+ if (rv != SECSuccess || !ss->cipherSpecs)
+ return 0;
}
PRINT_BUF(10, (ss, "specs from client:", cs, csLen));
qs = qualifiedSpecs;
ms = ss->cipherSpecs;
for (mc = ss->sizeCipherSpecs; mc > 0; mc -= 3, ms += 3) {
- if (ms[0] == 0)
- continue;
- for (hs = cs, hc = csLen; hc > 0; hs += 3, hc -= 3) {
- if ((hs[0] == ms[0]) &&
- (hs[1] == ms[1]) &&
- (hs[2] == ms[2])) {
- /* Copy this cipher spec into the "keep" section */
- qs[0] = hs[0];
- qs[1] = hs[1];
- qs[2] = hs[2];
- qs += 3;
- break;
- }
- }
+ if (ms[0] == 0)
+ continue;
+ for (hs = cs, hc = csLen; hc > 0; hs += 3, hc -= 3) {
+ if ((hs[0] == ms[0]) &&
+ (hs[1] == ms[1]) &&
+ (hs[2] == ms[2])) {
+ /* Copy this cipher spec into the "keep" section */
+ qs[0] = hs[0];
+ qs[1] = hs[1];
+ qs[2] = hs[2];
+ qs += 3;
+ break;
+ }
+ }
}
hc = qs - qualifiedSpecs;
PRINT_BUF(10, (ss, "qualified specs from client:", qualifiedSpecs, hc));
@@ -1766,158 +1769,158 @@ ssl2_QualifyCypherSpecs(sslSocket *ss,
** If successful, stores the master key size (bytes) in *pKeyLen.
**
** This is correct only for the client side, but presently
-** this function is only called from
-** ssl2_ClientSetupSessionCypher() <- ssl2_HandleServerHelloMessage()
+** this function is only called from
+** ssl2_ClientSetupSessionCypher() <- ssl2_HandleServerHelloMessage()
**
-** Note that most servers only return a single cipher suite in their
+** Note that most servers only return a single cipher suite in their
** ServerHello messages. So, the code below for finding the "best" cipher
-** suite usually has only one choice. The client and server should send
+** suite usually has only one choice. The client and server should send
** their cipher suite lists sorted in descending order by preference.
*/
static int
-ssl2_ChooseSessionCypher(sslSocket *ss,
- int hc, /* number of cs's in hs. */
- PRUint8 * hs, /* server hello's cipher suites. */
- int * pKeyLen) /* out: sym key size in bytes. */
+ssl2_ChooseSessionCypher(sslSocket *ss,
+ int hc, /* number of cs's in hs. */
+ PRUint8 *hs, /* server hello's cipher suites. */
+ int *pKeyLen) /* out: sym key size in bytes. */
{
- PRUint8 * ms;
- unsigned int i;
- int bestKeySize;
- int bestRealKeySize;
- int bestCypher;
- int keySize;
- int realKeySize;
- PRUint8 * ohs = hs;
- const PRUint8 * preferred;
+ PRUint8 *ms;
+ unsigned int i;
+ int bestKeySize;
+ int bestRealKeySize;
+ int bestCypher;
+ int keySize;
+ int realKeySize;
+ PRUint8 *ohs = hs;
+ const PRUint8 *preferred;
static const PRUint8 noneSuch[3] = { 0, 0, 0 };
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
if (!ss->cipherSpecs) {
- SECStatus rv = ssl2_ConstructCipherSpecs(ss);
- if (rv != SECSuccess || !ss->cipherSpecs)
- goto loser;
+ SECStatus rv = ssl2_ConstructCipherSpecs(ss);
+ if (rv != SECSuccess || !ss->cipherSpecs)
+ goto loser;
}
if (!ss->preferredCipher) {
- unsigned int allowed = ss->allowedByPolicy & ss->chosenPreference &
- SSL_CB_IMPLEMENTED;
- if (allowed) {
- preferred = implementedCipherSuites;
- for (i = ssl2_NUM_SUITES_IMPLEMENTED; i > 0; --i) {
- if (0 != (allowed & (1U << preferred[0]))) {
- ss->preferredCipher = preferred;
- break;
- }
- preferred += 3;
- }
- }
+ unsigned int allowed = ss->allowedByPolicy & ss->chosenPreference &
+ SSL_CB_IMPLEMENTED;
+ if (allowed) {
+ preferred = implementedCipherSuites;
+ for (i = ssl2_NUM_SUITES_IMPLEMENTED; i > 0; --i) {
+ if (0 != (allowed & (1U << preferred[0]))) {
+ ss->preferredCipher = preferred;
+ break;
+ }
+ preferred += 3;
+ }
+ }
}
preferred = ss->preferredCipher ? ss->preferredCipher : noneSuch;
/*
** Scan list of ciphers received from peer and look for a match in
- ** our list.
- * Note: Our list may contain SSL v3 ciphers.
- * We MUST NOT match on any of those.
+ ** our list.
+ * Note: Our list may contain SSL v3 ciphers.
+ * We MUST NOT match on any of those.
* Fortunately, this is easy to detect because SSLv3 ciphers have zero
* in the first byte, and none of the SSLv2 ciphers do.
*/
bestKeySize = bestRealKeySize = 0;
bestCypher = -1;
while (--hc >= 0) {
- for (i = 0, ms = ss->cipherSpecs; i < ss->sizeCipherSpecs; i += 3, ms += 3) {
- if ((hs[0] == preferred[0]) &&
- (hs[1] == preferred[1]) &&
- (hs[2] == preferred[2]) &&
- hs[0] != 0) {
- /* Pick this cipher immediately! */
- *pKeyLen = (((hs[1] << 8) | hs[2]) + 7) >> 3;
- return hs[0];
- }
- if ((hs[0] == ms[0]) && (hs[1] == ms[1]) && (hs[2] == ms[2]) &&
- hs[0] != 0) {
- /* Found a match */
-
- /* Use secret keySize to determine which cipher is best */
- realKeySize = (hs[1] << 8) | hs[2];
- switch (hs[0]) {
- case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
- case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
- keySize = 40;
- break;
- default:
- keySize = realKeySize;
- break;
- }
- if (keySize > bestKeySize) {
- bestCypher = hs[0];
- bestKeySize = keySize;
- bestRealKeySize = realKeySize;
- }
- }
- }
- hs += 3;
+ for (i = 0, ms = ss->cipherSpecs; i < ss->sizeCipherSpecs; i += 3, ms += 3) {
+ if ((hs[0] == preferred[0]) &&
+ (hs[1] == preferred[1]) &&
+ (hs[2] == preferred[2]) &&
+ hs[0] != 0) {
+ /* Pick this cipher immediately! */
+ *pKeyLen = (((hs[1] << 8) | hs[2]) + 7) >> 3;
+ return hs[0];
+ }
+ if ((hs[0] == ms[0]) && (hs[1] == ms[1]) && (hs[2] == ms[2]) &&
+ hs[0] != 0) {
+ /* Found a match */
+
+ /* Use secret keySize to determine which cipher is best */
+ realKeySize = (hs[1] << 8) | hs[2];
+ switch (hs[0]) {
+ case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
+ case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
+ keySize = 40;
+ break;
+ default:
+ keySize = realKeySize;
+ break;
+ }
+ if (keySize > bestKeySize) {
+ bestCypher = hs[0];
+ bestKeySize = keySize;
+ bestRealKeySize = realKeySize;
+ }
+ }
+ }
+ hs += 3;
}
if (bestCypher < 0) {
- /*
- ** No overlap between server and client. Re-examine server list
- ** to see what kind of ciphers it does support so that we can set
- ** the error code appropriately.
- */
- if ((ohs[0] == SSL_CK_RC4_128_WITH_MD5) ||
- (ohs[0] == SSL_CK_RC2_128_CBC_WITH_MD5)) {
- PORT_SetError(SSL_ERROR_US_ONLY_SERVER);
- } else if ((ohs[0] == SSL_CK_RC4_128_EXPORT40_WITH_MD5) ||
- (ohs[0] == SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5)) {
- PORT_SetError(SSL_ERROR_EXPORT_ONLY_SERVER);
- } else {
- PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
- }
- SSL_DBG(("%d: SSL[%d]: no cipher overlap", SSL_GETPID(), ss->fd));
- goto loser;
+ /*
+ ** No overlap between server and client. Re-examine server list
+ ** to see what kind of ciphers it does support so that we can set
+ ** the error code appropriately.
+ */
+ if ((ohs[0] == SSL_CK_RC4_128_WITH_MD5) ||
+ (ohs[0] == SSL_CK_RC2_128_CBC_WITH_MD5)) {
+ PORT_SetError(SSL_ERROR_US_ONLY_SERVER);
+ } else if ((ohs[0] == SSL_CK_RC4_128_EXPORT40_WITH_MD5) ||
+ (ohs[0] == SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5)) {
+ PORT_SetError(SSL_ERROR_EXPORT_ONLY_SERVER);
+ } else {
+ PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
+ }
+ SSL_DBG(("%d: SSL[%d]: no cipher overlap", SSL_GETPID(), ss->fd));
+ goto loser;
}
*pKeyLen = (bestRealKeySize + 7) >> 3;
return bestCypher;
- loser:
+loser:
return -1;
}
static SECStatus
ssl2_ClientHandleServerCert(sslSocket *ss, PRUint8 *certData, int certLen)
{
- CERTCertificate *cert = NULL;
- SECItem certItem;
+ CERTCertificate *cert = NULL;
+ SECItem certItem;
certItem.data = certData;
- certItem.len = certLen;
+ certItem.len = certLen;
/* decode the certificate */
cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL,
- PR_FALSE, PR_TRUE);
-
+ PR_FALSE, PR_TRUE);
+
if (cert == NULL) {
- SSL_DBG(("%d: SSL[%d]: decode of server certificate fails",
- SSL_GETPID(), ss->fd));
- PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: decode of server certificate fails",
+ SSL_GETPID(), ss->fd));
+ PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
+ return SECFailure;
}
#ifdef TRACE
{
- if (ssl_trace >= 1) {
- char *issuer;
- char *subject;
- issuer = CERT_NameToAscii(&cert->issuer);
- subject = CERT_NameToAscii(&cert->subject);
- SSL_TRC(1,("%d: server certificate issuer: '%s'",
- SSL_GETPID(), issuer ? issuer : "OOPS"));
- SSL_TRC(1,("%d: server name: '%s'",
- SSL_GETPID(), subject ? subject : "OOPS"));
- PORT_Free(issuer);
- PORT_Free(subject);
- }
+ if (ssl_trace >= 1) {
+ char *issuer;
+ char *subject;
+ issuer = CERT_NameToAscii(&cert->issuer);
+ subject = CERT_NameToAscii(&cert->subject);
+ SSL_TRC(1, ("%d: server certificate issuer: '%s'",
+ SSL_GETPID(), issuer ? issuer : "OOPS"));
+ SSL_TRC(1, ("%d: server name: '%s'",
+ SSL_GETPID(), subject ? subject : "OOPS"));
+ PORT_Free(issuer);
+ PORT_Free(subject);
+ }
}
#endif
@@ -1925,16 +1928,15 @@ ssl2_ClientHandleServerCert(sslSocket *ss, PRUint8 *certData, int certLen)
return SECSuccess;
}
-
/*
* Format one block of data for public/private key encryption using
* the rules defined in PKCS #1. SSL2 does this itself to handle the
* rollback detection.
*/
-#define RSA_BLOCK_MIN_PAD_LEN 8
-#define RSA_BLOCK_FIRST_OCTET 0x00
-#define RSA_BLOCK_AFTER_PAD_OCTET 0x00
-#define RSA_BLOCK_PUBLIC_OCTET 0x02
+#define RSA_BLOCK_MIN_PAD_LEN 8
+#define RSA_BLOCK_FIRST_OCTET 0x00
+#define RSA_BLOCK_AFTER_PAD_OCTET 0x00
+#define RSA_BLOCK_PUBLIC_OCTET 0x02
unsigned char *
ssl_FormatSSL2Block(unsigned modulusLen, SECItem *data)
{
@@ -1945,18 +1947,18 @@ ssl_FormatSSL2Block(unsigned modulusLen, SECItem *data)
int i;
if (modulusLen < data->len + (3 + RSA_BLOCK_MIN_PAD_LEN)) {
- PORT_SetError(SEC_ERROR_BAD_KEY);
- return NULL;
+ PORT_SetError(SEC_ERROR_BAD_KEY);
+ return NULL;
}
- block = (unsigned char *) PORT_Alloc(modulusLen);
+ block = (unsigned char *)PORT_Alloc(modulusLen);
if (block == NULL)
- return NULL;
+ return NULL;
bp = block;
/*
* All RSA blocks start with two octets:
- * 0x00 || BlockType
+ * 0x00 || BlockType
*/
*bp++ = RSA_BLOCK_FIRST_OCTET;
*bp++ = RSA_BLOCK_PUBLIC_OCTET;
@@ -1967,23 +1969,26 @@ ssl_FormatSSL2Block(unsigned modulusLen, SECItem *data)
* Pad is all non-zero random bytes.
*/
padLen = modulusLen - data->len - 3;
- PORT_Assert (padLen >= RSA_BLOCK_MIN_PAD_LEN);
+ PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
rv = PK11_GenerateRandom(bp, padLen);
- if (rv == SECFailure) goto loser;
+ if (rv == SECFailure)
+ goto loser;
/* replace all the 'zero' bytes */
for (i = 0; i < padLen; i++) {
- while (bp[i] == RSA_BLOCK_AFTER_PAD_OCTET) {
- rv = PK11_GenerateRandom(bp+i, 1);
- if (rv == SECFailure) goto loser;
- }
+ while (bp[i] == RSA_BLOCK_AFTER_PAD_OCTET) {
+ rv = PK11_GenerateRandom(bp + i, 1);
+ if (rv == SECFailure)
+ goto loser;
+ }
}
bp += padLen;
*bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
- PORT_Memcpy (bp, data->data, data->len);
+ PORT_Memcpy(bp, data->data, data->len);
return block;
loser:
- if (block) PORT_Free(block);
+ if (block)
+ PORT_Free(block);
return NULL;
}
@@ -1998,26 +2003,26 @@ loser:
static SECStatus
ssl2_ClientSetupSessionCypher(sslSocket *ss, PRUint8 *cs, int csLen)
{
- sslSessionID * sid;
- PRUint8 * ca; /* points to iv data, or NULL if none. */
- PRUint8 * ekbuf = 0;
- CERTCertificate * cert = 0;
- SECKEYPublicKey * serverKey = 0;
- unsigned modulusLen = 0;
- SECStatus rv;
- int cipher;
- int keyLen; /* cipher symkey size in bytes. */
- int ckLen; /* publicly reveal this many bytes of key. */
- int caLen; /* length of IV data at *ca. */
- int nc;
-
- unsigned char *eblock; /* holds unencrypted PKCS#1 formatted key. */
- SECItem rek; /* holds portion of symkey to be encrypted. */
-
- PRUint8 keyData[SSL_MAX_MASTER_KEY_BYTES];
- PRUint8 iv [8];
-
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ sslSessionID *sid;
+ PRUint8 *ca; /* points to iv data, or NULL if none. */
+ PRUint8 *ekbuf = 0;
+ CERTCertificate *cert = 0;
+ SECKEYPublicKey *serverKey = 0;
+ unsigned modulusLen = 0;
+ SECStatus rv;
+ int cipher;
+ int keyLen; /* cipher symkey size in bytes. */
+ int ckLen; /* publicly reveal this many bytes of key. */
+ int caLen; /* length of IV data at *ca. */
+ int nc;
+
+ unsigned char *eblock; /* holds unencrypted PKCS#1 formatted key. */
+ SECItem rek; /* holds portion of symkey to be encrypted. */
+
+ PRUint8 keyData[SSL_MAX_MASTER_KEY_BYTES];
+ PRUint8 iv[8];
+
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
eblock = NULL;
@@ -2025,28 +2030,28 @@ ssl2_ClientSetupSessionCypher(sslSocket *ss, PRUint8 *cs, int csLen)
PORT_Assert(sid != 0);
cert = ss->sec.peerCert;
-
+
serverKey = CERT_ExtractPublicKey(cert);
if (!serverKey) {
- SSL_DBG(("%d: SSL[%d]: extract public key failed: error=%d",
- SSL_GETPID(), ss->fd, PORT_GetError()));
- PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
- rv = SECFailure;
- goto loser2;
+ SSL_DBG(("%d: SSL[%d]: extract public key failed: error=%d",
+ SSL_GETPID(), ss->fd, PORT_GetError()));
+ PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
+ rv = SECFailure;
+ goto loser2;
}
ss->sec.authAlgorithm = ssl_sign_rsa;
- ss->sec.keaType = ssl_kea_rsa;
- ss->sec.keaKeyBits = \
- ss->sec.authKeyBits = SECKEY_PublicKeyStrengthInBits(serverKey);
+ ss->sec.keaType = ssl_kea_rsa;
+ ss->sec.keaKeyBits =
+ ss->sec.authKeyBits = SECKEY_PublicKeyStrengthInBits(serverKey);
/* Choose a compatible cipher with the server */
nc = csLen / 3;
cipher = ssl2_ChooseSessionCypher(ss, nc, cs, &keyLen);
if (cipher < 0) {
- /* ssl2_ChooseSessionCypher has set error code. */
- ssl2_SendErrorMessage(ss, SSL_PE_NO_CYPHERS);
- goto loser;
+ /* ssl2_ChooseSessionCypher has set error code. */
+ ssl2_SendErrorMessage(ss, SSL_PE_NO_CYPHERS);
+ goto loser;
}
/* Generate the random keys */
@@ -2061,79 +2066,79 @@ ssl2_ClientSetupSessionCypher(sslSocket *ss, PRUint8 *cs, int csLen)
*/
ca = 0;
- /* We know that cipher is a legit value here, because
+ /* We know that cipher is a legit value here, because
* ssl2_ChooseSessionCypher doesn't return bogus values.
*/
- ckLen = ssl_Specs[cipher].pubLen; /* cleartext key length. */
- caLen = ssl_Specs[cipher].ivLen; /* IV length. */
+ ckLen = ssl_Specs[cipher].pubLen; /* cleartext key length. */
+ caLen = ssl_Specs[cipher].ivLen; /* IV length. */
if (caLen) {
- PORT_Assert(sizeof iv >= caLen);
- PK11_GenerateRandom(iv, caLen);
- ca = iv;
+ PORT_Assert(sizeof iv >= caLen);
+ PK11_GenerateRandom(iv, caLen);
+ ca = iv;
}
/* Fill in session-id */
rv = ssl2_FillInSID(sid, cipher, keyData, keyLen,
- ca, caLen, keyLen << 3, (keyLen - ckLen) << 3,
- ss->sec.authAlgorithm, ss->sec.authKeyBits,
- ss->sec.keaType, ss->sec.keaKeyBits);
+ ca, caLen, keyLen << 3, (keyLen - ckLen) << 3,
+ ss->sec.authAlgorithm, ss->sec.authKeyBits,
+ ss->sec.keaType, ss->sec.keaKeyBits);
if (rv != SECSuccess) {
- goto loser;
+ goto loser;
}
SSL_TRC(1, ("%d: SSL[%d]: client, using %s cipher, clear=%d total=%d",
- SSL_GETPID(), ss->fd, ssl_cipherName[cipher],
- ckLen<<3, keyLen<<3));
+ SSL_GETPID(), ss->fd, ssl_cipherName[cipher],
+ ckLen << 3, keyLen << 3));
/* Now setup read and write ciphers */
rv = ssl2_CreateSessionCypher(ss, sid, PR_TRUE);
if (rv != SECSuccess) {
- goto loser;
+ goto loser;
}
/*
- ** Fill in the encryption buffer with some random bytes. Then
+ ** Fill in the encryption buffer with some random bytes. Then
** copy in the portion of the session key we are encrypting.
*/
modulusLen = SECKEY_PublicKeyStrength(serverKey);
- rek.data = keyData + ckLen;
- rek.len = keyLen - ckLen;
+ rek.data = keyData + ckLen;
+ rek.len = keyLen - ckLen;
eblock = ssl_FormatSSL2Block(modulusLen, &rek);
- if (eblock == NULL)
- goto loser;
+ if (eblock == NULL)
+ goto loser;
/* Set up the padding for version 2 rollback detection. */
/* XXX We should really use defines here */
if (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
- PORT_Assert((modulusLen - rek.len) > 12);
- PORT_Memset(eblock + modulusLen - rek.len - 8 - 1, 0x03, 8);
+ PORT_Assert((modulusLen - rek.len) > 12);
+ PORT_Memset(eblock + modulusLen - rek.len - 8 - 1, 0x03, 8);
}
- ekbuf = (PRUint8*) PORT_Alloc(modulusLen);
- if (!ekbuf)
- goto loser;
+ ekbuf = (PRUint8 *)PORT_Alloc(modulusLen);
+ if (!ekbuf)
+ goto loser;
PRINT_BUF(10, (ss, "master key encryption block:",
- eblock, modulusLen));
+ eblock, modulusLen));
/* Encrypt ekitem */
rv = PK11_PubEncryptRaw(serverKey, ekbuf, eblock, modulusLen,
- ss->pkcs11PinArg);
- if (rv)
- goto loser;
+ ss->pkcs11PinArg);
+ if (rv)
+ goto loser;
/* Now we have everything ready to send */
rv = ssl2_SendSessionKeyMessage(ss, cipher, keyLen << 3, ca, caLen,
- keyData, ckLen, ekbuf, modulusLen);
+ keyData, ckLen, ekbuf, modulusLen);
if (rv != SECSuccess) {
- goto loser;
+ goto loser;
}
rv = SECSuccess;
goto done;
- loser:
+loser:
rv = SECFailure;
- loser2:
- done:
+loser2:
+done:
PORT_Memset(keyData, 0, sizeof(keyData));
PORT_ZFree(ekbuf, modulusLen);
PORT_ZFree(eblock, modulusLen);
@@ -2143,7 +2148,7 @@ ssl2_ClientSetupSessionCypher(sslSocket *ss, PRUint8 *cs, int csLen)
/************************************************************************/
-/*
+/*
* Called from ssl2_HandleMessage in response to SSL_MT_SERVER_FINISHED message.
* Caller holds recvBufLock and handshakeLock
*/
@@ -2154,27 +2159,26 @@ ssl2_ClientRegSessionID(sslSocket *ss, PRUint8 *s)
/* Record entry in nonce cache */
if (sid->peerCert == NULL) {
- PORT_Memcpy(sid->u.ssl2.sessionID, s, sizeof(sid->u.ssl2.sessionID));
- sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
-
+ PORT_Memcpy(sid->u.ssl2.sessionID, s, sizeof(sid->u.ssl2.sessionID));
+ sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
}
if (!ss->opt.noCache && sid->cached == never_cached)
- (*ss->sec.cache)(sid);
+ (*ss->sec.cache)(sid);
}
/* Called from ssl2_HandleMessage() */
static SECStatus
ssl2_TriggerNextMessage(sslSocket *ss)
{
- SECStatus rv;
+ SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
if ((ss->sec.ci.requiredElements & CIS_HAVE_CERTIFICATE) &&
- !(ss->sec.ci.sentElements & CIS_HAVE_CERTIFICATE)) {
- ss->sec.ci.sentElements |= CIS_HAVE_CERTIFICATE;
- rv = ssl2_SendCertificateRequestMessage(ss);
- return rv;
+ !(ss->sec.ci.sentElements & CIS_HAVE_CERTIFICATE)) {
+ ss->sec.ci.sentElements |= CIS_HAVE_CERTIFICATE;
+ rv = ssl2_SendCertificateRequestMessage(ss);
+ return rv;
}
return SECSuccess;
}
@@ -2184,36 +2188,36 @@ ssl2_TriggerNextMessage(sslSocket *ss)
** Returns SECSuccess unless anything goes wrong.
**
** Called from ssl2_HandleMessage,
-** ssl2_HandleVerifyMessage
+** ssl2_HandleVerifyMessage
** ssl2_HandleServerHelloMessage
** ssl2_HandleClientSessionKeyMessage
*/
static SECStatus
ssl2_TryToFinish(sslSocket *ss)
{
- SECStatus rv;
- char e, ef;
+ SECStatus rv;
+ char e, ef;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
e = ss->sec.ci.elements;
ef = e | CIS_HAVE_FINISHED;
if ((ef & ss->sec.ci.requiredElements) == ss->sec.ci.requiredElements) {
- if (ss->sec.isServer) {
- /* Send server finished message if we already didn't */
- rv = ssl2_SendServerFinishedMessage(ss);
- } else {
- /* Send client finished message if we already didn't */
- rv = ssl2_SendClientFinishedMessage(ss);
- }
- if (rv != SECSuccess) {
- return rv;
- }
- if ((e & ss->sec.ci.requiredElements) == ss->sec.ci.requiredElements) {
- /* Totally finished */
- ss->handshake = 0;
- return SECSuccess;
- }
+ if (ss->sec.isServer) {
+ /* Send server finished message if we already didn't */
+ rv = ssl2_SendServerFinishedMessage(ss);
+ } else {
+ /* Send client finished message if we already didn't */
+ rv = ssl2_SendClientFinishedMessage(ss);
+ }
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ if ((e & ss->sec.ci.requiredElements) == ss->sec.ci.requiredElements) {
+ /* Totally finished */
+ ss->handshake = 0;
+ return SECSuccess;
+ }
}
return SECSuccess;
}
@@ -2223,42 +2227,42 @@ ssl2_TryToFinish(sslSocket *ss)
*/
static SECStatus
ssl2_SignResponse(sslSocket *ss,
- SECKEYPrivateKey *key,
- SECItem *response)
+ SECKEYPrivateKey *key,
+ SECItem *response)
{
- SGNContext * sgn = NULL;
- PRUint8 * challenge;
- unsigned int len;
- SECStatus rv = SECFailure;
-
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ SGNContext *sgn = NULL;
+ PRUint8 *challenge;
+ unsigned int len;
+ SECStatus rv = SECFailure;
+
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
challenge = ss->sec.ci.serverChallenge;
len = ss->sec.ci.serverChallengeLen;
-
+
/* Sign the expected data... */
- sgn = SGN_NewContext(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,key);
- if (!sgn)
- goto done;
+ sgn = SGN_NewContext(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, key);
+ if (!sgn)
+ goto done;
rv = SGN_Begin(sgn);
- if (rv != SECSuccess)
- goto done;
+ if (rv != SECSuccess)
+ goto done;
rv = SGN_Update(sgn, ss->sec.ci.readKey, ss->sec.ci.keySize);
- if (rv != SECSuccess)
- goto done;
+ if (rv != SECSuccess)
+ goto done;
rv = SGN_Update(sgn, ss->sec.ci.writeKey, ss->sec.ci.keySize);
- if (rv != SECSuccess)
- goto done;
+ if (rv != SECSuccess)
+ goto done;
rv = SGN_Update(sgn, challenge, len);
- if (rv != SECSuccess)
- goto done;
- rv = SGN_Update(sgn, ss->sec.peerCert->derCert.data,
- ss->sec.peerCert->derCert.len);
- if (rv != SECSuccess)
- goto done;
+ if (rv != SECSuccess)
+ goto done;
+ rv = SGN_Update(sgn, ss->sec.peerCert->derCert.data,
+ ss->sec.peerCert->derCert.len);
+ if (rv != SECSuccess)
+ goto done;
rv = SGN_End(sgn, response);
- if (rv != SECSuccess)
- goto done;
+ if (rv != SECSuccess)
+ goto done;
done:
SGN_DestroyContext(sgn, PR_TRUE);
@@ -2268,20 +2272,19 @@ done:
/*
** Try to handle a request-certificate message. Get client's certificate
** and private key and sign a message for the server to see.
-** Caller must hold handshakeLock
+** Caller must hold handshakeLock
**
** Called from ssl2_HandleMessage().
*/
static int
ssl2_HandleRequestCertificate(sslSocket *ss)
{
- CERTCertificate * cert = NULL; /* app-selected client cert. */
- SECKEYPrivateKey *key = NULL; /* priv key for cert. */
- SECStatus rv;
- SECItem response;
- int ret = 0;
- PRUint8 authType;
-
+ CERTCertificate *cert = NULL; /* app-selected client cert. */
+ SECKEYPrivateKey *key = NULL; /* priv key for cert. */
+ SECStatus rv;
+ SECItem response;
+ int ret = 0;
+ PRUint8 authType;
/*
* These things all need to be initialized before we can "goto loser".
@@ -2292,27 +2295,27 @@ ssl2_HandleRequestCertificate(sslSocket *ss)
authType = ss->sec.ci.authType;
if (authType != SSL_AT_MD5_WITH_RSA_ENCRYPTION) {
- SSL_TRC(7, ("%d: SSL[%d]: unsupported auth type 0x%x", SSL_GETPID(),
- ss->fd, authType));
- goto no_cert_error;
+ SSL_TRC(7, ("%d: SSL[%d]: unsupported auth type 0x%x", SSL_GETPID(),
+ ss->fd, authType));
+ goto no_cert_error;
}
/* Get certificate and private-key from client */
if (!ss->getClientAuthData) {
- SSL_TRC(7, ("%d: SSL[%d]: client doesn't support client-auth",
- SSL_GETPID(), ss->fd));
- goto no_cert_error;
+ SSL_TRC(7, ("%d: SSL[%d]: client doesn't support client-auth",
+ SSL_GETPID(), ss->fd));
+ goto no_cert_error;
}
ret = (*ss->getClientAuthData)(ss->getClientAuthDataArg, ss->fd,
- NULL, &cert, &key);
- if ( ret == SECWouldBlock ) {
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
- ret = -1;
- goto loser;
+ NULL, &cert, &key);
+ if (ret == SECWouldBlock) {
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
+ ret = -1;
+ goto loser;
}
if (ret) {
- goto no_cert_error;
+ goto no_cert_error;
}
/* check what the callback function returned */
@@ -2332,9 +2335,9 @@ ssl2_HandleRequestCertificate(sslSocket *ss)
}
rv = ssl2_SignResponse(ss, key, &response);
- if ( rv != SECSuccess ) {
- ret = -1;
- goto loser;
+ if (rv != SECSuccess) {
+ ret = -1;
+ goto loser;
}
/* Send response message */
@@ -2342,35 +2345,35 @@ ssl2_HandleRequestCertificate(sslSocket *ss)
/* Now, remember the cert we sent. But first, forget any previous one. */
if (ss->sec.localCert) {
- CERT_DestroyCertificate(ss->sec.localCert);
+ CERT_DestroyCertificate(ss->sec.localCert);
}
ss->sec.localCert = CERT_DupCertificate(cert);
PORT_Assert(!ss->sec.ci.sid->localCert);
if (ss->sec.ci.sid->localCert) {
- CERT_DestroyCertificate(ss->sec.ci.sid->localCert);
+ CERT_DestroyCertificate(ss->sec.ci.sid->localCert);
}
ss->sec.ci.sid->localCert = cert;
cert = NULL;
goto done;
- no_cert_error:
+no_cert_error:
SSL_TRC(7, ("%d: SSL[%d]: no certificate (ret=%d)", SSL_GETPID(),
- ss->fd, ret));
+ ss->fd, ret));
ret = ssl2_SendErrorMessage(ss, SSL_PE_NO_CERTIFICATE);
- loser:
- done:
- if ( cert ) {
- CERT_DestroyCertificate(cert);
+loser:
+done:
+ if (cert) {
+ CERT_DestroyCertificate(cert);
}
- if ( key ) {
- SECKEY_DestroyPrivateKey(key);
+ if (key) {
+ SECKEY_DestroyPrivateKey(key);
}
- if ( response.data ) {
- PORT_Free(response.data);
+ if (response.data) {
+ PORT_Free(response.data);
}
-
+
return ret;
}
@@ -2380,32 +2383,32 @@ ssl2_HandleRequestCertificate(sslSocket *ss)
** are contained in the gathered input data.
*/
static SECStatus
-ssl2_HandleClientCertificate(sslSocket * ss,
- PRUint8 certType, /* XXX unused */
- PRUint8 * cd,
- unsigned int cdLen,
- PRUint8 * response,
- unsigned int responseLen)
+ssl2_HandleClientCertificate(sslSocket *ss,
+ PRUint8 certType, /* XXX unused */
+ PRUint8 *cd,
+ unsigned int cdLen,
+ PRUint8 *response,
+ unsigned int responseLen)
{
- CERTCertificate *cert = NULL;
- SECKEYPublicKey *pubKey = NULL;
- VFYContext * vfy = NULL;
- SECItem * derCert;
- SECStatus rv = SECFailure;
- SECItem certItem;
- SECItem rep;
+ CERTCertificate *cert = NULL;
+ SECKEYPublicKey *pubKey = NULL;
+ VFYContext *vfy = NULL;
+ SECItem *derCert;
+ SECStatus rv = SECFailure;
+ SECItem certItem;
+ SECItem rep;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
/* Extract the certificate */
certItem.data = cd;
- certItem.len = cdLen;
+ certItem.len = cdLen;
cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL,
- PR_FALSE, PR_TRUE);
+ PR_FALSE, PR_TRUE);
if (cert == NULL) {
- goto loser;
+ goto loser;
}
/* save the certificate, since the auth routine will need it */
@@ -2413,46 +2416,46 @@ ssl2_HandleClientCertificate(sslSocket * ss,
/* Extract the public key */
pubKey = CERT_ExtractPublicKey(cert);
- if (!pubKey)
- goto loser;
-
+ if (!pubKey)
+ goto loser;
+
/* Verify the response data... */
rep.data = response;
rep.len = responseLen;
/* SSL 2.0 only supports RSA certs, so we don't have to worry about
* DSA here. */
vfy = VFY_CreateContext(pubKey, &rep, SEC_OID_PKCS1_RSA_ENCRYPTION,
- ss->pkcs11PinArg);
- if (!vfy)
- goto loser;
+ ss->pkcs11PinArg);
+ if (!vfy)
+ goto loser;
rv = VFY_Begin(vfy);
- if (rv)
- goto loser;
+ if (rv)
+ goto loser;
rv = VFY_Update(vfy, ss->sec.ci.readKey, ss->sec.ci.keySize);
- if (rv)
- goto loser;
+ if (rv)
+ goto loser;
rv = VFY_Update(vfy, ss->sec.ci.writeKey, ss->sec.ci.keySize);
- if (rv)
- goto loser;
+ if (rv)
+ goto loser;
rv = VFY_Update(vfy, ss->sec.ci.serverChallenge, SSL_CHALLENGE_BYTES);
- if (rv)
- goto loser;
+ if (rv)
+ goto loser;
derCert = &ss->serverCerts[kt_rsa].serverCert->derCert;
rv = VFY_Update(vfy, derCert->data, derCert->len);
- if (rv)
- goto loser;
+ if (rv)
+ goto loser;
rv = VFY_End(vfy);
- if (rv)
- goto loser;
+ if (rv)
+ goto loser;
/* Now ask the server application if it likes the certificate... */
- rv = (SECStatus) (*ss->authCertificate)(ss->authCertificateArg,
- ss->fd, PR_TRUE, PR_TRUE);
+ rv = (SECStatus)(*ss->authCertificate)(ss->authCertificateArg,
+ ss->fd, PR_TRUE, PR_TRUE);
/* Hey, it liked it. */
- if (SECSuccess == rv)
- goto done;
+ if (SECSuccess == rv)
+ goto done;
loser:
ss->sec.peerCert = NULL;
@@ -2467,200 +2470,200 @@ done:
/*
** Handle remaining messages between client/server. Process finished
** messages from either side and any authentication requests.
-** This should only be called for SSLv2 handshake messages,
+** This should only be called for SSLv2 handshake messages,
** not for application data records.
** Caller must hold handshake lock.
**
** Called from ssl_Do1stHandshake().
-**
+**
*/
static SECStatus
ssl2_HandleMessage(sslSocket *ss)
{
- PRUint8 * data;
- PRUint8 * cid;
- unsigned len, certType, certLen, responseLen;
- int rv;
+ PRUint8 *data;
+ PRUint8 *cid;
+ unsigned len, certType, certLen, responseLen;
+ int rv;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
ssl_GetRecvBufLock(ss);
data = ss->gs.buf.buf + ss->gs.recordOffset;
if (ss->gs.recordLen < 1) {
- goto bad_peer;
+ goto bad_peer;
}
SSL_TRC(3, ("%d: SSL[%d]: received %d message",
- SSL_GETPID(), ss->fd, data[0]));
+ SSL_GETPID(), ss->fd, data[0]));
DUMP_MSG(29, (ss, data, ss->gs.recordLen));
switch (data[0]) {
- case SSL_MT_CLIENT_FINISHED:
- if (ss->sec.ci.elements & CIS_HAVE_FINISHED) {
- SSL_DBG(("%d: SSL[%d]: dup client-finished message",
- SSL_GETPID(), ss->fd));
- goto bad_peer;
- }
-
- /* See if nonce matches */
- len = ss->gs.recordLen - 1;
- cid = data + 1;
- if ((len != sizeof(ss->sec.ci.connectionID)) ||
- (PORT_Memcmp(ss->sec.ci.connectionID, cid, len) != 0)) {
- SSL_DBG(("%d: SSL[%d]: bad connection-id", SSL_GETPID(), ss->fd));
- PRINT_BUF(5, (ss, "sent connection-id",
- ss->sec.ci.connectionID,
- sizeof(ss->sec.ci.connectionID)));
- PRINT_BUF(5, (ss, "rcvd connection-id", cid, len));
- goto bad_peer;
- }
-
- SSL_TRC(5, ("%d: SSL[%d]: got client finished, waiting for 0x%d",
- SSL_GETPID(), ss->fd,
- ss->sec.ci.requiredElements ^ ss->sec.ci.elements));
- ss->sec.ci.elements |= CIS_HAVE_FINISHED;
- break;
-
- case SSL_MT_SERVER_FINISHED:
- if (ss->sec.ci.elements & CIS_HAVE_FINISHED) {
- SSL_DBG(("%d: SSL[%d]: dup server-finished message",
- SSL_GETPID(), ss->fd));
- goto bad_peer;
- }
-
- if (ss->gs.recordLen - 1 != SSL2_SESSIONID_BYTES) {
- SSL_DBG(("%d: SSL[%d]: bad server-finished message, len=%d",
- SSL_GETPID(), ss->fd, ss->gs.recordLen));
- goto bad_peer;
- }
- ssl2_ClientRegSessionID(ss, data+1);
- SSL_TRC(5, ("%d: SSL[%d]: got server finished, waiting for 0x%d",
- SSL_GETPID(), ss->fd,
- ss->sec.ci.requiredElements ^ ss->sec.ci.elements));
- ss->sec.ci.elements |= CIS_HAVE_FINISHED;
- break;
-
- case SSL_MT_REQUEST_CERTIFICATE:
- len = ss->gs.recordLen - 2;
- if ((len < SSL_MIN_CHALLENGE_BYTES) ||
- (len > SSL_MAX_CHALLENGE_BYTES)) {
- /* Bad challenge */
- SSL_DBG(("%d: SSL[%d]: bad cert request message: code len=%d",
- SSL_GETPID(), ss->fd, len));
- goto bad_peer;
- }
-
- /* save auth request info */
- ss->sec.ci.authType = data[1];
- ss->sec.ci.serverChallengeLen = len;
- PORT_Memcpy(ss->sec.ci.serverChallenge, data + 2, len);
-
- rv = ssl2_HandleRequestCertificate(ss);
- if (rv == SECWouldBlock) {
- SSL_TRC(3, ("%d: SSL[%d]: async cert request",
- SSL_GETPID(), ss->fd));
- /* someone is handling this asynchronously */
- ssl_ReleaseRecvBufLock(ss);
- return SECWouldBlock;
- }
- if (rv) {
- SET_ERROR_CODE
- goto loser;
- }
- break;
-
- case SSL_MT_CLIENT_CERTIFICATE:
- if (!ss->authCertificate) {
- /* Server asked for authentication and can't handle it */
- PORT_SetError(SSL_ERROR_BAD_SERVER);
- goto loser;
- }
- if (ss->gs.recordLen < SSL_HL_CLIENT_CERTIFICATE_HBYTES) {
- SET_ERROR_CODE
- goto loser;
- }
- certType = data[1];
- certLen = (data[2] << 8) | data[3];
- responseLen = (data[4] << 8) | data[5];
- if (certType != SSL_CT_X509_CERTIFICATE) {
- PORT_SetError(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
- goto loser;
- }
- if (certLen + responseLen + SSL_HL_CLIENT_CERTIFICATE_HBYTES
- > ss->gs.recordLen) {
- /* prevent overflow crash. */
- rv = SECFailure;
- } else
- rv = ssl2_HandleClientCertificate(ss, data[1],
- data + SSL_HL_CLIENT_CERTIFICATE_HBYTES,
- certLen,
- data + SSL_HL_CLIENT_CERTIFICATE_HBYTES + certLen,
- responseLen);
- if (rv) {
- (void)ssl2_SendErrorMessage(ss, SSL_PE_BAD_CERTIFICATE);
- SET_ERROR_CODE
- goto loser;
- }
- ss->sec.ci.elements |= CIS_HAVE_CERTIFICATE;
- break;
-
- case SSL_MT_ERROR:
- rv = (data[1] << 8) | data[2];
- SSL_TRC(2, ("%d: SSL[%d]: got error message, error=0x%x",
- SSL_GETPID(), ss->fd, rv));
-
- /* Convert protocol error number into API error number */
- switch (rv) {
- case SSL_PE_NO_CYPHERS:
- rv = SSL_ERROR_NO_CYPHER_OVERLAP;
- break;
- case SSL_PE_NO_CERTIFICATE:
- rv = SSL_ERROR_NO_CERTIFICATE;
- break;
- case SSL_PE_BAD_CERTIFICATE:
- rv = SSL_ERROR_BAD_CERTIFICATE;
- break;
- case SSL_PE_UNSUPPORTED_CERTIFICATE_TYPE:
- rv = SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE;
- break;
- default:
- goto bad_peer;
- }
- /* XXX make certificate-request optionally fail... */
- PORT_SetError(rv);
- goto loser;
-
- default:
- SSL_DBG(("%d: SSL[%d]: unknown message %d",
- SSL_GETPID(), ss->fd, data[0]));
- goto loser;
+ case SSL_MT_CLIENT_FINISHED:
+ if (ss->sec.ci.elements & CIS_HAVE_FINISHED) {
+ SSL_DBG(("%d: SSL[%d]: dup client-finished message",
+ SSL_GETPID(), ss->fd));
+ goto bad_peer;
+ }
+
+ /* See if nonce matches */
+ len = ss->gs.recordLen - 1;
+ cid = data + 1;
+ if ((len != sizeof(ss->sec.ci.connectionID)) ||
+ (PORT_Memcmp(ss->sec.ci.connectionID, cid, len) != 0)) {
+ SSL_DBG(("%d: SSL[%d]: bad connection-id", SSL_GETPID(), ss->fd));
+ PRINT_BUF(5, (ss, "sent connection-id",
+ ss->sec.ci.connectionID,
+ sizeof(ss->sec.ci.connectionID)));
+ PRINT_BUF(5, (ss, "rcvd connection-id", cid, len));
+ goto bad_peer;
+ }
+
+ SSL_TRC(5, ("%d: SSL[%d]: got client finished, waiting for 0x%d",
+ SSL_GETPID(), ss->fd,
+ ss->sec.ci.requiredElements ^ ss->sec.ci.elements));
+ ss->sec.ci.elements |= CIS_HAVE_FINISHED;
+ break;
+
+ case SSL_MT_SERVER_FINISHED:
+ if (ss->sec.ci.elements & CIS_HAVE_FINISHED) {
+ SSL_DBG(("%d: SSL[%d]: dup server-finished message",
+ SSL_GETPID(), ss->fd));
+ goto bad_peer;
+ }
+
+ if (ss->gs.recordLen - 1 != SSL2_SESSIONID_BYTES) {
+ SSL_DBG(("%d: SSL[%d]: bad server-finished message, len=%d",
+ SSL_GETPID(), ss->fd, ss->gs.recordLen));
+ goto bad_peer;
+ }
+ ssl2_ClientRegSessionID(ss, data + 1);
+ SSL_TRC(5, ("%d: SSL[%d]: got server finished, waiting for 0x%d",
+ SSL_GETPID(), ss->fd,
+ ss->sec.ci.requiredElements ^ ss->sec.ci.elements));
+ ss->sec.ci.elements |= CIS_HAVE_FINISHED;
+ break;
+
+ case SSL_MT_REQUEST_CERTIFICATE:
+ len = ss->gs.recordLen - 2;
+ if ((len < SSL_MIN_CHALLENGE_BYTES) ||
+ (len > SSL_MAX_CHALLENGE_BYTES)) {
+ /* Bad challenge */
+ SSL_DBG(("%d: SSL[%d]: bad cert request message: code len=%d",
+ SSL_GETPID(), ss->fd, len));
+ goto bad_peer;
+ }
+
+ /* save auth request info */
+ ss->sec.ci.authType = data[1];
+ ss->sec.ci.serverChallengeLen = len;
+ PORT_Memcpy(ss->sec.ci.serverChallenge, data + 2, len);
+
+ rv = ssl2_HandleRequestCertificate(ss);
+ if (rv == SECWouldBlock) {
+ SSL_TRC(3, ("%d: SSL[%d]: async cert request",
+ SSL_GETPID(), ss->fd));
+ /* someone is handling this asynchronously */
+ ssl_ReleaseRecvBufLock(ss);
+ return SECWouldBlock;
+ }
+ if (rv) {
+ SET_ERROR_CODE
+ goto loser;
+ }
+ break;
+
+ case SSL_MT_CLIENT_CERTIFICATE:
+ if (!ss->authCertificate) {
+ /* Server asked for authentication and can't handle it */
+ PORT_SetError(SSL_ERROR_BAD_SERVER);
+ goto loser;
+ }
+ if (ss->gs.recordLen < SSL_HL_CLIENT_CERTIFICATE_HBYTES) {
+ SET_ERROR_CODE
+ goto loser;
+ }
+ certType = data[1];
+ certLen = (data[2] << 8) | data[3];
+ responseLen = (data[4] << 8) | data[5];
+ if (certType != SSL_CT_X509_CERTIFICATE) {
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
+ goto loser;
+ }
+ if (certLen + responseLen + SSL_HL_CLIENT_CERTIFICATE_HBYTES >
+ ss->gs.recordLen) {
+ /* prevent overflow crash. */
+ rv = SECFailure;
+ } else
+ rv = ssl2_HandleClientCertificate(ss, data[1],
+ data + SSL_HL_CLIENT_CERTIFICATE_HBYTES,
+ certLen,
+ data + SSL_HL_CLIENT_CERTIFICATE_HBYTES + certLen,
+ responseLen);
+ if (rv) {
+ (void)ssl2_SendErrorMessage(ss, SSL_PE_BAD_CERTIFICATE);
+ SET_ERROR_CODE
+ goto loser;
+ }
+ ss->sec.ci.elements |= CIS_HAVE_CERTIFICATE;
+ break;
+
+ case SSL_MT_ERROR:
+ rv = (data[1] << 8) | data[2];
+ SSL_TRC(2, ("%d: SSL[%d]: got error message, error=0x%x",
+ SSL_GETPID(), ss->fd, rv));
+
+ /* Convert protocol error number into API error number */
+ switch (rv) {
+ case SSL_PE_NO_CYPHERS:
+ rv = SSL_ERROR_NO_CYPHER_OVERLAP;
+ break;
+ case SSL_PE_NO_CERTIFICATE:
+ rv = SSL_ERROR_NO_CERTIFICATE;
+ break;
+ case SSL_PE_BAD_CERTIFICATE:
+ rv = SSL_ERROR_BAD_CERTIFICATE;
+ break;
+ case SSL_PE_UNSUPPORTED_CERTIFICATE_TYPE:
+ rv = SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE;
+ break;
+ default:
+ goto bad_peer;
+ }
+ /* XXX make certificate-request optionally fail... */
+ PORT_SetError(rv);
+ goto loser;
+
+ default:
+ SSL_DBG(("%d: SSL[%d]: unknown message %d",
+ SSL_GETPID(), ss->fd, data[0]));
+ goto loser;
}
SSL_TRC(3, ("%d: SSL[%d]: handled %d message, required=0x%x got=0x%x",
- SSL_GETPID(), ss->fd, data[0],
- ss->sec.ci.requiredElements, ss->sec.ci.elements));
+ SSL_GETPID(), ss->fd, data[0],
+ ss->sec.ci.requiredElements, ss->sec.ci.elements));
rv = ssl2_TryToFinish(ss);
- if (rv != SECSuccess)
- goto loser;
+ if (rv != SECSuccess)
+ goto loser;
ss->gs.recordLen = 0;
ssl_ReleaseRecvBufLock(ss);
if (ss->handshake == 0) {
- return SECSuccess;
+ return SECSuccess;
}
- ss->handshake = ssl_GatherRecord1stHandshake;
+ ss->handshake = ssl_GatherRecord1stHandshake;
ss->nextHandshake = ssl2_HandleMessage;
return ssl2_TriggerNextMessage(ss);
- bad_peer:
+bad_peer:
PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT : SSL_ERROR_BAD_SERVER);
- /* FALL THROUGH */
+/* FALL THROUGH */
- loser:
+loser:
ssl_ReleaseRecvBufLock(ss);
return SECFailure;
}
@@ -2672,67 +2675,66 @@ ssl2_HandleMessage(sslSocket *ss)
static SECStatus
ssl2_HandleVerifyMessage(sslSocket *ss)
{
- PRUint8 * data;
- SECStatus rv;
+ PRUint8 *data;
+ SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
ssl_GetRecvBufLock(ss);
data = ss->gs.buf.buf + ss->gs.recordOffset;
DUMP_MSG(29, (ss, data, ss->gs.recordLen));
if ((ss->gs.recordLen != 1 + SSL_CHALLENGE_BYTES) ||
- (data[0] != SSL_MT_SERVER_VERIFY) ||
- NSS_SecureMemcmp(data+1, ss->sec.ci.clientChallenge,
- SSL_CHALLENGE_BYTES)) {
- /* Bad server */
- PORT_SetError(SSL_ERROR_BAD_SERVER);
- goto loser;
+ (data[0] != SSL_MT_SERVER_VERIFY) ||
+ NSS_SecureMemcmp(data + 1, ss->sec.ci.clientChallenge,
+ SSL_CHALLENGE_BYTES)) {
+ /* Bad server */
+ PORT_SetError(SSL_ERROR_BAD_SERVER);
+ goto loser;
}
ss->sec.ci.elements |= CIS_HAVE_VERIFY;
SSL_TRC(5, ("%d: SSL[%d]: got server-verify, required=0x%d got=0x%x",
- SSL_GETPID(), ss->fd, ss->sec.ci.requiredElements,
- ss->sec.ci.elements));
+ SSL_GETPID(), ss->fd, ss->sec.ci.requiredElements,
+ ss->sec.ci.elements));
rv = ssl2_TryToFinish(ss);
- if (rv)
- goto loser;
+ if (rv)
+ goto loser;
ss->gs.recordLen = 0;
ssl_ReleaseRecvBufLock(ss);
if (ss->handshake == 0) {
- return SECSuccess;
+ return SECSuccess;
}
- ss->handshake = ssl_GatherRecord1stHandshake;
- ss->nextHandshake = ssl2_HandleMessage;
+ ss->handshake = ssl_GatherRecord1stHandshake;
+ ss->nextHandshake = ssl2_HandleMessage;
return SECSuccess;
-
- loser:
+loser:
ssl_ReleaseRecvBufLock(ss);
return SECFailure;
}
/* Not static because ssl2_GatherData() tests ss->nextHandshake for this value.
- * ICK!
+ * ICK!
* Called from ssl_Do1stHandshake after ssl2_BeginClientHandshake()
*/
SECStatus
ssl2_HandleServerHelloMessage(sslSocket *ss)
{
- sslSessionID * sid;
- PRUint8 * cert;
- PRUint8 * cs;
- PRUint8 * data;
- SECStatus rv;
+ sslSessionID *sid;
+ PRUint8 *cert;
+ PRUint8 *cs;
+ PRUint8 *data;
+ SECStatus rv;
unsigned int needed, sidHit, certLen, csLen, cidLen, certType, err;
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
if (!ss->opt.enableSSL2) {
- PORT_SetError(SSL_ERROR_SSL2_DISABLED);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_SSL2_DISABLED);
+ return SECFailure;
}
ssl_GetRecvBufLock(ss);
@@ -2744,51 +2746,51 @@ ssl2_HandleServerHelloMessage(sslSocket *ss)
DUMP_MSG(29, (ss, data, ss->gs.recordLen));
/* Make sure first message has some data and is the server hello message */
- if ((ss->gs.recordLen < SSL_HL_SERVER_HELLO_HBYTES)
- || (data[0] != SSL_MT_SERVER_HELLO)) {
- if ((data[0] == SSL_MT_ERROR) && (ss->gs.recordLen == 3)) {
- err = (data[1] << 8) | data[2];
- if (err == SSL_PE_NO_CYPHERS) {
- PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
- goto loser;
- }
- }
- goto bad_server;
- }
-
- sidHit = data[1];
- certType = data[2];
+ if ((ss->gs.recordLen < SSL_HL_SERVER_HELLO_HBYTES) ||
+ (data[0] != SSL_MT_SERVER_HELLO)) {
+ if ((data[0] == SSL_MT_ERROR) && (ss->gs.recordLen == 3)) {
+ err = (data[1] << 8) | data[2];
+ if (err == SSL_PE_NO_CYPHERS) {
+ PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
+ goto loser;
+ }
+ }
+ goto bad_server;
+ }
+
+ sidHit = data[1];
+ certType = data[2];
ss->version = (data[3] << 8) | data[4];
- certLen = (data[5] << 8) | data[6];
- csLen = (data[7] << 8) | data[8];
- cidLen = (data[9] << 8) | data[10];
- cert = data + SSL_HL_SERVER_HELLO_HBYTES;
- cs = cert + certLen;
+ certLen = (data[5] << 8) | data[6];
+ csLen = (data[7] << 8) | data[8];
+ cidLen = (data[9] << 8) | data[10];
+ cert = data + SSL_HL_SERVER_HELLO_HBYTES;
+ cs = cert + certLen;
SSL_TRC(5,
- ("%d: SSL[%d]: server-hello, hit=%d vers=%x certLen=%d csLen=%d cidLen=%d",
- SSL_GETPID(), ss->fd, sidHit, ss->version, certLen,
- csLen, cidLen));
+ ("%d: SSL[%d]: server-hello, hit=%d vers=%x certLen=%d csLen=%d cidLen=%d",
+ SSL_GETPID(), ss->fd, sidHit, ss->version, certLen,
+ csLen, cidLen));
if (ss->version != SSL_LIBRARY_VERSION_2) {
if (ss->version < SSL_LIBRARY_VERSION_2) {
- SSL_TRC(3, ("%d: SSL[%d]: demoting self (%x) to server version (%x)",
- SSL_GETPID(), ss->fd, SSL_LIBRARY_VERSION_2,
- ss->version));
- } else {
- SSL_TRC(1, ("%d: SSL[%d]: server version is %x (we are %x)",
- SSL_GETPID(), ss->fd, ss->version, SSL_LIBRARY_VERSION_2));
- /* server claims to be newer but does not follow protocol */
- PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
- goto loser;
- }
- }
-
- if ((SSL_HL_SERVER_HELLO_HBYTES + certLen + csLen + cidLen
- > ss->gs.recordLen)
- || (csLen % 3) != 0
- /* || cidLen < SSL_CONNECTIONID_BYTES || cidLen > 32 */
- ) {
- goto bad_server;
+ SSL_TRC(3, ("%d: SSL[%d]: demoting self (%x) to server version (%x)",
+ SSL_GETPID(), ss->fd, SSL_LIBRARY_VERSION_2,
+ ss->version));
+ } else {
+ SSL_TRC(1, ("%d: SSL[%d]: server version is %x (we are %x)",
+ SSL_GETPID(), ss->fd, ss->version, SSL_LIBRARY_VERSION_2));
+ /* server claims to be newer but does not follow protocol */
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
+ goto loser;
+ }
+ }
+
+ if ((SSL_HL_SERVER_HELLO_HBYTES + certLen + csLen + cidLen >
+ ss->gs.recordLen) ||
+ (csLen % 3) != 0
+ /* || cidLen < SSL_CONNECTIONID_BYTES || cidLen > 32 */
+ ) {
+ goto bad_server;
}
/* Save connection-id.
@@ -2796,117 +2798,118 @@ ssl2_HandleServerHelloMessage(sslSocket *ss)
** If the connectionID is shorter than 16 bytes, it is zero-padded.
*/
if (cidLen < sizeof ss->sec.ci.connectionID)
- memset(ss->sec.ci.connectionID, 0, sizeof ss->sec.ci.connectionID);
+ memset(ss->sec.ci.connectionID, 0, sizeof ss->sec.ci.connectionID);
cidLen = PR_MIN(cidLen, sizeof ss->sec.ci.connectionID);
PORT_Memcpy(ss->sec.ci.connectionID, cs + csLen, cidLen);
/* See if session-id hit */
needed = CIS_HAVE_MASTER_KEY | CIS_HAVE_FINISHED | CIS_HAVE_VERIFY;
if (sidHit) {
- if (certLen || csLen) {
- /* Uh oh - bogus server */
- SSL_DBG(("%d: SSL[%d]: client, huh? hit=%d certLen=%d csLen=%d",
- SSL_GETPID(), ss->fd, sidHit, certLen, csLen));
- goto bad_server;
- }
-
- /* Total winner. */
- SSL_TRC(1, ("%d: SSL[%d]: client, using nonce for peer=0x%08x "
- "port=0x%04x",
- SSL_GETPID(), ss->fd, ss->sec.ci.peer, ss->sec.ci.port));
- ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
+ if (certLen || csLen) {
+ /* Uh oh - bogus server */
+ SSL_DBG(("%d: SSL[%d]: client, huh? hit=%d certLen=%d csLen=%d",
+ SSL_GETPID(), ss->fd, sidHit, certLen, csLen));
+ goto bad_server;
+ }
+
+ /* Total winner. */
+ SSL_TRC(1, ("%d: SSL[%d]: client, using nonce for peer=0x%08x "
+ "port=0x%04x",
+ SSL_GETPID(), ss->fd, ss->sec.ci.peer, ss->sec.ci.port));
+ ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
ss->sec.authAlgorithm = sid->authAlgorithm;
- ss->sec.authKeyBits = sid->authKeyBits;
- ss->sec.keaType = sid->keaType;
- ss->sec.keaKeyBits = sid->keaKeyBits;
- rv = ssl2_CreateSessionCypher(ss, sid, PR_TRUE);
- if (rv != SECSuccess) {
- goto loser;
- }
+ ss->sec.authKeyBits = sid->authKeyBits;
+ ss->sec.keaType = sid->keaType;
+ ss->sec.keaKeyBits = sid->keaKeyBits;
+ rv = ssl2_CreateSessionCypher(ss, sid, PR_TRUE);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
} else {
- if (certType != SSL_CT_X509_CERTIFICATE) {
- PORT_SetError(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
- goto loser;
- }
- if (csLen == 0) {
- PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
- SSL_DBG(("%d: SSL[%d]: no cipher overlap",
- SSL_GETPID(), ss->fd));
- goto loser;
- }
- if (certLen == 0) {
- SSL_DBG(("%d: SSL[%d]: client, huh? certLen=%d csLen=%d",
- SSL_GETPID(), ss->fd, certLen, csLen));
- goto bad_server;
- }
-
- if (sid->cached != never_cached) {
- /* Forget our session-id - server didn't like it */
- SSL_TRC(7, ("%d: SSL[%d]: server forgot me, uncaching session-id",
- SSL_GETPID(), ss->fd));
- if (ss->sec.uncache)
- (*ss->sec.uncache)(sid);
- ssl_FreeSID(sid);
- ss->sec.ci.sid = sid = PORT_ZNew(sslSessionID);
- if (!sid) {
- goto loser;
- }
- sid->references = 1;
- sid->addr = ss->sec.ci.peer;
- sid->port = ss->sec.ci.port;
- }
-
- /* decode the server's certificate */
- rv = ssl2_ClientHandleServerCert(ss, cert, certLen);
- if (rv != SECSuccess) {
- if (PORT_GetError() == SSL_ERROR_BAD_CERTIFICATE) {
- (void) ssl2_SendErrorMessage(ss, SSL_PE_BAD_CERTIFICATE);
- }
- goto loser;
- }
-
- /* Setup new session cipher */
- rv = ssl2_ClientSetupSessionCypher(ss, cs, csLen);
- if (rv != SECSuccess) {
- if (PORT_GetError() == SSL_ERROR_BAD_CERTIFICATE) {
- (void) ssl2_SendErrorMessage(ss, SSL_PE_BAD_CERTIFICATE);
- }
- goto loser;
- }
+ if (certType != SSL_CT_X509_CERTIFICATE) {
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
+ goto loser;
+ }
+ if (csLen == 0) {
+ PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
+ SSL_DBG(("%d: SSL[%d]: no cipher overlap",
+ SSL_GETPID(), ss->fd));
+ goto loser;
+ }
+ if (certLen == 0) {
+ SSL_DBG(("%d: SSL[%d]: client, huh? certLen=%d csLen=%d",
+ SSL_GETPID(), ss->fd, certLen, csLen));
+ goto bad_server;
+ }
+
+ if (sid->cached != never_cached) {
+ /* Forget our session-id - server didn't like it */
+ SSL_TRC(7, ("%d: SSL[%d]: server forgot me, uncaching session-id",
+ SSL_GETPID(), ss->fd));
+ if (ss->sec.uncache)
+ (*ss->sec.uncache)(sid);
+ ssl_FreeSID(sid);
+ ss->sec.ci.sid = sid = PORT_ZNew(sslSessionID);
+ if (!sid) {
+ goto loser;
+ }
+ sid->references = 1;
+ sid->addr = ss->sec.ci.peer;
+ sid->port = ss->sec.ci.port;
+ }
+
+ /* decode the server's certificate */
+ rv = ssl2_ClientHandleServerCert(ss, cert, certLen);
+ if (rv != SECSuccess) {
+ if (PORT_GetError() == SSL_ERROR_BAD_CERTIFICATE) {
+ (void)ssl2_SendErrorMessage(ss, SSL_PE_BAD_CERTIFICATE);
+ }
+ goto loser;
+ }
+
+ /* Setup new session cipher */
+ rv = ssl2_ClientSetupSessionCypher(ss, cs, csLen);
+ if (rv != SECSuccess) {
+ if (PORT_GetError() == SSL_ERROR_BAD_CERTIFICATE) {
+ (void)ssl2_SendErrorMessage(ss, SSL_PE_BAD_CERTIFICATE);
+ }
+ goto loser;
+ }
}
/* Build up final list of required elements */
- ss->sec.ci.elements = CIS_HAVE_MASTER_KEY;
+ ss->sec.ci.elements = CIS_HAVE_MASTER_KEY;
ss->sec.ci.requiredElements = needed;
- if (!sidHit) {
- /* verify the server's certificate. if sidHit, don't check signatures */
- rv = (* ss->authCertificate)(ss->authCertificateArg, ss->fd,
- (PRBool)(!sidHit), PR_FALSE);
- if (rv) {
- if (ss->handleBadCert) {
- rv = (*ss->handleBadCert)(ss->badCertArg, ss->fd);
- if ( rv ) {
- if ( rv == SECWouldBlock ) {
- SSL_DBG(("%d: SSL[%d]: SSL2 bad cert handler returned "
- "SECWouldBlock", SSL_GETPID(), ss->fd));
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
- rv = SECFailure;
- } else {
- /* cert is bad */
- SSL_DBG(("%d: SSL[%d]: server certificate is no good: error=%d",
- SSL_GETPID(), ss->fd, PORT_GetError()));
- }
- goto loser;
- }
- /* cert is good */
- } else {
- SSL_DBG(("%d: SSL[%d]: server certificate is no good: error=%d",
- SSL_GETPID(), ss->fd, PORT_GetError()));
- goto loser;
- }
- }
- }
+ if (!sidHit) {
+ /* verify the server's certificate. if sidHit, don't check signatures */
+ rv = (*ss->authCertificate)(ss->authCertificateArg, ss->fd,
+ (PRBool)(!sidHit), PR_FALSE);
+ if (rv) {
+ if (ss->handleBadCert) {
+ rv = (*ss->handleBadCert)(ss->badCertArg, ss->fd);
+ if (rv) {
+ if (rv == SECWouldBlock) {
+ SSL_DBG(("%d: SSL[%d]: SSL2 bad cert handler returned "
+ "SECWouldBlock",
+ SSL_GETPID(), ss->fd));
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
+ rv = SECFailure;
+ } else {
+ /* cert is bad */
+ SSL_DBG(("%d: SSL[%d]: server certificate is no good: error=%d",
+ SSL_GETPID(), ss->fd, PORT_GetError()));
+ }
+ goto loser;
+ }
+ /* cert is good */
+ } else {
+ SSL_DBG(("%d: SSL[%d]: server certificate is no good: error=%d",
+ SSL_GETPID(), ss->fd, PORT_GetError()));
+ goto loser;
+ }
+ }
+ }
/*
** At this point we have a completed session key and our session
** cipher is setup and ready to go. Switch to encrypted write routine
@@ -2915,29 +2918,29 @@ ssl2_HandleServerHelloMessage(sslSocket *ss)
ssl2_UseEncryptedSendFunc(ss);
rv = ssl2_TryToFinish(ss);
- if (rv != SECSuccess)
- goto loser;
+ if (rv != SECSuccess)
+ goto loser;
ss->gs.recordLen = 0;
ssl_ReleaseRecvBufLock(ss);
if (ss->handshake == 0) {
- return SECSuccess;
+ return SECSuccess;
}
SSL_TRC(5, ("%d: SSL[%d]: got server-hello, required=0x%d got=0x%x",
- SSL_GETPID(), ss->fd, ss->sec.ci.requiredElements,
- ss->sec.ci.elements));
- ss->handshake = ssl_GatherRecord1stHandshake;
+ SSL_GETPID(), ss->fd, ss->sec.ci.requiredElements,
+ ss->sec.ci.elements));
+ ss->handshake = ssl_GatherRecord1stHandshake;
ss->nextHandshake = ssl2_HandleVerifyMessage;
return SECSuccess;
- bad_server:
+bad_server:
PORT_SetError(SSL_ERROR_BAD_SERVER);
- /* FALL THROUGH */
+/* FALL THROUGH */
- loser:
+loser:
ssl_ReleaseRecvBufLock(ss);
return SECFailure;
}
@@ -2948,27 +2951,27 @@ ssl2_HandleServerHelloMessage(sslSocket *ss)
SECStatus
ssl2_BeginClientHandshake(sslSocket *ss)
{
- sslSessionID *sid;
- PRUint8 *msg;
- PRUint8 *cp;
- PRUint8 *localCipherSpecs = NULL;
- unsigned int localCipherSize;
- unsigned int i;
- int sendLen, sidLen = 0;
- SECStatus rv;
- TLSExtensionData *xtnData;
-
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
-
- ss->sec.isServer = 0;
+ sslSessionID *sid;
+ PRUint8 *msg;
+ PRUint8 *cp;
+ PRUint8 *localCipherSpecs = NULL;
+ unsigned int localCipherSize;
+ unsigned int i;
+ int sendLen, sidLen = 0;
+ SECStatus rv;
+ TLSExtensionData *xtnData;
+
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
+
+ ss->sec.isServer = 0;
ss->sec.sendSequence = 0;
- ss->sec.rcvSequence = 0;
+ ss->sec.rcvSequence = 0;
ssl_ChooseSessionIDProcs(&ss->sec);
if (!ss->cipherSpecs) {
- rv = ssl2_ConstructCipherSpecs(ss);
- if (rv != SECSuccess)
- goto loser;
+ rv = ssl2_ConstructCipherSpecs(ss);
+ if (rv != SECSuccess)
+ goto loser;
}
/* count the SSL2 and SSL3 enabled ciphers.
@@ -2976,7 +2979,7 @@ ssl2_BeginClientHandshake(sslSocket *ss)
*/
rv = ssl2_CheckConfigSanity(ss);
if (rv != SECSuccess)
- goto loser;
+ goto loser;
/* Get peer name of server */
rv = ssl_GetPeerInfo(ss);
@@ -2990,14 +2993,14 @@ ssl2_BeginClientHandshake(sslSocket *ss)
*/
if (PR_GetError() == PR_NOT_CONNECTED_ERROR) {
char dummy;
- (void) PR_Write(ss->fd->lower, &dummy, 0);
+ (void)PR_Write(ss->fd->lower, &dummy, 0);
rv = ssl_GetPeerInfo(ss);
if (rv < 0) {
goto loser;
}
}
#else
- goto loser;
+ goto loser;
#endif
}
@@ -3005,125 +3008,125 @@ ssl2_BeginClientHandshake(sslSocket *ss)
/* Try to find server in our session-id cache */
if (ss->opt.noCache) {
- sid = NULL;
+ sid = NULL;
} else {
- sid = ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID,
- ss->url);
- }
- while (sid) { /* this isn't really a loop */
- PRBool sidVersionEnabled =
- (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange) &&
- sid->version >= ss->vrange.min &&
- sid->version <= ss->vrange.max) ||
- (sid->version < SSL_LIBRARY_VERSION_3_0 && ss->opt.enableSSL2);
-
- /* if we're not doing this SID's protocol any more, drop it. */
- if (!sidVersionEnabled) {
- if (ss->sec.uncache)
- ss->sec.uncache(sid);
- ssl_FreeSID(sid);
- sid = NULL;
- break;
- }
- if (sid->version < SSL_LIBRARY_VERSION_3_0) {
- /* If the cipher in this sid is not enabled, drop it. */
- for (i = 0; i < ss->sizeCipherSpecs; i += 3) {
- if (ss->cipherSpecs[i] == sid->u.ssl2.cipherType)
- break;
- }
- if (i >= ss->sizeCipherSpecs) {
- if (ss->sec.uncache)
- ss->sec.uncache(sid);
- ssl_FreeSID(sid);
- sid = NULL;
- break;
- }
- }
- sidLen = sizeof(sid->u.ssl2.sessionID);
- PRINT_BUF(4, (ss, "client, found session-id:", sid->u.ssl2.sessionID,
- sidLen));
- ss->version = sid->version;
- PORT_Assert(!ss->sec.localCert);
- if (ss->sec.localCert) {
- CERT_DestroyCertificate(ss->sec.localCert);
- }
- ss->sec.localCert = CERT_DupCertificate(sid->localCert);
- break; /* this isn't really a loop */
- }
+ sid = ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID,
+ ss->url);
+ }
+ while (sid) { /* this isn't really a loop */
+ PRBool sidVersionEnabled =
+ (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange) &&
+ sid->version >= ss->vrange.min &&
+ sid->version <= ss->vrange.max) ||
+ (sid->version < SSL_LIBRARY_VERSION_3_0 && ss->opt.enableSSL2);
+
+ /* if we're not doing this SID's protocol any more, drop it. */
+ if (!sidVersionEnabled) {
+ if (ss->sec.uncache)
+ ss->sec.uncache(sid);
+ ssl_FreeSID(sid);
+ sid = NULL;
+ break;
+ }
+ if (sid->version < SSL_LIBRARY_VERSION_3_0) {
+ /* If the cipher in this sid is not enabled, drop it. */
+ for (i = 0; i < ss->sizeCipherSpecs; i += 3) {
+ if (ss->cipherSpecs[i] == sid->u.ssl2.cipherType)
+ break;
+ }
+ if (i >= ss->sizeCipherSpecs) {
+ if (ss->sec.uncache)
+ ss->sec.uncache(sid);
+ ssl_FreeSID(sid);
+ sid = NULL;
+ break;
+ }
+ }
+ sidLen = sizeof(sid->u.ssl2.sessionID);
+ PRINT_BUF(4, (ss, "client, found session-id:", sid->u.ssl2.sessionID,
+ sidLen));
+ ss->version = sid->version;
+ PORT_Assert(!ss->sec.localCert);
+ if (ss->sec.localCert) {
+ CERT_DestroyCertificate(ss->sec.localCert);
+ }
+ ss->sec.localCert = CERT_DupCertificate(sid->localCert);
+ break; /* this isn't really a loop */
+ }
if (!sid) {
- sidLen = 0;
- sid = PORT_ZNew(sslSessionID);
- if (!sid) {
- goto loser;
- }
- sid->references = 1;
- sid->cached = never_cached;
- sid->addr = ss->sec.ci.peer;
- sid->port = ss->sec.ci.port;
- if (ss->peerID != NULL) {
- sid->peerID = PORT_Strdup(ss->peerID);
- }
- if (ss->url != NULL) {
- sid->urlSvrName = PORT_Strdup(ss->url);
- }
+ sidLen = 0;
+ sid = PORT_ZNew(sslSessionID);
+ if (!sid) {
+ goto loser;
+ }
+ sid->references = 1;
+ sid->cached = never_cached;
+ sid->addr = ss->sec.ci.peer;
+ sid->port = ss->sec.ci.port;
+ if (ss->peerID != NULL) {
+ sid->peerID = PORT_Strdup(ss->peerID);
+ }
+ if (ss->url != NULL) {
+ sid->urlSvrName = PORT_Strdup(ss->url);
+ }
}
ss->sec.ci.sid = sid;
PORT_Assert(sid != NULL);
if ((sid->version >= SSL_LIBRARY_VERSION_3_0 || !ss->opt.v2CompatibleHello) &&
- !SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
- ss->gs.state = GS_INIT;
- ss->handshake = ssl_GatherRecord1stHandshake;
+ !SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
+ ss->gs.state = GS_INIT;
+ ss->handshake = ssl_GatherRecord1stHandshake;
- /* ssl3_SendClientHello will override this if it succeeds. */
- ss->version = SSL_LIBRARY_VERSION_3_0;
+ /* ssl3_SendClientHello will override this if it succeeds. */
+ ss->version = SSL_LIBRARY_VERSION_3_0;
- ssl_GetSSL3HandshakeLock(ss);
- ssl_GetXmitBufLock(ss);
- rv = ssl3_SendClientHello(ss, PR_FALSE);
- ssl_ReleaseXmitBufLock(ss);
- ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+ ssl_GetXmitBufLock(ss);
+ rv = ssl3_SendClientHello(ss, PR_FALSE);
+ ssl_ReleaseXmitBufLock(ss);
+ ssl_ReleaseSSL3HandshakeLock(ss);
- return rv;
+ return rv;
}
#ifndef NSS_DISABLE_ECC
/* ensure we don't neogtiate ECC cipher suites with SSL2 hello */
ssl3_DisableECCSuites(ss, NULL); /* disable all ECC suites */
if (ss->cipherSpecs != NULL) {
- PORT_Free(ss->cipherSpecs);
- ss->cipherSpecs = NULL;
- ss->sizeCipherSpecs = 0;
+ PORT_Free(ss->cipherSpecs);
+ ss->cipherSpecs = NULL;
+ ss->sizeCipherSpecs = 0;
}
#endif /* NSS_DISABLE_ECC */
if (!ss->cipherSpecs) {
rv = ssl2_ConstructCipherSpecs(ss);
- if (rv < 0) {
- return rv;
- }
+ if (rv < 0) {
+ return rv;
+ }
}
localCipherSpecs = ss->cipherSpecs;
- localCipherSize = ss->sizeCipherSpecs;
+ localCipherSize = ss->sizeCipherSpecs;
/* Add 3 for SCSV */
sendLen = SSL_HL_CLIENT_HELLO_HBYTES + localCipherSize + 3 + sidLen +
- SSL_CHALLENGE_BYTES;
+ SSL_CHALLENGE_BYTES;
/* Generate challenge bytes for server */
PK11_GenerateRandom(ss->sec.ci.clientChallenge, SSL_CHALLENGE_BYTES);
- ssl_GetXmitBufLock(ss); /***************************************/
+ ssl_GetXmitBufLock(ss); /***************************************/
rv = ssl2_GetSendBuffer(ss, sendLen);
- if (rv)
- goto unlock_loser;
+ if (rv)
+ goto unlock_loser;
/* Construct client-hello message */
cp = msg = ss->sec.ci.sendBuf.buf;
msg[0] = SSL_MT_CLIENT_HELLO;
- ss->clientHelloVersion = SSL3_ALL_VERSIONS_DISABLED(&ss->vrange) ?
- SSL_LIBRARY_VERSION_2 : ss->vrange.max;
+ ss->clientHelloVersion = SSL3_ALL_VERSIONS_DISABLED(&ss->vrange) ? SSL_LIBRARY_VERSION_2
+ : ss->vrange.max;
msg[1] = MSB(ss->clientHelloVersion);
msg[2] = LSB(ss->clientHelloVersion);
@@ -3148,8 +3151,8 @@ ssl2_BeginClientHandshake(sslSocket *ss)
cp[2] = 0xff;
cp += 3;
if (sidLen) {
- PORT_Memcpy(cp, sid->u.ssl2.sessionID, sidLen);
- cp += sidLen;
+ PORT_Memcpy(cp, sid->u.ssl2.sessionID, sidLen);
+ cp += sidLen;
}
PORT_Memcpy(cp, ss->sec.ci.clientChallenge, SSL_CHALLENGE_BYTES);
@@ -3158,15 +3161,15 @@ ssl2_BeginClientHandshake(sslSocket *ss)
ss->handshakeBegun = 1;
rv = (*ss->sec.send)(ss, msg, sendLen, 0);
- ssl_ReleaseXmitBufLock(ss); /***************************************/
+ ssl_ReleaseXmitBufLock(ss); /***************************************/
if (rv < 0) {
- goto loser;
+ goto loser;
}
rv = ssl3_StartHandshakeHash(ss, msg, sendLen);
if (rv < 0) {
- goto loser;
+ goto loser;
}
/*
@@ -3182,7 +3185,7 @@ ssl2_BeginClientHandshake(sslSocket *ss)
ss->gs.recordLen = 0;
ssl_ReleaseRecvBufLock(ss);
- ss->handshake = ssl_GatherRecord1stHandshake;
+ ss->handshake = ssl_GatherRecord1stHandshake;
ss->nextHandshake = ssl2_HandleServerHelloMessage;
return SECSuccess;
@@ -3194,86 +3197,88 @@ loser:
/************************************************************************/
-/* Handle the CLIENT-MASTER-KEY message.
+/* Handle the CLIENT-MASTER-KEY message.
** Acquires and releases RecvBufLock.
-** Called from ssl2_HandleClientHelloMessage().
+** Called from ssl2_HandleClientHelloMessage().
*/
static SECStatus
ssl2_HandleClientSessionKeyMessage(sslSocket *ss)
{
- PRUint8 * data;
- unsigned int caLen;
- unsigned int ckLen;
- unsigned int ekLen;
- unsigned int keyBits;
- int cipher;
- SECStatus rv;
-
+ PRUint8 *data;
+ unsigned int caLen;
+ unsigned int ckLen;
+ unsigned int ekLen;
+ unsigned int keyBits;
+ int cipher;
+ SECStatus rv;
ssl_GetRecvBufLock(ss);
data = ss->gs.buf.buf + ss->gs.recordOffset;
DUMP_MSG(29, (ss, data, ss->gs.recordLen));
- if ((ss->gs.recordLen < SSL_HL_CLIENT_MASTER_KEY_HBYTES)
- || (data[0] != SSL_MT_CLIENT_MASTER_KEY)) {
- goto bad_client;
+ if ((ss->gs.recordLen < SSL_HL_CLIENT_MASTER_KEY_HBYTES) ||
+ (data[0] != SSL_MT_CLIENT_MASTER_KEY)) {
+ goto bad_client;
}
- cipher = data[1];
+ cipher = data[1];
keyBits = (data[2] << 8) | data[3];
- ckLen = (data[4] << 8) | data[5];
- ekLen = (data[6] << 8) | data[7];
- caLen = (data[8] << 8) | data[9];
+ ckLen = (data[4] << 8) | data[5];
+ ekLen = (data[6] << 8) | data[7];
+ caLen = (data[8] << 8) | data[9];
SSL_TRC(5, ("%d: SSL[%d]: session-key, cipher=%d keyBits=%d ckLen=%d ekLen=%d caLen=%d",
- SSL_GETPID(), ss->fd, cipher, keyBits, ckLen, ekLen, caLen));
+ SSL_GETPID(), ss->fd, cipher, keyBits, ckLen, ekLen, caLen));
- if (ss->gs.recordLen <
- SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen + caLen) {
- SSL_DBG(("%d: SSL[%d]: protocol size mismatch dataLen=%d",
- SSL_GETPID(), ss->fd, ss->gs.recordLen));
- goto bad_client;
+ if (ss->gs.recordLen <
+ SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen + caLen) {
+ SSL_DBG(("%d: SSL[%d]: protocol size mismatch dataLen=%d",
+ SSL_GETPID(), ss->fd, ss->gs.recordLen));
+ goto bad_client;
}
/* Use info from client to setup session key */
rv = ssl2_ServerSetupSessionCypher(ss, cipher, keyBits,
- data + SSL_HL_CLIENT_MASTER_KEY_HBYTES, ckLen,
- data + SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen, ekLen,
- data + SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen, caLen);
- ss->gs.recordLen = 0; /* we're done with this record. */
+ data + SSL_HL_CLIENT_MASTER_KEY_HBYTES,
+ ckLen,
+ data + SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen,
+ ekLen,
+ data + SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen,
+ caLen);
+ ss->gs.recordLen = 0; /* we're done with this record. */
ssl_ReleaseRecvBufLock(ss);
if (rv != SECSuccess) {
- goto loser;
+ goto loser;
}
ss->sec.ci.elements |= CIS_HAVE_MASTER_KEY;
ssl2_UseEncryptedSendFunc(ss);
/* Send server verify message now that keys are established */
rv = ssl2_SendServerVerifyMessage(ss);
- if (rv != SECSuccess)
- goto loser;
+ if (rv != SECSuccess)
+ goto loser;
rv = ssl2_TryToFinish(ss);
- if (rv != SECSuccess)
- goto loser;
+ if (rv != SECSuccess)
+ goto loser;
if (ss->handshake == 0) {
- return SECSuccess;
+ return SECSuccess;
}
SSL_TRC(5, ("%d: SSL[%d]: server: waiting for elements=0x%d",
- SSL_GETPID(), ss->fd,
- ss->sec.ci.requiredElements ^ ss->sec.ci.elements));
- ss->handshake = ssl_GatherRecord1stHandshake;
- ss->nextHandshake = ssl2_HandleMessage;
+ SSL_GETPID(), ss->fd,
+ ss->sec.ci.requiredElements ^ ss->sec.ci.elements));
+ ss->handshake = ssl_GatherRecord1stHandshake;
+ ss->nextHandshake = ssl2_HandleMessage;
return ssl2_TriggerNextMessage(ss);
bad_client:
ssl_ReleaseRecvBufLock(ss);
PORT_SetError(SSL_ERROR_BAD_CLIENT);
- /* FALLTHROUGH */
+/* FALLTHROUGH */
loser:
return SECFailure;
@@ -3287,75 +3292,74 @@ loser:
SECStatus
ssl2_HandleClientHelloMessage(sslSocket *ss)
{
- sslSessionID *sid;
- sslServerCerts * sc;
+ sslSessionID *sid;
+ sslServerCerts *sc;
CERTCertificate *serverCert;
- PRUint8 *msg;
- PRUint8 *data;
- PRUint8 *cs;
- PRUint8 *sd;
- PRUint8 *cert = NULL;
- PRUint8 *challenge;
- unsigned int challengeLen;
- SECStatus rv;
- int csLen;
- int sendLen;
- int sdLen;
- int certLen;
- int pid;
- int sent;
- int gotXmitBufLock = 0;
+ PRUint8 *msg;
+ PRUint8 *data;
+ PRUint8 *cs;
+ PRUint8 *sd;
+ PRUint8 *cert = NULL;
+ PRUint8 *challenge;
+ unsigned int challengeLen;
+ SECStatus rv;
+ int csLen;
+ int sendLen;
+ int sdLen;
+ int certLen;
+ int pid;
+ int sent;
+ int gotXmitBufLock = 0;
#if defined(SOLARIS) && defined(i386)
volatile PRUint8 hit;
#else
- int hit;
+ int hit;
#endif
- PRUint8 csImpl[sizeof implementedCipherSuites];
+ PRUint8 csImpl[sizeof implementedCipherSuites];
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
sc = ss->serverCerts + kt_rsa;
serverCert = sc->serverCert;
ssl_GetRecvBufLock(ss);
-
data = ss->gs.buf.buf + ss->gs.recordOffset;
DUMP_MSG(29, (ss, data, ss->gs.recordLen));
/* Make sure first message has some data and is the client hello message */
- if ((ss->gs.recordLen < SSL_HL_CLIENT_HELLO_HBYTES)
- || (data[0] != SSL_MT_CLIENT_HELLO)) {
- goto bad_client;
+ if ((ss->gs.recordLen < SSL_HL_CLIENT_HELLO_HBYTES) ||
+ (data[0] != SSL_MT_CLIENT_HELLO)) {
+ goto bad_client;
}
/* Get peer name of client */
rv = ssl_GetPeerInfo(ss);
if (rv != SECSuccess) {
- goto loser;
+ goto loser;
}
/* Examine version information */
/*
* See if this might be a V2 client hello asking to use the V3 protocol
*/
- if ((data[0] == SSL_MT_CLIENT_HELLO) &&
- (data[1] >= MSB(SSL_LIBRARY_VERSION_3_0)) &&
- !SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
- rv = ssl3_HandleV2ClientHello(ss, data, ss->gs.recordLen);
- if (rv != SECFailure) { /* Success */
- ss->handshake = NULL;
- ss->nextHandshake = ssl_GatherRecord1stHandshake;
- ss->securityHandshake = NULL;
- ss->gs.state = GS_INIT;
-
- /* ssl3_HandleV3ClientHello has set ss->version,
- ** and has gotten us a brand new sid.
- */
- ss->sec.ci.sid->version = ss->version;
- }
- ssl_ReleaseRecvBufLock(ss);
- return rv;
+ if ((data[0] == SSL_MT_CLIENT_HELLO) &&
+ (data[1] >= MSB(SSL_LIBRARY_VERSION_3_0)) &&
+ !SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
+ rv = ssl3_HandleV2ClientHello(ss, data, ss->gs.recordLen);
+ if (rv != SECFailure) { /* Success */
+ ss->handshake = NULL;
+ ss->nextHandshake = ssl_GatherRecord1stHandshake;
+ ss->securityHandshake = NULL;
+ ss->gs.state = GS_INIT;
+
+ /* ssl3_HandleV3ClientHello has set ss->version,
+ ** and has gotten us a brand new sid.
+ */
+ ss->sec.ci.sid->version = ss->version;
+ }
+ ssl_ReleaseRecvBufLock(ss);
+ return rv;
}
/* Previously, there was a test here to see if SSL2 was enabled.
** If not, an error code was set, and SECFailure was returned,
@@ -3372,64 +3376,64 @@ ssl2_HandleClientHelloMessage(sslSocket *ss)
/* If some client thinks ssl v2 is 2.0 instead of 0.2, we'll allow it. */
if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
- ss->version = SSL_LIBRARY_VERSION_2;
+ ss->version = SSL_LIBRARY_VERSION_2;
}
-
- csLen = (data[3] << 8) | data[4];
- sdLen = (data[5] << 8) | data[6];
+
+ csLen = (data[3] << 8) | data[4];
+ sdLen = (data[5] << 8) | data[6];
challengeLen = (data[7] << 8) | data[8];
- cs = data + SSL_HL_CLIENT_HELLO_HBYTES;
- sd = cs + csLen;
- challenge = sd + sdLen;
+ cs = data + SSL_HL_CLIENT_HELLO_HBYTES;
+ sd = cs + csLen;
+ challenge = sd + sdLen;
PRINT_BUF(7, (ss, "server, client session-id value:", sd, sdLen));
- if (!csLen || (csLen % 3) != 0 ||
+ if (!csLen || (csLen % 3) != 0 ||
(sdLen != 0 && sdLen != SSL2_SESSIONID_BYTES) ||
- challengeLen < SSL_MIN_CHALLENGE_BYTES ||
- challengeLen > SSL_MAX_CHALLENGE_BYTES ||
- (unsigned)ss->gs.recordLen !=
+ challengeLen < SSL_MIN_CHALLENGE_BYTES ||
+ challengeLen > SSL_MAX_CHALLENGE_BYTES ||
+ (unsigned)ss->gs.recordLen !=
SSL_HL_CLIENT_HELLO_HBYTES + csLen + sdLen + challengeLen) {
- SSL_DBG(("%d: SSL[%d]: bad client hello message, len=%d should=%d",
- SSL_GETPID(), ss->fd, ss->gs.recordLen,
- SSL_HL_CLIENT_HELLO_HBYTES+csLen+sdLen+challengeLen));
- goto bad_client;
+ SSL_DBG(("%d: SSL[%d]: bad client hello message, len=%d should=%d",
+ SSL_GETPID(), ss->fd, ss->gs.recordLen,
+ SSL_HL_CLIENT_HELLO_HBYTES + csLen + sdLen + challengeLen));
+ goto bad_client;
}
SSL_TRC(3, ("%d: SSL[%d]: client version is %x",
- SSL_GETPID(), ss->fd, ss->version));
+ SSL_GETPID(), ss->fd, ss->version));
if (ss->version != SSL_LIBRARY_VERSION_2) {
- if (ss->version > SSL_LIBRARY_VERSION_2) {
- /*
- ** Newer client than us. Things are ok because new clients
- ** are required to be backwards compatible with old servers.
- ** Change version number to our version number so that client
- ** knows whats up.
- */
- ss->version = SSL_LIBRARY_VERSION_2;
- } else {
- SSL_TRC(1, ("%d: SSL[%d]: client version is %x (we are %x)",
- SSL_GETPID(), ss->fd, ss->version, SSL_LIBRARY_VERSION_2));
- PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
- goto loser;
- }
+ if (ss->version > SSL_LIBRARY_VERSION_2) {
+ /*
+ ** Newer client than us. Things are ok because new clients
+ ** are required to be backwards compatible with old servers.
+ ** Change version number to our version number so that client
+ ** knows whats up.
+ */
+ ss->version = SSL_LIBRARY_VERSION_2;
+ } else {
+ SSL_TRC(1, ("%d: SSL[%d]: client version is %x (we are %x)",
+ SSL_GETPID(), ss->fd, ss->version, SSL_LIBRARY_VERSION_2));
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
+ goto loser;
+ }
}
/* Qualify cipher specs before returning them to client */
csLen = ssl2_QualifyCypherSpecs(ss, cs, csLen);
if (csLen == 0) {
- /* no overlap, send client our list of supported SSL v2 ciphers. */
- cs = csImpl;
- csLen = sizeof implementedCipherSuites;
- PORT_Memcpy(cs, implementedCipherSuites, csLen);
- csLen = ssl2_QualifyCypherSpecs(ss, cs, csLen);
- if (csLen == 0) {
- /* We don't support any SSL v2 ciphers! */
- ssl2_SendErrorMessage(ss, SSL_PE_NO_CYPHERS);
- PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
- goto loser;
- }
- /* Since this handhsake is going to fail, don't cache it. */
- ss->opt.noCache = 1;
+ /* no overlap, send client our list of supported SSL v2 ciphers. */
+ cs = csImpl;
+ csLen = sizeof implementedCipherSuites;
+ PORT_Memcpy(cs, implementedCipherSuites, csLen);
+ csLen = ssl2_QualifyCypherSpecs(ss, cs, csLen);
+ if (csLen == 0) {
+ /* We don't support any SSL v2 ciphers! */
+ ssl2_SendErrorMessage(ss, SSL_PE_NO_CYPHERS);
+ PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
+ goto loser;
+ }
+ /* Since this handhsake is going to fail, don't cache it. */
+ ss->opt.noCache = 1;
}
/* Squirrel away the challenge for later */
@@ -3438,104 +3442,105 @@ ssl2_HandleClientHelloMessage(sslSocket *ss)
/* Examine message and see if session-id is good */
ss->sec.ci.elements = 0;
if (sdLen > 0 && !ss->opt.noCache) {
- SSL_TRC(7, ("%d: SSL[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x",
- SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0],
- ss->sec.ci.peer.pr_s6_addr32[1],
- ss->sec.ci.peer.pr_s6_addr32[2],
- ss->sec.ci.peer.pr_s6_addr32[3]));
- sid = (*ssl_sid_lookup)(&ss->sec.ci.peer, sd, sdLen, ss->dbHandle);
+ SSL_TRC(7, ("%d: SSL[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x",
+ SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0],
+ ss->sec.ci.peer.pr_s6_addr32[1],
+ ss->sec.ci.peer.pr_s6_addr32[2],
+ ss->sec.ci.peer.pr_s6_addr32[3]));
+ sid = (*ssl_sid_lookup)(&ss->sec.ci.peer, sd, sdLen, ss->dbHandle);
} else {
- sid = NULL;
+ sid = NULL;
}
if (sid) {
- /* Got a good session-id. Short cut! */
- SSL_TRC(1, ("%d: SSL[%d]: server, using session-id for 0x%08x (age=%d)",
- SSL_GETPID(), ss->fd, ss->sec.ci.peer,
- ssl_Time() - sid->creationTime));
- PRINT_BUF(1, (ss, "session-id value:", sd, sdLen));
- ss->sec.ci.sid = sid;
- ss->sec.ci.elements = CIS_HAVE_MASTER_KEY;
- hit = 1;
- certLen = 0;
- csLen = 0;
+ /* Got a good session-id. Short cut! */
+ SSL_TRC(1, ("%d: SSL[%d]: server, using session-id for 0x%08x (age=%d)",
+ SSL_GETPID(), ss->fd, ss->sec.ci.peer,
+ ssl_Time() - sid->creationTime));
+ PRINT_BUF(1, (ss, "session-id value:", sd, sdLen));
+ ss->sec.ci.sid = sid;
+ ss->sec.ci.elements = CIS_HAVE_MASTER_KEY;
+ hit = 1;
+ certLen = 0;
+ csLen = 0;
ss->sec.authAlgorithm = sid->authAlgorithm;
- ss->sec.authKeyBits = sid->authKeyBits;
- ss->sec.keaType = sid->keaType;
- ss->sec.keaKeyBits = sid->keaKeyBits;
-
- rv = ssl2_CreateSessionCypher(ss, sid, PR_FALSE);
- if (rv != SECSuccess) {
- goto loser;
- }
+ ss->sec.authKeyBits = sid->authKeyBits;
+ ss->sec.keaType = sid->keaType;
+ ss->sec.keaKeyBits = sid->keaKeyBits;
+
+ rv = ssl2_CreateSessionCypher(ss, sid, PR_FALSE);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
} else {
- SECItem * derCert = &serverCert->derCert;
-
- SSL_TRC(7, ("%d: SSL[%d]: server, lookup nonce missed",
- SSL_GETPID(), ss->fd));
- if (!serverCert) {
- SET_ERROR_CODE
- goto loser;
- }
- hit = 0;
- sid = PORT_ZNew(sslSessionID);
- if (!sid) {
- goto loser;
- }
- sid->references = 1;
- sid->addr = ss->sec.ci.peer;
- sid->port = ss->sec.ci.port;
-
- /* Invent a session-id */
- ss->sec.ci.sid = sid;
- PK11_GenerateRandom(sid->u.ssl2.sessionID+2, SSL2_SESSIONID_BYTES-2);
-
- pid = SSL_GETPID();
- sid->u.ssl2.sessionID[0] = MSB(pid);
- sid->u.ssl2.sessionID[1] = LSB(pid);
- cert = derCert->data;
- certLen = derCert->len;
-
- /* pretend that server sids remember the local cert. */
- PORT_Assert(!sid->localCert);
- if (sid->localCert) {
- CERT_DestroyCertificate(sid->localCert);
- }
- sid->localCert = CERT_DupCertificate(serverCert);
-
- ss->sec.authAlgorithm = ssl_sign_rsa;
- ss->sec.keaType = ssl_kea_rsa;
- ss->sec.keaKeyBits = \
- ss->sec.authKeyBits = ss->serverCerts[kt_rsa].serverKeyBits;
+ SECItem *derCert = &serverCert->derCert;
+
+ SSL_TRC(7, ("%d: SSL[%d]: server, lookup nonce missed",
+ SSL_GETPID(), ss->fd));
+ if (!serverCert) {
+ SET_ERROR_CODE
+ goto loser;
+ }
+ hit = 0;
+ sid = PORT_ZNew(sslSessionID);
+ if (!sid) {
+ goto loser;
+ }
+ sid->references = 1;
+ sid->addr = ss->sec.ci.peer;
+ sid->port = ss->sec.ci.port;
+
+ /* Invent a session-id */
+ ss->sec.ci.sid = sid;
+ PK11_GenerateRandom(sid->u.ssl2.sessionID + 2, SSL2_SESSIONID_BYTES - 2);
+
+ pid = SSL_GETPID();
+ sid->u.ssl2.sessionID[0] = MSB(pid);
+ sid->u.ssl2.sessionID[1] = LSB(pid);
+ cert = derCert->data;
+ certLen = derCert->len;
+
+ /* pretend that server sids remember the local cert. */
+ PORT_Assert(!sid->localCert);
+ if (sid->localCert) {
+ CERT_DestroyCertificate(sid->localCert);
+ }
+ sid->localCert = CERT_DupCertificate(serverCert);
+
+ ss->sec.authAlgorithm = ssl_sign_rsa;
+ ss->sec.keaType = ssl_kea_rsa;
+ ss->sec.keaKeyBits =
+ ss->sec.authKeyBits = ss->serverCerts[kt_rsa].serverKeyBits;
}
/* server sids don't remember the local cert, so whether we found
** a sid or not, just "remember" we used the rsa server cert.
*/
if (ss->sec.localCert) {
- CERT_DestroyCertificate(ss->sec.localCert);
+ CERT_DestroyCertificate(ss->sec.localCert);
}
- ss->sec.localCert = CERT_DupCertificate(serverCert);
+ ss->sec.localCert = CERT_DupCertificate(serverCert);
/* Build up final list of required elements */
ss->sec.ci.requiredElements = CIS_HAVE_MASTER_KEY | CIS_HAVE_FINISHED;
if (ss->opt.requestCertificate) {
- ss->sec.ci.requiredElements |= CIS_HAVE_CERTIFICATE;
+ ss->sec.ci.requiredElements |= CIS_HAVE_CERTIFICATE;
}
ss->sec.ci.sentElements = 0;
/* Send hello message back to client */
- sendLen = SSL_HL_SERVER_HELLO_HBYTES + certLen + csLen
- + SSL_CONNECTIONID_BYTES;
+ sendLen = SSL_HL_SERVER_HELLO_HBYTES + certLen + csLen +
+ SSL_CONNECTIONID_BYTES;
- ssl_GetXmitBufLock(ss); gotXmitBufLock = 1;
+ ssl_GetXmitBufLock(ss);
+ gotXmitBufLock = 1;
rv = ssl2_GetSendBuffer(ss, sendLen);
if (rv != SECSuccess) {
- goto loser;
+ goto loser;
}
SSL_TRC(3, ("%d: SSL[%d]: sending server-hello (%d)",
- SSL_GETPID(), ss->fd, sendLen));
+ SSL_GETPID(), ss->fd, sendLen));
msg = ss->sec.ci.sendBuf.buf;
msg[0] = SSL_MT_SERVER_HELLO;
@@ -3550,12 +3555,12 @@ ssl2_HandleClientHelloMessage(sslSocket *ss)
msg[9] = MSB(SSL_CONNECTIONID_BYTES);
msg[10] = LSB(SSL_CONNECTIONID_BYTES);
if (certLen) {
- PORT_Memcpy(msg+SSL_HL_SERVER_HELLO_HBYTES, cert, certLen);
+ PORT_Memcpy(msg + SSL_HL_SERVER_HELLO_HBYTES, cert, certLen);
}
if (csLen) {
- PORT_Memcpy(msg+SSL_HL_SERVER_HELLO_HBYTES+certLen, cs, csLen);
+ PORT_Memcpy(msg + SSL_HL_SERVER_HELLO_HBYTES + certLen, cs, csLen);
}
- PORT_Memcpy(msg+SSL_HL_SERVER_HELLO_HBYTES+certLen+csLen,
+ PORT_Memcpy(msg + SSL_HL_SERVER_HELLO_HBYTES + certLen + csLen,
ss->sec.ci.connectionID, SSL_CONNECTIONID_BYTES);
DUMP_MSG(29, (ss, msg, sendLen));
@@ -3563,40 +3568,42 @@ ssl2_HandleClientHelloMessage(sslSocket *ss)
ss->handshakeBegun = 1;
sent = (*ss->sec.send)(ss, msg, sendLen, 0);
if (sent < 0) {
- goto loser;
+ goto loser;
}
- ssl_ReleaseXmitBufLock(ss); gotXmitBufLock = 0;
+ ssl_ReleaseXmitBufLock(ss);
+ gotXmitBufLock = 0;
ss->gs.recordLen = 0;
ss->handshake = ssl_GatherRecord1stHandshake;
if (hit) {
- /* Old SID Session key is good. Go encrypted */
- ssl2_UseEncryptedSendFunc(ss);
+ /* Old SID Session key is good. Go encrypted */
+ ssl2_UseEncryptedSendFunc(ss);
- /* Send server verify message now that keys are established */
- rv = ssl2_SendServerVerifyMessage(ss);
- if (rv != SECSuccess)
- goto loser;
+ /* Send server verify message now that keys are established */
+ rv = ssl2_SendServerVerifyMessage(ss);
+ if (rv != SECSuccess)
+ goto loser;
- ss->nextHandshake = ssl2_HandleMessage;
- ssl_ReleaseRecvBufLock(ss);
- rv = ssl2_TriggerNextMessage(ss);
- return rv;
+ ss->nextHandshake = ssl2_HandleMessage;
+ ssl_ReleaseRecvBufLock(ss);
+ rv = ssl2_TriggerNextMessage(ss);
+ return rv;
}
ss->nextHandshake = ssl2_HandleClientSessionKeyMessage;
ssl_ReleaseRecvBufLock(ss);
return SECSuccess;
- bad_client:
+bad_client:
PORT_SetError(SSL_ERROR_BAD_CLIENT);
- /* FALLTHROUGH */
+/* FALLTHROUGH */
- loser:
+loser:
if (gotXmitBufLock) {
- ssl_ReleaseXmitBufLock(ss); gotXmitBufLock = 0;
+ ssl_ReleaseXmitBufLock(ss);
+ gotXmitBufLock = 0;
}
SSL_TRC(10, ("%d: SSL[%d]: server, wait for client-hello lossage",
- SSL_GETPID(), ss->fd));
+ SSL_GETPID(), ss->fd));
ssl_ReleaseRecvBufLock(ss);
return SECFailure;
}
@@ -3604,8 +3611,8 @@ ssl2_HandleClientHelloMessage(sslSocket *ss)
SECStatus
ssl2_BeginServerHandshake(sslSocket *ss)
{
- SECStatus rv;
- sslServerCerts * rsaAuth = ss->serverCerts + kt_rsa;
+ SECStatus rv;
+ sslServerCerts *rsaAuth = ss->serverCerts + kt_rsa;
ss->sec.isServer = 1;
ssl_ChooseSessionIDProcs(&ss->sec);
@@ -3613,15 +3620,15 @@ ssl2_BeginServerHandshake(sslSocket *ss)
ss->sec.rcvSequence = 0;
/* don't turn on SSL2 if we don't have an RSA key and cert */
- if (!rsaAuth->serverKeyPair || !rsaAuth->SERVERKEY ||
+ if (!rsaAuth->serverKeyPair || !rsaAuth->SERVERKEY ||
!rsaAuth->serverCert) {
- ss->opt.enableSSL2 = PR_FALSE;
+ ss->opt.enableSSL2 = PR_FALSE;
}
if (!ss->cipherSpecs) {
- rv = ssl2_ConstructCipherSpecs(ss);
- if (rv != SECSuccess)
- goto loser;
+ rv = ssl2_ConstructCipherSpecs(ss);
+ if (rv != SECSuccess)
+ goto loser;
}
/* count the SSL2 and SSL3 enabled ciphers.
@@ -3629,18 +3636,18 @@ ssl2_BeginServerHandshake(sslSocket *ss)
*/
rv = ssl2_CheckConfigSanity(ss);
if (rv != SECSuccess)
- goto loser;
+ goto loser;
/*
** Generate connection-id. Always do this, even if things fail
** immediately. This way the random number generator is always
** rolling around, every time we get a connection.
*/
- PK11_GenerateRandom(ss->sec.ci.connectionID,
+ PK11_GenerateRandom(ss->sec.ci.connectionID,
sizeof(ss->sec.ci.connectionID));
ss->gs.recordLen = 0;
- ss->handshake = ssl_GatherRecord1stHandshake;
+ ss->handshake = ssl_GatherRecord1stHandshake;
ss->nextHandshake = ssl2_HandleClientHelloMessage;
return SECSuccess;
@@ -3649,7 +3656,7 @@ loser:
}
/* This function doesn't really belong in this file.
-** It's here to keep AIX compilers from optimizing it away,
+** It's here to keep AIX compilers from optimizing it away,
** and not including it in the DSO.
*/
diff --git a/chromium/net/third_party/nss/ssl/ssldef.c b/chromium/net/third_party/nss/ssl/ssldef.c
index cc3ecc8bf14..77a744cc7ab 100644
--- a/chromium/net/third_party/nss/ssl/ssldef.c
+++ b/chromium/net/third_party/nss/ssl/ssldef.c
@@ -10,14 +10,18 @@
#include "sslimpl.h"
#if defined(WIN32)
-#define MAP_ERROR(from,to) if (err == from) { PORT_SetError(to); }
-#define DEFINE_ERROR PRErrorCode err = PR_GetError();
+#define MAP_ERROR(from, to) \
+ if (err == from) { \
+ PORT_SetError(to); \
+ }
+#define DEFINE_ERROR PRErrorCode err = PR_GetError();
#else
-#define MAP_ERROR(from,to)
+#define MAP_ERROR(from, to)
#define DEFINE_ERROR
#endif
-int ssl_DefConnect(sslSocket *ss, const PRNetAddr *sa)
+int
+ssl_DefConnect(sslSocket *ss, const PRNetAddr *sa)
{
PRFileDesc *lower = ss->fd->lower;
int rv;
@@ -26,7 +30,8 @@ int ssl_DefConnect(sslSocket *ss, const PRNetAddr *sa)
return rv;
}
-int ssl_DefBind(sslSocket *ss, const PRNetAddr *addr)
+int
+ssl_DefBind(sslSocket *ss, const PRNetAddr *addr)
{
PRFileDesc *lower = ss->fd->lower;
int rv;
@@ -35,7 +40,8 @@ int ssl_DefBind(sslSocket *ss, const PRNetAddr *addr)
return rv;
}
-int ssl_DefListen(sslSocket *ss, int backlog)
+int
+ssl_DefListen(sslSocket *ss, int backlog)
{
PRFileDesc *lower = ss->fd->lower;
int rv;
@@ -44,7 +50,8 @@ int ssl_DefListen(sslSocket *ss, int backlog)
return rv;
}
-int ssl_DefShutdown(sslSocket *ss, int how)
+int
+ssl_DefShutdown(sslSocket *ss, int how)
{
PRFileDesc *lower = ss->fd->lower;
int rv;
@@ -53,19 +60,20 @@ int ssl_DefShutdown(sslSocket *ss, int how)
return rv;
}
-int ssl_DefRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
+int
+ssl_DefRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
{
PRFileDesc *lower = ss->fd->lower;
int rv;
rv = lower->methods->recv(lower, (void *)buf, len, flags, ss->rTimeout);
if (rv < 0) {
- DEFINE_ERROR
- MAP_ERROR(PR_SOCKET_SHUTDOWN_ERROR, PR_CONNECT_RESET_ERROR)
+ DEFINE_ERROR
+ MAP_ERROR(PR_SOCKET_SHUTDOWN_ERROR, PR_CONNECT_RESET_ERROR)
} else if (rv > len) {
- PORT_Assert(rv <= len);
- PORT_SetError(PR_BUFFER_OVERFLOW_ERROR);
- rv = SECFailure;
+ PORT_Assert(rv <= len);
+ PORT_SetError(PR_BUFFER_OVERFLOW_ERROR);
+ rv = SECFailure;
}
return rv;
}
@@ -73,87 +81,91 @@ int ssl_DefRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
/* Default (unencrypted) send.
* For blocking sockets, always returns len or SECFailure, no short writes.
* For non-blocking sockets:
- * Returns positive count if any data was written, else returns SECFailure.
+ * Returns positive count if any data was written, else returns SECFailure.
* Short writes may occur. Does not return SECWouldBlock.
*/
-int ssl_DefSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
+int
+ssl_DefSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
{
PRFileDesc *lower = ss->fd->lower;
int sent = 0;
#if NSS_DISABLE_NAGLE_DELAYS
- /* Although this is overkill, we disable Nagle delays completely for
+ /* Although this is overkill, we disable Nagle delays completely for
** SSL sockets.
*/
if (ss->opt.useSecurity && !ss->delayDisabled) {
- ssl_EnableNagleDelay(ss, PR_FALSE); /* ignore error */
- ss->delayDisabled = 1;
+ ssl_EnableNagleDelay(ss, PR_FALSE); /* ignore error */
+ ss->delayDisabled = 1;
}
#endif
do {
- int rv = lower->methods->send(lower, (const void *)(buf + sent),
- len - sent, flags, ss->wTimeout);
- if (rv < 0) {
- PRErrorCode err = PR_GetError();
- if (err == PR_WOULD_BLOCK_ERROR) {
- ss->lastWriteBlocked = 1;
- return sent ? sent : SECFailure;
- }
- ss->lastWriteBlocked = 0;
- MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR)
- /* Loser */
- return rv;
- }
- sent += rv;
-
- if (IS_DTLS(ss) && (len > sent)) {
- /* We got a partial write so just return it */
- return sent;
- }
+ int rv = lower->methods->send(lower, (const void *)(buf + sent),
+ len - sent, flags, ss->wTimeout);
+ if (rv < 0) {
+ PRErrorCode err = PR_GetError();
+ if (err == PR_WOULD_BLOCK_ERROR) {
+ ss->lastWriteBlocked = 1;
+ return sent ? sent : SECFailure;
+ }
+ ss->lastWriteBlocked = 0;
+ MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR)
+ /* Loser */
+ return rv;
+ }
+ sent += rv;
+
+ if (IS_DTLS(ss) && (len > sent)) {
+ /* We got a partial write so just return it */
+ return sent;
+ }
} while (len > sent);
ss->lastWriteBlocked = 0;
return sent;
}
-int ssl_DefRead(sslSocket *ss, unsigned char *buf, int len)
+int
+ssl_DefRead(sslSocket *ss, unsigned char *buf, int len)
{
PRFileDesc *lower = ss->fd->lower;
int rv;
rv = lower->methods->read(lower, (void *)buf, len);
if (rv < 0) {
- DEFINE_ERROR
- MAP_ERROR(PR_SOCKET_SHUTDOWN_ERROR, PR_CONNECT_RESET_ERROR)
+ DEFINE_ERROR
+ MAP_ERROR(PR_SOCKET_SHUTDOWN_ERROR, PR_CONNECT_RESET_ERROR)
}
return rv;
}
-int ssl_DefWrite(sslSocket *ss, const unsigned char *buf, int len)
+int
+ssl_DefWrite(sslSocket *ss, const unsigned char *buf, int len)
{
PRFileDesc *lower = ss->fd->lower;
int sent = 0;
do {
- int rv = lower->methods->write(lower, (const void *)(buf + sent),
- len - sent);
- if (rv < 0) {
- PRErrorCode err = PR_GetError();
- if (err == PR_WOULD_BLOCK_ERROR) {
- ss->lastWriteBlocked = 1;
- return sent ? sent : SECFailure;
- }
- ss->lastWriteBlocked = 0;
- MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR)
- /* Loser */
- return rv;
- }
- sent += rv;
+ int rv = lower->methods->write(lower, (const void *)(buf + sent),
+ len - sent);
+ if (rv < 0) {
+ PRErrorCode err = PR_GetError();
+ if (err == PR_WOULD_BLOCK_ERROR) {
+ ss->lastWriteBlocked = 1;
+ return sent ? sent : SECFailure;
+ }
+ ss->lastWriteBlocked = 0;
+ MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR)
+ /* Loser */
+ return rv;
+ }
+ sent += rv;
} while (len > sent);
ss->lastWriteBlocked = 0;
return sent;
}
-int ssl_DefGetpeername(sslSocket *ss, PRNetAddr *name)
+int
+ssl_DefGetpeername(sslSocket *ss, PRNetAddr *name)
{
PRFileDesc *lower = ss->fd->lower;
int rv;
@@ -162,7 +174,8 @@ int ssl_DefGetpeername(sslSocket *ss, PRNetAddr *name)
return rv;
}
-int ssl_DefGetsockname(sslSocket *ss, PRNetAddr *name)
+int
+ssl_DefGetsockname(sslSocket *ss, PRNetAddr *name)
{
PRFileDesc *lower = ss->fd->lower;
int rv;
@@ -171,22 +184,23 @@ int ssl_DefGetsockname(sslSocket *ss, PRNetAddr *name)
return rv;
}
-int ssl_DefClose(sslSocket *ss)
+int
+ssl_DefClose(sslSocket *ss)
{
PRFileDesc *fd;
PRFileDesc *popped;
- int rv;
+ int rv;
- fd = ss->fd;
+ fd = ss->fd;
- /* First, remove the SSL layer PRFileDesc from the socket's stack,
+ /* First, remove the SSL layer PRFileDesc from the socket's stack,
** then invoke the SSL layer's PRFileDesc destructor.
** This must happen before the next layer down is closed.
*/
PORT_Assert(fd->higher == NULL);
if (fd->higher) {
- PORT_SetError(PR_BAD_DESCRIPTOR_ERROR);
- return SECFailure;
+ PORT_SetError(PR_BAD_DESCRIPTOR_ERROR);
+ return SECFailure;
}
ss->fd = NULL;
@@ -194,17 +208,17 @@ int ssl_DefClose(sslSocket *ss)
** the stack, and then remove the second one. This way, the address
** of the PRFileDesc on the top of the stack doesn't change.
*/
- popped = PR_PopIOLayer(fd, PR_TOP_IO_LAYER);
+ popped = PR_PopIOLayer(fd, PR_TOP_IO_LAYER);
popped->dtor(popped);
/* fd is now the PRFileDesc for the next layer down.
- ** Now close the underlying socket.
+ ** Now close the underlying socket.
*/
rv = fd->methods->close(fd);
ssl_FreeSocket(ss);
SSL_TRC(5, ("%d: SSL[%d]: closing, rv=%d errno=%d",
- SSL_GETPID(), fd, rv, PORT_GetError()));
+ SSL_GETPID(), fd, rv, PORT_GetError()));
return rv;
}
diff --git a/chromium/net/third_party/nss/ssl/sslenum.c b/chromium/net/third_party/nss/ssl/sslenum.c
index b4a8844470b..d362b74ee04 100644
--- a/chromium/net/third_party/nss/ssl/sslenum.c
+++ b/chromium/net/third_party/nss/ssl/sslenum.c
@@ -37,23 +37,21 @@
*
* Exception: Because some servers ignore the high-order byte of the cipher
* suite ID, we must be careful about adding cipher suites with IDs larger
- * than 0x00ff; see bug 946147. For these broken servers, the first six cipher
+ * than 0x00ff; see bug 946147. For these broken servers, the first four cipher
* suites, with the MSB zeroed, look like:
- * TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA { 0x00,0x14 }
- * TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA { 0x00,0x13 }
* TLS_KRB5_EXPORT_WITH_RC4_40_MD5 { 0x00,0x2B }
* TLS_RSA_WITH_AES_128_CBC_SHA { 0x00,0x2F }
* TLS_RSA_WITH_3DES_EDE_CBC_SHA { 0x00,0x0A }
* TLS_RSA_WITH_DES_CBC_SHA { 0x00,0x09 }
- * The broken server only supports the fifth and sixth ones and will select
- * the fifth one.
+ * The broken server only supports the third and fourth ones and will select
+ * the third one.
*/
const PRUint16 SSL_ImplementedCiphers[] = {
#ifndef NSS_DISABLE_ECC
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
/* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA must appear before
* TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA to work around bug 946147.
*/
@@ -70,6 +68,7 @@ const PRUint16 SSL_ImplementedCiphers[] = {
#endif /* NSS_DISABLE_ECC */
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
@@ -125,7 +124,7 @@ const PRUint16 SSL_ImplementedCiphers[] = {
TLS_RSA_EXPORT_WITH_RC4_40_MD5,
TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
- /* ciphersuites with no encryption */
+/* ciphersuites with no encryption */
#ifndef NSS_DISABLE_ECC
TLS_ECDHE_ECDSA_WITH_NULL_SHA,
TLS_ECDHE_RSA_WITH_NULL_SHA,
@@ -139,7 +138,7 @@ const PRUint16 SSL_ImplementedCiphers[] = {
/* SSL2 cipher suites. */
SSL_EN_RC4_128_WITH_MD5,
SSL_EN_RC2_128_CBC_WITH_MD5,
- SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* actually 112, not 192 */
+ SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* actually 112, not 192 */
SSL_EN_DES_64_CBC_WITH_MD5,
SSL_EN_RC4_128_EXPORT40_WITH_MD5,
SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5,
@@ -148,10 +147,10 @@ const PRUint16 SSL_ImplementedCiphers[] = {
};
-const PRUint16 SSL_NumImplementedCiphers =
+const PRUint16 SSL_NumImplementedCiphers =
(sizeof SSL_ImplementedCiphers) / (sizeof SSL_ImplementedCiphers[0]) - 1;
-const PRUint16 *
+const PRUint16*
SSL_GetImplementedCiphers(void)
{
return SSL_ImplementedCiphers;
diff --git a/chromium/net/third_party/nss/ssl/sslerr.c b/chromium/net/third_party/nss/ssl/sslerr.c
index f827221aee2..edb941257d5 100644
--- a/chromium/net/third_party/nss/ssl/sslerr.c
+++ b/chromium/net/third_party/nss/ssl/sslerr.c
@@ -1,5 +1,5 @@
/*
- * Function to set error code only when meaningful error has not already
+ * Function to set error code only when meaningful error has not already
* been set.
*
* This Source Code Form is subject to the terms of the Mozilla Public
@@ -12,30 +12,30 @@
#include "seccomon.h"
/* look at the current value of PR_GetError, and evaluate it to see
- * if it is meaningful or meaningless (out of context).
+ * if it is meaningful or meaningless (out of context).
* If it is meaningless, replace it with the hiLevelError.
* Returns the chosen error value.
*/
int
ssl_MapLowLevelError(int hiLevelError)
{
- int oldErr = PORT_GetError();
+ int oldErr = PORT_GetError();
switch (oldErr) {
- case 0:
- case PR_IO_ERROR:
- case SEC_ERROR_IO:
- case SEC_ERROR_BAD_DATA:
- case SEC_ERROR_LIBRARY_FAILURE:
- case SEC_ERROR_EXTENSION_NOT_FOUND:
- case SSL_ERROR_BAD_CLIENT:
- case SSL_ERROR_BAD_SERVER:
- case SSL_ERROR_SESSION_NOT_FOUND:
- PORT_SetError(hiLevelError);
- return hiLevelError;
+ case 0:
+ case PR_IO_ERROR:
+ case SEC_ERROR_IO:
+ case SEC_ERROR_BAD_DATA:
+ case SEC_ERROR_LIBRARY_FAILURE:
+ case SEC_ERROR_EXTENSION_NOT_FOUND:
+ case SSL_ERROR_BAD_CLIENT:
+ case SSL_ERROR_BAD_SERVER:
+ case SSL_ERROR_SESSION_NOT_FOUND:
+ PORT_SetError(hiLevelError);
+ return hiLevelError;
- default: /* leave the majority of error codes alone. */
- return oldErr;
+ default: /* leave the majority of error codes alone. */
+ return oldErr;
}
}
diff --git a/chromium/net/third_party/nss/ssl/sslerr.h b/chromium/net/third_party/nss/ssl/sslerr.h
index 835b8125121..299951ce9f1 100644
--- a/chromium/net/third_party/nss/ssl/sslerr.h
+++ b/chromium/net/third_party/nss/ssl/sslerr.h
@@ -7,6 +7,7 @@
#ifndef __SSL_ERR_H_
#define __SSL_ERR_H_
+/* clang-format off */
#define SSL_ERROR_BASE (-0x3000)
#define SSL_ERROR_LIMIT (SSL_ERROR_BASE + 1000)
@@ -16,204 +17,218 @@
#ifndef NO_SECURITY_ERROR_ENUM
typedef enum {
-SSL_ERROR_EXPORT_ONLY_SERVER = (SSL_ERROR_BASE + 0),
-SSL_ERROR_US_ONLY_SERVER = (SSL_ERROR_BASE + 1),
-SSL_ERROR_NO_CYPHER_OVERLAP = (SSL_ERROR_BASE + 2),
-/*
- * Received an alert reporting what we did wrong. (more alerts below)
- */
-SSL_ERROR_NO_CERTIFICATE /*_ALERT */ = (SSL_ERROR_BASE + 3),
-SSL_ERROR_BAD_CERTIFICATE = (SSL_ERROR_BASE + 4),
-SSL_ERROR_UNUSED_5 = (SSL_ERROR_BASE + 5),
- /* error 5 is obsolete */
-SSL_ERROR_BAD_CLIENT = (SSL_ERROR_BASE + 6),
-SSL_ERROR_BAD_SERVER = (SSL_ERROR_BASE + 7),
-SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE = (SSL_ERROR_BASE + 8),
-SSL_ERROR_UNSUPPORTED_VERSION = (SSL_ERROR_BASE + 9),
-SSL_ERROR_UNUSED_10 = (SSL_ERROR_BASE + 10),
- /* error 10 is obsolete */
-SSL_ERROR_WRONG_CERTIFICATE = (SSL_ERROR_BASE + 11),
-SSL_ERROR_BAD_CERT_DOMAIN = (SSL_ERROR_BASE + 12),
-SSL_ERROR_POST_WARNING = (SSL_ERROR_BASE + 13),
-SSL_ERROR_SSL2_DISABLED = (SSL_ERROR_BASE + 14),
-SSL_ERROR_BAD_MAC_READ = (SSL_ERROR_BASE + 15),
-/*
- * Received an alert reporting what we did wrong.
- * (two more alerts above, and many more below)
- */
-SSL_ERROR_BAD_MAC_ALERT = (SSL_ERROR_BASE + 16),
-SSL_ERROR_BAD_CERT_ALERT = (SSL_ERROR_BASE + 17),
-SSL_ERROR_REVOKED_CERT_ALERT = (SSL_ERROR_BASE + 18),
-SSL_ERROR_EXPIRED_CERT_ALERT = (SSL_ERROR_BASE + 19),
-
-SSL_ERROR_SSL_DISABLED = (SSL_ERROR_BASE + 20),
-SSL_ERROR_FORTEZZA_PQG = (SSL_ERROR_BASE + 21),
-SSL_ERROR_UNKNOWN_CIPHER_SUITE = (SSL_ERROR_BASE + 22),
-SSL_ERROR_NO_CIPHERS_SUPPORTED = (SSL_ERROR_BASE + 23),
-SSL_ERROR_BAD_BLOCK_PADDING = (SSL_ERROR_BASE + 24),
-SSL_ERROR_RX_RECORD_TOO_LONG = (SSL_ERROR_BASE + 25),
-SSL_ERROR_TX_RECORD_TOO_LONG = (SSL_ERROR_BASE + 26),
-/*
- * Received a malformed (too long or short) SSL handshake.
- */
-SSL_ERROR_RX_MALFORMED_HELLO_REQUEST = (SSL_ERROR_BASE + 27),
-SSL_ERROR_RX_MALFORMED_CLIENT_HELLO = (SSL_ERROR_BASE + 28),
-SSL_ERROR_RX_MALFORMED_SERVER_HELLO = (SSL_ERROR_BASE + 29),
-SSL_ERROR_RX_MALFORMED_CERTIFICATE = (SSL_ERROR_BASE + 30),
-SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH = (SSL_ERROR_BASE + 31),
-SSL_ERROR_RX_MALFORMED_CERT_REQUEST = (SSL_ERROR_BASE + 32),
-SSL_ERROR_RX_MALFORMED_HELLO_DONE = (SSL_ERROR_BASE + 33),
-SSL_ERROR_RX_MALFORMED_CERT_VERIFY = (SSL_ERROR_BASE + 34),
-SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH = (SSL_ERROR_BASE + 35),
-SSL_ERROR_RX_MALFORMED_FINISHED = (SSL_ERROR_BASE + 36),
-/*
- * Received a malformed (too long or short) SSL record.
- */
-SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER = (SSL_ERROR_BASE + 37),
-SSL_ERROR_RX_MALFORMED_ALERT = (SSL_ERROR_BASE + 38),
-SSL_ERROR_RX_MALFORMED_HANDSHAKE = (SSL_ERROR_BASE + 39),
-SSL_ERROR_RX_MALFORMED_APPLICATION_DATA = (SSL_ERROR_BASE + 40),
-/*
- * Received an SSL handshake that was inappropriate for the state we're in.
- * E.g. Server received message from server, or wrong state in state machine.
- */
-SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST = (SSL_ERROR_BASE + 41),
-SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO = (SSL_ERROR_BASE + 42),
-SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO = (SSL_ERROR_BASE + 43),
-SSL_ERROR_RX_UNEXPECTED_CERTIFICATE = (SSL_ERROR_BASE + 44),
-SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH = (SSL_ERROR_BASE + 45),
-SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST = (SSL_ERROR_BASE + 46),
-SSL_ERROR_RX_UNEXPECTED_HELLO_DONE = (SSL_ERROR_BASE + 47),
-SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY = (SSL_ERROR_BASE + 48),
-SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH = (SSL_ERROR_BASE + 49),
-SSL_ERROR_RX_UNEXPECTED_FINISHED = (SSL_ERROR_BASE + 50),
-/*
- * Received an SSL record that was inappropriate for the state we're in.
- */
-SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER = (SSL_ERROR_BASE + 51),
-SSL_ERROR_RX_UNEXPECTED_ALERT = (SSL_ERROR_BASE + 52),
-SSL_ERROR_RX_UNEXPECTED_HANDSHAKE = (SSL_ERROR_BASE + 53),
-SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA = (SSL_ERROR_BASE + 54),
-/*
- * Received record/message with unknown discriminant.
- */
-SSL_ERROR_RX_UNKNOWN_RECORD_TYPE = (SSL_ERROR_BASE + 55),
-SSL_ERROR_RX_UNKNOWN_HANDSHAKE = (SSL_ERROR_BASE + 56),
-SSL_ERROR_RX_UNKNOWN_ALERT = (SSL_ERROR_BASE + 57),
-/*
- * Received an alert reporting what we did wrong. (more alerts above)
- */
-SSL_ERROR_CLOSE_NOTIFY_ALERT = (SSL_ERROR_BASE + 58),
-SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT = (SSL_ERROR_BASE + 59),
-SSL_ERROR_DECOMPRESSION_FAILURE_ALERT = (SSL_ERROR_BASE + 60),
-SSL_ERROR_HANDSHAKE_FAILURE_ALERT = (SSL_ERROR_BASE + 61),
-SSL_ERROR_ILLEGAL_PARAMETER_ALERT = (SSL_ERROR_BASE + 62),
-SSL_ERROR_UNSUPPORTED_CERT_ALERT = (SSL_ERROR_BASE + 63),
-SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT = (SSL_ERROR_BASE + 64),
-
-SSL_ERROR_GENERATE_RANDOM_FAILURE = (SSL_ERROR_BASE + 65),
-SSL_ERROR_SIGN_HASHES_FAILURE = (SSL_ERROR_BASE + 66),
-SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE = (SSL_ERROR_BASE + 67),
-SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE = (SSL_ERROR_BASE + 68),
-SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE = (SSL_ERROR_BASE + 69),
-
-SSL_ERROR_ENCRYPTION_FAILURE = (SSL_ERROR_BASE + 70),
-SSL_ERROR_DECRYPTION_FAILURE = (SSL_ERROR_BASE + 71), /* don't use */
-SSL_ERROR_SOCKET_WRITE_FAILURE = (SSL_ERROR_BASE + 72),
-
-SSL_ERROR_MD5_DIGEST_FAILURE = (SSL_ERROR_BASE + 73),
-SSL_ERROR_SHA_DIGEST_FAILURE = (SSL_ERROR_BASE + 74),
-SSL_ERROR_MAC_COMPUTATION_FAILURE = (SSL_ERROR_BASE + 75),
-SSL_ERROR_SYM_KEY_CONTEXT_FAILURE = (SSL_ERROR_BASE + 76),
-SSL_ERROR_SYM_KEY_UNWRAP_FAILURE = (SSL_ERROR_BASE + 77),
-SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED = (SSL_ERROR_BASE + 78),
-SSL_ERROR_IV_PARAM_FAILURE = (SSL_ERROR_BASE + 79),
-SSL_ERROR_INIT_CIPHER_SUITE_FAILURE = (SSL_ERROR_BASE + 80),
-SSL_ERROR_SESSION_KEY_GEN_FAILURE = (SSL_ERROR_BASE + 81),
-SSL_ERROR_NO_SERVER_KEY_FOR_ALG = (SSL_ERROR_BASE + 82),
-SSL_ERROR_TOKEN_INSERTION_REMOVAL = (SSL_ERROR_BASE + 83),
-SSL_ERROR_TOKEN_SLOT_NOT_FOUND = (SSL_ERROR_BASE + 84),
-SSL_ERROR_NO_COMPRESSION_OVERLAP = (SSL_ERROR_BASE + 85),
-SSL_ERROR_HANDSHAKE_NOT_COMPLETED = (SSL_ERROR_BASE + 86),
-SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE = (SSL_ERROR_BASE + 87),
-SSL_ERROR_CERT_KEA_MISMATCH = (SSL_ERROR_BASE + 88),
-/* SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA became obsolete in NSS 3.14. */
-SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA = (SSL_ERROR_BASE + 89),
-SSL_ERROR_SESSION_NOT_FOUND = (SSL_ERROR_BASE + 90),
-
-SSL_ERROR_DECRYPTION_FAILED_ALERT = (SSL_ERROR_BASE + 91),
-SSL_ERROR_RECORD_OVERFLOW_ALERT = (SSL_ERROR_BASE + 92),
-SSL_ERROR_UNKNOWN_CA_ALERT = (SSL_ERROR_BASE + 93),
-SSL_ERROR_ACCESS_DENIED_ALERT = (SSL_ERROR_BASE + 94),
-SSL_ERROR_DECODE_ERROR_ALERT = (SSL_ERROR_BASE + 95),
-SSL_ERROR_DECRYPT_ERROR_ALERT = (SSL_ERROR_BASE + 96),
-SSL_ERROR_EXPORT_RESTRICTION_ALERT = (SSL_ERROR_BASE + 97),
-SSL_ERROR_PROTOCOL_VERSION_ALERT = (SSL_ERROR_BASE + 98),
-SSL_ERROR_INSUFFICIENT_SECURITY_ALERT = (SSL_ERROR_BASE + 99),
-SSL_ERROR_INTERNAL_ERROR_ALERT = (SSL_ERROR_BASE + 100),
-SSL_ERROR_USER_CANCELED_ALERT = (SSL_ERROR_BASE + 101),
-SSL_ERROR_NO_RENEGOTIATION_ALERT = (SSL_ERROR_BASE + 102),
-
-SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED = (SSL_ERROR_BASE + 103),
-
-SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT = (SSL_ERROR_BASE + 104),
-SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT = (SSL_ERROR_BASE + 105),
-SSL_ERROR_UNRECOGNIZED_NAME_ALERT = (SSL_ERROR_BASE + 106),
-SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT = (SSL_ERROR_BASE + 107),
-SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT = (SSL_ERROR_BASE + 108),
-
-SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET = (SSL_ERROR_BASE + 109),
-SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET = (SSL_ERROR_BASE + 110),
-
-SSL_ERROR_DECOMPRESSION_FAILURE = (SSL_ERROR_BASE + 111),
-SSL_ERROR_RENEGOTIATION_NOT_ALLOWED = (SSL_ERROR_BASE + 112),
-SSL_ERROR_UNSAFE_NEGOTIATION = (SSL_ERROR_BASE + 113),
-
-SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD = (SSL_ERROR_BASE + 114),
-
-SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY = (SSL_ERROR_BASE + 115),
-
-SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID = (SSL_ERROR_BASE + 116),
-
-SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2 = (SSL_ERROR_BASE + 117),
-SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS = (SSL_ERROR_BASE + 118),
-SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_CLIENTS = (SSL_ERROR_BASE + 119),
-
-SSL_ERROR_INVALID_VERSION_RANGE = (SSL_ERROR_BASE + 120),
-SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION = (SSL_ERROR_BASE + 121),
-
-SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST = (SSL_ERROR_BASE + 122),
-SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST = (SSL_ERROR_BASE + 123),
-
-SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION = (SSL_ERROR_BASE + 124),
-
-SSL_ERROR_RX_UNEXPECTED_CERT_STATUS = (SSL_ERROR_BASE + 125),
-
-SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM = (SSL_ERROR_BASE + 126),
-SSL_ERROR_DIGEST_FAILURE = (SSL_ERROR_BASE + 127),
-SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 128),
-
-SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK = (SSL_ERROR_BASE + 129),
-SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL = (SSL_ERROR_BASE + 130),
-
-SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT = (SSL_ERROR_BASE + 131),
-
-SSL_ERROR_WEAK_SERVER_CERT_KEY = (SSL_ERROR_BASE + 132),
-
-SSL_ERROR_RX_SHORT_DTLS_READ = (SSL_ERROR_BASE + 133),
-
-SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 134),
-SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 135),
-
-SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET = (SSL_ERROR_BASE + 136),
-SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET = (SSL_ERROR_BASE + 137),
-
-SSL_ERROR_BAD_CHANNEL_ID_DATA = (SSL_ERROR_BASE + 138),
-SSL_ERROR_INVALID_CHANNEL_ID_KEY = (SSL_ERROR_BASE + 139),
-SSL_ERROR_GET_CHANNEL_ID_FAILED = (SSL_ERROR_BASE + 140),
-
-SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
+ SSL_ERROR_EXPORT_ONLY_SERVER = (SSL_ERROR_BASE + 0),
+ SSL_ERROR_US_ONLY_SERVER = (SSL_ERROR_BASE + 1),
+ SSL_ERROR_NO_CYPHER_OVERLAP = (SSL_ERROR_BASE + 2),
+ /*
+ * Received an alert reporting what we did wrong. (more alerts below)
+ */
+ SSL_ERROR_NO_CERTIFICATE /*_ALERT */ = (SSL_ERROR_BASE + 3),
+ SSL_ERROR_BAD_CERTIFICATE = (SSL_ERROR_BASE + 4),
+ SSL_ERROR_UNUSED_5 = (SSL_ERROR_BASE + 5),
+ /* error 5 is obsolete */
+ SSL_ERROR_BAD_CLIENT = (SSL_ERROR_BASE + 6),
+ SSL_ERROR_BAD_SERVER = (SSL_ERROR_BASE + 7),
+ SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE = (SSL_ERROR_BASE + 8),
+ SSL_ERROR_UNSUPPORTED_VERSION = (SSL_ERROR_BASE + 9),
+ SSL_ERROR_UNUSED_10 = (SSL_ERROR_BASE + 10),
+ /* error 10 is obsolete */
+ SSL_ERROR_WRONG_CERTIFICATE = (SSL_ERROR_BASE + 11),
+ SSL_ERROR_BAD_CERT_DOMAIN = (SSL_ERROR_BASE + 12),
+ SSL_ERROR_POST_WARNING = (SSL_ERROR_BASE + 13),
+ SSL_ERROR_SSL2_DISABLED = (SSL_ERROR_BASE + 14),
+ SSL_ERROR_BAD_MAC_READ = (SSL_ERROR_BASE + 15),
+ /*
+ * Received an alert reporting what we did wrong.
+ * (two more alerts above, and many more below)
+ */
+ SSL_ERROR_BAD_MAC_ALERT = (SSL_ERROR_BASE + 16),
+ SSL_ERROR_BAD_CERT_ALERT = (SSL_ERROR_BASE + 17),
+ SSL_ERROR_REVOKED_CERT_ALERT = (SSL_ERROR_BASE + 18),
+ SSL_ERROR_EXPIRED_CERT_ALERT = (SSL_ERROR_BASE + 19),
+
+ SSL_ERROR_SSL_DISABLED = (SSL_ERROR_BASE + 20),
+ SSL_ERROR_FORTEZZA_PQG = (SSL_ERROR_BASE + 21),
+ SSL_ERROR_UNKNOWN_CIPHER_SUITE = (SSL_ERROR_BASE + 22),
+ SSL_ERROR_NO_CIPHERS_SUPPORTED = (SSL_ERROR_BASE + 23),
+ SSL_ERROR_BAD_BLOCK_PADDING = (SSL_ERROR_BASE + 24),
+ SSL_ERROR_RX_RECORD_TOO_LONG = (SSL_ERROR_BASE + 25),
+ SSL_ERROR_TX_RECORD_TOO_LONG = (SSL_ERROR_BASE + 26),
+ /*
+ * Received a malformed (too long or short) SSL handshake.
+ */
+ SSL_ERROR_RX_MALFORMED_HELLO_REQUEST = (SSL_ERROR_BASE + 27),
+ SSL_ERROR_RX_MALFORMED_CLIENT_HELLO = (SSL_ERROR_BASE + 28),
+ SSL_ERROR_RX_MALFORMED_SERVER_HELLO = (SSL_ERROR_BASE + 29),
+ SSL_ERROR_RX_MALFORMED_CERTIFICATE = (SSL_ERROR_BASE + 30),
+ SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH = (SSL_ERROR_BASE + 31),
+ SSL_ERROR_RX_MALFORMED_CERT_REQUEST = (SSL_ERROR_BASE + 32),
+ SSL_ERROR_RX_MALFORMED_HELLO_DONE = (SSL_ERROR_BASE + 33),
+ SSL_ERROR_RX_MALFORMED_CERT_VERIFY = (SSL_ERROR_BASE + 34),
+ SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH = (SSL_ERROR_BASE + 35),
+ SSL_ERROR_RX_MALFORMED_FINISHED = (SSL_ERROR_BASE + 36),
+ /*
+ * Received a malformed (too long or short) SSL record.
+ */
+ SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER = (SSL_ERROR_BASE + 37),
+ SSL_ERROR_RX_MALFORMED_ALERT = (SSL_ERROR_BASE + 38),
+ SSL_ERROR_RX_MALFORMED_HANDSHAKE = (SSL_ERROR_BASE + 39),
+ SSL_ERROR_RX_MALFORMED_APPLICATION_DATA = (SSL_ERROR_BASE + 40),
+ /*
+ * Received an SSL handshake that was inappropriate for the state we're in.
+ * E.g. Server received message from server, or wrong state in state machine.
+ */
+ SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST = (SSL_ERROR_BASE + 41),
+ SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO = (SSL_ERROR_BASE + 42),
+ SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO = (SSL_ERROR_BASE + 43),
+ SSL_ERROR_RX_UNEXPECTED_CERTIFICATE = (SSL_ERROR_BASE + 44),
+ SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH = (SSL_ERROR_BASE + 45),
+ SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST = (SSL_ERROR_BASE + 46),
+ SSL_ERROR_RX_UNEXPECTED_HELLO_DONE = (SSL_ERROR_BASE + 47),
+ SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY = (SSL_ERROR_BASE + 48),
+ SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH = (SSL_ERROR_BASE + 49),
+ SSL_ERROR_RX_UNEXPECTED_FINISHED = (SSL_ERROR_BASE + 50),
+ /*
+ * Received an SSL record that was inappropriate for the state we're in.
+ */
+ SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER = (SSL_ERROR_BASE + 51),
+ SSL_ERROR_RX_UNEXPECTED_ALERT = (SSL_ERROR_BASE + 52),
+ SSL_ERROR_RX_UNEXPECTED_HANDSHAKE = (SSL_ERROR_BASE + 53),
+ SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA = (SSL_ERROR_BASE + 54),
+ /*
+ * Received record/message with unknown discriminant.
+ */
+ SSL_ERROR_RX_UNKNOWN_RECORD_TYPE = (SSL_ERROR_BASE + 55),
+ SSL_ERROR_RX_UNKNOWN_HANDSHAKE = (SSL_ERROR_BASE + 56),
+ SSL_ERROR_RX_UNKNOWN_ALERT = (SSL_ERROR_BASE + 57),
+ /*
+ * Received an alert reporting what we did wrong. (more alerts above)
+ */
+ SSL_ERROR_CLOSE_NOTIFY_ALERT = (SSL_ERROR_BASE + 58),
+ SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT = (SSL_ERROR_BASE + 59),
+ SSL_ERROR_DECOMPRESSION_FAILURE_ALERT = (SSL_ERROR_BASE + 60),
+ SSL_ERROR_HANDSHAKE_FAILURE_ALERT = (SSL_ERROR_BASE + 61),
+ SSL_ERROR_ILLEGAL_PARAMETER_ALERT = (SSL_ERROR_BASE + 62),
+ SSL_ERROR_UNSUPPORTED_CERT_ALERT = (SSL_ERROR_BASE + 63),
+ SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT = (SSL_ERROR_BASE + 64),
+
+ SSL_ERROR_GENERATE_RANDOM_FAILURE = (SSL_ERROR_BASE + 65),
+ SSL_ERROR_SIGN_HASHES_FAILURE = (SSL_ERROR_BASE + 66),
+ SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE = (SSL_ERROR_BASE + 67),
+ SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE = (SSL_ERROR_BASE + 68),
+ SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE = (SSL_ERROR_BASE + 69),
+
+ SSL_ERROR_ENCRYPTION_FAILURE = (SSL_ERROR_BASE + 70),
+ SSL_ERROR_DECRYPTION_FAILURE = (SSL_ERROR_BASE + 71), /* don't use */
+ SSL_ERROR_SOCKET_WRITE_FAILURE = (SSL_ERROR_BASE + 72),
+
+ SSL_ERROR_MD5_DIGEST_FAILURE = (SSL_ERROR_BASE + 73),
+ SSL_ERROR_SHA_DIGEST_FAILURE = (SSL_ERROR_BASE + 74),
+ SSL_ERROR_MAC_COMPUTATION_FAILURE = (SSL_ERROR_BASE + 75),
+ SSL_ERROR_SYM_KEY_CONTEXT_FAILURE = (SSL_ERROR_BASE + 76),
+ SSL_ERROR_SYM_KEY_UNWRAP_FAILURE = (SSL_ERROR_BASE + 77),
+ SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED = (SSL_ERROR_BASE + 78),
+ SSL_ERROR_IV_PARAM_FAILURE = (SSL_ERROR_BASE + 79),
+ SSL_ERROR_INIT_CIPHER_SUITE_FAILURE = (SSL_ERROR_BASE + 80),
+ SSL_ERROR_SESSION_KEY_GEN_FAILURE = (SSL_ERROR_BASE + 81),
+ SSL_ERROR_NO_SERVER_KEY_FOR_ALG = (SSL_ERROR_BASE + 82),
+ SSL_ERROR_TOKEN_INSERTION_REMOVAL = (SSL_ERROR_BASE + 83),
+ SSL_ERROR_TOKEN_SLOT_NOT_FOUND = (SSL_ERROR_BASE + 84),
+ SSL_ERROR_NO_COMPRESSION_OVERLAP = (SSL_ERROR_BASE + 85),
+ SSL_ERROR_HANDSHAKE_NOT_COMPLETED = (SSL_ERROR_BASE + 86),
+ SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE = (SSL_ERROR_BASE + 87),
+ SSL_ERROR_CERT_KEA_MISMATCH = (SSL_ERROR_BASE + 88),
+ /* SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA became obsolete in NSS 3.14. */
+ SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA = (SSL_ERROR_BASE + 89),
+ SSL_ERROR_SESSION_NOT_FOUND = (SSL_ERROR_BASE + 90),
+
+ SSL_ERROR_DECRYPTION_FAILED_ALERT = (SSL_ERROR_BASE + 91),
+ SSL_ERROR_RECORD_OVERFLOW_ALERT = (SSL_ERROR_BASE + 92),
+ SSL_ERROR_UNKNOWN_CA_ALERT = (SSL_ERROR_BASE + 93),
+ SSL_ERROR_ACCESS_DENIED_ALERT = (SSL_ERROR_BASE + 94),
+ SSL_ERROR_DECODE_ERROR_ALERT = (SSL_ERROR_BASE + 95),
+ SSL_ERROR_DECRYPT_ERROR_ALERT = (SSL_ERROR_BASE + 96),
+ SSL_ERROR_EXPORT_RESTRICTION_ALERT = (SSL_ERROR_BASE + 97),
+ SSL_ERROR_PROTOCOL_VERSION_ALERT = (SSL_ERROR_BASE + 98),
+ SSL_ERROR_INSUFFICIENT_SECURITY_ALERT = (SSL_ERROR_BASE + 99),
+ SSL_ERROR_INTERNAL_ERROR_ALERT = (SSL_ERROR_BASE + 100),
+ SSL_ERROR_USER_CANCELED_ALERT = (SSL_ERROR_BASE + 101),
+ SSL_ERROR_NO_RENEGOTIATION_ALERT = (SSL_ERROR_BASE + 102),
+
+ SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED = (SSL_ERROR_BASE + 103),
+
+ SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT = (SSL_ERROR_BASE + 104),
+ SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT = (SSL_ERROR_BASE + 105),
+ SSL_ERROR_UNRECOGNIZED_NAME_ALERT = (SSL_ERROR_BASE + 106),
+ SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT = (SSL_ERROR_BASE + 107),
+ SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT = (SSL_ERROR_BASE + 108),
+
+ SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET = (SSL_ERROR_BASE + 109),
+ SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET = (SSL_ERROR_BASE + 110),
+
+ SSL_ERROR_DECOMPRESSION_FAILURE = (SSL_ERROR_BASE + 111),
+ SSL_ERROR_RENEGOTIATION_NOT_ALLOWED = (SSL_ERROR_BASE + 112),
+ SSL_ERROR_UNSAFE_NEGOTIATION = (SSL_ERROR_BASE + 113),
+
+ SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD = (SSL_ERROR_BASE + 114),
+
+ SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY = (SSL_ERROR_BASE + 115),
+
+ SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID = (SSL_ERROR_BASE + 116),
+
+ SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2 = (SSL_ERROR_BASE + 117),
+ SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS = (SSL_ERROR_BASE + 118),
+ SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_CLIENTS = (SSL_ERROR_BASE + 119),
+
+ SSL_ERROR_INVALID_VERSION_RANGE = (SSL_ERROR_BASE + 120),
+ SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION = (SSL_ERROR_BASE + 121),
+
+ SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST = (SSL_ERROR_BASE + 122),
+ SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST = (SSL_ERROR_BASE + 123),
+
+ SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION = (SSL_ERROR_BASE + 124),
+
+ SSL_ERROR_RX_UNEXPECTED_CERT_STATUS = (SSL_ERROR_BASE + 125),
+
+ SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM = (SSL_ERROR_BASE + 126),
+ SSL_ERROR_DIGEST_FAILURE = (SSL_ERROR_BASE + 127),
+ SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 128),
+
+ SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK = (SSL_ERROR_BASE + 129),
+ SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL = (SSL_ERROR_BASE + 130),
+
+ SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT = (SSL_ERROR_BASE + 131),
+
+ SSL_ERROR_WEAK_SERVER_CERT_KEY = (SSL_ERROR_BASE + 132),
+
+ SSL_ERROR_RX_SHORT_DTLS_READ = (SSL_ERROR_BASE + 133),
+
+ SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 134),
+ SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 135),
+
+ SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET = (SSL_ERROR_BASE + 136),
+ SSL_ERROR_UNEXPECTED_EXTENDED_MASTER_SECRET = (SSL_ERROR_BASE + 137),
+
+ SSL_ERROR_RX_MALFORMED_KEY_SHARE = (SSL_ERROR_BASE + 138),
+ SSL_ERROR_MISSING_KEY_SHARE = (SSL_ERROR_BASE + 139),
+ SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE = (SSL_ERROR_BASE + 140),
+ SSL_ERROR_RX_MALFORMED_DHE_KEY_SHARE = (SSL_ERROR_BASE + 141),
+
+ SSL_ERROR_RX_UNEXPECTED_ENCRYPTED_EXTENSIONS = (SSL_ERROR_BASE + 142),
+ SSL_ERROR_MISSING_EXTENSION_ALERT = (SSL_ERROR_BASE + 143),
+
+ SSL_ERROR_KEY_EXCHANGE_FAILURE = (SSL_ERROR_BASE + 144),
+ SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION = (SSL_ERROR_BASE + 145),
+ SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS = (SSL_ERROR_BASE + 146),
+
+ SSL_ERROR_BAD_CHANNEL_ID_DATA = (SSL_ERROR_BASE + 147),
+ SSL_ERROR_INVALID_CHANNEL_ID_KEY = (SSL_ERROR_BASE + 148),
+ SSL_ERROR_GET_CHANNEL_ID_FAILED = (SSL_ERROR_BASE + 149),
+
+ SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
} SSLErrorCodes;
#endif /* NO_SECURITY_ERROR_ENUM */
+/* clang-format on */
+
#endif /* __SSL_ERR_H_ */
diff --git a/chromium/net/third_party/nss/ssl/sslerrstrs.c b/chromium/net/third_party/nss/ssl/sslerrstrs.c
index 34f4ea9b9d8..4e3db6d73c3 100644
--- a/chromium/net/third_party/nss/ssl/sslerrstrs.c
+++ b/chromium/net/third_party/nss/ssl/sslerrstrs.c
@@ -7,20 +7,21 @@
#include "nssutil.h"
#include "ssl.h"
-#define ER3(name, value, str) {#name, str},
+#define ER3(name, value, str) { #name, str },
static const struct PRErrorMessage ssltext[] = {
#include "SSLerrs.h"
- {0,0}
+ { 0, 0 }
};
static const struct PRErrorTable ssl_et = {
ssltext, "sslerr", SSL_ERROR_BASE,
- (sizeof ssltext)/(sizeof ssltext[0])
+ (sizeof ssltext) / (sizeof ssltext[0])
};
static PRStatus
-ssl_InitializePRErrorTableOnce(void) {
+ssl_InitializePRErrorTableOnce(void)
+{
return PR_ErrorInstallTable(&ssl_et);
}
@@ -30,5 +31,6 @@ SECStatus
ssl_InitializePRErrorTable(void)
{
return (PR_SUCCESS == PR_CallOnce(&once, ssl_InitializePRErrorTableOnce))
- ? SECSuccess : SECFailure;
+ ? SECSuccess
+ : SECFailure;
}
diff --git a/chromium/net/third_party/nss/ssl/sslgathr.c b/chromium/net/third_party/nss/ssl/sslgathr.c
index bdf470b0cf0..48d615ec0de 100644
--- a/chromium/net/third_party/nss/ssl/sslgathr.c
+++ b/chromium/net/third_party/nss/ssl/sslgathr.c
@@ -1,5 +1,5 @@
/*
- * Gather (Read) entire SSL2 records from socket into buffer.
+ * Gather (Read) entire SSL2 records from socket into buffer.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -20,7 +20,7 @@ static SECStatus ssl2_HandleV3HandshakeRecord(sslSocket *ss);
** and is to be called multiple times until ss->sec.recordLen != 0.
** This function decrypts the gathered record in place, in gs_buf.
*
- * Caller must hold RecvBufLock.
+ * Caller must hold RecvBufLock.
*
* Returns +1 when it has gathered a complete SSLV2 record.
* Returns 0 if it hits EOF.
@@ -41,7 +41,7 @@ static SECStatus ssl2_HandleV3HandshakeRecord(sslSocket *ss);
** advance to one of two states, depending on whether the record
** is encrypted (GS_MAC), or unencrypted (GS_DATA).
**
-** GS_MAC - The machine is in this state while waiting for the remainder
+** GS_MAC - The machine is in this state while waiting for the remainder
** of the SSL2 record to be read in. When the read is completed,
** the machine checks the record for valid length, decrypts it,
** and checks and discards the MAC, then advances to GS_INIT.
@@ -50,295 +50,291 @@ static SECStatus ssl2_HandleV3HandshakeRecord(sslSocket *ss);
** of the unencrypted SSL2 record to be read in. Upon completion,
** the machine advances to the GS_INIT state and returns the data.
*/
-int
+int
ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
{
- unsigned char * bp;
- unsigned char * pBuf;
- int nb, err, rv;
+ unsigned char *bp;
+ unsigned char *pBuf;
+ int nb, err, rv;
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
if (gs->state == GS_INIT) {
- /* Initialize gathering engine */
- gs->state = GS_HEADER;
- gs->remainder = 3;
- gs->count = 3;
- gs->offset = 0;
- gs->recordLen = 0;
- gs->recordPadding = 0;
- gs->hdr[2] = 0;
-
- gs->writeOffset = 0;
- gs->readOffset = 0;
+ /* Initialize gathering engine */
+ gs->state = GS_HEADER;
+ gs->remainder = 3;
+ gs->count = 3;
+ gs->offset = 0;
+ gs->recordLen = 0;
+ gs->recordPadding = 0;
+ gs->hdr[2] = 0;
+
+ gs->writeOffset = 0;
+ gs->readOffset = 0;
}
if (gs->encrypted) {
- PORT_Assert(ss->sec.hash != 0);
+ PORT_Assert(ss->sec.hash != 0);
}
pBuf = gs->buf.buf;
for (;;) {
- SSL_TRC(30, ("%d: SSL[%d]: gather state %d (need %d more)",
- SSL_GETPID(), ss->fd, gs->state, gs->remainder));
- bp = ((gs->state != GS_HEADER) ? pBuf : gs->hdr) + gs->offset;
- nb = ssl_DefRecv(ss, bp, gs->remainder, flags);
- if (nb > 0) {
- PRINT_BUF(60, (ss, "raw gather data:", bp, nb));
- }
- if (nb == 0) {
- /* EOF */
- SSL_TRC(30, ("%d: SSL[%d]: EOF", SSL_GETPID(), ss->fd));
- rv = 0;
- break;
- }
- if (nb < 0) {
- SSL_DBG(("%d: SSL[%d]: recv error %d", SSL_GETPID(), ss->fd,
- PR_GetError()));
- rv = SECFailure;
- break;
- }
-
- gs->offset += nb;
- gs->remainder -= nb;
-
- if (gs->remainder > 0) {
- continue;
- }
-
- /* Probably finished this piece */
- switch (gs->state) {
- case GS_HEADER:
- if (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange) && !ss->firstHsDone) {
-
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
-
- /* If this looks like an SSL3 handshake record,
- ** and we're expecting an SSL2 Hello message from our peer,
- ** handle it here.
- */
- if (gs->hdr[0] == content_handshake) {
- if ((ss->nextHandshake == ssl2_HandleClientHelloMessage) ||
- (ss->nextHandshake == ssl2_HandleServerHelloMessage)) {
- rv = ssl2_HandleV3HandshakeRecord(ss);
- if (rv == SECFailure) {
- return SECFailure;
- }
- }
- /* XXX_1 The call stack to here is:
- * ssl_Do1stHandshake -> ssl_GatherRecord1stHandshake ->
- * ssl2_GatherRecord -> here.
- * We want to return all the way out to ssl_Do1stHandshake,
- * and have it call ssl_GatherRecord1stHandshake again.
- * ssl_GatherRecord1stHandshake will call
- * ssl3_GatherCompleteHandshake when it is called again.
- *
- * Returning SECWouldBlock here causes
- * ssl_GatherRecord1stHandshake to return without clearing
- * ss->handshake, ensuring that ssl_Do1stHandshake will
- * call it again immediately.
- *
- * If we return 1 here, ssl_GatherRecord1stHandshake will
- * clear ss->handshake before returning, and thus will not
- * be called again by ssl_Do1stHandshake.
- */
- return SECWouldBlock;
- } else if (gs->hdr[0] == content_alert) {
- if (ss->nextHandshake == ssl2_HandleServerHelloMessage) {
- /* XXX This is a hack. We're assuming that any failure
- * XXX on the client hello is a failure to match
- * XXX ciphers.
- */
- PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
- return SECFailure;
- }
- }
- }
-
- /* we've got the first 3 bytes. The header may be two or three. */
- if (gs->hdr[0] & 0x80) {
- /* This record has a 2-byte header, and no padding */
- gs->count = ((gs->hdr[0] & 0x7f) << 8) | gs->hdr[1];
- gs->recordPadding = 0;
- } else {
- /* This record has a 3-byte header that is all read in now. */
- gs->count = ((gs->hdr[0] & 0x3f) << 8) | gs->hdr[1];
- /* is_escape = (gs->hdr[0] & 0x40) != 0; */
- gs->recordPadding = gs->hdr[2];
- }
- if (!gs->count) {
- PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
- goto cleanup;
- }
-
- if (gs->count > gs->buf.space) {
- err = sslBuffer_Grow(&gs->buf, gs->count);
- if (err) {
- return err;
- }
- pBuf = gs->buf.buf;
- }
-
-
- if (gs->hdr[0] & 0x80) {
- /* we've already read in the first byte of the body.
- ** Put it into the buffer.
- */
- pBuf[0] = gs->hdr[2];
- gs->offset = 1;
- gs->remainder = gs->count - 1;
- } else {
- gs->offset = 0;
- gs->remainder = gs->count;
- }
-
- if (gs->encrypted) {
- gs->state = GS_MAC;
- gs->recordLen = gs->count - gs->recordPadding
- - ss->sec.hash->length;
- } else {
- gs->state = GS_DATA;
- gs->recordLen = gs->count;
- }
-
- break;
-
-
- case GS_MAC:
- /* Have read in entire rest of the ciphertext.
- ** Check for valid length.
- ** Decrypt it.
- ** Check the MAC.
- */
- PORT_Assert(gs->encrypted);
-
- {
- unsigned int macLen;
- int nout;
- unsigned char mac[SSL_MAX_MAC_BYTES];
-
- ssl_GetSpecReadLock(ss); /**********************************/
-
- /* If this is a stream cipher, blockSize will be 1,
- * and this test will always be false.
- * If this is a block cipher, this will detect records
- * that are not a multiple of the blocksize in length.
- */
- if (gs->count & (ss->sec.blockSize - 1)) {
- /* This is an error. Sender is misbehaving */
- SSL_DBG(("%d: SSL[%d]: sender, count=%d blockSize=%d",
- SSL_GETPID(), ss->fd, gs->count,
- ss->sec.blockSize));
- PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING);
- rv = SECFailure;
- goto spec_locked_done;
- }
- PORT_Assert(gs->count == gs->offset);
-
- if (gs->offset == 0) {
- rv = 0; /* means EOF. */
- goto spec_locked_done;
- }
-
- /* Decrypt the portion of data that we just received.
- ** Decrypt it in place.
- */
- rv = (*ss->sec.dec)(ss->sec.readcx, pBuf, &nout, gs->offset,
- pBuf, gs->offset);
- if (rv != SECSuccess) {
- goto spec_locked_done;
- }
-
-
- /* Have read in all the MAC portion of record
- **
- ** Prepare MAC by resetting it and feeding it the shared secret
- */
- macLen = ss->sec.hash->length;
- if (gs->offset >= macLen) {
- PRUint32 sequenceNumber = ss->sec.rcvSequence++;
- unsigned char seq[4];
-
- seq[0] = (unsigned char) (sequenceNumber >> 24);
- seq[1] = (unsigned char) (sequenceNumber >> 16);
- seq[2] = (unsigned char) (sequenceNumber >> 8);
- seq[3] = (unsigned char) (sequenceNumber);
-
- (*ss->sec.hash->begin)(ss->sec.hashcx);
- (*ss->sec.hash->update)(ss->sec.hashcx, ss->sec.rcvSecret.data,
- ss->sec.rcvSecret.len);
- (*ss->sec.hash->update)(ss->sec.hashcx, pBuf + macLen,
- gs->offset - macLen);
- (*ss->sec.hash->update)(ss->sec.hashcx, seq, 4);
- (*ss->sec.hash->end)(ss->sec.hashcx, mac, &macLen, macLen);
-
- PORT_Assert(macLen == ss->sec.hash->length);
-
- ssl_ReleaseSpecReadLock(ss); /******************************/
-
- if (NSS_SecureMemcmp(mac, pBuf, macLen) != 0) {
- /* MAC's didn't match... */
- SSL_DBG(("%d: SSL[%d]: mac check failed, seq=%d",
- SSL_GETPID(), ss->fd, ss->sec.rcvSequence));
- PRINT_BUF(1, (ss, "computed mac:", mac, macLen));
- PRINT_BUF(1, (ss, "received mac:", pBuf, macLen));
- PORT_SetError(SSL_ERROR_BAD_MAC_READ);
- rv = SECFailure;
- goto cleanup;
- }
- } else {
- ssl_ReleaseSpecReadLock(ss); /******************************/
- }
-
- if (gs->recordPadding + macLen <= gs->offset) {
- gs->recordOffset = macLen;
- gs->readOffset = macLen;
- gs->writeOffset = gs->offset - gs->recordPadding;
- rv = 1;
- } else {
- PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING);
-cleanup:
- /* nothing in the buffer any more. */
- gs->recordOffset = 0;
- gs->readOffset = 0;
- gs->writeOffset = 0;
- rv = SECFailure;
- }
-
- gs->recordLen = gs->writeOffset - gs->readOffset;
- gs->recordPadding = 0; /* forget we did any padding. */
- gs->state = GS_INIT;
-
-
- if (rv > 0) {
- PRINT_BUF(50, (ss, "recv clear record:",
- pBuf + gs->recordOffset, gs->recordLen));
- }
- return rv;
-
-spec_locked_done:
- ssl_ReleaseSpecReadLock(ss);
- return rv;
- }
-
- case GS_DATA:
- /* Have read in all the DATA portion of record */
-
- gs->recordOffset = 0;
- gs->readOffset = 0;
- gs->writeOffset = gs->offset;
- PORT_Assert(gs->recordLen == gs->writeOffset - gs->readOffset);
- gs->recordLen = gs->offset;
- gs->recordPadding = 0;
- gs->state = GS_INIT;
-
- ++ss->sec.rcvSequence;
-
- PRINT_BUF(50, (ss, "recv clear record:",
- pBuf + gs->recordOffset, gs->recordLen));
- return 1;
-
- } /* end switch gs->state */
- } /* end gather loop. */
+ SSL_TRC(30, ("%d: SSL[%d]: gather state %d (need %d more)",
+ SSL_GETPID(), ss->fd, gs->state, gs->remainder));
+ bp = ((gs->state != GS_HEADER) ? pBuf : gs->hdr) + gs->offset;
+ nb = ssl_DefRecv(ss, bp, gs->remainder, flags);
+ if (nb > 0) {
+ PRINT_BUF(60, (ss, "raw gather data:", bp, nb));
+ }
+ if (nb == 0) {
+ /* EOF */
+ SSL_TRC(30, ("%d: SSL[%d]: EOF", SSL_GETPID(), ss->fd));
+ rv = 0;
+ break;
+ }
+ if (nb < 0) {
+ SSL_DBG(("%d: SSL[%d]: recv error %d", SSL_GETPID(), ss->fd,
+ PR_GetError()));
+ rv = SECFailure;
+ break;
+ }
+
+ gs->offset += nb;
+ gs->remainder -= nb;
+
+ if (gs->remainder > 0) {
+ continue;
+ }
+
+ /* Probably finished this piece */
+ switch (gs->state) {
+ case GS_HEADER:
+ if (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange) && !ss->firstHsDone) {
+
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
+
+ /* If this looks like an SSL3 handshake record,
+ ** and we're expecting an SSL2 Hello message from our peer,
+ ** handle it here.
+ */
+ if (gs->hdr[0] == content_handshake) {
+ if ((ss->nextHandshake == ssl2_HandleClientHelloMessage) ||
+ (ss->nextHandshake == ssl2_HandleServerHelloMessage)) {
+ rv = ssl2_HandleV3HandshakeRecord(ss);
+ if (rv == SECFailure) {
+ return SECFailure;
+ }
+ }
+ /* XXX_1 The call stack to here is:
+ * ssl_Do1stHandshake -> ssl_GatherRecord1stHandshake ->
+ * ssl2_GatherRecord -> here.
+ * We want to return all the way out to ssl_Do1stHandshake,
+ * and have it call ssl_GatherRecord1stHandshake again.
+ * ssl_GatherRecord1stHandshake will call
+ * ssl3_GatherCompleteHandshake when it is called again.
+ *
+ * Returning SECWouldBlock here causes
+ * ssl_GatherRecord1stHandshake to return without clearing
+ * ss->handshake, ensuring that ssl_Do1stHandshake will
+ * call it again immediately.
+ *
+ * If we return 1 here, ssl_GatherRecord1stHandshake will
+ * clear ss->handshake before returning, and thus will not
+ * be called again by ssl_Do1stHandshake.
+ */
+ return SECWouldBlock;
+ } else if (gs->hdr[0] == content_alert) {
+ if (ss->nextHandshake == ssl2_HandleServerHelloMessage) {
+ /* XXX This is a hack. We're assuming that any failure
+ * XXX on the client hello is a failure to match
+ * XXX ciphers.
+ */
+ PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
+ return SECFailure;
+ }
+ }
+ }
+
+ /* we've got the first 3 bytes. The header may be two or three. */
+ if (gs->hdr[0] & 0x80) {
+ /* This record has a 2-byte header, and no padding */
+ gs->count = ((gs->hdr[0] & 0x7f) << 8) | gs->hdr[1];
+ gs->recordPadding = 0;
+ } else {
+ /* This record has a 3-byte header that is all read in now. */
+ gs->count = ((gs->hdr[0] & 0x3f) << 8) | gs->hdr[1];
+ /* is_escape = (gs->hdr[0] & 0x40) != 0; */
+ gs->recordPadding = gs->hdr[2];
+ }
+ if (!gs->count) {
+ PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
+ goto cleanup;
+ }
+
+ if (gs->count > gs->buf.space) {
+ err = sslBuffer_Grow(&gs->buf, gs->count);
+ if (err) {
+ return err;
+ }
+ pBuf = gs->buf.buf;
+ }
+
+ if (gs->hdr[0] & 0x80) {
+ /* we've already read in the first byte of the body.
+ ** Put it into the buffer.
+ */
+ pBuf[0] = gs->hdr[2];
+ gs->offset = 1;
+ gs->remainder = gs->count - 1;
+ } else {
+ gs->offset = 0;
+ gs->remainder = gs->count;
+ }
+
+ if (gs->encrypted) {
+ gs->state = GS_MAC;
+ gs->recordLen = gs->count - gs->recordPadding -
+ ss->sec.hash->length;
+ } else {
+ gs->state = GS_DATA;
+ gs->recordLen = gs->count;
+ }
+
+ break;
+
+ case GS_MAC:
+ /* Have read in entire rest of the ciphertext.
+ ** Check for valid length.
+ ** Decrypt it.
+ ** Check the MAC.
+ */
+ PORT_Assert(gs->encrypted);
+
+ {
+ unsigned int macLen;
+ int nout;
+ unsigned char mac[SSL_MAX_MAC_BYTES];
+
+ ssl_GetSpecReadLock(ss); /**********************************/
+
+ /* If this is a stream cipher, blockSize will be 1,
+ * and this test will always be false.
+ * If this is a block cipher, this will detect records
+ * that are not a multiple of the blocksize in length.
+ */
+ if (gs->count & (ss->sec.blockSize - 1)) {
+ /* This is an error. Sender is misbehaving */
+ SSL_DBG(("%d: SSL[%d]: sender, count=%d blockSize=%d",
+ SSL_GETPID(), ss->fd, gs->count,
+ ss->sec.blockSize));
+ PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING);
+ rv = SECFailure;
+ goto spec_locked_done;
+ }
+ PORT_Assert(gs->count == gs->offset);
+
+ if (gs->offset == 0) {
+ rv = 0; /* means EOF. */
+ goto spec_locked_done;
+ }
+
+ /* Decrypt the portion of data that we just received.
+ ** Decrypt it in place.
+ */
+ rv = (*ss->sec.dec)(ss->sec.readcx, pBuf, &nout, gs->offset,
+ pBuf, gs->offset);
+ if (rv != SECSuccess) {
+ goto spec_locked_done;
+ }
+
+ /* Have read in all the MAC portion of record
+ **
+ ** Prepare MAC by resetting it and feeding it the shared secret
+ */
+ macLen = ss->sec.hash->length;
+ if (gs->offset >= macLen) {
+ PRUint32 sequenceNumber = ss->sec.rcvSequence++;
+ unsigned char seq[4];
+
+ seq[0] = (unsigned char)(sequenceNumber >> 24);
+ seq[1] = (unsigned char)(sequenceNumber >> 16);
+ seq[2] = (unsigned char)(sequenceNumber >> 8);
+ seq[3] = (unsigned char)(sequenceNumber);
+
+ (*ss->sec.hash->begin)(ss->sec.hashcx);
+ (*ss->sec.hash->update)(ss->sec.hashcx, ss->sec.rcvSecret.data,
+ ss->sec.rcvSecret.len);
+ (*ss->sec.hash->update)(ss->sec.hashcx, pBuf + macLen,
+ gs->offset - macLen);
+ (*ss->sec.hash->update)(ss->sec.hashcx, seq, 4);
+ (*ss->sec.hash->end)(ss->sec.hashcx, mac, &macLen, macLen);
+
+ PORT_Assert(macLen == ss->sec.hash->length);
+
+ ssl_ReleaseSpecReadLock(ss); /******************************/
+
+ if (NSS_SecureMemcmp(mac, pBuf, macLen) != 0) {
+ /* MAC's didn't match... */
+ SSL_DBG(("%d: SSL[%d]: mac check failed, seq=%d",
+ SSL_GETPID(), ss->fd, ss->sec.rcvSequence));
+ PRINT_BUF(1, (ss, "computed mac:", mac, macLen));
+ PRINT_BUF(1, (ss, "received mac:", pBuf, macLen));
+ PORT_SetError(SSL_ERROR_BAD_MAC_READ);
+ rv = SECFailure;
+ goto cleanup;
+ }
+ } else {
+ ssl_ReleaseSpecReadLock(ss); /******************************/
+ }
+
+ if (gs->recordPadding + macLen <= gs->offset) {
+ gs->recordOffset = macLen;
+ gs->readOffset = macLen;
+ gs->writeOffset = gs->offset - gs->recordPadding;
+ rv = 1;
+ } else {
+ PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING);
+ cleanup:
+ /* nothing in the buffer any more. */
+ gs->recordOffset = 0;
+ gs->readOffset = 0;
+ gs->writeOffset = 0;
+ rv = SECFailure;
+ }
+
+ gs->recordLen = gs->writeOffset - gs->readOffset;
+ gs->recordPadding = 0; /* forget we did any padding. */
+ gs->state = GS_INIT;
+
+ if (rv > 0) {
+ PRINT_BUF(50, (ss, "recv clear record:",
+ pBuf + gs->recordOffset, gs->recordLen));
+ }
+ return rv;
+
+ spec_locked_done:
+ ssl_ReleaseSpecReadLock(ss);
+ return rv;
+ }
+
+ case GS_DATA:
+ /* Have read in all the DATA portion of record */
+
+ gs->recordOffset = 0;
+ gs->readOffset = 0;
+ gs->writeOffset = gs->offset;
+ PORT_Assert(gs->recordLen == gs->writeOffset - gs->readOffset);
+ gs->recordLen = gs->offset;
+ gs->recordPadding = 0;
+ gs->state = GS_INIT;
+
+ ++ss->sec.rcvSequence;
+
+ PRINT_BUF(50, (ss, "recv clear record:",
+ pBuf + gs->recordOffset, gs->recordLen));
+ return 1;
+
+ } /* end switch gs->state */
+ } /* end gather loop. */
return rv;
}
@@ -352,13 +348,13 @@ spec_locked_done:
* Returns +1 when it has gathered a complete SSLV2 record.
* Returns 0 if it hits EOF.
* Returns -1 (SECFailure) on any error
- * Returns -2 (SECWouldBlock)
+ * Returns -2 (SECWouldBlock)
*
- * Called by ssl_GatherRecord1stHandshake in sslcon.c,
+ * Called by ssl_GatherRecord1stHandshake in sslcon.c,
* and by DoRecv in sslsecur.c
* Caller must hold RecvBufLock.
*/
-int
+int
ssl2_GatherRecord(sslSocket *ss, int flags)
{
return ssl2_GatherData(ss, &ss->gs, flags);
@@ -372,7 +368,7 @@ ssl_InitGather(sslGather *gs)
gs->state = GS_INIT;
gs->writeOffset = 0;
- gs->readOffset = 0;
+ gs->readOffset = 0;
gs->dtlsPacketOffset = 0;
gs->dtlsPacket.len = 0;
status = sslBuffer_Grow(&gs->buf, 4096);
@@ -380,13 +376,13 @@ ssl_InitGather(sslGather *gs)
}
/* Caller must hold RecvBufLock. */
-void
+void
ssl_DestroyGather(sslGather *gs)
{
- if (gs) { /* the PORT_*Free functions check for NULL pointers. */
- PORT_ZFree(gs->buf.buf, gs->buf.space);
- PORT_Free(gs->inbuf.buf);
- PORT_Free(gs->dtlsPacket.buf);
+ if (gs) { /* the PORT_*Free functions check for NULL pointers. */
+ PORT_ZFree(gs->buf.buf, gs->buf.space);
+ PORT_Free(gs->inbuf.buf);
+ PORT_Free(gs->dtlsPacket.buf);
}
}
@@ -394,32 +390,32 @@ ssl_DestroyGather(sslGather *gs)
static SECStatus
ssl2_HandleV3HandshakeRecord(sslSocket *ss)
{
- SECStatus rv;
+ SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
/* We've read in 3 bytes, there are 2 more to go in an ssl3 header. */
- ss->gs.remainder = 2;
- ss->gs.count = 0;
+ ss->gs.remainder = 2;
+ ss->gs.count = 0;
- /* Clearing these handshake pointers ensures that
+ /* Clearing these handshake pointers ensures that
* ssl_Do1stHandshake won't call ssl2_HandleMessage when we return.
*/
- ss->nextHandshake = 0;
+ ss->nextHandshake = 0;
ss->securityHandshake = 0;
- /* Setting ss->version to an SSL 3.x value will cause
- ** ssl_GatherRecord1stHandshake to invoke ssl3_GatherCompleteHandshake()
+ /* Setting ss->version to an SSL 3.x value will cause
+ ** ssl_GatherRecord1stHandshake to invoke ssl3_GatherCompleteHandshake()
** the next time it is called.
**/
rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED,
- PR_TRUE);
+ PR_TRUE);
if (rv != SECSuccess) {
- return rv;
+ return rv;
}
- ss->sec.send = ssl3_SendApplicationData;
+ ss->sec.send = ssl3_SendApplicationData;
return SECSuccess;
}
diff --git a/chromium/net/third_party/nss/ssl/sslimpl.h b/chromium/net/third_party/nss/ssl/sslimpl.h
index 874e59c6223..f56ab53c32b 100644
--- a/chromium/net/third_party/nss/ssl/sslimpl.h
+++ b/chromium/net/third_party/nss/ssl/sslimpl.h
@@ -21,7 +21,6 @@
#include "sslerr.h"
#include "ssl3prot.h"
#include "hasht.h"
-#include "keythi.h"
#include "nssilock.h"
#include "pkcs11t.h"
#if defined(XP_UNIX) || defined(XP_BEOS)
@@ -33,53 +32,38 @@
#include "sslt.h" /* for some formerly private types, now public */
-#ifdef NSS_PLATFORM_CLIENT_AUTH
-#if defined(XP_WIN32)
-#include <windows.h>
-#include <wincrypt.h>
-#elif defined(XP_MACOSX)
-#include <Security/Security.h>
-#endif
-#endif
-
/* to make some of these old enums public without namespace pollution,
** it was necessary to prepend ssl_ to the names.
** These #defines preserve compatibility with the old code here in libssl.
*/
-typedef SSLKEAType SSL3KEAType;
+typedef SSLKEAType SSL3KEAType;
typedef SSLMACAlgorithm SSL3MACAlgorithm;
-typedef SSLSignType SSL3SignType;
-
-#define sign_null ssl_sign_null
-#define sign_rsa ssl_sign_rsa
-#define sign_dsa ssl_sign_dsa
-#define sign_ecdsa ssl_sign_ecdsa
-
-#define calg_null ssl_calg_null
-#define calg_rc4 ssl_calg_rc4
-#define calg_rc2 ssl_calg_rc2
-#define calg_des ssl_calg_des
-#define calg_3des ssl_calg_3des
-#define calg_idea ssl_calg_idea
-#define calg_fortezza ssl_calg_fortezza /* deprecated, must preserve */
-#define calg_aes ssl_calg_aes
-#define calg_camellia ssl_calg_camellia
-#define calg_seed ssl_calg_seed
-#define calg_aes_gcm ssl_calg_aes_gcm
-#define calg_chacha20 ssl_calg_chacha20
-
-#define mac_null ssl_mac_null
-#define mac_md5 ssl_mac_md5
-#define mac_sha ssl_mac_sha
-#define hmac_md5 ssl_hmac_md5
-#define hmac_sha ssl_hmac_sha
-#define hmac_sha256 ssl_hmac_sha256
-#define mac_aead ssl_mac_aead
-
-#define SET_ERROR_CODE /* reminder */
-#define SEND_ALERT /* reminder */
-#define TEST_FOR_FAILURE /* reminder */
-#define DEAL_WITH_FAILURE /* reminder */
+
+#define calg_null ssl_calg_null
+#define calg_rc4 ssl_calg_rc4
+#define calg_rc2 ssl_calg_rc2
+#define calg_des ssl_calg_des
+#define calg_3des ssl_calg_3des
+#define calg_idea ssl_calg_idea
+#define calg_fortezza ssl_calg_fortezza /* deprecated, must preserve */
+#define calg_aes ssl_calg_aes
+#define calg_camellia ssl_calg_camellia
+#define calg_seed ssl_calg_seed
+#define calg_aes_gcm ssl_calg_aes_gcm
+#define calg_chacha20 ssl_calg_chacha20
+
+#define mac_null ssl_mac_null
+#define mac_md5 ssl_mac_md5
+#define mac_sha ssl_mac_sha
+#define hmac_md5 ssl_hmac_md5
+#define hmac_sha ssl_hmac_sha
+#define hmac_sha256 ssl_hmac_sha256
+#define mac_aead ssl_mac_aead
+
+#define SET_ERROR_CODE /* reminder */
+#define SEND_ALERT /* reminder */
+#define TEST_FOR_FAILURE /* reminder */
+#define DEAL_WITH_FAILURE /* reminder */
#if defined(DEBUG) || defined(TRACE)
#ifdef __cplusplus
@@ -96,63 +80,71 @@ extern int Debug;
#endif
#ifdef TRACE
-#define SSL_TRC(a,b) if (ssl_trace >= (a)) ssl_Trace b
-#define PRINT_BUF(a,b) if (ssl_trace >= (a)) ssl_PrintBuf b
-#define DUMP_MSG(a,b) if (ssl_trace >= (a)) ssl_DumpMsg b
+#define SSL_TRC(a, b) \
+ if (ssl_trace >= (a)) \
+ ssl_Trace b
+#define PRINT_BUF(a, b) \
+ if (ssl_trace >= (a)) \
+ ssl_PrintBuf b
+#define DUMP_MSG(a, b) \
+ if (ssl_trace >= (a)) \
+ ssl_DumpMsg b
#else
-#define SSL_TRC(a,b)
-#define PRINT_BUF(a,b)
-#define DUMP_MSG(a,b)
+#define SSL_TRC(a, b)
+#define PRINT_BUF(a, b)
+#define DUMP_MSG(a, b)
#endif
#ifdef DEBUG
-#define SSL_DBG(b) if (ssl_debug) ssl_Trace b
+#define SSL_DBG(b) \
+ if (ssl_debug) \
+ ssl_Trace b
#else
#define SSL_DBG(b)
#endif
-#include "private/pprthred.h" /* for PR_InMonitor() */
+#include "private/pprthred.h" /* for PR_InMonitor() */
#define ssl_InMonitor(m) PZ_InMonitor(m)
-#define LSB(x) ((unsigned char) ((x) & 0xff))
-#define MSB(x) ((unsigned char) (((unsigned)(x)) >> 8))
+#define LSB(x) ((unsigned char)((x)&0xff))
+#define MSB(x) ((unsigned char)(((unsigned)(x)) >> 8))
/************************************************************************/
typedef enum { SSLAppOpRead = 0,
- SSLAppOpWrite,
- SSLAppOpRDWR,
- SSLAppOpPost,
- SSLAppOpHeader
+ SSLAppOpWrite,
+ SSLAppOpRDWR,
+ SSLAppOpPost,
+ SSLAppOpHeader
} SSLAppOperation;
-#define SSL_MIN_MASTER_KEY_BYTES 5
-#define SSL_MAX_MASTER_KEY_BYTES 64
+#define SSL_MIN_MASTER_KEY_BYTES 5
+#define SSL_MAX_MASTER_KEY_BYTES 64
-#define SSL2_SESSIONID_BYTES 16
-#define SSL3_SESSIONID_BYTES 32
+#define SSL2_SESSIONID_BYTES 16
+#define SSL3_SESSIONID_BYTES 32
-#define SSL_MIN_CHALLENGE_BYTES 16
-#define SSL_MAX_CHALLENGE_BYTES 32
-#define SSL_CHALLENGE_BYTES 16
+#define SSL_MIN_CHALLENGE_BYTES 16
+#define SSL_MAX_CHALLENGE_BYTES 32
+#define SSL_CHALLENGE_BYTES 16
-#define SSL_CONNECTIONID_BYTES 16
+#define SSL_CONNECTIONID_BYTES 16
-#define SSL_MIN_CYPHER_ARG_BYTES 0
-#define SSL_MAX_CYPHER_ARG_BYTES 32
+#define SSL_MIN_CYPHER_ARG_BYTES 0
+#define SSL_MAX_CYPHER_ARG_BYTES 32
-#define SSL_MAX_MAC_BYTES 16
+#define SSL_MAX_MAC_BYTES 16
#define SSL3_RSA_PMS_LENGTH 48
#define SSL3_MASTER_SECRET_LENGTH 48
/* number of wrap mechanisms potentially used to wrap master secrets. */
-#define SSL_NUM_WRAP_MECHS 16
+#define SSL_NUM_WRAP_MECHS 16
/* This makes the cert cache entry exactly 4k. */
-#define SSL_MAX_CACHED_CERT_LEN 4060
+#define SSL_MAX_CACHED_CERT_LEN 4060
-#define NUM_MIXERS 9
+#define NUM_MIXERS 9
/* Mask of the 25 named curves we support. */
#define SSL3_ALL_SUPPORTED_CURVES_MASK 0x3fffffe
@@ -163,77 +155,77 @@ typedef enum { SSLAppOpRead = 0,
#define BPB 8 /* Bits Per Byte */
#endif
-#define EXPORT_RSA_KEY_LENGTH 64 /* bytes */
+#define EXPORT_RSA_KEY_LENGTH 64 /* bytes */
-#define INITIAL_DTLS_TIMEOUT_MS 1000 /* Default value from RFC 4347 = 1s*/
-#define MAX_DTLS_TIMEOUT_MS 60000 /* 1 minute */
-#define DTLS_FINISHED_TIMER_MS 120000 /* Time to wait in FINISHED state */
+#define INITIAL_DTLS_TIMEOUT_MS 1000 /* Default value from RFC 4347 = 1s*/
+#define MAX_DTLS_TIMEOUT_MS 60000 /* 1 minute */
+#define DTLS_FINISHED_TIMER_MS 120000 /* Time to wait in FINISHED state */
-typedef struct sslBufferStr sslBuffer;
-typedef struct sslConnectInfoStr sslConnectInfo;
-typedef struct sslGatherStr sslGather;
-typedef struct sslSecurityInfoStr sslSecurityInfo;
-typedef struct sslSessionIDStr sslSessionID;
-typedef struct sslSocketStr sslSocket;
-typedef struct sslSocketOpsStr sslSocketOps;
+typedef struct sslBufferStr sslBuffer;
+typedef struct sslConnectInfoStr sslConnectInfo;
+typedef struct sslGatherStr sslGather;
+typedef struct sslSecurityInfoStr sslSecurityInfo;
+typedef struct sslSessionIDStr sslSessionID;
+typedef struct sslSocketStr sslSocket;
+typedef struct sslSocketOpsStr sslSocketOps;
-typedef struct ssl3StateStr ssl3State;
-typedef struct ssl3CertNodeStr ssl3CertNode;
-typedef struct ssl3BulkCipherDefStr ssl3BulkCipherDef;
-typedef struct ssl3MACDefStr ssl3MACDef;
-typedef struct ssl3KeyPairStr ssl3KeyPair;
-typedef struct ssl3DHParamsStr ssl3DHParams;
+typedef struct ssl3StateStr ssl3State;
+typedef struct ssl3CertNodeStr ssl3CertNode;
+typedef struct ssl3BulkCipherDefStr ssl3BulkCipherDef;
+typedef struct ssl3MACDefStr ssl3MACDef;
+typedef struct ssl3KeyPairStr ssl3KeyPair;
+typedef struct ssl3DHParamsStr ssl3DHParams;
struct ssl3CertNodeStr {
struct ssl3CertNodeStr *next;
- CERTCertificate * cert;
+ CERTCertificate *cert;
};
typedef SECStatus (*sslHandshakeFunc)(sslSocket *ss);
-/* This type points to the low layer send func,
+/* This type points to the low layer send func,
** e.g. ssl2_SendStream or ssl3_SendPlainText.
-** These functions return the same values as PR_Send,
+** These functions return the same values as PR_Send,
** i.e. >= 0 means number of bytes sent, < 0 means error.
*/
-typedef PRInt32 (*sslSendFunc)(sslSocket *ss, const unsigned char *buf,
- PRInt32 n, PRInt32 flags);
+typedef PRInt32 (*sslSendFunc)(sslSocket *ss, const unsigned char *buf,
+ PRInt32 n, PRInt32 flags);
-typedef void (*sslSessionIDCacheFunc) (sslSessionID *sid);
-typedef void (*sslSessionIDUncacheFunc)(sslSessionID *sid);
-typedef sslSessionID *(*sslSessionIDLookupFunc)(const PRIPv6Addr *addr,
- unsigned char* sid,
- unsigned int sidLen,
- CERTCertDBHandle * dbHandle);
+typedef void (*sslSessionIDCacheFunc)(sslSessionID *sid);
+typedef void (*sslSessionIDUncacheFunc)(sslSessionID *sid);
+typedef sslSessionID *(*sslSessionIDLookupFunc)(const PRIPv6Addr *addr,
+ unsigned char *sid,
+ unsigned int sidLen,
+ CERTCertDBHandle *dbHandle);
/* registerable callback function that either appends extension to buffer
* or returns length of data that it would have appended.
*/
typedef PRInt32 (*ssl3HelloExtensionSenderFunc)(sslSocket *ss, PRBool append,
- PRUint32 maxBytes);
+ PRUint32 maxBytes);
-/* registerable callback function that handles a received extension,
+/* registerable callback function that handles a received extension,
* of the given type.
*/
-typedef SECStatus (* ssl3HelloExtensionHandlerFunc)(sslSocket *ss,
- PRUint16 ex_type,
- SECItem * data);
+typedef SECStatus (*ssl3HelloExtensionHandlerFunc)(sslSocket *ss,
+ PRUint16 ex_type,
+ SECItem *data);
/* row in a table of hello extension senders */
typedef struct {
- PRInt32 ex_type;
+ PRInt32 ex_type;
ssl3HelloExtensionSenderFunc ex_sender;
} ssl3HelloExtensionSender;
/* row in a table of hello extension handlers */
typedef struct {
- PRInt32 ex_type;
+ PRInt32 ex_type;
ssl3HelloExtensionHandlerFunc ex_handler;
} ssl3HelloExtensionHandler;
-extern SECStatus
+extern SECStatus
ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type,
- ssl3HelloExtensionSenderFunc cb);
+ ssl3HelloExtensionSenderFunc cb);
extern PRInt32
ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
@@ -244,44 +236,44 @@ ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength);
extern PRInt32
ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
- PRUint32 maxBytes);
+ PRUint32 maxBytes);
/* Socket ops */
struct sslSocketOpsStr {
- int (*connect) (sslSocket *, const PRNetAddr *);
- PRFileDesc *(*accept) (sslSocket *, PRNetAddr *);
- int (*bind) (sslSocket *, const PRNetAddr *);
- int (*listen) (sslSocket *, int);
- int (*shutdown)(sslSocket *, int);
- int (*close) (sslSocket *);
+ int (*connect)(sslSocket *, const PRNetAddr *);
+ PRFileDesc *(*accept)(sslSocket *, PRNetAddr *);
+ int (*bind)(sslSocket *, const PRNetAddr *);
+ int (*listen)(sslSocket *, int);
+ int (*shutdown)(sslSocket *, int);
+ int (*close)(sslSocket *);
- int (*recv) (sslSocket *, unsigned char *, int, int);
+ int (*recv)(sslSocket *, unsigned char *, int, int);
/* points to the higher-layer send func, e.g. ssl_SecureSend. */
- int (*send) (sslSocket *, const unsigned char *, int, int);
- int (*read) (sslSocket *, unsigned char *, int);
- int (*write) (sslSocket *, const unsigned char *, int);
+ int (*send)(sslSocket *, const unsigned char *, int, int);
+ int (*read)(sslSocket *, unsigned char *, int);
+ int (*write)(sslSocket *, const unsigned char *, int);
- int (*getpeername)(sslSocket *, PRNetAddr *);
- int (*getsockname)(sslSocket *, PRNetAddr *);
+ int (*getpeername)(sslSocket *, PRNetAddr *);
+ int (*getsockname)(sslSocket *, PRNetAddr *);
};
/* Flags interpreted by ssl send functions. */
-#define ssl_SEND_FLAG_FORCE_INTO_BUFFER 0x40000000
-#define ssl_SEND_FLAG_NO_BUFFER 0x20000000
-#define ssl_SEND_FLAG_USE_EPOCH 0x10000000 /* DTLS only */
-#define ssl_SEND_FLAG_NO_RETRANSMIT 0x08000000 /* DTLS only */
+#define ssl_SEND_FLAG_FORCE_INTO_BUFFER 0x40000000
+#define ssl_SEND_FLAG_NO_BUFFER 0x20000000
+#define ssl_SEND_FLAG_USE_EPOCH 0x10000000 /* DTLS only */
+#define ssl_SEND_FLAG_NO_RETRANSMIT 0x08000000 /* DTLS only */
#define ssl_SEND_FLAG_CAP_RECORD_VERSION \
- 0x04000000 /* TLS only */
-#define ssl_SEND_FLAG_MASK 0x7f000000
+ 0x04000000 /* TLS only */
+#define ssl_SEND_FLAG_MASK 0x7f000000
/*
** A buffer object.
*/
struct sslBufferStr {
- unsigned char * buf;
- unsigned int len;
- unsigned int space;
+ unsigned char *buf;
+ unsigned int len;
+ unsigned int space;
};
/*
@@ -289,22 +281,22 @@ struct sslBufferStr {
*/
typedef struct {
#if !defined(_WIN32)
- unsigned int cipher_suite : 16;
- unsigned int policy : 8;
- unsigned int enabled : 1;
- unsigned int isPresent : 1;
+ unsigned int cipher_suite : 16;
+ unsigned int policy : 8;
+ unsigned int enabled : 1;
+ unsigned int isPresent : 1;
#else
ssl3CipherSuite cipher_suite;
- PRUint8 policy;
- unsigned char enabled : 1;
- unsigned char isPresent : 1;
+ PRUint8 policy;
+ unsigned char enabled : 1;
+ unsigned char isPresent : 1;
#endif
} ssl3CipherSuiteCfg;
#ifndef NSS_DISABLE_ECC
-#define ssl_V3_SUITES_IMPLEMENTED 66
+#define ssl_V3_SUITES_IMPLEMENTED 67
#else
-#define ssl_V3_SUITES_IMPLEMENTED 40
+#define ssl_V3_SUITES_IMPLEMENTED 41
#endif /* NSS_DISABLE_ECC */
#define MAX_DTLS_SRTP_CIPHER_SUITES 4
@@ -314,72 +306,73 @@ typedef struct {
* doesn't allow space for combinations with MD5). */
#define MAX_SIGNATURE_ALGORITHMS 15
-
+/* clang-format off */
typedef struct sslOptionsStr {
/* If SSL_SetNextProtoNego has been called, then this contains the
* list of supported protocols. */
SECItem nextProtoNego;
- unsigned int useSecurity : 1; /* 1 */
- unsigned int useSocks : 1; /* 2 */
- unsigned int requestCertificate : 1; /* 3 */
- unsigned int requireCertificate : 2; /* 4-5 */
- unsigned int handshakeAsClient : 1; /* 6 */
- unsigned int handshakeAsServer : 1; /* 7 */
- unsigned int enableSSL2 : 1; /* 8 */
- unsigned int unusedBit9 : 1; /* 9 */
- unsigned int unusedBit10 : 1; /* 10 */
- unsigned int noCache : 1; /* 11 */
- unsigned int fdx : 1; /* 12 */
- unsigned int v2CompatibleHello : 1; /* 13 */
- unsigned int detectRollBack : 1; /* 14 */
- unsigned int noStepDown : 1; /* 15 */
- unsigned int bypassPKCS11 : 1; /* 16 */
- unsigned int noLocks : 1; /* 17 */
- unsigned int enableSessionTickets : 1; /* 18 */
- unsigned int enableDeflate : 1; /* 19 */
- unsigned int enableRenegotiation : 2; /* 20-21 */
- unsigned int requireSafeNegotiation : 1; /* 22 */
- unsigned int enableFalseStart : 1; /* 23 */
- unsigned int cbcRandomIV : 1; /* 24 */
- unsigned int enableOCSPStapling : 1; /* 25 */
- unsigned int enableNPN : 1; /* 26 */
- unsigned int enableALPN : 1; /* 27 */
- unsigned int reuseServerECDHEKey : 1; /* 28 */
- unsigned int enableFallbackSCSV : 1; /* 29 */
- unsigned int enableServerDhe : 1; /* 30 */
- unsigned int enableExtendedMS : 1; /* 31 */
+ unsigned int useSecurity : 1; /* 1 */
+ unsigned int useSocks : 1; /* 2 */
+ unsigned int requestCertificate : 1; /* 3 */
+ unsigned int requireCertificate : 2; /* 4-5 */
+ unsigned int handshakeAsClient : 1; /* 6 */
+ unsigned int handshakeAsServer : 1; /* 7 */
+ unsigned int enableSSL2 : 1; /* 8 */
+ unsigned int unusedBit9 : 1; /* 9 */
+ unsigned int unusedBit10 : 1; /* 10 */
+ unsigned int noCache : 1; /* 11 */
+ unsigned int fdx : 1; /* 12 */
+ unsigned int v2CompatibleHello : 1; /* 13 */
+ unsigned int detectRollBack : 1; /* 14 */
+ unsigned int noStepDown : 1; /* 15 */
+ unsigned int bypassPKCS11 : 1; /* 16 */
+ unsigned int noLocks : 1; /* 17 */
+ unsigned int enableSessionTickets : 1; /* 18 */
+ unsigned int enableDeflate : 1; /* 19 */
+ unsigned int enableRenegotiation : 2; /* 20-21 */
+ unsigned int requireSafeNegotiation : 1; /* 22 */
+ unsigned int enableFalseStart : 1; /* 23 */
+ unsigned int cbcRandomIV : 1; /* 24 */
+ unsigned int enableOCSPStapling : 1; /* 25 */
+ unsigned int enableNPN : 1; /* 26 */
+ unsigned int enableALPN : 1; /* 27 */
+ unsigned int reuseServerECDHEKey : 1; /* 28 */
+ unsigned int enableFallbackSCSV : 1; /* 29 */
+ unsigned int enableServerDhe : 1; /* 30 */
+ unsigned int enableExtendedMS : 1; /* 31 */
unsigned int enableSignedCertTimestamps : 1; /* 32 */
} sslOptions;
+/* clang-format on */
typedef enum { sslHandshakingUndetermined = 0,
- sslHandshakingAsClient,
- sslHandshakingAsServer
+ sslHandshakingAsClient,
+ sslHandshakingAsServer
} sslHandshakingType;
typedef struct sslServerCertsStr {
/* Configuration state for server sockets */
- CERTCertificate * serverCert;
- CERTCertificateList * serverCertChain;
- ssl3KeyPair * serverKeyPair;
- unsigned int serverKeyBits;
+ CERTCertificate *serverCert;
+ CERTCertificateList *serverCertChain;
+ ssl3KeyPair *serverKeyPair;
+ unsigned int serverKeyBits;
} sslServerCerts;
#define SERVERKEY serverKeyPair->privKey
-#define SSL_LOCK_RANK_SPEC 255
-#define SSL_LOCK_RANK_GLOBAL NSS_RWLOCK_RANK_NONE
+#define SSL_LOCK_RANK_SPEC 255
+#define SSL_LOCK_RANK_GLOBAL NSS_RWLOCK_RANK_NONE
-/* These are the valid values for shutdownHow.
+/* These are the valid values for shutdownHow.
** These values are each 1 greater than the NSPR values, and the code
-** depends on that relation to efficiently convert PR_SHUTDOWN values
-** into ssl_SHUTDOWN values. These values use one bit for read, and
+** depends on that relation to efficiently convert PR_SHUTDOWN values
+** into ssl_SHUTDOWN values. These values use one bit for read, and
** another bit for write, and can be used as bitmasks.
*/
-#define ssl_SHUTDOWN_NONE 0 /* NOT shutdown at all */
-#define ssl_SHUTDOWN_RCV 1 /* PR_SHUTDOWN_RCV +1 */
-#define ssl_SHUTDOWN_SEND 2 /* PR_SHUTDOWN_SEND +1 */
-#define ssl_SHUTDOWN_BOTH 3 /* PR_SHUTDOWN_BOTH +1 */
+#define ssl_SHUTDOWN_NONE 0 /* NOT shutdown at all */
+#define ssl_SHUTDOWN_RCV 1 /* PR_SHUTDOWN_RCV +1 */
+#define ssl_SHUTDOWN_SEND 2 /* PR_SHUTDOWN_SEND +1 */
+#define ssl_SHUTDOWN_BOTH 3 /* PR_SHUTDOWN_BOTH +1 */
/*
** A gather object. Used to read some data until a count has been
@@ -387,93 +380,83 @@ typedef struct sslServerCertsStr {
** Everything in here is protected by the recvBufLock.
*/
struct sslGatherStr {
- int state; /* see GS_ values below. */ /* ssl 2 & 3 */
+ int state; /* see GS_ values below. */ /* ssl 2 & 3 */
/* "buf" holds received plaintext SSL records, after decrypt and MAC check.
* SSL2: recv'd ciphertext records are put here, then decrypted in place.
- * SSL3: recv'd ciphertext records are put in inbuf (see below), then
+ * SSL3: recv'd ciphertext records are put in inbuf (see below), then
* decrypted into buf.
*/
- sslBuffer buf; /*recvBufLock*/ /* ssl 2 & 3 */
+ sslBuffer buf; /*recvBufLock*/ /* ssl 2 & 3 */
- /* number of bytes previously read into hdr or buf(ssl2) or inbuf (ssl3).
- ** (offset - writeOffset) is the number of ciphertext bytes read in but
+ /* number of bytes previously read into hdr or buf(ssl2) or inbuf (ssl3).
+ ** (offset - writeOffset) is the number of ciphertext bytes read in but
** not yet deciphered.
*/
- unsigned int offset; /* ssl 2 & 3 */
+ unsigned int offset; /* ssl 2 & 3 */
/* number of bytes to read in next call to ssl_DefRecv (recv) */
- unsigned int remainder; /* ssl 2 & 3 */
+ unsigned int remainder; /* ssl 2 & 3 */
/* Number of ciphertext bytes to read in after 2-byte SSL record header. */
- unsigned int count; /* ssl2 only */
+ unsigned int count; /* ssl2 only */
- /* size of the final plaintext record.
+ /* size of the final plaintext record.
** == count - (recordPadding + MAC size)
*/
- unsigned int recordLen; /* ssl2 only */
+ unsigned int recordLen; /* ssl2 only */
/* number of bytes of padding to be removed after decrypting. */
/* This value is taken from the record's hdr[2], which means a too large
* value could crash us.
*/
- unsigned int recordPadding; /* ssl2 only */
+ unsigned int recordPadding; /* ssl2 only */
/* plaintext DATA begins this many bytes into "buf". */
- unsigned int recordOffset; /* ssl2 only */
+ unsigned int recordOffset; /* ssl2 only */
- int encrypted; /* SSL2 session is now encrypted. ssl2 only */
+ int encrypted; /* SSL2 session is now encrypted. ssl2 only */
- /* These next two values are used by SSL2 and SSL3.
+ /* These next two values are used by SSL2 and SSL3.
** DoRecv uses them to extract application data.
- ** The difference between writeOffset and readOffset is the amount of
- ** data available to the application. Note that the actual offset of
+ ** The difference between writeOffset and readOffset is the amount of
+ ** data available to the application. Note that the actual offset of
** the data in "buf" is recordOffset (above), not readOffset.
- ** In the current implementation, this is made available before the
+ ** In the current implementation, this is made available before the
** MAC is checked!!
*/
- unsigned int readOffset; /* Spot where DATA reader (e.g. application
+ unsigned int readOffset; /* Spot where DATA reader (e.g. application
** or handshake code) will read next.
** Always zero for SSl3 application data.
- */
+ */
/* offset in buf/inbuf/hdr into which new data will be read from socket. */
- unsigned int writeOffset;
+ unsigned int writeOffset;
/* Buffer for ssl3 to read (encrypted) data from the socket */
- sslBuffer inbuf; /*recvBufLock*/ /* ssl3 only */
+ sslBuffer inbuf; /*recvBufLock*/ /* ssl3 only */
/* The ssl[23]_GatherData functions read data into this buffer, rather
- ** than into buf or inbuf, while in the GS_HEADER state.
- ** The portion of the SSL record header put here always comes off the wire
+ ** than into buf or inbuf, while in the GS_HEADER state.
+ ** The portion of the SSL record header put here always comes off the wire
** as plaintext, never ciphertext.
** For SSL2, the plaintext portion is two bytes long. For SSl3 it is 5.
** For DTLS it is 13.
*/
- unsigned char hdr[13]; /* ssl 2 & 3 or dtls */
+ unsigned char hdr[13]; /* ssl 2 & 3 or dtls */
/* Buffer for DTLS data read off the wire as a single datagram */
- sslBuffer dtlsPacket;
+ sslBuffer dtlsPacket;
/* the start of the buffered DTLS record in dtlsPacket */
- unsigned int dtlsPacketOffset;
+ unsigned int dtlsPacketOffset;
};
/* sslGather.state */
-#define GS_INIT 0
-#define GS_HEADER 1
-#define GS_MAC 2
-#define GS_DATA 3
-#define GS_PAD 4
-
-#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_WIN32)
-typedef PCERT_KEY_CONTEXT PlatformKey;
-#elif defined(NSS_PLATFORM_CLIENT_AUTH) && defined(XP_MACOSX)
-typedef SecKeyRef PlatformKey;
-#else
-typedef void *PlatformKey;
-#endif
-
-
+#define GS_INIT 0
+#define GS_HEADER 1
+#define GS_MAC 2
+#define GS_DATA 3
+#define GS_PAD 4
/*
** ssl3State and CipherSpec structs
@@ -482,15 +465,15 @@ typedef void *PlatformKey;
/* The SSL bulk cipher definition */
typedef enum {
cipher_null,
- cipher_rc4,
+ cipher_rc4,
cipher_rc4_40,
cipher_rc4_56,
- cipher_rc2,
+ cipher_rc2,
cipher_rc2_40,
- cipher_des,
- cipher_3des,
+ cipher_des,
+ cipher_3des,
cipher_des40,
- cipher_idea,
+ cipher_idea,
cipher_aes_128,
cipher_aes_256,
cipher_camellia_128,
@@ -498,75 +481,77 @@ typedef enum {
cipher_seed,
cipher_aes_128_gcm,
cipher_chacha20,
- cipher_missing /* reserved for no such supported cipher */
+ cipher_missing /* reserved for no such supported cipher */
/* This enum must match ssl3_cipherName[] in ssl3con.c. */
} SSL3BulkCipher;
-typedef enum { type_stream, type_block, type_aead } CipherType;
+typedef enum { type_stream,
+ type_block,
+ type_aead } CipherType;
#define MAX_IV_LENGTH 24
/*
- * Do not depend upon 64 bit arithmetic in the underlying machine.
+ * Do not depend upon 64 bit arithmetic in the underlying machine.
*/
typedef struct {
- PRUint32 high;
- PRUint32 low;
+ PRUint32 high;
+ PRUint32 low;
} SSL3SequenceNumber;
typedef PRUint16 DTLSEpoch;
typedef void (*DTLSTimerCb)(sslSocket *);
-#define MAX_MAC_CONTEXT_BYTES 400 /* 400 is large enough for MD5, SHA-1, and
- * SHA-256. For SHA-384 support, increase
- * it to 712. */
+/* 400 is large enough for MD5, SHA-1, and SHA-256.
+ * For SHA-384 support, increase it to 712. */
+#define MAX_MAC_CONTEXT_BYTES 400
#define MAX_MAC_CONTEXT_LLONGS (MAX_MAC_CONTEXT_BYTES / 8)
#define MAX_CIPHER_CONTEXT_BYTES 2080
#define MAX_CIPHER_CONTEXT_LLONGS (MAX_CIPHER_CONTEXT_BYTES / 8)
typedef struct {
- SSL3Opaque wrapped_master_secret[48];
- PRUint16 wrapped_master_secret_len;
- PRUint8 msIsWrapped;
- PRUint8 resumable;
- PRUint8 extendedMasterSecretUsed;
+ SSL3Opaque wrapped_master_secret[48];
+ PRUint16 wrapped_master_secret_len;
+ PRUint8 msIsWrapped;
+ PRUint8 resumable;
+ PRUint8 extendedMasterSecretUsed;
} ssl3SidKeys; /* 52 bytes */
typedef struct {
- PK11SymKey *write_key;
- PK11SymKey *write_mac_key;
+ PK11SymKey *write_key;
+ PK11SymKey *write_mac_key;
PK11Context *write_mac_context;
- SECItem write_key_item;
- SECItem write_iv_item;
- SECItem write_mac_key_item;
- SSL3Opaque write_iv[MAX_IV_LENGTH];
- PRUint64 cipher_context[MAX_CIPHER_CONTEXT_LLONGS];
+ SECItem write_key_item;
+ SECItem write_iv_item;
+ SECItem write_mac_key_item;
+ SSL3Opaque write_iv[MAX_IV_LENGTH];
+ PRUint64 cipher_context[MAX_CIPHER_CONTEXT_LLONGS];
} ssl3KeyMaterial;
-typedef SECStatus (*SSLCipher)(void * context,
- unsigned char * out,
- int * outlen,
- int maxout,
- const unsigned char *in,
- int inlen);
+typedef SECStatus (*SSLCipher)(void *context,
+ unsigned char *out,
+ int *outlen,
+ int maxout,
+ const unsigned char *in,
+ int inlen);
typedef SECStatus (*SSLAEADCipher)(
- ssl3KeyMaterial * keys,
- PRBool doDecrypt,
- unsigned char * out,
- int * outlen,
- int maxout,
- const unsigned char *in,
- int inlen,
- const unsigned char *additionalData,
- int additionalDataLen);
-typedef SECStatus (*SSLCompressor)(void * context,
- unsigned char * out,
- int * outlen,
- int maxout,
+ ssl3KeyMaterial *keys,
+ PRBool doDecrypt,
+ unsigned char *out,
+ int *outlen,
+ int maxout,
+ const unsigned char *in,
+ int inlen,
+ const unsigned char *additionalData,
+ int additionalDataLen);
+typedef SECStatus (*SSLCompressor)(void *context,
+ unsigned char *out,
+ int *outlen,
+ int maxout,
const unsigned char *in,
- int inlen);
+ int inlen);
typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit);
/* The DTLS anti-replay window. Defined here because we need it in
@@ -574,11 +559,11 @@ typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit);
* right represent the true window, with modular arithmetic used to
* map them onto the buffer.
*/
-#define DTLS_RECVD_RECORDS_WINDOW 1024 /* Packets; approximate
- * Must be divisible by 8
- */
+#define DTLS_RECVD_RECORDS_WINDOW 1024 /* Packets; approximate \
+ * Must be divisible by 8 \
+ */
typedef struct DTLSRecvdRecordsStr {
- unsigned char data[DTLS_RECVD_RECORDS_WINDOW/8];
+ unsigned char data[DTLS_RECVD_RECORDS_WINDOW / 8];
PRUint64 left;
PRUint64 right;
} DTLSRecvdRecords;
@@ -590,43 +575,43 @@ typedef struct DTLSRecvdRecordsStr {
*/
typedef struct {
const ssl3BulkCipherDef *cipher_def;
- const ssl3MACDef * mac_def;
+ const ssl3MACDef *mac_def;
SSLCompressionMethod compression_method;
- int mac_size;
- SSLCipher encode;
- SSLCipher decode;
- SSLAEADCipher aead;
- SSLDestroy destroy;
- void * encodeContext;
- void * decodeContext;
- SSLCompressor compressor; /* Don't name these fields compress */
- SSLCompressor decompressor; /* and uncompress because zconf.h */
- /* may define them as macros. */
- SSLDestroy destroyCompressContext;
- void * compressContext;
- SSLDestroy destroyDecompressContext;
- void * decompressContext;
- PRBool bypassCiphers; /* did double bypass (at least) */
- PK11SymKey * master_secret;
+ int mac_size;
+ SSLCipher encode;
+ SSLCipher decode;
+ SSLAEADCipher aead;
+ SSLDestroy destroy;
+ void *encodeContext;
+ void *decodeContext;
+ SSLCompressor compressor; /* Don't name these fields compress */
+ SSLCompressor decompressor; /* and uncompress because zconf.h */
+ /* may define them as macros. */
+ SSLDestroy destroyCompressContext;
+ void *compressContext;
+ SSLDestroy destroyDecompressContext;
+ void *decompressContext;
+ PRBool bypassCiphers; /* did double bypass (at least) */
+ PK11SymKey *master_secret;
SSL3SequenceNumber write_seq_num;
SSL3SequenceNumber read_seq_num;
SSL3ProtocolVersion version;
- ssl3KeyMaterial client;
- ssl3KeyMaterial server;
- SECItem msItem;
- unsigned char key_block[NUM_MIXERS * MD5_LENGTH];
- unsigned char raw_master_secret[56];
- SECItem srvVirtName; /* for server: name that was negotiated
- * with a client. For client - is
- * always set to NULL.*/
- DTLSEpoch epoch;
- DTLSRecvdRecords recvdRecords;
+ ssl3KeyMaterial client;
+ ssl3KeyMaterial server;
+ SECItem msItem;
+ unsigned char key_block[NUM_MIXERS * MD5_LENGTH];
+ unsigned char raw_master_secret[56];
+ SECItem srvVirtName; /* for server: name that was negotiated
+ * with a client. For client - is
+ * always set to NULL.*/
+ DTLSEpoch epoch;
+ DTLSRecvdRecords recvdRecords;
} ssl3CipherSpec;
-typedef enum { never_cached,
- in_client_cache,
- in_server_cache,
- invalid_cache /* no longer in any cache. */
+typedef enum { never_cached,
+ in_client_cache,
+ in_server_cache,
+ invalid_cache /* no longer in any cache. */
} Cached;
#define MAX_PEER_CERT_CHAIN_SIZE 8
@@ -635,95 +620,95 @@ struct sslSessionIDStr {
/* The global cache lock must be held when accessing these members when the
* sid is in any cache.
*/
- sslSessionID * next; /* chain used for client sockets, only */
- Cached cached;
- int references;
- PRUint32 lastAccessTime; /* seconds since Jan 1, 1970 */
+ sslSessionID *next; /* chain used for client sockets, only */
+ Cached cached;
+ int references;
+ PRUint32 lastAccessTime; /* seconds since Jan 1, 1970 */
/* The rest of the members, except for the members of u.ssl3.locked, may
* be modified only when the sid is not in any cache.
*/
- CERTCertificate * peerCert;
- CERTCertificate * peerCertChain[MAX_PEER_CERT_CHAIN_SIZE];
- SECItemArray peerCertStatus; /* client only */
- const char * peerID; /* client only */
- const char * urlSvrName; /* client only */
- CERTCertificate * localCert;
+ CERTCertificate *peerCert;
+ CERTCertificate *peerCertChain[MAX_PEER_CERT_CHAIN_SIZE];
+ SECItemArray peerCertStatus; /* client only */
+ const char *peerID; /* client only */
+ const char *urlSvrName; /* client only */
+ CERTCertificate *localCert;
- PRIPv6Addr addr;
- PRUint16 port;
+ PRIPv6Addr addr;
+ PRUint16 port;
- SSL3ProtocolVersion version;
+ SSL3ProtocolVersion version;
- PRUint32 creationTime; /* seconds since Jan 1, 1970 */
- PRUint32 expirationTime; /* seconds since Jan 1, 1970 */
+ PRUint32 creationTime; /* seconds since Jan 1, 1970 */
+ PRUint32 expirationTime; /* seconds since Jan 1, 1970 */
- SSLSignType authAlgorithm;
- PRUint32 authKeyBits;
- SSLKEAType keaType;
- PRUint32 keaKeyBits;
+ SSLSignType authAlgorithm;
+ PRUint32 authKeyBits;
+ SSLKEAType keaType;
+ PRUint32 keaKeyBits;
union {
- struct {
- /* the V2 code depends upon the size of sessionID. */
- unsigned char sessionID[SSL2_SESSIONID_BYTES];
-
- /* Stuff used to recreate key and read/write cipher objects */
- SECItem masterKey; /* never wrapped */
- int cipherType;
- SECItem cipherArg;
- int keyBits;
- int secretKeyBits;
- } ssl2;
- struct {
- /* values that are copied into the server's on-disk SID cache. */
- PRUint8 sessionIDLength;
- SSL3Opaque sessionID[SSL3_SESSIONID_BYTES];
-
- ssl3CipherSuite cipherSuite;
- SSLCompressionMethod compression;
- int policy;
- ssl3SidKeys keys;
- CK_MECHANISM_TYPE masterWrapMech;
- /* mechanism used to wrap master secret */
- SSL3KEAType exchKeyType;
- /* key type used in exchange algorithm,
- * and to wrap the sym wrapping key. */
+ struct {
+ /* the V2 code depends upon the size of sessionID. */
+ unsigned char sessionID[SSL2_SESSIONID_BYTES];
+
+ /* Stuff used to recreate key and read/write cipher objects */
+ SECItem masterKey; /* never wrapped */
+ int cipherType;
+ SECItem cipherArg;
+ int keyBits;
+ int secretKeyBits;
+ } ssl2;
+ struct {
+ /* values that are copied into the server's on-disk SID cache. */
+ PRUint8 sessionIDLength;
+ SSL3Opaque sessionID[SSL3_SESSIONID_BYTES];
+
+ ssl3CipherSuite cipherSuite;
+ SSLCompressionMethod compression;
+ int policy;
+ ssl3SidKeys keys;
+ CK_MECHANISM_TYPE masterWrapMech;
+ /* mechanism used to wrap master secret */
+ SSL3KEAType exchKeyType;
+ /* key type used in exchange algorithm,
+ * and to wrap the sym wrapping key. */
#ifndef NSS_DISABLE_ECC
- PRUint32 negotiatedECCurves;
+ PRUint32 negotiatedECCurves;
#endif /* NSS_DISABLE_ECC */
- /* The following values are NOT restored from the server's on-disk
- * session cache, but are restored from the client's cache.
- */
- PK11SymKey * clientWriteKey;
- PK11SymKey * serverWriteKey;
-
- /* The following values pertain to the slot that wrapped the
- ** master secret. (used only in client)
- */
- SECMODModuleID masterModuleID;
- /* what module wrapped the master secret */
- CK_SLOT_ID masterSlotID;
- PRUint16 masterWrapIndex;
- /* what's the key index for the wrapping key */
- PRUint16 masterWrapSeries;
- /* keep track of the slot series, so we don't
- * accidently try to use new keys after the
- * card gets removed and replaced.*/
-
- /* The following values pertain to the slot that did the signature
- ** for client auth. (used only in client)
- */
- SECMODModuleID clAuthModuleID;
- CK_SLOT_ID clAuthSlotID;
- PRUint16 clAuthSeries;
-
- char masterValid;
- char clAuthValid;
-
- SECItem srvName;
+ /* The following values are NOT restored from the server's on-disk
+ * session cache, but are restored from the client's cache.
+ */
+ PK11SymKey *clientWriteKey;
+ PK11SymKey *serverWriteKey;
+
+ /* The following values pertain to the slot that wrapped the
+ ** master secret. (used only in client)
+ */
+ SECMODModuleID masterModuleID;
+ /* what module wrapped the master secret */
+ CK_SLOT_ID masterSlotID;
+ PRUint16 masterWrapIndex;
+ /* what's the key index for the wrapping key */
+ PRUint16 masterWrapSeries;
+ /* keep track of the slot series, so we don't
+ * accidently try to use new keys after the
+ * card gets removed and replaced.*/
+
+ /* The following values pertain to the slot that did the signature
+ ** for client auth. (used only in client)
+ */
+ SECMODModuleID clAuthModuleID;
+ CK_SLOT_ID clAuthSlotID;
+ PRUint16 clAuthSeries;
+
+ char masterValid;
+ char clAuthValid;
+
+ SECItem srvName;
/* originalHandshakeHash contains the hash of the original, full
* handshake prior to the server's final flow. This is either a
@@ -731,38 +716,38 @@ struct sslSessionIDStr {
* TLS 1.2). This is recorded and used only when ChannelID is
* negotiated as it's used to bind the ChannelID signature on the
* resumption handshake to the original handshake. */
- SECItem originalHandshakeHash;
-
- /* Signed certificate timestamps received in a TLS extension.
- ** (used only in client).
- */
- SECItem signedCertTimestamps;
-
- /* This lock is lazily initialized by CacheSID when a sid is first
- * cached. Before then, there is no need to lock anything because
- * the sid isn't being shared by anything.
- */
- NSSRWLock *lock;
-
- /* The lock must be held while reading or writing these members
- * because they change while the sid is cached.
- */
- struct {
- /* The session ticket, if we have one, is sent as an extension
- * in the ClientHello message. This field is used only by
- * clients. It is protected by lock when lock is non-null
- * (after the sid has been added to the client session cache).
- */
- NewSessionTicket sessionTicket;
- } locked;
- } ssl3;
+ SECItem originalHandshakeHash;
+
+ /* Signed certificate timestamps received in a TLS extension.
+ ** (used only in client).
+ */
+ SECItem signedCertTimestamps;
+
+ /* This lock is lazily initialized by CacheSID when a sid is first
+ * cached. Before then, there is no need to lock anything because
+ * the sid isn't being shared by anything.
+ */
+ PRRWLock *lock;
+
+ /* The lock must be held while reading or writing these members
+ * because they change while the sid is cached.
+ */
+ struct {
+ /* The session ticket, if we have one, is sent as an extension
+ * in the ClientHello message. This field is used only by
+ * clients. It is protected by lock when lock is non-null
+ * (after the sid has been added to the client session cache).
+ */
+ NewSessionTicket sessionTicket;
+ } locked;
+ } ssl3;
} u;
};
typedef struct ssl3CipherSuiteDefStr {
- ssl3CipherSuite cipher_suite;
- SSL3BulkCipher bulk_cipher_alg;
- SSL3MACAlgorithm mac_alg;
+ ssl3CipherSuite cipher_suite;
+ SSL3BulkCipher bulk_cipher_alg;
+ SSL3MACAlgorithm mac_alg;
SSL3KeyExchangeAlgorithm key_exchange_alg;
} ssl3CipherSuiteDef;
@@ -771,32 +756,35 @@ typedef struct ssl3CipherSuiteDefStr {
*/
typedef struct {
SSL3KeyExchangeAlgorithm kea;
- SSL3KEAType exchKeyType;
- SSL3SignType signKeyType;
+ SSL3KEAType exchKeyType;
+ SSLSignType signKeyType;
/* For export cipher suites:
* is_limited identifies a suite as having a limit on the key size.
* key_size_limit provides the corresponding limit. */
- PRBool is_limited;
+ PRBool is_limited;
unsigned int key_size_limit;
- PRBool tls_keygen;
+ PRBool tls_keygen;
/* True if the key exchange for the suite is ephemeral. Or to be more
* precise: true if the ServerKeyExchange message is always required. */
- PRBool ephemeral;
+ PRBool ephemeral;
+ /* An OID describing the key exchange */
+ SECOidTag oid;
} ssl3KEADef;
/*
** There are tables of these, all const.
*/
struct ssl3BulkCipherDefStr {
- SSL3BulkCipher cipher;
+ SSL3BulkCipher cipher;
SSLCipherAlgorithm calg;
- int key_size;
- int secret_key_size;
- CipherType type;
- int iv_size;
- int block_size;
- int tag_size; /* authentication tag size for AEAD ciphers. */
- int explicit_nonce_size; /* for AEAD ciphers. */
+ int key_size;
+ int secret_key_size;
+ CipherType type;
+ int iv_size;
+ int block_size;
+ int tag_size; /* authentication tag size for AEAD ciphers. */
+ int explicit_nonce_size; /* for AEAD ciphers. */
+ SECOidTag oid;
};
/*
@@ -805,36 +793,41 @@ struct ssl3BulkCipherDefStr {
struct ssl3MACDefStr {
SSL3MACAlgorithm mac;
CK_MECHANISM_TYPE mmech;
- int pad_size;
- int mac_size;
+ int pad_size;
+ int mac_size;
+ SECOidTag oid;
};
typedef enum {
- wait_client_hello,
- wait_client_cert,
+ wait_client_hello,
+ wait_client_cert,
wait_client_key,
- wait_cert_verify,
- wait_change_cipher,
+ wait_cert_verify,
+ wait_change_cipher,
wait_finished,
- wait_server_hello,
+ wait_server_hello,
wait_certificate_status,
- wait_server_cert,
+ wait_server_cert,
wait_server_key,
- wait_cert_request,
+ wait_cert_request,
wait_hello_done,
wait_new_session_ticket,
- idle_handshake
+ wait_encrypted_extensions,
+ idle_handshake,
+ wait_invalid /* Invalid value. There is no handshake message "invalid". */
} SSL3WaitState;
/*
* TLS extension related constants and data structures.
*/
-typedef struct TLSExtensionDataStr TLSExtensionData;
-typedef struct SessionTicketDataStr SessionTicketData;
+typedef struct TLSExtensionDataStr TLSExtensionData;
+typedef struct SessionTicketDataStr SessionTicketData;
struct TLSExtensionDataStr {
/* registered callbacks that send server hello extensions */
- ssl3HelloExtensionSender serverSenders[SSL_MAX_EXTENSIONS];
+ ssl3HelloExtensionSender serverHelloSenders[SSL_MAX_EXTENSIONS];
+ ssl3HelloExtensionSender encryptedExtensionsSenders[SSL_MAX_EXTENSIONS];
+
/* Keep track of the extensions that are negotiated. */
PRUint16 numAdvertised;
PRUint16 numNegotiated;
@@ -879,10 +872,16 @@ typedef struct DTLSQueuedMessageStr {
PRUint16 len; /* The data length */
} DTLSQueuedMessage;
+typedef struct TLS13KeyShareEntryStr {
+ PRCList link; /* The linked list link */
+ PRUint16 group; /* The group for the entry */
+ SECItem key_exchange; /* The share itself */
+} TLS13KeyShareEntry;
+
typedef enum {
handshake_hash_unknown = 0,
- handshake_hash_combo = 1, /* The MD5/SHA-1 combination */
- handshake_hash_single = 2 /* A single hash */
+ handshake_hash_combo = 1, /* The MD5/SHA-1 combination */
+ handshake_hash_single = 2 /* A single hash */
} SSL3HandshakeHashType;
/*
@@ -890,22 +889,22 @@ typedef enum {
** This entire struct is protected by ssl3HandshakeLock
*/
typedef struct SSL3HandshakeStateStr {
- SSL3Random server_random;
- SSL3Random client_random;
- SSL3WaitState ws;
+ SSL3Random server_random;
+ SSL3Random client_random;
+ SSL3WaitState ws; /* May also contain SSL3WaitState | 0x80 for TLS 1.3 */
/* This group of members is used for handshake running hashes. */
SSL3HandshakeHashType hashType;
- sslBuffer messages; /* Accumulated handshake messages */
+ sslBuffer messages; /* Accumulated handshake messages */
#ifndef NO_PKCS11_BYPASS
/* Bypass mode:
* SSL 3.0 - TLS 1.1 use both |md5_cx| and |sha_cx|. |md5_cx| is used for
* MD5 and |sha_cx| for SHA-1.
* TLS 1.2 and later use only |sha_cx|, for SHA-256. NOTE: When we support
* SHA-384, increase MAX_MAC_CONTEXT_BYTES to 712. */
- PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS];
- PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS];
- const SECHashObject * sha_obj;
+ PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS];
+ PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS];
+ const SECHashObject *sha_obj;
/* The function prototype of sha_obj->clone() does not match the prototype
* of the freebl <HASH>_Clone functions, so we need a dedicated function
* pointer for the <HASH>_Clone function. */
@@ -919,55 +918,55 @@ typedef struct SSL3HandshakeStateStr {
* handshake hash for generating client auth signatures. Confusingly, the
* backup hash function is SHA-1. */
#define backupHash md5
- PK11Context * md5;
- PK11Context * sha;
-
-const ssl3KEADef * kea_def;
- ssl3CipherSuite cipher_suite;
-const ssl3CipherSuiteDef *suite_def;
- SSLCompressionMethod compression;
- sslBuffer msg_body; /* protected by recvBufLock */
- /* partial handshake message from record layer */
- unsigned int header_bytes;
- /* number of bytes consumed from handshake */
- /* message for message type and header length */
- SSL3HandshakeType msg_type;
- unsigned long msg_len;
- SECItem ca_list; /* used only by client */
- PRBool isResuming; /* are we resuming a session */
- PRBool usedStepDownKey; /* we did a server key exchange. */
- PRBool sendingSCSV; /* instead of empty RI */
- sslBuffer msgState; /* current state for handshake messages*/
- /* protected by recvBufLock */
+ PK11Context *md5;
+ PK11Context *sha;
+
+ const ssl3KEADef *kea_def;
+ ssl3CipherSuite cipher_suite;
+ const ssl3CipherSuiteDef *suite_def;
+ SSLCompressionMethod compression;
+ sslBuffer msg_body; /* protected by recvBufLock */
+ /* partial handshake message from record layer */
+ unsigned int header_bytes;
+ /* number of bytes consumed from handshake */
+ /* message for message type and header length */
+ SSL3HandshakeType msg_type;
+ unsigned long msg_len;
+ SECItem ca_list; /* used only by client */
+ PRBool isResuming; /* are we resuming a session */
+ PRBool usedStepDownKey; /* we did a server key exchange. */
+ PRBool sendingSCSV; /* instead of empty RI */
+ sslBuffer msgState; /* current state for handshake messages*/
+ /* protected by recvBufLock */
/* The session ticket received in a NewSessionTicket message is temporarily
* stored in newSessionTicket until the handshake is finished; then it is
* moved to the sid.
*/
- PRBool receivedNewSessionTicket;
- NewSessionTicket newSessionTicket;
+ PRBool receivedNewSessionTicket;
+ NewSessionTicket newSessionTicket;
- PRUint16 finishedBytes; /* size of single finished below */
+ PRUint16 finishedBytes; /* size of single finished below */
union {
- TLSFinished tFinished[2]; /* client, then server */
- SSL3Finished sFinished[2];
- SSL3Opaque data[72];
- } finishedMsgs;
+ TLSFinished tFinished[2]; /* client, then server */
+ SSL3Finished sFinished[2];
+ SSL3Opaque data[72];
+ } finishedMsgs;
#ifndef NSS_DISABLE_ECC
- PRUint32 negotiatedECCurves; /* bit mask */
-#endif /* NSS_DISABLE_ECC */
+ PRUint32 negotiatedECCurves; /* bit mask */
+#endif /* NSS_DISABLE_ECC */
- PRBool authCertificatePending;
+ PRBool authCertificatePending;
/* Which function should SSL_RestartHandshake* call if we're blocked?
* One of NULL, ssl3_SendClientSecondRound, ssl3_FinishHandshake,
* or ssl3_AlwaysFail */
- sslRestartTarget restartTarget;
+ sslRestartTarget restartTarget;
/* Shared state between ssl3_HandleFinished and ssl3_FinishHandshake */
- PRBool cacheSID;
+ PRBool cacheSID;
- PRBool canFalseStart; /* Can/did we False Start */
+ PRBool canFalseStart; /* Can/did we False Start */
/* Which preliminaryinfo values have been set. */
- PRUint32 preliminaryInfo;
+ PRUint32 preliminaryInfo;
/* clientSigAndHash contains the contents of the signature_algorithms
* extension (if any) from the client. This is only valid for TLS 1.2
@@ -976,155 +975,168 @@ const ssl3CipherSuiteDef *suite_def;
unsigned int numClientSigAndHash;
/* This group of values is used for DTLS */
- PRUint16 sendMessageSeq; /* The sending message sequence
- * number */
- PRCList lastMessageFlight; /* The last message flight we
- * sent */
- PRUint16 maxMessageSent; /* The largest message we sent */
- PRUint16 recvMessageSeq; /* The receiving message sequence
- * number */
- sslBuffer recvdFragments; /* The fragments we have received in
- * a bitmask */
- PRInt32 recvdHighWater; /* The high water mark for fragments
- * received. -1 means no reassembly
- * in progress. */
- unsigned char cookie[32]; /* The cookie */
- unsigned char cookieLen; /* The length of the cookie */
- PRIntervalTime rtTimerStarted; /* When the timer was started */
- DTLSTimerCb rtTimerCb; /* The function to call on expiry */
- PRUint32 rtTimeoutMs; /* The length of the current timeout
- * used for backoff (in ms) */
- PRUint32 rtRetries; /* The retry counter */
+ PRUint16 sendMessageSeq; /* The sending message sequence
+ * number */
+ PRCList lastMessageFlight; /* The last message flight we
+ * sent */
+ PRUint16 maxMessageSent; /* The largest message we sent */
+ PRUint16 recvMessageSeq; /* The receiving message sequence
+ * number */
+ sslBuffer recvdFragments; /* The fragments we have received in
+ * a bitmask */
+ PRInt32 recvdHighWater; /* The high water mark for fragments
+ * received. -1 means no reassembly
+ * in progress. */
+ unsigned char cookie[32]; /* The cookie */
+ unsigned char cookieLen; /* The length of the cookie */
+ PRIntervalTime rtTimerStarted; /* When the timer was started */
+ DTLSTimerCb rtTimerCb; /* The function to call on expiry */
+ PRUint32 rtTimeoutMs; /* The length of the current timeout
+ * used for backoff (in ms) */
+ PRUint32 rtRetries; /* The retry counter */
+
+ /* This group of values is used for TLS 1.3 and above */
+ PRCList remoteKeyShares; /* The other side's public keys */
+ PK11SymKey *xSS; /* Extracted static secret */
+ PK11SymKey *xES; /* Extracted ephemeral secret */
+ PK11SymKey *trafficSecret; /* The source key to use to generate
+ * traffic keys */
+ PK11SymKey *clientFinishedSecret; /* Used for client Finished */
+ PK11SymKey *serverFinishedSecret; /* Used for server Finished */
+ unsigned char certReqContext[255]; /* Ties CertificateRequest
+ * to Certificate */
+ PRUint8 certReqContextLen; /* Length of the context
+ * cannot be greater than 255. */
} SSL3HandshakeState;
-
-
/*
** This is the "ssl3" struct, as in "ss->ssl3".
** note:
-** usually, crSpec == cwSpec and prSpec == pwSpec.
+** usually, crSpec == cwSpec and prSpec == pwSpec.
** Sometimes, crSpec == pwSpec and prSpec == cwSpec.
-** But there are never more than 2 actual specs.
+** But there are never more than 2 actual specs.
** No spec must ever be modified if either "current" pointer points to it.
*/
struct ssl3StateStr {
/*
- ** The following Specs and Spec pointers must be protected using the
+ ** The following Specs and Spec pointers must be protected using the
** Spec Lock.
*/
- ssl3CipherSpec * crSpec; /* current read spec. */
- ssl3CipherSpec * prSpec; /* pending read spec. */
- ssl3CipherSpec * cwSpec; /* current write spec. */
- ssl3CipherSpec * pwSpec; /* pending write spec. */
-
- CERTCertificate * clientCertificate; /* used by client */
- SECKEYPrivateKey * clientPrivateKey; /* used by client */
- /* platformClientKey is present even when NSS_PLATFORM_CLIENT_AUTH is not
- * defined in order to allow cleaner conditional code.
- * At most one of clientPrivateKey and platformClientKey may be set. */
- PlatformKey platformClientKey; /* used by client */
- CERTCertificateList *clientCertChain; /* used by client */
- PRBool sendEmptyCert; /* used by client */
-
- SECKEYPrivateKey *channelID; /* used by client */
- SECKEYPublicKey *channelIDPub; /* used by client */
-
- int policy;
- /* This says what cipher suites we can do, and should
- * be either SSL_ALLOWED or SSL_RESTRICTED
- */
- PLArenaPool * peerCertArena;
- /* These are used to keep track of the peer CA */
- void * peerCertChain;
- /* chain while we are trying to validate it. */
- CERTDistNames * ca_list;
- /* used by server. trusted CAs for this socket. */
- PRBool initialized;
- SSL3HandshakeState hs;
- ssl3CipherSpec specs[2]; /* one is current, one is pending. */
+ ssl3CipherSpec *crSpec; /* current read spec. */
+ ssl3CipherSpec *prSpec; /* pending read spec. */
+ ssl3CipherSpec *cwSpec; /* current write spec. */
+ ssl3CipherSpec *pwSpec; /* pending write spec. */
+
+ CERTCertificate *clientCertificate; /* used by client */
+ SECKEYPrivateKey *clientPrivateKey; /* used by client */
+ CERTCertificateList *clientCertChain; /* used by client */
+ PRBool sendEmptyCert; /* used by client */
+
+ SECKEYPrivateKey *channelID; /* used by client */
+ SECKEYPublicKey *channelIDPub; /* used by client */
+
+ int policy;
+ /* This says what cipher suites we can do, and should
+ * be either SSL_ALLOWED or SSL_RESTRICTED
+ */
+ PLArenaPool *peerCertArena;
+ /* These are used to keep track of the peer CA */
+ void *peerCertChain;
+ /* chain while we are trying to validate it. */
+ CERTDistNames *ca_list;
+ /* used by server. trusted CAs for this socket. */
+ PRBool initialized;
+ SSL3HandshakeState hs;
+ ssl3CipherSpec specs[2]; /* one is current, one is pending. */
/* In a client: if the server supports Next Protocol Negotiation, then
* this is the protocol that was negotiated.
*/
- SECItem nextProto;
- SSLNextProtoState nextProtoState;
+ SECItem nextProto;
+ SSLNextProtoState nextProtoState;
- PRUint16 mtu; /* Our estimate of the MTU */
+ PRUint16 mtu; /* Our estimate of the MTU */
/* DTLS-SRTP cipher suite preferences (if any) */
- PRUint16 dtlsSRTPCiphers[MAX_DTLS_SRTP_CIPHER_SUITES];
- PRUint16 dtlsSRTPCipherCount;
- PRUint16 dtlsSRTPCipherSuite; /* 0 if not selected */
- PRBool fatalAlertSent;
- PRUint16 numDHEGroups; /* used by server */
- SSLDHEGroupType * dheGroups; /* used by server */
- PRBool dheWeakGroupEnabled; /* used by server */
+ PRUint16 dtlsSRTPCiphers[MAX_DTLS_SRTP_CIPHER_SUITES];
+ PRUint16 dtlsSRTPCipherCount;
+ PRUint16 dtlsSRTPCipherSuite; /* 0 if not selected */
+ PRBool fatalAlertSent;
+ PRUint16 numDHEGroups; /* used by server */
+ SSLDHEGroupType *dheGroups; /* used by server */
+ PRBool dheWeakGroupEnabled; /* used by server */
/* TLS 1.2 introduces separate signature algorithm negotiation.
* This is our preference order. */
SSLSignatureAndHashAlg signatureAlgorithms[MAX_SIGNATURE_ALGORITHMS];
unsigned int signatureAlgorithmCount;
+
+ /* The version to check if we fell back from our highest version
+ * of TLS. Default is 0 in which case we check against the maximum
+ * configured version for this socket. Used only on the client. */
+ SSL3ProtocolVersion downgradeCheckVersion;
};
-#define DTLS_MAX_MTU 1500U /* Ethernet MTU but without subtracting the
- * headers, so slightly larger than expected */
+/* Ethernet MTU but without subtracting the headers,
+ * so slightly larger than expected */
+#define DTLS_MAX_MTU 1500U
#define IS_DTLS(ss) (ss->protocolVariant == ssl_variant_datagram)
typedef struct {
- SSL3ContentType type;
- SSL3ProtocolVersion version;
- SSL3SequenceNumber seq_num; /* DTLS only */
- sslBuffer * buf;
+ SSL3ContentType type;
+ SSL3ProtocolVersion version;
+ SSL3SequenceNumber seq_num; /* DTLS only */
+ sslBuffer *buf;
} SSL3Ciphertext;
struct ssl3KeyPairStr {
- SECKEYPrivateKey * privKey;
- SECKEYPublicKey * pubKey;
- PRInt32 refCount; /* use PR_Atomic calls for this. */
+ SECKEYPrivateKey *privKey;
+ SECKEYPublicKey *pubKey;
+ PRInt32 refCount; /* use PR_Atomic calls for this. */
};
struct ssl3DHParamsStr {
SECItem prime; /* p */
- SECItem base; /* g */
+ SECItem base; /* g */
};
typedef struct SSLWrappedSymWrappingKeyStr {
- SSL3Opaque wrappedSymmetricWrappingkey[512];
- CK_MECHANISM_TYPE symWrapMechanism;
- /* unwrapped symmetric wrapping key uses this mechanism */
- CK_MECHANISM_TYPE asymWrapMechanism;
- /* mechanism used to wrap the SymmetricWrappingKey using
- * server's public and/or private keys. */
- SSL3KEAType exchKeyType; /* type of keys used to wrap SymWrapKey*/
- PRInt32 symWrapMechIndex;
- PRUint16 wrappedSymKeyLen;
+ SSL3Opaque wrappedSymmetricWrappingkey[512];
+ CK_MECHANISM_TYPE symWrapMechanism;
+ /* unwrapped symmetric wrapping key uses this mechanism */
+ CK_MECHANISM_TYPE asymWrapMechanism;
+ /* mechanism used to wrap the SymmetricWrappingKey using
+ * server's public and/or private keys. */
+ SSL3KEAType exchKeyType; /* type of keys used to wrap SymWrapKey*/
+ PRInt32 symWrapMechIndex;
+ PRUint16 wrappedSymKeyLen;
} SSLWrappedSymWrappingKey;
typedef struct SessionTicketStr {
- PRUint16 ticket_version;
- SSL3ProtocolVersion ssl_version;
- ssl3CipherSuite cipher_suite;
- SSLCompressionMethod compression_method;
- SSLSignType authAlgorithm;
- PRUint32 authKeyBits;
- SSLKEAType keaType;
- PRUint32 keaKeyBits;
+ PRUint16 ticket_version;
+ SSL3ProtocolVersion ssl_version;
+ ssl3CipherSuite cipher_suite;
+ SSLCompressionMethod compression_method;
+ SSLSignType authAlgorithm;
+ PRUint32 authKeyBits;
+ SSLKEAType keaType;
+ PRUint32 keaKeyBits;
/*
* exchKeyType and msWrapMech contain meaningful values only if
* ms_is_wrapped is true.
*/
- PRUint8 ms_is_wrapped;
- SSLKEAType exchKeyType; /* XXX(wtc): same as keaType above? */
- CK_MECHANISM_TYPE msWrapMech;
- PRUint16 ms_length;
- SSL3Opaque master_secret[48];
- PRBool extendedMasterSecretUsed;
- ClientIdentity client_identity;
- SECItem peer_cert;
- PRUint32 timestamp;
- SECItem srvName; /* negotiated server name */
-} SessionTicket;
+ PRUint8 ms_is_wrapped;
+ SSLKEAType exchKeyType; /* XXX(wtc): same as keaType above? */
+ CK_MECHANISM_TYPE msWrapMech;
+ PRUint16 ms_length;
+ SSL3Opaque master_secret[48];
+ PRBool extendedMasterSecretUsed;
+ ClientIdentity client_identity;
+ SECItem peer_cert;
+ PRUint32 timestamp;
+ SECItem srvName; /* negotiated server name */
+} SessionTicket;
/*
* SSL2 buffers used in SSL3.
@@ -1137,112 +1149,111 @@ typedef struct SessionTicketStr {
/*
** This is "ci", as in "ss->sec.ci".
**
-** Protection: All the variables in here are protected by
-** firstHandshakeLock AND (in ssl3) ssl3HandshakeLock
+** Protection: All the variables in here are protected by
+** firstHandshakeLock AND (in ssl3) ssl3HandshakeLock
*/
struct sslConnectInfoStr {
/* outgoing handshakes appended to this. */
- sslBuffer sendBuf; /*xmitBufLock*/ /* ssl 2 & 3 */
+ sslBuffer sendBuf; /*xmitBufLock*/ /* ssl 2 & 3 */
- PRIPv6Addr peer; /* ssl 2 & 3 */
- unsigned short port; /* ssl 2 & 3 */
+ PRIPv6Addr peer; /* ssl 2 & 3 */
+ unsigned short port; /* ssl 2 & 3 */
- sslSessionID *sid; /* ssl 2 & 3 */
+ sslSessionID *sid; /* ssl 2 & 3 */
/* see CIS_HAVE defines below for the bit values in *elements. */
- char elements; /* ssl2 only */
- char requiredElements; /* ssl2 only */
- char sentElements; /* ssl2 only */
+ char elements; /* ssl2 only */
+ char requiredElements; /* ssl2 only */
+ char sentElements; /* ssl2 only */
- char sentFinished; /* ssl2 only */
+ char sentFinished; /* ssl2 only */
/* Length of server challenge. Used by client when saving challenge */
- int serverChallengeLen; /* ssl2 only */
+ int serverChallengeLen; /* ssl2 only */
/* type of authentication requested by server */
- unsigned char authType; /* ssl2 only */
+ unsigned char authType; /* ssl2 only */
/* Challenge sent by client to server in client-hello message */
/* SSL3 gets a copy of this. See ssl3_StartHandshakeHash(). */
- unsigned char clientChallenge[SSL_MAX_CHALLENGE_BYTES]; /* ssl 2 & 3 */
+ unsigned char clientChallenge[SSL_MAX_CHALLENGE_BYTES]; /* ssl 2 & 3 */
/* Connection-id sent by server to client in server-hello message */
- unsigned char connectionID[SSL_CONNECTIONID_BYTES]; /* ssl2 only */
+ unsigned char connectionID[SSL_CONNECTIONID_BYTES]; /* ssl2 only */
/* Challenge sent by server to client in request-certificate message */
- unsigned char serverChallenge[SSL_MAX_CHALLENGE_BYTES]; /* ssl2 only */
+ unsigned char serverChallenge[SSL_MAX_CHALLENGE_BYTES]; /* ssl2 only */
/* Information kept to handle a request-certificate message */
- unsigned char readKey[SSL_MAX_MASTER_KEY_BYTES]; /* ssl2 only */
- unsigned char writeKey[SSL_MAX_MASTER_KEY_BYTES]; /* ssl2 only */
- unsigned keySize; /* ssl2 only */
+ unsigned char readKey[SSL_MAX_MASTER_KEY_BYTES]; /* ssl2 only */
+ unsigned char writeKey[SSL_MAX_MASTER_KEY_BYTES]; /* ssl2 only */
+ unsigned keySize; /* ssl2 only */
};
/* bit values for ci->elements, ci->requiredElements, sentElements. */
-#define CIS_HAVE_MASTER_KEY 0x01
-#define CIS_HAVE_CERTIFICATE 0x02
-#define CIS_HAVE_FINISHED 0x04
-#define CIS_HAVE_VERIFY 0x08
+#define CIS_HAVE_MASTER_KEY 0x01
+#define CIS_HAVE_CERTIFICATE 0x02
+#define CIS_HAVE_FINISHED 0x04
+#define CIS_HAVE_VERIFY 0x08
/* Note: The entire content of this struct and whatever it points to gets
* blown away by SSL_ResetHandshake(). This is "sec" as in "ss->sec".
*
- * Unless otherwise specified below, the contents of this struct are
+ * Unless otherwise specified below, the contents of this struct are
* protected by firstHandshakeLock AND (in ssl3) ssl3HandshakeLock.
*/
struct sslSecurityInfoStr {
- sslSendFunc send; /*xmitBufLock*/ /* ssl 2 & 3 */
- int isServer; /* Spec Lock?*/ /* ssl 2 & 3 */
- sslBuffer writeBuf; /*xmitBufLock*/ /* ssl 2 & 3 */
-
- int cipherType; /* ssl 2 & 3 */
- int keyBits; /* ssl 2 & 3 */
- int secretKeyBits; /* ssl 2 & 3 */
- CERTCertificate *localCert; /* ssl 2 & 3 */
- CERTCertificate *peerCert; /* ssl 2 & 3 */
- SECKEYPublicKey *peerKey; /* ssl3 only */
-
- SSLSignType authAlgorithm;
- PRUint32 authKeyBits;
- SSLKEAType keaType;
- PRUint32 keaKeyBits;
+ sslSendFunc send; /*xmitBufLock*/ /* ssl 2 & 3 */
+ int isServer; /* Spec Lock?*/ /* ssl 2 & 3 */
+ sslBuffer writeBuf; /*xmitBufLock*/ /* ssl 2 & 3 */
+
+ int cipherType; /* ssl 2 & 3 */
+ int keyBits; /* ssl 2 & 3 */
+ int secretKeyBits; /* ssl 2 & 3 */
+ CERTCertificate *localCert; /* ssl 2 & 3 */
+ CERTCertificate *peerCert; /* ssl 2 & 3 */
+ SECKEYPublicKey *peerKey; /* ssl3 only */
+
+ SSLSignType authAlgorithm;
+ PRUint32 authKeyBits;
+ SSLKEAType keaType;
+ PRUint32 keaKeyBits;
/*
- ** Procs used for SID cache (nonce) management.
- ** Different implementations exist for clients/servers
+ ** Procs used for SID cache (nonce) management.
+ ** Different implementations exist for clients/servers
** The lookup proc is only used for servers. Baloney!
*/
- sslSessionIDCacheFunc cache; /* ssl 2 & 3 */
- sslSessionIDUncacheFunc uncache; /* ssl 2 & 3 */
+ sslSessionIDCacheFunc cache; /* ssl 2 & 3 */
+ sslSessionIDUncacheFunc uncache; /* ssl 2 & 3 */
/*
** everything below here is for ssl2 only.
- ** This stuff is equivalent to SSL3's "spec", and is protected by the
+ ** This stuff is equivalent to SSL3's "spec", and is protected by the
** same "Spec Lock" as used for SSL3's specs.
*/
- PRUint32 sendSequence; /*xmitBufLock*/ /* ssl2 only */
- PRUint32 rcvSequence; /*recvBufLock*/ /* ssl2 only */
+ PRUint32 sendSequence; /*xmitBufLock*/ /* ssl2 only */
+ PRUint32 rcvSequence; /*recvBufLock*/ /* ssl2 only */
/* Hash information; used for one-way-hash functions (MD2, MD5, etc.) */
- const SECHashObject *hash; /* Spec Lock */ /* ssl2 only */
- void *hashcx; /* Spec Lock */ /* ssl2 only */
+ const SECHashObject *hash; /* Spec Lock */ /* ssl2 only */
+ void *hashcx; /* Spec Lock */ /* ssl2 only */
- SECItem sendSecret; /* Spec Lock */ /* ssl2 only */
- SECItem rcvSecret; /* Spec Lock */ /* ssl2 only */
+ SECItem sendSecret; /* Spec Lock */ /* ssl2 only */
+ SECItem rcvSecret; /* Spec Lock */ /* ssl2 only */
/* Session cypher contexts; one for each direction */
- void *readcx; /* Spec Lock */ /* ssl2 only */
- void *writecx; /* Spec Lock */ /* ssl2 only */
- SSLCipher enc; /* Spec Lock */ /* ssl2 only */
- SSLCipher dec; /* Spec Lock */ /* ssl2 only */
- void (*destroy)(void *, PRBool); /* Spec Lock */ /* ssl2 only */
+ void *readcx; /* Spec Lock */ /* ssl2 only */
+ void *writecx; /* Spec Lock */ /* ssl2 only */
+ SSLCipher enc; /* Spec Lock */ /* ssl2 only */
+ SSLCipher dec; /* Spec Lock */ /* ssl2 only */
+ void (*destroy)(void *, PRBool); /* Spec Lock */ /* ssl2 only */
/* Blocking information for the session cypher */
- int blockShift; /* Spec Lock */ /* ssl2 only */
- int blockSize; /* Spec Lock */ /* ssl2 only */
+ int blockShift; /* Spec Lock */ /* ssl2 only */
+ int blockSize; /* Spec Lock */ /* ssl2 only */
/* These are used during a connection handshake */
- sslConnectInfo ci; /* ssl 2 & 3 */
-
+ sslConnectInfo ci; /* ssl 2 & 3 */
};
/*
@@ -1251,187 +1262,178 @@ struct sslSecurityInfoStr {
** Protection: XXX
*/
struct sslSocketStr {
- PRFileDesc * fd;
+ PRFileDesc *fd;
/* Pointer to operations vector for this socket */
- const sslSocketOps * ops;
+ const sslSocketOps *ops;
/* SSL socket options */
- sslOptions opt;
+ sslOptions opt;
/* Enabled version range */
- SSLVersionRange vrange;
+ SSLVersionRange vrange;
/* State flags */
- unsigned long clientAuthRequested;
- unsigned long delayDisabled; /* Nagle delay disabled */
- unsigned long firstHsDone; /* first handshake is complete. */
- unsigned long enoughFirstHsDone; /* enough of the first handshake is
- * done for callbacks to be able to
- * retrieve channel security
- * parameters from the SSL socket. */
- unsigned long handshakeBegun;
- unsigned long lastWriteBlocked;
- unsigned long recvdCloseNotify; /* received SSL EOF. */
- unsigned long TCPconnected;
- unsigned long appDataBuffered;
- unsigned long peerRequestedProtection; /* from old renegotiation */
+ unsigned long clientAuthRequested;
+ unsigned long delayDisabled; /* Nagle delay disabled */
+ unsigned long firstHsDone; /* first handshake is complete. */
+ unsigned long enoughFirstHsDone; /* enough of the first handshake is
+ * done for callbacks to be able to
+ * retrieve channel security
+ * parameters from the SSL socket. */
+ unsigned long handshakeBegun;
+ unsigned long lastWriteBlocked;
+ unsigned long recvdCloseNotify; /* received SSL EOF. */
+ unsigned long TCPconnected;
+ unsigned long appDataBuffered;
+ unsigned long peerRequestedProtection; /* from old renegotiation */
/* version of the protocol to use */
SSL3ProtocolVersion version;
SSL3ProtocolVersion clientHelloVersion; /* version sent in client hello. */
- sslSecurityInfo sec; /* not a pointer any more */
+ sslSecurityInfo sec; /* not a pointer any more */
/* protected by firstHandshakeLock AND (in ssl3) ssl3HandshakeLock. */
- const char *url; /* ssl 2 & 3 */
+ const char *url; /* ssl 2 & 3 */
- sslHandshakeFunc handshake; /*firstHandshakeLock*/
- sslHandshakeFunc nextHandshake; /*firstHandshakeLock*/
- sslHandshakeFunc securityHandshake; /*firstHandshakeLock*/
+ sslHandshakeFunc handshake; /*firstHandshakeLock*/
+ sslHandshakeFunc nextHandshake; /*firstHandshakeLock*/
+ sslHandshakeFunc securityHandshake; /*firstHandshakeLock*/
/* the following variable is only used with socks or other proxies. */
- char * peerID; /* String uniquely identifies target server. */
+ char *peerID; /* String uniquely identifies target server. */
- unsigned char * cipherSpecs;
- unsigned int sizeCipherSpecs;
-const unsigned char * preferredCipher;
+ unsigned char *cipherSpecs;
+ unsigned int sizeCipherSpecs;
+ const unsigned char *preferredCipher;
/* TLS ClientCertificateTypes requested during HandleCertificateRequest. */
/* Will be NULL at all other times. */
- const SECItem *requestedCertTypes;
+ const SECItem *requestedCertTypes;
- ssl3KeyPair * stepDownKeyPair; /* RSA step down keys */
+ ssl3KeyPair *stepDownKeyPair; /* RSA step down keys */
- const ssl3DHParams *dheParams; /* DHE param */
- ssl3KeyPair * dheKeyPair; /* DHE keys */
+ const ssl3DHParams *dheParams; /* DHE param */
+ ssl3KeyPair *dheKeyPair; /* DHE keys */
/* Callbacks */
- SSLAuthCertificate authCertificate;
- void *authCertificateArg;
- SSLGetClientAuthData getClientAuthData;
- void *getClientAuthDataArg;
-#ifdef NSS_PLATFORM_CLIENT_AUTH
- SSLGetPlatformClientAuthData getPlatformClientAuthData;
- void *getPlatformClientAuthDataArg;
-#endif /* NSS_PLATFORM_CLIENT_AUTH */
- SSLSNISocketConfig sniSocketConfig;
- void *sniSocketConfigArg;
- SSLBadCertHandler handleBadCert;
- void *badCertArg;
- SSLHandshakeCallback handshakeCallback;
- void *handshakeCallbackData;
- SSLCanFalseStartCallback canFalseStartCallback;
- void *canFalseStartCallbackData;
- void *pkcs11PinArg;
- SSLNextProtoCallback nextProtoCallback;
- void *nextProtoArg;
+ SSLAuthCertificate authCertificate;
+ void *authCertificateArg;
+ SSLGetClientAuthData getClientAuthData;
+ void *getClientAuthDataArg;
+ SSLSNISocketConfig sniSocketConfig;
+ void *sniSocketConfigArg;
+ SSLBadCertHandler handleBadCert;
+ void *badCertArg;
+ SSLHandshakeCallback handshakeCallback;
+ void *handshakeCallbackData;
+ SSLCanFalseStartCallback canFalseStartCallback;
+ void *canFalseStartCallbackData;
+ void *pkcs11PinArg;
+ SSLNextProtoCallback nextProtoCallback;
+ void *nextProtoArg;
+
SSLClientChannelIDCallback getChannelID;
- void *getChannelIDArg;
+ void *getChannelIDArg;
- PRIntervalTime rTimeout; /* timeout for NSPR I/O */
- PRIntervalTime wTimeout; /* timeout for NSPR I/O */
- PRIntervalTime cTimeout; /* timeout for NSPR I/O */
+ PRIntervalTime rTimeout; /* timeout for NSPR I/O */
+ PRIntervalTime wTimeout; /* timeout for NSPR I/O */
+ PRIntervalTime cTimeout; /* timeout for NSPR I/O */
- PZLock * recvLock; /* lock against multiple reader threads. */
- PZLock * sendLock; /* lock against multiple sender threads. */
+ PZLock *recvLock; /* lock against multiple reader threads. */
+ PZLock *sendLock; /* lock against multiple sender threads. */
- PZMonitor * recvBufLock; /* locks low level recv buffers. */
- PZMonitor * xmitBufLock; /* locks low level xmit buffers. */
+ PZMonitor *recvBufLock; /* locks low level recv buffers. */
+ PZMonitor *xmitBufLock; /* locks low level xmit buffers. */
/* Only one thread may operate on the socket until the initial handshake
** is complete. This Monitor ensures that. Since SSL2 handshake is
** only done once, this is also effectively the SSL2 handshake lock.
*/
- PZMonitor * firstHandshakeLock;
+ PZMonitor *firstHandshakeLock;
/* This monitor protects the ssl3 handshake state machine data.
** Only one thread (reader or writer) may be in the ssl3 handshake state
** machine at any time. */
- PZMonitor * ssl3HandshakeLock;
+ PZMonitor *ssl3HandshakeLock;
/* reader/writer lock, protects the secret data needed to encrypt and MAC
- ** outgoing records, and to decrypt and MAC check incoming ciphertext
+ ** outgoing records, and to decrypt and MAC check incoming ciphertext
** records. */
- NSSRWLock * specLock;
+ NSSRWLock *specLock;
- /* handle to perm cert db (and implicitly to the temp cert db) used
- ** with this socket.
+ /* handle to perm cert db (and implicitly to the temp cert db) used
+ ** with this socket.
*/
- CERTCertDBHandle * dbHandle;
+ CERTCertDBHandle *dbHandle;
- PRThread * writerThread; /* thread holds SSL_LOCK_WRITER lock */
+ PRThread *writerThread; /* thread holds SSL_LOCK_WRITER lock */
- PRUint16 shutdownHow; /* See ssl_SHUTDOWN defines below. */
+ PRUint16 shutdownHow; /* See ssl_SHUTDOWN defines below. */
- PRUint16 allowedByPolicy; /* copy of global policy bits. */
- PRUint16 maybeAllowedByPolicy; /* copy of global policy bits. */
- PRUint16 chosenPreference; /* SSL2 cipher preferences. */
+ PRUint16 allowedByPolicy; /* copy of global policy bits. */
+ PRUint16 maybeAllowedByPolicy; /* copy of global policy bits. */
+ PRUint16 chosenPreference; /* SSL2 cipher preferences. */
sslHandshakingType handshaking;
/* Gather object used for gathering data */
- sslGather gs; /*recvBufLock*/
+ sslGather gs; /*recvBufLock*/
- sslBuffer saveBuf; /*xmitBufLock*/
- sslBuffer pendingBuf; /*xmitBufLock*/
+ sslBuffer saveBuf; /*xmitBufLock*/
+ sslBuffer pendingBuf; /*xmitBufLock*/
/* Configuration state for server sockets */
/* server cert and key for each KEA type */
- sslServerCerts serverCerts[kt_kea_size];
+ sslServerCerts serverCerts[kt_kea_size];
/* each cert needs its own status */
- SECItemArray * certStatusArray[kt_kea_size];
+ SECItemArray *certStatusArray[kt_kea_size];
+ /* Serialized signed certificate timestamps to be sent to the client
+ ** in a TLS extension (server only). Each certificate needs its own
+ ** timestamps item.
+ */
+ SECItem signedCertTimestamps[kt_kea_size];
ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED];
- ssl3KeyPair * ephemeralECDHKeyPair; /* for ECDHE-* handshake */
+ ssl3KeyPair *ephemeralECDHKeyPair; /* for ECDHE-* handshake */
/* SSL3 state info. Formerly was a pointer */
- ssl3State ssl3;
+ ssl3State ssl3;
/*
* TLS extension related data.
*/
/* True when the current session is a stateless resume. */
- PRBool statelessResume;
- TLSExtensionData xtnData;
+ PRBool statelessResume;
+ TLSExtensionData xtnData;
/* Whether we are doing stream or datagram mode */
- SSLProtocolVariant protocolVariant;
+ SSLProtocolVariant protocolVariant;
};
-
-
-/* All the global data items declared here should be protected using the
+/* All the global data items declared here should be protected using the
** ssl_global_data_lock, which is a reader/writer lock.
*/
-extern NSSRWLock * ssl_global_data_lock;
-extern char ssl_debug;
-extern char ssl_trace;
-extern FILE * ssl_trace_iob;
-extern FILE * ssl_keylog_iob;
-extern CERTDistNames * ssl3_server_ca_list;
-extern PRUint32 ssl_sid_timeout;
-extern PRUint32 ssl3_sid_timeout;
-
-extern const char * const ssl_cipherName[];
-extern const char * const ssl3_cipherName[];
-
-extern sslSessionIDLookupFunc ssl_sid_lookup;
-extern sslSessionIDCacheFunc ssl_sid_cache;
+extern NSSRWLock *ssl_global_data_lock;
+extern char ssl_debug;
+extern char ssl_trace;
+extern FILE *ssl_trace_iob;
+extern FILE *ssl_keylog_iob;
+extern CERTDistNames *ssl3_server_ca_list;
+extern PRUint32 ssl_sid_timeout;
+extern PRUint32 ssl3_sid_timeout;
+
+extern const char *const ssl_cipherName[];
+extern const char *const ssl3_cipherName[];
+
+extern sslSessionIDLookupFunc ssl_sid_lookup;
+extern sslSessionIDCacheFunc ssl_sid_cache;
extern sslSessionIDUncacheFunc ssl_sid_uncache;
/************************************************************************/
SEC_BEGIN_PROTOS
-/* Functions for handling SECItemArrays, added in NSS 3.15 */
-extern SECItemArray *SECITEM_AllocArray(PLArenaPool *arena,
- SECItemArray *array,
- unsigned int len);
-extern SECItemArray *SECITEM_DupArray(PLArenaPool *arena,
- const SECItemArray *from);
-extern void SECITEM_FreeArray(SECItemArray *array, PRBool freeit);
-extern void SECITEM_ZfreeArray(SECItemArray *array, PRBool freeit);
-
/* Internal initialization and installation of the SSL error tables */
extern SECStatus ssl_Init(void);
extern SECStatus ssl_InitializePRErrorTable(void);
@@ -1445,15 +1447,15 @@ extern int ssl_DefShutdown(sslSocket *ss, int how);
extern int ssl_DefClose(sslSocket *ss);
extern int ssl_DefRecv(sslSocket *ss, unsigned char *buf, int len, int flags);
extern int ssl_DefSend(sslSocket *ss, const unsigned char *buf,
- int len, int flags);
+ int len, int flags);
extern int ssl_DefRead(sslSocket *ss, unsigned char *buf, int len);
extern int ssl_DefWrite(sslSocket *ss, const unsigned char *buf, int len);
extern int ssl_DefGetpeername(sslSocket *ss, PRNetAddr *name);
extern int ssl_DefGetsockname(sslSocket *ss, PRNetAddr *name);
extern int ssl_DefGetsockopt(sslSocket *ss, PRSockOption optname,
- void *optval, PRInt32 *optlen);
+ void *optval, PRInt32 *optlen);
extern int ssl_DefSetsockopt(sslSocket *ss, PRSockOption optname,
- const void *optval, PRInt32 optlen);
+ const void *optval, PRInt32 optlen);
/* Implementation of ops for socks only case */
extern int ssl_SocksConnect(sslSocket *ss, const PRNetAddr *addr);
@@ -1463,7 +1465,7 @@ extern int ssl_SocksListen(sslSocket *ss, int backlog);
extern int ssl_SocksGetsockname(sslSocket *ss, PRNetAddr *name);
extern int ssl_SocksRecv(sslSocket *ss, unsigned char *buf, int len, int flags);
extern int ssl_SocksSend(sslSocket *ss, const unsigned char *buf,
- int len, int flags);
+ int len, int flags);
extern int ssl_SocksRead(sslSocket *ss, unsigned char *buf, int len);
extern int ssl_SocksWrite(sslSocket *ss, const unsigned char *buf, int len);
@@ -1471,9 +1473,9 @@ extern int ssl_SocksWrite(sslSocket *ss, const unsigned char *buf, int len);
extern int ssl_SecureConnect(sslSocket *ss, const PRNetAddr *addr);
extern PRFileDesc *ssl_SecureAccept(sslSocket *ss, PRNetAddr *addr);
extern int ssl_SecureRecv(sslSocket *ss, unsigned char *buf,
- int len, int flags);
+ int len, int flags);
extern int ssl_SecureSend(sslSocket *ss, const unsigned char *buf,
- int len, int flags);
+ int len, int flags);
extern int ssl_SecureRead(sslSocket *ss, unsigned char *buf, int len);
extern int ssl_SecureWrite(sslSocket *ss, const unsigned char *buf, int len);
extern int ssl_SecureShutdown(sslSocket *ss, int how);
@@ -1485,88 +1487,90 @@ extern PRFileDesc *ssl_SecureSocksAccept(sslSocket *ss, PRNetAddr *addr);
extern PRFileDesc *ssl_FindTop(sslSocket *ss);
/* Gather funcs. */
-extern sslGather * ssl_NewGather(void);
-extern SECStatus ssl_InitGather(sslGather *gs);
-extern void ssl_DestroyGather(sslGather *gs);
-extern int ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags);
-extern int ssl2_GatherRecord(sslSocket *ss, int flags);
-extern SECStatus ssl_GatherRecord1stHandshake(sslSocket *ss);
-
-extern SECStatus ssl2_HandleClientHelloMessage(sslSocket *ss);
-extern SECStatus ssl2_HandleServerHelloMessage(sslSocket *ss);
-
-extern SECStatus ssl_CreateSecurityInfo(sslSocket *ss);
-extern SECStatus ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os);
-extern void ssl_ResetSecurityInfo(sslSecurityInfo *sec, PRBool doMemset);
-extern void ssl_DestroySecurityInfo(sslSecurityInfo *sec);
-
-extern void ssl_PrintBuf(sslSocket *ss, const char *msg, const void *cp, int len);
-extern void ssl_DumpMsg(sslSocket *ss, unsigned char *bp, unsigned len);
-
-extern int ssl_SendSavedWriteData(sslSocket *ss);
-extern SECStatus ssl_SaveWriteData(sslSocket *ss,
- const void* p, unsigned int l);
+extern sslGather *ssl_NewGather(void);
+extern SECStatus ssl_InitGather(sslGather *gs);
+extern void ssl_DestroyGather(sslGather *gs);
+extern int ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags);
+extern int ssl2_GatherRecord(sslSocket *ss, int flags);
+extern SECStatus ssl_GatherRecord1stHandshake(sslSocket *ss);
+
+extern SECStatus ssl2_HandleClientHelloMessage(sslSocket *ss);
+extern SECStatus ssl2_HandleServerHelloMessage(sslSocket *ss);
+
+extern SECStatus ssl_CreateSecurityInfo(sslSocket *ss);
+extern SECStatus ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os);
+extern void ssl_ResetSecurityInfo(sslSecurityInfo *sec, PRBool doMemset);
+extern void ssl_DestroySecurityInfo(sslSecurityInfo *sec);
+
+extern void ssl_PrintBuf(sslSocket *ss, const char *msg, const void *cp, int len);
+extern void ssl_DumpMsg(sslSocket *ss, unsigned char *bp, unsigned len);
+
+extern int ssl_SendSavedWriteData(sslSocket *ss);
+extern SECStatus ssl_SaveWriteData(sslSocket *ss,
+ const void *p, unsigned int l);
extern SECStatus ssl2_BeginClientHandshake(sslSocket *ss);
extern SECStatus ssl2_BeginServerHandshake(sslSocket *ss);
-extern int ssl_Do1stHandshake(sslSocket *ss);
+extern int ssl_Do1stHandshake(sslSocket *ss);
extern SECStatus sslBuffer_Grow(sslBuffer *b, unsigned int newLen);
-extern SECStatus sslBuffer_Append(sslBuffer *b, const void * data,
- unsigned int len);
+extern SECStatus sslBuffer_Append(sslBuffer *b, const void *data,
+ unsigned int len);
-extern void ssl2_UseClearSendFunc(sslSocket *ss);
-extern void ssl_ChooseSessionIDProcs(sslSecurityInfo *sec);
+extern void ssl2_UseClearSendFunc(sslSocket *ss);
+extern void ssl_ChooseSessionIDProcs(sslSecurityInfo *sec);
extern sslSessionID *ssl3_NewSessionID(sslSocket *ss, PRBool is_server);
-extern sslSessionID *ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port,
+extern sslSessionID *ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port,
const char *peerID, const char *urlSvrName);
-extern void ssl_FreeSID(sslSessionID *sid);
+extern void ssl_FreeSID(sslSessionID *sid);
-extern int ssl3_SendApplicationData(sslSocket *ss, const PRUint8 *in,
- int len, int flags);
+extern int ssl3_SendApplicationData(sslSocket *ss, const PRUint8 *in,
+ int len, int flags);
-extern PRBool ssl_FdIsBlocking(PRFileDesc *fd);
+extern PRBool ssl_FdIsBlocking(PRFileDesc *fd);
-extern PRBool ssl_SocketIsBlocking(sslSocket *ss);
+extern PRBool ssl_SocketIsBlocking(sslSocket *ss);
-extern void ssl3_SetAlwaysBlock(sslSocket *ss);
+extern void ssl3_SetAlwaysBlock(sslSocket *ss);
extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled);
-extern void ssl_FinishHandshake(sslSocket *ss);
+extern void ssl_FinishHandshake(sslSocket *ss);
+
+extern SECStatus ssl_CipherPolicySet(PRInt32 which, PRInt32 policy);
-/* Returns PR_TRUE if we are still waiting for the server to respond to our
- * client second round. Once we've received any part of the server's second
- * round then we don't bother trying to false start since it is almost always
- * the case that the NewSessionTicket, ChangeCipherSoec, and Finished messages
- * were sent in the same packet and we want to process them all at the same
- * time. If we were to try to false start in the middle of the server's second
- * round, then we would increase the number of I/O operations
- * (SSL_ForceHandshake/PR_Recv/PR_Send/etc.) needed to finish the handshake.
+extern SECStatus ssl_CipherPrefSetDefault(PRInt32 which, PRBool enabled);
+
+extern SECStatus ssl3_ConstrainRangeByPolicy(void);
+
+/* Returns PR_TRUE if we are still waiting for the server to complete its
+ * response to our client second round. Once we've received the Finished from
+ * the server then there is no need to check false start.
*/
-extern PRBool ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss);
+extern PRBool ssl3_WaitingForServerSecondRound(sslSocket *ss);
extern SECStatus
-ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
- PRBool isServer,
- PRBool isDTLS,
- PRBool capRecordVersion,
- SSL3ContentType type,
- const SSL3Opaque * pIn,
- PRUint32 contentLen,
- sslBuffer * wrBuf);
-extern PRInt32 ssl3_SendRecord(sslSocket *ss, DTLSEpoch epoch,
- SSL3ContentType type,
- const SSL3Opaque* pIn, PRInt32 nIn,
- PRInt32 flags);
-
-#ifdef NSS_ENABLE_ZLIB
+ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec,
+ PRBool isServer,
+ PRBool isDTLS,
+ PRBool capRecordVersion,
+ SSL3ContentType type,
+ const SSL3Opaque *pIn,
+ PRUint32 contentLen,
+ sslBuffer *wrBuf);
+
+extern PRInt32 ssl3_SendRecord(sslSocket *ss, DTLSEpoch epoch,
+ SSL3ContentType type,
+ const SSL3Opaque *pIn, PRInt32 nIn,
+ PRInt32 flags);
+
+#ifdef NSS_SSL_ENABLE_ZLIB
/*
* The DEFLATE algorithm can result in an expansion of 0.1% + 12 bytes. For a
* maximum TLS record payload of 2**14 bytes, that's 29 bytes.
*/
#define SSL3_COMPRESSION_MAX_EXPANSION 29
-#else /* !NSS_ENABLE_ZLIB */
+#else /* !NSS_SSL_ENABLE_ZLIB */
#define SSL3_COMPRESSION_MAX_EXPANSION 0
#endif
@@ -1574,68 +1578,109 @@ extern PRInt32 ssl3_SendRecord(sslSocket *ss, DTLSEpoch epoch,
* make sure there is room in the write buffer for padding and
* other compression and cryptographic expansions.
*/
-#define SSL3_BUFFER_FUDGE 100 + SSL3_COMPRESSION_MAX_EXPANSION
-
-#define SSL_LOCK_READER(ss) if (ss->recvLock) PZ_Lock(ss->recvLock)
-#define SSL_UNLOCK_READER(ss) if (ss->recvLock) PZ_Unlock(ss->recvLock)
-#define SSL_LOCK_WRITER(ss) if (ss->sendLock) PZ_Lock(ss->sendLock)
-#define SSL_UNLOCK_WRITER(ss) if (ss->sendLock) PZ_Unlock(ss->sendLock)
+#define SSL3_BUFFER_FUDGE 100 + SSL3_COMPRESSION_MAX_EXPANSION
+
+#define SSL_LOCK_READER(ss) \
+ if (ss->recvLock) \
+ PZ_Lock(ss->recvLock)
+#define SSL_UNLOCK_READER(ss) \
+ if (ss->recvLock) \
+ PZ_Unlock(ss->recvLock)
+#define SSL_LOCK_WRITER(ss) \
+ if (ss->sendLock) \
+ PZ_Lock(ss->sendLock)
+#define SSL_UNLOCK_WRITER(ss) \
+ if (ss->sendLock) \
+ PZ_Unlock(ss->sendLock)
/* firstHandshakeLock -> recvBufLock */
-#define ssl_Get1stHandshakeLock(ss) \
- { if (!ss->opt.noLocks) { \
- PORT_Assert(PZ_InMonitor((ss)->firstHandshakeLock) || \
- !ssl_HaveRecvBufLock(ss)); \
- PZ_EnterMonitor((ss)->firstHandshakeLock); \
- } }
-#define ssl_Release1stHandshakeLock(ss) \
- { if (!ss->opt.noLocks) PZ_ExitMonitor((ss)->firstHandshakeLock); }
-#define ssl_Have1stHandshakeLock(ss) \
+#define ssl_Get1stHandshakeLock(ss) \
+ { \
+ if (!ss->opt.noLocks) { \
+ PORT_Assert(PZ_InMonitor((ss)->firstHandshakeLock) || \
+ !ssl_HaveRecvBufLock(ss)); \
+ PZ_EnterMonitor((ss)->firstHandshakeLock); \
+ } \
+ }
+#define ssl_Release1stHandshakeLock(ss) \
+ { \
+ if (!ss->opt.noLocks) \
+ PZ_ExitMonitor((ss)->firstHandshakeLock); \
+ }
+#define ssl_Have1stHandshakeLock(ss) \
(PZ_InMonitor((ss)->firstHandshakeLock))
/* ssl3HandshakeLock -> xmitBufLock */
-#define ssl_GetSSL3HandshakeLock(ss) \
- { if (!ss->opt.noLocks) { \
- PORT_Assert(!ssl_HaveXmitBufLock(ss)); \
- PZ_EnterMonitor((ss)->ssl3HandshakeLock); \
- } }
-#define ssl_ReleaseSSL3HandshakeLock(ss) \
- { if (!ss->opt.noLocks) PZ_ExitMonitor((ss)->ssl3HandshakeLock); }
-#define ssl_HaveSSL3HandshakeLock(ss) \
+#define ssl_GetSSL3HandshakeLock(ss) \
+ { \
+ if (!ss->opt.noLocks) { \
+ PORT_Assert(!ssl_HaveXmitBufLock(ss)); \
+ PZ_EnterMonitor((ss)->ssl3HandshakeLock); \
+ } \
+ }
+#define ssl_ReleaseSSL3HandshakeLock(ss) \
+ { \
+ if (!ss->opt.noLocks) \
+ PZ_ExitMonitor((ss)->ssl3HandshakeLock); \
+ }
+#define ssl_HaveSSL3HandshakeLock(ss) \
(PZ_InMonitor((ss)->ssl3HandshakeLock))
-#define ssl_GetSpecReadLock(ss) \
- { if (!ss->opt.noLocks) NSSRWLock_LockRead((ss)->specLock); }
-#define ssl_ReleaseSpecReadLock(ss) \
- { if (!ss->opt.noLocks) NSSRWLock_UnlockRead((ss)->specLock); }
+#define ssl_GetSpecReadLock(ss) \
+ { \
+ if (!ss->opt.noLocks) \
+ NSSRWLock_LockRead((ss)->specLock); \
+ }
+#define ssl_ReleaseSpecReadLock(ss) \
+ { \
+ if (!ss->opt.noLocks) \
+ NSSRWLock_UnlockRead((ss)->specLock); \
+ }
/* NSSRWLock_HaveReadLock is not exported so there's no
* ssl_HaveSpecReadLock macro. */
-#define ssl_GetSpecWriteLock(ss) \
- { if (!ss->opt.noLocks) NSSRWLock_LockWrite((ss)->specLock); }
-#define ssl_ReleaseSpecWriteLock(ss) \
- { if (!ss->opt.noLocks) NSSRWLock_UnlockWrite((ss)->specLock); }
-#define ssl_HaveSpecWriteLock(ss) \
+#define ssl_GetSpecWriteLock(ss) \
+ { \
+ if (!ss->opt.noLocks) \
+ NSSRWLock_LockWrite((ss)->specLock); \
+ }
+#define ssl_ReleaseSpecWriteLock(ss) \
+ { \
+ if (!ss->opt.noLocks) \
+ NSSRWLock_UnlockWrite((ss)->specLock); \
+ }
+#define ssl_HaveSpecWriteLock(ss) \
(NSSRWLock_HaveWriteLock((ss)->specLock))
/* recvBufLock -> ssl3HandshakeLock -> xmitBufLock */
-#define ssl_GetRecvBufLock(ss) \
- { if (!ss->opt.noLocks) { \
- PORT_Assert(!ssl_HaveSSL3HandshakeLock(ss)); \
- PORT_Assert(!ssl_HaveXmitBufLock(ss)); \
- PZ_EnterMonitor((ss)->recvBufLock); \
- } }
-#define ssl_ReleaseRecvBufLock(ss) \
- { if (!ss->opt.noLocks) PZ_ExitMonitor( (ss)->recvBufLock); }
-#define ssl_HaveRecvBufLock(ss) \
+#define ssl_GetRecvBufLock(ss) \
+ { \
+ if (!ss->opt.noLocks) { \
+ PORT_Assert(!ssl_HaveSSL3HandshakeLock(ss)); \
+ PORT_Assert(!ssl_HaveXmitBufLock(ss)); \
+ PZ_EnterMonitor((ss)->recvBufLock); \
+ } \
+ }
+#define ssl_ReleaseRecvBufLock(ss) \
+ { \
+ if (!ss->opt.noLocks) \
+ PZ_ExitMonitor((ss)->recvBufLock); \
+ }
+#define ssl_HaveRecvBufLock(ss) \
(PZ_InMonitor((ss)->recvBufLock))
/* xmitBufLock -> specLock */
-#define ssl_GetXmitBufLock(ss) \
- { if (!ss->opt.noLocks) PZ_EnterMonitor((ss)->xmitBufLock); }
-#define ssl_ReleaseXmitBufLock(ss) \
- { if (!ss->opt.noLocks) PZ_ExitMonitor( (ss)->xmitBufLock); }
-#define ssl_HaveXmitBufLock(ss) \
+#define ssl_GetXmitBufLock(ss) \
+ { \
+ if (!ss->opt.noLocks) \
+ PZ_EnterMonitor((ss)->xmitBufLock); \
+ }
+#define ssl_ReleaseXmitBufLock(ss) \
+ { \
+ if (!ss->opt.noLocks) \
+ PZ_ExitMonitor((ss)->xmitBufLock); \
+ }
+#define ssl_HaveXmitBufLock(ss) \
(PZ_InMonitor((ss)->xmitBufLock))
/* Placeholder value used in version ranges when SSL 3.0 and all
@@ -1643,7 +1688,7 @@ extern PRInt32 ssl3_SendRecord(sslSocket *ss, DTLSEpoch epoch,
*/
#define SSL_LIBRARY_VERSION_NONE 0
-/* SSL_LIBRARY_VERSION_MAX_SUPPORTED is the maximum version that this version
+/* SSL_LIBRARY_VERSION_MAX_SUPPORTED is the maximum version that this version
* of libssl supports. Applications should use SSL_VersionRangeGetSupported at
* runtime to determine which versions are supported by the version of libssl
* in use.
@@ -1659,14 +1704,14 @@ extern PRInt32 ssl3_SendRecord(sslSocket *ss, DTLSEpoch epoch,
((vrange)->min == SSL_LIBRARY_VERSION_NONE)
extern PRBool ssl3_VersionIsSupported(SSLProtocolVariant protocolVariant,
- SSL3ProtocolVersion version);
+ SSL3ProtocolVersion version);
-extern SECStatus ssl3_KeyAndMacDeriveBypass(ssl3CipherSpec * pwSpec,
- const unsigned char * cr, const unsigned char * sr,
- PRBool isTLS, PRBool isExport);
-extern SECStatus ssl3_MasterSecretDeriveBypass( ssl3CipherSpec * pwSpec,
- const unsigned char * cr, const unsigned char * sr,
- const SECItem * pms, PRBool isTLS, PRBool isRSA);
+extern SECStatus ssl3_KeyAndMacDeriveBypass(ssl3CipherSpec *pwSpec,
+ const unsigned char *cr, const unsigned char *sr,
+ PRBool isTLS, PRBool isExport);
+extern SECStatus ssl3_MasterSecretDeriveBypass(ssl3CipherSpec *pwSpec,
+ const unsigned char *cr, const unsigned char *sr,
+ const SECItem *pms, PRBool isTLS, PRBool isRSA);
/* These functions are called from secnav, even though they're "private". */
@@ -1674,13 +1719,13 @@ extern int ssl2_SendErrorMessage(struct sslSocketStr *ss, int error);
extern sslSocket *ssl_FindSocket(PRFileDesc *fd);
extern void ssl_FreeSocket(struct sslSocketStr *ssl);
extern SECStatus SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level,
- SSL3AlertDescription desc);
+ SSL3AlertDescription desc);
extern SECStatus ssl3_DecodeError(sslSocket *ss);
-extern SECStatus ssl3_RestartHandshakeAfterCertReq(sslSocket * ss,
- CERTCertificate * cert,
- SECKEYPrivateKey * key,
- CERTCertificateList *certChain);
+extern SECStatus ssl3_RestartHandshakeAfterCertReq(struct sslSocketStr *ss,
+ CERTCertificate *cert,
+ SECKEYPrivateKey *key,
+ CERTCertificateList *certChain);
extern SECStatus ssl3_RestartHandshakeAfterChannelIDReq(
sslSocket *ss,
@@ -1711,7 +1756,7 @@ SECStatus ssl3_HandleRecord(
int ssl3_GatherAppDataRecord(sslSocket *ss, int flags);
int ssl3_GatherCompleteHandshake(sslSocket *ss, int flags);
/*
- * When talking to export clients or using export cipher suites, servers
+ * When talking to export clients or using export cipher suites, servers
* with public RSA keys larger than 512 bits need to use a 512-bit public
* key, signed by the larger key. The smaller key is a "step down" key.
* Generate that key pair and keep it around.
@@ -1721,59 +1766,63 @@ extern SECStatus ssl3_CreateRSAStepDownKeys(sslSocket *ss);
extern SECStatus ssl3_SelectDHParams(sslSocket *ss);
#ifndef NSS_DISABLE_ECC
-extern void ssl3_FilterECCipherSuitesByServerCerts(sslSocket *ss);
-extern PRBool ssl3_IsECCEnabled(sslSocket *ss);
-extern SECStatus ssl3_DisableECCSuites(sslSocket * ss,
- const ssl3CipherSuite * suite);
-extern PRUint32 ssl3_GetSupportedECCurveMask(sslSocket *ss);
-
+extern void ssl3_FilterECCipherSuitesByServerCerts(sslSocket *ss);
+extern PRBool ssl3_IsECCEnabled(sslSocket *ss);
+extern SECStatus ssl3_DisableECCSuites(sslSocket *ss,
+ const ssl3CipherSuite *suite);
+extern PRUint32 ssl3_GetSupportedECCurveMask(sslSocket *ss);
/* Macro for finding a curve equivalent in strength to RSA key's */
-#define SSL_RSASTRENGTH_TO_ECSTRENGTH(s) \
- ((s <= 1024) ? 160 \
- : ((s <= 2048) ? 224 \
- : ((s <= 3072) ? 256 \
- : ((s <= 7168) ? 384 : 521 ) ) ) )
+/* clang-format off */
+#define SSL_RSASTRENGTH_TO_ECSTRENGTH(s) \
+ ((s <= 1024) ? 160 \
+ : ((s <= 2048) ? 224 \
+ : ((s <= 3072) ? 256 \
+ : ((s <= 7168) ? 384 \
+ : 521 ) ) ) )
+/* clang-format on */
/* Types and names of elliptic curves used in TLS */
-typedef enum { ec_type_explicitPrime = 1,
- ec_type_explicitChar2Curve = 2,
- ec_type_named
+typedef enum { ec_type_explicitPrime = 1,
+ ec_type_explicitChar2Curve = 2,
+ ec_type_named
} ECType;
-typedef enum { ec_noName = 0,
- ec_sect163k1 = 1,
- ec_sect163r1 = 2,
- ec_sect163r2 = 3,
- ec_sect193r1 = 4,
- ec_sect193r2 = 5,
- ec_sect233k1 = 6,
- ec_sect233r1 = 7,
- ec_sect239k1 = 8,
- ec_sect283k1 = 9,
- ec_sect283r1 = 10,
- ec_sect409k1 = 11,
- ec_sect409r1 = 12,
- ec_sect571k1 = 13,
- ec_sect571r1 = 14,
- ec_secp160k1 = 15,
- ec_secp160r1 = 16,
- ec_secp160r2 = 17,
- ec_secp192k1 = 18,
- ec_secp192r1 = 19,
- ec_secp224k1 = 20,
- ec_secp224r1 = 21,
- ec_secp256k1 = 22,
- ec_secp256r1 = 23,
- ec_secp384r1 = 24,
- ec_secp521r1 = 25,
- ec_pastLastName
+typedef enum { ec_noName = 0,
+ ec_sect163k1 = 1,
+ ec_sect163r1 = 2,
+ ec_sect163r2 = 3,
+ ec_sect193r1 = 4,
+ ec_sect193r2 = 5,
+ ec_sect233k1 = 6,
+ ec_sect233r1 = 7,
+ ec_sect239k1 = 8,
+ ec_sect283k1 = 9,
+ ec_sect283r1 = 10,
+ ec_sect409k1 = 11,
+ ec_sect409r1 = 12,
+ ec_sect571k1 = 13,
+ ec_sect571r1 = 14,
+ ec_secp160k1 = 15,
+ ec_secp160r1 = 16,
+ ec_secp160r2 = 17,
+ ec_secp192k1 = 18,
+ ec_secp192r1 = 19,
+ ec_secp224k1 = 20,
+ ec_secp224r1 = 21,
+ ec_secp256k1 = 22,
+ ec_secp256r1 = 23,
+ ec_secp384r1 = 24,
+ ec_secp521r1 = 25,
+ ec_pastLastName
} ECName;
extern SECStatus ssl3_ECName2Params(PLArenaPool *arena, ECName curve,
- SECKEYECParams *params);
-ECName ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits);
+ SECKEYECParams *params);
+ECName ssl3_PubKey2ECName(SECKEYPublicKey *pubKey);
+ECName ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits);
+ECName ssl3_GetCurveNameForServerSocket(sslSocket *ss);
#endif /* NSS_DISABLE_ECC */
@@ -1787,108 +1836,113 @@ extern SECStatus ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool
extern SECStatus ssl2_CipherPrefSet(sslSocket *ss, PRInt32 which, PRBool enabled);
extern SECStatus ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled);
extern SECStatus ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *cipher,
- unsigned int len);
+ unsigned int len);
extern SECStatus ssl3_SetPolicy(ssl3CipherSuite which, PRInt32 policy);
extern SECStatus ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *policy);
extern SECStatus ssl2_SetPolicy(PRInt32 which, PRInt32 policy);
extern SECStatus ssl2_GetPolicy(PRInt32 which, PRInt32 *policy);
-extern void ssl2_InitSocketPolicy(sslSocket *ss);
-extern void ssl3_InitSocketPolicy(sslSocket *ss);
+extern void ssl2_InitSocketPolicy(sslSocket *ss);
+extern void ssl3_InitSocketPolicy(sslSocket *ss);
extern SECStatus ssl3_ConstructV2CipherSpecsHack(sslSocket *ss,
- unsigned char *cs, int *size);
+ unsigned char *cs, int *size);
extern SECStatus ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache);
-extern SECStatus ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
- PRUint32 length);
+extern SECStatus ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
+ PRUint32 length);
extern void ssl3_DestroySSL3Info(sslSocket *ss);
-extern SECStatus ssl3_NegotiateVersion(sslSocket *ss,
- SSL3ProtocolVersion peerVersion,
- PRBool allowLargerPeerVersion);
+extern SECStatus ssl3_NegotiateVersion(sslSocket *ss,
+ SSL3ProtocolVersion peerVersion,
+ PRBool allowLargerPeerVersion);
extern SECStatus ssl_GetPeerInfo(sslSocket *ss);
#ifndef NSS_DISABLE_ECC
/* ECDH functions */
-extern SECStatus ssl3_SendECDHClientKeyExchange(sslSocket * ss,
- SECKEYPublicKey * svrPubKey);
-extern SECStatus ssl3_HandleECDHServerKeyExchange(sslSocket *ss,
- SSL3Opaque *b, PRUint32 length);
-extern SECStatus ssl3_HandleECDHClientKeyExchange(sslSocket *ss,
- SSL3Opaque *b, PRUint32 length,
- SECKEYPublicKey *srvrPubKey,
- SECKEYPrivateKey *srvrPrivKey);
+extern SECStatus ssl3_SendECDHClientKeyExchange(sslSocket *ss,
+ SECKEYPublicKey *svrPubKey);
+extern SECStatus ssl3_HandleECDHServerKeyExchange(sslSocket *ss,
+ SSL3Opaque *b, PRUint32 length);
+extern SECStatus ssl3_HandleECDHClientKeyExchange(sslSocket *ss,
+ SSL3Opaque *b, PRUint32 length,
+ SECKEYPublicKey *srvrPubKey,
+ SECKEYPrivateKey *srvrPrivKey);
extern SECStatus ssl3_SendECDHServerKeyExchange(
sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash);
+SECKEYPublicKey *tls13_ImportECDHKeyShare(
+ sslSocket *ss, SSL3Opaque *b, PRUint32 length, ECName curve);
+ECName tls13_GroupForECDHEKeyShare(ssl3KeyPair *pair);
+unsigned int tls13_SizeOfECDHEKeyShareKEX(ssl3KeyPair *pair);
+SECStatus tls13_EncodeECDHEKeyShareKEX(sslSocket *ss, ssl3KeyPair *pair);
#endif
extern SECStatus ssl3_ComputeCommonKeyHash(SSLHashType hashAlg,
- PRUint8 * hashBuf,
- unsigned int bufLen, SSL3Hashes *hashes,
- PRBool bypassPKCS11);
+ PRUint8 *hashBuf,
+ unsigned int bufLen, SSL3Hashes *hashes,
+ PRBool bypassPKCS11);
extern void ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName);
extern SECStatus ssl3_InitPendingCipherSpec(sslSocket *ss, PK11SymKey *pms);
-extern SECStatus ssl3_AppendHandshake(sslSocket *ss, const void *void_src,
- PRInt32 bytes);
-extern SECStatus ssl3_AppendHandshakeHeader(sslSocket *ss,
- SSL3HandshakeType t, PRUint32 length);
-extern SECStatus ssl3_AppendHandshakeNumber(sslSocket *ss, PRInt32 num,
- PRInt32 lenSize);
-extern SECStatus ssl3_AppendHandshakeVariable( sslSocket *ss,
- const SSL3Opaque *src, PRInt32 bytes, PRInt32 lenSize);
+extern SECStatus ssl3_AppendHandshake(sslSocket *ss, const void *void_src,
+ PRInt32 bytes);
+extern SECStatus ssl3_AppendHandshakeHeader(sslSocket *ss,
+ SSL3HandshakeType t, PRUint32 length);
+extern SECStatus ssl3_AppendHandshakeNumber(sslSocket *ss, PRInt32 num,
+ PRInt32 lenSize);
+extern SECStatus ssl3_AppendHandshakeVariable(sslSocket *ss,
+ const SSL3Opaque *src, PRInt32 bytes, PRInt32 lenSize);
extern SECStatus ssl3_AppendSignatureAndHashAlgorithm(
- sslSocket *ss, const SSLSignatureAndHashAlg* sigAndHash);
-extern SECStatus ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes,
- SSL3Opaque **b, PRUint32 *length);
-extern PRInt32 ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRInt32 bytes,
- SSL3Opaque **b, PRUint32 *length);
-extern SECStatus ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i,
- PRInt32 bytes, SSL3Opaque **b, PRUint32 *length);
+ sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash);
+extern SECStatus ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes,
+ SSL3Opaque **b, PRUint32 *length);
+extern PRInt32 ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRInt32 bytes,
+ SSL3Opaque **b, PRUint32 *length);
+extern SECStatus ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i,
+ PRInt32 bytes, SSL3Opaque **b, PRUint32 *length);
extern PRBool ssl3_IsSupportedSignatureAlgorithm(
const SSLSignatureAndHashAlg *alg);
extern SECStatus ssl3_CheckSignatureAndHashAlgorithmConsistency(
sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash,
- CERTCertificate* cert);
+ CERTCertificate *cert);
extern SECStatus ssl3_ConsumeSignatureAndHashAlgorithm(
sslSocket *ss, SSL3Opaque **b, PRUint32 *length,
SSLSignatureAndHashAlg *out);
-extern SECStatus ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key,
- SECItem *buf, PRBool isTLS);
-extern SECStatus ssl3_VerifySignedHashes(SSL3Hashes *hash,
- CERTCertificate *cert, SECItem *buf, PRBool isTLS,
- void *pwArg);
+extern SECStatus ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key,
+ SECItem *buf, PRBool isTLS);
+extern SECStatus ssl3_VerifySignedHashes(SSL3Hashes *hash,
+ CERTCertificate *cert, SECItem *buf, PRBool isTLS,
+ void *pwArg);
extern SECStatus ssl3_CacheWrappedMasterSecret(sslSocket *ss,
- sslSessionID *sid, ssl3CipherSpec *spec,
- SSL3KEAType effectiveExchKeyType);
+ sslSessionID *sid, ssl3CipherSpec *spec,
+ SSL3KEAType effectiveExchKeyType);
/* Functions that handle ClientHello and ServerHello extensions. */
-extern SECStatus ssl3_HandleServerNameXtn(sslSocket * ss,
- PRUint16 ex_type, SECItem *data);
-extern SECStatus ssl3_HandleSupportedCurvesXtn(sslSocket * ss,
- PRUint16 ex_type, SECItem *data);
-extern SECStatus ssl3_HandleSupportedPointFormatsXtn(sslSocket * ss,
- PRUint16 ex_type, SECItem *data);
+extern SECStatus ssl3_HandleServerNameXtn(sslSocket *ss,
+ PRUint16 ex_type, SECItem *data);
+extern SECStatus ssl3_HandleSupportedCurvesXtn(sslSocket *ss,
+ PRUint16 ex_type, SECItem *data);
+extern SECStatus ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss,
+ PRUint16 ex_type, SECItem *data);
extern SECStatus ssl3_ClientHandleSessionTicketXtn(sslSocket *ss,
- PRUint16 ex_type, SECItem *data);
+ PRUint16 ex_type, SECItem *data);
extern SECStatus ssl3_ServerHandleSessionTicketXtn(sslSocket *ss,
- PRUint16 ex_type, SECItem *data);
+ PRUint16 ex_type, SECItem *data);
/* ClientHello and ServerHello extension senders.
* Note that not all extension senders are exposed here; only those that
* that need exposure.
*/
extern PRInt32 ssl3_SendSessionTicketXtn(sslSocket *ss, PRBool append,
- PRUint32 maxBytes);
+ PRUint32 maxBytes);
/* ClientHello and ServerHello extension senders.
* The code is in ssl3ext.c.
*/
extern PRInt32 ssl3_SendServerNameXtn(sslSocket *ss, PRBool append,
- PRUint32 maxBytes);
+ PRUint32 maxBytes);
/* Assigns new cert, cert chain and keys to ss->serverCerts
* struct. If certChain is NULL, tries to find one. Aborts if
@@ -1900,38 +1954,39 @@ extern SECStatus ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert,
#ifndef NSS_DISABLE_ECC
extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss,
- PRBool append, PRUint32 maxBytes);
+ PRBool append, PRUint32 maxBytes);
extern PRInt32 ssl3_SendSupportedPointFormatsXtn(sslSocket *ss,
- PRBool append, PRUint32 maxBytes);
+ PRBool append, PRUint32 maxBytes);
#endif
/* call the registered extension handlers. */
-extern SECStatus ssl3_HandleHelloExtensions(sslSocket *ss,
- SSL3Opaque **b, PRUint32 *length);
+extern SECStatus ssl3_HandleHelloExtensions(sslSocket *ss,
+ SSL3Opaque **b, PRUint32 *length,
+ SSL3HandshakeType handshakeMessage);
/* Hello Extension related routines. */
extern PRBool ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type);
extern void ssl3_SetSIDSessionTicket(sslSessionID *sid,
- /*in/out*/ NewSessionTicket *session_ticket);
+ /*in/out*/ NewSessionTicket *session_ticket);
extern SECStatus ssl3_SendNewSessionTicket(sslSocket *ss);
extern PRBool ssl_GetSessionTicketKeys(unsigned char *keyName,
- unsigned char *encKey, unsigned char *macKey);
+ unsigned char *encKey, unsigned char *macKey);
extern PRBool ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey,
- SECKEYPublicKey *svrPubKey, void *pwArg,
- unsigned char *keyName, PK11SymKey **aesKey,
- PK11SymKey **macKey);
+ SECKEYPublicKey *svrPubKey, void *pwArg,
+ unsigned char *keyName, PK11SymKey **aesKey,
+ PK11SymKey **macKey);
/* Tell clients to consider tickets valid for this long. */
-#define TLS_EX_SESS_TICKET_LIFETIME_HINT (2 * 24 * 60 * 60) /* 2 days */
-#define TLS_EX_SESS_TICKET_VERSION (0x0101)
+#define TLS_EX_SESS_TICKET_LIFETIME_HINT (2 * 24 * 60 * 60) /* 2 days */
+#define TLS_EX_SESS_TICKET_VERSION (0x0101)
-extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data,
- unsigned int length);
+extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char *data,
+ unsigned int length);
extern SECStatus ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
- unsigned char *out,
- unsigned int *outLen,
- unsigned int outLenMax);
+ unsigned char *out,
+ unsigned int *outLen,
+ unsigned int outLenMax);
/* Construct a new NSPR socket for the app to use */
extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd);
@@ -1941,30 +1996,29 @@ extern void ssl_FreePRSocket(PRFileDesc *fd);
* various ciphers */
extern int ssl3_config_match_init(sslSocket *);
-
/* Create a new ref counted key pair object from two keys. */
-extern ssl3KeyPair * ssl3_NewKeyPair( SECKEYPrivateKey * privKey,
- SECKEYPublicKey * pubKey);
+extern ssl3KeyPair *ssl3_NewKeyPair(SECKEYPrivateKey *privKey,
+ SECKEYPublicKey *pubKey);
/* get a new reference (bump ref count) to an ssl3KeyPair. */
-extern ssl3KeyPair * ssl3_GetKeyPairRef(ssl3KeyPair * keyPair);
+extern ssl3KeyPair *ssl3_GetKeyPairRef(ssl3KeyPair *keyPair);
/* Decrement keypair's ref count and free if zero. */
-extern void ssl3_FreeKeyPair(ssl3KeyPair * keyPair);
+extern void ssl3_FreeKeyPair(ssl3KeyPair *keyPair);
/* calls for accessing wrapping keys across processes. */
extern PRBool
-ssl_GetWrappingKey( PRInt32 symWrapMechIndex,
- SSL3KEAType exchKeyType,
- SSLWrappedSymWrappingKey *wswk);
+ssl_GetWrappingKey(PRInt32 symWrapMechIndex,
+ SSL3KEAType exchKeyType,
+ SSLWrappedSymWrappingKey *wswk);
/* The caller passes in the new value it wants
- * to set. This code tests the wrapped sym key entry in the file on disk.
- * If it is uninitialized, this function writes the caller's value into
- * the disk entry, and returns false.
- * Otherwise, it overwrites the caller's wswk with the value obtained from
- * the disk, and returns PR_TRUE.
- * This is all done while holding the locks/semaphores necessary to make
+ * to set. This code tests the wrapped sym key entry in the file on disk.
+ * If it is uninitialized, this function writes the caller's value into
+ * the disk entry, and returns false.
+ * Otherwise, it overwrites the caller's wswk with the value obtained from
+ * the disk, and returns PR_TRUE.
+ * This is all done while holding the locks/semaphores necessary to make
* the operation atomic.
*/
extern PRBool
@@ -1979,27 +2033,6 @@ extern SECStatus ssl_FreeSymWrapKeysLock(void);
extern SECStatus ssl_InitSessionCacheLocks(void);
-/***************** platform client auth ****************/
-
-#ifdef NSS_PLATFORM_CLIENT_AUTH
-// Releases the platform key.
-extern void ssl_FreePlatformKey(PlatformKey key);
-
-// Implement the client CertificateVerify message for SSL3/TLS1.0
-extern SECStatus ssl3_PlatformSignHashes(SSL3Hashes *hash,
- PlatformKey key, SECItem *buf,
- PRBool isTLS, KeyType keyType);
-
-// Converts a CERTCertList* (A collection of CERTCertificates) into a
-// CERTCertificateList* (A collection of SECItems), or returns NULL if
-// it cannot be converted.
-// This is to allow the platform-supplied chain to be created with purely
-// public API functions, using the preferred CERTCertList mutators, rather
-// pushing this hack to clients.
-extern CERTCertificateList* hack_NewCertificateListFromCertList(
- CERTCertList* list);
-#endif /* NSS_PLATFORM_CLIENT_AUTH */
-
/**************** DTLS-specific functions **************/
extern void dtls_FreeQueuedMessage(DTLSQueuedMessage *msg);
extern void dtls_FreeQueuedMessages(PRCList *lst);
@@ -2007,34 +2040,78 @@ extern void dtls_FreeHandshakeMessages(PRCList *lst);
extern SECStatus dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf);
extern SECStatus dtls_HandleHelloVerifyRequest(sslSocket *ss,
- SSL3Opaque *b, PRUint32 length);
+ SSL3Opaque *b, PRUint32 length);
extern SECStatus dtls_StageHandshakeMessage(sslSocket *ss);
extern SECStatus dtls_QueueMessage(sslSocket *ss, SSL3ContentType type,
- const SSL3Opaque *pIn, PRInt32 nIn);
+ const SSL3Opaque *pIn, PRInt32 nIn);
extern SECStatus dtls_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags);
extern SECStatus dtls_CompressMACEncryptRecord(sslSocket *ss,
- DTLSEpoch epoch,
- PRBool use_epoch,
- SSL3ContentType type,
- const SSL3Opaque *pIn,
- PRUint32 contentLen,
- sslBuffer *wrBuf);
-SECStatus ssl3_DisableNonDTLSSuites(sslSocket * ss);
+ DTLSEpoch epoch,
+ PRBool use_epoch,
+ SSL3ContentType type,
+ const SSL3Opaque *pIn,
+ PRUint32 contentLen,
+ sslBuffer *wrBuf);
+SECStatus ssl3_DisableNonDTLSSuites(sslSocket *ss);
extern SECStatus dtls_StartTimer(sslSocket *ss, DTLSTimerCb cb);
extern SECStatus dtls_RestartTimer(sslSocket *ss, PRBool backoff,
- DTLSTimerCb cb);
+ DTLSTimerCb cb);
extern void dtls_CheckTimer(sslSocket *ss);
extern void dtls_CancelTimer(sslSocket *ss);
extern void dtls_FinishedTimerCb(sslSocket *ss);
extern void dtls_SetMTU(sslSocket *ss, PRUint16 advertised);
extern void dtls_InitRecvdRecords(DTLSRecvdRecords *records);
-extern int dtls_RecordGetRecvd(DTLSRecvdRecords *records, PRUint64 seq);
+extern int dtls_RecordGetRecvd(const DTLSRecvdRecords *records, PRUint64 seq);
extern void dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq);
extern void dtls_RehandshakeCleanup(sslSocket *ss);
extern SSL3ProtocolVersion
dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv);
extern SSL3ProtocolVersion
dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv);
+extern PRBool dtls_IsRelevant(sslSocket *ss, const ssl3CipherSpec *crSpec,
+ const SSL3Ciphertext *cText, PRUint64 *seqNum);
+
+CK_MECHANISM_TYPE ssl3_Alg2Mech(SSLCipherAlgorithm calg);
+SECStatus ssl3_SetupPendingCipherSpec(sslSocket *ss);
+SECStatus ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags);
+SECStatus ssl3_SendCertificate(sslSocket *ss);
+SECStatus ssl3_CompleteHandleCertificate(sslSocket *ss,
+ SSL3Opaque *b, PRUint32 length);
+SECStatus ssl3_SendEmptyCertificate(sslSocket *ss);
+SECStatus ssl3_SendCertificateStatus(sslSocket *ss);
+SECStatus ssl3_CompleteHandleCertificateStatus(sslSocket *ss, SSL3Opaque *b,
+ PRUint32 length);
+SECStatus ssl3_EncodeCertificateRequestSigAlgs(sslSocket *ss, PRUint8 *buf,
+ unsigned maxLen, PRUint32 *len);
+void ssl3_GetCertificateRequestCAs(sslSocket *ss, int *calenp, SECItem **namesp,
+ int *nnamesp);
+SECStatus ssl3_ParseCertificateRequestCAs(sslSocket *ss, SSL3Opaque **b,
+ PRUint32 *length, PLArenaPool *arena,
+ CERTDistNames *ca_list);
+SECStatus ssl3_CompleteHandleCertificateRequest(sslSocket *ss,
+ SECItem *algorithms,
+ CERTDistNames *ca_list);
+SECStatus ssl3_SendCertificateVerify(sslSocket *ss,
+ SECKEYPrivateKey *privKey);
+SECStatus ssl3_SendServerHello(sslSocket *ss);
+SECOidTag ssl3_TLSHashAlgorithmToOID(SSLHashType hashFunc);
+SECStatus ssl3_ComputeHandshakeHashes(sslSocket *ss,
+ ssl3CipherSpec *spec,
+ SSL3Hashes *hashes,
+ PRUint32 sender);
+void ssl3_BumpSequenceNumber(SSL3SequenceNumber *num);
+PRInt32 tls13_ServerSendKeyShareXtn(sslSocket *ss, PRBool append,
+ PRUint32 maxBytes);
+#ifndef NSS_DISABLE_ECC
+SECStatus ssl3_CreateECDHEphemeralKeyPair(ECName ec_curve,
+ ssl3KeyPair **keyPair);
+PK11SymKey *tls13_ComputeECDHSharedKey(sslSocket *ss,
+ SECKEYPrivateKey *myPrivKey,
+ SECKEYPublicKey *peerKey);
+#endif
+
+/* Pull in TLS 1.3 functions */
+#include "tls13con.h"
/********************** misc calls *********************/
@@ -2046,11 +2123,13 @@ extern int ssl_MapLowLevelError(int hiLevelError);
extern PRUint32 ssl_Time(void);
-extern void SSL_AtomicIncrementLong(long * x);
+extern void SSL_AtomicIncrementLong(long *x);
SECStatus SSL_DisableDefaultExportCipherSuites(void);
-SECStatus SSL_DisableExportCipherSuites(PRFileDesc * fd);
-PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite);
+SECStatus SSL_DisableExportCipherSuites(PRFileDesc *fd);
+PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite);
+
+SECStatus ssl3_ApplyNSSPolicy(void);
extern SECStatus
ssl3_TLSPRFWithMasterSecret(ssl3CipherSpec *spec,
diff --git a/chromium/net/third_party/nss/ssl/sslinfo.c b/chromium/net/third_party/nss/ssl/sslinfo.c
index bef3190f367..c59879c9c1b 100644
--- a/chromium/net/third_party/nss/ssl/sslinfo.c
+++ b/chromium/net/third_party/nss/ssl/sslinfo.c
@@ -9,34 +9,37 @@ static const char *
ssl_GetCompressionMethodName(SSLCompressionMethod compression)
{
switch (compression) {
- case ssl_compression_null:
- return "NULL";
+ case ssl_compression_null:
+ return "NULL";
#ifdef NSS_ENABLE_ZLIB
- case ssl_compression_deflate:
- return "DEFLATE";
+ case ssl_compression_deflate:
+ return "DEFLATE";
#endif
- default:
- return "???";
+ default:
+ return "???";
}
}
-SECStatus
+SECStatus
SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
{
- sslSocket * ss;
- SSLChannelInfo inf;
- sslSessionID * sid;
+ sslSocket *ss;
+ SSLChannelInfo inf;
+ sslSessionID *sid;
- if (!info || len < sizeof inf.length) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ /* Check if we can properly return the length of data written and that
+ * we're not asked to return more information than we know how to provide.
+ */
+ if (!info || len < sizeof inf.length || len > sizeof inf) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelInfo",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelInfo",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
memset(&inf, 0, sizeof inf);
@@ -44,42 +47,46 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
if (ss->opt.useSecurity && ss->enoughFirstHsDone) {
sid = ss->sec.ci.sid;
- inf.protocolVersion = ss->version;
- inf.authKeyBits = ss->sec.authKeyBits;
- inf.keaKeyBits = ss->sec.keaKeyBits;
- if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */
- inf.cipherSuite = ss->sec.cipherType | 0xff00;
- inf.compressionMethod = ssl_compression_null;
- inf.compressionMethodName = "N/A";
- } else if (ss->ssl3.initialized) { /* SSL3 and TLS */
- ssl_GetSpecReadLock(ss);
- /* XXX The cipher suite should be in the specs and this
- * function should get it from cwSpec rather than from the "hs".
- * See bug 275744 comment 69 and bug 766137.
- */
- inf.cipherSuite = ss->ssl3.hs.cipher_suite;
- inf.compressionMethod = ss->ssl3.cwSpec->compression_method;
- ssl_ReleaseSpecReadLock(ss);
- inf.compressionMethodName =
- ssl_GetCompressionMethodName(inf.compressionMethod);
- }
- if (sid) {
- inf.creationTime = sid->creationTime;
- inf.lastAccessTime = sid->lastAccessTime;
- inf.expirationTime = sid->expirationTime;
- inf.extendedMasterSecretUsed = sid->u.ssl3.keys.extendedMasterSecretUsed;
-
- if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */
- inf.sessionIDLength = SSL2_SESSIONID_BYTES;
- memcpy(inf.sessionID, sid->u.ssl2.sessionID,
- SSL2_SESSIONID_BYTES);
- } else {
- unsigned int sidLen = sid->u.ssl3.sessionIDLength;
- sidLen = PR_MIN(sidLen, sizeof inf.sessionID);
- inf.sessionIDLength = sidLen;
- memcpy(inf.sessionID, sid->u.ssl3.sessionID, sidLen);
- }
- }
+ inf.protocolVersion = ss->version;
+ inf.authKeyBits = ss->sec.authKeyBits;
+ inf.keaKeyBits = ss->sec.keaKeyBits;
+ if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */
+ inf.cipherSuite = ss->sec.cipherType | 0xff00;
+ inf.compressionMethod = ssl_compression_null;
+ inf.compressionMethodName = "N/A";
+ } else if (ss->ssl3.initialized) { /* SSL3 and TLS */
+ ssl_GetSpecReadLock(ss);
+ /* XXX The cipher suite should be in the specs and this
+ * function should get it from cwSpec rather than from the "hs".
+ * See bug 275744 comment 69 and bug 766137.
+ */
+ inf.cipherSuite = ss->ssl3.hs.cipher_suite;
+ inf.compressionMethod = ss->ssl3.cwSpec->compression_method;
+ ssl_ReleaseSpecReadLock(ss);
+ inf.compressionMethodName =
+ ssl_GetCompressionMethodName(inf.compressionMethod);
+ }
+ if (sid) {
+ inf.creationTime = sid->creationTime;
+ inf.lastAccessTime = sid->lastAccessTime;
+ inf.expirationTime = sid->expirationTime;
+ inf.extendedMasterSecretUsed =
+ (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 ||
+ sid->u.ssl3.keys.extendedMasterSecretUsed)
+ ? PR_TRUE
+ : PR_FALSE;
+
+ if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */
+ inf.sessionIDLength = SSL2_SESSIONID_BYTES;
+ memcpy(inf.sessionID, sid->u.ssl2.sessionID,
+ SSL2_SESSIONID_BYTES);
+ } else {
+ unsigned int sidLen = sid->u.ssl3.sessionIDLength;
+ sidLen = PR_MIN(sidLen, sizeof inf.sessionID);
+ inf.sessionIDLength = sidLen;
+ memcpy(inf.sessionID, sid->u.ssl3.sessionID, sidLen);
+ }
+ }
}
memcpy(info, &inf, inf.length);
@@ -95,7 +102,10 @@ SSL_GetPreliminaryChannelInfo(PRFileDesc *fd,
sslSocket *ss;
SSLPreliminaryChannelInfo inf;
- if (!info || len < sizeof inf.length) {
+ /* Check if we can properly return the length of data written and that
+ * we're not asked to return more information than we know how to provide.
+ */
+ if (!info || len < sizeof inf.length || len > sizeof inf) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@@ -123,200 +133,206 @@ SSL_GetPreliminaryChannelInfo(PRFileDesc *fd,
return SECSuccess;
}
-
#define CS(x) x, #x
#define CK(x) x | 0xff00, #x
-#define S_DSA "DSA", ssl_auth_dsa
-#define S_RSA "RSA", ssl_auth_rsa
-#define S_KEA "KEA", ssl_auth_kea
+#define S_DSA "DSA", ssl_auth_dsa
+#define S_RSA "RSA", ssl_auth_rsa
+#define S_KEA "KEA", ssl_auth_kea
#define S_ECDSA "ECDSA", ssl_auth_ecdsa
-#define K_DHE "DHE", kt_dh
-#define K_RSA "RSA", kt_rsa
-#define K_KEA "KEA", kt_kea
-#define K_ECDH "ECDH", kt_ecdh
-#define K_ECDHE "ECDHE", kt_ecdh
+#define K_DHE "DHE", kt_dh
+#define K_RSA "RSA", kt_rsa
+#define K_KEA "KEA", kt_kea
+#define K_ECDH "ECDH", kt_ecdh
+#define K_ECDHE "ECDHE", kt_ecdh
-#define C_SEED "SEED", calg_seed
+#define C_SEED "SEED", calg_seed
#define C_CAMELLIA "CAMELLIA", calg_camellia
-#define C_AES "AES", calg_aes
-#define C_RC4 "RC4", calg_rc4
-#define C_RC2 "RC2", calg_rc2
-#define C_DES "DES", calg_des
-#define C_3DES "3DES", calg_3des
-#define C_NULL "NULL", calg_null
-#define C_SJ "SKIPJACK", calg_sj
+#define C_AES "AES", calg_aes
+#define C_RC4 "RC4", calg_rc4
+#define C_RC2 "RC2", calg_rc2
+#define C_DES "DES", calg_des
+#define C_3DES "3DES", calg_3des
+#define C_NULL "NULL", calg_null
+#define C_SJ "SKIPJACK", calg_sj
#define C_AESGCM "AES-GCM", calg_aes_gcm
#define C_CHACHA20 "CHACHA20POLY1305", calg_chacha20
-#define B_256 256, 256, 256
-#define B_128 128, 128, 128
-#define B_3DES 192, 156, 112
-#define B_SJ 96, 80, 80
-#define B_DES 64, 56, 56
-#define B_56 128, 56, 56
-#define B_40 128, 40, 40
-#define B_0 0, 0, 0
+#define B_256 256, 256, 256
+#define B_128 128, 128, 128
+#define B_3DES 192, 156, 112
+#define B_SJ 96, 80, 80
+#define B_DES 64, 56, 56
+#define B_56 128, 56, 56
+#define B_40 128, 40, 40
+#define B_0 0, 0, 0
#define M_AEAD_128 "AEAD", ssl_mac_aead, 128
#define M_SHA256 "SHA256", ssl_hmac_sha256, 256
-#define M_SHA "SHA1", ssl_mac_sha, 160
-#define M_MD5 "MD5", ssl_mac_md5, 128
-#define M_NULL "NULL", ssl_mac_null, 0
+#define M_SHA "SHA1", ssl_mac_sha, 160
+#define M_MD5 "MD5", ssl_mac_md5, 128
+#define M_NULL "NULL", ssl_mac_null, 0
+/* clang-format off */
static const SSLCipherSuiteInfo suiteInfo[] = {
-/* <------ Cipher suite --------------------> <auth> <KEA> <bulk cipher> <MAC> <FIPS> */
-{0,CS(TLS_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_RSA, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0, },
-
-{0,CS(TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, },
-{0,CS(TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, },
-{0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0, },
-{0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0, },
-{0,CS(TLS_DHE_DSS_WITH_AES_256_CBC_SHA), S_DSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0, },
-{0,CS(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256), S_DSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0, },
-{0,CS(TLS_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, },
-{0,CS(TLS_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_RSA, C_AES, B_256, M_SHA256, 1, 0, 0, },
-{0,CS(TLS_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_RSA, C_AES, B_256, M_SHA, 1, 0, 0, },
-
-{0,CS(TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0, },
-{0,CS(TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0, },
-{0,CS(TLS_DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, 0, 0, 0, },
-{0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0, },
-{0,CS(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0, },
-{0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, },
-{0,CS(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256), S_DSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0, },
-{0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, },
-{0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256), S_DSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0, },
-{0,CS(TLS_RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED,B_128, M_SHA, 1, 0, 0, },
-{0,CS(TLS_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_128, M_SHA, 0, 0, 0, },
-{0,CS(TLS_RSA_WITH_RC4_128_SHA), S_RSA, K_RSA, C_RC4, B_128, M_SHA, 0, 0, 0, },
-{0,CS(TLS_RSA_WITH_RC4_128_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, 0, 0, 0, },
-{0,CS(TLS_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_RSA, C_AES, B_128, M_SHA256, 1, 0, 0, },
-{0,CS(TLS_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_RSA, C_AES, B_128, M_SHA, 1, 0, 0, },
-
-{0,CS(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0, },
-{0,CS(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA), S_DSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0, },
-{0,CS(SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 1, },
-{0,CS(TLS_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 0, },
-
-{0,CS(TLS_DHE_RSA_WITH_DES_CBC_SHA), S_RSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0, },
-{0,CS(TLS_DHE_DSS_WITH_DES_CBC_SHA), S_DSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0, },
-{0,CS(SSL_RSA_FIPS_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 1, },
-{0,CS(TLS_RSA_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 0, },
-
-{0,CS(TLS_RSA_EXPORT1024_WITH_RC4_56_SHA), S_RSA, K_RSA, C_RC4, B_56, M_SHA, 0, 1, 0, },
-{0,CS(TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 1, 0, },
-{0,CS(TLS_RSA_EXPORT_WITH_RC4_40_MD5), S_RSA, K_RSA, C_RC4, B_40, M_MD5, 0, 1, 0, },
-{0,CS(TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5), S_RSA, K_RSA, C_RC2, B_40, M_MD5, 0, 1, 0, },
-{0,CS(TLS_RSA_WITH_NULL_SHA256), S_RSA, K_RSA, C_NULL,B_0, M_SHA256, 0, 1, 0, },
-{0,CS(TLS_RSA_WITH_NULL_SHA), S_RSA, K_RSA, C_NULL,B_0, M_SHA, 0, 1, 0, },
-{0,CS(TLS_RSA_WITH_NULL_MD5), S_RSA, K_RSA, C_NULL,B_0, M_MD5, 0, 1, 0, },
-
-#ifndef NSS_DISABLE_ECC
-/* ECC cipher suites */
-{0,CS(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0, },
-{0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0, },
-
-{0,CS(TLS_ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, },
-{0,CS(TLS_ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0, },
-{0,CS(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0, },
-{0,CS(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0, },
-{0,CS(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0, },
-
-{0,CS(TLS_ECDHE_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0, },
-{0,CS(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0, },
-{0,CS(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDHE, C_3DES, B_3DES, M_SHA, 1, 0, 0, },
-{0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0, },
-{0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0, },
-{0,CS(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0, },
-{0,CS(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305),S_ECDSA,K_ECDHE,C_CHACHA20,B_256,M_AEAD_128,0, 0, 0, },
-
-{0,CS(TLS_ECDH_RSA_WITH_NULL_SHA), S_RSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, },
-{0,CS(TLS_ECDH_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0, },
-{0,CS(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0, },
-{0,CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0, },
-{0,CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0, },
-{0,CS(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305), S_RSA,K_ECDHE,C_CHACHA20,B_256,M_AEAD_128, 0, 0, 0, },
-
-{0,CS(TLS_ECDHE_RSA_WITH_NULL_SHA), S_RSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0, },
-{0,CS(TLS_ECDHE_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0, },
-{0,CS(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDHE, C_3DES, B_3DES, M_SHA, 1, 0, 0, },
-{0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0, },
-{0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0, },
-{0,CS(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0, },
-#endif /* NSS_DISABLE_ECC */
-
-/* SSL 2 table */
-{0,CK(SSL_CK_RC4_128_WITH_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, 0, 0, 0, },
-{0,CK(SSL_CK_RC2_128_CBC_WITH_MD5), S_RSA, K_RSA, C_RC2, B_128, M_MD5, 0, 0, 0, },
-{0,CK(SSL_CK_DES_192_EDE3_CBC_WITH_MD5), S_RSA, K_RSA, C_3DES,B_3DES,M_MD5, 0, 0, 0, },
-{0,CK(SSL_CK_DES_64_CBC_WITH_MD5), S_RSA, K_RSA, C_DES, B_DES, M_MD5, 0, 0, 0, },
-{0,CK(SSL_CK_RC4_128_EXPORT40_WITH_MD5), S_RSA, K_RSA, C_RC4, B_40, M_MD5, 0, 1, 0, },
-{0,CK(SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5), S_RSA, K_RSA, C_RC2, B_40, M_MD5, 0, 1, 0, }
+ /* <------ Cipher suite --------------------> <auth> <KEA> <bulk cipher> <MAC> <FIPS> */
+ {0,CS(TLS_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_RSA, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 },
+ {0,CS(TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_DHE, C_CHACHA20, B_256, M_AEAD_128, 0, 0, 0 },
+
+ {0,CS(TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0 },
+ {0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_DHE_DSS_WITH_AES_256_CBC_SHA), S_DSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256), S_DSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0 },
+ {0,CS(TLS_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_256, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_RSA, C_AES, B_256, M_SHA256, 1, 0, 0 },
+ {0,CS(TLS_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_RSA, C_AES, B_256, M_SHA, 1, 0, 0 },
+
+ {0,CS(TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0 },
+ {0,CS(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 },
+ {0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256), S_DSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 },
+ {0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256), S_DSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0 },
+ {0,CS(TLS_RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED,B_128, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_128, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_RSA_WITH_RC4_128_SHA), S_RSA, K_RSA, C_RC4, B_128, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_RSA_WITH_RC4_128_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, 0, 0, 0 },
+ {0,CS(TLS_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_RSA, C_AES, B_128, M_SHA256, 1, 0, 0 },
+ {0,CS(TLS_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_RSA, C_AES, B_128, M_SHA, 1, 0, 0 },
+
+ {0,CS(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0 },
+ {0,CS(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA), S_DSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0 },
+ {0,CS(SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 1 },
+ {0,CS(TLS_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 0 },
+
+ {0,CS(TLS_DHE_RSA_WITH_DES_CBC_SHA), S_RSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_DHE_DSS_WITH_DES_CBC_SHA), S_DSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0 },
+ {0,CS(SSL_RSA_FIPS_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 1 },
+ {0,CS(TLS_RSA_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 0 },
+
+ {0,CS(TLS_RSA_EXPORT1024_WITH_RC4_56_SHA), S_RSA, K_RSA, C_RC4, B_56, M_SHA, 0, 1, 0 },
+ {0,CS(TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 1, 0 },
+ {0,CS(TLS_RSA_EXPORT_WITH_RC4_40_MD5), S_RSA, K_RSA, C_RC4, B_40, M_MD5, 0, 1, 0 },
+ {0,CS(TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5), S_RSA, K_RSA, C_RC2, B_40, M_MD5, 0, 1, 0 },
+ {0,CS(TLS_RSA_WITH_NULL_SHA256), S_RSA, K_RSA, C_NULL,B_0, M_SHA256, 0, 1, 0 },
+ {0,CS(TLS_RSA_WITH_NULL_SHA), S_RSA, K_RSA, C_NULL,B_0, M_SHA, 0, 1, 0 },
+ {0,CS(TLS_RSA_WITH_NULL_MD5), S_RSA, K_RSA, C_NULL,B_0, M_MD5, 0, 1, 0 },
+
+ #ifndef NSS_DISABLE_ECC
+ /* ECC cipher suites */
+ {0,CS(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 },
+ {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 },
+
+ {0,CS(TLS_ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0 },
+
+ {0,CS(TLS_ECDHE_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDHE, C_3DES, B_3DES, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0 },
+ {0,CS(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), S_ECDSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, 0, 0, 0 },
+
+ {0,CS(TLS_ECDH_RSA_WITH_NULL_SHA), S_RSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_ECDH_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0 },
+
+ {0,CS(TLS_ECDHE_RSA_WITH_NULL_SHA), S_RSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_ECDHE_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0 },
+ {0,CS(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDHE, C_3DES, B_3DES, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0 },
+ {0,CS(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0 },
+ {0,CS(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, 0, 0, 0 },
+ #endif /* NSS_DISABLE_ECC */
+
+ /* SSL 2 table */
+ {0,CK(SSL_CK_RC4_128_WITH_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, 0, 0, 0 },
+ {0,CK(SSL_CK_RC2_128_CBC_WITH_MD5), S_RSA, K_RSA, C_RC2, B_128, M_MD5, 0, 0, 0 },
+ {0,CK(SSL_CK_DES_192_EDE3_CBC_WITH_MD5), S_RSA, K_RSA, C_3DES,B_3DES,M_MD5, 0, 0, 0 },
+ {0,CK(SSL_CK_DES_64_CBC_WITH_MD5), S_RSA, K_RSA, C_DES, B_DES, M_MD5, 0, 0, 0 },
+ {0,CK(SSL_CK_RC4_128_EXPORT40_WITH_MD5), S_RSA, K_RSA, C_RC4, B_40, M_MD5, 0, 1, 0 },
+ {0,CK(SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5), S_RSA, K_RSA, C_RC2, B_40, M_MD5, 0, 1, 0 }
};
+/* clang-format on */
#define NUM_SUITEINFOS ((sizeof suiteInfo) / (sizeof suiteInfo[0]))
-
-SECStatus SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
- SSLCipherSuiteInfo *info, PRUintn len)
+SECStatus
+SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
+ SSLCipherSuiteInfo *info, PRUintn len)
{
unsigned int i;
- len = PR_MIN(len, sizeof suiteInfo[0]);
- if (!info || len < sizeof suiteInfo[0].length) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ /* Check if we can properly return the length of data written and that
+ * we're not asked to return more information than we know how to provide.
+ */
+ if (!info || len < sizeof suiteInfo[0].length ||
+ len > sizeof suiteInfo[0]) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
+ len = PR_MIN(len, sizeof suiteInfo[0]);
for (i = 0; i < NUM_SUITEINFOS; i++) {
- if (suiteInfo[i].cipherSuite == cipherSuite) {
- memcpy(info, &suiteInfo[i], len);
- info->length = len;
- return SECSuccess;
- }
+ if (suiteInfo[i].cipherSuite == cipherSuite) {
+ memcpy(info, &suiteInfo[i], len);
+ info->length = len;
+ return SECSuccess;
+ }
}
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
-/* This function might be a candidate to be public.
+/* This function might be a candidate to be public.
* Disables all export ciphers in the default set of enabled ciphers.
*/
-SECStatus
+SECStatus
SSL_DisableDefaultExportCipherSuites(void)
{
- const SSLCipherSuiteInfo * pInfo = suiteInfo;
+ const SSLCipherSuiteInfo *pInfo = suiteInfo;
unsigned int i;
for (i = 0; i < NUM_SUITEINFOS; ++i, ++pInfo) {
- if (pInfo->isExportable) {
- PORT_CheckSuccess(SSL_CipherPrefSetDefault(pInfo->cipherSuite, PR_FALSE));
- }
+ if (pInfo->isExportable) {
+ PORT_CheckSuccess(SSL_CipherPrefSetDefault(pInfo->cipherSuite, PR_FALSE));
+ }
}
return SECSuccess;
}
-/* This function might be a candidate to be public,
+/* This function might be a candidate to be public,
* except that it takes an sslSocket pointer as an argument.
* A Public version would take a PRFileDesc pointer.
* Disables all export ciphers in the default set of enabled ciphers.
*/
-SECStatus
-SSL_DisableExportCipherSuites(PRFileDesc * fd)
+SECStatus
+SSL_DisableExportCipherSuites(PRFileDesc *fd)
{
- const SSLCipherSuiteInfo * pInfo = suiteInfo;
+ const SSLCipherSuiteInfo *pInfo = suiteInfo;
unsigned int i;
for (i = 0; i < NUM_SUITEINFOS; ++i, ++pInfo) {
- if (pInfo->isExportable) {
- PORT_CheckSuccess(SSL_CipherPrefSet(fd, pInfo->cipherSuite, PR_FALSE));
- }
+ if (pInfo->isExportable) {
+ PORT_CheckSuccess(SSL_CipherPrefSet(fd, pInfo->cipherSuite, PR_FALSE));
+ }
}
return SECSuccess;
}
-/* Tells us if the named suite is exportable
+/* Tells us if the named suite is exportable
* returns false for unknown suites.
*/
PRBool
@@ -324,14 +340,14 @@ SSL_IsExportCipherSuite(PRUint16 cipherSuite)
{
unsigned int i;
for (i = 0; i < NUM_SUITEINFOS; i++) {
- if (suiteInfo[i].cipherSuite == cipherSuite) {
- return (PRBool)(suiteInfo[i].isExportable);
- }
+ if (suiteInfo[i].cipherSuite == cipherSuite) {
+ return (PRBool)(suiteInfo[i].isExportable);
+ }
}
return PR_FALSE;
}
-SECItem*
+SECItem *
SSL_GetNegotiatedHostInfo(PRFileDesc *fd)
{
SECItem *sniName = NULL;
@@ -340,9 +356,9 @@ SSL_GetNegotiatedHostInfo(PRFileDesc *fd)
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNegotiatedHostInfo",
- SSL_GETPID(), fd));
- return NULL;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNegotiatedHostInfo",
+ SSL_GETPID(), fd));
+ return NULL;
}
if (ss->sec.isServer) {
@@ -357,7 +373,7 @@ SSL_GetNegotiatedHostInfo(PRFileDesc *fd)
ssl_ReleaseSpecReadLock(ss); /*----------------------------*/
}
return sniName;
- }
+ }
name = SSL_RevealURL(fd);
if (name) {
sniName = PORT_ZNew(SECItem);
@@ -365,8 +381,8 @@ SSL_GetNegotiatedHostInfo(PRFileDesc *fd)
PORT_Free(name);
return NULL;
}
- sniName->data = (void*)name;
- sniName->len = PORT_Strlen(name);
+ sniName->data = (void *)name;
+ sniName->len = PORT_Strlen(name);
}
return sniName;
}
@@ -385,44 +401,42 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd,
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in ExportKeyingMaterial",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in ExportKeyingMaterial",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
ssl_GetRecvBufLock(ss);
ssl_GetSSL3HandshakeLock(ss);
if (ss->version < SSL_LIBRARY_VERSION_3_1_TLS) {
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION);
- ssl_ReleaseSSL3HandshakeLock(ss);
- ssl_ReleaseRecvBufLock(ss);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_ReleaseRecvBufLock(ss);
+ return SECFailure;
}
/* construct PRF arguments */
valLen = SSL3_RANDOM_LENGTH * 2;
if (hasContext) {
- valLen += 2 /* PRUint16 length */ + contextLen;
+ valLen += 2 /* PRUint16 length */ + contextLen;
}
val = PORT_Alloc(valLen);
if (!val) {
- ssl_ReleaseSSL3HandshakeLock(ss);
- ssl_ReleaseRecvBufLock(ss);
- return SECFailure;
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_ReleaseRecvBufLock(ss);
+ return SECFailure;
}
i = 0;
-
PORT_Memcpy(val + i, &ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
i += SSL3_RANDOM_LENGTH;
PORT_Memcpy(val + i, &ss->ssl3.hs.server_random.rand, SSL3_RANDOM_LENGTH);
i += SSL3_RANDOM_LENGTH;
-
if (hasContext) {
- val[i++] = contextLen >> 8;
- val[i++] = contextLen;
- PORT_Memcpy(val + i, context, contextLen);
- i += contextLen;
+ val[i++] = contextLen >> 8;
+ val[i++] = contextLen;
+ PORT_Memcpy(val + i, context, contextLen);
+ i += contextLen;
}
PORT_Assert(i == valLen);
@@ -431,11 +445,11 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd,
*/
ssl_GetSpecReadLock(ss);
if (!ss->ssl3.cwSpec->master_secret && !ss->ssl3.cwSpec->msItem.len) {
- PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
- rv = SECFailure;
+ PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
+ rv = SECFailure;
} else {
- rv = ssl3_TLSPRFWithMasterSecret(ss->ssl3.cwSpec, label, labelLen, val,
- valLen, out, outLen);
+ rv = ssl3_TLSPRFWithMasterSecret(ss->ssl3.cwSpec, label, labelLen, val,
+ valLen, out, outLen);
}
ssl_ReleaseSpecReadLock(ss);
ssl_ReleaseSSL3HandshakeLock(ss);
diff --git a/chromium/net/third_party/nss/ssl/sslinit.c b/chromium/net/third_party/nss/ssl/sslinit.c
index bb9df255f35..0f38c0b57bd 100644
--- a/chromium/net/third_party/nss/ssl/sslinit.c
+++ b/chromium/net/third_party/nss/ssl/sslinit.c
@@ -11,23 +11,49 @@
#include "secerr.h"
#include "ssl.h"
#include "sslimpl.h"
+#include "sslproto.h"
-static int ssl_inited = 0;
+static int ssl_isInited = 0;
+static PRCallOnceType ssl_init = { 0 };
-SECStatus
-ssl_Init(void)
+PRStatus
+ssl_InitCallOnce(void *arg)
{
- if (!ssl_inited) {
- if (ssl_InitializePRErrorTable() != SECSuccess) {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- return (SECFailure);
- }
+ int *error = (int *)arg;
+ SECStatus rv;
+ rv = ssl_InitializePRErrorTable();
+ if (rv != SECSuccess) {
+ *error = SEC_ERROR_NO_MEMORY;
+ return PR_FAILURE;
+ }
#ifdef DEBUG
- ssl3_CheckCipherSuiteOrderConsistency();
+ ssl3_CheckCipherSuiteOrderConsistency();
#endif
- ssl_inited = 1;
+ rv = ssl3_ApplyNSSPolicy();
+ if (rv != SECSuccess) {
+ *error = PORT_GetError();
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+SECStatus
+ssl_Init(void)
+{
+ PRStatus nrv;
+
+ /* short circuit test if we are already inited */
+ if (!ssl_isInited) {
+ int error;
+ /* only do this once at init time, block all others until we are done */
+ nrv = PR_CallOnceWithArg(&ssl_init, ssl_InitCallOnce, &error);
+ if (nrv != PR_SUCCESS) {
+ PORT_SetError(error);
+ return SECFailure;
+ }
+ ssl_isInited = 1;
}
return SECSuccess;
}
diff --git a/chromium/net/third_party/nss/ssl/sslmutex.c b/chromium/net/third_party/nss/ssl/sslmutex.c
index af683daf561..0e2edc9f0e5 100644
--- a/chromium/net/third_party/nss/ssl/sslmutex.c
+++ b/chromium/net/third_party/nss/ssl/sslmutex.c
@@ -4,15 +4,16 @@
#include "seccomon.h"
/* This ifdef should match the one in sslsnce.c */
-#if defined(XP_UNIX) || defined(XP_WIN32) || defined (XP_OS2) || defined(XP_BEOS)
+#if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_OS2) || defined(XP_BEOS)
#include "sslmutex.h"
#include "prerr.h"
-static SECStatus single_process_sslMutex_Init(sslMutex* pMutex)
+static SECStatus
+single_process_sslMutex_Init(sslMutex* pMutex)
{
- PR_ASSERT(pMutex != 0 && pMutex->u.sslLock == 0 );
-
+ PR_ASSERT(pMutex != 0 && pMutex->u.sslLock == 0);
+
pMutex->u.sslLock = PR_NewLock();
if (!pMutex->u.sslLock) {
return SECFailure;
@@ -20,10 +21,11 @@ static SECStatus single_process_sslMutex_Init(sslMutex* pMutex)
return SECSuccess;
}
-static SECStatus single_process_sslMutex_Destroy(sslMutex* pMutex)
+static SECStatus
+single_process_sslMutex_Destroy(sslMutex* pMutex)
{
PR_ASSERT(pMutex != 0);
- PR_ASSERT(pMutex->u.sslLock!= 0);
+ PR_ASSERT(pMutex->u.sslLock != 0);
if (!pMutex->u.sslLock) {
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
return SECFailure;
@@ -32,10 +34,11 @@ static SECStatus single_process_sslMutex_Destroy(sslMutex* pMutex)
return SECSuccess;
}
-static SECStatus single_process_sslMutex_Unlock(sslMutex* pMutex)
+static SECStatus
+single_process_sslMutex_Unlock(sslMutex* pMutex)
{
- PR_ASSERT(pMutex != 0 );
- PR_ASSERT(pMutex->u.sslLock !=0);
+ PR_ASSERT(pMutex != 0);
+ PR_ASSERT(pMutex->u.sslLock != 0);
if (!pMutex->u.sslLock) {
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
return SECFailure;
@@ -44,10 +47,11 @@ static SECStatus single_process_sslMutex_Unlock(sslMutex* pMutex)
return SECSuccess;
}
-static SECStatus single_process_sslMutex_Lock(sslMutex* pMutex)
+static SECStatus
+single_process_sslMutex_Lock(sslMutex* pMutex)
{
PR_ASSERT(pMutex != 0);
- PR_ASSERT(pMutex->u.sslLock != 0 );
+ PR_ASSERT(pMutex->u.sslLock != 0);
if (!pMutex->u.sslLock) {
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
return SECFailure;
@@ -66,7 +70,7 @@ static SECStatus single_process_sslMutex_Lock(sslMutex* pMutex)
#include "pratom.h"
#define SSL_MUTEX_MAGIC 0xfeedfd
-#define NONBLOCKING_POSTS 1 /* maybe this is faster */
+#define NONBLOCKING_POSTS 1 /* maybe this is faster */
#if NONBLOCKING_POSTS
@@ -82,20 +86,20 @@ setNonBlocking(int fd, int nonBlocking)
flags = fcntl(fd, F_GETFL, 0);
if (0 > flags)
- return flags;
+ return flags;
if (nonBlocking)
- flags |= FNONBLOCK;
+ flags |= FNONBLOCK;
else
- flags &= ~FNONBLOCK;
+ flags &= ~FNONBLOCK;
err = fcntl(fd, F_SETFL, flags);
return err;
}
#endif
SECStatus
-sslMutex_Init(sslMutex *pMutex, int shared)
+sslMutex_Init(sslMutex* pMutex, int shared)
{
- int err;
+ int err;
PR_ASSERT(pMutex);
pMutex->isMultiProcess = (PRBool)(shared != 0);
if (!shared) {
@@ -104,17 +108,17 @@ sslMutex_Init(sslMutex *pMutex, int shared)
pMutex->u.pipeStr.mPipes[0] = -1;
pMutex->u.pipeStr.mPipes[1] = -1;
pMutex->u.pipeStr.mPipes[2] = -1;
- pMutex->u.pipeStr.nWaiters = 0;
+ pMutex->u.pipeStr.nWaiters = 0;
err = pipe(pMutex->u.pipeStr.mPipes);
if (err) {
- nss_MD_unix_map_default_error(errno);
- return err;
+ nss_MD_unix_map_default_error(errno);
+ return err;
}
#if NONBLOCKING_POSTS
err = setNonBlocking(pMutex->u.pipeStr.mPipes[1], 1);
if (err)
- goto loser;
+ goto loser;
#endif
pMutex->u.pipeStr.mPipes[2] = SSL_MUTEX_MAGIC;
@@ -135,26 +139,26 @@ loser:
}
SECStatus
-sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal)
+sslMutex_Destroy(sslMutex* pMutex, PRBool processLocal)
{
if (PR_FALSE == pMutex->isMultiProcess) {
return single_process_sslMutex_Destroy(pMutex);
}
if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return SECFailure;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return SECFailure;
}
close(pMutex->u.pipeStr.mPipes[0]);
close(pMutex->u.pipeStr.mPipes[1]);
if (processLocal) {
- return SECSuccess;
+ return SECSuccess;
}
pMutex->u.pipeStr.mPipes[0] = -1;
pMutex->u.pipeStr.mPipes[1] = -1;
pMutex->u.pipeStr.mPipes[2] = -1;
- pMutex->u.pipeStr.nWaiters = 0;
+ pMutex->u.pipeStr.nWaiters = 0;
return SECSuccess;
}
@@ -164,13 +168,12 @@ sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal)
/* nWaiters includes the holder of the lock (if any) and the number
** threads waiting for it. After incrementing nWaiters, if the count
-** is exactly 1, then you have the lock and may proceed. If the
+** is exactly 1, then you have the lock and may proceed. If the
** count is greater than 1, then you must wait on the pipe.
-*/
-
+*/
-SECStatus
-sslMutex_Unlock(sslMutex *pMutex)
+SECStatus
+sslMutex_Unlock(sslMutex* pMutex)
{
PRInt32 newValue;
if (PR_FALSE == pMutex->isMultiProcess) {
@@ -178,30 +181,30 @@ sslMutex_Unlock(sslMutex *pMutex)
}
if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return SECFailure;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return SECFailure;
}
/* Do Memory Barrier here. */
newValue = PR_ATOMIC_DECREMENT(&pMutex->u.pipeStr.nWaiters);
if (newValue > 0) {
- int cc;
- char c = 1;
- do {
- cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1);
- } while (cc < 0 && (errno == EINTR || errno == EAGAIN));
- if (cc != 1) {
- if (cc < 0)
- nss_MD_unix_map_default_error(errno);
- else
- PORT_SetError(PR_UNKNOWN_ERROR);
- return SECFailure;
- }
+ int cc;
+ char c = 1;
+ do {
+ cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1);
+ } while (cc < 0 && (errno == EINTR || errno == EAGAIN));
+ if (cc != 1) {
+ if (cc < 0)
+ nss_MD_unix_map_default_error(errno);
+ else
+ PORT_SetError(PR_UNKNOWN_ERROR);
+ return SECFailure;
+ }
}
return SECSuccess;
}
-SECStatus
-sslMutex_Lock(sslMutex *pMutex)
+SECStatus
+sslMutex_Lock(sslMutex* pMutex)
{
PRInt32 newValue;
if (PR_FALSE == pMutex->isMultiProcess) {
@@ -209,88 +212,88 @@ sslMutex_Lock(sslMutex *pMutex)
}
if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return SECFailure;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return SECFailure;
}
newValue = PR_ATOMIC_INCREMENT(&pMutex->u.pipeStr.nWaiters);
/* Do Memory Barrier here. */
if (newValue > 1) {
- int cc;
- char c;
- do {
- cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1);
- } while (cc < 0 && errno == EINTR);
- if (cc != 1) {
- if (cc < 0)
- nss_MD_unix_map_default_error(errno);
- else
- PORT_SetError(PR_UNKNOWN_ERROR);
- return SECFailure;
- }
+ int cc;
+ char c;
+ do {
+ cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1);
+ } while (cc < 0 && errno == EINTR);
+ if (cc != 1) {
+ if (cc < 0)
+ nss_MD_unix_map_default_error(errno);
+ else
+ PORT_SetError(PR_UNKNOWN_ERROR);
+ return SECFailure;
+ }
}
return SECSuccess;
}
#else
-/* Using Atomic operations requires the use of a memory barrier instruction
+/* Using Atomic operations requires the use of a memory barrier instruction
** on PowerPC, Sparc, and Alpha. NSPR's PR_Atomic functions do not perform
** them, and NSPR does not provide a function that does them (e.g. PR_Barrier).
-** So, we don't use them on those platforms.
+** So, we don't use them on those platforms.
*/
-SECStatus
-sslMutex_Unlock(sslMutex *pMutex)
+SECStatus
+sslMutex_Unlock(sslMutex* pMutex)
{
- int cc;
- char c = 1;
+ int cc;
+ char c = 1;
if (PR_FALSE == pMutex->isMultiProcess) {
return single_process_sslMutex_Unlock(pMutex);
}
if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return SECFailure;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return SECFailure;
}
do {
- cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1);
+ cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1);
} while (cc < 0 && (errno == EINTR || errno == EAGAIN));
if (cc != 1) {
- if (cc < 0)
- nss_MD_unix_map_default_error(errno);
- else
- PORT_SetError(PR_UNKNOWN_ERROR);
- return SECFailure;
+ if (cc < 0)
+ nss_MD_unix_map_default_error(errno);
+ else
+ PORT_SetError(PR_UNKNOWN_ERROR);
+ return SECFailure;
}
return SECSuccess;
}
-SECStatus
-sslMutex_Lock(sslMutex *pMutex)
+SECStatus
+sslMutex_Lock(sslMutex* pMutex)
{
- int cc;
- char c;
+ int cc;
+ char c;
if (PR_FALSE == pMutex->isMultiProcess) {
return single_process_sslMutex_Lock(pMutex);
}
-
+
if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return SECFailure;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return SECFailure;
}
do {
- cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1);
+ cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1);
} while (cc < 0 && errno == EINTR);
if (cc != 1) {
- if (cc < 0)
- nss_MD_unix_map_default_error(errno);
- else
- PORT_SetError(PR_UNKNOWN_ERROR);
- return SECFailure;
+ if (cc < 0)
+ nss_MD_unix_map_default_error(errno);
+ else
+ PORT_SetError(PR_UNKNOWN_ERROR);
+ return SECFailure;
}
return SECSuccess;
@@ -314,7 +317,8 @@ sslMutex_Lock(sslMutex *pMutex)
#ifdef WINNT
-SECStatus sslMutex_2LevelInit(sslMutex *sem)
+SECStatus
+sslMutex_2LevelInit(sslMutex *sem)
{
/* the following adds a PRLock to sslMutex . This is done in each
process of a multi-process server and is only needed on WINNT, if
@@ -330,7 +334,8 @@ SECStatus sslMutex_2LevelInit(sslMutex *sem)
return single_process_sslMutex_Init(sem);
}
-static SECStatus sslMutex_2LevelDestroy(sslMutex *sem)
+static SECStatus
+sslMutex_2LevelDestroy(sslMutex *sem)
{
return single_process_sslMutex_Destroy(sem);
}
@@ -345,26 +350,28 @@ sslMutex_Init(sslMutex *pMutex, int shared)
#endif
HANDLE hMutex;
SECURITY_ATTRIBUTES attributes =
- { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+ { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+
+ PR_ASSERT(pMutex != 0 && (pMutex->u.sslMutx == 0 ||
+ pMutex->u.sslMutx ==
+ INVALID_HANDLE_VALUE));
- PR_ASSERT(pMutex != 0 && (pMutex->u.sslMutx == 0 ||
- pMutex->u.sslMutx == INVALID_HANDLE_VALUE) );
-
pMutex->isMultiProcess = (PRBool)(shared != 0);
-
+
if (PR_FALSE == pMutex->isMultiProcess) {
return single_process_sslMutex_Init(pMutex);
}
-
+
#ifdef WINNT
/* we need a lock on WINNT for fibers in the parent process */
retvalue = sslMutex_2LevelInit(pMutex);
if (SECSuccess != retvalue)
return SECFailure;
#endif
-
- if (!pMutex || ((hMutex = pMutex->u.sslMutx) != 0 &&
- hMutex != INVALID_HANDLE_VALUE)) {
+
+ if (!pMutex || ((hMutex = pMutex->u.sslMutx) != 0 &&
+ hMutex !=
+ INVALID_HANDLE_VALUE)) {
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
return SECFailure;
}
@@ -383,7 +390,7 @@ SECStatus
sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal)
{
HANDLE hMutex;
- int rv;
+ int rv;
int retvalue = SECSuccess;
PR_ASSERT(pMutex != 0);
@@ -391,20 +398,20 @@ sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal)
return single_process_sslMutex_Destroy(pMutex);
}
- /* multi-process mode */
+/* multi-process mode */
#ifdef WINNT
/* on NT, get rid of the PRLock used for fibers within a process */
retvalue = sslMutex_2LevelDestroy(pMutex);
#endif
-
- PR_ASSERT( pMutex->u.sslMutx != 0 &&
- pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
- if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0
- || hMutex == INVALID_HANDLE_VALUE) {
+
+ PR_ASSERT(pMutex->u.sslMutx != 0 &&
+ pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
+ if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 ||
+ hMutex == INVALID_HANDLE_VALUE) {
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
return SECFailure;
}
-
+
rv = CloseHandle(hMutex); /* ignore error */
if (!processLocal && rv) {
pMutex->u.sslMutx = hMutex = INVALID_HANDLE_VALUE;
@@ -416,18 +423,18 @@ sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal)
return retvalue;
}
-int
+int
sslMutex_Unlock(sslMutex *pMutex)
{
- BOOL success = FALSE;
+ BOOL success = FALSE;
HANDLE hMutex;
- PR_ASSERT(pMutex != 0 );
+ PR_ASSERT(pMutex != 0);
if (PR_FALSE == pMutex->isMultiProcess) {
return single_process_sslMutex_Unlock(pMutex);
}
-
- PR_ASSERT(pMutex->u.sslMutx != 0 &&
+
+ PR_ASSERT(pMutex->u.sslMutx != 0 &&
pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 ||
hMutex == INVALID_HANDLE_VALUE) {
@@ -447,12 +454,12 @@ sslMutex_Unlock(sslMutex *pMutex)
#endif
}
-int
+int
sslMutex_Lock(sslMutex *pMutex)
{
- HANDLE hMutex;
- DWORD event;
- DWORD lastError;
+ HANDLE hMutex;
+ DWORD event;
+ DWORD lastError;
SECStatus rv;
SECStatus retvalue = SECSuccess;
PR_ASSERT(pMutex != 0);
@@ -465,42 +472,42 @@ sslMutex_Lock(sslMutex *pMutex)
in the same process */
retvalue = single_process_sslMutex_Lock(pMutex);
#endif
- PR_ASSERT(pMutex->u.sslMutx != 0 &&
+ PR_ASSERT(pMutex->u.sslMutx != 0 &&
pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
- if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 ||
+ if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 ||
hMutex == INVALID_HANDLE_VALUE) {
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return SECFailure; /* what else ? */
+ return SECFailure; /* what else ? */
}
/* acquire the mutex to be the only owner accross all other processes */
event = WaitForSingleObject(hMutex, INFINITE);
switch (event) {
- case WAIT_OBJECT_0:
- case WAIT_ABANDONED:
- rv = SECSuccess;
- break;
+ case WAIT_OBJECT_0:
+ case WAIT_ABANDONED:
+ rv = SECSuccess;
+ break;
- case WAIT_TIMEOUT:
+ case WAIT_TIMEOUT:
#if defined(WAIT_IO_COMPLETION)
- case WAIT_IO_COMPLETION:
+ case WAIT_IO_COMPLETION:
#endif
- default: /* should never happen. nothing we can do. */
- PR_ASSERT(!("WaitForSingleObject returned invalid value."));
- PORT_SetError(PR_UNKNOWN_ERROR);
- rv = SECFailure;
- break;
+ default: /* should never happen. nothing we can do. */
+ PR_ASSERT(!("WaitForSingleObject returned invalid value."));
+ PORT_SetError(PR_UNKNOWN_ERROR);
+ rv = SECFailure;
+ break;
- case WAIT_FAILED: /* failure returns this */
- rv = SECFailure;
- lastError = GetLastError(); /* for debugging */
- nss_MD_win32_map_default_error(lastError);
- break;
+ case WAIT_FAILED: /* failure returns this */
+ rv = SECFailure;
+ lastError = GetLastError(); /* for debugging */
+ nss_MD_win32_map_default_error(lastError);
+ break;
}
- if (! (SECSuccess == retvalue && SECSuccess == rv)) {
+ if (!(SECSuccess == retvalue && SECSuccess == rv)) {
return SECFailure;
}
-
+
return SECSuccess;
}
@@ -509,8 +516,8 @@ sslMutex_Lock(sslMutex *pMutex)
#include <errno.h>
#include "unix_err.h"
-SECStatus
-sslMutex_Init(sslMutex *pMutex, int shared)
+SECStatus
+sslMutex_Init(sslMutex* pMutex, int shared)
{
int rv;
PR_ASSERT(pMutex);
@@ -528,8 +535,8 @@ sslMutex_Init(sslMutex *pMutex, int shared)
return SECSuccess;
}
-SECStatus
-sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal)
+SECStatus
+sslMutex_Destroy(sslMutex* pMutex, PRBool processLocal)
{
int rv;
if (PR_FALSE == pMutex->isMultiProcess) {
@@ -538,56 +545,56 @@ sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal)
/* semaphores are global resources. See SEM_DESTROY(3) man page */
if (processLocal) {
- return SECSuccess;
+ return SECSuccess;
}
do {
- rv = sem_destroy(&pMutex->u.sem);
+ rv = sem_destroy(&pMutex->u.sem);
} while (rv < 0 && errno == EINTR);
if (rv < 0) {
- nss_MD_unix_map_default_error(errno);
- return SECFailure;
+ nss_MD_unix_map_default_error(errno);
+ return SECFailure;
}
return SECSuccess;
}
-SECStatus
-sslMutex_Unlock(sslMutex *pMutex)
+SECStatus
+sslMutex_Unlock(sslMutex* pMutex)
{
int rv;
if (PR_FALSE == pMutex->isMultiProcess) {
return single_process_sslMutex_Unlock(pMutex);
}
do {
- rv = sem_post(&pMutex->u.sem);
+ rv = sem_post(&pMutex->u.sem);
} while (rv < 0 && errno == EINTR);
if (rv < 0) {
- nss_MD_unix_map_default_error(errno);
- return SECFailure;
+ nss_MD_unix_map_default_error(errno);
+ return SECFailure;
}
return SECSuccess;
}
-SECStatus
-sslMutex_Lock(sslMutex *pMutex)
+SECStatus
+sslMutex_Lock(sslMutex* pMutex)
{
int rv;
if (PR_FALSE == pMutex->isMultiProcess) {
return single_process_sslMutex_Lock(pMutex);
}
do {
- rv = sem_wait(&pMutex->u.sem);
+ rv = sem_wait(&pMutex->u.sem);
} while (rv < 0 && errno == EINTR);
if (rv < 0) {
- nss_MD_unix_map_default_error(errno);
- return SECFailure;
+ nss_MD_unix_map_default_error(errno);
+ return SECFailure;
}
return SECSuccess;
}
#else
-SECStatus
-sslMutex_Init(sslMutex *pMutex, int shared)
+SECStatus
+sslMutex_Init(sslMutex* pMutex, int shared)
{
PR_ASSERT(pMutex);
pMutex->isMultiProcess = (PRBool)(shared != 0);
@@ -599,8 +606,8 @@ sslMutex_Init(sslMutex *pMutex, int shared)
return SECFailure;
}
-SECStatus
-sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal)
+SECStatus
+sslMutex_Destroy(sslMutex* pMutex, PRBool processLocal)
{
PR_ASSERT(pMutex);
if (PR_FALSE == pMutex->isMultiProcess) {
@@ -611,8 +618,8 @@ sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal)
return SECFailure;
}
-SECStatus
-sslMutex_Unlock(sslMutex *pMutex)
+SECStatus
+sslMutex_Unlock(sslMutex* pMutex)
{
PR_ASSERT(pMutex);
if (PR_FALSE == pMutex->isMultiProcess) {
@@ -623,8 +630,8 @@ sslMutex_Unlock(sslMutex *pMutex)
return SECFailure;
}
-SECStatus
-sslMutex_Lock(sslMutex *pMutex)
+SECStatus
+sslMutex_Lock(sslMutex* pMutex)
{
PR_ASSERT(pMutex);
if (PR_FALSE == pMutex->isMultiProcess) {
diff --git a/chromium/net/third_party/nss/ssl/sslmutex.h b/chromium/net/third_party/nss/ssl/sslmutex.h
index d374a883b73..7611148adce 100644
--- a/chromium/net/third_party/nss/ssl/sslmutex.h
+++ b/chromium/net/third_party/nss/ssl/sslmutex.h
@@ -4,20 +4,20 @@
#ifndef __SSLMUTEX_H_
#define __SSLMUTEX_H_ 1
-/* What SSL really wants is portable process-shared unnamed mutexes in
+/* What SSL really wants is portable process-shared unnamed mutexes in
* shared memory, that have the property that if the process that holds
- * them dies, they are released automatically, and that (unlike fcntl
- * record locking) lock to the thread, not to the process.
- * NSPR doesn't provide that.
- * Windows has mutexes that meet that description, but they're not portable.
- * POSIX mutexes are not automatically released when the holder dies,
- * and other processes/threads cannot release the mutex on behalf of the
- * dead holder.
- * POSIX semaphores can be used to accomplish this on systems that implement
- * process-shared unnamed POSIX semaphores, because a watchdog thread can
- * discover and release semaphores that were held by a dead process.
- * On systems that do not support process-shared POSIX unnamed semaphores,
- * they can be emulated using pipes.
+ * them dies, they are released automatically, and that (unlike fcntl
+ * record locking) lock to the thread, not to the process.
+ * NSPR doesn't provide that.
+ * Windows has mutexes that meet that description, but they're not portable.
+ * POSIX mutexes are not automatically released when the holder dies,
+ * and other processes/threads cannot release the mutex on behalf of the
+ * dead holder.
+ * POSIX semaphores can be used to accomplish this on systems that implement
+ * process-shared unnamed POSIX semaphores, because a watchdog thread can
+ * discover and release semaphores that were held by a dead process.
+ * On systems that do not support process-shared POSIX unnamed semaphores,
+ * they can be emulated using pipes.
* The performance cost of doing that is not yet measured.
*
* So, this API looks a lot like POSIX pthread mutexes.
@@ -34,8 +34,7 @@
#include <wtypes.h>
-typedef struct
-{
+typedef struct {
PRBool isMultiProcess;
#ifdef WINNT
/* on WINNT we need both the PRLock and the Win32 mutex for fibers */
@@ -43,25 +42,25 @@ typedef struct
#else
union {
#endif
- PRLock* sslLock;
+ PRLock *sslLock;
HANDLE sslMutx;
} u;
} sslMutex;
-typedef int sslPID;
+typedef int sslPID;
#elif defined(LINUX) || defined(AIX) || defined(BEOS) || defined(BSDI) || (defined(NETBSD) && __NetBSD_Version__ < 500000000) || defined(OPENBSD)
#include <sys/types.h>
#include "prtypes.h"
-typedef struct {
+typedef struct {
PRBool isMultiProcess;
union {
- PRLock* sslLock;
+ PRLock *sslLock;
struct {
- int mPipes[3];
- PRInt32 nWaiters;
+ int mPipes[3];
+ PRInt32 nWaiters;
} pipeStr;
} u;
} sslMutex;
@@ -70,15 +69,14 @@ typedef pid_t sslPID;
/* other types of unix, except OS X */
#elif defined(XP_UNIX) && !defined(DARWIN)
-#include <sys/types.h> /* for pid_t */
-#include <semaphore.h> /* for sem_t, and sem_* functions */
+#include <sys/types.h> /* for pid_t */
+#include <semaphore.h> /* for sem_t, and sem_* functions */
-typedef struct
-{
+typedef struct {
PRBool isMultiProcess;
union {
- PRLock* sslLock;
- sem_t sem;
+ PRLock *sslLock;
+ sem_t sem;
} u;
} sslMutex;
@@ -88,10 +86,10 @@ typedef pid_t sslPID;
/* what platform is this ?? */
-typedef struct {
+typedef struct {
PRBool isMultiProcess;
union {
- PRLock* sslLock;
+ PRLock *sslLock;
/* include cross-process locking mechanism here */
} u;
} sslMutex;
@@ -111,7 +109,7 @@ SEC_BEGIN_PROTOS
extern SECStatus sslMutex_Init(sslMutex *sem, int shared);
/* If processLocal is set to true, then just free resources which are *only* associated
- * with the current process. Leave any shared resources (including the state of
+ * with the current process. Leave any shared resources (including the state of
* shared memory) intact. */
extern SECStatus sslMutex_Destroy(sslMutex *sem, PRBool processLocal);
diff --git a/chromium/net/third_party/nss/ssl/sslnonce.c b/chromium/net/third_party/nss/ssl/sslnonce.c
index 28ad36435cc..99591cc1488 100644
--- a/chromium/net/third_party/nss/ssl/sslnonce.c
+++ b/chromium/net/third_party/nss/ssl/sslnonce.c
@@ -1,5 +1,5 @@
-/*
- * This file implements the CLIENT Session ID cache.
+/*
+ * This file implements the CLIENT Session ID cache.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -22,18 +22,18 @@ PRUint32 ssl_sid_timeout = 100;
PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */
static sslSessionID *cache = NULL;
-static PZLock * cacheLock = NULL;
+static PZLock *cacheLock = NULL;
/* sids can be in one of 4 states:
*
- * never_cached, created, but not yet put into cache.
- * in_client_cache, in the client cache's linked list.
- * in_server_cache, entry came from the server's cache file.
- * invalid_cache has been removed from the cache.
+ * never_cached, created, but not yet put into cache.
+ * in_client_cache, in the client cache's linked list.
+ * in_server_cache, entry came from the server's cache file.
+ * invalid_cache has been removed from the cache.
*/
-#define LOCK_CACHE lock_cache()
-#define UNLOCK_CACHE PZ_Unlock(cacheLock)
+#define LOCK_CACHE lock_cache()
+#define UNLOCK_CACHE PZ_Unlock(cacheLock)
static PRCallOnceType lockOnce;
@@ -41,7 +41,7 @@ static PRCallOnceType lockOnce;
* the session cache locks on shutdown and resets them to their initial
* state. */
static SECStatus
-FreeSessionCacheLocks(void* appData, void* nssData)
+FreeSessionCacheLocks(void *appData, void *nssData)
{
static const PRCallOnceType pristineCallOnce;
SECStatus rv;
@@ -92,11 +92,12 @@ InitSessionCacheLocks(void)
}
SECStatus
-ssl_InitSessionCacheLocks(void)
+ssl_InitSessionCacheLocks()
{
return (PR_SUCCESS ==
- PR_CallOnce(&lockOnce, InitSessionCacheLocks)) ?
- SECSuccess : SECFailure;
+ PR_CallOnce(&lockOnce, InitSessionCacheLocks))
+ ? SECSuccess
+ : SECFailure;
}
static void
@@ -118,8 +119,8 @@ ssl_DestroySID(sslSessionID *sid)
PORT_Assert(sid->cached != in_client_cache);
if (sid->version < SSL_LIBRARY_VERSION_3_0) {
- SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE);
- SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE);
+ SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE);
+ SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE);
} else {
if (sid->u.ssl3.locked.sessionTicket.ticket.data) {
SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket,
@@ -128,26 +129,26 @@ ssl_DestroySID(sslSessionID *sid)
if (sid->u.ssl3.srvName.data) {
SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE);
}
- if (sid->u.ssl3.originalHandshakeHash.data) {
- SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE);
- }
if (sid->u.ssl3.signedCertTimestamps.data) {
SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE);
}
+ if (sid->u.ssl3.originalHandshakeHash.data) {
+ SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE);
+ }
if (sid->u.ssl3.lock) {
- NSSRWLock_Destroy(sid->u.ssl3.lock);
+ PR_DestroyRWLock(sid->u.ssl3.lock);
}
}
if (sid->peerID != NULL)
- PORT_Free((void *)sid->peerID); /* CONST */
+ PORT_Free((void *)sid->peerID); /* CONST */
if (sid->urlSvrName != NULL)
- PORT_Free((void *)sid->urlSvrName); /* CONST */
+ PORT_Free((void *)sid->urlSvrName); /* CONST */
- if ( sid->peerCert ) {
- CERT_DestroyCertificate(sid->peerCert);
+ if (sid->peerCert) {
+ CERT_DestroyCertificate(sid->peerCert);
}
for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
CERT_DestroyCertificate(sid->peerCertChain[i]);
@@ -156,33 +157,33 @@ ssl_DestroySID(sslSessionID *sid)
SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE);
}
- if ( sid->localCert ) {
- CERT_DestroyCertificate(sid->localCert);
+ if (sid->localCert) {
+ CERT_DestroyCertificate(sid->localCert);
}
-
+
PORT_ZFree(sid, sizeof(sslSessionID));
}
/* BEWARE: This function gets called for both client and server SIDs !!
- * Decrement reference count, and
- * free sid if ref count is zero, and sid is not in the cache.
- * Does NOT remove from the cache first.
+ * Decrement reference count, and
+ * free sid if ref count is zero, and sid is not in the cache.
+ * Does NOT remove from the cache first.
* If the sid is still in the cache, it is left there until next time
* the cache list is traversed.
*/
-static void
+static void
ssl_FreeLockedSID(sslSessionID *sid)
{
PORT_Assert(sid->references >= 1);
if (--sid->references == 0) {
- ssl_DestroySID(sid);
+ ssl_DestroySID(sid);
}
}
/* BEWARE: This function gets called for both client and server SIDs !!
- * Decrement reference count, and
- * free sid if ref count is zero, and sid is not in the cache.
- * Does NOT remove from the cache first.
+ * Decrement reference count, and
+ * free sid if ref count is zero, and sid is not in the cache.
+ * Does NOT remove from the cache first.
* These locks are necessary because the sid _might_ be in the cache list.
*/
void
@@ -202,57 +203,54 @@ ssl_FreeSID(sslSessionID *sid)
*/
sslSessionID *
-ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID,
- const char * urlSvrName)
+ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID,
+ const char *urlSvrName)
{
sslSessionID **sidp;
- sslSessionID * sid;
- PRUint32 now;
+ sslSessionID *sid;
+ PRUint32 now;
if (!urlSvrName)
- return NULL;
+ return NULL;
now = ssl_Time();
LOCK_CACHE;
sidp = &cache;
while ((sid = *sidp) != 0) {
- PORT_Assert(sid->cached == in_client_cache);
- PORT_Assert(sid->references >= 1);
-
- SSL_TRC(8, ("SSL: Lookup1: sid=0x%x", sid));
-
- if (sid->expirationTime < now) {
- /*
- ** This session-id timed out.
- ** Don't even care who it belongs to, blow it out of our cache.
- */
- SSL_TRC(7, ("SSL: lookup1, throwing sid out, age=%d refs=%d",
- now - sid->creationTime, sid->references));
-
- *sidp = sid->next; /* delink it from the list. */
- sid->cached = invalid_cache; /* mark not on list. */
- ssl_FreeLockedSID(sid); /* drop ref count, free. */
- } else if (!memcmp(&sid->addr, addr, sizeof(PRIPv6Addr)) && /* server IP addr matches */
- (sid->port == port) && /* server port matches */
- /* proxy (peerID) matches */
- (((peerID == NULL) && (sid->peerID == NULL)) ||
- ((peerID != NULL) && (sid->peerID != NULL) &&
- PORT_Strcmp(sid->peerID, peerID) == 0)) &&
- /* is cacheable */
- (sid->version < SSL_LIBRARY_VERSION_3_0 ||
- sid->u.ssl3.keys.resumable) &&
- /* server hostname matches. */
- (sid->urlSvrName != NULL) &&
- ((0 == PORT_Strcmp(urlSvrName, sid->urlSvrName)) ||
- ((sid->peerCert != NULL) && (SECSuccess ==
- CERT_VerifyCertName(sid->peerCert, urlSvrName))) )
- ) {
- /* Hit */
- sid->lastAccessTime = now;
- sid->references++;
- break;
- } else {
- sidp = &sid->next;
- }
+ PORT_Assert(sid->cached == in_client_cache);
+ PORT_Assert(sid->references >= 1);
+
+ SSL_TRC(8, ("SSL: Lookup1: sid=0x%x", sid));
+
+ if (sid->expirationTime < now) {
+ /*
+ ** This session-id timed out.
+ ** Don't even care who it belongs to, blow it out of our cache.
+ */
+ SSL_TRC(7, ("SSL: lookup1, throwing sid out, age=%d refs=%d",
+ now - sid->creationTime, sid->references));
+
+ *sidp = sid->next; /* delink it from the list. */
+ sid->cached = invalid_cache; /* mark not on list. */
+ ssl_FreeLockedSID(sid); /* drop ref count, free. */
+ } else if (!memcmp(&sid->addr, addr, sizeof(PRIPv6Addr)) && /* server IP addr matches */
+ (sid->port == port) && /* server port matches */
+ /* proxy (peerID) matches */
+ (((peerID == NULL) && (sid->peerID == NULL)) ||
+ ((peerID != NULL) && (sid->peerID != NULL) &&
+ PORT_Strcmp(sid->peerID, peerID) == 0)) &&
+ /* is cacheable */
+ (sid->version < SSL_LIBRARY_VERSION_3_0 ||
+ sid->u.ssl3.keys.resumable) &&
+ /* server hostname matches. */
+ (sid->urlSvrName != NULL) &&
+ (0 == PORT_Strcmp(urlSvrName, sid->urlSvrName))) {
+ /* Hit */
+ sid->lastAccessTime = now;
+ sid->references++;
+ break;
+ } else {
+ sidp = &sid->next;
+ }
}
UNLOCK_CACHE;
return sid;
@@ -262,19 +260,19 @@ ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID,
** Add an sid to the cache or return a previously cached entry to the cache.
** Although this is static, it is called via ss->sec.cache().
*/
-static void
+static void
CacheSID(sslSessionID *sid)
{
- PRUint32 expirationPeriod;
+ PRUint32 expirationPeriod;
PORT_Assert(sid->cached == never_cached);
SSL_TRC(8, ("SSL: Cache: sid=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%04x "
- "time=%x cached=%d",
- sid, sid->cached, sid->addr.pr_s6_addr32[0],
- sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2],
- sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime,
- sid->cached));
+ "time=%x cached=%d",
+ sid, sid->cached, sid->addr.pr_s6_addr32[0],
+ sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2],
+ sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime,
+ sid->cached));
if (!sid->urlSvrName) {
/* don't cache this SID because it can never be matched */
@@ -283,41 +281,41 @@ CacheSID(sslSessionID *sid)
/* XXX should be different trace for version 2 vs. version 3 */
if (sid->version < SSL_LIBRARY_VERSION_3_0) {
- expirationPeriod = ssl_sid_timeout;
- PRINT_BUF(8, (0, "sessionID:",
- sid->u.ssl2.sessionID, sizeof(sid->u.ssl2.sessionID)));
- PRINT_BUF(8, (0, "masterKey:",
- sid->u.ssl2.masterKey.data, sid->u.ssl2.masterKey.len));
- PRINT_BUF(8, (0, "cipherArg:",
- sid->u.ssl2.cipherArg.data, sid->u.ssl2.cipherArg.len));
+ expirationPeriod = ssl_sid_timeout;
+ PRINT_BUF(8, (0, "sessionID:",
+ sid->u.ssl2.sessionID, sizeof(sid->u.ssl2.sessionID)));
+ PRINT_BUF(8, (0, "masterKey:",
+ sid->u.ssl2.masterKey.data, sid->u.ssl2.masterKey.len));
+ PRINT_BUF(8, (0, "cipherArg:",
+ sid->u.ssl2.cipherArg.data, sid->u.ssl2.cipherArg.len));
} else {
- if (sid->u.ssl3.sessionIDLength == 0 &&
- sid->u.ssl3.locked.sessionTicket.ticket.data == NULL)
- return;
-
- /* Client generates the SessionID if this was a stateless resume. */
- if (sid->u.ssl3.sessionIDLength == 0) {
- SECStatus rv;
- rv = PK11_GenerateRandom(sid->u.ssl3.sessionID,
- SSL3_SESSIONID_BYTES);
- if (rv != SECSuccess)
- return;
- sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES;
- }
- expirationPeriod = ssl3_sid_timeout;
- PRINT_BUF(8, (0, "sessionID:",
- sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength));
-
- sid->u.ssl3.lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL);
- if (!sid->u.ssl3.lock) {
- return;
- }
+ if (sid->u.ssl3.sessionIDLength == 0 &&
+ sid->u.ssl3.locked.sessionTicket.ticket.data == NULL)
+ return;
+
+ /* Client generates the SessionID if this was a stateless resume. */
+ if (sid->u.ssl3.sessionIDLength == 0) {
+ SECStatus rv;
+ rv = PK11_GenerateRandom(sid->u.ssl3.sessionID,
+ SSL3_SESSIONID_BYTES);
+ if (rv != SECSuccess)
+ return;
+ sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES;
+ }
+ expirationPeriod = ssl3_sid_timeout;
+ PRINT_BUF(8, (0, "sessionID:",
+ sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength));
+
+ sid->u.ssl3.lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, NULL);
+ if (!sid->u.ssl3.lock) {
+ return;
+ }
}
PORT_Assert(sid->creationTime != 0 && sid->expirationTime != 0);
if (!sid->creationTime)
- sid->lastAccessTime = sid->creationTime = ssl_Time();
+ sid->lastAccessTime = sid->creationTime = ssl_Time();
if (!sid->expirationTime)
- sid->expirationTime = sid->creationTime + expirationPeriod;
+ sid->expirationTime = sid->creationTime + expirationPeriod;
/*
* Put sid into the cache. Bump reference count to indicate that
@@ -327,12 +325,12 @@ CacheSID(sslSessionID *sid)
LOCK_CACHE;
sid->references++;
sid->cached = in_client_cache;
- sid->next = cache;
- cache = sid;
+ sid->next = cache;
+ cache = sid;
UNLOCK_CACHE;
}
-/*
+/*
* If sid "zap" is in the cache,
* removes sid from cache, and decrements reference count.
* Caller must hold cache lock.
@@ -344,43 +342,43 @@ UncacheSID(sslSessionID *zap)
sslSessionID *sid;
if (zap->cached != in_client_cache) {
- return;
+ return;
}
- SSL_TRC(8,("SSL: Uncache: zap=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%04x "
- "time=%x cipher=%d",
- zap, zap->cached, zap->addr.pr_s6_addr32[0],
- zap->addr.pr_s6_addr32[1], zap->addr.pr_s6_addr32[2],
- zap->addr.pr_s6_addr32[3], zap->port, zap->creationTime,
- zap->u.ssl2.cipherType));
+ SSL_TRC(8, ("SSL: Uncache: zap=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%04x "
+ "time=%x cipher=%d",
+ zap, zap->cached, zap->addr.pr_s6_addr32[0],
+ zap->addr.pr_s6_addr32[1], zap->addr.pr_s6_addr32[2],
+ zap->addr.pr_s6_addr32[3], zap->port, zap->creationTime,
+ zap->u.ssl2.cipherType));
if (zap->version < SSL_LIBRARY_VERSION_3_0) {
- PRINT_BUF(8, (0, "sessionID:",
- zap->u.ssl2.sessionID, sizeof(zap->u.ssl2.sessionID)));
- PRINT_BUF(8, (0, "masterKey:",
- zap->u.ssl2.masterKey.data, zap->u.ssl2.masterKey.len));
- PRINT_BUF(8, (0, "cipherArg:",
- zap->u.ssl2.cipherArg.data, zap->u.ssl2.cipherArg.len));
+ PRINT_BUF(8, (0, "sessionID:",
+ zap->u.ssl2.sessionID, sizeof(zap->u.ssl2.sessionID)));
+ PRINT_BUF(8, (0, "masterKey:",
+ zap->u.ssl2.masterKey.data, zap->u.ssl2.masterKey.len));
+ PRINT_BUF(8, (0, "cipherArg:",
+ zap->u.ssl2.cipherArg.data, zap->u.ssl2.cipherArg.len));
}
/* See if it's in the cache, if so nuke it */
while ((sid = *sidp) != 0) {
- if (sid == zap) {
- /*
- ** Bingo. Reduce reference count by one so that when
- ** everyone is done with the sid we can free it up.
- */
- *sidp = zap->next;
- zap->cached = invalid_cache;
- ssl_FreeLockedSID(zap);
- return;
- }
- sidp = &sid->next;
+ if (sid == zap) {
+ /*
+ ** Bingo. Reduce reference count by one so that when
+ ** everyone is done with the sid we can free it up.
+ */
+ *sidp = zap->next;
+ zap->cached = invalid_cache;
+ ssl_FreeLockedSID(zap);
+ return;
+ }
+ sidp = &sid->next;
}
}
/* If sid "zap" is in the cache,
* removes sid from cache, and decrements reference count.
- * Although this function is static, it is called externally via
+ * Although this function is static, it is called externally via
* ss->sec.uncache().
*/
static void
@@ -389,19 +387,18 @@ LockAndUncacheSID(sslSessionID *zap)
LOCK_CACHE;
UncacheSID(zap);
UNLOCK_CACHE;
-
}
/* choose client or server cache functions for this sslsocket. */
-void
+void
ssl_ChooseSessionIDProcs(sslSecurityInfo *sec)
{
if (sec->isServer) {
- sec->cache = ssl_sid_cache;
- sec->uncache = ssl_sid_uncache;
+ sec->cache = ssl_sid_cache;
+ sec->uncache = ssl_sid_uncache;
} else {
- sec->cache = CacheSID;
- sec->uncache = LockAndUncacheSID;
+ sec->cache = CacheSID;
+ sec->uncache = LockAndUncacheSID;
}
}
@@ -410,8 +407,8 @@ void
SSL_ClearSessionCache(void)
{
LOCK_CACHE;
- while(cache != NULL)
- UncacheSID(cache);
+ while (cache != NULL)
+ UncacheSID(cache);
UNLOCK_CACHE;
}
@@ -421,7 +418,7 @@ ssl_Time(void)
{
PRUint32 myTime;
#if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS)
- myTime = time(NULL); /* accurate until the year 2038. */
+ myTime = time(NULL); /* accurate until the year 2038. */
#else
/* portable, but possibly slower */
PRTime now;
@@ -450,11 +447,11 @@ ssl3_SetSIDSessionTicket(sslSessionID *sid,
* yet, so no locking is needed.
*/
if (sid->u.ssl3.lock) {
- NSSRWLock_LockWrite(sid->u.ssl3.lock);
- if (sid->u.ssl3.locked.sessionTicket.ticket.data) {
- SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket,
- PR_FALSE);
- }
+ PR_RWLock_Wlock(sid->u.ssl3.lock);
+ if (sid->u.ssl3.locked.sessionTicket.ticket.data) {
+ SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket,
+ PR_FALSE);
+ }
}
PORT_Assert(!sid->u.ssl3.locked.sessionTicket.ticket.data);
@@ -465,6 +462,6 @@ ssl3_SetSIDSessionTicket(sslSessionID *sid,
newSessionTicket->ticket.len = 0;
if (sid->u.ssl3.lock) {
- NSSRWLock_UnlockWrite(sid->u.ssl3.lock);
+ PR_RWLock_Unlock(sid->u.ssl3.lock);
}
}
diff --git a/chromium/net/third_party/nss/ssl/sslplatf.c b/chromium/net/third_party/nss/ssl/sslplatf.c
deleted file mode 100644
index 6f3cca64da8..00000000000
--- a/chromium/net/third_party/nss/ssl/sslplatf.c
+++ /dev/null
@@ -1,766 +0,0 @@
-/*
- * Platform specific crypto wrappers
- *
- * ***** 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 the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1994-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Ryan Sleevi <ryan.sleevi@gmail.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 ***** */
-/* $Id$ */
-#include "certt.h"
-#include "cryptohi.h"
-#include "keythi.h"
-#include "nss.h"
-#include "secitem.h"
-#include "ssl.h"
-#include "sslimpl.h"
-#include "prerror.h"
-#include "prinit.h"
-
-#ifdef NSS_PLATFORM_CLIENT_AUTH
-#ifdef XP_WIN32
-#include <NCrypt.h>
-#endif
-#endif
-
-#ifdef NSS_PLATFORM_CLIENT_AUTH
-CERTCertificateList*
-hack_NewCertificateListFromCertList(CERTCertList* list)
-{
- CERTCertificateList * chain = NULL;
- PLArenaPool * arena = NULL;
- CERTCertListNode * node;
- int len;
-
- if (CERT_LIST_EMPTY(list))
- goto loser;
-
- arena = PORT_NewArena(4096);
- if (arena == NULL)
- goto loser;
-
- for (len = 0, node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
- len++, node = CERT_LIST_NEXT(node)) {
- }
-
- chain = PORT_ArenaNew(arena, CERTCertificateList);
- if (chain == NULL)
- goto loser;
-
- chain->certs = PORT_ArenaNewArray(arena, SECItem, len);
- if (!chain->certs)
- goto loser;
- chain->len = len;
-
- for (len = 0, node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
- len++, node = CERT_LIST_NEXT(node)) {
- // Check to see if the last cert to be sent is a self-signed cert,
- // and if so, omit it from the list of certificates. However, if
- // there is only one cert (len == 0), include the cert, as it means
- // the EE cert is self-signed.
- if (len > 0 && (len == chain->len - 1) && node->cert->isRoot) {
- chain->len = len;
- break;
- }
- SECITEM_CopyItem(arena, &chain->certs[len], &node->cert->derCert);
- }
-
- chain->arena = arena;
- return chain;
-
-loser:
- if (arena) {
- PORT_FreeArena(arena, PR_FALSE);
- }
- return NULL;
-}
-
-#if defined(XP_WIN32)
-typedef SECURITY_STATUS (WINAPI *NCryptFreeObjectFunc)(NCRYPT_HANDLE);
-typedef SECURITY_STATUS (WINAPI *NCryptSignHashFunc)(
- NCRYPT_KEY_HANDLE /* hKey */,
- VOID* /* pPaddingInfo */,
- PBYTE /* pbHashValue */,
- DWORD /* cbHashValue */,
- PBYTE /* pbSignature */,
- DWORD /* cbSignature */,
- DWORD* /* pcbResult */,
- DWORD /* dwFlags */);
-
-static PRCallOnceType cngFunctionsInitOnce;
-static const PRCallOnceType pristineCallOnce;
-
-static PRLibrary *ncrypt_library = NULL;
-static NCryptFreeObjectFunc pNCryptFreeObject = NULL;
-static NCryptSignHashFunc pNCryptSignHash = NULL;
-
-static SECStatus
-ssl_ShutdownCngFunctions(void *appData, void *nssData)
-{
- pNCryptSignHash = NULL;
- pNCryptFreeObject = NULL;
- if (ncrypt_library) {
- PR_UnloadLibrary(ncrypt_library);
- ncrypt_library = NULL;
- }
-
- cngFunctionsInitOnce = pristineCallOnce;
-
- return SECSuccess;
-}
-
-static PRStatus
-ssl_InitCngFunctions(void)
-{
- SECStatus rv;
-
- ncrypt_library = PR_LoadLibrary("ncrypt.dll");
- if (ncrypt_library == NULL)
- goto loser;
-
- pNCryptFreeObject = (NCryptFreeObjectFunc)PR_FindFunctionSymbol(
- ncrypt_library, "NCryptFreeObject");
- if (pNCryptFreeObject == NULL)
- goto loser;
-
- pNCryptSignHash = (NCryptSignHashFunc)PR_FindFunctionSymbol(
- ncrypt_library, "NCryptSignHash");
- if (pNCryptSignHash == NULL)
- goto loser;
-
- rv = NSS_RegisterShutdown(ssl_ShutdownCngFunctions, NULL);
- if (rv != SECSuccess)
- goto loser;
-
- return PR_SUCCESS;
-
-loser:
- pNCryptSignHash = NULL;
- pNCryptFreeObject = NULL;
- if (ncrypt_library) {
- PR_UnloadLibrary(ncrypt_library);
- ncrypt_library = NULL;
- }
-
- return PR_FAILURE;
-}
-
-static SECStatus
-ssl_InitCng(void)
-{
- if (PR_CallOnce(&cngFunctionsInitOnce, ssl_InitCngFunctions) != PR_SUCCESS)
- return SECFailure;
- return SECSuccess;
-}
-
-void
-ssl_FreePlatformKey(PlatformKey key)
-{
- if (!key)
- return;
-
- if (key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) {
- if (ssl_InitCng() == SECSuccess) {
- (*pNCryptFreeObject)(key->hNCryptKey);
- }
- } else {
- CryptReleaseContext(key->hCryptProv, 0);
- }
- PORT_Free(key);
-}
-
-static SECStatus
-ssl3_CngPlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf,
- PRBool isTLS, KeyType keyType)
-{
- SECStatus rv = SECFailure;
- SECURITY_STATUS ncrypt_status;
- PRBool doDerEncode = PR_FALSE;
- SECItem hashItem;
- DWORD signatureLen = 0;
- DWORD dwFlags = 0;
- VOID *pPaddingInfo = NULL;
-
- /* Always encode using PKCS#1 block type. */
- BCRYPT_PKCS1_PADDING_INFO rsaPaddingInfo;
-
- if (key->dwKeySpec != CERT_NCRYPT_KEY_SPEC) {
- PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
- return SECFailure;
- }
- if (ssl_InitCng() != SECSuccess) {
- PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
- return SECFailure;
- }
-
- switch (keyType) {
- case rsaKey:
- switch (hash->hashAlg) {
- case SEC_OID_UNKNOWN:
- /* No OID/encoded DigestInfo. */
- rsaPaddingInfo.pszAlgId = NULL;
- break;
- case SEC_OID_SHA1:
- rsaPaddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM;
- break;
- case SEC_OID_SHA256:
- rsaPaddingInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM;
- break;
- case SEC_OID_SHA384:
- rsaPaddingInfo.pszAlgId = BCRYPT_SHA384_ALGORITHM;
- break;
- case SEC_OID_SHA512:
- rsaPaddingInfo.pszAlgId = BCRYPT_SHA512_ALGORITHM;
- break;
- default:
- PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
- return SECFailure;
- }
- hashItem.data = hash->u.raw;
- hashItem.len = hash->len;
- dwFlags = BCRYPT_PAD_PKCS1;
- pPaddingInfo = &rsaPaddingInfo;
- break;
- case dsaKey:
- case ecKey:
- if (keyType == ecKey) {
- doDerEncode = PR_TRUE;
- } else {
- doDerEncode = isTLS;
- }
- if (hash->hashAlg == SEC_OID_UNKNOWN) {
- hashItem.data = hash->u.s.sha;
- hashItem.len = sizeof(hash->u.s.sha);
- } else {
- hashItem.data = hash->u.raw;
- hashItem.len = hash->len;
- }
- break;
- default:
- PORT_SetError(SEC_ERROR_INVALID_KEY);
- goto done;
- }
- PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len));
-
- ncrypt_status = (*pNCryptSignHash)(key->hNCryptKey, pPaddingInfo,
- (PBYTE)hashItem.data, hashItem.len,
- NULL, 0, &signatureLen, dwFlags);
- if (FAILED(ncrypt_status) || signatureLen == 0) {
- PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, ncrypt_status);
- goto done;
- }
-
- buf->data = (unsigned char *)PORT_Alloc(signatureLen);
- if (!buf->data) {
- goto done; /* error code was set. */
- }
-
- ncrypt_status = (*pNCryptSignHash)(key->hNCryptKey, pPaddingInfo,
- (PBYTE)hashItem.data, hashItem.len,
- (PBYTE)buf->data, signatureLen,
- &signatureLen, dwFlags);
- if (FAILED(ncrypt_status) || signatureLen == 0) {
- PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, ncrypt_status);
- goto done;
- }
-
- buf->len = signatureLen;
-
- if (doDerEncode) {
- SECItem derSig = {siBuffer, NULL, 0};
-
- /* This also works for an ECDSA signature */
- rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len);
- if (rv == SECSuccess) {
- PORT_Free(buf->data); /* discard unencoded signature. */
- *buf = derSig; /* give caller encoded signature. */
- } else if (derSig.data) {
- PORT_Free(derSig.data);
- }
- } else {
- rv = SECSuccess;
- }
-
- PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len));
-
-done:
- if (rv != SECSuccess && buf->data) {
- PORT_Free(buf->data);
- buf->data = NULL;
- buf->len = 0;
- }
-
- return rv;
-}
-
-static SECStatus
-ssl3_CAPIPlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf,
- PRBool isTLS, KeyType keyType)
-{
- SECStatus rv = SECFailure;
- PRBool doDerEncode = PR_FALSE;
- SECItem hashItem;
- DWORD argLen = 0;
- DWORD signatureLen = 0;
- ALG_ID hashAlg = 0;
- HCRYPTHASH hHash = 0;
- DWORD hashLen = 0;
- unsigned int i = 0;
-
- buf->data = NULL;
-
- switch (hash->hashAlg) {
- case SEC_OID_UNKNOWN:
- hashAlg = 0;
- break;
- case SEC_OID_SHA1:
- hashAlg = CALG_SHA1;
- break;
- case SEC_OID_SHA256:
- hashAlg = CALG_SHA_256;
- break;
- case SEC_OID_SHA384:
- hashAlg = CALG_SHA_384;
- break;
- case SEC_OID_SHA512:
- hashAlg = CALG_SHA_512;
- break;
- default:
- PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
- return SECFailure;
- }
-
- switch (keyType) {
- case rsaKey:
- if (hashAlg == 0) {
- hashAlg = CALG_SSL3_SHAMD5;
- }
- hashItem.data = hash->u.raw;
- hashItem.len = hash->len;
- break;
- case dsaKey:
- case ecKey:
- if (keyType == ecKey) {
- doDerEncode = PR_TRUE;
- } else {
- doDerEncode = isTLS;
- }
- if (hashAlg == 0) {
- hashAlg = CALG_SHA1;
- hashItem.data = hash->u.s.sha;
- hashItem.len = sizeof(hash->u.s.sha);
- } else {
- hashItem.data = hash->u.raw;
- hashItem.len = hash->len;
- }
- break;
- default:
- PORT_SetError(SEC_ERROR_INVALID_KEY);
- goto done;
- }
- PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len));
-
- if (!CryptCreateHash(key->hCryptProv, hashAlg, 0, 0, &hHash)) {
- PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError());
- goto done;
- }
- argLen = sizeof(hashLen);
- if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashLen, &argLen, 0)) {
- PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError());
- goto done;
- }
- if (hashLen != hashItem.len) {
- PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, 0);
- goto done;
- }
- if (!CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*)hashItem.data, 0)) {
- PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError());
- goto done;
- }
- if (!CryptSignHash(hHash, key->dwKeySpec, NULL, 0,
- NULL, &signatureLen) || signatureLen == 0) {
- PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError());
- goto done;
- }
- buf->data = (unsigned char *)PORT_Alloc(signatureLen);
- if (!buf->data)
- goto done; /* error code was set. */
-
- if (!CryptSignHash(hHash, key->dwKeySpec, NULL, 0,
- (BYTE*)buf->data, &signatureLen)) {
- PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError());
- goto done;
- }
- buf->len = signatureLen;
-
- /* CryptoAPI signs in little-endian, so reverse */
- for (i = 0; i < buf->len / 2; ++i) {
- unsigned char tmp = buf->data[i];
- buf->data[i] = buf->data[buf->len - 1 - i];
- buf->data[buf->len - 1 - i] = tmp;
- }
- if (doDerEncode) {
- SECItem derSig = {siBuffer, NULL, 0};
-
- /* This also works for an ECDSA signature */
- rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len);
- if (rv == SECSuccess) {
- PORT_Free(buf->data); /* discard unencoded signature. */
- *buf = derSig; /* give caller encoded signature. */
- } else if (derSig.data) {
- PORT_Free(derSig.data);
- }
- } else {
- rv = SECSuccess;
- }
-
- PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len));
-done:
- if (hHash)
- CryptDestroyHash(hHash);
- if (rv != SECSuccess && buf->data) {
- PORT_Free(buf->data);
- buf->data = NULL;
- }
- return rv;
-}
-
-SECStatus
-ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf,
- PRBool isTLS, KeyType keyType)
-{
- if (key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) {
- return ssl3_CngPlatformSignHashes(hash, key, buf, isTLS, keyType);
- }
- return ssl3_CAPIPlatformSignHashes(hash, key, buf, isTLS, keyType);
-}
-
-#elif defined(XP_MACOSX)
-#include <Security/cssm.h>
-
-void
-ssl_FreePlatformKey(PlatformKey key)
-{
- CFRelease(key);
-}
-
-#define SSL_MAX_DIGEST_INFO_PREFIX 20
-
-/* ssl3_GetDigestInfoPrefix sets |out| and |out_len| to point to a buffer that
- * contains ASN.1 data that should be prepended to a hash of the given type in
- * order to create a DigestInfo structure that is valid for use in a PKCS #1
- * v1.5 RSA signature. |out_len| will not be set to a value greater than
- * SSL_MAX_DIGEST_INFO_PREFIX. */
-static SECStatus
-ssl3_GetDigestInfoPrefix(SECOidTag hashAlg,
- const SSL3Opaque** out, unsigned int *out_len)
-{
- /* These are the DER encoding of ASN.1 DigestInfo structures:
- * DigestInfo ::= SEQUENCE {
- * digestAlgorithm AlgorithmIdentifier,
- * digest OCTET STRING
- * }
- * See PKCS #1 v2.2 Section 9.2, Note 1.
- */
- static const unsigned char kSHA1[] = {
- 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
- 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
- };
- static const unsigned char kSHA224[] = {
- 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
- 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05,
- 0x00, 0x04, 0x1c
- };
- static const unsigned char kSHA256[] = {
- 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
- 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
- 0x00, 0x04, 0x20
- };
- static const unsigned char kSHA384[] = {
- 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
- 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
- 0x00, 0x04, 0x30
- };
- static const unsigned char kSHA512[] = {
- 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
- 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
- 0x00, 0x04, 0x40
- };
-
- switch (hashAlg) {
- case SEC_OID_UNKNOWN:
- *out_len = 0;
- break;
- case SEC_OID_SHA1:
- *out = kSHA1;
- *out_len = sizeof(kSHA1);
- break;
- case SEC_OID_SHA224:
- *out = kSHA224;
- *out_len = sizeof(kSHA224);
- break;
- case SEC_OID_SHA256:
- *out = kSHA256;
- *out_len = sizeof(kSHA256);
- break;
- case SEC_OID_SHA384:
- *out = kSHA384;
- *out_len = sizeof(kSHA384);
- break;
- case SEC_OID_SHA512:
- *out = kSHA512;
- *out_len = sizeof(kSHA512);
- break;
- default:
- PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
- return SECFailure;
- }
-
- return SECSuccess;
-}
-
-/* Given the length of a raw DSA signature (consisting of two integers
- * r and s), returns the maximum length of the DER encoding of the
- * following structure:
- *
- * Dss-Sig-Value ::= SEQUENCE {
- * r INTEGER,
- * s INTEGER
- * }
- */
-static unsigned int
-ssl3_DSAMaxDerEncodedLength(unsigned int rawDsaLen)
-{
- /* The length of one INTEGER. */
- unsigned int integerDerLen = rawDsaLen/2 + /* the integer itself */
- 1 + /* additional zero byte if high bit is 1 */
- SEC_ASN1LengthLength(rawDsaLen/2 + 1) + /* length */
- 1; /* INTEGER tag */
-
- /* The length of two INTEGERs in a SEQUENCE */
- return 2 * integerDerLen + /* two INTEGERs */
- SEC_ASN1LengthLength(2 * integerDerLen) + /* length */
- 1; /* SEQUENCE tag */
-}
-
-SECStatus
-ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf,
- PRBool isTLS, KeyType keyType)
-{
- SECStatus rv = SECFailure;
- PRBool doDerDecode = PR_FALSE;
- unsigned int rawDsaLen;
- unsigned int signatureLen;
- OSStatus status = noErr;
- CSSM_CSP_HANDLE cspHandle = 0;
- const CSSM_KEY *cssmKey = NULL;
- CSSM_ALGORITHMS sigAlg;
- CSSM_ALGORITHMS digestAlg;
- const CSSM_ACCESS_CREDENTIALS * cssmCreds = NULL;
- CSSM_RETURN cssmRv;
- CSSM_DATA hashData;
- CSSM_DATA signatureData;
- CSSM_CC_HANDLE cssmSignature = 0;
- const SSL3Opaque* prefix;
- unsigned int prefixLen;
- SSL3Opaque prefixAndHash[SSL_MAX_DIGEST_INFO_PREFIX + HASH_LENGTH_MAX];
-
- buf->data = NULL;
-
- status = SecKeyGetCSPHandle(key, &cspHandle);
- if (status != noErr) {
- PORT_SetError(SEC_ERROR_INVALID_KEY);
- goto done;
- }
-
- status = SecKeyGetCSSMKey(key, &cssmKey);
- if (status != noErr || !cssmKey) {
- PORT_SetError(SEC_ERROR_NO_KEY);
- goto done;
- }
-
- sigAlg = cssmKey->KeyHeader.AlgorithmId;
- digestAlg = CSSM_ALGID_NONE;
-
- switch (keyType) {
- case rsaKey:
- PORT_Assert(sigAlg == CSSM_ALGID_RSA);
- signatureLen = (cssmKey->KeyHeader.LogicalKeySizeInBits + 7) / 8;
- if (ssl3_GetDigestInfoPrefix(hash->hashAlg, &prefix, &prefixLen) !=
- SECSuccess) {
- goto done;
- }
- if (prefixLen + hash->len > sizeof(prefixAndHash)) {
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- goto done;
- }
- memcpy(prefixAndHash, prefix, prefixLen);
- memcpy(prefixAndHash + prefixLen, hash->u.raw, hash->len);
- hashData.Data = prefixAndHash;
- hashData.Length = prefixLen + hash->len;
- break;
- case dsaKey:
- case ecKey:
- /* SSL3 DSA signatures are raw, not DER-encoded. CSSM gives back
- * DER-encoded signatures, so they must be decoded. */
- doDerDecode = (keyType == dsaKey) && !isTLS;
-
- /* Compute the maximum size of a DER-encoded signature: */
- if (keyType == ecKey) {
- PORT_Assert(sigAlg == CSSM_ALGID_ECDSA);
- /* LogicalKeySizeInBits is the size of an EC public key. But an
- * ECDSA signature length depends on the size of the base
- * point's order. For P-256, P-384, and P-521, these two sizes
- * are the same. */
- rawDsaLen =
- (cssmKey->KeyHeader.LogicalKeySizeInBits + 7) / 8 * 2;
- } else {
- /* TODO(davidben): Get the size of the subprime out of CSSM. For
- * now, assume 160; Apple's implementation hardcodes it. */
- PORT_Assert(sigAlg == CSSM_ALGID_DSA);
- rawDsaLen = 2 * (160 / 8);
- }
- signatureLen = ssl3_DSAMaxDerEncodedLength(rawDsaLen);
-
- /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated
- * hash. In that case, we use just the SHA1 part. */
- if (hash->hashAlg == SEC_OID_UNKNOWN) {
- hashData.Data = hash->u.s.sha;
- hashData.Length = sizeof(hash->u.s.sha);
- } else {
- hashData.Data = hash->u.raw;
- hashData.Length = hash->len;
- }
- break;
- default:
- PORT_SetError(SEC_ERROR_INVALID_KEY);
- goto done;
- }
- PRINT_BUF(60, (NULL, "hash(es) to be signed", hashData.Data, hashData.Length));
-
- if (signatureLen == 0) {
- PORT_SetError(SEC_ERROR_INVALID_KEY);
- goto done;
- }
-
- buf->data = (unsigned char *)PORT_Alloc(signatureLen);
- if (!buf->data)
- goto done; /* error code was set. */
-
- /* TODO(rsleevi): Should it be kSecCredentialTypeNoUI? In Win32, at least,
- * you can prevent the UI by setting the provider handle on the
- * certificate to be opened with CRYPT_SILENT, but is there an equivalent?
- */
- status = SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_SIGN,
- kSecCredentialTypeDefault, &cssmCreds);
- if (status != noErr) {
- PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, status);
- goto done;
- }
-
- signatureData.Length = signatureLen;
- signatureData.Data = (uint8*)buf->data;
-
- cssmRv = CSSM_CSP_CreateSignatureContext(cspHandle, sigAlg, cssmCreds,
- cssmKey, &cssmSignature);
- if (cssmRv) {
- PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv);
- goto done;
- }
-
- /* See "Apple Cryptographic Service Provider Functional Specification" */
- if (cssmKey->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) {
- /* To set RSA blinding for RSA keys */
- CSSM_CONTEXT_ATTRIBUTE blindingAttr;
- blindingAttr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING;
- blindingAttr.AttributeLength = sizeof(uint32);
- blindingAttr.Attribute.Uint32 = 1;
- cssmRv = CSSM_UpdateContextAttributes(cssmSignature, 1, &blindingAttr);
- if (cssmRv) {
- PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv);
- goto done;
- }
- }
-
- cssmRv = CSSM_SignData(cssmSignature, &hashData, 1, digestAlg,
- &signatureData);
- if (cssmRv) {
- PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv);
- goto done;
- }
- buf->len = signatureData.Length;
-
- if (doDerDecode) {
- SECItem* rawSig = DSAU_DecodeDerSigToLen(buf, rawDsaLen);
- if (rawSig != NULL) {
- PORT_Free(buf->data); /* discard encoded signature. */
- *buf = *rawSig; /* give caller unencoded signature. */
- PORT_Free(rawSig);
- rv = SECSuccess;
- }
- } else {
- rv = SECSuccess;
- }
-
- PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len));
-done:
- /* cspHandle, cssmKey, and cssmCreds are owned by the SecKeyRef and
- * should not be freed. When the PlatformKey is freed, they will be
- * released.
- */
- if (cssmSignature)
- CSSM_DeleteContext(cssmSignature);
-
- if (rv != SECSuccess && buf->data) {
- PORT_Free(buf->data);
- buf->data = NULL;
- }
- return rv;
-}
-#else
-void
-ssl_FreePlatformKey(PlatformKey key)
-{
-}
-
-SECStatus
-ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf,
- PRBool isTLS, KeyType keyType)
-{
- PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
- return SECFailure;
-}
-#endif
-
-#endif /* NSS_PLATFORM_CLIENT_AUTH */
diff --git a/chromium/net/third_party/nss/ssl/sslproto.h b/chromium/net/third_party/nss/ssl/sslproto.h
index 36ae6c9c200..4fa260d6d0b 100644
--- a/chromium/net/third_party/nss/ssl/sslproto.h
+++ b/chromium/net/third_party/nss/ssl/sslproto.h
@@ -10,6 +10,8 @@
#ifndef __sslproto_h_
#define __sslproto_h_
+/* clang-format off */
+
/* All versions less than 3_0 are treated as SSL version 2 */
#define SSL_LIBRARY_VERSION_2 0x0002
#define SSL_LIBRARY_VERSION_3_0 0x0300
@@ -260,8 +262,9 @@
#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F
#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031
-#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 0xCC13
-#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 0xCC14
+#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8
+#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9
+#define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA
/* Netscape "experimental" cipher suites. */
#define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA 0xffe0
@@ -278,4 +281,6 @@
#define SRTP_NULL_HMAC_SHA1_80 0x0005
#define SRTP_NULL_HMAC_SHA1_32 0x0006
+/* clang-format on */
+
#endif /* __sslproto_h_ */
diff --git a/chromium/net/third_party/nss/ssl/sslreveal.c b/chromium/net/third_party/nss/ssl/sslreveal.c
index d97299885d9..4c124a1dc0c 100644
--- a/chromium/net/third_party/nss/ssl/sslreveal.c
+++ b/chromium/net/third_party/nss/ssl/sslreveal.c
@@ -1,4 +1,4 @@
-/*
+/*
* Accessor functions for SSLSocket private members.
*
* This Source Code Form is subject to the terms of the Mozilla Public
@@ -13,100 +13,98 @@
/* given PRFileDesc, returns a copy of certificate associated with the socket
* the caller should delete the cert when done with SSL_DestroyCertificate
*/
-CERTCertificate *
-SSL_RevealCert(PRFileDesc * fd)
+CERTCertificate *
+SSL_RevealCert(PRFileDesc *fd)
{
- CERTCertificate * cert = NULL;
- sslSocket * sslsocket = NULL;
-
- sslsocket = ssl_FindSocket(fd);
-
- /* CERT_DupCertificate increases reference count and returns pointer to
- * the same cert
- */
- if (sslsocket && sslsocket->sec.peerCert)
- cert = CERT_DupCertificate(sslsocket->sec.peerCert);
-
- return cert;
+ CERTCertificate *cert = NULL;
+ sslSocket *sslsocket = NULL;
+
+ sslsocket = ssl_FindSocket(fd);
+
+ /* CERT_DupCertificate increases reference count and returns pointer to
+ * the same cert
+ */
+ if (sslsocket && sslsocket->sec.peerCert)
+ cert = CERT_DupCertificate(sslsocket->sec.peerCert);
+
+ return cert;
}
/* given PRFileDesc, returns a pointer to PinArg associated with the socket
*/
-void *
-SSL_RevealPinArg(PRFileDesc * fd)
+void *
+SSL_RevealPinArg(PRFileDesc *fd)
{
- sslSocket * sslsocket = NULL;
- void * PinArg = NULL;
-
- sslsocket = ssl_FindSocket(fd);
-
- /* is pkcs11PinArg part of the sslSocket or sslSecurityInfo ? */
- if (sslsocket)
- PinArg = sslsocket->pkcs11PinArg;
-
- return PinArg;
-}
+ sslSocket *sslsocket = NULL;
+ void *PinArg = NULL;
+
+ sslsocket = ssl_FindSocket(fd);
+ /* is pkcs11PinArg part of the sslSocket or sslSecurityInfo ? */
+ if (sslsocket)
+ PinArg = sslsocket->pkcs11PinArg;
+
+ return PinArg;
+}
/* given PRFileDesc, returns a pointer to the URL associated with the socket
* the caller should free url when done
*/
-char *
-SSL_RevealURL(PRFileDesc * fd)
+char *
+SSL_RevealURL(PRFileDesc *fd)
{
- sslSocket * sslsocket = NULL;
- char * url = NULL;
-
- sslsocket = ssl_FindSocket(fd);
-
- if (sslsocket && sslsocket->url)
- url = PL_strdup(sslsocket->url);
-
- return url;
-}
+ sslSocket *sslsocket = NULL;
+ char *url = NULL;
+
+ sslsocket = ssl_FindSocket(fd);
+ if (sslsocket && sslsocket->url)
+ url = PL_strdup(sslsocket->url);
-/* given PRFileDesc, returns status information related to extensions
+ return url;
+}
+
+/* given PRFileDesc, returns status information related to extensions
* negotiated with peer during the handshake.
*/
SECStatus
-SSL_HandshakeNegotiatedExtension(PRFileDesc * socket,
+SSL_HandshakeNegotiatedExtension(PRFileDesc *socket,
SSLExtensionType extId,
PRBool *pYes)
{
- /* some decisions derived from SSL_GetChannelInfo */
- sslSocket * sslsocket = NULL;
-
- if (!pYes) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
-
- sslsocket = ssl_FindSocket(socket);
- if (!sslsocket) {
- SSL_DBG(("%d: SSL[%d]: bad socket in HandshakeNegotiatedExtension",
- SSL_GETPID(), socket));
- return SECFailure;
- }
-
- *pYes = PR_FALSE;
-
- /* according to public API SSL_GetChannelInfo, this doesn't need a lock */
- if (sslsocket->opt.useSecurity) {
- if (sslsocket->ssl3.initialized) { /* SSL3 and TLS */
- /* now we know this socket went through ssl3_InitState() and
- * ss->xtnData got initialized, which is the only member accessed by
- * ssl3_ExtensionNegotiated();
- * Member xtnData appears to get accessed in functions that handle
- * the handshake (hello messages and extension sending),
- * therefore the handshake lock should be sufficient.
- */
- ssl_GetSSL3HandshakeLock(sslsocket);
- *pYes = ssl3_ExtensionNegotiated(sslsocket, extId);
- ssl_ReleaseSSL3HandshakeLock(sslsocket);
+ /* some decisions derived from SSL_GetChannelInfo */
+ sslSocket *sslsocket = NULL;
+
+ if (!pYes) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ sslsocket = ssl_FindSocket(socket);
+ if (!sslsocket) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in HandshakeNegotiatedExtension",
+ SSL_GETPID(), socket));
+ return SECFailure;
+ }
+
+ *pYes = PR_FALSE;
+
+ /* according to public API SSL_GetChannelInfo, this doesn't need a lock */
+ if (sslsocket->opt.useSecurity) {
+ if (sslsocket->ssl3.initialized) { /* SSL3 and TLS */
+ /* now we know this socket went through ssl3_InitState() and
+ * ss->xtnData got initialized, which is the only member accessed by
+ * ssl3_ExtensionNegotiated();
+ * Member xtnData appears to get accessed in functions that handle
+ * the handshake (hello messages and extension sending),
+ * therefore the handshake lock should be sufficient.
+ */
+ ssl_GetSSL3HandshakeLock(sslsocket);
+ *pYes = ssl3_ExtensionNegotiated(sslsocket, extId);
+ ssl_ReleaseSSL3HandshakeLock(sslsocket);
+ }
}
- }
- return SECSuccess;
+ return SECSuccess;
}
diff --git a/chromium/net/third_party/nss/ssl/sslsecur.c b/chromium/net/third_party/nss/ssl/sslsecur.c
index b4b8e9558b1..129f1f354bc 100644
--- a/chromium/net/third_party/nss/ssl/sslsecur.c
+++ b/chromium/net/third_party/nss/ssl/sslsecur.c
@@ -10,23 +10,23 @@
#include "ssl.h"
#include "sslimpl.h"
#include "sslproto.h"
-#include "secoid.h" /* for SECOID_GetALgorithmTag */
-#include "pk11func.h" /* for PK11_GenerateRandom */
-#include "nss.h" /* for NSS_RegisterShutdown */
-#include "prinit.h" /* for PR_CallOnceWithArg */
+#include "secoid.h" /* for SECOID_GetALgorithmTag */
+#include "pk11func.h" /* for PK11_GenerateRandom */
+#include "nss.h" /* for NSS_RegisterShutdown */
+#include "prinit.h" /* for PR_CallOnceWithArg */
-#define MAX_BLOCK_CYPHER_SIZE 32
+#define MAX_BLOCK_CYPHER_SIZE 32
-#define TEST_FOR_FAILURE /* reminder */
-#define SET_ERROR_CODE /* reminder */
+#define TEST_FOR_FAILURE /* reminder */
+#define SET_ERROR_CODE /* reminder */
-/* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock.
- *
+/* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock.
+ *
* Currently, the list of functions called through ss->handshake is:
- *
+ *
* In sslsocks.c:
* SocksGatherRecord
- * SocksHandleReply
+ * SocksHandleReply
* SocksStartGather
*
* In sslcon.c:
@@ -38,88 +38,88 @@
* ssl2_BeginServerHandshake
* ssl2_HandleClientHelloMessage
* ssl2_HandleServerHelloMessage
- *
+ *
* The ss->handshake function returns SECWouldBlock under these conditions:
- * 1. ssl_GatherRecord1stHandshake called ssl2_GatherData which read in
- * the beginning of an SSL v3 hello message and returned SECWouldBlock
- * to switch to SSL v3 handshake processing.
+ * 1. ssl_GatherRecord1stHandshake called ssl2_GatherData which read in
+ * the beginning of an SSL v3 hello message and returned SECWouldBlock
+ * to switch to SSL v3 handshake processing.
*
- * 2. ssl2_HandleClientHelloMessage discovered version 3.0 in the incoming
- * v2 client hello msg, and called ssl3_HandleV2ClientHello which
- * returned SECWouldBlock.
+ * 2. ssl2_HandleClientHelloMessage discovered version 3.0 in the incoming
+ * v2 client hello msg, and called ssl3_HandleV2ClientHello which
+ * returned SECWouldBlock.
*
* 3. SECWouldBlock was returned by one of the callback functions, via
- * one of these paths:
- * - ssl2_HandleMessage() -> ssl2_HandleRequestCertificate() ->
- * ss->getClientAuthData()
+ * one of these paths:
+ * - ssl2_HandleMessage() -> ssl2_HandleRequestCertificate() ->
+ * ss->getClientAuthData()
*
- * - ssl2_HandleServerHelloMessage() -> ss->handleBadCert()
+ * - ssl2_HandleServerHelloMessage() -> ss->handleBadCert()
*
- * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() ->
- * ssl3_HandleRecord() -> ssl3_HandleHandshake() ->
- * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificate() ->
- * ss->handleBadCert()
+ * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() ->
+ * ssl3_HandleRecord() -> ssl3_HandleHandshake() ->
+ * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificate() ->
+ * ss->handleBadCert()
*
- * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() ->
- * ssl3_HandleRecord() -> ssl3_HandleHandshake() ->
- * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificateRequest() ->
- * ss->getClientAuthData()
+ * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() ->
+ * ssl3_HandleRecord() -> ssl3_HandleHandshake() ->
+ * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificateRequest() ->
+ * ss->getClientAuthData()
*
- * Called from: SSL_ForceHandshake (below),
- * ssl_SecureRecv (below) and
- * ssl_SecureSend (below)
- * from: WaitForResponse in sslsocks.c
- * ssl_SocksRecv in sslsocks.c
- * ssl_SocksSend in sslsocks.c
+ * Called from: SSL_ForceHandshake (below),
+ * ssl_SecureRecv (below) and
+ * ssl_SecureSend (below)
+ * from: WaitForResponse in sslsocks.c
+ * ssl_SocksRecv in sslsocks.c
+ * ssl_SocksSend in sslsocks.c
*
* Caller must hold the (write) handshakeLock.
*/
-int
+int
ssl_Do1stHandshake(sslSocket *ss)
{
- int rv = SECSuccess;
+ int rv = SECSuccess;
int loopCount = 0;
do {
- PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
- PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
- PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
- PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss));
-
- if (ss->handshake == 0) {
- /* Previous handshake finished. Switch to next one */
- ss->handshake = ss->nextHandshake;
- ss->nextHandshake = 0;
- }
- if (ss->handshake == 0) {
- /* Previous handshake finished. Switch to security handshake */
- ss->handshake = ss->securityHandshake;
- ss->securityHandshake = 0;
- }
- if (ss->handshake == 0) {
- /* for v3 this is done in ssl3_FinishHandshake */
- if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) {
- ssl_GetRecvBufLock(ss);
- ss->gs.recordLen = 0;
- ssl_FinishHandshake(ss);
- ssl_ReleaseRecvBufLock(ss);
- }
- break;
- }
- rv = (*ss->handshake)(ss);
- ++loopCount;
- /* This code must continue to loop on SECWouldBlock,
- * or any positive value. See XXX_1 comments.
- */
- } while (rv != SECFailure); /* was (rv >= 0); XXX_1 */
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss));
+
+ if (ss->handshake == 0) {
+ /* Previous handshake finished. Switch to next one */
+ ss->handshake = ss->nextHandshake;
+ ss->nextHandshake = 0;
+ }
+ if (ss->handshake == 0) {
+ /* Previous handshake finished. Switch to security handshake */
+ ss->handshake = ss->securityHandshake;
+ ss->securityHandshake = 0;
+ }
+ if (ss->handshake == 0) {
+ /* for v3 this is done in ssl3_FinishHandshake */
+ if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) {
+ ssl_GetRecvBufLock(ss);
+ ss->gs.recordLen = 0;
+ ssl_FinishHandshake(ss);
+ ssl_ReleaseRecvBufLock(ss);
+ }
+ break;
+ }
+ rv = (*ss->handshake)(ss);
+ ++loopCount;
+ /* This code must continue to loop on SECWouldBlock,
+ * or any positive value. See XXX_1 comments.
+ */
+ } while (rv != SECFailure); /* was (rv >= 0); XXX_1 */
PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss));
if (rv == SECWouldBlock) {
- PORT_SetError(PR_WOULD_BLOCK_ERROR);
- rv = SECFailure;
+ PORT_SetError(PR_WOULD_BLOCK_ERROR);
+ rv = SECFailure;
}
return rv;
}
@@ -127,21 +127,21 @@ ssl_Do1stHandshake(sslSocket *ss)
void
ssl_FinishHandshake(sslSocket *ss)
{
- PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
SSL_TRC(3, ("%d: SSL[%d]: handshake is completed", SSL_GETPID(), ss->fd));
ss->firstHsDone = PR_TRUE;
ss->enoughFirstHsDone = PR_TRUE;
ss->gs.writeOffset = 0;
- ss->gs.readOffset = 0;
+ ss->gs.readOffset = 0;
if (ss->handshakeCallback) {
- PORT_Assert(ss->version < SSL_LIBRARY_VERSION_3_0 ||
- (ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
- ssl_preinfo_all);
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
+ PORT_Assert(ss->version < SSL_LIBRARY_VERSION_3_0 ||
+ (ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) ==
+ ssl_preinfo_all);
+ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
}
}
@@ -152,7 +152,7 @@ ssl_FinishHandshake(sslSocket *ss)
static SECStatus
ssl3_AlwaysBlock(sslSocket *ss)
{
- PORT_SetError(PR_WOULD_BLOCK_ERROR); /* perhaps redundant. */
+ PORT_SetError(PR_WOULD_BLOCK_ERROR); /* perhaps redundant. */
return SECWouldBlock;
}
@@ -163,20 +163,20 @@ void
ssl3_SetAlwaysBlock(sslSocket *ss)
{
if (!ss->firstHsDone) {
- ss->handshake = ssl3_AlwaysBlock;
- ss->nextHandshake = 0;
+ ss->handshake = ssl3_AlwaysBlock;
+ ss->nextHandshake = 0;
}
}
-static SECStatus
+static SECStatus
ssl_SetTimeout(PRFileDesc *fd, PRIntervalTime timeout)
{
sslSocket *ss;
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SetTimeout", SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SetTimeout", SSL_GETPID(), fd));
+ return SECFailure;
}
SSL_LOCK_READER(ss);
ss->rTimeout = timeout;
@@ -202,13 +202,13 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
ss = ssl_FindSocket(s);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in ResetHandshake", SSL_GETPID(), s));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in ResetHandshake", SSL_GETPID(), s));
+ return SECFailure;
}
/* Don't waste my time */
if (!ss->opt.useSecurity)
- return SECSuccess;
+ return SECSuccess;
SSL_LOCK_READER(ss);
SSL_LOCK_WRITER(ss);
@@ -218,15 +218,15 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
ss->firstHsDone = PR_FALSE;
ss->enoughFirstHsDone = PR_FALSE;
- if ( asServer ) {
- ss->handshake = ssl2_BeginServerHandshake;
- ss->handshaking = sslHandshakingAsServer;
+ if (asServer) {
+ ss->handshake = ssl2_BeginServerHandshake;
+ ss->handshaking = sslHandshakingAsServer;
} else {
- ss->handshake = ssl2_BeginClientHandshake;
- ss->handshaking = sslHandshakingAsClient;
+ ss->handshake = ssl2_BeginClientHandshake;
+ ss->handshaking = sslHandshakingAsClient;
}
- ss->nextHandshake = 0;
- ss->securityHandshake = 0;
+ ss->nextHandshake = 0;
+ ss->securityHandshake = 0;
ssl_GetRecvBufLock(ss);
status = ssl_InitGather(&ss->gs);
@@ -239,16 +239,16 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
/*
** Blow away old security state and get a fresh setup.
*/
- ssl_GetXmitBufLock(ss);
+ ssl_GetXmitBufLock(ss);
ssl_ResetSecurityInfo(&ss->sec, PR_TRUE);
status = ssl_CreateSecurityInfo(ss);
- ssl_ReleaseXmitBufLock(ss);
+ ssl_ReleaseXmitBufLock(ss);
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss);
if (!ss->TCPconnected)
- ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr));
+ ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr));
SSL_UNLOCK_WRITER(ss);
SSL_UNLOCK_READER(ss);
@@ -265,27 +265,27 @@ SECStatus
SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache)
{
sslSocket *ss;
- SECStatus rv;
-
+ SECStatus rv;
+
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in RedoHandshake", SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in RedoHandshake", SSL_GETPID(), fd));
+ return SECFailure;
}
if (!ss->opt.useSecurity)
- return SECSuccess;
-
+ return SECSuccess;
+
ssl_Get1stHandshakeLock(ss);
/* SSL v2 protocol does not support subsequent handshakes. */
if (ss->version < SSL_LIBRARY_VERSION_3_0) {
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
- rv = SECFailure;
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
+ rv = SECFailure;
} else {
- ssl_GetSSL3HandshakeLock(ss);
- rv = ssl3_RedoHandshake(ss, flushCache); /* force full handshake. */
- ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+ rv = ssl3_RedoHandshake(ss, flushCache); /* force full handshake. */
+ ssl_ReleaseSSL3HandshakeLock(ss);
}
ssl_Release1stHandshakeLock(ss);
@@ -296,9 +296,10 @@ SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache)
/*
** Same as above, but with an I/O timeout.
*/
-SSL_IMPORT SECStatus SSL_ReHandshakeWithTimeout(PRFileDesc *fd,
- PRBool flushCache,
- PRIntervalTime timeout)
+SSL_IMPORT SECStatus
+SSL_ReHandshakeWithTimeout(PRFileDesc *fd,
+ PRBool flushCache,
+ PRIntervalTime timeout)
{
if (SECSuccess != ssl_SetTimeout(fd, timeout)) {
return SECFailure;
@@ -317,26 +318,26 @@ SSL_RedoHandshake(PRFileDesc *fd)
*/
SECStatus
SSL_HandshakeCallback(PRFileDesc *fd, SSLHandshakeCallback cb,
- void *client_data)
+ void *client_data)
{
sslSocket *ss;
-
+
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in HandshakeCallback",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in HandshakeCallback",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
if (!ss->opt.useSecurity) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss);
- ss->handshakeCallback = cb;
+ ss->handshakeCallback = cb;
ss->handshakeCallbackData = client_data;
ssl_ReleaseSSL3HandshakeLock(ss);
@@ -350,26 +351,26 @@ SSL_HandshakeCallback(PRFileDesc *fd, SSLHandshakeCallback cb,
*/
SECStatus
SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
- void *arg)
+ void *arg)
{
sslSocket *ss;
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetCanFalseStartCallback",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetCanFalseStartCallback",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
if (!ss->opt.useSecurity) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss);
- ss->canFalseStartCallback = cb;
+ ss->canFalseStartCallback = cb;
ss->canFalseStartCallbackData = arg;
ssl_ReleaseSSL3HandshakeLock(ss);
@@ -386,90 +387,90 @@ SSL_RecommendedCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
*canFalseStart = PR_FALSE;
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RecommendedCanFalseStart",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RecommendedCanFalseStart",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
if (!ss->ssl3.initialized) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
if (ss->version < SSL_LIBRARY_VERSION_3_0) {
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
+ return SECFailure;
}
/* Require a forward-secret key exchange. */
*canFalseStart = ss->ssl3.hs.kea_def->kea == kea_dhe_dss ||
- ss->ssl3.hs.kea_def->kea == kea_dhe_rsa ||
- ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
- ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa;
+ ss->ssl3.hs.kea_def->kea == kea_dhe_rsa ||
+ ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
+ ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa;
return SECSuccess;
}
-/* Try to make progress on an SSL handshake by attempting to read the
+/* Try to make progress on an SSL handshake by attempting to read the
** next handshake from the peer, and sending any responses.
-** For non-blocking sockets, returns PR_ERROR_WOULD_BLOCK if it cannot
+** For non-blocking sockets, returns PR_ERROR_WOULD_BLOCK if it cannot
** read the next handshake from the underlying socket.
** For SSLv2, returns when handshake is complete or fatal error occurs.
** For SSLv3, returns when handshake is complete, or application data has
-** arrived that must be taken by application before handshake can continue,
+** arrived that must be taken by application before handshake can continue,
** or a fatal error occurs.
-** Application should use handshake completion callback to tell which.
+** Application should use handshake completion callback to tell which.
*/
SECStatus
SSL_ForceHandshake(PRFileDesc *fd)
{
sslSocket *ss;
- SECStatus rv = SECFailure;
+ SECStatus rv = SECFailure;
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in ForceHandshake",
- SSL_GETPID(), fd));
- return rv;
+ SSL_DBG(("%d: SSL[%d]: bad socket in ForceHandshake",
+ SSL_GETPID(), fd));
+ return rv;
}
/* Don't waste my time */
- if (!ss->opt.useSecurity)
- return SECSuccess;
+ if (!ss->opt.useSecurity)
+ return SECSuccess;
if (!ssl_SocketIsBlocking(ss)) {
- ssl_GetXmitBufLock(ss);
- if (ss->pendingBuf.len != 0) {
- int sent = ssl_SendSavedWriteData(ss);
- if ((sent < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) {
- ssl_ReleaseXmitBufLock(ss);
- return SECFailure;
- }
- }
- ssl_ReleaseXmitBufLock(ss);
+ ssl_GetXmitBufLock(ss);
+ if (ss->pendingBuf.len != 0) {
+ int sent = ssl_SendSavedWriteData(ss);
+ if ((sent < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) {
+ ssl_ReleaseXmitBufLock(ss);
+ return SECFailure;
+ }
+ }
+ ssl_ReleaseXmitBufLock(ss);
}
ssl_Get1stHandshakeLock(ss);
if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
- int gatherResult;
-
- ssl_GetRecvBufLock(ss);
- gatherResult = ssl3_GatherCompleteHandshake(ss, 0);
- ssl_ReleaseRecvBufLock(ss);
- if (gatherResult > 0) {
- rv = SECSuccess;
- } else if (gatherResult == 0) {
- PORT_SetError(PR_END_OF_FILE_ERROR);
- } else if (gatherResult == SECWouldBlock) {
- PORT_SetError(PR_WOULD_BLOCK_ERROR);
- }
+ int gatherResult;
+
+ ssl_GetRecvBufLock(ss);
+ gatherResult = ssl3_GatherCompleteHandshake(ss, 0);
+ ssl_ReleaseRecvBufLock(ss);
+ if (gatherResult > 0) {
+ rv = SECSuccess;
+ } else if (gatherResult == 0) {
+ PORT_SetError(PR_END_OF_FILE_ERROR);
+ } else if (gatherResult == SECWouldBlock) {
+ PORT_SetError(PR_WOULD_BLOCK_ERROR);
+ }
} else if (!ss->firstHsDone) {
- rv = ssl_Do1stHandshake(ss);
+ rv = ssl_Do1stHandshake(ss);
} else {
- /* tried to force handshake on an SSL 2 socket that has
- ** already completed the handshake. */
- rv = SECSuccess; /* just pretend we did it. */
+ /* tried to force handshake on an SSL 2 socket that has
+ ** already completed the handshake. */
+ rv = SECSuccess; /* just pretend we did it. */
}
ssl_Release1stHandshakeLock(ss);
@@ -480,8 +481,9 @@ SSL_ForceHandshake(PRFileDesc *fd)
/*
** Same as above, but with an I/O timeout.
*/
-SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd,
- PRIntervalTime timeout)
+SSL_IMPORT SECStatus
+SSL_ForceHandshakeWithTimeout(PRFileDesc *fd,
+ PRIntervalTime timeout)
{
if (SECSuccess != ssl_SetTimeout(fd, timeout)) {
return SECFailure;
@@ -489,7 +491,6 @@ SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd,
return SSL_ForceHandshake(fd);
}
-
/************************************************************************/
/*
@@ -502,32 +503,32 @@ sslBuffer_Grow(sslBuffer *b, unsigned int newLen)
{
newLen = PR_MAX(newLen, MAX_FRAGMENT_LENGTH + 2048);
if (newLen > b->space) {
- unsigned char *newBuf;
- if (b->buf) {
- newBuf = (unsigned char *) PORT_Realloc(b->buf, newLen);
- } else {
- newBuf = (unsigned char *) PORT_Alloc(newLen);
- }
- if (!newBuf) {
- return SECFailure;
- }
- SSL_TRC(10, ("%d: SSL: grow buffer from %d to %d",
- SSL_GETPID(), b->space, newLen));
- b->buf = newBuf;
- b->space = newLen;
+ unsigned char *newBuf;
+ if (b->buf) {
+ newBuf = (unsigned char *)PORT_Realloc(b->buf, newLen);
+ } else {
+ newBuf = (unsigned char *)PORT_Alloc(newLen);
+ }
+ if (!newBuf) {
+ return SECFailure;
+ }
+ SSL_TRC(10, ("%d: SSL: grow buffer from %d to %d",
+ SSL_GETPID(), b->space, newLen));
+ b->buf = newBuf;
+ b->space = newLen;
}
return SECSuccess;
}
-SECStatus
-sslBuffer_Append(sslBuffer *b, const void * data, unsigned int len)
+SECStatus
+sslBuffer_Append(sslBuffer *b, const void *data, unsigned int len)
{
unsigned int newLen = b->len + len;
SECStatus rv;
rv = sslBuffer_Grow(b, newLen);
if (rv != SECSuccess)
- return rv;
+ return rv;
PORT_Memcpy(b->buf + b->len, data, len);
b->len += len;
return SECSuccess;
@@ -539,15 +540,15 @@ sslBuffer_Append(sslBuffer *b, const void * data, unsigned int len)
** flush this data out.
** Caller must hold xmitBufLock
*/
-SECStatus
+SECStatus
ssl_SaveWriteData(sslSocket *ss, const void *data, unsigned int len)
{
- SECStatus rv;
+ SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
rv = sslBuffer_Append(&ss->pendingBuf, data, len);
SSL_TRC(5, ("%d: SSL[%d]: saving %u bytes of data (%u total saved so far)",
- SSL_GETPID(), ss->fd, len, ss->pendingBuf.len));
+ SSL_GETPID(), ss->fd, len, ss->pendingBuf.len));
return rv;
}
@@ -557,25 +558,25 @@ ssl_SaveWriteData(sslSocket *ss, const void *data, unsigned int len)
** Returns count of the bytes sent, NOT a SECStatus.
** Caller must hold xmitBufLock
*/
-int
+int
ssl_SendSavedWriteData(sslSocket *ss)
{
- int rv = 0;
+ int rv = 0;
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
if (ss->pendingBuf.len != 0) {
- SSL_TRC(5, ("%d: SSL[%d]: sending %d bytes of saved data",
- SSL_GETPID(), ss->fd, ss->pendingBuf.len));
- rv = ssl_DefSend(ss, ss->pendingBuf.buf, ss->pendingBuf.len, 0);
- if (rv < 0) {
- return rv;
- }
- ss->pendingBuf.len -= rv;
- if (ss->pendingBuf.len > 0 && rv > 0) {
- /* UGH !! This shifts the whole buffer down by copying it */
- PORT_Memmove(ss->pendingBuf.buf, ss->pendingBuf.buf + rv,
- ss->pendingBuf.len);
- }
+ SSL_TRC(5, ("%d: SSL[%d]: sending %d bytes of saved data",
+ SSL_GETPID(), ss->fd, ss->pendingBuf.len));
+ rv = ssl_DefSend(ss, ss->pendingBuf.buf, ss->pendingBuf.len, 0);
+ if (rv < 0) {
+ return rv;
+ }
+ ss->pendingBuf.len -= rv;
+ if (ss->pendingBuf.len > 0 && rv > 0) {
+ /* UGH !! This shifts the whole buffer down by copying it */
+ PORT_Memmove(ss->pendingBuf.buf, ss->pendingBuf.buf + rv,
+ ss->pendingBuf.len);
+ }
}
return rv;
}
@@ -593,15 +594,15 @@ ssl_SendSavedWriteData(sslSocket *ss)
** For SSLv3, the call to ssl3_GatherAppDataRecord may encounter handshake
** messages from a subsequent handshake.
**
-** This code is similar to, and easily confused with,
+** This code is similar to, and easily confused with,
** ssl_GatherRecord1stHandshake() in sslcon.c
*/
-static int
+static int
DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
{
- int rv;
- int amount;
- int available;
+ int rv;
+ int amount;
+ int available;
/* ssl3_GatherAppDataRecord may call ssl_FinishHandshake, which needs the
* 1stHandshakeLock. */
@@ -610,51 +611,51 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
available = ss->gs.writeOffset - ss->gs.readOffset;
if (available == 0) {
- /* Get some more data */
- if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
- /* Wait for application data to arrive. */
- rv = ssl3_GatherAppDataRecord(ss, 0);
- } else {
- /* See if we have a complete record */
- rv = ssl2_GatherRecord(ss, 0);
- }
- if (rv <= 0) {
- if (rv == 0) {
- /* EOF */
- SSL_TRC(10, ("%d: SSL[%d]: ssl_recv EOF",
- SSL_GETPID(), ss->fd));
- goto done;
- }
- if ((rv != SECWouldBlock) &&
- (PR_GetError() != PR_WOULD_BLOCK_ERROR)) {
- /* Some random error */
- goto done;
- }
-
- /*
- ** Gather record is blocked waiting for more record data to
- ** arrive. Try to process what we have already received
- */
- } else {
- /* Gather record has finished getting a complete record */
- }
-
- /* See if any clear data is now available */
- available = ss->gs.writeOffset - ss->gs.readOffset;
- if (available == 0) {
- /*
- ** No partial data is available. Force error code to
- ** EWOULDBLOCK so that caller will try again later. Note
- ** that the error code is probably EWOULDBLOCK already,
- ** but if it isn't (for example, if we received a zero
- ** length record) then this will force it to be correct.
- */
- PORT_SetError(PR_WOULD_BLOCK_ERROR);
- rv = SECFailure;
- goto done;
- }
- SSL_TRC(30, ("%d: SSL[%d]: partial data ready, available=%d",
- SSL_GETPID(), ss->fd, available));
+ /* Get some more data */
+ if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
+ /* Wait for application data to arrive. */
+ rv = ssl3_GatherAppDataRecord(ss, 0);
+ } else {
+ /* See if we have a complete record */
+ rv = ssl2_GatherRecord(ss, 0);
+ }
+ if (rv <= 0) {
+ if (rv == 0) {
+ /* EOF */
+ SSL_TRC(10, ("%d: SSL[%d]: ssl_recv EOF",
+ SSL_GETPID(), ss->fd));
+ goto done;
+ }
+ if ((rv != SECWouldBlock) &&
+ (PR_GetError() != PR_WOULD_BLOCK_ERROR)) {
+ /* Some random error */
+ goto done;
+ }
+
+ /*
+ ** Gather record is blocked waiting for more record data to
+ ** arrive. Try to process what we have already received
+ */
+ } else {
+ /* Gather record has finished getting a complete record */
+ }
+
+ /* See if any clear data is now available */
+ available = ss->gs.writeOffset - ss->gs.readOffset;
+ if (available == 0) {
+ /*
+ ** No partial data is available. Force error code to
+ ** EWOULDBLOCK so that caller will try again later. Note
+ ** that the error code is probably EWOULDBLOCK already,
+ ** but if it isn't (for example, if we received a zero
+ ** length record) then this will force it to be correct.
+ */
+ PORT_SetError(PR_WOULD_BLOCK_ERROR);
+ rv = SECFailure;
+ goto done;
+ }
+ SSL_TRC(30, ("%d: SSL[%d]: partial data ready, available=%d",
+ SSL_GETPID(), ss->fd, available));
}
if (IS_DTLS(ss) && (len < available)) {
@@ -671,13 +672,13 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
amount = PR_MIN(len, available);
PORT_Memcpy(out, ss->gs.buf.buf + ss->gs.readOffset, amount);
if (!(flags & PR_MSG_PEEK)) {
- ss->gs.readOffset += amount;
+ ss->gs.readOffset += amount;
}
PORT_Assert(ss->gs.readOffset <= ss->gs.writeOffset);
rv = amount;
SSL_TRC(30, ("%d: SSL[%d]: amount=%d available=%d",
- SSL_GETPID(), ss->fd, amount, available));
+ SSL_GETPID(), ss->fd, amount, available));
PRINT_BUF(4, (ss, "DoRecv receiving plaintext:", out, amount));
done:
@@ -692,60 +693,63 @@ done:
** Return SSLKEAType derived from cert's Public Key algorithm info.
*/
SSLKEAType
-NSS_FindCertKEAType(CERTCertificate * cert)
+NSS_FindCertKEAType(CERTCertificate *cert)
{
- SSLKEAType keaType = kt_null;
- int tag;
-
- if (!cert) goto loser;
-
- tag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
-
- switch (tag) {
- case SEC_OID_X500_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_RSA_ENCRYPTION:
- keaType = kt_rsa;
- break;
- case SEC_OID_ANSIX9_DSA_SIGNATURE: /* hah, signature, not a key? */
- case SEC_OID_X942_DIFFIE_HELMAN_KEY:
- keaType = kt_dh;
- break;
+ SSLKEAType keaType = kt_null;
+ int tag;
+
+ if (!cert)
+ goto loser;
+
+ tag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
+
+ switch (tag) {
+ case SEC_OID_X500_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ keaType = kt_rsa;
+ break;
+ case SEC_OID_ANSIX9_DSA_SIGNATURE: /* hah, signature, not a key? */
+ case SEC_OID_X942_DIFFIE_HELMAN_KEY:
+ keaType = kt_dh;
+ break;
#ifndef NSS_DISABLE_ECC
- case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
- keaType = kt_ecdh;
- break;
+ case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
+ keaType = kt_ecdh;
+ break;
#endif /* NSS_DISABLE_ECC */
- default:
- keaType = kt_null;
- }
-
- loser:
-
- return keaType;
+ default:
+ keaType = kt_null;
+ }
+
+loser:
+
+ return keaType;
}
static const PRCallOnceType pristineCallOnce;
-static PRCallOnceType setupServerCAListOnce;
+static PRCallOnceType setupServerCAListOnce;
-static SECStatus serverCAListShutdown(void* appData, void* nssData)
+static SECStatus
+serverCAListShutdown(void *appData, void *nssData)
{
PORT_Assert(ssl3_server_ca_list);
if (ssl3_server_ca_list) {
- CERT_FreeDistNames(ssl3_server_ca_list);
- ssl3_server_ca_list = NULL;
+ CERT_FreeDistNames(ssl3_server_ca_list);
+ ssl3_server_ca_list = NULL;
}
setupServerCAListOnce = pristineCallOnce;
return SECSuccess;
}
-static PRStatus serverCAListSetup(void *arg)
+static PRStatus
+serverCAListSetup(void *arg)
{
CERTCertDBHandle *dbHandle = (CERTCertDBHandle *)arg;
SECStatus rv = NSS_RegisterShutdown(serverCAListShutdown, NULL);
PORT_Assert(SECSuccess == rv);
if (SECSuccess == rv) {
- ssl3_server_ca_list = CERT_GetSSLCACerts(dbHandle);
- return PR_SUCCESS;
+ ssl3_server_ca_list = CERT_GetSSLCACerts(dbHandle);
+ return PR_SUCCESS;
}
return PR_FAILURE;
}
@@ -756,18 +760,18 @@ ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert,
ssl3KeyPair *keyPair, SSLKEAType kea)
{
CERTCertificateList *localCertChain = NULL;
- sslServerCerts *sc = ss->serverCerts + kea;
+ sslServerCerts *sc = ss->serverCerts + kea;
/* load the server certificate */
if (sc->serverCert != NULL) {
- CERT_DestroyCertificate(sc->serverCert);
- sc->serverCert = NULL;
+ CERT_DestroyCertificate(sc->serverCert);
+ sc->serverCert = NULL;
sc->serverKeyBits = 0;
}
/* load the server cert chain */
if (sc->serverCertChain != NULL) {
- CERT_DestroyCertificateList(sc->serverCertChain);
- sc->serverCertChain = NULL;
+ CERT_DestroyCertificateList(sc->serverCertChain);
+ sc->serverCertChain = NULL;
}
if (cert) {
sc->serverCert = CERT_DupCertificate(cert);
@@ -781,11 +785,11 @@ ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert,
goto loser;
}
sc->serverCertChain = (certChain) ? CERT_DupCertList(certChain) :
- localCertChain;
+ localCertChain;
if (!sc->serverCertChain) {
goto loser;
}
- localCertChain = NULL; /* consumed */
+ localCertChain = NULL; /* consumed */
}
/* get keyPair */
@@ -798,7 +802,7 @@ ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert,
sc->serverKeyPair = ssl3_GetKeyPairRef(keyPair);
}
if (kea == kt_rsa && cert && sc->serverKeyBits > 512 &&
- !ss->opt.noStepDown && !ss->stepDownKeyPair) {
+ !ss->opt.noStepDown && !ss->stepDownKeyPair) {
if (ssl3_CreateRSAStepDownKeys(ss) != SECSuccess) {
goto loser;
}
@@ -807,7 +811,7 @@ ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert,
if (ssl3_SelectDHParams(ss) != SECSuccess) {
goto loser;
}
- }
+ }
return SECSuccess;
loser:
@@ -815,16 +819,16 @@ loser:
CERT_DestroyCertificateList(localCertChain);
}
if (sc->serverCert != NULL) {
- CERT_DestroyCertificate(sc->serverCert);
- sc->serverCert = NULL;
+ CERT_DestroyCertificate(sc->serverCert);
+ sc->serverCert = NULL;
}
if (sc->serverCertChain != NULL) {
- CERT_DestroyCertificateList(sc->serverCertChain);
- sc->serverCertChain = NULL;
+ CERT_DestroyCertificateList(sc->serverCertChain);
+ sc->serverCertChain = NULL;
}
if (sc->serverKeyPair != NULL) {
- ssl3_FreeKeyPair(sc->serverKeyPair);
- sc->serverKeyPair = NULL;
+ ssl3_FreeKeyPair(sc->serverKeyPair);
+ sc->serverKeyPair = NULL;
}
return SECFailure;
}
@@ -833,7 +837,7 @@ loser:
SECStatus
SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
- SECKEYPrivateKey *key, SSL3KEAType kea)
+ SECKEYPrivateKey *key, SSL3KEAType kea)
{
return SSL_ConfigSecureServerWithCertChain(fd, cert, NULL, key, kea);
@@ -851,68 +855,68 @@ SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert,
ss = ssl_FindSocket(fd);
if (!ss) {
- return SECFailure;
+ return SECFailure;
}
/* Both key and cert must have a value or be NULL */
/* Passing a value of NULL will turn off key exchange algorithms that were
* previously turned on */
if (!cert != !key) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
/* make sure the key exchange is recognized */
if ((kea >= kt_kea_size) || (kea < kt_null)) {
- PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
+ return SECFailure;
}
if (kea != NSS_FindCertKEAType(cert)) {
- PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH);
- return SECFailure;
+ PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH);
+ return SECFailure;
}
if (cert) {
- /* get the size of the cert's public key, and remember it */
- pubKey = CERT_ExtractPublicKey(cert);
- if (!pubKey)
+ /* get the size of the cert's public key, and remember it */
+ pubKey = CERT_ExtractPublicKey(cert);
+ if (!pubKey)
return SECFailure;
}
if (key) {
- SECKEYPrivateKey * keyCopy = NULL;
- CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM;
-
- if (key->pkcs11Slot) {
- PK11SlotInfo * bestSlot;
- bestSlot = PK11_ReferenceSlot(key->pkcs11Slot);
- if (bestSlot) {
- keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
- PK11_FreeSlot(bestSlot);
- }
- }
- if (keyCopy == NULL)
- keyMech = PK11_MapSignKeyType(key->keyType);
- if (keyMech != CKM_INVALID_MECHANISM) {
- PK11SlotInfo * bestSlot;
- /* XXX Maybe should be bestSlotMultiple? */
- bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */);
- if (bestSlot) {
- keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
- PK11_FreeSlot(bestSlot);
- }
- }
- if (keyCopy == NULL)
- keyCopy = SECKEY_CopyPrivateKey(key);
- if (keyCopy == NULL)
- goto loser;
+ SECKEYPrivateKey *keyCopy = NULL;
+ CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM;
+
+ if (key->pkcs11Slot) {
+ PK11SlotInfo *bestSlot;
+ bestSlot = PK11_ReferenceSlot(key->pkcs11Slot);
+ if (bestSlot) {
+ keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
+ PK11_FreeSlot(bestSlot);
+ }
+ }
+ if (keyCopy == NULL)
+ keyMech = PK11_MapSignKeyType(key->keyType);
+ if (keyMech != CKM_INVALID_MECHANISM) {
+ PK11SlotInfo *bestSlot;
+ /* XXX Maybe should be bestSlotMultiple? */
+ bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */);
+ if (bestSlot) {
+ keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
+ PK11_FreeSlot(bestSlot);
+ }
+ }
+ if (keyCopy == NULL)
+ keyCopy = SECKEY_CopyPrivateKey(key);
+ if (keyCopy == NULL)
+ goto loser;
keyPair = ssl3_NewKeyPair(keyCopy, pubKey);
if (keyPair == NULL) {
SECKEY_DestroyPrivateKey(keyCopy);
goto loser;
}
- pubKey = NULL; /* adopted by serverKeyPair */
+ pubKey = NULL; /* adopted by serverKeyPair */
}
if (ssl_ConfigSecureServer(ss, cert, certChainOpt,
keyPair, kea) == SECFailure) {
@@ -920,7 +924,7 @@ SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert,
}
/* Only do this once because it's global. */
- if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce,
+ if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce,
&serverCAListSetup,
(void *)(ss->dbHandle))) {
rv = SECSuccess;
@@ -931,8 +935,8 @@ loser:
ssl3_FreeKeyPair(keyPair);
}
if (pubKey) {
- SECKEY_DestroyPublicKey(pubKey);
- pubKey = NULL;
+ SECKEY_DestroyPublicKey(pubKey);
+ pubKey = NULL;
}
return rv;
}
@@ -947,12 +951,12 @@ ssl_CreateSecurityInfo(sslSocket *ss)
/* initialize sslv2 socket to send data in the clear. */
ssl2_UseClearSendFunc(ss);
- ss->sec.blockSize = 1;
+ ss->sec.blockSize = 1;
ss->sec.blockShift = 0;
- ssl_GetXmitBufLock(ss);
+ ssl_GetXmitBufLock(ss);
status = sslBuffer_Grow(&ss->sec.writeBuf, 4096);
- ssl_ReleaseXmitBufLock(ss);
+ ssl_ReleaseXmitBufLock(ss);
return status;
}
@@ -960,50 +964,50 @@ ssl_CreateSecurityInfo(sslSocket *ss)
SECStatus
ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os)
{
- ss->sec.send = os->sec.send;
- ss->sec.isServer = os->sec.isServer;
- ss->sec.keyBits = os->sec.keyBits;
- ss->sec.secretKeyBits = os->sec.secretKeyBits;
+ ss->sec.send = os->sec.send;
+ ss->sec.isServer = os->sec.isServer;
+ ss->sec.keyBits = os->sec.keyBits;
+ ss->sec.secretKeyBits = os->sec.secretKeyBits;
- ss->sec.peerCert = CERT_DupCertificate(os->sec.peerCert);
+ ss->sec.peerCert = CERT_DupCertificate(os->sec.peerCert);
if (os->sec.peerCert && !ss->sec.peerCert)
- goto loser;
+ goto loser;
- ss->sec.cache = os->sec.cache;
- ss->sec.uncache = os->sec.uncache;
+ ss->sec.cache = os->sec.cache;
+ ss->sec.uncache = os->sec.uncache;
/* we don't dup the connection info. */
- ss->sec.sendSequence = os->sec.sendSequence;
- ss->sec.rcvSequence = os->sec.rcvSequence;
+ ss->sec.sendSequence = os->sec.sendSequence;
+ ss->sec.rcvSequence = os->sec.rcvSequence;
if (os->sec.hash && os->sec.hashcx) {
- ss->sec.hash = os->sec.hash;
- ss->sec.hashcx = os->sec.hash->clone(os->sec.hashcx);
- if (os->sec.hashcx && !ss->sec.hashcx)
- goto loser;
+ ss->sec.hash = os->sec.hash;
+ ss->sec.hashcx = os->sec.hash->clone(os->sec.hashcx);
+ if (os->sec.hashcx && !ss->sec.hashcx)
+ goto loser;
} else {
- ss->sec.hash = NULL;
- ss->sec.hashcx = NULL;
+ ss->sec.hash = NULL;
+ ss->sec.hashcx = NULL;
}
if (SECITEM_CopyItem(0, &ss->sec.sendSecret, &os->sec.sendSecret))
- goto loser;
- if (SECITEM_CopyItem(0, &ss->sec.rcvSecret, &os->sec.rcvSecret))
- goto loser;
+ goto loser;
+ if (SECITEM_CopyItem(0, &ss->sec.rcvSecret, &os->sec.rcvSecret))
+ goto loser;
/* XXX following code is wrong if either cx != 0 */
- PORT_Assert(os->sec.readcx == 0);
+ PORT_Assert(os->sec.readcx == 0);
PORT_Assert(os->sec.writecx == 0);
- ss->sec.readcx = os->sec.readcx;
- ss->sec.writecx = os->sec.writecx;
- ss->sec.destroy = 0;
+ ss->sec.readcx = os->sec.readcx;
+ ss->sec.writecx = os->sec.writecx;
+ ss->sec.destroy = 0;
- ss->sec.enc = os->sec.enc;
- ss->sec.dec = os->sec.dec;
+ ss->sec.enc = os->sec.enc;
+ ss->sec.dec = os->sec.dec;
- ss->sec.blockShift = os->sec.blockShift;
- ss->sec.blockSize = os->sec.blockSize;
+ ss->sec.blockShift = os->sec.blockShift;
+ ss->sec.blockSize = os->sec.blockSize;
return SECSuccess;
@@ -1014,61 +1018,60 @@ loser:
/* Reset sec back to its initial state.
** Caller holds any relevant locks.
*/
-void
+void
ssl_ResetSecurityInfo(sslSecurityInfo *sec, PRBool doMemset)
{
/* Destroy MAC */
if (sec->hash && sec->hashcx) {
- (*sec->hash->destroy)(sec->hashcx, PR_TRUE);
- sec->hashcx = NULL;
- sec->hash = NULL;
+ (*sec->hash->destroy)(sec->hashcx, PR_TRUE);
+ sec->hashcx = NULL;
+ sec->hash = NULL;
}
SECITEM_ZfreeItem(&sec->sendSecret, PR_FALSE);
SECITEM_ZfreeItem(&sec->rcvSecret, PR_FALSE);
/* Destroy ciphers */
if (sec->destroy) {
- (*sec->destroy)(sec->readcx, PR_TRUE);
- (*sec->destroy)(sec->writecx, PR_TRUE);
- sec->readcx = NULL;
- sec->writecx = NULL;
+ (*sec->destroy)(sec->readcx, PR_TRUE);
+ (*sec->destroy)(sec->writecx, PR_TRUE);
+ sec->readcx = NULL;
+ sec->writecx = NULL;
} else {
- PORT_Assert(sec->readcx == 0);
- PORT_Assert(sec->writecx == 0);
+ PORT_Assert(sec->readcx == 0);
+ PORT_Assert(sec->writecx == 0);
}
sec->readcx = 0;
sec->writecx = 0;
if (sec->localCert) {
- CERT_DestroyCertificate(sec->localCert);
- sec->localCert = NULL;
+ CERT_DestroyCertificate(sec->localCert);
+ sec->localCert = NULL;
}
if (sec->peerCert) {
- CERT_DestroyCertificate(sec->peerCert);
- sec->peerCert = NULL;
+ CERT_DestroyCertificate(sec->peerCert);
+ sec->peerCert = NULL;
}
if (sec->peerKey) {
- SECKEY_DestroyPublicKey(sec->peerKey);
- sec->peerKey = NULL;
+ SECKEY_DestroyPublicKey(sec->peerKey);
+ sec->peerKey = NULL;
}
/* cleanup the ci */
if (sec->ci.sid != NULL) {
- ssl_FreeSID(sec->ci.sid);
+ ssl_FreeSID(sec->ci.sid);
}
PORT_ZFree(sec->ci.sendBuf.buf, sec->ci.sendBuf.space);
if (doMemset) {
memset(&sec->ci, 0, sizeof sec->ci);
}
-
}
/*
-** Called from SSL_ResetHandshake (above), and
+** Called from SSL_ResetHandshake (above), and
** from ssl_FreeSocket in sslsock.c
** Caller should hold relevant locks (e.g. XmitBufLock)
*/
-void
+void
ssl_DestroySecurityInfo(sslSecurityInfo *sec)
{
ssl_ResetSecurityInfo(sec, PR_FALSE);
@@ -1081,35 +1084,35 @@ ssl_DestroySecurityInfo(sslSecurityInfo *sec)
/************************************************************************/
-int
+int
ssl_SecureConnect(sslSocket *ss, const PRNetAddr *sa)
{
PRFileDesc *osfd = ss->fd->lower;
int rv;
- if ( ss->opt.handshakeAsServer ) {
- ss->securityHandshake = ssl2_BeginServerHandshake;
- ss->handshaking = sslHandshakingAsServer;
+ if (ss->opt.handshakeAsServer) {
+ ss->securityHandshake = ssl2_BeginServerHandshake;
+ ss->handshaking = sslHandshakingAsServer;
} else {
- ss->securityHandshake = ssl2_BeginClientHandshake;
- ss->handshaking = sslHandshakingAsClient;
+ ss->securityHandshake = ssl2_BeginClientHandshake;
+ ss->handshaking = sslHandshakingAsClient;
}
/* connect to server */
rv = osfd->methods->connect(osfd, sa, ss->cTimeout);
if (rv == PR_SUCCESS) {
- ss->TCPconnected = 1;
+ ss->TCPconnected = 1;
} else {
- int err = PR_GetError();
- SSL_DBG(("%d: SSL[%d]: connect failed, errno=%d",
- SSL_GETPID(), ss->fd, err));
- if (err == PR_IS_CONNECTED_ERROR) {
- ss->TCPconnected = 1;
- }
+ int err = PR_GetError();
+ SSL_DBG(("%d: SSL[%d]: connect failed, errno=%d",
+ SSL_GETPID(), ss->fd, err));
+ if (err == PR_IS_CONNECTED_ERROR) {
+ ss->TCPconnected = 1;
+ }
}
SSL_TRC(5, ("%d: SSL[%d]: secure connect completed, rv == %d",
- SSL_GETPID(), ss->fd, rv));
+ SSL_GETPID(), ss->fd, rv));
return rv;
}
@@ -1142,19 +1145,19 @@ ssl_SecureClose(sslSocket *ss)
{
int rv;
- if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
- !(ss->shutdownHow & ssl_SHUTDOWN_SEND) &&
- ss->firstHsDone &&
- !ss->recvdCloseNotify &&
- ss->ssl3.initialized) {
+ if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
+ !(ss->shutdownHow & ssl_SHUTDOWN_SEND) &&
+ ss->firstHsDone &&
+ !ss->recvdCloseNotify &&
+ ss->ssl3.initialized) {
- /* We don't want the final alert to be Nagle delayed. */
- if (!ss->delayDisabled) {
- ssl_EnableNagleDelay(ss, PR_FALSE);
- ss->delayDisabled = 1;
- }
+ /* We don't want the final alert to be Nagle delayed. */
+ if (!ss->delayDisabled) {
+ ssl_EnableNagleDelay(ss, PR_FALSE);
+ ss->delayDisabled = 1;
+ }
- (void) SSL3_SendAlert(ss, alert_warning, close_notify);
+ (void)SSL3_SendAlert(ss, alert_warning, close_notify);
}
rv = ssl_DefClose(ss);
return rv;
@@ -1165,22 +1168,22 @@ int
ssl_SecureShutdown(sslSocket *ss, int nsprHow)
{
PRFileDesc *osfd = ss->fd->lower;
- int rv;
- PRIntn sslHow = nsprHow + 1;
+ int rv;
+ PRIntn sslHow = nsprHow + 1;
if ((unsigned)nsprHow > PR_SHUTDOWN_BOTH) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return PR_FAILURE;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return PR_FAILURE;
}
- if ((sslHow & ssl_SHUTDOWN_SEND) != 0 &&
- ss->version >= SSL_LIBRARY_VERSION_3_0 &&
- !(ss->shutdownHow & ssl_SHUTDOWN_SEND) &&
- ss->firstHsDone &&
- !ss->recvdCloseNotify &&
- ss->ssl3.initialized) {
+ if ((sslHow & ssl_SHUTDOWN_SEND) != 0 &&
+ ss->version >= SSL_LIBRARY_VERSION_3_0 &&
+ !(ss->shutdownHow & ssl_SHUTDOWN_SEND) &&
+ ss->firstHsDone &&
+ !ss->recvdCloseNotify &&
+ ss->ssl3.initialized) {
- (void) SSL3_SendAlert(ss, alert_warning, close_notify);
+ (void)SSL3_SendAlert(ss, alert_warning, close_notify);
}
rv = osfd->methods->shutdown(osfd, nsprHow);
@@ -1192,51 +1195,51 @@ ssl_SecureShutdown(sslSocket *ss, int nsprHow)
/************************************************************************/
-
int
ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
{
- int rv = 0;
+ int rv = 0;
if (ss->shutdownHow & ssl_SHUTDOWN_RCV) {
- PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
- return PR_FAILURE;
+ PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
+ return PR_FAILURE;
}
if (flags & ~PR_MSG_PEEK) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return PR_FAILURE;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return PR_FAILURE;
}
if (!ssl_SocketIsBlocking(ss) && !ss->opt.fdx) {
- ssl_GetXmitBufLock(ss);
- if (ss->pendingBuf.len != 0) {
- rv = ssl_SendSavedWriteData(ss);
- if ((rv < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) {
- ssl_ReleaseXmitBufLock(ss);
- return SECFailure;
- }
- }
- ssl_ReleaseXmitBufLock(ss);
- }
-
+ ssl_GetXmitBufLock(ss);
+ if (ss->pendingBuf.len != 0) {
+ rv = ssl_SendSavedWriteData(ss);
+ if ((rv < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) {
+ ssl_ReleaseXmitBufLock(ss);
+ return SECFailure;
+ }
+ }
+ ssl_ReleaseXmitBufLock(ss);
+ }
+
rv = 0;
/* If any of these is non-zero, the initial handshake is not done. */
if (!ss->firstHsDone) {
- ssl_Get1stHandshakeLock(ss);
- if (ss->handshake || ss->nextHandshake || ss->securityHandshake) {
- rv = ssl_Do1stHandshake(ss);
- }
- ssl_Release1stHandshakeLock(ss);
+ ssl_Get1stHandshakeLock(ss);
+ if (ss->handshake || ss->nextHandshake || ss->securityHandshake) {
+ rv = ssl_Do1stHandshake(ss);
+ }
+ ssl_Release1stHandshakeLock(ss);
}
if (rv < 0) {
- return rv;
+ return rv;
}
- if (len == 0) return 0;
+ if (len == 0)
+ return 0;
- rv = DoRecv(ss, (unsigned char*) buf, len, flags);
+ rv = DoRecv(ss, (unsigned char *)buf, len, flags);
SSL_TRC(2, ("%d: SSL[%d]: recving %d bytes securely (errno=%d)",
- SSL_GETPID(), ss->fd, rv, PORT_GetError()));
+ SSL_GETPID(), ss->fd, rv, PORT_GetError()));
return rv;
}
@@ -1253,84 +1256,84 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
int rv = 0;
SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
- SSL_GETPID(), ss->fd, len));
+ SSL_GETPID(), ss->fd, len));
if (ss->shutdownHow & ssl_SHUTDOWN_SEND) {
- PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
- rv = PR_FAILURE;
- goto done;
+ PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
+ rv = PR_FAILURE;
+ goto done;
}
if (flags) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- rv = PR_FAILURE;
- goto done;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ rv = PR_FAILURE;
+ goto done;
}
ssl_GetXmitBufLock(ss);
if (ss->pendingBuf.len != 0) {
- PORT_Assert(ss->pendingBuf.len > 0);
- rv = ssl_SendSavedWriteData(ss);
- if (rv >= 0 && ss->pendingBuf.len != 0) {
- PORT_Assert(ss->pendingBuf.len > 0);
- PORT_SetError(PR_WOULD_BLOCK_ERROR);
- rv = SECFailure;
- }
+ PORT_Assert(ss->pendingBuf.len > 0);
+ rv = ssl_SendSavedWriteData(ss);
+ if (rv >= 0 && ss->pendingBuf.len != 0) {
+ PORT_Assert(ss->pendingBuf.len > 0);
+ PORT_SetError(PR_WOULD_BLOCK_ERROR);
+ rv = SECFailure;
+ }
}
ssl_ReleaseXmitBufLock(ss);
if (rv < 0) {
- goto done;
+ goto done;
}
- if (len > 0)
- ss->writerThread = PR_GetCurrentThread();
+ if (len > 0)
+ ss->writerThread = PR_GetCurrentThread();
/* If any of these is non-zero, the initial handshake is not done. */
if (!ss->firstHsDone) {
- PRBool falseStart = PR_FALSE;
- ssl_Get1stHandshakeLock(ss);
- if (ss->opt.enableFalseStart &&
- ss->version >= SSL_LIBRARY_VERSION_3_0) {
- ssl_GetSSL3HandshakeLock(ss);
- falseStart = ss->ssl3.hs.canFalseStart;
- ssl_ReleaseSSL3HandshakeLock(ss);
- }
- if (!falseStart &&
- (ss->handshake || ss->nextHandshake || ss->securityHandshake)) {
- rv = ssl_Do1stHandshake(ss);
- }
- ssl_Release1stHandshakeLock(ss);
+ PRBool falseStart = PR_FALSE;
+ ssl_Get1stHandshakeLock(ss);
+ if (ss->opt.enableFalseStart &&
+ ss->version >= SSL_LIBRARY_VERSION_3_0) {
+ ssl_GetSSL3HandshakeLock(ss);
+ falseStart = ss->ssl3.hs.canFalseStart;
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ }
+ if (!falseStart &&
+ (ss->handshake || ss->nextHandshake || ss->securityHandshake)) {
+ rv = ssl_Do1stHandshake(ss);
+ }
+ ssl_Release1stHandshakeLock(ss);
}
if (rv < 0) {
- ss->writerThread = NULL;
- goto done;
+ ss->writerThread = NULL;
+ goto done;
}
/* Check for zero length writes after we do housekeeping so we make forward
* progress.
*/
if (len == 0) {
- rv = 0;
- goto done;
+ rv = 0;
+ goto done;
}
PORT_Assert(buf != NULL);
if (!buf) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- rv = PR_FAILURE;
- goto done;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ rv = PR_FAILURE;
+ goto done;
}
if (!ss->firstHsDone) {
- PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_3_0);
+ PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_3_0);
#ifdef DEBUG
- ssl_GetSSL3HandshakeLock(ss);
- PORT_Assert(ss->ssl3.hs.canFalseStart);
- ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+ PORT_Assert(ss->ssl3.hs.canFalseStart);
+ ssl_ReleaseSSL3HandshakeLock(ss);
#endif
- SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start",
- SSL_GETPID(), ss->fd));
+ SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start",
+ SSL_GETPID(), ss->fd));
}
/* Send out the data using one of these functions:
- * ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock,
+ * ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock,
* ssl3_SendApplicationData
*/
ssl_GetXmitBufLock(ss);
@@ -1339,11 +1342,11 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
ss->writerThread = NULL;
done:
if (rv < 0) {
- SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count, error %d",
- SSL_GETPID(), ss->fd, rv, PORT_GetError()));
+ SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count, error %d",
+ SSL_GETPID(), ss->fd, rv, PORT_GetError()));
} else {
- SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count",
- SSL_GETPID(), ss->fd, rv));
+ SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count",
+ SSL_GETPID(), ss->fd, rv));
}
return rv;
}
@@ -1358,12 +1361,12 @@ SECStatus
SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, void *arg)
{
sslSocket *ss;
-
+
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSLBadCertHook",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSLBadCertHook",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
ss->handleBadCert = f;
@@ -1380,24 +1383,24 @@ SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, void *arg)
SECStatus
SSL_SetURL(PRFileDesc *fd, const char *url)
{
- sslSocket * ss = ssl_FindSocket(fd);
- SECStatus rv = SECSuccess;
+ sslSocket *ss = ssl_FindSocket(fd);
+ SECStatus rv = SECSuccess;
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSLSetURL",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSLSetURL",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss);
- if ( ss->url ) {
- PORT_Free((void *)ss->url); /* CONST */
+ if (ss->url) {
+ PORT_Free((void *)ss->url); /* CONST */
}
ss->url = (const char *)PORT_Strdup(url);
- if ( ss->url == NULL ) {
- rv = SECFailure;
+ if (ss->url == NULL) {
+ rv = SECFailure;
}
ssl_ReleaseSSL3HandshakeLock(ss);
@@ -1412,7 +1415,7 @@ SSL_SetURL(PRFileDesc *fd, const char *url)
SECStatus
SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *certList)
{
- sslSocket * ss = ssl_FindSocket(fd);
+ sslSocket *ss = ssl_FindSocket(fd);
CERTDistNames *names = NULL;
if (!certList) {
@@ -1420,9 +1423,9 @@ SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *certList)
return SECFailure;
}
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetTrustAnchors",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetTrustAnchors",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
names = CERT_DistNamesFromCertList(certList);
@@ -1449,14 +1452,14 @@ int
SSL_DataPending(PRFileDesc *fd)
{
sslSocket *ss;
- int rv = 0;
+ int rv = 0;
ss = ssl_FindSocket(fd);
if (ss && ss->opt.useSecurity) {
- ssl_GetRecvBufLock(ss);
- rv = ss->gs.writeOffset - ss->gs.readOffset;
- ssl_ReleaseRecvBufLock(ss);
+ ssl_GetRecvBufLock(ss);
+ rv = ss->gs.writeOffset - ss->gs.readOffset;
+ ssl_ReleaseRecvBufLock(ss);
}
return rv;
@@ -1465,20 +1468,20 @@ SSL_DataPending(PRFileDesc *fd)
SECStatus
SSL_InvalidateSession(PRFileDesc *fd)
{
- sslSocket * ss = ssl_FindSocket(fd);
- SECStatus rv = SECFailure;
+ sslSocket *ss = ssl_FindSocket(fd);
+ SECStatus rv = SECFailure;
if (ss) {
- ssl_Get1stHandshakeLock(ss);
- ssl_GetSSL3HandshakeLock(ss);
+ ssl_Get1stHandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
- if (ss->sec.ci.sid && ss->sec.uncache) {
- ss->sec.uncache(ss->sec.ci.sid);
- rv = SECSuccess;
- }
+ if (ss->sec.ci.sid && ss->sec.uncache) {
+ ss->sec.uncache(ss->sec.ci.sid);
+ rv = SECSuccess;
+ }
- ssl_ReleaseSSL3HandshakeLock(ss);
- ssl_Release1stHandshakeLock(ss);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
}
return rv;
}
@@ -1489,26 +1492,26 @@ ssl3_CacheSessionUnlocked(sslSocket *ss)
PORT_Assert(!ss->sec.isServer);
if (ss->ssl3.hs.cacheSID) {
- ss->sec.cache(ss->sec.ci.sid);
- ss->ssl3.hs.cacheSID = PR_FALSE;
+ ss->sec.cache(ss->sec.ci.sid);
+ ss->ssl3.hs.cacheSID = PR_FALSE;
}
}
SECStatus
SSL_CacheSession(PRFileDesc *fd)
{
- sslSocket * ss = ssl_FindSocket(fd);
- SECStatus rv = SECFailure;
+ sslSocket *ss = ssl_FindSocket(fd);
+ SECStatus rv = SECFailure;
if (ss) {
- ssl_Get1stHandshakeLock(ss);
- ssl_GetSSL3HandshakeLock(ss);
+ ssl_Get1stHandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
- ssl3_CacheSessionUnlocked(ss);
- rv = SECSuccess;
+ ssl3_CacheSessionUnlocked(ss);
+ rv = SECSuccess;
- ssl_ReleaseSSL3HandshakeLock(ss);
- ssl_Release1stHandshakeLock(ss);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
}
return rv;
}
@@ -1516,12 +1519,12 @@ SSL_CacheSession(PRFileDesc *fd)
SECStatus
SSL_CacheSessionUnlocked(PRFileDesc *fd)
{
- sslSocket * ss = ssl_FindSocket(fd);
- SECStatus rv = SECFailure;
+ sslSocket *ss = ssl_FindSocket(fd);
+ SECStatus rv = SECFailure;
if (ss) {
- ssl3_CacheSessionUnlocked(ss);
- rv = SECSuccess;
+ ssl3_CacheSessionUnlocked(ss);
+ rv = SECSuccess;
}
return rv;
}
@@ -1529,32 +1532,32 @@ SSL_CacheSessionUnlocked(PRFileDesc *fd)
SECItem *
SSL_GetSessionID(PRFileDesc *fd)
{
- sslSocket * ss;
- SECItem * item = NULL;
+ sslSocket *ss;
+ SECItem *item = NULL;
ss = ssl_FindSocket(fd);
if (ss) {
- ssl_Get1stHandshakeLock(ss);
- ssl_GetSSL3HandshakeLock(ss);
-
- if (ss->opt.useSecurity && ss->firstHsDone && ss->sec.ci.sid) {
- item = (SECItem *)PORT_Alloc(sizeof(SECItem));
- if (item) {
- sslSessionID * sid = ss->sec.ci.sid;
- if (sid->version < SSL_LIBRARY_VERSION_3_0) {
- item->len = SSL2_SESSIONID_BYTES;
- item->data = (unsigned char*)PORT_Alloc(item->len);
- PORT_Memcpy(item->data, sid->u.ssl2.sessionID, item->len);
- } else {
- item->len = sid->u.ssl3.sessionIDLength;
- item->data = (unsigned char*)PORT_Alloc(item->len);
- PORT_Memcpy(item->data, sid->u.ssl3.sessionID, item->len);
- }
- }
- }
-
- ssl_ReleaseSSL3HandshakeLock(ss);
- ssl_Release1stHandshakeLock(ss);
+ ssl_Get1stHandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+
+ if (ss->opt.useSecurity && ss->firstHsDone && ss->sec.ci.sid) {
+ item = (SECItem *)PORT_Alloc(sizeof(SECItem));
+ if (item) {
+ sslSessionID *sid = ss->sec.ci.sid;
+ if (sid->version < SSL_LIBRARY_VERSION_3_0) {
+ item->len = SSL2_SESSIONID_BYTES;
+ item->data = (unsigned char *)PORT_Alloc(item->len);
+ PORT_Memcpy(item->data, sid->u.ssl2.sessionID, item->len);
+ } else {
+ item->len = sid->u.ssl3.sessionIDLength;
+ item->data = (unsigned char *)PORT_Alloc(item->len);
+ PORT_Memcpy(item->data, sid->u.ssl3.sessionID, item->len);
+ }
+ }
+ }
+
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
}
return item;
}
@@ -1562,14 +1565,14 @@ SSL_GetSessionID(PRFileDesc *fd)
SECStatus
SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle)
{
- sslSocket * ss;
+ sslSocket *ss;
ss = ssl_FindSocket(fd);
if (!ss)
- return SECFailure;
+ return SECFailure;
if (!dbHandle) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
ss->dbHandle = dbHandle;
return SECSuccess;
@@ -1600,73 +1603,72 @@ SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle)
*
* XXX This code only works on the initial handshake on a connection, XXX
* It does not work on a subsequent handshake (redo).
- */
+ */
SECStatus
-SSL_RestartHandshakeAfterCertReq(PRFileDesc * fd,
- CERTCertificate * cert,
- SECKEYPrivateKey * key,
- CERTCertificateList *certChain)
+SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd,
+ CERTCertificate *cert,
+ SECKEYPrivateKey *key,
+ CERTCertificateList *certChain)
{
- sslSocket * ss = ssl_FindSocket(fd);
- SECStatus ret;
+ sslSocket *ss = ssl_FindSocket(fd);
+ SECStatus ret;
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RestartHandshakeAfterCertReq",
- SSL_GETPID(), fd));
- if (cert) {
- CERT_DestroyCertificate(cert);
- }
- if (key) {
- SECKEY_DestroyPrivateKey(key);
- }
- if (certChain) {
- CERT_DestroyCertificateList(certChain);
- }
- return SECFailure;
- }
-
- ssl_Get1stHandshakeLock(ss); /************************************/
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RestartHandshakeAfterCertReq",
+ SSL_GETPID(), fd));
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+ if (key) {
+ SECKEY_DestroyPrivateKey(key);
+ }
+ if (certChain) {
+ CERT_DestroyCertificateList(certChain);
+ }
+ return SECFailure;
+ }
+
+ ssl_Get1stHandshakeLock(ss); /************************************/
if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
- ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain);
+ ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain);
} else {
- if (certChain != NULL) {
- CERT_DestroyCertificateList(certChain);
- }
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
- ret = SECFailure;
+ if (certChain != NULL) {
+ CERT_DestroyCertificateList(certChain);
+ }
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
+ ret = SECFailure;
}
- ssl_Release1stHandshakeLock(ss); /************************************/
+ ssl_Release1stHandshakeLock(ss); /************************************/
return ret;
}
SECStatus
-SSL_RestartHandshakeAfterChannelIDReq(PRFileDesc * fd,
- SECKEYPublicKey * channelIDPub,
- SECKEYPrivateKey *channelID)
+SSL_RestartHandshakeAfterChannelIDReq(PRFileDesc *fd,
+ SECKEYPublicKey *channelIDPub,
+ SECKEYPrivateKey *channelID)
{
- sslSocket * ss = ssl_FindSocket(fd);
- SECStatus ret;
+ sslSocket *ss = ssl_FindSocket(fd);
+ SECStatus ret;
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in"
- " SSL_RestartHandshakeAfterChannelIDReq",
- SSL_GETPID(), fd));
- goto loser;
+ SSL_DBG(("%d: SSL[%d]: bad socket in"
+ " SSL_RestartHandshakeAfterChannelIDReq",
+ SSL_GETPID(), fd));
+ goto loser;
}
-
ssl_Get1stHandshakeLock(ss);
if (ss->version < SSL_LIBRARY_VERSION_3_0) {
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
- ssl_Release1stHandshakeLock(ss);
- goto loser;
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
+ ssl_Release1stHandshakeLock(ss);
+ goto loser;
}
ret = ssl3_RestartHandshakeAfterChannelIDReq(ss, channelIDPub,
- channelID);
+ channelID);
ssl_Release1stHandshakeLock(ss);
return ret;
@@ -1681,7 +1683,7 @@ loser:
* this implementation exists to maintain link-time compatibility.
*/
int
-SSL_RestartHandshakeAfterServerCert(sslSocket * ss)
+SSL_RestartHandshakeAfterServerCert(sslSocket *ss)
{
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
return -1;
@@ -1695,21 +1697,21 @@ SSL_AuthCertificateComplete(PRFileDesc *fd, PRErrorCode error)
sslSocket *ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_AuthCertificateComplete",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_AuthCertificateComplete",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
ssl_Get1stHandshakeLock(ss);
if (!ss->ssl3.initialized) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
} else if (ss->version < SSL_LIBRARY_VERSION_3_0) {
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
- rv = SECFailure;
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
+ rv = SECFailure;
} else {
- rv = ssl3_AuthCertificateComplete(ss, error);
+ rv = ssl3_AuthCertificateComplete(ss, error);
}
ssl_Release1stHandshakeLock(ss);
@@ -1718,7 +1720,7 @@ SSL_AuthCertificateComplete(PRFileDesc *fd, PRErrorCode error)
}
/* For more info see ssl.h */
-SECStatus
+SECStatus
SSL_SNISocketConfigHook(PRFileDesc *fd, SSLSNISocketConfig func,
void *arg)
{
@@ -1726,9 +1728,9 @@ SSL_SNISocketConfigHook(PRFileDesc *fd, SSLSNISocketConfig func,
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SNISocketConfigHook",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SNISocketConfigHook",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
ss->sniSocketConfig = func;
diff --git a/chromium/net/third_party/nss/ssl/sslsnce.c b/chromium/net/third_party/nss/ssl/sslsnce.c
index 3856c13166f..e3f749e577b 100644
--- a/chromium/net/third_party/nss/ssl/sslsnce.c
+++ b/chromium/net/third_party/nss/ssl/sslsnce.c
@@ -1,23 +1,23 @@
-/* This file implements the SERVER Session ID cache.
+/* This file implements the SERVER Session ID cache.
* NOTE: The contents of this file are NOT used by the client.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-/* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
+/* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
* cache sids!
*
* About record locking among different server processes:
*
- * All processes that are part of the same conceptual server (serving on
- * the same address and port) MUST share a common SSL session cache.
+ * All processes that are part of the same conceptual server (serving on
+ * the same address and port) MUST share a common SSL session cache.
* This code makes the content of the shared cache accessible to all
* processes on the same "server". This code works on Unix and Win32 only.
*
* We use NSPR anonymous shared memory and move data to & from shared memory.
* We must do explicit locking of the records for all reads and writes.
- * The set of Cache entries are divided up into "sets" of 128 entries.
+ * The set of Cache entries are divided up into "sets" of 128 entries.
* Each set is protected by a lock. There may be one or more sets protected
* by each lock. That is, locks to sets are 1:N.
* There is one lock for the entire cert cache.
@@ -44,7 +44,7 @@
*/
#include "seccomon.h"
-#if defined(XP_UNIX) || defined(XP_WIN32) || defined (XP_OS2) || defined(XP_BEOS)
+#if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_OS2) || defined(XP_BEOS)
#include "cert.h"
#include "ssl.h"
@@ -78,7 +78,7 @@
#include "win32err.h"
#endif
-#endif
+#endif
#include <sys/types.h>
#define SET_ERROR_CODE /* reminder */
@@ -88,146 +88,146 @@
/*
** Format of a cache entry in the shared memory.
-*/
+*/
struct sidCacheEntryStr {
-/* 16 */ PRIPv6Addr addr; /* client's IP address */
-/* 4 */ PRUint32 creationTime;
-/* 4 */ PRUint32 lastAccessTime;
-/* 4 */ PRUint32 expirationTime;
-/* 2 */ PRUint16 version;
-/* 1 */ PRUint8 valid;
-/* 1 */ PRUint8 sessionIDLength;
-/* 32 */ PRUint8 sessionID[SSL3_SESSIONID_BYTES];
-/* 2 */ PRUint16 authAlgorithm;
-/* 2 */ PRUint16 authKeyBits;
-/* 2 */ PRUint16 keaType;
-/* 2 */ PRUint16 keaKeyBits;
-/* 72 - common header total */
+ /* 16 */ PRIPv6Addr addr; /* client's IP address */
+ /* 4 */ PRUint32 creationTime;
+ /* 4 */ PRUint32 lastAccessTime;
+ /* 4 */ PRUint32 expirationTime;
+ /* 2 */ PRUint16 version;
+ /* 1 */ PRUint8 valid;
+ /* 1 */ PRUint8 sessionIDLength;
+ /* 32 */ PRUint8 sessionID[SSL3_SESSIONID_BYTES];
+ /* 2 */ PRUint16 authAlgorithm;
+ /* 2 */ PRUint16 authKeyBits;
+ /* 2 */ PRUint16 keaType;
+ /* 2 */ PRUint16 keaKeyBits;
+ /* 72 - common header total */
union {
- struct {
-/* 64 */ PRUint8 masterKey[SSL_MAX_MASTER_KEY_BYTES];
-/* 32 */ PRUint8 cipherArg[SSL_MAX_CYPHER_ARG_BYTES];
-
-/* 1 */ PRUint8 cipherType;
-/* 1 */ PRUint8 masterKeyLen;
-/* 1 */ PRUint8 keyBits;
-/* 1 */ PRUint8 secretKeyBits;
-/* 1 */ PRUint8 cipherArgLen;
+ struct {
+ /* 64 */ PRUint8 masterKey[SSL_MAX_MASTER_KEY_BYTES];
+ /* 32 */ PRUint8 cipherArg[SSL_MAX_CYPHER_ARG_BYTES];
+
+ /* 1 */ PRUint8 cipherType;
+ /* 1 */ PRUint8 masterKeyLen;
+ /* 1 */ PRUint8 keyBits;
+ /* 1 */ PRUint8 secretKeyBits;
+ /* 1 */ PRUint8 cipherArgLen;
/*101 */} ssl2;
- struct {
-/* 2 */ ssl3CipherSuite cipherSuite;
-/* 2 */ PRUint16 compression; /* SSLCompressionMethod */
+struct {
+ /* 2 */ ssl3CipherSuite cipherSuite;
+ /* 2 */ PRUint16 compression; /* SSLCompressionMethod */
-/* 54 */ ssl3SidKeys keys; /* keys, wrapped as needed. */
+ /* 54 */ ssl3SidKeys keys; /* keys, wrapped as needed. */
-/* 4 */ PRUint32 masterWrapMech;
-/* 4 */ SSL3KEAType exchKeyType;
-/* 4 */ PRInt32 certIndex;
-/* 4 */ PRInt32 srvNameIndex;
-/* 32 */ PRUint8 srvNameHash[SHA256_LENGTH]; /* SHA256 name hash */
+ /* 4 */ PRUint32 masterWrapMech;
+ /* 4 */ SSL3KEAType exchKeyType;
+ /* 4 */ PRInt32 certIndex;
+ /* 4 */ PRInt32 srvNameIndex;
+ /* 32 */ PRUint8 srvNameHash[SHA256_LENGTH]; /* SHA256 name hash */
/*108 */} ssl3;
+
/* force sizeof(sidCacheEntry) to be a multiple of cache line size */
- struct {
-/*120 */ PRUint8 filler[120]; /* 72+120==192, a multiple of 16 */
- } forceSize;
+struct {
+ /*120 */ PRUint8 filler[120]; /* 72+120==192, a multiple of 16 */
+} forceSize;
} u;
};
typedef struct sidCacheEntryStr sidCacheEntry;
/* The length of this struct is supposed to be a power of 2, e.g. 4KB */
struct certCacheEntryStr {
- PRUint16 certLength; /* 2 */
- PRUint16 sessionIDLength; /* 2 */
- PRUint8 sessionID[SSL3_SESSIONID_BYTES]; /* 32 */
- PRUint8 cert[SSL_MAX_CACHED_CERT_LEN]; /* 4060 */
-}; /* total 4096 */
+ PRUint16 certLength; /* 2 */
+ PRUint16 sessionIDLength; /* 2 */
+ PRUint8 sessionID[SSL3_SESSIONID_BYTES]; /* 32 */
+ PRUint8 cert[SSL_MAX_CACHED_CERT_LEN]; /* 4060 */
+}; /* total 4096 */
typedef struct certCacheEntryStr certCacheEntry;
struct sidCacheLockStr {
- PRUint32 timeStamp;
- sslMutex mutex;
- sslPID pid;
+ PRUint32 timeStamp;
+ sslMutex mutex;
+ sslPID pid;
};
typedef struct sidCacheLockStr sidCacheLock;
struct sidCacheSetStr {
- PRIntn next;
+ PRIntn next;
};
typedef struct sidCacheSetStr sidCacheSet;
struct encKeyCacheEntryStr {
- PRUint8 bytes[512];
- PRInt32 length;
+ PRUint8 bytes[512];
+ PRInt32 length;
};
typedef struct encKeyCacheEntryStr encKeyCacheEntry;
-#define SSL_MAX_DNS_HOST_NAME 1024
+#define SSL_MAX_DNS_HOST_NAME 1024
struct srvNameCacheEntryStr {
- PRUint16 type; /* 2 */
- PRUint16 nameLen; /* 2 */
- PRUint8 name[SSL_MAX_DNS_HOST_NAME + 12]; /* 1034 */
- PRUint8 nameHash[SHA256_LENGTH]; /* 32 */
- /* 1072 */
+ PRUint16 type; /* 2 */
+ PRUint16 nameLen; /* 2 */
+ PRUint8 name[SSL_MAX_DNS_HOST_NAME + 12]; /* 1034 */
+ PRUint8 nameHash[SHA256_LENGTH]; /* 32 */
+ /* 1072 */
};
typedef struct srvNameCacheEntryStr srvNameCacheEntry;
-
struct cacheDescStr {
- PRUint32 cacheMemSize;
+ PRUint32 cacheMemSize;
- PRUint32 numSIDCacheLocks;
- PRUint32 numSIDCacheSets;
- PRUint32 numSIDCacheSetsPerLock;
+ PRUint32 numSIDCacheLocks;
+ PRUint32 numSIDCacheSets;
+ PRUint32 numSIDCacheSetsPerLock;
- PRUint32 numSIDCacheEntries;
- PRUint32 sidCacheSize;
+ PRUint32 numSIDCacheEntries;
+ PRUint32 sidCacheSize;
- PRUint32 numCertCacheEntries;
- PRUint32 certCacheSize;
+ PRUint32 numCertCacheEntries;
+ PRUint32 certCacheSize;
- PRUint32 numKeyCacheEntries;
- PRUint32 keyCacheSize;
+ PRUint32 numKeyCacheEntries;
+ PRUint32 keyCacheSize;
- PRUint32 numSrvNameCacheEntries;
- PRUint32 srvNameCacheSize;
+ PRUint32 numSrvNameCacheEntries;
+ PRUint32 srvNameCacheSize;
- PRUint32 ssl2Timeout;
- PRUint32 ssl3Timeout;
+ PRUint32 ssl2Timeout;
+ PRUint32 ssl3Timeout;
- PRUint32 numSIDCacheLocksInitialized;
+ PRUint32 numSIDCacheLocksInitialized;
/* These values are volatile, and are accessed through sharedCache-> */
- PRUint32 nextCertCacheEntry; /* certCacheLock protects */
- PRBool stopPolling;
- PRBool everInherited;
+ PRUint32 nextCertCacheEntry; /* certCacheLock protects */
+ PRBool stopPolling;
+ PRBool everInherited;
/* The private copies of these values are pointers into shared mem */
/* The copies of these values in shared memory are merely offsets */
- sidCacheLock * sidCacheLocks;
- sidCacheLock * keyCacheLock;
- sidCacheLock * certCacheLock;
- sidCacheLock * srvNameCacheLock;
- sidCacheSet * sidCacheSets;
- sidCacheEntry * sidCacheData;
- certCacheEntry * certCacheData;
- SSLWrappedSymWrappingKey * keyCacheData;
- PRUint8 * ticketKeyNameSuffix;
- encKeyCacheEntry * ticketEncKey;
- encKeyCacheEntry * ticketMacKey;
- PRUint32 * ticketKeysValid;
- srvNameCacheEntry * srvNameCacheData;
+ sidCacheLock *sidCacheLocks;
+ sidCacheLock *keyCacheLock;
+ sidCacheLock *certCacheLock;
+ sidCacheLock *srvNameCacheLock;
+ sidCacheSet *sidCacheSets;
+ sidCacheEntry *sidCacheData;
+ certCacheEntry *certCacheData;
+ SSLWrappedSymWrappingKey *keyCacheData;
+ PRUint8 *ticketKeyNameSuffix;
+ encKeyCacheEntry *ticketEncKey;
+ encKeyCacheEntry *ticketMacKey;
+ PRUint32 *ticketKeysValid;
+ srvNameCacheEntry *srvNameCacheData;
/* Only the private copies of these pointers are valid */
- char * cacheMem;
- struct cacheDescStr * sharedCache; /* shared copy of this struct */
- PRFileMap * cacheMemMap;
- PRThread * poller;
- PRUint32 mutexTimeout;
- PRBool shared;
+ char *cacheMem;
+ struct cacheDescStr *sharedCache; /* shared copy of this struct */
+ PRFileMap *cacheMemMap;
+ PRThread *poller;
+ PRUint32 mutexTimeout;
+ PRBool shared;
};
typedef struct cacheDescStr cacheDesc;
@@ -235,48 +235,45 @@ static cacheDesc globalCache;
static const char envVarName[] = { SSL_ENV_VAR_NAME };
-static PRBool isMultiProcess = PR_FALSE;
-
+static PRBool isMultiProcess = PR_FALSE;
-#define DEF_SID_CACHE_ENTRIES 10000
+#define DEF_SID_CACHE_ENTRIES 10000
#define DEF_CERT_CACHE_ENTRIES 250
#define MIN_CERT_CACHE_ENTRIES 125 /* the effective size in old releases. */
-#define DEF_KEY_CACHE_ENTRIES 250
-#define DEF_NAME_CACHE_ENTRIES 1000
+#define DEF_KEY_CACHE_ENTRIES 250
+#define DEF_NAME_CACHE_ENTRIES 1000
-#define SID_CACHE_ENTRIES_PER_SET 128
-#define SID_ALIGNMENT 16
+#define SID_CACHE_ENTRIES_PER_SET 128
+#define SID_ALIGNMENT 16
-#define DEF_SSL2_TIMEOUT 100 /* seconds */
-#define MAX_SSL2_TIMEOUT 100 /* seconds */
-#define MIN_SSL2_TIMEOUT 5 /* seconds */
+#define DEF_SSL2_TIMEOUT 100 /* seconds */
+#define MAX_SSL2_TIMEOUT 100 /* seconds */
+#define MIN_SSL2_TIMEOUT 5 /* seconds */
-#define DEF_SSL3_TIMEOUT 86400L /* 24 hours */
-#define MAX_SSL3_TIMEOUT 86400L /* 24 hours */
-#define MIN_SSL3_TIMEOUT 5 /* seconds */
+#define DEF_SSL3_TIMEOUT 86400L /* 24 hours */
+#define MAX_SSL3_TIMEOUT 86400L /* 24 hours */
+#define MIN_SSL3_TIMEOUT 5 /* seconds */
#if defined(AIX) || defined(LINUX) || defined(NETBSD) || defined(OPENBSD)
-#define MAX_SID_CACHE_LOCKS 8 /* two FDs per lock */
+#define MAX_SID_CACHE_LOCKS 8 /* two FDs per lock */
#elif defined(OSF1)
-#define MAX_SID_CACHE_LOCKS 16 /* one FD per lock */
+#define MAX_SID_CACHE_LOCKS 16 /* one FD per lock */
#else
#define MAX_SID_CACHE_LOCKS 256
#endif
-#define SID_HOWMANY(val, size) (((val) + ((size) - 1)) / (size))
-#define SID_ROUNDUP(val, size) ((size) * SID_HOWMANY((val), (size)))
-
+#define SID_HOWMANY(val, size) (((val) + ((size)-1)) / (size))
+#define SID_ROUNDUP(val, size) ((size)*SID_HOWMANY((val), (size)))
static sslPID myPid;
-static PRUint32 ssl_max_sid_cache_locks = MAX_SID_CACHE_LOCKS;
+static PRUint32 ssl_max_sid_cache_locks = MAX_SID_CACHE_LOCKS;
/* forward static function declarations */
-static PRUint32 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s,
+static PRUint32 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s,
unsigned nl);
static SECStatus LaunchLockPoller(cacheDesc *cache);
static SECStatus StopLockPoller(cacheDesc *cache);
-
struct inheritanceStr {
PRUint32 cacheMemSize;
PRUint32 fmStrLen;
@@ -296,29 +293,28 @@ typedef struct inheritanceStr inheritance;
#endif /* XP_UNIX || XP_BEOS */
-
/************************************************************************/
static PRUint32
LockSidCacheLock(sidCacheLock *lock, PRUint32 now)
{
- SECStatus rv = sslMutex_Lock(&lock->mutex);
+ SECStatus rv = sslMutex_Lock(&lock->mutex);
if (rv != SECSuccess)
- return 0;
+ return 0;
if (!now)
- now = ssl_Time();
+ now = ssl_Time();
lock->timeStamp = now;
- lock->pid = myPid;
+ lock->pid = myPid;
return now;
}
static SECStatus
UnlockSidCacheLock(sidCacheLock *lock)
{
- SECStatus rv;
+ SECStatus rv;
lock->pid = 0;
- rv = sslMutex_Unlock(&lock->mutex);
+ rv = sslMutex_Unlock(&lock->mutex);
return rv;
}
@@ -326,8 +322,8 @@ UnlockSidCacheLock(sidCacheLock *lock)
static PRUint32
LockSet(cacheDesc *cache, PRUint32 set, PRUint32 now)
{
- PRUint32 lockNum = set % cache->numSIDCacheLocks;
- sidCacheLock * lock = cache->sidCacheLocks + lockNum;
+ PRUint32 lockNum = set % cache->numSIDCacheLocks;
+ sidCacheLock *lock = cache->sidCacheLocks + lockNum;
return LockSidCacheLock(lock, now);
}
@@ -335,28 +331,27 @@ LockSet(cacheDesc *cache, PRUint32 set, PRUint32 now)
static SECStatus
UnlockSet(cacheDesc *cache, PRUint32 set)
{
- PRUint32 lockNum = set % cache->numSIDCacheLocks;
- sidCacheLock * lock = cache->sidCacheLocks + lockNum;
+ PRUint32 lockNum = set % cache->numSIDCacheLocks;
+ sidCacheLock *lock = cache->sidCacheLocks + lockNum;
return UnlockSidCacheLock(lock);
}
/************************************************************************/
-
/* Put a certificate in the cache. Update the cert index in the sce.
*/
static PRUint32
-CacheCert(cacheDesc * cache, CERTCertificate *cert, sidCacheEntry *sce)
+CacheCert(cacheDesc *cache, CERTCertificate *cert, sidCacheEntry *sce)
{
- PRUint32 now;
- certCacheEntry cce;
+ PRUint32 now;
+ certCacheEntry cce;
if ((cert->derCert.len > SSL_MAX_CACHED_CERT_LEN) ||
(cert->derCert.len <= 0) ||
- (cert->derCert.data == NULL)) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return 0;
+ (cert->derCert.data == NULL)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return 0;
}
cce.sessionIDLength = sce->sessionIDLength;
@@ -369,24 +364,23 @@ CacheCert(cacheDesc * cache, CERTCertificate *cert, sidCacheEntry *sce)
now = LockSidCacheLock(cache->certCacheLock, 0);
if (now) {
- /* Find where to place the next cert cache entry. */
- cacheDesc * sharedCache = cache->sharedCache;
- PRUint32 ndx = sharedCache->nextCertCacheEntry;
+ /* Find where to place the next cert cache entry. */
+ cacheDesc *sharedCache = cache->sharedCache;
+ PRUint32 ndx = sharedCache->nextCertCacheEntry;
- /* write the entry */
- cache->certCacheData[ndx] = cce;
+ /* write the entry */
+ cache->certCacheData[ndx] = cce;
- /* remember where we put it. */
- sce->u.ssl3.certIndex = ndx;
+ /* remember where we put it. */
+ sce->u.ssl3.certIndex = ndx;
- /* update the "next" cache entry index */
- sharedCache->nextCertCacheEntry =
- (ndx + 1) % cache->numCertCacheEntries;
+ /* update the "next" cache entry index */
+ sharedCache->nextCertCacheEntry =
+ (ndx + 1) % cache->numCertCacheEntries;
- UnlockSidCacheLock(cache->certCacheLock);
+ UnlockSidCacheLock(cache->certCacheLock);
}
return now;
-
}
/* Server configuration hash tables need to account the SECITEM.type
@@ -395,9 +389,9 @@ static PLHashNumber
Get32BitNameHash(const SECItem *name)
{
PLHashNumber rv = SECITEM_Hash(name);
-
+
PRUint8 *rvc = (PRUint8 *)&rv;
- rvc[ name->len % sizeof(rv) ] ^= name->type;
+ rvc[name->len % sizeof(rv)] ^= name->type;
return rv;
}
@@ -405,16 +399,16 @@ Get32BitNameHash(const SECItem *name)
/* Put a name in the cache. Update the cert index in the sce.
*/
static PRUint32
-CacheSrvName(cacheDesc * cache, SECItem *name, sidCacheEntry *sce)
+CacheSrvName(cacheDesc *cache, SECItem *name, sidCacheEntry *sce)
{
- PRUint32 now;
- PRUint32 ndx;
- srvNameCacheEntry snce;
+ PRUint32 now;
+ PRUint32 ndx;
+ srvNameCacheEntry snce;
if (!name || name->len <= 0 ||
name->len > SSL_MAX_DNS_HOST_NAME) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return 0;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return 0;
}
snce.type = name->type;
@@ -423,7 +417,7 @@ CacheSrvName(cacheDesc * cache, SECItem *name, sidCacheEntry *sce)
#ifdef NO_PKCS11_BYPASS
HASH_HashBuf(HASH_AlgSHA256, snce.nameHash, name->data, name->len);
#else
- SHA256_HashBuf(snce.nameHash, (unsigned char*)name->data,
+ SHA256_HashBuf(snce.nameHash, (unsigned char *)name->data,
name->len);
#endif
/* get index of the next name */
@@ -441,7 +435,7 @@ CacheSrvName(cacheDesc * cache, SECItem *name, sidCacheEntry *sce)
/* Copy hash into sid hash */
PORT_Memcpy(sce->u.ssl3.srvNameHash, snce.nameHash, SHA256_LENGTH);
}
- UnlockSidCacheLock(cache->srvNameCacheLock);
+ UnlockSidCacheLock(cache->srvNameCacheLock);
}
return now;
}
@@ -449,72 +443,73 @@ CacheSrvName(cacheDesc * cache, SECItem *name, sidCacheEntry *sce)
/*
** Convert local SID to shared memory one
*/
-static void
+static void
ConvertFromSID(sidCacheEntry *to, sslSessionID *from)
{
- to->valid = 1;
+ to->valid = 1;
to->version = from->version;
- to->addr = from->addr;
- to->creationTime = from->creationTime;
- to->lastAccessTime = from->lastAccessTime;
- to->expirationTime = from->expirationTime;
- to->authAlgorithm = from->authAlgorithm;
- to->authKeyBits = from->authKeyBits;
- to->keaType = from->keaType;
- to->keaKeyBits = from->keaKeyBits;
+ to->addr = from->addr;
+ to->creationTime = from->creationTime;
+ to->lastAccessTime = from->lastAccessTime;
+ to->expirationTime = from->expirationTime;
+ to->authAlgorithm = from->authAlgorithm;
+ to->authKeyBits = from->authKeyBits;
+ to->keaType = from->keaType;
+ to->keaKeyBits = from->keaKeyBits;
if (from->version < SSL_LIBRARY_VERSION_3_0) {
- if ((from->u.ssl2.masterKey.len > SSL_MAX_MASTER_KEY_BYTES) ||
- (from->u.ssl2.cipherArg.len > SSL_MAX_CYPHER_ARG_BYTES)) {
- SSL_DBG(("%d: SSL: masterKeyLen=%d cipherArgLen=%d",
- myPid, from->u.ssl2.masterKey.len,
- from->u.ssl2.cipherArg.len));
- to->valid = 0;
- return;
- }
-
- to->u.ssl2.cipherType = from->u.ssl2.cipherType;
- to->u.ssl2.masterKeyLen = from->u.ssl2.masterKey.len;
- to->u.ssl2.cipherArgLen = from->u.ssl2.cipherArg.len;
- to->u.ssl2.keyBits = from->u.ssl2.keyBits;
- to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
- to->sessionIDLength = SSL2_SESSIONID_BYTES;
- PORT_Memcpy(to->sessionID, from->u.ssl2.sessionID, SSL2_SESSIONID_BYTES);
- PORT_Memcpy(to->u.ssl2.masterKey, from->u.ssl2.masterKey.data,
- from->u.ssl2.masterKey.len);
- PORT_Memcpy(to->u.ssl2.cipherArg, from->u.ssl2.cipherArg.data,
- from->u.ssl2.cipherArg.len);
+ if ((from->u.ssl2.masterKey.len > SSL_MAX_MASTER_KEY_BYTES) ||
+ (from->u.ssl2.cipherArg.len > SSL_MAX_CYPHER_ARG_BYTES)) {
+ SSL_DBG(("%d: SSL: masterKeyLen=%d cipherArgLen=%d",
+ myPid, from->u.ssl2.masterKey.len,
+ from->u.ssl2.cipherArg.len));
+ to->valid = 0;
+ return;
+ }
+
+ to->u.ssl2.cipherType = from->u.ssl2.cipherType;
+ to->u.ssl2.masterKeyLen = from->u.ssl2.masterKey.len;
+ to->u.ssl2.cipherArgLen = from->u.ssl2.cipherArg.len;
+ to->u.ssl2.keyBits = from->u.ssl2.keyBits;
+ to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
+ to->sessionIDLength = SSL2_SESSIONID_BYTES;
+ PORT_Memcpy(to->sessionID, from->u.ssl2.sessionID, SSL2_SESSIONID_BYTES);
+ PORT_Memcpy(to->u.ssl2.masterKey, from->u.ssl2.masterKey.data,
+ from->u.ssl2.masterKey.len);
+ PORT_Memcpy(to->u.ssl2.cipherArg, from->u.ssl2.cipherArg.data,
+ from->u.ssl2.cipherArg.len);
#ifdef DEBUG
- PORT_Memset(to->u.ssl2.masterKey+from->u.ssl2.masterKey.len, 0,
- sizeof(to->u.ssl2.masterKey) - from->u.ssl2.masterKey.len);
- PORT_Memset(to->u.ssl2.cipherArg+from->u.ssl2.cipherArg.len, 0,
- sizeof(to->u.ssl2.cipherArg) - from->u.ssl2.cipherArg.len);
+ PORT_Memset(to->u.ssl2.masterKey + from->u.ssl2.masterKey.len, 0,
+ sizeof(to->u.ssl2.masterKey) - from->u.ssl2.masterKey.len);
+ PORT_Memset(to->u.ssl2.cipherArg + from->u.ssl2.cipherArg.len, 0,
+ sizeof(to->u.ssl2.cipherArg) - from->u.ssl2.cipherArg.len);
#endif
- SSL_TRC(8, ("%d: SSL: ConvertSID: masterKeyLen=%d cipherArgLen=%d "
- "time=%d addr=0x%08x%08x%08x%08x cipherType=%d", myPid,
- to->u.ssl2.masterKeyLen, to->u.ssl2.cipherArgLen,
- to->creationTime, to->addr.pr_s6_addr32[0],
- to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
- to->addr.pr_s6_addr32[3], to->u.ssl2.cipherType));
+ SSL_TRC(8, ("%d: SSL: ConvertSID: masterKeyLen=%d cipherArgLen=%d "
+ "time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
+ myPid,
+ to->u.ssl2.masterKeyLen, to->u.ssl2.cipherArgLen,
+ to->creationTime, to->addr.pr_s6_addr32[0],
+ to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
+ to->addr.pr_s6_addr32[3], to->u.ssl2.cipherType));
} else {
- /* This is an SSL v3 session */
-
- to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
- to->u.ssl3.compression = (PRUint16)from->u.ssl3.compression;
- to->u.ssl3.keys = from->u.ssl3.keys;
- to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
- to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
- to->sessionIDLength = from->u.ssl3.sessionIDLength;
- to->u.ssl3.certIndex = -1;
- to->u.ssl3.srvNameIndex = -1;
- PORT_Memcpy(to->sessionID, from->u.ssl3.sessionID,
- to->sessionIDLength);
-
- SSL_TRC(8, ("%d: SSL3: ConvertSID: time=%d addr=0x%08x%08x%08x%08x "
- "cipherSuite=%d",
- myPid, to->creationTime, to->addr.pr_s6_addr32[0],
- to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
- to->addr.pr_s6_addr32[3], to->u.ssl3.cipherSuite));
+ /* This is an SSL v3 session */
+
+ to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
+ to->u.ssl3.compression = (PRUint16)from->u.ssl3.compression;
+ to->u.ssl3.keys = from->u.ssl3.keys;
+ to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
+ to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
+ to->sessionIDLength = from->u.ssl3.sessionIDLength;
+ to->u.ssl3.certIndex = -1;
+ to->u.ssl3.srvNameIndex = -1;
+ PORT_Memcpy(to->sessionID, from->u.ssl3.sessionID,
+ to->sessionIDLength);
+
+ SSL_TRC(8, ("%d: SSL3: ConvertSID: time=%d addr=0x%08x%08x%08x%08x "
+ "cipherSuite=%d",
+ myPid, to->creationTime, to->addr.pr_s6_addr32[0],
+ to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
+ to->addr.pr_s6_addr32[3], to->u.ssl3.cipherSuite));
}
}
@@ -523,144 +518,142 @@ ConvertFromSID(sidCacheEntry *to, sslSessionID *from)
** This is only called from ServerSessionIDLookup().
*/
static sslSessionID *
-ConvertToSID(sidCacheEntry * from,
- certCacheEntry * pcce,
+ConvertToSID(sidCacheEntry *from,
+ certCacheEntry *pcce,
srvNameCacheEntry *psnce,
- CERTCertDBHandle * dbHandle)
+ CERTCertDBHandle *dbHandle)
{
sslSessionID *to;
PRUint16 version = from->version;
to = PORT_ZNew(sslSessionID);
if (!to) {
- return 0;
+ return 0;
}
if (version < SSL_LIBRARY_VERSION_3_0) {
- /* This is an SSL v2 session */
- to->u.ssl2.masterKey.data =
- (unsigned char*) PORT_Alloc(from->u.ssl2.masterKeyLen);
- if (!to->u.ssl2.masterKey.data) {
- goto loser;
- }
- if (from->u.ssl2.cipherArgLen) {
- to->u.ssl2.cipherArg.data =
- (unsigned char*)PORT_Alloc(from->u.ssl2.cipherArgLen);
- if (!to->u.ssl2.cipherArg.data) {
- goto loser;
- }
- PORT_Memcpy(to->u.ssl2.cipherArg.data, from->u.ssl2.cipherArg,
- from->u.ssl2.cipherArgLen);
- }
-
- to->u.ssl2.cipherType = from->u.ssl2.cipherType;
- to->u.ssl2.masterKey.len = from->u.ssl2.masterKeyLen;
- to->u.ssl2.cipherArg.len = from->u.ssl2.cipherArgLen;
- to->u.ssl2.keyBits = from->u.ssl2.keyBits;
- to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
-/* to->sessionIDLength = SSL2_SESSIONID_BYTES; */
- PORT_Memcpy(to->u.ssl2.sessionID, from->sessionID, SSL2_SESSIONID_BYTES);
- PORT_Memcpy(to->u.ssl2.masterKey.data, from->u.ssl2.masterKey,
- from->u.ssl2.masterKeyLen);
-
- SSL_TRC(8, ("%d: SSL: ConvertToSID: masterKeyLen=%d cipherArgLen=%d "
- "time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
- myPid, to->u.ssl2.masterKey.len,
- to->u.ssl2.cipherArg.len, to->creationTime,
- to->addr.pr_s6_addr32[0], to->addr.pr_s6_addr32[1],
- to->addr.pr_s6_addr32[2], to->addr.pr_s6_addr32[3],
- to->u.ssl2.cipherType));
+ /* This is an SSL v2 session */
+ to->u.ssl2.masterKey.data =
+ (unsigned char *)PORT_Alloc(from->u.ssl2.masterKeyLen);
+ if (!to->u.ssl2.masterKey.data) {
+ goto loser;
+ }
+ if (from->u.ssl2.cipherArgLen) {
+ to->u.ssl2.cipherArg.data =
+ (unsigned char *)PORT_Alloc(from->u.ssl2.cipherArgLen);
+ if (!to->u.ssl2.cipherArg.data) {
+ goto loser;
+ }
+ PORT_Memcpy(to->u.ssl2.cipherArg.data, from->u.ssl2.cipherArg,
+ from->u.ssl2.cipherArgLen);
+ }
+
+ to->u.ssl2.cipherType = from->u.ssl2.cipherType;
+ to->u.ssl2.masterKey.len = from->u.ssl2.masterKeyLen;
+ to->u.ssl2.cipherArg.len = from->u.ssl2.cipherArgLen;
+ to->u.ssl2.keyBits = from->u.ssl2.keyBits;
+ to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
+ /* to->sessionIDLength = SSL2_SESSIONID_BYTES; */
+ PORT_Memcpy(to->u.ssl2.sessionID, from->sessionID, SSL2_SESSIONID_BYTES);
+ PORT_Memcpy(to->u.ssl2.masterKey.data, from->u.ssl2.masterKey,
+ from->u.ssl2.masterKeyLen);
+
+ SSL_TRC(8, ("%d: SSL: ConvertToSID: masterKeyLen=%d cipherArgLen=%d "
+ "time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
+ myPid, to->u.ssl2.masterKey.len,
+ to->u.ssl2.cipherArg.len, to->creationTime,
+ to->addr.pr_s6_addr32[0], to->addr.pr_s6_addr32[1],
+ to->addr.pr_s6_addr32[2], to->addr.pr_s6_addr32[3],
+ to->u.ssl2.cipherType));
} else {
- /* This is an SSL v3 session */
-
- to->u.ssl3.sessionIDLength = from->sessionIDLength;
- to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
- to->u.ssl3.compression = (SSLCompressionMethod)from->u.ssl3.compression;
- to->u.ssl3.keys = from->u.ssl3.keys;
- to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
- to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
- if (from->u.ssl3.srvNameIndex != -1 && psnce) {
+ /* This is an SSL v3 session */
+
+ to->u.ssl3.sessionIDLength = from->sessionIDLength;
+ to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
+ to->u.ssl3.compression = (SSLCompressionMethod)from->u.ssl3.compression;
+ to->u.ssl3.keys = from->u.ssl3.keys;
+ to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
+ to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
+ if (from->u.ssl3.srvNameIndex != -1 && psnce) {
SECItem name;
SECStatus rv;
- name.type = psnce->type;
- name.len = psnce->nameLen;
- name.data = psnce->name;
+ name.type = psnce->type;
+ name.len = psnce->nameLen;
+ name.data = psnce->name;
rv = SECITEM_CopyItem(NULL, &to->u.ssl3.srvName, &name);
if (rv != SECSuccess) {
goto loser;
}
}
- PORT_Memcpy(to->u.ssl3.sessionID, from->sessionID, from->sessionIDLength);
+ PORT_Memcpy(to->u.ssl3.sessionID, from->sessionID, from->sessionIDLength);
- /* the portions of the SID that are only restored on the client
- * are set to invalid values on the server.
- */
- to->u.ssl3.clientWriteKey = NULL;
- to->u.ssl3.serverWriteKey = NULL;
+ /* the portions of the SID that are only restored on the client
+ * are set to invalid values on the server.
+ */
+ to->u.ssl3.clientWriteKey = NULL;
+ to->u.ssl3.serverWriteKey = NULL;
- to->urlSvrName = NULL;
+ to->urlSvrName = NULL;
- to->u.ssl3.masterModuleID = (SECMODModuleID)-1; /* invalid value */
- to->u.ssl3.masterSlotID = (CK_SLOT_ID)-1; /* invalid value */
- to->u.ssl3.masterWrapIndex = 0;
- to->u.ssl3.masterWrapSeries = 0;
- to->u.ssl3.masterValid = PR_FALSE;
+ to->u.ssl3.masterModuleID = (SECMODModuleID)-1; /* invalid value */
+ to->u.ssl3.masterSlotID = (CK_SLOT_ID)-1; /* invalid value */
+ to->u.ssl3.masterWrapIndex = 0;
+ to->u.ssl3.masterWrapSeries = 0;
+ to->u.ssl3.masterValid = PR_FALSE;
- to->u.ssl3.clAuthModuleID = (SECMODModuleID)-1; /* invalid value */
- to->u.ssl3.clAuthSlotID = (CK_SLOT_ID)-1; /* invalid value */
- to->u.ssl3.clAuthSeries = 0;
- to->u.ssl3.clAuthValid = PR_FALSE;
+ to->u.ssl3.clAuthModuleID = (SECMODModuleID)-1; /* invalid value */
+ to->u.ssl3.clAuthSlotID = (CK_SLOT_ID)-1; /* invalid value */
+ to->u.ssl3.clAuthSeries = 0;
+ to->u.ssl3.clAuthValid = PR_FALSE;
- if (from->u.ssl3.certIndex != -1 && pcce) {
- SECItem derCert;
+ if (from->u.ssl3.certIndex != -1 && pcce) {
+ SECItem derCert;
- derCert.len = pcce->certLength;
- derCert.data = pcce->cert;
+ derCert.len = pcce->certLength;
+ derCert.data = pcce->cert;
- to->peerCert = CERT_NewTempCertificate(dbHandle, &derCert, NULL,
- PR_FALSE, PR_TRUE);
- if (to->peerCert == NULL)
- goto loser;
- }
+ to->peerCert = CERT_NewTempCertificate(dbHandle, &derCert, NULL,
+ PR_FALSE, PR_TRUE);
+ if (to->peerCert == NULL)
+ goto loser;
+ }
}
- to->version = from->version;
- to->creationTime = from->creationTime;
- to->lastAccessTime = from->lastAccessTime;
- to->expirationTime = from->expirationTime;
- to->cached = in_server_cache;
- to->addr = from->addr;
- to->references = 1;
- to->authAlgorithm = from->authAlgorithm;
- to->authKeyBits = from->authKeyBits;
- to->keaType = from->keaType;
- to->keaKeyBits = from->keaKeyBits;
+ to->version = from->version;
+ to->creationTime = from->creationTime;
+ to->lastAccessTime = from->lastAccessTime;
+ to->expirationTime = from->expirationTime;
+ to->cached = in_server_cache;
+ to->addr = from->addr;
+ to->references = 1;
+ to->authAlgorithm = from->authAlgorithm;
+ to->authKeyBits = from->authKeyBits;
+ to->keaType = from->keaType;
+ to->keaKeyBits = from->keaKeyBits;
return to;
- loser:
+loser:
if (to) {
- if (version < SSL_LIBRARY_VERSION_3_0) {
- if (to->u.ssl2.masterKey.data)
- PORT_Free(to->u.ssl2.masterKey.data);
- if (to->u.ssl2.cipherArg.data)
- PORT_Free(to->u.ssl2.cipherArg.data);
- } else {
+ if (version < SSL_LIBRARY_VERSION_3_0) {
+ if (to->u.ssl2.masterKey.data)
+ PORT_Free(to->u.ssl2.masterKey.data);
+ if (to->u.ssl2.cipherArg.data)
+ PORT_Free(to->u.ssl2.cipherArg.data);
+ } else {
SECITEM_FreeItem(&to->u.ssl3.srvName, PR_FALSE);
}
- PORT_Free(to);
+ PORT_Free(to);
}
return NULL;
}
-
-
/*
** Perform some mumbo jumbo on the ip-address and the session-id value to
** compute a hash value.
*/
-static PRUint32
+static PRUint32
SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s, unsigned nl)
{
PRUint32 rv;
@@ -668,18 +661,16 @@ SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s, unsigned nl)
memset(x, 0, sizeof x);
if (nl > sizeof x)
- nl = sizeof x;
+ nl = sizeof x;
memcpy(x, s, nl);
rv = (addr->pr_s6_addr32[0] ^ addr->pr_s6_addr32[1] ^
- addr->pr_s6_addr32[2] ^ addr->pr_s6_addr32[3] ^
- x[0] ^ x[1] ^ x[2] ^ x[3] ^ x[4] ^ x[5] ^ x[6] ^ x[7])
- % cache->numSIDCacheSets;
+ addr->pr_s6_addr32[2] ^ addr->pr_s6_addr32[3] ^
+ x[0] ^ x[1] ^ x[2] ^ x[3] ^ x[4] ^ x[5] ^ x[6] ^ x[7]) %
+ cache->numSIDCacheSets;
return rv;
}
-
-
/*
** Look something up in the cache. This will invalidate old entries
** in the process. Caller has locked the cache set!
@@ -688,45 +679,45 @@ SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s, unsigned nl)
static sidCacheEntry *
FindSID(cacheDesc *cache, PRUint32 setNum, PRUint32 now,
const PRIPv6Addr *addr, unsigned char *sessionID,
- unsigned sessionIDLength)
+ unsigned sessionIDLength)
{
- PRUint32 ndx = cache->sidCacheSets[setNum].next;
- int i;
+ PRUint32 ndx = cache->sidCacheSets[setNum].next;
+ int i;
- sidCacheEntry * set = cache->sidCacheData +
- (setNum * SID_CACHE_ENTRIES_PER_SET);
+ sidCacheEntry *set = cache->sidCacheData +
+ (setNum * SID_CACHE_ENTRIES_PER_SET);
for (i = SID_CACHE_ENTRIES_PER_SET; i > 0; --i) {
- sidCacheEntry * sce;
-
- ndx = (ndx - 1) % SID_CACHE_ENTRIES_PER_SET;
- sce = set + ndx;
-
- if (!sce->valid)
- continue;
-
- if (now > sce->expirationTime) {
- /* SessionID has timed out. Invalidate the entry. */
- SSL_TRC(7, ("%d: timed out sid entry addr=%08x%08x%08x%08x now=%x "
- "time+=%x",
- myPid, sce->addr.pr_s6_addr32[0],
- sce->addr.pr_s6_addr32[1], sce->addr.pr_s6_addr32[2],
- sce->addr.pr_s6_addr32[3], now,
- sce->expirationTime ));
- sce->valid = 0;
- continue;
- }
-
- /*
- ** Next, examine specific session-id/addr data to see if the cache
- ** entry matches our addr+session-id value
- */
- if (sessionIDLength == sce->sessionIDLength &&
- !memcmp(&sce->addr, addr, sizeof(PRIPv6Addr)) &&
- !memcmp(sce->sessionID, sessionID, sessionIDLength)) {
- /* Found it */
- return sce;
- }
+ sidCacheEntry *sce;
+
+ ndx = (ndx - 1) % SID_CACHE_ENTRIES_PER_SET;
+ sce = set + ndx;
+
+ if (!sce->valid)
+ continue;
+
+ if (now > sce->expirationTime) {
+ /* SessionID has timed out. Invalidate the entry. */
+ SSL_TRC(7, ("%d: timed out sid entry addr=%08x%08x%08x%08x now=%x "
+ "time+=%x",
+ myPid, sce->addr.pr_s6_addr32[0],
+ sce->addr.pr_s6_addr32[1], sce->addr.pr_s6_addr32[2],
+ sce->addr.pr_s6_addr32[3], now,
+ sce->expirationTime));
+ sce->valid = 0;
+ continue;
+ }
+
+ /*
+ ** Next, examine specific session-id/addr data to see if the cache
+ ** entry matches our addr+session-id value
+ */
+ if (sessionIDLength == sce->sessionIDLength &&
+ !memcmp(&sce->addr, addr, sizeof(PRIPv6Addr)) &&
+ !memcmp(sce->sessionID, sessionID, sessionIDLength)) {
+ /* Found it */
+ return sce;
+ }
}
PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND);
@@ -736,49 +727,49 @@ FindSID(cacheDesc *cache, PRUint32 setNum, PRUint32 now,
/************************************************************************/
/* This is the primary function for finding entries in the server's sid cache.
- * Although it is static, this function is called via the global function
+ * Although it is static, this function is called via the global function
* pointer ssl_sid_lookup.
*/
static sslSessionID *
ServerSessionIDLookup(const PRIPv6Addr *addr,
- unsigned char *sessionID,
- unsigned int sessionIDLength,
- CERTCertDBHandle * dbHandle)
+ unsigned char *sessionID,
+ unsigned int sessionIDLength,
+ CERTCertDBHandle *dbHandle)
{
- sslSessionID * sid = 0;
- sidCacheEntry * psce;
- certCacheEntry *pcce = 0;
+ sslSessionID *sid = 0;
+ sidCacheEntry *psce;
+ certCacheEntry *pcce = 0;
srvNameCacheEntry *psnce = 0;
- cacheDesc * cache = &globalCache;
- PRUint32 now;
- PRUint32 set;
- PRInt32 cndx;
- sidCacheEntry sce;
- certCacheEntry cce;
+ cacheDesc *cache = &globalCache;
+ PRUint32 now;
+ PRUint32 set;
+ PRInt32 cndx;
+ sidCacheEntry sce;
+ certCacheEntry cce;
srvNameCacheEntry snce;
set = SIDindex(cache, addr, sessionID, sessionIDLength);
now = LockSet(cache, set, 0);
if (!now)
- return NULL;
+ return NULL;
psce = FindSID(cache, set, now, addr, sessionID, sessionIDLength);
if (psce) {
- if (psce->version >= SSL_LIBRARY_VERSION_3_0) {
- if ((cndx = psce->u.ssl3.certIndex) != -1) {
-
+ if (psce->version >= SSL_LIBRARY_VERSION_3_0) {
+ if ((cndx = psce->u.ssl3.certIndex) != -1) {
+
PRUint32 gotLock = LockSidCacheLock(cache->certCacheLock, now);
if (gotLock) {
pcce = &cache->certCacheData[cndx];
-
+
/* See if the cert's session ID matches the sce cache. */
if ((pcce->sessionIDLength == psce->sessionIDLength) &&
- !PORT_Memcmp(pcce->sessionID, psce->sessionID,
+ !PORT_Memcmp(pcce->sessionID, psce->sessionID,
pcce->sessionIDLength)) {
cce = *pcce;
} else {
- /* The cert doesen't match the SID cache entry,
- ** so invalidate the SID cache entry.
+ /* The cert doesen't match the SID cache entry,
+ ** so invalidate the SID cache entry.
*/
psce->valid = 0;
psce = 0;
@@ -799,13 +790,13 @@ ServerSessionIDLookup(const PRIPv6Addr *addr,
now);
if (gotLock) {
psnce = &cache->srvNameCacheData[cndx];
-
- if (!PORT_Memcmp(psnce->nameHash, psce->u.ssl3.srvNameHash,
+
+ if (!PORT_Memcmp(psnce->nameHash, psce->u.ssl3.srvNameHash,
SHA256_LENGTH)) {
snce = *psnce;
} else {
- /* The name doesen't match the SID cache entry,
- ** so invalidate the SID cache entry.
+ /* The name doesen't match the SID cache entry,
+ ** so invalidate the SID cache entry.
*/
psce->valid = 0;
psce = 0;
@@ -820,80 +811,80 @@ ServerSessionIDLookup(const PRIPv6Addr *addr,
psce = 0;
psnce = 0;
}
-
}
}
- if (psce) {
- psce->lastAccessTime = now;
- sce = *psce; /* grab a copy while holding the lock */
- }
+ if (psce) {
+ psce->lastAccessTime = now;
+ sce = *psce; /* grab a copy while holding the lock */
+ }
}
UnlockSet(cache, set);
if (psce) {
- /* sce conains a copy of the cache entry.
- ** Convert shared memory format to local format
- */
- sid = ConvertToSID(&sce, pcce ? &cce : 0, psnce ? &snce : 0, dbHandle);
+ /* sce conains a copy of the cache entry.
+ ** Convert shared memory format to local format
+ */
+ sid = ConvertToSID(&sce, pcce ? &cce : 0, psnce ? &snce : 0, dbHandle);
}
return sid;
}
/*
-** Place a sid into the cache, if it isn't already there.
+** Place a sid into the cache, if it isn't already there.
*/
-static void
+static void
ServerSessionIDCache(sslSessionID *sid)
{
sidCacheEntry sce;
- PRUint32 now = 0;
- PRUint16 version = sid->version;
- cacheDesc * cache = &globalCache;
+ PRUint32 now = 0;
+ PRUint16 version = sid->version;
+ cacheDesc *cache = &globalCache;
if ((version >= SSL_LIBRARY_VERSION_3_0) &&
- (sid->u.ssl3.sessionIDLength == 0)) {
- return;
+ (sid->u.ssl3.sessionIDLength == 0)) {
+ return;
}
if (sid->cached == never_cached || sid->cached == invalid_cache) {
- PRUint32 set;
-
- PORT_Assert(sid->creationTime != 0);
- if (!sid->creationTime)
- sid->lastAccessTime = sid->creationTime = ssl_Time();
- if (version < SSL_LIBRARY_VERSION_3_0) {
- /* override caller's expiration time, which uses client timeout
- * duration, not server timeout duration.
- */
- sid->expirationTime = sid->creationTime + cache->ssl2Timeout;
- SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
- "cipher=%d", myPid, sid->cached,
- sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
- sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
- sid->creationTime, sid->u.ssl2.cipherType));
- PRINT_BUF(8, (0, "sessionID:", sid->u.ssl2.sessionID,
- SSL2_SESSIONID_BYTES));
- PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
- sid->u.ssl2.masterKey.len));
- PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
- sid->u.ssl2.cipherArg.len));
-
- } else {
- /* override caller's expiration time, which uses client timeout
- * duration, not server timeout duration.
- */
- sid->expirationTime = sid->creationTime + cache->ssl3Timeout;
- SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
- "cipherSuite=%d", myPid, sid->cached,
- sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
- sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
- sid->creationTime, sid->u.ssl3.cipherSuite));
- PRINT_BUF(8, (0, "sessionID:", sid->u.ssl3.sessionID,
- sid->u.ssl3.sessionIDLength));
- }
-
- ConvertFromSID(&sce, sid);
-
- if (version >= SSL_LIBRARY_VERSION_3_0) {
+ PRUint32 set;
+
+ PORT_Assert(sid->creationTime != 0);
+ if (!sid->creationTime)
+ sid->lastAccessTime = sid->creationTime = ssl_Time();
+ if (version < SSL_LIBRARY_VERSION_3_0) {
+ /* override caller's expiration time, which uses client timeout
+ * duration, not server timeout duration.
+ */
+ sid->expirationTime = sid->creationTime + cache->ssl2Timeout;
+ SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
+ "cipher=%d",
+ myPid, sid->cached,
+ sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
+ sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
+ sid->creationTime, sid->u.ssl2.cipherType));
+ PRINT_BUF(8, (0, "sessionID:", sid->u.ssl2.sessionID,
+ SSL2_SESSIONID_BYTES));
+ PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
+ sid->u.ssl2.masterKey.len));
+ PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
+ sid->u.ssl2.cipherArg.len));
+ } else {
+ /* override caller's expiration time, which uses client timeout
+ * duration, not server timeout duration.
+ */
+ sid->expirationTime = sid->creationTime + cache->ssl3Timeout;
+ SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
+ "cipherSuite=%d",
+ myPid, sid->cached,
+ sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
+ sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
+ sid->creationTime, sid->u.ssl3.cipherSuite));
+ PRINT_BUF(8, (0, "sessionID:", sid->u.ssl3.sessionID,
+ sid->u.ssl3.sessionIDLength));
+ }
+
+ ConvertFromSID(&sce, sid);
+
+ if (version >= SSL_LIBRARY_VERSION_3_0) {
SECItem *name = &sid->u.ssl3.srvName;
if (name->len && name->data) {
now = CacheSrvName(cache, name, &sce);
@@ -901,80 +892,82 @@ ServerSessionIDCache(sslSessionID *sid)
if (sid->peerCert != NULL) {
now = CacheCert(cache, sid->peerCert, &sce);
}
- }
+ }
- set = SIDindex(cache, &sce.addr, sce.sessionID, sce.sessionIDLength);
- now = LockSet(cache, set, now);
- if (now) {
- PRUint32 next = cache->sidCacheSets[set].next;
- PRUint32 ndx = set * SID_CACHE_ENTRIES_PER_SET + next;
+ set = SIDindex(cache, &sce.addr, sce.sessionID, sce.sessionIDLength);
+ now = LockSet(cache, set, now);
+ if (now) {
+ PRUint32 next = cache->sidCacheSets[set].next;
+ PRUint32 ndx = set * SID_CACHE_ENTRIES_PER_SET + next;
- /* Write out new cache entry */
- cache->sidCacheData[ndx] = sce;
+ /* Write out new cache entry */
+ cache->sidCacheData[ndx] = sce;
- cache->sidCacheSets[set].next =
- (next + 1) % SID_CACHE_ENTRIES_PER_SET;
+ cache->sidCacheSets[set].next =
+ (next + 1) % SID_CACHE_ENTRIES_PER_SET;
- UnlockSet(cache, set);
- sid->cached = in_server_cache;
- }
+ UnlockSet(cache, set);
+ sid->cached = in_server_cache;
+ }
}
}
/*
** Although this is static, it is called from ssl via global function pointer
-** ssl_sid_uncache. This invalidates the referenced cache entry.
+** ssl_sid_uncache. This invalidates the referenced cache entry.
*/
-static void
+static void
ServerSessionIDUncache(sslSessionID *sid)
{
- cacheDesc * cache = &globalCache;
- PRUint8 * sessionID;
- unsigned int sessionIDLength;
- PRErrorCode err;
- PRUint32 set;
- PRUint32 now;
+ cacheDesc *cache = &globalCache;
+ PRUint8 *sessionID;
+ unsigned int sessionIDLength;
+ PRErrorCode err;
+ PRUint32 set;
+ PRUint32 now;
sidCacheEntry *psce;
- if (sid == NULL)
- return;
-
- /* Uncaching a SID should never change the error code.
+ if (sid == NULL)
+ return;
+
+ /* Uncaching a SID should never change the error code.
** So save it here and restore it before exiting.
*/
err = PR_GetError();
if (sid->version < SSL_LIBRARY_VERSION_3_0) {
- sessionID = sid->u.ssl2.sessionID;
- sessionIDLength = SSL2_SESSIONID_BYTES;
- SSL_TRC(8, ("%d: SSL: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
- "cipher=%d", myPid, sid->cached,
- sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
- sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
- sid->creationTime, sid->u.ssl2.cipherType));
- PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
- PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
- sid->u.ssl2.masterKey.len));
- PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
- sid->u.ssl2.cipherArg.len));
+ sessionID = sid->u.ssl2.sessionID;
+ sessionIDLength = SSL2_SESSIONID_BYTES;
+ SSL_TRC(8, ("%d: SSL: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
+ "cipher=%d",
+ myPid, sid->cached,
+ sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
+ sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
+ sid->creationTime, sid->u.ssl2.cipherType));
+ PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
+ PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
+ sid->u.ssl2.masterKey.len));
+ PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
+ sid->u.ssl2.cipherArg.len));
} else {
- sessionID = sid->u.ssl3.sessionID;
- sessionIDLength = sid->u.ssl3.sessionIDLength;
- SSL_TRC(8, ("%d: SSL3: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
- "cipherSuite=%d", myPid, sid->cached,
- sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
- sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
- sid->creationTime, sid->u.ssl3.cipherSuite));
- PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
+ sessionID = sid->u.ssl3.sessionID;
+ sessionIDLength = sid->u.ssl3.sessionIDLength;
+ SSL_TRC(8, ("%d: SSL3: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
+ "cipherSuite=%d",
+ myPid, sid->cached,
+ sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
+ sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
+ sid->creationTime, sid->u.ssl3.cipherSuite));
+ PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
}
set = SIDindex(cache, &sid->addr, sessionID, sessionIDLength);
now = LockSet(cache, set, 0);
if (now) {
- psce = FindSID(cache, set, now, &sid->addr, sessionID, sessionIDLength);
- if (psce) {
- psce->valid = 0;
- }
- UnlockSet(cache, set);
+ psce = FindSID(cache, set, now, &sid->addr, sessionID, sessionIDLength);
+ if (psce) {
+ psce->valid = 0;
+ }
+ UnlockSet(cache, set);
}
sid->cached = invalid_cache;
PORT_SetError(err);
@@ -985,7 +978,8 @@ ServerSessionIDUncache(sslSessionID *sid)
#define INCL_DOSPROCESS
#include <os2.h>
-long gettid(void)
+long
+gettid(void)
{
PTIB ptib;
PPIB ppib;
@@ -1000,59 +994,59 @@ CloseCache(cacheDesc *cache)
int locks_initialized = cache->numSIDCacheLocksInitialized;
if (cache->cacheMem) {
- if (cache->sharedCache) {
- sidCacheLock *pLock = cache->sidCacheLocks;
- for (; locks_initialized > 0; --locks_initialized, ++pLock ) {
- /* If everInherited is true, this shared cache was (and may
- ** still be) in use by multiple processes. We do not wish to
- ** destroy the mutexes while they are still in use, but we do
- ** want to free mutex resources associated with this process.
- */
- sslMutex_Destroy(&pLock->mutex,
- cache->sharedCache->everInherited);
- }
- }
- if (cache->shared) {
- PR_MemUnmap(cache->cacheMem, cache->cacheMemSize);
- } else {
- PORT_Free(cache->cacheMem);
- }
- cache->cacheMem = NULL;
+ if (cache->sharedCache) {
+ sidCacheLock *pLock = cache->sidCacheLocks;
+ for (; locks_initialized > 0; --locks_initialized, ++pLock) {
+ /* If everInherited is true, this shared cache was (and may
+ ** still be) in use by multiple processes. We do not wish to
+ ** destroy the mutexes while they are still in use, but we do
+ ** want to free mutex resources associated with this process.
+ */
+ sslMutex_Destroy(&pLock->mutex,
+ cache->sharedCache->everInherited);
+ }
+ }
+ if (cache->shared) {
+ PR_MemUnmap(cache->cacheMem, cache->cacheMemSize);
+ } else {
+ PORT_Free(cache->cacheMem);
+ }
+ cache->cacheMem = NULL;
}
if (cache->cacheMemMap) {
- PR_CloseFileMap(cache->cacheMemMap);
- cache->cacheMemMap = NULL;
+ PR_CloseFileMap(cache->cacheMemMap);
+ cache->cacheMemMap = NULL;
}
memset(cache, 0, sizeof *cache);
}
static SECStatus
InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries,
- int maxSrvNameCacheEntries, PRUint32 ssl2_timeout,
+ int maxSrvNameCacheEntries, PRUint32 ssl2_timeout,
PRUint32 ssl3_timeout, const char *directory, PRBool shared)
{
- ptrdiff_t ptr;
+ ptrdiff_t ptr;
sidCacheLock *pLock;
- char * cacheMem;
- PRFileMap * cacheMemMap;
- char * cfn = NULL; /* cache file name */
- int locks_initialized = 0;
- int locks_to_initialize = 0;
- PRUint32 init_time;
-
- if ( (!cache) || (maxCacheEntries < 0) || (!directory) ) {
+ char *cacheMem;
+ PRFileMap *cacheMemMap;
+ char *cfn = NULL; /* cache file name */
+ int locks_initialized = 0;
+ int locks_to_initialize = 0;
+ PRUint32 init_time;
+
+ if ((!cache) || (maxCacheEntries < 0) || (!directory)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (cache->cacheMem) {
- /* Already done */
- return SECSuccess;
+ /* Already done */
+ return SECSuccess;
}
/* make sure loser can clean up properly */
cache->shared = shared;
- cache->cacheMem = cacheMem = NULL;
+ cache->cacheMem = cacheMem = NULL;
cache->cacheMemMap = cacheMemMap = NULL;
cache->sharedCache = (cacheDesc *)0;
@@ -1063,71 +1057,71 @@ InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries,
cache->poller = NULL;
cache->mutexTimeout = 0;
- cache->numSIDCacheEntries = maxCacheEntries ? maxCacheEntries
+ cache->numSIDCacheEntries = maxCacheEntries ? maxCacheEntries
: DEF_SID_CACHE_ENTRIES;
- cache->numSIDCacheSets =
- SID_HOWMANY(cache->numSIDCacheEntries, SID_CACHE_ENTRIES_PER_SET);
+ cache->numSIDCacheSets =
+ SID_HOWMANY(cache->numSIDCacheEntries, SID_CACHE_ENTRIES_PER_SET);
- cache->numSIDCacheEntries =
- cache->numSIDCacheSets * SID_CACHE_ENTRIES_PER_SET;
+ cache->numSIDCacheEntries =
+ cache->numSIDCacheSets * SID_CACHE_ENTRIES_PER_SET;
- cache->numSIDCacheLocks =
- PR_MIN(cache->numSIDCacheSets, ssl_max_sid_cache_locks);
+ cache->numSIDCacheLocks =
+ PR_MIN(cache->numSIDCacheSets, ssl_max_sid_cache_locks);
- cache->numSIDCacheSetsPerLock =
- SID_HOWMANY(cache->numSIDCacheSets, cache->numSIDCacheLocks);
+ cache->numSIDCacheSetsPerLock =
+ SID_HOWMANY(cache->numSIDCacheSets, cache->numSIDCacheLocks);
- cache->numCertCacheEntries = (maxCertCacheEntries > 0) ?
- maxCertCacheEntries : 0;
- cache->numSrvNameCacheEntries = (maxSrvNameCacheEntries >= 0) ?
- maxSrvNameCacheEntries : DEF_NAME_CACHE_ENTRIES;
+ cache->numCertCacheEntries = (maxCertCacheEntries > 0) ? maxCertCacheEntries
+ : 0;
+ cache->numSrvNameCacheEntries = (maxSrvNameCacheEntries >= 0) ? maxSrvNameCacheEntries
+ : DEF_NAME_CACHE_ENTRIES;
/* compute size of shared memory, and offsets of all pointers */
ptr = 0;
- cache->cacheMem = (char *)ptr;
+ cache->cacheMem = (char *)ptr;
ptr += SID_ROUNDUP(sizeof(cacheDesc), SID_ALIGNMENT);
cache->sidCacheLocks = (sidCacheLock *)ptr;
- cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
- cache->certCacheLock = cache->keyCacheLock + 1;
- cache->srvNameCacheLock = cache->certCacheLock + 1;
+ cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
+ cache->certCacheLock = cache->keyCacheLock + 1;
+ cache->srvNameCacheLock = cache->certCacheLock + 1;
ptr = (ptrdiff_t)(cache->srvNameCacheLock + 1);
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
- cache->sidCacheSets = (sidCacheSet *)ptr;
+ cache->sidCacheSets = (sidCacheSet *)ptr;
ptr = (ptrdiff_t)(cache->sidCacheSets + cache->numSIDCacheSets);
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
- cache->sidCacheData = (sidCacheEntry *)ptr;
+ cache->sidCacheData = (sidCacheEntry *)ptr;
ptr = (ptrdiff_t)(cache->sidCacheData + cache->numSIDCacheEntries);
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
cache->certCacheData = (certCacheEntry *)ptr;
- cache->sidCacheSize =
- (char *)cache->certCacheData - (char *)cache->sidCacheData;
+ cache->sidCacheSize =
+ (char *)cache->certCacheData - (char *)cache->sidCacheData;
if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES) {
/* This is really a poor way to computer this! */
cache->numCertCacheEntries = cache->sidCacheSize / sizeof(certCacheEntry);
if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES)
- cache->numCertCacheEntries = MIN_CERT_CACHE_ENTRIES;
+ cache->numCertCacheEntries = MIN_CERT_CACHE_ENTRIES;
}
ptr = (ptrdiff_t)(cache->certCacheData + cache->numCertCacheEntries);
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
- cache->keyCacheData = (SSLWrappedSymWrappingKey *)ptr;
- cache->certCacheSize =
- (char *)cache->keyCacheData - (char *)cache->certCacheData;
+ cache->keyCacheData = (SSLWrappedSymWrappingKey *)ptr;
+ cache->certCacheSize =
+ (char *)cache->keyCacheData - (char *)cache->certCacheData;
cache->numKeyCacheEntries = kt_kea_size * SSL_NUM_WRAP_MECHS;
ptr = (ptrdiff_t)(cache->keyCacheData + cache->numKeyCacheEntries);
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
- cache->keyCacheSize = (char *)ptr - (char *)cache->keyCacheData;
+ cache->keyCacheSize = (char *)ptr - (char *)cache->keyCacheData;
cache->ticketKeyNameSuffix = (PRUint8 *)ptr;
ptr = (ptrdiff_t)(cache->ticketKeyNameSuffix +
- SESS_TICKET_KEY_VAR_NAME_LEN);
+ SESS_TICKET_KEY_VAR_NAME_LEN);
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
cache->ticketEncKey = (encKeyCacheEntry *)ptr;
@@ -1150,66 +1144,66 @@ InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries,
cache->cacheMemSize = ptr;
- if (ssl2_timeout) {
- if (ssl2_timeout > MAX_SSL2_TIMEOUT) {
- ssl2_timeout = MAX_SSL2_TIMEOUT;
- }
- if (ssl2_timeout < MIN_SSL2_TIMEOUT) {
- ssl2_timeout = MIN_SSL2_TIMEOUT;
- }
- cache->ssl2Timeout = ssl2_timeout;
+ if (ssl2_timeout) {
+ if (ssl2_timeout > MAX_SSL2_TIMEOUT) {
+ ssl2_timeout = MAX_SSL2_TIMEOUT;
+ }
+ if (ssl2_timeout < MIN_SSL2_TIMEOUT) {
+ ssl2_timeout = MIN_SSL2_TIMEOUT;
+ }
+ cache->ssl2Timeout = ssl2_timeout;
} else {
- cache->ssl2Timeout = DEF_SSL2_TIMEOUT;
+ cache->ssl2Timeout = DEF_SSL2_TIMEOUT;
}
- if (ssl3_timeout) {
- if (ssl3_timeout > MAX_SSL3_TIMEOUT) {
- ssl3_timeout = MAX_SSL3_TIMEOUT;
- }
- if (ssl3_timeout < MIN_SSL3_TIMEOUT) {
- ssl3_timeout = MIN_SSL3_TIMEOUT;
- }
- cache->ssl3Timeout = ssl3_timeout;
+ if (ssl3_timeout) {
+ if (ssl3_timeout > MAX_SSL3_TIMEOUT) {
+ ssl3_timeout = MAX_SSL3_TIMEOUT;
+ }
+ if (ssl3_timeout < MIN_SSL3_TIMEOUT) {
+ ssl3_timeout = MIN_SSL3_TIMEOUT;
+ }
+ cache->ssl3Timeout = ssl3_timeout;
} else {
- cache->ssl3Timeout = DEF_SSL3_TIMEOUT;
+ cache->ssl3Timeout = DEF_SSL3_TIMEOUT;
}
if (shared) {
- /* Create file names */
+ /* Create file names */
#if defined(XP_UNIX) || defined(XP_BEOS)
- /* there's some confusion here about whether PR_OpenAnonFileMap wants
- ** a directory name or a file name for its first argument.
- cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid);
- */
- cfn = PR_smprintf("%s", directory);
+ /* there's some confusion here about whether PR_OpenAnonFileMap wants
+ ** a directory name or a file name for its first argument.
+ cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid);
+ */
+ cfn = PR_smprintf("%s", directory);
#elif defined(XP_WIN32)
- cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
- GetCurrentThreadId());
+ cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
+ GetCurrentThreadId());
#elif defined(XP_OS2)
- cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
- gettid());
+ cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
+ gettid());
#else
#error "Don't know how to create file name for this platform!"
#endif
- if (!cfn) {
- goto loser;
- }
+ if (!cfn) {
+ goto loser;
+ }
- /* Create cache */
- cacheMemMap = PR_OpenAnonFileMap(cfn, cache->cacheMemSize,
- PR_PROT_READWRITE);
+ /* Create cache */
+ cacheMemMap = PR_OpenAnonFileMap(cfn, cache->cacheMemSize,
+ PR_PROT_READWRITE);
- PR_smprintf_free(cfn);
- if(!cacheMemMap) {
- goto loser;
- }
+ PR_smprintf_free(cfn);
+ if (!cacheMemMap) {
+ goto loser;
+ }
cacheMem = PR_MemMap(cacheMemMap, 0, cache->cacheMemSize);
} else {
cacheMem = PORT_Alloc(cache->cacheMemSize);
}
-
- if (! cacheMem) {
+
+ if (!cacheMem) {
goto loser;
}
@@ -1221,53 +1215,40 @@ InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries,
/* save private copies of these values */
cache->cacheMemMap = cacheMemMap;
- cache->cacheMem = cacheMem;
+ cache->cacheMem = cacheMem;
cache->sharedCache = (cacheDesc *)cacheMem;
- /* Fix pointers in our private copy of cache descriptor to point to
- ** spaces in shared memory
+ /* Fix pointers in our private copy of cache descriptor to point to
+ ** spaces in shared memory
*/
- cache->sidCacheLocks = (sidCacheLock *)
- (cache->cacheMem + (ptrdiff_t)cache->sidCacheLocks);
- cache->keyCacheLock = (sidCacheLock *)
- (cache->cacheMem + (ptrdiff_t)cache->keyCacheLock);
- cache->certCacheLock = (sidCacheLock *)
- (cache->cacheMem + (ptrdiff_t)cache->certCacheLock);
- cache->srvNameCacheLock = (sidCacheLock *)
- (cache->cacheMem + (ptrdiff_t)cache->srvNameCacheLock);
- cache->sidCacheSets = (sidCacheSet *)
- (cache->cacheMem + (ptrdiff_t)cache->sidCacheSets);
- cache->sidCacheData = (sidCacheEntry *)
- (cache->cacheMem + (ptrdiff_t)cache->sidCacheData);
- cache->certCacheData = (certCacheEntry *)
- (cache->cacheMem + (ptrdiff_t)cache->certCacheData);
- cache->keyCacheData = (SSLWrappedSymWrappingKey *)
- (cache->cacheMem + (ptrdiff_t)cache->keyCacheData);
- cache->ticketKeyNameSuffix = (PRUint8 *)
- (cache->cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix);
- cache->ticketEncKey = (encKeyCacheEntry *)
- (cache->cacheMem + (ptrdiff_t)cache->ticketEncKey);
- cache->ticketMacKey = (encKeyCacheEntry *)
- (cache->cacheMem + (ptrdiff_t)cache->ticketMacKey);
- cache->ticketKeysValid = (PRUint32 *)
- (cache->cacheMem + (ptrdiff_t)cache->ticketKeysValid);
- cache->srvNameCacheData = (srvNameCacheEntry *)
- (cache->cacheMem + (ptrdiff_t)cache->srvNameCacheData);
+ cache->sidCacheLocks = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheLocks);
+ cache->keyCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->keyCacheLock);
+ cache->certCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->certCacheLock);
+ cache->srvNameCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->srvNameCacheLock);
+ cache->sidCacheSets = (sidCacheSet *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheSets);
+ cache->sidCacheData = (sidCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheData);
+ cache->certCacheData = (certCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->certCacheData);
+ cache->keyCacheData = (SSLWrappedSymWrappingKey *)(cache->cacheMem + (ptrdiff_t)cache->keyCacheData);
+ cache->ticketKeyNameSuffix = (PRUint8 *)(cache->cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix);
+ cache->ticketEncKey = (encKeyCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->ticketEncKey);
+ cache->ticketMacKey = (encKeyCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->ticketMacKey);
+ cache->ticketKeysValid = (PRUint32 *)(cache->cacheMem + (ptrdiff_t)cache->ticketKeysValid);
+ cache->srvNameCacheData = (srvNameCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->srvNameCacheData);
/* initialize the locks */
init_time = ssl_Time();
pLock = cache->sidCacheLocks;
for (locks_to_initialize = cache->numSIDCacheLocks + 3;
- locks_initialized < locks_to_initialize;
- ++locks_initialized, ++pLock ) {
-
- SECStatus err = sslMutex_Init(&pLock->mutex, shared);
- if (err) {
- cache->numSIDCacheLocksInitialized = locks_initialized;
- goto loser;
- }
+ locks_initialized < locks_to_initialize;
+ ++locks_initialized, ++pLock) {
+
+ SECStatus err = sslMutex_Init(&pLock->mutex, shared);
+ if (err) {
+ cache->numSIDCacheLocksInitialized = locks_initialized;
+ goto loser;
+ }
pLock->timeStamp = init_time;
- pLock->pid = 0;
+ pLock->pid = 0;
}
cache->numSIDCacheLocksInitialized = locks_initialized;
@@ -1294,8 +1275,8 @@ SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
** the maximum, other than trial and error.
*/
if (maxLocks < 3) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
ssl_max_sid_cache_locks = maxLocks - 2;
/* The extra two are the cert cache lock and the key cache lock. */
@@ -1305,12 +1286,12 @@ SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
static SECStatus
ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc *cache,
PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char * directory,
+ PRUint32 ssl3_timeout,
+ const char *directory,
PRBool shared,
- int maxCacheEntries,
- int maxCertCacheEntries,
- int maxSrvNameCacheEntries)
+ int maxCacheEntries,
+ int maxCertCacheEntries,
+ int maxSrvNameCacheEntries)
{
SECStatus rv;
@@ -1320,52 +1301,52 @@ ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc *cache,
rv = ssl_Init();
if (rv != SECSuccess) {
- return rv;
+ return rv;
}
myPid = SSL_GETPID();
if (!directory) {
- directory = DEFAULT_CACHE_DIRECTORY;
+ directory = DEFAULT_CACHE_DIRECTORY;
}
rv = InitCache(cache, maxCacheEntries, maxCertCacheEntries,
- maxSrvNameCacheEntries, ssl2_timeout, ssl3_timeout,
+ maxSrvNameCacheEntries, ssl2_timeout, ssl3_timeout,
directory, shared);
if (rv) {
- SET_ERROR_CODE
- return SECFailure;
+ SET_ERROR_CODE
+ return SECFailure;
}
- ssl_sid_lookup = ServerSessionIDLookup;
- ssl_sid_cache = ServerSessionIDCache;
+ ssl_sid_lookup = ServerSessionIDLookup;
+ ssl_sid_cache = ServerSessionIDCache;
ssl_sid_uncache = ServerSessionIDUncache;
return SECSuccess;
}
SECStatus
-SSL_ConfigServerSessionIDCacheInstance( cacheDesc *cache,
- int maxCacheEntries,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char * directory, PRBool shared)
+SSL_ConfigServerSessionIDCacheInstance(cacheDesc *cache,
+ int maxCacheEntries,
+ PRUint32 ssl2_timeout,
+ PRUint32 ssl3_timeout,
+ const char *directory, PRBool shared)
{
return ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache,
ssl2_timeout,
ssl3_timeout,
directory,
shared,
- maxCacheEntries,
+ maxCacheEntries,
-1, -1);
}
SECStatus
-SSL_ConfigServerSessionIDCache( int maxCacheEntries,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char * directory)
+SSL_ConfigServerSessionIDCache(int maxCacheEntries,
+ PRUint32 ssl2_timeout,
+ PRUint32 ssl3_timeout,
+ const char *directory)
{
ssl_InitSessionCacheLocks();
- return SSL_ConfigServerSessionIDCacheInstance(&globalCache,
- maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE);
+ return SSL_ConfigServerSessionIDCacheInstance(&globalCache,
+ maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE);
}
SECStatus
@@ -1390,49 +1371,49 @@ SSL_ShutdownServerSessionIDCache(void)
* if the cache will be shared by multiple processes.
*/
static SECStatus
-ssl_ConfigMPServerSIDCacheWithOpt( PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char * directory,
- int maxCacheEntries,
- int maxCertCacheEntries,
- int maxSrvNameCacheEntries)
+ssl_ConfigMPServerSIDCacheWithOpt(PRUint32 ssl2_timeout,
+ PRUint32 ssl3_timeout,
+ const char *directory,
+ int maxCacheEntries,
+ int maxCertCacheEntries,
+ int maxSrvNameCacheEntries)
{
- char * envValue;
- char * inhValue;
- cacheDesc * cache = &globalCache;
- PRUint32 fmStrLen;
- SECStatus result;
- PRStatus prStatus;
- SECStatus putEnvFailed;
+ char *envValue;
+ char *inhValue;
+ cacheDesc *cache = &globalCache;
+ PRUint32 fmStrLen;
+ SECStatus result;
+ PRStatus prStatus;
+ SECStatus putEnvFailed;
inheritance inherit;
- char fmString[PR_FILEMAP_STRING_BUFSIZE];
+ char fmString[PR_FILEMAP_STRING_BUFSIZE];
isMultiProcess = PR_TRUE;
result = ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache,
- ssl2_timeout, ssl3_timeout, directory, PR_TRUE,
- maxCacheEntries, maxCacheEntries, maxSrvNameCacheEntries);
- if (result != SECSuccess)
+ ssl2_timeout, ssl3_timeout, directory, PR_TRUE,
+ maxCacheEntries, maxCacheEntries, maxSrvNameCacheEntries);
+ if (result != SECSuccess)
return result;
- prStatus = PR_ExportFileMapAsString(cache->cacheMemMap,
+ prStatus = PR_ExportFileMapAsString(cache->cacheMemMap,
sizeof fmString, fmString);
if ((prStatus != PR_SUCCESS) || !(fmStrLen = strlen(fmString))) {
- SET_ERROR_CODE
- return SECFailure;
+ SET_ERROR_CODE
+ return SECFailure;
}
- inherit.cacheMemSize = cache->cacheMemSize;
- inherit.fmStrLen = fmStrLen;
+ inherit.cacheMemSize = cache->cacheMemSize;
+ inherit.fmStrLen = fmStrLen;
inhValue = BTOA_DataToAscii((unsigned char *)&inherit, sizeof inherit);
if (!inhValue || !strlen(inhValue)) {
- SET_ERROR_CODE
- return SECFailure;
+ SET_ERROR_CODE
+ return SECFailure;
}
envValue = PR_smprintf("%s,%s", inhValue, fmString);
if (!envValue || !strlen(envValue)) {
- SET_ERROR_CODE
- return SECFailure;
+ SET_ERROR_CODE
+ return SECFailure;
}
PORT_Free(inhValue);
@@ -1454,10 +1435,10 @@ ssl_ConfigMPServerSIDCacheWithOpt( PRUint32 ssl2_timeout,
* if the cache will be shared by multiple processes.
*/
SECStatus
-SSL_ConfigMPServerSIDCache( int maxCacheEntries,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char * directory)
+SSL_ConfigMPServerSIDCache(int maxCacheEntries,
+ PRUint32 ssl2_timeout,
+ PRUint32 ssl3_timeout,
+ const char *directory)
{
return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout,
ssl3_timeout,
@@ -1468,44 +1449,44 @@ SSL_ConfigMPServerSIDCache( int maxCacheEntries,
SECStatus
SSL_ConfigServerSessionIDCacheWithOpt(
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char * directory,
- int maxCacheEntries,
- int maxCertCacheEntries,
- int maxSrvNameCacheEntries,
- PRBool enableMPCache)
+ PRUint32 ssl2_timeout,
+ PRUint32 ssl3_timeout,
+ const char *directory,
+ int maxCacheEntries,
+ int maxCertCacheEntries,
+ int maxSrvNameCacheEntries,
+ PRBool enableMPCache)
{
if (!enableMPCache) {
ssl_InitSessionCacheLocks();
- return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache,
- ssl2_timeout, ssl3_timeout, directory, PR_FALSE,
- maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries);
+ return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache,
+ ssl2_timeout, ssl3_timeout, directory, PR_FALSE,
+ maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries);
} else {
return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout, ssl3_timeout,
- directory, maxCacheEntries, maxCertCacheEntries,
+ directory, maxCacheEntries, maxCertCacheEntries,
maxSrvNameCacheEntries);
}
}
SECStatus
-SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
+SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char *envString)
{
- unsigned char * decoString = NULL;
- char * fmString = NULL;
- char * myEnvString = NULL;
- unsigned int decoLen;
- inheritance inherit;
- cacheDesc my;
+ unsigned char *decoString = NULL;
+ char *fmString = NULL;
+ char *myEnvString = NULL;
+ unsigned int decoLen;
+ inheritance inherit;
+ cacheDesc my;
#ifdef WINNT
- sidCacheLock* newLocks;
- int locks_initialized = 0;
- int locks_to_initialize = 0;
+ sidCacheLock *newLocks;
+ int locks_initialized = 0;
+ int locks_to_initialize = 0;
#endif
- SECStatus status = ssl_Init();
+ SECStatus status = ssl_Init();
if (status != SECSuccess) {
- return status;
+ return status;
}
myPid = SSL_GETPID();
@@ -1515,110 +1496,97 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
** If not, we'll set it below.
*/
if (isMultiProcess) {
- if (cache && cache->sharedCache) {
- cache->sharedCache->everInherited = PR_TRUE;
- }
- return SECSuccess; /* already done. */
+ if (cache && cache->sharedCache) {
+ cache->sharedCache->everInherited = PR_TRUE;
+ }
+ return SECSuccess; /* already done. */
}
ssl_InitSessionCacheLocks();
- ssl_sid_lookup = ServerSessionIDLookup;
- ssl_sid_cache = ServerSessionIDCache;
+ ssl_sid_lookup = ServerSessionIDLookup;
+ ssl_sid_cache = ServerSessionIDCache;
ssl_sid_uncache = ServerSessionIDUncache;
if (!envString) {
- envString = getenv(envVarName);
- if (!envString) {
- SET_ERROR_CODE
- return SECFailure;
- }
+ envString = PR_GetEnvSecure(envVarName);
+ if (!envString) {
+ SET_ERROR_CODE
+ return SECFailure;
+ }
}
myEnvString = PORT_Strdup(envString);
- if (!myEnvString)
- return SECFailure;
+ if (!myEnvString)
+ return SECFailure;
fmString = strchr(myEnvString, ',');
- if (!fmString)
- goto loser;
+ if (!fmString)
+ goto loser;
*fmString++ = 0;
decoString = ATOB_AsciiToData(myEnvString, &decoLen);
if (!decoString) {
- SET_ERROR_CODE
- goto loser;
+ SET_ERROR_CODE
+ goto loser;
}
if (decoLen != sizeof inherit) {
- SET_ERROR_CODE
- goto loser;
+ SET_ERROR_CODE
+ goto loser;
}
PORT_Memcpy(&inherit, decoString, sizeof inherit);
- if (strlen(fmString) != inherit.fmStrLen ) {
- goto loser;
+ if (strlen(fmString) != inherit.fmStrLen) {
+ goto loser;
}
memset(cache, 0, sizeof *cache);
- cache->cacheMemSize = inherit.cacheMemSize;
+ cache->cacheMemSize = inherit.cacheMemSize;
/* Create cache */
cache->cacheMemMap = PR_ImportFileMapFromString(fmString);
- if(! cache->cacheMemMap) {
- goto loser;
+ if (!cache->cacheMemMap) {
+ goto loser;
}
cache->cacheMem = PR_MemMap(cache->cacheMemMap, 0, cache->cacheMemSize);
- if (! cache->cacheMem) {
- goto loser;
+ if (!cache->cacheMem) {
+ goto loser;
}
- cache->sharedCache = (cacheDesc *)cache->cacheMem;
+ cache->sharedCache = (cacheDesc *)cache->cacheMem;
if (cache->sharedCache->cacheMemSize != cache->cacheMemSize) {
- SET_ERROR_CODE
- goto loser;
+ SET_ERROR_CODE
+ goto loser;
}
- /* We're now going to overwrite the local cache instance with the
- ** shared copy of the cache struct, then update several values in
- ** the local cache using the values for cache->cacheMemMap and
- ** cache->cacheMem computed just above. So, we copy cache into
+ /* We're now going to overwrite the local cache instance with the
+ ** shared copy of the cache struct, then update several values in
+ ** the local cache using the values for cache->cacheMemMap and
+ ** cache->cacheMem computed just above. So, we copy cache into
** the automatic variable "my", to preserve the variables while
** cache is overwritten.
*/
- my = *cache; /* save values computed above. */
+ my = *cache; /* save values computed above. */
memcpy(cache, cache->sharedCache, sizeof *cache); /* overwrite */
- /* Fix pointers in our private copy of cache descriptor to point to
+ /* Fix pointers in our private copy of cache descriptor to point to
** spaces in shared memory, whose address is now in "my".
*/
- cache->sidCacheLocks = (sidCacheLock *)
- (my.cacheMem + (ptrdiff_t)cache->sidCacheLocks);
- cache->keyCacheLock = (sidCacheLock *)
- (my.cacheMem + (ptrdiff_t)cache->keyCacheLock);
- cache->certCacheLock = (sidCacheLock *)
- (my.cacheMem + (ptrdiff_t)cache->certCacheLock);
- cache->srvNameCacheLock = (sidCacheLock *)
- (my.cacheMem + (ptrdiff_t)cache->srvNameCacheLock);
- cache->sidCacheSets = (sidCacheSet *)
- (my.cacheMem + (ptrdiff_t)cache->sidCacheSets);
- cache->sidCacheData = (sidCacheEntry *)
- (my.cacheMem + (ptrdiff_t)cache->sidCacheData);
- cache->certCacheData = (certCacheEntry *)
- (my.cacheMem + (ptrdiff_t)cache->certCacheData);
- cache->keyCacheData = (SSLWrappedSymWrappingKey *)
- (my.cacheMem + (ptrdiff_t)cache->keyCacheData);
- cache->ticketKeyNameSuffix = (PRUint8 *)
- (my.cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix);
- cache->ticketEncKey = (encKeyCacheEntry *)
- (my.cacheMem + (ptrdiff_t)cache->ticketEncKey);
- cache->ticketMacKey = (encKeyCacheEntry *)
- (my.cacheMem + (ptrdiff_t)cache->ticketMacKey);
- cache->ticketKeysValid = (PRUint32 *)
- (my.cacheMem + (ptrdiff_t)cache->ticketKeysValid);
- cache->srvNameCacheData = (srvNameCacheEntry *)
- (my.cacheMem + (ptrdiff_t)cache->srvNameCacheData);
+ cache->sidCacheLocks = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->sidCacheLocks);
+ cache->keyCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->keyCacheLock);
+ cache->certCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->certCacheLock);
+ cache->srvNameCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->srvNameCacheLock);
+ cache->sidCacheSets = (sidCacheSet *)(my.cacheMem + (ptrdiff_t)cache->sidCacheSets);
+ cache->sidCacheData = (sidCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->sidCacheData);
+ cache->certCacheData = (certCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->certCacheData);
+ cache->keyCacheData = (SSLWrappedSymWrappingKey *)(my.cacheMem + (ptrdiff_t)cache->keyCacheData);
+ cache->ticketKeyNameSuffix = (PRUint8 *)(my.cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix);
+ cache->ticketEncKey = (encKeyCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->ticketEncKey);
+ cache->ticketMacKey = (encKeyCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->ticketMacKey);
+ cache->ticketKeysValid = (PRUint32 *)(my.cacheMem + (ptrdiff_t)cache->ticketKeysValid);
+ cache->srvNameCacheData = (srvNameCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->srvNameCacheData);
cache->cacheMemMap = my.cacheMemMap;
- cache->cacheMem = my.cacheMem;
+ cache->cacheMem = my.cacheMem;
cache->sharedCache = (cacheDesc *)cache->cacheMem;
#ifdef WINNT
@@ -1633,34 +1601,34 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
** copies of sidCacheLocks before modifying the sslMutex with our own
** PRLock
*/
-
+
/* note from jpierre : this should be free'd in child processes when
- ** a function is added to delete the SSL session cache in the future.
+ ** a function is added to delete the SSL session cache in the future.
*/
locks_to_initialize = cache->numSIDCacheLocks + 3;
newLocks = PORT_NewArray(sidCacheLock, locks_to_initialize);
if (!newLocks)
- goto loser;
+ goto loser;
/* copy the old locks */
- memcpy(newLocks, cache->sidCacheLocks,
+ memcpy(newLocks, cache->sidCacheLocks,
locks_to_initialize * sizeof(sidCacheLock));
cache->sidCacheLocks = newLocks;
- /* fix the locks */
+ /* fix the locks */
for (; locks_initialized < locks_to_initialize; ++locks_initialized) {
/* now, make a local PRLock in this sslMutex for this child process */
- SECStatus err;
+ SECStatus err;
err = sslMutex_2LevelInit(&newLocks[locks_initialized].mutex);
- if (err != SECSuccess) {
- cache->numSIDCacheLocksInitialized = locks_initialized;
- goto loser;
- }
+ if (err != SECSuccess) {
+ cache->numSIDCacheLocksInitialized = locks_initialized;
+ goto loser;
+ }
}
cache->numSIDCacheLocksInitialized = locks_initialized;
/* also fix the key and cert cache which use the last 2 lock entries */
- cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
- cache->certCacheLock = cache->keyCacheLock + 1;
- cache->srvNameCacheLock = cache->certCacheLock + 1;
+ cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
+ cache->certCacheLock = cache->keyCacheLock + 1;
+ cache->srvNameCacheLock = cache->certCacheLock + 1;
#endif
PORT_Free(myEnvString);
@@ -1674,112 +1642,112 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
loser:
PORT_Free(myEnvString);
- if (decoString)
- PORT_Free(decoString);
+ if (decoString)
+ PORT_Free(decoString);
CloseCache(cache);
return SECFailure;
}
SECStatus
-SSL_InheritMPServerSIDCache(const char * envString)
+SSL_InheritMPServerSIDCache(const char *envString)
{
return SSL_InheritMPServerSIDCacheInstance(&globalCache, envString);
}
#if defined(XP_UNIX) || defined(XP_BEOS)
-#define SID_LOCK_EXPIRATION_TIMEOUT 30 /* seconds */
+#define SID_LOCK_EXPIRATION_TIMEOUT 30 /* seconds */
static void
-LockPoller(void * arg)
+LockPoller(void *arg)
{
- cacheDesc * cache = (cacheDesc *)arg;
- cacheDesc * sharedCache = cache->sharedCache;
- sidCacheLock * pLock;
+ cacheDesc *cache = (cacheDesc *)arg;
+ cacheDesc *sharedCache = cache->sharedCache;
+ sidCacheLock *pLock;
PRIntervalTime timeout;
- PRUint32 now;
- PRUint32 then;
- int locks_polled = 0;
- int locks_to_poll = cache->numSIDCacheLocks + 2;
- PRUint32 expiration = cache->mutexTimeout;
+ PRUint32 now;
+ PRUint32 then;
+ int locks_polled = 0;
+ int locks_to_poll = cache->numSIDCacheLocks + 2;
+ PRUint32 expiration = cache->mutexTimeout;
timeout = PR_SecondsToInterval(expiration);
- while(!sharedCache->stopPolling) {
- PR_Sleep(timeout);
- if (sharedCache->stopPolling)
- break;
-
- now = ssl_Time();
- then = now - expiration;
- for (pLock = cache->sidCacheLocks, locks_polled = 0;
- locks_to_poll > locks_polled && !sharedCache->stopPolling;
- ++locks_polled, ++pLock ) {
- pid_t pid;
-
- if (pLock->timeStamp < then &&
- pLock->timeStamp != 0 &&
- (pid = pLock->pid) != 0) {
-
- /* maybe we should try the lock? */
- int result = kill(pid, 0);
- if (result < 0 && errno == ESRCH) {
- SECStatus rv;
- /* No process exists by that pid any more.
- ** Treat this mutex as abandoned.
- */
- pLock->timeStamp = now;
- pLock->pid = 0;
- rv = sslMutex_Unlock(&pLock->mutex);
- if (rv != SECSuccess) {
- /* Now what? */
- }
- }
- }
- } /* end of loop over locks */
- } /* end of entire polling loop */
+ while (!sharedCache->stopPolling) {
+ PR_Sleep(timeout);
+ if (sharedCache->stopPolling)
+ break;
+
+ now = ssl_Time();
+ then = now - expiration;
+ for (pLock = cache->sidCacheLocks, locks_polled = 0;
+ locks_to_poll > locks_polled && !sharedCache->stopPolling;
+ ++locks_polled, ++pLock) {
+ pid_t pid;
+
+ if (pLock->timeStamp < then &&
+ pLock->timeStamp != 0 &&
+ (pid = pLock->pid) != 0) {
+
+ /* maybe we should try the lock? */
+ int result = kill(pid, 0);
+ if (result < 0 && errno == ESRCH) {
+ SECStatus rv;
+ /* No process exists by that pid any more.
+ ** Treat this mutex as abandoned.
+ */
+ pLock->timeStamp = now;
+ pLock->pid = 0;
+ rv = sslMutex_Unlock(&pLock->mutex);
+ if (rv != SECSuccess) {
+ /* Now what? */
+ }
+ }
+ }
+ } /* end of loop over locks */
+ } /* end of entire polling loop */
}
/* Launch thread to poll cache for expired locks */
-static SECStatus
+static SECStatus
LaunchLockPoller(cacheDesc *cache)
{
- const char * timeoutString;
- PRThread * pollerThread;
+ const char *timeoutString;
+ PRThread *pollerThread;
cache->mutexTimeout = SID_LOCK_EXPIRATION_TIMEOUT;
- timeoutString = getenv("NSS_SSL_SERVER_CACHE_MUTEX_TIMEOUT");
+ timeoutString = PR_GetEnvSecure("NSS_SSL_SERVER_CACHE_MUTEX_TIMEOUT");
if (timeoutString) {
- long newTime = strtol(timeoutString, 0, 0);
- if (newTime == 0)
- return SECSuccess; /* application doesn't want poller thread */
- if (newTime > 0)
- cache->mutexTimeout = (PRUint32)newTime;
- /* if error (newTime < 0) ignore it and use default */
+ long newTime = strtol(timeoutString, 0, 0);
+ if (newTime == 0)
+ return SECSuccess; /* application doesn't want poller thread */
+ if (newTime > 0)
+ cache->mutexTimeout = (PRUint32)newTime;
+ /* if error (newTime < 0) ignore it and use default */
}
- pollerThread =
- PR_CreateThread(PR_USER_THREAD, LockPoller, cache, PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ pollerThread =
+ PR_CreateThread(PR_USER_THREAD, LockPoller, cache, PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
if (!pollerThread) {
- return SECFailure;
+ return SECFailure;
}
cache->poller = pollerThread;
return SECSuccess;
}
/* Stop the thread that polls cache for expired locks */
-static SECStatus
+static SECStatus
StopLockPoller(cacheDesc *cache)
{
if (!cache->poller) {
- return SECSuccess;
+ return SECSuccess;
}
cache->sharedCache->stopPolling = PR_TRUE;
if (PR_Interrupt(cache->poller) != PR_SUCCESS) {
- return SECFailure;
+ return SECFailure;
}
if (PR_JoinThread(cache->poller) != PR_SUCCESS) {
- return SECFailure;
+ return SECFailure;
}
cache->poller = NULL;
return SECSuccess;
@@ -1790,58 +1758,58 @@ StopLockPoller(cacheDesc *cache)
* Code dealing with shared wrapped symmetric wrapping keys below *
************************************************************************/
-/* If now is zero, it implies that the lock is not held, and must be
-** aquired here.
+/* If now is zero, it implies that the lock is not held, and must be
+** aquired here.
*/
static PRBool
-getSvrWrappingKey(PRInt32 symWrapMechIndex,
- SSL3KEAType exchKeyType,
- SSLWrappedSymWrappingKey *wswk,
- cacheDesc * cache,
- PRUint32 lockTime)
+getSvrWrappingKey(PRInt32 symWrapMechIndex,
+ SSL3KEAType exchKeyType,
+ SSLWrappedSymWrappingKey *wswk,
+ cacheDesc *cache,
+ PRUint32 lockTime)
{
- PRUint32 ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
- SSLWrappedSymWrappingKey * pwswk = cache->keyCacheData + ndx;
- PRUint32 now = 0;
- PRBool rv = PR_FALSE;
+ PRUint32 ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
+ SSLWrappedSymWrappingKey *pwswk = cache->keyCacheData + ndx;
+ PRUint32 now = 0;
+ PRBool rv = PR_FALSE;
if (!cache->cacheMem) { /* cache is uninitialized */
- PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
- return rv;
+ PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
+ return rv;
}
if (!lockTime) {
- lockTime = now = LockSidCacheLock(cache->keyCacheLock, now);
- if (!lockTime) {
- return rv;
- }
+ lockTime = now = LockSidCacheLock(cache->keyCacheLock, now);
+ if (!lockTime) {
+ return rv;
+ }
}
- if (pwswk->exchKeyType == exchKeyType &&
- pwswk->symWrapMechIndex == symWrapMechIndex &&
- pwswk->wrappedSymKeyLen != 0) {
- *wswk = *pwswk;
- rv = PR_TRUE;
+ if (pwswk->exchKeyType == exchKeyType &&
+ pwswk->symWrapMechIndex == symWrapMechIndex &&
+ pwswk->wrappedSymKeyLen != 0) {
+ *wswk = *pwswk;
+ rv = PR_TRUE;
}
if (now) {
- UnlockSidCacheLock(cache->keyCacheLock);
+ UnlockSidCacheLock(cache->keyCacheLock);
}
return rv;
}
PRBool
-ssl_GetWrappingKey( PRInt32 symWrapMechIndex,
- SSL3KEAType exchKeyType,
- SSLWrappedSymWrappingKey *wswk)
+ssl_GetWrappingKey(PRInt32 symWrapMechIndex,
+ SSL3KEAType exchKeyType,
+ SSLWrappedSymWrappingKey *wswk)
{
PRBool rv;
- PORT_Assert( (unsigned)exchKeyType < kt_kea_size);
- PORT_Assert( (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
+ PORT_Assert((unsigned)exchKeyType < kt_kea_size);
+ PORT_Assert((unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
if ((unsigned)exchKeyType < kt_kea_size &&
(unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS) {
- rv = getSvrWrappingKey(symWrapMechIndex, exchKeyType, wswk,
- &globalCache, 0);
+ rv = getSvrWrappingKey(symWrapMechIndex, exchKeyType, wswk,
+ &globalCache, 0);
} else {
- rv = PR_FALSE;
+ rv = PR_FALSE;
}
return rv;
@@ -1850,21 +1818,21 @@ ssl_GetWrappingKey( PRInt32 symWrapMechIndex,
/* Wrap and cache a session ticket key. */
static PRBool
WrapTicketKey(SECKEYPublicKey *svrPubKey, PK11SymKey *symKey,
- const char *keyName, encKeyCacheEntry* cacheEntry)
+ const char *keyName, encKeyCacheEntry *cacheEntry)
{
- SECItem wrappedKey = {siBuffer, NULL, 0};
+ SECItem wrappedKey = { siBuffer, NULL, 0 };
wrappedKey.len = SECKEY_PublicKeyStrength(svrPubKey);
PORT_Assert(wrappedKey.len <= sizeof(cacheEntry->bytes));
if (wrappedKey.len > sizeof(cacheEntry->bytes))
- return PR_FALSE;
+ return PR_FALSE;
wrappedKey.data = cacheEntry->bytes;
- if (PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, symKey, &wrappedKey)
- != SECSuccess) {
- SSL_DBG(("%d: SSL[%s]: Unable to wrap session ticket %s.",
- SSL_GETPID(), "unknown", keyName));
- return PR_FALSE;
+ if (PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, symKey, &wrappedKey) !=
+ SECSuccess) {
+ SSL_DBG(("%d: SSL[%s]: Unable to wrap session ticket %s.",
+ SSL_GETPID(), "unknown", keyName));
+ return PR_FALSE;
}
cacheEntry->length = wrappedKey.len;
return PR_TRUE;
@@ -1890,10 +1858,11 @@ GenerateTicketKeys(void *pwArg, unsigned char *keyName, PK11SymKey **aesKey,
}
if (PK11_GenerateRandom(ticketKeyNameSuffix,
- SESS_TICKET_KEY_VAR_NAME_LEN) != SECSuccess) {
- SSL_DBG(("%d: SSL[%s]: Unable to generate random key name bytes.",
- SSL_GETPID(), "unknown"));
- goto loser;
+ SESS_TICKET_KEY_VAR_NAME_LEN) !=
+ SECSuccess) {
+ SSL_DBG(("%d: SSL[%s]: Unable to generate random key name bytes.",
+ SSL_GETPID(), "unknown"));
+ goto loser;
}
mechanismArray[0] = CKM_AES_CBC;
@@ -1901,17 +1870,17 @@ GenerateTicketKeys(void *pwArg, unsigned char *keyName, PK11SymKey **aesKey,
slot = PK11_GetBestSlotMultiple(mechanismArray, 2, pwArg);
if (slot) {
- aesKeyTmp = PK11_KeyGen(slot, mechanismArray[0], NULL,
+ aesKeyTmp = PK11_KeyGen(slot, mechanismArray[0], NULL,
AES_256_KEY_LENGTH, pwArg);
- macKeyTmp = PK11_KeyGen(slot, mechanismArray[1], NULL,
+ macKeyTmp = PK11_KeyGen(slot, mechanismArray[1], NULL,
SHA256_LENGTH, pwArg);
- PK11_FreeSlot(slot);
+ PK11_FreeSlot(slot);
}
if (aesKeyTmp == NULL || macKeyTmp == NULL) {
- SSL_DBG(("%d: SSL[%s]: Unable to generate session ticket keys.",
- SSL_GETPID(), "unknown"));
- goto loser;
+ SSL_DBG(("%d: SSL[%s]: Unable to generate session ticket keys.",
+ SSL_GETPID(), "unknown"));
+ goto loser;
}
PORT_Memcpy(keyName, ticketKeyNameSuffix, SESS_TICKET_KEY_VAR_NAME_LEN);
*aesKey = aesKeyTmp;
@@ -1920,9 +1889,9 @@ GenerateTicketKeys(void *pwArg, unsigned char *keyName, PK11SymKey **aesKey,
loser:
if (aesKeyTmp)
- PK11_FreeSymKey(aesKeyTmp);
+ PK11_FreeSymKey(aesKeyTmp);
if (macKeyTmp)
- PK11_FreeSymKey(macKeyTmp);
+ PK11_FreeSymKey(macKeyTmp);
return PR_FALSE;
}
@@ -1952,9 +1921,9 @@ GenerateAndWrapTicketKeys(SECKEYPublicKey *svrPubKey, void *pwArg,
loser:
if (aesKeyTmp)
- PK11_FreeSymKey(aesKeyTmp);
+ PK11_FreeSymKey(aesKeyTmp);
if (macKeyTmp)
- PK11_FreeSymKey(macKeyTmp);
+ PK11_FreeSymKey(macKeyTmp);
return PR_FALSE;
}
@@ -1962,7 +1931,7 @@ static PRBool
UnwrapCachedTicketKeys(SECKEYPrivateKey *svrPrivKey, unsigned char *keyName,
PK11SymKey **aesKey, PK11SymKey **macKey)
{
- SECItem wrappedKey = {siBuffer, NULL, 0};
+ SECItem wrappedKey = { siBuffer, NULL, 0 };
PK11SymKey *aesKeyTmp = NULL;
PK11SymKey *macKeyTmp = NULL;
cacheDesc *cache = &globalCache;
@@ -1971,33 +1940,33 @@ UnwrapCachedTicketKeys(SECKEYPrivateKey *svrPrivKey, unsigned char *keyName,
wrappedKey.len = cache->ticketEncKey->length;
PORT_Assert(wrappedKey.len <= sizeof(cache->ticketEncKey->bytes));
aesKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
- CKM_AES_CBC, CKA_DECRYPT, 0);
+ CKM_AES_CBC, CKA_DECRYPT, 0);
wrappedKey.data = cache->ticketMacKey->bytes;
wrappedKey.len = cache->ticketMacKey->length;
PORT_Assert(wrappedKey.len <= sizeof(cache->ticketMacKey->bytes));
macKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
- CKM_SHA256_HMAC, CKA_SIGN, 0);
+ CKM_SHA256_HMAC, CKA_SIGN, 0);
if (aesKeyTmp == NULL || macKeyTmp == NULL) {
- SSL_DBG(("%d: SSL[%s]: Unable to unwrap session ticket keys.",
- SSL_GETPID(), "unknown"));
- goto loser;
+ SSL_DBG(("%d: SSL[%s]: Unable to unwrap session ticket keys.",
+ SSL_GETPID(), "unknown"));
+ goto loser;
}
SSL_DBG(("%d: SSL[%s]: Successfully unwrapped session ticket keys.",
- SSL_GETPID(), "unknown"));
+ SSL_GETPID(), "unknown"));
PORT_Memcpy(keyName, cache->ticketKeyNameSuffix,
- SESS_TICKET_KEY_VAR_NAME_LEN);
+ SESS_TICKET_KEY_VAR_NAME_LEN);
*aesKey = aesKeyTmp;
*macKey = macKeyTmp;
return PR_TRUE;
loser:
if (aesKeyTmp)
- PK11_FreeSymKey(aesKeyTmp);
+ PK11_FreeSymKey(aesKeyTmp);
if (macKeyTmp)
- PK11_FreeSymKey(macKeyTmp);
+ PK11_FreeSymKey(macKeyTmp);
return PR_FALSE;
}
@@ -2020,23 +1989,23 @@ ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey,
now = LockSidCacheLock(cache->keyCacheLock, now);
if (!now)
- return rv;
+ return rv;
if (!*(cache->ticketKeysValid)) {
- /* Keys do not exist, create them. */
- if (!GenerateAndWrapTicketKeys(svrPubKey, pwArg, keyName,
- aesKey, macKey))
- goto loser;
- keysGenerated = PR_TRUE;
- *(cache->ticketKeysValid) = 1;
+ /* Keys do not exist, create them. */
+ if (!GenerateAndWrapTicketKeys(svrPubKey, pwArg, keyName,
+ aesKey, macKey))
+ goto loser;
+ keysGenerated = PR_TRUE;
+ *(cache->ticketKeysValid) = 1;
}
rv = PR_TRUE;
- loser:
+loser:
UnlockSidCacheLock(cache->keyCacheLock);
if (rv && !keysGenerated)
- rv = UnwrapCachedTicketKeys(svrPrivKey, keyName, aesKey, macKey);
+ rv = UnwrapCachedTicketKeys(svrPrivKey, keyName, aesKey, macKey);
return rv;
}
@@ -2074,15 +2043,16 @@ ssl_GetSessionTicketKeys(unsigned char *keyName, unsigned char *encKey,
/* Going to regenerate keys on every call if cache was not
* initialized. */
if (!cacheIsEnabled || !*(cache->ticketKeysValid)) {
- if (PK11_GenerateRandom(ticketKeyNameSuffix,
- SESS_TICKET_KEY_VAR_NAME_LEN) != SECSuccess)
- goto loser;
- if (PK11_GenerateRandom(ticketEncKeyPtr,
+ if (PK11_GenerateRandom(ticketKeyNameSuffix,
+ SESS_TICKET_KEY_VAR_NAME_LEN) !=
+ SECSuccess)
+ goto loser;
+ if (PK11_GenerateRandom(ticketEncKeyPtr,
AES_256_KEY_LENGTH) != SECSuccess)
- goto loser;
- if (PK11_GenerateRandom(ticketMacKeyPtr,
+ goto loser;
+ if (PK11_GenerateRandom(ticketMacKeyPtr,
SHA256_LENGTH) != SECSuccess)
- goto loser;
+ goto loser;
if (cacheIsEnabled) {
*(cache->ticketKeysValid) = 1;
}
@@ -2090,73 +2060,73 @@ ssl_GetSessionTicketKeys(unsigned char *keyName, unsigned char *encKey,
rv = PR_TRUE;
- loser:
+loser:
if (cacheIsEnabled) {
UnlockSidCacheLock(cache->keyCacheLock);
}
if (rv) {
- PORT_Memcpy(keyName, ticketKeyNameSuffix,
+ PORT_Memcpy(keyName, ticketKeyNameSuffix,
SESS_TICKET_KEY_VAR_NAME_LEN);
- PORT_Memcpy(encKey, ticketEncKeyPtr, AES_256_KEY_LENGTH);
- PORT_Memcpy(macKey, ticketMacKeyPtr, SHA256_LENGTH);
+ PORT_Memcpy(encKey, ticketEncKeyPtr, AES_256_KEY_LENGTH);
+ PORT_Memcpy(macKey, ticketMacKeyPtr, SHA256_LENGTH);
}
return rv;
}
/* The caller passes in the new value it wants
* to set. This code tests the wrapped sym key entry in the shared memory.
- * If it is uninitialized, this function writes the caller's value into
- * the disk entry, and returns false.
- * Otherwise, it overwrites the caller's wswk with the value obtained from
- * the disk, and returns PR_TRUE.
- * This is all done while holding the locks/mutexes necessary to make
+ * If it is uninitialized, this function writes the caller's value into
+ * the disk entry, and returns false.
+ * Otherwise, it overwrites the caller's wswk with the value obtained from
+ * the disk, and returns PR_TRUE.
+ * This is all done while holding the locks/mutexes necessary to make
* the operation atomic.
*/
PRBool
ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
{
- cacheDesc * cache = &globalCache;
- PRBool rv = PR_FALSE;
- SSL3KEAType exchKeyType = wswk->exchKeyType;
- /* type of keys used to wrap SymWrapKey*/
- PRInt32 symWrapMechIndex = wswk->symWrapMechIndex;
- PRUint32 ndx;
- PRUint32 now = 0;
+ cacheDesc *cache = &globalCache;
+ PRBool rv = PR_FALSE;
+ SSL3KEAType exchKeyType = wswk->exchKeyType;
+ /* type of keys used to wrap SymWrapKey*/
+ PRInt32 symWrapMechIndex = wswk->symWrapMechIndex;
+ PRUint32 ndx;
+ PRUint32 now = 0;
SSLWrappedSymWrappingKey myWswk;
if (!cache->cacheMem) { /* cache is uninitialized */
- PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
- return 0;
+ PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
+ return 0;
}
- PORT_Assert( (unsigned)exchKeyType < kt_kea_size);
+ PORT_Assert((unsigned)exchKeyType < kt_kea_size);
if ((unsigned)exchKeyType >= kt_kea_size)
- return 0;
+ return 0;
- PORT_Assert( (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
- if ((unsigned)symWrapMechIndex >= SSL_NUM_WRAP_MECHS)
- return 0;
+ PORT_Assert((unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
+ if ((unsigned)symWrapMechIndex >= SSL_NUM_WRAP_MECHS)
+ return 0;
ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
- PORT_Memset(&myWswk, 0, sizeof myWswk); /* eliminate UMRs. */
+ PORT_Memset(&myWswk, 0, sizeof myWswk); /* eliminate UMRs. */
now = LockSidCacheLock(cache->keyCacheLock, now);
if (now) {
- rv = getSvrWrappingKey(wswk->symWrapMechIndex, wswk->exchKeyType,
- &myWswk, cache, now);
- if (rv) {
- /* we found it on disk, copy it out to the caller. */
- PORT_Memcpy(wswk, &myWswk, sizeof *wswk);
- } else {
- /* Wasn't on disk, and we're still holding the lock, so write it. */
- cache->keyCacheData[ndx] = *wswk;
- }
- UnlockSidCacheLock(cache->keyCacheLock);
+ rv = getSvrWrappingKey(wswk->symWrapMechIndex, wswk->exchKeyType,
+ &myWswk, cache, now);
+ if (rv) {
+ /* we found it on disk, copy it out to the caller. */
+ PORT_Memcpy(wswk, &myWswk, sizeof *wswk);
+ } else {
+ /* Wasn't on disk, and we're still holding the lock, so write it. */
+ cache->keyCacheData[ndx] = *wswk;
+ }
+ UnlockSidCacheLock(cache->keyCacheLock);
}
return rv;
}
-#else /* MAC version or other platform */
+#else /* MAC version or other platform */
#include "seccomon.h"
#include "cert.h"
@@ -2164,67 +2134,67 @@ ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
#include "sslimpl.h"
SECStatus
-SSL_ConfigServerSessionIDCache( int maxCacheEntries,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char * directory)
+SSL_ConfigServerSessionIDCache(int maxCacheEntries,
+ PRUint32 ssl2_timeout,
+ PRUint32 ssl3_timeout,
+ const char *directory)
{
- PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigServerSessionIDCache)");
+ PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigServerSessionIDCache)");
return SECFailure;
}
SECStatus
-SSL_ConfigMPServerSIDCache( int maxCacheEntries,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char * directory)
+SSL_ConfigMPServerSIDCache(int maxCacheEntries,
+ PRUint32 ssl2_timeout,
+ PRUint32 ssl3_timeout,
+ const char *directory)
{
- PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigMPServerSIDCache)");
+ PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigMPServerSIDCache)");
return SECFailure;
}
SECStatus
-SSL_InheritMPServerSIDCache(const char * envString)
+SSL_InheritMPServerSIDCache(const char *envString)
{
- PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_InheritMPServerSIDCache)");
+ PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_InheritMPServerSIDCache)");
return SECFailure;
}
PRBool
-ssl_GetWrappingKey( PRInt32 symWrapMechIndex,
- SSL3KEAType exchKeyType,
- SSLWrappedSymWrappingKey *wswk)
+ssl_GetWrappingKey(PRInt32 symWrapMechIndex,
+ SSL3KEAType exchKeyType,
+ SSLWrappedSymWrappingKey *wswk)
{
PRBool rv = PR_FALSE;
- PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_GetWrappingKey)");
+ PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_GetWrappingKey)");
return rv;
}
/* This is a kind of test-and-set. The caller passes in the new value it wants
* to set. This code tests the wrapped sym key entry in the shared memory.
- * If it is uninitialized, this function writes the caller's value into
- * the disk entry, and returns false.
- * Otherwise, it overwrites the caller's wswk with the value obtained from
- * the disk, and returns PR_TRUE.
- * This is all done while holding the locks/mutexes necessary to make
+ * If it is uninitialized, this function writes the caller's value into
+ * the disk entry, and returns false.
+ * Otherwise, it overwrites the caller's wswk with the value obtained from
+ * the disk, and returns PR_TRUE.
+ * This is all done while holding the locks/mutexes necessary to make
* the operation atomic.
*/
PRBool
ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
{
- PRBool rv = PR_FALSE;
+ PRBool rv = PR_FALSE;
PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_SetWrappingKey)");
return rv;
}
-PRUint32
+PRUint32
SSL_GetMaxServerCacheLocks(void)
{
PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_GetMaxServerCacheLocks)");
return -1;
}
-SECStatus
+SECStatus
SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
{
PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_SetMaxServerCacheLocks)");
diff --git a/chromium/net/third_party/nss/ssl/sslsock.c b/chromium/net/third_party/nss/ssl/sslsock.c
index 0a8fbf0fdcd..e82c9169341 100644
--- a/chromium/net/third_party/nss/ssl/sslsock.c
+++ b/chromium/net/third_party/nss/ssl/sslsock.c
@@ -17,46 +17,39 @@
#ifndef NO_PKCS11_BYPASS
#include "blapi.h"
#endif
-#include "pk11pub.h"
#include "nss.h"
#include "pk11pqg.h"
-/* This is a bodge to allow this code to be compiled against older NSS headers
- * that don't contain the TLS 1.2 changes. */
-#ifndef CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256
-#define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24)
-#endif
-
-#define SET_ERROR_CODE /* reminder */
-
-static const sslSocketOps ssl_default_ops = { /* No SSL. */
- ssl_DefConnect,
- NULL,
- ssl_DefBind,
- ssl_DefListen,
- ssl_DefShutdown,
- ssl_DefClose,
- ssl_DefRecv,
- ssl_DefSend,
- ssl_DefRead,
- ssl_DefWrite,
- ssl_DefGetpeername,
- ssl_DefGetsockname
+#define SET_ERROR_CODE /* reminder */
+
+static const sslSocketOps ssl_default_ops = { /* No SSL. */
+ ssl_DefConnect,
+ NULL,
+ ssl_DefBind,
+ ssl_DefListen,
+ ssl_DefShutdown,
+ ssl_DefClose,
+ ssl_DefRecv,
+ ssl_DefSend,
+ ssl_DefRead,
+ ssl_DefWrite,
+ ssl_DefGetpeername,
+ ssl_DefGetsockname
};
-static const sslSocketOps ssl_secure_ops = { /* SSL. */
- ssl_SecureConnect,
- NULL,
- ssl_DefBind,
- ssl_DefListen,
- ssl_SecureShutdown,
- ssl_SecureClose,
- ssl_SecureRecv,
- ssl_SecureSend,
- ssl_SecureRead,
- ssl_SecureWrite,
- ssl_DefGetpeername,
- ssl_DefGetsockname
+static const sslSocketOps ssl_secure_ops = { /* SSL. */
+ ssl_SecureConnect,
+ NULL,
+ ssl_DefBind,
+ ssl_DefListen,
+ ssl_SecureShutdown,
+ ssl_SecureClose,
+ ssl_SecureRecv,
+ ssl_SecureSend,
+ ssl_SecureRead,
+ ssl_SecureWrite,
+ ssl_DefGetpeername,
+ ssl_DefGetsockname
};
/*
@@ -64,36 +57,38 @@ static const sslSocketOps ssl_secure_ops = { /* SSL. */
*/
static sslOptions ssl_defaults = {
{ siBuffer, NULL, 0 }, /* nextProtoNego */
- PR_TRUE, /* useSecurity */
- PR_FALSE, /* useSocks */
- PR_FALSE, /* requestCertificate */
- 2, /* requireCertificate */
- PR_FALSE, /* handshakeAsClient */
- PR_FALSE, /* handshakeAsServer */
- PR_FALSE, /* enableSSL2 */ /* now defaults to off in NSS 3.13 */
- PR_FALSE, /* unusedBit9 */
- PR_FALSE, /* unusedBit10 */
- PR_FALSE, /* noCache */
- PR_FALSE, /* fdx */
- PR_FALSE, /* v2CompatibleHello */ /* now defaults to off in NSS 3.13 */
- PR_TRUE, /* detectRollBack */
- PR_FALSE, /* noStepDown */
- PR_FALSE, /* bypassPKCS11 */
- PR_FALSE, /* noLocks */
- PR_FALSE, /* enableSessionTickets */
- PR_FALSE, /* enableDeflate */
- 2, /* enableRenegotiation (default: requires extension) */
- PR_FALSE, /* requireSafeNegotiation */
- PR_FALSE, /* enableFalseStart */
- PR_TRUE, /* cbcRandomIV */
- PR_FALSE, /* enableOCSPStapling */
- PR_TRUE, /* enableNPN */
- PR_FALSE, /* enableALPN */
- PR_TRUE, /* reuseServerECDHEKey */
- PR_FALSE, /* enableFallbackSCSV */
- PR_TRUE, /* enableServerDhe */
- PR_FALSE, /* enableExtendedMS */
- PR_FALSE, /* enableSignedCertTimestamps */
+ PR_TRUE, /* useSecurity */
+ PR_FALSE, /* useSocks */
+ PR_FALSE, /* requestCertificate */
+ 2, /* requireCertificate */
+ PR_FALSE, /* handshakeAsClient */
+ PR_FALSE, /* handshakeAsServer */
+ PR_FALSE,
+ /* enableSSL2 */ /* now defaults to off in NSS 3.13 */
+ PR_FALSE, /* unusedBit9 */
+ PR_FALSE, /* unusedBit10 */
+ PR_FALSE, /* noCache */
+ PR_FALSE, /* fdx */
+ PR_FALSE,
+ /* v2CompatibleHello */ /* now defaults to off in NSS 3.13 */
+ PR_TRUE, /* detectRollBack */
+ PR_FALSE, /* noStepDown */
+ PR_FALSE, /* bypassPKCS11 */
+ PR_FALSE, /* noLocks */
+ PR_FALSE, /* enableSessionTickets */
+ PR_FALSE, /* enableDeflate */
+ 2, /* enableRenegotiation (default: requires extension) */
+ PR_FALSE, /* requireSafeNegotiation */
+ PR_FALSE, /* enableFalseStart */
+ PR_TRUE, /* cbcRandomIV */
+ PR_FALSE, /* enableOCSPStapling */
+ PR_TRUE, /* enableNPN */
+ PR_FALSE, /* enableALPN */
+ PR_TRUE, /* reuseServerECDHEKey */
+ PR_FALSE, /* enableFallbackSCSV */
+ PR_TRUE, /* enableServerDhe */
+ PR_FALSE, /* enableExtendedMS */
+ PR_FALSE, /* enableSignedCertTimestamps */
};
/*
@@ -109,24 +104,30 @@ static SSLVersionRange versions_defaults_datagram = {
SSL_LIBRARY_VERSION_TLS_1_2
};
-#define VERSIONS_DEFAULTS(variant) \
+#define VERSIONS_DEFAULTS(variant) \
(variant == ssl_variant_stream ? &versions_defaults_stream : \
- &versions_defaults_datagram)
-
-sslSessionIDLookupFunc ssl_sid_lookup;
-sslSessionIDCacheFunc ssl_sid_cache;
+ &versions_defaults_datagram)
+#define VERSIONS_POLICY_MIN(variant) \
+ (variant == ssl_variant_stream ? NSS_TLS_VERSION_MIN_POLICY : \
+ NSS_DTLS_VERSION_MIN_POLICY)
+#define VERSIONS_POLICY_MAX(variant) \
+ (variant == ssl_variant_stream ? NSS_TLS_VERSION_MAX_POLICY : \
+ NSS_DTLS_VERSION_MAX_POLICY)
+
+sslSessionIDLookupFunc ssl_sid_lookup;
+sslSessionIDCacheFunc ssl_sid_cache;
sslSessionIDUncacheFunc ssl_sid_uncache;
static PRBool ssl_inited = PR_FALSE;
static PRDescIdentity ssl_layer_id;
-PRBool locksEverDisabled; /* implicitly PR_FALSE */
-PRBool ssl_force_locks; /* implicitly PR_FALSE */
-int ssl_lock_readers = 1; /* default true. */
-char ssl_debug;
-char ssl_trace;
-FILE * ssl_trace_iob;
-FILE * ssl_keylog_iob;
+PRBool locksEverDisabled; /* implicitly PR_FALSE */
+PRBool ssl_force_locks; /* implicitly PR_FALSE */
+int ssl_lock_readers = 1; /* default true. */
+char ssl_debug;
+char ssl_trace;
+FILE *ssl_trace_iob;
+FILE *ssl_keylog_iob;
char lockStatus[] = "Locks are ENABLED. ";
#define LOCKSTATUS_OFFSET 10 /* offset of ENABLED */
@@ -139,10 +140,10 @@ static const PRUint16 srtpCiphers[] = {
/* forward declarations. */
static sslSocket *ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant variant);
-static SECStatus ssl_MakeLocks(sslSocket *ss);
-static void ssl_SetDefaultsFromEnvironment(void);
-static PRStatus ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack,
- PRDescIdentity id);
+static SECStatus ssl_MakeLocks(sslSocket *ss);
+static void ssl_SetDefaultsFromEnvironment(void);
+static PRStatus ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack,
+ PRDescIdentity id);
/************************************************************************/
@@ -214,31 +215,32 @@ ssl_DupSocket(sslSocket *os)
ss = ssl_NewSocket((PRBool)(!os->opt.noLocks), os->protocolVariant);
if (ss) {
- ss->opt = os->opt;
- ss->opt.useSocks = PR_FALSE;
- ss->vrange = os->vrange;
+ ss->opt = os->opt;
+ ss->opt.useSocks = PR_FALSE;
+ ss->vrange = os->vrange;
- ss->peerID = !os->peerID ? NULL : PORT_Strdup(os->peerID);
- ss->url = !os->url ? NULL : PORT_Strdup(os->url);
+ ss->peerID = !os->peerID ? NULL : PORT_Strdup(os->peerID);
+ ss->url = !os->url ? NULL : PORT_Strdup(os->url);
- ss->ops = os->ops;
+ ss->ops = os->ops;
ss->rTimeout = os->rTimeout;
ss->wTimeout = os->wTimeout;
ss->cTimeout = os->cTimeout;
ss->dbHandle = os->dbHandle;
/* copy ssl2&3 policy & prefs, even if it's not selected (yet) */
- ss->allowedByPolicy = os->allowedByPolicy;
- ss->maybeAllowedByPolicy= os->maybeAllowedByPolicy;
- ss->chosenPreference = os->chosenPreference;
+ ss->allowedByPolicy = os->allowedByPolicy;
+ ss->maybeAllowedByPolicy = os->maybeAllowedByPolicy;
+ ss->chosenPreference = os->chosenPreference;
PORT_Memcpy(ss->cipherSuites, os->cipherSuites, sizeof os->cipherSuites);
PORT_Memcpy(ss->ssl3.dtlsSRTPCiphers, os->ssl3.dtlsSRTPCiphers,
sizeof(PRUint16) * os->ssl3.dtlsSRTPCipherCount);
ss->ssl3.dtlsSRTPCipherCount = os->ssl3.dtlsSRTPCipherCount;
PORT_Memcpy(ss->ssl3.signatureAlgorithms, os->ssl3.signatureAlgorithms,
sizeof(ss->ssl3.signatureAlgorithms[0]) *
- os->ssl3.signatureAlgorithmCount);
+ os->ssl3.signatureAlgorithmCount);
ss->ssl3.signatureAlgorithmCount = os->ssl3.signatureAlgorithmCount;
+ ss->ssl3.downgradeCheckVersion = os->ssl3.downgradeCheckVersion;
ss->ssl3.dheWeakGroupEnabled = os->ssl3.dheWeakGroupEnabled;
ss->ssl3.numDHEGroups = os->ssl3.numDHEGroups;
@@ -255,74 +257,66 @@ ssl_DupSocket(sslSocket *os)
}
if (os->cipherSpecs) {
- ss->cipherSpecs = (unsigned char*)PORT_Alloc(os->sizeCipherSpecs);
+ ss->cipherSpecs = (unsigned char *)PORT_Alloc(os->sizeCipherSpecs);
if (ss->cipherSpecs)
PORT_Memcpy(ss->cipherSpecs, os->cipherSpecs,
os->sizeCipherSpecs);
- ss->sizeCipherSpecs = os->sizeCipherSpecs;
- ss->preferredCipher = os->preferredCipher;
+ ss->sizeCipherSpecs = os->sizeCipherSpecs;
+ ss->preferredCipher = os->preferredCipher;
} else {
- ss->cipherSpecs = NULL; /* produced lazily */
- ss->sizeCipherSpecs = 0;
- ss->preferredCipher = NULL;
+ ss->cipherSpecs = NULL; /* produced lazily */
+ ss->sizeCipherSpecs = 0;
+ ss->preferredCipher = NULL;
}
if (ss->opt.useSecurity) {
/* This int should be SSLKEAType, but CC on Irix complains,
* during the for loop.
*/
int i;
- sslServerCerts * oc = os->serverCerts;
- sslServerCerts * sc = ss->serverCerts;
+ sslServerCerts *oc = os->serverCerts;
+ sslServerCerts *sc = ss->serverCerts;
- for (i=kt_null; i < kt_kea_size; i++, oc++, sc++) {
+ for (i = kt_null; i < kt_kea_size; i++, oc++, sc++) {
if (oc->serverCert && oc->serverCertChain) {
- sc->serverCert = CERT_DupCertificate(oc->serverCert);
+ sc->serverCert = CERT_DupCertificate(oc->serverCert);
sc->serverCertChain = CERT_DupCertList(oc->serverCertChain);
if (!sc->serverCertChain)
goto loser;
} else {
- sc->serverCert = NULL;
+ sc->serverCert = NULL;
sc->serverCertChain = NULL;
}
- sc->serverKeyPair = oc->serverKeyPair ?
- ssl3_GetKeyPairRef(oc->serverKeyPair) : NULL;
+ sc->serverKeyPair = oc->serverKeyPair ? ssl3_GetKeyPairRef(oc->serverKeyPair)
+ : NULL;
if (oc->serverKeyPair && !sc->serverKeyPair)
goto loser;
sc->serverKeyBits = oc->serverKeyBits;
- ss->certStatusArray[i] = !os->certStatusArray[i] ? NULL :
- SECITEM_DupArray(NULL, os->certStatusArray[i]);
+ ss->certStatusArray[i] = !os->certStatusArray[i] ? NULL : SECITEM_DupArray(NULL, os->certStatusArray[i]);
}
- ss->stepDownKeyPair = !os->stepDownKeyPair ? NULL :
- ssl3_GetKeyPairRef(os->stepDownKeyPair);
- ss->ephemeralECDHKeyPair = !os->ephemeralECDHKeyPair ? NULL :
- ssl3_GetKeyPairRef(os->ephemeralECDHKeyPair);
- ss->dheKeyPair = !os->dheKeyPair ? NULL :
- ssl3_GetKeyPairRef(os->dheKeyPair);
+ ss->stepDownKeyPair = !os->stepDownKeyPair ? NULL : ssl3_GetKeyPairRef(os->stepDownKeyPair);
+ ss->ephemeralECDHKeyPair = !os->ephemeralECDHKeyPair ? NULL : ssl3_GetKeyPairRef(os->ephemeralECDHKeyPair);
+ ss->dheKeyPair = !os->dheKeyPair ? NULL : ssl3_GetKeyPairRef(os->dheKeyPair);
ss->dheParams = os->dheParams;
-/*
- * XXX the preceding CERT_ and SECKEY_ functions can fail and return NULL.
- * XXX We should detect this, and not just march on with NULL pointers.
- */
- ss->authCertificate = os->authCertificate;
- ss->authCertificateArg = os->authCertificateArg;
- ss->getClientAuthData = os->getClientAuthData;
- ss->getClientAuthDataArg = os->getClientAuthDataArg;
-#ifdef NSS_PLATFORM_CLIENT_AUTH
- ss->getPlatformClientAuthData = os->getPlatformClientAuthData;
- ss->getPlatformClientAuthDataArg = os->getPlatformClientAuthDataArg;
-#endif
- ss->sniSocketConfig = os->sniSocketConfig;
- ss->sniSocketConfigArg = os->sniSocketConfigArg;
- ss->handleBadCert = os->handleBadCert;
- ss->badCertArg = os->badCertArg;
- ss->handshakeCallback = os->handshakeCallback;
+ /*
+ * XXX the preceding CERT_ and SECKEY_ functions can fail and return NULL.
+ * XXX We should detect this, and not just march on with NULL pointers.
+ */
+ ss->authCertificate = os->authCertificate;
+ ss->authCertificateArg = os->authCertificateArg;
+ ss->getClientAuthData = os->getClientAuthData;
+ ss->getClientAuthDataArg = os->getClientAuthDataArg;
+ ss->sniSocketConfig = os->sniSocketConfig;
+ ss->sniSocketConfigArg = os->sniSocketConfigArg;
+ ss->handleBadCert = os->handleBadCert;
+ ss->badCertArg = os->badCertArg;
+ ss->handshakeCallback = os->handshakeCallback;
ss->handshakeCallbackData = os->handshakeCallbackData;
ss->canFalseStartCallback = os->canFalseStartCallback;
ss->canFalseStartCallbackData = os->canFalseStartCallbackData;
- ss->pkcs11PinArg = os->pkcs11PinArg;
- ss->getChannelID = os->getChannelID;
- ss->getChannelIDArg = os->getChannelIDArg;
+ ss->pkcs11PinArg = os->pkcs11PinArg;
+ ss->getChannelID = os->getChannelID;
+ ss->getChannelIDArg = os->getChannelIDArg;
/* Create security data */
rv = ssl_CopySecurityInfo(ss, os);
@@ -380,7 +374,7 @@ ssl_DestroySocketContents(sslSocket *ss)
/* "i" should be of type SSLKEAType, but CC on IRIX complains during
* the for loop.
*/
- int i;
+ int i;
/* Free up socket */
ssl_DestroySecurityInfo(&ss->sec);
@@ -394,16 +388,16 @@ ssl_DestroySocketContents(sslSocket *ss)
if (ss->peerID != NULL)
PORT_Free(ss->peerID);
if (ss->url != NULL)
- PORT_Free((void *)ss->url); /* CONST */
+ PORT_Free((void *)ss->url); /* CONST */
if (ss->cipherSpecs) {
PORT_Free(ss->cipherSpecs);
- ss->cipherSpecs = NULL;
+ ss->cipherSpecs = NULL;
ss->sizeCipherSpecs = 0;
}
/* Clean up server configuration */
- for (i=kt_null; i < kt_kea_size; i++) {
- sslServerCerts * sc = ss->serverCerts + i;
+ for (i = kt_null; i < kt_kea_size; i++) {
+ sslServerCerts *sc = ss->serverCerts + i;
if (sc->serverCert != NULL)
CERT_DestroyCertificate(sc->serverCert);
if (sc->serverCertChain != NULL)
@@ -414,6 +408,9 @@ ssl_DestroySocketContents(sslSocket *ss)
SECITEM_FreeArray(ss->certStatusArray[i], PR_TRUE);
ss->certStatusArray[i] = NULL;
}
+ if (ss->signedCertTimestamps[i].data) {
+ SECITEM_FreeItem(&ss->signedCertTimestamps[i], PR_FALSE);
+ }
}
if (ss->stepDownKeyPair) {
ssl3_FreeKeyPair(ss->stepDownKeyPair);
@@ -440,11 +437,11 @@ ssl_DestroySocketContents(sslSocket *ss)
void
ssl_FreeSocket(sslSocket *ss)
{
-/* Get every lock you can imagine!
-** Caller already holds these:
-** SSL_LOCK_READER(ss);
-** SSL_LOCK_WRITER(ss);
-*/
+ /* Get every lock you can imagine!
+ ** Caller already holds these:
+ ** SSL_LOCK_READER(ss);
+ ** SSL_LOCK_WRITER(ss);
+ */
ssl_Get1stHandshakeLock(ss);
ssl_GetRecvBufLock(ss);
ssl_GetSSL3HandshakeLock(ss);
@@ -475,15 +472,15 @@ ssl_FreeSocket(sslSocket *ss)
SECStatus
ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled)
{
- PRFileDesc * osfd = ss->fd->lower;
- SECStatus rv = SECFailure;
+ PRFileDesc *osfd = ss->fd->lower;
+ SECStatus rv = SECFailure;
PRSocketOptionData opt;
- opt.option = PR_SockOpt_NoDelay;
+ opt.option = PR_SockOpt_NoDelay;
opt.value.no_delay = (PRBool)!enabled;
if (osfd->methods->setsocketoption) {
- rv = (SECStatus) osfd->methods->setsocketoption(osfd, &opt);
+ rv = (SECStatus)osfd->methods->setsocketoption(osfd, &opt);
} else {
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
}
@@ -501,7 +498,7 @@ ssl_ChooseOps(sslSocket *ss)
static SECStatus
PrepareSocket(sslSocket *ss)
{
- SECStatus rv = SECSuccess;
+ SECStatus rv = SECSuccess;
ssl_ChooseOps(ss);
return rv;
@@ -517,7 +514,8 @@ SSL_Enable(PRFileDesc *fd, int which, PRBool on)
static const PRCallOnceType pristineCallOnce;
static PRCallOnceType setupBypassOnce;
-static SECStatus SSL_BypassShutdown(void* appData, void* nssData)
+static SECStatus
+SSL_BypassShutdown(void *appData, void *nssData)
{
/* unload freeBL shared library from memory */
BL_Unload();
@@ -525,7 +523,8 @@ static SECStatus SSL_BypassShutdown(void* appData, void* nssData)
return SECSuccess;
}
-static PRStatus SSL_BypassRegisterShutdown(void)
+static PRStatus
+SSL_BypassRegisterShutdown(void)
{
SECStatus rv = NSS_RegisterShutdown(SSL_BypassShutdown, NULL);
PORT_Assert(SECSuccess == rv);
@@ -533,7 +532,8 @@ static PRStatus SSL_BypassRegisterShutdown(void)
}
#endif
-static PRStatus SSL_BypassSetup(void)
+static PRStatus
+SSL_BypassSetup(void)
{
#ifdef NO_PKCS11_BYPASS
/* Guarantee binary compatibility */
@@ -543,12 +543,22 @@ static PRStatus SSL_BypassSetup(void)
#endif
}
+static PRBool ssl_VersionIsSupportedByPolicy(
+ SSLProtocolVariant protocolVariant, SSL3ProtocolVersion version);
+
/* Implements the semantics for SSL_OptionSet(SSL_ENABLE_TLS, on) described in
* ssl.h in the section "SSL version range setting API".
*/
static void
ssl_EnableTLS(SSLVersionRange *vrange, PRBool on)
{
+ if (on) {
+ /* don't turn it on if tls1.0 disallowed by by policy */
+ if (!ssl_VersionIsSupportedByPolicy(ssl_variant_stream,
+ SSL_LIBRARY_VERSION_TLS_1_0)) {
+ return;
+ }
+ }
if (SSL3_ALL_VERSIONS_DISABLED(vrange)) {
if (on) {
vrange->min = SSL_LIBRARY_VERSION_TLS_1_0;
@@ -579,7 +589,14 @@ ssl_EnableTLS(SSLVersionRange *vrange, PRBool on)
static void
ssl_EnableSSL3(SSLVersionRange *vrange, PRBool on)
{
- if (SSL3_ALL_VERSIONS_DISABLED(vrange)) {
+ if (on) {
+ /* don't turn it on if ssl3 disallowed by by policy */
+ if (!ssl_VersionIsSupportedByPolicy(ssl_variant_stream,
+ SSL_LIBRARY_VERSION_3_0)) {
+ return;
+ }
+ }
+ if (SSL3_ALL_VERSIONS_DISABLED(vrange)) {
if (on) {
vrange->min = SSL_LIBRARY_VERSION_3_0;
vrange->max = SSL_LIBRARY_VERSION_3_0;
@@ -587,13 +604,13 @@ ssl_EnableSSL3(SSLVersionRange *vrange, PRBool on)
return;
}
- if (on) {
+ if (on) {
/* Expand the range of enabled versions to include SSL 3.0. We know
* SSL 3.0 or some version of TLS is already enabled at this point, so
* we don't need to change vrange->max.
*/
vrange->min = SSL_LIBRARY_VERSION_3_0;
- } else {
+ } else {
/* Disable SSL 3.0, leaving TLS unaffected. */
if (vrange->max > SSL_LIBRARY_VERSION_3_0) {
vrange->min = PR_MAX(vrange->min, SSL_LIBRARY_VERSION_TLS_1_0);
@@ -609,8 +626,8 @@ SECStatus
SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
{
sslSocket *ss = ssl_FindSocket(fd);
- SECStatus rv = SECSuccess;
- PRBool holdingLocks;
+ SECStatus rv = SECSuccess;
+ PRBool holdingLocks;
if (!ss) {
SSL_DBG(("%d: SSL[%d]: bad socket in Enable", SSL_GETPID(), fd));
@@ -622,235 +639,242 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
ssl_GetSSL3HandshakeLock(ss);
switch (which) {
- case SSL_SOCKS:
- ss->opt.useSocks = PR_FALSE;
- rv = PrepareSocket(ss);
- if (on) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure;
- }
- break;
-
- case SSL_SECURITY:
- ss->opt.useSecurity = on;
- rv = PrepareSocket(ss);
- break;
-
- case SSL_REQUEST_CERTIFICATE:
- ss->opt.requestCertificate = on;
- break;
+ case SSL_SOCKS:
+ ss->opt.useSocks = PR_FALSE;
+ rv = PrepareSocket(ss);
+ if (on) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+ }
+ break;
- case SSL_REQUIRE_CERTIFICATE:
- ss->opt.requireCertificate = on;
- break;
+ case SSL_SECURITY:
+ ss->opt.useSecurity = on;
+ rv = PrepareSocket(ss);
+ break;
- case SSL_HANDSHAKE_AS_CLIENT:
- if ( ss->opt.handshakeAsServer && on ) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure;
+ case SSL_REQUEST_CERTIFICATE:
+ ss->opt.requestCertificate = on;
break;
- }
- ss->opt.handshakeAsClient = on;
- break;
- case SSL_HANDSHAKE_AS_SERVER:
- if ( ss->opt.handshakeAsClient && on ) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure;
+ case SSL_REQUIRE_CERTIFICATE:
+ ss->opt.requireCertificate = on;
break;
- }
- ss->opt.handshakeAsServer = on;
- break;
- case SSL_ENABLE_TLS:
- if (IS_DTLS(ss)) {
- if (on) {
+ case SSL_HANDSHAKE_AS_CLIENT:
+ if (ss->opt.handshakeAsServer && on) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure; /* not allowed */
+ rv = SECFailure;
+ break;
}
+ ss->opt.handshakeAsClient = on;
break;
- }
- ssl_EnableTLS(&ss->vrange, on);
- ss->preferredCipher = NULL;
- if (ss->cipherSpecs) {
- PORT_Free(ss->cipherSpecs);
- ss->cipherSpecs = NULL;
- ss->sizeCipherSpecs = 0;
- }
- break;
- case SSL_ENABLE_SSL3:
- if (IS_DTLS(ss)) {
- if (on) {
+ case SSL_HANDSHAKE_AS_SERVER:
+ if (ss->opt.handshakeAsClient && on) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure; /* not allowed */
+ rv = SECFailure;
+ break;
}
+ ss->opt.handshakeAsServer = on;
break;
- }
- ssl_EnableSSL3(&ss->vrange, on);
- ss->preferredCipher = NULL;
- if (ss->cipherSpecs) {
- PORT_Free(ss->cipherSpecs);
- ss->cipherSpecs = NULL;
- ss->sizeCipherSpecs = 0;
- }
- break;
- case SSL_ENABLE_SSL2:
- if (IS_DTLS(ss)) {
- if (on) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure; /* not allowed */
+ case SSL_ENABLE_TLS:
+ if (IS_DTLS(ss)) {
+ if (on) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure; /* not allowed */
+ }
+ break;
+ }
+ ssl_EnableTLS(&ss->vrange, on);
+ ss->preferredCipher = NULL;
+ if (ss->cipherSpecs) {
+ PORT_Free(ss->cipherSpecs);
+ ss->cipherSpecs = NULL;
+ ss->sizeCipherSpecs = 0;
}
break;
- }
- ss->opt.enableSSL2 = on;
- if (on) {
- ss->opt.v2CompatibleHello = on;
- }
- ss->preferredCipher = NULL;
- if (ss->cipherSpecs) {
- PORT_Free(ss->cipherSpecs);
- ss->cipherSpecs = NULL;
- ss->sizeCipherSpecs = 0;
- }
- break;
-
- case SSL_NO_CACHE:
- ss->opt.noCache = on;
- break;
- case SSL_ENABLE_FDX:
- if (on && ss->opt.noLocks) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure;
- }
- ss->opt.fdx = on;
- break;
+ case SSL_ENABLE_SSL3:
+ if (IS_DTLS(ss)) {
+ if (on) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure; /* not allowed */
+ }
+ break;
+ }
+ ssl_EnableSSL3(&ss->vrange, on);
+ ss->preferredCipher = NULL;
+ if (ss->cipherSpecs) {
+ PORT_Free(ss->cipherSpecs);
+ ss->cipherSpecs = NULL;
+ ss->sizeCipherSpecs = 0;
+ }
+ break;
- case SSL_V2_COMPATIBLE_HELLO:
- if (IS_DTLS(ss)) {
+ case SSL_ENABLE_SSL2:
+ if (IS_DTLS(ss)) {
+ if (on) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure; /* not allowed */
+ }
+ break;
+ }
+ if (on) {
+ /* don't turn it on if ssl2 disallowed by by policy */
+ if (!ssl_VersionIsSupportedByPolicy(ssl_variant_stream,
+ SSL_LIBRARY_VERSION_2)) {
+ break;
+ }
+ }
+ ss->opt.enableSSL2 = on;
if (on) {
+ ss->opt.v2CompatibleHello = on;
+ }
+ ss->preferredCipher = NULL;
+ if (ss->cipherSpecs) {
+ PORT_Free(ss->cipherSpecs);
+ ss->cipherSpecs = NULL;
+ ss->sizeCipherSpecs = 0;
+ }
+ break;
+
+ case SSL_NO_CACHE:
+ ss->opt.noCache = on;
+ break;
+
+ case SSL_ENABLE_FDX:
+ if (on && ss->opt.noLocks) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure; /* not allowed */
+ rv = SECFailure;
}
+ ss->opt.fdx = on;
break;
- }
- ss->opt.v2CompatibleHello = on;
- if (!on) {
- ss->opt.enableSSL2 = on;
- }
- break;
- case SSL_ROLLBACK_DETECTION:
- ss->opt.detectRollBack = on;
- break;
+ case SSL_V2_COMPATIBLE_HELLO:
+ if (IS_DTLS(ss)) {
+ if (on) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure; /* not allowed */
+ }
+ break;
+ }
+ ss->opt.v2CompatibleHello = on;
+ if (!on) {
+ ss->opt.enableSSL2 = on;
+ }
+ break;
- case SSL_NO_STEP_DOWN:
- ss->opt.noStepDown = on;
- if (on)
- SSL_DisableExportCipherSuites(fd);
- break;
+ case SSL_ROLLBACK_DETECTION:
+ ss->opt.detectRollBack = on;
+ break;
- case SSL_BYPASS_PKCS11:
- if (ss->handshakeBegun) {
- PORT_SetError(PR_INVALID_STATE_ERROR);
- rv = SECFailure;
- } else {
- if (PR_FALSE != on) {
- if (PR_SUCCESS == SSL_BypassSetup() ) {
+ case SSL_NO_STEP_DOWN:
+ ss->opt.noStepDown = on;
+ if (on)
+ SSL_DisableExportCipherSuites(fd);
+ break;
+
+ case SSL_BYPASS_PKCS11:
+ if (ss->handshakeBegun) {
+ PORT_SetError(PR_INVALID_STATE_ERROR);
+ rv = SECFailure;
+ } else {
+ if (PR_FALSE != on) {
+ if (PR_SUCCESS == SSL_BypassSetup()) {
#ifdef NO_PKCS11_BYPASS
- ss->opt.bypassPKCS11 = PR_FALSE;
+ ss->opt.bypassPKCS11 = PR_FALSE;
#else
- ss->opt.bypassPKCS11 = on;
+ ss->opt.bypassPKCS11 = on;
#endif
+ } else {
+ rv = SECFailure;
+ }
} else {
- rv = SECFailure;
+ ss->opt.bypassPKCS11 = PR_FALSE;
}
- } else {
- ss->opt.bypassPKCS11 = PR_FALSE;
}
- }
- break;
+ break;
- case SSL_NO_LOCKS:
- if (on && ss->opt.fdx) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure;
- }
- if (on && ssl_force_locks)
- on = PR_FALSE; /* silent override */
- ss->opt.noLocks = on;
- if (on) {
- locksEverDisabled = PR_TRUE;
- strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED.");
- } else if (!holdingLocks) {
- rv = ssl_MakeLocks(ss);
- if (rv != SECSuccess) {
- ss->opt.noLocks = PR_TRUE;
+ case SSL_NO_LOCKS:
+ if (on && ss->opt.fdx) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
}
- }
- break;
+ if (on && ssl_force_locks)
+ on = PR_FALSE; /* silent override */
+ ss->opt.noLocks = on;
+ if (on) {
+ locksEverDisabled = PR_TRUE;
+ strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED.");
+ } else if (!holdingLocks) {
+ rv = ssl_MakeLocks(ss);
+ if (rv != SECSuccess) {
+ ss->opt.noLocks = PR_TRUE;
+ }
+ }
+ break;
- case SSL_ENABLE_SESSION_TICKETS:
- ss->opt.enableSessionTickets = on;
- break;
+ case SSL_ENABLE_SESSION_TICKETS:
+ ss->opt.enableSessionTickets = on;
+ break;
- case SSL_ENABLE_DEFLATE:
- ss->opt.enableDeflate = on;
- break;
+ case SSL_ENABLE_DEFLATE:
+ ss->opt.enableDeflate = on;
+ break;
- case SSL_ENABLE_RENEGOTIATION:
- ss->opt.enableRenegotiation = on;
- break;
+ case SSL_ENABLE_RENEGOTIATION:
+ ss->opt.enableRenegotiation = on;
+ break;
- case SSL_REQUIRE_SAFE_NEGOTIATION:
- ss->opt.requireSafeNegotiation = on;
- break;
+ case SSL_REQUIRE_SAFE_NEGOTIATION:
+ ss->opt.requireSafeNegotiation = on;
+ break;
- case SSL_ENABLE_FALSE_START:
- ss->opt.enableFalseStart = on;
- break;
+ case SSL_ENABLE_FALSE_START:
+ ss->opt.enableFalseStart = on;
+ break;
- case SSL_CBC_RANDOM_IV:
- ss->opt.cbcRandomIV = on;
- break;
+ case SSL_CBC_RANDOM_IV:
+ ss->opt.cbcRandomIV = on;
+ break;
- case SSL_ENABLE_OCSP_STAPLING:
- ss->opt.enableOCSPStapling = on;
- break;
+ case SSL_ENABLE_OCSP_STAPLING:
+ ss->opt.enableOCSPStapling = on;
+ break;
- case SSL_ENABLE_NPN:
- ss->opt.enableNPN = on;
- break;
+ case SSL_ENABLE_NPN:
+ ss->opt.enableNPN = on;
+ break;
- case SSL_ENABLE_ALPN:
- ss->opt.enableALPN = on;
- break;
+ case SSL_ENABLE_ALPN:
+ ss->opt.enableALPN = on;
+ break;
- case SSL_REUSE_SERVER_ECDHE_KEY:
- ss->opt.reuseServerECDHEKey = on;
- break;
+ case SSL_REUSE_SERVER_ECDHE_KEY:
+ ss->opt.reuseServerECDHEKey = on;
+ break;
- case SSL_ENABLE_FALLBACK_SCSV:
- ss->opt.enableFallbackSCSV = on;
- break;
+ case SSL_ENABLE_FALLBACK_SCSV:
+ ss->opt.enableFallbackSCSV = on;
+ break;
- case SSL_ENABLE_SERVER_DHE:
- ss->opt.enableServerDhe = on;
- break;
+ case SSL_ENABLE_SERVER_DHE:
+ ss->opt.enableServerDhe = on;
+ break;
- case SSL_ENABLE_EXTENDED_MASTER_SECRET:
- ss->opt.enableExtendedMS = on;
- break;
+ case SSL_ENABLE_EXTENDED_MASTER_SECRET:
+ ss->opt.enableExtendedMS = on;
+ break;
- case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
- ss->opt.enableSignedCertTimestamps = on;
- break;
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ ss->opt.enableSignedCertTimestamps = on;
+ break;
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
}
/* We can't use the macros for releasing the locks here,
@@ -870,8 +894,8 @@ SECStatus
SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
{
sslSocket *ss = ssl_FindSocket(fd);
- SECStatus rv = SECSuccess;
- PRBool on = PR_FALSE;
+ SECStatus rv = SECSuccess;
+ PRBool on = PR_FALSE;
if (!pOn) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -887,52 +911,100 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
ssl_GetSSL3HandshakeLock(ss);
switch (which) {
- case SSL_SOCKS: on = PR_FALSE; break;
- case SSL_SECURITY: on = ss->opt.useSecurity; break;
- case SSL_REQUEST_CERTIFICATE: on = ss->opt.requestCertificate; break;
- case SSL_REQUIRE_CERTIFICATE: on = ss->opt.requireCertificate; break;
- case SSL_HANDSHAKE_AS_CLIENT: on = ss->opt.handshakeAsClient; break;
- case SSL_HANDSHAKE_AS_SERVER: on = ss->opt.handshakeAsServer; break;
- case SSL_ENABLE_TLS:
- on = ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_0;
- break;
- case SSL_ENABLE_SSL3:
- on = ss->vrange.min == SSL_LIBRARY_VERSION_3_0;
- break;
- case SSL_ENABLE_SSL2: on = ss->opt.enableSSL2; break;
- case SSL_NO_CACHE: on = ss->opt.noCache; break;
- case SSL_ENABLE_FDX: on = ss->opt.fdx; break;
- case SSL_V2_COMPATIBLE_HELLO: on = ss->opt.v2CompatibleHello; break;
- case SSL_ROLLBACK_DETECTION: on = ss->opt.detectRollBack; break;
- case SSL_NO_STEP_DOWN: on = ss->opt.noStepDown; break;
- case SSL_BYPASS_PKCS11: on = ss->opt.bypassPKCS11; break;
- case SSL_NO_LOCKS: on = ss->opt.noLocks; break;
- case SSL_ENABLE_SESSION_TICKETS:
- on = ss->opt.enableSessionTickets;
- break;
- case SSL_ENABLE_DEFLATE: on = ss->opt.enableDeflate; break;
- case SSL_ENABLE_RENEGOTIATION:
- on = ss->opt.enableRenegotiation; break;
- case SSL_REQUIRE_SAFE_NEGOTIATION:
- on = ss->opt.requireSafeNegotiation; break;
- case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break;
- case SSL_CBC_RANDOM_IV: on = ss->opt.cbcRandomIV; break;
- case SSL_ENABLE_OCSP_STAPLING: on = ss->opt.enableOCSPStapling; break;
- case SSL_ENABLE_NPN: on = ss->opt.enableNPN; break;
- case SSL_ENABLE_ALPN: on = ss->opt.enableALPN; break;
- case SSL_REUSE_SERVER_ECDHE_KEY:
- on = ss->opt.reuseServerECDHEKey; break;
- case SSL_ENABLE_FALLBACK_SCSV: on = ss->opt.enableFallbackSCSV; break;
- case SSL_ENABLE_SERVER_DHE: on = ss->opt.enableServerDhe; break;
- case SSL_ENABLE_EXTENDED_MASTER_SECRET:
- on = ss->opt.enableExtendedMS; break;
- case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
- on = ss->opt.enableSignedCertTimestamps;
- break;
-
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure;
+ case SSL_SOCKS:
+ on = PR_FALSE;
+ break;
+ case SSL_SECURITY:
+ on = ss->opt.useSecurity;
+ break;
+ case SSL_REQUEST_CERTIFICATE:
+ on = ss->opt.requestCertificate;
+ break;
+ case SSL_REQUIRE_CERTIFICATE:
+ on = ss->opt.requireCertificate;
+ break;
+ case SSL_HANDSHAKE_AS_CLIENT:
+ on = ss->opt.handshakeAsClient;
+ break;
+ case SSL_HANDSHAKE_AS_SERVER:
+ on = ss->opt.handshakeAsServer;
+ break;
+ case SSL_ENABLE_TLS:
+ on = ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_0;
+ break;
+ case SSL_ENABLE_SSL3:
+ on = ss->vrange.min == SSL_LIBRARY_VERSION_3_0;
+ break;
+ case SSL_ENABLE_SSL2:
+ on = ss->opt.enableSSL2;
+ break;
+ case SSL_NO_CACHE:
+ on = ss->opt.noCache;
+ break;
+ case SSL_ENABLE_FDX:
+ on = ss->opt.fdx;
+ break;
+ case SSL_V2_COMPATIBLE_HELLO:
+ on = ss->opt.v2CompatibleHello;
+ break;
+ case SSL_ROLLBACK_DETECTION:
+ on = ss->opt.detectRollBack;
+ break;
+ case SSL_NO_STEP_DOWN:
+ on = ss->opt.noStepDown;
+ break;
+ case SSL_BYPASS_PKCS11:
+ on = ss->opt.bypassPKCS11;
+ break;
+ case SSL_NO_LOCKS:
+ on = ss->opt.noLocks;
+ break;
+ case SSL_ENABLE_SESSION_TICKETS:
+ on = ss->opt.enableSessionTickets;
+ break;
+ case SSL_ENABLE_DEFLATE:
+ on = ss->opt.enableDeflate;
+ break;
+ case SSL_ENABLE_RENEGOTIATION:
+ on = ss->opt.enableRenegotiation;
+ break;
+ case SSL_REQUIRE_SAFE_NEGOTIATION:
+ on = ss->opt.requireSafeNegotiation;
+ break;
+ case SSL_ENABLE_FALSE_START:
+ on = ss->opt.enableFalseStart;
+ break;
+ case SSL_CBC_RANDOM_IV:
+ on = ss->opt.cbcRandomIV;
+ break;
+ case SSL_ENABLE_OCSP_STAPLING:
+ on = ss->opt.enableOCSPStapling;
+ break;
+ case SSL_ENABLE_NPN:
+ on = ss->opt.enableNPN;
+ break;
+ case SSL_ENABLE_ALPN:
+ on = ss->opt.enableALPN;
+ break;
+ case SSL_REUSE_SERVER_ECDHE_KEY:
+ on = ss->opt.reuseServerECDHEKey;
+ break;
+ case SSL_ENABLE_FALLBACK_SCSV:
+ on = ss->opt.enableFallbackSCSV;
+ break;
+ case SSL_ENABLE_SERVER_DHE:
+ on = ss->opt.enableServerDhe;
+ break;
+ case SSL_ENABLE_EXTENDED_MASTER_SECRET:
+ on = ss->opt.enableExtendedMS;
+ break;
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ on = ss->opt.enableSignedCertTimestamps;
+ break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
}
ssl_ReleaseSSL3HandshakeLock(ss);
@@ -945,8 +1017,8 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
SECStatus
SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
{
- SECStatus rv = SECSuccess;
- PRBool on = PR_FALSE;
+ SECStatus rv = SECSuccess;
+ PRBool on = PR_FALSE;
if (!pOn) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -956,61 +1028,100 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
ssl_SetDefaultsFromEnvironment();
switch (which) {
- case SSL_SOCKS: on = PR_FALSE; break;
- case SSL_SECURITY: on = ssl_defaults.useSecurity; break;
- case SSL_REQUEST_CERTIFICATE: on = ssl_defaults.requestCertificate; break;
- case SSL_REQUIRE_CERTIFICATE: on = ssl_defaults.requireCertificate; break;
- case SSL_HANDSHAKE_AS_CLIENT: on = ssl_defaults.handshakeAsClient; break;
- case SSL_HANDSHAKE_AS_SERVER: on = ssl_defaults.handshakeAsServer; break;
- case SSL_ENABLE_TLS:
- on = versions_defaults_stream.max >= SSL_LIBRARY_VERSION_TLS_1_0;
- break;
- case SSL_ENABLE_SSL3:
- on = versions_defaults_stream.min == SSL_LIBRARY_VERSION_3_0;
- break;
- case SSL_ENABLE_SSL2: on = ssl_defaults.enableSSL2; break;
- case SSL_NO_CACHE: on = ssl_defaults.noCache; break;
- case SSL_ENABLE_FDX: on = ssl_defaults.fdx; break;
- case SSL_V2_COMPATIBLE_HELLO: on = ssl_defaults.v2CompatibleHello; break;
- case SSL_ROLLBACK_DETECTION: on = ssl_defaults.detectRollBack; break;
- case SSL_NO_STEP_DOWN: on = ssl_defaults.noStepDown; break;
- case SSL_BYPASS_PKCS11: on = ssl_defaults.bypassPKCS11; break;
- case SSL_NO_LOCKS: on = ssl_defaults.noLocks; break;
- case SSL_ENABLE_SESSION_TICKETS:
- on = ssl_defaults.enableSessionTickets;
- break;
- case SSL_ENABLE_DEFLATE: on = ssl_defaults.enableDeflate; break;
- case SSL_ENABLE_RENEGOTIATION:
- on = ssl_defaults.enableRenegotiation; break;
- case SSL_REQUIRE_SAFE_NEGOTIATION:
- on = ssl_defaults.requireSafeNegotiation;
- break;
- case SSL_ENABLE_FALSE_START: on = ssl_defaults.enableFalseStart; break;
- case SSL_CBC_RANDOM_IV: on = ssl_defaults.cbcRandomIV; break;
- case SSL_ENABLE_OCSP_STAPLING:
- on = ssl_defaults.enableOCSPStapling;
- break;
- case SSL_ENABLE_NPN: on = ssl_defaults.enableNPN; break;
- case SSL_ENABLE_ALPN: on = ssl_defaults.enableALPN; break;
- case SSL_REUSE_SERVER_ECDHE_KEY:
- on = ssl_defaults.reuseServerECDHEKey;
- break;
- case SSL_ENABLE_FALLBACK_SCSV:
- on = ssl_defaults.enableFallbackSCSV;
- break;
- case SSL_ENABLE_SERVER_DHE:
- on = ssl_defaults.enableServerDhe;
- break;
- case SSL_ENABLE_EXTENDED_MASTER_SECRET:
- on = ssl_defaults.enableExtendedMS;
- break;
- case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
- on = ssl_defaults.enableSignedCertTimestamps;
- break;
-
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- rv = SECFailure;
+ case SSL_SOCKS:
+ on = PR_FALSE;
+ break;
+ case SSL_SECURITY:
+ on = ssl_defaults.useSecurity;
+ break;
+ case SSL_REQUEST_CERTIFICATE:
+ on = ssl_defaults.requestCertificate;
+ break;
+ case SSL_REQUIRE_CERTIFICATE:
+ on = ssl_defaults.requireCertificate;
+ break;
+ case SSL_HANDSHAKE_AS_CLIENT:
+ on = ssl_defaults.handshakeAsClient;
+ break;
+ case SSL_HANDSHAKE_AS_SERVER:
+ on = ssl_defaults.handshakeAsServer;
+ break;
+ case SSL_ENABLE_TLS:
+ on = versions_defaults_stream.max >= SSL_LIBRARY_VERSION_TLS_1_0;
+ break;
+ case SSL_ENABLE_SSL3:
+ on = versions_defaults_stream.min == SSL_LIBRARY_VERSION_3_0;
+ break;
+ case SSL_ENABLE_SSL2:
+ on = ssl_defaults.enableSSL2;
+ break;
+ case SSL_NO_CACHE:
+ on = ssl_defaults.noCache;
+ break;
+ case SSL_ENABLE_FDX:
+ on = ssl_defaults.fdx;
+ break;
+ case SSL_V2_COMPATIBLE_HELLO:
+ on = ssl_defaults.v2CompatibleHello;
+ break;
+ case SSL_ROLLBACK_DETECTION:
+ on = ssl_defaults.detectRollBack;
+ break;
+ case SSL_NO_STEP_DOWN:
+ on = ssl_defaults.noStepDown;
+ break;
+ case SSL_BYPASS_PKCS11:
+ on = ssl_defaults.bypassPKCS11;
+ break;
+ case SSL_NO_LOCKS:
+ on = ssl_defaults.noLocks;
+ break;
+ case SSL_ENABLE_SESSION_TICKETS:
+ on = ssl_defaults.enableSessionTickets;
+ break;
+ case SSL_ENABLE_DEFLATE:
+ on = ssl_defaults.enableDeflate;
+ break;
+ case SSL_ENABLE_RENEGOTIATION:
+ on = ssl_defaults.enableRenegotiation;
+ break;
+ case SSL_REQUIRE_SAFE_NEGOTIATION:
+ on = ssl_defaults.requireSafeNegotiation;
+ break;
+ case SSL_ENABLE_FALSE_START:
+ on = ssl_defaults.enableFalseStart;
+ break;
+ case SSL_CBC_RANDOM_IV:
+ on = ssl_defaults.cbcRandomIV;
+ break;
+ case SSL_ENABLE_OCSP_STAPLING:
+ on = ssl_defaults.enableOCSPStapling;
+ break;
+ case SSL_ENABLE_NPN:
+ on = ssl_defaults.enableNPN;
+ break;
+ case SSL_ENABLE_ALPN:
+ on = ssl_defaults.enableALPN;
+ break;
+ case SSL_REUSE_SERVER_ECDHE_KEY:
+ on = ssl_defaults.reuseServerECDHEKey;
+ break;
+ case SSL_ENABLE_FALLBACK_SCSV:
+ on = ssl_defaults.enableFallbackSCSV;
+ break;
+ case SSL_ENABLE_SERVER_DHE:
+ on = ssl_defaults.enableServerDhe;
+ break;
+ case SSL_ENABLE_EXTENDED_MASTER_SECRET:
+ on = ssl_defaults.enableExtendedMS;
+ break;
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ on = ssl_defaults.enableSignedCertTimestamps;
+ break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
}
*pOn = on;
@@ -1036,175 +1147,182 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
ssl_SetDefaultsFromEnvironment();
switch (which) {
- case SSL_SOCKS:
- ssl_defaults.useSocks = PR_FALSE;
- if (on) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
- break;
+ case SSL_SOCKS:
+ ssl_defaults.useSocks = PR_FALSE;
+ if (on) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ break;
- case SSL_SECURITY:
- ssl_defaults.useSecurity = on;
- break;
+ case SSL_SECURITY:
+ ssl_defaults.useSecurity = on;
+ break;
- case SSL_REQUEST_CERTIFICATE:
- ssl_defaults.requestCertificate = on;
- break;
+ case SSL_REQUEST_CERTIFICATE:
+ ssl_defaults.requestCertificate = on;
+ break;
- case SSL_REQUIRE_CERTIFICATE:
- ssl_defaults.requireCertificate = on;
- break;
+ case SSL_REQUIRE_CERTIFICATE:
+ ssl_defaults.requireCertificate = on;
+ break;
- case SSL_HANDSHAKE_AS_CLIENT:
- if ( ssl_defaults.handshakeAsServer && on ) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
- ssl_defaults.handshakeAsClient = on;
- break;
+ case SSL_HANDSHAKE_AS_CLIENT:
+ if (ssl_defaults.handshakeAsServer && on) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ ssl_defaults.handshakeAsClient = on;
+ break;
- case SSL_HANDSHAKE_AS_SERVER:
- if ( ssl_defaults.handshakeAsClient && on ) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
- ssl_defaults.handshakeAsServer = on;
- break;
+ case SSL_HANDSHAKE_AS_SERVER:
+ if (ssl_defaults.handshakeAsClient && on) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ ssl_defaults.handshakeAsServer = on;
+ break;
- case SSL_ENABLE_TLS:
- ssl_EnableTLS(&versions_defaults_stream, on);
- break;
+ case SSL_ENABLE_TLS:
+ ssl_EnableTLS(&versions_defaults_stream, on);
+ break;
- case SSL_ENABLE_SSL3:
- ssl_EnableSSL3(&versions_defaults_stream, on);
- break;
+ case SSL_ENABLE_SSL3:
+ ssl_EnableSSL3(&versions_defaults_stream, on);
+ break;
- case SSL_ENABLE_SSL2:
- ssl_defaults.enableSSL2 = on;
- if (on) {
- ssl_defaults.v2CompatibleHello = on;
- }
- break;
+ case SSL_ENABLE_SSL2:
+ if (on) {
+ /* don't turn it on if ssl2 disallowed by by policy */
+ if (!ssl_VersionIsSupportedByPolicy(ssl_variant_stream,
+ SSL_LIBRARY_VERSION_2)) {
+ break;
+ }
+ }
+ ssl_defaults.enableSSL2 = on;
+ if (on) {
+ ssl_defaults.v2CompatibleHello = on;
+ }
+ break;
- case SSL_NO_CACHE:
- ssl_defaults.noCache = on;
- break;
+ case SSL_NO_CACHE:
+ ssl_defaults.noCache = on;
+ break;
- case SSL_ENABLE_FDX:
- if (on && ssl_defaults.noLocks) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
- ssl_defaults.fdx = on;
- break;
+ case SSL_ENABLE_FDX:
+ if (on && ssl_defaults.noLocks) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ ssl_defaults.fdx = on;
+ break;
- case SSL_V2_COMPATIBLE_HELLO:
- ssl_defaults.v2CompatibleHello = on;
- if (!on) {
- ssl_defaults.enableSSL2 = on;
- }
- break;
+ case SSL_V2_COMPATIBLE_HELLO:
+ ssl_defaults.v2CompatibleHello = on;
+ if (!on) {
+ ssl_defaults.enableSSL2 = on;
+ }
+ break;
- case SSL_ROLLBACK_DETECTION:
- ssl_defaults.detectRollBack = on;
- break;
+ case SSL_ROLLBACK_DETECTION:
+ ssl_defaults.detectRollBack = on;
+ break;
- case SSL_NO_STEP_DOWN:
- ssl_defaults.noStepDown = on;
- if (on)
- SSL_DisableDefaultExportCipherSuites();
- break;
+ case SSL_NO_STEP_DOWN:
+ ssl_defaults.noStepDown = on;
+ if (on)
+ SSL_DisableDefaultExportCipherSuites();
+ break;
- case SSL_BYPASS_PKCS11:
- if (PR_FALSE != on) {
- if (PR_SUCCESS == SSL_BypassSetup()) {
+ case SSL_BYPASS_PKCS11:
+ if (PR_FALSE != on) {
+ if (PR_SUCCESS == SSL_BypassSetup()) {
#ifdef NO_PKCS11_BYPASS
- ssl_defaults.bypassPKCS11 = PR_FALSE;
+ ssl_defaults.bypassPKCS11 = PR_FALSE;
#else
- ssl_defaults.bypassPKCS11 = on;
+ ssl_defaults.bypassPKCS11 = on;
#endif
+ } else {
+ return SECFailure;
+ }
} else {
- return SECFailure;
+ ssl_defaults.bypassPKCS11 = PR_FALSE;
}
- } else {
- ssl_defaults.bypassPKCS11 = PR_FALSE;
- }
- break;
+ break;
- case SSL_NO_LOCKS:
- if (on && ssl_defaults.fdx) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
- if (on && ssl_force_locks)
- on = PR_FALSE; /* silent override */
- ssl_defaults.noLocks = on;
- if (on) {
- locksEverDisabled = PR_TRUE;
- strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED.");
- }
- break;
+ case SSL_NO_LOCKS:
+ if (on && ssl_defaults.fdx) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ if (on && ssl_force_locks)
+ on = PR_FALSE; /* silent override */
+ ssl_defaults.noLocks = on;
+ if (on) {
+ locksEverDisabled = PR_TRUE;
+ strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED.");
+ }
+ break;
- case SSL_ENABLE_SESSION_TICKETS:
- ssl_defaults.enableSessionTickets = on;
- break;
+ case SSL_ENABLE_SESSION_TICKETS:
+ ssl_defaults.enableSessionTickets = on;
+ break;
- case SSL_ENABLE_DEFLATE:
- ssl_defaults.enableDeflate = on;
- break;
+ case SSL_ENABLE_DEFLATE:
+ ssl_defaults.enableDeflate = on;
+ break;
- case SSL_ENABLE_RENEGOTIATION:
- ssl_defaults.enableRenegotiation = on;
- break;
+ case SSL_ENABLE_RENEGOTIATION:
+ ssl_defaults.enableRenegotiation = on;
+ break;
- case SSL_REQUIRE_SAFE_NEGOTIATION:
- ssl_defaults.requireSafeNegotiation = on;
- break;
+ case SSL_REQUIRE_SAFE_NEGOTIATION:
+ ssl_defaults.requireSafeNegotiation = on;
+ break;
- case SSL_ENABLE_FALSE_START:
- ssl_defaults.enableFalseStart = on;
- break;
+ case SSL_ENABLE_FALSE_START:
+ ssl_defaults.enableFalseStart = on;
+ break;
- case SSL_CBC_RANDOM_IV:
- ssl_defaults.cbcRandomIV = on;
- break;
+ case SSL_CBC_RANDOM_IV:
+ ssl_defaults.cbcRandomIV = on;
+ break;
- case SSL_ENABLE_OCSP_STAPLING:
- ssl_defaults.enableOCSPStapling = on;
- break;
+ case SSL_ENABLE_OCSP_STAPLING:
+ ssl_defaults.enableOCSPStapling = on;
+ break;
- case SSL_ENABLE_NPN:
- ssl_defaults.enableNPN = on;
- break;
+ case SSL_ENABLE_NPN:
+ ssl_defaults.enableNPN = on;
+ break;
- case SSL_ENABLE_ALPN:
- ssl_defaults.enableALPN = on;
- break;
+ case SSL_ENABLE_ALPN:
+ ssl_defaults.enableALPN = on;
+ break;
- case SSL_REUSE_SERVER_ECDHE_KEY:
- ssl_defaults.reuseServerECDHEKey = on;
- break;
+ case SSL_REUSE_SERVER_ECDHE_KEY:
+ ssl_defaults.reuseServerECDHEKey = on;
+ break;
- case SSL_ENABLE_FALLBACK_SCSV:
- ssl_defaults.enableFallbackSCSV = on;
- break;
+ case SSL_ENABLE_FALLBACK_SCSV:
+ ssl_defaults.enableFallbackSCSV = on;
+ break;
- case SSL_ENABLE_SERVER_DHE:
- ssl_defaults.enableServerDhe = on;
- break;
+ case SSL_ENABLE_SERVER_DHE:
+ ssl_defaults.enableServerDhe = on;
+ break;
- case SSL_ENABLE_EXTENDED_MASTER_SECRET:
- ssl_defaults.enableExtendedMS = on;
- break;
+ case SSL_ENABLE_EXTENDED_MASTER_SECRET:
+ ssl_defaults.enableExtendedMS = on;
+ break;
- case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
- ssl_defaults.enableSignedCertTimestamps = on;
- break;
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ ssl_defaults.enableSignedCertTimestamps = on;
+ break;
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
return SECSuccess;
}
@@ -1214,12 +1332,12 @@ static PRBool
ssl_IsRemovedCipherSuite(PRInt32 suite)
{
switch (suite) {
- case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
- case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
- case SSL_FORTEZZA_DMS_WITH_RC4_128_SHA:
- return PR_TRUE;
- default:
- return PR_FALSE;
+ case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
+ case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
+ case SSL_FORTEZZA_DMS_WITH_RC4_128_SHA:
+ return PR_TRUE;
+ default:
+ return PR_FALSE;
}
}
@@ -1243,13 +1361,9 @@ SSL_SetPolicy(long which, int policy)
}
SECStatus
-SSL_CipherPolicySet(PRInt32 which, PRInt32 policy)
+ssl_CipherPolicySet(PRInt32 which, PRInt32 policy)
{
- SECStatus rv = ssl_Init();
-
- if (rv != SECSuccess) {
- return rv;
- }
+ SECStatus rv = SECSuccess;
if (ssl_IsRemovedCipherSuite(which)) {
rv = SECSuccess;
@@ -1260,6 +1374,16 @@ SSL_CipherPolicySet(PRInt32 which, PRInt32 policy)
}
return rv;
}
+SECStatus
+SSL_CipherPolicySet(PRInt32 which, PRInt32 policy)
+{
+ SECStatus rv = ssl_Init();
+
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ return ssl_CipherPolicySet(which, policy);
+}
SECStatus
SSL_CipherPolicyGet(PRInt32 which, PRInt32 *oPolicy)
@@ -1302,13 +1426,9 @@ SSL_EnableCipher(long which, PRBool enabled)
}
SECStatus
-SSL_CipherPrefSetDefault(PRInt32 which, PRBool enabled)
+ssl_CipherPrefSetDefault(PRInt32 which, PRBool enabled)
{
- SECStatus rv = ssl_Init();
-
- if (rv != SECSuccess) {
- return rv;
- }
+ SECStatus rv = SECSuccess;
if (ssl_IsRemovedCipherSuite(which))
return SECSuccess;
@@ -1325,9 +1445,20 @@ SSL_CipherPrefSetDefault(PRInt32 which, PRBool enabled)
}
SECStatus
+SSL_CipherPrefSetDefault(PRInt32 which, PRBool enabled)
+{
+ SECStatus rv = ssl_Init();
+
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ return ssl_CipherPrefSetDefault(which, enabled);
+}
+
+SECStatus
SSL_CipherPrefGetDefault(PRInt32 which, PRBool *enabled)
{
- SECStatus rv;
+ SECStatus rv;
if (!enabled) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -1374,9 +1505,9 @@ SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers, unsigned int len)
sslSocket *ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in CipherOrderSet", SSL_GETPID(),
- fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in CipherOrderSet", SSL_GETPID(),
+ fd));
+ return SECFailure;
}
return ssl3_CipherOrderSet(ss, ciphers, len);
}
@@ -1384,7 +1515,7 @@ SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers, unsigned int len)
SECStatus
SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled)
{
- SECStatus rv;
+ SECStatus rv;
sslSocket *ss = ssl_FindSocket(fd);
if (!enabled) {
@@ -1410,8 +1541,16 @@ SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled)
SECStatus
NSS_SetDomesticPolicy(void)
{
- SECStatus status = SECSuccess;
+ SECStatus status = SECSuccess;
const PRUint16 *cipher;
+ SECStatus rv;
+ PRUint32 policy;
+
+ /* If we've already defined some policy oids, skip changing them */
+ rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, &policy);
+ if ((rv == SECSuccess) && (policy & NSS_USE_POLICY_IN_SSL)) {
+ return ssl_Init(); /* make sure the policies have bee loaded */
+ }
for (cipher = SSL_ImplementedCiphers; *cipher != 0; ++cipher) {
status = SSL_SetPolicy(*cipher, SSL_ALLOWED);
@@ -1469,7 +1608,6 @@ SSL_DHEGroupPrefSet(PRFileDesc *fd,
return SECSuccess;
}
-
PRCallOnceType gWeakDHParamsRegisterOnce;
int gWeakDHParamsRegisterError;
@@ -1498,7 +1636,7 @@ ssl3_CreateWeakDHParams(void)
rv = PK11_PQG_VerifyParams(gWeakParamsPQG, vfy, &passed);
if (rv != SECSuccess || passed != SECSuccess) {
SSL_DBG(("%d: PK11_PQG_VerifyParams failed in ssl3_CreateWeakDHParams",
- SSL_GETPID()));
+ SSL_GETPID()));
gWeakDHParamsError = PORT_GetError();
return PR_FAILURE;
}
@@ -1577,21 +1715,22 @@ SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled)
SECStatus
SSL_GetChannelBinding(PRFileDesc *fd,
- SSLChannelBindingType binding_type,
- unsigned char *out,
- unsigned int *outLen,
- unsigned int outLenMax) {
+ SSLChannelBindingType binding_type,
+ unsigned char *out,
+ unsigned int *outLen,
+ unsigned int outLenMax)
+{
sslSocket *ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
if (binding_type != SSL_CHANNEL_BINDING_TLS_UNIQUE) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return SECFailure;
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+ return SECFailure;
}
return ssl3_GetTLSUniqueChannelBinding(ss, out, outLen, outLenMax);
@@ -1636,11 +1775,11 @@ ssl3_SelectDHParams(sslSocket *ss)
} else {
if (ss->ssl3.dheGroups) {
selectedGroup = selectDHEGroup(ss, ss->ssl3.dheGroups,
- ss->ssl3.numDHEGroups);
+ ss->ssl3.numDHEGroups);
} else {
size_t number_of_default_groups = PR_ARRAY_SIZE(ssl_default_dhe_groups);
selectedGroup = selectDHEGroup(ss, ssl_default_dhe_groups,
- number_of_default_groups);
+ number_of_default_groups);
}
if (selectedGroup == ssl_dhe_group_none ||
@@ -1658,10 +1797,10 @@ ssl3_SelectDHParams(sslSocket *ss)
static PRFileDesc *
ssl_ImportFD(PRFileDesc *model, PRFileDesc *fd, SSLProtocolVariant variant)
{
- sslSocket * ns = NULL;
- PRStatus rv;
- PRNetAddr addr;
- SECStatus status = ssl_Init();
+ sslSocket *ns = NULL;
+ PRStatus rv;
+ PRNetAddr addr;
+ SECStatus status = ssl_Init();
if (status != SECSuccess) {
return NULL;
@@ -1671,10 +1810,10 @@ ssl_ImportFD(PRFileDesc *model, PRFileDesc *fd, SSLProtocolVariant variant)
/* Just create a default socket if we're given NULL for the model */
ns = ssl_NewSocket((PRBool)(!ssl_defaults.noLocks), variant);
} else {
- sslSocket * ss = ssl_FindSocket(model);
+ sslSocket *ss = ssl_FindSocket(model);
if (ss == NULL || ss->protocolVariant != variant) {
SSL_DBG(("%d: SSL[%d]: bad model socket in ssl_ImportFD",
- SSL_GETPID(), model));
+ SSL_GETPID(), model));
return NULL;
}
ns = ssl_DupSocket(ss);
@@ -1690,7 +1829,7 @@ ssl_ImportFD(PRFileDesc *model, PRFileDesc *fd, SSLProtocolVariant variant)
}
#if defined(DEBUG) || defined(FORCE_PR_ASSERT)
{
- sslSocket * ss = ssl_FindSocket(fd);
+ sslSocket *ss = ssl_FindSocket(fd);
PORT_Assert(ss == ns);
}
#endif
@@ -1755,11 +1894,11 @@ ssl_NextProtoNegoCallback(void *arg, PRFileDesc *fd,
}
/* For each protocol in server preference, see if we support it. */
- for (i = 0; i < protos_len; ) {
- for (j = 0; j < ss->opt.nextProtoNego.len; ) {
+ for (i = 0; i < protos_len;) {
+ for (j = 0; j < ss->opt.nextProtoNego.len;) {
if (protos[i] == ss->opt.nextProtoNego.data[j] &&
- PORT_Memcmp(&protos[i+1], &ss->opt.nextProtoNego.data[j+1],
- protos[i]) == 0) {
+ PORT_Memcmp(&protos[i + 1], &ss->opt.nextProtoNego.data[j + 1],
+ protos[i]) == 0) {
/* We found a match. */
ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED;
result = &protos[i];
@@ -1793,7 +1932,7 @@ SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data,
{
sslSocket *ss;
SECStatus rv;
- SECItem dataItem = { siBuffer, (unsigned char *) data, length };
+ SECItem dataItem = { siBuffer, (unsigned char *)data, length };
ss = ssl_FindSocket(fd);
if (!ss) {
@@ -1850,9 +1989,10 @@ SSL_GetNextProto(PRFileDesc *fd, SSLNextProtoState *state, unsigned char *buf,
return SECSuccess;
}
-SECStatus SSL_SetSRTPCiphers(PRFileDesc *fd,
- const PRUint16 *ciphers,
- unsigned int numCiphers)
+SECStatus
+SSL_SetSRTPCiphers(PRFileDesc *fd,
+ const PRUint16 *ciphers,
+ unsigned int numCiphers)
{
sslSocket *ss;
unsigned int i;
@@ -1884,8 +2024,9 @@ SECStatus SSL_SetSRTPCiphers(PRFileDesc *fd,
ciphers[i];
} else {
SSL_DBG(("%d: SSL[%d]: invalid or unimplemented SRTP cipher "
- "suite specified: 0x%04hx", SSL_GETPID(), fd,
- ciphers[i]));
+ "suite specified: 0x%04hx",
+ SSL_GETPID(), fd,
+ ciphers[i]));
}
}
@@ -1900,7 +2041,7 @@ SECStatus SSL_SetSRTPCiphers(PRFileDesc *fd,
SECStatus
SSL_GetSRTPCipher(PRFileDesc *fd, PRUint16 *cipher)
{
- sslSocket * ss;
+ sslSocket *ss;
ss = ssl_FindSocket(fd);
if (!ss) {
@@ -1922,10 +2063,10 @@ SSL_GetSRTPCipher(PRFileDesc *fd, PRUint16 *cipher)
PRFileDesc *
SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
{
- sslSocket * sm = NULL, *ss = NULL;
+ sslSocket *sm = NULL, *ss = NULL;
int i;
- sslServerCerts * mc = NULL;
- sslServerCerts * sc = NULL;
+ sslServerCerts *mc = NULL;
+ sslServerCerts *sc = NULL;
if (model == NULL) {
PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
@@ -1944,7 +2085,7 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
return NULL;
}
- ss->opt = sm->opt;
+ ss->opt = sm->opt;
ss->vrange = sm->vrange;
PORT_Memcpy(ss->cipherSuites, sm->cipherSuites, sizeof sm->cipherSuites);
PORT_Memcpy(ss->ssl3.dtlsSRTPCiphers, sm->ssl3.dtlsSRTPCiphers,
@@ -1952,8 +2093,9 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
ss->ssl3.dtlsSRTPCipherCount = sm->ssl3.dtlsSRTPCipherCount;
PORT_Memcpy(ss->ssl3.signatureAlgorithms, sm->ssl3.signatureAlgorithms,
sizeof(ss->ssl3.signatureAlgorithms[0]) *
- sm->ssl3.signatureAlgorithmCount);
+ sm->ssl3.signatureAlgorithmCount);
ss->ssl3.signatureAlgorithmCount = sm->ssl3.signatureAlgorithmCount;
+ ss->ssl3.downgradeCheckVersion = sm->ssl3.downgradeCheckVersion;
if (!ss->opt.useSecurity) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -1962,14 +2104,14 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
/* This int should be SSLKEAType, but CC on Irix complains,
* during the for loop.
*/
- for (i=kt_null; i < kt_kea_size; i++) {
+ for (i = kt_null; i < kt_kea_size; i++) {
mc = &(sm->serverCerts[i]);
sc = &(ss->serverCerts[i]);
if (mc->serverCert && mc->serverCertChain) {
if (sc->serverCert) {
CERT_DestroyCertificate(sc->serverCert);
}
- sc->serverCert = CERT_DupCertificate(mc->serverCert);
+ sc->serverCert = CERT_DupCertificate(mc->serverCert);
if (sc->serverCertChain) {
CERT_DestroyCertificateList(sc->serverCertChain);
}
@@ -1985,6 +2127,17 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
if (!ss->certStatusArray[i])
goto loser;
}
+ if (sm->signedCertTimestamps[i].data) {
+ if (ss->signedCertTimestamps[i].data) {
+ SECITEM_FreeItem(&ss->signedCertTimestamps[i], PR_FALSE);
+ }
+ if (SECITEM_CopyItem(NULL,
+ &ss->signedCertTimestamps[i],
+ &sm->signedCertTimestamps[i]) !=
+ SECSuccess) {
+ goto loser;
+ }
+ }
}
if (mc->serverKeyPair) {
if (sc->serverKeyPair) {
@@ -2019,58 +2172,148 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
}
if (sm->authCertificate)
- ss->authCertificate = sm->authCertificate;
+ ss->authCertificate = sm->authCertificate;
if (sm->authCertificateArg)
- ss->authCertificateArg = sm->authCertificateArg;
+ ss->authCertificateArg = sm->authCertificateArg;
if (sm->getClientAuthData)
- ss->getClientAuthData = sm->getClientAuthData;
+ ss->getClientAuthData = sm->getClientAuthData;
if (sm->getClientAuthDataArg)
- ss->getClientAuthDataArg = sm->getClientAuthDataArg;
-#ifdef NSS_PLATFORM_CLIENT_AUTH
- if (sm->getPlatformClientAuthData)
- ss->getPlatformClientAuthData = sm->getPlatformClientAuthData;
- if (sm->getPlatformClientAuthDataArg)
- ss->getPlatformClientAuthDataArg = sm->getPlatformClientAuthDataArg;
-#endif
+ ss->getClientAuthDataArg = sm->getClientAuthDataArg;
if (sm->sniSocketConfig)
- ss->sniSocketConfig = sm->sniSocketConfig;
+ ss->sniSocketConfig = sm->sniSocketConfig;
if (sm->sniSocketConfigArg)
- ss->sniSocketConfigArg = sm->sniSocketConfigArg;
+ ss->sniSocketConfigArg = sm->sniSocketConfigArg;
if (sm->handleBadCert)
- ss->handleBadCert = sm->handleBadCert;
+ ss->handleBadCert = sm->handleBadCert;
if (sm->badCertArg)
- ss->badCertArg = sm->badCertArg;
+ ss->badCertArg = sm->badCertArg;
if (sm->handshakeCallback)
- ss->handshakeCallback = sm->handshakeCallback;
+ ss->handshakeCallback = sm->handshakeCallback;
if (sm->handshakeCallbackData)
ss->handshakeCallbackData = sm->handshakeCallbackData;
if (sm->pkcs11PinArg)
- ss->pkcs11PinArg = sm->pkcs11PinArg;
+ ss->pkcs11PinArg = sm->pkcs11PinArg;
if (sm->getChannelID)
- ss->getChannelID = sm->getChannelID;
+ ss->getChannelID = sm->getChannelID;
if (sm->getChannelIDArg)
- ss->getChannelIDArg = sm->getChannelIDArg;
+ ss->getChannelIDArg = sm->getChannelIDArg;
return fd;
loser:
return NULL;
}
+/*
+ * Get the user supplied range
+ */
+static SECStatus
+ssl3_GetRangePolicy(SSLProtocolVariant protocolVariant, SSLVersionRange *prange)
+{
+ SECStatus rv;
+ PRUint32 policy;
+ PRInt32 option;
+
+ /* only use policy constraints if we've set the apply ssl policy bit */
+ rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, &policy);
+ if ((rv != SECSuccess) || !(policy & NSS_USE_POLICY_IN_SSL)) {
+ return SECFailure;
+ }
+ rv = NSS_OptionGet(VERSIONS_POLICY_MIN(protocolVariant), &option);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ prange->min = (PRUint16)option;
+ rv = NSS_OptionGet(VERSIONS_POLICY_MAX(protocolVariant), &option);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ prange->max = (PRUint16)option;
+ if (prange->max < prange->min) {
+ return SECFailure; /* don't accept an invalid policy */
+ }
+ return SECSuccess;
+}
+
+/*
+ * Constrain a single protocol variant's range based on the user policy
+ */
+static SECStatus
+ssl3_ConstrainVariantRangeByPolicy(SSLProtocolVariant protocolVariant)
+{
+ SSLVersionRange vrange;
+ SSLVersionRange pvrange;
+ SECStatus rv;
+
+ vrange = *VERSIONS_DEFAULTS(protocolVariant);
+ rv = ssl3_GetRangePolicy(protocolVariant, &pvrange);
+ if (rv != SECSuccess) {
+ return SECSuccess; /* we don't have any policy */
+ }
+ vrange.min = PR_MAX(vrange.min, pvrange.min);
+ vrange.max = PR_MIN(vrange.max, pvrange.max);
+ if (vrange.max >= vrange.min) {
+ *VERSIONS_DEFAULTS(protocolVariant) = vrange;
+ } else {
+ /* there was no overlap, turn off range altogether */
+ pvrange.min = pvrange.max = SSL_LIBRARY_VERSION_NONE;
+ *VERSIONS_DEFAULTS(protocolVariant) = pvrange;
+ }
+ return SECSuccess;
+}
+
+static PRBool
+ssl_VersionIsSupportedByPolicy(SSLProtocolVariant protocolVariant,
+ SSL3ProtocolVersion version)
+{
+ SSLVersionRange pvrange;
+ SECStatus rv;
+
+ rv = ssl3_GetRangePolicy(protocolVariant, &pvrange);
+ if (rv == SECSuccess) {
+ if ((version > pvrange.max) || (version < pvrange.min)) {
+ return PR_FALSE; /* disallowed by policy */
+ }
+ }
+ return PR_TRUE;
+}
+
+/*
+ * This is called at SSL init time to constrain the existing range based
+ * on user supplied policy.
+ */
+SECStatus
+ssl3_ConstrainRangeByPolicy(void)
+{
+ SECStatus rv;
+ rv = ssl3_ConstrainVariantRangeByPolicy(ssl_variant_stream);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ rv = ssl3_ConstrainVariantRangeByPolicy(ssl_variant_datagram);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ return SECSuccess;
+}
+
PRBool
ssl3_VersionIsSupported(SSLProtocolVariant protocolVariant,
SSL3ProtocolVersion version)
{
- switch (protocolVariant) {
- case ssl_variant_stream:
- return (version >= SSL_LIBRARY_VERSION_3_0 &&
- version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED);
- case ssl_variant_datagram:
- return (version >= SSL_LIBRARY_VERSION_TLS_1_1 &&
- version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED);
- default:
- /* Can't get here */
- PORT_Assert(PR_FALSE);
+ if (!ssl_VersionIsSupportedByPolicy(protocolVariant, version)) {
return PR_FALSE;
}
+ switch (protocolVariant) {
+ case ssl_variant_stream:
+ return (version >= SSL_LIBRARY_VERSION_3_0 &&
+ version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED);
+ case ssl_variant_datagram:
+ return (version >= SSL_LIBRARY_VERSION_TLS_1_1 &&
+ version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED);
+ default:
+ /* Can't get here */
+ PORT_Assert(PR_FALSE);
+ return PR_FALSE;
+ }
}
/* Returns PR_TRUE if the given version range is valid and
@@ -2086,6 +2329,29 @@ ssl3_VersionRangeIsValid(SSLProtocolVariant protocolVariant,
ssl3_VersionIsSupported(protocolVariant, vrange->max);
}
+const SECItem *
+SSL_PeerSignedCertTimestamps(PRFileDesc *fd)
+{
+ sslSocket *ss = ssl_FindSocket(fd);
+
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerSignedCertTimestamps",
+ SSL_GETPID(), fd));
+ return NULL;
+ }
+
+ if (!ss->sec.ci.sid) {
+ PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
+ return NULL;
+ }
+
+ if (ss->sec.ci.sid->version < SSL_LIBRARY_VERSION_3_0) {
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
+ return NULL;
+ }
+ return &ss->sec.ci.sid->u.ssl3.signedCertTimestamps;
+}
+
SECStatus
SSL_VersionRangeGetSupported(SSLProtocolVariant protocolVariant,
SSLVersionRange *vrange)
@@ -2096,17 +2362,17 @@ SSL_VersionRangeGetSupported(SSLProtocolVariant protocolVariant,
}
switch (protocolVariant) {
- case ssl_variant_stream:
- vrange->min = SSL_LIBRARY_VERSION_3_0;
- vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED;
- break;
- case ssl_variant_datagram:
- vrange->min = SSL_LIBRARY_VERSION_TLS_1_1;
- vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED;
- break;
- default:
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ case ssl_variant_stream:
+ vrange->min = SSL_LIBRARY_VERSION_3_0;
+ vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED;
+ break;
+ case ssl_variant_datagram:
+ vrange->min = SSL_LIBRARY_VERSION_TLS_1_1;
+ vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED;
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
return SECSuccess;
@@ -2117,7 +2383,8 @@ SSL_VersionRangeGetDefault(SSLProtocolVariant protocolVariant,
SSLVersionRange *vrange)
{
if ((protocolVariant != ssl_variant_stream &&
- protocolVariant != ssl_variant_datagram) || !vrange) {
+ protocolVariant != ssl_variant_datagram) ||
+ !vrange) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@@ -2147,8 +2414,8 @@ SSL_VersionRangeGet(PRFileDesc *fd, SSLVersionRange *vrange)
sslSocket *ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL3_VersionRangeGet",
- SSL_GETPID(), fd));
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_VersionRangeGet",
+ SSL_GETPID(), fd));
return SECFailure;
}
@@ -2168,32 +2435,14 @@ SSL_VersionRangeGet(PRFileDesc *fd, SSLVersionRange *vrange)
return SECSuccess;
}
-static PRCallOnceType checkTLS12TokenOnce;
-static PRBool tls12TokenExists;
-
-static PRStatus
-ssl_CheckTLS12Token(void)
-{
- tls12TokenExists =
- PK11_TokenExists(CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256);
- return PR_SUCCESS;
-}
-
-static PRBool
-ssl_TLS12TokenExists(void)
-{
- (void) PR_CallOnce(&checkTLS12TokenOnce, ssl_CheckTLS12Token);
- return tls12TokenExists;
-}
-
SECStatus
SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange)
{
sslSocket *ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL3_VersionRangeSet",
- SSL_GETPID(), fd));
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_VersionRangeSet",
+ SSL_GETPID(), fd));
return SECFailure;
}
@@ -2205,78 +2454,84 @@ SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange)
ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss);
- ss->vrange = *vrange;
- /* If we don't have a sufficiently up-to-date softoken then we cannot do
- * TLS 1.2. */
- if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_2 &&
- !ssl_TLS12TokenExists()) {
- /* If the user requested a minimum version of 1.2, then we don't
- * silently downgrade. */
- if (ss->vrange.min >= SSL_LIBRARY_VERSION_TLS_1_2) {
- ssl_ReleaseSSL3HandshakeLock(ss);
- ssl_Release1stHandshakeLock(ss);
- PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE);
- return SECFailure;
- }
- ss->vrange.max = SSL_LIBRARY_VERSION_TLS_1_1;
+ if (ss->ssl3.downgradeCheckVersion &&
+ ss->vrange.max > ss->ssl3.downgradeCheckVersion) {
+ PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
+ return SECFailure;
}
+ ss->vrange = *vrange;
+
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss);
return SECSuccess;
}
-const SECItemArray *
-SSL_PeerStapledOCSPResponses(PRFileDesc *fd)
+SECStatus
+SSL_SetDowngradeCheckVersion(PRFileDesc *fd, PRUint16 version)
{
sslSocket *ss = ssl_FindSocket(fd);
+ SECStatus rv = SECFailure;
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerStapledOCSPResponses",
- SSL_GETPID(), fd));
- return NULL;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetDowngradeCheckVersion",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
- if (!ss->sec.ci.sid) {
- PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
- return NULL;
+ if (version && !ssl3_VersionIsSupported(ss->protocolVariant, version)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
- return &ss->sec.ci.sid->peerCertStatus;
+ ssl_Get1stHandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+
+ if (version && version < ss->vrange.max) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ goto loser;
+ }
+ ss->ssl3.downgradeCheckVersion = version;
+ rv = SECSuccess;
+
+loser:
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
+
+ return rv;
}
-const SECItem *
-SSL_PeerSignedCertTimestamps(PRFileDesc *fd)
+const SECItemArray *
+SSL_PeerStapledOCSPResponses(PRFileDesc *fd)
{
sslSocket *ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerSignedCertTimestamps",
- SSL_GETPID(), fd));
- return NULL;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerStapledOCSPResponses",
+ SSL_GETPID(), fd));
+ return NULL;
}
if (!ss->sec.ci.sid) {
- PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
- return NULL;
+ PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
+ return NULL;
}
- if (ss->sec.ci.sid->version < SSL_LIBRARY_VERSION_3_0) {
- PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
- return NULL;
- }
- return &ss->sec.ci.sid->u.ssl3.signedCertTimestamps;
+ return &ss->sec.ci.sid->peerCertStatus;
}
SECStatus
-SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed) {
+SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed)
+{
sslSocket *ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_HandshakeResumedSession",
- SSL_GETPID(), fd));
- return SECFailure;
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_HandshakeResumedSession",
+ SSL_GETPID(), fd));
+ return SECFailure;
}
*handshake_resumed = ss->ssl3.hs.isResuming;
@@ -2286,15 +2541,16 @@ SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed) {
const SECItem *
SSL_GetRequestedClientCertificateTypes(PRFileDesc *fd)
{
- sslSocket *ss = ssl_FindSocket(fd);
+ sslSocket *ss = ssl_FindSocket(fd);
- if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in "
- "SSL_GetRequestedClientCertificateTypes", SSL_GETPID(), fd));
- return NULL;
- }
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in "
+ "SSL_GetRequestedClientCertificateTypes",
+ SSL_GETPID(), fd));
+ return NULL;
+ }
- return ss->requestedCertTypes;
+ return ss->requestedCertTypes;
}
/************************************************************************/
@@ -2302,14 +2558,14 @@ SSL_GetRequestedClientCertificateTypes(PRFileDesc *fd)
** They all get called through the NSPRIOMethods table below.
*/
-static PRFileDesc * PR_CALLBACK
+static PRFileDesc *PR_CALLBACK
ssl_Accept(PRFileDesc *fd, PRNetAddr *sockaddr, PRIntervalTime timeout)
{
- sslSocket *ss;
- sslSocket *ns = NULL;
- PRFileDesc *newfd = NULL;
+ sslSocket *ss;
+ sslSocket *ns = NULL;
+ PRFileDesc *newfd = NULL;
PRFileDesc *osfd;
- PRStatus status;
+ PRStatus status;
ss = ssl_GetPrivate(fd);
if (!ss) {
@@ -2340,7 +2596,7 @@ ssl_Accept(PRFileDesc *fd, PRNetAddr *sockaddr, PRIntervalTime timeout)
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss);
SSL_UNLOCK_WRITER(ss);
- SSL_UNLOCK_READER(ss); /* ss isn't used below here. */
+ SSL_UNLOCK_READER(ss); /* ss isn't used below here. */
if (ns == NULL)
goto loser;
@@ -2353,8 +2609,8 @@ ssl_Accept(PRFileDesc *fd, PRNetAddr *sockaddr, PRIntervalTime timeout)
/* Now start server connection handshake with client.
** Don't need locks here because nobody else has a reference to ns yet.
*/
- if ( ns->opt.useSecurity ) {
- if ( ns->opt.handshakeAsClient ) {
+ if (ns->opt.useSecurity) {
+ if (ns->opt.handshakeAsClient) {
ns->handshake = ssl2_BeginClientHandshake;
ss->handshaking = sslHandshakingAsClient;
} else {
@@ -2377,7 +2633,7 @@ static PRStatus PR_CALLBACK
ssl_Connect(PRFileDesc *fd, const PRNetAddr *sockaddr, PRIntervalTime timeout)
{
sslSocket *ss;
- PRStatus rv;
+ PRStatus rv;
ss = ssl_GetPrivate(fd);
if (!ss) {
@@ -2401,8 +2657,8 @@ ssl_Connect(PRFileDesc *fd, const PRNetAddr *sockaddr, PRIntervalTime timeout)
static PRStatus PR_CALLBACK
ssl_Bind(PRFileDesc *fd, const PRNetAddr *addr)
{
- sslSocket * ss = ssl_GetPrivate(fd);
- PRStatus rv;
+ sslSocket *ss = ssl_GetPrivate(fd);
+ PRStatus rv;
if (!ss) {
SSL_DBG(("%d: SSL[%d]: bad socket in bind", SSL_GETPID(), fd));
@@ -2421,8 +2677,8 @@ ssl_Bind(PRFileDesc *fd, const PRNetAddr *addr)
static PRStatus PR_CALLBACK
ssl_Listen(PRFileDesc *fd, PRIntn backlog)
{
- sslSocket * ss = ssl_GetPrivate(fd);
- PRStatus rv;
+ sslSocket *ss = ssl_GetPrivate(fd);
+ PRStatus rv;
if (!ss) {
SSL_DBG(("%d: SSL[%d]: bad socket in listen", SSL_GETPID(), fd));
@@ -2441,8 +2697,8 @@ ssl_Listen(PRFileDesc *fd, PRIntn backlog)
static PRStatus PR_CALLBACK
ssl_Shutdown(PRFileDesc *fd, PRIntn how)
{
- sslSocket * ss = ssl_GetPrivate(fd);
- PRStatus rv;
+ sslSocket *ss = ssl_GetPrivate(fd);
+ PRStatus rv;
if (!ss) {
SSL_DBG(("%d: SSL[%d]: bad socket in shutdown", SSL_GETPID(), fd));
@@ -2470,7 +2726,7 @@ static PRStatus PR_CALLBACK
ssl_Close(PRFileDesc *fd)
{
sslSocket *ss;
- PRStatus rv;
+ PRStatus rv;
ss = ssl_GetPrivate(fd);
if (!ss) {
@@ -2498,7 +2754,7 @@ ssl_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
PRIntervalTime timeout)
{
sslSocket *ss;
- int rv;
+ int rv;
ss = ssl_GetPrivate(fd);
if (!ss) {
@@ -2509,7 +2765,7 @@ ssl_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
ss->rTimeout = timeout;
if (!ss->opt.fdx)
ss->wTimeout = timeout;
- rv = (*ss->ops->recv)(ss, (unsigned char*)buf, len, flags);
+ rv = (*ss->ops->recv)(ss, (unsigned char *)buf, len, flags);
SSL_UNLOCK_READER(ss);
return rv;
}
@@ -2519,7 +2775,7 @@ ssl_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
PRIntervalTime timeout)
{
sslSocket *ss;
- int rv;
+ int rv;
ss = ssl_GetPrivate(fd);
if (!ss) {
@@ -2530,7 +2786,7 @@ ssl_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
ss->wTimeout = timeout;
if (!ss->opt.fdx)
ss->rTimeout = timeout;
- rv = (*ss->ops->send)(ss, (const unsigned char*)buf, len, flags);
+ rv = (*ss->ops->send)(ss, (const unsigned char *)buf, len, flags);
SSL_UNLOCK_WRITER(ss);
return rv;
}
@@ -2539,7 +2795,7 @@ static int PR_CALLBACK
ssl_Read(PRFileDesc *fd, void *buf, PRInt32 len)
{
sslSocket *ss;
- int rv;
+ int rv;
ss = ssl_GetPrivate(fd);
if (!ss) {
@@ -2550,7 +2806,7 @@ ssl_Read(PRFileDesc *fd, void *buf, PRInt32 len)
ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;
if (!ss->opt.fdx)
ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;
- rv = (*ss->ops->read)(ss, (unsigned char*)buf, len);
+ rv = (*ss->ops->read)(ss, (unsigned char *)buf, len);
SSL_UNLOCK_READER(ss);
return rv;
}
@@ -2559,7 +2815,7 @@ static int PR_CALLBACK
ssl_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
{
sslSocket *ss;
- int rv;
+ int rv;
ss = ssl_GetPrivate(fd);
if (!ss) {
@@ -2570,7 +2826,7 @@ ssl_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;
if (!ss->opt.fdx)
ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;
- rv = (*ss->ops->write)(ss, (const unsigned char*)buf, len);
+ rv = (*ss->ops->write)(ss, (const unsigned char *)buf, len);
SSL_UNLOCK_WRITER(ss);
return rv;
}
@@ -2593,9 +2849,9 @@ ssl_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
SECStatus
ssl_GetPeerInfo(sslSocket *ss)
{
- PRFileDesc * osfd;
- int rv;
- PRNetAddr sin;
+ PRFileDesc *osfd;
+ int rv;
+ PRNetAddr sin;
osfd = ss->fd->lower;
@@ -2644,8 +2900,8 @@ SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses,
return SECFailure;
}
- if ( kea <= 0 || kea >= kt_kea_size) {
- SSL_DBG(("%d: SSL[%d]: invalid key in SSL_SetStapledOCSPResponses",
+ if (kea <= 0 || kea >= kt_kea_size) {
+ SSL_DBG(("%d: SSL[%d]: invalid key type in SSL_SetStapledOCSPResponses",
SSL_GETPID(), fd));
return SECFailure;
}
@@ -2661,6 +2917,35 @@ SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses,
}
SECStatus
+SSL_SetSignedCertTimestamps(PRFileDesc *fd, const SECItem *scts, SSLKEAType kea)
+{
+ sslSocket *ss;
+
+ ss = ssl_FindSocket(fd);
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSignedCertTimestamps",
+ SSL_GETPID(), fd));
+ return SECFailure;
+ }
+
+ if (kea <= 0 || kea >= kt_kea_size) {
+ SSL_DBG(("%d: SSL[%d]: invalid key type in SSL_SetSignedCertTimestamps",
+ SSL_GETPID(), fd));
+ return SECFailure;
+ }
+
+ if (ss->signedCertTimestamps[kea].data) {
+ SECITEM_FreeItem(&ss->signedCertTimestamps[kea], PR_FALSE);
+ }
+
+ if (!scts) {
+ return SECSuccess;
+ }
+
+ return SECITEM_CopyItem(NULL, &ss->signedCertTimestamps[kea], scts);
+}
+
+SECStatus
SSL_SetSockPeerID(PRFileDesc *fd, const char *peerID)
{
sslSocket *ss;
@@ -2687,15 +2972,15 @@ static PRInt16 PR_CALLBACK
ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags)
{
sslSocket *ss;
- PRInt16 new_flags = how_flags; /* should select on these flags. */
- PRNetAddr addr;
+ PRInt16 new_flags = how_flags; /* should select on these flags. */
+ PRNetAddr addr;
*p_out_flags = 0;
ss = ssl_GetPrivate(fd);
if (!ss) {
SSL_DBG(("%d: SSL[%d]: bad socket in SSL_Poll",
SSL_GETPID(), fd));
- return 0; /* don't poll on this socket */
+ return 0; /* don't poll on this socket */
}
if (ss->opt.useSecurity &&
@@ -2721,36 +3006,36 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags)
new_flags |= PR_POLL_READ;
}
} else
- /* First handshake is in progress */
- if (ss->lastWriteBlocked) {
+ /* First handshake is in progress */
+ if (ss->lastWriteBlocked) {
if (new_flags & PR_POLL_READ) {
/* The caller is waiting for data to be received,
** but the initial handshake is blocked on write, or the
** client's first handshake record has not been written.
** The code should select on write, not read.
*/
- new_flags ^= PR_POLL_READ; /* don't select on read. */
- new_flags |= PR_POLL_WRITE; /* do select on write. */
+ new_flags ^= PR_POLL_READ; /* don't select on read. */
+ new_flags |= PR_POLL_WRITE; /* do select on write. */
}
} else if (new_flags & PR_POLL_WRITE) {
- /* The caller is trying to write, but the handshake is
- ** blocked waiting for data to read, and the first
- ** handshake has been sent. So do NOT to poll on write
- ** unless we did false start.
- */
- if (!(ss->version >= SSL_LIBRARY_VERSION_3_0 &&
- ss->ssl3.hs.canFalseStart)) {
- new_flags ^= PR_POLL_WRITE; /* don't select on write. */
- }
- new_flags |= PR_POLL_READ; /* do select on read. */
+ /* The caller is trying to write, but the handshake is
+ ** blocked waiting for data to read, and the first
+ ** handshake has been sent. So do NOT to poll on write
+ ** unless we did false start.
+ */
+ if (!(ss->version >= SSL_LIBRARY_VERSION_3_0 &&
+ ss->ssl3.hs.canFalseStart)) {
+ new_flags ^= PR_POLL_WRITE; /* don't select on write. */
+ }
+ new_flags |= PR_POLL_READ; /* do select on read. */
}
}
} else if ((new_flags & PR_POLL_READ) && (SSL_DataPending(fd) > 0)) {
- *p_out_flags = PR_POLL_READ; /* it's ready already. */
+ *p_out_flags = PR_POLL_READ; /* it's ready already. */
return new_flags;
} else if ((ss->lastWriteBlocked) && (how_flags & PR_POLL_READ) &&
(ss->pendingBuf.len != 0)) { /* write data waiting to be sent */
- new_flags |= PR_POLL_WRITE; /* also select on write. */
+ new_flags |= PR_POLL_WRITE; /* also select on write. */
}
if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
@@ -2782,8 +3067,8 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags)
}
if (new_flags && (fd->lower->methods->poll != NULL)) {
- PRInt16 lower_out_flags = 0;
- PRInt16 lower_new_flags;
+ PRInt16 lower_out_flags = 0;
+ PRInt16 lower_new_flags;
lower_new_flags = fd->lower->methods->poll(fd->lower, new_flags,
&lower_out_flags);
if ((lower_new_flags & lower_out_flags) && (how_flags != new_flags)) {
@@ -2796,7 +3081,7 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags)
new_flags = how_flags;
} else {
*p_out_flags = lower_out_flags;
- new_flags = lower_new_flags;
+ new_flags = lower_new_flags;
}
}
@@ -2821,14 +3106,13 @@ ssl_TransmitFile(PRFileDesc *sd, PRFileDesc *fd,
return sd->methods->sendfile(sd, &sfd, flags, timeout);
}
-
PRBool
ssl_FdIsBlocking(PRFileDesc *fd)
{
PRSocketOptionData opt;
- PRStatus status;
+ PRStatus status;
- opt.option = PR_SockOpt_Nonblocking;
+ opt.option = PR_SockOpt_Nonblocking;
opt.value.non_blocking = PR_FALSE;
status = PR_GetSocketOption(fd, &opt);
if (status != PR_SUCCESS)
@@ -2842,23 +3126,23 @@ ssl_SocketIsBlocking(sslSocket *ss)
return ssl_FdIsBlocking(ss->fd);
}
-PRInt32 sslFirstBufSize = 8 * 1024;
-PRInt32 sslCopyLimit = 1024;
+PRInt32 sslFirstBufSize = 8 * 1024;
+PRInt32 sslCopyLimit = 1024;
static PRInt32 PR_CALLBACK
ssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors,
PRIntervalTime timeout)
{
- PRInt32 i;
- PRInt32 bufLen;
- PRInt32 left;
- PRInt32 rv;
- PRInt32 sent = 0;
- const PRInt32 first_len = sslFirstBufSize;
- const PRInt32 limit = sslCopyLimit;
- PRBool blocking;
- PRIOVec myIov = { 0, 0 };
- char buf[MAX_FRAGMENT_LENGTH];
+ PRInt32 i;
+ PRInt32 bufLen;
+ PRInt32 left;
+ PRInt32 rv;
+ PRInt32 sent = 0;
+ const PRInt32 first_len = sslFirstBufSize;
+ const PRInt32 limit = sslCopyLimit;
+ PRBool blocking;
+ PRIOVec myIov = { 0, 0 };
+ char buf[MAX_FRAGMENT_LENGTH];
if (vectors < 0) {
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
@@ -2877,28 +3161,37 @@ ssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors,
blocking = ssl_FdIsBlocking(fd);
#define K16 sizeof(buf)
-#define KILL_VECTORS while (vectors && !iov->iov_len) { ++iov; --vectors; }
-#define GET_VECTOR do { myIov = *iov++; --vectors; KILL_VECTORS } while (0)
-#define HANDLE_ERR(rv, len) \
- if (rv != len) { \
- if (rv < 0) { \
- if (!blocking \
- && (PR_GetError() == PR_WOULD_BLOCK_ERROR) \
- && (sent > 0)) { \
- return sent; \
- } else { \
- return -1; \
- } \
- } \
+#define KILL_VECTORS \
+ while (vectors && !iov->iov_len) { \
+ ++iov; \
+ --vectors; \
+ }
+#define GET_VECTOR \
+ do { \
+ myIov = *iov++; \
+ --vectors; \
+ KILL_VECTORS \
+ } while (0)
+#define HANDLE_ERR(rv, len) \
+ if (rv != len) { \
+ if (rv < 0) { \
+ if (!blocking && \
+ (PR_GetError() == PR_WOULD_BLOCK_ERROR) && \
+ (sent > 0)) { \
+ return sent; \
+ } else { \
+ return -1; \
+ } \
+ } \
/* Only a nonblocking socket can have partial sends */ \
- PR_ASSERT(!blocking); \
- return sent + rv; \
+ PR_ASSERT(!blocking); \
+ return sent + rv; \
}
-#define SEND(bfr, len) \
- do { \
+#define SEND(bfr, len) \
+ do { \
rv = ssl_Send(fd, bfr, len, 0, timeout); \
- HANDLE_ERR(rv, len) \
- sent += len; \
+ HANDLE_ERR(rv, len) \
+ sent += len; \
} while (0)
/* Make sure the first write is at least 8 KB, if possible. */
@@ -2918,23 +3211,23 @@ ssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors,
GET_VECTOR;
toCopy = PR_MIN(left, myIov.iov_len);
PORT_Memcpy(buf + bufLen, myIov.iov_base, toCopy);
- bufLen += toCopy;
- left -= toCopy;
+ bufLen += toCopy;
+ left -= toCopy;
myIov.iov_base += toCopy;
- myIov.iov_len -= toCopy;
+ myIov.iov_len -= toCopy;
}
- SEND( buf, bufLen );
+ SEND(buf, bufLen);
}
while (vectors || myIov.iov_len) {
- PRInt32 addLen;
+ PRInt32 addLen;
if (!myIov.iov_len) {
GET_VECTOR;
}
while (myIov.iov_len >= K16) {
SEND(myIov.iov_base, K16);
myIov.iov_base += K16;
- myIov.iov_len -= K16;
+ myIov.iov_len -= K16;
}
if (!myIov.iov_len)
continue;
@@ -2944,13 +3237,13 @@ ssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors,
} else if ((addLen = iov->iov_len % K16) + myIov.iov_len <= limit) {
/* Addlen is already computed. */;
} else if (vectors > 1 &&
- iov[1].iov_len % K16 + addLen + myIov.iov_len <= 2 * limit) {
- addLen = limit - myIov.iov_len;
+ iov[1].iov_len % K16 + addLen + myIov.iov_len <= 2 * limit) {
+ addLen = limit - myIov.iov_len;
} else
addLen = 0;
if (!addLen) {
- SEND( myIov.iov_base, myIov.iov_len );
+ SEND(myIov.iov_base, myIov.iov_len);
myIov.iov_len = 0;
continue;
}
@@ -2960,25 +3253,24 @@ ssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors,
GET_VECTOR;
PORT_Memcpy(buf + bufLen, myIov.iov_base, addLen);
myIov.iov_base += addLen;
- myIov.iov_len -= addLen;
- bufLen += addLen;
-
- left = PR_MIN( limit, K16 - bufLen);
- if (!vectors /* no more left */
- || myIov.iov_len > 0 /* we didn't use that one all up */
- || bufLen >= K16 /* it's full. */
- ) {
+ myIov.iov_len -= addLen;
+ bufLen += addLen;
+
+ left = PR_MIN(limit, K16 - bufLen);
+ if (!vectors /* no more left */
+ || myIov.iov_len > 0 /* we didn't use that one all up */
+ || bufLen >= K16 /* it's full. */) {
addLen = 0;
} else if ((addLen = iov->iov_len % K16) <= left) {
/* Addlen is already computed. */;
} else if (vectors > 1 &&
- iov[1].iov_len % K16 + addLen <= left + limit) {
- addLen = left;
+ iov[1].iov_len % K16 + addLen <= left + limit) {
+ addLen = left;
} else
addLen = 0;
} while (addLen);
- SEND( buf, bufLen );
+ SEND(buf, bufLen);
}
return sent;
}
@@ -3015,14 +3307,16 @@ ssl_FSync(PRFileDesc *fd)
}
static PRInt32 PR_CALLBACK
-ssl_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence how) {
+ssl_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence how)
+{
PORT_Assert(0);
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
return SECFailure;
}
static PRInt64 PR_CALLBACK
-ssl_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence how) {
+ssl_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence how)
+{
PRInt64 res;
PORT_Assert(0);
@@ -3067,85 +3361,83 @@ ssl_SendTo(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
static const PRIOMethods ssl_methods = {
PR_DESC_LAYERED,
- ssl_Close, /* close */
- ssl_Read, /* read */
- ssl_Write, /* write */
- ssl_Available, /* available */
- ssl_Available64, /* available64 */
- ssl_FSync, /* fsync */
- ssl_Seek, /* seek */
- ssl_Seek64, /* seek64 */
- ssl_FileInfo, /* fileInfo */
- ssl_FileInfo64, /* fileInfo64 */
- ssl_WriteV, /* writev */
- ssl_Connect, /* connect */
- ssl_Accept, /* accept */
- ssl_Bind, /* bind */
- ssl_Listen, /* listen */
- ssl_Shutdown, /* shutdown */
- ssl_Recv, /* recv */
- ssl_Send, /* send */
- ssl_RecvFrom, /* recvfrom */
- ssl_SendTo, /* sendto */
- ssl_Poll, /* poll */
- PR_EmulateAcceptRead, /* acceptread */
- ssl_TransmitFile, /* transmitfile */
- ssl_GetSockName, /* getsockname */
- ssl_GetPeerName, /* getpeername */
- NULL, /* getsockopt OBSOLETE */
- NULL, /* setsockopt OBSOLETE */
- NULL, /* getsocketoption */
- NULL, /* setsocketoption */
- PR_EmulateSendFile, /* Send a (partial) file with header/trailer*/
- NULL, /* reserved for future use */
- NULL, /* reserved for future use */
- NULL, /* reserved for future use */
- NULL, /* reserved for future use */
- NULL /* reserved for future use */
+ ssl_Close, /* close */
+ ssl_Read, /* read */
+ ssl_Write, /* write */
+ ssl_Available, /* available */
+ ssl_Available64, /* available64 */
+ ssl_FSync, /* fsync */
+ ssl_Seek, /* seek */
+ ssl_Seek64, /* seek64 */
+ ssl_FileInfo, /* fileInfo */
+ ssl_FileInfo64, /* fileInfo64 */
+ ssl_WriteV, /* writev */
+ ssl_Connect, /* connect */
+ ssl_Accept, /* accept */
+ ssl_Bind, /* bind */
+ ssl_Listen, /* listen */
+ ssl_Shutdown, /* shutdown */
+ ssl_Recv, /* recv */
+ ssl_Send, /* send */
+ ssl_RecvFrom, /* recvfrom */
+ ssl_SendTo, /* sendto */
+ ssl_Poll, /* poll */
+ PR_EmulateAcceptRead, /* acceptread */
+ ssl_TransmitFile, /* transmitfile */
+ ssl_GetSockName, /* getsockname */
+ ssl_GetPeerName, /* getpeername */
+ NULL, /* getsockopt OBSOLETE */
+ NULL, /* setsockopt OBSOLETE */
+ NULL, /* getsocketoption */
+ NULL, /* setsocketoption */
+ PR_EmulateSendFile, /* Send a (partial) file with header/trailer*/
+ NULL, /* reserved for future use */
+ NULL, /* reserved for future use */
+ NULL, /* reserved for future use */
+ NULL, /* reserved for future use */
+ NULL /* reserved for future use */
};
-
static PRIOMethods combined_methods;
static void
ssl_SetupIOMethods(void)
{
- PRIOMethods *new_methods = &combined_methods;
+ PRIOMethods *new_methods = &combined_methods;
const PRIOMethods *nspr_methods = PR_GetDefaultIOMethods();
- const PRIOMethods *my_methods = &ssl_methods;
+ const PRIOMethods *my_methods = &ssl_methods;
*new_methods = *nspr_methods;
- new_methods->file_type = my_methods->file_type;
- new_methods->close = my_methods->close;
- new_methods->read = my_methods->read;
- new_methods->write = my_methods->write;
- new_methods->available = my_methods->available;
- new_methods->available64 = my_methods->available64;
- new_methods->fsync = my_methods->fsync;
- new_methods->seek = my_methods->seek;
- new_methods->seek64 = my_methods->seek64;
- new_methods->fileInfo = my_methods->fileInfo;
- new_methods->fileInfo64 = my_methods->fileInfo64;
- new_methods->writev = my_methods->writev;
- new_methods->connect = my_methods->connect;
- new_methods->accept = my_methods->accept;
- new_methods->bind = my_methods->bind;
- new_methods->listen = my_methods->listen;
- new_methods->shutdown = my_methods->shutdown;
- new_methods->recv = my_methods->recv;
- new_methods->send = my_methods->send;
- new_methods->recvfrom = my_methods->recvfrom;
- new_methods->sendto = my_methods->sendto;
- new_methods->poll = my_methods->poll;
- new_methods->acceptread = my_methods->acceptread;
- new_methods->transmitfile = my_methods->transmitfile;
- new_methods->getsockname = my_methods->getsockname;
- new_methods->getpeername = my_methods->getpeername;
-/* new_methods->getsocketoption = my_methods->getsocketoption; */
-/* new_methods->setsocketoption = my_methods->setsocketoption; */
- new_methods->sendfile = my_methods->sendfile;
-
+ new_methods->file_type = my_methods->file_type;
+ new_methods->close = my_methods->close;
+ new_methods->read = my_methods->read;
+ new_methods->write = my_methods->write;
+ new_methods->available = my_methods->available;
+ new_methods->available64 = my_methods->available64;
+ new_methods->fsync = my_methods->fsync;
+ new_methods->seek = my_methods->seek;
+ new_methods->seek64 = my_methods->seek64;
+ new_methods->fileInfo = my_methods->fileInfo;
+ new_methods->fileInfo64 = my_methods->fileInfo64;
+ new_methods->writev = my_methods->writev;
+ new_methods->connect = my_methods->connect;
+ new_methods->accept = my_methods->accept;
+ new_methods->bind = my_methods->bind;
+ new_methods->listen = my_methods->listen;
+ new_methods->shutdown = my_methods->shutdown;
+ new_methods->recv = my_methods->recv;
+ new_methods->send = my_methods->send;
+ new_methods->recvfrom = my_methods->recvfrom;
+ new_methods->sendto = my_methods->sendto;
+ new_methods->poll = my_methods->poll;
+ new_methods->acceptread = my_methods->acceptread;
+ new_methods->transmitfile = my_methods->transmitfile;
+ new_methods->getsockname = my_methods->getsockname;
+ new_methods->getpeername = my_methods->getpeername;
+ /* new_methods->getsocketoption = my_methods->getsocketoption; */
+ /* new_methods->setsocketoption = my_methods->setsocketoption; */
+ new_methods->sendfile = my_methods->sendfile;
}
static PRCallOnceType initIoLayerOnce;
@@ -3162,8 +3454,8 @@ ssl_InitIOLayer(void)
static PRStatus
ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack, PRDescIdentity id)
{
- PRFileDesc *layer = NULL;
- PRStatus status;
+ PRFileDesc *layer = NULL;
+ PRStatus status;
if (!ssl_inited) {
status = PR_CallOnce(&initIoLayerOnce, &ssl_InitIOLayer);
@@ -3211,24 +3503,24 @@ ssl_MakeLocks(sslSocket *ss)
ss->firstHandshakeLock = PZ_NewMonitor(nssILockSSL);
if (!ss->firstHandshakeLock)
goto loser;
- ss->ssl3HandshakeLock = PZ_NewMonitor(nssILockSSL);
+ ss->ssl3HandshakeLock = PZ_NewMonitor(nssILockSSL);
if (!ss->ssl3HandshakeLock)
goto loser;
- ss->specLock = NSSRWLock_New(SSL_LOCK_RANK_SPEC, NULL);
+ ss->specLock = NSSRWLock_New(SSL_LOCK_RANK_SPEC, NULL);
if (!ss->specLock)
goto loser;
- ss->recvBufLock = PZ_NewMonitor(nssILockSSL);
+ ss->recvBufLock = PZ_NewMonitor(nssILockSSL);
if (!ss->recvBufLock)
goto loser;
- ss->xmitBufLock = PZ_NewMonitor(nssILockSSL);
+ ss->xmitBufLock = PZ_NewMonitor(nssILockSSL);
if (!ss->xmitBufLock)
goto loser;
- ss->writerThread = NULL;
+ ss->writerThread = NULL;
if (ssl_lock_readers) {
- ss->recvLock = PZ_NewLock(nssILockSSL);
+ ss->recvLock = PZ_NewLock(nssILockSSL);
if (!ss->recvLock)
goto loser;
- ss->sendLock = PZ_NewLock(nssILockSSL);
+ ss->sendLock = PZ_NewLock(nssILockSSL);
if (!ss->sendLock)
goto loser;
}
@@ -3242,19 +3534,19 @@ loser:
#define NSS_HAVE_GETENV 1
#endif
-#define LOWER(x) (x | 0x20) /* cheap ToLower function ignores LOCALE */
+#define LOWER(x) (x | 0x20) /* cheap ToLower function ignores LOCALE */
static void
ssl_SetDefaultsFromEnvironment(void)
{
-#if defined( NSS_HAVE_GETENV )
+#if defined(NSS_HAVE_GETENV)
static int firsttime = 1;
if (firsttime) {
- char * ev;
+ char *ev;
firsttime = 0;
#ifdef DEBUG
- ev = getenv("SSLDEBUGFILE");
+ ev = PR_GetEnvSecure("SSLDEBUGFILE");
if (ev && ev[0]) {
ssl_trace_iob = fopen(ev, "w");
}
@@ -3262,19 +3554,19 @@ ssl_SetDefaultsFromEnvironment(void)
ssl_trace_iob = stderr;
}
#ifdef TRACE
- ev = getenv("SSLTRACE");
+ ev = PR_GetEnvSecure("SSLTRACE");
if (ev && ev[0]) {
ssl_trace = atoi(ev);
SSL_TRACE(("SSL: tracing set to %d", ssl_trace));
}
#endif /* TRACE */
- ev = getenv("SSLDEBUG");
+ ev = PR_GetEnvSecure("SSLDEBUG");
if (ev && ev[0]) {
ssl_debug = atoi(ev);
SSL_TRACE(("SSL: debugging set to %d", ssl_debug));
}
#endif /* DEBUG */
- ev = getenv("SSLKEYLOGFILE");
+ ev = PR_GetEnvSecure("SSLKEYLOGFILE");
if (ev && ev[0]) {
ssl_keylog_iob = fopen(ev, "a");
if (!ssl_keylog_iob) {
@@ -3288,21 +3580,21 @@ ssl_SetDefaultsFromEnvironment(void)
}
}
#ifndef NO_PKCS11_BYPASS
- ev = getenv("SSLBYPASS");
+ ev = PR_GetEnvSecure("SSLBYPASS");
if (ev && ev[0]) {
ssl_defaults.bypassPKCS11 = (ev[0] == '1');
- SSL_TRACE(("SSL: bypass default set to %d", \
- ssl_defaults.bypassPKCS11));
+ SSL_TRACE(("SSL: bypass default set to %d",
+ ssl_defaults.bypassPKCS11));
}
#endif /* NO_PKCS11_BYPASS */
- ev = getenv("SSLFORCELOCKS");
+ ev = PR_GetEnvSecure("SSLFORCELOCKS");
if (ev && ev[0] == '1') {
ssl_force_locks = PR_TRUE;
ssl_defaults.noLocks = 0;
strcpy(lockStatus + LOCKSTATUS_OFFSET, "FORCED. ");
SSL_TRACE(("SSL: force_locks set to %d", ssl_force_locks));
}
- ev = getenv("NSS_SSL_ENABLE_RENEGOTIATION");
+ ev = PR_GetEnvSecure("NSS_SSL_ENABLE_RENEGOTIATION");
if (ev) {
if (ev[0] == '1' || LOWER(ev[0]) == 'u')
ssl_defaults.enableRenegotiation = SSL_RENEGOTIATE_UNRESTRICTED;
@@ -3315,13 +3607,13 @@ ssl_SetDefaultsFromEnvironment(void)
SSL_TRACE(("SSL: enableRenegotiation set to %d",
ssl_defaults.enableRenegotiation));
}
- ev = getenv("NSS_SSL_REQUIRE_SAFE_NEGOTIATION");
+ ev = PR_GetEnvSecure("NSS_SSL_REQUIRE_SAFE_NEGOTIATION");
if (ev && ev[0] == '1') {
ssl_defaults.requireSafeNegotiation = PR_TRUE;
SSL_TRACE(("SSL: requireSafeNegotiation set to %d",
- PR_TRUE));
+ PR_TRUE));
}
- ev = getenv("NSS_SSL_CBC_RANDOM_IV");
+ ev = PR_GetEnvSecure("NSS_SSL_CBC_RANDOM_IV");
if (ev && ev[0] == '0') {
ssl_defaults.cbcRandomIV = PR_FALSE;
SSL_TRACE(("SSL: cbcRandomIV set to 0"));
@@ -3344,7 +3636,7 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
makeLocks = PR_TRUE;
/* Make a new socket and get it ready */
- ss = (sslSocket*) PORT_ZAlloc(sizeof(sslSocket));
+ ss = (sslSocket *)PORT_ZAlloc(sizeof(sslSocket));
if (ss) {
/* This should be of type SSLKEAType, but CC on IRIX
* complains during the for loop.
@@ -3352,58 +3644,55 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
int i;
SECStatus status;
- ss->opt = ssl_defaults;
- ss->opt.useSocks = PR_FALSE;
- ss->opt.noLocks = !makeLocks;
- ss->vrange = *VERSIONS_DEFAULTS(protocolVariant);
- ss->protocolVariant = protocolVariant;
-
- ss->peerID = NULL;
- ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;
- ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;
- ss->cTimeout = PR_INTERVAL_NO_TIMEOUT;
- ss->cipherSpecs = NULL;
- ss->sizeCipherSpecs = 0; /* produced lazily */
- ss->preferredCipher = NULL;
- ss->url = NULL;
-
- for (i=kt_null; i < kt_kea_size; i++) {
- sslServerCerts * sc = ss->serverCerts + i;
- sc->serverCert = NULL;
+ ss->opt = ssl_defaults;
+ ss->opt.useSocks = PR_FALSE;
+ ss->opt.noLocks = !makeLocks;
+ ss->vrange = *VERSIONS_DEFAULTS(protocolVariant);
+ ss->protocolVariant = protocolVariant;
+
+ ss->peerID = NULL;
+ ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;
+ ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;
+ ss->cTimeout = PR_INTERVAL_NO_TIMEOUT;
+ ss->cipherSpecs = NULL;
+ ss->sizeCipherSpecs = 0; /* produced lazily */
+ ss->preferredCipher = NULL;
+ ss->url = NULL;
+
+ for (i = kt_null; i < kt_kea_size; i++) {
+ sslServerCerts *sc = ss->serverCerts + i;
+ sc->serverCert = NULL;
sc->serverCertChain = NULL;
- sc->serverKeyPair = NULL;
- sc->serverKeyBits = 0;
+ sc->serverKeyPair = NULL;
+ sc->serverKeyBits = 0;
ss->certStatusArray[i] = NULL;
}
ss->requestedCertTypes = NULL;
- ss->stepDownKeyPair = NULL;
+ ss->stepDownKeyPair = NULL;
ss->dheParams = NULL;
ss->dheKeyPair = NULL;
- ss->dbHandle = CERT_GetDefaultCertDB();
+ ss->dbHandle = CERT_GetDefaultCertDB();
/* Provide default implementation of hooks */
- ss->authCertificate = SSL_AuthCertificate;
+ ss->authCertificate = SSL_AuthCertificate;
ss->authCertificateArg = (void *)ss->dbHandle;
- ss->sniSocketConfig = NULL;
+ ss->sniSocketConfig = NULL;
ss->sniSocketConfigArg = NULL;
- ss->getClientAuthData = NULL;
-#ifdef NSS_PLATFORM_CLIENT_AUTH
- ss->getPlatformClientAuthData = NULL;
- ss->getPlatformClientAuthDataArg = NULL;
-#endif /* NSS_PLATFORM_CLIENT_AUTH */
- ss->handleBadCert = NULL;
- ss->badCertArg = NULL;
- ss->pkcs11PinArg = NULL;
+ ss->getClientAuthData = NULL;
+ ss->handleBadCert = NULL;
+ ss->badCertArg = NULL;
+ ss->pkcs11PinArg = NULL;
ss->ephemeralECDHKeyPair = NULL;
- ss->getChannelID = NULL;
- ss->getChannelIDArg = NULL;
+ ss->getChannelID = NULL;
+ ss->getChannelIDArg = NULL;
ssl_ChooseOps(ss);
ssl2_InitSocketPolicy(ss);
ssl3_InitSocketPolicy(ss);
PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight);
+ PR_INIT_CLIST(&ss->ssl3.hs.remoteKeyShares);
if (makeLocks) {
status = ssl_MakeLocks(ss);
@@ -3415,7 +3704,7 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
goto loser;
status = ssl_InitGather(&ss->gs);
if (status != SECSuccess) {
-loser:
+ loser:
ssl_DestroySocketContents(ss);
ssl_DestroyLocks(ss);
PORT_Free(ss);
diff --git a/chromium/net/third_party/nss/ssl/sslt.h b/chromium/net/third_party/nss/ssl/sslt.h
index 36e34dfb8d0..6f26e5fd917 100644
--- a/chromium/net/third_party/nss/ssl/sslt.h
+++ b/chromium/net/third_party/nss/ssl/sslt.h
@@ -11,19 +11,6 @@
#include "prtypes.h"
-/* SECItemArray is added in NSS 3.15. Define the type if compiling
-** against an older version of NSS.
-*/
-#include "nssutil.h"
-#if NSSUTIL_VMAJOR == 3 && NSSUTIL_VMINOR < 15
-typedef struct SECItemArrayStr SECItemArray;
-
-struct SECItemArrayStr {
- SECItem *items;
- unsigned int len;
-};
-#endif /* NSSUTIL_VMAJOR == 3 && NSSUTIL_VMINOR < 15 */
-
typedef struct SSL3StatisticsStr {
/* statistics from ssl3_SendClientHello (sch) */
long sch_sid_cache_hits;
@@ -49,12 +36,12 @@ typedef struct SSL3StatisticsStr {
/* Key Exchange algorithm values */
typedef enum {
- ssl_kea_null = 0,
- ssl_kea_rsa = 1,
- ssl_kea_dh = 2,
- ssl_kea_fortezza = 3, /* deprecated, now unused */
- ssl_kea_ecdh = 4,
- ssl_kea_size /* number of ssl_kea_ algorithms */
+ ssl_kea_null = 0,
+ ssl_kea_rsa = 1,
+ ssl_kea_dh = 2,
+ ssl_kea_fortezza = 3, /* deprecated, now unused */
+ ssl_kea_ecdh = 4,
+ ssl_kea_size /* number of ssl_kea_ algorithms */
} SSLKEAType;
/* The following defines are for backwards compatibility.
@@ -62,21 +49,20 @@ typedef enum {
** programs that use the kt_ symbols should convert to the ssl_kt_ symbols
** soon.
*/
-#define kt_null ssl_kea_null
-#define kt_rsa ssl_kea_rsa
-#define kt_dh ssl_kea_dh
-#define kt_fortezza ssl_kea_fortezza /* deprecated, now unused */
-#define kt_ecdh ssl_kea_ecdh
-#define kt_kea_size ssl_kea_size
-
+#define kt_null ssl_kea_null
+#define kt_rsa ssl_kea_rsa
+#define kt_dh ssl_kea_dh
+#define kt_fortezza ssl_kea_fortezza /* deprecated, now unused */
+#define kt_ecdh ssl_kea_ecdh
+#define kt_kea_size ssl_kea_size
/* Values of this enum match the SignatureAlgorithm enum from
* https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
typedef enum {
- ssl_sign_null = 0, /* "anonymous" in TLS */
- ssl_sign_rsa = 1,
- ssl_sign_dsa = 2,
- ssl_sign_ecdsa = 3
+ ssl_sign_null = 0, /* "anonymous" in TLS */
+ ssl_sign_rsa = 1,
+ ssl_sign_dsa = 2,
+ ssl_sign_ecdsa = 3
} SSLSignType;
/* Values of this enum match the HashAlgorithm enum from
@@ -99,81 +85,86 @@ typedef struct SSLSignatureAndHashAlgStr {
} SSLSignatureAndHashAlg;
typedef enum {
- ssl_auth_null = 0,
- ssl_auth_rsa = 1,
- ssl_auth_dsa = 2,
- ssl_auth_kea = 3,
- ssl_auth_ecdsa = 4
+ ssl_auth_null = 0,
+ ssl_auth_rsa = 1,
+ ssl_auth_dsa = 2,
+ ssl_auth_kea = 3,
+ ssl_auth_ecdsa = 4
} SSLAuthType;
typedef enum {
- ssl_calg_null = 0,
- ssl_calg_rc4 = 1,
- ssl_calg_rc2 = 2,
- ssl_calg_des = 3,
- ssl_calg_3des = 4,
- ssl_calg_idea = 5,
- ssl_calg_fortezza = 6, /* deprecated, now unused */
- ssl_calg_aes = 7,
+ ssl_calg_null = 0,
+ ssl_calg_rc4 = 1,
+ ssl_calg_rc2 = 2,
+ ssl_calg_des = 3,
+ ssl_calg_3des = 4,
+ ssl_calg_idea = 5,
+ ssl_calg_fortezza = 6, /* deprecated, now unused */
+ ssl_calg_aes = 7,
ssl_calg_camellia = 8,
- ssl_calg_seed = 9,
- ssl_calg_aes_gcm = 10,
+ ssl_calg_seed = 9,
+ ssl_calg_aes_gcm = 10,
ssl_calg_chacha20 = 11
} SSLCipherAlgorithm;
-typedef enum {
- ssl_mac_null = 0,
- ssl_mac_md5 = 1,
- ssl_mac_sha = 2,
- ssl_hmac_md5 = 3, /* TLS HMAC version of mac_md5 */
- ssl_hmac_sha = 4, /* TLS HMAC version of mac_sha */
- ssl_hmac_sha256 = 5,
- ssl_mac_aead = 6
+typedef enum {
+ ssl_mac_null = 0,
+ ssl_mac_md5 = 1,
+ ssl_mac_sha = 2,
+ ssl_hmac_md5 = 3, /* TLS HMAC version of mac_md5 */
+ ssl_hmac_sha = 4, /* TLS HMAC version of mac_sha */
+ ssl_hmac_sha256 = 5,
+ ssl_mac_aead = 6
} SSLMACAlgorithm;
typedef enum {
ssl_compression_null = 0,
- ssl_compression_deflate = 1 /* RFC 3749 */
+ ssl_compression_deflate = 1 /* RFC 3749 */
} SSLCompressionMethod;
typedef struct SSLChannelInfoStr {
- PRUint32 length;
- PRUint16 protocolVersion;
- PRUint16 cipherSuite;
+ /* |length| is obsolete. On return, SSL_GetChannelInfo sets |length| to the
+ * smaller of the |len| argument and the length of the struct. The caller
+ * may ignore |length|. */
+ PRUint32 length;
+ PRUint16 protocolVersion;
+ PRUint16 cipherSuite;
/* server authentication info */
- PRUint32 authKeyBits;
+ PRUint32 authKeyBits;
/* key exchange algorithm info */
- PRUint32 keaKeyBits;
+ PRUint32 keaKeyBits;
/* session info */
- PRUint32 creationTime; /* seconds since Jan 1, 1970 */
- PRUint32 lastAccessTime; /* seconds since Jan 1, 1970 */
- PRUint32 expirationTime; /* seconds since Jan 1, 1970 */
- PRUint32 sessionIDLength; /* up to 32 */
- PRUint8 sessionID [32];
+ PRUint32 creationTime; /* seconds since Jan 1, 1970 */
+ PRUint32 lastAccessTime; /* seconds since Jan 1, 1970 */
+ PRUint32 expirationTime; /* seconds since Jan 1, 1970 */
+ PRUint32 sessionIDLength; /* up to 32 */
+ PRUint8 sessionID[32];
/* The following fields are added in NSS 3.12.5. */
/* compression method info */
- const char * compressionMethodName;
+ const char* compressionMethodName;
SSLCompressionMethod compressionMethod;
/* The following fields are added in NSS 3.21.
* This field only has meaning in TLS < 1.3 and will be set to
* PR_FALSE in TLS 1.3.
*/
- PRBool extendedMasterSecretUsed;
+ PRBool extendedMasterSecretUsed;
} SSLChannelInfo;
/* Preliminary channel info */
#define ssl_preinfo_version (1U << 0)
#define ssl_preinfo_cipher_suite (1U << 1)
-#define ssl_preinfo_all (ssl_preinfo_version|ssl_preinfo_cipher_suite)
+#define ssl_preinfo_all (ssl_preinfo_version | ssl_preinfo_cipher_suite)
typedef struct SSLPreliminaryChannelInfoStr {
- /* This is set to the length of the struct. */
+ /* |length| is obsolete. On return, SSL_GetPreliminaryChannelInfo sets
+ * |length| to the smaller of the |len| argument and the length of the
+ * struct. The caller may ignore |length|. */
PRUint32 length;
/* A bitfield over SSLPreliminaryValueSet that describes which
* preliminary values are set (see ssl_preinfo_*). */
@@ -185,39 +176,42 @@ typedef struct SSLPreliminaryChannelInfoStr {
} SSLPreliminaryChannelInfo;
typedef struct SSLCipherSuiteInfoStr {
- PRUint16 length;
- PRUint16 cipherSuite;
+ /* |length| is obsolete. On return, SSL_GetCipherSuitelInfo sets |length|
+ * to the smaller of the |len| argument and the length of the struct. The
+ * caller may ignore |length|. */
+ PRUint16 length;
+ PRUint16 cipherSuite;
/* Cipher Suite Name */
- const char * cipherSuiteName;
+ const char* cipherSuiteName;
/* server authentication info */
- const char * authAlgorithmName;
- SSLAuthType authAlgorithm;
+ const char* authAlgorithmName;
+ SSLAuthType authAlgorithm;
/* key exchange algorithm info */
- const char * keaTypeName;
- SSLKEAType keaType;
+ const char* keaTypeName;
+ SSLKEAType keaType;
/* symmetric encryption info */
- const char * symCipherName;
- SSLCipherAlgorithm symCipher;
- PRUint16 symKeyBits;
- PRUint16 symKeySpace;
- PRUint16 effectiveKeyBits;
+ const char* symCipherName;
+ SSLCipherAlgorithm symCipher;
+ PRUint16 symKeyBits;
+ PRUint16 symKeySpace;
+ PRUint16 effectiveKeyBits;
/* MAC info */
/* AEAD ciphers don't have a MAC. For an AEAD cipher, macAlgorithmName
* is "AEAD", macAlgorithm is ssl_mac_aead, and macBits is the length in
* bits of the authentication tag. */
- const char * macAlgorithmName;
- SSLMACAlgorithm macAlgorithm;
- PRUint16 macBits;
+ const char* macAlgorithmName;
+ SSLMACAlgorithm macAlgorithm;
+ PRUint16 macBits;
- PRUintn isFIPS : 1;
- PRUintn isExportable : 1;
- PRUintn nonStandard : 1;
- PRUintn reservedBits :29;
+ PRUintn isFIPS : 1;
+ PRUintn isExportable : 1;
+ PRUintn nonStandard : 1;
+ PRUintn reservedBits : 29;
} SSLCipherSuiteInfo;
@@ -232,33 +226,35 @@ typedef struct SSLVersionRangeStr {
} SSLVersionRange;
typedef enum {
- SSL_sni_host_name = 0,
+ SSL_sni_host_name = 0,
SSL_sni_type_total
} SSLSniNameType;
/* Supported extensions. */
/* Update SSL_MAX_EXTENSIONS whenever a new extension type is added. */
typedef enum {
- ssl_server_name_xtn = 0,
- ssl_cert_status_xtn = 5,
+ ssl_server_name_xtn = 0,
+ ssl_cert_status_xtn = 5,
#ifndef NSS_DISABLE_ECC
- ssl_elliptic_curves_xtn = 10,
- ssl_ec_point_formats_xtn = 11,
+ ssl_elliptic_curves_xtn = 10,
+ ssl_ec_point_formats_xtn = 11,
#endif
- ssl_signature_algorithms_xtn = 13,
- ssl_use_srtp_xtn = 14,
- ssl_app_layer_protocol_xtn = 16,
- ssl_signed_certificate_timestamp_xtn = 18, /* RFC 6962 */
- ssl_padding_xtn = 21,
- ssl_extended_master_secret_xtn = 23,
- ssl_session_ticket_xtn = 35,
- ssl_next_proto_nego_xtn = 13172,
- ssl_channel_id_xtn = 30032,
- ssl_renegotiation_info_xtn = 0xff01,
- ssl_tls13_draft_version_xtn = 0xff02 /* experimental number */
+ ssl_signature_algorithms_xtn = 13,
+ ssl_use_srtp_xtn = 14,
+ ssl_app_layer_protocol_xtn = 16,
+ /* signed_certificate_timestamp extension, RFC 6962 */
+ ssl_signed_cert_timestamp_xtn = 18,
+ ssl_padding_xtn = 21,
+ ssl_extended_master_secret_xtn = 23,
+ ssl_session_ticket_xtn = 35,
+ ssl_tls13_key_share_xtn = 40, /* unofficial TODO(ekr) */
+ ssl_next_proto_nego_xtn = 13172,
+ ssl_channel_id_xtn = 30032,
+ ssl_renegotiation_info_xtn = 0xff01,
+ ssl_tls13_draft_version_xtn = 0xff02 /* experimental number */
} SSLExtensionType;
-#define SSL_MAX_EXTENSIONS 14 /* doesn't include ssl_padding_xtn. */
+#define SSL_MAX_EXTENSIONS 15 /* doesn't include ssl_padding_xtn. */
typedef enum {
ssl_dhe_group_none = 0,
diff --git a/chromium/net/third_party/nss/ssl/ssltrace.c b/chromium/net/third_party/nss/ssl/ssltrace.c
index ee540d58751..6be9a6da350 100644
--- a/chromium/net/third_party/nss/ssl/ssltrace.c
+++ b/chromium/net/third_party/nss/ssl/ssltrace.c
@@ -15,25 +15,26 @@
static const char *hex = "0123456789abcdef";
static const char printable[257] = {
- "................" /* 0x */
- "................" /* 1x */
- " !\"#$%&'()*+,-./" /* 2x */
- "0123456789:;<=>?" /* 3x */
- "@ABCDEFGHIJKLMNO" /* 4x */
- "PQRSTUVWXYZ[\\]^_" /* 5x */
- "`abcdefghijklmno" /* 6x */
- "pqrstuvwxyz{|}~." /* 7x */
- "................" /* 8x */
- "................" /* 9x */
- "................" /* ax */
- "................" /* bx */
- "................" /* cx */
- "................" /* dx */
- "................" /* ex */
- "................" /* fx */
+ "................" /* 0x */
+ "................" /* 1x */
+ " !\"#$%&'()*+,-./" /* 2x */
+ "0123456789:;<=>?" /* 3x */
+ "@ABCDEFGHIJKLMNO" /* 4x */
+ "PQRSTUVWXYZ[\\]^_" /* 5x */
+ "`abcdefghijklmno" /* 6x */
+ "pqrstuvwxyz{|}~." /* 7x */
+ "................" /* 8x */
+ "................" /* 9x */
+ "................" /* ax */
+ "................" /* bx */
+ "................" /* cx */
+ "................" /* dx */
+ "................" /* ex */
+ "................" /* fx */
};
-void ssl_PrintBuf(sslSocket *ss, const char *msg, const void *vp, int len)
+void
+ssl_PrintBuf(sslSocket *ss, const char *msg, const void *vp, int len)
{
const unsigned char *cp = (const unsigned char *)vp;
char buf[80];
@@ -41,53 +42,53 @@ void ssl_PrintBuf(sslSocket *ss, const char *msg, const void *vp, int len)
char *ap;
if (ss) {
- SSL_TRACE(("%d: SSL[%d]: %s [Len: %d]", SSL_GETPID(), ss->fd,
- msg, len));
+ SSL_TRACE(("%d: SSL[%d]: %s [Len: %d]", SSL_GETPID(), ss->fd,
+ msg, len));
} else {
- SSL_TRACE(("%d: SSL: %s [Len: %d]", SSL_GETPID(), msg, len));
+ SSL_TRACE(("%d: SSL: %s [Len: %d]", SSL_GETPID(), msg, len));
}
memset(buf, ' ', sizeof buf);
bp = buf;
ap = buf + 50;
while (--len >= 0) {
- unsigned char ch = *cp++;
- *bp++ = hex[(ch >> 4) & 0xf];
- *bp++ = hex[ch & 0xf];
- *bp++ = ' ';
- *ap++ = printable[ch];
- if (ap - buf >= 66) {
- *ap = 0;
- SSL_TRACE((" %s", buf));
- memset(buf, ' ', sizeof buf);
- bp = buf;
- ap = buf + 50;
- }
+ unsigned char ch = *cp++;
+ *bp++ = hex[(ch >> 4) & 0xf];
+ *bp++ = hex[ch & 0xf];
+ *bp++ = ' ';
+ *ap++ = printable[ch];
+ if (ap - buf >= 66) {
+ *ap = 0;
+ SSL_TRACE((" %s", buf));
+ memset(buf, ' ', sizeof buf);
+ bp = buf;
+ ap = buf + 50;
+ }
}
if (bp > buf) {
- *ap = 0;
- SSL_TRACE((" %s", buf));
+ *ap = 0;
+ SSL_TRACE((" %s", buf));
}
}
-#define LEN(cp) (((cp)[0] << 8) | ((cp)[1]))
+#define LEN(cp) (((cp)[0] << 8) | ((cp)[1]))
-static void PrintType(sslSocket *ss, char *msg)
+static void
+PrintType(sslSocket *ss, char *msg)
{
if (ss) {
- SSL_TRACE(("%d: SSL[%d]: dump-msg: %s", SSL_GETPID(), ss->fd,
- msg));
+ SSL_TRACE(("%d: SSL[%d]: dump-msg: %s", SSL_GETPID(), ss->fd, msg));
} else {
- SSL_TRACE(("%d: SSL: dump-msg: %s", SSL_GETPID(), msg));
+ SSL_TRACE(("%d: SSL: dump-msg: %s", SSL_GETPID(), msg));
}
}
-static void PrintInt(sslSocket *ss, char *msg, unsigned v)
+static void
+PrintInt(sslSocket *ss, char *msg, unsigned v)
{
if (ss) {
- SSL_TRACE(("%d: SSL[%d]: %s=%u", SSL_GETPID(), ss->fd,
- msg, v));
+ SSL_TRACE(("%d: SSL[%d]: %s=%u", SSL_GETPID(), ss->fd, msg, v));
} else {
- SSL_TRACE(("%d: SSL: %s=%u", SSL_GETPID(), msg, v));
+ SSL_TRACE(("%d: SSL: %s=%u", SSL_GETPID(), msg, v));
}
}
@@ -95,149 +96,143 @@ static void PrintInt(sslSocket *ss, char *msg, unsigned v)
* a) It prefixes each line of the buffer with "XX: SSL[xxx] "
* b) It dumps only hex, not ASCII.
*/
-static void PrintBuf(sslSocket *ss, char *msg, unsigned char *cp, int len)
+static void
+PrintBuf(sslSocket *ss, char *msg, unsigned char *cp, int len)
{
char buf[80];
char *bp;
if (ss) {
- SSL_TRACE(("%d: SSL[%d]: %s [Len: %d]",
- SSL_GETPID(), ss->fd, msg, len));
+ SSL_TRACE(("%d: SSL[%d]: %s [Len: %d]",
+ SSL_GETPID(), ss->fd, msg, len));
} else {
- SSL_TRACE(("%d: SSL: %s [Len: %d]",
- SSL_GETPID(), msg, len));
+ SSL_TRACE(("%d: SSL: %s [Len: %d]",
+ SSL_GETPID(), msg, len));
}
bp = buf;
while (--len >= 0) {
- unsigned char ch = *cp++;
- *bp++ = hex[(ch >> 4) & 0xf];
- *bp++ = hex[ch & 0xf];
- *bp++ = ' ';
- if (bp + 4 > buf + 50) {
- *bp = 0;
- if (ss) {
- SSL_TRACE(("%d: SSL[%d]: %s",
- SSL_GETPID(), ss->fd, buf));
- } else {
- SSL_TRACE(("%d: SSL: %s", SSL_GETPID(), buf));
- }
- bp = buf;
- }
+ unsigned char ch = *cp++;
+ *bp++ = hex[(ch >> 4) & 0xf];
+ *bp++ = hex[ch & 0xf];
+ *bp++ = ' ';
+ if (bp + 4 > buf + 50) {
+ *bp = 0;
+ if (ss) {
+ SSL_TRACE(("%d: SSL[%d]: %s",
+ SSL_GETPID(), ss->fd, buf));
+ } else {
+ SSL_TRACE(("%d: SSL: %s", SSL_GETPID(), buf));
+ }
+ bp = buf;
+ }
}
if (bp > buf) {
- *bp = 0;
- if (ss) {
- SSL_TRACE(("%d: SSL[%d]: %s",
- SSL_GETPID(), ss->fd, buf));
- } else {
- SSL_TRACE(("%d: SSL: %s", SSL_GETPID(), buf));
- }
+ *bp = 0;
+ if (ss) {
+ SSL_TRACE(("%d: SSL[%d]: %s",
+ SSL_GETPID(), ss->fd, buf));
+ } else {
+ SSL_TRACE(("%d: SSL: %s", SSL_GETPID(), buf));
+ }
}
}
-void ssl_DumpMsg(sslSocket *ss, unsigned char *bp, unsigned len)
+void
+ssl_DumpMsg(sslSocket *ss, unsigned char *bp, unsigned len)
{
switch (bp[0]) {
- case SSL_MT_ERROR:
- PrintType(ss, "Error");
- PrintInt(ss, "error", LEN(bp+1));
- break;
-
- case SSL_MT_CLIENT_HELLO:
- {
- unsigned lcs = LEN(bp+3);
- unsigned ls = LEN(bp+5);
- unsigned lc = LEN(bp+7);
-
- PrintType(ss, "Client-Hello");
-
- PrintInt(ss, "version (Major)", bp[1]);
- PrintInt(ss, "version (minor)", bp[2]);
-
- PrintBuf(ss, "cipher-specs", bp+9, lcs);
- PrintBuf(ss, "session-id", bp+9+lcs, ls);
- PrintBuf(ss, "challenge", bp+9+lcs+ls, lc);
- }
- break;
- case SSL_MT_CLIENT_MASTER_KEY:
- {
- unsigned lck = LEN(bp+4);
- unsigned lek = LEN(bp+6);
- unsigned lka = LEN(bp+8);
-
- PrintType(ss, "Client-Master-Key");
-
- PrintInt(ss, "cipher-choice", bp[1]);
- PrintInt(ss, "key-length", LEN(bp+2));
-
- PrintBuf(ss, "clear-key", bp+10, lck);
- PrintBuf(ss, "encrypted-key", bp+10+lck, lek);
- PrintBuf(ss, "key-arg", bp+10+lck+lek, lka);
- }
- break;
- case SSL_MT_CLIENT_FINISHED:
- PrintType(ss, "Client-Finished");
- PrintBuf(ss, "connection-id", bp+1, len-1);
- break;
- case SSL_MT_SERVER_HELLO:
- {
- unsigned lc = LEN(bp+5);
- unsigned lcs = LEN(bp+7);
- unsigned lci = LEN(bp+9);
-
- PrintType(ss, "Server-Hello");
-
- PrintInt(ss, "session-id-hit", bp[1]);
- PrintInt(ss, "certificate-type", bp[2]);
- PrintInt(ss, "version (Major)", bp[3]);
- PrintInt(ss, "version (minor)", bp[3]);
- PrintBuf(ss, "certificate", bp+11, lc);
- PrintBuf(ss, "cipher-specs", bp+11+lc, lcs);
- PrintBuf(ss, "connection-id", bp+11+lc+lcs, lci);
- }
- break;
- case SSL_MT_SERVER_VERIFY:
- PrintType(ss, "Server-Verify");
- PrintBuf(ss, "challenge", bp+1, len-1);
- break;
- case SSL_MT_SERVER_FINISHED:
- PrintType(ss, "Server-Finished");
- PrintBuf(ss, "session-id", bp+1, len-1);
- break;
- case SSL_MT_REQUEST_CERTIFICATE:
- PrintType(ss, "Request-Certificate");
- PrintInt(ss, "authentication-type", bp[1]);
- PrintBuf(ss, "certificate-challenge", bp+2, len-2);
- break;
- case SSL_MT_CLIENT_CERTIFICATE:
- {
- unsigned lc = LEN(bp+2);
- unsigned lr = LEN(bp+4);
- PrintType(ss, "Client-Certificate");
- PrintInt(ss, "certificate-type", bp[1]);
- PrintBuf(ss, "certificate", bp+6, lc);
- PrintBuf(ss, "response", bp+6+lc, lr);
- }
- break;
- default:
- ssl_PrintBuf(ss, "sending *unknown* message type", bp, len);
- return;
+ case SSL_MT_ERROR:
+ PrintType(ss, "Error");
+ PrintInt(ss, "error", LEN(bp + 1));
+ break;
+
+ case SSL_MT_CLIENT_HELLO: {
+ unsigned lcs = LEN(bp + 3);
+ unsigned ls = LEN(bp + 5);
+ unsigned lc = LEN(bp + 7);
+
+ PrintType(ss, "Client-Hello");
+
+ PrintInt(ss, "version (Major)", bp[1]);
+ PrintInt(ss, "version (minor)", bp[2]);
+
+ PrintBuf(ss, "cipher-specs", bp + 9, lcs);
+ PrintBuf(ss, "session-id", bp + 9 + lcs, ls);
+ PrintBuf(ss, "challenge", bp + 9 + lcs + ls, lc);
+ } break;
+ case SSL_MT_CLIENT_MASTER_KEY: {
+ unsigned lck = LEN(bp + 4);
+ unsigned lek = LEN(bp + 6);
+ unsigned lka = LEN(bp + 8);
+
+ PrintType(ss, "Client-Master-Key");
+
+ PrintInt(ss, "cipher-choice", bp[1]);
+ PrintInt(ss, "key-length", LEN(bp + 2));
+
+ PrintBuf(ss, "clear-key", bp + 10, lck);
+ PrintBuf(ss, "encrypted-key", bp + 10 + lck, lek);
+ PrintBuf(ss, "key-arg", bp + 10 + lck + lek, lka);
+ } break;
+ case SSL_MT_CLIENT_FINISHED:
+ PrintType(ss, "Client-Finished");
+ PrintBuf(ss, "connection-id", bp + 1, len - 1);
+ break;
+ case SSL_MT_SERVER_HELLO: {
+ unsigned lc = LEN(bp + 5);
+ unsigned lcs = LEN(bp + 7);
+ unsigned lci = LEN(bp + 9);
+
+ PrintType(ss, "Server-Hello");
+
+ PrintInt(ss, "session-id-hit", bp[1]);
+ PrintInt(ss, "certificate-type", bp[2]);
+ PrintInt(ss, "version (Major)", bp[3]);
+ PrintInt(ss, "version (minor)", bp[3]);
+ PrintBuf(ss, "certificate", bp + 11, lc);
+ PrintBuf(ss, "cipher-specs", bp + 11 + lc, lcs);
+ PrintBuf(ss, "connection-id", bp + 11 + lc + lcs, lci);
+ } break;
+ case SSL_MT_SERVER_VERIFY:
+ PrintType(ss, "Server-Verify");
+ PrintBuf(ss, "challenge", bp + 1, len - 1);
+ break;
+ case SSL_MT_SERVER_FINISHED:
+ PrintType(ss, "Server-Finished");
+ PrintBuf(ss, "session-id", bp + 1, len - 1);
+ break;
+ case SSL_MT_REQUEST_CERTIFICATE:
+ PrintType(ss, "Request-Certificate");
+ PrintInt(ss, "authentication-type", bp[1]);
+ PrintBuf(ss, "certificate-challenge", bp + 2, len - 2);
+ break;
+ case SSL_MT_CLIENT_CERTIFICATE: {
+ unsigned lc = LEN(bp + 2);
+ unsigned lr = LEN(bp + 4);
+ PrintType(ss, "Client-Certificate");
+ PrintInt(ss, "certificate-type", bp[1]);
+ PrintBuf(ss, "certificate", bp + 6, lc);
+ PrintBuf(ss, "response", bp + 6 + lc, lr);
+ } break;
+ default:
+ ssl_PrintBuf(ss, "sending *unknown* message type", bp, len);
+ return;
}
}
void
-ssl_Trace(const char *format, ... )
+ssl_Trace(const char *format, ...)
{
- char buf[2000];
+ char buf[2000];
va_list args;
if (ssl_trace_iob) {
- va_start(args, format);
- PR_vsnprintf(buf, sizeof(buf), format, args);
- va_end(args);
+ va_start(args, format);
+ PR_vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
- fputs(buf, ssl_trace_iob);
- fputs("\n", ssl_trace_iob);
+ fputs(buf, ssl_trace_iob);
+ fputs("\n", ssl_trace_iob);
}
}
#endif
diff --git a/chromium/net/third_party/nss/ssl/tls13con.c b/chromium/net/third_party/nss/ssl/tls13con.c
new file mode 100644
index 00000000000..4bb136a5eef
--- /dev/null
+++ b/chromium/net/third_party/nss/ssl/tls13con.c
@@ -0,0 +1,2059 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * TLS 1.3 Protocol
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "stdarg.h"
+#include "cert.h"
+#include "ssl.h"
+#include "keyhi.h"
+#include "pk11func.h"
+#include "secitem.h"
+#include "sslimpl.h"
+#include "sslproto.h"
+#include "sslerr.h"
+#include "tls13hkdf.h"
+#include "tls13con.h"
+
+typedef enum {
+ TrafficKeyEarlyData,
+ TrafficKeyHandshake,
+ TrafficKeyApplicationData
+} TrafficKeyType;
+
+typedef enum {
+ InstallCipherSpecRead,
+ InstallCipherSpecWrite,
+ InstallCipherSpecBoth
+} InstallCipherSpecDirection;
+
+#define MAX_FINISHED_SIZE 64
+
+static SECStatus tls13_InitializeHandshakeEncryption(sslSocket *ss);
+static SECStatus tls13_InstallCipherSpec(
+ sslSocket *ss, InstallCipherSpecDirection direction);
+static SECStatus tls13_InitCipherSpec(
+ sslSocket *ss, TrafficKeyType type, InstallCipherSpecDirection install);
+static SECStatus tls13_AESGCM(
+ ssl3KeyMaterial *keys,
+ PRBool doDecrypt,
+ unsigned char *out, int *outlen, int maxout,
+ const unsigned char *in, int inlen,
+ const unsigned char *additionalData, int additionalDataLen);
+static SECStatus tls13_SendEncryptedExtensions(sslSocket *ss);
+static SECStatus tls13_HandleEncryptedExtensions(sslSocket *ss, SSL3Opaque *b,
+ PRUint32 length);
+static SECStatus tls13_HandleCertificate(
+ sslSocket *ss, SSL3Opaque *b, PRUint32 length);
+static SECStatus tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b,
+ PRUint32 length);
+static SECStatus tls13_HandleCertificateStatus(sslSocket *ss, SSL3Opaque *b,
+ PRUint32 length);
+static SECStatus tls13_HandleCertificateVerify(
+ sslSocket *ss, SSL3Opaque *b, PRUint32 length,
+ SSL3Hashes *hashes);
+static SECStatus tls13_HkdfExtractSharedKey(sslSocket *ss, PK11SymKey *key,
+ SharedSecretType keyType);
+static SECStatus tls13_SendFinished(sslSocket *ss);
+static SECStatus tls13_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
+ const SSL3Hashes *hashes);
+static SECStatus tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b,
+ PRUint32 length);
+static SECStatus tls13_ComputeSecrets1(sslSocket *ss);
+static SECStatus tls13_ComputeFinished(
+ sslSocket *ss, const SSL3Hashes *hashes,
+ PRBool sending,
+ PRUint8 *output, unsigned int *outputLen,
+ unsigned int maxOutputLen);
+static SECStatus tls13_SendClientSecondRound(sslSocket *ss);
+static SECStatus tls13_FinishHandshake(sslSocket *ss);
+
+const char kHkdfLabelExpandedSs[] = "expanded static secret";
+const char kHkdfLabelExpandedEs[] = "expanded ephemeral secret";
+const char kHkdfLabelMasterSecret[] = "master secret";
+const char kHkdfLabelTrafficSecret[] = "traffic secret";
+const char kHkdfLabelClientFinishedSecret[] = "client finished";
+const char kHkdfLabelServerFinishedSecret[] = "server finished";
+const char kHkdfLabelResumptionMasterSecret[] = "resumption master secret";
+const char kHkdfLabelExporterMasterSecret[] = "exporter master secret";
+const char kHkdfPhaseEarlyHandshakeDataKeys[] = "early handshake key expansion";
+const char kHkdfPhaseEarlyApplicationDataKeys[] = "early application data key expansion";
+const char kHkdfPhaseHandshakeKeys[] = "handshake key expansion";
+const char kHkdfPhaseApplicationDataKeys[] = "application data key expansion";
+const char kHkdfPurposeClientWriteKey[] = "client write key";
+const char kHkdfPurposeServerWriteKey[] = "server write key";
+const char kHkdfPurposeClientWriteIv[] = "client write iv";
+const char kHkdfPurposeServerWriteIv[] = "server write iv";
+const char kClientFinishedLabel[] = "client finished";
+const char kServerFinishedLabel[] = "server finished";
+
+const SSL3ProtocolVersion kRecordVersion = 0x0301U;
+
+#define FATAL_ERROR(ss, prError, desc) \
+ do { \
+ SSL_TRC(3, ("%d: TLS13[%d]: fatal error %d in %s (%s:%d)", \
+ SSL_GETPID(), ss->fd, prError, __func__, __FILE__, __LINE__)); \
+ tls13_FatalError(ss, prError, desc); \
+ } while (0)
+
+#define UNIMPLEMENTED() \
+ do { \
+ SSL_TRC(3, ("%d: TLS13[%d]: unimplemented feature in %s (%s:%d)", \
+ SSL_GETPID(), ss->fd, __func__, __FILE__, __LINE__)); \
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); \
+ PORT_Assert(0); \
+ return SECFailure; \
+ } while (0)
+
+void
+tls13_FatalError(sslSocket *ss, PRErrorCode prError, SSL3AlertDescription desc)
+{
+ PORT_Assert(desc != internal_error); /* These should never happen */
+ (void)SSL3_SendAlert(ss, alert_fatal, desc);
+ PORT_SetError(prError);
+}
+
+#ifdef TRACE
+#define STATE_CASE(a) \
+ case a: \
+ return #a
+static char *
+tls13_HandshakeState(SSL3WaitState st)
+{
+ switch (st) {
+ STATE_CASE(wait_client_hello);
+ STATE_CASE(wait_client_cert);
+ STATE_CASE(wait_cert_verify);
+ STATE_CASE(wait_finished);
+ STATE_CASE(wait_server_hello);
+ STATE_CASE(wait_certificate_status);
+ STATE_CASE(wait_server_cert);
+ STATE_CASE(wait_cert_request);
+ STATE_CASE(wait_encrypted_extensions);
+ STATE_CASE(idle_handshake);
+ default:
+ break;
+ }
+ PORT_Assert(0);
+ return "unknown";
+}
+#endif
+
+#define TLS13_WAIT_STATE_MASK 0x80
+
+#define TLS13_BASE_WAIT_STATE(ws) (ws & ~TLS13_WAIT_STATE_MASK)
+/* We don't mask idle_handshake because other parts of the code use it*/
+#define TLS13_WAIT_STATE(ws) (ws == idle_handshake ? ws : ws | TLS13_WAIT_STATE_MASK)
+#define TLS13_CHECK_HS_STATE(ss, err, ...) \
+ tls13_CheckHsState(ss, err, #err, __func__, __FILE__, __LINE__, \
+ __VA_ARGS__, \
+ wait_invalid)
+void
+tls13_SetHsState(sslSocket *ss, SSL3WaitState ws,
+ const char *func, const char *file, int line)
+{
+#ifdef TRACE
+ const char *new_state_name =
+ tls13_HandshakeState(ws);
+
+ SSL_TRC(3, ("%d: TLS13[%d]: state change from %s->%s in %s (%s:%d)",
+ SSL_GETPID(), ss->fd,
+ tls13_HandshakeState(TLS13_BASE_WAIT_STATE(ss->ssl3.hs.ws)),
+ new_state_name,
+ func, file, line));
+#endif
+
+ ss->ssl3.hs.ws = TLS13_WAIT_STATE(ws);
+}
+
+static PRBool
+tls13_InHsStateV(sslSocket *ss, va_list ap)
+{
+ SSL3WaitState ws;
+
+ while ((ws = va_arg(ap, SSL3WaitState)) != wait_invalid) {
+ if (ws == TLS13_BASE_WAIT_STATE(ss->ssl3.hs.ws)) {
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+PRBool
+tls13_InHsState(sslSocket *ss, ...)
+{
+ PRBool found;
+ va_list ap;
+
+ va_start(ap, ss);
+ found = tls13_InHsStateV(ss, ap);
+ va_end(ap);
+
+ return found;
+}
+
+static SECStatus
+tls13_CheckHsState(sslSocket *ss, int err, const char *error_name,
+ const char *func, const char *file, int line,
+ ...)
+{
+ va_list ap;
+ va_start(ap, line);
+ if (tls13_InHsStateV(ss, ap)) {
+ va_end(ap);
+ return SECSuccess;
+ }
+ va_end(ap);
+
+ SSL_TRC(3, ("%d: TLS13[%d]: error %s state is (%s) at %s (%s:%d)",
+ SSL_GETPID(), ss->fd,
+ error_name,
+ tls13_HandshakeState(TLS13_BASE_WAIT_STATE(ss->ssl3.hs.ws)),
+ func, file, line));
+ tls13_FatalError(ss, err, unexpected_message);
+ return SECFailure;
+}
+
+SSLHashType
+tls13_GetHash(sslSocket *ss)
+{
+ /* TODO(ekr@rtfm.com): This needs to actually be looked up. */
+ return ssl_hash_sha256;
+}
+
+CK_MECHANISM_TYPE
+tls13_GetHkdfMechanism(sslSocket *ss)
+{
+ /* TODO(ekr@rtfm.com): This needs to actually be looked up. */
+ return CKM_NSS_HKDF_SHA256;
+}
+
+static CK_MECHANISM_TYPE
+tls13_GetHmacMechanism(sslSocket *ss)
+{
+ /* TODO(ekr@rtfm.com): This needs to actually be looked up. */
+ return CKM_SHA256_HMAC;
+}
+
+/*
+ * Called from ssl3_SendClientHello
+ */
+SECStatus
+tls13_SetupClientHello(sslSocket *ss)
+{
+ SECStatus rv;
+ /* TODO(ekr@rtfm.com): Handle multiple curves here. */
+ ECName curves_to_try[] = { ec_secp256r1 };
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+
+ PORT_Assert(!ss->ephemeralECDHKeyPair);
+
+ rv = ssl3_CreateECDHEphemeralKeyPair(curves_to_try[0],
+ &ss->ephemeralECDHKeyPair);
+ if (rv != SECSuccess)
+ return rv;
+
+ return SECSuccess;
+}
+
+static SECStatus
+tls13_HandleECDHEKeyShare(sslSocket *ss,
+ TLS13KeyShareEntry *entry,
+ SECKEYPrivateKey *privKey,
+ SharedSecretType type)
+{
+ SECStatus rv;
+ SECKEYPublicKey *peerKey;
+ PK11SymKey *shared;
+
+ peerKey = tls13_ImportECDHKeyShare(ss, entry->key_exchange.data,
+ entry->key_exchange.len,
+ entry->group);
+ if (!peerKey)
+ return SECFailure; /* Error code set already. */
+
+ /* Compute shared key. */
+ shared = tls13_ComputeECDHSharedKey(ss, privKey, peerKey);
+ SECKEY_DestroyPublicKey(peerKey);
+ if (!shared) {
+ return SECFailure; /* Error code set already. */
+ }
+
+ /* Extract key. */
+ rv = tls13_HkdfExtractSharedKey(ss, shared, type);
+ PK11_FreeSymKey(shared);
+
+ return rv;
+}
+
+SECStatus
+tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
+ PRUint32 length, SSL3Hashes *hashesPtr)
+{
+ /* TODO(ekr@rtfm.com): Would it be better to check all the states here? */
+ switch (ss->ssl3.hs.msg_type) {
+ case certificate:
+ return tls13_HandleCertificate(ss, b, length);
+
+ case certificate_status:
+ return tls13_HandleCertificateStatus(ss, b, length);
+
+ case certificate_request:
+ return tls13_HandleCertificateRequest(ss, b, length);
+
+ case certificate_verify:
+ return tls13_HandleCertificateVerify(ss, b, length, hashesPtr);
+
+ case encrypted_extensions:
+ return tls13_HandleEncryptedExtensions(ss, b, length);
+
+ case new_session_ticket:
+ return tls13_HandleNewSessionTicket(ss, b, length);
+
+ case finished:
+ return tls13_HandleFinished(ss, b, length, hashesPtr);
+
+ default:
+ FATAL_ERROR(ss, SSL_ERROR_RX_UNKNOWN_HANDSHAKE, unexpected_message);
+ return SECFailure;
+ }
+
+ PORT_Assert(0); /* Unreached */
+ return SECFailure;
+}
+
+/* Called from ssl3_HandleClientHello.
+ *
+ * Caller must hold Handshake and RecvBuf locks.
+ */
+SECStatus
+tls13_HandleClientKeyShare(sslSocket *ss)
+{
+ ECName expectedGroup;
+ SECStatus rv;
+ TLS13KeyShareEntry *found = NULL;
+ PRCList *cur_p;
+
+ SSL_TRC(3, ("%d: TLS13[%d]: handle client_key_share handshake",
+ SSL_GETPID(), ss->fd));
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ rv = ssl3_SetupPendingCipherSpec(ss);
+ if (rv != SECSuccess)
+ return SECFailure; /* Error code set below */
+
+ /* Figure out what group we expect */
+ switch (ss->ssl3.hs.kea_def->exchKeyType) {
+#ifndef NSS_DISABLE_ECC
+ case ssl_kea_ecdh:
+ expectedGroup = ssl3_GetCurveNameForServerSocket(ss);
+ if (!expectedGroup) {
+ FATAL_ERROR(ss, SSL_ERROR_NO_CYPHER_OVERLAP,
+ handshake_failure);
+ return SECFailure;
+ }
+ break;
+#endif
+ default:
+ /* Got an unknown or unsupported Key Exchange Algorithm.
+ * Can't happen. */
+ FATAL_ERROR(ss, SEC_ERROR_UNSUPPORTED_KEYALG,
+ internal_error);
+ return SECFailure;
+ }
+
+ /* Now walk through the keys until we find one for our group */
+ cur_p = PR_NEXT_LINK(&ss->ssl3.hs.remoteKeyShares);
+ while (cur_p != &ss->ssl3.hs.remoteKeyShares) {
+ TLS13KeyShareEntry *offer = (TLS13KeyShareEntry *)cur_p;
+
+ if (offer->group == expectedGroup) {
+ found = offer;
+ break;
+ }
+ cur_p = PR_NEXT_LINK(cur_p);
+ }
+
+ if (!found) {
+ /* No acceptable group. In future, we will need to correct the client.
+ * Currently just generate an error.
+ * TODO(ekr@rtfm.com): Write code to correct client.
+ */
+ FATAL_ERROR(ss, SSL_ERROR_NO_CYPHER_OVERLAP, handshake_failure);
+ return SECFailure;
+ }
+
+ /* Generate our key */
+ rv = ssl3_CreateECDHEphemeralKeyPair(expectedGroup, &ss->ephemeralECDHKeyPair);
+ if (rv != SECSuccess)
+ return rv;
+
+ ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
+ ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(
+ ss->ephemeralECDHKeyPair->pubKey);
+
+ /* Register the sender */
+ rv = ssl3_RegisterServerHelloExtensionSender(ss, ssl_tls13_key_share_xtn,
+ tls13_ServerSendKeyShareXtn);
+ if (rv != SECSuccess)
+ return SECFailure; /* Error code set below */
+
+ rv = tls13_HandleECDHEKeyShare(ss, found,
+ ss->ephemeralECDHKeyPair->privKey,
+ EphemeralSharedSecret);
+ if (rv != SECSuccess)
+ return SECFailure; /* Error code set below */
+
+ return SECSuccess;
+}
+
+/*
+ * [draft-ietf-tls-tls13-11] Section 6.3.3.2
+ *
+ * opaque DistinguishedName<1..2^16-1>;
+ *
+ * struct {
+ * opaque certificate_extension_oid<1..2^8-1>;
+ * opaque certificate_extension_values<0..2^16-1>;
+ * } CertificateExtension;
+ *
+ * struct {
+ * opaque certificate_request_context<0..2^8-1>;
+ * SignatureAndHashAlgorithm
+ * supported_signature_algorithms<2..2^16-2>;
+ * DistinguishedName certificate_authorities<0..2^16-1>;
+ * CertificateExtension certificate_extensions<0..2^16-1>;
+ * } CertificateRequest;
+ */
+static SECStatus
+tls13_SendCertificateRequest(sslSocket *ss)
+{
+ SECStatus rv;
+ int calen;
+ SECItem *names;
+ int nnames;
+ SECItem *name;
+ int i;
+ PRUint8 sigAlgs[MAX_SIGNATURE_ALGORITHMS * 2];
+ unsigned int sigAlgsLength = 0;
+ int length;
+
+ SSL_TRC(3, ("%d: TLS13[%d]: begin send certificate_request",
+ SSL_GETPID(), ss->fd));
+
+ /* Fixed context value. */
+ ss->ssl3.hs.certReqContext[0] = 0;
+ ss->ssl3.hs.certReqContextLen = 1;
+
+ rv = ssl3_EncodeCertificateRequestSigAlgs(ss, sigAlgs, sizeof(sigAlgs),
+ &sigAlgsLength);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ ssl3_GetCertificateRequestCAs(ss, &calen, &names, &nnames);
+ length = 1 + ss->ssl3.hs.certReqContextLen +
+ 2 + sigAlgsLength + 2 + calen + 2;
+
+ rv = ssl3_AppendHandshakeHeader(ss, certificate_request, length);
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
+ rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.hs.certReqContext,
+ ss->ssl3.hs.certReqContextLen, 1);
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
+ rv = ssl3_AppendHandshakeVariable(ss, sigAlgs, sigAlgsLength, 2);
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
+ rv = ssl3_AppendHandshakeNumber(ss, calen, 2);
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
+ for (i = 0, name = names; i < nnames; i++, name++) {
+ rv = ssl3_AppendHandshakeVariable(ss, name->data, name->len, 2);
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
+ }
+ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
+
+ return SECSuccess;
+}
+
+static SECStatus
+tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+{
+ SECStatus rv;
+ SECItem context = { siBuffer, NULL, 0 };
+ SECItem algorithms = { siBuffer, NULL, 0 };
+ PLArenaPool *arena;
+ CERTDistNames ca_list;
+ PRInt32 extensionsLength;
+
+ SSL_TRC(3, ("%d: TLS13[%d]: handle certificate_request sequence",
+ SSL_GETPID(), ss->fd));
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ /* Client */
+ rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, wait_cert_request);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
+ PORT_Assert(ss->ssl3.clientCertChain == NULL);
+ PORT_Assert(ss->ssl3.clientCertificate == NULL);
+ PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
+
+ rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length);
+ if (rv != SECSuccess)
+ return SECFailure;
+ PORT_Assert(sizeof(ss->ssl3.hs.certReqContext) == 255);
+ PORT_Memcpy(ss->ssl3.hs.certReqContext, context.data, context.len);
+ ss->ssl3.hs.certReqContextLen = context.len;
+
+ rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &b, &length);
+ if (rv != SECSuccess)
+ return SECFailure;
+
+ if (algorithms.len == 0 || (algorithms.len & 1) != 0) {
+ FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST,
+ illegal_parameter);
+ return SECFailure;
+ }
+
+ arena = ca_list.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ rv = ssl3_ParseCertificateRequestCAs(ss, &b, &length, arena, &ca_list);
+ if (rv != SECSuccess)
+ goto loser; /* alert sent below */
+
+ /* Verify that the extensions length is correct. */
+ extensionsLength = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
+ if (extensionsLength < 0) {
+ goto loser; /* alert sent below */
+ }
+ if (extensionsLength != length) {
+ FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST,
+ illegal_parameter);
+ goto loser;
+ }
+
+ TLS13_SET_HS_STATE(ss, wait_server_cert);
+
+ rv = ssl3_CompleteHandleCertificateRequest(ss, &algorithms, &ca_list);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ goto loser;
+ }
+
+ return SECSuccess;
+
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECFailure;
+}
+
+static SECStatus
+tls13_InitializeHandshakeEncryption(sslSocket *ss)
+{
+ SECStatus rv;
+
+ /* For all present cipher suites, SS = ES.
+ * TODO(ekr@rtfm.com): Revisit for 0-RTT. */
+ ss->ssl3.hs.xSS = PK11_ReferenceSymKey(ss->ssl3.hs.xES);
+ if (!ss->ssl3.hs.xSS) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ rv = tls13_InitCipherSpec(ss, TrafficKeyHandshake,
+ InstallCipherSpecBoth);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SSL_ERROR_INIT_CIPHER_SUITE_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ return rv;
+}
+
+/* Called from: ssl3_HandleClientHello */
+SECStatus
+tls13_SendServerHelloSequence(sslSocket *ss)
+{
+ SECStatus rv;
+ SSL3KEAType certIndex;
+
+ SSL_TRC(3, ("%d: TLS13[%d]: begin send server_hello sequence",
+ SSL_GETPID(), ss->fd));
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+
+ rv = ssl3_SendServerHello(ss);
+ if (rv != SECSuccess) {
+ return rv; /* err code is set. */
+ }
+
+ rv = tls13_InitializeHandshakeEncryption(ss);
+ if (rv != SECSuccess) {
+ return SECFailure; /* error code is set. */
+ }
+
+ rv = tls13_SendEncryptedExtensions(ss);
+ if (rv != SECSuccess) {
+ return SECFailure; /* error code is set. */
+ }
+
+ if (ss->opt.requestCertificate) {
+ rv = tls13_SendCertificateRequest(ss);
+ if (rv != SECSuccess) {
+ return SECFailure; /* error code is set. */
+ }
+ }
+ rv = ssl3_SendCertificate(ss);
+ if (rv != SECSuccess) {
+ return SECFailure; /* error code is set. */
+ }
+ rv = ssl3_SendCertificateStatus(ss);
+ if (rv != SECSuccess) {
+ return SECFailure; /* error code is set. */
+ }
+
+ /* This was copied from: ssl3_SendCertificate.
+ * TODO(ekr@rtfm.com): Verify that this selection logic is correct.
+ * Bug 1237514.
+ */
+ if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) ||
+ (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) {
+ certIndex = kt_rsa;
+ } else {
+ certIndex = ss->ssl3.hs.kea_def->exchKeyType;
+ }
+ rv = ssl3_SendCertificateVerify(ss, ss->serverCerts[certIndex].SERVERKEY);
+ if (rv != SECSuccess) {
+ return rv; /* err code is set. */
+ }
+
+ /* Compute the rest of the secrets except for the resumption
+ * and exporter secret. */
+ rv = tls13_ComputeSecrets1(ss);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ rv = tls13_SendFinished(ss);
+ if (rv != SECSuccess) {
+ return rv; /* error code is set. */
+ }
+
+ TLS13_SET_HS_STATE(ss, ss->opt.requestCertificate ? wait_client_cert
+ : wait_finished);
+
+ return SECSuccess;
+}
+
+/*
+ * Called from ssl3_HandleServerHello.
+ *
+ * Caller must hold Handshake and RecvBuf locks.
+ */
+SECStatus
+tls13_HandleServerKeyShare(sslSocket *ss)
+{
+ SECStatus rv;
+ ECName expectedGroup;
+ PRCList *cur_p;
+ TLS13KeyShareEntry *entry;
+
+ SSL_TRC(3, ("%d: TLS13[%d]: handle server_key_share handshake",
+ SSL_GETPID(), ss->fd));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ switch (ss->ssl3.hs.kea_def->exchKeyType) {
+#ifndef NSS_DISABLE_ECC
+ case ssl_kea_ecdh:
+ expectedGroup = ssl3_PubKey2ECName(ss->ephemeralECDHKeyPair->pubKey);
+ break;
+#endif /* NSS_DISABLE_ECC */
+ default:
+ FATAL_ERROR(ss, SEC_ERROR_UNSUPPORTED_KEYALG, handshake_failure);
+ return SECFailure;
+ }
+
+ /* This list should have one entry. */
+ cur_p = PR_NEXT_LINK(&ss->ssl3.hs.remoteKeyShares);
+ if (!cur_p) {
+ FATAL_ERROR(ss, SSL_ERROR_MISSING_KEY_SHARE, missing_extension);
+ return SECFailure;
+ }
+ PORT_Assert(PR_NEXT_LINK(cur_p) == &ss->ssl3.hs.remoteKeyShares);
+
+ entry = (TLS13KeyShareEntry *)cur_p;
+ if (entry->group != expectedGroup) {
+ FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_KEY_SHARE, illegal_parameter);
+ return SECFailure;
+ }
+
+ rv = tls13_HandleECDHEKeyShare(ss, entry,
+ ss->ephemeralECDHKeyPair->privKey,
+ EphemeralSharedSecret);
+
+ ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
+ ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(
+ ss->ephemeralECDHKeyPair->pubKey);
+
+ if (rv != SECSuccess)
+ return SECFailure; /* Error code set below */
+
+ return tls13_InitializeHandshakeEncryption(ss);
+}
+
+/* Called from tls13_CompleteHandleHandshakeMessage() when it has deciphered a complete
+ * tls13 Certificate message.
+ * Caller must hold Handshake and RecvBuf locks.
+ */
+static SECStatus
+tls13_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+{
+ SECStatus rv;
+ SECItem context = { siBuffer, NULL, 0 };
+
+ SSL_TRC(3, ("%d: TLS13[%d]: handle certificate handshake",
+ SSL_GETPID(), ss->fd));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ if (ss->sec.isServer) {
+ rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE,
+ wait_client_cert);
+ } else {
+ rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE,
+ wait_cert_request, wait_server_cert);
+ }
+ if (rv != SECSuccess)
+ return SECFailure;
+
+ /* Process the context string */
+ rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length);
+ if (rv != SECSuccess)
+ return SECFailure;
+ if (!ss->sec.isServer) {
+ if (context.len) {
+ /* The server's context string MUST be empty */
+ FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE,
+ illegal_parameter);
+ return SECFailure;
+ }
+ } else {
+ if (!context.len || context.len != ss->ssl3.hs.certReqContextLen ||
+ (NSS_SecureMemcmp(ss->ssl3.hs.certReqContext,
+ context.data, context.len) != 0)) {
+ FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE,
+ illegal_parameter);
+ return SECFailure;
+ }
+ context.len = 0; /* Belt and suspenders. Zero out the context. */
+ }
+
+ return ssl3_CompleteHandleCertificate(ss, b, length);
+}
+
+/* Called from tls13_CompleteHandleHandshakeMessage() when it has deciphered a complete
+ * ssl3 CertificateStatus message.
+ * Caller must hold Handshake and RecvBuf locks.
+ */
+static SECStatus
+tls13_HandleCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+{
+ SECStatus rv;
+
+ rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_STATUS,
+ wait_certificate_status);
+ if (rv != SECSuccess)
+ return rv;
+
+ return ssl3_CompleteHandleCertificateStatus(ss, b, length);
+}
+
+/*
+ * TODO(ekr@rtfm.com): This install logic needs renaming since it's
+ * what happens at various stages of cipher spec setup. Legacy from ssl3con.c.
+ */
+int
+tls13_InstallCipherSpec(sslSocket *ss, InstallCipherSpecDirection direction)
+{
+ SSL_TRC(3, ("%d: TLS13[%d]: Installing new cipher specs direction = %s",
+ SSL_GETPID(), ss->fd,
+ direction == InstallCipherSpecRead ? "read" : "write"));
+
+ PORT_Assert(!IS_DTLS(ss)); /* TODO(ekr@rtfm.com): Update for DTLS */
+ /* TODO(ekr@rtfm.com): Holddown timer for DTLS. */
+ ssl_GetSpecWriteLock(ss); /**************************************/
+
+ /* Flush out any old stuff in the handshake buffers */
+ switch (direction) {
+ case InstallCipherSpecWrite: {
+ ssl3CipherSpec *pwSpec;
+ pwSpec = ss->ssl3.pwSpec;
+
+ ss->ssl3.pwSpec = ss->ssl3.cwSpec;
+ ss->ssl3.cwSpec = pwSpec;
+ break;
+ } break;
+ case InstallCipherSpecRead: {
+ ssl3CipherSpec *prSpec;
+
+ prSpec = ss->ssl3.prSpec;
+ ss->ssl3.prSpec = ss->ssl3.crSpec;
+ ss->ssl3.crSpec = prSpec;
+ } break;
+ default:
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ ssl_ReleaseSpecWriteLock(ss); /**************************************/
+ return SECFailure;
+ }
+
+ /* If we are really through with the old cipher prSpec
+ * (Both the read and write sides have changed) destroy it.
+ */
+ if (ss->ssl3.prSpec == ss->ssl3.pwSpec) {
+ ssl3_DestroyCipherSpec(ss->ssl3.prSpec, PR_FALSE /*freeSrvName*/);
+ }
+ ssl_ReleaseSpecWriteLock(ss); /**************************************/
+
+ return SECSuccess;
+}
+
+/* Add context to the hash functions as described in
+ [draft-ietf-tls-tls13; Section 4.9.1] */
+SECStatus
+tls13_AddContextToHashes(sslSocket *ss, SSL3Hashes *hashes /* IN/OUT */,
+ SSLHashType algorithm, PRBool sending)
+{
+ SECStatus rv = SECSuccess;
+ PK11Context *ctx;
+ const unsigned char context_padding[] = {
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ };
+ const char *client_cert_verify_string = "TLS 1.3, client CertificateVerify";
+ const char *server_cert_verify_string = "TLS 1.3, server CertificateVerify";
+ const char *context_string = (sending ^ ss->sec.isServer) ? client_cert_verify_string
+ : server_cert_verify_string;
+ unsigned int hashlength;
+
+ /* Double check that we are doing SHA-256 for the handshake hash.*/
+ PORT_Assert(hashes->hashAlg == ssl_hash_sha256);
+ if (hashes->hashAlg != ssl_hash_sha256) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ goto loser;
+ }
+ PORT_Assert(hashes->len == 32);
+
+ ctx = PK11_CreateDigestContext(ssl3_TLSHashAlgorithmToOID(algorithm));
+ if (!ctx) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto loser;
+ }
+
+ PORT_Assert(SECFailure);
+ PORT_Assert(!SECSuccess);
+
+ rv |= PK11_DigestBegin(ctx);
+ rv |= PK11_DigestOp(ctx, context_padding, sizeof(context_padding));
+ rv |= PK11_DigestOp(ctx, (unsigned char *)context_string,
+ strlen(context_string) + 1); /* +1 includes the terminating 0 */
+ rv |= PK11_DigestOp(ctx, hashes->u.raw, hashes->len);
+ /* Update the hash in-place */
+ rv |= PK11_DigestFinal(ctx, hashes->u.raw, &hashlength, sizeof(hashes->u.raw));
+ PK11_DestroyContext(ctx, PR_TRUE);
+ PRINT_BUF(90, (NULL, "TLS 1.3 hash with context", hashes->u.raw, hashlength));
+
+ hashes->len = hashlength;
+ hashes->hashAlg = algorithm;
+
+ if (rv) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ goto loser;
+ }
+ return SECSuccess;
+
+loser:
+ return SECFailure;
+}
+
+static SECStatus
+tls13_HkdfExtractSharedKey(sslSocket *ss, PK11SymKey *key,
+ SharedSecretType keyType)
+{
+ PK11SymKey **destp;
+
+ switch (keyType) {
+ case EphemeralSharedSecret:
+ destp = &ss->ssl3.hs.xES;
+ break;
+ case StaticSharedSecret:
+ destp = &ss->ssl3.hs.xSS;
+ break;
+ default:
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
+ PORT_Assert(!*destp);
+ return tls13_HkdfExtract(NULL, key, tls13_GetHash(ss), destp);
+}
+
+static SECStatus
+tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *pwSpec,
+ TrafficKeyType type)
+{
+ size_t keySize = pwSpec->cipher_def->key_size;
+ size_t ivSize = pwSpec->cipher_def->iv_size +
+ pwSpec->cipher_def->explicit_nonce_size; /* This isn't always going to
+ * work, but it does for
+ * AES-GCM */
+ CK_MECHANISM_TYPE bulkAlgorithm = ssl3_Alg2Mech(pwSpec->cipher_def->calg);
+ SSL3Hashes hashes;
+ PK11SymKey *prk = NULL;
+ const char *phase;
+ char label[256]; /* Arbitrary buffer large enough to hold the label */
+ SECStatus rv;
+
+#define FORMAT_LABEL(phase_, purpose_) \
+ do { \
+ PRUint32 n = PR_snprintf(label, sizeof(label), "%s, %s", phase_, purpose_); \
+ /* Check for getting close. */ \
+ if ((n + 1) >= sizeof(label)) { \
+ PORT_Assert(0); \
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); \
+ goto loser; \
+ } \
+ } while (0)
+#define EXPAND_TRAFFIC_KEY(purpose_, target_) \
+ do { \
+ FORMAT_LABEL(phase, purpose_); \
+ rv = tls13_HkdfExpandLabel(prk, tls13_GetHash(ss), \
+ hashes.u.raw, hashes.len, \
+ label, strlen(label), \
+ bulkAlgorithm, keySize, &pwSpec->target_); \
+ if (rv != SECSuccess) { \
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); \
+ PORT_Assert(0); \
+ goto loser; \
+ } \
+ } while (0)
+
+#define EXPAND_TRAFFIC_IV(purpose_, target_) \
+ do { \
+ FORMAT_LABEL(phase, purpose_); \
+ rv = tls13_HkdfExpandLabelRaw(prk, tls13_GetHash(ss), \
+ hashes.u.raw, hashes.len, \
+ label, strlen(label), \
+ pwSpec->target_, ivSize); \
+ if (rv != SECSuccess) { \
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); \
+ PORT_Assert(0); \
+ goto loser; \
+ } \
+ } while (0)
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
+ PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
+
+ rv = ssl3_ComputeHandshakeHashes(ss, pwSpec, &hashes, 0);
+ if (rv != SECSuccess) {
+ PORT_Assert(0); /* Should never fail */
+ ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
+ return SECFailure;
+ }
+ PRINT_BUF(60, (ss, "Deriving traffic keys. Session hash=", hashes.u.raw,
+ hashes.len));
+
+ switch (type) {
+ case TrafficKeyHandshake:
+ phase = kHkdfPhaseHandshakeKeys;
+ prk = ss->ssl3.hs.xES;
+ break;
+ case TrafficKeyApplicationData:
+ phase = kHkdfPhaseApplicationDataKeys;
+ prk = ss->ssl3.hs.trafficSecret;
+ break;
+ default:
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ PORT_Assert(prk != NULL);
+
+ SSL_TRC(3, ("%d: TLS13[%d]: deriving traffic keys phase='%s'",
+ SSL_GETPID(), ss->fd, phase));
+
+ EXPAND_TRAFFIC_KEY(kHkdfPurposeClientWriteKey, client.write_key);
+ EXPAND_TRAFFIC_KEY(kHkdfPurposeServerWriteKey, server.write_key);
+ EXPAND_TRAFFIC_IV(kHkdfPurposeClientWriteIv, client.write_iv);
+ EXPAND_TRAFFIC_IV(kHkdfPurposeServerWriteIv, server.write_iv);
+
+ return SECSuccess;
+
+loser:
+ return SECFailure;
+}
+
+/* Set up a cipher spec with keys. If install is nonzero, then also install
+ * it as the current cipher spec for each value in the mask. */
+SECStatus
+tls13_InitCipherSpec(sslSocket *ss, TrafficKeyType type, InstallCipherSpecDirection install)
+{
+ ssl3CipherSpec *pwSpec;
+ ssl3CipherSpec *cwSpec;
+ SECStatus rv;
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ if (install == InstallCipherSpecWrite ||
+ install == InstallCipherSpecBoth) {
+ ssl_GetXmitBufLock(ss);
+
+ rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
+ ssl_ReleaseXmitBufLock(ss);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+
+ ssl_GetSpecWriteLock(ss); /**************************************/
+
+ PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
+
+ pwSpec = ss->ssl3.pwSpec;
+ cwSpec = ss->ssl3.cwSpec;
+
+ switch (pwSpec->cipher_def->calg) {
+ case calg_aes_gcm:
+ pwSpec->aead = tls13_AESGCM;
+ break;
+ default:
+ PORT_Assert(0);
+ goto loser;
+ break;
+ }
+
+ /* Generic behaviors -- common to all crypto methods */
+ if (!IS_DTLS(ss)) {
+ pwSpec->read_seq_num.high = pwSpec->write_seq_num.high = 0;
+ } else {
+ if (cwSpec->epoch == PR_UINT16_MAX) {
+ /* The problem here is that we have rehandshaked too many
+ * times (you are not allowed to wrap the epoch). The
+ * spec says you should be discarding the connection
+ * and start over, so not much we can do here. */
+ rv = SECFailure;
+ goto loser;
+ }
+ /* The sequence number has the high 16 bits as the epoch. */
+ pwSpec->epoch = cwSpec->epoch + 1;
+ pwSpec->read_seq_num.high = pwSpec->write_seq_num.high =
+ pwSpec->epoch << 16;
+
+ dtls_InitRecvdRecords(&pwSpec->recvdRecords);
+ }
+ pwSpec->read_seq_num.low = pwSpec->write_seq_num.low = 0;
+
+ rv = tls13_DeriveTrafficKeys(ss, pwSpec, type);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (install == InstallCipherSpecWrite ||
+ install == InstallCipherSpecBoth) {
+ rv = tls13_InstallCipherSpec(ss, InstallCipherSpecWrite);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+ if (install == InstallCipherSpecRead ||
+ install == InstallCipherSpecBoth) {
+ rv = tls13_InstallCipherSpec(ss, InstallCipherSpecRead);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+ ssl_ReleaseSpecWriteLock(ss); /**************************************/
+
+ return SECSuccess;
+
+loser:
+ ssl_ReleaseSpecWriteLock(ss); /**************************************/
+ PORT_SetError(SSL_ERROR_INIT_CIPHER_SUITE_FAILURE);
+ return SECFailure;
+}
+
+static SECStatus
+tls13_ComputeSecrets1(sslSocket *ss)
+{
+ SECStatus rv;
+ PK11SymKey *mSS = NULL;
+ PK11SymKey *mES = NULL;
+ PK11SymKey *masterSecret = NULL;
+ SSL3Hashes hashes;
+
+ rv = ssl3_SetupPendingCipherSpec(ss);
+ if (rv != SECSuccess) {
+ return rv; /* error code set below. */
+ }
+
+ rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0);
+ if (rv != SECSuccess) {
+ PORT_Assert(0); /* Should never fail */
+ ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
+ return SECFailure;
+ }
+
+ PORT_Assert(ss->ssl3.hs.xSS);
+ PORT_Assert(ss->ssl3.hs.xES);
+
+ rv = tls13_HkdfExpandLabel(ss->ssl3.hs.xSS,
+ tls13_GetHash(ss),
+ hashes.u.raw, hashes.len,
+ kHkdfLabelExpandedSs,
+ strlen(kHkdfLabelExpandedSs),
+ tls13_GetHkdfMechanism(ss),
+ hashes.len, &mSS);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ rv = tls13_HkdfExpandLabel(ss->ssl3.hs.xES,
+ tls13_GetHash(ss),
+ hashes.u.raw, hashes.len,
+ kHkdfLabelExpandedEs,
+ strlen(kHkdfLabelExpandedEs),
+ tls13_GetHkdfMechanism(ss),
+ hashes.len, &mES);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ rv = tls13_HkdfExtract(mSS, mES,
+ tls13_GetHash(ss),
+ &masterSecret);
+
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ rv = tls13_HkdfExpandLabel(masterSecret,
+ tls13_GetHash(ss),
+ hashes.u.raw, hashes.len,
+ kHkdfLabelTrafficSecret,
+ strlen(kHkdfLabelTrafficSecret),
+ tls13_GetHkdfMechanism(ss),
+ hashes.len, &ss->ssl3.hs.trafficSecret);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ rv = tls13_HkdfExpandLabel(masterSecret,
+ tls13_GetHash(ss),
+ NULL, 0,
+ kHkdfLabelClientFinishedSecret,
+ strlen(kHkdfLabelClientFinishedSecret),
+ tls13_GetHmacMechanism(ss),
+ hashes.len, &ss->ssl3.hs.clientFinishedSecret);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ rv = tls13_HkdfExpandLabel(masterSecret,
+ tls13_GetHash(ss),
+ NULL, 0,
+ kHkdfLabelServerFinishedSecret,
+ strlen(kHkdfLabelServerFinishedSecret),
+ tls13_GetHmacMechanism(ss),
+ hashes.len, &ss->ssl3.hs.serverFinishedSecret);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+loser:
+ PK11_FreeSymKey(ss->ssl3.hs.xSS);
+ ss->ssl3.hs.xSS = NULL;
+ PK11_FreeSymKey(ss->ssl3.hs.xES);
+ ss->ssl3.hs.xES = NULL;
+
+ if (mSS) {
+ PK11_FreeSymKey(mSS);
+ }
+ if (mES) {
+ PK11_FreeSymKey(mES);
+ }
+ if (masterSecret) {
+ PK11_FreeSymKey(masterSecret);
+ }
+
+ return rv;
+}
+
+void
+tls13_DestroyKeyShareEntry(TLS13KeyShareEntry *offer)
+{
+ SECITEM_ZfreeItem(&offer->key_exchange, PR_FALSE);
+ PORT_ZFree(offer, sizeof(*offer));
+}
+
+void
+tls13_DestroyKeyShares(PRCList *list)
+{
+ PRCList *cur_p;
+
+ while (!PR_CLIST_IS_EMPTY(list)) {
+ cur_p = PR_LIST_TAIL(list);
+ PR_REMOVE_LINK(cur_p);
+ tls13_DestroyKeyShareEntry((TLS13KeyShareEntry *)cur_p);
+ }
+}
+
+/* Implement the SSLAEADCipher interface defined in sslimpl.h.
+ *
+ * That interface mixes the AD and the sequence number, but in
+ * TLS 1.3 there is no additional data so this value is just the
+ * encoded sequence number and we call it |seqNumBuf|.
+ */
+static SECStatus
+tls13_AESGCM(ssl3KeyMaterial *keys,
+ PRBool doDecrypt,
+ unsigned char *out,
+ int *outlen,
+ int maxout,
+ const unsigned char *in,
+ int inlen,
+ const unsigned char *seqNumBuf,
+ int seqNumLen)
+{
+ SECItem param;
+ SECStatus rv = SECFailure;
+ unsigned char nonce[12];
+ size_t i;
+ unsigned int uOutLen;
+ CK_GCM_PARAMS gcmParams;
+ static const int tagSize = 16;
+
+ PORT_Assert(seqNumLen == 8);
+
+ /* draft-ietf-tls-tls13 Section 5.2.2 specifies the following
+ * nonce algorithm:
+ *
+ * The length of the per-record nonce (iv_length) is set to max(8 bytes,
+ * N_MIN) for the AEAD algorithm (see [RFC5116] Section 4). An AEAD
+ * algorithm where N_MAX is less than 8 bytes MUST NOT be used with TLS.
+ * The per-record nonce for the AEAD construction is formed as follows:
+ *
+ * 1. The 64-bit record sequence number is padded to the left with
+ * zeroes to iv_length.
+ *
+ * 2. The padded sequence number is XORed with the static
+ * client_write_iv or server_write_iv, depending on the role.
+ *
+ * The resulting quantity (of length iv_length) is used as the per-
+ * record nonce.
+ *
+ * Per RFC 5288: N_MIN = N_MAX = 12 bytes.
+ *
+ */
+ memcpy(nonce, keys->write_iv, sizeof(nonce));
+ for (i = 0; i < 8; ++i) {
+ nonce[4 + i] ^= seqNumBuf[i];
+ }
+
+ param.type = siBuffer;
+ param.data = (unsigned char *)&gcmParams;
+ param.len = sizeof(gcmParams);
+ gcmParams.pIv = nonce;
+ gcmParams.ulIvLen = sizeof(nonce);
+ gcmParams.pAAD = NULL;
+ gcmParams.ulAADLen = 0;
+ gcmParams.ulTagBits = tagSize * 8;
+
+ if (doDecrypt) {
+ rv = PK11_Decrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
+ maxout, in, inlen);
+ } else {
+ rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
+ maxout, in, inlen);
+ }
+ *outlen = (int)uOutLen;
+
+ return rv;
+}
+
+static SECStatus
+tls13_HandleEncryptedExtensions(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+{
+ SECStatus rv;
+ PRInt32 innerLength;
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ SSL_TRC(3, ("%d: TLS13[%d]: handle encrypted extensions",
+ SSL_GETPID(), ss->fd));
+
+ rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_ENCRYPTED_EXTENSIONS,
+ wait_encrypted_extensions);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
+ innerLength = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
+ if (innerLength < 0) {
+ return SECFailure; /* Alert already sent. */
+ }
+ if (innerLength != length) {
+ FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS,
+ illegal_parameter);
+ return SECFailure;
+ }
+
+ rv = ssl3_HandleHelloExtensions(ss, &b, &length, encrypted_extensions);
+ if (rv != SECSuccess) {
+ return SECFailure; /* Error code set below */
+ }
+
+ TLS13_SET_HS_STATE(ss, wait_cert_request);
+ return SECSuccess;
+}
+
+static SECStatus
+tls13_SendEncryptedExtensions(sslSocket *ss)
+{
+ SECStatus rv;
+ PRInt32 extensions_len = 0;
+ PRInt32 sent_len = 0;
+ PRUint32 maxBytes = 65535;
+
+ SSL_TRC(3, ("%d: TLS13[%d]: send encrypted extensions handshake",
+ SSL_GETPID(), ss->fd));
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+
+ extensions_len = ssl3_CallHelloExtensionSenders(
+ ss, PR_FALSE, maxBytes, &ss->xtnData.encryptedExtensionsSenders[0]);
+
+ rv = ssl3_AppendHandshakeHeader(ss, encrypted_extensions,
+ extensions_len + 2);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+ rv = ssl3_AppendHandshakeNumber(ss, extensions_len, 2);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+ sent_len = ssl3_CallHelloExtensionSenders(
+ ss, PR_TRUE, extensions_len,
+ &ss->xtnData.encryptedExtensionsSenders[0]);
+ PORT_Assert(sent_len == extensions_len);
+ if (sent_len != extensions_len) {
+ PORT_Assert(sent_len == 0);
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+/* Called from tls13_CompleteHandleHandshakeMessage() when it has deciphered a complete
+ * tls13 CertificateVerify message
+ * Caller must hold Handshake and RecvBuf locks.
+ */
+SECStatus
+tls13_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
+ SSL3Hashes *hashes)
+{
+ SECItem signed_hash = { siBuffer, NULL, 0 };
+ SECStatus rv;
+ SSLSignatureAndHashAlg sigAndHash;
+
+ SSL_TRC(3, ("%d: TLS13[%d]: handle certificate_verify handshake",
+ SSL_GETPID(), ss->fd));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY,
+ wait_cert_verify);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
+ if (!hashes) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ /* We only support CertificateVerify messages that use the handshake
+ * hash.
+ * TODO(ekr@rtfm.com): This should be easy to relax in TLS 1.3 by
+ * reading the client's hash algorithm first, but there may
+ * be subtleties so retain the restriction for now.
+ */
+ rv = tls13_AddContextToHashes(ss, hashes, hashes->hashAlg, PR_FALSE);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SSL_ERROR_DIGEST_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
+ &sigAndHash);
+ if (rv != SECSuccess) {
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_VERIFY);
+ return SECFailure;
+ }
+
+ rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
+ ss, &sigAndHash, ss->sec.peerCert);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_VERIFY, decrypt_error);
+ return SECFailure;
+ }
+
+ /* We only support CertificateVerify messages that use the handshake
+ * hash. */
+ if (sigAndHash.hashAlg != hashes->hashAlg) {
+ FATAL_ERROR(ss, SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM, decrypt_error);
+ return SECFailure;
+ }
+
+ rv = ssl3_ConsumeHandshakeVariable(ss, &signed_hash, 2, &b, &length);
+ if (rv != SECSuccess) {
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_VERIFY);
+ return SECFailure;
+ }
+
+ if (length != 0) {
+ FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_VERIFY, decode_error);
+ return SECFailure;
+ }
+
+ rv = ssl3_VerifySignedHashes(hashes, ss->sec.peerCert, &signed_hash,
+ PR_TRUE, ss->pkcs11PinArg);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, PORT_GetError(), decrypt_error);
+ return SECFailure;
+ }
+
+ if (!ss->sec.isServer) {
+ /* Compute the rest of the secrets except for the resumption
+ * and exporter secret. */
+ rv = tls13_ComputeSecrets1(ss);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+ }
+ TLS13_SET_HS_STATE(ss, wait_finished);
+
+ return SECSuccess;
+}
+
+static SECStatus
+tls13_ComputeFinished(sslSocket *ss, const SSL3Hashes *hashes, PRBool sending,
+ PRUint8 *output, unsigned int *outputLen, unsigned int maxOutputLen)
+{
+ SECStatus rv;
+ PK11Context *hmacCtx = NULL;
+ CK_MECHANISM_TYPE macAlg = tls13_GetHmacMechanism(ss);
+ SECItem param = { siBuffer, NULL, 0 };
+ unsigned int outputLenUint;
+ PK11SymKey *secret = (ss->sec.isServer ^ sending) ? ss->ssl3.hs.clientFinishedSecret
+ : ss->ssl3.hs.serverFinishedSecret;
+
+ PORT_Assert(secret);
+ PRINT_BUF(90, (NULL, "Handshake hash", hashes->u.raw, hashes->len));
+
+ hmacCtx = PK11_CreateContextBySymKey(macAlg, CKA_SIGN,
+ secret, &param);
+ if (!hmacCtx) {
+ goto abort;
+ }
+
+ rv = PK11_DigestBegin(hmacCtx);
+ if (rv != SECSuccess)
+ goto abort;
+
+ rv = PK11_DigestOp(hmacCtx, hashes->u.raw, hashes->len);
+ if (rv != SECSuccess)
+ goto abort;
+
+ PORT_Assert(maxOutputLen >= hashes->len);
+ rv = PK11_DigestFinal(hmacCtx, output, &outputLenUint, maxOutputLen);
+ if (rv != SECSuccess)
+ goto abort;
+ *outputLen = outputLenUint;
+
+ PK11_DestroyContext(hmacCtx, PR_TRUE);
+ return SECSuccess;
+
+abort:
+ if (hmacCtx) {
+ PK11_DestroyContext(hmacCtx, PR_TRUE);
+ }
+
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+}
+
+static SECStatus
+tls13_SendFinished(sslSocket *ss)
+{
+ SECStatus rv;
+ PRUint8 finishedBuf[MAX_FINISHED_SIZE];
+ unsigned int finishedLen;
+ SSL3Hashes hashes;
+ int errCode;
+
+ SSL_TRC(3, ("%d: TLS13[%d]: send finished handshake", SSL_GETPID(), ss->fd));
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ ssl_GetSpecReadLock(ss);
+ rv = tls13_ComputeFinished(ss, &hashes, PR_TRUE,
+ finishedBuf, &finishedLen, sizeof(finishedBuf));
+ ssl_ReleaseSpecReadLock(ss);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ rv = ssl3_AppendHandshakeHeader(ss, finished, finishedLen);
+ if (rv != SECSuccess) {
+ errCode = PR_GetError();
+ goto alert_loser;
+ }
+
+ rv = ssl3_AppendHandshake(ss, finishedBuf, finishedLen);
+ if (rv != SECSuccess) {
+ errCode = PR_GetError();
+ goto alert_loser;
+ }
+
+ rv = ssl3_FlushHandshake(ss, 0);
+ if (rv != SECSuccess) {
+ errCode = PR_GetError();
+ goto alert_loser;
+ }
+
+ if (ss->sec.isServer) {
+ rv = tls13_InitCipherSpec(ss, TrafficKeyApplicationData,
+ InstallCipherSpecWrite);
+ } else {
+ rv = tls13_InstallCipherSpec(ss, InstallCipherSpecWrite);
+ }
+ if (rv != SECSuccess) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
+ /* TODO(ekr@rtfm.com): Record key log */
+ return SECSuccess;
+
+alert_loser:
+ (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
+ PORT_SetError(errCode); /* Restore error code */
+ return rv;
+}
+
+static SECStatus
+tls13_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
+ const SSL3Hashes *hashes)
+{
+ SECStatus rv;
+ PRUint8 finishedBuf[MAX_FINISHED_SIZE];
+ unsigned int finishedLen;
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ SSL_TRC(3, ("%d: TLS13[%d]: handle finished handshake",
+ SSL_GETPID(), ss->fd));
+
+ rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_FINISHED, wait_finished);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ if (!hashes) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ ssl_GetSpecReadLock(ss);
+ rv = tls13_ComputeFinished(ss, hashes, PR_FALSE,
+ finishedBuf, &finishedLen, sizeof(finishedBuf));
+ ssl_ReleaseSpecReadLock(ss);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ if (length != finishedLen) {
+ FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_FINISHED, decode_error);
+ return SECFailure;
+ }
+
+ if (NSS_SecureMemcmp(b, finishedBuf, finishedLen) != 0) {
+ FATAL_ERROR(ss, SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE,
+ decrypt_error);
+ return SECFailure;
+ }
+
+ /* Server is now finished.
+ * Client sends second flight
+ */
+ /* TODO(ekr@rtfm.com): Send NewSession Ticket if server. */
+ if (ss->sec.isServer) {
+ rv = tls13_InstallCipherSpec(ss, InstallCipherSpecRead);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ rv = tls13_FinishHandshake(ss);
+ } else {
+ if (ss->ssl3.hs.authCertificatePending) {
+ /* TODO(ekr@rtfm.com): Handle pending auth */
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ PORT_Assert(0);
+ return SECFailure;
+ }
+ rv = tls13_InitCipherSpec(ss, TrafficKeyApplicationData,
+ InstallCipherSpecRead);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+
+ rv = tls13_SendClientSecondRound(ss);
+ if (rv != SECSuccess)
+ return SECFailure; /* Error code and alerts handled below */
+ }
+
+ return rv;
+}
+
+static SECStatus
+tls13_FinishHandshake(sslSocket *ss)
+{
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->ssl3.hs.restartTarget == NULL);
+
+ /* The first handshake is now completed. */
+ ss->handshake = NULL;
+
+ TLS13_SET_HS_STATE(ss, idle_handshake);
+
+ ssl_FinishHandshake(ss);
+
+ return SECSuccess;
+}
+
+static SECStatus
+tls13_SendClientSecondRound(sslSocket *ss)
+{
+ SECStatus rv;
+ PRBool sendClientCert;
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ sendClientCert = !ss->ssl3.sendEmptyCert &&
+ ss->ssl3.clientCertChain != NULL &&
+ ss->ssl3.clientPrivateKey != NULL;
+
+ /* Defer client authentication sending if we are still
+ * waiting for server authentication. See the long block
+ * comment in ssl3_SendClientSecondRound for more detail.
+ */
+ if (ss->ssl3.hs.restartTarget) {
+ PR_NOT_REACHED("unexpected ss->ssl3.hs.restartTarget");
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ if (ss->ssl3.hs.authCertificatePending && (sendClientCert ||
+ ss->ssl3.sendEmptyCert)) {
+ SSL_TRC(3, ("%d: TLS13[%p]: deferring ssl3_SendClientSecondRound because"
+ " certificate authentication is still pending.",
+ SSL_GETPID(), ss->fd));
+ ss->ssl3.hs.restartTarget = tls13_SendClientSecondRound;
+ return SECWouldBlock;
+ }
+
+ ssl_GetXmitBufLock(ss); /*******************************/
+ if (ss->ssl3.sendEmptyCert) {
+ ss->ssl3.sendEmptyCert = PR_FALSE;
+ rv = ssl3_SendEmptyCertificate(ss);
+ /* Don't send verify */
+ if (rv != SECSuccess) {
+ goto loser; /* error code is set. */
+ }
+ } else if (sendClientCert) {
+ rv = ssl3_SendCertificate(ss);
+ if (rv != SECSuccess) {
+ goto loser; /* error code is set. */
+ }
+ }
+
+ if (sendClientCert) {
+ rv = ssl3_SendCertificateVerify(ss, ss->ssl3.clientPrivateKey);
+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
+ ss->ssl3.clientPrivateKey = NULL;
+ if (rv != SECSuccess) {
+ goto loser; /* err is set. */
+ }
+ }
+
+ rv = tls13_SendFinished(ss);
+ if (rv != SECSuccess) {
+ goto loser; /* err code was set. */
+ }
+ ssl_ReleaseXmitBufLock(ss); /*******************************/
+
+ /* The handshake is now finished */
+ return tls13_FinishHandshake(ss);
+
+loser:
+ ssl_ReleaseXmitBufLock(ss); /*******************************/
+ return SECFailure;
+}
+
+static SECStatus
+tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+{
+ SECStatus rv;
+
+ rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET,
+ idle_handshake);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
+ UNIMPLEMENTED();
+
+ /* Ignore */
+ return SECSuccess;
+}
+
+typedef enum {
+ ExtensionNotUsed,
+ ExtensionClientOnly,
+ ExtensionSendClear,
+ ExtensionSendEncrypted,
+} Tls13ExtensionStatus;
+
+static const struct {
+ SSLExtensionType ex_value;
+ Tls13ExtensionStatus status;
+} KnownExtensions[] = {
+ { ssl_server_name_xtn,
+ ExtensionSendEncrypted },
+ {
+ ssl_cert_status_xtn,
+ ExtensionNotUsed /* TODO(ekr@rtfm.com): Disabled because broken
+ in TLS 1.3. */
+ /* ExtensionSendEncrypted */
+ },
+ { ssl_elliptic_curves_xtn,
+ ExtensionSendClear },
+ { ssl_ec_point_formats_xtn,
+ ExtensionNotUsed },
+ { ssl_signature_algorithms_xtn,
+ ExtensionClientOnly },
+ { ssl_use_srtp_xtn,
+ ExtensionSendEncrypted },
+ { ssl_app_layer_protocol_xtn,
+ ExtensionSendEncrypted },
+ { ssl_padding_xtn,
+ ExtensionNotUsed },
+ { ssl_extended_master_secret_xtn,
+ ExtensionNotUsed },
+ { ssl_session_ticket_xtn,
+ ExtensionClientOnly },
+ { ssl_tls13_key_share_xtn,
+ ExtensionSendClear },
+ { ssl_next_proto_nego_xtn,
+ ExtensionNotUsed },
+ { ssl_renegotiation_info_xtn,
+ ExtensionNotUsed },
+ { ssl_tls13_draft_version_xtn,
+ ExtensionClientOnly }
+};
+
+PRBool
+tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message)
+{
+ unsigned int i;
+
+ PORT_Assert((message == client_hello) ||
+ (message == server_hello) ||
+ (message == encrypted_extensions));
+
+ for (i = 0; i < PR_ARRAY_SIZE(KnownExtensions); i++) {
+ if (KnownExtensions[i].ex_value == extension)
+ break;
+ }
+ if (i == PR_ARRAY_SIZE(KnownExtensions)) {
+ /* We have never heard of this extension which is OK on
+ * the server but not the client. */
+ return message == client_hello;
+ }
+
+ switch (KnownExtensions[i].status) {
+ case ExtensionNotUsed:
+ return PR_FALSE;
+ case ExtensionClientOnly:
+ return message == client_hello;
+ case ExtensionSendClear:
+ return message == client_hello ||
+ message == server_hello;
+ case ExtensionSendEncrypted:
+ return message == client_hello ||
+ message == encrypted_extensions;
+ }
+
+ PORT_Assert(0);
+
+ /* Not reached */
+ return PR_TRUE;
+}
+
+/* Helper function to encode a uint32 into a buffer */
+unsigned char *
+tls13_EncodeUintX(PRUint32 value, unsigned int bytes, unsigned char *to)
+{
+ PRUint32 encoded;
+
+ PORT_Assert(bytes > 0 && bytes <= 4);
+
+ encoded = PR_htonl(value);
+ memcpy(to, ((unsigned char *)(&encoded)) + (4 - bytes), bytes);
+ return to + bytes;
+}
+
+/* TLS 1.3 doesn't actually have additional data but the aead function
+ * signature overloads additional data to carry the record sequence
+ * number and that's what we put here. The TLS 1.3 AEAD functions
+ * just use this input as the sequence number and not as additional
+ * data. */
+static void
+tls13_FormatAdditionalData(unsigned char *aad, unsigned int length,
+ SSL3SequenceNumber seqNum)
+{
+ unsigned char *ptr = aad;
+
+ PORT_Assert(length == 8);
+ ptr = tls13_EncodeUintX(seqNum.high, 4, ptr);
+ ptr = tls13_EncodeUintX(seqNum.low, 4, ptr);
+ PORT_Assert((ptr - aad) == length);
+}
+
+SECStatus
+tls13_ProtectRecord(sslSocket *ss,
+ SSL3ContentType type,
+ const SSL3Opaque *pIn,
+ PRUint32 contentLen,
+ sslBuffer *wrBuf)
+{
+ ssl3CipherSpec *cwSpec = ss->ssl3.cwSpec;
+ const ssl3BulkCipherDef *cipher_def = cwSpec->cipher_def;
+ SECStatus rv;
+ PRUint16 headerLen;
+ int cipherBytes = 0;
+ const int tagLen = cipher_def->tag_size;
+
+ SSL_TRC(3, ("%d: TLS13[%d]: protect record of length %u, seq=0x%0x%0x",
+ SSL_GETPID(), ss->fd, contentLen,
+ cwSpec->write_seq_num.high,
+ cwSpec->write_seq_num.low));
+
+ headerLen = IS_DTLS(ss) ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH;
+
+ if (headerLen + contentLen + 1 + tagLen > wrBuf->space) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
+ /* Copy the data into the wrBuf. We're going to encrypt in-place
+ * in the AEAD branch anyway */
+ PORT_Memcpy(wrBuf->buf + headerLen, pIn, contentLen);
+
+ if (cipher_def->calg == ssl_calg_null) {
+ /* Shortcut for plaintext */
+ cipherBytes = contentLen;
+ } else {
+ unsigned char aad[8];
+ PORT_Assert(cipher_def->type == type_aead);
+
+ /* Add the content type at the end. */
+ wrBuf->buf[headerLen + contentLen] = type;
+
+ /* Stomp the content type to be application_data */
+ type = content_application_data;
+
+ tls13_FormatAdditionalData(aad, sizeof(aad),
+ cwSpec->write_seq_num);
+ cipherBytes = contentLen + 1; /* Room for the content type on the end. */
+ rv = cwSpec->aead(
+ ss->sec.isServer ? &cwSpec->server : &cwSpec->client,
+ PR_FALSE, /* do encrypt */
+ wrBuf->buf + headerLen, /* output */
+ &cipherBytes, /* out len */
+ wrBuf->space - headerLen, /* max out */
+ wrBuf->buf + headerLen, contentLen + 1, /* input */
+ aad, sizeof(aad));
+ if (rv != SECSuccess) {
+ PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
+ return SECFailure;
+ }
+ }
+
+ PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 256);
+
+ wrBuf->len = cipherBytes + headerLen;
+ wrBuf->buf[0] = type;
+
+ if (IS_DTLS(ss)) {
+ (void)tls13_EncodeUintX(2, dtls_TLSVersionToDTLSVersion(kRecordVersion),
+ &wrBuf->buf[1]);
+ (void)tls13_EncodeUintX(cwSpec->write_seq_num.high, 4, &wrBuf->buf[3]);
+ (void)tls13_EncodeUintX(cwSpec->write_seq_num.low, 4, &wrBuf->buf[7]);
+ (void)tls13_EncodeUintX(cipherBytes, 2, &wrBuf->buf[11]);
+ } else {
+ (void)tls13_EncodeUintX(kRecordVersion, 2, &wrBuf->buf[1]);
+ (void)tls13_EncodeUintX(cipherBytes, 2, &wrBuf->buf[3]);
+ }
+ ssl3_BumpSequenceNumber(&cwSpec->write_seq_num);
+
+ return SECSuccess;
+}
+
+/* Unprotect a TLS 1.3 record and leave the result in plaintext.
+ *
+ * Called by ssl3_HandleRecord. Caller must hold the spec read lock.
+ * Therefore, we MUST not call SSL3_SendAlert().
+ *
+ * If SECFailure is returned, we:
+ * 1. Set |*alert| to the alert to be sent.
+ * 2. Call PORT_SetError() witn an appropriate code.
+ */
+SECStatus
+tls13_UnprotectRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *plaintext,
+ SSL3AlertDescription *alert)
+{
+ ssl3CipherSpec *crSpec = ss->ssl3.crSpec;
+ const ssl3BulkCipherDef *cipher_def = crSpec->cipher_def;
+ unsigned char aad[8];
+ SECStatus rv;
+
+ *alert = bad_record_mac; /* Default alert for most issues. */
+
+ SSL_TRC(3, ("%d: TLS13[%d]: unprotect record of length %u",
+ SSL_GETPID(), ss->fd, cText->buf->len));
+
+ /* We can perform this test in variable time because the record's total
+ * length and the ciphersuite are both public knowledge. */
+ if (cText->buf->len < cipher_def->tag_size) {
+ PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
+ return SECFailure;
+ }
+
+ /* Verify that the content type is right, even though we overwrite it. */
+ if (cText->type != content_application_data) {
+ /* Do we need a better error here? */
+ PORT_SetError(SSL_ERROR_BAD_MAC_READ);
+ return SECFailure;
+ }
+
+ /* Check the version number in the record */
+ if (cText->version != kRecordVersion) {
+ /* Do we need a better error here? */
+ PORT_SetError(SSL_ERROR_BAD_MAC_READ);
+ return SECFailure;
+ }
+
+ /* Decrypt */
+ PORT_Assert(cipher_def->type == type_aead);
+ tls13_FormatAdditionalData(aad, sizeof(aad),
+ IS_DTLS(ss) ? cText->seq_num
+ : crSpec->read_seq_num);
+ rv = crSpec->aead(
+ ss->sec.isServer ? &crSpec->client : &crSpec->server,
+ PR_TRUE, /* do decrypt */
+ plaintext->buf, /* out */
+ (int *)&plaintext->len, /* outlen */
+ plaintext->space, /* maxout */
+ cText->buf->buf, /* in */
+ cText->buf->len, /* inlen */
+ aad, sizeof(aad));
+ if (rv != SECSuccess) {
+ PORT_SetError(SSL_ERROR_BAD_MAC_READ);
+ return SECFailure;
+ }
+
+ /* The record is right-padded with 0s, followed by the true
+ * content type, so read from the right until we receive a
+ * nonzero byte. */
+ while (plaintext->len > 0 && !(plaintext->buf[plaintext->len - 1])) {
+ --plaintext->len;
+ }
+
+ /* Bogus padding. */
+ if (plaintext->len < 1) {
+ /* It's safe to report this specifically because it happened
+ * after the MAC has been verified. */
+ PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING);
+ return SECFailure;
+ }
+
+ /* Record the type. */
+ cText->type = plaintext->buf[plaintext->len - 1];
+ --plaintext->len;
+
+ return SECSuccess;
+}
diff --git a/chromium/net/third_party/nss/ssl/tls13con.h b/chromium/net/third_party/nss/ssl/tls13con.h
new file mode 100644
index 00000000000..a96d3236794
--- /dev/null
+++ b/chromium/net/third_party/nss/ssl/tls13con.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is PRIVATE to SSL.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __tls13con_h_
+#define __tls13con_h_
+
+typedef enum {
+ StaticSharedSecret,
+ EphemeralSharedSecret
+} SharedSecretType;
+
+SECStatus tls13_UnprotectRecord(
+ sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *plaintext,
+ SSL3AlertDescription *alert);
+unsigned char *
+tls13_EncodeUintX(PRUint32 value, unsigned int bytes, unsigned char *to);
+
+#if defined(WIN32)
+#define __func__ __FUNCTION__
+#endif
+
+void tls13_SetHsState(sslSocket *ss, SSL3WaitState ws,
+ const char *func, const char *file, int line);
+#define TLS13_SET_HS_STATE(ss, ws) \
+ tls13_SetHsState(ss, ws, __func__, __FILE__, __LINE__)
+
+/* Return PR_TRUE if the socket is in one of the given states, else return
+ * PR_FALSE. Only call the macro not the function, because the trailing
+ * wait_invalid is needed to terminate the argument list. */
+PRBool tls13_InHsState(sslSocket *ss, ...);
+#define TLS13_IN_HS_STATE(ss, ...) \
+ tls13_InHsState(ss, __VA_ARGS__, wait_invalid)
+
+SSLHashType tls13_GetHash(sslSocket *ss);
+CK_MECHANISM_TYPE tls13_GetHkdfMechanism(sslSocket *ss);
+void tls13_FatalError(sslSocket *ss, PRErrorCode prError,
+ SSL3AlertDescription desc);
+SECStatus tls13_SetupClientHello(sslSocket *ss);
+SECStatus tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
+ PRUint32 length,
+ SSL3Hashes *hashesPtr);
+SECStatus tls13_HandleClientKeyShare(sslSocket *ss);
+SECStatus tls13_SendServerHelloSequence(sslSocket *ss);
+SECStatus tls13_HandleServerKeyShare(sslSocket *ss);
+SECStatus tls13_AddContextToHashes(sslSocket *ss,
+ SSL3Hashes *hashes /* IN/OUT */,
+ SSLHashType algorithm, PRBool sending);
+void tls13_DestroyKeyShareEntry(TLS13KeyShareEntry *entry);
+void tls13_DestroyKeyShares(PRCList *list);
+PRBool tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message);
+SECStatus tls13_ProtectRecord(sslSocket *ss,
+ SSL3ContentType type,
+ const SSL3Opaque *pIn,
+ PRUint32 contentLen,
+ sslBuffer *wrBuf);
+
+#endif /* __tls13con_h_ */
diff --git a/chromium/net/third_party/nss/ssl/tls13hkdf.c b/chromium/net/third_party/nss/ssl/tls13hkdf.c
new file mode 100644
index 00000000000..3dc2d1bf8d0
--- /dev/null
+++ b/chromium/net/third_party/nss/ssl/tls13hkdf.c
@@ -0,0 +1,212 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * TLS 1.3 Protocol
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "keyhi.h"
+#include "pk11func.h"
+#include "secitem.h"
+#include "sslt.h"
+#include "sslerr.h"
+
+// TODO(ekr@rtfm.com): Export this separately.
+unsigned char *tls13_EncodeUintX(PRUint32 value, unsigned int bytes, unsigned char *to);
+
+/* This table contains the mapping between TLS hash identifiers and the
+ * PKCS#11 identifiers */
+static const struct {
+ SSLHashType hash;
+ CK_MECHANISM_TYPE pkcs11Mech;
+ unsigned int hashSize;
+} kTlsHkdfInfo[] = {
+ { ssl_hash_none, 0, 0 },
+ { ssl_hash_md5, 0, 0 },
+ { ssl_hash_sha1, 0, 0 },
+ { ssl_hash_sha224, 0 },
+ { ssl_hash_sha256, CKM_NSS_HKDF_SHA256, 32 },
+ { ssl_hash_sha384, CKM_NSS_HKDF_SHA384, 48 },
+ { ssl_hash_sha512, CKM_NSS_HKDF_SHA512, 64 }
+};
+
+SECStatus
+tls13_HkdfExtract(PK11SymKey *ikm1, PK11SymKey *ikm2, SSLHashType baseHash,
+ PK11SymKey **prkp)
+{
+ CK_NSS_HKDFParams params;
+ SECItem paramsi;
+ SECStatus rv;
+ SECItem *salt;
+ PK11SymKey *prk;
+
+ params.bExtract = CK_TRUE;
+ params.bExpand = CK_FALSE;
+ params.pInfo = NULL;
+ params.ulInfoLen = 0UL;
+
+ if (ikm1) {
+ /* TODO(ekr@rtfm.com): This violates the PKCS#11 key boundary
+ * but is imposed on us by the present HKDF interface. */
+ rv = PK11_ExtractKeyValue(ikm1);
+ if (rv != SECSuccess)
+ return rv;
+
+ salt = PK11_GetKeyData(ikm1);
+ if (!salt)
+ return SECFailure;
+
+ params.pSalt = salt->data;
+ params.ulSaltLen = salt->len;
+ PORT_Assert(salt->len > 0);
+ } else {
+ /* Per documentation for CKM_NSS_HKDF_*:
+ *
+ * If the optional salt is given, it is used; otherwise, the salt is
+ * set to a sequence of zeros equal in length to the HMAC output.
+ */
+ params.pSalt = NULL;
+ params.ulSaltLen = 0UL;
+ }
+ paramsi.data = (unsigned char *)&params;
+ paramsi.len = sizeof(params);
+
+ PORT_Assert(kTlsHkdfInfo[baseHash].pkcs11Mech);
+ PORT_Assert(kTlsHkdfInfo[baseHash].hashSize);
+ PORT_Assert(kTlsHkdfInfo[baseHash].hash == baseHash);
+ prk = PK11_Derive(ikm2, kTlsHkdfInfo[baseHash].pkcs11Mech,
+ &paramsi, kTlsHkdfInfo[baseHash].pkcs11Mech,
+ CKA_DERIVE, kTlsHkdfInfo[baseHash].hashSize);
+ if (!prk)
+ return SECFailure;
+
+ *prkp = prk;
+ return SECSuccess;
+}
+
+SECStatus
+tls13_HkdfExpandLabel(PK11SymKey *prk, SSLHashType baseHash,
+ const PRUint8 *handshakeHash, unsigned int handshakeHashLen,
+ const char *label, unsigned int labelLen,
+ CK_MECHANISM_TYPE algorithm, unsigned int keySize,
+ PK11SymKey **keyp)
+{
+ CK_NSS_HKDFParams params;
+ SECItem paramsi = { siBuffer, NULL, 0 };
+ PRUint8 info[100];
+ PRUint8 *ptr = info;
+ unsigned int infoLen;
+ PK11SymKey *derived;
+ const char *kLabelPrefix = "TLS 1.3, ";
+ const unsigned int kLabelPrefixLen = strlen(kLabelPrefix);
+
+ if (handshakeHash) {
+ PORT_Assert(handshakeHashLen == kTlsHkdfInfo[baseHash].hashSize);
+ } else {
+ PORT_Assert(!handshakeHashLen);
+ }
+
+ /*
+ * [draft-ietf-tls-tls13-11] Section 7.1:
+ *
+ * HKDF-Expand-Label(Secret, Label, HashValue, Length) =
+ * HKDF-Expand(Secret, HkdfLabel, Length)
+ *
+ * Where HkdfLabel is specified as:
+ *
+ * struct HkdfLabel {
+ * uint16 length;
+ * opaque label<9..255>;
+ * opaque hash_value<0..255>;
+ * };
+ *
+ * Where:
+ * - HkdfLabel.length is Length
+ * - HkdfLabel.hash_value is HashValue.
+ * - HkdfLabel.label is "TLS 1.3, " + Label
+ *
+ */
+ infoLen = 2 + 1 + kLabelPrefixLen + labelLen + 1 + handshakeHashLen;
+ if (infoLen > sizeof(info)) {
+ PORT_Assert(0);
+ goto abort;
+ }
+
+ ptr = tls13_EncodeUintX(keySize, 2, ptr);
+ ptr = tls13_EncodeUintX(labelLen + kLabelPrefixLen, 1, ptr);
+ PORT_Memcpy(ptr, kLabelPrefix, kLabelPrefixLen);
+ ptr += kLabelPrefixLen;
+ PORT_Memcpy(ptr, label, labelLen);
+ ptr += labelLen;
+ ptr = tls13_EncodeUintX(handshakeHashLen, 1, ptr);
+ if (handshakeHash) {
+ PORT_Memcpy(ptr, handshakeHash, handshakeHashLen);
+ ptr += handshakeHashLen;
+ }
+ PORT_Assert((ptr - info) == infoLen);
+
+ params.bExtract = CK_FALSE;
+ params.bExpand = CK_TRUE;
+ params.pInfo = info;
+ params.ulInfoLen = infoLen;
+ paramsi.data = (unsigned char *)&params;
+ paramsi.len = sizeof(params);
+
+ derived = PK11_DeriveWithFlags(prk, kTlsHkdfInfo[baseHash].pkcs11Mech,
+ &paramsi, algorithm,
+ CKA_DERIVE, keySize,
+ CKF_SIGN | CKF_VERIFY);
+ if (!derived)
+ return SECFailure;
+
+ *keyp = derived;
+
+ return SECSuccess;
+
+abort:
+ PORT_SetError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
+ return SECFailure;
+}
+
+SECStatus
+tls13_HkdfExpandLabelRaw(PK11SymKey *prk, SSLHashType baseHash,
+ const PRUint8 *handshakeHash, unsigned int handshakeHashLen,
+ const char *label, unsigned int labelLen,
+ unsigned char *output, unsigned int outputLen)
+{
+ PK11SymKey *derived = NULL;
+ SECItem *rawkey;
+ SECStatus rv;
+
+ rv = tls13_HkdfExpandLabel(prk, baseHash, handshakeHash, handshakeHashLen,
+ label, labelLen,
+ kTlsHkdfInfo[baseHash].pkcs11Mech, outputLen,
+ &derived);
+ if (rv != SECSuccess || !derived) {
+ goto abort;
+ }
+
+ rv = PK11_ExtractKeyValue(derived);
+ if (rv != SECSuccess) {
+ goto abort;
+ }
+
+ rawkey = PK11_GetKeyData(derived);
+ if (!rawkey) {
+ goto abort;
+ }
+
+ PORT_Assert(rawkey->len == outputLen);
+ memcpy(output, rawkey->data, outputLen);
+ PK11_FreeSymKey(derived);
+
+ return SECSuccess;
+
+abort:
+ if (derived) {
+ PK11_FreeSymKey(derived);
+ }
+ PORT_SetError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
+ return SECFailure;
+}
diff --git a/chromium/net/third_party/nss/ssl/tls13hkdf.h b/chromium/net/third_party/nss/ssl/tls13hkdf.h
new file mode 100644
index 00000000000..78347a11dc2
--- /dev/null
+++ b/chromium/net/third_party/nss/ssl/tls13hkdf.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is PRIVATE to SSL.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __tls13hkdf_h_
+#define __tls13hkdf_h_
+
+#include "keyhi.h"
+#include "sslt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SECStatus tls13_HkdfExtract(
+ PK11SymKey *ikm1, PK11SymKey *ikm2, SSLHashType baseHash,
+ PK11SymKey **prkp);
+SECStatus tls13_HkdfExpandLabelRaw(
+ PK11SymKey *prk, SSLHashType baseHash,
+ const PRUint8 *handshakeHash, unsigned int handshakeHashLen,
+ const char *label, unsigned int labelLen,
+ unsigned char *output, unsigned int outputLen);
+SECStatus tls13_HkdfExpandLabel(
+ PK11SymKey *prk, SSLHashType baseHash,
+ const PRUint8 *handshakeHash, unsigned int handshakeHashLen,
+ const char *label, unsigned int labelLen,
+ CK_MECHANISM_TYPE algorithm, unsigned int keySize,
+ PK11SymKey **keyp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/chromium/net/third_party/nss/ssl/unix_err.c b/chromium/net/third_party/nss/ssl/unix_err.c
index 1857cfefc70..ca0b0507b27 100644
--- a/chromium/net/third_party/nss/ssl/unix_err.c
+++ b/chromium/net/third_party/nss/ssl/unix_err.c
@@ -1,12 +1,12 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* This file essentially replicates NSPR's source for the functions that
- * map system-specific error codes to NSPR error codes. We would use
+ * map system-specific error codes to NSPR error codes. We would use
* NSPR's functions, instead of duplicating them, but they're private.
* As long as SSL's server session cache code must do platform native I/O
* to accomplish its job, and NSPR's error mapping functions remain private,
* this code will continue to need to be replicated.
- *
+ *
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@@ -18,7 +18,7 @@
#include "prerror.h"
#endif
-#if defined (__bsdi__) || defined(NTO) || defined(DARWIN) || defined(BEOS)
+#if defined(__bsdi__) || defined(NTO) || defined(DARWIN) || defined(BEOS)
#undef _PR_POLL_AVAILABLE
#endif
@@ -30,357 +30,547 @@
/* forward declarations. */
void nss_MD_unix_map_default_error(int err);
-void nss_MD_unix_map_opendir_error(int err)
+void
+nss_MD_unix_map_opendir_error(int err)
{
nss_MD_unix_map_default_error(err);
}
-void nss_MD_unix_map_closedir_error(int err)
+void
+nss_MD_unix_map_closedir_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EINVAL: prError = PR_BAD_DESCRIPTOR_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EINVAL:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_readdir_error(int err)
+void
+nss_MD_unix_readdir_error(int err)
{
PRErrorCode prError;
switch (err) {
- case ENOENT: prError = PR_NO_MORE_FILES_ERROR; break;
+ case ENOENT:
+ prError = PR_NO_MORE_FILES_ERROR;
+ break;
#ifdef EOVERFLOW
- case EOVERFLOW: prError = PR_IO_ERROR; break;
+ case EOVERFLOW:
+ prError = PR_IO_ERROR;
+ break;
#endif
- case EINVAL: prError = PR_IO_ERROR; break;
- case ENXIO: prError = PR_IO_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EINVAL:
+ prError = PR_IO_ERROR;
+ break;
+ case ENXIO:
+ prError = PR_IO_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_unlink_error(int err)
+void
+nss_MD_unix_map_unlink_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EPERM: prError = PR_IS_DIRECTORY_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EPERM:
+ prError = PR_IS_DIRECTORY_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_stat_error(int err)
+void
+nss_MD_unix_map_stat_error(int err)
{
PRErrorCode prError;
switch (err) {
- case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_fstat_error(int err)
+void
+nss_MD_unix_map_fstat_error(int err)
{
PRErrorCode prError;
switch (err) {
- case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_rename_error(int err)
+void
+nss_MD_unix_map_rename_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EEXIST: prError = PR_DIRECTORY_NOT_EMPTY_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EEXIST:
+ prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_access_error(int err)
+void
+nss_MD_unix_map_access_error(int err)
{
PRErrorCode prError;
switch (err) {
- case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_mkdir_error(int err)
+void
+nss_MD_unix_map_mkdir_error(int err)
{
nss_MD_unix_map_default_error(err);
}
-void nss_MD_unix_map_rmdir_error(int err)
+void
+nss_MD_unix_map_rmdir_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EEXIST: prError = PR_DIRECTORY_NOT_EMPTY_ERROR; break;
- case EINVAL: prError = PR_DIRECTORY_NOT_EMPTY_ERROR; break;
- case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EEXIST:
+ prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
+ break;
+ case EINVAL:
+ prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
+ break;
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_read_error(int err)
+void
+nss_MD_unix_map_read_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EINVAL: prError = PR_INVALID_METHOD_ERROR; break;
- case ENXIO: prError = PR_INVALID_ARGUMENT_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EINVAL:
+ prError = PR_INVALID_METHOD_ERROR;
+ break;
+ case ENXIO:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_write_error(int err)
+void
+nss_MD_unix_map_write_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EINVAL: prError = PR_INVALID_METHOD_ERROR; break;
- case ENXIO: prError = PR_INVALID_METHOD_ERROR; break;
- case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EINVAL:
+ prError = PR_INVALID_METHOD_ERROR;
+ break;
+ case ENXIO:
+ prError = PR_INVALID_METHOD_ERROR;
+ break;
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_lseek_error(int err)
+void
+nss_MD_unix_map_lseek_error(int err)
{
nss_MD_unix_map_default_error(err);
}
-void nss_MD_unix_map_fsync_error(int err)
+void
+nss_MD_unix_map_fsync_error(int err)
{
PRErrorCode prError;
switch (err) {
- case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break;
- case EINVAL: prError = PR_INVALID_METHOD_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ case EINVAL:
+ prError = PR_INVALID_METHOD_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_close_error(int err)
+void
+nss_MD_unix_map_close_error(int err)
{
PRErrorCode prError;
switch (err) {
- case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_socket_error(int err)
+void
+nss_MD_unix_map_socket_error(int err)
{
PRErrorCode prError;
switch (err) {
- case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_socketavailable_error(int err)
+void
+nss_MD_unix_map_socketavailable_error(int err)
{
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
}
-void nss_MD_unix_map_recv_error(int err)
+void
+nss_MD_unix_map_recv_error(int err)
{
nss_MD_unix_map_default_error(err);
}
-void nss_MD_unix_map_recvfrom_error(int err)
+void
+nss_MD_unix_map_recvfrom_error(int err)
{
nss_MD_unix_map_default_error(err);
}
-void nss_MD_unix_map_send_error(int err)
+void
+nss_MD_unix_map_send_error(int err)
{
nss_MD_unix_map_default_error(err);
}
-void nss_MD_unix_map_sendto_error(int err)
+void
+nss_MD_unix_map_sendto_error(int err)
{
nss_MD_unix_map_default_error(err);
}
-void nss_MD_unix_map_writev_error(int err)
+void
+nss_MD_unix_map_writev_error(int err)
{
nss_MD_unix_map_default_error(err);
}
-void nss_MD_unix_map_accept_error(int err)
+void
+nss_MD_unix_map_accept_error(int err)
{
PRErrorCode prError;
switch (err) {
- case ENODEV: prError = PR_NOT_TCP_SOCKET_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case ENODEV:
+ prError = PR_NOT_TCP_SOCKET_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_connect_error(int err)
+void
+nss_MD_unix_map_connect_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EACCES: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
+ case EACCES:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
#if defined(UNIXWARE) || defined(SNI) || defined(NEC)
- /*
- * On some platforms, if we connect to a port on the local host
- * (the loopback address) that no process is listening on, we get
- * EIO instead of ECONNREFUSED.
- */
- case EIO: prError = PR_CONNECT_REFUSED_ERROR; break;
+ /*
+ * On some platforms, if we connect to a port on the local host
+ * (the loopback address) that no process is listening on, we get
+ * EIO instead of ECONNREFUSED.
+ */
+ case EIO:
+ prError = PR_CONNECT_REFUSED_ERROR;
+ break;
#endif
- case ELOOP: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
- case ENOENT: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
- case ENXIO: prError = PR_IO_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case ELOOP:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case ENOENT:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case ENXIO:
+ prError = PR_IO_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_bind_error(int err)
+void
+nss_MD_unix_map_bind_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EINVAL: prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR; break;
- /*
- * UNIX domain sockets are not supported in NSPR
- */
- case EIO: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
- case EISDIR: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
- case ELOOP: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
- case ENOENT: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
- case ENOTDIR: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
- case EROFS: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EINVAL:
+ prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR;
+ break;
+ /*
+ * UNIX domain sockets are not supported in NSPR
+ */
+ case EIO:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case EISDIR:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case ELOOP:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case ENOENT:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case ENOTDIR:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case EROFS:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_listen_error(int err)
+void
+nss_MD_unix_map_listen_error(int err)
{
nss_MD_unix_map_default_error(err);
}
-void nss_MD_unix_map_shutdown_error(int err)
+void
+nss_MD_unix_map_shutdown_error(int err)
{
nss_MD_unix_map_default_error(err);
}
-void nss_MD_unix_map_socketpair_error(int err)
+void
+nss_MD_unix_map_socketpair_error(int err)
{
PRErrorCode prError;
switch (err) {
- case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_getsockname_error(int err)
+void
+nss_MD_unix_map_getsockname_error(int err)
{
PRErrorCode prError;
switch (err) {
- case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_getpeername_error(int err)
+void
+nss_MD_unix_map_getpeername_error(int err)
{
PRErrorCode prError;
switch (err) {
- case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_getsockopt_error(int err)
+void
+nss_MD_unix_map_getsockopt_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EINVAL: prError = PR_BUFFER_OVERFLOW_ERROR; break;
- case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EINVAL:
+ prError = PR_BUFFER_OVERFLOW_ERROR;
+ break;
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_setsockopt_error(int err)
+void
+nss_MD_unix_map_setsockopt_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EINVAL: prError = PR_BUFFER_OVERFLOW_ERROR; break;
- case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EINVAL:
+ prError = PR_BUFFER_OVERFLOW_ERROR;
+ break;
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_open_error(int err)
+void
+nss_MD_unix_map_open_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EAGAIN: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- case EBUSY: prError = PR_IO_ERROR; break;
- case ENODEV: prError = PR_FILE_NOT_FOUND_ERROR; break;
- case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EAGAIN:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case EBUSY:
+ prError = PR_IO_ERROR;
+ break;
+ case ENODEV:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_mmap_error(int err)
+void
+nss_MD_unix_map_mmap_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EAGAIN: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- case EMFILE: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- case ENODEV: prError = PR_OPERATION_NOT_SUPPORTED_ERROR; break;
- case ENXIO: prError = PR_INVALID_ARGUMENT_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EAGAIN:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case EMFILE:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case ENODEV:
+ prError = PR_OPERATION_NOT_SUPPORTED_ERROR;
+ break;
+ case ENXIO:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_gethostname_error(int err)
+void
+nss_MD_unix_map_gethostname_error(int err)
{
nss_MD_unix_map_default_error(err);
}
-void nss_MD_unix_map_select_error(int err)
+void
+nss_MD_unix_map_select_error(int err)
{
nss_MD_unix_map_default_error(err);
}
#ifdef _PR_POLL_AVAILABLE
-void nss_MD_unix_map_poll_error(int err)
+void
+nss_MD_unix_map_poll_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EAGAIN: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EAGAIN:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_poll_revents_error(int err)
+void
+nss_MD_unix_map_poll_revents_error(int err)
{
if (err & POLLNVAL)
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
@@ -393,125 +583,255 @@ void nss_MD_unix_map_poll_revents_error(int err)
}
#endif /* _PR_POLL_AVAILABLE */
-
-void nss_MD_unix_map_flock_error(int err)
+void
+nss_MD_unix_map_flock_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EINVAL: prError = PR_BAD_DESCRIPTOR_ERROR; break;
- case EWOULDBLOCK: prError = PR_FILE_IS_LOCKED_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EINVAL:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ case EWOULDBLOCK:
+ prError = PR_FILE_IS_LOCKED_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_unix_map_lockf_error(int err)
+void
+nss_MD_unix_map_lockf_error(int err)
{
PRErrorCode prError;
switch (err) {
- case EACCES: prError = PR_FILE_IS_LOCKED_ERROR; break;
- case EDEADLK: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- default: nss_MD_unix_map_default_error(err); return;
+ case EACCES:
+ prError = PR_FILE_IS_LOCKED_ERROR;
+ break;
+ case EDEADLK:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ nss_MD_unix_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
#ifdef HPUX11
-void nss_MD_hpux_map_sendfile_error(int err)
+void
+nss_MD_hpux_map_sendfile_error(int err)
{
nss_MD_unix_map_default_error(err);
}
#endif /* HPUX11 */
-
-void nss_MD_unix_map_default_error(int err)
+void
+nss_MD_unix_map_default_error(int err)
{
PRErrorCode prError;
- switch (err ) {
- case EACCES: prError = PR_NO_ACCESS_RIGHTS_ERROR; break;
- case EADDRINUSE: prError = PR_ADDRESS_IN_USE_ERROR; break;
- case EADDRNOTAVAIL: prError = PR_ADDRESS_NOT_AVAILABLE_ERROR; break;
- case EAFNOSUPPORT: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
- case EAGAIN: prError = PR_WOULD_BLOCK_ERROR; break;
+ switch (err) {
+ case EACCES:
+ prError = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case EADDRINUSE:
+ prError = PR_ADDRESS_IN_USE_ERROR;
+ break;
+ case EADDRNOTAVAIL:
+ prError = PR_ADDRESS_NOT_AVAILABLE_ERROR;
+ break;
+ case EAFNOSUPPORT:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case EAGAIN:
+ prError = PR_WOULD_BLOCK_ERROR;
+ break;
/*
* On QNX and Neutrino, EALREADY is defined as EBUSY.
*/
#if EALREADY != EBUSY
- case EALREADY: prError = PR_ALREADY_INITIATED_ERROR; break;
+ case EALREADY:
+ prError = PR_ALREADY_INITIATED_ERROR;
+ break;
#endif
- case EBADF: prError = PR_BAD_DESCRIPTOR_ERROR; break;
+ case EBADF:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
#ifdef EBADMSG
- case EBADMSG: prError = PR_IO_ERROR; break;
+ case EBADMSG:
+ prError = PR_IO_ERROR;
+ break;
#endif
- case EBUSY: prError = PR_FILESYSTEM_MOUNTED_ERROR; break;
- case ECONNREFUSED: prError = PR_CONNECT_REFUSED_ERROR; break;
- case ECONNRESET: prError = PR_CONNECT_RESET_ERROR; break;
- case EDEADLK: prError = PR_DEADLOCK_ERROR; break;
+ case EBUSY:
+ prError = PR_FILESYSTEM_MOUNTED_ERROR;
+ break;
+ case ECONNREFUSED:
+ prError = PR_CONNECT_REFUSED_ERROR;
+ break;
+ case ECONNRESET:
+ prError = PR_CONNECT_RESET_ERROR;
+ break;
+ case EDEADLK:
+ prError = PR_DEADLOCK_ERROR;
+ break;
#ifdef EDIRCORRUPTED
- case EDIRCORRUPTED: prError = PR_DIRECTORY_CORRUPTED_ERROR; break;
+ case EDIRCORRUPTED:
+ prError = PR_DIRECTORY_CORRUPTED_ERROR;
+ break;
#endif
#ifdef EDQUOT
- case EDQUOT: prError = PR_NO_DEVICE_SPACE_ERROR; break;
+ case EDQUOT:
+ prError = PR_NO_DEVICE_SPACE_ERROR;
+ break;
#endif
- case EEXIST: prError = PR_FILE_EXISTS_ERROR; break;
- case EFAULT: prError = PR_ACCESS_FAULT_ERROR; break;
- case EFBIG: prError = PR_FILE_TOO_BIG_ERROR; break;
- case EINPROGRESS: prError = PR_IN_PROGRESS_ERROR; break;
- case EINTR: prError = PR_PENDING_INTERRUPT_ERROR; break;
- case EINVAL: prError = PR_INVALID_ARGUMENT_ERROR; break;
- case EIO: prError = PR_IO_ERROR; break;
- case EISCONN: prError = PR_IS_CONNECTED_ERROR; break;
- case EISDIR: prError = PR_IS_DIRECTORY_ERROR; break;
- case ELOOP: prError = PR_LOOP_ERROR; break;
- case EMFILE: prError = PR_PROC_DESC_TABLE_FULL_ERROR; break;
- case EMLINK: prError = PR_MAX_DIRECTORY_ENTRIES_ERROR; break;
- case EMSGSIZE: prError = PR_INVALID_ARGUMENT_ERROR; break;
+ case EEXIST:
+ prError = PR_FILE_EXISTS_ERROR;
+ break;
+ case EFAULT:
+ prError = PR_ACCESS_FAULT_ERROR;
+ break;
+ case EFBIG:
+ prError = PR_FILE_TOO_BIG_ERROR;
+ break;
+ case EINPROGRESS:
+ prError = PR_IN_PROGRESS_ERROR;
+ break;
+ case EINTR:
+ prError = PR_PENDING_INTERRUPT_ERROR;
+ break;
+ case EINVAL:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case EIO:
+ prError = PR_IO_ERROR;
+ break;
+ case EISCONN:
+ prError = PR_IS_CONNECTED_ERROR;
+ break;
+ case EISDIR:
+ prError = PR_IS_DIRECTORY_ERROR;
+ break;
+ case ELOOP:
+ prError = PR_LOOP_ERROR;
+ break;
+ case EMFILE:
+ prError = PR_PROC_DESC_TABLE_FULL_ERROR;
+ break;
+ case EMLINK:
+ prError = PR_MAX_DIRECTORY_ENTRIES_ERROR;
+ break;
+ case EMSGSIZE:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
#ifdef EMULTIHOP
- case EMULTIHOP: prError = PR_REMOTE_FILE_ERROR; break;
+ case EMULTIHOP:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
#endif
- case ENAMETOOLONG: prError = PR_NAME_TOO_LONG_ERROR; break;
- case ENETUNREACH: prError = PR_NETWORK_UNREACHABLE_ERROR; break;
- case ENFILE: prError = PR_SYS_DESC_TABLE_FULL_ERROR; break;
+ case ENAMETOOLONG:
+ prError = PR_NAME_TOO_LONG_ERROR;
+ break;
+ case ENETUNREACH:
+ prError = PR_NETWORK_UNREACHABLE_ERROR;
+ break;
+ case ENFILE:
+ prError = PR_SYS_DESC_TABLE_FULL_ERROR;
+ break;
#if !defined(SCO)
- case ENOBUFS: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
+ case ENOBUFS:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
#endif
- case ENODEV: prError = PR_FILE_NOT_FOUND_ERROR; break;
- case ENOENT: prError = PR_FILE_NOT_FOUND_ERROR; break;
- case ENOLCK: prError = PR_FILE_IS_LOCKED_ERROR; break;
-#ifdef ENOLINK
- case ENOLINK: prError = PR_REMOTE_FILE_ERROR; break;
+ case ENODEV:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case ENOENT:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case ENOLCK:
+ prError = PR_FILE_IS_LOCKED_ERROR;
+ break;
+#ifdef ENOLINK
+ case ENOLINK:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
#endif
- case ENOMEM: prError = PR_OUT_OF_MEMORY_ERROR; break;
- case ENOPROTOOPT: prError = PR_INVALID_ARGUMENT_ERROR; break;
- case ENOSPC: prError = PR_NO_DEVICE_SPACE_ERROR; break;
-#ifdef ENOSR
- case ENOSR: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
+ case ENOMEM:
+ prError = PR_OUT_OF_MEMORY_ERROR;
+ break;
+ case ENOPROTOOPT:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case ENOSPC:
+ prError = PR_NO_DEVICE_SPACE_ERROR;
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
#endif
- case ENOTCONN: prError = PR_NOT_CONNECTED_ERROR; break;
- case ENOTDIR: prError = PR_NOT_DIRECTORY_ERROR; break;
- case ENOTSOCK: prError = PR_NOT_SOCKET_ERROR; break;
- case ENXIO: prError = PR_FILE_NOT_FOUND_ERROR; break;
- case EOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break;
+ case ENOTCONN:
+ prError = PR_NOT_CONNECTED_ERROR;
+ break;
+ case ENOTDIR:
+ prError = PR_NOT_DIRECTORY_ERROR;
+ break;
+ case ENOTSOCK:
+ prError = PR_NOT_SOCKET_ERROR;
+ break;
+ case ENXIO:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case EOPNOTSUPP:
+ prError = PR_NOT_TCP_SOCKET_ERROR;
+ break;
#ifdef EOVERFLOW
- case EOVERFLOW: prError = PR_BUFFER_OVERFLOW_ERROR; break;
+ case EOVERFLOW:
+ prError = PR_BUFFER_OVERFLOW_ERROR;
+ break;
#endif
- case EPERM: prError = PR_NO_ACCESS_RIGHTS_ERROR; break;
- case EPIPE: prError = PR_CONNECT_RESET_ERROR; break;
+ case EPERM:
+ prError = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case EPIPE:
+ prError = PR_CONNECT_RESET_ERROR;
+ break;
#ifdef EPROTO
- case EPROTO: prError = PR_IO_ERROR; break;
+ case EPROTO:
+ prError = PR_IO_ERROR;
+ break;
#endif
- case EPROTONOSUPPORT: prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR; break;
- case EPROTOTYPE: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
- case ERANGE: prError = PR_INVALID_METHOD_ERROR; break;
- case EROFS: prError = PR_READ_ONLY_FILESYSTEM_ERROR; break;
- case ESPIPE: prError = PR_INVALID_METHOD_ERROR; break;
- case ETIMEDOUT: prError = PR_IO_TIMEOUT_ERROR; break;
+ case EPROTONOSUPPORT:
+ prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR;
+ break;
+ case EPROTOTYPE:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case ERANGE:
+ prError = PR_INVALID_METHOD_ERROR;
+ break;
+ case EROFS:
+ prError = PR_READ_ONLY_FILESYSTEM_ERROR;
+ break;
+ case ESPIPE:
+ prError = PR_INVALID_METHOD_ERROR;
+ break;
+ case ETIMEDOUT:
+ prError = PR_IO_TIMEOUT_ERROR;
+ break;
#if EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK: prError = PR_WOULD_BLOCK_ERROR; break;
+ case EWOULDBLOCK:
+ prError = PR_WOULD_BLOCK_ERROR;
+ break;
#endif
- case EXDEV: prError = PR_NOT_SAME_DEVICE_ERROR; break;
+ case EXDEV:
+ prError = PR_NOT_SAME_DEVICE_ERROR;
+ break;
- default: prError = PR_UNKNOWN_ERROR; break;
+ default:
+ prError = PR_UNKNOWN_ERROR;
+ break;
}
PR_SetError(prError, err);
}
diff --git a/chromium/net/third_party/nss/ssl/unix_err.h b/chromium/net/third_party/nss/ssl/unix_err.h
index be7fe292178..5d7d547bfb6 100644
--- a/chromium/net/third_party/nss/ssl/unix_err.h
+++ b/chromium/net/third_party/nss/ssl/unix_err.h
@@ -1,11 +1,11 @@
/*
* This file essentially replicates NSPR's source for the functions that
- * map system-specific error codes to NSPR error codes. We would use
+ * map system-specific error codes to NSPR error codes. We would use
* NSPR's functions, instead of duplicating them, but they're private.
* As long as SSL's server session cache code must do platform native I/O
* to accomplish its job, and NSPR's error mapping functions remain private,
* this code will continue to need to be replicated.
- *
+ *
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
diff --git a/chromium/net/third_party/nss/ssl/win32err.c b/chromium/net/third_party/nss/ssl/win32err.c
index a70010d370a..caa12b956e1 100644
--- a/chromium/net/third_party/nss/ssl/win32err.c
+++ b/chromium/net/third_party/nss/ssl/win32err.c
@@ -1,12 +1,12 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* This file essentially replicates NSPR's source for the functions that
- * map system-specific error codes to NSPR error codes. We would use
+ * map system-specific error codes to NSPR error codes. We would use
* NSPR's functions, instead of duplicating them, but they're private.
* As long as SSL's server session cache code must do platform native I/O
* to accomplish its job, and NSPR's error mapping functions remain private,
* this code will continue to need to be replicated.
- *
+ *
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@@ -33,79 +33,94 @@
/* forward declaration. */
void nss_MD_win32_map_default_error(PRInt32 err);
-void nss_MD_win32_map_opendir_error(PRInt32 err)
+void
+nss_MD_win32_map_opendir_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_closedir_error(PRInt32 err)
+void
+nss_MD_win32_map_closedir_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_readdir_error(PRInt32 err)
+void
+nss_MD_win32_map_readdir_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_delete_error(PRInt32 err)
+void
+nss_MD_win32_map_delete_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
/* The error code for stat() is in errno. */
-void nss_MD_win32_map_stat_error(PRInt32 err)
+void
+nss_MD_win32_map_stat_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_fstat_error(PRInt32 err)
+void
+nss_MD_win32_map_fstat_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_rename_error(PRInt32 err)
+void
+nss_MD_win32_map_rename_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
/* The error code for access() is in errno. */
-void nss_MD_win32_map_access_error(PRInt32 err)
+void
+nss_MD_win32_map_access_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_mkdir_error(PRInt32 err)
+void
+nss_MD_win32_map_mkdir_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_rmdir_error(PRInt32 err)
+void
+nss_MD_win32_map_rmdir_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_read_error(PRInt32 err)
+void
+nss_MD_win32_map_read_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_transmitfile_error(PRInt32 err)
+void
+nss_MD_win32_map_transmitfile_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_write_error(PRInt32 err)
+void
+nss_MD_win32_map_write_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_lseek_error(PRInt32 err)
+void
+nss_MD_win32_map_lseek_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_fsync_error(PRInt32 err)
+void
+nss_MD_win32_map_fsync_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
@@ -113,231 +128,423 @@ void nss_MD_win32_map_fsync_error(PRInt32 err)
/*
* For both CloseHandle() and closesocket().
*/
-void nss_MD_win32_map_close_error(PRInt32 err)
+void
+nss_MD_win32_map_close_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_socket_error(PRInt32 err)
+void
+nss_MD_win32_map_socket_error(PRInt32 err)
{
PR_ASSERT(err != WSANOTINITIALISED);
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_recv_error(PRInt32 err)
+void
+nss_MD_win32_map_recv_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_recvfrom_error(PRInt32 err)
+void
+nss_MD_win32_map_recvfrom_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_send_error(PRInt32 err)
+void
+nss_MD_win32_map_send_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
- case WSAEMSGSIZE: prError = PR_INVALID_ARGUMENT_ERROR; break;
- default: nss_MD_win32_map_default_error(err); return;
+ case WSAEMSGSIZE:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ default:
+ nss_MD_win32_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_win32_map_sendto_error(PRInt32 err)
+void
+nss_MD_win32_map_sendto_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
- case WSAEMSGSIZE: prError = PR_INVALID_ARGUMENT_ERROR; break;
- default: nss_MD_win32_map_default_error(err); return;
+ case WSAEMSGSIZE:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ default:
+ nss_MD_win32_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_win32_map_accept_error(PRInt32 err)
+void
+nss_MD_win32_map_accept_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
- case WSAEOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break;
- case WSAEINVAL: prError = PR_INVALID_STATE_ERROR; break;
- default: nss_MD_win32_map_default_error(err); return;
+ case WSAEOPNOTSUPP:
+ prError = PR_NOT_TCP_SOCKET_ERROR;
+ break;
+ case WSAEINVAL:
+ prError = PR_INVALID_STATE_ERROR;
+ break;
+ default:
+ nss_MD_win32_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_win32_map_acceptex_error(PRInt32 err)
+void
+nss_MD_win32_map_acceptex_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_connect_error(PRInt32 err)
+void
+nss_MD_win32_map_connect_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
- case WSAEWOULDBLOCK: prError = PR_IN_PROGRESS_ERROR; break;
- case WSAEINVAL: prError = PR_ALREADY_INITIATED_ERROR; break;
- case WSAETIMEDOUT: prError = PR_IO_TIMEOUT_ERROR; break;
- default: nss_MD_win32_map_default_error(err); return;
+ case WSAEWOULDBLOCK:
+ prError = PR_IN_PROGRESS_ERROR;
+ break;
+ case WSAEINVAL:
+ prError = PR_ALREADY_INITIATED_ERROR;
+ break;
+ case WSAETIMEDOUT:
+ prError = PR_IO_TIMEOUT_ERROR;
+ break;
+ default:
+ nss_MD_win32_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_win32_map_bind_error(PRInt32 err)
+void
+nss_MD_win32_map_bind_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
- case WSAEINVAL: prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR; break;
- default: nss_MD_win32_map_default_error(err); return;
+ case WSAEINVAL:
+ prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR;
+ break;
+ default:
+ nss_MD_win32_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_win32_map_listen_error(PRInt32 err)
+void
+nss_MD_win32_map_listen_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
- case WSAEOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break;
- case WSAEINVAL: prError = PR_INVALID_STATE_ERROR; break;
- default: nss_MD_win32_map_default_error(err); return;
+ case WSAEOPNOTSUPP:
+ prError = PR_NOT_TCP_SOCKET_ERROR;
+ break;
+ case WSAEINVAL:
+ prError = PR_INVALID_STATE_ERROR;
+ break;
+ default:
+ nss_MD_win32_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_win32_map_shutdown_error(PRInt32 err)
+void
+nss_MD_win32_map_shutdown_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_getsockname_error(PRInt32 err)
+void
+nss_MD_win32_map_getsockname_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
- case WSAEINVAL: prError = PR_INVALID_STATE_ERROR; break;
- default: nss_MD_win32_map_default_error(err); return;
+ case WSAEINVAL:
+ prError = PR_INVALID_STATE_ERROR;
+ break;
+ default:
+ nss_MD_win32_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_win32_map_getpeername_error(PRInt32 err)
+void
+nss_MD_win32_map_getpeername_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_getsockopt_error(PRInt32 err)
+void
+nss_MD_win32_map_getsockopt_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_setsockopt_error(PRInt32 err)
+void
+nss_MD_win32_map_setsockopt_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_open_error(PRInt32 err)
+void
+nss_MD_win32_map_open_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-void nss_MD_win32_map_gethostname_error(PRInt32 err)
+void
+nss_MD_win32_map_gethostname_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
/* Win32 select() only works on sockets. So in this
-** context, WSAENOTSOCK is equivalent to EBADF on Unix.
+** context, WSAENOTSOCK is equivalent to EBADF on Unix.
*/
-void nss_MD_win32_map_select_error(PRInt32 err)
+void
+nss_MD_win32_map_select_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
- case WSAENOTSOCK: prError = PR_BAD_DESCRIPTOR_ERROR; break;
- default: nss_MD_win32_map_default_error(err); return;
+ case WSAENOTSOCK:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ default:
+ nss_MD_win32_map_default_error(err);
+ return;
}
PR_SetError(prError, err);
}
-void nss_MD_win32_map_lockf_error(PRInt32 err)
+void
+nss_MD_win32_map_lockf_error(PRInt32 err)
{
nss_MD_win32_map_default_error(err);
}
-
-
-void nss_MD_win32_map_default_error(PRInt32 err)
+void
+nss_MD_win32_map_default_error(PRInt32 err)
{
PRErrorCode prError;
switch (err) {
- case EACCES: prError = PR_NO_ACCESS_RIGHTS_ERROR; break;
- case ENOENT: prError = PR_FILE_NOT_FOUND_ERROR; break;
- case ERROR_ACCESS_DENIED: prError = PR_NO_ACCESS_RIGHTS_ERROR; break;
- case ERROR_ALREADY_EXISTS: prError = PR_FILE_EXISTS_ERROR; break;
- case ERROR_DISK_CORRUPT: prError = PR_IO_ERROR; break;
- case ERROR_DISK_FULL: prError = PR_NO_DEVICE_SPACE_ERROR; break;
- case ERROR_DISK_OPERATION_FAILED: prError = PR_IO_ERROR; break;
- case ERROR_DRIVE_LOCKED: prError = PR_FILE_IS_LOCKED_ERROR; break;
- case ERROR_FILENAME_EXCED_RANGE: prError = PR_NAME_TOO_LONG_ERROR; break;
- case ERROR_FILE_CORRUPT: prError = PR_IO_ERROR; break;
- case ERROR_FILE_EXISTS: prError = PR_FILE_EXISTS_ERROR; break;
- case ERROR_FILE_INVALID: prError = PR_BAD_DESCRIPTOR_ERROR; break;
+ case EACCES:
+ prError = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case ENOENT:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case ERROR_ACCESS_DENIED:
+ prError = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case ERROR_ALREADY_EXISTS:
+ prError = PR_FILE_EXISTS_ERROR;
+ break;
+ case ERROR_DISK_CORRUPT:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_DISK_FULL:
+ prError = PR_NO_DEVICE_SPACE_ERROR;
+ break;
+ case ERROR_DISK_OPERATION_FAILED:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_DRIVE_LOCKED:
+ prError = PR_FILE_IS_LOCKED_ERROR;
+ break;
+ case ERROR_FILENAME_EXCED_RANGE:
+ prError = PR_NAME_TOO_LONG_ERROR;
+ break;
+ case ERROR_FILE_CORRUPT:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_FILE_EXISTS:
+ prError = PR_FILE_EXISTS_ERROR;
+ break;
+ case ERROR_FILE_INVALID:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
#if ERROR_FILE_NOT_FOUND != ENOENT
- case ERROR_FILE_NOT_FOUND: prError = PR_FILE_NOT_FOUND_ERROR; break;
+ case ERROR_FILE_NOT_FOUND:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
#endif
- case ERROR_HANDLE_DISK_FULL: prError = PR_NO_DEVICE_SPACE_ERROR; break;
- case ERROR_INVALID_ADDRESS: prError = PR_ACCESS_FAULT_ERROR; break;
- case ERROR_INVALID_HANDLE: prError = PR_BAD_DESCRIPTOR_ERROR; break;
- case ERROR_INVALID_NAME: prError = PR_INVALID_ARGUMENT_ERROR; break;
- case ERROR_INVALID_PARAMETER: prError = PR_INVALID_ARGUMENT_ERROR; break;
- case ERROR_INVALID_USER_BUFFER: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- case ERROR_LOCKED: prError = PR_FILE_IS_LOCKED_ERROR; break;
- case ERROR_NETNAME_DELETED: prError = PR_CONNECT_RESET_ERROR; break;
- case ERROR_NOACCESS: prError = PR_ACCESS_FAULT_ERROR; break;
- case ERROR_NOT_ENOUGH_MEMORY: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- case ERROR_NOT_ENOUGH_QUOTA: prError = PR_OUT_OF_MEMORY_ERROR; break;
- case ERROR_NOT_READY: prError = PR_IO_ERROR; break;
- case ERROR_NO_MORE_FILES: prError = PR_NO_MORE_FILES_ERROR; break;
- case ERROR_OPEN_FAILED: prError = PR_IO_ERROR; break;
- case ERROR_OPEN_FILES: prError = PR_IO_ERROR; break;
- case ERROR_OUTOFMEMORY: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- case ERROR_PATH_BUSY: prError = PR_IO_ERROR; break;
- case ERROR_PATH_NOT_FOUND: prError = PR_FILE_NOT_FOUND_ERROR; break;
- case ERROR_SEEK_ON_DEVICE: prError = PR_IO_ERROR; break;
- case ERROR_SHARING_VIOLATION: prError = PR_FILE_IS_BUSY_ERROR; break;
- case ERROR_STACK_OVERFLOW: prError = PR_ACCESS_FAULT_ERROR; break;
- case ERROR_TOO_MANY_OPEN_FILES: prError = PR_SYS_DESC_TABLE_FULL_ERROR; break;
- case ERROR_WRITE_PROTECT: prError = PR_NO_ACCESS_RIGHTS_ERROR; break;
- case WSAEACCES: prError = PR_NO_ACCESS_RIGHTS_ERROR; break;
- case WSAEADDRINUSE: prError = PR_ADDRESS_IN_USE_ERROR; break;
- case WSAEADDRNOTAVAIL: prError = PR_ADDRESS_NOT_AVAILABLE_ERROR; break;
- case WSAEAFNOSUPPORT: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break;
- case WSAEALREADY: prError = PR_ALREADY_INITIATED_ERROR; break;
- case WSAEBADF: prError = PR_BAD_DESCRIPTOR_ERROR; break;
- case WSAECONNABORTED: prError = PR_CONNECT_ABORTED_ERROR; break;
- case WSAECONNREFUSED: prError = PR_CONNECT_REFUSED_ERROR; break;
- case WSAECONNRESET: prError = PR_CONNECT_RESET_ERROR; break;
- case WSAEDESTADDRREQ: prError = PR_INVALID_ARGUMENT_ERROR; break;
- case WSAEFAULT: prError = PR_ACCESS_FAULT_ERROR; break;
- case WSAEHOSTUNREACH: prError = PR_HOST_UNREACHABLE_ERROR; break;
- case WSAEINVAL: prError = PR_INVALID_ARGUMENT_ERROR; break;
- case WSAEISCONN: prError = PR_IS_CONNECTED_ERROR; break;
- case WSAEMFILE: prError = PR_PROC_DESC_TABLE_FULL_ERROR; break;
- case WSAEMSGSIZE: prError = PR_BUFFER_OVERFLOW_ERROR; break;
- case WSAENETDOWN: prError = PR_NETWORK_DOWN_ERROR; break;
- case WSAENETRESET: prError = PR_CONNECT_ABORTED_ERROR; break;
- case WSAENETUNREACH: prError = PR_NETWORK_UNREACHABLE_ERROR; break;
- case WSAENOBUFS: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break;
- case WSAENOPROTOOPT: prError = PR_INVALID_ARGUMENT_ERROR; break;
- case WSAENOTCONN: prError = PR_NOT_CONNECTED_ERROR; break;
- case WSAENOTSOCK: prError = PR_NOT_SOCKET_ERROR; break;
- case WSAEOPNOTSUPP: prError = PR_OPERATION_NOT_SUPPORTED_ERROR; break;
- case WSAEPROTONOSUPPORT: prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR; break;
- case WSAEPROTOTYPE: prError = PR_INVALID_ARGUMENT_ERROR; break;
- case WSAESHUTDOWN: prError = PR_SOCKET_SHUTDOWN_ERROR; break;
- case WSAESOCKTNOSUPPORT: prError = PR_INVALID_ARGUMENT_ERROR; break;
- case WSAETIMEDOUT: prError = PR_CONNECT_ABORTED_ERROR; break;
- case WSAEWOULDBLOCK: prError = PR_WOULD_BLOCK_ERROR; break;
- default: prError = PR_UNKNOWN_ERROR; break;
+ case ERROR_HANDLE_DISK_FULL:
+ prError = PR_NO_DEVICE_SPACE_ERROR;
+ break;
+ case ERROR_INVALID_ADDRESS:
+ prError = PR_ACCESS_FAULT_ERROR;
+ break;
+ case ERROR_INVALID_HANDLE:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ case ERROR_INVALID_NAME:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case ERROR_INVALID_PARAMETER:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case ERROR_INVALID_USER_BUFFER:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case ERROR_LOCKED:
+ prError = PR_FILE_IS_LOCKED_ERROR;
+ break;
+ case ERROR_NETNAME_DELETED:
+ prError = PR_CONNECT_RESET_ERROR;
+ break;
+ case ERROR_NOACCESS:
+ prError = PR_ACCESS_FAULT_ERROR;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case ERROR_NOT_ENOUGH_QUOTA:
+ prError = PR_OUT_OF_MEMORY_ERROR;
+ break;
+ case ERROR_NOT_READY:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_NO_MORE_FILES:
+ prError = PR_NO_MORE_FILES_ERROR;
+ break;
+ case ERROR_OPEN_FAILED:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_OPEN_FILES:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_OUTOFMEMORY:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case ERROR_PATH_BUSY:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_PATH_NOT_FOUND:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case ERROR_SEEK_ON_DEVICE:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_SHARING_VIOLATION:
+ prError = PR_FILE_IS_BUSY_ERROR;
+ break;
+ case ERROR_STACK_OVERFLOW:
+ prError = PR_ACCESS_FAULT_ERROR;
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ prError = PR_SYS_DESC_TABLE_FULL_ERROR;
+ break;
+ case ERROR_WRITE_PROTECT:
+ prError = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case WSAEACCES:
+ prError = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case WSAEADDRINUSE:
+ prError = PR_ADDRESS_IN_USE_ERROR;
+ break;
+ case WSAEADDRNOTAVAIL:
+ prError = PR_ADDRESS_NOT_AVAILABLE_ERROR;
+ break;
+ case WSAEAFNOSUPPORT:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case WSAEALREADY:
+ prError = PR_ALREADY_INITIATED_ERROR;
+ break;
+ case WSAEBADF:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ case WSAECONNABORTED:
+ prError = PR_CONNECT_ABORTED_ERROR;
+ break;
+ case WSAECONNREFUSED:
+ prError = PR_CONNECT_REFUSED_ERROR;
+ break;
+ case WSAECONNRESET:
+ prError = PR_CONNECT_RESET_ERROR;
+ break;
+ case WSAEDESTADDRREQ:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case WSAEFAULT:
+ prError = PR_ACCESS_FAULT_ERROR;
+ break;
+ case WSAEHOSTUNREACH:
+ prError = PR_HOST_UNREACHABLE_ERROR;
+ break;
+ case WSAEINVAL:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case WSAEISCONN:
+ prError = PR_IS_CONNECTED_ERROR;
+ break;
+ case WSAEMFILE:
+ prError = PR_PROC_DESC_TABLE_FULL_ERROR;
+ break;
+ case WSAEMSGSIZE:
+ prError = PR_BUFFER_OVERFLOW_ERROR;
+ break;
+ case WSAENETDOWN:
+ prError = PR_NETWORK_DOWN_ERROR;
+ break;
+ case WSAENETRESET:
+ prError = PR_CONNECT_ABORTED_ERROR;
+ break;
+ case WSAENETUNREACH:
+ prError = PR_NETWORK_UNREACHABLE_ERROR;
+ break;
+ case WSAENOBUFS:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case WSAENOPROTOOPT:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case WSAENOTCONN:
+ prError = PR_NOT_CONNECTED_ERROR;
+ break;
+ case WSAENOTSOCK:
+ prError = PR_NOT_SOCKET_ERROR;
+ break;
+ case WSAEOPNOTSUPP:
+ prError = PR_OPERATION_NOT_SUPPORTED_ERROR;
+ break;
+ case WSAEPROTONOSUPPORT:
+ prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR;
+ break;
+ case WSAEPROTOTYPE:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case WSAESHUTDOWN:
+ prError = PR_SOCKET_SHUTDOWN_ERROR;
+ break;
+ case WSAESOCKTNOSUPPORT:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case WSAETIMEDOUT:
+ prError = PR_CONNECT_ABORTED_ERROR;
+ break;
+ case WSAEWOULDBLOCK:
+ prError = PR_WOULD_BLOCK_ERROR;
+ break;
+ default:
+ prError = PR_UNKNOWN_ERROR;
+ break;
}
PR_SetError(prError, err);
}
-
diff --git a/chromium/net/third_party/nss/ssl/win32err.h b/chromium/net/third_party/nss/ssl/win32err.h
index 8ce588ec5a1..a698849061c 100644
--- a/chromium/net/third_party/nss/ssl/win32err.h
+++ b/chromium/net/third_party/nss/ssl/win32err.h
@@ -1,11 +1,11 @@
/*
* This file essentially replicates NSPR's source for the functions that
- * map system-specific error codes to NSPR error codes. We would use
+ * map system-specific error codes to NSPR error codes. We would use
* NSPR's functions, instead of duplicating them, but they're private.
* As long as SSL's server session cache code must do platform native I/O
* to accomplish its job, and NSPR's error mapping functions remain private,
* This code will continue to need to be replicated.
- *
+ *
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
diff --git a/chromium/net/tools/balsa/balsa_frame.cc b/chromium/net/tools/balsa/balsa_frame.cc
index 8505ac16a0c..33777fa8d28 100644
--- a/chromium/net/tools/balsa/balsa_frame.cc
+++ b/chromium/net/tools/balsa/balsa_frame.cc
@@ -28,7 +28,6 @@
#include "net/tools/balsa/balsa_visitor_interface.h"
#include "net/tools/balsa/buffer_interface.h"
#include "net/tools/balsa/simple_buffer.h"
-#include "net/tools/balsa/split.h"
#include "net/tools/balsa/string_piece_utils.h"
#if defined(COMPILER_MSVC)
@@ -751,9 +750,9 @@ void ProcessChunkExtensionsManual(base::StringPiece all_extensions,
SplitStringPiece(extension, '=', &key, &value);
if (!value.empty()) {
// Strip quotation marks if they exist.
- if (!value.empty() && value[0] == '"')
+ if (!value.empty() && value.front() == '"')
value.remove_prefix(1);
- if (!value.empty() && value[value.length() - 1] == '"')
+ if (!value.empty() && value.back() == '"')
value.remove_suffix(1);
}
diff --git a/chromium/net/tools/balsa/split.cc b/chromium/net/tools/balsa/split.cc
deleted file mode 100644
index 20be430d731..00000000000
--- a/chromium/net/tools/balsa/split.cc
+++ /dev/null
@@ -1,72 +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/balsa/split.h"
-
-#include <string.h>
-
-#include <vector>
-
-#include "base/strings/string_piece.h"
-
-namespace net {
-
-// Yea, this could be done with less code duplication using
-// template magic, I know.
-void SplitStringPieceToVector(const base::StringPiece& full,
- const char* delim,
- std::vector<base::StringPiece>* vec,
- bool omit_empty_strings) {
- vec->clear();
- if (full.empty() || delim[0] == '\0')
- return;
-
- if (delim[1] == '\0') {
- base::StringPiece::const_iterator s = full.begin();
- base::StringPiece::const_iterator e = s;
- for (;e != full.end(); ++e) {
- if (*e == delim[0]) {
- if (e != s || !omit_empty_strings) {
- vec->push_back(base::StringPiece(s, e - s));
- }
- s = e;
- ++s;
- }
- }
- if (s != e) {
- --e;
- if (e != s || !omit_empty_strings) {
- vec->push_back(base::StringPiece(s, e - s));
- }
- }
- } else {
- base::StringPiece::const_iterator s = full.begin();
- base::StringPiece::const_iterator e = s;
- for (;e != full.end(); ++e) {
- bool one_matched = false;
- for (const char *d = delim; *d != '\0'; ++d) {
- if (*d == *e) {
- one_matched = true;
- break;
- }
- }
- if (one_matched) {
- if (e != s || !omit_empty_strings) {
- vec->push_back(base::StringPiece(s, e - s));
- }
- s = e;
- ++s;
- }
- }
- if (s != e) {
- --e;
- if (e != s || !omit_empty_strings) {
- vec->push_back(base::StringPiece(s, e - s));
- }
- }
- }
-}
-
-} // namespace net
-
diff --git a/chromium/net/tools/balsa/split.h b/chromium/net/tools/balsa/split.h
deleted file mode 100644
index 6901c2d5651..00000000000
--- a/chromium/net/tools/balsa/split.h
+++ /dev/null
@@ -1,23 +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_BALSA_SPLIT_H_
-#define NET_TOOLS_BALSA_SPLIT_H_
-
-#include <vector>
-#include "base/strings/string_piece.h"
-
-namespace net {
-
-// Yea, this could be done with less code duplication using
-// template magic, I know.
-void SplitStringPieceToVector(const base::StringPiece& full,
- const char* delim,
- std::vector<base::StringPiece>* vec,
- bool omit_empty_strings);
-
-} // namespace net
-
-#endif // NET_TOOLS_BALSA_SPLIT_H_
-
diff --git a/chromium/net/tools/cachetool/cachetool.cc b/chromium/net/tools/cachetool/cachetool.cc
new file mode 100644
index 00000000000..c186400d9da
--- /dev/null
+++ b/chromium/net/tools/cachetool/cachetool.cc
@@ -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.
+
+#include <iostream>
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "net/base/io_buffer.h"
+#include "net/base/test_completion_callback.h"
+#include "net/disk_cache/disk_cache.h"
+#include "net/http/http_cache.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+
+using disk_cache::Backend;
+using disk_cache::Entry;
+
+namespace {
+
+// Print all of a cache's keys to stdout.
+bool ListKeys(Backend* cache_backend) {
+ scoped_ptr<Backend::Iterator> entry_iterator =
+ cache_backend->CreateIterator();
+ Entry* entry = nullptr;
+ net::TestCompletionCallback cb;
+ int rv = entry_iterator->OpenNextEntry(&entry, cb.callback());
+ while (cb.GetResult(rv) == net::OK) {
+ std::string url = entry->GetKey();
+ std::cout << url << std::endl;
+ entry->Close();
+ entry = nullptr;
+ rv = entry_iterator->OpenNextEntry(&entry, cb.callback());
+ }
+ return true;
+}
+
+// Print a key's stream to stdout.
+bool GetKeyStream(Backend* cache_backend, const std::string& key, int index) {
+ if (index < 0 || index > 2) {
+ std::cerr << "Invalid stream index." << std::endl;
+ return false;
+ }
+
+ Entry* cache_entry;
+ net::TestCompletionCallback cb;
+ int rv = cache_backend->OpenEntry(key, &cache_entry, cb.callback());
+ if (cb.GetResult(rv) != net::OK) {
+ std::cerr << "Couldn't find key's entry." << std::endl;
+ return false;
+ }
+
+ const int kInitBufferSize = 8192;
+ scoped_refptr<net::GrowableIOBuffer> buffer(new net::GrowableIOBuffer());
+ buffer->SetCapacity(kInitBufferSize);
+ while (true) {
+ rv = cache_entry->ReadData(index, buffer->offset(), buffer.get(),
+ buffer->capacity() - buffer->offset(),
+ cb.callback());
+ rv = cb.GetResult(rv);
+ if (rv < 0) {
+ cache_entry->Close();
+ std::cerr << "Stream read error." << std::endl;
+ return false;
+ }
+ buffer->set_offset(buffer->offset() + rv);
+ if (rv == 0)
+ break;
+ buffer->SetCapacity(buffer->offset() * 2);
+ }
+ cache_entry->Close();
+ if (index == 0) {
+ net::HttpResponseInfo response_info;
+ bool truncated_response_info = false;
+ net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(),
+ &response_info, &truncated_response_info);
+ if (truncated_response_info) {
+ std::cerr << "Truncated HTTP response." << std::endl;
+ return false;
+ }
+ std::cout << net::HttpUtil::ConvertHeadersBackToHTTPResponse(
+ response_info.headers->raw_headers());
+ } else {
+ std::cout.write(buffer->StartOfBuffer(), buffer->offset());
+ }
+ return true;
+}
+
+// Delete a specified key from the cache.
+bool DeleteKey(Backend* cache_backend, const std::string& key) {
+ net::TestCompletionCallback cb;
+ int rv = cache_backend->DoomEntry(key, cb.callback());
+ if (cb.GetResult(rv) != net::OK) {
+ std::cerr << "Couldn't delete key." << std::endl;
+ return false;
+ }
+ return true;
+}
+
+// Print the command line help.
+void PrintHelp() {
+ std::cout << "cachetool <cache_path> <cache_backend_type> <subcommand> ..."
+ << std::endl
+ << std::endl;
+ std::cout << "Available cache backend types: simple, blockfile" << std::endl;
+ std::cout << "Available subcommands:" << std::endl;
+ std::cout << " validate: Verify that the cache can be opened and return, "
+ << "confirming the cache exists and is of the right type."
+ << std::endl;
+ std::cout << " list_keys: List all keys in the cache." << std::endl;
+ std::cout << " get_stream <key> <index>: Print a particular stream for a"
+ << " given key." << std::endl;
+ std::cout << " delete_key <key>: Delete key from cache." << std::endl;
+ std::cout << "Expected values of <index> are:" << std::endl;
+ std::cout << " 0 (HTTP response headers)" << std::endl;
+ std::cout << " 1 (transport encoded content)" << std::endl;
+ std::cout << " 2 (compiled content)" << std::endl;
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ base::AtExitManager at_exit_manager;
+ base::MessageLoopForIO message_loop;
+ base::CommandLine::Init(argc, argv);
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+
+ base::CommandLine::StringVector args = command_line.GetArgs();
+ if (args.size() < 3U) {
+ PrintHelp();
+ return 1;
+ }
+
+ base::FilePath cache_path(args[0]);
+ std::string cache_backend_type(args[1]);
+ std::string subcommand(args[2]);
+
+ net::BackendType backend_type;
+ if (cache_backend_type == "simple") {
+ backend_type = net::CACHE_BACKEND_SIMPLE;
+ } else if (cache_backend_type == "blockfile") {
+ backend_type = net::CACHE_BACKEND_BLOCKFILE;
+ } else {
+ std::cerr << "Unknown cache type." << std::endl;
+ PrintHelp();
+ return 1;
+ }
+
+ scoped_ptr<Backend> cache_backend;
+ net::TestCompletionCallback cb;
+ int rv = disk_cache::CreateCacheBackend(
+ net::DISK_CACHE, backend_type, cache_path, INT_MAX, false,
+ message_loop.task_runner(), nullptr, &cache_backend, cb.callback());
+ if (cb.GetResult(rv) != net::OK) {
+ std::cerr << "Invalid cache." << std::endl;
+ return 1;
+ }
+
+ bool successful_command = false;
+ if (subcommand == "validate") {
+ if (args.size() != 3) {
+ PrintHelp();
+ return 1;
+ }
+ successful_command = true;
+ } else if (subcommand == "list_keys") {
+ if (args.size() != 3) {
+ PrintHelp();
+ return 1;
+ }
+ successful_command = ListKeys(cache_backend.get());
+ } else if (subcommand == "get_stream") {
+ if (args.size() != 5) {
+ PrintHelp();
+ return 1;
+ }
+ std::string key(args[3]);
+ int index = 0;
+ if (!base::StringToInt(args[4], &index)) {
+ std::cerr << "<index> must be an integer." << std::endl;
+ PrintHelp();
+ return 1;
+ }
+ successful_command = GetKeyStream(cache_backend.get(), key, index);
+ } else if (subcommand == "delete_key") {
+ if (args.size() != 4) {
+ PrintHelp();
+ return 1;
+ }
+ std::string key(args[3]);
+ successful_command = DeleteKey(cache_backend.get(), key);
+ } else {
+ std::cerr << "Unknown subcommand." << std::endl;
+ PrintHelp();
+ }
+ return !successful_command;
+}
diff --git a/chromium/net/tools/content_decoder_tool/content_decoder_tool.cc b/chromium/net/tools/content_decoder_tool/content_decoder_tool.cc
new file mode 100644
index 00000000000..0eae255394a
--- /dev/null
+++ b/chromium/net/tools/content_decoder_tool/content_decoder_tool.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 <iostream>
+
+#include "base/command_line.h"
+#include "net/base/io_buffer.h"
+#include "net/filter/filter.h"
+#include "net/filter/mock_filter_context.h"
+
+using net::Filter;
+
+namespace {
+
+// Print the command line help.
+void PrintHelp(const char* command_line_name) {
+ std::cout << command_line_name << " content_encoding [content_encoding]..."
+ << std::endl
+ << std::endl;
+ std::cout << "Decodes the stdin into the stdout using an content_encoding "
+ << "list given in arguments. This list is expected to be the "
+ << "Content-Encoding HTTP response header's value split by ','."
+ << std::endl;
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ base::CommandLine::Init(argc, argv);
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+
+ std::vector<std::string> content_encodings = command_line.GetArgs();
+ if (content_encodings.size() == 0) {
+ PrintHelp(argv[0]);
+ return 1;
+ }
+
+ std::vector<Filter::FilterType> filter_types;
+ for (const auto& content_encoding : content_encodings) {
+ Filter::FilterType filter_type =
+ Filter::ConvertEncodingToType(content_encoding);
+ if (filter_type == Filter::FILTER_TYPE_UNSUPPORTED) {
+ std::cerr << "Unsupported decoder '" << content_encoding << "'."
+ << std::endl;
+ return 1;
+ }
+ filter_types.push_back(filter_type);
+ }
+
+ net::MockFilterContext filter_context;
+ scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
+ if (!filter) {
+ std::cerr << "Couldn't create the decoder." << std::endl;
+ return 1;
+ }
+
+ net::IOBuffer* pre_filter_buf = filter->stream_buffer();
+ int pre_filter_buf_len = filter->stream_buffer_size();
+ while (std::cin) {
+ std::cin.read(pre_filter_buf->data(), pre_filter_buf_len);
+ int pre_filter_data_len = std::cin.gcount();
+ filter->FlushStreamBuffer(pre_filter_data_len);
+
+ while (true) {
+ const int kPostFilterBufLen = 4096;
+ char post_filter_buf[kPostFilterBufLen];
+ int post_filter_data_len = kPostFilterBufLen;
+ Filter::FilterStatus filter_status =
+ filter->ReadData(post_filter_buf, &post_filter_data_len);
+ std::cout.write(post_filter_buf, post_filter_data_len);
+ if (filter_status == Filter::FILTER_ERROR) {
+ std::cerr << "Couldn't decode stdin." << std::endl;
+ return 1;
+ } else if (filter_status != Filter::FILTER_OK) {
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/chromium/net/tools/dafsa/make_dafsa.py b/chromium/net/tools/dafsa/make_dafsa.py
index 78358effa84..5c9082d372c 100755
--- a/chromium/net/tools/dafsa/make_dafsa.py
+++ b/chromium/net/tools/dafsa/make_dafsa.py
@@ -448,10 +448,10 @@ def parse_gperf(infile):
for line in lines:
if line[-3:-1] != ', ':
raise InputError('Expected "domainname, <digit>", found "%s"' % line)
- # Technically the DAFSA format could support return values in range [0-31],
- # but the values below are the only with a defined meaning.
- if line[-1] not in '0124':
- raise InputError('Expected value to be one of {0,1,2,4}, found "%s"' %
+ # Technically the DAFSA format can support return values in the range
+ # [0-31], but only the first three bits have any defined meaning.
+ if not line.endswith(('0', '1', '2', '3', '4', '5', '6', '7')):
+ raise InputError('Expected value to be in the range of 0-7, found "%s"' %
line[-1])
return [line[:-3] + line[-1] for line in lines]
diff --git a/chromium/net/tools/dafsa/make_dafsa_unittest.py b/chromium/net/tools/dafsa/make_dafsa_unittest.py
index 5ff92e62292..65a82445122 100755
--- a/chromium/net/tools/dafsa/make_dafsa_unittest.py
+++ b/chromium/net/tools/dafsa/make_dafsa_unittest.py
@@ -29,13 +29,7 @@ class ParseGperfTest(unittest.TestCase):
infile2 = [ '%%', 'a, x', '%%' ]
self.assertRaises(make_dafsa.InputError, make_dafsa.parse_gperf, infile2)
- infile3 = [ '%%', 'a, 3', '%%' ]
- self.assertRaises(make_dafsa.InputError, make_dafsa.parse_gperf, infile3)
-
- infile4 = [ '%%', 'a, 6', '%%' ]
- self.assertRaises(make_dafsa.InputError, make_dafsa.parse_gperf, infile4)
-
- infile5 = [ '%%', 'a, 12', '%%' ]
+ infile5 = [ '%%', 'a, 12', '%%' ]
self.assertRaises(make_dafsa.InputError, make_dafsa.parse_gperf, infile5)
def testValues(self):
@@ -52,10 +46,18 @@ class ParseGperfTest(unittest.TestCase):
words3 = [ 'a2' ]
self.assertEqual(make_dafsa.parse_gperf(infile3), words3)
- infile4 = [ '%%', 'a, 4', '%%' ]
- words4 = [ 'a4' ]
+ infile4 = [ '%%', 'a, 3', '%%' ]
+ words4 = [ 'a3' ]
self.assertEqual(make_dafsa.parse_gperf(infile4), words4)
+ infile5 = [ '%%', 'a, 4', '%%' ]
+ words5 = [ 'a4' ]
+ self.assertEqual(make_dafsa.parse_gperf(infile5), words5)
+
+ infile6 = [ '%%', 'a, 6', '%%' ]
+ words6 = [ 'a6' ]
+ self.assertEqual(make_dafsa.parse_gperf(infile6), words6)
+
def testOneWord(self):
"""Tests a single key can be parsed."""
infile = [ '%%', 'apa, 1', '%%' ]
diff --git a/chromium/net/tools/flip_server/acceptor_thread.cc b/chromium/net/tools/flip_server/acceptor_thread.cc
index 4e7866344c2..22b94f3e53e 100644
--- a/chromium/net/tools/flip_server/acceptor_thread.cc
+++ b/chromium/net/tools/flip_server/acceptor_thread.cc
@@ -6,13 +6,13 @@
#include <errno.h>
#include <netinet/in.h>
-#include <netinet/tcp.h> // For TCP_NODELAY
#include <string.h> // For strerror
#include <sys/socket.h>
#include <sys/types.h>
#include <string>
+#include "net/socket/tcp_socket.h"
#include "net/tools/flip_server/constants.h"
#include "net/tools/flip_server/flip_config.h"
#include "net/tools/flip_server/sm_connection.h"
@@ -82,17 +82,10 @@ void SMAcceptorThread::InitWorker() {
void SMAcceptorThread::HandleConnection(int server_fd,
struct sockaddr_in* remote_addr) {
- int on = 1;
- int rc;
if (acceptor_->disable_nagle_) {
- rc = setsockopt(server_fd,
- IPPROTO_TCP,
- TCP_NODELAY,
- reinterpret_cast<char*>(&on),
- sizeof(on));
- if (rc < 0) {
+ if (!SetTCPNoDelay(server_fd, /*no_delay=*/true)) {
close(server_fd);
- LOG(ERROR) << "setsockopt() failed fd=" << server_fd;
+ LOG(FATAL) << "SetTCPNoDelay() failed on fd: " << server_fd;
return;
}
}
diff --git a/chromium/net/tools/flip_server/flip_config.cc b/chromium/net/tools/flip_server/flip_config.cc
index d0647ae06c5..afc858ce165 100644
--- a/chromium/net/tools/flip_server/flip_config.cc
+++ b/chromium/net/tools/flip_server/flip_config.cc
@@ -6,7 +6,8 @@
#include <unistd.h>
-#include "net/tools/flip_server/create_listener.h"
+#include "base/files/file_util.h"
+#include "net/tools/flip_server/tcp_socket_util.h"
namespace net {
@@ -51,7 +52,7 @@ FlipAcceptor::FlipAcceptor(enum FlipHandlerType flip_handler_type,
https_server_port_ = http_server_port_;
while (1) {
- int ret = CreateListeningSocket(listen_ip_,
+ int ret = CreateTCPServerSocket(listen_ip_,
listen_port_,
true,
accept_backlog_size_,
@@ -73,7 +74,10 @@ FlipAcceptor::FlipAcceptor(enum FlipHandlerType flip_handler_type,
}
}
- FlipSetNonBlocking(listen_fd_);
+ if (!base::SetNonBlocking(listen_fd_)) {
+ LOG(FATAL) << "base::SetNonBlocking() failed: " << listen_fd_;
+ }
+
VLOG(1) << "Listening on socket: ";
if (flip_handler_type == FLIP_HANDLER_PROXY)
VLOG(1) << "\tType : Proxy";
diff --git a/chromium/net/tools/flip_server/flip_in_mem_edsm_server.cc b/chromium/net/tools/flip_server/flip_in_mem_edsm_server.cc
index 8473560534d..d14af00d1a1 100644
--- a/chromium/net/tools/flip_server/flip_in_mem_edsm_server.cc
+++ b/chromium/net/tools/flip_server/flip_in_mem_edsm_server.cc
@@ -16,7 +16,6 @@
#include "base/logging.h"
#include "base/strings/string_split.h"
#include "base/synchronization/lock.h"
-#include "net/tools/balsa/split.h"
#include "net/tools/flip_server/acceptor_thread.h"
#include "net/tools/flip_server/constants.h"
#include "net/tools/flip_server/flip_config.h"
@@ -53,7 +52,7 @@ double FLAGS_server_think_time_in_s = 0;
net::FlipConfig g_proxy_config;
-bool GotQuitFromStdin() {
+static bool GotQuitFromStdin() {
// Make stdin nonblocking. Yes this is done each time. Oh well.
fcntl(0, F_SETFL, O_NONBLOCK);
char c;
@@ -68,22 +67,16 @@ bool GotQuitFromStdin() {
(maybequit.c_str()[0] == 'q' || maybequit.c_str()[0] == 'Q'));
}
-const char* BoolToStr(bool b) {
- if (b)
- return "true";
- return "false";
-}
-
-static bool wantExit = false;
-static bool wantLogClose = false;
-void SignalHandler(int signum) {
+static bool g_want_exit = false;
+static bool g_want_log_close = false;
+static void SignalHandler(int signum) {
switch (signum) {
case SIGTERM:
case SIGINT:
- wantExit = true;
+ g_want_exit = true;
break;
case SIGHUP:
- wantLogClose = true;
+ g_want_log_close = true;
break;
}
}
@@ -287,21 +280,21 @@ int main(int argc, char** argv) {
break;
}
std::string value = cl.GetSwitchValueASCII(name.str());
- std::vector<std::string> valueArgs = base::SplitString(
+ std::vector<std::string> value_args = base::SplitString(
value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- CHECK_EQ((unsigned int)9, valueArgs.size());
- int spdy_only = atoi(valueArgs[8].c_str());
+ CHECK_EQ((unsigned int)9, value_args.size());
+ int spdy_only = atoi(value_args[8].c_str());
// If wait_for_iface is enabled, then this call will block
// indefinitely until the interface is raised.
g_proxy_config.AddAcceptor(net::FLIP_HANDLER_PROXY,
- valueArgs[0],
- valueArgs[1],
- valueArgs[2],
- valueArgs[3],
- valueArgs[4],
- valueArgs[5],
- valueArgs[6],
- valueArgs[7],
+ value_args[0],
+ value_args[1],
+ value_args[2],
+ value_args[3],
+ value_args[4],
+ value_args[5],
+ value_args[6],
+ value_args[7],
spdy_only,
FLAGS_accept_backlog_size,
FLAGS_disable_nagle,
@@ -316,15 +309,15 @@ int main(int argc, char** argv) {
if (cl.HasSwitch("spdy-server")) {
spdy_memory_cache.AddFiles();
std::string value = cl.GetSwitchValueASCII("spdy-server");
- std::vector<std::string> valueArgs = base::SplitString(
+ std::vector<std::string> value_args = base::SplitString(
value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- while (valueArgs.size() < 4)
- valueArgs.push_back(std::string());
+ while (value_args.size() < 4)
+ value_args.push_back(std::string());
g_proxy_config.AddAcceptor(net::FLIP_HANDLER_SPDY_SERVER,
- valueArgs[0],
- valueArgs[1],
- valueArgs[2],
- valueArgs[3],
+ value_args[0],
+ value_args[1],
+ value_args[2],
+ value_args[3],
std::string(),
std::string(),
std::string(),
@@ -343,15 +336,15 @@ int main(int argc, char** argv) {
if (cl.HasSwitch("http-server")) {
http_memory_cache.AddFiles();
std::string value = cl.GetSwitchValueASCII("http-server");
- std::vector<std::string> valueArgs = base::SplitString(
+ std::vector<std::string> value_args = base::SplitString(
value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- while (valueArgs.size() < 4)
- valueArgs.push_back(std::string());
+ while (value_args.size() < 4)
+ value_args.push_back(std::string());
g_proxy_config.AddAcceptor(net::FLIP_HANDLER_HTTP_SERVER,
- valueArgs[0],
- valueArgs[1],
- valueArgs[2],
- valueArgs[3],
+ value_args[0],
+ value_args[1],
+ value_args[2],
+ value_args[3],
std::string(),
std::string(),
std::string(),
@@ -365,12 +358,12 @@ int main(int argc, char** argv) {
&http_memory_cache);
}
- std::vector<net::SMAcceptorThread*> sm_worker_threads_;
+ std::vector<net::SMAcceptorThread*> sm_worker_threads;
for (i = 0; i < g_proxy_config.acceptors_.size(); i++) {
net::FlipAcceptor* acceptor = g_proxy_config.acceptors_[i];
- sm_worker_threads_.push_back(new net::SMAcceptorThread(
+ sm_worker_threads.push_back(new net::SMAcceptorThread(
acceptor, (net::MemoryCache*)acceptor->memory_cache_));
// Note that spdy_memory_cache is not threadsafe, it is merely
// thread compatible. Thus, if ever we are to spawn multiple threads,
@@ -380,24 +373,24 @@ int main(int argc, char** argv) {
// The latter is what is currently being done as we spawn
// a separate thread for each http and spdy server acceptor.
- sm_worker_threads_.back()->InitWorker();
- sm_worker_threads_.back()->Start();
+ sm_worker_threads.back()->InitWorker();
+ sm_worker_threads.back()->Start();
}
- while (!wantExit) {
+ while (!g_want_exit) {
// Close logfile when HUP signal is received. Logging system will
// automatically reopen on next log message.
- if (wantLogClose) {
- wantLogClose = false;
+ if (g_want_log_close) {
+ g_want_log_close = false;
VLOG(1) << "HUP received, reopening log file.";
logging::CloseLogFile();
}
if (GotQuitFromStdin()) {
- for (unsigned int i = 0; i < sm_worker_threads_.size(); ++i) {
- sm_worker_threads_[i]->Quit();
+ for (unsigned int i = 0; i < sm_worker_threads.size(); ++i) {
+ sm_worker_threads[i]->Quit();
}
- for (unsigned int i = 0; i < sm_worker_threads_.size(); ++i) {
- sm_worker_threads_[i]->Join();
+ for (unsigned int i = 0; i < sm_worker_threads.size(); ++i) {
+ sm_worker_threads[i]->Join();
}
break;
}
diff --git a/chromium/net/tools/flip_server/output_ordering.cc b/chromium/net/tools/flip_server/output_ordering.cc
index f378a8742cf..24e92c0c000 100644
--- a/chromium/net/tools/flip_server/output_ordering.cc
+++ b/chromium/net/tools/flip_server/output_ordering.cc
@@ -14,6 +14,9 @@ namespace net {
OutputOrdering::PriorityMapPointer::PriorityMapPointer()
: ring(NULL), alarm_enabled(false) {}
+OutputOrdering::PriorityMapPointer::PriorityMapPointer(
+ const PriorityMapPointer& other) = default;
+
OutputOrdering::PriorityMapPointer::~PriorityMapPointer() {}
// static
diff --git a/chromium/net/tools/flip_server/output_ordering.h b/chromium/net/tools/flip_server/output_ordering.h
index 364146037d5..ecd32a2ba47 100644
--- a/chromium/net/tools/flip_server/output_ordering.h
+++ b/chromium/net/tools/flip_server/output_ordering.h
@@ -27,6 +27,7 @@ class OutputOrdering {
struct PriorityMapPointer {
PriorityMapPointer();
+ PriorityMapPointer(const PriorityMapPointer& other);
~PriorityMapPointer();
PriorityRing* ring;
PriorityRing::iterator it;
diff --git a/chromium/net/tools/flip_server/sm_connection.cc b/chromium/net/tools/flip_server/sm_connection.cc
index ea874e26b47..9c232f97a74 100644
--- a/chromium/net/tools/flip_server/sm_connection.cc
+++ b/chromium/net/tools/flip_server/sm_connection.cc
@@ -14,12 +14,12 @@
#include <string>
#include "net/tools/flip_server/constants.h"
-#include "net/tools/flip_server/create_listener.h"
#include "net/tools/flip_server/flip_config.h"
#include "net/tools/flip_server/http_interface.h"
#include "net/tools/flip_server/spdy_interface.h"
#include "net/tools/flip_server/spdy_ssl.h"
#include "net/tools/flip_server/streamer_interface.h"
+#include "net/tools/flip_server/tcp_socket_util.h"
namespace net {
@@ -102,8 +102,8 @@ void SMConnection::InitSMConnection(SMConnectionPoolInterface* connection_pool,
// TODO(kelindsay): is_numeric_host_address value needs to be detected
server_ip_ = server_ip;
server_port_ = server_port;
- int ret = CreateConnectedSocket(
- &fd_, server_ip, server_port, true, acceptor_->disable_nagle_);
+ int ret = CreateTCPClientSocket(
+ server_ip, server_port, true, acceptor_->disable_nagle_, &fd_);
if (ret < 0) {
LOG(ERROR) << "-1 Could not create connected socket";
diff --git a/chromium/net/tools/flip_server/spdy_interface.cc b/chromium/net/tools/flip_server/spdy_interface.cc
index d08394041ad..5dbd7cb1ca8 100644
--- a/chromium/net/tools/flip_server/spdy_interface.cc
+++ b/chromium/net/tools/flip_server/spdy_interface.cc
@@ -22,14 +22,15 @@ std::string SpdySM::forward_ip_header_;
class SpdyFrameDataFrame : public DataFrame {
public:
- explicit SpdyFrameDataFrame(SpdyFrame* spdy_frame) : frame(spdy_frame) {
+ explicit SpdyFrameDataFrame(SpdySerializedFrame* spdy_frame)
+ : frame(spdy_frame) {
data = spdy_frame->data();
size = spdy_frame->size();
}
~SpdyFrameDataFrame() override { delete frame; }
- const SpdyFrame* frame;
+ const SpdySerializedFrame* frame;
};
SpdySM::SpdySM(SMConnection* connection,
@@ -38,7 +39,7 @@ SpdySM::SpdySM(SMConnection* connection,
MemoryCache* memory_cache,
FlipAcceptor* acceptor,
SpdyMajorVersion spdy_version)
- : buffered_spdy_framer_(new BufferedSpdyFramer(spdy_version, true)),
+ : buffered_spdy_framer_(new BufferedSpdyFramer(spdy_version)),
valid_spdy_session_(false),
connection_(connection),
client_output_list_(connection->output_list()),
@@ -344,7 +345,8 @@ int SpdySM::PostAcceptHook() {
SettingsMap settings;
settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 100);
- SpdyFrame* settings_frame = buffered_spdy_framer_->CreateSettings(settings);
+ SpdySerializedFrame* settings_frame =
+ buffered_spdy_framer_->CreateSettings(settings);
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Sending Settings Frame";
EnqueueDataFrame(new SpdyFrameDataFrame(settings_frame));
@@ -467,7 +469,7 @@ size_t SpdySM::SendSynStreamImpl(uint32_t stream_id,
}
DCHECK(buffered_spdy_framer_);
- SpdyFrame* fsrcf = buffered_spdy_framer_->CreateSynStream(
+ SpdySerializedFrame* fsrcf = buffered_spdy_framer_->CreateSynStream(
stream_id, 0, 0, CONTROL_FLAG_NONE, &block);
size_t df_size = fsrcf->size();
EnqueueDataFrame(new SpdyFrameDataFrame(fsrcf));
@@ -486,7 +488,7 @@ size_t SpdySM::SendSynReplyImpl(uint32_t stream_id,
block[":version"] = headers.response_version().as_string();
DCHECK(buffered_spdy_framer_);
- SpdyFrame* fsrcf = buffered_spdy_framer_->CreateSynReply(
+ SpdySerializedFrame* fsrcf = buffered_spdy_framer_->CreateSynReply(
stream_id, CONTROL_FLAG_NONE, &block);
size_t df_size = fsrcf->size();
EnqueueDataFrame(new SpdyFrameDataFrame(fsrcf));
@@ -506,7 +508,7 @@ void SpdySM::SendDataFrameImpl(uint32_t stream_id,
// priority queue. Compression needs to be done
// with late binding.
if (len == 0) {
- SpdyFrame* fdf =
+ SpdySerializedFrame* fdf =
buffered_spdy_framer_->CreateDataFrame(stream_id, data, len, flags);
EnqueueDataFrame(new SpdyFrameDataFrame(fdf));
return;
@@ -523,7 +525,7 @@ void SpdySM::SendDataFrameImpl(uint32_t stream_id,
if ((size < len) && (flags & DATA_FLAG_FIN))
chunk_flags = static_cast<SpdyDataFlags>(chunk_flags & ~DATA_FLAG_FIN);
- SpdyFrame* fdf = buffered_spdy_framer_->CreateDataFrame(
+ SpdySerializedFrame* fdf = buffered_spdy_framer_->CreateDataFrame(
stream_id, data, size, chunk_flags);
EnqueueDataFrame(new SpdyFrameDataFrame(fdf));
@@ -604,7 +606,7 @@ void SpdySM::GetOutput() {
void SpdySM::CreateFramer(SpdyMajorVersion spdy_version) {
DCHECK(!buffered_spdy_framer_);
- buffered_spdy_framer_.reset(new BufferedSpdyFramer(spdy_version, true));
+ buffered_spdy_framer_.reset(new BufferedSpdyFramer(spdy_version));
buffered_spdy_framer_->set_visitor(this);
}
diff --git a/chromium/net/tools/flip_server/spdy_interface_test.cc b/chromium/net/tools/flip_server/spdy_interface_test.cc
index 1d4c09ac16e..dc172fcd633 100644
--- a/chromium/net/tools/flip_server/spdy_interface_test.cc
+++ b/chromium/net/tools/flip_server/spdy_interface_test.cc
@@ -169,7 +169,7 @@ class SpdySMTestBase : public ::testing::TestWithParam<SpdyMajorVersion> {
acceptor_.get(),
GetParam()));
- spdy_framer_.reset(new BufferedSpdyFramer(GetParam(), true));
+ spdy_framer_.reset(new BufferedSpdyFramer(GetParam()));
spdy_framer_visitor_.reset(new SpdyFramerVisitor);
spdy_framer_->set_visitor(spdy_framer_visitor_.get());
}
@@ -236,7 +236,8 @@ TEST_P(SpdySMProxyTest, OnStreamFrameData) {
SpdyHeaderBlock block;
testing::MockFunction<void(int)> checkpoint; // NOLINT
- scoped_ptr<SpdyFrame> frame(spdy_framer_->CreatePingFrame(12, false));
+ scoped_ptr<SpdySerializedFrame> frame(
+ spdy_framer_->CreatePingFrame(12, false));
block[":method"] = "GET";
block[":host"] = "www.example.com";
block[":path"] = "/path";
diff --git a/chromium/net/tools/flip_server/create_listener.cc b/chromium/net/tools/flip_server/tcp_socket_util.cc
index 3e976036cb3..00f9b7e59e0 100644
--- a/chromium/net/tools/flip_server/create_listener.cc
+++ b/chromium/net/tools/flip_server/tcp_socket_util.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 "net/tools/flip_server/create_listener.h"
+#include "net/tools/flip_server/tcp_socket_util.h"
#include <arpa/inet.h>
#include <errno.h>
-#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
@@ -16,10 +15,14 @@
#include <sys/types.h>
#include <unistd.h>
+#include "base/files/file_util.h"
#include "base/logging.h"
+#include "net/socket/tcp_socket.h"
namespace net {
+namespace {
+
// Used to ensure we delete the addrinfo structure alloc'd by getaddrinfo().
class AddrinfoGuard {
public:
@@ -57,38 +60,9 @@ bool CloseSocket(int* fd, int tries) {
return false;
}
-// Sets an FD to be nonblocking.
-void FlipSetNonBlocking(int fd) {
- DCHECK_GE(fd, 0);
-
- int fcntl_return = fcntl(fd, F_GETFL, 0);
- CHECK_NE(fcntl_return, -1) << "error doing fcntl(fd, F_GETFL, 0) fd: " << fd
- << " errno=" << errno;
+} // namespace
- if (fcntl_return & O_NONBLOCK)
- return;
-
- fcntl_return = fcntl(fd, F_SETFL, fcntl_return | O_NONBLOCK);
- CHECK_NE(fcntl_return, -1)
- << "error doing fcntl(fd, F_SETFL, fcntl_return) fd: " << fd
- << " errno=" << errno;
-}
-
-int SetDisableNagle(int fd) {
- int on = 1;
- int rc;
- rc = setsockopt(
- fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&on), sizeof(on));
- if (rc < 0) {
- close(fd);
- LOG(FATAL) << "setsockopt() TCP_NODELAY: failed on fd " << fd;
- return 0;
- }
- return 1;
-}
-
-// see header for documentation of this function.
-int CreateListeningSocket(const std::string& host,
+int CreateTCPServerSocket(const std::string& host,
const std::string& port,
bool is_numeric_host_address,
int backlog,
@@ -157,7 +131,7 @@ int CreateListeningSocket(const std::string& host,
#define SO_REUSEPORT 15
#endif
if (reuseport) {
- // set SO_REUSEADDR on the listening socket.
+ // set SO_REUSEPORT on the listening socket.
int on = 1;
int rc;
rc = setsockopt(sock,
@@ -196,7 +170,9 @@ int CreateListeningSocket(const std::string& host,
}
if (disable_nagle) {
- if (!SetDisableNagle(sock)) {
+ if (!SetTCPNoDelay(sock, /*no_delay=*/true)) {
+ close(sock);
+ LOG(FATAL) << "SetTCPNoDelay() failed on fd: " << sock;
return -1;
}
}
@@ -224,11 +200,11 @@ int CreateListeningSocket(const std::string& host,
return 0;
}
-int CreateConnectedSocket(int* connect_fd,
- const std::string& host,
+int CreateTCPClientSocket(const std::string& host,
const std::string& port,
bool is_numeric_host_address,
- bool disable_nagle) {
+ bool disable_nagle,
+ int* connect_fd) {
const char* node = NULL;
const char* service = NULL;
@@ -267,10 +243,14 @@ int CreateConnectedSocket(int* connect_fd,
return -1;
}
- FlipSetNonBlocking(sock);
+ if (!base::SetNonBlocking(sock)) {
+ LOG(FATAL) << "base::SetNonBlocking failed: " << sock;
+ }
if (disable_nagle) {
- if (!SetDisableNagle(sock)) {
+ if (!SetTCPNoDelay(sock, /*no_delay=*/true)) {
+ close(sock);
+ LOG(FATAL) << "SetTCPNoDelay() failed on fd: " << sock;
return -1;
}
}
diff --git a/chromium/net/tools/flip_server/create_listener.h b/chromium/net/tools/flip_server/tcp_socket_util.h
index 72b790f2cef..4e2e910ef43 100644
--- a/chromium/net/tools/flip_server/create_listener.h
+++ b/chromium/net/tools/flip_server/tcp_socket_util.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_TOOLS_FLIP_SERVER_CREATE_LISTENER_H_
-#define NET_TOOLS_FLIP_SERVER_CREATE_LISTENER_H_
+#ifndef NET_TOOLS_FLIP_SERVER_TCP_SOCKET_UTIL_H_
+#define NET_TOOLS_FLIP_SERVER_TCP_SOCKET_UTIL_H_
#include <string>
namespace net {
-void FlipSetNonBlocking(int fd);
-
// Summary:
// creates a socket for listening, and bind()s and listen()s it.
// Args:
@@ -29,13 +27,13 @@ void FlipSetNonBlocking(int fd);
// the OS starts rejecting new incoming connections.
// reuseaddr - if true sets SO_REUSEADDR on the listening socket
// reuseport - if true sets SO_REUSEPORT on the listening socket
-// wait_for_iface - A boolean indicating that CreateListeningSocket should
+// wait_for_iface - A boolean indicating that CreateTCPServerSocket should
// block until the interface that it will bind to has been
// raised. This is intended for HA environments.
// disable_nagle - if true sets TCP_NODELAY on the listening socket.
// listen_fd - this will be assigned a positive value if the socket is
// successfully created, else it will be assigned -1.
-int CreateListeningSocket(const std::string& host,
+int CreateTCPServerSocket(const std::string& host,
const std::string& port,
bool is_numeric_host_address,
int backlog,
@@ -45,12 +43,12 @@ int CreateListeningSocket(const std::string& host,
bool disable_nagle,
int* listen_fd);
-int CreateConnectedSocket(int* connect_fd,
- const std::string& host,
+int CreateTCPClientSocket(const std::string& host,
const std::string& port,
bool is_numeric_host_address,
- bool disable_nagle);
+ bool disable_nagle,
+ int* connect_fd);
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_CREATE_LISTENER_H_
+#endif // NET_TOOLS_FLIP_SERVER_TCP_SOCKET_UTIL_H_
diff --git a/chromium/net/tools/flip_server/url_to_filename_encoder.cc b/chromium/net/tools/flip_server/url_to_filename_encoder.cc
index b3d80e4b5a1..b5a01d18c37 100644
--- a/chromium/net/tools/flip_server/url_to_filename_encoder.cc
+++ b/chromium/net/tools/flip_server/url_to_filename_encoder.cc
@@ -8,7 +8,6 @@
#include "base/logging.h"
#include "base/strings/string_util.h"
-#include "net/base/net_util.h"
using std::string;
diff --git a/chromium/net/tools/flip_server/url_to_filename_encoder.h b/chromium/net/tools/flip_server/url_to_filename_encoder.h
index 583e2fbb341..c68a9a1d4cc 100644
--- a/chromium/net/tools/flip_server/url_to_filename_encoder.h
+++ b/chromium/net/tools/flip_server/url_to_filename_encoder.h
@@ -108,7 +108,7 @@ class UrlToFilenameEncoder {
#endif
} else {
std::string clean_url(url);
- if (clean_url.length() && clean_url[clean_url.length() - 1] == '/')
+ if (clean_url.length() && clean_url.back() == '/')
clean_url.append("index.html");
std::string host = UrlUtilities::GetUrlHost(clean_url);
diff --git a/chromium/net/tools/gdig/gdig.cc b/chromium/net/tools/gdig/gdig.cc
index 9a0176b140d..7d9410d93e4 100644
--- a/chromium/net/tools/gdig/gdig.cc
+++ b/chromium/net/tools/gdig/gdig.cc
@@ -23,9 +23,10 @@
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "net/base/address_list.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "net/dns/dns_client.h"
#include "net/dns/dns_config_service.h"
#include "net/dns/dns_protocol.h"
@@ -53,11 +54,11 @@ bool StringToIPEndPoint(const std::string& ip_address_and_port,
if (port == -1)
port = dns_protocol::kDefaultPort;
- net::IPAddressNumber ip_number;
- if (!net::ParseIPLiteralToNumber(ip, &ip_number))
+ net::IPAddress ip_address;
+ if (!ip_address.AssignFromIPLiteral(ip))
return false;
- *ip_end_point = net::IPEndPoint(ip_number, static_cast<uint16_t>(port));
+ *ip_end_point = net::IPEndPoint(ip_address, static_cast<uint16_t>(port));
return true;
}
@@ -328,7 +329,7 @@ bool GDig::ParseCommandLine(int argc, const char* argv[]) {
parsed_command_line.GetSwitchValueASCII("nameserver");
if (!StringToIPEndPoint(nameserver, &nameserver_)) {
fprintf(stderr,
- "Cannot parse the namerserver string into an IPEndPoint\n");
+ "Cannot parse the nameserver string into an IPEndPoint\n");
return false;
}
}
diff --git a/chromium/net/tools/get_server_time/get_server_time.cc b/chromium/net/tools/get_server_time/get_server_time.cc
index 3363bb08391..65279d57804 100644
--- a/chromium/net/tools/get_server_time/get_server_time.cc
+++ b/chromium/net/tools/get_server_time/get_server_time.cc
@@ -283,7 +283,7 @@ int main(int argc, char* argv[]) {
return EXIT_FAILURE;
}
- void* iter = NULL;
+ size_t iter = 0;
std::string date_header;
while (headers->EnumerateHeader(&iter, "Date", &date_header)) {
std::printf("Got date header: %s\n", date_header.c_str());
diff --git a/chromium/net/tools/quic/end_to_end_test.cc b/chromium/net/tools/quic/end_to_end_test.cc
index b1cee41f65b..095142d6a71 100644
--- a/chromium/net/tools/quic/end_to_end_test.cc
+++ b/chromium/net/tools/quic/end_to_end_test.cc
@@ -4,6 +4,8 @@
#include <stddef.h>
#include <sys/epoll.h>
+
+#include <list>
#include <string>
#include <vector>
@@ -13,10 +15,11 @@
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
-#include "net/quic/congestion_control/tcp_cubic_sender.h"
#include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
#include "net/quic/crypto/null_encrypter.h"
+#include "net/quic/quic_client_session_base.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
@@ -56,7 +59,6 @@ using base::IntToString;
using base::StringPiece;
using base::WaitableEvent;
using net::EpollServer;
-using net::IPAddressNumber;
using net::test::ConstructEncryptedPacket;
using net::test::CryptoTestUtils;
using net::test::GenerateBody;
@@ -72,15 +74,14 @@ using net::test::ValueRestore;
using net::test::kClientDataStreamId1;
using net::test::kInitialSessionFlowControlWindowForTest;
using net::test::kInitialStreamFlowControlWindowForTest;
-using net::tools::test::PacketDroppingTestWriter;
-using net::tools::test::QuicDispatcherPeer;
-using net::tools::test::QuicServerPeer;
+using net::test::PacketDroppingTestWriter;
+using net::test::QuicDispatcherPeer;
+using net::test::QuicServerPeer;
using std::ostream;
using std::string;
using std::vector;
namespace net {
-namespace tools {
namespace test {
namespace {
@@ -93,7 +94,6 @@ struct TestParams {
TestParams(const QuicVersionVector& client_supported_versions,
const QuicVersionVector& server_supported_versions,
QuicVersion negotiated_version,
- bool use_fec,
bool client_supports_stateless_rejects,
bool server_uses_stateless_rejects_if_peer_supported,
QuicTag congestion_control_tag,
@@ -101,7 +101,6 @@ struct TestParams {
: client_supported_versions(client_supported_versions),
server_supported_versions(server_supported_versions),
negotiated_version(negotiated_version),
- use_fec(use_fec),
client_supports_stateless_rejects(client_supports_stateless_rejects),
server_uses_stateless_rejects_if_peer_supported(
server_uses_stateless_rejects_if_peer_supported),
@@ -118,7 +117,6 @@ struct TestParams {
<< p.client_supports_stateless_rejects;
os << " server_uses_stateless_rejects_if_peer_supported: "
<< p.server_uses_stateless_rejects_if_peer_supported;
- os << " use_fec: " << p.use_fec;
os << " congestion_control_tag: "
<< QuicUtils::TagToString(p.congestion_control_tag);
os << " auto_tune_flow_control_window: " << p.auto_tune_flow_control_window
@@ -129,7 +127,6 @@ struct TestParams {
QuicVersionVector client_supported_versions;
QuicVersionVector server_supported_versions;
QuicVersion negotiated_version;
- bool use_fec;
bool client_supports_stateless_rejects;
bool server_uses_stateless_rejects_if_peer_supported;
QuicTag congestion_control_tag;
@@ -165,62 +162,56 @@ vector<TestParams> GetTestParams() {
// TODO(rtenneti): Add kTBBR after BBR code is checked in.
for (const QuicTag congestion_control_tag : {kRENO, kQBIC}) {
for (bool auto_tune_flow_control_window : {true, false}) {
- for (const bool use_fec : {false, true}) {
- const int kMaxEnabledOptions = 5;
- int enabled_options = 0;
- if (congestion_control_tag != kQBIC) {
- ++enabled_options;
- }
- if (use_fec) {
- ++enabled_options;
- }
- if (auto_tune_flow_control_window) {
- ++enabled_options;
- }
- if (client_supports_stateless_rejects) {
- ++enabled_options;
- }
- if (server_uses_stateless_rejects_if_peer_supported) {
- ++enabled_options;
- }
- CHECK_GE(kMaxEnabledOptions, enabled_options);
+ const int kMaxEnabledOptions = 5;
+ int enabled_options = 0;
+ if (congestion_control_tag != kQBIC) {
+ ++enabled_options;
+ }
+ if (auto_tune_flow_control_window) {
+ ++enabled_options;
+ }
+ if (client_supports_stateless_rejects) {
+ ++enabled_options;
+ }
+ if (server_uses_stateless_rejects_if_peer_supported) {
+ ++enabled_options;
+ }
+ CHECK_GE(kMaxEnabledOptions, enabled_options);
- // Run tests with no options, a single option, or all the options
- // enabled to avoid a combinatorial explosion.
- if (enabled_options > 1 && enabled_options < kMaxEnabledOptions) {
+ // Run tests with no options, a single option, or all the options
+ // enabled to avoid a combinatorial explosion.
+ if (enabled_options > 1 && enabled_options < kMaxEnabledOptions) {
+ continue;
+ }
+
+ for (const QuicVersionVector& client_versions : version_buckets) {
+ CHECK(!client_versions.empty());
+ // Add an entry for server and client supporting all versions.
+ params.push_back(TestParams(
+ client_versions, all_supported_versions,
+ client_versions.front(), client_supports_stateless_rejects,
+ server_uses_stateless_rejects_if_peer_supported,
+ congestion_control_tag, auto_tune_flow_control_window));
+
+ // Run version negotiation tests tests with no options, or all
+ // the options enabled to avoid a combinatorial explosion.
+ if (enabled_options > 0 && enabled_options < kMaxEnabledOptions) {
continue;
}
- for (const QuicVersionVector& client_versions : version_buckets) {
- CHECK(!client_versions.empty());
- // Add an entry for server and client supporting all versions.
+ // Test client supporting all versions and server supporting 1
+ // version. Simulate an old server and exercise version downgrade
+ // in the client. Protocol negotiation should occur. Skip the i =
+ // 0 case because it is essentially the same as the default case.
+ for (size_t i = 1; i < client_versions.size(); ++i) {
+ QuicVersionVector server_supported_versions;
+ server_supported_versions.push_back(client_versions[i]);
params.push_back(TestParams(
- client_versions, all_supported_versions,
- client_versions.front(), use_fec,
+ client_versions, server_supported_versions,
+ server_supported_versions.front(),
client_supports_stateless_rejects,
server_uses_stateless_rejects_if_peer_supported,
congestion_control_tag, auto_tune_flow_control_window));
-
- // Run version negotiation tests tests with no options, or all
- // the options enabled to avoid a combinatorial explosion.
- if (enabled_options > 0 && enabled_options < kMaxEnabledOptions) {
- continue;
- }
-
- // Test client supporting all versions and server supporting 1
- // version. Simulate an old server and exercise version downgrade
- // in the client. Protocol negotiation should occur. Skip the i =
- // 0 case because it is essentially the same as the default case.
- for (size_t i = 1; i < client_versions.size(); ++i) {
- QuicVersionVector server_supported_versions;
- server_supported_versions.push_back(client_versions[i]);
- params.push_back(TestParams(
- client_versions, server_supported_versions,
- server_supported_versions.front(), use_fec,
- client_supports_stateless_rejects,
- server_uses_stateless_rejects_if_peer_supported,
- congestion_control_tag, auto_tune_flow_control_window));
- }
}
}
}
@@ -247,7 +238,7 @@ class ClientDelegate : public PacketDroppingTestWriter::Delegate {
~ClientDelegate() override {}
void OnCanWrite() override {
EpollEvent event(EPOLLOUT, false);
- client_->OnEvent(client_->fd(), &event);
+ client_->OnEvent(client_->GetLatestFD(), &event);
}
private:
@@ -267,7 +258,6 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
client_supported_versions_ = GetParam().client_supported_versions;
server_supported_versions_ = GetParam().server_supported_versions;
negotiated_version_ = GetParam().negotiated_version;
- FLAGS_enable_quic_fec = GetParam().use_fec;
VLOG(1) << "Using Configuration: " << GetParam();
@@ -354,10 +344,6 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
// client as well according to the test parameter.
copt.push_back(GetParam().congestion_control_tag);
- if (GetParam().use_fec) {
- // Set FEC config in client's connection options and in client session.
- copt.push_back(kFHDR);
- }
if (GetParam().client_supports_stateless_rejects) {
copt.push_back(kSREJ);
}
@@ -372,10 +358,6 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
StartServer();
client_.reset(CreateQuicClient(client_writer_));
- if (GetParam().use_fec) {
- // Set FecPolicy to always protect data on all streams.
- client_->SetFecPolicy(FEC_PROTECT_ALWAYS);
- }
static EpollEvent event(EPOLLOUT, false);
client_writer_->Initialize(
reinterpret_cast<QuicEpollConnectionHelper*>(
@@ -469,13 +451,12 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
// being discarded, based on connection stats.
// Calls server_thread_ Pause() and Resume(), which may only be called once
// per test.
- void VerifyCleanConnection(bool /*had_packet_loss*/) {
+ void VerifyCleanConnection(bool had_packet_loss) {
QuicConnectionStats client_stats =
client_->client()->session()->connection()->GetStats();
- // TODO(ianswett): Re-enable this check once b/19572432 is fixed.
- // if (!had_packet_loss) {
- // EXPECT_EQ(0u, client_stats.packets_lost);
- // }
+ if (FLAGS_quic_reply_to_rej && !had_packet_loss) {
+ EXPECT_EQ(0u, client_stats.packets_lost);
+ }
EXPECT_EQ(0u, client_stats.packets_discarded);
// When doing 0-RTT with stateless rejects, the encrypted requests cause
// a retranmission of the SREJ packets which are dropped by the client.
@@ -498,10 +479,9 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
ASSERT_EQ(1u, dispatcher->session_map().size());
QuicSession* session = dispatcher->session_map().begin()->second;
QuicConnectionStats server_stats = session->connection()->GetStats();
- // TODO(ianswett): Re-enable this check once b/19572432 is fixed.
- // if (!had_packet_loss) {
- // EXPECT_EQ(0u, server_stats.packets_lost);
- // }
+ if (FLAGS_quic_reply_to_rej && !had_packet_loss) {
+ EXPECT_EQ(0u, server_stats.packets_lost);
+ }
EXPECT_EQ(0u, server_stats.packets_discarded);
// TODO(ianswett): Restore the check for packets_dropped equals 0.
// The expect for packets received is equal to packets processed fails
@@ -567,12 +547,11 @@ TEST_P(EndToEndTest, SimpleRequestResponseWithLargeReject) {
EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
}
-// TODO(rch): figure out how to detect missing v6 supprt (like on the linux
+// TODO(rch): figure out how to detect missing v6 support (like on the linux
// try bots) and selectively disable this test.
TEST_P(EndToEndTest, DISABLED_SimpleRequestResponsev6) {
- IPAddressNumber ip;
- CHECK(net::ParseIPLiteralToNumber("::1", &ip));
- server_address_ = IPEndPoint(ip, server_address_.port());
+ server_address_ =
+ IPEndPoint(IPAddress::IPv6Localhost(), server_address_.port());
ASSERT_TRUE(Initialize());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
@@ -807,14 +786,9 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
client_->WaitForResponseForMs(-1);
ASSERT_TRUE(client_->client()->connected());
EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
- if (FLAGS_require_strike_register_or_server_nonce) {
- 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(expected_num_hellos_latest_session,
+ client_->client()->session()->GetNumSentClientHellos());
+ EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
client_->Disconnect();
@@ -865,14 +839,9 @@ TEST_P(EndToEndTest, SynchronousRequestZeroRTTFailure) {
client_->WaitForInitialResponse();
ASSERT_TRUE(client_->client()->connected());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
- if (FLAGS_require_strike_register_or_server_nonce) {
- 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(expected_num_hellos_latest_session,
+ client_->client()->session()->GetNumSentClientHellos());
+ EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
client_->Disconnect();
@@ -929,14 +898,9 @@ TEST_P(EndToEndTest, LargePostSynchronousRequest) {
client_->WaitForInitialResponse();
ASSERT_TRUE(client_->client()->connected());
EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
- if (FLAGS_require_strike_register_or_server_nonce) {
- 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(expected_num_hellos_latest_session,
+ client_->client()->session()->GetNumSentClientHellos());
+ EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
client_->Disconnect();
@@ -994,31 +958,6 @@ TEST_P(EndToEndTest, SetInitialReceivedConnectionOptions) {
ContainsQuicTag(server_config_.ReceivedConnectionOptions(), kPRST));
}
-TEST_P(EndToEndTest, CorrectlyConfiguredFec) {
- ASSERT_TRUE(Initialize());
- client_->client()->WaitForCryptoHandshakeConfirmed();
- server_thread_->WaitForCryptoHandshakeConfirmed();
-
- FecPolicy expected_policy =
- GetParam().use_fec ? FEC_PROTECT_ALWAYS : FEC_PROTECT_OPTIONAL;
-
- // Verify that server's FEC configuration is correct.
- server_thread_->Pause();
- QuicDispatcher* dispatcher =
- QuicServerPeer::GetDispatcher(server_thread_->server());
- ASSERT_EQ(1u, dispatcher->session_map().size());
- QuicSpdySession* session = dispatcher->session_map().begin()->second;
- EXPECT_EQ(expected_policy,
- QuicSpdySessionPeer::GetHeadersStream(session)->fec_policy());
- server_thread_->Resume();
-
- // Verify that client's FEC configuration is correct.
- EXPECT_EQ(expected_policy,
- QuicSpdySessionPeer::GetHeadersStream(client_->client()->session())
- ->fec_policy());
- EXPECT_EQ(expected_policy, client_->GetOrCreateStream()->fec_policy());
-}
-
TEST_P(EndToEndTest, LargePostSmallBandwidthLargeBuffer) {
ASSERT_TRUE(Initialize());
SetPacketSendDelay(QuicTime::Delta::FromMicroseconds(1));
@@ -1064,7 +1003,7 @@ TEST_P(EndToEndTest, DoNotSetResumeWriteAlarmIfConnectionFlowControlBlocked) {
// Make sure that the stream has data pending so that it will be marked as
// write blocked when it receives a stream level WINDOW_UPDATE.
- stream->SendBody("hello", false);
+ stream->WriteOrBufferBody("hello", false, nullptr);
// The stream now attempts to write, fails because it is still connection
// level flow control blocked, and is added to the write blocked list.
@@ -1169,8 +1108,8 @@ TEST_P(EndToEndTest, NegotiateMaxOpenStreams) {
// Make the client misbehave after negotiation.
const int kServerMaxStreams = kMaxStreamsMinimumIncrement + 1;
- QuicSessionPeer::SetMaxOpenStreams(client_->client()->session(),
- kServerMaxStreams + 1);
+ QuicSessionPeer::SetMaxOpenOutgoingStreams(client_->client()->session(),
+ kServerMaxStreams + 1);
HTTPMessage request(HttpConstants::HTTP_1_1, HttpConstants::POST, "/foo");
request.AddHeader("content-length", "3");
@@ -1454,18 +1393,17 @@ TEST_P(EndToEndTest, StreamCancelErrorTest) {
class WrongAddressWriter : public QuicPacketWriterWrapper {
public:
WrongAddressWriter() {
- IPAddressNumber ip;
- CHECK(net::ParseIPLiteralToNumber("127.0.0.2", &ip));
- self_address_ = IPEndPoint(ip, 0);
+ self_address_ = IPEndPoint(IPAddress(127, 0, 0, 2), 0);
}
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddressNumber& /*real_self_address*/,
- const IPEndPoint& peer_address) override {
+ const IPAddress& /*real_self_address*/,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) override {
// Use wrong address!
return QuicPacketWriterWrapper::WritePacket(
- buffer, buf_len, self_address_.address(), peer_address);
+ buffer, buf_len, self_address_.address(), peer_address, options);
}
bool IsWriteBlockedDataBuffered() const override { return false; }
@@ -1480,11 +1418,10 @@ TEST_P(EndToEndTest, ConnectionMigrationClientIPChanged) {
EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
// Store the client IP address which was used to send the first request.
- IPAddressNumber old_host = client_->client()->client_address().address();
+ IPAddress old_host = client_->client()->GetLatestClientAddress().address();
// Migrate socket to the new IP address.
- IPAddressNumber new_host;
- CHECK(net::ParseIPLiteralToNumber("127.0.0.2", &new_host));
+ IPAddress new_host(127, 0, 0, 2);
EXPECT_NE(old_host, new_host);
ASSERT_TRUE(client_->client()->MigrateSocket(new_host));
@@ -1503,16 +1440,15 @@ TEST_P(EndToEndTest, ConnectionMigrationClientPortChanged) {
EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
// Store the client address which was used to send the first request.
- IPEndPoint old_address = client_->client()->client_address();
+ IPEndPoint old_address = client_->client()->GetLatestClientAddress();
+
+ // Stop listening and close the old FD.
+ QuicClientPeer::CleanUpUDPSocket(client_->client(),
+ client_->client()->GetLatestFD());
- // Stop listening on the old FD.
- EpollServer* eps = client_->epoll_server();
- int old_fd = client_->client()->fd();
- eps->UnregisterFD(old_fd);
// Create a new socket before closing the old one, which will result in a new
// ephemeral port.
- QuicClientPeer::CreateUDPSocket(client_->client());
- close(old_fd);
+ QuicClientPeer::CreateUDPSocketAndBind(client_->client());
// The packet writer needs to be updated to use the new FD.
client_->client()->CreateQuicPacketWriter();
@@ -1522,7 +1458,7 @@ TEST_P(EndToEndTest, ConnectionMigrationClientPortChanged) {
// port change, and so expects no change to incoming port.
// This is kind of ugly, but needed as we are simply swapping out the client
// FD rather than any more complex NAT rebinding simulation.
- int new_port = client_->client()->client_address().port();
+ int new_port = client_->client()->GetLatestClientAddress().port();
QuicClientPeer::SetClientPort(client_->client(), new_port);
QuicConnectionPeer::SetSelfAddress(
client_->client()->session()->connection(),
@@ -1531,7 +1467,8 @@ TEST_P(EndToEndTest, ConnectionMigrationClientPortChanged) {
new_port));
// Register the new FD for epoll events.
- int new_fd = client_->client()->fd();
+ int new_fd = client_->client()->GetLatestFD();
+ EpollServer* eps = client_->epoll_server();
eps->RegisterFD(new_fd, client_->client(), EPOLLIN | EPOLLOUT | EPOLLET);
// Send a second request, using the new FD.
@@ -1539,7 +1476,7 @@ TEST_P(EndToEndTest, ConnectionMigrationClientPortChanged) {
EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
// Verify that the client's ephemeral port is different.
- IPEndPoint new_address = client_->client()->client_address();
+ IPEndPoint new_address = client_->client()->GetLatestClientAddress();
EXPECT_EQ(old_address.address(), new_address.address());
EXPECT_NE(old_address.port(), new_address.port());
}
@@ -1568,7 +1505,7 @@ TEST_P(EndToEndTest, DifferentFlowControlWindows) {
// Open a data stream to make sure the stream level flow control is updated.
QuicSpdyClientStream* stream = client_->GetOrCreateStream();
- stream->SendBody("hello", false);
+ stream->WriteOrBufferBody("hello", false, nullptr);
// Client should have the right values for server's receive window.
EXPECT_EQ(kServerStreamIFCW,
@@ -1702,8 +1639,9 @@ TEST_P(EndToEndTest, RequestWithNoBodyWillNeverSendStreamFrameWithFIN) {
QuicDispatcher* dispatcher =
QuicServerPeer::GetDispatcher(server_thread_->server());
QuicSession* session = dispatcher->session_map().begin()->second;
- EXPECT_EQ(0u, QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(session)
- .size());
+ EXPECT_EQ(
+ 0u,
+ QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(session).size());
server_thread_->Resume();
}
@@ -1731,6 +1669,18 @@ class TestAckListener : public QuicAckListenerInterface {
int num_notifications_;
};
+class TestResponseListener : public QuicClient::ResponseListener {
+ public:
+ void OnCompleteResponse(QuicStreamId id,
+ const BalsaHeaders& response_headers,
+ const string& response_body) override {
+ string debug_string;
+ response_headers.DumpHeadersToString(&debug_string);
+ DVLOG(1) << "response for stream " << id << " " << debug_string << "\n"
+ << response_body;
+ }
+};
+
TEST_P(EndToEndTest, AckNotifierWithPacketLossAndBlockedSocket) {
// Verify that even in the presence of packet loss and occasionally blocked
// socket, an AckNotifierDelegate will get informed that the data it is
@@ -1803,9 +1753,9 @@ TEST_P(EndToEndTest, ServerSendPublicResetWithDifferentConnectionId) {
// We must pause the server's thread in order to call WritePacket without
// race conditions.
server_thread_->Pause();
- server_writer_->WritePacket(packet->data(), packet->length(),
- server_address_.address(),
- client_->client()->client_address());
+ server_writer_->WritePacket(
+ packet->data(), packet->length(), server_address_.address(),
+ client_->client()->GetLatestClientAddress(), nullptr);
server_thread_->Resume();
// The connection should be unaffected.
@@ -1831,9 +1781,10 @@ TEST_P(EndToEndTest, ClientSendPublicResetWithDifferentConnectionId) {
QuicFramer framer(server_supported_versions_, QuicTime::Zero(),
Perspective::IS_CLIENT);
scoped_ptr<QuicEncryptedPacket> packet(framer.BuildPublicResetPacket(header));
- client_writer_->WritePacket(packet->data(), packet->length(),
- client_->client()->client_address().address(),
- server_address_);
+ client_writer_->WritePacket(
+ packet->data(), packet->length(),
+ client_->client()->GetLatestClientAddress().address(), server_address_,
+ nullptr);
// The connection should be unaffected.
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
@@ -1858,9 +1809,9 @@ TEST_P(EndToEndTest, ServerSendVersionNegotiationWithDifferentConnectionId) {
// We must pause the server's thread in order to call WritePacket without
// race conditions.
server_thread_->Pause();
- server_writer_->WritePacket(packet->data(), packet->length(),
- server_address_.address(),
- client_->client()->client_address());
+ server_writer_->WritePacket(
+ packet->data(), packet->length(), server_address_.address(),
+ client_->client()->GetLatestClientAddress(), nullptr);
server_thread_->Resume();
// The connection should be unaffected.
@@ -1884,9 +1835,10 @@ TEST_P(EndToEndTest, BadPacketHeaderTruncated) {
0x3C,
// truncated connection ID
0x11};
- client_writer_->WritePacket(&packet[0], sizeof(packet),
- client_->client()->client_address().address(),
- server_address_);
+ client_writer_->WritePacket(
+ &packet[0], sizeof(packet),
+ client_->client()->GetLatestClientAddress().address(), server_address_,
+ nullptr);
// Give the server time to process the packet.
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
// Pause the server so we can access the server's internals without races.
@@ -1922,9 +1874,10 @@ TEST_P(EndToEndTest, BadPacketHeaderFlags) {
// private flags
0x00,
};
- client_writer_->WritePacket(&packet[0], sizeof(packet),
- client_->client()->client_address().address(),
- server_address_);
+ client_writer_->WritePacket(
+ &packet[0], sizeof(packet),
+ client_->client()->GetLatestClientAddress().address(), server_address_,
+ nullptr);
// Give the server time to process the packet.
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
// Pause the server so we can access the server's internals without races.
@@ -1951,15 +1904,16 @@ TEST_P(EndToEndTest, BadEncryptedData) {
scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
client_->client()->session()->connection()->connection_id(), false, false,
- 1, "At least 20 characters.", PACKET_8BYTE_CONNECTION_ID,
- PACKET_6BYTE_PACKET_NUMBER));
+ false, kDefaultPathId, 1, "At least 20 characters.",
+ PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER));
// Damage the encrypted data.
string damaged_packet(packet->data(), packet->length());
damaged_packet[30] ^= 0x01;
DVLOG(1) << "Sending bad packet.";
- client_writer_->WritePacket(damaged_packet.data(), damaged_packet.length(),
- client_->client()->client_address().address(),
- server_address_);
+ client_writer_->WritePacket(
+ damaged_packet.data(), damaged_packet.length(),
+ client_->client()->GetLatestClientAddress().address(), server_address_,
+ nullptr);
// Give the server time to process the packet.
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
// This error is sent to the connection's OnError (which ignores it), so the
@@ -2018,6 +1972,182 @@ class StreamWithErrorFactory : public QuicTestServer::StreamFactory {
string response_body_;
};
+// A test server stream that drops all received body.
+class ServerStreamThatDropsBody : public QuicSimpleServerStream {
+ public:
+ ServerStreamThatDropsBody(QuicStreamId id, QuicSpdySession* session)
+ : QuicSimpleServerStream(id, session) {}
+
+ ~ServerStreamThatDropsBody() override {}
+
+ protected:
+ void OnDataAvailable() override {
+ while (HasBytesToRead()) {
+ struct iovec iov;
+ if (GetReadableRegions(&iov, 1) == 0) {
+ // No more data to read.
+ break;
+ }
+ DVLOG(1) << "Processed " << iov.iov_len << " bytes for stream " << id();
+ MarkConsumed(iov.iov_len);
+ }
+
+ if (!sequencer()->IsClosed()) {
+ sequencer()->SetUnblocked();
+ return;
+ }
+
+ // If the sequencer is closed, then all the body, including the fin, has
+ // been consumed.
+ OnFinRead();
+
+ if (write_side_closed() || fin_buffered()) {
+ return;
+ }
+
+ SendResponse();
+ }
+};
+
+class ServerStreamThatDropsBodyFactory : public QuicTestServer::StreamFactory {
+ public:
+ ServerStreamThatDropsBodyFactory() {}
+
+ ~ServerStreamThatDropsBodyFactory() override{};
+
+ QuicSimpleServerStream* CreateStream(QuicStreamId id,
+ QuicSpdySession* session) override {
+ return new ServerStreamThatDropsBody(id, session);
+ }
+};
+
+// A test server stream that sends response with body size greater than 4GB.
+class ServerStreamThatSendsHugeResponse : public QuicSimpleServerStream {
+ public:
+ ServerStreamThatSendsHugeResponse(QuicStreamId id,
+ QuicSpdySession* session,
+ int64_t body_bytes)
+ : QuicSimpleServerStream(id, session), body_bytes_(body_bytes) {}
+
+ ~ServerStreamThatSendsHugeResponse() override {}
+
+ protected:
+ void SendResponse() override {
+ QuicInMemoryCache::Response response;
+ string body;
+ test::GenerateBody(&body, body_bytes_);
+ response.set_body(body);
+ SendHeadersAndBodyAndTrailers(response.headers(), response.body(),
+ response.trailers());
+ }
+
+ private:
+ // Use a explicit int64 rather than size_t to simulate a 64-bit server talking
+ // to a 32-bit client.
+ int64_t body_bytes_;
+};
+
+class ServerStreamThatSendsHugeResponseFactory
+ : public QuicTestServer::StreamFactory {
+ public:
+ explicit ServerStreamThatSendsHugeResponseFactory(int64_t body_bytes)
+ : body_bytes_(body_bytes) {}
+
+ ~ServerStreamThatSendsHugeResponseFactory() override{};
+
+ QuicSimpleServerStream* CreateStream(QuicStreamId id,
+ QuicSpdySession* session) override {
+ return new ServerStreamThatSendsHugeResponse(id, session, body_bytes_);
+ }
+
+ int64_t body_bytes_;
+};
+
+// A test client stream that drops all received body.
+class ClientStreamThatDropsBody : public QuicSpdyClientStream {
+ public:
+ ClientStreamThatDropsBody(QuicStreamId id, QuicClientSession* session)
+ : QuicSpdyClientStream(id, session) {}
+ ~ClientStreamThatDropsBody() override {}
+
+ void OnDataAvailable() override {
+ while (HasBytesToRead()) {
+ struct iovec iov;
+ if (GetReadableRegions(&iov, 1) == 0) {
+ break;
+ }
+ MarkConsumed(iov.iov_len);
+ }
+ if (sequencer()->IsClosed()) {
+ OnFinRead();
+ } else {
+ sequencer()->SetUnblocked();
+ }
+ }
+};
+
+class ClientSessionThatDropsBody : public QuicClientSession {
+ public:
+ ClientSessionThatDropsBody(const QuicConfig& config,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index)
+ : QuicClientSession(config,
+ connection,
+ server_id,
+ crypto_config,
+ push_promise_index) {}
+
+ ~ClientSessionThatDropsBody() override {}
+
+ QuicSpdyClientStream* CreateClientStream() override {
+ return new ClientStreamThatDropsBody(GetNextOutgoingStreamId(), this);
+ }
+};
+
+class MockableQuicClientThatDropsBody : public MockableQuicClient {
+ public:
+ MockableQuicClientThatDropsBody(IPEndPoint server_address,
+ const QuicServerId& server_id,
+ const QuicConfig& config,
+ const QuicVersionVector& supported_versions,
+ EpollServer* epoll_server)
+ : MockableQuicClient(server_address,
+ server_id,
+ config,
+ supported_versions,
+ epoll_server) {}
+ ~MockableQuicClientThatDropsBody() override {}
+
+ QuicClientSession* CreateQuicClientSession(
+ QuicConnection* connection) override {
+ auto session =
+ new ClientSessionThatDropsBody(*config(), connection, server_id(),
+ crypto_config(), push_promise_index());
+ set_session(session);
+ return session;
+ }
+};
+
+class QuicTestClientThatDropsBody : public QuicTestClient {
+ public:
+ QuicTestClientThatDropsBody(IPEndPoint server_address,
+ const string& server_hostname,
+ const QuicConfig& config,
+ const QuicVersionVector& supported_versions)
+ : QuicTestClient(server_address,
+ server_hostname,
+ config,
+ supported_versions) {
+ set_client(new MockableQuicClientThatDropsBody(
+ server_address, QuicServerId(server_hostname, server_address.port(),
+ PRIVACY_MODE_DISABLED),
+ config, supported_versions, epoll_server()));
+ }
+ ~QuicTestClientThatDropsBody() override {}
+};
+
TEST_P(EndToEndTest, EarlyResponseFinRecording) {
set_smaller_flow_control_receive_window();
@@ -2139,7 +2269,6 @@ TEST_P(EndToEndTest, LargePostEarlyResponse) {
TEST_P(EndToEndTest, Trailers) {
// Test sending and receiving HTTP/2 Trailers (trailing HEADERS frames).
- ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true);
ASSERT_TRUE(Initialize());
client_->client()->WaitForCryptoHandshakeConfirmed();
@@ -2166,7 +2295,330 @@ TEST_P(EndToEndTest, Trailers) {
EXPECT_EQ(trailers, client_->response_trailers());
}
+class EndToEndTestServerPush : public EndToEndTest {
+ protected:
+ const size_t kNumMaxStreams = 10;
+
+ EndToEndTestServerPush() : EndToEndTest() {
+ FLAGS_quic_supports_push_promise = true;
+ client_config_.SetMaxStreamsPerConnection(kNumMaxStreams, kNumMaxStreams);
+ }
+
+ // Add a request with its response and |num_resources| push resources into
+ // cache.
+ // If |resource_size| == 0, response body of push resources use default string
+ // concatenating with resource url. Otherwise, generate a string of
+ // |resource_size| as body.
+ void AddRequestAndResponseWithServerPush(string host,
+ string path,
+ string response_body,
+ string* push_urls,
+ const size_t num_resources,
+ const size_t resource_size) {
+ bool use_large_response = resource_size != 0;
+ string large_resource;
+ if (use_large_response) {
+ // Generate a response common body larger than flow control window for
+ // push response.
+ test::GenerateBody(&large_resource, resource_size);
+ }
+ std::list<QuicInMemoryCache::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;
+ 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(
+ resource_url, response_headers, kV3LowestPriority, body));
+ }
+
+ QuicInMemoryCache::GetInstance()->AddSimpleResponseWithServerPushResources(
+ host, path, 200, response_body, push_resources);
+ }
+};
+
+// Run all server push end to end tests with all supported versions.
+INSTANTIATE_TEST_CASE_P(EndToEndTestsServerPush,
+ EndToEndTestServerPush,
+ ::testing::ValuesIn(GetTestParams()));
+
+TEST_P(EndToEndTestServerPush, ServerPush) {
+ ASSERT_TRUE(Initialize());
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+
+ // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
+ SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
+ SetReorderPercentage(30);
+
+ // Add a response with headers, body, and push resources.
+ const string kBody = "body content";
+ size_t kNumResources = 4;
+ string push_urls[] = {
+ "https://google.com/font.woff", "https://google.com/script.js",
+ "https://fonts.google.com/font.woff", "https://google.com/logo-hires.jpg",
+ };
+ AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
+ push_urls, kNumResources, 0);
+
+ client_->client()->set_response_listener(new TestResponseListener);
+
+ DVLOG(1) << "send request for /push_example";
+ EXPECT_EQ(kBody, client_->SendSynchronousRequest(
+ "https://example.com/push_example"));
+ 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;
+ string response_body = client_->SendSynchronousRequest(url);
+ DVLOG(1) << "response body " << response_body;
+ EXPECT_EQ(expected_body, response_body);
+ }
+}
+
+TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) {
+ // Tests that sending a request which has 4 push resources will trigger server
+ // to push those 4 resources and client can handle pushed resources and match
+ // them with requests later.
+ ASSERT_TRUE(Initialize());
+
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+
+ // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
+ SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
+ SetReorderPercentage(30);
+
+ // Add a response with headers, body, and push resources.
+ const string kBody = "body content";
+ size_t const kNumResources = 4;
+ string push_urls[] = {
+ "https://example.com/font.woff", "https://example.com/script.js",
+ "https://fonts.example.com/font.woff",
+ "https://example.com/logo-hires.jpg",
+ };
+ AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
+ push_urls, kNumResources, 0);
+ client_->client()->set_response_listener(new TestResponseListener);
+
+ // Send the first request: this will trigger the server to send all the push
+ // resources associated with this request, and these will be cached by the
+ // client.
+ EXPECT_EQ(kBody, client_->SendSynchronousRequest(
+ "https://example.com/push_example"));
+
+ for (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;
+ string response_body = client_->SendSynchronousRequest(url);
+ DVLOG(1) << "response body " << response_body;
+ EXPECT_EQ(expected_body, response_body);
+ }
+ // Expect only original request has been sent and push responses have been
+ // received as normal response.
+ EXPECT_EQ(1u, client_->num_requests());
+ EXPECT_EQ(1u + kNumResources, client_->num_responses());
+}
+
+TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
+ // Tests that when streams are not blocked by flow control or congestion
+ // control, pushing even more resources than max number of open outgoing
+ // streams should still work because all response streams get closed
+ // immediately after pushing resources.
+ ASSERT_TRUE(Initialize());
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+
+ // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
+ SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
+ SetReorderPercentage(30);
+
+ // Add a response with headers, body, and push resources.
+ const string kBody = "body content";
+
+ // One more resource than max number of outgoing stream of this session.
+ const size_t kNumResources = 1 + kNumMaxStreams; // 11.
+ string push_urls[11];
+ for (uint32_t i = 0; i < kNumResources; ++i) {
+ push_urls[i] = "https://example.com/push_resources" + base::UintToString(i);
+ }
+ AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
+ push_urls, kNumResources, 0);
+ client_->client()->set_response_listener(new TestResponseListener);
+
+ // Send the first request: this will trigger the server to send all the push
+ // resources associated with this request, and these will be cached by the
+ // client.
+ EXPECT_EQ(kBody, client_->SendSynchronousRequest(
+ "https://example.com/push_example"));
+
+ 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,
+ client_->SendSynchronousRequest(url));
+ }
+
+ // Only 1 request should have been sent.
+ EXPECT_EQ(1u, client_->num_requests());
+ // The responses to the original request and all the promised resources
+ // should have been received.
+ EXPECT_EQ(12u, client_->num_responses());
+}
+
+TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) {
+ // Tests that when server tries to send more large resources(large enough to
+ // be blocked by flow control window or congestion control window) than max
+ // open outgoing streams , server can open upto max number of outgoing
+ // streams for them, and the rest will be queued up.
+
+ // Reset flow control windows.
+ size_t kFlowControlWnd = 20 * 1024; // 20KB.
+ // Response body is larger than 1 flow controlblock window.
+ size_t kBodySize = kFlowControlWnd * 2;
+ set_client_initial_stream_flow_control_receive_window(kFlowControlWnd);
+ // Make sure conntection level flow control window is large enough not to
+ // block data being sent out though they will be blocked by stream level one.
+ set_client_initial_session_flow_control_receive_window(
+ kBodySize * kNumMaxStreams + 1024);
+
+ ASSERT_TRUE(Initialize());
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+
+ // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
+ SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
+ SetReorderPercentage(30);
+
+ // Add a response with headers, body, and push resources.
+ const string kBody = "body content";
+
+ const size_t kNumResources = kNumMaxStreams + 1;
+ string push_urls[11];
+ for (uint32_t i = 0; i < kNumResources; ++i) {
+ push_urls[i] = "http://example.com/push_resources" + base::UintToString(i);
+ }
+ AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
+ push_urls, kNumResources, kBodySize);
+
+ client_->client()->set_response_listener(new TestResponseListener);
+
+ client_->SendRequest("https://example.com/push_example");
+
+ // Pause after the first response arrives.
+ while (!client_->response_complete()) {
+ // Because of priority, the first response arrived should be to original
+ // request.
+ client_->WaitForResponse();
+ }
+
+ // Check server session to see if it has max number of outgoing streams opened
+ // though more resources need to be pushed.
+ server_thread_->Pause();
+ QuicDispatcher* dispatcher =
+ QuicServerPeer::GetDispatcher(server_thread_->server());
+ ASSERT_EQ(1u, dispatcher->session_map().size());
+ QuicSession* session = dispatcher->session_map().begin()->second;
+ EXPECT_EQ(kNumMaxStreams, session->GetNumOpenOutgoingStreams());
+ server_thread_->Resume();
+
+ EXPECT_EQ(1u, client_->num_requests());
+ EXPECT_EQ(1u, client_->num_responses());
+ EXPECT_EQ(kBody, client_->response_body());
+
+ // "Send" request for a promised resources will not really send out it because
+ // its response is being pushed(but blocked). And the following ack and
+ // flow control behavior of SendSynchronousRequests()
+ // will unblock the stream to finish receiving response.
+ client_->SendSynchronousRequest(push_urls[0]);
+ EXPECT_EQ(1u, client_->num_requests());
+ EXPECT_EQ(2u, client_->num_responses());
+
+ // Do same thing for the rest 10 resources.
+ for (uint32_t i = 1; i < kNumResources; ++i) {
+ client_->SendSynchronousRequest(push_urls[i]);
+ }
+
+ // Because of server push, client gets all pushed resources without actually
+ // sending requests for them.
+ EXPECT_EQ(1u, client_->num_requests());
+ // Including response to original request, 12 responses in total were
+ // recieved.
+ EXPECT_EQ(12u, client_->num_responses());
+}
+
+// TODO(fayang): this test seems to cause net_unittests timeouts :|
+TEST_P(EndToEndTest, DISABLED_TestHugePostWithPacketLoss) {
+ // This test tests a huge post with introduced packet loss from client to
+ // server and body size greater than 4GB, making sure QUIC code does not break
+ // for 32-bit builds.
+ ServerStreamThatDropsBodyFactory stream_factory;
+ SetSpdyStreamFactory(&stream_factory);
+ ASSERT_TRUE(Initialize());
+ // Set client's epoll server's time out to 0 to make this test be finished
+ // within a short time.
+ client_->epoll_server()->set_timeout_in_us(0);
+
+ 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.
+ const int kSizeBytes = 128 * 1024;
+ HTTPMessage request(HttpConstants::HTTP_1_1, HttpConstants::POST, "/foo");
+ // 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);
+ request.AddHeader("content-length", IntToString(request_body_size_bytes));
+ request.set_has_complete_message(false);
+ string body;
+ test::GenerateBody(&body, kSizeBytes);
+
+ client_->SendMessage(request);
+ for (int i = 0; i < request_body_size_bytes / kSizeBytes; ++i) {
+ bool fin = (i == request_body_size_bytes - 1);
+ client_->SendData(string(body.data(), kSizeBytes), fin);
+ client_->client()->WaitForEvents();
+ }
+ VerifyCleanConnection(false);
+}
+
+// TODO(fayang): this test seems to cause net_unittests timeouts :|
+TEST_P(EndToEndTest, DISABLED_TestHugeResponseWithPacketLoss) {
+ // This test tests a huge response with introduced loss from server to client
+ // and body size greater than 4GB, making sure QUIC code does not break for
+ // 32-bit builds.
+ const int kSizeBytes = 128 * 1024;
+ int64_t response_body_size_bytes = pow(2, 32) + kSizeBytes;
+ ASSERT_LT(4294967296, response_body_size_bytes);
+ ServerStreamThatSendsHugeResponseFactory stream_factory(
+ response_body_size_bytes);
+ SetSpdyStreamFactory(&stream_factory);
+
+ StartServer();
+
+ // Use a quic client that drops received body.
+ QuicTestClient* client = new QuicTestClientThatDropsBody(
+ server_address_, server_hostname_, client_config_,
+ client_supported_versions_);
+ client->UseWriter(client_writer_);
+ client->Connect();
+ client_.reset(client);
+ static EpollEvent event(EPOLLOUT, false);
+ client_writer_->Initialize(
+ QuicConnectionPeer::GetHelper(client_->client()->session()->connection()),
+ new ClientDelegate(client_->client()));
+ initialized_ = true;
+ ASSERT_TRUE(client_->client()->connected());
+
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+ SetPacketLossPercentage(1);
+ client_->SendRequest("/huge_response");
+ client_->WaitForResponse();
+ VerifyCleanConnection(false);
+}
+
} // namespace
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_client.cc b/chromium/net/tools/quic/quic_client.cc
index 2ecfe6d73a9..15f6f5ce0f7 100644
--- a/chromium/net/tools/quic/quic_client.cc
+++ b/chromium/net/tools/quic/quic_client.cc
@@ -15,6 +15,7 @@
#include "base/run_loop.h"
#include "net/base/sockaddr_storage.h"
#include "net/quic/crypto/quic_random.h"
+#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_data_reader.h"
#include "net/quic/quic_flags.h"
@@ -28,11 +29,13 @@
#define SO_RXQ_OVFL 40
#endif
+// TODO(rtenneti): Add support for MMSG_MORE.
+#define MMSG_MORE 0
+
using std::string;
using std::vector;
namespace net {
-namespace tools {
const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
@@ -60,36 +63,42 @@ QuicClient::QuicClient(IPEndPoint server_address,
const QuicConfig& config,
EpollServer* epoll_server,
ProofVerifier* proof_verifier)
- : QuicClientBase(server_id,
- supported_versions,
- config,
- new QuicEpollConnectionHelper(epoll_server),
- proof_verifier),
+ : QuicClientBase(
+ server_id,
+ supported_versions,
+ config,
+ new QuicEpollConnectionHelper(epoll_server, QuicAllocator::SIMPLE),
+ proof_verifier),
server_address_(server_address),
local_port_(0),
epoll_server_(epoll_server),
- fd_(-1),
initialized_(false),
packets_dropped_(0),
overflow_supported_(false),
store_response_(false),
- latest_response_code_(-1) {}
+ latest_response_code_(-1),
+ packet_reader_(new QuicPacketReader()) {}
QuicClient::~QuicClient() {
if (connected()) {
- session()->connection()->SendConnectionCloseWithDetails(
- QUIC_PEER_GOING_AWAY, "Client being torn down");
+ session()->connection()->CloseConnection(
+ QUIC_PEER_GOING_AWAY, "Client being torn down",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
STLDeleteElements(&data_to_resend_on_connect_);
STLDeleteElements(&data_sent_before_handshake_);
- CleanUpUDPSocketImpl();
+ CleanUpAllUDPSockets();
}
bool QuicClient::Initialize() {
QuicClientBase::Initialize();
+ set_num_sent_client_hellos(0);
+ set_num_stateless_rejects_received(0);
+ set_connection_error(QUIC_NO_ERROR);
+
// If an initial flow control window has not explicitly been set, then use the
// same values that Chrome uses.
const uint32_t kSessionMaxRecvWindowSize = 15 * 1024 * 1024; // 15 MB
@@ -106,11 +115,11 @@ bool QuicClient::Initialize() {
epoll_server_->set_timeout_in_us(50 * 1000);
- if (!CreateUDPSocket()) {
+ if (!CreateUDPSocketAndBind()) {
return false;
}
- epoll_server_->RegisterFD(fd_, this, kEpollFlags);
+ epoll_server_->RegisterFD(GetLatestFD(), this, kEpollFlags);
initialized_ = true;
return true;
}
@@ -126,67 +135,42 @@ QuicClient::QuicDataToResend::~QuicDataToResend() {
}
}
-bool QuicClient::CreateUDPSocket() {
- int address_family = server_address_.GetSockAddrFamily();
- fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
- if (fd_ < 0) {
- LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
- return false;
- }
-
- int get_overflow = 1;
- int rc = setsockopt(fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
- sizeof(get_overflow));
- if (rc < 0) {
- DLOG(WARNING) << "Socket overflow detection not supported";
- } else {
- overflow_supported_ = true;
- }
-
- if (!QuicSocketUtils::SetReceiveBufferSize(fd_,
- kDefaultSocketReceiveBuffer)) {
- return false;
- }
-
- if (!QuicSocketUtils::SetSendBufferSize(fd_, kDefaultSocketReceiveBuffer)) {
- return false;
- }
-
- rc = QuicSocketUtils::SetGetAddressInfo(fd_, address_family);
- if (rc < 0) {
- LOG(ERROR) << "IP detection not supported" << strerror(errno);
+bool QuicClient::CreateUDPSocketAndBind() {
+ int fd =
+ QuicSocketUtils::CreateUDPSocket(server_address_, &overflow_supported_);
+ if (fd < 0) {
return false;
}
+ IPEndPoint client_address;
if (bind_to_address_.size() != 0) {
- client_address_ = IPEndPoint(bind_to_address_, local_port_);
- } else if (address_family == AF_INET) {
- IPAddressNumber any4;
- CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
- client_address_ = IPEndPoint(any4, local_port_);
+ client_address = IPEndPoint(bind_to_address_, local_port_);
+ } else if (server_address_.GetSockAddrFamily() == AF_INET) {
+ client_address = IPEndPoint(IPAddress::IPv4AllZeros(), local_port_);
} else {
- IPAddressNumber any6;
- CHECK(net::ParseIPLiteralToNumber("::", &any6));
- client_address_ = IPEndPoint(any6, local_port_);
+ IPAddress any6 = IPAddress::IPv6AllZeros();
+ client_address = IPEndPoint(any6, local_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));
- rc =
- bind(fd_, reinterpret_cast<const sockaddr*>(&raw_addr), 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));
if (rc < 0) {
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)) {
+ 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);
}
+ fd_address_map_[fd] = client_address;
+
return true;
}
@@ -261,36 +245,59 @@ void QuicClient::Disconnect() {
DCHECK(initialized_);
if (connected()) {
- session()->connection()->SendConnectionCloseWithDetails(
- QUIC_PEER_GOING_AWAY, "Client disconnecting");
+ session()->connection()->CloseConnection(
+ QUIC_PEER_GOING_AWAY, "Client disconnecting",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
STLDeleteElements(&data_to_resend_on_connect_);
STLDeleteElements(&data_sent_before_handshake_);
- CleanUpUDPSocket();
+ CleanUpAllUDPSockets();
initialized_ = false;
}
-void QuicClient::CleanUpUDPSocket() {
- CleanUpUDPSocketImpl();
+void QuicClient::CleanUpUDPSocket(int fd) {
+ CleanUpUDPSocketImpl(fd);
+ fd_address_map_.erase(fd);
}
-void QuicClient::CleanUpUDPSocketImpl() {
- if (fd_ > -1) {
- epoll_server_->UnregisterFD(fd_);
- int rc = close(fd_);
+void QuicClient::CleanUpAllUDPSockets() {
+ for (std::pair<int, IPEndPoint> fd_address : fd_address_map_) {
+ CleanUpUDPSocketImpl(fd_address.first);
+ }
+ fd_address_map_.clear();
+}
+
+void QuicClient::CleanUpUDPSocketImpl(int fd) {
+ if (fd > -1) {
+ epoll_server_->UnregisterFD(fd);
+ int rc = close(fd);
DCHECK_EQ(0, rc);
- fd_ = -1;
}
}
void QuicClient::SendRequest(const BalsaHeaders& headers,
StringPiece body,
bool fin) {
+ QuicClientPushPromiseIndex::TryHandle* handle;
+ QuicAsyncStatus rv = push_promise_index()->Try(
+ SpdyBalsaUtils::RequestHeadersToSpdyHeaders(headers), this, &handle);
+ if (rv == QUIC_SUCCESS)
+ return;
+
+ if (rv == QUIC_PENDING) {
+ // May need to retry request if asynchronous rendezvous fails.
+ auto new_headers = new BalsaHeaders;
+ new_headers->CopyFrom(headers);
+ push_promise_data_to_resend_.reset(
+ new ClientQuicDataToResend(new_headers, body, fin, this));
+ return;
+ }
+
QuicSpdyClientStream* stream = CreateReliableClientStream();
if (stream == nullptr) {
- LOG(DFATAL) << "stream creation failed!";
+ QUIC_BUG << "stream creation failed!";
return;
}
stream->set_visitor(this);
@@ -358,20 +365,20 @@ bool QuicClient::WaitForEvents() {
return session()->num_active_requests() != 0;
}
-bool QuicClient::MigrateSocket(const IPAddressNumber& new_host) {
+bool QuicClient::MigrateSocket(const IPAddress& new_host) {
if (!connected()) {
return false;
}
- CleanUpUDPSocket();
+ CleanUpUDPSocket(GetLatestFD());
bind_to_address_ = new_host;
- if (!CreateUDPSocket()) {
+ if (!CreateUDPSocketAndBind()) {
return false;
}
- epoll_server_->RegisterFD(fd_, this, kEpollFlags);
- session()->connection()->SetSelfAddress(client_address_);
+ epoll_server_->RegisterFD(GetLatestFD(), this, kEpollFlags);
+ session()->connection()->SetSelfAddress(GetLatestClientAddress());
QuicPacketWriter* writer = CreateQuicPacketWriter();
set_writer(writer);
@@ -381,10 +388,15 @@ bool QuicClient::MigrateSocket(const IPAddressNumber& new_host) {
}
void QuicClient::OnEvent(int fd, EpollEvent* event) {
- DCHECK_EQ(fd, fd_);
+ DCHECK_EQ(fd, GetLatestFD());
if (event->in_events & EPOLLIN) {
- while (connected() && ReadAndProcessPacket()) {
+ bool more_to_read = true;
+ while (connected() && more_to_read) {
+ more_to_read = packet_reader_->ReadAndDispatchPackets(
+ GetLatestFD(), QuicClient::GetLatestClientAddress().port(),
+ *helper()->GetClock(), this,
+ overflow_supported_ ? &packets_dropped_ : nullptr);
}
}
if (connected() && (event->in_events & EPOLLOUT)) {
@@ -400,79 +412,86 @@ void QuicClient::OnClose(QuicSpdyStream* stream) {
DCHECK(stream != nullptr);
QuicSpdyClientStream* client_stream =
static_cast<QuicSpdyClientStream*>(stream);
- BalsaHeaders headers;
- SpdyBalsaUtils::SpdyHeadersToResponseHeaders(client_stream->headers(),
- &headers);
+ BalsaHeaders response_headers;
+ SpdyBalsaUtils::SpdyHeadersToResponseHeaders(
+ client_stream->response_headers(), &response_headers);
if (response_listener_.get() != nullptr) {
- response_listener_->OnCompleteResponse(stream->id(), headers,
+ response_listener_->OnCompleteResponse(stream->id(), response_headers,
client_stream->data());
}
// Store response headers and body.
if (store_response_) {
- latest_response_code_ = headers.parsed_response_code();
- headers.DumpHeadersToString(&latest_response_headers_);
+ latest_response_code_ = response_headers.parsed_response_code();
+ response_headers.DumpHeadersToString(&latest_response_headers_);
latest_response_body_ = client_stream->data();
- latest_response_trailers_ = client_stream->trailers().DebugString();
+ latest_response_trailers_ =
+ client_stream->received_trailers().DebugString();
+ }
+}
+
+bool QuicClient::CheckVary(const SpdyHeaderBlock& client_request,
+ const SpdyHeaderBlock& promise_request,
+ const SpdyHeaderBlock& promise_response) {
+ return true;
+}
+
+void QuicClient::OnRendezvousResult(QuicSpdyStream* stream) {
+ std::unique_ptr<ClientQuicDataToResend> data_to_resend =
+ std::move(push_promise_data_to_resend_);
+ if (stream) {
+ stream->set_visitor(this);
+ stream->OnDataAvailable();
+ } else if (data_to_resend.get()) {
+ data_to_resend->Resend();
}
}
size_t QuicClient::latest_response_code() const {
- LOG_IF(DFATAL, !store_response_) << "Response not stored!";
+ QUIC_BUG_IF(!store_response_) << "Response not stored!";
return latest_response_code_;
}
const string& QuicClient::latest_response_headers() const {
- LOG_IF(DFATAL, !store_response_) << "Response not stored!";
+ QUIC_BUG_IF(!store_response_) << "Response not stored!";
return latest_response_headers_;
}
const string& QuicClient::latest_response_body() const {
- LOG_IF(DFATAL, !store_response_) << "Response not stored!";
+ QUIC_BUG_IF(!store_response_) << "Response not stored!";
return latest_response_body_;
}
const string& QuicClient::latest_response_trailers() const {
- LOG_IF(DFATAL, !store_response_) << "Response not stored!";
+ QUIC_BUG_IF(!store_response_) << "Response not stored!";
return latest_response_trailers_;
}
QuicPacketWriter* QuicClient::CreateQuicPacketWriter() {
- return new QuicDefaultPacketWriter(fd_);
+ return new QuicDefaultPacketWriter(GetLatestFD());
}
-int QuicClient::ReadPacket(char* buffer,
- int buffer_len,
- IPEndPoint* server_address,
- IPAddressNumber* client_ip) {
- return QuicSocketUtils::ReadPacket(
- fd_, buffer, buffer_len,
- overflow_supported_ ? &packets_dropped_ : nullptr, client_ip,
- server_address);
-}
-
-bool QuicClient::ReadAndProcessPacket() {
- // Allocate some extra space so we can send an error if the server goes over
- // the limit.
- char buf[2 * kMaxPacketSize];
-
- IPEndPoint server_address;
- IPAddressNumber client_ip;
+const IPEndPoint QuicClient::GetLatestClientAddress() const {
+ if (fd_address_map_.empty()) {
+ return IPEndPoint();
+ }
- int bytes_read = ReadPacket(buf, arraysize(buf), &server_address, &client_ip);
+ return fd_address_map_.back().second;
+}
- if (bytes_read < 0) {
- return false;
+int QuicClient::GetLatestFD() const {
+ if (fd_address_map_.empty()) {
+ return -1;
}
- QuicEncryptedPacket packet(buf, bytes_read, false);
+ return fd_address_map_.back().first;
+}
- IPEndPoint client_address(client_ip, client_address_.port());
- session()->connection()->ProcessUdpPacket(client_address, server_address,
- packet);
- return true;
+void QuicClient::ProcessPacket(const IPEndPoint& self_address,
+ const IPEndPoint& peer_address,
+ const QuicReceivedPacket& packet) {
+ session()->connection()->ProcessUdpPacket(self_address, peer_address, packet);
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_client.h b/chromium/net/tools/quic/quic_client.h
index 29febd7675d..56a02463710 100644
--- a/chromium/net/tools/quic/quic_client.h
+++ b/chromium/net/tools/quic/quic_client.h
@@ -16,19 +16,22 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
+#include "net/quic/quic_client_push_promise_index.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_spdy_stream.h"
#include "net/tools/balsa/balsa_headers.h"
#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_client_base.h"
+#include "net/tools/quic/quic_client_session.h"
+#include "net/tools/quic/quic_packet_reader.h"
+#include "net/tools/quic/quic_process_packet_interface.h"
namespace net {
class QuicServerId;
-namespace tools {
-
class QuicEpollConnectionHelper;
namespace test {
@@ -37,7 +40,9 @@ class QuicClientPeer;
class QuicClient : public QuicClientBase,
public EpollCallbackInterface,
- public QuicSpdyStream::Visitor {
+ public QuicSpdyStream::Visitor,
+ public ProcessPacketInterface,
+ public QuicClientPushPromiseIndex::Delegate {
public:
class ResponseListener {
public:
@@ -123,7 +128,7 @@ class QuicClient : public QuicClientBase,
void SendRequestsAndWaitForResponse(const std::vector<std::string>& url_list);
// Migrate to a new socket during an active connection.
- bool MigrateSocket(const IPAddressNumber& new_host);
+ bool MigrateSocket(const IPAddress& new_host);
// From EpollCallbackInterface
void OnRegistration(EpollServer* eps, int fd, int event_mask) override {}
@@ -138,25 +143,34 @@ class QuicClient : public QuicClientBase,
// QuicSpdyStream::Visitor
void OnClose(QuicSpdyStream* stream) override;
+ bool CheckVary(const SpdyHeaderBlock& client_request,
+ const SpdyHeaderBlock& promise_request,
+ const SpdyHeaderBlock& promise_response) override;
+ void OnRendezvousResult(QuicSpdyStream*) override;
+
// If the crypto handshake has not yet been confirmed, adds the data to the
// queue of data to resend if the client receives a stateless reject.
// Otherwise, deletes the data. Takes ownerership of |data_to_resend|.
void MaybeAddQuicDataToResend(QuicDataToResend* data_to_resend);
- void set_bind_to_address(IPAddressNumber address) {
+ // If the client has at least one UDP socket, return address of the latest
+ // created one. Otherwise, return an empty socket address.
+ const IPEndPoint GetLatestClientAddress() const;
+
+ // If the client has at least one UDP socket, return the latest created one.
+ // Otherwise, return -1.
+ int GetLatestFD() const;
+
+ void set_bind_to_address(const IPAddress& address) {
bind_to_address_ = address;
}
- IPAddressNumber bind_to_address() const { return bind_to_address_; }
+ const IPAddress& bind_to_address() const { return bind_to_address_; }
void set_local_port(int local_port) { local_port_ = local_port; }
const IPEndPoint& server_address() const { return server_address_; }
- const IPEndPoint& client_address() const { return client_address_; }
-
- int fd() { return fd_; }
-
// Takes ownership of the listener.
void set_response_listener(ResponseListener* listener) {
response_listener_.reset(listener);
@@ -169,21 +183,29 @@ class QuicClient : public QuicClientBase,
const std::string& latest_response_body() const;
const std::string& latest_response_trailers() const;
- protected:
+ // Implements ProcessPacketInterface. This will be called for each received
+ // packet.
+ void ProcessPacket(const IPEndPoint& self_address,
+ const IPEndPoint& peer_address,
+ const QuicReceivedPacket& packet) override;
+
virtual QuicPacketWriter* CreateQuicPacketWriter();
- virtual int ReadPacket(char* buffer,
- int buffer_len,
- IPEndPoint* server_address,
- IPAddressNumber* client_ip);
+ // If |fd| is an open UDP socket, unregister and close it. Otherwise, do
+ // nothing.
+ virtual void CleanUpUDPSocket(int fd);
+
+ // Unregister and close all open UDP sockets.
+ virtual void CleanUpAllUDPSockets();
EpollServer* epoll_server() { return epoll_server_; }
- // If the socket has been created, then unregister and close() the FD.
- virtual void CleanUpUDPSocket();
+ const linked_hash_map<int, IPEndPoint>& fd_address_map() const {
+ return fd_address_map_;
+ }
private:
- friend class net::tools::test::QuicClientPeer;
+ friend class net::test::QuicClientPeer;
// Specific QuicClient class for storing data to resend.
class ClientQuicDataToResend : public QuicDataToResend {
@@ -210,29 +232,33 @@ class QuicClient : public QuicClientBase,
// Used during initialization: creates the UDP socket FD, sets socket options,
// and binds the socket to our address.
- bool CreateUDPSocket();
+ bool CreateUDPSocketAndBind();
- // Actually clean up the socket.
- void CleanUpUDPSocketImpl();
+ // Actually clean up |fd|.
+ void CleanUpUDPSocketImpl(int fd);
- // Read a UDP packet and hand it to the framer.
- bool ReadAndProcessPacket();
+ // If the request URL matches a push promise, bypass sending the
+ // request.
+ bool MaybeHandlePromised(const BalsaHeaders& headers,
+ const SpdyHeaderBlock& spdy_headers,
+ base::StringPiece body,
+ bool fin);
// Address of the server.
const IPEndPoint server_address_;
- // Address of the client if the client is connected to the server.
- IPEndPoint client_address_;
-
// If initialized, the address to bind to.
- IPAddressNumber bind_to_address_;
+ IPAddress bind_to_address_;
+
// Local port to bind to. Initialize to 0.
int local_port_;
// Listens for events on the client socket.
EpollServer* epoll_server_;
- // UDP socket.
- int fd_;
+
+ // 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_;
// Listens for full responses.
scoped_ptr<ResponseListener> response_listener_;
@@ -266,10 +292,18 @@ class QuicClient : public QuicClientBase,
// must be resent upon a subsequent successful connection.
std::vector<QuicDataToResend*> data_to_resend_on_connect_;
+ // Point to a QuicPacketReader object on the heap. The reader allocates more
+ // space than allowed on the stack.
+ //
+ // TODO(rtenneti): Chromium code doesn't use |packet_reader_|. Add support for
+ // QuicPacketReader
+ scoped_ptr<QuicPacketReader> packet_reader_;
+
+ std::unique_ptr<ClientQuicDataToResend> push_promise_data_to_resend_;
+
DISALLOW_COPY_AND_ASSIGN(QuicClient);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_CLIENT_H_
diff --git a/chromium/net/tools/quic/quic_client_base.cc b/chromium/net/tools/quic/quic_client_base.cc
index 5c8daa26af3..91000db2c14 100644
--- a/chromium/net/tools/quic/quic_client_base.cc
+++ b/chromium/net/tools/quic/quic_client_base.cc
@@ -8,7 +8,6 @@
#include "net/quic/quic_server_id.h"
namespace net {
-namespace tools {
QuicClientBase::QuicClientBase(const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
@@ -42,8 +41,8 @@ ProofVerifier* QuicClientBase::proof_verifier() const {
QuicClientSession* QuicClientBase::CreateQuicClientSession(
QuicConnection* connection) {
- session_.reset(
- new QuicClientSession(config_, connection, server_id_, &crypto_config_));
+ session_.reset(new QuicClientSession(config_, connection, server_id_,
+ &crypto_config_, &push_promise_index_));
if (initial_max_packet_length_ != 0) {
session()->connection()->SetMaxPacketLength(initial_max_packet_length_);
}
@@ -104,6 +103,17 @@ void QuicClientBase::UpdateStats() {
}
}
+int QuicClientBase::GetNumReceivedServerConfigUpdates() {
+ // If we are not actively attempting to connect, the session object
+ // corresponds to the previous connection and should not be used.
+ // We do not need to take stateless rejects into account, since we
+ // don't expect any scup messages to be sent during a
+ // statelessly-rejected connection.
+ return !connected_or_attempting_connect_
+ ? 0
+ : session_->GetNumReceivedServerConfigUpdates();
+}
+
QuicErrorCode QuicClientBase::connection_error() const {
// Return the high-level error if there was one. Otherwise, return the
// connection error from the last session.
@@ -138,5 +148,4 @@ QuicConnectionId QuicClientBase::GenerateNewConnectionId() {
return QuicRandom::GetInstance()->RandUint64();
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_client_base.h b/chromium/net/tools/quic/quic_client_base.h
index 2ca8acac3ee..af44bdaca19 100644
--- a/chromium/net/tools/quic/quic_client_base.h
+++ b/chromium/net/tools/quic/quic_client_base.h
@@ -17,6 +17,7 @@
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/quic_crypto_client_config.h"
#include "net/quic/quic_bandwidth.h"
+#include "net/quic/quic_client_push_promise_index.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_packet_writer.h"
@@ -29,8 +30,6 @@ namespace net {
class ProofVerifier;
class QuicServerId;
-namespace tools {
-
class QuicClientBase {
public:
QuicClientBase(const QuicServerId& server_id,
@@ -121,6 +120,11 @@ class QuicClientBase {
// connection.
void UpdateStats();
+ // The number of server config updates received. We assume no
+ // updates can be sent during a previously, statelessly rejected
+ // connection, so only the latest session is taken into account.
+ int GetNumReceivedServerConfigUpdates();
+
// Returns any errors that occurred at the connection-level (as
// opposed to the session-level). When a stateless reject occurs,
// the error of the last session may not reflect the overall state
@@ -152,6 +156,12 @@ class QuicClientBase {
ProofVerifier* proof_verifier() const;
+ void set_session(QuicClientSession* session) { session_.reset(session); }
+
+ QuicClientPushPromiseIndex* push_promise_index() {
+ return &push_promise_index_;
+ }
+
protected:
virtual QuicClientSession* CreateQuicClientSession(
QuicConnection* connection);
@@ -171,6 +181,14 @@ class QuicClientBase {
QuicConnectionHelperInterface* helper() { return helper_.get(); }
+ void set_num_sent_client_hellos(int num_sent_client_hellos) {
+ num_sent_client_hellos_ = num_sent_client_hellos;
+ }
+
+ void set_num_stateless_rejects_received(int num_stateless_rejects_received) {
+ num_stateless_rejects_received_ = num_stateless_rejects_received;
+ }
+
private:
// |server_id_| is a tuple (hostname, port, is_https) of the server.
QuicServerId server_id_;
@@ -222,10 +240,11 @@ class QuicClientBase {
// to the previous client-level connection.
bool connected_or_attempting_connect_;
+ QuicClientPushPromiseIndex push_promise_index_;
+
DISALLOW_COPY_AND_ASSIGN(QuicClientBase);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_CLIENT_BASE_H_
diff --git a/chromium/net/tools/quic/quic_client_bin.cc b/chromium/net/tools/quic/quic_client_bin.cc
index 41f75cbc994..ead19bae020 100644
--- a/chromium/net/tools/quic/quic_client_bin.cc
+++ b/chromium/net/tools/quic/quic_client_bin.cc
@@ -48,6 +48,7 @@
#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"
@@ -159,8 +160,6 @@ int main(int argc, char* argv[]) {
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
CHECK(logging::InitLogging(settings));
- FLAGS_quic_supports_trailers = true;
-
if (line->HasSwitch("h") || line->HasSwitch("help") || urls.empty()) {
const char* help_str =
"Usage: quic_client [options] <url>\n"
@@ -241,7 +240,7 @@ int main(int argc, char* argv[]) {
base::MessageLoopForIO message_loop;
// Determine IP address to connect to from supplied hostname.
- net::IPAddressNumber ip_addr;
+ net::IPAddress ip_addr;
GURL url(urls[0]);
string host = FLAGS_host;
@@ -252,9 +251,9 @@ int main(int argc, char* argv[]) {
if (port == 0) {
port = url.EffectiveIntPort();
}
- if (!net::ParseIPLiteralToNumber(host, &ip_addr)) {
+ if (!ip_addr.AssignFromIPLiteral(host)) {
net::AddressList addresses;
- int rv = net::tools::SynchronousHostResolver::Resolve(host, &addresses);
+ int rv = net::SynchronousHostResolver::Resolve(host, &addresses);
if (rv != net::OK) {
LOG(ERROR) << "Unable to resolve '" << host
<< "' : " << net::ErrorToShortString(rv);
@@ -287,8 +286,8 @@ int main(int argc, char* argv[]) {
ProofVerifierChromium* proof_verifier = new ProofVerifierChromium(
cert_verifier.get(), nullptr, transport_security_state.get(),
ct_verifier.get());
- net::tools::QuicClient client(net::IPEndPoint(ip_addr, FLAGS_port), server_id,
- versions, &epoll_server, proof_verifier);
+ net::QuicClient client(net::IPEndPoint(ip_addr, FLAGS_port), server_id,
+ versions, &epoll_server, proof_verifier);
client.set_initial_max_packet_length(
FLAGS_initial_mtu != 0 ? FLAGS_initial_mtu : net::kDefaultMaxPacketSize);
if (!client.Initialize()) {
@@ -345,7 +344,7 @@ int main(int argc, char* argv[]) {
// Send the request.
net::SpdyHeaderBlock header_block =
- net::tools::SpdyBalsaUtils::RequestHeadersToSpdyHeaders(headers);
+ net::SpdyBalsaUtils::RequestHeadersToSpdyHeaders(headers);
client.SendRequestAndWaitForResponse(headers, body, /*fin=*/true);
// Print request and response details.
diff --git a/chromium/net/tools/quic/quic_client_session.cc b/chromium/net/tools/quic/quic_client_session.cc
index 4ae4851af8a..a0e11b1cfb4 100644
--- a/chromium/net/tools/quic/quic_client_session.cc
+++ b/chromium/net/tools/quic/quic_client_session.cc
@@ -13,13 +13,14 @@
using std::string;
namespace net {
-namespace tools {
-QuicClientSession::QuicClientSession(const QuicConfig& config,
- QuicConnection* connection,
- const QuicServerId& server_id,
- QuicCryptoClientConfig* crypto_config)
- : QuicClientSessionBase(connection, config),
+QuicClientSession::QuicClientSession(
+ const QuicConfig& config,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index)
+ : QuicClientSessionBase(connection, push_promise_index, config),
server_id_(server_id),
crypto_config_(crypto_config),
respect_goaway_(true) {}
@@ -37,20 +38,27 @@ void QuicClientSession::OnProofValid(
void QuicClientSession::OnProofVerifyDetailsAvailable(
const ProofVerifyDetails& /*verify_details*/) {}
-QuicSpdyClientStream* QuicClientSession::CreateOutgoingDynamicStream(
- SpdyPriority priority) {
+bool QuicClientSession::ShouldCreateOutgoingDynamicStream() {
if (!crypto_stream_->encryption_established()) {
DVLOG(1) << "Encryption not active so no outgoing stream created.";
- return nullptr;
+ return false;
}
- if (GetNumOpenOutgoingStreams() >= get_max_open_streams()) {
+ if (GetNumOpenOutgoingStreams() >= max_open_outgoing_streams()) {
DVLOG(1) << "Failed to create a new outgoing stream. "
<< "Already " << GetNumOpenOutgoingStreams() << " open.";
- return nullptr;
+ return false;
}
if (goaway_received() && respect_goaway_) {
DVLOG(1) << "Failed to create a new outgoing stream. "
<< "Already received goaway.";
+ return false;
+ }
+ return true;
+}
+
+QuicSpdyClientStream* QuicClientSession::CreateOutgoingDynamicStream(
+ SpdyPriority priority) {
+ if (!ShouldCreateOutgoingDynamicStream()) {
return nullptr;
}
QuicSpdyClientStream* stream = CreateClientStream();
@@ -76,18 +84,49 @@ int QuicClientSession::GetNumSentClientHellos() const {
return crypto_stream_->num_sent_client_hellos();
}
+int QuicClientSession::GetNumReceivedServerConfigUpdates() const {
+ return crypto_stream_->num_scup_messages_received();
+}
+
+bool QuicClientSession::ShouldCreateIncomingDynamicStream(QuicStreamId id) {
+ if (!connection()->connected()) {
+ LOG(DFATAL) << "ShouldCreateIncomingDynamicStream called when disconnected";
+ return false;
+ }
+ if (goaway_received() && respect_goaway_) {
+ DVLOG(1) << "Failed to create a new outgoing stream. "
+ << "Already received goaway.";
+ return false;
+ }
+ if (id % 2 != 0) {
+ LOG(WARNING) << "Received invalid push stream id " << id;
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Server created odd numbered stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ return true;
+}
+
QuicSpdyStream* QuicClientSession::CreateIncomingDynamicStream(
QuicStreamId id) {
- DLOG(ERROR) << "Server push not supported";
- return nullptr;
+ if (!ShouldCreateIncomingDynamicStream(id)) {
+ return nullptr;
+ }
+ QuicSpdyStream* stream = new QuicSpdyClientStream(id, this);
+ stream->CloseWriteSide();
+ ActivateStream(stream);
+ return stream;
}
QuicCryptoClientStreamBase* QuicClientSession::CreateQuicCryptoStream() {
return new QuicCryptoClientStream(
server_id_, this, new ProofVerifyContextChromium(0, BoundNetLog()),
- crypto_config_);
+ crypto_config_, this);
}
-} // namespace tools
+bool QuicClientSession::IsAuthorized(const string& authority) {
+ return true;
+}
} // namespace net
diff --git a/chromium/net/tools/quic/quic_client_session.h b/chromium/net/tools/quic/quic_client_session.h
index 6d25b592cb1..321c17f38a7 100644
--- a/chromium/net/tools/quic/quic_client_session.h
+++ b/chromium/net/tools/quic/quic_client_session.h
@@ -21,18 +21,14 @@ class QuicConnection;
class QuicServerId;
class ReliableQuicStream;
-namespace tools {
-
-// The maximum time a promises stream can be reserved without being
-// claimed by a client request.
-const int64_t kPushPromiseTimeoutSecs = 60;
-
class QuicClientSession : public QuicClientSessionBase {
public:
+ // Caller retains ownership of |promised_by_url|.
QuicClientSession(const QuicConfig& config,
QuicConnection* connection,
const QuicServerId& server_id,
- QuicCryptoClientConfig* crypto_config);
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index);
~QuicClientSession() override;
// Set up the QuicClientSession. Must be called prior to use.
void Initialize() override;
@@ -42,6 +38,8 @@ class QuicClientSession : public QuicClientSessionBase {
SpdyPriority priority) override;
QuicCryptoClientStreamBase* GetCryptoStream() override;
+ bool IsAuthorized(const std::string& authority) override;
+
// QuicClientSessionBase methods:
void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override;
void OnProofVerifyDetailsAvailable(
@@ -55,6 +53,8 @@ class QuicClientSession : public QuicClientSessionBase {
// than the number of round-trips needed for the handshake.
int GetNumSentClientHellos() const;
+ int GetNumReceivedServerConfigUpdates() const;
+
void set_respect_goaway(bool respect_goaway) {
respect_goaway_ = respect_goaway;
}
@@ -62,6 +62,11 @@ class QuicClientSession : public QuicClientSessionBase {
protected:
// QuicSession methods:
QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override;
+ // If an outgoing stream can be created, return true.
+ bool ShouldCreateOutgoingDynamicStream() override;
+
+ // If an incoming stream can be created, return true.
+ bool ShouldCreateIncomingDynamicStream(QuicStreamId id) override;
// Create the crypto stream. Called by Initialize()
virtual QuicCryptoClientStreamBase* CreateQuicCryptoStream();
@@ -76,7 +81,6 @@ class QuicClientSession : public QuicClientSessionBase {
QuicCryptoClientConfig* crypto_config() { return crypto_config_; }
private:
- bool ShouldCreateIncomingDynamicStream(QuicStreamId id);
scoped_ptr<QuicCryptoClientStreamBase> crypto_stream_;
QuicServerId server_id_;
QuicCryptoClientConfig* crypto_config_;
@@ -88,7 +92,6 @@ class QuicClientSession : public QuicClientSessionBase {
DISALLOW_COPY_AND_ASSIGN(QuicClientSession);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_CLIENT_SESSION_H_
diff --git a/chromium/net/tools/quic/quic_client_session_test.cc b/chromium/net/tools/quic/quic_client_session_test.cc
index 7b43f963e35..1619eed3417 100644
--- a/chromium/net/tools/quic/quic_client_session_test.cc
+++ b/chromium/net/tools/quic/quic_client_session_test.cc
@@ -6,10 +6,13 @@
#include <vector>
+#include "base/strings/stringprintf.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
#include "net/quic/quic_flags.h"
+#include "net/quic/spdy_utils.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_connection_peer.h"
#include "net/quic/test_tools/quic_packet_creator_peer.h"
#include "net/quic/test_tools/quic_spdy_session_peer.h"
@@ -17,12 +20,14 @@
#include "net/tools/quic/quic_spdy_client_stream.h"
#include "testing/gtest/include/gtest/gtest.h"
+using base::StringPrintf;
using net::test::ConstructEncryptedPacket;
using net::test::ConstructMisFramedEncryptedPacket;
using net::test::CryptoTestUtils;
using net::test::DefaultQuicConfig;
using net::test::MockConnection;
using net::test::MockConnectionHelper;
+using net::test::MockQuicSpdyClientStream;
using net::test::PacketSavingConnection;
using net::test::QuicConnectionPeer;
using net::test::QuicPacketCreatorPeer;
@@ -30,39 +35,78 @@ using net::test::QuicSpdySessionPeer;
using net::test::SupportedVersions;
using net::test::TestPeerIPAddress;
using net::test::ValueRestore;
+using net::test::kClientDataStreamId1;
+using net::test::kServerDataStreamId1;
using net::test::kTestPort;
+using std::string;
using testing::AnyNumber;
using testing::Invoke;
using testing::Truly;
using testing::_;
namespace net {
-namespace tools {
namespace test {
namespace {
const char kServerHostname[] = "test.example.com";
-const uint16_t kPort = 80;
+const uint16_t kPort = 443;
+
+class TestQuicClientSession : public QuicClientSession {
+ public:
+ explicit TestQuicClientSession(const QuicConfig& config,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index)
+ : QuicClientSession(config,
+ connection,
+ server_id,
+ crypto_config,
+ push_promise_index) {}
+
+ QuicSpdyClientStream* CreateClientStream() override {
+ return new MockQuicSpdyClientStream(GetNextOutgoingStreamId(), this);
+ }
+
+ MockQuicSpdyClientStream* CreateIncomingDynamicStream(
+ QuicStreamId id) override {
+ MockQuicSpdyClientStream* stream = new MockQuicSpdyClientStream(id, this);
+ ActivateStream(stream);
+ return stream;
+ }
+};
-class ToolsQuicClientSessionTest
- : public ::testing::TestWithParam<QuicVersion> {
+class QuicClientSessionTest : public ::testing::TestWithParam<QuicVersion> {
protected:
- ToolsQuicClientSessionTest()
- : crypto_config_(CryptoTestUtils::ProofVerifierForTesting()) {
+ QuicClientSessionTest()
+ : crypto_config_(CryptoTestUtils::ProofVerifierForTesting()),
+ promised_stream_id_(kServerDataStreamId1),
+ associated_stream_id_(kClientDataStreamId1) {
Initialize();
// Advance the time, because timers do not like uninitialized times.
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
+ ~QuicClientSessionTest() override {
+ // Session must be destroyed before promised_by_url_
+ session_.reset(nullptr);
+ }
+
void Initialize() {
session_.reset();
connection_ = new PacketSavingConnection(&helper_, Perspective::IS_CLIENT,
SupportedVersions(GetParam()));
- session_.reset(new QuicClientSession(
+ session_.reset(new TestQuicClientSession(
DefaultQuicConfig(), connection_,
QuicServerId(kServerHostname, kPort, PRIVACY_MODE_DISABLED),
- &crypto_config_));
+ &crypto_config_, &push_promise_index_));
session_->Initialize();
+ push_promise_[":path"] = "/bar";
+ push_promise_[":authority"] = "www.google.com";
+ push_promise_[":version"] = "HTTP/1.1";
+ push_promise_[":method"] = "GET";
+ push_promise_[":scheme"] = "https";
+ promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
}
void CompleteCryptoHandshake() {
@@ -77,19 +121,23 @@ class ToolsQuicClientSessionTest
QuicCryptoClientConfig crypto_config_;
MockConnectionHelper helper_;
PacketSavingConnection* connection_;
- scoped_ptr<QuicClientSession> session_;
+ scoped_ptr<TestQuicClientSession> session_;
+ QuicClientPushPromiseIndex push_promise_index_;
+ SpdyHeaderBlock push_promise_;
+ string promise_url_;
+ QuicStreamId promised_stream_id_;
+ QuicStreamId associated_stream_id_;
};
INSTANTIATE_TEST_CASE_P(Tests,
- ToolsQuicClientSessionTest,
+ QuicClientSessionTest,
::testing::ValuesIn(QuicSupportedVersions()));
-TEST_P(ToolsQuicClientSessionTest, CryptoConnect) {
+TEST_P(QuicClientSessionTest, CryptoConnect) {
CompleteCryptoHandshake();
}
-TEST_P(ToolsQuicClientSessionTest, NoEncryptionAfterInitialEncryption) {
- ValueRestore<bool> old_flag(&FLAGS_quic_block_unencrypted_writes, true);
+TEST_P(QuicClientSessionTest, NoEncryptionAfterInitialEncryption) {
// Complete a handshake in order to prime the crypto config for 0-RTT.
CompleteCryptoHandshake();
@@ -102,8 +150,8 @@ TEST_P(ToolsQuicClientSessionTest, NoEncryptionAfterInitialEncryption) {
EXPECT_TRUE(session_->IsEncryptionEstablished());
QuicSpdyClientStream* stream =
session_->CreateOutgoingDynamicStream(kDefaultPriority);
- DCHECK_NE(kCryptoStreamId, stream->id());
- EXPECT_TRUE(stream != nullptr);
+ ASSERT_TRUE(stream != nullptr);
+ EXPECT_NE(kCryptoStreamId, stream->id());
// Process an "inchoate" REJ from the server which will cause
// an inchoate CHLO to be sent and will leave the encryption level
@@ -123,13 +171,13 @@ TEST_P(ToolsQuicClientSessionTest, NoEncryptionAfterInitialEncryption) {
char data[] = "hello world";
struct iovec iov = {data, arraysize(data)};
QuicIOVector iovector(&iov, 1, iov.iov_len);
- QuicConsumedData consumed = session_->WritevData(
- stream->id(), iovector, 0, false, MAY_FEC_PROTECT, nullptr);
+ QuicConsumedData consumed =
+ session_->WritevData(stream->id(), iovector, 0, false, nullptr);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_EQ(0u, consumed.bytes_consumed);
}
-TEST_P(ToolsQuicClientSessionTest, MaxNumStreamsWithNoFinOrRst) {
+TEST_P(QuicClientSessionTest, MaxNumStreamsWithNoFinOrRst) {
EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(AnyNumber());
session_->config()->SetMaxStreamsPerConnection(1, 1);
@@ -151,7 +199,7 @@ TEST_P(ToolsQuicClientSessionTest, MaxNumStreamsWithNoFinOrRst) {
EXPECT_FALSE(stream);
}
-TEST_P(ToolsQuicClientSessionTest, MaxNumStreamsWithRst) {
+TEST_P(QuicClientSessionTest, MaxNumStreamsWithRst) {
EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(AnyNumber());
session_->config()->SetMaxStreamsPerConnection(1, 1);
@@ -175,7 +223,7 @@ TEST_P(ToolsQuicClientSessionTest, MaxNumStreamsWithRst) {
EXPECT_TRUE(stream);
}
-TEST_P(ToolsQuicClientSessionTest, GoAwayReceived) {
+TEST_P(QuicClientSessionTest, GoAwayReceived) {
CompleteCryptoHandshake();
// After receiving a GoAway, I should no longer be able to create outgoing
@@ -185,34 +233,12 @@ TEST_P(ToolsQuicClientSessionTest, GoAwayReceived) {
EXPECT_EQ(nullptr, session_->CreateOutgoingDynamicStream(kDefaultPriority));
}
-TEST_P(ToolsQuicClientSessionTest, SetFecProtectionFromConfig) {
- ValueRestore<bool> old_flag(&FLAGS_enable_quic_fec, true);
-
- // Set FEC config in client's connection options.
- QuicTagVector copt;
- copt.push_back(kFHDR);
- session_->config()->SetConnectionOptionsToSend(copt);
-
- // Doing the handshake should set up FEC config correctly.
- CompleteCryptoHandshake();
-
- // Verify that headers stream is always protected and data streams are
- // optionally protected.
- EXPECT_EQ(
- FEC_PROTECT_ALWAYS,
- QuicSpdySessionPeer::GetHeadersStream(session_.get())->fec_policy());
- QuicSpdyClientStream* stream =
- session_->CreateOutgoingDynamicStream(kDefaultPriority);
- ASSERT_TRUE(stream);
- EXPECT_EQ(FEC_PROTECT_OPTIONAL, stream->fec_policy());
-}
-
static bool CheckForDecryptionError(QuicFramer* framer) {
return framer->error() == QUIC_DECRYPTION_FAILURE;
}
// Regression test for b/17206611.
-TEST_P(ToolsQuicClientSessionTest, InvalidPacketReceived) {
+TEST_P(QuicClientSessionTest, InvalidPacketReceived) {
IPEndPoint server_address(TestPeerIPAddress(), kTestPort);
IPEndPoint client_address(TestPeerIPAddress(), kTestPort);
@@ -223,33 +249,33 @@ TEST_P(ToolsQuicClientSessionTest, InvalidPacketReceived) {
EXPECT_CALL(*connection_, OnError(_)).Times(1);
// Verify that empty packets don't close the connection.
- QuicEncryptedPacket zero_length_packet(nullptr, 0, false);
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0);
- session_->connection()->ProcessUdpPacket(client_address, server_address,
- zero_length_packet);
+ QuicReceivedPacket zero_length_packet(nullptr, 0, QuicTime::Zero(), false);
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ session_->ProcessUdpPacket(client_address, server_address,
+ zero_length_packet);
// Verifiy that small, invalid packets don't close the connection.
char buf[2] = {0x00, 0x01};
- QuicEncryptedPacket valid_packet(buf, 2, false);
+ QuicReceivedPacket valid_packet(buf, 2, QuicTime::Zero(), false);
// Close connection shouldn't be called.
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0);
- session_->connection()->ProcessUdpPacket(client_address, server_address,
- valid_packet);
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ session_->ProcessUdpPacket(client_address, server_address, valid_packet);
// Verify that a non-decryptable packet doesn't close the connection.
QuicConnectionId connection_id = session_->connection()->connection_id();
- scoped_ptr<QuicEncryptedPacket> packet(
- ConstructEncryptedPacket(connection_id, false, false, 100, "data"));
+ scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
+ connection_id, false, false, false, kDefaultPathId, 100, "data"));
+ scoped_ptr<QuicReceivedPacket> received(
+ ConstructReceivedPacket(*packet, QuicTime::Zero()));
// Change the last byte of the encrypted data.
- *(const_cast<char*>(packet->data() + packet->length() - 1)) += 1;
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0);
+ *(const_cast<char*>(received->data() + received->length() - 1)) += 1;
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
EXPECT_CALL(*connection_, OnError(Truly(CheckForDecryptionError))).Times(1);
- session_->connection()->ProcessUdpPacket(client_address, server_address,
- *packet);
+ session_->ProcessUdpPacket(client_address, server_address, *received);
}
// A packet with invalid framing should cause a connection to be closed.
-TEST_P(ToolsQuicClientSessionTest, InvalidFramedPacketReceived) {
+TEST_P(QuicClientSessionTest, InvalidFramedPacketReceived) {
IPEndPoint server_address(TestPeerIPAddress(), kTestPort);
IPEndPoint client_address(TestPeerIPAddress(), kTestPort);
@@ -261,14 +287,227 @@ TEST_P(ToolsQuicClientSessionTest, InvalidFramedPacketReceived) {
// Verify that a decryptable packet with bad frames does close the connection.
QuicConnectionId connection_id = session_->connection()->connection_id();
scoped_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket(
- connection_id, false, false, 100, "data", PACKET_8BYTE_CONNECTION_ID,
- PACKET_6BYTE_PACKET_NUMBER, nullptr));
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(1);
- session_->connection()->ProcessUdpPacket(client_address, server_address,
- *packet);
+ connection_id, false, false, false, kDefaultPathId, 100, "data",
+ PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, nullptr));
+ scoped_ptr<QuicReceivedPacket> received(
+ ConstructReceivedPacket(*packet, QuicTime::Zero()));
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1);
+ session_->ProcessUdpPacket(client_address, server_address, *received);
+}
+
+TEST_P(QuicClientSessionTest, PushPromiseOnPromiseHeaders) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+
+ MockQuicSpdyClientStream* stream = static_cast<MockQuicSpdyClientStream*>(
+ session_->CreateOutgoingDynamicStream(kDefaultPriority));
+
+ EXPECT_CALL(*stream, OnPromiseHeaders(_));
+ StringPiece headers_data;
+ session_->OnPromiseHeaders(associated_stream_id_, headers_data);
+}
+
+TEST_P(QuicClientSessionTest, PushPromiseOnPromiseHeadersAlreadyClosed) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+
+ session_->CreateOutgoingDynamicStream(kDefaultPriority);
+
+ EXPECT_CALL(*connection_,
+ SendRstStream(associated_stream_id_, QUIC_REFUSED_STREAM, 0));
+ session_->ResetPromised(associated_stream_id_, QUIC_REFUSED_STREAM);
+
+ StringPiece headers_data;
+ session_->OnPromiseHeaders(associated_stream_id_, headers_data);
+}
+
+TEST_P(QuicClientSessionTest, PushPromiseOnHeadersCompleteAlreadyClosed) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+
+ session_->CreateOutgoingDynamicStream(kDefaultPriority);
+ EXPECT_CALL(*connection_,
+ SendRstStream(associated_stream_id_, QUIC_REFUSED_STREAM, 0));
+ session_->ResetPromised(associated_stream_id_, QUIC_REFUSED_STREAM);
+
+ session_->OnPromiseHeadersComplete(associated_stream_id_, promised_stream_id_,
+ 0);
+}
+
+TEST_P(QuicClientSessionTest, PushPromiseOutOfOrder) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+
+ MockQuicSpdyClientStream* stream = static_cast<MockQuicSpdyClientStream*>(
+ session_->CreateOutgoingDynamicStream(kDefaultPriority));
+
+ EXPECT_CALL(*stream, OnPromiseHeadersComplete(promised_stream_id_, _));
+ session_->OnPromiseHeadersComplete(associated_stream_id_, promised_stream_id_,
+ 0);
+ associated_stream_id_ += 2;
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Received push stream id lesser or equal to the"
+ " last accepted before",
+ _));
+ session_->OnPromiseHeadersComplete(associated_stream_id_, promised_stream_id_,
+ 0);
+}
+
+TEST_P(QuicClientSessionTest, PushPromiseHandlePromise) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+
+ session_->CreateOutgoingDynamicStream(kDefaultPriority);
+
+ session_->HandlePromised(associated_stream_id_, promised_stream_id_,
+ push_promise_);
+
+ EXPECT_NE(session_->GetPromisedById(promised_stream_id_), nullptr);
+ EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
+}
+
+TEST_P(QuicClientSessionTest, PushPromiseAlreadyClosed) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+
+ session_->CreateOutgoingDynamicStream(kDefaultPriority);
+ session_->GetStream(promised_stream_id_);
+
+ EXPECT_CALL(*connection_,
+ SendRstStream(promised_stream_id_, QUIC_REFUSED_STREAM, 0));
+
+ session_->ResetPromised(promised_stream_id_, QUIC_REFUSED_STREAM);
+ SpdyHeaderBlock promise_headers;
+ session_->HandlePromised(associated_stream_id_, promised_stream_id_,
+ promise_headers);
+
+ // Verify that the promise was not created.
+ EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr);
+ EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
+}
+
+TEST_P(QuicClientSessionTest, PushPromiseDuplicateUrl) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+
+ session_->CreateOutgoingDynamicStream(kDefaultPriority);
+
+ session_->HandlePromised(associated_stream_id_, promised_stream_id_,
+ push_promise_);
+
+ EXPECT_NE(session_->GetPromisedById(promised_stream_id_), nullptr);
+ EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
+
+ promised_stream_id_ += 2;
+ EXPECT_CALL(*connection_, SendRstStream(promised_stream_id_,
+ QUIC_DUPLICATE_PROMISE_URL, 0));
+
+ session_->HandlePromised(associated_stream_id_, promised_stream_id_,
+ push_promise_);
+
+ // Verify that the promise was not created.
+ EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr);
+}
+
+TEST_P(QuicClientSessionTest, ReceivingPromiseEnhanceYourCalm) {
+ for (size_t i = 0u; i < session_->get_max_promises(); i++) {
+ push_promise_[":path"] = StringPrintf("/bar%zu", i);
+
+ QuicStreamId id = promised_stream_id_ + i * 2;
+
+ session_->HandlePromised(associated_stream_id_, id, push_promise_);
+
+ // Verify that the promise is in the unclaimed streams map.
+ string promise_url(SpdyUtils::GetUrlFromHeaderBlock(push_promise_));
+ EXPECT_NE(session_->GetPromisedByUrl(promise_url), nullptr);
+ EXPECT_NE(session_->GetPromisedById(id), nullptr);
+ }
+
+ // One more promise, this should be refused.
+ int i = session_->get_max_promises();
+ push_promise_[":path"] = StringPrintf("/bar%d", i);
+
+ QuicStreamId id = promised_stream_id_ + i * 2;
+ EXPECT_CALL(*connection_, SendRstStream(id, QUIC_REFUSED_STREAM, 0));
+ session_->HandlePromised(associated_stream_id_, id, push_promise_);
+
+ // Verify that the promise was not created.
+ string promise_url(SpdyUtils::GetUrlFromHeaderBlock(push_promise_));
+ EXPECT_EQ(session_->GetPromisedById(id), nullptr);
+ EXPECT_EQ(session_->GetPromisedByUrl(promise_url), nullptr);
+}
+
+TEST_P(QuicClientSessionTest, IsClosedTrueAfterResetPromisedAlreadyOpen) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+
+ session_->GetStream(promised_stream_id_);
+ session_->ResetPromised(promised_stream_id_, QUIC_REFUSED_STREAM);
+ EXPECT_TRUE(session_->IsClosedStream(promised_stream_id_));
+}
+
+TEST_P(QuicClientSessionTest, IsClosedTrueAfterResetPromisedNonexistant) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+
+ session_->ResetPromised(promised_stream_id_, QUIC_REFUSED_STREAM);
+ EXPECT_TRUE(session_->IsClosedStream(promised_stream_id_));
+}
+
+TEST_P(QuicClientSessionTest, OnInitialHeadersCompleteIsPush) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+ session_->GetStream(promised_stream_id_);
+ session_->HandlePromised(associated_stream_id_, promised_stream_id_,
+ push_promise_);
+ EXPECT_NE(session_->GetPromisedById(promised_stream_id_), nullptr);
+ EXPECT_NE(session_->GetPromisedStream(promised_stream_id_), nullptr);
+ EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
+
+ session_->OnInitialHeadersComplete(promised_stream_id_, SpdyHeaderBlock());
+}
+
+TEST_P(QuicClientSessionTest, OnInitialHeadersCompleteIsNotPush) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+ session_->CreateOutgoingDynamicStream(kDefaultPriority);
+ session_->OnInitialHeadersComplete(promised_stream_id_, SpdyHeaderBlock());
+}
+
+TEST_P(QuicClientSessionTest, DeletePromised) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+ session_->GetStream(promised_stream_id_);
+ session_->HandlePromised(associated_stream_id_, promised_stream_id_,
+ push_promise_);
+ QuicClientPromisedInfo* promised =
+ session_->GetPromisedById(promised_stream_id_);
+ EXPECT_NE(promised, nullptr);
+ EXPECT_NE(session_->GetPromisedStream(promised_stream_id_), nullptr);
+ EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
+
+ session_->DeletePromised(promised);
+ EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr);
+ EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
+}
+
+TEST_P(QuicClientSessionTest, ResetPromised) {
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+ session_->GetStream(promised_stream_id_);
+ session_->HandlePromised(associated_stream_id_, promised_stream_id_,
+ push_promise_);
+ EXPECT_CALL(*connection_, SendRstStream(promised_stream_id_,
+ QUIC_STREAM_PEER_GOING_AWAY, 0));
+ session_->SendRstStream(promised_stream_id_, QUIC_STREAM_PEER_GOING_AWAY, 0);
+ QuicClientPromisedInfo* promised =
+ session_->GetPromisedById(promised_stream_id_);
+ EXPECT_NE(promised, nullptr);
+ EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
+ EXPECT_EQ(session_->GetPromisedStream(promised_stream_id_), nullptr);
}
} // namespace
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_client_test.cc b/chromium/net/tools/quic/quic_client_test.cc
index 8ab4a65e05e..373a2d81f60 100644
--- a/chromium/net/tools/quic/quic_client_test.cc
+++ b/chromium/net/tools/quic/quic_client_test.cc
@@ -11,13 +11,13 @@
#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 tools {
namespace test {
namespace {
@@ -76,7 +76,30 @@ TEST(QuicClientTest, DoNotLeakFDs) {
EXPECT_EQ(number_of_open_fds, NumOpenFDs());
}
+TEST(QuicClientTest, CreateAndCleanUpUDPSockets) {
+ // Create a ProofVerifier before counting the number of open FDs to work
+ // around some ASAN weirdness.
+ delete CryptoTestUtils::ProofVerifierForTesting();
+
+ EpollServer eps;
+ int number_of_open_fds = NumOpenFDs();
+
+ scoped_ptr<QuicClient> client(
+ CreateAndInitializeQuicClient(&eps, net::test::kTestPort));
+ EXPECT_EQ(number_of_open_fds + 1, NumOpenFDs());
+ // Create more UDP sockets.
+ EXPECT_TRUE(QuicClientPeer::CreateUDPSocketAndBind(client.get()));
+ EXPECT_EQ(number_of_open_fds + 2, NumOpenFDs());
+ EXPECT_TRUE(QuicClientPeer::CreateUDPSocketAndBind(client.get()));
+ EXPECT_EQ(number_of_open_fds + 3, NumOpenFDs());
+
+ // Clean up UDP sockets.
+ QuicClientPeer::CleanUpUDPSocket(client.get(), client->GetLatestFD());
+ EXPECT_EQ(number_of_open_fds + 2, NumOpenFDs());
+ QuicClientPeer::CleanUpUDPSocket(client.get(), client->GetLatestFD());
+ EXPECT_EQ(number_of_open_fds + 1, NumOpenFDs());
+}
+
} // namespace
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_default_packet_writer.cc b/chromium/net/tools/quic/quic_default_packet_writer.cc
index c5e48750c69..66a6440c535 100644
--- a/chromium/net/tools/quic/quic_default_packet_writer.cc
+++ b/chromium/net/tools/quic/quic_default_packet_writer.cc
@@ -7,19 +7,20 @@
#include "net/tools/quic/quic_socket_utils.h"
namespace net {
-namespace tools {
QuicDefaultPacketWriter::QuicDefaultPacketWriter(int fd)
: fd_(fd), write_blocked_(false) {}
QuicDefaultPacketWriter::~QuicDefaultPacketWriter() {}
-WriteResult QuicDefaultPacketWriter::WritePacket(
- const char* buffer,
- size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) {
+WriteResult QuicDefaultPacketWriter::WritePacket(const char* buffer,
+ size_t buf_len,
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) {
DCHECK(!IsWriteBlocked());
+ DCHECK(nullptr == options)
+ << "QuicDefaultPacketWriter does not accept any options.";
WriteResult result = QuicSocketUtils::WritePacket(fd_, buffer, buf_len,
self_address, peer_address);
if (result.status == WRITE_STATUS_BLOCKED) {
@@ -45,5 +46,4 @@ QuicByteCount QuicDefaultPacketWriter::GetMaxPacketSize(
return kMaxPacketSize;
}
-} // namespace tools
} // 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 f423ff0c834..0a8f1093273 100644
--- a/chromium/net/tools/quic/quic_default_packet_writer.h
+++ b/chromium/net/tools/quic/quic_default_packet_writer.h
@@ -15,7 +15,6 @@ namespace net {
struct WriteResult;
-namespace tools {
// Default packet writer which wraps QuicSocketUtils WritePacket.
class QuicDefaultPacketWriter : public QuicPacketWriter {
@@ -26,8 +25,9 @@ class QuicDefaultPacketWriter : public QuicPacketWriter {
// QuicPacketWriter
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) override;
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) override;
bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
@@ -46,7 +46,6 @@ class QuicDefaultPacketWriter : public QuicPacketWriter {
DISALLOW_COPY_AND_ASSIGN(QuicDefaultPacketWriter);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_DEFAULT_PACKET_WRITER_H_
diff --git a/chromium/net/tools/quic/quic_dispatcher.cc b/chromium/net/tools/quic/quic_dispatcher.cc
index a02955b469e..6d08fbe2dd8 100644
--- a/chromium/net/tools/quic/quic_dispatcher.cc
+++ b/chromium/net/tools/quic/quic_dispatcher.cc
@@ -17,12 +17,10 @@
#include "net/tools/quic/quic_simple_server_session.h"
#include "net/tools/quic/quic_time_wait_list_manager.h"
-namespace net {
-
-namespace tools {
-
-using std::make_pair;
using base::StringPiece;
+using std::string;
+
+namespace net {
namespace {
@@ -32,11 +30,7 @@ class DeleteSessionsAlarm : public QuicAlarm::Delegate {
explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher)
: dispatcher_(dispatcher) {}
- QuicTime OnAlarm() override {
- dispatcher_->DeleteSessions();
- // Let the dispatcher register the alarm at appropriate time.
- return QuicTime::Zero();
- }
+ void OnAlarm() override { dispatcher_->DeleteSessions(); }
private:
// Not owned.
@@ -47,109 +41,14 @@ class DeleteSessionsAlarm : public QuicAlarm::Delegate {
} // namespace
-class QuicDispatcher::QuicFramerVisitor : public QuicFramerVisitorInterface {
- public:
- explicit QuicFramerVisitor(QuicDispatcher* dispatcher)
- : dispatcher_(dispatcher), connection_id_(0) {}
-
- // QuicFramerVisitorInterface implementation
- void OnPacket() override {}
- bool OnUnauthenticatedPublicHeader(
- const QuicPacketPublicHeader& header) override {
- connection_id_ = header.connection_id;
- return dispatcher_->OnUnauthenticatedPublicHeader(header);
- }
- bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override {
- dispatcher_->OnUnauthenticatedHeader(header);
- return false;
- }
- void OnError(QuicFramer* framer) override {
- QuicErrorCode error = framer->error();
- dispatcher_->SetLastError(error);
- DVLOG(1) << QuicUtils::ErrorToString(error);
- }
-
- bool OnProtocolVersionMismatch(QuicVersion /*received_version*/) override {
- DVLOG(1) << "Version mismatch, connection ID " << connection_id_;
- // Keep processing after protocol mismatch - this will be dealt with by the
- // time wait list or connection that we will create.
- return true;
- }
-
- // The following methods should never get called because
- // OnUnauthenticatedPublicHeader() or OnUnauthenticatedHeader() (whichever was
- // called last), will return false and prevent a subsequent invocation of
- // these methods. Thus, the payload of the packet is never processed in the
- // dispatcher.
- void OnPublicResetPacket(const QuicPublicResetPacket& /*packet*/) override {
- DCHECK(false);
- }
- void OnVersionNegotiationPacket(
- const QuicVersionNegotiationPacket& /*packet*/) override {
- DCHECK(false);
- }
- void OnDecryptedPacket(EncryptionLevel level) override { DCHECK(false); }
- bool OnPacketHeader(const QuicPacketHeader& /*header*/) override {
- DCHECK(false);
- return false;
- }
- void OnRevivedPacket() override { DCHECK(false); }
- void OnFecProtectedPayload(StringPiece /*payload*/) override {
- DCHECK(false);
- }
- bool OnStreamFrame(const QuicStreamFrame& /*frame*/) override {
- DCHECK(false);
- return false;
- }
- bool OnAckFrame(const QuicAckFrame& /*frame*/) override {
- DCHECK(false);
- return false;
- }
- bool OnStopWaitingFrame(const QuicStopWaitingFrame& /*frame*/) override {
- DCHECK(false);
- return false;
- }
- bool OnPingFrame(const QuicPingFrame& /*frame*/) override {
- DCHECK(false);
- return false;
- }
- bool OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) override {
- DCHECK(false);
- return false;
- }
- bool OnConnectionCloseFrame(
- const QuicConnectionCloseFrame& /*frame*/) override {
- DCHECK(false);
- return false;
- }
- bool OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) override {
- DCHECK(false);
- return false;
- }
- bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& /*frame*/) override {
- DCHECK(false);
- return false;
- }
- bool OnBlockedFrame(const QuicBlockedFrame& frame) override {
- DCHECK(false);
- return false;
- }
- void OnFecData(StringPiece /*redundancy*/) override { DCHECK(false); }
- void OnPacketComplete() override { DCHECK(false); }
-
- private:
- QuicDispatcher* dispatcher_;
-
- // Latched in OnUnauthenticatedPublicHeader for use later.
- QuicConnectionId connection_id_;
-};
-
QuicDispatcher::QuicDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig* crypto_config,
const QuicVersionVector& supported_versions,
QuicConnectionHelperInterface* helper)
: config_(config),
crypto_config_(crypto_config),
+ compressed_certs_cache_(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
helper_(helper),
delete_sessions_alarm_(
helper_->CreateAlarm(new DeleteSessionsAlarm(this))),
@@ -158,9 +57,8 @@ QuicDispatcher::QuicDispatcher(const QuicConfig& config,
framer_(supported_versions,
/*unused*/ QuicTime::Zero(),
Perspective::IS_SERVER),
- framer_visitor_(new QuicFramerVisitor(this)),
last_error_(QUIC_NO_ERROR) {
- framer_.set_visitor(framer_visitor_.get());
+ framer_.set_visitor(this);
}
QuicDispatcher::~QuicDispatcher() {
@@ -176,7 +74,7 @@ void QuicDispatcher::InitializeWithWriter(QuicPacketWriter* writer) {
void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address,
const IPEndPoint& client_address,
- const QuicEncryptedPacket& packet) {
+ const QuicReceivedPacket& packet) {
current_server_address_ = server_address;
current_client_address_ = client_address;
current_packet_ = &packet;
@@ -190,6 +88,8 @@ void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address,
bool QuicDispatcher::OnUnauthenticatedPublicHeader(
const QuicPacketPublicHeader& header) {
+ current_connection_id_ = header.connection_id;
+
// Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC.
// Given that we can't even send a reply rejecting the packet, just drop the
// packet.
@@ -210,8 +110,8 @@ bool QuicDispatcher::OnUnauthenticatedPublicHeader(
QuicConnectionId connection_id = header.connection_id;
SessionMap::iterator it = session_map_.find(connection_id);
if (it != session_map_.end()) {
- it->second->connection()->ProcessUdpPacket(
- current_server_address_, current_client_address_, *current_packet_);
+ it->second->ProcessUdpPacket(current_server_address_,
+ current_client_address_, *current_packet_);
return false;
}
@@ -237,12 +137,24 @@ bool QuicDispatcher::OnUnauthenticatedPublicHeader(
if (framer_.IsSupportedVersion(packet_version)) {
version = packet_version;
} else {
- // Packets set to be processed but having an unsupported version will
- // cause a connection to be created. The connection will handle
- // sending a version negotiation packet.
- // TODO(ianswett): This will malfunction if the full header of the packet
- // causes a parsing error when parsed using the server's preferred
- // version.
+ if (FLAGS_quic_stateless_version_negotiation) {
+ if (ShouldCreateSessionForUnknownVersion(framer_.last_version_tag())) {
+ return true;
+ }
+ // Since the version is not supported, send a version negotiation
+ // packet and stop processing the current packet.
+ time_wait_list_manager()->SendVersionNegotiationPacket(
+ connection_id, supported_versions_, current_server_address_,
+ current_client_address_);
+ return false;
+ } else {
+ // Packets set to be processed but having an unsupported version will
+ // cause a connection to be created. The connection will handle
+ // sending a version negotiation packet.
+ // TODO(ianswett): This will malfunction if the full header of the
+ // packet causes a parsing error when parsed using the server's
+ // preferred version.
+ }
}
}
// Set the framer's version and continue processing.
@@ -250,7 +162,7 @@ bool QuicDispatcher::OnUnauthenticatedPublicHeader(
return true;
}
-void QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
+bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
QuicConnectionId connection_id = header.public_header.connection_id;
if (time_wait_list_manager_->IsConnectionIdInTimeWait(
@@ -260,7 +172,7 @@ void QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
current_server_address_, current_client_address_,
header.public_header.connection_id, header.packet_number,
*current_packet_);
- return;
+ return false;
}
// Packet's connection ID is unknown.
@@ -273,8 +185,8 @@ void QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
CreateQuicSession(connection_id, current_client_address_);
DVLOG(1) << "Created new session for " << connection_id;
session_map_.insert(std::make_pair(connection_id, session));
- session->connection()->ProcessUdpPacket(
- current_server_address_, current_client_address_, *current_packet_);
+ session->ProcessUdpPacket(current_server_address_,
+ current_client_address_, *current_packet_);
break;
}
case kFateTimeWait:
@@ -296,6 +208,8 @@ void QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
// Do nothing with the packet.
break;
}
+
+ return false;
}
QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
@@ -369,8 +283,9 @@ bool QuicDispatcher::HasPendingWrites() const {
void QuicDispatcher::Shutdown() {
while (!session_map_.empty()) {
QuicServerSessionBase* session = session_map_.begin()->second;
- session->connection()->SendConnectionCloseWithDetails(
- QUIC_PEER_GOING_AWAY, "Server shutdown imminent");
+ session->connection()->CloseConnection(
+ QUIC_PEER_GOING_AWAY, "Server shutdown imminent",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
// Validate that the session removes itself from the session map on close.
DCHECK(session_map_.empty() || session_map_.begin()->second != session);
}
@@ -378,7 +293,8 @@ void QuicDispatcher::Shutdown() {
}
void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id,
- QuicErrorCode error) {
+ QuicErrorCode error,
+ const string& error_details) {
SessionMap::iterator it = session_map_.find(connection_id);
if (it == session_map_.end()) {
QUIC_BUG << "ConnectionId " << connection_id
@@ -390,7 +306,8 @@ void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id,
DVLOG_IF(1, error != QUIC_NO_ERROR)
<< "Closing connection (" << connection_id
- << ") due to error: " << QuicUtils::ErrorToString(error);
+ << ") due to error: " << QuicUtils::ErrorToString(error)
+ << ", with details: " << error_details;
if (closed_session_list_.empty()) {
delete_sessions_alarm_->Cancel();
@@ -405,8 +322,8 @@ void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id,
void QuicDispatcher::OnWriteBlocked(
QuicBlockedWriterInterface* blocked_writer) {
if (!writer_->IsWriteBlocked()) {
- LOG(DFATAL) << "QuicDispatcher::OnWriteBlocked called when the writer is "
- "not blocked.";
+ QUIC_BUG << "QuicDispatcher::OnWriteBlocked called when the writer is "
+ "not blocked.";
// Return without adding the connection to the blocked list, to avoid
// infinite loops in OnCanWrite.
return;
@@ -424,6 +341,109 @@ void QuicDispatcher::OnConnectionRemovedFromTimeWaitList(
DVLOG(1) << "Connection " << connection_id << " removed from time wait list.";
}
+void QuicDispatcher::OnPacket() {}
+
+void QuicDispatcher::OnError(QuicFramer* framer) {
+ QuicErrorCode error = framer->error();
+ SetLastError(error);
+ DVLOG(1) << QuicUtils::ErrorToString(error);
+}
+
+bool QuicDispatcher::ShouldCreateSessionForUnknownVersion(QuicTag version_tag) {
+ return false;
+}
+
+bool QuicDispatcher::OnProtocolVersionMismatch(
+ QuicVersion /*received_version*/) {
+ if (FLAGS_quic_stateless_version_negotiation) {
+ QUIC_BUG_IF(
+ !time_wait_list_manager_->IsConnectionIdInTimeWait(
+ current_connection_id_) &&
+ !ShouldCreateSessionForUnknownVersion(framer_.last_version_tag()))
+ << "Unexpected version mismatch: "
+ << QuicUtils::TagToString(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.
+ return true;
+}
+
+void QuicDispatcher::OnPublicResetPacket(
+ const QuicPublicResetPacket& /*packet*/) {
+ DCHECK(false);
+}
+
+void QuicDispatcher::OnVersionNegotiationPacket(
+ const QuicVersionNegotiationPacket& /*packet*/) {
+ DCHECK(false);
+}
+
+void QuicDispatcher::OnDecryptedPacket(EncryptionLevel level) {
+ DCHECK(false);
+}
+
+bool QuicDispatcher::OnPacketHeader(const QuicPacketHeader& /*header*/) {
+ DCHECK(false);
+ return false;
+}
+
+bool QuicDispatcher::OnStreamFrame(const QuicStreamFrame& /*frame*/) {
+ DCHECK(false);
+ return false;
+}
+
+bool QuicDispatcher::OnAckFrame(const QuicAckFrame& /*frame*/) {
+ DCHECK(false);
+ return false;
+}
+
+bool QuicDispatcher::OnStopWaitingFrame(const QuicStopWaitingFrame& /*frame*/) {
+ DCHECK(false);
+ return false;
+}
+
+bool QuicDispatcher::OnPingFrame(const QuicPingFrame& /*frame*/) {
+ DCHECK(false);
+ return false;
+}
+
+bool QuicDispatcher::OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) {
+ DCHECK(false);
+ return false;
+}
+
+bool QuicDispatcher::OnConnectionCloseFrame(
+ const QuicConnectionCloseFrame& /*frame*/) {
+ DCHECK(false);
+ return false;
+}
+
+bool QuicDispatcher::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) {
+ DCHECK(false);
+ return false;
+}
+
+bool QuicDispatcher::OnWindowUpdateFrame(
+ const QuicWindowUpdateFrame& /*frame*/) {
+ DCHECK(false);
+ return false;
+}
+
+bool QuicDispatcher::OnBlockedFrame(const QuicBlockedFrame& frame) {
+ DCHECK(false);
+ return false;
+}
+
+bool QuicDispatcher::OnPathCloseFrame(const QuicPathCloseFrame& frame) {
+ DCHECK(false);
+ return false;
+}
+
+void QuicDispatcher::OnPacketComplete() {
+ DCHECK(false);
+}
+
QuicServerSessionBase* QuicDispatcher::CreateQuicSession(
QuicConnectionId connection_id,
const IPEndPoint& client_address) {
@@ -432,18 +452,14 @@ QuicServerSessionBase* QuicDispatcher::CreateQuicSession(
connection_id, client_address, helper_.get(), CreatePerConnectionWriter(),
/* owns_writer= */ true, Perspective::IS_SERVER, supported_versions_);
- QuicServerSessionBase* session =
- new QuicSimpleServerSession(config_, connection, this, crypto_config_);
+ QuicServerSessionBase* session = new QuicSimpleServerSession(
+ config_, connection, this, crypto_config_, &compressed_certs_cache_);
session->Initialize();
return session;
}
QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
- // TODO(rjshade): The QuicTimeWaitListManager should take ownership of the
- // per-connection packet writer.
- time_wait_list_writer_.reset(CreatePerConnectionWriter());
- return new QuicTimeWaitListManager(time_wait_list_writer_.get(), this,
- helper_.get());
+ return new QuicTimeWaitListManager(writer_.get(), this, helper_.get());
}
bool QuicDispatcher::HandlePacketForTimeWait(
@@ -471,5 +487,4 @@ void QuicDispatcher::SetLastError(QuicErrorCode error) {
last_error_ = error;
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_dispatcher.h b/chromium/net/tools/quic/quic_dispatcher.h
index 3c5b9c90307..763280a8a47 100644
--- a/chromium/net/tools/quic/quic_dispatcher.h
+++ b/chromium/net/tools/quic/quic_dispatcher.h
@@ -8,6 +8,7 @@
#ifndef NET_TOOLS_QUIC_QUIC_DISPATCHER_H_
#define NET_TOOLS_QUIC_QUIC_DISPATCHER_H_
+#include <unordered_map>
#include <vector>
#include "base/containers/hash_tables.h"
@@ -15,9 +16,11 @@
#include "base/memory/scoped_ptr.h"
#include "net/base/ip_endpoint.h"
#include "net/base/linked_hash_map.h"
+#include "net/quic/crypto/quic_compressed_certs_cache.h"
#include "net/quic/quic_blocked_writer_interface.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_protocol.h"
+#include "net/tools/quic/quic_process_packet_interface.h"
#include "net/tools/quic/quic_server_session_base.h"
#include "net/tools/quic/quic_time_wait_list_manager.h"
@@ -27,26 +30,20 @@ class QuicConfig;
class QuicCryptoServerConfig;
class QuicServerSessionBase;
-namespace tools {
-
namespace test {
class QuicDispatcherPeer;
} // namespace test
-class ProcessPacketInterface {
- public:
- virtual ~ProcessPacketInterface() {}
- virtual void ProcessPacket(const IPEndPoint& server_address,
- const IPEndPoint& client_address,
- const QuicEncryptedPacket& packet) = 0;
-};
-
class QuicDispatcher : public QuicServerSessionVisitor,
public ProcessPacketInterface,
- public QuicBlockedWriterInterface {
+ public QuicBlockedWriterInterface,
+ public QuicFramerVisitorInterface {
public:
// Ideally we'd have a linked_hash_set: the boolean is unused.
- typedef linked_hash_map<QuicBlockedWriterInterface*, bool> WriteBlockedList;
+ typedef linked_hash_map<QuicBlockedWriterInterface*,
+ bool,
+ QuicBlockedWriterInterfacePtrHash>
+ WriteBlockedList;
// Due to the way delete_sessions_closure_ is registered, the Dispatcher must
// live until server Shutdown. |supported_versions| specifies the std::list
@@ -66,7 +63,7 @@ class QuicDispatcher : public QuicServerSessionVisitor,
// an existing session, or passing it to the time wait list.
void ProcessPacket(const IPEndPoint& server_address,
const IPEndPoint& client_address,
- const QuicEncryptedPacket& packet) override;
+ const QuicReceivedPacket& packet) override;
// Called when the socket becomes writable to allow queued writes to happen.
void OnCanWrite() override;
@@ -80,7 +77,8 @@ class QuicDispatcher : public QuicServerSessionVisitor,
// QuicServerSessionVisitor interface implementation:
// Ensure that the closed connection is cleaned up asynchronously.
void OnConnectionClosed(QuicConnectionId connection_id,
- QuicErrorCode error) override;
+ QuicErrorCode error,
+ const std::string& error_details) override;
// Queues the blocked writer for later resumption.
void OnWriteBlocked(QuicBlockedWriterInterface* blocked_writer) override;
@@ -94,7 +92,8 @@ class QuicDispatcher : public QuicServerSessionVisitor,
void OnConnectionRemovedFromTimeWaitList(
QuicConnectionId connection_id) override;
- typedef base::hash_map<QuicConnectionId, QuicServerSessionBase*> SessionMap;
+ typedef std::unordered_map<QuicConnectionId, QuicServerSessionBase*>
+ SessionMap;
const SessionMap& session_map() const { return session_map_; }
@@ -112,15 +111,45 @@ class QuicDispatcher : public QuicServerSessionVisitor,
"kMaxReasonableInitialPacketNumber is unreasonably small "
"relative to kInitialCongestionWindow.");
+ // QuicFramerVisitorInterface implementation. Not expected to be called
+ // outside of this class.
+ void OnPacket() override;
+ // Called when the public header has been parsed.
+ bool OnUnauthenticatedPublicHeader(
+ const QuicPacketPublicHeader& header) override;
+ // Called when the private header has been parsed of a data packet that is
+ // destined for the time wait manager.
+ bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
+ void OnError(QuicFramer* framer) override;
+ bool OnProtocolVersionMismatch(QuicVersion received_version) override;
+
+ // The following methods should never get called because
+ // OnUnauthenticatedPublicHeader() or OnUnauthenticatedHeader() (whichever
+ // was called last), will return false and prevent a subsequent invocation
+ // of these methods. Thus, the payload of the packet is never processed in
+ // the dispatcher.
+ void OnPublicResetPacket(const QuicPublicResetPacket& packet) override;
+ void OnVersionNegotiationPacket(
+ const QuicVersionNegotiationPacket& packet) override;
+ void OnDecryptedPacket(EncryptionLevel level) override;
+ bool OnPacketHeader(const QuicPacketHeader& header) override;
+ bool OnStreamFrame(const QuicStreamFrame& frame) override;
+ bool OnAckFrame(const QuicAckFrame& frame) override;
+ bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override;
+ bool OnPingFrame(const QuicPingFrame& frame) override;
+ bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override;
+ bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override;
+ bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
+ bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
+ bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
+ bool OnPathCloseFrame(const QuicPathCloseFrame& frame) override;
+ void OnPacketComplete() override;
+
protected:
virtual QuicServerSessionBase* CreateQuicSession(
QuicConnectionId connection_id,
const IPEndPoint& client_address);
- // Called by |framer_visitor_| when the public header has been parsed.
- virtual bool OnUnauthenticatedPublicHeader(
- const QuicPacketPublicHeader& header);
-
// Values to be returned by ValidityChecks() to indicate what should be done
// with a packet. Fates with greater values are considered to be higher
// priority, in that if one validity check indicates a lower-valued fate and
@@ -154,12 +183,16 @@ class QuicDispatcher : public QuicServerSessionVisitor,
const IPEndPoint& current_server_address() { return current_server_address_; }
const IPEndPoint& current_client_address() { return current_client_address_; }
- const QuicEncryptedPacket& current_packet() { return *current_packet_; }
+ const QuicReceivedPacket& current_packet() { return *current_packet_; }
const QuicConfig& config() const { return config_; }
const QuicCryptoServerConfig* crypto_config() const { return crypto_config_; }
+ QuicCompressedCertsCache* compressed_certs_cache() {
+ return &compressed_certs_cache_;
+ }
+
QuicFramer* framer() { return &framer_; }
QuicConnectionHelperInterface* helper() { return helper_.get(); }
@@ -173,15 +206,14 @@ class QuicDispatcher : public QuicServerSessionVisitor,
// cleaned up for bug 16950226.)
virtual QuicPacketWriter* CreatePerConnectionWriter();
+ // Returns true if a session should be created for a connection with an
+ // unknown version identified by |version_tag|.
+ virtual bool ShouldCreateSessionForUnknownVersion(QuicTag version_tag);
+
void SetLastError(QuicErrorCode error);
private:
- class QuicFramerVisitor;
- friend class net::tools::test::QuicDispatcherPeer;
-
- // Called by |framer_visitor_| when the private header has been parsed
- // of a data packet that is destined for the time wait manager.
- void OnUnauthenticatedHeader(const QuicPacketHeader& header);
+ friend class net::test::QuicDispatcherPeer;
// Removes the session from the session map and write blocked list, and adds
// the ConnectionId to the time-wait list. If |session_closed_statelessly| is
@@ -194,6 +226,9 @@ class QuicDispatcher : public QuicServerSessionVisitor,
const QuicCryptoServerConfig* crypto_config_;
+ // The cache for most recently compressed certs.
+ QuicCompressedCertsCache compressed_certs_cache_;
+
// The list of connections waiting to write.
WriteBlockedList write_blocked_list_;
@@ -214,9 +249,6 @@ class QuicDispatcher : public QuicServerSessionVisitor,
// The writer to write to the socket with.
scoped_ptr<QuicPacketWriter> writer_;
- // A per-connection writer that is passed to the time wait list manager.
- scoped_ptr<QuicPacketWriter> time_wait_list_writer_;
-
// 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
@@ -226,10 +258,10 @@ class QuicDispatcher : public QuicServerSessionVisitor,
// Information about the packet currently being handled.
IPEndPoint current_client_address_;
IPEndPoint current_server_address_;
- const QuicEncryptedPacket* current_packet_;
+ const QuicReceivedPacket* current_packet_;
+ QuicConnectionId current_connection_id_;
QuicFramer framer_;
- scoped_ptr<QuicFramerVisitor> framer_visitor_;
// The last error set by SetLastError(), which is called by
// framer_visitor_->OnError().
@@ -238,7 +270,6 @@ class QuicDispatcher : public QuicServerSessionVisitor,
DISALLOW_COPY_AND_ASSIGN(QuicDispatcher);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_DISPATCHER_H_
diff --git a/chromium/net/tools/quic/quic_dispatcher_test.cc b/chromium/net/tools/quic/quic_dispatcher_test.cc
index bbf797eeefc..a8c8ab4561e 100644
--- a/chromium/net/tools/quic/quic_dispatcher_test.cc
+++ b/chromium/net/tools/quic/quic_dispatcher_test.cc
@@ -43,7 +43,6 @@ using testing::WithoutArgs;
using testing::_;
namespace net {
-namespace tools {
namespace test {
namespace {
@@ -51,19 +50,30 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase {
public:
TestQuicSpdyServerSession(const QuicConfig& config,
QuicConnection* connection,
- const QuicCryptoServerConfig* crypto_config)
- : QuicServerSessionBase(config, connection, nullptr, crypto_config),
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache)
+ : QuicServerSessionBase(config,
+ connection,
+ nullptr,
+ crypto_config,
+ compressed_certs_cache),
crypto_stream_(QuicServerSessionBase::GetCryptoStream()) {}
~TestQuicSpdyServerSession() override{};
- MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer));
+ MOCK_METHOD3(OnConnectionClosed,
+ void(QuicErrorCode error,
+ const string& error_details,
+ ConnectionCloseSource source));
MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id));
MOCK_METHOD1(CreateOutgoingDynamicStream,
QuicSpdyStream*(SpdyPriority priority));
QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
- const QuicCryptoServerConfig* crypto_config) override {
- return new QuicCryptoServerStream(crypto_config, this);
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache) override {
+ return new QuicCryptoServerStream(
+ crypto_config, compressed_certs_cache,
+ FLAGS_enable_quic_stateless_reject_support, this);
}
void SetCryptoStream(QuicCryptoServerStream* crypto_stream) {
@@ -85,10 +95,11 @@ class TestDispatcher : public QuicDispatcher {
TestDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig* crypto_config,
EpollServer* eps)
- : QuicDispatcher(config,
- crypto_config,
- QuicSupportedVersions(),
- new QuicEpollConnectionHelper(eps)) {}
+ : QuicDispatcher(
+ config,
+ crypto_config,
+ QuicSupportedVersions(),
+ new QuicEpollConnectionHelper(eps, QuicAllocator::BUFFER_POOL)) {}
MOCK_METHOD2(CreateQuicSession,
QuicServerSessionBase*(QuicConnectionId connection_id,
@@ -112,7 +123,8 @@ class MockServerConnection : public MockConnection {
void UnregisterOnConnectionClosed() {
LOG(ERROR) << "Unregistering " << connection_id();
- dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR);
+ dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR,
+ "Unregistering.");
}
private:
@@ -126,12 +138,14 @@ QuicServerSessionBase* CreateSession(
const IPEndPoint& client_address,
MockConnectionHelper* helper,
const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
TestQuicSpdyServerSession** session) {
MockServerConnection* connection =
new MockServerConnection(connection_id, helper, dispatcher);
- *session = new TestQuicSpdyServerSession(config, connection, crypto_config);
+ *session = new TestQuicSpdyServerSession(config, connection, crypto_config,
+ compressed_certs_cache);
connection->set_visitor(*session);
- ON_CALL(*connection, SendConnectionCloseWithDetails(_, _))
+ ON_CALL(*connection, CloseConnection(_, _, _))
.WillByDefault(WithoutArgs(Invoke(
connection, &MockServerConnection::UnregisterOnConnectionClosed)));
EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()),
@@ -143,7 +157,7 @@ QuicServerSessionBase* CreateSession(
class QuicDispatcherTest : public ::testing::Test {
public:
QuicDispatcherTest()
- : helper_(&eps_),
+ : helper_(&eps_, QuicAllocator::BUFFER_POOL),
crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance(),
CryptoTestUtils::ProofSourceForTesting()),
@@ -164,36 +178,67 @@ class QuicDispatcherTest : public ::testing::Test {
return reinterpret_cast<MockConnection*>(session2_->connection());
}
+ // 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,
QuicConnectionId connection_id,
bool has_version_flag,
+ bool has_multipath_flag,
const string& data) {
- ProcessPacket(client_address, connection_id, has_version_flag, data,
- PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER);
+ ProcessPacket(client_address, connection_id, has_version_flag,
+ has_multipath_flag, data, PACKET_8BYTE_CONNECTION_ID,
+ PACKET_6BYTE_PACKET_NUMBER);
}
+ // Process a packet with a default path id, and packet number 1,
+ // using the first supported version.
void ProcessPacket(IPEndPoint client_address,
QuicConnectionId connection_id,
bool has_version_flag,
+ bool has_multipath_flag,
const string& data,
QuicConnectionIdLength connection_id_length,
QuicPacketNumberLength packet_number_length) {
- ProcessPacket(client_address, connection_id, has_version_flag, data,
- connection_id_length, packet_number_length, 1);
+ ProcessPacket(client_address, connection_id, has_version_flag,
+ has_multipath_flag, data, connection_id_length,
+ packet_number_length, kDefaultPathId, 1);
}
+ // Process a packet using the first supported version.
void ProcessPacket(IPEndPoint client_address,
QuicConnectionId connection_id,
bool has_version_flag,
+ bool has_multipath_flag,
const string& data,
QuicConnectionIdLength connection_id_length,
QuicPacketNumberLength packet_number_length,
+ QuicPathId path_id,
QuicPacketNumber packet_number) {
+ ProcessPacket(client_address, connection_id, has_version_flag,
+ QuicSupportedVersions().front(), data, connection_id_length,
+ packet_number_length, packet_number);
+ }
+
+ // Processes a packet.
+ void ProcessPacket(IPEndPoint client_address,
+ QuicConnectionId connection_id,
+ bool has_version_flag,
+ QuicVersion version,
+ const string& data,
+ QuicConnectionIdLength connection_id_length,
+ QuicPacketNumberLength packet_number_length,
+ QuicPacketNumber packet_number) {
+ QuicVersionVector versions(SupportedVersions(version));
scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
- connection_id, has_version_flag, false, packet_number, data,
- connection_id_length, packet_number_length));
+ connection_id, has_version_flag, false, false, 0, packet_number, data,
+ connection_id_length, packet_number_length, &versions));
+ scoped_ptr<QuicReceivedPacket> received_packet(
+ ConstructReceivedPacket(*packet, helper_.GetClock()->Now()));
+
data_ = string(packet->data(), packet->length());
- dispatcher_.ProcessPacket(server_address_, client_address, *packet);
+ dispatcher_.ProcessPacket(server_address_, client_address,
+ *received_packet);
}
void ValidatePacket(const QuicEncryptedPacket& packet) {
@@ -227,39 +272,68 @@ TEST_F(QuicDispatcherTest, ProcessPackets) {
server_address_ = IPEndPoint(net::test::Any4(), 5);
EXPECT_CALL(dispatcher_, CreateQuicSession(1, client_address))
- .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1,
- client_address, &mock_helper_,
- &crypto_config_, &session1_)));
- ProcessPacket(client_address, 1, true, "foo");
+ .WillOnce(testing::Return(CreateSession(
+ &dispatcher_, config_, 1, client_address, &mock_helper_,
+ &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_),
+ &session1_)));
+ ProcessPacket(client_address, 1, true, false, "foo");
EXPECT_EQ(client_address, dispatcher_.current_client_address());
EXPECT_EQ(server_address_, dispatcher_.current_server_address());
EXPECT_CALL(dispatcher_, CreateQuicSession(2, client_address))
- .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 2,
- client_address, &mock_helper_,
- &crypto_config_, &session2_)));
- ProcessPacket(client_address, 2, true, "bar");
+ .WillOnce(testing::Return(CreateSession(
+ &dispatcher_, config_, 2, client_address, &mock_helper_,
+ &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_),
+ &session2_)));
+ ProcessPacket(client_address, 2, true, false, "bar");
EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.Times(1)
.WillOnce(testing::WithArgs<2>(
Invoke(this, &QuicDispatcherTest::ValidatePacket)));
- ProcessPacket(client_address, 1, false, "eep");
+ ProcessPacket(client_address, 1, false, false, "eep");
+}
+
+TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
+ ValueRestore<bool> old_flag(&FLAGS_quic_stateless_version_negotiation, true);
+ IPEndPoint client_address(net::test::Loopback4(), 1);
+ server_address_ = IPEndPoint(net::test::Any4(), 5);
+
+ EXPECT_CALL(dispatcher_, CreateQuicSession(1, client_address)).Times(0);
+ QuicVersion version = static_cast<QuicVersion>(QuicVersionMin() - 1);
+ ProcessPacket(client_address, 1, true, version, "foo",
+ PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, 1);
+}
+
+TEST_F(QuicDispatcherTest, StatefulVersionNegotiation) {
+ ValueRestore<bool> old_flag(&FLAGS_quic_stateless_version_negotiation, false);
+ IPEndPoint client_address(net::test::Loopback4(), 1);
+ server_address_ = IPEndPoint(net::test::Any4(), 5);
+
+ EXPECT_CALL(dispatcher_, CreateQuicSession(1, client_address))
+ .WillOnce(testing::Return(CreateSession(
+ &dispatcher_, config_, 1, client_address, &mock_helper_,
+ &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_),
+ &session1_)));
+ QuicVersion version = static_cast<QuicVersion>(QuicVersionMin() - 1);
+ ProcessPacket(client_address, 1, true, version, "foo",
+ PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, 1);
}
TEST_F(QuicDispatcherTest, Shutdown) {
IPEndPoint client_address(net::test::Loopback4(), 1);
EXPECT_CALL(dispatcher_, CreateQuicSession(_, client_address))
- .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1,
- client_address, &mock_helper_,
- &crypto_config_, &session1_)));
+ .WillOnce(testing::Return(CreateSession(
+ &dispatcher_, config_, 1, client_address, &mock_helper_,
+ &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_),
+ &session1_)));
- ProcessPacket(client_address, 1, true, "foo");
+ ProcessPacket(client_address, 1, true, false, "foo");
EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
- SendConnectionCloseWithDetails(QUIC_PEER_GOING_AWAY, _));
+ CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
dispatcher_.Shutdown();
}
@@ -271,10 +345,11 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
IPEndPoint client_address(net::test::Loopback4(), 1);
QuicConnectionId connection_id = 1;
EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, client_address))
- .WillOnce(testing::Return(
- CreateSession(&dispatcher_, config_, connection_id, client_address,
- &mock_helper_, &crypto_config_, &session1_)));
- ProcessPacket(client_address, connection_id, true, "foo");
+ .WillOnce(testing::Return(CreateSession(
+ &dispatcher_, config_, connection_id, client_address, &mock_helper_,
+ &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_),
+ &session1_)));
+ ProcessPacket(client_address, connection_id, true, false, "foo");
// Close the connection by sending public reset packet.
QuicPublicResetPacket packet;
@@ -285,7 +360,10 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
packet.nonce_proof = 132232;
scoped_ptr<QuicEncryptedPacket> encrypted(
QuicFramer::BuildPublicResetPacket(packet));
- EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET, true))
+ scoped_ptr<QuicReceivedPacket> received(
+ ConstructReceivedPacket(*encrypted, helper_.GetClock()->Now()));
+ EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET, _,
+ ConnectionCloseSource::FROM_PEER))
.Times(1)
.WillOnce(WithoutArgs(Invoke(
reinterpret_cast<MockServerConnection*>(session1_->connection()),
@@ -295,7 +373,7 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
.WillOnce(
Invoke(reinterpret_cast<MockConnection*>(session1_->connection()),
&MockConnection::ReallyProcessUdpPacket));
- dispatcher_.ProcessPacket(IPEndPoint(), client_address, *encrypted);
+ dispatcher_.ProcessPacket(IPEndPoint(), client_address, *received);
EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
// Dispatcher forwards subsequent packets for this connection_id to the time
@@ -305,7 +383,7 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
.Times(1);
EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
.Times(0);
- ProcessPacket(client_address, connection_id, true, "foo");
+ ProcessPacket(client_address, connection_id, true, false, "foo");
}
TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
@@ -321,15 +399,19 @@ TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
.Times(1);
EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
.Times(1);
- ProcessPacket(client_address, connection_id, false, "data");
+ ProcessPacket(client_address, connection_id, false, false, "data");
}
// Enables mocking of the handshake-confirmation for stateless rejects.
class MockQuicCryptoServerStream : public QuicCryptoServerStream {
public:
MockQuicCryptoServerStream(const QuicCryptoServerConfig& crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
QuicSession* session)
- : QuicCryptoServerStream(&crypto_config, session) {}
+ : QuicCryptoServerStream(&crypto_config,
+ compressed_certs_cache,
+ FLAGS_enable_quic_stateless_reject_support,
+ session) {}
void set_handshake_confirmed_for_testing(bool handshake_confirmed) {
handshake_confirmed_ = handshake_confirmed;
}
@@ -414,9 +496,11 @@ class QuicDispatcherStatelessRejectTest
QuicConnectionId connection_id,
const IPEndPoint& client_address) {
CreateSession(&dispatcher_, config_, connection_id, client_address,
- &mock_helper_, &crypto_config_, &session1_);
+ &mock_helper_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(&dispatcher_), &session1_);
- crypto_stream1_ = new MockQuicCryptoServerStream(crypto_config_, session1_);
+ crypto_stream1_ = new MockQuicCryptoServerStream(
+ crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_), session1_);
session1_->SetCryptoStream(crypto_stream1_);
crypto_stream1_->set_handshake_confirmed_for_testing(
GetParam().crypto_handshake_successful);
@@ -439,7 +523,7 @@ TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
.Times(0);
- ProcessPacket(client_address, 1, true, "foo");
+ ProcessPacket(client_address, 1, true, false, "foo");
}
TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
@@ -448,13 +532,15 @@ TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
server_address_ = IPEndPoint(net::test::Any4(), 5);
EXPECT_CALL(dispatcher_, CreateQuicSession(1, client_address))
- .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1,
- client_address, &mock_helper_,
- &crypto_config_, &session1_)));
+ .WillOnce(testing::Return(CreateSession(
+ &dispatcher_, config_, 1, client_address, &mock_helper_,
+ &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_),
+ &session1_)));
// A packet whose packet number is the largest that is allowed to start a
// connection.
- ProcessPacket(client_address, connection_id, true, "data",
+ ProcessPacket(client_address, connection_id, true, false, "data",
PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER,
+ kDefaultPathId,
QuicDispatcher::kMaxReasonableInitialPacketNumber);
EXPECT_EQ(client_address, dispatcher_.current_client_address());
EXPECT_EQ(server_address_, dispatcher_.current_server_address());
@@ -475,8 +561,9 @@ TEST_F(QuicDispatcherTest, TooBigSeqNoPacketToTimeWaitListManager) {
.Times(1);
// A packet whose packet number is one to large to be allowed to start a
// connection.
- ProcessPacket(client_address, connection_id, true, "data",
+ ProcessPacket(client_address, connection_id, true, false, "data",
PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER,
+ kDefaultPathId,
QuicDispatcher::kMaxReasonableInitialPacketNumber + 1);
}
@@ -497,17 +584,13 @@ TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) {
CreateSessionBasedOnTestParams(connection_id, client_address)));
// Process the first packet for the connection.
- ProcessPacket(client_address, connection_id, true, "foo");
+ ProcessPacket(client_address, connection_id, true, false, "foo");
if (ExpectStatelessReject()) {
// If this is a stateless reject, the crypto stream will close the
// connection.
- EXPECT_CALL(*session1_, OnConnectionClosed(_, _))
- .Times(1)
- .WillOnce(WithoutArgs(Invoke(
- reinterpret_cast<MockServerConnection*>(session1_->connection()),
- &MockServerConnection::UnregisterOnConnectionClosed)));
session1_->connection()->CloseConnection(
- QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, /* from_peer */ false);
+ QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject",
+ ConnectionCloseBehavior::SILENT_CLOSE);
}
// Send a second packet and check the results. If this is a stateless reject,
@@ -527,7 +610,7 @@ TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) {
.WillOnce(testing::WithArgs<2>(
Invoke(this, &QuicDispatcherTest::ValidatePacket)));
}
- ProcessPacket(client_address, connection_id, true, "foo");
+ ProcessPacket(client_address, connection_id, true, false, "foo");
}
// Verify the stopgap test: Packets with truncated connection IDs should be
@@ -552,7 +635,7 @@ TEST_P(QuicDispatcherTestStrayPacketConnectionId,
.Times(0);
EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
.Times(0);
- ProcessPacket(client_address, connection_id, true, "data",
+ ProcessPacket(client_address, connection_id, true, false, "data",
connection_id_length, PACKET_6BYTE_PACKET_NUMBER);
}
@@ -571,8 +654,9 @@ class BlockingWriter : public QuicPacketWriterWrapper {
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_client_address,
- const IPEndPoint& peer_client_address) override {
+ const IPAddress& self_client_address,
+ const IPEndPoint& 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.
@@ -592,25 +676,23 @@ class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
IPEndPoint client_address(net::test::Loopback4(), 1);
EXPECT_CALL(dispatcher_, CreateQuicSession(_, client_address))
- .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1,
- client_address, &helper_,
- &crypto_config_, &session1_)));
- ProcessPacket(client_address, 1, true, "foo");
+ .WillOnce(testing::Return(CreateSession(
+ &dispatcher_, config_, 1, client_address, &helper_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(&dispatcher_), &session1_)));
+ ProcessPacket(client_address, 1, true, false, "foo");
EXPECT_CALL(dispatcher_, CreateQuicSession(_, client_address))
- .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 2,
- client_address, &helper_,
- &crypto_config_, &session2_)));
- ProcessPacket(client_address, 2, true, "bar");
+ .WillOnce(testing::Return(CreateSession(
+ &dispatcher_, config_, 2, client_address, &helper_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(&dispatcher_), &session2_)));
+ ProcessPacket(client_address, 2, true, false, "bar");
blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(&dispatcher_);
}
void TearDown() override {
- EXPECT_CALL(*connection1(),
- SendConnectionCloseWithDetails(QUIC_PEER_GOING_AWAY, _));
- EXPECT_CALL(*connection2(),
- SendConnectionCloseWithDetails(QUIC_PEER_GOING_AWAY, _));
+ EXPECT_CALL(*connection1(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
+ EXPECT_CALL(*connection2(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
dispatcher_.Shutdown();
}
@@ -760,5 +842,4 @@ TEST_F(QuicDispatcherWriteBlockedListTest, TestWriteLimits) {
} // namespace
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_epoll_clock.cc b/chromium/net/tools/quic/quic_epoll_clock.cc
index bb607257743..34ebf2cce8e 100644
--- a/chromium/net/tools/quic/quic_epoll_clock.cc
+++ b/chromium/net/tools/quic/quic_epoll_clock.cc
@@ -7,7 +7,6 @@
#include "net/tools/epoll_server/epoll_server.h"
namespace net {
-namespace tools {
QuicEpollClock::QuicEpollClock(EpollServer* epoll_server)
: epoll_server_(epoll_server) {}
@@ -29,5 +28,4 @@ QuicWallTime QuicEpollClock::WallNow() const {
epoll_server_->ApproximateNowInUsec());
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_epoll_clock.h b/chromium/net/tools/quic/quic_epoll_clock.h
index 05b2b9fda86..cc5dd44397b 100644
--- a/chromium/net/tools/quic/quic_epoll_clock.h
+++ b/chromium/net/tools/quic/quic_epoll_clock.h
@@ -14,7 +14,6 @@ namespace net {
class EpollServer;
-namespace tools {
// Clock to efficiently retrieve an approximately accurate time from an
// EpollServer.
@@ -41,7 +40,6 @@ class QuicEpollClock : public QuicClock {
DISALLOW_COPY_AND_ASSIGN(QuicEpollClock);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_EPOLL_CLOCK_H_
diff --git a/chromium/net/tools/quic/quic_epoll_clock_test.cc b/chromium/net/tools/quic/quic_epoll_clock_test.cc
index 05b2d7a388e..039e8bfa318 100644
--- a/chromium/net/tools/quic/quic_epoll_clock_test.cc
+++ b/chromium/net/tools/quic/quic_epoll_clock_test.cc
@@ -8,7 +8,6 @@
#include "testing/gmock/include/gmock/gmock.h"
namespace net {
-namespace tools {
namespace test {
TEST(QuicEpollClockTest, ApproximateNowInUsec) {
@@ -44,5 +43,4 @@ TEST(QuicEpollClockTest, NowInUsec) {
}
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_epoll_connection_helper.cc b/chromium/net/tools/quic/quic_epoll_connection_helper.cc
index 853f0d02571..2534ade5787 100644
--- a/chromium/net/tools/quic/quic_epoll_connection_helper.cc
+++ b/chromium/net/tools/quic/quic_epoll_connection_helper.cc
@@ -15,14 +15,14 @@
#include "net/tools/quic/quic_socket_utils.h"
namespace net {
-namespace tools {
namespace {
class QuicEpollAlarm : public QuicAlarm {
public:
- QuicEpollAlarm(EpollServer* epoll_server, QuicAlarm::Delegate* delegate)
- : QuicAlarm(delegate),
+ QuicEpollAlarm(EpollServer* epoll_server,
+ QuicArenaScopedPtr<Delegate> delegate)
+ : QuicAlarm(std::move(delegate)),
epoll_server_(epoll_server),
epoll_alarm_impl_(this) {}
@@ -61,10 +61,12 @@ class QuicEpollAlarm : public QuicAlarm {
} // namespace
-QuicEpollConnectionHelper::QuicEpollConnectionHelper(EpollServer* epoll_server)
+QuicEpollConnectionHelper::QuicEpollConnectionHelper(EpollServer* epoll_server,
+ QuicAllocator type)
: epoll_server_(epoll_server),
clock_(epoll_server),
- random_generator_(QuicRandom::GetInstance()) {}
+ random_generator_(QuicRandom::GetInstance()),
+ allocator_type_(type) {}
QuicEpollConnectionHelper::~QuicEpollConnectionHelper() {}
@@ -78,12 +80,28 @@ QuicRandom* QuicEpollConnectionHelper::GetRandomGenerator() {
QuicAlarm* QuicEpollConnectionHelper::CreateAlarm(
QuicAlarm::Delegate* delegate) {
- return new QuicEpollAlarm(epoll_server_, delegate);
+ return new QuicEpollAlarm(epoll_server_,
+ QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate));
+}
+
+QuicArenaScopedPtr<QuicAlarm> QuicEpollConnectionHelper::CreateAlarm(
+ QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+ QuicConnectionArena* arena) {
+ if (arena != nullptr) {
+ return arena->New<QuicEpollAlarm>(epoll_server_, std::move(delegate));
+ } else {
+ return QuicArenaScopedPtr<QuicAlarm>(
+ new QuicEpollAlarm(epoll_server_, std::move(delegate)));
+ }
}
QuicBufferAllocator* QuicEpollConnectionHelper::GetBufferAllocator() {
- return &buffer_allocator_;
+ if (allocator_type_ == QuicAllocator::BUFFER_POOL) {
+ return &buffer_allocator_;
+ } else {
+ DCHECK(allocator_type_ == QuicAllocator::SIMPLE);
+ return &simple_buffer_allocator_;
+ }
}
-} // namespace tools
} // 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 b3cc28ee22d..fd18fb3432d 100644
--- a/chromium/net/tools/quic/quic_epoll_connection_helper.h
+++ b/chromium/net/tools/quic/quic_epoll_connection_helper.h
@@ -25,22 +25,29 @@ namespace net {
class EpollServer;
class QuicRandom;
-namespace tools {
class AckAlarm;
class RetransmissionAlarm;
class SendAlarm;
class TimeoutAlarm;
+using QuicStreamBufferAllocator = SimpleBufferAllocator;
+
+enum class QuicAllocator { SIMPLE, BUFFER_POOL };
+
class QuicEpollConnectionHelper : public QuicConnectionHelperInterface {
public:
- explicit QuicEpollConnectionHelper(EpollServer* eps);
+ QuicEpollConnectionHelper(EpollServer* eps, QuicAllocator allocator);
~QuicEpollConnectionHelper() override;
// QuicEpollConnectionHelperInterface
const QuicClock* GetClock() const override;
QuicRandom* GetRandomGenerator() override;
QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override;
+ QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
+ QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+ QuicConnectionArena* arena) override;
+
QuicBufferAllocator* GetBufferAllocator() override;
EpollServer* epoll_server() { return epoll_server_; }
@@ -52,12 +59,14 @@ class QuicEpollConnectionHelper : public QuicConnectionHelperInterface {
const QuicEpollClock clock_;
QuicRandom* random_generator_;
- SimpleBufferAllocator buffer_allocator_;
+ // Set up both allocators. They take up minimal memory before use.
+ QuicStreamBufferAllocator buffer_allocator_;
+ SimpleBufferAllocator simple_buffer_allocator_;
+ QuicAllocator allocator_type_;
DISALLOW_COPY_AND_ASSIGN(QuicEpollConnectionHelper);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_EPOLL_CONNECTION_HELPER_H_
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 36ea8bd2983..caa44a833a8 100644
--- a/chromium/net/tools/quic/quic_epoll_connection_helper_test.cc
+++ b/chromium/net/tools/quic/quic_epoll_connection_helper_test.cc
@@ -8,10 +8,9 @@
#include "net/tools/quic/test_tools/mock_epoll_server.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::tools::test::MockEpollServer;
+using net::test::MockEpollServer;
namespace net {
-namespace tools {
namespace test {
namespace {
@@ -19,10 +18,7 @@ class TestDelegate : public QuicAlarm::Delegate {
public:
TestDelegate() : fired_(false) {}
- QuicTime OnAlarm() override {
- fired_ = true;
- return QuicTime::Zero();
- }
+ void OnAlarm() override { fired_ = true; }
bool fired() const { return fired_; }
@@ -32,7 +28,8 @@ class TestDelegate : public QuicAlarm::Delegate {
class QuicEpollConnectionHelperTest : public ::testing::Test {
protected:
- QuicEpollConnectionHelperTest() : helper_(&epoll_server_) {}
+ QuicEpollConnectionHelperTest()
+ : helper_(&epoll_server_, QuicAllocator::BUFFER_POOL) {}
MockEpollServer epoll_server_;
QuicEpollConnectionHelper helper_;
@@ -53,9 +50,28 @@ TEST_F(QuicEpollConnectionHelperTest, GetRandomGenerator) {
EXPECT_EQ(QuicRandom::GetInstance(), random);
}
-TEST_F(QuicEpollConnectionHelperTest, CreateAlarm) {
- TestDelegate* delegate = new TestDelegate();
- scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
+// The boolean parameter denotes whether or not to use an arena.
+class QuicEpollConnectionHelperAlarmTest
+ : public QuicEpollConnectionHelperTest,
+ public ::testing::WithParamInterface<bool> {
+ protected:
+ QuicConnectionArena* GetArenaParam() {
+ return GetParam() ? &arena_ : nullptr;
+ }
+
+ private:
+ QuicConnectionArena arena_;
+};
+
+INSTANTIATE_TEST_CASE_P(QuicEpollConnectionHelperAlarmTest,
+ QuicEpollConnectionHelperAlarmTest,
+ ::testing::Bool());
+
+TEST_P(QuicEpollConnectionHelperAlarmTest, CreateAlarm) {
+ QuicArenaScopedPtr<TestDelegate> delegate =
+ QuicArenaScopedPtr<TestDelegate>(new TestDelegate());
+ QuicArenaScopedPtr<QuicAlarm> alarm(
+ helper_.CreateAlarm(std::move(delegate), GetArenaParam()));
const QuicClock* clock = helper_.GetClock();
QuicTime start = clock->Now();
@@ -67,9 +83,12 @@ TEST_F(QuicEpollConnectionHelperTest, CreateAlarm) {
EXPECT_EQ(start.Add(delta), clock->Now());
}
-TEST_F(QuicEpollConnectionHelperTest, CreateAlarmAndCancel) {
- TestDelegate* delegate = new TestDelegate();
- scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
+TEST_P(QuicEpollConnectionHelperAlarmTest, CreateAlarmAndCancel) {
+ QuicArenaScopedPtr<TestDelegate> delegate =
+ QuicArenaScopedPtr<TestDelegate>(new TestDelegate());
+ TestDelegate* unowned_delegate = delegate.get();
+ QuicArenaScopedPtr<QuicAlarm> alarm(
+ helper_.CreateAlarm(std::move(delegate), GetArenaParam()));
const QuicClock* clock = helper_.GetClock();
QuicTime start = clock->Now();
@@ -79,12 +98,15 @@ TEST_F(QuicEpollConnectionHelperTest, CreateAlarmAndCancel) {
epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds());
EXPECT_EQ(start.Add(delta), clock->Now());
- EXPECT_FALSE(delegate->fired());
+ EXPECT_FALSE(unowned_delegate->fired());
}
-TEST_F(QuicEpollConnectionHelperTest, CreateAlarmAndReset) {
- TestDelegate* delegate = new TestDelegate();
- scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
+TEST_P(QuicEpollConnectionHelperAlarmTest, CreateAlarmAndReset) {
+ QuicArenaScopedPtr<TestDelegate> delegate =
+ QuicArenaScopedPtr<TestDelegate>(new TestDelegate());
+ TestDelegate* unowned_delegate = delegate.get();
+ QuicArenaScopedPtr<QuicAlarm> alarm(
+ helper_.CreateAlarm(std::move(delegate), GetArenaParam()));
const QuicClock* clock = helper_.GetClock();
QuicTime start = clock->Now();
@@ -96,17 +118,20 @@ TEST_F(QuicEpollConnectionHelperTest, CreateAlarmAndReset) {
epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds());
EXPECT_EQ(start.Add(delta), clock->Now());
- EXPECT_FALSE(delegate->fired());
+ EXPECT_FALSE(unowned_delegate->fired());
epoll_server_.AdvanceByExactlyAndCallCallbacks(
new_delta.Subtract(delta).ToMicroseconds());
EXPECT_EQ(start.Add(new_delta), clock->Now());
- EXPECT_TRUE(delegate->fired());
+ EXPECT_TRUE(unowned_delegate->fired());
}
-TEST_F(QuicEpollConnectionHelperTest, CreateAlarmAndUpdate) {
- TestDelegate* delegate = new TestDelegate();
- scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
+TEST_P(QuicEpollConnectionHelperAlarmTest, CreateAlarmAndUpdate) {
+ QuicArenaScopedPtr<TestDelegate> delegate =
+ QuicArenaScopedPtr<TestDelegate>(new TestDelegate());
+ TestDelegate* unowned_delegate = delegate.get();
+ QuicArenaScopedPtr<QuicAlarm> alarm(
+ helper_.CreateAlarm(std::move(delegate), GetArenaParam()));
const QuicClock* clock = helper_.GetClock();
QuicTime start = clock->Now();
@@ -118,7 +143,7 @@ TEST_F(QuicEpollConnectionHelperTest, CreateAlarmAndUpdate) {
epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds());
EXPECT_EQ(start.Add(delta), clock->Now());
- EXPECT_FALSE(delegate->fired());
+ EXPECT_FALSE(unowned_delegate->fired());
// Move the alarm forward 1us and ensure it doesn't move forward.
alarm->Update(clock->Now().Add(new_delta),
@@ -127,7 +152,7 @@ TEST_F(QuicEpollConnectionHelperTest, CreateAlarmAndUpdate) {
epoll_server_.AdvanceByExactlyAndCallCallbacks(
new_delta.Subtract(delta).ToMicroseconds());
EXPECT_EQ(start.Add(new_delta), clock->Now());
- EXPECT_TRUE(delegate->fired());
+ EXPECT_TRUE(unowned_delegate->fired());
// Set the alarm via an update call.
new_delta = QuicTime::Delta::FromMicroseconds(5);
@@ -142,5 +167,4 @@ TEST_F(QuicEpollConnectionHelperTest, CreateAlarmAndUpdate) {
} // namespace
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_in_memory_cache.cc b/chromium/net/tools/quic/quic_in_memory_cache.cc
index 9c248414d5f..4efd73d88fa 100644
--- a/chromium/net/tools/quic/quic_in_memory_cache.cc
+++ b/chromium/net/tools/quic/quic_in_memory_cache.cc
@@ -18,10 +18,67 @@
using base::FilePath;
using base::IntToString;
using base::StringPiece;
+using std::list;
using std::string;
namespace net {
-namespace tools {
+
+namespace {
+
+class ResourceFileImpl : public net::QuicInMemoryCache::ResourceFile {
+ public:
+ explicit ResourceFileImpl(const base::FilePath& file_name)
+ : ResourceFile(file_name) {}
+
+ void Read() override {
+ base::ReadFileToString(FilePath(file_name_), &file_contents_);
+
+ int file_len = static_cast<int>(file_contents_.length());
+ int headers_end =
+ HttpUtil::LocateEndOfHeaders(file_contents_.data(), file_len);
+ if (headers_end < 1) {
+ LOG(DFATAL) << "Headers invalid or empty, ignoring: "
+ << file_name_.value();
+ return;
+ }
+ http_headers_ = new HttpResponseHeaders(
+ HttpUtil::AssembleRawHeaders(file_contents_.data(), headers_end));
+
+ if (http_headers_->GetNormalizedHeader("X-Original-Url", &url_)) {
+ x_original_url_ = StringPiece(url_);
+ HandleXOriginalUrl();
+ }
+
+ // X-Push-URL header is a relatively quick way to support sever push
+ // in the toy server. A production server should use link=preload
+ // stuff as described in https://w3c.github.io/preload/.
+ StringPiece x_push_url("X-Push-Url");
+ if (http_headers_->HasHeader(x_push_url)) {
+ size_t iter = 0;
+ std::unique_ptr<string> push_url(new string());
+ while (
+ http_headers_->EnumerateHeader(&iter, x_push_url, push_url.get())) {
+ push_urls_.push_back(StringPiece(*push_url));
+ push_url_values_.push_back(std::move(push_url));
+ push_url.reset(new string());
+ }
+ }
+
+ body_ = StringPiece(file_contents_.data() + headers_end,
+ file_contents_.size() - headers_end);
+
+ CreateSpdyHeadersFromHttpResponse(*http_headers_, HTTP2, &spdy_headers_);
+ }
+
+ private:
+ scoped_refptr<HttpResponseHeaders> http_headers_;
+ string url_;
+ list<std::unique_ptr<string>> push_url_values_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceFileImpl);
+};
+
+} // namespace
QuicInMemoryCache::ServerPushInfo::ServerPushInfo(
GURL request_url,
@@ -33,10 +90,46 @@ QuicInMemoryCache::ServerPushInfo::ServerPushInfo(
priority(priority),
body(body) {}
+QuicInMemoryCache::ServerPushInfo::ServerPushInfo(const ServerPushInfo& other) =
+ default;
+
QuicInMemoryCache::Response::Response() : response_type_(REGULAR_RESPONSE) {}
QuicInMemoryCache::Response::~Response() {}
+QuicInMemoryCache::ResourceFile::ResourceFile(const base::FilePath& file_name)
+ : file_name_(file_name), file_name_string_(file_name.AsUTF8Unsafe()) {}
+
+QuicInMemoryCache::ResourceFile::~ResourceFile() {}
+
+void QuicInMemoryCache::ResourceFile::SetHostPathFromBase(StringPiece base) {
+ size_t path_start = base.find_first_of('/');
+ DCHECK_LT(0UL, path_start);
+ host_ = base.substr(0, path_start);
+ size_t query_start = base.find_first_of(',');
+ if (query_start > 0) {
+ path_ = base.substr(path_start, query_start - 1);
+ } else {
+ path_ = base.substr(path_start);
+ }
+}
+
+StringPiece QuicInMemoryCache::ResourceFile::RemoveScheme(StringPiece url) {
+ if (url.starts_with("https://")) {
+ url.remove_prefix(8);
+ } else if (url.starts_with("http://")) {
+ url.remove_prefix(7);
+ }
+ return url;
+}
+
+void QuicInMemoryCache::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();
@@ -47,6 +140,8 @@ const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse(
StringPiece path) const {
ResponseMap::const_iterator it = responses_.find(GetKey(host, path));
if (it == responses_.end()) {
+ DVLOG(1) << "Get response for resource failed: host " << host << " path "
+ << path;
if (default_response_.get()) {
return default_response_.get();
}
@@ -122,7 +217,7 @@ void QuicInMemoryCache::InitializeFromDirectory(const string& cache_directory) {
<< cache_directory;
FilePath directory(FilePath::FromUTF8Unsafe(cache_directory));
base::FileEnumerator file_list(directory, true, base::FileEnumerator::FILES);
-
+ list<std::unique_ptr<ResourceFile>> resource_files;
for (FilePath file_iter = file_list.Next(); !file_iter.empty();
file_iter = file_list.Next()) {
// Need to skip files in .svn directories
@@ -130,55 +225,40 @@ void QuicInMemoryCache::InitializeFromDirectory(const string& cache_directory) {
continue;
}
+ std::unique_ptr<ResourceFile> resource_file(
+ new ResourceFileImpl(file_iter));
+
// Tease apart filename into host and path.
- string file = file_iter.AsUTF8Unsafe();
- file.erase(0, cache_directory.length());
- if (file[0] == '/') {
- file.erase(0, 1);
+ StringPiece base(resource_file->file_name());
+ base.remove_prefix(cache_directory.length());
+ if (base[0] == '/') {
+ base.remove_prefix(1);
}
- string file_contents;
- base::ReadFileToString(file_iter, &file_contents);
- int file_len = static_cast<int>(file_contents.length());
- int headers_end =
- HttpUtil::LocateEndOfHeaders(file_contents.data(), file_len);
- if (headers_end < 1) {
- LOG(DFATAL) << "Headers invalid or empty, ignoring: " << file;
- continue;
- }
+ resource_file->SetHostPathFromBase(base);
+ resource_file->Read();
- string raw_headers =
- HttpUtil::AssembleRawHeaders(file_contents.data(), headers_end);
-
- scoped_refptr<HttpResponseHeaders> response_headers =
- new HttpResponseHeaders(raw_headers);
-
- string base;
- if (response_headers->GetNormalizedHeader("X-Original-Url", &base)) {
- response_headers->RemoveHeader("X-Original-Url");
- // Remove the protocol so we can add it below.
- if (base::StartsWith(base, "https://",
- base::CompareCase::INSENSITIVE_ASCII)) {
- base = base.substr(8);
- } else if (base::StartsWith(base, "http://",
- base::CompareCase::INSENSITIVE_ASCII)) {
- base = base.substr(7);
- }
- } else {
- base = file;
- }
+ AddResponse(resource_file->host(), resource_file->path(),
+ resource_file->spdy_headers(), resource_file->body());
+
+ resource_files.push_back(std::move(resource_file));
+ }
- size_t path_start = base.find_first_of('/');
- StringPiece host(StringPiece(base).substr(0, path_start));
- StringPiece path(StringPiece(base).substr(path_start));
- if (path[path.length() - 1] == ',') {
- path.remove_suffix(1);
+ for (const auto& resource_file : resource_files) {
+ list<ServerPushInfo> push_resources;
+ for (const auto& push_url : resource_file->push_urls()) {
+ GURL url(push_url);
+ const Response* response = GetResponse(url.host(), url.path());
+ if (!response) {
+ QUIC_BUG << "Push URL '" << push_url << "' not found.";
+ return;
+ }
+ push_resources.push_back(ServerPushInfo(url, response->headers(),
+ net::kV3LowestPriority,
+ response->body().as_string()));
}
- StringPiece body(file_contents.data() + headers_end,
- file_contents.size() - headers_end);
- SpdyHeaderBlock header_block;
- CreateSpdyHeadersFromHttpResponse(*response_headers, HTTP2, &header_block);
- AddResponse(host, path, header_block, body);
+ MaybeAddServerPushResources(resource_file->host(), resource_file->path(),
+ push_resources);
}
}
@@ -189,6 +269,8 @@ list<ServerPushInfo> QuicInMemoryCache::GetServerPushResources(
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;
return resources;
}
@@ -214,6 +296,7 @@ void QuicInMemoryCache::AddResponseImpl(
new_response->set_headers(response_headers);
new_response->set_body(response_body);
new_response->set_trailers(response_trailers);
+ DVLOG(1) << "Add response with key " << key;
responses_[key] = new_response;
}
@@ -225,22 +308,29 @@ void QuicInMemoryCache::MaybeAddServerPushResources(
StringPiece request_host,
StringPiece request_path,
list<ServerPushInfo> push_resources) {
- string request_url = request_host.as_string() + request_path.as_string();
+ string request_url = GetKey(request_host, request_path);
for (const auto& push_resource : push_resources) {
if (PushResourceExistsInCache(request_url, push_resource)) {
continue;
}
- DVLOG(1) << "Add request-resource association.";
+ DVLOG(1) << "Add request-resource association: request url " << request_url
+ << " push url " << push_resource.request_url
+ << " response headers " << push_resource.headers.DebugString();
server_push_resources_.insert(std::make_pair(request_url, push_resource));
+ string host = push_resource.request_url.host();
+ if (host.empty()) {
+ host = request_host.as_string();
+ }
string path = push_resource.request_url.path();
- if (responses_.find(GetKey(request_host, path)) == responses_.end()) {
+ if (responses_.find(GetKey(host, path)) == responses_.end()) {
// Add a server push response to responses map, if it is not in the map.
SpdyHeaderBlock headers = push_resource.headers;
StringPiece body = push_resource.body;
- DVLOG(1) << "Add response for push resource " << body;
- AddResponse(request_host, path, headers, body);
+ DVLOG(1) << "Add response for push resource: host " << host << " path "
+ << path;
+ AddResponse(host, path, headers, body);
}
}
}
@@ -258,5 +348,4 @@ bool QuicInMemoryCache::PushResourceExistsInCache(string original_request_url,
return false;
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_in_memory_cache.h b/chromium/net/tools/quic/quic_in_memory_cache.h
index e6ebada8740..72b210a3489 100644
--- a/chromium/net/tools/quic/quic_in_memory_cache.h
+++ b/chromium/net/tools/quic/quic_in_memory_cache.h
@@ -5,21 +5,22 @@
#ifndef NET_TOOLS_QUIC_QUIC_IN_MEMORY_CACHE_H_
#define NET_TOOLS_QUIC_QUIC_IN_MEMORY_CACHE_H_
+#include <list>
#include <map>
#include <string>
+#include <unordered_map>
+#include <vector>
#include "base/containers/hash_tables.h"
+#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/spdy_utils.h"
#include "net/spdy/spdy_framer.h"
#include "url/gurl.h"
-using base::StringPiece;
-using std::string;
-using std::list;
-
namespace base {
template <typename Type>
@@ -28,7 +29,6 @@ struct DefaultSingletonTraits;
} // namespace base
namespace net {
-namespace tools {
namespace test {
class QuicInMemoryCachePeer;
@@ -45,13 +45,14 @@ class QuicInMemoryCache {
// comprising a response for the push request.
struct ServerPushInfo {
ServerPushInfo(GURL request_url,
- const net::SpdyHeaderBlock& headers,
- net::SpdyPriority priority,
- string body);
+ const SpdyHeaderBlock& headers,
+ SpdyPriority priority,
+ std::string body);
+ ServerPushInfo(const ServerPushInfo& other);
GURL request_url;
- net::SpdyHeaderBlock headers;
- net::SpdyPriority priority;
- string body;
+ SpdyHeaderBlock headers;
+ SpdyPriority priority;
+ std::string body;
};
enum SpecialResponseType {
@@ -87,6 +88,56 @@ class QuicInMemoryCache {
DISALLOW_COPY_AND_ASSIGN(Response);
};
+ // Class to manage loading a resource file into memory. There are
+ // two uses: called by InitializeFromDirectory to load resources
+ // from files, and recursively called when said resources specify
+ // server push associations.
+ class ResourceFile {
+ public:
+ explicit ResourceFile(const base::FilePath& file_name);
+ virtual ~ResourceFile();
+
+ // abstract: implementation details are chromium and internal
+ // version specific.
+ virtual void Read() = 0;
+ void SetHostPathFromBase(base::StringPiece base);
+
+ base::StringPiece host() { return host_; }
+ void set_host(base::StringPiece host) { host_ = host; }
+
+ base::StringPiece path() { return path_; }
+ void set_path(base::StringPiece path) { path_ = path; }
+
+ SpdyHeaderBlock spdy_headers() { return spdy_headers_; }
+
+ base::StringPiece body() { return body_; }
+
+ const std::vector<base::StringPiece>& push_urls() { return push_urls_; }
+
+ const std::string& file_name() { return file_name_string_; }
+
+ protected:
+ void HandleXOriginalUrl();
+ void HandlePushUrls(const std::vector<base::StringPiece>& push_urls);
+ base::StringPiece RemoveScheme(base::StringPiece url);
+
+ const std::string cache_directory_;
+ const base::FilePath file_name_;
+ const std::string file_name_string_;
+ std::string file_contents_;
+ base::StringPiece body_;
+ SpdyHeaderBlock spdy_headers_;
+ base::StringPiece x_original_url_;
+ std::vector<base::StringPiece> push_urls_;
+
+ private:
+ base::StringPiece host_;
+ base::StringPiece path_;
+ QuicInMemoryCache* cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceFile);
+ };
+
// Returns the singleton instance of the cache.
static QuicInMemoryCache* GetInstance();
@@ -107,11 +158,11 @@ class QuicInMemoryCache {
// path) associated with it.
// Push resource implicitly come from the same host.
void AddSimpleResponseWithServerPushResources(
- StringPiece host,
- StringPiece path,
+ base::StringPiece host,
+ base::StringPiece path,
int response_code,
- StringPiece body,
- list<ServerPushInfo> push_resources);
+ base::StringPiece body,
+ std::list<ServerPushInfo> push_resources);
// Add a response to the cache.
void AddResponse(base::StringPiece host,
@@ -136,13 +187,13 @@ class QuicInMemoryCache {
void AddDefaultResponse(Response* response);
// |cache_cirectory| can be generated using `wget -p --save-headers <url>`.
- void InitializeFromDirectory(const string& cache_directory);
+ void InitializeFromDirectory(const std::string& cache_directory);
// Find all the server push resources associated with |request_url|.
- list<ServerPushInfo> GetServerPushResources(string request_url);
+ std::list<ServerPushInfo> GetServerPushResources(std::string request_url);
private:
- typedef base::hash_map<string, Response*> ResponseMap;
+ typedef std::unordered_map<std::string, Response*> ResponseMap;
friend struct base::DefaultSingletonTraits<QuicInMemoryCache>;
friend class test::QuicInMemoryCachePeer;
@@ -159,17 +210,17 @@ class QuicInMemoryCache {
base::StringPiece response_body,
const SpdyHeaderBlock& response_trailers);
- string GetKey(base::StringPiece host, base::StringPiece path) const;
+ std::string GetKey(base::StringPiece host, base::StringPiece path) const;
// Add some server push urls with given responses for specified
// request if these push resources are not associated with this request yet.
- void MaybeAddServerPushResources(StringPiece request_host,
- StringPiece request_path,
- list<ServerPushInfo> push_resources);
+ void MaybeAddServerPushResources(base::StringPiece request_host,
+ base::StringPiece request_path,
+ std::list<ServerPushInfo> push_resources);
// Check if push resource(push_host/push_path) associated with given request
// url already exists in server push map.
- bool PushResourceExistsInCache(string original_request_url,
+ bool PushResourceExistsInCache(std::string original_request_url,
ServerPushInfo resource);
// Cached responses.
@@ -179,12 +230,11 @@ class QuicInMemoryCache {
scoped_ptr<Response> default_response_;
// A map from request URL to associated server push responses (if any).
- std::multimap<string, ServerPushInfo> server_push_resources_;
+ std::multimap<std::string, ServerPushInfo> server_push_resources_;
DISALLOW_COPY_AND_ASSIGN(QuicInMemoryCache);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_IN_MEMORY_CACHE_H_
diff --git a/chromium/net/tools/quic/quic_in_memory_cache_test.cc b/chromium/net/tools/quic/quic_in_memory_cache_test.cc
index 227d615d20a..4f547bcf21a 100644
--- a/chromium/net/tools/quic/quic_in_memory_cache_test.cc
+++ b/chromium/net/tools/quic/quic_in_memory_cache_test.cc
@@ -20,10 +20,10 @@
using base::IntToString;
using base::StringPiece;
using net::SpdyHeaderBlock;
+using std::list;
using std::string;
namespace net {
-namespace tools {
namespace test {
namespace {
@@ -113,6 +113,24 @@ TEST_F(QuicInMemoryCacheTest, ReadsCacheDir) {
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/");
+ 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");
+ ASSERT_EQ(2UL, resources.size());
+}
+
TEST_F(QuicInMemoryCacheTest, UsesOriginalUrl) {
QuicInMemoryCache::GetInstance()->InitializeFromDirectory(CacheDirectory());
const QuicInMemoryCache::Response* response =
@@ -187,8 +205,7 @@ TEST_F(QuicInMemoryCacheTest, AddSimpleResponseWithServerPushResources) {
cache->AddSimpleResponseWithServerPushResources(
request_host, "/", 200, response_body, push_resources);
string request_url = request_host + "/";
- std::list<ServerPushInfo> resources =
- cache->GetServerPushResources(request_url);
+ list<ServerPushInfo> resources = cache->GetServerPushResources(request_url);
ASSERT_EQ(kNumResources, resources.size());
for (const auto& push_resource : push_resources) {
ServerPushInfo resource = resources.front();
@@ -222,8 +239,7 @@ TEST_F(QuicInMemoryCacheTest, GetServerPushResourcesAndPushResponses) {
cache->AddSimpleResponseWithServerPushResources(
request_host, "/", 200, response_body, push_resources);
string request_url = request_host + "/";
- std::list<ServerPushInfo> resources =
- cache->GetServerPushResources(request_url);
+ list<ServerPushInfo> resources = cache->GetServerPushResources(request_url);
ASSERT_EQ(kNumResources, resources.size());
int i = 0;
for (const auto& push_resource : push_resources) {
@@ -242,5 +258,4 @@ TEST_F(QuicInMemoryCacheTest, GetServerPushResourcesAndPushResponses) {
}
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_packet_reader.cc b/chromium/net/tools/quic/quic_packet_reader.cc
index a6d325e5737..beba973842c 100644
--- a/chromium/net/tools/quic/quic_packet_reader.cc
+++ b/chromium/net/tools/quic/quic_packet_reader.cc
@@ -13,10 +13,12 @@
#include <sys/epoll.h>
#include "base/logging.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_flags.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
@@ -27,32 +29,33 @@
namespace net {
-namespace tools {
QuicPacketReader::QuicPacketReader() {
Initialize();
}
void QuicPacketReader::Initialize() {
+#if MMSG_MORE
// Zero initialize uninitialized memory.
- memset(cbuf_, 0, arraysize(cbuf_));
- memset(buf_, 0, arraysize(buf_));
- memset(raw_address_, 0, sizeof(raw_address_));
memset(mmsg_hdr_, 0, sizeof(mmsg_hdr_));
for (int i = 0; i < kNumPacketsPerReadMmsgCall; ++i) {
- iov_[i].iov_base = buf_ + (kMaxPacketSize * i);
- iov_[i].iov_len = kMaxPacketSize;
+ packets_[i].iov.iov_base = packets_[i].buf;
+ packets_[i].iov.iov_len = kMaxPacketSize;
+ memset(&packets_[i].raw_address, 0, sizeof(packets_[i].raw_address));
+ memset(packets_[i].cbuf, 0, sizeof(packets_[i].cbuf));
+ memset(packets_[i].buf, 0, sizeof(packets_[i].buf));
msghdr* hdr = &mmsg_hdr_[i].msg_hdr;
- hdr->msg_name = &raw_address_[i];
+ hdr->msg_name = &packets_[i].raw_address;
hdr->msg_namelen = sizeof(sockaddr_storage);
- hdr->msg_iov = &iov_[i];
+ hdr->msg_iov = &packets_[i].iov;
hdr->msg_iovlen = 1;
- hdr->msg_control = cbuf_ + kSpaceForOverflowAndIp * i;
- hdr->msg_controllen = kSpaceForOverflowAndIp;
+ hdr->msg_control = packets_[i].cbuf;
+ hdr->msg_controllen = QuicSocketUtils::kSpaceForCmsg;
}
+#endif
}
QuicPacketReader::~QuicPacketReader() {}
@@ -60,17 +63,32 @@ QuicPacketReader::~QuicPacketReader() {}
bool QuicPacketReader::ReadAndDispatchPackets(
int fd,
int port,
+ const QuicClock& clock,
+ ProcessPacketInterface* processor,
+ QuicPacketCount* packets_dropped) {
+#if MMSG_MORE
+ return ReadAndDispatchManyPackets(fd, port, clock, processor,
+ packets_dropped);
+#else
+ return ReadAndDispatchSinglePacket(fd, port, clock, processor,
+ packets_dropped);
+#endif
+}
+
+bool QuicPacketReader::ReadAndDispatchManyPackets(
+ int fd,
+ int port,
+ const QuicClock& clock,
ProcessPacketInterface* processor,
QuicPacketCount* packets_dropped) {
#if MMSG_MORE
// Re-set the length fields in case recvmmsg has changed them.
for (int i = 0; i < kNumPacketsPerReadMmsgCall; ++i) {
- iov_[i].iov_len = kMaxPacketSize;
- mmsg_hdr_[i].msg_len = 0;
+ DCHECK_EQ(kMaxPacketSize, packets_[i].iov.iov_len);
msghdr* hdr = &mmsg_hdr_[i].msg_hdr;
hdr->msg_namelen = sizeof(sockaddr_storage);
- hdr->msg_iovlen = 1;
- hdr->msg_controllen = kSpaceForOverflowAndIp;
+ DCHECK_EQ(1, hdr->msg_iovlen);
+ hdr->msg_controllen = QuicSocketUtils::kSpaceForCmsg;
}
int packets_read =
@@ -80,21 +98,42 @@ bool QuicPacketReader::ReadAndDispatchPackets(
return false; // recvmmsg failed.
}
+ QuicTime fallback_timestamp = QuicTime::Zero();
for (int i = 0; i < packets_read; ++i) {
if (mmsg_hdr_[i].msg_len == 0) {
continue;
}
- IPEndPoint client_address = IPEndPoint(raw_address_[i]);
- IPAddressNumber server_ip =
- QuicSocketUtils::GetAddressFromMsghdr(&mmsg_hdr_[i].msg_hdr);
+ if (mmsg_hdr_[i].msg_hdr.msg_controllen >= QuicSocketUtils::kSpaceForCmsg) {
+ QUIC_BUG << "Incorrectly set control length: "
+ << mmsg_hdr_[i].msg_hdr.msg_controllen << ", expected "
+ << QuicSocketUtils::kSpaceForCmsg;
+ continue;
+ }
+
+ IPEndPoint client_address = IPEndPoint(packets_[i].raw_address);
+ IPAddressNumber server_ip;
+ QuicTime packet_timestamp = QuicTime::Zero();
+ QuicSocketUtils::GetAddressAndTimestampFromMsghdr(
+ &mmsg_hdr_[i].msg_hdr, &server_ip, &packet_timestamp);
if (!IsInitializedAddress(server_ip)) {
QUIC_BUG << "Unable to get server address.";
continue;
}
- QuicEncryptedPacket packet(reinterpret_cast<char*>(iov_[i].iov_base),
- mmsg_hdr_[i].msg_len, false);
+ if (FLAGS_quic_use_socket_timestamp) {
+ if (packet_timestamp == QuicTime::Zero()) {
+ // This isn't particularly desirable, but not all platforms support
+ // socket timestamping.
+ if (fallback_timestamp == QuicTime::Zero()) {
+ fallback_timestamp = clock.Now();
+ }
+ packet_timestamp = fallback_timestamp;
+ }
+ }
+
+ QuicReceivedPacket packet(reinterpret_cast<char*>(packets_[i].iov.iov_base),
+ mmsg_hdr_[i].msg_len, packet_timestamp, false);
IPEndPoint server_address(server_ip, port);
processor->ProcessPacket(server_address, client_address, packet);
}
@@ -116,20 +155,33 @@ bool QuicPacketReader::ReadAndDispatchPackets(
bool QuicPacketReader::ReadAndDispatchSinglePacket(
int fd,
int port,
+ const QuicClock& clock,
ProcessPacketInterface* processor,
QuicPacketCount* packets_dropped) {
char buf[kMaxPacketSize];
IPEndPoint client_address;
- IPAddressNumber server_ip;
- int bytes_read = QuicSocketUtils::ReadPacket(
- fd, buf, arraysize(buf), packets_dropped, &server_ip, &client_address);
+ IPAddress server_ip;
+ QuicTime timestamp = QuicTime::Zero();
+ int bytes_read =
+ QuicSocketUtils::ReadPacket(fd, buf, arraysize(buf), packets_dropped,
+ &server_ip, &timestamp, &client_address);
if (bytes_read < 0) {
return false; // ReadPacket failed.
}
- QuicEncryptedPacket packet(buf, bytes_read, false);
+ if (server_ip.empty()) {
+ QUIC_BUG << "Unable to get server address.";
+ return false;
+ }
+ if (FLAGS_quic_use_socket_timestamp && timestamp == QuicTime::Zero()) {
+ // This isn't particularly desirable, but not all platforms support socket
+ // timestamping.
+ timestamp = clock.Now();
+ }
+
+ QuicReceivedPacket packet(buf, bytes_read, timestamp, false);
IPEndPoint server_address(server_ip, port);
processor->ProcessPacket(server_address, client_address, packet);
@@ -138,6 +190,5 @@ bool QuicPacketReader::ReadAndDispatchSinglePacket(
return true;
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_packet_reader.h b/chromium/net/tools/quic/quic_packet_reader.h
index 0d99afbc745..b388406b478 100644
--- a/chromium/net/tools/quic/quic_packet_reader.h
+++ b/chromium/net/tools/quic/quic_packet_reader.h
@@ -11,23 +11,24 @@
#include <sys/socket.h>
#include "base/macros.h"
+#include "net/quic/quic_clock.h"
#include "net/quic/quic_protocol.h"
+#include "net/tools/quic/quic_process_packet_interface.h"
+#include "net/tools/quic/quic_socket_utils.h"
-namespace net {
+#define MMSG_MORE 0
-namespace tools {
+namespace net {
+#if MMSG_MORE
// Read in larger batches to minimize recvmmsg overhead.
const int kNumPacketsPerReadMmsgCall = 16;
-// Allocate space for in6_pktinfo as it's larger than in_pktinfo
-const int kSpaceForOverflowAndIp =
- CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(in6_pktinfo));
+#endif
namespace test {
class QuicServerPeer;
} // namespace test
-class ProcessPacketInterface;
class QuicDispatcher;
class QuicPacketReader {
@@ -41,40 +42,57 @@ class QuicPacketReader {
// packets available on the socket.
// Populates |packets_dropped| if it is non-null and the socket is configured
// to track dropped packets and some packets are read.
+ // If the socket has timestamping enabled, the per packet timestamps will be
+ // passed to the processor. Otherwise, |clock| will be used.
virtual bool ReadAndDispatchPackets(int fd,
int port,
+ const QuicClock& clock,
ProcessPacketInterface* processor,
QuicPacketCount* packets_dropped);
- // Same as ReadAndDispatchPackets, only does one packet at a time.
+ private:
+ // Initialize the internal state of the reader.
+ void Initialize();
+
+ // Reads and dispatches many packets using recvmmsg.
+ bool ReadAndDispatchManyPackets(int fd,
+ int port,
+ const QuicClock& clock,
+ ProcessPacketInterface* processor,
+ QuicPacketCount* packets_dropped);
+
+ // Reads and dispatches a single packet using recvmsg.
static bool ReadAndDispatchSinglePacket(int fd,
int port,
+ const QuicClock& clock,
ProcessPacketInterface* processor,
QuicPacketCount* packets_dropped);
- private:
- // Initialize the internal state of the reader.
- void Initialize();
-
// Storage only used when recvmmsg is available.
- // cbuf_ is used for ancillary data from the kernel on recvmmsg.
- char cbuf_[kSpaceForOverflowAndIp * kNumPacketsPerReadMmsgCall];
- // buf_ is used for the data read from the kernel on recvmmsg.
+#if MMSG_MORE
// TODO(danzh): change it to be a pointer to avoid the allocation on the stack
// from exceeding maximum allowed frame size.
- char buf_[kMaxPacketSize * kNumPacketsPerReadMmsgCall];
- // iov_ and mmsg_hdr_ are used to supply cbuf and buf to the recvmmsg call.
- iovec iov_[kNumPacketsPerReadMmsgCall];
+ // packets_ and mmsg_hdr_ are used to supply cbuf and buf to the recvmmsg
+ // call.
+
+ struct PacketData {
+ iovec iov;
+ // raw_address is used for address information provided by the recvmmsg
+ // call on the packets.
+ struct sockaddr_storage raw_address;
+ // cbuf is used for ancillary data from the kernel on recvmmsg.
+ char cbuf[QuicSocketUtils::kSpaceForCmsg];
+ // buf is used for the data read from the kernel on recvmmsg.
+ char buf[kMaxPacketSize];
+ };
+ PacketData packets_[kNumPacketsPerReadMmsgCall];
mmsghdr mmsg_hdr_[kNumPacketsPerReadMmsgCall];
- // raw_address_ is used for address information provided by the recvmmsg
- // call on the packets.
- struct sockaddr_storage raw_address_[kNumPacketsPerReadMmsgCall];
+#endif
DISALLOW_COPY_AND_ASSIGN(QuicPacketReader);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_PACKET_READER_H_
diff --git a/chromium/net/tools/quic/quic_packet_writer_wrapper.cc b/chromium/net/tools/quic/quic_packet_writer_wrapper.cc
index 546331a3185..3d008f09c73 100644
--- a/chromium/net/tools/quic/quic_packet_writer_wrapper.cc
+++ b/chromium/net/tools/quic/quic_packet_writer_wrapper.cc
@@ -7,7 +7,6 @@
#include "net/quic/quic_types.h"
namespace net {
-namespace tools {
QuicPacketWriterWrapper::QuicPacketWriterWrapper() {}
@@ -16,12 +15,13 @@ QuicPacketWriterWrapper::QuicPacketWriterWrapper(QuicPacketWriter* writer)
QuicPacketWriterWrapper::~QuicPacketWriterWrapper() {}
-WriteResult QuicPacketWriterWrapper::WritePacket(
- const char* buffer,
- size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) {
- return writer_->WritePacket(buffer, buf_len, self_address, peer_address);
+WriteResult QuicPacketWriterWrapper::WritePacket(const char* buffer,
+ size_t buf_len,
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) {
+ return writer_->WritePacket(buffer, buf_len, self_address, peer_address,
+ options);
}
bool QuicPacketWriterWrapper::IsWriteBlockedDataBuffered() const {
@@ -45,5 +45,4 @@ void QuicPacketWriterWrapper::set_writer(QuicPacketWriter* writer) {
writer_.reset(writer);
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_packet_writer_wrapper.h b/chromium/net/tools/quic/quic_packet_writer_wrapper.h
index f425b5c3b77..92044c020d0 100644
--- a/chromium/net/tools/quic/quic_packet_writer_wrapper.h
+++ b/chromium/net/tools/quic/quic_packet_writer_wrapper.h
@@ -13,8 +13,6 @@
namespace net {
-namespace tools {
-
// Wraps a writer object to allow dynamically extending functionality. Use
// cases: replace writer while dispatcher and connections hold on to the
// wrapper; mix in monitoring; mix in mocks in unit tests.
@@ -28,8 +26,9 @@ class QuicPacketWriterWrapper : public QuicPacketWriter {
// to |writer_|.
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) override;
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) override;
bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
@@ -44,7 +43,6 @@ class QuicPacketWriterWrapper : public QuicPacketWriter {
DISALLOW_COPY_AND_ASSIGN(QuicPacketWriterWrapper);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_PACKET_WRITER_WRAPPER_H_
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 f95e0169104..a83179400cf 100644
--- a/chromium/net/tools/quic/quic_per_connection_packet_writer.cc
+++ b/chromium/net/tools/quic/quic_per_connection_packet_writer.cc
@@ -6,8 +6,6 @@
namespace net {
-namespace tools {
-
QuicPerConnectionPacketWriter::QuicPerConnectionPacketWriter(
QuicPacketWriter* shared_writer)
: shared_writer_(shared_writer) {}
@@ -17,10 +15,11 @@ QuicPerConnectionPacketWriter::~QuicPerConnectionPacketWriter() {}
WriteResult QuicPerConnectionPacketWriter::WritePacket(
const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) {
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) {
return shared_writer_->WritePacket(buffer, buf_len, self_address,
- peer_address);
+ peer_address, options);
}
bool QuicPerConnectionPacketWriter::IsWriteBlockedDataBuffered() const {
@@ -40,6 +39,4 @@ QuicByteCount QuicPerConnectionPacketWriter::GetMaxPacketSize(
return shared_writer_->GetMaxPacketSize(peer_address);
}
-} // namespace tools
-
} // namespace net
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 e4c20450605..6902f3af839 100644
--- a/chromium/net/tools/quic/quic_per_connection_packet_writer.h
+++ b/chromium/net/tools/quic/quic_per_connection_packet_writer.h
@@ -13,8 +13,6 @@
namespace net {
-namespace tools {
-
// A connection-specific packet writer that wraps a shared writer.
class QuicPerConnectionPacketWriter : public QuicPacketWriter {
public:
@@ -28,8 +26,9 @@ class QuicPerConnectionPacketWriter : public QuicPacketWriter {
// to |shared_writer_|.
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) override;
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) override;
bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
@@ -41,8 +40,6 @@ class QuicPerConnectionPacketWriter : public QuicPacketWriter {
DISALLOW_COPY_AND_ASSIGN(QuicPerConnectionPacketWriter);
};
-} // namespace tools
-
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_PER_CONNECTION_PACKET_WRITER_H_
diff --git a/chromium/net/tools/quic/quic_process_packet_interface.h b/chromium/net/tools/quic/quic_process_packet_interface.h
new file mode 100644
index 00000000000..aa1035d946b
--- /dev/null
+++ b/chromium/net/tools/quic/quic_process_packet_interface.h
@@ -0,0 +1,25 @@
+// 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_TOOLS_QUIC_QUIC_PROCESS_PACKET_INTERFACE_H_
+#define NET_TOOLS_QUIC_QUIC_PROCESS_PACKET_INTERFACE_H_
+
+#include "base/macros.h"
+#include "net/base/ip_endpoint.h"
+#include "net/quic/quic_protocol.h"
+
+namespace net {
+
+// A class to process each incoming packet.
+class ProcessPacketInterface {
+ public:
+ virtual ~ProcessPacketInterface() {}
+ virtual void ProcessPacket(const IPEndPoint& server_address,
+ const IPEndPoint& client_address,
+ const QuicReceivedPacket& packet) = 0;
+};
+
+} // namespace net
+
+#endif // NET_TOOLS_QUIC_QUIC_PROCESS_PACKET_INTERFACE_H_
diff --git a/chromium/net/tools/quic/quic_server.cc b/chromium/net/tools/quic/quic_server.cc
index 743060033f6..c67e554f2c8 100644
--- a/chromium/net/tools/quic/quic_server.cc
+++ b/chromium/net/tools/quic/quic_server.cc
@@ -26,15 +26,11 @@
#include "net/tools/quic/quic_packet_reader.h"
#include "net/tools/quic/quic_socket_utils.h"
-// TODO(rtenneti): Add support for MMSG_MORE.
-#define MMSG_MORE 0
-
#ifndef SO_RXQ_OVFL
#define SO_RXQ_OVFL 40
#endif
namespace net {
-namespace tools {
namespace {
// Specifies the directory used during QuicInMemoryCache
@@ -48,30 +44,31 @@ const char kSourceAddressTokenSecret[] = "secret";
} // namespace
QuicServer::QuicServer(ProofSource* proof_source)
- : QuicServer(proof_source, QuicConfig(), QuicSupportedVersions()) {}
-
-QuicServer::QuicServer(ProofSource* proof_source,
- const QuicConfig& config,
- const QuicVersionVector& supported_versions)
+ : QuicServer(proof_source,
+ QuicConfig(),
+ QuicCryptoServerConfig::ConfigOptions(),
+ QuicSupportedVersions()) {}
+
+QuicServer::QuicServer(
+ ProofSource* proof_source,
+ const QuicConfig& config,
+ const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
+ const QuicVersionVector& supported_versions)
: port_(0),
fd_(-1),
packets_dropped_(0),
overflow_supported_(false),
- use_recvmmsg_(false),
config_(config),
crypto_config_(kSourceAddressTokenSecret,
QuicRandom::GetInstance(),
proof_source),
+ crypto_config_options_(crypto_config_options),
supported_versions_(supported_versions),
packet_reader_(new QuicPacketReader()) {
Initialize();
}
void QuicServer::Initialize() {
-#if MMSG_MORE
- use_recvmmsg_ = true;
-#endif
-
// If an initial flow control window has not explicitly been set, then use a
// sensible value for a server: 1 MB for session, 64 KB for each stream.
const uint32_t kInitialSessionFlowControlWindow = 1 * 1024 * 1024; // 1 MB
@@ -96,58 +93,24 @@ void QuicServer::Initialize() {
QuicEpollClock clock(&epoll_server_);
- scoped_ptr<CryptoHandshakeMessage> scfg(
- crypto_config_.AddDefaultConfig(QuicRandom::GetInstance(), &clock,
- QuicCryptoServerConfig::ConfigOptions()));
+ scoped_ptr<CryptoHandshakeMessage> scfg(crypto_config_.AddDefaultConfig(
+ QuicRandom::GetInstance(), &clock, crypto_config_options_));
}
QuicServer::~QuicServer() {}
-bool QuicServer::Listen(const IPEndPoint& address) {
- port_ = address.port();
- int address_family = address.GetSockAddrFamily();
- fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
+bool QuicServer::CreateUDPSocketAndListen(const IPEndPoint& address) {
+ fd_ = QuicSocketUtils::CreateUDPSocket(address, &overflow_supported_);
if (fd_ < 0) {
LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
return false;
}
- // Enable the socket option that allows the local address to be
- // returned if the socket is bound to more than one address.
- int rc = QuicSocketUtils::SetGetAddressInfo(fd_, address_family);
-
- if (rc < 0) {
- LOG(ERROR) << "IP detection not supported" << strerror(errno);
- return false;
- }
-
- int get_overflow = 1;
- rc = setsockopt(fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
- sizeof(get_overflow));
-
- if (rc < 0) {
- DLOG(WARNING) << "Socket overflow detection not supported";
- } else {
- overflow_supported_ = true;
- }
-
- // These send and receive buffer sizes are sized for a single connection,
- // because the default usage of QuicServer is as a test server with one or
- // two clients. Adjust higher for use with many clients.
- if (!QuicSocketUtils::SetReceiveBufferSize(fd_,
- kDefaultSocketReceiveBuffer)) {
- return false;
- }
-
- if (!QuicSocketUtils::SetSendBufferSize(fd_, kDefaultSocketReceiveBuffer)) {
- 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));
- rc =
+ int rc =
bind(fd_, reinterpret_cast<const sockaddr*>(&raw_addr), sizeof(raw_addr));
if (rc < 0) {
LOG(ERROR) << "Bind failed: " << strerror(errno);
@@ -180,7 +143,8 @@ QuicDefaultPacketWriter* QuicServer::CreateWriter(int fd) {
QuicDispatcher* QuicServer::CreateQuicDispatcher() {
return new QuicDispatcher(config_, &crypto_config_, supported_versions_,
- new QuicEpollConnectionHelper(&epoll_server_));
+ new QuicEpollConnectionHelper(
+ &epoll_server_, QuicAllocator::BUFFER_POOL));
}
void QuicServer::WaitForEvents() {
@@ -204,15 +168,9 @@ void QuicServer::OnEvent(int fd, EpollEvent* event) {
DVLOG(1) << "EPOLLIN";
bool more_to_read = true;
while (more_to_read) {
- if (use_recvmmsg_) {
- more_to_read = packet_reader_->ReadAndDispatchPackets(
- fd_, port_, dispatcher_.get(),
- overflow_supported_ ? &packets_dropped_ : nullptr);
- } else {
- more_to_read = QuicPacketReader::ReadAndDispatchSinglePacket(
- fd_, port_, dispatcher_.get(),
- overflow_supported_ ? &packets_dropped_ : nullptr);
- }
+ more_to_read = packet_reader_->ReadAndDispatchPackets(
+ fd_, port_, QuicEpollClock(&epoll_server_), dispatcher_.get(),
+ overflow_supported_ ? &packets_dropped_ : nullptr);
}
}
if (event->in_events & EPOLLOUT) {
@@ -225,5 +183,4 @@ void QuicServer::OnEvent(int fd, EpollEvent* event) {
}
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_server.h b/chromium/net/tools/quic/quic_server.h
index b2023e3c8c5..24523ded14f 100644
--- a/chromium/net/tools/quic/quic_server.h
+++ b/chromium/net/tools/quic/quic_server.h
@@ -24,13 +24,11 @@
#include "net/tools/quic/quic_default_packet_writer.h"
namespace net {
-namespace tools {
namespace test {
class QuicServerPeer;
} // namespace test
-class ProcessPacketInterface;
class QuicDispatcher;
class QuicPacketReader;
@@ -39,12 +37,13 @@ class QuicServer : public EpollCallbackInterface {
explicit QuicServer(ProofSource* proof_source);
QuicServer(ProofSource* proof_source,
const QuicConfig& config,
+ const QuicCryptoServerConfig::ConfigOptions& server_config_options,
const QuicVersionVector& supported_versions);
~QuicServer() override;
// Start listening on the specified address.
- bool Listen(const IPEndPoint& address);
+ bool CreateUDPSocketAndListen(const IPEndPoint& address);
// Wait up to 50ms, and handle any events which occur.
void WaitForEvents();
@@ -89,7 +88,7 @@ class QuicServer : public EpollCallbackInterface {
QuicDispatcher* dispatcher() { return dispatcher_.get(); }
private:
- friend class net::tools::test::QuicServerPeer;
+ friend class net::test::QuicServerPeer;
// Initialize the internal state of the server.
void Initialize();
@@ -114,14 +113,13 @@ class QuicServer : public EpollCallbackInterface {
// because the socket would otherwise overflow.
bool overflow_supported_;
- // If true, use recvmmsg for reading.
- bool use_recvmmsg_;
-
// config_ contains non-crypto parameters that are negotiated in the crypto
// handshake.
QuicConfig config_;
// crypto_config_ contains crypto parameters for the handshake.
QuicCryptoServerConfig crypto_config_;
+ // crypto_config_options_ contains crypto parameters for the handshake.
+ QuicCryptoServerConfig::ConfigOptions crypto_config_options_;
// This vector contains QUIC versions which we currently support.
// This should be ordered such that the highest supported version is the first
@@ -129,12 +127,13 @@ class QuicServer : public EpollCallbackInterface {
// skipped as necessary).
QuicVersionVector supported_versions_;
+ // Point to a QuicPacketReader object on the heap. The reader allocates more
+ // space than allowed on the stack.
scoped_ptr<QuicPacketReader> packet_reader_;
DISALLOW_COPY_AND_ASSIGN(QuicServer);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_SERVER_H_
diff --git a/chromium/net/tools/quic/quic_server_bin.cc b/chromium/net/tools/quic/quic_server_bin.cc
index 5e04ccbaab0..983c58443bc 100644
--- a/chromium/net/tools/quic/quic_server_bin.cc
+++ b/chromium/net/tools/quic/quic_server_bin.cc
@@ -12,6 +12,7 @@
#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/crypto/proof_source_chromium.h"
#include "net/quic/quic_protocol.h"
@@ -55,7 +56,7 @@ int main(int argc, char* argv[]) {
}
if (line->HasSwitch("quic_in_memory_cache_dir")) {
- net::tools::QuicInMemoryCache::GetInstance()->InitializeFromDirectory(
+ net::QuicInMemoryCache::GetInstance()->InitializeFromDirectory(
line->GetSwitchValueASCII("quic_in_memory_cache_dir"));
}
@@ -76,17 +77,17 @@ int main(int argc, char* argv[]) {
return 1;
}
- net::IPAddressNumber ip;
- CHECK(net::ParseIPLiteralToNumber("::", &ip));
+ auto ip = net::IPAddress::IPv6AllZeros();
net::QuicConfig config;
- net::tools::QuicServer server(
+ net::QuicServer server(
CreateProofSource(line->GetSwitchValuePath("certificate_file"),
line->GetSwitchValuePath("key_file")),
- config, net::QuicSupportedVersions());
+ config, net::QuicCryptoServerConfig::ConfigOptions(),
+ net::QuicSupportedVersions());
server.SetStrikeRegisterNoStartupPeriod();
- int rc = server.Listen(net::IPEndPoint(ip, FLAGS_port));
+ int rc = server.CreateUDPSocketAndListen(net::IPEndPoint(ip, FLAGS_port));
if (rc < 0) {
return 1;
}
diff --git a/chromium/net/tools/quic/quic_server_session_base.cc b/chromium/net/tools/quic/quic_server_session_base.cc
index 835df612ffb..e2341906bdf 100644
--- a/chromium/net/tools/quic/quic_server_session_base.cc
+++ b/chromium/net/tools/quic/quic_server_session_base.cc
@@ -6,21 +6,25 @@
#include "base/logging.h"
#include "net/quic/proto/cached_network_parameters.pb.h"
+#include "net/quic/quic_bug_tracker.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_spdy_session.h"
#include "net/quic/reliable_quic_stream.h"
+using std::string;
+
namespace net {
-namespace tools {
QuicServerSessionBase::QuicServerSessionBase(
const QuicConfig& config,
QuicConnection* connection,
QuicServerSessionVisitor* visitor,
- const QuicCryptoServerConfig* crypto_config)
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache)
: QuicSpdySession(connection, config),
crypto_config_(crypto_config),
+ compressed_certs_cache_(compressed_certs_cache),
visitor_(visitor),
bandwidth_resumption_enabled_(false),
bandwidth_estimate_sent_to_client_(QuicBandwidth::Zero()),
@@ -30,7 +34,8 @@ QuicServerSessionBase::QuicServerSessionBase(
QuicServerSessionBase::~QuicServerSessionBase() {}
void QuicServerSessionBase::Initialize() {
- crypto_stream_.reset(CreateQuicCryptoServerStream(crypto_config_));
+ crypto_stream_.reset(
+ CreateQuicCryptoServerStream(crypto_config_, compressed_certs_cache_));
QuicSpdySession::Initialize();
}
@@ -41,47 +46,49 @@ void QuicServerSessionBase::OnConfigNegotiated() {
return;
}
- // If the client has provided a bandwidth estimate from the same serving
- // region, then pass it to the sent packet manager in preparation for possible
- // bandwidth resumption.
- const CachedNetworkParameters* cached_network_params =
- crypto_stream_->PreviousCachedNetworkParams();
+ // Enable bandwidth resumption if peer sent correct connection options.
const bool last_bandwidth_resumption =
ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWRE);
const bool max_bandwidth_resumption =
ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWMX);
bandwidth_resumption_enabled_ =
last_bandwidth_resumption || max_bandwidth_resumption;
- if (cached_network_params != nullptr && bandwidth_resumption_enabled_ &&
+
+ // If the client has provided a bandwidth estimate from the same serving
+ // region as this server, then decide whether to use the data for bandwidth
+ // resumption.
+ const CachedNetworkParameters* cached_network_params =
+ crypto_stream_->PreviousCachedNetworkParams();
+ if (cached_network_params != nullptr &&
cached_network_params->serving_region() == serving_region_) {
- int64_t seconds_since_estimate =
- connection()->clock()->WallNow().ToUNIXSeconds() -
- cached_network_params->timestamp();
- bool estimate_within_last_hour =
- seconds_since_estimate <= kNumSecondsPerHour;
- if (estimate_within_last_hour) {
- connection()->ResumeConnectionState(*cached_network_params,
- max_bandwidth_resumption);
+ if (FLAGS_quic_log_received_parameters) {
+ connection()->OnReceiveConnectionState(*cached_network_params);
}
- }
- if (FLAGS_enable_quic_fec &&
- ContainsQuicTag(config()->ReceivedConnectionOptions(), kFHDR)) {
- // kFHDR config maps to FEC protection always for headers stream.
- // TODO(jri): Add crypto stream in addition to headers for kHDR.
- headers_stream()->set_fec_policy(FEC_PROTECT_ALWAYS);
+ if (bandwidth_resumption_enabled_) {
+ // Only do bandwidth resumption if estimate is recent enough.
+ const int64_t seconds_since_estimate =
+ connection()->clock()->WallNow().ToUNIXSeconds() -
+ cached_network_params->timestamp();
+ if (seconds_since_estimate <= kNumSecondsPerHour) {
+ connection()->ResumeConnectionState(*cached_network_params,
+ max_bandwidth_resumption);
+ }
+ }
}
}
void QuicServerSessionBase::OnConnectionClosed(QuicErrorCode error,
- bool from_peer) {
- QuicSession::OnConnectionClosed(error, from_peer);
+ const string& error_details,
+ ConnectionCloseSource source) {
+ QuicSession::OnConnectionClosed(error, error_details, source);
// In the unlikely event we get a connection close while doing an asynchronous
// crypto event, make sure we cancel the callback.
if (crypto_stream_.get() != nullptr) {
crypto_stream_->CancelOutstandingCallbacks();
}
- visitor_->OnConnectionClosed(connection()->connection_id(), error);
+ visitor_->OnConnectionClosed(connection()->connection_id(), error,
+ error_details);
}
void QuicServerSessionBase::OnWriteBlocked() {
@@ -149,11 +156,20 @@ void QuicServerSessionBase::OnCongestionWindowChange(QuicTime now) {
int32_t max_bandwidth_timestamp = bandwidth_recorder.MaxBandwidthTimestamp();
// Fill the proto before passing it to the crypto stream to send.
+ const int32_t bw_estimate_bytes_per_second =
+ BandwidthToCachedParameterBytesPerSecond(
+ bandwidth_estimate_sent_to_client_);
+ const int32_t max_bw_estimate_bytes_per_second =
+ BandwidthToCachedParameterBytesPerSecond(max_bandwidth_estimate);
+ QUIC_BUG_IF(max_bw_estimate_bytes_per_second < 0)
+ << max_bw_estimate_bytes_per_second;
+ QUIC_BUG_IF(bw_estimate_bytes_per_second < 0) << bw_estimate_bytes_per_second;
+
CachedNetworkParameters cached_network_params;
cached_network_params.set_bandwidth_estimate_bytes_per_second(
- bandwidth_estimate_sent_to_client_.ToBytesPerSecond());
+ bw_estimate_bytes_per_second);
cached_network_params.set_max_bandwidth_estimate_bytes_per_second(
- max_bandwidth_estimate.ToBytesPerSecond());
+ max_bw_estimate_bytes_per_second);
cached_network_params.set_max_bandwidth_timestamp_seconds(
max_bandwidth_timestamp);
cached_network_params.set_min_rtt_ms(
@@ -178,14 +194,15 @@ void QuicServerSessionBase::OnCongestionWindowChange(QuicTime now) {
bool QuicServerSessionBase::ShouldCreateIncomingDynamicStream(QuicStreamId id) {
if (!connection()->connected()) {
- LOG(DFATAL) << "ShouldCreateIncomingDynamicStream called when disconnected";
+ QUIC_BUG << "ShouldCreateIncomingDynamicStream called when disconnected";
return false;
}
if (id % 2 == 0) {
DVLOG(1) << "Invalid incoming even stream_id:" << id;
- connection()->SendConnectionCloseWithDetails(
- QUIC_INVALID_STREAM_ID, "Client created even numbered stream");
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Client created even numbered stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
return true;
@@ -193,14 +210,14 @@ bool QuicServerSessionBase::ShouldCreateIncomingDynamicStream(QuicStreamId id) {
bool QuicServerSessionBase::ShouldCreateOutgoingDynamicStream() {
if (!connection()->connected()) {
- LOG(DFATAL) << "ShouldCreateOutgoingDynamicStream called when disconnected";
+ QUIC_BUG << "ShouldCreateOutgoingDynamicStream called when disconnected";
return false;
}
if (!crypto_stream_->encryption_established()) {
- LOG(DFATAL) << "Encryption not established so no outgoing stream created.";
+ QUIC_BUG << "Encryption not established so no outgoing stream created.";
return false;
}
- if (GetNumOpenOutgoingStreams() >= get_max_open_streams()) {
+ if (GetNumOpenOutgoingStreams() >= max_open_outgoing_streams()) {
VLOG(1) << "No more streams should be created. "
<< "Already " << GetNumOpenOutgoingStreams() << " open.";
return false;
@@ -212,5 +229,12 @@ QuicCryptoServerStreamBase* QuicServerSessionBase::GetCryptoStream() {
return crypto_stream_.get();
}
-} // namespace tools
+int32_t QuicServerSessionBase::BandwidthToCachedParameterBytesPerSecond(
+ const QuicBandwidth& bandwidth) {
+ int64_t bytes_per_second = bandwidth.ToBytesPerSecond();
+ return (bytes_per_second > static_cast<int64_t>(INT32_MAX)
+ ? INT32_MAX
+ : static_cast<int32_t>(bytes_per_second));
+}
+
} // namespace net
diff --git a/chromium/net/tools/quic/quic_server_session_base.h b/chromium/net/tools/quic/quic_server_session_base.h
index a68d52bd293..1f19de4d116 100644
--- a/chromium/net/tools/quic/quic_server_session_base.h
+++ b/chromium/net/tools/quic/quic_server_session_base.h
@@ -16,6 +16,7 @@
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "net/quic/crypto/quic_compressed_certs_cache.h"
#include "net/quic/quic_crypto_server_stream.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_spdy_session.h"
@@ -28,7 +29,6 @@ class QuicConnection;
class QuicCryptoServerConfig;
class ReliableQuicStream;
-namespace tools {
namespace test {
class QuicServerSessionBasePeer;
@@ -43,7 +43,8 @@ class QuicServerSessionVisitor {
virtual ~QuicServerSessionVisitor() {}
virtual void OnConnectionClosed(QuicConnectionId connection_id,
- QuicErrorCode error) = 0;
+ QuicErrorCode error,
+ const std::string& error_details) = 0;
virtual void OnWriteBlocked(QuicBlockedWriterInterface* blocked_writer) = 0;
// Called after the given connection is added to the time-wait list.
virtual void OnConnectionAddedToTimeWaitList(QuicConnectionId connection_id) {
@@ -59,10 +60,13 @@ class QuicServerSessionBase : public QuicSpdySession {
QuicServerSessionBase(const QuicConfig& config,
QuicConnection* connection,
QuicServerSessionVisitor* visitor,
- const QuicCryptoServerConfig* crypto_config);
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache);
// Override the base class to notify the owner of the connection close.
- void OnConnectionClosed(QuicErrorCode error, bool from_peer) override;
+ void OnConnectionClosed(QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) override;
void OnWriteBlocked() override;
// Sends a server config update to the client, containing new bandwidth
@@ -77,7 +81,8 @@ class QuicServerSessionBase : public QuicSpdySession {
return crypto_stream_.get();
}
- // Override base class to process FEC config received from client.
+ // Override base class to process bandwidth related config received from
+ // client.
void OnConfigNegotiated() override;
void set_serving_region(const std::string& serving_region) {
@@ -92,15 +97,16 @@ class QuicServerSessionBase : public QuicSpdySession {
// Return false when connection is closed or forward secure encryption hasn't
// established yet or number of server initiated streams already reaches the
// upper limit.
- bool ShouldCreateOutgoingDynamicStream();
+ bool ShouldCreateOutgoingDynamicStream() override;
// If we should create an incoming stream, returns true. Otherwise
// does error handling, including communicating the error to the client and
// possibly closing the connection, and returns false.
- virtual bool ShouldCreateIncomingDynamicStream(QuicStreamId id);
+ bool ShouldCreateIncomingDynamicStream(QuicStreamId id) override;
virtual QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
- const QuicCryptoServerConfig* crypto_config) = 0;
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache) = 0;
const QuicCryptoServerConfig* crypto_config() { return crypto_config_; }
@@ -109,6 +115,11 @@ class QuicServerSessionBase : public QuicSpdySession {
friend class test::QuicSimpleServerSessionPeer;
const QuicCryptoServerConfig* crypto_config_;
+
+ // The cache which contains most recently compressed certs.
+ // Owned by QuicDispatcher.
+ QuicCompressedCertsCache* compressed_certs_cache_;
+
scoped_ptr<QuicCryptoServerStreamBase> crypto_stream_;
QuicServerSessionVisitor* visitor_;
@@ -128,10 +139,15 @@ class QuicServerSessionBase : public QuicSpdySession {
// Number of packets sent to the peer, at the time we last sent a SCUP.
int64_t last_scup_packet_number_;
+ // Converts QuicBandwidth to an int32 bytes/second that can be
+ // stored in CachedNetworkParameters. TODO(jokulik): This function
+ // should go away once we fix http://b//27897982
+ int32_t BandwidthToCachedParameterBytesPerSecond(
+ const QuicBandwidth& bandwidth);
+
DISALLOW_COPY_AND_ASSIGN(QuicServerSessionBase);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_SERVER_SESSION_BASE_H_
diff --git a/chromium/net/tools/quic/quic_server_session_base_test.cc b/chromium/net/tools/quic/quic_server_session_base_test.cc
index 36432aa5749..282804e81dd 100644
--- a/chromium/net/tools/quic/quic_server_session_base_test.cc
+++ b/chromium/net/tools/quic/quic_server_session_base_test.cc
@@ -26,7 +26,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using __gnu_cxx::vector;
using net::test::CryptoTestUtils;
using net::test::MockConnection;
using net::test::MockConnectionHelper;
@@ -49,7 +48,6 @@ using testing::StrictMock;
using testing::_;
namespace net {
-namespace tools {
namespace test {
class QuicServerSessionBasePeer {
@@ -75,8 +73,13 @@ class TestServerSession : public QuicServerSessionBase {
TestServerSession(const QuicConfig& config,
QuicConnection* connection,
QuicServerSessionVisitor* visitor,
- const QuicCryptoServerConfig* crypto_config)
- : QuicServerSessionBase(config, connection, visitor, crypto_config) {}
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache)
+ : QuicServerSessionBase(config,
+ connection,
+ visitor,
+ crypto_config,
+ compressed_certs_cache) {}
~TestServerSession() override{};
@@ -85,7 +88,9 @@ class TestServerSession : public QuicServerSessionBase {
if (!ShouldCreateIncomingDynamicStream(id)) {
return nullptr;
}
- return new QuicSimpleServerStream(id, this);
+ QuicSpdyStream* stream = new QuicSimpleServerStream(id, this);
+ ActivateStream(stream);
+ return stream;
}
QuicSpdyStream* CreateOutgoingDynamicStream(SpdyPriority priority) override {
@@ -101,8 +106,11 @@ class TestServerSession : public QuicServerSessionBase {
}
QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
- const QuicCryptoServerConfig* crypto_config) override {
- return new QuicCryptoServerStream(crypto_config, this);
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache) override {
+ return new QuicCryptoServerStream(
+ crypto_config, compressed_certs_cache,
+ FLAGS_enable_quic_stateless_reject_support, this);
}
};
@@ -113,7 +121,10 @@ class QuicServerSessionBaseTest : public ::testing::TestWithParam<QuicVersion> {
QuicServerSessionBaseTest()
: crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance(),
- CryptoTestUtils::ProofSourceForTesting()) {
+ CryptoTestUtils::ProofSourceForTesting()),
+ compressed_certs_cache_(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
+ FLAGS_quic_always_log_bugs_for_tests = true;
config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest);
config_.SetInitialStreamFlowControlWindowToSend(
kInitialStreamFlowControlWindowForTest);
@@ -122,8 +133,9 @@ class QuicServerSessionBaseTest : public ::testing::TestWithParam<QuicVersion> {
connection_ = new StrictMock<MockConnection>(
&helper_, Perspective::IS_SERVER, SupportedVersions(GetParam()));
- session_.reset(
- new TestServerSession(config_, connection_, &owner_, &crypto_config_));
+ session_.reset(new TestServerSession(config_, connection_, &owner_,
+ &crypto_config_,
+ &compressed_certs_cache_));
MockClock clock;
handshake_message_.reset(crypto_config_.AddDefaultConfig(
QuicRandom::GetInstance(), &clock,
@@ -137,6 +149,7 @@ class QuicServerSessionBaseTest : public ::testing::TestWithParam<QuicVersion> {
StrictMock<MockConnection>* connection_;
QuicConfig config_;
QuicCryptoServerConfig crypto_config_;
+ QuicCompressedCertsCache compressed_certs_cache_;
scoped_ptr<TestServerSession> session_;
scoped_ptr<CryptoHandshakeMessage> handshake_message_;
QuicConnectionVisitorInterface* visitor_;
@@ -239,12 +252,12 @@ TEST_P(QuicServerSessionBaseTest, MaxOpenStreams) {
// The slightly increased stream limit is set during config negotiation. It
// is either an increase of 10 over negotiated limit, or a fixed percentage
// scaling, whichever is larger. Test both before continuing.
- EXPECT_EQ(kMaxStreamsForTest, session_->get_max_open_streams());
+ EXPECT_EQ(kMaxStreamsForTest, session_->max_open_incoming_streams());
session_->OnConfigNegotiated();
EXPECT_LT(kMaxStreamsMultiplier * kMaxStreamsForTest,
kMaxStreamsForTest + kMaxStreamsMinimumIncrement);
EXPECT_EQ(kMaxStreamsForTest + kMaxStreamsMinimumIncrement,
- session_->get_max_open_streams());
+ session_->max_open_incoming_streams());
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
QuicStreamId stream_id = kClientDataStreamId1;
// Open the max configured number of streams, should be no problem.
@@ -265,10 +278,10 @@ TEST_P(QuicServerSessionBaseTest, MaxOpenStreams) {
stream_id += 2;
if (connection_->version() <= QUIC_VERSION_27) {
EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(QUIC_TOO_MANY_OPEN_STREAMS, _));
+ CloseConnection(QUIC_TOO_MANY_OPEN_STREAMS, _, _));
EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(0);
} else {
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0);
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
EXPECT_CALL(*connection_, SendRstStream(stream_id, QUIC_REFUSED_STREAM, 0));
}
// Even if the connection remains open, the stream creation should fail.
@@ -282,11 +295,12 @@ TEST_P(QuicServerSessionBaseTest, MaxAvailableStreams) {
// stream limit to deal with rare cases where a client FIN/RST is lost.
// The slightly increased stream limit is set during config negotiation.
- EXPECT_EQ(kMaxStreamsForTest, session_->get_max_open_streams());
+ EXPECT_EQ(kMaxStreamsForTest, session_->max_open_incoming_streams());
session_->OnConfigNegotiated();
- const size_t kAvailableStreamLimit = session_->get_max_available_streams();
- EXPECT_EQ(session_->get_max_open_streams() * kMaxAvailableStreamsMultiplier,
- session_->get_max_available_streams());
+ const size_t kAvailableStreamLimit = session_->MaxAvailableStreams();
+ EXPECT_EQ(
+ session_->max_open_incoming_streams() * kMaxAvailableStreamsMultiplier,
+ session_->MaxAvailableStreams());
// The protocol specification requires that there can be at least 10 times
// as many available streams as the connection's maximum open streams.
EXPECT_LE(10 * kMaxStreamsForTest, kAvailableStreamLimit);
@@ -302,8 +316,8 @@ TEST_P(QuicServerSessionBaseTest, MaxAvailableStreams) {
session_.get(), kLimitingStreamId));
// A further available stream will result in connection close.
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_TOO_MANY_AVAILABLE_STREAMS, _));
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
// This forces stream kLimitingStreamId + 2 to become available, which
// violates the quota.
EXPECT_FALSE(QuicServerSessionBasePeer::GetOrCreateDynamicStream(
@@ -312,47 +326,29 @@ TEST_P(QuicServerSessionBaseTest, MaxAvailableStreams) {
TEST_P(QuicServerSessionBaseTest, GetEvenIncomingError) {
// Incoming streams on the server session must be odd.
- EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(QUIC_INVALID_STREAM_ID, _));
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
EXPECT_EQ(nullptr, QuicServerSessionBasePeer::GetOrCreateDynamicStream(
session_.get(), 4));
}
TEST_P(QuicServerSessionBaseTest, GetStreamDisconnected) {
// Don't create new streams if the connection is disconnected.
- QuicConnectionPeer::CloseConnection(connection_);
+ QuicConnectionPeer::TearDownLocalConnectionState(connection_);
EXPECT_DFATAL(
QuicServerSessionBasePeer::GetOrCreateDynamicStream(session_.get(), 5),
"ShouldCreateIncomingDynamicStream called when disconnected");
}
-TEST_P(QuicServerSessionBaseTest, SetFecProtectionFromConfig) {
- ValueRestore<bool> old_flag(&FLAGS_enable_quic_fec, true);
-
- // Set received config to have FEC connection option.
- QuicTagVector copt;
- copt.push_back(kFHDR);
- QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt);
- session_->OnConfigNegotiated();
-
- // Verify that headers stream is always protected and data streams are
- // optionally protected.
- EXPECT_EQ(
- FEC_PROTECT_ALWAYS,
- QuicSpdySessionPeer::GetHeadersStream(session_.get())->fec_policy());
- ReliableQuicStream* stream =
- QuicServerSessionBasePeer::GetOrCreateDynamicStream(session_.get(),
- kClientDataStreamId1);
- ASSERT_TRUE(stream);
- EXPECT_EQ(FEC_PROTECT_OPTIONAL, stream->fec_policy());
-}
-
class MockQuicCryptoServerStream : public QuicCryptoServerStream {
public:
explicit MockQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
QuicSession* session)
- : QuicCryptoServerStream(crypto_config, session) {}
+ : QuicCryptoServerStream(crypto_config,
+ compressed_certs_cache,
+ FLAGS_enable_quic_stateless_reject_support,
+ session) {}
~MockQuicCryptoServerStream() override {}
MOCK_METHOD1(SendServerConfigUpdate,
@@ -386,8 +382,8 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
const string serving_region = "not a real region";
session_->set_serving_region(serving_region);
- MockQuicCryptoServerStream* crypto_stream =
- new MockQuicCryptoServerStream(&crypto_config_, session_.get());
+ MockQuicCryptoServerStream* crypto_stream = new MockQuicCryptoServerStream(
+ &crypto_config_, &compressed_certs_cache_, session_.get());
QuicServerSessionBasePeer::SetCryptoStream(session_.get(), crypto_stream);
// Set some initial bandwidth values.
@@ -407,8 +403,7 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
&bandwidth_recorder, max_bandwidth_estimate_kbytes_per_second,
max_bandwidth_estimate_timestamp);
// Queue up some pending data.
- session_->MarkConnectionLevelWriteBlocked(kCryptoStreamId,
- net::kV3HighestPriority);
+ session_->MarkConnectionLevelWriteBlocked(kCryptoStreamId);
EXPECT_TRUE(session_->HasDataToWrite());
// There will be no update sent yet - not enough time has passed.
@@ -536,5 +531,4 @@ TEST_P(QuicServerSessionBaseTest, NoBandwidthResumptionByDefault) {
} // namespace
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_server_test.cc b/chromium/net/tools/quic/quic_server_test.cc
index 60b2a695629..6cd0d49d024 100644
--- a/chromium/net/tools/quic/quic_server_test.cc
+++ b/chromium/net/tools/quic/quic_server_test.cc
@@ -16,7 +16,6 @@ using net::test::CryptoTestUtils;
using net::test::MockQuicDispatcher;
namespace net {
-namespace tools {
namespace test {
namespace {
@@ -27,13 +26,14 @@ class QuicServerDispatchPacketTest : public ::testing::Test {
: crypto_config_("blah",
QuicRandom::GetInstance(),
CryptoTestUtils::ProofSourceForTesting()),
- dispatcher_(config_,
- &crypto_config_,
- new QuicEpollConnectionHelper(&eps_)) {
+ dispatcher_(
+ config_,
+ &crypto_config_,
+ new QuicEpollConnectionHelper(&eps_, QuicAllocator::BUFFER_POOL)) {
dispatcher_.InitializeWithWriter(new QuicDefaultPacketWriter(1234));
}
- void DispatchPacket(const QuicEncryptedPacket& packet) {
+ void DispatchPacket(const QuicReceivedPacket& packet) {
IPEndPoint client_addr, server_addr;
dispatcher_.ProcessPacket(server_addr, client_addr, packet);
}
@@ -60,8 +60,9 @@ TEST_F(QuicServerDispatchPacketTest, DispatchPacket) {
0x00
};
// clang-format on
- QuicEncryptedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet),
- arraysize(valid_packet), false);
+ QuicReceivedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet),
+ arraysize(valid_packet),
+ QuicTime::Zero(), false);
EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _)).Times(1);
DispatchPacket(encrypted_valid_packet);
@@ -69,5 +70,4 @@ TEST_F(QuicServerDispatchPacketTest, DispatchPacket) {
} // namespace
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_simple_client.cc b/chromium/net/tools/quic/quic_simple_client.cc
index 4c05b6710df..a3d0850f990 100644
--- a/chromium/net/tools/quic/quic_simple_client.cc
+++ b/chromium/net/tools/quic/quic_simple_client.cc
@@ -12,10 +12,10 @@
#include "net/http/http_response_info.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_chromium_connection_helper.h"
+#include "net/quic/quic_chromium_packet_reader.h"
+#include "net/quic/quic_chromium_packet_writer.h"
#include "net/quic/quic_connection.h"
-#include "net/quic/quic_default_packet_writer.h"
#include "net/quic/quic_flags.h"
-#include "net/quic/quic_packet_reader.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_server_id.h"
#include "net/quic/spdy_utils.h"
@@ -27,7 +27,6 @@ using std::string;
using std::vector;
namespace net {
-namespace tools {
void QuicSimpleClient::ClientQuicDataToResend::Resend() {
client_->SendRequest(*headers_, body_, fin_);
@@ -68,8 +67,9 @@ QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address,
QuicSimpleClient::~QuicSimpleClient() {
if (connected()) {
- session()->connection()->SendConnectionClosePacket(QUIC_PEER_GOING_AWAY,
- "");
+ session()->connection()->CloseConnection(
+ QUIC_PEER_GOING_AWAY, "",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
STLDeleteElements(&data_to_resend_on_connect_);
STLDeleteElements(&data_sent_before_handshake_);
@@ -108,13 +108,9 @@ bool QuicSimpleClient::CreateUDPSocket() {
if (bind_to_address_.size() != 0) {
client_address_ = IPEndPoint(bind_to_address_, local_port_);
} else if (address_family == AF_INET) {
- IPAddressNumber any4;
- CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
- client_address_ = IPEndPoint(any4, local_port_);
+ client_address_ = IPEndPoint(IPAddress::IPv4AllZeros(), local_port_);
} else {
- IPAddressNumber any6;
- CHECK(net::ParseIPLiteralToNumber("::", &any6));
- client_address_ = IPEndPoint(any6, local_port_);
+ client_address_ = IPEndPoint(IPAddress::IPv6AllZeros(), local_port_);
}
int rc = socket->Connect(server_address_);
@@ -142,7 +138,7 @@ bool QuicSimpleClient::CreateUDPSocket() {
}
socket_.swap(socket);
- packet_reader_.reset(new QuicPacketReader(
+ packet_reader_.reset(new QuicChromiumPacketReader(
socket_.get(), &clock_, this, kQuicYieldAfterPacketsRead,
QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
BoundNetLog()));
@@ -230,8 +226,9 @@ void QuicSimpleClient::Disconnect() {
DCHECK(initialized_);
if (connected()) {
- session()->connection()->SendConnectionCloseWithDetails(
- QUIC_PEER_GOING_AWAY, "Client disconnecting");
+ session()->connection()->CloseConnection(
+ QUIC_PEER_GOING_AWAY, "Client disconnecting",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
STLDeleteElements(&data_to_resend_on_connect_);
STLDeleteElements(&data_sent_before_handshake_);
@@ -320,7 +317,7 @@ bool QuicSimpleClient::WaitForEvents() {
return session()->num_active_requests() != 0;
}
-bool QuicSimpleClient::MigrateSocket(const IPAddressNumber& new_host) {
+bool QuicSimpleClient::MigrateSocket(const IPAddress& new_host) {
if (!connected()) {
return false;
}
@@ -344,7 +341,8 @@ void QuicSimpleClient::OnClose(QuicSpdyStream* stream) {
QuicSpdyClientStream* client_stream =
static_cast<QuicSpdyClientStream*>(stream);
HttpResponseInfo response;
- SpdyHeadersToHttpResponse(client_stream->headers(), net::HTTP2, &response);
+ SpdyHeadersToHttpResponse(client_stream->response_headers(), net::HTTP2,
+ &response);
if (response_listener_.get() != nullptr) {
response_listener_->OnCompleteResponse(stream->id(), *response.headers,
client_stream->data());
@@ -384,7 +382,7 @@ QuicChromiumConnectionHelper* QuicSimpleClient::CreateQuicConnectionHelper() {
}
QuicPacketWriter* QuicSimpleClient::CreateQuicPacketWriter() {
- return new QuicDefaultPacketWriter(socket_.get());
+ return new QuicChromiumPacketWriter(socket_.get());
}
void QuicSimpleClient::OnReadError(int result,
@@ -393,7 +391,7 @@ void QuicSimpleClient::OnReadError(int result,
Disconnect();
}
-bool QuicSimpleClient::OnPacket(const QuicEncryptedPacket& packet,
+bool QuicSimpleClient::OnPacket(const QuicReceivedPacket& packet,
IPEndPoint local_address,
IPEndPoint peer_address) {
session()->connection()->ProcessUdpPacket(local_address, peer_address,
@@ -405,5 +403,4 @@ bool QuicSimpleClient::OnPacket(const QuicEncryptedPacket& packet,
return true;
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_simple_client.h b/chromium/net/tools/quic/quic_simple_client.h
index ce6e42555f0..bcd0bdabe0f 100644
--- a/chromium/net/tools/quic/quic_simple_client.h
+++ b/chromium/net/tools/quic/quic_simple_client.h
@@ -16,11 +16,12 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/http/http_response_headers.h"
#include "net/log/net_log.h"
+#include "net/quic/quic_chromium_packet_reader.h"
#include "net/quic/quic_config.h"
-#include "net/quic/quic_packet_reader.h"
#include "net/quic/quic_spdy_stream.h"
#include "net/tools/quic/quic_client_base.h"
@@ -30,7 +31,6 @@ struct HttpRequestInfo;
class QuicChromiumConnectionHelper;
class UDPClientSocket;
-namespace tools {
namespace test {
class QuicClientPeer;
@@ -38,7 +38,7 @@ class QuicClientPeer;
class QuicSimpleClient : public QuicClientBase,
public QuicSpdyStream::Visitor,
- public QuicPacketReader::Visitor {
+ public QuicChromiumPacketReader::Visitor {
public:
class ResponseListener {
public:
@@ -126,11 +126,11 @@ class QuicSimpleClient : public QuicClientBase,
const base::CommandLine::StringVector& url_list);
// Migrate to a new socket during an active connection.
- bool MigrateSocket(const IPAddressNumber& new_host);
+ bool MigrateSocket(const IPAddress& new_host);
- // QuicPacketReader::Visitor
+ // QuicChromiumPacketReader::Visitor
void OnReadError(int result, const DatagramClientSocket* socket) override;
- bool OnPacket(const QuicEncryptedPacket& packet,
+ bool OnPacket(const QuicReceivedPacket& packet,
IPEndPoint local_address,
IPEndPoint peer_address) override;
@@ -142,11 +142,11 @@ class QuicSimpleClient : public QuicClientBase,
// Otherwise, deletes the data. Takes ownerership of |data_to_resend|.
void MaybeAddQuicDataToResend(QuicDataToResend* data_to_resend);
- void set_bind_to_address(IPAddressNumber address) {
+ void set_bind_to_address(const IPAddress& address) {
bind_to_address_ = address;
}
- IPAddressNumber bind_to_address() const { return bind_to_address_; }
+ const IPAddress& bind_to_address() const { return bind_to_address_; }
void set_local_port(int local_port) { local_port_ = local_port; }
@@ -170,7 +170,7 @@ class QuicSimpleClient : public QuicClientBase,
virtual QuicPacketWriter* CreateQuicPacketWriter();
private:
- friend class net::tools::test::QuicClientPeer;
+ friend class net::test::QuicClientPeer;
// Specific QuicClient class for storing data to resend.
class ClientQuicDataToResend : public QuicDataToResend {
@@ -214,7 +214,8 @@ class QuicSimpleClient : public QuicClientBase,
IPEndPoint client_address_;
// If initialized, the address to bind to.
- IPAddressNumber bind_to_address_;
+ IPAddress bind_to_address_;
+
// Local port to bind to. Initialize to 0.
int local_port_;
@@ -254,7 +255,7 @@ class QuicSimpleClient : public QuicClientBase,
// The log used for the sockets.
NetLog net_log_;
- scoped_ptr<QuicPacketReader> packet_reader_;
+ scoped_ptr<QuicChromiumPacketReader> packet_reader_;
bool packet_reader_started_;
@@ -263,7 +264,6 @@ class QuicSimpleClient : public QuicClientBase,
DISALLOW_COPY_AND_ASSIGN(QuicSimpleClient);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_SIMPLE_CLIENT_H_
diff --git a/chromium/net/tools/quic/quic_simple_client_bin.cc b/chromium/net/tools/quic/quic_simple_client_bin.cc
index cf261fbcf8e..d7f5ef5757c 100644
--- a/chromium/net/tools/quic/quic_simple_client_bin.cc
+++ b/chromium/net/tools/quic/quic_simple_client_bin.cc
@@ -48,6 +48,7 @@
#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"
@@ -159,8 +160,6 @@ int main(int argc, char* argv[]) {
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
CHECK(logging::InitLogging(settings));
- FLAGS_quic_supports_trailers = true;
-
if (line->HasSwitch("h") || line->HasSwitch("help") || urls.empty()) {
const char* help_str =
"Usage: quic_client [options] <url>\n"
@@ -241,7 +240,7 @@ int main(int argc, char* argv[]) {
base::MessageLoopForIO message_loop;
// Determine IP address to connect to from supplied hostname.
- net::IPAddressNumber ip_addr;
+ net::IPAddress ip_addr;
// TODO(rtenneti): GURL's doesn't support default_protocol argument, thus
// protocol is required in the URL.
@@ -254,9 +253,9 @@ int main(int argc, char* argv[]) {
if (port == 0) {
port = url.EffectiveIntPort();
}
- if (!net::ParseIPLiteralToNumber(host, &ip_addr)) {
+ if (!ip_addr.AssignFromIPLiteral(host)) {
net::AddressList addresses;
- int rv = net::tools::SynchronousHostResolver::Resolve(host, &addresses);
+ int rv = net::SynchronousHostResolver::Resolve(host, &addresses);
if (rv != net::OK) {
LOG(ERROR) << "Unable to resolve '" << host
<< "' : " << net::ErrorToShortString(rv);
@@ -287,8 +286,8 @@ int main(int argc, char* argv[]) {
ProofVerifierChromium* proof_verifier = new ProofVerifierChromium(
cert_verifier.get(), nullptr, transport_security_state.get(),
ct_verifier.get());
- net::tools::QuicSimpleClient client(net::IPEndPoint(ip_addr, port), server_id,
- versions, proof_verifier);
+ net::QuicSimpleClient client(net::IPEndPoint(ip_addr, port), server_id,
+ versions, proof_verifier);
client.set_initial_max_packet_length(
FLAGS_initial_mtu != 0 ? FLAGS_initial_mtu : net::kDefaultMaxPacketSize);
if (!client.Initialize()) {
diff --git a/chromium/net/tools/quic/quic_simple_client_test.cc b/chromium/net/tools/quic/quic_simple_client_test.cc
index 096ff0f59be..02a5807b683 100644
--- a/chromium/net/tools/quic/quic_simple_client_test.cc
+++ b/chromium/net/tools/quic/quic_simple_client_test.cc
@@ -12,7 +12,6 @@
using net::test::CryptoTestUtils;
namespace net {
-namespace tools {
namespace test {
TEST(QuicSimpleClientTest, Initialize) {
@@ -26,5 +25,4 @@ TEST(QuicSimpleClientTest, Initialize) {
}
} // namespace test
-} // namespace tools
} // 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 9020a2ffabe..57c85dd9307 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
@@ -8,7 +8,6 @@
#include "net/tools/quic/quic_simple_server_packet_writer.h"
namespace net {
-namespace tools {
QuicSimplePerConnectionPacketWriter::QuicSimplePerConnectionPacketWriter(
QuicSimpleServerPacketWriter* shared_writer)
@@ -25,10 +24,11 @@ QuicPacketWriter* QuicSimplePerConnectionPacketWriter::shared_writer() const {
WriteResult QuicSimplePerConnectionPacketWriter::WritePacket(
const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) {
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) {
return shared_writer_->WritePacketWithCallback(
- buffer, buf_len, self_address, peer_address,
+ buffer, buf_len, self_address, peer_address, options,
base::Bind(&QuicSimplePerConnectionPacketWriter::OnWriteComplete,
weak_factory_.GetWeakPtr()));
}
@@ -56,5 +56,4 @@ QuicByteCount QuicSimplePerConnectionPacketWriter::GetMaxPacketSize(
return shared_writer_->GetMaxPacketSize(peer_address);
}
-} // namespace tools
} // namespace net
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 b3fd647a0e6..d1d4881efb3 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
@@ -13,7 +13,6 @@
#include "net/quic/quic_packet_writer.h"
namespace net {
-namespace tools {
class QuicSimpleServerPacketWriter;
@@ -36,8 +35,9 @@ class QuicSimplePerConnectionPacketWriter : public QuicPacketWriter {
// to |shared_writer_|.
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) override;
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) override;
bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
@@ -54,7 +54,6 @@ class QuicSimplePerConnectionPacketWriter : public QuicPacketWriter {
DISALLOW_COPY_AND_ASSIGN(QuicSimplePerConnectionPacketWriter);
};
-} // namespace tools
} // namespace net
#endif // NET_QUIC_TOOLS_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 755ab06bdd5..77139862507 100644
--- a/chromium/net/tools/quic/quic_simple_server.cc
+++ b/chromium/net/tools/quic/quic_simple_server.cc
@@ -22,7 +22,6 @@
#include "net/udp/udp_server_socket.h"
namespace net {
-namespace tools {
namespace {
@@ -203,11 +202,11 @@ void QuicSimpleServer::OnReadComplete(int result) {
return;
}
- QuicEncryptedPacket packet(read_buffer_->data(), result, false);
+ QuicReceivedPacket packet(read_buffer_->data(), result,
+ helper_->GetClock()->Now(), false);
dispatcher_->ProcessPacket(server_address_, client_address_, packet);
StartReading();
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_simple_server.h b/chromium/net/tools/quic/quic_simple_server.h
index ba4575e9c6b..21c39bf7521 100644
--- a/chromium/net/tools/quic/quic_simple_server.h
+++ b/chromium/net/tools/quic/quic_simple_server.h
@@ -22,7 +22,6 @@ namespace net {
class UDPServerSocket;
-namespace tools {
class QuicDispatcher;
@@ -113,7 +112,6 @@ class QuicSimpleServer {
DISALLOW_COPY_AND_ASSIGN(QuicSimpleServer);
};
-} // namespace tools
} // namespace net
#endif // NET_QUIC_TOOLS_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 e7ec276e652..b04bf15bce3 100644
--- a/chromium/net/tools/quic/quic_simple_server_bin.cc
+++ b/chromium/net/tools/quic/quic_simple_server_bin.cc
@@ -12,6 +12,7 @@
#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/crypto/proof_source_chromium.h"
#include "net/quic/quic_protocol.h"
@@ -55,7 +56,7 @@ int main(int argc, char* argv[]) {
}
if (line->HasSwitch("quic_in_memory_cache_dir")) {
- net::tools::QuicInMemoryCache::GetInstance()->InitializeFromDirectory(
+ net::QuicInMemoryCache::GetInstance()->InitializeFromDirectory(
line->GetSwitchValueASCII("quic_in_memory_cache_dir"));
}
@@ -76,11 +77,10 @@ int main(int argc, char* argv[]) {
return 1;
}
- net::IPAddressNumber ip;
- CHECK(net::ParseIPLiteralToNumber("::", &ip));
+ net::IPAddress ip = net::IPAddress::IPv6AllZeros();
net::QuicConfig config;
- net::tools::QuicSimpleServer server(
+ net::QuicSimpleServer server(
CreateProofSource(line->GetSwitchValuePath("certificate_file"),
line->GetSwitchValuePath("key_file")),
config, net::QuicSupportedVersions());
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 5754875e2a5..7d64b316e23 100644
--- a/chromium/net/tools/quic/quic_simple_server_packet_writer.cc
+++ b/chromium/net/tools/quic/quic_simple_server_packet_writer.cc
@@ -13,7 +13,6 @@
#include "net/udp/udp_server_socket.h"
namespace net {
-namespace tools {
QuicSimpleServerPacketWriter::QuicSimpleServerPacketWriter(
UDPServerSocket* socket,
@@ -28,12 +27,14 @@ QuicSimpleServerPacketWriter::~QuicSimpleServerPacketWriter() {}
WriteResult QuicSimpleServerPacketWriter::WritePacketWithCallback(
const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
+ const IPAddress& self_address,
const IPEndPoint& peer_address,
+ PerPacketOptions* options,
WriteCallback callback) {
DCHECK(callback_.is_null());
callback_ = callback;
- WriteResult result = WritePacket(buffer, buf_len, self_address, peer_address);
+ WriteResult result =
+ WritePacket(buffer, buf_len, self_address, peer_address, options);
if (result.status != WRITE_STATUS_BLOCKED) {
callback_.Reset();
}
@@ -64,8 +65,9 @@ void QuicSimpleServerPacketWriter::SetWritable() {
WriteResult QuicSimpleServerPacketWriter::WritePacket(
const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) {
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) {
scoped_refptr<StringIOBuffer> buf(
new StringIOBuffer(std::string(buffer, buf_len)));
DCHECK(!IsWriteBlocked());
@@ -97,5 +99,4 @@ QuicByteCount QuicSimpleServerPacketWriter::GetMaxPacketSize(
return kMaxPacketSize;
}
-} // namespace tools
} // namespace net
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 6e4cf8a81a6..3a6b562d639 100644
--- a/chromium/net/tools/quic/quic_simple_server_packet_writer.h
+++ b/chromium/net/tools/quic/quic_simple_server_packet_writer.h
@@ -17,11 +17,11 @@
namespace net {
+class IPAddress;
class QuicBlockedWriterInterface;
class UDPServerSocket;
struct WriteResult;
-namespace tools {
// Chrome specific packet writer which uses a UDPServerSocket for writing
// data.
@@ -36,12 +36,12 @@ class QuicSimpleServerPacketWriter : public QuicPacketWriter {
// Use this method to write packets rather than WritePacket:
// QuicSimpleServerPacketWriter requires a callback to exist for every
// write, which will be called once the write completes.
- virtual WriteResult WritePacketWithCallback(
- const char* buffer,
- size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address,
- WriteCallback callback);
+ virtual WriteResult WritePacketWithCallback(const char* buffer,
+ size_t buf_len,
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options,
+ WriteCallback callback);
void OnWriteComplete(int rv);
@@ -55,8 +55,9 @@ class QuicSimpleServerPacketWriter : public QuicPacketWriter {
// Do not call WritePacket on its own -- use WritePacketWithCallback
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) override;
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) override;
private:
UDPServerSocket* socket_;
@@ -75,7 +76,6 @@ class QuicSimpleServerPacketWriter : public QuicPacketWriter {
DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerPacketWriter);
};
-} // namespace tools
} // namespace net
#endif // NET_QUIC_TOOLS_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 fea72a3a0d3..8a31699e163 100644
--- a/chromium/net/tools/quic/quic_simple_server_session.cc
+++ b/chromium/net/tools/quic/quic_simple_server_session.cc
@@ -14,23 +14,32 @@
#include "net/tools/quic/quic_simple_server_stream.h"
#include "url/gurl.h"
+using std::string;
+
namespace net {
-namespace tools {
QuicSimpleServerSession::QuicSimpleServerSession(
const QuicConfig& config,
QuicConnection* connection,
QuicServerSessionVisitor* visitor,
- const QuicCryptoServerConfig* crypto_config)
- : QuicServerSessionBase(config, connection, visitor, crypto_config),
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache)
+ : QuicServerSessionBase(config,
+ connection,
+ visitor,
+ crypto_config,
+ compressed_certs_cache),
highest_promised_stream_id_(0) {}
QuicSimpleServerSession::~QuicSimpleServerSession() {}
QuicCryptoServerStreamBase*
QuicSimpleServerSession::CreateQuicCryptoServerStream(
- const QuicCryptoServerConfig* crypto_config) {
- return new QuicCryptoServerStream(crypto_config, this);
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache) {
+ return new QuicCryptoServerStream(crypto_config, compressed_certs_cache,
+ FLAGS_enable_quic_stateless_reject_support,
+ this);
}
void QuicSimpleServerSession::StreamDraining(QuicStreamId id) {
@@ -43,8 +52,9 @@ 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";
- connection()->SendConnectionCloseWithDetails(
- QUIC_INVALID_STREAM_ID, "Client sent data on server push stream");
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Client sent data on server push stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
QuicSpdySession::OnStreamFrame(frame);
@@ -52,7 +62,7 @@ void QuicSimpleServerSession::OnStreamFrame(const QuicStreamFrame& frame) {
void QuicSimpleServerSession::PromisePushResources(
const string& request_url,
- const list<QuicInMemoryCache::ServerPushInfo>& resources,
+ const std::list<QuicInMemoryCache::ServerPushInfo>& resources,
QuicStreamId original_stream_id,
const SpdyHeaderBlock& original_request_headers) {
for (QuicInMemoryCache::ServerPushInfo resource : resources) {
@@ -74,7 +84,9 @@ QuicSpdyStream* QuicSimpleServerSession::CreateIncomingDynamicStream(
return nullptr;
}
- return new QuicSimpleServerStream(id, this);
+ QuicSpdyStream* stream = new QuicSimpleServerStream(id, this);
+ ActivateStream(stream);
+ return stream;
}
QuicSimpleServerStream* QuicSimpleServerSession::CreateOutgoingDynamicStream(
@@ -176,11 +188,11 @@ void QuicSimpleServerSession::HandlePromisedPushRequests() {
DCHECK_EQ(promised_info.stream_id, promised_stream->id());
DVLOG(1) << "created server push stream " << promised_stream->id();
- promised_stream->PushResponse(promised_info.request_headers);
+ const SpdyHeaderBlock request_headers(promised_info.request_headers);
promised_streams_.pop_front();
+ promised_stream->PushResponse(request_headers);
}
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_simple_server_session.h b/chromium/net/tools/quic/quic_simple_server_session.h
index d9b2901c4bc..2754f366168 100644
--- a/chromium/net/tools/quic/quic_simple_server_session.h
+++ b/chromium/net/tools/quic/quic_simple_server_session.h
@@ -9,6 +9,8 @@
#include <stdint.h>
+#include <deque>
+#include <list>
#include <set>
#include <string>
#include <vector>
@@ -31,7 +33,6 @@ class QuicConnection;
class QuicCryptoServerConfig;
class ReliableQuicStream;
-namespace tools {
namespace test {
class QuicSimpleServerSessionPeer;
@@ -60,7 +61,8 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
QuicSimpleServerSession(const QuicConfig& config,
QuicConnection* connection,
QuicServerSessionVisitor* visitor,
- const QuicCryptoServerConfig* crypto_config);
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache);
~QuicSimpleServerSession() override;
@@ -77,8 +79,8 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
// And enqueue HEADERS block in those PUSH_PROMISED for sending push response
// later.
virtual void PromisePushResources(
- const string& request_url,
- const list<QuicInMemoryCache::ServerPushInfo>& resources,
+ const std::string& request_url,
+ const std::list<QuicInMemoryCache::ServerPushInfo>& resources,
QuicStreamId original_stream_id,
const SpdyHeaderBlock& original_request_headers);
@@ -98,7 +100,8 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
// QuicServerSessionBaseMethod:
QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
- const QuicCryptoServerConfig* crypto_config) override;
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache) override;
private:
friend class test::QuicSimpleServerSessionPeer;
@@ -110,7 +113,7 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
// Copying the rest headers ensures they are the same as the original
// request, especially cookies.
SpdyHeaderBlock SynthesizePushRequestHeaders(
- string request_url,
+ std::string request_url,
QuicInMemoryCache::ServerPushInfo resource,
const SpdyHeaderBlock& original_request_headers);
@@ -148,7 +151,6 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerSession);
};
-} // namespace tools
} // namespace net
-#endif // NET_TOOLS_QUIC_QUIC_SERVER_SESSION_H_
+#endif // NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_SESSION_H_
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 e3ed3c9e601..ccc9573c95f 100644
--- a/chromium/net/tools/quic/quic_simple_server_session_test.cc
+++ b/chromium/net/tools/quic/quic_simple_server_session_test.cc
@@ -30,8 +30,8 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using __gnu_cxx::vector;
using net::test::CryptoTestUtils;
+using net::test::GenerateBody;
using net::test::MockConnection;
using net::test::MockConnectionHelper;
using net::test::QuicConfigPeer;
@@ -55,7 +55,6 @@ using testing::InSequence;
using testing::Return;
namespace net {
-namespace tools {
namespace test {
namespace {
typedef QuicSimpleServerSession::PromisedStreamInfo PromisedStreamInfo;
@@ -84,8 +83,12 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream {
public:
explicit MockQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
QuicSession* session)
- : QuicCryptoServerStream(crypto_config, session) {}
+ : QuicCryptoServerStream(crypto_config,
+ compressed_certs_cache,
+ FLAGS_enable_quic_stateless_reject_support,
+ session) {}
~MockQuicCryptoServerStream() override {}
MOCK_METHOD1(SendServerConfigUpdate,
@@ -106,12 +109,11 @@ class MockConnectionWithSendStreamData : public MockConnection {
const QuicVersionVector& supported_versions)
: MockConnection(helper, perspective, supported_versions) {}
- MOCK_METHOD6(SendStreamData,
+ MOCK_METHOD5(SendStreamData,
QuicConsumedData(QuicStreamId id,
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
- FecProtection fec_protection,
QuicAckListenerInterface* listern));
};
@@ -154,7 +156,10 @@ class QuicSimpleServerSessionTest
QuicSimpleServerSessionTest()
: crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance(),
- CryptoTestUtils::ProofSourceForTesting()) {
+ CryptoTestUtils::ProofSourceForTesting()),
+ compressed_certs_cache_(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
+ FLAGS_quic_always_log_bugs_for_tests = true;
config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest);
config_.SetInitialStreamFlowControlWindowToSend(
kInitialStreamFlowControlWindowForTest);
@@ -164,7 +169,8 @@ class QuicSimpleServerSessionTest
connection_ = new StrictMock<MockConnectionWithSendStreamData>(
&helper_, Perspective::IS_SERVER, SupportedVersions(GetParam()));
session_.reset(new QuicSimpleServerSession(config_, connection_, &owner_,
- &crypto_config_));
+ &crypto_config_,
+ &compressed_certs_cache_));
MockClock clock;
handshake_message_.reset(crypto_config_.AddDefaultConfig(
QuicRandom::GetInstance(), &clock,
@@ -173,54 +179,8 @@ class QuicSimpleServerSessionTest
visitor_ = QuicConnectionPeer::GetVisitor(connection_);
headers_stream_ = new MockQuicHeadersStream(session_.get());
QuicSpdySessionPeer::SetHeadersStream(session_.get(), headers_stream_);
- }
-
- // Given |num_resources|, create this number of fake push resources and push
- // them by sending PUSH_PROMISE for all and sending push responses for as much
- // as possible(limited by kMaxStreamsForTest).
- // If |num_resources| > kMaxStreamsForTest, the left over will be queued.
- void PromisePushResources(size_t num_resources) {
- // Assume encryption already established.
- MockQuicCryptoServerStream* crypto_stream =
- new MockQuicCryptoServerStream(&crypto_config_, session_.get());
- crypto_stream->set_encryption_established(true);
- QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
-
- 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";
- string partial_push_response_body =
- "Push resource body " + partial_push_resource_path;
- list<QuicInMemoryCache::ServerPushInfo> push_resources;
- string scheme = "http";
- for (unsigned int i = 1; i <= num_resources; ++i) {
- string path = partial_push_resource_path + base::UintToString(i);
- string url = scheme + "://" + resource_host + path;
- GURL resource_url = GURL(url);
- string body = partial_push_response_body + base::UintToString(i);
- SpdyHeaderBlock response_headers;
- QuicInMemoryCache::GetInstance()->AddSimpleResponse(resource_host, path,
- 200, body);
- push_resources.push_back(QuicInMemoryCache::ServerPushInfo(
- resource_url, response_headers, kDefaultPriority, body));
- // PUSH_PROMISED are sent for all the resources.
- EXPECT_CALL(*headers_stream_,
- WritePushPromise(kClientDataStreamId1, i * 2, _, nullptr));
- if (i <= kMaxStreamsForTest) {
- // |kMaxStreamsForTest| promised responses should be sent.
- EXPECT_CALL(*headers_stream_,
- WriteHeaders(i * 2, _, false, kDefaultPriority, nullptr));
- // Mock that SendStreamData() returns less than supposed to send to keep
- // the stream open.
- EXPECT_CALL(*connection_, SendStreamData(i * 2, _, 0, true, _, nullptr))
- .WillOnce(Return(QuicConsumedData(0, false)));
- }
- }
- session_->PromisePushResources(request_url, push_resources,
- kClientDataStreamId1, request_headers);
+ // TODO(jri): Remove this line once tests pass.
+ FLAGS_quic_cede_correctly = false;
}
StrictMock<MockQuicServerSessionVisitor> owner_;
@@ -228,6 +188,7 @@ class QuicSimpleServerSessionTest
StrictMock<MockConnectionWithSendStreamData>* connection_;
QuicConfig config_;
QuicCryptoServerConfig crypto_config_;
+ QuicCompressedCertsCache compressed_certs_cache_;
scoped_ptr<QuicSimpleServerSession> session_;
scoped_ptr<CryptoHandshakeMessage> handshake_message_;
QuicConnectionVisitorInterface* visitor_;
@@ -310,7 +271,7 @@ TEST_P(QuicSimpleServerSessionTest, AcceptClosedStream) {
TEST_P(QuicSimpleServerSessionTest, CreateIncomingDynamicStreamDisconnected) {
// Tests that incoming stream creation fails when connection is not connected.
size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams();
- QuicConnectionPeer::CloseConnection(connection_);
+ QuicConnectionPeer::TearDownLocalConnectionState(connection_);
EXPECT_DFATAL(QuicSimpleServerSessionPeer::CreateIncomingDynamicStream(
session_.get(), kClientDataStreamId1),
"ShouldCreateIncomingDynamicStream called when disconnected");
@@ -320,17 +281,17 @@ TEST_P(QuicSimpleServerSessionTest, CreateIncomingDynamicStreamDisconnected) {
TEST_P(QuicSimpleServerSessionTest, CreateEvenIncomingDynamicStream) {
// Tests that incoming stream creation fails when given stream id is even.
size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams();
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_INVALID_STREAM_ID,
- "Client created even numbered stream"));
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Client created even numbered stream", _));
QuicSimpleServerSessionPeer::CreateIncomingDynamicStream(session_.get(), 2);
EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams());
}
TEST_P(QuicSimpleServerSessionTest, CreateIncomingDynamicStream) {
- std::unique_ptr<QuicSpdyStream> stream(
+ QuicSpdyStream* stream =
QuicSimpleServerSessionPeer::CreateIncomingDynamicStream(
- session_.get(), kClientDataStreamId1));
+ session_.get(), kClientDataStreamId1);
EXPECT_NE(nullptr, stream);
EXPECT_EQ(kClientDataStreamId1, stream->id());
}
@@ -338,7 +299,7 @@ TEST_P(QuicSimpleServerSessionTest, CreateIncomingDynamicStream) {
TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamDisconnected) {
// Tests that outgoing stream creation fails when connection is not connected.
size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams();
- QuicConnectionPeer::CloseConnection(connection_);
+ QuicConnectionPeer::TearDownLocalConnectionState(connection_);
EXPECT_DFATAL(QuicSimpleServerSessionPeer::CreateOutgoingDynamicStream(
session_.get(), kDefaultPriority),
"ShouldCreateOutgoingDynamicStream called when disconnected");
@@ -369,8 +330,8 @@ TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) {
EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
// Assume encryption already established.
- MockQuicCryptoServerStream* crypto_stream =
- new MockQuicCryptoServerStream(&crypto_config_, session_.get());
+ MockQuicCryptoServerStream* crypto_stream = new MockQuicCryptoServerStream(
+ &crypto_config_, &compressed_certs_cache_, session_.get());
crypto_stream->set_encryption_established(true);
QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
@@ -396,13 +357,123 @@ TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) {
TEST_P(QuicSimpleServerSessionTest, OnStreamFrameWithEvenStreamId) {
QuicStreamFrame frame(2, false, 0, StringPiece());
- EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
- QUIC_INVALID_STREAM_ID,
- "Client sent data on server push stream"));
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Client sent data on server push stream", _));
session_->OnStreamFrame(frame);
}
-TEST_P(QuicSimpleServerSessionTest, TestPromisePushResources) {
+TEST_P(QuicSimpleServerSessionTest, GetEvenIncomingError) {
+ // Tests that calling GetOrCreateDynamicStream() on an outgoing stream not
+ // promised yet should result close connection.
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Data for nonexistent stream", _));
+ EXPECT_EQ(nullptr,
+ QuicSessionPeer::GetOrCreateDynamicStream(session_.get(), 4));
+}
+
+// In order to test the case where server push stream creation goes beyond
+// limit, server push streams need to be hanging there instead of
+// immediately closing after sending back response.
+// To achieve this goal, this class resets flow control windows so that large
+// responses will not be sent fully in order to prevent push streams from being
+// closed immediately.
+// Also adjust connection-level flow control window to ensure a large response
+// can cause stream-level flow control blocked but not connection-level.
+class QuicSimpleServerSessionServerPushTest
+ : public QuicSimpleServerSessionTest {
+ protected:
+ const size_t kStreamFlowControlWindowSize = 32 * 1024; // 32KB.
+
+ QuicSimpleServerSessionServerPushTest() : QuicSimpleServerSessionTest() {
+ config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest);
+
+ // Reset stream level flow control window to be 32KB.
+ QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(
+ &config_, kStreamFlowControlWindowSize);
+ // Reset connection level flow control window to be 1.5 MB which is large
+ // enough that it won't block any stream to write before stream level flow
+ // control blocks it.
+ QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
+ &config_, kInitialSessionFlowControlWindowForTest);
+
+ connection_ = new StrictMock<MockConnectionWithSendStreamData>(
+ &helper_, Perspective::IS_SERVER, SupportedVersions(GetParam()));
+ session_.reset(new QuicSimpleServerSession(config_, connection_, &owner_,
+ &crypto_config_,
+ &compressed_certs_cache_));
+ session_->Initialize();
+ // Needed to make new session flow control window 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(
+ &crypto_config_, &compressed_certs_cache_, session_.get());
+ crypto_stream->set_encryption_established(true);
+ QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
+ }
+
+ // Given |num_resources|, create this number of fake push resources and push
+ // them by sending PUSH_PROMISE for all and sending push responses for as much
+ // as possible(limited by kMaxStreamsForTest).
+ // If |num_resources| > kMaxStreamsForTest, the left over will be queued.
+ void PromisePushResources(size_t num_resources) {
+ // To prevent push streams from being closed the response need to be larger
+ // than stream flow control window so stream won't send the full body.
+ size_t body_size = 2 * kStreamFlowControlWindowSize; // 64KB.
+
+ 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;
+ 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 url = scheme + "://" + resource_host + path;
+ GURL resource_url = GURL(url);
+ string body;
+ GenerateBody(&body, body_size);
+ SpdyHeaderBlock response_headers;
+ QuicInMemoryCache::GetInstance()->AddSimpleResponse(resource_host, path,
+ 200, body);
+ push_resources.push_back(QuicInMemoryCache::ServerPushInfo(
+ resource_url, response_headers, kDefaultPriority, body));
+ // PUSH_PROMISED are sent for all the resources.
+ EXPECT_CALL(*headers_stream_, WritePushPromise(kClientDataStreamId1,
+ stream_id, _, nullptr));
+ if (i <= kMaxStreamsForTest) {
+ // |kMaxStreamsForTest| promised responses should be sent.
+ EXPECT_CALL(*headers_stream_, WriteHeaders(stream_id, _, false,
+ kDefaultPriority, nullptr));
+ // Since flow control window is smaller than response body, not the
+ // whole body will be sent.
+ EXPECT_CALL(*connection_,
+ SendStreamData(stream_id, _, 0, false, nullptr))
+ .WillOnce(
+ Return(QuicConsumedData(kStreamFlowControlWindowSize, false)));
+ EXPECT_CALL(*connection_, SendBlocked(stream_id));
+ }
+ }
+ session_->PromisePushResources(request_url, push_resources,
+ kClientDataStreamId1, request_headers);
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(Tests,
+ QuicSimpleServerSessionServerPushTest,
+ ::testing::ValuesIn(QuicSupportedVersions()));
+
+TEST_P(QuicSimpleServerSessionServerPushTest, TestPromisePushResources) {
// Tests that given more than kMaxOpenStreamForTest resources, all their
// PUSH_PROMISE's will be sent out and only |kMaxOpenStreamForTest| streams
// will be opened and send push response.
@@ -411,7 +482,7 @@ TEST_P(QuicSimpleServerSessionTest, TestPromisePushResources) {
EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
}
-TEST_P(QuicSimpleServerSessionTest,
+TEST_P(QuicSimpleServerSessionServerPushTest,
HandlePromisedPushRequestsAfterStreamDraining) {
// Tests that after promised stream queued up, when an opened stream is marked
// draining, a queued promised stream will become open and send push response.
@@ -424,25 +495,17 @@ TEST_P(QuicSimpleServerSessionTest,
EXPECT_CALL(*headers_stream_, WriteHeaders(next_out_going_stream_id, _, false,
kDefaultPriority, nullptr));
EXPECT_CALL(*connection_,
- SendStreamData(next_out_going_stream_id, _, 0, true, _, nullptr))
- .WillOnce(Return(QuicConsumedData(0, false)));
+ SendStreamData(next_out_going_stream_id, _, 0, false, nullptr))
+ .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false)));
+ EXPECT_CALL(*connection_, SendBlocked(next_out_going_stream_id));
session_->StreamDraining(2);
// Number of open outgoing streams should still be the same, because a new
// stream is opened. And the queue should be empty.
EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
}
-TEST_P(QuicSimpleServerSessionTest, GetEvenIncomingError) {
- // Tests that calling GetOrCreateDynamicStream() on an outgoing stream not
- // promised yet should result close connection.
- EXPECT_CALL(*connection_,
- SendConnectionCloseWithDetails(QUIC_INVALID_STREAM_ID,
- "Data for nonexistent stream"));
- EXPECT_EQ(nullptr,
- QuicSessionPeer::GetOrCreateDynamicStream(session_.get(), 4));
-}
-
-TEST_P(QuicSimpleServerSessionTest, ResetPromisedStreamToCancelServerPush) {
+TEST_P(QuicSimpleServerSessionServerPushTest,
+ ResetPromisedStreamToCancelServerPush) {
// Tests that after all resources are promised, a RST frame from client can
// prevent a promised resource to be send out.
@@ -466,8 +529,9 @@ TEST_P(QuicSimpleServerSessionTest, ResetPromisedStreamToCancelServerPush) {
EXPECT_CALL(*headers_stream_, WriteHeaders(stream_not_reset, _, false,
kDefaultPriority, nullptr));
EXPECT_CALL(*connection_,
- SendStreamData(stream_not_reset, _, 0, true, _, nullptr))
- .WillOnce(Return(QuicConsumedData(0, false)));
+ SendStreamData(stream_not_reset, _, 0, false, nullptr))
+ .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false)));
+ EXPECT_CALL(*connection_, SendBlocked(stream_not_reset));
EXPECT_CALL(*headers_stream_, WriteHeaders(stream_got_reset, _, false,
kDefaultPriority, nullptr))
.Times(0);
@@ -476,7 +540,8 @@ TEST_P(QuicSimpleServerSessionTest, ResetPromisedStreamToCancelServerPush) {
session_->StreamDraining(4);
}
-TEST_P(QuicSimpleServerSessionTest, CloseStreamToHandleMorePromisedStream) {
+TEST_P(QuicSimpleServerSessionServerPushTest,
+ CloseStreamToHandleMorePromisedStream) {
// Tests that closing a open outgoing stream can trigger a promised resource
// in the queue to be send out.
size_t num_resources = kMaxStreamsForTest + 1;
@@ -491,14 +556,14 @@ TEST_P(QuicSimpleServerSessionTest, CloseStreamToHandleMorePromisedStream) {
EXPECT_CALL(*headers_stream_, WriteHeaders(stream_to_open, _, false,
kDefaultPriority, nullptr));
EXPECT_CALL(*connection_,
- SendStreamData(stream_to_open, _, 0, true, _, nullptr))
- .WillOnce(Return(QuicConsumedData(0, false)));
+ SendStreamData(stream_to_open, _, 0, false, nullptr))
+ .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false)));
+ EXPECT_CALL(*connection_, SendBlocked(stream_to_open));
QuicRstStreamFrame rst(stream_got_reset, QUIC_STREAM_CANCELLED, 0);
visitor_->OnRstStream(rst);
}
} // namespace
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_simple_server_stream.cc b/chromium/net/tools/quic/quic_simple_server_stream.cc
index 6a34fc6b75a..500754d6330 100644
--- a/chromium/net/tools/quic/quic_simple_server_stream.cc
+++ b/chromium/net/tools/quic/quic_simple_server_stream.cc
@@ -4,11 +4,14 @@
#include "net/tools/quic/quic_simple_server_stream.h"
+#include <list>
+
#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/quic_bug_tracker.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_spdy_stream.h"
#include "net/quic/spdy_utils.h"
@@ -21,7 +24,6 @@ using base::StringToInt;
using std::string;
namespace net {
-namespace tools {
QuicSimpleServerStream::QuicSimpleServerStream(QuicStreamId id,
QuicSpdySession* session)
@@ -43,7 +45,7 @@ void QuicSimpleServerStream::OnInitialHeadersComplete(bool fin,
void QuicSimpleServerStream::OnTrailingHeadersComplete(bool fin,
size_t frame_len) {
- LOG(DFATAL) << "Server does not support receiving Trailers.";
+ QUIC_BUG << "Server does not support receiving Trailers.";
SendErrorResponse();
}
@@ -58,7 +60,7 @@ void QuicSimpleServerStream::OnDataAvailable() {
body_.append(static_cast<char*>(iov.iov_base), iov.iov_len);
if (content_length_ >= 0 &&
- static_cast<int>(body_.size()) > content_length_) {
+ body_.size() > static_cast<uint64_t>(content_length_)) {
DVLOG(1) << "Body size (" << body_.size() << ") > content length ("
<< content_length_ << ").";
SendErrorResponse();
@@ -86,7 +88,7 @@ void QuicSimpleServerStream::OnDataAvailable() {
}
if (content_length_ > 0 &&
- content_length_ != static_cast<int>(body_.size())) {
+ static_cast<uint64_t>(content_length_) != body_.size()) {
DVLOG(1) << "Content length (" << content_length_ << ") != body size ("
<< body_.size() << ").";
SendErrorResponse();
@@ -99,8 +101,7 @@ void QuicSimpleServerStream::OnDataAvailable() {
void QuicSimpleServerStream::PushResponse(
SpdyHeaderBlock push_request_headers) {
if (id() % 2 != 0) {
- LOG(DFATAL) << "Client initiated stream shouldn't be used "
- << "as promised stream.";
+ QUIC_BUG << "Client initiated stream shouldn't be used as promised stream.";
return;
}
// Change the stream state to emulate a client request.
@@ -126,7 +127,7 @@ void QuicSimpleServerStream::SendResponse() {
request_headers_[":authority"], request_headers_[":path"]);
if (response == nullptr) {
DVLOG(1) << "Response not found in cache.";
- SendErrorResponse();
+ SendNotFoundResponse();
return;
}
@@ -143,18 +144,11 @@ void QuicSimpleServerStream::SendResponse() {
// Examing response status, if it was not pure integer as typical h2 response
// status, send error response.
- string request_url;
- if (!request_headers_[":scheme"].as_string().empty()) {
- request_url = request_headers_[":scheme"].as_string() + "://" +
- request_headers_[":authority"].as_string() +
- request_headers_[":path"].as_string();
- } else {
- request_url = request_headers_[":authority"].as_string() +
- request_headers_[":path"].as_string();
- }
+ string request_url = request_headers_[":authority"].as_string() +
+ request_headers_[":path"].as_string();
int response_code;
SpdyHeaderBlock response_headers = response->headers();
- if (!base::StringToInt(response_headers[":status"], &response_code)) {
+ if (!ParseHeaderStatusCode(&response_headers, &response_code)) {
DVLOG(1) << "Illegal (non-integer) response :status from cache: "
<< response_headers[":status"].as_string() << " for request "
<< request_url;
@@ -174,7 +168,7 @@ void QuicSimpleServerStream::SendResponse() {
return;
}
}
- list<QuicInMemoryCache::ServerPushInfo> resources =
+ std::list<QuicInMemoryCache::ServerPushInfo> resources =
QuicInMemoryCache::GetInstance()->GetServerPushResources(request_url);
DVLOG(1) << "Found " << resources.size() << " push resources for stream "
<< id();
@@ -191,6 +185,14 @@ void QuicSimpleServerStream::SendResponse() {
response->trailers());
}
+void QuicSimpleServerStream::SendNotFoundResponse() {
+ DVLOG(1) << "Sending not found response for stream " << id();
+ SpdyHeaderBlock headers;
+ headers[":status"] = "404";
+ headers["content-length"] = base::IntToString(strlen(kNotFoundResponseBody));
+ SendHeadersAndBody(headers, kNotFoundResponseBody);
+}
+
void QuicSimpleServerStream::SendErrorResponse() {
DVLOG(1) << "Sending error response for stream " << id();
SpdyHeaderBlock headers;
@@ -242,6 +244,7 @@ void QuicSimpleServerStream::SendHeadersAndBodyAndTrailers(
}
const char* const QuicSimpleServerStream::kErrorResponseBody = "bad";
+const char* const QuicSimpleServerStream::kNotFoundResponseBody =
+ "file not found";
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_simple_server_stream.h b/chromium/net/tools/quic/quic_simple_server_stream.h
index 015a96a28ac..b88b8471ee6 100644
--- a/chromium/net/tools/quic/quic_simple_server_stream.h
+++ b/chromium/net/tools/quic/quic_simple_server_stream.h
@@ -16,7 +16,6 @@
namespace net {
-namespace tools {
namespace test {
class QuicSimpleServerStreamPeer;
@@ -44,6 +43,7 @@ class QuicSimpleServerStream : public QuicSpdyStream {
// The response body of error responses.
static const char* const kErrorResponseBody;
+ static const char* const kNotFoundResponseBody;
protected:
// Sends a basic 200 response using SendHeaders for the headers and WriteData
@@ -51,9 +51,13 @@ class QuicSimpleServerStream : public QuicSpdyStream {
virtual void SendResponse();
// Sends a basic 500 response using SendHeaders for the headers and WriteData
- // for the body
+ // for the body.
virtual void SendErrorResponse();
+ // Sends a basic 404 response using SendHeaders for the headers and WriteData
+ // for the body.
+ void SendNotFoundResponse();
+
void SendHeadersAndBody(const SpdyHeaderBlock& response_headers,
base::StringPiece body);
void SendHeadersAndBodyAndTrailers(const SpdyHeaderBlock& response_headers,
@@ -69,13 +73,12 @@ class QuicSimpleServerStream : public QuicSpdyStream {
// The parsed headers received from the client.
SpdyHeaderBlock request_headers_;
- int content_length_;
+ int64_t content_length_;
std::string body_;
DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerStream);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_STREAM_H_
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 5c28df03596..2914defbf15 100644
--- a/chromium/net/tools/quic/quic_simple_server_stream_test.cc
+++ b/chromium/net/tools/quic/quic_simple_server_stream_test.cc
@@ -42,8 +42,9 @@ using testing::Return;
using testing::StrictMock;
using testing::WithArgs;
+DECLARE_bool(quic_always_log_bugs_for_tests);
+
namespace net {
-namespace tools {
namespace test {
class QuicSimpleServerStreamPeer : public QuicSimpleServerStream {
@@ -83,28 +84,34 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
public:
const size_t kMaxStreamsForTest = 100;
- explicit MockQuicSimpleServerSession(QuicConnection* connection,
- MockQuicServerSessionVisitor* owner,
- QuicCryptoServerConfig* crypto_config)
- : QuicSimpleServerSession(::net::test::DefaultQuicConfig(),
+ explicit MockQuicSimpleServerSession(
+ QuicConnection* connection,
+ MockQuicServerSessionVisitor* owner,
+ QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache)
+ : QuicSimpleServerSession(DefaultQuicConfig(),
connection,
owner,
- crypto_config) {
- set_max_open_streams(kMaxStreamsForTest);
- ON_CALL(*this, WritevData(_, _, _, _, _, _))
+ crypto_config,
+ compressed_certs_cache) {
+ set_max_open_incoming_streams(kMaxStreamsForTest);
+ set_max_open_outgoing_streams(kMaxStreamsForTest);
+ ON_CALL(*this, WritevData(_, _, _, _, _))
.WillByDefault(testing::Return(QuicConsumedData(0, false)));
}
~MockQuicSimpleServerSession() override {}
- MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer));
+ MOCK_METHOD3(OnConnectionClosed,
+ void(QuicErrorCode error,
+ const string& error_details,
+ ConnectionCloseSource source));
MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id));
- MOCK_METHOD6(WritevData,
+ MOCK_METHOD5(WritevData,
QuicConsumedData(QuicStreamId id,
QuicIOVector data,
QuicStreamOffset offset,
bool fin,
- FecProtection fec_protection,
QuicAckListenerInterface*));
MOCK_METHOD2(OnStreamHeaders,
void(QuicStreamId stream_id, StringPiece headers_data));
@@ -150,8 +157,14 @@ class QuicSimpleServerStreamTest
QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance(),
::net::test::CryptoTestUtils::ProofSourceForTesting())),
- session_(connection_, session_owner_, crypto_config_.get()),
+ compressed_certs_cache_(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
+ session_(connection_,
+ session_owner_,
+ crypto_config_.get(),
+ &compressed_certs_cache_),
body_("hello world") {
+ FLAGS_quic_always_log_bugs_for_tests = true;
SpdyHeaderBlock request_headers;
request_headers[":host"] = "";
request_headers[":authority"] = "www.google.com";
@@ -194,6 +207,7 @@ class QuicSimpleServerStreamTest
StrictMock<MockConnection>* connection_;
StrictMock<MockQuicServerSessionVisitor>* session_owner_;
std::unique_ptr<QuicCryptoServerConfig> crypto_config_;
+ QuicCompressedCertsCache compressed_certs_cache_;
StrictMock<MockQuicSimpleServerSession> session_;
QuicSimpleServerStreamPeer* stream_; // Owned by session_.
string headers_string_;
@@ -205,7 +219,7 @@ INSTANTIATE_TEST_CASE_P(Tests,
::testing::ValuesIn(QuicSupportedVersions()));
TEST_P(QuicSimpleServerStreamTest, TestFraming) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData));
stream_->OnStreamHeaders(headers_string_);
@@ -219,7 +233,7 @@ TEST_P(QuicSimpleServerStreamTest, TestFraming) {
}
TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData));
@@ -234,7 +248,7 @@ TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) {
}
TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorInStopReading) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData));
@@ -257,7 +271,7 @@ TEST_P(QuicSimpleServerStreamTest, TestFramingExtraData) {
// We'll automatically write out an error (headers + body)
EXPECT_CALL(session_, WriteHeaders(_, _, _, _, _));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.WillOnce(Invoke(MockQuicSpdySession::ConsumeAllData));
EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0);
@@ -275,7 +289,7 @@ TEST_P(QuicSimpleServerStreamTest, TestFramingExtraData) {
}
TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus) {
- // Send a illegal response with response status not supported by HTTP/2.
+ // Send an illegal response with response status not supported by HTTP/2.
SpdyHeaderBlock* request_headers = stream_->mutable_headers();
(*request_headers)[":path"] = "/bar";
(*request_headers)[":authority"] = "www.google.com";
@@ -294,7 +308,38 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus) {
InSequence s;
EXPECT_CALL(session_, WriteHeaders(stream_->id(), _, false, _, nullptr));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(Return(QuicConsumedData(
+ strlen(QuicSimpleServerStream::kErrorResponseBody), true)));
+
+ QuicSimpleServerStreamPeer::SendResponse(stream_);
+ EXPECT_FALSE(ReliableQuicStreamPeer::read_side_closed(stream_));
+ EXPECT_TRUE(stream_->reading_stopped());
+ EXPECT_TRUE(stream_->write_side_closed());
+}
+
+TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus2) {
+ // Send an illegal response with response status not supported by HTTP/2.
+ SpdyHeaderBlock* request_headers = stream_->mutable_headers();
+ (*request_headers)[":path"] = "/bar";
+ (*request_headers)[":authority"] = "www.google.com";
+ (*request_headers)[":version"] = "HTTP/1.1";
+ (*request_headers)[":method"] = "GET";
+
+ response_headers_[":version"] = "HTTP/1.1";
+ // HTTP/2 only supports 3-digit-integer, so "+200" is illegal.
+ response_headers_[":status"] = "+200";
+ response_headers_["content-length"] = "5";
+ string body = "Yummm";
+ QuicInMemoryCache::GetInstance()->AddResponse("www.google.com", "/bar",
+ response_headers_, body);
+
+ stream_->set_fin_received(true);
+
+ InSequence s;
+ EXPECT_CALL(session_, WriteHeaders(stream_->id(), _, false, _, nullptr));
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(
strlen(QuicSimpleServerStream::kErrorResponseBody), true)));
@@ -351,7 +396,7 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithValidHeaders) {
InSequence s;
EXPECT_CALL(session_, WriteHeaders(stream_->id(), _, false, _, nullptr));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(body.length(), true)));
@@ -390,7 +435,7 @@ TEST_P(QuicSimpleServerStreamTest, SendReponseWithPushResources) {
::net::test::kClientDataStreamId1,
*request_headers));
EXPECT_CALL(session_, WriteHeaders(stream_->id(), _, false, _, nullptr));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(body.length(), true)));
QuicSimpleServerStreamPeer::SendResponse(stream_);
@@ -435,8 +480,8 @@ TEST_P(QuicSimpleServerStreamTest, PushResponseOnServerInitiatedStream) {
// and send it back.
EXPECT_CALL(session_,
WriteHeaders(kServerInitiatedStreamId, _, false,
- server_initiated_stream->Priority(), nullptr));
- EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, _, _, _, _, _))
+ server_initiated_stream->priority(), nullptr));
+ EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(kBody.size(), true)));
server_initiated_stream->PushResponse(headers);
@@ -458,7 +503,7 @@ TEST_P(QuicSimpleServerStreamTest, TestSendErrorResponse) {
InSequence s;
EXPECT_CALL(session_, WriteHeaders(_, _, _, _, _));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(3, true)));
@@ -478,7 +523,7 @@ TEST_P(QuicSimpleServerStreamTest, InvalidMultipleContentLength) {
headers_string_ = SpdyUtils::SerializeUncompressedHeaders(request_headers);
EXPECT_CALL(session_, WriteHeaders(_, _, _, _, _));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData));
stream_->OnStreamHeaders(headers_string_);
@@ -499,7 +544,7 @@ TEST_P(QuicSimpleServerStreamTest, InvalidLeadingNullContentLength) {
headers_string_ = SpdyUtils::SerializeUncompressedHeaders(request_headers);
EXPECT_CALL(session_, WriteHeaders(_, _, _, _, _));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData));
stream_->OnStreamHeaders(headers_string_);
@@ -533,7 +578,7 @@ TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorWithEarlyResponse) {
InSequence s;
EXPECT_CALL(session_, WriteHeaders(stream_->id(), _, _, _, _));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(3, true)));
if (GetParam() > QUIC_VERSION_28) {
@@ -597,5 +642,4 @@ TEST_P(QuicSimpleServerStreamTest, InvalidHeadersWithFin) {
} // namespace
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_simple_server_test.cc b/chromium/net/tools/quic/quic_simple_server_test.cc
index d98069c5c3c..3a7c54ee1f9 100644
--- a/chromium/net/tools/quic/quic_simple_server_test.cc
+++ b/chromium/net/tools/quic/quic_simple_server_test.cc
@@ -15,7 +15,6 @@ using ::testing::_;
using net::test::CryptoTestUtils;
namespace net {
-namespace tools {
namespace test {
// TODO(dmz) Remove "Chrome" part of name once net/tools/quic is deleted.
@@ -31,7 +30,7 @@ class QuicChromeServerDispatchPacketTest : public ::testing::Test {
dispatcher_.InitializeWithWriter(nullptr);
}
- void DispatchPacket(const QuicEncryptedPacket& packet) {
+ void DispatchPacket(const QuicReceivedPacket& packet) {
IPEndPoint client_addr, server_addr;
dispatcher_.ProcessPacket(server_addr, client_addr, packet);
}
@@ -52,13 +51,13 @@ TEST_F(QuicChromeServerDispatchPacketTest, DispatchPacket) {
0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
// private flags
0x00};
- QuicEncryptedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet),
- arraysize(valid_packet), false);
+ QuicReceivedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet),
+ arraysize(valid_packet),
+ QuicTime::Zero(), false);
EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _)).Times(1);
DispatchPacket(encrypted_valid_packet);
}
-} // namespace tools
} // namespace test
} // namespace net
diff --git a/chromium/net/tools/quic/quic_socket_utils.cc b/chromium/net/tools/quic/quic_socket_utils.cc
index 1853a6bf568..1ef874ca45f 100644
--- a/chromium/net/tools/quic/quic_socket_utils.cc
+++ b/chromium/net/tools/quic/quic_socket_utils.cc
@@ -5,6 +5,7 @@
#include "net/tools/quic/quic_socket_utils.h"
#include <errno.h>
+#include <linux/net_tstamp.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
@@ -12,6 +13,8 @@
#include <string>
#include "base/logging.h"
+#include "net/quic/quic_bug_tracker.h"
+#include "net/quic/quic_flags.h"
#include "net/quic/quic_protocol.h"
#ifndef SO_RXQ_OVFL
@@ -19,31 +22,38 @@
#endif
namespace net {
-namespace tools {
// static
-IPAddressNumber QuicSocketUtils::GetAddressFromMsghdr(struct msghdr* hdr) {
+void QuicSocketUtils::GetAddressAndTimestampFromMsghdr(struct msghdr* hdr,
+ IPAddress* address,
+ QuicTime* timestamp) {
if (hdr->msg_controllen > 0) {
for (cmsghdr* cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr;
cmsg = CMSG_NXTHDR(hdr, cmsg)) {
const uint8_t* addr_data = nullptr;
int len = 0;
if (cmsg->cmsg_type == IPV6_PKTINFO) {
- in6_pktinfo* info = reinterpret_cast<in6_pktinfo*> CMSG_DATA(cmsg);
+ in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg));
addr_data = reinterpret_cast<const uint8_t*>(&info->ipi6_addr);
len = sizeof(in6_addr);
+ *address = IPAddress(addr_data, len);
} else if (cmsg->cmsg_type == IP_PKTINFO) {
- in_pktinfo* info = reinterpret_cast<in_pktinfo*> CMSG_DATA(cmsg);
+ in_pktinfo* info = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg));
addr_data = reinterpret_cast<const uint8_t*>(&info->ipi_addr);
len = sizeof(in_addr);
- } else {
- continue;
+ *address = IPAddress(addr_data, len);
+ } else if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SO_TIMESTAMPING) {
+ LinuxTimestamping* lts =
+ reinterpret_cast<LinuxTimestamping*>(CMSG_DATA(cmsg));
+ timespec* ts = &lts->systime;
+ int64_t usec = (static_cast<int64_t>(ts->tv_sec) * 1000 * 1000) +
+ (static_cast<int64_t>(ts->tv_nsec) / 1000);
+ *timestamp =
+ QuicTime::Zero().Add(QuicTime::Delta::FromMicroseconds(usec));
}
- return IPAddressNumber(addr_data, addr_data + len);
}
}
- DCHECK(false) << "Unable to get address from msghdr";
- return IPAddressNumber();
}
// static
@@ -75,6 +85,13 @@ int QuicSocketUtils::SetGetAddressInfo(int fd, int address_family) {
}
// static
+int QuicSocketUtils::SetGetSoftwareReceiveTimestamp(int fd) {
+ int timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
+ return setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, &timestamping,
+ sizeof(timestamping));
+}
+
+// static
bool QuicSocketUtils::SetSendBufferSize(int fd, size_t size) {
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) != 0) {
LOG(ERROR) << "Failed to set socket send size";
@@ -97,12 +114,11 @@ int QuicSocketUtils::ReadPacket(int fd,
char* buffer,
size_t buf_len,
QuicPacketCount* dropped_packets,
- IPAddressNumber* self_address,
+ IPAddress* self_address,
+ QuicTime* timestamp,
IPEndPoint* peer_address) {
DCHECK(peer_address != nullptr);
- const int kSpaceForOverflowAndIp =
- CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(in6_pktinfo));
- char cbuf[kSpaceForOverflowAndIp];
+ char cbuf[kSpaceForCmsg];
memset(cbuf, 0, arraysize(cbuf));
iovec iov = {buffer, buf_len};
@@ -131,13 +147,28 @@ int QuicSocketUtils::ReadPacket(int fd,
return -1;
}
+ if (hdr.msg_controllen >= arraysize(cbuf)) {
+ QUIC_BUG << "Incorrectly set control length: " << hdr.msg_controllen
+ << ", expected " << arraysize(cbuf);
+ return -1;
+ }
+
if (dropped_packets != nullptr) {
GetOverflowFromMsghdr(&hdr, dropped_packets);
}
- if (self_address != nullptr) {
- *self_address = QuicSocketUtils::GetAddressFromMsghdr(&hdr);
+
+ IPAddress stack_address;
+ if (self_address == nullptr) {
+ self_address = &stack_address;
+ }
+
+ QuicTime stack_timestamp = QuicTime::Zero();
+ if (timestamp == nullptr) {
+ timestamp = &stack_timestamp;
}
+ GetAddressAndTimestampFromMsghdr(&hdr, self_address, timestamp);
+
if (raw_address.ss_family == AF_INET) {
CHECK(peer_address->FromSockAddr(
reinterpret_cast<const sockaddr*>(&raw_address),
@@ -151,25 +182,30 @@ int QuicSocketUtils::ReadPacket(int fd,
return bytes_read;
}
-size_t QuicSocketUtils::SetIpInfoInCmsg(const IPAddressNumber& self_address,
+size_t QuicSocketUtils::SetIpInfoInCmsg(const IPAddress& self_address,
cmsghdr* cmsg) {
- if (GetAddressFamily(self_address) == ADDRESS_FAMILY_IPV4) {
+ if (self_address.IsIPv4()) {
cmsg->cmsg_len = CMSG_LEN(sizeof(in_pktinfo));
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_PKTINFO;
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[0], self_address.size());
+ memcpy(&pktinfo->ipi_spec_dst, self_address.bytes().data(),
+ self_address.size());
return sizeof(in_pktinfo);
- } else {
+ } else if (self_address.IsIPv6()) {
cmsg->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo));
cmsg->cmsg_level = IPPROTO_IPV6;
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[0], self_address.size());
+ memcpy(&pktinfo->ipi6_addr, self_address.bytes().data(),
+ self_address.size());
return sizeof(in6_pktinfo);
+ } else {
+ NOTREACHED() << "Unrecognized IPAddress";
+ return 0;
}
}
@@ -177,7 +213,7 @@ size_t QuicSocketUtils::SetIpInfoInCmsg(const IPAddressNumber& self_address,
WriteResult QuicSocketUtils::WritePacket(int fd,
const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
+ const IPAddress& self_address,
const IPEndPoint& peer_address) {
sockaddr_storage raw_address;
socklen_t address_len = sizeof(raw_address);
@@ -209,7 +245,10 @@ WriteResult QuicSocketUtils::WritePacket(int fd,
hdr.msg_controllen = cmsg->cmsg_len;
}
- int rc = sendmsg(fd, &hdr, 0);
+ int rc;
+ do {
+ rc = sendmsg(fd, &hdr, 0);
+ } while (rc < 0 && errno == EINTR);
if (rc >= 0) {
return WriteResult(WRITE_STATUS_OK, rc);
}
@@ -219,5 +258,48 @@ WriteResult QuicSocketUtils::WritePacket(int fd,
errno);
}
-} // namespace tools
+// static
+int QuicSocketUtils::CreateUDPSocket(const IPEndPoint& address,
+ bool* overflow_supported) {
+ int address_family = address.GetSockAddrFamily();
+ int fd = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
+ if (fd < 0) {
+ LOG(ERROR) << "socket() failed: " << strerror(errno);
+ return -1;
+ }
+
+ int get_overflow = 1;
+ int rc = setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
+ sizeof(get_overflow));
+ if (rc < 0) {
+ DLOG(WARNING) << "Socket overflow detection not supported";
+ } else {
+ *overflow_supported = true;
+ }
+
+ if (!SetReceiveBufferSize(fd, kDefaultSocketReceiveBuffer)) {
+ return -1;
+ }
+
+ if (!SetSendBufferSize(fd, kDefaultSocketReceiveBuffer)) {
+ return -1;
+ }
+
+ rc = SetGetAddressInfo(fd, address_family);
+ if (rc < 0) {
+ LOG(ERROR) << "IP detection not supported" << strerror(errno);
+ return -1;
+ }
+
+ if (FLAGS_quic_use_socket_timestamp) {
+ rc = SetGetSoftwareReceiveTimestamp(fd);
+ if (rc < 0) {
+ LOG(WARNING) << "SO_TIMESTAMPING not supported; using fallback: "
+ << strerror(errno);
+ }
+ }
+
+ return fd;
+}
+
} // namespace net
diff --git a/chromium/net/tools/quic/quic_socket_utils.h b/chromium/net/tools/quic/quic_socket_utils.h
index 2d152f9a36e..72e90f84f23 100644
--- a/chromium/net/tools/quic/quic_socket_utils.h
+++ b/chromium/net/tools/quic/quic_socket_utils.h
@@ -7,25 +7,51 @@
#ifndef NET_TOOLS_QUIC_QUIC_SOCKET_UTILS_H_
#define NET_TOOLS_QUIC_QUIC_SOCKET_UTILS_H_
+#include <netinet/in.h>
#include <stddef.h>
#include <sys/socket.h>
#include <string>
#include "base/macros.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/quic_bandwidth.h"
#include "net/quic/quic_types.h"
namespace net {
-namespace tools {
+
+// 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
+// https://www.kernel.org/doc/Documentation/networking/timestamping.txt for more
+// information.
+struct LinuxTimestamping {
+ // The converted system time of the timestamp.
+ struct timespec systime;
+ // Deprecated; serves only as padding.
+ struct timespec hwtimetrans;
+ // The raw hardware timestamp.
+ struct timespec hwtimeraw;
+};
class QuicSocketUtils {
public:
- // If the msghdr contains IP_PKTINFO or IPV6_PKTINFO, this will return the
- // IPAddressNumber in that header. Returns an uninitialized IPAddress on
- // failure.
- static IPAddressNumber GetAddressFromMsghdr(struct msghdr* hdr);
+ // The first integer is for overflow. The in6_pktinfo is the larger of the
+ // address structures present. LinuxTimestamping is present for socket
+ // timestamping.
+ // The final int is a sentinel so the msg_controllen feedback
+ // can be used to detect larger control messages than there is space for.
+ static const int kSpaceForCmsg =
+ CMSG_SPACE(CMSG_LEN(sizeof(int)) + CMSG_LEN(sizeof(in6_pktinfo)) +
+ CMSG_LEN(sizeof(LinuxTimestamping)) +
+ CMSG_LEN(sizeof(int)));
+
+ // Fills in |address| if |hdr| contains IP_PKTINFO or IPV6_PKTINFO. Fills in
+ // |timestamp| if |hdr| contains |SO_TIMESTAMPING|. |address| and |timestamp|
+ // must not be null.
+ static void GetAddressAndTimestampFromMsghdr(struct msghdr* hdr,
+ IPAddress* address,
+ QuicTime* timestamp);
// If the msghdr contains an SO_RXQ_OVFL entry, this will set dropped_packets
// to the correct value and return true. Otherwise it will return false.
@@ -36,6 +62,10 @@ class QuicSocketUtils {
// address_family. Returns the return code from setsockopt.
static int SetGetAddressInfo(int fd, int address_family);
+ // Sets SO_TIMESTAMPING on the socket for software receive timestamping.
+ // Returns the return code from setsockopt.
+ static int SetGetSoftwareReceiveTimestamp(int fd);
+
// Sets the send buffer size to |size| and returns false if it fails.
static bool SetSendBufferSize(int fd, size_t size);
@@ -51,11 +81,17 @@ class QuicSocketUtils {
//
// If self_address is non-null, it will be set to the address the peer sent
// packets to, assuming a packet was read.
+ //
+ // If timestamp is non-null, it will be filled with the timestamp of the
+ // received packet, assuming a packet was read and the platform supports
+ // packet receipt timestamping. If the platform does not support packet
+ // receipt timestamping, timestamp will not be changed.
static int ReadPacket(int fd,
char* buffer,
size_t buf_len,
QuicPacketCount* dropped_packets,
- IPAddressNumber* self_address,
+ IPAddress* self_address,
+ QuicTime* timestamp,
IPEndPoint* peer_address);
// Writes buf_len to the socket. If writing is successful, sets the result's
@@ -65,20 +101,24 @@ class QuicSocketUtils {
static WriteResult WritePacket(int fd,
const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
+ const IPAddress& self_address,
const IPEndPoint& 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 IPAddressNumber& self_address,
- cmsghdr* cmsg);
+ static size_t SetIpInfoInCmsg(const IPAddress& 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,
+ bool* overflow_supported);
private:
DISALLOW_COPY_AND_ASSIGN(QuicSocketUtils);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_SOCKET_UTILS_H_
diff --git a/chromium/net/tools/quic/quic_spdy_client_stream.cc b/chromium/net/tools/quic/quic_spdy_client_stream.cc
index a77cab7fbac..8ac758a5236 100644
--- a/chromium/net/tools/quic/quic_spdy_client_stream.cc
+++ b/chromium/net/tools/quic/quic_spdy_client_stream.cc
@@ -7,6 +7,8 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
+#include "net/quic/quic_alarm.h"
+#include "net/quic/quic_client_promised_info.h"
#include "net/quic/spdy_utils.h"
#include "net/spdy/spdy_protocol.h"
#include "net/tools/quic/quic_client_session.h"
@@ -17,7 +19,6 @@ using std::string;
using base::StringToInt;
namespace net {
-namespace tools {
QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id,
QuicClientSession* session)
@@ -26,7 +27,8 @@ QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id,
response_code_(0),
header_bytes_read_(0),
header_bytes_written_(0),
- allow_bidirectional_data_(false) {}
+ allow_bidirectional_data_(false),
+ session_(session) {}
QuicSpdyClientStream::~QuicSpdyClientStream() {}
@@ -44,49 +46,60 @@ void QuicSpdyClientStream::OnInitialHeadersComplete(bool fin,
QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len);
DCHECK(headers_decompressed());
- header_bytes_read_ = frame_len;
+ header_bytes_read_ += frame_len;
if (!SpdyUtils::ParseHeaders(decompressed_headers().data(),
decompressed_headers().length(),
&content_length_, &response_headers_)) {
+ DLOG(ERROR) << "Failed to parse headers: " << decompressed_headers();
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return;
}
- string status = response_headers_[":status"].as_string();
- size_t end = status.find(" ");
- if (end != string::npos) {
- status.erase(end);
- }
- if (!StringToInt(status, &response_code_)) {
- // Invalid response code.
+ if (!ParseHeaderStatusCode(&response_headers_, &response_code_)) {
+ DLOG(ERROR) << "Received invalid response code: "
+ << response_headers_[":status"].as_string();
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return;
}
MarkHeadersConsumed(decompressed_headers().length());
+ DVLOG(1) << "headers complete for stream " << id();
+
+ session_->OnInitialHeadersComplete(id(), response_headers_);
}
void QuicSpdyClientStream::OnTrailingHeadersComplete(bool fin,
size_t frame_len) {
QuicSpdyStream::OnTrailingHeadersComplete(fin, frame_len);
+ MarkTrailersConsumed(decompressed_trailers().length());
+}
- size_t final_byte_offset = 0;
- if (!SpdyUtils::ParseTrailers(decompressed_trailers().data(),
- decompressed_trailers().length(),
- &final_byte_offset, &response_trailers_)) {
+void QuicSpdyClientStream::OnPromiseHeadersComplete(QuicStreamId promised_id,
+ size_t frame_len) {
+ header_bytes_read_ += frame_len;
+ int64_t content_length = -1;
+ SpdyHeaderBlock promise_headers;
+ if (!SpdyUtils::ParseHeaders(decompressed_headers().data(),
+ decompressed_headers().length(), &content_length,
+ &promise_headers)) {
+ DLOG(ERROR) << "Failed to parse promise headers: "
+ << decompressed_headers();
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return;
}
- MarkTrailersConsumed(decompressed_trailers().length());
+ MarkHeadersConsumed(decompressed_headers().length());
- // The data on this stream ends at |final_byte_offset|.
- DVLOG(1) << "Stream ends at byte offset: " << final_byte_offset
- << " currently read: " << stream_bytes_read();
- OnStreamFrame(
- QuicStreamFrame(id(), /*fin=*/true, final_byte_offset, StringPiece()));
+ session_->HandlePromised(id(), promised_id, promise_headers);
}
void QuicSpdyClientStream::OnDataAvailable() {
+ if (FLAGS_quic_supports_push_promise) {
+ // For push streams, visitor will not be set until the rendezvous
+ // between server promise and client request is complete.
+ if (visitor() == nullptr)
+ return;
+ }
+
while (HasBytesToRead()) {
struct iovec iov;
if (GetReadableRegions(&iov, 1) == 0) {
@@ -98,7 +111,9 @@ void QuicSpdyClientStream::OnDataAvailable() {
data_.append(static_cast<char*>(iov.iov_base), iov.iov_len);
if (content_length_ >= 0 &&
- static_cast<int>(data_.size()) > content_length_) {
+ data_.size() > static_cast<uint64_t>(content_length_)) {
+ DLOG(ERROR) << "Invalid content length (" << content_length_
+ << ") with data of size " << data_.size();
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return;
}
@@ -126,15 +141,4 @@ size_t QuicSpdyClientStream::SendRequest(const SpdyHeaderBlock& headers,
return bytes_sent;
}
-void QuicSpdyClientStream::SendBody(const string& data, bool fin) {
- SendBody(data, fin, nullptr);
-}
-
-void QuicSpdyClientStream::SendBody(const string& data,
- bool fin,
- QuicAckListenerInterface* listener) {
- WriteOrBufferData(data, fin, listener);
-}
-
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_spdy_client_stream.h b/chromium/net/tools/quic/quic_spdy_client_stream.h
index d56eb554b6d..f225717c2ff 100644
--- a/chromium/net/tools/quic/quic_spdy_client_stream.h
+++ b/chromium/net/tools/quic/quic_spdy_client_stream.h
@@ -7,7 +7,6 @@
#include <stddef.h>
#include <sys/types.h>
-
#include <string>
#include "base/macros.h"
@@ -17,7 +16,6 @@
#include "net/spdy/spdy_framer.h"
namespace net {
-namespace tools {
class QuicClientSession;
@@ -39,6 +37,10 @@ class QuicSpdyClientStream : public QuicSpdyStream {
// Override the base class to parse and store trailers.
void OnTrailingHeadersComplete(bool fin, size_t frame_len) override;
+ // Override the base class to handle creation of the push stream.
+ void OnPromiseHeadersComplete(QuicStreamId promised_stream_id,
+ size_t frame_len) override;
+
// ReliableQuicStream implementation called by the session when there's
// data for us.
void OnDataAvailable() override;
@@ -49,21 +51,11 @@ class QuicSpdyClientStream : public QuicSpdyStream {
base::StringPiece body,
bool fin);
- // Sends body data to the server, or buffers if it can't be sent immediately.
- void SendBody(const std::string& data, bool fin);
- // As above, but |delegate| will be notified once |data| is ACKed.
- void SendBody(const std::string& data,
- bool fin,
- QuicAckListenerInterface* listener);
-
// Returns the response data.
const std::string& data() { return data_; }
// Returns whatever headers have been received for this stream.
- const SpdyHeaderBlock& headers() { return response_headers_; }
-
- // Returns whatever trailers have been received for this stream.
- const SpdyHeaderBlock& trailers() { return response_trailers_; }
+ const SpdyHeaderBlock& response_headers() { return response_headers_; }
size_t header_bytes_read() const { return header_bytes_read_; }
@@ -87,11 +79,8 @@ class QuicSpdyClientStream : public QuicSpdyStream {
// The parsed headers received from the server.
SpdyHeaderBlock response_headers_;
- // The parsed trailers received from the server.
- SpdyHeaderBlock response_trailers_;
-
// The parsed content-length, or -1 if none is specified.
- int content_length_;
+ int64_t content_length_;
int response_code_;
std::string data_;
size_t header_bytes_read_;
@@ -100,10 +89,11 @@ class QuicSpdyClientStream : public QuicSpdyStream {
// arriving.
bool allow_bidirectional_data_;
+ QuicClientSession* session_;
+
DISALLOW_COPY_AND_ASSIGN(QuicSpdyClientStream);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_STREAM_H_
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 eaefac5843f..53e414d8f29 100644
--- a/chromium/net/tools/quic/quic_spdy_client_stream_test.cc
+++ b/chromium/net/tools/quic/quic_spdy_client_stream_test.cc
@@ -11,7 +11,6 @@
#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"
-#include "net/tools/quic/quic_spdy_client_stream.h"
#include "net/tools/quic/spdy_balsa_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -22,26 +21,30 @@ using net::test::MockConnection;
using net::test::MockConnectionHelper;
using net::test::SupportedVersions;
using net::test::kClientDataStreamId1;
+using net::test::kServerDataStreamId1;
using net::test::kInitialSessionFlowControlWindowForTest;
using net::test::kInitialStreamFlowControlWindowForTest;
+using net::test::ValueRestore;
using std::string;
using testing::StrictMock;
using testing::TestWithParam;
namespace net {
-namespace tools {
namespace test {
+
namespace {
class MockQuicClientSession : public QuicClientSession {
public:
- explicit MockQuicClientSession(QuicConnection* connection)
+ explicit MockQuicClientSession(QuicConnection* connection,
+ QuicClientPushPromiseIndex* push_promise_index)
: QuicClientSession(
DefaultQuicConfig(),
connection,
- QuicServerId("example.com", 80, PRIVACY_MODE_DISABLED),
- &crypto_config_),
+ QuicServerId("example.com", 443, PRIVACY_MODE_DISABLED),
+ &crypto_config_,
+ push_promise_index),
crypto_config_(CryptoTestUtils::ProofVerifierForTesting()) {}
~MockQuicClientSession() override {}
@@ -55,37 +58,60 @@ class MockQuicClientSession : public QuicClientSession {
class QuicSpdyClientStreamTest : public ::testing::Test {
public:
+ class StreamVisitor;
+
QuicSpdyClientStreamTest()
: connection_(
new StrictMock<MockConnection>(&helper_, Perspective::IS_CLIENT)),
- session_(connection_),
+ session_(connection_, &push_promise_index_),
body_("hello world") {
session_.Initialize();
headers_.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "Ok");
headers_.ReplaceOrAppendHeader("content-length", "11");
- headers_string_ =
- net::tools::SpdyBalsaUtils::SerializeResponseHeaders(headers_);
+ headers_string_ = net::SpdyBalsaUtils::SerializeResponseHeaders(headers_);
stream_.reset(new QuicSpdyClientStream(kClientDataStreamId1, &session_));
+ stream_visitor_.reset(new StreamVisitor());
+ stream_->set_visitor(stream_visitor_.get());
}
+ class StreamVisitor : public QuicSpdyClientStream::Visitor {
+ void OnClose(QuicSpdyStream* stream) override {
+ DVLOG(1) << "stream " << stream->id();
+ }
+ };
+
MockConnectionHelper helper_;
StrictMock<MockConnection>* connection_;
+ QuicClientPushPromiseIndex push_promise_index_;
+
MockQuicClientSession session_;
scoped_ptr<QuicSpdyClientStream> stream_;
+ scoped_ptr<StreamVisitor> stream_visitor_;
BalsaHeaders headers_;
string headers_string_;
string body_;
};
+TEST_F(QuicSpdyClientStreamTest, TestReceivingIllegalResponseStatusCode) {
+ headers_.ReplaceOrAppendHeader(":status", "200 ok");
+ headers_string_ = SpdyBalsaUtils::SerializeResponseHeaders(headers_);
+
+ stream_->OnStreamHeaders(headers_string_);
+ EXPECT_CALL(*connection_,
+ SendRstStream(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD, 0));
+ stream_->OnStreamHeadersComplete(false, headers_string_.size());
+ EXPECT_EQ(QUIC_BAD_APPLICATION_PAYLOAD, stream_->stream_error());
+}
+
TEST_F(QuicSpdyClientStreamTest, TestFraming) {
stream_->OnStreamHeaders(headers_string_);
stream_->OnStreamHeadersComplete(false, headers_string_.size());
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_));
- EXPECT_EQ("200", stream_->headers().find(":status")->second);
+ EXPECT_EQ("200", stream_->response_headers().find(":status")->second);
EXPECT_EQ(200, stream_->response_code());
EXPECT_EQ(body_, stream_->data());
}
@@ -95,7 +121,7 @@ TEST_F(QuicSpdyClientStreamTest, TestFramingOnePacket) {
stream_->OnStreamHeadersComplete(false, headers_string_.size());
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_));
- EXPECT_EQ("200", stream_->headers().find(":status")->second);
+ EXPECT_EQ("200", stream_->response_headers().find(":status")->second);
EXPECT_EQ(200, stream_->response_code());
EXPECT_EQ(body_, stream_->data());
}
@@ -107,7 +133,7 @@ TEST_F(QuicSpdyClientStreamTest, DISABLED_TestFramingExtraData) {
stream_->OnStreamHeadersComplete(false, headers_string_.size());
// The headers should parse successfully.
EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
- EXPECT_EQ("200", stream_->headers().find(":status")->second);
+ EXPECT_EQ("200", stream_->response_headers().find(":status")->second);
EXPECT_EQ(200, stream_->response_code());
EXPECT_CALL(*connection_,
@@ -129,8 +155,6 @@ TEST_F(QuicSpdyClientStreamTest, TestNoBidirectionalStreaming) {
TEST_F(QuicSpdyClientStreamTest, ReceivingTrailers) {
// Test that receiving trailing headers, containing a final offset, results in
// the stream being closed at that byte offset.
- FLAGS_quic_supports_trailers = true;
-
// Send headers as usual.
stream_->OnStreamHeaders(headers_string_);
stream_->OnStreamHeadersComplete(false, headers_string_.size());
@@ -154,5 +178,4 @@ TEST_F(QuicSpdyClientStreamTest, ReceivingTrailers) {
} // namespace
} // namespace test
-} // namespace tools
} // 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 9472e736aaa..91c48d089b0 100644
--- a/chromium/net/tools/quic/quic_time_wait_list_manager.cc
+++ b/chromium/net/tools/quic/quic_time_wait_list_manager.cc
@@ -24,7 +24,6 @@
using base::StringPiece;
namespace net {
-namespace tools {
// A very simple alarm that just informs the QuicTimeWaitListManager to clean
// up old connection_ids. This alarm should be cancelled and deleted before
@@ -35,10 +34,8 @@ class ConnectionIdCleanUpAlarm : public QuicAlarm::Delegate {
QuicTimeWaitListManager* time_wait_list_manager)
: time_wait_list_manager_(time_wait_list_manager) {}
- QuicTime OnAlarm() override {
+ void OnAlarm() override {
time_wait_list_manager_->CleanUpOldConnectionIds();
- // Let the time wait manager register the alarm at appropriate time.
- return QuicTime::Zero();
}
private:
@@ -191,6 +188,17 @@ void QuicTimeWaitListManager::ProcessPacket(
SendPublicReset(server_address, client_address, connection_id, packet_number);
}
+void QuicTimeWaitListManager::SendVersionNegotiationPacket(
+ QuicConnectionId connection_id,
+ const QuicVersionVector& supported_versions,
+ const IPEndPoint& server_address,
+ const IPEndPoint& client_address) {
+ QueuedPacket* packet = new QueuedPacket(
+ server_address, client_address, QuicFramer::BuildVersionNegotiationPacket(
+ connection_id, supported_versions));
+ SendOrQueuePacket(packet);
+}
+
// Returns true if the number of packets received for this connection_id is a
// power of 2 to throttle the number of public reset packets we send to a
// client.
@@ -241,7 +249,7 @@ 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());
+ queued_packet->client_address(), nullptr);
if (result.status == WRITE_STATUS_BLOCKED) {
// If blocked and unbuffered, return false to retry sending.
DCHECK(writer_->IsWriteBlocked());
@@ -326,7 +334,9 @@ QuicTimeWaitListManager::ConnectionIdData::ConnectionIdData(
time_added(time_added_),
connection_rejected_statelessly(connection_rejected_statelessly) {}
+QuicTimeWaitListManager::ConnectionIdData::ConnectionIdData(
+ const ConnectionIdData& other) = default;
+
QuicTimeWaitListManager::ConnectionIdData::~ConnectionIdData() {}
-} // namespace tools
} // namespace net
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 777ab0eb691..52e1d6210ca 100644
--- a/chromium/net/tools/quic/quic_time_wait_list_manager.h
+++ b/chromium/net/tools/quic/quic_time_wait_list_manager.h
@@ -22,7 +22,6 @@
#include "net/quic/quic_protocol.h"
namespace net {
-namespace tools {
class QuicServerSessionVisitor;
@@ -99,6 +98,14 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
// The number of connections on the time-wait list.
size_t num_connections() const { return connection_id_map_.size(); }
+ // Sends a version negotiation packet for |connection_id| announcing support
+ // for |supported_versions| to |client_address| from |server_address|.
+ virtual void SendVersionNegotiationPacket(
+ QuicConnectionId connection_id,
+ const QuicVersionVector& supported_versions,
+ const IPEndPoint& server_address,
+ const IPEndPoint& client_address);
+
protected:
virtual QuicEncryptedPacket* BuildPublicReset(
const QuicPublicResetPacket& packet);
@@ -150,6 +157,8 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
QuicTime time_added_,
bool connection_rejected_statelessly);
+ ConnectionIdData(const ConnectionIdData& other);
+
~ConnectionIdData();
int num_packets;
@@ -187,7 +196,6 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
DISALLOW_COPY_AND_ASSIGN(QuicTimeWaitListManager);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_TIME_WAIT_LIST_MANAGER_H_
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 a1c7b6008aa..58c9112d0c2 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
@@ -46,7 +46,6 @@ using testing::Truly;
using testing::_;
namespace net {
-namespace tools {
namespace test {
class FramerVisitorCapturingPublicReset : public NoOpFramerVisitor {
@@ -95,7 +94,7 @@ class MockFakeTimeEpollServer : public FakeTimeEpollServer {
class QuicTimeWaitListManagerTest : public ::testing::Test {
protected:
QuicTimeWaitListManagerTest()
- : helper_(&epoll_server_),
+ : helper_(&epoll_server_, QuicAllocator::BUFFER_POOL),
time_wait_list_manager_(&writer_, &visitor_, &helper_),
connection_id_(45),
client_address_(net::test::TestPeerIPAddress(), kTestPort),
@@ -146,6 +145,7 @@ class QuicTimeWaitListManagerTest : public ::testing::Test {
QuicConnectionId connection_id,
QuicPacketNumber packet_number) {
return net::test::ConstructEncryptedPacket(connection_id, false, false,
+ false, kDefaultPathId,
packet_number, "data");
}
@@ -218,6 +218,21 @@ TEST_F(QuicTimeWaitListManagerTest, CheckStatelessConnectionIdInTimeWait) {
EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_));
}
+TEST_F(QuicTimeWaitListManagerTest, SendVersionNegotiationPacket) {
+ scoped_ptr<QuicEncryptedPacket> packet(
+ QuicFramer::BuildVersionNegotiationPacket(connection_id_,
+ QuicSupportedVersions()));
+ EXPECT_CALL(writer_,
+ WritePacket(_, packet->length(), server_address_.address(),
+ client_address_, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
+
+ time_wait_list_manager_.SendVersionNegotiationPacket(
+ connection_id_, QuicSupportedVersions(), server_address_,
+ client_address_);
+ EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
+}
+
TEST_F(QuicTimeWaitListManagerTest, SendConnectionClose) {
const size_t kConnectionCloseLength = 100;
EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
@@ -228,8 +243,9 @@ 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_.address(),
+ client_address_, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
ProcessPacket(connection_id_, kRandomSequenceNumber);
@@ -247,8 +263,9 @@ 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_.address(),
+ client_address_, _))
.Times(2)
.WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 1)));
@@ -260,9 +277,8 @@ TEST_F(QuicTimeWaitListManagerTest, SendPublicReset) {
AddConnectionId(connection_id_);
const int kRandomSequenceNumber = 1;
EXPECT_CALL(writer_,
- WritePacket(_, _, server_address_.address(), client_address_))
- .With(Args<0, 1>(
- PublicResetPacketEq(connection_id_, kRandomSequenceNumber)))
+ WritePacket(_, _, server_address_.address(), client_address_, _))
+ .With(Args<0, 1>(PublicResetPacketEq(connection_id_, 0)))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
ProcessPacket(connection_id_, kRandomSequenceNumber);
@@ -274,7 +290,7 @@ TEST_F(QuicTimeWaitListManagerTest, SendPublicResetWithExponentialBackOff) {
EXPECT_EQ(1u, time_wait_list_manager_.num_connections());
for (int packet_number = 1; packet_number < 101; ++packet_number) {
if ((packet_number & (packet_number - 1)) == 0) {
- EXPECT_CALL(writer_, WritePacket(_, _, _, _))
+ EXPECT_CALL(writer_, WritePacket(_, _, _, _, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
}
ProcessPacket(connection_id_, packet_number);
@@ -295,7 +311,7 @@ TEST_F(QuicTimeWaitListManagerTest, NoPublicResetForStatelessConnections) {
const int kRandomSequenceNumber = 1;
EXPECT_CALL(writer_,
- WritePacket(_, _, server_address_.address(), client_address_))
+ WritePacket(_, _, server_address_.address(), client_address_, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
ProcessPacket(connection_id_, kRandomSequenceNumber);
@@ -362,15 +378,15 @@ TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
ConstructEncryptedPacket(connection_id, packet_number));
// Let first write through.
EXPECT_CALL(writer_,
- WritePacket(_, _, server_address_.address(), client_address_))
- .With(Args<0, 1>(PublicResetPacketEq(connection_id, packet_number)))
+ WritePacket(_, _, server_address_.address(), 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_))
- .With(Args<0, 1>(PublicResetPacketEq(connection_id, packet_number)))
+ WritePacket(_, _, server_address_.address(), client_address_, _))
+ .With(Args<0, 1>(PublicResetPacketEq(connection_id, 0)))
.WillOnce(DoAll(Assign(&writer_is_blocked_, true),
Return(WriteResult(WRITE_STATUS_BLOCKED, EAGAIN))));
EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_));
@@ -386,7 +402,7 @@ TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
QuicPacketNumber other_packet_number = 23423;
scoped_ptr<QuicEncryptedPacket> other_packet(
ConstructEncryptedPacket(other_connection_id, other_packet_number));
- EXPECT_CALL(writer_, WritePacket(_, _, _, _)).Times(0);
+ EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(0);
EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_));
ProcessPacket(other_connection_id, other_packet_number);
EXPECT_EQ(2u, time_wait_list_manager_.num_connections());
@@ -394,13 +410,12 @@ 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_))
- .With(Args<0, 1>(PublicResetPacketEq(connection_id, packet_number)))
+ WritePacket(_, _, server_address_.address(), 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_))
- .With(Args<0, 1>(
- PublicResetPacketEq(other_connection_id, other_packet_number)))
+ WritePacket(_, _, server_address_.address(), 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,8 +462,9 @@ 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_.address(),
+ client_address_, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
const int kRandomSequenceNumber = 1;
@@ -541,5 +557,4 @@ TEST_F(QuicTimeWaitListManagerTest, MaxConnectionsTest) {
} // namespace
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/spdy_balsa_utils.cc b/chromium/net/tools/quic/spdy_balsa_utils.cc
index b298e38c79d..dd24c9935d2 100644
--- a/chromium/net/tools/quic/spdy_balsa_utils.cc
+++ b/chromium/net/tools/quic/spdy_balsa_utils.cc
@@ -20,12 +20,12 @@
#include "url/gurl.h"
using base::StringPiece;
+using base::StringPieceHash;
using std::make_pair;
using std::pair;
using std::string;
namespace net {
-namespace tools {
namespace {
const char kV4Host[] = ":authority";
@@ -41,7 +41,7 @@ void PopulateSpdyHeaderBlock(const BalsaHeaders& headers,
SpdyHeaderBlock* block,
bool allow_empty_values) {
using HeaderValuesMap =
- linked_hash_map<StringPiece, std::vector<StringPiece>>;
+ linked_hash_map<StringPiece, std::vector<StringPiece>, StringPieceHash>;
std::deque<string> names;
HeaderValuesMap header_values_map;
// First, gather references to all values for each name.
@@ -227,16 +227,16 @@ SpdyHeaderBlock SpdyBalsaUtils::RequestHeadersToSpdyHeaders(
if (url.empty() || url[0] == '/') {
path = url;
} else {
- GURL request_uri(url);
+ std::unique_ptr<GURL> request_uri(new GURL(url));
if (request_headers.request_method() == "CONNECT") {
path = url;
} else {
- path = request_uri.path();
- if (!request_uri.query().empty()) {
- path = path + "?" + request_uri.query();
+ path = request_uri->path();
+ if (!request_uri->query().empty()) {
+ path = path + "?" + request_uri->query();
}
- host_and_port = request_uri.host();
- scheme = request_uri.scheme();
+ host_and_port = request_uri->host();
+ scheme = request_uri->scheme();
}
}
@@ -279,5 +279,4 @@ void SpdyBalsaUtils::SpdyHeadersToRequestHeaders(const SpdyHeaderBlock& block,
SpdyHeadersToBalsaHeaders(block, headers, SpdyHeaderValidatorType::REQUEST);
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/spdy_balsa_utils.h b/chromium/net/tools/quic/spdy_balsa_utils.h
index 6cbdffa2db2..a1d555a642b 100644
--- a/chromium/net/tools/quic/spdy_balsa_utils.h
+++ b/chromium/net/tools/quic/spdy_balsa_utils.h
@@ -15,7 +15,6 @@
#include "net/tools/balsa/balsa_headers.h"
namespace net {
-namespace tools {
class SpdyBalsaUtils {
public:
@@ -38,7 +37,6 @@ class SpdyBalsaUtils {
DISALLOW_COPY_AND_ASSIGN(SpdyBalsaUtils);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_SPDY_BALSA_UTILS_H_
diff --git a/chromium/net/tools/quic/spdy_balsa_utils_test.cc b/chromium/net/tools/quic/spdy_balsa_utils_test.cc
index 0bceda367ad..0a7f2fabe25 100644
--- a/chromium/net/tools/quic/spdy_balsa_utils_test.cc
+++ b/chromium/net/tools/quic/spdy_balsa_utils_test.cc
@@ -8,7 +8,6 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
-namespace tools {
namespace test {
namespace {
@@ -81,5 +80,4 @@ TEST(SpdyBalsaUtilsTest, SpdyHeadersToResponseHeaders) {
} // namespace
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/synchronous_host_resolver.cc b/chromium/net/tools/quic/synchronous_host_resolver.cc
index b0ec18ed18c..2808cc7dad1 100644
--- a/chromium/net/tools/quic/synchronous_host_resolver.cc
+++ b/chromium/net/tools/quic/synchronous_host_resolver.cc
@@ -18,7 +18,6 @@
namespace net {
-namespace tools {
namespace {
@@ -101,5 +100,4 @@ int SynchronousHostResolver::Resolve(const std::string& host,
return resolver.Resolve(host, addresses);
}
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/synchronous_host_resolver.h b/chromium/net/tools/quic/synchronous_host_resolver.h
index 258c8e4dedc..7089c874251 100644
--- a/chromium/net/tools/quic/synchronous_host_resolver.h
+++ b/chromium/net/tools/quic/synchronous_host_resolver.h
@@ -13,14 +13,12 @@
namespace net {
-namespace tools {
class SynchronousHostResolver {
public:
static int Resolve(const std::string& host, AddressList* addresses);
};
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_SYNCHRONOUS_HOST_RESOLVER_H_
diff --git a/chromium/net/tools/quic/test_tools/http_message.cc b/chromium/net/tools/quic/test_tools/http_message.cc
index 1ea56382c73..3f2c2573fd3 100644
--- a/chromium/net/tools/quic/test_tools/http_message.cc
+++ b/chromium/net/tools/quic/test_tools/http_message.cc
@@ -14,7 +14,6 @@ using std::string;
using std::vector;
namespace net {
-namespace tools {
namespace test {
namespace {
@@ -154,5 +153,4 @@ void HTTPMessage::ValidateMessage() const {
}
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/test_tools/http_message.h b/chromium/net/tools/quic/test_tools/http_message.h
index de0ee3a5314..bbf770baa90 100644
--- a/chromium/net/tools/quic/test_tools/http_message.h
+++ b/chromium/net/tools/quic/test_tools/http_message.h
@@ -14,7 +14,6 @@
#include "net/tools/balsa/balsa_headers.h"
namespace net {
-namespace tools {
namespace test {
class HttpConstants {
@@ -123,7 +122,6 @@ class HTTPMessage {
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_TEST_TOOLS_HTTP_MESSAGE_H_
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 1e9fa7daa79..4af2439759a 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
@@ -5,27 +5,25 @@
#include "net/tools/quic/test_tools/limited_mtu_test_writer.h"
namespace net {
-namespace tools {
namespace test {
LimitedMtuTestWriter::LimitedMtuTestWriter(QuicByteCount mtu) : mtu_(mtu) {}
LimitedMtuTestWriter::~LimitedMtuTestWriter() {}
-WriteResult LimitedMtuTestWriter::WritePacket(
- const char* buffer,
- size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) {
+WriteResult LimitedMtuTestWriter::WritePacket(const char* buffer,
+ size_t buf_len,
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) {
if (buf_len > mtu_) {
// Drop the packet.
return WriteResult(WRITE_STATUS_OK, buf_len);
}
return QuicPacketWriterWrapper::WritePacket(buffer, buf_len, self_address,
- peer_address);
+ peer_address, options);
}
} // namespace test
-} // namespace tools
} // namespace net
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 31040828b8f..a9efa7f1d91 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
@@ -12,7 +12,6 @@
#include "net/tools/quic/quic_packet_writer_wrapper.h"
namespace net {
-namespace tools {
namespace test {
// Simulates a connection over a link with fixed MTU. Drops packets which
@@ -25,8 +24,9 @@ class LimitedMtuTestWriter : public QuicPacketWriterWrapper {
// Inherited from QuicPacketWriterWrapper.
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) override;
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) override;
private:
QuicByteCount mtu_;
@@ -35,7 +35,6 @@ class LimitedMtuTestWriter : public QuicPacketWriterWrapper {
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_LIMITED_MTU_TEST_WRITER_H_
diff --git a/chromium/net/tools/quic/test_tools/mock_epoll_server.cc b/chromium/net/tools/quic/test_tools/mock_epoll_server.cc
index b5cd974681e..11b6ada74d4 100644
--- a/chromium/net/tools/quic/test_tools/mock_epoll_server.cc
+++ b/chromium/net/tools/quic/test_tools/mock_epoll_server.cc
@@ -5,7 +5,6 @@
#include "net/tools/quic/test_tools/mock_epoll_server.h"
namespace net {
-namespace tools {
namespace test {
FakeTimeEpollServer::FakeTimeEpollServer() : now_in_usec_(0) {}
@@ -58,5 +57,4 @@ int MockEpollServer::epoll_wait_impl(int epfd,
}
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/test_tools/mock_epoll_server.h b/chromium/net/tools/quic/test_tools/mock_epoll_server.h
index e10fc498697..f56f4ab1953 100644
--- a/chromium/net/tools/quic/test_tools/mock_epoll_server.h
+++ b/chromium/net/tools/quic/test_tools/mock_epoll_server.h
@@ -14,7 +14,6 @@
#include "testing/gmock/include/gmock/gmock.h"
namespace net {
-namespace tools {
namespace test {
// Unlike the full MockEpollServer, this only lies about the time but lets
@@ -108,7 +107,6 @@ class MockEpollServer : public FakeTimeEpollServer {
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_MOCK_EPOLL_SERVER_H_
diff --git a/chromium/net/tools/quic/test_tools/mock_quic_server_session_visitor.cc b/chromium/net/tools/quic/test_tools/mock_quic_server_session_visitor.cc
index 552c2954233..489555cd0f6 100644
--- a/chromium/net/tools/quic/test_tools/mock_quic_server_session_visitor.cc
+++ b/chromium/net/tools/quic/test_tools/mock_quic_server_session_visitor.cc
@@ -5,7 +5,6 @@
#include "net/tools/quic/test_tools/mock_quic_server_session_visitor.h"
namespace net {
-namespace tools {
namespace test {
MockQuicServerSessionVisitor::MockQuicServerSessionVisitor() {}
@@ -13,5 +12,4 @@ MockQuicServerSessionVisitor::MockQuicServerSessionVisitor() {}
MockQuicServerSessionVisitor::~MockQuicServerSessionVisitor() {}
} // namespace test
-} // namespace tools
} // namespace net
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 15fba1d62a5..22a1b05bc45 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
@@ -10,15 +10,16 @@
#include "testing/gmock/include/gmock/gmock.h"
namespace net {
-namespace tools {
namespace test {
class MockQuicServerSessionVisitor : public QuicServerSessionVisitor {
public:
MockQuicServerSessionVisitor();
- virtual ~MockQuicServerSessionVisitor();
- MOCK_METHOD2(OnConnectionClosed,
- void(QuicConnectionId connection_id, QuicErrorCode error));
+ virtual ~MockQuicServerSessionVisitor() override;
+ MOCK_METHOD3(OnConnectionClosed,
+ void(QuicConnectionId connection_id,
+ QuicErrorCode error,
+ const std::string& error_details));
MOCK_METHOD1(OnWriteBlocked,
void(QuicBlockedWriterInterface* blocked_writer));
MOCK_METHOD1(OnConnectionAddedToTimeWaitList,
@@ -31,7 +32,6 @@ class MockQuicServerSessionVisitor : public QuicServerSessionVisitor {
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_SERVER_SESSION_VISITOR_H_
diff --git a/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.cc b/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.cc
index 8e972f3b7c8..468e6efded7 100644
--- a/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.cc
+++ b/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.cc
@@ -9,7 +9,6 @@ using testing::AnyNumber;
using testing::Invoke;
namespace net {
-namespace tools {
namespace test {
MockTimeWaitListManager::MockTimeWaitListManager(
@@ -30,5 +29,4 @@ MockTimeWaitListManager::MockTimeWaitListManager(
MockTimeWaitListManager::~MockTimeWaitListManager() {}
} // namespace test
-} // namespace tools
} // namespace net
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 116fd7e30c9..5d5542b14a6 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
@@ -11,7 +11,6 @@
#include "testing/gmock/include/gmock/gmock.h"
namespace net {
-namespace tools {
namespace test {
class MockTimeWaitListManager : public QuicTimeWaitListManager {
@@ -43,10 +42,15 @@ class MockTimeWaitListManager : public QuicTimeWaitListManager {
QuicConnectionId connection_id,
QuicPacketNumber packet_number,
const QuicEncryptedPacket& packet));
+
+ MOCK_METHOD4(SendVersionNegotiationPacket,
+ void(QuicConnectionId connection_id,
+ const QuicVersionVector& supported_versions,
+ const IPEndPoint& server_address,
+ const IPEndPoint& client_address));
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_TIME_WAIT_LIST_MANAGER_H_
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 5e1bfb81063..3858b7828b8 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
@@ -11,7 +11,6 @@
#include "net/tools/quic/quic_socket_utils.h"
namespace net {
-namespace tools {
namespace test {
// An alarm that is scheduled if a blocked socket is simulated to indicate
@@ -21,10 +20,9 @@ class WriteUnblockedAlarm : public QuicAlarm::Delegate {
explicit WriteUnblockedAlarm(PacketDroppingTestWriter* writer)
: writer_(writer) {}
- QuicTime OnAlarm() override {
+ void OnAlarm() override {
DVLOG(1) << "Unblocking socket.";
writer_->OnCanWrite();
- return QuicTime::Zero();
}
private:
@@ -37,7 +35,12 @@ class DelayAlarm : public QuicAlarm::Delegate {
public:
explicit DelayAlarm(PacketDroppingTestWriter* writer) : writer_(writer) {}
- QuicTime OnAlarm() override { return writer_->ReleaseOldPackets(); }
+ void OnAlarm() override {
+ QuicTime new_deadline = writer_->ReleaseOldPackets();
+ if (new_deadline.IsInitialized()) {
+ writer_->SetDelayAlarm(new_deadline);
+ }
+ }
private:
PacketDroppingTestWriter* writer_;
@@ -74,8 +77,9 @@ void PacketDroppingTestWriter::Initialize(QuicConnectionHelperInterface* helper,
WriteResult PacketDroppingTestWriter::WritePacket(
const char* buffer,
size_t buf_len,
- const net::IPAddressNumber& self_address,
- const net::IPEndPoint& peer_address) {
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) {
++num_calls_to_write_;
ReleaseOldPackets();
@@ -122,8 +126,13 @@ WriteResult PacketDroppingTestWriter::WritePacket(
? send_time.Add(bandwidth_delay)
: delayed_packets_.back().send_time.Add(bandwidth_delay);
}
+ std::unique_ptr<PerPacketOptions> delayed_options;
+ if (options != nullptr) {
+ delayed_options.reset(options->Clone());
+ }
delayed_packets_.push_back(
- DelayedWrite(buffer, buf_len, self_address, peer_address, send_time));
+ DelayedWrite(buffer, buf_len, self_address, peer_address,
+ std::move(delayed_options), send_time));
cur_buffer_size_ += buf_len;
// Set the alarm if it's not yet set.
@@ -135,7 +144,7 @@ WriteResult PacketDroppingTestWriter::WritePacket(
}
return QuicPacketWriterWrapper::WritePacket(buffer, buf_len, self_address,
- peer_address);
+ peer_address, options);
}
bool PacketDroppingTestWriter::IsWriteBlocked() const {
@@ -173,9 +182,9 @@ QuicTime PacketDroppingTestWriter::ReleaseNextPacket() {
DVLOG(1) << "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, iter->peer_address);
+ QuicPacketWriterWrapper::WritePacket(
+ iter->buffer.data(), iter->buffer.length(), iter->self_address,
+ iter->peer_address, iter->options.get());
DCHECK_GE(cur_buffer_size_, iter->buffer.length());
cur_buffer_size_ -= iter->buffer.length();
delayed_packets_.erase(iter);
@@ -198,6 +207,10 @@ QuicTime PacketDroppingTestWriter::ReleaseOldPackets() {
return QuicTime::Zero();
}
+void PacketDroppingTestWriter::SetDelayAlarm(QuicTime new_deadline) {
+ delay_alarm_->Set(new_deadline);
+}
+
void PacketDroppingTestWriter::OnCanWrite() {
on_can_write_->OnCanWrite();
}
@@ -205,16 +218,28 @@ void PacketDroppingTestWriter::OnCanWrite() {
PacketDroppingTestWriter::DelayedWrite::DelayedWrite(
const char* buffer,
size_t buf_len,
- const net::IPAddressNumber& self_address,
- const net::IPEndPoint& peer_address,
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ std::unique_ptr<PerPacketOptions> options,
QuicTime send_time)
: buffer(buffer, buf_len),
self_address(self_address),
peer_address(peer_address),
+ options(std::move(options)),
send_time(send_time) {}
+// TODO(rtenneti): on windows RValue reference gives errors.
+PacketDroppingTestWriter::DelayedWrite::DelayedWrite(
+ PacketDroppingTestWriter::DelayedWrite&& other) = default;
+
+// TODO(rtenneti): on windows RValue reference gives errors.
+// IPAddress has no move assignment operator.
+//
+// PacketDroppingTestWriter::DelayedWrite&
+// PacketDroppingTestWriter::DelayedWrite::operator=(
+// PacketDroppingTestWriter::DelayedWrite&& other) = default;
+
PacketDroppingTestWriter::DelayedWrite::~DelayedWrite() {}
} // namespace test
-} // namespace tools
} // namespace net
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 ed5dc82f5f8..20d2c278e38 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
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
+#include "net/base/ip_address.h"
#include "net/quic/quic_alarm.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/tools/quic/quic_epoll_clock.h"
@@ -22,7 +23,6 @@
#include "net/tools/quic/test_tools/quic_test_client.h"
namespace net {
-namespace tools {
namespace test {
// Simulates a connection that drops packets a configured percentage of the time
@@ -50,8 +50,9 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
// QuicPacketWriter methods:
WriteResult WritePacket(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address) override;
+ const IPAddress& self_address,
+ const IPEndPoint& peer_address,
+ PerPacketOptions* options) override;
bool IsWriteBlocked() const override;
@@ -62,6 +63,9 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
// for the next delayed packet to be written.
QuicTime ReleaseOldPackets();
+ // Sets |delay_alarm_| to fire at |new_deadline|.
+ void SetDelayAlarm(QuicTime new_deadline);
+
void OnCanWrite();
// The percent of time a packet is simulated as being lost.
@@ -126,15 +130,24 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
public:
DelayedWrite(const char* buffer,
size_t buf_len,
- const IPAddressNumber& self_address,
+ const IPAddress& self_address,
const IPEndPoint& peer_address,
+ std::unique_ptr<PerPacketOptions> options,
QuicTime send_time);
+ // TODO(rtenneti): on windows RValue reference gives errors.
+ DelayedWrite(DelayedWrite&& other);
+ // TODO(rtenneti): on windows RValue reference gives errors.
+ // DelayedWrite& operator=(DelayedWrite&& other);
~DelayedWrite();
std::string buffer;
- const IPAddressNumber self_address;
+ const IPAddress self_address;
const IPEndPoint peer_address;
+ std::unique_ptr<PerPacketOptions> options;
QuicTime send_time;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DelayedWrite);
};
typedef std::list<DelayedWrite> DelayedPacketList;
@@ -162,7 +175,6 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_
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 26af191c86d..71d3520f9d7 100644
--- a/chromium/net/tools/quic/test_tools/quic_client_peer.cc
+++ b/chromium/net/tools/quic/test_tools/quic_client_peer.cc
@@ -7,19 +7,23 @@
#include "net/tools/quic/quic_client.h"
namespace net {
-namespace tools {
namespace test {
// static
-bool QuicClientPeer::CreateUDPSocket(QuicClient* client) {
- return client->CreateUDPSocket();
+bool QuicClientPeer::CreateUDPSocketAndBind(QuicClient* client) {
+ return client->CreateUDPSocketAndBind();
+}
+
+// static
+void QuicClientPeer::CleanUpUDPSocket(QuicClient* client, int fd) {
+ client->CleanUpUDPSocket(fd);
}
// static
void QuicClientPeer::SetClientPort(QuicClient* client, int port) {
- client->client_address_ = IPEndPoint(client->client_address_.address(), port);
+ client->fd_address_map_.back().second =
+ IPEndPoint(client->GetLatestClientAddress().address(), port);
}
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/test_tools/quic_client_peer.h b/chromium/net/tools/quic/test_tools/quic_client_peer.h
index 9d9d1034122..4d249a3087d 100644
--- a/chromium/net/tools/quic/test_tools/quic_client_peer.h
+++ b/chromium/net/tools/quic/test_tools/quic_client_peer.h
@@ -12,7 +12,6 @@ namespace net {
class QuicCryptoClientConfig;
class QuicPacketWriter;
-namespace tools {
class QuicClient;
@@ -20,7 +19,8 @@ namespace test {
class QuicClientPeer {
public:
- static bool CreateUDPSocket(QuicClient* client);
+ static bool CreateUDPSocketAndBind(QuicClient* client);
+ static void CleanUpUDPSocket(QuicClient* client, int fd);
static void SetClientPort(QuicClient* client, int port);
private:
@@ -28,7 +28,6 @@ class QuicClientPeer {
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_CLIENT_PEER_H_
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 ab8f28119b5..232043fbc5c 100644
--- a/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc
+++ b/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc
@@ -8,7 +8,6 @@
#include "net/tools/quic/quic_packet_writer_wrapper.h"
namespace net {
-namespace tools {
namespace test {
// static
@@ -31,6 +30,12 @@ QuicPacketWriter* QuicDispatcherPeer::GetWriter(QuicDispatcher* dispatcher) {
}
// static
+QuicCompressedCertsCache* QuicDispatcherPeer::GetCache(
+ QuicDispatcher* dispatcher) {
+ return dispatcher->compressed_certs_cache();
+}
+
+// static
QuicConnectionHelperInterface* QuicDispatcherPeer::GetHelper(
QuicDispatcher* dispatcher) {
return dispatcher->helper_.get();
@@ -57,5 +62,4 @@ const QuicDispatcher::SessionMap& QuicDispatcherPeer::session_map(
}
} // namespace test
-} // namespace tools
} // namespace net
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 19311bd4915..cbd60e27b8f 100644
--- a/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.h
+++ b/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.h
@@ -11,7 +11,6 @@
#include "net/base/ip_endpoint.h"
namespace net {
-namespace tools {
class QuicPacketWriterWrapper;
@@ -29,6 +28,8 @@ class QuicDispatcherPeer {
static QuicPacketWriter* GetWriter(QuicDispatcher* dispatcher);
+ static QuicCompressedCertsCache* GetCache(QuicDispatcher* dispatcher);
+
static QuicConnectionHelperInterface* GetHelper(QuicDispatcher* dispatcher);
static QuicDispatcher::WriteBlockedList* GetWriteBlockedList(
@@ -46,7 +47,6 @@ class QuicDispatcherPeer {
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_DISPATCHER_PEER_H_
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
index feb506e49c8..e342e4a39fc 100644
--- 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
@@ -7,7 +7,6 @@
#include "net/tools/quic/quic_in_memory_cache.h"
namespace net {
-namespace tools {
namespace test {
// static
@@ -16,5 +15,4 @@ void QuicInMemoryCachePeer::ResetForTests() {
}
} // namespace test
-} // namespace tools
} // 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
index e7241099412..55d28d3f0e2 100644
--- 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
@@ -9,7 +9,6 @@
#include "net/tools/quic/quic_in_memory_cache.h"
namespace net {
-namespace tools {
namespace test {
class QuicInMemoryCachePeer {
@@ -22,7 +21,6 @@ class QuicInMemoryCachePeer {
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_IN_MEMORY_CACHE_PEER_H_
diff --git a/chromium/net/tools/quic/test_tools/quic_server_peer.cc b/chromium/net/tools/quic/test_tools/quic_server_peer.cc
index eabebf86541..892c6922785 100644
--- a/chromium/net/tools/quic/test_tools/quic_server_peer.cc
+++ b/chromium/net/tools/quic/test_tools/quic_server_peer.cc
@@ -9,7 +9,6 @@
#include "net/tools/quic/quic_server.h"
namespace net {
-namespace tools {
namespace test {
// static
@@ -20,11 +19,6 @@ bool QuicServerPeer::SetSmallSocket(QuicServer* server) {
}
// static
-void QuicServerPeer::DisableRecvmmsg(QuicServer* server) {
- server->use_recvmmsg_ = false;
-}
-
-// static
QuicDispatcher* QuicServerPeer::GetDispatcher(QuicServer* server) {
return server->dispatcher_.get();
}
@@ -35,5 +29,4 @@ void QuicServerPeer::SetReader(QuicServer* server, QuicPacketReader* reader) {
}
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/test_tools/quic_server_peer.h b/chromium/net/tools/quic/test_tools/quic_server_peer.h
index ae3c1498dd9..6aed20a6689 100644
--- a/chromium/net/tools/quic/test_tools/quic_server_peer.h
+++ b/chromium/net/tools/quic/test_tools/quic_server_peer.h
@@ -9,7 +9,6 @@
namespace net {
-namespace tools {
class QuicDispatcher;
class QuicServer;
@@ -20,7 +19,6 @@ namespace test {
class QuicServerPeer {
public:
static bool SetSmallSocket(QuicServer* server);
- static void DisableRecvmmsg(QuicServer* server);
static QuicDispatcher* GetDispatcher(QuicServer* server);
static void SetReader(QuicServer* server, QuicPacketReader* reader);
@@ -29,7 +27,6 @@ class QuicServerPeer {
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_SERVER_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 4deec5688df..db9a9b982e8 100644
--- a/chromium/net/tools/quic/test_tools/quic_test_client.cc
+++ b/chromium/net/tools/quic/test_tools/quic_test_client.cc
@@ -34,7 +34,6 @@ using std::string;
using std::vector;
namespace net {
-namespace tools {
namespace test {
namespace {
@@ -44,7 +43,10 @@ class RecordingProofVerifier : public ProofVerifier {
public:
// ProofVerifier interface.
QuicAsyncStatus VerifyProof(const string& hostname,
+ const uint16_t port,
const string& server_config,
+ QuicVersion quic_version,
+ StringPiece chlo_hash,
const vector<string>& certs,
const string& cert_sct,
const string& signature,
@@ -182,7 +184,9 @@ QuicTestClient::QuicTestClient(IPEndPoint server_address,
config,
supported_versions,
&epoll_server_)),
- allow_bidirectional_data_(false) {
+ allow_bidirectional_data_(false),
+ num_requests_(0),
+ num_responses_(0) {
Initialize();
}
@@ -200,7 +204,6 @@ void QuicTestClient::Initialize() {
connect_attempted_ = false;
auto_reconnect_ = false;
buffer_body_ = true;
- fec_policy_ = FEC_PROTECT_OPTIONAL;
ClearPerRequestState();
// As chrome will generally do this, we want it to be the default when it's
// not overridden.
@@ -234,6 +237,22 @@ ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest(
StringPiece body,
bool fin,
QuicAckListenerInterface* delegate) {
+ if (headers) {
+ QuicClientPushPromiseIndex::TryHandle* handle;
+ QuicAsyncStatus rv = client()->push_promise_index()->Try(
+ SpdyBalsaUtils::RequestHeadersToSpdyHeaders(*headers), this, &handle);
+ if (rv == QUIC_SUCCESS)
+ return 1;
+ if (rv == QUIC_PENDING) {
+ // May need to retry request if asynchronous rendezvous fails.
+ auto new_headers = new BalsaHeaders;
+ new_headers->CopyFrom(*headers);
+ push_promise_data_to_resend_.reset(
+ new TestClientDataToResend(new_headers, body, fin, this, delegate));
+ return 1;
+ }
+ }
+
// Maybe it's better just to overload this. it's just that we need
// for the GetOrCreateStream function to call something else...which
// is icky and complicated, but maybe not worse than this.
@@ -241,8 +260,8 @@ ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest(
if (stream == nullptr) {
return 0;
}
- ssize_t ret = 0;
+ ssize_t ret = 0;
if (headers != nullptr) {
SpdyHeaderBlock spdy_headers =
SpdyBalsaUtils::RequestHeadersToSpdyHeaders(*headers);
@@ -258,8 +277,9 @@ ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest(
spdy_headers[":authority"] = client_->server_id().host();
}
ret = stream->SendRequest(spdy_headers, body, fin);
+ ++num_requests_;
} else {
- stream->SendBody(body.as_string(), fin, delegate);
+ stream->WriteOrBufferBody(body.as_string(), fin, delegate);
ret = body.length();
}
if (FLAGS_enable_quic_stateless_reject_support) {
@@ -376,8 +396,6 @@ QuicSpdyClientStream* QuicTestClient::GetOrCreateStream() {
QuicSpdyClientStream* cs = reinterpret_cast<QuicSpdyClientStream*>(stream_);
cs->SetPriority(priority_);
cs->set_allow_bidirectional_data(allow_bidirectional_data_);
- // Set FEC policy on stream.
- ReliableQuicStreamPeer::SetFecPolicy(stream_, fec_policy_);
}
return stream_;
@@ -437,7 +455,7 @@ void QuicTestClient::Disconnect() {
}
IPEndPoint QuicTestClient::local_address() const {
- return client_->client_address();
+ return client_->GetLatestClientAddress();
}
void QuicTestClient::ClearPerRequestState() {
@@ -446,13 +464,19 @@ void QuicTestClient::ClearPerRequestState() {
response_ = "";
response_complete_ = false;
response_headers_complete_ = false;
- headers_.Clear();
+ response_headers_.Clear();
bytes_read_ = 0;
bytes_written_ = 0;
response_header_size_ = 0;
response_body_size_ = 0;
}
+bool QuicTestClient::HaveActiveStream() {
+ return push_promise_data_to_resend_.get() ||
+ (stream_ != nullptr &&
+ !client_->session()->IsClosedStream(stream_->id()));
+}
+
void QuicTestClient::WaitForResponseForMs(int timeout_ms) {
int64_t timeout_us = timeout_ms * base::Time::kMicrosecondsPerMillisecond;
int64_t old_timeout_us = epoll_server()->timeout_in_us();
@@ -464,8 +488,7 @@ void QuicTestClient::WaitForResponseForMs(int timeout_ms) {
->GetClock();
QuicTime end_waiting_time =
clock->Now().Add(QuicTime::Delta::FromMicroseconds(timeout_us));
- while (stream_ != nullptr &&
- !client_->session()->IsClosedStream(stream_->id()) &&
+ while (HaveActiveStream() &&
(timeout_us < 0 || clock->Now() < end_waiting_time)) {
client_->WaitForEvents();
}
@@ -509,10 +532,11 @@ bool QuicTestClient::response_headers_complete() const {
const BalsaHeaders* QuicTestClient::response_headers() const {
if (stream_ != nullptr) {
- SpdyBalsaUtils::SpdyHeadersToResponseHeaders(stream_->headers(), &headers_);
- return &headers_;
+ SpdyBalsaUtils::SpdyHeadersToResponseHeaders(stream_->response_headers(),
+ &response_headers_);
+ return &response_headers_;
} else {
- return &headers_;
+ return &response_headers_;
}
}
@@ -547,15 +571,35 @@ void QuicTestClient::OnClose(QuicSpdyStream* stream) {
}
response_complete_ = true;
response_headers_complete_ = stream_->headers_decompressed();
- SpdyBalsaUtils::SpdyHeadersToResponseHeaders(stream_->headers(), &headers_);
- response_trailers_ = stream_->trailers();
+ SpdyBalsaUtils::SpdyHeadersToResponseHeaders(stream_->response_headers(),
+ &response_headers_);
+ response_trailers_ = stream_->received_trailers();
stream_error_ = stream_->stream_error();
bytes_read_ = stream_->stream_bytes_read() + stream_->header_bytes_read();
bytes_written_ =
stream_->stream_bytes_written() + stream_->header_bytes_written();
- response_header_size_ = headers_.GetSizeForWriteBuffer();
+ response_header_size_ = response_headers_.GetSizeForWriteBuffer();
response_body_size_ = stream_->data().size();
stream_ = nullptr;
+ ++num_responses_;
+}
+
+bool QuicTestClient::CheckVary(const SpdyHeaderBlock& client_request,
+ const SpdyHeaderBlock& promise_request,
+ const SpdyHeaderBlock& promise_response) {
+ return true;
+}
+
+void QuicTestClient::OnRendezvousResult(QuicSpdyStream* stream) {
+ std::unique_ptr<TestClientDataToResend> data_to_resend =
+ std::move(push_promise_data_to_resend_);
+ stream_ = static_cast<QuicSpdyClientStream*>(stream);
+ if (stream) {
+ stream->set_visitor(this);
+ stream->OnDataAvailable();
+ } else if (data_to_resend.get()) {
+ data_to_resend->Resend();
+ }
}
void QuicTestClient::UseWriter(QuicPacketWriterWrapper* writer) {
@@ -577,7 +621,7 @@ void QuicTestClient::Bind(IPEndPoint* local_address) {
DLOG(WARNING) << "Bind will be done during connect";
}
-void QuicTestClient::MigrateSocket(const IPAddressNumber& new_host) {
+void QuicTestClient::MigrateSocket(const IPAddress& new_host) {
client_->MigrateSocket(new_host);
}
@@ -586,11 +630,11 @@ string QuicTestClient::SerializeMessage(const HTTPMessage& message) {
return "";
}
-IPAddressNumber QuicTestClient::bind_to_address() const {
+IPAddress QuicTestClient::bind_to_address() const {
return client_->bind_to_address();
}
-void QuicTestClient::set_bind_to_address(IPAddressNumber address) {
+void QuicTestClient::set_bind_to_address(const IPAddress& address) {
client_->set_bind_to_address(address);
}
@@ -609,15 +653,6 @@ void QuicTestClient::WaitForWriteToFlush() {
}
}
-void QuicTestClient::SetFecPolicy(FecPolicy fec_policy) {
- fec_policy_ = fec_policy;
- // Set policy for headers and crypto streams.
- ReliableQuicStreamPeer::SetFecPolicy(
- QuicSpdySessionPeer::GetHeadersStream(client()->session()), fec_policy);
- ReliableQuicStreamPeer::SetFecPolicy(client()->session()->GetCryptoStream(),
- fec_policy);
-}
-
void QuicTestClient::TestClientDataToResend::Resend() {
test_client_->GetOrCreateStreamAndSendRequest(headers_, body_, fin_,
delegate_);
@@ -638,5 +673,4 @@ void QuicTestClient::FillInRequest(const string& uri, HTTPMessage* message) {
}
} // namespace test
-} // namespace tools
} // namespace net
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 d4f27e90f79..b8530f46f46 100644
--- a/chromium/net/tools/quic/test_tools/quic_test_client.h
+++ b/chromium/net/tools/quic/test_tools/quic_test_client.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/proto/cached_network_parameters.pb.h"
#include "net/quic/quic_framer.h"
@@ -26,8 +27,6 @@ namespace net {
class ProofVerifier;
-namespace tools {
-
class QuicPacketWriterWrapper;
namespace test {
@@ -68,7 +67,9 @@ class MockableQuicClient : public QuicClient {
};
// A toy QUIC client used for testing, mostly following the SimpleClient APIs.
-class QuicTestClient : public SimpleClient, public QuicSpdyStream::Visitor {
+class QuicTestClient : public test::SimpleClient,
+ public QuicSpdyStream::Visitor,
+ public QuicClientPushPromiseIndex::Delegate {
public:
QuicTestClient(IPEndPoint server_address,
const std::string& server_hostname,
@@ -127,10 +128,10 @@ class QuicTestClient : public SimpleClient, public QuicSpdyStream::Visitor {
// DFATAL if called by users of SimpleClient.
ssize_t SendAndWaitForResponse(const void* buffer, size_t size) override;
void Bind(IPEndPoint* local_address) override;
- void MigrateSocket(const IPAddressNumber& new_host) override;
+ void MigrateSocket(const IPAddress& new_host) override;
std::string SerializeMessage(const HTTPMessage& message) override;
- IPAddressNumber bind_to_address() const override;
- void set_bind_to_address(IPAddressNumber address) override;
+ IPAddress bind_to_address() const override;
+ void set_bind_to_address(const IPAddress& address) override;
const IPEndPoint& address() const override;
size_t requests_sent() const override;
@@ -140,6 +141,12 @@ class QuicTestClient : public SimpleClient, public QuicSpdyStream::Visitor {
// From QuicSpdyStream::Visitor
void OnClose(QuicSpdyStream* stream) override;
+ // From QuicClientPushPromiseIndex::Delegate
+ bool CheckVary(const SpdyHeaderBlock& client_request,
+ const SpdyHeaderBlock& promise_request,
+ const SpdyHeaderBlock& promise_response) override;
+ void OnRendezvousResult(QuicSpdyStream*) override;
+
// Configures client_ to take ownership of and use the writer.
// Must be called before initial connect.
void UseWriter(QuicPacketWriterWrapper* writer);
@@ -150,8 +157,8 @@ class QuicTestClient : public SimpleClient, public QuicSpdyStream::Visitor {
// Returns nullptr if the maximum number of streams have already been created.
QuicSpdyClientStream* GetOrCreateStream();
- // Calls GetorCreateStream(), sends the request on the stream, and
- // stores the reuest in case it needs to be resent. If |headers| is
+ // 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 BalsaHeaders* headers,
StringPiece body,
@@ -178,10 +185,6 @@ class QuicTestClient : public SimpleClient, public QuicSpdyStream::Visitor {
void set_priority(SpdyPriority priority) { priority_ = priority; }
- // Sets client's FEC policy. This policy applies to the data stream(s), and
- // also to the headers and crypto streams.
- void SetFecPolicy(FecPolicy fec_policy);
-
void WaitForWriteToFlush();
EpollServer* epoll_server() { return &epoll_server_; }
@@ -192,6 +195,10 @@ class QuicTestClient : public SimpleClient, public QuicSpdyStream::Visitor {
bool allow_bidirectional_data() const { return allow_bidirectional_data_; }
+ size_t num_requests() const { return num_requests_; }
+
+ size_t num_responses() const { return num_responses_; }
+
protected:
QuicTestClient();
@@ -223,6 +230,8 @@ class QuicTestClient : public SimpleClient, public QuicSpdyStream::Visitor {
// Given a uri, creates a simple HTTPMessage request message for testing.
static void FillInRequest(const std::string& uri, HTTPMessage* message);
+ bool HaveActiveStream();
+
EpollServer epoll_server_;
scoped_ptr<MockableQuicClient> client_; // The actual client
QuicSpdyClientStream* stream_;
@@ -231,7 +240,7 @@ class QuicTestClient : public SimpleClient, public QuicSpdyStream::Visitor {
bool response_complete_;
bool response_headers_complete_;
- mutable BalsaHeaders headers_;
+ mutable BalsaHeaders response_headers_;
// Parsed response trailers (if present), copied from the stream in OnClose.
SpdyHeaderBlock response_trailers_;
@@ -252,18 +261,21 @@ class QuicTestClient : public SimpleClient, public QuicSpdyStream::Visitor {
bool auto_reconnect_;
// Should we buffer the response body? Defaults to true.
bool buffer_body_;
- // FEC policy for data sent by this client.
- FecPolicy fec_policy_;
// When true allows the sending of a request to continue while the response is
// arriving.
bool allow_bidirectional_data_;
+ // For async push promise rendezvous, validation may fail in which
+ // case the request should be retried.
+ std::unique_ptr<TestClientDataToResend> push_promise_data_to_resend_;
+ // Number of requests/responses this client has sent/received.
+ size_t num_requests_;
+ size_t num_responses_;
DISALLOW_COPY_AND_ASSIGN(QuicTestClient);
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_
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 421952bc910..dc5fc45141d 100644
--- a/chromium/net/tools/quic/test_tools/quic_test_server.cc
+++ b/chromium/net/tools/quic/test_tools/quic_test_server.cc
@@ -24,7 +24,6 @@
#include "net/tools/quic/quic_simple_server_stream.h"
namespace net {
-namespace tools {
namespace test {
class CustomStreamSession : public QuicSimpleServerSession {
@@ -34,9 +33,14 @@ class CustomStreamSession : public QuicSimpleServerSession {
QuicConnection* connection,
QuicServerSessionVisitor* visitor,
const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
QuicTestServer::StreamFactory* factory,
QuicTestServer::CryptoStreamFactory* crypto_stream_factory)
- : QuicSimpleServerSession(config, connection, visitor, crypto_config),
+ : QuicSimpleServerSession(config,
+ connection,
+ visitor,
+ crypto_config,
+ compressed_certs_cache),
stream_factory_(factory),
crypto_stream_factory_(crypto_stream_factory) {}
@@ -45,17 +49,21 @@ class CustomStreamSession : public QuicSimpleServerSession {
return nullptr;
}
if (stream_factory_) {
- return stream_factory_->CreateStream(id, this);
+ QuicSpdyStream* stream = stream_factory_->CreateStream(id, this);
+ ActivateStream(stream);
+ return stream;
}
return QuicSimpleServerSession::CreateIncomingDynamicStream(id);
}
QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
- const QuicCryptoServerConfig* crypto_config) override {
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache) override {
if (crypto_stream_factory_) {
return crypto_stream_factory_->CreateCryptoStream(crypto_config, this);
}
- return QuicSimpleServerSession::CreateQuicCryptoServerStream(crypto_config);
+ return QuicSimpleServerSession::CreateQuicCryptoServerStream(
+ crypto_config, compressed_certs_cache);
}
private:
@@ -87,12 +95,13 @@ class QuicTestDispatcher : public QuicDispatcher {
QuicServerSessionBase* session = nullptr;
if (stream_factory_ != nullptr || crypto_stream_factory_ != nullptr) {
- session =
- new CustomStreamSession(config(), connection, this, crypto_config(),
- stream_factory_, crypto_stream_factory_);
+ session = new CustomStreamSession(
+ config(), connection, this, crypto_config(), compressed_certs_cache(),
+ stream_factory_, crypto_stream_factory_);
} else {
session = session_factory_->CreateSession(config(), connection, this,
- crypto_config());
+ crypto_config(),
+ compressed_certs_cache());
}
session->Initialize();
return session;
@@ -133,12 +142,16 @@ QuicTestServer::QuicTestServer(ProofSource* proof_source)
QuicTestServer::QuicTestServer(ProofSource* proof_source,
const QuicConfig& config,
const QuicVersionVector& supported_versions)
- : QuicServer(proof_source, config, supported_versions) {}
+ : QuicServer(proof_source,
+ config,
+ QuicCryptoServerConfig::ConfigOptions(),
+ supported_versions) {}
QuicDispatcher* QuicTestServer::CreateQuicDispatcher() {
- return new QuicTestDispatcher(config(), &crypto_config(),
- supported_versions(),
- new QuicEpollConnectionHelper(epoll_server()));
+ return new QuicTestDispatcher(
+ config(), &crypto_config(), supported_versions(),
+ new QuicEpollConnectionHelper(epoll_server(),
+ QuicAllocator::BUFFER_POOL));
}
void QuicTestServer::SetSessionFactory(SessionFactory* factory) {
@@ -161,11 +174,15 @@ ImmediateGoAwaySession::ImmediateGoAwaySession(
const QuicConfig& config,
QuicConnection* connection,
QuicServerSessionVisitor* visitor,
- const QuicCryptoServerConfig* crypto_config)
- : QuicSimpleServerSession(config, connection, visitor, crypto_config) {
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache)
+ : QuicSimpleServerSession(config,
+ connection,
+ visitor,
+ crypto_config,
+ compressed_certs_cache) {
SendGoAway(QUIC_PEER_GOING_AWAY, "");
}
} // namespace test
-} // namespace tools
} // namespace net
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 a38923ccbbb..7af5f51a97c 100644
--- a/chromium/net/tools/quic/test_tools/quic_test_server.h
+++ b/chromium/net/tools/quic/test_tools/quic_test_server.h
@@ -17,7 +17,6 @@
namespace net {
-namespace tools {
namespace test {
@@ -36,7 +35,8 @@ class QuicTestServer : public QuicServer {
const QuicConfig& config,
QuicConnection* connection,
QuicServerSessionVisitor* visitor,
- const QuicCryptoServerConfig* crypto_config) = 0;
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache) = 0;
};
// Factory for creating QuicSimpleServerStreams.
@@ -90,12 +90,12 @@ class ImmediateGoAwaySession : public QuicSimpleServerSession {
ImmediateGoAwaySession(const QuicConfig& config,
QuicConnection* connection,
QuicServerSessionVisitor* visitor,
- const QuicCryptoServerConfig* crypto_config);
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache);
};
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/test_tools/server_thread.cc b/chromium/net/tools/quic/test_tools/server_thread.cc
index 4ca948980d5..b51dfb119aa 100644
--- a/chromium/net/tools/quic/test_tools/server_thread.cc
+++ b/chromium/net/tools/quic/test_tools/server_thread.cc
@@ -9,7 +9,6 @@
#include "net/tools/quic/test_tools/quic_server_peer.h"
namespace net {
-namespace tools {
namespace test {
ServerThread::ServerThread(QuicServer* server,
@@ -37,7 +36,7 @@ void ServerThread::Initialize() {
return;
}
- server_->Listen(address_);
+ server_->CreateUDPSocketAndListen(address_);
port_lock_.Acquire();
port_ = server_->port();
@@ -110,5 +109,4 @@ void ServerThread::MaybeNotifyOfHandshakeConfirmation() {
}
} // namespace test
-} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/test_tools/server_thread.h b/chromium/net/tools/quic/test_tools/server_thread.h
index e6cb97d24ac..244a87c55e5 100644
--- a/chromium/net/tools/quic/test_tools/server_thread.h
+++ b/chromium/net/tools/quic/test_tools/server_thread.h
@@ -12,7 +12,6 @@
#include "net/tools/quic/quic_server.h"
namespace net {
-namespace tools {
namespace test {
// Simple wrapper class to run QuicServer in a dedicated thread.
@@ -75,7 +74,6 @@ class ServerThread : public base::SimpleThread {
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_SERVER_THREAD_H_
diff --git a/chromium/net/tools/quic/test_tools/simple_client.cc b/chromium/net/tools/quic/test_tools/simple_client.cc
index 8d3d51b3139..3559da1375e 100644
--- a/chromium/net/tools/quic/test_tools/simple_client.cc
+++ b/chromium/net/tools/quic/test_tools/simple_client.cc
@@ -5,7 +5,6 @@
#include "net/tools/quic/test_tools/simple_client.h"
namespace net {
-namespace tools {
namespace test {
void SimpleClient::WaitForResponse() {
@@ -36,5 +35,4 @@ int64_t SimpleClient::response_body_size() const {
}
} // namespace net
-} // namespace tools
} // namespace test
diff --git a/chromium/net/tools/quic/test_tools/simple_client.h b/chromium/net/tools/quic/test_tools/simple_client.h
index 322210129db..3c5d02cfd0a 100644
--- a/chromium/net/tools/quic/test_tools/simple_client.h
+++ b/chromium/net/tools/quic/test_tools/simple_client.h
@@ -11,11 +11,11 @@
#include <string>
#include <vector>
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/tools/balsa/balsa_frame.h"
namespace net {
-namespace tools {
namespace test {
class HTTPMessage;
@@ -89,7 +89,7 @@ class SimpleClient {
// if the given address has port 0.
virtual void Bind(IPEndPoint* local_address) = 0;
- virtual void MigrateSocket(const IPAddressNumber& new_host) = 0;
+ virtual void MigrateSocket(const IPAddress& new_host) = 0;
// Returns the local socket address of the client fd. Call only when
// connected.
@@ -104,8 +104,8 @@ class SimpleClient {
// Sets the IP address to bind to on future Connect()s in case Bind() is not
// called in advance. If it's set to uninitialized IPAddress, default loopback
// address will be used.
- virtual IPAddressNumber bind_to_address() const = 0;
- virtual void set_bind_to_address(IPAddressNumber address) = 0;
+ virtual IPAddress bind_to_address() const = 0;
+ virtual void set_bind_to_address(const IPAddress& address) = 0;
// Returns true if the headers have been processed and are available.
virtual bool response_headers_complete() const = 0;
@@ -158,7 +158,6 @@ class SimpleClient {
};
} // namespace test
-} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_TEST_TOOLS_SIMPLE_CLIENT_H_
diff --git a/chromium/net/tools/testserver/testserver.py b/chromium/net/tools/testserver/testserver.py
index 15317657d08..ba130af9943 100755
--- a/chromium/net/tools/testserver/testserver.py
+++ b/chromium/net/tools/testserver/testserver.py
@@ -340,6 +340,8 @@ class TestPageHandler(testserver_base.BasePageHandler):
self.GetSSLSessionCacheHandler,
self.SSLManySmallRecords,
self.GetChannelID,
+ self.GetTokenBindingEKM,
+ self.ForwardTokenBindingHeader,
self.GetClientCert,
self.ClientCipherListHandler,
self.CloseSocketHandler,
@@ -1516,6 +1518,41 @@ class TestPageHandler(testserver_base.BasePageHandler):
self.wfile.write(hashlib.sha256(channel_id).digest().encode('base64'))
return True
+ def GetTokenBindingEKM(self):
+ """Send a reply containing the EKM value for token binding from the TLS
+ layer."""
+
+ if not self._ShouldHandleRequest('/tokbind-ekm'):
+ return False
+
+ ekm = self.server.tlsConnection.exportKeyingMaterial(
+ "EXPORTER-Token-Binding", "", False, 32)
+ self.send_response(200)
+ self.send_header('Content-Type', 'application/octet-stream')
+ self.end_headers()
+ self.wfile.write(ekm)
+ return True
+
+ def ForwardTokenBindingHeader(self):
+ """Send a redirect that sets the Include-Referer-Token-Binding-ID
+ header."""
+
+ test_name = '/forward-tokbind'
+ if not self._ShouldHandleRequest(test_name):
+ return False
+
+ query_char = self.path.find('?')
+ if query_char < 0 or len(self.path) <= query_char + 1:
+ self.sendRedirectHelp(test_name)
+ return True
+ dest = urllib.unquote(self.path[query_char + 1:])
+
+ self.send_response(302)
+ self.send_header('Location', dest)
+ self.send_header('Include-Referer-Token-Binding-ID', 'true')
+ self.end_headers()
+ return True
+
def GetClientCert(self):
"""Send a reply whether a client certificate was provided."""
diff --git a/chromium/net/udp/datagram_client_socket.h b/chromium/net/udp/datagram_client_socket.h
index e8d54c18d51..88eeced8698 100644
--- a/chromium/net/udp/datagram_client_socket.h
+++ b/chromium/net/udp/datagram_client_socket.h
@@ -18,25 +18,28 @@ class NET_EXPORT_PRIVATE DatagramClientSocket : public DatagramSocket,
public:
~DatagramClientSocket() override {}
- // Binds this socket to |network|. All data traffic on the socket will be sent
- // and received via |network|. Must be called before Connect(). This call will
- // fail if |network| has disconnected. Communication using this socket will
- // fail if |network| disconnects.
- // Returns a net error code.
- virtual int BindToNetwork(NetworkChangeNotifier::NetworkHandle network) = 0;
+ // Initialize this socket as a client socket to server at |address|.
+ // Returns a network error code.
+ virtual int Connect(const IPEndPoint& address) = 0;
- // Same as BindToNetwork, except that the current default network is used.
+ // Binds this socket to |network| and initializes socket as a client socket
+ // to server at |address|. All data traffic on the socket will be sent and
+ // received via |network|. This call will fail if |network| has disconnected.
+ // Communication using this socket will fail if |network| disconnects.
// Returns a net error code.
- virtual int BindToDefaultNetwork() = 0;
+ virtual int ConnectUsingNetwork(NetworkChangeNotifier::NetworkHandle network,
+ const IPEndPoint& address) = 0;
- // Returns the network that either BindToNetwork() or BindToDefaultNetwork()
- // bound this socket to. Returns NetworkChangeNotifier::kInvalidNetworkHandle
- // if not explicitly bound via BindToNetwork() or BindToDefaultNetwork().
+ // Same as ConnectUsingNetwork, except that the current default network is
+ // used. Returns a net error code.
+ virtual int ConnectUsingDefaultNetwork(const IPEndPoint& address) = 0;
+
+ // Returns the network that either ConnectUsingNetwork() or
+ // ConnectUsingDefaultNetwork() bound this socket to. Returns
+ // NetworkChangeNotifier::kInvalidNetworkHandle if not explicitly bound via
+ // ConnectUsingNetwork() or ConnectUsingDefaultNetwork().
virtual NetworkChangeNotifier::NetworkHandle GetBoundNetwork() const = 0;
- // Initialize this socket as a client socket to server at |address|.
- // Returns a network error code.
- virtual int Connect(const IPEndPoint& address) = 0;
};
} // namespace net
diff --git a/chromium/net/udp/datagram_server_socket.h b/chromium/net/udp/datagram_server_socket.h
index 1dd444f444c..7e5adee15e0 100644
--- a/chromium/net/udp/datagram_server_socket.h
+++ b/chromium/net/udp/datagram_server_socket.h
@@ -13,6 +13,7 @@
namespace net {
+class IPAddress;
class IPEndPoint;
class IOBuffer;
@@ -31,23 +32,19 @@ class NET_EXPORT DatagramServerSocket : public DatagramSocket {
// |address| is a buffer provided by the caller for receiving the sender
// address information about the received data. This buffer must be kept
// alive by the caller until the callback is placed.
- // |address_length| is a ptr to the length of the |address| buffer. This
- // is an input parameter containing the maximum size |address| can hold
- // and also an output parameter for the size of |address| upon completion.
// |callback| is the callback on completion of the RecvFrom.
// Returns a net error code, or ERR_IO_PENDING if the IO is in progress.
- // If ERR_IO_PENDING is returned, the caller must keep |buf|, |address|,
- // and |address_length| alive until the callback is called.
+ // If ERR_IO_PENDING is returned, the caller must keep |buf| and |address|
+ // alive until the callback is called.
virtual int RecvFrom(IOBuffer* buf,
int buf_len,
IPEndPoint* address,
const CompletionCallback& callback) = 0;
// Send to a socket with a particular destination.
- // |buf| is the buffer to send
- // |buf_len| is the number of bytes to send
+ // |buf| is the buffer to send.
+ // |buf_len| is the number of bytes to send.
// |address| is the recipient address.
- // |address_length| is the size of the recipient address
// |callback| is the user callback function to call on complete.
// Returns a net error code, or ERR_IO_PENDING if the IO is in progress.
// If ERR_IO_PENDING is returned, the caller must keep |buf| and |address|
@@ -75,14 +72,14 @@ class NET_EXPORT DatagramServerSocket : public DatagramSocket {
// Join the multicast group with address |group_address|.
// Returns a network error code.
- virtual int JoinGroup(const IPAddressNumber& group_address) const = 0;
+ virtual int JoinGroup(const IPAddress& group_address) const = 0;
// Leave the multicast group with address |group_address|.
// If the socket hasn't joined the group, it will be ignored.
// It's optional to leave the multicast group before destroying
// the socket. It will be done by the OS.
// Returns a network error code.
- virtual int LeaveGroup(const IPAddressNumber& group_address) const = 0;
+ virtual int LeaveGroup(const IPAddress& group_address) const = 0;
// Set interface to use for multicast. If |interface_index| set to 0, default
// interface is used.
diff --git a/chromium/net/udp/udp_client_socket.cc b/chromium/net/udp/udp_client_socket.cc
index 7559c77f9ee..7c3a2722a17 100644
--- a/chromium/net/udp/udp_client_socket.cc
+++ b/chromium/net/udp/udp_client_socket.cc
@@ -19,18 +19,35 @@ UDPClientSocket::UDPClientSocket(DatagramSocket::BindType bind_type,
UDPClientSocket::~UDPClientSocket() {
}
-int UDPClientSocket::BindToNetwork(
- NetworkChangeNotifier::NetworkHandle network) {
- int rv = socket_.BindToNetwork(network);
- if (rv == OK)
- network_ = network;
- return rv;
+int UDPClientSocket::Connect(const IPEndPoint& address) {
+ int rv = socket_.Open(address.GetFamily());
+ if (rv != OK)
+ return rv;
+ return socket_.Connect(address);
}
-int UDPClientSocket::BindToDefaultNetwork() {
+int UDPClientSocket::ConnectUsingNetwork(
+ NetworkChangeNotifier::NetworkHandle network,
+ const IPEndPoint& address) {
+ if (!NetworkChangeNotifier::AreNetworkHandlesSupported())
+ return ERR_NOT_IMPLEMENTED;
+ int rv = socket_.Open(address.GetFamily());
+ if (rv != OK)
+ return rv;
+ rv = socket_.BindToNetwork(network);
+ if (rv != OK)
+ return rv;
+ network_ = network;
+ return socket_.Connect(address);
+}
+
+int UDPClientSocket::ConnectUsingDefaultNetwork(const IPEndPoint& address) {
if (!NetworkChangeNotifier::AreNetworkHandlesSupported())
return ERR_NOT_IMPLEMENTED;
int rv;
+ rv = socket_.Open(address.GetFamily());
+ if (rv != OK)
+ return rv;
// Calling connect() will bind a socket to the default network, however there
// is no way to determine what network the socket got bound to. The
// alternative is to query what the default network is and bind the socket to
@@ -38,32 +55,28 @@ int UDPClientSocket::BindToDefaultNetwork() {
// can change in between when we query it and when we bind to it. This is
// rare but should be accounted for. Since changes of the default network
// should not come in quick succession, we can simply try again.
+ NetworkChangeNotifier::NetworkHandle network;
for (int attempt = 0; attempt < 2; attempt++) {
- NetworkChangeNotifier::NetworkHandle network =
- NetworkChangeNotifier::GetDefaultNetwork();
+ network = NetworkChangeNotifier::GetDefaultNetwork();
if (network == NetworkChangeNotifier::kInvalidNetworkHandle)
return ERR_INTERNET_DISCONNECTED;
- rv = BindToNetwork(network);
+ rv = socket_.BindToNetwork(network);
// |network| may have disconnected between the call to GetDefaultNetwork()
- // and the call to BindToNetwork(). Loop if this is the case (|rv| will be
- // ERR_NETWORK_CHANGED).
+ // and the call to BindToNetwork(). Loop only if this is the case (|rv| will
+ // be ERR_NETWORK_CHANGED).
if (rv != ERR_NETWORK_CHANGED)
- return rv;
+ break;
}
- return rv;
+ if (rv != OK)
+ return rv;
+ network_ = network;
+ return socket_.Connect(address);
}
NetworkChangeNotifier::NetworkHandle UDPClientSocket::GetBoundNetwork() const {
return network_;
}
-int UDPClientSocket::Connect(const IPEndPoint& address) {
- int rv = socket_.Open(address.GetFamily());
- if (rv != OK)
- return rv;
- return socket_.Connect(address);
-}
-
int UDPClientSocket::Read(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) {
diff --git a/chromium/net/udp/udp_client_socket.h b/chromium/net/udp/udp_client_socket.h
index 99b9fe601af..ca563bbc0f1 100644
--- a/chromium/net/udp/udp_client_socket.h
+++ b/chromium/net/udp/udp_client_socket.h
@@ -27,10 +27,11 @@ class NET_EXPORT_PRIVATE UDPClientSocket : public DatagramClientSocket {
~UDPClientSocket() override;
// DatagramClientSocket implementation.
- int BindToNetwork(NetworkChangeNotifier::NetworkHandle network) override;
- int BindToDefaultNetwork() override;
- NetworkChangeNotifier::NetworkHandle GetBoundNetwork() const override;
int Connect(const IPEndPoint& address) override;
+ int ConnectUsingNetwork(NetworkChangeNotifier::NetworkHandle network,
+ const IPEndPoint& address) override;
+ int ConnectUsingDefaultNetwork(const IPEndPoint& address) override;
+ NetworkChangeNotifier::NetworkHandle GetBoundNetwork() const override;
int Read(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) override;
diff --git a/chromium/net/udp/udp_server_socket.cc b/chromium/net/udp/udp_server_socket.cc
index 8cda8d40017..4cba115d5fc 100644
--- a/chromium/net/udp/udp_server_socket.cc
+++ b/chromium/net/udp/udp_server_socket.cc
@@ -92,11 +92,11 @@ void UDPServerSocket::AllowBroadcast() {
allow_broadcast_ = true;
}
-int UDPServerSocket::JoinGroup(const IPAddressNumber& group_address) const {
+int UDPServerSocket::JoinGroup(const IPAddress& group_address) const {
return socket_.JoinGroup(group_address);
}
-int UDPServerSocket::LeaveGroup(const IPAddressNumber& group_address) const {
+int UDPServerSocket::LeaveGroup(const IPAddress& group_address) const {
return socket_.LeaveGroup(group_address);
}
diff --git a/chromium/net/udp/udp_server_socket.h b/chromium/net/udp/udp_server_socket.h
index 668ebcc4b2d..a0b4852b958 100644
--- a/chromium/net/udp/udp_server_socket.h
+++ b/chromium/net/udp/udp_server_socket.h
@@ -9,12 +9,12 @@
#include "base/macros.h"
#include "net/base/completion_callback.h"
-#include "net/base/ip_address_number.h"
#include "net/udp/datagram_server_socket.h"
#include "net/udp/udp_socket.h"
namespace net {
+class IPAddress;
class IPEndPoint;
class BoundNetLog;
@@ -42,8 +42,8 @@ class NET_EXPORT UDPServerSocket : public DatagramServerSocket {
const BoundNetLog& NetLog() const override;
void AllowAddressReuse() override;
void AllowBroadcast() override;
- int JoinGroup(const IPAddressNumber& group_address) const override;
- int LeaveGroup(const IPAddressNumber& group_address) const override;
+ int JoinGroup(const IPAddress& group_address) const override;
+ int LeaveGroup(const IPAddress& group_address) const override;
int SetMulticastInterface(uint32_t interface_index) override;
int SetMulticastTimeToLive(int time_to_live) override;
int SetMulticastLoopbackMode(bool loopback) override;
diff --git a/chromium/net/udp/udp_socket_perftest.cc b/chromium/net/udp/udp_socket_perftest.cc
index 066ec28bb06..67804a7e9fd 100644
--- a/chromium/net/udp/udp_socket_perftest.cc
+++ b/chromium/net/udp/udp_socket_perftest.cc
@@ -10,7 +10,6 @@
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/test_completion_callback.h"
#include "net/test/net_test_suite.h"
#include "net/udp/udp_client_socket.h"
@@ -54,11 +53,10 @@ class UDPSocketPerfTest : public PlatformTest {
void CreateUDPAddress(const std::string& ip_str,
uint16_t port,
IPEndPoint* address) {
- IPAddressNumber ip_number;
- bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
- if (!rv)
+ IPAddress ip_address;
+ if (!ip_address.AssignFromIPLiteral(ip_str))
return;
- *address = IPEndPoint(ip_number, port);
+ *address = IPEndPoint(ip_address, port);
}
void UDPSocketPerfTest::WritePacketsToSocket(UDPClientSocket* socket,
diff --git a/chromium/net/udp/udp_socket_posix.cc b/chromium/net/udp/udp_socket_posix.cc
index ea1a560289e..7e75b860574 100644
--- a/chromium/net/udp/udp_socket_posix.cc
+++ b/chromium/net/udp/udp_socket_posix.cc
@@ -20,7 +20,9 @@
#include "base/metrics/sparse_histogram.h"
#include "base/posix/eintr_wrapper.h"
#include "base/rand_util.h"
+#include "base/trace_event/trace_event.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/network_activity_monitor.h"
@@ -281,12 +283,12 @@ int UDPSocketPosix::InternalConnect(const IPEndPoint& address) {
int rv = 0;
if (bind_type_ == DatagramSocket::RANDOM_BIND) {
- // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
+ // Construct IPAddress of appropriate size (IPv4 or IPv6) of 0s,
// representing INADDR_ANY or in6addr_any.
- size_t addr_size = address.GetSockAddrFamily() == AF_INET ?
- kIPv4AddressSize : kIPv6AddressSize;
- IPAddressNumber addr_any(addr_size);
- rv = RandomBind(addr_any);
+ size_t addr_size = address.GetSockAddrFamily() == AF_INET
+ ? IPAddress::kIPv4AddressSize
+ : IPAddress::kIPv6AddressSize;
+ rv = RandomBind(IPAddress::AllZeros(addr_size));
}
// else connect() does the DatagramSocket::DEFAULT_BIND
@@ -412,6 +414,8 @@ int UDPSocketPosix::SetBroadcast(bool broadcast) {
}
void UDPSocketPosix::ReadWatcher::OnFileCanReadWithoutBlocking(int) {
+ TRACE_EVENT0("net",
+ "UDPSocketPosix::ReadWatcher::OnFileCanReadWithoutBlocking");
if (!socket_->read_callback_.is_null())
socket_->DidCompleteRead();
}
@@ -652,7 +656,7 @@ int UDPSocketPosix::DoBind(const IPEndPoint& address) {
return MapSystemError(last_error);
}
-int UDPSocketPosix::RandomBind(const IPAddressNumber& address) {
+int UDPSocketPosix::RandomBind(const IPAddress& address) {
DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
for (int i = 0; i < kBindRetries; ++i) {
@@ -664,13 +668,13 @@ int UDPSocketPosix::RandomBind(const IPAddressNumber& address) {
return DoBind(IPEndPoint(address, 0));
}
-int UDPSocketPosix::JoinGroup(const IPAddressNumber& group_address) const {
+int UDPSocketPosix::JoinGroup(const IPAddress& group_address) const {
DCHECK(CalledOnValidThread());
if (!is_connected())
return ERR_SOCKET_NOT_CONNECTED;
switch (group_address.size()) {
- case kIPv4AddressSize: {
+ case IPAddress::kIPv4AddressSize: {
if (addr_family_ != AF_INET)
return ERR_ADDRESS_INVALID;
@@ -681,23 +685,25 @@ int UDPSocketPosix::JoinGroup(const IPAddressNumber& group_address) const {
#else
ip_mreq mreq;
int error = GetIPv4AddressFromIndex(socket_, multicast_interface_,
- &mreq.imr_interface.s_addr);
+ &mreq.imr_interface.s_addr);
if (error != OK)
return error;
#endif
- memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
+ memcpy(&mreq.imr_multiaddr, group_address.bytes().data(),
+ IPAddress::kIPv4AddressSize);
int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&mreq, sizeof(mreq));
if (rv < 0)
return MapSystemError(errno);
return OK;
}
- case kIPv6AddressSize: {
+ case IPAddress::kIPv6AddressSize: {
if (addr_family_ != AF_INET6)
return ERR_ADDRESS_INVALID;
ipv6_mreq mreq;
mreq.ipv6mr_interface = multicast_interface_;
- memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
+ memcpy(&mreq.ipv6mr_multiaddr, group_address.bytes().data(),
+ IPAddress::kIPv6AddressSize);
int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP,
&mreq, sizeof(mreq));
if (rv < 0)
@@ -710,31 +716,33 @@ int UDPSocketPosix::JoinGroup(const IPAddressNumber& group_address) const {
}
}
-int UDPSocketPosix::LeaveGroup(const IPAddressNumber& group_address) const {
+int UDPSocketPosix::LeaveGroup(const IPAddress& group_address) const {
DCHECK(CalledOnValidThread());
if (!is_connected())
return ERR_SOCKET_NOT_CONNECTED;
switch (group_address.size()) {
- case kIPv4AddressSize: {
+ case IPAddress::kIPv4AddressSize: {
if (addr_family_ != AF_INET)
return ERR_ADDRESS_INVALID;
ip_mreq mreq;
mreq.imr_interface.s_addr = INADDR_ANY;
- memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
+ memcpy(&mreq.imr_multiaddr, group_address.bytes().data(),
+ IPAddress::kIPv4AddressSize);
int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
&mreq, sizeof(mreq));
if (rv < 0)
return MapSystemError(errno);
return OK;
}
- case kIPv6AddressSize: {
+ case IPAddress::kIPv6AddressSize: {
if (addr_family_ != AF_INET6)
return ERR_ADDRESS_INVALID;
ipv6_mreq mreq;
mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface.
- memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
+ memcpy(&mreq.ipv6mr_multiaddr, group_address.bytes().data(),
+ IPAddress::kIPv6AddressSize);
int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
&mreq, sizeof(mreq));
if (rv < 0)
diff --git a/chromium/net/udp/udp_socket_posix.h b/chromium/net/udp/udp_socket_posix.h
index 2219f2e6aa5..60b095c0d4a 100644
--- a/chromium/net/udp/udp_socket_posix.h
+++ b/chromium/net/udp/udp_socket_posix.h
@@ -26,6 +26,8 @@
namespace net {
+class IPAddress;
+
class NET_EXPORT UDPSocketPosix : public base::NonThreadSafe {
public:
UDPSocketPosix(DatagramSocket::BindType bind_type,
@@ -86,23 +88,19 @@ class NET_EXPORT UDPSocketPosix : public base::NonThreadSafe {
// |address| is a buffer provided by the caller for receiving the sender
// address information about the received data. This buffer must be kept
// alive by the caller until the callback is placed.
- // |address_length| is a ptr to the length of the |address| buffer. This
- // is an input parameter containing the maximum size |address| can hold
- // and also an output parameter for the size of |address| upon completion.
// |callback| is the callback on completion of the RecvFrom.
// Returns a net error code, or ERR_IO_PENDING if the IO is in progress.
- // If ERR_IO_PENDING is returned, the caller must keep |buf|, |address|,
- // and |address_length| alive until the callback is called.
+ // If ERR_IO_PENDING is returned, the caller must keep |buf| and |address|
+ // alive until the callback is called.
int RecvFrom(IOBuffer* buf,
int buf_len,
IPEndPoint* address,
const CompletionCallback& callback);
// Sends to a socket with a particular destination.
- // |buf| is the buffer to send
- // |buf_len| is the number of bytes to send
+ // |buf| is the buffer to send.
+ // |buf_len| is the number of bytes to send.
// |address| is the recipient address.
- // |address_length| is the size of the recipient address
// |callback| is the user callback function to call on complete.
// Returns a net error code, or ERR_IO_PENDING if the IO is in progress.
// If ERR_IO_PENDING is returned, the caller must keep |buf| and |address|
@@ -140,7 +138,7 @@ class NET_EXPORT UDPSocketPosix : public base::NonThreadSafe {
// |group_address| is the group address to join, could be either
// an IPv4 or IPv6 address.
// Returns a net error code.
- int JoinGroup(const IPAddressNumber& group_address) const;
+ int JoinGroup(const IPAddress& group_address) const;
// Leaves the multicast group.
// |group_address| is the group address to leave, could be either
@@ -149,7 +147,7 @@ class NET_EXPORT UDPSocketPosix : public base::NonThreadSafe {
// It's optional to leave the multicast group before destroying
// the socket. It will be done by the OS.
// Returns a net error code.
- int LeaveGroup(const IPAddressNumber& group_address) const;
+ int LeaveGroup(const IPAddress& group_address) const;
// Sets interface to use for multicast. If |interface_index| set to 0,
// default interface is used.
@@ -255,7 +253,7 @@ class NET_EXPORT UDPSocketPosix : public base::NonThreadSafe {
int SetMulticastOptions();
int DoBind(const IPEndPoint& address);
// Binds to a random port on |address|.
- int RandomBind(const IPAddressNumber& address);
+ int RandomBind(const IPAddress& address);
int socket_;
diff --git a/chromium/net/udp/udp_socket_unittest.cc b/chromium/net/udp/udp_socket_unittest.cc
index 4bd8a9ece0d..28f29cc6403 100644
--- a/chromium/net/udp/udp_socket_unittest.cc
+++ b/chromium/net/udp/udp_socket_unittest.cc
@@ -16,9 +16,9 @@
#include "base/stl_util.h"
#include "base/thread_task_runner_handle.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/test_completion_callback.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_entry.h"
@@ -129,11 +129,10 @@ class UDPSocketTest : public PlatformTest {
void CreateUDPAddress(const std::string& ip_str,
uint16_t port,
IPEndPoint* address) {
- IPAddressNumber ip_number;
- bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
- if (!rv)
+ IPAddress ip_address;
+ if (!ip_address.AssignFromIPLiteral(ip_str))
return;
- *address = IPEndPoint(ip_number, port);
+ *address = IPEndPoint(ip_address, port);
}
// Run unit test for a connection test.
@@ -513,11 +512,11 @@ TEST_F(UDPSocketTest, ClientGetLocalPeerAddresses) {
SCOPED_TRACE(std::string("Connecting from ") + tests[i].local_address +
std::string(" to ") + tests[i].remote_address);
- IPAddressNumber ip_number;
- ParseIPLiteralToNumber(tests[i].remote_address, &ip_number);
- IPEndPoint remote_address(ip_number, 80);
- ParseIPLiteralToNumber(tests[i].local_address, &ip_number);
- IPEndPoint local_address(ip_number, 80);
+ IPAddress ip_address;
+ EXPECT_TRUE(ip_address.AssignFromIPLiteral(tests[i].remote_address));
+ IPEndPoint remote_address(ip_address, 80);
+ EXPECT_TRUE(ip_address.AssignFromIPLiteral(tests[i].local_address));
+ IPEndPoint local_address(ip_address, 80);
UDPClientSocket client(DatagramSocket::DEFAULT_BIND,
RandIntCallback(),
@@ -611,8 +610,8 @@ TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) {
IPEndPoint bind_address;
CreateUDPAddress("0.0.0.0", kPort, &bind_address);
- IPAddressNumber group_ip;
- EXPECT_TRUE(ParseIPLiteralToNumber(kGroup, &group_ip));
+ IPAddress group_ip;
+ EXPECT_TRUE(group_ip.AssignFromIPLiteral(kGroup));
UDPSocket socket(DatagramSocket::DEFAULT_BIND,
RandIntCallback(),
diff --git a/chromium/net/udp/udp_socket_win.cc b/chromium/net/udp/udp_socket_win.cc
index 27e2750e40e..c1628229833 100644
--- a/chromium/net/udp/udp_socket_win.cc
+++ b/chromium/net/udp/udp_socket_win.cc
@@ -15,6 +15,7 @@
#include "base/metrics/sparse_histogram.h"
#include "base/rand_util.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/network_activity_monitor.h"
@@ -439,12 +440,12 @@ int UDPSocketWin::InternalConnect(const IPEndPoint& address) {
int rv = 0;
if (bind_type_ == DatagramSocket::RANDOM_BIND) {
- // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
+ // Construct IPAddress of appropriate size (IPv4 or IPv6) of 0s,
// representing INADDR_ANY or in6addr_any.
- size_t addr_size = (address.GetSockAddrFamily() == AF_INET) ?
- kIPv4AddressSize : kIPv6AddressSize;
- IPAddressNumber addr_any(addr_size);
- rv = RandomBind(addr_any);
+ size_t addr_size = (address.GetSockAddrFamily() == AF_INET)
+ ? IPAddress::kIPv4AddressSize
+ : IPAddress::kIPv6AddressSize;
+ rv = RandomBind(IPAddress::AllZeros(addr_size));
}
// else connect() does the DatagramSocket::DEFAULT_BIND
@@ -952,7 +953,7 @@ int UDPSocketWin::DoBind(const IPEndPoint& address) {
return MapSystemError(last_error);
}
-int UDPSocketWin::RandomBind(const IPAddressNumber& address) {
+int UDPSocketWin::RandomBind(const IPAddress& address) {
DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
for (int i = 0; i < kBindRetries; ++i) {
@@ -964,19 +965,19 @@ int UDPSocketWin::RandomBind(const IPAddressNumber& address) {
return DoBind(IPEndPoint(address, 0));
}
-int UDPSocketWin::JoinGroup(
- const IPAddressNumber& group_address) const {
+int UDPSocketWin::JoinGroup(const IPAddress& group_address) const {
DCHECK(CalledOnValidThread());
if (!is_connected())
return ERR_SOCKET_NOT_CONNECTED;
switch (group_address.size()) {
- case kIPv4AddressSize: {
+ case IPAddress::kIPv4AddressSize: {
if (addr_family_ != AF_INET)
return ERR_ADDRESS_INVALID;
ip_mreq mreq;
mreq.imr_interface.s_addr = htonl(multicast_interface_);
- memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
+ memcpy(&mreq.imr_multiaddr, group_address.bytes().data(),
+ IPAddress::kIPv4AddressSize);
int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
reinterpret_cast<const char*>(&mreq),
sizeof(mreq));
@@ -984,12 +985,13 @@ int UDPSocketWin::JoinGroup(
return MapSystemError(WSAGetLastError());
return OK;
}
- case kIPv6AddressSize: {
+ case IPAddress::kIPv6AddressSize: {
if (addr_family_ != AF_INET6)
return ERR_ADDRESS_INVALID;
ipv6_mreq mreq;
mreq.ipv6mr_interface = multicast_interface_;
- memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
+ memcpy(&mreq.ipv6mr_multiaddr, group_address.bytes().data(),
+ IPAddress::kIPv6AddressSize);
int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
reinterpret_cast<const char*>(&mreq),
sizeof(mreq));
@@ -1003,31 +1005,32 @@ int UDPSocketWin::JoinGroup(
}
}
-int UDPSocketWin::LeaveGroup(
- const IPAddressNumber& group_address) const {
+int UDPSocketWin::LeaveGroup(const IPAddress& group_address) const {
DCHECK(CalledOnValidThread());
if (!is_connected())
return ERR_SOCKET_NOT_CONNECTED;
switch (group_address.size()) {
- case kIPv4AddressSize: {
+ case IPAddress::kIPv4AddressSize: {
if (addr_family_ != AF_INET)
return ERR_ADDRESS_INVALID;
ip_mreq mreq;
mreq.imr_interface.s_addr = htonl(multicast_interface_);
- memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
+ memcpy(&mreq.imr_multiaddr, group_address.bytes().data(),
+ IPAddress::kIPv4AddressSize);
int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
reinterpret_cast<const char*>(&mreq), sizeof(mreq));
if (rv)
return MapSystemError(WSAGetLastError());
return OK;
}
- case kIPv6AddressSize: {
+ case IPAddress::kIPv6AddressSize: {
if (addr_family_ != AF_INET6)
return ERR_ADDRESS_INVALID;
ipv6_mreq mreq;
mreq.ipv6mr_interface = multicast_interface_;
- memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
+ memcpy(&mreq.ipv6mr_multiaddr, group_address.bytes().data(),
+ IPAddress::kIPv6AddressSize);
int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP,
reinterpret_cast<const char*>(&mreq), sizeof(mreq));
if (rv)
diff --git a/chromium/net/udp/udp_socket_win.h b/chromium/net/udp/udp_socket_win.h
index ea72e28b84c..62c3e1163d3 100644
--- a/chromium/net/udp/udp_socket_win.h
+++ b/chromium/net/udp/udp_socket_win.h
@@ -29,6 +29,8 @@
namespace net {
+class IPAddress;
+
class NET_EXPORT UDPSocketWin
: NON_EXPORTED_BASE(public base::NonThreadSafe),
NON_EXPORTED_BASE(public base::win::ObjectWatcher::Delegate) {
@@ -91,23 +93,19 @@ class NET_EXPORT UDPSocketWin
// |address| is a buffer provided by the caller for receiving the sender
// address information about the received data. This buffer must be kept
// alive by the caller until the callback is placed.
- // |address_length| is a ptr to the length of the |address| buffer. This
- // is an input parameter containing the maximum size |address| can hold
- // and also an output parameter for the size of |address| upon completion.
// |callback| is the callback on completion of the RecvFrom.
// Returns a net error code, or ERR_IO_PENDING if the IO is in progress.
- // If ERR_IO_PENDING is returned, the caller must keep |buf|, |address|,
- // and |address_length| alive until the callback is called.
+ // If ERR_IO_PENDING is returned, the caller must keep |buf| and |address|,
+ // alive until the callback is called.
int RecvFrom(IOBuffer* buf,
int buf_len,
IPEndPoint* address,
const CompletionCallback& callback);
// Sends to a socket with a particular destination.
- // |buf| is the buffer to send
- // |buf_len| is the number of bytes to send
+ // |buf| is the buffer to send.
+ // |buf_len| is the number of bytes to send.
// |address| is the recipient address.
- // |address_length| is the size of the recipient address
// |callback| is the user callback function to call on complete.
// Returns a net error code, or ERR_IO_PENDING if the IO is in progress.
// If ERR_IO_PENDING is returned, the caller must keep |buf| and |address|
@@ -144,7 +142,7 @@ class NET_EXPORT UDPSocketWin
// |group_address| is the group address to join, could be either
// an IPv4 or IPv6 address.
// Returns a net error code.
- int JoinGroup(const IPAddressNumber& group_address) const;
+ int JoinGroup(const IPAddress& group_address) const;
// Leaves the multicast group.
// |group_address| is the group address to leave, could be either
@@ -153,7 +151,7 @@ class NET_EXPORT UDPSocketWin
// It's optional to leave the multicast group before destroying
// the socket. It will be done by the OS.
// Return a net error code.
- int LeaveGroup(const IPAddressNumber& group_address) const;
+ int LeaveGroup(const IPAddress& group_address) const;
// Sets interface to use for multicast. If |interface_index| set to 0,
// default interface is used.
@@ -249,7 +247,7 @@ class NET_EXPORT UDPSocketWin
int SetMulticastOptions();
int DoBind(const IPEndPoint& address);
// Binds to a random port on |address|.
- int RandomBind(const IPAddressNumber& address);
+ int RandomBind(const IPAddress& address);
SOCKET socket_;
int addr_family_;
diff --git a/chromium/net/url_request/certificate_report_sender.cc b/chromium/net/url_request/certificate_report_sender.cc
index 55b27a59275..5db245783e7 100644
--- a/chromium/net/url_request/certificate_report_sender.cc
+++ b/chromium/net/url_request/certificate_report_sender.cc
@@ -19,8 +19,17 @@ namespace net {
CertificateReportSender::CertificateReportSender(
URLRequestContext* request_context,
CookiesPreference cookies_preference)
+ : CertificateReportSender(request_context,
+ cookies_preference,
+ ErrorCallback()) {}
+
+CertificateReportSender::CertificateReportSender(
+ URLRequestContext* request_context,
+ CookiesPreference cookies_preference,
+ const ErrorCallback& error_callback)
: request_context_(request_context),
- cookies_preference_(cookies_preference) {}
+ cookies_preference_(cookies_preference),
+ error_callback_(error_callback) {}
CertificateReportSender::~CertificateReportSender() {
// Cancel all of the uncompleted requests.
@@ -51,10 +60,18 @@ void CertificateReportSender::Send(const GURL& report_uri,
raw_url_request->Start();
}
+void CertificateReportSender::SetErrorCallback(
+ const ErrorCallback& error_callback) {
+ error_callback_ = error_callback;
+}
+
void CertificateReportSender::OnResponseStarted(URLRequest* request) {
- // TODO(estark): call a callback so that the caller can print a
- // warning on failure.
- DVLOG(1) << "Failed to send certificate report for " << request->url().host();
+ if (!request->status().is_success()) {
+ DVLOG(1) << "Failed to send certificate report for "
+ << request->url().host();
+ if (!error_callback_.is_null())
+ error_callback_.Run(request->url(), request->status().error());
+ }
CHECK_GT(inflight_requests_.erase(request), 0u);
// Clean up the request, which cancels it.
diff --git a/chromium/net/url_request/certificate_report_sender.h b/chromium/net/url_request/certificate_report_sender.h
index 0f247c3e4e2..a5b686c0487 100644
--- a/chromium/net/url_request/certificate_report_sender.h
+++ b/chromium/net/url_request/certificate_report_sender.h
@@ -8,6 +8,7 @@
#include <set>
#include <string>
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "net/http/transport_security_state.h"
@@ -29,6 +30,8 @@ class NET_EXPORT CertificateReportSender
: public URLRequest::Delegate,
public TransportSecurityState::ReportSender {
public:
+ using ErrorCallback = base::Callback<void(const GURL&, int)>;
+
// Represents whether or not to send cookies along with reports.
enum CookiesPreference { SEND_COOKIES, DO_NOT_SEND_COOKIES };
@@ -39,10 +42,21 @@ class NET_EXPORT CertificateReportSender
CertificateReportSender(URLRequestContext* request_context,
CookiesPreference cookies_preference);
+ // Constructs a CertificateReportSender that sends reports with the
+ // given |request_context| and includes or excludes cookies based on
+ // |cookies_preference|. |request_context| must outlive the
+ // CertificateReportSender. When sending a report results in an error,
+ // |error_callback| is called with the report URI and net error as
+ // arguments.
+ CertificateReportSender(URLRequestContext* request_context,
+ CookiesPreference cookies_preference,
+ const ErrorCallback& error_callback);
+
~CertificateReportSender() override;
// TransportSecurityState::ReportSender implementation.
void Send(const GURL& report_uri, const std::string& report) override;
+ void SetErrorCallback(const ErrorCallback& error_callback) override;
// net::URLRequest::Delegate implementation.
void OnResponseStarted(URLRequest* request) override;
@@ -56,6 +70,9 @@ class NET_EXPORT CertificateReportSender
// Owns the contained requests.
std::set<URLRequest*> inflight_requests_;
+ // Called when a sent report results in an error.
+ ErrorCallback error_callback_;
+
DISALLOW_COPY_AND_ASSIGN(CertificateReportSender);
};
diff --git a/chromium/net/url_request/certificate_report_sender_unittest.cc b/chromium/net/url_request/certificate_report_sender_unittest.cc
index 0024bcbe5eb..98e7ac8b6c4 100644
--- a/chromium/net/url_request/certificate_report_sender_unittest.cc
+++ b/chromium/net/url_request/certificate_report_sender_unittest.cc
@@ -47,6 +47,13 @@ void CheckUploadData(const URLRequest& request,
EXPECT_EQ(1u, expect_reports->erase(upload_data));
}
+// Provides an error callback for report sending that sets |called| to
+// true.
+void ErrorCallback(bool* called, const GURL& report_uri, int net_error) {
+ EXPECT_NE(OK, net_error);
+ *called = true;
+}
+
// A network delegate that lets tests check that a certificate report
// was sent. It counts the number of requests and lets tests register a
// callback to run when the request is destroyed. It also checks that
@@ -238,6 +245,31 @@ TEST_F(CertificateReportSenderTest, ErroredRequestGetsDeleted) {
SendReport(&reporter, kDummyReport, url, 0);
}
+// Test that the error callback, if provided, gets called when a request
+// returns an error.
+TEST_F(CertificateReportSenderTest, ErroredRequestCallsCallback) {
+ bool error_callback_called = false;
+ GURL url = URLRequestFailedJob::GetMockHttpsUrl(ERR_FAILED);
+ CertificateReportSender reporter(
+ context(), CertificateReportSender::DO_NOT_SEND_COOKIES,
+ base::Bind(ErrorCallback, &error_callback_called));
+ // SendReport will block until the URLRequest is destroyed.
+ SendReport(&reporter, kDummyReport, url, 0);
+ EXPECT_TRUE(error_callback_called);
+}
+
+// Test that the error callback does not get called when a request
+// does not return an error.
+TEST_F(CertificateReportSenderTest, SuccessfulRequestDoesNotCallErrorCallback) {
+ bool error_callback_called = false;
+ GURL url = URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
+ CertificateReportSender reporter(
+ context(), CertificateReportSender::DO_NOT_SEND_COOKIES,
+ base::Bind(ErrorCallback, &error_callback_called));
+ SendReport(&reporter, kDummyReport, url, 0);
+ EXPECT_FALSE(error_callback_called);
+}
+
// Test that cookies are sent or not sent according to the error
// reporter's cookies preference.
diff --git a/chromium/net/url_request/redirect_info.cc b/chromium/net/url_request/redirect_info.cc
index 16b517a994b..f7f95383e2d 100644
--- a/chromium/net/url_request/redirect_info.cc
+++ b/chromium/net/url_request/redirect_info.cc
@@ -8,6 +8,8 @@ namespace net {
RedirectInfo::RedirectInfo() : status_code(-1) {}
+RedirectInfo::RedirectInfo(const RedirectInfo& other) = default;
+
RedirectInfo::~RedirectInfo() {}
} // namespace net
diff --git a/chromium/net/url_request/redirect_info.h b/chromium/net/url_request/redirect_info.h
index b1ae6369eb3..19343dbe675 100644
--- a/chromium/net/url_request/redirect_info.h
+++ b/chromium/net/url_request/redirect_info.h
@@ -17,6 +17,7 @@ namespace net {
// content/common/resource_messages.h.
struct NET_EXPORT RedirectInfo {
RedirectInfo();
+ RedirectInfo(const RedirectInfo& other);
~RedirectInfo();
// The status code for the redirect response. This is almost redundant with
@@ -36,6 +37,11 @@ struct NET_EXPORT RedirectInfo {
// The new HTTP referrer header.
std::string new_referrer;
+
+ // The hostname of the referrer if it asked the client to include a referred
+ // Token Binding when following the redirect; otherwise this is the empty
+ // string.
+ std::string referred_token_binding_host;
};
} // namespace net
diff --git a/chromium/net/url_request/url_fetcher.h b/chromium/net/url_request/url_fetcher.h
index b8642405986..3536f0bc12a 100644
--- a/chromium/net/url_request/url_fetcher.h
+++ b/chromium/net/url_request/url_fetcher.h
@@ -39,9 +39,9 @@ typedef std::vector<std::string> ResponseCookies;
// To use this class, create an instance with the desired URL and a pointer to
// the object to be notified when the URL has been loaded:
// scoped_ptr<URLFetcher> fetcher =
-// URLFetcher::Create("http://www.google.com",
-// URLFetcher::GET,
-// this);
+// URLFetcher::Create(GURL("http://www.google.com"),
+// URLFetcher::GET,
+// this);
//
// You must also set a request context getter:
//
@@ -49,7 +49,7 @@ typedef std::vector<std::string> ResponseCookies;
//
// Then, optionally set properties on this object, like the request context or
// extra headers:
-// fetcher->set_extra_request_headers("X-Foo: bar");
+// fetcher->AddExtraRequestHeader("X-Foo: bar");
//
// Finally, start the request:
// fetcher->Start();
@@ -57,14 +57,13 @@ typedef std::vector<std::string> ResponseCookies;
// You may cancel the request by destroying the URLFetcher:
// fetcher.reset();
//
-// The object you supply as a delegate must inherit from
-// URLFetcherDelegate; when the fetch is completed,
-// OnURLFetchComplete() will be called with a pointer to the URLFetcher. From
-// that point until the original URLFetcher instance is destroyed, you may use
-// accessor methods to see the result of the fetch. You should copy these
-// objects if you need them to live longer than the URLFetcher instance. If the
-// URLFetcher instance is destroyed before the callback happens, the fetch will
-// be canceled and no callback will occur.
+// The object you supply as a delegate must inherit from URLFetcherDelegate.
+// When the fetch is completed, OnURLFetchComplete() will be called with a
+// pointer to the URLFetcher. From that point until the original URLFetcher
+// instance is destroyed, you may use accessor methods to see the result of the
+// fetch. You should copy these objects if you need them to live longer than
+// 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.
diff --git a/chromium/net/url_request/url_fetcher_core.cc b/chromium/net/url_request/url_fetcher_core.cc
index ee1a3d8c830..3b1e1cc55d0 100644
--- a/chromium/net/url_request/url_fetcher_core.cc
+++ b/chromium/net/url_request/url_fetcher_core.cc
@@ -205,6 +205,7 @@ void URLFetcherCore::AppendChunkToUpload(const std::string& content,
bool is_last_chunk) {
DCHECK(delegate_task_runner_.get());
DCHECK(network_task_runner_.get());
+ DCHECK(is_chunked_upload_);
network_task_runner_->PostTask(
FROM_HERE,
base::Bind(&URLFetcherCore::CompleteAddingUploadDataChunk, this, content,
@@ -516,6 +517,14 @@ URLFetcherCore::~URLFetcherCore() {
void URLFetcherCore::StartOnIOThread() {
DCHECK(network_task_runner_->BelongsToCurrentThread());
+ // Create ChunkedUploadDataStream, if needed, so the consumer can start
+ // appending data. Have to do it here because StartURLRequest() may be called
+ // asynchonously.
+ if (is_chunked_upload_) {
+ chunked_stream_.reset(new ChunkedUploadDataStream(0));
+ chunked_stream_writer_ = chunked_stream_->CreateWriter();
+ }
+
if (!response_writer_)
response_writer_.reset(new URLFetcherStringWriter);
@@ -550,8 +559,11 @@ void URLFetcherCore::StartURLRequest() {
request_->set_stack_trace(stack_trace_);
int flags = request_->load_flags() | load_flags_;
- if (is_chunked_upload_)
- request_->EnableChunkedUpload();
+ // TODO(mmenke): This should really be with the other code to set the upload
+ // body, below.
+ if (chunked_stream_)
+ request_->set_upload(std::move(chunked_stream_));
+
request_->SetLoadFlags(flags);
request_->SetReferrer(referrer_);
request_->set_referrer_policy(referrer_policy_);
@@ -835,17 +847,10 @@ base::TimeTicks URLFetcherCore::GetBackoffReleaseTime() {
void URLFetcherCore::CompleteAddingUploadDataChunk(
const std::string& content, bool is_last_chunk) {
- if (was_cancelled_) {
- // Since CompleteAddingUploadDataChunk() is posted as a *delayed* task, it
- // may run after the URLFetcher was already stopped.
- return;
- }
DCHECK(is_chunked_upload_);
- DCHECK(request_.get());
DCHECK(!content.empty());
- request_->AppendChunkToUpload(content.data(),
- static_cast<int>(content.length()),
- is_last_chunk);
+ chunked_stream_writer_->AppendData(
+ content.data(), static_cast<int>(content.length()), is_last_chunk);
}
int URLFetcherCore::WriteBuffer(scoped_refptr<DrainableIOBuffer> data) {
diff --git a/chromium/net/url_request/url_fetcher_core.h b/chromium/net/url_request/url_fetcher_core.h
index 9b4bba2c53b..1f3d7fdde4b 100644
--- a/chromium/net/url_request/url_fetcher_core.h
+++ b/chromium/net/url_request/url_fetcher_core.h
@@ -18,6 +18,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
+#include "net/base/chunked_upload_data_stream.h"
#include "net/base/host_port_pair.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/url_fetcher.h"
@@ -273,6 +274,14 @@ class URLFetcherCore : public base::RefCountedThreadSafe<URLFetcherCore>,
URLRequest::ReferrerPolicy referrer_policy_;
bool is_chunked_upload_; // True if using chunked transfer encoding
+ // Used to write to |chunked_stream|, even after ownership has been passed to
+ // the URLRequest. Continues to be valid even after the request deletes its
+ // upload data.
+ scoped_ptr<ChunkedUploadDataStream::Writer> chunked_stream_writer_;
+
+ // Temporary storage of ChunkedUploadDataStream, before request is created.
+ scoped_ptr<ChunkedUploadDataStream> chunked_stream_;
+
// Used to determine how long to wait before making a request or doing a
// retry.
//
diff --git a/chromium/net/url_request/url_fetcher_impl_unittest.cc b/chromium/net/url_request/url_fetcher_impl_unittest.cc
index 9b0c5621a9c..6775fa27d29 100644
--- a/chromium/net/url_request/url_fetcher_impl_unittest.cc
+++ b/chromium/net/url_request/url_fetcher_impl_unittest.cc
@@ -24,7 +24,9 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/test_timeouts.h"
#include "base/thread_task_runner_handle.h"
+#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "crypto/nss_util.h"
@@ -42,7 +44,7 @@
#include "net/url_request/url_request_throttler_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
#include "net/cert_net/nss_ocsp.h"
#endif
@@ -422,14 +424,14 @@ class URLFetcherTest : public testing::Test {
kDefaultResponsePath));
ASSERT_TRUE(hanging_url_.is_valid());
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
crypto::EnsureNSSInit();
EnsureNSSHttpIOInit();
#endif
}
void TearDown() override {
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
ShutdownNSSHttpIO();
#endif
}
@@ -775,6 +777,67 @@ TEST_F(URLFetcherTest, PostWithUploadStreamFactoryAndRetries) {
EXPECT_EQ(2u, num_upload_streams_created());
}
+// Tests simple chunked POST case.
+TEST_F(URLFetcherTest, PostChunked) {
+ scoped_refptr<FetcherTestURLRequestContextGetter> context_getter(
+ CreateCrossThreadContextGetter());
+
+ WaitingURLFetcherDelegate delegate;
+ delegate.CreateFetcher(test_server_->GetURL("/echo"), URLFetcher::POST,
+ CreateCrossThreadContextGetter());
+
+ delegate.fetcher()->SetChunkedUpload("text/plain");
+
+ // This posts a task to start the fetcher.
+ delegate.fetcher()->Start();
+
+ delegate.fetcher()->AppendChunkToUpload(kCreateUploadStreamBody, false);
+ delegate.fetcher()->AppendChunkToUpload(kCreateUploadStreamBody, true);
+
+ delegate.WaitForComplete();
+
+ EXPECT_TRUE(delegate.fetcher()->GetStatus().is_success());
+ EXPECT_EQ(200, delegate.fetcher()->GetResponseCode());
+ std::string data;
+ ASSERT_TRUE(delegate.fetcher()->GetResponseAsString(&data));
+ EXPECT_EQ(std::string(kCreateUploadStreamBody) +
+ std::string(kCreateUploadStreamBody),
+ data);
+}
+
+// Tests that data can be appended to a request after it fails. This is needed
+// because the consumer may try to append data to a request after it failed, but
+// before the consumer learns that it failed.
+TEST_F(URLFetcherTest, PostAppendChunkAfterError) {
+ scoped_refptr<FetcherTestURLRequestContextGetter> context_getter(
+ CreateCrossThreadContextGetter());
+
+ WaitingURLFetcherDelegate delegate;
+ // Request that will fail almost immediately after being started, due to using
+ // a reserved port.
+ delegate.CreateFetcher(GURL("http://127.0.0.1:7"), URLFetcher::POST,
+ context_getter);
+
+ delegate.fetcher()->SetChunkedUpload("text/plain");
+
+ // This posts a task to start the fetcher.
+ delegate.fetcher()->Start();
+
+ // Give the request a chance to fail, and inform the fetcher of the failure,
+ // while blocking the current thread so the error doesn't reach the delegate.
+ base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
+
+ // Try to append data.
+ delegate.fetcher()->AppendChunkToUpload("kCreateUploadStreamBody", false);
+ delegate.fetcher()->AppendChunkToUpload("kCreateUploadStreamBody", true);
+
+ delegate.WaitForComplete();
+
+ // Make sure the request failed, as expected.
+ EXPECT_FALSE(delegate.fetcher()->GetStatus().is_success());
+ EXPECT_EQ(ERR_UNSAFE_PORT, delegate.fetcher()->GetStatus().error());
+}
+
// Checks that upload progress increases over time, never exceeds what's already
// been sent, and adds a chunk whenever all previously appended chunks have
// been uploaded.
@@ -1043,6 +1106,38 @@ TEST_F(URLFetcherTest, ThrottleOnRepeatedFetches) {
EXPECT_GE(Time::Now() - start_time, base::TimeDelta::FromSeconds(1));
}
+// If throttling kicks in for a chunked upload, there should be no crash.
+TEST_F(URLFetcherTest, ThrottleChunkedUpload) {
+ GURL url(test_server_->GetURL("/echo"));
+
+ scoped_refptr<FetcherTestURLRequestContextGetter> context_getter(
+ CreateSameThreadContextGetter());
+
+ // Registers an entry for test url. It only allows 3 requests to be sent
+ // in 200 milliseconds.
+ context_getter->AddThrottlerEntry(
+ url, std::string() /* url_id */, 200 /* sliding_window_period_ms */,
+ 3 /* max_send_threshold */, 1 /* initial_backoff_ms */,
+ 2.0 /* multiply_factor */, 0.0 /* jitter_factor */,
+ 256 /* maximum_backoff_ms */,
+ false /* reserve_sending_time_for_next_request*/);
+
+ for (int i = 0; i < 20; ++i) {
+ WaitingURLFetcherDelegate delegate;
+ delegate.CreateFetcher(url, URLFetcher::POST, context_getter);
+ delegate.fetcher()->SetChunkedUpload("text/plain");
+ delegate.fetcher()->Start();
+ delegate.fetcher()->AppendChunkToUpload(kCreateUploadStreamBody, true);
+ delegate.WaitForComplete();
+
+ EXPECT_TRUE(delegate.fetcher()->GetStatus().is_success());
+ EXPECT_EQ(200, delegate.fetcher()->GetResponseCode());
+ std::string data;
+ ASSERT_TRUE(delegate.fetcher()->GetResponseAsString(&data));
+ EXPECT_EQ(kCreateUploadStreamBody, data);
+ }
+}
+
TEST_F(URLFetcherTest, ThrottleOn5xxRetries) {
base::Time start_time = Time::Now();
GURL url(test_server_->GetURL("/server-unavailable.html"));
diff --git a/chromium/net/url_request/url_request.cc b/chromium/net/url_request/url_request.cc
index 7bd01e0a6c2..2ace1d257a9 100644
--- a/chromium/net/url_request/url_request.cc
+++ b/chromium/net/url_request/url_request.cc
@@ -10,8 +10,6 @@
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
-#include "base/debug/alias.h"
-#include "base/debug/dump_without_crashing.h"
#include "base/debug/stack_trace.h"
#include "base/lazy_instance.h"
#include "base/memory/singleton.h"
@@ -23,7 +21,6 @@
#include "base/synchronization/lock.h"
#include "base/values.h"
#include "net/base/auth.h"
-#include "net/base/chunked_upload_data_stream.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/load_timing_info.h"
@@ -193,22 +190,6 @@ URLRequest::~URLRequest() {
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_REQUEST_ALIVE, net_error);
}
-void URLRequest::EnableChunkedUpload() {
- DCHECK(!upload_data_stream_ || upload_data_stream_->is_chunked());
- if (!upload_data_stream_) {
- upload_chunked_data_stream_ = new ChunkedUploadDataStream(0);
- upload_data_stream_.reset(upload_chunked_data_stream_);
- }
-}
-
-void URLRequest::AppendChunkToUpload(const char* bytes,
- int bytes_len,
- bool is_last_chunk) {
- DCHECK(upload_data_stream_);
- DCHECK(upload_data_stream_->is_chunked());
- upload_chunked_data_stream_->AppendData(bytes, bytes_len, is_last_chunk);
-}
-
void URLRequest::set_upload(scoped_ptr<UploadDataStream> upload) {
upload_data_stream_ = std::move(upload);
}
@@ -372,7 +353,8 @@ UploadProgress URLRequest::GetUploadProgress() const {
return job_->GetUploadProgress();
}
-void URLRequest::GetResponseHeaderByName(const string& name, string* value) {
+void URLRequest::GetResponseHeaderByName(const string& name,
+ string* value) const {
DCHECK(value);
if (response_info_.headers.get()) {
response_info_.headers->GetNormalizedHeader(name, value);
@@ -526,7 +508,6 @@ void URLRequest::Start() {
load_timing_info_.request_start_time = response_info_.request_time;
load_timing_info_.request_start = base::TimeTicks::Now();
- // Only notify the delegate for the initial request.
if (network_delegate_) {
// TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed.
tracked_objects::ScopedTracker tracking_profile25(
@@ -663,10 +644,13 @@ void URLRequest::StartJob(URLRequestJob* job) {
}
}
- // Don't allow errors to be sent from within Start().
- // TODO(brettw) this may cause NotifyDone to be sent synchronously,
- // we probably don't want this: they should be sent asynchronously so
- // the caller does not get reentered.
+ // Start() always completes asynchronously.
+ //
+ // Status is generally set by URLRequestJob itself, but Start() calls
+ // directly into the URLRequestJob subclass, so URLRequestJob can't set it
+ // here.
+ // TODO(mmenke): Make the URLRequest manage its own status.
+ status_ = URLRequestStatus::FromError(ERR_IO_PENDING);
job_->Start();
}
@@ -702,24 +686,6 @@ void URLRequest::CancelWithSSLError(int error, const SSLInfo& ssl_info) {
void URLRequest::DoCancel(int error, const SSLInfo& ssl_info) {
DCHECK(error < 0);
- // ~500,000 ERR_ABORTED < 100ms in Canary channel a day. Sample .01% to get
- // ~50 reports a day.
- // TODO(csharrison) Remove this code when crbug.com/557430 is resolved.
- int64_t request_time =
- (base::TimeTicks::Now() - creation_time_).InMilliseconds();
- if (!has_notified_completion_ && error == ERR_ABORTED &&
- request_time <= 100 && load_flags_ & LOAD_MAIN_FRAME &&
- base::RandDouble() < .00001) {
- static int dump_times = 0;
- if (dump_times < 5) {
- char url_copy[256] = {0};
- strncpy(url_copy, url().spec().c_str(), sizeof(url_copy));
- base::debug::Alias(&url_copy);
- base::debug::Alias(&request_time);
- base::debug::DumpWithoutCrashing();
- dump_times++;
- }
- }
// If cancelled while calling a delegate, clear delegate info.
if (calling_delegate_) {
LogUnblocked();
@@ -860,9 +826,10 @@ void URLRequest::NotifyResponseStarted() {
}
void URLRequest::FollowDeferredRedirect() {
- CHECK(job_.get());
- CHECK(status_.is_success());
+ DCHECK(job_.get());
+ DCHECK(status_.is_success());
+ status_ = URLRequestStatus::FromError(ERR_IO_PENDING);
job_->FollowDeferredRedirect();
}
@@ -870,6 +837,7 @@ void URLRequest::SetAuth(const AuthCredentials& credentials) {
DCHECK(job_.get());
DCHECK(job_->NeedsAuth());
+ status_ = URLRequestStatus::FromError(ERR_IO_PENDING);
job_->SetAuth(credentials);
}
@@ -877,6 +845,7 @@ void URLRequest::CancelAuth() {
DCHECK(job_.get());
DCHECK(job_->NeedsAuth());
+ status_ = URLRequestStatus::FromError(ERR_IO_PENDING);
job_->CancelAuth();
}
@@ -884,12 +853,14 @@ void URLRequest::ContinueWithCertificate(X509Certificate* client_cert,
SSLPrivateKey* client_private_key) {
DCHECK(job_.get());
+ status_ = URLRequestStatus::FromError(ERR_IO_PENDING);
job_->ContinueWithCertificate(client_cert, client_private_key);
}
void URLRequest::ContinueDespiteLastError() {
DCHECK(job_.get());
+ status_ = URLRequestStatus::FromError(ERR_IO_PENDING);
job_->ContinueDespiteLastError();
}
@@ -1001,6 +972,7 @@ int URLRequest::Redirect(const RedirectInfo& redirect_info) {
referrer_ = redirect_info.new_referrer;
first_party_for_cookies_ = redirect_info.new_first_party_for_cookies;
+ token_binding_referrer_ = redirect_info.referred_token_binding_host;
url_chain_.push_back(redirect_info.new_url);
--redirect_limit_;
@@ -1116,11 +1088,13 @@ void URLRequest::NotifyAuthRequiredComplete(
void URLRequest::NotifyCertificateRequested(
SSLCertRequestInfo* cert_request_info) {
+ status_ = URLRequestStatus();
delegate_->OnCertificateRequested(this, cert_request_info);
}
void URLRequest::NotifySSLCertificateError(const SSLInfo& ssl_info,
bool fatal) {
+ status_ = URLRequestStatus();
delegate_->OnSSLCertificateError(this, ssl_info, fatal);
}
diff --git a/chromium/net/url_request/url_request.h b/chromium/net/url_request/url_request.h
index 1a174704c6c..fcbc4454b8c 100644
--- a/chromium/net/url_request/url_request.h
+++ b/chromium/net/url_request/url_request.h
@@ -46,7 +46,6 @@ class StackTrace;
namespace net {
-class ChunkedUploadDataStream;
class CookieOptions;
class HostPortPair;
class IOBuffer;
@@ -326,28 +325,18 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe),
ReferrerPolicy referrer_policy() const { return referrer_policy_; }
void set_referrer_policy(ReferrerPolicy referrer_policy);
+ // If this request should include a referred Token Binding, this returns the
+ // hostname of the referrer that indicated this request should include a
+ // referred Token Binding. Otherwise, this returns the empty string.
+ const std::string& token_binding_referrer() const {
+ return token_binding_referrer_;
+ }
+
// Sets the delegate of the request. This is only to allow creating a request
// before creating its delegate. |delegate| must be non-NULL and the request
// must not yet have a Delegate set.
void set_delegate(Delegate* delegate);
- // Indicates that the request body should be sent using chunked transfer
- // encoding. This method may only be called before Start() is called.
- void EnableChunkedUpload();
-
- // Appends the given bytes to the request's upload data to be sent
- // immediately via chunked transfer encoding. When all data has been added,
- // set |is_last_chunk| to true to indicate the end of upload data. All chunks
- // but the last must have |bytes_len| > 0.
- //
- // This method may be called only after calling EnableChunkedUpload().
- //
- // Despite the name of this method, over-the-wire chunk boundaries will most
- // likely not match the "chunks" appended with this function.
- void AppendChunkToUpload(const char* bytes,
- int bytes_len,
- bool is_last_chunk);
-
// Sets the upload data.
void set_upload(scoped_ptr<UploadDataStream> upload);
@@ -435,7 +424,8 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe),
// that appear more than once in the response are coalesced, with values
// separated by commas (per RFC 2616). This will not work with cookies since
// comma can be used in cookie values.
- void GetResponseHeaderByName(const std::string& name, std::string* value);
+ void GetResponseHeaderByName(const std::string& name,
+ std::string* value) const;
// The time when |this| was constructed.
base::TimeTicks creation_time() const { return creation_time_; }
@@ -782,9 +772,6 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe),
scoped_ptr<URLRequestJob> job_;
scoped_ptr<UploadDataStream> upload_data_stream_;
- // TODO(mmenke): Make whether or not an upload is chunked transparent to the
- // URLRequest.
- ChunkedUploadDataStream* upload_chunked_data_stream_;
std::vector<GURL> url_chain_;
GURL first_party_for_cookies_;
@@ -793,6 +780,7 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe),
std::string method_; // "GET", "POST", etc. Should be all uppercase.
std::string referrer_;
ReferrerPolicy referrer_policy_;
+ std::string token_binding_referrer_;
FirstPartyURLPolicy first_party_url_policy_;
HttpRequestHeaders extra_request_headers_;
int load_flags_; // Flags indicating the request type for the load;
diff --git a/chromium/net/url_request/url_request_backoff_manager.cc b/chromium/net/url_request/url_request_backoff_manager.cc
index 86fa9650dca..1212c47b77a 100644
--- a/chromium/net/url_request/url_request_backoff_manager.cc
+++ b/chromium/net/url_request/url_request_backoff_manager.cc
@@ -111,7 +111,7 @@ bool URLRequestBackoffManager::GetBackoffTime(HttpResponseHeaders* headers,
base::TimeDelta* result) const {
base::StringPiece name("Backoff");
std::string value;
- void* iter = NULL;
+ size_t iter = 0;
while (headers->EnumerateHeader(&iter, name, &value)) {
int64_t seconds;
base::StringToInt64(value, &seconds);
diff --git a/chromium/net/url_request/url_request_context.cc b/chromium/net/url_request/url_request_context.cc
index e9ab617dd58..e52021c6d06 100644
--- a/chromium/net/url_request/url_request_context.cc
+++ b/chromium/net/url_request/url_request_context.cc
@@ -25,6 +25,7 @@ URLRequestContext::URLRequestContext()
proxy_service_(nullptr),
network_delegate_(nullptr),
http_user_agent_settings_(nullptr),
+ cookie_store_(nullptr),
transport_security_state_(nullptr),
cert_transparency_verifier_(nullptr),
http_transaction_factory_(nullptr),
@@ -33,8 +34,8 @@ URLRequestContext::URLRequestContext()
backoff_manager_(nullptr),
sdch_manager_(nullptr),
network_quality_estimator_(nullptr),
- url_requests_(new std::set<const URLRequest*>) {
-}
+ url_requests_(new std::set<const URLRequest*>),
+ has_known_mismatched_cookie_store_(false) {}
URLRequestContext::~URLRequestContext() {
AssertNoURLRequests();
@@ -51,7 +52,7 @@ void URLRequestContext::CopyFrom(const URLRequestContext* other) {
set_ssl_config_service(other->ssl_config_service_.get());
set_network_delegate(other->network_delegate_);
set_http_server_properties(other->http_server_properties_);
- set_cookie_store(other->cookie_store_.get());
+ set_cookie_store(other->cookie_store_);
set_transport_security_state(other->transport_security_state_);
set_cert_transparency_verifier(other->cert_transparency_verifier_);
set_http_transaction_factory(other->http_transaction_factory_);
diff --git a/chromium/net/url_request/url_request_context.h b/chromium/net/url_request/url_request_context.h
index bb1486e0157..ee165b461fe 100644
--- a/chromium/net/url_request/url_request_context.h
+++ b/chromium/net/url_request/url_request_context.h
@@ -145,7 +145,7 @@ class NET_EXPORT URLRequestContext
// Gets the cookie store for this context (may be null, in which case
// cookies are not stored).
- CookieStore* cookie_store() const { return cookie_store_.get(); }
+ CookieStore* cookie_store() const { return cookie_store_; }
void set_cookie_store(CookieStore* cookie_store);
TransportSecurityState* transport_security_state() const {
@@ -219,6 +219,21 @@ class NET_EXPORT URLRequestContext
network_quality_estimator_ = network_quality_estimator;
}
+ // This is a temporary flag to aid in debugging crbug.com/548423. A
+ // CookieStore that is persisted shouldn't be used with a ChannelIDStore that
+ // is ephemeral, but there are occasional cases where that is ok. This method
+ // returns whether this URLRequestContext is in a situation where the
+ // ephemerality of the stores don't match and it has been determined that it
+ // is ok to do that. This helps in logging to filter legitimate cases of this
+ // mismatch from other cases.
+ bool has_known_mismatched_cookie_store() const {
+ return has_known_mismatched_cookie_store_;
+ }
+
+ void set_has_known_mismatched_cookie_store() {
+ has_known_mismatched_cookie_store_ = true;
+ }
+
private:
// ---------------------------------------------------------------------------
// Important: When adding any new members below, consider whether they need to
@@ -237,7 +252,7 @@ class NET_EXPORT URLRequestContext
NetworkDelegate* network_delegate_;
base::WeakPtr<HttpServerProperties> http_server_properties_;
HttpUserAgentSettings* http_user_agent_settings_;
- scoped_refptr<CookieStore> cookie_store_;
+ CookieStore* cookie_store_;
TransportSecurityState* transport_security_state_;
CTVerifier* cert_transparency_verifier_;
HttpTransactionFactory* http_transaction_factory_;
@@ -253,6 +268,7 @@ class NET_EXPORT URLRequestContext
// ---------------------------------------------------------------------------
scoped_ptr<std::set<const URLRequest*> > url_requests_;
+ bool has_known_mismatched_cookie_store_;
DISALLOW_COPY_AND_ASSIGN(URLRequestContext);
};
diff --git a/chromium/net/url_request/url_request_context_builder.cc b/chromium/net/url_request/url_request_context_builder.cc
index 3112f1f017e..e612ab81517 100644
--- a/chromium/net/url_request/url_request_context_builder.cc
+++ b/chromium/net/url_request/url_request_context_builder.cc
@@ -11,7 +11,6 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/thread_task_runner_handle.h"
@@ -23,7 +22,6 @@
#include "net/cert/cert_verifier.h"
#include "net/cookies/cookie_monster.h"
#include "net/dns/host_resolver.h"
-#include "net/ftp/ftp_network_layer.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
@@ -46,11 +44,12 @@
#include "net/url_request/url_request_throttler_manager.h"
#if !defined(DISABLE_FILE_SUPPORT)
-#include "net/url_request/file_protocol_handler.h"
+#include "net/url_request/file_protocol_handler.h" // nogncheck
#endif
#if !defined(DISABLE_FTP_SUPPORT)
-#include "net/url_request/ftp_protocol_handler.h"
+#include "net/ftp/ftp_network_layer.h" // nogncheck
+#include "net/url_request/ftp_protocol_handler.h" // nogncheck
#endif
namespace net {
@@ -179,14 +178,21 @@ URLRequestContextBuilder::HttpNetworkSessionParams::HttpNetworkSessionParams()
host_mapping_rules(NULL),
testing_fixed_http_port(0),
testing_fixed_https_port(0),
- next_protos(NextProtosDefaults()),
- use_alternative_services(true),
+ enable_spdy31(false),
+ enable_http2(true),
+ parse_alternative_services(false),
+ enable_alternative_service_with_different_host(false),
enable_quic(false),
quic_max_server_configs_stored_in_properties(0),
quic_delay_tcp_race(false),
quic_max_number_of_lossy_connections(0),
+ quic_prefer_aes(false),
quic_packet_loss_threshold(1.0f),
- quic_idle_connection_timeout_seconds(kIdleConnectionTimeoutSeconds) {}
+ quic_idle_connection_timeout_seconds(kIdleConnectionTimeoutSeconds),
+ quic_close_sessions_on_ip_change(false),
+ quic_migrate_sessions_on_network_change(false),
+ quic_migrate_sessions_early(false),
+ quic_disable_bidirectional_streams(false) {}
URLRequestContextBuilder::HttpNetworkSessionParams::~HttpNetworkSessionParams()
{}
@@ -203,6 +209,7 @@ URLRequestContextBuilder::URLRequestContextBuilder()
throttling_enabled_(false),
backoff_enabled_(false),
sdch_enabled_(false),
+ cookie_store_set_by_client_(false),
net_log_(nullptr) {
}
@@ -218,7 +225,6 @@ void URLRequestContextBuilder::SetHttpNetworkSessionComponents(
params->proxy_service = context->proxy_service();
params->ssl_config_service = context->ssl_config_service();
params->http_auth_handler_factory = context->http_auth_handler_factory();
- params->network_delegate = context->network_delegate();
params->http_server_properties = context->http_server_properties();
params->net_log = context->net_log();
params->channel_id_service = context->channel_id_service();
@@ -236,8 +242,8 @@ void URLRequestContextBuilder::DisableHttpCache() {
void URLRequestContextBuilder::SetSpdyAndQuicEnabled(bool spdy_enabled,
bool quic_enabled) {
- http_network_session_params_.next_protos =
- NextProtosWithSpdyAndQuic(spdy_enabled, quic_enabled);
+ http_network_session_params_.enable_spdy31 = spdy_enabled;
+ http_network_session_params_.enable_http2 = spdy_enabled;
http_network_session_params_.enable_quic = quic_enabled;
}
@@ -252,10 +258,12 @@ void URLRequestContextBuilder::SetInterceptors(
}
void URLRequestContextBuilder::SetCookieAndChannelIdStores(
- const scoped_refptr<CookieStore>& cookie_store,
- scoped_ptr<ChannelIDService> channel_id_service) {
- DCHECK(cookie_store);
- cookie_store_ = cookie_store;
+ scoped_ptr<CookieStore> cookie_store,
+ scoped_ptr<ChannelIDService> channel_id_service) {
+ cookie_store_set_by_client_ = true;
+ // If |cookie_store| is NULL, |channel_id_service| must be NULL too.
+ DCHECK(cookie_store || !channel_id_service);
+ cookie_store_ = std::move(cookie_store);
channel_id_service_ = std::move(channel_id_service);
}
@@ -264,6 +272,13 @@ void URLRequestContextBuilder::SetFileTaskRunner(
file_task_runner_ = task_runner;
}
+void URLRequestContextBuilder::SetProtocolHandler(
+ const std::string& scheme,
+ scoped_ptr<URLRequestJobFactory::ProtocolHandler> protocol_handler) {
+ DCHECK(protocol_handler);
+ protocol_handlers_[scheme] = std::move(protocol_handler);
+}
+
void URLRequestContextBuilder::SetHttpAuthHandlerFactory(
scoped_ptr<HttpAuthHandlerFactory> factory) {
http_auth_handler_factory_ = std::move(factory);
@@ -325,15 +340,18 @@ scoped_ptr<URLRequestContext> URLRequestContextBuilder::Build() {
storage->set_http_auth_handler_factory(std::move(http_auth_handler_factory_));
- if (cookie_store_) {
- storage->set_cookie_store(cookie_store_.get());
+ if (cookie_store_set_by_client_) {
+ storage->set_cookie_store(std::move(cookie_store_));
storage->set_channel_id_service(std::move(channel_id_service_));
} else {
- storage->set_cookie_store(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieStore> cookie_store(new CookieMonster(nullptr, nullptr));
// TODO(mmenke): This always creates a file thread, even when it ends up
// not being used. Consider lazily creating the thread.
- storage->set_channel_id_service(make_scoped_ptr(new ChannelIDService(
- new DefaultChannelIDStore(NULL), context->GetFileTaskRunner())));
+ scoped_ptr<ChannelIDService> channel_id_service(new ChannelIDService(
+ new DefaultChannelIDStore(NULL), context->GetFileTaskRunner()));
+ cookie_store->SetChannelIDServiceID(channel_id_service->GetUniqueID());
+ storage->set_cookie_store(std::move(cookie_store));
+ storage->set_channel_id_service(std::move(channel_id_service));
}
if (sdch_enabled_) {
@@ -385,11 +403,15 @@ scoped_ptr<URLRequestContext> URLRequestContextBuilder::Build() {
http_network_session_params_.testing_fixed_http_port;
network_session_params.testing_fixed_https_port =
http_network_session_params_.testing_fixed_https_port;
- network_session_params.use_alternative_services =
- http_network_session_params_.use_alternative_services;
- network_session_params.trusted_spdy_proxy =
- http_network_session_params_.trusted_spdy_proxy;
- network_session_params.next_protos = http_network_session_params_.next_protos;
+ network_session_params.enable_spdy31 =
+ http_network_session_params_.enable_spdy31;
+ network_session_params.enable_http2 =
+ http_network_session_params_.enable_http2;
+ network_session_params.parse_alternative_services =
+ http_network_session_params_.parse_alternative_services;
+ network_session_params.enable_alternative_service_with_different_host =
+ http_network_session_params_
+ .enable_alternative_service_with_different_host;
network_session_params.enable_quic = http_network_session_params_.enable_quic;
network_session_params.quic_max_server_configs_stored_in_properties =
http_network_session_params_.quic_max_server_configs_stored_in_properties;
@@ -405,6 +427,22 @@ scoped_ptr<URLRequestContext> URLRequestContextBuilder::Build() {
http_network_session_params_.quic_connection_options;
network_session_params.quic_host_whitelist =
http_network_session_params_.quic_host_whitelist;
+ network_session_params.quic_close_sessions_on_ip_change =
+ http_network_session_params_.quic_close_sessions_on_ip_change;
+ network_session_params.quic_migrate_sessions_on_network_change =
+ http_network_session_params_.quic_migrate_sessions_on_network_change;
+ network_session_params.quic_user_agent_id =
+ http_network_session_params_.quic_user_agent_id;
+ network_session_params.quic_prefer_aes =
+ http_network_session_params_.quic_prefer_aes;
+ network_session_params.quic_migrate_sessions_early =
+ http_network_session_params_.quic_migrate_sessions_early;
+ network_session_params.quic_disable_bidirectional_streams =
+ http_network_session_params_.quic_disable_bidirectional_streams;
+ if (proxy_delegate_) {
+ network_session_params.proxy_delegate = proxy_delegate_.get();
+ storage->set_proxy_delegate(std::move(proxy_delegate_));
+ }
storage->set_http_network_session(
make_scoped_ptr(new HttpNetworkSession(network_session_params)));
@@ -434,6 +472,14 @@ scoped_ptr<URLRequestContext> URLRequestContextBuilder::Build() {
storage->set_http_transaction_factory(std::move(http_transaction_factory));
URLRequestJobFactoryImpl* job_factory = new URLRequestJobFactoryImpl;
+ // Adds caller-provided protocol handlers first so that these handlers are
+ // used over data/file/ftp handlers below.
+ for (auto& scheme_handler : protocol_handlers_) {
+ job_factory->SetProtocolHandler(scheme_handler.first,
+ std::move(scheme_handler.second));
+ }
+ protocol_handlers_.clear();
+
if (data_enabled_)
job_factory->SetProtocolHandler("data",
make_scoped_ptr(new DataProtocolHandler));
diff --git a/chromium/net/url_request/url_request_context_builder.h b/chromium/net/url_request/url_request_context_builder.h
index b955c96c797..c570d609158 100644
--- a/chromium/net/url_request/url_request_context_builder.h
+++ b/chromium/net/url_request/url_request_context_builder.h
@@ -15,9 +15,11 @@
#define NET_URL_REQUEST_URL_REQUEST_CONTEXT_BUILDER_H_
#include <stdint.h>
+#include <map>
#include <string>
#include <unordered_map>
#include <utility>
+#include <vector>
#include "base/files/file_path.h"
#include "base/macros.h"
@@ -26,12 +28,14 @@
#include "build/build_config.h"
#include "net/base/net_export.h"
#include "net/base/network_delegate.h"
+#include "net/base/proxy_delegate.h"
#include "net/dns/host_resolver.h"
#include "net/http/http_network_session.h"
#include "net/proxy/proxy_config_service.h"
#include "net/proxy/proxy_service.h"
#include "net/quic/quic_protocol.h"
#include "net/socket/next_proto.h"
+#include "net/url_request/url_request_job_factory.h"
namespace base {
class SingleThreadTaskRunner;
@@ -84,17 +88,24 @@ class NET_EXPORT URLRequestContextBuilder {
HostMappingRules* host_mapping_rules;
uint16_t testing_fixed_http_port;
uint16_t testing_fixed_https_port;
- NextProtoVector next_protos;
- std::string trusted_spdy_proxy;
- bool use_alternative_services;
+ bool enable_spdy31;
+ bool enable_http2;
+ bool parse_alternative_services;
+ bool enable_alternative_service_with_different_host;
bool enable_quic;
+ std::string quic_user_agent_id;
int quic_max_server_configs_stored_in_properties;
bool quic_delay_tcp_race;
int quic_max_number_of_lossy_connections;
std::unordered_set<std::string> quic_host_whitelist;
+ bool quic_prefer_aes;
float quic_packet_loss_threshold;
int quic_idle_connection_timeout_seconds;
QuicTagVector quic_connection_options;
+ bool quic_close_sessions_on_ip_change;
+ bool quic_migrate_sessions_on_network_change;
+ bool quic_migrate_sessions_early;
+ bool quic_disable_bidirectional_streams;
};
URLRequestContextBuilder();
@@ -147,6 +158,12 @@ class NET_EXPORT URLRequestContextBuilder {
}
#endif
+ // Sets a valid ProtocolHandler for a scheme.
+ // A ProtocolHandler already exists for |scheme| will be overwritten.
+ void SetProtocolHandler(
+ const std::string& scheme,
+ scoped_ptr<URLRequestJobFactory::ProtocolHandler> protocol_handler);
+
// Unlike the other setters, the builder does not take ownership of the
// NetLog.
// TODO(mmenke): Probably makes sense to get rid of this, and have consumers
@@ -165,6 +182,12 @@ class NET_EXPORT URLRequestContextBuilder {
network_delegate_ = std::move(delegate);
}
+ // Temporarily stores a ProxyDelegate. Ownership is transferred to
+ // UrlRequestContextStorage during Build.
+ void set_proxy_delegate(scoped_ptr<ProxyDelegate> delegate) {
+ proxy_delegate_ = std::move(delegate);
+ }
+
// Sets a specific HttpAuthHandlerFactory to be used by the URLRequestContext
// rather than the default |HttpAuthHandlerRegistryFactory|. The builder
// takes ownership of the factory and will eventually transfer it to the new
@@ -188,7 +211,6 @@ class NET_EXPORT URLRequestContextBuilder {
transport_security_persister_path_ = transport_security_persister_path;
}
- // Adjust |http_network_session_params_.next_protos| to enable SPDY and QUIC.
void SetSpdyAndQuicEnabled(bool spdy_enabled,
bool quic_enabled);
@@ -198,6 +220,10 @@ class NET_EXPORT URLRequestContextBuilder {
quic_connection_options;
}
+ void set_quic_user_agent_id(const std::string& quic_user_agent_id) {
+ http_network_session_params_.quic_user_agent_id = quic_user_agent_id;
+ }
+
void set_quic_max_server_configs_stored_in_properties(
int quic_max_server_configs_stored_in_properties) {
http_network_session_params_.quic_max_server_configs_stored_in_properties =
@@ -230,6 +256,33 @@ class NET_EXPORT URLRequestContextBuilder {
http_network_session_params_.quic_host_whitelist = quic_host_whitelist;
}
+ void set_quic_close_sessions_on_ip_change(
+ bool quic_close_sessions_on_ip_change) {
+ http_network_session_params_.quic_close_sessions_on_ip_change =
+ quic_close_sessions_on_ip_change;
+ }
+
+ void set_quic_migrate_sessions_on_network_change(
+ bool quic_migrate_sessions_on_network_change) {
+ http_network_session_params_.quic_migrate_sessions_on_network_change =
+ quic_migrate_sessions_on_network_change;
+ }
+
+ void set_quic_prefer_aes(bool quic_prefer_aes) {
+ http_network_session_params_.quic_prefer_aes = quic_prefer_aes;
+ }
+
+ void set_quic_migrate_sessions_early(bool quic_migrate_sessions_early) {
+ http_network_session_params_.quic_migrate_sessions_early =
+ quic_migrate_sessions_early;
+ }
+
+ void set_quic_disable_bidirectional_streams(
+ bool quic_disable_bidirectional_streams) {
+ http_network_session_params_.quic_disable_bidirectional_streams =
+ quic_disable_bidirectional_streams;
+ }
+
void set_throttling_enabled(bool throttling_enabled) {
throttling_enabled_ = throttling_enabled;
}
@@ -244,14 +297,16 @@ class NET_EXPORT URLRequestContextBuilder {
std::vector<scoped_ptr<URLRequestInterceptor>> url_request_interceptors);
// Override the default in-memory cookie store and channel id service.
- // |cookie_store| must not be NULL. |channel_id_service| may be NULL to
- // disable channel id for this context.
+ // If both |cookie_store| and |channel_id_service| are NULL, CookieStore and
+ // ChannelIDService will be disabled for this context.
+ // If |cookie_store| is not NULL and |channel_id_service| is NULL,
+ // only ChannelIdService is disabled for this context.
// Note that a persistent cookie store should not be used with an in-memory
// channel id service, and one cookie store should not be shared between
// multiple channel-id stores (or used both with and without a channel id
// store).
void SetCookieAndChannelIdStores(
- const scoped_refptr<CookieStore>& cookie_store,
+ scoped_ptr<CookieStore> cookie_store,
scoped_ptr<ChannelIDService> channel_id_service);
// Sets the task runner used to perform file operations. If not set, one will
@@ -290,6 +345,7 @@ class NET_EXPORT URLRequestContextBuilder {
bool throttling_enabled_;
bool backoff_enabled_;
bool sdch_enabled_;
+ bool cookie_store_set_by_client_;
scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
HttpCacheParams http_cache_params_;
@@ -301,12 +357,17 @@ class NET_EXPORT URLRequestContextBuilder {
scoped_ptr<ProxyConfigService> proxy_config_service_;
scoped_ptr<ProxyService> proxy_service_;
scoped_ptr<NetworkDelegate> network_delegate_;
- scoped_refptr<CookieStore> cookie_store_;
+ scoped_ptr<ProxyDelegate> proxy_delegate_;
+ scoped_ptr<CookieStore> cookie_store_;
+#if !defined(DISABLE_FTP_SUPPORT)
scoped_ptr<FtpTransactionFactory> ftp_transaction_factory_;
+#endif
scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
scoped_ptr<CertVerifier> cert_verifier_;
std::vector<scoped_ptr<URLRequestInterceptor>> url_request_interceptors_;
scoped_ptr<HttpServerProperties> http_server_properties_;
+ std::map<std::string, scoped_ptr<URLRequestJobFactory::ProtocolHandler>>
+ protocol_handlers_;
DISALLOW_COPY_AND_ASSIGN(URLRequestContextBuilder);
};
diff --git a/chromium/net/url_request/url_request_context_builder_unittest.cc b/chromium/net/url_request/url_request_context_builder_unittest.cc
index e4f04f5be3e..a2706d4ca4a 100644
--- a/chromium/net/url_request/url_request_context_builder_unittest.cc
+++ b/chromium/net/url_request/url_request_context_builder_unittest.cc
@@ -10,6 +10,7 @@
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_handler.h"
#include "net/http/http_auth_handler_factory.h"
+#include "net/ssl/ssl_info.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
@@ -33,6 +34,7 @@ class MockHttpAuthHandlerFactory : public HttpAuthHandlerFactory {
int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
HttpAuth::Target target,
+ const SSLInfo& ssl_info,
const GURL& origin,
CreateReason reason,
int nonce_count,
@@ -98,11 +100,13 @@ TEST_F(URLRequestContextBuilderTest, DefaultHttpAuthHandlerFactory) {
GURL gurl("www.google.com");
scoped_ptr<HttpAuthHandler> handler;
scoped_ptr<URLRequestContext> context(builder_.Build());
+ SSLInfo null_ssl_info;
// Verify that the default basic handler is present
EXPECT_EQ(OK,
context->http_auth_handler_factory()->CreateAuthHandlerFromString(
- "basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
+ "basic", HttpAuth::AUTH_SERVER, null_ssl_info, gurl,
+ BoundNetLog(), &handler));
}
TEST_F(URLRequestContextBuilderTest, CustomHttpAuthHandlerFactory) {
@@ -112,24 +116,24 @@ TEST_F(URLRequestContextBuilderTest, CustomHttpAuthHandlerFactory) {
builder_.SetHttpAuthHandlerFactory(make_scoped_ptr(
new MockHttpAuthHandlerFactory("ExtraScheme", kBasicReturnCode)));
scoped_ptr<URLRequestContext> context(builder_.Build());
+ SSLInfo null_ssl_info;
// Verify that a handler is returned for a custom scheme.
EXPECT_EQ(kBasicReturnCode,
context->http_auth_handler_factory()->CreateAuthHandlerFromString(
- "ExtraScheme",
- HttpAuth::AUTH_SERVER,
- gurl,
- BoundNetLog(),
- &handler));
+ "ExtraScheme", HttpAuth::AUTH_SERVER, null_ssl_info, gurl,
+ BoundNetLog(), &handler));
// Verify that the default basic handler isn't present
EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME,
context->http_auth_handler_factory()->CreateAuthHandlerFromString(
- "basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
+ "basic", HttpAuth::AUTH_SERVER, null_ssl_info, gurl,
+ BoundNetLog(), &handler));
// Verify that a handler isn't returned for a bogus scheme.
EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME,
context->http_auth_handler_factory()->CreateAuthHandlerFromString(
- "Bogus", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
+ "Bogus", HttpAuth::AUTH_SERVER, null_ssl_info, gurl,
+ BoundNetLog(), &handler));
}
} // namespace
diff --git a/chromium/net/url_request/url_request_context_getter.cc b/chromium/net/url_request/url_request_context_getter.cc
index 34d77809be5..18086175214 100644
--- a/chromium/net/url_request/url_request_context_getter.cc
+++ b/chromium/net/url_request/url_request_context_getter.cc
@@ -4,6 +4,7 @@
#include "net/url_request/url_request_context_getter.h"
+#include "base/debug/leak_annotations.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "net/url_request/url_request_context.h"
@@ -41,6 +42,8 @@ void URLRequestContextGetter::OnDestruct() const {
// aid in debugging.
DLOG(WARNING) << "URLRequestContextGetter leaking due to no owning"
<< " thread.";
+ // Let LSan know we know this is a leak. https://crbug.com/594130
+ ANNOTATE_LEAKING_OBJECT_PTR(this);
}
}
}
diff --git a/chromium/net/url_request/url_request_context_getter.h b/chromium/net/url_request/url_request_context_getter.h
index 1616f7c92f1..3e6cd084766 100644
--- a/chromium/net/url_request/url_request_context_getter.h
+++ b/chromium/net/url_request/url_request_context_getter.h
@@ -29,7 +29,8 @@ class NET_EXPORT URLRequestContextGetter
public:
// Returns the URLRequestContextGetter's URLRequestContext. Must only be
// called on the network task runner. Once NotifyContextShuttingDown() is
- // invoked, must always return nullptr.
+ // invoked, must always return nullptr. Does not transfer ownership of
+ // the URLRequestContext.
virtual URLRequestContext* GetURLRequestContext() = 0;
// Returns a SingleThreadTaskRunner corresponding to the thread on
diff --git a/chromium/net/url_request/url_request_context_storage.cc b/chromium/net/url_request/url_request_context_storage.cc
index 399bc47caab..ed3f9052790 100644
--- a/chromium/net/url_request/url_request_context_storage.cc
+++ b/chromium/net/url_request/url_request_context_storage.cc
@@ -8,11 +8,11 @@
#include "base/logging.h"
#include "net/base/network_delegate.h"
+#include "net/base/proxy_delegate.h"
#include "net/base/sdch_manager.h"
#include "net/cert/cert_verifier.h"
#include "net/cookies/cookie_store.h"
#include "net/dns/host_resolver.h"
-#include "net/ftp/ftp_transaction_factory.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_server_properties.h"
#include "net/http/http_transaction_factory.h"
@@ -81,15 +81,21 @@ void URLRequestContextStorage::set_network_delegate(
network_delegate_ = std::move(network_delegate);
}
+void URLRequestContextStorage::set_proxy_delegate(
+ scoped_ptr<ProxyDelegate> proxy_delegate) {
+ proxy_delegate_ = std::move(proxy_delegate);
+}
+
void URLRequestContextStorage::set_http_server_properties(
scoped_ptr<HttpServerProperties> http_server_properties) {
http_server_properties_ = std::move(http_server_properties);
context_->set_http_server_properties(http_server_properties_->GetWeakPtr());
}
-void URLRequestContextStorage::set_cookie_store(CookieStore* cookie_store) {
- context_->set_cookie_store(cookie_store);
- cookie_store_ = cookie_store;
+void URLRequestContextStorage::set_cookie_store(
+ scoped_ptr<CookieStore> cookie_store) {
+ context_->set_cookie_store(cookie_store.get());
+ cookie_store_ = std::move(cookie_store);
}
void URLRequestContextStorage::set_transport_security_state(
diff --git a/chromium/net/url_request/url_request_context_storage.h b/chromium/net/url_request/url_request_context_storage.h
index f05e186001f..b888fb0c3ce 100644
--- a/chromium/net/url_request/url_request_context_storage.h
+++ b/chromium/net/url_request/url_request_context_storage.h
@@ -24,6 +24,7 @@ class HttpTransactionFactory;
class HttpUserAgentSettings;
class NetLog;
class NetworkDelegate;
+class ProxyDelegate;
class ProxyService;
class SdchManager;
class SSLConfigService;
@@ -55,9 +56,10 @@ class NET_EXPORT URLRequestContextStorage {
void set_proxy_service(scoped_ptr<ProxyService> proxy_service);
void set_ssl_config_service(SSLConfigService* ssl_config_service);
void set_network_delegate(scoped_ptr<NetworkDelegate> network_delegate);
+ void set_proxy_delegate(scoped_ptr<ProxyDelegate> proxy_delegate);
void set_http_server_properties(
scoped_ptr<HttpServerProperties> http_server_properties);
- void set_cookie_store(CookieStore* cookie_store);
+ void set_cookie_store(scoped_ptr<CookieStore> cookie_store);
void set_transport_security_state(
scoped_ptr<TransportSecurityState> transport_security_state);
void set_http_network_session(
@@ -96,9 +98,10 @@ class NET_EXPORT URLRequestContextStorage {
// TODO(willchan): Remove refcounting on these members.
scoped_refptr<SSLConfigService> ssl_config_service_;
scoped_ptr<NetworkDelegate> network_delegate_;
+ scoped_ptr<ProxyDelegate> proxy_delegate_;
scoped_ptr<HttpServerProperties> http_server_properties_;
scoped_ptr<HttpUserAgentSettings> http_user_agent_settings_;
- scoped_refptr<CookieStore> cookie_store_;
+ scoped_ptr<CookieStore> cookie_store_;
scoped_ptr<TransportSecurityState> transport_security_state_;
// Not actually pointed at by the URLRequestContext, but may be used (but not
diff --git a/chromium/net/url_request/url_request_file_dir_job.cc b/chromium/net/url_request/url_request_file_dir_job.cc
index b331e442765..ebb9ddf5e9e 100644
--- a/chromium/net/url_request/url_request_file_dir_job.cc
+++ b/chromium/net/url_request/url_request_file_dir_job.cc
@@ -26,19 +26,29 @@ namespace net {
URLRequestFileDirJob::URLRequestFileDirJob(URLRequest* request,
NetworkDelegate* network_delegate,
const base::FilePath& dir_path)
+ : URLRequestFileDirJob(request,
+ network_delegate,
+ dir_path,
+ base::WorkerPool::GetTaskRunner(true)) {}
+
+URLRequestFileDirJob::URLRequestFileDirJob(
+ URLRequest* request,
+ NetworkDelegate* network_delegate,
+ const base::FilePath& dir_path,
+ const scoped_refptr<base::TaskRunner>& dir_task_runner)
: URLRequestJob(request, network_delegate),
lister_(dir_path, this),
dir_path_(dir_path),
+ dir_task_runner_(dir_task_runner),
canceled_(false),
list_complete_(false),
wrote_header_(false),
read_pending_(false),
read_buffer_length_(0),
- weak_factory_(this) {
-}
+ weak_factory_(this) {}
void URLRequestFileDirJob::StartAsync() {
- lister_.Start();
+ lister_.Start(dir_task_runner_.get());
NotifyHeadersComplete();
}
@@ -66,18 +76,16 @@ void URLRequestFileDirJob::Kill() {
}
int URLRequestFileDirJob::ReadRawData(IOBuffer* buf, int buf_size) {
- if (is_done())
- return 0;
-
- int bytes_read = 0;
- if (FillReadBuffer(buf->data(), buf_size, &bytes_read))
- return bytes_read;
+ int result = ReadBuffer(buf->data(), buf_size);
+ if (result == ERR_IO_PENDING) {
+ // We are waiting for more data
+ read_pending_ = true;
+ read_buffer_ = buf;
+ read_buffer_length_ = buf_size;
+ return ERR_IO_PENDING;
+ }
- // We are waiting for more data
- read_pending_ = true;
- read_buffer_ = buf;
- read_buffer_length_ = buf_size;
- return ERR_IO_PENDING;
+ return result;
}
bool URLRequestFileDirJob::GetMimeType(std::string* mime_type) const {
@@ -132,27 +140,26 @@ void URLRequestFileDirJob::OnListFile(
void URLRequestFileDirJob::OnListDone(int error) {
DCHECK(!canceled_);
DCHECK_LE(error, OK);
- if (error == OK)
- list_complete_ = true;
- CompleteRead(static_cast<Error>(error));
+
+ list_complete_ = true;
+ list_complete_result_ = static_cast<Error>(error);
+ CompleteRead(list_complete_result_);
}
URLRequestFileDirJob::~URLRequestFileDirJob() {}
-void URLRequestFileDirJob::CompleteRead(Error status) {
- DCHECK_LE(status, OK);
- DCHECK_NE(status, ERR_IO_PENDING);
+void URLRequestFileDirJob::CompleteRead(Error error) {
+ DCHECK_LE(error, OK);
+ DCHECK_NE(error, ERR_IO_PENDING);
// Do nothing if there is no read pending.
if (!read_pending_)
return;
- int result = status;
- if (status == OK) {
- int filled_bytes = 0;
- if (FillReadBuffer(read_buffer_->data(), read_buffer_length_,
- &filled_bytes)) {
- result = filled_bytes;
+ int result = error;
+ if (error == OK) {
+ result = ReadBuffer(read_buffer_->data(), read_buffer_length_);
+ if (result >= 0) {
// We completed the read, so reset the read buffer.
read_buffer_ = NULL;
read_buffer_length_ = 0;
@@ -167,23 +174,17 @@ void URLRequestFileDirJob::CompleteRead(Error status) {
ReadRawDataComplete(result);
}
-bool URLRequestFileDirJob::FillReadBuffer(char* buf, int buf_size,
- int* bytes_read) {
- DCHECK(bytes_read);
-
- *bytes_read = 0;
-
+int URLRequestFileDirJob::ReadBuffer(char* buf, int buf_size) {
int count = std::min(buf_size, static_cast<int>(data_.size()));
if (count) {
memcpy(buf, &data_[0], count);
data_.erase(0, count);
- *bytes_read = count;
- return true;
+ return count;
} else if (list_complete_) {
// EOF
- return true;
+ return list_complete_result_;
}
- return false;
+ return ERR_IO_PENDING;
}
} // namespace net
diff --git a/chromium/net/url_request/url_request_file_dir_job.h b/chromium/net/url_request/url_request_file_dir_job.h
index a5db178b009..719cdf0e0ae 100644
--- a/chromium/net/url_request/url_request_file_dir_job.h
+++ b/chromium/net/url_request/url_request_file_dir_job.h
@@ -7,27 +7,32 @@
#include <string>
+#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/threading/worker_pool.h"
#include "net/base/directory_lister.h"
#include "net/base/net_errors.h"
+#include "net/base/net_export.h"
#include "net/url_request/url_request_job.h"
namespace net {
-class URLRequestFileDirJob
- : public URLRequestJob,
- public DirectoryLister::DirectoryListerDelegate {
+class NET_EXPORT_PRIVATE URLRequestFileDirJob
+ : public URLRequestJob,
+ public NON_EXPORTED_BASE(DirectoryLister::DirectoryListerDelegate) {
public:
URLRequestFileDirJob(URLRequest* request,
NetworkDelegate* network_delegate,
const base::FilePath& dir_path);
- bool list_complete() const { return list_complete_; }
-
- virtual void StartAsync();
+ URLRequestFileDirJob(URLRequest* request,
+ NetworkDelegate* network_delegate,
+ const base::FilePath& dir_path,
+ const scoped_refptr<base::TaskRunner>& dir_task_runner);
+ void StartAsync();
// Overridden from URLRequestJob:
void Start() override;
void Kill() override;
@@ -39,9 +44,10 @@ class URLRequestFileDirJob
void OnListFile(const DirectoryLister::DirectoryListerData& data) override;
void OnListDone(int error) override;
- private:
+ protected:
~URLRequestFileDirJob() override;
+ private:
void CloseLister();
// When we have data and a read has been pending, this function
@@ -49,17 +55,22 @@ class URLRequestFileDirJob
// appropriately.
void CompleteRead(Error error);
- // Fills a buffer with the output.
- bool FillReadBuffer(char* buf, int buf_size, int* bytes_read);
+ int ReadBuffer(char* buf, int buf_size);
DirectoryLister lister_;
base::FilePath dir_path_;
+
+ const scoped_refptr<base::TaskRunner> dir_task_runner_;
+
std::string data_;
bool canceled_;
// Indicates whether we have the complete list of the dir
bool list_complete_;
+ // Indicates the status of the list
+ Error list_complete_result_;
+
// Indicates whether we have written the HTML header
bool wrote_header_;
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
new file mode 100644
index 00000000000..5701b3e37de
--- /dev/null
+++ b/chromium/net/url_request/url_request_file_dir_job_unittest.cc
@@ -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.
+
+#include "net/url_request/url_request_file_dir_job.h"
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "net/base/filename_util.h"
+#include "net/base/io_buffer.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"
+
+namespace net {
+
+namespace {
+
+const int kBufferSize = 4096;
+
+class TestJobFactory : public URLRequestJobFactory {
+ public:
+ explicit TestJobFactory(const base::FilePath& path) : path_(path) {}
+ ~TestJobFactory() override {}
+
+ URLRequestJob* MaybeCreateJobWithProtocolHandler(
+ const std::string& scheme,
+ URLRequest* request,
+ NetworkDelegate* network_delegate) const override {
+ URLRequestJob* job = new URLRequestFileDirJob(
+ request, network_delegate, path_, base::ThreadTaskRunnerHandle::Get());
+
+ return job;
+ }
+
+ URLRequestJob* MaybeInterceptRedirect(URLRequest* request,
+ NetworkDelegate* network_delegate,
+ const GURL& location) const override {
+ return nullptr;
+ }
+
+ URLRequestJob* MaybeInterceptResponse(
+ URLRequest* request,
+ NetworkDelegate* network_delegate) const override {
+ return nullptr;
+ }
+
+ bool IsHandledProtocol(const std::string& scheme) const override {
+ return scheme == "file";
+ }
+
+ bool IsHandledURL(const GURL& url) const override {
+ return IsHandledProtocol(url.scheme());
+ }
+
+ bool IsSafeRedirectTarget(const GURL& location) const override {
+ return false;
+ }
+
+ private:
+ const base::FilePath path_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestJobFactory);
+};
+
+class TestDirectoryURLRequestDelegate : public TestDelegate {
+ public:
+ TestDirectoryURLRequestDelegate() {}
+
+ ~TestDirectoryURLRequestDelegate() override {}
+
+ void OnResponseStarted(URLRequest* request) override {
+ got_response_started_ = true;
+ }
+
+ bool got_response_started() const { return got_response_started_; }
+
+ private:
+ bool got_response_started_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(TestDirectoryURLRequestDelegate);
+};
+
+class URLRequestFileDirTest : public testing::Test {
+ public:
+ URLRequestFileDirTest() : buffer_(new IOBuffer(kBufferSize)) {}
+
+ protected:
+ TestURLRequestContext context_;
+ TestDirectoryURLRequestDelegate delegate_;
+ scoped_refptr<IOBuffer> buffer_;
+};
+
+TEST_F(URLRequestFileDirTest, ListCompletionOnNoPending) {
+ base::ScopedTempDir directory;
+ // It is necessary to pass an existing directory to UrlRequest object,
+ // but it will be deleted for testing purpose after request is started.
+ ASSERT_TRUE(directory.CreateUniqueTempDir());
+ TestJobFactory factory(directory.path());
+ context_.set_job_factory(&factory);
+ scoped_ptr<URLRequest> request(context_.CreateRequest(
+ FilePathToFileURL(
+ directory.path().AppendASCII("this_path_does_not_exist")),
+ DEFAULT_PRIORITY, &delegate_));
+
+ request->Start();
+ ASSERT_TRUE(directory.Delete());
+
+ // Since the DirectoryLister is running on the network thread, this
+ // will spin the message loop until the read error is returned to the
+ // URLRequestFileDirJob.
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(delegate_.got_response_started());
+
+ int bytes_read = 0;
+ EXPECT_FALSE(request->Read(buffer_.get(), kBufferSize, &bytes_read));
+
+ // The URLRequestFileDirJobShould return the cached read error synchronously.
+ // If it's not returned synchronously, the code path this is intended to test
+ // was not executed.
+ EXPECT_EQ(ERR_FILE_NOT_FOUND, request->status().ToNetError());
+}
+
+// Test the case where reading the response completes synchronously.
+TEST_F(URLRequestFileDirTest, DirectoryWithASingleFileSync) {
+ base::ScopedTempDir directory;
+ ASSERT_TRUE(directory.CreateUniqueTempDir());
+ base::FilePath path;
+ base::CreateTemporaryFileInDir(directory.path(), &path);
+
+ TestJobFactory factory(directory.path());
+ context_.set_job_factory(&factory);
+
+ scoped_ptr<URLRequest> request(context_.CreateRequest(
+ FilePathToFileURL(path), DEFAULT_PRIORITY, &delegate_));
+ request->Start();
+ EXPECT_TRUE(request->is_pending());
+
+ // Since the DirectoryLister is running on the network thread, this will spin
+ // the message loop until the URLRequetsFileDirJob has received the
+ // entire directory listing and cached it.
+ base::RunLoop().RunUntilIdle();
+
+ int bytes_read = 0;
+ // This will complete synchronously, since the URLRequetsFileDirJob had
+ // directory listing cached in memory.
+ EXPECT_TRUE(request->Read(buffer_.get(), kBufferSize, &bytes_read));
+
+ EXPECT_EQ(URLRequestStatus::SUCCESS, request->status().status());
+
+ ASSERT_GT(bytes_read, 0);
+ ASSERT_LE(bytes_read, kBufferSize);
+ std::string data(buffer_->data(), bytes_read);
+ EXPECT_TRUE(data.find(directory.path().BaseName().MaybeAsASCII()) !=
+ std::string::npos);
+ EXPECT_TRUE(data.find(path.BaseName().MaybeAsASCII()) != std::string::npos);
+}
+
+// Test the case where reading the response completes asynchronously.
+TEST_F(URLRequestFileDirTest, DirectoryWithASingleFileAsync) {
+ base::ScopedTempDir directory;
+ ASSERT_TRUE(directory.CreateUniqueTempDir());
+ base::FilePath path;
+ base::CreateTemporaryFileInDir(directory.path(), &path);
+
+ TestJobFactory factory(directory.path());
+ context_.set_job_factory(&factory);
+
+ TestDelegate delegate;
+ scoped_ptr<URLRequest> request(context_.CreateRequest(
+ FilePathToFileURL(path), DEFAULT_PRIORITY, &delegate));
+ request->Start();
+ EXPECT_TRUE(request->is_pending());
+
+ base::RunLoop().Run();
+
+ ASSERT_GT(delegate.bytes_received(), 0);
+ ASSERT_LE(delegate.bytes_received(), kBufferSize);
+ EXPECT_TRUE(delegate.data_received().find(
+ directory.path().BaseName().MaybeAsASCII()) !=
+ std::string::npos);
+ EXPECT_TRUE(delegate.data_received().find(path.BaseName().MaybeAsASCII()) !=
+ std::string::npos);
+}
+
+TEST_F(URLRequestFileDirTest, DirectoryWithAFileAndSubdirectory) {
+ base::ScopedTempDir directory;
+ ASSERT_TRUE(directory.CreateUniqueTempDir());
+
+ base::FilePath sub_dir;
+ CreateTemporaryDirInDir(directory.path(),
+ FILE_PATH_LITERAL("CreateNewSubDirectoryInDirectory"),
+ &sub_dir);
+
+ base::FilePath path;
+ base::CreateTemporaryFileInDir(directory.path(), &path);
+
+ TestJobFactory factory(directory.path());
+ context_.set_job_factory(&factory);
+
+ TestDelegate delegate;
+ scoped_ptr<URLRequest> request(context_.CreateRequest(
+ FilePathToFileURL(path), DEFAULT_PRIORITY, &delegate));
+ request->Start();
+ EXPECT_TRUE(request->is_pending());
+
+ base::RunLoop().Run();
+
+ ASSERT_GT(delegate.bytes_received(), 0);
+ ASSERT_LE(delegate.bytes_received(), kBufferSize);
+ EXPECT_TRUE(delegate.data_received().find(
+ directory.path().BaseName().MaybeAsASCII()) !=
+ std::string::npos);
+ EXPECT_TRUE(delegate.data_received().find(
+ sub_dir.BaseName().MaybeAsASCII()) != std::string::npos);
+ EXPECT_TRUE(delegate.data_received().find(path.BaseName().MaybeAsASCII()) !=
+ std::string::npos);
+}
+
+TEST_F(URLRequestFileDirTest, EmptyDirectory) {
+ base::ScopedTempDir directory;
+ ASSERT_TRUE(directory.CreateUniqueTempDir());
+
+ TestJobFactory factory(directory.path());
+ context_.set_job_factory(&factory);
+
+ TestDelegate delegate;
+ scoped_ptr<URLRequest> request(context_.CreateRequest(
+ FilePathToFileURL(directory.path()), DEFAULT_PRIORITY, &delegate));
+ request->Start();
+ EXPECT_TRUE(request->is_pending());
+
+ base::RunLoop().Run();
+
+ ASSERT_GT(delegate.bytes_received(), 0);
+ ASSERT_LE(delegate.bytes_received(), kBufferSize);
+ EXPECT_TRUE(delegate.data_received().find(
+ directory.path().BaseName().MaybeAsASCII()) !=
+ std::string::npos);
+}
+
+} // namespace
+
+} // namespace net
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 d8e0691d548..da43aabcb19 100644
--- a/chromium/net/url_request/url_request_file_job_unittest.cc
+++ b/chromium/net/url_request/url_request_file_job_unittest.cc
@@ -13,7 +13,6 @@
#include "base/thread_task_runner_handle.h"
#include "base/threading/sequenced_worker_pool.h"
#include "net/base/filename_util.h"
-#include "net/base/net_util.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/url_request/url_request_filter.h b/chromium/net/url_request/url_request_filter.h
index 7c460489133..d72aa752aae 100644
--- a/chromium/net/url_request/url_request_filter.h
+++ b/chromium/net/url_request/url_request_filter.h
@@ -25,11 +25,11 @@ class URLRequestInterceptor;
// rather than just the scheme. Example usage:
//
// // Intercept "scheme://host/" requests.
-// URLRequestFilter::GetInstance()->AddHostnameInterceptor("scheme", "host",
-// interceptor.Pass());
+// URLRequestFilter::GetInstance()->AddHostnameInterceptor(
+// "scheme", "host", std::move(interceptor));
// // Add special handling for the URL http://foo.com/
-// URLRequestFilter::GetInstance()->AddUrlInterceptor(GURL("http://foo.com/"),
-// interceptor.Pass());
+// URLRequestFilter::GetInstance()->AddUrlInterceptor(
+// GURL("http://foo.com/"), std::move(interceptor));
//
// The URLRequestFilter is implemented as a singleton that is not thread-safe,
// and hence must only be used in test code where the network stack is used
diff --git a/chromium/net/url_request/url_request_ftp_job.cc b/chromium/net/url_request/url_request_ftp_job.cc
index 596363f8535..dc2fc686585 100644
--- a/chromium/net/url_request/url_request_ftp_job.cc
+++ b/chromium/net/url_request/url_request_ftp_job.cc
@@ -13,7 +13,6 @@
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/ftp/ftp_auth_cache.h"
#include "net/ftp/ftp_response_info.h"
#include "net/ftp/ftp_transaction_factory.h"
@@ -102,14 +101,10 @@ void URLRequestFtpJob::Start() {
} else {
DCHECK_EQ(request_->context()->proxy_service(), proxy_service_);
rv = proxy_service_->ResolveProxy(
- request_->url(),
- request_->load_flags(),
- &proxy_info_,
+ request_->url(), "GET", request_->load_flags(), &proxy_info_,
base::Bind(&URLRequestFtpJob::OnResolveProxyComplete,
base::Unretained(this)),
- &pac_request_,
- NULL,
- request_->net_log());
+ &pac_request_, NULL, request_->net_log());
if (rv == ERR_IO_PENDING)
return;
@@ -160,9 +155,6 @@ void URLRequestFtpJob::StartFtpTransaction() {
ftp_request_info_.url = request_->url();
ftp_transaction_ = ftp_transaction_factory_->CreateTransaction();
- // No matter what, we want to report our status as IO pending since we will
- // be notifying our consumer asynchronously via OnStartCompleted.
- SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
int rv;
if (ftp_transaction_) {
rv = ftp_transaction_->Start(
@@ -211,9 +203,6 @@ void URLRequestFtpJob::StartHttpTransaction() {
}
void URLRequestFtpJob::OnStartCompleted(int result) {
- // Clear the IO_PENDING status
- SetStatus(URLRequestStatus());
-
// Note that ftp_transaction_ may be NULL due to a creation failure.
if (ftp_transaction_) {
// FTP obviously doesn't have HTTP Content-Length header. We have to pass
@@ -257,10 +246,6 @@ void URLRequestFtpJob::OnReadCompleted(int result) {
void URLRequestFtpJob::RestartTransactionWithAuth() {
DCHECK(auth_data_.get() && auth_data_->state == AUTH_STATE_HAVE_AUTH);
- // No matter what, we want to report our status as IO pending since we will
- // be notifying our consumer asynchronously via OnStartCompleted.
- SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
-
int rv;
if (proxy_info_.is_direct()) {
rv = ftp_transaction_->RestartWithAuth(
diff --git a/chromium/net/url_request/url_request_http_job.cc b/chromium/net/url_request/url_request_http_job.cc
index c2a70dd3f67..51b69082430 100644
--- a/chromium/net/url_request/url_request_http_job.cc
+++ b/chromium/net/url_request/url_request_http_job.cc
@@ -20,15 +20,17 @@
#include "base/strings/string_util.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/network_delegate.h"
#include "net/base/network_quality_estimator.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/sdch_manager.h"
#include "net/base/sdch_net_log_params.h"
+#include "net/base/url_util.h"
#include "net/cert/cert_status_flags.h"
#include "net/cookies/cookie_store.h"
#include "net/http/http_content_disposition.h"
@@ -41,6 +43,7 @@
#include "net/http/http_transaction_factory.h"
#include "net/http/http_util.h"
#include "net/proxy/proxy_info.h"
+#include "net/ssl/channel_id_service.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_config_service.h"
#include "net/url_request/http_user_agent_settings.h"
@@ -64,6 +67,96 @@ bool IsMethodSafe(const std::string& method) {
method == "TRACE";
}
+// Logs whether the CookieStore used for this request matches the
+// ChannelIDService used when establishing the connection that this request is
+// sent over. This logging is only done for requests to accounts.google.com, and
+// only for requests where Channel ID was sent when establishing the connection.
+void LogChannelIDAndCookieStores(const GURL& url,
+ const net::URLRequestContext* context,
+ const net::SSLInfo& ssl_info) {
+ if (url.host() != "accounts.google.com" || !ssl_info.channel_id_sent)
+ return;
+ // This enum is used for an UMA histogram - don't reuse or renumber entries.
+ enum {
+ // Value 0 was removed (CID_EPHEMERAL_COOKIE_EPHEMERAL)
+ // ChannelIDStore is ephemeral, but CookieStore is persistent.
+ CID_EPHEMERAL_COOKIE_PERSISTENT = 1,
+ // ChannelIDStore is persistent, but CookieStore is ephemeral.
+ CID_PERSISTENT_COOKIE_EPHEMERAL = 2,
+ // Value 3 was removed (CID_PERSISTENT_COOKIE_PERSISTENT)
+ // There is no CookieStore for this request.
+ NO_COOKIE_STORE = 4,
+ // There is no ChannelIDStore for this request. This should never happen,
+ // because we only log if Channel ID was sent.
+ NO_CHANNEL_ID_STORE = 5,
+ // A case where the CookieStore is persistent and the ChannelIDStore is
+ // ephemeral, but it has been identified as not being a problem.
+ KNOWN_MISMATCH = 6,
+ // Both stores are ephemeral, and the ChannelIDService used when
+ // establishing the connection is the same one that the CookieStore was
+ // created to be used with.
+ EPHEMERAL_MATCH = 7,
+ // Both stores are ephemeral, but a different CookieStore should have been
+ // used on this request.
+ EPHEMERAL_MISMATCH = 8,
+ // Both stores are persistent, and the ChannelIDService used when
+ // establishing the connection is the same one that the CookieStore was
+ // created to be used with.
+ PERSISTENT_MATCH = 9,
+ // Both stores are persistent, but a different CookieStore should have been
+ // used on this request.
+ PERSISTENT_MISMATCH = 10,
+ // Both stores are ephemeral, but it was never recorded in the CookieStore
+ // which ChannelIDService it was created for, so it is unknown whether the
+ // stores match.
+ EPHEMERAL_UNKNOWN = 11,
+ // Both stores are persistent, but it was never recorded in the CookieStore
+ // which ChannelIDService it was created for, so it is unknown whether the
+ // stores match.
+ PERSISTENT_UNKNOWN = 12,
+ EPHEMERALITY_MAX
+ } ephemerality;
+ const net::HttpNetworkSession::Params* params =
+ context->GetNetworkSessionParams();
+ net::CookieStore* cookie_store = context->cookie_store();
+ if (params == nullptr || params->channel_id_service == nullptr) {
+ ephemerality = NO_CHANNEL_ID_STORE;
+ } else if (cookie_store == nullptr) {
+ ephemerality = NO_COOKIE_STORE;
+ } else if (params->channel_id_service->GetChannelIDStore()->IsEphemeral()) {
+ if (cookie_store->IsEphemeral()) {
+ if (cookie_store->GetChannelIDServiceID() == -1) {
+ ephemerality = EPHEMERAL_UNKNOWN;
+ } else if (cookie_store->GetChannelIDServiceID() ==
+ params->channel_id_service->GetUniqueID()) {
+ ephemerality = EPHEMERAL_MATCH;
+ } else {
+ NOTREACHED();
+ ephemerality = EPHEMERAL_MISMATCH;
+ }
+ } else if (context->has_known_mismatched_cookie_store()) {
+ ephemerality = KNOWN_MISMATCH;
+ } else {
+ NOTREACHED();
+ ephemerality = CID_EPHEMERAL_COOKIE_PERSISTENT;
+ }
+ } else if (cookie_store->IsEphemeral()) {
+ // TODO(crbug.com/599049): Add NOTREACHED once this case doesn't happen on
+ // iOS anymore.
+ ephemerality = CID_PERSISTENT_COOKIE_EPHEMERAL;
+ } else if (cookie_store->GetChannelIDServiceID() == -1) {
+ ephemerality = PERSISTENT_UNKNOWN;
+ } else if (cookie_store->GetChannelIDServiceID() ==
+ params->channel_id_service->GetUniqueID()) {
+ ephemerality = PERSISTENT_MATCH;
+ } else {
+ NOTREACHED();
+ ephemerality = PERSISTENT_MISMATCH;
+ }
+ UMA_HISTOGRAM_ENUMERATION("Net.TokenBinding.StoreEphemerality", ephemerality,
+ EPHEMERALITY_MAX);
+}
+
} // namespace
namespace net {
@@ -182,8 +275,7 @@ URLRequestHttpJob::URLRequestHttpJob(
const HttpUserAgentSettings* http_user_agent_settings)
: URLRequestJob(request, network_delegate),
priority_(DEFAULT_PRIORITY),
- response_info_(NULL),
- response_cookies_save_index_(0),
+ response_info_(nullptr),
proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
server_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
start_callback_(base::Bind(&URLRequestHttpJob::OnStartCompleted,
@@ -192,7 +284,7 @@ URLRequestHttpJob::URLRequestHttpJob(
base::Bind(&URLRequestHttpJob::NotifyBeforeSendHeadersCallback,
base::Unretained(this))),
read_in_progress_(false),
- throttling_entry_(NULL),
+ throttling_entry_(nullptr),
sdch_test_activated_(false),
sdch_test_control_(false),
is_cached_content_(false),
@@ -262,8 +354,8 @@ void URLRequestHttpJob::Start() {
(request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES) ||
(request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) ||
CanEnablePrivacyMode();
- // Privacy mode could still be disabled in OnCookiesLoaded if we are going
- // to send previously saved cookies.
+ // Privacy mode could still be disabled in SetCookieHeaderAndStart if we are
+ // going to send previously saved cookies.
request_info_.privacy_mode = enable_privacy_mode ?
PRIVACY_MODE_ENABLED : PRIVACY_MODE_DISABLED;
@@ -279,6 +371,8 @@ void URLRequestHttpJob::Start() {
referrer.spec());
}
+ request_info_.token_binding_referrer = request_->token_binding_referrer();
+
request_info_.extra_headers.SetHeaderIfMissing(
HttpRequestHeaders::kUserAgent,
http_user_agent_settings_ ?
@@ -351,6 +445,7 @@ void URLRequestHttpJob::NotifyHeadersComplete() {
// The ordering of these calls is not important.
ProcessStrictTransportSecurityHeader();
ProcessPublicKeyPinsHeader();
+ ProcessExpectCTHeader();
// Handle the server notification of a new SDCH dictionary.
SdchManager* sdch_manager(request()->context()->sdch_manager());
@@ -364,7 +459,7 @@ void URLRequestHttpJob::NotifyHeadersComplete() {
} else {
const std::string name = "Get-Dictionary";
std::string url_text;
- void* iter = NULL;
+ size_t iter = 0;
// TODO(jar): We need to not fetch dictionaries the first time they are
// seen, but rather wait until we can justify their usefulness.
// For now, we will only fetch the first dictionary, which will at least
@@ -376,7 +471,9 @@ void URLRequestHttpJob::NotifyHeadersComplete() {
if (GetResponseHeaders()->EnumerateHeader(&iter, name, &url_text)) {
// Resolve suggested URL relative to request url.
GURL sdch_dictionary_url = request_->url().Resolve(url_text);
- if (sdch_dictionary_url.is_valid()) {
+ // Don't try to download Dictionary for cached responses. It's either
+ // useless or too late.
+ if (sdch_dictionary_url.is_valid() && !is_cached_content_) {
rv = sdch_manager->OnGetDictionary(request_->url(),
sdch_dictionary_url);
if (rv != SDCH_OK) {
@@ -399,7 +496,7 @@ void URLRequestHttpJob::NotifyHeadersComplete() {
// as though the content is corrupted (when we discover it is not SDCH
// encoded).
std::string sdch_response_status;
- void* iter = NULL;
+ size_t iter = 0;
while (GetResponseHeaders()->EnumerateHeader(&iter, "X-Sdch-Encode",
&sdch_response_status)) {
if (sdch_response_status == "0") {
@@ -480,7 +577,6 @@ void URLRequestHttpJob::MaybeStartTransactionInternal(int result) {
std::string source("delegate");
request_->net_log().AddEvent(NetLog::TYPE_CANCELLED,
NetLog::StringCallback("source", &source));
- NotifyCanceled();
NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
}
}
@@ -661,61 +757,60 @@ void URLRequestHttpJob::AddExtraHeaders() {
}
void URLRequestHttpJob::AddCookieHeaderAndStart() {
- // No matter what, we want to report our status as IO pending since we will
- // be notifying our consumer asynchronously via OnStartCompleted.
- SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
-
// If the request was destroyed, then there is no more work to do.
if (!request_)
return;
CookieStore* cookie_store = request_->context()->cookie_store();
if (cookie_store && !(request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES)) {
- cookie_store->GetAllCookiesForURLAsync(
- request_->url(),
- base::Bind(&URLRequestHttpJob::CheckCookiePolicyAndLoad,
+ CookieOptions options;
+ options.set_include_httponly();
+
+ // Set SameSiteCookieMode according to the rules laid out in
+ // https://tools.ietf.org/html/draft-west-first-party-cookies:
+ //
+ // * 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.
+ //
+ // * Include only "lax" same-site cookies if the request's |URL| and
+ // |first_party_for_cookies| have the same registrable domain, _and_ the
+ // request's |method| is "safe" ("GET" or "HEAD").
+ //
+ // Note that this will generally be the case only for cross-site requests
+ // 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,
+ registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
+ if (registry_controlled_domains::SameDomainOrHost(
+ requested_origin, request_->initiator(),
+ registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ } else if (IsMethodSafe(request_->method())) {
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_LAX);
+ }
+ }
+
+ cookie_store->GetCookieListWithOptionsAsync(
+ request_->url(), options,
+ base::Bind(&URLRequestHttpJob::SetCookieHeaderAndStart,
weak_factory_.GetWeakPtr()));
} else {
DoStartTransaction();
}
}
-void URLRequestHttpJob::DoLoadCookies() {
- CookieOptions options;
- options.set_include_httponly();
-
- // TODO(mkwst): If first-party-only cookies aren't enabled, pretend the
- // request is first-party regardless, in order to include all cookies. Drop
- // this check once we decide whether or not we're shipping this feature:
- // https://crbug.com/459154
- url::Origin requested_origin(request_->url());
- if (!network_delegate() ||
- !network_delegate()->AreExperimentalCookieFeaturesEnabled()) {
- options.set_include_first_party_only_cookies();
- } else if (requested_origin.IsSameOriginWith(
- url::Origin(request_->first_party_for_cookies())) &&
- (IsMethodSafe(request_->method()) ||
- requested_origin.IsSameOriginWith(request_->initiator()))) {
- options.set_include_first_party_only_cookies();
- }
-
- request_->context()->cookie_store()->GetCookiesWithOptionsAsync(
- request_->url(), options, base::Bind(&URLRequestHttpJob::OnCookiesLoaded,
- weak_factory_.GetWeakPtr()));
-}
-
-void URLRequestHttpJob::CheckCookiePolicyAndLoad(
- const CookieList& cookie_list) {
- if (CanGetCookies(cookie_list))
- DoLoadCookies();
- else
- DoStartTransaction();
-}
-
-void URLRequestHttpJob::OnCookiesLoaded(const std::string& cookie_line) {
- if (!cookie_line.empty()) {
+void URLRequestHttpJob::SetCookieHeaderAndStart(const CookieList& cookie_list) {
+ if (cookie_list.size() && CanGetCookies(cookie_list)) {
request_info_.extra_headers.SetHeader(
- HttpRequestHeaders::kCookie, cookie_line);
+ HttpRequestHeaders::kCookie, CookieStore::BuildCookieLine(cookie_list));
// Disable privacy mode as we are sending cookies anyway.
request_info_.privacy_mode = PRIVACY_MODE_DISABLED;
}
@@ -743,106 +838,35 @@ void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
return;
}
- DCHECK(transaction_.get());
-
- const HttpResponseInfo* response_info = transaction_->GetResponseInfo();
- DCHECK(response_info);
-
- response_cookies_.clear();
- response_cookies_save_index_ = 0;
-
- FetchResponseCookies(&response_cookies_);
-
- if (!GetResponseHeaders()->GetDateValue(&response_date_))
- response_date_ = base::Time();
-
- // Now, loop over the response cookies, and attempt to persist each.
- SaveNextCookie();
-}
-
-// If the save occurs synchronously, SaveNextCookie will loop and save the next
-// cookie. If the save is deferred, the callback is responsible for continuing
-// to iterate through the cookies.
-// TODO(erikwright): Modify the CookieStore API to indicate via return value
-// whether it completed synchronously or asynchronously.
-// See http://crbug.com/131066.
-void URLRequestHttpJob::SaveNextCookie() {
- // No matter what, we want to report our status as IO pending since we will
- // be notifying our consumer asynchronously via OnStartCompleted.
- SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
+ std::vector<std::string> response_cookies;
+ FetchResponseCookies(&response_cookies);
- // Used to communicate with the callback. See the implementation of
- // OnCookieSaved.
- scoped_refptr<SharedBoolean> callback_pending = new SharedBoolean(false);
- scoped_refptr<SharedBoolean> save_next_cookie_running =
- new SharedBoolean(true);
+ base::Time response_date;
+ if (!GetResponseHeaders()->GetDateValue(&response_date))
+ response_date = base::Time();
if (!(request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) &&
- request_->context()->cookie_store() && response_cookies_.size() > 0) {
+ request_->context()->cookie_store()) {
CookieOptions options;
options.set_include_httponly();
- options.set_server_time(response_date_);
+ options.set_server_time(response_date);
if (network_delegate() &&
network_delegate()->AreStrictSecureCookiesEnabled()) {
options.set_enforce_strict_secure();
}
- CookieStore::SetCookiesCallback callback(base::Bind(
- &URLRequestHttpJob::OnCookieSaved, weak_factory_.GetWeakPtr(),
- save_next_cookie_running, callback_pending));
-
- // Loop through the cookies as long as SetCookieWithOptionsAsync completes
- // synchronously.
- while (!callback_pending->data &&
- response_cookies_save_index_ < response_cookies_.size()) {
- if (CanSetCookie(
- response_cookies_[response_cookies_save_index_], &options)) {
- callback_pending->data = true;
- request_->context()->cookie_store()->SetCookieWithOptionsAsync(
- request_->url(), response_cookies_[response_cookies_save_index_],
- options, callback);
- }
- ++response_cookies_save_index_;
+ // Set all cookies, without waiting for them to be set. Any subsequent read
+ // will see the combined result of all cookie operation.
+ for (const std::string& cookie : response_cookies) {
+ if (!CanSetCookie(cookie, &options))
+ continue;
+ request_->context()->cookie_store()->SetCookieWithOptionsAsync(
+ request_->url(), cookie, options, CookieStore::SetCookiesCallback());
}
}
- save_next_cookie_running->data = false;
-
- if (!callback_pending->data) {
- response_cookies_.clear();
- response_cookies_save_index_ = 0;
- SetStatus(URLRequestStatus()); // Clear the IO_PENDING status
- NotifyHeadersComplete();
- return;
- }
-}
-
-// |save_next_cookie_running| is true when the callback is bound and set to
-// false when SaveNextCookie exits, allowing the callback to determine if the
-// save occurred synchronously or asynchronously.
-// |callback_pending| is false when the callback is invoked and will be set to
-// true by the callback, allowing SaveNextCookie to detect whether the save
-// occurred synchronously.
-// See SaveNextCookie() for more information.
-void URLRequestHttpJob::OnCookieSaved(
- scoped_refptr<SharedBoolean> save_next_cookie_running,
- scoped_refptr<SharedBoolean> callback_pending,
- bool cookie_status) {
- callback_pending->data = false;
-
- // If we were called synchronously, return.
- if (save_next_cookie_running->data) {
- return;
- }
-
- // We were called asynchronously, so trigger the next save.
- // We may have been canceled within OnSetCookie.
- if (GetStatus().is_success()) {
- SaveNextCookie();
- } else {
- NotifyCanceled();
- }
+ NotifyHeadersComplete();
}
void URLRequestHttpJob::FetchResponseCookies(
@@ -850,7 +874,7 @@ void URLRequestHttpJob::FetchResponseCookies(
const std::string name = "Set-Cookie";
std::string value;
- void* iter = NULL;
+ size_t iter = 0;
HttpResponseHeaders* headers = GetResponseHeaders();
while (headers->EnumerateHeader(&iter, name, &value)) {
if (!value.empty())
@@ -903,7 +927,7 @@ void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
// first such header field.
HttpResponseHeaders* headers = GetResponseHeaders();
std::string value;
- if (headers->EnumerateHeader(NULL, "Strict-Transport-Security", &value))
+ if (headers->EnumerateHeader(nullptr, "Strict-Transport-Security", &value))
security_state->AddHSTSHeader(request_info_.url.host(), value);
}
@@ -939,7 +963,31 @@ void URLRequestHttpJob::ProcessPublicKeyPinsHeader() {
}
}
+void URLRequestHttpJob::ProcessExpectCTHeader() {
+ DCHECK(response_info_);
+ TransportSecurityState* security_state =
+ request_->context()->transport_security_state();
+ const SSLInfo& ssl_info = response_info_->ssl_info;
+
+ // Only accept Expect CT headers on HTTPS connections that have no
+ // certificate errors.
+ if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
+ !security_state) {
+ return;
+ }
+
+ // Only process the first Expect-CT header value.
+ HttpResponseHeaders* headers = GetResponseHeaders();
+ std::string value;
+ if (headers->EnumerateHeader(nullptr, "Expect-CT", &value)) {
+ security_state->ProcessExpectCTHeader(
+ value, HostPortPair::FromURL(request_info_.url), ssl_info);
+ }
+}
+
void URLRequestHttpJob::OnStartCompleted(int result) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "URLRequestHttpJob::OnStartCompleted");
RecordTimer();
// If the request was destroyed, then there is no more work to do.
@@ -953,9 +1001,6 @@ void URLRequestHttpJob::OnStartCompleted(int result) {
receive_headers_end_ = base::TimeTicks::Now();
- // Clear the IO_PENDING status
- SetStatus(URLRequestStatus());
-
const URLRequestContext* context = request_->context();
if (result == OK) {
@@ -965,7 +1010,7 @@ void URLRequestHttpJob::OnStartCompleted(int result) {
scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
if (headers) {
- void* iter = NULL;
+ size_t iter = 0;
std::string name;
std::string value;
bool invalid_header_values_in_rfc7230 = false;
@@ -1006,6 +1051,10 @@ void URLRequestHttpJob::OnStartCompleted(int result) {
return;
}
}
+ if (transaction_ && transaction_->GetResponseInfo()) {
+ LogChannelIDAndCookieStores(request_->url(), request_->context(),
+ transaction_->GetResponseInfo()->ssl_info);
+ }
SaveCookiesAndNotifyHeadersComplete(OK);
} else if (IsCertificateError(result)) {
@@ -1047,6 +1096,8 @@ void URLRequestHttpJob::OnHeadersReceivedCallback(int result) {
}
void URLRequestHttpJob::OnReadCompleted(int result) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"),
+ "URLRequestHttpJob::OnReadCompleted");
read_in_progress_ = false;
DCHECK_NE(ERR_IO_PENDING, result);
@@ -1068,7 +1119,6 @@ void URLRequestHttpJob::RestartTransactionWithAuth(
// These will be reset in OnStartCompleted.
response_info_ = NULL;
receive_headers_end_ = base::TimeTicks();
- response_cookies_.clear();
ResetTimer();
@@ -1157,9 +1207,6 @@ bool URLRequestHttpJob::GetResponseCookies(std::vector<std::string>* cookies) {
if (!response_info_)
return false;
- // TODO(darin): Why are we extracting response cookies again? Perhaps we
- // should just leverage response_cookies_.
-
cookies->clear();
FetchResponseCookies(cookies);
return true;
@@ -1189,7 +1236,7 @@ Filter* URLRequestHttpJob::SetupFilter() const {
std::vector<Filter::FilterType> encoding_types;
std::string encoding_type;
HttpResponseHeaders* headers = GetResponseHeaders();
- void* iter = NULL;
+ size_t iter = 0;
while (headers->EnumerateHeader(&iter, "Content-Encoding", &encoding_type)) {
encoding_types.push_back(Filter::ConvertEncodingToType(encoding_type));
}
@@ -1295,7 +1342,6 @@ void URLRequestHttpJob::CancelAuth() {
// These will be reset in OnStartCompleted.
response_info_ = NULL;
receive_headers_end_ = base::TimeTicks::Now();
- response_cookies_.clear();
ResetTimer();
@@ -1322,10 +1368,6 @@ void URLRequestHttpJob::ContinueWithCertificate(
ResetTimer();
- // No matter what, we want to report our status as IO pending since we will
- // be notifying our consumer asynchronously via OnStartCompleted.
- SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
-
int rv = transaction_->RestartWithCertificate(client_cert, client_private_key,
start_callback_);
if (rv == ERR_IO_PENDING)
@@ -1348,10 +1390,6 @@ void URLRequestHttpJob::ContinueDespiteLastError() {
ResetTimer();
- // No matter what, we want to report our status as IO pending since we will
- // be notifying our consumer asynchronously via OnStartCompleted.
- SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
-
int rv = transaction_->RestartIgnoringLastError(start_callback_);
if (rv == ERR_IO_PENDING)
return;
diff --git a/chromium/net/url_request/url_request_http_job.h b/chromium/net/url_request/url_request_http_job.h
index 79b4aa9dfc0..c914ff13046 100644
--- a/chromium/net/url_request/url_request_http_job.h
+++ b/chromium/net/url_request/url_request_http_job.h
@@ -87,7 +87,6 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob {
void AddExtraHeaders();
void AddCookieHeaderAndStart();
void SaveCookiesAndNotifyHeadersComplete(int result);
- void SaveNextCookie();
void FetchResponseCookies(std::vector<std::string>* cookies);
// Processes a Backoff header, if one exists.
@@ -99,6 +98,11 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob {
// Processes the Public-Key-Pins header, if one exists.
void ProcessPublicKeyPinsHeader();
+ // Processes the Expect-CT header, if one exists. This header
+ // indicates that the server wants the user agent to send a report
+ // when a connection violates the Expect CT policy.
+ void ProcessExpectCTHeader();
+
// |result| should be OK, or the request is canceled.
void OnHeadersReceivedCallback(int result);
void OnStartCompleted(int result);
@@ -163,17 +167,9 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob {
void DoneWithRequest(CompletionCause reason);
// Callback functions for Cookie Monster
- void DoLoadCookies();
- void CheckCookiePolicyAndLoad(const CookieList& cookie_list);
- void OnCookiesLoaded(const std::string& cookie_line);
+ void SetCookieHeaderAndStart(const CookieList& cookie_list);
void DoStartTransaction();
- // See the implementation for a description of save_next_cookie_running and
- // callback_pending.
- void OnCookieSaved(scoped_refptr<SharedBoolean> save_next_cookie_running,
- scoped_refptr<SharedBoolean> callback_pending,
- bool cookie_status);
-
// Some servers send the body compressed, but specify the content length as
// the uncompressed size. If this is the case, we return true in order
// to request to work around this non-adherence to the HTTP standard.
@@ -190,10 +186,6 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob {
HttpRequestInfo request_info_;
const HttpResponseInfo* response_info_;
- std::vector<std::string> response_cookies_;
- size_t response_cookies_save_index_;
- base::Time response_date_;
-
// Auth states for proxy and origin server.
AuthState proxy_auth_state_;
AuthState server_auth_state_;
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 713ae608e40..accf94c0902 100644
--- a/chromium/net/url_request/url_request_http_job_unittest.cc
+++ b/chromium/net/url_request/url_request_http_job_unittest.cc
@@ -15,6 +15,7 @@
#include "base/strings/string_split.h"
#include "net/base/auth.h"
#include "net/base/request_priority.h"
+#include "net/base/sdch_observer.h"
#include "net/base/test_data_directory.h"
#include "net/cookies/cookie_store_test_helpers.h"
#include "net/http/http_transaction_factory.h"
@@ -22,12 +23,14 @@
#include "net/socket/socket_test_util.h"
#include "net/test/cert_test_util.h"
#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_status.h"
#include "net/url_request/url_request_test_util.h"
#include "net/websockets/websocket_handshake_stream_base.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+#include "url/url_constants.h"
namespace net {
@@ -52,11 +55,19 @@ class TestURLRequestHttpJob : public URLRequestHttpJob {
class URLRequestHttpJobTest : public ::testing::Test {
protected:
- URLRequestHttpJobTest()
- : req_(context_.CreateRequest(GURL("http://www.example.com"),
- DEFAULT_PRIORITY,
- &delegate_)) {
+ URLRequestHttpJobTest() : context_(true) {
context_.set_http_transaction_factory(&network_layer_);
+
+ // The |test_job_factory_| takes ownership of the interceptor.
+ test_job_interceptor_ = new TestJobInterceptor();
+ EXPECT_TRUE(test_job_factory_.SetProtocolHandler(
+ url::kHttpScheme, make_scoped_ptr(test_job_interceptor_)));
+ context_.set_job_factory(&test_job_factory_);
+
+ context_.Init();
+
+ req_ = context_.CreateRequest(GURL("http://www.example.com"),
+ DEFAULT_PRIORITY, &delegate_);
}
bool TransactionAcceptsSdchEncoding() {
@@ -91,6 +102,11 @@ class URLRequestHttpJobTest : public ::testing::Test {
}
MockNetworkLayer network_layer_;
+
+ // |test_job_interceptor_| is owned by |test_job_factory_|.
+ TestJobInterceptor* test_job_interceptor_;
+ URLRequestJobFactoryImpl test_job_factory_;
+
TestURLRequestContext context_;
TestDelegate delegate_;
scoped_ptr<URLRequest> req_;
@@ -528,10 +544,13 @@ TEST_F(URLRequestHttpJobWithMockSocketsTest, BackoffHeaderCachedResponse) {
}
TEST_F(URLRequestHttpJobTest, TestCancelWhileReadingCookies) {
- context_.set_cookie_store(new DelayedCookieMonster());
+ DelayedCookieMonster cookie_monster;
+ TestURLRequestContext context(true);
+ context.set_cookie_store(&cookie_monster);
+ context.Init();
TestDelegate delegate;
- scoped_ptr<URLRequest> request = context_.CreateRequest(
+ scoped_ptr<URLRequest> request = context.CreateRequest(
GURL("http://www.example.com"), DEFAULT_PRIORITY, &delegate);
request->Start();
@@ -543,7 +562,7 @@ TEST_F(URLRequestHttpJobTest, TestCancelWhileReadingCookies) {
}
// Make sure that SetPriority actually sets the URLRequestHttpJob's
-// priority, both before and after start.
+// priority, before start. Other tests handle the after start case.
TEST_F(URLRequestHttpJobTest, SetPriorityBasic) {
scoped_ptr<TestURLRequestHttpJob> job(new TestURLRequestHttpJob(req_.get()));
EXPECT_EQ(DEFAULT_PRIORITY, job->priority());
@@ -553,23 +572,18 @@ TEST_F(URLRequestHttpJobTest, SetPriorityBasic) {
job->SetPriority(LOW);
EXPECT_EQ(LOW, job->priority());
-
- job->Start();
- EXPECT_EQ(LOW, job->priority());
-
- job->SetPriority(MEDIUM);
- EXPECT_EQ(MEDIUM, job->priority());
}
// Make sure that URLRequestHttpJob passes on its priority to its
// transaction on start.
TEST_F(URLRequestHttpJobTest, SetTransactionPriorityOnStart) {
- scoped_ptr<TestURLRequestHttpJob> job(new TestURLRequestHttpJob(req_.get()));
- job->SetPriority(LOW);
+ test_job_interceptor_->set_main_intercept_job(
+ make_scoped_ptr(new TestURLRequestHttpJob(req_.get())));
+ req_->SetPriority(LOW);
EXPECT_FALSE(network_layer_.last_transaction());
- job->Start();
+ req_->Start();
ASSERT_TRUE(network_layer_.last_transaction());
EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
@@ -578,13 +592,14 @@ TEST_F(URLRequestHttpJobTest, SetTransactionPriorityOnStart) {
// Make sure that URLRequestHttpJob passes on its priority updates to
// its transaction.
TEST_F(URLRequestHttpJobTest, SetTransactionPriority) {
- scoped_ptr<TestURLRequestHttpJob> job(new TestURLRequestHttpJob(req_.get()));
- job->SetPriority(LOW);
- job->Start();
+ test_job_interceptor_->set_main_intercept_job(
+ make_scoped_ptr(new TestURLRequestHttpJob(req_.get())));
+ req_->SetPriority(LOW);
+ req_->Start();
ASSERT_TRUE(network_layer_.last_transaction());
EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
- job->SetPriority(HIGHEST);
+ req_->SetPriority(HIGHEST);
EXPECT_EQ(HIGHEST, network_layer_.last_transaction()->priority());
}
@@ -592,8 +607,9 @@ TEST_F(URLRequestHttpJobTest, SetTransactionPriority) {
TEST_F(URLRequestHttpJobTest, SdchAdvertisementGet) {
EnableSdch();
req_->set_method("GET"); // Redundant with default.
- scoped_ptr<TestURLRequestHttpJob> job(new TestURLRequestHttpJob(req_.get()));
- job->Start();
+ test_job_interceptor_->set_main_intercept_job(
+ make_scoped_ptr(new TestURLRequestHttpJob(req_.get())));
+ req_->Start();
EXPECT_TRUE(TransactionAcceptsSdchEncoding());
}
@@ -601,11 +617,87 @@ TEST_F(URLRequestHttpJobTest, SdchAdvertisementGet) {
TEST_F(URLRequestHttpJobTest, SdchAdvertisementPost) {
EnableSdch();
req_->set_method("POST");
- scoped_ptr<TestURLRequestHttpJob> job(new TestURLRequestHttpJob(req_.get()));
- job->Start();
+ test_job_interceptor_->set_main_intercept_job(
+ make_scoped_ptr(new TestURLRequestHttpJob(req_.get())));
+ req_->Start();
EXPECT_FALSE(TransactionAcceptsSdchEncoding());
}
+class MockSdchObserver : public SdchObserver {
+ public:
+ MockSdchObserver() {}
+ MOCK_METHOD2(OnDictionaryAdded,
+ void(const GURL& request_url, const std::string& server_hash));
+ MOCK_METHOD1(OnDictionaryRemoved, void(const std::string& server_hash));
+ MOCK_METHOD1(OnDictionaryUsed, void(const std::string& server_hash));
+ MOCK_METHOD2(OnGetDictionary,
+ void(const GURL& request_url, const GURL& dictionary_url));
+ MOCK_METHOD0(OnClearDictionaries, void());
+};
+
+class URLRequestHttpJobWithSdchSupportTest : public ::testing::Test {
+ protected:
+ URLRequestHttpJobWithSdchSupportTest() : context_(true) {
+ scoped_ptr<HttpNetworkSession::Params> params(
+ new HttpNetworkSession::Params);
+ context_.set_http_network_session_params(std::move(params));
+ context_.set_client_socket_factory(&socket_factory_);
+ context_.Init();
+ }
+
+ MockClientSocketFactory socket_factory_;
+ TestURLRequestContext context_;
+};
+
+TEST_F(URLRequestHttpJobWithSdchSupportTest, GetDictionary) {
+ MockWrite writes[] = {
+ MockWrite("GET / HTTP/1.1\r\n"
+ "Host: 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"
+ "Get-Dictionary: /sdch.dict\r\n"
+ "Cache-Control: max-age=120\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);
+
+ // First response will be "from network" and we should have OnGetDictionary
+ // invoked.
+ GURL url("http://example.com");
+ EXPECT_CALL(sdch_observer,
+ OnGetDictionary(url, GURL("http://example.com/sdch.dict")));
+ TestDelegate delegate;
+ scoped_ptr<URLRequest> request =
+ context_.CreateRequest(url, DEFAULT_PRIORITY, &delegate);
+ request->Start();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(request->status().is_success());
+
+ // Second response should be from cache without notification of SdchObserver
+ TestDelegate delegate2;
+ scoped_ptr<URLRequest> request2 =
+ context_.CreateRequest(url, DEFAULT_PRIORITY, &delegate2);
+ request2->Start();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(request->status().is_success());
+
+ // Cleanup manager.
+ sdch_manager.RemoveObserver(&sdch_observer);
+}
+
class URLRequestHttpJobWithBrotliSupportTest : public ::testing::Test {
protected:
URLRequestHttpJobWithBrotliSupportTest()
@@ -710,12 +802,6 @@ class URLRequestHttpJobWebSocketTest
: req_(context_.CreateRequest(GURL("ws://www.example.com"),
DEFAULT_PRIORITY,
&delegate_)) {
- // The TestNetworkDelegate expects a call to NotifyBeforeURLRequest before
- // anything else happens.
- GURL url("ws://localhost/");
- TestCompletionCallback dummy;
- network_delegate_.NotifyBeforeURLRequest(
- req_.get(), dummy.callback(), &url);
}
TestDelegate delegate_;
@@ -741,6 +827,12 @@ class MockCreateHelper : public WebSocketHandshakeStreamBase::CreateHelper {
bool));
};
+// iOS doesn't support WebSockets, so these tests fail with ERR_UNKOWN_SCHEME on
+// iOS.
+// TODO(mmenke): Hard coding features based on OS is regression prone and ugly.
+// Seems like this should use a build flag instead.
+#if !defined(OS_IOS)
+
class FakeWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
public:
FakeWebSocketHandshakeStream() : initialize_stream_was_called_(false) {}
@@ -796,6 +888,12 @@ class FakeWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override {
+ ADD_FAILURE();
+ return ERR_NOT_IMPLEMENTED;
+ }
+
void Drain(HttpNetworkSession* session) override {}
void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
@@ -818,15 +916,13 @@ class FakeWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
};
TEST_F(URLRequestHttpJobWebSocketTest, RejectedWithoutCreateHelper) {
- scoped_ptr<TestURLRequestHttpJob> job(new TestURLRequestHttpJob(req_.get()));
- job->Start();
+ req_->Start();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(URLRequestStatus::FAILED, req_->status().status());
EXPECT_EQ(ERR_DISALLOWED_URL_SCHEME, req_->status().error());
}
TEST_F(URLRequestHttpJobWebSocketTest, CreateHelperPassedThrough) {
- scoped_ptr<TestURLRequestHttpJob> job(new TestURLRequestHttpJob(req_.get()));
scoped_ptr<MockCreateHelper> create_helper(
new ::testing::StrictMock<MockCreateHelper>());
FakeWebSocketHandshakeStream* fake_handshake_stream(
@@ -838,12 +934,14 @@ TEST_F(URLRequestHttpJobWebSocketTest, CreateHelperPassedThrough) {
req_->SetUserData(WebSocketHandshakeStreamBase::CreateHelper::DataKey(),
create_helper.release());
req_->SetLoadFlags(LOAD_DISABLE_CACHE);
- job->Start();
+ req_->Start();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(URLRequestStatus::IO_PENDING, req_->status().status());
EXPECT_TRUE(fake_handshake_stream->initialize_stream_was_called());
}
+#endif // !defined(OS_IOS)
+
} // namespace
} // namespace net
diff --git a/chromium/net/url_request/url_request_job.cc b/chromium/net/url_request/url_request_job.cc
index 55a4f51e26e..239ab4bf6ee 100644
--- a/chromium/net/url_request/url_request_job.cc
+++ b/chromium/net/url_request/url_request_job.cc
@@ -384,11 +384,11 @@ void URLRequestJob::NotifyHeadersComplete() {
if (has_handled_response_)
return;
- // This should not be called on error, and the job type should have cleared
- // IO_PENDING state before calling this method.
- // TODO(mmenke): Change this to a DCHECK once https://crbug.com/508900 is
- // resolved.
- CHECK(request_->status().is_success());
+ // The URLRequest status should still be IO_PENDING, which it was set to
+ // before the URLRequestJob was started. On error or cancellation, this
+ // method should not be called.
+ DCHECK(request_->status().is_io_pending());
+ SetStatus(URLRequestStatus());
// Initialize to the current time, and let the subclass optionally override
// the time stamps if it has that information. The default request_time is
@@ -474,6 +474,8 @@ void URLRequestJob::ConvertResultToError(int result, Error* error, int* count) {
}
void URLRequestJob::ReadRawDataComplete(int result) {
+ DCHECK(request_->status().is_io_pending());
+
// TODO(cbentzel): Remove ScopedTracker below once crbug.com/475755 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
@@ -493,29 +495,20 @@ void URLRequestJob::ReadRawDataComplete(int result) {
DCHECK_NE(ERR_IO_PENDING, error);
- // Synchronize the URLRequest state machine with the URLRequestJob state
- // machine. If this read succeeded, either the request is at EOF and the
- // URLRequest state machine goes to 'finished', or it is not and the
- // URLRequest state machine goes to 'success'. If the read failed, the
- // URLRequest state machine goes directly to 'finished'.
- //
- // Update the URLRequest's status first, so that NotifyReadCompleted has an
- // accurate view of the request.
- if (error == OK && bytes_read > 0) {
- SetStatus(URLRequestStatus());
- } else {
- NotifyDone(URLRequestStatus::FromError(error));
- }
-
GatherRawReadStats(error, bytes_read);
if (filter_.get() && error == OK) {
+ // |bytes_read| being 0 indicates an EOF was received. ReadFilteredData
+ // can incorrectly return ERR_IO_PENDING when 0 bytes are passed to it, so
+ // just don't call into the filter in that case.
int filter_bytes_read = 0;
- // Tell the filter that it has more data.
- PushInputToFilter(bytes_read);
+ if (bytes_read > 0) {
+ // Tell the filter that it has more data.
+ PushInputToFilter(bytes_read);
- // Filter the data.
- error = ReadFilteredData(&filter_bytes_read);
+ // Filter the data.
+ error = ReadFilteredData(&filter_bytes_read);
+ }
if (error == OK && !filter_bytes_read)
DoneReading();
@@ -534,6 +527,22 @@ void URLRequestJob::ReadRawDataComplete(int result) {
<< " post total = " << postfilter_bytes_read_;
}
+ // Synchronize the URLRequest state machine with the URLRequestJob state
+ // machine. If this read succeeded, either the request is at EOF and the
+ // URLRequest state machine goes to 'finished', or it is not and the
+ // URLRequest state machine goes to 'success'. If the read failed, the
+ // URLRequest state machine goes directly to 'finished'. If filtered data is
+ // pending, then there's nothing to do, since the status of the request is
+ // already pending.
+ //
+ // Update the URLRequest's status first, so that NotifyReadCompleted has an
+ // accurate view of the request.
+ if (error == OK && bytes_read > 0) {
+ SetStatus(URLRequestStatus());
+ } else if (error != ERR_IO_PENDING) {
+ NotifyDone(URLRequestStatus::FromError(error));
+ }
+
// NotifyReadCompleted should be called after SetStatus or NotifyDone updates
// the status.
if (error == OK)
@@ -544,12 +553,14 @@ void URLRequestJob::ReadRawDataComplete(int result) {
void URLRequestJob::NotifyStartError(const URLRequestStatus &status) {
DCHECK(!has_handled_response_);
+ DCHECK(request_->status().is_io_pending());
+
has_handled_response_ = true;
// There may be relevant information in the response info even in the
// error case.
GetResponseInfo(&request_->response_info_);
- request_->set_status(status);
+ SetStatus(status);
request_->NotifyResponseStarted();
// |this| may have been deleted here.
}
@@ -738,6 +749,8 @@ Error URLRequestJob::ReadFilteredData(int* bytes_read) {
<< " Filter Error";
filter_needs_more_output_space_ = false;
error = ERR_CONTENT_DECODING_FAILED;
+ UMA_HISTOGRAM_ENUMERATION("Net.ContentDecodingFailed.FilterType",
+ filter_->type(), Filter::FILTER_TYPE_MAX);
break;
}
default: {
@@ -783,10 +796,9 @@ void URLRequestJob::SetStatus(const URLRequestStatus &status) {
// An error status should never be replaced by a non-error status by a
// URLRequestJob. URLRequest has some retry paths, but it resets the status
// itself, if needed.
- // TODO(mmenke): Change this to a DCHECK once https://crbug.com/508900 is
- // resolved.
- CHECK(request_->status().is_io_pending() || request_->status().is_success() ||
- (!status.is_success() && !status.is_io_pending()));
+ DCHECK(request_->status().is_io_pending() ||
+ request_->status().is_success() ||
+ (!status.is_success() && !status.is_io_pending()));
request_->set_status(status);
}
@@ -941,6 +953,14 @@ RedirectInfo URLRequestJob::ComputeRedirectInfo(const GURL& location,
request_->referrer(),
redirect_info.new_url).spec();
+ std::string include_referer;
+ request_->GetResponseHeaderByName("include-referer-token-binding-id",
+ &include_referer);
+ if (include_referer == "true" &&
+ request_->ssl_info().token_binding_negotiated) {
+ redirect_info.referred_token_binding_host = url.host();
+ }
+
return redirect_info;
}
diff --git a/chromium/net/url_request/url_request_job.h b/chromium/net/url_request/url_request_job.h
index 2fbf70e39bc..9555b67f0f2 100644
--- a/chromium/net/url_request/url_request_job.h
+++ b/chromium/net/url_request/url_request_job.h
@@ -337,9 +337,6 @@ class NET_EXPORT URLRequestJob : public base::PowerObserver {
// The status of the job.
const URLRequestStatus GetStatus();
- // Set the status of the job.
- void SetStatus(const URLRequestStatus& status);
-
// Set the proxy server that was used, if any.
void SetProxyServer(const HostPortPair& proxy_server);
@@ -366,6 +363,10 @@ class NET_EXPORT URLRequestJob : public base::PowerObserver {
URLRequest* request_;
private:
+ // Set the status of the associated URLRequest.
+ // TODO(mmenke): Make the URLRequest manage its own status.
+ void SetStatus(const URLRequestStatus& status);
+
// When data filtering is enabled, this function is used to read data
// for the filter. Returns a net error code to indicate if raw data was
// successfully read, an error happened, or the IO is pending.
diff --git a/chromium/net/url_request/url_request_job_factory_impl_unittest.cc b/chromium/net/url_request/url_request_job_factory_impl_unittest.cc
index adce41b311f..dbcc8caab14 100644
--- a/chromium/net/url_request/url_request_job_factory_impl_unittest.cc
+++ b/chromium/net/url_request/url_request_job_factory_impl_unittest.cc
@@ -22,12 +22,8 @@ namespace {
class MockURLRequestJob : public URLRequestJob {
public:
- MockURLRequestJob(URLRequest* request,
- NetworkDelegate* network_delegate,
- const URLRequestStatus& status)
- : URLRequestJob(request, network_delegate),
- status_(status),
- weak_factory_(this) {}
+ MockURLRequestJob(URLRequest* request, NetworkDelegate* network_delegate)
+ : URLRequestJob(request, network_delegate), weak_factory_(this) {}
void Start() override {
// Start reading asynchronously so that all error reporting and data
@@ -42,11 +38,9 @@ class MockURLRequestJob : public URLRequestJob {
private:
void StartAsync() {
- SetStatus(status_);
NotifyHeadersComplete();
}
- URLRequestStatus status_;
base::WeakPtrFactory<MockURLRequestJob> weak_factory_;
};
@@ -55,10 +49,7 @@ class DummyProtocolHandler : public URLRequestJobFactory::ProtocolHandler {
URLRequestJob* MaybeCreateJob(
URLRequest* request,
NetworkDelegate* network_delegate) const override {
- return new MockURLRequestJob(
- request,
- network_delegate,
- URLRequestStatus(URLRequestStatus::SUCCESS, OK));
+ return new MockURLRequestJob(request, network_delegate);
}
};
diff --git a/chromium/net/url_request/url_request_job_unittest.cc b/chromium/net/url_request/url_request_job_unittest.cc
index f3796bdb4c9..37a457f5090 100644
--- a/chromium/net/url_request/url_request_job_unittest.cc
+++ b/chromium/net/url_request/url_request_job_unittest.cc
@@ -126,6 +126,15 @@ const MockTransaction kEmptyBodyGzip_Transaction = {
OK,
};
+const MockTransaction kInvalidContentGZip_Transaction = {
+ "http://www.google.com/gzyp", "GET", base::Time(), "", LOAD_NORMAL,
+ "HTTP/1.1 200 OK",
+ "Content-Encoding: gzip\n"
+ "Content-Length: 21\n",
+ base::Time(), "not a valid gzip body", TEST_MODE_NORMAL, nullptr, nullptr,
+ 0, 0, OK,
+};
+
const MockTransaction kBrotli_Slow_Transaction = {
"http://www.google.com/brotli", "GET", base::Time(), "", LOAD_NORMAL,
"HTTP/1.1 200 OK",
@@ -272,6 +281,34 @@ TEST(URLRequestJob, EmptyBodySkipFilter) {
RemoveMockTransaction(&kEmptyBodyGzip_Transaction);
}
+// Regression test for crbug.com/575213.
+TEST(URLRequestJob, InvalidContentGZipTransaction) {
+ MockNetworkLayer network_layer;
+ TestURLRequestContext context;
+ context.set_http_transaction_factory(&network_layer);
+
+ TestDelegate d;
+ scoped_ptr<URLRequest> req(context.CreateRequest(
+ GURL(kInvalidContentGZip_Transaction.url), DEFAULT_PRIORITY, &d));
+ AddMockTransaction(&kInvalidContentGZip_Transaction);
+
+ req->set_method("GET");
+ req->Start();
+
+ base::MessageLoop::current()->Run();
+
+ // Request failed indicates the request failed before headers were received,
+ // so should be false.
+ EXPECT_FALSE(d.request_failed());
+ EXPECT_EQ(200, req->GetResponseCode());
+ EXPECT_FALSE(req->status().is_success());
+ EXPECT_EQ(ERR_CONTENT_DECODING_FAILED, req->status().error());
+ EXPECT_TRUE(d.data_received().empty());
+ EXPECT_FALSE(network_layer.done_reading_called());
+
+ RemoveMockTransaction(&kInvalidContentGZip_Transaction);
+}
+
// Regression test for crbug.com/553300.
TEST(URLRequestJob, SlowFilterRead) {
MockNetworkLayer network_layer;
diff --git a/chromium/net/url_request/url_request_test_util.cc b/chromium/net/url_request/url_request_test_util.cc
index b3c03c71164..fbcc19b420f 100644
--- a/chromium/net/url_request/url_request_test_util.cc
+++ b/chromium/net/url_request/url_request_test_util.cc
@@ -16,6 +16,7 @@
#include "base/threading/worker_pool.h"
#include "net/base/host_port_pair.h"
#include "net/cert/cert_verifier.h"
+#include "net/cert/ct_verifier.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_network_session.h"
#include "net/http/http_response_headers.h"
@@ -50,16 +51,13 @@ const int kStageDestruction = 1 << 10;
} // namespace
-TestURLRequestContext::TestURLRequestContext()
- : initialized_(false),
- client_socket_factory_(NULL),
- context_storage_(this) {
- Init();
-}
+TestURLRequestContext::TestURLRequestContext() : TestURLRequestContext(false) {}
TestURLRequestContext::TestURLRequestContext(bool delay_initialization)
: initialized_(false),
- client_socket_factory_(NULL),
+ client_socket_factory_(nullptr),
+ proxy_delegate_(nullptr),
+ ct_policy_enforcer_(nullptr),
context_storage_(this) {
if (!delay_initialization)
Init();
@@ -99,18 +97,23 @@ void TestURLRequestContext::Init() {
EXPECT_FALSE(client_socket_factory_);
} else {
HttpNetworkSession::Params params;
+
if (http_network_session_params_)
params = *http_network_session_params_;
params.client_socket_factory = client_socket_factory();
+ params.proxy_delegate = proxy_delegate();
params.host_resolver = host_resolver();
params.cert_verifier = cert_verifier();
+ params.cert_transparency_verifier = cert_transparency_verifier();
+ if (ct_policy_enforcer())
+ params.ct_policy_enforcer = ct_policy_enforcer();
params.transport_security_state = transport_security_state();
params.proxy_service = proxy_service();
params.ssl_config_service = ssl_config_service();
params.http_auth_handler_factory = http_auth_handler_factory();
- params.network_delegate = network_delegate();
params.http_server_properties = http_server_properties();
params.net_log = net_log();
+ params.channel_id_service = channel_id_service();
context_storage_.set_http_network_session(
make_scoped_ptr(new HttpNetworkSession(params)));
context_storage_.set_http_transaction_factory(make_scoped_ptr(
@@ -118,12 +121,14 @@ void TestURLRequestContext::Init() {
HttpCache::DefaultBackend::InMemory(0), false)));
}
// In-memory cookie store.
- if (!cookie_store())
- context_storage_.set_cookie_store(new CookieMonster(NULL, NULL));
+ if (!cookie_store()) {
+ context_storage_.set_cookie_store(
+ make_scoped_ptr(new CookieMonster(nullptr, nullptr)));
+ }
// In-memory Channel ID service.
if (!channel_id_service()) {
context_storage_.set_channel_id_service(make_scoped_ptr(
- new ChannelIDService(new DefaultChannelIDStore(NULL),
+ new ChannelIDService(new DefaultChannelIDStore(nullptr),
base::WorkerPool::GetTaskRunner(true))));
}
if (!http_user_agent_settings()) {
diff --git a/chromium/net/url_request/url_request_test_util.h b/chromium/net/url_request/url_request_test_util.h
index 1a829d5c12c..dc8d0e18954 100644
--- a/chromium/net/url_request/url_request_test_util.h
+++ b/chromium/net/url_request/url_request_test_util.h
@@ -69,6 +69,12 @@ class TestURLRequestContext : public URLRequestContext {
client_socket_factory_ = factory;
}
+ ProxyDelegate* proxy_delegate() { return proxy_delegate_; }
+
+ void set_proxy_delegate(ProxyDelegate* proxy_delegate) {
+ proxy_delegate_ = proxy_delegate;
+ }
+
void set_http_network_session_params(
scoped_ptr<HttpNetworkSession::Params> params) {
http_network_session_params_ = std::move(params);
@@ -78,6 +84,11 @@ class TestURLRequestContext : public URLRequestContext {
context_storage_.set_sdch_manager(std::move(sdch_manager));
}
+ CTPolicyEnforcer* ct_policy_enforcer() { return ct_policy_enforcer_; }
+ void set_ct_policy_enforcer(CTPolicyEnforcer* ct_policy_enforcer) {
+ ct_policy_enforcer_ = ct_policy_enforcer;
+ }
+
private:
bool initialized_;
@@ -89,6 +100,10 @@ class TestURLRequestContext : public URLRequestContext {
// Not owned:
ClientSocketFactory* client_socket_factory_;
+ ProxyDelegate* proxy_delegate_;
+
+ CTPolicyEnforcer* ct_policy_enforcer_;
+
protected:
URLRequestContextStorage context_storage_;
};
diff --git a/chromium/net/url_request/url_request_throttler_manager.cc b/chromium/net/url_request/url_request_throttler_manager.cc
index 3f08e9e1ac8..a36f0c96e93 100644
--- a/chromium/net/url_request/url_request_throttler_manager.cc
+++ b/chromium/net/url_request/url_request_throttler_manager.cc
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "base/strings/string_util.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "net/log/net_log.h"
namespace net {
diff --git a/chromium/net/url_request/url_request_unittest.cc b/chromium/net/url_request/url_request_unittest.cc
index b1bf6189c02..620d8b81cb4 100644
--- a/chromium/net/url_request/url_request_unittest.cc
+++ b/chromium/net/url_request/url_request_unittest.cc
@@ -16,6 +16,7 @@
#include <algorithm>
#include <limits>
+#include "base/base64url.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
@@ -51,13 +52,15 @@
#include "net/base/load_timing_info_test_util.h"
#include "net/base/net_errors.h"
#include "net/base/net_module.h"
-#include "net/base/net_util.h"
-#include "net/base/network_quality_estimator.h"
#include "net/base/request_priority.h"
#include "net/base/test_data_directory.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/base/upload_file_element_reader.h"
+#include "net/base/url_util.h"
+#include "net/cert/ct_policy_status.h"
+#include "net/cert/ct_verifier.h"
+#include "net/cert/ct_verify_result.h"
#include "net/cert/ev_root_ca_metadata.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/cert/test_root_certs.h"
@@ -79,9 +82,12 @@
#include "net/log/test_net_log_util.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/ssl_client_socket.h"
+#include "net/ssl/channel_id_service.h"
+#include "net/ssl/default_channel_id_store.h"
#include "net/ssl/ssl_cipher_suite_names.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_server_config.h"
+#include "net/ssl/token_binding.h"
#include "net/test/cert_test_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
@@ -683,6 +689,9 @@ class MockCertificateReportSender
latest_report_ = report;
}
+ void SetErrorCallback(
+ const base::Callback<void(const GURL&, int)>& error_callback) override {}
+
const GURL& latest_report_uri() { return latest_report_uri_; }
const std::string& latest_report() { return latest_report_; }
@@ -826,7 +835,15 @@ TEST_F(URLRequestTest, DataURLImageTest) {
#if !defined(DISABLE_FILE_SUPPORT)
TEST_F(URLRequestTest, FileTest) {
base::FilePath app_path;
+
+#if defined(OS_ANDROID)
+ // Android devices are not guaranteed to be able to read /proc/self/exe
+ // Use /etc/hosts instead
+ app_path = base::FilePath("/etc/hosts");
+#else
PathService::Get(base::FILE_EXE, &app_path);
+#endif // OS_ANDROID
+
GURL app_url = FilePathToFileURL(app_path);
TestDelegate d;
@@ -2247,9 +2264,7 @@ TEST_F(URLRequestTest, DelayedCookieCallback) {
ASSERT_TRUE(test_server.Start());
TestURLRequestContext context;
- scoped_refptr<DelayedCookieMonster> delayed_cm =
- new DelayedCookieMonster();
- scoped_refptr<CookieStore> cookie_store = delayed_cm;
+ scoped_ptr<DelayedCookieMonster> delayed_cm(new DelayedCookieMonster());
context.set_cookie_store(delayed_cm.get());
// Set up a cookie.
@@ -2646,152 +2661,117 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) {
}
}
-TEST_F(URLRequestTest, FirstPartyOnlyCookiesEnabled) {
+TEST_F(URLRequestTest, SameSiteCookies) {
LocalHttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
TestNetworkDelegate network_delegate;
- network_delegate.set_experimental_cookie_features_enabled(true);
default_context_.set_network_delegate(&network_delegate);
- // Set up a 'First-Party-Only' cookie (on '127.0.0.1', as that's where
- // LocalHttpTestServer points).
+ const std::string kHost = "example.test";
+ const std::string kSubHost = "subdomain.example.test";
+ const std::string kCrossHost = "cross-origin.test";
+
+ // Set up two 'SameSite' cookies on 'example.test'
{
TestDelegate d;
scoped_ptr<URLRequest> req(default_context_.CreateRequest(
- test_server.GetURL(
- "/set-cookie?FirstPartyCookieToSet=1;First-Party-Only"),
+ test_server.GetURL(kHost,
+ "/set-cookie?StrictSameSiteCookie=1;SameSite=Strict&"
+ "LaxSameSiteCookie=1;SameSite=Lax"),
DEFAULT_PRIORITY, &d));
req->Start();
base::RunLoop().Run();
EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
- EXPECT_EQ(1, network_delegate.set_cookie_count());
+ EXPECT_EQ(2, network_delegate.set_cookie_count());
}
- // Verify that the cookie is sent for first-party requests.
+ // Verify that both cookies are sent for same-site requests.
{
TestDelegate d;
scoped_ptr<URLRequest> req(default_context_.CreateRequest(
- test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d));
- req->set_first_party_for_cookies(test_server.GetURL("/"));
- req->set_initiator(url::Origin(test_server.GetURL("/")));
+ test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d));
+ req->set_first_party_for_cookies(test_server.GetURL(kHost, "/"));
+ req->set_initiator(url::Origin(test_server.GetURL(kHost, "/")));
req->Start();
base::RunLoop().Run();
- EXPECT_TRUE(d.data_received().find("FirstPartyCookieToSet=1") !=
- std::string::npos);
+ 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 the cookie is not sent for non-first-party requests.
+ // Verify that both cookies are sent for same-registrable-domain requests.
{
TestDelegate d;
scoped_ptr<URLRequest> req(default_context_.CreateRequest(
- test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d));
- req->set_first_party_for_cookies(GURL("http://third-party.test/"));
- req->set_initiator(url::Origin(GURL("http://third-party.test/")));
+ test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d));
+ req->set_first_party_for_cookies(test_server.GetURL(kSubHost, "/"));
+ req->set_initiator(url::Origin(test_server.GetURL(kSubHost, "/")));
req->Start();
base::RunLoop().Run();
- EXPECT_TRUE(d.data_received().find("FirstPartyCookieToSet=1") ==
- std::string::npos);
+ 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 the cookie is sent for non-first-party initiators when the
- // method is "safe".
+ // Verify that neither cookie is not sent for cross-site requests.
{
TestDelegate d;
scoped_ptr<URLRequest> req(default_context_.CreateRequest(
- test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d));
- req->set_first_party_for_cookies(test_server.GetURL("/"));
- req->set_initiator(url::Origin(GURL("http://third-party.test/")));
+ test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d));
+ req->set_first_party_for_cookies(test_server.GetURL(kCrossHost, "/"));
+ req->set_initiator(url::Origin(test_server.GetURL(kCrossHost, "/")));
req->Start();
base::RunLoop().Run();
- EXPECT_FALSE(d.data_received().find("FirstPartyCookieToSet=1") ==
- std::string::npos);
+ EXPECT_EQ(std::string::npos,
+ d.data_received().find("StrictSameSiteCookie=1"));
+ EXPECT_EQ(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 the cookie is not sent for non-first-party initiators when the
- // method is unsafe (e.g. POST).
- {
- TestDelegate d;
- scoped_ptr<URLRequest> req(default_context_.CreateRequest(
- test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d));
- req->set_first_party_for_cookies(test_server.GetURL("/"));
- req->set_initiator(url::Origin(GURL("http://third-party.test/")));
- req->set_method("POST");
- req->Start();
- base::RunLoop().Run();
-
- EXPECT_TRUE(d.data_received().find("FirstPartyCookieToSet=1") ==
- std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
- EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
- }
-}
-
-TEST_F(URLRequestTest, FirstPartyOnlyCookiesDisabled) {
- LocalHttpTestServer test_server;
- ASSERT_TRUE(test_server.Start());
-
- // Set up a 'First-Party-Only' cookie (on '127.0.0.1', as that's where
- // LocalHttpTestServer points).
- {
- TestNetworkDelegate network_delegate;
- network_delegate.set_experimental_cookie_features_enabled(false);
- default_context_.set_network_delegate(&network_delegate);
-
- TestDelegate d;
- scoped_ptr<URLRequest> req(default_context_.CreateRequest(
- test_server.GetURL(
- "/set-cookie?FirstPartyCookieToSet=1;First-Party-Only"),
- DEFAULT_PRIORITY, &d));
- req->Start();
- base::RunLoop().Run();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
- EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
- EXPECT_EQ(1, network_delegate.set_cookie_count());
- }
-
- // Verify that the cookie is sent for first-party requests.
+ // Verify that the lax cookie is sent for cross-site initiators when the
+ // method is "safe".
{
- TestNetworkDelegate network_delegate;
- network_delegate.set_experimental_cookie_features_enabled(false);
- default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
scoped_ptr<URLRequest> req(default_context_.CreateRequest(
- test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d));
- req->set_first_party_for_cookies(test_server.GetURL("/"));
+ test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d));
+ req->set_first_party_for_cookies(test_server.GetURL(kHost, "/"));
+ req->set_initiator(url::Origin(test_server.GetURL(kCrossHost, "/")));
+ req->set_method("GET");
req->Start();
base::RunLoop().Run();
- EXPECT_TRUE(d.data_received().find("FirstPartyCookieToSet=1") !=
- std::string::npos);
+ EXPECT_EQ(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 the cookie is also sent for non-first-party requests.
+ // Verify that neither cookie is sent for cross-site initiators when the
+ // method is unsafe (e.g. POST).
{
- TestNetworkDelegate network_delegate;
- network_delegate.set_experimental_cookie_features_enabled(false);
- default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
scoped_ptr<URLRequest> req(default_context_.CreateRequest(
- test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d));
- req->set_first_party_for_cookies(GURL("http://third-party.test/"));
+ test_server.GetURL(kHost, "/echoheader?Cookie"), DEFAULT_PRIORITY, &d));
+ req->set_first_party_for_cookies(test_server.GetURL(kHost, "/"));
+ req->set_initiator(url::Origin(test_server.GetURL(kCrossHost, "/")));
+ req->set_method("POST");
req->Start();
base::RunLoop().Run();
- EXPECT_NE(d.data_received().find("FirstPartyCookieToSet=1"),
- std::string::npos);
+ EXPECT_EQ(std::string::npos,
+ d.data_received().find("StrictSameSiteCookie=1"));
+ EXPECT_EQ(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());
}
@@ -3300,30 +3280,6 @@ class URLRequestTestHTTP : public URLRequestTest {
delete[] uploadBytes;
}
- void AddChunksToUpload(URLRequest* r) {
- r->AppendChunkToUpload("a", 1, false);
- r->AppendChunkToUpload("bcd", 3, false);
- r->AppendChunkToUpload("this is a longer chunk than before.", 35, false);
- r->AppendChunkToUpload("\r\n\r\n", 4, false);
- r->AppendChunkToUpload("0", 1, false);
- r->AppendChunkToUpload("2323", 4, true);
- }
-
- void VerifyReceivedDataMatchesChunks(URLRequest* r, TestDelegate* d) {
- // This should match the chunks sent by AddChunksToUpload().
- const std::string expected_data =
- "abcdthis is a longer chunk than before.\r\n\r\n02323";
-
- ASSERT_EQ(1, d->response_started_count())
- << "request failed: " << r->status().status()
- << ", os error: " << r->status().error();
-
- EXPECT_FALSE(d->received_data_before_response());
-
- EXPECT_EQ(expected_data.size(), static_cast<size_t>(d->bytes_received()));
- EXPECT_EQ(expected_data, d->data_received());
- }
-
bool DoManyCookiesRequest(int num_cookies) {
TestDelegate d;
scoped_ptr<URLRequest> r(default_context_.CreateRequest(
@@ -3370,7 +3326,250 @@ scoped_ptr<test_server::HttpResponse> HandleRedirectConnect(
} // namespace
-// In this unit test, we're using the EmbeddedTestServer as a proxy server and
+class TestSSLConfigService : public SSLConfigService {
+ public:
+ TestSSLConfigService(bool ev_enabled,
+ bool online_rev_checking,
+ bool rev_checking_required_local_anchors,
+ bool token_binding_enabled)
+ : ev_enabled_(ev_enabled),
+ online_rev_checking_(online_rev_checking),
+ rev_checking_required_local_anchors_(
+ rev_checking_required_local_anchors),
+ token_binding_enabled_(token_binding_enabled),
+ min_version_(kDefaultSSLVersionMin),
+ fallback_min_version_(kDefaultSSLVersionFallbackMin) {}
+
+ void set_min_version(uint16_t version) { min_version_ = version; }
+
+ void set_fallback_min_version(uint16_t version) {
+ fallback_min_version_ = version;
+ }
+
+ // SSLConfigService:
+ void GetSSLConfig(SSLConfig* config) override {
+ *config = SSLConfig();
+ config->rev_checking_enabled = online_rev_checking_;
+ config->verify_ev_cert = ev_enabled_;
+ config->rev_checking_required_local_anchors =
+ rev_checking_required_local_anchors_;
+ if (fallback_min_version_) {
+ config->version_fallback_min = fallback_min_version_;
+ }
+ if (min_version_) {
+ config->version_min = min_version_;
+ }
+ if (token_binding_enabled_) {
+ config->token_binding_params.push_back(TB_PARAM_ECDSAP256);
+ }
+ }
+
+ protected:
+ ~TestSSLConfigService() override {}
+
+ private:
+ const bool ev_enabled_;
+ const bool online_rev_checking_;
+ const bool rev_checking_required_local_anchors_;
+ const bool token_binding_enabled_;
+ uint16_t min_version_;
+ uint16_t fallback_min_version_;
+};
+
+// TODO(svaldez): Update tests to use EmbeddedTestServer.
+#if !defined(OS_IOS)
+class TokenBindingURLRequestTest : public URLRequestTestHTTP {
+ public:
+ void SetUp() override {
+ default_context_.set_ssl_config_service(
+ new TestSSLConfigService(false, false, false, true));
+ channel_id_service_.reset(new ChannelIDService(
+ new DefaultChannelIDStore(NULL), base::ThreadTaskRunnerHandle::Get()));
+ default_context_.set_channel_id_service(channel_id_service_.get());
+ URLRequestTestHTTP::SetUp();
+ }
+
+ protected:
+ scoped_ptr<ChannelIDService> channel_id_service_;
+};
+
+TEST_F(TokenBindingURLRequestTest, TokenBindingTest) {
+ SpawnedTestServer::SSLOptions ssl_options;
+ ssl_options.supported_token_binding_params.push_back(TB_PARAM_ECDSAP256);
+ SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath(kTestFilePath));
+ ASSERT_TRUE(https_test_server.Start());
+
+ TestDelegate d;
+ {
+ scoped_ptr<URLRequest> r(default_context_.CreateRequest(
+ https_test_server.GetURL("tokbind-ekm"), DEFAULT_PRIORITY, &d));
+ r->Start();
+ EXPECT_TRUE(r->is_pending());
+
+ base::RunLoop().Run();
+
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status());
+
+ HttpRequestHeaders headers;
+ std::string token_binding_header, token_binding_message;
+ EXPECT_TRUE(r->GetFullRequestHeaders(&headers));
+ EXPECT_TRUE(headers.GetHeader(HttpRequestHeaders::kTokenBinding,
+ &token_binding_header));
+ EXPECT_TRUE(base::Base64UrlDecode(
+ token_binding_header, base::Base64UrlDecodePolicy::REQUIRE_PADDING,
+ &token_binding_message));
+ std::vector<TokenBinding> token_bindings;
+ ASSERT_TRUE(
+ ParseTokenBindingMessage(token_binding_message, &token_bindings));
+ ASSERT_EQ(1ull, token_bindings.size());
+
+ EXPECT_GT(d.bytes_received(), 0);
+ std::string ekm = d.data_received();
+
+ EXPECT_EQ(TokenBindingType::PROVIDED, token_bindings[0].type);
+ EXPECT_TRUE(VerifyEKMSignature(token_bindings[0].ec_point,
+ token_bindings[0].signature, ekm));
+ }
+}
+
+TEST_F(TokenBindingURLRequestTest, ForwardTokenBinding) {
+ SpawnedTestServer::SSLOptions ssl_options;
+ ssl_options.supported_token_binding_params.push_back(TB_PARAM_ECDSAP256);
+ SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath(kTestFilePath));
+ ASSERT_TRUE(https_test_server.Start());
+
+ TestDelegate d;
+ {
+ GURL redirect_url =
+ https_test_server.GetURL("forward-tokbind?/tokbind-ekm");
+ scoped_ptr<URLRequest> r(
+ default_context_.CreateRequest(redirect_url, DEFAULT_PRIORITY, &d));
+ r->Start();
+ EXPECT_TRUE(r->is_pending());
+
+ base::RunLoop().Run();
+
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status());
+
+ HttpRequestHeaders headers;
+ std::string token_binding_header, token_binding_message;
+ EXPECT_TRUE(r->GetFullRequestHeaders(&headers));
+ EXPECT_TRUE(headers.GetHeader(HttpRequestHeaders::kTokenBinding,
+ &token_binding_header));
+ EXPECT_TRUE(base::Base64UrlDecode(
+ token_binding_header, base::Base64UrlDecodePolicy::REQUIRE_PADDING,
+ &token_binding_message));
+ std::vector<TokenBinding> token_bindings;
+ ASSERT_TRUE(
+ ParseTokenBindingMessage(token_binding_message, &token_bindings));
+ ASSERT_EQ(2ull, token_bindings.size());
+
+ EXPECT_GT(d.bytes_received(), 0);
+ std::string ekm = d.data_received();
+
+ EXPECT_EQ(TokenBindingType::PROVIDED, token_bindings[0].type);
+ EXPECT_TRUE(VerifyEKMSignature(token_bindings[0].ec_point,
+ token_bindings[0].signature, ekm));
+ EXPECT_EQ(TokenBindingType::REFERRED, token_bindings[1].type);
+ EXPECT_TRUE(VerifyEKMSignature(token_bindings[1].ec_point,
+ token_bindings[1].signature, ekm));
+ }
+}
+
+// TODO(nharper): Remove this #ifdef and replace SpawnedTestServer with
+// EmbeddedTestServer once crbug.com/599187 is resolved.
+#if !defined(OS_ANDROID)
+TEST_F(TokenBindingURLRequestTest, DontForwardHeaderFromHttp) {
+ SpawnedTestServer http_server(SpawnedTestServer::TYPE_HTTP,
+ SpawnedTestServer::kLocalhost,
+ base::FilePath());
+ ASSERT_TRUE(http_server.Start());
+ SpawnedTestServer::SSLOptions ssl_options;
+ ssl_options.supported_token_binding_params.push_back(TB_PARAM_ECDSAP256);
+ SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath(kTestFilePath));
+ ASSERT_TRUE(https_test_server.Start());
+
+ TestDelegate d;
+ {
+ GURL redirect_url = http_server.GetURL(
+ "forward-tokbind?" + https_test_server.GetURL("tokbind-ekm").spec());
+ scoped_ptr<URLRequest> r(
+ default_context_.CreateRequest(redirect_url, DEFAULT_PRIORITY, &d));
+ r->Start();
+ EXPECT_TRUE(r->is_pending());
+
+ base::RunLoop().Run();
+
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status());
+
+ HttpRequestHeaders headers;
+ std::string token_binding_header, token_binding_message;
+ EXPECT_TRUE(r->GetFullRequestHeaders(&headers));
+ EXPECT_TRUE(headers.GetHeader(HttpRequestHeaders::kTokenBinding,
+ &token_binding_header));
+ EXPECT_TRUE(base::Base64UrlDecode(
+ token_binding_header, base::Base64UrlDecodePolicy::REQUIRE_PADDING,
+ &token_binding_message));
+ std::vector<TokenBinding> token_bindings;
+ ASSERT_TRUE(
+ ParseTokenBindingMessage(token_binding_message, &token_bindings));
+ ASSERT_EQ(1ull, token_bindings.size());
+
+ EXPECT_GT(d.bytes_received(), 0);
+ std::string ekm = d.data_received();
+
+ EXPECT_EQ(TokenBindingType::PROVIDED, token_bindings[0].type);
+ EXPECT_TRUE(VerifyEKMSignature(token_bindings[0].ec_point,
+ token_bindings[0].signature, ekm));
+ }
+}
+
+// Test that if a server supporting Token Binding redirects (with
+// Include-Referer-Token-Binding-ID) to an https url on a server that does not
+// support Token Binding, then we do not send a Sec-Token-Binding when following
+// the redirect.
+TEST_F(TokenBindingURLRequestTest, ForwardWithoutTokenBinding) {
+ SpawnedTestServer::SSLOptions ssl_options;
+ SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath(kTestFilePath));
+ ASSERT_TRUE(https_test_server.Start());
+ ssl_options.supported_token_binding_params.push_back(TB_PARAM_ECDSAP256);
+ SpawnedTestServer token_binding_test_server(SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath(kTestFilePath));
+ ASSERT_TRUE(token_binding_test_server.Start());
+
+ TestDelegate d;
+ {
+ GURL redirect_url = token_binding_test_server.GetURL(
+ "forward-tokbind?" + https_test_server.GetURL("tokbind-ekm").spec());
+ scoped_ptr<URLRequest> r(
+ default_context_.CreateRequest(redirect_url, DEFAULT_PRIORITY, &d));
+ r->Start();
+ EXPECT_TRUE(r->is_pending());
+
+ base::RunLoop().Run();
+
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status());
+
+ HttpRequestHeaders headers;
+ std::string token_binding_header, token_binding_message;
+ EXPECT_TRUE(r->GetFullRequestHeaders(&headers));
+ EXPECT_FALSE(headers.GetHeader(HttpRequestHeaders::kTokenBinding,
+ &token_binding_header));
+ }
+}
+#endif // !defined(OS_ANDROID)
+#endif // !defined(OS_IOS)
+
+// In this unit test, we're using the HTTPTestServer as a proxy server and
// issuing a CONNECT request with the magic host name "www.redirect.com".
// The EmbeddedTestServer will return a 302 response, which we should not
// follow.
@@ -4470,49 +4669,6 @@ TEST_F(URLRequestTestHTTP, GetZippedTest) {
}
#endif // !defined(OS_IOS)
-TEST_F(URLRequestTestHTTP, NetworkQualityEstimator) {
- ASSERT_TRUE(http_test_server()->Start());
- // Enable requests to local host to be used for network quality estimation.
- std::map<std::string, std::string> variation_params;
- NetworkQualityEstimator estimator(scoped_ptr<net::ExternalEstimateProvider>(),
- variation_params, true, true);
-
- TestDelegate d;
- TestNetworkDelegate network_delegate; // Must outlive URLRequest.
- TestURLRequestContext context(true);
- context.set_network_quality_estimator(&estimator);
- context.set_network_delegate(&network_delegate);
- context.Init();
-
- std::string url = "/defaultresponse";
-
- scoped_ptr<URLRequest> r(context.CreateRequest(
- http_test_server()->GetURL(url), DEFAULT_PRIORITY, &d));
- r->Start();
-
- base::RunLoop().Run();
-
- base::TimeDelta rtt;
- int32_t kbps;
- EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
- EXPECT_GE(rtt, base::TimeDelta());
- EXPECT_LT(rtt, base::TimeDelta::Max());
- EXPECT_GT(kbps, 0);
-
- // Verify that histograms are not populated. They should populate only when
- // there is a change in ConnectionType.
- base::HistogramTester histogram_tester;
- histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 0);
- histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 0);
-
- NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
- NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI);
- base::MessageLoop::current()->RunUntilIdle();
- histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 1);
- histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 1);
-}
-
TEST_F(URLRequestTestHTTP, RedirectLoadTiming) {
ASSERT_TRUE(http_test_server()->Start());
@@ -5619,6 +5775,38 @@ TEST_F(URLRequestTestHTTP, PostUnreadableFileTest) {
}
}
+namespace {
+
+// Adds a standard set of data to an upload for chunked upload integration
+// tests.
+void AddDataToUpload(ChunkedUploadDataStream::Writer* writer) {
+ writer->AppendData("a", 1, false);
+ writer->AppendData("bcd", 3, false);
+ writer->AppendData("this is a longer chunk than before.", 35, false);
+ writer->AppendData("\r\n\r\n", 4, false);
+ writer->AppendData("0", 1, false);
+ writer->AppendData("2323", 4, true);
+}
+
+// Checks that the upload data added in AddChunksToUpload() was echoed back from
+// the server.
+void VerifyReceivedDataMatchesChunks(URLRequest* r, TestDelegate* d) {
+ // This should match the chunks sent by AddChunksToUpload().
+ const std::string expected_data =
+ "abcdthis is a longer chunk than before.\r\n\r\n02323";
+
+ ASSERT_EQ(1, d->response_started_count())
+ << "request failed: " << r->status().status()
+ << ", os error: " << r->status().error();
+
+ EXPECT_FALSE(d->received_data_before_response());
+
+ EXPECT_EQ(expected_data.size(), static_cast<size_t>(d->bytes_received()));
+ EXPECT_EQ(expected_data, d->data_received());
+}
+
+} // namespace
+
TEST_F(URLRequestTestHTTP, TestPostChunkedDataBeforeStart) {
ASSERT_TRUE(http_test_server()->Start());
@@ -5626,9 +5814,13 @@ TEST_F(URLRequestTestHTTP, TestPostChunkedDataBeforeStart) {
{
scoped_ptr<URLRequest> r(default_context_.CreateRequest(
http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d));
- r->EnableChunkedUpload();
+ scoped_ptr<ChunkedUploadDataStream> upload_data_stream(
+ new ChunkedUploadDataStream(0));
+ scoped_ptr<ChunkedUploadDataStream::Writer> writer =
+ upload_data_stream->CreateWriter();
+ r->set_upload(std::move(upload_data_stream));
r->set_method("POST");
- AddChunksToUpload(r.get());
+ AddDataToUpload(writer.get());
r->Start();
EXPECT_TRUE(r->is_pending());
@@ -5645,11 +5837,15 @@ TEST_F(URLRequestTestHTTP, TestPostChunkedDataJustAfterStart) {
{
scoped_ptr<URLRequest> r(default_context_.CreateRequest(
http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d));
- r->EnableChunkedUpload();
+ scoped_ptr<ChunkedUploadDataStream> upload_data_stream(
+ new ChunkedUploadDataStream(0));
+ scoped_ptr<ChunkedUploadDataStream::Writer> writer =
+ upload_data_stream->CreateWriter();
+ r->set_upload(make_scoped_ptr(upload_data_stream.release()));
r->set_method("POST");
r->Start();
EXPECT_TRUE(r->is_pending());
- AddChunksToUpload(r.get());
+ AddDataToUpload(writer.get());
base::RunLoop().Run();
VerifyReceivedDataMatchesChunks(r.get(), &d);
@@ -5663,13 +5859,17 @@ TEST_F(URLRequestTestHTTP, TestPostChunkedDataAfterStart) {
{
scoped_ptr<URLRequest> r(default_context_.CreateRequest(
http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d));
- r->EnableChunkedUpload();
+ scoped_ptr<ChunkedUploadDataStream> upload_data_stream(
+ new ChunkedUploadDataStream(0));
+ scoped_ptr<ChunkedUploadDataStream::Writer> writer =
+ upload_data_stream->CreateWriter();
+ r->set_upload(std::move(upload_data_stream));
r->set_method("POST");
r->Start();
EXPECT_TRUE(r->is_pending());
base::RunLoop().RunUntilIdle();
- AddChunksToUpload(r.get());
+ AddDataToUpload(writer.get());
base::RunLoop().Run();
VerifyReceivedDataMatchesChunks(r.get(), &d);
@@ -5782,6 +5982,7 @@ TEST_F(URLRequestTestHTTP, STSNotProcessedOnIP) {
#endif
namespace {
+const char kExpectCTStaticHostname[] = "preloaded-expect-ct.badssl.com";
const char kHPKPReportUri[] = "https://hpkp-report.test";
} // namespace
@@ -6133,6 +6334,124 @@ TEST_F(URLRequestTestHTTP, ProcessSTSAndPKP2) {
EXPECT_FALSE(pkp_state.include_subdomains);
}
+// An ExpectCTReporter that records the number of times OnExpectCTFailed() was
+// called.
+class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter {
+ public:
+ MockExpectCTReporter() : num_failures_(0) {}
+ ~MockExpectCTReporter() override {}
+
+ void OnExpectCTFailed(const HostPortPair& host_port_pair,
+ const GURL& report_uri,
+ const net::SSLInfo& ssl_info) override {
+ num_failures_++;
+ }
+
+ uint32_t num_failures() { return num_failures_; }
+
+ private:
+ 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,
+ ct::CTVerifyResult* result,
+ const BoundNetLog& 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 {
+ public:
+ MockCTPolicyEnforcer()
+ : default_result_(
+ ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS) {}
+ ~MockCTPolicyEnforcer() override {}
+
+ ct::CertPolicyCompliance DoesConformToCertPolicy(
+ X509Certificate* cert,
+ const SCTList& verified_scts,
+ const BoundNetLog& net_log) override {
+ return default_result_;
+ }
+
+ void set_default_result(ct::CertPolicyCompliance default_result) {
+ default_result_ = default_result;
+ }
+
+ private:
+ ct::CertPolicyCompliance default_result_;
+};
+
+// Tests that Expect CT headers are processed correctly.
+TEST_F(URLRequestTestHTTP, ExpectCTHeader) {
+ 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());
+
+ MockExpectCTReporter reporter;
+ TransportSecurityState transport_security_state;
+ transport_security_state.enable_static_expect_ct_ = true;
+ transport_security_state.SetExpectCTReporter(&reporter);
+
+ // Set up a MockCertVerifier to accept the certificate that the server sends.
+ 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;
+ cert_verifier.AddResultForCert(cert.get(), verify_result, OK);
+
+ // Set up a MockCTVerifier and MockCTPolicyEnforcer to trigger an Expect CT
+ // violation.
+ MockCTVerifier ct_verifier;
+ MockCTPolicyEnforcer ct_policy_enforcer;
+ ct_policy_enforcer.set_default_result(
+ ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS);
+
+ TestNetworkDelegate network_delegate;
+ // Use a MockHostResolver (which by default maps all hosts to
+ // 127.0.0.1) so that the request can be sent to a site on the Expect
+ // CT preload list.
+ MockHostResolver host_resolver;
+ TestURLRequestContext context(true);
+ 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.set_cert_transparency_verifier(&ct_verifier);
+ context.set_ct_policy_enforcer(&ct_policy_enforcer);
+ context.Init();
+
+ // Now send a request to trigger the violation.
+ TestDelegate d;
+ GURL url = https_test_server.GetURL("/expect-ct-header.html");
+ GURL::Replacements replace_host;
+ replace_host.SetHostStr(kExpectCTStaticHostname);
+ url = url.ReplaceComponents(replace_host);
+ scoped_ptr<URLRequest> violating_request(
+ context.CreateRequest(url, DEFAULT_PRIORITY, &d));
+ violating_request->Start();
+ base::RunLoop().Run();
+
+ EXPECT_EQ(1u, reporter.num_failures());
+}
+
#endif // !defined(OS_IOS)
TEST_F(URLRequestTestHTTP, ContentTypeNormalizationTest) {
@@ -6459,6 +6778,20 @@ TEST_F(URLRequestTestHTTP, RedirectJobWithReferenceFragment) {
EXPECT_EQ(redirect_url, r->url());
}
+TEST_F(URLRequestTestHTTP, UnsupportedReferrerScheme) {
+ ASSERT_TRUE(http_test_server()->Start());
+
+ const std::string referrer("foobar://totally.legit.referrer");
+ TestDelegate d;
+ scoped_ptr<URLRequest> req(default_context_.CreateRequest(
+ http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d));
+ req->SetReferrer(referrer);
+ req->Start();
+ base::RunLoop().Run();
+
+ EXPECT_EQ(std::string("None"), d.data_received());
+}
+
TEST_F(URLRequestTestHTTP, NoUserPassInReferrer) {
ASSERT_TRUE(http_test_server()->Start());
@@ -8289,7 +8622,8 @@ class SSLClientAuthTestDelegate : public TestDelegate {
TEST_F(HTTPSRequestTest, ClientAuthTest) {
EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::SSLServerConfig ssl_config;
- ssl_config.require_client_cert = true;
+ ssl_config.client_cert_type =
+ SSLServerConfig::ClientCertType::OPTIONAL_CLIENT_CERT;
test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);
test_server.AddDefaultHandlers(
base::FilePath(FILE_PATH_LITERAL("net/data/ssl")));
@@ -8448,7 +8782,6 @@ TEST_F(HTTPSRequestTest, SSLSessionCacheShardTest) {
params.ssl_config_service = default_context_.ssl_config_service();
params.http_auth_handler_factory =
default_context_.http_auth_handler_factory();
- params.network_delegate = &default_network_delegate_;
params.http_server_properties = default_context_.http_server_properties();
HttpNetworkSession network_session(params);
@@ -8528,61 +8861,17 @@ TEST_F(HTTPSRequestTest, DisableECDSAOnXP) {
#endif // OS_WIN
-class TestSSLConfigService : public SSLConfigService {
- public:
- TestSSLConfigService(bool ev_enabled,
- bool online_rev_checking,
- bool rev_checking_required_local_anchors)
- : ev_enabled_(ev_enabled),
- online_rev_checking_(online_rev_checking),
- rev_checking_required_local_anchors_(
- rev_checking_required_local_anchors),
- min_version_(kDefaultSSLVersionMin),
- fallback_min_version_(kDefaultSSLVersionFallbackMin) {}
-
- void set_min_version(uint16_t version) { min_version_ = version; }
-
- void set_fallback_min_version(uint16_t version) {
- fallback_min_version_ = version;
- }
-
- // SSLConfigService:
- void GetSSLConfig(SSLConfig* config) override {
- *config = SSLConfig();
- config->rev_checking_enabled = online_rev_checking_;
- config->verify_ev_cert = ev_enabled_;
- config->rev_checking_required_local_anchors =
- rev_checking_required_local_anchors_;
- if (fallback_min_version_) {
- config->version_fallback_min = fallback_min_version_;
- }
- if (min_version_) {
- config->version_min = min_version_;
- }
- }
-
- protected:
- ~TestSSLConfigService() override {}
-
- private:
- const bool ev_enabled_;
- const bool online_rev_checking_;
- const bool rev_checking_required_local_anchors_;
- uint16_t min_version_;
- uint16_t fallback_min_version_;
-};
-
class FallbackTestURLRequestContext : public TestURLRequestContext {
public:
explicit FallbackTestURLRequestContext(bool delay_initialization)
: TestURLRequestContext(delay_initialization) {}
void set_fallback_min_version(uint16_t version) {
- TestSSLConfigService *ssl_config_service =
- new TestSSLConfigService(true /* check for EV */,
- false /* online revocation checking */,
- false /* require rev. checking for local
- anchors */);
+ TestSSLConfigService* ssl_config_service = new TestSSLConfigService(
+ true /* check for EV */, false /* online revocation checking */,
+ false /* require rev. checking for local
+ anchors */,
+ false /* token binding enabled */);
ssl_config_service->set_fallback_min_version(version);
set_ssl_config_service(ssl_config_service);
}
@@ -8646,21 +8935,33 @@ TEST_F(HTTPSFallbackTest, TLSv1NoFallback) {
SpawnedTestServer::SSLOptions::TLS_INTOLERANT_TLS1_1;
ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_options));
+ ExpectFailure(ERR_SSL_VERSION_OR_CIPHER_MISMATCH);
+}
+
+// Tests the TLS 1.1 fallback doesn't happen but 1.2-intolerance is detected.
+TEST_F(HTTPSFallbackTest, TLSv1_1NoFallback) {
+ SpawnedTestServer::SSLOptions ssl_options(
+ SpawnedTestServer::SSLOptions::CERT_OK);
+ ssl_options.tls_intolerant =
+ SpawnedTestServer::SSLOptions::TLS_INTOLERANT_TLS1_2;
+
+ ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_options));
ExpectFailure(ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION);
}
-// Tests the TLS 1.1 fallback.
+// Tests the TLS 1.1 fallback when explicitly enabled.
TEST_F(HTTPSFallbackTest, TLSv1_1Fallback) {
SpawnedTestServer::SSLOptions ssl_options(
SpawnedTestServer::SSLOptions::CERT_OK);
ssl_options.tls_intolerant =
SpawnedTestServer::SSLOptions::TLS_INTOLERANT_TLS1_2;
+ set_fallback_min_version(SSL_PROTOCOL_VERSION_TLS1_1);
ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_options));
ExpectConnection(SSL_CONNECTION_VERSION_TLS1_1);
}
-// Tests that the TLS 1.1 fallback triggers on closed connections.
+// Tests that the TLS 1.1 fallback, if enabled, triggers on closed connections.
TEST_F(HTTPSFallbackTest, TLSv1_1FallbackClosed) {
SpawnedTestServer::SSLOptions ssl_options(
SpawnedTestServer::SSLOptions::CERT_OK);
@@ -8669,6 +8970,7 @@ TEST_F(HTTPSFallbackTest, TLSv1_1FallbackClosed) {
ssl_options.tls_intolerance_type =
SpawnedTestServer::SSLOptions::TLS_INTOLERANCE_CLOSE;
+ set_fallback_min_version(SSL_PROTOCOL_VERSION_TLS1_1);
ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_options));
ExpectConnection(SSL_CONNECTION_VERSION_TLS1_1);
}
@@ -8676,7 +8978,7 @@ TEST_F(HTTPSFallbackTest, TLSv1_1FallbackClosed) {
// This test is disabled on Android because the remote test server doesn't cause
// a TCP reset.
#if !defined(OS_ANDROID)
-// Tests fallback to TLS 1.1 on connection reset.
+// Tests fallback to TLS 1.1, if enabled, on connection reset.
TEST_F(HTTPSFallbackTest, TLSv1_1FallbackReset) {
SpawnedTestServer::SSLOptions ssl_options(
SpawnedTestServer::SSLOptions::CERT_OK);
@@ -8685,13 +8987,15 @@ TEST_F(HTTPSFallbackTest, TLSv1_1FallbackReset) {
ssl_options.tls_intolerance_type =
SpawnedTestServer::SSLOptions::TLS_INTOLERANCE_RESET;
+ set_fallback_min_version(SSL_PROTOCOL_VERSION_TLS1_1);
ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_options));
ExpectConnection(SSL_CONNECTION_VERSION_TLS1_1);
}
#endif // !OS_ANDROID
-// Tests that we don't fallback on handshake failure with servers that implement
-// TLS_FALLBACK_SCSV. Also ensure that the original error code is reported.
+// Tests that we don't fallback, even if enabled, on handshake failure with
+// servers that implement TLS_FALLBACK_SCSV. Also ensure that the original error
+// code is reported.
TEST_F(HTTPSFallbackTest, FallbackSCSV) {
SpawnedTestServer::SSLOptions ssl_options(
SpawnedTestServer::SSLOptions::CERT_OK);
@@ -8703,6 +9007,7 @@ TEST_F(HTTPSFallbackTest, FallbackSCSV) {
// connections are rejected.
ssl_options.fallback_scsv_enabled = true;
+ set_fallback_min_version(SSL_PROTOCOL_VERSION_TLS1_1);
ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_options));
// ERR_SSL_VERSION_OR_CIPHER_MISMATCH is how the server simulates version
@@ -8712,8 +9017,9 @@ TEST_F(HTTPSFallbackTest, FallbackSCSV) {
ExpectFailure(ERR_SSL_VERSION_OR_CIPHER_MISMATCH);
}
-// Tests that we don't fallback on connection closed with servers that implement
-// TLS_FALLBACK_SCSV. Also ensure that the original error code is reported.
+// Tests that we don't fallback, even if enabled, on connection closed with
+// servers that implement TLS_FALLBACK_SCSV. Also ensure that the original error
+// code is reported.
TEST_F(HTTPSFallbackTest, FallbackSCSVClosed) {
SpawnedTestServer::SSLOptions ssl_options(
SpawnedTestServer::SSLOptions::CERT_OK);
@@ -8727,6 +9033,7 @@ TEST_F(HTTPSFallbackTest, FallbackSCSVClosed) {
// connections are rejected.
ssl_options.fallback_scsv_enabled = true;
+ set_fallback_min_version(SSL_PROTOCOL_VERSION_TLS1_1);
ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_options));
// The original error should be replayed on rejected fallback.
@@ -8738,7 +9045,7 @@ TEST_F(HTTPSRequestTest, FallbackProbeNoCache) {
SpawnedTestServer::SSLOptions ssl_options(
SpawnedTestServer::SSLOptions::CERT_OK);
ssl_options.tls_intolerant =
- SpawnedTestServer::SSLOptions::TLS_INTOLERANT_TLS1_1;
+ SpawnedTestServer::SSLOptions::TLS_INTOLERANT_TLS1_2;
ssl_options.tls_intolerance_type =
SpawnedTestServer::SSLOptions::TLS_INTOLERANCE_CLOSE;
ssl_options.record_resume = true;
@@ -8751,14 +9058,13 @@ TEST_F(HTTPSRequestTest, FallbackProbeNoCache) {
SSLClientSocket::ClearSessionCache();
- // Make a connection that does a probe fallback to TLSv1 but fails because
- // TLSv1 fallback is disabled. We don't wish a session for this connection to
- // be inserted locally.
+ // Make a connection that does a probe fallback to TLSv1.1 but fails because
+ // fallback is disabled. We don't wish a session for this connection to be
+ // inserted locally.
{
TestDelegate delegate;
FallbackTestURLRequestContext context(true);
- context.set_fallback_min_version(SSL_PROTOCOL_VERSION_TLS1_2);
context.Init();
scoped_ptr<URLRequest> request(context.CreateRequest(
test_server.GetURL("/"), DEFAULT_PRIORITY, &delegate));
@@ -8773,11 +9079,11 @@ TEST_F(HTTPSRequestTest, FallbackProbeNoCache) {
request->status().error());
}
- // Now allow TLSv1 fallback connections and request the session cache log.
+ // Now allow TLSv1.1 fallback connections and request the session cache log.
{
TestDelegate delegate;
FallbackTestURLRequestContext context(true);
- context.set_fallback_min_version(SSL_PROTOCOL_VERSION_TLS1);
+ context.set_fallback_min_version(SSL_PROTOCOL_VERSION_TLS1_1);
context.Init();
scoped_ptr<URLRequest> request(context.CreateRequest(
@@ -8789,7 +9095,7 @@ TEST_F(HTTPSRequestTest, FallbackProbeNoCache) {
EXPECT_EQ(1, delegate.response_started_count());
EXPECT_NE(0, delegate.bytes_received());
EXPECT_EQ(
- SSL_CONNECTION_VERSION_TLS1,
+ SSL_CONNECTION_VERSION_TLS1_1,
SSLConnectionStatusToVersion(request->ssl_info().connection_status));
EXPECT_TRUE(request->ssl_info().connection_status &
SSL_CONNECTION_VERSION_FALLBACK);
@@ -8918,7 +9224,7 @@ class HTTPSOCSPTest : public HTTPSRequestTest {
CHECK_NE(static_cast<X509Certificate*>(NULL), root_cert.get());
test_root_.reset(new ScopedTestRoot(root_cert.get()));
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
SetURLRequestContextForNSSHttpIO(&context_);
EnsureNSSHttpIOInit();
#endif
@@ -8947,7 +9253,7 @@ class HTTPSOCSPTest : public HTTPSRequestTest {
}
~HTTPSOCSPTest() override {
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
ShutdownNSSHttpIO();
#endif
}
@@ -8957,11 +9263,11 @@ class HTTPSOCSPTest : public HTTPSRequestTest {
// connetions to testserver. This can be overridden in test subclasses for
// different behaviour.
virtual void SetupContext(URLRequestContext* context) {
- context->set_ssl_config_service(
- new TestSSLConfigService(true /* check for EV */,
- true /* online revocation checking */,
- false /* require rev. checking for local
- anchors */));
+ context->set_ssl_config_service(new TestSSLConfigService(
+ true /* check for EV */, true /* online revocation checking */,
+ false /* require rev. checking for local
+ anchors */,
+ false /* token binding enabled */));
}
scoped_ptr<ScopedTestRoot> test_root_;
@@ -8987,7 +9293,7 @@ static CertStatus ExpectedCertStatusForFailedOnlineRevocationCheck() {
// If it does not, then tests which rely on 'hard fail' behaviour should be
// skipped.
static bool SystemSupportsHardFailRevocationChecking() {
-#if defined(OS_WIN) || defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(OS_WIN) || defined(USE_NSS_VERIFIER)
return true;
#else
return false;
@@ -9026,7 +9332,7 @@ static bool SystemSupportsOCSP() {
}
static bool SystemSupportsOCSPStapling() {
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+#if defined(USE_NSS_VERIFIER)
return true;
#elif defined(OS_WIN)
return base::win::GetVersion() >= base::win::VERSION_VISTA;
@@ -9152,11 +9458,11 @@ TEST_F(HTTPSOCSPTest, MAYBE_RevokedStapled) {
class HTTPSHardFailTest : public HTTPSOCSPTest {
protected:
void SetupContext(URLRequestContext* context) override {
- context->set_ssl_config_service(
- new TestSSLConfigService(false /* check for EV */,
- false /* online revocation checking */,
- true /* require rev. checking for local
- anchors */));
+ context->set_ssl_config_service(new TestSSLConfigService(
+ false /* check for EV */, false /* online revocation checking */,
+ true /* require rev. checking for local
+ anchors */,
+ false /* token binding enabled */));
}
};
@@ -9189,11 +9495,11 @@ TEST_F(HTTPSHardFailTest, FailsOnOCSPInvalid) {
class HTTPSEVCRLSetTest : public HTTPSOCSPTest {
protected:
void SetupContext(URLRequestContext* context) override {
- context->set_ssl_config_service(
- new TestSSLConfigService(true /* check for EV */,
- false /* online revocation checking */,
- false /* require rev. checking for local
- anchors */));
+ context->set_ssl_config_service(new TestSSLConfigService(
+ true /* check for EV */, false /* online revocation checking */,
+ false /* require rev. checking for local
+ anchors */,
+ false /* token binding enabled */));
}
};
@@ -9374,11 +9680,11 @@ TEST_F(HTTPSEVCRLSetTest, ExpiredCRLSetAndRevokedNonEVCert) {
class HTTPSCRLSetTest : public HTTPSOCSPTest {
protected:
void SetupContext(URLRequestContext* context) override {
- context->set_ssl_config_service(
- new TestSSLConfigService(false /* check for EV */,
- false /* online revocation checking */,
- false /* require rev. checking for local
- anchors */));
+ 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 */));
}
};
diff --git a/chromium/net/url_request/view_cache_helper.cc b/chromium/net/url_request/view_cache_helper.cc
index 36d3ae5ce0d..b18d336fba5 100644
--- a/chromium/net/url_request/view_cache_helper.cc
+++ b/chromium/net/url_request/view_cache_helper.cc
@@ -311,7 +311,7 @@ int ViewCacheHelper::DoReadResponseComplete(int result) {
data_->append(EscapeForHTML(response.headers->GetStatusLine()));
data_->push_back('\n');
- void* iter = NULL;
+ size_t iter = 0;
std::string name, value;
while (response.headers->EnumerateHeaderLines(&iter, &name, &value)) {
data_->append(EscapeForHTML(name));
diff --git a/chromium/net/websockets/websocket_basic_handshake_stream.cc b/chromium/net/websockets/websocket_basic_handshake_stream.cc
index 92af20cb2d8..aee33673f00 100644
--- a/chromium/net/websockets/websocket_basic_handshake_stream.cc
+++ b/chromium/net/websockets/websocket_basic_handshake_stream.cc
@@ -101,10 +101,10 @@ void AddVectorHeaderIfNonEmpty(const char* name,
GetHeaderResult GetSingleHeaderValue(const HttpResponseHeaders* headers,
const base::StringPiece& name,
std::string* value) {
- void* state = nullptr;
+ size_t iter = 0;
size_t num_values = 0;
std::string temp_value;
- while (headers->EnumerateHeader(&state, name, &temp_value)) {
+ while (headers->EnumerateHeader(&iter, name, &temp_value)) {
if (++num_values > 1)
return GET_HEADER_MULTIPLE;
*value = temp_value;
@@ -185,7 +185,7 @@ bool ValidateSubProtocol(
const std::vector<std::string>& requested_sub_protocols,
std::string* sub_protocol,
std::string* failure_message) {
- void* state = nullptr;
+ size_t iter = 0;
std::string value;
base::hash_set<std::string> requested_set(requested_sub_protocols.begin(),
requested_sub_protocols.end());
@@ -195,8 +195,8 @@ bool ValidateSubProtocol(
while (!has_invalid_protocol || !has_multiple_protocols) {
std::string temp_value;
- if (!headers->EnumerateHeader(
- &state, websockets::kSecWebSocketProtocol, &temp_value))
+ if (!headers->EnumerateHeader(&iter, websockets::kSecWebSocketProtocol,
+ &temp_value))
break;
value = temp_value;
if (requested_set.count(value) == 0)
@@ -235,13 +235,13 @@ bool ValidateExtensions(const HttpResponseHeaders* headers,
std::string* accepted_extensions_descriptor,
std::string* failure_message,
WebSocketExtensionParams* params) {
- void* state = nullptr;
+ size_t iter = 0;
std::string header_value;
std::vector<std::string> header_values;
// TODO(ricea): If adding support for additional extensions, generalise this
// code.
bool seen_permessage_deflate = false;
- while (headers->EnumerateHeader(&state, websockets::kSecWebSocketExtensions,
+ while (headers->EnumerateHeader(&iter, websockets::kSecWebSocketExtensions,
&header_value)) {
WebSocketExtensionParser parser;
if (!parser.Parse(header_value)) {
@@ -444,6 +444,13 @@ void WebSocketBasicHandshakeStream::PopulateNetErrorDetails(
return;
}
+Error WebSocketBasicHandshakeStream::GetSignedEKMForTokenBinding(
+ crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ NOTREACHED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
void WebSocketBasicHandshakeStream::Drain(HttpNetworkSession* session) {
HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(this);
drainer->Start(session);
diff --git a/chromium/net/websockets/websocket_basic_handshake_stream.h b/chromium/net/websockets/websocket_basic_handshake_stream.h
index d84ef22bc8f..d39098278f2 100644
--- a/chromium/net/websockets/websocket_basic_handshake_stream.h
+++ b/chromium/net/websockets/websocket_basic_handshake_stream.h
@@ -64,6 +64,8 @@ class NET_EXPORT_PRIVATE WebSocketBasicHandshakeStream
void GetSSLInfo(SSLInfo* ssl_info) override;
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
+ Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) override;
void Drain(HttpNetworkSession* session) override;
void SetPriority(RequestPriority priority) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
diff --git a/chromium/net/websockets/websocket_basic_stream_test.cc b/chromium/net/websockets/websocket_basic_stream_test.cc
index d7796d3886c..f60a1057ed8 100644
--- a/chromium/net/websockets/websocket_basic_stream_test.cc
+++ b/chromium/net/websockets/websocket_basic_stream_test.cc
@@ -128,12 +128,9 @@ class WebSocketBasicStreamSocketTest : public WebSocketBasicStreamTest {
scoped_ptr<ClientSocketHandle> transport_socket(new ClientSocketHandle);
scoped_refptr<MockTransportSocketParams> params;
- transport_socket->Init("a",
- params,
- MEDIUM,
- CompletionCallback(),
- &pool_,
- bound_net_log_.bound());
+ transport_socket->Init(
+ "a", params, MEDIUM, ClientSocketPool::RespectLimits::ENABLED,
+ CompletionCallback(), &pool_, bound_net_log_.bound());
return transport_socket;
}
diff --git a/chromium/net/websockets/websocket_channel.cc b/chromium/net/websockets/websocket_channel.cc
index 3018088db35..7d166ee6d9f 100644
--- a/chromium/net/websockets/websocket_channel.cc
+++ b/chromium/net/websockets/websocket_channel.cc
@@ -286,6 +286,9 @@ WebSocketChannel::PendingReceivedFrame::PendingReceivedFrame(
offset_(offset),
size_(size) {}
+WebSocketChannel::PendingReceivedFrame::PendingReceivedFrame(
+ const PendingReceivedFrame& other) = default;
+
WebSocketChannel::PendingReceivedFrame::~PendingReceivedFrame() {}
void WebSocketChannel::PendingReceivedFrame::ResetOpcode() {
diff --git a/chromium/net/websockets/websocket_channel.h b/chromium/net/websockets/websocket_channel.h
index 7f341950244..97db65f1eb8 100644
--- a/chromium/net/websockets/websocket_channel.h
+++ b/chromium/net/websockets/websocket_channel.h
@@ -149,6 +149,7 @@ class NET_EXPORT WebSocketChannel {
const scoped_refptr<IOBuffer>& data,
uint64_t offset,
uint64_t size);
+ PendingReceivedFrame(const PendingReceivedFrame& other);
~PendingReceivedFrame();
bool final() const { return final_; }
diff --git a/chromium/net/websockets/websocket_end_to_end_test.cc b/chromium/net/websockets/websocket_end_to_end_test.cc
index bb1d9519b18..24053374e61 100644
--- a/chromium/net/websockets/websocket_end_to_end_test.cc
+++ b/chromium/net/websockets/websocket_end_to_end_test.cc
@@ -9,6 +9,7 @@
// require special server configurations.
#include <stdint.h>
+
#include <string>
#include "base/bind.h"
@@ -22,7 +23,7 @@
#include "base/strings/string_piece.h"
#include "base/thread_task_runner_handle.h"
#include "net/base/auth.h"
-#include "net/base/network_delegate.h"
+#include "net/base/proxy_delegate.h"
#include "net/base/test_data_directory.h"
#include "net/proxy/proxy_service.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -195,9 +196,9 @@ void ConnectTestingEventInterface::QuitNestedEventLoop() {
// A subclass of TestNetworkDelegate that additionally implements the
// OnResolveProxy callback and records the information passed to it.
-class TestNetworkDelegateWithProxyInfo : public TestNetworkDelegate {
+class TestProxyDelegateWithProxyInfo : public ProxyDelegate {
public:
- TestNetworkDelegateWithProxyInfo() {}
+ TestProxyDelegateWithProxyInfo() {}
struct ResolvedProxyInfo {
GURL url;
@@ -210,6 +211,7 @@ class TestNetworkDelegateWithProxyInfo : public TestNetworkDelegate {
protected:
void OnResolveProxy(const GURL& url,
+ const std::string& method,
int load_flags,
const ProxyService& proxy_service,
ProxyInfo* result) override {
@@ -217,17 +219,34 @@ class TestNetworkDelegateWithProxyInfo : public TestNetworkDelegate {
resolved_proxy_info_.proxy_info = *result;
}
+ void OnTunnelConnectCompleted(const HostPortPair& endpoint,
+ const HostPortPair& proxy_server,
+ int net_error) override {}
+ void OnFallback(const ProxyServer& bad_proxy, int net_error) override {}
+ void OnBeforeSendHeaders(URLRequest* request,
+ const ProxyInfo& proxy_info,
+ HttpRequestHeaders* headers) override {}
+ void OnBeforeTunnelRequest(const HostPortPair& proxy_server,
+ HttpRequestHeaders* extra_headers) override {}
+ void OnTunnelHeadersReceived(
+ const HostPortPair& origin,
+ const HostPortPair& proxy_server,
+ const HttpResponseHeaders& response_headers) override {}
+ bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override {
+ return true;
+ }
+
private:
ResolvedProxyInfo resolved_proxy_info_;
- DISALLOW_COPY_AND_ASSIGN(TestNetworkDelegateWithProxyInfo);
+ DISALLOW_COPY_AND_ASSIGN(TestProxyDelegateWithProxyInfo);
};
class WebSocketEndToEndTest : public ::testing::Test {
protected:
WebSocketEndToEndTest()
: event_interface_(),
- network_delegate_(new TestNetworkDelegateWithProxyInfo),
+ proxy_delegate_(new TestProxyDelegateWithProxyInfo),
context_(true),
channel_(),
initialised_context_(false) {}
@@ -236,7 +255,7 @@ class WebSocketEndToEndTest : public ::testing::Test {
// ConnectAndWait(). This method is for the use of tests that need the
// URLRequestContext initialised before calling ConnectAndWait().
void InitialiseContext() {
- context_.set_network_delegate(network_delegate_.get());
+ context_.set_proxy_delegate(proxy_delegate_.get());
context_.Init();
initialised_context_ = true;
}
@@ -257,7 +276,7 @@ class WebSocketEndToEndTest : public ::testing::Test {
}
ConnectTestingEventInterface* event_interface_; // owned by channel_
- scoped_ptr<TestNetworkDelegateWithProxyInfo> network_delegate_;
+ scoped_ptr<TestProxyDelegateWithProxyInfo> proxy_delegate_;
TestURLRequestContext context_;
scoped_ptr<WebSocketChannel> channel_;
std::vector<std::string> sub_protocols_;
@@ -369,8 +388,8 @@ TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(HttpsProxyUsed)) {
GURL ws_url = ws_server.GetURL(kEchoServer);
EXPECT_TRUE(ConnectAndWait(ws_url));
- const TestNetworkDelegateWithProxyInfo::ResolvedProxyInfo& info =
- network_delegate_->resolved_proxy_info();
+ const TestProxyDelegateWithProxyInfo::ResolvedProxyInfo& info =
+ proxy_delegate_->resolved_proxy_info();
EXPECT_EQ(ws_url, info.url);
EXPECT_TRUE(info.proxy_info.is_http());
}
diff --git a/chromium/net/websockets/websocket_extension.cc b/chromium/net/websockets/websocket_extension.cc
index c5e8e1720bf..a0d55607e35 100644
--- a/chromium/net/websockets/websocket_extension.cc
+++ b/chromium/net/websockets/websocket_extension.cc
@@ -32,6 +32,9 @@ WebSocketExtension::WebSocketExtension() {}
WebSocketExtension::WebSocketExtension(const std::string& name)
: name_(name) {}
+WebSocketExtension::WebSocketExtension(const WebSocketExtension& other) =
+ default;
+
WebSocketExtension::~WebSocketExtension() {}
bool WebSocketExtension::Equals(const WebSocketExtension& other) const {
diff --git a/chromium/net/websockets/websocket_extension.h b/chromium/net/websockets/websocket_extension.h
index 20f29220a78..4c42a76f310 100644
--- a/chromium/net/websockets/websocket_extension.h
+++ b/chromium/net/websockets/websocket_extension.h
@@ -38,6 +38,7 @@ class NET_EXPORT_PRIVATE WebSocketExtension {
WebSocketExtension();
explicit WebSocketExtension(const std::string& name);
+ WebSocketExtension(const WebSocketExtension& other);
~WebSocketExtension();
void Add(const Parameter& parameter) { parameters_.push_back(parameter); }
diff --git a/chromium/net/websockets/websocket_frame_parser_fuzzer.cc b/chromium/net/websockets/websocket_frame_parser_fuzzer.cc
new file mode 100644
index 00000000000..717a9a4aaa3
--- /dev/null
+++ b/chromium/net/websockets/websocket_frame_parser_fuzzer.cc
@@ -0,0 +1,19 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include <vector>
+
+#include "net/websockets/websocket_frame_parser.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ net::WebSocketFrameParser parser;
+ std::vector<scoped_ptr<net::WebSocketFrameChunk>> frame_chunks;
+ parser.Decode(reinterpret_cast<const char*>(data), size, &frame_chunks);
+
+ return 0;
+}
diff --git a/chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc b/chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc
index ffdbfe2ebfa..6a8499cfb92 100644
--- a/chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc
+++ b/chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc
@@ -41,13 +41,9 @@ class MockClientSocketHandleFactory {
const std::string& return_to_read) {
socket_factory_maker_.SetExpectations(expect_written, return_to_read);
scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle);
- socket_handle->Init(
- "a",
- scoped_refptr<MockTransportSocketParams>(),
- MEDIUM,
- CompletionCallback(),
- &pool_,
- BoundNetLog());
+ socket_handle->Init("a", scoped_refptr<MockTransportSocketParams>(), MEDIUM,
+ ClientSocketPool::RespectLimits::ENABLED,
+ CompletionCallback(), &pool_, BoundNetLog());
return socket_handle;
}
diff --git a/chromium/net/websockets/websocket_stream_create_test_base.cc b/chromium/net/websockets/websocket_stream_create_test_base.cc
index 4211e1a485c..00e5f7fe737 100644
--- a/chromium/net/websockets/websocket_stream_create_test_base.cc
+++ b/chromium/net/websockets/websocket_stream_create_test_base.cc
@@ -133,7 +133,7 @@ WebSocketStreamCreateTestBase::RequestHeadersToVector(
std::vector<HeaderKeyValuePair>
WebSocketStreamCreateTestBase::ResponseHeadersToVector(
const HttpResponseHeaders& headers) {
- void* iter = NULL;
+ size_t iter = 0;
std::string name, value;
std::vector<HeaderKeyValuePair> result;
while (headers.EnumerateHeaderLines(&iter, &name, &value))